Skip to content

Commit 7aac719

Browse files
committed
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
2 parents 1b5d466 + dd2fa82 commit 7aac719

File tree

14 files changed

+129
-99
lines changed

14 files changed

+129
-99
lines changed

fs/nfs/client.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -888,6 +888,8 @@ static void nfs_server_set_fsinfo(struct nfs_server *server,
888888

889889
if (fsinfo->xattr_support)
890890
server->caps |= NFS_CAP_XATTR;
891+
else
892+
server->caps &= ~NFS_CAP_XATTR;
891893
#endif
892894
}
893895

fs/nfs/file.c

Lines changed: 37 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
#include <linux/mm.h>
2929
#include <linux/pagemap.h>
3030
#include <linux/gfp.h>
31+
#include <linux/rmap.h>
3132
#include <linux/swap.h>
3233
#include <linux/compaction.h>
3334

@@ -280,6 +281,37 @@ nfs_file_fsync(struct file *file, loff_t start, loff_t end, int datasync)
280281
}
281282
EXPORT_SYMBOL_GPL(nfs_file_fsync);
282283

284+
void nfs_truncate_last_folio(struct address_space *mapping, loff_t from,
285+
loff_t to)
286+
{
287+
struct folio *folio;
288+
289+
if (from >= to)
290+
return;
291+
292+
folio = filemap_lock_folio(mapping, from >> PAGE_SHIFT);
293+
if (IS_ERR(folio))
294+
return;
295+
296+
if (folio_mkclean(folio))
297+
folio_mark_dirty(folio);
298+
299+
if (folio_test_uptodate(folio)) {
300+
loff_t fpos = folio_pos(folio);
301+
size_t offset = from - fpos;
302+
size_t end = folio_size(folio);
303+
304+
if (to - fpos < end)
305+
end = to - fpos;
306+
folio_zero_segment(folio, offset, end);
307+
trace_nfs_size_truncate_folio(mapping->host, to);
308+
}
309+
310+
folio_unlock(folio);
311+
folio_put(folio);
312+
}
313+
EXPORT_SYMBOL_GPL(nfs_truncate_last_folio);
314+
283315
/*
284316
* Decide whether a read/modify/write cycle may be more efficient
285317
* 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,
356388

357389
dfprintk(PAGECACHE, "NFS: write_begin(%pD2(%lu), %u@%lld)\n",
358390
file, mapping->host->i_ino, len, (long long) pos);
391+
nfs_truncate_last_folio(mapping, i_size_read(mapping->host), pos);
359392

360393
fgp |= fgf_set_order(len);
361394
start:
@@ -442,10 +475,11 @@ static void nfs_invalidate_folio(struct folio *folio, size_t offset,
442475
dfprintk(PAGECACHE, "NFS: invalidate_folio(%lu, %zu, %zu)\n",
443476
folio->index, offset, length);
444477

445-
if (offset != 0 || length < folio_size(folio))
446-
return;
447478
/* Cancel any unstarted writes on this page */
448-
nfs_wb_folio_cancel(inode, folio);
479+
if (offset != 0 || length < folio_size(folio))
480+
nfs_wb_folio(inode, folio);
481+
else
482+
nfs_wb_folio_cancel(inode, folio);
449483
folio_wait_private_2(folio); /* [DEPRECATED] */
450484
trace_nfs_invalidate_folio(inode, folio_pos(folio) + offset, length);
451485
}

