diff options
-rw-r--r-- | fs/ext2/inode.c | 12 | ||||
-rw-r--r-- | fs/udf/inode.c | 28 | ||||
-rw-r--r-- | fs/udf/super.c | 13 |
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; |