aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/nfs/nfs4proc.c53
1 files changed, 30 insertions, 23 deletions
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index fee2d14b158b..d90209e79587 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -214,7 +214,7 @@ static void update_changeattr(struct inode *dir, struct nfs4_change_info *cinfo)
214} 214}
215 215
216struct nfs4_opendata { 216struct nfs4_opendata {
217 atomic_t count; 217 struct kref kref;
218 struct nfs_openargs o_arg; 218 struct nfs_openargs o_arg;
219 struct nfs_openres o_res; 219 struct nfs_openres o_res;
220 struct nfs_open_confirmargs c_arg; 220 struct nfs_open_confirmargs c_arg;
@@ -245,7 +245,6 @@ static struct nfs4_opendata *nfs4_opendata_alloc(struct path *path,
245 p->o_arg.seqid = nfs_alloc_seqid(&sp->so_seqid); 245 p->o_arg.seqid = nfs_alloc_seqid(&sp->so_seqid);
246 if (p->o_arg.seqid == NULL) 246 if (p->o_arg.seqid == NULL)
247 goto err_free; 247 goto err_free;
248 atomic_set(&p->count, 1);
249 p->path.mnt = mntget(path->mnt); 248 p->path.mnt = mntget(path->mnt);
250 p->path.dentry = dget(path->dentry); 249 p->path.dentry = dget(path->dentry);
251 p->dir = parent; 250 p->dir = parent;
@@ -275,6 +274,7 @@ static struct nfs4_opendata *nfs4_opendata_alloc(struct path *path,
275 p->c_arg.fh = &p->o_res.fh; 274 p->c_arg.fh = &p->o_res.fh;
276 p->c_arg.stateid = &p->o_res.stateid; 275 p->c_arg.stateid = &p->o_res.stateid;
277 p->c_arg.seqid = p->o_arg.seqid; 276 p->c_arg.seqid = p->o_arg.seqid;
277 kref_init(&p->kref);
278 return p; 278 return p;
279err_free: 279err_free:
280 kfree(p); 280 kfree(p);
@@ -283,16 +283,23 @@ err:
283 return NULL; 283 return NULL;
284} 284}
285 285
286static void nfs4_opendata_free(struct nfs4_opendata *p) 286static void nfs4_opendata_free(struct kref *kref)
287{ 287{
288 if (p != NULL && atomic_dec_and_test(&p->count)) { 288 struct nfs4_opendata *p = container_of(kref,
289 nfs_free_seqid(p->o_arg.seqid); 289 struct nfs4_opendata, kref);
290 nfs4_put_state_owner(p->owner); 290
291 dput(p->dir); 291 nfs_free_seqid(p->o_arg.seqid);
292 dput(p->path.dentry); 292 nfs4_put_state_owner(p->owner);
293 mntput(p->path.mnt); 293 dput(p->dir);
294 kfree(p); 294 dput(p->path.dentry);
295 } 295 mntput(p->path.mnt);
296 kfree(p);
297}
298
299static void nfs4_opendata_put(struct nfs4_opendata *p)
300{
301 if (p != NULL)
302 kref_put(&p->kref, nfs4_opendata_free);
296} 303}
297 304
298static int nfs4_wait_for_completion_rpc_task(struct rpc_task *task) 305static int nfs4_wait_for_completion_rpc_task(struct rpc_task *task)
@@ -476,7 +483,7 @@ static int _nfs4_do_open_reclaim(struct nfs_open_context *ctx, struct nfs4_state
476 nfs_copy_fh(&opendata->o_res.fh, opendata->o_arg.fh); 483 nfs_copy_fh(&opendata->o_res.fh, opendata->o_arg.fh);
477 opendata->o_arg.u.delegation_type = delegation_type; 484 opendata->o_arg.u.delegation_type = delegation_type;
478 status = nfs4_open_recover(opendata, state); 485 status = nfs4_open_recover(opendata, state);
479 nfs4_opendata_free(opendata); 486 nfs4_opendata_put(opendata);
480 return status; 487 return status;
481} 488}
482 489
@@ -522,7 +529,7 @@ static int _nfs4_open_delegation_recall(struct nfs_open_context *ctx, struct nfs
522 memcpy(opendata->o_arg.u.delegation.data, state->stateid.data, 529 memcpy(opendata->o_arg.u.delegation.data, state->stateid.data,
523 sizeof(opendata->o_arg.u.delegation.data)); 530 sizeof(opendata->o_arg.u.delegation.data));
524 ret = nfs4_open_recover(opendata, state); 531 ret = nfs4_open_recover(opendata, state);
525 nfs4_opendata_free(opendata); 532 nfs4_opendata_put(opendata);
526 return ret; 533 return ret;
527} 534}
528 535
@@ -593,7 +600,7 @@ static void nfs4_open_confirm_release(void *calldata)
593 if (state != NULL) 600 if (state != NULL)
594 nfs4_close_state(&data->path, state, data->o_arg.open_flags); 601 nfs4_close_state(&data->path, state, data->o_arg.open_flags);
595out_free: 602out_free:
596 nfs4_opendata_free(data); 603 nfs4_opendata_put(data);
597} 604}
598 605
599static const struct rpc_call_ops nfs4_open_confirm_ops = { 606static const struct rpc_call_ops nfs4_open_confirm_ops = {
@@ -611,7 +618,7 @@ static int _nfs4_proc_open_confirm(struct nfs4_opendata *data)
611 struct rpc_task *task; 618 struct rpc_task *task;
612 int status; 619 int status;
613 620
614 atomic_inc(&data->count); 621 kref_get(&data->kref);
615 /* 622 /*
616 * If rpc_run_task() ends up calling ->rpc_release(), we 623 * If rpc_run_task() ends up calling ->rpc_release(), we
617 * want to ensure that it takes the 'error' code path. 624 * want to ensure that it takes the 'error' code path.
@@ -696,7 +703,7 @@ static void nfs4_open_release(void *calldata)
696 if (state != NULL) 703 if (state != NULL)
697 nfs4_close_state(&data->path, state, data->o_arg.open_flags); 704 nfs4_close_state(&data->path, state, data->o_arg.open_flags);
698out_free: 705out_free:
699 nfs4_opendata_free(data); 706 nfs4_opendata_put(data);
700} 707}
701 708
702static const struct rpc_call_ops nfs4_open_ops = { 709static const struct rpc_call_ops nfs4_open_ops = {
@@ -717,7 +724,7 @@ static int _nfs4_proc_open(struct nfs4_opendata *data)
717 struct rpc_task *task; 724 struct rpc_task *task;
718 int status; 725 int status;
719 726
720 atomic_inc(&data->count); 727 kref_get(&data->kref);
721 /* 728 /*
722 * If rpc_run_task() ends up calling ->rpc_release(), we 729 * If rpc_run_task() ends up calling ->rpc_release(), we
723 * want to ensure that it takes the 'error' code path. 730 * want to ensure that it takes the 'error' code path.
@@ -826,7 +833,7 @@ static int _nfs4_open_expired(struct nfs_open_context *ctx, struct nfs4_state *s
826 nfs4_drop_state_owner(state->owner); 833 nfs4_drop_state_owner(state->owner);
827 d_drop(ctx->path.dentry); 834 d_drop(ctx->path.dentry);
828 } 835 }
829 nfs4_opendata_free(opendata); 836 nfs4_opendata_put(opendata);
830 return ret; 837 return ret;
831} 838}
832 839
@@ -987,7 +994,7 @@ static int _nfs4_do_open(struct inode *dir, struct path *path, int flags, struct
987 994
988 status = _nfs4_proc_open(opendata); 995 status = _nfs4_proc_open(opendata);
989 if (status != 0) 996 if (status != 0)
990 goto err_opendata_free; 997 goto err_opendata_put;
991 998
992 if (opendata->o_arg.open_flags & O_EXCL) 999 if (opendata->o_arg.open_flags & O_EXCL)
993 nfs4_exclusive_attrset(opendata, sattr); 1000 nfs4_exclusive_attrset(opendata, sattr);
@@ -995,16 +1002,16 @@ static int _nfs4_do_open(struct inode *dir, struct path *path, int flags, struct
995 status = -ENOMEM; 1002 status = -ENOMEM;
996 state = nfs4_opendata_to_nfs4_state(opendata); 1003 state = nfs4_opendata_to_nfs4_state(opendata);
997 if (state == NULL) 1004 if (state == NULL)
998 goto err_opendata_free; 1005 goto err_opendata_put;
999 if (opendata->o_res.delegation_type != 0) 1006 if (opendata->o_res.delegation_type != 0)
1000 nfs_inode_set_delegation(state->inode, cred, &opendata->o_res); 1007 nfs_inode_set_delegation(state->inode, cred, &opendata->o_res);
1001 nfs4_opendata_free(opendata); 1008 nfs4_opendata_put(opendata);
1002 nfs4_put_state_owner(sp); 1009 nfs4_put_state_owner(sp);
1003 up_read(&clp->cl_sem); 1010 up_read(&clp->cl_sem);
1004 *res = state; 1011 *res = state;
1005 return 0; 1012 return 0;
1006err_opendata_free: 1013err_opendata_put:
1007 nfs4_opendata_free(opendata); 1014 nfs4_opendata_put(opendata);
1008err_release_rwsem: 1015err_release_rwsem:
1009 up_read(&clp->cl_sem); 1016 up_read(&clp->cl_sem);
1010err_put_state_owner: 1017err_put_state_owner: