Skip to content

Commit

Permalink
Merge tag 'nfs-for-6.6-1' of git://git.linux-nfs.org/projects/anna/li…
Browse files Browse the repository at this point in the history
…nux-nfs

Pull NFS client updates from Anna Schumaker:
 "New Features:
   - Enable the NFS v4.2 READ_PLUS operation by default

  Stable Fixes:
   - NFSv4/pnfs: minor fix for cleanup path in nfs4_get_device_info
   - NFS: Fix a potential data corruption

  Bugfixes:
   - Fix various READ_PLUS issues including:
      - smatch warnings
      - xdr size calculations
      - scratch buffer handling
      - 32bit / highmem xdr page handling
   - Fix checkpatch errors in file.c
   - Fix redundant readdir request after an EOF
   - Fix handling of COPY ERR_OFFLOAD_NO_REQ
   - Fix assignment of xprtdata.cred

  Cleanups:
   - Remove unused xprtrdma function declarations
   - Clean up an integer overflow check to avoid a warning
   - Clean up #includes in dns_resolve.c
   - Clean up nfs4_get_device_info so we don't pass a NULL pointer
     to __free_page()
   - Clean up sunrpc TCP socket timeout configuration
   - Guard against READDIR loops when entry names are too long
   - Use EXCHID4_FLAG_USE_PNFS_DS for DS servers"

* tag 'nfs-for-6.6-1' of git://git.linux-nfs.org/projects/anna/linux-nfs: (22 commits)
  pNFS: Fix assignment of xprtdata.cred
  NFSv4.2: fix handling of COPY ERR_OFFLOAD_NO_REQ
  NFS: Guard against READDIR loop when entry names exceed MAXNAMELEN
  NFSv4.1: use EXCHGID4_FLAG_USE_PNFS_DS for DS server
  NFS/pNFS: Set the connect timeout for the pNFS flexfiles driver
  SUNRPC: Don't override connect timeouts in rpc_clnt_add_xprt()
  SUNRPC: Allow specification of TCP client connect timeout at setup
  SUNRPC: Refactor and simplify connect timeout
  SUNRPC: Set the TCP_SYNCNT to match the socket timeout
  NFS: Fix a potential data corruption
  nfs: fix redundant readdir request after get eof
  nfs/blocklayout: Use the passed in gfp flags
  filemap: Fix errors in file.c
  NFSv4/pnfs: minor fix for cleanup path in nfs4_get_device_info
  NFS: Move common includes outside ifdef
  SUNRPC: clean up integer overflow check
  xprtrdma: Remove unused function declaration rpcrdma_bc_post_recv()
  NFS: Enable the READ_PLUS operation by default
  SUNRPC: kmap() the xdr pages during decode
  NFSv4.2: Rework scratch handling for READ_PLUS (again)
  ...
  • Loading branch information
torvalds committed Aug 31, 2023
2 parents f35d170 + c4a123d commit 99d9982
Show file tree
Hide file tree
Showing 27 changed files with 171 additions and 63 deletions.
6 changes: 2 additions & 4 deletions fs/nfs/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -209,8 +209,6 @@ config NFS_DISABLE_UDP_SUPPORT
config NFS_V4_2_READ_PLUS
bool "NFS: Enable support for the NFSv4.2 READ_PLUS operation"
depends on NFS_V4_2
default n
default y
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.
Choose Y here to enable use of the NFS v4.2 READ_PLUS operation.
4 changes: 2 additions & 2 deletions fs/nfs/blocklayout/dev.c
Original file line number Diff line number Diff line change
Expand Up @@ -404,7 +404,7 @@ bl_parse_concat(struct nfs_server *server, struct pnfs_block_dev *d,
int ret, i;

d->children = kcalloc(v->concat.volumes_count,
sizeof(struct pnfs_block_dev), GFP_KERNEL);
sizeof(struct pnfs_block_dev), gfp_mask);
if (!d->children)
return -ENOMEM;

Expand Down Expand Up @@ -433,7 +433,7 @@ bl_parse_stripe(struct nfs_server *server, struct pnfs_block_dev *d,
int ret, i;

d->children = kcalloc(v->stripe.volumes_count,
sizeof(struct pnfs_block_dev), GFP_KERNEL);
sizeof(struct pnfs_block_dev), gfp_mask);
if (!d->children)
return -ENOMEM;

