aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/nfs4proc.c
diff options
context:
space:
mode:
authorTrond Myklebust <Trond.Myklebust@netapp.com>2005-10-18 17:20:15 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2005-10-18 17:20:15 -0400
commitfaf5f49c2d9c0af2847837c232a432cc146e203b (patch)
treef0c097ae68ca3ec3cd5ee0a904916493b00b9c1b /fs/nfs/nfs4proc.c
parent0a8838f972883112f0a7b259141b24db17583c2d (diff)
NFSv4: Make NFS clean up byte range locks asynchronously
Currently we fail to do so if the process was signalled. Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs/nfs/nfs4proc.c')
-rw-r--r--fs/nfs/nfs4proc.c161
1 files changed, 110 insertions, 51 deletions
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index f57dba815099..612a9a14aed3 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -58,9 +58,9 @@
58 58
59static int _nfs4_proc_open_confirm(struct rpc_clnt *clnt, const struct nfs_fh *fh, struct nfs4_state_owner *sp, nfs4_stateid *stateid, struct nfs_seqid *seqid); 59static int _nfs4_proc_open_confirm(struct rpc_clnt *clnt, const struct nfs_fh *fh, struct nfs4_state_owner *sp, nfs4_stateid *stateid, struct nfs_seqid *seqid);
60static int nfs4_do_fsinfo(struct nfs_server *, struct nfs_fh *, struct nfs_fsinfo *); 60static int nfs4_do_fsinfo(struct nfs_server *, struct nfs_fh *, struct nfs_fsinfo *);
61static int nfs4_async_handle_error(struct rpc_task *, struct nfs_server *); 61static int nfs4_async_handle_error(struct rpc_task *, const struct nfs_server *);
62static int _nfs4_proc_access(struct inode *inode, struct nfs_access_entry *entry); 62static int _nfs4_proc_access(struct inode *inode, struct nfs_access_entry *entry);
63static int nfs4_handle_exception(struct nfs_server *server, int errorcode, struct nfs4_exception *exception); 63static int nfs4_handle_exception(const struct nfs_server *server, int errorcode, struct nfs4_exception *exception);
64extern u32 *nfs4_decode_dirent(u32 *p, struct nfs_entry *entry, int plus); 64extern u32 *nfs4_decode_dirent(u32 *p, struct nfs_entry *entry, int plus);
65extern struct rpc_procinfo nfs4_procedures[]; 65extern struct rpc_procinfo nfs4_procedures[];
66 66
@@ -2422,7 +2422,7 @@ static int nfs4_proc_set_acl(struct inode *inode, const void *buf, size_t buflen
2422} 2422}
2423 2423
2424static int 2424static int
2425nfs4_async_handle_error(struct rpc_task *task, struct nfs_server *server) 2425nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server)
2426{ 2426{
2427 struct nfs4_client *clp = server->nfs4_state; 2427 struct nfs4_client *clp = server->nfs4_state;
2428 2428
@@ -2500,7 +2500,7 @@ static int nfs4_delay(struct rpc_clnt *clnt, long *timeout)
2500/* This is the error handling routine for processes that are allowed 2500/* This is the error handling routine for processes that are allowed
2501 * to sleep. 2501 * to sleep.
2502 */ 2502 */
2503int nfs4_handle_exception(struct nfs_server *server, int errorcode, struct nfs4_exception *exception) 2503int nfs4_handle_exception(const struct nfs_server *server, int errorcode, struct nfs4_exception *exception)
2504{ 2504{
2505 struct nfs4_client *clp = server->nfs4_state; 2505 struct nfs4_client *clp = server->nfs4_state;
2506 int ret = errorcode; 2506 int ret = errorcode;
@@ -2763,68 +2763,127 @@ static int do_vfs_lock(struct file *file, struct file_lock *fl)
2763 return res; 2763 return res;
2764} 2764}
2765 2765
2766static int _nfs4_proc_unlck(struct nfs4_state *state, int cmd, struct file_lock *request) 2766struct nfs4_unlockdata {
2767 struct nfs_lockargs arg;
2768 struct nfs_locku_opargs luargs;
2769 struct nfs_lockres res;
2770 struct nfs4_lock_state *lsp;
2771 struct nfs_open_context *ctx;
2772 atomic_t refcount;
2773 struct completion completion;
2774};
2775
2776static void nfs4_locku_release_calldata(struct nfs4_unlockdata *calldata)
2767{ 2777{
2768 struct inode *inode = state->inode; 2778 if (atomic_dec_and_test(&calldata->refcount)) {
2769 struct nfs_server *server = NFS_SERVER(inode); 2779 nfs_free_seqid(calldata->luargs.seqid);
2770 struct nfs_lockargs arg = { 2780 nfs4_put_lock_state(calldata->lsp);
2771 .fh = NFS_FH(inode), 2781 put_nfs_open_context(calldata->ctx);
2772 .type = nfs4_lck_type(cmd, request), 2782 kfree(calldata);
2773 .offset = request->fl_start, 2783 }
2774 .length = nfs4_lck_length(request), 2784}
2775 }; 2785
2776 struct nfs_lockres res = { 2786static void nfs4_locku_complete(struct nfs4_unlockdata *calldata)
2777 .server = server, 2787{
2778 }; 2788 complete(&calldata->completion);
2789 nfs4_locku_release_calldata(calldata);
2790}
2791
2792static void nfs4_locku_done(struct rpc_task *task)
2793{
2794 struct nfs4_unlockdata *calldata = (struct nfs4_unlockdata *)task->tk_calldata;
2795
2796 nfs_increment_lock_seqid(task->tk_status, calldata->luargs.seqid);
2797 switch (task->tk_status) {
2798 case 0:
2799 memcpy(calldata->lsp->ls_stateid.data,
2800 calldata->res.u.stateid.data,
2801 sizeof(calldata->lsp->ls_stateid.data));
2802 break;
2803 case -NFS4ERR_STALE_STATEID:
2804 case -NFS4ERR_EXPIRED:
2805 nfs4_schedule_state_recovery(calldata->res.server->nfs4_state);
2806 break;
2807 default:
2808 if (nfs4_async_handle_error(task, calldata->res.server) == -EAGAIN) {
2809 rpc_restart_call(task);
2810 return;
2811 }
2812 }
2813 nfs4_locku_complete(calldata);
2814}
2815
2816static void nfs4_locku_begin(struct rpc_task *task)
2817{
2818 struct nfs4_unlockdata *calldata = (struct nfs4_unlockdata *)task->tk_calldata;
2779 struct rpc_message msg = { 2819 struct rpc_message msg = {
2780 .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LOCKU], 2820 .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LOCKU],
2781 .rpc_argp = &arg, 2821 .rpc_argp = &calldata->arg,
2782 .rpc_resp = &res, 2822 .rpc_resp = &calldata->res,
2783 .rpc_cred = state->owner->so_cred, 2823 .rpc_cred = calldata->lsp->ls_state->owner->so_cred,
2784 }; 2824 };
2825 int status;
2826
2827 status = nfs_wait_on_sequence(calldata->luargs.seqid, task);
2828 if (status != 0)
2829 return;
2830 if ((calldata->lsp->ls_flags & NFS_LOCK_INITIALIZED) == 0) {
2831 nfs4_locku_complete(calldata);
2832 task->tk_exit = NULL;
2833 rpc_exit(task, 0);
2834 return;
2835 }
2836 rpc_call_setup(task, &msg, 0);
2837}
2838
2839static int nfs4_proc_unlck(struct nfs4_state *state, int cmd, struct file_lock *request)
2840{
2841 struct nfs4_unlockdata *calldata;
2842 struct inode *inode = state->inode;
2843 struct nfs_server *server = NFS_SERVER(inode);
2785 struct nfs4_lock_state *lsp; 2844 struct nfs4_lock_state *lsp;
2786 struct nfs_locku_opargs luargs;
2787 int status; 2845 int status;
2788 2846
2789 status = nfs4_set_lock_state(state, request); 2847 status = nfs4_set_lock_state(state, request);
2790 if (status != 0) 2848 if (status != 0)
2791 goto out; 2849 return status;
2792 lsp = request->fl_u.nfs4_fl.owner; 2850 lsp = request->fl_u.nfs4_fl.owner;
2793 /* We might have lost the locks! */ 2851 /* We might have lost the locks! */
2794 if ((lsp->ls_flags & NFS_LOCK_INITIALIZED) == 0) 2852 if ((lsp->ls_flags & NFS_LOCK_INITIALIZED) == 0)
2795 goto out; 2853 return 0;
2796 luargs.seqid = nfs_alloc_seqid(&lsp->ls_seqid); 2854 calldata = kmalloc(sizeof(*calldata), GFP_KERNEL);
2797 status = -ENOMEM; 2855 if (calldata == NULL)
2798 if (luargs.seqid == NULL) 2856 return -ENOMEM;
2799 goto out; 2857 calldata->luargs.seqid = nfs_alloc_seqid(&lsp->ls_seqid);
2800 memcpy(luargs.stateid.data, lsp->ls_stateid.data, sizeof(luargs.stateid.data)); 2858 if (calldata->luargs.seqid == NULL) {
2801 arg.u.locku = &luargs; 2859 kfree(calldata);
2802 status = rpc_call_sync(server->client, &msg, RPC_TASK_NOINTR); 2860 return -ENOMEM;
2803 nfs_increment_lock_seqid(status, luargs.seqid); 2861 }
2804 2862 calldata->luargs.stateid = &lsp->ls_stateid;
2805 if (status == 0) 2863 calldata->arg.fh = NFS_FH(inode);
2806 memcpy(lsp->ls_stateid.data, res.u.stateid.data, 2864 calldata->arg.type = nfs4_lck_type(cmd, request);
2807 sizeof(lsp->ls_stateid.data)); 2865 calldata->arg.offset = request->fl_start;
2808 nfs_free_seqid(luargs.seqid); 2866 calldata->arg.length = nfs4_lck_length(request);
2809out: 2867 calldata->arg.u.locku = &calldata->luargs;
2868 calldata->res.server = server;
2869 calldata->lsp = lsp;
2870 atomic_inc(&lsp->ls_count);
2871
2872 /* Ensure we don't close file until we're done freeing locks! */
2873 calldata->ctx = get_nfs_open_context((struct nfs_open_context*)request->fl_file->private_data);
2874
2875 atomic_set(&calldata->refcount, 2);
2876 init_completion(&calldata->completion);
2877
2878 status = nfs4_call_async(NFS_SERVER(inode)->client, nfs4_locku_begin,
2879 nfs4_locku_done, calldata);
2810 if (status == 0) 2880 if (status == 0)
2811 do_vfs_lock(request->fl_file, request); 2881 wait_for_completion_interruptible(&calldata->completion);
2882 do_vfs_lock(request->fl_file, request);
2883 nfs4_locku_release_calldata(calldata);
2812 return status; 2884 return status;
2813} 2885}
2814 2886
2815static int nfs4_proc_unlck(struct nfs4_state *state, int cmd, struct file_lock *request)
2816{
2817 struct nfs4_exception exception = { };
2818 int err;
2819
2820 do {
2821 err = nfs4_handle_exception(NFS_SERVER(state->inode),
2822 _nfs4_proc_unlck(state, cmd, request),
2823 &exception);
2824 } while (exception.retry);
2825 return err;
2826}
2827
2828static int _nfs4_do_setlk(struct nfs4_state *state, int cmd, struct file_lock *request, int reclaim) 2887static int _nfs4_do_setlk(struct nfs4_state *state, int cmd, struct file_lock *request, int reclaim)
2829{ 2888{
2830 struct inode *inode = state->inode; 2889 struct inode *inode = state->inode;