Skip to content

Commit a647034

Browse files
committed
Merge tag 'nfs-for-5.13-1' of git://git.linux-nfs.org/projects/trondmy/linux-nfs
Pull NFS client updates from Trond Myklebust: "Highlights include: Stable fixes: - Add validation of the UDP retrans parameter to prevent shift out-of-bounds - Don't discard pNFS layout segments that are marked for return Bugfixes: - Fix a NULL dereference crash in xprt_complete_bc_request() when the NFSv4.1 server misbehaves. - Fix the handling of NFS READDIR cookie verifiers - Sundry fixes to ensure attribute revalidation works correctly when the server does not return post-op attributes. - nfs4_bitmask_adjust() must not change the server global bitmasks - Fix major timeout handling in the RPC code. - NFSv4.2 fallocate() fixes. - Fix the NFSv4.2 SEEK_HOLE/SEEK_DATA end-of-file handling - Copy offload attribute revalidation fixes - Fix an incorrect filehandle size check in the pNFS flexfiles driver - Fix several RDMA transport setup/teardown races - Fix several RDMA queue wrapping issues - Fix a misplaced memory read barrier in sunrpc's call_decode() Features: - Micro optimisation of the TCP transmission queue using TCP_CORK - statx() performance improvements by further splitting up the tracking of invalid cached file metadata. - Support the NFSv4.2 'change_attr_type' attribute and use it to optimise handling of change attribute updates" * tag 'nfs-for-5.13-1' of git://git.linux-nfs.org/projects/trondmy/linux-nfs: (85 commits) xprtrdma: Fix a NULL dereference in frwr_unmap_sync() sunrpc: Fix misplaced barrier in call_decode NFSv4.2: Remove ifdef CONFIG_NFSD from NFSv4.2 client SSC code. xprtrdma: Move fr_mr field to struct rpcrdma_mr xprtrdma: Move the Work Request union to struct rpcrdma_mr xprtrdma: Move fr_linv_done field to struct rpcrdma_mr xprtrdma: Move cqe to struct rpcrdma_mr xprtrdma: Move fr_cid to struct rpcrdma_mr xprtrdma: Remove the RPC/RDMA QP event handler xprtrdma: Don't display r_xprt memory addresses in tracepoints xprtrdma: Add an rpcrdma_mr_completion_class xprtrdma: Add tracepoints showing FastReg WRs and remote invalidation xprtrdma: Avoid Send Queue wrapping xprtrdma: Do not wake RPC consumer on a failed LocalInv xprtrdma: Do not recycle MR after FastReg/LocalInv flushes xprtrdma: Clarify use of barrier in frwr_wc_localinv_done() xprtrdma: Rename frwr_release_mr() xprtrdma: rpcrdma_mr_pop() already does list_del_init() xprtrdma: Delete rpcrdma_recv_buffer_put() xprtrdma: Fix cwnd update ordering ...
2 parents e22e983 + 9e895cd commit a647034

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

48 files changed

+1112
-715
lines changed

fs/Kconfig

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -338,8 +338,8 @@ config NFS_COMMON
338338
default y
339339

340340
config NFS_V4_2_SSC_HELPER
341-
tristate
342-
default y if NFS_V4=y || NFS_FS=y
341+
bool
342+
default y if NFS_V4_2
343343

344344
source "net/sunrpc/Kconfig"
345345
source "fs/ceph/Kconfig"

