Patch "udf: Fix lock ordering in udf_evict_inode()" has been added to the 6.10-stable tree

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This is a note to let you know that I've just added the patch titled

    udf: Fix lock ordering in udf_evict_inode()

to the 6.10-stable tree which can be found at:
    http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
     udf-fix-lock-ordering-in-udf_evict_inode.patch
and it can be found in the queue-6.10 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree,
please let <stable@xxxxxxxxxxxxxxx> know about it.



commit a3d2b8e798b24395aaf5f70cae921ebf6fdcbcd5
Author: Jan Kara <jack@xxxxxxx>
Date:   Mon May 20 15:23:37 2024 +0200

    udf: Fix lock ordering in udf_evict_inode()
    
    [ Upstream commit 8832fc1e502687869606bb0a7b79848ed3bf036f ]
    
    udf_evict_inode() calls udf_setsize() to truncate deleted inode.
    However inode deletion through udf_evict_inode() can happen from inode
    reclaim context and udf_setsize() grabs mapping->invalidate_lock which
    isn't generally safe to acquire from fs reclaim context since we
    allocate pages under mapping->invalidate_lock for example in a page
    fault path.  This is however not a real deadlock possibility as by the
    time udf_evict_inode() is called, nobody can be accessing the inode,
    even less work with its page cache. So this is just a lockdep triggering
    false positive. Fix the problem by moving mapping->invalidate_lock
    locking outsize of udf_setsize() into udf_setattr() as grabbing
    mapping->invalidate_lock from udf_evict_inode() is pointless.
    
    Reported-by: syzbot+0333a6f4b88bcd68a62f@xxxxxxxxxxxxxxxxxxxxxxxxx
    Fixes: b9a861fd527a ("udf: Protect truncate and file type conversion with invalidate_lock")
    Signed-off-by: Jan Kara <jack@xxxxxxx>
    Signed-off-by: Sasha Levin <sashal@xxxxxxxxxx>

diff --git a/fs/udf/file.c b/fs/udf/file.c
index 97c59585208ca..3a4179de316b4 100644
--- a/fs/udf/file.c
+++ b/fs/udf/file.c
@@ -232,7 +232,9 @@ static int udf_setattr(struct mnt_idmap *idmap, struct dentry *dentry,
 
 	if ((attr->ia_valid & ATTR_SIZE) &&
 	    attr->ia_size != i_size_read(inode)) {
+		filemap_invalidate_lock(inode->i_mapping);
 		error = udf_setsize(inode, attr->ia_size);
+		filemap_invalidate_unlock(inode->i_mapping);
 		if (error)
 			return error;
 	}
diff --git a/fs/udf/inode.c b/fs/udf/inode.c
index 2fb21c5ffccfe..08767bd21eb7f 100644
--- a/fs/udf/inode.c
+++ b/fs/udf/inode.c
@@ -1250,7 +1250,6 @@ int udf_setsize(struct inode *inode, loff_t newsize)
 	if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
 		return -EPERM;
 
-	filemap_invalidate_lock(inode->i_mapping);
 	iinfo = UDF_I(inode);
 	if (newsize > inode->i_size) {
 		if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) {
@@ -1263,11 +1262,11 @@ int udf_setsize(struct inode *inode, loff_t newsize)
 			}
 			err = udf_expand_file_adinicb(inode);
 			if (err)
-				goto out_unlock;
+				return err;
 		}
 		err = udf_extend_file(inode, newsize);
 		if (err)
-			goto out_unlock;
+			return err;
 set_size:
 		truncate_setsize(inode, newsize);
 	} else {
@@ -1285,14 +1284,14 @@ int udf_setsize(struct inode *inode, loff_t newsize)
 		err = block_truncate_page(inode->i_mapping, newsize,
 					  udf_get_block);
 		if (err)
-			goto out_unlock;
+			return err;
 		truncate_setsize(inode, newsize);
 		down_write(&iinfo->i_data_sem);
 		udf_clear_extent_cache(inode);
 		err = udf_truncate_extents(inode);
 		up_write(&iinfo->i_data_sem);
 		if (err)
-			goto out_unlock;
+			return err;
 	}
 update_time:
 	inode_set_mtime_to_ts(inode, inode_set_ctime_current(inode));
@@ -1300,8 +1299,6 @@ int udf_setsize(struct inode *inode, loff_t newsize)
 		udf_sync_inode(inode);
 	else
 		mark_inode_dirty(inode);
-out_unlock:
-	filemap_invalidate_unlock(inode->i_mapping);
 	return err;
 }
 




[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux