diff options
author | Trond Myklebust <Trond.Myklebust@netapp.com> | 2010-05-13 12:51:01 -0400 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2010-05-14 15:09:33 -0400 |
commit | 8535b2be5181fc3019e4150567ef53210fe3b04f (patch) | |
tree | ba366f5304f12876f1e45d3c2b423d12f9ec0c90 /fs/nfs/nfs4proc.c | |
parent | 712a4338669d7d57f952244abb608e6ac07e39da (diff) |
NFSv4: Don't use GFP_KERNEL allocations in state recovery
We do not want to have the state recovery thread kick off and wait for a
memory reclaim, since that may deadlock when the writebacks end up
waiting for the state recovery thread to complete.
The safe thing is therefore to use GFP_NOFS in all open, close,
delegation return, lock, etc. operations that may be called by the
state recovery thread.
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs/nfs/nfs4proc.c')
-rw-r--r-- | fs/nfs/nfs4proc.c | 47 |
1 files changed, 25 insertions, 22 deletions
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 9998c2958103..70015dd60a98 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
@@ -717,17 +717,18 @@ static void nfs4_init_opendata_res(struct nfs4_opendata *p) | |||
717 | 717 | ||
718 | static struct nfs4_opendata *nfs4_opendata_alloc(struct path *path, | 718 | static struct nfs4_opendata *nfs4_opendata_alloc(struct path *path, |
719 | struct nfs4_state_owner *sp, fmode_t fmode, int flags, | 719 | struct nfs4_state_owner *sp, fmode_t fmode, int flags, |
720 | const struct iattr *attrs) | 720 | const struct iattr *attrs, |
721 | gfp_t gfp_mask) | ||
721 | { | 722 | { |
722 | struct dentry *parent = dget_parent(path->dentry); | 723 | struct dentry *parent = dget_parent(path->dentry); |
723 | struct inode *dir = parent->d_inode; | 724 | struct inode *dir = parent->d_inode; |
724 | struct nfs_server *server = NFS_SERVER(dir); | 725 | struct nfs_server *server = NFS_SERVER(dir); |
725 | struct nfs4_opendata *p; | 726 | struct nfs4_opendata *p; |
726 | 727 | ||
727 | p = kzalloc(sizeof(*p), GFP_KERNEL); | 728 | p = kzalloc(sizeof(*p), gfp_mask); |
728 | if (p == NULL) | 729 | if (p == NULL) |
729 | goto err; | 730 | goto err; |
730 | p->o_arg.seqid = nfs_alloc_seqid(&sp->so_seqid); | 731 | p->o_arg.seqid = nfs_alloc_seqid(&sp->so_seqid, gfp_mask); |
731 | if (p->o_arg.seqid == NULL) | 732 | if (p->o_arg.seqid == NULL) |
732 | goto err_free; | 733 | goto err_free; |
733 | path_get(path); | 734 | path_get(path); |
@@ -1063,7 +1064,7 @@ static struct nfs4_opendata *nfs4_open_recoverdata_alloc(struct nfs_open_context | |||
1063 | { | 1064 | { |
1064 | struct nfs4_opendata *opendata; | 1065 | struct nfs4_opendata *opendata; |
1065 | 1066 | ||
1066 | opendata = nfs4_opendata_alloc(&ctx->path, state->owner, 0, 0, NULL); | 1067 | opendata = nfs4_opendata_alloc(&ctx->path, state->owner, 0, 0, NULL, GFP_NOFS); |
1067 | if (opendata == NULL) | 1068 | if (opendata == NULL) |
1068 | return ERR_PTR(-ENOMEM); | 1069 | return ERR_PTR(-ENOMEM); |
1069 | opendata->state = state; | 1070 | opendata->state = state; |
@@ -1651,7 +1652,7 @@ static int _nfs4_do_open(struct inode *dir, struct path *path, fmode_t fmode, in | |||
1651 | if (path->dentry->d_inode != NULL) | 1652 | if (path->dentry->d_inode != NULL) |
1652 | nfs4_return_incompatible_delegation(path->dentry->d_inode, fmode); | 1653 | nfs4_return_incompatible_delegation(path->dentry->d_inode, fmode); |
1653 | status = -ENOMEM; | 1654 | status = -ENOMEM; |
1654 | opendata = nfs4_opendata_alloc(path, sp, fmode, flags, sattr); | 1655 | opendata = nfs4_opendata_alloc(path, sp, fmode, flags, sattr, GFP_KERNEL); |
1655 | if (opendata == NULL) | 1656 | if (opendata == NULL) |
1656 | goto err_put_state_owner; | 1657 | goto err_put_state_owner; |
1657 | 1658 | ||
@@ -1926,7 +1927,7 @@ static const struct rpc_call_ops nfs4_close_ops = { | |||
1926 | * | 1927 | * |
1927 | * NOTE: Caller must be holding the sp->so_owner semaphore! | 1928 | * NOTE: Caller must be holding the sp->so_owner semaphore! |
1928 | */ | 1929 | */ |
1929 | int nfs4_do_close(struct path *path, struct nfs4_state *state, int wait) | 1930 | int nfs4_do_close(struct path *path, struct nfs4_state *state, gfp_t gfp_mask, int wait) |
1930 | { | 1931 | { |
1931 | struct nfs_server *server = NFS_SERVER(state->inode); | 1932 | struct nfs_server *server = NFS_SERVER(state->inode); |
1932 | struct nfs4_closedata *calldata; | 1933 | struct nfs4_closedata *calldata; |
@@ -1945,7 +1946,7 @@ int nfs4_do_close(struct path *path, struct nfs4_state *state, int wait) | |||
1945 | }; | 1946 | }; |
1946 | int status = -ENOMEM; | 1947 | int status = -ENOMEM; |
1947 | 1948 | ||
1948 | calldata = kzalloc(sizeof(*calldata), GFP_KERNEL); | 1949 | calldata = kzalloc(sizeof(*calldata), gfp_mask); |
1949 | if (calldata == NULL) | 1950 | if (calldata == NULL) |
1950 | goto out; | 1951 | goto out; |
1951 | calldata->inode = state->inode; | 1952 | calldata->inode = state->inode; |
@@ -1953,7 +1954,7 @@ int nfs4_do_close(struct path *path, struct nfs4_state *state, int wait) | |||
1953 | calldata->arg.fh = NFS_FH(state->inode); | 1954 | calldata->arg.fh = NFS_FH(state->inode); |
1954 | calldata->arg.stateid = &state->open_stateid; | 1955 | calldata->arg.stateid = &state->open_stateid; |
1955 | /* Serialization for the sequence id */ | 1956 | /* Serialization for the sequence id */ |
1956 | calldata->arg.seqid = nfs_alloc_seqid(&state->owner->so_seqid); | 1957 | calldata->arg.seqid = nfs_alloc_seqid(&state->owner->so_seqid, gfp_mask); |
1957 | if (calldata->arg.seqid == NULL) | 1958 | if (calldata->arg.seqid == NULL) |
1958 | goto out_free_calldata; | 1959 | goto out_free_calldata; |
1959 | calldata->arg.fmode = 0; | 1960 | calldata->arg.fmode = 0; |
@@ -3704,7 +3705,7 @@ static int _nfs4_proc_delegreturn(struct inode *inode, struct rpc_cred *cred, co | |||
3704 | }; | 3705 | }; |
3705 | int status = 0; | 3706 | int status = 0; |
3706 | 3707 | ||
3707 | data = kzalloc(sizeof(*data), GFP_KERNEL); | 3708 | data = kzalloc(sizeof(*data), GFP_NOFS); |
3708 | if (data == NULL) | 3709 | if (data == NULL) |
3709 | return -ENOMEM; | 3710 | return -ENOMEM; |
3710 | data->args.fhandle = &data->fh; | 3711 | data->args.fhandle = &data->fh; |
@@ -3860,7 +3861,7 @@ static struct nfs4_unlockdata *nfs4_alloc_unlockdata(struct file_lock *fl, | |||
3860 | struct nfs4_unlockdata *p; | 3861 | struct nfs4_unlockdata *p; |
3861 | struct inode *inode = lsp->ls_state->inode; | 3862 | struct inode *inode = lsp->ls_state->inode; |
3862 | 3863 | ||
3863 | p = kzalloc(sizeof(*p), GFP_KERNEL); | 3864 | p = kzalloc(sizeof(*p), GFP_NOFS); |
3864 | if (p == NULL) | 3865 | if (p == NULL) |
3865 | return NULL; | 3866 | return NULL; |
3866 | p->arg.fh = NFS_FH(inode); | 3867 | p->arg.fh = NFS_FH(inode); |
@@ -3998,7 +3999,7 @@ static int nfs4_proc_unlck(struct nfs4_state *state, int cmd, struct file_lock * | |||
3998 | if (test_bit(NFS_DELEGATED_STATE, &state->flags)) | 3999 | if (test_bit(NFS_DELEGATED_STATE, &state->flags)) |
3999 | goto out; | 4000 | goto out; |
4000 | lsp = request->fl_u.nfs4_fl.owner; | 4001 | lsp = request->fl_u.nfs4_fl.owner; |
4001 | seqid = nfs_alloc_seqid(&lsp->ls_seqid); | 4002 | seqid = nfs_alloc_seqid(&lsp->ls_seqid, GFP_KERNEL); |
4002 | status = -ENOMEM; | 4003 | status = -ENOMEM; |
4003 | if (seqid == NULL) | 4004 | if (seqid == NULL) |
4004 | goto out; | 4005 | goto out; |
@@ -4026,22 +4027,23 @@ struct nfs4_lockdata { | |||
4026 | }; | 4027 | }; |
4027 | 4028 | ||
4028 | static struct nfs4_lockdata *nfs4_alloc_lockdata(struct file_lock *fl, | 4029 | static struct nfs4_lockdata *nfs4_alloc_lockdata(struct file_lock *fl, |
4029 | struct nfs_open_context *ctx, struct nfs4_lock_state *lsp) | 4030 | struct nfs_open_context *ctx, struct nfs4_lock_state *lsp, |
4031 | gfp_t gfp_mask) | ||
4030 | { | 4032 | { |
4031 | struct nfs4_lockdata *p; | 4033 | struct nfs4_lockdata *p; |
4032 | struct inode *inode = lsp->ls_state->inode; | 4034 | struct inode *inode = lsp->ls_state->inode; |
4033 | struct nfs_server *server = NFS_SERVER(inode); | 4035 | struct nfs_server *server = NFS_SERVER(inode); |
4034 | 4036 | ||
4035 | p = kzalloc(sizeof(*p), GFP_KERNEL); | 4037 | p = kzalloc(sizeof(*p), gfp_mask); |
4036 | if (p == NULL) | 4038 | if (p == NULL) |
4037 | return NULL; | 4039 | return NULL; |
4038 | 4040 | ||
4039 | p->arg.fh = NFS_FH(inode); | 4041 | p->arg.fh = NFS_FH(inode); |
4040 | p->arg.fl = &p->fl; | 4042 | p->arg.fl = &p->fl; |
4041 | p->arg.open_seqid = nfs_alloc_seqid(&lsp->ls_state->owner->so_seqid); | 4043 | p->arg.open_seqid = nfs_alloc_seqid(&lsp->ls_state->owner->so_seqid, gfp_mask); |
4042 | if (p->arg.open_seqid == NULL) | 4044 | if (p->arg.open_seqid == NULL) |
4043 | goto out_free; | 4045 | goto out_free; |
4044 | p->arg.lock_seqid = nfs_alloc_seqid(&lsp->ls_seqid); | 4046 | p->arg.lock_seqid = nfs_alloc_seqid(&lsp->ls_seqid, gfp_mask); |
4045 | if (p->arg.lock_seqid == NULL) | 4047 | if (p->arg.lock_seqid == NULL) |
4046 | goto out_free_seqid; | 4048 | goto out_free_seqid; |
4047 | p->arg.lock_stateid = &lsp->ls_stateid; | 4049 | p->arg.lock_stateid = &lsp->ls_stateid; |
@@ -4195,7 +4197,8 @@ static int _nfs4_do_setlk(struct nfs4_state *state, int cmd, struct file_lock *f | |||
4195 | 4197 | ||
4196 | dprintk("%s: begin!\n", __func__); | 4198 | dprintk("%s: begin!\n", __func__); |
4197 | data = nfs4_alloc_lockdata(fl, nfs_file_open_context(fl->fl_file), | 4199 | data = nfs4_alloc_lockdata(fl, nfs_file_open_context(fl->fl_file), |
4198 | fl->fl_u.nfs4_fl.owner); | 4200 | fl->fl_u.nfs4_fl.owner, |
4201 | recovery_type == NFS_LOCK_NEW ? GFP_KERNEL : GFP_NOFS); | ||
4199 | if (data == NULL) | 4202 | if (data == NULL) |
4200 | return -ENOMEM; | 4203 | return -ENOMEM; |
4201 | if (IS_SETLKW(cmd)) | 4204 | if (IS_SETLKW(cmd)) |
@@ -4684,7 +4687,7 @@ static int nfs4_reset_slot_table(struct nfs4_slot_table *tbl, u32 max_reqs, | |||
4684 | if (max_reqs != tbl->max_slots) { | 4687 | if (max_reqs != tbl->max_slots) { |
4685 | ret = -ENOMEM; | 4688 | ret = -ENOMEM; |
4686 | new = kmalloc(max_reqs * sizeof(struct nfs4_slot), | 4689 | new = kmalloc(max_reqs * sizeof(struct nfs4_slot), |
4687 | GFP_KERNEL); | 4690 | GFP_NOFS); |
4688 | if (!new) | 4691 | if (!new) |
4689 | goto out; | 4692 | goto out; |
4690 | ret = 0; | 4693 | ret = 0; |
@@ -4749,7 +4752,7 @@ static int nfs4_init_slot_table(struct nfs4_slot_table *tbl, | |||
4749 | 4752 | ||
4750 | dprintk("--> %s: max_reqs=%u\n", __func__, max_slots); | 4753 | dprintk("--> %s: max_reqs=%u\n", __func__, max_slots); |
4751 | 4754 | ||
4752 | slot = kcalloc(max_slots, sizeof(struct nfs4_slot), GFP_KERNEL); | 4755 | slot = kcalloc(max_slots, sizeof(struct nfs4_slot), GFP_NOFS); |
4753 | if (!slot) | 4756 | if (!slot) |
4754 | goto out; | 4757 | goto out; |
4755 | ret = 0; | 4758 | ret = 0; |
@@ -4798,7 +4801,7 @@ struct nfs4_session *nfs4_alloc_session(struct nfs_client *clp) | |||
4798 | struct nfs4_session *session; | 4801 | struct nfs4_session *session; |
4799 | struct nfs4_slot_table *tbl; | 4802 | struct nfs4_slot_table *tbl; |
4800 | 4803 | ||
4801 | session = kzalloc(sizeof(struct nfs4_session), GFP_KERNEL); | 4804 | session = kzalloc(sizeof(struct nfs4_session), GFP_NOFS); |
4802 | if (!session) | 4805 | if (!session) |
4803 | return NULL; | 4806 | return NULL; |
4804 | 4807 | ||
@@ -5142,8 +5145,8 @@ static int nfs41_proc_async_sequence(struct nfs_client *clp, | |||
5142 | 5145 | ||
5143 | if (!atomic_inc_not_zero(&clp->cl_count)) | 5146 | if (!atomic_inc_not_zero(&clp->cl_count)) |
5144 | return -EIO; | 5147 | return -EIO; |
5145 | args = kzalloc(sizeof(*args), GFP_KERNEL); | 5148 | args = kzalloc(sizeof(*args), GFP_NOFS); |
5146 | res = kzalloc(sizeof(*res), GFP_KERNEL); | 5149 | res = kzalloc(sizeof(*res), GFP_NOFS); |
5147 | if (!args || !res) { | 5150 | if (!args || !res) { |
5148 | kfree(args); | 5151 | kfree(args); |
5149 | kfree(res); | 5152 | kfree(res); |
@@ -5244,7 +5247,7 @@ static int nfs41_proc_reclaim_complete(struct nfs_client *clp) | |||
5244 | int status = -ENOMEM; | 5247 | int status = -ENOMEM; |
5245 | 5248 | ||
5246 | dprintk("--> %s\n", __func__); | 5249 | dprintk("--> %s\n", __func__); |
5247 | calldata = kzalloc(sizeof(*calldata), GFP_KERNEL); | 5250 | calldata = kzalloc(sizeof(*calldata), GFP_NOFS); |
5248 | if (calldata == NULL) | 5251 | if (calldata == NULL) |
5249 | goto out; | 5252 | goto out; |
5250 | calldata->clp = clp; | 5253 | calldata->clp = clp; |