Skip to content

Commit

Permalink
Merge tag 'fixes_for_v6.2-rc1' of git://git.kernel.org/pub/scm/linux/…
Browse files Browse the repository at this point in the history
…kernel/git/jack/linux-fs

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
  • Loading branch information
Linus Torvalds committed Dec 13, 2022
2 parents 07d7a4d + 1f3868f commit cda6a60
Show file tree
Hide file tree
Showing 10 changed files with 98 additions and 119 deletions.
7 changes: 7 additions & 0 deletions MAINTAINERS
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
12 changes: 6 additions & 6 deletions fs/ext2/balloc.c
Original file line number Diff line number Diff line change
Expand Up @@ -667,7 +667,7 @@ ext2_try_to_allocate(struct super_block *sb, int group,
{
ext2_fsblk_t group_first_block = ext2_group_first_block_no(sb, group);
ext2_fsblk_t group_last_block = ext2_group_last_block_no(sb, group);
ext2_grpblk_t start, end;
ext2_grpblk_t start, end;
unsigned long num = 0;

start = 0;
Expand Down Expand Up @@ -1481,11 +1481,11 @@ unsigned long ext2_count_free_blocks (struct super_block * sb)
desc_count, bitmap_count);
return bitmap_count;
#else
for (i = 0; i < EXT2_SB(sb)->s_groups_count; i++) {
desc = ext2_get_group_desc (sb, i, NULL);
if (!desc)
continue;
desc_count += le16_to_cpu(desc->bg_free_blocks_count);
for (i = 0; i < EXT2_SB(sb)->s_groups_count; i++) {
desc = ext2_get_group_desc(sb, i, NULL);
if (!desc)
continue;
desc_count += le16_to_cpu(desc->bg_free_blocks_count);
}
return desc_count;
#endif
Expand Down
41 changes: 23 additions & 18 deletions fs/ext2/dir.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -94,16 +93,7 @@ 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;
unlock_page(page);
}

static bool ext2_check_page(struct page *page, int quiet, char *kaddr)
Expand Down Expand Up @@ -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).
*
Expand Down Expand Up @@ -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)
Expand All @@ -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);
}

/*
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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;
Expand All @@ -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;
Expand Down
6 changes: 0 additions & 6 deletions fs/ext2/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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,
Expand Down
2 changes: 1 addition & 1 deletion fs/ext2/super.c
Original file line number Diff line number Diff line change
Expand Up @@ -1648,7 +1648,7 @@ static int __init init_ext2_fs(void)
err = init_inodecache();
if (err)
return err;
err = register_filesystem(&ext2_fs_type);
err = register_filesystem(&ext2_fs_type);
if (err)
goto out;
return 0;
Expand Down
83 changes: 35 additions & 48 deletions fs/udf/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down Expand Up @@ -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,
};

/*
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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;

Expand All @@ -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) {
Expand Down Expand Up @@ -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);
}

Expand Down Expand Up @@ -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);
Expand All @@ -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;

Expand All @@ -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);
Expand All @@ -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))) {
Expand All @@ -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)
Expand Down Expand Up @@ -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)
Expand Down
8 changes: 4 additions & 4 deletions fs/udf/namei.c
Original file line number Diff line number Diff line change
Expand Up @@ -1091,8 +1091,9 @@ 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)) {
retval = PTR_ERR(ofi);
if (!ofi || IS_ERR(ofi)) {
if (IS_ERR(ofi))
retval = PTR_ERR(ofi);
goto end_rename;
}

Expand All @@ -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);
Expand Down
Loading

0 comments on commit cda6a60

Please sign in to comment.