Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge tag 'nfsd-5.14' of git://linux-nfs.org/~bfields/linux

Pull nfsd updates from Bruce Fields:

- add tracepoints for callbacks and for client creation and destruction

- cache the mounts used for server-to-server copies

- expose callback information in /proc/fs/nfsd/clients/*/info

- don't hold locks unnecessarily while waiting for commits

- update NLM to use xdr_stream, as we have for NFSv2/v3/v4

* tag 'nfsd-5.14' of git://linux-nfs.org/~bfields/linux: (69 commits)
nfsd: fix NULL dereference in nfs3svc_encode_getaclres
NFSD: Prevent a possible oops in the nfs_dirent() tracepoint
nfsd: remove redundant assignment to pointer 'this'
nfsd: Reduce contention for the nfsd_file nf_rwsem
lockd: Update the NLMv4 SHARE results encoder to use struct xdr_stream
lockd: Update the NLMv4 nlm_res results encoder to use struct xdr_stream
lockd: Update the NLMv4 TEST results encoder to use struct xdr_stream
lockd: Update the NLMv4 void results encoder to use struct xdr_stream
lockd: Update the NLMv4 FREE_ALL arguments decoder to use struct xdr_stream
lockd: Update the NLMv4 SHARE arguments decoder to use struct xdr_stream
lockd: Update the NLMv4 SM_NOTIFY arguments decoder to use struct xdr_stream
lockd: Update the NLMv4 nlm_res arguments decoder to use struct xdr_stream
lockd: Update the NLMv4 UNLOCK arguments decoder to use struct xdr_stream
lockd: Update the NLMv4 CANCEL arguments decoder to use struct xdr_stream
lockd: Update the NLMv4 LOCK arguments decoder to use struct xdr_stream
lockd: Update the NLMv4 TEST arguments decoder to use struct xdr_stream
lockd: Update the NLMv4 void arguments decoder to use struct xdr_stream
lockd: Update the NLMv1 SHARE results encoder to use struct xdr_stream
lockd: Update the NLMv1 nlm_res results encoder to use struct xdr_stream
lockd: Update the NLMv1 TEST results encoder to use struct xdr_stream
...

+1222 -585
+43
fs/lockd/svc.c
··· 766 766 module_init(init_nlm); 767 767 module_exit(exit_nlm); 768 768 769 + /** 770 + * nlmsvc_dispatch - Process an NLM Request 771 + * @rqstp: incoming request 772 + * @statp: pointer to location of accept_stat field in RPC Reply buffer 773 + * 774 + * Return values: 775 + * %0: Processing complete; do not send a Reply 776 + * %1: Processing complete; send Reply in rqstp->rq_res 777 + */ 778 + static int nlmsvc_dispatch(struct svc_rqst *rqstp, __be32 *statp) 779 + { 780 + const struct svc_procedure *procp = rqstp->rq_procinfo; 781 + struct kvec *argv = rqstp->rq_arg.head; 782 + struct kvec *resv = rqstp->rq_res.head; 783 + 784 + svcxdr_init_decode(rqstp); 785 + if (!procp->pc_decode(rqstp, argv->iov_base)) 786 + goto out_decode_err; 787 + 788 + *statp = procp->pc_func(rqstp); 789 + if (*statp == rpc_drop_reply) 790 + return 0; 791 + if (*statp != rpc_success) 792 + return 1; 793 + 794 + svcxdr_init_encode(rqstp); 795 + if (!procp->pc_encode(rqstp, resv->iov_base + resv->iov_len)) 796 + goto out_encode_err; 797 + 798 + return 1; 799 + 800 + out_decode_err: 801 + *statp = rpc_garbage_args; 802 + return 1; 803 + 804 + out_encode_err: 805 + *statp = rpc_system_err; 806 + return 1; 807 + } 808 + 769 809 /* 770 810 * Define NLM program and procedures 771 811 */ ··· 815 775 .vs_nproc = 17, 816 776 .vs_proc = nlmsvc_procedures, 817 777 .vs_count = nlmsvc_version1_count, 778 + .vs_dispatch = nlmsvc_dispatch, 818 779 .vs_xdrsize = NLMSVC_XDRSIZE, 819 780 }; 820 781 static unsigned int nlmsvc_version3_count[24]; ··· 824 783 .vs_nproc = 24, 825 784 .vs_proc = nlmsvc_procedures, 826 785 .vs_count = nlmsvc_version3_count, 786 + .vs_dispatch = nlmsvc_dispatch, 827 787 .vs_xdrsize = NLMSVC_XDRSIZE, 828 788 }; 829 789 #ifdef CONFIG_LOCKD_V4 ··· 834 792 .vs_nproc = 24, 835 793 .vs_proc = nlmsvc_procedures4, 836 794 .vs_count = nlmsvc_version4_count, 795 + .vs_dispatch = nlmsvc_dispatch, 837 796 .vs_xdrsize = NLMSVC_XDRSIZE, 838 797 }; 839 798 #endif
+151
fs/lockd/svcxdr.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* 3 + * Encode/decode NLM basic data types 4 + * 5 + * Basic NLMv3 XDR data types are not defined in an IETF standards 6 + * document. X/Open has a description of these data types that 7 + * is useful. See Chapter 10 of "Protocols for Interworking: 8 + * XNFS, Version 3W". 9 + * 10 + * Basic NLMv4 XDR data types are defined in Appendix II.1.4 of 11 + * RFC 1813: "NFS Version 3 Protocol Specification". 12 + * 13 + * Author: Chuck Lever <chuck.lever@oracle.com> 14 + * 15 + * Copyright (c) 2020, Oracle and/or its affiliates. 16 + */ 17 + 18 + #ifndef _LOCKD_SVCXDR_H_ 19 + #define _LOCKD_SVCXDR_H_ 20 + 21 + static inline bool 22 + svcxdr_decode_stats(struct xdr_stream *xdr, __be32 *status) 23 + { 24 + __be32 *p; 25 + 26 + p = xdr_inline_decode(xdr, XDR_UNIT); 27 + if (!p) 28 + return false; 29 + *status = *p; 30 + 31 + return true; 32 + } 33 + 34 + static inline bool 35 + svcxdr_encode_stats(struct xdr_stream *xdr, __be32 status) 36 + { 37 + __be32 *p; 38 + 39 + p = xdr_reserve_space(xdr, XDR_UNIT); 40 + if (!p) 41 + return false; 42 + *p = status; 43 + 44 + return true; 45 + } 46 + 47 + static inline bool 48 + svcxdr_decode_string(struct xdr_stream *xdr, char **data, unsigned int *data_len) 49 + { 50 + __be32 *p; 51 + u32 len; 52 + 53 + if (xdr_stream_decode_u32(xdr, &len) < 0) 54 + return false; 55 + if (len > NLM_MAXSTRLEN) 56 + return false; 57 + p = xdr_inline_decode(xdr, len); 58 + if (!p) 59 + return false; 60 + *data_len = len; 61 + *data = (char *)p; 62 + 63 + return true; 64 + } 65 + 66 + /* 67 + * NLM cookies are defined by specification to be a variable-length 68 + * XDR opaque no longer than 1024 bytes. However, this implementation 69 + * limits their length to 32 bytes, and treats zero-length cookies 70 + * specially. 71 + */ 72 + static inline bool 73 + svcxdr_decode_cookie(struct xdr_stream *xdr, struct nlm_cookie *cookie) 74 + { 75 + __be32 *p; 76 + u32 len; 77 + 78 + if (xdr_stream_decode_u32(xdr, &len) < 0) 79 + return false; 80 + if (len > NLM_MAXCOOKIELEN) 81 + return false; 82 + if (!len) 83 + goto out_hpux; 84 + 85 + p = xdr_inline_decode(xdr, len); 86 + if (!p) 87 + return false; 88 + cookie->len = len; 89 + memcpy(cookie->data, p, len); 90 + 91 + return true; 92 + 93 + /* apparently HPUX can return empty cookies */ 94 + out_hpux: 95 + cookie->len = 4; 96 + memset(cookie->data, 0, 4); 97 + return true; 98 + } 99 + 100 + static inline bool 101 + svcxdr_encode_cookie(struct xdr_stream *xdr, const struct nlm_cookie *cookie) 102 + { 103 + __be32 *p; 104 + 105 + if (xdr_stream_encode_u32(xdr, cookie->len) < 0) 106 + return false; 107 + p = xdr_reserve_space(xdr, cookie->len); 108 + if (!p) 109 + return false; 110 + memcpy(p, cookie->data, cookie->len); 111 + 112 + return true; 113 + } 114 + 115 + static inline bool 116 + svcxdr_decode_owner(struct xdr_stream *xdr, struct xdr_netobj *obj) 117 + { 118 + __be32 *p; 119 + u32 len; 120 + 121 + if (xdr_stream_decode_u32(xdr, &len) < 0) 122 + return false; 123 + if (len > XDR_MAX_NETOBJ) 124 + return false; 125 + p = xdr_inline_decode(xdr, len); 126 + if (!p) 127 + return false; 128 + obj->len = len; 129 + obj->data = (u8 *)p; 130 + 131 + return true; 132 + } 133 + 134 + static inline bool 135 + svcxdr_encode_owner(struct xdr_stream *xdr, const struct xdr_netobj *obj) 136 + { 137 + unsigned int quadlen = XDR_QUADLEN(obj->len); 138 + __be32 *p; 139 + 140 + if (xdr_stream_encode_u32(xdr, obj->len) < 0) 141 + return false; 142 + p = xdr_reserve_space(xdr, obj->len); 143 + if (!p) 144 + return false; 145 + p[quadlen - 1] = 0; /* XDR pad */ 146 + memcpy(p, obj->data, obj->len); 147 + 148 + return true; 149 + } 150 + 151 + #endif /* _LOCKD_SVCXDR_H_ */
+230 -218
fs/lockd/xdr.c
··· 19 19 20 20 #include <uapi/linux/nfs2.h> 21 21 22 - #define NLMDBG_FACILITY NLMDBG_XDR 22 + #include "svcxdr.h" 23 23 24 24 25 25 static inline loff_t ··· 42 42 } 43 43 44 44 /* 45 - * XDR functions for basic NLM types 45 + * NLM file handles are defined by specification to be a variable-length 46 + * XDR opaque no longer than 1024 bytes. However, this implementation 47 + * constrains their length to exactly the length of an NFSv2 file 48 + * handle. 46 49 */ 47 - static __be32 *nlm_decode_cookie(__be32 *p, struct nlm_cookie *c) 50 + static bool 51 + svcxdr_decode_fhandle(struct xdr_stream *xdr, struct nfs_fh *fh) 48 52 { 49 - unsigned int len; 53 + __be32 *p; 54 + u32 len; 50 55 51 - len = ntohl(*p++); 52 - 53 - if(len==0) 54 - { 55 - c->len=4; 56 - memset(c->data, 0, 4); /* hockeypux brain damage */ 57 - } 58 - else if(len<=NLM_MAXCOOKIELEN) 59 - { 60 - c->len=len; 61 - memcpy(c->data, p, len); 62 - p+=XDR_QUADLEN(len); 63 - } 64 - else 65 - { 66 - dprintk("lockd: bad cookie size %d (only cookies under " 67 - "%d bytes are supported.)\n", 68 - len, NLM_MAXCOOKIELEN); 69 - return NULL; 70 - } 71 - return p; 56 + if (xdr_stream_decode_u32(xdr, &len) < 0) 57 + return false; 58 + if (len != NFS2_FHSIZE) 59 + return false; 60 + 61 + p = xdr_inline_decode(xdr, len); 62 + if (!p) 63 + return false; 64 + fh->size = NFS2_FHSIZE; 65 + memcpy(fh->data, p, len); 66 + memset(fh->data + NFS2_FHSIZE, 0, sizeof(fh->data) - NFS2_FHSIZE); 67 + 68 + return true; 72 69 } 73 70 74 - static inline __be32 * 75 - nlm_encode_cookie(__be32 *p, struct nlm_cookie *c) 71 + static bool 72 + svcxdr_decode_lock(struct xdr_stream *xdr, struct nlm_lock *lock) 76 73 { 77 - *p++ = htonl(c->len); 78 - memcpy(p, c->data, c->len); 79 - p+=XDR_QUADLEN(c->len); 80 - return p; 81 - } 74 + struct file_lock *fl = &lock->fl; 75 + s32 start, len, end; 82 76 83 - static __be32 * 84 - nlm_decode_fh(__be32 *p, struct nfs_fh *f) 85 - { 86 - unsigned int len; 87 - 88 - if ((len = ntohl(*p++)) != NFS2_FHSIZE) { 89 - dprintk("lockd: bad fhandle size %d (should be %d)\n", 90 - len, NFS2_FHSIZE); 91 - return NULL; 92 - } 93 - f->size = NFS2_FHSIZE; 94 - memset(f->data, 0, sizeof(f->data)); 95 - memcpy(f->data, p, NFS2_FHSIZE); 96 - return p + XDR_QUADLEN(NFS2_FHSIZE); 97 - } 98 - 99 - /* 100 - * Encode and decode owner handle 101 - */ 102 - static inline __be32 * 103 - nlm_decode_oh(__be32 *p, struct xdr_netobj *oh) 104 - { 105 - return xdr_decode_netobj(p, oh); 106 - } 107 - 108 - static inline __be32 * 109 - nlm_encode_oh(__be32 *p, struct xdr_netobj *oh) 110 - { 111 - return xdr_encode_netobj(p, oh); 112 - } 113 - 114 - static __be32 * 115 - nlm_decode_lock(__be32 *p, struct nlm_lock *lock) 116 - { 117 - struct file_lock *fl = &lock->fl; 118 - s32 start, len, end; 119 - 120 - if (!(p = xdr_decode_string_inplace(p, &lock->caller, 121 - &lock->len, 122 - NLM_MAXSTRLEN)) 123 - || !(p = nlm_decode_fh(p, &lock->fh)) 124 - || !(p = nlm_decode_oh(p, &lock->oh))) 125 - return NULL; 126 - lock->svid = ntohl(*p++); 77 + if (!svcxdr_decode_string(xdr, &lock->caller, &lock->len)) 78 + return false; 79 + if (!svcxdr_decode_fhandle(xdr, &lock->fh)) 80 + return false; 81 + if (!svcxdr_decode_owner(xdr, &lock->oh)) 82 + return false; 83 + if (xdr_stream_decode_u32(xdr, &lock->svid) < 0) 84 + return false; 85 + if (xdr_stream_decode_u32(xdr, &start) < 0) 86 + return false; 87 + if (xdr_stream_decode_u32(xdr, &len) < 0) 88 + return false; 127 89 128 90 locks_init_lock(fl); 129 91 fl->fl_flags = FL_POSIX; 130 - fl->fl_type = F_RDLCK; /* as good as anything else */ 131 - start = ntohl(*p++); 132 - len = ntohl(*p++); 92 + fl->fl_type = F_RDLCK; 133 93 end = start + len - 1; 134 - 135 94 fl->fl_start = s32_to_loff_t(start); 136 - 137 95 if (len == 0 || end < 0) 138 96 fl->fl_end = OFFSET_MAX; 139 97 else 140 98 fl->fl_end = s32_to_loff_t(end); 141 - return p; 99 + 100 + return true; 142 101 } 143 102 144 - /* 145 - * Encode result of a TEST/TEST_MSG call 146 - */ 147 - static __be32 * 148 - nlm_encode_testres(__be32 *p, struct nlm_res *resp) 103 + static bool 104 + svcxdr_encode_holder(struct xdr_stream *xdr, const struct nlm_lock *lock) 149 105 { 150 - s32 start, len; 106 + const struct file_lock *fl = &lock->fl; 107 + s32 start, len; 151 108 152 - if (!(p = nlm_encode_cookie(p, &resp->cookie))) 153 - return NULL; 154 - *p++ = resp->status; 109 + /* exclusive */ 110 + if (xdr_stream_encode_bool(xdr, fl->fl_type != F_RDLCK) < 0) 111 + return false; 112 + if (xdr_stream_encode_u32(xdr, lock->svid) < 0) 113 + return false; 114 + if (!svcxdr_encode_owner(xdr, &lock->oh)) 115 + return false; 116 + start = loff_t_to_s32(fl->fl_start); 117 + if (fl->fl_end == OFFSET_MAX) 118 + len = 0; 119 + else 120 + len = loff_t_to_s32(fl->fl_end - fl->fl_start + 1); 121 + if (xdr_stream_encode_u32(xdr, start) < 0) 122 + return false; 123 + if (xdr_stream_encode_u32(xdr, len) < 0) 124 + return false; 155 125 156 - if (resp->status == nlm_lck_denied) { 157 - struct file_lock *fl = &resp->lock.fl; 126 + return true; 127 + } 158 128 159 - *p++ = (fl->fl_type == F_RDLCK)? xdr_zero : xdr_one; 160 - *p++ = htonl(resp->lock.svid); 161 - 162 - /* Encode owner handle. */ 163 - if (!(p = xdr_encode_netobj(p, &resp->lock.oh))) 164 - return NULL; 165 - 166 - start = loff_t_to_s32(fl->fl_start); 167 - if (fl->fl_end == OFFSET_MAX) 168 - len = 0; 169 - else 170 - len = loff_t_to_s32(fl->fl_end - fl->fl_start + 1); 171 - 172 - *p++ = htonl(start); 173 - *p++ = htonl(len); 129 + static bool 130 + svcxdr_encode_testrply(struct xdr_stream *xdr, const struct nlm_res *resp) 131 + { 132 + if (!svcxdr_encode_stats(xdr, resp->status)) 133 + return false; 134 + switch (resp->status) { 135 + case nlm_lck_denied: 136 + if (!svcxdr_encode_holder(xdr, &resp->lock)) 137 + return false; 174 138 } 175 139 176 - return p; 140 + return true; 177 141 } 178 142 179 143 180 144 /* 181 - * First, the server side XDR functions 145 + * Decode Call arguments 182 146 */ 147 + 148 + int 149 + nlmsvc_decode_void(struct svc_rqst *rqstp, __be32 *p) 150 + { 151 + return 1; 152 + } 153 + 183 154 int 184 155 nlmsvc_decode_testargs(struct svc_rqst *rqstp, __be32 *p) 185 156 { 157 + struct xdr_stream *xdr = &rqstp->rq_arg_stream; 186 158 struct nlm_args *argp = rqstp->rq_argp; 187 - u32 exclusive; 159 + u32 exclusive; 188 160 189 - if (!(p = nlm_decode_cookie(p, &argp->cookie))) 161 + if (!svcxdr_decode_cookie(xdr, &argp->cookie)) 190 162 return 0; 191 - 192 - exclusive = ntohl(*p++); 193 - if (!(p = nlm_decode_lock(p, &argp->lock))) 163 + if (xdr_stream_decode_bool(xdr, &exclusive) < 0) 164 + return 0; 165 + if (!svcxdr_decode_lock(xdr, &argp->lock)) 194 166 return 0; 195 167 if (exclusive) 196 168 argp->lock.fl.fl_type = F_WRLCK; 197 169 198 - return xdr_argsize_check(rqstp, p); 199 - } 200 - 201 - int 202 - nlmsvc_encode_testres(struct svc_rqst *rqstp, __be32 *p) 203 - { 204 - struct nlm_res *resp = rqstp->rq_resp; 205 - 206 - if (!(p = nlm_encode_testres(p, resp))) 207 - return 0; 208 - return xdr_ressize_check(rqstp, p); 170 + return 1; 209 171 } 210 172 211 173 int 212 174 nlmsvc_decode_lockargs(struct svc_rqst *rqstp, __be32 *p) 213 175 { 176 + struct xdr_stream *xdr = &rqstp->rq_arg_stream; 214 177 struct nlm_args *argp = rqstp->rq_argp; 215 - u32 exclusive; 178 + u32 exclusive; 216 179 217 - if (!(p = nlm_decode_cookie(p, &argp->cookie))) 180 + if (!svcxdr_decode_cookie(xdr, &argp->cookie)) 218 181 return 0; 219 - argp->block = ntohl(*p++); 220 - exclusive = ntohl(*p++); 221 - if (!(p = nlm_decode_lock(p, &argp->lock))) 182 + if (xdr_stream_decode_bool(xdr, &argp->block) < 0) 183 + return 0; 184 + if (xdr_stream_decode_bool(xdr, &exclusive) < 0) 185 + return 0; 186 + if (!svcxdr_decode_lock(xdr, &argp->lock)) 222 187 return 0; 223 188 if (exclusive) 224 189 argp->lock.fl.fl_type = F_WRLCK; 225 - argp->reclaim = ntohl(*p++); 226 - argp->state = ntohl(*p++); 190 + if (xdr_stream_decode_bool(xdr, &argp->reclaim) < 0) 191 + return 0; 192 + if (xdr_stream_decode_u32(xdr, &argp->state) < 0) 193 + return 0; 227 194 argp->monitor = 1; /* monitor client by default */ 228 195 229 - return xdr_argsize_check(rqstp, p); 196 + return 1; 230 197 } 231 198 232 199 int 233 200 nlmsvc_decode_cancargs(struct svc_rqst *rqstp, __be32 *p) 234 201 { 202 + struct xdr_stream *xdr = &rqstp->rq_arg_stream; 235 203 struct nlm_args *argp = rqstp->rq_argp; 236 - u32 exclusive; 204 + u32 exclusive; 237 205 238 - if (!(p = nlm_decode_cookie(p, &argp->cookie))) 206 + if (!svcxdr_decode_cookie(xdr, &argp->cookie)) 239 207 return 0; 240 - argp->block = ntohl(*p++); 241 - exclusive = ntohl(*p++); 242 - if (!(p = nlm_decode_lock(p, &argp->lock))) 208 + if (xdr_stream_decode_bool(xdr, &argp->block) < 0) 209 + return 0; 210 + if (xdr_stream_decode_bool(xdr, &exclusive) < 0) 211 + return 0; 212 + if (!svcxdr_decode_lock(xdr, &argp->lock)) 243 213 return 0; 244 214 if (exclusive) 245 215 argp->lock.fl.fl_type = F_WRLCK; 246 - return xdr_argsize_check(rqstp, p); 216 + 217 + return 1; 247 218 } 248 219 249 220 int 250 221 nlmsvc_decode_unlockargs(struct svc_rqst *rqstp, __be32 *p) 251 222 { 223 + struct xdr_stream *xdr = &rqstp->rq_arg_stream; 252 224 struct nlm_args *argp = rqstp->rq_argp; 253 225 254 - if (!(p = nlm_decode_cookie(p, &argp->cookie)) 255 - || !(p = nlm_decode_lock(p, &argp->lock))) 226 + if (!svcxdr_decode_cookie(xdr, &argp->cookie)) 227 + return 0; 228 + if (!svcxdr_decode_lock(xdr, &argp->lock)) 256 229 return 0; 257 230 argp->lock.fl.fl_type = F_UNLCK; 258 - return xdr_argsize_check(rqstp, p); 259 - } 260 231 261 - int 262 - nlmsvc_decode_shareargs(struct svc_rqst *rqstp, __be32 *p) 263 - { 264 - struct nlm_args *argp = rqstp->rq_argp; 265 - struct nlm_lock *lock = &argp->lock; 266 - 267 - memset(lock, 0, sizeof(*lock)); 268 - locks_init_lock(&lock->fl); 269 - lock->svid = ~(u32) 0; 270 - 271 - if (!(p = nlm_decode_cookie(p, &argp->cookie)) 272 - || !(p = xdr_decode_string_inplace(p, &lock->caller, 273 - &lock->len, NLM_MAXSTRLEN)) 274 - || !(p = nlm_decode_fh(p, &lock->fh)) 275 - || !(p = nlm_decode_oh(p, &lock->oh))) 276 - return 0; 277 - argp->fsm_mode = ntohl(*p++); 278 - argp->fsm_access = ntohl(*p++); 279 - return xdr_argsize_check(rqstp, p); 280 - } 281 - 282 - int 283 - nlmsvc_encode_shareres(struct svc_rqst *rqstp, __be32 *p) 284 - { 285 - struct nlm_res *resp = rqstp->rq_resp; 286 - 287 - if (!(p = nlm_encode_cookie(p, &resp->cookie))) 288 - return 0; 289 - *p++ = resp->status; 290 - *p++ = xdr_zero; /* sequence argument */ 291 - return xdr_ressize_check(rqstp, p); 292 - } 293 - 294 - int 295 - nlmsvc_encode_res(struct svc_rqst *rqstp, __be32 *p) 296 - { 297 - struct nlm_res *resp = rqstp->rq_resp; 298 - 299 - if (!(p = nlm_encode_cookie(p, &resp->cookie))) 300 - return 0; 301 - *p++ = resp->status; 302 - return xdr_ressize_check(rqstp, p); 303 - } 304 - 305 - int 306 - nlmsvc_decode_notify(struct svc_rqst *rqstp, __be32 *p) 307 - { 308 - struct nlm_args *argp = rqstp->rq_argp; 309 - struct nlm_lock *lock = &argp->lock; 310 - 311 - if (!(p = xdr_decode_string_inplace(p, &lock->caller, 312 - &lock->len, NLM_MAXSTRLEN))) 313 - return 0; 314 - argp->state = ntohl(*p++); 315 - return xdr_argsize_check(rqstp, p); 316 - } 317 - 318 - int 319 - nlmsvc_decode_reboot(struct svc_rqst *rqstp, __be32 *p) 320 - { 321 - struct nlm_reboot *argp = rqstp->rq_argp; 322 - 323 - if (!(p = xdr_decode_string_inplace(p, &argp->mon, &argp->len, SM_MAXSTRLEN))) 324 - return 0; 325 - argp->state = ntohl(*p++); 326 - memcpy(&argp->priv.data, p, sizeof(argp->priv.data)); 327 - p += XDR_QUADLEN(SM_PRIV_SIZE); 328 - return xdr_argsize_check(rqstp, p); 232 + return 1; 329 233 } 330 234 331 235 int 332 236 nlmsvc_decode_res(struct svc_rqst *rqstp, __be32 *p) 333 237 { 238 + struct xdr_stream *xdr = &rqstp->rq_arg_stream; 334 239 struct nlm_res *resp = rqstp->rq_argp; 335 240 336 - if (!(p = nlm_decode_cookie(p, &resp->cookie))) 241 + if (!svcxdr_decode_cookie(xdr, &resp->cookie)) 337 242 return 0; 338 - resp->status = *p++; 339 - return xdr_argsize_check(rqstp, p); 243 + if (!svcxdr_decode_stats(xdr, &resp->status)) 244 + return 0; 245 + 246 + return 1; 340 247 } 341 248 342 249 int 343 - nlmsvc_decode_void(struct svc_rqst *rqstp, __be32 *p) 250 + nlmsvc_decode_reboot(struct svc_rqst *rqstp, __be32 *p) 344 251 { 345 - return xdr_argsize_check(rqstp, p); 252 + struct xdr_stream *xdr = &rqstp->rq_arg_stream; 253 + struct nlm_reboot *argp = rqstp->rq_argp; 254 + u32 len; 255 + 256 + if (xdr_stream_decode_u32(xdr, &len) < 0) 257 + return 0; 258 + if (len > SM_MAXSTRLEN) 259 + return 0; 260 + p = xdr_inline_decode(xdr, len); 261 + if (!p) 262 + return 0; 263 + argp->len = len; 264 + argp->mon = (char *)p; 265 + if (xdr_stream_decode_u32(xdr, &argp->state) < 0) 266 + return 0; 267 + p = xdr_inline_decode(xdr, SM_PRIV_SIZE); 268 + if (!p) 269 + return 0; 270 + memcpy(&argp->priv.data, p, sizeof(argp->priv.data)); 271 + 272 + return 1; 346 273 } 274 + 275 + int 276 + nlmsvc_decode_shareargs(struct svc_rqst *rqstp, __be32 *p) 277 + { 278 + struct xdr_stream *xdr = &rqstp->rq_arg_stream; 279 + struct nlm_args *argp = rqstp->rq_argp; 280 + struct nlm_lock *lock = &argp->lock; 281 + 282 + memset(lock, 0, sizeof(*lock)); 283 + locks_init_lock(&lock->fl); 284 + lock->svid = ~(u32)0; 285 + 286 + if (!svcxdr_decode_cookie(xdr, &argp->cookie)) 287 + return 0; 288 + if (!svcxdr_decode_string(xdr, &lock->caller, &lock->len)) 289 + return 0; 290 + if (!svcxdr_decode_fhandle(xdr, &lock->fh)) 291 + return 0; 292 + if (!svcxdr_decode_owner(xdr, &lock->oh)) 293 + return 0; 294 + /* XXX: Range checks are missing in the original code */ 295 + if (xdr_stream_decode_u32(xdr, &argp->fsm_mode) < 0) 296 + return 0; 297 + if (xdr_stream_decode_u32(xdr, &argp->fsm_access) < 0) 298 + return 0; 299 + 300 + return 1; 301 + } 302 + 303 + int 304 + nlmsvc_decode_notify(struct svc_rqst *rqstp, __be32 *p) 305 + { 306 + struct xdr_stream *xdr = &rqstp->rq_arg_stream; 307 + struct nlm_args *argp = rqstp->rq_argp; 308 + struct nlm_lock *lock = &argp->lock; 309 + 310 + if (!svcxdr_decode_string(xdr, &lock->caller, &lock->len)) 311 + return 0; 312 + if (xdr_stream_decode_u32(xdr, &argp->state) < 0) 313 + return 0; 314 + 315 + return 1; 316 + } 317 + 318 + 319 + /* 320 + * Encode Reply results 321 + */ 347 322 348 323 int 349 324 nlmsvc_encode_void(struct svc_rqst *rqstp, __be32 *p) 350 325 { 351 - return xdr_ressize_check(rqstp, p); 326 + return 1; 327 + } 328 + 329 + int 330 + nlmsvc_encode_testres(struct svc_rqst *rqstp, __be32 *p) 331 + { 332 + struct xdr_stream *xdr = &rqstp->rq_res_stream; 333 + struct nlm_res *resp = rqstp->rq_resp; 334 + 335 + return svcxdr_encode_cookie(xdr, &resp->cookie) && 336 + svcxdr_encode_testrply(xdr, resp); 337 + } 338 + 339 + int 340 + nlmsvc_encode_res(struct svc_rqst *rqstp, __be32 *p) 341 + { 342 + struct xdr_stream *xdr = &rqstp->rq_res_stream; 343 + struct nlm_res *resp = rqstp->rq_resp; 344 + 345 + return svcxdr_encode_cookie(xdr, &resp->cookie) && 346 + svcxdr_encode_stats(xdr, resp->status); 347 + } 348 + 349 + int 350 + nlmsvc_encode_shareres(struct svc_rqst *rqstp, __be32 *p) 351 + { 352 + struct xdr_stream *xdr = &rqstp->rq_res_stream; 353 + struct nlm_res *resp = rqstp->rq_resp; 354 + 355 + if (!svcxdr_encode_cookie(xdr, &resp->cookie)) 356 + return 0; 357 + if (!svcxdr_encode_stats(xdr, resp->status)) 358 + return 0; 359 + /* sequence */ 360 + if (xdr_stream_encode_u32(xdr, 0) < 0) 361 + return 0; 362 + 363 + return 1; 352 364 }
+229 -216
fs/lockd/xdr4.c
··· 18 18 #include <linux/sunrpc/stats.h> 19 19 #include <linux/lockd/lockd.h> 20 20 21 - #define NLMDBG_FACILITY NLMDBG_XDR 21 + #include "svcxdr.h" 22 22 23 23 static inline loff_t 24 24 s64_to_loff_t(__s64 offset) ··· 41 41 } 42 42 43 43 /* 44 - * XDR functions for basic NLM types 44 + * NLM file handles are defined by specification to be a variable-length 45 + * XDR opaque no longer than 1024 bytes. However, this implementation 46 + * limits their length to the size of an NFSv3 file handle. 45 47 */ 46 - static __be32 * 47 - nlm4_decode_cookie(__be32 *p, struct nlm_cookie *c) 48 + static bool 49 + svcxdr_decode_fhandle(struct xdr_stream *xdr, struct nfs_fh *fh) 48 50 { 49 - unsigned int len; 51 + __be32 *p; 52 + u32 len; 50 53 51 - len = ntohl(*p++); 52 - 53 - if(len==0) 54 - { 55 - c->len=4; 56 - memset(c->data, 0, 4); /* hockeypux brain damage */ 57 - } 58 - else if(len<=NLM_MAXCOOKIELEN) 59 - { 60 - c->len=len; 61 - memcpy(c->data, p, len); 62 - p+=XDR_QUADLEN(len); 63 - } 64 - else 65 - { 66 - dprintk("lockd: bad cookie size %d (only cookies under " 67 - "%d bytes are supported.)\n", 68 - len, NLM_MAXCOOKIELEN); 69 - return NULL; 70 - } 71 - return p; 54 + if (xdr_stream_decode_u32(xdr, &len) < 0) 55 + return false; 56 + if (len > NFS_MAXFHSIZE) 57 + return false; 58 + 59 + p = xdr_inline_decode(xdr, len); 60 + if (!p) 61 + return false; 62 + fh->size = len; 63 + memcpy(fh->data, p, len); 64 + memset(fh->data + len, 0, sizeof(fh->data) - len); 65 + 66 + return true; 72 67 } 73 68 74 - static __be32 * 75 - nlm4_encode_cookie(__be32 *p, struct nlm_cookie *c) 69 + static bool 70 + svcxdr_decode_lock(struct xdr_stream *xdr, struct nlm_lock *lock) 76 71 { 77 - *p++ = htonl(c->len); 78 - memcpy(p, c->data, c->len); 79 - p+=XDR_QUADLEN(c->len); 80 - return p; 81 - } 72 + struct file_lock *fl = &lock->fl; 73 + u64 len, start; 74 + s64 end; 82 75 83 - static __be32 * 84 - nlm4_decode_fh(__be32 *p, struct nfs_fh *f) 85 - { 86 - memset(f->data, 0, sizeof(f->data)); 87 - f->size = ntohl(*p++); 88 - if (f->size > NFS_MAXFHSIZE) { 89 - dprintk("lockd: bad fhandle size %d (should be <=%d)\n", 90 - f->size, NFS_MAXFHSIZE); 91 - return NULL; 92 - } 93 - memcpy(f->data, p, f->size); 94 - return p + XDR_QUADLEN(f->size); 95 - } 96 - 97 - /* 98 - * Encode and decode owner handle 99 - */ 100 - static __be32 * 101 - nlm4_decode_oh(__be32 *p, struct xdr_netobj *oh) 102 - { 103 - return xdr_decode_netobj(p, oh); 104 - } 105 - 106 - static __be32 * 107 - nlm4_decode_lock(__be32 *p, struct nlm_lock *lock) 108 - { 109 - struct file_lock *fl = &lock->fl; 110 - __u64 len, start; 111 - __s64 end; 112 - 113 - if (!(p = xdr_decode_string_inplace(p, &lock->caller, 114 - &lock->len, NLM_MAXSTRLEN)) 115 - || !(p = nlm4_decode_fh(p, &lock->fh)) 116 - || !(p = nlm4_decode_oh(p, &lock->oh))) 117 - return NULL; 118 - lock->svid = ntohl(*p++); 76 + if (!svcxdr_decode_string(xdr, &lock->caller, &lock->len)) 77 + return false; 78 + if (!svcxdr_decode_fhandle(xdr, &lock->fh)) 79 + return false; 80 + if (!svcxdr_decode_owner(xdr, &lock->oh)) 81 + return false; 82 + if (xdr_stream_decode_u32(xdr, &lock->svid) < 0) 83 + return false; 84 + if (xdr_stream_decode_u64(xdr, &start) < 0) 85 + return false; 86 + if (xdr_stream_decode_u64(xdr, &len) < 0) 87 + return false; 119 88 120 89 locks_init_lock(fl); 121 90 fl->fl_flags = FL_POSIX; 122 - fl->fl_type = F_RDLCK; /* as good as anything else */ 123 - p = xdr_decode_hyper(p, &start); 124 - p = xdr_decode_hyper(p, &len); 91 + fl->fl_type = F_RDLCK; 125 92 end = start + len - 1; 126 - 127 93 fl->fl_start = s64_to_loff_t(start); 128 - 129 94 if (len == 0 || end < 0) 130 95 fl->fl_end = OFFSET_MAX; 131 96 else 132 97 fl->fl_end = s64_to_loff_t(end); 133 - return p; 98 + 99 + return true; 134 100 } 135 101 136 - /* 137 - * Encode result of a TEST/TEST_MSG call 138 - */ 139 - static __be32 * 140 - nlm4_encode_testres(__be32 *p, struct nlm_res *resp) 102 + static bool 103 + svcxdr_encode_holder(struct xdr_stream *xdr, const struct nlm_lock *lock) 141 104 { 142 - s64 start, len; 105 + const struct file_lock *fl = &lock->fl; 106 + s64 start, len; 143 107 144 - dprintk("xdr: before encode_testres (p %p resp %p)\n", p, resp); 145 - if (!(p = nlm4_encode_cookie(p, &resp->cookie))) 146 - return NULL; 147 - *p++ = resp->status; 108 + /* exclusive */ 109 + if (xdr_stream_encode_bool(xdr, fl->fl_type != F_RDLCK) < 0) 110 + return false; 111 + if (xdr_stream_encode_u32(xdr, lock->svid) < 0) 112 + return false; 113 + if (!svcxdr_encode_owner(xdr, &lock->oh)) 114 + return false; 115 + start = loff_t_to_s64(fl->fl_start); 116 + if (fl->fl_end == OFFSET_MAX) 117 + len = 0; 118 + else 119 + len = loff_t_to_s64(fl->fl_end - fl->fl_start + 1); 120 + if (xdr_stream_encode_u64(xdr, start) < 0) 121 + return false; 122 + if (xdr_stream_encode_u64(xdr, len) < 0) 123 + return false; 148 124 149 - if (resp->status == nlm_lck_denied) { 150 - struct file_lock *fl = &resp->lock.fl; 125 + return true; 126 + } 151 127 152 - *p++ = (fl->fl_type == F_RDLCK)? xdr_zero : xdr_one; 153 - *p++ = htonl(resp->lock.svid); 154 - 155 - /* Encode owner handle. */ 156 - if (!(p = xdr_encode_netobj(p, &resp->lock.oh))) 157 - return NULL; 158 - 159 - start = loff_t_to_s64(fl->fl_start); 160 - if (fl->fl_end == OFFSET_MAX) 161 - len = 0; 162 - else 163 - len = loff_t_to_s64(fl->fl_end - fl->fl_start + 1); 164 - 165 - p = xdr_encode_hyper(p, start); 166 - p = xdr_encode_hyper(p, len); 167 - dprintk("xdr: encode_testres (status %u pid %d type %d start %Ld end %Ld)\n", 168 - resp->status, (int)resp->lock.svid, fl->fl_type, 169 - (long long)fl->fl_start, (long long)fl->fl_end); 128 + static bool 129 + svcxdr_encode_testrply(struct xdr_stream *xdr, const struct nlm_res *resp) 130 + { 131 + if (!svcxdr_encode_stats(xdr, resp->status)) 132 + return false; 133 + switch (resp->status) { 134 + case nlm_lck_denied: 135 + if (!svcxdr_encode_holder(xdr, &resp->lock)) 136 + return false; 170 137 } 171 138 172 - dprintk("xdr: after encode_testres (p %p resp %p)\n", p, resp); 173 - return p; 139 + return true; 174 140 } 175 141 176 142 177 143 /* 178 - * First, the server side XDR functions 144 + * Decode Call arguments 179 145 */ 146 + 147 + int 148 + nlm4svc_decode_void(struct svc_rqst *rqstp, __be32 *p) 149 + { 150 + return 1; 151 + } 152 + 180 153 int 181 154 nlm4svc_decode_testargs(struct svc_rqst *rqstp, __be32 *p) 182 155 { 156 + struct xdr_stream *xdr = &rqstp->rq_arg_stream; 183 157 struct nlm_args *argp = rqstp->rq_argp; 184 - u32 exclusive; 158 + u32 exclusive; 185 159 186 - if (!(p = nlm4_decode_cookie(p, &argp->cookie))) 160 + if (!svcxdr_decode_cookie(xdr, &argp->cookie)) 187 161 return 0; 188 - 189 - exclusive = ntohl(*p++); 190 - if (!(p = nlm4_decode_lock(p, &argp->lock))) 162 + if (xdr_stream_decode_bool(xdr, &exclusive) < 0) 163 + return 0; 164 + if (!svcxdr_decode_lock(xdr, &argp->lock)) 191 165 return 0; 192 166 if (exclusive) 193 167 argp->lock.fl.fl_type = F_WRLCK; 194 168 195 - return xdr_argsize_check(rqstp, p); 196 - } 197 - 198 - int 199 - nlm4svc_encode_testres(struct svc_rqst *rqstp, __be32 *p) 200 - { 201 - struct nlm_res *resp = rqstp->rq_resp; 202 - 203 - if (!(p = nlm4_encode_testres(p, resp))) 204 - return 0; 205 - return xdr_ressize_check(rqstp, p); 169 + return 1; 206 170 } 207 171 208 172 int 209 173 nlm4svc_decode_lockargs(struct svc_rqst *rqstp, __be32 *p) 210 174 { 175 + struct xdr_stream *xdr = &rqstp->rq_arg_stream; 211 176 struct nlm_args *argp = rqstp->rq_argp; 212 - u32 exclusive; 177 + u32 exclusive; 213 178 214 - if (!(p = nlm4_decode_cookie(p, &argp->cookie))) 179 + if (!svcxdr_decode_cookie(xdr, &argp->cookie)) 215 180 return 0; 216 - argp->block = ntohl(*p++); 217 - exclusive = ntohl(*p++); 218 - if (!(p = nlm4_decode_lock(p, &argp->lock))) 181 + if (xdr_stream_decode_bool(xdr, &argp->block) < 0) 182 + return 0; 183 + if (xdr_stream_decode_bool(xdr, &exclusive) < 0) 184 + return 0; 185 + if (!svcxdr_decode_lock(xdr, &argp->lock)) 219 186 return 0; 220 187 if (exclusive) 221 188 argp->lock.fl.fl_type = F_WRLCK; 222 - argp->reclaim = ntohl(*p++); 223 - argp->state = ntohl(*p++); 189 + if (xdr_stream_decode_bool(xdr, &argp->reclaim) < 0) 190 + return 0; 191 + if (xdr_stream_decode_u32(xdr, &argp->state) < 0) 192 + return 0; 224 193 argp->monitor = 1; /* monitor client by default */ 225 194 226 - return xdr_argsize_check(rqstp, p); 195 + return 1; 227 196 } 228 197 229 198 int 230 199 nlm4svc_decode_cancargs(struct svc_rqst *rqstp, __be32 *p) 231 200 { 201 + struct xdr_stream *xdr = &rqstp->rq_arg_stream; 232 202 struct nlm_args *argp = rqstp->rq_argp; 233 - u32 exclusive; 203 + u32 exclusive; 234 204 235 - if (!(p = nlm4_decode_cookie(p, &argp->cookie))) 205 + if (!svcxdr_decode_cookie(xdr, &argp->cookie)) 236 206 return 0; 237 - argp->block = ntohl(*p++); 238 - exclusive = ntohl(*p++); 239 - if (!(p = nlm4_decode_lock(p, &argp->lock))) 207 + if (xdr_stream_decode_bool(xdr, &argp->block) < 0) 208 + return 0; 209 + if (xdr_stream_decode_bool(xdr, &exclusive) < 0) 210 + return 0; 211 + if (!svcxdr_decode_lock(xdr, &argp->lock)) 240 212 return 0; 241 213 if (exclusive) 242 214 argp->lock.fl.fl_type = F_WRLCK; 243 - return xdr_argsize_check(rqstp, p); 215 + return 1; 244 216 } 245 217 246 218 int 247 219 nlm4svc_decode_unlockargs(struct svc_rqst *rqstp, __be32 *p) 248 220 { 221 + struct xdr_stream *xdr = &rqstp->rq_arg_stream; 249 222 struct nlm_args *argp = rqstp->rq_argp; 250 223 251 - if (!(p = nlm4_decode_cookie(p, &argp->cookie)) 252 - || !(p = nlm4_decode_lock(p, &argp->lock))) 224 + if (!svcxdr_decode_cookie(xdr, &argp->cookie)) 225 + return 0; 226 + if (!svcxdr_decode_lock(xdr, &argp->lock)) 253 227 return 0; 254 228 argp->lock.fl.fl_type = F_UNLCK; 255 - return xdr_argsize_check(rqstp, p); 256 - } 257 229 258 - int 259 - nlm4svc_decode_shareargs(struct svc_rqst *rqstp, __be32 *p) 260 - { 261 - struct nlm_args *argp = rqstp->rq_argp; 262 - struct nlm_lock *lock = &argp->lock; 263 - 264 - memset(lock, 0, sizeof(*lock)); 265 - locks_init_lock(&lock->fl); 266 - lock->svid = ~(u32) 0; 267 - 268 - if (!(p = nlm4_decode_cookie(p, &argp->cookie)) 269 - || !(p = xdr_decode_string_inplace(p, &lock->caller, 270 - &lock->len, NLM_MAXSTRLEN)) 271 - || !(p = nlm4_decode_fh(p, &lock->fh)) 272 - || !(p = nlm4_decode_oh(p, &lock->oh))) 273 - return 0; 274 - argp->fsm_mode = ntohl(*p++); 275 - argp->fsm_access = ntohl(*p++); 276 - return xdr_argsize_check(rqstp, p); 277 - } 278 - 279 - int 280 - nlm4svc_encode_shareres(struct svc_rqst *rqstp, __be32 *p) 281 - { 282 - struct nlm_res *resp = rqstp->rq_resp; 283 - 284 - if (!(p = nlm4_encode_cookie(p, &resp->cookie))) 285 - return 0; 286 - *p++ = resp->status; 287 - *p++ = xdr_zero; /* sequence argument */ 288 - return xdr_ressize_check(rqstp, p); 289 - } 290 - 291 - int 292 - nlm4svc_encode_res(struct svc_rqst *rqstp, __be32 *p) 293 - { 294 - struct nlm_res *resp = rqstp->rq_resp; 295 - 296 - if (!(p = nlm4_encode_cookie(p, &resp->cookie))) 297 - return 0; 298 - *p++ = resp->status; 299 - return xdr_ressize_check(rqstp, p); 300 - } 301 - 302 - int 303 - nlm4svc_decode_notify(struct svc_rqst *rqstp, __be32 *p) 304 - { 305 - struct nlm_args *argp = rqstp->rq_argp; 306 - struct nlm_lock *lock = &argp->lock; 307 - 308 - if (!(p = xdr_decode_string_inplace(p, &lock->caller, 309 - &lock->len, NLM_MAXSTRLEN))) 310 - return 0; 311 - argp->state = ntohl(*p++); 312 - return xdr_argsize_check(rqstp, p); 313 - } 314 - 315 - int 316 - nlm4svc_decode_reboot(struct svc_rqst *rqstp, __be32 *p) 317 - { 318 - struct nlm_reboot *argp = rqstp->rq_argp; 319 - 320 - if (!(p = xdr_decode_string_inplace(p, &argp->mon, &argp->len, SM_MAXSTRLEN))) 321 - return 0; 322 - argp->state = ntohl(*p++); 323 - memcpy(&argp->priv.data, p, sizeof(argp->priv.data)); 324 - p += XDR_QUADLEN(SM_PRIV_SIZE); 325 - return xdr_argsize_check(rqstp, p); 230 + return 1; 326 231 } 327 232 328 233 int 329 234 nlm4svc_decode_res(struct svc_rqst *rqstp, __be32 *p) 330 235 { 236 + struct xdr_stream *xdr = &rqstp->rq_arg_stream; 331 237 struct nlm_res *resp = rqstp->rq_argp; 332 238 333 - if (!(p = nlm4_decode_cookie(p, &resp->cookie))) 239 + if (!svcxdr_decode_cookie(xdr, &resp->cookie)) 334 240 return 0; 335 - resp->status = *p++; 336 - return xdr_argsize_check(rqstp, p); 241 + if (!svcxdr_decode_stats(xdr, &resp->status)) 242 + return 0; 243 + 244 + return 1; 337 245 } 338 246 339 247 int 340 - nlm4svc_decode_void(struct svc_rqst *rqstp, __be32 *p) 248 + nlm4svc_decode_reboot(struct svc_rqst *rqstp, __be32 *p) 341 249 { 342 - return xdr_argsize_check(rqstp, p); 250 + struct xdr_stream *xdr = &rqstp->rq_arg_stream; 251 + struct nlm_reboot *argp = rqstp->rq_argp; 252 + u32 len; 253 + 254 + if (xdr_stream_decode_u32(xdr, &len) < 0) 255 + return 0; 256 + if (len > SM_MAXSTRLEN) 257 + return 0; 258 + p = xdr_inline_decode(xdr, len); 259 + if (!p) 260 + return 0; 261 + argp->len = len; 262 + argp->mon = (char *)p; 263 + if (xdr_stream_decode_u32(xdr, &argp->state) < 0) 264 + return 0; 265 + p = xdr_inline_decode(xdr, SM_PRIV_SIZE); 266 + if (!p) 267 + return 0; 268 + memcpy(&argp->priv.data, p, sizeof(argp->priv.data)); 269 + 270 + return 1; 343 271 } 272 + 273 + int 274 + nlm4svc_decode_shareargs(struct svc_rqst *rqstp, __be32 *p) 275 + { 276 + struct xdr_stream *xdr = &rqstp->rq_arg_stream; 277 + struct nlm_args *argp = rqstp->rq_argp; 278 + struct nlm_lock *lock = &argp->lock; 279 + 280 + memset(lock, 0, sizeof(*lock)); 281 + locks_init_lock(&lock->fl); 282 + lock->svid = ~(u32)0; 283 + 284 + if (!svcxdr_decode_cookie(xdr, &argp->cookie)) 285 + return 0; 286 + if (!svcxdr_decode_string(xdr, &lock->caller, &lock->len)) 287 + return 0; 288 + if (!svcxdr_decode_fhandle(xdr, &lock->fh)) 289 + return 0; 290 + if (!svcxdr_decode_owner(xdr, &lock->oh)) 291 + return 0; 292 + /* XXX: Range checks are missing in the original code */ 293 + if (xdr_stream_decode_u32(xdr, &argp->fsm_mode) < 0) 294 + return 0; 295 + if (xdr_stream_decode_u32(xdr, &argp->fsm_access) < 0) 296 + return 0; 297 + 298 + return 1; 299 + } 300 + 301 + int 302 + nlm4svc_decode_notify(struct svc_rqst *rqstp, __be32 *p) 303 + { 304 + struct xdr_stream *xdr = &rqstp->rq_arg_stream; 305 + struct nlm_args *argp = rqstp->rq_argp; 306 + struct nlm_lock *lock = &argp->lock; 307 + 308 + if (!svcxdr_decode_string(xdr, &lock->caller, &lock->len)) 309 + return 0; 310 + if (xdr_stream_decode_u32(xdr, &argp->state) < 0) 311 + return 0; 312 + 313 + return 1; 314 + } 315 + 316 + 317 + /* 318 + * Encode Reply results 319 + */ 344 320 345 321 int 346 322 nlm4svc_encode_void(struct svc_rqst *rqstp, __be32 *p) 347 323 { 348 - return xdr_ressize_check(rqstp, p); 324 + return 1; 325 + } 326 + 327 + int 328 + nlm4svc_encode_testres(struct svc_rqst *rqstp, __be32 *p) 329 + { 330 + struct xdr_stream *xdr = &rqstp->rq_res_stream; 331 + struct nlm_res *resp = rqstp->rq_resp; 332 + 333 + return svcxdr_encode_cookie(xdr, &resp->cookie) && 334 + svcxdr_encode_testrply(xdr, resp); 335 + } 336 + 337 + int 338 + nlm4svc_encode_res(struct svc_rqst *rqstp, __be32 *p) 339 + { 340 + struct xdr_stream *xdr = &rqstp->rq_res_stream; 341 + struct nlm_res *resp = rqstp->rq_resp; 342 + 343 + return svcxdr_encode_cookie(xdr, &resp->cookie) && 344 + svcxdr_encode_stats(xdr, resp->status); 345 + } 346 + 347 + int 348 + nlm4svc_encode_shareres(struct svc_rqst *rqstp, __be32 *p) 349 + { 350 + struct xdr_stream *xdr = &rqstp->rq_res_stream; 351 + struct nlm_res *resp = rqstp->rq_resp; 352 + 353 + if (!svcxdr_encode_cookie(xdr, &resp->cookie)) 354 + return 0; 355 + if (!svcxdr_encode_stats(xdr, resp->status)) 356 + return 0; 357 + /* sequence */ 358 + if (xdr_stream_encode_u32(xdr, 0) < 0) 359 + return 0; 360 + 361 + return 1; 349 362 }
+1
fs/nfs_common/grace.c
··· 82 82 83 83 /** 84 84 * locks_in_grace 85 + * @net: network namespace 85 86 * 86 87 * Lock managers call this function to determine when it is OK for them 87 88 * to answer ordinary lock requests, and when they should accept only
+6
fs/nfsd/netns.h
··· 176 176 unsigned int longest_chain_cachesize; 177 177 178 178 struct shrinker nfsd_reply_cache_shrinker; 179 + 180 + /* tracking server-to-server copy mounts */ 181 + spinlock_t nfsd_ssc_lock; 182 + struct list_head nfsd_ssc_mount_list; 183 + wait_queue_head_t nfsd_ssc_waitq; 184 + 179 185 /* utsname taken from the process that starts the server */ 180 186 char nfsd_name[UNX_MAXNODENAME+1]; 181 187 };
+2 -1
fs/nfsd/nfs3acl.c
··· 172 172 struct nfsd3_getaclres *resp = rqstp->rq_resp; 173 173 struct dentry *dentry = resp->fh.fh_dentry; 174 174 struct kvec *head = rqstp->rq_res.head; 175 - struct inode *inode = d_inode(dentry); 175 + struct inode *inode; 176 176 unsigned int base; 177 177 int n; 178 178 int w; ··· 181 181 return 0; 182 182 switch (resp->status) { 183 183 case nfs_ok: 184 + inode = d_inode(dentry); 184 185 if (!svcxdr_encode_post_op_attr(rqstp, xdr, &resp->fh)) 185 186 return 0; 186 187 if (xdr_stream_encode_u32(xdr, resp->mask) < 0)
+24 -23
fs/nfsd/nfs4callback.c
··· 915 915 args.authflavor = clp->cl_cred.cr_flavor; 916 916 clp->cl_cb_ident = conn->cb_ident; 917 917 } else { 918 - if (!conn->cb_xprt) { 919 - trace_nfsd_cb_setup_err(clp, -EINVAL); 918 + if (!conn->cb_xprt) 920 919 return -EINVAL; 921 - } 922 920 clp->cl_cb_conn.cb_xprt = conn->cb_xprt; 923 921 clp->cl_cb_session = ses; 924 922 args.bc_xprt = conn->cb_xprt; ··· 939 941 } 940 942 clp->cl_cb_client = client; 941 943 clp->cl_cb_cred = cred; 942 - trace_nfsd_cb_setup(clp); 944 + rcu_read_lock(); 945 + trace_nfsd_cb_setup(clp, rpc_peeraddr2str(client, RPC_DISPLAY_NETID), 946 + args.authflavor); 947 + rcu_read_unlock(); 943 948 return 0; 949 + } 950 + 951 + static void nfsd4_mark_cb_state(struct nfs4_client *clp, int newstate) 952 + { 953 + if (clp->cl_cb_state != newstate) { 954 + clp->cl_cb_state = newstate; 955 + trace_nfsd_cb_state(clp); 956 + } 944 957 } 945 958 946 959 static void nfsd4_mark_cb_down(struct nfs4_client *clp, int reason) 947 960 { 948 961 if (test_bit(NFSD4_CLIENT_CB_UPDATE, &clp->cl_flags)) 949 962 return; 950 - clp->cl_cb_state = NFSD4_CB_DOWN; 951 - trace_nfsd_cb_state(clp); 963 + nfsd4_mark_cb_state(clp, NFSD4_CB_DOWN); 952 964 } 953 965 954 966 static void nfsd4_mark_cb_fault(struct nfs4_client *clp, int reason) 955 967 { 956 968 if (test_bit(NFSD4_CLIENT_CB_UPDATE, &clp->cl_flags)) 957 969 return; 958 - clp->cl_cb_state = NFSD4_CB_FAULT; 959 - trace_nfsd_cb_state(clp); 970 + nfsd4_mark_cb_state(clp, NFSD4_CB_FAULT); 960 971 } 961 972 962 973 static void nfsd4_cb_probe_done(struct rpc_task *task, void *calldata) 963 974 { 964 975 struct nfs4_client *clp = container_of(calldata, struct nfs4_client, cl_cb_null); 965 976 966 - trace_nfsd_cb_done(clp, task->tk_status); 967 977 if (task->tk_status) 968 978 nfsd4_mark_cb_down(clp, task->tk_status); 969 - else { 970 - clp->cl_cb_state = NFSD4_CB_UP; 971 - trace_nfsd_cb_state(clp); 972 - } 979 + else 980 + nfsd4_mark_cb_state(clp, NFSD4_CB_UP); 973 981 } 974 982 975 983 static void nfsd4_cb_probe_release(void *calldata) ··· 999 995 */ 1000 996 void nfsd4_probe_callback(struct nfs4_client *clp) 1001 997 { 1002 - clp->cl_cb_state = NFSD4_CB_UNKNOWN; 1003 - trace_nfsd_cb_state(clp); 998 + trace_nfsd_cb_probe(clp); 999 + nfsd4_mark_cb_state(clp, NFSD4_CB_UNKNOWN); 1004 1000 set_bit(NFSD4_CLIENT_CB_UPDATE, &clp->cl_flags); 1005 1001 nfsd4_run_cb(&clp->cl_cb_null); 1006 1002 } ··· 1013 1009 1014 1010 void nfsd4_change_callback(struct nfs4_client *clp, struct nfs4_cb_conn *conn) 1015 1011 { 1016 - clp->cl_cb_state = NFSD4_CB_UNKNOWN; 1012 + nfsd4_mark_cb_state(clp, NFSD4_CB_UNKNOWN); 1017 1013 spin_lock(&clp->cl_lock); 1018 1014 memcpy(&clp->cl_cb_conn, conn, sizeof(struct nfs4_cb_conn)); 1019 1015 spin_unlock(&clp->cl_lock); 1020 - trace_nfsd_cb_state(clp); 1021 1016 } 1022 1017 1023 1018 /* ··· 1173 1170 struct nfsd4_callback *cb = calldata; 1174 1171 struct nfs4_client *clp = cb->cb_clp; 1175 1172 1176 - trace_nfsd_cb_done(clp, task->tk_status); 1177 - 1178 1173 if (!nfsd4_cb_sequence_done(task, cb)) 1179 1174 return; 1180 1175 ··· 1232 1231 /* must be called under the state lock */ 1233 1232 void nfsd4_shutdown_callback(struct nfs4_client *clp) 1234 1233 { 1234 + if (clp->cl_cb_state != NFSD4_CB_UNKNOWN) 1235 + trace_nfsd_cb_shutdown(clp); 1236 + 1235 1237 set_bit(NFSD4_CLIENT_CB_KILL, &clp->cl_flags); 1236 1238 /* 1237 1239 * Note this won't actually result in a null callback; ··· 1280 1276 * kill the old client: 1281 1277 */ 1282 1278 if (clp->cl_cb_client) { 1283 - trace_nfsd_cb_shutdown(clp); 1284 1279 rpc_shutdown_client(clp->cl_cb_client); 1285 1280 clp->cl_cb_client = NULL; 1286 1281 put_cred(clp->cl_cb_cred); ··· 1325 1322 struct rpc_clnt *clnt; 1326 1323 int flags; 1327 1324 1328 - trace_nfsd_cb_work(clp, cb->cb_msg.rpc_proc->p_name); 1329 - 1330 1325 if (cb->cb_need_restart) { 1331 1326 cb->cb_need_restart = false; 1332 1327 } else { ··· 1346 1345 * Don't send probe messages for 4.1 or later. 1347 1346 */ 1348 1347 if (!cb->cb_ops && clp->cl_minorversion) { 1349 - clp->cl_cb_state = NFSD4_CB_UP; 1348 + nfsd4_mark_cb_state(clp, NFSD4_CB_UP); 1350 1349 nfsd41_destroy_cb(cb); 1351 1350 return; 1352 1351 }
+148 -6
fs/nfsd/nfs4proc.c
··· 55 55 MODULE_PARM_DESC(inter_copy_offload_enable, 56 56 "Enable inter server to server copy offload. Default: false"); 57 57 58 + #ifdef CONFIG_NFSD_V4_2_INTER_SSC 59 + static int nfsd4_ssc_umount_timeout = 900000; /* default to 15 mins */ 60 + module_param(nfsd4_ssc_umount_timeout, int, 0644); 61 + MODULE_PARM_DESC(nfsd4_ssc_umount_timeout, 62 + "idle msecs before unmount export from source server"); 63 + #endif 64 + 58 65 #ifdef CONFIG_NFSD_V4_SECURITY_LABEL 59 66 #include <linux/security.h> 60 67 ··· 1173 1166 #define NFSD42_INTERSSC_MOUNTOPS "vers=4.2,addr=%s,sec=sys" 1174 1167 1175 1168 /* 1169 + * setup a work entry in the ssc delayed unmount list. 1170 + */ 1171 + static __be32 nfsd4_ssc_setup_dul(struct nfsd_net *nn, char *ipaddr, 1172 + struct nfsd4_ssc_umount_item **retwork, struct vfsmount **ss_mnt) 1173 + { 1174 + struct nfsd4_ssc_umount_item *ni = 0; 1175 + struct nfsd4_ssc_umount_item *work = NULL; 1176 + struct nfsd4_ssc_umount_item *tmp; 1177 + DEFINE_WAIT(wait); 1178 + 1179 + *ss_mnt = NULL; 1180 + *retwork = NULL; 1181 + work = kzalloc(sizeof(*work), GFP_KERNEL); 1182 + try_again: 1183 + spin_lock(&nn->nfsd_ssc_lock); 1184 + list_for_each_entry_safe(ni, tmp, &nn->nfsd_ssc_mount_list, nsui_list) { 1185 + if (strncmp(ni->nsui_ipaddr, ipaddr, sizeof(ni->nsui_ipaddr))) 1186 + continue; 1187 + /* found a match */ 1188 + if (ni->nsui_busy) { 1189 + /* wait - and try again */ 1190 + prepare_to_wait(&nn->nfsd_ssc_waitq, &wait, 1191 + TASK_INTERRUPTIBLE); 1192 + spin_unlock(&nn->nfsd_ssc_lock); 1193 + 1194 + /* allow 20secs for mount/unmount for now - revisit */ 1195 + if (signal_pending(current) || 1196 + (schedule_timeout(20*HZ) == 0)) { 1197 + kfree(work); 1198 + return nfserr_eagain; 1199 + } 1200 + finish_wait(&nn->nfsd_ssc_waitq, &wait); 1201 + goto try_again; 1202 + } 1203 + *ss_mnt = ni->nsui_vfsmount; 1204 + refcount_inc(&ni->nsui_refcnt); 1205 + spin_unlock(&nn->nfsd_ssc_lock); 1206 + kfree(work); 1207 + 1208 + /* return vfsmount in ss_mnt */ 1209 + return 0; 1210 + } 1211 + if (work) { 1212 + strncpy(work->nsui_ipaddr, ipaddr, sizeof(work->nsui_ipaddr)); 1213 + refcount_set(&work->nsui_refcnt, 2); 1214 + work->nsui_busy = true; 1215 + list_add_tail(&work->nsui_list, &nn->nfsd_ssc_mount_list); 1216 + *retwork = work; 1217 + } 1218 + spin_unlock(&nn->nfsd_ssc_lock); 1219 + return 0; 1220 + } 1221 + 1222 + static void nfsd4_ssc_update_dul_work(struct nfsd_net *nn, 1223 + struct nfsd4_ssc_umount_item *work, struct vfsmount *ss_mnt) 1224 + { 1225 + /* set nsui_vfsmount, clear busy flag and wakeup waiters */ 1226 + spin_lock(&nn->nfsd_ssc_lock); 1227 + work->nsui_vfsmount = ss_mnt; 1228 + work->nsui_busy = false; 1229 + wake_up_all(&nn->nfsd_ssc_waitq); 1230 + spin_unlock(&nn->nfsd_ssc_lock); 1231 + } 1232 + 1233 + static void nfsd4_ssc_cancel_dul_work(struct nfsd_net *nn, 1234 + struct nfsd4_ssc_umount_item *work) 1235 + { 1236 + spin_lock(&nn->nfsd_ssc_lock); 1237 + list_del(&work->nsui_list); 1238 + wake_up_all(&nn->nfsd_ssc_waitq); 1239 + spin_unlock(&nn->nfsd_ssc_lock); 1240 + kfree(work); 1241 + } 1242 + 1243 + /* 1176 1244 * Support one copy source server for now. 1177 1245 */ 1178 1246 static __be32 ··· 1263 1181 char *ipaddr, *dev_name, *raw_data; 1264 1182 int len, raw_len; 1265 1183 __be32 status = nfserr_inval; 1184 + struct nfsd4_ssc_umount_item *work = NULL; 1185 + struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id); 1266 1186 1267 1187 naddr = &nss->u.nl4_addr; 1268 1188 tmp_addrlen = rpc_uaddr2sockaddr(SVC_NET(rqstp), naddr->addr, ··· 1313 1229 goto out_free_rawdata; 1314 1230 snprintf(dev_name, len + 5, "%s%s%s:/", startsep, ipaddr, endsep); 1315 1231 1232 + status = nfsd4_ssc_setup_dul(nn, ipaddr, &work, &ss_mnt); 1233 + if (status) 1234 + goto out_free_devname; 1235 + if (ss_mnt) 1236 + goto out_done; 1237 + 1316 1238 /* Use an 'internal' mount: SB_KERNMOUNT -> MNT_INTERNAL */ 1317 1239 ss_mnt = vfs_kern_mount(type, SB_KERNMOUNT, dev_name, raw_data); 1318 1240 module_put(type->owner); 1319 - if (IS_ERR(ss_mnt)) 1241 + if (IS_ERR(ss_mnt)) { 1242 + status = nfserr_nodev; 1243 + if (work) 1244 + nfsd4_ssc_cancel_dul_work(nn, work); 1320 1245 goto out_free_devname; 1321 - 1246 + } 1247 + if (work) 1248 + nfsd4_ssc_update_dul_work(nn, work, ss_mnt); 1249 + out_done: 1322 1250 status = 0; 1323 1251 *mount = ss_mnt; 1324 1252 ··· 1397 1301 nfsd4_cleanup_inter_ssc(struct vfsmount *ss_mnt, struct nfsd_file *src, 1398 1302 struct nfsd_file *dst) 1399 1303 { 1304 + bool found = false; 1305 + long timeout; 1306 + struct nfsd4_ssc_umount_item *tmp; 1307 + struct nfsd4_ssc_umount_item *ni = NULL; 1308 + struct nfsd_net *nn = net_generic(dst->nf_net, nfsd_net_id); 1309 + 1400 1310 nfs42_ssc_close(src->nf_file); 1401 - fput(src->nf_file); 1402 1311 nfsd_file_put(dst); 1403 - mntput(ss_mnt); 1312 + fput(src->nf_file); 1313 + 1314 + if (!nn) { 1315 + mntput(ss_mnt); 1316 + return; 1317 + } 1318 + spin_lock(&nn->nfsd_ssc_lock); 1319 + timeout = msecs_to_jiffies(nfsd4_ssc_umount_timeout); 1320 + list_for_each_entry_safe(ni, tmp, &nn->nfsd_ssc_mount_list, nsui_list) { 1321 + if (ni->nsui_vfsmount->mnt_sb == ss_mnt->mnt_sb) { 1322 + list_del(&ni->nsui_list); 1323 + /* 1324 + * vfsmount can be shared by multiple exports, 1325 + * decrement refcnt. If the count drops to 1 it 1326 + * will be unmounted when nsui_expire expires. 1327 + */ 1328 + refcount_dec(&ni->nsui_refcnt); 1329 + ni->nsui_expire = jiffies + timeout; 1330 + list_add_tail(&ni->nsui_list, &nn->nfsd_ssc_mount_list); 1331 + found = true; 1332 + break; 1333 + } 1334 + } 1335 + spin_unlock(&nn->nfsd_ssc_lock); 1336 + if (!found) { 1337 + mntput(ss_mnt); 1338 + return; 1339 + } 1404 1340 } 1405 1341 1406 1342 #else /* CONFIG_NFSD_V4_2_INTER_SSC */ ··· 1503 1375 1504 1376 static void nfsd4_init_copy_res(struct nfsd4_copy *copy, bool sync) 1505 1377 { 1506 - copy->cp_res.wr_stable_how = NFS_UNSTABLE; 1378 + copy->cp_res.wr_stable_how = 1379 + copy->committed ? NFS_FILE_SYNC : NFS_UNSTABLE; 1507 1380 copy->cp_synchronous = sync; 1508 1381 gen_boot_verifier(&copy->cp_res.wr_verifier, copy->cp_clp->net); 1509 1382 } ··· 1515 1386 u64 bytes_total = copy->cp_count; 1516 1387 u64 src_pos = copy->cp_src_pos; 1517 1388 u64 dst_pos = copy->cp_dst_pos; 1389 + __be32 status; 1518 1390 1519 1391 /* See RFC 7862 p.67: */ 1520 1392 if (bytes_total == 0) ··· 1533 1403 src_pos += bytes_copied; 1534 1404 dst_pos += bytes_copied; 1535 1405 } while (bytes_total > 0 && !copy->cp_synchronous); 1406 + /* for a non-zero asynchronous copy do a commit of data */ 1407 + if (!copy->cp_synchronous && copy->cp_res.wr_bytes_written > 0) { 1408 + down_write(&copy->nf_dst->nf_rwsem); 1409 + status = vfs_fsync_range(copy->nf_dst->nf_file, 1410 + copy->cp_dst_pos, 1411 + copy->cp_res.wr_bytes_written, 0); 1412 + up_write(&copy->nf_dst->nf_rwsem); 1413 + if (!status) 1414 + copy->committed = true; 1415 + } 1536 1416 return bytes_copied; 1537 1417 } 1538 1418 ··· 1637 1497 memcpy(&cb_copy->fh, &copy->fh, sizeof(copy->fh)); 1638 1498 nfsd4_init_cb(&cb_copy->cp_cb, cb_copy->cp_clp, 1639 1499 &nfsd4_cb_offload_ops, NFSPROC4_CLNT_CB_OFFLOAD); 1500 + trace_nfsd_cb_offload(copy->cp_clp, &copy->cp_res.cb_stateid, 1501 + &copy->fh, copy->cp_count, copy->nfserr); 1640 1502 nfsd4_run_cb(&cb_copy->cp_cb); 1641 1503 out: 1642 1504 if (!copy->cp_intra) ··· 3374 3232 { 3375 3233 struct nfsd4_compoundres *resp = rqstp->rq_resp; 3376 3234 struct nfsd4_compoundargs *argp = rqstp->rq_argp; 3377 - struct nfsd4_op *this = &argp->ops[resp->opcnt - 1]; 3235 + struct nfsd4_op *this; 3378 3236 struct nfsd4_compound_state *cstate = &resp->cstate; 3379 3237 struct nfs4_op_map *allow = &cstate->clp->cl_spo_must_allow; 3380 3238 u32 opiter;
+143 -34
fs/nfsd/nfs4state.c
··· 44 44 #include <linux/jhash.h> 45 45 #include <linux/string_helpers.h> 46 46 #include <linux/fsnotify.h> 47 + #include <linux/nfs_ssc.h> 47 48 #include "xdr4.h" 48 49 #include "xdr4cb.h" 49 50 #include "vfs.h" ··· 1746 1745 struct nfsd4_conn *c = container_of(u, struct nfsd4_conn, cn_xpt_user); 1747 1746 struct nfs4_client *clp = c->cn_session->se_client; 1748 1747 1748 + trace_nfsd_cb_lost(clp); 1749 + 1749 1750 spin_lock(&clp->cl_lock); 1750 1751 if (!list_empty(&c->cn_persession)) { 1751 1752 list_del(&c->cn_persession); ··· 2358 2355 seq_printf(m, "\""); 2359 2356 } 2360 2357 2358 + static const char *cb_state2str(int state) 2359 + { 2360 + switch (state) { 2361 + case NFSD4_CB_UP: 2362 + return "UP"; 2363 + case NFSD4_CB_UNKNOWN: 2364 + return "UNKNOWN"; 2365 + case NFSD4_CB_DOWN: 2366 + return "DOWN"; 2367 + case NFSD4_CB_FAULT: 2368 + return "FAULT"; 2369 + } 2370 + return "UNDEFINED"; 2371 + } 2372 + 2361 2373 static int client_info_show(struct seq_file *m, void *v) 2362 2374 { 2363 2375 struct inode *inode = m->private; ··· 2401 2383 seq_printf(m, "\nImplementation time: [%lld, %ld]\n", 2402 2384 clp->cl_nii_time.tv_sec, clp->cl_nii_time.tv_nsec); 2403 2385 } 2386 + seq_printf(m, "callback state: %s\n", cb_state2str(clp->cl_cb_state)); 2387 + seq_printf(m, "callback address: %pISpc\n", &clp->cl_cb_conn.cb_addr); 2404 2388 drop_client(clp); 2405 2389 2406 2390 return 0; ··· 2685 2665 struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id); 2686 2666 bool already_expired; 2687 2667 2668 + trace_nfsd_clid_admin_expired(&clp->cl_clientid); 2669 + 2688 2670 spin_lock(&clp->cl_lock); 2689 2671 clp->cl_time = 0; 2690 2672 spin_unlock(&clp->cl_lock); ··· 2838 2816 2839 2817 lockdep_assert_held(&nn->client_lock); 2840 2818 2841 - dprintk("NFSD: move_to_confirm nfs4_client %p\n", clp); 2842 2819 list_move(&clp->cl_idhash, &nn->conf_id_hashtbl[idhashval]); 2843 2820 rb_erase(&clp->cl_namenode, &nn->unconf_name_tree); 2844 2821 add_clp_to_name_tree(clp, &nn->conf_name_tree); 2845 - if (!test_and_set_bit(NFSD4_CLIENT_CONFIRMED, &clp->cl_flags) && 2846 - clp->cl_nfsd_dentry && 2847 - clp->cl_nfsd_info_dentry) 2848 - fsnotify_dentry(clp->cl_nfsd_info_dentry, FS_MODIFY); 2822 + set_bit(NFSD4_CLIENT_CONFIRMED, &clp->cl_flags); 2823 + trace_nfsd_clid_confirmed(&clp->cl_clientid); 2849 2824 renew_client_locked(clp); 2850 2825 } 2851 2826 ··· 3195 3176 } 3196 3177 /* case 6 */ 3197 3178 exid->flags |= EXCHGID4_FLAG_CONFIRMED_R; 3179 + trace_nfsd_clid_confirmed_r(conf); 3198 3180 goto out_copy; 3199 3181 } 3200 3182 if (!creds_match) { /* case 3 */ 3201 3183 if (client_has_state(conf)) { 3202 3184 status = nfserr_clid_inuse; 3185 + trace_nfsd_clid_cred_mismatch(conf, rqstp); 3203 3186 goto out; 3204 3187 } 3205 3188 goto out_new; 3206 3189 } 3207 3190 if (verfs_match) { /* case 2 */ 3208 3191 conf->cl_exchange_flags |= EXCHGID4_FLAG_CONFIRMED_R; 3192 + trace_nfsd_clid_confirmed_r(conf); 3209 3193 goto out_copy; 3210 3194 } 3211 3195 /* case 5, client reboot */ 3196 + trace_nfsd_clid_verf_mismatch(conf, rqstp, &verf); 3212 3197 conf = NULL; 3213 3198 goto out_new; 3214 3199 } ··· 3222 3199 goto out; 3223 3200 } 3224 3201 3225 - unconf = find_unconfirmed_client_by_name(&exid->clname, nn); 3202 + unconf = find_unconfirmed_client_by_name(&exid->clname, nn); 3226 3203 if (unconf) /* case 4, possible retry or client restart */ 3227 3204 unhash_client_locked(unconf); 3228 3205 3229 - /* case 1 (normal case) */ 3206 + /* case 1, new owner ID */ 3207 + trace_nfsd_clid_fresh(new); 3208 + 3230 3209 out_new: 3231 3210 if (conf) { 3232 3211 status = mark_client_expired_locked(conf); 3233 3212 if (status) 3234 3213 goto out; 3214 + trace_nfsd_clid_replaced(&conf->cl_clientid); 3235 3215 } 3236 3216 new->cl_minorversion = cstate->minorversion; 3237 3217 new->cl_spo_must_allow.u.words[0] = exid->spo_must_allow[0]; ··· 3258 3232 out_nolock: 3259 3233 if (new) 3260 3234 expire_client(new); 3261 - if (unconf) 3235 + if (unconf) { 3236 + trace_nfsd_clid_expire_unconf(&unconf->cl_clientid); 3262 3237 expire_client(unconf); 3238 + } 3263 3239 return status; 3264 3240 } 3265 3241 ··· 3453 3425 goto out_free_conn; 3454 3426 } 3455 3427 } else if (unconf) { 3428 + status = nfserr_clid_inuse; 3456 3429 if (!same_creds(&unconf->cl_cred, &rqstp->rq_cred) || 3457 3430 !rpc_cmp_addr(sa, (struct sockaddr *) &unconf->cl_addr)) { 3458 - status = nfserr_clid_inuse; 3431 + trace_nfsd_clid_cred_mismatch(unconf, rqstp); 3459 3432 goto out_free_conn; 3460 3433 } 3461 3434 status = nfserr_wrong_cred; ··· 3476 3447 old = NULL; 3477 3448 goto out_free_conn; 3478 3449 } 3450 + trace_nfsd_clid_replaced(&old->cl_clientid); 3479 3451 } 3480 3452 move_to_confirmed(unconf); 3481 3453 conf = unconf; ··· 3501 3471 /* cache solo and embedded create sessions under the client_lock */ 3502 3472 nfsd4_cache_create_session(cr_ses, cs_slot, status); 3503 3473 spin_unlock(&nn->client_lock); 3474 + if (conf == unconf) 3475 + fsnotify_dentry(conf->cl_nfsd_info_dentry, FS_MODIFY); 3504 3476 /* init connection and backchannel */ 3505 3477 nfsd4_init_conn(rqstp, conn, new); 3506 3478 nfsd4_put_session(new); ··· 3936 3904 status = nfserr_wrong_cred; 3937 3905 goto out; 3938 3906 } 3907 + trace_nfsd_clid_destroyed(&clp->cl_clientid); 3939 3908 unhash_client_locked(clp); 3940 3909 out: 3941 3910 spin_unlock(&nn->client_lock); ··· 3979 3946 goto out; 3980 3947 3981 3948 status = nfs_ok; 3949 + trace_nfsd_clid_reclaim_complete(&clp->cl_clientid); 3982 3950 nfsd4_client_record_create(clp); 3983 3951 inc_reclaim_complete(clp); 3984 3952 out: ··· 4001 3967 new = create_client(clname, rqstp, &clverifier); 4002 3968 if (new == NULL) 4003 3969 return nfserr_jukebox; 4004 - /* Cases below refer to rfc 3530 section 14.2.33: */ 4005 3970 spin_lock(&nn->client_lock); 4006 3971 conf = find_confirmed_client_by_name(&clname, nn); 4007 3972 if (conf && client_has_state(conf)) { 4008 - /* case 0: */ 4009 3973 status = nfserr_clid_inuse; 4010 3974 if (clp_used_exchangeid(conf)) 4011 3975 goto out; 4012 3976 if (!same_creds(&conf->cl_cred, &rqstp->rq_cred)) { 4013 - trace_nfsd_clid_inuse_err(conf); 3977 + trace_nfsd_clid_cred_mismatch(conf, rqstp); 4014 3978 goto out; 4015 3979 } 4016 3980 } 4017 3981 unconf = find_unconfirmed_client_by_name(&clname, nn); 4018 3982 if (unconf) 4019 3983 unhash_client_locked(unconf); 4020 - /* We need to handle only case 1: probable callback update */ 4021 - if (conf && same_verf(&conf->cl_verifier, &clverifier)) { 4022 - copy_clid(new, conf); 4023 - gen_confirm(new, nn); 4024 - } 3984 + if (conf) { 3985 + if (same_verf(&conf->cl_verifier, &clverifier)) { 3986 + copy_clid(new, conf); 3987 + gen_confirm(new, nn); 3988 + } else 3989 + trace_nfsd_clid_verf_mismatch(conf, rqstp, 3990 + &clverifier); 3991 + } else 3992 + trace_nfsd_clid_fresh(new); 4025 3993 new->cl_minorversion = 0; 4026 3994 gen_callback(new, setclid, rqstp); 4027 3995 add_to_unconfirmed(new); ··· 4036 4000 spin_unlock(&nn->client_lock); 4037 4001 if (new) 4038 4002 free_client(new); 4039 - if (unconf) 4003 + if (unconf) { 4004 + trace_nfsd_clid_expire_unconf(&unconf->cl_clientid); 4040 4005 expire_client(unconf); 4006 + } 4041 4007 return status; 4042 4008 } 4043 - 4044 4009 4045 4010 __be32 4046 4011 nfsd4_setclientid_confirm(struct svc_rqst *rqstp, ··· 4071 4034 * Nevertheless, RFC 7530 recommends INUSE for this case: 4072 4035 */ 4073 4036 status = nfserr_clid_inuse; 4074 - if (unconf && !same_creds(&unconf->cl_cred, &rqstp->rq_cred)) 4037 + if (unconf && !same_creds(&unconf->cl_cred, &rqstp->rq_cred)) { 4038 + trace_nfsd_clid_cred_mismatch(unconf, rqstp); 4075 4039 goto out; 4076 - if (conf && !same_creds(&conf->cl_cred, &rqstp->rq_cred)) 4040 + } 4041 + if (conf && !same_creds(&conf->cl_cred, &rqstp->rq_cred)) { 4042 + trace_nfsd_clid_cred_mismatch(conf, rqstp); 4077 4043 goto out; 4078 - /* cases below refer to rfc 3530 section 14.2.34: */ 4044 + } 4079 4045 if (!unconf || !same_verf(&confirm, &unconf->cl_confirm)) { 4080 4046 if (conf && same_verf(&confirm, &conf->cl_confirm)) { 4081 - /* case 2: probable retransmit */ 4082 4047 status = nfs_ok; 4083 - } else /* case 4: client hasn't noticed we rebooted yet? */ 4048 + } else 4084 4049 status = nfserr_stale_clientid; 4085 4050 goto out; 4086 4051 } 4087 4052 status = nfs_ok; 4088 - if (conf) { /* case 1: callback update */ 4053 + if (conf) { 4089 4054 old = unconf; 4090 4055 unhash_client_locked(old); 4091 4056 nfsd4_change_callback(conf, &unconf->cl_cb_conn); 4092 - } else { /* case 3: normal case; new or rebooted client */ 4057 + } else { 4093 4058 old = find_confirmed_client_by_name(&unconf->cl_name, nn); 4094 4059 if (old) { 4095 4060 status = nfserr_clid_inuse; ··· 4104 4065 old = NULL; 4105 4066 goto out; 4106 4067 } 4068 + trace_nfsd_clid_replaced(&old->cl_clientid); 4107 4069 } 4108 4070 move_to_confirmed(unconf); 4109 4071 conf = unconf; 4110 4072 } 4111 4073 get_client_locked(conf); 4112 4074 spin_unlock(&nn->client_lock); 4075 + if (conf == unconf) 4076 + fsnotify_dentry(conf->cl_nfsd_info_dentry, FS_MODIFY); 4113 4077 nfsd4_probe_callback(conf); 4114 4078 spin_lock(&nn->client_lock); 4115 4079 put_client_renew_locked(conf); ··· 4660 4618 struct nfs4_delegation *dp = (struct nfs4_delegation *)fl->fl_owner; 4661 4619 struct nfs4_file *fp = dp->dl_stid.sc_file; 4662 4620 4663 - trace_nfsd_deleg_break(&dp->dl_stid.sc_stateid); 4621 + trace_nfsd_cb_recall(&dp->dl_stid); 4664 4622 4665 4623 /* 4666 4624 * We don't want the locks code to timeout the lease for us; ··· 5499 5457 return false; 5500 5458 } 5501 5459 5460 + #ifdef CONFIG_NFSD_V4_2_INTER_SSC 5461 + void nfsd4_ssc_init_umount_work(struct nfsd_net *nn) 5462 + { 5463 + spin_lock_init(&nn->nfsd_ssc_lock); 5464 + INIT_LIST_HEAD(&nn->nfsd_ssc_mount_list); 5465 + init_waitqueue_head(&nn->nfsd_ssc_waitq); 5466 + } 5467 + EXPORT_SYMBOL_GPL(nfsd4_ssc_init_umount_work); 5468 + 5469 + /* 5470 + * This is called when nfsd is being shutdown, after all inter_ssc 5471 + * cleanup were done, to destroy the ssc delayed unmount list. 5472 + */ 5473 + static void nfsd4_ssc_shutdown_umount(struct nfsd_net *nn) 5474 + { 5475 + struct nfsd4_ssc_umount_item *ni = NULL; 5476 + struct nfsd4_ssc_umount_item *tmp; 5477 + 5478 + spin_lock(&nn->nfsd_ssc_lock); 5479 + list_for_each_entry_safe(ni, tmp, &nn->nfsd_ssc_mount_list, nsui_list) { 5480 + list_del(&ni->nsui_list); 5481 + spin_unlock(&nn->nfsd_ssc_lock); 5482 + mntput(ni->nsui_vfsmount); 5483 + kfree(ni); 5484 + spin_lock(&nn->nfsd_ssc_lock); 5485 + } 5486 + spin_unlock(&nn->nfsd_ssc_lock); 5487 + } 5488 + 5489 + static void nfsd4_ssc_expire_umount(struct nfsd_net *nn) 5490 + { 5491 + bool do_wakeup = false; 5492 + struct nfsd4_ssc_umount_item *ni = 0; 5493 + struct nfsd4_ssc_umount_item *tmp; 5494 + 5495 + spin_lock(&nn->nfsd_ssc_lock); 5496 + list_for_each_entry_safe(ni, tmp, &nn->nfsd_ssc_mount_list, nsui_list) { 5497 + if (time_after(jiffies, ni->nsui_expire)) { 5498 + if (refcount_read(&ni->nsui_refcnt) > 1) 5499 + continue; 5500 + 5501 + /* mark being unmount */ 5502 + ni->nsui_busy = true; 5503 + spin_unlock(&nn->nfsd_ssc_lock); 5504 + mntput(ni->nsui_vfsmount); 5505 + spin_lock(&nn->nfsd_ssc_lock); 5506 + 5507 + /* waiters need to start from begin of list */ 5508 + list_del(&ni->nsui_list); 5509 + kfree(ni); 5510 + 5511 + /* wakeup ssc_connect waiters */ 5512 + do_wakeup = true; 5513 + continue; 5514 + } 5515 + break; 5516 + } 5517 + if (do_wakeup) 5518 + wake_up_all(&nn->nfsd_ssc_waitq); 5519 + spin_unlock(&nn->nfsd_ssc_lock); 5520 + } 5521 + #endif 5522 + 5502 5523 static time64_t 5503 5524 nfs4_laundromat(struct nfsd_net *nn) 5504 5525 { ··· 5600 5495 clp = list_entry(pos, struct nfs4_client, cl_lru); 5601 5496 if (!state_expired(&lt, clp->cl_time)) 5602 5497 break; 5603 - if (mark_client_expired_locked(clp)) { 5604 - trace_nfsd_clid_expired(&clp->cl_clientid); 5498 + if (mark_client_expired_locked(clp)) 5605 5499 continue; 5606 - } 5607 5500 list_add(&clp->cl_lru, &reaplist); 5608 5501 } 5609 5502 spin_unlock(&nn->client_lock); ··· 5671 5568 list_del_init(&nbl->nbl_lru); 5672 5569 free_blocked_lock(nbl); 5673 5570 } 5571 + #ifdef CONFIG_NFSD_V4_2_INTER_SSC 5572 + /* service the server-to-server copy delayed unmount list */ 5573 + nfsd4_ssc_expire_umount(nn); 5574 + #endif 5674 5575 out: 5675 5576 return max_t(time64_t, lt.new_timeo, NFSD_LAUNDROMAT_MINTIMEOUT); 5676 5577 } ··· 6537 6430 } 6538 6431 spin_unlock(&nn->blocked_locks_lock); 6539 6432 6540 - if (queue) 6433 + if (queue) { 6434 + trace_nfsd_cb_notify_lock(lo, nbl); 6541 6435 nfsd4_run_cb(&nbl->nbl_cb); 6436 + } 6542 6437 } 6543 6438 6544 6439 static const struct lock_manager_operations nfsd_posix_mng_ops = { ··· 7338 7229 unsigned int strhashval; 7339 7230 struct nfs4_client_reclaim *crp; 7340 7231 7341 - trace_nfsd_clid_reclaim(nn, name.len, name.data); 7342 7232 crp = alloc_reclaim(); 7343 7233 if (crp) { 7344 7234 strhashval = clientstr_hashval(name); ··· 7386 7278 { 7387 7279 unsigned int strhashval; 7388 7280 struct nfs4_client_reclaim *crp = NULL; 7389 - 7390 - trace_nfsd_clid_find(nn, name.len, name.data); 7391 7281 7392 7282 strhashval = clientstr_hashval(name); 7393 7283 list_for_each_entry(crp, &nn->reclaim_str_hashtbl[strhashval], cr_strhash) { ··· 7592 7486 7593 7487 nfsd4_client_tracking_exit(net); 7594 7488 nfs4_state_destroy_net(net); 7489 + #ifdef CONFIG_NFSD_V4_2_INTER_SSC 7490 + nfsd4_ssc_shutdown_umount(nn); 7491 + #endif 7595 7492 } 7596 7493 7597 7494 void
+4
fs/nfsd/nfsd.h
··· 484 484 extern int nfsd4_is_junction(struct dentry *dentry); 485 485 extern int register_cld_notifier(void); 486 486 extern void unregister_cld_notifier(void); 487 + #ifdef CONFIG_NFSD_V4_2_INTER_SSC 488 + extern void nfsd4_ssc_init_umount_work(struct nfsd_net *nn); 489 + #endif 490 + 487 491 #else /* CONFIG_NFSD_V4 */ 488 492 static inline int nfsd4_is_junction(struct dentry *dentry) 489 493 {
+2 -5
fs/nfsd/nfsfh.h
··· 225 225 * returns a crc32 hash for the filehandle that is compatible with 226 226 * the one displayed by "wireshark". 227 227 */ 228 - 229 - static inline u32 230 - knfsd_fh_hash(struct knfsd_fh *fh) 228 + static inline u32 knfsd_fh_hash(const struct knfsd_fh *fh) 231 229 { 232 230 return ~crc32_le(0xFFFFFFFF, (unsigned char *)&fh->fh_base, fh->fh_size); 233 231 } 234 232 #else 235 - static inline u32 236 - knfsd_fh_hash(struct knfsd_fh *fh) 233 + static inline u32 knfsd_fh_hash(const struct knfsd_fh *fh) 237 234 { 238 235 return 0; 239 236 }
+3
fs/nfsd/nfssvc.c
··· 403 403 if (ret) 404 404 goto out_filecache; 405 405 406 + #ifdef CONFIG_NFSD_V4_2_INTER_SSC 407 + nfsd4_ssc_init_umount_work(nn); 408 + #endif 406 409 nn->nfsd_net_up = true; 407 410 return 0; 408 411
+193 -63
fs/nfsd/trace.h
··· 408 408 __entry->ino = ino; 409 409 __entry->len = namlen; 410 410 memcpy(__get_str(name), name, namlen); 411 - __assign_str(name, name); 412 411 ), 413 412 TP_printk("fh_hash=0x%08x ino=%llu name=%.*s", 414 413 __entry->fh_hash, __entry->ino, ··· 458 459 459 460 DEFINE_STATEID_EVENT(open); 460 461 DEFINE_STATEID_EVENT(deleg_read); 461 - DEFINE_STATEID_EVENT(deleg_break); 462 462 DEFINE_STATEID_EVENT(deleg_recall); 463 463 464 464 DECLARE_EVENT_CLASS(nfsd_stateseqid_class, ··· 509 511 TP_PROTO(const clientid_t *clid), \ 510 512 TP_ARGS(clid)) 511 513 512 - DEFINE_CLIENTID_EVENT(expired); 514 + DEFINE_CLIENTID_EVENT(expire_unconf); 515 + DEFINE_CLIENTID_EVENT(reclaim_complete); 516 + DEFINE_CLIENTID_EVENT(confirmed); 517 + DEFINE_CLIENTID_EVENT(destroyed); 518 + DEFINE_CLIENTID_EVENT(admin_expired); 519 + DEFINE_CLIENTID_EVENT(replaced); 513 520 DEFINE_CLIENTID_EVENT(purged); 514 521 DEFINE_CLIENTID_EVENT(renew); 515 522 DEFINE_CLIENTID_EVENT(stale); ··· 539 536 DEFINE_NET_EVENT(grace_start); 540 537 DEFINE_NET_EVENT(grace_complete); 541 538 542 - DECLARE_EVENT_CLASS(nfsd_clid_class, 543 - TP_PROTO(const struct nfsd_net *nn, 544 - unsigned int namelen, 545 - const unsigned char *namedata), 546 - TP_ARGS(nn, namelen, namedata), 539 + TRACE_EVENT(nfsd_clid_cred_mismatch, 540 + TP_PROTO( 541 + const struct nfs4_client *clp, 542 + const struct svc_rqst *rqstp 543 + ), 544 + TP_ARGS(clp, rqstp), 547 545 TP_STRUCT__entry( 548 - __field(unsigned long long, boot_time) 549 - __field(unsigned int, namelen) 550 - __dynamic_array(unsigned char, name, namelen) 546 + __field(u32, cl_boot) 547 + __field(u32, cl_id) 548 + __field(unsigned long, cl_flavor) 549 + __field(unsigned long, new_flavor) 550 + __array(unsigned char, addr, sizeof(struct sockaddr_in6)) 551 551 ), 552 552 TP_fast_assign( 553 - __entry->boot_time = nn->boot_time; 554 - __entry->namelen = namelen; 555 - memcpy(__get_dynamic_array(name), namedata, namelen); 553 + __entry->cl_boot = clp->cl_clientid.cl_boot; 554 + __entry->cl_id = clp->cl_clientid.cl_id; 555 + __entry->cl_flavor = clp->cl_cred.cr_flavor; 556 + __entry->new_flavor = rqstp->rq_cred.cr_flavor; 557 + memcpy(__entry->addr, &rqstp->rq_xprt->xpt_remote, 558 + sizeof(struct sockaddr_in6)); 556 559 ), 557 - TP_printk("boot_time=%16llx nfs4_clientid=%.*s", 558 - __entry->boot_time, __entry->namelen, __get_str(name)) 560 + TP_printk("client %08x:%08x flavor=%s, conflict=%s from addr=%pISpc", 561 + __entry->cl_boot, __entry->cl_id, 562 + show_nfsd_authflavor(__entry->cl_flavor), 563 + show_nfsd_authflavor(__entry->new_flavor), __entry->addr 564 + ) 559 565 ) 560 566 561 - #define DEFINE_CLID_EVENT(name) \ 562 - DEFINE_EVENT(nfsd_clid_class, nfsd_clid_##name, \ 563 - TP_PROTO(const struct nfsd_net *nn, \ 564 - unsigned int namelen, \ 565 - const unsigned char *namedata), \ 566 - TP_ARGS(nn, namelen, namedata)) 567 + TRACE_EVENT(nfsd_clid_verf_mismatch, 568 + TP_PROTO( 569 + const struct nfs4_client *clp, 570 + const struct svc_rqst *rqstp, 571 + const nfs4_verifier *verf 572 + ), 573 + TP_ARGS(clp, rqstp, verf), 574 + TP_STRUCT__entry( 575 + __field(u32, cl_boot) 576 + __field(u32, cl_id) 577 + __array(unsigned char, cl_verifier, NFS4_VERIFIER_SIZE) 578 + __array(unsigned char, new_verifier, NFS4_VERIFIER_SIZE) 579 + __array(unsigned char, addr, sizeof(struct sockaddr_in6)) 580 + ), 581 + TP_fast_assign( 582 + __entry->cl_boot = clp->cl_clientid.cl_boot; 583 + __entry->cl_id = clp->cl_clientid.cl_id; 584 + memcpy(__entry->cl_verifier, (void *)&clp->cl_verifier, 585 + NFS4_VERIFIER_SIZE); 586 + memcpy(__entry->new_verifier, (void *)verf, 587 + NFS4_VERIFIER_SIZE); 588 + memcpy(__entry->addr, &rqstp->rq_xprt->xpt_remote, 589 + sizeof(struct sockaddr_in6)); 590 + ), 591 + TP_printk("client %08x:%08x verf=0x%s, updated=0x%s from addr=%pISpc", 592 + __entry->cl_boot, __entry->cl_id, 593 + __print_hex_str(__entry->cl_verifier, NFS4_VERIFIER_SIZE), 594 + __print_hex_str(__entry->new_verifier, NFS4_VERIFIER_SIZE), 595 + __entry->addr 596 + ) 597 + ); 567 598 568 - DEFINE_CLID_EVENT(find); 569 - DEFINE_CLID_EVENT(reclaim); 570 - 571 - TRACE_EVENT(nfsd_clid_inuse_err, 599 + DECLARE_EVENT_CLASS(nfsd_clid_class, 572 600 TP_PROTO(const struct nfs4_client *clp), 573 601 TP_ARGS(clp), 574 602 TP_STRUCT__entry( 575 603 __field(u32, cl_boot) 576 604 __field(u32, cl_id) 577 605 __array(unsigned char, addr, sizeof(struct sockaddr_in6)) 578 - __field(unsigned int, namelen) 579 - __dynamic_array(unsigned char, name, clp->cl_name.len) 606 + __field(unsigned long, flavor) 607 + __array(unsigned char, verifier, NFS4_VERIFIER_SIZE) 608 + __dynamic_array(char, name, clp->cl_name.len + 1) 580 609 ), 581 610 TP_fast_assign( 582 611 __entry->cl_boot = clp->cl_clientid.cl_boot; 583 612 __entry->cl_id = clp->cl_clientid.cl_id; 584 613 memcpy(__entry->addr, &clp->cl_addr, 585 614 sizeof(struct sockaddr_in6)); 586 - __entry->namelen = clp->cl_name.len; 587 - memcpy(__get_dynamic_array(name), clp->cl_name.data, 588 - clp->cl_name.len); 615 + __entry->flavor = clp->cl_cred.cr_flavor; 616 + memcpy(__entry->verifier, (void *)&clp->cl_verifier, 617 + NFS4_VERIFIER_SIZE); 618 + memcpy(__get_str(name), clp->cl_name.data, clp->cl_name.len); 619 + __get_str(name)[clp->cl_name.len] = '\0'; 589 620 ), 590 - TP_printk("nfs4_clientid %.*s already in use by %pISpc, client %08x:%08x", 591 - __entry->namelen, __get_str(name), __entry->addr, 621 + TP_printk("addr=%pISpc name='%s' verifier=0x%s flavor=%s client=%08x:%08x", 622 + __entry->addr, __get_str(name), 623 + __print_hex_str(__entry->verifier, NFS4_VERIFIER_SIZE), 624 + show_nfsd_authflavor(__entry->flavor), 592 625 __entry->cl_boot, __entry->cl_id) 593 - ) 626 + ); 627 + 628 + #define DEFINE_CLID_EVENT(name) \ 629 + DEFINE_EVENT(nfsd_clid_class, nfsd_clid_##name, \ 630 + TP_PROTO(const struct nfs4_client *clp), \ 631 + TP_ARGS(clp)) 632 + 633 + DEFINE_CLID_EVENT(fresh); 634 + DEFINE_CLID_EVENT(confirmed_r); 594 635 595 636 /* 596 637 * from fs/nfsd/filecache.h ··· 856 809 memcpy(__entry->addr, &conn->cb_addr, 857 810 sizeof(struct sockaddr_in6)); 858 811 ), 859 - TP_printk("client %08x:%08x callback addr=%pISpc prog=%u ident=%u", 860 - __entry->cl_boot, __entry->cl_id, 861 - __entry->addr, __entry->prog, __entry->ident) 812 + TP_printk("addr=%pISpc client %08x:%08x prog=%u ident=%u", 813 + __entry->addr, __entry->cl_boot, __entry->cl_id, 814 + __entry->prog, __entry->ident) 862 815 ); 863 816 864 817 TRACE_EVENT(nfsd_cb_nodelegs, ··· 874 827 ), 875 828 TP_printk("client %08x:%08x", __entry->cl_boot, __entry->cl_id) 876 829 ) 877 - 878 - TRACE_DEFINE_ENUM(NFSD4_CB_UP); 879 - TRACE_DEFINE_ENUM(NFSD4_CB_UNKNOWN); 880 - TRACE_DEFINE_ENUM(NFSD4_CB_DOWN); 881 - TRACE_DEFINE_ENUM(NFSD4_CB_FAULT); 882 830 883 831 #define show_cb_state(val) \ 884 832 __print_symbolic(val, \ ··· 908 866 TP_PROTO(const struct nfs4_client *clp), \ 909 867 TP_ARGS(clp)) 910 868 911 - DEFINE_NFSD_CB_EVENT(setup); 912 869 DEFINE_NFSD_CB_EVENT(state); 870 + DEFINE_NFSD_CB_EVENT(probe); 871 + DEFINE_NFSD_CB_EVENT(lost); 913 872 DEFINE_NFSD_CB_EVENT(shutdown); 873 + 874 + TRACE_DEFINE_ENUM(RPC_AUTH_NULL); 875 + TRACE_DEFINE_ENUM(RPC_AUTH_UNIX); 876 + TRACE_DEFINE_ENUM(RPC_AUTH_GSS); 877 + TRACE_DEFINE_ENUM(RPC_AUTH_GSS_KRB5); 878 + TRACE_DEFINE_ENUM(RPC_AUTH_GSS_KRB5I); 879 + TRACE_DEFINE_ENUM(RPC_AUTH_GSS_KRB5P); 880 + 881 + #define show_nfsd_authflavor(val) \ 882 + __print_symbolic(val, \ 883 + { RPC_AUTH_NULL, "none" }, \ 884 + { RPC_AUTH_UNIX, "sys" }, \ 885 + { RPC_AUTH_GSS, "gss" }, \ 886 + { RPC_AUTH_GSS_KRB5, "krb5" }, \ 887 + { RPC_AUTH_GSS_KRB5I, "krb5i" }, \ 888 + { RPC_AUTH_GSS_KRB5P, "krb5p" }) 889 + 890 + TRACE_EVENT(nfsd_cb_setup, 891 + TP_PROTO(const struct nfs4_client *clp, 892 + const char *netid, 893 + rpc_authflavor_t authflavor 894 + ), 895 + TP_ARGS(clp, netid, authflavor), 896 + TP_STRUCT__entry( 897 + __field(u32, cl_boot) 898 + __field(u32, cl_id) 899 + __field(unsigned long, authflavor) 900 + __array(unsigned char, addr, sizeof(struct sockaddr_in6)) 901 + __array(unsigned char, netid, 8) 902 + ), 903 + TP_fast_assign( 904 + __entry->cl_boot = clp->cl_clientid.cl_boot; 905 + __entry->cl_id = clp->cl_clientid.cl_id; 906 + strlcpy(__entry->netid, netid, sizeof(__entry->netid)); 907 + __entry->authflavor = authflavor; 908 + memcpy(__entry->addr, &clp->cl_cb_conn.cb_addr, 909 + sizeof(struct sockaddr_in6)); 910 + ), 911 + TP_printk("addr=%pISpc client %08x:%08x proto=%s flavor=%s", 912 + __entry->addr, __entry->cl_boot, __entry->cl_id, 913 + __entry->netid, show_nfsd_authflavor(__entry->authflavor)) 914 + ); 914 915 915 916 TRACE_EVENT(nfsd_cb_setup_err, 916 917 TP_PROTO( ··· 978 893 __entry->addr, __entry->cl_boot, __entry->cl_id, __entry->error) 979 894 ); 980 895 981 - TRACE_EVENT(nfsd_cb_work, 896 + TRACE_EVENT(nfsd_cb_recall, 982 897 TP_PROTO( 983 - const struct nfs4_client *clp, 984 - const char *procedure 898 + const struct nfs4_stid *stid 985 899 ), 986 - TP_ARGS(clp, procedure), 900 + TP_ARGS(stid), 987 901 TP_STRUCT__entry( 988 902 __field(u32, cl_boot) 989 903 __field(u32, cl_id) 990 - __string(procedure, procedure) 904 + __field(u32, si_id) 905 + __field(u32, si_generation) 991 906 __array(unsigned char, addr, sizeof(struct sockaddr_in6)) 992 907 ), 993 908 TP_fast_assign( 994 - __entry->cl_boot = clp->cl_clientid.cl_boot; 995 - __entry->cl_id = clp->cl_clientid.cl_id; 996 - __assign_str(procedure, procedure) 997 - memcpy(__entry->addr, &clp->cl_cb_conn.cb_addr, 998 - sizeof(struct sockaddr_in6)); 909 + const stateid_t *stp = &stid->sc_stateid; 910 + const struct nfs4_client *clp = stid->sc_client; 911 + 912 + __entry->cl_boot = stp->si_opaque.so_clid.cl_boot; 913 + __entry->cl_id = stp->si_opaque.so_clid.cl_id; 914 + __entry->si_id = stp->si_opaque.so_id; 915 + __entry->si_generation = stp->si_generation; 916 + if (clp) 917 + memcpy(__entry->addr, &clp->cl_cb_conn.cb_addr, 918 + sizeof(struct sockaddr_in6)); 919 + else 920 + memset(__entry->addr, 0, sizeof(struct sockaddr_in6)); 999 921 ), 1000 - TP_printk("addr=%pISpc client %08x:%08x procedure=%s", 922 + TP_printk("addr=%pISpc client %08x:%08x stateid %08x:%08x", 1001 923 __entry->addr, __entry->cl_boot, __entry->cl_id, 1002 - __get_str(procedure)) 924 + __entry->si_id, __entry->si_generation) 1003 925 ); 1004 926 1005 - TRACE_EVENT(nfsd_cb_done, 927 + TRACE_EVENT(nfsd_cb_notify_lock, 1006 928 TP_PROTO( 1007 - const struct nfs4_client *clp, 1008 - int status 929 + const struct nfs4_lockowner *lo, 930 + const struct nfsd4_blocked_lock *nbl 1009 931 ), 1010 - TP_ARGS(clp, status), 932 + TP_ARGS(lo, nbl), 1011 933 TP_STRUCT__entry( 1012 934 __field(u32, cl_boot) 1013 935 __field(u32, cl_id) 1014 - __field(int, status) 936 + __field(u32, fh_hash) 1015 937 __array(unsigned char, addr, sizeof(struct sockaddr_in6)) 1016 938 ), 1017 939 TP_fast_assign( 940 + const struct nfs4_client *clp = lo->lo_owner.so_client; 941 + 1018 942 __entry->cl_boot = clp->cl_clientid.cl_boot; 1019 943 __entry->cl_id = clp->cl_clientid.cl_id; 1020 - __entry->status = status; 944 + __entry->fh_hash = knfsd_fh_hash(&nbl->nbl_fh); 1021 945 memcpy(__entry->addr, &clp->cl_cb_conn.cb_addr, 1022 946 sizeof(struct sockaddr_in6)); 1023 947 ), 1024 - TP_printk("addr=%pISpc client %08x:%08x status=%d", 948 + TP_printk("addr=%pISpc client %08x:%08x fh_hash=0x%08x", 1025 949 __entry->addr, __entry->cl_boot, __entry->cl_id, 1026 - __entry->status) 950 + __entry->fh_hash) 951 + ); 952 + 953 + TRACE_EVENT(nfsd_cb_offload, 954 + TP_PROTO( 955 + const struct nfs4_client *clp, 956 + const stateid_t *stp, 957 + const struct knfsd_fh *fh, 958 + u64 count, 959 + __be32 status 960 + ), 961 + TP_ARGS(clp, stp, fh, count, status), 962 + TP_STRUCT__entry( 963 + __field(u32, cl_boot) 964 + __field(u32, cl_id) 965 + __field(u32, si_id) 966 + __field(u32, si_generation) 967 + __field(u32, fh_hash) 968 + __field(int, status) 969 + __field(u64, count) 970 + __array(unsigned char, addr, sizeof(struct sockaddr_in6)) 971 + ), 972 + TP_fast_assign( 973 + __entry->cl_boot = stp->si_opaque.so_clid.cl_boot; 974 + __entry->cl_id = stp->si_opaque.so_clid.cl_id; 975 + __entry->si_id = stp->si_opaque.so_id; 976 + __entry->si_generation = stp->si_generation; 977 + __entry->fh_hash = knfsd_fh_hash(fh); 978 + __entry->status = be32_to_cpu(status); 979 + __entry->count = count; 980 + memcpy(__entry->addr, &clp->cl_cb_conn.cb_addr, 981 + sizeof(struct sockaddr_in6)); 982 + ), 983 + TP_printk("addr=%pISpc client %08x:%08x stateid %08x:%08x fh_hash=0x%08x count=%llu status=%d", 984 + __entry->addr, __entry->cl_boot, __entry->cl_id, 985 + __entry->si_id, __entry->si_generation, 986 + __entry->fh_hash, __entry->count, __entry->status) 1027 987 ); 1028 988 1029 989 #endif /* _NFSD_TRACE_H */
+23 -3
fs/nfsd/vfs.c
··· 1123 1123 } 1124 1124 1125 1125 #ifdef CONFIG_NFSD_V3 1126 + static int 1127 + nfsd_filemap_write_and_wait_range(struct nfsd_file *nf, loff_t offset, 1128 + loff_t end) 1129 + { 1130 + struct address_space *mapping = nf->nf_file->f_mapping; 1131 + int ret = filemap_fdatawrite_range(mapping, offset, end); 1132 + 1133 + if (ret) 1134 + return ret; 1135 + filemap_fdatawait_range_keep_errors(mapping, offset, end); 1136 + return 0; 1137 + } 1138 + 1126 1139 /* 1127 1140 * Commit all pending writes to stable storage. 1128 1141 * ··· 1166 1153 if (err) 1167 1154 goto out; 1168 1155 if (EX_ISSYNC(fhp->fh_export)) { 1169 - int err2; 1156 + int err2 = nfsd_filemap_write_and_wait_range(nf, offset, end); 1170 1157 1171 1158 down_write(&nf->nf_rwsem); 1172 - err2 = vfs_fsync_range(nf->nf_file, offset, end, 0); 1159 + if (!err2) 1160 + err2 = vfs_fsync_range(nf->nf_file, offset, end, 0); 1173 1161 switch (err2) { 1174 1162 case 0: 1175 1163 nfsd_copy_boot_verifier(verf, net_generic(nf->nf_net, ··· 1627 1613 1628 1614 host_err = vfs_symlink(&init_user_ns, d_inode(dentry), dnew, path); 1629 1615 err = nfserrno(host_err); 1616 + fh_unlock(fhp); 1630 1617 if (!err) 1631 1618 err = nfserrno(commit_metadata(fhp)); 1632 - fh_unlock(fhp); 1633 1619 1634 1620 fh_drop_write(fhp); 1635 1621 ··· 1694 1680 if (d_really_is_negative(dold)) 1695 1681 goto out_dput; 1696 1682 host_err = vfs_link(dold, &init_user_ns, dirp, dnew, NULL); 1683 + fh_unlock(ffhp); 1697 1684 if (!host_err) { 1698 1685 err = nfserrno(commit_metadata(ffhp)); 1699 1686 if (!err) ··· 1874 1859 { 1875 1860 struct dentry *dentry, *rdentry; 1876 1861 struct inode *dirp; 1862 + struct inode *rinode; 1877 1863 __be32 err; 1878 1864 int host_err; 1879 1865 ··· 1903 1887 host_err = -ENOENT; 1904 1888 goto out_drop_write; 1905 1889 } 1890 + rinode = d_inode(rdentry); 1891 + ihold(rinode); 1906 1892 1907 1893 if (!type) 1908 1894 type = d_inode(rdentry)->i_mode & S_IFMT; ··· 1917 1899 host_err = vfs_rmdir(&init_user_ns, dirp, rdentry); 1918 1900 } 1919 1901 1902 + fh_unlock(fhp); 1920 1903 if (!host_err) 1921 1904 host_err = commit_metadata(fhp); 1922 1905 dput(rdentry); 1906 + iput(rinode); /* truncate the inode here */ 1923 1907 1924 1908 out_drop_write: 1925 1909 fh_drop_write(fhp);
+1
fs/nfsd/xdr4.h
··· 567 567 struct vfsmount *ss_mnt; 568 568 struct nfs_fh c_fh; 569 569 nfs4_stateid stateid; 570 + bool committed; 570 571 }; 571 572 572 573 struct nfsd4_seek {
-6
include/linux/lockd/xdr.h
··· 109 109 int nlmsvc_encode_shareres(struct svc_rqst *, __be32 *); 110 110 int nlmsvc_decode_notify(struct svc_rqst *, __be32 *); 111 111 int nlmsvc_decode_reboot(struct svc_rqst *, __be32 *); 112 - /* 113 - int nlmclt_encode_testargs(struct rpc_rqst *, u32 *, struct nlm_args *); 114 - int nlmclt_encode_lockargs(struct rpc_rqst *, u32 *, struct nlm_args *); 115 - int nlmclt_encode_cancargs(struct rpc_rqst *, u32 *, struct nlm_args *); 116 - int nlmclt_encode_unlockargs(struct rpc_rqst *, u32 *, struct nlm_args *); 117 - */ 118 112 119 113 #endif /* LOCKD_XDR_H */
+1 -6
include/linux/lockd/xdr4.h
··· 37 37 int nlm4svc_encode_shareres(struct svc_rqst *, __be32 *); 38 38 int nlm4svc_decode_notify(struct svc_rqst *, __be32 *); 39 39 int nlm4svc_decode_reboot(struct svc_rqst *, __be32 *); 40 - /* 41 - int nlmclt_encode_testargs(struct rpc_rqst *, u32 *, struct nlm_args *); 42 - int nlmclt_encode_lockargs(struct rpc_rqst *, u32 *, struct nlm_args *); 43 - int nlmclt_encode_cancargs(struct rpc_rqst *, u32 *, struct nlm_args *); 44 - int nlmclt_encode_unlockargs(struct rpc_rqst *, u32 *, struct nlm_args *); 45 - */ 40 + 46 41 extern const struct rpc_version nlm_version4; 47 42 48 43 #endif /* LOCKD_XDR4_H */
+14
include/linux/nfs_ssc.h
··· 8 8 */ 9 9 10 10 #include <linux/nfs_fs.h> 11 + #include <linux/sunrpc/svc.h> 11 12 12 13 extern struct nfs_ssc_client_ops_tbl nfs_ssc_client_tbl; 13 14 ··· 53 52 if (nfs_ssc_client_tbl.ssc_nfs4_ops) 54 53 (*nfs_ssc_client_tbl.ssc_nfs4_ops->sco_close)(filep); 55 54 } 55 + 56 + struct nfsd4_ssc_umount_item { 57 + struct list_head nsui_list; 58 + bool nsui_busy; 59 + /* 60 + * nsui_refcnt inited to 2, 1 on list and 1 for consumer. Entry 61 + * is removed when refcnt drops to 1 and nsui_expire expires. 62 + */ 63 + refcount_t nsui_refcnt; 64 + unsigned long nsui_expire; 65 + struct vfsmount *nsui_vfsmount; 66 + char nsui_ipaddr[RPC_MAX_ADDRBUFLEN]; 67 + }; 56 68 #endif 57 69 58 70 /*
+1 -1
net/sunrpc/auth_gss/svcauth_gss.c
··· 1275 1275 long long ctxh; 1276 1276 struct gss_api_mech *gm = NULL; 1277 1277 time64_t expiry; 1278 - int status = -EINVAL; 1278 + int status; 1279 1279 1280 1280 memset(&rsci, 0, sizeof(rsci)); 1281 1281 /* context handle */
+3 -3
net/sunrpc/xprtrdma/svc_rdma_rw.c
··· 483 483 * @iov: kvec to write 484 484 * 485 485 * Returns: 486 - * On succes, returns zero 486 + * On success, returns zero 487 487 * %-E2BIG if the client-provided Write chunk is too small 488 488 * %-ENOMEM if a resource has been exhausted 489 489 * %-EIO if an rdma-rw error occurred ··· 504 504 * @length: number of bytes to write 505 505 * 506 506 * Returns: 507 - * On succes, returns zero 507 + * On success, returns zero 508 508 * %-E2BIG if the client-provided Write chunk is too small 509 509 * %-ENOMEM if a resource has been exhausted 510 510 * %-EIO if an rdma-rw error occurred ··· 526 526 * @data: pointer to write arguments 527 527 * 528 528 * Returns: 529 - * On succes, returns zero 529 + * On success, returns zero 530 530 * %-E2BIG if the client-provided Write chunk is too small 531 531 * %-ENOMEM if a resource has been exhausted 532 532 * %-EIO if an rdma-rw error occurred