f2fs: use kvmalloc, if kmalloc is failed
authorJaegeuk Kim <jaegeuk@kernel.org>
Fri, 14 Dec 2018 02:38:33 +0000 (18:38 -0800)
committerJaegeuk Kim <jaegeuk@kernel.org>
Wed, 26 Dec 2018 23:16:53 +0000 (15:16 -0800)
One report says memalloc failure during mount.

 (unwind_backtrace) from [<c010cd4c>] (show_stack+0x10/0x14)
 (show_stack) from [<c049c6b8>] (dump_stack+0x8c/0xa0)
 (dump_stack) from [<c024fcf0>] (warn_alloc+0xc4/0x160)
 (warn_alloc) from [<c0250218>] (__alloc_pages_nodemask+0x3f4/0x10d0)
 (__alloc_pages_nodemask) from [<c0270450>] (kmalloc_order_trace+0x2c/0x120)
 (kmalloc_order_trace) from [<c03fa748>] (build_node_manager+0x35c/0x688)
 (build_node_manager) from [<c03de494>] (f2fs_fill_super+0xf0c/0x16cc)
 (f2fs_fill_super) from [<c02a5864>] (mount_bdev+0x15c/0x188)
 (mount_bdev) from [<c03da624>] (f2fs_mount+0x18/0x20)
 (f2fs_mount) from [<c02a68b8>] (mount_fs+0x158/0x19c)
 (mount_fs) from [<c02c3c9c>] (vfs_kern_mount+0x78/0x134)
 (vfs_kern_mount) from [<c02c76ac>] (do_mount+0x474/0xca4)
 (do_mount) from [<c02c8264>] (SyS_mount+0x94/0xbc)
 (SyS_mount) from [<c0108180>] (ret_fast_syscall+0x0/0x48)

Reviewed-by: Chao Yu <yuchao0@huawei.com>
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
fs/f2fs/acl.c
fs/f2fs/checkpoint.c
fs/f2fs/data.c
fs/f2fs/debug.c
fs/f2fs/f2fs.h
fs/f2fs/gc.c
fs/f2fs/inline.c
fs/f2fs/namei.c
fs/f2fs/node.c
fs/f2fs/segment.c
fs/f2fs/super.c

index 22f0d17..63e5995 100644 (file)
@@ -160,7 +160,7 @@ static void *f2fs_acl_to_disk(struct f2fs_sb_info *sbi,
        return (void *)f2fs_acl;
 
 fail:
-       kfree(f2fs_acl);
+       kvfree(f2fs_acl);
        return ERR_PTR(-EINVAL);
 }
 
@@ -190,7 +190,7 @@ static struct posix_acl *__f2fs_get_acl(struct inode *inode, int type,
                acl = NULL;
        else
                acl = ERR_PTR(retval);
-       kfree(value);
+       kvfree(value);
 
        return acl;
 }
@@ -240,7 +240,7 @@ static int __f2fs_set_acl(struct inode *inode, int type,
 
        error = f2fs_setxattr(inode, name_index, "", value, size, ipage, 0);
 
-       kfree(value);
+       kvfree(value);
        if (!error)
                set_cached_acl(inode, type, acl);
 
index 4f02461..1d82833 100644 (file)
@@ -911,7 +911,7 @@ free_fail_no_cp:
        f2fs_put_page(cp1, 1);
        f2fs_put_page(cp2, 1);
 fail_no_cp:
-       kfree(sbi->ckpt);
+       kvfree(sbi->ckpt);
        return -EINVAL;
 }
 
index fd3a1e5..59d86f6 100644 (file)
@@ -2573,7 +2573,7 @@ static void f2fs_dio_end_io(struct bio *bio)
        bio->bi_private = dio->orig_private;
        bio->bi_end_io = dio->orig_end_io;
 
-       kfree(dio);
+       kvfree(dio);
 
        bio_endio(bio);
 }
index 1f1230f..11d4448 100644 (file)
@@ -503,7 +503,7 @@ void f2fs_destroy_stats(struct f2fs_sb_info *sbi)
        list_del(&si->stat_list);
        mutex_unlock(&f2fs_stat_mutex);
 
-       kfree(si);
+       kvfree(si);
 }
 
 int __init f2fs_create_root_stats(void)
index 03e7b37..d30b4a0 100644 (file)
@@ -1630,7 +1630,7 @@ static inline void disable_nat_bits(struct f2fs_sb_info *sbi, bool lock)
        if (lock)
                spin_lock_irqsave(&sbi->cp_lock, flags);
        __clear_ckpt_flags(F2FS_CKPT(sbi), CP_NAT_BITS_FLAG);
