Commit cda6a60a authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull udf and ext2 fixes from Jan Kara:

 - a couple of smaller cleanups and fixes for ext2

 - fixes of a data corruption issues in udf when handling holes and
   preallocation extents

 - fixes and cleanups of several smaller issues in udf

 - add maintainer entry for isofs

* tag 'fixes_for_v6.2-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/jack/linux-fs:
  udf: Fix extending file within last block
  udf: Discard preallocation before extending file with a hole
  udf: Do not bother looking for prealloc extents if i_lenExtents matches i_size
  udf: Fix preallocation discarding at indirect extent boundary
  udf: Increase UDF_MAX_READ_VERSION to 0x0260
  fs/ext2: Fix code indentation
  ext2: unbugger ext2_empty_dir()
  udf: remove ->writepage
  ext2: remove ->writepage
  ext2: Don't flush page immediately for DIRSYNC directories
  ext2: Fix some kernel-doc warnings
  maintainers: Add ISOFS entry
  udf: Avoid double brelse() in udf_rename()
  fs: udf: Optimize udf_free_in_core_inode and udf_find_fileset function
parents 07d7a4d6 1f3868f0
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -10925,6 +10925,13 @@ F: drivers/isdn/Makefile
F:	drivers/isdn/hardware/
F:	drivers/isdn/mISDN/
ISOFS FILESYSTEM
M:	Jan Kara <jack@suse.cz>
L:	linux-fsdevel@vger.kernel.org
S:	Maintained
F:	Documentation/filesystems/isofs.rst
F:	fs/isofs/
IT87 HARDWARE MONITORING DRIVER
M:	Jean Delvare <jdelvare@suse.com>
L:	linux-hwmon@vger.kernel.org
+23 −18
Original line number Diff line number Diff line
@@ -81,11 +81,10 @@ ext2_last_byte(struct inode *inode, unsigned long page_nr)
	return last_byte;
}

static int ext2_commit_chunk(struct page *page, loff_t pos, unsigned len)
static void ext2_commit_chunk(struct page *page, loff_t pos, unsigned len)
{
	struct address_space *mapping = page->mapping;
	struct inode *dir = mapping->host;
	int err = 0;

	inode_inc_iversion(dir);
	block_write_end(NULL, mapping, pos, len, len, page, NULL);
@@ -94,18 +93,9 @@ static int ext2_commit_chunk(struct page *page, loff_t pos, unsigned len)
		i_size_write(dir, pos+len);
		mark_inode_dirty(dir);
	}

	if (IS_DIRSYNC(dir)) {
		err = write_one_page(page);
		if (!err)
			err = sync_inode_metadata(dir, 1);
	} else {
	unlock_page(page);
}

	return err;
}

