Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=e6e21970baff4845de74584e2efc8c964a55d574
Commit:     e6e21970baff4845de74584e2efc8c964a55d574
Parent:     bb22629ee87eed5054f8b508dbe7c58abad0a324
Author:     Trond Myklebust <[EMAIL PROTECTED]>
AuthorDate: Wed Jan 2 16:27:16 2008 -0500
Committer:  Trond Myklebust <[EMAIL PROTECTED]>
CommitDate: Thu Jan 3 09:37:17 2008 -0500

    NFSv4: Fix open_to_lock_owner sequenceid allocation...
    
    NFSv4 file locking is currently completely broken since it doesn't respect
    the OPEN sequencing when it is given an unconfirmed lock_owner and needs to
    do an open_to_lock_owner. Worse: it breaks the sunrpc rules by doing a
    GFP_KERNEL allocation inside an rpciod callback.
    
    Fix is to preallocate the open seqid structure in nfs4_alloc_lockdata if we
    see that the lock_owner is unconfirmed.
    Then, in nfs4_lock_prepare() we wait for either the open_seqid, if
    the lock_owner is still unconfirmed, or else fall back to waiting on the
    standard lock_seqid.
    
    Signed-off-by: Trond Myklebust <[EMAIL PROTECTED]>
---
 fs/nfs/nfs4proc.c |   30 +++++++++++++++++++-----------
 1 files changed, 19 insertions(+), 11 deletions(-)

diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 571b5ec..9e2e1c7 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -3331,6 +3331,12 @@ static struct nfs4_lockdata *nfs4_alloc_lockdata(struct 
file_lock *fl,
 
        p->arg.fh = NFS_FH(inode);
        p->arg.fl = &p->fl;
+       if (!(lsp->ls_seqid.flags & NFS_SEQID_CONFIRMED)) {
+               p->arg.open_seqid = 
nfs_alloc_seqid(&lsp->ls_state->owner->so_seqid);
+               if (p->arg.open_seqid == NULL)
+                       goto out_free;
+
+       }
        p->arg.lock_seqid = nfs_alloc_seqid(&lsp->ls_seqid);
        if (p->arg.lock_seqid == NULL)
                goto out_free;
@@ -3343,6 +3349,8 @@ static struct nfs4_lockdata *nfs4_alloc_lockdata(struct 
file_lock *fl,
        memcpy(&p->fl, fl, sizeof(p->fl));
        return p;
 out_free:
+       if (p->arg.open_seqid != NULL)
+               nfs_free_seqid(p->arg.open_seqid);
        kfree(p);
        return NULL;
 }
@@ -3359,23 +3367,23 @@ static void nfs4_lock_prepare(struct rpc_task *task, 
void *calldata)
                .rpc_cred = sp->so_cred,
        };
 
-       if (nfs_wait_on_sequence(data->arg.lock_seqid, task) != 0)
-               return;
        dprintk("%s: begin!\n", __FUNCTION__);
        /* Do we need to do an open_to_lock_owner? */
        if (!(data->arg.lock_seqid->sequence->flags & NFS_SEQID_CONFIRMED)) {
-               data->arg.open_seqid = nfs_alloc_seqid(&sp->so_seqid);
-               if (data->arg.open_seqid == NULL) {
-                       data->rpc_status = -ENOMEM;
-                       task->tk_action = NULL;
-                       goto out;
-               }
+               if (nfs_wait_on_sequence(data->arg.open_seqid, task) != 0)
+                       return;
                data->arg.open_stateid = &state->stateid;
                data->arg.new_lock_owner = 1;
+               /* Retest in case we raced... */
+               if (!(data->arg.lock_seqid->sequence->flags & 
NFS_SEQID_CONFIRMED))
+                       goto do_rpc;
        }
+       if (nfs_wait_on_sequence(data->arg.lock_seqid, task) != 0)
+               return;
+       data->arg.new_lock_owner = 0;
+do_rpc:        
        data->timestamp = jiffies;
        rpc_call_setup(task, &msg, 0);
-out:
        dprintk("%s: done!, ret = %d\n", __FUNCTION__, data->rpc_status);
 }
 
@@ -3411,8 +3419,6 @@ static void nfs4_lock_release(void *calldata)
        struct nfs4_lockdata *data = calldata;
 
        dprintk("%s: begin!\n", __FUNCTION__);
-       if (data->arg.open_seqid != NULL)
-               nfs_free_seqid(data->arg.open_seqid);
        if (data->cancelled != 0) {
                struct rpc_task *task;
                task = nfs4_do_unlck(&data->fl, data->ctx, data->lsp,
@@ -3422,6 +3428,8 @@ static void nfs4_lock_release(void *calldata)
                dprintk("%s: cancelling lock!\n", __FUNCTION__);
        } else
                nfs_free_seqid(data->arg.lock_seqid);
+       if (data->arg.open_seqid != NULL)
+               nfs_free_seqid(data->arg.open_seqid);
        nfs4_put_lock_state(data->lsp);
        put_nfs_open_context(data->ctx);
        kfree(data);
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to