Skip to content

Commit ccc1ead

Browse files
committed
Merge tag 'nfs-for-6.17-1' of git://git.linux-nfs.org/projects/trondmy/linux-nfs
Pull NFS client updates from Trond Myklebust: "Highlights include: Stable fixes: - don't inherit NFS filesystem capabilities when crossing from one filesystem to another Bugfixes: - NFS wakeup of __nfs_lookup_revalidate() needs memory barriers - NFS improve bounds checking in nfs_fh_to_dentry() - NFS Fix allocation errors when writing to a NFS file backed loopback device - NFSv4: More listxattr fixes - SUNRPC: fix client handling of TLS alerts - pNFS block/scsi layout fix for an uninitialised pointer dereference - pNFS block/scsi layout fixes for the extent encoding, stripe mapping, and disk offset overflows - pNFS layoutcommit work around for RPC size limitations - pNFS/flexfiles avoid looping when handling fatal errors after layoutget - localio: fix various race conditions Features and cleanups: - Add NFSv4 support for retrieving the btime - NFS: Allow folio migration for the case of mode == MIGRATE_SYNC - NFS: Support using a kernel keyring to store TLS certificates - NFSv4: Speed up delegation lookup using a hash table - Assorted cleanups to remove unused variables and struct fields - Assorted new tracepoints to improve debugging" * tag 'nfs-for-6.17-1' of git://git.linux-nfs.org/projects/trondmy/linux-nfs: (44 commits) NFS/localio: nfs_uuid_put() fix the wake up after unlinking the file NFS/localio: nfs_uuid_put() fix races with nfs_open/close_local_fh() NFS/localio: nfs_close_local_fh() fix check for file closed NFSv4: Remove duplicate lookups, capability probes and fsinfo calls NFS: Fix the setting of capabilities when automounting a new filesystem sunrpc: fix client side handling of tls alerts nfs/localio: use read_seqbegin() rather than read_seqbegin_or_lock() NFS: Fixup allocation flags for nfsiod's __GFP_NORETRY NFSv4.2: another fix for listxattr NFS: Fix filehandle bounds checking in nfs_fh_to_dentry() SUNRPC: Silence warnings about parameters not being described NFS: Clean up pnfs_put_layout_hdr()/pnfs_destroy_layout_final() NFS: Fix wakeup of __nfs_lookup_revalidate() in unblock_revalidate() NFS: use a hash table for delegation lookup NFS: track active delegations per-server NFS: move the delegation_watermark module parameter NFS: cleanup nfs_inode_reclaim_delegation NFS: cleanup error handling in nfs4_server_common_setup pNFS/flexfiles: don't attempt pnfs on fatal DS errors NFS: drop __exit from nfs_exit_keyring ...
2 parents cfaf773 + 4ec752c commit ccc1ead

35 files changed

+858
-562
lines changed

