diff options
-rw-r--r-- | fs/nfs/nfs4proc.c | 53 |
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 | ||
216 | struct nfs4_opendata { | 216 | struct 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; |
279 | err_free: | 279 | err_free: |
280 | kfree(p); | 280 | kfree(p); |
@@ -283,16 +283,23 @@ err: | |||
283 | return NULL; | 283 | return NULL; |
284 | } | 284 | } |
285 | 285 | ||
286 | static void nfs4_opendata_free(struct nfs4_opendata *p) | 286 | static 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 | |||
299 | static 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 | ||
298 | static int nfs4_wait_for_completion_rpc_task(struct rpc_task *task) | 305 | static 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); |
595 | out_free: | 602 | out_free: |
596 | nfs4_opendata_free(data); | 603 | nfs4_opendata_put(data); |
597 | } | 604 | } |
598 | 605 | ||
599 | static const struct rpc_call_ops nfs4_open_confirm_ops = { | 606 | static 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); |
698 | out_free: | 705 | out_free: |
699 | nfs4_opendata_free(data); | 706 | nfs4_opendata_put(data); |
700 | } | 707 | } |
701 | 708 | ||
702 | static const struct rpc_call_ops nfs4_open_ops = { | 709 | static 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; |
1006 | err_opendata_free: | 1013 | err_opendata_put: |
1007 | nfs4_opendata_free(opendata); | 1014 | nfs4_opendata_put(opendata); |
1008 | err_release_rwsem: | 1015 | err_release_rwsem: |
1009 | up_read(&clp->cl_sem); | 1016 | up_read(&clp->cl_sem); |
1010 | err_put_state_owner: | 1017 | err_put_state_owner: |