Skip to content

Commit 6860c98

Browse files
committed
Merge tag 'nfs-for-5.3-1' of git://git.linux-nfs.org/projects/trondmy/linux-nfs
Pull NFS client updates from Trond Myklebust: "Highlights include: Stable fixes: - SUNRPC: Ensure bvecs are re-synced when we re-encode the RPC request - Fix an Oops in ff_layout_track_ds_error due to a PTR_ERR() dereference - Revert buggy NFS readdirplus optimisation - NFSv4: Handle the special Linux file open access mode - pnfs: Fix a problem where we gratuitously start doing I/O through the MDS Features: - Allow NFS client to set up multiple TCP connections to the server using a new 'nconnect=X' mount option. Queue length is used to balance load. - Enhance statistics reporting to report on all transports when using multiple connections. - Speed up SUNRPC by removing bh-safe spinlocks - Add a mechanism to allow NFSv4 to request that containers set a unique per-host identifier for when the hostname is not set. - Ensure NFSv4 updates the lease_time after a clientid update Bugfixes and cleanup: - Fix use-after-free in rpcrdma_post_recvs - Fix a memory leak when nfs_match_client() is interrupted - Fix buggy file access checking in NFSv4 open for execute - disable unsupported client side deduplication - Fix spurious client disconnections - Fix occasional RDMA transport deadlock - Various RDMA cleanups - Various tracepoint fixes - Fix the TCP callback channel to guarantee the server can actually send the number of callback requests that was negotiated at mount time" * tag 'nfs-for-5.3-1' of git://git.linux-nfs.org/projects/trondmy/linux-nfs: (68 commits) pnfs/flexfiles: Add tracepoints for detecting pnfs fallback to MDS pnfs: Fix a problem where we gratuitously start doing I/O through the MDS SUNRPC: Optimise transport balancing code SUNRPC: Ensure the bvecs are reset when we re-encode the RPC request pnfs/flexfiles: Fix PTR_ERR() dereferences in ff_layout_track_ds_error NFSv4: Don't use the zero stateid with layoutget SUNRPC: Fix up backchannel slot table accounting SUNRPC: Fix initialisation of struct rpc_xprt_switch SUNRPC: Skip zero-refcount transports SUNRPC: Replace division by multiplication in calculation of queue length NFSv4: Validate the stateid before applying it to state recovery nfs4.0: Refetch lease_time after clientid update nfs4: Rename nfs41_setup_state_renewal nfs4: Make nfs4_proc_get_lease_time available for nfs4.0 nfs: Fix copy-and-paste error in debug message NFS: Replace 16 seq_printf() calls by seq_puts() NFS: Use seq_putc() in nfs_show_stats() Revert "NFS: readdirplus optimization by cache mechanism" (memleak) SUNRPC: Fix transport accounting when caller specifies an rpc_xprt NFS: Record task, client ID, and XID in xdr_status trace points ...
2 parents 0570bc8 + d5b9216 commit 6860c98

Some content is hidden

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

56 files changed

+1831
-870
lines changed

fs/nfs/Makefile

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@ obj-$(CONFIG_NFS_FS) += nfs.o
88
CFLAGS_nfstrace.o += -I$(src)
99
nfs-y := client.o dir.o file.o getroot.o inode.o super.o \
1010
io.o direct.o pagelist.o read.o symlink.o unlink.o \
11-
write.o namespace.o mount_clnt.o nfstrace.o export.o
11+
write.o namespace.o mount_clnt.o nfstrace.o \
12+
export.o sysfs.o
1213
nfs-$(CONFIG_ROOT_NFS) += nfsroot.o
1314
nfs-$(CONFIG_SYSCTL) += sysctl.o
1415
nfs-$(CONFIG_NFS_FSCACHE) += fscache.o fscache-index.o

