Skip to content

Commit 684a64b

Browse files
committed
Merge tag 'nfs-for-6.12-1' of git://git.linux-nfs.org/projects/anna/linux-nfs
Pull NFS client updates from Anna Schumaker: "New Features: - Add a 'noalignwrite' mount option for lock-less 'lost writes' prevention - Add support for the LOCALIO protocol extention Bugfixes: - Fix memory leak in error path of nfs4_do_reclaim() - Simplify and guarantee lock owner uniqueness - Fix -Wformat-truncation warning - Fix folio refcounts by using folio_attach_private() - Fix failing the mount system call when the server is down - Fix detection of "Proxying of Times" server support Cleanups: - Annotate struct nfs_cache_array with __counted_by() - Remove unnecessary NULL checks before kfree() - Convert RPC_TASK_* constants to an enum - Remove obsolete or misleading comments and declerations" * tag 'nfs-for-6.12-1' of git://git.linux-nfs.org/projects/anna/linux-nfs: (41 commits) nfs: Fix `make htmldocs` warnings in the localio documentation nfs: add "NFS Client and Server Interlock" section to localio.rst nfs: add FAQ section to Documentation/filesystems/nfs/localio.rst nfs: add Documentation/filesystems/nfs/localio.rst nfs: implement client support for NFS_LOCALIO_PROGRAM nfs/localio: use dedicated workqueues for filesystem read and write pnfs/flexfiles: enable localio support nfs: enable localio for non-pNFS IO nfs: add LOCALIO support nfs: pass struct nfsd_file to nfs_init_pgio and nfs_init_commit nfsd: implement server support for NFS_LOCALIO_PROGRAM nfsd: add LOCALIO support nfs_common: prepare for the NFS client to use nfsd_file for LOCALIO nfs_common: add NFS LOCALIO auxiliary protocol enablement SUNRPC: replace program list with program array SUNRPC: add svcauth_map_clnt_to_svc_cred_local SUNRPC: remove call_allocate() BUG_ONs nfsd: add nfsd_serv_try_get and nfsd_serv_put nfsd: add nfsd_file_acquire_local() nfsd: factor out __fh_verify to allow NULL rqstp to be passed ...
2 parents f7fccaa + 6889813 commit 684a64b

Some content is hidden

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

58 files changed

+2519
-464
lines changed

Documentation/filesystems/nfs/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ NFS
88

99
client-identifier
1010
exporting
11+
localio
1112
pnfs
1213
rpc-cache
1314
rpc-server-gss

Documentation/filesystems/nfs/localio.rst

Lines changed: 357 additions & 0 deletions
Large diffs are not rendered by default.

fs/Kconfig

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -386,6 +386,29 @@ config NFS_COMMON
386386
depends on NFSD || NFS_FS || LOCKD
387387
default y
388388

389+
config NFS_COMMON_LOCALIO_SUPPORT
390+
tristate
391+
default n
392+
default y if NFSD=y || NFS_FS=y
393+
default m if NFSD=m && NFS_FS=m
394+
select SUNRPC
395+
396+
config NFS_LOCALIO
397+
bool "NFS client and server support for LOCALIO auxiliary protocol"
398+
depends on NFSD && NFS_FS
399+
select NFS_COMMON_LOCALIO_SUPPORT
400+
default n
401+
help
402+
Some NFS servers support an auxiliary NFS LOCALIO protocol
403+
that is not an official part of the NFS protocol.
404+
405+
This option enables support for the LOCALIO protocol in the
406+
kernel's NFS server and client. Enable this to permit local
407+
NFS clients to bypass the network when issuing reads and
408+
writes to the local NFS server.
409+
410+
If unsure, say N.
411+
389412
config NFS_V4_2_SSC_HELPER
390413
bool
391414
default y if NFS_V4_2

fs/nfs/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ config NFS_FS
44
depends on INET && FILE_LOCKING && MULTIUSER
55
select LOCKD
66
select SUNRPC
7+
select NFS_COMMON
78
select NFS_ACL_SUPPORT if NFS_V3_ACL
89
help
910
Choose Y here if you want to access files residing on other

fs/nfs/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ nfs-y := client.o dir.o file.o getroot.o inode.o super.o \
1313
nfs-$(CONFIG_ROOT_NFS) += nfsroot.o
1414
nfs-$(CONFIG_SYSCTL) += sysctl.o
1515
nfs-$(CONFIG_NFS_FSCACHE) += fscache.o
16+
nfs-$(CONFIG_NFS_LOCALIO) += localio.o
1617

