]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
f2fs: change to use rwsem for gc_mutex
authorChao Yu <yuchao0@huawei.com>
Tue, 14 Jan 2020 11:36:50 +0000 (19:36 +0800)
committerJaegeuk Kim <jaegeuk@kernel.org>
Sat, 18 Jan 2020 00:48:44 +0000 (16:48 -0800)
Mutex lock won't serialize callers, in order to avoid starving of unlucky
caller, let's use rwsem lock instead.

Signed-off-by: Chao Yu <yuchao0@huawei.com>
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
fs/f2fs/f2fs.h
fs/f2fs/file.c
fs/f2fs/gc.c
fs/f2fs/segment.c
fs/f2fs/super.c

index e7208442d32aa101b987f51b4ef66410593072eb..61d62cd06449ea8f6d0d08933607755a3b8af969 100644 (file)
@@ -1391,7 +1391,10 @@ struct f2fs_sb_info {
        struct f2fs_mount_info mount_opt;       /* mount options */
 
        /* for cleaning operations */
-       struct mutex gc_mutex;                  /* mutex for GC */
+       struct rw_semaphore gc_lock;            /*
+                                                * semaphore for GC, avoid
+                                                * race between GC and GC or CP
+                                                */
        struct f2fs_gc_kthread  *gc_thread;     /* GC thread */
        unsigned int cur_victim_sec;            /* current victim section num */
        unsigned int gc_mode;                   /* current GC state */
index 0dff22566a1d1fa545c0a91fbd29b175add5166e..86ddbb55d2b187122453d151b35d964bf0d6b91b 100644 (file)
@@ -1642,7 +1642,7 @@ static int expand_inode_data(struct inode *inode, loff_t offset,
 next_alloc:
                if (has_not_enough_free_secs(sbi, 0,
                        GET_SEC_FROM_SEG(sbi, overprovision_segments(sbi)))) {
-                       mutex_lock(&sbi->gc_mutex);
+                       down_write(&sbi->gc_lock);
                        err = f2fs_gc(sbi, true, false, NULL_SEGNO);
                        if (err && err != -ENODATA && err != -EAGAIN)
                                goto out_err;
@@ -2450,12 +2450,12 @@ static int f2fs_ioc_gc(struct file *filp, unsigned long arg)
                return ret;
 
        if (!sync) {
-               if (!mutex_trylock(&sbi->gc_mutex)) {
+               if (!down_write_trylock(&sbi->gc_lock)) {
                        ret = -EBUSY;
                        goto out;
                }
        } else {
-               mutex_lock(&sbi->gc_mutex);
+               down_write(&sbi->gc_lock);
        }
 
        ret = f2fs_gc(sbi, sync, true, NULL_SEGNO);
@@ -2493,12 +2493,12 @@ static int f2fs_ioc_gc_range(struct file *filp, unsigned long arg)
 
 do_more:
        if (!range.sync) {
-               if (!mutex_trylock(&sbi->gc_mutex)) {
+               if (!down_write_trylock(&sbi->gc_lock)) {
                        ret = -EBUSY;
                        goto out;
                }
        } else {
-               mutex_lock(&sbi->gc_mutex);
+               down_write(&sbi->gc_lock);
        }
 
        ret = f2fs_gc(sbi, range.sync, true, GET_SEGNO(sbi, range.start));
@@ -2929,7 +2929,7 @@ static int f2fs_ioc_flush_device(struct file *filp, unsigned long arg)
        end_segno = min(start_segno + range.segments, dev_end_segno);
 
        while (start_segno < end_segno) {
-               if (!mutex_trylock(&sbi->gc_mutex)) {
+               if (!down_write_trylock(&sbi->gc_lock)) {
                        ret = -EBUSY;
                        goto out;
                }
index c43181ef98c46e0e7907c8152fa9e9f4fac7e65c..67eca7c2d9838a1bb046b7029054038f34d8b063 100644 (file)
@@ -78,18 +78,18 @@ static int gc_thread_func(void *data)
                 */
                if (sbi->gc_mode == GC_URGENT) {
                        wait_ms = gc_th->urgent_sleep_time;
-                       mutex_lock(&sbi->gc_mutex);
+                       down_write(&sbi->gc_lock);
                        goto do_gc;
                }
 
-               if (!mutex_trylock(&sbi->gc_mutex)) {
+               if (!down_write_trylock(&sbi->gc_lock)) {
                        stat_other_skip_bggc_count(sbi);
                        goto next;
                }
 
                if (!is_idle(sbi, GC_TIME)) {
                        increase_sleep_time(gc_th, &wait_ms);
-                       mutex_unlock(&sbi->gc_mutex);
+                       up_write(&sbi->gc_lock);
                        stat_io_skip_bggc_count(sbi);
                        goto next;
                }
@@ -1370,7 +1370,7 @@ int f2fs_gc(struct f2fs_sb_info *sbi, bool sync,
                                reserved_segments(sbi),
                                prefree_segments(sbi));
 
-       mutex_unlock(&sbi->gc_mutex);
+       up_write(&sbi->gc_lock);
 
        put_gc_inode(&gc_list);
 
@@ -1409,9 +1409,9 @@ static int free_segment_range(struct f2fs_sb_info *sbi, unsigned int start,
                        .iroot = RADIX_TREE_INIT(gc_list.iroot, GFP_NOFS),
                };
 
-               mutex_lock(&sbi->gc_mutex);
+               down_write(&sbi->gc_lock);
                do_garbage_collect(sbi, segno, &gc_list, FG_GC);
-               mutex_unlock(&sbi->gc_mutex);
+               up_write(&sbi->gc_lock);
                put_gc_inode(&gc_list);
 
                if (get_valid_blocks(sbi, segno, true))
index 1d3bb2605b038dca691ceca88d890037356aad01..cf0eb002cfd40ced0bd135ab9593f9d30df68af0 100644 (file)
@@ -504,7 +504,7 @@ void f2fs_balance_fs(struct f2fs_sb_info *sbi, bool need)
         * dir/node pages without enough free segments.
         */
        if (has_not_enough_free_secs(sbi, 0, 0)) {
-               mutex_lock(&sbi->gc_mutex);
+               down_write(&sbi->gc_lock);
                f2fs_gc(sbi, false, false, NULL_SEGNO);
        }
 }
@@ -2860,9 +2860,9 @@ int f2fs_trim_fs(struct f2fs_sb_info *sbi, struct fstrim_range *range)
        if (sbi->discard_blks == 0)
                goto out;
 
-       mutex_lock(&sbi->gc_mutex);
+       down_write(&sbi->gc_lock);
        err = f2fs_write_checkpoint(sbi, &cpc);
-       mutex_unlock(&sbi->gc_mutex);
+       up_write(&sbi->gc_lock);
        if (err)
                goto out;
 
index 593dc3d2b80b56b14cddf62c478569179c8aa0be..65a7a432dfee26f0df4354a3254782b1e090e28a 100644 (file)
@@ -1238,9 +1238,9 @@ int f2fs_sync_fs(struct super_block *sb, int sync)
 
                cpc.reason = __get_cp_reason(sbi);
 
-               mutex_lock(&sbi->gc_mutex);
+               down_write(&sbi->gc_lock);
                err = f2fs_write_checkpoint(sbi, &cpc);
-               mutex_unlock(&sbi->gc_mutex);
+               up_write(&sbi->gc_lock);
        }
        f2fs_trace_ios(NULL, 1);
 
@@ -1621,7 +1621,7 @@ static int f2fs_disable_checkpoint(struct f2fs_sb_info *sbi)
        f2fs_update_time(sbi, DISABLE_TIME);
 
        while (!f2fs_time_over(sbi, DISABLE_TIME)) {
-               mutex_lock(&sbi->gc_mutex);
+               down_write(&sbi->gc_lock);
                err = f2fs_gc(sbi, true, false, NULL_SEGNO);
                if (err == -ENODATA) {
                        err = 0;
@@ -1643,7 +1643,7 @@ static int f2fs_disable_checkpoint(struct f2fs_sb_info *sbi)
                goto restore_flag;
        }
 
-       mutex_lock(&sbi->gc_mutex);
+       down_write(&sbi->gc_lock);
        cpc.reason = CP_PAUSE;
        set_sbi_flag(sbi, SBI_CP_DISABLED);
        err = f2fs_write_checkpoint(sbi, &cpc);
@@ -1655,7 +1655,7 @@ static int f2fs_disable_checkpoint(struct f2fs_sb_info *sbi)
        spin_unlock(&sbi->stat_lock);
 
 out_unlock:
-       mutex_unlock(&sbi->gc_mutex);
+       up_write(&sbi->gc_lock);
 restore_flag:
        sbi->sb->s_flags = s_flags;     /* Restore MS_RDONLY status */
        return err;
@@ -1663,12 +1663,12 @@ static int f2fs_disable_checkpoint(struct f2fs_sb_info *sbi)
 
 static void f2fs_enable_checkpoint(struct f2fs_sb_info *sbi)
 {
-       mutex_lock(&sbi->gc_mutex);
+       down_write(&sbi->gc_lock);
        f2fs_dirty_to_prefree(sbi);
 
        clear_sbi_flag(sbi, SBI_CP_DISABLED);
        set_sbi_flag(sbi, SBI_IS_DIRTY);
-       mutex_unlock(&sbi->gc_mutex);
+       up_write(&sbi->gc_lock);
 
        f2fs_sync_fs(sbi->sb, 1);
 }
@@ -3398,7 +3398,7 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent)
 
        /* init f2fs-specific super block info */
        sbi->valid_super_block = valid_super_block;
-       mutex_init(&sbi->gc_mutex);
+       init_rwsem(&sbi->gc_lock);
        mutex_init(&sbi->writepages);
        mutex_init(&sbi->cp_mutex);
        mutex_init(&sbi->resize_mutex);