From 2f74c0a05612b9c2014b5b67833dba9b9f523948 Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Tue, 8 Jan 2008 17:56:07 -0500 Subject: NFSv4: Clean up the OPEN/CLOSE serialisation code Reduce the time spent locking the rpc_sequence structure by queuing the nfs_seqid only when we are ready to take the lock (when calling nfs_wait_on_sequence). Signed-off-by: Trond Myklebust --- fs/nfs/nfs4proc.c | 30 +++++++++++------------------- 1 file changed, 11 insertions(+), 19 deletions(-) (limited to 'fs/nfs/nfs4proc.c') diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 9e2e1c7291db..a51a7537f3f6 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -3331,15 +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.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; + goto out_free_seqid; p->arg.lock_stateid = &lsp->ls_stateid; p->arg.lock_owner.clientid = server->nfs_client->cl_clientid; p->arg.lock_owner.id = lsp->ls_id.id; @@ -3348,9 +3345,9 @@ static struct nfs4_lockdata *nfs4_alloc_lockdata(struct file_lock *fl, p->ctx = get_nfs_open_context(ctx); memcpy(&p->fl, fl, sizeof(p->fl)); return p; +out_free_seqid: + nfs_free_seqid(p->arg.open_seqid); out_free: - if (p->arg.open_seqid != NULL) - nfs_free_seqid(p->arg.open_seqid); kfree(p); return NULL; } @@ -3368,20 +3365,16 @@ static void nfs4_lock_prepare(struct rpc_task *task, void *calldata) }; dprintk("%s: begin!\n", __FUNCTION__); + if (nfs_wait_on_sequence(data->arg.lock_seqid, task) != 0) + return; /* Do we need to do an open_to_lock_owner? */ if (!(data->arg.lock_seqid->sequence->flags & NFS_SEQID_CONFIRMED)) { 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: + } else + data->arg.new_lock_owner = 0; data->timestamp = jiffies; rpc_call_setup(task, &msg, 0); dprintk("%s: done!, ret = %d\n", __FUNCTION__, data->rpc_status); @@ -3419,6 +3412,7 @@ static void nfs4_lock_release(void *calldata) struct nfs4_lockdata *data = calldata; dprintk("%s: begin!\n", __FUNCTION__); + 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, @@ -3428,8 +3422,6 @@ 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); -- cgit v1.2.3 From c970aa85e71bd581726c42df843f6f129db275ac Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Sat, 14 Jul 2007 15:39:59 -0400 Subject: SUNRPC: Clean up rpc_run_task Make it use the new task initialiser structure instead of acting as a wrapper. Signed-off-by: Trond Myklebust --- fs/nfs/nfs4proc.c | 49 ++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 42 insertions(+), 7 deletions(-) (limited to 'fs/nfs/nfs4proc.c') diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index a51a7537f3f6..ff2c5f83ce87 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -779,12 +779,18 @@ static int _nfs4_proc_open_confirm(struct nfs4_opendata *data) { struct nfs_server *server = NFS_SERVER(data->dir->d_inode); struct rpc_task *task; + struct rpc_task_setup task_setup_data = { + .rpc_client = server->client, + .callback_ops = &nfs4_open_confirm_ops, + .callback_data = data, + .flags = RPC_TASK_ASYNC, + }; int status; kref_get(&data->kref); data->rpc_done = 0; data->rpc_status = 0; - task = rpc_run_task(server->client, RPC_TASK_ASYNC, &nfs4_open_confirm_ops, data); + task = rpc_run_task(&task_setup_data); if (IS_ERR(task)) return PTR_ERR(task); status = nfs4_wait_for_completion_rpc_task(task); @@ -908,13 +914,19 @@ static int _nfs4_proc_open(struct nfs4_opendata *data) struct nfs_openargs *o_arg = &data->o_arg; struct nfs_openres *o_res = &data->o_res; struct rpc_task *task; + struct rpc_task_setup task_setup_data = { + .rpc_client = server->client, + .callback_ops = &nfs4_open_ops, + .callback_data = data, + .flags = RPC_TASK_ASYNC, + }; int status; kref_get(&data->kref); data->rpc_done = 0; data->rpc_status = 0; data->cancelled = 0; - task = rpc_run_task(server->client, RPC_TASK_ASYNC, &nfs4_open_ops, data); + task = rpc_run_task(&task_setup_data); if (IS_ERR(task)) return PTR_ERR(task); status = nfs4_wait_for_completion_rpc_task(task); @@ -1309,6 +1321,11 @@ int nfs4_do_close(struct path *path, struct nfs4_state *state, int wait) struct nfs4_closedata *calldata; struct nfs4_state_owner *sp = state->owner; struct rpc_task *task; + struct rpc_task_setup task_setup_data = { + .rpc_client = server->client, + .callback_ops = &nfs4_close_ops, + .flags = RPC_TASK_ASYNC, + }; int status = -ENOMEM; calldata = kmalloc(sizeof(*calldata), GFP_KERNEL); @@ -1328,7 +1345,8 @@ int nfs4_do_close(struct path *path, struct nfs4_state *state, int wait) calldata->path.mnt = mntget(path->mnt); calldata->path.dentry = dget(path->dentry); - task = rpc_run_task(server->client, RPC_TASK_ASYNC, &nfs4_close_ops, calldata); + task_setup_data.callback_data = calldata; + task = rpc_run_task(&task_setup_data); if (IS_ERR(task)) return PTR_ERR(task); status = 0; @@ -3027,6 +3045,11 @@ static int _nfs4_proc_delegreturn(struct inode *inode, struct rpc_cred *cred, co struct nfs4_delegreturndata *data; struct nfs_server *server = NFS_SERVER(inode); struct rpc_task *task; + struct rpc_task_setup task_setup_data = { + .rpc_client = server->client, + .callback_ops = &nfs4_delegreturn_ops, + .flags = RPC_TASK_ASYNC, + }; int status; data = kmalloc(sizeof(*data), GFP_KERNEL); @@ -3043,7 +3066,8 @@ static int _nfs4_proc_delegreturn(struct inode *inode, struct rpc_cred *cred, co data->timestamp = jiffies; data->rpc_status = 0; - task = rpc_run_task(NFS_CLIENT(inode), RPC_TASK_ASYNC, &nfs4_delegreturn_ops, data); + task_setup_data.callback_data = data; + task = rpc_run_task(&task_setup_data); if (IS_ERR(task)) return PTR_ERR(task); status = nfs4_wait_for_completion_rpc_task(task); @@ -3260,6 +3284,11 @@ static struct rpc_task *nfs4_do_unlck(struct file_lock *fl, struct nfs_seqid *seqid) { struct nfs4_unlockdata *data; + struct rpc_task_setup task_setup_data = { + .rpc_client = NFS_CLIENT(lsp->ls_state->inode), + .callback_ops = &nfs4_locku_ops, + .flags = RPC_TASK_ASYNC, + }; /* Ensure this is an unlock - when canceling a lock, the * canceled lock is passed in, and it won't be an unlock. @@ -3272,7 +3301,8 @@ static struct rpc_task *nfs4_do_unlck(struct file_lock *fl, return ERR_PTR(-ENOMEM); } - return rpc_run_task(NFS_CLIENT(lsp->ls_state->inode), RPC_TASK_ASYNC, &nfs4_locku_ops, data); + task_setup_data.callback_data = data; + return rpc_run_task(&task_setup_data); } static int nfs4_proc_unlck(struct nfs4_state *state, int cmd, struct file_lock *request) @@ -3438,6 +3468,11 @@ static int _nfs4_do_setlk(struct nfs4_state *state, int cmd, struct file_lock *f { struct nfs4_lockdata *data; struct rpc_task *task; + struct rpc_task_setup task_setup_data = { + .rpc_client = NFS_CLIENT(state->inode), + .callback_ops = &nfs4_lock_ops, + .flags = RPC_TASK_ASYNC, + }; int ret; dprintk("%s: begin!\n", __FUNCTION__); @@ -3449,8 +3484,8 @@ static int _nfs4_do_setlk(struct nfs4_state *state, int cmd, struct file_lock *f data->arg.block = 1; if (reclaim != 0) data->arg.reclaim = 1; - task = rpc_run_task(NFS_CLIENT(state->inode), RPC_TASK_ASYNC, - &nfs4_lock_ops, data); + task_setup_data.callback_data = data; + task = rpc_run_task(&task_setup_data); if (IS_ERR(task)) return PTR_ERR(task); ret = nfs4_wait_for_completion_rpc_task(task); -- cgit v1.2.3 From bdc7f021f3a1fade77adf3c2d7f65690566fddfe Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Sat, 14 Jul 2007 15:40:00 -0400 Subject: NFS: Clean up the (commit|read|write)_setup() callback routines Move the common code for setting up the nfs_write_data and nfs_read_data structures into fs/nfs/read.c, fs/nfs/write.c and fs/nfs/direct.c. Signed-off-by: Trond Myklebust --- fs/nfs/nfs4proc.c | 49 ++++++++----------------------------------------- 1 file changed, 8 insertions(+), 41 deletions(-) (limited to 'fs/nfs/nfs4proc.c') diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index ff2c5f83ce87..7c0baf23abdc 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -2432,18 +2432,10 @@ static int nfs4_read_done(struct rpc_task *task, struct nfs_read_data *data) return 0; } -static void nfs4_proc_read_setup(struct nfs_read_data *data) +static void nfs4_proc_read_setup(struct nfs_read_data *data, struct rpc_message *msg) { - struct rpc_message msg = { - .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_READ], - .rpc_argp = &data->args, - .rpc_resp = &data->res, - .rpc_cred = data->cred, - }; - data->timestamp = jiffies; - - rpc_call_setup(&data->task, &msg, 0); + msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_READ]; } static int nfs4_write_done(struct rpc_task *task, struct nfs_write_data *data) @@ -2461,33 +2453,15 @@ static int nfs4_write_done(struct rpc_task *task, struct nfs_write_data *data) return 0; } -static void nfs4_proc_write_setup(struct nfs_write_data *data, int how) +static void nfs4_proc_write_setup(struct nfs_write_data *data, struct rpc_message *msg) { - struct rpc_message msg = { - .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_WRITE], - .rpc_argp = &data->args, - .rpc_resp = &data->res, - .rpc_cred = data->cred, - }; - struct inode *inode = data->inode; - struct nfs_server *server = NFS_SERVER(inode); - int stable; - - if (how & FLUSH_STABLE) { - if (!NFS_I(inode)->ncommit) - stable = NFS_FILE_SYNC; - else - stable = NFS_DATA_SYNC; - } else - stable = NFS_UNSTABLE; - data->args.stable = stable; + struct nfs_server *server = NFS_SERVER(data->inode); + data->args.bitmask = server->attr_bitmask; data->res.server = server; - data->timestamp = jiffies; - /* Finalize the task. */ - rpc_call_setup(&data->task, &msg, 0); + msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_WRITE]; } static int nfs4_commit_done(struct rpc_task *task, struct nfs_write_data *data) @@ -2502,20 +2476,13 @@ static int nfs4_commit_done(struct rpc_task *task, struct nfs_write_data *data) return 0; } -static void nfs4_proc_commit_setup(struct nfs_write_data *data, int how) +static void nfs4_proc_commit_setup(struct nfs_write_data *data, struct rpc_message *msg) { - struct rpc_message msg = { - .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_COMMIT], - .rpc_argp = &data->args, - .rpc_resp = &data->res, - .rpc_cred = data->cred, - }; struct nfs_server *server = NFS_SERVER(data->inode); data->args.bitmask = server->attr_bitmask; data->res.server = server; - - rpc_call_setup(&data->task, &msg, 0); + msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_COMMIT]; } /* -- cgit v1.2.3 From 5138fde01161cd7976fdc51f6a17da73adaa6baf Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Sat, 14 Jul 2007 15:40:01 -0400 Subject: NFS/SUNRPC: Convert all users of rpc_call_setup() Replace use of rpc_call_setup() with rpc_init_task(), and in cases where we need to initialise task->tk_action, with rpc_call_start(). Signed-off-by: Trond Myklebust --- fs/nfs/nfs4proc.c | 118 ++++++++++++++++++++++++------------------------------ 1 file changed, 52 insertions(+), 66 deletions(-) (limited to 'fs/nfs/nfs4proc.c') diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 7c0baf23abdc..826b445b8c70 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -718,19 +718,6 @@ int nfs4_open_delegation_recall(struct nfs_open_context *ctx, struct nfs4_state return err; } -static void nfs4_open_confirm_prepare(struct rpc_task *task, void *calldata) -{ - struct nfs4_opendata *data = calldata; - struct rpc_message msg = { - .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OPEN_CONFIRM], - .rpc_argp = &data->c_arg, - .rpc_resp = &data->c_res, - .rpc_cred = data->owner->so_cred, - }; - data->timestamp = jiffies; - rpc_call_setup(task, &msg, 0); -} - static void nfs4_open_confirm_done(struct rpc_task *task, void *calldata) { struct nfs4_opendata *data = calldata; @@ -767,7 +754,6 @@ out_free: } static const struct rpc_call_ops nfs4_open_confirm_ops = { - .rpc_call_prepare = nfs4_open_confirm_prepare, .rpc_call_done = nfs4_open_confirm_done, .rpc_release = nfs4_open_confirm_release, }; @@ -779,8 +765,15 @@ static int _nfs4_proc_open_confirm(struct nfs4_opendata *data) { struct nfs_server *server = NFS_SERVER(data->dir->d_inode); struct rpc_task *task; + struct rpc_message msg = { + .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OPEN_CONFIRM], + .rpc_argp = &data->c_arg, + .rpc_resp = &data->c_res, + .rpc_cred = data->owner->so_cred, + }; struct rpc_task_setup task_setup_data = { .rpc_client = server->client, + .rpc_message = &msg, .callback_ops = &nfs4_open_confirm_ops, .callback_data = data, .flags = RPC_TASK_ASYNC, @@ -790,6 +783,7 @@ static int _nfs4_proc_open_confirm(struct nfs4_opendata *data) kref_get(&data->kref); data->rpc_done = 0; data->rpc_status = 0; + data->timestamp = jiffies; task = rpc_run_task(&task_setup_data); if (IS_ERR(task)) return PTR_ERR(task); @@ -807,13 +801,7 @@ static void nfs4_open_prepare(struct rpc_task *task, void *calldata) { struct nfs4_opendata *data = calldata; struct nfs4_state_owner *sp = data->owner; - struct rpc_message msg = { - .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OPEN], - .rpc_argp = &data->o_arg, - .rpc_resp = &data->o_res, - .rpc_cred = sp->so_cred, - }; - + if (nfs_wait_on_sequence(data->o_arg.seqid, task) != 0) return; /* @@ -838,11 +826,11 @@ static void nfs4_open_prepare(struct rpc_task *task, void *calldata) data->o_arg.id = sp->so_owner_id.id; data->o_arg.clientid = sp->so_client->cl_clientid; if (data->o_arg.claim == NFS4_OPEN_CLAIM_PREVIOUS) { - msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OPEN_NOATTR]; + task->tk_msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OPEN_NOATTR]; nfs_copy_fh(&data->o_res.fh, data->o_arg.fh); } data->timestamp = jiffies; - rpc_call_setup(task, &msg, 0); + rpc_call_start(task); return; out_no_action: task->tk_action = NULL; @@ -914,8 +902,15 @@ static int _nfs4_proc_open(struct nfs4_opendata *data) struct nfs_openargs *o_arg = &data->o_arg; struct nfs_openres *o_res = &data->o_res; struct rpc_task *task; + struct rpc_message msg = { + .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OPEN], + .rpc_argp = o_arg, + .rpc_resp = o_res, + .rpc_cred = data->owner->so_cred, + }; struct rpc_task_setup task_setup_data = { .rpc_client = server->client, + .rpc_message = &msg, .callback_ops = &nfs4_open_ops, .callback_data = data, .flags = RPC_TASK_ASYNC, @@ -1256,12 +1251,6 @@ static void nfs4_close_prepare(struct rpc_task *task, void *data) { struct nfs4_closedata *calldata = data; struct nfs4_state *state = calldata->state; - struct rpc_message msg = { - .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_CLOSE], - .rpc_argp = &calldata->arg, - .rpc_resp = &calldata->res, - .rpc_cred = state->owner->so_cred, - }; int clear_rd, clear_wr, clear_rdwr; if (nfs_wait_on_sequence(calldata->arg.seqid, task) != 0) @@ -1288,14 +1277,14 @@ static void nfs4_close_prepare(struct rpc_task *task, void *data) } nfs_fattr_init(calldata->res.fattr); if (test_bit(NFS_O_RDONLY_STATE, &state->flags) != 0) { - msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OPEN_DOWNGRADE]; + task->tk_msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OPEN_DOWNGRADE]; calldata->arg.open_flags = FMODE_READ; } else if (test_bit(NFS_O_WRONLY_STATE, &state->flags) != 0) { - msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OPEN_DOWNGRADE]; + task->tk_msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OPEN_DOWNGRADE]; calldata->arg.open_flags = FMODE_WRITE; } calldata->timestamp = jiffies; - rpc_call_setup(task, &msg, 0); + rpc_call_start(task); } static const struct rpc_call_ops nfs4_close_ops = { @@ -1321,8 +1310,13 @@ int nfs4_do_close(struct path *path, struct nfs4_state *state, int wait) struct nfs4_closedata *calldata; struct nfs4_state_owner *sp = state->owner; struct rpc_task *task; + struct rpc_message msg = { + .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_CLOSE], + .rpc_cred = state->owner->so_cred, + }; struct rpc_task_setup task_setup_data = { .rpc_client = server->client, + .rpc_message = &msg, .callback_ops = &nfs4_close_ops, .flags = RPC_TASK_ASYNC, }; @@ -1345,6 +1339,8 @@ int nfs4_do_close(struct path *path, struct nfs4_state *state, int wait) calldata->path.mnt = mntget(path->mnt); calldata->path.dentry = dget(path->dentry); + msg.rpc_argp = &calldata->arg, + msg.rpc_resp = &calldata->res, task_setup_data.callback_data = calldata; task = rpc_run_task(&task_setup_data); if (IS_ERR(task)) @@ -2966,25 +2962,11 @@ struct nfs4_delegreturndata { struct nfs4_delegreturnres res; struct nfs_fh fh; nfs4_stateid stateid; - struct rpc_cred *cred; unsigned long timestamp; struct nfs_fattr fattr; int rpc_status; }; -static void nfs4_delegreturn_prepare(struct rpc_task *task, void *calldata) -{ - struct nfs4_delegreturndata *data = calldata; - struct rpc_message msg = { - .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_DELEGRETURN], - .rpc_argp = &data->args, - .rpc_resp = &data->res, - .rpc_cred = data->cred, - }; - nfs_fattr_init(data->res.fattr); - rpc_call_setup(task, &msg, 0); -} - static void nfs4_delegreturn_done(struct rpc_task *task, void *calldata) { struct nfs4_delegreturndata *data = calldata; @@ -2995,14 +2977,10 @@ static void nfs4_delegreturn_done(struct rpc_task *task, void *calldata) static void nfs4_delegreturn_release(void *calldata) { - struct nfs4_delegreturndata *data = calldata; - - put_rpccred(data->cred); kfree(calldata); } static const struct rpc_call_ops nfs4_delegreturn_ops = { - .rpc_call_prepare = nfs4_delegreturn_prepare, .rpc_call_done = nfs4_delegreturn_done, .rpc_release = nfs4_delegreturn_release, }; @@ -3012,8 +2990,13 @@ static int _nfs4_proc_delegreturn(struct inode *inode, struct rpc_cred *cred, co struct nfs4_delegreturndata *data; struct nfs_server *server = NFS_SERVER(inode); struct rpc_task *task; + struct rpc_message msg = { + .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_DELEGRETURN], + .rpc_cred = cred, + }; struct rpc_task_setup task_setup_data = { .rpc_client = server->client, + .rpc_message = &msg, .callback_ops = &nfs4_delegreturn_ops, .flags = RPC_TASK_ASYNC, }; @@ -3029,11 +3012,13 @@ static int _nfs4_proc_delegreturn(struct inode *inode, struct rpc_cred *cred, co memcpy(&data->stateid, stateid, sizeof(data->stateid)); data->res.fattr = &data->fattr; data->res.server = server; - data->cred = get_rpccred(cred); + nfs_fattr_init(data->res.fattr); data->timestamp = jiffies; data->rpc_status = 0; task_setup_data.callback_data = data; + msg.rpc_argp = &data->args, + msg.rpc_resp = &data->res, task = rpc_run_task(&task_setup_data); if (IS_ERR(task)) return PTR_ERR(task); @@ -3221,12 +3206,6 @@ static void nfs4_locku_done(struct rpc_task *task, void *data) static void nfs4_locku_prepare(struct rpc_task *task, void *data) { struct nfs4_unlockdata *calldata = data; - struct rpc_message msg = { - .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LOCKU], - .rpc_argp = &calldata->arg, - .rpc_resp = &calldata->res, - .rpc_cred = calldata->lsp->ls_state->owner->so_cred, - }; if (nfs_wait_on_sequence(calldata->arg.seqid, task) != 0) return; @@ -3236,7 +3215,7 @@ static void nfs4_locku_prepare(struct rpc_task *task, void *data) return; } calldata->timestamp = jiffies; - rpc_call_setup(task, &msg, 0); + rpc_call_start(task); } static const struct rpc_call_ops nfs4_locku_ops = { @@ -3251,8 +3230,13 @@ static struct rpc_task *nfs4_do_unlck(struct file_lock *fl, struct nfs_seqid *seqid) { struct nfs4_unlockdata *data; + struct rpc_message msg = { + .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LOCKU], + .rpc_cred = ctx->cred, + }; struct rpc_task_setup task_setup_data = { .rpc_client = NFS_CLIENT(lsp->ls_state->inode), + .rpc_message = &msg, .callback_ops = &nfs4_locku_ops, .flags = RPC_TASK_ASYNC, }; @@ -3268,6 +3252,8 @@ static struct rpc_task *nfs4_do_unlck(struct file_lock *fl, return ERR_PTR(-ENOMEM); } + msg.rpc_argp = &data->arg, + msg.rpc_resp = &data->res, task_setup_data.callback_data = data; return rpc_run_task(&task_setup_data); } @@ -3353,13 +3339,6 @@ static void nfs4_lock_prepare(struct rpc_task *task, void *calldata) { struct nfs4_lockdata *data = calldata; struct nfs4_state *state = data->lsp->ls_state; - struct nfs4_state_owner *sp = state->owner; - struct rpc_message msg = { - .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LOCK], - .rpc_argp = &data->arg, - .rpc_resp = &data->res, - .rpc_cred = sp->so_cred, - }; dprintk("%s: begin!\n", __FUNCTION__); if (nfs_wait_on_sequence(data->arg.lock_seqid, task) != 0) @@ -3373,7 +3352,7 @@ static void nfs4_lock_prepare(struct rpc_task *task, void *calldata) } else data->arg.new_lock_owner = 0; data->timestamp = jiffies; - rpc_call_setup(task, &msg, 0); + rpc_call_start(task); dprintk("%s: done!, ret = %d\n", __FUNCTION__, data->rpc_status); } @@ -3435,8 +3414,13 @@ static int _nfs4_do_setlk(struct nfs4_state *state, int cmd, struct file_lock *f { struct nfs4_lockdata *data; struct rpc_task *task; + struct rpc_message msg = { + .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LOCK], + .rpc_cred = state->owner->so_cred, + }; struct rpc_task_setup task_setup_data = { .rpc_client = NFS_CLIENT(state->inode), + .rpc_message = &msg, .callback_ops = &nfs4_lock_ops, .flags = RPC_TASK_ASYNC, }; @@ -3451,6 +3435,8 @@ static int _nfs4_do_setlk(struct nfs4_state *state, int cmd, struct file_lock *f data->arg.block = 1; if (reclaim != 0) data->arg.reclaim = 1; + msg.rpc_argp = &data->arg, + msg.rpc_resp = &data->res, task_setup_data.callback_data = data; task = rpc_run_task(&task_setup_data); if (IS_ERR(task)) -- cgit v1.2.3 From bfc69a456642a51c89dfd8e5184468857cb44f32 Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Mon, 15 Oct 2007 18:18:29 -0400 Subject: NFS: define a function to update nfsi->cache_change_attribute Signed-off-by: Trond Myklebust --- fs/nfs/nfs4proc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'fs/nfs/nfs4proc.c') diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 826b445b8c70..26192a703129 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -210,7 +210,7 @@ static void update_changeattr(struct inode *dir, struct nfs4_change_info *cinfo) spin_lock(&dir->i_lock); nfsi->cache_validity |= NFS_INO_INVALID_ATTR|NFS_INO_REVAL_PAGECACHE|NFS_INO_INVALID_DATA; if (!cinfo->atomic || cinfo->before != nfsi->change_attr) - nfsi->cache_change_attribute = jiffies; + nfs_force_lookup_revalidate(dir); nfsi->change_attr = cinfo->after; spin_unlock(&dir->i_lock); } -- cgit v1.2.3 From d4d3c507493afd3c9d19fbe9762f44e790909dbe Mon Sep 17 00:00:00 2001 From: Chuck Lever Date: Mon, 10 Dec 2007 14:57:09 -0500 Subject: NFS: Enable NFS client to generate CLIENTID strings with IPv6 addresses We recently added methods to RPC transports that provide string versions of the remote peer address information. Convert the NFSv4 SETCLIENTID procedure to use those methods instead of building the client ID out of whole cloth. Signed-off-by: Chuck Lever Cc: Aurelien Charbon Signed-off-by: Trond Myklebust --- fs/nfs/nfs4proc.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'fs/nfs/nfs4proc.c') diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 26192a703129..5e8c4cf7959e 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -2891,14 +2891,18 @@ int nfs4_proc_setclientid(struct nfs_client *clp, u32 program, unsigned short po for(;;) { setclientid.sc_name_len = scnprintf(setclientid.sc_name, - sizeof(setclientid.sc_name), "%s/%u.%u.%u.%u %s %u", - clp->cl_ipaddr, NIPQUAD(clp->cl_addr.sin_addr), + sizeof(setclientid.sc_name), "%s/%s %s %u", + clp->cl_ipaddr, + rpc_peeraddr2str(clp->cl_rpcclient, + RPC_DISPLAY_ADDR), cred->cr_ops->cr_name, clp->cl_id_uniquifier); setclientid.sc_netid_len = scnprintf(setclientid.sc_netid, - sizeof(setclientid.sc_netid), "tcp"); + sizeof(setclientid.sc_netid), + rpc_peeraddr2str(clp->cl_rpcclient, + RPC_DISPLAY_NETID)); setclientid.sc_uaddr_len = scnprintf(setclientid.sc_uaddr, - sizeof(setclientid.sc_uaddr), "%s.%d.%d", + sizeof(setclientid.sc_uaddr), "%s.%u.%u", clp->cl_ipaddr, port >> 8, port & 255); status = rpc_call_sync(clp->cl_rpcclient, &msg, 0); -- cgit v1.2.3 From 69dd716c5ffd89f5ba14ffb871d633ecea74d13a Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Fri, 14 Dec 2007 14:56:07 -0500 Subject: NFSv4: Add socket proto argument to setclientid Signed-off-by: Trond Myklebust --- fs/nfs/nfs4proc.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'fs/nfs/nfs4proc.c') diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 5e8c4cf7959e..b3d4e8e5696a 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -2891,10 +2891,12 @@ int nfs4_proc_setclientid(struct nfs_client *clp, u32 program, unsigned short po for(;;) { setclientid.sc_name_len = scnprintf(setclientid.sc_name, - sizeof(setclientid.sc_name), "%s/%s %s %u", + sizeof(setclientid.sc_name), "%s/%s %s %s %u", clp->cl_ipaddr, rpc_peeraddr2str(clp->cl_rpcclient, RPC_DISPLAY_ADDR), + rpc_peeraddr2str(clp->cl_rpcclient, + RPC_DISPLAY_PROTO), cred->cr_ops->cr_name, clp->cl_id_uniquifier); setclientid.sc_netid_len = scnprintf(setclientid.sc_netid, -- cgit v1.2.3 From 3d1c550874bcaf0d9b7fb66f601caed109074f4b Mon Sep 17 00:00:00 2001 From: "J. Bruce Fields" Date: Tue, 15 Jan 2008 16:43:19 -0500 Subject: nfs4: allow nfsv4 acls on non-regular-files The rfc doesn't give any reason it shouldn't be possible to set an attribute on a non-regular file. And if the server supports it, then it shouldn't be up to us to prevent it. Thanks to Erez for the report and Trond for further analysis. Signed-off-by: J. Bruce Fields Tested-by: Erez Zadok Signed-off-by: Trond Myklebust --- fs/nfs/nfs4proc.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'fs/nfs/nfs4proc.c') diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index b3d4e8e5696a..89efbcd6fd53 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -3617,10 +3617,6 @@ int nfs4_setxattr(struct dentry *dentry, const char *key, const void *buf, if (strcmp(key, XATTR_NAME_NFSV4_ACL) != 0) return -EOPNOTSUPP; - if (!S_ISREG(inode->i_mode) && - (!S_ISDIR(inode->i_mode) || inode->i_mode & S_ISVTX)) - return -EPERM; - return nfs4_proc_set_acl(inode, buf, buflen); } -- cgit v1.2.3 From e6f810759505bc86c009854b82cc495ffd8eb020 Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Thu, 24 Jan 2008 18:14:34 -0500 Subject: NFS: Add an asynchronous delegreturn operation for use in nfs_clear_inode Otherwise, there is a potential deadlock if the last dput() from an NFSv4 close() or other asynchronous operation leads to nfs_clear_inode calling the synchronous delegreturn. Signed-off-by: Trond Myklebust --- fs/nfs/nfs4proc.c | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) (limited to 'fs/nfs/nfs4proc.c') diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 89efbcd6fd53..5c189bd57eb2 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -2991,7 +2991,7 @@ static const struct rpc_call_ops nfs4_delegreturn_ops = { .rpc_release = nfs4_delegreturn_release, }; -static int _nfs4_proc_delegreturn(struct inode *inode, struct rpc_cred *cred, const nfs4_stateid *stateid) +static int _nfs4_proc_delegreturn(struct inode *inode, struct rpc_cred *cred, const nfs4_stateid *stateid, int issync) { struct nfs4_delegreturndata *data; struct nfs_server *server = NFS_SERVER(inode); @@ -3006,7 +3006,7 @@ static int _nfs4_proc_delegreturn(struct inode *inode, struct rpc_cred *cred, co .callback_ops = &nfs4_delegreturn_ops, .flags = RPC_TASK_ASYNC, }; - int status; + int status = 0; data = kmalloc(sizeof(*data), GFP_KERNEL); if (data == NULL) @@ -3028,23 +3028,27 @@ static int _nfs4_proc_delegreturn(struct inode *inode, struct rpc_cred *cred, co task = rpc_run_task(&task_setup_data); if (IS_ERR(task)) return PTR_ERR(task); + if (!issync) + goto out; status = nfs4_wait_for_completion_rpc_task(task); - if (status == 0) { - status = data->rpc_status; - if (status == 0) - nfs_refresh_inode(inode, &data->fattr); - } + if (status != 0) + goto out; + status = data->rpc_status; + if (status != 0) + goto out; + nfs_refresh_inode(inode, &data->fattr); +out: rpc_put_task(task); return status; } -int nfs4_proc_delegreturn(struct inode *inode, struct rpc_cred *cred, const nfs4_stateid *stateid) +int nfs4_proc_delegreturn(struct inode *inode, struct rpc_cred *cred, const nfs4_stateid *stateid, int issync) { struct nfs_server *server = NFS_SERVER(inode); struct nfs4_exception exception = { }; int err; do { - err = _nfs4_proc_delegreturn(inode, cred, stateid); + err = _nfs4_proc_delegreturn(inode, cred, stateid, issync); switch (err) { case -NFS4ERR_STALE_STATEID: case -NFS4ERR_EXPIRED: -- cgit v1.2.3