-       kfree(NM_I(sbi)->nat_bits);
+       kvfree(NM_I(sbi)->nat_bits);
        NM_I(sbi)->nat_bits = NULL;
        if (lock)
                spin_unlock_irqrestore(&sbi->cp_lock, flags);
@@ -2704,12 +2704,18 @@ static inline bool f2fs_may_extent_tree(struct inode *inode)
 static inline void *f2fs_kmalloc(struct f2fs_sb_info *sbi,
                                        size_t size, gfp_t flags)
 {
+       void *ret;
+
        if (time_to_inject(sbi, FAULT_KMALLOC)) {
                f2fs_show_injection_info(FAULT_KMALLOC);
                return NULL;
        }
 
-       return kmalloc(size, flags);
+       ret = kmalloc(size, flags);
+       if (ret)
+               return ret;
+
+       return kvmalloc(size, flags);
 }
 
 static inline void *f2fs_kzalloc(struct f2fs_sb_info *sbi,
index 666518e..aed7084 100644 (file)
@@ -142,7 +142,7 @@ int f2fs_start_gc_thread(struct f2fs_sb_info *sbi)
                        "f2fs_gc-%u:%u", MAJOR(dev), MINOR(dev));
        if (IS_ERR(gc_th->f2fs_gc_task)) {
                err = PTR_ERR(gc_th->f2fs_gc_task);
-               kfree(gc_th);
+               kvfree(gc_th);
                sbi->gc_thread = NULL;
        }
 out:
@@ -155,7 +155,7 @@ void f2fs_stop_gc_thread(struct f2fs_sb_info *sbi)
        if (!gc_th)
                return;
        kthread_stop(gc_th->f2fs_gc_task);
-       kfree(gc_th);
+       kvfree(gc_th);
        sbi->gc_thread = NULL;
 }
 
index 7b0cff7..0113beb 100644 (file)
@@ -501,7 +501,7 @@ static int f2fs_move_rehashed_dirents(struct inode *dir, struct page *ipage,
 
        stat_dec_inline_dir(dir);
        clear_inode_flag(dir, FI_INLINE_DENTRY);
-       kfree(backup_dentry);
+       kvfree(backup_dentry);
        return 0;
 recover:
        lock_page(ipage);
@@ -512,7 +512,7 @@ recover:
        set_page_dirty(ipage);
        f2fs_put_page(ipage, 1);
 
-       kfree(backup_dentry);
+       kvfree(backup_dentry);
        return err;
 }
 
index 2d56269..62d9829 100644 (file)
@@ -635,7 +635,7 @@ out_f2fs_handle_failed_inode:
        f2fs_handle_failed_inode(inode);
 out_free_encrypted_link:
        if (disk_link.name != (unsigned char *)symname)
-               kfree(disk_link.name);
+               kvfree(disk_link.name);
        return err;
 }
 
index c09df77..20c08fb 100644 (file)
@@ -3116,17 +3116,17 @@ void f2fs_destroy_node_manager(struct f2fs_sb_info *sbi)
 
                for (i = 0; i < nm_i->nat_blocks; i++)
                        kvfree(nm_i->free_nid_bitmap[i]);
-               kfree(nm_i->free_nid_bitmap);
+               kvfree(nm_i->free_nid_bitmap);
        }
        kvfree(nm_i->free_nid_count);
 
-       kfree(nm_i->nat_bitmap);
-       kfree(nm_i->nat_bits);
+       kvfree(nm_i->nat_bitmap);
+       kvfree(nm_i->nat_bits);
 #ifdef CONFIG_F2FS_CHECK_FS
-       kfree(nm_i->nat_bitmap_mir);
+       kvfree(nm_i->nat_bitmap_mir);
 #endif
        sbi->nm_info = NULL;
-       kfree(nm_i);
+       kvfree(nm_i);
 }
 
 int __init f2fs_create_node_manager_caches(void)
index e2e971e..de2c919 100644 (file)
@@ -706,7 +706,7 @@ init_thread:
                                "f2fs_flush-%u:%u", MAJOR(dev), MINOR(dev));
        if (IS_ERR(fcc->f2fs_issue_flush)) {
                err = PTR_ERR(fcc->f2fs_issue_flush);
-               kfree(fcc);
+               kvfree(fcc);
                SM_I(sbi)->fcc_info = NULL;
                return err;
        }
