summaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
Diffstat (limited to 'fs')
-rw-r--r--fs/nfs/delegation.c17
-rw-r--r--fs/nfs/delegation.h1
-rw-r--r--fs/nfs/nfs4proc.c16
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 */
559int 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
550static void nfs_mark_return_if_closed_delegation(struct nfs_server *server, 567static 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);
70bool nfs4_delegation_flush_on_close(const struct inode *inode); 70bool nfs4_delegation_flush_on_close(const struct inode *inode);
71void nfs_inode_find_delegation_state_and_recover(struct inode *inode, 71void nfs_inode_find_delegation_state_and_recover(struct inode *inode,
72 const nfs4_stateid *stateid); 72 const nfs4_stateid *stateid);
73int 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 /*