NFS client bugfixes for Linux 6.17

Stable patches:
  - Revert "SUNRPC: Don't allow waiting for exiting tasks" as it is
    breaking ltp tests.
 
 Bugfixes:
  - Another set of fixes to the tracking of NFSv4 server capabilities
    when crossing filesystem boundaries.
  - Localio fix to restore credentials and prevent triggering a BUG_ON().
  - Fix to prevent flapping of the localio on/off trigger.
  - Protections against 'eof page pollution' as demonstrated in xfstests
    generic/363.
  - Series of patches to ensure correct ordering of O_DIRECT i/o and
    truncate, fallocate and copy functions.
  - Fix a NULL pointer check in flexfiles reads that regresses 6.17.
  - Correct a typo that breaks flexfiles layout segment processing.
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCgAdFiEESQctxSBg8JpV8KqEZwvnipYKAPIFAmjBjysACgkQZwvnipYK
 APJkNg/9Gd2IWoWse0PeOkijLhsxwnH6S6huvX3ouD9RziWobJAHbk7zpgycMt5/
 C+DYoqhpM/uIKRBjLPafnMFXQhsx/jEJcBSZOP3C1AD5OEvA/qtaE5nfGw9Zbnyr
 /j+B5yVhC8yPrDGFH9PlQ6UeFxnK9frqqqbNXDoCn5QCpmAjlbyESOiQ6ZZKUpZV
 vXPv9C4DeSZoZ2CsXMAWsLarGcrHE3ctpi+Bpfq7iDdUCdeYBOtaJHrgKtgwmCQy
 My5J3l7KRKmAy22XWvu+sRn7wQO0y5UOWtXUiDZD73ufC4hF1IIRuBWHW/5IBYD+
 6ojdBxYqTW01JeFWt4MoT8f+AKbej36x7abnf0ztxVpzXhp19KXiF+ddWrcyjKvc
 bjohM0slddM4TLAz/98D6Kwm7N/KFOD7DHPBv9vvMA8ci2efx+cQvKToNRnxK0xi
 FNmIi8+ZuKz9Pr32JINHHC1RFtl1dTb39l7jJVIK2niGYTjPwlxpcE7bax9CL1S7
 ke9m7GtX5dUyBYG2rKzLjihpTthL4GQgW6PlSMhIk2BA/m1ZZUVLAxI8xh9TR02V
 oMlxq78fsFNCxCvvqlUeo93IH7YHGSl1PbUqPjD0fs5k8lOX6rHXmHULqYgkmsC/
 QCAiXDg6gh2Rj69/9yvkWPe0KIXIULKGT++oZakgbMQPujNEtxE=
 =5TC7
 -----END PGP SIGNATURE-----

Merge tag 'nfs-for-6.17-3' of git://git.linux-nfs.org/projects/trondmy/linux-nfs

Pull NFS client fixes from Trond Myklebust:
 "Stable patches:

   - Revert "SUNRPC: Don't allow waiting for exiting tasks" as it is
     breaking ltp tests

  Bugfixes:

   - Another set of fixes to the tracking of NFSv4 server capabilities
     when crossing filesystem boundaries

   - Localio fix to restore credentials and prevent triggering a
     BUG_ON()

   - Fix to prevent flapping of the localio on/off trigger

   - Protections against 'eof page pollution' as demonstrated in
     xfstests generic/363

   - Series of patches to ensure correct ordering of O_DIRECT i/o and
     truncate, fallocate and copy functions

   - Fix a NULL pointer check in flexfiles reads that regresses 6.17

   - Correct a typo that breaks flexfiles layout segment processing"