fs/nfs/blocklayout/blocklayout.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -149,8 +149,8 @@ do_add_page_to_bio(struct bio *bio, int npg, enum req_op op, sector_t isect,
149149

150150
/* limit length to what the device mapping allows */
151151
end = disk_addr + *len;
152-
if (end >= map->start + map->len)
153-
*len = map->start + map->len - disk_addr;
152+
if (end >= map->disk_offset + map->len)
153+
*len = map->disk_offset + map->len - disk_addr;
154154

155155
retry:
156156
if (!bio) {

fs/nfs/blocklayout/dev.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -257,10 +257,11 @@ static bool bl_map_stripe(struct pnfs_block_dev *dev, u64 offset,
257257
struct pnfs_block_dev *child;
258258
u64 chunk;
259259
u32 chunk_idx;
260+
u64 disk_chunk;
260261
u64 disk_offset;
261262

262263
chunk = div_u64(offset, dev->chunk_size);
263-
div_u64_rem(chunk, dev->nr_children, &chunk_idx);
264+
disk_chunk = div_u64_rem(chunk, dev->nr_children, &chunk_idx);
264265

265266
if (chunk_idx >= dev->nr_children) {
266267
dprintk("%s: invalid chunk idx %d (%lld/%lld)\n",
@@ -273,7 +274,7 @@ static bool bl_map_stripe(struct pnfs_block_dev *dev, u64 offset,
273274
offset = chunk * dev->chunk_size;
274275

275276
/* disk offset of the stripe */
276-
disk_offset = div_u64(offset, dev->nr_children);
277+
disk_offset = disk_chunk * dev->chunk_size;
277278

278279
child = &dev->children[chunk_idx];
279280
child->map(child, disk_offset, map);

fs/nfs/blocklayout/extent_tree.c

Lines changed: 91 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include <linux/vmalloc.h>
77

88
#include "blocklayout.h"
9+
#include "../nfs4trace.h"
910

1011
#define NFSDBG_FACILITY NFSDBG_PNFS_LD
1112

@@ -520,10 +521,71 @@ static __be32 *encode_scsi_range(struct pnfs_block_extent *be, __be32 *p)
520521
return xdr_encode_hyper(p, be->be_length << SECTOR_SHIFT);
521522
}
522523

523-
static int ext_tree_encode_commit(struct pnfs_block_layout *bl, __be32 *p,
524+
/**
525+
* ext_tree_try_encode_commit - try to encode all extents into the buffer
526+
* @bl: pointer to the layout
527+
* @p: pointer to the output buffer
528+
* @buffer_size: size of the output buffer
529+
* @count: output pointer to the number of encoded extents
530+
* @lastbyte: output pointer to the last written byte
531+
*
532+
* Return values:
533+
* %0: Success, all required extents encoded, outputs are valid
534+
* %-ENOSPC: Buffer too small, nothing encoded, outputs are invalid
535+
*/
536+
static int
537+
ext_tree_try_encode_commit(struct pnfs_block_layout *bl, __be32 *p,
524538
size_t buffer_size, size_t *count, __u64 *lastbyte)
525539
{
526540
struct pnfs_block_extent *be;
541+
542+
spin_lock(&bl->bl_ext_lock);
543+
for (be = ext_tree_first(&bl->bl_ext_rw); be; be = ext_tree_next(be)) {
544+
if (be->be_state != PNFS_BLOCK_INVALID_DATA ||
545+
be->be_tag != EXTENT_WRITTEN)
546+
continue;
547+
548+
(*count)++;
549+
if (ext_tree_layoutupdate_size(bl, *count) > buffer_size) {
550+
spin_unlock(&bl->bl_ext_lock);
551+
return -ENOSPC;
552+
}
553+
}
554+
for (be = ext_tree_first(&bl->bl_ext_rw); be; be = ext_tree_next(be)) {
555+
if (be->be_state != PNFS_BLOCK_INVALID_DATA ||
556+
be->be_tag != EXTENT_WRITTEN)
557+
continue;
558+
559+
if (bl->bl_scsi_layout)
560+
p = encode_scsi_range(be, p);
561+
else
562+
p = encode_block_extent(be, p);
563+
be->be_tag = EXTENT_COMMITTING;
564+
}
565+
*lastbyte = (bl->bl_lwb != 0) ? bl->bl_lwb - 1 : U64_MAX;
566+
bl->bl_lwb = 0;
567+
spin_unlock(&bl->bl_ext_lock);
568+
569+
return 0;
570+
}
571+
572+
/**
573+
* ext_tree_encode_commit - encode as much as possible extents into the buffer
574+
* @bl: pointer to the layout
575+
* @p: pointer to the output buffer
576+
* @buffer_size: size of the output buffer
577+
* @count: output pointer to the number of encoded extents
578+
* @lastbyte: output pointer to the last written byte
579+
*
580+
* Return values:
581+
* %0: Success, all required extents encoded, outputs are valid
582+
* %-ENOSPC: Buffer too small, some extents are encoded, outputs are valid
583+
*/
584+
static int
585+
ext_tree_encode_commit(struct pnfs_block_layout *bl, __be32 *p,
586+
size_t buffer_size, size_t *count, __u64 *lastbyte)
587+
{
588+
struct pnfs_block_extent *be, *be_prev;
527589
int ret = 0;
528590

529591
spin_lock(&bl->bl_ext_lock);
@@ -534,24 +596,40 @@ static int ext_tree_encode_commit(struct pnfs_block_layout *bl, __be32 *p,
534596

535597
(*count)++;
536598
if (ext_tree_layoutupdate_size(bl, *count) > buffer_size) {
537-
/* keep counting.. */
599+
(*count)--;
538600
ret = -ENOSPC;
539-
continue;
601+
break;
540602
}
541603

542604
if (bl->bl_scsi_layout)
543605
p = encode_scsi_range(be, p);
544606
else
545607
p = encode_block_extent(be, p);
546608
be->be_tag = EXTENT_COMMITTING;
609+
be_prev = be;
610+
}
611+
if (!ret) {
612+
*lastbyte = (bl->bl_lwb != 0) ? bl->bl_lwb - 1 : U64_MAX;
613+
bl->bl_lwb = 0;
614+
} else {
615+
*lastbyte = be_prev->be_f_offset + be_prev->be_length;
616+
*lastbyte <<= SECTOR_SHIFT;
617+
*lastbyte -= 1;
547618
}
548-
*lastbyte = bl->bl_lwb - 1;
549-
bl->bl_lwb = 0;
550619
spin_unlock(&bl->bl_ext_lock);
551620

552621
return ret;
553622
}
554623

624+
/**
625+
* ext_tree_prepare_commit - encode extents that need to be committed
626+
* @arg: layout commit data
627+
*
628+
* Return values:
629+
* %0: Success, all required extents are encoded
630+
* %-ENOSPC: Some extents are encoded, but not all, due to RPC size limit
631+
* %-ENOMEM: Out of memory, extents not encoded
632+
*/
555633
int
556634
ext_tree_prepare_commit(struct nfs4_layoutcommit_args *arg)
557635
{
@@ -560,20 +638,18 @@ ext_tree_prepare_commit(struct nfs4_layoutcommit_args *arg)
560638
__be32 *start_p;
561639
int ret;
562640

563-
dprintk("%s enter\n", __func__);
564-
565641
arg->layoutupdate_page = alloc_page(GFP_NOFS);
566642
if (!arg->layoutupdate_page)
567643
return -ENOMEM;
568644
start_p = page_address(arg->layoutupdate_page);
569645
arg->layoutupdate_pages = &arg->layoutupdate_page;
570646

571-
retry:
572-
ret = ext_tree_encode_commit(bl, start_p + 1, buffer_size, &count, &arg->lastbytewritten);
647+
ret = ext_tree_try_encode_commit(bl, start_p + 1, buffer_size,
648+
&count, &arg->lastbytewritten);
573649
if (unlikely(ret)) {
574650
ext_tree_free_commitdata(arg, buffer_size);
575651

576-
buffer_size = ext_tree_layoutupdate_size(bl, count);
652+
buffer_size = NFS_SERVER(arg->inode)->wsize;
577653
count = 0;
578654

579655
arg->layoutupdate_pages =
@@ -588,7 +664,8 @@ ext_tree_prepare_commit(struct nfs4_layoutcommit_args *arg)
588664
return -ENOMEM;
589665
}
590666

591-
goto retry;
667+
ret = ext_tree_encode_commit(bl, start_p + 1, buffer_size,
668+
&count, &arg->lastbytewritten);
592669
}
593670

594671
*start_p = cpu_to_be32(count);
@@ -607,8 +684,9 @@ ext_tree_prepare_commit(struct nfs4_layoutcommit_args *arg)
607684
}
608685
}
609686

610-
dprintk("%s found %zu ranges\n", __func__, count);
611-
return 0;
687+
trace_bl_ext_tree_prepare_commit(ret, count,
688+
arg->lastbytewritten, !!ret);
689+
return ret;
612690
}
613691

614692
void

fs/nfs/client.c

Lines changed: 43 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -682,6 +682,44 @@ struct nfs_client *nfs_init_client(struct nfs_client *clp,
682682
}
683683
EXPORT_SYMBOL_GPL(nfs_init_client);
684684

685+
static void nfs4_server_set_init_caps(struct nfs_server *server)
686+
{
687+
#if IS_ENABLED(CONFIG_NFS_V4)
688+
/* Set the basic capabilities */
689+
server->caps = server->nfs_client->cl_mvops->init_caps;
690+
if (server->flags & NFS_MOUNT_NORDIRPLUS)
691+
server->caps &= ~NFS_CAP_READDIRPLUS;
692+
if (server->nfs_client->cl_proto == XPRT_TRANSPORT_RDMA)
693+
server->caps &= ~NFS_CAP_READ_PLUS;
694+
695+
/*
696+
* Don't use NFS uid/gid mapping if we're using AUTH_SYS or lower
697+
* authentication.
698+
*/
699+
if (nfs4_disable_idmapping &&
700+
server->client->cl_auth->au_flavor == RPC_AUTH_UNIX)
701+
server->caps |= NFS_CAP_UIDGID_NOMAP;
702+
#endif
703+
}
704+
705+
void nfs_server_set_init_caps(struct nfs_server *server)
706+
{
707+
switch (server->nfs_client->rpc_ops->version) {
708+
case 2:
709+
server->caps = NFS_CAP_HARDLINKS | NFS_CAP_SYMLINKS;
710+
break;
711+
case 3:
712+
server->caps = NFS_CAP_HARDLINKS | NFS_CAP_SYMLINKS;
713+
if (!(server->flags & NFS_MOUNT_NORDIRPLUS))
714+
server->caps |= NFS_CAP_READDIRPLUS;
715+
break;
716+
default:
717+
nfs4_server_set_init_caps(server);
718+
break;
719+
}
720+
}
721+
EXPORT_SYMBOL_GPL(nfs_server_set_init_caps);
722+
685723
/*
686724
* Create a version 2 or 3 client
687725
*/
@@ -726,7 +764,6 @@ static int nfs_init_server(struct nfs_server *server,
726764
/* Initialise the client representation from the mount data */
727765
server->flags = ctx->flags;
728766
server->options = ctx->options;
729-
server->caps |= NFS_CAP_HARDLINKS | NFS_CAP_SYMLINKS;
730767

731768
switch (clp->rpc_ops->version) {
732769
case 2:
@@ -762,6 +799,8 @@ static int nfs_init_server(struct nfs_server *server,
762799
if (error < 0)
763800
goto error;
764801

802+
nfs_server_set_init_caps(server);
803+
765804
/* Preserve the values of mount_server-related mount options */
766805
if (ctx->mount_server.addrlen) {
767806
memcpy(&server->mountd_address, &ctx->mount_server.address,
@@ -814,7 +853,6 @@ static void nfs_server_set_fsinfo(struct nfs_server *server,
814853
server->wsize = max_rpc_payload;
815854
if (server->wsize > NFS_MAX_FILE_IO_SIZE)
816855
server->wsize = NFS_MAX_FILE_IO_SIZE;
817-
server->wpages = (server->wsize + PAGE_SIZE - 1) >> PAGE_SHIFT;
818856

819857
server->wtmult = nfs_block_bits(fsinfo->wtmult, NULL);
820858

@@ -831,7 +869,6 @@ static void nfs_server_set_fsinfo(struct nfs_server *server,
831869

832870
server->maxfilesize = fsinfo->maxfilesize;
833871

834-
server->time_delta = fsinfo->time_delta;
835872
server->change_attr_type = fsinfo->change_attr_type;
836873

837874
server->clone_blksize = fsinfo->clone_blksize;
@@ -936,7 +973,6 @@ void nfs_server_copy_userdata(struct nfs_server *target, struct nfs_server *sour
936973
target->acregmax = source->acregmax;
937974
target->acdirmin = source->acdirmin;
938975
target->acdirmax = source->acdirmax;
939-
target->caps = source->caps;
940976
target->options = source->options;
941977
target->auth_info = source->auth_info;
942978
target->port = source->port;
@@ -1007,6 +1043,7 @@ struct nfs_server *nfs_alloc_server(void)
10071043
INIT_LIST_HEAD(&server->ss_src_copies);
10081044

10091045
atomic_set(&server->active, 0);
1046+
atomic_long_set(&server->nr_active_delegations, 0);
10101047

10111048
server->io_stats = nfs_alloc_iostats();
10121049
if (!server->io_stats) {
@@ -1170,6 +1207,8 @@ struct nfs_server *nfs_clone_server(struct nfs_server *source,
11701207
if (error < 0)
11711208
goto out_free_server;
11721209

1210+
nfs_server_set_init_caps(server);
1211+
11731212
/* probe the filesystem info for this server filesystem */
11741213
error = nfs_probe_server(server, fh);
11751214
if (error < 0)

0 commit comments

Comments
 (0)