1718
obj-$(CONFIG_NFS_V2) += nfsv2.o
1819
nfsv2-y := nfs2super.o proc.o nfs2xdr.o

fs/nfs/client.c

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,14 @@ struct nfs_client *nfs_alloc_client(const struct nfs_client_initdata *cl_init)
178178
clp->cl_max_connect = cl_init->max_connect ? cl_init->max_connect : 1;
179179
clp->cl_net = get_net(cl_init->net);
180180

181+
#if IS_ENABLED(CONFIG_NFS_LOCALIO)
182+
seqlock_init(&clp->cl_boot_lock);
183+
ktime_get_real_ts64(&clp->cl_nfssvc_boot);
184+
clp->cl_uuid.net = NULL;
185+
clp->cl_uuid.dom = NULL;
186+
spin_lock_init(&clp->cl_localio_lock);
187+
#endif /* CONFIG_NFS_LOCALIO */
188+
181189
clp->cl_principal = "*";
182190
clp->cl_xprtsec = cl_init->xprtsec;
183191
return clp;
@@ -233,6 +241,8 @@ static void pnfs_init_server(struct nfs_server *server)
233241
*/
234242
void nfs_free_client(struct nfs_client *clp)
235243
{
244+
nfs_local_disable(clp);
245+
236246
/* -EIO all pending I/O */
237247
if (!IS_ERR(clp->cl_rpcclient))
238248
rpc_shutdown_client(clp->cl_rpcclient);
@@ -424,7 +434,10 @@ struct nfs_client *nfs_get_client(const struct nfs_client_initdata *cl_init)
424434
list_add_tail(&new->cl_share_link,
425435
&nn->nfs_client_list);
426436
spin_unlock(&nn->nfs_client_lock);
427-
return rpc_ops->init_client(new, cl_init);
437+
new = rpc_ops->init_client(new, cl_init);
438+
if (!IS_ERR(new))
439+
nfs_local_probe(new);
440+
return new;
428441
}
429442

430443
spin_unlock(&nn->nfs_client_lock);
@@ -997,8 +1010,8 @@ struct nfs_server *nfs_alloc_server(void)
9971010
init_waitqueue_head(&server->write_congestion_wait);
9981011
atomic_long_set(&server->writeback, 0);
9991012

1000-
ida_init(&server->openowner_id);
1001-
ida_init(&server->lockowner_id);
1013+
atomic64_set(&server->owner_ctr, 0);
1014+
10021015
pnfs_init_server(server);
10031016
rpc_init_wait_queue(&server->uoc_rpcwaitq, "NFS UOC");
10041017

@@ -1037,8 +1050,6 @@ void nfs_free_server(struct nfs_server *server)
10371050
}
10381051
ida_free(&s_sysfs_ids, server->s_sysfs_id);
10391052

1040-
ida_destroy(&server->lockowner_id);
1041-
ida_destroy(&server->openowner_id);
10421053
put_cred(server->cred);
10431054
nfs_release_automount_timer();
10441055
call_rcu(&server->rcu, delayed_free);

fs/nfs/dir.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@ struct nfs_cache_array {
151151
unsigned char folio_full : 1,
152152
folio_is_eof : 1,
153153
cookies_are_ordered : 1;
154-
struct nfs_cache_array_entry array[];
154+
struct nfs_cache_array_entry array[] __counted_by(size);
155155
};
156156

157157
struct nfs_readdir_descriptor {
@@ -328,7 +328,8 @@ static int nfs_readdir_folio_array_append(struct folio *folio,
328328
goto out;
329329
}
330330

331-
cache_entry = &array->array[array->size];
331+
array->size++;
332+
cache_entry = &array->array[array->size - 1];
332333
cache_entry->cookie = array->last_cookie;
333334
cache_entry->ino = entry->ino;
334335
cache_entry->d_type = entry->d_type;
@@ -337,7 +338,6 @@ static int nfs_readdir_folio_array_append(struct folio *folio,
337338
array->last_cookie = entry->cookie;
338339
if (array->last_cookie <= cache_entry->cookie)
339340
array->cookies_are_ordered = 0;
340-
array->size++;
341341
if (entry->eof != 0)
342342
nfs_readdir_array_set_eof(array);
343343
out:

fs/nfs/filelayout/filelayout.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -488,7 +488,7 @@ filelayout_read_pagelist(struct nfs_pgio_header *hdr)
488488
/* Perform an asynchronous read to ds */
489489
nfs_initiate_pgio(ds_clnt, hdr, hdr->cred,
490490
NFS_PROTO(hdr->inode), &filelayout_read_call_ops,
491-
0, RPC_TASK_SOFTCONN);
491+
0, RPC_TASK_SOFTCONN, NULL);
492492
return PNFS_ATTEMPTED;
493493
}
494494

