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

Merge branch 'for-3.16' of git://linux-nfs.org/~bfields/linux

Pull nfsd updates from Bruce Fields:
"The largest piece is a long-overdue rewrite of the xdr code to remove
some annoying limitations: for example, there was no way to return
ACLs larger than 4K, and readdir results were returned only in 4k
chunks, limiting performance on large directories.

Also:
- part of Neil Brown's work to make NFS work reliably over the
loopback interface (so client and server can run on the same
machine without deadlocks). The rest of it is coming through
other trees.
- cleanup and bugfixes for some of the server RDMA code, from
Steve Wise.
- Various cleanup of NFSv4 state code in preparation for an
overhaul of the locking, from Jeff, Trond, and Benny.
- smaller bugfixes and cleanup from Christoph Hellwig and
Kinglong Mee.

Thanks to everyone!

This summer looks likely to be busier than usual for knfsd. Hopefully
we won't break it too badly; testing definitely welcomed"

* 'for-3.16' of git://linux-nfs.org/~bfields/linux: (100 commits)
nfsd4: fix FREE_STATEID lockowner leak
svcrdma: Fence LOCAL_INV work requests
svcrdma: refactor marshalling logic
nfsd: don't halt scanning the DRC LRU list when there's an RC_INPROG entry
nfs4: remove unused CHANGE_SECURITY_LABEL
nfsd4: kill READ64
nfsd4: kill READ32
nfsd4: simplify server xdr->next_page use
nfsd4: hash deleg stateid only on successful nfs4_set_delegation
nfsd4: rename recall_lock to state_lock
nfsd: remove unneeded zeroing of fields in nfsd4_proc_compound
nfsd: fix setting of NFS4_OO_CONFIRMED in nfsd4_open
nfsd4: use recall_lock for delegation hashing
nfsd: fix laundromat next-run-time calculation
nfsd: make nfsd4_encode_fattr static
SUNRPC/NFSD: Remove using of dprintk with KERN_WARNING
nfsd: remove unused function nfsd_read_file
nfsd: getattr for FATTR4_WORD0_FILES_AVAIL needs the statfs buffer
NFSD: Error out when getting more than one fsloc/secinfo/uuid
NFSD: Using type of uint32_t for ex_nflavors instead of int
...

+2298 -2032
-2
Documentation/filesystems/nfs/nfs41-server.txt
··· 176 176 ca_maxrequestsize request and a ca_maxresponsesize reply, so we may 177 177 fail to live up to the promise we made in CREATE_SESSION fore channel 178 178 negotiation. 179 - * No more than one read-like operation allowed per compound; encoding 180 - replies that cross page boundaries (except for read data) not handled. 181 179 182 180 See also http://wiki.linux-nfs.org/wiki/index.php/Server_4.0_and_4.1_issues.
+2
fs/lockd/clnt4xdr.c
··· 14 14 #include <linux/sunrpc/stats.h> 15 15 #include <linux/lockd/lockd.h> 16 16 17 + #include <uapi/linux/nfs3.h> 18 + 17 19 #define NLMDBG_FACILITY NLMDBG_XDR 18 20 19 21 #if (NLMCLNT_OHSIZE > XDR_MAX_NETOBJ)
+2
fs/lockd/clntxdr.c
··· 15 15 #include <linux/sunrpc/stats.h> 16 16 #include <linux/lockd/lockd.h> 17 17 18 + #include <uapi/linux/nfs2.h> 19 + 18 20 #define NLMDBG_FACILITY NLMDBG_XDR 19 21 20 22 #if (NLMCLNT_OHSIZE > XDR_MAX_NETOBJ)
+1 -1
fs/lockd/svc.c
··· 622 622 err_pernet: 623 623 #ifdef CONFIG_SYSCTL 624 624 unregister_sysctl_table(nlm_sysctl_table); 625 - #endif 626 625 err_sysctl: 626 + #endif 627 627 return err; 628 628 } 629 629
+1 -2
fs/lockd/svcsubs.c
··· 14 14 #include <linux/mutex.h> 15 15 #include <linux/sunrpc/svc.h> 16 16 #include <linux/sunrpc/addr.h> 17 - #include <linux/nfsd/nfsfh.h> 18 - #include <linux/nfsd/export.h> 19 17 #include <linux/lockd/lockd.h> 20 18 #include <linux/lockd/share.h> 21 19 #include <linux/module.h> 22 20 #include <linux/mount.h> 21 + #include <uapi/linux/nfs2.h> 23 22 24 23 #define NLMDBG_FACILITY NLMDBG_SVCSUBS 25 24
+2
fs/lockd/xdr.c
··· 16 16 #include <linux/sunrpc/stats.h> 17 17 #include <linux/lockd/lockd.h> 18 18 19 + #include <uapi/linux/nfs2.h> 20 + 19 21 #define NLMDBG_FACILITY NLMDBG_XDR 20 22 21 23
+1 -1
fs/nfs/nfs4proc.c
··· 2750 2750 2751 2751 #define FATTR4_WORD1_NFS40_MASK (2*FATTR4_WORD1_MOUNTED_ON_FILEID - 1UL) 2752 2752 #define FATTR4_WORD2_NFS41_MASK (2*FATTR4_WORD2_SUPPATTR_EXCLCREAT - 1UL) 2753 - #define FATTR4_WORD2_NFS42_MASK (2*FATTR4_WORD2_CHANGE_SECURITY_LABEL - 1UL) 2753 + #define FATTR4_WORD2_NFS42_MASK (2*FATTR4_WORD2_SECURITY_LABEL - 1UL) 2754 2754 2755 2755 static int _nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *fhandle) 2756 2756 {
+1 -1
fs/nfsd/acl.h
··· 49 49 50 50 struct nfs4_acl *nfs4_acl_new(int); 51 51 int nfs4_acl_get_whotype(char *, u32); 52 - __be32 nfs4_acl_write_who(int who, __be32 **p, int *len); 52 + __be32 nfs4_acl_write_who(struct xdr_stream *xdr, int who); 53 53 54 54 int nfsd4_get_nfs4_acl(struct svc_rqst *rqstp, struct dentry *dentry, 55 55 struct nfs4_acl **acl);
+1 -4
fs/nfsd/auth.c
··· 1 1 /* Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de> */ 2 2 3 3 #include <linux/sched.h> 4 - #include <linux/user_namespace.h> 5 4 #include "nfsd.h" 6 5 #include "auth.h" 7 6 ··· 24 25 struct cred *new; 25 26 int i; 26 27 int flags = nfsexp_flags(rqstp, exp); 27 - int ret; 28 28 29 29 validate_process_creds(); 30 30 ··· 84 86 return 0; 85 87 86 88 oom: 87 - ret = -ENOMEM; 88 89 abort_creds(new); 89 - return ret; 90 + return -ENOMEM; 90 91 } 91 92
+55 -33
fs/nfsd/export.c
··· 17 17 #include <linux/exportfs.h> 18 18 #include <linux/sunrpc/svc_xprt.h> 19 19 20 - #include <net/ipv6.h> 21 - 22 20 #include "nfsd.h" 23 21 #include "nfsfh.h" 24 22 #include "netns.h" 25 23 26 24 #define NFSDDBG_FACILITY NFSDDBG_EXPORT 27 - 28 - typedef struct auth_domain svc_client; 29 - typedef struct svc_export svc_export; 30 25 31 26 /* 32 27 * We have two caches. ··· 68 73 69 74 static int expkey_parse(struct cache_detail *cd, char *mesg, int mlen) 70 75 { 71 - /* client fsidtype fsid [path] */ 76 + /* client fsidtype fsid expiry [path] */ 72 77 char *buf; 73 78 int len; 74 79 struct auth_domain *dom = NULL; ··· 290 295 291 296 static void nfsd4_fslocs_free(struct nfsd4_fs_locations *fsloc) 292 297 { 298 + struct nfsd4_fs_location *locations = fsloc->locations; 293 299 int i; 294 300 301 + if (!locations) 302 + return; 303 + 295 304 for (i = 0; i < fsloc->locations_count; i++) { 296 - kfree(fsloc->locations[i].path); 297 - kfree(fsloc->locations[i].hosts); 305 + kfree(locations[i].path); 306 + kfree(locations[i].hosts); 298 307 } 299 - kfree(fsloc->locations); 308 + 309 + kfree(locations); 310 + fsloc->locations = NULL; 300 311 } 301 312 302 313 static void svc_export_put(struct kref *ref) ··· 389 388 int len; 390 389 int migrated, i, err; 391 390 391 + /* more than one fsloc */ 392 + if (fsloc->locations) 393 + return -EINVAL; 394 + 392 395 /* listsize */ 393 396 err = get_uint(mesg, &fsloc->locations_count); 394 397 if (err) ··· 442 437 443 438 static int secinfo_parse(char **mesg, char *buf, struct svc_export *exp) 444 439 { 445 - int listsize, err; 446 440 struct exp_flavor_info *f; 441 + u32 listsize; 442 + int err; 447 443 448 - err = get_int(mesg, &listsize); 444 + /* more than one secinfo */ 445 + if (exp->ex_nflavors) 446 + return -EINVAL; 447 + 448 + err = get_uint(mesg, &listsize); 449 449 if (err) 450 450 return err; 451 - if (listsize < 0 || listsize > MAX_SECINFO_LIST) 451 + if (listsize > MAX_SECINFO_LIST) 452 452 return -EINVAL; 453 453 454 454 for (f = exp->ex_flavors; f < exp->ex_flavors + listsize; f++) { ··· 483 473 static inline int 484 474 secinfo_parse(char **mesg, char *buf, struct svc_export *exp) { return 0; } 485 475 #endif 476 + 477 + static inline int 478 + uuid_parse(char **mesg, char *buf, unsigned char **puuid) 479 + { 480 + int len; 481 + 482 + /* more than one uuid */ 483 + if (*puuid) 484 + return -EINVAL; 485 + 486 + /* expect a 16 byte uuid encoded as \xXXXX... */ 487 + len = qword_get(mesg, buf, PAGE_SIZE); 488 + if (len != EX_UUID_LEN) 489 + return -EINVAL; 490 + 491 + *puuid = kmemdup(buf, EX_UUID_LEN, GFP_KERNEL); 492 + if (*puuid == NULL) 493 + return -ENOMEM; 494 + 495 + return 0; 496 + } 486 497 487 498 static int svc_export_parse(struct cache_detail *cd, char *mesg, int mlen) 488 499 { ··· 583 552 while ((len = qword_get(&mesg, buf, PAGE_SIZE)) > 0) { 584 553 if (strcmp(buf, "fsloc") == 0) 585 554 err = fsloc_parse(&mesg, buf, &exp.ex_fslocs); 586 - else if (strcmp(buf, "uuid") == 0) { 587 - /* expect a 16 byte uuid encoded as \xXXXX... */ 588 - len = qword_get(&mesg, buf, PAGE_SIZE); 589 - if (len != 16) 590 - err = -EINVAL; 591 - else { 592 - exp.ex_uuid = 593 - kmemdup(buf, 16, GFP_KERNEL); 594 - if (exp.ex_uuid == NULL) 595 - err = -ENOMEM; 596 - } 597 - } else if (strcmp(buf, "secinfo") == 0) 555 + else if (strcmp(buf, "uuid") == 0) 556 + err = uuid_parse(&mesg, buf, &exp.ex_uuid); 557 + else if (strcmp(buf, "secinfo") == 0) 598 558 err = secinfo_parse(&mesg, buf, &exp); 599 559 else 600 560 /* quietly ignore unknown words and anything ··· 671 649 if (exp->ex_uuid) { 672 650 int i; 673 651 seq_puts(m, ",uuid="); 674 - for (i=0; i<16; i++) { 652 + for (i = 0; i < EX_UUID_LEN; i++) { 675 653 if ((i&3) == 0 && i) 676 654 seq_putc(m, ':'); 677 655 seq_printf(m, "%02x", exp->ex_uuid[i]); ··· 793 771 794 772 795 773 static struct svc_expkey * 796 - exp_find_key(struct cache_detail *cd, svc_client *clp, int fsid_type, 774 + exp_find_key(struct cache_detail *cd, struct auth_domain *clp, int fsid_type, 797 775 u32 *fsidv, struct cache_req *reqp) 798 776 { 799 777 struct svc_expkey key, *ek; ··· 815 793 return ek; 816 794 } 817 795 818 - 819 - static svc_export *exp_get_by_name(struct cache_detail *cd, svc_client *clp, 820 - const struct path *path, struct cache_req *reqp) 796 + static struct svc_export * 797 + exp_get_by_name(struct cache_detail *cd, struct auth_domain *clp, 798 + const struct path *path, struct cache_req *reqp) 821 799 { 822 800 struct svc_export *exp, key; 823 801 int err; ··· 841 819 /* 842 820 * Find the export entry for a given dentry. 843 821 */ 844 - static struct svc_export *exp_parent(struct cache_detail *cd, svc_client *clp, 845 - struct path *path) 822 + static struct svc_export * 823 + exp_parent(struct cache_detail *cd, struct auth_domain *clp, struct path *path) 846 824 { 847 825 struct dentry *saved = dget(path->dentry); 848 - svc_export *exp = exp_get_by_name(cd, clp, path, NULL); 826 + struct svc_export *exp = exp_get_by_name(cd, clp, path, NULL); 849 827 850 828 while (PTR_ERR(exp) == -ENOENT && !IS_ROOT(path->dentry)) { 851 829 struct dentry *parent = dget_parent(path->dentry); ··· 866 844 * since its harder to fool a kernel module than a user space program. 867 845 */ 868 846 int 869 - exp_rootfh(struct net *net, svc_client *clp, char *name, 847 + exp_rootfh(struct net *net, struct auth_domain *clp, char *name, 870 848 struct knfsd_fh *f, int maxsize) 871 849 { 872 850 struct svc_export *exp;
+2 -13
fs/nfsd/fault_inject.c
··· 97 97 { 98 98 static u64 val; 99 99 char read_buf[25]; 100 - size_t size, ret; 100 + size_t size; 101 101 loff_t pos = *ppos; 102 102 103 103 if (!pos) 104 104 nfsd_inject_get(file_inode(file)->i_private, &val); 105 105 size = scnprintf(read_buf, sizeof(read_buf), "%llu\n", val); 106 106 107 - if (pos < 0) 108 - return -EINVAL; 109 - if (pos >= size || !len) 110 - return 0; 111 - if (len > size - pos) 112 - len = size - pos; 113 - ret = copy_to_user(buf, read_buf + pos, len); 114 - if (ret == len) 115 - return -EFAULT; 116 - len -= ret; 117 - *ppos = pos + len; 118 - return len; 107 + return simple_read_from_buffer(buf, len, ppos, read_buf, size); 119 108 } 120 109 121 110 static ssize_t fault_inject_write(struct file *file, const char __user *buf,
+2 -2
fs/nfsd/idmap.h
··· 56 56 57 57 __be32 nfsd_map_name_to_uid(struct svc_rqst *, const char *, size_t, kuid_t *); 58 58 __be32 nfsd_map_name_to_gid(struct svc_rqst *, const char *, size_t, kgid_t *); 59 - __be32 nfsd4_encode_user(struct svc_rqst *, kuid_t, __be32 **, int *); 60 - __be32 nfsd4_encode_group(struct svc_rqst *, kgid_t, __be32 **, int *); 59 + __be32 nfsd4_encode_user(struct xdr_stream *, struct svc_rqst *, kuid_t); 60 + __be32 nfsd4_encode_group(struct xdr_stream *, struct svc_rqst *, kgid_t); 61 61 62 62 #endif /* LINUX_NFSD_IDMAP_H */
+8 -4
fs/nfsd/nfs2acl.c
··· 182 182 static int nfsaclsvc_decode_getaclargs(struct svc_rqst *rqstp, __be32 *p, 183 183 struct nfsd3_getaclargs *argp) 184 184 { 185 - if (!(p = nfs2svc_decode_fh(p, &argp->fh))) 185 + p = nfs2svc_decode_fh(p, &argp->fh); 186 + if (!p) 186 187 return 0; 187 188 argp->mask = ntohl(*p); p++; 188 189 ··· 198 197 unsigned int base; 199 198 int n; 200 199 201 - if (!(p = nfs2svc_decode_fh(p, &argp->fh))) 200 + p = nfs2svc_decode_fh(p, &argp->fh); 201 + if (!p) 202 202 return 0; 203 203 argp->mask = ntohl(*p++); 204 204 if (argp->mask & ~(NFS_ACL|NFS_ACLCNT|NFS_DFACL|NFS_DFACLCNT) || ··· 220 218 static int nfsaclsvc_decode_fhandleargs(struct svc_rqst *rqstp, __be32 *p, 221 219 struct nfsd_fhandle *argp) 222 220 { 223 - if (!(p = nfs2svc_decode_fh(p, &argp->fh))) 221 + p = nfs2svc_decode_fh(p, &argp->fh); 222 + if (!p) 224 223 return 0; 225 224 return xdr_argsize_check(rqstp, p); 226 225 } ··· 229 226 static int nfsaclsvc_decode_accessargs(struct svc_rqst *rqstp, __be32 *p, 230 227 struct nfsd3_accessargs *argp) 231 228 { 232 - if (!(p = nfs2svc_decode_fh(p, &argp->fh))) 229 + p = nfs2svc_decode_fh(p, &argp->fh); 230 + if (!p) 233 231 return 0; 234 232 argp->access = ntohl(*p++); 235 233
+4 -2
fs/nfsd/nfs3acl.c
··· 128 128 static int nfs3svc_decode_getaclargs(struct svc_rqst *rqstp, __be32 *p, 129 129 struct nfsd3_getaclargs *args) 130 130 { 131 - if (!(p = nfs3svc_decode_fh(p, &args->fh))) 131 + p = nfs3svc_decode_fh(p, &args->fh); 132 + if (!p) 132 133 return 0; 133 134 args->mask = ntohl(*p); p++; 134 135 ··· 144 143 unsigned int base; 145 144 int n; 146 145 147 - if (!(p = nfs3svc_decode_fh(p, &args->fh))) 146 + p = nfs3svc_decode_fh(p, &args->fh); 147 + if (!p) 148 148 return 0; 149 149 args->mask = ntohl(*p++); 150 150 if (args->mask & ~(NFS_ACL|NFS_ACLCNT|NFS_DFACL|NFS_DFACLCNT) ||
+18 -9
fs/nfsd/nfs3xdr.c
··· 278 278 int 279 279 nfs3svc_decode_fhandle(struct svc_rqst *rqstp, __be32 *p, struct nfsd_fhandle *args) 280 280 { 281 - if (!(p = decode_fh(p, &args->fh))) 281 + p = decode_fh(p, &args->fh); 282 + if (!p) 282 283 return 0; 283 284 return xdr_argsize_check(rqstp, p); 284 285 } ··· 288 287 nfs3svc_decode_sattrargs(struct svc_rqst *rqstp, __be32 *p, 289 288 struct nfsd3_sattrargs *args) 290 289 { 291 - if (!(p = decode_fh(p, &args->fh))) 290 + p = decode_fh(p, &args->fh); 291 + if (!p) 292 292 return 0; 293 293 p = decode_sattr3(p, &args->attrs); 294 294 ··· 317 315 nfs3svc_decode_accessargs(struct svc_rqst *rqstp, __be32 *p, 318 316 struct nfsd3_accessargs *args) 319 317 { 320 - if (!(p = decode_fh(p, &args->fh))) 318 + p = decode_fh(p, &args->fh); 319 + if (!p) 321 320 return 0; 322 321 args->access = ntohl(*p++); 323 322 ··· 333 330 int v; 334 331 u32 max_blocksize = svc_max_payload(rqstp); 335 332 336 - if (!(p = decode_fh(p, &args->fh))) 333 + p = decode_fh(p, &args->fh); 334 + if (!p) 337 335 return 0; 338 336 p = xdr_decode_hyper(p, &args->offset); 339 337 ··· 364 360 unsigned int len, v, hdr, dlen; 365 361 u32 max_blocksize = svc_max_payload(rqstp); 366 362 367 - if (!(p = decode_fh(p, &args->fh))) 363 + p = decode_fh(p, &args->fh); 364 + if (!p) 368 365 return 0; 369 366 p = xdr_decode_hyper(p, &args->offset); 370 367 ··· 540 535 nfs3svc_decode_readlinkargs(struct svc_rqst *rqstp, __be32 *p, 541 536 struct nfsd3_readlinkargs *args) 542 537 { 543 - if (!(p = decode_fh(p, &args->fh))) 538 + p = decode_fh(p, &args->fh); 539 + if (!p) 544 540 return 0; 545 541 args->buffer = page_address(*(rqstp->rq_next_page++)); 546 542 ··· 564 558 nfs3svc_decode_readdirargs(struct svc_rqst *rqstp, __be32 *p, 565 559 struct nfsd3_readdirargs *args) 566 560 { 567 - if (!(p = decode_fh(p, &args->fh))) 561 + p = decode_fh(p, &args->fh); 562 + if (!p) 568 563 return 0; 569 564 p = xdr_decode_hyper(p, &args->cookie); 570 565 args->verf = p; p += 2; ··· 587 580 int len; 588 581 u32 max_blocksize = svc_max_payload(rqstp); 589 582 590 - if (!(p = decode_fh(p, &args->fh))) 583 + p = decode_fh(p, &args->fh); 584 + if (!p) 591 585 return 0; 592 586 p = xdr_decode_hyper(p, &args->cookie); 593 587 args->verf = p; p += 2; ··· 613 605 nfs3svc_decode_commitargs(struct svc_rqst *rqstp, __be32 *p, 614 606 struct nfsd3_commitargs *args) 615 607 { 616 - if (!(p = decode_fh(p, &args->fh))) 608 + p = decode_fh(p, &args->fh); 609 + if (!p) 617 610 return 0; 618 611 p = xdr_decode_hyper(p, &args->offset); 619 612 args->count = ntohl(*p++);
+5 -7
fs/nfsd/nfs4acl.c
··· 36 36 37 37 #include <linux/slab.h> 38 38 #include <linux/nfs_fs.h> 39 - #include <linux/export.h> 40 39 #include "nfsfh.h" 41 40 #include "nfsd.h" 42 41 #include "acl.h" ··· 919 920 return NFS4_ACL_WHO_NAMED; 920 921 } 921 922 922 - __be32 nfs4_acl_write_who(int who, __be32 **p, int *len) 923 + __be32 nfs4_acl_write_who(struct xdr_stream *xdr, int who) 923 924 { 925 + __be32 *p; 924 926 int i; 925 - int bytes; 926 927 927 928 for (i = 0; i < ARRAY_SIZE(s2t_map); i++) { 928 929 if (s2t_map[i].type != who) 929 930 continue; 930 - bytes = 4 + (XDR_QUADLEN(s2t_map[i].stringlen) << 2); 931 - if (bytes > *len) 931 + p = xdr_reserve_space(xdr, s2t_map[i].stringlen + 4); 932 + if (!p) 932 933 return nfserr_resource; 933 - *p = xdr_encode_opaque(*p, s2t_map[i].string, 934 + p = xdr_encode_opaque(p, s2t_map[i].string, 934 935 s2t_map[i].stringlen); 935 - *len -= bytes; 936 936 return 0; 937 937 } 938 938 WARN_ON_ONCE(1);
+22 -20
fs/nfsd/nfs4idmap.c
··· 551 551 return 0; 552 552 } 553 553 554 - static __be32 encode_ascii_id(u32 id, __be32 **p, int *buflen) 554 + static __be32 encode_ascii_id(struct xdr_stream *xdr, u32 id) 555 555 { 556 556 char buf[11]; 557 557 int len; 558 - int bytes; 558 + __be32 *p; 559 559 560 560 len = sprintf(buf, "%u", id); 561 - bytes = 4 + (XDR_QUADLEN(len) << 2); 562 - if (bytes > *buflen) 561 + p = xdr_reserve_space(xdr, len + 4); 562 + if (!p) 563 563 return nfserr_resource; 564 - *p = xdr_encode_opaque(*p, buf, len); 565 - *buflen -= bytes; 564 + p = xdr_encode_opaque(p, buf, len); 566 565 return 0; 567 566 } 568 567 569 - static __be32 idmap_id_to_name(struct svc_rqst *rqstp, int type, u32 id, __be32 **p, int *buflen) 568 + static __be32 idmap_id_to_name(struct xdr_stream *xdr, 569 + struct svc_rqst *rqstp, int type, u32 id) 570 570 { 571 571 struct ent *item, key = { 572 572 .id = id, 573 573 .type = type, 574 574 }; 575 + __be32 *p; 575 576 int ret; 576 - int bytes; 577 577 struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id); 578 578 579 579 strlcpy(key.authname, rqst_authname(rqstp), sizeof(key.authname)); 580 580 ret = idmap_lookup(rqstp, idtoname_lookup, &key, nn->idtoname_cache, &item); 581 581 if (ret == -ENOENT) 582 - return encode_ascii_id(id, p, buflen); 582 + return encode_ascii_id(xdr, id); 583 583 if (ret) 584 584 return nfserrno(ret); 585 585 ret = strlen(item->name); 586 586 WARN_ON_ONCE(ret > IDMAP_NAMESZ); 587 - bytes = 4 + (XDR_QUADLEN(ret) << 2); 588 - if (bytes > *buflen) 587 + p = xdr_reserve_space(xdr, ret + 4); 588 + if (!p) 589 589 return nfserr_resource; 590 - *p = xdr_encode_opaque(*p, item->name, ret); 591 - *buflen -= bytes; 590 + p = xdr_encode_opaque(p, item->name, ret); 592 591 cache_put(&item->h, nn->idtoname_cache); 593 592 return 0; 594 593 } ··· 621 622 return idmap_name_to_id(rqstp, type, name, namelen, id); 622 623 } 623 624 624 - static __be32 encode_name_from_id(struct svc_rqst *rqstp, int type, u32 id, __be32 **p, int *buflen) 625 + static __be32 encode_name_from_id(struct xdr_stream *xdr, 626 + struct svc_rqst *rqstp, int type, u32 id) 625 627 { 626 628 if (nfs4_disable_idmapping && rqstp->rq_cred.cr_flavor < RPC_AUTH_GSS) 627 - return encode_ascii_id(id, p, buflen); 628 - return idmap_id_to_name(rqstp, type, id, p, buflen); 629 + return encode_ascii_id(xdr, id); 630 + return idmap_id_to_name(xdr, rqstp, type, id); 629 631 } 630 632 631 633 __be32 ··· 655 655 return status; 656 656 } 657 657 658 - __be32 nfsd4_encode_user(struct svc_rqst *rqstp, kuid_t uid, __be32 **p, int *buflen) 658 + __be32 nfsd4_encode_user(struct xdr_stream *xdr, struct svc_rqst *rqstp, 659 + kuid_t uid) 659 660 { 660 661 u32 id = from_kuid(&init_user_ns, uid); 661 - return encode_name_from_id(rqstp, IDMAP_TYPE_USER, id, p, buflen); 662 + return encode_name_from_id(xdr, rqstp, IDMAP_TYPE_USER, id); 662 663 } 663 664 664 - __be32 nfsd4_encode_group(struct svc_rqst *rqstp, kgid_t gid, __be32 **p, int *buflen) 665 + __be32 nfsd4_encode_group(struct xdr_stream *xdr, struct svc_rqst *rqstp, 666 + kgid_t gid) 665 667 { 666 668 u32 id = from_kgid(&init_user_ns, gid); 667 - return encode_name_from_id(rqstp, IDMAP_TYPE_GROUP, id, p, buflen); 669 + return encode_name_from_id(xdr, rqstp, IDMAP_TYPE_GROUP, id); 668 670 }
+118 -62
fs/nfsd/nfs4proc.c
··· 430 430 goto out; 431 431 break; 432 432 case NFS4_OPEN_CLAIM_PREVIOUS: 433 - open->op_openowner->oo_flags |= NFS4_OO_CONFIRMED; 434 433 status = nfs4_check_open_reclaim(&open->op_clientid, 435 434 cstate->minorversion, 436 435 nn); 437 436 if (status) 438 437 goto out; 438 + open->op_openowner->oo_flags |= NFS4_OO_CONFIRMED; 439 439 case NFS4_OPEN_CLAIM_FH: 440 440 case NFS4_OPEN_CLAIM_DELEG_CUR_FH: 441 441 status = do_open_fhandle(rqstp, cstate, open); ··· 445 445 break; 446 446 case NFS4_OPEN_CLAIM_DELEG_PREV_FH: 447 447 case NFS4_OPEN_CLAIM_DELEGATE_PREV: 448 - open->op_openowner->oo_flags |= NFS4_OO_CONFIRMED; 449 448 dprintk("NFSD: unsupported OPEN claim type %d\n", 450 449 open->op_claim_type); 451 450 status = nfserr_notsupp; ··· 785 786 if (!nfsd4_last_compound_op(rqstp)) 786 787 rqstp->rq_splice_ok = false; 787 788 788 - nfs4_lock_state(); 789 789 /* check stateid */ 790 790 if ((status = nfs4_preprocess_stateid_op(SVC_NET(rqstp), 791 791 cstate, &read->rd_stateid, ··· 792 794 dprintk("NFSD: nfsd4_read: couldn't process stateid!\n"); 793 795 goto out; 794 796 } 795 - if (read->rd_filp) 796 - get_file(read->rd_filp); 797 797 status = nfs_ok; 798 798 out: 799 - nfs4_unlock_state(); 800 799 read->rd_rqstp = rqstp; 801 800 read->rd_fhp = &cstate->current_fh; 802 801 return status; ··· 932 937 int err; 933 938 934 939 if (setattr->sa_iattr.ia_valid & ATTR_SIZE) { 935 - nfs4_lock_state(); 936 940 status = nfs4_preprocess_stateid_op(SVC_NET(rqstp), cstate, 937 941 &setattr->sa_stateid, WR_STATE, NULL); 938 - nfs4_unlock_state(); 939 942 if (status) { 940 943 dprintk("NFSD: nfsd4_setattr: couldn't process stateid!\n"); 941 944 return status; ··· 999 1006 if (write->wr_offset >= OFFSET_MAX) 1000 1007 return nfserr_inval; 1001 1008 1002 - nfs4_lock_state(); 1003 1009 status = nfs4_preprocess_stateid_op(SVC_NET(rqstp), 1004 1010 cstate, stateid, WR_STATE, &filp); 1005 1011 if (status) { 1006 - nfs4_unlock_state(); 1007 1012 dprintk("NFSD: nfsd4_write: couldn't process stateid!\n"); 1008 1013 return status; 1009 1014 } 1010 - if (filp) 1011 - get_file(filp); 1012 - nfs4_unlock_state(); 1013 1015 1014 1016 cnt = write->wr_buflen; 1015 1017 write->wr_how_written = write->wr_stable_how; ··· 1060 1072 return nfserr_jukebox; 1061 1073 1062 1074 p = buf; 1063 - status = nfsd4_encode_fattr(&cstate->current_fh, 1075 + status = nfsd4_encode_fattr_to_buf(&p, count, &cstate->current_fh, 1064 1076 cstate->current_fh.fh_export, 1065 - cstate->current_fh.fh_dentry, &p, 1066 - count, verify->ve_bmval, 1077 + cstate->current_fh.fh_dentry, 1078 + verify->ve_bmval, 1067 1079 rqstp, 0); 1068 1080 /* 1069 1081 * If nfsd4_encode_fattr() ran out of space, assume that's because ··· 1170 1182 1171 1183 static struct nfsd4_operation nfsd4_ops[]; 1172 1184 1173 - #ifdef NFSD_DEBUG 1174 1185 static const char *nfsd4_op_name(unsigned opnum); 1175 - #endif 1176 1186 1177 1187 /* 1178 1188 * Enforce NFSv4.1 COMPOUND ordering rules: ··· 1212 1226 1213 1227 bool nfsd4_cache_this_op(struct nfsd4_op *op) 1214 1228 { 1229 + if (op->opnum == OP_ILLEGAL) 1230 + return false; 1215 1231 return OPDESC(op)->op_flags & OP_CACHEME; 1216 1232 } 1217 1233 ··· 1250 1262 return !(nextd->op_flags & OP_HANDLES_WRONGSEC); 1251 1263 } 1252 1264 1265 + static void svcxdr_init_encode(struct svc_rqst *rqstp, 1266 + struct nfsd4_compoundres *resp) 1267 + { 1268 + struct xdr_stream *xdr = &resp->xdr; 1269 + struct xdr_buf *buf = &rqstp->rq_res; 1270 + struct kvec *head = buf->head; 1271 + 1272 + xdr->buf = buf; 1273 + xdr->iov = head; 1274 + xdr->p = head->iov_base + head->iov_len; 1275 + xdr->end = head->iov_base + PAGE_SIZE - rqstp->rq_auth_slack; 1276 + /* Tail and page_len should be zero at this point: */ 1277 + buf->len = buf->head[0].iov_len; 1278 + xdr->scratch.iov_len = 0; 1279 + xdr->page_ptr = buf->pages - 1; 1280 + buf->buflen = PAGE_SIZE * (1 + rqstp->rq_page_end - buf->pages) 1281 + - rqstp->rq_auth_slack; 1282 + } 1283 + 1253 1284 /* 1254 1285 * COMPOUND call. 1255 1286 */ ··· 1282 1275 struct nfsd4_compound_state *cstate = &resp->cstate; 1283 1276 struct svc_fh *current_fh = &cstate->current_fh; 1284 1277 struct svc_fh *save_fh = &cstate->save_fh; 1285 - int slack_bytes; 1286 - u32 plen = 0; 1287 1278 __be32 status; 1288 1279 1289 - resp->xbuf = &rqstp->rq_res; 1290 - resp->p = rqstp->rq_res.head[0].iov_base + 1291 - rqstp->rq_res.head[0].iov_len; 1292 - resp->tagp = resp->p; 1280 + svcxdr_init_encode(rqstp, resp); 1281 + resp->tagp = resp->xdr.p; 1293 1282 /* reserve space for: taglen, tag, and opcnt */ 1294 - resp->p += 2 + XDR_QUADLEN(args->taglen); 1295 - resp->end = rqstp->rq_res.head[0].iov_base + PAGE_SIZE; 1283 + xdr_reserve_space(&resp->xdr, 8 + args->taglen); 1296 1284 resp->taglen = args->taglen; 1297 1285 resp->tag = args->tag; 1298 - resp->opcnt = 0; 1299 1286 resp->rqstp = rqstp; 1300 1287 cstate->minorversion = args->minorversion; 1301 - cstate->replay_owner = NULL; 1302 - cstate->session = NULL; 1303 1288 fh_init(current_fh, NFS4_FHSIZE); 1304 1289 fh_init(save_fh, NFS4_FHSIZE); 1305 1290 /* ··· 1331 1332 goto encode_op; 1332 1333 } 1333 1334 1334 - /* We must be able to encode a successful response to 1335 - * this operation, with enough room left over to encode a 1336 - * failed response to the next operation. If we don't 1337 - * have enough room, fail with ERR_RESOURCE. 1338 - */ 1339 - slack_bytes = (char *)resp->end - (char *)resp->p; 1340 - if (slack_bytes < COMPOUND_SLACK_SPACE 1341 - + COMPOUND_ERR_SLACK_SPACE) { 1342 - BUG_ON(slack_bytes < COMPOUND_ERR_SLACK_SPACE); 1343 - op->status = nfserr_resource; 1344 - goto encode_op; 1345 - } 1346 - 1347 1335 opdesc = OPDESC(op); 1348 1336 1349 1337 if (!current_fh->fh_dentry) { ··· 1348 1362 1349 1363 /* If op is non-idempotent */ 1350 1364 if (opdesc->op_flags & OP_MODIFIES_SOMETHING) { 1351 - plen = opdesc->op_rsize_bop(rqstp, op); 1352 1365 /* 1353 - * If there's still another operation, make sure 1366 + * Don't execute this op if we couldn't encode a 1367 + * succesful reply: 1368 + */ 1369 + u32 plen = opdesc->op_rsize_bop(rqstp, op); 1370 + /* 1371 + * Plus if there's another operation, make sure 1354 1372 * we'll have space to at least encode an error: 1355 1373 */ 1356 1374 if (resp->opcnt < args->opcnt) ··· 1389 1399 } 1390 1400 if (op->status == nfserr_replay_me) { 1391 1401 op->replay = &cstate->replay_owner->so_replay; 1392 - nfsd4_encode_replay(resp, op); 1402 + nfsd4_encode_replay(&resp->xdr, op); 1393 1403 status = op->status = op->replay->rp_status; 1394 1404 } else { 1395 1405 nfsd4_encode_operation(resp, op); ··· 1428 1438 #define op_encode_change_info_maxsz (5) 1429 1439 #define nfs4_fattr_bitmap_maxsz (4) 1430 1440 1431 - #define op_encode_lockowner_maxsz (1 + XDR_QUADLEN(IDMAP_NAMESZ)) 1441 + /* We'll fall back on returning no lockowner if run out of space: */ 1442 + #define op_encode_lockowner_maxsz (0) 1432 1443 #define op_encode_lock_denied_maxsz (8 + op_encode_lockowner_maxsz) 1433 1444 1434 1445 #define nfs4_owner_maxsz (1 + XDR_QUADLEN(IDMAP_NAMESZ)) ··· 1459 1468 { 1460 1469 return (op_encode_hdr_size + op_encode_change_info_maxsz 1461 1470 + nfs4_fattr_bitmap_maxsz) * sizeof(__be32); 1471 + } 1472 + 1473 + /* 1474 + * Note since this is an idempotent operation we won't insist on failing 1475 + * the op prematurely if the estimate is too large. We may turn off splice 1476 + * reads unnecessarily. 1477 + */ 1478 + static inline u32 nfsd4_getattr_rsize(struct svc_rqst *rqstp, 1479 + struct nfsd4_op *op) 1480 + { 1481 + u32 *bmap = op->u.getattr.ga_bmval; 1482 + u32 bmap0 = bmap[0], bmap1 = bmap[1], bmap2 = bmap[2]; 1483 + u32 ret = 0; 1484 + 1485 + if (bmap0 & FATTR4_WORD0_ACL) 1486 + return svc_max_payload(rqstp); 1487 + if (bmap0 & FATTR4_WORD0_FS_LOCATIONS) 1488 + return svc_max_payload(rqstp); 1489 + 1490 + if (bmap1 & FATTR4_WORD1_OWNER) { 1491 + ret += IDMAP_NAMESZ + 4; 1492 + bmap1 &= ~FATTR4_WORD1_OWNER; 1493 + } 1494 + if (bmap1 & FATTR4_WORD1_OWNER_GROUP) { 1495 + ret += IDMAP_NAMESZ + 4; 1496 + bmap1 &= ~FATTR4_WORD1_OWNER_GROUP; 1497 + } 1498 + if (bmap0 & FATTR4_WORD0_FILEHANDLE) { 1499 + ret += NFS4_FHSIZE + 4; 1500 + bmap0 &= ~FATTR4_WORD0_FILEHANDLE; 1501 + } 1502 + if (bmap2 & FATTR4_WORD2_SECURITY_LABEL) { 1503 + ret += NFSD4_MAX_SEC_LABEL_LEN + 12; 1504 + bmap2 &= ~FATTR4_WORD2_SECURITY_LABEL; 1505 + } 1506 + /* 1507 + * Largest of remaining attributes are 16 bytes (e.g., 1508 + * supported_attributes) 1509 + */ 1510 + ret += 16 * (hweight32(bmap0) + hweight32(bmap1) + hweight32(bmap2)); 1511 + /* bitmask, length */ 1512 + ret += 20; 1513 + return ret; 1462 1514 } 1463 1515 1464 1516 static inline u32 nfsd4_link_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op) ··· 1534 1500 if (rlen > maxcount) 1535 1501 rlen = maxcount; 1536 1502 1537 - return (op_encode_hdr_size + 2) * sizeof(__be32) + rlen; 1503 + return (op_encode_hdr_size + 2 + XDR_QUADLEN(rlen)) * sizeof(__be32); 1538 1504 } 1539 1505 1540 1506 static inline u32 nfsd4_readdir_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op) 1541 1507 { 1508 + u32 maxcount = svc_max_payload(rqstp); 1542 1509 u32 rlen = op->u.readdir.rd_maxcount; 1543 1510 1544 - if (rlen > PAGE_SIZE) 1545 - rlen = PAGE_SIZE; 1511 + if (rlen > maxcount) 1512 + rlen = maxcount; 1546 1513 1547 - return (op_encode_hdr_size + op_encode_verifier_maxsz) 1548 - * sizeof(__be32) + rlen; 1514 + return (op_encode_hdr_size + op_encode_verifier_maxsz + 1515 + XDR_QUADLEN(rlen)) * sizeof(__be32); 1549 1516 } 1550 1517 1551 1518 static inline u32 nfsd4_remove_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op) ··· 1559 1524 { 1560 1525 return (op_encode_hdr_size + op_encode_change_info_maxsz 1561 1526 + op_encode_change_info_maxsz) * sizeof(__be32); 1527 + } 1528 + 1529 + static inline u32 nfsd4_sequence_rsize(struct svc_rqst *rqstp, 1530 + struct nfsd4_op *op) 1531 + { 1532 + return NFS4_MAX_SESSIONID_LEN + 20; 1562 1533 } 1563 1534 1564 1535 static inline u32 nfsd4_setattr_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op) ··· 1580 1539 1581 1540 static inline u32 nfsd4_write_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op) 1582 1541 { 1583 - return (op_encode_hdr_size + op_encode_verifier_maxsz) * sizeof(__be32); 1542 + return (op_encode_hdr_size + 2 + op_encode_verifier_maxsz) * sizeof(__be32); 1584 1543 } 1585 1544 1586 1545 static inline u32 nfsd4_exchange_id_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op) ··· 1648 1607 [OP_GETATTR] = { 1649 1608 .op_func = (nfsd4op_func)nfsd4_getattr, 1650 1609 .op_flags = ALLOWED_ON_ABSENT_FS, 1610 + .op_rsize_bop = nfsd4_getattr_rsize, 1651 1611 .op_name = "OP_GETATTR", 1652 1612 }, 1653 1613 [OP_GETFH] = { ··· 1718 1676 [OP_PUTFH] = { 1719 1677 .op_func = (nfsd4op_func)nfsd4_putfh, 1720 1678 .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS 1721 - | OP_IS_PUTFH_LIKE | OP_MODIFIES_SOMETHING 1722 - | OP_CLEAR_STATEID, 1679 + | OP_IS_PUTFH_LIKE | OP_CLEAR_STATEID, 1723 1680 .op_name = "OP_PUTFH", 1724 1681 .op_rsize_bop = (nfsd4op_rsize)nfsd4_only_status_rsize, 1725 1682 }, 1726 1683 [OP_PUTPUBFH] = { 1727 1684 .op_func = (nfsd4op_func)nfsd4_putrootfh, 1728 1685 .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS 1729 - | OP_IS_PUTFH_LIKE | OP_MODIFIES_SOMETHING 1730 - | OP_CLEAR_STATEID, 1686 + | OP_IS_PUTFH_LIKE | OP_CLEAR_STATEID, 1731 1687 .op_name = "OP_PUTPUBFH", 1732 1688 .op_rsize_bop = (nfsd4op_rsize)nfsd4_only_status_rsize, 1733 1689 }, 1734 1690 [OP_PUTROOTFH] = { 1735 1691 .op_func = (nfsd4op_func)nfsd4_putrootfh, 1736 1692 .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS 1737 - | OP_IS_PUTFH_LIKE | OP_MODIFIES_SOMETHING 1738 - | OP_CLEAR_STATEID, 1693 + | OP_IS_PUTFH_LIKE | OP_CLEAR_STATEID, 1739 1694 .op_name = "OP_PUTROOTFH", 1740 1695 .op_rsize_bop = (nfsd4op_rsize)nfsd4_only_status_rsize, 1741 1696 }, 1742 1697 [OP_READ] = { 1743 1698 .op_func = (nfsd4op_func)nfsd4_read, 1744 - .op_flags = OP_MODIFIES_SOMETHING, 1745 1699 .op_name = "OP_READ", 1746 1700 .op_rsize_bop = (nfsd4op_rsize)nfsd4_read_rsize, 1747 1701 .op_get_currentstateid = (stateid_getter)nfsd4_get_readstateid, 1748 1702 }, 1749 1703 [OP_READDIR] = { 1750 1704 .op_func = (nfsd4op_func)nfsd4_readdir, 1751 - .op_flags = OP_MODIFIES_SOMETHING, 1752 1705 .op_name = "OP_READDIR", 1753 1706 .op_rsize_bop = (nfsd4op_rsize)nfsd4_readdir_rsize, 1754 1707 }, ··· 1901 1864 }, 1902 1865 }; 1903 1866 1904 - #ifdef NFSD_DEBUG 1867 + int nfsd4_max_reply(struct svc_rqst *rqstp, struct nfsd4_op *op) 1868 + { 1869 + struct nfsd4_operation *opdesc; 1870 + nfsd4op_rsize estimator; 1871 + 1872 + if (op->opnum == OP_ILLEGAL) 1873 + return op_encode_hdr_size * sizeof(__be32); 1874 + opdesc = OPDESC(op); 1875 + estimator = opdesc->op_rsize_bop; 1876 + return estimator ? estimator(rqstp, op) : PAGE_SIZE; 1877 + } 1878 + 1879 + void warn_on_nonidempotent_op(struct nfsd4_op *op) 1880 + { 1881 + if (OPDESC(op)->op_flags & OP_MODIFIES_SOMETHING) { 1882 + pr_err("unable to encode reply to nonidempotent op %d (%s)\n", 1883 + op->opnum, nfsd4_op_name(op->opnum)); 1884 + WARN_ON_ONCE(1); 1885 + } 1886 + } 1887 + 1905 1888 static const char *nfsd4_op_name(unsigned opnum) 1906 1889 { 1907 1890 if (opnum < ARRAY_SIZE(nfsd4_ops)) 1908 1891 return nfsd4_ops[opnum].op_name; 1909 1892 return "unknown_operation"; 1910 1893 } 1911 - #endif 1912 1894 1913 1895 #define nfsd4_voidres nfsd4_voidargs 1914 1896 struct nfsd4_voidargs { int dummy; };
+142 -131
fs/nfsd/nfs4state.c
··· 81 81 * effort to decrease the scope of the client_mutex, this spinlock may 82 82 * eventually cover more: 83 83 */ 84 - static DEFINE_SPINLOCK(recall_lock); 84 + static DEFINE_SPINLOCK(state_lock); 85 85 86 - static struct kmem_cache *openowner_slab = NULL; 87 - static struct kmem_cache *lockowner_slab = NULL; 88 - static struct kmem_cache *file_slab = NULL; 89 - static struct kmem_cache *stateid_slab = NULL; 90 - static struct kmem_cache *deleg_slab = NULL; 86 + static struct kmem_cache *openowner_slab; 87 + static struct kmem_cache *lockowner_slab; 88 + static struct kmem_cache *file_slab; 89 + static struct kmem_cache *stateid_slab; 90 + static struct kmem_cache *deleg_slab; 91 91 92 92 void 93 93 nfs4_lock_state(void) ··· 235 235 static inline void 236 236 put_nfs4_file(struct nfs4_file *fi) 237 237 { 238 - if (atomic_dec_and_lock(&fi->fi_ref, &recall_lock)) { 238 + if (atomic_dec_and_lock(&fi->fi_ref, &state_lock)) { 239 239 hlist_del(&fi->fi_hash); 240 - spin_unlock(&recall_lock); 240 + spin_unlock(&state_lock); 241 241 iput(fi->fi_inode); 242 242 nfsd4_free_file(fi); 243 243 } ··· 375 375 dp = delegstateid(nfs4_alloc_stid(clp, deleg_slab)); 376 376 if (dp == NULL) 377 377 return dp; 378 - dp->dl_stid.sc_type = NFS4_DELEG_STID; 379 378 /* 380 379 * delegation seqid's are never incremented. The 4.1 special 381 380 * meaning of seqid 0 isn't meaningful, really, but let's avoid ··· 417 418 418 419 static void nfs4_put_deleg_lease(struct nfs4_file *fp) 419 420 { 421 + if (!fp->fi_lease) 422 + return; 420 423 if (atomic_dec_and_test(&fp->fi_delegees)) { 421 424 vfs_setlease(fp->fi_deleg_file, F_UNLCK, &fp->fi_lease); 422 425 fp->fi_lease = NULL; ··· 432 431 s->sc_type = 0; 433 432 } 434 433 434 + static void 435 + hash_delegation_locked(struct nfs4_delegation *dp, struct nfs4_file *fp) 436 + { 437 + lockdep_assert_held(&state_lock); 438 + 439 + dp->dl_stid.sc_type = NFS4_DELEG_STID; 440 + list_add(&dp->dl_perfile, &fp->fi_delegations); 441 + list_add(&dp->dl_perclnt, &dp->dl_stid.sc_client->cl_delegations); 442 + } 443 + 435 444 /* Called under the state lock. */ 436 445 static void 437 446 unhash_delegation(struct nfs4_delegation *dp) 438 447 { 448 + spin_lock(&state_lock); 439 449 list_del_init(&dp->dl_perclnt); 440 - spin_lock(&recall_lock); 441 450 list_del_init(&dp->dl_perfile); 442 451 list_del_init(&dp->dl_recall_lru); 443 - spin_unlock(&recall_lock); 444 - nfs4_put_deleg_lease(dp->dl_file); 445 - put_nfs4_file(dp->dl_file); 446 - dp->dl_file = NULL; 452 + spin_unlock(&state_lock); 453 + if (dp->dl_file) { 454 + nfs4_put_deleg_lease(dp->dl_file); 455 + put_nfs4_file(dp->dl_file); 456 + dp->dl_file = NULL; 457 + } 447 458 } 448 459 449 460 ··· 658 645 } 659 646 } 660 647 648 + static void nfs4_free_lockowner(struct nfs4_lockowner *lo) 649 + { 650 + kfree(lo->lo_owner.so_owner.data); 651 + kmem_cache_free(lockowner_slab, lo); 652 + } 653 + 661 654 static void release_lockowner(struct nfs4_lockowner *lo) 662 655 { 663 656 unhash_lockowner(lo); ··· 716 697 free_generic_stateid(s); 717 698 oo->oo_last_closed_stid = NULL; 718 699 } 700 + } 701 + 702 + static void nfs4_free_openowner(struct nfs4_openowner *oo) 703 + { 704 + kfree(oo->oo_owner.so_owner.data); 705 + kmem_cache_free(openowner_slab, oo); 719 706 } 720 707 721 708 static void release_openowner(struct nfs4_openowner *oo) ··· 1118 1093 return clp; 1119 1094 } 1120 1095 1121 - static inline void 1096 + static void 1122 1097 free_client(struct nfs4_client *clp) 1123 1098 { 1124 1099 struct nfsd_net __maybe_unused *nn = net_generic(clp->net, nfsd_net_id); ··· 1161 1136 struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id); 1162 1137 1163 1138 INIT_LIST_HEAD(&reaplist); 1164 - spin_lock(&recall_lock); 1139 + spin_lock(&state_lock); 1165 1140 while (!list_empty(&clp->cl_delegations)) { 1166 1141 dp = list_entry(clp->cl_delegations.next, struct nfs4_delegation, dl_perclnt); 1167 1142 list_del_init(&dp->dl_perclnt); 1168 1143 list_move(&dp->dl_recall_lru, &reaplist); 1169 1144 } 1170 - spin_unlock(&recall_lock); 1145 + spin_unlock(&state_lock); 1171 1146 while (!list_empty(&reaplist)) { 1172 1147 dp = list_entry(reaplist.next, struct nfs4_delegation, dl_recall_lru); 1173 1148 destroy_delegation(dp); ··· 1569 1544 void 1570 1545 nfsd4_store_cache_entry(struct nfsd4_compoundres *resp) 1571 1546 { 1547 + struct xdr_buf *buf = resp->xdr.buf; 1572 1548 struct nfsd4_slot *slot = resp->cstate.slot; 1573 1549 unsigned int base; 1574 1550 ··· 1583 1557 slot->sl_datalen = 0; 1584 1558 return; 1585 1559 } 1586 - slot->sl_datalen = (char *)resp->p - (char *)resp->cstate.datap; 1587 - base = (char *)resp->cstate.datap - 1588 - (char *)resp->xbuf->head[0].iov_base; 1589 - if (read_bytes_from_xdr_buf(resp->xbuf, base, slot->sl_data, 1590 - slot->sl_datalen)) 1560 + base = resp->cstate.data_offset; 1561 + slot->sl_datalen = buf->len - base; 1562 + if (read_bytes_from_xdr_buf(buf, base, slot->sl_data, slot->sl_datalen)) 1591 1563 WARN("%s: sessions DRC could not cache compound\n", __func__); 1592 1564 return; 1593 1565 } ··· 1626 1602 struct nfsd4_sequence *seq) 1627 1603 { 1628 1604 struct nfsd4_slot *slot = resp->cstate.slot; 1605 + struct xdr_stream *xdr = &resp->xdr; 1606 + __be32 *p; 1629 1607 __be32 status; 1630 1608 1631 1609 dprintk("--> %s slot %p\n", __func__, slot); ··· 1636 1610 if (status) 1637 1611 return status; 1638 1612 1639 - /* The sequence operation has been encoded, cstate->datap set. */ 1640 - memcpy(resp->cstate.datap, slot->sl_data, slot->sl_datalen); 1613 + p = xdr_reserve_space(xdr, slot->sl_datalen); 1614 + if (!p) { 1615 + WARN_ON_ONCE(1); 1616 + return nfserr_serverfault; 1617 + } 1618 + xdr_encode_opaque_fixed(p, slot->sl_data, slot->sl_datalen); 1619 + xdr_commit_encode(xdr); 1641 1620 1642 1621 resp->opcnt = slot->sl_opcnt; 1643 - resp->p = resp->cstate.datap + XDR_QUADLEN(slot->sl_datalen); 1644 - status = slot->sl_status; 1645 - 1646 - return status; 1622 + return slot->sl_status; 1647 1623 } 1648 1624 1649 1625 /* ··· 2217 2189 struct nfsd4_sequence *seq) 2218 2190 { 2219 2191 struct nfsd4_compoundres *resp = rqstp->rq_resp; 2192 + struct xdr_stream *xdr = &resp->xdr; 2220 2193 struct nfsd4_session *session; 2221 2194 struct nfs4_client *clp; 2222 2195 struct nfsd4_slot *slot; 2223 2196 struct nfsd4_conn *conn; 2224 2197 __be32 status; 2198 + int buflen; 2225 2199 struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id); 2226 2200 2227 2201 if (resp->opcnt != 1) ··· 2292 2262 if (status) 2293 2263 goto out_put_session; 2294 2264 2265 + buflen = (seq->cachethis) ? 2266 + session->se_fchannel.maxresp_cached : 2267 + session->se_fchannel.maxresp_sz; 2268 + status = (seq->cachethis) ? nfserr_rep_too_big_to_cache : 2269 + nfserr_rep_too_big; 2270 + if (xdr_restrict_buflen(xdr, buflen - rqstp->rq_auth_slack)) 2271 + goto out_put_session; 2272 + svc_reserve(rqstp, buflen); 2273 + 2274 + status = nfs_ok; 2295 2275 /* Success! bump slot seqid */ 2296 2276 slot->sl_seqid = seq->seqid; 2297 2277 slot->sl_flags |= NFSD4_SLOT_INUSE; ··· 2539 2499 fp->fi_lease = NULL; 2540 2500 memset(fp->fi_fds, 0, sizeof(fp->fi_fds)); 2541 2501 memset(fp->fi_access, 0, sizeof(fp->fi_access)); 2542 - spin_lock(&recall_lock); 2502 + spin_lock(&state_lock); 2543 2503 hlist_add_head(&fp->fi_hash, &file_hashtbl[hashval]); 2544 - spin_unlock(&recall_lock); 2545 - } 2546 - 2547 - static void 2548 - nfsd4_free_slab(struct kmem_cache **slab) 2549 - { 2550 - if (*slab == NULL) 2551 - return; 2552 - kmem_cache_destroy(*slab); 2553 - *slab = NULL; 2504 + spin_unlock(&state_lock); 2554 2505 } 2555 2506 2556 2507 void 2557 2508 nfsd4_free_slabs(void) 2558 2509 { 2559 - nfsd4_free_slab(&openowner_slab); 2560 - nfsd4_free_slab(&lockowner_slab); 2561 - nfsd4_free_slab(&file_slab); 2562 - nfsd4_free_slab(&stateid_slab); 2563 - nfsd4_free_slab(&deleg_slab); 2510 + kmem_cache_destroy(openowner_slab); 2511 + kmem_cache_destroy(lockowner_slab); 2512 + kmem_cache_destroy(file_slab); 2513 + kmem_cache_destroy(stateid_slab); 2514 + kmem_cache_destroy(deleg_slab); 2564 2515 } 2565 2516 2566 2517 int ··· 2560 2529 openowner_slab = kmem_cache_create("nfsd4_openowners", 2561 2530 sizeof(struct nfs4_openowner), 0, 0, NULL); 2562 2531 if (openowner_slab == NULL) 2563 - goto out_nomem; 2532 + goto out; 2564 2533 lockowner_slab = kmem_cache_create("nfsd4_lockowners", 2565 2534 sizeof(struct nfs4_lockowner), 0, 0, NULL); 2566 2535 if (lockowner_slab == NULL) 2567 - goto out_nomem; 2536 + goto out_free_openowner_slab; 2568 2537 file_slab = kmem_cache_create("nfsd4_files", 2569 2538 sizeof(struct nfs4_file), 0, 0, NULL); 2570 2539 if (file_slab == NULL) 2571 - goto out_nomem; 2540 + goto out_free_lockowner_slab; 2572 2541 stateid_slab = kmem_cache_create("nfsd4_stateids", 2573 2542 sizeof(struct nfs4_ol_stateid), 0, 0, NULL); 2574 2543 if (stateid_slab == NULL) 2575 - goto out_nomem; 2544 + goto out_free_file_slab; 2576 2545 deleg_slab = kmem_cache_create("nfsd4_delegations", 2577 2546 sizeof(struct nfs4_delegation), 0, 0, NULL); 2578 2547 if (deleg_slab == NULL) 2579 - goto out_nomem; 2548 + goto out_free_stateid_slab; 2580 2549 return 0; 2581 - out_nomem: 2582 - nfsd4_free_slabs(); 2550 + 2551 + out_free_stateid_slab: 2552 + kmem_cache_destroy(stateid_slab); 2553 + out_free_file_slab: 2554 + kmem_cache_destroy(file_slab); 2555 + out_free_lockowner_slab: 2556 + kmem_cache_destroy(lockowner_slab); 2557 + out_free_openowner_slab: 2558 + kmem_cache_destroy(openowner_slab); 2559 + out: 2583 2560 dprintk("nfsd4: out of memory while initializing nfsv4\n"); 2584 2561 return -ENOMEM; 2585 - } 2586 - 2587 - void nfs4_free_openowner(struct nfs4_openowner *oo) 2588 - { 2589 - kfree(oo->oo_owner.so_owner.data); 2590 - kmem_cache_free(openowner_slab, oo); 2591 - } 2592 - 2593 - void nfs4_free_lockowner(struct nfs4_lockowner *lo) 2594 - { 2595 - kfree(lo->lo_owner.so_owner.data); 2596 - kmem_cache_free(lockowner_slab, lo); 2597 2562 } 2598 2563 2599 2564 static void init_nfs4_replay(struct nfs4_replay *rp) ··· 2712 2685 unsigned int hashval = file_hashval(ino); 2713 2686 struct nfs4_file *fp; 2714 2687 2715 - spin_lock(&recall_lock); 2688 + spin_lock(&state_lock); 2716 2689 hlist_for_each_entry(fp, &file_hashtbl[hashval], fi_hash) { 2717 2690 if (fp->fi_inode == ino) { 2718 2691 get_nfs4_file(fp); 2719 - spin_unlock(&recall_lock); 2692 + spin_unlock(&state_lock); 2720 2693 return fp; 2721 2694 } 2722 2695 } 2723 - spin_unlock(&recall_lock); 2696 + spin_unlock(&state_lock); 2724 2697 return NULL; 2725 2698 } 2726 2699 ··· 2757 2730 struct nfs4_client *clp = dp->dl_stid.sc_client; 2758 2731 struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id); 2759 2732 2733 + lockdep_assert_held(&state_lock); 2760 2734 /* We're assuming the state code never drops its reference 2761 2735 * without first removing the lease. Since we're in this lease 2762 2736 * callback (and since the lease code is serialized by the kernel ··· 2794 2766 */ 2795 2767 fl->fl_break_time = 0; 2796 2768 2797 - spin_lock(&recall_lock); 2769 + spin_lock(&state_lock); 2798 2770 fp->fi_had_conflict = true; 2799 2771 list_for_each_entry(dp, &fp->fi_delegations, dl_perfile) 2800 2772 nfsd_break_one_deleg(dp); 2801 - spin_unlock(&recall_lock); 2773 + spin_unlock(&state_lock); 2802 2774 } 2803 2775 2804 2776 static ··· 3075 3047 status = vfs_setlease(fl->fl_file, fl->fl_type, &fl); 3076 3048 if (status) 3077 3049 goto out_free; 3078 - list_add(&dp->dl_perclnt, &dp->dl_stid.sc_client->cl_delegations); 3079 3050 fp->fi_lease = fl; 3080 3051 fp->fi_deleg_file = get_file(fl->fl_file); 3081 3052 atomic_set(&fp->fi_delegees, 1); 3082 - list_add(&dp->dl_perfile, &fp->fi_delegations); 3053 + spin_lock(&state_lock); 3054 + hash_delegation_locked(dp, fp); 3055 + spin_unlock(&state_lock); 3083 3056 return 0; 3084 3057 out_free: 3085 3058 locks_free_lock(fl); ··· 3089 3060 3090 3061 static int nfs4_set_delegation(struct nfs4_delegation *dp, struct nfs4_file *fp) 3091 3062 { 3092 - int status; 3093 - 3094 3063 if (fp->fi_had_conflict) 3095 3064 return -EAGAIN; 3096 3065 get_nfs4_file(fp); 3097 3066 dp->dl_file = fp; 3098 - if (!fp->fi_lease) { 3099 - status = nfs4_setlease(dp); 3100 - if (status) 3101 - goto out_free; 3102 - return 0; 3103 - } 3104 - spin_lock(&recall_lock); 3105 - if (fp->fi_had_conflict) { 3106 - spin_unlock(&recall_lock); 3107 - status = -EAGAIN; 3108 - goto out_free; 3109 - } 3067 + if (!fp->fi_lease) 3068 + return nfs4_setlease(dp); 3069 + spin_lock(&state_lock); 3110 3070 atomic_inc(&fp->fi_delegees); 3111 - list_add(&dp->dl_perfile, &fp->fi_delegations); 3112 - spin_unlock(&recall_lock); 3113 - list_add(&dp->dl_perclnt, &dp->dl_stid.sc_client->cl_delegations); 3071 + if (fp->fi_had_conflict) { 3072 + spin_unlock(&state_lock); 3073 + return -EAGAIN; 3074 + } 3075 + hash_delegation_locked(dp, fp); 3076 + spin_unlock(&state_lock); 3114 3077 return 0; 3115 - out_free: 3116 - put_nfs4_file(fp); 3117 - dp->dl_file = fp; 3118 - return status; 3119 3078 } 3120 3079 3121 3080 static void nfsd4_open_deleg_none_ext(struct nfsd4_open *open, int status) ··· 3190 3173 open->op_delegate_type = NFS4_OPEN_DELEGATE_READ; 3191 3174 return; 3192 3175 out_free: 3193 - remove_stid(&dp->dl_stid); 3194 - nfs4_put_delegation(dp); 3176 + destroy_delegation(dp); 3195 3177 out_no_deleg: 3196 3178 open->op_delegate_type = NFS4_OPEN_DELEGATE_NONE; 3197 3179 if (open->op_claim_type == NFS4_OPEN_CLAIM_PREVIOUS && ··· 3407 3391 struct nfs4_delegation *dp; 3408 3392 struct list_head *pos, *next, reaplist; 3409 3393 time_t cutoff = get_seconds() - nn->nfsd4_lease; 3410 - time_t t, clientid_val = nn->nfsd4_lease; 3411 - time_t u, test_val = nn->nfsd4_lease; 3394 + time_t t, new_timeo = nn->nfsd4_lease; 3412 3395 3413 3396 nfs4_lock_state(); 3414 3397 ··· 3419 3404 clp = list_entry(pos, struct nfs4_client, cl_lru); 3420 3405 if (time_after((unsigned long)clp->cl_time, (unsigned long)cutoff)) { 3421 3406 t = clp->cl_time - cutoff; 3422 - if (clientid_val > t) 3423 - clientid_val = t; 3407 + new_timeo = min(new_timeo, t); 3424 3408 break; 3425 3409 } 3426 3410 if (mark_client_expired_locked(clp)) { ··· 3436 3422 clp->cl_clientid.cl_id); 3437 3423 expire_client(clp); 3438 3424 } 3439 - spin_lock(&recall_lock); 3425 + spin_lock(&state_lock); 3440 3426 list_for_each_safe(pos, next, &nn->del_recall_lru) { 3441 3427 dp = list_entry (pos, struct nfs4_delegation, dl_recall_lru); 3442 3428 if (net_generic(dp->dl_stid.sc_client->net, nfsd_net_id) != nn) 3443 3429 continue; 3444 3430 if (time_after((unsigned long)dp->dl_time, (unsigned long)cutoff)) { 3445 - u = dp->dl_time - cutoff; 3446 - if (test_val > u) 3447 - test_val = u; 3431 + t = dp->dl_time - cutoff; 3432 + new_timeo = min(new_timeo, t); 3448 3433 break; 3449 3434 } 3450 3435 list_move(&dp->dl_recall_lru, &reaplist); 3451 3436 } 3452 - spin_unlock(&recall_lock); 3437 + spin_unlock(&state_lock); 3453 3438 list_for_each_safe(pos, next, &reaplist) { 3454 3439 dp = list_entry (pos, struct nfs4_delegation, dl_recall_lru); 3455 3440 revoke_delegation(dp); 3456 3441 } 3457 - test_val = nn->nfsd4_lease; 3458 3442 list_for_each_safe(pos, next, &nn->close_lru) { 3459 3443 oo = container_of(pos, struct nfs4_openowner, oo_close_lru); 3460 3444 if (time_after((unsigned long)oo->oo_time, (unsigned long)cutoff)) { 3461 - u = oo->oo_time - cutoff; 3462 - if (test_val > u) 3463 - test_val = u; 3445 + t = oo->oo_time - cutoff; 3446 + new_timeo = min(new_timeo, t); 3464 3447 break; 3465 3448 } 3466 3449 release_openowner(oo); 3467 3450 } 3468 - if (clientid_val < NFSD_LAUNDROMAT_MINTIMEOUT) 3469 - clientid_val = NFSD_LAUNDROMAT_MINTIMEOUT; 3451 + new_timeo = max_t(time_t, new_timeo, NFSD_LAUNDROMAT_MINTIMEOUT); 3470 3452 nfs4_unlock_state(); 3471 - return clientid_val; 3453 + return new_timeo; 3472 3454 } 3473 3455 3474 3456 static struct workqueue_struct *laundry_wq; ··· 3664 3654 struct svc_fh *current_fh = &cstate->current_fh; 3665 3655 struct inode *ino = current_fh->fh_dentry->d_inode; 3666 3656 struct nfsd_net *nn = net_generic(net, nfsd_net_id); 3657 + struct file *file = NULL; 3667 3658 __be32 status; 3668 3659 3669 3660 if (filpp) ··· 3676 3665 if (ZERO_STATEID(stateid) || ONE_STATEID(stateid)) 3677 3666 return check_special_stateids(net, current_fh, stateid, flags); 3678 3667 3668 + nfs4_lock_state(); 3669 + 3679 3670 status = nfsd4_lookup_stateid(stateid, NFS4_DELEG_STID|NFS4_OPEN_STID|NFS4_LOCK_STID, 3680 3671 &s, cstate->minorversion, nn); 3681 3672 if (status) 3682 - return status; 3673 + goto out; 3683 3674 status = check_stateid_generation(stateid, &s->sc_stateid, nfsd4_has_session(cstate)); 3684 3675 if (status) 3685 3676 goto out; ··· 3692 3679 if (status) 3693 3680 goto out; 3694 3681 if (filpp) { 3695 - *filpp = dp->dl_file->fi_deleg_file; 3696 - if (!*filpp) { 3682 + file = dp->dl_file->fi_deleg_file; 3683 + if (!file) { 3697 3684 WARN_ON_ONCE(1); 3698 3685 status = nfserr_serverfault; 3699 3686 goto out; ··· 3714 3701 goto out; 3715 3702 if (filpp) { 3716 3703 if (flags & RD_STATE) 3717 - *filpp = find_readable_file(stp->st_file); 3704 + file = find_readable_file(stp->st_file); 3718 3705 else 3719 - *filpp = find_writeable_file(stp->st_file); 3706 + file = find_writeable_file(stp->st_file); 3720 3707 } 3721 3708 break; 3722 3709 default: 3723 - return nfserr_bad_stateid; 3710 + status = nfserr_bad_stateid; 3711 + goto out; 3724 3712 } 3725 3713 status = nfs_ok; 3714 + if (file) 3715 + *filpp = get_file(file); 3726 3716 out: 3717 + nfs4_unlock_state(); 3727 3718 return status; 3728 3719 } 3729 3720 ··· 3743 3726 * correspondance, and we have to delete the lockowner when we 3744 3727 * delete the lock stateid: 3745 3728 */ 3746 - unhash_lockowner(lo); 3729 + release_lockowner(lo); 3747 3730 return nfs_ok; 3748 3731 } 3749 3732 ··· 4913 4896 struct nfs4_delegation *dp, *next; 4914 4897 u64 count = 0; 4915 4898 4899 + lockdep_assert_held(&state_lock); 4916 4900 list_for_each_entry_safe(dp, next, &clp->cl_delegations, dl_perclnt) { 4917 4901 if (victims) 4918 4902 list_move(&dp->dl_recall_lru, victims); ··· 4929 4911 LIST_HEAD(victims); 4930 4912 u64 count; 4931 4913 4932 - spin_lock(&recall_lock); 4914 + spin_lock(&state_lock); 4933 4915 count = nfsd_find_all_delegations(clp, max, &victims); 4934 - spin_unlock(&recall_lock); 4916 + spin_unlock(&state_lock); 4935 4917 4936 4918 list_for_each_entry_safe(dp, next, &victims, dl_recall_lru) 4937 4919 revoke_delegation(dp); ··· 4945 4927 LIST_HEAD(victims); 4946 4928 u64 count; 4947 4929 4948 - spin_lock(&recall_lock); 4930 + spin_lock(&state_lock); 4949 4931 count = nfsd_find_all_delegations(clp, max, &victims); 4950 4932 list_for_each_entry_safe(dp, next, &victims, dl_recall_lru) 4951 4933 nfsd_break_one_deleg(dp); 4952 - spin_unlock(&recall_lock); 4934 + spin_unlock(&state_lock); 4953 4935 4954 4936 return count; 4955 4937 } ··· 4958 4940 { 4959 4941 u64 count = 0; 4960 4942 4961 - spin_lock(&recall_lock); 4943 + spin_lock(&state_lock); 4962 4944 count = nfsd_find_all_delegations(clp, max, NULL); 4963 - spin_unlock(&recall_lock); 4945 + spin_unlock(&state_lock); 4964 4946 4965 4947 nfsd_print_count(clp, count, "delegations"); 4966 4948 return count; ··· 5000 4982 } 5001 4983 5002 4984 #endif /* CONFIG_NFSD_FAULT_INJECTION */ 5003 - 5004 - /* initialization to perform at module load time: */ 5005 - 5006 - void 5007 - nfs4_state_init(void) 5008 - { 5009 - } 5010 4985 5011 4986 /* 5012 4987 * Since the lifetime of a delegation isn't limited to that of an open, a ··· 5171 5160 5172 5161 nfs4_lock_state(); 5173 5162 INIT_LIST_HEAD(&reaplist); 5174 - spin_lock(&recall_lock); 5163 + spin_lock(&state_lock); 5175 5164 list_for_each_safe(pos, next, &nn->del_recall_lru) { 5176 5165 dp = list_entry (pos, struct nfs4_delegation, dl_recall_lru); 5177 5166 list_move(&dp->dl_recall_lru, &reaplist); 5178 5167 } 5179 - spin_unlock(&recall_lock); 5168 + spin_unlock(&state_lock); 5180 5169 list_for_each_safe(pos, next, &reaplist) { 5181 5170 dp = list_entry (pos, struct nfs4_delegation, dl_recall_lru); 5182 5171 destroy_delegation(dp);
+1111 -832
fs/nfsd/nfs4xdr.c
··· 98 98 status = nfserr_bad_xdr; \ 99 99 goto out 100 100 101 - #define READ32(x) (x) = ntohl(*p++) 102 - #define READ64(x) do { \ 103 - (x) = (u64)ntohl(*p++) << 32; \ 104 - (x) |= ntohl(*p++); \ 105 - } while (0) 106 101 #define READMEM(x,nbytes) do { \ 107 102 x = (char *)p; \ 108 103 p += XDR_QUADLEN(nbytes); \ ··· 243 248 bmval[2] = 0; 244 249 245 250 READ_BUF(4); 246 - READ32(bmlen); 251 + bmlen = be32_to_cpup(p++); 247 252 if (bmlen > 1000) 248 253 goto xdr_error; 249 254 250 255 READ_BUF(bmlen << 2); 251 256 if (bmlen > 0) 252 - READ32(bmval[0]); 257 + bmval[0] = be32_to_cpup(p++); 253 258 if (bmlen > 1) 254 - READ32(bmval[1]); 259 + bmval[1] = be32_to_cpup(p++); 255 260 if (bmlen > 2) 256 - READ32(bmval[2]); 261 + bmval[2] = be32_to_cpup(p++); 257 262 258 263 DECODE_TAIL; 259 264 } ··· 265 270 { 266 271 int expected_len, len = 0; 267 272 u32 dummy32; 273 + u64 sec; 268 274 char *buf; 269 275 270 276 DECODE_HEAD; ··· 274 278 return status; 275 279 276 280 READ_BUF(4); 277 - READ32(expected_len); 281 + expected_len = be32_to_cpup(p++); 278 282 279 283 if (bmval[0] & FATTR4_WORD0_SIZE) { 280 284 READ_BUF(8); 281 285 len += 8; 282 - READ64(iattr->ia_size); 286 + p = xdr_decode_hyper(p, &iattr->ia_size); 283 287 iattr->ia_valid |= ATTR_SIZE; 284 288 } 285 289 if (bmval[0] & FATTR4_WORD0_ACL) { ··· 287 291 struct nfs4_ace *ace; 288 292 289 293 READ_BUF(4); len += 4; 290 - READ32(nace); 294 + nace = be32_to_cpup(p++); 291 295 292 296 if (nace > NFS4_ACL_MAX) 293 297 return nfserr_fbig; ··· 301 305 (*acl)->naces = nace; 302 306 for (ace = (*acl)->aces; ace < (*acl)->aces + nace; ace++) { 303 307 READ_BUF(16); len += 16; 304 - READ32(ace->type); 305 - READ32(ace->flag); 306 - READ32(ace->access_mask); 307 - READ32(dummy32); 308 + ace->type = be32_to_cpup(p++); 309 + ace->flag = be32_to_cpup(p++); 310 + ace->access_mask = be32_to_cpup(p++); 311 + dummy32 = be32_to_cpup(p++); 308 312 READ_BUF(dummy32); 309 313 len += XDR_QUADLEN(dummy32) << 2; 310 314 READMEM(buf, dummy32); ··· 326 330 if (bmval[1] & FATTR4_WORD1_MODE) { 327 331 READ_BUF(4); 328 332 len += 4; 329 - READ32(iattr->ia_mode); 333 + iattr->ia_mode = be32_to_cpup(p++); 330 334 iattr->ia_mode &= (S_IFMT | S_IALLUGO); 331 335 iattr->ia_valid |= ATTR_MODE; 332 336 } 333 337 if (bmval[1] & FATTR4_WORD1_OWNER) { 334 338 READ_BUF(4); 335 339 len += 4; 336 - READ32(dummy32); 340 + dummy32 = be32_to_cpup(p++); 337 341 READ_BUF(dummy32); 338 342 len += (XDR_QUADLEN(dummy32) << 2); 339 343 READMEM(buf, dummy32); ··· 344 348 if (bmval[1] & FATTR4_WORD1_OWNER_GROUP) { 345 349 READ_BUF(4); 346 350 len += 4; 347 - READ32(dummy32); 351 + dummy32 = be32_to_cpup(p++); 348 352 READ_BUF(dummy32); 349 353 len += (XDR_QUADLEN(dummy32) << 2); 350 354 READMEM(buf, dummy32); ··· 355 359 if (bmval[1] & FATTR4_WORD1_TIME_ACCESS_SET) { 356 360 READ_BUF(4); 357 361 len += 4; 358 - READ32(dummy32); 362 + dummy32 = be32_to_cpup(p++); 359 363 switch (dummy32) { 360 364 case NFS4_SET_TO_CLIENT_TIME: 361 365 /* We require the high 32 bits of 'seconds' to be 0, and we ignore 362 366 all 32 bits of 'nseconds'. */ 363 367 READ_BUF(12); 364 368 len += 12; 365 - READ64(iattr->ia_atime.tv_sec); 366 - READ32(iattr->ia_atime.tv_nsec); 369 + p = xdr_decode_hyper(p, &sec); 370 + iattr->ia_atime.tv_sec = (time_t)sec; 371 + iattr->ia_atime.tv_nsec = be32_to_cpup(p++); 367 372 if (iattr->ia_atime.tv_nsec >= (u32)1000000000) 368 373 return nfserr_inval; 369 374 iattr->ia_valid |= (ATTR_ATIME | ATTR_ATIME_SET); ··· 379 382 if (bmval[1] & FATTR4_WORD1_TIME_MODIFY_SET) { 380 383 READ_BUF(4); 381 384 len += 4; 382 - READ32(dummy32); 385 + dummy32 = be32_to_cpup(p++); 383 386 switch (dummy32) { 384 387 case NFS4_SET_TO_CLIENT_TIME: 385 388 /* We require the high 32 bits of 'seconds' to be 0, and we ignore 386 389 all 32 bits of 'nseconds'. */ 387 390 READ_BUF(12); 388 391 len += 12; 389 - READ64(iattr->ia_mtime.tv_sec); 390 - READ32(iattr->ia_mtime.tv_nsec); 392 + p = xdr_decode_hyper(p, &sec); 393 + iattr->ia_mtime.tv_sec = sec; 394 + iattr->ia_mtime.tv_nsec = be32_to_cpup(p++); 391 395 if (iattr->ia_mtime.tv_nsec >= (u32)1000000000) 392 396 return nfserr_inval; 393 397 iattr->ia_valid |= (ATTR_MTIME | ATTR_MTIME_SET); ··· 406 408 if (bmval[2] & FATTR4_WORD2_SECURITY_LABEL) { 407 409 READ_BUF(4); 408 410 len += 4; 409 - READ32(dummy32); /* lfs: we don't use it */ 411 + dummy32 = be32_to_cpup(p++); /* lfs: we don't use it */ 410 412 READ_BUF(4); 411 413 len += 4; 412 - READ32(dummy32); /* pi: we don't use it either */ 414 + dummy32 = be32_to_cpup(p++); /* pi: we don't use it either */ 413 415 READ_BUF(4); 414 416 len += 4; 415 - READ32(dummy32); 417 + dummy32 = be32_to_cpup(p++); 416 418 READ_BUF(dummy32); 417 419 if (dummy32 > NFSD4_MAX_SEC_LABEL_LEN) 418 420 return nfserr_badlabel; ··· 443 445 DECODE_HEAD; 444 446 445 447 READ_BUF(sizeof(stateid_t)); 446 - READ32(sid->si_generation); 448 + sid->si_generation = be32_to_cpup(p++); 447 449 COPYMEM(&sid->si_opaque, sizeof(stateid_opaque_t)); 448 450 449 451 DECODE_TAIL; ··· 455 457 DECODE_HEAD; 456 458 457 459 READ_BUF(4); 458 - READ32(access->ac_req_access); 460 + access->ac_req_access = be32_to_cpup(p++); 459 461 460 462 DECODE_TAIL; 461 463 } ··· 470 472 471 473 /* callback_sec_params4 */ 472 474 READ_BUF(4); 473 - READ32(nr_secflavs); 475 + nr_secflavs = be32_to_cpup(p++); 474 476 if (nr_secflavs) 475 477 cbs->flavor = (u32)(-1); 476 478 else ··· 478 480 cbs->flavor = 0; 479 481 for (i = 0; i < nr_secflavs; ++i) { 480 482 READ_BUF(4); 481 - READ32(dummy); 483 + dummy = be32_to_cpup(p++); 482 484 switch (dummy) { 483 485 case RPC_AUTH_NULL: 484 486 /* Nothing to read */ ··· 488 490 case RPC_AUTH_UNIX: 489 491 READ_BUF(8); 490 492 /* stamp */ 491 - READ32(dummy); 493 + dummy = be32_to_cpup(p++); 492 494 493 495 /* machine name */ 494 - READ32(dummy); 496 + dummy = be32_to_cpup(p++); 495 497 READ_BUF(dummy); 496 498 SAVEMEM(machine_name, dummy); 497 499 498 500 /* uid, gid */ 499 501 READ_BUF(8); 500 - READ32(uid); 501 - READ32(gid); 502 + uid = be32_to_cpup(p++); 503 + gid = be32_to_cpup(p++); 502 504 503 505 /* more gids */ 504 506 READ_BUF(4); 505 - READ32(dummy); 507 + dummy = be32_to_cpup(p++); 506 508 READ_BUF(dummy * 4); 507 509 if (cbs->flavor == (u32)(-1)) { 508 510 kuid_t kuid = make_kuid(&init_user_ns, uid); ··· 522 524 "not supported!\n"); 523 525 READ_BUF(8); 524 526 /* gcbp_service */ 525 - READ32(dummy); 527 + dummy = be32_to_cpup(p++); 526 528 /* gcbp_handle_from_server */ 527 - READ32(dummy); 529 + dummy = be32_to_cpup(p++); 528 530 READ_BUF(dummy); 529 531 p += XDR_QUADLEN(dummy); 530 532 /* gcbp_handle_from_client */ 531 533 READ_BUF(4); 532 - READ32(dummy); 534 + dummy = be32_to_cpup(p++); 533 535 READ_BUF(dummy); 534 536 break; 535 537 default: ··· 545 547 DECODE_HEAD; 546 548 547 549 READ_BUF(4); 548 - READ32(bc->bc_cb_program); 550 + bc->bc_cb_program = be32_to_cpup(p++); 549 551 nfsd4_decode_cb_sec(argp, &bc->bc_cb_sec); 550 552 551 553 DECODE_TAIL; ··· 557 559 558 560 READ_BUF(NFS4_MAX_SESSIONID_LEN + 8); 559 561 COPYMEM(bcts->sessionid.data, NFS4_MAX_SESSIONID_LEN); 560 - READ32(bcts->dir); 562 + bcts->dir = be32_to_cpup(p++); 561 563 /* XXX: skipping ctsa_use_conn_in_rdma_mode. Perhaps Tom Tucker 562 564 * could help us figure out we should be using it. */ 563 565 DECODE_TAIL; ··· 569 571 DECODE_HEAD; 570 572 571 573 READ_BUF(4); 572 - READ32(close->cl_seqid); 574 + close->cl_seqid = be32_to_cpup(p++); 573 575 return nfsd4_decode_stateid(argp, &close->cl_stateid); 574 576 575 577 DECODE_TAIL; ··· 582 584 DECODE_HEAD; 583 585 584 586 READ_BUF(12); 585 - READ64(commit->co_offset); 586 - READ32(commit->co_count); 587 + p = xdr_decode_hyper(p, &commit->co_offset); 588 + commit->co_count = be32_to_cpup(p++); 587 589 588 590 DECODE_TAIL; 589 591 } ··· 594 596 DECODE_HEAD; 595 597 596 598 READ_BUF(4); 597 - READ32(create->cr_type); 599 + create->cr_type = be32_to_cpup(p++); 598 600 switch (create->cr_type) { 599 601 case NF4LNK: 600 602 READ_BUF(4); 601 - READ32(create->cr_linklen); 603 + create->cr_linklen = be32_to_cpup(p++); 602 604 READ_BUF(create->cr_linklen); 603 605 SAVEMEM(create->cr_linkname, create->cr_linklen); 604 606 break; 605 607 case NF4BLK: 606 608 case NF4CHR: 607 609 READ_BUF(8); 608 - READ32(create->cr_specdata1); 609 - READ32(create->cr_specdata2); 610 + create->cr_specdata1 = be32_to_cpup(p++); 611 + create->cr_specdata2 = be32_to_cpup(p++); 610 612 break; 611 613 case NF4SOCK: 612 614 case NF4FIFO: ··· 616 618 } 617 619 618 620 READ_BUF(4); 619 - READ32(create->cr_namelen); 621 + create->cr_namelen = be32_to_cpup(p++); 620 622 READ_BUF(create->cr_namelen); 621 623 SAVEMEM(create->cr_name, create->cr_namelen); 622 624 if ((status = check_filename(create->cr_name, create->cr_namelen))) ··· 648 650 DECODE_HEAD; 649 651 650 652 READ_BUF(4); 651 - READ32(link->li_namelen); 653 + link->li_namelen = be32_to_cpup(p++); 652 654 READ_BUF(link->li_namelen); 653 655 SAVEMEM(link->li_name, link->li_namelen); 654 656 if ((status = check_filename(link->li_name, link->li_namelen))) ··· 666 668 * type, reclaim(boolean), offset, length, new_lock_owner(boolean) 667 669 */ 668 670 READ_BUF(28); 669 - READ32(lock->lk_type); 671 + lock->lk_type = be32_to_cpup(p++); 670 672 if ((lock->lk_type < NFS4_READ_LT) || (lock->lk_type > NFS4_WRITEW_LT)) 671 673 goto xdr_error; 672 - READ32(lock->lk_reclaim); 673 - READ64(lock->lk_offset); 674 - READ64(lock->lk_length); 675 - READ32(lock->lk_is_new); 674 + lock->lk_reclaim = be32_to_cpup(p++); 675 + p = xdr_decode_hyper(p, &lock->lk_offset); 676 + p = xdr_decode_hyper(p, &lock->lk_length); 677 + lock->lk_is_new = be32_to_cpup(p++); 676 678 677 679 if (lock->lk_is_new) { 678 680 READ_BUF(4); 679 - READ32(lock->lk_new_open_seqid); 681 + lock->lk_new_open_seqid = be32_to_cpup(p++); 680 682 status = nfsd4_decode_stateid(argp, &lock->lk_new_open_stateid); 681 683 if (status) 682 684 return status; 683 685 READ_BUF(8 + sizeof(clientid_t)); 684 - READ32(lock->lk_new_lock_seqid); 686 + lock->lk_new_lock_seqid = be32_to_cpup(p++); 685 687 COPYMEM(&lock->lk_new_clientid, sizeof(clientid_t)); 686 - READ32(lock->lk_new_owner.len); 688 + lock->lk_new_owner.len = be32_to_cpup(p++); 687 689 READ_BUF(lock->lk_new_owner.len); 688 690 READMEM(lock->lk_new_owner.data, lock->lk_new_owner.len); 689 691 } else { ··· 691 693 if (status) 692 694 return status; 693 695 READ_BUF(4); 694 - READ32(lock->lk_old_lock_seqid); 696 + lock->lk_old_lock_seqid = be32_to_cpup(p++); 695 697 } 696 698 697 699 DECODE_TAIL; ··· 703 705 DECODE_HEAD; 704 706 705 707 READ_BUF(32); 706 - READ32(lockt->lt_type); 708 + lockt->lt_type = be32_to_cpup(p++); 707 709 if((lockt->lt_type < NFS4_READ_LT) || (lockt->lt_type > NFS4_WRITEW_LT)) 708 710 goto xdr_error; 709 - READ64(lockt->lt_offset); 710 - READ64(lockt->lt_length); 711 + p = xdr_decode_hyper(p, &lockt->lt_offset); 712 + p = xdr_decode_hyper(p, &lockt->lt_length); 711 713 COPYMEM(&lockt->lt_clientid, 8); 712 - READ32(lockt->lt_owner.len); 714 + lockt->lt_owner.len = be32_to_cpup(p++); 713 715 READ_BUF(lockt->lt_owner.len); 714 716 READMEM(lockt->lt_owner.data, lockt->lt_owner.len); 715 717 ··· 722 724 DECODE_HEAD; 723 725 724 726 READ_BUF(8); 725 - READ32(locku->lu_type); 727 + locku->lu_type = be32_to_cpup(p++); 726 728 if ((locku->lu_type < NFS4_READ_LT) || (locku->lu_type > NFS4_WRITEW_LT)) 727 729 goto xdr_error; 728 - READ32(locku->lu_seqid); 730 + locku->lu_seqid = be32_to_cpup(p++); 729 731 status = nfsd4_decode_stateid(argp, &locku->lu_stateid); 730 732 if (status) 731 733 return status; 732 734 READ_BUF(16); 733 - READ64(locku->lu_offset); 734 - READ64(locku->lu_length); 735 + p = xdr_decode_hyper(p, &locku->lu_offset); 736 + p = xdr_decode_hyper(p, &locku->lu_length); 735 737 736 738 DECODE_TAIL; 737 739 } ··· 742 744 DECODE_HEAD; 743 745 744 746 READ_BUF(4); 745 - READ32(lookup->lo_len); 747 + lookup->lo_len = be32_to_cpup(p++); 746 748 READ_BUF(lookup->lo_len); 747 749 SAVEMEM(lookup->lo_name, lookup->lo_len); 748 750 if ((status = check_filename(lookup->lo_name, lookup->lo_len))) ··· 757 759 u32 w; 758 760 759 761 READ_BUF(4); 760 - READ32(w); 762 + w = be32_to_cpup(p++); 761 763 *share_access = w & NFS4_SHARE_ACCESS_MASK; 762 764 *deleg_want = w & NFS4_SHARE_WANT_MASK; 763 765 if (deleg_when) ··· 809 811 __be32 *p; 810 812 811 813 READ_BUF(4); 812 - READ32(*x); 814 + *x = be32_to_cpup(p++); 813 815 /* Note: unlinke access bits, deny bits may be zero. */ 814 816 if (*x & ~NFS4_SHARE_DENY_BOTH) 815 817 return nfserr_bad_xdr; ··· 823 825 __be32 *p; 824 826 825 827 READ_BUF(4); 826 - READ32(o->len); 828 + o->len = be32_to_cpup(p++); 827 829 828 830 if (o->len == 0 || o->len > NFS4_OPAQUE_LIMIT) 829 831 return nfserr_bad_xdr; ··· 848 850 open->op_xdr_error = 0; 849 851 /* seqid, share_access, share_deny, clientid, ownerlen */ 850 852 READ_BUF(4); 851 - READ32(open->op_seqid); 853 + open->op_seqid = be32_to_cpup(p++); 852 854 /* decode, yet ignore deleg_when until supported */ 853 855 status = nfsd4_decode_share_access(argp, &open->op_share_access, 854 856 &open->op_deleg_want, &dummy); ··· 863 865 if (status) 864 866 goto xdr_error; 865 867 READ_BUF(4); 866 - READ32(open->op_create); 868 + open->op_create = be32_to_cpup(p++); 867 869 switch (open->op_create) { 868 870 case NFS4_OPEN_NOCREATE: 869 871 break; 870 872 case NFS4_OPEN_CREATE: 871 873 READ_BUF(4); 872 - READ32(open->op_createmode); 874 + open->op_createmode = be32_to_cpup(p++); 873 875 switch (open->op_createmode) { 874 876 case NFS4_CREATE_UNCHECKED: 875 877 case NFS4_CREATE_GUARDED: ··· 902 904 903 905 /* open_claim */ 904 906 READ_BUF(4); 905 - READ32(open->op_claim_type); 907 + open->op_claim_type = be32_to_cpup(p++); 906 908 switch (open->op_claim_type) { 907 909 case NFS4_OPEN_CLAIM_NULL: 908 910 case NFS4_OPEN_CLAIM_DELEGATE_PREV: 909 911 READ_BUF(4); 910 - READ32(open->op_fname.len); 912 + open->op_fname.len = be32_to_cpup(p++); 911 913 READ_BUF(open->op_fname.len); 912 914 SAVEMEM(open->op_fname.data, open->op_fname.len); 913 915 if ((status = check_filename(open->op_fname.data, open->op_fname.len))) ··· 915 917 break; 916 918 case NFS4_OPEN_CLAIM_PREVIOUS: 917 919 READ_BUF(4); 918 - READ32(open->op_delegate_type); 920 + open->op_delegate_type = be32_to_cpup(p++); 919 921 break; 920 922 case NFS4_OPEN_CLAIM_DELEGATE_CUR: 921 923 status = nfsd4_decode_stateid(argp, &open->op_delegate_stateid); 922 924 if (status) 923 925 return status; 924 926 READ_BUF(4); 925 - READ32(open->op_fname.len); 927 + open->op_fname.len = be32_to_cpup(p++); 926 928 READ_BUF(open->op_fname.len); 927 929 SAVEMEM(open->op_fname.data, open->op_fname.len); 928 930 if ((status = check_filename(open->op_fname.data, open->op_fname.len))) ··· 960 962 if (status) 961 963 return status; 962 964 READ_BUF(4); 963 - READ32(open_conf->oc_seqid); 965 + open_conf->oc_seqid = be32_to_cpup(p++); 964 966 965 967 DECODE_TAIL; 966 968 } ··· 974 976 if (status) 975 977 return status; 976 978 READ_BUF(4); 977 - READ32(open_down->od_seqid); 979 + open_down->od_seqid = be32_to_cpup(p++); 978 980 status = nfsd4_decode_share_access(argp, &open_down->od_share_access, 979 981 &open_down->od_deleg_want, NULL); 980 982 if (status) ··· 991 993 DECODE_HEAD; 992 994 993 995 READ_BUF(4); 994 - READ32(putfh->pf_fhlen); 996 + putfh->pf_fhlen = be32_to_cpup(p++); 995 997 if (putfh->pf_fhlen > NFS4_FHSIZE) 996 998 goto xdr_error; 997 999 READ_BUF(putfh->pf_fhlen); ··· 1017 1019 if (status) 1018 1020 return status; 1019 1021 READ_BUF(12); 1020 - READ64(read->rd_offset); 1021 - READ32(read->rd_length); 1022 + p = xdr_decode_hyper(p, &read->rd_offset); 1023 + read->rd_length = be32_to_cpup(p++); 1022 1024 1023 1025 DECODE_TAIL; 1024 1026 } ··· 1029 1031 DECODE_HEAD; 1030 1032 1031 1033 READ_BUF(24); 1032 - READ64(readdir->rd_cookie); 1034 + p = xdr_decode_hyper(p, &readdir->rd_cookie); 1033 1035 COPYMEM(readdir->rd_verf.data, sizeof(readdir->rd_verf.data)); 1034 - READ32(readdir->rd_dircount); /* just in case you needed a useless field... */ 1035 - READ32(readdir->rd_maxcount); 1036 + readdir->rd_dircount = be32_to_cpup(p++); 1037 + readdir->rd_maxcount = be32_to_cpup(p++); 1036 1038 if ((status = nfsd4_decode_bitmap(argp, readdir->rd_bmval))) 1037 1039 goto out; 1038 1040 ··· 1045 1047 DECODE_HEAD; 1046 1048 1047 1049 READ_BUF(4); 1048 - READ32(remove->rm_namelen); 1050 + remove->rm_namelen = be32_to_cpup(p++); 1049 1051 READ_BUF(remove->rm_namelen); 1050 1052 SAVEMEM(remove->rm_name, remove->rm_namelen); 1051 1053 if ((status = check_filename(remove->rm_name, remove->rm_namelen))) ··· 1060 1062 DECODE_HEAD; 1061 1063 1062 1064 READ_BUF(4); 1063 - READ32(rename->rn_snamelen); 1065 + rename->rn_snamelen = be32_to_cpup(p++); 1064 1066 READ_BUF(rename->rn_snamelen + 4); 1065 1067 SAVEMEM(rename->rn_sname, rename->rn_snamelen); 1066 - READ32(rename->rn_tnamelen); 1068 + rename->rn_tnamelen = be32_to_cpup(p++); 1067 1069 READ_BUF(rename->rn_tnamelen); 1068 1070 SAVEMEM(rename->rn_tname, rename->rn_tnamelen); 1069 1071 if ((status = check_filename(rename->rn_sname, rename->rn_snamelen))) ··· 1095 1097 DECODE_HEAD; 1096 1098 1097 1099 READ_BUF(4); 1098 - READ32(secinfo->si_namelen); 1100 + secinfo->si_namelen = be32_to_cpup(p++); 1099 1101 READ_BUF(secinfo->si_namelen); 1100 1102 SAVEMEM(secinfo->si_name, secinfo->si_namelen); 1101 1103 status = check_filename(secinfo->si_name, secinfo->si_namelen); ··· 1111 1113 DECODE_HEAD; 1112 1114 1113 1115 READ_BUF(4); 1114 - READ32(sin->sin_style); 1116 + sin->sin_style = be32_to_cpup(p++); 1115 1117 DECODE_TAIL; 1116 1118 } 1117 1119 ··· 1142 1144 if (status) 1143 1145 return nfserr_bad_xdr; 1144 1146 READ_BUF(8); 1145 - READ32(setclientid->se_callback_prog); 1146 - READ32(setclientid->se_callback_netid_len); 1147 + setclientid->se_callback_prog = be32_to_cpup(p++); 1148 + setclientid->se_callback_netid_len = be32_to_cpup(p++); 1147 1149 1148 1150 READ_BUF(setclientid->se_callback_netid_len + 4); 1149 1151 SAVEMEM(setclientid->se_callback_netid_val, setclientid->se_callback_netid_len); 1150 - READ32(setclientid->se_callback_addr_len); 1152 + setclientid->se_callback_addr_len = be32_to_cpup(p++); 1151 1153 1152 1154 READ_BUF(setclientid->se_callback_addr_len + 4); 1153 1155 SAVEMEM(setclientid->se_callback_addr_val, setclientid->se_callback_addr_len); 1154 - READ32(setclientid->se_callback_ident); 1156 + setclientid->se_callback_ident = be32_to_cpup(p++); 1155 1157 1156 1158 DECODE_TAIL; 1157 1159 } ··· 1184 1186 * nfsd4_proc_verify */ 1185 1187 1186 1188 READ_BUF(4); 1187 - READ32(verify->ve_attrlen); 1189 + verify->ve_attrlen = be32_to_cpup(p++); 1188 1190 READ_BUF(verify->ve_attrlen); 1189 1191 SAVEMEM(verify->ve_attrval, verify->ve_attrlen); 1190 1192 ··· 1202 1204 if (status) 1203 1205 return status; 1204 1206 READ_BUF(16); 1205 - READ64(write->wr_offset); 1206 - READ32(write->wr_stable_how); 1207 + p = xdr_decode_hyper(p, &write->wr_offset); 1208 + write->wr_stable_how = be32_to_cpup(p++); 1207 1209 if (write->wr_stable_how > 2) 1208 1210 goto xdr_error; 1209 - READ32(write->wr_buflen); 1211 + write->wr_buflen = be32_to_cpup(p++); 1210 1212 1211 1213 /* Sorry .. no magic macros for this.. * 1212 1214 * READ_BUF(write->wr_buflen); ··· 1252 1254 1253 1255 READ_BUF(12); 1254 1256 COPYMEM(&rlockowner->rl_clientid, sizeof(clientid_t)); 1255 - READ32(rlockowner->rl_owner.len); 1257 + rlockowner->rl_owner.len = be32_to_cpup(p++); 1256 1258 READ_BUF(rlockowner->rl_owner.len); 1257 1259 READMEM(rlockowner->rl_owner.data, rlockowner->rl_owner.len); 1258 1260 ··· 1276 1278 return nfserr_bad_xdr; 1277 1279 1278 1280 READ_BUF(4); 1279 - READ32(exid->flags); 1281 + exid->flags = be32_to_cpup(p++); 1280 1282 1281 1283 /* Ignore state_protect4_a */ 1282 1284 READ_BUF(4); 1283 - READ32(exid->spa_how); 1285 + exid->spa_how = be32_to_cpup(p++); 1284 1286 switch (exid->spa_how) { 1285 1287 case SP4_NONE: 1286 1288 break; 1287 1289 case SP4_MACH_CRED: 1288 1290 /* spo_must_enforce */ 1289 1291 READ_BUF(4); 1290 - READ32(dummy); 1292 + dummy = be32_to_cpup(p++); 1291 1293 READ_BUF(dummy * 4); 1292 1294 p += dummy; 1293 1295 1294 1296 /* spo_must_allow */ 1295 1297 READ_BUF(4); 1296 - READ32(dummy); 1298 + dummy = be32_to_cpup(p++); 1297 1299 READ_BUF(dummy * 4); 1298 1300 p += dummy; 1299 1301 break; 1300 1302 case SP4_SSV: 1301 1303 /* ssp_ops */ 1302 1304 READ_BUF(4); 1303 - READ32(dummy); 1305 + dummy = be32_to_cpup(p++); 1304 1306 READ_BUF(dummy * 4); 1305 1307 p += dummy; 1306 1308 1307 1309 READ_BUF(4); 1308 - READ32(dummy); 1310 + dummy = be32_to_cpup(p++); 1309 1311 READ_BUF(dummy * 4); 1310 1312 p += dummy; 1311 1313 1312 1314 /* ssp_hash_algs<> */ 1313 1315 READ_BUF(4); 1314 - READ32(tmp); 1316 + tmp = be32_to_cpup(p++); 1315 1317 while (tmp--) { 1316 1318 READ_BUF(4); 1317 - READ32(dummy); 1319 + dummy = be32_to_cpup(p++); 1318 1320 READ_BUF(dummy); 1319 1321 p += XDR_QUADLEN(dummy); 1320 1322 } 1321 1323 1322 1324 /* ssp_encr_algs<> */ 1323 1325 READ_BUF(4); 1324 - READ32(tmp); 1326 + tmp = be32_to_cpup(p++); 1325 1327 while (tmp--) { 1326 1328 READ_BUF(4); 1327 - READ32(dummy); 1329 + dummy = be32_to_cpup(p++); 1328 1330 READ_BUF(dummy); 1329 1331 p += XDR_QUADLEN(dummy); 1330 1332 } 1331 1333 1332 1334 /* ssp_window and ssp_num_gss_handles */ 1333 1335 READ_BUF(8); 1334 - READ32(dummy); 1335 - READ32(dummy); 1336 + dummy = be32_to_cpup(p++); 1337 + dummy = be32_to_cpup(p++); 1336 1338 break; 1337 1339 default: 1338 1340 goto xdr_error; ··· 1340 1342 1341 1343 /* Ignore Implementation ID */ 1342 1344 READ_BUF(4); /* nfs_impl_id4 array length */ 1343 - READ32(dummy); 1345 + dummy = be32_to_cpup(p++); 1344 1346 1345 1347 if (dummy > 1) 1346 1348 goto xdr_error; ··· 1348 1350 if (dummy == 1) { 1349 1351 /* nii_domain */ 1350 1352 READ_BUF(4); 1351 - READ32(dummy); 1353 + dummy = be32_to_cpup(p++); 1352 1354 READ_BUF(dummy); 1353 1355 p += XDR_QUADLEN(dummy); 1354 1356 1355 1357 /* nii_name */ 1356 1358 READ_BUF(4); 1357 - READ32(dummy); 1359 + dummy = be32_to_cpup(p++); 1358 1360 READ_BUF(dummy); 1359 1361 p += XDR_QUADLEN(dummy); 1360 1362 ··· 1374 1376 1375 1377 READ_BUF(16); 1376 1378 COPYMEM(&sess->clientid, 8); 1377 - READ32(sess->seqid); 1378 - READ32(sess->flags); 1379 + sess->seqid = be32_to_cpup(p++); 1380 + sess->flags = be32_to_cpup(p++); 1379 1381 1380 1382 /* Fore channel attrs */ 1381 1383 READ_BUF(28); 1382 - READ32(dummy); /* headerpadsz is always 0 */ 1383 - READ32(sess->fore_channel.maxreq_sz); 1384 - READ32(sess->fore_channel.maxresp_sz); 1385 - READ32(sess->fore_channel.maxresp_cached); 1386 - READ32(sess->fore_channel.maxops); 1387 - READ32(sess->fore_channel.maxreqs); 1388 - READ32(sess->fore_channel.nr_rdma_attrs); 1384 + dummy = be32_to_cpup(p++); /* headerpadsz is always 0 */ 1385 + sess->fore_channel.maxreq_sz = be32_to_cpup(p++); 1386 + sess->fore_channel.maxresp_sz = be32_to_cpup(p++); 1387 + sess->fore_channel.maxresp_cached = be32_to_cpup(p++); 1388 + sess->fore_channel.maxops = be32_to_cpup(p++); 1389 + sess->fore_channel.maxreqs = be32_to_cpup(p++); 1390 + sess->fore_channel.nr_rdma_attrs = be32_to_cpup(p++); 1389 1391 if (sess->fore_channel.nr_rdma_attrs == 1) { 1390 1392 READ_BUF(4); 1391 - READ32(sess->fore_channel.rdma_attrs); 1393 + sess->fore_channel.rdma_attrs = be32_to_cpup(p++); 1392 1394 } else if (sess->fore_channel.nr_rdma_attrs > 1) { 1393 1395 dprintk("Too many fore channel attr bitmaps!\n"); 1394 1396 goto xdr_error; ··· 1396 1398 1397 1399 /* Back channel attrs */ 1398 1400 READ_BUF(28); 1399 - READ32(dummy); /* headerpadsz is always 0 */ 1400 - READ32(sess->back_channel.maxreq_sz); 1401 - READ32(sess->back_channel.maxresp_sz); 1402 - READ32(sess->back_channel.maxresp_cached); 1403 - READ32(sess->back_channel.maxops); 1404 - READ32(sess->back_channel.maxreqs); 1405 - READ32(sess->back_channel.nr_rdma_attrs); 1401 + dummy = be32_to_cpup(p++); /* headerpadsz is always 0 */ 1402 + sess->back_channel.maxreq_sz = be32_to_cpup(p++); 1403 + sess->back_channel.maxresp_sz = be32_to_cpup(p++); 1404 + sess->back_channel.maxresp_cached = be32_to_cpup(p++); 1405 + sess->back_channel.maxops = be32_to_cpup(p++); 1406 + sess->back_channel.maxreqs = be32_to_cpup(p++); 1407 + sess->back_channel.nr_rdma_attrs = be32_to_cpup(p++); 1406 1408 if (sess->back_channel.nr_rdma_attrs == 1) { 1407 1409 READ_BUF(4); 1408 - READ32(sess->back_channel.rdma_attrs); 1410 + sess->back_channel.rdma_attrs = be32_to_cpup(p++); 1409 1411 } else if (sess->back_channel.nr_rdma_attrs > 1) { 1410 1412 dprintk("Too many back channel attr bitmaps!\n"); 1411 1413 goto xdr_error; 1412 1414 } 1413 1415 1414 1416 READ_BUF(4); 1415 - READ32(sess->callback_prog); 1417 + sess->callback_prog = be32_to_cpup(p++); 1416 1418 nfsd4_decode_cb_sec(argp, &sess->cb_sec); 1417 1419 DECODE_TAIL; 1418 1420 } ··· 1435 1437 DECODE_HEAD; 1436 1438 1437 1439 READ_BUF(sizeof(stateid_t)); 1438 - READ32(free_stateid->fr_stateid.si_generation); 1440 + free_stateid->fr_stateid.si_generation = be32_to_cpup(p++); 1439 1441 COPYMEM(&free_stateid->fr_stateid.si_opaque, sizeof(stateid_opaque_t)); 1440 1442 1441 1443 DECODE_TAIL; ··· 1449 1451 1450 1452 READ_BUF(NFS4_MAX_SESSIONID_LEN + 16); 1451 1453 COPYMEM(seq->sessionid.data, NFS4_MAX_SESSIONID_LEN); 1452 - READ32(seq->seqid); 1453 - READ32(seq->slotid); 1454 - READ32(seq->maxslots); 1455 - READ32(seq->cachethis); 1454 + seq->seqid = be32_to_cpup(p++); 1455 + seq->slotid = be32_to_cpup(p++); 1456 + seq->maxslots = be32_to_cpup(p++); 1457 + seq->cachethis = be32_to_cpup(p++); 1456 1458 1457 1459 DECODE_TAIL; 1458 1460 } ··· 1509 1511 DECODE_HEAD; 1510 1512 1511 1513 READ_BUF(4); 1512 - READ32(rc->rca_one_fs); 1514 + rc->rca_one_fs = be32_to_cpup(p++); 1513 1515 1514 1516 DECODE_TAIL; 1515 1517 } ··· 1603 1605 return true; 1604 1606 } 1605 1607 1606 - /* 1607 - * Return a rough estimate of the maximum possible reply size. Note the 1608 - * estimate includes rpc headers so is meant to be passed to 1609 - * svc_reserve, not svc_reserve_auth. 1610 - * 1611 - * Also note the current compound encoding permits only one operation to 1612 - * use pages beyond the first one, so the maximum possible length is the 1613 - * maximum over these values, not the sum. 1614 - */ 1615 - static int nfsd4_max_reply(u32 opnum) 1616 - { 1617 - switch (opnum) { 1618 - case OP_READLINK: 1619 - case OP_READDIR: 1620 - /* 1621 - * Both of these ops take a single page for data and put 1622 - * the head and tail in another page: 1623 - */ 1624 - return 2 * PAGE_SIZE; 1625 - case OP_READ: 1626 - return INT_MAX; 1627 - default: 1628 - return PAGE_SIZE; 1629 - } 1630 - } 1631 - 1632 1608 static __be32 1633 1609 nfsd4_decode_compound(struct nfsd4_compoundargs *argp) 1634 1610 { 1635 1611 DECODE_HEAD; 1636 1612 struct nfsd4_op *op; 1637 1613 bool cachethis = false; 1638 - int max_reply = PAGE_SIZE; 1614 + int auth_slack= argp->rqstp->rq_auth_slack; 1615 + int max_reply = auth_slack + 8; /* opcnt, status */ 1616 + int readcount = 0; 1617 + int readbytes = 0; 1639 1618 int i; 1640 1619 1641 1620 READ_BUF(4); 1642 - READ32(argp->taglen); 1621 + argp->taglen = be32_to_cpup(p++); 1643 1622 READ_BUF(argp->taglen + 8); 1644 1623 SAVEMEM(argp->tag, argp->taglen); 1645 - READ32(argp->minorversion); 1646 - READ32(argp->opcnt); 1624 + argp->minorversion = be32_to_cpup(p++); 1625 + argp->opcnt = be32_to_cpup(p++); 1626 + max_reply += 4 + (XDR_QUADLEN(argp->taglen) << 2); 1647 1627 1648 1628 if (argp->taglen > NFSD4_MAX_TAGLEN) 1649 1629 goto xdr_error; ··· 1645 1669 op->replay = NULL; 1646 1670 1647 1671 READ_BUF(4); 1648 - READ32(op->opnum); 1672 + op->opnum = be32_to_cpup(p++); 1649 1673 1650 1674 if (nfsd4_opnum_in_range(argp, op)) 1651 1675 op->status = nfsd4_dec_ops[op->opnum](argp, &op->u); ··· 1653 1677 op->opnum = OP_ILLEGAL; 1654 1678 op->status = nfserr_op_illegal; 1655 1679 } 1656 - 1657 - if (op->status) { 1658 - argp->opcnt = i+1; 1659 - break; 1660 - } 1661 1680 /* 1662 1681 * We'll try to cache the result in the DRC if any one 1663 1682 * op in the compound wants to be cached: 1664 1683 */ 1665 1684 cachethis |= nfsd4_cache_this_op(op); 1666 1685 1667 - max_reply = max(max_reply, nfsd4_max_reply(op->opnum)); 1686 + if (op->opnum == OP_READ) { 1687 + readcount++; 1688 + readbytes += nfsd4_max_reply(argp->rqstp, op); 1689 + } else 1690 + max_reply += nfsd4_max_reply(argp->rqstp, op); 1691 + 1692 + if (op->status) { 1693 + argp->opcnt = i+1; 1694 + break; 1695 + } 1668 1696 } 1669 1697 /* Sessions make the DRC unnecessary: */ 1670 1698 if (argp->minorversion) 1671 1699 cachethis = false; 1672 - if (max_reply != INT_MAX) 1673 - svc_reserve(argp->rqstp, max_reply); 1700 + svc_reserve(argp->rqstp, max_reply + readbytes); 1674 1701 argp->rqstp->rq_cachetype = cachethis ? RC_REPLBUFF : RC_NOCACHE; 1702 + 1703 + if (readcount > 1 || max_reply > PAGE_SIZE - auth_slack) 1704 + argp->rqstp->rq_splice_ok = false; 1675 1705 1676 1706 DECODE_TAIL; 1677 1707 } 1678 1708 1679 - #define WRITE32(n) *p++ = htonl(n) 1680 - #define WRITE64(n) do { \ 1681 - *p++ = htonl((u32)((n) >> 32)); \ 1682 - *p++ = htonl((u32)(n)); \ 1683 - } while (0) 1684 - #define WRITEMEM(ptr,nbytes) do { if (nbytes > 0) { \ 1685 - *(p + XDR_QUADLEN(nbytes) -1) = 0; \ 1686 - memcpy(p, ptr, nbytes); \ 1687 - p += XDR_QUADLEN(nbytes); \ 1688 - }} while (0) 1689 - 1690 - static void write32(__be32 **p, u32 n) 1691 - { 1692 - *(*p)++ = htonl(n); 1693 - } 1694 - 1695 - static void write64(__be32 **p, u64 n) 1696 - { 1697 - write32(p, (n >> 32)); 1698 - write32(p, (u32)n); 1699 - } 1700 - 1701 - static void write_change(__be32 **p, struct kstat *stat, struct inode *inode) 1709 + static __be32 *encode_change(__be32 *p, struct kstat *stat, struct inode *inode) 1702 1710 { 1703 1711 if (IS_I_VERSION(inode)) { 1704 - write64(p, inode->i_version); 1712 + p = xdr_encode_hyper(p, inode->i_version); 1705 1713 } else { 1706 - write32(p, stat->ctime.tv_sec); 1707 - write32(p, stat->ctime.tv_nsec); 1714 + *p++ = cpu_to_be32(stat->ctime.tv_sec); 1715 + *p++ = cpu_to_be32(stat->ctime.tv_nsec); 1708 1716 } 1717 + return p; 1709 1718 } 1710 1719 1711 - static void write_cinfo(__be32 **p, struct nfsd4_change_info *c) 1720 + static __be32 *encode_cinfo(__be32 *p, struct nfsd4_change_info *c) 1712 1721 { 1713 - write32(p, c->atomic); 1722 + *p++ = cpu_to_be32(c->atomic); 1714 1723 if (c->change_supported) { 1715 - write64(p, c->before_change); 1716 - write64(p, c->after_change); 1724 + p = xdr_encode_hyper(p, c->before_change); 1725 + p = xdr_encode_hyper(p, c->after_change); 1717 1726 } else { 1718 - write32(p, c->before_ctime_sec); 1719 - write32(p, c->before_ctime_nsec); 1720 - write32(p, c->after_ctime_sec); 1721 - write32(p, c->after_ctime_nsec); 1727 + *p++ = cpu_to_be32(c->before_ctime_sec); 1728 + *p++ = cpu_to_be32(c->before_ctime_nsec); 1729 + *p++ = cpu_to_be32(c->after_ctime_sec); 1730 + *p++ = cpu_to_be32(c->after_ctime_nsec); 1722 1731 } 1732 + return p; 1723 1733 } 1724 - 1725 - #define RESERVE_SPACE(nbytes) do { \ 1726 - p = resp->p; \ 1727 - BUG_ON(p + XDR_QUADLEN(nbytes) > resp->end); \ 1728 - } while (0) 1729 - #define ADJUST_ARGS() resp->p = p 1730 1734 1731 1735 /* Encode as an array of strings the string given with components 1732 1736 * separated @sep, escaped with esc_enter and esc_exit. 1733 1737 */ 1734 - static __be32 nfsd4_encode_components_esc(char sep, char *components, 1735 - __be32 **pp, int *buflen, 1736 - char esc_enter, char esc_exit) 1738 + static __be32 nfsd4_encode_components_esc(struct xdr_stream *xdr, char sep, 1739 + char *components, char esc_enter, 1740 + char esc_exit) 1737 1741 { 1738 - __be32 *p = *pp; 1739 - __be32 *countp = p; 1742 + __be32 *p; 1743 + __be32 pathlen; 1744 + int pathlen_offset; 1740 1745 int strlen, count=0; 1741 1746 char *str, *end, *next; 1742 1747 1743 1748 dprintk("nfsd4_encode_components(%s)\n", components); 1744 - if ((*buflen -= 4) < 0) 1749 + 1750 + pathlen_offset = xdr->buf->len; 1751 + p = xdr_reserve_space(xdr, 4); 1752 + if (!p) 1745 1753 return nfserr_resource; 1746 - WRITE32(0); /* We will fill this in with @count later */ 1754 + p++; /* We will fill this in with @count later */ 1755 + 1747 1756 end = str = components; 1748 1757 while (*end) { 1749 1758 bool found_esc = false; ··· 1750 1789 1751 1790 strlen = end - str; 1752 1791 if (strlen) { 1753 - if ((*buflen -= ((XDR_QUADLEN(strlen) << 2) + 4)) < 0) 1792 + p = xdr_reserve_space(xdr, strlen + 4); 1793 + if (!p) 1754 1794 return nfserr_resource; 1755 - WRITE32(strlen); 1756 - WRITEMEM(str, strlen); 1795 + p = xdr_encode_opaque(p, str, strlen); 1757 1796 count++; 1758 1797 } 1759 1798 else 1760 1799 end++; 1761 1800 str = end; 1762 1801 } 1763 - *pp = p; 1764 - p = countp; 1765 - WRITE32(count); 1802 + pathlen = htonl(xdr->buf->len - pathlen_offset); 1803 + write_bytes_to_xdr_buf(xdr->buf, pathlen_offset, &pathlen, 4); 1766 1804 return 0; 1767 1805 } 1768 1806 1769 1807 /* Encode as an array of strings the string given with components 1770 1808 * separated @sep. 1771 1809 */ 1772 - static __be32 nfsd4_encode_components(char sep, char *components, 1773 - __be32 **pp, int *buflen) 1810 + static __be32 nfsd4_encode_components(struct xdr_stream *xdr, char sep, 1811 + char *components) 1774 1812 { 1775 - return nfsd4_encode_components_esc(sep, components, pp, buflen, 0, 0); 1813 + return nfsd4_encode_components_esc(xdr, sep, components, 0, 0); 1776 1814 } 1777 1815 1778 1816 /* 1779 1817 * encode a location element of a fs_locations structure 1780 1818 */ 1781 - static __be32 nfsd4_encode_fs_location4(struct nfsd4_fs_location *location, 1782 - __be32 **pp, int *buflen) 1819 + static __be32 nfsd4_encode_fs_location4(struct xdr_stream *xdr, 1820 + struct nfsd4_fs_location *location) 1783 1821 { 1784 1822 __be32 status; 1785 - __be32 *p = *pp; 1786 1823 1787 - status = nfsd4_encode_components_esc(':', location->hosts, &p, buflen, 1824 + status = nfsd4_encode_components_esc(xdr, ':', location->hosts, 1788 1825 '[', ']'); 1789 1826 if (status) 1790 1827 return status; 1791 - status = nfsd4_encode_components('/', location->path, &p, buflen); 1828 + status = nfsd4_encode_components(xdr, '/', location->path); 1792 1829 if (status) 1793 1830 return status; 1794 - *pp = p; 1795 1831 return 0; 1796 1832 } 1797 1833 1798 1834 /* 1799 1835 * Encode a path in RFC3530 'pathname4' format 1800 1836 */ 1801 - static __be32 nfsd4_encode_path(const struct path *root, 1802 - const struct path *path, __be32 **pp, int *buflen) 1837 + static __be32 nfsd4_encode_path(struct xdr_stream *xdr, 1838 + const struct path *root, 1839 + const struct path *path) 1803 1840 { 1804 1841 struct path cur = *path; 1805 - __be32 *p = *pp; 1842 + __be32 *p; 1806 1843 struct dentry **components = NULL; 1807 1844 unsigned int ncomponents = 0; 1808 1845 __be32 err = nfserr_jukebox; ··· 1831 1872 components[ncomponents++] = cur.dentry; 1832 1873 cur.dentry = dget_parent(cur.dentry); 1833 1874 } 1834 - 1835 - *buflen -= 4; 1836 - if (*buflen < 0) 1875 + err = nfserr_resource; 1876 + p = xdr_reserve_space(xdr, 4); 1877 + if (!p) 1837 1878 goto out_free; 1838 - WRITE32(ncomponents); 1879 + *p++ = cpu_to_be32(ncomponents); 1839 1880 1840 1881 while (ncomponents) { 1841 1882 struct dentry *dentry = components[ncomponents - 1]; ··· 1843 1884 1844 1885 spin_lock(&dentry->d_lock); 1845 1886 len = dentry->d_name.len; 1846 - *buflen -= 4 + (XDR_QUADLEN(len) << 2); 1847 - if (*buflen < 0) { 1887 + p = xdr_reserve_space(xdr, len + 4); 1888 + if (!p) { 1848 1889 spin_unlock(&dentry->d_lock); 1849 1890 goto out_free; 1850 1891 } 1851 - WRITE32(len); 1852 - WRITEMEM(dentry->d_name.name, len); 1892 + p = xdr_encode_opaque(p, dentry->d_name.name, len); 1853 1893 dprintk("/%s", dentry->d_name.name); 1854 1894 spin_unlock(&dentry->d_lock); 1855 1895 dput(dentry); 1856 1896 ncomponents--; 1857 1897 } 1858 1898 1859 - *pp = p; 1860 1899 err = 0; 1861 1900 out_free: 1862 1901 dprintk(")\n"); ··· 1865 1908 return err; 1866 1909 } 1867 1910 1868 - static __be32 nfsd4_encode_fsloc_fsroot(struct svc_rqst *rqstp, 1869 - const struct path *path, __be32 **pp, int *buflen) 1911 + static __be32 nfsd4_encode_fsloc_fsroot(struct xdr_stream *xdr, 1912 + struct svc_rqst *rqstp, const struct path *path) 1870 1913 { 1871 1914 struct svc_export *exp_ps; 1872 1915 __be32 res; ··· 1874 1917 exp_ps = rqst_find_fsidzero_export(rqstp); 1875 1918 if (IS_ERR(exp_ps)) 1876 1919 return nfserrno(PTR_ERR(exp_ps)); 1877 - res = nfsd4_encode_path(&exp_ps->ex_path, path, pp, buflen); 1920 + res = nfsd4_encode_path(xdr, &exp_ps->ex_path, path); 1878 1921 exp_put(exp_ps); 1879 1922 return res; 1880 1923 } ··· 1882 1925 /* 1883 1926 * encode a fs_locations structure 1884 1927 */ 1885 - static __be32 nfsd4_encode_fs_locations(struct svc_rqst *rqstp, 1886 - struct svc_export *exp, 1887 - __be32 **pp, int *buflen) 1928 + static __be32 nfsd4_encode_fs_locations(struct xdr_stream *xdr, 1929 + struct svc_rqst *rqstp, struct svc_export *exp) 1888 1930 { 1889 1931 __be32 status; 1890 1932 int i; 1891 - __be32 *p = *pp; 1933 + __be32 *p; 1892 1934 struct nfsd4_fs_locations *fslocs = &exp->ex_fslocs; 1893 1935 1894 - status = nfsd4_encode_fsloc_fsroot(rqstp, &exp->ex_path, &p, buflen); 1936 + status = nfsd4_encode_fsloc_fsroot(xdr, rqstp, &exp->ex_path); 1895 1937 if (status) 1896 1938 return status; 1897 - if ((*buflen -= 4) < 0) 1939 + p = xdr_reserve_space(xdr, 4); 1940 + if (!p) 1898 1941 return nfserr_resource; 1899 - WRITE32(fslocs->locations_count); 1942 + *p++ = cpu_to_be32(fslocs->locations_count); 1900 1943 for (i=0; i<fslocs->locations_count; i++) { 1901 - status = nfsd4_encode_fs_location4(&fslocs->locations[i], 1902 - &p, buflen); 1944 + status = nfsd4_encode_fs_location4(xdr, &fslocs->locations[i]); 1903 1945 if (status) 1904 1946 return status; 1905 1947 } 1906 - *pp = p; 1907 1948 return 0; 1908 1949 } 1909 1950 ··· 1920 1965 } 1921 1966 1922 1967 static inline __be32 1923 - nfsd4_encode_aclname(struct svc_rqst *rqstp, struct nfs4_ace *ace, 1924 - __be32 **p, int *buflen) 1968 + nfsd4_encode_aclname(struct xdr_stream *xdr, struct svc_rqst *rqstp, 1969 + struct nfs4_ace *ace) 1925 1970 { 1926 1971 if (ace->whotype != NFS4_ACL_WHO_NAMED) 1927 - return nfs4_acl_write_who(ace->whotype, p, buflen); 1972 + return nfs4_acl_write_who(xdr, ace->whotype); 1928 1973 else if (ace->flag & NFS4_ACE_IDENTIFIER_GROUP) 1929 - return nfsd4_encode_group(rqstp, ace->who_gid, p, buflen); 1974 + return nfsd4_encode_group(xdr, rqstp, ace->who_gid); 1930 1975 else 1931 - return nfsd4_encode_user(rqstp, ace->who_uid, p, buflen); 1976 + return nfsd4_encode_user(xdr, rqstp, ace->who_uid); 1932 1977 } 1933 1978 1934 1979 #define WORD0_ABSENT_FS_ATTRS (FATTR4_WORD0_FS_LOCATIONS | FATTR4_WORD0_FSID | \ ··· 1937 1982 1938 1983 #ifdef CONFIG_NFSD_V4_SECURITY_LABEL 1939 1984 static inline __be32 1940 - nfsd4_encode_security_label(struct svc_rqst *rqstp, void *context, int len, __be32 **pp, int *buflen) 1985 + nfsd4_encode_security_label(struct xdr_stream *xdr, struct svc_rqst *rqstp, 1986 + void *context, int len) 1941 1987 { 1942 - __be32 *p = *pp; 1988 + __be32 *p; 1943 1989 1944 - if (*buflen < ((XDR_QUADLEN(len) << 2) + 4 + 4 + 4)) 1990 + p = xdr_reserve_space(xdr, len + 4 + 4 + 4); 1991 + if (!p) 1945 1992 return nfserr_resource; 1946 1993 1947 1994 /* 1948 1995 * For now we use a 0 here to indicate the null translation; in 1949 1996 * the future we may place a call to translation code here. 1950 1997 */ 1951 - if ((*buflen -= 8) < 0) 1952 - return nfserr_resource; 1953 - 1954 - WRITE32(0); /* lfs */ 1955 - WRITE32(0); /* pi */ 1998 + *p++ = cpu_to_be32(0); /* lfs */ 1999 + *p++ = cpu_to_be32(0); /* pi */ 1956 2000 p = xdr_encode_opaque(p, context, len); 1957 - *buflen -= (XDR_QUADLEN(len) << 2) + 4; 1958 - 1959 - *pp = p; 1960 2001 return 0; 1961 2002 } 1962 2003 #else 1963 2004 static inline __be32 1964 - nfsd4_encode_security_label(struct svc_rqst *rqstp, void *context, int len, __be32 **pp, int *buflen) 2005 + nfsd4_encode_security_label(struct xdr_stream *xdr, struct svc_rqst *rqstp, 2006 + void *context, int len) 1965 2007 { return 0; } 1966 2008 #endif 1967 2009 ··· 1997 2045 /* 1998 2046 * Note: @fhp can be NULL; in this case, we might have to compose the filehandle 1999 2047 * ourselves. 2000 - * 2001 - * countp is the buffer size in _words_ 2002 2048 */ 2003 - __be32 2004 - nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp, 2005 - struct dentry *dentry, __be32 **buffer, int count, u32 *bmval, 2049 + static __be32 2050 + nfsd4_encode_fattr(struct xdr_stream *xdr, struct svc_fh *fhp, 2051 + struct svc_export *exp, 2052 + struct dentry *dentry, u32 *bmval, 2006 2053 struct svc_rqst *rqstp, int ignore_crossmnt) 2007 2054 { 2008 2055 u32 bmval0 = bmval[0]; ··· 2010 2059 struct kstat stat; 2011 2060 struct svc_fh *tempfh = NULL; 2012 2061 struct kstatfs statfs; 2013 - int buflen = count << 2; 2014 - __be32 *attrlenp; 2062 + __be32 *p; 2063 + int starting_len = xdr->buf->len; 2064 + int attrlen_offset; 2065 + __be32 attrlen; 2015 2066 u32 dummy; 2016 2067 u64 dummy64; 2017 2068 u32 rdattr_err = 0; 2018 - __be32 *p = *buffer; 2019 2069 __be32 status; 2020 2070 int err; 2021 2071 int aclsupport = 0; ··· 2047 2095 err = vfs_getattr(&path, &stat); 2048 2096 if (err) 2049 2097 goto out_nfserr; 2050 - if ((bmval0 & (FATTR4_WORD0_FILES_FREE | FATTR4_WORD0_FILES_TOTAL | 2051 - FATTR4_WORD0_MAXNAME)) || 2098 + if ((bmval0 & (FATTR4_WORD0_FILES_AVAIL | FATTR4_WORD0_FILES_FREE | 2099 + FATTR4_WORD0_FILES_TOTAL | FATTR4_WORD0_MAXNAME)) || 2052 2100 (bmval1 & (FATTR4_WORD1_SPACE_AVAIL | FATTR4_WORD1_SPACE_FREE | 2053 2101 FATTR4_WORD1_SPACE_TOTAL))) { 2054 2102 err = vfs_statfs(&path, &statfs); ··· 2097 2145 #endif /* CONFIG_NFSD_V4_SECURITY_LABEL */ 2098 2146 2099 2147 if (bmval2) { 2100 - if ((buflen -= 16) < 0) 2148 + p = xdr_reserve_space(xdr, 16); 2149 + if (!p) 2101 2150 goto out_resource; 2102 - WRITE32(3); 2103 - WRITE32(bmval0); 2104 - WRITE32(bmval1); 2105 - WRITE32(bmval2); 2151 + *p++ = cpu_to_be32(3); 2152 + *p++ = cpu_to_be32(bmval0); 2153 + *p++ = cpu_to_be32(bmval1); 2154 + *p++ = cpu_to_be32(bmval2); 2106 2155 } else if (bmval1) { 2107 - if ((buflen -= 12) < 0) 2156 + p = xdr_reserve_space(xdr, 12); 2157 + if (!p) 2108 2158 goto out_resource; 2109 - WRITE32(2); 2110 - WRITE32(bmval0); 2111 - WRITE32(bmval1); 2159 + *p++ = cpu_to_be32(2); 2160 + *p++ = cpu_to_be32(bmval0); 2161 + *p++ = cpu_to_be32(bmval1); 2112 2162 } else { 2113 - if ((buflen -= 8) < 0) 2163 + p = xdr_reserve_space(xdr, 8); 2164 + if (!p) 2114 2165 goto out_resource; 2115 - WRITE32(1); 2116 - WRITE32(bmval0); 2166 + *p++ = cpu_to_be32(1); 2167 + *p++ = cpu_to_be32(bmval0); 2117 2168 } 2118 - attrlenp = p++; /* to be backfilled later */ 2169 + 2170 + attrlen_offset = xdr->buf->len; 2171 + p = xdr_reserve_space(xdr, 4); 2172 + if (!p) 2173 + goto out_resource; 2174 + p++; /* to be backfilled later */ 2119 2175 2120 2176 if (bmval0 & FATTR4_WORD0_SUPPORTED_ATTRS) { 2121 2177 u32 word0 = nfsd_suppattrs0(minorversion); ··· 2135 2175 if (!contextsupport) 2136 2176 word2 &= ~FATTR4_WORD2_SECURITY_LABEL; 2137 2177 if (!word2) { 2138 - if ((buflen -= 12) < 0) 2178 + p = xdr_reserve_space(xdr, 12); 2179 + if (!p) 2139 2180 goto out_resource; 2140 - WRITE32(2); 2141 - WRITE32(word0); 2142 - WRITE32(word1); 2181 + *p++ = cpu_to_be32(2); 2182 + *p++ = cpu_to_be32(word0); 2183 + *p++ = cpu_to_be32(word1); 2143 2184 } else { 2144 - if ((buflen -= 16) < 0) 2185 + p = xdr_reserve_space(xdr, 16); 2186 + if (!p) 2145 2187 goto out_resource; 2146 - WRITE32(3); 2147 - WRITE32(word0); 2148 - WRITE32(word1); 2149 - WRITE32(word2); 2188 + *p++ = cpu_to_be32(3); 2189 + *p++ = cpu_to_be32(word0); 2190 + *p++ = cpu_to_be32(word1); 2191 + *p++ = cpu_to_be32(word2); 2150 2192 } 2151 2193 } 2152 2194 if (bmval0 & FATTR4_WORD0_TYPE) { 2153 - if ((buflen -= 4) < 0) 2195 + p = xdr_reserve_space(xdr, 4); 2196 + if (!p) 2154 2197 goto out_resource; 2155 2198 dummy = nfs4_file_type(stat.mode); 2156 2199 if (dummy == NF4BAD) { 2157 2200 status = nfserr_serverfault; 2158 2201 goto out; 2159 2202 } 2160 - WRITE32(dummy); 2203 + *p++ = cpu_to_be32(dummy); 2161 2204 } 2162 2205 if (bmval0 & FATTR4_WORD0_FH_EXPIRE_TYPE) { 2163 - if ((buflen -= 4) < 0) 2206 + p = xdr_reserve_space(xdr, 4); 2207 + if (!p) 2164 2208 goto out_resource; 2165 2209 if (exp->ex_flags & NFSEXP_NOSUBTREECHECK) 2166 - WRITE32(NFS4_FH_PERSISTENT); 2210 + *p++ = cpu_to_be32(NFS4_FH_PERSISTENT); 2167 2211 else 2168 - WRITE32(NFS4_FH_PERSISTENT|NFS4_FH_VOL_RENAME); 2212 + *p++ = cpu_to_be32(NFS4_FH_PERSISTENT| 2213 + NFS4_FH_VOL_RENAME); 2169 2214 } 2170 2215 if (bmval0 & FATTR4_WORD0_CHANGE) { 2171 - if ((buflen -= 8) < 0) 2216 + p = xdr_reserve_space(xdr, 8); 2217 + if (!p) 2172 2218 goto out_resource; 2173 - write_change(&p, &stat, dentry->d_inode); 2219 + p = encode_change(p, &stat, dentry->d_inode); 2174 2220 } 2175 2221 if (bmval0 & FATTR4_WORD0_SIZE) { 2176 - if ((buflen -= 8) < 0) 2222 + p = xdr_reserve_space(xdr, 8); 2223 + if (!p) 2177 2224 goto out_resource; 2178 - WRITE64(stat.size); 2225 + p = xdr_encode_hyper(p, stat.size); 2179 2226 } 2180 2227 if (bmval0 & FATTR4_WORD0_LINK_SUPPORT) { 2181 - if ((buflen -= 4) < 0) 2228 + p = xdr_reserve_space(xdr, 4); 2229 + if (!p) 2182 2230 goto out_resource; 2183 - WRITE32(1); 2231 + *p++ = cpu_to_be32(1); 2184 2232 } 2185 2233 if (bmval0 & FATTR4_WORD0_SYMLINK_SUPPORT) { 2186 - if ((buflen -= 4) < 0) 2234 + p = xdr_reserve_space(xdr, 4); 2235 + if (!p) 2187 2236 goto out_resource; 2188 - WRITE32(1); 2237 + *p++ = cpu_to_be32(1); 2189 2238 } 2190 2239 if (bmval0 & FATTR4_WORD0_NAMED_ATTR) { 2191 - if ((buflen -= 4) < 0) 2240 + p = xdr_reserve_space(xdr, 4); 2241 + if (!p) 2192 2242 goto out_resource; 2193 - WRITE32(0); 2243 + *p++ = cpu_to_be32(0); 2194 2244 } 2195 2245 if (bmval0 & FATTR4_WORD0_FSID) { 2196 - if ((buflen -= 16) < 0) 2246 + p = xdr_reserve_space(xdr, 16); 2247 + if (!p) 2197 2248 goto out_resource; 2198 2249 if (exp->ex_fslocs.migrated) { 2199 - WRITE64(NFS4_REFERRAL_FSID_MAJOR); 2200 - WRITE64(NFS4_REFERRAL_FSID_MINOR); 2250 + p = xdr_encode_hyper(p, NFS4_REFERRAL_FSID_MAJOR); 2251 + p = xdr_encode_hyper(p, NFS4_REFERRAL_FSID_MINOR); 2201 2252 } else switch(fsid_source(fhp)) { 2202 2253 case FSIDSOURCE_FSID: 2203 - WRITE64((u64)exp->ex_fsid); 2204 - WRITE64((u64)0); 2254 + p = xdr_encode_hyper(p, (u64)exp->ex_fsid); 2255 + p = xdr_encode_hyper(p, (u64)0); 2205 2256 break; 2206 2257 case FSIDSOURCE_DEV: 2207 - WRITE32(0); 2208 - WRITE32(MAJOR(stat.dev)); 2209 - WRITE32(0); 2210 - WRITE32(MINOR(stat.dev)); 2258 + *p++ = cpu_to_be32(0); 2259 + *p++ = cpu_to_be32(MAJOR(stat.dev)); 2260 + *p++ = cpu_to_be32(0); 2261 + *p++ = cpu_to_be32(MINOR(stat.dev)); 2211 2262 break; 2212 2263 case FSIDSOURCE_UUID: 2213 - WRITEMEM(exp->ex_uuid, 16); 2264 + p = xdr_encode_opaque_fixed(p, exp->ex_uuid, 2265 + EX_UUID_LEN); 2214 2266 break; 2215 2267 } 2216 2268 } 2217 2269 if (bmval0 & FATTR4_WORD0_UNIQUE_HANDLES) { 2218 - if ((buflen -= 4) < 0) 2270 + p = xdr_reserve_space(xdr, 4); 2271 + if (!p) 2219 2272 goto out_resource; 2220 - WRITE32(0); 2273 + *p++ = cpu_to_be32(0); 2221 2274 } 2222 2275 if (bmval0 & FATTR4_WORD0_LEASE_TIME) { 2223 - if ((buflen -= 4) < 0) 2276 + p = xdr_reserve_space(xdr, 4); 2277 + if (!p) 2224 2278 goto out_resource; 2225 - WRITE32(nn->nfsd4_lease); 2279 + *p++ = cpu_to_be32(nn->nfsd4_lease); 2226 2280 } 2227 2281 if (bmval0 & FATTR4_WORD0_RDATTR_ERROR) { 2228 - if ((buflen -= 4) < 0) 2282 + p = xdr_reserve_space(xdr, 4); 2283 + if (!p) 2229 2284 goto out_resource; 2230 - WRITE32(rdattr_err); 2285 + *p++ = cpu_to_be32(rdattr_err); 2231 2286 } 2232 2287 if (bmval0 & FATTR4_WORD0_ACL) { 2233 2288 struct nfs4_ace *ace; 2234 2289 2235 2290 if (acl == NULL) { 2236 - if ((buflen -= 4) < 0) 2291 + p = xdr_reserve_space(xdr, 4); 2292 + if (!p) 2237 2293 goto out_resource; 2238 2294 2239 - WRITE32(0); 2295 + *p++ = cpu_to_be32(0); 2240 2296 goto out_acl; 2241 2297 } 2242 - if ((buflen -= 4) < 0) 2298 + p = xdr_reserve_space(xdr, 4); 2299 + if (!p) 2243 2300 goto out_resource; 2244 - WRITE32(acl->naces); 2301 + *p++ = cpu_to_be32(acl->naces); 2245 2302 2246 2303 for (ace = acl->aces; ace < acl->aces + acl->naces; ace++) { 2247 - if ((buflen -= 4*3) < 0) 2304 + p = xdr_reserve_space(xdr, 4*3); 2305 + if (!p) 2248 2306 goto out_resource; 2249 - WRITE32(ace->type); 2250 - WRITE32(ace->flag); 2251 - WRITE32(ace->access_mask & NFS4_ACE_MASK_ALL); 2252 - status = nfsd4_encode_aclname(rqstp, ace, &p, &buflen); 2307 + *p++ = cpu_to_be32(ace->type); 2308 + *p++ = cpu_to_be32(ace->flag); 2309 + *p++ = cpu_to_be32(ace->access_mask & 2310 + NFS4_ACE_MASK_ALL); 2311 + status = nfsd4_encode_aclname(xdr, rqstp, ace); 2253 2312 if (status) 2254 2313 goto out; 2255 2314 } 2256 2315 } 2257 2316 out_acl: 2258 2317 if (bmval0 & FATTR4_WORD0_ACLSUPPORT) { 2259 - if ((buflen -= 4) < 0) 2318 + p = xdr_reserve_space(xdr, 4); 2319 + if (!p) 2260 2320 goto out_resource; 2261 - WRITE32(aclsupport ? 2321 + *p++ = cpu_to_be32(aclsupport ? 2262 2322 ACL4_SUPPORT_ALLOW_ACL|ACL4_SUPPORT_DENY_ACL : 0); 2263 2323 } 2264 2324 if (bmval0 & FATTR4_WORD0_CANSETTIME) { 2265 - if ((buflen -= 4) < 0) 2325 + p = xdr_reserve_space(xdr, 4); 2326 + if (!p) 2266 2327 goto out_resource; 2267 - WRITE32(1); 2328 + *p++ = cpu_to_be32(1); 2268 2329 } 2269 2330 if (bmval0 & FATTR4_WORD0_CASE_INSENSITIVE) { 2270 - if ((buflen -= 4) < 0) 2331 + p = xdr_reserve_space(xdr, 4); 2332 + if (!p) 2271 2333 goto out_resource; 2272 - WRITE32(0); 2334 + *p++ = cpu_to_be32(0); 2273 2335 } 2274 2336 if (bmval0 & FATTR4_WORD0_CASE_PRESERVING) { 2275 - if ((buflen -= 4) < 0) 2337 + p = xdr_reserve_space(xdr, 4); 2338 + if (!p) 2276 2339 goto out_resource; 2277 - WRITE32(1); 2340 + *p++ = cpu_to_be32(1); 2278 2341 } 2279 2342 if (bmval0 & FATTR4_WORD0_CHOWN_RESTRICTED) { 2280 - if ((buflen -= 4) < 0) 2343 + p = xdr_reserve_space(xdr, 4); 2344 + if (!p) 2281 2345 goto out_resource; 2282 - WRITE32(1); 2346 + *p++ = cpu_to_be32(1); 2283 2347 } 2284 2348 if (bmval0 & FATTR4_WORD0_FILEHANDLE) { 2285 - buflen -= (XDR_QUADLEN(fhp->fh_handle.fh_size) << 2) + 4; 2286 - if (buflen < 0) 2349 + p = xdr_reserve_space(xdr, fhp->fh_handle.fh_size + 4); 2350 + if (!p) 2287 2351 goto out_resource; 2288 - WRITE32(fhp->fh_handle.fh_size); 2289 - WRITEMEM(&fhp->fh_handle.fh_base, fhp->fh_handle.fh_size); 2352 + p = xdr_encode_opaque(p, &fhp->fh_handle.fh_base, 2353 + fhp->fh_handle.fh_size); 2290 2354 } 2291 2355 if (bmval0 & FATTR4_WORD0_FILEID) { 2292 - if ((buflen -= 8) < 0) 2356 + p = xdr_reserve_space(xdr, 8); 2357 + if (!p) 2293 2358 goto out_resource; 2294 - WRITE64(stat.ino); 2359 + p = xdr_encode_hyper(p, stat.ino); 2295 2360 } 2296 2361 if (bmval0 & FATTR4_WORD0_FILES_AVAIL) { 2297 - if ((buflen -= 8) < 0) 2362 + p = xdr_reserve_space(xdr, 8); 2363 + if (!p) 2298 2364 goto out_resource; 2299 - WRITE64((u64) statfs.f_ffree); 2365 + p = xdr_encode_hyper(p, (u64) statfs.f_ffree); 2300 2366 } 2301 2367 if (bmval0 & FATTR4_WORD0_FILES_FREE) { 2302 - if ((buflen -= 8) < 0) 2368 + p = xdr_reserve_space(xdr, 8); 2369 + if (!p) 2303 2370 goto out_resource; 2304 - WRITE64((u64) statfs.f_ffree); 2371 + p = xdr_encode_hyper(p, (u64) statfs.f_ffree); 2305 2372 } 2306 2373 if (bmval0 & FATTR4_WORD0_FILES_TOTAL) { 2307 - if ((buflen -= 8) < 0) 2374 + p = xdr_reserve_space(xdr, 8); 2375 + if (!p) 2308 2376 goto out_resource; 2309 - WRITE64((u64) statfs.f_files); 2377 + p = xdr_encode_hyper(p, (u64) statfs.f_files); 2310 2378 } 2311 2379 if (bmval0 & FATTR4_WORD0_FS_LOCATIONS) { 2312 - status = nfsd4_encode_fs_locations(rqstp, exp, &p, &buflen); 2380 + status = nfsd4_encode_fs_locations(xdr, rqstp, exp); 2313 2381 if (status) 2314 2382 goto out; 2315 2383 } 2316 2384 if (bmval0 & FATTR4_WORD0_HOMOGENEOUS) { 2317 - if ((buflen -= 4) < 0) 2385 + p = xdr_reserve_space(xdr, 4); 2386 + if (!p) 2318 2387 goto out_resource; 2319 - WRITE32(1); 2388 + *p++ = cpu_to_be32(1); 2320 2389 } 2321 2390 if (bmval0 & FATTR4_WORD0_MAXFILESIZE) { 2322 - if ((buflen -= 8) < 0) 2391 + p = xdr_reserve_space(xdr, 8); 2392 + if (!p) 2323 2393 goto out_resource; 2324 - WRITE64(exp->ex_path.mnt->mnt_sb->s_maxbytes); 2394 + p = xdr_encode_hyper(p, exp->ex_path.mnt->mnt_sb->s_maxbytes); 2325 2395 } 2326 2396 if (bmval0 & FATTR4_WORD0_MAXLINK) { 2327 - if ((buflen -= 4) < 0) 2397 + p = xdr_reserve_space(xdr, 4); 2398 + if (!p) 2328 2399 goto out_resource; 2329 - WRITE32(255); 2400 + *p++ = cpu_to_be32(255); 2330 2401 } 2331 2402 if (bmval0 & FATTR4_WORD0_MAXNAME) { 2332 - if ((buflen -= 4) < 0) 2403 + p = xdr_reserve_space(xdr, 4); 2404 + if (!p) 2333 2405 goto out_resource; 2334 - WRITE32(statfs.f_namelen); 2406 + *p++ = cpu_to_be32(statfs.f_namelen); 2335 2407 } 2336 2408 if (bmval0 & FATTR4_WORD0_MAXREAD) { 2337 - if ((buflen -= 8) < 0) 2409 + p = xdr_reserve_space(xdr, 8); 2410 + if (!p) 2338 2411 goto out_resource; 2339 - WRITE64((u64) svc_max_payload(rqstp)); 2412 + p = xdr_encode_hyper(p, (u64) svc_max_payload(rqstp)); 2340 2413 } 2341 2414 if (bmval0 & FATTR4_WORD0_MAXWRITE) { 2342 - if ((buflen -= 8) < 0) 2415 + p = xdr_reserve_space(xdr, 8); 2416 + if (!p) 2343 2417 goto out_resource; 2344 - WRITE64((u64) svc_max_payload(rqstp)); 2418 + p = xdr_encode_hyper(p, (u64) svc_max_payload(rqstp)); 2345 2419 } 2346 2420 if (bmval1 & FATTR4_WORD1_MODE) { 2347 - if ((buflen -= 4) < 0) 2421 + p = xdr_reserve_space(xdr, 4); 2422 + if (!p) 2348 2423 goto out_resource; 2349 - WRITE32(stat.mode & S_IALLUGO); 2424 + *p++ = cpu_to_be32(stat.mode & S_IALLUGO); 2350 2425 } 2351 2426 if (bmval1 & FATTR4_WORD1_NO_TRUNC) { 2352 - if ((buflen -= 4) < 0) 2427 + p = xdr_reserve_space(xdr, 4); 2428 + if (!p) 2353 2429 goto out_resource; 2354 - WRITE32(1); 2430 + *p++ = cpu_to_be32(1); 2355 2431 } 2356 2432 if (bmval1 & FATTR4_WORD1_NUMLINKS) { 2357 - if ((buflen -= 4) < 0) 2433 + p = xdr_reserve_space(xdr, 4); 2434 + if (!p) 2358 2435 goto out_resource; 2359 - WRITE32(stat.nlink); 2436 + *p++ = cpu_to_be32(stat.nlink); 2360 2437 } 2361 2438 if (bmval1 & FATTR4_WORD1_OWNER) { 2362 - status = nfsd4_encode_user(rqstp, stat.uid, &p, &buflen); 2439 + status = nfsd4_encode_user(xdr, rqstp, stat.uid); 2363 2440 if (status) 2364 2441 goto out; 2365 2442 } 2366 2443 if (bmval1 & FATTR4_WORD1_OWNER_GROUP) { 2367 - status = nfsd4_encode_group(rqstp, stat.gid, &p, &buflen); 2444 + status = nfsd4_encode_group(xdr, rqstp, stat.gid); 2368 2445 if (status) 2369 2446 goto out; 2370 2447 } 2371 2448 if (bmval1 & FATTR4_WORD1_RAWDEV) { 2372 - if ((buflen -= 8) < 0) 2449 + p = xdr_reserve_space(xdr, 8); 2450 + if (!p) 2373 2451 goto out_resource; 2374 - WRITE32((u32) MAJOR(stat.rdev)); 2375 - WRITE32((u32) MINOR(stat.rdev)); 2452 + *p++ = cpu_to_be32((u32) MAJOR(stat.rdev)); 2453 + *p++ = cpu_to_be32((u32) MINOR(stat.rdev)); 2376 2454 } 2377 2455 if (bmval1 & FATTR4_WORD1_SPACE_AVAIL) { 2378 - if ((buflen -= 8) < 0) 2456 + p = xdr_reserve_space(xdr, 8); 2457 + if (!p) 2379 2458 goto out_resource; 2380 2459 dummy64 = (u64)statfs.f_bavail * (u64)statfs.f_bsize; 2381 - WRITE64(dummy64); 2460 + p = xdr_encode_hyper(p, dummy64); 2382 2461 } 2383 2462 if (bmval1 & FATTR4_WORD1_SPACE_FREE) { 2384 - if ((buflen -= 8) < 0) 2463 + p = xdr_reserve_space(xdr, 8); 2464 + if (!p) 2385 2465 goto out_resource; 2386 2466 dummy64 = (u64)statfs.f_bfree * (u64)statfs.f_bsize; 2387 - WRITE64(dummy64); 2467 + p = xdr_encode_hyper(p, dummy64); 2388 2468 } 2389 2469 if (bmval1 & FATTR4_WORD1_SPACE_TOTAL) { 2390 - if ((buflen -= 8) < 0) 2470 + p = xdr_reserve_space(xdr, 8); 2471 + if (!p) 2391 2472 goto out_resource; 2392 2473 dummy64 = (u64)statfs.f_blocks * (u64)statfs.f_bsize; 2393 - WRITE64(dummy64); 2474 + p = xdr_encode_hyper(p, dummy64); 2394 2475 } 2395 2476 if (bmval1 & FATTR4_WORD1_SPACE_USED) { 2396 - if ((buflen -= 8) < 0) 2477 + p = xdr_reserve_space(xdr, 8); 2478 + if (!p) 2397 2479 goto out_resource; 2398 2480 dummy64 = (u64)stat.blocks << 9; 2399 - WRITE64(dummy64); 2481 + p = xdr_encode_hyper(p, dummy64); 2400 2482 } 2401 2483 if (bmval1 & FATTR4_WORD1_TIME_ACCESS) { 2402 - if ((buflen -= 12) < 0) 2484 + p = xdr_reserve_space(xdr, 12); 2485 + if (!p) 2403 2486 goto out_resource; 2404 - WRITE64((s64)stat.atime.tv_sec); 2405 - WRITE32(stat.atime.tv_nsec); 2487 + p = xdr_encode_hyper(p, (s64)stat.atime.tv_sec); 2488 + *p++ = cpu_to_be32(stat.atime.tv_nsec); 2406 2489 } 2407 2490 if (bmval1 & FATTR4_WORD1_TIME_DELTA) { 2408 - if ((buflen -= 12) < 0) 2491 + p = xdr_reserve_space(xdr, 12); 2492 + if (!p) 2409 2493 goto out_resource; 2410 - WRITE32(0); 2411 - WRITE32(1); 2412 - WRITE32(0); 2494 + *p++ = cpu_to_be32(0); 2495 + *p++ = cpu_to_be32(1); 2496 + *p++ = cpu_to_be32(0); 2413 2497 } 2414 2498 if (bmval1 & FATTR4_WORD1_TIME_METADATA) { 2415 - if ((buflen -= 12) < 0) 2499 + p = xdr_reserve_space(xdr, 12); 2500 + if (!p) 2416 2501 goto out_resource; 2417 - WRITE64((s64)stat.ctime.tv_sec); 2418 - WRITE32(stat.ctime.tv_nsec); 2502 + p = xdr_encode_hyper(p, (s64)stat.ctime.tv_sec); 2503 + *p++ = cpu_to_be32(stat.ctime.tv_nsec); 2419 2504 } 2420 2505 if (bmval1 & FATTR4_WORD1_TIME_MODIFY) { 2421 - if ((buflen -= 12) < 0) 2506 + p = xdr_reserve_space(xdr, 12); 2507 + if (!p) 2422 2508 goto out_resource; 2423 - WRITE64((s64)stat.mtime.tv_sec); 2424 - WRITE32(stat.mtime.tv_nsec); 2509 + p = xdr_encode_hyper(p, (s64)stat.mtime.tv_sec); 2510 + *p++ = cpu_to_be32(stat.mtime.tv_nsec); 2425 2511 } 2426 2512 if (bmval1 & FATTR4_WORD1_MOUNTED_ON_FILEID) { 2427 - if ((buflen -= 8) < 0) 2513 + p = xdr_reserve_space(xdr, 8); 2514 + if (!p) 2428 2515 goto out_resource; 2429 2516 /* 2430 2517 * Get parent's attributes if not ignoring crossmount ··· 2480 2473 if (ignore_crossmnt == 0 && 2481 2474 dentry == exp->ex_path.mnt->mnt_root) 2482 2475 get_parent_attributes(exp, &stat); 2483 - WRITE64(stat.ino); 2476 + p = xdr_encode_hyper(p, stat.ino); 2484 2477 } 2485 2478 if (bmval2 & FATTR4_WORD2_SECURITY_LABEL) { 2486 - status = nfsd4_encode_security_label(rqstp, context, 2487 - contextlen, &p, &buflen); 2479 + status = nfsd4_encode_security_label(xdr, rqstp, context, 2480 + contextlen); 2488 2481 if (status) 2489 2482 goto out; 2490 2483 } 2491 2484 if (bmval2 & FATTR4_WORD2_SUPPATTR_EXCLCREAT) { 2492 - if ((buflen -= 16) < 0) 2485 + p = xdr_reserve_space(xdr, 16); 2486 + if (!p) 2493 2487 goto out_resource; 2494 - WRITE32(3); 2495 - WRITE32(NFSD_SUPPATTR_EXCLCREAT_WORD0); 2496 - WRITE32(NFSD_SUPPATTR_EXCLCREAT_WORD1); 2497 - WRITE32(NFSD_SUPPATTR_EXCLCREAT_WORD2); 2488 + *p++ = cpu_to_be32(3); 2489 + *p++ = cpu_to_be32(NFSD_SUPPATTR_EXCLCREAT_WORD0); 2490 + *p++ = cpu_to_be32(NFSD_SUPPATTR_EXCLCREAT_WORD1); 2491 + *p++ = cpu_to_be32(NFSD_SUPPATTR_EXCLCREAT_WORD2); 2498 2492 } 2499 2493 2500 - *attrlenp = htonl((char *)p - (char *)attrlenp - 4); 2501 - *buffer = p; 2494 + attrlen = htonl(xdr->buf->len - attrlen_offset - 4); 2495 + write_bytes_to_xdr_buf(xdr->buf, attrlen_offset, &attrlen, 4); 2502 2496 status = nfs_ok; 2503 2497 2504 2498 out: ··· 2512 2504 fh_put(tempfh); 2513 2505 kfree(tempfh); 2514 2506 } 2507 + if (status) 2508 + xdr_truncate_encode(xdr, starting_len); 2515 2509 return status; 2516 2510 out_nfserr: 2517 2511 status = nfserrno(err); ··· 2521 2511 out_resource: 2522 2512 status = nfserr_resource; 2523 2513 goto out; 2514 + } 2515 + 2516 + static void svcxdr_init_encode_from_buffer(struct xdr_stream *xdr, 2517 + struct xdr_buf *buf, __be32 *p, int bytes) 2518 + { 2519 + xdr->scratch.iov_len = 0; 2520 + memset(buf, 0, sizeof(struct xdr_buf)); 2521 + buf->head[0].iov_base = p; 2522 + buf->head[0].iov_len = 0; 2523 + buf->len = 0; 2524 + xdr->buf = buf; 2525 + xdr->iov = buf->head; 2526 + xdr->p = p; 2527 + xdr->end = (void *)p + bytes; 2528 + buf->buflen = bytes; 2529 + } 2530 + 2531 + __be32 nfsd4_encode_fattr_to_buf(__be32 **p, int words, 2532 + struct svc_fh *fhp, struct svc_export *exp, 2533 + struct dentry *dentry, u32 *bmval, 2534 + struct svc_rqst *rqstp, int ignore_crossmnt) 2535 + { 2536 + struct xdr_buf dummy; 2537 + struct xdr_stream xdr; 2538 + __be32 ret; 2539 + 2540 + svcxdr_init_encode_from_buffer(&xdr, &dummy, *p, words << 2); 2541 + ret = nfsd4_encode_fattr(&xdr, fhp, exp, dentry, bmval, rqstp, 2542 + ignore_crossmnt); 2543 + *p = xdr.p; 2544 + return ret; 2524 2545 } 2525 2546 2526 2547 static inline int attributes_need_mount(u32 *bmval) ··· 2564 2523 } 2565 2524 2566 2525 static __be32 2567 - nfsd4_encode_dirent_fattr(struct nfsd4_readdir *cd, 2568 - const char *name, int namlen, __be32 **p, int buflen) 2526 + nfsd4_encode_dirent_fattr(struct xdr_stream *xdr, struct nfsd4_readdir *cd, 2527 + const char *name, int namlen) 2569 2528 { 2570 2529 struct svc_export *exp = cd->rd_fhp->fh_export; 2571 2530 struct dentry *dentry; ··· 2617 2576 2618 2577 } 2619 2578 out_encode: 2620 - nfserr = nfsd4_encode_fattr(NULL, exp, dentry, p, buflen, cd->rd_bmval, 2579 + nfserr = nfsd4_encode_fattr(xdr, NULL, exp, dentry, cd->rd_bmval, 2621 2580 cd->rd_rqstp, ignore_crossmnt); 2622 2581 out_put: 2623 2582 dput(dentry); ··· 2626 2585 } 2627 2586 2628 2587 static __be32 * 2629 - nfsd4_encode_rdattr_error(__be32 *p, int buflen, __be32 nfserr) 2588 + nfsd4_encode_rdattr_error(struct xdr_stream *xdr, __be32 nfserr) 2630 2589 { 2631 - if (buflen < 6) 2590 + __be32 *p; 2591 + 2592 + p = xdr_reserve_space(xdr, 6); 2593 + if (!p) 2632 2594 return NULL; 2633 2595 *p++ = htonl(2); 2634 2596 *p++ = htonl(FATTR4_WORD0_RDATTR_ERROR); /* bmval0 */ ··· 2648 2604 { 2649 2605 struct readdir_cd *ccd = ccdv; 2650 2606 struct nfsd4_readdir *cd = container_of(ccd, struct nfsd4_readdir, common); 2651 - int buflen; 2652 - __be32 *p = cd->buffer; 2653 - __be32 *cookiep; 2607 + struct xdr_stream *xdr = cd->xdr; 2608 + int start_offset = xdr->buf->len; 2609 + int cookie_offset; 2610 + int entry_bytes; 2654 2611 __be32 nfserr = nfserr_toosmall; 2612 + __be64 wire_offset; 2613 + __be32 *p; 2655 2614 2656 2615 /* In nfsv4, "." and ".." never make it onto the wire.. */ 2657 2616 if (name && isdotent(name, namlen)) { ··· 2662 2615 return 0; 2663 2616 } 2664 2617 2665 - if (cd->offset) 2666 - xdr_encode_hyper(cd->offset, (u64) offset); 2618 + if (cd->cookie_offset) { 2619 + wire_offset = cpu_to_be64(offset); 2620 + write_bytes_to_xdr_buf(xdr->buf, cd->cookie_offset, 2621 + &wire_offset, 8); 2622 + } 2667 2623 2668 - buflen = cd->buflen - 4 - XDR_QUADLEN(namlen); 2669 - if (buflen < 0) 2624 + p = xdr_reserve_space(xdr, 4); 2625 + if (!p) 2670 2626 goto fail; 2671 - 2672 2627 *p++ = xdr_one; /* mark entry present */ 2673 - cookiep = p; 2628 + cookie_offset = xdr->buf->len; 2629 + p = xdr_reserve_space(xdr, 3*4 + namlen); 2630 + if (!p) 2631 + goto fail; 2674 2632 p = xdr_encode_hyper(p, NFS_OFFSET_MAX); /* offset of next entry */ 2675 2633 p = xdr_encode_array(p, name, namlen); /* name length & name */ 2676 2634 2677 - nfserr = nfsd4_encode_dirent_fattr(cd, name, namlen, &p, buflen); 2635 + nfserr = nfsd4_encode_dirent_fattr(xdr, cd, name, namlen); 2678 2636 switch (nfserr) { 2679 2637 case nfs_ok: 2680 2638 break; ··· 2698 2646 */ 2699 2647 if (!(cd->rd_bmval[0] & FATTR4_WORD0_RDATTR_ERROR)) 2700 2648 goto fail; 2701 - p = nfsd4_encode_rdattr_error(p, buflen, nfserr); 2649 + p = nfsd4_encode_rdattr_error(xdr, nfserr); 2702 2650 if (p == NULL) { 2703 2651 nfserr = nfserr_toosmall; 2704 2652 goto fail; 2705 2653 } 2706 2654 } 2707 - cd->buflen -= (p - cd->buffer); 2708 - cd->buffer = p; 2709 - cd->offset = cookiep; 2655 + nfserr = nfserr_toosmall; 2656 + entry_bytes = xdr->buf->len - start_offset; 2657 + if (entry_bytes > cd->rd_maxcount) 2658 + goto fail; 2659 + cd->rd_maxcount -= entry_bytes; 2660 + if (!cd->rd_dircount) 2661 + goto fail; 2662 + cd->rd_dircount--; 2663 + cd->cookie_offset = cookie_offset; 2710 2664 skip_entry: 2711 2665 cd->common.err = nfs_ok; 2712 2666 return 0; 2713 2667 fail: 2668 + xdr_truncate_encode(xdr, start_offset); 2714 2669 cd->common.err = nfserr; 2715 2670 return -EINVAL; 2716 2671 } 2717 2672 2718 - static void 2719 - nfsd4_encode_stateid(struct nfsd4_compoundres *resp, stateid_t *sid) 2673 + static __be32 2674 + nfsd4_encode_stateid(struct xdr_stream *xdr, stateid_t *sid) 2720 2675 { 2721 2676 __be32 *p; 2722 2677 2723 - RESERVE_SPACE(sizeof(stateid_t)); 2724 - WRITE32(sid->si_generation); 2725 - WRITEMEM(&sid->si_opaque, sizeof(stateid_opaque_t)); 2726 - ADJUST_ARGS(); 2678 + p = xdr_reserve_space(xdr, sizeof(stateid_t)); 2679 + if (!p) 2680 + return nfserr_resource; 2681 + *p++ = cpu_to_be32(sid->si_generation); 2682 + p = xdr_encode_opaque_fixed(p, &sid->si_opaque, 2683 + sizeof(stateid_opaque_t)); 2684 + return 0; 2727 2685 } 2728 2686 2729 2687 static __be32 2730 2688 nfsd4_encode_access(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_access *access) 2731 2689 { 2690 + struct xdr_stream *xdr = &resp->xdr; 2732 2691 __be32 *p; 2733 2692 2734 2693 if (!nfserr) { 2735 - RESERVE_SPACE(8); 2736 - WRITE32(access->ac_supported); 2737 - WRITE32(access->ac_resp_access); 2738 - ADJUST_ARGS(); 2694 + p = xdr_reserve_space(xdr, 8); 2695 + if (!p) 2696 + return nfserr_resource; 2697 + *p++ = cpu_to_be32(access->ac_supported); 2698 + *p++ = cpu_to_be32(access->ac_resp_access); 2739 2699 } 2740 2700 return nfserr; 2741 2701 } 2742 2702 2743 2703 static __be32 nfsd4_encode_bind_conn_to_session(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_bind_conn_to_session *bcts) 2744 2704 { 2705 + struct xdr_stream *xdr = &resp->xdr; 2745 2706 __be32 *p; 2746 2707 2747 2708 if (!nfserr) { 2748 - RESERVE_SPACE(NFS4_MAX_SESSIONID_LEN + 8); 2749 - WRITEMEM(bcts->sessionid.data, NFS4_MAX_SESSIONID_LEN); 2750 - WRITE32(bcts->dir); 2709 + p = xdr_reserve_space(xdr, NFS4_MAX_SESSIONID_LEN + 8); 2710 + if (!p) 2711 + return nfserr_resource; 2712 + p = xdr_encode_opaque_fixed(p, bcts->sessionid.data, 2713 + NFS4_MAX_SESSIONID_LEN); 2714 + *p++ = cpu_to_be32(bcts->dir); 2751 2715 /* Sorry, we do not yet support RDMA over 4.1: */ 2752 - WRITE32(0); 2753 - ADJUST_ARGS(); 2716 + *p++ = cpu_to_be32(0); 2754 2717 } 2755 2718 return nfserr; 2756 2719 } ··· 2773 2706 static __be32 2774 2707 nfsd4_encode_close(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_close *close) 2775 2708 { 2709 + struct xdr_stream *xdr = &resp->xdr; 2710 + 2776 2711 if (!nfserr) 2777 - nfsd4_encode_stateid(resp, &close->cl_stateid); 2712 + nfserr = nfsd4_encode_stateid(xdr, &close->cl_stateid); 2778 2713 2779 2714 return nfserr; 2780 2715 } ··· 2785 2716 static __be32 2786 2717 nfsd4_encode_commit(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_commit *commit) 2787 2718 { 2719 + struct xdr_stream *xdr = &resp->xdr; 2788 2720 __be32 *p; 2789 2721 2790 2722 if (!nfserr) { 2791 - RESERVE_SPACE(NFS4_VERIFIER_SIZE); 2792 - WRITEMEM(commit->co_verf.data, NFS4_VERIFIER_SIZE); 2793 - ADJUST_ARGS(); 2723 + p = xdr_reserve_space(xdr, NFS4_VERIFIER_SIZE); 2724 + if (!p) 2725 + return nfserr_resource; 2726 + p = xdr_encode_opaque_fixed(p, commit->co_verf.data, 2727 + NFS4_VERIFIER_SIZE); 2794 2728 } 2795 2729 return nfserr; 2796 2730 } ··· 2801 2729 static __be32 2802 2730 nfsd4_encode_create(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_create *create) 2803 2731 { 2732 + struct xdr_stream *xdr = &resp->xdr; 2804 2733 __be32 *p; 2805 2734 2806 2735 if (!nfserr) { 2807 - RESERVE_SPACE(32); 2808 - write_cinfo(&p, &create->cr_cinfo); 2809 - WRITE32(2); 2810 - WRITE32(create->cr_bmval[0]); 2811 - WRITE32(create->cr_bmval[1]); 2812 - ADJUST_ARGS(); 2736 + p = xdr_reserve_space(xdr, 32); 2737 + if (!p) 2738 + return nfserr_resource; 2739 + p = encode_cinfo(p, &create->cr_cinfo); 2740 + *p++ = cpu_to_be32(2); 2741 + *p++ = cpu_to_be32(create->cr_bmval[0]); 2742 + *p++ = cpu_to_be32(create->cr_bmval[1]); 2813 2743 } 2814 2744 return nfserr; 2815 2745 } ··· 2820 2746 nfsd4_encode_getattr(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_getattr *getattr) 2821 2747 { 2822 2748 struct svc_fh *fhp = getattr->ga_fhp; 2823 - int buflen; 2749 + struct xdr_stream *xdr = &resp->xdr; 2824 2750 2825 2751 if (nfserr) 2826 2752 return nfserr; 2827 2753 2828 - buflen = resp->end - resp->p - (COMPOUND_ERR_SLACK_SPACE >> 2); 2829 - nfserr = nfsd4_encode_fattr(fhp, fhp->fh_export, fhp->fh_dentry, 2830 - &resp->p, buflen, getattr->ga_bmval, 2754 + nfserr = nfsd4_encode_fattr(xdr, fhp, fhp->fh_export, fhp->fh_dentry, 2755 + getattr->ga_bmval, 2831 2756 resp->rqstp, 0); 2832 2757 return nfserr; 2833 2758 } ··· 2834 2761 static __be32 2835 2762 nfsd4_encode_getfh(struct nfsd4_compoundres *resp, __be32 nfserr, struct svc_fh **fhpp) 2836 2763 { 2764 + struct xdr_stream *xdr = &resp->xdr; 2837 2765 struct svc_fh *fhp = *fhpp; 2838 2766 unsigned int len; 2839 2767 __be32 *p; 2840 2768 2841 2769 if (!nfserr) { 2842 2770 len = fhp->fh_handle.fh_size; 2843 - RESERVE_SPACE(len + 4); 2844 - WRITE32(len); 2845 - WRITEMEM(&fhp->fh_handle.fh_base, len); 2846 - ADJUST_ARGS(); 2771 + p = xdr_reserve_space(xdr, len + 4); 2772 + if (!p) 2773 + return nfserr_resource; 2774 + p = xdr_encode_opaque(p, &fhp->fh_handle.fh_base, len); 2847 2775 } 2848 2776 return nfserr; 2849 2777 } ··· 2853 2779 * Including all fields other than the name, a LOCK4denied structure requires 2854 2780 * 8(clientid) + 4(namelen) + 8(offset) + 8(length) + 4(type) = 32 bytes. 2855 2781 */ 2856 - static void 2857 - nfsd4_encode_lock_denied(struct nfsd4_compoundres *resp, struct nfsd4_lock_denied *ld) 2782 + static __be32 2783 + nfsd4_encode_lock_denied(struct xdr_stream *xdr, struct nfsd4_lock_denied *ld) 2858 2784 { 2859 2785 struct xdr_netobj *conf = &ld->ld_owner; 2860 2786 __be32 *p; 2861 2787 2862 - RESERVE_SPACE(32 + XDR_LEN(conf->len)); 2863 - WRITE64(ld->ld_start); 2864 - WRITE64(ld->ld_length); 2865 - WRITE32(ld->ld_type); 2866 - if (conf->len) { 2867 - WRITEMEM(&ld->ld_clientid, 8); 2868 - WRITE32(conf->len); 2869 - WRITEMEM(conf->data, conf->len); 2870 - kfree(conf->data); 2871 - } else { /* non - nfsv4 lock in conflict, no clientid nor owner */ 2872 - WRITE64((u64)0); /* clientid */ 2873 - WRITE32(0); /* length of owner name */ 2788 + again: 2789 + p = xdr_reserve_space(xdr, 32 + XDR_LEN(conf->len)); 2790 + if (!p) { 2791 + /* 2792 + * Don't fail to return the result just because we can't 2793 + * return the conflicting open: 2794 + */ 2795 + if (conf->len) { 2796 + conf->len = 0; 2797 + conf->data = NULL; 2798 + goto again; 2799 + } 2800 + return nfserr_resource; 2874 2801 } 2875 - ADJUST_ARGS(); 2802 + p = xdr_encode_hyper(p, ld->ld_start); 2803 + p = xdr_encode_hyper(p, ld->ld_length); 2804 + *p++ = cpu_to_be32(ld->ld_type); 2805 + if (conf->len) { 2806 + p = xdr_encode_opaque_fixed(p, &ld->ld_clientid, 8); 2807 + p = xdr_encode_opaque(p, conf->data, conf->len); 2808 + } else { /* non - nfsv4 lock in conflict, no clientid nor owner */ 2809 + p = xdr_encode_hyper(p, (u64)0); /* clientid */ 2810 + *p++ = cpu_to_be32(0); /* length of owner name */ 2811 + } 2812 + return nfserr_denied; 2876 2813 } 2877 2814 2878 2815 static __be32 2879 2816 nfsd4_encode_lock(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_lock *lock) 2880 2817 { 2881 - if (!nfserr) 2882 - nfsd4_encode_stateid(resp, &lock->lk_resp_stateid); 2883 - else if (nfserr == nfserr_denied) 2884 - nfsd4_encode_lock_denied(resp, &lock->lk_denied); 2818 + struct xdr_stream *xdr = &resp->xdr; 2885 2819 2820 + if (!nfserr) 2821 + nfserr = nfsd4_encode_stateid(xdr, &lock->lk_resp_stateid); 2822 + else if (nfserr == nfserr_denied) 2823 + nfserr = nfsd4_encode_lock_denied(xdr, &lock->lk_denied); 2824 + kfree(lock->lk_denied.ld_owner.data); 2886 2825 return nfserr; 2887 2826 } 2888 2827 2889 2828 static __be32 2890 2829 nfsd4_encode_lockt(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_lockt *lockt) 2891 2830 { 2831 + struct xdr_stream *xdr = &resp->xdr; 2832 + 2892 2833 if (nfserr == nfserr_denied) 2893 - nfsd4_encode_lock_denied(resp, &lockt->lt_denied); 2834 + nfsd4_encode_lock_denied(xdr, &lockt->lt_denied); 2894 2835 return nfserr; 2895 2836 } 2896 2837 2897 2838 static __be32 2898 2839 nfsd4_encode_locku(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_locku *locku) 2899 2840 { 2841 + struct xdr_stream *xdr = &resp->xdr; 2842 + 2900 2843 if (!nfserr) 2901 - nfsd4_encode_stateid(resp, &locku->lu_stateid); 2844 + nfserr = nfsd4_encode_stateid(xdr, &locku->lu_stateid); 2902 2845 2903 2846 return nfserr; 2904 2847 } ··· 2924 2833 static __be32 2925 2834 nfsd4_encode_link(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_link *link) 2926 2835 { 2836 + struct xdr_stream *xdr = &resp->xdr; 2927 2837 __be32 *p; 2928 2838 2929 2839 if (!nfserr) { 2930 - RESERVE_SPACE(20); 2931 - write_cinfo(&p, &link->li_cinfo); 2932 - ADJUST_ARGS(); 2840 + p = xdr_reserve_space(xdr, 20); 2841 + if (!p) 2842 + return nfserr_resource; 2843 + p = encode_cinfo(p, &link->li_cinfo); 2933 2844 } 2934 2845 return nfserr; 2935 2846 } ··· 2940 2847 static __be32 2941 2848 nfsd4_encode_open(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_open *open) 2942 2849 { 2850 + struct xdr_stream *xdr = &resp->xdr; 2943 2851 __be32 *p; 2944 2852 2945 2853 if (nfserr) 2946 2854 goto out; 2947 2855 2948 - nfsd4_encode_stateid(resp, &open->op_stateid); 2949 - RESERVE_SPACE(40); 2950 - write_cinfo(&p, &open->op_cinfo); 2951 - WRITE32(open->op_rflags); 2952 - WRITE32(2); 2953 - WRITE32(open->op_bmval[0]); 2954 - WRITE32(open->op_bmval[1]); 2955 - WRITE32(open->op_delegate_type); 2956 - ADJUST_ARGS(); 2856 + nfserr = nfsd4_encode_stateid(xdr, &open->op_stateid); 2857 + if (nfserr) 2858 + goto out; 2859 + p = xdr_reserve_space(xdr, 40); 2860 + if (!p) 2861 + return nfserr_resource; 2862 + p = encode_cinfo(p, &open->op_cinfo); 2863 + *p++ = cpu_to_be32(open->op_rflags); 2864 + *p++ = cpu_to_be32(2); 2865 + *p++ = cpu_to_be32(open->op_bmval[0]); 2866 + *p++ = cpu_to_be32(open->op_bmval[1]); 2867 + *p++ = cpu_to_be32(open->op_delegate_type); 2957 2868 2958 2869 switch (open->op_delegate_type) { 2959 2870 case NFS4_OPEN_DELEGATE_NONE: 2960 2871 break; 2961 2872 case NFS4_OPEN_DELEGATE_READ: 2962 - nfsd4_encode_stateid(resp, &open->op_delegate_stateid); 2963 - RESERVE_SPACE(20); 2964 - WRITE32(open->op_recall); 2873 + nfserr = nfsd4_encode_stateid(xdr, &open->op_delegate_stateid); 2874 + if (nfserr) 2875 + return nfserr; 2876 + p = xdr_reserve_space(xdr, 20); 2877 + if (!p) 2878 + return nfserr_resource; 2879 + *p++ = cpu_to_be32(open->op_recall); 2965 2880 2966 2881 /* 2967 2882 * TODO: ACE's in delegations 2968 2883 */ 2969 - WRITE32(NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE); 2970 - WRITE32(0); 2971 - WRITE32(0); 2972 - WRITE32(0); /* XXX: is NULL principal ok? */ 2973 - ADJUST_ARGS(); 2884 + *p++ = cpu_to_be32(NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE); 2885 + *p++ = cpu_to_be32(0); 2886 + *p++ = cpu_to_be32(0); 2887 + *p++ = cpu_to_be32(0); /* XXX: is NULL principal ok? */ 2974 2888 break; 2975 2889 case NFS4_OPEN_DELEGATE_WRITE: 2976 - nfsd4_encode_stateid(resp, &open->op_delegate_stateid); 2977 - RESERVE_SPACE(32); 2978 - WRITE32(0); 2890 + nfserr = nfsd4_encode_stateid(xdr, &open->op_delegate_stateid); 2891 + if (nfserr) 2892 + return nfserr; 2893 + p = xdr_reserve_space(xdr, 32); 2894 + if (!p) 2895 + return nfserr_resource; 2896 + *p++ = cpu_to_be32(0); 2979 2897 2980 2898 /* 2981 2899 * TODO: space_limit's in delegations 2982 2900 */ 2983 - WRITE32(NFS4_LIMIT_SIZE); 2984 - WRITE32(~(u32)0); 2985 - WRITE32(~(u32)0); 2901 + *p++ = cpu_to_be32(NFS4_LIMIT_SIZE); 2902 + *p++ = cpu_to_be32(~(u32)0); 2903 + *p++ = cpu_to_be32(~(u32)0); 2986 2904 2987 2905 /* 2988 2906 * TODO: ACE's in delegations 2989 2907 */ 2990 - WRITE32(NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE); 2991 - WRITE32(0); 2992 - WRITE32(0); 2993 - WRITE32(0); /* XXX: is NULL principal ok? */ 2994 - ADJUST_ARGS(); 2908 + *p++ = cpu_to_be32(NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE); 2909 + *p++ = cpu_to_be32(0); 2910 + *p++ = cpu_to_be32(0); 2911 + *p++ = cpu_to_be32(0); /* XXX: is NULL principal ok? */ 2995 2912 break; 2996 2913 case NFS4_OPEN_DELEGATE_NONE_EXT: /* 4.1 */ 2997 2914 switch (open->op_why_no_deleg) { 2998 2915 case WND4_CONTENTION: 2999 2916 case WND4_RESOURCE: 3000 - RESERVE_SPACE(8); 3001 - WRITE32(open->op_why_no_deleg); 3002 - WRITE32(0); /* deleg signaling not supported yet */ 2917 + p = xdr_reserve_space(xdr, 8); 2918 + if (!p) 2919 + return nfserr_resource; 2920 + *p++ = cpu_to_be32(open->op_why_no_deleg); 2921 + /* deleg signaling not supported yet: */ 2922 + *p++ = cpu_to_be32(0); 3003 2923 break; 3004 2924 default: 3005 - RESERVE_SPACE(4); 3006 - WRITE32(open->op_why_no_deleg); 2925 + p = xdr_reserve_space(xdr, 4); 2926 + if (!p) 2927 + return nfserr_resource; 2928 + *p++ = cpu_to_be32(open->op_why_no_deleg); 3007 2929 } 3008 - ADJUST_ARGS(); 3009 2930 break; 3010 2931 default: 3011 2932 BUG(); ··· 3032 2925 static __be32 3033 2926 nfsd4_encode_open_confirm(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_open_confirm *oc) 3034 2927 { 2928 + struct xdr_stream *xdr = &resp->xdr; 2929 + 3035 2930 if (!nfserr) 3036 - nfsd4_encode_stateid(resp, &oc->oc_resp_stateid); 2931 + nfserr = nfsd4_encode_stateid(xdr, &oc->oc_resp_stateid); 3037 2932 3038 2933 return nfserr; 3039 2934 } ··· 3043 2934 static __be32 3044 2935 nfsd4_encode_open_downgrade(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_open_downgrade *od) 3045 2936 { 2937 + struct xdr_stream *xdr = &resp->xdr; 2938 + 3046 2939 if (!nfserr) 3047 - nfsd4_encode_stateid(resp, &od->od_stateid); 2940 + nfserr = nfsd4_encode_stateid(xdr, &od->od_stateid); 3048 2941 3049 2942 return nfserr; 2943 + } 2944 + 2945 + static __be32 nfsd4_encode_splice_read( 2946 + struct nfsd4_compoundres *resp, 2947 + struct nfsd4_read *read, 2948 + struct file *file, unsigned long maxcount) 2949 + { 2950 + struct xdr_stream *xdr = &resp->xdr; 2951 + struct xdr_buf *buf = xdr->buf; 2952 + u32 eof; 2953 + int space_left; 2954 + __be32 nfserr; 2955 + __be32 *p = xdr->p - 2; 2956 + 2957 + /* 2958 + * Don't inline pages unless we know there's room for eof, 2959 + * count, and possible padding: 2960 + */ 2961 + if (xdr->end - xdr->p < 3) 2962 + return nfserr_resource; 2963 + 2964 + nfserr = nfsd_splice_read(read->rd_rqstp, file, 2965 + read->rd_offset, &maxcount); 2966 + if (nfserr) { 2967 + /* 2968 + * nfsd_splice_actor may have already messed with the 2969 + * page length; reset it so as not to confuse 2970 + * xdr_truncate_encode: 2971 + */ 2972 + buf->page_len = 0; 2973 + return nfserr; 2974 + } 2975 + 2976 + eof = (read->rd_offset + maxcount >= 2977 + read->rd_fhp->fh_dentry->d_inode->i_size); 2978 + 2979 + *(p++) = htonl(eof); 2980 + *(p++) = htonl(maxcount); 2981 + 2982 + buf->page_len = maxcount; 2983 + buf->len += maxcount; 2984 + xdr->page_ptr += (maxcount + PAGE_SIZE - 1) / PAGE_SIZE; 2985 + 2986 + /* Use rest of head for padding and remaining ops: */ 2987 + buf->tail[0].iov_base = xdr->p; 2988 + buf->tail[0].iov_len = 0; 2989 + xdr->iov = buf->tail; 2990 + if (maxcount&3) { 2991 + int pad = 4 - (maxcount&3); 2992 + 2993 + *(xdr->p++) = 0; 2994 + 2995 + buf->tail[0].iov_base += maxcount&3; 2996 + buf->tail[0].iov_len = pad; 2997 + buf->len += pad; 2998 + } 2999 + 3000 + space_left = min_t(int, (void *)xdr->end - (void *)xdr->p, 3001 + buf->buflen - buf->len); 3002 + buf->buflen = buf->len + space_left; 3003 + xdr->end = (__be32 *)((void *)xdr->end + space_left); 3004 + 3005 + return 0; 3006 + } 3007 + 3008 + static __be32 nfsd4_encode_readv(struct nfsd4_compoundres *resp, 3009 + struct nfsd4_read *read, 3010 + struct file *file, unsigned long maxcount) 3011 + { 3012 + struct xdr_stream *xdr = &resp->xdr; 3013 + u32 eof; 3014 + int v; 3015 + int starting_len = xdr->buf->len - 8; 3016 + long len; 3017 + int thislen; 3018 + __be32 nfserr; 3019 + __be32 tmp; 3020 + __be32 *p; 3021 + u32 zzz = 0; 3022 + int pad; 3023 + 3024 + len = maxcount; 3025 + v = 0; 3026 + 3027 + thislen = (void *)xdr->end - (void *)xdr->p; 3028 + if (len < thislen) 3029 + thislen = len; 3030 + p = xdr_reserve_space(xdr, (thislen+3)&~3); 3031 + WARN_ON_ONCE(!p); 3032 + resp->rqstp->rq_vec[v].iov_base = p; 3033 + resp->rqstp->rq_vec[v].iov_len = thislen; 3034 + v++; 3035 + len -= thislen; 3036 + 3037 + while (len) { 3038 + thislen = min_t(long, len, PAGE_SIZE); 3039 + p = xdr_reserve_space(xdr, (thislen+3)&~3); 3040 + WARN_ON_ONCE(!p); 3041 + resp->rqstp->rq_vec[v].iov_base = p; 3042 + resp->rqstp->rq_vec[v].iov_len = thislen; 3043 + v++; 3044 + len -= thislen; 3045 + } 3046 + read->rd_vlen = v; 3047 + 3048 + nfserr = nfsd_readv(file, read->rd_offset, resp->rqstp->rq_vec, 3049 + read->rd_vlen, &maxcount); 3050 + if (nfserr) 3051 + return nfserr; 3052 + xdr_truncate_encode(xdr, starting_len + 8 + ((maxcount+3)&~3)); 3053 + 3054 + eof = (read->rd_offset + maxcount >= 3055 + read->rd_fhp->fh_dentry->d_inode->i_size); 3056 + 3057 + tmp = htonl(eof); 3058 + write_bytes_to_xdr_buf(xdr->buf, starting_len , &tmp, 4); 3059 + tmp = htonl(maxcount); 3060 + write_bytes_to_xdr_buf(xdr->buf, starting_len + 4, &tmp, 4); 3061 + 3062 + pad = (maxcount&3) ? 4 - (maxcount&3) : 0; 3063 + write_bytes_to_xdr_buf(xdr->buf, starting_len + 8 + maxcount, 3064 + &zzz, pad); 3065 + return 0; 3066 + 3050 3067 } 3051 3068 3052 3069 static __be32 3053 3070 nfsd4_encode_read(struct nfsd4_compoundres *resp, __be32 nfserr, 3054 3071 struct nfsd4_read *read) 3055 3072 { 3056 - u32 eof; 3057 - int v; 3058 - struct page *page; 3059 - unsigned long maxcount; 3060 - long len; 3073 + unsigned long maxcount; 3074 + struct xdr_stream *xdr = &resp->xdr; 3075 + struct file *file = read->rd_filp; 3076 + int starting_len = xdr->buf->len; 3077 + struct raparms *ra; 3061 3078 __be32 *p; 3079 + __be32 err; 3062 3080 3063 3081 if (nfserr) 3064 3082 return nfserr; 3065 - if (resp->xbuf->page_len) 3066 - return nfserr_resource; 3067 3083 3068 - RESERVE_SPACE(8); /* eof flag and byte count */ 3084 + p = xdr_reserve_space(xdr, 8); /* eof flag and byte count */ 3085 + if (!p) { 3086 + WARN_ON_ONCE(resp->rqstp->rq_splice_ok); 3087 + return nfserr_resource; 3088 + } 3089 + if (resp->xdr.buf->page_len && resp->rqstp->rq_splice_ok) { 3090 + WARN_ON_ONCE(1); 3091 + return nfserr_resource; 3092 + } 3093 + xdr_commit_encode(xdr); 3069 3094 3070 3095 maxcount = svc_max_payload(resp->rqstp); 3096 + if (maxcount > xdr->buf->buflen - xdr->buf->len) 3097 + maxcount = xdr->buf->buflen - xdr->buf->len; 3071 3098 if (maxcount > read->rd_length) 3072 3099 maxcount = read->rd_length; 3073 3100 3074 - len = maxcount; 3075 - v = 0; 3076 - while (len > 0) { 3077 - page = *(resp->rqstp->rq_next_page); 3078 - if (!page) { /* ran out of pages */ 3079 - maxcount -= len; 3080 - break; 3081 - } 3082 - resp->rqstp->rq_vec[v].iov_base = page_address(page); 3083 - resp->rqstp->rq_vec[v].iov_len = 3084 - len < PAGE_SIZE ? len : PAGE_SIZE; 3085 - resp->rqstp->rq_next_page++; 3086 - v++; 3087 - len -= PAGE_SIZE; 3101 + if (!read->rd_filp) { 3102 + err = nfsd_get_tmp_read_open(resp->rqstp, read->rd_fhp, 3103 + &file, &ra); 3104 + if (err) 3105 + goto err_truncate; 3088 3106 } 3089 - read->rd_vlen = v; 3090 3107 3091 - nfserr = nfsd_read_file(read->rd_rqstp, read->rd_fhp, read->rd_filp, 3092 - read->rd_offset, resp->rqstp->rq_vec, read->rd_vlen, 3093 - &maxcount); 3108 + if (file->f_op->splice_read && resp->rqstp->rq_splice_ok) 3109 + err = nfsd4_encode_splice_read(resp, read, file, maxcount); 3110 + else 3111 + err = nfsd4_encode_readv(resp, read, file, maxcount); 3094 3112 3095 - if (nfserr) 3096 - return nfserr; 3097 - eof = (read->rd_offset + maxcount >= 3098 - read->rd_fhp->fh_dentry->d_inode->i_size); 3113 + if (!read->rd_filp) 3114 + nfsd_put_tmp_read_open(file, ra); 3099 3115 3100 - WRITE32(eof); 3101 - WRITE32(maxcount); 3102 - ADJUST_ARGS(); 3103 - resp->xbuf->head[0].iov_len = (char*)p 3104 - - (char*)resp->xbuf->head[0].iov_base; 3105 - resp->xbuf->page_len = maxcount; 3106 - 3107 - /* Use rest of head for padding and remaining ops: */ 3108 - resp->xbuf->tail[0].iov_base = p; 3109 - resp->xbuf->tail[0].iov_len = 0; 3110 - if (maxcount&3) { 3111 - RESERVE_SPACE(4); 3112 - WRITE32(0); 3113 - resp->xbuf->tail[0].iov_base += maxcount&3; 3114 - resp->xbuf->tail[0].iov_len = 4 - (maxcount&3); 3115 - ADJUST_ARGS(); 3116 - } 3117 - return 0; 3116 + err_truncate: 3117 + if (err) 3118 + xdr_truncate_encode(xdr, starting_len); 3119 + return err; 3118 3120 } 3119 3121 3120 3122 static __be32 3121 3123 nfsd4_encode_readlink(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_readlink *readlink) 3122 3124 { 3123 3125 int maxcount; 3124 - char *page; 3126 + __be32 wire_count; 3127 + int zero = 0; 3128 + struct xdr_stream *xdr = &resp->xdr; 3129 + int length_offset = xdr->buf->len; 3125 3130 __be32 *p; 3126 3131 3127 3132 if (nfserr) 3128 3133 return nfserr; 3129 - if (resp->xbuf->page_len) 3130 - return nfserr_resource; 3131 - if (!*resp->rqstp->rq_next_page) 3132 - return nfserr_resource; 3133 3134 3134 - page = page_address(*(resp->rqstp->rq_next_page++)); 3135 - 3135 + p = xdr_reserve_space(xdr, 4); 3136 + if (!p) 3137 + return nfserr_resource; 3136 3138 maxcount = PAGE_SIZE; 3137 - RESERVE_SPACE(4); 3138 3139 3140 + p = xdr_reserve_space(xdr, maxcount); 3141 + if (!p) 3142 + return nfserr_resource; 3139 3143 /* 3140 3144 * XXX: By default, the ->readlink() VFS op will truncate symlinks 3141 3145 * if they would overflow the buffer. Is this kosher in NFSv4? If 3142 3146 * not, one easy fix is: if ->readlink() precisely fills the buffer, 3143 3147 * assume that truncation occurred, and return NFS4ERR_RESOURCE. 3144 3148 */ 3145 - nfserr = nfsd_readlink(readlink->rl_rqstp, readlink->rl_fhp, page, &maxcount); 3149 + nfserr = nfsd_readlink(readlink->rl_rqstp, readlink->rl_fhp, 3150 + (char *)p, &maxcount); 3146 3151 if (nfserr == nfserr_isdir) 3147 - return nfserr_inval; 3148 - if (nfserr) 3152 + nfserr = nfserr_inval; 3153 + if (nfserr) { 3154 + xdr_truncate_encode(xdr, length_offset); 3149 3155 return nfserr; 3150 - 3151 - WRITE32(maxcount); 3152 - ADJUST_ARGS(); 3153 - resp->xbuf->head[0].iov_len = (char*)p 3154 - - (char*)resp->xbuf->head[0].iov_base; 3155 - resp->xbuf->page_len = maxcount; 3156 - 3157 - /* Use rest of head for padding and remaining ops: */ 3158 - resp->xbuf->tail[0].iov_base = p; 3159 - resp->xbuf->tail[0].iov_len = 0; 3160 - if (maxcount&3) { 3161 - RESERVE_SPACE(4); 3162 - WRITE32(0); 3163 - resp->xbuf->tail[0].iov_base += maxcount&3; 3164 - resp->xbuf->tail[0].iov_len = 4 - (maxcount&3); 3165 - ADJUST_ARGS(); 3166 3156 } 3157 + 3158 + wire_count = htonl(maxcount); 3159 + write_bytes_to_xdr_buf(xdr->buf, length_offset, &wire_count, 4); 3160 + xdr_truncate_encode(xdr, length_offset + 4 + maxcount); 3161 + if (maxcount & 3) 3162 + write_bytes_to_xdr_buf(xdr->buf, length_offset + 4 + maxcount, 3163 + &zero, 4 - (maxcount&3)); 3167 3164 return 0; 3168 3165 } 3169 3166 ··· 3277 3062 nfsd4_encode_readdir(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_readdir *readdir) 3278 3063 { 3279 3064 int maxcount; 3065 + int bytes_left; 3280 3066 loff_t offset; 3281 - __be32 *page, *savep, *tailbase; 3067 + __be64 wire_offset; 3068 + struct xdr_stream *xdr = &resp->xdr; 3069 + int starting_len = xdr->buf->len; 3282 3070 __be32 *p; 3283 3071 3284 3072 if (nfserr) 3285 3073 return nfserr; 3286 - if (resp->xbuf->page_len) 3287 - return nfserr_resource; 3288 - if (!*resp->rqstp->rq_next_page) 3289 - return nfserr_resource; 3290 3074 3291 - RESERVE_SPACE(NFS4_VERIFIER_SIZE); 3292 - savep = p; 3075 + p = xdr_reserve_space(xdr, NFS4_VERIFIER_SIZE); 3076 + if (!p) 3077 + return nfserr_resource; 3293 3078 3294 3079 /* XXX: Following NFSv3, we ignore the READDIR verifier for now. */ 3295 - WRITE32(0); 3296 - WRITE32(0); 3297 - ADJUST_ARGS(); 3298 - resp->xbuf->head[0].iov_len = ((char*)resp->p) - (char*)resp->xbuf->head[0].iov_base; 3299 - tailbase = p; 3300 - 3301 - maxcount = PAGE_SIZE; 3302 - if (maxcount > readdir->rd_maxcount) 3303 - maxcount = readdir->rd_maxcount; 3080 + *p++ = cpu_to_be32(0); 3081 + *p++ = cpu_to_be32(0); 3082 + resp->xdr.buf->head[0].iov_len = ((char *)resp->xdr.p) 3083 + - (char *)resp->xdr.buf->head[0].iov_base; 3304 3084 3305 3085 /* 3306 - * Convert from bytes to words, account for the two words already 3307 - * written, make sure to leave two words at the end for the next 3308 - * pointer and eof field. 3086 + * Number of bytes left for directory entries allowing for the 3087 + * final 8 bytes of the readdir and a following failed op: 3309 3088 */ 3310 - maxcount = (maxcount >> 2) - 4; 3311 - if (maxcount < 0) { 3312 - nfserr = nfserr_toosmall; 3089 + bytes_left = xdr->buf->buflen - xdr->buf->len 3090 + - COMPOUND_ERR_SLACK_SPACE - 8; 3091 + if (bytes_left < 0) { 3092 + nfserr = nfserr_resource; 3313 3093 goto err_no_verf; 3314 3094 } 3095 + maxcount = min_t(u32, readdir->rd_maxcount, INT_MAX); 3096 + /* 3097 + * Note the rfc defines rd_maxcount as the size of the 3098 + * READDIR4resok structure, which includes the verifier above 3099 + * and the 8 bytes encoded at the end of this function: 3100 + */ 3101 + if (maxcount < 16) { 3102 + nfserr = nfserr_toosmall; 3103 + goto err_no_verf; 3104 + } 3105 + maxcount = min_t(int, maxcount-16, bytes_left); 3315 3106 3316 - page = page_address(*(resp->rqstp->rq_next_page++)); 3107 + readdir->xdr = xdr; 3108 + readdir->rd_maxcount = maxcount; 3317 3109 readdir->common.err = 0; 3318 - readdir->buflen = maxcount; 3319 - readdir->buffer = page; 3320 - readdir->offset = NULL; 3110 + readdir->cookie_offset = 0; 3321 3111 3322 3112 offset = readdir->rd_cookie; 3323 3113 nfserr = nfsd_readdir(readdir->rd_rqstp, readdir->rd_fhp, ··· 3330 3110 &readdir->common, nfsd4_encode_dirent); 3331 3111 if (nfserr == nfs_ok && 3332 3112 readdir->common.err == nfserr_toosmall && 3333 - readdir->buffer == page) 3334 - nfserr = nfserr_toosmall; 3113 + xdr->buf->len == starting_len + 8) { 3114 + /* nothing encoded; which limit did we hit?: */ 3115 + if (maxcount - 16 < bytes_left) 3116 + /* It was the fault of rd_maxcount: */ 3117 + nfserr = nfserr_toosmall; 3118 + else 3119 + /* We ran out of buffer space: */ 3120 + nfserr = nfserr_resource; 3121 + } 3335 3122 if (nfserr) 3336 3123 goto err_no_verf; 3337 3124 3338 - if (readdir->offset) 3339 - xdr_encode_hyper(readdir->offset, offset); 3125 + if (readdir->cookie_offset) { 3126 + wire_offset = cpu_to_be64(offset); 3127 + write_bytes_to_xdr_buf(xdr->buf, readdir->cookie_offset, 3128 + &wire_offset, 8); 3129 + } 3340 3130 3341 - p = readdir->buffer; 3131 + p = xdr_reserve_space(xdr, 8); 3132 + if (!p) { 3133 + WARN_ON_ONCE(1); 3134 + goto err_no_verf; 3135 + } 3342 3136 *p++ = 0; /* no more entries */ 3343 3137 *p++ = htonl(readdir->common.err == nfserr_eof); 3344 - resp->xbuf->page_len = ((char*)p) - 3345 - (char*)page_address(*(resp->rqstp->rq_next_page-1)); 3346 - 3347 - /* Use rest of head for padding and remaining ops: */ 3348 - resp->xbuf->tail[0].iov_base = tailbase; 3349 - resp->xbuf->tail[0].iov_len = 0; 3350 - resp->p = resp->xbuf->tail[0].iov_base; 3351 - resp->end = resp->p + (PAGE_SIZE - resp->xbuf->head[0].iov_len)/4; 3352 3138 3353 3139 return 0; 3354 3140 err_no_verf: 3355 - p = savep; 3356 - ADJUST_ARGS(); 3141 + xdr_truncate_encode(xdr, starting_len); 3357 3142 return nfserr; 3358 3143 } 3359 3144 3360 3145 static __be32 3361 3146 nfsd4_encode_remove(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_remove *remove) 3362 3147 { 3148 + struct xdr_stream *xdr = &resp->xdr; 3363 3149 __be32 *p; 3364 3150 3365 3151 if (!nfserr) { 3366 - RESERVE_SPACE(20); 3367 - write_cinfo(&p, &remove->rm_cinfo); 3368 - ADJUST_ARGS(); 3152 + p = xdr_reserve_space(xdr, 20); 3153 + if (!p) 3154 + return nfserr_resource; 3155 + p = encode_cinfo(p, &remove->rm_cinfo); 3369 3156 } 3370 3157 return nfserr; 3371 3158 } ··· 3380 3153 static __be32 3381 3154 nfsd4_encode_rename(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_rename *rename) 3382 3155 { 3156 + struct xdr_stream *xdr = &resp->xdr; 3383 3157 __be32 *p; 3384 3158 3385 3159 if (!nfserr) { 3386 - RESERVE_SPACE(40); 3387 - write_cinfo(&p, &rename->rn_sinfo); 3388 - write_cinfo(&p, &rename->rn_tinfo); 3389 - ADJUST_ARGS(); 3160 + p = xdr_reserve_space(xdr, 40); 3161 + if (!p) 3162 + return nfserr_resource; 3163 + p = encode_cinfo(p, &rename->rn_sinfo); 3164 + p = encode_cinfo(p, &rename->rn_tinfo); 3390 3165 } 3391 3166 return nfserr; 3392 3167 } 3393 3168 3394 3169 static __be32 3395 - nfsd4_do_encode_secinfo(struct nfsd4_compoundres *resp, 3170 + nfsd4_do_encode_secinfo(struct xdr_stream *xdr, 3396 3171 __be32 nfserr, struct svc_export *exp) 3397 3172 { 3398 3173 u32 i, nflavs, supported; ··· 3405 3176 3406 3177 if (nfserr) 3407 3178 goto out; 3179 + nfserr = nfserr_resource; 3408 3180 if (exp->ex_nflavors) { 3409 3181 flavs = exp->ex_flavors; 3410 3182 nflavs = exp->ex_nflavors; ··· 3427 3197 } 3428 3198 3429 3199 supported = 0; 3430 - RESERVE_SPACE(4); 3200 + p = xdr_reserve_space(xdr, 4); 3201 + if (!p) 3202 + goto out; 3431 3203 flavorsp = p++; /* to be backfilled later */ 3432 - ADJUST_ARGS(); 3433 3204 3434 3205 for (i = 0; i < nflavs; i++) { 3435 3206 rpc_authflavor_t pf = flavs[i].pseudoflavor; ··· 3438 3207 3439 3208 if (rpcauth_get_gssinfo(pf, &info) == 0) { 3440 3209 supported++; 3441 - RESERVE_SPACE(4 + 4 + XDR_LEN(info.oid.len) + 4 + 4); 3442 - WRITE32(RPC_AUTH_GSS); 3443 - WRITE32(info.oid.len); 3444 - WRITEMEM(info.oid.data, info.oid.len); 3445 - WRITE32(info.qop); 3446 - WRITE32(info.service); 3447 - ADJUST_ARGS(); 3210 + p = xdr_reserve_space(xdr, 4 + 4 + 3211 + XDR_LEN(info.oid.len) + 4 + 4); 3212 + if (!p) 3213 + goto out; 3214 + *p++ = cpu_to_be32(RPC_AUTH_GSS); 3215 + p = xdr_encode_opaque(p, info.oid.data, info.oid.len); 3216 + *p++ = cpu_to_be32(info.qop); 3217 + *p++ = cpu_to_be32(info.service); 3448 3218 } else if (pf < RPC_AUTH_MAXFLAVOR) { 3449 3219 supported++; 3450 - RESERVE_SPACE(4); 3451 - WRITE32(pf); 3452 - ADJUST_ARGS(); 3220 + p = xdr_reserve_space(xdr, 4); 3221 + if (!p) 3222 + goto out; 3223 + *p++ = cpu_to_be32(pf); 3453 3224 } else { 3454 3225 if (report) 3455 3226 pr_warn("NFS: SECINFO: security flavor %u " ··· 3462 3229 if (nflavs != supported) 3463 3230 report = false; 3464 3231 *flavorsp = htonl(supported); 3465 - 3232 + nfserr = 0; 3466 3233 out: 3467 3234 if (exp) 3468 3235 exp_put(exp); ··· 3473 3240 nfsd4_encode_secinfo(struct nfsd4_compoundres *resp, __be32 nfserr, 3474 3241 struct nfsd4_secinfo *secinfo) 3475 3242 { 3476 - return nfsd4_do_encode_secinfo(resp, nfserr, secinfo->si_exp); 3243 + struct xdr_stream *xdr = &resp->xdr; 3244 + 3245 + return nfsd4_do_encode_secinfo(xdr, nfserr, secinfo->si_exp); 3477 3246 } 3478 3247 3479 3248 static __be32 3480 3249 nfsd4_encode_secinfo_no_name(struct nfsd4_compoundres *resp, __be32 nfserr, 3481 3250 struct nfsd4_secinfo_no_name *secinfo) 3482 3251 { 3483 - return nfsd4_do_encode_secinfo(resp, nfserr, secinfo->sin_exp); 3252 + struct xdr_stream *xdr = &resp->xdr; 3253 + 3254 + return nfsd4_do_encode_secinfo(xdr, nfserr, secinfo->sin_exp); 3484 3255 } 3485 3256 3486 3257 /* ··· 3494 3257 static __be32 3495 3258 nfsd4_encode_setattr(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_setattr *setattr) 3496 3259 { 3260 + struct xdr_stream *xdr = &resp->xdr; 3497 3261 __be32 *p; 3498 3262 3499 - RESERVE_SPACE(16); 3263 + p = xdr_reserve_space(xdr, 16); 3264 + if (!p) 3265 + return nfserr_resource; 3500 3266 if (nfserr) { 3501 - WRITE32(3); 3502 - WRITE32(0); 3503 - WRITE32(0); 3504 - WRITE32(0); 3267 + *p++ = cpu_to_be32(3); 3268 + *p++ = cpu_to_be32(0); 3269 + *p++ = cpu_to_be32(0); 3270 + *p++ = cpu_to_be32(0); 3505 3271 } 3506 3272 else { 3507 - WRITE32(3); 3508 - WRITE32(setattr->sa_bmval[0]); 3509 - WRITE32(setattr->sa_bmval[1]); 3510 - WRITE32(setattr->sa_bmval[2]); 3273 + *p++ = cpu_to_be32(3); 3274 + *p++ = cpu_to_be32(setattr->sa_bmval[0]); 3275 + *p++ = cpu_to_be32(setattr->sa_bmval[1]); 3276 + *p++ = cpu_to_be32(setattr->sa_bmval[2]); 3511 3277 } 3512 - ADJUST_ARGS(); 3513 3278 return nfserr; 3514 3279 } 3515 3280 3516 3281 static __be32 3517 3282 nfsd4_encode_setclientid(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_setclientid *scd) 3518 3283 { 3284 + struct xdr_stream *xdr = &resp->xdr; 3519 3285 __be32 *p; 3520 3286 3521 3287 if (!nfserr) { 3522 - RESERVE_SPACE(8 + NFS4_VERIFIER_SIZE); 3523 - WRITEMEM(&scd->se_clientid, 8); 3524 - WRITEMEM(&scd->se_confirm, NFS4_VERIFIER_SIZE); 3525 - ADJUST_ARGS(); 3288 + p = xdr_reserve_space(xdr, 8 + NFS4_VERIFIER_SIZE); 3289 + if (!p) 3290 + return nfserr_resource; 3291 + p = xdr_encode_opaque_fixed(p, &scd->se_clientid, 8); 3292 + p = xdr_encode_opaque_fixed(p, &scd->se_confirm, 3293 + NFS4_VERIFIER_SIZE); 3526 3294 } 3527 3295 else if (nfserr == nfserr_clid_inuse) { 3528 - RESERVE_SPACE(8); 3529 - WRITE32(0); 3530 - WRITE32(0); 3531 - ADJUST_ARGS(); 3296 + p = xdr_reserve_space(xdr, 8); 3297 + if (!p) 3298 + return nfserr_resource; 3299 + *p++ = cpu_to_be32(0); 3300 + *p++ = cpu_to_be32(0); 3532 3301 } 3533 3302 return nfserr; 3534 3303 } ··· 3542 3299 static __be32 3543 3300 nfsd4_encode_write(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_write *write) 3544 3301 { 3302 + struct xdr_stream *xdr = &resp->xdr; 3545 3303 __be32 *p; 3546 3304 3547 3305 if (!nfserr) { 3548 - RESERVE_SPACE(16); 3549 - WRITE32(write->wr_bytes_written); 3550 - WRITE32(write->wr_how_written); 3551 - WRITEMEM(write->wr_verifier.data, NFS4_VERIFIER_SIZE); 3552 - ADJUST_ARGS(); 3306 + p = xdr_reserve_space(xdr, 16); 3307 + if (!p) 3308 + return nfserr_resource; 3309 + *p++ = cpu_to_be32(write->wr_bytes_written); 3310 + *p++ = cpu_to_be32(write->wr_how_written); 3311 + p = xdr_encode_opaque_fixed(p, write->wr_verifier.data, 3312 + NFS4_VERIFIER_SIZE); 3553 3313 } 3554 3314 return nfserr; 3555 3315 } ··· 3569 3323 nfsd4_encode_exchange_id(struct nfsd4_compoundres *resp, __be32 nfserr, 3570 3324 struct nfsd4_exchange_id *exid) 3571 3325 { 3326 + struct xdr_stream *xdr = &resp->xdr; 3572 3327 __be32 *p; 3573 3328 char *major_id; 3574 3329 char *server_scope; ··· 3585 3338 server_scope = utsname()->nodename; 3586 3339 server_scope_sz = strlen(server_scope); 3587 3340 3588 - RESERVE_SPACE( 3341 + p = xdr_reserve_space(xdr, 3589 3342 8 /* eir_clientid */ + 3590 3343 4 /* eir_sequenceid */ + 3591 3344 4 /* eir_flags */ + 3592 3345 4 /* spr_how */); 3346 + if (!p) 3347 + return nfserr_resource; 3593 3348 3594 - WRITEMEM(&exid->clientid, 8); 3595 - WRITE32(exid->seqid); 3596 - WRITE32(exid->flags); 3349 + p = xdr_encode_opaque_fixed(p, &exid->clientid, 8); 3350 + *p++ = cpu_to_be32(exid->seqid); 3351 + *p++ = cpu_to_be32(exid->flags); 3597 3352 3598 - WRITE32(exid->spa_how); 3599 - ADJUST_ARGS(); 3353 + *p++ = cpu_to_be32(exid->spa_how); 3600 3354 3601 3355 switch (exid->spa_how) { 3602 3356 case SP4_NONE: 3603 3357 break; 3604 3358 case SP4_MACH_CRED: 3605 3359 /* spo_must_enforce, spo_must_allow */ 3606 - RESERVE_SPACE(16); 3360 + p = xdr_reserve_space(xdr, 16); 3361 + if (!p) 3362 + return nfserr_resource; 3607 3363 3608 3364 /* spo_must_enforce bitmap: */ 3609 - WRITE32(2); 3610 - WRITE32(nfs4_minimal_spo_must_enforce[0]); 3611 - WRITE32(nfs4_minimal_spo_must_enforce[1]); 3365 + *p++ = cpu_to_be32(2); 3366 + *p++ = cpu_to_be32(nfs4_minimal_spo_must_enforce[0]); 3367 + *p++ = cpu_to_be32(nfs4_minimal_spo_must_enforce[1]); 3612 3368 /* empty spo_must_allow bitmap: */ 3613 - WRITE32(0); 3369 + *p++ = cpu_to_be32(0); 3614 3370 3615 - ADJUST_ARGS(); 3616 3371 break; 3617 3372 default: 3618 3373 WARN_ON_ONCE(1); 3619 3374 } 3620 3375 3621 - RESERVE_SPACE( 3376 + p = xdr_reserve_space(xdr, 3622 3377 8 /* so_minor_id */ + 3623 3378 4 /* so_major_id.len */ + 3624 3379 (XDR_QUADLEN(major_id_sz) * 4) + 3625 3380 4 /* eir_server_scope.len */ + 3626 3381 (XDR_QUADLEN(server_scope_sz) * 4) + 3627 3382 4 /* eir_server_impl_id.count (0) */); 3383 + if (!p) 3384 + return nfserr_resource; 3628 3385 3629 3386 /* The server_owner struct */ 3630 - WRITE64(minor_id); /* Minor id */ 3387 + p = xdr_encode_hyper(p, minor_id); /* Minor id */ 3631 3388 /* major id */ 3632 - WRITE32(major_id_sz); 3633 - WRITEMEM(major_id, major_id_sz); 3389 + p = xdr_encode_opaque(p, major_id, major_id_sz); 3634 3390 3635 3391 /* Server scope */ 3636 - WRITE32(server_scope_sz); 3637 - WRITEMEM(server_scope, server_scope_sz); 3392 + p = xdr_encode_opaque(p, server_scope, server_scope_sz); 3638 3393 3639 3394 /* Implementation id */ 3640 - WRITE32(0); /* zero length nfs_impl_id4 array */ 3641 - ADJUST_ARGS(); 3395 + *p++ = cpu_to_be32(0); /* zero length nfs_impl_id4 array */ 3642 3396 return 0; 3643 3397 } 3644 3398 ··· 3647 3399 nfsd4_encode_create_session(struct nfsd4_compoundres *resp, __be32 nfserr, 3648 3400 struct nfsd4_create_session *sess) 3649 3401 { 3402 + struct xdr_stream *xdr = &resp->xdr; 3650 3403 __be32 *p; 3651 3404 3652 3405 if (nfserr) 3653 3406 return nfserr; 3654 3407 3655 - RESERVE_SPACE(24); 3656 - WRITEMEM(sess->sessionid.data, NFS4_MAX_SESSIONID_LEN); 3657 - WRITE32(sess->seqid); 3658 - WRITE32(sess->flags); 3659 - ADJUST_ARGS(); 3408 + p = xdr_reserve_space(xdr, 24); 3409 + if (!p) 3410 + return nfserr_resource; 3411 + p = xdr_encode_opaque_fixed(p, sess->sessionid.data, 3412 + NFS4_MAX_SESSIONID_LEN); 3413 + *p++ = cpu_to_be32(sess->seqid); 3414 + *p++ = cpu_to_be32(sess->flags); 3660 3415 3661 - RESERVE_SPACE(28); 3662 - WRITE32(0); /* headerpadsz */ 3663 - WRITE32(sess->fore_channel.maxreq_sz); 3664 - WRITE32(sess->fore_channel.maxresp_sz); 3665 - WRITE32(sess->fore_channel.maxresp_cached); 3666 - WRITE32(sess->fore_channel.maxops); 3667 - WRITE32(sess->fore_channel.maxreqs); 3668 - WRITE32(sess->fore_channel.nr_rdma_attrs); 3669 - ADJUST_ARGS(); 3416 + p = xdr_reserve_space(xdr, 28); 3417 + if (!p) 3418 + return nfserr_resource; 3419 + *p++ = cpu_to_be32(0); /* headerpadsz */ 3420 + *p++ = cpu_to_be32(sess->fore_channel.maxreq_sz); 3421 + *p++ = cpu_to_be32(sess->fore_channel.maxresp_sz); 3422 + *p++ = cpu_to_be32(sess->fore_channel.maxresp_cached); 3423 + *p++ = cpu_to_be32(sess->fore_channel.maxops); 3424 + *p++ = cpu_to_be32(sess->fore_channel.maxreqs); 3425 + *p++ = cpu_to_be32(sess->fore_channel.nr_rdma_attrs); 3670 3426 3671 3427 if (sess->fore_channel.nr_rdma_attrs) { 3672 - RESERVE_SPACE(4); 3673 - WRITE32(sess->fore_channel.rdma_attrs); 3674 - ADJUST_ARGS(); 3428 + p = xdr_reserve_space(xdr, 4); 3429 + if (!p) 3430 + return nfserr_resource; 3431 + *p++ = cpu_to_be32(sess->fore_channel.rdma_attrs); 3675 3432 } 3676 3433 3677 - RESERVE_SPACE(28); 3678 - WRITE32(0); /* headerpadsz */ 3679 - WRITE32(sess->back_channel.maxreq_sz); 3680 - WRITE32(sess->back_channel.maxresp_sz); 3681 - WRITE32(sess->back_channel.maxresp_cached); 3682 - WRITE32(sess->back_channel.maxops); 3683 - WRITE32(sess->back_channel.maxreqs); 3684 - WRITE32(sess->back_channel.nr_rdma_attrs); 3685 - ADJUST_ARGS(); 3434 + p = xdr_reserve_space(xdr, 28); 3435 + if (!p) 3436 + return nfserr_resource; 3437 + *p++ = cpu_to_be32(0); /* headerpadsz */ 3438 + *p++ = cpu_to_be32(sess->back_channel.maxreq_sz); 3439 + *p++ = cpu_to_be32(sess->back_channel.maxresp_sz); 3440 + *p++ = cpu_to_be32(sess->back_channel.maxresp_cached); 3441 + *p++ = cpu_to_be32(sess->back_channel.maxops); 3442 + *p++ = cpu_to_be32(sess->back_channel.maxreqs); 3443 + *p++ = cpu_to_be32(sess->back_channel.nr_rdma_attrs); 3686 3444 3687 3445 if (sess->back_channel.nr_rdma_attrs) { 3688 - RESERVE_SPACE(4); 3689 - WRITE32(sess->back_channel.rdma_attrs); 3690 - ADJUST_ARGS(); 3446 + p = xdr_reserve_space(xdr, 4); 3447 + if (!p) 3448 + return nfserr_resource; 3449 + *p++ = cpu_to_be32(sess->back_channel.rdma_attrs); 3691 3450 } 3692 3451 return 0; 3693 3452 } ··· 3703 3448 nfsd4_encode_sequence(struct nfsd4_compoundres *resp, __be32 nfserr, 3704 3449 struct nfsd4_sequence *seq) 3705 3450 { 3451 + struct xdr_stream *xdr = &resp->xdr; 3706 3452 __be32 *p; 3707 3453 3708 3454 if (nfserr) 3709 3455 return nfserr; 3710 3456 3711 - RESERVE_SPACE(NFS4_MAX_SESSIONID_LEN + 20); 3712 - WRITEMEM(seq->sessionid.data, NFS4_MAX_SESSIONID_LEN); 3713 - WRITE32(seq->seqid); 3714 - WRITE32(seq->slotid); 3457 + p = xdr_reserve_space(xdr, NFS4_MAX_SESSIONID_LEN + 20); 3458 + if (!p) 3459 + return nfserr_resource; 3460 + p = xdr_encode_opaque_fixed(p, seq->sessionid.data, 3461 + NFS4_MAX_SESSIONID_LEN); 3462 + *p++ = cpu_to_be32(seq->seqid); 3463 + *p++ = cpu_to_be32(seq->slotid); 3715 3464 /* Note slotid's are numbered from zero: */ 3716 - WRITE32(seq->maxslots - 1); /* sr_highest_slotid */ 3717 - WRITE32(seq->maxslots - 1); /* sr_target_highest_slotid */ 3718 - WRITE32(seq->status_flags); 3465 + *p++ = cpu_to_be32(seq->maxslots - 1); /* sr_highest_slotid */ 3466 + *p++ = cpu_to_be32(seq->maxslots - 1); /* sr_target_highest_slotid */ 3467 + *p++ = cpu_to_be32(seq->status_flags); 3719 3468 3720 - ADJUST_ARGS(); 3721 - resp->cstate.datap = p; /* DRC cache data pointer */ 3469 + resp->cstate.data_offset = xdr->buf->len; /* DRC cache data pointer */ 3722 3470 return 0; 3723 3471 } 3724 3472 ··· 3729 3471 nfsd4_encode_test_stateid(struct nfsd4_compoundres *resp, __be32 nfserr, 3730 3472 struct nfsd4_test_stateid *test_stateid) 3731 3473 { 3474 + struct xdr_stream *xdr = &resp->xdr; 3732 3475 struct nfsd4_test_stateid_id *stateid, *next; 3733 3476 __be32 *p; 3734 3477 3735 3478 if (nfserr) 3736 3479 return nfserr; 3737 3480 3738 - RESERVE_SPACE(4 + (4 * test_stateid->ts_num_ids)); 3481 + p = xdr_reserve_space(xdr, 4 + (4 * test_stateid->ts_num_ids)); 3482 + if (!p) 3483 + return nfserr_resource; 3739 3484 *p++ = htonl(test_stateid->ts_num_ids); 3740 3485 3741 3486 list_for_each_entry_safe(stateid, next, &test_stateid->ts_stateid_list, ts_id_list) { 3742 3487 *p++ = stateid->ts_id_status; 3743 3488 } 3744 3489 3745 - ADJUST_ARGS(); 3746 3490 return nfserr; 3747 3491 } 3748 3492 ··· 3823 3563 }; 3824 3564 3825 3565 /* 3826 - * Calculate the total amount of memory that the compound response has taken 3827 - * after encoding the current operation with pad. 3566 + * Calculate whether we still have space to encode repsize bytes. 3567 + * There are two considerations: 3568 + * - For NFS versions >=4.1, the size of the reply must stay within 3569 + * session limits 3570 + * - For all NFS versions, we must stay within limited preallocated 3571 + * buffer space. 3828 3572 * 3829 - * pad: if operation is non-idempotent, pad was calculate by op_rsize_bop() 3830 - * which was specified at nfsd4_operation, else pad is zero. 3831 - * 3832 - * Compare this length to the session se_fmaxresp_sz and se_fmaxresp_cached. 3833 - * 3834 - * Our se_fmaxresp_cached will always be a multiple of PAGE_SIZE, and so 3835 - * will be at least a page and will therefore hold the xdr_buf head. 3573 + * This is called before the operation is processed, so can only provide 3574 + * an upper estimate. For some nonidempotent operations (such as 3575 + * getattr), it's not necessarily a problem if that estimate is wrong, 3576 + * as we can fail it after processing without significant side effects. 3836 3577 */ 3837 - __be32 nfsd4_check_resp_size(struct nfsd4_compoundres *resp, u32 pad) 3578 + __be32 nfsd4_check_resp_size(struct nfsd4_compoundres *resp, u32 respsize) 3838 3579 { 3839 - struct xdr_buf *xb = &resp->rqstp->rq_res; 3840 - struct nfsd4_session *session = NULL; 3580 + struct xdr_buf *buf = &resp->rqstp->rq_res; 3841 3581 struct nfsd4_slot *slot = resp->cstate.slot; 3842 - u32 length, tlen = 0; 3843 3582 3583 + if (buf->len + respsize <= buf->buflen) 3584 + return nfs_ok; 3844 3585 if (!nfsd4_has_session(&resp->cstate)) 3845 - return 0; 3846 - 3847 - session = resp->cstate.session; 3848 - 3849 - if (xb->page_len == 0) { 3850 - length = (char *)resp->p - (char *)xb->head[0].iov_base + pad; 3851 - } else { 3852 - if (xb->tail[0].iov_base && xb->tail[0].iov_len > 0) 3853 - tlen = (char *)resp->p - (char *)xb->tail[0].iov_base; 3854 - 3855 - length = xb->head[0].iov_len + xb->page_len + tlen + pad; 3856 - } 3857 - dprintk("%s length %u, xb->page_len %u tlen %u pad %u\n", __func__, 3858 - length, xb->page_len, tlen, pad); 3859 - 3860 - if (length > session->se_fchannel.maxresp_sz) 3861 - return nfserr_rep_too_big; 3862 - 3863 - if ((slot->sl_flags & NFSD4_SLOT_CACHETHIS) && 3864 - length > session->se_fchannel.maxresp_cached) 3586 + return nfserr_resource; 3587 + if (slot->sl_flags & NFSD4_SLOT_CACHETHIS) { 3588 + WARN_ON_ONCE(1); 3865 3589 return nfserr_rep_too_big_to_cache; 3866 - 3867 - return 0; 3590 + } 3591 + return nfserr_rep_too_big; 3868 3592 } 3869 3593 3870 3594 void 3871 3595 nfsd4_encode_operation(struct nfsd4_compoundres *resp, struct nfsd4_op *op) 3872 3596 { 3597 + struct xdr_stream *xdr = &resp->xdr; 3873 3598 struct nfs4_stateowner *so = resp->cstate.replay_owner; 3874 - __be32 *statp; 3599 + struct svc_rqst *rqstp = resp->rqstp; 3600 + int post_err_offset; 3601 + nfsd4_enc encoder; 3875 3602 __be32 *p; 3876 3603 3877 - RESERVE_SPACE(8); 3878 - WRITE32(op->opnum); 3879 - statp = p++; /* to be backfilled at the end */ 3880 - ADJUST_ARGS(); 3604 + p = xdr_reserve_space(xdr, 8); 3605 + if (!p) { 3606 + WARN_ON_ONCE(1); 3607 + return; 3608 + } 3609 + *p++ = cpu_to_be32(op->opnum); 3610 + post_err_offset = xdr->buf->len; 3881 3611 3882 3612 if (op->opnum == OP_ILLEGAL) 3883 3613 goto status; 3884 3614 BUG_ON(op->opnum < 0 || op->opnum >= ARRAY_SIZE(nfsd4_enc_ops) || 3885 3615 !nfsd4_enc_ops[op->opnum]); 3886 - op->status = nfsd4_enc_ops[op->opnum](resp, op->status, &op->u); 3616 + encoder = nfsd4_enc_ops[op->opnum]; 3617 + op->status = encoder(resp, op->status, &op->u); 3618 + xdr_commit_encode(xdr); 3619 + 3887 3620 /* nfsd4_check_resp_size guarantees enough room for error status */ 3888 - if (!op->status) 3889 - op->status = nfsd4_check_resp_size(resp, 0); 3621 + if (!op->status) { 3622 + int space_needed = 0; 3623 + if (!nfsd4_last_compound_op(rqstp)) 3624 + space_needed = COMPOUND_ERR_SLACK_SPACE; 3625 + op->status = nfsd4_check_resp_size(resp, space_needed); 3626 + } 3627 + if (op->status == nfserr_resource && nfsd4_has_session(&resp->cstate)) { 3628 + struct nfsd4_slot *slot = resp->cstate.slot; 3629 + 3630 + if (slot->sl_flags & NFSD4_SLOT_CACHETHIS) 3631 + op->status = nfserr_rep_too_big_to_cache; 3632 + else 3633 + op->status = nfserr_rep_too_big; 3634 + } 3635 + if (op->status == nfserr_resource || 3636 + op->status == nfserr_rep_too_big || 3637 + op->status == nfserr_rep_too_big_to_cache) { 3638 + /* 3639 + * The operation may have already been encoded or 3640 + * partially encoded. No op returns anything additional 3641 + * in the case of one of these three errors, so we can 3642 + * just truncate back to after the status. But it's a 3643 + * bug if we had to do this on a non-idempotent op: 3644 + */ 3645 + warn_on_nonidempotent_op(op); 3646 + xdr_truncate_encode(xdr, post_err_offset); 3647 + } 3890 3648 if (so) { 3649 + int len = xdr->buf->len - post_err_offset; 3650 + 3891 3651 so->so_replay.rp_status = op->status; 3892 - so->so_replay.rp_buflen = (char *)resp->p - (char *)(statp+1); 3893 - memcpy(so->so_replay.rp_buf, statp+1, so->so_replay.rp_buflen); 3652 + so->so_replay.rp_buflen = len; 3653 + read_bytes_from_xdr_buf(xdr->buf, post_err_offset, 3654 + so->so_replay.rp_buf, len); 3894 3655 } 3895 3656 status: 3896 - /* 3897 - * Note: We write the status directly, instead of using WRITE32(), 3898 - * since it is already in network byte order. 3899 - */ 3900 - *statp = op->status; 3657 + /* Note that op->status is already in network byte order: */ 3658 + write_bytes_to_xdr_buf(xdr->buf, post_err_offset - 4, &op->status, 4); 3901 3659 } 3902 3660 3903 3661 /* ··· 3927 3649 * called with nfs4_lock_state() held 3928 3650 */ 3929 3651 void 3930 - nfsd4_encode_replay(struct nfsd4_compoundres *resp, struct nfsd4_op *op) 3652 + nfsd4_encode_replay(struct xdr_stream *xdr, struct nfsd4_op *op) 3931 3653 { 3932 3654 __be32 *p; 3933 3655 struct nfs4_replay *rp = op->replay; 3934 3656 3935 3657 BUG_ON(!rp); 3936 3658 3937 - RESERVE_SPACE(8); 3938 - WRITE32(op->opnum); 3659 + p = xdr_reserve_space(xdr, 8 + rp->rp_buflen); 3660 + if (!p) { 3661 + WARN_ON_ONCE(1); 3662 + return; 3663 + } 3664 + *p++ = cpu_to_be32(op->opnum); 3939 3665 *p++ = rp->rp_status; /* already xdr'ed */ 3940 - ADJUST_ARGS(); 3941 3666 3942 - RESERVE_SPACE(rp->rp_buflen); 3943 - WRITEMEM(rp->rp_buf, rp->rp_buflen); 3944 - ADJUST_ARGS(); 3667 + p = xdr_encode_opaque_fixed(p, rp->rp_buf, rp->rp_buflen); 3945 3668 } 3946 3669 3947 3670 int ··· 3999 3720 * All that remains is to write the tag and operation count... 4000 3721 */ 4001 3722 struct nfsd4_compound_state *cs = &resp->cstate; 4002 - struct kvec *iov; 3723 + struct xdr_buf *buf = resp->xdr.buf; 3724 + 3725 + WARN_ON_ONCE(buf->len != buf->head[0].iov_len + buf->page_len + 3726 + buf->tail[0].iov_len); 3727 + 3728 + rqstp->rq_next_page = resp->xdr.page_ptr + 1; 3729 + 4003 3730 p = resp->tagp; 4004 3731 *p++ = htonl(resp->taglen); 4005 3732 memcpy(p, resp->tag, resp->taglen); 4006 3733 p += XDR_QUADLEN(resp->taglen); 4007 3734 *p++ = htonl(resp->opcnt); 4008 3735 4009 - if (rqstp->rq_res.page_len) 4010 - iov = &rqstp->rq_res.tail[0]; 4011 - else 4012 - iov = &rqstp->rq_res.head[0]; 4013 - iov->iov_len = ((char*)resp->p) - (char*)iov->iov_base; 4014 - BUG_ON(iov->iov_len > PAGE_SIZE); 4015 3736 if (nfsd4_has_session(cs)) { 4016 3737 struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id); 4017 3738 struct nfs4_client *clp = cs->session->se_client;
+8 -9
fs/nfsd/nfscache.c
··· 224 224 hlist_add_head(&rp->c_hash, cache_hash + hash_32(rp->c_xid, maskbits)); 225 225 } 226 226 227 - static inline bool 228 - nfsd_cache_entry_expired(struct svc_cacherep *rp) 229 - { 230 - return rp->c_state != RC_INPROG && 231 - time_after(jiffies, rp->c_timestamp + RC_EXPIRE); 232 - } 233 - 234 227 /* 235 228 * Walk the LRU list and prune off entries that are older than RC_EXPIRE. 236 229 * Also prune the oldest ones when the total exceeds the max number of entries. ··· 235 242 long freed = 0; 236 243 237 244 list_for_each_entry_safe(rp, tmp, &lru_head, c_lru) { 238 - if (!nfsd_cache_entry_expired(rp) && 239 - num_drc_entries <= max_drc_entries) 245 + /* 246 + * Don't free entries attached to calls that are still 247 + * in-progress, but do keep scanning the list. 248 + */ 249 + if (rp->c_state == RC_INPROG) 250 + continue; 251 + if (num_drc_entries <= max_drc_entries && 252 + time_before(jiffies, rp->c_timestamp + RC_EXPIRE)) 240 253 break; 241 254 nfsd_reply_cache_free_locked(rp); 242 255 freed++;
-1
fs/nfsd/nfsctl.c
··· 1179 1179 retval = nfsd4_init_slabs(); 1180 1180 if (retval) 1181 1181 goto out_unregister_pernet; 1182 - nfs4_state_init(); 1183 1182 retval = nfsd_fault_inject_init(); /* nfsd fault injection controls */ 1184 1183 if (retval) 1185 1184 goto out_free_slabs;
+12 -5
fs/nfsd/nfsd.h
··· 15 15 #include <linux/nfs2.h> 16 16 #include <linux/nfs3.h> 17 17 #include <linux/nfs4.h> 18 + #include <linux/sunrpc/svc.h> 18 19 #include <linux/sunrpc/msg_prot.h> 19 20 20 - #include <linux/nfsd/debug.h> 21 - #include <linux/nfsd/export.h> 22 - #include <linux/nfsd/stats.h> 21 + #include <uapi/linux/nfsd/debug.h> 22 + 23 + #include "stats.h" 24 + #include "export.h" 25 + 26 + #undef ifdebug 27 + #ifdef NFSD_DEBUG 28 + # define ifdebug(flag) if (nfsd_debug & NFSDDBG_##flag) 29 + #else 30 + # define ifdebug(flag) if (0) 31 + #endif 23 32 24 33 /* 25 34 * nfsd version ··· 115 106 */ 116 107 #ifdef CONFIG_NFSD_V4 117 108 extern unsigned long max_delegations; 118 - void nfs4_state_init(void); 119 109 int nfsd4_init_slabs(void); 120 110 void nfsd4_free_slabs(void); 121 111 int nfs4_state_start(void); ··· 125 117 int nfs4_reset_recoverydir(char *recdir); 126 118 char * nfs4_recoverydir(void); 127 119 #else 128 - static inline void nfs4_state_init(void) { } 129 120 static inline int nfsd4_init_slabs(void) { return 0; } 130 121 static inline void nfsd4_free_slabs(void) { } 131 122 static inline int nfs4_state_start(void) { return 0; }
+11 -14
fs/nfsd/nfsfh.c
··· 88 88 /* Check if the request originated from a secure port. */ 89 89 if (!rqstp->rq_secure && !(flags & NFSEXP_INSECURE_PORT)) { 90 90 RPC_IFDEBUG(char buf[RPC_MAX_ADDRBUFLEN]); 91 - dprintk(KERN_WARNING 92 - "nfsd: request from insecure port %s!\n", 93 - svc_print_addr(rqstp, buf, sizeof(buf))); 91 + dprintk("nfsd: request from insecure port %s!\n", 92 + svc_print_addr(rqstp, buf, sizeof(buf))); 94 93 return nfserr_perm; 95 94 } 96 95 ··· 168 169 data_left -= len; 169 170 if (data_left < 0) 170 171 return error; 171 - exp = rqst_exp_find(rqstp, fh->fh_fsid_type, fh->fh_auth); 172 - fid = (struct fid *)(fh->fh_auth + len); 172 + exp = rqst_exp_find(rqstp, fh->fh_fsid_type, fh->fh_fsid); 173 + fid = (struct fid *)(fh->fh_fsid + len); 173 174 } else { 174 175 __u32 tfh[2]; 175 176 dev_t xdev; ··· 384 385 { 385 386 if (dentry != exp->ex_path.dentry) { 386 387 struct fid *fid = (struct fid *) 387 - (fhp->fh_handle.fh_auth + fhp->fh_handle.fh_size/4 - 1); 388 + (fhp->fh_handle.fh_fsid + fhp->fh_handle.fh_size/4 - 1); 388 389 int maxsize = (fhp->fh_maxsize - fhp->fh_handle.fh_size)/4; 389 390 int subtreecheck = !(exp->ex_flags & NFSEXP_NOSUBTREECHECK); 390 391 ··· 512 513 */ 513 514 514 515 struct inode * inode = dentry->d_inode; 515 - __u32 *datap; 516 516 dev_t ex_dev = exp_sb(exp)->s_dev; 517 517 518 518 dprintk("nfsd: fh_compose(exp %02x:%02x/%ld %pd2, ino=%ld)\n", ··· 555 557 if (inode) 556 558 _fh_update_old(dentry, exp, &fhp->fh_handle); 557 559 } else { 558 - int len; 560 + fhp->fh_handle.fh_size = 561 + key_len(fhp->fh_handle.fh_fsid_type) + 4; 559 562 fhp->fh_handle.fh_auth_type = 0; 560 - datap = fhp->fh_handle.fh_auth+0; 561 - mk_fsid(fhp->fh_handle.fh_fsid_type, datap, ex_dev, 563 + 564 + mk_fsid(fhp->fh_handle.fh_fsid_type, 565 + fhp->fh_handle.fh_fsid, 566 + ex_dev, 562 567 exp->ex_path.dentry->d_inode->i_ino, 563 568 exp->ex_fsid, exp->ex_uuid); 564 - 565 - len = key_len(fhp->fh_handle.fh_fsid_type); 566 - datap += len/4; 567 - fhp->fh_handle.fh_size = 4 + len; 568 569 569 570 if (inode) 570 571 _fh_update(fhp, exp, dentry);
+54 -5
fs/nfsd/nfsfh.h
··· 1 - /* Copyright (C) 1995, 1996, 1997 Olaf Kirch <okir@monad.swb.de> */ 1 + /* 2 + * Copyright (C) 1995, 1996, 1997 Olaf Kirch <okir@monad.swb.de> 3 + * 4 + * This file describes the layout of the file handles as passed 5 + * over the wire. 6 + */ 7 + #ifndef _LINUX_NFSD_NFSFH_H 8 + #define _LINUX_NFSD_NFSFH_H 2 9 3 - #ifndef _LINUX_NFSD_FH_INT_H 4 - #define _LINUX_NFSD_FH_INT_H 10 + #include <linux/sunrpc/svc.h> 11 + #include <uapi/linux/nfsd/nfsfh.h> 5 12 6 - #include <linux/nfsd/nfsfh.h> 13 + static inline __u32 ino_t_to_u32(ino_t ino) 14 + { 15 + return (__u32) ino; 16 + } 17 + 18 + static inline ino_t u32_to_ino_t(__u32 uino) 19 + { 20 + return (ino_t) uino; 21 + } 22 + 23 + /* 24 + * This is the internal representation of an NFS handle used in knfsd. 25 + * pre_mtime/post_version will be used to support wcc_attr's in NFSv3. 26 + */ 27 + typedef struct svc_fh { 28 + struct knfsd_fh fh_handle; /* FH data */ 29 + struct dentry * fh_dentry; /* validated dentry */ 30 + struct svc_export * fh_export; /* export pointer */ 31 + int fh_maxsize; /* max size for fh_handle */ 32 + 33 + unsigned char fh_locked; /* inode locked by us */ 34 + unsigned char fh_want_write; /* remount protection taken */ 35 + 36 + #ifdef CONFIG_NFSD_V3 37 + unsigned char fh_post_saved; /* post-op attrs saved */ 38 + unsigned char fh_pre_saved; /* pre-op attrs saved */ 39 + 40 + /* Pre-op attributes saved during fh_lock */ 41 + __u64 fh_pre_size; /* size before operation */ 42 + struct timespec fh_pre_mtime; /* mtime before oper */ 43 + struct timespec fh_pre_ctime; /* ctime before oper */ 44 + /* 45 + * pre-op nfsv4 change attr: note must check IS_I_VERSION(inode) 46 + * to find out if it is valid. 47 + */ 48 + u64 fh_pre_change; 49 + 50 + /* Post-op attributes saved in fh_unlock */ 51 + struct kstat fh_post_attr; /* full attrs after operation */ 52 + u64 fh_post_change; /* nfsv4 change; see above */ 53 + #endif /* CONFIG_NFSD_V3 */ 54 + 55 + } svc_fh; 7 56 8 57 enum nfsd_fsid { 9 58 FSID_DEV = 0, ··· 264 215 } 265 216 } 266 217 267 - #endif /* _LINUX_NFSD_FH_INT_H */ 218 + #endif /* _LINUX_NFSD_NFSFH_H */
-6
fs/nfsd/nfssvc.c
··· 591 591 nfsdstats.th_cnt++; 592 592 mutex_unlock(&nfsd_mutex); 593 593 594 - /* 595 - * We want less throttling in balance_dirty_pages() so that nfs to 596 - * localhost doesn't cause nfsd to lock up due to all the client's 597 - * dirty pages. 598 - */ 599 - current->flags |= PF_LESS_THROTTLE; 600 594 set_freezable(); 601 595 602 596 /*
+10 -5
fs/nfsd/nfsxdr.c
··· 214 214 int 215 215 nfssvc_decode_fhandle(struct svc_rqst *rqstp, __be32 *p, struct nfsd_fhandle *args) 216 216 { 217 - if (!(p = decode_fh(p, &args->fh))) 217 + p = decode_fh(p, &args->fh); 218 + if (!p) 218 219 return 0; 219 220 return xdr_argsize_check(rqstp, p); 220 221 } ··· 249 248 { 250 249 unsigned int len; 251 250 int v; 252 - if (!(p = decode_fh(p, &args->fh))) 251 + p = decode_fh(p, &args->fh); 252 + if (!p) 253 253 return 0; 254 254 255 255 args->offset = ntohl(*p++); ··· 283 281 unsigned int len, hdr, dlen; 284 282 int v; 285 283 286 - if (!(p = decode_fh(p, &args->fh))) 284 + p = decode_fh(p, &args->fh); 285 + if (!p) 287 286 return 0; 288 287 289 288 p++; /* beginoffset */ ··· 358 355 int 359 356 nfssvc_decode_readlinkargs(struct svc_rqst *rqstp, __be32 *p, struct nfsd_readlinkargs *args) 360 357 { 361 - if (!(p = decode_fh(p, &args->fh))) 358 + p = decode_fh(p, &args->fh); 359 + if (!p) 362 360 return 0; 363 361 args->buffer = page_address(*(rqstp->rq_next_page++)); 364 362 ··· 395 391 nfssvc_decode_readdirargs(struct svc_rqst *rqstp, __be32 *p, 396 392 struct nfsd_readdirargs *args) 397 393 { 398 - if (!(p = decode_fh(p, &args->fh))) 394 + p = decode_fh(p, &args->fh); 395 + if (!p) 399 396 return 0; 400 397 args->cookie = ntohl(*p++); 401 398 args->count = ntohl(*p++);
+1 -4
fs/nfsd/state.h
··· 37 37 38 38 #include <linux/idr.h> 39 39 #include <linux/sunrpc/svc_xprt.h> 40 - #include <linux/nfsd/nfsfh.h> 41 40 #include "nfsfh.h" 42 41 43 42 typedef struct { ··· 122 123 /* Maximum number of operations per session compound */ 123 124 #define NFSD_MAX_OPS_PER_COMPOUND 16 124 125 /* Maximum session per slot cache size */ 125 - #define NFSD_SLOT_CACHE_SIZE 1024 126 + #define NFSD_SLOT_CACHE_SIZE 2048 126 127 /* Maximum number of NFSD_SLOT_CACHE_SIZE slots per session */ 127 128 #define NFSD_CACHE_SIZE_SLOTS_PER_SESSION 32 128 129 #define NFSD_MAX_MEM_PER_SESSION \ ··· 463 464 extern struct nfs4_client_reclaim *nfsd4_find_reclaim_client(const char *recdir, 464 465 struct nfsd_net *nn); 465 466 extern __be32 nfs4_check_open_reclaim(clientid_t *clid, bool sessions, struct nfsd_net *nn); 466 - extern void nfs4_free_openowner(struct nfs4_openowner *); 467 - extern void nfs4_free_lockowner(struct nfs4_lockowner *); 468 467 extern int set_callback_cred(void); 469 468 extern void nfsd4_init_callback(struct nfsd4_callback *); 470 469 extern void nfsd4_probe_callback(struct nfs4_client *clp);
-1
fs/nfsd/stats.c
··· 24 24 #include <linux/seq_file.h> 25 25 #include <linux/module.h> 26 26 #include <linux/sunrpc/stats.h> 27 - #include <linux/nfsd/stats.h> 28 27 #include <net/net_namespace.h> 29 28 30 29 #include "nfsd.h"
+87 -84
fs/nfsd/vfs.c
··· 820 820 return __splice_from_pipe(pipe, sd, nfsd_splice_actor); 821 821 } 822 822 823 - static __be32 824 - nfsd_vfs_read(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file, 825 - loff_t offset, struct kvec *vec, int vlen, unsigned long *count) 823 + __be32 nfsd_finish_read(struct file *file, unsigned long *count, int host_err) 826 824 { 827 - mm_segment_t oldfs; 828 - __be32 err; 829 - int host_err; 830 - 831 - err = nfserr_perm; 832 - 833 - if (file->f_op->splice_read && rqstp->rq_splice_ok) { 834 - struct splice_desc sd = { 835 - .len = 0, 836 - .total_len = *count, 837 - .pos = offset, 838 - .u.data = rqstp, 839 - }; 840 - 841 - rqstp->rq_next_page = rqstp->rq_respages + 1; 842 - host_err = splice_direct_to_actor(file, &sd, nfsd_direct_splice_actor); 843 - } else { 844 - oldfs = get_fs(); 845 - set_fs(KERNEL_DS); 846 - host_err = vfs_readv(file, (struct iovec __user *)vec, vlen, &offset); 847 - set_fs(oldfs); 848 - } 849 - 850 825 if (host_err >= 0) { 851 826 nfsdstats.io_read += host_err; 852 827 *count = host_err; 853 - err = 0; 854 828 fsnotify_access(file); 829 + return 0; 855 830 } else 856 - err = nfserrno(host_err); 857 - return err; 831 + return nfserrno(host_err); 858 832 } 859 833 860 - static void kill_suid(struct dentry *dentry) 834 + int nfsd_splice_read(struct svc_rqst *rqstp, 835 + struct file *file, loff_t offset, unsigned long *count) 861 836 { 862 - struct iattr ia; 863 - ia.ia_valid = ATTR_KILL_SUID | ATTR_KILL_SGID | ATTR_KILL_PRIV; 837 + struct splice_desc sd = { 838 + .len = 0, 839 + .total_len = *count, 840 + .pos = offset, 841 + .u.data = rqstp, 842 + }; 843 + int host_err; 864 844 865 - mutex_lock(&dentry->d_inode->i_mutex); 866 - /* 867 - * Note we call this on write, so notify_change will not 868 - * encounter any conflicting delegations: 869 - */ 870 - notify_change(dentry, &ia, NULL); 871 - mutex_unlock(&dentry->d_inode->i_mutex); 845 + rqstp->rq_next_page = rqstp->rq_respages + 1; 846 + host_err = splice_direct_to_actor(file, &sd, nfsd_direct_splice_actor); 847 + return nfsd_finish_read(file, count, host_err); 848 + } 849 + 850 + int nfsd_readv(struct file *file, loff_t offset, struct kvec *vec, int vlen, 851 + unsigned long *count) 852 + { 853 + mm_segment_t oldfs; 854 + int host_err; 855 + 856 + oldfs = get_fs(); 857 + set_fs(KERNEL_DS); 858 + host_err = vfs_readv(file, (struct iovec __user *)vec, vlen, &offset); 859 + set_fs(oldfs); 860 + return nfsd_finish_read(file, count, host_err); 861 + } 862 + 863 + static __be32 864 + nfsd_vfs_read(struct svc_rqst *rqstp, struct file *file, 865 + loff_t offset, struct kvec *vec, int vlen, unsigned long *count) 866 + { 867 + if (file->f_op->splice_read && rqstp->rq_splice_ok) 868 + return nfsd_splice_read(rqstp, file, offset, count); 869 + else 870 + return nfsd_readv(file, offset, vec, vlen, count); 872 871 } 873 872 874 873 /* ··· 921 922 int stable = *stablep; 922 923 int use_wgather; 923 924 loff_t pos = offset; 925 + unsigned int pflags = current->flags; 926 + 927 + if (rqstp->rq_local) 928 + /* 929 + * We want less throttling in balance_dirty_pages() 930 + * and shrink_inactive_list() so that nfs to 931 + * localhost doesn't cause nfsd to lock up due to all 932 + * the client's dirty pages or its congested queue. 933 + */ 934 + current->flags |= PF_LESS_THROTTLE; 924 935 925 936 dentry = file->f_path.dentry; 926 937 inode = dentry->d_inode; ··· 951 942 nfsdstats.io_write += host_err; 952 943 fsnotify_modify(file); 953 944 954 - /* clear setuid/setgid flag after write */ 955 - if (inode->i_mode & (S_ISUID | S_ISGID)) 956 - kill_suid(dentry); 957 - 958 945 if (stable) { 959 946 if (use_wgather) 960 947 host_err = wait_for_concurrent_writes(file); ··· 964 959 err = 0; 965 960 else 966 961 err = nfserrno(host_err); 962 + if (rqstp->rq_local) 963 + tsk_restore_flags(current, pflags, PF_LESS_THROTTLE); 967 964 return err; 965 + } 966 + 967 + __be32 nfsd_get_tmp_read_open(struct svc_rqst *rqstp, struct svc_fh *fhp, 968 + struct file **file, struct raparms **ra) 969 + { 970 + struct inode *inode; 971 + __be32 err; 972 + 973 + err = nfsd_open(rqstp, fhp, S_IFREG, NFSD_MAY_READ, file); 974 + if (err) 975 + return err; 976 + 977 + inode = file_inode(*file); 978 + 979 + /* Get readahead parameters */ 980 + *ra = nfsd_get_raparms(inode->i_sb->s_dev, inode->i_ino); 981 + 982 + if (*ra && (*ra)->p_set) 983 + (*file)->f_ra = (*ra)->p_ra; 984 + return nfs_ok; 985 + } 986 + 987 + void nfsd_put_tmp_read_open(struct file *file, struct raparms *ra) 988 + { 989 + /* Write back readahead params */ 990 + if (ra) { 991 + struct raparm_hbucket *rab = &raparm_hash[ra->p_hindex]; 992 + spin_lock(&rab->pb_lock); 993 + ra->p_ra = file->f_ra; 994 + ra->p_set = 1; 995 + ra->p_count--; 996 + spin_unlock(&rab->pb_lock); 997 + } 998 + nfsd_close(file); 968 999 } 969 1000 970 1001 /* ··· 1012 971 loff_t offset, struct kvec *vec, int vlen, unsigned long *count) 1013 972 { 1014 973 struct file *file; 1015 - struct inode *inode; 1016 974 struct raparms *ra; 1017 975 __be32 err; 1018 976 1019 - err = nfsd_open(rqstp, fhp, S_IFREG, NFSD_MAY_READ, &file); 977 + err = nfsd_get_tmp_read_open(rqstp, fhp, &file, &ra); 1020 978 if (err) 1021 979 return err; 1022 980 1023 - inode = file_inode(file); 981 + err = nfsd_vfs_read(rqstp, file, offset, vec, vlen, count); 1024 982 1025 - /* Get readahead parameters */ 1026 - ra = nfsd_get_raparms(inode->i_sb->s_dev, inode->i_ino); 983 + nfsd_put_tmp_read_open(file, ra); 1027 984 1028 - if (ra && ra->p_set) 1029 - file->f_ra = ra->p_ra; 1030 - 1031 - err = nfsd_vfs_read(rqstp, fhp, file, offset, vec, vlen, count); 1032 - 1033 - /* Write back readahead params */ 1034 - if (ra) { 1035 - struct raparm_hbucket *rab = &raparm_hash[ra->p_hindex]; 1036 - spin_lock(&rab->pb_lock); 1037 - ra->p_ra = file->f_ra; 1038 - ra->p_set = 1; 1039 - ra->p_count--; 1040 - spin_unlock(&rab->pb_lock); 1041 - } 1042 - 1043 - nfsd_close(file); 1044 - return err; 1045 - } 1046 - 1047 - /* As above, but use the provided file descriptor. */ 1048 - __be32 1049 - nfsd_read_file(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file, 1050 - loff_t offset, struct kvec *vec, int vlen, 1051 - unsigned long *count) 1052 - { 1053 - __be32 err; 1054 - 1055 - if (file) { 1056 - err = nfsd_permission(rqstp, fhp->fh_export, fhp->fh_dentry, 1057 - NFSD_MAY_READ|NFSD_MAY_OWNER_OVERRIDE); 1058 - if (err) 1059 - goto out; 1060 - err = nfsd_vfs_read(rqstp, fhp, file, offset, vec, vlen, count); 1061 - } else /* Note file may still be NULL in NFSv4 special stateid case: */ 1062 - err = nfsd_read(rqstp, fhp, offset, vec, vlen, count); 1063 - out: 1064 985 return err; 1065 986 } 1066 987
+8 -2
fs/nfsd/vfs.h
··· 70 70 __be32 nfsd_open(struct svc_rqst *, struct svc_fh *, umode_t, 71 71 int, struct file **); 72 72 void nfsd_close(struct file *); 73 + struct raparms; 74 + __be32 nfsd_get_tmp_read_open(struct svc_rqst *, struct svc_fh *, 75 + struct file **, struct raparms **); 76 + void nfsd_put_tmp_read_open(struct file *, struct raparms *); 77 + int nfsd_splice_read(struct svc_rqst *, 78 + struct file *, loff_t, unsigned long *); 79 + int nfsd_readv(struct file *, loff_t, struct kvec *, int, 80 + unsigned long *); 73 81 __be32 nfsd_read(struct svc_rqst *, struct svc_fh *, 74 - loff_t, struct kvec *, int, unsigned long *); 75 - __be32 nfsd_read_file(struct svc_rqst *, struct svc_fh *, struct file *, 76 82 loff_t, struct kvec *, int, unsigned long *); 77 83 __be32 nfsd_write(struct svc_rqst *, struct svc_fh *,struct file *, 78 84 loff_t, struct kvec *,int, unsigned long *, int *);
+12 -11
fs/nfsd/xdr4.h
··· 58 58 /* For sessions DRC */ 59 59 struct nfsd4_session *session; 60 60 struct nfsd4_slot *slot; 61 - __be32 *datap; 61 + int data_offset; 62 62 size_t iovlen; 63 63 u32 minorversion; 64 64 __be32 status; ··· 287 287 struct svc_fh * rd_fhp; /* response */ 288 288 289 289 struct readdir_cd common; 290 - __be32 * buffer; 291 - int buflen; 292 - __be32 * offset; 290 + struct xdr_stream *xdr; 291 + int cookie_offset; 293 292 }; 294 293 295 294 struct nfsd4_release_lockowner { ··· 505 506 506 507 struct nfsd4_compoundres { 507 508 /* scratch variables for XDR encode */ 508 - __be32 * p; 509 - __be32 * end; 510 - struct xdr_buf * xbuf; 509 + struct xdr_stream xdr; 511 510 struct svc_rqst * rqstp; 512 511 513 512 u32 taglen; ··· 535 538 return argp->opcnt == resp->opcnt; 536 539 } 537 540 541 + int nfsd4_max_reply(struct svc_rqst *rqstp, struct nfsd4_op *op); 542 + void warn_on_nonidempotent_op(struct nfsd4_op *op); 543 + 538 544 #define NFS4_SVC_XDRSIZE sizeof(struct nfsd4_compoundargs) 539 545 540 546 static inline void ··· 563 563 struct nfsd4_compoundres *); 564 564 __be32 nfsd4_check_resp_size(struct nfsd4_compoundres *, u32); 565 565 void nfsd4_encode_operation(struct nfsd4_compoundres *, struct nfsd4_op *); 566 - void nfsd4_encode_replay(struct nfsd4_compoundres *resp, struct nfsd4_op *op); 567 - __be32 nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp, 568 - struct dentry *dentry, __be32 **buffer, int countp, 569 - u32 *bmval, struct svc_rqst *, int ignore_crossmnt); 566 + void nfsd4_encode_replay(struct xdr_stream *xdr, struct nfsd4_op *op); 567 + __be32 nfsd4_encode_fattr_to_buf(__be32 **p, int words, 568 + struct svc_fh *fhp, struct svc_export *exp, 569 + struct dentry *dentry, 570 + u32 *bmval, struct svc_rqst *, int ignore_crossmnt); 570 571 extern __be32 nfsd4_setclientid(struct svc_rqst *rqstp, 571 572 struct nfsd4_compound_state *, 572 573 struct nfsd4_setclientid *setclid);
+1 -1
include/linux/lockd/lockd.h
··· 17 17 #include <linux/fs.h> 18 18 #include <linux/kref.h> 19 19 #include <linux/utsname.h> 20 - #include <linux/nfsd/nfsfh.h> 21 20 #include <linux/lockd/bind.h> 22 21 #include <linux/lockd/xdr.h> 23 22 #ifdef CONFIG_LOCKD_V4 24 23 #include <linux/lockd/xdr4.h> 25 24 #endif 26 25 #include <linux/lockd/debug.h> 26 + #include <linux/sunrpc/svc.h> 27 27 28 28 /* 29 29 * Version string
-2
include/linux/nfs4.h
··· 399 399 #define FATTR4_WORD2_LAYOUT_BLKSIZE (1UL << 1) 400 400 #define FATTR4_WORD2_MDSTHRESHOLD (1UL << 4) 401 401 #define FATTR4_WORD2_SECURITY_LABEL (1UL << 16) 402 - #define FATTR4_WORD2_CHANGE_SECURITY_LABEL \ 403 - (1UL << 17) 404 402 405 403 /* MDS threshold bitmap bits */ 406 404 #define THRESHOLD_RD (1UL << 0)
-19
include/linux/nfsd/debug.h
··· 1 - /* 2 - * linux/include/linux/nfsd/debug.h 3 - * 4 - * Debugging-related stuff for nfsd 5 - * 6 - * Copyright (C) 1995 Olaf Kirch <okir@monad.swb.de> 7 - */ 8 - #ifndef LINUX_NFSD_DEBUG_H 9 - #define LINUX_NFSD_DEBUG_H 10 - 11 - #include <uapi/linux/nfsd/debug.h> 12 - 13 - # undef ifdebug 14 - # ifdef NFSD_DEBUG 15 - # define ifdebug(flag) if (nfsd_debug & NFSDDBG_##flag) 16 - # else 17 - # define ifdebug(flag) if (0) 18 - # endif 19 - #endif /* LINUX_NFSD_DEBUG_H */
+7 -7
include/linux/nfsd/export.h fs/nfsd/export.h
··· 1 1 /* 2 - * include/linux/nfsd/export.h 3 - * 4 - * Public declarations for NFS exports. The definitions for the 5 - * syscall interface are in nfsctl.h 6 - * 7 2 * Copyright (C) 1995-1997 Olaf Kirch <okir@monad.swb.de> 8 3 */ 9 4 #ifndef NFSD_EXPORT_H 10 5 #define NFSD_EXPORT_H 11 6 12 - # include <linux/nfsd/nfsfh.h> 7 + #include <linux/sunrpc/cache.h> 13 8 #include <uapi/linux/nfsd/export.h> 9 + 10 + struct knfsd_fh; 11 + struct svc_fh; 12 + struct svc_rqst; 14 13 15 14 /* 16 15 * FS Locations ··· 37 38 * spkm3i, and spkm3p (and using all 8 at once should be rare). 38 39 */ 39 40 #define MAX_SECINFO_LIST 8 41 + #define EX_UUID_LEN 16 40 42 41 43 struct exp_flavor_info { 42 44 u32 pseudoflavor; ··· 54 54 int ex_fsid; 55 55 unsigned char * ex_uuid; /* 16 byte fsid */ 56 56 struct nfsd4_fs_locations ex_fslocs; 57 - int ex_nflavors; 57 + uint32_t ex_nflavors; 58 58 struct exp_flavor_info ex_flavors[MAX_SECINFO_LIST]; 59 59 struct cache_detail *cd; 60 60 };
-63
include/linux/nfsd/nfsfh.h
··· 1 - /* 2 - * include/linux/nfsd/nfsfh.h 3 - * 4 - * This file describes the layout of the file handles as passed 5 - * over the wire. 6 - * 7 - * Earlier versions of knfsd used to sign file handles using keyed MD5 8 - * or SHA. I've removed this code, because it doesn't give you more 9 - * security than blocking external access to port 2049 on your firewall. 10 - * 11 - * Copyright (C) 1995, 1996, 1997 Olaf Kirch <okir@monad.swb.de> 12 - */ 13 - #ifndef _LINUX_NFSD_FH_H 14 - #define _LINUX_NFSD_FH_H 15 - 16 - # include <linux/sunrpc/svc.h> 17 - #include <uapi/linux/nfsd/nfsfh.h> 18 - 19 - static inline __u32 ino_t_to_u32(ino_t ino) 20 - { 21 - return (__u32) ino; 22 - } 23 - 24 - static inline ino_t u32_to_ino_t(__u32 uino) 25 - { 26 - return (ino_t) uino; 27 - } 28 - 29 - /* 30 - * This is the internal representation of an NFS handle used in knfsd. 31 - * pre_mtime/post_version will be used to support wcc_attr's in NFSv3. 32 - */ 33 - typedef struct svc_fh { 34 - struct knfsd_fh fh_handle; /* FH data */ 35 - struct dentry * fh_dentry; /* validated dentry */ 36 - struct svc_export * fh_export; /* export pointer */ 37 - int fh_maxsize; /* max size for fh_handle */ 38 - 39 - unsigned char fh_locked; /* inode locked by us */ 40 - unsigned char fh_want_write; /* remount protection taken */ 41 - 42 - #ifdef CONFIG_NFSD_V3 43 - unsigned char fh_post_saved; /* post-op attrs saved */ 44 - unsigned char fh_pre_saved; /* pre-op attrs saved */ 45 - 46 - /* Pre-op attributes saved during fh_lock */ 47 - __u64 fh_pre_size; /* size before operation */ 48 - struct timespec fh_pre_mtime; /* mtime before oper */ 49 - struct timespec fh_pre_ctime; /* ctime before oper */ 50 - /* 51 - * pre-op nfsv4 change attr: note must check IS_I_VERSION(inode) 52 - * to find out if it is valid. 53 - */ 54 - u64 fh_pre_change; 55 - 56 - /* Post-op attributes saved in fh_unlock */ 57 - struct kstat fh_post_attr; /* full attrs after operation */ 58 - u64 fh_post_change; /* nfsv4 change; see above */ 59 - #endif /* CONFIG_NFSD_V3 */ 60 - 61 - } svc_fh; 62 - 63 - #endif /* _LINUX_NFSD_FH_H */
+3 -5
include/linux/nfsd/stats.h fs/nfsd/stats.h
··· 1 1 /* 2 - * linux/include/linux/nfsd/stats.h 3 - * 4 2 * Statistics for NFS server. 5 3 * 6 4 * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de> 7 5 */ 8 - #ifndef LINUX_NFSD_STATS_H 9 - #define LINUX_NFSD_STATS_H 6 + #ifndef _NFSD_STATS_H 7 + #define _NFSD_STATS_H 10 8 11 9 #include <uapi/linux/nfsd/stats.h> 12 10 ··· 40 42 void nfsd_stat_init(void); 41 43 void nfsd_stat_shutdown(void); 42 44 43 - #endif /* LINUX_NFSD_STATS_H */ 45 + #endif /* _NFSD_STATS_H */
+7 -6
include/linux/sunrpc/svc.h
··· 244 244 struct page * rq_pages[RPCSVC_MAXPAGES]; 245 245 struct page * *rq_respages; /* points into rq_pages */ 246 246 struct page * *rq_next_page; /* next reply page to use */ 247 + struct page * *rq_page_end; /* one past the last page */ 247 248 248 249 struct kvec rq_vec[RPCSVC_MAXPAGES]; /* generally useful.. */ 249 250 ··· 255 254 u32 rq_prot; /* IP protocol */ 256 255 unsigned short 257 256 rq_secure : 1; /* secure port */ 257 + unsigned short rq_local : 1; /* local request */ 258 258 259 259 void * rq_argp; /* decoded arguments */ 260 260 void * rq_resp; /* xdr'd results */ 261 261 void * rq_auth_data; /* flavor-specific data */ 262 - 262 + int rq_auth_slack; /* extra space xdr code 263 + * should leave in head 264 + * for krb5i, krb5p. 265 + */ 263 266 int rq_reserved; /* space on socket outq 264 267 * reserved for this request 265 268 */ ··· 459 454 */ 460 455 static inline void svc_reserve_auth(struct svc_rqst *rqstp, int space) 461 456 { 462 - int added_space = 0; 463 - 464 - if (rqstp->rq_authop->flavour) 465 - added_space = RPC_MAX_AUTH_SIZE; 466 - svc_reserve(rqstp, space + added_space); 457 + svc_reserve(rqstp, space + rqstp->rq_auth_slack); 467 458 } 468 459 469 460 #endif /* SUNRPC_SVC_H */
+1 -2
include/linux/sunrpc/svc_rdma.h
··· 115 115 struct list_head frmr_list; 116 116 }; 117 117 struct svc_rdma_req_map { 118 - struct svc_rdma_fastreg_mr *frmr; 119 118 unsigned long count; 120 119 union { 121 120 struct kvec sge[RPCSVC_MAXPAGES]; 122 121 struct svc_rdma_chunk_sge ch[RPCSVC_MAXPAGES]; 122 + unsigned long lkey[RPCSVC_MAXPAGES]; 123 123 }; 124 124 }; 125 - #define RDMACTXT_F_FAST_UNREG 1 126 125 #define RDMACTXT_F_LAST_CTXT 2 127 126 128 127 #define SVCRDMA_DEVCAP_FAST_REG 1 /* fast mr registration */
+2
include/linux/sunrpc/svc_xprt.h
··· 24 24 void (*xpo_release_rqst)(struct svc_rqst *); 25 25 void (*xpo_detach)(struct svc_xprt *); 26 26 void (*xpo_free)(struct svc_xprt *); 27 + int (*xpo_secure_port)(struct svc_rqst *); 27 28 }; 28 29 29 30 struct svc_xprt_class { ··· 64 63 #define XPT_DETACHED 10 /* detached from tempsocks list */ 65 64 #define XPT_LISTENER 11 /* listening endpoint */ 66 65 #define XPT_CACHE_AUTH 12 /* cache auth info */ 66 + #define XPT_LOCAL 13 /* connection from loopback interface */ 67 67 68 68 struct svc_serv *xpt_server; /* service for transport */ 69 69 atomic_t xpt_reserved; /* space on outq that is rsvd */
+3
include/linux/sunrpc/xdr.h
··· 215 215 216 216 extern void xdr_init_encode(struct xdr_stream *xdr, struct xdr_buf *buf, __be32 *p); 217 217 extern __be32 *xdr_reserve_space(struct xdr_stream *xdr, size_t nbytes); 218 + extern void xdr_commit_encode(struct xdr_stream *xdr); 219 + extern void xdr_truncate_encode(struct xdr_stream *xdr, size_t len); 220 + extern int xdr_restrict_buflen(struct xdr_stream *xdr, int newbuflen); 218 221 extern void xdr_write_pages(struct xdr_stream *xdr, struct page **pages, 219 222 unsigned int base, unsigned int len); 220 223 extern unsigned int xdr_stream_pos(const struct xdr_stream *xdr);
+7 -25
include/uapi/linux/nfsd/nfsfh.h
··· 1 1 /* 2 - * include/linux/nfsd/nfsfh.h 3 - * 4 2 * This file describes the layout of the file handles as passed 5 3 * over the wire. 6 - * 7 - * Earlier versions of knfsd used to sign file handles using keyed MD5 8 - * or SHA. I've removed this code, because it doesn't give you more 9 - * security than blocking external access to port 2049 on your firewall. 10 4 * 11 5 * Copyright (C) 1995, 1996, 1997 Olaf Kirch <okir@monad.swb.de> 12 6 */ ··· 31 37 }; 32 38 33 39 /* 34 - * This is the new flexible, extensible style NFSv2/v3 file handle. 40 + * This is the new flexible, extensible style NFSv2/v3/v4 file handle. 35 41 * by Neil Brown <neilb@cse.unsw.edu.au> - March 2000 36 42 * 37 43 * The file handle starts with a sequence of four-byte words. ··· 41 47 * 42 48 * All four-byte values are in host-byte-order. 43 49 * 44 - * The auth_type field specifies how the filehandle can be authenticated 45 - * This might allow a file to be confirmed to be in a writable part of a 46 - * filetree without checking the path from it up to the root. 47 - * Current values: 48 - * 0 - No authentication. fb_auth is 0 bytes long 49 - * Possible future values: 50 - * 1 - 4 bytes taken from MD5 hash of the remainer of the file handle 51 - * prefixed by a secret and with the important export flags. 50 + * The auth_type field is deprecated and must be set to 0. 52 51 * 53 52 * The fsid_type identifies how the filesystem (or export point) is 54 53 * encoded. ··· 58 71 * 7 - 8 byte inode number and 16 byte uuid 59 72 * 60 73 * The fileid_type identified how the file within the filesystem is encoded. 61 - * This is (will be) passed to, and set by, the underlying filesystem if it supports 62 - * filehandle operations. The filesystem must not use the value '0' or '0xff' and may 63 - * only use the values 1 and 2 as defined below: 64 - * Current values: 65 - * 0 - The root, or export point, of the filesystem. fb_fileid is 0 bytes. 66 - * 1 - 32bit inode number, 32 bit generation number. 67 - * 2 - 32bit inode number, 32 bit generation number, 32 bit parent directory inode number. 68 - * 74 + * The values for this field are filesystem specific, exccept that 75 + * filesystems must not use the values '0' or '0xff'. 'See enum fid_type' 76 + * in include/linux/exportfs.h for currently registered values. 69 77 */ 70 78 struct nfs_fhbase_new { 71 79 __u8 fb_version; /* == 1, even => nfs_fhbase_old */ ··· 96 114 #define fh_fsid_type fh_base.fh_new.fb_fsid_type 97 115 #define fh_auth_type fh_base.fh_new.fb_auth_type 98 116 #define fh_fileid_type fh_base.fh_new.fb_fileid_type 99 - #define fh_auth fh_base.fh_new.fb_auth 100 117 #define fh_fsid fh_base.fh_new.fb_auth 101 118 102 - 119 + /* Do not use, provided for userspace compatiblity. */ 120 + #define fh_auth fh_base.fh_new.fb_auth 103 121 104 122 #endif /* _UAPI_LINUX_NFSD_FH_H */
+2
net/sunrpc/auth_gss/svcauth_gss.c
··· 1503 1503 if (unwrap_integ_data(rqstp, &rqstp->rq_arg, 1504 1504 gc->gc_seq, rsci->mechctx)) 1505 1505 goto garbage_args; 1506 + rqstp->rq_auth_slack = RPC_MAX_AUTH_SIZE; 1506 1507 break; 1507 1508 case RPC_GSS_SVC_PRIVACY: 1508 1509 /* placeholders for length and seq. number: */ ··· 1512 1511 if (unwrap_priv_data(rqstp, &rqstp->rq_arg, 1513 1512 gc->gc_seq, rsci->mechctx)) 1514 1513 goto garbage_args; 1514 + rqstp->rq_auth_slack = RPC_MAX_AUTH_SIZE * 2; 1515 1515 break; 1516 1516 default: 1517 1517 goto auth_err;
+1 -1
net/sunrpc/cache.c
··· 374 374 } 375 375 return; 376 376 out: 377 - printk(KERN_ERR "nfsd: failed to unregister %s cache\n", cd->name); 377 + printk(KERN_ERR "RPC: failed to unregister %s cache\n", cd->name); 378 378 } 379 379 EXPORT_SYMBOL_GPL(sunrpc_destroy_cache_detail); 380 380
+13
net/sunrpc/sunrpc.h
··· 43 43 (task->tk_msg.rpc_proc->p_decode != NULL); 44 44 } 45 45 46 + static inline int sock_is_loopback(struct sock *sk) 47 + { 48 + struct dst_entry *dst; 49 + int loopback = 0; 50 + rcu_read_lock(); 51 + dst = rcu_dereference(sk->sk_dst_cache); 52 + if (dst && dst->dev && 53 + (dst->dev->features & NETIF_F_LOOPBACK)) 54 + loopback = 1; 55 + rcu_read_unlock(); 56 + return loopback; 57 + } 58 + 46 59 int svc_send_common(struct socket *sock, struct xdr_buf *xdr, 47 60 struct page *headpage, unsigned long headoffset, 48 61 struct page *tailpage, unsigned long tailoffset);
+4 -1
net/sunrpc/svc_xprt.c
··· 597 597 } 598 598 rqstp->rq_pages[i] = p; 599 599 } 600 + rqstp->rq_page_end = &rqstp->rq_pages[i]; 600 601 rqstp->rq_pages[i++] = NULL; /* this might be seen in nfs_read_actor */ 601 602 602 603 /* Make arg->head point to first page and arg->pages point to rest */ ··· 731 730 newxpt = xprt->xpt_ops->xpo_accept(xprt); 732 731 if (newxpt) 733 732 svc_add_new_temp_xprt(serv, newxpt); 733 + else 734 + module_put(xprt->xpt_class->xcl_owner); 734 735 } else if (xprt->xpt_ops->xpo_has_wspace(xprt)) { 735 736 /* XPT_DATA|XPT_DEFERRED case: */ 736 737 dprintk("svc: server %p, pool %u, transport %p, inuse=%d\n", ··· 796 793 797 794 clear_bit(XPT_OLD, &xprt->xpt_flags); 798 795 799 - rqstp->rq_secure = svc_port_is_privileged(svc_addr(rqstp)); 796 + rqstp->rq_secure = xprt->xpt_ops->xpo_secure_port(rqstp); 800 797 rqstp->rq_chandle.defer = svc_defer; 801 798 802 799 if (serv->sv_stats)
+2
net/sunrpc/svcauth.c
··· 54 54 } 55 55 spin_unlock(&authtab_lock); 56 56 57 + rqstp->rq_auth_slack = 0; 58 + 57 59 rqstp->rq_authop = aops; 58 60 return aops->accept(rqstp, authp); 59 61 }
+15 -2
net/sunrpc/svcsock.c
··· 400 400 release_sock(sock->sk); 401 401 #endif 402 402 } 403 + 404 + static int svc_sock_secure_port(struct svc_rqst *rqstp) 405 + { 406 + return svc_port_is_privileged(svc_addr(rqstp)); 407 + } 408 + 403 409 /* 404 410 * INET callback when data has been received on the socket. 405 411 */ ··· 684 678 .xpo_prep_reply_hdr = svc_udp_prep_reply_hdr, 685 679 .xpo_has_wspace = svc_udp_has_wspace, 686 680 .xpo_accept = svc_udp_accept, 681 + .xpo_secure_port = svc_sock_secure_port, 687 682 }; 688 683 689 684 static struct svc_xprt_class svc_udp_class = { ··· 849 842 * tell us anything. For now just warn about unpriv connections. 850 843 */ 851 844 if (!svc_port_is_privileged(sin)) { 852 - dprintk(KERN_WARNING 853 - "%s: connect from unprivileged port: %s\n", 845 + dprintk("%s: connect from unprivileged port: %s\n", 854 846 serv->sv_name, 855 847 __svc_print_addr(sin, buf, sizeof(buf))); 856 848 } ··· 873 867 } 874 868 svc_xprt_set_local(&newsvsk->sk_xprt, sin, slen); 875 869 870 + if (sock_is_loopback(newsock->sk)) 871 + set_bit(XPT_LOCAL, &newsvsk->sk_xprt.xpt_flags); 872 + else 873 + clear_bit(XPT_LOCAL, &newsvsk->sk_xprt.xpt_flags); 876 874 if (serv->sv_stats) 877 875 serv->sv_stats->nettcpconn++; 878 876 ··· 1122 1112 1123 1113 rqstp->rq_xprt_ctxt = NULL; 1124 1114 rqstp->rq_prot = IPPROTO_TCP; 1115 + rqstp->rq_local = !!test_bit(XPT_LOCAL, &svsk->sk_xprt.xpt_flags); 1125 1116 1126 1117 p = (__be32 *)rqstp->rq_arg.head[0].iov_base; 1127 1118 calldir = p[1]; ··· 1245 1234 .xpo_detach = svc_bc_tcp_sock_detach, 1246 1235 .xpo_free = svc_bc_sock_free, 1247 1236 .xpo_prep_reply_hdr = svc_tcp_prep_reply_hdr, 1237 + .xpo_secure_port = svc_sock_secure_port, 1248 1238 }; 1249 1239 1250 1240 static struct svc_xprt_class svc_tcp_bc_class = { ··· 1284 1272 .xpo_prep_reply_hdr = svc_tcp_prep_reply_hdr, 1285 1273 .xpo_has_wspace = svc_tcp_has_wspace, 1286 1274 .xpo_accept = svc_tcp_accept, 1275 + .xpo_secure_port = svc_sock_secure_port, 1287 1276 }; 1288 1277 1289 1278 static struct svc_xprt_class svc_tcp_class = {
+172 -2
net/sunrpc/xdr.c
··· 462 462 struct kvec *iov = buf->head; 463 463 int scratch_len = buf->buflen - buf->page_len - buf->tail[0].iov_len; 464 464 465 + xdr_set_scratch_buffer(xdr, NULL, 0); 465 466 BUG_ON(scratch_len < 0); 466 467 xdr->buf = buf; 467 468 xdr->iov = iov; ··· 483 482 EXPORT_SYMBOL_GPL(xdr_init_encode); 484 483 485 484 /** 485 + * xdr_commit_encode - Ensure all data is written to buffer 486 + * @xdr: pointer to xdr_stream 487 + * 488 + * We handle encoding across page boundaries by giving the caller a 489 + * temporary location to write to, then later copying the data into 490 + * place; xdr_commit_encode does that copying. 491 + * 492 + * Normally the caller doesn't need to call this directly, as the 493 + * following xdr_reserve_space will do it. But an explicit call may be 494 + * required at the end of encoding, or any other time when the xdr_buf 495 + * data might be read. 496 + */ 497 + void xdr_commit_encode(struct xdr_stream *xdr) 498 + { 499 + int shift = xdr->scratch.iov_len; 500 + void *page; 501 + 502 + if (shift == 0) 503 + return; 504 + page = page_address(*xdr->page_ptr); 505 + memcpy(xdr->scratch.iov_base, page, shift); 506 + memmove(page, page + shift, (void *)xdr->p - page); 507 + xdr->scratch.iov_len = 0; 508 + } 509 + EXPORT_SYMBOL_GPL(xdr_commit_encode); 510 + 511 + __be32 *xdr_get_next_encode_buffer(struct xdr_stream *xdr, size_t nbytes) 512 + { 513 + static __be32 *p; 514 + int space_left; 515 + int frag1bytes, frag2bytes; 516 + 517 + if (nbytes > PAGE_SIZE) 518 + return NULL; /* Bigger buffers require special handling */ 519 + if (xdr->buf->len + nbytes > xdr->buf->buflen) 520 + return NULL; /* Sorry, we're totally out of space */ 521 + frag1bytes = (xdr->end - xdr->p) << 2; 522 + frag2bytes = nbytes - frag1bytes; 523 + if (xdr->iov) 524 + xdr->iov->iov_len += frag1bytes; 525 + else 526 + xdr->buf->page_len += frag1bytes; 527 + xdr->page_ptr++; 528 + xdr->iov = NULL; 529 + /* 530 + * If the last encode didn't end exactly on a page boundary, the 531 + * next one will straddle boundaries. Encode into the next 532 + * page, then copy it back later in xdr_commit_encode. We use 533 + * the "scratch" iov to track any temporarily unused fragment of 534 + * space at the end of the previous buffer: 535 + */ 536 + xdr->scratch.iov_base = xdr->p; 537 + xdr->scratch.iov_len = frag1bytes; 538 + p = page_address(*xdr->page_ptr); 539 + /* 540 + * Note this is where the next encode will start after we've 541 + * shifted this one back: 542 + */ 543 + xdr->p = (void *)p + frag2bytes; 544 + space_left = xdr->buf->buflen - xdr->buf->len; 545 + xdr->end = (void *)p + min_t(int, space_left, PAGE_SIZE); 546 + xdr->buf->page_len += frag2bytes; 547 + xdr->buf->len += nbytes; 548 + return p; 549 + } 550 + 551 + /** 486 552 * xdr_reserve_space - Reserve buffer space for sending 487 553 * @xdr: pointer to xdr_stream 488 554 * @nbytes: number of bytes to reserve ··· 563 495 __be32 *p = xdr->p; 564 496 __be32 *q; 565 497 498 + xdr_commit_encode(xdr); 566 499 /* align nbytes on the next 32-bit boundary */ 567 500 nbytes += 3; 568 501 nbytes &= ~3; 569 502 q = p + (nbytes >> 2); 570 503 if (unlikely(q > xdr->end || q < p)) 571 - return NULL; 504 + return xdr_get_next_encode_buffer(xdr, nbytes); 572 505 xdr->p = q; 573 - xdr->iov->iov_len += nbytes; 506 + if (xdr->iov) 507 + xdr->iov->iov_len += nbytes; 508 + else 509 + xdr->buf->page_len += nbytes; 574 510 xdr->buf->len += nbytes; 575 511 return p; 576 512 } 577 513 EXPORT_SYMBOL_GPL(xdr_reserve_space); 514 + 515 + /** 516 + * xdr_truncate_encode - truncate an encode buffer 517 + * @xdr: pointer to xdr_stream 518 + * @len: new length of buffer 519 + * 520 + * Truncates the xdr stream, so that xdr->buf->len == len, 521 + * and xdr->p points at offset len from the start of the buffer, and 522 + * head, tail, and page lengths are adjusted to correspond. 523 + * 524 + * If this means moving xdr->p to a different buffer, we assume that 525 + * that the end pointer should be set to the end of the current page, 526 + * except in the case of the head buffer when we assume the head 527 + * buffer's current length represents the end of the available buffer. 528 + * 529 + * This is *not* safe to use on a buffer that already has inlined page 530 + * cache pages (as in a zero-copy server read reply), except for the 531 + * simple case of truncating from one position in the tail to another. 532 + * 533 + */ 534 + void xdr_truncate_encode(struct xdr_stream *xdr, size_t len) 535 + { 536 + struct xdr_buf *buf = xdr->buf; 537 + struct kvec *head = buf->head; 538 + struct kvec *tail = buf->tail; 539 + int fraglen; 540 + int new, old; 541 + 542 + if (len > buf->len) { 543 + WARN_ON_ONCE(1); 544 + return; 545 + } 546 + xdr_commit_encode(xdr); 547 + 548 + fraglen = min_t(int, buf->len - len, tail->iov_len); 549 + tail->iov_len -= fraglen; 550 + buf->len -= fraglen; 551 + if (tail->iov_len && buf->len == len) { 552 + xdr->p = tail->iov_base + tail->iov_len; 553 + /* xdr->end, xdr->iov should be set already */ 554 + return; 555 + } 556 + WARN_ON_ONCE(fraglen); 557 + fraglen = min_t(int, buf->len - len, buf->page_len); 558 + buf->page_len -= fraglen; 559 + buf->len -= fraglen; 560 + 561 + new = buf->page_base + buf->page_len; 562 + old = new + fraglen; 563 + xdr->page_ptr -= (old >> PAGE_SHIFT) - (new >> PAGE_SHIFT); 564 + 565 + if (buf->page_len && buf->len == len) { 566 + xdr->p = page_address(*xdr->page_ptr); 567 + xdr->end = (void *)xdr->p + PAGE_SIZE; 568 + xdr->p = (void *)xdr->p + (new % PAGE_SIZE); 569 + /* xdr->iov should already be NULL */ 570 + return; 571 + } 572 + if (fraglen) { 573 + xdr->end = head->iov_base + head->iov_len; 574 + xdr->page_ptr--; 575 + } 576 + /* (otherwise assume xdr->end is already set) */ 577 + head->iov_len = len; 578 + buf->len = len; 579 + xdr->p = head->iov_base + head->iov_len; 580 + xdr->iov = buf->head; 581 + } 582 + EXPORT_SYMBOL(xdr_truncate_encode); 583 + 584 + /** 585 + * xdr_restrict_buflen - decrease available buffer space 586 + * @xdr: pointer to xdr_stream 587 + * @newbuflen: new maximum number of bytes available 588 + * 589 + * Adjust our idea of how much space is available in the buffer. 590 + * If we've already used too much space in the buffer, returns -1. 591 + * If the available space is already smaller than newbuflen, returns 0 592 + * and does nothing. Otherwise, adjusts xdr->buf->buflen to newbuflen 593 + * and ensures xdr->end is set at most offset newbuflen from the start 594 + * of the buffer. 595 + */ 596 + int xdr_restrict_buflen(struct xdr_stream *xdr, int newbuflen) 597 + { 598 + struct xdr_buf *buf = xdr->buf; 599 + int left_in_this_buf = (void *)xdr->end - (void *)xdr->p; 600 + int end_offset = buf->len + left_in_this_buf; 601 + 602 + if (newbuflen < 0 || newbuflen < buf->len) 603 + return -1; 604 + if (newbuflen > buf->buflen) 605 + return 0; 606 + if (newbuflen < end_offset) 607 + xdr->end = (void *)xdr->end + newbuflen - end_offset; 608 + buf->buflen = newbuflen; 609 + return 0; 610 + } 611 + EXPORT_SYMBOL(xdr_restrict_buflen); 578 612 579 613 /** 580 614 * xdr_write_pages - Insert a list of pages into an XDR buffer for sending
+292 -389
net/sunrpc/xprtrdma/svc_rdma_recvfrom.c
··· 1 1 /* 2 + * Copyright (c) 2014 Open Grid Computing, Inc. All rights reserved. 2 3 * Copyright (c) 2005-2006 Network Appliance, Inc. All rights reserved. 3 4 * 4 5 * This software is available to you under a choice of one of two ··· 70 69 71 70 /* Set up the XDR head */ 72 71 rqstp->rq_arg.head[0].iov_base = page_address(page); 73 - rqstp->rq_arg.head[0].iov_len = min(byte_count, ctxt->sge[0].length); 72 + rqstp->rq_arg.head[0].iov_len = 73 + min_t(size_t, byte_count, ctxt->sge[0].length); 74 74 rqstp->rq_arg.len = byte_count; 75 75 rqstp->rq_arg.buflen = byte_count; 76 76 ··· 87 85 page = ctxt->pages[sge_no]; 88 86 put_page(rqstp->rq_pages[sge_no]); 89 87 rqstp->rq_pages[sge_no] = page; 90 - bc -= min(bc, ctxt->sge[sge_no].length); 88 + bc -= min_t(u32, bc, ctxt->sge[sge_no].length); 91 89 rqstp->rq_arg.buflen += ctxt->sge[sge_no].length; 92 90 sge_no++; 93 91 } ··· 115 113 rqstp->rq_arg.tail[0].iov_len = 0; 116 114 } 117 115 118 - /* Encode a read-chunk-list as an array of IB SGE 119 - * 120 - * Assumptions: 121 - * - chunk[0]->position points to pages[0] at an offset of 0 122 - * - pages[] is not physically or virtually contiguous and consists of 123 - * PAGE_SIZE elements. 124 - * 125 - * Output: 126 - * - sge array pointing into pages[] array. 127 - * - chunk_sge array specifying sge index and count for each 128 - * chunk in the read list 129 - * 130 - */ 131 - static int map_read_chunks(struct svcxprt_rdma *xprt, 132 - struct svc_rqst *rqstp, 133 - struct svc_rdma_op_ctxt *head, 134 - struct rpcrdma_msg *rmsgp, 135 - struct svc_rdma_req_map *rpl_map, 136 - struct svc_rdma_req_map *chl_map, 137 - int ch_count, 138 - int byte_count) 139 - { 140 - int sge_no; 141 - int sge_bytes; 142 - int page_off; 143 - int page_no; 144 - int ch_bytes; 145 - int ch_no; 146 - struct rpcrdma_read_chunk *ch; 147 - 148 - sge_no = 0; 149 - page_no = 0; 150 - page_off = 0; 151 - ch = (struct rpcrdma_read_chunk *)&rmsgp->rm_body.rm_chunks[0]; 152 - ch_no = 0; 153 - ch_bytes = ntohl(ch->rc_target.rs_length); 154 - head->arg.head[0] = rqstp->rq_arg.head[0]; 155 - head->arg.tail[0] = rqstp->rq_arg.tail[0]; 156 - head->arg.pages = &head->pages[head->count]; 157 - head->hdr_count = head->count; /* save count of hdr pages */ 158 - head->arg.page_base = 0; 159 - head->arg.page_len = ch_bytes; 160 - head->arg.len = rqstp->rq_arg.len + ch_bytes; 161 - head->arg.buflen = rqstp->rq_arg.buflen + ch_bytes; 162 - head->count++; 163 - chl_map->ch[0].start = 0; 164 - while (byte_count) { 165 - rpl_map->sge[sge_no].iov_base = 166 - page_address(rqstp->rq_arg.pages[page_no]) + page_off; 167 - sge_bytes = min_t(int, PAGE_SIZE-page_off, ch_bytes); 168 - rpl_map->sge[sge_no].iov_len = sge_bytes; 169 - /* 170 - * Don't bump head->count here because the same page 171 - * may be used by multiple SGE. 172 - */ 173 - head->arg.pages[page_no] = rqstp->rq_arg.pages[page_no]; 174 - rqstp->rq_respages = &rqstp->rq_arg.pages[page_no+1]; 175 - rqstp->rq_next_page = rqstp->rq_respages + 1; 176 - 177 - byte_count -= sge_bytes; 178 - ch_bytes -= sge_bytes; 179 - sge_no++; 180 - /* 181 - * If all bytes for this chunk have been mapped to an 182 - * SGE, move to the next SGE 183 - */ 184 - if (ch_bytes == 0) { 185 - chl_map->ch[ch_no].count = 186 - sge_no - chl_map->ch[ch_no].start; 187 - ch_no++; 188 - ch++; 189 - chl_map->ch[ch_no].start = sge_no; 190 - ch_bytes = ntohl(ch->rc_target.rs_length); 191 - /* If bytes remaining account for next chunk */ 192 - if (byte_count) { 193 - head->arg.page_len += ch_bytes; 194 - head->arg.len += ch_bytes; 195 - head->arg.buflen += ch_bytes; 196 - } 197 - } 198 - /* 199 - * If this SGE consumed all of the page, move to the 200 - * next page 201 - */ 202 - if ((sge_bytes + page_off) == PAGE_SIZE) { 203 - page_no++; 204 - page_off = 0; 205 - /* 206 - * If there are still bytes left to map, bump 207 - * the page count 208 - */ 209 - if (byte_count) 210 - head->count++; 211 - } else 212 - page_off += sge_bytes; 213 - } 214 - BUG_ON(byte_count != 0); 215 - return sge_no; 216 - } 217 - 218 - /* Map a read-chunk-list to an XDR and fast register the page-list. 219 - * 220 - * Assumptions: 221 - * - chunk[0] position points to pages[0] at an offset of 0 222 - * - pages[] will be made physically contiguous by creating a one-off memory 223 - * region using the fastreg verb. 224 - * - byte_count is # of bytes in read-chunk-list 225 - * - ch_count is # of chunks in read-chunk-list 226 - * 227 - * Output: 228 - * - sge array pointing into pages[] array. 229 - * - chunk_sge array specifying sge index and count for each 230 - * chunk in the read list 231 - */ 232 - static int fast_reg_read_chunks(struct svcxprt_rdma *xprt, 233 - struct svc_rqst *rqstp, 234 - struct svc_rdma_op_ctxt *head, 235 - struct rpcrdma_msg *rmsgp, 236 - struct svc_rdma_req_map *rpl_map, 237 - struct svc_rdma_req_map *chl_map, 238 - int ch_count, 239 - int byte_count) 240 - { 241 - int page_no; 242 - int ch_no; 243 - u32 offset; 244 - struct rpcrdma_read_chunk *ch; 245 - struct svc_rdma_fastreg_mr *frmr; 246 - int ret = 0; 247 - 248 - frmr = svc_rdma_get_frmr(xprt); 249 - if (IS_ERR(frmr)) 250 - return -ENOMEM; 251 - 252 - head->frmr = frmr; 253 - head->arg.head[0] = rqstp->rq_arg.head[0]; 254 - head->arg.tail[0] = rqstp->rq_arg.tail[0]; 255 - head->arg.pages = &head->pages[head->count]; 256 - head->hdr_count = head->count; /* save count of hdr pages */ 257 - head->arg.page_base = 0; 258 - head->arg.page_len = byte_count; 259 - head->arg.len = rqstp->rq_arg.len + byte_count; 260 - head->arg.buflen = rqstp->rq_arg.buflen + byte_count; 261 - 262 - /* Fast register the page list */ 263 - frmr->kva = page_address(rqstp->rq_arg.pages[0]); 264 - frmr->direction = DMA_FROM_DEVICE; 265 - frmr->access_flags = (IB_ACCESS_LOCAL_WRITE|IB_ACCESS_REMOTE_WRITE); 266 - frmr->map_len = byte_count; 267 - frmr->page_list_len = PAGE_ALIGN(byte_count) >> PAGE_SHIFT; 268 - for (page_no = 0; page_no < frmr->page_list_len; page_no++) { 269 - frmr->page_list->page_list[page_no] = 270 - ib_dma_map_page(xprt->sc_cm_id->device, 271 - rqstp->rq_arg.pages[page_no], 0, 272 - PAGE_SIZE, DMA_FROM_DEVICE); 273 - if (ib_dma_mapping_error(xprt->sc_cm_id->device, 274 - frmr->page_list->page_list[page_no])) 275 - goto fatal_err; 276 - atomic_inc(&xprt->sc_dma_used); 277 - head->arg.pages[page_no] = rqstp->rq_arg.pages[page_no]; 278 - } 279 - head->count += page_no; 280 - 281 - /* rq_respages points one past arg pages */ 282 - rqstp->rq_respages = &rqstp->rq_arg.pages[page_no]; 283 - rqstp->rq_next_page = rqstp->rq_respages + 1; 284 - 285 - /* Create the reply and chunk maps */ 286 - offset = 0; 287 - ch = (struct rpcrdma_read_chunk *)&rmsgp->rm_body.rm_chunks[0]; 288 - for (ch_no = 0; ch_no < ch_count; ch_no++) { 289 - int len = ntohl(ch->rc_target.rs_length); 290 - rpl_map->sge[ch_no].iov_base = frmr->kva + offset; 291 - rpl_map->sge[ch_no].iov_len = len; 292 - chl_map->ch[ch_no].count = 1; 293 - chl_map->ch[ch_no].start = ch_no; 294 - offset += len; 295 - ch++; 296 - } 297 - 298 - ret = svc_rdma_fastreg(xprt, frmr); 299 - if (ret) 300 - goto fatal_err; 301 - 302 - return ch_no; 303 - 304 - fatal_err: 305 - printk("svcrdma: error fast registering xdr for xprt %p", xprt); 306 - svc_rdma_put_frmr(xprt, frmr); 307 - return -EIO; 308 - } 309 - 310 - static int rdma_set_ctxt_sge(struct svcxprt_rdma *xprt, 311 - struct svc_rdma_op_ctxt *ctxt, 312 - struct svc_rdma_fastreg_mr *frmr, 313 - struct kvec *vec, 314 - u64 *sgl_offset, 315 - int count) 316 - { 317 - int i; 318 - unsigned long off; 319 - 320 - ctxt->count = count; 321 - ctxt->direction = DMA_FROM_DEVICE; 322 - for (i = 0; i < count; i++) { 323 - ctxt->sge[i].length = 0; /* in case map fails */ 324 - if (!frmr) { 325 - BUG_ON(!virt_to_page(vec[i].iov_base)); 326 - off = (unsigned long)vec[i].iov_base & ~PAGE_MASK; 327 - ctxt->sge[i].addr = 328 - ib_dma_map_page(xprt->sc_cm_id->device, 329 - virt_to_page(vec[i].iov_base), 330 - off, 331 - vec[i].iov_len, 332 - DMA_FROM_DEVICE); 333 - if (ib_dma_mapping_error(xprt->sc_cm_id->device, 334 - ctxt->sge[i].addr)) 335 - return -EINVAL; 336 - ctxt->sge[i].lkey = xprt->sc_dma_lkey; 337 - atomic_inc(&xprt->sc_dma_used); 338 - } else { 339 - ctxt->sge[i].addr = (unsigned long)vec[i].iov_base; 340 - ctxt->sge[i].lkey = frmr->mr->lkey; 341 - } 342 - ctxt->sge[i].length = vec[i].iov_len; 343 - *sgl_offset = *sgl_offset + vec[i].iov_len; 344 - } 345 - return 0; 346 - } 347 - 348 116 static int rdma_read_max_sge(struct svcxprt_rdma *xprt, int sge_count) 349 117 { 350 - if ((rdma_node_get_transport(xprt->sc_cm_id->device->node_type) == 351 - RDMA_TRANSPORT_IWARP) && 352 - sge_count > 1) 118 + if (rdma_node_get_transport(xprt->sc_cm_id->device->node_type) == 119 + RDMA_TRANSPORT_IWARP) 353 120 return 1; 354 121 else 355 122 return min_t(int, sge_count, xprt->sc_max_sge); 356 123 } 357 124 358 - /* 359 - * Use RDMA_READ to read data from the advertised client buffer into the 360 - * XDR stream starting at rq_arg.head[0].iov_base. 361 - * Each chunk in the array 362 - * contains the following fields: 363 - * discrim - '1', This isn't used for data placement 364 - * position - The xdr stream offset (the same for every chunk) 365 - * handle - RMR for client memory region 366 - * length - data transfer length 367 - * offset - 64 bit tagged offset in remote memory region 368 - * 369 - * On our side, we need to read into a pagelist. The first page immediately 370 - * follows the RPC header. 371 - * 372 - * This function returns: 373 - * 0 - No error and no read-list found. 374 - * 375 - * 1 - Successful read-list processing. The data is not yet in 376 - * the pagelist and therefore the RPC request must be deferred. The 377 - * I/O completion will enqueue the transport again and 378 - * svc_rdma_recvfrom will complete the request. 379 - * 380 - * <0 - Error processing/posting read-list. 381 - * 382 - * NOTE: The ctxt must not be touched after the last WR has been posted 383 - * because the I/O completion processing may occur on another 384 - * processor and free / modify the context. Ne touche pas! 385 - */ 386 - static int rdma_read_xdr(struct svcxprt_rdma *xprt, 387 - struct rpcrdma_msg *rmsgp, 388 - struct svc_rqst *rqstp, 389 - struct svc_rdma_op_ctxt *hdr_ctxt) 125 + typedef int (*rdma_reader_fn)(struct svcxprt_rdma *xprt, 126 + struct svc_rqst *rqstp, 127 + struct svc_rdma_op_ctxt *head, 128 + int *page_no, 129 + u32 *page_offset, 130 + u32 rs_handle, 131 + u32 rs_length, 132 + u64 rs_offset, 133 + int last); 134 + 135 + /* Issue an RDMA_READ using the local lkey to map the data sink */ 136 + static int rdma_read_chunk_lcl(struct svcxprt_rdma *xprt, 137 + struct svc_rqst *rqstp, 138 + struct svc_rdma_op_ctxt *head, 139 + int *page_no, 140 + u32 *page_offset, 141 + u32 rs_handle, 142 + u32 rs_length, 143 + u64 rs_offset, 144 + int last) 145 + { 146 + struct ib_send_wr read_wr; 147 + int pages_needed = PAGE_ALIGN(*page_offset + rs_length) >> PAGE_SHIFT; 148 + struct svc_rdma_op_ctxt *ctxt = svc_rdma_get_context(xprt); 149 + int ret, read, pno; 150 + u32 pg_off = *page_offset; 151 + u32 pg_no = *page_no; 152 + 153 + ctxt->direction = DMA_FROM_DEVICE; 154 + ctxt->read_hdr = head; 155 + pages_needed = 156 + min_t(int, pages_needed, rdma_read_max_sge(xprt, pages_needed)); 157 + read = min_t(int, pages_needed << PAGE_SHIFT, rs_length); 158 + 159 + for (pno = 0; pno < pages_needed; pno++) { 160 + int len = min_t(int, rs_length, PAGE_SIZE - pg_off); 161 + 162 + head->arg.pages[pg_no] = rqstp->rq_arg.pages[pg_no]; 163 + head->arg.page_len += len; 164 + head->arg.len += len; 165 + if (!pg_off) 166 + head->count++; 167 + rqstp->rq_respages = &rqstp->rq_arg.pages[pg_no+1]; 168 + rqstp->rq_next_page = rqstp->rq_respages + 1; 169 + ctxt->sge[pno].addr = 170 + ib_dma_map_page(xprt->sc_cm_id->device, 171 + head->arg.pages[pg_no], pg_off, 172 + PAGE_SIZE - pg_off, 173 + DMA_FROM_DEVICE); 174 + ret = ib_dma_mapping_error(xprt->sc_cm_id->device, 175 + ctxt->sge[pno].addr); 176 + if (ret) 177 + goto err; 178 + atomic_inc(&xprt->sc_dma_used); 179 + 180 + /* The lkey here is either a local dma lkey or a dma_mr lkey */ 181 + ctxt->sge[pno].lkey = xprt->sc_dma_lkey; 182 + ctxt->sge[pno].length = len; 183 + ctxt->count++; 184 + 185 + /* adjust offset and wrap to next page if needed */ 186 + pg_off += len; 187 + if (pg_off == PAGE_SIZE) { 188 + pg_off = 0; 189 + pg_no++; 190 + } 191 + rs_length -= len; 192 + } 193 + 194 + if (last && rs_length == 0) 195 + set_bit(RDMACTXT_F_LAST_CTXT, &ctxt->flags); 196 + else 197 + clear_bit(RDMACTXT_F_LAST_CTXT, &ctxt->flags); 198 + 199 + memset(&read_wr, 0, sizeof(read_wr)); 200 + read_wr.wr_id = (unsigned long)ctxt; 201 + read_wr.opcode = IB_WR_RDMA_READ; 202 + ctxt->wr_op = read_wr.opcode; 203 + read_wr.send_flags = IB_SEND_SIGNALED; 204 + read_wr.wr.rdma.rkey = rs_handle; 205 + read_wr.wr.rdma.remote_addr = rs_offset; 206 + read_wr.sg_list = ctxt->sge; 207 + read_wr.num_sge = pages_needed; 208 + 209 + ret = svc_rdma_send(xprt, &read_wr); 210 + if (ret) { 211 + pr_err("svcrdma: Error %d posting RDMA_READ\n", ret); 212 + set_bit(XPT_CLOSE, &xprt->sc_xprt.xpt_flags); 213 + goto err; 214 + } 215 + 216 + /* return current location in page array */ 217 + *page_no = pg_no; 218 + *page_offset = pg_off; 219 + ret = read; 220 + atomic_inc(&rdma_stat_read); 221 + return ret; 222 + err: 223 + svc_rdma_unmap_dma(ctxt); 224 + svc_rdma_put_context(ctxt, 0); 225 + return ret; 226 + } 227 + 228 + /* Issue an RDMA_READ using an FRMR to map the data sink */ 229 + static int rdma_read_chunk_frmr(struct svcxprt_rdma *xprt, 230 + struct svc_rqst *rqstp, 231 + struct svc_rdma_op_ctxt *head, 232 + int *page_no, 233 + u32 *page_offset, 234 + u32 rs_handle, 235 + u32 rs_length, 236 + u64 rs_offset, 237 + int last) 390 238 { 391 239 struct ib_send_wr read_wr; 392 240 struct ib_send_wr inv_wr; 393 - int err = 0; 394 - int ch_no; 395 - int ch_count; 396 - int byte_count; 397 - int sge_count; 398 - u64 sgl_offset; 241 + struct ib_send_wr fastreg_wr; 242 + u8 key; 243 + int pages_needed = PAGE_ALIGN(*page_offset + rs_length) >> PAGE_SHIFT; 244 + struct svc_rdma_op_ctxt *ctxt = svc_rdma_get_context(xprt); 245 + struct svc_rdma_fastreg_mr *frmr = svc_rdma_get_frmr(xprt); 246 + int ret, read, pno; 247 + u32 pg_off = *page_offset; 248 + u32 pg_no = *page_no; 249 + 250 + if (IS_ERR(frmr)) 251 + return -ENOMEM; 252 + 253 + ctxt->direction = DMA_FROM_DEVICE; 254 + ctxt->frmr = frmr; 255 + pages_needed = min_t(int, pages_needed, xprt->sc_frmr_pg_list_len); 256 + read = min_t(int, pages_needed << PAGE_SHIFT, rs_length); 257 + 258 + frmr->kva = page_address(rqstp->rq_arg.pages[pg_no]); 259 + frmr->direction = DMA_FROM_DEVICE; 260 + frmr->access_flags = (IB_ACCESS_LOCAL_WRITE|IB_ACCESS_REMOTE_WRITE); 261 + frmr->map_len = pages_needed << PAGE_SHIFT; 262 + frmr->page_list_len = pages_needed; 263 + 264 + for (pno = 0; pno < pages_needed; pno++) { 265 + int len = min_t(int, rs_length, PAGE_SIZE - pg_off); 266 + 267 + head->arg.pages[pg_no] = rqstp->rq_arg.pages[pg_no]; 268 + head->arg.page_len += len; 269 + head->arg.len += len; 270 + if (!pg_off) 271 + head->count++; 272 + rqstp->rq_respages = &rqstp->rq_arg.pages[pg_no+1]; 273 + rqstp->rq_next_page = rqstp->rq_respages + 1; 274 + frmr->page_list->page_list[pno] = 275 + ib_dma_map_page(xprt->sc_cm_id->device, 276 + head->arg.pages[pg_no], 0, 277 + PAGE_SIZE, DMA_FROM_DEVICE); 278 + ret = ib_dma_mapping_error(xprt->sc_cm_id->device, 279 + frmr->page_list->page_list[pno]); 280 + if (ret) 281 + goto err; 282 + atomic_inc(&xprt->sc_dma_used); 283 + 284 + /* adjust offset and wrap to next page if needed */ 285 + pg_off += len; 286 + if (pg_off == PAGE_SIZE) { 287 + pg_off = 0; 288 + pg_no++; 289 + } 290 + rs_length -= len; 291 + } 292 + 293 + if (last && rs_length == 0) 294 + set_bit(RDMACTXT_F_LAST_CTXT, &ctxt->flags); 295 + else 296 + clear_bit(RDMACTXT_F_LAST_CTXT, &ctxt->flags); 297 + 298 + /* Bump the key */ 299 + key = (u8)(frmr->mr->lkey & 0x000000FF); 300 + ib_update_fast_reg_key(frmr->mr, ++key); 301 + 302 + ctxt->sge[0].addr = (unsigned long)frmr->kva + *page_offset; 303 + ctxt->sge[0].lkey = frmr->mr->lkey; 304 + ctxt->sge[0].length = read; 305 + ctxt->count = 1; 306 + ctxt->read_hdr = head; 307 + 308 + /* Prepare FASTREG WR */ 309 + memset(&fastreg_wr, 0, sizeof(fastreg_wr)); 310 + fastreg_wr.opcode = IB_WR_FAST_REG_MR; 311 + fastreg_wr.send_flags = IB_SEND_SIGNALED; 312 + fastreg_wr.wr.fast_reg.iova_start = (unsigned long)frmr->kva; 313 + fastreg_wr.wr.fast_reg.page_list = frmr->page_list; 314 + fastreg_wr.wr.fast_reg.page_list_len = frmr->page_list_len; 315 + fastreg_wr.wr.fast_reg.page_shift = PAGE_SHIFT; 316 + fastreg_wr.wr.fast_reg.length = frmr->map_len; 317 + fastreg_wr.wr.fast_reg.access_flags = frmr->access_flags; 318 + fastreg_wr.wr.fast_reg.rkey = frmr->mr->lkey; 319 + fastreg_wr.next = &read_wr; 320 + 321 + /* Prepare RDMA_READ */ 322 + memset(&read_wr, 0, sizeof(read_wr)); 323 + read_wr.send_flags = IB_SEND_SIGNALED; 324 + read_wr.wr.rdma.rkey = rs_handle; 325 + read_wr.wr.rdma.remote_addr = rs_offset; 326 + read_wr.sg_list = ctxt->sge; 327 + read_wr.num_sge = 1; 328 + if (xprt->sc_dev_caps & SVCRDMA_DEVCAP_READ_W_INV) { 329 + read_wr.opcode = IB_WR_RDMA_READ_WITH_INV; 330 + read_wr.wr_id = (unsigned long)ctxt; 331 + read_wr.ex.invalidate_rkey = ctxt->frmr->mr->lkey; 332 + } else { 333 + read_wr.opcode = IB_WR_RDMA_READ; 334 + read_wr.next = &inv_wr; 335 + /* Prepare invalidate */ 336 + memset(&inv_wr, 0, sizeof(inv_wr)); 337 + inv_wr.wr_id = (unsigned long)ctxt; 338 + inv_wr.opcode = IB_WR_LOCAL_INV; 339 + inv_wr.send_flags = IB_SEND_SIGNALED | IB_SEND_FENCE; 340 + inv_wr.ex.invalidate_rkey = frmr->mr->lkey; 341 + } 342 + ctxt->wr_op = read_wr.opcode; 343 + 344 + /* Post the chain */ 345 + ret = svc_rdma_send(xprt, &fastreg_wr); 346 + if (ret) { 347 + pr_err("svcrdma: Error %d posting RDMA_READ\n", ret); 348 + set_bit(XPT_CLOSE, &xprt->sc_xprt.xpt_flags); 349 + goto err; 350 + } 351 + 352 + /* return current location in page array */ 353 + *page_no = pg_no; 354 + *page_offset = pg_off; 355 + ret = read; 356 + atomic_inc(&rdma_stat_read); 357 + return ret; 358 + err: 359 + svc_rdma_unmap_dma(ctxt); 360 + svc_rdma_put_context(ctxt, 0); 361 + svc_rdma_put_frmr(xprt, frmr); 362 + return ret; 363 + } 364 + 365 + static int rdma_read_chunks(struct svcxprt_rdma *xprt, 366 + struct rpcrdma_msg *rmsgp, 367 + struct svc_rqst *rqstp, 368 + struct svc_rdma_op_ctxt *head) 369 + { 370 + int page_no, ch_count, ret; 399 371 struct rpcrdma_read_chunk *ch; 400 - struct svc_rdma_op_ctxt *ctxt = NULL; 401 - struct svc_rdma_req_map *rpl_map; 402 - struct svc_rdma_req_map *chl_map; 372 + u32 page_offset, byte_count; 373 + u64 rs_offset; 374 + rdma_reader_fn reader; 403 375 404 376 /* If no read list is present, return 0 */ 405 377 ch = svc_rdma_get_read_chunk(rmsgp); ··· 384 408 if (ch_count > RPCSVC_MAXPAGES) 385 409 return -EINVAL; 386 410 387 - /* Allocate temporary reply and chunk maps */ 388 - rpl_map = svc_rdma_get_req_map(); 389 - chl_map = svc_rdma_get_req_map(); 411 + /* The request is completed when the RDMA_READs complete. The 412 + * head context keeps all the pages that comprise the 413 + * request. 414 + */ 415 + head->arg.head[0] = rqstp->rq_arg.head[0]; 416 + head->arg.tail[0] = rqstp->rq_arg.tail[0]; 417 + head->arg.pages = &head->pages[head->count]; 418 + head->hdr_count = head->count; 419 + head->arg.page_base = 0; 420 + head->arg.page_len = 0; 421 + head->arg.len = rqstp->rq_arg.len; 422 + head->arg.buflen = rqstp->rq_arg.buflen; 390 423 391 - if (!xprt->sc_frmr_pg_list_len) 392 - sge_count = map_read_chunks(xprt, rqstp, hdr_ctxt, rmsgp, 393 - rpl_map, chl_map, ch_count, 394 - byte_count); 424 + /* Use FRMR if supported */ 425 + if (xprt->sc_dev_caps & SVCRDMA_DEVCAP_FAST_REG) 426 + reader = rdma_read_chunk_frmr; 395 427 else 396 - sge_count = fast_reg_read_chunks(xprt, rqstp, hdr_ctxt, rmsgp, 397 - rpl_map, chl_map, ch_count, 398 - byte_count); 399 - if (sge_count < 0) { 400 - err = -EIO; 401 - goto out; 402 - } 428 + reader = rdma_read_chunk_lcl; 403 429 404 - sgl_offset = 0; 405 - ch_no = 0; 406 - 430 + page_no = 0; page_offset = 0; 407 431 for (ch = (struct rpcrdma_read_chunk *)&rmsgp->rm_body.rm_chunks[0]; 408 - ch->rc_discrim != 0; ch++, ch_no++) { 409 - u64 rs_offset; 410 - next_sge: 411 - ctxt = svc_rdma_get_context(xprt); 412 - ctxt->direction = DMA_FROM_DEVICE; 413 - ctxt->frmr = hdr_ctxt->frmr; 414 - ctxt->read_hdr = NULL; 415 - clear_bit(RDMACTXT_F_LAST_CTXT, &ctxt->flags); 416 - clear_bit(RDMACTXT_F_FAST_UNREG, &ctxt->flags); 432 + ch->rc_discrim != 0; ch++) { 417 433 418 - /* Prepare READ WR */ 419 - memset(&read_wr, 0, sizeof read_wr); 420 - read_wr.wr_id = (unsigned long)ctxt; 421 - read_wr.opcode = IB_WR_RDMA_READ; 422 - ctxt->wr_op = read_wr.opcode; 423 - read_wr.send_flags = IB_SEND_SIGNALED; 424 - read_wr.wr.rdma.rkey = ntohl(ch->rc_target.rs_handle); 425 434 xdr_decode_hyper((__be32 *)&ch->rc_target.rs_offset, 426 435 &rs_offset); 427 - read_wr.wr.rdma.remote_addr = rs_offset + sgl_offset; 428 - read_wr.sg_list = ctxt->sge; 429 - read_wr.num_sge = 430 - rdma_read_max_sge(xprt, chl_map->ch[ch_no].count); 431 - err = rdma_set_ctxt_sge(xprt, ctxt, hdr_ctxt->frmr, 432 - &rpl_map->sge[chl_map->ch[ch_no].start], 433 - &sgl_offset, 434 - read_wr.num_sge); 435 - if (err) { 436 - svc_rdma_unmap_dma(ctxt); 437 - svc_rdma_put_context(ctxt, 0); 438 - goto out; 439 - } 440 - if (((ch+1)->rc_discrim == 0) && 441 - (read_wr.num_sge == chl_map->ch[ch_no].count)) { 442 - /* 443 - * Mark the last RDMA_READ with a bit to 444 - * indicate all RPC data has been fetched from 445 - * the client and the RPC needs to be enqueued. 446 - */ 447 - set_bit(RDMACTXT_F_LAST_CTXT, &ctxt->flags); 448 - if (hdr_ctxt->frmr) { 449 - set_bit(RDMACTXT_F_FAST_UNREG, &ctxt->flags); 450 - /* 451 - * Invalidate the local MR used to map the data 452 - * sink. 453 - */ 454 - if (xprt->sc_dev_caps & 455 - SVCRDMA_DEVCAP_READ_W_INV) { 456 - read_wr.opcode = 457 - IB_WR_RDMA_READ_WITH_INV; 458 - ctxt->wr_op = read_wr.opcode; 459 - read_wr.ex.invalidate_rkey = 460 - ctxt->frmr->mr->lkey; 461 - } else { 462 - /* Prepare INVALIDATE WR */ 463 - memset(&inv_wr, 0, sizeof inv_wr); 464 - inv_wr.opcode = IB_WR_LOCAL_INV; 465 - inv_wr.send_flags = IB_SEND_SIGNALED; 466 - inv_wr.ex.invalidate_rkey = 467 - hdr_ctxt->frmr->mr->lkey; 468 - read_wr.next = &inv_wr; 469 - } 470 - } 471 - ctxt->read_hdr = hdr_ctxt; 472 - } 473 - /* Post the read */ 474 - err = svc_rdma_send(xprt, &read_wr); 475 - if (err) { 476 - printk(KERN_ERR "svcrdma: Error %d posting RDMA_READ\n", 477 - err); 478 - set_bit(XPT_CLOSE, &xprt->sc_xprt.xpt_flags); 479 - svc_rdma_unmap_dma(ctxt); 480 - svc_rdma_put_context(ctxt, 0); 481 - goto out; 482 - } 483 - atomic_inc(&rdma_stat_read); 436 + byte_count = ntohl(ch->rc_target.rs_length); 484 437 485 - if (read_wr.num_sge < chl_map->ch[ch_no].count) { 486 - chl_map->ch[ch_no].count -= read_wr.num_sge; 487 - chl_map->ch[ch_no].start += read_wr.num_sge; 488 - goto next_sge; 438 + while (byte_count > 0) { 439 + ret = reader(xprt, rqstp, head, 440 + &page_no, &page_offset, 441 + ntohl(ch->rc_target.rs_handle), 442 + byte_count, rs_offset, 443 + ((ch+1)->rc_discrim == 0) /* last */ 444 + ); 445 + if (ret < 0) 446 + goto err; 447 + byte_count -= ret; 448 + rs_offset += ret; 449 + head->arg.buflen += ret; 489 450 } 490 - sgl_offset = 0; 491 - err = 1; 492 451 } 493 - 494 - out: 495 - svc_rdma_put_req_map(rpl_map); 496 - svc_rdma_put_req_map(chl_map); 497 - 452 + ret = 1; 453 + err: 498 454 /* Detach arg pages. svc_recv will replenish them */ 499 - for (ch_no = 0; &rqstp->rq_pages[ch_no] < rqstp->rq_respages; ch_no++) 500 - rqstp->rq_pages[ch_no] = NULL; 455 + for (page_no = 0; 456 + &rqstp->rq_pages[page_no] < rqstp->rq_respages; page_no++) 457 + rqstp->rq_pages[page_no] = NULL; 501 458 502 - return err; 459 + return ret; 503 460 } 504 461 505 462 static int rdma_read_complete(struct svc_rqst *rqstp, ··· 504 595 struct svc_rdma_op_ctxt, 505 596 dto_q); 506 597 list_del_init(&ctxt->dto_q); 507 - } 508 - if (ctxt) { 509 598 spin_unlock_bh(&rdma_xprt->sc_rq_dto_lock); 510 599 return rdma_read_complete(rqstp, ctxt); 511 - } 512 - 513 - if (!list_empty(&rdma_xprt->sc_rq_dto_q)) { 600 + } else if (!list_empty(&rdma_xprt->sc_rq_dto_q)) { 514 601 ctxt = list_entry(rdma_xprt->sc_rq_dto_q.next, 515 602 struct svc_rdma_op_ctxt, 516 603 dto_q); ··· 526 621 if (test_bit(XPT_CLOSE, &xprt->xpt_flags)) 527 622 goto close_out; 528 623 529 - BUG_ON(ret); 530 624 goto out; 531 625 } 532 626 dprintk("svcrdma: processing ctxt=%p on xprt=%p, rqstp=%p, status=%d\n", ··· 548 644 } 549 645 550 646 /* Read read-list data. */ 551 - ret = rdma_read_xdr(rdma_xprt, rmsgp, rqstp, ctxt); 647 + ret = rdma_read_chunks(rdma_xprt, rmsgp, rqstp, ctxt); 552 648 if (ret > 0) { 553 649 /* read-list posted, defer until data received from client. */ 554 650 goto defer; 555 - } 556 - if (ret < 0) { 651 + } else if (ret < 0) { 557 652 /* Post of read-list failed, free context. */ 558 653 svc_rdma_put_context(ctxt, 1); 559 654 return 0;
+22 -208
net/sunrpc/xprtrdma/svc_rdma_sendto.c
··· 1 1 /* 2 + * Copyright (c) 2014 Open Grid Computing, Inc. All rights reserved. 2 3 * Copyright (c) 2005-2006 Network Appliance, Inc. All rights reserved. 3 4 * 4 5 * This software is available to you under a choice of one of two ··· 50 49 51 50 #define RPCDBG_FACILITY RPCDBG_SVCXPRT 52 51 53 - /* Encode an XDR as an array of IB SGE 54 - * 55 - * Assumptions: 56 - * - head[0] is physically contiguous. 57 - * - tail[0] is physically contiguous. 58 - * - pages[] is not physically or virtually contiguous and consists of 59 - * PAGE_SIZE elements. 60 - * 61 - * Output: 62 - * SGE[0] reserved for RCPRDMA header 63 - * SGE[1] data from xdr->head[] 64 - * SGE[2..sge_count-2] data from xdr->pages[] 65 - * SGE[sge_count-1] data from xdr->tail. 66 - * 67 - * The max SGE we need is the length of the XDR / pagesize + one for 68 - * head + one for tail + one for RPCRDMA header. Since RPCSVC_MAXPAGES 69 - * reserves a page for both the request and the reply header, and this 70 - * array is only concerned with the reply we are assured that we have 71 - * on extra page for the RPCRMDA header. 72 - */ 73 - static int fast_reg_xdr(struct svcxprt_rdma *xprt, 74 - struct xdr_buf *xdr, 75 - struct svc_rdma_req_map *vec) 76 - { 77 - int sge_no; 78 - u32 sge_bytes; 79 - u32 page_bytes; 80 - u32 page_off; 81 - int page_no = 0; 82 - u8 *frva; 83 - struct svc_rdma_fastreg_mr *frmr; 84 - 85 - frmr = svc_rdma_get_frmr(xprt); 86 - if (IS_ERR(frmr)) 87 - return -ENOMEM; 88 - vec->frmr = frmr; 89 - 90 - /* Skip the RPCRDMA header */ 91 - sge_no = 1; 92 - 93 - /* Map the head. */ 94 - frva = (void *)((unsigned long)(xdr->head[0].iov_base) & PAGE_MASK); 95 - vec->sge[sge_no].iov_base = xdr->head[0].iov_base; 96 - vec->sge[sge_no].iov_len = xdr->head[0].iov_len; 97 - vec->count = 2; 98 - sge_no++; 99 - 100 - /* Map the XDR head */ 101 - frmr->kva = frva; 102 - frmr->direction = DMA_TO_DEVICE; 103 - frmr->access_flags = 0; 104 - frmr->map_len = PAGE_SIZE; 105 - frmr->page_list_len = 1; 106 - page_off = (unsigned long)xdr->head[0].iov_base & ~PAGE_MASK; 107 - frmr->page_list->page_list[page_no] = 108 - ib_dma_map_page(xprt->sc_cm_id->device, 109 - virt_to_page(xdr->head[0].iov_base), 110 - page_off, 111 - PAGE_SIZE - page_off, 112 - DMA_TO_DEVICE); 113 - if (ib_dma_mapping_error(xprt->sc_cm_id->device, 114 - frmr->page_list->page_list[page_no])) 115 - goto fatal_err; 116 - atomic_inc(&xprt->sc_dma_used); 117 - 118 - /* Map the XDR page list */ 119 - page_off = xdr->page_base; 120 - page_bytes = xdr->page_len + page_off; 121 - if (!page_bytes) 122 - goto encode_tail; 123 - 124 - /* Map the pages */ 125 - vec->sge[sge_no].iov_base = frva + frmr->map_len + page_off; 126 - vec->sge[sge_no].iov_len = page_bytes; 127 - sge_no++; 128 - while (page_bytes) { 129 - struct page *page; 130 - 131 - page = xdr->pages[page_no++]; 132 - sge_bytes = min_t(u32, page_bytes, (PAGE_SIZE - page_off)); 133 - page_bytes -= sge_bytes; 134 - 135 - frmr->page_list->page_list[page_no] = 136 - ib_dma_map_page(xprt->sc_cm_id->device, 137 - page, page_off, 138 - sge_bytes, DMA_TO_DEVICE); 139 - if (ib_dma_mapping_error(xprt->sc_cm_id->device, 140 - frmr->page_list->page_list[page_no])) 141 - goto fatal_err; 142 - 143 - atomic_inc(&xprt->sc_dma_used); 144 - page_off = 0; /* reset for next time through loop */ 145 - frmr->map_len += PAGE_SIZE; 146 - frmr->page_list_len++; 147 - } 148 - vec->count++; 149 - 150 - encode_tail: 151 - /* Map tail */ 152 - if (0 == xdr->tail[0].iov_len) 153 - goto done; 154 - 155 - vec->count++; 156 - vec->sge[sge_no].iov_len = xdr->tail[0].iov_len; 157 - 158 - if (((unsigned long)xdr->tail[0].iov_base & PAGE_MASK) == 159 - ((unsigned long)xdr->head[0].iov_base & PAGE_MASK)) { 160 - /* 161 - * If head and tail use the same page, we don't need 162 - * to map it again. 163 - */ 164 - vec->sge[sge_no].iov_base = xdr->tail[0].iov_base; 165 - } else { 166 - void *va; 167 - 168 - /* Map another page for the tail */ 169 - page_off = (unsigned long)xdr->tail[0].iov_base & ~PAGE_MASK; 170 - va = (void *)((unsigned long)xdr->tail[0].iov_base & PAGE_MASK); 171 - vec->sge[sge_no].iov_base = frva + frmr->map_len + page_off; 172 - 173 - frmr->page_list->page_list[page_no] = 174 - ib_dma_map_page(xprt->sc_cm_id->device, virt_to_page(va), 175 - page_off, 176 - PAGE_SIZE, 177 - DMA_TO_DEVICE); 178 - if (ib_dma_mapping_error(xprt->sc_cm_id->device, 179 - frmr->page_list->page_list[page_no])) 180 - goto fatal_err; 181 - atomic_inc(&xprt->sc_dma_used); 182 - frmr->map_len += PAGE_SIZE; 183 - frmr->page_list_len++; 184 - } 185 - 186 - done: 187 - if (svc_rdma_fastreg(xprt, frmr)) 188 - goto fatal_err; 189 - 190 - return 0; 191 - 192 - fatal_err: 193 - printk("svcrdma: Error fast registering memory for xprt %p\n", xprt); 194 - vec->frmr = NULL; 195 - svc_rdma_put_frmr(xprt, frmr); 196 - return -EIO; 197 - } 198 - 199 52 static int map_xdr(struct svcxprt_rdma *xprt, 200 53 struct xdr_buf *xdr, 201 54 struct svc_rdma_req_map *vec) ··· 62 207 63 208 BUG_ON(xdr->len != 64 209 (xdr->head[0].iov_len + xdr->page_len + xdr->tail[0].iov_len)); 65 - 66 - if (xprt->sc_frmr_pg_list_len) 67 - return fast_reg_xdr(xprt, xdr, vec); 68 210 69 211 /* Skip the first sge, this is for the RPCRDMA header */ 70 212 sge_no = 1; ··· 134 282 } 135 283 136 284 /* Assumptions: 137 - * - We are using FRMR 138 - * - or - 139 285 * - The specified write_len can be represented in sc_max_sge * PAGE_SIZE 140 286 */ 141 287 static int send_write(struct svcxprt_rdma *xprt, struct svc_rqst *rqstp, ··· 177 327 sge_bytes = min_t(size_t, 178 328 bc, vec->sge[xdr_sge_no].iov_len-sge_off); 179 329 sge[sge_no].length = sge_bytes; 180 - if (!vec->frmr) { 181 - sge[sge_no].addr = 182 - dma_map_xdr(xprt, &rqstp->rq_res, xdr_off, 183 - sge_bytes, DMA_TO_DEVICE); 184 - xdr_off += sge_bytes; 185 - if (ib_dma_mapping_error(xprt->sc_cm_id->device, 186 - sge[sge_no].addr)) 187 - goto err; 188 - atomic_inc(&xprt->sc_dma_used); 189 - sge[sge_no].lkey = xprt->sc_dma_lkey; 190 - } else { 191 - sge[sge_no].addr = (unsigned long) 192 - vec->sge[xdr_sge_no].iov_base + sge_off; 193 - sge[sge_no].lkey = vec->frmr->mr->lkey; 194 - } 330 + sge[sge_no].addr = 331 + dma_map_xdr(xprt, &rqstp->rq_res, xdr_off, 332 + sge_bytes, DMA_TO_DEVICE); 333 + xdr_off += sge_bytes; 334 + if (ib_dma_mapping_error(xprt->sc_cm_id->device, 335 + sge[sge_no].addr)) 336 + goto err; 337 + atomic_inc(&xprt->sc_dma_used); 338 + sge[sge_no].lkey = xprt->sc_dma_lkey; 195 339 ctxt->count++; 196 - ctxt->frmr = vec->frmr; 197 340 sge_off = 0; 198 341 sge_no++; 199 342 xdr_sge_no++; ··· 212 369 return 0; 213 370 err: 214 371 svc_rdma_unmap_dma(ctxt); 215 - svc_rdma_put_frmr(xprt, vec->frmr); 216 372 svc_rdma_put_context(ctxt, 0); 217 373 /* Fatal error, close transport */ 218 374 return -EIO; ··· 239 397 res_ary = (struct rpcrdma_write_array *) 240 398 &rdma_resp->rm_body.rm_chunks[1]; 241 399 242 - if (vec->frmr) 243 - max_write = vec->frmr->map_len; 244 - else 245 - max_write = xprt->sc_max_sge * PAGE_SIZE; 400 + max_write = xprt->sc_max_sge * PAGE_SIZE; 246 401 247 402 /* Write chunks start at the pagelist */ 248 403 for (xdr_off = rqstp->rq_res.head[0].iov_len, chunk_no = 0; ··· 311 472 res_ary = (struct rpcrdma_write_array *) 312 473 &rdma_resp->rm_body.rm_chunks[2]; 313 474 314 - if (vec->frmr) 315 - max_write = vec->frmr->map_len; 316 - else 317 - max_write = xprt->sc_max_sge * PAGE_SIZE; 475 + max_write = xprt->sc_max_sge * PAGE_SIZE; 318 476 319 477 /* xdr offset starts at RPC message */ 320 478 nchunks = ntohl(arg_ary->wc_nchunks); ··· 381 545 int byte_count) 382 546 { 383 547 struct ib_send_wr send_wr; 384 - struct ib_send_wr inv_wr; 385 548 int sge_no; 386 549 int sge_bytes; 387 550 int page_no; ··· 394 559 "svcrdma: could not post a receive buffer, err=%d." 395 560 "Closing transport %p.\n", ret, rdma); 396 561 set_bit(XPT_CLOSE, &rdma->sc_xprt.xpt_flags); 397 - svc_rdma_put_frmr(rdma, vec->frmr); 398 562 svc_rdma_put_context(ctxt, 0); 399 563 return -ENOTCONN; 400 564 } ··· 401 567 /* Prepare the context */ 402 568 ctxt->pages[0] = page; 403 569 ctxt->count = 1; 404 - ctxt->frmr = vec->frmr; 405 - if (vec->frmr) 406 - set_bit(RDMACTXT_F_FAST_UNREG, &ctxt->flags); 407 - else 408 - clear_bit(RDMACTXT_F_FAST_UNREG, &ctxt->flags); 409 570 410 571 /* Prepare the SGE for the RPCRDMA Header */ 411 572 ctxt->sge[0].lkey = rdma->sc_dma_lkey; ··· 419 590 int xdr_off = 0; 420 591 sge_bytes = min_t(size_t, vec->sge[sge_no].iov_len, byte_count); 421 592 byte_count -= sge_bytes; 422 - if (!vec->frmr) { 423 - ctxt->sge[sge_no].addr = 424 - dma_map_xdr(rdma, &rqstp->rq_res, xdr_off, 425 - sge_bytes, DMA_TO_DEVICE); 426 - xdr_off += sge_bytes; 427 - if (ib_dma_mapping_error(rdma->sc_cm_id->device, 428 - ctxt->sge[sge_no].addr)) 429 - goto err; 430 - atomic_inc(&rdma->sc_dma_used); 431 - ctxt->sge[sge_no].lkey = rdma->sc_dma_lkey; 432 - } else { 433 - ctxt->sge[sge_no].addr = (unsigned long) 434 - vec->sge[sge_no].iov_base; 435 - ctxt->sge[sge_no].lkey = vec->frmr->mr->lkey; 436 - } 593 + ctxt->sge[sge_no].addr = 594 + dma_map_xdr(rdma, &rqstp->rq_res, xdr_off, 595 + sge_bytes, DMA_TO_DEVICE); 596 + xdr_off += sge_bytes; 597 + if (ib_dma_mapping_error(rdma->sc_cm_id->device, 598 + ctxt->sge[sge_no].addr)) 599 + goto err; 600 + atomic_inc(&rdma->sc_dma_used); 601 + ctxt->sge[sge_no].lkey = rdma->sc_dma_lkey; 437 602 ctxt->sge[sge_no].length = sge_bytes; 438 603 } 439 604 BUG_ON(byte_count != 0); ··· 450 627 ctxt->sge[page_no+1].length = 0; 451 628 } 452 629 rqstp->rq_next_page = rqstp->rq_respages + 1; 630 + 453 631 BUG_ON(sge_no > rdma->sc_max_sge); 454 632 memset(&send_wr, 0, sizeof send_wr); 455 633 ctxt->wr_op = IB_WR_SEND; ··· 459 635 send_wr.num_sge = sge_no; 460 636 send_wr.opcode = IB_WR_SEND; 461 637 send_wr.send_flags = IB_SEND_SIGNALED; 462 - if (vec->frmr) { 463 - /* Prepare INVALIDATE WR */ 464 - memset(&inv_wr, 0, sizeof inv_wr); 465 - inv_wr.opcode = IB_WR_LOCAL_INV; 466 - inv_wr.send_flags = IB_SEND_SIGNALED; 467 - inv_wr.ex.invalidate_rkey = 468 - vec->frmr->mr->lkey; 469 - send_wr.next = &inv_wr; 470 - } 471 638 472 639 ret = svc_rdma_send(rdma, &send_wr); 473 640 if (ret) ··· 468 653 469 654 err: 470 655 svc_rdma_unmap_dma(ctxt); 471 - svc_rdma_put_frmr(rdma, vec->frmr); 472 656 svc_rdma_put_context(ctxt, 1); 473 657 return -EIO; 474 658 }
+43 -26
net/sunrpc/xprtrdma/svc_rdma_transport.c
··· 1 1 /* 2 + * Copyright (c) 2014 Open Grid Computing, Inc. All rights reserved. 2 3 * Copyright (c) 2005-2007 Network Appliance, Inc. All rights reserved. 3 4 * 4 5 * This software is available to you under a choice of one of two ··· 66 65 static void svc_rdma_detach(struct svc_xprt *xprt); 67 66 static void svc_rdma_free(struct svc_xprt *xprt); 68 67 static int svc_rdma_has_wspace(struct svc_xprt *xprt); 68 + static int svc_rdma_secure_port(struct svc_rqst *); 69 69 static void rq_cq_reap(struct svcxprt_rdma *xprt); 70 70 static void sq_cq_reap(struct svcxprt_rdma *xprt); 71 71 ··· 84 82 .xpo_prep_reply_hdr = svc_rdma_prep_reply_hdr, 85 83 .xpo_has_wspace = svc_rdma_has_wspace, 86 84 .xpo_accept = svc_rdma_accept, 85 + .xpo_secure_port = svc_rdma_secure_port, 87 86 }; 88 87 89 88 struct svc_xprt_class svc_rdma_class = { ··· 163 160 schedule_timeout_uninterruptible(msecs_to_jiffies(500)); 164 161 } 165 162 map->count = 0; 166 - map->frmr = NULL; 167 163 return map; 168 164 } 169 165 ··· 338 336 339 337 switch (ctxt->wr_op) { 340 338 case IB_WR_SEND: 341 - if (test_bit(RDMACTXT_F_FAST_UNREG, &ctxt->flags)) 342 - svc_rdma_put_frmr(xprt, ctxt->frmr); 339 + BUG_ON(ctxt->frmr); 343 340 svc_rdma_put_context(ctxt, 1); 344 341 break; 345 342 346 343 case IB_WR_RDMA_WRITE: 344 + BUG_ON(ctxt->frmr); 347 345 svc_rdma_put_context(ctxt, 0); 348 346 break; 349 347 350 348 case IB_WR_RDMA_READ: 351 349 case IB_WR_RDMA_READ_WITH_INV: 350 + svc_rdma_put_frmr(xprt, ctxt->frmr); 352 351 if (test_bit(RDMACTXT_F_LAST_CTXT, &ctxt->flags)) { 353 352 struct svc_rdma_op_ctxt *read_hdr = ctxt->read_hdr; 354 353 BUG_ON(!read_hdr); 355 - if (test_bit(RDMACTXT_F_FAST_UNREG, &ctxt->flags)) 356 - svc_rdma_put_frmr(xprt, ctxt->frmr); 357 354 spin_lock_bh(&xprt->sc_rq_dto_lock); 358 355 set_bit(XPT_DATA, &xprt->sc_xprt.xpt_flags); 359 356 list_add_tail(&read_hdr->dto_q, ··· 364 363 break; 365 364 366 365 default: 366 + BUG_ON(1); 367 367 printk(KERN_ERR "svcrdma: unexpected completion type, " 368 368 "opcode=%d\n", 369 369 ctxt->wr_op); ··· 380 378 static void sq_cq_reap(struct svcxprt_rdma *xprt) 381 379 { 382 380 struct svc_rdma_op_ctxt *ctxt = NULL; 383 - struct ib_wc wc; 381 + struct ib_wc wc_a[6]; 382 + struct ib_wc *wc; 384 383 struct ib_cq *cq = xprt->sc_sq_cq; 385 384 int ret; 385 + 386 + memset(wc_a, 0, sizeof(wc_a)); 386 387 387 388 if (!test_and_clear_bit(RDMAXPRT_SQ_PENDING, &xprt->sc_flags)) 388 389 return; 389 390 390 391 ib_req_notify_cq(xprt->sc_sq_cq, IB_CQ_NEXT_COMP); 391 392 atomic_inc(&rdma_stat_sq_poll); 392 - while ((ret = ib_poll_cq(cq, 1, &wc)) > 0) { 393 - if (wc.status != IB_WC_SUCCESS) 394 - /* Close the transport */ 395 - set_bit(XPT_CLOSE, &xprt->sc_xprt.xpt_flags); 393 + while ((ret = ib_poll_cq(cq, ARRAY_SIZE(wc_a), wc_a)) > 0) { 394 + int i; 396 395 397 - /* Decrement used SQ WR count */ 398 - atomic_dec(&xprt->sc_sq_count); 399 - wake_up(&xprt->sc_send_wait); 396 + for (i = 0; i < ret; i++) { 397 + wc = &wc_a[i]; 398 + if (wc->status != IB_WC_SUCCESS) { 399 + dprintk("svcrdma: sq wc err status %d\n", 400 + wc->status); 400 401 401 - ctxt = (struct svc_rdma_op_ctxt *)(unsigned long)wc.wr_id; 402 - if (ctxt) 403 - process_context(xprt, ctxt); 402 + /* Close the transport */ 403 + set_bit(XPT_CLOSE, &xprt->sc_xprt.xpt_flags); 404 + } 404 405 405 - svc_xprt_put(&xprt->sc_xprt); 406 + /* Decrement used SQ WR count */ 407 + atomic_dec(&xprt->sc_sq_count); 408 + wake_up(&xprt->sc_send_wait); 409 + 410 + ctxt = (struct svc_rdma_op_ctxt *) 411 + (unsigned long)wc->wr_id; 412 + if (ctxt) 413 + process_context(xprt, ctxt); 414 + 415 + svc_xprt_put(&xprt->sc_xprt); 416 + } 406 417 } 407 418 408 419 if (ctxt) ··· 1008 993 need_dma_mr = 0; 1009 994 break; 1010 995 case RDMA_TRANSPORT_IB: 1011 - if (!(devattr.device_cap_flags & IB_DEVICE_LOCAL_DMA_LKEY)) { 996 + if (!(newxprt->sc_dev_caps & SVCRDMA_DEVCAP_FAST_REG)) { 997 + need_dma_mr = 1; 998 + dma_mr_acc = IB_ACCESS_LOCAL_WRITE; 999 + } else if (!(devattr.device_cap_flags & 1000 + IB_DEVICE_LOCAL_DMA_LKEY)) { 1012 1001 need_dma_mr = 1; 1013 1002 dma_mr_acc = IB_ACCESS_LOCAL_WRITE; 1014 1003 } else ··· 1209 1190 container_of(xprt, struct svcxprt_rdma, sc_xprt); 1210 1191 1211 1192 /* 1212 - * If there are fewer SQ WR available than required to send a 1213 - * simple response, return false. 1214 - */ 1215 - if ((rdma->sc_sq_depth - atomic_read(&rdma->sc_sq_count) < 3)) 1216 - return 0; 1217 - 1218 - /* 1219 - * ...or there are already waiters on the SQ, 1193 + * If there are already waiters on the SQ, 1220 1194 * return false. 1221 1195 */ 1222 1196 if (waitqueue_active(&rdma->sc_send_wait)) 1223 1197 return 0; 1224 1198 1225 1199 /* Otherwise return true. */ 1200 + return 1; 1201 + } 1202 + 1203 + static int svc_rdma_secure_port(struct svc_rqst *rqstp) 1204 + { 1226 1205 return 1; 1227 1206 } 1228 1207