aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/nfs4proc.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nfs/nfs4proc.c')
-rw-r--r--fs/nfs/nfs4proc.c50
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);
2593out_release: 2598out_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);