aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2017-06-28 16:27:15 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2017-06-28 16:27:15 -0400
commite547204f1f4f314a7352f7b93332fdc1a2e4b24c (patch)
tree2a6d1cdd9224b4a402f479c8d3b25944ae0a111e /fs
parent5a37be4b51bbf85e37cdb5831899c330505faf03 (diff)
parent2e31b4cb895ae78db31dffb860cd255d86c6561c (diff)
Merge tag 'nfs-for-4.12-3' of git://git.linux-nfs.org/projects/trondmy/linux-nfs
Pull NFS client bugfixes from Trond Myklebust: "Bugfixes include: - stable fix for exclusive create if the server supports the umask attribute - trunking detection should handle ERESTARTSYS/EINTR - stable fix for a race in the LAYOUTGET function - stable fix to revert "nfs_rename() handle -ERESTARTSYS dentry left behind" - nfs4_callback_free_slot() cannot call nfs4_slot_tbl_drain_complete()" * tag 'nfs-for-4.12-3' of git://git.linux-nfs.org/projects/trondmy/linux-nfs: NFSv4.1: nfs4_callback_free_slot() cannot call nfs4_slot_tbl_drain_complete() Revert "NFS: nfs_rename() handle -ERESTARTSYS dentry left behind" NFSv4.1: Fix a race in nfs4_proc_layoutget NFS: Trunking detection should handle ERESTARTSYS/EINTR NFSv4.2: Don't send mode again in post-EXCLUSIVE4_1 SETATTR with umask
Diffstat (limited to 'fs')
-rw-r--r--fs/nfs/callback_xdr.c1
-rw-r--r--fs/nfs/dir.c51
-rw-r--r--fs/nfs/nfs4proc.c5
-rw-r--r--fs/nfs/nfs4state.c2
4 files changed, 29 insertions, 30 deletions
diff --git a/fs/nfs/callback_xdr.c b/fs/nfs/callback_xdr.c
index c14758e08d73..390ac9c39c59 100644
--- a/fs/nfs/callback_xdr.c
+++ b/fs/nfs/callback_xdr.c
@@ -753,7 +753,6 @@ static void nfs4_callback_free_slot(struct nfs4_session *session,
753 * A single slot, so highest used slotid is either 0 or -1 753 * A single slot, so highest used slotid is either 0 or -1
754 */ 754 */
755 nfs4_free_slot(tbl, slot); 755 nfs4_free_slot(tbl, slot);
756 nfs4_slot_tbl_drain_complete(tbl);
757 spin_unlock(&tbl->slot_tbl_lock); 756 spin_unlock(&tbl->slot_tbl_lock);
758} 757}
759 758
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index 32ccd7754f8a..2ac00bf4ecf1 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -1946,29 +1946,6 @@ nfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry)
1946} 1946}
1947EXPORT_SYMBOL_GPL(nfs_link); 1947EXPORT_SYMBOL_GPL(nfs_link);
1948 1948
1949static void
1950nfs_complete_rename(struct rpc_task *task, struct nfs_renamedata *data)
1951{
1952 struct dentry *old_dentry = data->old_dentry;
1953 struct dentry *new_dentry = data->new_dentry;
1954 struct inode *old_inode = d_inode(old_dentry);
1955 struct inode *new_inode = d_inode(new_dentry);
1956
1957 nfs_mark_for_revalidate(old_inode);
1958
1959 switch (task->tk_status) {
1960 case 0:
1961 if (new_inode != NULL)
1962 nfs_drop_nlink(new_inode);
1963 d_move(old_dentry, new_dentry);
1964 nfs_set_verifier(new_dentry,
1965 nfs_save_change_attribute(data->new_dir));
1966 break;
1967 case -ENOENT:
1968 nfs_dentry_handle_enoent(old_dentry);
1969 }
1970}
1971
1972/* 1949/*
1973 * RENAME 1950 * RENAME
1974 * FIXME: Some nfsds, like the Linux user space nfsd, may generate a 1951 * FIXME: Some nfsds, like the Linux user space nfsd, may generate a
@@ -1999,7 +1976,7 @@ int nfs_rename(struct inode *old_dir, struct dentry *old_dentry,
1999{ 1976{
2000 struct inode *old_inode = d_inode(old_dentry); 1977 struct inode *old_inode = d_inode(old_dentry);
2001 struct inode *new_inode = d_inode(new_dentry); 1978 struct inode *new_inode = d_inode(new_dentry);
2002 struct dentry *dentry = NULL; 1979 struct dentry *dentry = NULL, *rehash = NULL;
2003 struct rpc_task *task; 1980 struct rpc_task *task;
2004 int error = -EBUSY; 1981 int error = -EBUSY;
2005 1982
@@ -2022,8 +1999,10 @@ int nfs_rename(struct inode *old_dir, struct dentry *old_dentry,
2022 * To prevent any new references to the target during the 1999 * To prevent any new references to the target during the
2023 * rename, we unhash the dentry in advance. 2000 * rename, we unhash the dentry in advance.
2024 */ 2001 */
2025 if (!d_unhashed(new_dentry)) 2002 if (!d_unhashed(new_dentry)) {
2026 d_drop(new_dentry); 2003 d_drop(new_dentry);
2004 rehash = new_dentry;
2005 }
2027 2006
2028 if (d_count(new_dentry) > 2) { 2007 if (d_count(new_dentry) > 2) {
2029 int err; 2008 int err;
@@ -2040,6 +2019,7 @@ int nfs_rename(struct inode *old_dir, struct dentry *old_dentry,
2040 goto out; 2019 goto out;
2041 2020
2042 new_dentry = dentry; 2021 new_dentry = dentry;
2022 rehash = NULL;
2043 new_inode = NULL; 2023 new_inode = NULL;
2044 } 2024 }
2045 } 2025 }
@@ -2048,8 +2028,7 @@ int nfs_rename(struct inode *old_dir, struct dentry *old_dentry,
2048 if (new_inode != NULL) 2028 if (new_inode != NULL)
2049 NFS_PROTO(new_inode)->return_delegation(new_inode); 2029 NFS_PROTO(new_inode)->return_delegation(new_inode);
2050 2030
2051 task = nfs_async_rename(old_dir, new_dir, old_dentry, new_dentry, 2031 task = nfs_async_rename(old_dir, new_dir, old_dentry, new_dentry, NULL);
2052 nfs_complete_rename);
2053 if (IS_ERR(task)) { 2032 if (IS_ERR(task)) {
2054 error = PTR_ERR(task); 2033 error = PTR_ERR(task);
2055 goto out; 2034 goto out;
@@ -2059,9 +2038,27 @@ int nfs_rename(struct inode *old_dir, struct dentry *old_dentry,
2059 if (error == 0) 2038 if (error == 0)
2060 error = task->tk_status; 2039 error = task->tk_status;
2061 rpc_put_task(task); 2040 rpc_put_task(task);
2041 nfs_mark_for_revalidate(old_inode);
2062out: 2042out:
2043 if (rehash)
2044 d_rehash(rehash);
2063 trace_nfs_rename_exit(old_dir, old_dentry, 2045 trace_nfs_rename_exit(old_dir, old_dentry,
2064 new_dir, new_dentry, error); 2046 new_dir, new_dentry, error);
2047 if (!error) {
2048 if (new_inode != NULL)
2049 nfs_drop_nlink(new_inode);
2050 /*
2051 * The d_move() should be here instead of in an async RPC completion
2052 * handler because we need the proper locks to move the dentry. If
2053 * we're interrupted by a signal, the async RPC completion handler
2054 * should mark the directories for revalidation.
2055 */
2056 d_move(old_dentry, new_dentry);
2057 nfs_set_verifier(new_dentry,
2058 nfs_save_change_attribute(new_dir));
2059 } else if (error == -ENOENT)
2060 nfs_dentry_handle_enoent(old_dentry);
2061
2065 /* new dentry created? */ 2062 /* new dentry created? */
2066 if (dentry) 2063 if (dentry)
2067 dput(dentry); 2064 dput(dentry);
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index c08c46a3b8cd..dbfa18900e25 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -2589,7 +2589,8 @@ static inline void nfs4_exclusive_attrset(struct nfs4_opendata *opendata,
2589 2589
2590 /* Except MODE, it seems harmless of setting twice. */ 2590 /* Except MODE, it seems harmless of setting twice. */
2591 if (opendata->o_arg.createmode != NFS4_CREATE_EXCLUSIVE && 2591 if (opendata->o_arg.createmode != NFS4_CREATE_EXCLUSIVE &&
2592 attrset[1] & FATTR4_WORD1_MODE) 2592 (attrset[1] & FATTR4_WORD1_MODE ||
2593 attrset[2] & FATTR4_WORD2_MODE_UMASK))
2593 sattr->ia_valid &= ~ATTR_MODE; 2594 sattr->ia_valid &= ~ATTR_MODE;
2594 2595
2595 if (attrset[2] & FATTR4_WORD2_SECURITY_LABEL) 2596 if (attrset[2] & FATTR4_WORD2_SECURITY_LABEL)
@@ -8416,6 +8417,7 @@ static void nfs4_layoutget_release(void *calldata)
8416 size_t max_pages = max_response_pages(server); 8417 size_t max_pages = max_response_pages(server);
8417 8418
8418 dprintk("--> %s\n", __func__); 8419 dprintk("--> %s\n", __func__);
8420 nfs4_sequence_free_slot(&lgp->res.seq_res);
8419 nfs4_free_pages(lgp->args.layout.pages, max_pages); 8421 nfs4_free_pages(lgp->args.layout.pages, max_pages);
8420 pnfs_put_layout_hdr(NFS_I(inode)->layout); 8422 pnfs_put_layout_hdr(NFS_I(inode)->layout);
8421 put_nfs_open_context(lgp->args.ctx); 8423 put_nfs_open_context(lgp->args.ctx);
@@ -8490,7 +8492,6 @@ nfs4_proc_layoutget(struct nfs4_layoutget *lgp, long *timeout, gfp_t gfp_flags)
8490 /* if layoutp->len is 0, nfs4_layoutget_prepare called rpc_exit */ 8492 /* if layoutp->len is 0, nfs4_layoutget_prepare called rpc_exit */
8491 if (status == 0 && lgp->res.layoutp->len) 8493 if (status == 0 && lgp->res.layoutp->len)
8492 lseg = pnfs_layout_process(lgp); 8494 lseg = pnfs_layout_process(lgp);
8493 nfs4_sequence_free_slot(&lgp->res.seq_res);
8494 rpc_put_task(task); 8495 rpc_put_task(task);
8495 dprintk("<-- %s status=%d\n", __func__, status); 8496 dprintk("<-- %s status=%d\n", __func__, status);
8496 if (status) 8497 if (status)
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c
index b34de036501b..cbf82b0d4467 100644
--- a/fs/nfs/nfs4state.c
+++ b/fs/nfs/nfs4state.c
@@ -2134,6 +2134,8 @@ again:
2134 put_rpccred(cred); 2134 put_rpccred(cred);
2135 switch (status) { 2135 switch (status) {
2136 case 0: 2136 case 0:
2137 case -EINTR:
2138 case -ERESTARTSYS:
2137 break; 2139 break;
2138 case -ETIMEDOUT: 2140 case -ETIMEDOUT:
2139 if (clnt->cl_softrtry) 2141 if (clnt->cl_softrtry)