static bool ext2_check_page(struct page *page, int quiet, char *kaddr)
{
	struct inode *dir = page->mapping->host;
@@ -413,7 +403,7 @@ struct ext2_dir_entry_2 *ext2_find_entry (struct inode *dir,
	return de;
}

/**
/*
 * Return the '..' directory entry and the page in which the entry was found
 * (as a parameter - p).
 *
@@ -460,6 +450,17 @@ static int ext2_prepare_chunk(struct page *page, loff_t pos, unsigned len)
	return __block_write_begin(page, pos, len, ext2_get_block);
}


static int ext2_handle_dirsync(struct inode *dir)
{
	int err;

	err = filemap_write_and_wait(dir->i_mapping);
	if (!err)
		err = sync_inode_metadata(dir, 1);
	return err;
}

void ext2_set_link(struct inode *dir, struct ext2_dir_entry_2 *de,
		   struct page *page, void *page_addr, struct inode *inode,
		   int update_times)
@@ -474,11 +475,12 @@ void ext2_set_link(struct inode *dir, struct ext2_dir_entry_2 *de,
	BUG_ON(err);
	de->inode = cpu_to_le32(inode->i_ino);
	ext2_set_de_type(de, inode);
	err = ext2_commit_chunk(page, pos, len);
	ext2_commit_chunk(page, pos, len);
	if (update_times)
		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);
}

/*
@@ -566,10 +568,11 @@ int ext2_add_link (struct dentry *dentry, struct inode *inode)
	memcpy(de->name, name, namelen);
	de->inode = cpu_to_le32(inode->i_ino);
	ext2_set_de_type (de, inode);
	err = ext2_commit_chunk(page, pos, rec_len);
	ext2_commit_chunk(page, pos, rec_len);
	dir->i_mtime = dir->i_ctime = current_time(dir);
	EXT2_I(dir)->i_flags &= ~EXT2_BTREE_FL;
	mark_inode_dirty(dir);
	err = ext2_handle_dirsync(dir);
	/* OFFSET_CACHE */
out_put:
	ext2_put_page(page, page_addr);
@@ -615,10 +618,11 @@ int ext2_delete_entry (struct ext2_dir_entry_2 *dir, struct page *page,
	if (pde)
		pde->rec_len = ext2_rec_len_to_disk(to - from);
	dir->inode = 0;
	err = ext2_commit_chunk(page, pos, to - from);
	ext2_commit_chunk(page, pos, to - from);
	inode->i_ctime = inode->i_mtime = current_time(inode);
	EXT2_I(inode)->i_flags &= ~EXT2_BTREE_FL;
	mark_inode_dirty(inode);
	err = ext2_handle_dirsync(inode);
out:
	return err;
}
@@ -658,7 +662,8 @@ int ext2_make_empty(struct inode *inode, struct inode *parent)
	memcpy (de->name, "..\0", 4);
	ext2_set_de_type (de, inode);
	kunmap_atomic(kaddr);
	err = ext2_commit_chunk(page, 0, chunk_size);
	ext2_commit_chunk(page, 0, chunk_size);
	err = ext2_handle_dirsync(inode);
fail:
	put_page(page);
	return err;
@@ -679,7 +684,7 @@ int ext2_empty_dir (struct inode * inode)
		page = ext2_get_page(inode, i, 0, &page_addr);

		if (IS_ERR(page))
			goto not_empty;
			return 0;

		kaddr = page_addr;
		de = (ext2_dirent *)kaddr;
+0 −6
Original line number Diff line number Diff line
@@ -869,11 +869,6 @@ int ext2_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
	return ret;
}

static int ext2_writepage(struct page *page, struct writeback_control *wbc)
{
	return block_write_full_page(page, ext2_get_block, wbc);
}

static int ext2_read_folio(struct file *file, struct folio *folio)
{
	return mpage_read_folio(folio, ext2_get_block);
@@ -948,7 +943,6 @@ const struct address_space_operations ext2_aops = {
	.invalidate_folio	= block_invalidate_folio,
	.read_folio		= ext2_read_folio,
	.readahead		= ext2_readahead,
	.writepage		= ext2_writepage,
	.write_begin		= ext2_write_begin,
	.write_end		= ext2_write_end,
	.bmap			= ext2_bmap,
+35 −48
Original line number Diff line number Diff line
@@ -182,11 +182,6 @@ static void udf_write_failed(struct address_space *mapping, loff_t to)
	}
}

static int udf_writepage(struct page *page, struct writeback_control *wbc)
{
	return block_write_full_page(page, udf_get_block, wbc);
}

