Commit 274978f1 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull UDF and ext2 fixes from Jan Kara:

 - Rewrite of udf directory iteration code to address multiple syzbot
   reports

 - Fixes to udf extent handling and block mapping code to address
   several syzbot reports and filesystem corruption issues uncovered by
   fsx & fsstress

 - Convert udf to kmap_local()

 - Add sanity checks when loading udf bitmaps

 - Drop old VARCONV support which I've never seen used and which was
   broken for quite some years without anybody noticing

 - Finish conversion of ext2 to kmap_local()

 - One fix to mpage_writepages() on which other udf fixes depend

* tag 'fixes_for_v6.3-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/jack/linux-fs: (78 commits)
  udf: Avoid directory type conversion failure due to ENOMEM
  udf: Use unsigned variables for size calculations
  udf: remove reporting loc in debug output
  udf: Check consistency of Space Bitmap Descriptor
  udf: Fix file counting in LVID
  udf: Limit file size to 4TB
  udf: Don't return bh from udf_expand_dir_adinicb()
  udf: Convert udf_expand_file_adinicb() to avoid kmap_atomic()
  udf: Convert udf_adinicb_writepage() to memcpy_to_page()
  udf: Switch udf_adinicb_readpage() to kmap_local_page()
  udf: Move udf_adinicb_readpage() to inode.c
  udf: Mark aops implementation static
  udf: Switch to single address_space_operations
  udf: Add handling of in-ICB files to udf_bmap()
  udf: Convert all file types to use udf_write_end()
  udf: Convert in-ICB files to use udf_write_begin()
  udf: Convert in-ICB files to use udf_direct_IO()
  udf: Convert in-ICB files to use udf_writepages()
  udf: Unify .read_folio for normal and in-ICB files
  udf: Fix off-by-one error when discarding preallocation
  ...
parents cd776a43 df97f64d
Loading
Loading
Loading
Loading
+10 −7
Original line number Diff line number Diff line
@@ -461,9 +461,9 @@ static int ext2_handle_dirsync(struct inode *dir)
	return err;
}