fs/nfs/callback_proc.c

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -414,27 +414,39 @@ static __be32
414414
validate_seqid(const struct nfs4_slot_table *tbl, const struct nfs4_slot *slot,
415415
const struct cb_sequenceargs * args)
416416
{
417+
__be32 ret;
418+
419+
ret = cpu_to_be32(NFS4ERR_BADSLOT);
417420
if (args->csa_slotid > tbl->server_highest_slotid)
418-
return htonl(NFS4ERR_BADSLOT);
421+
goto out_err;
419422

420423
/* Replay */
421424
if (args->csa_sequenceid == slot->seq_nr) {
425+
ret = cpu_to_be32(NFS4ERR_DELAY);
422426
if (nfs4_test_locked_slot(tbl, slot->slot_nr))
423-
return htonl(NFS4ERR_DELAY);
427+
goto out_err;
428+
424429
/* Signal process_op to set this error on next op */
430+
ret = cpu_to_be32(NFS4ERR_RETRY_UNCACHED_REP);
425431
if (args->csa_cachethis == 0)
426-
return htonl(NFS4ERR_RETRY_UNCACHED_REP);
432+
goto out_err;
427433

428434
/* Liar! We never allowed you to set csa_cachethis != 0 */
429-
return htonl(NFS4ERR_SEQ_FALSE_RETRY);
435+
ret = cpu_to_be32(NFS4ERR_SEQ_FALSE_RETRY);
436+
goto out_err;
430437
}
431438

432439
/* Note: wraparound relies on seq_nr being of type u32 */
433-
if (likely(args->csa_sequenceid == slot->seq_nr + 1))
434-
return htonl(NFS4_OK);
435-
436440
/* Misordered request */
437-
return htonl(NFS4ERR_SEQ_MISORDERED);
441+
ret = cpu_to_be32(NFS4ERR_SEQ_MISORDERED);
442+
if (args->csa_sequenceid != slot->seq_nr + 1)
443+
goto out_err;
444+
445+
return cpu_to_be32(NFS4_OK);
446+
447+
out_err:
448+
trace_nfs4_cb_seqid_err(args, ret);
449+
return ret;
438450
}
439451