static int udf_writepages(struct address_space *mapping,
			struct writeback_control *wbc)
{
@@ -239,12 +234,12 @@ const struct address_space_operations udf_aops = {
	.invalidate_folio = block_invalidate_folio,
	.read_folio	= udf_read_folio,
	.readahead	= udf_readahead,
	.writepage	= udf_writepage,
	.writepages	= udf_writepages,
	.write_begin	= udf_write_begin,
	.write_end	= generic_write_end,
	.direct_IO	= udf_direct_IO,
	.bmap		= udf_bmap,
	.migrate_folio	= buffer_migrate_folio,
};

/*
@@ -439,6 +434,12 @@ static int udf_get_block(struct inode *inode, sector_t block,
		iinfo->i_next_alloc_goal++;
	}

	/*
	 * Block beyond EOF and prealloc extents? Just discard preallocation
	 * as it is not useful and complicates things.
	 */
	if (((loff_t)block) << inode->i_blkbits > iinfo->i_lenExtents)
		udf_discard_prealloc(inode);
	udf_clear_extent_cache(inode);
	phys = inode_getblk(inode, block, &err, &new);
	if (!phys)
@@ -488,8 +489,6 @@ static int udf_do_extend_file(struct inode *inode,
	uint32_t add;
	int count = 0, fake = !(last_ext->extLength & UDF_EXTENT_LENGTH_MASK);
	struct super_block *sb = inode->i_sb;
	struct kernel_lb_addr prealloc_loc = {};
	uint32_t prealloc_len = 0;
	struct udf_inode_info *iinfo;
	int err;

@@ -510,19 +509,6 @@ static int udf_do_extend_file(struct inode *inode,
			~(sb->s_blocksize - 1);
	}

	/* Last extent are just preallocated blocks? */
	if ((last_ext->extLength & UDF_EXTENT_FLAG_MASK) ==
						EXT_NOT_RECORDED_ALLOCATED) {
		/* Save the extent so that we can reattach it to the end */
		prealloc_loc = last_ext->extLocation;
		prealloc_len = last_ext->extLength;
		/* Mark the extent as a hole */
		last_ext->extLength = EXT_NOT_RECORDED_NOT_ALLOCATED |
			(last_ext->extLength & UDF_EXTENT_LENGTH_MASK);
		last_ext->extLocation.logicalBlockNum = 0;
		last_ext->extLocation.partitionReferenceNum = 0;
	}

	/* Can we merge with the previous extent? */
	if ((last_ext->extLength & UDF_EXTENT_FLAG_MASK) ==
					EXT_NOT_RECORDED_NOT_ALLOCATED) {
@@ -550,7 +536,7 @@ static int udf_do_extend_file(struct inode *inode,
		 * more extents, we may need to enter possible following
		 * empty indirect extent.
		 */
		if (new_block_bytes || prealloc_len)
		if (new_block_bytes)
			udf_next_aext(inode, last_pos, &tmploc, &tmplen, 0);
	}

@@ -584,17 +570,6 @@ static int udf_do_extend_file(struct inode *inode,
	}

out:
	/* Do we have some preallocated blocks saved? */
	if (prealloc_len) {
		err = udf_add_aext(inode, last_pos, &prealloc_loc,
				   prealloc_len, 1);
		if (err)
			return err;
		last_ext->extLocation = prealloc_loc;
		last_ext->extLength = prealloc_len;
		count++;
	}

	/* last_pos should point to the last written extent... */
	if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT)
		last_pos->offset -= sizeof(struct short_ad);
@@ -610,13 +585,17 @@ static int udf_do_extend_file(struct inode *inode,
static void udf_do_extend_final_block(struct inode *inode,
				      struct extent_position *last_pos,
				      struct kernel_long_ad *last_ext,
				      uint32_t final_block_len)
				      uint32_t new_elen)
{
	struct super_block *sb = inode->i_sb;
	uint32_t added_bytes;

	added_bytes = final_block_len -
		      (last_ext->extLength & (sb->s_blocksize - 1));
	/*
	 * Extent already large enough? It may be already rounded up to block
	 * size...
	 */
	if (new_elen <= (last_ext->extLength & UDF_EXTENT_LENGTH_MASK))
		return;
	added_bytes = (last_ext->extLength & UDF_EXTENT_LENGTH_MASK) - new_elen;
	last_ext->extLength += added_bytes;
	UDF_I(inode)->i_lenExtents += added_bytes;

@@ -633,12 +612,12 @@ static int udf_extend_file(struct inode *inode, loff_t newsize)
	int8_t etype;
	struct super_block *sb = inode->i_sb;
	sector_t first_block = newsize >> sb->s_blocksize_bits, offset;
	unsigned long partial_final_block;
	loff_t new_elen;
	int adsize;
	struct udf_inode_info *iinfo = UDF_I(inode);
	struct kernel_long_ad extent;
	int err = 0;
	int within_final_block;
	bool within_last_ext;

	if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT)
		adsize = sizeof(struct short_ad);
@@ -647,8 +626,17 @@ static int udf_extend_file(struct inode *inode, loff_t newsize)
	else
		BUG();

	/*
	 * When creating hole in file, just don't bother with preserving
	 * preallocation. It likely won't be very useful anyway.
	 */
	udf_discard_prealloc(inode);

	etype = inode_bmap(inode, first_block, &epos, &eloc, &elen, &offset);
	within_final_block = (etype != -1);
	within_last_ext = (etype != -1);
	/* We don't expect extents past EOF... */
	WARN_ON_ONCE(within_last_ext &&
		     elen > ((loff_t)offset + 1) << inode->i_blkbits);

	if ((!epos.bh && epos.offset == udf_file_entry_alloc_offset(inode)) ||
	    (epos.bh && epos.offset == sizeof(struct allocExtDesc))) {
@@ -664,19 +652,17 @@ static int udf_extend_file(struct inode *inode, loff_t newsize)
		extent.extLength |= etype << 30;
	}

	partial_final_block = newsize & (sb->s_blocksize - 1);
	new_elen = ((loff_t)offset << inode->i_blkbits) |
					(newsize & (sb->s_blocksize - 1));

	/* File has extent covering the new size (could happen when extending
	 * inside a block)?
	 */
	if (within_final_block) {
	if (within_last_ext) {
		/* Extending file within the last file block */
		udf_do_extend_final_block(inode, &epos, &extent,
					  partial_final_block);
		udf_do_extend_final_block(inode, &epos, &extent, new_elen);
	} else {
		loff_t add = ((loff_t)offset << sb->s_blocksize_bits) |
			     partial_final_block;
		err = udf_do_extend_file(inode, &epos, &extent, add);
		err = udf_do_extend_file(inode, &epos, &extent, new_elen);
	}

	if (err < 0)
@@ -777,10 +763,11 @@ static sector_t inode_getblk(struct inode *inode, sector_t block,
		goto out_free;
	}

	/* Are we beyond EOF? */
	/* Are we beyond EOF and preallocated extent? */
	if (etype == -1) {
		int ret;
		loff_t hole_len;

		isBeyondEOF = true;
		if (count) {
			if (c)
+4 −4
Original line number Diff line number Diff line
@@ -1091,7 +1091,8 @@ static int udf_rename(struct user_namespace *mnt_userns, struct inode *old_dir,
		return -EINVAL;

	ofi = udf_find_entry(old_dir, &old_dentry->d_name, &ofibh, &ocfi);
	if (IS_ERR(ofi)) {
	if (!ofi || IS_ERR(ofi)) {
		if (IS_ERR(ofi))
			retval = PTR_ERR(ofi);
		goto end_rename;
	}
@@ -1101,8 +1102,7 @@ static int udf_rename(struct user_namespace *mnt_userns, struct inode *old_dir,

	brelse(ofibh.sbh);
	tloc = lelb_to_cpu(ocfi.icb.extLocation);
	if (!ofi || udf_get_lb_pblock(old_dir->i_sb, &tloc, 0)
	    != old_inode->i_ino)
	if (udf_get_lb_pblock(old_dir->i_sb, &tloc, 0) != old_inode->i_ino)
		goto end_rename;

	nfi = udf_find_entry(new_dir, &new_dentry->d_name, &nfibh, &ncfi);
Loading