@@ -725,7 +725,7 @@ void f2fs_destroy_flush_cmd_control(struct f2fs_sb_info *sbi, bool free)
                kthread_stop(flush_thread);
        }
        if (free) {
-               kfree(fcc);
+               kvfree(fcc);
                SM_I(sbi)->fcc_info = NULL;
        }
 }
@@ -2013,7 +2013,7 @@ init_thread:
                                "f2fs_discard-%u:%u", MAJOR(dev), MINOR(dev));
        if (IS_ERR(dcc->f2fs_issue_discard)) {
                err = PTR_ERR(dcc->f2fs_issue_discard);
-               kfree(dcc);
+               kvfree(dcc);
                SM_I(sbi)->dcc_info = NULL;
                return err;
        }
@@ -2030,7 +2030,7 @@ static void destroy_discard_cmd_control(struct f2fs_sb_info *sbi)
 
        f2fs_stop_discard_thread(sbi);
 
-       kfree(dcc);
+       kvfree(dcc);
        SM_I(sbi)->dcc_info = NULL;
 }
 
@@ -4317,7 +4317,7 @@ static void destroy_dirty_segmap(struct f2fs_sb_info *sbi)
 
        destroy_victim_secmap(sbi);
        SM_I(sbi)->dirty_info = NULL;
-       kfree(dirty_i);
+       kvfree(dirty_i);
 }
 
 static void destroy_curseg(struct f2fs_sb_info *sbi)
@@ -4329,10 +4329,10 @@ static void destroy_curseg(struct f2fs_sb_info *sbi)
                return;
        SM_I(sbi)->curseg_array = NULL;
        for (i = 0; i < NR_CURSEG_TYPE; i++) {
-               kfree(array[i].sum_blk);
-               kfree(array[i].journal);
+               kvfree(array[i].sum_blk);
+               kvfree(array[i].journal);
        }
-       kfree(array);
+       kvfree(array);
 }
 
 static void destroy_free_segmap(struct f2fs_sb_info *sbi)
@@ -4343,7 +4343,7 @@ static void destroy_free_segmap(struct f2fs_sb_info *sbi)
        SM_I(sbi)->free_info = NULL;
        kvfree(free_i->free_segmap);
        kvfree(free_i->free_secmap);
-       kfree(free_i);
+       kvfree(free_i);
 }
 
 static void destroy_sit_info(struct f2fs_sb_info *sbi)
@@ -4356,26 +4356,26 @@ static void destroy_sit_info(struct f2fs_sb_info *sbi)
 
        if (sit_i->sentries) {
                for (start = 0; start < MAIN_SEGS(sbi); start++) {
-                       kfree(sit_i->sentries[start].cur_valid_map);
+                       kvfree(sit_i->sentries[start].cur_valid_map);
 #ifdef CONFIG_F2FS_CHECK_FS
-                       kfree(sit_i->sentries[start].cur_valid_map_mir);
+                       kvfree(sit_i->sentries[start].cur_valid_map_mir);
 #endif
-                       kfree(sit_i->sentries[start].ckpt_valid_map);
-                       kfree(sit_i->sentries[start].discard_map);
+                       kvfree(sit_i->sentries[start].ckpt_valid_map);
+                       kvfree(sit_i->sentries[start].discard_map);
                }
        }
-       kfree(sit_i->tmp_map);
+       kvfree(sit_i->tmp_map);
 
        kvfree(sit_i->sentries);
        kvfree(sit_i->sec_entries);
        kvfree(sit_i->dirty_sentries_bitmap);
 
        SM_I(sbi)->sit_info = NULL;
-       kfree(sit_i->sit_bitmap);
+       kvfree(sit_i->sit_bitmap);
 #ifdef CONFIG_F2FS_CHECK_FS
-       kfree(sit_i->sit_bitmap_mir);
+       kvfree(sit_i->sit_bitmap_mir);
 #endif
-       kfree(sit_i);
+       kvfree(sit_i);
 }
 
 void f2fs_destroy_segment_manager(struct f2fs_sb_info *sbi)
@@ -4391,7 +4391,7 @@ void f2fs_destroy_segment_manager(struct f2fs_sb_info *sbi)
        destroy_free_segmap(sbi);
        destroy_sit_info(sbi);
        sbi->sm_info = NULL;
-       kfree(sm_info);
+       kvfree(sm_info);
 }
 
 int __init f2fs_create_segment_manager_caches(void)
index e184ad4..b796776 100644 (file)
@@ -289,7 +289,7 @@ static int f2fs_set_qf_name(struct super_block *sb, int qtype,
        set_opt(sbi, QUOTA);
        return 0;
 errout:
-       kfree(qname);
+       kvfree(qname);
        return ret;
 }
 
