diff options
Diffstat (limited to 'fs/nfsd')
-rw-r--r-- | fs/nfsd/export.c | 22 | ||||
-rw-r--r-- | fs/nfsd/lockd.c | 1 | ||||
-rw-r--r-- | fs/nfsd/nfs2acl.c | 14 | ||||
-rw-r--r-- | fs/nfsd/nfs3acl.c | 3 | ||||
-rw-r--r-- | fs/nfsd/nfs3proc.c | 1 | ||||
-rw-r--r-- | fs/nfsd/nfs4acl.c | 2 | ||||
-rw-r--r-- | fs/nfsd/nfs4proc.c | 1 | ||||
-rw-r--r-- | fs/nfsd/nfs4recover.c | 1 | ||||
-rw-r--r-- | fs/nfsd/nfs4state.c | 65 | ||||
-rw-r--r-- | fs/nfsd/nfs4xdr.c | 1 | ||||
-rw-r--r-- | fs/nfsd/nfsfh.c | 1 | ||||
-rw-r--r-- | fs/nfsd/nfsproc.c | 2 | ||||
-rw-r--r-- | fs/nfsd/nfssvc.c | 1 | ||||
-rw-r--r-- | fs/nfsd/vfs.c | 63 | ||||
-rw-r--r-- | fs/nfsd/vfs.h | 98 |
15 files changed, 210 insertions, 66 deletions
diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c index c1c9e035d4a4..b73baba3fb97 100644 --- a/fs/nfsd/export.c +++ b/fs/nfsd/export.c | |||
@@ -1320,6 +1320,23 @@ rqst_exp_parent(struct svc_rqst *rqstp, struct path *path) | |||
1320 | return exp; | 1320 | return exp; |
1321 | } | 1321 | } |
1322 | 1322 | ||
1323 | static struct svc_export *find_fsidzero_export(struct svc_rqst *rqstp) | ||
1324 | { | ||
1325 | struct svc_export *exp; | ||
1326 | u32 fsidv[2]; | ||
1327 | |||
1328 | mk_fsid(FSID_NUM, fsidv, 0, 0, 0, NULL); | ||
1329 | |||
1330 | exp = rqst_exp_find(rqstp, FSID_NUM, fsidv); | ||
1331 | /* | ||
1332 | * We shouldn't have accepting an nfsv4 request at all if we | ||
1333 | * don't have a pseudoexport!: | ||
1334 | */ | ||
1335 | if (IS_ERR(exp) && PTR_ERR(exp) == -ENOENT) | ||
1336 | exp = ERR_PTR(-ESERVERFAULT); | ||
1337 | return exp; | ||
1338 | } | ||
1339 | |||
1323 | /* | 1340 | /* |
1324 | * Called when we need the filehandle for the root of the pseudofs, | 1341 | * Called when we need the filehandle for the root of the pseudofs, |
1325 | * for a given NFSv4 client. The root is defined to be the | 1342 | * for a given NFSv4 client. The root is defined to be the |
@@ -1330,11 +1347,8 @@ exp_pseudoroot(struct svc_rqst *rqstp, struct svc_fh *fhp) | |||
1330 | { | 1347 | { |
1331 | struct svc_export *exp; | 1348 | struct svc_export *exp; |
1332 | __be32 rv; | 1349 | __be32 rv; |
1333 | u32 fsidv[2]; | ||
1334 | |||
1335 | mk_fsid(FSID_NUM, fsidv, 0, 0, 0, NULL); | ||
1336 | 1350 | ||
1337 | exp = rqst_exp_find(rqstp, FSID_NUM, fsidv); | 1351 | exp = find_fsidzero_export(rqstp); |
1338 | if (IS_ERR(exp)) | 1352 | if (IS_ERR(exp)) |
1339 | return nfserrno(PTR_ERR(exp)); | 1353 | return nfserrno(PTR_ERR(exp)); |
1340 | rv = fh_compose(fhp, exp, exp->ex_path.dentry, NULL); | 1354 | rv = fh_compose(fhp, exp, exp->ex_path.dentry, NULL); |
diff --git a/fs/nfsd/lockd.c b/fs/nfsd/lockd.c index b2786a5f9afe..812bc64874f6 100644 --- a/fs/nfsd/lockd.c +++ b/fs/nfsd/lockd.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <linux/sunrpc/svc.h> | 16 | #include <linux/sunrpc/svc.h> |
17 | #include <linux/nfsd/nfsd.h> | 17 | #include <linux/nfsd/nfsd.h> |
18 | #include <linux/lockd/bind.h> | 18 | #include <linux/lockd/bind.h> |
19 | #include "vfs.h" | ||
19 | 20 | ||
20 | #define NFSDDBG_FACILITY NFSDDBG_LOCKD | 21 | #define NFSDDBG_FACILITY NFSDDBG_LOCKD |
21 | 22 | ||
diff --git a/fs/nfsd/nfs2acl.c b/fs/nfsd/nfs2acl.c index 4e3219e84116..38c883d48b02 100644 --- a/fs/nfsd/nfs2acl.c +++ b/fs/nfsd/nfs2acl.c | |||
@@ -14,6 +14,7 @@ | |||
14 | #include <linux/nfsd/xdr3.h> | 14 | #include <linux/nfsd/xdr3.h> |
15 | #include <linux/posix_acl.h> | 15 | #include <linux/posix_acl.h> |
16 | #include <linux/nfsacl.h> | 16 | #include <linux/nfsacl.h> |
17 | #include "vfs.h" | ||
17 | 18 | ||
18 | #define NFSDDBG_FACILITY NFSDDBG_PROC | 19 | #define NFSDDBG_FACILITY NFSDDBG_PROC |
19 | #define RETURN_STATUS(st) { resp->status = (st); return (st); } | 20 | #define RETURN_STATUS(st) { resp->status = (st); return (st); } |
@@ -217,6 +218,16 @@ static int nfsaclsvc_decode_accessargs(struct svc_rqst *rqstp, __be32 *p, | |||
217 | * XDR encode functions | 218 | * XDR encode functions |
218 | */ | 219 | */ |
219 | 220 | ||
221 | /* | ||
222 | * There must be an encoding function for void results so svc_process | ||
223 | * will work properly. | ||
224 | */ | ||
225 | int | ||
226 | nfsaclsvc_encode_voidres(struct svc_rqst *rqstp, __be32 *p, void *dummy) | ||
227 | { | ||
228 | return xdr_ressize_check(rqstp, p); | ||
229 | } | ||
230 | |||
220 | /* GETACL */ | 231 | /* GETACL */ |
221 | static int nfsaclsvc_encode_getaclres(struct svc_rqst *rqstp, __be32 *p, | 232 | static int nfsaclsvc_encode_getaclres(struct svc_rqst *rqstp, __be32 *p, |
222 | struct nfsd3_getaclres *resp) | 233 | struct nfsd3_getaclres *resp) |
@@ -308,7 +319,6 @@ static int nfsaclsvc_release_access(struct svc_rqst *rqstp, __be32 *p, | |||
308 | } | 319 | } |
309 | 320 | ||
310 | #define nfsaclsvc_decode_voidargs NULL | 321 | #define nfsaclsvc_decode_voidargs NULL |
311 | #define nfsaclsvc_encode_voidres NULL | ||
312 | #define nfsaclsvc_release_void NULL | 322 | #define nfsaclsvc_release_void NULL |
313 | #define nfsd3_fhandleargs nfsd_fhandle | 323 | #define nfsd3_fhandleargs nfsd_fhandle |
314 | #define nfsd3_attrstatres nfsd_attrstat | 324 | #define nfsd3_attrstatres nfsd_attrstat |
@@ -346,5 +356,5 @@ struct svc_version nfsd_acl_version2 = { | |||
346 | .vs_proc = nfsd_acl_procedures2, | 356 | .vs_proc = nfsd_acl_procedures2, |
347 | .vs_dispatch = nfsd_dispatch, | 357 | .vs_dispatch = nfsd_dispatch, |
348 | .vs_xdrsize = NFS3_SVC_XDRSIZE, | 358 | .vs_xdrsize = NFS3_SVC_XDRSIZE, |
349 | .vs_hidden = 1, | 359 | .vs_hidden = 0, |
350 | }; | 360 | }; |
diff --git a/fs/nfsd/nfs3acl.c b/fs/nfsd/nfs3acl.c index 9981dbb377a3..526d85a65f76 100644 --- a/fs/nfsd/nfs3acl.c +++ b/fs/nfsd/nfs3acl.c | |||
@@ -13,6 +13,7 @@ | |||
13 | #include <linux/nfsd/xdr3.h> | 13 | #include <linux/nfsd/xdr3.h> |
14 | #include <linux/posix_acl.h> | 14 | #include <linux/posix_acl.h> |
15 | #include <linux/nfsacl.h> | 15 | #include <linux/nfsacl.h> |
16 | #include "vfs.h" | ||
16 | 17 | ||
17 | #define RETURN_STATUS(st) { resp->status = (st); return (st); } | 18 | #define RETURN_STATUS(st) { resp->status = (st); return (st); } |
18 | 19 | ||
@@ -264,6 +265,6 @@ struct svc_version nfsd_acl_version3 = { | |||
264 | .vs_proc = nfsd_acl_procedures3, | 265 | .vs_proc = nfsd_acl_procedures3, |
265 | .vs_dispatch = nfsd_dispatch, | 266 | .vs_dispatch = nfsd_dispatch, |
266 | .vs_xdrsize = NFS3_SVC_XDRSIZE, | 267 | .vs_xdrsize = NFS3_SVC_XDRSIZE, |
267 | .vs_hidden = 1, | 268 | .vs_hidden = 0, |
268 | }; | 269 | }; |
269 | 270 | ||
diff --git a/fs/nfsd/nfs3proc.c b/fs/nfsd/nfs3proc.c index a713c418a922..1a259d313e14 100644 --- a/fs/nfsd/nfs3proc.c +++ b/fs/nfsd/nfs3proc.c | |||
@@ -25,6 +25,7 @@ | |||
25 | #include <linux/nfsd/cache.h> | 25 | #include <linux/nfsd/cache.h> |
26 | #include <linux/nfsd/xdr3.h> | 26 | #include <linux/nfsd/xdr3.h> |
27 | #include <linux/nfs3.h> | 27 | #include <linux/nfs3.h> |
28 | #include "vfs.h" | ||
28 | 29 | ||
29 | #define NFSDDBG_FACILITY NFSDDBG_PROC | 30 | #define NFSDDBG_FACILITY NFSDDBG_PROC |
30 | 31 | ||
diff --git a/fs/nfsd/nfs4acl.c b/fs/nfsd/nfs4acl.c index 725d02f210e2..6d9c6aabc85e 100644 --- a/fs/nfsd/nfs4acl.c +++ b/fs/nfsd/nfs4acl.c | |||
@@ -389,7 +389,7 @@ sort_pacl(struct posix_acl *pacl) | |||
389 | sort_pacl_range(pacl, 1, i-1); | 389 | sort_pacl_range(pacl, 1, i-1); |
390 | 390 | ||
391 | BUG_ON(pacl->a_entries[i].e_tag != ACL_GROUP_OBJ); | 391 | BUG_ON(pacl->a_entries[i].e_tag != ACL_GROUP_OBJ); |
392 | j = i++; | 392 | j = ++i; |
393 | while (pacl->a_entries[j].e_tag == ACL_GROUP) | 393 | while (pacl->a_entries[j].e_tag == ACL_GROUP) |
394 | j++; | 394 | j++; |
395 | sort_pacl_range(pacl, i, j-1); | 395 | sort_pacl_range(pacl, i, j-1); |
diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c index bebc0c2e1b0a..60a93cdefef5 100644 --- a/fs/nfsd/nfs4proc.c +++ b/fs/nfsd/nfs4proc.c | |||
@@ -48,6 +48,7 @@ | |||
48 | #include <linux/nfsd/xdr4.h> | 48 | #include <linux/nfsd/xdr4.h> |
49 | #include <linux/nfs4_acl.h> | 49 | #include <linux/nfs4_acl.h> |
50 | #include <linux/sunrpc/gss_api.h> | 50 | #include <linux/sunrpc/gss_api.h> |
51 | #include "vfs.h" | ||
51 | 52 | ||
52 | #define NFSDDBG_FACILITY NFSDDBG_PROC | 53 | #define NFSDDBG_FACILITY NFSDDBG_PROC |
53 | 54 | ||
diff --git a/fs/nfsd/nfs4recover.c b/fs/nfsd/nfs4recover.c index b5348405046b..c7a6b245c7ad 100644 --- a/fs/nfsd/nfs4recover.c +++ b/fs/nfsd/nfs4recover.c | |||
@@ -47,6 +47,7 @@ | |||
47 | #include <linux/crypto.h> | 47 | #include <linux/crypto.h> |
48 | #include <linux/sched.h> | 48 | #include <linux/sched.h> |
49 | #include <linux/mount.h> | 49 | #include <linux/mount.h> |
50 | #include "vfs.h" | ||
50 | 51 | ||
51 | #define NFSDDBG_FACILITY NFSDDBG_PROC | 52 | #define NFSDDBG_FACILITY NFSDDBG_PROC |
52 | 53 | ||
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index 2153f9bdbebd..850960e5d626 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c | |||
@@ -56,6 +56,7 @@ | |||
56 | #include <linux/module.h> | 56 | #include <linux/module.h> |
57 | #include <linux/sunrpc/svcauth_gss.h> | 57 | #include <linux/sunrpc/svcauth_gss.h> |
58 | #include <linux/sunrpc/clnt.h> | 58 | #include <linux/sunrpc/clnt.h> |
59 | #include "vfs.h" | ||
59 | 60 | ||
60 | #define NFSDDBG_FACILITY NFSDDBG_PROC | 61 | #define NFSDDBG_FACILITY NFSDDBG_PROC |
61 | 62 | ||
@@ -477,13 +478,14 @@ static int set_forechannel_drc_size(struct nfsd4_channel_attrs *fchan) | |||
477 | 478 | ||
478 | /* | 479 | /* |
479 | * fchan holds the client values on input, and the server values on output | 480 | * fchan holds the client values on input, and the server values on output |
481 | * sv_max_mesg is the maximum payload plus one page for overhead. | ||
480 | */ | 482 | */ |
481 | static int init_forechannel_attrs(struct svc_rqst *rqstp, | 483 | static int init_forechannel_attrs(struct svc_rqst *rqstp, |
482 | struct nfsd4_channel_attrs *session_fchan, | 484 | struct nfsd4_channel_attrs *session_fchan, |
483 | struct nfsd4_channel_attrs *fchan) | 485 | struct nfsd4_channel_attrs *fchan) |
484 | { | 486 | { |
485 | int status = 0; | 487 | int status = 0; |
486 | __u32 maxcount = svc_max_payload(rqstp); | 488 | __u32 maxcount = nfsd_serv->sv_max_mesg; |
487 | 489 | ||
488 | /* headerpadsz set to zero in encode routine */ | 490 | /* headerpadsz set to zero in encode routine */ |
489 | 491 | ||
@@ -523,6 +525,15 @@ free_session_slots(struct nfsd4_session *ses) | |||
523 | kfree(ses->se_slots[i]); | 525 | kfree(ses->se_slots[i]); |
524 | } | 526 | } |
525 | 527 | ||
528 | /* | ||
529 | * We don't actually need to cache the rpc and session headers, so we | ||
530 | * can allocate a little less for each slot: | ||
531 | */ | ||
532 | static inline int slot_bytes(struct nfsd4_channel_attrs *ca) | ||
533 | { | ||
534 | return ca->maxresp_cached - NFSD_MIN_HDR_SEQ_SZ; | ||
535 | } | ||
536 | |||
526 | static int | 537 | static int |
527 | alloc_init_session(struct svc_rqst *rqstp, struct nfs4_client *clp, | 538 | alloc_init_session(struct svc_rqst *rqstp, struct nfs4_client *clp, |
528 | struct nfsd4_create_session *cses) | 539 | struct nfsd4_create_session *cses) |
@@ -554,7 +565,7 @@ alloc_init_session(struct svc_rqst *rqstp, struct nfs4_client *clp, | |||
554 | memcpy(new, &tmp, sizeof(*new)); | 565 | memcpy(new, &tmp, sizeof(*new)); |
555 | 566 | ||
556 | /* allocate each struct nfsd4_slot and data cache in one piece */ | 567 | /* allocate each struct nfsd4_slot and data cache in one piece */ |
557 | cachesize = new->se_fchannel.maxresp_cached - NFSD_MIN_HDR_SEQ_SZ; | 568 | cachesize = slot_bytes(&new->se_fchannel); |
558 | for (i = 0; i < new->se_fchannel.maxreqs; i++) { | 569 | for (i = 0; i < new->se_fchannel.maxreqs; i++) { |
559 | sp = kzalloc(sizeof(*sp) + cachesize, GFP_KERNEL); | 570 | sp = kzalloc(sizeof(*sp) + cachesize, GFP_KERNEL); |
560 | if (!sp) | 571 | if (!sp) |
@@ -628,10 +639,12 @@ void | |||
628 | free_session(struct kref *kref) | 639 | free_session(struct kref *kref) |
629 | { | 640 | { |
630 | struct nfsd4_session *ses; | 641 | struct nfsd4_session *ses; |
642 | int mem; | ||
631 | 643 | ||
632 | ses = container_of(kref, struct nfsd4_session, se_ref); | 644 | ses = container_of(kref, struct nfsd4_session, se_ref); |
633 | spin_lock(&nfsd_drc_lock); | 645 | spin_lock(&nfsd_drc_lock); |
634 | nfsd_drc_mem_used -= ses->se_fchannel.maxreqs * NFSD_SLOT_CACHE_SIZE; | 646 | mem = ses->se_fchannel.maxreqs * slot_bytes(&ses->se_fchannel); |
647 | nfsd_drc_mem_used -= mem; | ||
635 | spin_unlock(&nfsd_drc_lock); | 648 | spin_unlock(&nfsd_drc_lock); |
636 | free_session_slots(ses); | 649 | free_session_slots(ses); |
637 | kfree(ses); | 650 | kfree(ses); |
@@ -2404,11 +2417,8 @@ nfs4_open_delegation(struct svc_fh *fh, struct nfsd4_open *open, struct nfs4_sta | |||
2404 | 2417 | ||
2405 | memcpy(&open->op_delegate_stateid, &dp->dl_stateid, sizeof(dp->dl_stateid)); | 2418 | memcpy(&open->op_delegate_stateid, &dp->dl_stateid, sizeof(dp->dl_stateid)); |
2406 | 2419 | ||
2407 | dprintk("NFSD: delegation stateid=(%08x/%08x/%08x/%08x)\n\n", | 2420 | dprintk("NFSD: delegation stateid=" STATEID_FMT "\n", |
2408 | dp->dl_stateid.si_boot, | 2421 | STATEID_VAL(&dp->dl_stateid)); |
2409 | dp->dl_stateid.si_stateownerid, | ||
2410 | dp->dl_stateid.si_fileid, | ||
2411 | dp->dl_stateid.si_generation); | ||
2412 | out: | 2422 | out: |
2413 | if (open->op_claim_type == NFS4_OPEN_CLAIM_PREVIOUS | 2423 | if (open->op_claim_type == NFS4_OPEN_CLAIM_PREVIOUS |
2414 | && flag == NFS4_OPEN_DELEGATE_NONE | 2424 | && flag == NFS4_OPEN_DELEGATE_NONE |
@@ -2498,9 +2508,8 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf | |||
2498 | 2508 | ||
2499 | status = nfs_ok; | 2509 | status = nfs_ok; |
2500 | 2510 | ||
2501 | dprintk("nfs4_process_open2: stateid=(%08x/%08x/%08x/%08x)\n", | 2511 | dprintk("%s: stateid=" STATEID_FMT "\n", __func__, |
2502 | stp->st_stateid.si_boot, stp->st_stateid.si_stateownerid, | 2512 | STATEID_VAL(&stp->st_stateid)); |
2503 | stp->st_stateid.si_fileid, stp->st_stateid.si_generation); | ||
2504 | out: | 2513 | out: |
2505 | if (fp) | 2514 | if (fp) |
2506 | put_nfs4_file(fp); | 2515 | put_nfs4_file(fp); |
@@ -2666,9 +2675,8 @@ STALE_STATEID(stateid_t *stateid) | |||
2666 | { | 2675 | { |
2667 | if (time_after((unsigned long)boot_time, | 2676 | if (time_after((unsigned long)boot_time, |
2668 | (unsigned long)stateid->si_boot)) { | 2677 | (unsigned long)stateid->si_boot)) { |
2669 | dprintk("NFSD: stale stateid (%08x/%08x/%08x/%08x)!\n", | 2678 | dprintk("NFSD: stale stateid " STATEID_FMT "!\n", |
2670 | stateid->si_boot, stateid->si_stateownerid, | 2679 | STATEID_VAL(stateid)); |
2671 | stateid->si_fileid, stateid->si_generation); | ||
2672 | return 1; | 2680 | return 1; |
2673 | } | 2681 | } |
2674 | return 0; | 2682 | return 0; |
@@ -2680,9 +2688,8 @@ EXPIRED_STATEID(stateid_t *stateid) | |||
2680 | if (time_before((unsigned long)boot_time, | 2688 | if (time_before((unsigned long)boot_time, |
2681 | ((unsigned long)stateid->si_boot)) && | 2689 | ((unsigned long)stateid->si_boot)) && |
2682 | time_before((unsigned long)(stateid->si_boot + lease_time), get_seconds())) { | 2690 | time_before((unsigned long)(stateid->si_boot + lease_time), get_seconds())) { |
2683 | dprintk("NFSD: expired stateid (%08x/%08x/%08x/%08x)!\n", | 2691 | dprintk("NFSD: expired stateid " STATEID_FMT "!\n", |
2684 | stateid->si_boot, stateid->si_stateownerid, | 2692 | STATEID_VAL(stateid)); |
2685 | stateid->si_fileid, stateid->si_generation); | ||
2686 | return 1; | 2693 | return 1; |
2687 | } | 2694 | } |
2688 | return 0; | 2695 | return 0; |
@@ -2696,9 +2703,8 @@ stateid_error_map(stateid_t *stateid) | |||
2696 | if (EXPIRED_STATEID(stateid)) | 2703 | if (EXPIRED_STATEID(stateid)) |
2697 | return nfserr_expired; | 2704 | return nfserr_expired; |
2698 | 2705 | ||
2699 | dprintk("NFSD: bad stateid (%08x/%08x/%08x/%08x)!\n", | 2706 | dprintk("NFSD: bad stateid " STATEID_FMT "!\n", |
2700 | stateid->si_boot, stateid->si_stateownerid, | 2707 | STATEID_VAL(stateid)); |
2701 | stateid->si_fileid, stateid->si_generation); | ||
2702 | return nfserr_bad_stateid; | 2708 | return nfserr_bad_stateid; |
2703 | } | 2709 | } |
2704 | 2710 | ||
@@ -2884,10 +2890,8 @@ nfs4_preprocess_seqid_op(struct nfsd4_compound_state *cstate, u32 seqid, | |||
2884 | struct svc_fh *current_fh = &cstate->current_fh; | 2890 | struct svc_fh *current_fh = &cstate->current_fh; |
2885 | __be32 status; | 2891 | __be32 status; |
2886 | 2892 | ||
2887 | dprintk("NFSD: preprocess_seqid_op: seqid=%d " | 2893 | dprintk("NFSD: %s: seqid=%d stateid = " STATEID_FMT "\n", __func__, |
2888 | "stateid = (%08x/%08x/%08x/%08x)\n", seqid, | 2894 | seqid, STATEID_VAL(stateid)); |
2889 | stateid->si_boot, stateid->si_stateownerid, stateid->si_fileid, | ||
2890 | stateid->si_generation); | ||
2891 | 2895 | ||
2892 | *stpp = NULL; | 2896 | *stpp = NULL; |
2893 | *sopp = NULL; | 2897 | *sopp = NULL; |
@@ -3019,12 +3023,8 @@ nfsd4_open_confirm(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, | |||
3019 | sop->so_confirmed = 1; | 3023 | sop->so_confirmed = 1; |
3020 | update_stateid(&stp->st_stateid); | 3024 | update_stateid(&stp->st_stateid); |
3021 | memcpy(&oc->oc_resp_stateid, &stp->st_stateid, sizeof(stateid_t)); | 3025 | memcpy(&oc->oc_resp_stateid, &stp->st_stateid, sizeof(stateid_t)); |
3022 | dprintk("NFSD: nfsd4_open_confirm: success, seqid=%d " | 3026 | dprintk("NFSD: %s: success, seqid=%d stateid=" STATEID_FMT "\n", |
3023 | "stateid=(%08x/%08x/%08x/%08x)\n", oc->oc_seqid, | 3027 | __func__, oc->oc_seqid, STATEID_VAL(&stp->st_stateid)); |
3024 | stp->st_stateid.si_boot, | ||
3025 | stp->st_stateid.si_stateownerid, | ||
3026 | stp->st_stateid.si_fileid, | ||
3027 | stp->st_stateid.si_generation); | ||
3028 | 3028 | ||
3029 | nfsd4_create_clid_dir(sop->so_client); | 3029 | nfsd4_create_clid_dir(sop->so_client); |
3030 | out: | 3030 | out: |
@@ -3283,9 +3283,8 @@ find_delegation_stateid(struct inode *ino, stateid_t *stid) | |||
3283 | struct nfs4_file *fp; | 3283 | struct nfs4_file *fp; |
3284 | struct nfs4_delegation *dl; | 3284 | struct nfs4_delegation *dl; |
3285 | 3285 | ||
3286 | dprintk("NFSD:find_delegation_stateid stateid=(%08x/%08x/%08x/%08x)\n", | 3286 | dprintk("NFSD: %s: stateid=" STATEID_FMT "\n", __func__, |
3287 | stid->si_boot, stid->si_stateownerid, | 3287 | STATEID_VAL(stid)); |
3288 | stid->si_fileid, stid->si_generation); | ||
3289 | 3288 | ||
3290 | fp = find_file(ino); | 3289 | fp = find_file(ino); |
3291 | if (!fp) | 3290 | if (!fp) |
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c index 0fbd50cee1f6..db0fc55670b3 100644 --- a/fs/nfsd/nfs4xdr.c +++ b/fs/nfsd/nfs4xdr.c | |||
@@ -57,6 +57,7 @@ | |||
57 | #include <linux/nfs4_acl.h> | 57 | #include <linux/nfs4_acl.h> |
58 | #include <linux/sunrpc/gss_api.h> | 58 | #include <linux/sunrpc/gss_api.h> |
59 | #include <linux/sunrpc/svcauth_gss.h> | 59 | #include <linux/sunrpc/svcauth_gss.h> |
60 | #include "vfs.h" | ||
60 | 61 | ||
61 | #define NFSDDBG_FACILITY NFSDDBG_XDR | 62 | #define NFSDDBG_FACILITY NFSDDBG_XDR |
62 | 63 | ||
diff --git a/fs/nfsd/nfsfh.c b/fs/nfsd/nfsfh.c index 01965b2f3a76..d0d8a217a3ea 100644 --- a/fs/nfsd/nfsfh.c +++ b/fs/nfsd/nfsfh.c | |||
@@ -22,6 +22,7 @@ | |||
22 | #include <linux/sunrpc/svc.h> | 22 | #include <linux/sunrpc/svc.h> |
23 | #include <linux/sunrpc/svcauth_gss.h> | 23 | #include <linux/sunrpc/svcauth_gss.h> |
24 | #include <linux/nfsd/nfsd.h> | 24 | #include <linux/nfsd/nfsd.h> |
25 | #include "vfs.h" | ||
25 | #include "auth.h" | 26 | #include "auth.h" |
26 | 27 | ||
27 | #define NFSDDBG_FACILITY NFSDDBG_FH | 28 | #define NFSDDBG_FACILITY NFSDDBG_FH |
diff --git a/fs/nfsd/nfsproc.c b/fs/nfsd/nfsproc.c index 0eb9c820b7a6..6c967e1ba37b 100644 --- a/fs/nfsd/nfsproc.c +++ b/fs/nfsd/nfsproc.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include <linux/nfsd/nfsd.h> | 24 | #include <linux/nfsd/nfsd.h> |
25 | #include <linux/nfsd/cache.h> | 25 | #include <linux/nfsd/cache.h> |
26 | #include <linux/nfsd/xdr.h> | 26 | #include <linux/nfsd/xdr.h> |
27 | #include "vfs.h" | ||
27 | 28 | ||
28 | typedef struct svc_rqst svc_rqst; | 29 | typedef struct svc_rqst svc_rqst; |
29 | typedef struct svc_buf svc_buf; | 30 | typedef struct svc_buf svc_buf; |
@@ -758,6 +759,7 @@ nfserrno (int errno) | |||
758 | { nfserr_io, -ETXTBSY }, | 759 | { nfserr_io, -ETXTBSY }, |
759 | { nfserr_notsupp, -EOPNOTSUPP }, | 760 | { nfserr_notsupp, -EOPNOTSUPP }, |
760 | { nfserr_toosmall, -ETOOSMALL }, | 761 | { nfserr_toosmall, -ETOOSMALL }, |
762 | { nfserr_serverfault, -ESERVERFAULT }, | ||
761 | }; | 763 | }; |
762 | int i; | 764 | int i; |
763 | 765 | ||
diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c index 67ea83eedd43..2944b31dcbe6 100644 --- a/fs/nfsd/nfssvc.c +++ b/fs/nfsd/nfssvc.c | |||
@@ -35,6 +35,7 @@ | |||
35 | #include <linux/lockd/bind.h> | 35 | #include <linux/lockd/bind.h> |
36 | #include <linux/nfsacl.h> | 36 | #include <linux/nfsacl.h> |
37 | #include <linux/seq_file.h> | 37 | #include <linux/seq_file.h> |
38 | #include "vfs.h" | ||
38 | 39 | ||
39 | #define NFSDDBG_FACILITY NFSDDBG_SVC | 40 | #define NFSDDBG_FACILITY NFSDDBG_SVC |
40 | 41 | ||
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index a293f0273263..a7038ede671a 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c | |||
@@ -56,6 +56,7 @@ | |||
56 | #endif /* CONFIG_NFSD_V4 */ | 56 | #endif /* CONFIG_NFSD_V4 */ |
57 | #include <linux/jhash.h> | 57 | #include <linux/jhash.h> |
58 | #include <linux/ima.h> | 58 | #include <linux/ima.h> |
59 | #include "vfs.h" | ||
59 | 60 | ||
60 | #include <asm/uaccess.h> | 61 | #include <asm/uaccess.h> |
61 | 62 | ||
@@ -141,6 +142,40 @@ out: | |||
141 | return err; | 142 | return err; |
142 | } | 143 | } |
143 | 144 | ||
145 | static void follow_to_parent(struct path *path) | ||
146 | { | ||
147 | struct dentry *dp; | ||
148 | |||
149 | while (path->dentry == path->mnt->mnt_root && follow_up(path)) | ||
150 | ; | ||
151 | dp = dget_parent(path->dentry); | ||
152 | dput(path->dentry); | ||
153 | path->dentry = dp; | ||
154 | } | ||
155 | |||
156 | static int nfsd_lookup_parent(struct svc_rqst *rqstp, struct dentry *dparent, struct svc_export **exp, struct dentry **dentryp) | ||
157 | { | ||
158 | struct svc_export *exp2; | ||
159 | struct path path = {.mnt = mntget((*exp)->ex_path.mnt), | ||
160 | .dentry = dget(dparent)}; | ||
161 | |||
162 | follow_to_parent(&path); | ||
163 | |||
164 | exp2 = rqst_exp_parent(rqstp, &path); | ||
165 | if (PTR_ERR(exp2) == -ENOENT) { | ||
166 | *dentryp = dget(dparent); | ||
167 | } else if (IS_ERR(exp2)) { | ||
168 | path_put(&path); | ||
169 | return PTR_ERR(exp2); | ||
170 | } else { | ||
171 | *dentryp = dget(path.dentry); | ||
172 | exp_put(*exp); | ||
173 | *exp = exp2; | ||
174 | } | ||
175 | path_put(&path); | ||
176 | return 0; | ||
177 | } | ||
178 | |||
144 | __be32 | 179 | __be32 |
145 | nfsd_lookup_dentry(struct svc_rqst *rqstp, struct svc_fh *fhp, | 180 | nfsd_lookup_dentry(struct svc_rqst *rqstp, struct svc_fh *fhp, |
146 | const char *name, unsigned int len, | 181 | const char *name, unsigned int len, |
@@ -169,35 +204,13 @@ nfsd_lookup_dentry(struct svc_rqst *rqstp, struct svc_fh *fhp, | |||
169 | dentry = dget(dparent); | 204 | dentry = dget(dparent); |
170 | else if (dparent != exp->ex_path.dentry) | 205 | else if (dparent != exp->ex_path.dentry) |
171 | dentry = dget_parent(dparent); | 206 | dentry = dget_parent(dparent); |
172 | else if (!EX_NOHIDE(exp)) | 207 | else if (!EX_NOHIDE(exp) && !nfsd_v4client(rqstp)) |
173 | dentry = dget(dparent); /* .. == . just like at / */ | 208 | dentry = dget(dparent); /* .. == . just like at / */ |
174 | else { | 209 | else { |
175 | /* checking mountpoint crossing is very different when stepping up */ | 210 | /* checking mountpoint crossing is very different when stepping up */ |
176 | struct svc_export *exp2 = NULL; | 211 | host_err = nfsd_lookup_parent(rqstp, dparent, &exp, &dentry); |
177 | struct dentry *dp; | 212 | if (host_err) |
178 | struct path path = {.mnt = mntget(exp->ex_path.mnt), | ||
179 | .dentry = dget(dparent)}; | ||
180 | |||
181 | while (path.dentry == path.mnt->mnt_root && | ||
182 | follow_up(&path)) | ||
183 | ; | ||
184 | dp = dget_parent(path.dentry); | ||
185 | dput(path.dentry); | ||
186 | path.dentry = dp; | ||
187 | |||
188 | exp2 = rqst_exp_parent(rqstp, &path); | ||
189 | if (PTR_ERR(exp2) == -ENOENT) { | ||
190 | dentry = dget(dparent); | ||
191 | } else if (IS_ERR(exp2)) { | ||
192 | host_err = PTR_ERR(exp2); | ||
193 | path_put(&path); | ||
194 | goto out_nfserr; | 213 | goto out_nfserr; |
195 | } else { | ||
196 | dentry = dget(path.dentry); | ||
197 | exp_put(exp); | ||
198 | exp = exp2; | ||
199 | } | ||
200 | path_put(&path); | ||
201 | } | 214 | } |
202 | } else { | 215 | } else { |
203 | fh_lock(fhp); | 216 | fh_lock(fhp); |
diff --git a/fs/nfsd/vfs.h b/fs/nfsd/vfs.h new file mode 100644 index 000000000000..b8011fd2fcab --- /dev/null +++ b/fs/nfsd/vfs.h | |||
@@ -0,0 +1,98 @@ | |||
1 | /* | ||
2 | * Copyright (C) 1995-1997 Olaf Kirch <okir@monad.swb.de> | ||
3 | */ | ||
4 | |||
5 | #ifndef LINUX_NFSD_VFS_H | ||
6 | #define LINUX_NFSD_VFS_H | ||
7 | |||
8 | /* | ||
9 | * Flags for nfsd_permission | ||
10 | */ | ||
11 | #define NFSD_MAY_NOP 0 | ||
12 | #define NFSD_MAY_EXEC 1 /* == MAY_EXEC */ | ||
13 | #define NFSD_MAY_WRITE 2 /* == MAY_WRITE */ | ||
14 | #define NFSD_MAY_READ 4 /* == MAY_READ */ | ||
15 | #define NFSD_MAY_SATTR 8 | ||
16 | #define NFSD_MAY_TRUNC 16 | ||
17 | #define NFSD_MAY_LOCK 32 | ||
18 | #define NFSD_MAY_OWNER_OVERRIDE 64 | ||
19 | #define NFSD_MAY_LOCAL_ACCESS 128 /* IRIX doing local access check on device special file*/ | ||
20 | #define NFSD_MAY_BYPASS_GSS_ON_ROOT 256 | ||
21 | |||
22 | #define NFSD_MAY_CREATE (NFSD_MAY_EXEC|NFSD_MAY_WRITE) | ||
23 | #define NFSD_MAY_REMOVE (NFSD_MAY_EXEC|NFSD_MAY_WRITE|NFSD_MAY_TRUNC) | ||
24 | |||
25 | /* | ||
26 | * Callback function for readdir | ||
27 | */ | ||
28 | typedef int (*nfsd_dirop_t)(struct inode *, struct dentry *, int, int); | ||
29 | |||
30 | /* nfsd/vfs.c */ | ||
31 | int fh_lock_parent(struct svc_fh *, struct dentry *); | ||
32 | int nfsd_racache_init(int); | ||
33 | void nfsd_racache_shutdown(void); | ||
34 | int nfsd_cross_mnt(struct svc_rqst *rqstp, struct dentry **dpp, | ||
35 | struct svc_export **expp); | ||
36 | __be32 nfsd_lookup(struct svc_rqst *, struct svc_fh *, | ||
37 | const char *, unsigned int, struct svc_fh *); | ||
38 | __be32 nfsd_lookup_dentry(struct svc_rqst *, struct svc_fh *, | ||
39 | const char *, unsigned int, | ||
40 | struct svc_export **, struct dentry **); | ||
41 | __be32 nfsd_setattr(struct svc_rqst *, struct svc_fh *, | ||
42 | struct iattr *, int, time_t); | ||
43 | #ifdef CONFIG_NFSD_V4 | ||
44 | __be32 nfsd4_set_nfs4_acl(struct svc_rqst *, struct svc_fh *, | ||
45 | struct nfs4_acl *); | ||
46 | int nfsd4_get_nfs4_acl(struct svc_rqst *, struct dentry *, struct nfs4_acl **); | ||
47 | #endif /* CONFIG_NFSD_V4 */ | ||
48 | __be32 nfsd_create(struct svc_rqst *, struct svc_fh *, | ||
49 | char *name, int len, struct iattr *attrs, | ||
50 | int type, dev_t rdev, struct svc_fh *res); | ||
51 | #ifdef CONFIG_NFSD_V3 | ||
52 | __be32 nfsd_access(struct svc_rqst *, struct svc_fh *, u32 *, u32 *); | ||
53 | __be32 nfsd_create_v3(struct svc_rqst *, struct svc_fh *, | ||
54 | char *name, int len, struct iattr *attrs, | ||
55 | struct svc_fh *res, int createmode, | ||
56 | u32 *verifier, int *truncp, int *created); | ||
57 | __be32 nfsd_commit(struct svc_rqst *, struct svc_fh *, | ||
58 | loff_t, unsigned long); | ||
59 | #endif /* CONFIG_NFSD_V3 */ | ||
60 | __be32 nfsd_open(struct svc_rqst *, struct svc_fh *, int, | ||
61 | int, struct file **); | ||
62 | void nfsd_close(struct file *); | ||
63 | __be32 nfsd_read(struct svc_rqst *, struct svc_fh *, struct file *, | ||
64 | loff_t, struct kvec *, int, unsigned long *); | ||
65 | __be32 nfsd_write(struct svc_rqst *, struct svc_fh *,struct file *, | ||
66 | loff_t, struct kvec *,int, unsigned long *, int *); | ||
67 | __be32 nfsd_readlink(struct svc_rqst *, struct svc_fh *, | ||
68 | char *, int *); | ||
69 | __be32 nfsd_symlink(struct svc_rqst *, struct svc_fh *, | ||
70 | char *name, int len, char *path, int plen, | ||
71 | struct svc_fh *res, struct iattr *); | ||
72 | __be32 nfsd_link(struct svc_rqst *, struct svc_fh *, | ||
73 | char *, int, struct svc_fh *); | ||
74 | __be32 nfsd_rename(struct svc_rqst *, | ||
75 | struct svc_fh *, char *, int, | ||
76 | struct svc_fh *, char *, int); | ||
77 | __be32 nfsd_remove(struct svc_rqst *, | ||
78 | struct svc_fh *, char *, int); | ||
79 | __be32 nfsd_unlink(struct svc_rqst *, struct svc_fh *, int type, | ||
80 | char *name, int len); | ||
81 | int nfsd_truncate(struct svc_rqst *, struct svc_fh *, | ||
82 | unsigned long size); | ||
83 | __be32 nfsd_readdir(struct svc_rqst *, struct svc_fh *, | ||
84 | loff_t *, struct readdir_cd *, filldir_t); | ||
85 | __be32 nfsd_statfs(struct svc_rqst *, struct svc_fh *, | ||
86 | struct kstatfs *, int access); | ||
87 | |||
88 | int nfsd_notify_change(struct inode *, struct iattr *); | ||
89 | __be32 nfsd_permission(struct svc_rqst *, struct svc_export *, | ||
90 | struct dentry *, int); | ||
91 | int nfsd_sync_dir(struct dentry *dp); | ||
92 | |||
93 | #if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL) | ||
94 | struct posix_acl *nfsd_get_posix_acl(struct svc_fh *, int); | ||
95 | int nfsd_set_posix_acl(struct svc_fh *, int, struct posix_acl *); | ||
96 | #endif | ||
97 | |||
98 | #endif /* LINUX_NFSD_VFS_H */ | ||