Expand Down
2 changes: 2 additions & 0 deletions fs/nfs/client.c
Original file line number Diff line number Diff line change
Expand Up @@ -517,6 +517,8 @@ int nfs_create_rpc_client(struct nfs_client *clp,
.authflavor = flavor,
.cred = cl_init->cred,
.xprtsec = cl_init->xprtsec,
.connect_timeout = cl_init->connect_timeout,
.reconnect_timeout = cl_init->reconnect_timeout,
};

if (test_bit(NFS_CS_DISCRTRY, &clp->cl_flags))
Expand Down
15 changes: 11 additions & 4 deletions fs/nfs/dir.c
Original file line number Diff line number Diff line change
Expand Up @@ -1089,6 +1089,17 @@ static void nfs_do_filldir(struct nfs_readdir_descriptor *desc,
for (i = desc->cache_entry_index; i < array->size; i++) {
struct nfs_cache_array_entry *ent;

/*
* nfs_readdir_handle_cache_misses return force clear at
* (cache_misses > NFS_READDIR_CACHE_MISS_THRESHOLD) for
* readdir heuristic, NFS_READDIR_CACHE_MISS_THRESHOLD + 1
* entries need be emitted here.
*/
if (first_emit && i > NFS_READDIR_CACHE_MISS_THRESHOLD + 2) {
desc->eob = true;
break;
}

ent = &array->array[i];
if (!dir_emit(desc->ctx, ent->name, ent->name_len,
nfs_compat_user_ino64(ent->ino), ent->d_type)) {
Expand All @@ -1107,10 +1118,6 @@ static void nfs_do_filldir(struct nfs_readdir_descriptor *desc,
desc->ctx->pos = desc->dir_cookie;
else
desc->ctx->pos++;
if (first_emit && i > NFS_READDIR_CACHE_MISS_THRESHOLD + 1) {
desc->eob = true;
break;
}
}
if (array->folio_is_eof)
desc->eof = !desc->eob;
Expand Down
20 changes: 19 additions & 1 deletion fs/nfs/direct.c
Original file line number Diff line number Diff line change
Expand Up @@ -472,13 +472,31 @@ ssize_t nfs_file_direct_read(struct kiocb *iocb, struct iov_iter *iter,
return result;
}

static void nfs_direct_add_page_head(struct list_head *list,
struct nfs_page *req)
{
struct nfs_page *head = req->wb_head;

if (!list_empty(&head->wb_list) || !nfs_lock_request(head))
return;
if (!list_empty(&head->wb_list)) {
nfs_unlock_request(head);
return;
}
list_add(&head->wb_list, list);
kref_get(&head->wb_kref);
kref_get(&head->wb_kref);
}

static void nfs_direct_join_group(struct list_head *list, struct inode *inode)
{
struct nfs_page *req, *subreq;

list_for_each_entry(req, list, wb_list) {
if (req->wb_head != req)
if (req->wb_head != req) {
nfs_direct_add_page_head(&req->wb_list, req);
continue;
}
subreq = req->wb_this_page;
if (subreq == req)
continue;
Expand Down
12 changes: 5 additions & 7 deletions fs/nfs/dns_resolve.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,16 @@
* Resolves DNS hostnames into valid ip addresses
*/

#ifdef CONFIG_NFS_USE_KERNEL_DNS

#include <linux/module.h>
#include <linux/sunrpc/clnt.h>
#include <linux/sunrpc/addr.h>
#include <linux/dns_resolver.h>

#include "dns_resolve.h"

#ifdef CONFIG_NFS_USE_KERNEL_DNS

#include <linux/dns_resolver.h>

ssize_t nfs_dns_resolve_name(struct net *net, char *name, size_t namelen,
struct sockaddr_storage *ss, size_t salen)
{
Expand All @@ -35,23 +37,19 @@ ssize_t nfs_dns_resolve_name(struct net *net, char *name, size_t namelen,

#else

#include <linux/module.h>
#include <linux/hash.h>
#include <linux/string.h>
#include <linux/kmod.h>
#include <linux/slab.h>
#include <linux/socket.h>
#include <linux/seq_file.h>
#include <linux/inet.h>
#include <linux/sunrpc/clnt.h>
#include <linux/sunrpc/addr.h>
#include <linux/sunrpc/cache.h>
#include <linux/sunrpc/svcauth.h>
#include <linux/sunrpc/rpc_pipe_fs.h>
#include <linux/nfs_fs.h>

#include "nfs4_fs.h"
#include "dns_resolve.h"
#include "cache_lib.h"
#include "netns.h"

Expand Down
2 changes: 1 addition & 1 deletion fs/nfs/file.c
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,7 @@ nfs_file_splice_read(struct file *in, loff_t *ppos, struct pipe_inode_info *pipe
EXPORT_SYMBOL_GPL(nfs_file_splice_read);

int
nfs_file_mmap(struct file * file, struct vm_area_struct * vma)
nfs_file_mmap(struct file *file, struct vm_area_struct *vma)
{
struct inode *inode = file_inode(file);
int status;
Expand Down
3 changes: 3 additions & 0 deletions fs/nfs/internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,8 @@ struct nfs_client_initdata {
const struct rpc_timeout *timeparms;
const struct cred *cred;
struct xprtsec_parms xprtsec;
unsigned long connect_timeout;
unsigned long reconnect_timeout;
};

/*
Expand Down Expand Up @@ -493,6 +495,7 @@ extern const struct nfs_pgio_completion_ops nfs_async_read_completion_ops;
extern void nfs_pageio_init_read(struct nfs_pageio_descriptor *pgio,
struct inode *inode, bool force_mds,
const struct nfs_pgio_completion_ops *compl_ops);
extern bool nfs_read_alloc_scratch(struct nfs_pgio_header *hdr, size_t size);
extern int nfs_read_add_folio(struct nfs_pageio_descriptor *pgio,
struct nfs_open_context *ctx,
struct folio *folio);
Expand Down
2 changes: 1 addition & 1 deletion fs/nfs/nfs2xdr.c
Original file line number Diff line number Diff line change
Expand Up @@ -949,7 +949,7 @@ int nfs2_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry,

error = decode_filename_inline(xdr, &entry->name, &entry->len);
if (unlikely(error))
return -EAGAIN;
return error == -ENAMETOOLONG ? -ENAMETOOLONG : -EAGAIN;

/*
* The type (size and byte order) of nfscookie isn't defined in
Expand Down
3 changes: 3 additions & 0 deletions fs/nfs/nfs3client.c
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ struct nfs_client *nfs3_set_ds_client(struct nfs_server *mds_srv,
int ds_proto, unsigned int ds_timeo, unsigned int ds_retrans)
{
struct rpc_timeout ds_timeout;
unsigned long connect_timeout = ds_timeo * (ds_retrans + 1) * HZ / 10;
struct nfs_client *mds_clp = mds_srv->nfs_client;
struct nfs_client_initdata cl_init = {
.addr = ds_addr,
Expand All @@ -98,6 +99,8 @@ struct nfs_client *nfs3_set_ds_client(struct nfs_server *mds_srv,
.timeparms = &ds_timeout,
.cred = mds_srv->cred,
.xprtsec = mds_clp->cl_xprtsec,
.connect_timeout = connect_timeout,
.reconnect_timeout = connect_timeout,
};
struct nfs_client *clp;
char buf[INET6_ADDRSTRLEN + 1];
Expand Down
2 changes: 1 addition & 1 deletion fs/nfs/nfs3xdr.c
Original file line number Diff line number Diff line change
Expand Up @@ -1991,7 +1991,7 @@ int nfs3_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry,

error = decode_inline_filename3(xdr, &entry->name, &entry->len);
if (unlikely(error))
return -EAGAIN;
return error == -ENAMETOOLONG ? -ENAMETOOLONG : -EAGAIN;

error = decode_cookie3(xdr, &new_cookie);
if (unlikely(error))
Expand Down
1 change: 1 addition & 0 deletions fs/nfs/nfs42.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
* more? Need to consider not to pre-alloc too much for a compound.
*/
#define PNFS_LAYOUTSTATS_MAXDEV (4)
#define READ_PLUS_SCRATCH_SIZE (16)

/* nfs4.2proc.c */
#ifdef CONFIG_NFS_V4_2
Expand Down
5 changes: 3 additions & 2 deletions fs/nfs/nfs42proc.c
Original file line number Diff line number Diff line change
Expand Up @@ -471,8 +471,9 @@ ssize_t nfs42_proc_copy(struct file *src, loff_t pos_src,
continue;
}
break;
} else if (err == -NFS4ERR_OFFLOAD_NO_REQS && !args.sync) {
args.sync = true;
} else if (err == -NFS4ERR_OFFLOAD_NO_REQS &&
args.sync != res.synchronous) {
args.sync = res.synchronous;
dst_exception.retry = 1;
continue;
} else if ((err == -ESTALE ||
Expand Down
17 changes: 11 additions & 6 deletions fs/nfs/nfs42xdr.c
Original file line number Diff line number Diff line change
Expand Up @@ -54,10 +54,16 @@
(1 /* data_content4 */ + \
2 /* data_info4.di_offset */ + \
1 /* data_info4.di_length */)
#define NFS42_READ_PLUS_HOLE_SEGMENT_SIZE \
(1 /* data_content4 */ + \
2 /* data_info4.di_offset */ + \
2 /* data_info4.di_length */)
#define READ_PLUS_SEGMENT_SIZE_DIFF (NFS42_READ_PLUS_HOLE_SEGMENT_SIZE - \
NFS42_READ_PLUS_DATA_SEGMENT_SIZE)
#define decode_read_plus_maxsz (op_decode_hdr_maxsz + \
1 /* rpr_eof */ + \
1 /* rpr_contents count */ + \
NFS42_READ_PLUS_DATA_SEGMENT_SIZE)
NFS42_READ_PLUS_HOLE_SEGMENT_SIZE)
#define encode_seek_maxsz (op_encode_hdr_maxsz + \
encode_stateid_maxsz + \
2 /* offset */ + \
Expand Down Expand Up @@ -617,8 +623,8 @@ static void nfs4_xdr_enc_read_plus(struct rpc_rqst *req,
encode_putfh(xdr, args->fh, &hdr);
encode_read_plus(xdr, args, &hdr);

rpc_prepare_reply_pages(req, args->pages, args->pgbase,
args->count, hdr.replen);
rpc_prepare_reply_pages(req, args->pages, args->pgbase, args->count,
hdr.replen - READ_PLUS_SEGMENT_SIZE_DIFF);
encode_nops(&hdr);
}

Expand Down Expand Up @@ -1056,13 +1062,12 @@ static int decode_read_plus(struct xdr_stream *xdr, struct nfs_pgio_res *res)
res->eof = be32_to_cpup(p++);
segments = be32_to_cpup(p++);
if (segments == 0)
return status;
return 0;

segs = kmalloc_array(segments, sizeof(*segs), GFP_KERNEL);
if (!segs)
return -ENOMEM;

status = -EIO;
for (i = 0; i < segments; i++) {
status = decode_read_plus_segment(xdr, &segs[i]);
if (status < 0)
Expand Down Expand Up @@ -1428,7 +1433,7 @@ static int nfs4_xdr_dec_read_plus(struct rpc_rqst *rqstp,
struct compound_hdr hdr;
int status;

xdr_set_scratch_buffer(xdr, res->scratch, sizeof(res->scratch));
xdr_set_scratch_buffer(xdr, res->scratch, READ_PLUS_SCRATCH_SIZE);

status = decode_compound_hdr(xdr, &hdr);
if (status)
Expand Down
3 changes: 3 additions & 0 deletions fs/nfs/nfs4client.c
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,8 @@ struct nfs_client *nfs4_alloc_client(const struct nfs_client_initdata *cl_init)
__set_bit(NFS_CS_DISCRTRY, &clp->cl_flags);
__set_bit(NFS_CS_NO_RETRANS_TIMEOUT, &clp->cl_flags);

if (test_bit(NFS_CS_DS, &cl_init->init_flags))
__set_bit(NFS_CS_DS, &clp->cl_flags);
/*
* Set up the connection to the server before we add add to the
* global list.
Expand Down Expand Up @@ -1007,6 +1009,7 @@ struct nfs_client *nfs4_set_ds_client(struct nfs_server *mds_srv,
if (mds_srv->flags & NFS_MOUNT_NORESVPORT)
__set_bit(NFS_CS_NORESVPORT, &cl_init.init_flags);

__set_bit(NFS_CS_DS, &cl_init.init_flags);
/*
* Set an authflavor equual to the MDS value. Use the MDS nfs_client
* cl_ipaddr so as to use the same EXCHANGE_ID co_ownerid as the MDS
Expand Down
17 changes: 5 additions & 12 deletions fs/nfs/nfs4proc.c
Original file line number Diff line number Diff line change
Expand Up @@ -5438,18 +5438,8 @@ static bool nfs4_read_plus_not_supported(struct rpc_task *task,
return false;
}

static inline void nfs4_read_plus_scratch_free(struct nfs_pgio_header *hdr)
{
if (hdr->res.scratch) {
kfree(hdr->res.scratch);
hdr->res.scratch = NULL;
}
}

static int nfs4_read_done(struct rpc_task *task, struct nfs_pgio_header *hdr)
{
nfs4_read_plus_scratch_free(hdr);

if (!nfs4_sequence_done(task, &hdr->res.seq_res))
return -EAGAIN;
if (nfs4_read_stateid_changed(task, &hdr->args))
Expand All @@ -5469,8 +5459,7 @@ static bool nfs42_read_plus_support(struct nfs_pgio_header *hdr,
/* Note: We don't use READ_PLUS with pNFS yet */
if (nfs_server_capable(hdr->inode, NFS_CAP_READ_PLUS) && !hdr->ds_clp) {
msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_READ_PLUS];
hdr->res.scratch = kmalloc(32, GFP_KERNEL);
return hdr->res.scratch != NULL;
return nfs_read_alloc_scratch(hdr, READ_PLUS_SCRATCH_SIZE);
}
return false;
}
Expand Down Expand Up @@ -8798,6 +8787,8 @@ nfs4_run_exchange_id(struct nfs_client *clp, const struct cred *cred,
#ifdef CONFIG_NFS_V4_1_MIGRATION
calldata->args.flags |= EXCHGID4_FLAG_SUPP_MOVED_MIGR;
#endif
if (test_bit(NFS_CS_DS, &clp->cl_flags))
calldata->args.flags |= EXCHGID4_FLAG_USE_PNFS_DS;
msg.rpc_argp = &calldata->args;
msg.rpc_resp = &calldata->res;
task_setup_data.callback_data = calldata;
Expand Down Expand Up @@ -8875,6 +8866,8 @@ static int _nfs4_proc_exchange_id(struct nfs_client *clp, const struct cred *cre
/* Save the EXCHANGE_ID verifier session trunk tests */
memcpy(clp->cl_confirm.data, argp->verifier.data,
sizeof(clp->cl_confirm.data));
if (resp->flags & EXCHGID4_FLAG_USE_PNFS_DS)
set_bit(NFS_CS_DS, &clp->cl_flags);
out:
trace_nfs4_exchange_id(clp, status);
rpc_put_task(task);
Expand Down
2 changes: 1 addition & 1 deletion fs/nfs/pnfs_dev.c
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ nfs4_get_device_info(struct nfs_server *server,
set_bit(NFS_DEVICEID_NOCACHE, &d->flags);

out_free_pages:
for (i = 0; i < max_pages; i++)
while (--i >= 0)
__free_page(pages[i]);
kfree(pages);
out_free_pdev:
Expand Down
5 changes: 4 additions & 1 deletion fs/nfs/pnfs_nfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -852,6 +852,7 @@ static int _nfs4_pnfs_v3_ds_connect(struct nfs_server *mds_srv,
{
struct nfs_client *clp = ERR_PTR(-EIO);
struct nfs4_pnfs_ds_addr *da;
unsigned long connect_timeout = timeo * (retrans + 1) * HZ / 10;
int status = 0;

dprintk("--> %s DS %s\n", __func__, ds->ds_remotestr);
Expand All @@ -870,6 +871,8 @@ static int _nfs4_pnfs_v3_ds_connect(struct nfs_server *mds_srv,
.dstaddr = (struct sockaddr *)&da->da_addr,
.addrlen = da->da_addrlen,
.servername = clp->cl_hostname,
.connect_timeout = connect_timeout,
.reconnect_timeout = connect_timeout,
};

if (da->da_transport != clp->cl_proto)
Expand Down Expand Up @@ -943,7 +946,7 @@ static int _nfs4_pnfs_v4_ds_connect(struct nfs_server *mds_srv,
* Test this address for session trunking and
* add as an alias
*/
xprtdata.cred = nfs4_get_clid_cred(clp),
xprtdata.cred = nfs4_get_clid_cred(clp);
rpc_clnt_add_xprt(clp->cl_rpcclient, &xprt_args,
rpc_clnt_setup_test_and_add_xprt,
&rpcdata);
Expand Down
Loading

0 comments on commit 99d9982

Please sign in to comment.