From f33321b29b672d0d1e565e3c1a6886bfd14d4673 Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Wed, 18 Jan 2023 14:26:04 +0100 Subject: udf: Do not call udf_block_map() on ICB files Currently udf_symlink_filler() called udf_block_map() even on files which have data stored inside the ICB. This is invalid as we cannot map blocks for such files (although so far the error got silently ignored). The call happened because we could not call block mapping function once we've acquired i_data_sem and determined whether the file has data stored in the ICB. For symlinks the situation is luckily simple as they get never modified so file type never changes once it is set. Hence we can check the file type even without i_data_sem. Just drop the i_data_sem locking and move block mapping to where it is needed. Signed-off-by: Jan Kara --- fs/udf/symlink.c | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) (limited to 'fs/udf/symlink.c') diff --git a/fs/udf/symlink.c b/fs/udf/symlink.c index f3642f9c23f8..451d6d6c701e 100644 --- a/fs/udf/symlink.c +++ b/fs/udf/symlink.c @@ -109,27 +109,24 @@ static int udf_symlink_filler(struct file *file, struct folio *folio) unsigned char *symlink; int err; unsigned char *p = page_address(page); - struct udf_inode_info *iinfo; + struct udf_inode_info *iinfo = UDF_I(inode); uint32_t pos; /* We don't support symlinks longer than one block */ if (inode->i_size > inode->i_sb->s_blocksize) { err = -ENAMETOOLONG; - goto out_unmap; + goto out_unlock; } - iinfo = UDF_I(inode); - pos = udf_block_map(inode, 0); - - down_read(&iinfo->i_data_sem); if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) { symlink = iinfo->i_data + iinfo->i_lenEAttr; } else { + pos = udf_block_map(inode, 0); bh = sb_bread(inode->i_sb, pos); if (!bh) { err = -EIO; - goto out_unlock_inode; + goto out_err; } symlink = bh->b_data; @@ -138,17 +135,15 @@ static int udf_symlink_filler(struct file *file, struct folio *folio) err = udf_pc_to_char(inode->i_sb, symlink, inode->i_size, p, PAGE_SIZE); brelse(bh); if (err) - goto out_unlock_inode; + goto out_err; - up_read(&iinfo->i_data_sem); SetPageUptodate(page); unlock_page(page); return 0; -out_unlock_inode: - up_read(&iinfo->i_data_sem); +out_err: SetPageError(page); -out_unmap: +out_unlock: unlock_page(page); return err; } -- cgit v1.2.3-73-gaa49b From 15a08f51624a252ddadf7ce95ad5256d634873fc Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Wed, 18 Jan 2023 14:32:45 +0100 Subject: udf: Convert udf_symlink_filler() to use udf_bread() Convert udf_symlink_filler() to use udf_bread() instead of mapping and reading buffer head manually. Signed-off-by: Jan Kara --- fs/udf/symlink.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) (limited to 'fs/udf/symlink.c') diff --git a/fs/udf/symlink.c b/fs/udf/symlink.c index 451d6d6c701e..a6cabaa5f1c2 100644 --- a/fs/udf/symlink.c +++ b/fs/udf/symlink.c @@ -107,10 +107,9 @@ static int udf_symlink_filler(struct file *file, struct folio *folio) struct inode *inode = page->mapping->host; struct buffer_head *bh = NULL; unsigned char *symlink; - int err; + int err = 0; unsigned char *p = page_address(page); struct udf_inode_info *iinfo = UDF_I(inode); - uint32_t pos; /* We don't support symlinks longer than one block */ if (inode->i_size > inode->i_sb->s_blocksize) { @@ -121,14 +120,12 @@ static int udf_symlink_filler(struct file *file, struct folio *folio) if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) { symlink = iinfo->i_data + iinfo->i_lenEAttr; } else { - pos = udf_block_map(inode, 0); - bh = sb_bread(inode->i_sb, pos); - + bh = udf_bread(inode, 0, 0, &err); if (!bh) { - err = -EIO; + if (!err) + err = -EFSCORRUPTED; goto out_err; } - symlink = bh->b_data; } -- cgit v1.2.3-73-gaa49b