@@ -530,7 +530,7 @@ filelayout_write_pagelist(struct nfs_pgio_header *hdr, int sync)
530530
/* Perform an asynchronous write */
531531
nfs_initiate_pgio(ds_clnt, hdr, hdr->cred,
532532
NFS_PROTO(hdr->inode), &filelayout_write_call_ops,
533-
sync, RPC_TASK_SOFTCONN);
533+
sync, RPC_TASK_SOFTCONN, NULL);
534534
return PNFS_ATTEMPTED;
535535
}
536536

@@ -1011,7 +1011,7 @@ static int filelayout_initiate_commit(struct nfs_commit_data *data, int how)
10111011
data->args.fh = fh;
10121012
return nfs_initiate_commit(ds_clnt, data, NFS_PROTO(data->inode),
10131013
&filelayout_commit_call_ops, how,
1014-
RPC_TASK_SOFTCONN);
1014+
RPC_TASK_SOFTCONN, NULL);
10151015
out_err:
10161016
pnfs_generic_prepare_to_resend_writes(data);
10171017
pnfs_generic_commit_release(data);

fs/nfs/flexfilelayout/flexfilelayout.c

Lines changed: 46 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include <linux/nfs_mount.h>
1212
#include <linux/nfs_page.h>
1313
#include <linux/module.h>
14+
#include <linux/file.h>
1415
#include <linux/sched/mm.h>
1516

1617
#include <linux/sunrpc/metrics.h>
@@ -162,6 +163,21 @@ decode_name(struct xdr_stream *xdr, u32 *id)
162163
return 0;
163164
}
164165

166+
static struct nfsd_file *
167+
ff_local_open_fh(struct nfs_client *clp, const struct cred *cred,
168+
struct nfs_fh *fh, fmode_t mode)
169+
{
170+
if (mode & FMODE_WRITE) {
171+
/*
172+
* Always request read and write access since this corresponds
173+
* to a rw layout.
174+
*/
175+
mode |= FMODE_READ;
176+
}
177+
178+
return nfs_local_open_fh(clp, cred, fh, mode);
179+
}
180+
165181
static bool ff_mirror_match_fh(const struct nfs4_ff_layout_mirror *m1,
166182
const struct nfs4_ff_layout_mirror *m2)
167183
{
@@ -237,7 +253,7 @@ static struct nfs4_ff_layout_mirror *ff_layout_alloc_mirror(gfp_t gfp_flags)
237253

238254
static void ff_layout_free_mirror(struct nfs4_ff_layout_mirror *mirror)
239255
{
240-
const struct cred *cred;
256+
const struct cred *cred;
241257

242258
ff_layout_remove_mirror(mirror);
243259
kfree(mirror->fh_versions);
@@ -1756,6 +1772,7 @@ ff_layout_read_pagelist(struct nfs_pgio_header *hdr)
17561772
struct pnfs_layout_segment *lseg = hdr->lseg;
17571773
struct nfs4_pnfs_ds *ds;
17581774
struct rpc_clnt *ds_clnt;
1775+
struct nfsd_file *localio;
17591776
struct nfs4_ff_layout_mirror *mirror;
17601777
const struct cred *ds_cred;
17611778
loff_t offset = hdr->args.offset;
@@ -1802,11 +1819,18 @@ ff_layout_read_pagelist(struct nfs_pgio_header *hdr)
18021819
hdr->args.offset = offset;
18031820
hdr->mds_offset = offset;
18041821

1822+
/* Start IO accounting for local read */
1823+
localio = ff_local_open_fh(ds->ds_clp, ds_cred, fh, FMODE_READ);
1824+
if (localio) {
1825+
hdr->task.tk_start = ktime_get();
1826+
ff_layout_read_record_layoutstats_start(&hdr->task, hdr);
1827+
}
1828+
18051829
/* Perform an asynchronous read to ds */
18061830
nfs_initiate_pgio(ds_clnt, hdr, ds_cred, ds->ds_clp->rpc_ops,
18071831
vers == 3 ? &ff_layout_read_call_ops_v3 :
18081832
&ff_layout_read_call_ops_v4,
1809-
0, RPC_TASK_SOFTCONN);
1833+
0, RPC_TASK_SOFTCONN, localio);
18101834
put_cred(ds_cred);
18111835
return PNFS_ATTEMPTED;
18121836

@@ -1826,6 +1850,7 @@ ff_layout_write_pagelist(struct nfs_pgio_header *hdr, int sync)
18261850
struct pnfs_layout_segment *lseg = hdr->lseg;
18271851
struct nfs4_pnfs_ds *ds;
18281852
struct rpc_clnt *ds_clnt;
1853+
struct nfsd_file *localio;
18291854
struct nfs4_ff_layout_mirror *mirror;
18301855
const struct cred *ds_cred;
18311856
loff_t offset = hdr->args.offset;
@@ -1870,11 +1895,19 @@ ff_layout_write_pagelist(struct nfs_pgio_header *hdr, int sync)
18701895
*/
18711896
hdr->args.offset = offset;
18721897

1898+
/* Start IO accounting for local write */
1899+
localio = ff_local_open_fh(ds->ds_clp, ds_cred, fh,
1900+
FMODE_READ|FMODE_WRITE);
1901+
if (localio) {
1902+
hdr->task.tk_start = ktime_get();
1903+
ff_layout_write_record_layoutstats_start(&hdr->task, hdr);
1904+
}
1905+
18731906
/* Perform an asynchronous write */
18741907
nfs_initiate_pgio(ds_clnt, hdr, ds_cred, ds->ds_clp->rpc_ops,
18751908
vers == 3 ? &ff_layout_write_call_ops_v3 :
18761909
&ff_layout_write_call_ops_v4,
1877-
sync, RPC_TASK_SOFTCONN);
1910+
sync, RPC_TASK_SOFTCONN, localio);
18781911
put_cred(ds_cred);
18791912
return PNFS_ATTEMPTED;
18801913

