aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2014-01-30 13:18:43 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2014-01-30 13:18:43 -0500
commitd9894c228b11273e720bb63ba120d1d326fe9d94 (patch)
treec9b91b716f281f5accf8860dfadb1ac95abf0090
parentdfa19426160046770b3a38985042df9c9760a25a (diff)
parented47b062ce9546fbe1eebf9da6937df4c5035372 (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 ...
-rw-r--r--Documentation/filesystems/nfs/nfs41-server.txt42
-rw-r--r--fs/nfsd/acl.h2
-rw-r--r--fs/nfsd/cache.h8
-rw-r--r--fs/nfsd/idmap.h4
-rw-r--r--fs/nfsd/netns.h1
-rw-r--r--fs/nfsd/nfs3xdr.c14
-rw-r--r--fs/nfsd/nfs4acl.c20
-rw-r--r--fs/nfsd/nfs4idmap.c50
-rw-r--r--fs/nfsd/nfs4proc.c57
-rw-r--r--fs/nfsd/nfs4state.c40
-rw-r--r--fs/nfsd/nfs4xdr.c178
-rw-r--r--fs/nfsd/nfscache.c36
-rw-r--r--fs/nfsd/nfssvc.c30
-rw-r--r--fs/nfsd/nfsxdr.c2
-rw-r--r--fs/nfsd/vfs.c40
-rw-r--r--fs/nfsd/vfs.h2
-rw-r--r--fs/nfsd/xdr3.h3
-rw-r--r--fs/nfsd/xdr4.h4
-rw-r--r--include/linux/sunrpc/svc.h6
-rw-r--r--net/sunrpc/auth_gss/gss_krb5_keys.c17
-rw-r--r--net/sunrpc/auth_gss/gss_rpc_upcall.c2
-rw-r--r--net/sunrpc/auth_gss/svcauth_gss.c82
-rw-r--r--net/sunrpc/cache.c4
-rw-r--r--net/sunrpc/netns.h1
-rw-r--r--net/sunrpc/svc.c25
-rw-r--r--net/sunrpc/xprtsock.c7
26 files changed, 284 insertions, 393 deletions
diff --git a/Documentation/filesystems/nfs/nfs41-server.txt b/Documentation/filesystems/nfs/nfs41-server.txt
index 01c2db769791..b930ad087780 100644
--- a/Documentation/filesystems/nfs/nfs41-server.txt
+++ b/Documentation/filesystems/nfs/nfs41-server.txt
@@ -5,11 +5,11 @@ Server support for minorversion 1 can be controlled using the
5by reading this file will contain either "+4.1" or "-4.1" 5by reading this file will contain either "+4.1" or "-4.1"
6correspondingly. 6correspondingly.
7 7
8Currently, server support for minorversion 1 is disabled by default. 8Currently, server support for minorversion 1 is enabled by default.
9It can be enabled at run time by writing the string "+4.1" to 9It can be disabled at run time by writing the string "-4.1" to
10the /proc/fs/nfsd/versions control file. Note that to write this 10the /proc/fs/nfsd/versions control file. Note that to write this
11control file, the nfsd service must be taken down. Use your user-mode 11control file, the nfsd service must be taken down. You can use rpc.nfsd
12nfs-utils to set this up; see rpc.nfsd(8) 12for this; see rpc.nfsd(8).
13 13
14(Warning: older servers will interpret "+4.1" and "-4.1" as "+4" and 14(Warning: older servers will interpret "+4.1" and "-4.1" as "+4" and
15"-4", respectively. Therefore, code meant to work on both new and old 15"-4", respectively. Therefore, code meant to work on both new and old
@@ -29,29 +29,6 @@ are still under development out of tree.
29See http://wiki.linux-nfs.org/wiki/index.php/PNFS_prototype_design 29See http://wiki.linux-nfs.org/wiki/index.php/PNFS_prototype_design
30for more information. 30for more information.
31 31
32The current implementation is intended for developers only: while it
33does support ordinary file operations on clients we have tested against
34(including the linux client), it is incomplete in ways which may limit
35features unexpectedly, cause known bugs in rare cases, or cause
36interoperability problems with future clients. Known issues:
37
38 - gss support is questionable: currently mounts with kerberos
39 from a linux client are possible, but we aren't really
40 conformant with the spec (for example, we don't use kerberos
41 on the backchannel correctly).
42 - We do not support SSV, which provides security for shared
43 client-server state (thus preventing unauthorized tampering
44 with locks and opens, for example). It is mandatory for
45 servers to support this, though no clients use it yet.
46
47In addition, some limitations are inherited from the current NFSv4
48implementation:
49
50 - Incomplete delegation enforcement: if a file is renamed or
51 unlinked by a local process, a client holding a delegation may
52 continue to indefinitely allow opens of the file under the old
53 name.
54
55The table below, taken from the NFSv4.1 document, lists 32The table below, taken from the NFSv4.1 document, lists
56the operations that are mandatory to implement (REQ), optional 33the operations that are mandatory to implement (REQ), optional
57(OPT), and NFSv4.0 operations that are required not to implement (MNI) 34(OPT), and NFSv4.0 operations that are required not to implement (MNI)
@@ -169,6 +146,16 @@ NS*| CB_WANTS_CANCELLED | OPT | FDELG, | Section 20.10 |
169 146
170Implementation notes: 147Implementation notes:
171 148
149SSV:
150* The spec claims this is mandatory, but we don't actually know of any
151 implementations, so we're ignoring it for now. The server returns
152 NFS4ERR_ENCR_ALG_UNSUPP on EXCHANGE_ID, which should be future-proof.
153
154GSS on the backchannel:
155* Again, theoretically required but not widely implemented (in
156 particular, the current Linux client doesn't request it). We return
157 NFS4ERR_ENCR_ALG_UNSUPP on CREATE_SESSION.
158
172DELEGPURGE: 159DELEGPURGE:
173* mandatory only for servers that support CLAIM_DELEGATE_PREV and/or 160* mandatory only for servers that support CLAIM_DELEGATE_PREV and/or
174 CLAIM_DELEG_PREV_FH (which allows clients to keep delegations that 161 CLAIM_DELEG_PREV_FH (which allows clients to keep delegations that
@@ -176,7 +163,6 @@ DELEGPURGE:
176 now. 163 now.
177 164
178EXCHANGE_ID: 165EXCHANGE_ID:
179* only SP4_NONE state protection supported
180* implementation ids are ignored 166* implementation ids are ignored
181 167
182CREATE_SESSION: 168CREATE_SESSION:
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
46struct nfs4_acl *nfs4_acl_new(int); 46struct nfs4_acl *nfs4_acl_new(int);
47int nfs4_acl_get_whotype(char *, u32); 47int nfs4_acl_get_whotype(char *, u32);
48int nfs4_acl_write_who(int who, char *p); 48__be32 nfs4_acl_write_who(int who, __be32 **p, int *len);
49 49
50int nfsd4_get_nfs4_acl(struct svc_rqst *rqstp, struct dentry *dentry, 50int 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 *);
84void nfsd_cache_update(struct svc_rqst *, int, __be32 *); 84void nfsd_cache_update(struct svc_rqst *, int, __be32 *);
85int nfsd_reply_cache_stats_open(struct inode *, struct file *); 85int nfsd_reply_cache_stats_open(struct inode *, struct file *);
86 86
87#ifdef CONFIG_NFSD_V4
88void nfsd4_set_statp(struct svc_rqst *rqstp, __be32 *statp);
89#else /* CONFIG_NFSD_V4 */
90static 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 *);
59int nfsd_map_uid_to_name(struct svc_rqst *, kuid_t, char *); 59__be32 nfsd4_encode_user(struct svc_rqst *, kuid_t, __be32 **, int *);
60int 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
843static __be32 *encode_entryplus_baggage(struct nfsd3_readdirres *cd, __be32 *p, const char *name, int namlen) 843static __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);
858out: 858out:
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
919int 920__be32 nfs4_acl_write_who(int who, __be32 **p, int *len)
920nfs4_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
554static int 554static __be32 encode_ascii_id(u32 id, __be32 **p, int *buflen)
555idmap_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
569static __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
577static bool 596static 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
606static int 625static __be32 encode_name_from_id(struct svc_rqst *rqstp, int type, u32 id, __be32 **p, int *buflen)
607do_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
640int 658__be32 nfsd4_encode_user(struct svc_rqst *rqstp, kuid_t uid, __be32 **p, int *buflen)
641nfsd_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
647int 664__be32 nfsd4_encode_group(struct svc_rqst *rqstp, kgid_t gid, __be32 **p, int *buflen)
648nfsd_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
233static __be32 233static __be32
234do_open_lookup(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, struct nfsd4_open *open) 234do_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);
306out: 308out:
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);
464out: 466out:
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)
1525static inline u32 nfsd4_exchange_id_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op) 1534static 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
835static struct nfsd4_session *alloc_session(struct nfsd4_channel_attrs *attrs) 835static 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;
856out_free: 861out_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
1854static __be32 check_backchannel_attrs(struct nfsd4_channel_attrs *ca) 1863static __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;
3055out_free:
3056 locks_free_lock(fl);
3057 return status;
3049} 3058}
3050 3059
3051static int nfs4_set_delegation(struct nfs4_delegation *dp, struct nfs4_file *fp) 3060static 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 */
193static int 197static int
194defer_free(struct nfsd4_compoundargs *argp, 198defer_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 */
209static char *savemem(struct nfsd4_compoundargs *argp, __be32 *p, int nbytes) 223static 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
429out_nfserr:
430 status = nfserrno(host_err);
431 goto out;
432} 440}
433 441
434static __be32 442static __be32
@@ -1957,56 +1965,16 @@ static u32 nfs4_file_type(umode_t mode)
1957 }; 1965 };
1958} 1966}
1959 1967
1960static __be32
1961nfsd4_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
1982static inline __be32
1983nfsd4_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
1989static inline __be32
1990nfsd4_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
1996static inline __be32 1968static inline __be32
1997nfsd4_encode_aclname(struct svc_rqst *rqstp, struct nfs4_ace *ace, 1969nfsd4_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;
2539out_nfserr: 2505out_nfserr:
2540 status = nfserrno(err); 2506 status = nfserrno(err);
@@ -2542,9 +2508,6 @@ out_nfserr:
2542out_resource: 2508out_resource:
2543 status = nfserr_resource; 2509 status = nfserr_resource;
2544 goto out; 2510 goto out;
2545out_serverfault:
2546 status = nfserr_serverfault;
2547 goto out;
2548} 2511}
2549 2512
2550static inline int attributes_need_mount(u32 *bmval) 2513static inline int attributes_need_mount(u32 *bmval)
@@ -2621,17 +2584,14 @@ out_put:
2621static __be32 * 2584static __be32 *
2622nfsd4_encode_rdattr_error(__be32 *p, int buflen, __be32 nfserr) 2585nfsd4_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
3476static __be32 3444static __be32
3477nfsd4_encode_destroy_session(struct nfsd4_compoundres *resp, __be32 nfserr,
3478 struct nfsd4_destroy_session *destroy_session)
3479{
3480 return nfserr;
3481}
3482
3483static __be32
3484nfsd4_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
3498static __be32
3499nfsd4_encode_sequence(struct nfsd4_compoundres *resp, __be32 nfserr, 3445nfsd4_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
134static void 134static void
135nfsd_reply_cache_unhash(struct svc_cacherep *rp)
136{
137 hlist_del_init(&rp->c_hash);
138 list_del_init(&rp->c_lru);
139}
140
141static void
142nfsd_reply_cache_free_locked(struct svc_cacherep *rp) 135nfsd_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
442search_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
244static 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
244static int nfsd_startup_net(int nrservs, struct net *net) 253static 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
268out_lockd: 282out_lockd:
269 lockd_down(net); 283 if (nn->lockd_up) {
284 lockd_down(net);
285 nn->lockd_up = 0;
286 }
270out_socks: 287out_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
276static 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
460out_put_write_access_nfserror:
461 err = nfserrno(host_err);
462out_put_write_access: 453out_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);
1796out_put:
1797 dput(rdentry); 1771 dput(rdentry);
1798 1772
1799out_nfserr: 1773out_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 {
174struct nfsd3_readdirres { 174struct 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
255struct nfsd4_open_confirm { 254struct 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
375struct nfsd4_free_stateid { 374struct 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 */
diff --git a/include/linux/sunrpc/svc.h b/include/linux/sunrpc/svc.h
index 6eecfc2e4f98..04e763221246 100644
--- a/include/linux/sunrpc/svc.h
+++ b/include/linux/sunrpc/svc.h
@@ -368,7 +368,7 @@ struct svc_program {
368 struct svc_program * pg_next; /* other programs (same xprt) */ 368 struct svc_program * pg_next; /* other programs (same xprt) */
369 u32 pg_prog; /* program number */ 369 u32 pg_prog; /* program number */
370 unsigned int pg_lovers; /* lowest version */ 370 unsigned int pg_lovers; /* lowest version */
371 unsigned int pg_hivers; /* lowest version */ 371 unsigned int pg_hivers; /* highest version */
372 unsigned int pg_nvers; /* number of versions */ 372 unsigned int pg_nvers; /* number of versions */
373 struct svc_version ** pg_vers; /* version array */ 373 struct svc_version ** pg_vers; /* version array */
374 char * pg_name; /* service name */ 374 char * pg_name; /* service name */
@@ -386,8 +386,10 @@ struct svc_version {
386 struct svc_procedure * vs_proc; /* per-procedure info */ 386 struct svc_procedure * vs_proc; /* per-procedure info */
387 u32 vs_xdrsize; /* xdrsize needed for this version */ 387 u32 vs_xdrsize; /* xdrsize needed for this version */
388 388
389 unsigned int vs_hidden : 1; /* Don't register with portmapper. 389 unsigned int vs_hidden : 1, /* Don't register with portmapper.
390 * Only used for nfsacl so far. */ 390 * Only used for nfsacl so far. */
391 vs_rpcb_optnl:1;/* Don't care the result of register.
392 * Only used for nfsv4. */
391 393
392 /* Override dispatch function (e.g. when caching replies). 394 /* Override dispatch function (e.g. when caching replies).
393 * A return value of 0 means drop the request. 395 * A return value of 0 means drop the request.
diff --git a/net/sunrpc/auth_gss/gss_krb5_keys.c b/net/sunrpc/auth_gss/gss_krb5_keys.c
index 76e42e6be755..24589bd2a4b6 100644
--- a/net/sunrpc/auth_gss/gss_krb5_keys.c
+++ b/net/sunrpc/auth_gss/gss_krb5_keys.c
@@ -59,6 +59,7 @@
59#include <linux/crypto.h> 59#include <linux/crypto.h>
60#include <linux/sunrpc/gss_krb5.h> 60#include <linux/sunrpc/gss_krb5.h>
61#include <linux/sunrpc/xdr.h> 61#include <linux/sunrpc/xdr.h>
62#include <linux/lcm.h>
62 63
63#ifdef RPC_DEBUG 64#ifdef RPC_DEBUG
64# define RPCDBG_FACILITY RPCDBG_AUTH 65# define RPCDBG_FACILITY RPCDBG_AUTH
@@ -72,7 +73,7 @@
72static void krb5_nfold(u32 inbits, const u8 *in, 73static void krb5_nfold(u32 inbits, const u8 *in,
73 u32 outbits, u8 *out) 74 u32 outbits, u8 *out)
74{ 75{
75 int a, b, c, lcm; 76 unsigned long ulcm;
76 int byte, i, msbit; 77 int byte, i, msbit;
77 78
78 /* the code below is more readable if I make these bytes 79 /* the code below is more readable if I make these bytes
@@ -82,17 +83,7 @@ static void krb5_nfold(u32 inbits, const u8 *in,
82 outbits >>= 3; 83 outbits >>= 3;
83 84
84 /* first compute lcm(n,k) */ 85 /* first compute lcm(n,k) */
85 86 ulcm = lcm(inbits, outbits);
86 a = outbits;
87 b = inbits;
88
89 while (b != 0) {
90 c = b;
91 b = a%b;
92 a = c;
93 }
94
95 lcm = outbits*inbits/a;
96 87
97 /* now do the real work */ 88 /* now do the real work */
98 89
@@ -101,7 +92,7 @@ static void krb5_nfold(u32 inbits, const u8 *in,
101 92
102 /* this will end up cycling through k lcm(k,n)/k times, which 93 /* this will end up cycling through k lcm(k,n)/k times, which
103 is correct */ 94 is correct */
104 for (i = lcm-1; i >= 0; i--) { 95 for (i = ulcm-1; i >= 0; i--) {
105 /* compute the msbit in k which gets added into this byte */ 96 /* compute the msbit in k which gets added into this byte */
106 msbit = ( 97 msbit = (
107 /* first, start with the msbit in the first, 98 /* first, start with the msbit in the first,
diff --git a/net/sunrpc/auth_gss/gss_rpc_upcall.c b/net/sunrpc/auth_gss/gss_rpc_upcall.c
index 458f85e9b0ba..abbb7dcd1689 100644
--- a/net/sunrpc/auth_gss/gss_rpc_upcall.c
+++ b/net/sunrpc/auth_gss/gss_rpc_upcall.c
@@ -137,7 +137,6 @@ void init_gssp_clnt(struct sunrpc_net *sn)
137{ 137{
138 mutex_init(&sn->gssp_lock); 138 mutex_init(&sn->gssp_lock);
139 sn->gssp_clnt = NULL; 139 sn->gssp_clnt = NULL;
140 init_waitqueue_head(&sn->gssp_wq);
141} 140}
142 141
143int set_gssp_clnt(struct net *net) 142int set_gssp_clnt(struct net *net)
@@ -154,7 +153,6 @@ int set_gssp_clnt(struct net *net)
154 sn->gssp_clnt = clnt; 153 sn->gssp_clnt = clnt;
155 } 154 }
156 mutex_unlock(&sn->gssp_lock); 155 mutex_unlock(&sn->gssp_lock);
157 wake_up(&sn->gssp_wq);
158 return ret; 156 return ret;
159} 157}
160 158
diff --git a/net/sunrpc/auth_gss/svcauth_gss.c b/net/sunrpc/auth_gss/svcauth_gss.c
index 008cdade5aae..0f73f4507746 100644
--- a/net/sunrpc/auth_gss/svcauth_gss.c
+++ b/net/sunrpc/auth_gss/svcauth_gss.c
@@ -1263,65 +1263,34 @@ out:
1263 return ret; 1263 return ret;
1264} 1264}
1265 1265
1266DEFINE_SPINLOCK(use_gssp_lock); 1266/*
1267 1267 * Try to set the sn->use_gss_proxy variable to a new value. We only allow
1268static bool use_gss_proxy(struct net *net) 1268 * it to be changed if it's currently undefined (-1). If it's any other value
1269{ 1269 * then return -EBUSY unless the type wouldn't have changed anyway.
1270 struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); 1270 */
1271
1272 if (sn->use_gss_proxy != -1)
1273 return sn->use_gss_proxy;
1274 spin_lock(&use_gssp_lock);
1275 /*
1276 * If you wanted gss-proxy, you should have said so before
1277 * starting to accept requests:
1278 */
1279 sn->use_gss_proxy = 0;
1280 spin_unlock(&use_gssp_lock);
1281 return 0;
1282}
1283
1284#ifdef CONFIG_PROC_FS
1285
1286static int set_gss_proxy(struct net *net, int type) 1271static int set_gss_proxy(struct net *net, int type)
1287{ 1272{
1288 struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); 1273 struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
1289 int ret = 0; 1274 int ret;
1290 1275
1291 WARN_ON_ONCE(type != 0 && type != 1); 1276 WARN_ON_ONCE(type != 0 && type != 1);
1292 spin_lock(&use_gssp_lock); 1277 ret = cmpxchg(&sn->use_gss_proxy, -1, type);
1293 if (sn->use_gss_proxy == -1 || sn->use_gss_proxy == type) 1278 if (ret != -1 && ret != type)
1294 sn->use_gss_proxy = type; 1279 return -EBUSY;
1295 else 1280 return 0;
1296 ret = -EBUSY;
1297 spin_unlock(&use_gssp_lock);
1298 wake_up(&sn->gssp_wq);
1299 return ret;
1300}
1301
1302static inline bool gssp_ready(struct sunrpc_net *sn)
1303{
1304 switch (sn->use_gss_proxy) {
1305 case -1:
1306 return false;
1307 case 0:
1308 return true;
1309 case 1:
1310 return sn->gssp_clnt;
1311 }
1312 WARN_ON_ONCE(1);
1313 return false;
1314} 1281}
1315 1282
1316static int wait_for_gss_proxy(struct net *net, struct file *file) 1283static bool use_gss_proxy(struct net *net)
1317{ 1284{
1318 struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); 1285 struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
1319 1286
1320 if (file->f_flags & O_NONBLOCK && !gssp_ready(sn)) 1287 /* If use_gss_proxy is still undefined, then try to disable it */
1321 return -EAGAIN; 1288 if (sn->use_gss_proxy == -1)
1322 return wait_event_interruptible(sn->gssp_wq, gssp_ready(sn)); 1289 set_gss_proxy(net, 0);
1290 return sn->use_gss_proxy;
1323} 1291}
1324 1292
1293#ifdef CONFIG_PROC_FS
1325 1294
1326static ssize_t write_gssp(struct file *file, const char __user *buf, 1295static ssize_t write_gssp(struct file *file, const char __user *buf,
1327 size_t count, loff_t *ppos) 1296 size_t count, loff_t *ppos)
@@ -1342,10 +1311,10 @@ static ssize_t write_gssp(struct file *file, const char __user *buf,
1342 return res; 1311 return res;
1343 if (i != 1) 1312 if (i != 1)
1344 return -EINVAL; 1313 return -EINVAL;
1345 res = set_gss_proxy(net, 1); 1314 res = set_gssp_clnt(net);
1346 if (res) 1315 if (res)
1347 return res; 1316 return res;
1348 res = set_gssp_clnt(net); 1317 res = set_gss_proxy(net, 1);
1349 if (res) 1318 if (res)
1350 return res; 1319 return res;
1351 return count; 1320 return count;
@@ -1355,16 +1324,12 @@ static ssize_t read_gssp(struct file *file, char __user *buf,
1355 size_t count, loff_t *ppos) 1324 size_t count, loff_t *ppos)
1356{ 1325{
1357 struct net *net = PDE_DATA(file_inode(file)); 1326 struct net *net = PDE_DATA(file_inode(file));
1327 struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
1358 unsigned long p = *ppos; 1328 unsigned long p = *ppos;
1359 char tbuf[10]; 1329 char tbuf[10];
1360 size_t len; 1330 size_t len;
1361 int ret;
1362 1331
1363 ret = wait_for_gss_proxy(net, file); 1332 snprintf(tbuf, sizeof(tbuf), "%d\n", sn->use_gss_proxy);
1364 if (ret)
1365 return ret;
1366
1367 snprintf(tbuf, sizeof(tbuf), "%d\n", use_gss_proxy(net));
1368 len = strlen(tbuf); 1333 len = strlen(tbuf);
1369 if (p >= len) 1334 if (p >= len)
1370 return 0; 1335 return 0;
@@ -1626,8 +1591,7 @@ svcauth_gss_wrap_resp_integ(struct svc_rqst *rqstp)
1626 BUG_ON(integ_len % 4); 1591 BUG_ON(integ_len % 4);
1627 *p++ = htonl(integ_len); 1592 *p++ = htonl(integ_len);
1628 *p++ = htonl(gc->gc_seq); 1593 *p++ = htonl(gc->gc_seq);
1629 if (xdr_buf_subsegment(resbuf, &integ_buf, integ_offset, 1594 if (xdr_buf_subsegment(resbuf, &integ_buf, integ_offset, integ_len))
1630 integ_len))
1631 BUG(); 1595 BUG();
1632 if (resbuf->tail[0].iov_base == NULL) { 1596 if (resbuf->tail[0].iov_base == NULL) {
1633 if (resbuf->head[0].iov_len + RPC_MAX_AUTH_SIZE > PAGE_SIZE) 1597 if (resbuf->head[0].iov_len + RPC_MAX_AUTH_SIZE > PAGE_SIZE)
@@ -1635,10 +1599,8 @@ svcauth_gss_wrap_resp_integ(struct svc_rqst *rqstp)
1635 resbuf->tail[0].iov_base = resbuf->head[0].iov_base 1599 resbuf->tail[0].iov_base = resbuf->head[0].iov_base
1636 + resbuf->head[0].iov_len; 1600 + resbuf->head[0].iov_len;
1637 resbuf->tail[0].iov_len = 0; 1601 resbuf->tail[0].iov_len = 0;
1638 resv = &resbuf->tail[0];
1639 } else {
1640 resv = &resbuf->tail[0];
1641 } 1602 }
1603 resv = &resbuf->tail[0];
1642 mic.data = (u8 *)resv->iov_base + resv->iov_len + 4; 1604 mic.data = (u8 *)resv->iov_base + resv->iov_len + 4;
1643 if (gss_get_mic(gsd->rsci->mechctx, &integ_buf, &mic)) 1605 if (gss_get_mic(gsd->rsci->mechctx, &integ_buf, &mic))
1644 goto out_err; 1606 goto out_err;
diff --git a/net/sunrpc/cache.c b/net/sunrpc/cache.c
index e521d20e1970..ae333c1845bb 100644
--- a/net/sunrpc/cache.c
+++ b/net/sunrpc/cache.c
@@ -1111,9 +1111,7 @@ void qword_addhex(char **bpp, int *lp, char *buf, int blen)
1111 *bp++ = 'x'; 1111 *bp++ = 'x';
1112 len -= 2; 1112 len -= 2;
1113 while (blen && len >= 2) { 1113 while (blen && len >= 2) {
1114 unsigned char c = *buf++; 1114 bp = hex_byte_pack(bp, *buf++);
1115 *bp++ = '0' + ((c&0xf0)>>4) + (c>=0xa0)*('a'-'9'-1);
1116 *bp++ = '0' + (c&0x0f) + ((c&0x0f)>=0x0a)*('a'-'9'-1);
1117 len -= 2; 1115 len -= 2;
1118 blen--; 1116 blen--;
1119 } 1117 }
diff --git a/net/sunrpc/netns.h b/net/sunrpc/netns.h
index 94e506f9d72b..df5826876535 100644
--- a/net/sunrpc/netns.h
+++ b/net/sunrpc/netns.h
@@ -27,7 +27,6 @@ struct sunrpc_net {
27 unsigned int rpcb_is_af_local : 1; 27 unsigned int rpcb_is_af_local : 1;
28 28
29 struct mutex gssp_lock; 29 struct mutex gssp_lock;
30 wait_queue_head_t gssp_wq;
31 struct rpc_clnt *gssp_clnt; 30 struct rpc_clnt *gssp_clnt;
32 int use_gss_proxy; 31 int use_gss_proxy;
33 int pipe_version; 32 int pipe_version;
diff --git a/net/sunrpc/svc.c b/net/sunrpc/svc.c
index e7fbe368b4a3..5de6801cd924 100644
--- a/net/sunrpc/svc.c
+++ b/net/sunrpc/svc.c
@@ -916,9 +916,6 @@ static int __svc_register(struct net *net, const char *progname,
916#endif 916#endif
917 } 917 }
918 918
919 if (error < 0)
920 printk(KERN_WARNING "svc: failed to register %sv%u RPC "
921 "service (errno %d).\n", progname, version, -error);
922 return error; 919 return error;
923} 920}
924 921
@@ -937,6 +934,7 @@ int svc_register(const struct svc_serv *serv, struct net *net,
937 const unsigned short port) 934 const unsigned short port)
938{ 935{
939 struct svc_program *progp; 936 struct svc_program *progp;
937 struct svc_version *vers;
940 unsigned int i; 938 unsigned int i;
941 int error = 0; 939 int error = 0;
942 940
@@ -946,7 +944,8 @@ int svc_register(const struct svc_serv *serv, struct net *net,
946 944
947 for (progp = serv->sv_program; progp; progp = progp->pg_next) { 945 for (progp = serv->sv_program; progp; progp = progp->pg_next) {
948 for (i = 0; i < progp->pg_nvers; i++) { 946 for (i = 0; i < progp->pg_nvers; i++) {
949 if (progp->pg_vers[i] == NULL) 947 vers = progp->pg_vers[i];
948 if (vers == NULL)
950 continue; 949 continue;
951 950
952 dprintk("svc: svc_register(%sv%d, %s, %u, %u)%s\n", 951 dprintk("svc: svc_register(%sv%d, %s, %u, %u)%s\n",
@@ -955,16 +954,26 @@ int svc_register(const struct svc_serv *serv, struct net *net,
955 proto == IPPROTO_UDP? "udp" : "tcp", 954 proto == IPPROTO_UDP? "udp" : "tcp",
956 port, 955 port,
957 family, 956 family,
958 progp->pg_vers[i]->vs_hidden? 957 vers->vs_hidden ?
959 " (but not telling portmap)" : ""); 958 " (but not telling portmap)" : "");
960 959
961 if (progp->pg_vers[i]->vs_hidden) 960 if (vers->vs_hidden)
962 continue; 961 continue;
963 962
964 error = __svc_register(net, progp->pg_name, progp->pg_prog, 963 error = __svc_register(net, progp->pg_name, progp->pg_prog,
965 i, family, proto, port); 964 i, family, proto, port);
966 if (error < 0) 965
966 if (vers->vs_rpcb_optnl) {
967 error = 0;
968 continue;
969 }
970
971 if (error < 0) {
972 printk(KERN_WARNING "svc: failed to register "
973 "%sv%u RPC service (errno %d).\n",
974 progp->pg_name, i, -error);
967 break; 975 break;
976 }
968 } 977 }
969 } 978 }
970 979
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c
index 2a7ca8ffe83a..817a1e523969 100644
--- a/net/sunrpc/xprtsock.c
+++ b/net/sunrpc/xprtsock.c
@@ -2964,10 +2964,9 @@ static struct rpc_xprt *xs_setup_bc_tcp(struct xprt_create *args)
2964 2964
2965 /* 2965 /*
2966 * Once we've associated a backchannel xprt with a connection, 2966 * Once we've associated a backchannel xprt with a connection,
2967 * we want to keep it around as long as long as the connection 2967 * we want to keep it around as long as the connection lasts,
2968 * lasts, in case we need to start using it for a backchannel 2968 * in case we need to start using it for a backchannel again;
2969 * again; this reference won't be dropped until bc_xprt is 2969 * this reference won't be dropped until bc_xprt is destroyed.
2970 * destroyed.
2971 */ 2970 */
2972 xprt_get(xprt); 2971 xprt_get(xprt);
2973 args->bc_xprt->xpt_bc_xprt = xprt; 2972 args->bc_xprt->xpt_bc_xprt = xprt;