@@ -302,7 +302,7 @@ static int f2fs_clear_qf_name(struct super_block *sb, int qtype)
                        " when quota turned on");
                return -EINVAL;
        }
-       kfree(F2FS_OPTION(sbi).s_qf_names[qtype]);
+       kvfree(F2FS_OPTION(sbi).s_qf_names[qtype]);
        F2FS_OPTION(sbi).s_qf_names[qtype] = NULL;
        return 0;
 }
@@ -399,10 +399,10 @@ static int parse_options(struct super_block *sb, char *options)
                                set_opt(sbi, BG_GC);
                                set_opt(sbi, FORCE_FG_GC);
                        } else {
-                               kfree(name);
+                               kvfree(name);
                                return -EINVAL;
                        }
-                       kfree(name);
+                       kvfree(name);
                        break;
                case Opt_disable_roll_forward:
                        set_opt(sbi, DISABLE_ROLL_FORWARD);
@@ -570,7 +570,7 @@ static int parse_options(struct super_block *sb, char *options)
                                        f2fs_msg(sb, KERN_WARNING,
                                                 "adaptive mode is not allowed with "
                                                 "zoned block device feature");
-                                       kfree(name);
+                                       kvfree(name);
                                        return -EINVAL;
                                }
                                set_opt_mode(sbi, F2FS_MOUNT_ADAPTIVE);
@@ -578,10 +578,10 @@ static int parse_options(struct super_block *sb, char *options)
                                        !strncmp(name, "lfs", 3)) {
                                set_opt_mode(sbi, F2FS_MOUNT_LFS);
                        } else {
-                               kfree(name);
+                               kvfree(name);
                                return -EINVAL;
                        }
-                       kfree(name);
+                       kvfree(name);
                        break;
                case Opt_io_size_bits:
                        if (args->from && match_int(args, &arg))
@@ -714,10 +714,10 @@ static int parse_options(struct super_block *sb, char *options)
                                        !strncmp(name, "fs-based", 8)) {
                                F2FS_OPTION(sbi).whint_mode = WHINT_MODE_FS;
                        } else {
-                               kfree(name);
+                               kvfree(name);
                                return -EINVAL;
                        }
-                       kfree(name);
+                       kvfree(name);
                        break;
                case Opt_alloc:
                        name = match_strdup(&args[0]);
@@ -731,10 +731,10 @@ static int parse_options(struct super_block *sb, char *options)
                                        !strncmp(name, "reuse", 5)) {
                                F2FS_OPTION(sbi).alloc_mode = ALLOC_MODE_REUSE;
                        } else {
-                               kfree(name);
+                               kvfree(name);
                                return -EINVAL;
                        }
-                       kfree(name);
+                       kvfree(name);
                        break;
                case Opt_fsync:
                        name = match_strdup(&args[0]);
@@ -751,10 +751,10 @@ static int parse_options(struct super_block *sb, char *options)
                                F2FS_OPTION(sbi).fsync_mode =
                                                        FSYNC_MODE_NOBARRIER;
                        } else {
-                               kfree(name);
+                               kvfree(name);
                                return -EINVAL;
                        }
-                       kfree(name);
+                       kvfree(name);
                        break;
                case Opt_test_dummy_encryption:
 #ifdef CONFIG_F2FS_FS_ENCRYPTION
@@ -783,10 +783,10 @@ static int parse_options(struct super_block *sb, char *options)
                                        !strncmp(name, "disable", 7)) {
                                set_opt(sbi, DISABLE_CHECKPOINT);
                        } else {
-                               kfree(name);
+                               kvfree(name);
                                return -EINVAL;
                        }
-                       kfree(name);
+                       kvfree(name);
                        break;
                default:
                        f2fs_msg(sb, KERN_ERR,
@@ -1017,10 +1017,10 @@ static void destroy_device_list(struct f2fs_sb_info *sbi)
        for (i = 0; i < sbi->s_ndevs; i++) {
                blkdev_put(FDEV(i).bdev, FMODE_EXCL);
 #ifdef CONFIG_BLK_DEV_ZONED
-               kfree(FDEV(i).blkz_type);
+               kvfree(FDEV(i).blkz_type);
 #endif
        }
-       kfree(sbi->devs);
+       kvfree(sbi->devs);
 }
 
 static void f2fs_put_super(struct super_block *sb)
@@ -1084,25 +1084,25 @@ static void f2fs_put_super(struct super_block *sb)
        f2fs_destroy_node_manager(sbi);
        f2fs_destroy_segment_manager(sbi);
 
