diff options
Diffstat (limited to 'fs/nfs/nfs4proc.c')
-rw-r--r-- | fs/nfs/nfs4proc.c | 50 |
1 files changed, 31 insertions, 19 deletions
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 75ae8d22f067..6ca0c8e7a945 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
@@ -2226,9 +2226,13 @@ static int _nfs4_open_and_get_state(struct nfs4_opendata *opendata, | |||
2226 | ret = _nfs4_proc_open(opendata); | 2226 | ret = _nfs4_proc_open(opendata); |
2227 | if (ret != 0) { | 2227 | if (ret != 0) { |
2228 | if (ret == -ENOENT) { | 2228 | if (ret == -ENOENT) { |
2229 | d_drop(opendata->dentry); | 2229 | dentry = opendata->dentry; |
2230 | d_add(opendata->dentry, NULL); | 2230 | if (dentry->d_inode) |
2231 | nfs_set_verifier(opendata->dentry, | 2231 | d_delete(dentry); |
2232 | else if (d_unhashed(dentry)) | ||
2233 | d_add(dentry, NULL); | ||
2234 | |||
2235 | nfs_set_verifier(dentry, | ||
2232 | nfs_save_change_attribute(opendata->dir->d_inode)); | 2236 | nfs_save_change_attribute(opendata->dir->d_inode)); |
2233 | } | 2237 | } |
2234 | goto out; | 2238 | goto out; |
@@ -2560,6 +2564,7 @@ static void nfs4_close_done(struct rpc_task *task, void *data) | |||
2560 | struct nfs4_closedata *calldata = data; | 2564 | struct nfs4_closedata *calldata = data; |
2561 | struct nfs4_state *state = calldata->state; | 2565 | struct nfs4_state *state = calldata->state; |
2562 | struct nfs_server *server = NFS_SERVER(calldata->inode); | 2566 | struct nfs_server *server = NFS_SERVER(calldata->inode); |
2567 | nfs4_stateid *res_stateid = NULL; | ||
2563 | 2568 | ||
2564 | dprintk("%s: begin!\n", __func__); | 2569 | dprintk("%s: begin!\n", __func__); |
2565 | if (!nfs4_sequence_done(task, &calldata->res.seq_res)) | 2570 | if (!nfs4_sequence_done(task, &calldata->res.seq_res)) |
@@ -2570,12 +2575,12 @@ static void nfs4_close_done(struct rpc_task *task, void *data) | |||
2570 | */ | 2575 | */ |
2571 | switch (task->tk_status) { | 2576 | switch (task->tk_status) { |
2572 | case 0: | 2577 | case 0: |
2573 | if (calldata->roc) | 2578 | res_stateid = &calldata->res.stateid; |
2579 | if (calldata->arg.fmode == 0 && calldata->roc) | ||
2574 | pnfs_roc_set_barrier(state->inode, | 2580 | pnfs_roc_set_barrier(state->inode, |
2575 | calldata->roc_barrier); | 2581 | calldata->roc_barrier); |
2576 | nfs_clear_open_stateid(state, &calldata->res.stateid, 0); | ||
2577 | renew_lease(server, calldata->timestamp); | 2582 | renew_lease(server, calldata->timestamp); |
2578 | goto out_release; | 2583 | break; |
2579 | case -NFS4ERR_ADMIN_REVOKED: | 2584 | case -NFS4ERR_ADMIN_REVOKED: |
2580 | case -NFS4ERR_STALE_STATEID: | 2585 | case -NFS4ERR_STALE_STATEID: |
2581 | case -NFS4ERR_OLD_STATEID: | 2586 | case -NFS4ERR_OLD_STATEID: |
@@ -2589,7 +2594,7 @@ static void nfs4_close_done(struct rpc_task *task, void *data) | |||
2589 | goto out_release; | 2594 | goto out_release; |
2590 | } | 2595 | } |
2591 | } | 2596 | } |
2592 | nfs_clear_open_stateid(state, NULL, calldata->arg.fmode); | 2597 | nfs_clear_open_stateid(state, res_stateid, calldata->arg.fmode); |
2593 | out_release: | 2598 | out_release: |
2594 | nfs_release_seqid(calldata->arg.seqid); | 2599 | nfs_release_seqid(calldata->arg.seqid); |
2595 | nfs_refresh_inode(calldata->inode, calldata->res.fattr); | 2600 | nfs_refresh_inode(calldata->inode, calldata->res.fattr); |
@@ -2601,6 +2606,7 @@ static void nfs4_close_prepare(struct rpc_task *task, void *data) | |||
2601 | struct nfs4_closedata *calldata = data; | 2606 | struct nfs4_closedata *calldata = data; |
2602 | struct nfs4_state *state = calldata->state; | 2607 | struct nfs4_state *state = calldata->state; |
2603 | struct inode *inode = calldata->inode; | 2608 | struct inode *inode = calldata->inode; |
2609 | bool is_rdonly, is_wronly, is_rdwr; | ||
2604 | int call_close = 0; | 2610 | int call_close = 0; |
2605 | 2611 | ||
2606 | dprintk("%s: begin!\n", __func__); | 2612 | dprintk("%s: begin!\n", __func__); |
@@ -2608,21 +2614,27 @@ static void nfs4_close_prepare(struct rpc_task *task, void *data) | |||
2608 | goto out_wait; | 2614 | goto out_wait; |
2609 | 2615 | ||
2610 | task->tk_msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OPEN_DOWNGRADE]; | 2616 | task->tk_msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OPEN_DOWNGRADE]; |
2611 | calldata->arg.fmode = FMODE_READ|FMODE_WRITE; | ||
2612 | spin_lock(&state->owner->so_lock); | 2617 | spin_lock(&state->owner->so_lock); |
2618 | is_rdwr = test_bit(NFS_O_RDWR_STATE, &state->flags); | ||
2619 | is_rdonly = test_bit(NFS_O_RDONLY_STATE, &state->flags); | ||
2620 | is_wronly = test_bit(NFS_O_WRONLY_STATE, &state->flags); | ||
2613 | /* Calculate the change in open mode */ | 2621 | /* Calculate the change in open mode */ |
2622 | calldata->arg.fmode = 0; | ||
2614 | if (state->n_rdwr == 0) { | 2623 | if (state->n_rdwr == 0) { |
2615 | if (state->n_rdonly == 0) { | 2624 | if (state->n_rdonly == 0) |
2616 | call_close |= test_bit(NFS_O_RDONLY_STATE, &state->flags); | 2625 | call_close |= is_rdonly; |
2617 | call_close |= test_bit(NFS_O_RDWR_STATE, &state->flags); | 2626 | else if (is_rdonly) |
2618 | calldata->arg.fmode &= ~FMODE_READ; | 2627 | calldata->arg.fmode |= FMODE_READ; |
2619 | } | 2628 | if (state->n_wronly == 0) |
2620 | if (state->n_wronly == 0) { | 2629 | call_close |= is_wronly; |
2621 | call_close |= test_bit(NFS_O_WRONLY_STATE, &state->flags); | 2630 | else if (is_wronly) |
2622 | call_close |= test_bit(NFS_O_RDWR_STATE, &state->flags); | 2631 | calldata->arg.fmode |= FMODE_WRITE; |
2623 | calldata->arg.fmode &= ~FMODE_WRITE; | 2632 | } else if (is_rdwr) |
2624 | } | 2633 | calldata->arg.fmode |= FMODE_READ|FMODE_WRITE; |
2625 | } | 2634 | |
2635 | if (calldata->arg.fmode == 0) | ||
2636 | call_close |= is_rdwr; | ||
2637 | |||
2626 | if (!nfs4_valid_open_stateid(state)) | 2638 | if (!nfs4_valid_open_stateid(state)) |
2627 | call_close = 0; | 2639 | call_close = 0; |
2628 | spin_unlock(&state->owner->so_lock); | 2640 | spin_unlock(&state->owner->so_lock); |