summaryrefslogtreecommitdiff
path: root/fs/xfs
diff options
context:
space:
mode:
authorMark Brown <broonie@kernel.org>2026-09-30 11:58:30 +0100
committerMark Brown <broonie@kernel.org>2026-09-30 11:58:30 +0100
commit5eb3fdca6ca7667a73d52adfd047d94e8b8b105e (patch)
treec935b3fa5b47c9d70e0e66c7cc7830e74988b13f /fs/xfs
parentf60deca1c3741ab8fcf318a7bb82a3d026ea7c49 (diff)
parent84086827932b58e7645d93d970bbc566c4ee408b (diff)
downloadlinux-next-5eb3fdca6ca7667a73d52adfd047d94e8b8b105e.tar.gz
linux-next-5eb3fdca6ca7667a73d52adfd047d94e8b8b105e.zip
Merge branch 'vfs.all' of https://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs.git
# Conflicts: # fs/smb/server/smb2pdu.c # fs/smb/server/vfs.c # fs/smb/server/vfs.h
Diffstat (limited to 'fs/xfs')
-rw-r--r--fs/xfs/libxfs/xfs_errortag.h6
-rw-r--r--fs/xfs/libxfs/xfs_inode_util.h2
-rw-r--r--fs/xfs/xfs_acl.c2
-rw-r--r--fs/xfs/xfs_acl.h2
-rw-r--r--fs/xfs/xfs_aops.c13
-rw-r--r--fs/xfs/xfs_buf.c11
-rw-r--r--fs/xfs/xfs_file.c11
-rw-r--r--fs/xfs/xfs_handle.c6
-rw-r--r--fs/xfs/xfs_inode.c4
-rw-r--r--fs/xfs/xfs_inode.h2
-rw-r--r--fs/xfs/xfs_ioctl.c2
-rw-r--r--fs/xfs/xfs_ioctl.h2
-rw-r--r--fs/xfs/xfs_ioend.c137
-rw-r--r--fs/xfs/xfs_ioend.h2
-rw-r--r--fs/xfs/xfs_iops.c24
-rw-r--r--fs/xfs/xfs_iops.h2
-rw-r--r--fs/xfs/xfs_itable.c2
-rw-r--r--fs/xfs/xfs_itable.h2
-rw-r--r--fs/xfs/xfs_mount.h8
-rw-r--r--fs/xfs/xfs_super.c1
-rw-r--r--fs/xfs/xfs_symlink.c2
-rw-r--r--fs/xfs/xfs_symlink.h2
-rw-r--r--fs/xfs/xfs_sysfs.c78
-rw-r--r--fs/xfs/xfs_trace.h1
-rw-r--r--fs/xfs/xfs_xattr.c2
-rw-r--r--fs/xfs/xfs_zone_alloc.c4
26 files changed, 277 insertions, 53 deletions
diff --git a/fs/xfs/libxfs/xfs_errortag.h b/fs/xfs/libxfs/xfs_errortag.h
index f0c83f1f0b3b..d14aa289699f 100644
--- a/fs/xfs/libxfs/xfs_errortag.h
+++ b/fs/xfs/libxfs/xfs_errortag.h
@@ -75,7 +75,8 @@
#define XFS_ERRTAG_METAFILE_RESV_CRITICAL 45
#define XFS_ERRTAG_FORCE_ZERO_RANGE 46
#define XFS_ERRTAG_ZONE_RESET 47
-#define XFS_ERRTAG_MAX 48
+#define XFS_ERRTAG_BOUNCE_REREAD 48
+#define XFS_ERRTAG_MAX 49
/*
* Random factors for above tags, 1 means always, 2 means 1/2 time, etc.
@@ -137,7 +138,8 @@ XFS_ERRTAG(WRITE_DELAY_MS, write_delay_ms, 3000) \
XFS_ERRTAG(EXCHMAPS_FINISH_ONE, exchmaps_finish_one, 1) \
XFS_ERRTAG(METAFILE_RESV_CRITICAL, metafile_resv_crit, 4) \
XFS_ERRTAG(FORCE_ZERO_RANGE, force_zero_range, 4) \
-XFS_ERRTAG(ZONE_RESET, zone_reset, 1)
+XFS_ERRTAG(ZONE_RESET, zone_reset, 1) \
+XFS_ERRTAG(BOUNCE_REREAD, bounce_reread, XFS_RANDOM_DEFAULT)
#endif /* XFS_ERRTAG */
#endif /* __XFS_ERRORTAG_H_ */
diff --git a/fs/xfs/libxfs/xfs_inode_util.h b/fs/xfs/libxfs/xfs_inode_util.h
index 060242998a23..e9eac35159c3 100644
--- a/fs/xfs/libxfs/xfs_inode_util.h
+++ b/fs/xfs/libxfs/xfs_inode_util.h
@@ -27,7 +27,7 @@ prid_t xfs_get_initial_prid(struct xfs_inode *dp);
* idmap to NULL. To create a tree root, set pip to NULL.
*/
struct xfs_icreate_args {
- struct mnt_idmap *idmap;
+ const struct mnt_idmap *idmap;
struct xfs_inode *pip; /* parent inode or null */
dev_t rdev;
umode_t mode;
diff --git a/fs/xfs/xfs_acl.c b/fs/xfs/xfs_acl.c
index fdfca6fc75b6..20d87b52c4fc 100644
--- a/fs/xfs/xfs_acl.c
+++ b/fs/xfs/xfs_acl.c
@@ -243,7 +243,7 @@ xfs_acl_set_mode(
}
int
-xfs_set_acl(struct mnt_idmap *idmap, struct dentry *dentry,
+xfs_set_acl(const struct mnt_idmap *idmap, struct dentry *dentry,
struct posix_acl *acl, int type)
{
umode_t mode;
diff --git a/fs/xfs/xfs_acl.h b/fs/xfs/xfs_acl.h
index bf7f960997d3..183526bec32c 100644
--- a/fs/xfs/xfs_acl.h
+++ b/fs/xfs/xfs_acl.h
@@ -11,7 +11,7 @@ struct posix_acl;
#ifdef CONFIG_XFS_POSIX_ACL
extern struct posix_acl *xfs_get_acl(struct inode *inode, int type, bool rcu);
-extern int xfs_set_acl(struct mnt_idmap *idmap, struct dentry *dentry,
+extern int xfs_set_acl(const struct mnt_idmap *idmap, struct dentry *dentry,
struct posix_acl *acl, int type);
extern int __xfs_set_acl(struct inode *inode, struct posix_acl *acl, int type);
void xfs_forget_acl(struct inode *inode, const char *name);
diff --git a/fs/xfs/xfs_aops.c b/fs/xfs/xfs_aops.c
index 8b6119776fb3..c30e688cfc9f 100644
--- a/fs/xfs/xfs_aops.c
+++ b/fs/xfs/xfs_aops.c
@@ -23,7 +23,6 @@
#include "xfs_ioend.h"
#include "xfs_zone_alloc.h"
#include "xfs_rtgroup.h"
-#include <linux/bio-integrity.h>
struct xfs_writepage_ctx {
struct iomap_writepage_ctx ctx;
@@ -498,8 +497,7 @@ xfs_zoned_writeback_submit(
bio_endio(&ioend->io_bio);
return error;
}
- if (wpc->iomap.flags & IOMAP_F_INTEGRITY)
- fs_bio_integrity_generate(&ioend->io_bio);
+
xfs_zone_alloc_and_submit(ioend, &XFS_ZWPC(wpc)->open_zone);
return 0;
}
@@ -585,11 +583,10 @@ xfs_bio_submit_read(
const struct iomap_iter *iter,
struct iomap_read_folio_ctx *ctx)
{
- struct bio *bio = ctx->read_ctx;
-
- /* defer read completions to the ioend workqueue */
- iomap_init_ioend(iter->inode, bio, ctx->read_ctx_file_offset, 0);
- iomap_bio_submit_read_endio(iter, ctx, xfs_end_bio);
+ xfs_ioend_submit_read(iter->inode, ctx->read_ctx,
+ ctx->read_ctx_file_offset,
+ iomap_ioend_flags(&iter->iomap));
+ ctx->read_ctx = NULL;
}
static const struct iomap_read_ops xfs_iomap_read_ops = {
diff --git a/fs/xfs/xfs_buf.c b/fs/xfs/xfs_buf.c
index 8256c1d13ce2..6c93b4f5629c 100644
--- a/fs/xfs/xfs_buf.c
+++ b/fs/xfs/xfs_buf.c
@@ -5,6 +5,7 @@
*/
#include "xfs_platform.h"
#include <linux/backing-dev.h>
+#include <linux/blk-integrity.h>
#include <linux/dax.h>
#include "xfs_shared.h"
@@ -1694,6 +1695,7 @@ xfs_configure_buftarg(
struct xfs_mount *mp = btp->bt_mount;
if (btp->bt_bdev) {
+ struct blk_integrity *bi = bdev_get_integrity(btp->bt_bdev);
int error;
error = bdev_validate_blocksize(btp->bt_bdev, sectorsize);
@@ -1706,6 +1708,15 @@ xfs_configure_buftarg(
if (bdev_can_atomic_write(btp->bt_bdev))
xfs_configure_buftarg_atomic_writes(btp);
+
+ if (!bi)
+ ;
+ else if (btp->bt_bdev == btp->bt_mount->m_super->s_bdev)
+ xfs_info(mp, "using %s integrity profile",
+ blk_integrity_profile_name(bi));
+ else
+ xfs_info(mp, "using %s integrity profile for %pg",
+ blk_integrity_profile_name(bi), btp->bt_bdev);
}
btp->bt_meta_sectorsize = sectorsize;
diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c
index dd6d2e08faff..d164de6ff98b 100644
--- a/fs/xfs/xfs_file.c
+++ b/fs/xfs/xfs_file.c
@@ -37,6 +37,7 @@
#include <linux/fadvise.h>
#include <linux/mount.h>
#include <linux/filelock.h>
+#include <linux/bio-integrity.h>
static const struct vm_operations_struct xfs_file_vm_ops;
@@ -222,9 +223,8 @@ xfs_dio_read_bounce_submit_io(
struct bio *bio,
loff_t file_offset)
{
- iomap_init_ioend(iter->inode, bio, file_offset, IOMAP_IOEND_DIRECT);
- bio->bi_end_io = xfs_end_bio;
- submit_bio(bio);
+ xfs_ioend_submit_read(iter->inode, bio, file_offset,
+ iomap_ioend_flags(&iter->iomap) | IOMAP_IOEND_DIRECT);
}
static const struct iomap_dio_ops xfs_dio_read_bounce_ops = {
@@ -252,8 +252,7 @@ xfs_file_dio_read(
return ret;
if (mapping_stable_writes(iocb->ki_filp->f_mapping)) {
ret = iomap_dio_rw(iocb, to, &xfs_read_iomap_ops,
- &xfs_dio_read_bounce_ops, IOMAP_DIO_BOUNCE,
- NULL, 0);
+ &xfs_dio_read_bounce_ops, 0, NULL, 0);
} else {
ret = iomap_dio_read_simple(iocb, to, xfs_read_iomap_begin);
if (ret == -ENOTBLK)
@@ -713,7 +712,7 @@ xfs_dio_zoned_submit_io(
bio->bi_end_io = xfs_end_bio;
ioend = iomap_init_ioend(iter->inode, bio, file_offset,
- IOMAP_IOEND_DIRECT);
+ iomap_ioend_flags(&iter->iomap) | IOMAP_IOEND_DIRECT);
xfs_zone_alloc_and_submit(ioend, &ac->open_zone);
}
diff --git a/fs/xfs/xfs_handle.c b/fs/xfs/xfs_handle.c
index fd9d4d8258ff..4924e676ae91 100644
--- a/fs/xfs/xfs_handle.c
+++ b/fs/xfs/xfs_handle.c
@@ -272,11 +272,11 @@ xfs_open_by_handle(
path.mnt = mntget(parfilp->f_path.mnt);
FD_PREPARE(fdf, 0, dentry_open(&path, hreq->oflags, cred));
- if (fdf.err)
- return fdf.err;
+ if (fdf->fd < 0)
+ return fdf->fd;
if (S_ISREG(inode->i_mode)) {
- struct file *filp = fd_prepare_file(fdf);
+ struct file *filp = fdf->file;
filp->f_flags |= O_NOATIME;
filp->f_mode |= FMODE_NOCMTIME;
diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c
index 15b62574b8d4..05a14da28031 100644
--- a/fs/xfs/xfs_inode.c
+++ b/fs/xfs/xfs_inode.c
@@ -2084,7 +2084,7 @@ xfs_sort_inodes(
*/
static int
xfs_rename_alloc_whiteout(
- struct mnt_idmap *idmap,
+ const struct mnt_idmap *idmap,
struct xfs_name *src_name,
struct xfs_inode *dp,
struct xfs_inode **wip)
@@ -2130,7 +2130,7 @@ xfs_rename_alloc_whiteout(
*/
int
xfs_rename(
- struct mnt_idmap *idmap,
+ const struct mnt_idmap *idmap,
struct xfs_inode *src_dp,
struct xfs_name *src_name,
struct xfs_inode *src_ip,
diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h
index 1602027cd0aa..ca96ba096359 100644
--- a/fs/xfs/xfs_inode.h
+++ b/fs/xfs/xfs_inode.h
@@ -568,7 +568,7 @@ int xfs_remove(struct xfs_inode *dp, struct xfs_name *name,
struct xfs_inode *ip);
int xfs_link(struct xfs_inode *tdp, struct xfs_inode *sip,
struct xfs_name *target_name);
-int xfs_rename(struct mnt_idmap *idmap,
+int xfs_rename(const struct mnt_idmap *idmap,
struct xfs_inode *src_dp, struct xfs_name *src_name,
struct xfs_inode *src_ip, struct xfs_inode *target_dp,
struct xfs_name *target_name,
diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c
index c0fc9b34f393..f81b6e52ac40 100644
--- a/fs/xfs/xfs_ioctl.c
+++ b/fs/xfs/xfs_ioctl.c
@@ -748,7 +748,7 @@ xfs_ioctl_setattr_check_projid(
int
xfs_fileattr_set(
- struct mnt_idmap *idmap,
+ const struct mnt_idmap *idmap,
struct dentry *dentry,
struct file_kattr *fa)
{
diff --git a/fs/xfs/xfs_ioctl.h b/fs/xfs/xfs_ioctl.h
index e57d8f5148bf..6e55cc847654 100644
--- a/fs/xfs/xfs_ioctl.h
+++ b/fs/xfs/xfs_ioctl.h
@@ -19,7 +19,7 @@ xfs_fileattr_get(
extern int
xfs_fileattr_set(
- struct mnt_idmap *idmap,
+ const struct mnt_idmap *idmap,
struct dentry *dentry,
struct file_kattr *fa);
diff --git a/fs/xfs/xfs_ioend.c b/fs/xfs/xfs_ioend.c
index 40695d18dac0..e70be5b86f0b 100644
--- a/fs/xfs/xfs_ioend.c
+++ b/fs/xfs/xfs_ioend.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0
/*
- * Copyright (c) 2016-2025 Christoph Hellwig.
+ * Copyright (c) 2016-2026 Christoph Hellwig.
* All Rights Reserved.
*/
#include "xfs_platform.h"
@@ -16,6 +16,135 @@
#include "xfs_reflink.h"
#include "xfs_zone_alloc.h"
#include "xfs_ioend.h"
+#include "xfs_error.h"
+#include "xfs_errortag.h"
+#include <linux/bio-integrity.h>
+
+static void
+xfs_dio_bounce_end_io(
+ struct bio *bio)
+{
+ struct iomap_ioend *ioend = iomap_ioend_from_bio(bio);
+ int error = blk_status_to_errno(bio->bi_status);
+ struct bio *orig_bio = bio->bi_private;
+
+ if ((ioend->io_flags & IOMAP_IOEND_INTEGRITY) && !bio->bi_status)
+ error = iomap_ioend_integrity_verify(ioend);
+ iomap_bounce_read_end_io(ioend, orig_bio, error);
+}
+
+static void
+xfs_bounce_submit_ioend(
+ struct iomap_ioend *ioend)
+{
+ if (ioend->io_flags & IOMAP_IOEND_INTEGRITY)
+ fs_bio_integrity_alloc(&ioend->io_bio);
+ ioend->io_bio.bi_end_io = xfs_dio_bounce_end_io;
+ bio_set_flag(&ioend->io_bio, BIO_COMPLETE_IN_TASK);
+ submit_bio(&ioend->io_bio);
+}
+
+static void
+xfs_end_bio_bounced(
+ struct bio *bio)
+{
+ /*
+ * Just complete the original ioends as all verification is done by the
+ * end_io handlers for the clone bio(s).
+ */
+ iomap_finish_ioends(iomap_ioend_from_bio(bio),
+ blk_status_to_errno(bio->bi_status));
+}
+
+static void
+xfs_read_bounce_and_resubmit(
+ struct iomap_ioend *ioend)
+{
+ struct bio *bio = &ioend->io_bio;
+ struct xfs_inode *ip = XFS_I(ioend->io_inode);
+ unsigned int nofs_flag = memalloc_nofs_save();
+
+ trace_xfs_bounce_reread(ip, ioend->io_offset, ioend->io_size);
+
+ /*
+ * Free the bio integrity data for the original bio, as we'll allocate
+ * a new one for each sub-I/O, which could deadlock if we keep the
+ * integrity data for the original bio around.
+ */
+ if (bio_integrity(bio))
+ fs_bio_integrity_free(bio);
+
+ /*
+ * Resubmit the bio through the iomap bounce machinery. The original
+ * bio itself is not resubmitted to the block layer, but just used to
+ * track I/O completion of the cloned bios.
+ */
+ bio_prepare_reissue(bio, xfs_inode_buftarg(ip)->bt_bdev);
+ bio->bi_iter = (struct bvec_iter) {
+ .bi_sector = ioend->io_sector,
+ .bi_size = ioend->io_size,
+ .bi_offset = ioend->io_bvec_offset,
+ };
+ bio->bi_end_io = xfs_end_bio_bounced;
+ iomap_bounce_read(ioend, bdev_logical_block_size(bio->bi_bdev),
+ xfs_bounce_submit_ioend);
+ memalloc_nofs_restore(nofs_flag);
+}
+
+static void
+xfs_end_io_read(
+ struct bio *bio)
+{
+ struct iomap_ioend *ioend = iomap_ioend_from_bio(bio);
+ struct xfs_inode *ip = XFS_I(ioend->io_inode);
+ struct xfs_mount *mp = ip->i_mount;
+ int error = blk_status_to_errno(bio->bi_status);
+
+ if (!error && (ioend->io_flags & IOMAP_IOEND_INTEGRITY)) {
+ error = iomap_ioend_integrity_verify(ioend);
+ if ((ioend->io_flags & IOMAP_IOEND_DIRECT) &&
+ READ_ONCE(mp->m_read_bounce) == XFS_READ_BOUNCE_LAZY) {
+ /*
+ * We only really need to retry for guard tag errors,
+ * but right now we can't distinguish them from other
+ * (i.e, reftag) errors.
+ */
+ if (error ||
+ XFS_TEST_ERROR(mp, XFS_ERRTAG_BOUNCE_REREAD)) {
+ xfs_read_bounce_and_resubmit(ioend);
+ return;
+ }
+ }
+ }
+
+ iomap_finish_ioends(ioend, error);
+}
+
+void
+xfs_ioend_submit_read(
+ struct inode *inode,
+ struct bio *bio,
+ loff_t file_offset,
+ u16 ioend_flags)
+{
+ struct xfs_inode *ip = XFS_I(inode);
+ struct xfs_mount *mp = ip->i_mount;
+ struct iomap_ioend *ioend;
+
+ ioend = iomap_init_ioend(inode, bio, file_offset, ioend_flags);
+ if ((ioend_flags & IOMAP_IOEND_DIRECT) &&
+ READ_ONCE(mp->m_read_bounce) == XFS_READ_BOUNCE_ALWAYS) {
+ iomap_bounce_read(ioend, bdev_logical_block_size(bio->bi_bdev),
+ xfs_bounce_submit_ioend);
+ return;
+ }
+
+ if (ioend_flags & IOMAP_IOEND_INTEGRITY)
+ fs_bio_integrity_alloc(bio);
+ bio->bi_end_io = xfs_end_io_read;
+ bio_set_flag(bio, BIO_COMPLETE_IN_TASK);
+ submit_bio(bio);
+}
static void
xfs_ioend_put_open_zones(
@@ -148,11 +277,7 @@ xfs_end_io(
io_list))) {
list_del_init(&ioend->io_list);
iomap_ioend_try_merge(ioend, &tmp);
- if (bio_op(&ioend->io_bio) == REQ_OP_READ)
- iomap_finish_ioends(ioend,
- blk_status_to_errno(ioend->io_bio.bi_status));
- else
- xfs_end_ioend_write(ioend);
+ xfs_end_ioend_write(ioend);
cond_resched();
}
}
diff --git a/fs/xfs/xfs_ioend.h b/fs/xfs/xfs_ioend.h
index 525865767fca..7c2a1ea3e6ed 100644
--- a/fs/xfs/xfs_ioend.h
+++ b/fs/xfs/xfs_ioend.h
@@ -12,5 +12,7 @@ static inline bool xfs_ioend_is_append(struct iomap_ioend *ioend)
}
void xfs_end_bio(struct bio *bio);
+void xfs_ioend_submit_read(struct inode *inode, struct bio *bio,
+ loff_t file_offset, u16 ioend_flags);
#endif /* __XFS_IOEND_H */
diff --git a/fs/xfs/xfs_iops.c b/fs/xfs/xfs_iops.c
index d1306e723899..f67a541ef35a 100644
--- a/fs/xfs/xfs_iops.c
+++ b/fs/xfs/xfs_iops.c
@@ -169,7 +169,7 @@ xfs_create_need_xattr(
STATIC int
xfs_generic_create(
- struct mnt_idmap *idmap,
+ const struct mnt_idmap *idmap,
struct inode *dir,
struct dentry *dentry,
umode_t mode,
@@ -279,7 +279,7 @@ xfs_generic_create(
STATIC int
xfs_vn_mknod(
- struct mnt_idmap *idmap,
+ const struct mnt_idmap *idmap,
struct inode *dir,
struct dentry *dentry,
umode_t mode,
@@ -290,7 +290,7 @@ xfs_vn_mknod(
STATIC int
xfs_vn_create(
- struct mnt_idmap *idmap,
+ const struct mnt_idmap *idmap,
struct inode *dir,
struct dentry *dentry,
umode_t mode)
@@ -300,7 +300,7 @@ xfs_vn_create(
STATIC struct dentry *
xfs_vn_mkdir(
- struct mnt_idmap *idmap,
+ const struct mnt_idmap *idmap,
struct inode *dir,
struct dentry *dentry,
umode_t mode)
@@ -425,7 +425,7 @@ xfs_vn_unlink(
STATIC int
xfs_vn_symlink(
- struct mnt_idmap *idmap,
+ const struct mnt_idmap *idmap,
struct inode *dir,
struct dentry *dentry,
const char *symname)
@@ -466,7 +466,7 @@ xfs_vn_symlink(
STATIC int
xfs_vn_rename(
- struct mnt_idmap *idmap,
+ const struct mnt_idmap *idmap,
struct inode *odir,
struct dentry *odentry,
struct inode *ndir,
@@ -679,7 +679,7 @@ xfs_report_atomic_write(
STATIC int
xfs_vn_getattr(
- struct mnt_idmap *idmap,
+ const struct mnt_idmap *idmap,
const struct path *path,
struct kstat *stat,
u32 request_mask,
@@ -754,7 +754,7 @@ xfs_vn_getattr(
static int
xfs_vn_change_ok(
- struct mnt_idmap *idmap,
+ const struct mnt_idmap *idmap,
struct dentry *dentry,
struct iattr *iattr)
{
@@ -777,7 +777,7 @@ xfs_vn_change_ok(
*/
static int
xfs_setattr_nonsize(
- struct mnt_idmap *idmap,
+ const struct mnt_idmap *idmap,
struct dentry *dentry,
struct xfs_inode *ip,
struct iattr *iattr)
@@ -903,7 +903,7 @@ out_dqrele:
*/
int
xfs_vn_setattr_size(
- struct mnt_idmap *idmap,
+ const struct mnt_idmap *idmap,
struct dentry *dentry,
struct iattr *iattr)
{
@@ -1130,7 +1130,7 @@ out_trans_cancel:
STATIC int
xfs_vn_setattr(
- struct mnt_idmap *idmap,
+ const struct mnt_idmap *idmap,
struct dentry *dentry,
struct iattr *iattr)
{
@@ -1250,7 +1250,7 @@ xfs_vn_fiemap(
STATIC int
xfs_vn_tmpfile(
- struct mnt_idmap *idmap,
+ const struct mnt_idmap *idmap,
struct inode *dir,
struct file *file,
umode_t mode)
diff --git a/fs/xfs/xfs_iops.h b/fs/xfs/xfs_iops.h
index 0896f6b8b3b8..328305bba19d 100644
--- a/fs/xfs/xfs_iops.h
+++ b/fs/xfs/xfs_iops.h
@@ -10,7 +10,7 @@ struct xfs_inode;
extern ssize_t xfs_vn_listxattr(struct dentry *, char *data, size_t size);
-int xfs_vn_setattr_size(struct mnt_idmap *idmap,
+int xfs_vn_setattr_size(const struct mnt_idmap *idmap,
struct dentry *dentry, struct iattr *vap);
int xfs_inode_init_security(struct inode *inode, struct inode *dir,
diff --git a/fs/xfs/xfs_itable.c b/fs/xfs/xfs_itable.c
index 159295c63e8f..a4cf1effa5e6 100644
--- a/fs/xfs/xfs_itable.c
+++ b/fs/xfs/xfs_itable.c
@@ -63,7 +63,7 @@ want_metadir_file(
STATIC int
xfs_bulkstat_one_int(
struct xfs_mount *mp,
- struct mnt_idmap *idmap,
+ const struct mnt_idmap *idmap,
struct xfs_trans *tp,
xfs_ino_t ino,
struct xfs_bstat_chunk *bc)
diff --git a/fs/xfs/xfs_itable.h b/fs/xfs/xfs_itable.h
index 2d0612f14d6e..c0567bfc30fb 100644
--- a/fs/xfs/xfs_itable.h
+++ b/fs/xfs/xfs_itable.h
@@ -8,7 +8,7 @@
/* In-memory representation of a userspace request for batch inode data. */
struct xfs_ibulk {
struct xfs_mount *mp;
- struct mnt_idmap *idmap;
+ const struct mnt_idmap *idmap;
void __user *ubuffer; /* user output buffer */
xfs_ino_t startino; /* start with this inode */
unsigned int icount; /* number of elements in ubuffer */
diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h
index 216a38a354e7..894ff2f4ecbd 100644
--- a/fs/xfs/xfs_mount.h
+++ b/fs/xfs/xfs_mount.h
@@ -142,6 +142,12 @@ struct xfs_freecounter {
uint64_t res_saved;
};
+enum xfs_read_bounce {
+ XFS_READ_BOUNCE_NEVER,
+ XFS_READ_BOUNCE_ALWAYS,
+ XFS_READ_BOUNCE_LAZY,
+};
+
/*
* The struct xfsmount layout is optimised to separate read-mostly variables
* from variables that are frequently modified. We put the read-mostly variables
@@ -177,6 +183,7 @@ typedef struct xfs_mount {
struct workqueue_struct *m_sync_workqueue;
struct workqueue_struct *m_blockgc_wq;
struct workqueue_struct *m_inodegc_wq;
+ enum xfs_read_bounce m_read_bounce;
int m_bsize; /* fs logical block size */
uint8_t m_blkbit_log; /* blocklog + NBBY */
@@ -291,6 +298,7 @@ typedef struct xfs_mount {
struct xfs_zone_info *m_zone_info; /* zone allocator information */
struct dentry *m_debugfs; /* debugfs parent */
struct xfs_kobj m_kobj;
+ struct xfs_kobj m_csum_kobj;
struct xfs_kobj m_error_kobj;
struct xfs_kobj m_error_meta_kobj;
struct xfs_error_cfg m_error_cfg[XFS_ERR_CLASS_MAX][XFS_ERR_ERRNO_MAX];
diff --git a/fs/xfs/xfs_super.c b/fs/xfs/xfs_super.c
index 2edc2a497883..5a06132aa384 100644
--- a/fs/xfs/xfs_super.c
+++ b/fs/xfs/xfs_super.c
@@ -2317,6 +2317,7 @@ xfs_init_fs_context(
mp->m_logbufs = -1;
mp->m_logbsize = -1;
mp->m_allocsize_log = 16; /* 64k */
+ mp->m_read_bounce = XFS_READ_BOUNCE_LAZY;
xfs_hooks_init(&mp->m_dir_update_hooks);
diff --git a/fs/xfs/xfs_symlink.c b/fs/xfs/xfs_symlink.c
index cc13819df6f2..709cd22248f8 100644
--- a/fs/xfs/xfs_symlink.c
+++ b/fs/xfs/xfs_symlink.c
@@ -82,7 +82,7 @@ xfs_readlink(
int
xfs_symlink(
- struct mnt_idmap *idmap,
+ const struct mnt_idmap *idmap,
struct xfs_inode *dp,
struct xfs_name *link_name,
const char *target_path,
diff --git a/fs/xfs/xfs_symlink.h b/fs/xfs/xfs_symlink.h
index 0d29a50e66fd..3c5a969f9fc5 100644
--- a/fs/xfs/xfs_symlink.h
+++ b/fs/xfs/xfs_symlink.h
@@ -7,7 +7,7 @@
/* Kernel only symlink definitions */
-int xfs_symlink(struct mnt_idmap *idmap, struct xfs_inode *dp,
+int xfs_symlink(const struct mnt_idmap *idmap, struct xfs_inode *dp,
struct xfs_name *link_name, const char *target_path,
umode_t mode, struct xfs_inode **ipp);
int xfs_readlink(struct xfs_inode *ip, char *link);
diff --git a/fs/xfs/xfs_sysfs.c b/fs/xfs/xfs_sysfs.c
index b62712187324..e77917ac179d 100644
--- a/fs/xfs/xfs_sysfs.c
+++ b/fs/xfs/xfs_sysfs.c
@@ -392,6 +392,71 @@ const struct kobj_type xfs_stats_ktype = {
.default_groups = xfs_stats_groups,
};
+static inline struct xfs_mount *csum_to_mp(struct kobject *kobj)
+{
+ return container_of(to_kobj(kobj), struct xfs_mount, m_csum_kobj);
+}
+
+static bool
+xfs_has_read_bounce(
+ struct xfs_mount *mp)
+{
+ if (bdev_has_integrity_csum(mp->m_ddev_targp->bt_bdev))
+ return true;
+ if (mp->m_rtdev_targp &&
+ bdev_has_integrity_csum(mp->m_rtdev_targp->bt_bdev))
+ return true;
+ return false;
+}
+
+static const char * const bounce_modes[] = {
+ [XFS_READ_BOUNCE_NEVER] = "never",
+ [XFS_READ_BOUNCE_ALWAYS] = "always",
+ [XFS_READ_BOUNCE_LAZY] = "lazy",
+};
+
+static ssize_t
+read_bounce_show(
+ struct kobject *kobj,
+ char *buf)
+{
+ struct xfs_mount *mp = csum_to_mp(kobj);
+
+ return sysfs_emit(buf, "%s\n",
+ bounce_modes[READ_ONCE(mp->m_read_bounce)]);
+}
+
+static ssize_t
+read_bounce_store(
+ struct kobject *kobj,
+ const char *buf,
+ size_t count)
+{
+ struct xfs_mount *mp = csum_to_mp(kobj);
+ int ret;
+
+ if (!xfs_has_read_bounce(mp))
+ return -EINVAL;
+ ret = sysfs_match_string(bounce_modes, buf);
+ if (ret < 0)
+ return ret;
+ WRITE_ONCE(mp->m_read_bounce, ret);
+ return count;
+}
+XFS_SYSFS_ATTR_RW(read_bounce);
+
+static struct attribute *xfs_csum_attrs[] = {
+ ATTR_LIST(read_bounce),
+ NULL,
+};
+ATTRIBUTE_GROUPS(xfs_csum);
+
+static const struct kobj_type xfs_csum_ktype = {
+ .release = xfs_sysfs_release,
+ .sysfs_ops = &xfs_sysfs_ops,
+ .default_groups = xfs_csum_groups,
+};
+
/* xlog */
static inline struct xlog *
@@ -817,11 +882,17 @@ xfs_mount_sysfs_init(
if (error)
goto out_remove_fsdir;
+ /* .../xfs/<dev>/csum/ */
+ error = xfs_sysfs_init(&mp->m_csum_kobj, &xfs_csum_ktype, &mp->m_kobj,
+ "csum");
+ if (error)
+ goto out_remove_stats_dir;
+
/* .../xfs/<dev>/error/ */
error = xfs_sysfs_init(&mp->m_error_kobj, &xfs_error_ktype,
&mp->m_kobj, "error");
if (error)
- goto out_remove_stats_dir;
+ goto out_remove_csum_dir;
/* .../xfs/<dev>/error/fail_at_unmount */
error = sysfs_create_file(&mp->m_error_kobj.kobject,
@@ -835,12 +906,14 @@ xfs_mount_sysfs_init(
"metadata", &mp->m_error_meta_kobj,
xfs_error_meta_init);
if (error)
- goto out_remove_error_dir;
+ goto out_remove_csum_dir;
return 0;
out_remove_error_dir:
xfs_sysfs_del(&mp->m_error_kobj);
+out_remove_csum_dir:
+ xfs_sysfs_del(&mp->m_csum_kobj);
out_remove_stats_dir:
xfs_sysfs_del(&mp->m_stats.xs_kobj);
out_remove_fsdir:
@@ -864,6 +937,7 @@ xfs_mount_sysfs_del(
}
xfs_sysfs_del(&mp->m_error_meta_kobj);
xfs_sysfs_del(&mp->m_error_kobj);
+ xfs_sysfs_del(&mp->m_csum_kobj);
xfs_sysfs_del(&mp->m_stats.xs_kobj);
xfs_sysfs_del(&mp->m_kobj);
}
diff --git a/fs/xfs/xfs_trace.h b/fs/xfs/xfs_trace.h
index 0fc8927339b5..28d49f158b22 100644
--- a/fs/xfs/xfs_trace.h
+++ b/fs/xfs/xfs_trace.h
@@ -1896,6 +1896,7 @@ DEFINE_SIMPLE_IO_EVENT(xfs_zero_eof);
DEFINE_SIMPLE_IO_EVENT(xfs_end_io_direct_write);
DEFINE_SIMPLE_IO_EVENT(xfs_file_splice_read);
DEFINE_SIMPLE_IO_EVENT(xfs_zoned_map_blocks);
+DEFINE_SIMPLE_IO_EVENT(xfs_bounce_reread);
DECLARE_EVENT_CLASS(xfs_itrunc_class,
TP_PROTO(struct xfs_inode *ip, xfs_fsize_t new_size),
diff --git a/fs/xfs/xfs_xattr.c b/fs/xfs/xfs_xattr.c
index 1efe6c8139b2..b059a9714d11 100644
--- a/fs/xfs/xfs_xattr.c
+++ b/fs/xfs/xfs_xattr.c
@@ -169,7 +169,7 @@ xfs_xattr_flags_to_op(
static int
xfs_xattr_set(const struct xattr_handler *handler,
- struct mnt_idmap *idmap, struct dentry *unused,
+ const struct mnt_idmap *idmap, struct dentry *unused,
struct inode *inode, const char *name, const void *value,
size_t size, int flags)
{
diff --git a/fs/xfs/xfs_zone_alloc.c b/fs/xfs/xfs_zone_alloc.c
index b75cf3bfe33c..5f0af0c2c5e5 100644
--- a/fs/xfs/xfs_zone_alloc.c
+++ b/fs/xfs/xfs_zone_alloc.c
@@ -26,6 +26,7 @@
#include "xfs_zones.h"
#include "xfs_trace.h"
#include "xfs_mru_cache.h"
+#include <linux/bio-integrity.h>
static void
xfs_open_zone_free_rcu(
@@ -911,6 +912,9 @@ xfs_zone_alloc_and_submit(
if (xfs_is_shutdown(mp))
goto out_error;
+ if (ioend->io_flags & IOMAP_IOEND_INTEGRITY)
+ fs_bio_integrity_generate(&ioend->io_bio);
+
/*
* If we don't have a locally cached zone in this write context, see if
* the inode is still associated with a zone and use that if so.