Commit b59e3c0e authored by Neil Brown's avatar Neil Brown Committed by Linus Torvalds

[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: default avatarJ. Bruce Fields <bfields@citi.umich.edu>
Signed-off-by: default avatarNeil Brown <neilb@suse.de>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent f2327d9a
...@@ -2629,7 +2629,9 @@ alloc_init_lock_stateowner(unsigned int strhashval, struct nfs4_client *clp, str ...@@ -2629,7 +2629,9 @@ alloc_init_lock_stateowner(unsigned int strhashval, struct nfs4_client *clp, str
sop->so_is_open_owner = 0; sop->so_is_open_owner = 0;
sop->so_id = current_ownerid++; sop->so_id = current_ownerid++;
sop->so_client = clp; sop->so_client = clp;
sop->so_seqid = lock->lk_new_lock_seqid; /* It is the openowner seqid that will be incremented in encode in the
* case of new lockowners; so increment the lock seqid manually: */
sop->so_seqid = lock->lk_new_lock_seqid + 1;
sop->so_confirmed = 1; sop->so_confirmed = 1;
rp = &sop->so_replay; rp = &sop->so_replay;
rp->rp_status = NFSERR_SERVERFAULT; rp->rp_status = NFSERR_SERVERFAULT;
...@@ -2684,6 +2686,7 @@ int ...@@ -2684,6 +2686,7 @@ int
nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock *lock, struct nfs4_stateowner **replay_owner) nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock *lock, struct nfs4_stateowner **replay_owner)
{ {
struct nfs4_stateowner *open_sop = NULL; struct nfs4_stateowner *open_sop = NULL;
struct nfs4_stateowner *lock_sop = NULL;
struct nfs4_stateid *lock_stp; struct nfs4_stateid *lock_stp;
struct file *filp; struct file *filp;
struct file_lock file_lock; struct file_lock file_lock;
...@@ -2718,9 +2721,11 @@ nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock ...@@ -2718,9 +2721,11 @@ nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock
lock->lk_new_open_seqid, lock->lk_new_open_seqid,
&lock->lk_new_open_stateid, &lock->lk_new_open_stateid,
CHECK_FH | OPEN_STATE, CHECK_FH | OPEN_STATE,
&open_sop, &open_stp, lock); &lock->lk_stateowner, &open_stp,
lock);
if (status) if (status)
goto out; goto out;
open_sop = lock->lk_stateowner;
/* create lockowner and lock stateid */ /* create lockowner and lock stateid */
fp = open_stp->st_file; fp = open_stp->st_file;
strhashval = lock_ownerstr_hashval(fp->fi_inode, 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,16 +2735,15 @@ nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock
* the same file, or should they just be allowed (and * the same file, or should they just be allowed (and
* create new stateids)? */ * create new stateids)? */
status = nfserr_resource; status = nfserr_resource;
if (!(lock->lk_stateowner = alloc_init_lock_stateowner(strhashval, open_sop->so_client, open_stp, lock))) lock_sop = alloc_init_lock_stateowner(strhashval,
open_sop->so_client, open_stp, lock);
if (lock_sop == NULL)
goto out; goto out;
if ((lock_stp = alloc_init_lock_stateid(lock->lk_stateowner, lock_stp = alloc_init_lock_stateid(lock_sop, fp, open_stp);
fp, open_stp)) == NULL) { if (lock_stp == NULL) {
release_stateowner(lock->lk_stateowner); release_stateowner(lock_sop);
lock->lk_stateowner = NULL;
goto out; goto out;
} }
/* bump the open seqid used to create the lock */
open_sop->so_seqid++;
} else { } else {
/* lock (lock owner + lock stateid) already exists */ /* lock (lock owner + lock stateid) already exists */
status = nfs4_preprocess_seqid_op(current_fh, 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,6 +2753,7 @@ nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock
&lock->lk_stateowner, &lock_stp, lock); &lock->lk_stateowner, &lock_stp, lock);
if (status) if (status)
goto out; goto out;
lock_sop = lock->lk_stateowner;
} }
/* lock->lk_stateowner and lock_stp have been created or found */ /* lock->lk_stateowner and lock_stp have been created or found */
filp = lock_stp->st_vfs_file; 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,7 +2784,7 @@ nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock
status = nfserr_inval; status = nfserr_inval;
goto out; goto out;
} }
file_lock.fl_owner = (fl_owner_t) lock->lk_stateowner; file_lock.fl_owner = (fl_owner_t)lock_sop;
file_lock.fl_pid = current->tgid; file_lock.fl_pid = current->tgid;
file_lock.fl_file = filp; file_lock.fl_file = filp;
file_lock.fl_flags = FL_POSIX; file_lock.fl_flags = FL_POSIX;
...@@ -2835,9 +2840,6 @@ out_destroy_new_stateid: ...@@ -2835,9 +2840,6 @@ out_destroy_new_stateid:
* An error encountered after instantiation of the new * An error encountered after instantiation of the new
* stateid has forced us to destroy it. * stateid has forced us to destroy it.
*/ */
if (!seqid_mutating_err(status))
open_sop->so_seqid--;
release_state_owner(lock_stp, LOCK_STATE); release_state_owner(lock_stp, LOCK_STATE);
} }
out: out:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment