diff options
author | Neil Brown <neilb@suse.de> | 2005-09-13 04:25:38 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2005-09-13 11:22:32 -0400 |
commit | b59e3c0e172e3f3a147021aa16b929482b8d5846 (patch) | |
tree | 60aec6ff8a214adfa828af8a89460aca55731d46 | |
parent | f2327d9adb1e948a7041128e971effd8d6e2d42c (diff) |
[PATCH] nfsd4: fix open seqid incrementing in lock
In the case of a lock which introduces a new lockowner, the openowner's
sequence id should be incremented, even when the operation fails, if the
error is a sequence-id-mutating error. The current code fails to do that
in some cases. Fix this by using the same sequence-id-incrementing
mechanism that all other such operations use.
Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>
Signed-off-by: Neil Brown <neilb@suse.de>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r-- | fs/nfsd/nfs4state.c | 28 |
1 files changed, 15 insertions, 13 deletions
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index 11405e530e70..ec2fdb009bf1 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c | |||
@@ -2629,7 +2629,9 @@ alloc_init_lock_stateowner(unsigned int strhashval, struct nfs4_client *clp, str | |||
2629 | sop->so_is_open_owner = 0; | 2629 | sop->so_is_open_owner = 0; |
2630 | sop->so_id = current_ownerid++; | 2630 | sop->so_id = current_ownerid++; |
2631 | sop->so_client = clp; | 2631 | sop->so_client = clp; |
2632 | sop->so_seqid = lock->lk_new_lock_seqid; | 2632 | /* It is the openowner seqid that will be incremented in encode in the |
2633 | * case of new lockowners; so increment the lock seqid manually: */ | ||
2634 | sop->so_seqid = lock->lk_new_lock_seqid + 1; | ||
2633 | sop->so_confirmed = 1; | 2635 | sop->so_confirmed = 1; |
2634 | rp = &sop->so_replay; | 2636 | rp = &sop->so_replay; |
2635 | rp->rp_status = NFSERR_SERVERFAULT; | 2637 | rp->rp_status = NFSERR_SERVERFAULT; |
@@ -2684,6 +2686,7 @@ int | |||
2684 | nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock *lock, struct nfs4_stateowner **replay_owner) | 2686 | nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock *lock, struct nfs4_stateowner **replay_owner) |
2685 | { | 2687 | { |
2686 | struct nfs4_stateowner *open_sop = NULL; | 2688 | struct nfs4_stateowner *open_sop = NULL; |
2689 | struct nfs4_stateowner *lock_sop = NULL; | ||
2687 | struct nfs4_stateid *lock_stp; | 2690 | struct nfs4_stateid *lock_stp; |
2688 | struct file *filp; | 2691 | struct file *filp; |
2689 | struct file_lock file_lock; | 2692 | struct file_lock file_lock; |
@@ -2718,9 +2721,11 @@ nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock | |||
2718 | lock->lk_new_open_seqid, | 2721 | lock->lk_new_open_seqid, |
2719 | &lock->lk_new_open_stateid, | 2722 | &lock->lk_new_open_stateid, |
2720 | CHECK_FH | OPEN_STATE, | 2723 | CHECK_FH | OPEN_STATE, |
2721 | &open_sop, &open_stp, lock); | 2724 | &lock->lk_stateowner, &open_stp, |
2725 | lock); | ||
2722 | if (status) | 2726 | if (status) |
2723 | goto out; | 2727 | goto out; |
2728 | open_sop = lock->lk_stateowner; | ||
2724 | /* create lockowner and lock stateid */ | 2729 | /* create lockowner and lock stateid */ |
2725 | fp = open_stp->st_file; | 2730 | fp = open_stp->st_file; |
2726 | strhashval = lock_ownerstr_hashval(fp->fi_inode, | 2731 | strhashval = lock_ownerstr_hashval(fp->fi_inode, |
@@ -2730,16 +2735,15 @@ nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock | |||
2730 | * the same file, or should they just be allowed (and | 2735 | * the same file, or should they just be allowed (and |
2731 | * create new stateids)? */ | 2736 | * create new stateids)? */ |
2732 | status = nfserr_resource; | 2737 | status = nfserr_resource; |
2733 | if (!(lock->lk_stateowner = alloc_init_lock_stateowner(strhashval, open_sop->so_client, open_stp, lock))) | 2738 | lock_sop = alloc_init_lock_stateowner(strhashval, |
2739 | open_sop->so_client, open_stp, lock); | ||
2740 | if (lock_sop == NULL) | ||
2734 | goto out; | 2741 | goto out; |
2735 | if ((lock_stp = alloc_init_lock_stateid(lock->lk_stateowner, | 2742 | lock_stp = alloc_init_lock_stateid(lock_sop, fp, open_stp); |
2736 | fp, open_stp)) == NULL) { | 2743 | if (lock_stp == NULL) { |
2737 | release_stateowner(lock->lk_stateowner); | 2744 | release_stateowner(lock_sop); |
2738 | lock->lk_stateowner = NULL; | ||
2739 | goto out; | 2745 | goto out; |
2740 | } | 2746 | } |
2741 | /* bump the open seqid used to create the lock */ | ||
2742 | open_sop->so_seqid++; | ||
2743 | } else { | 2747 | } else { |
2744 | /* lock (lock owner + lock stateid) already exists */ | 2748 | /* lock (lock owner + lock stateid) already exists */ |
2745 | status = nfs4_preprocess_seqid_op(current_fh, | 2749 | status = nfs4_preprocess_seqid_op(current_fh, |
@@ -2749,6 +2753,7 @@ nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock | |||
2749 | &lock->lk_stateowner, &lock_stp, lock); | 2753 | &lock->lk_stateowner, &lock_stp, lock); |
2750 | if (status) | 2754 | if (status) |
2751 | goto out; | 2755 | goto out; |
2756 | lock_sop = lock->lk_stateowner; | ||
2752 | } | 2757 | } |
2753 | /* lock->lk_stateowner and lock_stp have been created or found */ | 2758 | /* lock->lk_stateowner and lock_stp have been created or found */ |
2754 | filp = lock_stp->st_vfs_file; | 2759 | filp = lock_stp->st_vfs_file; |
@@ -2779,7 +2784,7 @@ nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock | |||
2779 | status = nfserr_inval; | 2784 | status = nfserr_inval; |
2780 | goto out; | 2785 | goto out; |
2781 | } | 2786 | } |
2782 | file_lock.fl_owner = (fl_owner_t) lock->lk_stateowner; | 2787 | file_lock.fl_owner = (fl_owner_t)lock_sop; |
2783 | file_lock.fl_pid = current->tgid; | 2788 | file_lock.fl_pid = current->tgid; |
2784 | file_lock.fl_file = filp; | 2789 | file_lock.fl_file = filp; |
2785 | file_lock.fl_flags = FL_POSIX; | 2790 | file_lock.fl_flags = FL_POSIX; |
@@ -2835,9 +2840,6 @@ out_destroy_new_stateid: | |||
2835 | * An error encountered after instantiation of the new | 2840 | * An error encountered after instantiation of the new |
2836 | * stateid has forced us to destroy it. | 2841 | * stateid has forced us to destroy it. |
2837 | */ | 2842 | */ |
2838 | if (!seqid_mutating_err(status)) | ||
2839 | open_sop->so_seqid--; | ||
2840 | |||
2841 | release_state_owner(lock_stp, LOCK_STATE); | 2843 | release_state_owner(lock_stp, LOCK_STATE); |
2842 | } | 2844 | } |
2843 | out: | 2845 | out: |