summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--fs/ext2/inode.c12
-rw-r--r--fs/udf/inode.c28
-rw-r--r--fs/udf/super.c13
3 files changed, 38 insertions, 15 deletions
diff --git a/fs/ext2/inode.c b/fs/ext2/inode.c
index d35ca26eee3c..e10c376843d7 100644
--- a/fs/ext2/inode.c
+++ b/fs/ext2/inode.c
@@ -895,9 +895,19 @@ int ext2_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
u64 start, u64 len)
{
int ret;
+ loff_t i_size;
inode_lock(inode);
- len = min_t(u64, len, i_size_read(inode));
+ i_size = i_size_read(inode);
+ /*
+ * iomap_fiemap() returns EINVAL for 0 length. Make sure we don't trim
+ * length to 0 but still trim the range as much as possible since
+ * ext2_get_blocks() iterates unmapped space block by block which is
+ * slow.
+ */
+ if (i_size == 0)
+ i_size = 1;
+ len = min_t(u64, len, i_size);
ret = iomap_fiemap(inode, fieinfo, start, len, &ext2_iomap_ops);
inode_unlock(inode);
diff --git a/fs/udf/inode.c b/fs/udf/inode.c
index 356b75676fa9..f24aa98e6869 100644
--- a/fs/udf/inode.c
+++ b/fs/udf/inode.c
@@ -181,19 +181,23 @@ static void udf_write_failed(struct address_space *mapping, loff_t to)
}
}
-static int udf_adinicb_writepage(struct folio *folio,
- struct writeback_control *wbc, void *data)
+static int udf_adinicb_writepages(struct address_space *mapping,
+ struct writeback_control *wbc)
{
- struct inode *inode = folio->mapping->host;
+ struct inode *inode = mapping->host;
struct udf_inode_info *iinfo = UDF_I(inode);
+ struct folio *folio = NULL;
+ int error = 0;
+
+ while ((folio = writeback_iter(mapping, wbc, folio, &error))) {
+ BUG_ON(!folio_test_locked(folio));
+ BUG_ON(folio->index != 0);
+ memcpy_from_file_folio(iinfo->i_data + iinfo->i_lenEAttr, folio,
+ 0, i_size_read(inode));
+ folio_unlock(folio);
+ }
- BUG_ON(!folio_test_locked(folio));
- BUG_ON(folio->index != 0);
- memcpy_from_file_folio(iinfo->i_data + iinfo->i_lenEAttr, folio, 0,
- i_size_read(inode));
- folio_unlock(folio);
mark_inode_dirty(inode);
-
return 0;
}
@@ -203,9 +207,9 @@ static int udf_writepages(struct address_space *mapping,
struct inode *inode = mapping->host;
struct udf_inode_info *iinfo = UDF_I(inode);
- if (iinfo->i_alloc_type != ICBTAG_FLAG_AD_IN_ICB)
- return mpage_writepages(mapping, wbc, udf_get_block_wb);
- return write_cache_pages(mapping, wbc, udf_adinicb_writepage, NULL);
+ if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB)
+ return udf_adinicb_writepages(mapping, wbc);
+ return mpage_writepages(mapping, wbc, udf_get_block_wb);
}
static void udf_adinicb_read_folio(struct folio *folio)
diff --git a/fs/udf/super.c b/fs/udf/super.c
index 1c8a736b3309..b2f168b0a0d1 100644
--- a/fs/udf/super.c
+++ b/fs/udf/super.c
@@ -1440,7 +1440,7 @@ static int udf_load_logicalvol(struct super_block *sb, sector_t block,
struct genericPartitionMap *gpm;
uint16_t ident;
struct buffer_head *bh;
- unsigned int table_len;
+ unsigned int table_len, part_map_count;
int ret;
bh = udf_read_tagged(sb, block, block, &ident);
@@ -1461,7 +1461,16 @@ static int udf_load_logicalvol(struct super_block *sb, sector_t block,
"logical volume");
if (ret)
goto out_bh;
- ret = udf_sb_alloc_partition_maps(sb, le32_to_cpu(lvd->numPartitionMaps));
+
+ part_map_count = le32_to_cpu(lvd->numPartitionMaps);
+ if (part_map_count > table_len / sizeof(struct genericPartitionMap1)) {
+ udf_err(sb, "error loading logical volume descriptor: "
+ "Too many partition maps (%u > %u)\n", part_map_count,
+ table_len / (unsigned)sizeof(struct genericPartitionMap1));
+ ret = -EIO;
+ goto out_bh;
+ }
+ ret = udf_sb_alloc_partition_maps(sb, part_map_count);
if (ret)
goto out_bh;