diff options
Diffstat (limited to 'fs/nfsd/nfs4state.c')
-rw-r--r-- | fs/nfsd/nfs4state.c | 90 |
1 files changed, 47 insertions, 43 deletions
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index b83f8fb441e1..6bbefd06f10d 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c | |||
@@ -624,7 +624,7 @@ gen_callback(struct nfs4_client *clp, struct nfsd4_setclientid *se) | |||
624 | cb->cb_ident = se->se_callback_ident; | 624 | cb->cb_ident = se->se_callback_ident; |
625 | return; | 625 | return; |
626 | out_err: | 626 | out_err: |
627 | printk(KERN_INFO "NFSD: this client (clientid %08x/%08x) " | 627 | dprintk(KERN_INFO "NFSD: this client (clientid %08x/%08x) " |
628 | "will not receive delegations\n", | 628 | "will not receive delegations\n", |
629 | clp->cl_clientid.cl_boot, clp->cl_clientid.cl_id); | 629 | clp->cl_clientid.cl_boot, clp->cl_clientid.cl_id); |
630 | 630 | ||
@@ -678,13 +678,12 @@ nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_setclientid *setclid) | |||
678 | int status; | 678 | int status; |
679 | char dname[HEXDIR_LEN]; | 679 | char dname[HEXDIR_LEN]; |
680 | 680 | ||
681 | status = nfserr_inval; | ||
682 | if (!check_name(clname)) | 681 | if (!check_name(clname)) |
683 | goto out; | 682 | return nfserr_inval; |
684 | 683 | ||
685 | status = nfs4_make_rec_clidname(dname, &clname); | 684 | status = nfs4_make_rec_clidname(dname, &clname); |
686 | if (status) | 685 | if (status) |
687 | goto out; | 686 | return status; |
688 | 687 | ||
689 | /* | 688 | /* |
690 | * XXX The Duplicate Request Cache (DRC) has been checked (??) | 689 | * XXX The Duplicate Request Cache (DRC) has been checked (??) |
@@ -2014,7 +2013,7 @@ STALE_STATEID(stateid_t *stateid) | |||
2014 | { | 2013 | { |
2015 | if (stateid->si_boot == boot_time) | 2014 | if (stateid->si_boot == boot_time) |
2016 | return 0; | 2015 | return 0; |
2017 | printk("NFSD: stale stateid (%08x/%08x/%08x/%08x)!\n", | 2016 | dprintk("NFSD: stale stateid (%08x/%08x/%08x/%08x)!\n", |
2018 | stateid->si_boot, stateid->si_stateownerid, stateid->si_fileid, | 2017 | stateid->si_boot, stateid->si_stateownerid, stateid->si_fileid, |
2019 | stateid->si_generation); | 2018 | stateid->si_generation); |
2020 | return 1; | 2019 | return 1; |
@@ -2275,7 +2274,7 @@ nfs4_preprocess_seqid_op(struct svc_fh *current_fh, u32 seqid, stateid_t *statei | |||
2275 | 2274 | ||
2276 | check_replay: | 2275 | check_replay: |
2277 | if (seqid == sop->so_seqid - 1) { | 2276 | if (seqid == sop->so_seqid - 1) { |
2278 | printk("NFSD: preprocess_seqid_op: retransmission?\n"); | 2277 | dprintk("NFSD: preprocess_seqid_op: retransmission?\n"); |
2279 | /* indicate replay to calling function */ | 2278 | /* indicate replay to calling function */ |
2280 | return NFSERR_REPLAY_ME; | 2279 | return NFSERR_REPLAY_ME; |
2281 | } | 2280 | } |
@@ -2286,7 +2285,7 @@ check_replay: | |||
2286 | } | 2285 | } |
2287 | 2286 | ||
2288 | int | 2287 | int |
2289 | nfsd4_open_confirm(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open_confirm *oc) | 2288 | nfsd4_open_confirm(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open_confirm *oc, struct nfs4_stateowner **replay_owner) |
2290 | { | 2289 | { |
2291 | int status; | 2290 | int status; |
2292 | struct nfs4_stateowner *sop; | 2291 | struct nfs4_stateowner *sop; |
@@ -2320,8 +2319,10 @@ nfsd4_open_confirm(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfs | |||
2320 | 2319 | ||
2321 | nfsd4_create_clid_dir(sop->so_client); | 2320 | nfsd4_create_clid_dir(sop->so_client); |
2322 | out: | 2321 | out: |
2323 | if (oc->oc_stateowner) | 2322 | if (oc->oc_stateowner) { |
2324 | nfs4_get_stateowner(oc->oc_stateowner); | 2323 | nfs4_get_stateowner(oc->oc_stateowner); |
2324 | *replay_owner = oc->oc_stateowner; | ||
2325 | } | ||
2325 | nfs4_unlock_state(); | 2326 | nfs4_unlock_state(); |
2326 | return status; | 2327 | return status; |
2327 | } | 2328 | } |
@@ -2352,7 +2353,7 @@ reset_union_bmap_deny(unsigned long deny, unsigned long *bmap) | |||
2352 | } | 2353 | } |
2353 | 2354 | ||
2354 | int | 2355 | int |
2355 | nfsd4_open_downgrade(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open_downgrade *od) | 2356 | nfsd4_open_downgrade(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open_downgrade *od, struct nfs4_stateowner **replay_owner) |
2356 | { | 2357 | { |
2357 | int status; | 2358 | int status; |
2358 | struct nfs4_stateid *stp; | 2359 | struct nfs4_stateid *stp; |
@@ -2394,8 +2395,10 @@ nfsd4_open_downgrade(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct n | |||
2394 | memcpy(&od->od_stateid, &stp->st_stateid, sizeof(stateid_t)); | 2395 | memcpy(&od->od_stateid, &stp->st_stateid, sizeof(stateid_t)); |
2395 | status = nfs_ok; | 2396 | status = nfs_ok; |
2396 | out: | 2397 | out: |
2397 | if (od->od_stateowner) | 2398 | if (od->od_stateowner) { |
2398 | nfs4_get_stateowner(od->od_stateowner); | 2399 | nfs4_get_stateowner(od->od_stateowner); |
2400 | *replay_owner = od->od_stateowner; | ||
2401 | } | ||
2399 | nfs4_unlock_state(); | 2402 | nfs4_unlock_state(); |
2400 | return status; | 2403 | return status; |
2401 | } | 2404 | } |
@@ -2404,7 +2407,7 @@ out: | |||
2404 | * nfs4_unlock_state() called after encode | 2407 | * nfs4_unlock_state() called after encode |
2405 | */ | 2408 | */ |
2406 | int | 2409 | int |
2407 | nfsd4_close(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_close *close) | 2410 | nfsd4_close(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_close *close, struct nfs4_stateowner **replay_owner) |
2408 | { | 2411 | { |
2409 | int status; | 2412 | int status; |
2410 | struct nfs4_stateid *stp; | 2413 | struct nfs4_stateid *stp; |
@@ -2430,8 +2433,10 @@ nfsd4_close(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_clos | |||
2430 | /* release_state_owner() calls nfsd_close() if needed */ | 2433 | /* release_state_owner() calls nfsd_close() if needed */ |
2431 | release_state_owner(stp, OPEN_STATE); | 2434 | release_state_owner(stp, OPEN_STATE); |
2432 | out: | 2435 | out: |
2433 | if (close->cl_stateowner) | 2436 | if (close->cl_stateowner) { |
2434 | nfs4_get_stateowner(close->cl_stateowner); | 2437 | nfs4_get_stateowner(close->cl_stateowner); |
2438 | *replay_owner = close->cl_stateowner; | ||
2439 | } | ||
2435 | nfs4_unlock_state(); | 2440 | nfs4_unlock_state(); |
2436 | return status; | 2441 | return status; |
2437 | } | 2442 | } |
@@ -2500,8 +2505,7 @@ find_stateid(stateid_t *stid, int flags) | |||
2500 | (local->st_stateid.si_fileid == f_id)) | 2505 | (local->st_stateid.si_fileid == f_id)) |
2501 | return local; | 2506 | return local; |
2502 | } | 2507 | } |
2503 | } else | 2508 | } |
2504 | printk("NFSD: find_stateid: ERROR: no state flag\n"); | ||
2505 | return NULL; | 2509 | return NULL; |
2506 | } | 2510 | } |
2507 | 2511 | ||
@@ -2624,7 +2628,9 @@ alloc_init_lock_stateowner(unsigned int strhashval, struct nfs4_client *clp, str | |||
2624 | sop->so_is_open_owner = 0; | 2628 | sop->so_is_open_owner = 0; |
2625 | sop->so_id = current_ownerid++; | 2629 | sop->so_id = current_ownerid++; |
2626 | sop->so_client = clp; | 2630 | sop->so_client = clp; |
2627 | sop->so_seqid = lock->lk_new_lock_seqid; | 2631 | /* It is the openowner seqid that will be incremented in encode in the |
2632 | * case of new lockowners; so increment the lock seqid manually: */ | ||
2633 | sop->so_seqid = lock->lk_new_lock_seqid + 1; | ||
2628 | sop->so_confirmed = 1; | 2634 | sop->so_confirmed = 1; |
2629 | rp = &sop->so_replay; | 2635 | rp = &sop->so_replay; |
2630 | rp->rp_status = NFSERR_SERVERFAULT; | 2636 | rp->rp_status = NFSERR_SERVERFAULT; |
@@ -2676,9 +2682,10 @@ check_lock_length(u64 offset, u64 length) | |||
2676 | * LOCK operation | 2682 | * LOCK operation |
2677 | */ | 2683 | */ |
2678 | int | 2684 | int |
2679 | nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock *lock) | 2685 | nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock *lock, struct nfs4_stateowner **replay_owner) |
2680 | { | 2686 | { |
2681 | struct nfs4_stateowner *open_sop = NULL; | 2687 | struct nfs4_stateowner *open_sop = NULL; |
2688 | struct nfs4_stateowner *lock_sop = NULL; | ||
2682 | struct nfs4_stateid *lock_stp; | 2689 | struct nfs4_stateid *lock_stp; |
2683 | struct file *filp; | 2690 | struct file *filp; |
2684 | struct file_lock file_lock; | 2691 | struct file_lock file_lock; |
@@ -2705,19 +2712,19 @@ nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock | |||
2705 | struct nfs4_file *fp; | 2712 | struct nfs4_file *fp; |
2706 | 2713 | ||
2707 | status = nfserr_stale_clientid; | 2714 | status = nfserr_stale_clientid; |
2708 | if (STALE_CLIENTID(&lock->lk_new_clientid)) { | 2715 | if (STALE_CLIENTID(&lock->lk_new_clientid)) |
2709 | printk("NFSD: nfsd4_lock: clientid is stale!\n"); | ||
2710 | goto out; | 2716 | goto out; |
2711 | } | ||
2712 | 2717 | ||
2713 | /* validate and update open stateid and open seqid */ | 2718 | /* validate and update open stateid and open seqid */ |
2714 | status = nfs4_preprocess_seqid_op(current_fh, | 2719 | status = nfs4_preprocess_seqid_op(current_fh, |
2715 | lock->lk_new_open_seqid, | 2720 | lock->lk_new_open_seqid, |
2716 | &lock->lk_new_open_stateid, | 2721 | &lock->lk_new_open_stateid, |
2717 | CHECK_FH | OPEN_STATE, | 2722 | CHECK_FH | OPEN_STATE, |
2718 | &open_sop, &open_stp, lock); | 2723 | &lock->lk_stateowner, &open_stp, |
2724 | lock); | ||
2719 | if (status) | 2725 | if (status) |
2720 | goto out; | 2726 | goto out; |
2727 | open_sop = lock->lk_stateowner; | ||
2721 | /* create lockowner and lock stateid */ | 2728 | /* create lockowner and lock stateid */ |
2722 | fp = open_stp->st_file; | 2729 | fp = open_stp->st_file; |
2723 | strhashval = lock_ownerstr_hashval(fp->fi_inode, | 2730 | strhashval = lock_ownerstr_hashval(fp->fi_inode, |
@@ -2727,16 +2734,15 @@ nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock | |||
2727 | * the same file, or should they just be allowed (and | 2734 | * the same file, or should they just be allowed (and |
2728 | * create new stateids)? */ | 2735 | * create new stateids)? */ |
2729 | status = nfserr_resource; | 2736 | status = nfserr_resource; |
2730 | if (!(lock->lk_stateowner = alloc_init_lock_stateowner(strhashval, open_sop->so_client, open_stp, lock))) | 2737 | lock_sop = alloc_init_lock_stateowner(strhashval, |
2738 | open_sop->so_client, open_stp, lock); | ||
2739 | if (lock_sop == NULL) | ||
2731 | goto out; | 2740 | goto out; |
2732 | if ((lock_stp = alloc_init_lock_stateid(lock->lk_stateowner, | 2741 | lock_stp = alloc_init_lock_stateid(lock_sop, fp, open_stp); |
2733 | fp, open_stp)) == NULL) { | 2742 | if (lock_stp == NULL) { |
2734 | release_stateowner(lock->lk_stateowner); | 2743 | release_stateowner(lock_sop); |
2735 | lock->lk_stateowner = NULL; | ||
2736 | goto out; | 2744 | goto out; |
2737 | } | 2745 | } |
2738 | /* bump the open seqid used to create the lock */ | ||
2739 | open_sop->so_seqid++; | ||
2740 | } else { | 2746 | } else { |
2741 | /* lock (lock owner + lock stateid) already exists */ | 2747 | /* lock (lock owner + lock stateid) already exists */ |
2742 | status = nfs4_preprocess_seqid_op(current_fh, | 2748 | status = nfs4_preprocess_seqid_op(current_fh, |
@@ -2746,12 +2752,13 @@ nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock | |||
2746 | &lock->lk_stateowner, &lock_stp, lock); | 2752 | &lock->lk_stateowner, &lock_stp, lock); |
2747 | if (status) | 2753 | if (status) |
2748 | goto out; | 2754 | goto out; |
2755 | lock_sop = lock->lk_stateowner; | ||
2749 | } | 2756 | } |
2750 | /* lock->lk_stateowner and lock_stp have been created or found */ | 2757 | /* lock->lk_stateowner and lock_stp have been created or found */ |
2751 | filp = lock_stp->st_vfs_file; | 2758 | filp = lock_stp->st_vfs_file; |
2752 | 2759 | ||
2753 | if ((status = fh_verify(rqstp, current_fh, S_IFREG, MAY_LOCK))) { | 2760 | if ((status = fh_verify(rqstp, current_fh, S_IFREG, MAY_LOCK))) { |
2754 | printk("NFSD: nfsd4_lock: permission denied!\n"); | 2761 | dprintk("NFSD: nfsd4_lock: permission denied!\n"); |
2755 | goto out; | 2762 | goto out; |
2756 | } | 2763 | } |
2757 | 2764 | ||
@@ -2776,7 +2783,7 @@ nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock | |||
2776 | status = nfserr_inval; | 2783 | status = nfserr_inval; |
2777 | goto out; | 2784 | goto out; |
2778 | } | 2785 | } |
2779 | file_lock.fl_owner = (fl_owner_t) lock->lk_stateowner; | 2786 | file_lock.fl_owner = (fl_owner_t)lock_sop; |
2780 | file_lock.fl_pid = current->tgid; | 2787 | file_lock.fl_pid = current->tgid; |
2781 | file_lock.fl_file = filp; | 2788 | file_lock.fl_file = filp; |
2782 | file_lock.fl_flags = FL_POSIX; | 2789 | file_lock.fl_flags = FL_POSIX; |
@@ -2832,14 +2839,13 @@ out_destroy_new_stateid: | |||
2832 | * An error encountered after instantiation of the new | 2839 | * An error encountered after instantiation of the new |
2833 | * stateid has forced us to destroy it. | 2840 | * stateid has forced us to destroy it. |
2834 | */ | 2841 | */ |
2835 | if (!seqid_mutating_err(status)) | ||
2836 | open_sop->so_seqid--; | ||
2837 | |||
2838 | release_state_owner(lock_stp, LOCK_STATE); | 2842 | release_state_owner(lock_stp, LOCK_STATE); |
2839 | } | 2843 | } |
2840 | out: | 2844 | out: |
2841 | if (lock->lk_stateowner) | 2845 | if (lock->lk_stateowner) { |
2842 | nfs4_get_stateowner(lock->lk_stateowner); | 2846 | nfs4_get_stateowner(lock->lk_stateowner); |
2847 | *replay_owner = lock->lk_stateowner; | ||
2848 | } | ||
2843 | nfs4_unlock_state(); | 2849 | nfs4_unlock_state(); |
2844 | return status; | 2850 | return status; |
2845 | } | 2851 | } |
@@ -2866,13 +2872,11 @@ nfsd4_lockt(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock | |||
2866 | nfs4_lock_state(); | 2872 | nfs4_lock_state(); |
2867 | 2873 | ||
2868 | status = nfserr_stale_clientid; | 2874 | status = nfserr_stale_clientid; |
2869 | if (STALE_CLIENTID(&lockt->lt_clientid)) { | 2875 | if (STALE_CLIENTID(&lockt->lt_clientid)) |
2870 | printk("NFSD: nfsd4_lockt: clientid is stale!\n"); | ||
2871 | goto out; | 2876 | goto out; |
2872 | } | ||
2873 | 2877 | ||
2874 | if ((status = fh_verify(rqstp, current_fh, S_IFREG, 0))) { | 2878 | if ((status = fh_verify(rqstp, current_fh, S_IFREG, 0))) { |
2875 | printk("NFSD: nfsd4_lockt: fh_verify() failed!\n"); | 2879 | dprintk("NFSD: nfsd4_lockt: fh_verify() failed!\n"); |
2876 | if (status == nfserr_symlink) | 2880 | if (status == nfserr_symlink) |
2877 | status = nfserr_inval; | 2881 | status = nfserr_inval; |
2878 | goto out; | 2882 | goto out; |
@@ -2930,7 +2934,7 @@ out: | |||
2930 | } | 2934 | } |
2931 | 2935 | ||
2932 | int | 2936 | int |
2933 | nfsd4_locku(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_locku *locku) | 2937 | nfsd4_locku(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_locku *locku, struct nfs4_stateowner **replay_owner) |
2934 | { | 2938 | { |
2935 | struct nfs4_stateid *stp; | 2939 | struct nfs4_stateid *stp; |
2936 | struct file *filp = NULL; | 2940 | struct file *filp = NULL; |
@@ -2976,7 +2980,7 @@ nfsd4_locku(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock | |||
2976 | if (file_lock.fl_ops && file_lock.fl_ops->fl_release_private) | 2980 | if (file_lock.fl_ops && file_lock.fl_ops->fl_release_private) |
2977 | file_lock.fl_ops->fl_release_private(&file_lock); | 2981 | file_lock.fl_ops->fl_release_private(&file_lock); |
2978 | if (status) { | 2982 | if (status) { |
2979 | printk("NFSD: nfs4_locku: posix_lock_file failed!\n"); | 2983 | dprintk("NFSD: nfs4_locku: posix_lock_file failed!\n"); |
2980 | goto out_nfserr; | 2984 | goto out_nfserr; |
2981 | } | 2985 | } |
2982 | /* | 2986 | /* |
@@ -2986,8 +2990,10 @@ nfsd4_locku(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock | |||
2986 | memcpy(&locku->lu_stateid, &stp->st_stateid, sizeof(stateid_t)); | 2990 | memcpy(&locku->lu_stateid, &stp->st_stateid, sizeof(stateid_t)); |
2987 | 2991 | ||
2988 | out: | 2992 | out: |
2989 | if (locku->lu_stateowner) | 2993 | if (locku->lu_stateowner) { |
2990 | nfs4_get_stateowner(locku->lu_stateowner); | 2994 | nfs4_get_stateowner(locku->lu_stateowner); |
2995 | *replay_owner = locku->lu_stateowner; | ||
2996 | } | ||
2991 | nfs4_unlock_state(); | 2997 | nfs4_unlock_state(); |
2992 | return status; | 2998 | return status; |
2993 | 2999 | ||
@@ -3036,10 +3042,8 @@ nfsd4_release_lockowner(struct svc_rqst *rqstp, struct nfsd4_release_lockowner * | |||
3036 | /* XXX check for lease expiration */ | 3042 | /* XXX check for lease expiration */ |
3037 | 3043 | ||
3038 | status = nfserr_stale_clientid; | 3044 | status = nfserr_stale_clientid; |
3039 | if (STALE_CLIENTID(clid)) { | 3045 | if (STALE_CLIENTID(clid)) |
3040 | printk("NFSD: nfsd4_release_lockowner: clientid is stale!\n"); | ||
3041 | return status; | 3046 | return status; |
3042 | } | ||
3043 | 3047 | ||
3044 | nfs4_lock_state(); | 3048 | nfs4_lock_state(); |
3045 | 3049 | ||