440452
/*

fs/nfs/client.c

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@
4949
#include "pnfs.h"
5050
#include "nfs.h"
5151
#include "netns.h"
52+
#include "sysfs.h"
5253

5354
#define NFSDBG_FACILITY NFSDBG_CLIENT
5455

@@ -175,6 +176,7 @@ struct nfs_client *nfs_alloc_client(const struct nfs_client_initdata *cl_init)
175176
clp->cl_rpcclient = ERR_PTR(-EINVAL);
176177

177178
clp->cl_proto = cl_init->proto;
179+
clp->cl_nconnect = cl_init->nconnect;
178180
clp->cl_net = get_net(cl_init->net);
179181

180182
clp->cl_principal = "*";
@@ -192,7 +194,7 @@ struct nfs_client *nfs_alloc_client(const struct nfs_client_initdata *cl_init)
192194
EXPORT_SYMBOL_GPL(nfs_alloc_client);
193195

194196
#if IS_ENABLED(CONFIG_NFS_V4)
195-
void nfs_cleanup_cb_ident_idr(struct net *net)
197+
static void nfs_cleanup_cb_ident_idr(struct net *net)
196198
{
197199
struct nfs_net *nn = net_generic(net, nfs_net_id);
198200

@@ -214,7 +216,7 @@ static void pnfs_init_server(struct nfs_server *server)
214216
}
215217

216218
#else
217-
void nfs_cleanup_cb_ident_idr(struct net *net)
219+
static void nfs_cleanup_cb_ident_idr(struct net *net)
218220
{
219221
}
220222

@@ -406,10 +408,10 @@ struct nfs_client *nfs_get_client(const struct nfs_client_initdata *cl_init)
406408
clp = nfs_match_client(cl_init);
407409
if (clp) {
408410
spin_unlock(&nn->nfs_client_lock);
409-
if (IS_ERR(clp))
410-
return clp;
411411
if (new)
412412
new->rpc_ops->free_client(new);
413+
if (IS_ERR(clp))
414+
return clp;
413415
return nfs_found_client(cl_init, clp);
414416
}
415417
if (new) {
@@ -493,6 +495,7 @@ int nfs_create_rpc_client(struct nfs_client *clp,
493495
struct rpc_create_args args = {
494496
.net = clp->cl_net,
495497
.protocol = clp->cl_proto,
498+
.nconnect = clp->cl_nconnect,
496499
.address = (struct sockaddr *)&clp->cl_addr,
497500
.addrsize = clp->cl_addrlen,
498501
.timeout = cl_init->timeparms,
@@ -658,6 +661,7 @@ static int nfs_init_server(struct nfs_server *server,
658661
.net = data->net,
659662
.timeparms = &timeparms,
660663
.cred = server->cred,
664+
.nconnect = data->nfs_server.nconnect,
661665
};
662666
struct nfs_client *clp;
663667
int error;
@@ -1072,6 +1076,18 @@ void nfs_clients_init(struct net *net)
10721076
#endif
10731077
spin_lock_init(&nn->nfs_client_lock);
10741078
nn->boot_time = ktime_get_real();
1079+
1080+
nfs_netns_sysfs_setup(nn, net);
1081+
}
1082+
1083+
void nfs_clients_exit(struct net *net)
1084+
{
1085+
struct nfs_net *nn = net_generic(net, nfs_net_id);
1086+
1087+
nfs_netns_sysfs_destroy(nn);
1088+
nfs_cleanup_cb_ident_idr(net);
1089+
WARN_ON_ONCE(!list_empty(&nn->nfs_client_list));
1090+
WARN_ON_ONCE(!list_empty(&nn->nfs_volume_list));
10751091
}
10761092

10771093
#ifdef CONFIG_PROC_FS

fs/nfs/dir.c

Lines changed: 10 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,10 @@ static struct nfs_open_dir_context *alloc_nfs_open_dir_context(struct inode *dir
8080
ctx->dup_cookie = 0;
8181
ctx->cred = get_cred(cred);
8282
spin_lock(&dir->i_lock);
83+
if (list_empty(&nfsi->open_files) &&
84+
(nfsi->cache_validity & NFS_INO_DATA_INVAL_DEFER))
85+
nfsi->cache_validity |= NFS_INO_INVALID_DATA |
86+
NFS_INO_REVAL_FORCED;
8387
list_add(&ctx->list, &nfsi->open_files);
8488
spin_unlock(&dir->i_lock);
8589
return ctx;
@@ -140,19 +144,12 @@ struct nfs_cache_array {
140144
struct nfs_cache_array_entry array[0];
141145
};
142146

143-
struct readdirvec {
144-
unsigned long nr;
145-
unsigned long index;
146-
struct page *pages[NFS_MAX_READDIR_RAPAGES];
147-
};
148-
149147
typedef int (*decode_dirent_t)(struct xdr_stream *, struct nfs_entry *, bool);
150148
typedef struct {
151149
struct file *file;
152150
struct page *page;
153151
struct dir_context *ctx;
154152
unsigned long page_index;
155-
struct readdirvec pvec;
156153
u64 *dir_cookie;
157154
u64 last_cookie;
158155
loff_t current_index;
@@ -532,10 +529,6 @@ int nfs_readdir_page_filler(nfs_readdir_descriptor_t *desc, struct nfs_entry *en
532529
struct nfs_cache_array *array;
533530
unsigned int count = 0;
534531
int status;
535-
int max_rapages = NFS_MAX_READDIR_RAPAGES;
536-
537-
desc->pvec.index = desc->page_index;
538-
desc->pvec.nr = 0;
539532

540533
scratch = alloc_page(GFP_KERNEL);
541534
if (scratch == NULL)
@@ -560,40 +553,20 @@ int nfs_readdir_page_filler(nfs_readdir_descriptor_t *desc, struct nfs_entry *en
560553
if (desc->plus)
561554
nfs_prime_dcache(file_dentry(desc->file), entry);
562555

563-
status = nfs_readdir_add_to_array(entry, desc->pvec.pages[desc->pvec.nr]);
564-
if (status == -ENOSPC) {
565-
desc->pvec.nr++;
566-
if (desc->pvec.nr == max_rapages)
567-
break;
568-
status = nfs_readdir_add_to_array(entry, desc->pvec.pages[desc->pvec.nr]);
569-
}
556+
status = nfs_readdir_add_to_array(entry, page);
570557
if (status != 0)
571558
break;
572559
} while (!entry->eof);
573560

574-
/*
575-
* page and desc->pvec.pages[0] are valid, don't need to check
576-
* whether or not to be NULL.
577-
*/
578-
copy_highpage(page, desc->pvec.pages[0]);
579-
580561
out_nopages:
581562
if (count == 0 || (status == -EBADCOOKIE && entry->eof != 0)) {
582-
array = kmap_atomic(desc->pvec.pages[desc->pvec.nr]);
563+
array = kmap(page);
583564
array->eof_index = array->size;
584565
status = 0;
585-
kunmap_atomic(array);
566+
kunmap(page);
586567
}
587568

588569
put_page(scratch);
589-
590-
/*
591-
* desc->pvec.nr > 0 means at least one page was completely filled,
592-
* we should return -ENOSPC. Otherwise function
593-
* nfs_readdir_xdr_to_array will enter infinite loop.
594-
*/
595-
if (desc->pvec.nr > 0)
596-
return -ENOSPC;
597570
return status;
598571
}
599572

