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 | ||