* tag 'nfs-for-6.17-3' of git://git.linux-nfs.org/projects/trondmy/linux-nfs:
  NFSv4/flexfiles: Fix layout merge mirror check.
  SUNRPC: call xs_sock_process_cmsg for all cmsg
  Revert "SUNRPC: Don't allow waiting for exiting tasks"
  NFS: Fix the marking of the folio as up to date
  NFS: nfs_invalidate_folio() must observe the offset and size arguments
  NFSv4.2: Serialise O_DIRECT i/o and copy range
  NFSv4.2: Serialise O_DIRECT i/o and clone range
  NFSv4.2: Serialise O_DIRECT i/o and fallocate()
  NFS: Serialise O_DIRECT i/o and truncate()
  NFSv4.2: Protect copy offload and clone against 'eof page pollution'
  NFS: Protect against 'eof page pollution'
  flexfiles/pNFS: fix NULL checks on result of ff_layout_choose_ds_for_read
  nfs/localio: avoid bouncing LOCALIO if nfs_client_is_local()
  nfs/localio: restore creds before releasing pageio data
  NFSv4: Clear the NFS_CAP_XATTR flag if not supported by the server
  NFSv4: Clear NFS_CAP_OPEN_XOR and NFS_CAP_DELEGTIME if not supported
  NFSv4: Clear the NFS_CAP_FS_LOCATIONS flag if it is not set
  NFSv4: Don't clear capabilities that won't be reset
pull/824/head
Linus Torvalds 2025-09-10 12:38:41 -07:00
commit 7aac71907b
14 changed files with 129 additions and 99 deletions

View File

@ -888,6 +888,8 @@ static void nfs_server_set_fsinfo(struct nfs_server *server,
if (fsinfo->xattr_support)
server->caps |= NFS_CAP_XATTR;
else
server->caps &= ~NFS_CAP_XATTR;
#endif
}

View File

@ -28,6 +28,7 @@
#include <linux/mm.h>
#include <linux/pagemap.h>
#include <linux/gfp.h>
#include <linux/rmap.h>
#include <linux/swap.h>
#include <linux/compaction.h>
@ -280,6 +281,37 @@ nfs_file_fsync(struct file *file, loff_t start, loff_t end, int datasync)
}
EXPORT_SYMBOL_GPL(nfs_file_fsync);
void nfs_truncate_last_folio(struct address_space *mapping, loff_t from,
loff_t to)
{
struct folio *folio;
if (from >= to)
return;
folio = filemap_lock_folio(mapping, from >> PAGE_SHIFT);
if (IS_ERR(folio))
return;
if (folio_mkclean(folio))
folio_mark_dirty(folio);
if (folio_test_uptodate(folio)) {
loff_t fpos = folio_pos(folio);
size_t offset = from - fpos;
size_t end = folio_size(folio);
if (to - fpos < end)
end = to - fpos;
folio_zero_segment(folio, offset, end);
trace_nfs_size_truncate_folio(mapping->host, to);
}
folio_unlock(folio);
folio_put(folio);
}
EXPORT_SYMBOL_GPL(nfs_truncate_last_folio);
/*
* Decide whether a read/modify/write cycle may be more efficient
* then a modify/write/read cycle when writing to a page in the
@ -356,6 +388,7 @@ static int nfs_write_begin(const struct kiocb *iocb,
dfprintk(PAGECACHE, "NFS: write_begin(%pD2(%lu), %u@%lld)\n",
file, mapping->host->i_ino, len, (long long) pos);
nfs_truncate_last_folio(mapping, i_size_read(mapping->host), pos);
fgp |= fgf_set_order(len);
start:
@ -442,10 +475,11 @@ static void nfs_invalidate_folio(struct folio *folio, size_t offset,
dfprintk(PAGECACHE, "NFS: invalidate_folio(%lu, %zu, %zu)\n",
folio->index, offset, length);
if (offset != 0 || length < folio_size(folio))
return;
/* Cancel any unstarted writes on this page */
nfs_wb_folio_cancel(inode, folio);
if (offset != 0 || length < folio_size(folio))
nfs_wb_folio(inode, folio);
else
nfs_wb_folio_cancel(inode, folio);
folio_wait_private_2(folio); /* [DEPRECATED] */
trace_nfs_invalidate_folio(inode, folio_pos(folio) + offset, length);
}