@@ -627,24 +600,6 @@ int nfs_readdir_alloc_pages(struct page **pages, unsigned int npages)
627600
return -ENOMEM;
628601
}
629602

630-
/*
631-
* nfs_readdir_rapages_init initialize rapages by nfs_cache_array structure.
632-
*/
633-
static
634-
void nfs_readdir_rapages_init(nfs_readdir_descriptor_t *desc)
635-
{
636-
struct nfs_cache_array *array;
637-
int max_rapages = NFS_MAX_READDIR_RAPAGES;
638-
int index;
639-
640-
for (index = 0; index < max_rapages; index++) {
641-
array = kmap_atomic(desc->pvec.pages[index]);
642-
memset(array, 0, sizeof(struct nfs_cache_array));
643-
array->eof_index = -1;
644-
kunmap_atomic(array);
645-
}
646-
}
647-
648603
static
649604
int nfs_readdir_xdr_to_array(nfs_readdir_descriptor_t *desc, struct page *page, struct inode *inode)
650605
{
@@ -655,12 +610,6 @@ int nfs_readdir_xdr_to_array(nfs_readdir_descriptor_t *desc, struct page *page,
655610
int status = -ENOMEM;
656611
unsigned int array_size = ARRAY_SIZE(pages);
657612

658-
/*
659-
* This means we hit readdir rdpages miss, the preallocated rdpages
660-
* are useless, the preallocate rdpages should be reinitialized.
661-
*/
662-
nfs_readdir_rapages_init(desc);
663-
664613
entry.prev_cookie = 0;
665614
entry.cookie = desc->last_cookie;
666615
entry.eof = 0;
@@ -721,24 +670,9 @@ int nfs_readdir_filler(void *data, struct page* page)
721670
struct inode *inode = file_inode(desc->file);
722671
int ret;
723672

724-
/*
725-
* If desc->page_index in range desc->pvec.index and
726-
* desc->pvec.index + desc->pvec.nr, we get readdir cache hit.
727-
*/
728-
if (desc->page_index >= desc->pvec.index &&
729-
desc->page_index < (desc->pvec.index + desc->pvec.nr)) {
730-
/*
731-
* page and desc->pvec.pages[x] are valid, don't need to check
732-
* whether or not to be NULL.
733-
*/
734-
copy_highpage(page, desc->pvec.pages[desc->page_index - desc->pvec.index]);
735-
ret = 0;
736-
} else {
737-
ret = nfs_readdir_xdr_to_array(desc, page, inode);
738-
if (ret < 0)
739-
goto error;
740-
}
741-
673+
ret = nfs_readdir_xdr_to_array(desc, page, inode);
674+
if (ret < 0)
675+
goto error;
742676
SetPageUptodate(page);
743677

744678
if (invalidate_inode_pages2_range(inode->i_mapping, page->index + 1, -1) < 0) {
@@ -903,7 +837,6 @@ static int nfs_readdir(struct file *file, struct dir_context *ctx)
903837
*desc = &my_desc;
904838
struct nfs_open_dir_context *dir_ctx = file->private_data;
905839
int res = 0;
906-
int max_rapages = NFS_MAX_READDIR_RAPAGES;
907840

908841
dfprintk(FILE, "NFS: readdir(%pD2) starting at cookie %llu\n",
909842
file, (long long)ctx->pos);
@@ -923,12 +856,6 @@ static int nfs_readdir(struct file *file, struct dir_context *ctx)
923856
desc->decode = NFS_PROTO(inode)->decode_dirent;
924857
desc->plus = nfs_use_readdirplus(inode, ctx);
925858

926-
res = nfs_readdir_alloc_pages(desc->pvec.pages, max_rapages);
927-
if (res < 0)
928-
return -ENOMEM;
929-
930-
nfs_readdir_rapages_init(desc);
931-
932859
if (ctx->pos == 0 || nfs_attribute_cache_expired(inode))
933860
res = nfs_revalidate_mapping(inode, file->f_mapping);
934861
if (res < 0)
@@ -964,7 +891,6 @@ static int nfs_readdir(struct file *file, struct dir_context *ctx)
964891
break;
965892
} while (!desc->eof);
966893
out:
967-
nfs_readdir_free_pages(desc->pvec.pages, max_rapages);
968894
if (res > 0)
969895
res = 0;
970896
dfprintk(FILE, "NFS: readdir(%pD2) returns %d\n", file, res);

fs/nfs/flexfilelayout/flexfilelayout.c

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -934,6 +934,10 @@ ff_layout_pg_init_read(struct nfs_pageio_descriptor *pgio,
934934
if (pgio->pg_error < 0)
935935
return;
936936
out_mds:
937+
trace_pnfs_mds_fallback_pg_init_read(pgio->pg_inode,
938+
0, NFS4_MAX_UINT64, IOMODE_READ,
939+
NFS_I(pgio->pg_inode)->layout,
940+
pgio->pg_lseg);
937941
pnfs_put_lseg(pgio->pg_lseg);
938942
pgio->pg_lseg = NULL;
939943
nfs_pageio_reset_read_mds(pgio);
@@ -1000,6 +1004,10 @@ ff_layout_pg_init_write(struct nfs_pageio_descriptor *pgio,
10001004
return;
10011005

10021006
out_mds:
1007+
trace_pnfs_mds_fallback_pg_init_write(pgio->pg_inode,
1008+
0, NFS4_MAX_UINT64, IOMODE_RW,
1009+
NFS_I(pgio->pg_inode)->layout,
1010+
pgio->pg_lseg);
10031011
pnfs_put_lseg(pgio->pg_lseg);
10041012
pgio->pg_lseg = NULL;
10051013
nfs_pageio_reset_write_mds(pgio);
@@ -1026,6 +1034,10 @@ ff_layout_pg_get_mirror_count_write(struct nfs_pageio_descriptor *pgio,
10261034
if (pgio->pg_lseg)
10271035
return FF_LAYOUT_MIRROR_COUNT(pgio->pg_lseg);
10281036

1037+
trace_pnfs_mds_fallback_pg_get_mirror_count(pgio->pg_inode,
1038+
0, NFS4_MAX_UINT64, IOMODE_RW,
1039+
NFS_I(pgio->pg_inode)->layout,
1040+
pgio->pg_lseg);
10291041
/* no lseg means that pnfs is not in use, so no mirroring here */
10301042
nfs_pageio_reset_write_mds(pgio);
10311043
out:
@@ -1075,6 +1087,10 @@ static void ff_layout_reset_write(struct nfs_pgio_header *hdr, bool retry_pnfs)
10751087
hdr->args.count,
10761088
(unsigned long long)hdr->args.offset);
10771089

1090+
trace_pnfs_mds_fallback_write_done(hdr->inode,
1091+
hdr->args.offset, hdr->args.count,
1092+
IOMODE_RW, NFS_I(hdr->inode)->layout,
1093+
hdr->lseg);
10781094
task->tk_status = pnfs_write_done_resend_to_mds(hdr);
10791095
}
10801096
}
@@ -1094,6 +1110,10 @@ static void ff_layout_reset_read(struct nfs_pgio_header *hdr)
10941110
hdr->args.count,
10951111
(unsigned long long)hdr->args.offset);
10961112

1113+
trace_pnfs_mds_fallback_read_done(hdr->inode,
1114+
hdr->args.offset, hdr->args.count,
1115+
IOMODE_READ, NFS_I(hdr->inode)->layout,
1116+
hdr->lseg);
10971117
task->tk_status = pnfs_read_done_resend_to_mds(hdr);
10981118
}
10991119
}
@@ -1827,6 +1847,9 @@ ff_layout_read_pagelist(struct nfs_pgio_header *hdr)
18271847
out_failed:
18281848
if (ff_layout_avoid_mds_available_ds(lseg))
18291849
return PNFS_TRY_AGAIN;
1850+
trace_pnfs_mds_fallback_read_pagelist(hdr->inode,
1851+
hdr->args.offset, hdr->args.count,
1852+
IOMODE_READ, NFS_I(hdr->inode)->layout, lseg);
18301853
return PNFS_NOT_ATTEMPTED;
18311854
}
18321855

@@ -1892,6 +1915,9 @@ ff_layout_write_pagelist(struct nfs_pgio_header *hdr, int sync)
18921915
out_failed:
18931916
if (ff_layout_avoid_mds_available_ds(lseg))
18941917
return PNFS_TRY_AGAIN;
1918+
trace_pnfs_mds_fallback_write_pagelist(hdr->inode,
1919+
hdr->args.offset, hdr->args.count,
1920+
IOMODE_RW, NFS_I(hdr->inode)->layout, lseg);
18951921
return PNFS_NOT_ATTEMPTED;
18961922
}
18971923

0 commit comments

Comments
 (0)