-       kfree(sbi->ckpt);
+       kvfree(sbi->ckpt);
 
        f2fs_unregister_sysfs(sbi);
 
        sb->s_fs_info = NULL;
        if (sbi->s_chksum_driver)
                crypto_free_shash(sbi->s_chksum_driver);
-       kfree(sbi->raw_super);
+       kvfree(sbi->raw_super);
 
        destroy_device_list(sbi);
        mempool_destroy(sbi->write_io_dummy);
 #ifdef CONFIG_QUOTA
        for (i = 0; i < MAXQUOTAS; i++)
-               kfree(F2FS_OPTION(sbi).s_qf_names[i]);
+               kvfree(F2FS_OPTION(sbi).s_qf_names[i]);
 #endif
        destroy_percpu_info(sbi);
        for (i = 0; i < NR_PAGE_TYPE; i++)
-               kfree(sbi->write_io[i]);
-       kfree(sbi);
+               kvfree(sbi->write_io[i]);
+       kvfree(sbi);
 }
 
 int f2fs_sync_fs(struct super_block *sb, int sync)
@@ -1531,7 +1531,7 @@ static int f2fs_remount(struct super_block *sb, int *flags, char *data)
                                GFP_KERNEL);
                        if (!org_mount_opt.s_qf_names[i]) {
                                for (j = 0; j < i; j++)
-                                       kfree(org_mount_opt.s_qf_names[j]);
+                                       kvfree(org_mount_opt.s_qf_names[j]);
                                return -ENOMEM;
                        }
                } else {
@@ -1651,7 +1651,7 @@ skip:
 #ifdef CONFIG_QUOTA
        /* Release old quota file names */
        for (i = 0; i < MAXQUOTAS; i++)
-               kfree(org_mount_opt.s_qf_names[i]);
+               kvfree(org_mount_opt.s_qf_names[i]);
 #endif
        /* Update the POSIXACL Flag */
        sb->s_flags = (sb->s_flags & ~SB_POSIXACL) |
@@ -1672,7 +1672,7 @@ restore_opts:
 #ifdef CONFIG_QUOTA
        F2FS_OPTION(sbi).s_jquota_fmt = org_mount_opt.s_jquota_fmt;
        for (i = 0; i < MAXQUOTAS; i++) {
-               kfree(F2FS_OPTION(sbi).s_qf_names[i]);
+               kvfree(F2FS_OPTION(sbi).s_qf_names[i]);
                F2FS_OPTION(sbi).s_qf_names[i] = org_mount_opt.s_qf_names[i];
        }
 #endif
@@ -2800,7 +2800,7 @@ static int init_blkz_info(struct f2fs_sb_info *sbi, int devi)
                }
        }
 
-       kfree(zones);
+       kvfree(zones);
 
        return err;
 }
@@ -2860,7 +2860,7 @@ static int read_raw_super_block(struct f2fs_sb_info *sbi,
 
        /* No valid superblock */
        if (!*raw_super)
-               kfree(super);
+               kvfree(super);
        else
                err = 0;
 
@@ -3369,7 +3369,7 @@ skip_recovery:
                if (err)
                        goto free_meta;
        }
-       kfree(options);
+       kvfree(options);
 
        /* recover broken superblock */
        if (recovery) {
@@ -3418,7 +3418,7 @@ free_sm:
        f2fs_destroy_segment_manager(sbi);
 free_devices:
        destroy_device_list(sbi);
-       kfree(sbi->ckpt);
+       kvfree(sbi->ckpt);
 free_meta_inode:
        make_bad_inode(sbi->meta_inode);
        iput(sbi->meta_inode);
@@ -3428,19 +3428,19 @@ free_percpu:
        destroy_percpu_info(sbi);
 free_bio_info:
        for (i = 0; i < NR_PAGE_TYPE; i++)
-               kfree(sbi->write_io[i]);
+               kvfree(sbi->write_io[i]);
 free_options:
 #ifdef CONFIG_QUOTA
        for (i = 0; i < MAXQUOTAS; i++)
-               kfree(F2FS_OPTION(sbi).s_qf_names[i]);
+               kvfree(F2FS_OPTION(sbi).s_qf_names[i]);
 #endif
-       kfree(options);
+       kvfree(options);
 free_sb_buf:
-       kfree(raw_super);
+       kvfree(raw_super);
 free_sbi:
        if (sbi->s_chksum_driver)
                crypto_free_shash(sbi->s_chksum_driver);
-       kfree(sbi);
+       kvfree(sbi);
 
        /* give only one another chance */
        if (retry) {