diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2017-06-28 16:27:15 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2017-06-28 16:27:15 -0400 |
| commit | e547204f1f4f314a7352f7b93332fdc1a2e4b24c (patch) | |
| tree | 2a6d1cdd9224b4a402f479c8d3b25944ae0a111e /fs | |
| parent | 5a37be4b51bbf85e37cdb5831899c330505faf03 (diff) | |
| parent | 2e31b4cb895ae78db31dffb860cd255d86c6561c (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.c | 1 | ||||
| -rw-r--r-- | fs/nfs/dir.c | 51 | ||||
| -rw-r--r-- | fs/nfs/nfs4proc.c | 5 | ||||
| -rw-r--r-- | fs/nfs/nfs4state.c | 2 |
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 | } |
| 1947 | EXPORT_SYMBOL_GPL(nfs_link); | 1947 | EXPORT_SYMBOL_GPL(nfs_link); |
| 1948 | 1948 | ||
| 1949 | static void | ||
| 1950 | nfs_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); | ||
| 2062 | out: | 2042 | out: |
| 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) |