void ext2_set_link(struct inode *dir, struct ext2_dir_entry_2 *de,
int ext2_set_link(struct inode *dir, struct ext2_dir_entry_2 *de,
		struct page *page, void *page_addr, struct inode *inode,
		   int update_times)
		bool update_times)
{
	loff_t pos = page_offset(page) +
			(char *) de - (char *) page_addr;
@@ -472,7 +472,10 @@ void ext2_set_link(struct inode *dir, struct ext2_dir_entry_2 *de,

	lock_page(page);
	err = ext2_prepare_chunk(page, pos, len);
	BUG_ON(err);
	if (err) {
		unlock_page(page);
		return err;
	}
	de->inode = cpu_to_le32(inode->i_ino);
	ext2_set_de_type(de, inode);
	ext2_commit_chunk(page, pos, len);
@@ -480,7 +483,7 @@ void ext2_set_link(struct inode *dir, struct ext2_dir_entry_2 *de,
		dir->i_mtime = dir->i_ctime = current_time(dir);
	EXT2_I(dir)->i_flags &= ~EXT2_BTREE_FL;
	mark_inode_dirty(dir);
	ext2_handle_dirsync(dir);
	return ext2_handle_dirsync(dir);
}

/*
@@ -646,7 +649,7 @@ int ext2_make_empty(struct inode *inode, struct inode *parent)
		unlock_page(page);
		goto fail;
	}
	kaddr = kmap_atomic(page);
	kaddr = kmap_local_page(page);
	memset(kaddr, 0, chunk_size);
	de = (struct ext2_dir_entry_2 *)kaddr;
	de->name_len = 1;
@@ -661,7 +664,7 @@ int ext2_make_empty(struct inode *inode, struct inode *parent)
	de->inode = cpu_to_le32(parent->i_ino);
	memcpy (de->name, "..\0", 4);
	ext2_set_de_type (de, inode);
	kunmap_atomic(kaddr);
	kunmap_local(kaddr);
	ext2_commit_chunk(page, 0, chunk_size);
	err = ext2_handle_dirsync(inode);
fail:
+3 −2
Original line number Diff line number Diff line
@@ -734,8 +734,9 @@ extern int ext2_delete_entry(struct ext2_dir_entry_2 *dir, struct page *page,
			     char *kaddr);
extern int ext2_empty_dir (struct inode *);
extern struct ext2_dir_entry_2 *ext2_dotdot(struct inode *dir, struct page **p, void **pa);
extern void ext2_set_link(struct inode *, struct ext2_dir_entry_2 *, struct page *, void *,
			  struct inode *, int);
int ext2_set_link(struct inode *dir, struct ext2_dir_entry_2 *de,
		struct page *page, void *page_addr, struct inode *inode,
		bool update_times);
static inline void ext2_put_page(struct page *page, void *page_addr)
{
	kunmap_local(page_addr);
+12 −9
Original line number Diff line number Diff line
@@ -370,8 +370,11 @@ static int ext2_rename (struct mnt_idmap * idmap,
			err = PTR_ERR(new_de);
			goto out_dir;
		}
		ext2_set_link(new_dir, new_de, new_page, page_addr, old_inode, 1);
		err = ext2_set_link(new_dir, new_de, new_page, page_addr,
				    old_inode, true);
		ext2_put_page(new_page, page_addr);
		if (err)
			goto out_dir;
		new_inode->i_ctime = current_time(new_inode);
		if (dir_de)
			drop_nlink(new_inode);
@@ -394,24 +397,24 @@ static int ext2_rename (struct mnt_idmap * idmap,
	ext2_delete_entry(old_de, old_page, old_page_addr);

	if (dir_de) {
		if (old_dir != new_dir)
			ext2_set_link(old_inode, dir_de, dir_page,
				      dir_page_addr, new_dir, 0);
		if (old_dir != new_dir) {
			err = ext2_set_link(old_inode, dir_de, dir_page,
					    dir_page_addr, new_dir, false);

		}
		ext2_put_page(dir_page, dir_page_addr);
		inode_dec_link_count(old_dir);
	}

out_old:
	ext2_put_page(old_page, old_page_addr);
	return 0;
out:
	return err;

out_dir:
	if (dir_de)
		ext2_put_page(dir_page, dir_page_addr);
out_old:
	ext2_put_page(old_page, old_page_addr);
out:
	return err;
	goto out_old;
}

const struct inode_operations ext2_dir_inode_operations = {
+2 −0
Original line number Diff line number Diff line
@@ -532,6 +532,8 @@ static int __mpage_writepage(struct page *page, struct writeback_control *wbc,
		map_bh.b_size = 1 << blkbits;
		if (mpd->get_block(inode, block_in_file, &map_bh, 1))
			goto confused;
		if (!buffer_mapped(&map_bh))
			goto confused;
		if (buffer_new(&map_bh))
			clean_bdev_bh_alias(&map_bh);
		if (buffer_boundary(&map_bh)) {
+28 −5
Original line number Diff line number Diff line
@@ -36,18 +36,41 @@ static int read_block_bitmap(struct super_block *sb,
			     unsigned long bitmap_nr)
{
	struct buffer_head *bh = NULL;
	int retval = 0;
	int i;
	int max_bits, off, count;
	struct kernel_lb_addr loc;

	loc.logicalBlockNum = bitmap->s_extPosition;
	loc.partitionReferenceNum = UDF_SB(sb)->s_partition;

	bh = udf_tread(sb, udf_get_lb_pblock(sb, &loc, block));
	bh = sb_bread(sb, udf_get_lb_pblock(sb, &loc, block));
	bitmap->s_block_bitmap[bitmap_nr] = bh;
	if (!bh)
		retval = -EIO;
		return -EIO;

	bitmap->s_block_bitmap[bitmap_nr] = bh;
	return retval;
	/* Check consistency of Space Bitmap buffer. */
	max_bits = sb->s_blocksize * 8;
	if (!bitmap_nr) {
		off = sizeof(struct spaceBitmapDesc) << 3;
		count = min(max_bits - off, bitmap->s_nr_groups);
	} else {
		/*
		 * Rough check if bitmap number is too big to have any bitmap
 		 * blocks reserved.
		 */
		if (bitmap_nr >
		    (bitmap->s_nr_groups >> (sb->s_blocksize_bits + 3)) + 2)
			return 0;
		off = 0;
		count = bitmap->s_nr_groups - bitmap_nr * max_bits +
				(sizeof(struct spaceBitmapDesc) << 3);
		count = min(count, max_bits);
	}

	for (i = 0; i < count; i++)
		if (udf_test_bit(i + off, bh->b_data))
			return -EFSCORRUPTED;
	return 0;
}

static int __load_block_bitmap(struct super_block *sb,
Loading