diff options
Diffstat (limited to 'fs/nfsd')
-rw-r--r-- | fs/nfsd/auth.c | 46 | ||||
-rw-r--r-- | fs/nfsd/export.c | 3 | ||||
-rw-r--r-- | fs/nfsd/nfs3proc.c | 2 | ||||
-rw-r--r-- | fs/nfsd/nfs4acl.c | 8 | ||||
-rw-r--r-- | fs/nfsd/nfs4callback.c | 6 | ||||
-rw-r--r-- | fs/nfsd/nfs4proc.c | 4 | ||||
-rw-r--r-- | fs/nfsd/nfs4state.c | 150 | ||||
-rw-r--r-- | fs/nfsd/nfs4xdr.c | 62 | ||||
-rw-r--r-- | fs/nfsd/nfsproc.c | 2 | ||||
-rw-r--r-- | fs/nfsd/vfs.c | 6 |
10 files changed, 136 insertions, 153 deletions
diff --git a/fs/nfsd/auth.c b/fs/nfsd/auth.c index cfe9ce881613..6e92b0fe5323 100644 --- a/fs/nfsd/auth.c +++ b/fs/nfsd/auth.c | |||
@@ -14,46 +14,46 @@ | |||
14 | 14 | ||
15 | int nfsd_setuser(struct svc_rqst *rqstp, struct svc_export *exp) | 15 | int nfsd_setuser(struct svc_rqst *rqstp, struct svc_export *exp) |
16 | { | 16 | { |
17 | struct svc_cred *cred = &rqstp->rq_cred; | 17 | struct svc_cred cred = rqstp->rq_cred; |
18 | int i; | 18 | int i; |
19 | int ret; | 19 | int ret; |
20 | 20 | ||
21 | if (exp->ex_flags & NFSEXP_ALLSQUASH) { | 21 | if (exp->ex_flags & NFSEXP_ALLSQUASH) { |
22 | cred->cr_uid = exp->ex_anon_uid; | 22 | cred.cr_uid = exp->ex_anon_uid; |
23 | cred->cr_gid = exp->ex_anon_gid; | 23 | cred.cr_gid = exp->ex_anon_gid; |
24 | put_group_info(cred->cr_group_info); | 24 | cred.cr_group_info = groups_alloc(0); |
25 | cred->cr_group_info = groups_alloc(0); | ||
26 | } else if (exp->ex_flags & NFSEXP_ROOTSQUASH) { | 25 | } else if (exp->ex_flags & NFSEXP_ROOTSQUASH) { |
27 | struct group_info *gi; | 26 | struct group_info *gi; |
28 | if (!cred->cr_uid) | 27 | if (!cred.cr_uid) |
29 | cred->cr_uid = exp->ex_anon_uid; | 28 | cred.cr_uid = exp->ex_anon_uid; |
30 | if (!cred->cr_gid) | 29 | if (!cred.cr_gid) |
31 | cred->cr_gid = exp->ex_anon_gid; | 30 | cred.cr_gid = exp->ex_anon_gid; |
32 | gi = groups_alloc(cred->cr_group_info->ngroups); | 31 | gi = groups_alloc(cred.cr_group_info->ngroups); |
33 | if (gi) | 32 | if (gi) |
34 | for (i = 0; i < cred->cr_group_info->ngroups; i++) { | 33 | for (i = 0; i < cred.cr_group_info->ngroups; i++) { |
35 | if (!GROUP_AT(cred->cr_group_info, i)) | 34 | if (!GROUP_AT(cred.cr_group_info, i)) |
36 | GROUP_AT(gi, i) = exp->ex_anon_gid; | 35 | GROUP_AT(gi, i) = exp->ex_anon_gid; |
37 | else | 36 | else |
38 | GROUP_AT(gi, i) = GROUP_AT(cred->cr_group_info, i); | 37 | GROUP_AT(gi, i) = GROUP_AT(cred.cr_group_info, i); |
39 | } | 38 | } |
40 | put_group_info(cred->cr_group_info); | 39 | cred.cr_group_info = gi; |
41 | cred->cr_group_info = gi; | 40 | } else |
42 | } | 41 | get_group_info(cred.cr_group_info); |
43 | 42 | ||
44 | if (cred->cr_uid != (uid_t) -1) | 43 | if (cred.cr_uid != (uid_t) -1) |
45 | current->fsuid = cred->cr_uid; | 44 | current->fsuid = cred.cr_uid; |
46 | else | 45 | else |
47 | current->fsuid = exp->ex_anon_uid; | 46 | current->fsuid = exp->ex_anon_uid; |
48 | if (cred->cr_gid != (gid_t) -1) | 47 | if (cred.cr_gid != (gid_t) -1) |
49 | current->fsgid = cred->cr_gid; | 48 | current->fsgid = cred.cr_gid; |
50 | else | 49 | else |
51 | current->fsgid = exp->ex_anon_gid; | 50 | current->fsgid = exp->ex_anon_gid; |
52 | 51 | ||
53 | if (!cred->cr_group_info) | 52 | if (!cred.cr_group_info) |
54 | return -ENOMEM; | 53 | return -ENOMEM; |
55 | ret = set_current_groups(cred->cr_group_info); | 54 | ret = set_current_groups(cred.cr_group_info); |
56 | if ((cred->cr_uid)) { | 55 | put_group_info(cred.cr_group_info); |
56 | if ((cred.cr_uid)) { | ||
57 | cap_t(current->cap_effective) &= ~CAP_NFSD_MASK; | 57 | cap_t(current->cap_effective) &= ~CAP_NFSD_MASK; |
58 | } else { | 58 | } else { |
59 | cap_t(current->cap_effective) |= (CAP_NFSD_MASK & | 59 | cap_t(current->cap_effective) |= (CAP_NFSD_MASK & |
diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c index c340be0a3f59..4e0578121d9a 100644 --- a/fs/nfsd/export.c +++ b/fs/nfsd/export.c | |||
@@ -422,7 +422,7 @@ static int svc_export_parse(struct cache_detail *cd, char *mesg, int mlen) | |||
422 | if ((len=qword_get(&mesg, buf, PAGE_SIZE)) <= 0) | 422 | if ((len=qword_get(&mesg, buf, PAGE_SIZE)) <= 0) |
423 | goto out; | 423 | goto out; |
424 | err = path_lookup(buf, 0, &nd); | 424 | err = path_lookup(buf, 0, &nd); |
425 | if (err) goto out; | 425 | if (err) goto out_no_path; |
426 | 426 | ||
427 | exp.h.flags = 0; | 427 | exp.h.flags = 0; |
428 | exp.ex_client = dom; | 428 | exp.ex_client = dom; |
@@ -475,6 +475,7 @@ static int svc_export_parse(struct cache_detail *cd, char *mesg, int mlen) | |||
475 | out: | 475 | out: |
476 | if (nd.dentry) | 476 | if (nd.dentry) |
477 | path_release(&nd); | 477 | path_release(&nd); |
478 | out_no_path: | ||
478 | if (dom) | 479 | if (dom) |
479 | auth_domain_put(dom); | 480 | auth_domain_put(dom); |
480 | kfree(buf); | 481 | kfree(buf); |
diff --git a/fs/nfsd/nfs3proc.c b/fs/nfsd/nfs3proc.c index 6d2dfed1de08..f61142afea44 100644 --- a/fs/nfsd/nfs3proc.c +++ b/fs/nfsd/nfs3proc.c | |||
@@ -682,7 +682,7 @@ static struct svc_procedure nfsd_procedures3[22] = { | |||
682 | PROC(lookup, dirop, dirop, fhandle2, RC_NOCACHE, ST+FH+pAT+pAT), | 682 | PROC(lookup, dirop, dirop, fhandle2, RC_NOCACHE, ST+FH+pAT+pAT), |
683 | PROC(access, access, access, fhandle, RC_NOCACHE, ST+pAT+1), | 683 | PROC(access, access, access, fhandle, RC_NOCACHE, ST+pAT+1), |
684 | PROC(readlink, readlink, readlink, fhandle, RC_NOCACHE, ST+pAT+1+NFS3_MAXPATHLEN/4), | 684 | PROC(readlink, readlink, readlink, fhandle, RC_NOCACHE, ST+pAT+1+NFS3_MAXPATHLEN/4), |
685 | PROC(read, read, read, fhandle, RC_NOCACHE, ST+pAT+4+NFSSVC_MAXBLKSIZE), | 685 | PROC(read, read, read, fhandle, RC_NOCACHE, ST+pAT+4+NFSSVC_MAXBLKSIZE/4), |
686 | PROC(write, write, write, fhandle, RC_REPLBUFF, ST+WC+4), | 686 | PROC(write, write, write, fhandle, RC_REPLBUFF, ST+WC+4), |
687 | PROC(create, create, create, fhandle2, RC_REPLBUFF, ST+(1+FH+pAT)+WC), | 687 | PROC(create, create, create, fhandle2, RC_REPLBUFF, ST+(1+FH+pAT)+WC), |
688 | PROC(mkdir, mkdir, create, fhandle2, RC_REPLBUFF, ST+(1+FH+pAT)+WC), | 688 | PROC(mkdir, mkdir, create, fhandle2, RC_REPLBUFF, ST+(1+FH+pAT)+WC), |
diff --git a/fs/nfsd/nfs4acl.c b/fs/nfsd/nfs4acl.c index 7391f4aabedb..edb107e61b91 100644 --- a/fs/nfsd/nfs4acl.c +++ b/fs/nfsd/nfs4acl.c | |||
@@ -710,9 +710,9 @@ calculate_posix_ace_count(struct nfs4_acl *n4acl) | |||
710 | /* Also, the remaining entries are for named users and | 710 | /* Also, the remaining entries are for named users and |
711 | * groups, and come in threes (mask, allow, deny): */ | 711 | * groups, and come in threes (mask, allow, deny): */ |
712 | if (n4acl->naces < 7) | 712 | if (n4acl->naces < 7) |
713 | return -1; | 713 | return -EINVAL; |
714 | if ((n4acl->naces - 7) % 3) | 714 | if ((n4acl->naces - 7) % 3) |
715 | return -1; | 715 | return -EINVAL; |
716 | return 4 + (n4acl->naces - 7)/3; | 716 | return 4 + (n4acl->naces - 7)/3; |
717 | } | 717 | } |
718 | } | 718 | } |
@@ -790,7 +790,7 @@ nfs4_acl_split(struct nfs4_acl *acl, struct nfs4_acl *dacl) | |||
790 | continue; | 790 | continue; |
791 | 791 | ||
792 | error = nfs4_acl_add_ace(dacl, ace->type, ace->flag, | 792 | error = nfs4_acl_add_ace(dacl, ace->type, ace->flag, |
793 | ace->access_mask, ace->whotype, ace->who) == -1; | 793 | ace->access_mask, ace->whotype, ace->who); |
794 | if (error < 0) | 794 | if (error < 0) |
795 | goto out; | 795 | goto out; |
796 | 796 | ||
@@ -866,7 +866,7 @@ nfs4_acl_add_ace(struct nfs4_acl *acl, u32 type, u32 flag, u32 access_mask, | |||
866 | struct nfs4_ace *ace; | 866 | struct nfs4_ace *ace; |
867 | 867 | ||
868 | if ((ace = kmalloc(sizeof(*ace), GFP_KERNEL)) == NULL) | 868 | if ((ace = kmalloc(sizeof(*ace), GFP_KERNEL)) == NULL) |
869 | return -1; | 869 | return -ENOMEM; |
870 | 870 | ||
871 | ace->type = type; | 871 | ace->type = type; |
872 | ace->flag = flag; | 872 | ace->flag = flag; |
diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c index c872bd07fc10..dbaf3f93f328 100644 --- a/fs/nfsd/nfs4callback.c +++ b/fs/nfsd/nfs4callback.c | |||
@@ -441,8 +441,9 @@ nfsd4_probe_callback(struct nfs4_client *clp) | |||
441 | goto out_clnt; | 441 | goto out_clnt; |
442 | } | 442 | } |
443 | 443 | ||
444 | /* the task holds a reference to the nfs4_client struct */ | ||
445 | cb->cb_client = clnt; | 444 | cb->cb_client = clnt; |
445 | |||
446 | /* the task holds a reference to the nfs4_client struct */ | ||
446 | atomic_inc(&clp->cl_count); | 447 | atomic_inc(&clp->cl_count); |
447 | 448 | ||
448 | msg.rpc_cred = nfsd4_lookupcred(clp,0); | 449 | msg.rpc_cred = nfsd4_lookupcred(clp,0); |
@@ -460,13 +461,12 @@ nfsd4_probe_callback(struct nfs4_client *clp) | |||
460 | out_rpciod: | 461 | out_rpciod: |
461 | atomic_dec(&clp->cl_count); | 462 | atomic_dec(&clp->cl_count); |
462 | rpciod_down(); | 463 | rpciod_down(); |
464 | cb->cb_client = NULL; | ||
463 | out_clnt: | 465 | out_clnt: |
464 | rpc_shutdown_client(clnt); | 466 | rpc_shutdown_client(clnt); |
465 | goto out_err; | ||
466 | out_err: | 467 | out_err: |
467 | dprintk("NFSD: warning: no callback path to client %.*s\n", | 468 | dprintk("NFSD: warning: no callback path to client %.*s\n", |
468 | (int)clp->cl_name.len, clp->cl_name.data); | 469 | (int)clp->cl_name.len, clp->cl_name.data); |
469 | cb->cb_client = NULL; | ||
470 | } | 470 | } |
471 | 471 | ||
472 | static void | 472 | static void |
diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c index 6d63f1d9e5f5..b0e095ea0c03 100644 --- a/fs/nfsd/nfs4proc.c +++ b/fs/nfsd/nfs4proc.c | |||
@@ -288,8 +288,6 @@ nfsd4_putrootfh(struct svc_rqst *rqstp, struct svc_fh *current_fh) | |||
288 | fh_put(current_fh); | 288 | fh_put(current_fh); |
289 | status = exp_pseudoroot(rqstp->rq_client, current_fh, | 289 | status = exp_pseudoroot(rqstp->rq_client, current_fh, |
290 | &rqstp->rq_chandle); | 290 | &rqstp->rq_chandle); |
291 | if (!status) | ||
292 | status = nfserrno(nfsd_setuser(rqstp, current_fh->fh_export)); | ||
293 | return status; | 291 | return status; |
294 | } | 292 | } |
295 | 293 | ||
@@ -975,7 +973,7 @@ struct nfsd4_voidargs { int dummy; }; | |||
975 | */ | 973 | */ |
976 | static struct svc_procedure nfsd_procedures4[2] = { | 974 | static struct svc_procedure nfsd_procedures4[2] = { |
977 | PROC(null, void, void, void, RC_NOCACHE, 1), | 975 | PROC(null, void, void, void, RC_NOCACHE, 1), |
978 | PROC(compound, compound, compound, compound, RC_NOCACHE, NFSD_BUFSIZE) | 976 | PROC(compound, compound, compound, compound, RC_NOCACHE, NFSD_BUFSIZE/4) |
979 | }; | 977 | }; |
980 | 978 | ||
981 | struct svc_version nfsd_version4 = { | 979 | struct svc_version nfsd_version4 = { |
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index 47ec112b266c..96c7578cbe1e 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c | |||
@@ -147,6 +147,42 @@ get_nfs4_file(struct nfs4_file *fi) | |||
147 | kref_get(&fi->fi_ref); | 147 | kref_get(&fi->fi_ref); |
148 | } | 148 | } |
149 | 149 | ||
150 | static int num_delegations; | ||
151 | |||
152 | /* | ||
153 | * Open owner state (share locks) | ||
154 | */ | ||
155 | |||
156 | /* hash tables for nfs4_stateowner */ | ||
157 | #define OWNER_HASH_BITS 8 | ||
158 | #define OWNER_HASH_SIZE (1 << OWNER_HASH_BITS) | ||
159 | #define OWNER_HASH_MASK (OWNER_HASH_SIZE - 1) | ||
160 | |||
161 | #define ownerid_hashval(id) \ | ||
162 | ((id) & OWNER_HASH_MASK) | ||
163 | #define ownerstr_hashval(clientid, ownername) \ | ||
164 | (((clientid) + opaque_hashval((ownername.data), (ownername.len))) & OWNER_HASH_MASK) | ||
165 | |||
166 | static struct list_head ownerid_hashtbl[OWNER_HASH_SIZE]; | ||
167 | static struct list_head ownerstr_hashtbl[OWNER_HASH_SIZE]; | ||
168 | |||
169 | /* hash table for nfs4_file */ | ||
170 | #define FILE_HASH_BITS 8 | ||
171 | #define FILE_HASH_SIZE (1 << FILE_HASH_BITS) | ||
172 | #define FILE_HASH_MASK (FILE_HASH_SIZE - 1) | ||
173 | /* hash table for (open)nfs4_stateid */ | ||
174 | #define STATEID_HASH_BITS 10 | ||
175 | #define STATEID_HASH_SIZE (1 << STATEID_HASH_BITS) | ||
176 | #define STATEID_HASH_MASK (STATEID_HASH_SIZE - 1) | ||
177 | |||
178 | #define file_hashval(x) \ | ||
179 | hash_ptr(x, FILE_HASH_BITS) | ||
180 | #define stateid_hashval(owner_id, file_id) \ | ||
181 | (((owner_id) + (file_id)) & STATEID_HASH_MASK) | ||
182 | |||
183 | static struct list_head file_hashtbl[FILE_HASH_SIZE]; | ||
184 | static struct list_head stateid_hashtbl[STATEID_HASH_SIZE]; | ||
185 | |||
150 | static struct nfs4_delegation * | 186 | static struct nfs4_delegation * |
151 | alloc_init_deleg(struct nfs4_client *clp, struct nfs4_stateid *stp, struct svc_fh *current_fh, u32 type) | 187 | alloc_init_deleg(struct nfs4_client *clp, struct nfs4_stateid *stp, struct svc_fh *current_fh, u32 type) |
152 | { | 188 | { |
@@ -155,9 +191,12 @@ alloc_init_deleg(struct nfs4_client *clp, struct nfs4_stateid *stp, struct svc_f | |||
155 | struct nfs4_callback *cb = &stp->st_stateowner->so_client->cl_callback; | 191 | struct nfs4_callback *cb = &stp->st_stateowner->so_client->cl_callback; |
156 | 192 | ||
157 | dprintk("NFSD alloc_init_deleg\n"); | 193 | dprintk("NFSD alloc_init_deleg\n"); |
194 | if (num_delegations > STATEID_HASH_SIZE * 4) | ||
195 | return NULL; | ||
158 | dp = kmem_cache_alloc(deleg_slab, GFP_KERNEL); | 196 | dp = kmem_cache_alloc(deleg_slab, GFP_KERNEL); |
159 | if (dp == NULL) | 197 | if (dp == NULL) |
160 | return dp; | 198 | return dp; |
199 | num_delegations++; | ||
161 | INIT_LIST_HEAD(&dp->dl_perfile); | 200 | INIT_LIST_HEAD(&dp->dl_perfile); |
162 | INIT_LIST_HEAD(&dp->dl_perclnt); | 201 | INIT_LIST_HEAD(&dp->dl_perclnt); |
163 | INIT_LIST_HEAD(&dp->dl_recall_lru); | 202 | INIT_LIST_HEAD(&dp->dl_recall_lru); |
@@ -192,6 +231,7 @@ nfs4_put_delegation(struct nfs4_delegation *dp) | |||
192 | dprintk("NFSD: freeing dp %p\n",dp); | 231 | dprintk("NFSD: freeing dp %p\n",dp); |
193 | put_nfs4_file(dp->dl_file); | 232 | put_nfs4_file(dp->dl_file); |
194 | kmem_cache_free(deleg_slab, dp); | 233 | kmem_cache_free(deleg_slab, dp); |
234 | num_delegations--; | ||
195 | } | 235 | } |
196 | } | 236 | } |
197 | 237 | ||
@@ -330,22 +370,29 @@ put_nfs4_client(struct nfs4_client *clp) | |||
330 | } | 370 | } |
331 | 371 | ||
332 | static void | 372 | static void |
373 | shutdown_callback_client(struct nfs4_client *clp) | ||
374 | { | ||
375 | struct rpc_clnt *clnt = clp->cl_callback.cb_client; | ||
376 | |||
377 | /* shutdown rpc client, ending any outstanding recall rpcs */ | ||
378 | if (clnt) { | ||
379 | clp->cl_callback.cb_client = NULL; | ||
380 | rpc_shutdown_client(clnt); | ||
381 | rpciod_down(); | ||
382 | } | ||
383 | } | ||
384 | |||
385 | static void | ||
333 | expire_client(struct nfs4_client *clp) | 386 | expire_client(struct nfs4_client *clp) |
334 | { | 387 | { |
335 | struct nfs4_stateowner *sop; | 388 | struct nfs4_stateowner *sop; |
336 | struct nfs4_delegation *dp; | 389 | struct nfs4_delegation *dp; |
337 | struct nfs4_callback *cb = &clp->cl_callback; | ||
338 | struct rpc_clnt *clnt = clp->cl_callback.cb_client; | ||
339 | struct list_head reaplist; | 390 | struct list_head reaplist; |
340 | 391 | ||
341 | dprintk("NFSD: expire_client cl_count %d\n", | 392 | dprintk("NFSD: expire_client cl_count %d\n", |
342 | atomic_read(&clp->cl_count)); | 393 | atomic_read(&clp->cl_count)); |
343 | 394 | ||
344 | /* shutdown rpc client, ending any outstanding recall rpcs */ | 395 | shutdown_callback_client(clp); |
345 | if (atomic_read(&cb->cb_set) == 1 && clnt) { | ||
346 | rpc_shutdown_client(clnt); | ||
347 | clnt = clp->cl_callback.cb_client = NULL; | ||
348 | } | ||
349 | 396 | ||
350 | INIT_LIST_HEAD(&reaplist); | 397 | INIT_LIST_HEAD(&reaplist); |
351 | spin_lock(&recall_lock); | 398 | spin_lock(&recall_lock); |
@@ -936,40 +983,6 @@ out: | |||
936 | return status; | 983 | return status; |
937 | } | 984 | } |
938 | 985 | ||
939 | /* | ||
940 | * Open owner state (share locks) | ||
941 | */ | ||
942 | |||
943 | /* hash tables for nfs4_stateowner */ | ||
944 | #define OWNER_HASH_BITS 8 | ||
945 | #define OWNER_HASH_SIZE (1 << OWNER_HASH_BITS) | ||
946 | #define OWNER_HASH_MASK (OWNER_HASH_SIZE - 1) | ||
947 | |||
948 | #define ownerid_hashval(id) \ | ||
949 | ((id) & OWNER_HASH_MASK) | ||
950 | #define ownerstr_hashval(clientid, ownername) \ | ||
951 | (((clientid) + opaque_hashval((ownername.data), (ownername.len))) & OWNER_HASH_MASK) | ||
952 | |||
953 | static struct list_head ownerid_hashtbl[OWNER_HASH_SIZE]; | ||
954 | static struct list_head ownerstr_hashtbl[OWNER_HASH_SIZE]; | ||
955 | |||
956 | /* hash table for nfs4_file */ | ||
957 | #define FILE_HASH_BITS 8 | ||
958 | #define FILE_HASH_SIZE (1 << FILE_HASH_BITS) | ||
959 | #define FILE_HASH_MASK (FILE_HASH_SIZE - 1) | ||
960 | /* hash table for (open)nfs4_stateid */ | ||
961 | #define STATEID_HASH_BITS 10 | ||
962 | #define STATEID_HASH_SIZE (1 << STATEID_HASH_BITS) | ||
963 | #define STATEID_HASH_MASK (STATEID_HASH_SIZE - 1) | ||
964 | |||
965 | #define file_hashval(x) \ | ||
966 | hash_ptr(x, FILE_HASH_BITS) | ||
967 | #define stateid_hashval(owner_id, file_id) \ | ||
968 | (((owner_id) + (file_id)) & STATEID_HASH_MASK) | ||
969 | |||
970 | static struct list_head file_hashtbl[FILE_HASH_SIZE]; | ||
971 | static struct list_head stateid_hashtbl[STATEID_HASH_SIZE]; | ||
972 | |||
973 | /* OPEN Share state helper functions */ | 986 | /* OPEN Share state helper functions */ |
974 | static inline struct nfs4_file * | 987 | static inline struct nfs4_file * |
975 | alloc_init_file(struct inode *ino) | 988 | alloc_init_file(struct inode *ino) |
@@ -1186,8 +1199,7 @@ move_to_close_lru(struct nfs4_stateowner *sop) | |||
1186 | { | 1199 | { |
1187 | dprintk("NFSD: move_to_close_lru nfs4_stateowner %p\n", sop); | 1200 | dprintk("NFSD: move_to_close_lru nfs4_stateowner %p\n", sop); |
1188 | 1201 | ||
1189 | unhash_stateowner(sop); | 1202 | list_move_tail(&sop->so_close_lru, &close_lru); |
1190 | list_add_tail(&sop->so_close_lru, &close_lru); | ||
1191 | sop->so_time = get_seconds(); | 1203 | sop->so_time = get_seconds(); |
1192 | } | 1204 | } |
1193 | 1205 | ||
@@ -1916,8 +1928,7 @@ nfs4_laundromat(void) | |||
1916 | } | 1928 | } |
1917 | dprintk("NFSD: purging unused open stateowner (so_id %d)\n", | 1929 | dprintk("NFSD: purging unused open stateowner (so_id %d)\n", |
1918 | sop->so_id); | 1930 | sop->so_id); |
1919 | list_del(&sop->so_close_lru); | 1931 | release_stateowner(sop); |
1920 | nfs4_put_stateowner(sop); | ||
1921 | } | 1932 | } |
1922 | if (clientid_val < NFSD_LAUNDROMAT_MINTIMEOUT) | 1933 | if (clientid_val < NFSD_LAUNDROMAT_MINTIMEOUT) |
1923 | clientid_val = NFSD_LAUNDROMAT_MINTIMEOUT; | 1934 | clientid_val = NFSD_LAUNDROMAT_MINTIMEOUT; |
@@ -2495,36 +2506,27 @@ nfs4_transform_lock_offset(struct file_lock *lock) | |||
2495 | lock->fl_end = OFFSET_MAX; | 2506 | lock->fl_end = OFFSET_MAX; |
2496 | } | 2507 | } |
2497 | 2508 | ||
2498 | static int | 2509 | /* Hack!: For now, we're defining this just so we can use a pointer to it |
2499 | nfs4_verify_lock_stateowner(struct nfs4_stateowner *sop, unsigned int hashval) | 2510 | * as a unique cookie to identify our (NFSv4's) posix locks. */ |
2500 | { | 2511 | static struct lock_manager_operations nfsd_posix_mng_ops = { |
2501 | struct nfs4_stateowner *local = NULL; | 2512 | }; |
2502 | int status = 0; | ||
2503 | |||
2504 | if (hashval >= LOCK_HASH_SIZE) | ||
2505 | goto out; | ||
2506 | list_for_each_entry(local, &lock_ownerid_hashtbl[hashval], so_idhash) { | ||
2507 | if (local == sop) { | ||
2508 | status = 1; | ||
2509 | goto out; | ||
2510 | } | ||
2511 | } | ||
2512 | out: | ||
2513 | return status; | ||
2514 | } | ||
2515 | |||
2516 | 2513 | ||
2517 | static inline void | 2514 | static inline void |
2518 | nfs4_set_lock_denied(struct file_lock *fl, struct nfsd4_lock_denied *deny) | 2515 | nfs4_set_lock_denied(struct file_lock *fl, struct nfsd4_lock_denied *deny) |
2519 | { | 2516 | { |
2520 | struct nfs4_stateowner *sop = (struct nfs4_stateowner *) fl->fl_owner; | 2517 | struct nfs4_stateowner *sop; |
2521 | unsigned int hval = lockownerid_hashval(sop->so_id); | 2518 | unsigned int hval; |
2522 | 2519 | ||
2523 | deny->ld_sop = NULL; | 2520 | if (fl->fl_lmops == &nfsd_posix_mng_ops) { |
2524 | if (nfs4_verify_lock_stateowner(sop, hval)) { | 2521 | sop = (struct nfs4_stateowner *) fl->fl_owner; |
2522 | hval = lockownerid_hashval(sop->so_id); | ||
2525 | kref_get(&sop->so_ref); | 2523 | kref_get(&sop->so_ref); |
2526 | deny->ld_sop = sop; | 2524 | deny->ld_sop = sop; |
2527 | deny->ld_clientid = sop->so_client->cl_clientid; | 2525 | deny->ld_clientid = sop->so_client->cl_clientid; |
2526 | } else { | ||
2527 | deny->ld_sop = NULL; | ||
2528 | deny->ld_clientid.cl_boot = 0; | ||
2529 | deny->ld_clientid.cl_id = 0; | ||
2528 | } | 2530 | } |
2529 | deny->ld_start = fl->fl_start; | 2531 | deny->ld_start = fl->fl_start; |
2530 | deny->ld_length = ~(u64)0; | 2532 | deny->ld_length = ~(u64)0; |
@@ -2736,6 +2738,7 @@ nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock | |||
2736 | file_lock.fl_pid = current->tgid; | 2738 | file_lock.fl_pid = current->tgid; |
2737 | file_lock.fl_file = filp; | 2739 | file_lock.fl_file = filp; |
2738 | file_lock.fl_flags = FL_POSIX; | 2740 | file_lock.fl_flags = FL_POSIX; |
2741 | file_lock.fl_lmops = &nfsd_posix_mng_ops; | ||
2739 | 2742 | ||
2740 | file_lock.fl_start = lock->lk_offset; | 2743 | file_lock.fl_start = lock->lk_offset; |
2741 | if ((lock->lk_length == ~(u64)0) || | 2744 | if ((lock->lk_length == ~(u64)0) || |
@@ -2841,6 +2844,7 @@ nfsd4_lockt(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock | |||
2841 | file_lock.fl_owner = (fl_owner_t)lockt->lt_stateowner; | 2844 | file_lock.fl_owner = (fl_owner_t)lockt->lt_stateowner; |
2842 | file_lock.fl_pid = current->tgid; | 2845 | file_lock.fl_pid = current->tgid; |
2843 | file_lock.fl_flags = FL_POSIX; | 2846 | file_lock.fl_flags = FL_POSIX; |
2847 | file_lock.fl_lmops = &nfsd_posix_mng_ops; | ||
2844 | 2848 | ||
2845 | file_lock.fl_start = lockt->lt_offset; | 2849 | file_lock.fl_start = lockt->lt_offset; |
2846 | if ((lockt->lt_length == ~(u64)0) || LOFF_OVERFLOW(lockt->lt_offset, lockt->lt_length)) | 2850 | if ((lockt->lt_length == ~(u64)0) || LOFF_OVERFLOW(lockt->lt_offset, lockt->lt_length)) |
@@ -2900,6 +2904,7 @@ nfsd4_locku(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock | |||
2900 | file_lock.fl_pid = current->tgid; | 2904 | file_lock.fl_pid = current->tgid; |
2901 | file_lock.fl_file = filp; | 2905 | file_lock.fl_file = filp; |
2902 | file_lock.fl_flags = FL_POSIX; | 2906 | file_lock.fl_flags = FL_POSIX; |
2907 | file_lock.fl_lmops = &nfsd_posix_mng_ops; | ||
2903 | file_lock.fl_start = locku->lu_offset; | 2908 | file_lock.fl_start = locku->lu_offset; |
2904 | 2909 | ||
2905 | if ((locku->lu_length == ~(u64)0) || LOFF_OVERFLOW(locku->lu_offset, locku->lu_length)) | 2910 | if ((locku->lu_length == ~(u64)0) || LOFF_OVERFLOW(locku->lu_offset, locku->lu_length)) |
@@ -3211,15 +3216,8 @@ __nfs4_state_shutdown(void) | |||
3211 | int i; | 3216 | int i; |
3212 | struct nfs4_client *clp = NULL; | 3217 | struct nfs4_client *clp = NULL; |
3213 | struct nfs4_delegation *dp = NULL; | 3218 | struct nfs4_delegation *dp = NULL; |
3214 | struct nfs4_stateowner *sop = NULL; | ||
3215 | struct list_head *pos, *next, reaplist; | 3219 | struct list_head *pos, *next, reaplist; |
3216 | 3220 | ||
3217 | list_for_each_safe(pos, next, &close_lru) { | ||
3218 | sop = list_entry(pos, struct nfs4_stateowner, so_close_lru); | ||
3219 | list_del(&sop->so_close_lru); | ||
3220 | nfs4_put_stateowner(sop); | ||
3221 | } | ||
3222 | |||
3223 | for (i = 0; i < CLIENT_HASH_SIZE; i++) { | 3221 | for (i = 0; i < CLIENT_HASH_SIZE; i++) { |
3224 | while (!list_empty(&conf_id_hashtbl[i])) { | 3222 | while (!list_empty(&conf_id_hashtbl[i])) { |
3225 | clp = list_entry(conf_id_hashtbl[i].next, struct nfs4_client, cl_idhash); | 3223 | clp = list_entry(conf_id_hashtbl[i].next, struct nfs4_client, cl_idhash); |
@@ -3244,8 +3242,6 @@ __nfs4_state_shutdown(void) | |||
3244 | } | 3242 | } |
3245 | 3243 | ||
3246 | cancel_delayed_work(&laundromat_work); | 3244 | cancel_delayed_work(&laundromat_work); |
3247 | flush_workqueue(laundry_wq); | ||
3248 | destroy_workqueue(laundry_wq); | ||
3249 | nfsd4_shutdown_recdir(); | 3245 | nfsd4_shutdown_recdir(); |
3250 | nfs4_init = 0; | 3246 | nfs4_init = 0; |
3251 | } | 3247 | } |
@@ -3253,6 +3249,8 @@ __nfs4_state_shutdown(void) | |||
3253 | void | 3249 | void |
3254 | nfs4_state_shutdown(void) | 3250 | nfs4_state_shutdown(void) |
3255 | { | 3251 | { |
3252 | cancel_rearming_delayed_workqueue(laundry_wq, &laundromat_work); | ||
3253 | destroy_workqueue(laundry_wq); | ||
3256 | nfs4_lock_state(); | 3254 | nfs4_lock_state(); |
3257 | nfs4_release_reclaim(); | 3255 | nfs4_release_reclaim(); |
3258 | __nfs4_state_shutdown(); | 3256 | __nfs4_state_shutdown(); |
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c index 03857fd81126..de3998f15f10 100644 --- a/fs/nfsd/nfs4xdr.c +++ b/fs/nfsd/nfs4xdr.c | |||
@@ -299,11 +299,10 @@ nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval, struct iattr *ia | |||
299 | buf, dummy32, &ace.who); | 299 | buf, dummy32, &ace.who); |
300 | if (status) | 300 | if (status) |
301 | goto out_nfserr; | 301 | goto out_nfserr; |
302 | if (nfs4_acl_add_ace(*acl, ace.type, ace.flag, | 302 | status = nfs4_acl_add_ace(*acl, ace.type, ace.flag, |
303 | ace.access_mask, ace.whotype, ace.who) != 0) { | 303 | ace.access_mask, ace.whotype, ace.who); |
304 | status = -ENOMEM; | 304 | if (status) |
305 | goto out_nfserr; | 305 | goto out_nfserr; |
306 | } | ||
307 | } | 306 | } |
308 | } else | 307 | } else |
309 | *acl = NULL; | 308 | *acl = NULL; |
@@ -2085,27 +2084,20 @@ nfsd4_encode_read(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_read | |||
2085 | WRITE32(eof); | 2084 | WRITE32(eof); |
2086 | WRITE32(maxcount); | 2085 | WRITE32(maxcount); |
2087 | ADJUST_ARGS(); | 2086 | ADJUST_ARGS(); |
2088 | resp->xbuf->head[0].iov_len = ((char*)resp->p) - (char*)resp->xbuf->head[0].iov_base; | 2087 | resp->xbuf->head[0].iov_len = (char*)p |
2089 | 2088 | - (char*)resp->xbuf->head[0].iov_base; | |
2090 | resp->xbuf->page_len = maxcount; | 2089 | resp->xbuf->page_len = maxcount; |
2091 | 2090 | ||
2092 | /* read zero bytes -> don't set up tail */ | 2091 | /* Use rest of head for padding and remaining ops: */ |
2093 | if(!maxcount) | 2092 | resp->rqstp->rq_restailpage = 0; |
2094 | return 0; | 2093 | resp->xbuf->tail[0].iov_base = p; |
2095 | |||
2096 | /* set up page for remaining responses */ | ||
2097 | svc_take_page(resp->rqstp); | ||
2098 | resp->xbuf->tail[0].iov_base = | ||
2099 | page_address(resp->rqstp->rq_respages[resp->rqstp->rq_resused-1]); | ||
2100 | resp->rqstp->rq_restailpage = resp->rqstp->rq_resused-1; | ||
2101 | resp->xbuf->tail[0].iov_len = 0; | 2094 | resp->xbuf->tail[0].iov_len = 0; |
2102 | resp->p = resp->xbuf->tail[0].iov_base; | ||
2103 | resp->end = resp->p + PAGE_SIZE/4; | ||
2104 | |||
2105 | if (maxcount&3) { | 2095 | if (maxcount&3) { |
2106 | *(resp->p)++ = 0; | 2096 | RESERVE_SPACE(4); |
2097 | WRITE32(0); | ||
2107 | resp->xbuf->tail[0].iov_base += maxcount&3; | 2098 | resp->xbuf->tail[0].iov_base += maxcount&3; |
2108 | resp->xbuf->tail[0].iov_len = 4 - (maxcount&3); | 2099 | resp->xbuf->tail[0].iov_len = 4 - (maxcount&3); |
2100 | ADJUST_ARGS(); | ||
2109 | } | 2101 | } |
2110 | return 0; | 2102 | return 0; |
2111 | } | 2103 | } |
@@ -2142,21 +2134,20 @@ nfsd4_encode_readlink(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_r | |||
2142 | 2134 | ||
2143 | WRITE32(maxcount); | 2135 | WRITE32(maxcount); |
2144 | ADJUST_ARGS(); | 2136 | ADJUST_ARGS(); |
2145 | resp->xbuf->head[0].iov_len = ((char*)resp->p) - (char*)resp->xbuf->head[0].iov_base; | 2137 | resp->xbuf->head[0].iov_len = (char*)p |
2138 | - (char*)resp->xbuf->head[0].iov_base; | ||
2139 | resp->xbuf->page_len = maxcount; | ||
2146 | 2140 | ||
2147 | svc_take_page(resp->rqstp); | 2141 | /* Use rest of head for padding and remaining ops: */ |
2148 | resp->xbuf->tail[0].iov_base = | 2142 | resp->rqstp->rq_restailpage = 0; |
2149 | page_address(resp->rqstp->rq_respages[resp->rqstp->rq_resused-1]); | 2143 | resp->xbuf->tail[0].iov_base = p; |
2150 | resp->rqstp->rq_restailpage = resp->rqstp->rq_resused-1; | ||
2151 | resp->xbuf->tail[0].iov_len = 0; | 2144 | resp->xbuf->tail[0].iov_len = 0; |
2152 | resp->p = resp->xbuf->tail[0].iov_base; | ||
2153 | resp->end = resp->p + PAGE_SIZE/4; | ||
2154 | |||
2155 | resp->xbuf->page_len = maxcount; | ||
2156 | if (maxcount&3) { | 2145 | if (maxcount&3) { |
2157 | *(resp->p)++ = 0; | 2146 | RESERVE_SPACE(4); |
2147 | WRITE32(0); | ||
2158 | resp->xbuf->tail[0].iov_base += maxcount&3; | 2148 | resp->xbuf->tail[0].iov_base += maxcount&3; |
2159 | resp->xbuf->tail[0].iov_len = 4 - (maxcount&3); | 2149 | resp->xbuf->tail[0].iov_len = 4 - (maxcount&3); |
2150 | ADJUST_ARGS(); | ||
2160 | } | 2151 | } |
2161 | return 0; | 2152 | return 0; |
2162 | } | 2153 | } |
@@ -2166,7 +2157,7 @@ nfsd4_encode_readdir(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_re | |||
2166 | { | 2157 | { |
2167 | int maxcount; | 2158 | int maxcount; |
2168 | loff_t offset; | 2159 | loff_t offset; |
2169 | u32 *page, *savep; | 2160 | u32 *page, *savep, *tailbase; |
2170 | ENCODE_HEAD; | 2161 | ENCODE_HEAD; |
2171 | 2162 | ||
2172 | if (nfserr) | 2163 | if (nfserr) |
@@ -2182,6 +2173,7 @@ nfsd4_encode_readdir(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_re | |||
2182 | WRITE32(0); | 2173 | WRITE32(0); |
2183 | ADJUST_ARGS(); | 2174 | ADJUST_ARGS(); |
2184 | resp->xbuf->head[0].iov_len = ((char*)resp->p) - (char*)resp->xbuf->head[0].iov_base; | 2175 | resp->xbuf->head[0].iov_len = ((char*)resp->p) - (char*)resp->xbuf->head[0].iov_base; |
2176 | tailbase = p; | ||
2185 | 2177 | ||
2186 | maxcount = PAGE_SIZE; | 2178 | maxcount = PAGE_SIZE; |
2187 | if (maxcount > readdir->rd_maxcount) | 2179 | if (maxcount > readdir->rd_maxcount) |
@@ -2226,14 +2218,12 @@ nfsd4_encode_readdir(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_re | |||
2226 | *p++ = htonl(readdir->common.err == nfserr_eof); | 2218 | *p++ = htonl(readdir->common.err == nfserr_eof); |
2227 | resp->xbuf->page_len = ((char*)p) - (char*)page_address(resp->rqstp->rq_respages[resp->rqstp->rq_resused-1]); | 2219 | resp->xbuf->page_len = ((char*)p) - (char*)page_address(resp->rqstp->rq_respages[resp->rqstp->rq_resused-1]); |
2228 | 2220 | ||
2229 | /* allocate a page for the tail */ | 2221 | /* Use rest of head for padding and remaining ops: */ |
2230 | svc_take_page(resp->rqstp); | 2222 | resp->rqstp->rq_restailpage = 0; |
2231 | resp->xbuf->tail[0].iov_base = | 2223 | resp->xbuf->tail[0].iov_base = tailbase; |
2232 | page_address(resp->rqstp->rq_respages[resp->rqstp->rq_resused-1]); | ||
2233 | resp->rqstp->rq_restailpage = resp->rqstp->rq_resused-1; | ||
2234 | resp->xbuf->tail[0].iov_len = 0; | 2224 | resp->xbuf->tail[0].iov_len = 0; |
2235 | resp->p = resp->xbuf->tail[0].iov_base; | 2225 | resp->p = resp->xbuf->tail[0].iov_base; |
2236 | resp->end = resp->p + PAGE_SIZE/4; | 2226 | resp->end = resp->p + (PAGE_SIZE - resp->xbuf->head[0].iov_len)/4; |
2237 | 2227 | ||
2238 | return 0; | 2228 | return 0; |
2239 | err_no_verf: | 2229 | err_no_verf: |
diff --git a/fs/nfsd/nfsproc.c b/fs/nfsd/nfsproc.c index 3e6b75cd90fd..06cd0db0f32b 100644 --- a/fs/nfsd/nfsproc.c +++ b/fs/nfsd/nfsproc.c | |||
@@ -553,7 +553,7 @@ static struct svc_procedure nfsd_procedures2[18] = { | |||
553 | PROC(none, void, void, none, RC_NOCACHE, ST), | 553 | PROC(none, void, void, none, RC_NOCACHE, ST), |
554 | PROC(lookup, diropargs, diropres, fhandle, RC_NOCACHE, ST+FH+AT), | 554 | PROC(lookup, diropargs, diropres, fhandle, RC_NOCACHE, ST+FH+AT), |
555 | PROC(readlink, readlinkargs, readlinkres, none, RC_NOCACHE, ST+1+NFS_MAXPATHLEN/4), | 555 | PROC(readlink, readlinkargs, readlinkres, none, RC_NOCACHE, ST+1+NFS_MAXPATHLEN/4), |
556 | PROC(read, readargs, readres, fhandle, RC_NOCACHE, ST+AT+1+NFSSVC_MAXBLKSIZE), | 556 | PROC(read, readargs, readres, fhandle, RC_NOCACHE, ST+AT+1+NFSSVC_MAXBLKSIZE/4), |
557 | PROC(none, void, void, none, RC_NOCACHE, ST), | 557 | PROC(none, void, void, none, RC_NOCACHE, ST), |
558 | PROC(write, writeargs, attrstat, fhandle, RC_REPLBUFF, ST+AT), | 558 | PROC(write, writeargs, attrstat, fhandle, RC_REPLBUFF, ST+AT), |
559 | PROC(create, createargs, diropres, fhandle, RC_REPLBUFF, ST+FH+AT), | 559 | PROC(create, createargs, diropres, fhandle, RC_REPLBUFF, ST+FH+AT), |
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index 31018333dc38..6aa92d0e6876 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c | |||
@@ -371,7 +371,6 @@ out_nfserr: | |||
371 | static ssize_t nfsd_getxattr(struct dentry *dentry, char *key, void **buf) | 371 | static ssize_t nfsd_getxattr(struct dentry *dentry, char *key, void **buf) |
372 | { | 372 | { |
373 | ssize_t buflen; | 373 | ssize_t buflen; |
374 | int error; | ||
375 | 374 | ||
376 | buflen = vfs_getxattr(dentry, key, NULL, 0); | 375 | buflen = vfs_getxattr(dentry, key, NULL, 0); |
377 | if (buflen <= 0) | 376 | if (buflen <= 0) |
@@ -381,10 +380,7 @@ static ssize_t nfsd_getxattr(struct dentry *dentry, char *key, void **buf) | |||
381 | if (!*buf) | 380 | if (!*buf) |
382 | return -ENOMEM; | 381 | return -ENOMEM; |
383 | 382 | ||
384 | error = vfs_getxattr(dentry, key, *buf, buflen); | 383 | return vfs_getxattr(dentry, key, *buf, buflen); |
385 | if (error < 0) | ||
386 | return error; | ||
387 | return buflen; | ||
388 | } | 384 | } |
389 | #endif | 385 | #endif |
390 | 386 | ||