More NFS Client Bugfixes for Linux 5.10
- Bugfixes: - Fix array overflow when flexfiles mirroring is enabled - Fix rpcrdma_inline_fixup() crash with new LISTXATTRS - Fix 5 second delay when doing inter-server copy - Disable READ_PLUS by default -----BEGIN PGP SIGNATURE----- iQIzBAABCAAdFiEEnZ5MQTpR7cLU7KEp18tUv7ClQOsFAl/Sl70ACgkQ18tUv7Cl QOuGdw/9GMmrLF26brO3q3lSTD9xdljJGQi0q1DEF2amNUL9cPgxB0xZB9lyUPqs AbpLxsCgfJ+rN3sbOnDdz8Ae/wiWS1PkeJWw4cu0/kIIjyPD2Uu4jWuIwxpFvP1v lFfBHeEdsNgqS5t9t9cF9u30PjPKt9SHG/64/8GY92zlrKDRUaJUyvW1zUKo4ne4 m3JxZ1rCxNkBYV+odrQIYE9gqFI6OBWpVsUeIXjBWWDZ/+zK9rGiO5fxZ8oe+yT2 cmrR/vOznoPgUGaH380HrCbXcIKwim2mn76t1MH9fScZQc1ocSWckrZRRdOVWlJ+ 228ImDPACLFaTqpgi8ZhFmuD3Mwbz4AtPLce52lvZLuMAPVMoFhR8xrm/VpJFSim pNjwsl/j9qlGSAe5XdGW+X/DzmHPVd6uhfzOFAd7ZErt7rU0gjyJTWzrmayoB3N1 GF5g4LaK1dYYj7SG8d8DrEV2CGyYle2UP4aDm8qJ/ZLQhd10RHeVt4BHfSKwY05l 03Gim7wlH/ercYfgU6wrgmEG2SWjuFJr+j1v//aqcmJVhA7FvTKygGpGyNK16pNL 9dZ81wUHKHzVt5C/ruG+3tARvnobvmB4ngQAQmtu0aXe9c+Kr2XlaXUAusHPK+Me pVqtmaKBgddUtJwFms8JF6dePiSBRQgpwyvluqNi1D7ntRhS+Ik= =EXrS -----END PGP SIGNATURE----- Merge tag 'nfs-for-5.10-3' of git://git.linux-nfs.org/projects/anna/linux-nfs Pull NFS client fixes from Anna Schumaker: "Here are a handful more bugfixes for 5.10. Unfortunately, we found some problems with the new READ_PLUS operation that aren't easy to fix. We've decided to disable this codepath through a Kconfig option for now, but a series of patches going into 5.11 will clean up the code and fix the issues at the same time. This seemed like the best way to go about it. Summary: - Fix array overflow when flexfiles mirroring is enabled - Fix rpcrdma_inline_fixup() crash with new LISTXATTRS - Fix 5 second delay when doing inter-server copy - Disable READ_PLUS by default" * tag 'nfs-for-5.10-3' of git://git.linux-nfs.org/projects/anna/linux-nfs: NFS: Disable READ_PLUS by default NFSv4.2: Fix 5 seconds delay when doing inter server copy NFS: Fix rpcrdma_inline_fixup() crash with new LISTXATTRS operation pNFS/flexfiles: Fix array overflow when flexfiles mirroring is enabled
This commit is contained in:
commit
6840a3dcc2
|
@ -205,3 +205,12 @@ config NFS_DISABLE_UDP_SUPPORT
|
|||
Choose Y here to disable the use of NFS over UDP. NFS over UDP
|
||||
on modern networks (1Gb+) can lead to data corruption caused by
|
||||
fragmentation during high loads.
|
||||
|
||||
config NFS_V4_2_READ_PLUS
|
||||
bool "NFS: Enable support for the NFSv4.2 READ_PLUS operation"
|
||||
depends on NFS_V4_2
|
||||
default n
|
||||
help
|
||||
This is intended for developers only. The READ_PLUS operation has
|
||||
been shown to have issues under specific conditions and should not
|
||||
be used in production.
|
||||
|
|
|
@ -838,7 +838,7 @@ ff_layout_pg_init_read(struct nfs_pageio_descriptor *pgio,
|
|||
struct nfs_pgio_mirror *pgm;
|
||||
struct nfs4_ff_layout_mirror *mirror;
|
||||
struct nfs4_pnfs_ds *ds;
|
||||
u32 ds_idx, i;
|
||||
u32 ds_idx;
|
||||
|
||||
retry:
|
||||
ff_layout_pg_check_layout(pgio, req);
|
||||
|
@ -864,11 +864,9 @@ retry:
|
|||
goto retry;
|
||||
}
|
||||
|
||||
for (i = 0; i < pgio->pg_mirror_count; i++) {
|
||||
mirror = FF_LAYOUT_COMP(pgio->pg_lseg, i);
|
||||
pgm = &pgio->pg_mirrors[i];
|
||||
pgm->pg_bsize = mirror->mirror_ds->ds_versions[0].rsize;
|
||||
}
|
||||
mirror = FF_LAYOUT_COMP(pgio->pg_lseg, ds_idx);
|
||||
pgm = &pgio->pg_mirrors[0];
|
||||
pgm->pg_bsize = mirror->mirror_ds->ds_versions[0].rsize;
|
||||
|
||||
pgio->pg_mirror_idx = ds_idx;
|
||||
|
||||
|
@ -985,6 +983,21 @@ out:
|
|||
return 1;
|
||||
}
|
||||
|
||||
static u32
|
||||
ff_layout_pg_set_mirror_write(struct nfs_pageio_descriptor *desc, u32 idx)
|
||||
{
|
||||
u32 old = desc->pg_mirror_idx;
|
||||
|
||||
desc->pg_mirror_idx = idx;
|
||||
return old;
|
||||
}
|
||||
|
||||
static struct nfs_pgio_mirror *
|
||||
ff_layout_pg_get_mirror_write(struct nfs_pageio_descriptor *desc, u32 idx)
|
||||
{
|
||||
return &desc->pg_mirrors[idx];
|
||||
}
|
||||
|
||||
static const struct nfs_pageio_ops ff_layout_pg_read_ops = {
|
||||
.pg_init = ff_layout_pg_init_read,
|
||||
.pg_test = pnfs_generic_pg_test,
|
||||
|
@ -998,6 +1011,8 @@ static const struct nfs_pageio_ops ff_layout_pg_write_ops = {
|
|||
.pg_doio = pnfs_generic_pg_writepages,
|
||||
.pg_get_mirror_count = ff_layout_pg_get_mirror_count_write,
|
||||
.pg_cleanup = pnfs_generic_pg_cleanup,
|
||||
.pg_get_mirror = ff_layout_pg_get_mirror_write,
|
||||
.pg_set_mirror = ff_layout_pg_set_mirror_write,
|
||||
};
|
||||
|
||||
static void ff_layout_reset_write(struct nfs_pgio_header *hdr, bool retry_pnfs)
|
||||
|
|
|
@ -1241,12 +1241,13 @@ static ssize_t _nfs42_proc_listxattrs(struct inode *inode, void *buf,
|
|||
.rpc_resp = &res,
|
||||
};
|
||||
u32 xdrlen;
|
||||
int ret, np;
|
||||
int ret, np, i;
|
||||
|
||||
|
||||
ret = -ENOMEM;
|
||||
res.scratch = alloc_page(GFP_KERNEL);
|
||||
if (!res.scratch)
|
||||
return -ENOMEM;
|
||||
goto out;
|
||||
|
||||
xdrlen = nfs42_listxattr_xdrsize(buflen);
|
||||
if (xdrlen > server->lxasize)
|
||||
|
@ -1254,9 +1255,12 @@ static ssize_t _nfs42_proc_listxattrs(struct inode *inode, void *buf,
|
|||
np = xdrlen / PAGE_SIZE + 1;
|
||||
|
||||
pages = kcalloc(np, sizeof(struct page *), GFP_KERNEL);
|
||||
if (pages == NULL) {
|
||||
__free_page(res.scratch);
|
||||
return -ENOMEM;
|
||||
if (!pages)
|
||||
goto out_free_scratch;
|
||||
for (i = 0; i < np; i++) {
|
||||
pages[i] = alloc_page(GFP_KERNEL);
|
||||
if (!pages[i])
|
||||
goto out_free_pages;
|
||||
}
|
||||
|
||||
arg.xattr_pages = pages;
|
||||
|
@ -1271,14 +1275,15 @@ static ssize_t _nfs42_proc_listxattrs(struct inode *inode, void *buf,
|
|||
*eofp = res.eof;
|
||||
}
|
||||
|
||||
out_free_pages:
|
||||
while (--np >= 0) {
|
||||
if (pages[np])
|
||||
__free_page(pages[np]);
|
||||
}
|
||||
|
||||
__free_page(res.scratch);
|
||||
kfree(pages);
|
||||
|
||||
out_free_scratch:
|
||||
__free_page(res.scratch);
|
||||
out:
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
|
|
@ -1528,7 +1528,6 @@ static void nfs4_xdr_enc_listxattrs(struct rpc_rqst *req,
|
|||
|
||||
rpc_prepare_reply_pages(req, args->xattr_pages, 0, args->count,
|
||||
hdr.replen);
|
||||
req->rq_rcv_buf.flags |= XDRBUF_SPARSE_PAGES;
|
||||
|
||||
encode_nops(&hdr);
|
||||
}
|
||||
|
|
|
@ -377,10 +377,10 @@ static struct file *__nfs42_ssc_open(struct vfsmount *ss_mnt,
|
|||
goto out_stateowner;
|
||||
|
||||
set_bit(NFS_SRV_SSC_COPY_STATE, &ctx->state->flags);
|
||||
set_bit(NFS_OPEN_STATE, &ctx->state->flags);
|
||||
memcpy(&ctx->state->open_stateid.other, &stateid->other,
|
||||
NFS4_STATEID_OTHER_SIZE);
|
||||
update_open_stateid(ctx->state, stateid, NULL, filep->f_mode);
|
||||
set_bit(NFS_OPEN_STATE, &ctx->state->flags);
|
||||
|
||||
nfs_file_set_open_context(filep, ctx);
|
||||
put_nfs_open_context(ctx);
|
||||
|
|
|
@ -5309,7 +5309,7 @@ static int nfs4_read_done(struct rpc_task *task, struct nfs_pgio_header *hdr)
|
|||
nfs4_read_done_cb(task, hdr);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_NFS_V4_2
|
||||
#if defined CONFIG_NFS_V4_2 && defined CONFIG_NFS_V4_2_READ_PLUS
|
||||
static void nfs42_read_plus_support(struct nfs_server *server, struct rpc_message *msg)
|
||||
{
|
||||
if (server->caps & NFS_CAP_READ_PLUS)
|
||||
|
|
|
@ -31,13 +31,29 @@
|
|||
static struct kmem_cache *nfs_page_cachep;
|
||||
static const struct rpc_call_ops nfs_pgio_common_ops;
|
||||
|
||||
static struct nfs_pgio_mirror *
|
||||
nfs_pgio_get_mirror(struct nfs_pageio_descriptor *desc, u32 idx)
|
||||
{
|
||||
if (desc->pg_ops->pg_get_mirror)
|
||||
return desc->pg_ops->pg_get_mirror(desc, idx);
|
||||
return &desc->pg_mirrors[0];
|
||||
}
|
||||
|
||||
struct nfs_pgio_mirror *
|
||||
nfs_pgio_current_mirror(struct nfs_pageio_descriptor *desc)
|
||||
{
|
||||
return &desc->pg_mirrors[desc->pg_mirror_idx];
|
||||
return nfs_pgio_get_mirror(desc, desc->pg_mirror_idx);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(nfs_pgio_current_mirror);
|
||||
|
||||
static u32
|
||||
nfs_pgio_set_current_mirror(struct nfs_pageio_descriptor *desc, u32 idx)
|
||||
{
|
||||
if (desc->pg_ops->pg_set_mirror)
|
||||
return desc->pg_ops->pg_set_mirror(desc, idx);
|
||||
return desc->pg_mirror_idx;
|
||||
}
|
||||
|
||||
void nfs_pgheader_init(struct nfs_pageio_descriptor *desc,
|
||||
struct nfs_pgio_header *hdr,
|
||||
void (*release)(struct nfs_pgio_header *hdr))
|
||||
|
@ -1259,7 +1275,7 @@ static void nfs_pageio_error_cleanup(struct nfs_pageio_descriptor *desc)
|
|||
return;
|
||||
|
||||
for (midx = 0; midx < desc->pg_mirror_count; midx++) {
|
||||
mirror = &desc->pg_mirrors[midx];
|
||||
mirror = nfs_pgio_get_mirror(desc, midx);
|
||||
desc->pg_completion_ops->error_cleanup(&mirror->pg_list,
|
||||
desc->pg_error);
|
||||
}
|
||||
|
@ -1293,12 +1309,12 @@ int nfs_pageio_add_request(struct nfs_pageio_descriptor *desc,
|
|||
goto out_failed;
|
||||
}
|
||||
|
||||
desc->pg_mirror_idx = midx;
|
||||
nfs_pgio_set_current_mirror(desc, midx);
|
||||
if (!nfs_pageio_add_request_mirror(desc, dupreq))
|
||||
goto out_cleanup_subreq;
|
||||
}
|
||||
|
||||
desc->pg_mirror_idx = 0;
|
||||
nfs_pgio_set_current_mirror(desc, 0);
|
||||
if (!nfs_pageio_add_request_mirror(desc, req))
|
||||
goto out_failed;
|
||||
|
||||
|
@ -1320,10 +1336,12 @@ out_failed:
|
|||
static void nfs_pageio_complete_mirror(struct nfs_pageio_descriptor *desc,
|
||||
u32 mirror_idx)
|
||||
{
|
||||
struct nfs_pgio_mirror *mirror = &desc->pg_mirrors[mirror_idx];
|
||||
u32 restore_idx = desc->pg_mirror_idx;
|
||||
struct nfs_pgio_mirror *mirror;
|
||||
u32 restore_idx;
|
||||
|
||||
restore_idx = nfs_pgio_set_current_mirror(desc, mirror_idx);
|
||||
mirror = nfs_pgio_current_mirror(desc);
|
||||
|
||||
desc->pg_mirror_idx = mirror_idx;
|
||||
for (;;) {
|
||||
nfs_pageio_doio(desc);
|
||||
if (desc->pg_error < 0 || !mirror->pg_recoalesce)
|
||||
|
@ -1331,7 +1349,7 @@ static void nfs_pageio_complete_mirror(struct nfs_pageio_descriptor *desc,
|
|||
if (!nfs_do_recoalesce(desc))
|
||||
break;
|
||||
}
|
||||
desc->pg_mirror_idx = restore_idx;
|
||||
nfs_pgio_set_current_mirror(desc, restore_idx);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1405,7 +1423,7 @@ void nfs_pageio_cond_complete(struct nfs_pageio_descriptor *desc, pgoff_t index)
|
|||
u32 midx;
|
||||
|
||||
for (midx = 0; midx < desc->pg_mirror_count; midx++) {
|
||||
mirror = &desc->pg_mirrors[midx];
|
||||
mirror = nfs_pgio_get_mirror(desc, midx);
|
||||
if (!list_empty(&mirror->pg_list)) {
|
||||
prev = nfs_list_entry(mirror->pg_list.prev);
|
||||
if (index != prev->wb_index + 1) {
|
||||
|
|
|
@ -55,6 +55,7 @@ struct nfs_page {
|
|||
unsigned short wb_nio; /* Number of I/O attempts */
|
||||
};
|
||||
|
||||
struct nfs_pgio_mirror;
|
||||
struct nfs_pageio_descriptor;
|
||||
struct nfs_pageio_ops {
|
||||
void (*pg_init)(struct nfs_pageio_descriptor *, struct nfs_page *);
|
||||
|
@ -64,6 +65,9 @@ struct nfs_pageio_ops {
|
|||
unsigned int (*pg_get_mirror_count)(struct nfs_pageio_descriptor *,
|
||||
struct nfs_page *);
|
||||
void (*pg_cleanup)(struct nfs_pageio_descriptor *);
|
||||
struct nfs_pgio_mirror *
|
||||
(*pg_get_mirror)(struct nfs_pageio_descriptor *, u32);
|
||||
u32 (*pg_set_mirror)(struct nfs_pageio_descriptor *, u32);
|
||||
};
|
||||
|
||||
struct nfs_rw_ops {
|
||||
|
|
Loading…
Reference in New Issue