fs/nfs/callback_proc.c

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -137,12 +137,12 @@ static struct inode *nfs_layout_find_inode_by_stateid(struct nfs_client *clp,
137137
list_for_each_entry_rcu(lo, &server->layouts, plh_layouts) {
138138
if (!pnfs_layout_is_valid(lo))
139139
continue;
140-
if (stateid != NULL &&
141-
!nfs4_stateid_match_other(stateid, &lo->plh_stateid))
140+
if (!nfs4_stateid_match_other(stateid, &lo->plh_stateid))
142141
continue;
143-
if (!nfs_sb_active(server->super))
144-
continue;
145-
inode = igrab(lo->plh_inode);
142+
if (nfs_sb_active(server->super))
143+
inode = igrab(lo->plh_inode);
144+
else
145+
inode = ERR_PTR(-EAGAIN);
146146
rcu_read_unlock();
147147
if (inode)
148148
return inode;
@@ -176,9 +176,10 @@ static struct inode *nfs_layout_find_inode_by_fh(struct nfs_client *clp,
176176
continue;
177177
if (nfsi->layout != lo)
178178
continue;
179-
if (!nfs_sb_active(server->super))
180-
continue;
181-
inode = igrab(lo->plh_inode);
179+
if (nfs_sb_active(server->super))
180+
inode = igrab(lo->plh_inode);
181+
else
182+
inode = ERR_PTR(-EAGAIN);
182183
rcu_read_unlock();
183184
if (inode)
184185
return inode;

fs/nfs/client.c

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -476,7 +476,6 @@ void nfs_init_timeout_values(struct rpc_timeout *to, int proto,
476476
to->to_maxval = to->to_initval;
477477
to->to_exponential = 0;
478478
break;
479-
#ifndef CONFIG_NFS_DISABLE_UDP_SUPPORT
480479
case XPRT_TRANSPORT_UDP:
481480
if (retrans == NFS_UNSPEC_RETRANS)
482481
to->to_retries = NFS_DEF_UDP_RETRANS;
@@ -487,7 +486,6 @@ void nfs_init_timeout_values(struct rpc_timeout *to, int proto,
487486
to->to_maxval = NFS_MAX_UDP_TIMEOUT;
488487
to->to_exponential = 1;
489488
break;
490-
#endif
491489
default:
492490
BUG();
493491
}
@@ -698,9 +696,18 @@ static int nfs_init_server(struct nfs_server *server,
698696
/* Initialise the client representation from the mount data */
699697
server->flags = ctx->flags;
700698
server->options = ctx->options;
701-
server->caps |= NFS_CAP_HARDLINKS|NFS_CAP_SYMLINKS|NFS_CAP_FILEID|
702-
NFS_CAP_MODE|NFS_CAP_NLINK|NFS_CAP_OWNER|NFS_CAP_OWNER_GROUP|
703-
NFS_CAP_ATIME|NFS_CAP_CTIME|NFS_CAP_MTIME;
699+
server->caps |= NFS_CAP_HARDLINKS | NFS_CAP_SYMLINKS;
700+
701+
switch (clp->rpc_ops->version) {
702+
case 2:
703+
server->fattr_valid = NFS_ATTR_FATTR_V2;
704+
break;
705+
case 3:
706+
server->fattr_valid = NFS_ATTR_FATTR_V3;
707+
break;
708+
default:
709+
server->fattr_valid = NFS_ATTR_FATTR_V4;
710+
}
704711

705712
if (ctx->rsize)
706713
server->rsize = nfs_block_size(ctx->rsize, NULL);
@@ -794,6 +801,7 @@ static void nfs_server_set_fsinfo(struct nfs_server *server,
794801
server->maxfilesize = fsinfo->maxfilesize;
795802

796803
server->time_delta = fsinfo->time_delta;
804+
server->change_attr_type = fsinfo->change_attr_type;
797805

798806
server->clone_blksize = fsinfo->clone_blksize;
799807
/* We're airborne Set socket buffersize */
@@ -935,6 +943,8 @@ struct nfs_server *nfs_alloc_server(void)
935943
return NULL;
936944
}
937945

946+
server->change_attr_type = NFS4_CHANGE_TYPE_IS_UNDEFINED;
947+
938948
ida_init(&server->openowner_id);
939949
ida_init(&server->lockowner_id);
940950
pnfs_init_server(server);

fs/nfs/delegation.c

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ nfs4_do_check_delegation(struct inode *inode, fmode_t flags, bool mark)
114114
return ret;
115115
}
116116
/**
117-
* nfs_have_delegation - check if inode has a delegation, mark it
117+
* nfs4_have_delegation - check if inode has a delegation, mark it
118118
* NFS_DELEGATION_REFERENCED if there is one.
119119
* @inode: inode to check
120120
* @flags: delegation types to check for
@@ -481,18 +481,29 @@ int nfs_inode_set_delegation(struct inode *inode, const struct cred *cred,
481481
if (freeme == NULL)
482482
goto out;
483483
add_new:
484+
/*
485+
* If we didn't revalidate the change attribute before setting
486+
* the delegation, then pre-emptively ask for a full attribute
487+
* cache revalidation.
488+
*/
489+
spin_lock(&inode->i_lock);
490+
if (NFS_I(inode)->cache_validity & NFS_INO_INVALID_CHANGE)
491+
nfs_set_cache_invalid(inode,
492+
NFS_INO_INVALID_ATIME | NFS_INO_INVALID_CTIME |
493+
NFS_INO_INVALID_MTIME | NFS_INO_INVALID_SIZE |
494+
NFS_INO_INVALID_BLOCKS | NFS_INO_INVALID_NLINK |
495+
NFS_INO_INVALID_OTHER | NFS_INO_INVALID_DATA |
496+
NFS_INO_INVALID_ACCESS | NFS_INO_INVALID_ACL |
497+
NFS_INO_INVALID_XATTR);
498+
spin_unlock(&inode->i_lock);
499+
484500
list_add_tail_rcu(&delegation->super_list, &server->delegations);
485501
rcu_assign_pointer(nfsi->delegation, delegation);
486502
delegation = NULL;
487503

488504
atomic_long_inc(&nfs_active_delegations);
489505

490506
trace_nfs4_set_delegation(inode, type);
491-
492-
spin_lock(&inode->i_lock);
493-
if (NFS_I(inode)->cache_validity & (NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ATIME))
494-
NFS_I(inode)->cache_validity |= NFS_INO_REVAL_FORCED;
495-
spin_unlock(&inode->i_lock);
496507
out:
497508
spin_unlock(&clp->cl_lock);
498509
if (delegation != NULL)
@@ -674,7 +685,7 @@ void nfs_inode_evict_delegation(struct inode *inode)
674685
}
675686

676687
/**
677-
* nfs_inode_return_delegation - synchronously return a delegation
688+
* nfs4_inode_return_delegation - synchronously return a delegation
678689
* @inode: inode to process
679690
*
680691
* This routine will always flush any dirty data to disk on the
@@ -697,7 +708,7 @@ int nfs4_inode_return_delegation(struct inode *inode)
697708
}
698709

699710
/**
700-
* nfs_inode_return_delegation_on_close - asynchronously return a delegation
711+
* nfs4_inode_return_delegation_on_close - asynchronously return a delegation
701712
* @inode: inode to process
702713
*
703714
* This routine is called on file close in order to determine if the
@@ -811,7 +822,7 @@ void nfs_expire_all_delegations(struct nfs_client *clp)
811822
}
812823

813824
/**
814-
* nfs_super_return_all_delegations - return delegations for one superblock
825+
* nfs_server_return_all_delegations - return delegations for one superblock
815826
* @server: pointer to nfs_server to process
816827
*
817828
*/

fs/nfs/delegation.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,8 +84,7 @@ int nfs4_inode_make_writeable(struct inode *inode);
8484

8585
static inline int nfs_have_delegated_attributes(struct inode *inode)
8686
{
87-
return NFS_PROTO(inode)->have_delegation(inode, FMODE_READ) &&
88-
!(NFS_I(inode)->cache_validity & NFS_INO_REVAL_FORCED);
87+
return NFS_PROTO(inode)->have_delegation(inode, FMODE_READ);
8988
}
9089

9190
#endif

fs/nfs/dir.c

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -866,6 +866,8 @@ static int nfs_readdir_xdr_to_array(struct nfs_readdir_descriptor *desc,
866866
break;
867867
}
868868

869+
verf_arg = verf_res;
870+
869871
status = nfs_readdir_page_filler(desc, entry, pages, pglen,
870872
arrays, narrays);
871873
} while (!status && nfs_readdir_page_needs_filling(page));
@@ -927,7 +929,12 @@ static int find_and_lock_cache_page(struct nfs_readdir_descriptor *desc)
927929
}
928930
return res;
929931
}
930-
memcpy(nfsi->cookieverf, verf, sizeof(nfsi->cookieverf));
932+
/*
933+
* Set the cookie verifier if the page cache was empty
934+
*/
935+
if (desc->page_index == 0)
936+
memcpy(nfsi->cookieverf, verf,
937+
sizeof(nfsi->cookieverf));
931938
}
932939
res = nfs_readdir_search_array(desc);
933940
if (res == 0) {
@@ -974,10 +981,10 @@ static int readdir_search_pagecache(struct nfs_readdir_descriptor *desc)
974981
/*
975982
* Once we've found the start of the dirent within a page: fill 'er up...
976983
*/
977-
static void nfs_do_filldir(struct nfs_readdir_descriptor *desc)
984+
static void nfs_do_filldir(struct nfs_readdir_descriptor *desc,
985+
const __be32 *verf)
978986
{
979987
struct file *file = desc->file;
980-
struct nfs_inode *nfsi = NFS_I(file_inode(file));
981988
struct nfs_cache_array *array;
982989
unsigned int i = 0;
983990

@@ -991,7 +998,7 @@ static void nfs_do_filldir(struct nfs_readdir_descriptor *desc)
991998
desc->eof = true;
992999
break;
9931000
}
994-
memcpy(desc->verf, nfsi->cookieverf, sizeof(desc->verf));
1001+
memcpy(desc->verf, verf, sizeof(desc->verf));
9951002
if (i < (array->size-1))
9961003
desc->dir_cookie = array->array[i+1].cookie;
9971004
else
@@ -1048,7 +1055,7 @@ static int uncached_readdir(struct nfs_readdir_descriptor *desc)
10481055

10491056
for (i = 0; !desc->eof && i < sz && arrays[i]; i++) {
10501057
desc->page = arrays[i];
1051-
nfs_do_filldir(desc);
1058+
nfs_do_filldir(desc, verf);
10521059
}
10531060
desc->page = NULL;
10541061

@@ -1069,6 +1076,7 @@ static int nfs_readdir(struct file *file, struct dir_context *ctx)
10691076
{
10701077
struct dentry *dentry = file_dentry(file);
10711078
struct inode *inode = d_inode(dentry);
1079+
struct nfs_inode *nfsi = NFS_I(inode);
10721080
struct nfs_open_dir_context *dir_ctx = file->private_data;
10731081
struct nfs_readdir_descriptor *desc;
10741082
int res;
@@ -1122,7 +1130,7 @@ static int nfs_readdir(struct file *file, struct dir_context *ctx)
11221130
break;
11231131
}
11241132
if (res == -ETOOSMALL && desc->plus) {
1125-
clear_bit(NFS_INO_ADVISE_RDPLUS, &NFS_I(inode)->flags);
1133+
clear_bit(NFS_INO_ADVISE_RDPLUS, &nfsi->flags);
11261134
nfs_zap_caches(inode);
11271135
desc->page_index = 0;
11281136
desc->plus = false;
@@ -1132,7 +1140,7 @@ static int nfs_readdir(struct file *file, struct dir_context *ctx)
11321140
if (res < 0)
11331141
break;
11341142

1135-
nfs_do_filldir(desc);
1143+
nfs_do_filldir(desc, nfsi->cookieverf);
11361144
nfs_readdir_page_unlock_and_put_cached(desc);
11371145
} while (!desc->eof);
11381146

@@ -1703,7 +1711,7 @@ static void nfs_drop_nlink(struct inode *inode)
17031711
NFS_I(inode)->attr_gencount = nfs_inc_attr_generation_counter();
17041712
nfs_set_cache_invalid(
17051713
inode, NFS_INO_INVALID_CHANGE | NFS_INO_INVALID_CTIME |
1706-
NFS_INO_INVALID_OTHER | NFS_INO_REVAL_FORCED);
1714+
NFS_INO_INVALID_NLINK);
17071715
spin_unlock(&inode->i_lock);
17081716
}
17091717

