diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-01-30 13:18:43 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-01-30 13:18:43 -0500 |
commit | d9894c228b11273e720bb63ba120d1d326fe9d94 (patch) | |
tree | c9b91b716f281f5accf8860dfadb1ac95abf0090 /fs | |
parent | dfa19426160046770b3a38985042df9c9760a25a (diff) | |
parent | ed47b062ce9546fbe1eebf9da6937df4c5035372 (diff) |
Merge branch 'for-3.14' of git://linux-nfs.org/~bfields/linux
Pull nfsd updates from Bruce Fields:
- Handle some loose ends from the vfs read delegation support.
(For example nfsd can stop breaking leases on its own in a
fewer places where it can now depend on the vfs to.)
- Make life a little easier for NFSv4-only configurations
(thanks to Kinglong Mee).
- Fix some gss-proxy problems (thanks Jeff Layton).
- miscellaneous bug fixes and cleanup
* 'for-3.14' of git://linux-nfs.org/~bfields/linux: (38 commits)
nfsd: consider CLAIM_FH when handing out delegation
nfsd4: fix delegation-unlink/rename race
nfsd4: delay setting current_fh in open
nfsd4: minor nfs4_setlease cleanup
gss_krb5: use lcm from kernel lib
nfsd4: decrease nfsd4_encode_fattr stack usage
nfsd: fix encode_entryplus_baggage stack usage
nfsd4: simplify xdr encoding of nfsv4 names
nfsd4: encode_rdattr_error cleanup
nfsd4: nfsd4_encode_fattr cleanup
minor svcauth_gss.c cleanup
nfsd4: better VERIFY comment
nfsd4: break only delegations when appropriate
NFSD: Fix a memory leak in nfsd4_create_session
sunrpc: get rid of use_gssp_lock
sunrpc: fix potential race between setting use_gss_proxy and the upcall rpc_clnt
sunrpc: don't wait for write before allowing reads from use-gss-proxy file
nfsd: get rid of unused function definition
Define op_iattr for nfsd4_open instead using macro
NFSD: fix compile warning without CONFIG_NFSD_V3
...
Diffstat (limited to 'fs')
-rw-r--r-- | fs/nfsd/acl.h | 2 | ||||
-rw-r--r-- | fs/nfsd/cache.h | 8 | ||||
-rw-r--r-- | fs/nfsd/idmap.h | 4 | ||||
-rw-r--r-- | fs/nfsd/netns.h | 1 | ||||
-rw-r--r-- | fs/nfsd/nfs3xdr.c | 14 | ||||
-rw-r--r-- | fs/nfsd/nfs4acl.c | 20 | ||||
-rw-r--r-- | fs/nfsd/nfs4idmap.c | 50 | ||||
-rw-r--r-- | fs/nfsd/nfs4proc.c | 57 | ||||
-rw-r--r-- | fs/nfsd/nfs4state.c | 40 | ||||
-rw-r--r-- | fs/nfsd/nfs4xdr.c | 178 | ||||
-rw-r--r-- | fs/nfsd/nfscache.c | 36 | ||||
-rw-r--r-- | fs/nfsd/nfssvc.c | 30 | ||||
-rw-r--r-- | fs/nfsd/nfsxdr.c | 2 | ||||
-rw-r--r-- | fs/nfsd/vfs.c | 40 | ||||
-rw-r--r-- | fs/nfsd/vfs.h | 2 | ||||
-rw-r--r-- | fs/nfsd/xdr3.h | 3 | ||||
-rw-r--r-- | fs/nfsd/xdr4.h | 4 |
17 files changed, 219 insertions, 272 deletions
diff --git a/fs/nfsd/acl.h b/fs/nfsd/acl.h index 8b68218e2c1c..a812fd1b92a4 100644 --- a/fs/nfsd/acl.h +++ b/fs/nfsd/acl.h | |||
@@ -45,7 +45,7 @@ struct svc_rqst; | |||
45 | 45 | ||
46 | struct nfs4_acl *nfs4_acl_new(int); | 46 | struct nfs4_acl *nfs4_acl_new(int); |
47 | int nfs4_acl_get_whotype(char *, u32); | 47 | int nfs4_acl_get_whotype(char *, u32); |
48 | int nfs4_acl_write_who(int who, char *p); | 48 | __be32 nfs4_acl_write_who(int who, __be32 **p, int *len); |
49 | 49 | ||
50 | int nfsd4_get_nfs4_acl(struct svc_rqst *rqstp, struct dentry *dentry, | 50 | int nfsd4_get_nfs4_acl(struct svc_rqst *rqstp, struct dentry *dentry, |
51 | struct nfs4_acl **acl); | 51 | struct nfs4_acl **acl); |
diff --git a/fs/nfsd/cache.h b/fs/nfsd/cache.h index d5c5b3e00266..b582f9ab6b2a 100644 --- a/fs/nfsd/cache.h +++ b/fs/nfsd/cache.h | |||
@@ -84,12 +84,4 @@ int nfsd_cache_lookup(struct svc_rqst *); | |||
84 | void nfsd_cache_update(struct svc_rqst *, int, __be32 *); | 84 | void nfsd_cache_update(struct svc_rqst *, int, __be32 *); |
85 | int nfsd_reply_cache_stats_open(struct inode *, struct file *); | 85 | int nfsd_reply_cache_stats_open(struct inode *, struct file *); |
86 | 86 | ||
87 | #ifdef CONFIG_NFSD_V4 | ||
88 | void nfsd4_set_statp(struct svc_rqst *rqstp, __be32 *statp); | ||
89 | #else /* CONFIG_NFSD_V4 */ | ||
90 | static inline void nfsd4_set_statp(struct svc_rqst *rqstp, __be32 *statp) | ||
91 | { | ||
92 | } | ||
93 | #endif /* CONFIG_NFSD_V4 */ | ||
94 | |||
95 | #endif /* NFSCACHE_H */ | 87 | #endif /* NFSCACHE_H */ |
diff --git a/fs/nfsd/idmap.h b/fs/nfsd/idmap.h index bf95f6b817a4..66e58db01936 100644 --- a/fs/nfsd/idmap.h +++ b/fs/nfsd/idmap.h | |||
@@ -56,7 +56,7 @@ static inline void nfsd_idmap_shutdown(struct net *net) | |||
56 | 56 | ||
57 | __be32 nfsd_map_name_to_uid(struct svc_rqst *, const char *, size_t, kuid_t *); | 57 | __be32 nfsd_map_name_to_uid(struct svc_rqst *, const char *, size_t, kuid_t *); |
58 | __be32 nfsd_map_name_to_gid(struct svc_rqst *, const char *, size_t, kgid_t *); | 58 | __be32 nfsd_map_name_to_gid(struct svc_rqst *, const char *, size_t, kgid_t *); |
59 | int nfsd_map_uid_to_name(struct svc_rqst *, kuid_t, char *); | 59 | __be32 nfsd4_encode_user(struct svc_rqst *, kuid_t, __be32 **, int *); |
60 | int nfsd_map_gid_to_name(struct svc_rqst *, kgid_t, char *); | 60 | __be32 nfsd4_encode_group(struct svc_rqst *, kgid_t, __be32 **, int *); |
61 | 61 | ||
62 | #endif /* LINUX_NFSD_IDMAP_H */ | 62 | #endif /* LINUX_NFSD_IDMAP_H */ |
diff --git a/fs/nfsd/netns.h b/fs/nfsd/netns.h index 849a7c3ced22..d32b3aa6600d 100644 --- a/fs/nfsd/netns.h +++ b/fs/nfsd/netns.h | |||
@@ -95,6 +95,7 @@ struct nfsd_net { | |||
95 | time_t nfsd4_grace; | 95 | time_t nfsd4_grace; |
96 | 96 | ||
97 | bool nfsd_net_up; | 97 | bool nfsd_net_up; |
98 | bool lockd_up; | ||
98 | 99 | ||
99 | /* | 100 | /* |
100 | * Time of server startup | 101 | * Time of server startup |
diff --git a/fs/nfsd/nfs3xdr.c b/fs/nfsd/nfs3xdr.c index 14d9ecb96cff..de6e39e12cb3 100644 --- a/fs/nfsd/nfs3xdr.c +++ b/fs/nfsd/nfs3xdr.c | |||
@@ -168,7 +168,7 @@ encode_fattr3(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp, | |||
168 | struct kstat *stat) | 168 | struct kstat *stat) |
169 | { | 169 | { |
170 | *p++ = htonl(nfs3_ftypes[(stat->mode & S_IFMT) >> 12]); | 170 | *p++ = htonl(nfs3_ftypes[(stat->mode & S_IFMT) >> 12]); |
171 | *p++ = htonl((u32) stat->mode); | 171 | *p++ = htonl((u32) (stat->mode & S_IALLUGO)); |
172 | *p++ = htonl((u32) stat->nlink); | 172 | *p++ = htonl((u32) stat->nlink); |
173 | *p++ = htonl((u32) from_kuid(&init_user_ns, stat->uid)); | 173 | *p++ = htonl((u32) from_kuid(&init_user_ns, stat->uid)); |
174 | *p++ = htonl((u32) from_kgid(&init_user_ns, stat->gid)); | 174 | *p++ = htonl((u32) from_kgid(&init_user_ns, stat->gid)); |
@@ -842,21 +842,21 @@ out: | |||
842 | 842 | ||
843 | static __be32 *encode_entryplus_baggage(struct nfsd3_readdirres *cd, __be32 *p, const char *name, int namlen) | 843 | static __be32 *encode_entryplus_baggage(struct nfsd3_readdirres *cd, __be32 *p, const char *name, int namlen) |
844 | { | 844 | { |
845 | struct svc_fh fh; | 845 | struct svc_fh *fh = &cd->scratch; |
846 | __be32 err; | 846 | __be32 err; |
847 | 847 | ||
848 | fh_init(&fh, NFS3_FHSIZE); | 848 | fh_init(fh, NFS3_FHSIZE); |
849 | err = compose_entry_fh(cd, &fh, name, namlen); | 849 | err = compose_entry_fh(cd, fh, name, namlen); |
850 | if (err) { | 850 | if (err) { |
851 | *p++ = 0; | 851 | *p++ = 0; |
852 | *p++ = 0; | 852 | *p++ = 0; |
853 | goto out; | 853 | goto out; |
854 | } | 854 | } |
855 | p = encode_post_op_attr(cd->rqstp, p, &fh); | 855 | p = encode_post_op_attr(cd->rqstp, p, fh); |
856 | *p++ = xdr_one; /* yes, a file handle follows */ | 856 | *p++ = xdr_one; /* yes, a file handle follows */ |
857 | p = encode_fh(p, &fh); | 857 | p = encode_fh(p, fh); |
858 | out: | 858 | out: |
859 | fh_put(&fh); | 859 | fh_put(fh); |
860 | return p; | 860 | return p; |
861 | } | 861 | } |
862 | 862 | ||
diff --git a/fs/nfsd/nfs4acl.c b/fs/nfsd/nfs4acl.c index 649ad7cf2204..d3a587144222 100644 --- a/fs/nfsd/nfs4acl.c +++ b/fs/nfsd/nfs4acl.c | |||
@@ -38,6 +38,7 @@ | |||
38 | #include <linux/nfs_fs.h> | 38 | #include <linux/nfs_fs.h> |
39 | #include <linux/export.h> | 39 | #include <linux/export.h> |
40 | #include "nfsfh.h" | 40 | #include "nfsfh.h" |
41 | #include "nfsd.h" | ||
41 | #include "acl.h" | 42 | #include "acl.h" |
42 | #include "vfs.h" | 43 | #include "vfs.h" |
43 | 44 | ||
@@ -916,17 +917,22 @@ nfs4_acl_get_whotype(char *p, u32 len) | |||
916 | return NFS4_ACL_WHO_NAMED; | 917 | return NFS4_ACL_WHO_NAMED; |
917 | } | 918 | } |
918 | 919 | ||
919 | int | 920 | __be32 nfs4_acl_write_who(int who, __be32 **p, int *len) |
920 | nfs4_acl_write_who(int who, char *p) | ||
921 | { | 921 | { |
922 | int i; | 922 | int i; |
923 | int bytes; | ||
923 | 924 | ||
924 | for (i = 0; i < ARRAY_SIZE(s2t_map); i++) { | 925 | for (i = 0; i < ARRAY_SIZE(s2t_map); i++) { |
925 | if (s2t_map[i].type == who) { | 926 | if (s2t_map[i].type != who) |
926 | memcpy(p, s2t_map[i].string, s2t_map[i].stringlen); | 927 | continue; |
927 | return s2t_map[i].stringlen; | 928 | bytes = 4 + (XDR_QUADLEN(s2t_map[i].stringlen) << 2); |
928 | } | 929 | if (bytes > *len) |
930 | return nfserr_resource; | ||
931 | *p = xdr_encode_opaque(*p, s2t_map[i].string, | ||
932 | s2t_map[i].stringlen); | ||
933 | *len -= bytes; | ||
934 | return 0; | ||
929 | } | 935 | } |
930 | BUG(); | 936 | WARN_ON_ONCE(1); |
931 | return -1; | 937 | return -1; |
932 | } | 938 | } |
diff --git a/fs/nfsd/nfs4idmap.c b/fs/nfsd/nfs4idmap.c index 4832fd819f88..c0dfde68742e 100644 --- a/fs/nfsd/nfs4idmap.c +++ b/fs/nfsd/nfs4idmap.c | |||
@@ -551,27 +551,46 @@ idmap_name_to_id(struct svc_rqst *rqstp, int type, const char *name, u32 namelen | |||
551 | return 0; | 551 | return 0; |
552 | } | 552 | } |
553 | 553 | ||
554 | static int | 554 | static __be32 encode_ascii_id(u32 id, __be32 **p, int *buflen) |
555 | idmap_id_to_name(struct svc_rqst *rqstp, int type, u32 id, char *name) | 555 | { |
556 | char buf[11]; | ||
557 | int len; | ||
558 | int bytes; | ||
559 | |||
560 | len = sprintf(buf, "%u", id); | ||
561 | bytes = 4 + (XDR_QUADLEN(len) << 2); | ||
562 | if (bytes > *buflen) | ||
563 | return nfserr_resource; | ||
564 | *p = xdr_encode_opaque(*p, buf, len); | ||
565 | *buflen -= bytes; | ||
566 | return 0; | ||
567 | } | ||
568 | |||
569 | static __be32 idmap_id_to_name(struct svc_rqst *rqstp, int type, u32 id, __be32 **p, int *buflen) | ||
556 | { | 570 | { |
557 | struct ent *item, key = { | 571 | struct ent *item, key = { |
558 | .id = id, | 572 | .id = id, |
559 | .type = type, | 573 | .type = type, |
560 | }; | 574 | }; |
561 | int ret; | 575 | int ret; |
576 | int bytes; | ||
562 | struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id); | 577 | struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id); |
563 | 578 | ||
564 | strlcpy(key.authname, rqst_authname(rqstp), sizeof(key.authname)); | 579 | strlcpy(key.authname, rqst_authname(rqstp), sizeof(key.authname)); |
565 | ret = idmap_lookup(rqstp, idtoname_lookup, &key, nn->idtoname_cache, &item); | 580 | ret = idmap_lookup(rqstp, idtoname_lookup, &key, nn->idtoname_cache, &item); |
566 | if (ret == -ENOENT) | 581 | if (ret == -ENOENT) |
567 | return sprintf(name, "%u", id); | 582 | return encode_ascii_id(id, p, buflen); |
568 | if (ret) | 583 | if (ret) |
569 | return ret; | 584 | return nfserrno(ret); |
570 | ret = strlen(item->name); | 585 | ret = strlen(item->name); |
571 | BUG_ON(ret > IDMAP_NAMESZ); | 586 | WARN_ON_ONCE(ret > IDMAP_NAMESZ); |
572 | memcpy(name, item->name, ret); | 587 | bytes = 4 + (XDR_QUADLEN(ret) << 2); |
588 | if (bytes > *buflen) | ||
589 | return nfserr_resource; | ||
590 | *p = xdr_encode_opaque(*p, item->name, ret); | ||
591 | *buflen -= bytes; | ||
573 | cache_put(&item->h, nn->idtoname_cache); | 592 | cache_put(&item->h, nn->idtoname_cache); |
574 | return ret; | 593 | return 0; |
575 | } | 594 | } |
576 | 595 | ||
577 | static bool | 596 | static bool |
@@ -603,12 +622,11 @@ do_name_to_id(struct svc_rqst *rqstp, int type, const char *name, u32 namelen, u | |||
603 | return idmap_name_to_id(rqstp, type, name, namelen, id); | 622 | return idmap_name_to_id(rqstp, type, name, namelen, id); |
604 | } | 623 | } |
605 | 624 | ||
606 | static int | 625 | static __be32 encode_name_from_id(struct svc_rqst *rqstp, int type, u32 id, __be32 **p, int *buflen) |
607 | do_id_to_name(struct svc_rqst *rqstp, int type, u32 id, char *name) | ||
608 | { | 626 | { |
609 | if (nfs4_disable_idmapping && rqstp->rq_cred.cr_flavor < RPC_AUTH_GSS) | 627 | if (nfs4_disable_idmapping && rqstp->rq_cred.cr_flavor < RPC_AUTH_GSS) |
610 | return sprintf(name, "%u", id); | 628 | return encode_ascii_id(id, p, buflen); |
611 | return idmap_id_to_name(rqstp, type, id, name); | 629 | return idmap_id_to_name(rqstp, type, id, p, buflen); |
612 | } | 630 | } |
613 | 631 | ||
614 | __be32 | 632 | __be32 |
@@ -637,16 +655,14 @@ nfsd_map_name_to_gid(struct svc_rqst *rqstp, const char *name, size_t namelen, | |||
637 | return status; | 655 | return status; |
638 | } | 656 | } |
639 | 657 | ||
640 | int | 658 | __be32 nfsd4_encode_user(struct svc_rqst *rqstp, kuid_t uid, __be32 **p, int *buflen) |
641 | nfsd_map_uid_to_name(struct svc_rqst *rqstp, kuid_t uid, char *name) | ||
642 | { | 659 | { |
643 | u32 id = from_kuid(&init_user_ns, uid); | 660 | u32 id = from_kuid(&init_user_ns, uid); |
644 | return do_id_to_name(rqstp, IDMAP_TYPE_USER, id, name); | 661 | return encode_name_from_id(rqstp, IDMAP_TYPE_USER, id, p, buflen); |
645 | } | 662 | } |
646 | 663 | ||
647 | int | 664 | __be32 nfsd4_encode_group(struct svc_rqst *rqstp, kgid_t gid, __be32 **p, int *buflen) |
648 | nfsd_map_gid_to_name(struct svc_rqst *rqstp, kgid_t gid, char *name) | ||
649 | { | 665 | { |
650 | u32 id = from_kgid(&init_user_ns, gid); | 666 | u32 id = from_kgid(&init_user_ns, gid); |
651 | return do_id_to_name(rqstp, IDMAP_TYPE_GROUP, id, name); | 667 | return encode_name_from_id(rqstp, IDMAP_TYPE_GROUP, id, p, buflen); |
652 | } | 668 | } |
diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c index 825b8a99b99b..82189b208af3 100644 --- a/fs/nfsd/nfs4proc.c +++ b/fs/nfsd/nfs4proc.c | |||
@@ -231,17 +231,16 @@ static void nfsd4_set_open_owner_reply_cache(struct nfsd4_compound_state *cstate | |||
231 | } | 231 | } |
232 | 232 | ||
233 | static __be32 | 233 | static __be32 |
234 | do_open_lookup(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, struct nfsd4_open *open) | 234 | do_open_lookup(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, struct nfsd4_open *open, struct svc_fh **resfh) |
235 | { | 235 | { |
236 | struct svc_fh *current_fh = &cstate->current_fh; | 236 | struct svc_fh *current_fh = &cstate->current_fh; |
237 | struct svc_fh *resfh; | ||
238 | int accmode; | 237 | int accmode; |
239 | __be32 status; | 238 | __be32 status; |
240 | 239 | ||
241 | resfh = kmalloc(sizeof(struct svc_fh), GFP_KERNEL); | 240 | *resfh = kmalloc(sizeof(struct svc_fh), GFP_KERNEL); |
242 | if (!resfh) | 241 | if (!*resfh) |
243 | return nfserr_jukebox; | 242 | return nfserr_jukebox; |
244 | fh_init(resfh, NFS4_FHSIZE); | 243 | fh_init(*resfh, NFS4_FHSIZE); |
245 | open->op_truncate = 0; | 244 | open->op_truncate = 0; |
246 | 245 | ||
247 | if (open->op_create) { | 246 | if (open->op_create) { |
@@ -266,12 +265,12 @@ do_open_lookup(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, stru | |||
266 | */ | 265 | */ |
267 | status = do_nfsd_create(rqstp, current_fh, open->op_fname.data, | 266 | status = do_nfsd_create(rqstp, current_fh, open->op_fname.data, |
268 | open->op_fname.len, &open->op_iattr, | 267 | open->op_fname.len, &open->op_iattr, |
269 | resfh, open->op_createmode, | 268 | *resfh, open->op_createmode, |
270 | (u32 *)open->op_verf.data, | 269 | (u32 *)open->op_verf.data, |
271 | &open->op_truncate, &open->op_created); | 270 | &open->op_truncate, &open->op_created); |
272 | 271 | ||
273 | if (!status && open->op_label.len) | 272 | if (!status && open->op_label.len) |
274 | nfsd4_security_inode_setsecctx(resfh, &open->op_label, open->op_bmval); | 273 | nfsd4_security_inode_setsecctx(*resfh, &open->op_label, open->op_bmval); |
275 | 274 | ||
276 | /* | 275 | /* |
277 | * Following rfc 3530 14.2.16, use the returned bitmask | 276 | * Following rfc 3530 14.2.16, use the returned bitmask |
@@ -281,31 +280,32 @@ do_open_lookup(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, stru | |||
281 | if (open->op_createmode == NFS4_CREATE_EXCLUSIVE && status == 0) | 280 | if (open->op_createmode == NFS4_CREATE_EXCLUSIVE && status == 0) |
282 | open->op_bmval[1] = (FATTR4_WORD1_TIME_ACCESS | | 281 | open->op_bmval[1] = (FATTR4_WORD1_TIME_ACCESS | |
283 | FATTR4_WORD1_TIME_MODIFY); | 282 | FATTR4_WORD1_TIME_MODIFY); |
284 | } else { | 283 | } else |
284 | /* | ||
285 | * Note this may exit with the parent still locked. | ||
286 | * We will hold the lock until nfsd4_open's final | ||
287 | * lookup, to prevent renames or unlinks until we've had | ||
288 | * a chance to an acquire a delegation if appropriate. | ||
289 | */ | ||
285 | status = nfsd_lookup(rqstp, current_fh, | 290 | status = nfsd_lookup(rqstp, current_fh, |
286 | open->op_fname.data, open->op_fname.len, resfh); | 291 | open->op_fname.data, open->op_fname.len, *resfh); |
287 | fh_unlock(current_fh); | ||
288 | } | ||
289 | if (status) | 292 | if (status) |
290 | goto out; | 293 | goto out; |
291 | status = nfsd_check_obj_isreg(resfh); | 294 | status = nfsd_check_obj_isreg(*resfh); |
292 | if (status) | 295 | if (status) |
293 | goto out; | 296 | goto out; |
294 | 297 | ||
295 | if (is_create_with_attrs(open) && open->op_acl != NULL) | 298 | if (is_create_with_attrs(open) && open->op_acl != NULL) |
296 | do_set_nfs4_acl(rqstp, resfh, open->op_acl, open->op_bmval); | 299 | do_set_nfs4_acl(rqstp, *resfh, open->op_acl, open->op_bmval); |
297 | 300 | ||
298 | nfsd4_set_open_owner_reply_cache(cstate, open, resfh); | 301 | nfsd4_set_open_owner_reply_cache(cstate, open, *resfh); |
299 | accmode = NFSD_MAY_NOP; | 302 | accmode = NFSD_MAY_NOP; |
300 | if (open->op_created || | 303 | if (open->op_created || |
301 | open->op_claim_type == NFS4_OPEN_CLAIM_DELEGATE_CUR) | 304 | open->op_claim_type == NFS4_OPEN_CLAIM_DELEGATE_CUR) |
302 | accmode |= NFSD_MAY_OWNER_OVERRIDE; | 305 | accmode |= NFSD_MAY_OWNER_OVERRIDE; |
303 | status = do_open_permission(rqstp, resfh, open, accmode); | 306 | status = do_open_permission(rqstp, *resfh, open, accmode); |
304 | set_change_info(&open->op_cinfo, current_fh); | 307 | set_change_info(&open->op_cinfo, current_fh); |
305 | fh_dup2(current_fh, resfh); | ||
306 | out: | 308 | out: |
307 | fh_put(resfh); | ||
308 | kfree(resfh); | ||
309 | return status; | 309 | return status; |
310 | } | 310 | } |
311 | 311 | ||
@@ -358,6 +358,7 @@ nfsd4_open(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, | |||
358 | struct nfsd4_open *open) | 358 | struct nfsd4_open *open) |
359 | { | 359 | { |
360 | __be32 status; | 360 | __be32 status; |
361 | struct svc_fh *resfh = NULL; | ||
361 | struct nfsd4_compoundres *resp; | 362 | struct nfsd4_compoundres *resp; |
362 | struct net *net = SVC_NET(rqstp); | 363 | struct net *net = SVC_NET(rqstp); |
363 | struct nfsd_net *nn = net_generic(net, nfsd_net_id); | 364 | struct nfsd_net *nn = net_generic(net, nfsd_net_id); |
@@ -424,7 +425,7 @@ nfsd4_open(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, | |||
424 | switch (open->op_claim_type) { | 425 | switch (open->op_claim_type) { |
425 | case NFS4_OPEN_CLAIM_DELEGATE_CUR: | 426 | case NFS4_OPEN_CLAIM_DELEGATE_CUR: |
426 | case NFS4_OPEN_CLAIM_NULL: | 427 | case NFS4_OPEN_CLAIM_NULL: |
427 | status = do_open_lookup(rqstp, cstate, open); | 428 | status = do_open_lookup(rqstp, cstate, open, &resfh); |
428 | if (status) | 429 | if (status) |
429 | goto out; | 430 | goto out; |
430 | break; | 431 | break; |
@@ -440,6 +441,7 @@ nfsd4_open(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, | |||
440 | status = do_open_fhandle(rqstp, cstate, open); | 441 | status = do_open_fhandle(rqstp, cstate, open); |
441 | if (status) | 442 | if (status) |
442 | goto out; | 443 | goto out; |
444 | resfh = &cstate->current_fh; | ||
443 | break; | 445 | break; |
444 | case NFS4_OPEN_CLAIM_DELEG_PREV_FH: | 446 | case NFS4_OPEN_CLAIM_DELEG_PREV_FH: |
445 | case NFS4_OPEN_CLAIM_DELEGATE_PREV: | 447 | case NFS4_OPEN_CLAIM_DELEGATE_PREV: |
@@ -459,9 +461,14 @@ nfsd4_open(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, | |||
459 | * successful, it (1) truncates the file if open->op_truncate was | 461 | * successful, it (1) truncates the file if open->op_truncate was |
460 | * set, (2) sets open->op_stateid, (3) sets open->op_delegation. | 462 | * set, (2) sets open->op_stateid, (3) sets open->op_delegation. |
461 | */ | 463 | */ |
462 | status = nfsd4_process_open2(rqstp, &cstate->current_fh, open); | 464 | status = nfsd4_process_open2(rqstp, resfh, open); |
463 | WARN_ON(status && open->op_created); | 465 | WARN_ON(status && open->op_created); |
464 | out: | 466 | out: |
467 | if (resfh && resfh != &cstate->current_fh) { | ||
468 | fh_dup2(&cstate->current_fh, resfh); | ||
469 | fh_put(resfh); | ||
470 | kfree(resfh); | ||
471 | } | ||
465 | nfsd4_cleanup_open_state(open, status); | 472 | nfsd4_cleanup_open_state(open, status); |
466 | if (open->op_openowner && !nfsd4_has_session(cstate)) | 473 | if (open->op_openowner && !nfsd4_has_session(cstate)) |
467 | cstate->replay_owner = &open->op_openowner->oo_owner; | 474 | cstate->replay_owner = &open->op_openowner->oo_owner; |
@@ -1070,8 +1077,10 @@ _nfsd4_verify(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, | |||
1070 | cstate->current_fh.fh_dentry, &p, | 1077 | cstate->current_fh.fh_dentry, &p, |
1071 | count, verify->ve_bmval, | 1078 | count, verify->ve_bmval, |
1072 | rqstp, 0); | 1079 | rqstp, 0); |
1073 | 1080 | /* | |
1074 | /* this means that nfsd4_encode_fattr() ran out of space */ | 1081 | * If nfsd4_encode_fattr() ran out of space, assume that's because |
1082 | * the attributes are longer (hence different) than those given: | ||
1083 | */ | ||
1075 | if (status == nfserr_resource) | 1084 | if (status == nfserr_resource) |
1076 | status = nfserr_not_same; | 1085 | status = nfserr_not_same; |
1077 | if (status) | 1086 | if (status) |
@@ -1525,7 +1534,8 @@ static inline u32 nfsd4_write_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op) | |||
1525 | static inline u32 nfsd4_exchange_id_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op) | 1534 | static inline u32 nfsd4_exchange_id_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op) |
1526 | { | 1535 | { |
1527 | return (op_encode_hdr_size + 2 + 1 + /* eir_clientid, eir_sequenceid */\ | 1536 | return (op_encode_hdr_size + 2 + 1 + /* eir_clientid, eir_sequenceid */\ |
1528 | 1 + 1 + 2 + /* eir_flags, spr_how, spo_must_enforce & _allow */\ | 1537 | 1 + 1 + /* eir_flags, spr_how */\ |
1538 | 4 + /* spo_must_enforce & _allow with bitmap */\ | ||
1529 | 2 + /*eir_server_owner.so_minor_id */\ | 1539 | 2 + /*eir_server_owner.so_minor_id */\ |
1530 | /* eir_server_owner.so_major_id<> */\ | 1540 | /* eir_server_owner.so_major_id<> */\ |
1531 | XDR_QUADLEN(NFS4_OPAQUE_LIMIT) + 1 +\ | 1541 | XDR_QUADLEN(NFS4_OPAQUE_LIMIT) + 1 +\ |
@@ -1882,6 +1892,7 @@ struct svc_version nfsd_version4 = { | |||
1882 | .vs_proc = nfsd_procedures4, | 1892 | .vs_proc = nfsd_procedures4, |
1883 | .vs_dispatch = nfsd_dispatch, | 1893 | .vs_dispatch = nfsd_dispatch, |
1884 | .vs_xdrsize = NFS4_SVC_XDRSIZE, | 1894 | .vs_xdrsize = NFS4_SVC_XDRSIZE, |
1895 | .vs_rpcb_optnl = 1, | ||
1885 | }; | 1896 | }; |
1886 | 1897 | ||
1887 | /* | 1898 | /* |
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index 105d6fa7c514..d5d070fbeb35 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c | |||
@@ -832,10 +832,11 @@ static void nfsd4_put_drc_mem(struct nfsd4_channel_attrs *ca) | |||
832 | spin_unlock(&nfsd_drc_lock); | 832 | spin_unlock(&nfsd_drc_lock); |
833 | } | 833 | } |
834 | 834 | ||
835 | static struct nfsd4_session *alloc_session(struct nfsd4_channel_attrs *attrs) | 835 | static struct nfsd4_session *alloc_session(struct nfsd4_channel_attrs *fattrs, |
836 | struct nfsd4_channel_attrs *battrs) | ||
836 | { | 837 | { |
837 | int numslots = attrs->maxreqs; | 838 | int numslots = fattrs->maxreqs; |
838 | int slotsize = slot_bytes(attrs); | 839 | int slotsize = slot_bytes(fattrs); |
839 | struct nfsd4_session *new; | 840 | struct nfsd4_session *new; |
840 | int mem, i; | 841 | int mem, i; |
841 | 842 | ||
@@ -852,6 +853,10 @@ static struct nfsd4_session *alloc_session(struct nfsd4_channel_attrs *attrs) | |||
852 | if (!new->se_slots[i]) | 853 | if (!new->se_slots[i]) |
853 | goto out_free; | 854 | goto out_free; |
854 | } | 855 | } |
856 | |||
857 | memcpy(&new->se_fchannel, fattrs, sizeof(struct nfsd4_channel_attrs)); | ||
858 | memcpy(&new->se_bchannel, battrs, sizeof(struct nfsd4_channel_attrs)); | ||
859 | |||
855 | return new; | 860 | return new; |
856 | out_free: | 861 | out_free: |
857 | while (i--) | 862 | while (i--) |
@@ -997,8 +1002,7 @@ static void init_session(struct svc_rqst *rqstp, struct nfsd4_session *new, stru | |||
997 | list_add(&new->se_perclnt, &clp->cl_sessions); | 1002 | list_add(&new->se_perclnt, &clp->cl_sessions); |
998 | spin_unlock(&clp->cl_lock); | 1003 | spin_unlock(&clp->cl_lock); |
999 | spin_unlock(&nn->client_lock); | 1004 | spin_unlock(&nn->client_lock); |
1000 | memcpy(&new->se_fchannel, &cses->fore_channel, | 1005 | |
1001 | sizeof(struct nfsd4_channel_attrs)); | ||
1002 | if (cses->flags & SESSION4_BACK_CHAN) { | 1006 | if (cses->flags & SESSION4_BACK_CHAN) { |
1003 | struct sockaddr *sa = svc_addr(rqstp); | 1007 | struct sockaddr *sa = svc_addr(rqstp); |
1004 | /* | 1008 | /* |
@@ -1851,6 +1855,11 @@ static __be32 check_forechannel_attrs(struct nfsd4_channel_attrs *ca, struct nfs | |||
1851 | return nfs_ok; | 1855 | return nfs_ok; |
1852 | } | 1856 | } |
1853 | 1857 | ||
1858 | #define NFSD_CB_MAX_REQ_SZ ((NFS4_enc_cb_recall_sz + \ | ||
1859 | RPC_MAX_HEADER_WITH_AUTH) * sizeof(__be32)) | ||
1860 | #define NFSD_CB_MAX_RESP_SZ ((NFS4_dec_cb_recall_sz + \ | ||
1861 | RPC_MAX_REPHEADER_WITH_AUTH) * sizeof(__be32)) | ||
1862 | |||
1854 | static __be32 check_backchannel_attrs(struct nfsd4_channel_attrs *ca) | 1863 | static __be32 check_backchannel_attrs(struct nfsd4_channel_attrs *ca) |
1855 | { | 1864 | { |
1856 | ca->headerpadsz = 0; | 1865 | ca->headerpadsz = 0; |
@@ -1861,9 +1870,9 @@ static __be32 check_backchannel_attrs(struct nfsd4_channel_attrs *ca) | |||
1861 | * less than 1k. Tighten up this estimate in the unlikely event | 1870 | * less than 1k. Tighten up this estimate in the unlikely event |
1862 | * it turns out to be a problem for some client: | 1871 | * it turns out to be a problem for some client: |
1863 | */ | 1872 | */ |
1864 | if (ca->maxreq_sz < NFS4_enc_cb_recall_sz + RPC_MAX_HEADER_WITH_AUTH) | 1873 | if (ca->maxreq_sz < NFSD_CB_MAX_REQ_SZ) |
1865 | return nfserr_toosmall; | 1874 | return nfserr_toosmall; |
1866 | if (ca->maxresp_sz < NFS4_dec_cb_recall_sz + RPC_MAX_REPHEADER_WITH_AUTH) | 1875 | if (ca->maxresp_sz < NFSD_CB_MAX_RESP_SZ) |
1867 | return nfserr_toosmall; | 1876 | return nfserr_toosmall; |
1868 | ca->maxresp_cached = 0; | 1877 | ca->maxresp_cached = 0; |
1869 | if (ca->maxops < 2) | 1878 | if (ca->maxops < 2) |
@@ -1913,9 +1922,9 @@ nfsd4_create_session(struct svc_rqst *rqstp, | |||
1913 | return status; | 1922 | return status; |
1914 | status = check_backchannel_attrs(&cr_ses->back_channel); | 1923 | status = check_backchannel_attrs(&cr_ses->back_channel); |
1915 | if (status) | 1924 | if (status) |
1916 | return status; | 1925 | goto out_release_drc_mem; |
1917 | status = nfserr_jukebox; | 1926 | status = nfserr_jukebox; |
1918 | new = alloc_session(&cr_ses->fore_channel); | 1927 | new = alloc_session(&cr_ses->fore_channel, &cr_ses->back_channel); |
1919 | if (!new) | 1928 | if (!new) |
1920 | goto out_release_drc_mem; | 1929 | goto out_release_drc_mem; |
1921 | conn = alloc_conn_from_crses(rqstp, cr_ses); | 1930 | conn = alloc_conn_from_crses(rqstp, cr_ses); |
@@ -3034,18 +3043,18 @@ static int nfs4_setlease(struct nfs4_delegation *dp) | |||
3034 | if (!fl) | 3043 | if (!fl) |
3035 | return -ENOMEM; | 3044 | return -ENOMEM; |
3036 | fl->fl_file = find_readable_file(fp); | 3045 | fl->fl_file = find_readable_file(fp); |
3037 | list_add(&dp->dl_perclnt, &dp->dl_stid.sc_client->cl_delegations); | ||
3038 | status = vfs_setlease(fl->fl_file, fl->fl_type, &fl); | 3046 | status = vfs_setlease(fl->fl_file, fl->fl_type, &fl); |
3039 | if (status) { | 3047 | if (status) |
3040 | list_del_init(&dp->dl_perclnt); | 3048 | goto out_free; |
3041 | locks_free_lock(fl); | 3049 | list_add(&dp->dl_perclnt, &dp->dl_stid.sc_client->cl_delegations); |
3042 | return status; | ||
3043 | } | ||
3044 | fp->fi_lease = fl; | 3050 | fp->fi_lease = fl; |
3045 | fp->fi_deleg_file = get_file(fl->fl_file); | 3051 | fp->fi_deleg_file = get_file(fl->fl_file); |
3046 | atomic_set(&fp->fi_delegees, 1); | 3052 | atomic_set(&fp->fi_delegees, 1); |
3047 | list_add(&dp->dl_perfile, &fp->fi_delegations); | 3053 | list_add(&dp->dl_perfile, &fp->fi_delegations); |
3048 | return 0; | 3054 | return 0; |
3055 | out_free: | ||
3056 | locks_free_lock(fl); | ||
3057 | return status; | ||
3049 | } | 3058 | } |
3050 | 3059 | ||
3051 | static int nfs4_set_delegation(struct nfs4_delegation *dp, struct nfs4_file *fp) | 3060 | static int nfs4_set_delegation(struct nfs4_delegation *dp, struct nfs4_file *fp) |
@@ -3125,6 +3134,7 @@ nfs4_open_delegation(struct net *net, struct svc_fh *fh, | |||
3125 | goto out_no_deleg; | 3134 | goto out_no_deleg; |
3126 | break; | 3135 | break; |
3127 | case NFS4_OPEN_CLAIM_NULL: | 3136 | case NFS4_OPEN_CLAIM_NULL: |
3137 | case NFS4_OPEN_CLAIM_FH: | ||
3128 | /* | 3138 | /* |
3129 | * Let's not give out any delegations till everyone's | 3139 | * Let's not give out any delegations till everyone's |
3130 | * had the chance to reclaim theirs.... | 3140 | * had the chance to reclaim theirs.... |
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c index ee7237f99f54..63f2395c57ed 100644 --- a/fs/nfsd/nfs4xdr.c +++ b/fs/nfsd/nfs4xdr.c | |||
@@ -103,11 +103,6 @@ xdr_error: \ | |||
103 | (x) = (u64)ntohl(*p++) << 32; \ | 103 | (x) = (u64)ntohl(*p++) << 32; \ |
104 | (x) |= ntohl(*p++); \ | 104 | (x) |= ntohl(*p++); \ |
105 | } while (0) | 105 | } while (0) |
106 | #define READTIME(x) do { \ | ||
107 | p++; \ | ||
108 | (x) = ntohl(*p++); \ | ||
109 | p++; \ | ||
110 | } while (0) | ||
111 | #define READMEM(x,nbytes) do { \ | 106 | #define READMEM(x,nbytes) do { \ |
112 | x = (char *)p; \ | 107 | x = (char *)p; \ |
113 | p += XDR_QUADLEN(nbytes); \ | 108 | p += XDR_QUADLEN(nbytes); \ |
@@ -190,6 +185,15 @@ static int zero_clientid(clientid_t *clid) | |||
190 | return (clid->cl_boot == 0) && (clid->cl_id == 0); | 185 | return (clid->cl_boot == 0) && (clid->cl_id == 0); |
191 | } | 186 | } |
192 | 187 | ||
188 | /** | ||
189 | * defer_free - mark an allocation as deferred freed | ||
190 | * @argp: NFSv4 compound argument structure to be freed with | ||
191 | * @release: release callback to free @p, typically kfree() | ||
192 | * @p: pointer to be freed | ||
193 | * | ||
194 | * Marks @p to be freed when processing the compound operation | ||
195 | * described in @argp finishes. | ||
196 | */ | ||
193 | static int | 197 | static int |
194 | defer_free(struct nfsd4_compoundargs *argp, | 198 | defer_free(struct nfsd4_compoundargs *argp, |
195 | void (*release)(const void *), void *p) | 199 | void (*release)(const void *), void *p) |
@@ -206,6 +210,16 @@ defer_free(struct nfsd4_compoundargs *argp, | |||
206 | return 0; | 210 | return 0; |
207 | } | 211 | } |
208 | 212 | ||
213 | /** | ||
214 | * savemem - duplicate a chunk of memory for later processing | ||
215 | * @argp: NFSv4 compound argument structure to be freed with | ||
216 | * @p: pointer to be duplicated | ||
217 | * @nbytes: length to be duplicated | ||
218 | * | ||
219 | * Returns a pointer to a copy of @nbytes bytes of memory at @p | ||
220 | * that are preserved until processing of the NFSv4 compound | ||
221 | * operation described by @argp finishes. | ||
222 | */ | ||
209 | static char *savemem(struct nfsd4_compoundargs *argp, __be32 *p, int nbytes) | 223 | static char *savemem(struct nfsd4_compoundargs *argp, __be32 *p, int nbytes) |
210 | { | 224 | { |
211 | if (p == argp->tmp) { | 225 | if (p == argp->tmp) { |
@@ -257,7 +271,6 @@ nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval, | |||
257 | int expected_len, len = 0; | 271 | int expected_len, len = 0; |
258 | u32 dummy32; | 272 | u32 dummy32; |
259 | char *buf; | 273 | char *buf; |
260 | int host_err; | ||
261 | 274 | ||
262 | DECODE_HEAD; | 275 | DECODE_HEAD; |
263 | iattr->ia_valid = 0; | 276 | iattr->ia_valid = 0; |
@@ -284,10 +297,9 @@ nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval, | |||
284 | return nfserr_resource; | 297 | return nfserr_resource; |
285 | 298 | ||
286 | *acl = nfs4_acl_new(nace); | 299 | *acl = nfs4_acl_new(nace); |
287 | if (*acl == NULL) { | 300 | if (*acl == NULL) |
288 | host_err = -ENOMEM; | 301 | return nfserr_jukebox; |
289 | goto out_nfserr; | 302 | |
290 | } | ||
291 | defer_free(argp, kfree, *acl); | 303 | defer_free(argp, kfree, *acl); |
292 | 304 | ||
293 | (*acl)->naces = nace; | 305 | (*acl)->naces = nace; |
@@ -425,10 +437,6 @@ nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval, | |||
425 | goto xdr_error; | 437 | goto xdr_error; |
426 | 438 | ||
427 | DECODE_TAIL; | 439 | DECODE_TAIL; |
428 | |||
429 | out_nfserr: | ||
430 | status = nfserrno(host_err); | ||
431 | goto out; | ||
432 | } | 440 | } |
433 | 441 | ||
434 | static __be32 | 442 | static __be32 |
@@ -1957,56 +1965,16 @@ static u32 nfs4_file_type(umode_t mode) | |||
1957 | }; | 1965 | }; |
1958 | } | 1966 | } |
1959 | 1967 | ||
1960 | static __be32 | ||
1961 | nfsd4_encode_name(struct svc_rqst *rqstp, int whotype, kuid_t uid, kgid_t gid, | ||
1962 | __be32 **p, int *buflen) | ||
1963 | { | ||
1964 | int status; | ||
1965 | |||
1966 | if (*buflen < (XDR_QUADLEN(IDMAP_NAMESZ) << 2) + 4) | ||
1967 | return nfserr_resource; | ||
1968 | if (whotype != NFS4_ACL_WHO_NAMED) | ||
1969 | status = nfs4_acl_write_who(whotype, (u8 *)(*p + 1)); | ||
1970 | else if (gid_valid(gid)) | ||
1971 | status = nfsd_map_gid_to_name(rqstp, gid, (u8 *)(*p + 1)); | ||
1972 | else | ||
1973 | status = nfsd_map_uid_to_name(rqstp, uid, (u8 *)(*p + 1)); | ||
1974 | if (status < 0) | ||
1975 | return nfserrno(status); | ||
1976 | *p = xdr_encode_opaque(*p, NULL, status); | ||
1977 | *buflen -= (XDR_QUADLEN(status) << 2) + 4; | ||
1978 | BUG_ON(*buflen < 0); | ||
1979 | return 0; | ||
1980 | } | ||
1981 | |||
1982 | static inline __be32 | ||
1983 | nfsd4_encode_user(struct svc_rqst *rqstp, kuid_t user, __be32 **p, int *buflen) | ||
1984 | { | ||
1985 | return nfsd4_encode_name(rqstp, NFS4_ACL_WHO_NAMED, user, INVALID_GID, | ||
1986 | p, buflen); | ||
1987 | } | ||
1988 | |||
1989 | static inline __be32 | ||
1990 | nfsd4_encode_group(struct svc_rqst *rqstp, kgid_t group, __be32 **p, int *buflen) | ||
1991 | { | ||
1992 | return nfsd4_encode_name(rqstp, NFS4_ACL_WHO_NAMED, INVALID_UID, group, | ||
1993 | p, buflen); | ||
1994 | } | ||
1995 | |||
1996 | static inline __be32 | 1968 | static inline __be32 |
1997 | nfsd4_encode_aclname(struct svc_rqst *rqstp, struct nfs4_ace *ace, | 1969 | nfsd4_encode_aclname(struct svc_rqst *rqstp, struct nfs4_ace *ace, |
1998 | __be32 **p, int *buflen) | 1970 | __be32 **p, int *buflen) |
1999 | { | 1971 | { |
2000 | kuid_t uid = INVALID_UID; | 1972 | if (ace->whotype != NFS4_ACL_WHO_NAMED) |
2001 | kgid_t gid = INVALID_GID; | 1973 | return nfs4_acl_write_who(ace->whotype, p, buflen); |
2002 | 1974 | else if (ace->flag & NFS4_ACE_IDENTIFIER_GROUP) | |
2003 | if (ace->whotype == NFS4_ACL_WHO_NAMED) { | 1975 | return nfsd4_encode_group(rqstp, ace->who_gid, p, buflen); |
2004 | if (ace->flag & NFS4_ACE_IDENTIFIER_GROUP) | 1976 | else |
2005 | gid = ace->who_gid; | 1977 | return nfsd4_encode_user(rqstp, ace->who_uid, p, buflen); |
2006 | else | ||
2007 | uid = ace->who_uid; | ||
2008 | } | ||
2009 | return nfsd4_encode_name(rqstp, ace->whotype, uid, gid, p, buflen); | ||
2010 | } | 1978 | } |
2011 | 1979 | ||
2012 | #define WORD0_ABSENT_FS_ATTRS (FATTR4_WORD0_FS_LOCATIONS | FATTR4_WORD0_FSID | \ | 1980 | #define WORD0_ABSENT_FS_ATTRS (FATTR4_WORD0_FS_LOCATIONS | FATTR4_WORD0_FSID | \ |
@@ -2090,7 +2058,7 @@ nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp, | |||
2090 | u32 bmval1 = bmval[1]; | 2058 | u32 bmval1 = bmval[1]; |
2091 | u32 bmval2 = bmval[2]; | 2059 | u32 bmval2 = bmval[2]; |
2092 | struct kstat stat; | 2060 | struct kstat stat; |
2093 | struct svc_fh tempfh; | 2061 | struct svc_fh *tempfh = NULL; |
2094 | struct kstatfs statfs; | 2062 | struct kstatfs statfs; |
2095 | int buflen = count << 2; | 2063 | int buflen = count << 2; |
2096 | __be32 *attrlenp; | 2064 | __be32 *attrlenp; |
@@ -2137,11 +2105,15 @@ nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp, | |||
2137 | goto out_nfserr; | 2105 | goto out_nfserr; |
2138 | } | 2106 | } |
2139 | if ((bmval0 & (FATTR4_WORD0_FILEHANDLE | FATTR4_WORD0_FSID)) && !fhp) { | 2107 | if ((bmval0 & (FATTR4_WORD0_FILEHANDLE | FATTR4_WORD0_FSID)) && !fhp) { |
2140 | fh_init(&tempfh, NFS4_FHSIZE); | 2108 | tempfh = kmalloc(sizeof(struct svc_fh), GFP_KERNEL); |
2141 | status = fh_compose(&tempfh, exp, dentry, NULL); | 2109 | status = nfserr_jukebox; |
2110 | if (!tempfh) | ||
2111 | goto out; | ||
2112 | fh_init(tempfh, NFS4_FHSIZE); | ||
2113 | status = fh_compose(tempfh, exp, dentry, NULL); | ||
2142 | if (status) | 2114 | if (status) |
2143 | goto out; | 2115 | goto out; |
2144 | fhp = &tempfh; | 2116 | fhp = tempfh; |
2145 | } | 2117 | } |
2146 | if (bmval0 & (FATTR4_WORD0_ACL | FATTR4_WORD0_ACLSUPPORT | 2118 | if (bmval0 & (FATTR4_WORD0_ACL | FATTR4_WORD0_ACLSUPPORT |
2147 | | FATTR4_WORD0_SUPPORTED_ATTRS)) { | 2119 | | FATTR4_WORD0_SUPPORTED_ATTRS)) { |
@@ -2222,8 +2194,10 @@ nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp, | |||
2222 | if ((buflen -= 4) < 0) | 2194 | if ((buflen -= 4) < 0) |
2223 | goto out_resource; | 2195 | goto out_resource; |
2224 | dummy = nfs4_file_type(stat.mode); | 2196 | dummy = nfs4_file_type(stat.mode); |
2225 | if (dummy == NF4BAD) | 2197 | if (dummy == NF4BAD) { |
2226 | goto out_serverfault; | 2198 | status = nfserr_serverfault; |
2199 | goto out; | ||
2200 | } | ||
2227 | WRITE32(dummy); | 2201 | WRITE32(dummy); |
2228 | } | 2202 | } |
2229 | if (bmval0 & FATTR4_WORD0_FH_EXPIRE_TYPE) { | 2203 | if (bmval0 & FATTR4_WORD0_FH_EXPIRE_TYPE) { |
@@ -2317,8 +2291,6 @@ nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp, | |||
2317 | WRITE32(ace->flag); | 2291 | WRITE32(ace->flag); |
2318 | WRITE32(ace->access_mask & NFS4_ACE_MASK_ALL); | 2292 | WRITE32(ace->access_mask & NFS4_ACE_MASK_ALL); |
2319 | status = nfsd4_encode_aclname(rqstp, ace, &p, &buflen); | 2293 | status = nfsd4_encode_aclname(rqstp, ace, &p, &buflen); |
2320 | if (status == nfserr_resource) | ||
2321 | goto out_resource; | ||
2322 | if (status) | 2294 | if (status) |
2323 | goto out; | 2295 | goto out; |
2324 | } | 2296 | } |
@@ -2379,8 +2351,6 @@ out_acl: | |||
2379 | } | 2351 | } |
2380 | if (bmval0 & FATTR4_WORD0_FS_LOCATIONS) { | 2352 | if (bmval0 & FATTR4_WORD0_FS_LOCATIONS) { |
2381 | status = nfsd4_encode_fs_locations(rqstp, exp, &p, &buflen); | 2353 | status = nfsd4_encode_fs_locations(rqstp, exp, &p, &buflen); |
2382 | if (status == nfserr_resource) | ||
2383 | goto out_resource; | ||
2384 | if (status) | 2354 | if (status) |
2385 | goto out; | 2355 | goto out; |
2386 | } | 2356 | } |
@@ -2431,15 +2401,11 @@ out_acl: | |||
2431 | } | 2401 | } |
2432 | if (bmval1 & FATTR4_WORD1_OWNER) { | 2402 | if (bmval1 & FATTR4_WORD1_OWNER) { |
2433 | status = nfsd4_encode_user(rqstp, stat.uid, &p, &buflen); | 2403 | status = nfsd4_encode_user(rqstp, stat.uid, &p, &buflen); |
2434 | if (status == nfserr_resource) | ||
2435 | goto out_resource; | ||
2436 | if (status) | 2404 | if (status) |
2437 | goto out; | 2405 | goto out; |
2438 | } | 2406 | } |
2439 | if (bmval1 & FATTR4_WORD1_OWNER_GROUP) { | 2407 | if (bmval1 & FATTR4_WORD1_OWNER_GROUP) { |
2440 | status = nfsd4_encode_group(rqstp, stat.gid, &p, &buflen); | 2408 | status = nfsd4_encode_group(rqstp, stat.gid, &p, &buflen); |
2441 | if (status == nfserr_resource) | ||
2442 | goto out_resource; | ||
2443 | if (status) | 2409 | if (status) |
2444 | goto out; | 2410 | goto out; |
2445 | } | 2411 | } |
@@ -2533,8 +2499,8 @@ out: | |||
2533 | security_release_secctx(context, contextlen); | 2499 | security_release_secctx(context, contextlen); |
2534 | #endif /* CONFIG_NFSD_V4_SECURITY_LABEL */ | 2500 | #endif /* CONFIG_NFSD_V4_SECURITY_LABEL */ |
2535 | kfree(acl); | 2501 | kfree(acl); |
2536 | if (fhp == &tempfh) | 2502 | if (tempfh) |
2537 | fh_put(&tempfh); | 2503 | fh_put(tempfh); |
2538 | return status; | 2504 | return status; |
2539 | out_nfserr: | 2505 | out_nfserr: |
2540 | status = nfserrno(err); | 2506 | status = nfserrno(err); |
@@ -2542,9 +2508,6 @@ out_nfserr: | |||
2542 | out_resource: | 2508 | out_resource: |
2543 | status = nfserr_resource; | 2509 | status = nfserr_resource; |
2544 | goto out; | 2510 | goto out; |
2545 | out_serverfault: | ||
2546 | status = nfserr_serverfault; | ||
2547 | goto out; | ||
2548 | } | 2511 | } |
2549 | 2512 | ||
2550 | static inline int attributes_need_mount(u32 *bmval) | 2513 | static inline int attributes_need_mount(u32 *bmval) |
@@ -2621,17 +2584,14 @@ out_put: | |||
2621 | static __be32 * | 2584 | static __be32 * |
2622 | nfsd4_encode_rdattr_error(__be32 *p, int buflen, __be32 nfserr) | 2585 | nfsd4_encode_rdattr_error(__be32 *p, int buflen, __be32 nfserr) |
2623 | { | 2586 | { |
2624 | __be32 *attrlenp; | ||
2625 | |||
2626 | if (buflen < 6) | 2587 | if (buflen < 6) |
2627 | return NULL; | 2588 | return NULL; |
2628 | *p++ = htonl(2); | 2589 | *p++ = htonl(2); |
2629 | *p++ = htonl(FATTR4_WORD0_RDATTR_ERROR); /* bmval0 */ | 2590 | *p++ = htonl(FATTR4_WORD0_RDATTR_ERROR); /* bmval0 */ |
2630 | *p++ = htonl(0); /* bmval1 */ | 2591 | *p++ = htonl(0); /* bmval1 */ |
2631 | 2592 | ||
2632 | attrlenp = p++; | 2593 | *p++ = htonl(4); /* attribute length */ |
2633 | *p++ = nfserr; /* no htonl */ | 2594 | *p++ = nfserr; /* no htonl */ |
2634 | *attrlenp = htonl((char *)p - (char *)attrlenp - 4); | ||
2635 | return p; | 2595 | return p; |
2636 | } | 2596 | } |
2637 | 2597 | ||
@@ -3244,7 +3204,7 @@ nfsd4_do_encode_secinfo(struct nfsd4_compoundres *resp, | |||
3244 | 3204 | ||
3245 | if (rpcauth_get_gssinfo(pf, &info) == 0) { | 3205 | if (rpcauth_get_gssinfo(pf, &info) == 0) { |
3246 | supported++; | 3206 | supported++; |
3247 | RESERVE_SPACE(4 + 4 + info.oid.len + 4 + 4); | 3207 | RESERVE_SPACE(4 + 4 + XDR_LEN(info.oid.len) + 4 + 4); |
3248 | WRITE32(RPC_AUTH_GSS); | 3208 | WRITE32(RPC_AUTH_GSS); |
3249 | WRITE32(info.oid.len); | 3209 | WRITE32(info.oid.len); |
3250 | WRITEMEM(info.oid.data, info.oid.len); | 3210 | WRITEMEM(info.oid.data, info.oid.len); |
@@ -3379,35 +3339,43 @@ nfsd4_encode_exchange_id(struct nfsd4_compoundres *resp, __be32 nfserr, | |||
3379 | 8 /* eir_clientid */ + | 3339 | 8 /* eir_clientid */ + |
3380 | 4 /* eir_sequenceid */ + | 3340 | 4 /* eir_sequenceid */ + |
3381 | 4 /* eir_flags */ + | 3341 | 4 /* eir_flags */ + |
3382 | 4 /* spr_how */ + | 3342 | 4 /* spr_how */); |
3383 | 8 /* spo_must_enforce, spo_must_allow */ + | ||
3384 | 8 /* so_minor_id */ + | ||
3385 | 4 /* so_major_id.len */ + | ||
3386 | (XDR_QUADLEN(major_id_sz) * 4) + | ||
3387 | 4 /* eir_server_scope.len */ + | ||
3388 | (XDR_QUADLEN(server_scope_sz) * 4) + | ||
3389 | 4 /* eir_server_impl_id.count (0) */); | ||
3390 | 3343 | ||
3391 | WRITEMEM(&exid->clientid, 8); | 3344 | WRITEMEM(&exid->clientid, 8); |
3392 | WRITE32(exid->seqid); | 3345 | WRITE32(exid->seqid); |
3393 | WRITE32(exid->flags); | 3346 | WRITE32(exid->flags); |
3394 | 3347 | ||
3395 | WRITE32(exid->spa_how); | 3348 | WRITE32(exid->spa_how); |
3349 | ADJUST_ARGS(); | ||
3350 | |||
3396 | switch (exid->spa_how) { | 3351 | switch (exid->spa_how) { |
3397 | case SP4_NONE: | 3352 | case SP4_NONE: |
3398 | break; | 3353 | break; |
3399 | case SP4_MACH_CRED: | 3354 | case SP4_MACH_CRED: |
3355 | /* spo_must_enforce, spo_must_allow */ | ||
3356 | RESERVE_SPACE(16); | ||
3357 | |||
3400 | /* spo_must_enforce bitmap: */ | 3358 | /* spo_must_enforce bitmap: */ |
3401 | WRITE32(2); | 3359 | WRITE32(2); |
3402 | WRITE32(nfs4_minimal_spo_must_enforce[0]); | 3360 | WRITE32(nfs4_minimal_spo_must_enforce[0]); |
3403 | WRITE32(nfs4_minimal_spo_must_enforce[1]); | 3361 | WRITE32(nfs4_minimal_spo_must_enforce[1]); |
3404 | /* empty spo_must_allow bitmap: */ | 3362 | /* empty spo_must_allow bitmap: */ |
3405 | WRITE32(0); | 3363 | WRITE32(0); |
3364 | |||
3365 | ADJUST_ARGS(); | ||
3406 | break; | 3366 | break; |
3407 | default: | 3367 | default: |
3408 | WARN_ON_ONCE(1); | 3368 | WARN_ON_ONCE(1); |
3409 | } | 3369 | } |
3410 | 3370 | ||
3371 | RESERVE_SPACE( | ||
3372 | 8 /* so_minor_id */ + | ||
3373 | 4 /* so_major_id.len */ + | ||
3374 | (XDR_QUADLEN(major_id_sz) * 4) + | ||
3375 | 4 /* eir_server_scope.len */ + | ||
3376 | (XDR_QUADLEN(server_scope_sz) * 4) + | ||
3377 | 4 /* eir_server_impl_id.count (0) */); | ||
3378 | |||
3411 | /* The server_owner struct */ | 3379 | /* The server_owner struct */ |
3412 | WRITE64(minor_id); /* Minor id */ | 3380 | WRITE64(minor_id); /* Minor id */ |
3413 | /* major id */ | 3381 | /* major id */ |
@@ -3474,28 +3442,6 @@ nfsd4_encode_create_session(struct nfsd4_compoundres *resp, __be32 nfserr, | |||
3474 | } | 3442 | } |
3475 | 3443 | ||
3476 | static __be32 | 3444 | static __be32 |
3477 | nfsd4_encode_destroy_session(struct nfsd4_compoundres *resp, __be32 nfserr, | ||
3478 | struct nfsd4_destroy_session *destroy_session) | ||
3479 | { | ||
3480 | return nfserr; | ||
3481 | } | ||
3482 | |||
3483 | static __be32 | ||
3484 | nfsd4_encode_free_stateid(struct nfsd4_compoundres *resp, __be32 nfserr, | ||
3485 | struct nfsd4_free_stateid *free_stateid) | ||
3486 | { | ||
3487 | __be32 *p; | ||
3488 | |||
3489 | if (nfserr) | ||
3490 | return nfserr; | ||
3491 | |||
3492 | RESERVE_SPACE(4); | ||
3493 | *p++ = nfserr; | ||
3494 | ADJUST_ARGS(); | ||
3495 | return nfserr; | ||
3496 | } | ||
3497 | |||
3498 | static __be32 | ||
3499 | nfsd4_encode_sequence(struct nfsd4_compoundres *resp, __be32 nfserr, | 3445 | nfsd4_encode_sequence(struct nfsd4_compoundres *resp, __be32 nfserr, |
3500 | struct nfsd4_sequence *seq) | 3446 | struct nfsd4_sequence *seq) |
3501 | { | 3447 | { |
@@ -3593,8 +3539,8 @@ static nfsd4_enc nfsd4_enc_ops[] = { | |||
3593 | [OP_BIND_CONN_TO_SESSION] = (nfsd4_enc)nfsd4_encode_bind_conn_to_session, | 3539 | [OP_BIND_CONN_TO_SESSION] = (nfsd4_enc)nfsd4_encode_bind_conn_to_session, |
3594 | [OP_EXCHANGE_ID] = (nfsd4_enc)nfsd4_encode_exchange_id, | 3540 | [OP_EXCHANGE_ID] = (nfsd4_enc)nfsd4_encode_exchange_id, |
3595 | [OP_CREATE_SESSION] = (nfsd4_enc)nfsd4_encode_create_session, | 3541 | [OP_CREATE_SESSION] = (nfsd4_enc)nfsd4_encode_create_session, |
3596 | [OP_DESTROY_SESSION] = (nfsd4_enc)nfsd4_encode_destroy_session, | 3542 | [OP_DESTROY_SESSION] = (nfsd4_enc)nfsd4_encode_noop, |
3597 | [OP_FREE_STATEID] = (nfsd4_enc)nfsd4_encode_free_stateid, | 3543 | [OP_FREE_STATEID] = (nfsd4_enc)nfsd4_encode_noop, |
3598 | [OP_GET_DIR_DELEGATION] = (nfsd4_enc)nfsd4_encode_noop, | 3544 | [OP_GET_DIR_DELEGATION] = (nfsd4_enc)nfsd4_encode_noop, |
3599 | [OP_GETDEVICEINFO] = (nfsd4_enc)nfsd4_encode_noop, | 3545 | [OP_GETDEVICEINFO] = (nfsd4_enc)nfsd4_encode_noop, |
3600 | [OP_GETDEVICELIST] = (nfsd4_enc)nfsd4_encode_noop, | 3546 | [OP_GETDEVICELIST] = (nfsd4_enc)nfsd4_encode_noop, |
diff --git a/fs/nfsd/nfscache.c b/fs/nfsd/nfscache.c index b6af150c96b8..f8f060ffbf4f 100644 --- a/fs/nfsd/nfscache.c +++ b/fs/nfsd/nfscache.c | |||
@@ -132,13 +132,6 @@ nfsd_reply_cache_alloc(void) | |||
132 | } | 132 | } |
133 | 133 | ||
134 | static void | 134 | static void |
135 | nfsd_reply_cache_unhash(struct svc_cacherep *rp) | ||
136 | { | ||
137 | hlist_del_init(&rp->c_hash); | ||
138 | list_del_init(&rp->c_lru); | ||
139 | } | ||
140 | |||
141 | static void | ||
142 | nfsd_reply_cache_free_locked(struct svc_cacherep *rp) | 135 | nfsd_reply_cache_free_locked(struct svc_cacherep *rp) |
143 | { | 136 | { |
144 | if (rp->c_type == RC_REPLBUFF && rp->c_replvec.iov_base) { | 137 | if (rp->c_type == RC_REPLBUFF && rp->c_replvec.iov_base) { |
@@ -416,22 +409,8 @@ nfsd_cache_lookup(struct svc_rqst *rqstp) | |||
416 | 409 | ||
417 | /* | 410 | /* |
418 | * Since the common case is a cache miss followed by an insert, | 411 | * Since the common case is a cache miss followed by an insert, |
419 | * preallocate an entry. First, try to reuse the first entry on the LRU | 412 | * preallocate an entry. |
420 | * if it works, then go ahead and prune the LRU list. | ||
421 | */ | 413 | */ |
422 | spin_lock(&cache_lock); | ||
423 | if (!list_empty(&lru_head)) { | ||
424 | rp = list_first_entry(&lru_head, struct svc_cacherep, c_lru); | ||
425 | if (nfsd_cache_entry_expired(rp) || | ||
426 | num_drc_entries >= max_drc_entries) { | ||
427 | nfsd_reply_cache_unhash(rp); | ||
428 | prune_cache_entries(); | ||
429 | goto search_cache; | ||
430 | } | ||
431 | } | ||
432 | |||
433 | /* No expired ones available, allocate a new one. */ | ||
434 | spin_unlock(&cache_lock); | ||
435 | rp = nfsd_reply_cache_alloc(); | 414 | rp = nfsd_reply_cache_alloc(); |
436 | spin_lock(&cache_lock); | 415 | spin_lock(&cache_lock); |
437 | if (likely(rp)) { | 416 | if (likely(rp)) { |
@@ -439,7 +418,9 @@ nfsd_cache_lookup(struct svc_rqst *rqstp) | |||
439 | drc_mem_usage += sizeof(*rp); | 418 | drc_mem_usage += sizeof(*rp); |
440 | } | 419 | } |
441 | 420 | ||
442 | search_cache: | 421 | /* go ahead and prune the cache */ |
422 | prune_cache_entries(); | ||
423 | |||
443 | found = nfsd_cache_search(rqstp, csum); | 424 | found = nfsd_cache_search(rqstp, csum); |
444 | if (found) { | 425 | if (found) { |
445 | if (likely(rp)) | 426 | if (likely(rp)) |
@@ -453,15 +434,6 @@ search_cache: | |||
453 | goto out; | 434 | goto out; |
454 | } | 435 | } |
455 | 436 | ||
456 | /* | ||
457 | * We're keeping the one we just allocated. Are we now over the | ||
458 | * limit? Prune one off the tip of the LRU in trade for the one we | ||
459 | * just allocated if so. | ||
460 | */ | ||
461 | if (num_drc_entries >= max_drc_entries) | ||
462 | nfsd_reply_cache_free_locked(list_first_entry(&lru_head, | ||
463 | struct svc_cacherep, c_lru)); | ||
464 | |||
465 | nfsdstats.rcmisses++; | 437 | nfsdstats.rcmisses++; |
466 | rqstp->rq_cacherep = rp; | 438 | rqstp->rq_cacherep = rp; |
467 | rp->c_state = RC_INPROG; | 439 | rp->c_state = RC_INPROG; |
diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c index 760c85a6f534..9a4a5f9e7468 100644 --- a/fs/nfsd/nfssvc.c +++ b/fs/nfsd/nfssvc.c | |||
@@ -241,6 +241,15 @@ static void nfsd_shutdown_generic(void) | |||
241 | nfsd_racache_shutdown(); | 241 | nfsd_racache_shutdown(); |
242 | } | 242 | } |
243 | 243 | ||
244 | static bool nfsd_needs_lockd(void) | ||
245 | { | ||
246 | #if defined(CONFIG_NFSD_V3) | ||
247 | return (nfsd_versions[2] != NULL) || (nfsd_versions[3] != NULL); | ||
248 | #else | ||
249 | return (nfsd_versions[2] != NULL); | ||
250 | #endif | ||
251 | } | ||
252 | |||
244 | static int nfsd_startup_net(int nrservs, struct net *net) | 253 | static int nfsd_startup_net(int nrservs, struct net *net) |
245 | { | 254 | { |
246 | struct nfsd_net *nn = net_generic(net, nfsd_net_id); | 255 | struct nfsd_net *nn = net_generic(net, nfsd_net_id); |
@@ -255,9 +264,14 @@ static int nfsd_startup_net(int nrservs, struct net *net) | |||
255 | ret = nfsd_init_socks(net); | 264 | ret = nfsd_init_socks(net); |
256 | if (ret) | 265 | if (ret) |
257 | goto out_socks; | 266 | goto out_socks; |
258 | ret = lockd_up(net); | 267 | |
259 | if (ret) | 268 | if (nfsd_needs_lockd() && !nn->lockd_up) { |
260 | goto out_socks; | 269 | ret = lockd_up(net); |
270 | if (ret) | ||
271 | goto out_socks; | ||
272 | nn->lockd_up = 1; | ||
273 | } | ||
274 | |||
261 | ret = nfs4_state_start_net(net); | 275 | ret = nfs4_state_start_net(net); |
262 | if (ret) | 276 | if (ret) |
263 | goto out_lockd; | 277 | goto out_lockd; |
@@ -266,7 +280,10 @@ static int nfsd_startup_net(int nrservs, struct net *net) | |||
266 | return 0; | 280 | return 0; |
267 | 281 | ||
268 | out_lockd: | 282 | out_lockd: |
269 | lockd_down(net); | 283 | if (nn->lockd_up) { |
284 | lockd_down(net); | ||
285 | nn->lockd_up = 0; | ||
286 | } | ||
270 | out_socks: | 287 | out_socks: |
271 | nfsd_shutdown_generic(); | 288 | nfsd_shutdown_generic(); |
272 | return ret; | 289 | return ret; |
@@ -277,7 +294,10 @@ static void nfsd_shutdown_net(struct net *net) | |||
277 | struct nfsd_net *nn = net_generic(net, nfsd_net_id); | 294 | struct nfsd_net *nn = net_generic(net, nfsd_net_id); |
278 | 295 | ||
279 | nfs4_state_shutdown_net(net); | 296 | nfs4_state_shutdown_net(net); |
280 | lockd_down(net); | 297 | if (nn->lockd_up) { |
298 | lockd_down(net); | ||
299 | nn->lockd_up = 0; | ||
300 | } | ||
281 | nn->nfsd_net_up = false; | 301 | nn->nfsd_net_up = false; |
282 | nfsd_shutdown_generic(); | 302 | nfsd_shutdown_generic(); |
283 | } | 303 | } |
diff --git a/fs/nfsd/nfsxdr.c b/fs/nfsd/nfsxdr.c index 9c769a47ac5a..b17d93214d01 100644 --- a/fs/nfsd/nfsxdr.c +++ b/fs/nfsd/nfsxdr.c | |||
@@ -152,7 +152,7 @@ encode_fattr(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp, | |||
152 | type = (stat->mode & S_IFMT); | 152 | type = (stat->mode & S_IFMT); |
153 | 153 | ||
154 | *p++ = htonl(nfs_ftypes[type >> 12]); | 154 | *p++ = htonl(nfs_ftypes[type >> 12]); |
155 | *p++ = htonl((u32) stat->mode); | 155 | *p++ = htonl((u32) (stat->mode & S_IALLUGO)); |
156 | *p++ = htonl((u32) stat->nlink); | 156 | *p++ = htonl((u32) stat->nlink); |
157 | *p++ = htonl((u32) from_kuid(&init_user_ns, stat->uid)); | 157 | *p++ = htonl((u32) from_kuid(&init_user_ns, stat->uid)); |
158 | *p++ = htonl((u32) from_kgid(&init_user_ns, stat->gid)); | 158 | *p++ = htonl((u32) from_kgid(&init_user_ns, stat->gid)); |
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index 1426eb66c8c6..017d3cb5e99b 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c | |||
@@ -207,7 +207,12 @@ nfsd_lookup_dentry(struct svc_rqst *rqstp, struct svc_fh *fhp, | |||
207 | goto out_nfserr; | 207 | goto out_nfserr; |
208 | } | 208 | } |
209 | } else { | 209 | } else { |
210 | fh_lock(fhp); | 210 | /* |
211 | * In the nfsd4_open() case, this may be held across | ||
212 | * subsequent open and delegation acquisition which may | ||
213 | * need to take the child's i_mutex: | ||
214 | */ | ||
215 | fh_lock_nested(fhp, I_MUTEX_PARENT); | ||
211 | dentry = lookup_one_len(name, dparent, len); | 216 | dentry = lookup_one_len(name, dparent, len); |
212 | host_err = PTR_ERR(dentry); | 217 | host_err = PTR_ERR(dentry); |
213 | if (IS_ERR(dentry)) | 218 | if (IS_ERR(dentry)) |
@@ -273,13 +278,6 @@ out: | |||
273 | return err; | 278 | return err; |
274 | } | 279 | } |
275 | 280 | ||
276 | static int nfsd_break_lease(struct inode *inode) | ||
277 | { | ||
278 | if (!S_ISREG(inode->i_mode)) | ||
279 | return 0; | ||
280 | return break_lease(inode, O_WRONLY | O_NONBLOCK); | ||
281 | } | ||
282 | |||
283 | /* | 281 | /* |
284 | * Commit metadata changes to stable storage. | 282 | * Commit metadata changes to stable storage. |
285 | */ | 283 | */ |
@@ -348,8 +346,7 @@ nfsd_sanitize_attrs(struct inode *inode, struct iattr *iap) | |||
348 | 346 | ||
349 | /* Revoke setuid/setgid on chown */ | 347 | /* Revoke setuid/setgid on chown */ |
350 | if (!S_ISDIR(inode->i_mode) && | 348 | if (!S_ISDIR(inode->i_mode) && |
351 | (((iap->ia_valid & ATTR_UID) && !uid_eq(iap->ia_uid, inode->i_uid)) || | 349 | ((iap->ia_valid & ATTR_UID) || (iap->ia_valid & ATTR_GID))) { |
352 | ((iap->ia_valid & ATTR_GID) && !gid_eq(iap->ia_gid, inode->i_gid)))) { | ||
353 | iap->ia_valid |= ATTR_KILL_PRIV; | 350 | iap->ia_valid |= ATTR_KILL_PRIV; |
354 | if (iap->ia_valid & ATTR_MODE) { | 351 | if (iap->ia_valid & ATTR_MODE) { |
355 | /* we're setting mode too, just clear the s*id bits */ | 352 | /* we're setting mode too, just clear the s*id bits */ |
@@ -449,16 +446,10 @@ nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp, struct iattr *iap, | |||
449 | goto out_put_write_access; | 446 | goto out_put_write_access; |
450 | } | 447 | } |
451 | 448 | ||
452 | host_err = nfsd_break_lease(inode); | ||
453 | if (host_err) | ||
454 | goto out_put_write_access_nfserror; | ||
455 | |||
456 | fh_lock(fhp); | 449 | fh_lock(fhp); |
457 | host_err = notify_change(dentry, iap, NULL); | 450 | host_err = notify_change(dentry, iap, NULL); |
458 | fh_unlock(fhp); | 451 | fh_unlock(fhp); |
459 | 452 | ||
460 | out_put_write_access_nfserror: | ||
461 | err = nfserrno(host_err); | ||
462 | out_put_write_access: | 453 | out_put_write_access: |
463 | if (size_change) | 454 | if (size_change) |
464 | put_write_access(inode); | 455 | put_write_access(inode); |
@@ -1609,11 +1600,6 @@ nfsd_link(struct svc_rqst *rqstp, struct svc_fh *ffhp, | |||
1609 | err = nfserr_noent; | 1600 | err = nfserr_noent; |
1610 | if (!dold->d_inode) | 1601 | if (!dold->d_inode) |
1611 | goto out_dput; | 1602 | goto out_dput; |
1612 | host_err = nfsd_break_lease(dold->d_inode); | ||
1613 | if (host_err) { | ||
1614 | err = nfserrno(host_err); | ||
1615 | goto out_dput; | ||
1616 | } | ||
1617 | host_err = vfs_link(dold, dirp, dnew, NULL); | 1603 | host_err = vfs_link(dold, dirp, dnew, NULL); |
1618 | if (!host_err) { | 1604 | if (!host_err) { |
1619 | err = nfserrno(commit_metadata(ffhp)); | 1605 | err = nfserrno(commit_metadata(ffhp)); |
@@ -1707,14 +1693,6 @@ nfsd_rename(struct svc_rqst *rqstp, struct svc_fh *ffhp, char *fname, int flen, | |||
1707 | if (ffhp->fh_export->ex_path.dentry != tfhp->fh_export->ex_path.dentry) | 1693 | if (ffhp->fh_export->ex_path.dentry != tfhp->fh_export->ex_path.dentry) |
1708 | goto out_dput_new; | 1694 | goto out_dput_new; |
1709 | 1695 | ||
1710 | host_err = nfsd_break_lease(odentry->d_inode); | ||
1711 | if (host_err) | ||
1712 | goto out_dput_new; | ||
1713 | if (ndentry->d_inode) { | ||
1714 | host_err = nfsd_break_lease(ndentry->d_inode); | ||
1715 | if (host_err) | ||
1716 | goto out_dput_new; | ||
1717 | } | ||
1718 | host_err = vfs_rename(fdir, odentry, tdir, ndentry, NULL); | 1696 | host_err = vfs_rename(fdir, odentry, tdir, ndentry, NULL); |
1719 | if (!host_err) { | 1697 | if (!host_err) { |
1720 | host_err = commit_metadata(tfhp); | 1698 | host_err = commit_metadata(tfhp); |
@@ -1784,16 +1762,12 @@ nfsd_unlink(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, | |||
1784 | if (!type) | 1762 | if (!type) |
1785 | type = rdentry->d_inode->i_mode & S_IFMT; | 1763 | type = rdentry->d_inode->i_mode & S_IFMT; |
1786 | 1764 | ||
1787 | host_err = nfsd_break_lease(rdentry->d_inode); | ||
1788 | if (host_err) | ||
1789 | goto out_put; | ||
1790 | if (type != S_IFDIR) | 1765 | if (type != S_IFDIR) |
1791 | host_err = vfs_unlink(dirp, rdentry, NULL); | 1766 | host_err = vfs_unlink(dirp, rdentry, NULL); |
1792 | else | 1767 | else |
1793 | host_err = vfs_rmdir(dirp, rdentry); | 1768 | host_err = vfs_rmdir(dirp, rdentry); |
1794 | if (!host_err) | 1769 | if (!host_err) |
1795 | host_err = commit_metadata(fhp); | 1770 | host_err = commit_metadata(fhp); |
1796 | out_put: | ||
1797 | dput(rdentry); | 1771 | dput(rdentry); |
1798 | 1772 | ||
1799 | out_nfserr: | 1773 | out_nfserr: |
diff --git a/fs/nfsd/vfs.h b/fs/nfsd/vfs.h index 1bc1d440a1a5..fbe90bdb2214 100644 --- a/fs/nfsd/vfs.h +++ b/fs/nfsd/vfs.h | |||
@@ -86,8 +86,6 @@ __be32 nfsd_link(struct svc_rqst *, struct svc_fh *, | |||
86 | __be32 nfsd_rename(struct svc_rqst *, | 86 | __be32 nfsd_rename(struct svc_rqst *, |
87 | struct svc_fh *, char *, int, | 87 | struct svc_fh *, char *, int, |
88 | struct svc_fh *, char *, int); | 88 | struct svc_fh *, char *, int); |
89 | __be32 nfsd_remove(struct svc_rqst *, | ||
90 | struct svc_fh *, char *, int); | ||
91 | __be32 nfsd_unlink(struct svc_rqst *, struct svc_fh *, int type, | 89 | __be32 nfsd_unlink(struct svc_rqst *, struct svc_fh *, int type, |
92 | char *name, int len); | 90 | char *name, int len); |
93 | __be32 nfsd_readdir(struct svc_rqst *, struct svc_fh *, | 91 | __be32 nfsd_readdir(struct svc_rqst *, struct svc_fh *, |
diff --git a/fs/nfsd/xdr3.h b/fs/nfsd/xdr3.h index b6d5542a4ac8..335e04aaf7db 100644 --- a/fs/nfsd/xdr3.h +++ b/fs/nfsd/xdr3.h | |||
@@ -174,6 +174,9 @@ struct nfsd3_linkres { | |||
174 | struct nfsd3_readdirres { | 174 | struct nfsd3_readdirres { |
175 | __be32 status; | 175 | __be32 status; |
176 | struct svc_fh fh; | 176 | struct svc_fh fh; |
177 | /* Just to save kmalloc on every readdirplus entry (svc_fh is a | ||
178 | * little large for the stack): */ | ||
179 | struct svc_fh scratch; | ||
177 | int count; | 180 | int count; |
178 | __be32 verf[2]; | 181 | __be32 verf[2]; |
179 | 182 | ||
diff --git a/fs/nfsd/xdr4.h b/fs/nfsd/xdr4.h index b3ed6446ed8e..d278a0d03496 100644 --- a/fs/nfsd/xdr4.h +++ b/fs/nfsd/xdr4.h | |||
@@ -228,7 +228,7 @@ struct nfsd4_open { | |||
228 | u32 op_create; /* request */ | 228 | u32 op_create; /* request */ |
229 | u32 op_createmode; /* request */ | 229 | u32 op_createmode; /* request */ |
230 | u32 op_bmval[3]; /* request */ | 230 | u32 op_bmval[3]; /* request */ |
231 | struct iattr iattr; /* UNCHECKED4, GUARDED4, EXCLUSIVE4_1 */ | 231 | struct iattr op_iattr; /* UNCHECKED4, GUARDED4, EXCLUSIVE4_1 */ |
232 | nfs4_verifier op_verf __attribute__((aligned(32))); | 232 | nfs4_verifier op_verf __attribute__((aligned(32))); |
233 | /* EXCLUSIVE4 */ | 233 | /* EXCLUSIVE4 */ |
234 | clientid_t op_clientid; /* request */ | 234 | clientid_t op_clientid; /* request */ |
@@ -250,7 +250,6 @@ struct nfsd4_open { | |||
250 | struct nfs4_acl *op_acl; | 250 | struct nfs4_acl *op_acl; |
251 | struct xdr_netobj op_label; | 251 | struct xdr_netobj op_label; |
252 | }; | 252 | }; |
253 | #define op_iattr iattr | ||
254 | 253 | ||
255 | struct nfsd4_open_confirm { | 254 | struct nfsd4_open_confirm { |
256 | stateid_t oc_req_stateid /* request */; | 255 | stateid_t oc_req_stateid /* request */; |
@@ -374,7 +373,6 @@ struct nfsd4_test_stateid { | |||
374 | 373 | ||
375 | struct nfsd4_free_stateid { | 374 | struct nfsd4_free_stateid { |
376 | stateid_t fr_stateid; /* request */ | 375 | stateid_t fr_stateid; /* request */ |
377 | __be32 fr_status; /* response */ | ||
378 | }; | 376 | }; |
379 | 377 | ||
380 | /* also used for NVERIFY */ | 378 | /* also used for NVERIFY */ |