ext4: fixup ext4_fc_track_* functions' signature
authorHarshad Shirwadkar <harshadshirwadkar@gmail.com>
Fri, 6 Nov 2020 03:58:53 +0000 (19:58 -0800)
committerTheodore Ts'o <tytso@mit.edu>
Sat, 7 Nov 2020 04:01:02 +0000 (23:01 -0500)
Firstly, pass handle to all ext4_fc_track_* functions and use
transaction id found in handle->h_transaction->h_tid for tracking fast
commit updates. Secondly, don't pass inode to
ext4_fc_track_link/create/unlink functions. inode can be found inside
these functions as d_inode(dentry). However, rename path is an
exeception. That's because in that case, we need inode that's not same
as d_inode(dentry). To handle that, add a couple of low-level wrapper
functions that take inode and dentry as arguments.

Suggested-by: Jan Kara <jack@suse.cz>
Signed-off-by: Harshad Shirwadkar <harshadshirwadkar@gmail.com>
Link: https://lore.kernel.org/r/20201106035911.1942128-5-harshadshirwadkar@gmail.com
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
fs/ext4/ext4.h
fs/ext4/extents.c
fs/ext4/fast_commit.c
fs/ext4/inode.c
fs/ext4/namei.c

index d513553..c6339bd 100644 (file)
@@ -2738,12 +2738,16 @@ extern void ext4_end_bitmap_read(struct buffer_head *bh, int uptodate);
 int ext4_fc_info_show(struct seq_file *seq, void *v);
 void ext4_fc_init(struct super_block *sb, journal_t *journal);
 void ext4_fc_init_inode(struct inode *inode);
