diff options
Diffstat (limited to 'fs')
-rw-r--r-- | fs/nfs/delegation.c | 17 | ||||
-rw-r--r-- | fs/nfs/delegation.h | 1 | ||||
-rw-r--r-- | fs/nfs/nfs4proc.c | 16 |
3 files changed, 28 insertions, 6 deletions
diff --git a/fs/nfs/delegation.c b/fs/nfs/delegation.c index d8b47624fee2..a5cb44375100 100644 --- a/fs/nfs/delegation.c +++ b/fs/nfs/delegation.c | |||
@@ -19,6 +19,7 @@ | |||
19 | #include <linux/nfs_xdr.h> | 19 | #include <linux/nfs_xdr.h> |
20 | 20 | ||
21 | #include "nfs4_fs.h" | 21 | #include "nfs4_fs.h" |
22 | #include "nfs4session.h" | ||
22 | #include "delegation.h" | 23 | #include "delegation.h" |
23 | #include "internal.h" | 24 | #include "internal.h" |
24 | #include "nfs4trace.h" | 25 | #include "nfs4trace.h" |
@@ -547,6 +548,22 @@ int nfs4_inode_return_delegation(struct inode *inode) | |||
547 | return err; | 548 | return err; |
548 | } | 549 | } |
549 | 550 | ||
551 | /** | ||
552 | * nfs4_inode_make_writeable | ||
553 | * @inode: pointer to inode | ||
554 | * | ||
555 | * Make the inode writeable by returning the delegation if necessary | ||
556 | * | ||
557 | * Returns zero on success, or a negative errno value. | ||
558 | */ | ||
559 | int nfs4_inode_make_writeable(struct inode *inode) | ||
560 | { | ||
561 | if (!nfs4_has_session(NFS_SERVER(inode)->nfs_client) || | ||
562 | !nfs4_check_delegation(inode, FMODE_WRITE)) | ||
563 | return nfs4_inode_return_delegation(inode); | ||
564 | return 0; | ||
565 | } | ||
566 | |||
550 | static void nfs_mark_return_if_closed_delegation(struct nfs_server *server, | 567 | static void nfs_mark_return_if_closed_delegation(struct nfs_server *server, |
551 | struct nfs_delegation *delegation) | 568 | struct nfs_delegation *delegation) |
552 | { | 569 | { |
diff --git a/fs/nfs/delegation.h b/fs/nfs/delegation.h index 185a09f37a89..dcc8a783a6e1 100644 --- a/fs/nfs/delegation.h +++ b/fs/nfs/delegation.h | |||
@@ -70,6 +70,7 @@ int nfs4_check_delegation(struct inode *inode, fmode_t flags); | |||
70 | bool nfs4_delegation_flush_on_close(const struct inode *inode); | 70 | bool nfs4_delegation_flush_on_close(const struct inode *inode); |
71 | void nfs_inode_find_delegation_state_and_recover(struct inode *inode, | 71 | void nfs_inode_find_delegation_state_and_recover(struct inode *inode, |
72 | const nfs4_stateid *stateid); | 72 | const nfs4_stateid *stateid); |
73 | int nfs4_inode_make_writeable(struct inode *inode); | ||
73 | 74 | ||
74 | #endif | 75 | #endif |
75 | 76 | ||
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 04978bfd6beb..24b5c80b8128 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
@@ -3877,7 +3877,7 @@ nfs4_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr, | |||
3877 | 3877 | ||
3878 | /* Return any delegations if we're going to change ACLs */ | 3878 | /* Return any delegations if we're going to change ACLs */ |
3879 | if ((sattr->ia_valid & (ATTR_MODE|ATTR_UID|ATTR_GID)) != 0) | 3879 | if ((sattr->ia_valid & (ATTR_MODE|ATTR_UID|ATTR_GID)) != 0) |
3880 | nfs4_inode_return_delegation(inode); | 3880 | nfs4_inode_make_writeable(inode); |
3881 | 3881 | ||
3882 | status = nfs4_do_setattr(inode, cred, fattr, sattr, ctx, NULL, label); | 3882 | status = nfs4_do_setattr(inode, cred, fattr, sattr, ctx, NULL, label); |
3883 | if (status == 0) { | 3883 | if (status == 0) { |
@@ -4210,8 +4210,12 @@ static int nfs4_proc_remove(struct inode *dir, struct dentry *dentry) | |||
4210 | struct inode *inode = d_inode(dentry); | 4210 | struct inode *inode = d_inode(dentry); |
4211 | int err; | 4211 | int err; |
4212 | 4212 | ||
4213 | if (inode) | 4213 | if (inode) { |
4214 | nfs4_inode_return_delegation(inode); | 4214 | if (inode->i_nlink == 1) |
4215 | nfs4_inode_return_delegation(inode); | ||
4216 | else | ||
4217 | nfs4_inode_make_writeable(inode); | ||
4218 | } | ||
4215 | do { | 4219 | do { |
4216 | err = _nfs4_proc_remove(dir, &dentry->d_name); | 4220 | err = _nfs4_proc_remove(dir, &dentry->d_name); |
4217 | trace_nfs4_remove(dir, &dentry->d_name, err); | 4221 | trace_nfs4_remove(dir, &dentry->d_name, err); |
@@ -4284,7 +4288,7 @@ static void nfs4_proc_rename_setup(struct rpc_message *msg, | |||
4284 | struct inode *new_inode = d_inode(new_dentry); | 4288 | struct inode *new_inode = d_inode(new_dentry); |
4285 | 4289 | ||
4286 | if (old_inode) | 4290 | if (old_inode) |
4287 | nfs4_inode_return_delegation(old_inode); | 4291 | nfs4_inode_make_writeable(old_inode); |
4288 | if (new_inode) | 4292 | if (new_inode) |
4289 | nfs4_inode_return_delegation(new_inode); | 4293 | nfs4_inode_return_delegation(new_inode); |
4290 | msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_RENAME]; | 4294 | msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_RENAME]; |
@@ -4350,7 +4354,7 @@ static int _nfs4_proc_link(struct inode *inode, struct inode *dir, const struct | |||
4350 | } | 4354 | } |
4351 | arg.bitmask = nfs4_bitmask(server, res.label); | 4355 | arg.bitmask = nfs4_bitmask(server, res.label); |
4352 | 4356 | ||
4353 | nfs4_inode_return_delegation(inode); | 4357 | nfs4_inode_make_writeable(inode); |
4354 | 4358 | ||
4355 | status = nfs4_call_sync(server->client, server, &msg, &arg.seq_args, &res.seq_res, 1); | 4359 | status = nfs4_call_sync(server->client, server, &msg, &arg.seq_args, &res.seq_res, 1); |
4356 | if (!status) { | 4360 | if (!status) { |
@@ -5345,7 +5349,7 @@ static int __nfs4_proc_set_acl(struct inode *inode, const void *buf, size_t bufl | |||
5345 | i = buf_to_pages_noslab(buf, buflen, arg.acl_pages); | 5349 | i = buf_to_pages_noslab(buf, buflen, arg.acl_pages); |
5346 | if (i < 0) | 5350 | if (i < 0) |
5347 | return i; | 5351 | return i; |
5348 | nfs4_inode_return_delegation(inode); | 5352 | nfs4_inode_make_writeable(inode); |
5349 | ret = nfs4_call_sync(server->client, server, &msg, &arg.seq_args, &res.seq_res, 1); | 5353 | ret = nfs4_call_sync(server->client, server, &msg, &arg.seq_args, &res.seq_res, 1); |
5350 | 5354 | ||
5351 | /* | 5355 | /* |