View File

@ -293,7 +293,7 @@ ff_lseg_match_mirrors(struct pnfs_layout_segment *l1,
struct pnfs_layout_segment *l2)
{
const struct nfs4_ff_layout_segment *fl1 = FF_LAYOUT_LSEG(l1);
const struct nfs4_ff_layout_segment *fl2 = FF_LAYOUT_LSEG(l1);
const struct nfs4_ff_layout_segment *fl2 = FF_LAYOUT_LSEG(l2);
u32 i;
if (fl1->mirror_array_cnt != fl2->mirror_array_cnt)
@ -773,8 +773,11 @@ ff_layout_choose_ds_for_read(struct pnfs_layout_segment *lseg,
continue;
if (check_device &&
nfs4_test_deviceid_unavailable(&mirror->mirror_ds->id_node))
nfs4_test_deviceid_unavailable(&mirror->mirror_ds->id_node)) {
// reinitialize the error state in case if this is the last iteration
ds = ERR_PTR(-EINVAL);
continue;
}
*best_idx = idx;
break;
@ -804,7 +807,7 @@ ff_layout_choose_best_ds_for_read(struct pnfs_layout_segment *lseg,
struct nfs4_pnfs_ds *ds;
ds = ff_layout_choose_valid_ds_for_read(lseg, start_idx, best_idx);
if (ds)
if (!IS_ERR(ds))
return ds;
return ff_layout_choose_any_ds_for_read(lseg, start_idx, best_idx);
}
@ -818,7 +821,7 @@ ff_layout_get_ds_for_read(struct nfs_pageio_descriptor *pgio,
ds = ff_layout_choose_best_ds_for_read(lseg, pgio->pg_mirror_idx,
best_idx);
if (ds || !pgio->pg_mirror_idx)
if (!IS_ERR(ds) || !pgio->pg_mirror_idx)
return ds;
return ff_layout_choose_best_ds_for_read(lseg, 0, best_idx);
}
@ -868,7 +871,7 @@ retry:
req->wb_nio = 0;
ds = ff_layout_get_ds_for_read(pgio, &ds_idx);
if (!ds) {
if (IS_ERR(ds)) {
if (!ff_layout_no_fallback_to_mds(pgio->pg_lseg))
goto out_mds;
pnfs_generic_pg_cleanup(pgio);
@ -1072,11 +1075,13 @@ static void ff_layout_resend_pnfs_read(struct nfs_pgio_header *hdr)
{
u32 idx = hdr->pgio_mirror_idx + 1;
u32 new_idx = 0;
struct nfs4_pnfs_ds *ds;
if (ff_layout_choose_any_ds_for_read(hdr->lseg, idx, &new_idx))
ff_layout_send_layouterror(hdr->lseg);
else
ds = ff_layout_choose_any_ds_for_read(hdr->lseg, idx, &new_idx);
if (IS_ERR(ds))
pnfs_error_mark_layout_for_return(hdr->inode, hdr->lseg);
else
ff_layout_send_layouterror(hdr->lseg);
pnfs_read_resend_pnfs(hdr, new_idx);
}

View File

@ -716,6 +716,7 @@ nfs_setattr(struct mnt_idmap *idmap, struct dentry *dentry,
{
struct inode *inode = d_inode(dentry);
struct nfs_fattr *fattr;
loff_t oldsize = i_size_read(inode);
int error = 0;
nfs_inc_stats(inode, NFSIOS_VFSSETATTR);
@ -731,7 +732,7 @@ nfs_setattr(struct mnt_idmap *idmap, struct dentry *dentry,
if (error)
return error;
if (attr->ia_size == i_size_read(inode))
if (attr->ia_size == oldsize)
attr->ia_valid &= ~ATTR_SIZE;
}
@ -767,8 +768,10 @@ nfs_setattr(struct mnt_idmap *idmap, struct dentry *dentry,
trace_nfs_setattr_enter(inode);
/* Write all dirty data */
if (S_ISREG(inode->i_mode))
if (S_ISREG(inode->i_mode)) {
nfs_file_block_o_direct(NFS_I(inode));
nfs_sync_inode(inode);
}
fattr = nfs_alloc_fattr_with_label(NFS_SERVER(inode));
if (fattr == NULL) {
@ -777,8 +780,12 @@ nfs_setattr(struct mnt_idmap *idmap, struct dentry *dentry,
}
error = NFS_PROTO(inode)->setattr(dentry, fattr, attr);
if (error == 0)
if (error == 0) {
if (attr->ia_valid & ATTR_SIZE)
nfs_truncate_last_folio(inode->i_mapping, oldsize,
attr->ia_size);
error = nfs_refresh_inode(inode, fattr);
}
nfs_free_fattr(fattr);
out:
trace_nfs_setattr_exit(inode, error);

View File

@ -437,6 +437,8 @@ int nfs_file_release(struct inode *, struct file *);
int nfs_lock(struct file *, int, struct file_lock *);
int nfs_flock(struct file *, int, struct file_lock *);
int nfs_check_flags(int);
void nfs_truncate_last_folio(struct address_space *mapping, loff_t from,
loff_t to);
/* inode.c */
extern struct workqueue_struct *nfsiod_workqueue;
@ -530,6 +532,16 @@ static inline bool nfs_file_io_is_buffered(struct nfs_inode *nfsi)
return test_bit(NFS_INO_ODIRECT, &nfsi->flags) == 0;
}
/* Must be called with exclusively locked inode->i_rwsem */
static inline void nfs_file_block_o_direct(struct nfs_inode *nfsi)
{
if (test_bit(NFS_INO_ODIRECT, &nfsi->flags)) {
clear_bit(NFS_INO_ODIRECT, &nfsi->flags);
inode_dio_wait(&nfsi->vfs_inode);
}
}
/* namespace.c */
#define NFS_PATH_CANONICAL 1
extern char *nfs_path(char **p, struct dentry *dentry,

View File

@ -14,15 +14,6 @@
#include "internal.h"
/* Call with exclusively locked inode->i_rwsem */
static void nfs_block_o_direct(struct nfs_inode *nfsi, struct inode *inode)
{
if (test_bit(NFS_INO_ODIRECT, &nfsi->flags)) {
clear_bit(NFS_INO_ODIRECT, &nfsi->flags);
inode_dio_wait(inode);
}
}
/**
* nfs_start_io_read - declare the file is being used for buffered reads
* @inode: file inode
@ -57,7 +48,7 @@ nfs_start_io_read(struct inode *inode)
err = down_write_killable(&inode->i_rwsem);
if (err)
return err;
nfs_block_o_direct(nfsi, inode);
nfs_file_block_o_direct(nfsi);
downgrade_write(&inode->i_rwsem);
return 0;
@ -90,7 +81,7 @@ nfs_start_io_write(struct inode *inode)
err = down_write_killable(&inode->i_rwsem);
if (!err)
nfs_block_o_direct(NFS_I(inode), inode);
nfs_file_block_o_direct(NFS_I(inode));
return err;
}

View File

@ -180,10 +180,8 @@ static void nfs_local_probe(struct nfs_client *clp)
return;
}
if (nfs_client_is_local(clp)) {
/* If already enabled, disable and re-enable */
nfs_localio_disable_client(clp);
}
if (nfs_client_is_local(clp))
return;
if (!nfs_uuid_begin(&clp->cl_uuid))
return;
@ -244,7 +242,8 @@ __nfs_local_open_fh(struct nfs_client *clp, const struct cred *cred,
case -ENOMEM:
case -ENXIO:
case -ENOENT:
/* Revalidate localio, will disable if unsupported */
/* Revalidate localio */
nfs_localio_disable_client(clp);
nfs_local_probe(clp);
}
}
@ -453,12 +452,13 @@ static void nfs_local_call_read(struct work_struct *work)
nfs_local_iter_init(&iter, iocb, READ);
status = filp->f_op->read_iter(&iocb->kiocb, &iter);
revert_creds(save_cred);
if (status != -EIOCBQUEUED) {
nfs_local_read_done(iocb, status);
nfs_local_pgio_release(iocb);
}
revert_creds(save_cred);
}
static int
@ -648,14 +648,15 @@ static void nfs_local_call_write(struct work_struct *work)
file_start_write(filp);
status = filp->f_op->write_iter(&iocb->kiocb, &iter);
file_end_write(filp);
revert_creds(save_cred);
current->flags = old_flags;
if (status != -EIOCBQUEUED) {
nfs_local_write_done(iocb, status);
nfs_local_vfs_getattr(iocb);
nfs_local_pgio_release(iocb);
}
revert_creds(save_cred);
current->flags = old_flags;
}
static int

View File

@ -114,6 +114,7 @@ static int nfs42_proc_fallocate(struct rpc_message *msg, struct file *filep,
exception.inode = inode;
exception.state = lock->open_context->state;
nfs_file_block_o_direct(NFS_I(inode));
err = nfs_sync_inode(inode);
if (err)
goto out;
@ -137,6 +138,7 @@ int nfs42_proc_allocate(struct file *filep, loff_t offset, loff_t len)
.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_ALLOCATE],
};
struct inode *inode = file_inode(filep);
loff_t oldsize = i_size_read(inode);
int err;
if (!nfs_server_capable(inode, NFS_CAP_ALLOCATE))
@ -145,7 +147,11 @@ int nfs42_proc_allocate(struct file *filep, loff_t offset, loff_t len)
inode_lock(inode);
err = nfs42_proc_fallocate(&msg, filep, offset, len);
if (err == -EOPNOTSUPP)
if (err == 0)
nfs_truncate_last_folio(inode->i_mapping, oldsize,
offset + len);
else if (err == -EOPNOTSUPP)
NFS_SERVER(inode)->caps &= ~(NFS_CAP_ALLOCATE |
NFS_CAP_ZERO_RANGE);
@ -183,6 +189,7 @@ int nfs42_proc_zero_range(struct file *filep, loff_t offset, loff_t len)
.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_ZERO_RANGE],
};
struct inode *inode = file_inode(filep);
loff_t oldsize = i_size_read(inode);
int err;
if (!nfs_server_capable(inode, NFS_CAP_ZERO_RANGE))
@ -191,9 +198,11 @@ int nfs42_proc_zero_range(struct file *filep, loff_t offset, loff_t len)
inode_lock(inode);
err = nfs42_proc_fallocate(&msg, filep, offset, len);
if (err == 0)
if (err == 0) {
nfs_truncate_last_folio(inode->i_mapping, oldsize,
offset + len);
truncate_pagecache_range(inode, offset, (offset + len) -1);
if (err == -EOPNOTSUPP)
} else if (err == -EOPNOTSUPP)
NFS_SERVER(inode)->caps &= ~NFS_CAP_ZERO_RANGE;
inode_unlock(inode);
@ -354,22 +363,27 @@ out:
/**
* nfs42_copy_dest_done - perform inode cache updates after clone/copy offload
* @inode: pointer to destination inode
* @file: pointer to destination file
* @pos: destination offset
* @len: copy length
* @oldsize: length of the file prior to clone/copy
*
* Punch a hole in the inode page cache, so that the NFS client will
* know to retrieve new data.
* Update the file size if necessary, and then mark the inode as having
* invalid cached values for change attribute, ctime, mtime and space used.
*/
static void nfs42_copy_dest_done(struct inode *inode, loff_t pos, loff_t len)
static void nfs42_copy_dest_done(struct file *file, loff_t pos, loff_t len,
loff_t oldsize)
{
struct inode *inode = file_inode(file);
struct address_space *mapping = file->f_mapping;
loff_t newsize = pos + len;
loff_t end = newsize - 1;
WARN_ON_ONCE(invalidate_inode_pages2_range(inode->i_mapping,
pos >> PAGE_SHIFT, end >> PAGE_SHIFT));
nfs_truncate_last_folio(mapping, oldsize, pos);
WARN_ON_ONCE(invalidate_inode_pages2_range(mapping, pos >> PAGE_SHIFT,
end >> PAGE_SHIFT));
spin_lock(&inode->i_lock);
if (newsize > i_size_read(inode))
@ -402,6 +416,7 @@ static ssize_t _nfs42_proc_copy(struct file *src,
struct nfs_server *src_server = NFS_SERVER(src_inode);
loff_t pos_src = args->src_pos;
loff_t pos_dst = args->dst_pos;
loff_t oldsize_dst = i_size_read(dst_inode);
size_t count = args->count;
ssize_t status;
@ -430,6 +445,7 @@ static ssize_t _nfs42_proc_copy(struct file *src,
return status;
}
nfs_file_block_o_direct(NFS_I(dst_inode));
status = nfs_sync_inode(dst_inode);
if (status)
return status;
@ -475,7 +491,7 @@ static ssize_t _nfs42_proc_copy(struct file *src,
goto out;
}
nfs42_copy_dest_done(dst_inode, pos_dst, res->write_res.count);
nfs42_copy_dest_done(dst, pos_dst, res->write_res.count, oldsize_dst);
nfs_invalidate_atime(src_inode);
status = res->write_res.count;
out:
@ -1242,6 +1258,7 @@ static int _nfs42_proc_clone(struct rpc_message *msg, struct file *src_f,
struct nfs42_clone_res res = {
.server = server,
};
loff_t oldsize_dst = i_size_read(dst_inode);
int status;
msg->rpc_argp = &args;
@ -1276,7 +1293,7 @@ static int _nfs42_proc_clone(struct rpc_message *msg, struct file *src_f,
/* a zero-length count means clone to EOF in src */
if (count == 0 && res.dst_fattr->valid & NFS_ATTR_FATTR_SIZE)
count = nfs_size_to_loff_t(res.dst_fattr->size) - dst_offset;
nfs42_copy_dest_done(dst_inode, dst_offset, count);
nfs42_copy_dest_done(dst_f, dst_offset, count, oldsize_dst);
status = nfs_post_op_update_inode(dst_inode, res.dst_fattr);
}

View File

@ -278,9 +278,11 @@ static loff_t nfs42_remap_file_range(struct file *src_file, loff_t src_off,
lock_two_nondirectories(src_inode, dst_inode);
/* flush all pending writes on both src and dst so that server
* has the latest data */
nfs_file_block_o_direct(NFS_I(src_inode));
ret = nfs_sync_inode(src_inode);
if (ret)
goto out_unlock;
nfs_file_block_o_direct(NFS_I(dst_inode));
ret = nfs_sync_inode(dst_inode);
if (ret)
goto out_unlock;

View File

@ -4013,8 +4013,10 @@ static int _nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *f
res.attr_bitmask[2];
}
memcpy(server->attr_bitmask, res.attr_bitmask, sizeof(server->attr_bitmask));
server->caps &= ~(NFS_CAP_ACLS | NFS_CAP_HARDLINKS |
NFS_CAP_SYMLINKS| NFS_CAP_SECURITY_LABEL);
server->caps &=
~(NFS_CAP_ACLS | NFS_CAP_HARDLINKS | NFS_CAP_SYMLINKS |
NFS_CAP_SECURITY_LABEL | NFS_CAP_FS_LOCATIONS |
NFS_CAP_OPEN_XOR | NFS_CAP_DELEGTIME);
server->fattr_valid = NFS_ATTR_FATTR_V4;
if (res.attr_bitmask[0] & FATTR4_WORD0_ACL &&
res.acl_bitmask & ACL4_SUPPORT_ALLOW_ACL)
@ -4092,7 +4094,6 @@ int nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *fhandle)
};
int err;
nfs_server_set_init_caps(server);
do {
err = nfs4_handle_exception(server,
_nfs4_server_capabilities(server, fhandle),

View File

@ -272,6 +272,7 @@ DECLARE_EVENT_CLASS(nfs_update_size_class,
TP_ARGS(inode, new_size))
DEFINE_NFS_UPDATE_SIZE_EVENT(truncate);
DEFINE_NFS_UPDATE_SIZE_EVENT(truncate_folio);
DEFINE_NFS_UPDATE_SIZE_EVENT(wcc);
DEFINE_NFS_UPDATE_SIZE_EVENT(update);
DEFINE_NFS_UPDATE_SIZE_EVENT(grow);

View File

@ -237,59 +237,17 @@ static void nfs_mapping_set_error(struct folio *folio, int error)
}
/*
* nfs_page_group_search_locked
* @head - head request of page group
* @page_offset - offset into page
* nfs_page_covers_folio
* @req: struct nfs_page
*
* Search page group with head @head to find a request that contains the
* page offset @page_offset.
*
* Returns a pointer to the first matching nfs request, or NULL if no
* match is found.
*
* Must be called with the page group lock held
*/
static struct nfs_page *
nfs_page_group_search_locked(struct nfs_page *head, unsigned int page_offset)
{
struct nfs_page *req;
req = head;
do {
if (page_offset >= req->wb_pgbase &&
page_offset < (req->wb_pgbase + req->wb_bytes))
return req;
req = req->wb_this_page;
} while (req != head);
return NULL;
}
/*
* nfs_page_group_covers_page
* @head - head request of page group
*
* Return true if the page group with head @head covers the whole page,
* returns false otherwise
* Return true if the request covers the whole folio.
* Note that the caller should ensure all subrequests have been joined
*/
static bool nfs_page_group_covers_page(struct nfs_page *req)
{
unsigned int len = nfs_folio_length(nfs_page_to_folio(req));
struct nfs_page *tmp;
unsigned int pos = 0;
nfs_page_group_lock(req);
for (;;) {
tmp = nfs_page_group_search_locked(req->wb_head, pos);
if (!tmp)
break;
pos = tmp->wb_pgbase + tmp->wb_bytes;
}
nfs_page_group_unlock(req);
return pos >= len;
return req->wb_pgbase == 0 && req->wb_bytes == len;
}
/* We can set the PG_uptodate flag if we see that a write request
@ -2045,6 +2003,7 @@ int nfs_wb_folio_cancel(struct inode *inode, struct folio *folio)
* release it */
nfs_inode_remove_request(req);
nfs_unlock_and_release_request(req);
folio_cancel_dirty(folio);
}
return ret;

View File

@ -276,8 +276,6 @@ EXPORT_SYMBOL_GPL(rpc_destroy_wait_queue);
static int rpc_wait_bit_killable(struct wait_bit_key *key, int mode)
{
if (unlikely(current->flags & PF_EXITING))
return -EINTR;
schedule();
if (signal_pending_state(mode, current))
return -ERESTARTSYS;

View File

@ -407,9 +407,9 @@ xs_sock_recv_cmsg(struct socket *sock, unsigned int *msg_flags, int flags)
iov_iter_kvec(&msg.msg_iter, ITER_DEST, &alert_kvec, 1,
alert_kvec.iov_len);
ret = sock_recvmsg(sock, &msg, flags);
if (ret > 0 &&
tls_get_record_type(sock->sk, &u.cmsg) == TLS_RECORD_TYPE_ALERT) {
iov_iter_revert(&msg.msg_iter, ret);
if (ret > 0) {
if (tls_get_record_type(sock->sk, &u.cmsg) == TLS_RECORD_TYPE_ALERT)
iov_iter_revert(&msg.msg_iter, ret);
ret = xs_sock_process_cmsg(sock, &msg, msg_flags, &u.cmsg,
-EAGAIN);
}