ext4: convert i_fc_lock to spinlock
authorHarshad Shirwadkar <harshadshirwadkar@gmail.com>
Thu, 8 May 2025 17:59:00 +0000 (17:59 +0000)
committerTheodore Ts'o <tytso@mit.edu>
Fri, 9 May 2025 01:56:17 +0000 (21:56 -0400)
Convert ext4_inode_info->i_fc_lock to spinlock to avoid sleeping
in invalid contexts.

Reviewed-by: Jan Kara <jack@suse.cz>
Signed-off-by: Harshad Shirwadkar <harshadshirwadkar@gmail.com>
Link: https://patch.msgid.link/20250508175908.1004880-2-harshadshirwadkar@gmail.com
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
fs/ext4/ext4.h
fs/ext4/fast_commit.c
fs/ext4/super.c

index 5a20e9cd71849144d67b4743f40fe1846bf4e5ab..79dfb57a7046c4af7ad87dcad514e8656e1ab40d 100644 (file)
@@ -1069,8 +1069,11 @@ struct ext4_inode_info {
        /* Fast commit wait queue for this inode */
        wait_queue_head_t i_fc_wait;
 
-       /* Protect concurrent accesses on i_fc_lblk_start, i_fc_lblk_len */
-       struct mutex i_fc_lock;
+       /*
+        * Protect concurrent accesses on i_fc_lblk_start, i_fc_lblk_len
+        * and inode's EXT4_FC_STATE_COMMITTING state bit.
+        */
+       spinlock_t i_fc_lock;
 
        /*
         * i_disksize keeps track of what the inode size is ON DISK, not
index da4263a14a203d060232c81202a161698d40b13c..63859ec6d91dde56bbef80ad7a5e82e965f4fc45 100644 (file)
@@ -385,7 +385,7 @@ static int ext4_fc_track_template(
        int ret;
 
        tid = handle->h_transaction->t_tid;
-       mutex_lock(&ei->i_fc_lock);
+       spin_lock(&ei->i_fc_lock);
        if (tid == ei->i_sync_tid) {
                update = true;
        } else {
@@ -393,8 +393,7 @@ static int ext4_fc_track_template(
                ei->i_sync_tid = tid;
        }
        ret = __fc_track_fn(handle, inode, args, update);
-       mutex_unlock(&ei->i_fc_lock);
-
+       spin_unlock(&ei->i_fc_lock);
        if (!enqueue)
                return ret;
 
@@ -428,19 +427,19 @@ static int __track_dentry_update(handle_t *handle, struct inode *inode,
        struct super_block *sb = inode->i_sb;
        struct ext4_sb_info *sbi = EXT4_SB(sb);
 
-       mutex_unlock(&ei->i_fc_lock);
+       spin_unlock(&ei->i_fc_lock);
 
        if (IS_ENCRYPTED(dir)) {
                ext4_fc_mark_ineligible(sb, EXT4_FC_REASON_ENCRYPTED_FILENAME,
                                        handle);
-               mutex_lock(&ei->i_fc_lock);
+               spin_lock(&ei->i_fc_lock);
                return -EOPNOTSUPP;
        }
 
        node = kmem_cache_alloc(ext4_fc_dentry_cachep, GFP_NOFS);
        if (!node) {
                ext4_fc_mark_ineligible(sb, EXT4_FC_REASON_NOMEM, handle);
-               mutex_lock(&ei->i_fc_lock);
+               spin_lock(&ei->i_fc_lock);
                return -ENOMEM;
        }
 
@@ -471,7 +470,7 @@ static int __track_dentry_update(handle_t *handle, struct inode *inode,
                list_add_tail(&node->fcd_dilist, &ei->i_fc_dilist);
        }
        spin_unlock(&sbi->s_fc_lock);
-       mutex_lock(&ei->i_fc_lock);
+       spin_lock(&ei->i_fc_lock);
 
        return 0;
 }
@@ -893,15 +892,15 @@ static int ext4_fc_write_inode_data(struct inode *inode, u32 *crc)
        struct ext4_extent *ex;
        int ret;
 
-       mutex_lock(&ei->i_fc_lock);
+       spin_lock(&ei->i_fc_lock);
        if (ei->i_fc_lblk_len == 0) {
-               mutex_unlock(&ei->i_fc_lock);
+               spin_unlock(&ei->i_fc_lock);
                return 0;
        }
        old_blk_size = ei->i_fc_lblk_start;
        new_blk_size = ei->i_fc_lblk_start + ei->i_fc_lblk_len - 1;
        ei->i_fc_lblk_len = 0;
-       mutex_unlock(&ei->i_fc_lock);
+       spin_unlock(&ei->i_fc_lock);
 
        cur_lblk_off = old_blk_size;
        ext4_debug("will try writing %d to %d for inode %ld\n",
index 1819344996242f2b6f82fba13a1ad21a06e1510f..ed8166fe2ad078cee9729105b4ea82de835704a0 100644 (file)
@@ -1415,7 +1415,7 @@ static struct inode *ext4_alloc_inode(struct super_block *sb)
        ei->i_datasync_tid = 0;
        INIT_WORK(&ei->i_rsv_conversion_work, ext4_end_io_rsv_work);
        ext4_fc_init_inode(&ei->vfs_inode);
-       mutex_init(&ei->i_fc_lock);
+       spin_lock_init(&ei->i_fc_lock);
        return &ei->vfs_inode;
 }