aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2014-08-29 16:04:13 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2014-08-29 16:04:13 -0400
commit878e580e211c519c1b32a2c65786d308a759ec24 (patch)
treeabb7a44574589d016d3a94898187fb2ea86bb95f /fs
parent848298c6fb36fbe459854e376ce90af32ba6e1ce (diff)
parentf87d928f6d98644d39809a013a22f981d39017cf (diff)
Merge tag 'nfs-for-3.17-3' of git://git.linux-nfs.org/projects/trondmy/linux-nfs
Pull NFS client fixes from Trond Myklebust: "Highlights: - NFSv3 stable fix for another POSIX ACL regression - NFSv4 stable fix for a regression with OPEN_DOWNGRADE - NFSv4 stable fix for bad close() behaviour when holding a delegation" * tag 'nfs-for-3.17-3' of git://git.linux-nfs.org/projects/trondmy/linux-nfs: NFSv3: Fix another acl regression NFSv4: Don't clear the open state when we just did an OPEN_DOWNGRADE NFSv4: Fix problems with close in the presence of a delegation
Diffstat (limited to 'fs')
-rw-r--r--fs/nfs/nfs3acl.c5
-rw-r--r--fs/nfs/nfs4proc.c26
2 files changed, 21 insertions, 10 deletions
diff --git a/fs/nfs/nfs3acl.c b/fs/nfs/nfs3acl.c
index d0fec260132a..24c6898159cc 100644
--- a/fs/nfs/nfs3acl.c
+++ b/fs/nfs/nfs3acl.c
@@ -129,7 +129,10 @@ static int __nfs3_proc_setacls(struct inode *inode, struct posix_acl *acl,
129 .rpc_argp = &args, 129 .rpc_argp = &args,
130 .rpc_resp = &fattr, 130 .rpc_resp = &fattr,
131 }; 131 };
132 int status; 132 int status = 0;
133
134 if (acl == NULL && (!S_ISDIR(inode->i_mode) || dfacl == NULL))
135 goto out;
133 136
134 status = -EOPNOTSUPP; 137 status = -EOPNOTSUPP;
135 if (!nfs_server_capable(inode, NFS_CAP_ACLS)) 138 if (!nfs_server_capable(inode, NFS_CAP_ACLS))
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 75ae8d22f067..7dd8aca31c29 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -2560,6 +2560,7 @@ static void nfs4_close_done(struct rpc_task *task, void *data)
2560 struct nfs4_closedata *calldata = data; 2560 struct nfs4_closedata *calldata = data;
2561 struct nfs4_state *state = calldata->state; 2561 struct nfs4_state *state = calldata->state;
2562 struct nfs_server *server = NFS_SERVER(calldata->inode); 2562 struct nfs_server *server = NFS_SERVER(calldata->inode);
2563 nfs4_stateid *res_stateid = NULL;
2563 2564
2564 dprintk("%s: begin!\n", __func__); 2565 dprintk("%s: begin!\n", __func__);
2565 if (!nfs4_sequence_done(task, &calldata->res.seq_res)) 2566 if (!nfs4_sequence_done(task, &calldata->res.seq_res))
@@ -2570,12 +2571,12 @@ static void nfs4_close_done(struct rpc_task *task, void *data)
2570 */ 2571 */
2571 switch (task->tk_status) { 2572 switch (task->tk_status) {
2572 case 0: 2573 case 0:
2573 if (calldata->roc) 2574 res_stateid = &calldata->res.stateid;
2575 if (calldata->arg.fmode == 0 && calldata->roc)
2574 pnfs_roc_set_barrier(state->inode, 2576 pnfs_roc_set_barrier(state->inode,
2575 calldata->roc_barrier); 2577 calldata->roc_barrier);
2576 nfs_clear_open_stateid(state, &calldata->res.stateid, 0);
2577 renew_lease(server, calldata->timestamp); 2578 renew_lease(server, calldata->timestamp);
2578 goto out_release; 2579 break;
2579 case -NFS4ERR_ADMIN_REVOKED: 2580 case -NFS4ERR_ADMIN_REVOKED:
2580 case -NFS4ERR_STALE_STATEID: 2581 case -NFS4ERR_STALE_STATEID:
2581 case -NFS4ERR_OLD_STATEID: 2582 case -NFS4ERR_OLD_STATEID:
@@ -2589,7 +2590,7 @@ static void nfs4_close_done(struct rpc_task *task, void *data)
2589 goto out_release; 2590 goto out_release;
2590 } 2591 }
2591 } 2592 }
2592 nfs_clear_open_stateid(state, NULL, calldata->arg.fmode); 2593 nfs_clear_open_stateid(state, res_stateid, calldata->arg.fmode);
2593out_release: 2594out_release:
2594 nfs_release_seqid(calldata->arg.seqid); 2595 nfs_release_seqid(calldata->arg.seqid);
2595 nfs_refresh_inode(calldata->inode, calldata->res.fattr); 2596 nfs_refresh_inode(calldata->inode, calldata->res.fattr);
@@ -2601,6 +2602,7 @@ static void nfs4_close_prepare(struct rpc_task *task, void *data)
2601 struct nfs4_closedata *calldata = data; 2602 struct nfs4_closedata *calldata = data;
2602 struct nfs4_state *state = calldata->state; 2603 struct nfs4_state *state = calldata->state;
2603 struct inode *inode = calldata->inode; 2604 struct inode *inode = calldata->inode;
2605 bool is_rdonly, is_wronly, is_rdwr;
2604 int call_close = 0; 2606 int call_close = 0;
2605 2607
2606 dprintk("%s: begin!\n", __func__); 2608 dprintk("%s: begin!\n", __func__);
@@ -2608,18 +2610,24 @@ static void nfs4_close_prepare(struct rpc_task *task, void *data)
2608 goto out_wait; 2610 goto out_wait;
2609 2611
2610 task->tk_msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OPEN_DOWNGRADE]; 2612 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); 2613 spin_lock(&state->owner->so_lock);
2614 is_rdwr = test_bit(NFS_O_RDWR_STATE, &state->flags);
2615 is_rdonly = test_bit(NFS_O_RDONLY_STATE, &state->flags);
2616 is_wronly = test_bit(NFS_O_WRONLY_STATE, &state->flags);
2617 /* Calculate the current open share mode */
2618 calldata->arg.fmode = 0;
2619 if (is_rdonly || is_rdwr)
2620 calldata->arg.fmode |= FMODE_READ;
2621 if (is_wronly || is_rdwr)
2622 calldata->arg.fmode |= FMODE_WRITE;
2613 /* Calculate the change in open mode */ 2623 /* Calculate the change in open mode */
2614 if (state->n_rdwr == 0) { 2624 if (state->n_rdwr == 0) {
2615 if (state->n_rdonly == 0) { 2625 if (state->n_rdonly == 0) {
2616 call_close |= test_bit(NFS_O_RDONLY_STATE, &state->flags); 2626 call_close |= is_rdonly || is_rdwr;
2617 call_close |= test_bit(NFS_O_RDWR_STATE, &state->flags);
2618 calldata->arg.fmode &= ~FMODE_READ; 2627 calldata->arg.fmode &= ~FMODE_READ;
2619 } 2628 }
2620 if (state->n_wronly == 0) { 2629 if (state->n_wronly == 0) {
2621 call_close |= test_bit(NFS_O_WRONLY_STATE, &state->flags); 2630 call_close |= is_wronly || is_rdwr;
2622 call_close |= test_bit(NFS_O_RDWR_STATE, &state->flags);
2623 calldata->arg.fmode &= ~FMODE_WRITE; 2631 calldata->arg.fmode &= ~FMODE_WRITE;
2624 } 2632 }
2625 } 2633 }