fs/nfs/flexfilelayout/flexfilelayout.c

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -293,7 +293,7 @@ ff_lseg_match_mirrors(struct pnfs_layout_segment *l1,
293293
struct pnfs_layout_segment *l2)
294294
{
295295
const struct nfs4_ff_layout_segment *fl1 = FF_LAYOUT_LSEG(l1);
296-
const struct nfs4_ff_layout_segment *fl2 = FF_LAYOUT_LSEG(l1);
296+
const struct nfs4_ff_layout_segment *fl2 = FF_LAYOUT_LSEG(l2);
297297
u32 i;
298298

299299
if (fl1->mirror_array_cnt != fl2->mirror_array_cnt)
@@ -773,8 +773,11 @@ ff_layout_choose_ds_for_read(struct pnfs_layout_segment *lseg,
773773
continue;
774774

775775
if (check_device &&
776-
nfs4_test_deviceid_unavailable(&mirror->mirror_ds->id_node))
776+
nfs4_test_deviceid_unavailable(&mirror->mirror_ds->id_node)) {
777+
// reinitialize the error state in case if this is the last iteration
778+
ds = ERR_PTR(-EINVAL);
777779
continue;
780+
}
778781

779782
*best_idx = idx;
780783
break;
@@ -804,7 +807,7 @@ ff_layout_choose_best_ds_for_read(struct pnfs_layout_segment *lseg,
804807
struct nfs4_pnfs_ds *ds;
805808

806809
ds = ff_layout_choose_valid_ds_for_read(lseg, start_idx, best_idx);
807-
if (ds)
810+
if (!IS_ERR(ds))
808811
return ds;
809812
return ff_layout_choose_any_ds_for_read(lseg, start_idx, best_idx);
810813
}
@@ -818,7 +821,7 @@ ff_layout_get_ds_for_read(struct nfs_pageio_descriptor *pgio,
818821

819822
ds = ff_layout_choose_best_ds_for_read(lseg, pgio->pg_mirror_idx,
820823
best_idx);
821-
if (ds || !pgio->pg_mirror_idx)
824+
if (!IS_ERR(ds) || !pgio->pg_mirror_idx)
822825
return ds;
823826
return ff_layout_choose_best_ds_for_read(lseg, 0, best_idx);
824827
}
@@ -868,7 +871,7 @@ ff_layout_pg_init_read(struct nfs_pageio_descriptor *pgio,
868871
req->wb_nio = 0;
869872

870873
ds = ff_layout_get_ds_for_read(pgio, &ds_idx);
871-
if (!ds) {
874+
if (IS_ERR(ds)) {
872875
if (!ff_layout_no_fallback_to_mds(pgio->pg_lseg))
873876
goto out_mds;
874877
pnfs_generic_pg_cleanup(pgio);
@@ -1072,11 +1075,13 @@ static void ff_layout_resend_pnfs_read(struct nfs_pgio_header *hdr)
10721075
{
10731076
u32 idx = hdr->pgio_mirror_idx + 1;
10741077
u32 new_idx = 0;
1078+
struct nfs4_pnfs_ds *ds;
10751079

1076-
if (ff_layout_choose_any_ds_for_read(hdr->lseg, idx, &new_idx))
1077-
ff_layout_send_layouterror(hdr->lseg);
1078-
else
1080+
ds = ff_layout_choose_any_ds_for_read(hdr->lseg, idx, &new_idx);
1081+
if (IS_ERR(ds))
10791082
pnfs_error_mark_layout_for_return(hdr->inode, hdr->lseg);
1083+
else
1084+
ff_layout_send_layouterror(hdr->lseg);
10801085
pnfs_read_resend_pnfs(hdr, new_idx);
10811086
}
10821087

fs/nfs/inode.c

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -716,6 +716,7 @@ nfs_setattr(struct mnt_idmap *idmap, struct dentry *dentry,
716716
{
717717
struct inode *inode = d_inode(dentry);
718718
struct nfs_fattr *fattr;
719+
loff_t oldsize = i_size_read(inode);
719720
int error = 0;
720721

721722
nfs_inc_stats(inode, NFSIOS_VFSSETATTR);
@@ -731,7 +732,7 @@ nfs_setattr(struct mnt_idmap *idmap, struct dentry *dentry,
731732
if (error)
732733
return error;
733734

734-
if (attr->ia_size == i_size_read(inode))
735+
if (attr->ia_size == oldsize)
735736
attr->ia_valid &= ~ATTR_SIZE;
736737
}
737738

@@ -767,8 +768,10 @@ nfs_setattr(struct mnt_idmap *idmap, struct dentry *dentry,
767768
trace_nfs_setattr_enter(inode);
768769

769770
/* Write all dirty data */
770-
if (S_ISREG(inode->i_mode))
771+
if (S_ISREG(inode->i_mode)) {
772+
nfs_file_block_o_direct(NFS_I(inode));
771773
nfs_sync_inode(inode);
774+
}
772775

773776
fattr = nfs_alloc_fattr_with_label(NFS_SERVER(inode));
774777
if (fattr == NULL) {
@@ -777,8 +780,12 @@ nfs_setattr(struct mnt_idmap *idmap, struct dentry *dentry,
777780
}
778781

779782
error = NFS_PROTO(inode)->setattr(dentry, fattr, attr);
780-
if (error == 0)
783+
if (error == 0) {
784+
if (attr->ia_valid & ATTR_SIZE)
785+
nfs_truncate_last_folio(inode->i_mapping, oldsize,
786+
attr->ia_size);
781787
error = nfs_refresh_inode(inode, fattr);
788+
}
782789
nfs_free_fattr(fattr);
783790
out:
784791
trace_nfs_setattr_exit(inode, error);

fs/nfs/internal.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -437,6 +437,8 @@ int nfs_file_release(struct inode *, struct file *);
437437
int nfs_lock(struct file *, int, struct file_lock *);
438438
int nfs_flock(struct file *, int, struct file_lock *);
439439
int nfs_check_flags(int);
440+
void nfs_truncate_last_folio(struct address_space *mapping, loff_t from,
441+
loff_t to);
440442

441443
/* inode.c */
442444
extern struct workqueue_struct *nfsiod_workqueue;
@@ -530,6 +532,16 @@ static inline bool nfs_file_io_is_buffered(struct nfs_inode *nfsi)
530532
return test_bit(NFS_INO_ODIRECT, &nfsi->flags) == 0;
531533
}
532534

535+
/* Must be called with exclusively locked inode->i_rwsem */
536+
static inline void nfs_file_block_o_direct(struct nfs_inode *nfsi)
537+
{
538+
if (test_bit(NFS_INO_ODIRECT, &nfsi->flags)) {
539+
clear_bit(NFS_INO_ODIRECT, &nfsi->flags);
540+
inode_dio_wait(&nfsi->vfs_inode);
541+
}
542+
}
543+
544+
533545
/* namespace.c */
534546
#define NFS_PATH_CANONICAL 1
535547
extern char *nfs_path(char **p, struct dentry *dentry,

fs/nfs/io.c

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -14,15 +14,6 @@
1414

1515
#include "internal.h"
1616

17-
/* Call with exclusively locked inode->i_rwsem */
18-
static void nfs_block_o_direct(struct nfs_inode *nfsi, struct inode *inode)
19-
{
20-
if (test_bit(NFS_INO_ODIRECT, &nfsi->flags)) {
21-
clear_bit(NFS_INO_ODIRECT, &nfsi->flags);
22-
inode_dio_wait(inode);
23-
}
24-
}
25-
2617
/**
2718
* nfs_start_io_read - declare the file is being used for buffered reads
2819
* @inode: file inode
@@ -57,7 +48,7 @@ nfs_start_io_read(struct inode *inode)
5748
err = down_write_killable(&inode->i_rwsem);
5849
if (err)
5950
return err;
60-
nfs_block_o_direct(nfsi, inode);
51+
nfs_file_block_o_direct(nfsi);
6152
downgrade_write(&inode->i_rwsem);
6253

6354
return 0;
@@ -90,7 +81,7 @@ nfs_start_io_write(struct inode *inode)
9081

9182
err = down_write_killable(&inode->i_rwsem);
9283
if (!err)
93-
nfs_block_o_direct(NFS_I(inode), inode);
84+
nfs_file_block_o_direct(NFS_I(inode));
9485
return err;
9586
}
9687

fs/nfs/localio.c

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -180,10 +180,8 @@ static void nfs_local_probe(struct nfs_client *clp)
180180
return;
181181
}
182182

183-
if (nfs_client_is_local(clp)) {
184-
/* If already enabled, disable and re-enable */
185-
nfs_localio_disable_client(clp);
186-
}
183+
if (nfs_client_is_local(clp))
184+
return;
187185

188186
if (!nfs_uuid_begin(&clp->cl_uuid))
189187
return;
@@ -244,7 +242,8 @@ __nfs_local_open_fh(struct nfs_client *clp, const struct cred *cred,
244242
case -ENOMEM:
245243
case -ENXIO:
246244
case -ENOENT:
247-
/* Revalidate localio, will disable if unsupported */
245+
/* Revalidate localio */
246+
nfs_localio_disable_client(clp);
248247
nfs_local_probe(clp);
249248
}
250249
}
@@ -453,12 +452,13 @@ static void nfs_local_call_read(struct work_struct *work)
453452
nfs_local_iter_init(&iter, iocb, READ);
454453

455454
status = filp->f_op->read_iter(&iocb->kiocb, &iter);
455+
456+
revert_creds(save_cred);
457+
456458
if (status != -EIOCBQUEUED) {
457459
nfs_local_read_done(iocb, status);
458460
nfs_local_pgio_release(iocb);
459461
}
460-
461-
revert_creds(save_cred);
462462
}
463463

464464
static int
@@ -648,14 +648,15 @@ static void nfs_local_call_write(struct work_struct *work)
648648
file_start_write(filp);
649649
status = filp->f_op->write_iter(&iocb->kiocb, &iter);
650650
file_end_write(filp);
651+
652+
revert_creds(save_cred);
653+
current->flags = old_flags;
654+
651655
if (status != -EIOCBQUEUED) {
652656
nfs_local_write_done(iocb, status);
653657
nfs_local_vfs_getattr(iocb);
654658
nfs_local_pgio_release(iocb);
655659
}
656-
657-
revert_creds(save_cred);
658-
current->flags = old_flags;
659660
}
660661

661662
static int

0 commit comments

Comments
 (0)