diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-10-12 21:53:54 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-10-12 21:53:54 -0400 |
commit | bd81ccea8558daab570d70d2c23746413f26cecf (patch) | |
tree | a3a75dde2dc3cf26c74353b21792da30d65d7c13 | |
parent | 98260daa184c4a171834463cf85ab3a2c509d983 (diff) | |
parent | a9ca4043d074509b9d15003fbcb068d3cdae85a4 (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
...
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 @@ | |||
1 | Administrative interfaces for nfsd | ||
2 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ||
3 | |||
4 | Note that normally these interfaces are used only by the utilities in | ||
5 | nfs-utils. | ||
6 | |||
7 | nfsd is controlled mainly by pseudofiles under the "nfsd" filesystem, | ||
8 | which is normally mounted at /proc/fs/nfsd/. | ||
9 | |||
10 | The server is always started by the first write of a nonzero value to | ||
11 | nfsd/threads. | ||
12 | |||
13 | Before doing that, NFSD can be told which sockets to listen on by | ||
14 | writing 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 | |||
21 | If nfsd is started without doing any of these, then it will create one | ||
22 | udp and one tcp listener at port 2049 (see nfsd_init_socks). | ||
23 | |||
24 | On startup, nfsd and lockd grace periods start. | ||
25 | |||
26 | nfsd is shut down by a write of 0 to nfsd/threads. All locks and state | ||
27 | are thrown away at that point. | ||
28 | |||
29 | Between startup and shutdown, the number of threads may be adjusted up | ||
30 | or down by additional writes to nfsd/threads or by writes to | ||
31 | nfsd/pool_threads. | ||
32 | |||
33 | For more detail about files under nfsd/ and what they control, see | ||
34 | fs/nfsd/nfsctl.c; most of them have detailed comments. | ||
35 | |||
36 | Implementation notes | ||
37 | ^^^^^^^^^^^^^^^^^^^^ | ||
38 | |||
39 | Note that the rpc server requires the caller to serialize addition and | ||
40 | removal of listening sockets, and startup and shutdown of the server. | ||
41 | For 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) | |||
126 | static int | 126 | static int |
127 | lockd(void *vrqstp) | 127 | lockd(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); | |||
1289 | void lease_get_mtime(struct inode *inode, struct timespec *time) | 1289 | void 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: | |||
72 | static int | 72 | static int |
73 | nfs4_callback_svc(void *vrqstp) | 73 | nfs4_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 | */ |
221 | int | 221 | static int nfsaclsvc_encode_voidres(struct svc_rqst *rqstp, __be32 *p, void *dummy) |
222 | nfsaclsvc_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 | ||
1061 | static struct nfsd4_operation nfsd4_ops[]; | 1061 | static 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 | ||
761 | static struct nfsd4_session *alloc_session(int slotsize, int numslots) | 761 | static 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 | ||
855 | static __be32 nfsd4_new_conn(struct svc_rqst *rqstp, struct nfsd4_session *ses, u32 dir) | 855 | static 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 | ||
876 | static __be32 nfsd4_new_conn_from_crses(struct svc_rqst *rqstp, struct nfsd4_session *ses) | 870 | static 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 | ||
899 | static 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 | |||
906 | static void free_session(struct kref *kref) | 906 | static 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 | ||
922 | void nfsd4_put_session(struct nfsd4_session *ses) | 916 | void 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 | ||
929 | static struct nfsd4_session *alloc_init_session(struct svc_rqst *rqstp, struct nfs4_client *clp, struct nfsd4_create_session *cses) | 923 | static 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 | |||
948 | static 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 | ||
1133 | static void | 1120 | static void |
1134 | expire_client(struct nfs4_client *clp) | 1121 | destroy_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 | ||
1155 | static void expire_client(struct nfs4_client *clp) | ||
1156 | { | ||
1157 | nfsd4_client_record_remove(clp); | ||
1158 | destroy_client(clp); | ||
1159 | } | ||
1160 | |||
1168 | static void copy_verf(struct nfs4_client *target, nfs4_verifier *source) | 1161 | static 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 | */ | ||
1228 | static 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 | |||
1226 | static bool | 1235 | static bool |
1227 | same_creds(struct svc_cred *cr1, struct svc_cred *cr2) | 1236 | same_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 | ||
1342 | static struct nfs4_client * | 1351 | static struct nfs4_client * |
1343 | find_confirmed_client(clientid_t *clid) | 1352 | find_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 | ||
1357 | static struct nfs4_client * | 1368 | static struct nfs4_client * |
1358 | find_unconfirmed_client(clientid_t *clid) | 1369 | find_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 | } | ||
1824 | out: | 1835 | out: |
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; |
1839 | out_free_conn: | ||
1840 | free_conn(conn); | ||
1841 | out_free_session: | ||
1842 | __free_session(new); | ||
1843 | goto out; | ||
1828 | } | 1844 | } |
1829 | 1845 | ||
1830 | static bool nfsd4_last_compound_op(struct svc_rqst *rqstp) | 1846 | static 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 | ||
1878 | static bool nfsd4_compound_in_session(struct nfsd4_session *session, struct nfs4_sessionid *sid) | 1899 | static 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 | ||
2449 | static struct nfs4_openowner * | 2464 | static struct nfs4_openowner * |
2450 | find_openstateowner_str(unsigned int hashval, struct nfsd4_open *open) | 2465 | find_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 | ||
2708 | static void nfs4_free_stateid(struct nfs4_ol_stateid *s) | ||
2709 | { | ||
2710 | kmem_cache_free(stateid_slab, s); | ||
2711 | } | ||
2712 | |||
2713 | static inline int nfs4_access_to_access(u32 nfs4_access) | 2727 | static 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 | ||
3375 | static __be32 nfsd4_lookup_stateid(stateid_t *stateid, unsigned char typemask, struct nfs4_stid **s) | 3388 | static __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 | } |
4268 | out: | 4300 | out: |
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, | |||
4328 | out: | 4368 | out: |
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 | ||
4333 | out_nfserr: | 4375 | out_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 |
4504 | nfs4_check_open_reclaim(clientid_t *clid) | 4546 | nfs4_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 | ||
4585 | int nfsd_process_n_delegations(u64 num, struct list_head *list) | 4626 | static 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 | */ | ||
688 | static 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 | */ | ||
753 | static 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 | |||
774 | static ssize_t __write_ports(struct file *file, char *buf, size_t size) | 730 | static 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 | */ |
865 | static ssize_t write_ports(struct file *file, char *buf, size_t size) | 787 | static 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 | ||
1011 | extern char *nfs4_recoverydir(void); | ||
1012 | |||
1013 | static ssize_t __write_recoverydir(struct file *file, char *buf, size_t size) | 933 | static 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 | */ |
68 | int nfsd_svc(unsigned short port, int nrservs); | 68 | int nfsd_svc(int nrservs); |
69 | int nfsd_dispatch(struct svc_rqst *rqstp, __be32 *statp); | 69 | int nfsd_dispatch(struct svc_rqst *rqstp, __be32 *statp); |
70 | 70 | ||
71 | int nfsd_nrthreads(void); | 71 | int nfsd_nrthreads(void); |
@@ -124,6 +124,7 @@ int nfs4_state_start(void); | |||
124 | void nfs4_state_shutdown(void); | 124 | void nfs4_state_shutdown(void); |
125 | void nfs4_reset_lease(time_t leasetime); | 125 | void nfs4_reset_lease(time_t leasetime); |
126 | int nfs4_reset_recoverydir(char *recdir); | 126 | int nfs4_reset_recoverydir(char *recdir); |
127 | char * nfs4_recoverydir(void); | ||
127 | #else | 128 | #else |
128 | static inline void nfs4_state_init(void) { } | 129 | static inline void nfs4_state_init(void) { } |
129 | static inline int nfsd4_init_slabs(void) { return 0; } | 130 | static inline int nfsd4_init_slabs(void) { return 0; } |
@@ -132,6 +133,7 @@ static inline int nfs4_state_start(void) { return 0; } | |||
132 | static inline void nfs4_state_shutdown(void) { } | 133 | static inline void nfs4_state_shutdown(void) { } |
133 | static inline void nfs4_reset_lease(time_t leasetime) { } | 134 | static inline void nfs4_reset_lease(time_t leasetime) { } |
134 | static inline int nfs4_reset_recoverydir(char *recdir) { return 0; } | 135 | static inline int nfs4_reset_recoverydir(char *recdir) { return 0; } |
136 | static 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 | ||
186 | static int nfsd_init_socks(int port) | 186 | static 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 | ||
205 | static bool nfsd_up = false; | 205 | static bool nfsd_up = false; |
206 | 206 | ||
207 | static int nfsd_startup(unsigned short port, int nrservs) | 207 | static 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 | */ |
438 | int | 438 | int |
439 | nfsd_svc(unsigned short port, int nrservs) | 439 | nfsd_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 | |||
487 | nfsd(void *vrqstp) | 487 | nfsd(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 | */ | ||
381 | struct nfs4_file { | 377 | struct 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); | |||
459 | extern int nfs4_in_grace(void); | 455 | extern int nfs4_in_grace(void); |
460 | extern void nfs4_release_reclaim(void); | 456 | extern void nfs4_release_reclaim(void); |
461 | extern struct nfs4_client_reclaim *nfsd4_find_reclaim_client(struct nfs4_client *crp); | 457 | extern struct nfs4_client_reclaim *nfsd4_find_reclaim_client(struct nfs4_client *crp); |
462 | extern __be32 nfs4_check_open_reclaim(clientid_t *clid); | 458 | extern __be32 nfs4_check_open_reclaim(clientid_t *clid, bool sessions); |
463 | extern void nfs4_free_openowner(struct nfs4_openowner *); | 459 | extern void nfs4_free_openowner(struct nfs4_openowner *); |
464 | extern void nfs4_free_lockowner(struct nfs4_lockowner *); | 460 | extern void nfs4_free_lockowner(struct nfs4_lockowner *); |
465 | extern int set_callback_cred(void); | 461 | extern 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 @@ | |||
1 | header-y += cld.h | ||
2 | header-y += debug.h | ||
3 | header-y += export.h | ||
4 | header-y += nfsfh.h | ||
5 | header-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 | } |
155 | struct svc_export * rqst_exp_find(struct svc_rqst *, int, u32 *); | 108 | struct 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 | */ | ||
32 | struct 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 | */ | ||
86 | struct 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 | |||
96 | struct 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 | ||
125 | static inline __u32 ino_t_to_u32(ino_t ino) | 19 | static 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 | ||
19 | struct nfsd_stats { | 14 | struct nfsd_stats { |
20 | unsigned int rchits; /* repcache hits */ | 15 | unsigned int rchits; /* repcache hits */ |
@@ -47,5 +42,4 @@ extern struct svc_stat nfsd_svcstats; | |||
47 | void nfsd_stat_init(void); | 42 | void nfsd_stat_init(void); |
48 | void nfsd_stat_shutdown(void); | 43 | void 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 @@ | |||
1 | header-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); | |||
87 | void rpc_unregister_sysctl(void); | 70 | void 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 | |||
99 | enum { | ||
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 *, | |||
114 | int svc_create_xprt(struct svc_serv *, const char *, struct net *, | 114 | int svc_create_xprt(struct svc_serv *, const char *, struct net *, |
115 | const int, const unsigned short, int); | 115 | const int, const unsigned short, int); |
116 | void svc_xprt_enqueue(struct svc_xprt *xprt); | 116 | void svc_xprt_enqueue(struct svc_xprt *xprt); |
117 | void svc_xprt_received(struct svc_xprt *); | ||
118 | void svc_xprt_put(struct svc_xprt *xprt); | 117 | void svc_xprt_put(struct svc_xprt *xprt); |
119 | void svc_xprt_copy_addrs(struct svc_rqst *rqstp, struct svc_xprt *xprt); | 118 | void svc_xprt_copy_addrs(struct svc_rqst *rqstp, struct svc_xprt *xprt); |
120 | void svc_close_xprt(struct svc_xprt *xprt); | 119 | void 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); |
126 | int svc_xprt_names(struct svc_serv *serv, char *buf, const int buflen); | 125 | int svc_xprt_names(struct svc_serv *serv, char *buf, const int buflen); |
126 | void svc_add_new_perm_xprt(struct svc_serv *serv, struct svc_xprt *xprt); | ||
127 | 127 | ||
128 | static inline void svc_xprt_get(struct svc_xprt *xprt) | 128 | static 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 | ||
173 | static inline unsigned short svc_xprt_local_port(const struct svc_xprt *xprt) | 172 | static 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); | |||
39 | int svc_send(struct svc_rqst *); | 39 | int svc_send(struct svc_rqst *); |
40 | void svc_drop(struct svc_rqst *); | 40 | void svc_drop(struct svc_rqst *); |
41 | void svc_sock_update_bufs(struct svc_serv *serv); | 41 | void svc_sock_update_bufs(struct svc_serv *serv); |
42 | int svc_sock_names(struct svc_serv *serv, char *buf, | ||
43 | const size_t buflen, | ||
44 | const char *toclose); | ||
45 | int svc_addsock(struct svc_serv *serv, const int fd, | 42 | int 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); |
47 | void svc_init_xprt_sock(void); | 44 | void 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 |
2 | header-y += cld.h | ||
3 | header-y += debug.h | ||
4 | header-y += export.h | ||
5 | header-y += nfsfh.h | ||
6 | header-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 | */ | ||
29 | struct 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 | */ | ||
83 | struct 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 | |||
93 | struct 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 |
2 | header-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 | |||
37 | enum { | ||
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 | */ | ||
219 | static 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 | |||
231 | void 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 | |||
211 | int svc_create_xprt(struct svc_serv *serv, const char *xprt_name, | 240 | int 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 | */ | ||
405 | void 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 | } | ||
416 | EXPORT_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 | /* | 571 | int 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 | */ | ||
573 | int 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(); | 609 | struct 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 | |||
682 | void 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 | |||
699 | static 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 | */ | ||
745 | int 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 | } |
918 | EXPORT_SYMBOL_GPL(svc_close_xprt); | 955 | EXPORT_SYMBOL_GPL(svc_close_xprt); |
919 | 956 | ||
920 | static void svc_close_list(struct list_head *xprt_list, struct net *net) | 957 | static 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 | ||
932 | static void svc_clear_pools(struct svc_serv *serv, struct net *net) | 971 | static 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 | ||
952 | static void svc_clear_list(struct list_head *xprt_list, struct net *net) | 991 | static 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 | ||
966 | void svc_close_net(struct svc_serv *serv, struct net *net) | 1009 | void 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 | ||
61 | static struct svc_sock *svc_setup_socket(struct svc_serv *, struct socket *, | 61 | static struct svc_sock *svc_setup_socket(struct svc_serv *, struct socket *, |
62 | int *errp, int flags); | 62 | int flags); |
63 | static void svc_udp_data_ready(struct sock *, int); | 63 | static void svc_udp_data_ready(struct sock *, int); |
64 | static int svc_udp_recvfrom(struct svc_rqst *); | 64 | static int svc_udp_recvfrom(struct svc_rqst *); |
65 | static int svc_udp_sendto(struct svc_rqst *); | 65 | static 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 | */ | ||
323 | int 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 | } | ||
357 | EXPORT_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); |
623 | out_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; |
609 | out_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 | ||
667 | static int | 615 | static 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; |
1178 | err_other: | 1127 | err_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); |
1182 | err_noclose: | 1131 | err_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 | */ |
1384 | static struct svc_sock *svc_setup_socket(struct svc_serv *serv, | 1333 | static 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); |
1431 | out: | ||
1432 | sockfd_put(so); | ||
1433 | return err; | ||
1489 | } | 1434 | } |
1490 | EXPORT_SYMBOL_GPL(svc_addsock); | 1435 | EXPORT_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; | ||
1571 | bummer: | 1518 | bummer: |
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 | } |