summaryrefslogtreecommitdiff
path: root/fs
diff options
context:
space:
mode:
authorMark Brown <broonie@kernel.org>2026-01-28 11:22:06 +0000
committerMark Brown <broonie@kernel.org>2026-01-28 11:22:06 +0000
commit751ec6dd6773237bf480291ca894a696a2991c62 (patch)
tree6ac1b53826f7836b3f7b29f3f17bb45d118535c0 /fs
parente540be7d56d740144b1bd6f220b61ffe2f3830d4 (diff)
parent04f7516ab70f7b82aae1d2830af2ee6f17f3fe98 (diff)
spi: aspeed: Improve handling of shared SPI
Merge series from Chin-Ting Kuo <chin-ting_kuo@aspeedtech.com>: This patch series improves handling of SPI controllers that are shared by spi-mem devices and other SPI peripherals. The primary goal of this series is to support non-spi-mem devices in the ASPEED FMC/SPI controller driver. It also addresses an issue in the spi-mem framework observed when different types of SPI devices operate concurrently on the same controller, ensuring that spi-mem operations are properly serialized.
Diffstat (limited to 'fs')
-rw-r--r--fs/btrfs/disk-io.c19
-rw-r--r--fs/btrfs/fs.h8
-rw-r--r--fs/btrfs/tree-log.c2
-rw-r--r--fs/btrfs/volumes.c42
-rw-r--r--fs/btrfs/volumes.h4
-rw-r--r--fs/fs-writeback.c7
-rw-r--r--fs/fuse/file.c4
-rw-r--r--fs/smb/server/transport_rdma.c16
-rw-r--r--fs/smb/server/vfs.c2
9 files changed, 91 insertions, 13 deletions
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index d8ca5b6e88e0..89022e9f393b 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -1661,7 +1661,7 @@ static void backup_super_roots(struct btrfs_fs_info *info)
btrfs_set_backup_chunk_root_level(root_backup,
btrfs_header_level(info->chunk_root->node));
- if (!btrfs_fs_compat_ro(info, BLOCK_GROUP_TREE)) {
+ if (!btrfs_fs_incompat(info, EXTENT_TREE_V2)) {
struct btrfs_root *extent_root = btrfs_extent_root(info, 0);
struct btrfs_root *csum_root = btrfs_csum_root(info, 0);
@@ -3255,6 +3255,15 @@ int btrfs_check_features(struct btrfs_fs_info *fs_info, bool is_rw_mount)
return 0;
}
+static bool fs_is_full_ro(const struct btrfs_fs_info *fs_info)
+{
+ if (!sb_rdonly(fs_info->sb))
+ return false;
+ if (unlikely(fs_info->mount_opt & BTRFS_MOUNT_FULL_RO_MASK))
+ return true;
+ return false;
+}
+
int __cold open_ctree(struct super_block *sb, struct btrfs_fs_devices *fs_devices)
{
u32 sectorsize;
@@ -3363,6 +3372,10 @@ int __cold open_ctree(struct super_block *sb, struct btrfs_fs_devices *fs_device
if (btrfs_super_flags(disk_super) & BTRFS_SUPER_FLAG_ERROR)
WRITE_ONCE(fs_info->fs_error, -EUCLEAN);
+ /* If the fs has any rescue options, no transaction is allowed. */
+ if (fs_is_full_ro(fs_info))
+ WRITE_ONCE(fs_info->fs_error, -EROFS);
+
/* Set up fs_info before parsing mount options */
nodesize = btrfs_super_nodesize(disk_super);
sectorsize = btrfs_super_sectorsize(disk_super);
@@ -3489,6 +3502,10 @@ int __cold open_ctree(struct super_block *sb, struct btrfs_fs_devices *fs_device
fs_info->generation == btrfs_super_uuid_tree_generation(disk_super))
set_bit(BTRFS_FS_UPDATE_UUID_TREE_GEN, &fs_info->flags);
+ if (unlikely(btrfs_verify_dev_items(fs_info))) {
+ ret = -EUCLEAN;
+ goto fail_block_groups;
+ }
ret = btrfs_verify_dev_extents(fs_info);
if (ret) {
btrfs_err(fs_info,
diff --git a/fs/btrfs/fs.h b/fs/btrfs/fs.h
index 0f7e1ef27891..8ffbc40ebe45 100644
--- a/fs/btrfs/fs.h
+++ b/fs/btrfs/fs.h
@@ -264,6 +264,14 @@ enum {
BTRFS_MOUNT_REF_TRACKER = (1ULL << 33),
};
+/* These mount options require a full read-only fs, no new transaction is allowed. */
+#define BTRFS_MOUNT_FULL_RO_MASK \
+ (BTRFS_MOUNT_NOLOGREPLAY | \
+ BTRFS_MOUNT_IGNOREBADROOTS | \
+ BTRFS_MOUNT_IGNOREDATACSUMS | \
+ BTRFS_MOUNT_IGNOREMETACSUMS | \
+ BTRFS_MOUNT_IGNORESUPERFLAGS)
+
/*
* Compat flags that we support. If any incompat flags are set other than the
* ones specified below then we will fail to mount
diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c
index 2d9d38b82daa..6cffcf0c3e7a 100644
--- a/fs/btrfs/tree-log.c
+++ b/fs/btrfs/tree-log.c
@@ -2798,7 +2798,7 @@ static int replay_one_buffer(struct extent_buffer *eb,
nritems = btrfs_header_nritems(eb);
for (wc->log_slot = 0; wc->log_slot < nritems; wc->log_slot++) {
- struct btrfs_inode_item *inode_item;
+ struct btrfs_inode_item *inode_item = NULL;
btrfs_item_key_to_cpu(eb, &wc->log_key, wc->log_slot);
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
index 13c514684cfb..8a08412f3529 100644
--- a/fs/btrfs/volumes.c
+++ b/fs/btrfs/volumes.c
@@ -1364,7 +1364,9 @@ struct btrfs_super_block *btrfs_read_disk_super(struct block_device *bdev,
(bytenr + BTRFS_SUPER_INFO_SIZE) >> PAGE_SHIFT);
}
+ filemap_invalidate_lock(mapping);
page = read_cache_page_gfp(mapping, bytenr >> PAGE_SHIFT, GFP_NOFS);
+ filemap_invalidate_unlock(mapping);
if (IS_ERR(page))
return ERR_CAST(page);
@@ -7257,6 +7259,7 @@ static int read_one_dev(struct extent_buffer *leaf,
return -EINVAL;
}
}
+ set_bit(BTRFS_DEV_STATE_ITEM_FOUND, &device->dev_state);
set_bit(BTRFS_DEV_STATE_IN_FS_METADATA, &device->dev_state);
if (test_bit(BTRFS_DEV_STATE_WRITEABLE, &device->dev_state) &&
!test_bit(BTRFS_DEV_STATE_REPLACE_TGT, &device->dev_state)) {
@@ -8083,6 +8086,45 @@ int btrfs_verify_dev_extents(struct btrfs_fs_info *fs_info)
}
/*
+ * Ensure that all devices registered in the fs have their device items in the
+ * chunk tree.
+ *
+ * Return true if unexpected device is found.
+ * Return false otherwise.
+ */
+bool btrfs_verify_dev_items(const struct btrfs_fs_info *fs_info)
+{
+ struct btrfs_fs_devices *seed_devs;
+ struct btrfs_device *dev;
+ bool ret = false;
+
+ mutex_lock(&uuid_mutex);
+ list_for_each_entry(dev, &fs_info->fs_devices->devices, dev_list) {
+ if (!test_bit(BTRFS_DEV_STATE_ITEM_FOUND, &dev->dev_state)) {
+ btrfs_err(fs_info,
+ "devid %llu path %s is registered but not found in chunk tree",
+ dev->devid, btrfs_dev_name(dev));
+ ret = true;
+ }
+ }
+ list_for_each_entry(seed_devs, &fs_info->fs_devices->seed_list, seed_list) {
+ list_for_each_entry(dev, &seed_devs->devices, dev_list) {
+ if (!test_bit(BTRFS_DEV_STATE_ITEM_FOUND, &dev->dev_state)) {
+ btrfs_err(fs_info,
+ "devid %llu path %s is registered but not found in chunk tree",
+ dev->devid, btrfs_dev_name(dev));
+ ret = true;
+ }
+ }
+ }
+ mutex_unlock(&uuid_mutex);
+ if (ret)
+ btrfs_err(fs_info,
+"remove the above devices or use 'btrfs device scan --forget <dev>' to unregister them before mount");
+ return ret;
+}
+
+/*
* Check whether the given block group or device is pinned by any inode being
* used as a swapfile.
*/
diff --git a/fs/btrfs/volumes.h b/fs/btrfs/volumes.h
index 34b854c1a303..f20abeb16bce 100644
--- a/fs/btrfs/volumes.h
+++ b/fs/btrfs/volumes.h
@@ -100,6 +100,9 @@ enum btrfs_raid_types {
#define BTRFS_DEV_STATE_FLUSH_SENT (4)
#define BTRFS_DEV_STATE_NO_READA (5)
+/* Set when the device item is found in chunk tree, used to catch unexpected registered device. */
+#define BTRFS_DEV_STATE_ITEM_FOUND (7)
+
/* Special value encoding failure to write primary super block. */
#define BTRFS_SUPER_PRIMARY_WRITE_ERROR (INT_MAX / 2)
@@ -893,6 +896,7 @@ enum btrfs_raid_types __attribute_const__ btrfs_bg_flags_to_raid_index(u64 flags
int btrfs_bg_type_to_factor(u64 flags);
const char *btrfs_bg_type_to_raid_name(u64 flags);
int btrfs_verify_dev_extents(struct btrfs_fs_info *fs_info);
+bool btrfs_verify_dev_items(const struct btrfs_fs_info *fs_info);
bool btrfs_repair_one_zone(struct btrfs_fs_info *fs_info, u64 logical);
bool btrfs_pinned_by_swapfile(struct btrfs_fs_info *fs_info, void *ptr);
diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c
index 6800886c4d10..baa2f2141146 100644
--- a/fs/fs-writeback.c
+++ b/fs/fs-writeback.c
@@ -2750,8 +2750,13 @@ static void wait_sb_inodes(struct super_block *sb)
* The mapping can appear untagged while still on-list since we
* do not have the mapping lock. Skip it here, wb completion
* will remove it.
+ *
+ * If the mapping does not have data integrity semantics,
+ * there's no need to wait for the writeout to complete, as the
+ * mapping cannot guarantee that data is persistently stored.
*/
- if (!mapping_tagged(mapping, PAGECACHE_TAG_WRITEBACK))
+ if (!mapping_tagged(mapping, PAGECACHE_TAG_WRITEBACK) ||
+ mapping_no_data_integrity(mapping))
continue;
spin_unlock_irq(&sb->s_inode_wblist_lock);
diff --git a/fs/fuse/file.c b/fs/fuse/file.c
index 01bc894e9c2b..3b2a171e652f 100644
--- a/fs/fuse/file.c
+++ b/fs/fuse/file.c
@@ -3200,8 +3200,10 @@ void fuse_init_file_inode(struct inode *inode, unsigned int flags)
inode->i_fop = &fuse_file_operations;
inode->i_data.a_ops = &fuse_file_aops;
- if (fc->writeback_cache)
+ if (fc->writeback_cache) {
mapping_set_writeback_may_deadlock_on_reclaim(&inode->i_data);
+ mapping_set_no_data_integrity(&inode->i_data);
+ }
INIT_LIST_HEAD(&fi->write_files);
INIT_LIST_HEAD(&fi->queued_writes);
diff --git a/fs/smb/server/transport_rdma.c b/fs/smb/server/transport_rdma.c
index f585359684d4..e4273932e7e4 100644
--- a/fs/smb/server/transport_rdma.c
+++ b/fs/smb/server/transport_rdma.c
@@ -1353,14 +1353,12 @@ static int get_sg_list(void *buf, int size, struct scatterlist *sg_list, int nen
static int get_mapped_sg_list(struct ib_device *device, void *buf, int size,
struct scatterlist *sg_list, int nentries,
- enum dma_data_direction dir)
+ enum dma_data_direction dir, int *npages)
{
- int npages;
-
- npages = get_sg_list(buf, size, sg_list, nentries);
- if (npages < 0)
+ *npages = get_sg_list(buf, size, sg_list, nentries);
+ if (*npages < 0)
return -EINVAL;
- return ib_dma_map_sg(device, sg_list, npages, dir);
+ return ib_dma_map_sg(device, sg_list, *npages, dir);
}
static int post_sendmsg(struct smbdirect_socket *sc,
@@ -1431,12 +1429,13 @@ static int smb_direct_post_send_data(struct smbdirect_socket *sc,
for (i = 0; i < niov; i++) {
struct ib_sge *sge;
int sg_cnt;
+ int npages;
sg_init_table(sg, SMBDIRECT_SEND_IO_MAX_SGE - 1);
sg_cnt = get_mapped_sg_list(sc->ib.dev,
iov[i].iov_base, iov[i].iov_len,
sg, SMBDIRECT_SEND_IO_MAX_SGE - 1,
- DMA_TO_DEVICE);
+ DMA_TO_DEVICE, &npages);
if (sg_cnt <= 0) {
pr_err("failed to map buffer\n");
ret = -ENOMEM;
@@ -1444,7 +1443,7 @@ static int smb_direct_post_send_data(struct smbdirect_socket *sc,
} else if (sg_cnt + msg->num_sge > SMBDIRECT_SEND_IO_MAX_SGE) {
pr_err("buffer not fitted into sges\n");
ret = -E2BIG;
- ib_dma_unmap_sg(sc->ib.dev, sg, sg_cnt,
+ ib_dma_unmap_sg(sc->ib.dev, sg, npages,
DMA_TO_DEVICE);
goto err;
}
@@ -2708,6 +2707,7 @@ int ksmbd_rdma_init(void)
{
int ret;
+ smb_direct_port = SMB_DIRECT_PORT_INFINIBAND;
smb_direct_listener.cm_id = NULL;
ret = ib_register_client(&smb_direct_ib_client);
diff --git a/fs/smb/server/vfs.c b/fs/smb/server/vfs.c
index f891344bd76b..b8e648b8300f 100644
--- a/fs/smb/server/vfs.c
+++ b/fs/smb/server/vfs.c
@@ -1227,7 +1227,7 @@ int ksmbd_vfs_kern_path(struct ksmbd_work *work, char *filepath,
}
/**
- * ksmbd_vfs_kern_path_start_remove() - lookup a file and get path info prior to removal
+ * ksmbd_vfs_kern_path_start_removing() - lookup a file and get path info prior to removal
* @work: work
* @filepath: file path that is relative to share
* @flags: lookup flags