aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-10-12 21:53:54 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2012-10-12 21:53:54 -0400
commitbd81ccea8558daab570d70d2c23746413f26cecf (patch)
treea3a75dde2dc3cf26c74353b21792da30d65d7c13
parent98260daa184c4a171834463cf85ab3a2c509d983 (diff)
parenta9ca4043d074509b9d15003fbcb068d3cdae85a4 (diff)
Merge branch 'for-3.7' of git://linux-nfs.org/~bfields/linux
Pull nfsd update from J Bruce Fields: "Another relatively quiet cycle. There was some progress on my remaining 4.1 todo's, but a couple of them were just of the form "check that we do X correctly", so didn't have much affect on the code. Other than that, a bunch of cleanup and some bugfixes (including an annoying NFSv4.0 state leak and a busy-loop in the server that could cause it to peg the CPU without making progress)." * 'for-3.7' of git://linux-nfs.org/~bfields/linux: (46 commits) UAPI: (Scripted) Disintegrate include/linux/sunrpc UAPI: (Scripted) Disintegrate include/linux/nfsd nfsd4: don't allow reclaims of expired clients nfsd4: remove redundant callback probe nfsd4: expire old client earlier nfsd4: separate session allocation and initialization nfsd4: clean up session allocation nfsd4: minor free_session cleanup nfsd4: new_conn_from_crses should only allocate nfsd4: separate connection allocation and initialization nfsd4: reject bad forechannel attrs earlier nfsd4: enforce per-client sessions/no-sessions distinction nfsd4: set cl_minorversion at create time nfsd4: don't pin clientids to pseudoflavors nfsd4: fix bind_conn_to_session xdr comment nfsd4: cast readlink() bug argument NFSD: pass null terminated buf to kstrtouint() nfsd: remove duplicate init in nfsd4_cb_recall nfsd4: eliminate redundant nfs4_free_stateid fs/nfsd/nfs4idmap.c: adjust inconsistent IS_ERR and PTR_ERR ...
-rw-r--r--Documentation/filesystems/nfs/nfsd-admin-interfaces.txt41
-rw-r--r--fs/lockd/svc.c17
-rw-r--r--fs/locks.c6
-rw-r--r--fs/nfs/callback.c16
-rw-r--r--fs/nfsd/nfs2acl.c3
-rw-r--r--fs/nfsd/nfs3proc.c2
-rw-r--r--fs/nfsd/nfs4callback.c1
-rw-r--r--fs/nfsd/nfs4idmap.c4
-rw-r--r--fs/nfsd/nfs4proc.c6
-rw-r--r--fs/nfsd/nfs4state.c351
-rw-r--r--fs/nfsd/nfs4xdr.c2
-rw-r--r--fs/nfsd/nfsctl.c84
-rw-r--r--fs/nfsd/nfsd.h4
-rw-r--r--fs/nfsd/nfssvc.c26
-rw-r--r--fs/nfsd/state.h8
-rw-r--r--fs/nfsd/vfs.c2
-rw-r--r--include/linux/nfsd/Kbuild5
-rw-r--r--include/linux/nfsd/debug.h31
-rw-r--r--include/linux/nfsd/export.h52
-rw-r--r--include/linux/nfsd/nfsfh.h111
-rw-r--r--include/linux/nfsd/stats.h8
-rw-r--r--include/linux/sunrpc/Kbuild1
-rw-r--r--include/linux/sunrpc/debug.h39
-rw-r--r--include/linux/sunrpc/svc_xprt.h5
-rw-r--r--include/linux/sunrpc/svcsock.h3
-rw-r--r--include/uapi/linux/nfsd/Kbuild5
-rw-r--r--include/uapi/linux/nfsd/cld.h (renamed from include/linux/nfsd/cld.h)0
-rw-r--r--include/uapi/linux/nfsd/debug.h40
-rw-r--r--include/uapi/linux/nfsd/export.h58
-rw-r--r--include/uapi/linux/nfsd/nfsfh.h122
-rw-r--r--include/uapi/linux/nfsd/stats.h17
-rw-r--r--include/uapi/linux/sunrpc/Kbuild1
-rw-r--r--include/uapi/linux/sunrpc/debug.h48
-rw-r--r--net/sunrpc/svc_xprt.c233
-rw-r--r--net/sunrpc/svcsock.c157
-rw-r--r--net/sunrpc/xprtrdma/svc_rdma_transport.c4
36 files changed, 756 insertions, 757 deletions
diff --git a/Documentation/filesystems/nfs/nfsd-admin-interfaces.txt b/Documentation/filesystems/nfs/nfsd-admin-interfaces.txt
new file mode 100644
index 000000000000..56a96fb08a73
--- /dev/null
+++ b/Documentation/filesystems/nfs/nfsd-admin-interfaces.txt
@@ -0,0 +1,41 @@
1Administrative interfaces for nfsd
2^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
3
4Note that normally these interfaces are used only by the utilities in
5nfs-utils.
6
7nfsd is controlled mainly by pseudofiles under the "nfsd" filesystem,
8which is normally mounted at /proc/fs/nfsd/.
9
10The server is always started by the first write of a nonzero value to
11nfsd/threads.
12
13Before doing that, NFSD can be told which sockets to listen on by
14writing to nfsd/portlist; that write may be:
15
16 - an ascii-encoded file descriptor, which should refer to a
17 bound (and listening, for tcp) socket, or
18 - "transportname port", where transportname is currently either
19 "udp", "tcp", or "rdma".
20
21If nfsd is started without doing any of these, then it will create one
22udp and one tcp listener at port 2049 (see nfsd_init_socks).
23
24On startup, nfsd and lockd grace periods start.
25
26nfsd is shut down by a write of 0 to nfsd/threads. All locks and state
27are thrown away at that point.
28
29Between startup and shutdown, the number of threads may be adjusted up
30or down by additional writes to nfsd/threads or by writes to
31nfsd/pool_threads.
32
33For more detail about files under nfsd/ and what they control, see
34fs/nfsd/nfsctl.c; most of them have detailed comments.
35
36Implementation notes
37^^^^^^^^^^^^^^^^^^^^
38
39Note that the rpc server requires the caller to serialize addition and
40removal of listening sockets, and startup and shutdown of the server.
41For nfsd this is done using nfsd_mutex.
diff --git a/fs/lockd/svc.c b/fs/lockd/svc.c
index 7e355870d519..a2aa97d45670 100644
--- a/fs/lockd/svc.c
+++ b/fs/lockd/svc.c
@@ -126,7 +126,7 @@ static void restart_grace(void)
126static int 126static int
127lockd(void *vrqstp) 127lockd(void *vrqstp)
128{ 128{
129 int err = 0, preverr = 0; 129 int err = 0;
130 struct svc_rqst *rqstp = vrqstp; 130 struct svc_rqst *rqstp = vrqstp;
131 131
132 /* try_to_freeze() is called from svc_recv() */ 132 /* try_to_freeze() is called from svc_recv() */
@@ -165,21 +165,8 @@ lockd(void *vrqstp)
165 * recvfrom routine. 165 * recvfrom routine.
166 */ 166 */
167 err = svc_recv(rqstp, timeout); 167 err = svc_recv(rqstp, timeout);
168 if (err == -EAGAIN || err == -EINTR) { 168 if (err == -EAGAIN || err == -EINTR)
169 preverr = err;
170 continue; 169 continue;
171 }
172 if (err < 0) {
173 if (err != preverr) {
174 printk(KERN_WARNING "%s: unexpected error "
175 "from svc_recv (%d)\n", __func__, err);
176 preverr = err;
177 }
178 schedule_timeout_interruptible(HZ);
179 continue;
180 }
181 preverr = err;
182
183 dprintk("lockd: request from %s\n", 170 dprintk("lockd: request from %s\n",
184 svc_print_addr(rqstp, buf, sizeof(buf))); 171 svc_print_addr(rqstp, buf, sizeof(buf)));
185 172
diff --git a/fs/locks.c b/fs/locks.c
index abc7dc6c490b..a94e331a52a2 100644
--- a/fs/locks.c
+++ b/fs/locks.c
@@ -1289,7 +1289,7 @@ EXPORT_SYMBOL(__break_lease);
1289void lease_get_mtime(struct inode *inode, struct timespec *time) 1289void lease_get_mtime(struct inode *inode, struct timespec *time)
1290{ 1290{
1291 struct file_lock *flock = inode->i_flock; 1291 struct file_lock *flock = inode->i_flock;
1292 if (flock && IS_LEASE(flock) && (flock->fl_type & F_WRLCK)) 1292 if (flock && IS_LEASE(flock) && (flock->fl_type == F_WRLCK))
1293 *time = current_fs_time(inode->i_sb); 1293 *time = current_fs_time(inode->i_sb);
1294 else 1294 else
1295 *time = inode->i_mtime; 1295 *time = inode->i_mtime;
@@ -2185,8 +2185,8 @@ static void lock_get_status(struct seq_file *f, struct file_lock *fl,
2185 } else { 2185 } else {
2186 seq_printf(f, "%s ", 2186 seq_printf(f, "%s ",
2187 (lease_breaking(fl)) 2187 (lease_breaking(fl))
2188 ? (fl->fl_type & F_UNLCK) ? "UNLCK" : "READ " 2188 ? (fl->fl_type == F_UNLCK) ? "UNLCK" : "READ "
2189 : (fl->fl_type & F_WRLCK) ? "WRITE" : "READ "); 2189 : (fl->fl_type == F_WRLCK) ? "WRITE" : "READ ");
2190 } 2190 }
2191 if (inode) { 2191 if (inode) {
2192#ifdef WE_CAN_BREAK_LSLK_NOW 2192#ifdef WE_CAN_BREAK_LSLK_NOW
diff --git a/fs/nfs/callback.c b/fs/nfs/callback.c
index 2245bef50f37..9a521fb39869 100644
--- a/fs/nfs/callback.c
+++ b/fs/nfs/callback.c
@@ -72,7 +72,7 @@ out_err:
72static int 72static int
73nfs4_callback_svc(void *vrqstp) 73nfs4_callback_svc(void *vrqstp)
74{ 74{
75 int err, preverr = 0; 75 int err;
76 struct svc_rqst *rqstp = vrqstp; 76 struct svc_rqst *rqstp = vrqstp;
77 77
78 set_freezable(); 78 set_freezable();
@@ -82,20 +82,8 @@ nfs4_callback_svc(void *vrqstp)
82 * Listen for a request on the socket 82 * Listen for a request on the socket
83 */ 83 */
84 err = svc_recv(rqstp, MAX_SCHEDULE_TIMEOUT); 84 err = svc_recv(rqstp, MAX_SCHEDULE_TIMEOUT);
85 if (err == -EAGAIN || err == -EINTR) { 85 if (err == -EAGAIN || err == -EINTR)
86 preverr = err;
87 continue; 86 continue;
88 }
89 if (err < 0) {
90 if (err != preverr) {
91 printk(KERN_WARNING "NFS: %s: unexpected error "
92 "from svc_recv (%d)\n", __func__, err);
93 preverr = err;
94 }
95 schedule_timeout_uninterruptible(HZ);
96 continue;
97 }
98 preverr = err;
99 svc_process(rqstp); 87 svc_process(rqstp);
100 } 88 }
101 return 0; 89 return 0;
diff --git a/fs/nfsd/nfs2acl.c b/fs/nfsd/nfs2acl.c
index 6aa5590c3679..b314888825d5 100644
--- a/fs/nfsd/nfs2acl.c
+++ b/fs/nfsd/nfs2acl.c
@@ -218,8 +218,7 @@ static int nfsaclsvc_decode_accessargs(struct svc_rqst *rqstp, __be32 *p,
218 * There must be an encoding function for void results so svc_process 218 * There must be an encoding function for void results so svc_process
219 * will work properly. 219 * will work properly.
220 */ 220 */
221int 221static int nfsaclsvc_encode_voidres(struct svc_rqst *rqstp, __be32 *p, void *dummy)
222nfsaclsvc_encode_voidres(struct svc_rqst *rqstp, __be32 *p, void *dummy)
223{ 222{
224 return xdr_ressize_check(rqstp, p); 223 return xdr_ressize_check(rqstp, p);
225} 224}
diff --git a/fs/nfsd/nfs3proc.c b/fs/nfsd/nfs3proc.c
index 9095f3c21df9..97d90d1c8608 100644
--- a/fs/nfsd/nfs3proc.c
+++ b/fs/nfsd/nfs3proc.c
@@ -247,7 +247,7 @@ nfsd3_proc_create(struct svc_rqst *rqstp, struct nfsd3_createargs *argp,
247 /* Now create the file and set attributes */ 247 /* Now create the file and set attributes */
248 nfserr = do_nfsd_create(rqstp, dirfhp, argp->name, argp->len, 248 nfserr = do_nfsd_create(rqstp, dirfhp, argp->name, argp->len,
249 attr, newfhp, 249 attr, newfhp,
250 argp->createmode, argp->verf, NULL, NULL); 250 argp->createmode, (u32 *)argp->verf, NULL, NULL);
251 251
252 RETURN_STATUS(nfserr); 252 RETURN_STATUS(nfserr);
253} 253}
diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c
index 4c7bd35b1876..bdf29c96e4cd 100644
--- a/fs/nfsd/nfs4callback.c
+++ b/fs/nfsd/nfs4callback.c
@@ -1028,7 +1028,6 @@ void nfsd4_cb_recall(struct nfs4_delegation *dp)
1028 cb->cb_msg.rpc_cred = callback_cred; 1028 cb->cb_msg.rpc_cred = callback_cred;
1029 1029
1030 cb->cb_ops = &nfsd4_cb_recall_ops; 1030 cb->cb_ops = &nfsd4_cb_recall_ops;
1031 dp->dl_retries = 1;
1032 1031
1033 INIT_LIST_HEAD(&cb->cb_per_client); 1032 INIT_LIST_HEAD(&cb->cb_per_client);
1034 cb->cb_done = true; 1033 cb->cb_done = true;
diff --git a/fs/nfsd/nfs4idmap.c b/fs/nfsd/nfs4idmap.c
index fdc91a6fc9c4..a1f10c0a6255 100644
--- a/fs/nfsd/nfs4idmap.c
+++ b/fs/nfsd/nfs4idmap.c
@@ -478,7 +478,7 @@ nfsd_idmap_init(struct net *net)
478 goto destroy_idtoname_cache; 478 goto destroy_idtoname_cache;
479 nn->nametoid_cache = cache_create_net(&nametoid_cache_template, net); 479 nn->nametoid_cache = cache_create_net(&nametoid_cache_template, net);
480 if (IS_ERR(nn->nametoid_cache)) { 480 if (IS_ERR(nn->nametoid_cache)) {
481 rv = PTR_ERR(nn->idtoname_cache); 481 rv = PTR_ERR(nn->nametoid_cache);
482 goto unregister_idtoname_cache; 482 goto unregister_idtoname_cache;
483 } 483 }
484 rv = cache_register_net(nn->nametoid_cache, net); 484 rv = cache_register_net(nn->nametoid_cache, net);
@@ -598,7 +598,7 @@ numeric_name_to_id(struct svc_rqst *rqstp, int type, const char *name, u32 namel
598 /* Just to make sure it's null-terminated: */ 598 /* Just to make sure it's null-terminated: */
599 memcpy(buf, name, namelen); 599 memcpy(buf, name, namelen);
600 buf[namelen] = '\0'; 600 buf[namelen] = '\0';
601 ret = kstrtouint(name, 10, id); 601 ret = kstrtouint(buf, 10, id);
602 return ret == 0; 602 return ret == 0;
603} 603}
604 604
diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
index c9c1c0a25417..6c9a4b291dba 100644
--- a/fs/nfsd/nfs4proc.c
+++ b/fs/nfsd/nfs4proc.c
@@ -370,7 +370,7 @@ nfsd4_open(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
370 break; 370 break;
371 case NFS4_OPEN_CLAIM_PREVIOUS: 371 case NFS4_OPEN_CLAIM_PREVIOUS:
372 open->op_openowner->oo_flags |= NFS4_OO_CONFIRMED; 372 open->op_openowner->oo_flags |= NFS4_OO_CONFIRMED;
373 status = nfs4_check_open_reclaim(&open->op_clientid); 373 status = nfs4_check_open_reclaim(&open->op_clientid, cstate->minorversion);
374 if (status) 374 if (status)
375 goto out; 375 goto out;
376 case NFS4_OPEN_CLAIM_FH: 376 case NFS4_OPEN_CLAIM_FH:
@@ -1054,8 +1054,8 @@ struct nfsd4_operation {
1054 char *op_name; 1054 char *op_name;
1055 /* Try to get response size before operation */ 1055 /* Try to get response size before operation */
1056 nfsd4op_rsize op_rsize_bop; 1056 nfsd4op_rsize op_rsize_bop;
1057 stateid_setter op_get_currentstateid; 1057 stateid_getter op_get_currentstateid;
1058 stateid_getter op_set_currentstateid; 1058 stateid_setter op_set_currentstateid;
1059}; 1059};
1060 1060
1061static struct nfsd4_operation nfsd4_ops[]; 1061static struct nfsd4_operation nfsd4_ops[];
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index 48a1bad37334..d0237f872cc4 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -758,7 +758,7 @@ static void nfsd4_put_drc_mem(int slotsize, int num)
758 spin_unlock(&nfsd_drc_lock); 758 spin_unlock(&nfsd_drc_lock);
759} 759}
760 760
761static struct nfsd4_session *alloc_session(int slotsize, int numslots) 761static struct nfsd4_session *__alloc_session(int slotsize, int numslots)
762{ 762{
763 struct nfsd4_session *new; 763 struct nfsd4_session *new;
764 int mem, i; 764 int mem, i;
@@ -852,35 +852,28 @@ static int nfsd4_register_conn(struct nfsd4_conn *conn)
852 return register_xpt_user(conn->cn_xprt, &conn->cn_xpt_user); 852 return register_xpt_user(conn->cn_xprt, &conn->cn_xpt_user);
853} 853}
854 854
855static __be32 nfsd4_new_conn(struct svc_rqst *rqstp, struct nfsd4_session *ses, u32 dir) 855static void nfsd4_init_conn(struct svc_rqst *rqstp, struct nfsd4_conn *conn, struct nfsd4_session *ses)
856{ 856{
857 struct nfsd4_conn *conn;
858 int ret; 857 int ret;
859 858
860 conn = alloc_conn(rqstp, dir);
861 if (!conn)
862 return nfserr_jukebox;
863 nfsd4_hash_conn(conn, ses); 859 nfsd4_hash_conn(conn, ses);
864 ret = nfsd4_register_conn(conn); 860 ret = nfsd4_register_conn(conn);
865 if (ret) 861 if (ret)
866 /* oops; xprt is already down: */ 862 /* oops; xprt is already down: */
867 nfsd4_conn_lost(&conn->cn_xpt_user); 863 nfsd4_conn_lost(&conn->cn_xpt_user);
868 if (ses->se_client->cl_cb_state == NFSD4_CB_DOWN && 864 if (conn->cn_flags & NFS4_CDFC4_BACK) {
869 dir & NFS4_CDFC4_BACK) {
870 /* callback channel may be back up */ 865 /* callback channel may be back up */
871 nfsd4_probe_callback(ses->se_client); 866 nfsd4_probe_callback(ses->se_client);
872 } 867 }
873 return nfs_ok;
874} 868}
875 869
876static __be32 nfsd4_new_conn_from_crses(struct svc_rqst *rqstp, struct nfsd4_session *ses) 870static struct nfsd4_conn *alloc_conn_from_crses(struct svc_rqst *rqstp, struct nfsd4_create_session *cses)
877{ 871{
878 u32 dir = NFS4_CDFC4_FORE; 872 u32 dir = NFS4_CDFC4_FORE;
879 873
880 if (ses->se_flags & SESSION4_BACK_CHAN) 874 if (cses->flags & SESSION4_BACK_CHAN)
881 dir |= NFS4_CDFC4_BACK; 875 dir |= NFS4_CDFC4_BACK;
882 876 return alloc_conn(rqstp, dir);
883 return nfsd4_new_conn(rqstp, ses, dir);
884} 877}
885 878
886/* must be called under client_lock */ 879/* must be called under client_lock */
@@ -903,20 +896,21 @@ static void nfsd4_del_conns(struct nfsd4_session *s)
903 spin_unlock(&clp->cl_lock); 896 spin_unlock(&clp->cl_lock);
904} 897}
905 898
899static void __free_session(struct nfsd4_session *ses)
900{
901 nfsd4_put_drc_mem(slot_bytes(&ses->se_fchannel), ses->se_fchannel.maxreqs);
902 free_session_slots(ses);
903 kfree(ses);
904}
905
906static void free_session(struct kref *kref) 906static void free_session(struct kref *kref)
907{ 907{
908 struct nfsd4_session *ses; 908 struct nfsd4_session *ses;
909 int mem;
910 909
911 lockdep_assert_held(&client_lock); 910 lockdep_assert_held(&client_lock);
912 ses = container_of(kref, struct nfsd4_session, se_ref); 911 ses = container_of(kref, struct nfsd4_session, se_ref);
913 nfsd4_del_conns(ses); 912 nfsd4_del_conns(ses);
914 spin_lock(&nfsd_drc_lock); 913 __free_session(ses);
915 mem = ses->se_fchannel.maxreqs * slot_bytes(&ses->se_fchannel);
916 nfsd_drc_mem_used -= mem;
917 spin_unlock(&nfsd_drc_lock);
918 free_session_slots(ses);
919 kfree(ses);
920} 914}
921 915
922void nfsd4_put_session(struct nfsd4_session *ses) 916void nfsd4_put_session(struct nfsd4_session *ses)
@@ -926,14 +920,10 @@ void nfsd4_put_session(struct nfsd4_session *ses)
926 spin_unlock(&client_lock); 920 spin_unlock(&client_lock);
927} 921}
928 922
929static struct nfsd4_session *alloc_init_session(struct svc_rqst *rqstp, struct nfs4_client *clp, struct nfsd4_create_session *cses) 923static struct nfsd4_session *alloc_session(struct nfsd4_channel_attrs *fchan)
930{ 924{
931 struct nfsd4_session *new; 925 struct nfsd4_session *new;
932 struct nfsd4_channel_attrs *fchan = &cses->fore_channel;
933 int numslots, slotsize; 926 int numslots, slotsize;
934 __be32 status;
935 int idx;
936
937 /* 927 /*
938 * Note decreasing slot size below client's request may 928 * Note decreasing slot size below client's request may
939 * make it difficult for client to function correctly, whereas 929 * make it difficult for client to function correctly, whereas
@@ -946,12 +936,18 @@ static struct nfsd4_session *alloc_init_session(struct svc_rqst *rqstp, struct n
946 if (numslots < 1) 936 if (numslots < 1)
947 return NULL; 937 return NULL;
948 938
949 new = alloc_session(slotsize, numslots); 939 new = __alloc_session(slotsize, numslots);
950 if (!new) { 940 if (!new) {
951 nfsd4_put_drc_mem(slotsize, fchan->maxreqs); 941 nfsd4_put_drc_mem(slotsize, fchan->maxreqs);
952 return NULL; 942 return NULL;
953 } 943 }
954 init_forechannel_attrs(&new->se_fchannel, fchan, numslots, slotsize); 944 init_forechannel_attrs(&new->se_fchannel, fchan, numslots, slotsize);
945 return new;
946}
947
948static struct nfsd4_session *init_session(struct svc_rqst *rqstp, struct nfsd4_session *new, struct nfs4_client *clp, struct nfsd4_create_session *cses)
949{
950 int idx;
955 951
956 new->se_client = clp; 952 new->se_client = clp;
957 gen_sessionid(new); 953 gen_sessionid(new);
@@ -970,14 +966,6 @@ static struct nfsd4_session *alloc_init_session(struct svc_rqst *rqstp, struct n
970 spin_unlock(&clp->cl_lock); 966 spin_unlock(&clp->cl_lock);
971 spin_unlock(&client_lock); 967 spin_unlock(&client_lock);
972 968
973 status = nfsd4_new_conn_from_crses(rqstp, new);
974 /* whoops: benny points out, status is ignored! (err, or bogus) */
975 if (status) {
976 spin_lock(&client_lock);
977 free_session(&new->se_ref);
978 spin_unlock(&client_lock);
979 return NULL;
980 }
981 if (cses->flags & SESSION4_BACK_CHAN) { 969 if (cses->flags & SESSION4_BACK_CHAN) {
982 struct sockaddr *sa = svc_addr(rqstp); 970 struct sockaddr *sa = svc_addr(rqstp);
983 /* 971 /*
@@ -990,7 +978,6 @@ static struct nfsd4_session *alloc_init_session(struct svc_rqst *rqstp, struct n
990 rpc_copy_addr((struct sockaddr *)&clp->cl_cb_conn.cb_addr, sa); 978 rpc_copy_addr((struct sockaddr *)&clp->cl_cb_conn.cb_addr, sa);
991 clp->cl_cb_conn.cb_addrlen = svc_addr_len(sa); 979 clp->cl_cb_conn.cb_addrlen = svc_addr_len(sa);
992 } 980 }
993 nfsd4_probe_callback(clp);
994 return new; 981 return new;
995} 982}
996 983
@@ -1131,7 +1118,7 @@ unhash_client_locked(struct nfs4_client *clp)
1131} 1118}
1132 1119
1133static void 1120static void
1134expire_client(struct nfs4_client *clp) 1121destroy_client(struct nfs4_client *clp)
1135{ 1122{
1136 struct nfs4_openowner *oo; 1123 struct nfs4_openowner *oo;
1137 struct nfs4_delegation *dp; 1124 struct nfs4_delegation *dp;
@@ -1165,6 +1152,12 @@ expire_client(struct nfs4_client *clp)
1165 spin_unlock(&client_lock); 1152 spin_unlock(&client_lock);
1166} 1153}
1167 1154
1155static void expire_client(struct nfs4_client *clp)
1156{
1157 nfsd4_client_record_remove(clp);
1158 destroy_client(clp);
1159}
1160
1168static void copy_verf(struct nfs4_client *target, nfs4_verifier *source) 1161static void copy_verf(struct nfs4_client *target, nfs4_verifier *source)
1169{ 1162{
1170 memcpy(target->cl_verifier.data, source->data, 1163 memcpy(target->cl_verifier.data, source->data,
@@ -1223,10 +1216,26 @@ static bool groups_equal(struct group_info *g1, struct group_info *g2)
1223 return true; 1216 return true;
1224} 1217}
1225 1218
1219/*
1220 * RFC 3530 language requires clid_inuse be returned when the
1221 * "principal" associated with a requests differs from that previously
1222 * used. We use uid, gid's, and gss principal string as our best
1223 * approximation. We also don't want to allow non-gss use of a client
1224 * established using gss: in theory cr_principal should catch that
1225 * change, but in practice cr_principal can be null even in the gss case
1226 * since gssd doesn't always pass down a principal string.
1227 */
1228static bool is_gss_cred(struct svc_cred *cr)
1229{
1230 /* Is cr_flavor one of the gss "pseudoflavors"?: */
1231 return (cr->cr_flavor > RPC_AUTH_MAXFLAVOR);
1232}
1233
1234
1226static bool 1235static bool
1227same_creds(struct svc_cred *cr1, struct svc_cred *cr2) 1236same_creds(struct svc_cred *cr1, struct svc_cred *cr2)
1228{ 1237{
1229 if ((cr1->cr_flavor != cr2->cr_flavor) 1238 if ((is_gss_cred(cr1) != is_gss_cred(cr2))
1230 || (cr1->cr_uid != cr2->cr_uid) 1239 || (cr1->cr_uid != cr2->cr_uid)
1231 || (cr1->cr_gid != cr2->cr_gid) 1240 || (cr1->cr_gid != cr2->cr_gid)
1232 || !groups_equal(cr1->cr_group_info, cr2->cr_group_info)) 1241 || !groups_equal(cr1->cr_group_info, cr2->cr_group_info))
@@ -1340,13 +1349,15 @@ move_to_confirmed(struct nfs4_client *clp)
1340} 1349}
1341 1350
1342static struct nfs4_client * 1351static struct nfs4_client *
1343find_confirmed_client(clientid_t *clid) 1352find_confirmed_client(clientid_t *clid, bool sessions)
1344{ 1353{
1345 struct nfs4_client *clp; 1354 struct nfs4_client *clp;
1346 unsigned int idhashval = clientid_hashval(clid->cl_id); 1355 unsigned int idhashval = clientid_hashval(clid->cl_id);
1347 1356
1348 list_for_each_entry(clp, &conf_id_hashtbl[idhashval], cl_idhash) { 1357 list_for_each_entry(clp, &conf_id_hashtbl[idhashval], cl_idhash) {
1349 if (same_clid(&clp->cl_clientid, clid)) { 1358 if (same_clid(&clp->cl_clientid, clid)) {
1359 if ((bool)clp->cl_minorversion != sessions)
1360 return NULL;
1350 renew_client(clp); 1361 renew_client(clp);
1351 return clp; 1362 return clp;
1352 } 1363 }
@@ -1355,14 +1366,17 @@ find_confirmed_client(clientid_t *clid)
1355} 1366}
1356 1367
1357static struct nfs4_client * 1368static struct nfs4_client *
1358find_unconfirmed_client(clientid_t *clid) 1369find_unconfirmed_client(clientid_t *clid, bool sessions)
1359{ 1370{
1360 struct nfs4_client *clp; 1371 struct nfs4_client *clp;
1361 unsigned int idhashval = clientid_hashval(clid->cl_id); 1372 unsigned int idhashval = clientid_hashval(clid->cl_id);
1362 1373
1363 list_for_each_entry(clp, &unconf_id_hashtbl[idhashval], cl_idhash) { 1374 list_for_each_entry(clp, &unconf_id_hashtbl[idhashval], cl_idhash) {
1364 if (same_clid(&clp->cl_clientid, clid)) 1375 if (same_clid(&clp->cl_clientid, clid)) {
1376 if ((bool)clp->cl_minorversion != sessions)
1377 return NULL;
1365 return clp; 1378 return clp;
1379 }
1366 } 1380 }
1367 return NULL; 1381 return NULL;
1368} 1382}
@@ -1651,6 +1665,7 @@ out_new:
1651 status = nfserr_jukebox; 1665 status = nfserr_jukebox;
1652 goto out; 1666 goto out;
1653 } 1667 }
1668 new->cl_minorversion = 1;
1654 1669
1655 gen_clid(new); 1670 gen_clid(new);
1656 add_to_unconfirmed(new, strhashval); 1671 add_to_unconfirmed(new, strhashval);
@@ -1743,67 +1758,71 @@ nfsd4_create_session(struct svc_rqst *rqstp,
1743 struct sockaddr *sa = svc_addr(rqstp); 1758 struct sockaddr *sa = svc_addr(rqstp);
1744 struct nfs4_client *conf, *unconf; 1759 struct nfs4_client *conf, *unconf;
1745 struct nfsd4_session *new; 1760 struct nfsd4_session *new;
1761 struct nfsd4_conn *conn;
1746 struct nfsd4_clid_slot *cs_slot = NULL; 1762 struct nfsd4_clid_slot *cs_slot = NULL;
1747 bool confirm_me = false;
1748 __be32 status = 0; 1763 __be32 status = 0;
1749 1764
1750 if (cr_ses->flags & ~SESSION4_FLAG_MASK_A) 1765 if (cr_ses->flags & ~SESSION4_FLAG_MASK_A)
1751 return nfserr_inval; 1766 return nfserr_inval;
1767 if (check_forechannel_attrs(cr_ses->fore_channel))
1768 return nfserr_toosmall;
1769 new = alloc_session(&cr_ses->fore_channel);
1770 if (!new)
1771 return nfserr_jukebox;
1772 status = nfserr_jukebox;
1773 conn = alloc_conn_from_crses(rqstp, cr_ses);
1774 if (!conn)
1775 goto out_free_session;
1752 1776
1753 nfs4_lock_state(); 1777 nfs4_lock_state();
1754 unconf = find_unconfirmed_client(&cr_ses->clientid); 1778 unconf = find_unconfirmed_client(&cr_ses->clientid, true);
1755 conf = find_confirmed_client(&cr_ses->clientid); 1779 conf = find_confirmed_client(&cr_ses->clientid, true);
1756 1780
1757 if (conf) { 1781 if (conf) {
1758 cs_slot = &conf->cl_cs_slot; 1782 cs_slot = &conf->cl_cs_slot;
1759 status = check_slot_seqid(cr_ses->seqid, cs_slot->sl_seqid, 0); 1783 status = check_slot_seqid(cr_ses->seqid, cs_slot->sl_seqid, 0);
1760 if (status == nfserr_replay_cache) { 1784 if (status == nfserr_replay_cache) {
1761 status = nfsd4_replay_create_session(cr_ses, cs_slot); 1785 status = nfsd4_replay_create_session(cr_ses, cs_slot);
1762 goto out; 1786 goto out_free_conn;
1763 } else if (cr_ses->seqid != cs_slot->sl_seqid + 1) { 1787 } else if (cr_ses->seqid != cs_slot->sl_seqid + 1) {
1764 status = nfserr_seq_misordered; 1788 status = nfserr_seq_misordered;
1765 goto out; 1789 goto out_free_conn;
1766 } 1790 }
1767 } else if (unconf) { 1791 } else if (unconf) {
1792 unsigned int hash;
1793 struct nfs4_client *old;
1768 if (!same_creds(&unconf->cl_cred, &rqstp->rq_cred) || 1794 if (!same_creds(&unconf->cl_cred, &rqstp->rq_cred) ||
1769 !rpc_cmp_addr(sa, (struct sockaddr *) &unconf->cl_addr)) { 1795 !rpc_cmp_addr(sa, (struct sockaddr *) &unconf->cl_addr)) {
1770 status = nfserr_clid_inuse; 1796 status = nfserr_clid_inuse;
1771 goto out; 1797 goto out_free_conn;
1772 } 1798 }
1773 cs_slot = &unconf->cl_cs_slot; 1799 cs_slot = &unconf->cl_cs_slot;
1774 status = check_slot_seqid(cr_ses->seqid, cs_slot->sl_seqid, 0); 1800 status = check_slot_seqid(cr_ses->seqid, cs_slot->sl_seqid, 0);
1775 if (status) { 1801 if (status) {
1776 /* an unconfirmed replay returns misordered */ 1802 /* an unconfirmed replay returns misordered */
1777 status = nfserr_seq_misordered; 1803 status = nfserr_seq_misordered;
1778 goto out; 1804 goto out_free_conn;
1779 } 1805 }
1780 confirm_me = true; 1806 hash = clientstr_hashval(unconf->cl_recdir);
1807 old = find_confirmed_client_by_str(unconf->cl_recdir, hash);
1808 if (old)
1809 expire_client(old);
1810 move_to_confirmed(unconf);
1781 conf = unconf; 1811 conf = unconf;
1782 } else { 1812 } else {
1783 status = nfserr_stale_clientid; 1813 status = nfserr_stale_clientid;
1784 goto out; 1814 goto out_free_conn;
1785 } 1815 }
1786 1816 status = nfs_ok;
1787 /*
1788 * XXX: we should probably set this at creation time, and check
1789 * for consistent minorversion use throughout:
1790 */
1791 conf->cl_minorversion = 1;
1792 /* 1817 /*
1793 * We do not support RDMA or persistent sessions 1818 * We do not support RDMA or persistent sessions
1794 */ 1819 */
1795 cr_ses->flags &= ~SESSION4_PERSIST; 1820 cr_ses->flags &= ~SESSION4_PERSIST;
1796 cr_ses->flags &= ~SESSION4_RDMA; 1821 cr_ses->flags &= ~SESSION4_RDMA;
1797 1822
1798 status = nfserr_toosmall; 1823 init_session(rqstp, new, conf, cr_ses);
1799 if (check_forechannel_attrs(cr_ses->fore_channel)) 1824 nfsd4_init_conn(rqstp, conn, new);
1800 goto out;
1801 1825
1802 status = nfserr_jukebox;
1803 new = alloc_init_session(rqstp, conf, cr_ses);
1804 if (!new)
1805 goto out;
1806 status = nfs_ok;
1807 memcpy(cr_ses->sessionid.data, new->se_sessionid.data, 1826 memcpy(cr_ses->sessionid.data, new->se_sessionid.data,
1808 NFS4_MAX_SESSIONID_LEN); 1827 NFS4_MAX_SESSIONID_LEN);
1809 memcpy(&cr_ses->fore_channel, &new->se_fchannel, 1828 memcpy(&cr_ses->fore_channel, &new->se_fchannel,
@@ -1813,18 +1832,15 @@ nfsd4_create_session(struct svc_rqst *rqstp,
1813 1832
1814 /* cache solo and embedded create sessions under the state lock */ 1833 /* cache solo and embedded create sessions under the state lock */
1815 nfsd4_cache_create_session(cr_ses, cs_slot, status); 1834 nfsd4_cache_create_session(cr_ses, cs_slot, status);
1816 if (confirm_me) {
1817 unsigned int hash = clientstr_hashval(unconf->cl_recdir);
1818 struct nfs4_client *old =
1819 find_confirmed_client_by_str(conf->cl_recdir, hash);
1820 if (old)
1821 expire_client(old);
1822 move_to_confirmed(conf);
1823 }
1824out: 1835out:
1825 nfs4_unlock_state(); 1836 nfs4_unlock_state();
1826 dprintk("%s returns %d\n", __func__, ntohl(status)); 1837 dprintk("%s returns %d\n", __func__, ntohl(status));
1827 return status; 1838 return status;
1839out_free_conn:
1840 free_conn(conn);
1841out_free_session:
1842 __free_session(new);
1843 goto out;
1828} 1844}
1829 1845
1830static bool nfsd4_last_compound_op(struct svc_rqst *rqstp) 1846static bool nfsd4_last_compound_op(struct svc_rqst *rqstp)
@@ -1854,6 +1870,7 @@ __be32 nfsd4_bind_conn_to_session(struct svc_rqst *rqstp,
1854 struct nfsd4_bind_conn_to_session *bcts) 1870 struct nfsd4_bind_conn_to_session *bcts)
1855{ 1871{
1856 __be32 status; 1872 __be32 status;
1873 struct nfsd4_conn *conn;
1857 1874
1858 if (!nfsd4_last_compound_op(rqstp)) 1875 if (!nfsd4_last_compound_op(rqstp))
1859 return nfserr_not_only_op; 1876 return nfserr_not_only_op;
@@ -1870,9 +1887,13 @@ __be32 nfsd4_bind_conn_to_session(struct svc_rqst *rqstp,
1870 return nfserr_badsession; 1887 return nfserr_badsession;
1871 1888
1872 status = nfsd4_map_bcts_dir(&bcts->dir); 1889 status = nfsd4_map_bcts_dir(&bcts->dir);
1873 if (!status) 1890 if (status)
1874 nfsd4_new_conn(rqstp, cstate->session, bcts->dir); 1891 return status;
1875 return status; 1892 conn = alloc_conn(rqstp, bcts->dir);
1893 if (!conn)
1894 return nfserr_jukebox;
1895 nfsd4_init_conn(rqstp, conn, cstate->session);
1896 return nfs_ok;
1876} 1897}
1877 1898
1878static bool nfsd4_compound_in_session(struct nfsd4_session *session, struct nfs4_sessionid *sid) 1899static bool nfsd4_compound_in_session(struct nfsd4_session *session, struct nfs4_sessionid *sid)
@@ -2085,8 +2106,8 @@ nfsd4_destroy_clientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *csta
2085 __be32 status = 0; 2106 __be32 status = 0;
2086 2107
2087 nfs4_lock_state(); 2108 nfs4_lock_state();
2088 unconf = find_unconfirmed_client(&dc->clientid); 2109 unconf = find_unconfirmed_client(&dc->clientid, true);
2089 conf = find_confirmed_client(&dc->clientid); 2110 conf = find_confirmed_client(&dc->clientid, true);
2090 2111
2091 if (conf) { 2112 if (conf) {
2092 clp = conf; 2113 clp = conf;
@@ -2200,10 +2221,6 @@ nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
2200 copy_clid(new, conf); 2221 copy_clid(new, conf);
2201 else /* case 4 (new client) or cases 2, 3 (client reboot): */ 2222 else /* case 4 (new client) or cases 2, 3 (client reboot): */
2202 gen_clid(new); 2223 gen_clid(new);
2203 /*
2204 * XXX: we should probably set this at creation time, and check
2205 * for consistent minorversion use throughout:
2206 */
2207 new->cl_minorversion = 0; 2224 new->cl_minorversion = 0;
2208 gen_callback(new, setclid, rqstp); 2225 gen_callback(new, setclid, rqstp);
2209 add_to_unconfirmed(new, strhashval); 2226 add_to_unconfirmed(new, strhashval);
@@ -2232,8 +2249,8 @@ nfsd4_setclientid_confirm(struct svc_rqst *rqstp,
2232 return nfserr_stale_clientid; 2249 return nfserr_stale_clientid;
2233 nfs4_lock_state(); 2250 nfs4_lock_state();
2234 2251
2235 conf = find_confirmed_client(clid); 2252 conf = find_confirmed_client(clid, false);
2236 unconf = find_unconfirmed_client(clid); 2253 unconf = find_unconfirmed_client(clid, false);
2237 /* 2254 /*
2238 * We try hard to give out unique clientid's, so if we get an 2255 * We try hard to give out unique clientid's, so if we get an
2239 * attempt to confirm the same clientid with a different cred, 2256 * attempt to confirm the same clientid with a different cred,
@@ -2262,10 +2279,8 @@ nfsd4_setclientid_confirm(struct svc_rqst *rqstp,
2262 unsigned int hash = clientstr_hashval(unconf->cl_recdir); 2279 unsigned int hash = clientstr_hashval(unconf->cl_recdir);
2263 2280
2264 conf = find_confirmed_client_by_str(unconf->cl_recdir, hash); 2281 conf = find_confirmed_client_by_str(unconf->cl_recdir, hash);
2265 if (conf) { 2282 if (conf)
2266 nfsd4_client_record_remove(conf);
2267 expire_client(conf); 2283 expire_client(conf);
2268 }
2269 move_to_confirmed(unconf); 2284 move_to_confirmed(unconf);
2270 nfsd4_probe_callback(unconf); 2285 nfsd4_probe_callback(unconf);
2271 } 2286 }
@@ -2447,16 +2462,20 @@ same_owner_str(struct nfs4_stateowner *sop, struct xdr_netobj *owner,
2447} 2462}
2448 2463
2449static struct nfs4_openowner * 2464static struct nfs4_openowner *
2450find_openstateowner_str(unsigned int hashval, struct nfsd4_open *open) 2465find_openstateowner_str(unsigned int hashval, struct nfsd4_open *open, bool sessions)
2451{ 2466{
2452 struct nfs4_stateowner *so; 2467 struct nfs4_stateowner *so;
2453 struct nfs4_openowner *oo; 2468 struct nfs4_openowner *oo;
2469 struct nfs4_client *clp;
2454 2470
2455 list_for_each_entry(so, &ownerstr_hashtbl[hashval], so_strhash) { 2471 list_for_each_entry(so, &ownerstr_hashtbl[hashval], so_strhash) {
2456 if (!so->so_is_open_owner) 2472 if (!so->so_is_open_owner)
2457 continue; 2473 continue;
2458 if (same_owner_str(so, &open->op_owner, &open->op_clientid)) { 2474 if (same_owner_str(so, &open->op_owner, &open->op_clientid)) {
2459 oo = openowner(so); 2475 oo = openowner(so);
2476 clp = oo->oo_owner.so_client;
2477 if ((bool)clp->cl_minorversion != sessions)
2478 return NULL;
2460 renew_client(oo->oo_owner.so_client); 2479 renew_client(oo->oo_owner.so_client);
2461 return oo; 2480 return oo;
2462 } 2481 }
@@ -2600,10 +2619,10 @@ nfsd4_process_open1(struct nfsd4_compound_state *cstate,
2600 return nfserr_jukebox; 2619 return nfserr_jukebox;
2601 2620
2602 strhashval = ownerstr_hashval(clientid->cl_id, &open->op_owner); 2621 strhashval = ownerstr_hashval(clientid->cl_id, &open->op_owner);
2603 oo = find_openstateowner_str(strhashval, open); 2622 oo = find_openstateowner_str(strhashval, open, cstate->minorversion);
2604 open->op_openowner = oo; 2623 open->op_openowner = oo;
2605 if (!oo) { 2624 if (!oo) {
2606 clp = find_confirmed_client(clientid); 2625 clp = find_confirmed_client(clientid, cstate->minorversion);
2607 if (clp == NULL) 2626 if (clp == NULL)
2608 return nfserr_expired; 2627 return nfserr_expired;
2609 goto new_owner; 2628 goto new_owner;
@@ -2705,11 +2724,6 @@ nfs4_check_open(struct nfs4_file *fp, struct nfsd4_open *open, struct nfs4_ol_st
2705 return nfs_ok; 2724 return nfs_ok;
2706} 2725}
2707 2726
2708static void nfs4_free_stateid(struct nfs4_ol_stateid *s)
2709{
2710 kmem_cache_free(stateid_slab, s);
2711}
2712
2713static inline int nfs4_access_to_access(u32 nfs4_access) 2727static inline int nfs4_access_to_access(u32 nfs4_access)
2714{ 2728{
2715 int flags = 0; 2729 int flags = 0;
@@ -3087,7 +3101,7 @@ void nfsd4_cleanup_open_state(struct nfsd4_open *open, __be32 status)
3087 if (open->op_file) 3101 if (open->op_file)
3088 nfsd4_free_file(open->op_file); 3102 nfsd4_free_file(open->op_file);
3089 if (open->op_stp) 3103 if (open->op_stp)
3090 nfs4_free_stateid(open->op_stp); 3104 free_generic_stateid(open->op_stp);
3091} 3105}
3092 3106
3093__be32 3107__be32
@@ -3104,7 +3118,7 @@ nfsd4_renew(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
3104 status = nfserr_stale_clientid; 3118 status = nfserr_stale_clientid;
3105 if (STALE_CLIENTID(clid, nn)) 3119 if (STALE_CLIENTID(clid, nn))
3106 goto out; 3120 goto out;
3107 clp = find_confirmed_client(clid); 3121 clp = find_confirmed_client(clid, cstate->minorversion);
3108 status = nfserr_expired; 3122 status = nfserr_expired;
3109 if (clp == NULL) { 3123 if (clp == NULL) {
3110 /* We assume the client took too long to RENEW. */ 3124 /* We assume the client took too long to RENEW. */
@@ -3180,7 +3194,6 @@ nfs4_laundromat(void)
3180 clp = list_entry(pos, struct nfs4_client, cl_lru); 3194 clp = list_entry(pos, struct nfs4_client, cl_lru);
3181 dprintk("NFSD: purging unused client (clientid %08x)\n", 3195 dprintk("NFSD: purging unused client (clientid %08x)\n",
3182 clp->cl_clientid.cl_id); 3196 clp->cl_clientid.cl_id);
3183 nfsd4_client_record_remove(clp);
3184 expire_client(clp); 3197 expire_client(clp);
3185 } 3198 }
3186 spin_lock(&recall_lock); 3199 spin_lock(&recall_lock);
@@ -3372,7 +3385,7 @@ static __be32 nfsd4_validate_stateid(struct nfs4_client *cl, stateid_t *stateid)
3372 return nfs_ok; 3385 return nfs_ok;
3373} 3386}
3374 3387
3375static __be32 nfsd4_lookup_stateid(stateid_t *stateid, unsigned char typemask, struct nfs4_stid **s) 3388static __be32 nfsd4_lookup_stateid(stateid_t *stateid, unsigned char typemask, struct nfs4_stid **s, bool sessions)
3376{ 3389{
3377 struct nfs4_client *cl; 3390 struct nfs4_client *cl;
3378 struct nfsd_net *nn = net_generic(&init_net, nfsd_net_id); 3391 struct nfsd_net *nn = net_generic(&init_net, nfsd_net_id);
@@ -3381,7 +3394,7 @@ static __be32 nfsd4_lookup_stateid(stateid_t *stateid, unsigned char typemask, s
3381 return nfserr_bad_stateid; 3394 return nfserr_bad_stateid;
3382 if (STALE_STATEID(stateid, nn)) 3395 if (STALE_STATEID(stateid, nn))
3383 return nfserr_stale_stateid; 3396 return nfserr_stale_stateid;
3384 cl = find_confirmed_client(&stateid->si_opaque.so_clid); 3397 cl = find_confirmed_client(&stateid->si_opaque.so_clid, sessions);
3385 if (!cl) 3398 if (!cl)
3386 return nfserr_expired; 3399 return nfserr_expired;
3387 *s = find_stateid_by_type(cl, stateid, typemask); 3400 *s = find_stateid_by_type(cl, stateid, typemask);
@@ -3414,7 +3427,7 @@ nfs4_preprocess_stateid_op(struct net *net, struct nfsd4_compound_state *cstate,
3414 if (ZERO_STATEID(stateid) || ONE_STATEID(stateid)) 3427 if (ZERO_STATEID(stateid) || ONE_STATEID(stateid))
3415 return check_special_stateids(net, current_fh, stateid, flags); 3428 return check_special_stateids(net, current_fh, stateid, flags);
3416 3429
3417 status = nfsd4_lookup_stateid(stateid, NFS4_DELEG_STID|NFS4_OPEN_STID|NFS4_LOCK_STID, &s); 3430 status = nfsd4_lookup_stateid(stateid, NFS4_DELEG_STID|NFS4_OPEN_STID|NFS4_LOCK_STID, &s, cstate->minorversion);
3418 if (status) 3431 if (status)
3419 return status; 3432 return status;
3420 status = check_stateid_generation(stateid, &s->sc_stateid, nfsd4_has_session(cstate)); 3433 status = check_stateid_generation(stateid, &s->sc_stateid, nfsd4_has_session(cstate));
@@ -3564,7 +3577,7 @@ nfs4_preprocess_seqid_op(struct nfsd4_compound_state *cstate, u32 seqid,
3564 seqid, STATEID_VAL(stateid)); 3577 seqid, STATEID_VAL(stateid));
3565 3578
3566 *stpp = NULL; 3579 *stpp = NULL;
3567 status = nfsd4_lookup_stateid(stateid, typemask, &s); 3580 status = nfsd4_lookup_stateid(stateid, typemask, &s, cstate->minorversion);
3568 if (status) 3581 if (status)
3569 return status; 3582 return status;
3570 *stpp = openlockstateid(s); 3583 *stpp = openlockstateid(s);
@@ -3765,6 +3778,7 @@ nfsd4_close(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
3765 memcpy(&close->cl_stateid, &stp->st_stid.sc_stateid, sizeof(stateid_t)); 3778 memcpy(&close->cl_stateid, &stp->st_stid.sc_stateid, sizeof(stateid_t));
3766 3779
3767 nfsd4_close_open_stateid(stp); 3780 nfsd4_close_open_stateid(stp);
3781 release_last_closed_stateid(oo);
3768 oo->oo_last_closed_stid = stp; 3782 oo->oo_last_closed_stid = stp;
3769 3783
3770 if (list_empty(&oo->oo_owner.so_stateids)) { 3784 if (list_empty(&oo->oo_owner.so_stateids)) {
@@ -3801,7 +3815,7 @@ nfsd4_delegreturn(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
3801 inode = cstate->current_fh.fh_dentry->d_inode; 3815 inode = cstate->current_fh.fh_dentry->d_inode;
3802 3816
3803 nfs4_lock_state(); 3817 nfs4_lock_state();
3804 status = nfsd4_lookup_stateid(stateid, NFS4_DELEG_STID, &s); 3818 status = nfsd4_lookup_stateid(stateid, NFS4_DELEG_STID, &s, cstate->minorversion);
3805 if (status) 3819 if (status)
3806 goto out; 3820 goto out;
3807 dp = delegstateid(s); 3821 dp = delegstateid(s);
@@ -4045,8 +4059,8 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
4045 struct nfs4_lockowner *lock_sop = NULL; 4059 struct nfs4_lockowner *lock_sop = NULL;
4046 struct nfs4_ol_stateid *lock_stp; 4060 struct nfs4_ol_stateid *lock_stp;
4047 struct file *filp = NULL; 4061 struct file *filp = NULL;
4048 struct file_lock file_lock; 4062 struct file_lock *file_lock = NULL;
4049 struct file_lock conflock; 4063 struct file_lock *conflock = NULL;
4050 __be32 status = 0; 4064 __be32 status = 0;
4051 bool new_state = false; 4065 bool new_state = false;
4052 int lkflg; 4066 int lkflg;
@@ -4116,21 +4130,28 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
4116 if (!locks_in_grace(SVC_NET(rqstp)) && lock->lk_reclaim) 4130 if (!locks_in_grace(SVC_NET(rqstp)) && lock->lk_reclaim)
4117 goto out; 4131 goto out;
4118 4132
4119 locks_init_lock(&file_lock); 4133 file_lock = locks_alloc_lock();
4134 if (!file_lock) {
4135 dprintk("NFSD: %s: unable to allocate lock!\n", __func__);
4136 status = nfserr_jukebox;
4137 goto out;
4138 }
4139
4140 locks_init_lock(file_lock);
4120 switch (lock->lk_type) { 4141 switch (lock->lk_type) {
4121 case NFS4_READ_LT: 4142 case NFS4_READ_LT:
4122 case NFS4_READW_LT: 4143 case NFS4_READW_LT:
4123 filp = find_readable_file(lock_stp->st_file); 4144 filp = find_readable_file(lock_stp->st_file);
4124 if (filp) 4145 if (filp)
4125 get_lock_access(lock_stp, NFS4_SHARE_ACCESS_READ); 4146 get_lock_access(lock_stp, NFS4_SHARE_ACCESS_READ);
4126 file_lock.fl_type = F_RDLCK; 4147 file_lock->fl_type = F_RDLCK;
4127 break; 4148 break;
4128 case NFS4_WRITE_LT: 4149 case NFS4_WRITE_LT:
4129 case NFS4_WRITEW_LT: 4150 case NFS4_WRITEW_LT:
4130 filp = find_writeable_file(lock_stp->st_file); 4151 filp = find_writeable_file(lock_stp->st_file);
4131 if (filp) 4152 if (filp)
4132 get_lock_access(lock_stp, NFS4_SHARE_ACCESS_WRITE); 4153 get_lock_access(lock_stp, NFS4_SHARE_ACCESS_WRITE);
4133 file_lock.fl_type = F_WRLCK; 4154 file_lock->fl_type = F_WRLCK;
4134 break; 4155 break;
4135 default: 4156 default:
4136 status = nfserr_inval; 4157 status = nfserr_inval;
@@ -4140,22 +4161,23 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
4140 status = nfserr_openmode; 4161 status = nfserr_openmode;
4141 goto out; 4162 goto out;
4142 } 4163 }
4143 file_lock.fl_owner = (fl_owner_t)lock_sop; 4164 file_lock->fl_owner = (fl_owner_t)lock_sop;
4144 file_lock.fl_pid = current->tgid; 4165 file_lock->fl_pid = current->tgid;
4145 file_lock.fl_file = filp; 4166 file_lock->fl_file = filp;
4146 file_lock.fl_flags = FL_POSIX; 4167 file_lock->fl_flags = FL_POSIX;
4147 file_lock.fl_lmops = &nfsd_posix_mng_ops; 4168 file_lock->fl_lmops = &nfsd_posix_mng_ops;
4148 4169 file_lock->fl_start = lock->lk_offset;
4149 file_lock.fl_start = lock->lk_offset; 4170 file_lock->fl_end = last_byte_offset(lock->lk_offset, lock->lk_length);
4150 file_lock.fl_end = last_byte_offset(lock->lk_offset, lock->lk_length); 4171 nfs4_transform_lock_offset(file_lock);
4151 nfs4_transform_lock_offset(&file_lock); 4172
4152 4173 conflock = locks_alloc_lock();
4153 /* 4174 if (!conflock) {
4154 * Try to lock the file in the VFS. 4175 dprintk("NFSD: %s: unable to allocate lock!\n", __func__);
4155 * Note: locks.c uses the BKL to protect the inode's lock list. 4176 status = nfserr_jukebox;
4156 */ 4177 goto out;
4178 }
4157 4179
4158 err = vfs_lock_file(filp, F_SETLK, &file_lock, &conflock); 4180 err = vfs_lock_file(filp, F_SETLK, file_lock, conflock);
4159 switch (-err) { 4181 switch (-err) {
4160 case 0: /* success! */ 4182 case 0: /* success! */
4161 update_stateid(&lock_stp->st_stid.sc_stateid); 4183 update_stateid(&lock_stp->st_stid.sc_stateid);
@@ -4166,7 +4188,7 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
4166 case (EAGAIN): /* conflock holds conflicting lock */ 4188 case (EAGAIN): /* conflock holds conflicting lock */
4167 status = nfserr_denied; 4189 status = nfserr_denied;
4168 dprintk("NFSD: nfsd4_lock: conflicting lock found!\n"); 4190 dprintk("NFSD: nfsd4_lock: conflicting lock found!\n");
4169 nfs4_set_lock_denied(&conflock, &lock->lk_denied); 4191 nfs4_set_lock_denied(conflock, &lock->lk_denied);
4170 break; 4192 break;
4171 case (EDEADLK): 4193 case (EDEADLK):
4172 status = nfserr_deadlock; 4194 status = nfserr_deadlock;
@@ -4181,6 +4203,10 @@ out:
4181 release_lockowner(lock_sop); 4203 release_lockowner(lock_sop);
4182 if (!cstate->replay_owner) 4204 if (!cstate->replay_owner)
4183 nfs4_unlock_state(); 4205 nfs4_unlock_state();
4206 if (file_lock)
4207 locks_free_lock(file_lock);
4208 if (conflock)
4209 locks_free_lock(conflock);
4184 return status; 4210 return status;
4185} 4211}
4186 4212
@@ -4209,7 +4235,7 @@ nfsd4_lockt(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
4209 struct nfsd4_lockt *lockt) 4235 struct nfsd4_lockt *lockt)
4210{ 4236{
4211 struct inode *inode; 4237 struct inode *inode;
4212 struct file_lock file_lock; 4238 struct file_lock *file_lock = NULL;
4213 struct nfs4_lockowner *lo; 4239 struct nfs4_lockowner *lo;
4214 __be32 status; 4240 __be32 status;
4215 struct nfsd_net *nn = net_generic(&init_net, nfsd_net_id); 4241 struct nfsd_net *nn = net_generic(&init_net, nfsd_net_id);
@@ -4230,15 +4256,21 @@ nfsd4_lockt(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
4230 goto out; 4256 goto out;
4231 4257
4232 inode = cstate->current_fh.fh_dentry->d_inode; 4258 inode = cstate->current_fh.fh_dentry->d_inode;
4233 locks_init_lock(&file_lock); 4259 file_lock = locks_alloc_lock();
4260 if (!file_lock) {
4261 dprintk("NFSD: %s: unable to allocate lock!\n", __func__);
4262 status = nfserr_jukebox;
4263 goto out;
4264 }
4265 locks_init_lock(file_lock);
4234 switch (lockt->lt_type) { 4266 switch (lockt->lt_type) {
4235 case NFS4_READ_LT: 4267 case NFS4_READ_LT:
4236 case NFS4_READW_LT: 4268 case NFS4_READW_LT:
4237 file_lock.fl_type = F_RDLCK; 4269 file_lock->fl_type = F_RDLCK;
4238 break; 4270 break;
4239 case NFS4_WRITE_LT: 4271 case NFS4_WRITE_LT:
4240 case NFS4_WRITEW_LT: 4272 case NFS4_WRITEW_LT:
4241 file_lock.fl_type = F_WRLCK; 4273 file_lock->fl_type = F_WRLCK;
4242 break; 4274 break;
4243 default: 4275 default:
4244 dprintk("NFSD: nfs4_lockt: bad lock type!\n"); 4276 dprintk("NFSD: nfs4_lockt: bad lock type!\n");
@@ -4248,25 +4280,27 @@ nfsd4_lockt(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
4248 4280
4249 lo = find_lockowner_str(inode, &lockt->lt_clientid, &lockt->lt_owner); 4281 lo = find_lockowner_str(inode, &lockt->lt_clientid, &lockt->lt_owner);
4250 if (lo) 4282 if (lo)
4251 file_lock.fl_owner = (fl_owner_t)lo; 4283 file_lock->fl_owner = (fl_owner_t)lo;
4252 file_lock.fl_pid = current->tgid; 4284 file_lock->fl_pid = current->tgid;
4253 file_lock.fl_flags = FL_POSIX; 4285 file_lock->fl_flags = FL_POSIX;
4254 4286
4255 file_lock.fl_start = lockt->lt_offset; 4287 file_lock->fl_start = lockt->lt_offset;
4256 file_lock.fl_end = last_byte_offset(lockt->lt_offset, lockt->lt_length); 4288 file_lock->fl_end = last_byte_offset(lockt->lt_offset, lockt->lt_length);
4257 4289
4258 nfs4_transform_lock_offset(&file_lock); 4290 nfs4_transform_lock_offset(file_lock);
4259 4291
4260 status = nfsd_test_lock(rqstp, &cstate->current_fh, &file_lock); 4292 status = nfsd_test_lock(rqstp, &cstate->current_fh, file_lock);
4261 if (status) 4293 if (status)
4262 goto out; 4294 goto out;
4263 4295
4264 if (file_lock.fl_type != F_UNLCK) { 4296 if (file_lock->fl_type != F_UNLCK) {
4265 status = nfserr_denied; 4297 status = nfserr_denied;
4266 nfs4_set_lock_denied(&file_lock, &lockt->lt_denied); 4298 nfs4_set_lock_denied(file_lock, &lockt->lt_denied);
4267 } 4299 }
4268out: 4300out:
4269 nfs4_unlock_state(); 4301 nfs4_unlock_state();
4302 if (file_lock)
4303 locks_free_lock(file_lock);
4270 return status; 4304 return status;
4271} 4305}
4272 4306
@@ -4276,7 +4310,7 @@ nfsd4_locku(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
4276{ 4310{
4277 struct nfs4_ol_stateid *stp; 4311 struct nfs4_ol_stateid *stp;
4278 struct file *filp = NULL; 4312 struct file *filp = NULL;
4279 struct file_lock file_lock; 4313 struct file_lock *file_lock = NULL;
4280 __be32 status; 4314 __be32 status;
4281 int err; 4315 int err;
4282 4316
@@ -4298,23 +4332,29 @@ nfsd4_locku(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
4298 status = nfserr_lock_range; 4332 status = nfserr_lock_range;
4299 goto out; 4333 goto out;
4300 } 4334 }
4301 BUG_ON(!filp); 4335 file_lock = locks_alloc_lock();
4302 locks_init_lock(&file_lock); 4336 if (!file_lock) {
4303 file_lock.fl_type = F_UNLCK; 4337 dprintk("NFSD: %s: unable to allocate lock!\n", __func__);
4304 file_lock.fl_owner = (fl_owner_t)lockowner(stp->st_stateowner); 4338 status = nfserr_jukebox;
4305 file_lock.fl_pid = current->tgid; 4339 goto out;
4306 file_lock.fl_file = filp; 4340 }
4307 file_lock.fl_flags = FL_POSIX; 4341 locks_init_lock(file_lock);
4308 file_lock.fl_lmops = &nfsd_posix_mng_ops; 4342 file_lock->fl_type = F_UNLCK;
4309 file_lock.fl_start = locku->lu_offset; 4343 file_lock->fl_owner = (fl_owner_t)lockowner(stp->st_stateowner);
4310 4344 file_lock->fl_pid = current->tgid;
4311 file_lock.fl_end = last_byte_offset(locku->lu_offset, locku->lu_length); 4345 file_lock->fl_file = filp;
4312 nfs4_transform_lock_offset(&file_lock); 4346 file_lock->fl_flags = FL_POSIX;
4347 file_lock->fl_lmops = &nfsd_posix_mng_ops;
4348 file_lock->fl_start = locku->lu_offset;
4349
4350 file_lock->fl_end = last_byte_offset(locku->lu_offset,
4351 locku->lu_length);
4352 nfs4_transform_lock_offset(file_lock);
4313 4353
4314 /* 4354 /*
4315 * Try to unlock the file in the VFS. 4355 * Try to unlock the file in the VFS.
4316 */ 4356 */
4317 err = vfs_lock_file(filp, F_SETLK, &file_lock, NULL); 4357 err = vfs_lock_file(filp, F_SETLK, file_lock, NULL);
4318 if (err) { 4358 if (err) {
4319 dprintk("NFSD: nfs4_locku: vfs_lock_file failed!\n"); 4359 dprintk("NFSD: nfs4_locku: vfs_lock_file failed!\n");
4320 goto out_nfserr; 4360 goto out_nfserr;
@@ -4328,6 +4368,8 @@ nfsd4_locku(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
4328out: 4368out:
4329 if (!cstate->replay_owner) 4369 if (!cstate->replay_owner)
4330 nfs4_unlock_state(); 4370 nfs4_unlock_state();
4371 if (file_lock)
4372 locks_free_lock(file_lock);
4331 return status; 4373 return status;
4332 4374
4333out_nfserr: 4375out_nfserr:
@@ -4501,12 +4543,12 @@ nfsd4_find_reclaim_client(struct nfs4_client *clp)
4501* Called from OPEN. Look for clientid in reclaim list. 4543* Called from OPEN. Look for clientid in reclaim list.
4502*/ 4544*/
4503__be32 4545__be32
4504nfs4_check_open_reclaim(clientid_t *clid) 4546nfs4_check_open_reclaim(clientid_t *clid, bool sessions)
4505{ 4547{
4506 struct nfs4_client *clp; 4548 struct nfs4_client *clp;
4507 4549
4508 /* find clientid in conf_id_hashtbl */ 4550 /* find clientid in conf_id_hashtbl */
4509 clp = find_confirmed_client(clid); 4551 clp = find_confirmed_client(clid, sessions);
4510 if (clp == NULL) 4552 if (clp == NULL)
4511 return nfserr_reclaim_bad; 4553 return nfserr_reclaim_bad;
4512 4554
@@ -4522,7 +4564,6 @@ void nfsd_forget_clients(u64 num)
4522 4564
4523 nfs4_lock_state(); 4565 nfs4_lock_state();
4524 list_for_each_entry_safe(clp, next, &client_lru, cl_lru) { 4566 list_for_each_entry_safe(clp, next, &client_lru, cl_lru) {
4525 nfsd4_client_record_remove(clp);
4526 expire_client(clp); 4567 expire_client(clp);
4527 if (++count == num) 4568 if (++count == num)
4528 break; 4569 break;
@@ -4582,7 +4623,7 @@ void nfsd_forget_openowners(u64 num)
4582 printk(KERN_INFO "NFSD: Forgot %d open owners", count); 4623 printk(KERN_INFO "NFSD: Forgot %d open owners", count);
4583} 4624}
4584 4625
4585int nfsd_process_n_delegations(u64 num, struct list_head *list) 4626static int nfsd_process_n_delegations(u64 num, struct list_head *list)
4586{ 4627{
4587 int i, count = 0; 4628 int i, count = 0;
4588 struct nfs4_file *fp, *fnext; 4629 struct nfs4_file *fp, *fnext;
@@ -4747,11 +4788,11 @@ __nfs4_state_shutdown(void)
4747 for (i = 0; i < CLIENT_HASH_SIZE; i++) { 4788 for (i = 0; i < CLIENT_HASH_SIZE; i++) {
4748 while (!list_empty(&conf_id_hashtbl[i])) { 4789 while (!list_empty(&conf_id_hashtbl[i])) {
4749 clp = list_entry(conf_id_hashtbl[i].next, struct nfs4_client, cl_idhash); 4790 clp = list_entry(conf_id_hashtbl[i].next, struct nfs4_client, cl_idhash);
4750 expire_client(clp); 4791 destroy_client(clp);
4751 } 4792 }
4752 while (!list_empty(&unconf_str_hashtbl[i])) { 4793 while (!list_empty(&unconf_str_hashtbl[i])) {
4753 clp = list_entry(unconf_str_hashtbl[i].next, struct nfs4_client, cl_strhash); 4794 clp = list_entry(unconf_str_hashtbl[i].next, struct nfs4_client, cl_strhash);
4754 expire_client(clp); 4795 destroy_client(clp);
4755 } 4796 }
4756 } 4797 }
4757 INIT_LIST_HEAD(&reaplist); 4798 INIT_LIST_HEAD(&reaplist);
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index 6322df36031f..fd548d155088 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -2659,7 +2659,7 @@ static __be32 nfsd4_encode_bind_conn_to_session(struct nfsd4_compoundres *resp,
2659 RESERVE_SPACE(NFS4_MAX_SESSIONID_LEN + 8); 2659 RESERVE_SPACE(NFS4_MAX_SESSIONID_LEN + 8);
2660 WRITEMEM(bcts->sessionid.data, NFS4_MAX_SESSIONID_LEN); 2660 WRITEMEM(bcts->sessionid.data, NFS4_MAX_SESSIONID_LEN);
2661 WRITE32(bcts->dir); 2661 WRITE32(bcts->dir);
2662 /* XXX: ? */ 2662 /* Sorry, we do not yet support RDMA over 4.1: */
2663 WRITE32(0); 2663 WRITE32(0);
2664 ADJUST_ARGS(); 2664 ADJUST_ARGS();
2665 } 2665 }
diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c
index fa49cff5ee65..dab350dfc376 100644
--- a/fs/nfsd/nfsctl.c
+++ b/fs/nfsd/nfsctl.c
@@ -406,7 +406,7 @@ static ssize_t write_threads(struct file *file, char *buf, size_t size)
406 return rv; 406 return rv;
407 if (newthreads < 0) 407 if (newthreads < 0)
408 return -EINVAL; 408 return -EINVAL;
409 rv = nfsd_svc(NFS_PORT, newthreads); 409 rv = nfsd_svc(newthreads);
410 if (rv < 0) 410 if (rv < 0)
411 return rv; 411 return rv;
412 } else 412 } else
@@ -683,25 +683,6 @@ static ssize_t __write_ports_addfd(char *buf)
683} 683}
684 684
685/* 685/*
686 * A '-' followed by the 'name' of a socket means we close the socket.
687 */
688static ssize_t __write_ports_delfd(char *buf)
689{
690 char *toclose;
691 int len = 0;
692
693 toclose = kstrdup(buf + 1, GFP_KERNEL);
694 if (toclose == NULL)
695 return -ENOMEM;
696
697 if (nfsd_serv != NULL)
698 len = svc_sock_names(nfsd_serv, buf,
699 SIMPLE_TRANSACTION_LIMIT, toclose);
700 kfree(toclose);
701 return len;
702}
703
704/*
705 * A transport listener is added by writing it's transport name and 686 * A transport listener is added by writing it's transport name and
706 * a port number. 687 * a port number.
707 */ 688 */
@@ -712,7 +693,7 @@ static ssize_t __write_ports_addxprt(char *buf)
712 int port, err; 693 int port, err;
713 struct net *net = &init_net; 694 struct net *net = &init_net;
714 695
715 if (sscanf(buf, "%15s %4u", transport, &port) != 2) 696 if (sscanf(buf, "%15s %5u", transport, &port) != 2)
716 return -EINVAL; 697 return -EINVAL;
717 698
718 if (port < 1 || port > USHRT_MAX) 699 if (port < 1 || port > USHRT_MAX)
@@ -746,31 +727,6 @@ out_err:
746 return err; 727 return err;
747} 728}
748 729
749/*
750 * A transport listener is removed by writing a "-", it's transport
751 * name, and it's port number.
752 */
753static ssize_t __write_ports_delxprt(char *buf)
754{
755 struct svc_xprt *xprt;
756 char transport[16];
757 int port;
758
759 if (sscanf(&buf[1], "%15s %4u", transport, &port) != 2)
760 return -EINVAL;
761
762 if (port < 1 || port > USHRT_MAX || nfsd_serv == NULL)
763 return -EINVAL;
764
765 xprt = svc_find_xprt(nfsd_serv, transport, &init_net, AF_UNSPEC, port);
766 if (xprt == NULL)
767 return -ENOTCONN;
768
769 svc_close_xprt(xprt);
770 svc_xprt_put(xprt);
771 return 0;
772}
773
774static ssize_t __write_ports(struct file *file, char *buf, size_t size) 730static ssize_t __write_ports(struct file *file, char *buf, size_t size)
775{ 731{
776 if (size == 0) 732 if (size == 0)
@@ -779,15 +735,9 @@ static ssize_t __write_ports(struct file *file, char *buf, size_t size)
779 if (isdigit(buf[0])) 735 if (isdigit(buf[0]))
780 return __write_ports_addfd(buf); 736 return __write_ports_addfd(buf);
781 737
782 if (buf[0] == '-' && isdigit(buf[1]))
783 return __write_ports_delfd(buf);
784
785 if (isalpha(buf[0])) 738 if (isalpha(buf[0]))
786 return __write_ports_addxprt(buf); 739 return __write_ports_addxprt(buf);
787 740
788 if (buf[0] == '-' && isalpha(buf[1]))
789 return __write_ports_delxprt(buf);
790
791 return -EINVAL; 741 return -EINVAL;
792} 742}
793 743
@@ -825,21 +775,6 @@ static ssize_t __write_ports(struct file *file, char *buf, size_t size)
825 * OR 775 * OR
826 * 776 *
827 * Input: 777 * Input:
828 * buf: C string containing a "-" followed
829 * by an integer value representing a
830 * previously passed in socket file
831 * descriptor
832 * size: non-zero length of C string in @buf
833 * Output:
834 * On success: NFS service no longer listens on that socket;
835 * passed-in buffer filled with a '\n'-terminated C
836 * string containing a unique name of the listener;
837 * return code is the size in bytes of the string
838 * On error: return code is a negative errno value
839 *
840 * OR
841 *
842 * Input:
843 * buf: C string containing a transport 778 * buf: C string containing a transport
844 * name and an unsigned integer value 779 * name and an unsigned integer value
845 * representing the port to listen on, 780 * representing the port to listen on,
@@ -848,19 +783,6 @@ static ssize_t __write_ports(struct file *file, char *buf, size_t size)
848 * Output: 783 * Output:
849 * On success: returns zero; NFS service is started 784 * On success: returns zero; NFS service is started
850 * On error: return code is a negative errno value 785 * On error: return code is a negative errno value
851 *
852 * OR
853 *
854 * Input:
855 * buf: C string containing a "-" followed
856 * by a transport name and an unsigned
857 * integer value representing the port
858 * to listen on, separated by whitespace
859 * size: non-zero length of C string in @buf
860 * Output:
861 * On success: returns zero; NFS service no longer listens
862 * on that transport
863 * On error: return code is a negative errno value
864 */ 786 */
865static ssize_t write_ports(struct file *file, char *buf, size_t size) 787static ssize_t write_ports(struct file *file, char *buf, size_t size)
866{ 788{
@@ -1008,8 +930,6 @@ static ssize_t write_gracetime(struct file *file, char *buf, size_t size)
1008 return nfsd4_write_time(file, buf, size, &nfsd4_grace); 930 return nfsd4_write_time(file, buf, size, &nfsd4_grace);
1009} 931}
1010 932
1011extern char *nfs4_recoverydir(void);
1012
1013static ssize_t __write_recoverydir(struct file *file, char *buf, size_t size) 933static ssize_t __write_recoverydir(struct file *file, char *buf, size_t size)
1014{ 934{
1015 char *mesg = buf; 935 char *mesg = buf;
diff --git a/fs/nfsd/nfsd.h b/fs/nfsd/nfsd.h
index 2244222368ab..80d5ce40aadb 100644
--- a/fs/nfsd/nfsd.h
+++ b/fs/nfsd/nfsd.h
@@ -65,7 +65,7 @@ extern const struct seq_operations nfs_exports_op;
65/* 65/*
66 * Function prototypes. 66 * Function prototypes.
67 */ 67 */
68int nfsd_svc(unsigned short port, int nrservs); 68int nfsd_svc(int nrservs);
69int nfsd_dispatch(struct svc_rqst *rqstp, __be32 *statp); 69int nfsd_dispatch(struct svc_rqst *rqstp, __be32 *statp);
70 70
71int nfsd_nrthreads(void); 71int nfsd_nrthreads(void);
@@ -124,6 +124,7 @@ int nfs4_state_start(void);
124void nfs4_state_shutdown(void); 124void nfs4_state_shutdown(void);
125void nfs4_reset_lease(time_t leasetime); 125void nfs4_reset_lease(time_t leasetime);
126int nfs4_reset_recoverydir(char *recdir); 126int nfs4_reset_recoverydir(char *recdir);
127char * nfs4_recoverydir(void);
127#else 128#else
128static inline void nfs4_state_init(void) { } 129static inline void nfs4_state_init(void) { }
129static inline int nfsd4_init_slabs(void) { return 0; } 130static inline int nfsd4_init_slabs(void) { return 0; }
@@ -132,6 +133,7 @@ static inline int nfs4_state_start(void) { return 0; }
132static inline void nfs4_state_shutdown(void) { } 133static inline void nfs4_state_shutdown(void) { }
133static inline void nfs4_reset_lease(time_t leasetime) { } 134static inline void nfs4_reset_lease(time_t leasetime) { }
134static inline int nfs4_reset_recoverydir(char *recdir) { return 0; } 135static inline int nfs4_reset_recoverydir(char *recdir) { return 0; }
136static inline char * nfs4_recoverydir(void) {return NULL; }
135#endif 137#endif
136 138
137/* 139/*
diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c
index 240473cb708f..2013aa001dab 100644
--- a/fs/nfsd/nfssvc.c
+++ b/fs/nfsd/nfssvc.c
@@ -183,18 +183,18 @@ int nfsd_nrthreads(void)
183 return rv; 183 return rv;
184} 184}
185 185
186static int nfsd_init_socks(int port) 186static int nfsd_init_socks(void)
187{ 187{
188 int error; 188 int error;
189 if (!list_empty(&nfsd_serv->sv_permsocks)) 189 if (!list_empty(&nfsd_serv->sv_permsocks))
190 return 0; 190 return 0;
191 191
192 error = svc_create_xprt(nfsd_serv, "udp", &init_net, PF_INET, port, 192 error = svc_create_xprt(nfsd_serv, "udp", &init_net, PF_INET, NFS_PORT,
193 SVC_SOCK_DEFAULTS); 193 SVC_SOCK_DEFAULTS);
194 if (error < 0) 194 if (error < 0)
195 return error; 195 return error;
196 196
197 error = svc_create_xprt(nfsd_serv, "tcp", &init_net, PF_INET, port, 197 error = svc_create_xprt(nfsd_serv, "tcp", &init_net, PF_INET, NFS_PORT,
198 SVC_SOCK_DEFAULTS); 198 SVC_SOCK_DEFAULTS);
199 if (error < 0) 199 if (error < 0)
200 return error; 200 return error;
@@ -204,7 +204,7 @@ static int nfsd_init_socks(int port)
204 204
205static bool nfsd_up = false; 205static bool nfsd_up = false;
206 206
207static int nfsd_startup(unsigned short port, int nrservs) 207static int nfsd_startup(int nrservs)
208{ 208{
209 int ret; 209 int ret;
210 210
@@ -218,7 +218,7 @@ static int nfsd_startup(unsigned short port, int nrservs)
218 ret = nfsd_racache_init(2*nrservs); 218 ret = nfsd_racache_init(2*nrservs);
219 if (ret) 219 if (ret)
220 return ret; 220 return ret;
221 ret = nfsd_init_socks(port); 221 ret = nfsd_init_socks();
222 if (ret) 222 if (ret)
223 goto out_racache; 223 goto out_racache;
224 ret = lockd_up(&init_net); 224 ret = lockd_up(&init_net);
@@ -436,7 +436,7 @@ int nfsd_set_nrthreads(int n, int *nthreads)
436 * this is the first time nrservs is nonzero. 436 * this is the first time nrservs is nonzero.
437 */ 437 */
438int 438int
439nfsd_svc(unsigned short port, int nrservs) 439nfsd_svc(int nrservs)
440{ 440{
441 int error; 441 int error;
442 bool nfsd_up_before; 442 bool nfsd_up_before;
@@ -458,7 +458,7 @@ nfsd_svc(unsigned short port, int nrservs)
458 458
459 nfsd_up_before = nfsd_up; 459 nfsd_up_before = nfsd_up;
460 460
461 error = nfsd_startup(port, nrservs); 461 error = nfsd_startup(nrservs);
462 if (error) 462 if (error)
463 goto out_destroy; 463 goto out_destroy;
464 error = svc_set_num_threads(nfsd_serv, NULL, nrservs); 464 error = svc_set_num_threads(nfsd_serv, NULL, nrservs);
@@ -487,7 +487,7 @@ static int
487nfsd(void *vrqstp) 487nfsd(void *vrqstp)
488{ 488{
489 struct svc_rqst *rqstp = (struct svc_rqst *) vrqstp; 489 struct svc_rqst *rqstp = (struct svc_rqst *) vrqstp;
490 int err, preverr = 0; 490 int err;
491 491
492 /* Lock module and set up kernel thread */ 492 /* Lock module and set up kernel thread */
493 mutex_lock(&nfsd_mutex); 493 mutex_lock(&nfsd_mutex);
@@ -534,16 +534,6 @@ nfsd(void *vrqstp)
534 ; 534 ;
535 if (err == -EINTR) 535 if (err == -EINTR)
536 break; 536 break;
537 else if (err < 0) {
538 if (err != preverr) {
539 printk(KERN_WARNING "%s: unexpected error "
540 "from svc_recv (%d)\n", __func__, -err);
541 preverr = err;
542 }
543 schedule_timeout_uninterruptible(HZ);
544 continue;
545 }
546
547 validate_process_creds(); 537 validate_process_creds();
548 svc_process(rqstp); 538 svc_process(rqstp);
549 validate_process_creds(); 539 validate_process_creds();
diff --git a/fs/nfsd/state.h b/fs/nfsd/state.h
index 22bd0a66c356..e036894bce57 100644
--- a/fs/nfsd/state.h
+++ b/fs/nfsd/state.h
@@ -373,11 +373,7 @@ static inline struct nfs4_lockowner * lockowner(struct nfs4_stateowner *so)
373 return container_of(so, struct nfs4_lockowner, lo_owner); 373 return container_of(so, struct nfs4_lockowner, lo_owner);
374} 374}
375 375
376/* 376/* nfs4_file: a file opened by some number of (open) nfs4_stateowners. */
377* nfs4_file: a file opened by some number of (open) nfs4_stateowners.
378* o fi_perfile list is used to search for conflicting
379* share_acces, share_deny on the file.
380*/
381struct nfs4_file { 377struct nfs4_file {
382 atomic_t fi_ref; 378 atomic_t fi_ref;
383 struct list_head fi_hash; /* hash by "struct inode *" */ 379 struct list_head fi_hash; /* hash by "struct inode *" */
@@ -459,7 +455,7 @@ extern void nfs4_unlock_state(void);
459extern int nfs4_in_grace(void); 455extern int nfs4_in_grace(void);
460extern void nfs4_release_reclaim(void); 456extern void nfs4_release_reclaim(void);
461extern struct nfs4_client_reclaim *nfsd4_find_reclaim_client(struct nfs4_client *crp); 457extern struct nfs4_client_reclaim *nfsd4_find_reclaim_client(struct nfs4_client *crp);
462extern __be32 nfs4_check_open_reclaim(clientid_t *clid); 458extern __be32 nfs4_check_open_reclaim(clientid_t *clid, bool sessions);
463extern void nfs4_free_openowner(struct nfs4_openowner *); 459extern void nfs4_free_openowner(struct nfs4_openowner *);
464extern void nfs4_free_lockowner(struct nfs4_lockowner *); 460extern void nfs4_free_lockowner(struct nfs4_lockowner *);
465extern int set_callback_cred(void); 461extern int set_callback_cred(void);
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
index 3f67b8e12251..c120b48ec305 100644
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -1581,7 +1581,7 @@ nfsd_readlink(struct svc_rqst *rqstp, struct svc_fh *fhp, char *buf, int *lenp)
1581 */ 1581 */
1582 1582
1583 oldfs = get_fs(); set_fs(KERNEL_DS); 1583 oldfs = get_fs(); set_fs(KERNEL_DS);
1584 host_err = inode->i_op->readlink(path.dentry, buf, *lenp); 1584 host_err = inode->i_op->readlink(path.dentry, (char __user *)buf, *lenp);
1585 set_fs(oldfs); 1585 set_fs(oldfs);
1586 1586
1587 if (host_err < 0) 1587 if (host_err < 0)
diff --git a/include/linux/nfsd/Kbuild b/include/linux/nfsd/Kbuild
index 5b7d84ac954a..e69de29bb2d1 100644
--- a/include/linux/nfsd/Kbuild
+++ b/include/linux/nfsd/Kbuild
@@ -1,5 +0,0 @@
1header-y += cld.h
2header-y += debug.h
3header-y += export.h
4header-y += nfsfh.h
5header-y += stats.h
diff --git a/include/linux/nfsd/debug.h b/include/linux/nfsd/debug.h
index ee4aa91788e7..19ef8375b577 100644
--- a/include/linux/nfsd/debug.h
+++ b/include/linux/nfsd/debug.h
@@ -5,44 +5,15 @@
5 * 5 *
6 * Copyright (C) 1995 Olaf Kirch <okir@monad.swb.de> 6 * Copyright (C) 1995 Olaf Kirch <okir@monad.swb.de>
7 */ 7 */
8
9#ifndef LINUX_NFSD_DEBUG_H 8#ifndef LINUX_NFSD_DEBUG_H
10#define LINUX_NFSD_DEBUG_H 9#define LINUX_NFSD_DEBUG_H
11 10
12#include <linux/sunrpc/debug.h> 11#include <uapi/linux/nfsd/debug.h>
13 12
14/*
15 * Enable debugging for nfsd.
16 * Requires RPC_DEBUG.
17 */
18#ifdef RPC_DEBUG
19# define NFSD_DEBUG 1
20#endif
21
22/*
23 * knfsd debug flags
24 */
25#define NFSDDBG_SOCK 0x0001
26#define NFSDDBG_FH 0x0002
27#define NFSDDBG_EXPORT 0x0004
28#define NFSDDBG_SVC 0x0008
29#define NFSDDBG_PROC 0x0010
30#define NFSDDBG_FILEOP 0x0020
31#define NFSDDBG_AUTH 0x0040
32#define NFSDDBG_REPCACHE 0x0080
33#define NFSDDBG_XDR 0x0100
34#define NFSDDBG_LOCKD 0x0200
35#define NFSDDBG_ALL 0x7FFF
36#define NFSDDBG_NOCHANGE 0xFFFF
37
38
39#ifdef __KERNEL__
40# undef ifdebug 13# undef ifdebug
41# ifdef NFSD_DEBUG 14# ifdef NFSD_DEBUG
42# define ifdebug(flag) if (nfsd_debug & NFSDDBG_##flag) 15# define ifdebug(flag) if (nfsd_debug & NFSDDBG_##flag)
43# else 16# else
44# define ifdebug(flag) if (0) 17# define ifdebug(flag) if (0)
45# endif 18# endif
46#endif /* __KERNEL__ */
47
48#endif /* LINUX_NFSD_DEBUG_H */ 19#endif /* LINUX_NFSD_DEBUG_H */
diff --git a/include/linux/nfsd/export.h b/include/linux/nfsd/export.h
index e33f747b173c..24c139288db4 100644
--- a/include/linux/nfsd/export.h
+++ b/include/linux/nfsd/export.h
@@ -6,58 +6,11 @@
6 * 6 *
7 * Copyright (C) 1995-1997 Olaf Kirch <okir@monad.swb.de> 7 * Copyright (C) 1995-1997 Olaf Kirch <okir@monad.swb.de>
8 */ 8 */
9
10#ifndef NFSD_EXPORT_H 9#ifndef NFSD_EXPORT_H
11#define NFSD_EXPORT_H 10#define NFSD_EXPORT_H
12 11
13# include <linux/types.h>
14#ifdef __KERNEL__
15# include <linux/nfsd/nfsfh.h> 12# include <linux/nfsd/nfsfh.h>
16#endif 13#include <uapi/linux/nfsd/export.h>
17
18/*
19 * Important limits for the exports stuff.
20 */
21#define NFSCLNT_IDMAX 1024
22#define NFSCLNT_ADDRMAX 16
23#define NFSCLNT_KEYMAX 32
24
25/*
26 * Export flags.
27 */
28#define NFSEXP_READONLY 0x0001
29#define NFSEXP_INSECURE_PORT 0x0002
30#define NFSEXP_ROOTSQUASH 0x0004
31#define NFSEXP_ALLSQUASH 0x0008
32#define NFSEXP_ASYNC 0x0010
33#define NFSEXP_GATHERED_WRITES 0x0020
34/* 40 80 100 currently unused */
35#define NFSEXP_NOHIDE 0x0200
36#define NFSEXP_NOSUBTREECHECK 0x0400
37#define NFSEXP_NOAUTHNLM 0x0800 /* Don't authenticate NLM requests - just trust */
38#define NFSEXP_MSNFS 0x1000 /* do silly things that MS clients expect; no longer supported */
39#define NFSEXP_FSID 0x2000
40#define NFSEXP_CROSSMOUNT 0x4000
41#define NFSEXP_NOACL 0x8000 /* reserved for possible ACL related use */
42/*
43 * The NFSEXP_V4ROOT flag causes the kernel to give access only to NFSv4
44 * clients, and only to the single directory that is the root of the
45 * export; further lookup and readdir operations are treated as if every
46 * subdirectory was a mountpoint, and ignored if they are not themselves
47 * exported. This is used by nfsd and mountd to construct the NFSv4
48 * pseudofilesystem, which provides access only to paths leading to each
49 * exported filesystem.
50 */
51#define NFSEXP_V4ROOT 0x10000
52/* All flags that we claim to support. (Note we don't support NOACL.) */
53#define NFSEXP_ALLFLAGS 0x17E3F
54
55/* The flags that may vary depending on security flavor: */
56#define NFSEXP_SECINFO_FLAGS (NFSEXP_READONLY | NFSEXP_ROOTSQUASH \
57 | NFSEXP_ALLSQUASH \
58 | NFSEXP_INSECURE_PORT)
59
60#ifdef __KERNEL__
61 14
62/* 15/*
63 * FS Locations 16 * FS Locations
@@ -154,7 +107,4 @@ static inline void exp_get(struct svc_export *exp)
154} 107}
155struct svc_export * rqst_exp_find(struct svc_rqst *, int, u32 *); 108struct svc_export * rqst_exp_find(struct svc_rqst *, int, u32 *);
156 109
157#endif /* __KERNEL__ */
158
159#endif /* NFSD_EXPORT_H */ 110#endif /* NFSD_EXPORT_H */
160
diff --git a/include/linux/nfsd/nfsfh.h b/include/linux/nfsd/nfsfh.h
index fa63048fecff..a93593f1fa4e 100644
--- a/include/linux/nfsd/nfsfh.h
+++ b/include/linux/nfsd/nfsfh.h
@@ -10,117 +10,11 @@
10 * 10 *
11 * Copyright (C) 1995, 1996, 1997 Olaf Kirch <okir@monad.swb.de> 11 * Copyright (C) 1995, 1996, 1997 Olaf Kirch <okir@monad.swb.de>
12 */ 12 */
13
14#ifndef _LINUX_NFSD_FH_H 13#ifndef _LINUX_NFSD_FH_H
15#define _LINUX_NFSD_FH_H 14#define _LINUX_NFSD_FH_H
16 15
17#include <linux/types.h>
18#include <linux/nfs.h>
19#include <linux/nfs2.h>
20#include <linux/nfs3.h>
21#include <linux/nfs4.h>
22#ifdef __KERNEL__
23# include <linux/sunrpc/svc.h> 16# include <linux/sunrpc/svc.h>
24#endif 17#include <uapi/linux/nfsd/nfsfh.h>
25
26/*
27 * This is the old "dentry style" Linux NFSv2 file handle.
28 *
29 * The xino and xdev fields are currently used to transport the
30 * ino/dev of the exported inode.
31 */
32struct nfs_fhbase_old {
33 __u32 fb_dcookie; /* dentry cookie - always 0xfeebbaca */
34 __u32 fb_ino; /* our inode number */
35 __u32 fb_dirino; /* dir inode number, 0 for directories */
36 __u32 fb_dev; /* our device */
37 __u32 fb_xdev;
38 __u32 fb_xino;
39 __u32 fb_generation;
40};
41
42/*
43 * This is the new flexible, extensible style NFSv2/v3 file handle.
44 * by Neil Brown <neilb@cse.unsw.edu.au> - March 2000
45 *
46 * The file handle starts with a sequence of four-byte words.
47 * The first word contains a version number (1) and three descriptor bytes
48 * that tell how the remaining 3 variable length fields should be handled.
49 * These three bytes are auth_type, fsid_type and fileid_type.
50 *
51 * All four-byte values are in host-byte-order.
52 *
53 * The auth_type field specifies how the filehandle can be authenticated
54 * This might allow a file to be confirmed to be in a writable part of a
55 * filetree without checking the path from it up to the root.
56 * Current values:
57 * 0 - No authentication. fb_auth is 0 bytes long
58 * Possible future values:
59 * 1 - 4 bytes taken from MD5 hash of the remainer of the file handle
60 * prefixed by a secret and with the important export flags.
61 *
62 * The fsid_type identifies how the filesystem (or export point) is
63 * encoded.
64 * Current values:
65 * 0 - 4 byte device id (ms-2-bytes major, ls-2-bytes minor), 4byte inode number
66 * NOTE: we cannot use the kdev_t device id value, because kdev_t.h
67 * says we mustn't. We must break it up and reassemble.
68 * 1 - 4 byte user specified identifier
69 * 2 - 4 byte major, 4 byte minor, 4 byte inode number - DEPRECATED
70 * 3 - 4 byte device id, encoded for user-space, 4 byte inode number
71 * 4 - 4 byte inode number and 4 byte uuid
72 * 5 - 8 byte uuid
73 * 6 - 16 byte uuid
74 * 7 - 8 byte inode number and 16 byte uuid
75 *
76 * The fileid_type identified how the file within the filesystem is encoded.
77 * This is (will be) passed to, and set by, the underlying filesystem if it supports
78 * filehandle operations. The filesystem must not use the value '0' or '0xff' and may
79 * only use the values 1 and 2 as defined below:
80 * Current values:
81 * 0 - The root, or export point, of the filesystem. fb_fileid is 0 bytes.
82 * 1 - 32bit inode number, 32 bit generation number.
83 * 2 - 32bit inode number, 32 bit generation number, 32 bit parent directory inode number.
84 *
85 */
86struct nfs_fhbase_new {
87 __u8 fb_version; /* == 1, even => nfs_fhbase_old */
88 __u8 fb_auth_type;
89 __u8 fb_fsid_type;
90 __u8 fb_fileid_type;
91 __u32 fb_auth[1];
92/* __u32 fb_fsid[0]; floating */
93/* __u32 fb_fileid[0]; floating */
94};
95
96struct knfsd_fh {
97 unsigned int fh_size; /* significant for NFSv3.
98 * Points to the current size while building
99 * a new file handle
100 */
101 union {
102 struct nfs_fhbase_old fh_old;
103 __u32 fh_pad[NFS4_FHSIZE/4];
104 struct nfs_fhbase_new fh_new;
105 } fh_base;
106};
107
108#define ofh_dcookie fh_base.fh_old.fb_dcookie
109#define ofh_ino fh_base.fh_old.fb_ino
110#define ofh_dirino fh_base.fh_old.fb_dirino
111#define ofh_dev fh_base.fh_old.fb_dev
112#define ofh_xdev fh_base.fh_old.fb_xdev
113#define ofh_xino fh_base.fh_old.fb_xino
114#define ofh_generation fh_base.fh_old.fb_generation
115
116#define fh_version fh_base.fh_new.fb_version
117#define fh_fsid_type fh_base.fh_new.fb_fsid_type
118#define fh_auth_type fh_base.fh_new.fb_auth_type
119#define fh_fileid_type fh_base.fh_new.fb_fileid_type
120#define fh_auth fh_base.fh_new.fb_auth
121#define fh_fsid fh_base.fh_new.fb_auth
122
123#ifdef __KERNEL__
124 18
125static inline __u32 ino_t_to_u32(ino_t ino) 19static inline __u32 ino_t_to_u32(ino_t ino)
126{ 20{
@@ -166,7 +60,4 @@ typedef struct svc_fh {
166 60
167} svc_fh; 61} svc_fh;
168 62
169#endif /* __KERNEL__ */
170
171
172#endif /* _LINUX_NFSD_FH_H */ 63#endif /* _LINUX_NFSD_FH_H */
diff --git a/include/linux/nfsd/stats.h b/include/linux/nfsd/stats.h
index 2693ef647df6..e75b2544ff12 100644
--- a/include/linux/nfsd/stats.h
+++ b/include/linux/nfsd/stats.h
@@ -5,16 +5,11 @@
5 * 5 *
6 * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de> 6 * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
7 */ 7 */
8
9#ifndef LINUX_NFSD_STATS_H 8#ifndef LINUX_NFSD_STATS_H
10#define LINUX_NFSD_STATS_H 9#define LINUX_NFSD_STATS_H
11 10
12#include <linux/nfs4.h> 11#include <uapi/linux/nfsd/stats.h>
13
14/* thread usage wraps very million seconds (approx one fortnight) */
15#define NFSD_USAGE_WRAP (HZ*1000000)
16 12
17#ifdef __KERNEL__
18 13
19struct nfsd_stats { 14struct nfsd_stats {
20 unsigned int rchits; /* repcache hits */ 15 unsigned int rchits; /* repcache hits */
@@ -47,5 +42,4 @@ extern struct svc_stat nfsd_svcstats;
47void nfsd_stat_init(void); 42void nfsd_stat_init(void);
48void nfsd_stat_shutdown(void); 43void nfsd_stat_shutdown(void);
49 44
50#endif /* __KERNEL__ */
51#endif /* LINUX_NFSD_STATS_H */ 45#endif /* LINUX_NFSD_STATS_H */
diff --git a/include/linux/sunrpc/Kbuild b/include/linux/sunrpc/Kbuild
index 98df21164a86..e69de29bb2d1 100644
--- a/include/linux/sunrpc/Kbuild
+++ b/include/linux/sunrpc/Kbuild
@@ -1 +0,0 @@
1header-y += debug.h
diff --git a/include/linux/sunrpc/debug.h b/include/linux/sunrpc/debug.h
index a76cc20d98ce..9385bd74c860 100644
--- a/include/linux/sunrpc/debug.h
+++ b/include/linux/sunrpc/debug.h
@@ -5,28 +5,11 @@
5 * 5 *
6 * Copyright (C) 1996, Olaf Kirch <okir@monad.swb.de> 6 * Copyright (C) 1996, Olaf Kirch <okir@monad.swb.de>
7 */ 7 */
8
9#ifndef _LINUX_SUNRPC_DEBUG_H_ 8#ifndef _LINUX_SUNRPC_DEBUG_H_
10#define _LINUX_SUNRPC_DEBUG_H_ 9#define _LINUX_SUNRPC_DEBUG_H_
11 10
12/* 11#include <uapi/linux/sunrpc/debug.h>
13 * RPC debug facilities
14 */
15#define RPCDBG_XPRT 0x0001
16#define RPCDBG_CALL 0x0002
17#define RPCDBG_DEBUG 0x0004
18#define RPCDBG_NFS 0x0008
19#define RPCDBG_AUTH 0x0010
20#define RPCDBG_BIND 0x0020
21#define RPCDBG_SCHED 0x0040
22#define RPCDBG_TRANS 0x0080
23#define RPCDBG_SVCXPRT 0x0100
24#define RPCDBG_SVCDSP 0x0200
25#define RPCDBG_MISC 0x0400
26#define RPCDBG_CACHE 0x0800
27#define RPCDBG_ALL 0x7fff
28 12
29#ifdef __KERNEL__
30 13
31/* 14/*
32 * Enable RPC debugging/profiling. 15 * Enable RPC debugging/profiling.
@@ -87,24 +70,4 @@ void rpc_register_sysctl(void);
87void rpc_unregister_sysctl(void); 70void rpc_unregister_sysctl(void);
88#endif 71#endif
89 72
90#endif /* __KERNEL__ */
91
92/*
93 * Declarations for the sysctl debug interface, which allows to read or
94 * change the debug flags for rpc, nfs, nfsd, and lockd. Since the sunrpc
95 * module currently registers its sysctl table dynamically, the sysctl path
96 * for module FOO is <CTL_SUNRPC, CTL_FOODEBUG>.
97 */
98
99enum {
100 CTL_RPCDEBUG = 1,
101 CTL_NFSDEBUG,
102 CTL_NFSDDEBUG,
103 CTL_NLMDEBUG,
104 CTL_SLOTTABLE_UDP,
105 CTL_SLOTTABLE_TCP,
106 CTL_MIN_RESVPORT,
107 CTL_MAX_RESVPORT,
108};
109
110#endif /* _LINUX_SUNRPC_DEBUG_H_ */ 73#endif /* _LINUX_SUNRPC_DEBUG_H_ */
diff --git a/include/linux/sunrpc/svc_xprt.h b/include/linux/sunrpc/svc_xprt.h
index b3f64b12f141..b05963f09ebf 100644
--- a/include/linux/sunrpc/svc_xprt.h
+++ b/include/linux/sunrpc/svc_xprt.h
@@ -114,7 +114,6 @@ void svc_xprt_init(struct net *, struct svc_xprt_class *, struct svc_xprt *,
114int svc_create_xprt(struct svc_serv *, const char *, struct net *, 114int svc_create_xprt(struct svc_serv *, const char *, struct net *,
115 const int, const unsigned short, int); 115 const int, const unsigned short, int);
116void svc_xprt_enqueue(struct svc_xprt *xprt); 116void svc_xprt_enqueue(struct svc_xprt *xprt);
117void svc_xprt_received(struct svc_xprt *);
118void svc_xprt_put(struct svc_xprt *xprt); 117void svc_xprt_put(struct svc_xprt *xprt);
119void svc_xprt_copy_addrs(struct svc_rqst *rqstp, struct svc_xprt *xprt); 118void svc_xprt_copy_addrs(struct svc_rqst *rqstp, struct svc_xprt *xprt);
120void svc_close_xprt(struct svc_xprt *xprt); 119void svc_close_xprt(struct svc_xprt *xprt);
@@ -124,6 +123,7 @@ struct svc_xprt *svc_find_xprt(struct svc_serv *serv, const char *xcl_name,
124 struct net *net, const sa_family_t af, 123 struct net *net, const sa_family_t af,
125 const unsigned short port); 124 const unsigned short port);
126int svc_xprt_names(struct svc_serv *serv, char *buf, const int buflen); 125int svc_xprt_names(struct svc_serv *serv, char *buf, const int buflen);
126void svc_add_new_perm_xprt(struct svc_serv *serv, struct svc_xprt *xprt);
127 127
128static inline void svc_xprt_get(struct svc_xprt *xprt) 128static inline void svc_xprt_get(struct svc_xprt *xprt)
129{ 129{
@@ -166,8 +166,7 @@ static inline size_t svc_addr_len(const struct sockaddr *sa)
166 case AF_INET6: 166 case AF_INET6:
167 return sizeof(struct sockaddr_in6); 167 return sizeof(struct sockaddr_in6);
168 } 168 }
169 169 BUG();
170 return 0;
171} 170}
172 171
173static inline unsigned short svc_xprt_local_port(const struct svc_xprt *xprt) 172static inline unsigned short svc_xprt_local_port(const struct svc_xprt *xprt)
diff --git a/include/linux/sunrpc/svcsock.h b/include/linux/sunrpc/svcsock.h
index cb4ac69e1f33..92ad02f0dcc0 100644
--- a/include/linux/sunrpc/svcsock.h
+++ b/include/linux/sunrpc/svcsock.h
@@ -39,9 +39,6 @@ int svc_recv(struct svc_rqst *, long);
39int svc_send(struct svc_rqst *); 39int svc_send(struct svc_rqst *);
40void svc_drop(struct svc_rqst *); 40void svc_drop(struct svc_rqst *);
41void svc_sock_update_bufs(struct svc_serv *serv); 41void svc_sock_update_bufs(struct svc_serv *serv);
42int svc_sock_names(struct svc_serv *serv, char *buf,
43 const size_t buflen,
44 const char *toclose);
45int svc_addsock(struct svc_serv *serv, const int fd, 42int svc_addsock(struct svc_serv *serv, const int fd,
46 char *name_return, const size_t len); 43 char *name_return, const size_t len);
47void svc_init_xprt_sock(void); 44void svc_init_xprt_sock(void);
diff --git a/include/uapi/linux/nfsd/Kbuild b/include/uapi/linux/nfsd/Kbuild
index aafaa5aa54d4..c11bc404053c 100644
--- a/include/uapi/linux/nfsd/Kbuild
+++ b/include/uapi/linux/nfsd/Kbuild
@@ -1 +1,6 @@
1# UAPI Header export list 1# UAPI Header export list
2header-y += cld.h
3header-y += debug.h
4header-y += export.h
5header-y += nfsfh.h
6header-y += stats.h
diff --git a/include/linux/nfsd/cld.h b/include/uapi/linux/nfsd/cld.h
index f14a9ab06f1f..f14a9ab06f1f 100644
--- a/include/linux/nfsd/cld.h
+++ b/include/uapi/linux/nfsd/cld.h
diff --git a/include/uapi/linux/nfsd/debug.h b/include/uapi/linux/nfsd/debug.h
new file mode 100644
index 000000000000..a6f453c740b8
--- /dev/null
+++ b/include/uapi/linux/nfsd/debug.h
@@ -0,0 +1,40 @@
1/*
2 * linux/include/linux/nfsd/debug.h
3 *
4 * Debugging-related stuff for nfsd
5 *
6 * Copyright (C) 1995 Olaf Kirch <okir@monad.swb.de>
7 */
8
9#ifndef _UAPILINUX_NFSD_DEBUG_H
10#define _UAPILINUX_NFSD_DEBUG_H
11
12#include <linux/sunrpc/debug.h>
13
14/*
15 * Enable debugging for nfsd.
16 * Requires RPC_DEBUG.
17 */
18#ifdef RPC_DEBUG
19# define NFSD_DEBUG 1
20#endif
21
22/*
23 * knfsd debug flags
24 */
25#define NFSDDBG_SOCK 0x0001
26#define NFSDDBG_FH 0x0002
27#define NFSDDBG_EXPORT 0x0004
28#define NFSDDBG_SVC 0x0008
29#define NFSDDBG_PROC 0x0010
30#define NFSDDBG_FILEOP 0x0020
31#define NFSDDBG_AUTH 0x0040
32#define NFSDDBG_REPCACHE 0x0080
33#define NFSDDBG_XDR 0x0100
34#define NFSDDBG_LOCKD 0x0200
35#define NFSDDBG_ALL 0x7FFF
36#define NFSDDBG_NOCHANGE 0xFFFF
37
38
39
40#endif /* _UAPILINUX_NFSD_DEBUG_H */
diff --git a/include/uapi/linux/nfsd/export.h b/include/uapi/linux/nfsd/export.h
new file mode 100644
index 000000000000..cf47c313794e
--- /dev/null
+++ b/include/uapi/linux/nfsd/export.h
@@ -0,0 +1,58 @@
1/*
2 * include/linux/nfsd/export.h
3 *
4 * Public declarations for NFS exports. The definitions for the
5 * syscall interface are in nfsctl.h
6 *
7 * Copyright (C) 1995-1997 Olaf Kirch <okir@monad.swb.de>
8 */
9
10#ifndef _UAPINFSD_EXPORT_H
11#define _UAPINFSD_EXPORT_H
12
13# include <linux/types.h>
14
15/*
16 * Important limits for the exports stuff.
17 */
18#define NFSCLNT_IDMAX 1024
19#define NFSCLNT_ADDRMAX 16
20#define NFSCLNT_KEYMAX 32
21
22/*
23 * Export flags.
24 */
25#define NFSEXP_READONLY 0x0001
26#define NFSEXP_INSECURE_PORT 0x0002
27#define NFSEXP_ROOTSQUASH 0x0004
28#define NFSEXP_ALLSQUASH 0x0008
29#define NFSEXP_ASYNC 0x0010
30#define NFSEXP_GATHERED_WRITES 0x0020
31/* 40 80 100 currently unused */
32#define NFSEXP_NOHIDE 0x0200
33#define NFSEXP_NOSUBTREECHECK 0x0400
34#define NFSEXP_NOAUTHNLM 0x0800 /* Don't authenticate NLM requests - just trust */
35#define NFSEXP_MSNFS 0x1000 /* do silly things that MS clients expect; no longer supported */
36#define NFSEXP_FSID 0x2000
37#define NFSEXP_CROSSMOUNT 0x4000
38#define NFSEXP_NOACL 0x8000 /* reserved for possible ACL related use */
39/*
40 * The NFSEXP_V4ROOT flag causes the kernel to give access only to NFSv4
41 * clients, and only to the single directory that is the root of the
42 * export; further lookup and readdir operations are treated as if every
43 * subdirectory was a mountpoint, and ignored if they are not themselves
44 * exported. This is used by nfsd and mountd to construct the NFSv4
45 * pseudofilesystem, which provides access only to paths leading to each
46 * exported filesystem.
47 */
48#define NFSEXP_V4ROOT 0x10000
49/* All flags that we claim to support. (Note we don't support NOACL.) */
50#define NFSEXP_ALLFLAGS 0x17E3F
51
52/* The flags that may vary depending on security flavor: */
53#define NFSEXP_SECINFO_FLAGS (NFSEXP_READONLY | NFSEXP_ROOTSQUASH \
54 | NFSEXP_ALLSQUASH \
55 | NFSEXP_INSECURE_PORT)
56
57
58#endif /* _UAPINFSD_EXPORT_H */
diff --git a/include/uapi/linux/nfsd/nfsfh.h b/include/uapi/linux/nfsd/nfsfh.h
new file mode 100644
index 000000000000..616e3b396476
--- /dev/null
+++ b/include/uapi/linux/nfsd/nfsfh.h
@@ -0,0 +1,122 @@
1/*
2 * include/linux/nfsd/nfsfh.h
3 *
4 * This file describes the layout of the file handles as passed
5 * over the wire.
6 *
7 * Earlier versions of knfsd used to sign file handles using keyed MD5
8 * or SHA. I've removed this code, because it doesn't give you more
9 * security than blocking external access to port 2049 on your firewall.
10 *
11 * Copyright (C) 1995, 1996, 1997 Olaf Kirch <okir@monad.swb.de>
12 */
13
14#ifndef _UAPI_LINUX_NFSD_FH_H
15#define _UAPI_LINUX_NFSD_FH_H
16
17#include <linux/types.h>
18#include <linux/nfs.h>
19#include <linux/nfs2.h>
20#include <linux/nfs3.h>
21#include <linux/nfs4.h>
22
23/*
24 * This is the old "dentry style" Linux NFSv2 file handle.
25 *
26 * The xino and xdev fields are currently used to transport the
27 * ino/dev of the exported inode.
28 */
29struct nfs_fhbase_old {
30 __u32 fb_dcookie; /* dentry cookie - always 0xfeebbaca */
31 __u32 fb_ino; /* our inode number */
32 __u32 fb_dirino; /* dir inode number, 0 for directories */
33 __u32 fb_dev; /* our device */
34 __u32 fb_xdev;
35 __u32 fb_xino;
36 __u32 fb_generation;
37};
38
39/*
40 * This is the new flexible, extensible style NFSv2/v3 file handle.
41 * by Neil Brown <neilb@cse.unsw.edu.au> - March 2000
42 *
43 * The file handle starts with a sequence of four-byte words.
44 * The first word contains a version number (1) and three descriptor bytes
45 * that tell how the remaining 3 variable length fields should be handled.
46 * These three bytes are auth_type, fsid_type and fileid_type.
47 *
48 * All four-byte values are in host-byte-order.
49 *
50 * The auth_type field specifies how the filehandle can be authenticated
51 * This might allow a file to be confirmed to be in a writable part of a
52 * filetree without checking the path from it up to the root.
53 * Current values:
54 * 0 - No authentication. fb_auth is 0 bytes long
55 * Possible future values:
56 * 1 - 4 bytes taken from MD5 hash of the remainer of the file handle
57 * prefixed by a secret and with the important export flags.
58 *
59 * The fsid_type identifies how the filesystem (or export point) is
60 * encoded.
61 * Current values:
62 * 0 - 4 byte device id (ms-2-bytes major, ls-2-bytes minor), 4byte inode number
63 * NOTE: we cannot use the kdev_t device id value, because kdev_t.h
64 * says we mustn't. We must break it up and reassemble.
65 * 1 - 4 byte user specified identifier
66 * 2 - 4 byte major, 4 byte minor, 4 byte inode number - DEPRECATED
67 * 3 - 4 byte device id, encoded for user-space, 4 byte inode number
68 * 4 - 4 byte inode number and 4 byte uuid
69 * 5 - 8 byte uuid
70 * 6 - 16 byte uuid
71 * 7 - 8 byte inode number and 16 byte uuid
72 *
73 * The fileid_type identified how the file within the filesystem is encoded.
74 * This is (will be) passed to, and set by, the underlying filesystem if it supports
75 * filehandle operations. The filesystem must not use the value '0' or '0xff' and may
76 * only use the values 1 and 2 as defined below:
77 * Current values:
78 * 0 - The root, or export point, of the filesystem. fb_fileid is 0 bytes.
79 * 1 - 32bit inode number, 32 bit generation number.
80 * 2 - 32bit inode number, 32 bit generation number, 32 bit parent directory inode number.
81 *
82 */
83struct nfs_fhbase_new {
84 __u8 fb_version; /* == 1, even => nfs_fhbase_old */
85 __u8 fb_auth_type;
86 __u8 fb_fsid_type;
87 __u8 fb_fileid_type;
88 __u32 fb_auth[1];
89/* __u32 fb_fsid[0]; floating */
90/* __u32 fb_fileid[0]; floating */
91};
92
93struct knfsd_fh {
94 unsigned int fh_size; /* significant for NFSv3.
95 * Points to the current size while building
96 * a new file handle
97 */
98 union {
99 struct nfs_fhbase_old fh_old;
100 __u32 fh_pad[NFS4_FHSIZE/4];
101 struct nfs_fhbase_new fh_new;
102 } fh_base;
103};
104
105#define ofh_dcookie fh_base.fh_old.fb_dcookie
106#define ofh_ino fh_base.fh_old.fb_ino
107#define ofh_dirino fh_base.fh_old.fb_dirino
108#define ofh_dev fh_base.fh_old.fb_dev
109#define ofh_xdev fh_base.fh_old.fb_xdev
110#define ofh_xino fh_base.fh_old.fb_xino
111#define ofh_generation fh_base.fh_old.fb_generation
112
113#define fh_version fh_base.fh_new.fb_version
114#define fh_fsid_type fh_base.fh_new.fb_fsid_type
115#define fh_auth_type fh_base.fh_new.fb_auth_type
116#define fh_fileid_type fh_base.fh_new.fb_fileid_type
117#define fh_auth fh_base.fh_new.fb_auth
118#define fh_fsid fh_base.fh_new.fb_auth
119
120
121
122#endif /* _UAPI_LINUX_NFSD_FH_H */
diff --git a/include/uapi/linux/nfsd/stats.h b/include/uapi/linux/nfsd/stats.h
new file mode 100644
index 000000000000..9fb7a0644263
--- /dev/null
+++ b/include/uapi/linux/nfsd/stats.h
@@ -0,0 +1,17 @@
1/*
2 * linux/include/linux/nfsd/stats.h
3 *
4 * Statistics for NFS server.
5 *
6 * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
7 */
8
9#ifndef _UAPILINUX_NFSD_STATS_H
10#define _UAPILINUX_NFSD_STATS_H
11
12#include <linux/nfs4.h>
13
14/* thread usage wraps very million seconds (approx one fortnight) */
15#define NFSD_USAGE_WRAP (HZ*1000000)
16
17#endif /* _UAPILINUX_NFSD_STATS_H */
diff --git a/include/uapi/linux/sunrpc/Kbuild b/include/uapi/linux/sunrpc/Kbuild
index aafaa5aa54d4..8e02e47c20fb 100644
--- a/include/uapi/linux/sunrpc/Kbuild
+++ b/include/uapi/linux/sunrpc/Kbuild
@@ -1 +1,2 @@
1# UAPI Header export list 1# UAPI Header export list
2header-y += debug.h
diff --git a/include/uapi/linux/sunrpc/debug.h b/include/uapi/linux/sunrpc/debug.h
new file mode 100644
index 000000000000..830e34493a8c
--- /dev/null
+++ b/include/uapi/linux/sunrpc/debug.h
@@ -0,0 +1,48 @@
1/*
2 * linux/include/linux/sunrpc/debug.h
3 *
4 * Debugging support for sunrpc module
5 *
6 * Copyright (C) 1996, Olaf Kirch <okir@monad.swb.de>
7 */
8
9#ifndef _UAPI_LINUX_SUNRPC_DEBUG_H_
10#define _UAPI_LINUX_SUNRPC_DEBUG_H_
11
12/*
13 * RPC debug facilities
14 */
15#define RPCDBG_XPRT 0x0001
16#define RPCDBG_CALL 0x0002
17#define RPCDBG_DEBUG 0x0004
18#define RPCDBG_NFS 0x0008
19#define RPCDBG_AUTH 0x0010
20#define RPCDBG_BIND 0x0020
21#define RPCDBG_SCHED 0x0040
22#define RPCDBG_TRANS 0x0080
23#define RPCDBG_SVCXPRT 0x0100
24#define RPCDBG_SVCDSP 0x0200
25#define RPCDBG_MISC 0x0400
26#define RPCDBG_CACHE 0x0800
27#define RPCDBG_ALL 0x7fff
28
29
30/*
31 * Declarations for the sysctl debug interface, which allows to read or
32 * change the debug flags for rpc, nfs, nfsd, and lockd. Since the sunrpc
33 * module currently registers its sysctl table dynamically, the sysctl path
34 * for module FOO is <CTL_SUNRPC, CTL_FOODEBUG>.
35 */
36
37enum {
38 CTL_RPCDEBUG = 1,
39 CTL_NFSDEBUG,
40 CTL_NFSDDEBUG,
41 CTL_NLMDEBUG,
42 CTL_SLOTTABLE_UDP,
43 CTL_SLOTTABLE_TCP,
44 CTL_MIN_RESVPORT,
45 CTL_MAX_RESVPORT,
46};
47
48#endif /* _UAPI_LINUX_SUNRPC_DEBUG_H_ */
diff --git a/net/sunrpc/svc_xprt.c b/net/sunrpc/svc_xprt.c
index bac973a31367..194d865fae72 100644
--- a/net/sunrpc/svc_xprt.c
+++ b/net/sunrpc/svc_xprt.c
@@ -208,6 +208,35 @@ static struct svc_xprt *__svc_xpo_create(struct svc_xprt_class *xcl,
208 return xcl->xcl_ops->xpo_create(serv, net, sap, len, flags); 208 return xcl->xcl_ops->xpo_create(serv, net, sap, len, flags);
209} 209}
210 210
211/*
212 * svc_xprt_received conditionally queues the transport for processing
213 * by another thread. The caller must hold the XPT_BUSY bit and must
214 * not thereafter touch transport data.
215 *
216 * Note: XPT_DATA only gets cleared when a read-attempt finds no (or
217 * insufficient) data.
218 */
219static void svc_xprt_received(struct svc_xprt *xprt)
220{
221 BUG_ON(!test_bit(XPT_BUSY, &xprt->xpt_flags));
222 /* As soon as we clear busy, the xprt could be closed and
223 * 'put', so we need a reference to call svc_xprt_enqueue with:
224 */
225 svc_xprt_get(xprt);
226 clear_bit(XPT_BUSY, &xprt->xpt_flags);
227 svc_xprt_enqueue(xprt);
228 svc_xprt_put(xprt);
229}
230
231void svc_add_new_perm_xprt(struct svc_serv *serv, struct svc_xprt *new)
232{
233 clear_bit(XPT_TEMP, &new->xpt_flags);
234 spin_lock_bh(&serv->sv_lock);
235 list_add(&new->xpt_list, &serv->sv_permsocks);
236 spin_unlock_bh(&serv->sv_lock);
237 svc_xprt_received(new);
238}
239
211int svc_create_xprt(struct svc_serv *serv, const char *xprt_name, 240int svc_create_xprt(struct svc_serv *serv, const char *xprt_name,
212 struct net *net, const int family, 241 struct net *net, const int family,
213 const unsigned short port, int flags) 242 const unsigned short port, int flags)
@@ -232,13 +261,8 @@ int svc_create_xprt(struct svc_serv *serv, const char *xprt_name,
232 module_put(xcl->xcl_owner); 261 module_put(xcl->xcl_owner);
233 return PTR_ERR(newxprt); 262 return PTR_ERR(newxprt);
234 } 263 }
235 264 svc_add_new_perm_xprt(serv, newxprt);
236 clear_bit(XPT_TEMP, &newxprt->xpt_flags);
237 spin_lock_bh(&serv->sv_lock);
238 list_add(&newxprt->xpt_list, &serv->sv_permsocks);
239 spin_unlock_bh(&serv->sv_lock);
240 newport = svc_xprt_local_port(newxprt); 265 newport = svc_xprt_local_port(newxprt);
241 clear_bit(XPT_BUSY, &newxprt->xpt_flags);
242 return newport; 266 return newport;
243 } 267 }
244 err: 268 err:
@@ -394,27 +418,6 @@ static struct svc_xprt *svc_xprt_dequeue(struct svc_pool *pool)
394 return xprt; 418 return xprt;
395} 419}
396 420
397/*
398 * svc_xprt_received conditionally queues the transport for processing
399 * by another thread. The caller must hold the XPT_BUSY bit and must
400 * not thereafter touch transport data.
401 *
402 * Note: XPT_DATA only gets cleared when a read-attempt finds no (or
403 * insufficient) data.
404 */
405void svc_xprt_received(struct svc_xprt *xprt)
406{
407 BUG_ON(!test_bit(XPT_BUSY, &xprt->xpt_flags));
408 /* As soon as we clear busy, the xprt could be closed and
409 * 'put', so we need a reference to call svc_xprt_enqueue with:
410 */
411 svc_xprt_get(xprt);
412 clear_bit(XPT_BUSY, &xprt->xpt_flags);
413 svc_xprt_enqueue(xprt);
414 svc_xprt_put(xprt);
415}
416EXPORT_SYMBOL_GPL(svc_xprt_received);
417
418/** 421/**
419 * svc_reserve - change the space reserved for the reply to a request. 422 * svc_reserve - change the space reserved for the reply to a request.
420 * @rqstp: The request in question 423 * @rqstp: The request in question
@@ -565,33 +568,12 @@ static void svc_check_conn_limits(struct svc_serv *serv)
565 } 568 }
566} 569}
567 570
568/* 571int svc_alloc_arg(struct svc_rqst *rqstp)
569 * Receive the next request on any transport. This code is carefully
570 * organised not to touch any cachelines in the shared svc_serv
571 * structure, only cachelines in the local svc_pool.
572 */
573int svc_recv(struct svc_rqst *rqstp, long timeout)
574{ 572{
575 struct svc_xprt *xprt = NULL; 573 struct svc_serv *serv = rqstp->rq_server;
576 struct svc_serv *serv = rqstp->rq_server; 574 struct xdr_buf *arg;
577 struct svc_pool *pool = rqstp->rq_pool; 575 int pages;
578 int len, i; 576 int i;
579 int pages;
580 struct xdr_buf *arg;
581 DECLARE_WAITQUEUE(wait, current);
582 long time_left;
583
584 dprintk("svc: server %p waiting for data (to = %ld)\n",
585 rqstp, timeout);
586
587 if (rqstp->rq_xprt)
588 printk(KERN_ERR
589 "svc_recv: service %p, transport not NULL!\n",
590 rqstp);
591 if (waitqueue_active(&rqstp->rq_wait))
592 printk(KERN_ERR
593 "svc_recv: service %p, wait queue active!\n",
594 rqstp);
595 577
596 /* now allocate needed pages. If we get a failure, sleep briefly */ 578 /* now allocate needed pages. If we get a failure, sleep briefly */
597 pages = (serv->sv_max_mesg + PAGE_SIZE) / PAGE_SIZE; 579 pages = (serv->sv_max_mesg + PAGE_SIZE) / PAGE_SIZE;
@@ -621,11 +603,15 @@ int svc_recv(struct svc_rqst *rqstp, long timeout)
621 arg->page_len = (pages-2)*PAGE_SIZE; 603 arg->page_len = (pages-2)*PAGE_SIZE;
622 arg->len = (pages-1)*PAGE_SIZE; 604 arg->len = (pages-1)*PAGE_SIZE;
623 arg->tail[0].iov_len = 0; 605 arg->tail[0].iov_len = 0;
606 return 0;
607}
624 608
625 try_to_freeze(); 609struct svc_xprt *svc_get_next_xprt(struct svc_rqst *rqstp, long timeout)
626 cond_resched(); 610{
627 if (signalled() || kthread_should_stop()) 611 struct svc_xprt *xprt;
628 return -EINTR; 612 struct svc_pool *pool = rqstp->rq_pool;
613 DECLARE_WAITQUEUE(wait, current);
614 long time_left;
629 615
630 /* Normally we will wait up to 5 seconds for any required 616 /* Normally we will wait up to 5 seconds for any required
631 * cache information to be provided. 617 * cache information to be provided.
@@ -663,7 +649,7 @@ int svc_recv(struct svc_rqst *rqstp, long timeout)
663 if (kthread_should_stop()) { 649 if (kthread_should_stop()) {
664 set_current_state(TASK_RUNNING); 650 set_current_state(TASK_RUNNING);
665 spin_unlock_bh(&pool->sp_lock); 651 spin_unlock_bh(&pool->sp_lock);
666 return -EINTR; 652 return ERR_PTR(-EINTR);
667 } 653 }
668 654
669 add_wait_queue(&rqstp->rq_wait, &wait); 655 add_wait_queue(&rqstp->rq_wait, &wait);
@@ -684,48 +670,58 @@ int svc_recv(struct svc_rqst *rqstp, long timeout)
684 spin_unlock_bh(&pool->sp_lock); 670 spin_unlock_bh(&pool->sp_lock);
685 dprintk("svc: server %p, no data yet\n", rqstp); 671 dprintk("svc: server %p, no data yet\n", rqstp);
686 if (signalled() || kthread_should_stop()) 672 if (signalled() || kthread_should_stop())
687 return -EINTR; 673 return ERR_PTR(-EINTR);
688 else 674 else
689 return -EAGAIN; 675 return ERR_PTR(-EAGAIN);
690 } 676 }
691 } 677 }
692 spin_unlock_bh(&pool->sp_lock); 678 spin_unlock_bh(&pool->sp_lock);
679 return xprt;
680}
681
682void svc_add_new_temp_xprt(struct svc_serv *serv, struct svc_xprt *newxpt)
683{
684 spin_lock_bh(&serv->sv_lock);
685 set_bit(XPT_TEMP, &newxpt->xpt_flags);
686 list_add(&newxpt->xpt_list, &serv->sv_tempsocks);
687 serv->sv_tmpcnt++;
688 if (serv->sv_temptimer.function == NULL) {
689 /* setup timer to age temp transports */
690 setup_timer(&serv->sv_temptimer, svc_age_temp_xprts,
691 (unsigned long)serv);
692 mod_timer(&serv->sv_temptimer,
693 jiffies + svc_conn_age_period * HZ);
694 }
695 spin_unlock_bh(&serv->sv_lock);
696 svc_xprt_received(newxpt);
697}
698
699static int svc_handle_xprt(struct svc_rqst *rqstp, struct svc_xprt *xprt)
700{
701 struct svc_serv *serv = rqstp->rq_server;
702 int len = 0;
693 703
694 len = 0;
695 if (test_bit(XPT_CLOSE, &xprt->xpt_flags)) { 704 if (test_bit(XPT_CLOSE, &xprt->xpt_flags)) {
696 dprintk("svc_recv: found XPT_CLOSE\n"); 705 dprintk("svc_recv: found XPT_CLOSE\n");
697 svc_delete_xprt(xprt); 706 svc_delete_xprt(xprt);
698 /* Leave XPT_BUSY set on the dead xprt: */ 707 /* Leave XPT_BUSY set on the dead xprt: */
699 goto out; 708 return 0;
700 } 709 }
701 if (test_bit(XPT_LISTENER, &xprt->xpt_flags)) { 710 if (test_bit(XPT_LISTENER, &xprt->xpt_flags)) {
702 struct svc_xprt *newxpt; 711 struct svc_xprt *newxpt;
712 /*
713 * We know this module_get will succeed because the
714 * listener holds a reference too
715 */
716 __module_get(xprt->xpt_class->xcl_owner);
717 svc_check_conn_limits(xprt->xpt_server);
703 newxpt = xprt->xpt_ops->xpo_accept(xprt); 718 newxpt = xprt->xpt_ops->xpo_accept(xprt);
704 if (newxpt) { 719 if (newxpt)
705 /* 720 svc_add_new_temp_xprt(serv, newxpt);
706 * We know this module_get will succeed because the
707 * listener holds a reference too
708 */
709 __module_get(newxpt->xpt_class->xcl_owner);
710 svc_check_conn_limits(xprt->xpt_server);
711 spin_lock_bh(&serv->sv_lock);
712 set_bit(XPT_TEMP, &newxpt->xpt_flags);
713 list_add(&newxpt->xpt_list, &serv->sv_tempsocks);
714 serv->sv_tmpcnt++;
715 if (serv->sv_temptimer.function == NULL) {
716 /* setup timer to age temp transports */
717 setup_timer(&serv->sv_temptimer,
718 svc_age_temp_xprts,
719 (unsigned long)serv);
720 mod_timer(&serv->sv_temptimer,
721 jiffies + svc_conn_age_period * HZ);
722 }
723 spin_unlock_bh(&serv->sv_lock);
724 svc_xprt_received(newxpt);
725 }
726 } else if (xprt->xpt_ops->xpo_has_wspace(xprt)) { 721 } else if (xprt->xpt_ops->xpo_has_wspace(xprt)) {
722 /* XPT_DATA|XPT_DEFERRED case: */
727 dprintk("svc: server %p, pool %u, transport %p, inuse=%d\n", 723 dprintk("svc: server %p, pool %u, transport %p, inuse=%d\n",
728 rqstp, pool->sp_id, xprt, 724 rqstp, rqstp->rq_pool->sp_id, xprt,
729 atomic_read(&xprt->xpt_ref.refcount)); 725 atomic_read(&xprt->xpt_ref.refcount));
730 rqstp->rq_deferred = svc_deferred_dequeue(xprt); 726 rqstp->rq_deferred = svc_deferred_dequeue(xprt);
731 if (rqstp->rq_deferred) 727 if (rqstp->rq_deferred)
@@ -736,10 +732,51 @@ int svc_recv(struct svc_rqst *rqstp, long timeout)
736 rqstp->rq_reserved = serv->sv_max_mesg; 732 rqstp->rq_reserved = serv->sv_max_mesg;
737 atomic_add(rqstp->rq_reserved, &xprt->xpt_reserved); 733 atomic_add(rqstp->rq_reserved, &xprt->xpt_reserved);
738 } 734 }
735 /* clear XPT_BUSY: */
739 svc_xprt_received(xprt); 736 svc_xprt_received(xprt);
737 return len;
738}
739
740/*
741 * Receive the next request on any transport. This code is carefully
742 * organised not to touch any cachelines in the shared svc_serv
743 * structure, only cachelines in the local svc_pool.
744 */
745int svc_recv(struct svc_rqst *rqstp, long timeout)
746{
747 struct svc_xprt *xprt = NULL;
748 struct svc_serv *serv = rqstp->rq_server;
749 int len, err;
750
751 dprintk("svc: server %p waiting for data (to = %ld)\n",
752 rqstp, timeout);
753
754 if (rqstp->rq_xprt)
755 printk(KERN_ERR
756 "svc_recv: service %p, transport not NULL!\n",
757 rqstp);
758 if (waitqueue_active(&rqstp->rq_wait))
759 printk(KERN_ERR
760 "svc_recv: service %p, wait queue active!\n",
761 rqstp);
762
763 err = svc_alloc_arg(rqstp);
764 if (err)
765 return err;
766
767 try_to_freeze();
768 cond_resched();
769 if (signalled() || kthread_should_stop())
770 return -EINTR;
771
772 xprt = svc_get_next_xprt(rqstp, timeout);
773 if (IS_ERR(xprt))
774 return PTR_ERR(xprt);
775
776 len = svc_handle_xprt(rqstp, xprt);
740 777
741 /* No data, incomplete (TCP) read, or accept() */ 778 /* No data, incomplete (TCP) read, or accept() */
742 if (len == 0 || len == -EAGAIN) 779 if (len <= 0)
743 goto out; 780 goto out;
744 781
745 clear_bit(XPT_OLD, &xprt->xpt_flags); 782 clear_bit(XPT_OLD, &xprt->xpt_flags);
@@ -917,16 +954,18 @@ void svc_close_xprt(struct svc_xprt *xprt)
917} 954}
918EXPORT_SYMBOL_GPL(svc_close_xprt); 955EXPORT_SYMBOL_GPL(svc_close_xprt);
919 956
920static void svc_close_list(struct list_head *xprt_list, struct net *net) 957static void svc_close_list(struct svc_serv *serv, struct list_head *xprt_list, struct net *net)
921{ 958{
922 struct svc_xprt *xprt; 959 struct svc_xprt *xprt;
923 960
961 spin_lock(&serv->sv_lock);
924 list_for_each_entry(xprt, xprt_list, xpt_list) { 962 list_for_each_entry(xprt, xprt_list, xpt_list) {
925 if (xprt->xpt_net != net) 963 if (xprt->xpt_net != net)
926 continue; 964 continue;
927 set_bit(XPT_CLOSE, &xprt->xpt_flags); 965 set_bit(XPT_CLOSE, &xprt->xpt_flags);
928 set_bit(XPT_BUSY, &xprt->xpt_flags); 966 set_bit(XPT_BUSY, &xprt->xpt_flags);
929 } 967 }
968 spin_unlock(&serv->sv_lock);
930} 969}
931 970
932static void svc_clear_pools(struct svc_serv *serv, struct net *net) 971static void svc_clear_pools(struct svc_serv *serv, struct net *net)
@@ -949,24 +988,28 @@ static void svc_clear_pools(struct svc_serv *serv, struct net *net)
949 } 988 }
950} 989}
951 990
952static void svc_clear_list(struct list_head *xprt_list, struct net *net) 991static void svc_clear_list(struct svc_serv *serv, struct list_head *xprt_list, struct net *net)
953{ 992{
954 struct svc_xprt *xprt; 993 struct svc_xprt *xprt;
955 struct svc_xprt *tmp; 994 struct svc_xprt *tmp;
995 LIST_HEAD(victims);
956 996
997 spin_lock(&serv->sv_lock);
957 list_for_each_entry_safe(xprt, tmp, xprt_list, xpt_list) { 998 list_for_each_entry_safe(xprt, tmp, xprt_list, xpt_list) {
958 if (xprt->xpt_net != net) 999 if (xprt->xpt_net != net)
959 continue; 1000 continue;
960 svc_delete_xprt(xprt); 1001 list_move(&xprt->xpt_list, &victims);
961 } 1002 }
962 list_for_each_entry(xprt, xprt_list, xpt_list) 1003 spin_unlock(&serv->sv_lock);
963 BUG_ON(xprt->xpt_net == net); 1004
1005 list_for_each_entry_safe(xprt, tmp, &victims, xpt_list)
1006 svc_delete_xprt(xprt);
964} 1007}
965 1008
966void svc_close_net(struct svc_serv *serv, struct net *net) 1009void svc_close_net(struct svc_serv *serv, struct net *net)
967{ 1010{
968 svc_close_list(&serv->sv_tempsocks, net); 1011 svc_close_list(serv, &serv->sv_tempsocks, net);
969 svc_close_list(&serv->sv_permsocks, net); 1012 svc_close_list(serv, &serv->sv_permsocks, net);
970 1013
971 svc_clear_pools(serv, net); 1014 svc_clear_pools(serv, net);
972 /* 1015 /*
@@ -974,8 +1017,8 @@ void svc_close_net(struct svc_serv *serv, struct net *net)
974 * svc_xprt_enqueue will not add new entries without taking the 1017 * svc_xprt_enqueue will not add new entries without taking the
975 * sp_lock and checking XPT_BUSY. 1018 * sp_lock and checking XPT_BUSY.
976 */ 1019 */
977 svc_clear_list(&serv->sv_tempsocks, net); 1020 svc_clear_list(serv, &serv->sv_tempsocks, net);
978 svc_clear_list(&serv->sv_permsocks, net); 1021 svc_clear_list(serv, &serv->sv_permsocks, net);
979} 1022}
980 1023
981/* 1024/*
diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c
index 998aa8c1807c..03827cef1fa7 100644
--- a/net/sunrpc/svcsock.c
+++ b/net/sunrpc/svcsock.c
@@ -59,7 +59,7 @@
59 59
60 60
61static struct svc_sock *svc_setup_socket(struct svc_serv *, struct socket *, 61static struct svc_sock *svc_setup_socket(struct svc_serv *, struct socket *,
62 int *errp, int flags); 62 int flags);
63static void svc_udp_data_ready(struct sock *, int); 63static void svc_udp_data_ready(struct sock *, int);
64static int svc_udp_recvfrom(struct svc_rqst *); 64static int svc_udp_recvfrom(struct svc_rqst *);
65static int svc_udp_sendto(struct svc_rqst *); 65static int svc_udp_sendto(struct svc_rqst *);
@@ -305,57 +305,6 @@ static int svc_one_sock_name(struct svc_sock *svsk, char *buf, int remaining)
305 return len; 305 return len;
306} 306}
307 307
308/**
309 * svc_sock_names - construct a list of listener names in a string
310 * @serv: pointer to RPC service
311 * @buf: pointer to a buffer to fill in with socket names
312 * @buflen: size of the buffer to be filled
313 * @toclose: pointer to '\0'-terminated C string containing the name
314 * of a listener to be closed
315 *
316 * Fills in @buf with a '\n'-separated list of names of listener
317 * sockets. If @toclose is not NULL, the socket named by @toclose
318 * is closed, and is not included in the output list.
319 *
320 * Returns positive length of the socket name string, or a negative
321 * errno value on error.
322 */
323int svc_sock_names(struct svc_serv *serv, char *buf, const size_t buflen,
324 const char *toclose)
325{
326 struct svc_sock *svsk, *closesk = NULL;
327 int len = 0;
328
329 if (!serv)
330 return 0;
331
332 spin_lock_bh(&serv->sv_lock);
333 list_for_each_entry(svsk, &serv->sv_permsocks, sk_xprt.xpt_list) {
334 int onelen = svc_one_sock_name(svsk, buf + len, buflen - len);
335 if (onelen < 0) {
336 len = onelen;
337 break;
338 }
339 if (toclose && strcmp(toclose, buf + len) == 0) {
340 closesk = svsk;
341 svc_xprt_get(&closesk->sk_xprt);
342 } else
343 len += onelen;
344 }
345 spin_unlock_bh(&serv->sv_lock);
346
347 if (closesk) {
348 /* Should unregister with portmap, but you cannot
349 * unregister just one protocol...
350 */
351 svc_close_xprt(&closesk->sk_xprt);
352 svc_xprt_put(&closesk->sk_xprt);
353 } else if (toclose)
354 return -ENOENT;
355 return len;
356}
357EXPORT_SYMBOL_GPL(svc_sock_names);
358
359/* 308/*
360 * Check input queue length 309 * Check input queue length
361 */ 310 */
@@ -598,11 +547,9 @@ static int svc_udp_recvfrom(struct svc_rqst *rqstp)
598 dprintk("svc: recvfrom returned error %d\n", -err); 547 dprintk("svc: recvfrom returned error %d\n", -err);
599 set_bit(XPT_DATA, &svsk->sk_xprt.xpt_flags); 548 set_bit(XPT_DATA, &svsk->sk_xprt.xpt_flags);
600 } 549 }
601 return -EAGAIN; 550 return 0;
602 } 551 }
603 len = svc_addr_len(svc_addr(rqstp)); 552 len = svc_addr_len(svc_addr(rqstp));
604 if (len == 0)
605 return -EAFNOSUPPORT;
606 rqstp->rq_addrlen = len; 553 rqstp->rq_addrlen = len;
607 if (skb->tstamp.tv64 == 0) { 554 if (skb->tstamp.tv64 == 0) {
608 skb->tstamp = ktime_get_real(); 555 skb->tstamp = ktime_get_real();
@@ -620,10 +567,7 @@ static int svc_udp_recvfrom(struct svc_rqst *rqstp)
620 if (!svc_udp_get_dest_address(rqstp, cmh)) { 567 if (!svc_udp_get_dest_address(rqstp, cmh)) {
621 net_warn_ratelimited("svc: received unknown control message %d/%d; dropping RPC reply datagram\n", 568 net_warn_ratelimited("svc: received unknown control message %d/%d; dropping RPC reply datagram\n",
622 cmh->cmsg_level, cmh->cmsg_type); 569 cmh->cmsg_level, cmh->cmsg_type);
623out_free: 570 goto out_free;
624 trace_kfree_skb(skb, svc_udp_recvfrom);
625 skb_free_datagram_locked(svsk->sk_sk, skb);
626 return 0;
627 } 571 }
628 rqstp->rq_daddrlen = svc_addr_len(svc_daddr(rqstp)); 572 rqstp->rq_daddrlen = svc_addr_len(svc_daddr(rqstp));
629 573
@@ -662,6 +606,10 @@ out_free:
662 serv->sv_stats->netudpcnt++; 606 serv->sv_stats->netudpcnt++;
663 607
664 return len; 608 return len;
609out_free:
610 trace_kfree_skb(skb, svc_udp_recvfrom);
611 skb_free_datagram_locked(svsk->sk_sk, skb);
612 return 0;
665} 613}
666 614
667static int 615static int
@@ -900,8 +848,9 @@ static struct svc_xprt *svc_tcp_accept(struct svc_xprt *xprt)
900 */ 848 */
901 newsock->sk->sk_sndtimeo = HZ*30; 849 newsock->sk->sk_sndtimeo = HZ*30;
902 850
903 if (!(newsvsk = svc_setup_socket(serv, newsock, &err, 851 newsvsk = svc_setup_socket(serv, newsock,
904 (SVC_SOCK_ANONYMOUS | SVC_SOCK_TEMPORARY)))) 852 (SVC_SOCK_ANONYMOUS | SVC_SOCK_TEMPORARY));
853 if (IS_ERR(newsvsk))
905 goto failed; 854 goto failed;
906 svc_xprt_set_remote(&newsvsk->sk_xprt, sin, slen); 855 svc_xprt_set_remote(&newsvsk->sk_xprt, sin, slen);
907 err = kernel_getsockname(newsock, sin, &slen); 856 err = kernel_getsockname(newsock, sin, &slen);
@@ -1174,13 +1123,13 @@ error:
1174 if (len != -EAGAIN) 1123 if (len != -EAGAIN)
1175 goto err_other; 1124 goto err_other;
1176 dprintk("RPC: TCP recvfrom got EAGAIN\n"); 1125 dprintk("RPC: TCP recvfrom got EAGAIN\n");
1177 return -EAGAIN; 1126 return 0;
1178err_other: 1127err_other:
1179 printk(KERN_NOTICE "%s: recvfrom returned errno %d\n", 1128 printk(KERN_NOTICE "%s: recvfrom returned errno %d\n",
1180 svsk->sk_xprt.xpt_server->sv_name, -len); 1129 svsk->sk_xprt.xpt_server->sv_name, -len);
1181 set_bit(XPT_CLOSE, &svsk->sk_xprt.xpt_flags); 1130 set_bit(XPT_CLOSE, &svsk->sk_xprt.xpt_flags);
1182err_noclose: 1131err_noclose:
1183 return -EAGAIN; /* record not complete */ 1132 return 0; /* record not complete */
1184} 1133}
1185 1134
1186/* 1135/*
@@ -1383,29 +1332,29 @@ EXPORT_SYMBOL_GPL(svc_sock_update_bufs);
1383 */ 1332 */
1384static struct svc_sock *svc_setup_socket(struct svc_serv *serv, 1333static struct svc_sock *svc_setup_socket(struct svc_serv *serv,
1385 struct socket *sock, 1334 struct socket *sock,
1386 int *errp, int flags) 1335 int flags)
1387{ 1336{
1388 struct svc_sock *svsk; 1337 struct svc_sock *svsk;
1389 struct sock *inet; 1338 struct sock *inet;
1390 int pmap_register = !(flags & SVC_SOCK_ANONYMOUS); 1339 int pmap_register = !(flags & SVC_SOCK_ANONYMOUS);
1340 int err = 0;
1391 1341
1392 dprintk("svc: svc_setup_socket %p\n", sock); 1342 dprintk("svc: svc_setup_socket %p\n", sock);
1393 if (!(svsk = kzalloc(sizeof(*svsk), GFP_KERNEL))) { 1343 svsk = kzalloc(sizeof(*svsk), GFP_KERNEL);
1394 *errp = -ENOMEM; 1344 if (!svsk)
1395 return NULL; 1345 return ERR_PTR(-ENOMEM);
1396 }
1397 1346
1398 inet = sock->sk; 1347 inet = sock->sk;
1399 1348
1400 /* Register socket with portmapper */ 1349 /* Register socket with portmapper */
1401 if (*errp >= 0 && pmap_register) 1350 if (pmap_register)
1402 *errp = svc_register(serv, sock_net(sock->sk), inet->sk_family, 1351 err = svc_register(serv, sock_net(sock->sk), inet->sk_family,
1403 inet->sk_protocol, 1352 inet->sk_protocol,
1404 ntohs(inet_sk(inet)->inet_sport)); 1353 ntohs(inet_sk(inet)->inet_sport));
1405 1354
1406 if (*errp < 0) { 1355 if (err < 0) {
1407 kfree(svsk); 1356 kfree(svsk);
1408 return NULL; 1357 return ERR_PTR(err);
1409 } 1358 }
1410 1359
1411 inet->sk_user_data = svsk; 1360 inet->sk_user_data = svsk;
@@ -1450,42 +1399,38 @@ int svc_addsock(struct svc_serv *serv, const int fd, char *name_return,
1450 int err = 0; 1399 int err = 0;
1451 struct socket *so = sockfd_lookup(fd, &err); 1400 struct socket *so = sockfd_lookup(fd, &err);
1452 struct svc_sock *svsk = NULL; 1401 struct svc_sock *svsk = NULL;
1402 struct sockaddr_storage addr;
1403 struct sockaddr *sin = (struct sockaddr *)&addr;
1404 int salen;
1453 1405
1454 if (!so) 1406 if (!so)
1455 return err; 1407 return err;
1408 err = -EAFNOSUPPORT;
1456 if ((so->sk->sk_family != PF_INET) && (so->sk->sk_family != PF_INET6)) 1409 if ((so->sk->sk_family != PF_INET) && (so->sk->sk_family != PF_INET6))
1457 err = -EAFNOSUPPORT; 1410 goto out;
1458 else if (so->sk->sk_protocol != IPPROTO_TCP && 1411 err = -EPROTONOSUPPORT;
1412 if (so->sk->sk_protocol != IPPROTO_TCP &&
1459 so->sk->sk_protocol != IPPROTO_UDP) 1413 so->sk->sk_protocol != IPPROTO_UDP)
1460 err = -EPROTONOSUPPORT; 1414 goto out;
1461 else if (so->state > SS_UNCONNECTED) 1415 err = -EISCONN;
1462 err = -EISCONN; 1416 if (so->state > SS_UNCONNECTED)
1463 else { 1417 goto out;
1464 if (!try_module_get(THIS_MODULE)) 1418 err = -ENOENT;
1465 err = -ENOENT; 1419 if (!try_module_get(THIS_MODULE))
1466 else 1420 goto out;
1467 svsk = svc_setup_socket(serv, so, &err, 1421 svsk = svc_setup_socket(serv, so, SVC_SOCK_DEFAULTS);
1468 SVC_SOCK_DEFAULTS); 1422 if (IS_ERR(svsk)) {
1469 if (svsk) { 1423 module_put(THIS_MODULE);
1470 struct sockaddr_storage addr; 1424 err = PTR_ERR(svsk);
1471 struct sockaddr *sin = (struct sockaddr *)&addr; 1425 goto out;
1472 int salen;
1473 if (kernel_getsockname(svsk->sk_sock, sin, &salen) == 0)
1474 svc_xprt_set_local(&svsk->sk_xprt, sin, salen);
1475 clear_bit(XPT_TEMP, &svsk->sk_xprt.xpt_flags);
1476 spin_lock_bh(&serv->sv_lock);
1477 list_add(&svsk->sk_xprt.xpt_list, &serv->sv_permsocks);
1478 spin_unlock_bh(&serv->sv_lock);
1479 svc_xprt_received(&svsk->sk_xprt);
1480 err = 0;
1481 } else
1482 module_put(THIS_MODULE);
1483 }
1484 if (err) {
1485 sockfd_put(so);
1486 return err;
1487 } 1426 }
1427 if (kernel_getsockname(svsk->sk_sock, sin, &salen) == 0)
1428 svc_xprt_set_local(&svsk->sk_xprt, sin, salen);
1429 svc_add_new_perm_xprt(serv, &svsk->sk_xprt);
1488 return svc_one_sock_name(svsk, name_return, len); 1430 return svc_one_sock_name(svsk, name_return, len);
1431out:
1432 sockfd_put(so);
1433 return err;
1489} 1434}
1490EXPORT_SYMBOL_GPL(svc_addsock); 1435EXPORT_SYMBOL_GPL(svc_addsock);
1491 1436
@@ -1563,11 +1508,13 @@ static struct svc_xprt *svc_create_socket(struct svc_serv *serv,
1563 goto bummer; 1508 goto bummer;
1564 } 1509 }
1565 1510
1566 if ((svsk = svc_setup_socket(serv, sock, &error, flags)) != NULL) { 1511 svsk = svc_setup_socket(serv, sock, flags);
1567 svc_xprt_set_local(&svsk->sk_xprt, newsin, newlen); 1512 if (IS_ERR(svsk)) {
1568 return (struct svc_xprt *)svsk; 1513 error = PTR_ERR(svsk);
1514 goto bummer;
1569 } 1515 }
1570 1516 svc_xprt_set_local(&svsk->sk_xprt, newsin, newlen);
1517 return (struct svc_xprt *)svsk;
1571bummer: 1518bummer:
1572 dprintk("svc: svc_create_socket error = %d\n", -error); 1519 dprintk("svc: svc_create_socket error = %d\n", -error);
1573 sock_release(sock); 1520 sock_release(sock);
diff --git a/net/sunrpc/xprtrdma/svc_rdma_transport.c b/net/sunrpc/xprtrdma/svc_rdma_transport.c
index 73b428bef598..62e4f9bcc387 100644
--- a/net/sunrpc/xprtrdma/svc_rdma_transport.c
+++ b/net/sunrpc/xprtrdma/svc_rdma_transport.c
@@ -578,10 +578,6 @@ static void handle_connect_req(struct rdma_cm_id *new_cma_id, size_t client_ird)
578 list_add_tail(&newxprt->sc_accept_q, &listen_xprt->sc_accept_q); 578 list_add_tail(&newxprt->sc_accept_q, &listen_xprt->sc_accept_q);
579 spin_unlock_bh(&listen_xprt->sc_lock); 579 spin_unlock_bh(&listen_xprt->sc_lock);
580 580
581 /*
582 * Can't use svc_xprt_received here because we are not on a
583 * rqstp thread
584 */
585 set_bit(XPT_CONN, &listen_xprt->sc_xprt.xpt_flags); 581 set_bit(XPT_CONN, &listen_xprt->sc_xprt.xpt_flags);
586 svc_xprt_enqueue(&listen_xprt->sc_xprt); 582 svc_xprt_enqueue(&listen_xprt->sc_xprt);
587} 583}