-void ext4_fc_track_range(struct inode *inode, ext4_lblk_t start,
+void ext4_fc_track_range(handle_t *handle, struct inode *inode, ext4_lblk_t start,
                         ext4_lblk_t end);
-void ext4_fc_track_unlink(struct inode *inode, struct dentry *dentry);
-void ext4_fc_track_link(struct inode *inode, struct dentry *dentry);
-void ext4_fc_track_create(struct inode *inode, struct dentry *dentry);
-void ext4_fc_track_inode(struct inode *inode);
+void __ext4_fc_track_unlink(handle_t *handle, struct inode *inode,
+       struct dentry *dentry);
+void __ext4_fc_track_link(handle_t *handle, struct inode *inode,
+       struct dentry *dentry);
+void ext4_fc_track_unlink(handle_t *handle, struct dentry *dentry);
+void ext4_fc_track_link(handle_t *handle, struct dentry *dentry);
+void ext4_fc_track_create(handle_t *handle, struct dentry *dentry);
+void ext4_fc_track_inode(handle_t *handle, struct inode *inode);
 void ext4_fc_mark_ineligible(struct super_block *sb, int reason);
 void ext4_fc_start_ineligible(struct super_block *sb, int reason);
 void ext4_fc_stop_ineligible(struct super_block *sb);
@@ -3459,7 +3463,7 @@ extern int ext4_handle_dirty_dirblock(handle_t *handle, struct inode *inode,
 extern int ext4_ci_compare(const struct inode *parent,
                           const struct qstr *fname,
                           const struct qstr *entry, bool quick);
-extern int __ext4_unlink(struct inode *dir, const struct qstr *d_name,
+extern int __ext4_unlink(handle_t *handle, struct inode *dir, const struct qstr *d_name,
                         struct inode *inode);
 extern int __ext4_link(struct inode *dir, struct inode *inode,
                       struct dentry *dentry);
index 94ba447..17d7096 100644 (file)
@@ -4599,7 +4599,7 @@ static long ext4_zero_range(struct file *file, loff_t offset,
        ret = ext4_mark_inode_dirty(handle, inode);
        if (unlikely(ret))
                goto out_handle;
-       ext4_fc_track_range(inode, offset >> inode->i_sb->s_blocksize_bits,
+       ext4_fc_track_range(handle, inode, offset >> inode->i_sb->s_blocksize_bits,
                        (offset + len - 1) >> inode->i_sb->s_blocksize_bits);
        /* Zero out partial block at the edges of the range */
        ret = ext4_zero_partial_blocks(handle, inode, offset, len);
index 48b7bc1..9399e9c 100644 (file)
@@ -323,13 +323,14 @@ static inline int ext4_fc_is_ineligible(struct super_block *sb)
  * If enqueue is set, this function enqueues the inode in fast commit list.
  */
 static int ext4_fc_track_template(
-       struct inode *inode, int (*__fc_track_fn)(struct inode *, void *, bool),
+       handle_t *handle, struct inode *inode,
+       int (*__fc_track_fn)(struct inode *, void *, bool),
        void *args, int enqueue)
 {
-       tid_t running_txn_tid;
        bool update = false;
        struct ext4_inode_info *ei = EXT4_I(inode);
        struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
+       tid_t tid = 0;
        int ret;
 
        if (!test_opt2(inode->i_sb, JOURNAL_FAST_COMMIT) ||
@@ -339,15 +340,13 @@ static int ext4_fc_track_template(
        if (ext4_fc_is_ineligible(inode->i_sb))
                return -EINVAL;
 
-       running_txn_tid = sbi->s_journal ?
-               sbi->s_journal->j_commit_sequence + 1 : 0;
-
+       tid = handle->h_transaction->t_tid;
        mutex_lock(&ei->i_fc_lock);
-       if (running_txn_tid == ei->i_sync_tid) {
+       if (tid == ei->i_sync_tid) {
                update = true;
        } else {
                ext4_fc_reset_inode(inode);
-               ei->i_sync_tid = running_txn_tid;
+               ei->i_sync_tid = tid;
        }
        ret = __fc_track_fn(inode, args, update);
        mutex_unlock(&ei->i_fc_lock);
@@ -422,7 +421,8 @@ static int __track_dentry_update(struct inode *inode, void *arg, bool update)
        return 0;
 }
 
-void ext4_fc_track_unlink(struct inode *inode, struct dentry *dentry)
+void __ext4_fc_track_unlink(handle_t *handle,
+               struct inode *inode, struct dentry *dentry)
 {
        struct __track_dentry_update_args args;
        int ret;
@@ -430,12 +430,18 @@ void ext4_fc_track_unlink(struct inode *inode, struct dentry *dentry)
        args.dentry = dentry;
        args.op = EXT4_FC_TAG_UNLINK;
 
-       ret = ext4_fc_track_template(inode, __track_dentry_update,
+       ret = ext4_fc_track_template(handle, inode, __track_dentry_update,
                                        (void *)&args, 0);
        trace_ext4_fc_track_unlink(inode, dentry, ret);
 }
 
-void ext4_fc_track_link(struct inode *inode, struct dentry *dentry)
+void ext4_fc_track_unlink(handle_t *handle, struct dentry *dentry)
+{
+       __ext4_fc_track_unlink(handle, d_inode(dentry), dentry);
+}
+
+void __ext4_fc_track_link(handle_t *handle,
+       struct inode *inode, struct dentry *dentry)
 {
        struct __track_dentry_update_args args;
        int ret;
@@ -443,20 +449,26 @@ void ext4_fc_track_link(struct inode *inode, struct dentry *dentry)
        args.dentry = dentry;
        args.op = EXT4_FC_TAG_LINK;
 
-       ret = ext4_fc_track_template(inode, __track_dentry_update,
+       ret = ext4_fc_track_template(handle, inode, __track_dentry_update,
                                        (void *)&args, 0);
        trace_ext4_fc_track_link(inode, dentry, ret);
 }
 
-void ext4_fc_track_create(struct inode *inode, struct dentry *dentry)
+void ext4_fc_track_link(handle_t *handle, struct dentry *dentry)
+{
+       __ext4_fc_track_link(handle, d_inode(dentry), dentry);
+}
+
+void ext4_fc_track_create(handle_t *handle, struct dentry *dentry)
 {
        struct __track_dentry_update_args args;
+       struct inode *inode = d_inode(dentry);
        int ret;
 
        args.dentry = dentry;
        args.op = EXT4_FC_TAG_CREAT;
 
-       ret = ext4_fc_track_template(inode, __track_dentry_update,
+       ret = ext4_fc_track_template(handle, inode, __track_dentry_update,
                                        (void *)&args, 0);
        trace_ext4_fc_track_create(inode, dentry, ret);
 }
@@ -472,14 +484,14 @@ static int __track_inode(struct inode *inode, void *arg, bool update)
        return 0;
 }
 
-void ext4_fc_track_inode(struct inode *inode)
+void ext4_fc_track_inode(handle_t *handle, struct inode *inode)
 {
        int ret;
 
        if (S_ISDIR(inode->i_mode))
                return;
 
-       ret = ext4_fc_track_template(inode, __track_inode, NULL, 1);
+       ret = ext4_fc_track_template(handle, inode, __track_inode, NULL, 1);
        trace_ext4_fc_track_inode(inode, ret);
 }
 
@@ -515,7 +527,7 @@ static int __track_range(struct inode *inode, void *arg, bool update)
        return 0;
 }
 
-void ext4_fc_track_range(struct inode *inode, ext4_lblk_t start,
+void ext4_fc_track_range(handle_t *handle, struct inode *inode, ext4_lblk_t start,
                         ext4_lblk_t end)
 {
        struct __track_range_args args;
@@ -527,7 +539,7 @@ void ext4_fc_track_range(struct inode *inode, ext4_lblk_t start,
        args.start = start;
        args.end = end;
 
-       ret = ext4_fc_track_template(inode,  __track_range, &args, 1);
+       ret = ext4_fc_track_template(handle, inode,  __track_range, &args, 1);
 
        trace_ext4_fc_track_range(inode, start, end, ret);
 }
@@ -1263,7 +1275,7 @@ static int ext4_fc_replay_unlink(struct super_block *sb, struct ext4_fc_tl *tl)
                return 0;
        }
 
-       ret = __ext4_unlink(old_parent, &entry, inode);
+       ret = __ext4_unlink(NULL, old_parent, &entry, inode);
        /* -ENOENT ok coz it might not exist anymore. */
        if (ret == -ENOENT)
                ret = 0;
index 081b6a8..87120c4 100644 (file)
@@ -732,7 +732,7 @@ out_sem:
                        if (ret)
                                return ret;
                }
-               ext4_fc_track_range(inode, map->m_lblk,
+               ext4_fc_track_range(handle, inode, map->m_lblk,
                            map->m_lblk + map->m_len - 1);
        }
 
@@ -4111,7 +4111,7 @@ int ext4_punch_hole(struct inode *inode, loff_t offset, loff_t length)
 
                up_write(&EXT4_I(inode)->i_data_sem);
        }
-       ext4_fc_track_range(inode, first_block, stop_block);
+       ext4_fc_track_range(handle, inode, first_block, stop_block);
        if (IS_SYNC(inode))
                ext4_handle_sync(handle);
 
@@ -5444,14 +5444,14 @@ int ext4_setattr(struct dentry *dentry, struct iattr *attr)
                        }
 
                        if (shrink)
-                               ext4_fc_track_range(inode,
+                               ext4_fc_track_range(handle, inode,
                                        (attr->ia_size > 0 ? attr->ia_size - 1 : 0) >>
                                        inode->i_sb->s_blocksize_bits,
                                        (oldsize > 0 ? oldsize - 1 : 0) >>
                                        inode->i_sb->s_blocksize_bits);
                        else
                                ext4_fc_track_range(
-                                       inode,
+                                       handle, inode,
                                        (oldsize > 0 ? oldsize - 1 : oldsize) >>
                                        inode->i_sb->s_blocksize_bits,
                                        (attr->ia_size > 0 ? attr->ia_size - 1 : 0) >>
@@ -5701,7 +5701,7 @@ int ext4_mark_iloc_dirty(handle_t *handle,
                put_bh(iloc->bh);
                return -EIO;
        }
-       ext4_fc_track_inode(inode);
+       ext4_fc_track_inode(handle, inode);
 
        if (IS_I_VERSION(inode))
                inode_inc_iversion(inode);
index f458d1d..3350926 100644 (file)
@@ -2606,7 +2606,7 @@ static int ext4_create(struct inode *dir, struct dentry *dentry, umode_t mode,
                       bool excl)
 {
        handle_t *handle;
-       struct inode *inode, *inode_save;
+       struct inode *inode;
        int err, credits, retries = 0;
 
        err = dquot_initialize(dir);
@@ -2624,11 +2624,9 @@ retry:
                inode->i_op = &ext4_file_inode_operations;
                inode->i_fop = &ext4_file_operations;
                ext4_set_aops(inode);
-               inode_save = inode;
-               ihold(inode_save);
                err = ext4_add_nondir(handle, dentry, &inode);
-               ext4_fc_track_create(inode_save, dentry);
-               iput(inode_save);
+               if (!err)
+                       ext4_fc_track_create(handle, dentry);
        }
        if (handle)
                ext4_journal_stop(handle);
@@ -2643,7 +2641,7 @@ static int ext4_mknod(struct inode *dir, struct dentry *dentry,
                      umode_t mode, dev_t rdev)
 {
        handle_t *handle;
-       struct inode *inode, *inode_save;
+       struct inode *inode;
        int err, credits, retries = 0;
 
        err = dquot_initialize(dir);
@@ -2660,12 +2658,9 @@ retry:
        if (!IS_ERR(inode)) {
                init_special_inode(inode, inode->i_mode, rdev);
                inode->i_op = &ext4_special_inode_operations;
-               inode_save = inode;
-               ihold(inode_save);
                err = ext4_add_nondir(handle, dentry, &inode);
                if (!err)
-                       ext4_fc_track_create(inode_save, dentry);
-               iput(inode_save);
+                       ext4_fc_track_create(handle, dentry);
        }
        if (handle)
                ext4_journal_stop(handle);
@@ -2829,7 +2824,6 @@ out_clear_inode:
                iput(inode);
                goto out_retry;
        }
-       ext4_fc_track_create(inode, dentry);
        ext4_inc_count(dir);
 
        ext4_update_dx_flag(dir);
@@ -2837,6 +2831,7 @@ out_clear_inode:
        if (err)
                goto out_clear_inode;
        d_instantiate_new(dentry, inode);
+       ext4_fc_track_create(handle, dentry);
        if (IS_DIRSYNC(dir))
                ext4_handle_sync(handle);
 
@@ -3171,7 +3166,7 @@ static int ext4_rmdir(struct inode *dir, struct dentry *dentry)
                goto end_rmdir;
        ext4_dec_count(dir);
        ext4_update_dx_flag(dir);
-       ext4_fc_track_unlink(inode, dentry);
+       ext4_fc_track_unlink(handle, dentry);
        retval = ext4_mark_inode_dirty(handle, dir);
 
 #ifdef CONFIG_UNICODE
@@ -3192,13 +3187,12 @@ end_rmdir:
        return retval;
 }
 
-int __ext4_unlink(struct inode *dir, const struct qstr *d_name,
+int __ext4_unlink(handle_t *handle, struct inode *dir, const struct qstr *d_name,
                  struct inode *inode)
 {
        int retval = -ENOENT;
        struct buffer_head *bh;
        struct ext4_dir_entry_2 *de;
-       handle_t *handle = NULL;
        int skip_remove_dentry = 0;
 
        bh = ext4_find_entry(dir, d_name, &de, NULL);
@@ -3217,14 +3211,7 @@ int __ext4_unlink(struct inode *dir, const struct qstr *d_name,
                if (EXT4_SB(inode->i_sb)->s_mount_state & EXT4_FC_REPLAY)
                        skip_remove_dentry = 1;
                else
-                       goto out_bh;
-       }
-
-       handle = ext4_journal_start(dir, EXT4_HT_DIR,
-                                   EXT4_DATA_TRANS_BLOCKS(dir->i_sb));
-       if (IS_ERR(handle)) {
-               retval = PTR_ERR(handle);
-               goto out_bh;
+                       goto out;
        }
 
        if (IS_DIRSYNC(dir))
@@ -3233,12 +3220,12 @@ int __ext4_unlink(struct inode *dir, const struct qstr *d_name,
        if (!skip_remove_dentry) {
                retval = ext4_delete_entry(handle, dir, de, bh);
                if (retval)
-                       goto out_handle;
+                       goto out;
                dir->i_ctime = dir->i_mtime = current_time(dir);
                ext4_update_dx_flag(dir);
                retval = ext4_mark_inode_dirty(handle, dir);
                if (retval)
-                       goto out_handle;
+                       goto out;
        } else {
                retval = 0;
        }
@@ -3252,15 +3239,14 @@ int __ext4_unlink(struct inode *dir, const struct qstr *d_name,
        inode->i_ctime = current_time(inode);
        retval = ext4_mark_inode_dirty(handle, inode);
 
-out_handle:
-       ext4_journal_stop(handle);
-out_bh:
+out:
        brelse(bh);
        return retval;
 }
 
 static int ext4_unlink(struct inode *dir, struct dentry *dentry)
 {
+       handle_t *handle;
        int retval;
 
        if (unlikely(ext4_forced_shutdown(EXT4_SB(dir->i_sb))))
@@ -3278,9 +3264,16 @@ static int ext4_unlink(struct inode *dir, struct dentry *dentry)
        if (retval)
                goto out_trace;
 
-       retval = __ext4_unlink(dir, &dentry->d_name, d_inode(dentry));
+       handle = ext4_journal_start(dir, EXT4_HT_DIR,
+                                   EXT4_DATA_TRANS_BLOCKS(dir->i_sb));
+       if (IS_ERR(handle)) {
+               retval = PTR_ERR(handle);
+               goto out_trace;
+       }
+
+       retval = __ext4_unlink(handle, dir, &dentry->d_name, d_inode(dentry));
        if (!retval)
-               ext4_fc_track_unlink(d_inode(dentry), dentry);
+               ext4_fc_track_unlink(handle, dentry);
 #ifdef CONFIG_UNICODE
        /* VFS negative dentries are incompatible with Encoding and
         * Case-insensitiveness. Eventually we'll want avoid
@@ -3291,6 +3284,8 @@ static int ext4_unlink(struct inode *dir, struct dentry *dentry)
        if (IS_CASEFOLDED(dir))
                d_invalidate(dentry);
 #endif
+       if (handle)
+               ext4_journal_stop(handle);
 
 out_trace:
        trace_ext4_unlink_exit(dentry, retval);
@@ -3447,7 +3442,6 @@ retry:
 
        err = ext4_add_entry(handle, dentry, inode);
        if (!err) {
-               ext4_fc_track_link(inode, dentry);
                err = ext4_mark_inode_dirty(handle, inode);
                /* this can happen only for tmpfile being
                 * linked the first time
@@ -3455,6 +3449,7 @@ retry:
                if (inode->i_nlink == 1)
                        ext4_orphan_del(handle, inode);
                d_instantiate(dentry, inode);
+               ext4_fc_track_link(handle, dentry);
        } else {
                drop_nlink(inode);
                iput(inode);
@@ -3915,9 +3910,9 @@ static int ext4_rename(struct inode *old_dir, struct dentry *old_dentry,
                        EXT4_FC_REASON_RENAME_DIR);
        } else {
                if (new.inode)
-                       ext4_fc_track_unlink(new.inode, new.dentry);
-               ext4_fc_track_link(old.inode, new.dentry);
-               ext4_fc_track_unlink(old.inode, old.dentry);
+                       ext4_fc_track_unlink(handle, new.dentry);
+               __ext4_fc_track_link(handle, old.inode, new.dentry);
+               __ext4_fc_track_unlink(handle, old.inode, old.dentry);
        }
 
        if (new.inode) {