@@ -2940,7 +2948,7 @@ static int nfs_execute_ok(struct inode *inode, int mask)
29402948

29412949
if (S_ISDIR(inode->i_mode))
29422950
return 0;
2943-
if (nfs_check_cache_invalid(inode, NFS_INO_INVALID_OTHER)) {
2951+
if (nfs_check_cache_invalid(inode, NFS_INO_INVALID_MODE)) {
29442952
if (mask & MAY_NOT_BLOCK)
29452953
return -ECHILD;
29462954
ret = __nfs_revalidate_inode(server, inode);
@@ -2998,7 +3006,8 @@ int nfs_permission(struct user_namespace *mnt_userns,
29983006
if (mask & MAY_NOT_BLOCK)
29993007
return -ECHILD;
30003008

3001-
res = nfs_revalidate_inode(NFS_SERVER(inode), inode);
3009+
res = nfs_revalidate_inode(inode, NFS_INO_INVALID_MODE |
3010+
NFS_INO_INVALID_OTHER);
30023011
if (res == 0)
30033012
res = generic_permission(&init_user_ns, inode, mask);
30043013
goto out;

fs/nfs/export.c

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -169,19 +169,8 @@ nfs_get_parent(struct dentry *dentry)
169169

170170
static u64 nfs_fetch_iversion(struct inode *inode)
171171
{
172-
struct nfs_server *server = NFS_SERVER(inode);
173-
174-
/* Is this the right call?: */
175-
nfs_revalidate_inode(server, inode);
176-
/*
177-
* Also, note we're ignoring any returned error. That seems to be
178-
* the practice for cache consistency information elsewhere in
179-
* the server, but I'm not sure why.
180-
*/
181-
if (server->nfs_client->rpc_ops->version >= 4)
182-
return inode_peek_iversion_raw(inode);
183-
else
184-
return time_to_chattr(&inode->i_ctime);
172+
nfs_revalidate_inode(inode, NFS_INO_INVALID_CHANGE);
173+
return inode_peek_iversion_raw(inode);
185174
}
186175

187176
const struct export_operations nfs_export_ops = {

fs/nfs/file.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ static int nfs_revalidate_file_size(struct inode *inode, struct file *filp)
105105

106106
if (filp->f_flags & O_DIRECT)
107107
goto force_reval;
108-
if (nfs_check_cache_invalid(inode, NFS_INO_REVAL_PAGECACHE))
108+
if (nfs_check_cache_invalid(inode, NFS_INO_INVALID_SIZE))
109109
goto force_reval;
110110
return 0;
111111
force_reval:

fs/nfs/flexfilelayout/flexfilelayout.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ static int decode_nfs_fh(struct xdr_stream *xdr, struct nfs_fh *fh)
106106
if (unlikely(!p))
107107
return -ENOBUFS;
108108
fh->size = be32_to_cpup(p++);
109-
if (fh->size > sizeof(struct nfs_fh)) {
109+
if (fh->size > NFS_MAXFHSIZE) {
110110
printk(KERN_ERR "NFS flexfiles: Too big fh received %d\n",
111111
fh->size);
112112
return -EOVERFLOW;

0 commit comments

Comments
 (0)