@@ -1908,6 +1941,7 @@ static int ff_layout_initiate_commit(struct nfs_commit_data *data, int how)
19081941
struct pnfs_layout_segment *lseg = data->lseg;
19091942
struct nfs4_pnfs_ds *ds;
19101943
struct rpc_clnt *ds_clnt;
1944+
struct nfsd_file *localio;
19111945
struct nfs4_ff_layout_mirror *mirror;
19121946
const struct cred *ds_cred;
19131947
u32 idx;
@@ -1946,10 +1980,18 @@ static int ff_layout_initiate_commit(struct nfs_commit_data *data, int how)
19461980
if (fh)
19471981
data->args.fh = fh;
19481982

1983+
/* Start IO accounting for local commit */
1984+
localio = ff_local_open_fh(ds->ds_clp, ds_cred, fh,
1985+
FMODE_READ|FMODE_WRITE);
1986+
if (localio) {
1987+
data->task.tk_start = ktime_get();
1988+
ff_layout_commit_record_layoutstats_start(&data->task, data);
1989+
}
1990+
19491991
ret = nfs_initiate_commit(ds_clnt, data, ds->ds_clp->rpc_ops,
19501992
vers == 3 ? &ff_layout_commit_call_ops_v3 :
19511993
&ff_layout_commit_call_ops_v4,
1952-
how, RPC_TASK_SOFTCONN);
1994+
how, RPC_TASK_SOFTCONN, localio);
19531995
put_cred(ds_cred);
19541996
return ret;
19551997
out_err:
@@ -2086,12 +2128,6 @@ static int ff_layout_encode_ioerr(struct xdr_stream *xdr,
20862128
return ff_layout_encode_ds_ioerr(xdr, &ff_args->errors);
20872129
}
20882130

2089-
static void
2090-
encode_opaque_fixed(struct xdr_stream *xdr, const void *buf, size_t len)
2091-
{
2092-
WARN_ON_ONCE(xdr_stream_encode_opaque_fixed(xdr, buf, len) < 0);
2093-
}
2094-
20952131
static void
20962132
ff_layout_encode_ff_iostat_head(struct xdr_stream *xdr,
20972133
const nfs4_stateid *stateid,

fs/nfs/flexfilelayout/flexfilelayoutdev.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -395,6 +395,12 @@ nfs4_ff_layout_prepare_ds(struct pnfs_layout_segment *lseg,
395395

396396
/* connect success, check rsize/wsize limit */
397397
if (!status) {
398+
/*
399+
* ds_clp is put in destroy_ds().
400+
* keep ds_clp even if DS is local, so that if local IO cannot
401+
* proceed somehow, we can fall back to NFS whenever we want.
402+
*/
403+
nfs_local_probe(ds->ds_clp);
398404
max_payload =
399405
nfs_block_size(rpc_max_payload(ds->ds_clp->cl_rpcclient),
400406
NULL);

0 commit comments

Comments
 (0)