18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * fs/f2fs/super.c 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (c) 2012 Samsung Electronics Co., Ltd. 68c2ecf20Sopenharmony_ci * http://www.samsung.com/ 78c2ecf20Sopenharmony_ci */ 88c2ecf20Sopenharmony_ci#include <linux/module.h> 98c2ecf20Sopenharmony_ci#include <linux/init.h> 108c2ecf20Sopenharmony_ci#include <linux/fs.h> 118c2ecf20Sopenharmony_ci#include <linux/statfs.h> 128c2ecf20Sopenharmony_ci#include <linux/buffer_head.h> 138c2ecf20Sopenharmony_ci#include <linux/backing-dev.h> 148c2ecf20Sopenharmony_ci#include <linux/kthread.h> 158c2ecf20Sopenharmony_ci#include <linux/parser.h> 168c2ecf20Sopenharmony_ci#include <linux/mount.h> 178c2ecf20Sopenharmony_ci#include <linux/seq_file.h> 188c2ecf20Sopenharmony_ci#include <linux/proc_fs.h> 198c2ecf20Sopenharmony_ci#include <linux/random.h> 208c2ecf20Sopenharmony_ci#include <linux/exportfs.h> 218c2ecf20Sopenharmony_ci#include <linux/blkdev.h> 228c2ecf20Sopenharmony_ci#include <linux/quotaops.h> 238c2ecf20Sopenharmony_ci#include <linux/f2fs_fs.h> 248c2ecf20Sopenharmony_ci#include <linux/sysfs.h> 258c2ecf20Sopenharmony_ci#include <linux/quota.h> 268c2ecf20Sopenharmony_ci#include <linux/unicode.h> 278c2ecf20Sopenharmony_ci#include <linux/part_stat.h> 288c2ecf20Sopenharmony_ci 298c2ecf20Sopenharmony_ci#include "f2fs.h" 308c2ecf20Sopenharmony_ci#include "node.h" 318c2ecf20Sopenharmony_ci#include "segment.h" 328c2ecf20Sopenharmony_ci#include "xattr.h" 338c2ecf20Sopenharmony_ci#include "gc.h" 348c2ecf20Sopenharmony_ci#include "trace.h" 358c2ecf20Sopenharmony_ci 368c2ecf20Sopenharmony_ci#define CREATE_TRACE_POINTS 378c2ecf20Sopenharmony_ci#include <trace/events/f2fs.h> 388c2ecf20Sopenharmony_ci 398c2ecf20Sopenharmony_ci#ifdef CONFIG_F2FS_GRADING_SSR 408c2ecf20Sopenharmony_ci#define SSR_DEFALT_SPACE_LIMIT (5<<20) /* 5G default space limit */ 418c2ecf20Sopenharmony_ci#define SSR_DEFALT_WATERLINE 80 /* 80% default waterline */ 428c2ecf20Sopenharmony_ci#define SSR_HN_SAPCE_LIMIT_128G (8<<20) /* 8G default sapce limit for 128G devices */ 438c2ecf20Sopenharmony_ci#define SSR_HN_WATERLINE_128G 80 /* 80% default hot node waterline for 128G devices */ 448c2ecf20Sopenharmony_ci#define SSR_WN_SAPCE_LIMIT_128G (5<<20) /* 5G default warm node sapce limit for 128G devices */ 458c2ecf20Sopenharmony_ci#define SSR_WN_WATERLINE_128G 70 /* 70% default warm node waterline for 128G devices */ 468c2ecf20Sopenharmony_ci#define SSR_HD_SAPCE_LIMIT_128G (8<<20) /* 8G default hot data sapce limit for 128G devices */ 478c2ecf20Sopenharmony_ci#define SSR_HD_WATERLINE_128G 65 /* 65% default hot data waterline for 128G devices */ 488c2ecf20Sopenharmony_ci#define SSR_WD_SAPCE_LIMIT_128G (5<<20) /* 5G default warm data sapce limit for 128G devices */ 498c2ecf20Sopenharmony_ci#define SSR_WD_WATERLINE_128G 60 /* 60% default warm data waterline for 128G devices */ 508c2ecf20Sopenharmony_ci#endif 518c2ecf20Sopenharmony_ci 528c2ecf20Sopenharmony_cistatic struct kmem_cache *f2fs_inode_cachep; 538c2ecf20Sopenharmony_ci 548c2ecf20Sopenharmony_ci#ifdef CONFIG_F2FS_FAULT_INJECTION 558c2ecf20Sopenharmony_ci 568c2ecf20Sopenharmony_ciconst char *f2fs_fault_name[FAULT_MAX] = { 578c2ecf20Sopenharmony_ci [FAULT_KMALLOC] = "kmalloc", 588c2ecf20Sopenharmony_ci [FAULT_KVMALLOC] = "kvmalloc", 598c2ecf20Sopenharmony_ci [FAULT_PAGE_ALLOC] = "page alloc", 608c2ecf20Sopenharmony_ci [FAULT_PAGE_GET] = "page get", 618c2ecf20Sopenharmony_ci [FAULT_ALLOC_BIO] = "alloc bio", 628c2ecf20Sopenharmony_ci [FAULT_ALLOC_NID] = "alloc nid", 638c2ecf20Sopenharmony_ci [FAULT_ORPHAN] = "orphan", 648c2ecf20Sopenharmony_ci [FAULT_BLOCK] = "no more block", 658c2ecf20Sopenharmony_ci [FAULT_DIR_DEPTH] = "too big dir depth", 668c2ecf20Sopenharmony_ci [FAULT_EVICT_INODE] = "evict_inode fail", 678c2ecf20Sopenharmony_ci [FAULT_TRUNCATE] = "truncate fail", 688c2ecf20Sopenharmony_ci [FAULT_READ_IO] = "read IO error", 698c2ecf20Sopenharmony_ci [FAULT_CHECKPOINT] = "checkpoint error", 708c2ecf20Sopenharmony_ci [FAULT_DISCARD] = "discard error", 718c2ecf20Sopenharmony_ci [FAULT_WRITE_IO] = "write IO error", 728c2ecf20Sopenharmony_ci}; 738c2ecf20Sopenharmony_ci 748c2ecf20Sopenharmony_ciint f2fs_build_fault_attr(struct f2fs_sb_info *sbi, unsigned long rate, 758c2ecf20Sopenharmony_ci unsigned long type) 768c2ecf20Sopenharmony_ci{ 778c2ecf20Sopenharmony_ci struct f2fs_fault_info *ffi = &F2FS_OPTION(sbi).fault_info; 788c2ecf20Sopenharmony_ci 798c2ecf20Sopenharmony_ci if (rate) { 808c2ecf20Sopenharmony_ci if (rate > INT_MAX) 818c2ecf20Sopenharmony_ci return -EINVAL; 828c2ecf20Sopenharmony_ci atomic_set(&ffi->inject_ops, 0); 838c2ecf20Sopenharmony_ci ffi->inject_rate = (int)rate; 848c2ecf20Sopenharmony_ci } 858c2ecf20Sopenharmony_ci 868c2ecf20Sopenharmony_ci if (type) { 878c2ecf20Sopenharmony_ci if (type >= BIT(FAULT_MAX)) 888c2ecf20Sopenharmony_ci return -EINVAL; 898c2ecf20Sopenharmony_ci ffi->inject_type = (unsigned int)type; 908c2ecf20Sopenharmony_ci } 918c2ecf20Sopenharmony_ci 928c2ecf20Sopenharmony_ci if (!rate && !type) 938c2ecf20Sopenharmony_ci memset(ffi, 0, sizeof(struct f2fs_fault_info)); 948c2ecf20Sopenharmony_ci else 958c2ecf20Sopenharmony_ci f2fs_info(sbi, 968c2ecf20Sopenharmony_ci "build fault injection attr: rate: %lu, type: 0x%lx", 978c2ecf20Sopenharmony_ci rate, type); 988c2ecf20Sopenharmony_ci return 0; 998c2ecf20Sopenharmony_ci} 1008c2ecf20Sopenharmony_ci#endif 1018c2ecf20Sopenharmony_ci 1028c2ecf20Sopenharmony_ci/* f2fs-wide shrinker description */ 1038c2ecf20Sopenharmony_cistatic struct shrinker f2fs_shrinker_info = { 1048c2ecf20Sopenharmony_ci .scan_objects = f2fs_shrink_scan, 1058c2ecf20Sopenharmony_ci .count_objects = f2fs_shrink_count, 1068c2ecf20Sopenharmony_ci .seeks = DEFAULT_SEEKS, 1078c2ecf20Sopenharmony_ci}; 1088c2ecf20Sopenharmony_ci 1098c2ecf20Sopenharmony_cienum { 1108c2ecf20Sopenharmony_ci Opt_gc_background, 1118c2ecf20Sopenharmony_ci Opt_disable_roll_forward, 1128c2ecf20Sopenharmony_ci Opt_norecovery, 1138c2ecf20Sopenharmony_ci Opt_discard, 1148c2ecf20Sopenharmony_ci Opt_nodiscard, 1158c2ecf20Sopenharmony_ci Opt_noheap, 1168c2ecf20Sopenharmony_ci Opt_heap, 1178c2ecf20Sopenharmony_ci Opt_user_xattr, 1188c2ecf20Sopenharmony_ci Opt_nouser_xattr, 1198c2ecf20Sopenharmony_ci Opt_acl, 1208c2ecf20Sopenharmony_ci Opt_noacl, 1218c2ecf20Sopenharmony_ci Opt_active_logs, 1228c2ecf20Sopenharmony_ci Opt_disable_ext_identify, 1238c2ecf20Sopenharmony_ci Opt_inline_xattr, 1248c2ecf20Sopenharmony_ci Opt_noinline_xattr, 1258c2ecf20Sopenharmony_ci Opt_inline_xattr_size, 1268c2ecf20Sopenharmony_ci Opt_inline_data, 1278c2ecf20Sopenharmony_ci Opt_inline_dentry, 1288c2ecf20Sopenharmony_ci Opt_noinline_dentry, 1298c2ecf20Sopenharmony_ci Opt_flush_merge, 1308c2ecf20Sopenharmony_ci Opt_noflush_merge, 1318c2ecf20Sopenharmony_ci Opt_nobarrier, 1328c2ecf20Sopenharmony_ci Opt_fastboot, 1338c2ecf20Sopenharmony_ci Opt_extent_cache, 1348c2ecf20Sopenharmony_ci Opt_noextent_cache, 1358c2ecf20Sopenharmony_ci Opt_noinline_data, 1368c2ecf20Sopenharmony_ci Opt_data_flush, 1378c2ecf20Sopenharmony_ci Opt_reserve_root, 1388c2ecf20Sopenharmony_ci Opt_resgid, 1398c2ecf20Sopenharmony_ci Opt_resuid, 1408c2ecf20Sopenharmony_ci Opt_mode, 1418c2ecf20Sopenharmony_ci Opt_io_size_bits, 1428c2ecf20Sopenharmony_ci Opt_fault_injection, 1438c2ecf20Sopenharmony_ci Opt_fault_type, 1448c2ecf20Sopenharmony_ci Opt_lazytime, 1458c2ecf20Sopenharmony_ci Opt_nolazytime, 1468c2ecf20Sopenharmony_ci Opt_quota, 1478c2ecf20Sopenharmony_ci Opt_noquota, 1488c2ecf20Sopenharmony_ci Opt_usrquota, 1498c2ecf20Sopenharmony_ci Opt_grpquota, 1508c2ecf20Sopenharmony_ci Opt_prjquota, 1518c2ecf20Sopenharmony_ci Opt_usrjquota, 1528c2ecf20Sopenharmony_ci Opt_grpjquota, 1538c2ecf20Sopenharmony_ci Opt_prjjquota, 1548c2ecf20Sopenharmony_ci Opt_offusrjquota, 1558c2ecf20Sopenharmony_ci Opt_offgrpjquota, 1568c2ecf20Sopenharmony_ci Opt_offprjjquota, 1578c2ecf20Sopenharmony_ci Opt_jqfmt_vfsold, 1588c2ecf20Sopenharmony_ci Opt_jqfmt_vfsv0, 1598c2ecf20Sopenharmony_ci Opt_jqfmt_vfsv1, 1608c2ecf20Sopenharmony_ci Opt_whint, 1618c2ecf20Sopenharmony_ci Opt_alloc, 1628c2ecf20Sopenharmony_ci Opt_fsync, 1638c2ecf20Sopenharmony_ci Opt_test_dummy_encryption, 1648c2ecf20Sopenharmony_ci Opt_inlinecrypt, 1658c2ecf20Sopenharmony_ci Opt_checkpoint_disable, 1668c2ecf20Sopenharmony_ci Opt_checkpoint_disable_cap, 1678c2ecf20Sopenharmony_ci Opt_checkpoint_disable_cap_perc, 1688c2ecf20Sopenharmony_ci Opt_checkpoint_enable, 1698c2ecf20Sopenharmony_ci Opt_compress_algorithm, 1708c2ecf20Sopenharmony_ci Opt_compress_log_size, 1718c2ecf20Sopenharmony_ci Opt_compress_extension, 1728c2ecf20Sopenharmony_ci Opt_atgc, 1738c2ecf20Sopenharmony_ci Opt_gc_merge, 1748c2ecf20Sopenharmony_ci Opt_nogc_merge, 1758c2ecf20Sopenharmony_ci Opt_err, 1768c2ecf20Sopenharmony_ci}; 1778c2ecf20Sopenharmony_ci 1788c2ecf20Sopenharmony_cistatic match_table_t f2fs_tokens = { 1798c2ecf20Sopenharmony_ci {Opt_gc_background, "background_gc=%s"}, 1808c2ecf20Sopenharmony_ci {Opt_disable_roll_forward, "disable_roll_forward"}, 1818c2ecf20Sopenharmony_ci {Opt_norecovery, "norecovery"}, 1828c2ecf20Sopenharmony_ci {Opt_discard, "discard"}, 1838c2ecf20Sopenharmony_ci {Opt_nodiscard, "nodiscard"}, 1848c2ecf20Sopenharmony_ci {Opt_noheap, "no_heap"}, 1858c2ecf20Sopenharmony_ci {Opt_heap, "heap"}, 1868c2ecf20Sopenharmony_ci {Opt_user_xattr, "user_xattr"}, 1878c2ecf20Sopenharmony_ci {Opt_nouser_xattr, "nouser_xattr"}, 1888c2ecf20Sopenharmony_ci {Opt_acl, "acl"}, 1898c2ecf20Sopenharmony_ci {Opt_noacl, "noacl"}, 1908c2ecf20Sopenharmony_ci {Opt_active_logs, "active_logs=%u"}, 1918c2ecf20Sopenharmony_ci {Opt_disable_ext_identify, "disable_ext_identify"}, 1928c2ecf20Sopenharmony_ci {Opt_inline_xattr, "inline_xattr"}, 1938c2ecf20Sopenharmony_ci {Opt_noinline_xattr, "noinline_xattr"}, 1948c2ecf20Sopenharmony_ci {Opt_inline_xattr_size, "inline_xattr_size=%u"}, 1958c2ecf20Sopenharmony_ci {Opt_inline_data, "inline_data"}, 1968c2ecf20Sopenharmony_ci {Opt_inline_dentry, "inline_dentry"}, 1978c2ecf20Sopenharmony_ci {Opt_noinline_dentry, "noinline_dentry"}, 1988c2ecf20Sopenharmony_ci {Opt_flush_merge, "flush_merge"}, 1998c2ecf20Sopenharmony_ci {Opt_noflush_merge, "noflush_merge"}, 2008c2ecf20Sopenharmony_ci {Opt_nobarrier, "nobarrier"}, 2018c2ecf20Sopenharmony_ci {Opt_fastboot, "fastboot"}, 2028c2ecf20Sopenharmony_ci {Opt_extent_cache, "extent_cache"}, 2038c2ecf20Sopenharmony_ci {Opt_noextent_cache, "noextent_cache"}, 2048c2ecf20Sopenharmony_ci {Opt_noinline_data, "noinline_data"}, 2058c2ecf20Sopenharmony_ci {Opt_data_flush, "data_flush"}, 2068c2ecf20Sopenharmony_ci {Opt_reserve_root, "reserve_root=%u"}, 2078c2ecf20Sopenharmony_ci {Opt_resgid, "resgid=%u"}, 2088c2ecf20Sopenharmony_ci {Opt_resuid, "resuid=%u"}, 2098c2ecf20Sopenharmony_ci {Opt_mode, "mode=%s"}, 2108c2ecf20Sopenharmony_ci {Opt_io_size_bits, "io_bits=%u"}, 2118c2ecf20Sopenharmony_ci {Opt_fault_injection, "fault_injection=%u"}, 2128c2ecf20Sopenharmony_ci {Opt_fault_type, "fault_type=%u"}, 2138c2ecf20Sopenharmony_ci {Opt_lazytime, "lazytime"}, 2148c2ecf20Sopenharmony_ci {Opt_nolazytime, "nolazytime"}, 2158c2ecf20Sopenharmony_ci {Opt_quota, "quota"}, 2168c2ecf20Sopenharmony_ci {Opt_noquota, "noquota"}, 2178c2ecf20Sopenharmony_ci {Opt_usrquota, "usrquota"}, 2188c2ecf20Sopenharmony_ci {Opt_grpquota, "grpquota"}, 2198c2ecf20Sopenharmony_ci {Opt_prjquota, "prjquota"}, 2208c2ecf20Sopenharmony_ci {Opt_usrjquota, "usrjquota=%s"}, 2218c2ecf20Sopenharmony_ci {Opt_grpjquota, "grpjquota=%s"}, 2228c2ecf20Sopenharmony_ci {Opt_prjjquota, "prjjquota=%s"}, 2238c2ecf20Sopenharmony_ci {Opt_offusrjquota, "usrjquota="}, 2248c2ecf20Sopenharmony_ci {Opt_offgrpjquota, "grpjquota="}, 2258c2ecf20Sopenharmony_ci {Opt_offprjjquota, "prjjquota="}, 2268c2ecf20Sopenharmony_ci {Opt_jqfmt_vfsold, "jqfmt=vfsold"}, 2278c2ecf20Sopenharmony_ci {Opt_jqfmt_vfsv0, "jqfmt=vfsv0"}, 2288c2ecf20Sopenharmony_ci {Opt_jqfmt_vfsv1, "jqfmt=vfsv1"}, 2298c2ecf20Sopenharmony_ci {Opt_whint, "whint_mode=%s"}, 2308c2ecf20Sopenharmony_ci {Opt_alloc, "alloc_mode=%s"}, 2318c2ecf20Sopenharmony_ci {Opt_fsync, "fsync_mode=%s"}, 2328c2ecf20Sopenharmony_ci {Opt_test_dummy_encryption, "test_dummy_encryption=%s"}, 2338c2ecf20Sopenharmony_ci {Opt_test_dummy_encryption, "test_dummy_encryption"}, 2348c2ecf20Sopenharmony_ci {Opt_inlinecrypt, "inlinecrypt"}, 2358c2ecf20Sopenharmony_ci {Opt_checkpoint_disable, "checkpoint=disable"}, 2368c2ecf20Sopenharmony_ci {Opt_checkpoint_disable_cap, "checkpoint=disable:%u"}, 2378c2ecf20Sopenharmony_ci {Opt_checkpoint_disable_cap_perc, "checkpoint=disable:%u%%"}, 2388c2ecf20Sopenharmony_ci {Opt_checkpoint_enable, "checkpoint=enable"}, 2398c2ecf20Sopenharmony_ci {Opt_compress_algorithm, "compress_algorithm=%s"}, 2408c2ecf20Sopenharmony_ci {Opt_compress_log_size, "compress_log_size=%u"}, 2418c2ecf20Sopenharmony_ci {Opt_compress_extension, "compress_extension=%s"}, 2428c2ecf20Sopenharmony_ci {Opt_atgc, "atgc"}, 2438c2ecf20Sopenharmony_ci {Opt_gc_merge, "gc_merge"}, 2448c2ecf20Sopenharmony_ci {Opt_nogc_merge, "nogc_merge"}, 2458c2ecf20Sopenharmony_ci {Opt_err, NULL}, 2468c2ecf20Sopenharmony_ci}; 2478c2ecf20Sopenharmony_ci 2488c2ecf20Sopenharmony_civoid f2fs_printk(struct f2fs_sb_info *sbi, const char *fmt, ...) 2498c2ecf20Sopenharmony_ci{ 2508c2ecf20Sopenharmony_ci struct va_format vaf; 2518c2ecf20Sopenharmony_ci va_list args; 2528c2ecf20Sopenharmony_ci int level; 2538c2ecf20Sopenharmony_ci 2548c2ecf20Sopenharmony_ci va_start(args, fmt); 2558c2ecf20Sopenharmony_ci 2568c2ecf20Sopenharmony_ci level = printk_get_level(fmt); 2578c2ecf20Sopenharmony_ci vaf.fmt = printk_skip_level(fmt); 2588c2ecf20Sopenharmony_ci vaf.va = &args; 2598c2ecf20Sopenharmony_ci printk("%c%cF2FS-fs (%s): %pV\n", 2608c2ecf20Sopenharmony_ci KERN_SOH_ASCII, level, sbi->sb->s_id, &vaf); 2618c2ecf20Sopenharmony_ci 2628c2ecf20Sopenharmony_ci va_end(args); 2638c2ecf20Sopenharmony_ci} 2648c2ecf20Sopenharmony_ci 2658c2ecf20Sopenharmony_ci#ifdef CONFIG_UNICODE 2668c2ecf20Sopenharmony_cistatic const struct f2fs_sb_encodings { 2678c2ecf20Sopenharmony_ci __u16 magic; 2688c2ecf20Sopenharmony_ci char *name; 2698c2ecf20Sopenharmony_ci char *version; 2708c2ecf20Sopenharmony_ci} f2fs_sb_encoding_map[] = { 2718c2ecf20Sopenharmony_ci {F2FS_ENC_UTF8_12_1, "utf8", "12.1.0"}, 2728c2ecf20Sopenharmony_ci}; 2738c2ecf20Sopenharmony_ci 2748c2ecf20Sopenharmony_cistatic int f2fs_sb_read_encoding(const struct f2fs_super_block *sb, 2758c2ecf20Sopenharmony_ci const struct f2fs_sb_encodings **encoding, 2768c2ecf20Sopenharmony_ci __u16 *flags) 2778c2ecf20Sopenharmony_ci{ 2788c2ecf20Sopenharmony_ci __u16 magic = le16_to_cpu(sb->s_encoding); 2798c2ecf20Sopenharmony_ci int i; 2808c2ecf20Sopenharmony_ci 2818c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(f2fs_sb_encoding_map); i++) 2828c2ecf20Sopenharmony_ci if (magic == f2fs_sb_encoding_map[i].magic) 2838c2ecf20Sopenharmony_ci break; 2848c2ecf20Sopenharmony_ci 2858c2ecf20Sopenharmony_ci if (i >= ARRAY_SIZE(f2fs_sb_encoding_map)) 2868c2ecf20Sopenharmony_ci return -EINVAL; 2878c2ecf20Sopenharmony_ci 2888c2ecf20Sopenharmony_ci *encoding = &f2fs_sb_encoding_map[i]; 2898c2ecf20Sopenharmony_ci *flags = le16_to_cpu(sb->s_encoding_flags); 2908c2ecf20Sopenharmony_ci 2918c2ecf20Sopenharmony_ci return 0; 2928c2ecf20Sopenharmony_ci} 2938c2ecf20Sopenharmony_ci#endif 2948c2ecf20Sopenharmony_ci 2958c2ecf20Sopenharmony_cistatic inline void limit_reserve_root(struct f2fs_sb_info *sbi) 2968c2ecf20Sopenharmony_ci{ 2978c2ecf20Sopenharmony_ci block_t limit = min((sbi->user_block_count >> 3), 2988c2ecf20Sopenharmony_ci sbi->user_block_count - sbi->reserved_blocks); 2998c2ecf20Sopenharmony_ci 3008c2ecf20Sopenharmony_ci /* limit is 12.5% */ 3018c2ecf20Sopenharmony_ci if (test_opt(sbi, RESERVE_ROOT) && 3028c2ecf20Sopenharmony_ci F2FS_OPTION(sbi).root_reserved_blocks > limit) { 3038c2ecf20Sopenharmony_ci F2FS_OPTION(sbi).root_reserved_blocks = limit; 3048c2ecf20Sopenharmony_ci f2fs_info(sbi, "Reduce reserved blocks for root = %u", 3058c2ecf20Sopenharmony_ci F2FS_OPTION(sbi).root_reserved_blocks); 3068c2ecf20Sopenharmony_ci } 3078c2ecf20Sopenharmony_ci if (!test_opt(sbi, RESERVE_ROOT) && 3088c2ecf20Sopenharmony_ci (!uid_eq(F2FS_OPTION(sbi).s_resuid, 3098c2ecf20Sopenharmony_ci make_kuid(&init_user_ns, F2FS_DEF_RESUID)) || 3108c2ecf20Sopenharmony_ci !gid_eq(F2FS_OPTION(sbi).s_resgid, 3118c2ecf20Sopenharmony_ci make_kgid(&init_user_ns, F2FS_DEF_RESGID)))) 3128c2ecf20Sopenharmony_ci f2fs_info(sbi, "Ignore s_resuid=%u, s_resgid=%u w/o reserve_root", 3138c2ecf20Sopenharmony_ci from_kuid_munged(&init_user_ns, 3148c2ecf20Sopenharmony_ci F2FS_OPTION(sbi).s_resuid), 3158c2ecf20Sopenharmony_ci from_kgid_munged(&init_user_ns, 3168c2ecf20Sopenharmony_ci F2FS_OPTION(sbi).s_resgid)); 3178c2ecf20Sopenharmony_ci} 3188c2ecf20Sopenharmony_ci 3198c2ecf20Sopenharmony_cistatic inline int adjust_reserved_segment(struct f2fs_sb_info *sbi) 3208c2ecf20Sopenharmony_ci{ 3218c2ecf20Sopenharmony_ci unsigned int sec_blks = sbi->blocks_per_seg * sbi->segs_per_sec; 3228c2ecf20Sopenharmony_ci unsigned int avg_vblocks; 3238c2ecf20Sopenharmony_ci unsigned int wanted_reserved_segments; 3248c2ecf20Sopenharmony_ci block_t avail_user_block_count; 3258c2ecf20Sopenharmony_ci 3268c2ecf20Sopenharmony_ci if (!F2FS_IO_ALIGNED(sbi)) 3278c2ecf20Sopenharmony_ci return 0; 3288c2ecf20Sopenharmony_ci 3298c2ecf20Sopenharmony_ci /* average valid block count in section in worst case */ 3308c2ecf20Sopenharmony_ci avg_vblocks = sec_blks / F2FS_IO_SIZE(sbi); 3318c2ecf20Sopenharmony_ci 3328c2ecf20Sopenharmony_ci /* 3338c2ecf20Sopenharmony_ci * we need enough free space when migrating one section in worst case 3348c2ecf20Sopenharmony_ci */ 3358c2ecf20Sopenharmony_ci wanted_reserved_segments = (F2FS_IO_SIZE(sbi) / avg_vblocks) * 3368c2ecf20Sopenharmony_ci reserved_segments(sbi); 3378c2ecf20Sopenharmony_ci wanted_reserved_segments -= reserved_segments(sbi); 3388c2ecf20Sopenharmony_ci 3398c2ecf20Sopenharmony_ci avail_user_block_count = sbi->user_block_count - 3408c2ecf20Sopenharmony_ci sbi->current_reserved_blocks - 3418c2ecf20Sopenharmony_ci F2FS_OPTION(sbi).root_reserved_blocks; 3428c2ecf20Sopenharmony_ci 3438c2ecf20Sopenharmony_ci if (wanted_reserved_segments * sbi->blocks_per_seg > 3448c2ecf20Sopenharmony_ci avail_user_block_count) { 3458c2ecf20Sopenharmony_ci f2fs_err(sbi, "IO align feature can't grab additional reserved segment: %u, available segments: %u", 3468c2ecf20Sopenharmony_ci wanted_reserved_segments, 3478c2ecf20Sopenharmony_ci avail_user_block_count >> sbi->log_blocks_per_seg); 3488c2ecf20Sopenharmony_ci return -ENOSPC; 3498c2ecf20Sopenharmony_ci } 3508c2ecf20Sopenharmony_ci 3518c2ecf20Sopenharmony_ci SM_I(sbi)->additional_reserved_segments = wanted_reserved_segments; 3528c2ecf20Sopenharmony_ci 3538c2ecf20Sopenharmony_ci f2fs_info(sbi, "IO align feature needs additional reserved segment: %u", 3548c2ecf20Sopenharmony_ci wanted_reserved_segments); 3558c2ecf20Sopenharmony_ci 3568c2ecf20Sopenharmony_ci return 0; 3578c2ecf20Sopenharmony_ci} 3588c2ecf20Sopenharmony_ci 3598c2ecf20Sopenharmony_cistatic inline void adjust_unusable_cap_perc(struct f2fs_sb_info *sbi) 3608c2ecf20Sopenharmony_ci{ 3618c2ecf20Sopenharmony_ci if (!F2FS_OPTION(sbi).unusable_cap_perc) 3628c2ecf20Sopenharmony_ci return; 3638c2ecf20Sopenharmony_ci 3648c2ecf20Sopenharmony_ci if (F2FS_OPTION(sbi).unusable_cap_perc == 100) 3658c2ecf20Sopenharmony_ci F2FS_OPTION(sbi).unusable_cap = sbi->user_block_count; 3668c2ecf20Sopenharmony_ci else 3678c2ecf20Sopenharmony_ci F2FS_OPTION(sbi).unusable_cap = (sbi->user_block_count / 100) * 3688c2ecf20Sopenharmony_ci F2FS_OPTION(sbi).unusable_cap_perc; 3698c2ecf20Sopenharmony_ci 3708c2ecf20Sopenharmony_ci f2fs_info(sbi, "Adjust unusable cap for checkpoint=disable = %u / %u%%", 3718c2ecf20Sopenharmony_ci F2FS_OPTION(sbi).unusable_cap, 3728c2ecf20Sopenharmony_ci F2FS_OPTION(sbi).unusable_cap_perc); 3738c2ecf20Sopenharmony_ci} 3748c2ecf20Sopenharmony_ci 3758c2ecf20Sopenharmony_cistatic void init_once(void *foo) 3768c2ecf20Sopenharmony_ci{ 3778c2ecf20Sopenharmony_ci struct f2fs_inode_info *fi = (struct f2fs_inode_info *) foo; 3788c2ecf20Sopenharmony_ci 3798c2ecf20Sopenharmony_ci inode_init_once(&fi->vfs_inode); 3808c2ecf20Sopenharmony_ci} 3818c2ecf20Sopenharmony_ci 3828c2ecf20Sopenharmony_ci#ifdef CONFIG_QUOTA 3838c2ecf20Sopenharmony_cistatic const char * const quotatypes[] = INITQFNAMES; 3848c2ecf20Sopenharmony_ci#define QTYPE2NAME(t) (quotatypes[t]) 3858c2ecf20Sopenharmony_cistatic int f2fs_set_qf_name(struct super_block *sb, int qtype, 3868c2ecf20Sopenharmony_ci substring_t *args) 3878c2ecf20Sopenharmony_ci{ 3888c2ecf20Sopenharmony_ci struct f2fs_sb_info *sbi = F2FS_SB(sb); 3898c2ecf20Sopenharmony_ci char *qname; 3908c2ecf20Sopenharmony_ci int ret = -EINVAL; 3918c2ecf20Sopenharmony_ci 3928c2ecf20Sopenharmony_ci if (sb_any_quota_loaded(sb) && !F2FS_OPTION(sbi).s_qf_names[qtype]) { 3938c2ecf20Sopenharmony_ci f2fs_err(sbi, "Cannot change journaled quota options when quota turned on"); 3948c2ecf20Sopenharmony_ci return -EINVAL; 3958c2ecf20Sopenharmony_ci } 3968c2ecf20Sopenharmony_ci if (f2fs_sb_has_quota_ino(sbi)) { 3978c2ecf20Sopenharmony_ci f2fs_info(sbi, "QUOTA feature is enabled, so ignore qf_name"); 3988c2ecf20Sopenharmony_ci return 0; 3998c2ecf20Sopenharmony_ci } 4008c2ecf20Sopenharmony_ci 4018c2ecf20Sopenharmony_ci qname = match_strdup(args); 4028c2ecf20Sopenharmony_ci if (!qname) { 4038c2ecf20Sopenharmony_ci f2fs_err(sbi, "Not enough memory for storing quotafile name"); 4048c2ecf20Sopenharmony_ci return -ENOMEM; 4058c2ecf20Sopenharmony_ci } 4068c2ecf20Sopenharmony_ci if (F2FS_OPTION(sbi).s_qf_names[qtype]) { 4078c2ecf20Sopenharmony_ci if (strcmp(F2FS_OPTION(sbi).s_qf_names[qtype], qname) == 0) 4088c2ecf20Sopenharmony_ci ret = 0; 4098c2ecf20Sopenharmony_ci else 4108c2ecf20Sopenharmony_ci f2fs_err(sbi, "%s quota file already specified", 4118c2ecf20Sopenharmony_ci QTYPE2NAME(qtype)); 4128c2ecf20Sopenharmony_ci goto errout; 4138c2ecf20Sopenharmony_ci } 4148c2ecf20Sopenharmony_ci if (strchr(qname, '/')) { 4158c2ecf20Sopenharmony_ci f2fs_err(sbi, "quotafile must be on filesystem root"); 4168c2ecf20Sopenharmony_ci goto errout; 4178c2ecf20Sopenharmony_ci } 4188c2ecf20Sopenharmony_ci F2FS_OPTION(sbi).s_qf_names[qtype] = qname; 4198c2ecf20Sopenharmony_ci set_opt(sbi, QUOTA); 4208c2ecf20Sopenharmony_ci return 0; 4218c2ecf20Sopenharmony_cierrout: 4228c2ecf20Sopenharmony_ci kfree(qname); 4238c2ecf20Sopenharmony_ci return ret; 4248c2ecf20Sopenharmony_ci} 4258c2ecf20Sopenharmony_ci 4268c2ecf20Sopenharmony_cistatic int f2fs_clear_qf_name(struct super_block *sb, int qtype) 4278c2ecf20Sopenharmony_ci{ 4288c2ecf20Sopenharmony_ci struct f2fs_sb_info *sbi = F2FS_SB(sb); 4298c2ecf20Sopenharmony_ci 4308c2ecf20Sopenharmony_ci if (sb_any_quota_loaded(sb) && F2FS_OPTION(sbi).s_qf_names[qtype]) { 4318c2ecf20Sopenharmony_ci f2fs_err(sbi, "Cannot change journaled quota options when quota turned on"); 4328c2ecf20Sopenharmony_ci return -EINVAL; 4338c2ecf20Sopenharmony_ci } 4348c2ecf20Sopenharmony_ci kfree(F2FS_OPTION(sbi).s_qf_names[qtype]); 4358c2ecf20Sopenharmony_ci F2FS_OPTION(sbi).s_qf_names[qtype] = NULL; 4368c2ecf20Sopenharmony_ci return 0; 4378c2ecf20Sopenharmony_ci} 4388c2ecf20Sopenharmony_ci 4398c2ecf20Sopenharmony_cistatic int f2fs_check_quota_options(struct f2fs_sb_info *sbi) 4408c2ecf20Sopenharmony_ci{ 4418c2ecf20Sopenharmony_ci /* 4428c2ecf20Sopenharmony_ci * We do the test below only for project quotas. 'usrquota' and 4438c2ecf20Sopenharmony_ci * 'grpquota' mount options are allowed even without quota feature 4448c2ecf20Sopenharmony_ci * to support legacy quotas in quota files. 4458c2ecf20Sopenharmony_ci */ 4468c2ecf20Sopenharmony_ci if (test_opt(sbi, PRJQUOTA) && !f2fs_sb_has_project_quota(sbi)) { 4478c2ecf20Sopenharmony_ci f2fs_err(sbi, "Project quota feature not enabled. Cannot enable project quota enforcement."); 4488c2ecf20Sopenharmony_ci return -1; 4498c2ecf20Sopenharmony_ci } 4508c2ecf20Sopenharmony_ci if (F2FS_OPTION(sbi).s_qf_names[USRQUOTA] || 4518c2ecf20Sopenharmony_ci F2FS_OPTION(sbi).s_qf_names[GRPQUOTA] || 4528c2ecf20Sopenharmony_ci F2FS_OPTION(sbi).s_qf_names[PRJQUOTA]) { 4538c2ecf20Sopenharmony_ci if (test_opt(sbi, USRQUOTA) && 4548c2ecf20Sopenharmony_ci F2FS_OPTION(sbi).s_qf_names[USRQUOTA]) 4558c2ecf20Sopenharmony_ci clear_opt(sbi, USRQUOTA); 4568c2ecf20Sopenharmony_ci 4578c2ecf20Sopenharmony_ci if (test_opt(sbi, GRPQUOTA) && 4588c2ecf20Sopenharmony_ci F2FS_OPTION(sbi).s_qf_names[GRPQUOTA]) 4598c2ecf20Sopenharmony_ci clear_opt(sbi, GRPQUOTA); 4608c2ecf20Sopenharmony_ci 4618c2ecf20Sopenharmony_ci if (test_opt(sbi, PRJQUOTA) && 4628c2ecf20Sopenharmony_ci F2FS_OPTION(sbi).s_qf_names[PRJQUOTA]) 4638c2ecf20Sopenharmony_ci clear_opt(sbi, PRJQUOTA); 4648c2ecf20Sopenharmony_ci 4658c2ecf20Sopenharmony_ci if (test_opt(sbi, GRPQUOTA) || test_opt(sbi, USRQUOTA) || 4668c2ecf20Sopenharmony_ci test_opt(sbi, PRJQUOTA)) { 4678c2ecf20Sopenharmony_ci f2fs_err(sbi, "old and new quota format mixing"); 4688c2ecf20Sopenharmony_ci return -1; 4698c2ecf20Sopenharmony_ci } 4708c2ecf20Sopenharmony_ci 4718c2ecf20Sopenharmony_ci if (!F2FS_OPTION(sbi).s_jquota_fmt) { 4728c2ecf20Sopenharmony_ci f2fs_err(sbi, "journaled quota format not specified"); 4738c2ecf20Sopenharmony_ci return -1; 4748c2ecf20Sopenharmony_ci } 4758c2ecf20Sopenharmony_ci } 4768c2ecf20Sopenharmony_ci 4778c2ecf20Sopenharmony_ci if (f2fs_sb_has_quota_ino(sbi) && F2FS_OPTION(sbi).s_jquota_fmt) { 4788c2ecf20Sopenharmony_ci f2fs_info(sbi, "QUOTA feature is enabled, so ignore jquota_fmt"); 4798c2ecf20Sopenharmony_ci F2FS_OPTION(sbi).s_jquota_fmt = 0; 4808c2ecf20Sopenharmony_ci } 4818c2ecf20Sopenharmony_ci return 0; 4828c2ecf20Sopenharmony_ci} 4838c2ecf20Sopenharmony_ci#endif 4848c2ecf20Sopenharmony_ci 4858c2ecf20Sopenharmony_cistatic int f2fs_set_test_dummy_encryption(struct super_block *sb, 4868c2ecf20Sopenharmony_ci const char *opt, 4878c2ecf20Sopenharmony_ci const substring_t *arg, 4888c2ecf20Sopenharmony_ci bool is_remount) 4898c2ecf20Sopenharmony_ci{ 4908c2ecf20Sopenharmony_ci struct f2fs_sb_info *sbi = F2FS_SB(sb); 4918c2ecf20Sopenharmony_ci#ifdef CONFIG_FS_ENCRYPTION 4928c2ecf20Sopenharmony_ci int err; 4938c2ecf20Sopenharmony_ci 4948c2ecf20Sopenharmony_ci if (!f2fs_sb_has_encrypt(sbi)) { 4958c2ecf20Sopenharmony_ci f2fs_err(sbi, "Encrypt feature is off"); 4968c2ecf20Sopenharmony_ci return -EINVAL; 4978c2ecf20Sopenharmony_ci } 4988c2ecf20Sopenharmony_ci 4998c2ecf20Sopenharmony_ci /* 5008c2ecf20Sopenharmony_ci * This mount option is just for testing, and it's not worthwhile to 5018c2ecf20Sopenharmony_ci * implement the extra complexity (e.g. RCU protection) that would be 5028c2ecf20Sopenharmony_ci * needed to allow it to be set or changed during remount. We do allow 5038c2ecf20Sopenharmony_ci * it to be specified during remount, but only if there is no change. 5048c2ecf20Sopenharmony_ci */ 5058c2ecf20Sopenharmony_ci if (is_remount && !F2FS_OPTION(sbi).dummy_enc_policy.policy) { 5068c2ecf20Sopenharmony_ci f2fs_warn(sbi, "Can't set test_dummy_encryption on remount"); 5078c2ecf20Sopenharmony_ci return -EINVAL; 5088c2ecf20Sopenharmony_ci } 5098c2ecf20Sopenharmony_ci err = fscrypt_set_test_dummy_encryption( 5108c2ecf20Sopenharmony_ci sb, arg->from, &F2FS_OPTION(sbi).dummy_enc_policy); 5118c2ecf20Sopenharmony_ci if (err) { 5128c2ecf20Sopenharmony_ci if (err == -EEXIST) 5138c2ecf20Sopenharmony_ci f2fs_warn(sbi, 5148c2ecf20Sopenharmony_ci "Can't change test_dummy_encryption on remount"); 5158c2ecf20Sopenharmony_ci else if (err == -EINVAL) 5168c2ecf20Sopenharmony_ci f2fs_warn(sbi, "Value of option \"%s\" is unrecognized", 5178c2ecf20Sopenharmony_ci opt); 5188c2ecf20Sopenharmony_ci else 5198c2ecf20Sopenharmony_ci f2fs_warn(sbi, "Error processing option \"%s\" [%d]", 5208c2ecf20Sopenharmony_ci opt, err); 5218c2ecf20Sopenharmony_ci return -EINVAL; 5228c2ecf20Sopenharmony_ci } 5238c2ecf20Sopenharmony_ci f2fs_warn(sbi, "Test dummy encryption mode enabled"); 5248c2ecf20Sopenharmony_ci#else 5258c2ecf20Sopenharmony_ci f2fs_warn(sbi, "Test dummy encryption mount option ignored"); 5268c2ecf20Sopenharmony_ci#endif 5278c2ecf20Sopenharmony_ci return 0; 5288c2ecf20Sopenharmony_ci} 5298c2ecf20Sopenharmony_ci 5308c2ecf20Sopenharmony_cistatic int parse_options(struct super_block *sb, char *options, bool is_remount) 5318c2ecf20Sopenharmony_ci{ 5328c2ecf20Sopenharmony_ci struct f2fs_sb_info *sbi = F2FS_SB(sb); 5338c2ecf20Sopenharmony_ci substring_t args[MAX_OPT_ARGS]; 5348c2ecf20Sopenharmony_ci#ifdef CONFIG_F2FS_FS_COMPRESSION 5358c2ecf20Sopenharmony_ci unsigned char (*ext)[F2FS_EXTENSION_LEN]; 5368c2ecf20Sopenharmony_ci int ext_cnt; 5378c2ecf20Sopenharmony_ci#endif 5388c2ecf20Sopenharmony_ci char *p, *name; 5398c2ecf20Sopenharmony_ci int arg = 0; 5408c2ecf20Sopenharmony_ci kuid_t uid; 5418c2ecf20Sopenharmony_ci kgid_t gid; 5428c2ecf20Sopenharmony_ci int ret; 5438c2ecf20Sopenharmony_ci 5448c2ecf20Sopenharmony_ci if (!options) 5458c2ecf20Sopenharmony_ci return 0; 5468c2ecf20Sopenharmony_ci 5478c2ecf20Sopenharmony_ci while ((p = strsep(&options, ",")) != NULL) { 5488c2ecf20Sopenharmony_ci int token; 5498c2ecf20Sopenharmony_ci if (!*p) 5508c2ecf20Sopenharmony_ci continue; 5518c2ecf20Sopenharmony_ci /* 5528c2ecf20Sopenharmony_ci * Initialize args struct so we know whether arg was 5538c2ecf20Sopenharmony_ci * found; some options take optional arguments. 5548c2ecf20Sopenharmony_ci */ 5558c2ecf20Sopenharmony_ci args[0].to = args[0].from = NULL; 5568c2ecf20Sopenharmony_ci token = match_token(p, f2fs_tokens, args); 5578c2ecf20Sopenharmony_ci 5588c2ecf20Sopenharmony_ci switch (token) { 5598c2ecf20Sopenharmony_ci case Opt_gc_background: 5608c2ecf20Sopenharmony_ci name = match_strdup(&args[0]); 5618c2ecf20Sopenharmony_ci 5628c2ecf20Sopenharmony_ci if (!name) 5638c2ecf20Sopenharmony_ci return -ENOMEM; 5648c2ecf20Sopenharmony_ci if (!strcmp(name, "on")) { 5658c2ecf20Sopenharmony_ci F2FS_OPTION(sbi).bggc_mode = BGGC_MODE_ON; 5668c2ecf20Sopenharmony_ci } else if (!strcmp(name, "off")) { 5678c2ecf20Sopenharmony_ci F2FS_OPTION(sbi).bggc_mode = BGGC_MODE_OFF; 5688c2ecf20Sopenharmony_ci } else if (!strcmp(name, "sync")) { 5698c2ecf20Sopenharmony_ci F2FS_OPTION(sbi).bggc_mode = BGGC_MODE_SYNC; 5708c2ecf20Sopenharmony_ci } else { 5718c2ecf20Sopenharmony_ci kfree(name); 5728c2ecf20Sopenharmony_ci return -EINVAL; 5738c2ecf20Sopenharmony_ci } 5748c2ecf20Sopenharmony_ci kfree(name); 5758c2ecf20Sopenharmony_ci break; 5768c2ecf20Sopenharmony_ci case Opt_disable_roll_forward: 5778c2ecf20Sopenharmony_ci set_opt(sbi, DISABLE_ROLL_FORWARD); 5788c2ecf20Sopenharmony_ci break; 5798c2ecf20Sopenharmony_ci case Opt_norecovery: 5808c2ecf20Sopenharmony_ci /* this option mounts f2fs with ro */ 5818c2ecf20Sopenharmony_ci set_opt(sbi, NORECOVERY); 5828c2ecf20Sopenharmony_ci if (!f2fs_readonly(sb)) 5838c2ecf20Sopenharmony_ci return -EINVAL; 5848c2ecf20Sopenharmony_ci break; 5858c2ecf20Sopenharmony_ci case Opt_discard: 5868c2ecf20Sopenharmony_ci set_opt(sbi, DISCARD); 5878c2ecf20Sopenharmony_ci break; 5888c2ecf20Sopenharmony_ci case Opt_nodiscard: 5898c2ecf20Sopenharmony_ci if (f2fs_sb_has_blkzoned(sbi)) { 5908c2ecf20Sopenharmony_ci f2fs_warn(sbi, "discard is required for zoned block devices"); 5918c2ecf20Sopenharmony_ci return -EINVAL; 5928c2ecf20Sopenharmony_ci } 5938c2ecf20Sopenharmony_ci clear_opt(sbi, DISCARD); 5948c2ecf20Sopenharmony_ci break; 5958c2ecf20Sopenharmony_ci case Opt_noheap: 5968c2ecf20Sopenharmony_ci set_opt(sbi, NOHEAP); 5978c2ecf20Sopenharmony_ci break; 5988c2ecf20Sopenharmony_ci case Opt_heap: 5998c2ecf20Sopenharmony_ci clear_opt(sbi, NOHEAP); 6008c2ecf20Sopenharmony_ci break; 6018c2ecf20Sopenharmony_ci#ifdef CONFIG_F2FS_FS_XATTR 6028c2ecf20Sopenharmony_ci case Opt_user_xattr: 6038c2ecf20Sopenharmony_ci set_opt(sbi, XATTR_USER); 6048c2ecf20Sopenharmony_ci break; 6058c2ecf20Sopenharmony_ci case Opt_nouser_xattr: 6068c2ecf20Sopenharmony_ci clear_opt(sbi, XATTR_USER); 6078c2ecf20Sopenharmony_ci break; 6088c2ecf20Sopenharmony_ci case Opt_inline_xattr: 6098c2ecf20Sopenharmony_ci set_opt(sbi, INLINE_XATTR); 6108c2ecf20Sopenharmony_ci break; 6118c2ecf20Sopenharmony_ci case Opt_noinline_xattr: 6128c2ecf20Sopenharmony_ci clear_opt(sbi, INLINE_XATTR); 6138c2ecf20Sopenharmony_ci break; 6148c2ecf20Sopenharmony_ci case Opt_inline_xattr_size: 6158c2ecf20Sopenharmony_ci if (args->from && match_int(args, &arg)) 6168c2ecf20Sopenharmony_ci return -EINVAL; 6178c2ecf20Sopenharmony_ci set_opt(sbi, INLINE_XATTR_SIZE); 6188c2ecf20Sopenharmony_ci F2FS_OPTION(sbi).inline_xattr_size = arg; 6198c2ecf20Sopenharmony_ci break; 6208c2ecf20Sopenharmony_ci#else 6218c2ecf20Sopenharmony_ci case Opt_user_xattr: 6228c2ecf20Sopenharmony_ci f2fs_info(sbi, "user_xattr options not supported"); 6238c2ecf20Sopenharmony_ci break; 6248c2ecf20Sopenharmony_ci case Opt_nouser_xattr: 6258c2ecf20Sopenharmony_ci f2fs_info(sbi, "nouser_xattr options not supported"); 6268c2ecf20Sopenharmony_ci break; 6278c2ecf20Sopenharmony_ci case Opt_inline_xattr: 6288c2ecf20Sopenharmony_ci f2fs_info(sbi, "inline_xattr options not supported"); 6298c2ecf20Sopenharmony_ci break; 6308c2ecf20Sopenharmony_ci case Opt_noinline_xattr: 6318c2ecf20Sopenharmony_ci f2fs_info(sbi, "noinline_xattr options not supported"); 6328c2ecf20Sopenharmony_ci break; 6338c2ecf20Sopenharmony_ci#endif 6348c2ecf20Sopenharmony_ci#ifdef CONFIG_F2FS_FS_POSIX_ACL 6358c2ecf20Sopenharmony_ci case Opt_acl: 6368c2ecf20Sopenharmony_ci set_opt(sbi, POSIX_ACL); 6378c2ecf20Sopenharmony_ci break; 6388c2ecf20Sopenharmony_ci case Opt_noacl: 6398c2ecf20Sopenharmony_ci clear_opt(sbi, POSIX_ACL); 6408c2ecf20Sopenharmony_ci break; 6418c2ecf20Sopenharmony_ci#else 6428c2ecf20Sopenharmony_ci case Opt_acl: 6438c2ecf20Sopenharmony_ci f2fs_info(sbi, "acl options not supported"); 6448c2ecf20Sopenharmony_ci break; 6458c2ecf20Sopenharmony_ci case Opt_noacl: 6468c2ecf20Sopenharmony_ci f2fs_info(sbi, "noacl options not supported"); 6478c2ecf20Sopenharmony_ci break; 6488c2ecf20Sopenharmony_ci#endif 6498c2ecf20Sopenharmony_ci case Opt_active_logs: 6508c2ecf20Sopenharmony_ci if (args->from && match_int(args, &arg)) 6518c2ecf20Sopenharmony_ci return -EINVAL; 6528c2ecf20Sopenharmony_ci if (arg != 2 && arg != 4 && 6538c2ecf20Sopenharmony_ci arg != NR_CURSEG_PERSIST_TYPE) 6548c2ecf20Sopenharmony_ci return -EINVAL; 6558c2ecf20Sopenharmony_ci F2FS_OPTION(sbi).active_logs = arg; 6568c2ecf20Sopenharmony_ci break; 6578c2ecf20Sopenharmony_ci case Opt_disable_ext_identify: 6588c2ecf20Sopenharmony_ci set_opt(sbi, DISABLE_EXT_IDENTIFY); 6598c2ecf20Sopenharmony_ci break; 6608c2ecf20Sopenharmony_ci case Opt_inline_data: 6618c2ecf20Sopenharmony_ci set_opt(sbi, INLINE_DATA); 6628c2ecf20Sopenharmony_ci break; 6638c2ecf20Sopenharmony_ci case Opt_inline_dentry: 6648c2ecf20Sopenharmony_ci set_opt(sbi, INLINE_DENTRY); 6658c2ecf20Sopenharmony_ci break; 6668c2ecf20Sopenharmony_ci case Opt_noinline_dentry: 6678c2ecf20Sopenharmony_ci clear_opt(sbi, INLINE_DENTRY); 6688c2ecf20Sopenharmony_ci break; 6698c2ecf20Sopenharmony_ci case Opt_flush_merge: 6708c2ecf20Sopenharmony_ci set_opt(sbi, FLUSH_MERGE); 6718c2ecf20Sopenharmony_ci break; 6728c2ecf20Sopenharmony_ci case Opt_noflush_merge: 6738c2ecf20Sopenharmony_ci clear_opt(sbi, FLUSH_MERGE); 6748c2ecf20Sopenharmony_ci break; 6758c2ecf20Sopenharmony_ci case Opt_nobarrier: 6768c2ecf20Sopenharmony_ci set_opt(sbi, NOBARRIER); 6778c2ecf20Sopenharmony_ci break; 6788c2ecf20Sopenharmony_ci case Opt_fastboot: 6798c2ecf20Sopenharmony_ci set_opt(sbi, FASTBOOT); 6808c2ecf20Sopenharmony_ci break; 6818c2ecf20Sopenharmony_ci case Opt_extent_cache: 6828c2ecf20Sopenharmony_ci set_opt(sbi, EXTENT_CACHE); 6838c2ecf20Sopenharmony_ci break; 6848c2ecf20Sopenharmony_ci case Opt_noextent_cache: 6858c2ecf20Sopenharmony_ci clear_opt(sbi, EXTENT_CACHE); 6868c2ecf20Sopenharmony_ci break; 6878c2ecf20Sopenharmony_ci case Opt_noinline_data: 6888c2ecf20Sopenharmony_ci clear_opt(sbi, INLINE_DATA); 6898c2ecf20Sopenharmony_ci break; 6908c2ecf20Sopenharmony_ci case Opt_data_flush: 6918c2ecf20Sopenharmony_ci set_opt(sbi, DATA_FLUSH); 6928c2ecf20Sopenharmony_ci break; 6938c2ecf20Sopenharmony_ci case Opt_reserve_root: 6948c2ecf20Sopenharmony_ci if (args->from && match_int(args, &arg)) 6958c2ecf20Sopenharmony_ci return -EINVAL; 6968c2ecf20Sopenharmony_ci if (test_opt(sbi, RESERVE_ROOT)) { 6978c2ecf20Sopenharmony_ci f2fs_info(sbi, "Preserve previous reserve_root=%u", 6988c2ecf20Sopenharmony_ci F2FS_OPTION(sbi).root_reserved_blocks); 6998c2ecf20Sopenharmony_ci } else { 7008c2ecf20Sopenharmony_ci F2FS_OPTION(sbi).root_reserved_blocks = arg; 7018c2ecf20Sopenharmony_ci set_opt(sbi, RESERVE_ROOT); 7028c2ecf20Sopenharmony_ci } 7038c2ecf20Sopenharmony_ci break; 7048c2ecf20Sopenharmony_ci case Opt_resuid: 7058c2ecf20Sopenharmony_ci if (args->from && match_int(args, &arg)) 7068c2ecf20Sopenharmony_ci return -EINVAL; 7078c2ecf20Sopenharmony_ci uid = make_kuid(current_user_ns(), arg); 7088c2ecf20Sopenharmony_ci if (!uid_valid(uid)) { 7098c2ecf20Sopenharmony_ci f2fs_err(sbi, "Invalid uid value %d", arg); 7108c2ecf20Sopenharmony_ci return -EINVAL; 7118c2ecf20Sopenharmony_ci } 7128c2ecf20Sopenharmony_ci F2FS_OPTION(sbi).s_resuid = uid; 7138c2ecf20Sopenharmony_ci break; 7148c2ecf20Sopenharmony_ci case Opt_resgid: 7158c2ecf20Sopenharmony_ci if (args->from && match_int(args, &arg)) 7168c2ecf20Sopenharmony_ci return -EINVAL; 7178c2ecf20Sopenharmony_ci gid = make_kgid(current_user_ns(), arg); 7188c2ecf20Sopenharmony_ci if (!gid_valid(gid)) { 7198c2ecf20Sopenharmony_ci f2fs_err(sbi, "Invalid gid value %d", arg); 7208c2ecf20Sopenharmony_ci return -EINVAL; 7218c2ecf20Sopenharmony_ci } 7228c2ecf20Sopenharmony_ci F2FS_OPTION(sbi).s_resgid = gid; 7238c2ecf20Sopenharmony_ci break; 7248c2ecf20Sopenharmony_ci case Opt_mode: 7258c2ecf20Sopenharmony_ci name = match_strdup(&args[0]); 7268c2ecf20Sopenharmony_ci 7278c2ecf20Sopenharmony_ci if (!name) 7288c2ecf20Sopenharmony_ci return -ENOMEM; 7298c2ecf20Sopenharmony_ci if (!strcmp(name, "adaptive")) { 7308c2ecf20Sopenharmony_ci if (f2fs_sb_has_blkzoned(sbi)) { 7318c2ecf20Sopenharmony_ci f2fs_warn(sbi, "adaptive mode is not allowed with zoned block device feature"); 7328c2ecf20Sopenharmony_ci kfree(name); 7338c2ecf20Sopenharmony_ci return -EINVAL; 7348c2ecf20Sopenharmony_ci } 7358c2ecf20Sopenharmony_ci F2FS_OPTION(sbi).fs_mode = FS_MODE_ADAPTIVE; 7368c2ecf20Sopenharmony_ci } else if (!strcmp(name, "lfs")) { 7378c2ecf20Sopenharmony_ci F2FS_OPTION(sbi).fs_mode = FS_MODE_LFS; 7388c2ecf20Sopenharmony_ci } else { 7398c2ecf20Sopenharmony_ci kfree(name); 7408c2ecf20Sopenharmony_ci return -EINVAL; 7418c2ecf20Sopenharmony_ci } 7428c2ecf20Sopenharmony_ci kfree(name); 7438c2ecf20Sopenharmony_ci break; 7448c2ecf20Sopenharmony_ci case Opt_io_size_bits: 7458c2ecf20Sopenharmony_ci if (args->from && match_int(args, &arg)) 7468c2ecf20Sopenharmony_ci return -EINVAL; 7478c2ecf20Sopenharmony_ci if (arg <= 0 || arg > __ilog2_u32(BIO_MAX_PAGES)) { 7488c2ecf20Sopenharmony_ci f2fs_warn(sbi, "Not support %d, larger than %d", 7498c2ecf20Sopenharmony_ci 1 << arg, BIO_MAX_PAGES); 7508c2ecf20Sopenharmony_ci return -EINVAL; 7518c2ecf20Sopenharmony_ci } 7528c2ecf20Sopenharmony_ci F2FS_OPTION(sbi).write_io_size_bits = arg; 7538c2ecf20Sopenharmony_ci break; 7548c2ecf20Sopenharmony_ci#ifdef CONFIG_F2FS_FAULT_INJECTION 7558c2ecf20Sopenharmony_ci case Opt_fault_injection: 7568c2ecf20Sopenharmony_ci if (args->from && match_int(args, &arg)) 7578c2ecf20Sopenharmony_ci return -EINVAL; 7588c2ecf20Sopenharmony_ci if (f2fs_build_fault_attr(sbi, arg, 7598c2ecf20Sopenharmony_ci F2FS_ALL_FAULT_TYPE)) 7608c2ecf20Sopenharmony_ci return -EINVAL; 7618c2ecf20Sopenharmony_ci set_opt(sbi, FAULT_INJECTION); 7628c2ecf20Sopenharmony_ci break; 7638c2ecf20Sopenharmony_ci 7648c2ecf20Sopenharmony_ci case Opt_fault_type: 7658c2ecf20Sopenharmony_ci if (args->from && match_int(args, &arg)) 7668c2ecf20Sopenharmony_ci return -EINVAL; 7678c2ecf20Sopenharmony_ci if (f2fs_build_fault_attr(sbi, 0, arg)) 7688c2ecf20Sopenharmony_ci return -EINVAL; 7698c2ecf20Sopenharmony_ci set_opt(sbi, FAULT_INJECTION); 7708c2ecf20Sopenharmony_ci break; 7718c2ecf20Sopenharmony_ci#else 7728c2ecf20Sopenharmony_ci case Opt_fault_injection: 7738c2ecf20Sopenharmony_ci f2fs_info(sbi, "fault_injection options not supported"); 7748c2ecf20Sopenharmony_ci break; 7758c2ecf20Sopenharmony_ci 7768c2ecf20Sopenharmony_ci case Opt_fault_type: 7778c2ecf20Sopenharmony_ci f2fs_info(sbi, "fault_type options not supported"); 7788c2ecf20Sopenharmony_ci break; 7798c2ecf20Sopenharmony_ci#endif 7808c2ecf20Sopenharmony_ci case Opt_lazytime: 7818c2ecf20Sopenharmony_ci sb->s_flags |= SB_LAZYTIME; 7828c2ecf20Sopenharmony_ci break; 7838c2ecf20Sopenharmony_ci case Opt_nolazytime: 7848c2ecf20Sopenharmony_ci sb->s_flags &= ~SB_LAZYTIME; 7858c2ecf20Sopenharmony_ci break; 7868c2ecf20Sopenharmony_ci#ifdef CONFIG_QUOTA 7878c2ecf20Sopenharmony_ci case Opt_quota: 7888c2ecf20Sopenharmony_ci case Opt_usrquota: 7898c2ecf20Sopenharmony_ci set_opt(sbi, USRQUOTA); 7908c2ecf20Sopenharmony_ci break; 7918c2ecf20Sopenharmony_ci case Opt_grpquota: 7928c2ecf20Sopenharmony_ci set_opt(sbi, GRPQUOTA); 7938c2ecf20Sopenharmony_ci break; 7948c2ecf20Sopenharmony_ci case Opt_prjquota: 7958c2ecf20Sopenharmony_ci set_opt(sbi, PRJQUOTA); 7968c2ecf20Sopenharmony_ci break; 7978c2ecf20Sopenharmony_ci case Opt_usrjquota: 7988c2ecf20Sopenharmony_ci ret = f2fs_set_qf_name(sb, USRQUOTA, &args[0]); 7998c2ecf20Sopenharmony_ci if (ret) 8008c2ecf20Sopenharmony_ci return ret; 8018c2ecf20Sopenharmony_ci break; 8028c2ecf20Sopenharmony_ci case Opt_grpjquota: 8038c2ecf20Sopenharmony_ci ret = f2fs_set_qf_name(sb, GRPQUOTA, &args[0]); 8048c2ecf20Sopenharmony_ci if (ret) 8058c2ecf20Sopenharmony_ci return ret; 8068c2ecf20Sopenharmony_ci break; 8078c2ecf20Sopenharmony_ci case Opt_prjjquota: 8088c2ecf20Sopenharmony_ci ret = f2fs_set_qf_name(sb, PRJQUOTA, &args[0]); 8098c2ecf20Sopenharmony_ci if (ret) 8108c2ecf20Sopenharmony_ci return ret; 8118c2ecf20Sopenharmony_ci break; 8128c2ecf20Sopenharmony_ci case Opt_offusrjquota: 8138c2ecf20Sopenharmony_ci ret = f2fs_clear_qf_name(sb, USRQUOTA); 8148c2ecf20Sopenharmony_ci if (ret) 8158c2ecf20Sopenharmony_ci return ret; 8168c2ecf20Sopenharmony_ci break; 8178c2ecf20Sopenharmony_ci case Opt_offgrpjquota: 8188c2ecf20Sopenharmony_ci ret = f2fs_clear_qf_name(sb, GRPQUOTA); 8198c2ecf20Sopenharmony_ci if (ret) 8208c2ecf20Sopenharmony_ci return ret; 8218c2ecf20Sopenharmony_ci break; 8228c2ecf20Sopenharmony_ci case Opt_offprjjquota: 8238c2ecf20Sopenharmony_ci ret = f2fs_clear_qf_name(sb, PRJQUOTA); 8248c2ecf20Sopenharmony_ci if (ret) 8258c2ecf20Sopenharmony_ci return ret; 8268c2ecf20Sopenharmony_ci break; 8278c2ecf20Sopenharmony_ci case Opt_jqfmt_vfsold: 8288c2ecf20Sopenharmony_ci F2FS_OPTION(sbi).s_jquota_fmt = QFMT_VFS_OLD; 8298c2ecf20Sopenharmony_ci break; 8308c2ecf20Sopenharmony_ci case Opt_jqfmt_vfsv0: 8318c2ecf20Sopenharmony_ci F2FS_OPTION(sbi).s_jquota_fmt = QFMT_VFS_V0; 8328c2ecf20Sopenharmony_ci break; 8338c2ecf20Sopenharmony_ci case Opt_jqfmt_vfsv1: 8348c2ecf20Sopenharmony_ci F2FS_OPTION(sbi).s_jquota_fmt = QFMT_VFS_V1; 8358c2ecf20Sopenharmony_ci break; 8368c2ecf20Sopenharmony_ci case Opt_noquota: 8378c2ecf20Sopenharmony_ci clear_opt(sbi, QUOTA); 8388c2ecf20Sopenharmony_ci clear_opt(sbi, USRQUOTA); 8398c2ecf20Sopenharmony_ci clear_opt(sbi, GRPQUOTA); 8408c2ecf20Sopenharmony_ci clear_opt(sbi, PRJQUOTA); 8418c2ecf20Sopenharmony_ci break; 8428c2ecf20Sopenharmony_ci#else 8438c2ecf20Sopenharmony_ci case Opt_quota: 8448c2ecf20Sopenharmony_ci case Opt_usrquota: 8458c2ecf20Sopenharmony_ci case Opt_grpquota: 8468c2ecf20Sopenharmony_ci case Opt_prjquota: 8478c2ecf20Sopenharmony_ci case Opt_usrjquota: 8488c2ecf20Sopenharmony_ci case Opt_grpjquota: 8498c2ecf20Sopenharmony_ci case Opt_prjjquota: 8508c2ecf20Sopenharmony_ci case Opt_offusrjquota: 8518c2ecf20Sopenharmony_ci case Opt_offgrpjquota: 8528c2ecf20Sopenharmony_ci case Opt_offprjjquota: 8538c2ecf20Sopenharmony_ci case Opt_jqfmt_vfsold: 8548c2ecf20Sopenharmony_ci case Opt_jqfmt_vfsv0: 8558c2ecf20Sopenharmony_ci case Opt_jqfmt_vfsv1: 8568c2ecf20Sopenharmony_ci case Opt_noquota: 8578c2ecf20Sopenharmony_ci f2fs_info(sbi, "quota operations not supported"); 8588c2ecf20Sopenharmony_ci break; 8598c2ecf20Sopenharmony_ci#endif 8608c2ecf20Sopenharmony_ci case Opt_whint: 8618c2ecf20Sopenharmony_ci name = match_strdup(&args[0]); 8628c2ecf20Sopenharmony_ci if (!name) 8638c2ecf20Sopenharmony_ci return -ENOMEM; 8648c2ecf20Sopenharmony_ci if (!strcmp(name, "user-based")) { 8658c2ecf20Sopenharmony_ci F2FS_OPTION(sbi).whint_mode = WHINT_MODE_USER; 8668c2ecf20Sopenharmony_ci } else if (!strcmp(name, "off")) { 8678c2ecf20Sopenharmony_ci F2FS_OPTION(sbi).whint_mode = WHINT_MODE_OFF; 8688c2ecf20Sopenharmony_ci } else if (!strcmp(name, "fs-based")) { 8698c2ecf20Sopenharmony_ci F2FS_OPTION(sbi).whint_mode = WHINT_MODE_FS; 8708c2ecf20Sopenharmony_ci } else { 8718c2ecf20Sopenharmony_ci kfree(name); 8728c2ecf20Sopenharmony_ci return -EINVAL; 8738c2ecf20Sopenharmony_ci } 8748c2ecf20Sopenharmony_ci kfree(name); 8758c2ecf20Sopenharmony_ci break; 8768c2ecf20Sopenharmony_ci case Opt_alloc: 8778c2ecf20Sopenharmony_ci name = match_strdup(&args[0]); 8788c2ecf20Sopenharmony_ci if (!name) 8798c2ecf20Sopenharmony_ci return -ENOMEM; 8808c2ecf20Sopenharmony_ci 8818c2ecf20Sopenharmony_ci if (!strcmp(name, "default")) { 8828c2ecf20Sopenharmony_ci F2FS_OPTION(sbi).alloc_mode = ALLOC_MODE_DEFAULT; 8838c2ecf20Sopenharmony_ci } else if (!strcmp(name, "reuse")) { 8848c2ecf20Sopenharmony_ci F2FS_OPTION(sbi).alloc_mode = ALLOC_MODE_REUSE; 8858c2ecf20Sopenharmony_ci } else { 8868c2ecf20Sopenharmony_ci kfree(name); 8878c2ecf20Sopenharmony_ci return -EINVAL; 8888c2ecf20Sopenharmony_ci } 8898c2ecf20Sopenharmony_ci kfree(name); 8908c2ecf20Sopenharmony_ci break; 8918c2ecf20Sopenharmony_ci case Opt_fsync: 8928c2ecf20Sopenharmony_ci name = match_strdup(&args[0]); 8938c2ecf20Sopenharmony_ci if (!name) 8948c2ecf20Sopenharmony_ci return -ENOMEM; 8958c2ecf20Sopenharmony_ci if (!strcmp(name, "posix")) { 8968c2ecf20Sopenharmony_ci F2FS_OPTION(sbi).fsync_mode = FSYNC_MODE_POSIX; 8978c2ecf20Sopenharmony_ci } else if (!strcmp(name, "strict")) { 8988c2ecf20Sopenharmony_ci F2FS_OPTION(sbi).fsync_mode = FSYNC_MODE_STRICT; 8998c2ecf20Sopenharmony_ci } else if (!strcmp(name, "nobarrier")) { 9008c2ecf20Sopenharmony_ci F2FS_OPTION(sbi).fsync_mode = 9018c2ecf20Sopenharmony_ci FSYNC_MODE_NOBARRIER; 9028c2ecf20Sopenharmony_ci } else { 9038c2ecf20Sopenharmony_ci kfree(name); 9048c2ecf20Sopenharmony_ci return -EINVAL; 9058c2ecf20Sopenharmony_ci } 9068c2ecf20Sopenharmony_ci kfree(name); 9078c2ecf20Sopenharmony_ci break; 9088c2ecf20Sopenharmony_ci case Opt_test_dummy_encryption: 9098c2ecf20Sopenharmony_ci ret = f2fs_set_test_dummy_encryption(sb, p, &args[0], 9108c2ecf20Sopenharmony_ci is_remount); 9118c2ecf20Sopenharmony_ci if (ret) 9128c2ecf20Sopenharmony_ci return ret; 9138c2ecf20Sopenharmony_ci break; 9148c2ecf20Sopenharmony_ci case Opt_inlinecrypt: 9158c2ecf20Sopenharmony_ci#ifdef CONFIG_FS_ENCRYPTION_INLINE_CRYPT 9168c2ecf20Sopenharmony_ci sb->s_flags |= SB_INLINECRYPT; 9178c2ecf20Sopenharmony_ci#else 9188c2ecf20Sopenharmony_ci f2fs_info(sbi, "inline encryption not supported"); 9198c2ecf20Sopenharmony_ci#endif 9208c2ecf20Sopenharmony_ci break; 9218c2ecf20Sopenharmony_ci case Opt_checkpoint_disable_cap_perc: 9228c2ecf20Sopenharmony_ci if (args->from && match_int(args, &arg)) 9238c2ecf20Sopenharmony_ci return -EINVAL; 9248c2ecf20Sopenharmony_ci if (arg < 0 || arg > 100) 9258c2ecf20Sopenharmony_ci return -EINVAL; 9268c2ecf20Sopenharmony_ci F2FS_OPTION(sbi).unusable_cap_perc = arg; 9278c2ecf20Sopenharmony_ci set_opt(sbi, DISABLE_CHECKPOINT); 9288c2ecf20Sopenharmony_ci break; 9298c2ecf20Sopenharmony_ci case Opt_checkpoint_disable_cap: 9308c2ecf20Sopenharmony_ci if (args->from && match_int(args, &arg)) 9318c2ecf20Sopenharmony_ci return -EINVAL; 9328c2ecf20Sopenharmony_ci F2FS_OPTION(sbi).unusable_cap = arg; 9338c2ecf20Sopenharmony_ci set_opt(sbi, DISABLE_CHECKPOINT); 9348c2ecf20Sopenharmony_ci break; 9358c2ecf20Sopenharmony_ci case Opt_checkpoint_disable: 9368c2ecf20Sopenharmony_ci set_opt(sbi, DISABLE_CHECKPOINT); 9378c2ecf20Sopenharmony_ci break; 9388c2ecf20Sopenharmony_ci case Opt_checkpoint_enable: 9398c2ecf20Sopenharmony_ci clear_opt(sbi, DISABLE_CHECKPOINT); 9408c2ecf20Sopenharmony_ci break; 9418c2ecf20Sopenharmony_ci#ifdef CONFIG_F2FS_FS_COMPRESSION 9428c2ecf20Sopenharmony_ci case Opt_compress_algorithm: 9438c2ecf20Sopenharmony_ci if (!f2fs_sb_has_compression(sbi)) { 9448c2ecf20Sopenharmony_ci f2fs_info(sbi, "Image doesn't support compression"); 9458c2ecf20Sopenharmony_ci break; 9468c2ecf20Sopenharmony_ci } 9478c2ecf20Sopenharmony_ci name = match_strdup(&args[0]); 9488c2ecf20Sopenharmony_ci if (!name) 9498c2ecf20Sopenharmony_ci return -ENOMEM; 9508c2ecf20Sopenharmony_ci if (!strcmp(name, "lzo")) { 9518c2ecf20Sopenharmony_ci F2FS_OPTION(sbi).compress_algorithm = 9528c2ecf20Sopenharmony_ci COMPRESS_LZO; 9538c2ecf20Sopenharmony_ci } else if (!strcmp(name, "lz4")) { 9548c2ecf20Sopenharmony_ci F2FS_OPTION(sbi).compress_algorithm = 9558c2ecf20Sopenharmony_ci COMPRESS_LZ4; 9568c2ecf20Sopenharmony_ci } else if (!strcmp(name, "zstd")) { 9578c2ecf20Sopenharmony_ci F2FS_OPTION(sbi).compress_algorithm = 9588c2ecf20Sopenharmony_ci COMPRESS_ZSTD; 9598c2ecf20Sopenharmony_ci } else if (!strcmp(name, "lzo-rle")) { 9608c2ecf20Sopenharmony_ci F2FS_OPTION(sbi).compress_algorithm = 9618c2ecf20Sopenharmony_ci COMPRESS_LZORLE; 9628c2ecf20Sopenharmony_ci } else { 9638c2ecf20Sopenharmony_ci kfree(name); 9648c2ecf20Sopenharmony_ci return -EINVAL; 9658c2ecf20Sopenharmony_ci } 9668c2ecf20Sopenharmony_ci kfree(name); 9678c2ecf20Sopenharmony_ci break; 9688c2ecf20Sopenharmony_ci case Opt_compress_log_size: 9698c2ecf20Sopenharmony_ci if (!f2fs_sb_has_compression(sbi)) { 9708c2ecf20Sopenharmony_ci f2fs_info(sbi, "Image doesn't support compression"); 9718c2ecf20Sopenharmony_ci break; 9728c2ecf20Sopenharmony_ci } 9738c2ecf20Sopenharmony_ci if (args->from && match_int(args, &arg)) 9748c2ecf20Sopenharmony_ci return -EINVAL; 9758c2ecf20Sopenharmony_ci if (arg < MIN_COMPRESS_LOG_SIZE || 9768c2ecf20Sopenharmony_ci arg > MAX_COMPRESS_LOG_SIZE) { 9778c2ecf20Sopenharmony_ci f2fs_err(sbi, 9788c2ecf20Sopenharmony_ci "Compress cluster log size is out of range"); 9798c2ecf20Sopenharmony_ci return -EINVAL; 9808c2ecf20Sopenharmony_ci } 9818c2ecf20Sopenharmony_ci F2FS_OPTION(sbi).compress_log_size = arg; 9828c2ecf20Sopenharmony_ci break; 9838c2ecf20Sopenharmony_ci case Opt_compress_extension: 9848c2ecf20Sopenharmony_ci if (!f2fs_sb_has_compression(sbi)) { 9858c2ecf20Sopenharmony_ci f2fs_info(sbi, "Image doesn't support compression"); 9868c2ecf20Sopenharmony_ci break; 9878c2ecf20Sopenharmony_ci } 9888c2ecf20Sopenharmony_ci name = match_strdup(&args[0]); 9898c2ecf20Sopenharmony_ci if (!name) 9908c2ecf20Sopenharmony_ci return -ENOMEM; 9918c2ecf20Sopenharmony_ci 9928c2ecf20Sopenharmony_ci ext = F2FS_OPTION(sbi).extensions; 9938c2ecf20Sopenharmony_ci ext_cnt = F2FS_OPTION(sbi).compress_ext_cnt; 9948c2ecf20Sopenharmony_ci 9958c2ecf20Sopenharmony_ci if (strlen(name) >= F2FS_EXTENSION_LEN || 9968c2ecf20Sopenharmony_ci ext_cnt >= COMPRESS_EXT_NUM) { 9978c2ecf20Sopenharmony_ci f2fs_err(sbi, 9988c2ecf20Sopenharmony_ci "invalid extension length/number"); 9998c2ecf20Sopenharmony_ci kfree(name); 10008c2ecf20Sopenharmony_ci return -EINVAL; 10018c2ecf20Sopenharmony_ci } 10028c2ecf20Sopenharmony_ci 10038c2ecf20Sopenharmony_ci strcpy(ext[ext_cnt], name); 10048c2ecf20Sopenharmony_ci F2FS_OPTION(sbi).compress_ext_cnt++; 10058c2ecf20Sopenharmony_ci kfree(name); 10068c2ecf20Sopenharmony_ci break; 10078c2ecf20Sopenharmony_ci#else 10088c2ecf20Sopenharmony_ci case Opt_compress_algorithm: 10098c2ecf20Sopenharmony_ci case Opt_compress_log_size: 10108c2ecf20Sopenharmony_ci case Opt_compress_extension: 10118c2ecf20Sopenharmony_ci f2fs_info(sbi, "compression options not supported"); 10128c2ecf20Sopenharmony_ci break; 10138c2ecf20Sopenharmony_ci#endif 10148c2ecf20Sopenharmony_ci case Opt_atgc: 10158c2ecf20Sopenharmony_ci set_opt(sbi, ATGC); 10168c2ecf20Sopenharmony_ci break; 10178c2ecf20Sopenharmony_ci case Opt_gc_merge: 10188c2ecf20Sopenharmony_ci set_opt(sbi, GC_MERGE); 10198c2ecf20Sopenharmony_ci break; 10208c2ecf20Sopenharmony_ci case Opt_nogc_merge: 10218c2ecf20Sopenharmony_ci clear_opt(sbi, GC_MERGE); 10228c2ecf20Sopenharmony_ci break; 10238c2ecf20Sopenharmony_ci default: 10248c2ecf20Sopenharmony_ci f2fs_err(sbi, "Unrecognized mount option \"%s\" or missing value", 10258c2ecf20Sopenharmony_ci p); 10268c2ecf20Sopenharmony_ci return -EINVAL; 10278c2ecf20Sopenharmony_ci } 10288c2ecf20Sopenharmony_ci } 10298c2ecf20Sopenharmony_ci#ifdef CONFIG_QUOTA 10308c2ecf20Sopenharmony_ci if (f2fs_check_quota_options(sbi)) 10318c2ecf20Sopenharmony_ci return -EINVAL; 10328c2ecf20Sopenharmony_ci#else 10338c2ecf20Sopenharmony_ci if (f2fs_sb_has_quota_ino(sbi) && !f2fs_readonly(sbi->sb)) { 10348c2ecf20Sopenharmony_ci f2fs_info(sbi, "Filesystem with quota feature cannot be mounted RDWR without CONFIG_QUOTA"); 10358c2ecf20Sopenharmony_ci return -EINVAL; 10368c2ecf20Sopenharmony_ci } 10378c2ecf20Sopenharmony_ci if (f2fs_sb_has_project_quota(sbi) && !f2fs_readonly(sbi->sb)) { 10388c2ecf20Sopenharmony_ci f2fs_err(sbi, "Filesystem with project quota feature cannot be mounted RDWR without CONFIG_QUOTA"); 10398c2ecf20Sopenharmony_ci return -EINVAL; 10408c2ecf20Sopenharmony_ci } 10418c2ecf20Sopenharmony_ci#endif 10428c2ecf20Sopenharmony_ci#ifndef CONFIG_UNICODE 10438c2ecf20Sopenharmony_ci if (f2fs_sb_has_casefold(sbi)) { 10448c2ecf20Sopenharmony_ci f2fs_err(sbi, 10458c2ecf20Sopenharmony_ci "Filesystem with casefold feature cannot be mounted without CONFIG_UNICODE"); 10468c2ecf20Sopenharmony_ci return -EINVAL; 10478c2ecf20Sopenharmony_ci } 10488c2ecf20Sopenharmony_ci#endif 10498c2ecf20Sopenharmony_ci /* 10508c2ecf20Sopenharmony_ci * The BLKZONED feature indicates that the drive was formatted with 10518c2ecf20Sopenharmony_ci * zone alignment optimization. This is optional for host-aware 10528c2ecf20Sopenharmony_ci * devices, but mandatory for host-managed zoned block devices. 10538c2ecf20Sopenharmony_ci */ 10548c2ecf20Sopenharmony_ci#ifndef CONFIG_BLK_DEV_ZONED 10558c2ecf20Sopenharmony_ci if (f2fs_sb_has_blkzoned(sbi)) { 10568c2ecf20Sopenharmony_ci f2fs_err(sbi, "Zoned block device support is not enabled"); 10578c2ecf20Sopenharmony_ci return -EINVAL; 10588c2ecf20Sopenharmony_ci } 10598c2ecf20Sopenharmony_ci#endif 10608c2ecf20Sopenharmony_ci 10618c2ecf20Sopenharmony_ci if (F2FS_IO_SIZE_BITS(sbi) && !f2fs_lfs_mode(sbi)) { 10628c2ecf20Sopenharmony_ci f2fs_err(sbi, "Should set mode=lfs with %uKB-sized IO", 10638c2ecf20Sopenharmony_ci F2FS_IO_SIZE_KB(sbi)); 10648c2ecf20Sopenharmony_ci return -EINVAL; 10658c2ecf20Sopenharmony_ci } 10668c2ecf20Sopenharmony_ci 10678c2ecf20Sopenharmony_ci if (test_opt(sbi, INLINE_XATTR_SIZE)) { 10688c2ecf20Sopenharmony_ci int min_size, max_size; 10698c2ecf20Sopenharmony_ci 10708c2ecf20Sopenharmony_ci if (!f2fs_sb_has_extra_attr(sbi) || 10718c2ecf20Sopenharmony_ci !f2fs_sb_has_flexible_inline_xattr(sbi)) { 10728c2ecf20Sopenharmony_ci f2fs_err(sbi, "extra_attr or flexible_inline_xattr feature is off"); 10738c2ecf20Sopenharmony_ci return -EINVAL; 10748c2ecf20Sopenharmony_ci } 10758c2ecf20Sopenharmony_ci if (!test_opt(sbi, INLINE_XATTR)) { 10768c2ecf20Sopenharmony_ci f2fs_err(sbi, "inline_xattr_size option should be set with inline_xattr option"); 10778c2ecf20Sopenharmony_ci return -EINVAL; 10788c2ecf20Sopenharmony_ci } 10798c2ecf20Sopenharmony_ci 10808c2ecf20Sopenharmony_ci min_size = sizeof(struct f2fs_xattr_header) / sizeof(__le32); 10818c2ecf20Sopenharmony_ci max_size = MAX_INLINE_XATTR_SIZE; 10828c2ecf20Sopenharmony_ci 10838c2ecf20Sopenharmony_ci if (F2FS_OPTION(sbi).inline_xattr_size < min_size || 10848c2ecf20Sopenharmony_ci F2FS_OPTION(sbi).inline_xattr_size > max_size) { 10858c2ecf20Sopenharmony_ci f2fs_err(sbi, "inline xattr size is out of range: %d ~ %d", 10868c2ecf20Sopenharmony_ci min_size, max_size); 10878c2ecf20Sopenharmony_ci return -EINVAL; 10888c2ecf20Sopenharmony_ci } 10898c2ecf20Sopenharmony_ci } 10908c2ecf20Sopenharmony_ci 10918c2ecf20Sopenharmony_ci if (test_opt(sbi, DISABLE_CHECKPOINT) && f2fs_lfs_mode(sbi)) { 10928c2ecf20Sopenharmony_ci f2fs_err(sbi, "LFS not compatible with checkpoint=disable\n"); 10938c2ecf20Sopenharmony_ci return -EINVAL; 10948c2ecf20Sopenharmony_ci } 10958c2ecf20Sopenharmony_ci 10968c2ecf20Sopenharmony_ci /* Not pass down write hints if the number of active logs is lesser 10978c2ecf20Sopenharmony_ci * than NR_CURSEG_PERSIST_TYPE. 10988c2ecf20Sopenharmony_ci */ 10998c2ecf20Sopenharmony_ci if (F2FS_OPTION(sbi).active_logs != NR_CURSEG_PERSIST_TYPE) 11008c2ecf20Sopenharmony_ci F2FS_OPTION(sbi).whint_mode = WHINT_MODE_OFF; 11018c2ecf20Sopenharmony_ci return 0; 11028c2ecf20Sopenharmony_ci} 11038c2ecf20Sopenharmony_ci 11048c2ecf20Sopenharmony_cistatic struct inode *f2fs_alloc_inode(struct super_block *sb) 11058c2ecf20Sopenharmony_ci{ 11068c2ecf20Sopenharmony_ci struct f2fs_inode_info *fi; 11078c2ecf20Sopenharmony_ci 11088c2ecf20Sopenharmony_ci fi = kmem_cache_alloc(f2fs_inode_cachep, GFP_F2FS_ZERO); 11098c2ecf20Sopenharmony_ci if (!fi) 11108c2ecf20Sopenharmony_ci return NULL; 11118c2ecf20Sopenharmony_ci 11128c2ecf20Sopenharmony_ci init_once((void *) fi); 11138c2ecf20Sopenharmony_ci 11148c2ecf20Sopenharmony_ci /* Initialize f2fs-specific inode info */ 11158c2ecf20Sopenharmony_ci atomic_set(&fi->dirty_pages, 0); 11168c2ecf20Sopenharmony_ci atomic_set(&fi->i_compr_blocks, 0); 11178c2ecf20Sopenharmony_ci init_rwsem(&fi->i_sem); 11188c2ecf20Sopenharmony_ci spin_lock_init(&fi->i_size_lock); 11198c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&fi->dirty_list); 11208c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&fi->gdirty_list); 11218c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&fi->inmem_ilist); 11228c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&fi->inmem_pages); 11238c2ecf20Sopenharmony_ci mutex_init(&fi->inmem_lock); 11248c2ecf20Sopenharmony_ci init_rwsem(&fi->i_gc_rwsem[READ]); 11258c2ecf20Sopenharmony_ci init_rwsem(&fi->i_gc_rwsem[WRITE]); 11268c2ecf20Sopenharmony_ci init_rwsem(&fi->i_mmap_sem); 11278c2ecf20Sopenharmony_ci init_rwsem(&fi->i_xattr_sem); 11288c2ecf20Sopenharmony_ci 11298c2ecf20Sopenharmony_ci /* Will be used by directory only */ 11308c2ecf20Sopenharmony_ci fi->i_dir_level = F2FS_SB(sb)->dir_level; 11318c2ecf20Sopenharmony_ci 11328c2ecf20Sopenharmony_ci fi->ra_offset = -1; 11338c2ecf20Sopenharmony_ci 11348c2ecf20Sopenharmony_ci return &fi->vfs_inode; 11358c2ecf20Sopenharmony_ci} 11368c2ecf20Sopenharmony_ci 11378c2ecf20Sopenharmony_cistatic int f2fs_drop_inode(struct inode *inode) 11388c2ecf20Sopenharmony_ci{ 11398c2ecf20Sopenharmony_ci struct f2fs_sb_info *sbi = F2FS_I_SB(inode); 11408c2ecf20Sopenharmony_ci int ret; 11418c2ecf20Sopenharmony_ci 11428c2ecf20Sopenharmony_ci /* 11438c2ecf20Sopenharmony_ci * during filesystem shutdown, if checkpoint is disabled, 11448c2ecf20Sopenharmony_ci * drop useless meta/node dirty pages. 11458c2ecf20Sopenharmony_ci */ 11468c2ecf20Sopenharmony_ci if (unlikely(is_sbi_flag_set(sbi, SBI_CP_DISABLED))) { 11478c2ecf20Sopenharmony_ci if (inode->i_ino == F2FS_NODE_INO(sbi) || 11488c2ecf20Sopenharmony_ci inode->i_ino == F2FS_META_INO(sbi)) { 11498c2ecf20Sopenharmony_ci trace_f2fs_drop_inode(inode, 1); 11508c2ecf20Sopenharmony_ci return 1; 11518c2ecf20Sopenharmony_ci } 11528c2ecf20Sopenharmony_ci } 11538c2ecf20Sopenharmony_ci 11548c2ecf20Sopenharmony_ci /* 11558c2ecf20Sopenharmony_ci * This is to avoid a deadlock condition like below. 11568c2ecf20Sopenharmony_ci * writeback_single_inode(inode) 11578c2ecf20Sopenharmony_ci * - f2fs_write_data_page 11588c2ecf20Sopenharmony_ci * - f2fs_gc -> iput -> evict 11598c2ecf20Sopenharmony_ci * - inode_wait_for_writeback(inode) 11608c2ecf20Sopenharmony_ci */ 11618c2ecf20Sopenharmony_ci if ((!inode_unhashed(inode) && inode->i_state & I_SYNC)) { 11628c2ecf20Sopenharmony_ci if (!inode->i_nlink && !is_bad_inode(inode)) { 11638c2ecf20Sopenharmony_ci /* to avoid evict_inode call simultaneously */ 11648c2ecf20Sopenharmony_ci atomic_inc(&inode->i_count); 11658c2ecf20Sopenharmony_ci spin_unlock(&inode->i_lock); 11668c2ecf20Sopenharmony_ci 11678c2ecf20Sopenharmony_ci /* some remained atomic pages should discarded */ 11688c2ecf20Sopenharmony_ci if (f2fs_is_atomic_file(inode)) 11698c2ecf20Sopenharmony_ci f2fs_drop_inmem_pages(inode); 11708c2ecf20Sopenharmony_ci 11718c2ecf20Sopenharmony_ci /* should remain fi->extent_tree for writepage */ 11728c2ecf20Sopenharmony_ci f2fs_destroy_extent_node(inode); 11738c2ecf20Sopenharmony_ci 11748c2ecf20Sopenharmony_ci sb_start_intwrite(inode->i_sb); 11758c2ecf20Sopenharmony_ci f2fs_i_size_write(inode, 0); 11768c2ecf20Sopenharmony_ci 11778c2ecf20Sopenharmony_ci f2fs_submit_merged_write_cond(F2FS_I_SB(inode), 11788c2ecf20Sopenharmony_ci inode, NULL, 0, DATA); 11798c2ecf20Sopenharmony_ci truncate_inode_pages_final(inode->i_mapping); 11808c2ecf20Sopenharmony_ci 11818c2ecf20Sopenharmony_ci if (F2FS_HAS_BLOCKS(inode)) 11828c2ecf20Sopenharmony_ci f2fs_truncate(inode); 11838c2ecf20Sopenharmony_ci 11848c2ecf20Sopenharmony_ci sb_end_intwrite(inode->i_sb); 11858c2ecf20Sopenharmony_ci 11868c2ecf20Sopenharmony_ci spin_lock(&inode->i_lock); 11878c2ecf20Sopenharmony_ci atomic_dec(&inode->i_count); 11888c2ecf20Sopenharmony_ci } 11898c2ecf20Sopenharmony_ci trace_f2fs_drop_inode(inode, 0); 11908c2ecf20Sopenharmony_ci return 0; 11918c2ecf20Sopenharmony_ci } 11928c2ecf20Sopenharmony_ci ret = generic_drop_inode(inode); 11938c2ecf20Sopenharmony_ci if (!ret) 11948c2ecf20Sopenharmony_ci ret = fscrypt_drop_inode(inode); 11958c2ecf20Sopenharmony_ci trace_f2fs_drop_inode(inode, ret); 11968c2ecf20Sopenharmony_ci return ret; 11978c2ecf20Sopenharmony_ci} 11988c2ecf20Sopenharmony_ci 11998c2ecf20Sopenharmony_ciint f2fs_inode_dirtied(struct inode *inode, bool sync) 12008c2ecf20Sopenharmony_ci{ 12018c2ecf20Sopenharmony_ci struct f2fs_sb_info *sbi = F2FS_I_SB(inode); 12028c2ecf20Sopenharmony_ci int ret = 0; 12038c2ecf20Sopenharmony_ci 12048c2ecf20Sopenharmony_ci spin_lock(&sbi->inode_lock[DIRTY_META]); 12058c2ecf20Sopenharmony_ci if (is_inode_flag_set(inode, FI_DIRTY_INODE)) { 12068c2ecf20Sopenharmony_ci ret = 1; 12078c2ecf20Sopenharmony_ci } else { 12088c2ecf20Sopenharmony_ci set_inode_flag(inode, FI_DIRTY_INODE); 12098c2ecf20Sopenharmony_ci stat_inc_dirty_inode(sbi, DIRTY_META); 12108c2ecf20Sopenharmony_ci } 12118c2ecf20Sopenharmony_ci if (sync && list_empty(&F2FS_I(inode)->gdirty_list)) { 12128c2ecf20Sopenharmony_ci list_add_tail(&F2FS_I(inode)->gdirty_list, 12138c2ecf20Sopenharmony_ci &sbi->inode_list[DIRTY_META]); 12148c2ecf20Sopenharmony_ci inc_page_count(sbi, F2FS_DIRTY_IMETA); 12158c2ecf20Sopenharmony_ci } 12168c2ecf20Sopenharmony_ci spin_unlock(&sbi->inode_lock[DIRTY_META]); 12178c2ecf20Sopenharmony_ci return ret; 12188c2ecf20Sopenharmony_ci} 12198c2ecf20Sopenharmony_ci 12208c2ecf20Sopenharmony_civoid f2fs_inode_synced(struct inode *inode) 12218c2ecf20Sopenharmony_ci{ 12228c2ecf20Sopenharmony_ci struct f2fs_sb_info *sbi = F2FS_I_SB(inode); 12238c2ecf20Sopenharmony_ci 12248c2ecf20Sopenharmony_ci spin_lock(&sbi->inode_lock[DIRTY_META]); 12258c2ecf20Sopenharmony_ci if (!is_inode_flag_set(inode, FI_DIRTY_INODE)) { 12268c2ecf20Sopenharmony_ci spin_unlock(&sbi->inode_lock[DIRTY_META]); 12278c2ecf20Sopenharmony_ci return; 12288c2ecf20Sopenharmony_ci } 12298c2ecf20Sopenharmony_ci if (!list_empty(&F2FS_I(inode)->gdirty_list)) { 12308c2ecf20Sopenharmony_ci list_del_init(&F2FS_I(inode)->gdirty_list); 12318c2ecf20Sopenharmony_ci dec_page_count(sbi, F2FS_DIRTY_IMETA); 12328c2ecf20Sopenharmony_ci } 12338c2ecf20Sopenharmony_ci clear_inode_flag(inode, FI_DIRTY_INODE); 12348c2ecf20Sopenharmony_ci clear_inode_flag(inode, FI_AUTO_RECOVER); 12358c2ecf20Sopenharmony_ci stat_dec_dirty_inode(F2FS_I_SB(inode), DIRTY_META); 12368c2ecf20Sopenharmony_ci spin_unlock(&sbi->inode_lock[DIRTY_META]); 12378c2ecf20Sopenharmony_ci} 12388c2ecf20Sopenharmony_ci 12398c2ecf20Sopenharmony_ci/* 12408c2ecf20Sopenharmony_ci * f2fs_dirty_inode() is called from __mark_inode_dirty() 12418c2ecf20Sopenharmony_ci * 12428c2ecf20Sopenharmony_ci * We should call set_dirty_inode to write the dirty inode through write_inode. 12438c2ecf20Sopenharmony_ci */ 12448c2ecf20Sopenharmony_cistatic void f2fs_dirty_inode(struct inode *inode, int flags) 12458c2ecf20Sopenharmony_ci{ 12468c2ecf20Sopenharmony_ci struct f2fs_sb_info *sbi = F2FS_I_SB(inode); 12478c2ecf20Sopenharmony_ci 12488c2ecf20Sopenharmony_ci if (inode->i_ino == F2FS_NODE_INO(sbi) || 12498c2ecf20Sopenharmony_ci inode->i_ino == F2FS_META_INO(sbi)) 12508c2ecf20Sopenharmony_ci return; 12518c2ecf20Sopenharmony_ci 12528c2ecf20Sopenharmony_ci if (flags == I_DIRTY_TIME) 12538c2ecf20Sopenharmony_ci return; 12548c2ecf20Sopenharmony_ci 12558c2ecf20Sopenharmony_ci if (is_inode_flag_set(inode, FI_AUTO_RECOVER)) 12568c2ecf20Sopenharmony_ci clear_inode_flag(inode, FI_AUTO_RECOVER); 12578c2ecf20Sopenharmony_ci 12588c2ecf20Sopenharmony_ci f2fs_inode_dirtied(inode, false); 12598c2ecf20Sopenharmony_ci} 12608c2ecf20Sopenharmony_ci 12618c2ecf20Sopenharmony_cistatic void f2fs_free_inode(struct inode *inode) 12628c2ecf20Sopenharmony_ci{ 12638c2ecf20Sopenharmony_ci fscrypt_free_inode(inode); 12648c2ecf20Sopenharmony_ci kmem_cache_free(f2fs_inode_cachep, F2FS_I(inode)); 12658c2ecf20Sopenharmony_ci} 12668c2ecf20Sopenharmony_ci 12678c2ecf20Sopenharmony_cistatic void destroy_percpu_info(struct f2fs_sb_info *sbi) 12688c2ecf20Sopenharmony_ci{ 12698c2ecf20Sopenharmony_ci percpu_counter_destroy(&sbi->alloc_valid_block_count); 12708c2ecf20Sopenharmony_ci percpu_counter_destroy(&sbi->total_valid_inode_count); 12718c2ecf20Sopenharmony_ci} 12728c2ecf20Sopenharmony_ci 12738c2ecf20Sopenharmony_cistatic void destroy_device_list(struct f2fs_sb_info *sbi) 12748c2ecf20Sopenharmony_ci{ 12758c2ecf20Sopenharmony_ci int i; 12768c2ecf20Sopenharmony_ci 12778c2ecf20Sopenharmony_ci for (i = 0; i < sbi->s_ndevs; i++) { 12788c2ecf20Sopenharmony_ci blkdev_put(FDEV(i).bdev, FMODE_EXCL); 12798c2ecf20Sopenharmony_ci#ifdef CONFIG_BLK_DEV_ZONED 12808c2ecf20Sopenharmony_ci kvfree(FDEV(i).blkz_seq); 12818c2ecf20Sopenharmony_ci#endif 12828c2ecf20Sopenharmony_ci } 12838c2ecf20Sopenharmony_ci kvfree(sbi->devs); 12848c2ecf20Sopenharmony_ci} 12858c2ecf20Sopenharmony_ci 12868c2ecf20Sopenharmony_cistatic void f2fs_put_super(struct super_block *sb) 12878c2ecf20Sopenharmony_ci{ 12888c2ecf20Sopenharmony_ci struct f2fs_sb_info *sbi = F2FS_SB(sb); 12898c2ecf20Sopenharmony_ci int i; 12908c2ecf20Sopenharmony_ci bool dropped; 12918c2ecf20Sopenharmony_ci 12928c2ecf20Sopenharmony_ci /* unregister procfs/sysfs entries in advance to avoid race case */ 12938c2ecf20Sopenharmony_ci f2fs_unregister_sysfs(sbi); 12948c2ecf20Sopenharmony_ci 12958c2ecf20Sopenharmony_ci f2fs_quota_off_umount(sb); 12968c2ecf20Sopenharmony_ci 12978c2ecf20Sopenharmony_ci /* prevent remaining shrinker jobs */ 12988c2ecf20Sopenharmony_ci mutex_lock(&sbi->umount_mutex); 12998c2ecf20Sopenharmony_ci 13008c2ecf20Sopenharmony_ci /* 13018c2ecf20Sopenharmony_ci * We don't need to do checkpoint when superblock is clean. 13028c2ecf20Sopenharmony_ci * But, the previous checkpoint was not done by umount, it needs to do 13038c2ecf20Sopenharmony_ci * clean checkpoint again. 13048c2ecf20Sopenharmony_ci */ 13058c2ecf20Sopenharmony_ci if ((is_sbi_flag_set(sbi, SBI_IS_DIRTY) || 13068c2ecf20Sopenharmony_ci !is_set_ckpt_flags(sbi, CP_UMOUNT_FLAG))) { 13078c2ecf20Sopenharmony_ci struct cp_control cpc = { 13088c2ecf20Sopenharmony_ci .reason = CP_UMOUNT, 13098c2ecf20Sopenharmony_ci }; 13108c2ecf20Sopenharmony_ci f2fs_write_checkpoint(sbi, &cpc); 13118c2ecf20Sopenharmony_ci } 13128c2ecf20Sopenharmony_ci 13138c2ecf20Sopenharmony_ci /* be sure to wait for any on-going discard commands */ 13148c2ecf20Sopenharmony_ci dropped = f2fs_issue_discard_timeout(sbi); 13158c2ecf20Sopenharmony_ci 13168c2ecf20Sopenharmony_ci if ((f2fs_hw_support_discard(sbi) || f2fs_hw_should_discard(sbi)) && 13178c2ecf20Sopenharmony_ci !sbi->discard_blks && !dropped) { 13188c2ecf20Sopenharmony_ci struct cp_control cpc = { 13198c2ecf20Sopenharmony_ci .reason = CP_UMOUNT | CP_TRIMMED, 13208c2ecf20Sopenharmony_ci }; 13218c2ecf20Sopenharmony_ci f2fs_write_checkpoint(sbi, &cpc); 13228c2ecf20Sopenharmony_ci } 13238c2ecf20Sopenharmony_ci 13248c2ecf20Sopenharmony_ci /* 13258c2ecf20Sopenharmony_ci * normally superblock is clean, so we need to release this. 13268c2ecf20Sopenharmony_ci * In addition, EIO will skip do checkpoint, we need this as well. 13278c2ecf20Sopenharmony_ci */ 13288c2ecf20Sopenharmony_ci f2fs_release_ino_entry(sbi, true); 13298c2ecf20Sopenharmony_ci 13308c2ecf20Sopenharmony_ci f2fs_leave_shrinker(sbi); 13318c2ecf20Sopenharmony_ci mutex_unlock(&sbi->umount_mutex); 13328c2ecf20Sopenharmony_ci 13338c2ecf20Sopenharmony_ci /* our cp_error case, we can wait for any writeback page */ 13348c2ecf20Sopenharmony_ci f2fs_flush_merged_writes(sbi); 13358c2ecf20Sopenharmony_ci 13368c2ecf20Sopenharmony_ci f2fs_wait_on_all_pages(sbi, F2FS_WB_CP_DATA); 13378c2ecf20Sopenharmony_ci 13388c2ecf20Sopenharmony_ci f2fs_bug_on(sbi, sbi->fsync_node_num); 13398c2ecf20Sopenharmony_ci 13408c2ecf20Sopenharmony_ci iput(sbi->node_inode); 13418c2ecf20Sopenharmony_ci sbi->node_inode = NULL; 13428c2ecf20Sopenharmony_ci 13438c2ecf20Sopenharmony_ci iput(sbi->meta_inode); 13448c2ecf20Sopenharmony_ci sbi->meta_inode = NULL; 13458c2ecf20Sopenharmony_ci 13468c2ecf20Sopenharmony_ci /* 13478c2ecf20Sopenharmony_ci * iput() can update stat information, if f2fs_write_checkpoint() 13488c2ecf20Sopenharmony_ci * above failed with error. 13498c2ecf20Sopenharmony_ci */ 13508c2ecf20Sopenharmony_ci f2fs_destroy_stats(sbi); 13518c2ecf20Sopenharmony_ci 13528c2ecf20Sopenharmony_ci /* destroy f2fs internal modules */ 13538c2ecf20Sopenharmony_ci f2fs_destroy_node_manager(sbi); 13548c2ecf20Sopenharmony_ci f2fs_destroy_segment_manager(sbi); 13558c2ecf20Sopenharmony_ci 13568c2ecf20Sopenharmony_ci f2fs_destroy_post_read_wq(sbi); 13578c2ecf20Sopenharmony_ci 13588c2ecf20Sopenharmony_ci kvfree(sbi->ckpt); 13598c2ecf20Sopenharmony_ci 13608c2ecf20Sopenharmony_ci sb->s_fs_info = NULL; 13618c2ecf20Sopenharmony_ci if (sbi->s_chksum_driver) 13628c2ecf20Sopenharmony_ci crypto_free_shash(sbi->s_chksum_driver); 13638c2ecf20Sopenharmony_ci kfree(sbi->raw_super); 13648c2ecf20Sopenharmony_ci 13658c2ecf20Sopenharmony_ci destroy_device_list(sbi); 13668c2ecf20Sopenharmony_ci f2fs_destroy_page_array_cache(sbi); 13678c2ecf20Sopenharmony_ci f2fs_destroy_xattr_caches(sbi); 13688c2ecf20Sopenharmony_ci mempool_destroy(sbi->write_io_dummy); 13698c2ecf20Sopenharmony_ci#ifdef CONFIG_QUOTA 13708c2ecf20Sopenharmony_ci for (i = 0; i < MAXQUOTAS; i++) 13718c2ecf20Sopenharmony_ci kfree(F2FS_OPTION(sbi).s_qf_names[i]); 13728c2ecf20Sopenharmony_ci#endif 13738c2ecf20Sopenharmony_ci fscrypt_free_dummy_policy(&F2FS_OPTION(sbi).dummy_enc_policy); 13748c2ecf20Sopenharmony_ci destroy_percpu_info(sbi); 13758c2ecf20Sopenharmony_ci for (i = 0; i < NR_PAGE_TYPE; i++) 13768c2ecf20Sopenharmony_ci kvfree(sbi->write_io[i]); 13778c2ecf20Sopenharmony_ci#ifdef CONFIG_UNICODE 13788c2ecf20Sopenharmony_ci utf8_unload(sb->s_encoding); 13798c2ecf20Sopenharmony_ci#endif 13808c2ecf20Sopenharmony_ci kfree(sbi); 13818c2ecf20Sopenharmony_ci} 13828c2ecf20Sopenharmony_ci 13838c2ecf20Sopenharmony_ciint f2fs_sync_fs(struct super_block *sb, int sync) 13848c2ecf20Sopenharmony_ci{ 13858c2ecf20Sopenharmony_ci struct f2fs_sb_info *sbi = F2FS_SB(sb); 13868c2ecf20Sopenharmony_ci int err = 0; 13878c2ecf20Sopenharmony_ci 13888c2ecf20Sopenharmony_ci if (unlikely(f2fs_cp_error(sbi))) 13898c2ecf20Sopenharmony_ci return 0; 13908c2ecf20Sopenharmony_ci if (unlikely(is_sbi_flag_set(sbi, SBI_CP_DISABLED))) 13918c2ecf20Sopenharmony_ci return 0; 13928c2ecf20Sopenharmony_ci 13938c2ecf20Sopenharmony_ci trace_f2fs_sync_fs(sb, sync); 13948c2ecf20Sopenharmony_ci 13958c2ecf20Sopenharmony_ci if (unlikely(is_sbi_flag_set(sbi, SBI_POR_DOING))) 13968c2ecf20Sopenharmony_ci return -EAGAIN; 13978c2ecf20Sopenharmony_ci 13988c2ecf20Sopenharmony_ci if (sync) { 13998c2ecf20Sopenharmony_ci struct cp_control cpc; 14008c2ecf20Sopenharmony_ci 14018c2ecf20Sopenharmony_ci cpc.reason = __get_cp_reason(sbi); 14028c2ecf20Sopenharmony_ci 14038c2ecf20Sopenharmony_ci down_write(&sbi->gc_lock); 14048c2ecf20Sopenharmony_ci err = f2fs_write_checkpoint(sbi, &cpc); 14058c2ecf20Sopenharmony_ci up_write(&sbi->gc_lock); 14068c2ecf20Sopenharmony_ci } 14078c2ecf20Sopenharmony_ci f2fs_trace_ios(NULL, 1); 14088c2ecf20Sopenharmony_ci 14098c2ecf20Sopenharmony_ci return err; 14108c2ecf20Sopenharmony_ci} 14118c2ecf20Sopenharmony_ci 14128c2ecf20Sopenharmony_cistatic int f2fs_freeze(struct super_block *sb) 14138c2ecf20Sopenharmony_ci{ 14148c2ecf20Sopenharmony_ci if (f2fs_readonly(sb)) 14158c2ecf20Sopenharmony_ci return 0; 14168c2ecf20Sopenharmony_ci 14178c2ecf20Sopenharmony_ci /* IO error happened before */ 14188c2ecf20Sopenharmony_ci if (unlikely(f2fs_cp_error(F2FS_SB(sb)))) 14198c2ecf20Sopenharmony_ci return -EIO; 14208c2ecf20Sopenharmony_ci 14218c2ecf20Sopenharmony_ci /* must be clean, since sync_filesystem() was already called */ 14228c2ecf20Sopenharmony_ci if (is_sbi_flag_set(F2FS_SB(sb), SBI_IS_DIRTY)) 14238c2ecf20Sopenharmony_ci return -EINVAL; 14248c2ecf20Sopenharmony_ci return 0; 14258c2ecf20Sopenharmony_ci} 14268c2ecf20Sopenharmony_ci 14278c2ecf20Sopenharmony_cistatic int f2fs_unfreeze(struct super_block *sb) 14288c2ecf20Sopenharmony_ci{ 14298c2ecf20Sopenharmony_ci return 0; 14308c2ecf20Sopenharmony_ci} 14318c2ecf20Sopenharmony_ci 14328c2ecf20Sopenharmony_ci#ifdef CONFIG_QUOTA 14338c2ecf20Sopenharmony_cistatic int f2fs_statfs_project(struct super_block *sb, 14348c2ecf20Sopenharmony_ci kprojid_t projid, struct kstatfs *buf) 14358c2ecf20Sopenharmony_ci{ 14368c2ecf20Sopenharmony_ci struct kqid qid; 14378c2ecf20Sopenharmony_ci struct dquot *dquot; 14388c2ecf20Sopenharmony_ci u64 limit; 14398c2ecf20Sopenharmony_ci u64 curblock; 14408c2ecf20Sopenharmony_ci 14418c2ecf20Sopenharmony_ci qid = make_kqid_projid(projid); 14428c2ecf20Sopenharmony_ci dquot = dqget(sb, qid); 14438c2ecf20Sopenharmony_ci if (IS_ERR(dquot)) 14448c2ecf20Sopenharmony_ci return PTR_ERR(dquot); 14458c2ecf20Sopenharmony_ci spin_lock(&dquot->dq_dqb_lock); 14468c2ecf20Sopenharmony_ci 14478c2ecf20Sopenharmony_ci limit = min_not_zero(dquot->dq_dqb.dqb_bsoftlimit, 14488c2ecf20Sopenharmony_ci dquot->dq_dqb.dqb_bhardlimit); 14498c2ecf20Sopenharmony_ci if (limit) 14508c2ecf20Sopenharmony_ci limit >>= sb->s_blocksize_bits; 14518c2ecf20Sopenharmony_ci 14528c2ecf20Sopenharmony_ci if (limit && buf->f_blocks > limit) { 14538c2ecf20Sopenharmony_ci curblock = (dquot->dq_dqb.dqb_curspace + 14548c2ecf20Sopenharmony_ci dquot->dq_dqb.dqb_rsvspace) >> sb->s_blocksize_bits; 14558c2ecf20Sopenharmony_ci buf->f_blocks = limit; 14568c2ecf20Sopenharmony_ci buf->f_bfree = buf->f_bavail = 14578c2ecf20Sopenharmony_ci (buf->f_blocks > curblock) ? 14588c2ecf20Sopenharmony_ci (buf->f_blocks - curblock) : 0; 14598c2ecf20Sopenharmony_ci } 14608c2ecf20Sopenharmony_ci 14618c2ecf20Sopenharmony_ci limit = min_not_zero(dquot->dq_dqb.dqb_isoftlimit, 14628c2ecf20Sopenharmony_ci dquot->dq_dqb.dqb_ihardlimit); 14638c2ecf20Sopenharmony_ci 14648c2ecf20Sopenharmony_ci if (limit && buf->f_files > limit) { 14658c2ecf20Sopenharmony_ci buf->f_files = limit; 14668c2ecf20Sopenharmony_ci buf->f_ffree = 14678c2ecf20Sopenharmony_ci (buf->f_files > dquot->dq_dqb.dqb_curinodes) ? 14688c2ecf20Sopenharmony_ci (buf->f_files - dquot->dq_dqb.dqb_curinodes) : 0; 14698c2ecf20Sopenharmony_ci } 14708c2ecf20Sopenharmony_ci 14718c2ecf20Sopenharmony_ci spin_unlock(&dquot->dq_dqb_lock); 14728c2ecf20Sopenharmony_ci dqput(dquot); 14738c2ecf20Sopenharmony_ci return 0; 14748c2ecf20Sopenharmony_ci} 14758c2ecf20Sopenharmony_ci#endif 14768c2ecf20Sopenharmony_ci 14778c2ecf20Sopenharmony_cistatic int f2fs_statfs(struct dentry *dentry, struct kstatfs *buf) 14788c2ecf20Sopenharmony_ci{ 14798c2ecf20Sopenharmony_ci struct super_block *sb = dentry->d_sb; 14808c2ecf20Sopenharmony_ci struct f2fs_sb_info *sbi = F2FS_SB(sb); 14818c2ecf20Sopenharmony_ci u64 id = huge_encode_dev(sb->s_bdev->bd_dev); 14828c2ecf20Sopenharmony_ci block_t total_count, user_block_count, start_count; 14838c2ecf20Sopenharmony_ci u64 avail_node_count; 14848c2ecf20Sopenharmony_ci 14858c2ecf20Sopenharmony_ci total_count = le64_to_cpu(sbi->raw_super->block_count); 14868c2ecf20Sopenharmony_ci user_block_count = sbi->user_block_count; 14878c2ecf20Sopenharmony_ci start_count = le32_to_cpu(sbi->raw_super->segment0_blkaddr); 14888c2ecf20Sopenharmony_ci buf->f_type = F2FS_SUPER_MAGIC; 14898c2ecf20Sopenharmony_ci buf->f_bsize = sbi->blocksize; 14908c2ecf20Sopenharmony_ci 14918c2ecf20Sopenharmony_ci buf->f_blocks = total_count - start_count; 14928c2ecf20Sopenharmony_ci buf->f_bfree = user_block_count - valid_user_blocks(sbi) - 14938c2ecf20Sopenharmony_ci sbi->current_reserved_blocks; 14948c2ecf20Sopenharmony_ci 14958c2ecf20Sopenharmony_ci spin_lock(&sbi->stat_lock); 14968c2ecf20Sopenharmony_ci if (unlikely(buf->f_bfree <= sbi->unusable_block_count)) 14978c2ecf20Sopenharmony_ci buf->f_bfree = 0; 14988c2ecf20Sopenharmony_ci else 14998c2ecf20Sopenharmony_ci buf->f_bfree -= sbi->unusable_block_count; 15008c2ecf20Sopenharmony_ci spin_unlock(&sbi->stat_lock); 15018c2ecf20Sopenharmony_ci 15028c2ecf20Sopenharmony_ci if (buf->f_bfree > F2FS_OPTION(sbi).root_reserved_blocks) 15038c2ecf20Sopenharmony_ci buf->f_bavail = buf->f_bfree - 15048c2ecf20Sopenharmony_ci F2FS_OPTION(sbi).root_reserved_blocks; 15058c2ecf20Sopenharmony_ci else 15068c2ecf20Sopenharmony_ci buf->f_bavail = 0; 15078c2ecf20Sopenharmony_ci 15088c2ecf20Sopenharmony_ci avail_node_count = sbi->total_node_count - F2FS_RESERVED_NODE_NUM; 15098c2ecf20Sopenharmony_ci 15108c2ecf20Sopenharmony_ci if (avail_node_count > user_block_count) { 15118c2ecf20Sopenharmony_ci buf->f_files = user_block_count; 15128c2ecf20Sopenharmony_ci buf->f_ffree = buf->f_bavail; 15138c2ecf20Sopenharmony_ci } else { 15148c2ecf20Sopenharmony_ci buf->f_files = avail_node_count; 15158c2ecf20Sopenharmony_ci buf->f_ffree = min(avail_node_count - valid_node_count(sbi), 15168c2ecf20Sopenharmony_ci buf->f_bavail); 15178c2ecf20Sopenharmony_ci } 15188c2ecf20Sopenharmony_ci 15198c2ecf20Sopenharmony_ci buf->f_namelen = F2FS_NAME_LEN; 15208c2ecf20Sopenharmony_ci buf->f_fsid = u64_to_fsid(id); 15218c2ecf20Sopenharmony_ci 15228c2ecf20Sopenharmony_ci#ifdef CONFIG_QUOTA 15238c2ecf20Sopenharmony_ci if (is_inode_flag_set(dentry->d_inode, FI_PROJ_INHERIT) && 15248c2ecf20Sopenharmony_ci sb_has_quota_limits_enabled(sb, PRJQUOTA)) { 15258c2ecf20Sopenharmony_ci f2fs_statfs_project(sb, F2FS_I(dentry->d_inode)->i_projid, buf); 15268c2ecf20Sopenharmony_ci } 15278c2ecf20Sopenharmony_ci#endif 15288c2ecf20Sopenharmony_ci return 0; 15298c2ecf20Sopenharmony_ci} 15308c2ecf20Sopenharmony_ci 15318c2ecf20Sopenharmony_cistatic inline void f2fs_show_quota_options(struct seq_file *seq, 15328c2ecf20Sopenharmony_ci struct super_block *sb) 15338c2ecf20Sopenharmony_ci{ 15348c2ecf20Sopenharmony_ci#ifdef CONFIG_QUOTA 15358c2ecf20Sopenharmony_ci struct f2fs_sb_info *sbi = F2FS_SB(sb); 15368c2ecf20Sopenharmony_ci 15378c2ecf20Sopenharmony_ci if (F2FS_OPTION(sbi).s_jquota_fmt) { 15388c2ecf20Sopenharmony_ci char *fmtname = ""; 15398c2ecf20Sopenharmony_ci 15408c2ecf20Sopenharmony_ci switch (F2FS_OPTION(sbi).s_jquota_fmt) { 15418c2ecf20Sopenharmony_ci case QFMT_VFS_OLD: 15428c2ecf20Sopenharmony_ci fmtname = "vfsold"; 15438c2ecf20Sopenharmony_ci break; 15448c2ecf20Sopenharmony_ci case QFMT_VFS_V0: 15458c2ecf20Sopenharmony_ci fmtname = "vfsv0"; 15468c2ecf20Sopenharmony_ci break; 15478c2ecf20Sopenharmony_ci case QFMT_VFS_V1: 15488c2ecf20Sopenharmony_ci fmtname = "vfsv1"; 15498c2ecf20Sopenharmony_ci break; 15508c2ecf20Sopenharmony_ci } 15518c2ecf20Sopenharmony_ci seq_printf(seq, ",jqfmt=%s", fmtname); 15528c2ecf20Sopenharmony_ci } 15538c2ecf20Sopenharmony_ci 15548c2ecf20Sopenharmony_ci if (F2FS_OPTION(sbi).s_qf_names[USRQUOTA]) 15558c2ecf20Sopenharmony_ci seq_show_option(seq, "usrjquota", 15568c2ecf20Sopenharmony_ci F2FS_OPTION(sbi).s_qf_names[USRQUOTA]); 15578c2ecf20Sopenharmony_ci 15588c2ecf20Sopenharmony_ci if (F2FS_OPTION(sbi).s_qf_names[GRPQUOTA]) 15598c2ecf20Sopenharmony_ci seq_show_option(seq, "grpjquota", 15608c2ecf20Sopenharmony_ci F2FS_OPTION(sbi).s_qf_names[GRPQUOTA]); 15618c2ecf20Sopenharmony_ci 15628c2ecf20Sopenharmony_ci if (F2FS_OPTION(sbi).s_qf_names[PRJQUOTA]) 15638c2ecf20Sopenharmony_ci seq_show_option(seq, "prjjquota", 15648c2ecf20Sopenharmony_ci F2FS_OPTION(sbi).s_qf_names[PRJQUOTA]); 15658c2ecf20Sopenharmony_ci#endif 15668c2ecf20Sopenharmony_ci} 15678c2ecf20Sopenharmony_ci 15688c2ecf20Sopenharmony_cistatic inline void f2fs_show_compress_options(struct seq_file *seq, 15698c2ecf20Sopenharmony_ci struct super_block *sb) 15708c2ecf20Sopenharmony_ci{ 15718c2ecf20Sopenharmony_ci struct f2fs_sb_info *sbi = F2FS_SB(sb); 15728c2ecf20Sopenharmony_ci char *algtype = ""; 15738c2ecf20Sopenharmony_ci int i; 15748c2ecf20Sopenharmony_ci 15758c2ecf20Sopenharmony_ci if (!f2fs_sb_has_compression(sbi)) 15768c2ecf20Sopenharmony_ci return; 15778c2ecf20Sopenharmony_ci 15788c2ecf20Sopenharmony_ci switch (F2FS_OPTION(sbi).compress_algorithm) { 15798c2ecf20Sopenharmony_ci case COMPRESS_LZO: 15808c2ecf20Sopenharmony_ci algtype = "lzo"; 15818c2ecf20Sopenharmony_ci break; 15828c2ecf20Sopenharmony_ci case COMPRESS_LZ4: 15838c2ecf20Sopenharmony_ci algtype = "lz4"; 15848c2ecf20Sopenharmony_ci break; 15858c2ecf20Sopenharmony_ci case COMPRESS_ZSTD: 15868c2ecf20Sopenharmony_ci algtype = "zstd"; 15878c2ecf20Sopenharmony_ci break; 15888c2ecf20Sopenharmony_ci case COMPRESS_LZORLE: 15898c2ecf20Sopenharmony_ci algtype = "lzo-rle"; 15908c2ecf20Sopenharmony_ci break; 15918c2ecf20Sopenharmony_ci } 15928c2ecf20Sopenharmony_ci seq_printf(seq, ",compress_algorithm=%s", algtype); 15938c2ecf20Sopenharmony_ci 15948c2ecf20Sopenharmony_ci seq_printf(seq, ",compress_log_size=%u", 15958c2ecf20Sopenharmony_ci F2FS_OPTION(sbi).compress_log_size); 15968c2ecf20Sopenharmony_ci 15978c2ecf20Sopenharmony_ci for (i = 0; i < F2FS_OPTION(sbi).compress_ext_cnt; i++) { 15988c2ecf20Sopenharmony_ci seq_printf(seq, ",compress_extension=%s", 15998c2ecf20Sopenharmony_ci F2FS_OPTION(sbi).extensions[i]); 16008c2ecf20Sopenharmony_ci } 16018c2ecf20Sopenharmony_ci} 16028c2ecf20Sopenharmony_ci 16038c2ecf20Sopenharmony_cistatic int f2fs_show_options(struct seq_file *seq, struct dentry *root) 16048c2ecf20Sopenharmony_ci{ 16058c2ecf20Sopenharmony_ci struct f2fs_sb_info *sbi = F2FS_SB(root->d_sb); 16068c2ecf20Sopenharmony_ci 16078c2ecf20Sopenharmony_ci if (F2FS_OPTION(sbi).bggc_mode == BGGC_MODE_SYNC) 16088c2ecf20Sopenharmony_ci seq_printf(seq, ",background_gc=%s", "sync"); 16098c2ecf20Sopenharmony_ci else if (F2FS_OPTION(sbi).bggc_mode == BGGC_MODE_ON) 16108c2ecf20Sopenharmony_ci seq_printf(seq, ",background_gc=%s", "on"); 16118c2ecf20Sopenharmony_ci else if (F2FS_OPTION(sbi).bggc_mode == BGGC_MODE_OFF) 16128c2ecf20Sopenharmony_ci seq_printf(seq, ",background_gc=%s", "off"); 16138c2ecf20Sopenharmony_ci 16148c2ecf20Sopenharmony_ci if (test_opt(sbi, GC_MERGE)) 16158c2ecf20Sopenharmony_ci seq_puts(seq, ",gc_merge"); 16168c2ecf20Sopenharmony_ci 16178c2ecf20Sopenharmony_ci if (test_opt(sbi, DISABLE_ROLL_FORWARD)) 16188c2ecf20Sopenharmony_ci seq_puts(seq, ",disable_roll_forward"); 16198c2ecf20Sopenharmony_ci if (test_opt(sbi, NORECOVERY)) 16208c2ecf20Sopenharmony_ci seq_puts(seq, ",norecovery"); 16218c2ecf20Sopenharmony_ci if (test_opt(sbi, DISCARD)) 16228c2ecf20Sopenharmony_ci seq_puts(seq, ",discard"); 16238c2ecf20Sopenharmony_ci else 16248c2ecf20Sopenharmony_ci seq_puts(seq, ",nodiscard"); 16258c2ecf20Sopenharmony_ci if (test_opt(sbi, NOHEAP)) 16268c2ecf20Sopenharmony_ci seq_puts(seq, ",no_heap"); 16278c2ecf20Sopenharmony_ci else 16288c2ecf20Sopenharmony_ci seq_puts(seq, ",heap"); 16298c2ecf20Sopenharmony_ci#ifdef CONFIG_F2FS_FS_XATTR 16308c2ecf20Sopenharmony_ci if (test_opt(sbi, XATTR_USER)) 16318c2ecf20Sopenharmony_ci seq_puts(seq, ",user_xattr"); 16328c2ecf20Sopenharmony_ci else 16338c2ecf20Sopenharmony_ci seq_puts(seq, ",nouser_xattr"); 16348c2ecf20Sopenharmony_ci if (test_opt(sbi, INLINE_XATTR)) 16358c2ecf20Sopenharmony_ci seq_puts(seq, ",inline_xattr"); 16368c2ecf20Sopenharmony_ci else 16378c2ecf20Sopenharmony_ci seq_puts(seq, ",noinline_xattr"); 16388c2ecf20Sopenharmony_ci if (test_opt(sbi, INLINE_XATTR_SIZE)) 16398c2ecf20Sopenharmony_ci seq_printf(seq, ",inline_xattr_size=%u", 16408c2ecf20Sopenharmony_ci F2FS_OPTION(sbi).inline_xattr_size); 16418c2ecf20Sopenharmony_ci#endif 16428c2ecf20Sopenharmony_ci#ifdef CONFIG_F2FS_FS_POSIX_ACL 16438c2ecf20Sopenharmony_ci if (test_opt(sbi, POSIX_ACL)) 16448c2ecf20Sopenharmony_ci seq_puts(seq, ",acl"); 16458c2ecf20Sopenharmony_ci else 16468c2ecf20Sopenharmony_ci seq_puts(seq, ",noacl"); 16478c2ecf20Sopenharmony_ci#endif 16488c2ecf20Sopenharmony_ci if (test_opt(sbi, DISABLE_EXT_IDENTIFY)) 16498c2ecf20Sopenharmony_ci seq_puts(seq, ",disable_ext_identify"); 16508c2ecf20Sopenharmony_ci if (test_opt(sbi, INLINE_DATA)) 16518c2ecf20Sopenharmony_ci seq_puts(seq, ",inline_data"); 16528c2ecf20Sopenharmony_ci else 16538c2ecf20Sopenharmony_ci seq_puts(seq, ",noinline_data"); 16548c2ecf20Sopenharmony_ci if (test_opt(sbi, INLINE_DENTRY)) 16558c2ecf20Sopenharmony_ci seq_puts(seq, ",inline_dentry"); 16568c2ecf20Sopenharmony_ci else 16578c2ecf20Sopenharmony_ci seq_puts(seq, ",noinline_dentry"); 16588c2ecf20Sopenharmony_ci if (!f2fs_readonly(sbi->sb) && test_opt(sbi, FLUSH_MERGE)) 16598c2ecf20Sopenharmony_ci seq_puts(seq, ",flush_merge"); 16608c2ecf20Sopenharmony_ci if (test_opt(sbi, NOBARRIER)) 16618c2ecf20Sopenharmony_ci seq_puts(seq, ",nobarrier"); 16628c2ecf20Sopenharmony_ci if (test_opt(sbi, FASTBOOT)) 16638c2ecf20Sopenharmony_ci seq_puts(seq, ",fastboot"); 16648c2ecf20Sopenharmony_ci if (test_opt(sbi, EXTENT_CACHE)) 16658c2ecf20Sopenharmony_ci seq_puts(seq, ",extent_cache"); 16668c2ecf20Sopenharmony_ci else 16678c2ecf20Sopenharmony_ci seq_puts(seq, ",noextent_cache"); 16688c2ecf20Sopenharmony_ci if (test_opt(sbi, DATA_FLUSH)) 16698c2ecf20Sopenharmony_ci seq_puts(seq, ",data_flush"); 16708c2ecf20Sopenharmony_ci 16718c2ecf20Sopenharmony_ci seq_puts(seq, ",mode="); 16728c2ecf20Sopenharmony_ci if (F2FS_OPTION(sbi).fs_mode == FS_MODE_ADAPTIVE) 16738c2ecf20Sopenharmony_ci seq_puts(seq, "adaptive"); 16748c2ecf20Sopenharmony_ci else if (F2FS_OPTION(sbi).fs_mode == FS_MODE_LFS) 16758c2ecf20Sopenharmony_ci seq_puts(seq, "lfs"); 16768c2ecf20Sopenharmony_ci seq_printf(seq, ",active_logs=%u", F2FS_OPTION(sbi).active_logs); 16778c2ecf20Sopenharmony_ci if (test_opt(sbi, RESERVE_ROOT)) 16788c2ecf20Sopenharmony_ci seq_printf(seq, ",reserve_root=%u,resuid=%u,resgid=%u", 16798c2ecf20Sopenharmony_ci F2FS_OPTION(sbi).root_reserved_blocks, 16808c2ecf20Sopenharmony_ci from_kuid_munged(&init_user_ns, 16818c2ecf20Sopenharmony_ci F2FS_OPTION(sbi).s_resuid), 16828c2ecf20Sopenharmony_ci from_kgid_munged(&init_user_ns, 16838c2ecf20Sopenharmony_ci F2FS_OPTION(sbi).s_resgid)); 16848c2ecf20Sopenharmony_ci if (F2FS_IO_SIZE_BITS(sbi)) 16858c2ecf20Sopenharmony_ci seq_printf(seq, ",io_bits=%u", 16868c2ecf20Sopenharmony_ci F2FS_OPTION(sbi).write_io_size_bits); 16878c2ecf20Sopenharmony_ci#ifdef CONFIG_F2FS_FAULT_INJECTION 16888c2ecf20Sopenharmony_ci if (test_opt(sbi, FAULT_INJECTION)) { 16898c2ecf20Sopenharmony_ci seq_printf(seq, ",fault_injection=%u", 16908c2ecf20Sopenharmony_ci F2FS_OPTION(sbi).fault_info.inject_rate); 16918c2ecf20Sopenharmony_ci seq_printf(seq, ",fault_type=%u", 16928c2ecf20Sopenharmony_ci F2FS_OPTION(sbi).fault_info.inject_type); 16938c2ecf20Sopenharmony_ci } 16948c2ecf20Sopenharmony_ci#endif 16958c2ecf20Sopenharmony_ci#ifdef CONFIG_QUOTA 16968c2ecf20Sopenharmony_ci if (test_opt(sbi, QUOTA)) 16978c2ecf20Sopenharmony_ci seq_puts(seq, ",quota"); 16988c2ecf20Sopenharmony_ci if (test_opt(sbi, USRQUOTA)) 16998c2ecf20Sopenharmony_ci seq_puts(seq, ",usrquota"); 17008c2ecf20Sopenharmony_ci if (test_opt(sbi, GRPQUOTA)) 17018c2ecf20Sopenharmony_ci seq_puts(seq, ",grpquota"); 17028c2ecf20Sopenharmony_ci if (test_opt(sbi, PRJQUOTA)) 17038c2ecf20Sopenharmony_ci seq_puts(seq, ",prjquota"); 17048c2ecf20Sopenharmony_ci#endif 17058c2ecf20Sopenharmony_ci f2fs_show_quota_options(seq, sbi->sb); 17068c2ecf20Sopenharmony_ci if (F2FS_OPTION(sbi).whint_mode == WHINT_MODE_USER) 17078c2ecf20Sopenharmony_ci seq_printf(seq, ",whint_mode=%s", "user-based"); 17088c2ecf20Sopenharmony_ci else if (F2FS_OPTION(sbi).whint_mode == WHINT_MODE_FS) 17098c2ecf20Sopenharmony_ci seq_printf(seq, ",whint_mode=%s", "fs-based"); 17108c2ecf20Sopenharmony_ci 17118c2ecf20Sopenharmony_ci fscrypt_show_test_dummy_encryption(seq, ',', sbi->sb); 17128c2ecf20Sopenharmony_ci 17138c2ecf20Sopenharmony_ci if (sbi->sb->s_flags & SB_INLINECRYPT) 17148c2ecf20Sopenharmony_ci seq_puts(seq, ",inlinecrypt"); 17158c2ecf20Sopenharmony_ci 17168c2ecf20Sopenharmony_ci if (F2FS_OPTION(sbi).alloc_mode == ALLOC_MODE_DEFAULT) 17178c2ecf20Sopenharmony_ci seq_printf(seq, ",alloc_mode=%s", "default"); 17188c2ecf20Sopenharmony_ci else if (F2FS_OPTION(sbi).alloc_mode == ALLOC_MODE_REUSE) 17198c2ecf20Sopenharmony_ci seq_printf(seq, ",alloc_mode=%s", "reuse"); 17208c2ecf20Sopenharmony_ci 17218c2ecf20Sopenharmony_ci if (test_opt(sbi, DISABLE_CHECKPOINT)) 17228c2ecf20Sopenharmony_ci seq_printf(seq, ",checkpoint=disable:%u", 17238c2ecf20Sopenharmony_ci F2FS_OPTION(sbi).unusable_cap); 17248c2ecf20Sopenharmony_ci if (F2FS_OPTION(sbi).fsync_mode == FSYNC_MODE_POSIX) 17258c2ecf20Sopenharmony_ci seq_printf(seq, ",fsync_mode=%s", "posix"); 17268c2ecf20Sopenharmony_ci else if (F2FS_OPTION(sbi).fsync_mode == FSYNC_MODE_STRICT) 17278c2ecf20Sopenharmony_ci seq_printf(seq, ",fsync_mode=%s", "strict"); 17288c2ecf20Sopenharmony_ci else if (F2FS_OPTION(sbi).fsync_mode == FSYNC_MODE_NOBARRIER) 17298c2ecf20Sopenharmony_ci seq_printf(seq, ",fsync_mode=%s", "nobarrier"); 17308c2ecf20Sopenharmony_ci 17318c2ecf20Sopenharmony_ci#ifdef CONFIG_F2FS_FS_COMPRESSION 17328c2ecf20Sopenharmony_ci f2fs_show_compress_options(seq, sbi->sb); 17338c2ecf20Sopenharmony_ci#endif 17348c2ecf20Sopenharmony_ci 17358c2ecf20Sopenharmony_ci if (test_opt(sbi, ATGC)) 17368c2ecf20Sopenharmony_ci seq_puts(seq, ",atgc"); 17378c2ecf20Sopenharmony_ci return 0; 17388c2ecf20Sopenharmony_ci} 17398c2ecf20Sopenharmony_ci 17408c2ecf20Sopenharmony_cistatic void default_options(struct f2fs_sb_info *sbi) 17418c2ecf20Sopenharmony_ci{ 17428c2ecf20Sopenharmony_ci /* init some FS parameters */ 17438c2ecf20Sopenharmony_ci F2FS_OPTION(sbi).active_logs = NR_CURSEG_PERSIST_TYPE; 17448c2ecf20Sopenharmony_ci F2FS_OPTION(sbi).inline_xattr_size = DEFAULT_INLINE_XATTR_ADDRS; 17458c2ecf20Sopenharmony_ci F2FS_OPTION(sbi).whint_mode = WHINT_MODE_OFF; 17468c2ecf20Sopenharmony_ci F2FS_OPTION(sbi).alloc_mode = ALLOC_MODE_DEFAULT; 17478c2ecf20Sopenharmony_ci F2FS_OPTION(sbi).fsync_mode = FSYNC_MODE_POSIX; 17488c2ecf20Sopenharmony_ci F2FS_OPTION(sbi).s_resuid = make_kuid(&init_user_ns, F2FS_DEF_RESUID); 17498c2ecf20Sopenharmony_ci F2FS_OPTION(sbi).s_resgid = make_kgid(&init_user_ns, F2FS_DEF_RESGID); 17508c2ecf20Sopenharmony_ci F2FS_OPTION(sbi).compress_algorithm = COMPRESS_LZ4; 17518c2ecf20Sopenharmony_ci F2FS_OPTION(sbi).compress_log_size = MIN_COMPRESS_LOG_SIZE; 17528c2ecf20Sopenharmony_ci F2FS_OPTION(sbi).compress_ext_cnt = 0; 17538c2ecf20Sopenharmony_ci F2FS_OPTION(sbi).bggc_mode = BGGC_MODE_ON; 17548c2ecf20Sopenharmony_ci 17558c2ecf20Sopenharmony_ci set_opt(sbi, INLINE_XATTR); 17568c2ecf20Sopenharmony_ci set_opt(sbi, INLINE_DATA); 17578c2ecf20Sopenharmony_ci set_opt(sbi, INLINE_DENTRY); 17588c2ecf20Sopenharmony_ci set_opt(sbi, EXTENT_CACHE); 17598c2ecf20Sopenharmony_ci set_opt(sbi, NOHEAP); 17608c2ecf20Sopenharmony_ci clear_opt(sbi, DISABLE_CHECKPOINT); 17618c2ecf20Sopenharmony_ci F2FS_OPTION(sbi).unusable_cap = 0; 17628c2ecf20Sopenharmony_ci sbi->sb->s_flags |= SB_LAZYTIME; 17638c2ecf20Sopenharmony_ci set_opt(sbi, FLUSH_MERGE); 17648c2ecf20Sopenharmony_ci set_opt(sbi, DISCARD); 17658c2ecf20Sopenharmony_ci if (f2fs_sb_has_blkzoned(sbi)) 17668c2ecf20Sopenharmony_ci F2FS_OPTION(sbi).fs_mode = FS_MODE_LFS; 17678c2ecf20Sopenharmony_ci else 17688c2ecf20Sopenharmony_ci F2FS_OPTION(sbi).fs_mode = FS_MODE_ADAPTIVE; 17698c2ecf20Sopenharmony_ci 17708c2ecf20Sopenharmony_ci#ifdef CONFIG_F2FS_FS_XATTR 17718c2ecf20Sopenharmony_ci set_opt(sbi, XATTR_USER); 17728c2ecf20Sopenharmony_ci#endif 17738c2ecf20Sopenharmony_ci#ifdef CONFIG_F2FS_FS_POSIX_ACL 17748c2ecf20Sopenharmony_ci set_opt(sbi, POSIX_ACL); 17758c2ecf20Sopenharmony_ci#endif 17768c2ecf20Sopenharmony_ci 17778c2ecf20Sopenharmony_ci f2fs_build_fault_attr(sbi, 0, 0); 17788c2ecf20Sopenharmony_ci} 17798c2ecf20Sopenharmony_ci 17808c2ecf20Sopenharmony_ci#ifdef CONFIG_QUOTA 17818c2ecf20Sopenharmony_cistatic int f2fs_enable_quotas(struct super_block *sb); 17828c2ecf20Sopenharmony_ci#endif 17838c2ecf20Sopenharmony_ci 17848c2ecf20Sopenharmony_cistatic int f2fs_disable_checkpoint(struct f2fs_sb_info *sbi) 17858c2ecf20Sopenharmony_ci{ 17868c2ecf20Sopenharmony_ci unsigned int s_flags = sbi->sb->s_flags; 17878c2ecf20Sopenharmony_ci struct cp_control cpc; 17888c2ecf20Sopenharmony_ci int err = 0; 17898c2ecf20Sopenharmony_ci int ret; 17908c2ecf20Sopenharmony_ci block_t unusable; 17918c2ecf20Sopenharmony_ci 17928c2ecf20Sopenharmony_ci if (s_flags & SB_RDONLY) { 17938c2ecf20Sopenharmony_ci f2fs_err(sbi, "checkpoint=disable on readonly fs"); 17948c2ecf20Sopenharmony_ci return -EINVAL; 17958c2ecf20Sopenharmony_ci } 17968c2ecf20Sopenharmony_ci sbi->sb->s_flags |= SB_ACTIVE; 17978c2ecf20Sopenharmony_ci 17988c2ecf20Sopenharmony_ci f2fs_update_time(sbi, DISABLE_TIME); 17998c2ecf20Sopenharmony_ci 18008c2ecf20Sopenharmony_ci while (!f2fs_time_over(sbi, DISABLE_TIME)) { 18018c2ecf20Sopenharmony_ci down_write(&sbi->gc_lock); 18028c2ecf20Sopenharmony_ci err = f2fs_gc(sbi, true, false, false, NULL_SEGNO); 18038c2ecf20Sopenharmony_ci if (err == -ENODATA) { 18048c2ecf20Sopenharmony_ci err = 0; 18058c2ecf20Sopenharmony_ci break; 18068c2ecf20Sopenharmony_ci } 18078c2ecf20Sopenharmony_ci if (err && err != -EAGAIN) 18088c2ecf20Sopenharmony_ci break; 18098c2ecf20Sopenharmony_ci } 18108c2ecf20Sopenharmony_ci 18118c2ecf20Sopenharmony_ci ret = sync_filesystem(sbi->sb); 18128c2ecf20Sopenharmony_ci if (ret || err) { 18138c2ecf20Sopenharmony_ci err = ret ? ret: err; 18148c2ecf20Sopenharmony_ci goto restore_flag; 18158c2ecf20Sopenharmony_ci } 18168c2ecf20Sopenharmony_ci 18178c2ecf20Sopenharmony_ci unusable = f2fs_get_unusable_blocks(sbi); 18188c2ecf20Sopenharmony_ci if (f2fs_disable_cp_again(sbi, unusable)) { 18198c2ecf20Sopenharmony_ci err = -EAGAIN; 18208c2ecf20Sopenharmony_ci goto restore_flag; 18218c2ecf20Sopenharmony_ci } 18228c2ecf20Sopenharmony_ci 18238c2ecf20Sopenharmony_ci down_write(&sbi->gc_lock); 18248c2ecf20Sopenharmony_ci cpc.reason = CP_PAUSE; 18258c2ecf20Sopenharmony_ci set_sbi_flag(sbi, SBI_CP_DISABLED); 18268c2ecf20Sopenharmony_ci err = f2fs_write_checkpoint(sbi, &cpc); 18278c2ecf20Sopenharmony_ci if (err) 18288c2ecf20Sopenharmony_ci goto out_unlock; 18298c2ecf20Sopenharmony_ci 18308c2ecf20Sopenharmony_ci spin_lock(&sbi->stat_lock); 18318c2ecf20Sopenharmony_ci sbi->unusable_block_count = unusable; 18328c2ecf20Sopenharmony_ci spin_unlock(&sbi->stat_lock); 18338c2ecf20Sopenharmony_ci 18348c2ecf20Sopenharmony_ciout_unlock: 18358c2ecf20Sopenharmony_ci up_write(&sbi->gc_lock); 18368c2ecf20Sopenharmony_cirestore_flag: 18378c2ecf20Sopenharmony_ci sbi->sb->s_flags = s_flags; /* Restore SB_RDONLY status */ 18388c2ecf20Sopenharmony_ci return err; 18398c2ecf20Sopenharmony_ci} 18408c2ecf20Sopenharmony_ci 18418c2ecf20Sopenharmony_cistatic void f2fs_enable_checkpoint(struct f2fs_sb_info *sbi) 18428c2ecf20Sopenharmony_ci{ 18438c2ecf20Sopenharmony_ci int retry = DEFAULT_RETRY_IO_COUNT; 18448c2ecf20Sopenharmony_ci 18458c2ecf20Sopenharmony_ci /* we should flush all the data to keep data consistency */ 18468c2ecf20Sopenharmony_ci do { 18478c2ecf20Sopenharmony_ci sync_inodes_sb(sbi->sb); 18488c2ecf20Sopenharmony_ci cond_resched(); 18498c2ecf20Sopenharmony_ci congestion_wait(BLK_RW_ASYNC, DEFAULT_IO_TIMEOUT); 18508c2ecf20Sopenharmony_ci } while (get_pages(sbi, F2FS_DIRTY_DATA) && retry--); 18518c2ecf20Sopenharmony_ci 18528c2ecf20Sopenharmony_ci if (unlikely(retry < 0)) 18538c2ecf20Sopenharmony_ci f2fs_warn(sbi, "checkpoint=enable has some unwritten data."); 18548c2ecf20Sopenharmony_ci 18558c2ecf20Sopenharmony_ci down_write(&sbi->gc_lock); 18568c2ecf20Sopenharmony_ci f2fs_dirty_to_prefree(sbi); 18578c2ecf20Sopenharmony_ci 18588c2ecf20Sopenharmony_ci clear_sbi_flag(sbi, SBI_CP_DISABLED); 18598c2ecf20Sopenharmony_ci set_sbi_flag(sbi, SBI_IS_DIRTY); 18608c2ecf20Sopenharmony_ci up_write(&sbi->gc_lock); 18618c2ecf20Sopenharmony_ci 18628c2ecf20Sopenharmony_ci f2fs_sync_fs(sbi->sb, 1); 18638c2ecf20Sopenharmony_ci} 18648c2ecf20Sopenharmony_ci 18658c2ecf20Sopenharmony_cistatic int f2fs_remount(struct super_block *sb, int *flags, char *data) 18668c2ecf20Sopenharmony_ci{ 18678c2ecf20Sopenharmony_ci struct f2fs_sb_info *sbi = F2FS_SB(sb); 18688c2ecf20Sopenharmony_ci struct f2fs_mount_info org_mount_opt; 18698c2ecf20Sopenharmony_ci unsigned long old_sb_flags; 18708c2ecf20Sopenharmony_ci int err; 18718c2ecf20Sopenharmony_ci bool need_restart_gc = false; 18728c2ecf20Sopenharmony_ci bool need_stop_gc = false; 18738c2ecf20Sopenharmony_ci bool no_extent_cache = !test_opt(sbi, EXTENT_CACHE); 18748c2ecf20Sopenharmony_ci bool disable_checkpoint = test_opt(sbi, DISABLE_CHECKPOINT); 18758c2ecf20Sopenharmony_ci bool no_io_align = !F2FS_IO_ALIGNED(sbi); 18768c2ecf20Sopenharmony_ci bool no_atgc = !test_opt(sbi, ATGC); 18778c2ecf20Sopenharmony_ci bool checkpoint_changed; 18788c2ecf20Sopenharmony_ci#ifdef CONFIG_QUOTA 18798c2ecf20Sopenharmony_ci int i, j; 18808c2ecf20Sopenharmony_ci#endif 18818c2ecf20Sopenharmony_ci 18828c2ecf20Sopenharmony_ci /* 18838c2ecf20Sopenharmony_ci * Save the old mount options in case we 18848c2ecf20Sopenharmony_ci * need to restore them. 18858c2ecf20Sopenharmony_ci */ 18868c2ecf20Sopenharmony_ci org_mount_opt = sbi->mount_opt; 18878c2ecf20Sopenharmony_ci old_sb_flags = sb->s_flags; 18888c2ecf20Sopenharmony_ci 18898c2ecf20Sopenharmony_ci#ifdef CONFIG_QUOTA 18908c2ecf20Sopenharmony_ci org_mount_opt.s_jquota_fmt = F2FS_OPTION(sbi).s_jquota_fmt; 18918c2ecf20Sopenharmony_ci for (i = 0; i < MAXQUOTAS; i++) { 18928c2ecf20Sopenharmony_ci if (F2FS_OPTION(sbi).s_qf_names[i]) { 18938c2ecf20Sopenharmony_ci org_mount_opt.s_qf_names[i] = 18948c2ecf20Sopenharmony_ci kstrdup(F2FS_OPTION(sbi).s_qf_names[i], 18958c2ecf20Sopenharmony_ci GFP_KERNEL); 18968c2ecf20Sopenharmony_ci if (!org_mount_opt.s_qf_names[i]) { 18978c2ecf20Sopenharmony_ci for (j = 0; j < i; j++) 18988c2ecf20Sopenharmony_ci kfree(org_mount_opt.s_qf_names[j]); 18998c2ecf20Sopenharmony_ci return -ENOMEM; 19008c2ecf20Sopenharmony_ci } 19018c2ecf20Sopenharmony_ci } else { 19028c2ecf20Sopenharmony_ci org_mount_opt.s_qf_names[i] = NULL; 19038c2ecf20Sopenharmony_ci } 19048c2ecf20Sopenharmony_ci } 19058c2ecf20Sopenharmony_ci#endif 19068c2ecf20Sopenharmony_ci 19078c2ecf20Sopenharmony_ci /* recover superblocks we couldn't write due to previous RO mount */ 19088c2ecf20Sopenharmony_ci if (!(*flags & SB_RDONLY) && is_sbi_flag_set(sbi, SBI_NEED_SB_WRITE)) { 19098c2ecf20Sopenharmony_ci err = f2fs_commit_super(sbi, false); 19108c2ecf20Sopenharmony_ci f2fs_info(sbi, "Try to recover all the superblocks, ret: %d", 19118c2ecf20Sopenharmony_ci err); 19128c2ecf20Sopenharmony_ci if (!err) 19138c2ecf20Sopenharmony_ci clear_sbi_flag(sbi, SBI_NEED_SB_WRITE); 19148c2ecf20Sopenharmony_ci } 19158c2ecf20Sopenharmony_ci 19168c2ecf20Sopenharmony_ci default_options(sbi); 19178c2ecf20Sopenharmony_ci 19188c2ecf20Sopenharmony_ci /* parse mount options */ 19198c2ecf20Sopenharmony_ci err = parse_options(sb, data, true); 19208c2ecf20Sopenharmony_ci if (err) 19218c2ecf20Sopenharmony_ci goto restore_opts; 19228c2ecf20Sopenharmony_ci checkpoint_changed = 19238c2ecf20Sopenharmony_ci disable_checkpoint != test_opt(sbi, DISABLE_CHECKPOINT); 19248c2ecf20Sopenharmony_ci 19258c2ecf20Sopenharmony_ci /* 19268c2ecf20Sopenharmony_ci * Previous and new state of filesystem is RO, 19278c2ecf20Sopenharmony_ci * so skip checking GC and FLUSH_MERGE conditions. 19288c2ecf20Sopenharmony_ci */ 19298c2ecf20Sopenharmony_ci if (f2fs_readonly(sb) && (*flags & SB_RDONLY)) 19308c2ecf20Sopenharmony_ci goto skip; 19318c2ecf20Sopenharmony_ci 19328c2ecf20Sopenharmony_ci#ifdef CONFIG_QUOTA 19338c2ecf20Sopenharmony_ci if (!f2fs_readonly(sb) && (*flags & SB_RDONLY)) { 19348c2ecf20Sopenharmony_ci err = dquot_suspend(sb, -1); 19358c2ecf20Sopenharmony_ci if (err < 0) 19368c2ecf20Sopenharmony_ci goto restore_opts; 19378c2ecf20Sopenharmony_ci } else if (f2fs_readonly(sb) && !(*flags & SB_RDONLY)) { 19388c2ecf20Sopenharmony_ci /* dquot_resume needs RW */ 19398c2ecf20Sopenharmony_ci sb->s_flags &= ~SB_RDONLY; 19408c2ecf20Sopenharmony_ci if (sb_any_quota_suspended(sb)) { 19418c2ecf20Sopenharmony_ci dquot_resume(sb, -1); 19428c2ecf20Sopenharmony_ci } else if (f2fs_sb_has_quota_ino(sbi)) { 19438c2ecf20Sopenharmony_ci err = f2fs_enable_quotas(sb); 19448c2ecf20Sopenharmony_ci if (err) 19458c2ecf20Sopenharmony_ci goto restore_opts; 19468c2ecf20Sopenharmony_ci } 19478c2ecf20Sopenharmony_ci } 19488c2ecf20Sopenharmony_ci#endif 19498c2ecf20Sopenharmony_ci /* disallow enable atgc dynamically */ 19508c2ecf20Sopenharmony_ci if (no_atgc == !!test_opt(sbi, ATGC)) { 19518c2ecf20Sopenharmony_ci err = -EINVAL; 19528c2ecf20Sopenharmony_ci f2fs_warn(sbi, "switch atgc option is not allowed"); 19538c2ecf20Sopenharmony_ci goto restore_opts; 19548c2ecf20Sopenharmony_ci } 19558c2ecf20Sopenharmony_ci 19568c2ecf20Sopenharmony_ci /* disallow enable/disable extent_cache dynamically */ 19578c2ecf20Sopenharmony_ci if (no_extent_cache == !!test_opt(sbi, EXTENT_CACHE)) { 19588c2ecf20Sopenharmony_ci err = -EINVAL; 19598c2ecf20Sopenharmony_ci f2fs_warn(sbi, "switch extent_cache option is not allowed"); 19608c2ecf20Sopenharmony_ci goto restore_opts; 19618c2ecf20Sopenharmony_ci } 19628c2ecf20Sopenharmony_ci 19638c2ecf20Sopenharmony_ci if (no_io_align == !!F2FS_IO_ALIGNED(sbi)) { 19648c2ecf20Sopenharmony_ci err = -EINVAL; 19658c2ecf20Sopenharmony_ci f2fs_warn(sbi, "switch io_bits option is not allowed"); 19668c2ecf20Sopenharmony_ci goto restore_opts; 19678c2ecf20Sopenharmony_ci } 19688c2ecf20Sopenharmony_ci 19698c2ecf20Sopenharmony_ci if ((*flags & SB_RDONLY) && test_opt(sbi, DISABLE_CHECKPOINT)) { 19708c2ecf20Sopenharmony_ci err = -EINVAL; 19718c2ecf20Sopenharmony_ci f2fs_warn(sbi, "disabling checkpoint not compatible with read-only"); 19728c2ecf20Sopenharmony_ci goto restore_opts; 19738c2ecf20Sopenharmony_ci } 19748c2ecf20Sopenharmony_ci 19758c2ecf20Sopenharmony_ci /* 19768c2ecf20Sopenharmony_ci * We stop the GC thread if FS is mounted as RO 19778c2ecf20Sopenharmony_ci * or if background_gc = off is passed in mount 19788c2ecf20Sopenharmony_ci * option. Also sync the filesystem. 19798c2ecf20Sopenharmony_ci */ 19808c2ecf20Sopenharmony_ci if ((*flags & SB_RDONLY) || 19818c2ecf20Sopenharmony_ci (F2FS_OPTION(sbi).bggc_mode == BGGC_MODE_OFF && 19828c2ecf20Sopenharmony_ci !test_opt(sbi, GC_MERGE))) { 19838c2ecf20Sopenharmony_ci if (sbi->gc_thread) { 19848c2ecf20Sopenharmony_ci f2fs_stop_gc_thread(sbi); 19858c2ecf20Sopenharmony_ci need_restart_gc = true; 19868c2ecf20Sopenharmony_ci } 19878c2ecf20Sopenharmony_ci } else if (!sbi->gc_thread) { 19888c2ecf20Sopenharmony_ci err = f2fs_start_gc_thread(sbi); 19898c2ecf20Sopenharmony_ci if (err) 19908c2ecf20Sopenharmony_ci goto restore_opts; 19918c2ecf20Sopenharmony_ci need_stop_gc = true; 19928c2ecf20Sopenharmony_ci } 19938c2ecf20Sopenharmony_ci 19948c2ecf20Sopenharmony_ci if (*flags & SB_RDONLY || 19958c2ecf20Sopenharmony_ci F2FS_OPTION(sbi).whint_mode != org_mount_opt.whint_mode) { 19968c2ecf20Sopenharmony_ci writeback_inodes_sb(sb, WB_REASON_SYNC); 19978c2ecf20Sopenharmony_ci sync_inodes_sb(sb); 19988c2ecf20Sopenharmony_ci 19998c2ecf20Sopenharmony_ci set_sbi_flag(sbi, SBI_IS_DIRTY); 20008c2ecf20Sopenharmony_ci set_sbi_flag(sbi, SBI_IS_CLOSE); 20018c2ecf20Sopenharmony_ci f2fs_sync_fs(sb, 1); 20028c2ecf20Sopenharmony_ci clear_sbi_flag(sbi, SBI_IS_CLOSE); 20038c2ecf20Sopenharmony_ci } 20048c2ecf20Sopenharmony_ci 20058c2ecf20Sopenharmony_ci if (checkpoint_changed) { 20068c2ecf20Sopenharmony_ci if (test_opt(sbi, DISABLE_CHECKPOINT)) { 20078c2ecf20Sopenharmony_ci err = f2fs_disable_checkpoint(sbi); 20088c2ecf20Sopenharmony_ci if (err) 20098c2ecf20Sopenharmony_ci goto restore_gc; 20108c2ecf20Sopenharmony_ci } else { 20118c2ecf20Sopenharmony_ci f2fs_enable_checkpoint(sbi); 20128c2ecf20Sopenharmony_ci } 20138c2ecf20Sopenharmony_ci } 20148c2ecf20Sopenharmony_ci 20158c2ecf20Sopenharmony_ci /* 20168c2ecf20Sopenharmony_ci * We stop issue flush thread if FS is mounted as RO 20178c2ecf20Sopenharmony_ci * or if flush_merge is not passed in mount option. 20188c2ecf20Sopenharmony_ci */ 20198c2ecf20Sopenharmony_ci if ((*flags & SB_RDONLY) || !test_opt(sbi, FLUSH_MERGE)) { 20208c2ecf20Sopenharmony_ci clear_opt(sbi, FLUSH_MERGE); 20218c2ecf20Sopenharmony_ci f2fs_destroy_flush_cmd_control(sbi, false); 20228c2ecf20Sopenharmony_ci } else { 20238c2ecf20Sopenharmony_ci err = f2fs_create_flush_cmd_control(sbi); 20248c2ecf20Sopenharmony_ci if (err) 20258c2ecf20Sopenharmony_ci goto restore_gc; 20268c2ecf20Sopenharmony_ci } 20278c2ecf20Sopenharmony_ciskip: 20288c2ecf20Sopenharmony_ci#ifdef CONFIG_QUOTA 20298c2ecf20Sopenharmony_ci /* Release old quota file names */ 20308c2ecf20Sopenharmony_ci for (i = 0; i < MAXQUOTAS; i++) 20318c2ecf20Sopenharmony_ci kfree(org_mount_opt.s_qf_names[i]); 20328c2ecf20Sopenharmony_ci#endif 20338c2ecf20Sopenharmony_ci /* Update the POSIXACL Flag */ 20348c2ecf20Sopenharmony_ci sb->s_flags = (sb->s_flags & ~SB_POSIXACL) | 20358c2ecf20Sopenharmony_ci (test_opt(sbi, POSIX_ACL) ? SB_POSIXACL : 0); 20368c2ecf20Sopenharmony_ci 20378c2ecf20Sopenharmony_ci limit_reserve_root(sbi); 20388c2ecf20Sopenharmony_ci adjust_unusable_cap_perc(sbi); 20398c2ecf20Sopenharmony_ci *flags = (*flags & ~SB_LAZYTIME) | (sb->s_flags & SB_LAZYTIME); 20408c2ecf20Sopenharmony_ci return 0; 20418c2ecf20Sopenharmony_cirestore_gc: 20428c2ecf20Sopenharmony_ci if (need_restart_gc) { 20438c2ecf20Sopenharmony_ci if (f2fs_start_gc_thread(sbi)) 20448c2ecf20Sopenharmony_ci f2fs_warn(sbi, "background gc thread has stopped"); 20458c2ecf20Sopenharmony_ci } else if (need_stop_gc) { 20468c2ecf20Sopenharmony_ci f2fs_stop_gc_thread(sbi); 20478c2ecf20Sopenharmony_ci } 20488c2ecf20Sopenharmony_cirestore_opts: 20498c2ecf20Sopenharmony_ci#ifdef CONFIG_QUOTA 20508c2ecf20Sopenharmony_ci F2FS_OPTION(sbi).s_jquota_fmt = org_mount_opt.s_jquota_fmt; 20518c2ecf20Sopenharmony_ci for (i = 0; i < MAXQUOTAS; i++) { 20528c2ecf20Sopenharmony_ci kfree(F2FS_OPTION(sbi).s_qf_names[i]); 20538c2ecf20Sopenharmony_ci F2FS_OPTION(sbi).s_qf_names[i] = org_mount_opt.s_qf_names[i]; 20548c2ecf20Sopenharmony_ci } 20558c2ecf20Sopenharmony_ci#endif 20568c2ecf20Sopenharmony_ci sbi->mount_opt = org_mount_opt; 20578c2ecf20Sopenharmony_ci sb->s_flags = old_sb_flags; 20588c2ecf20Sopenharmony_ci return err; 20598c2ecf20Sopenharmony_ci} 20608c2ecf20Sopenharmony_ci 20618c2ecf20Sopenharmony_ci#ifdef CONFIG_QUOTA 20628c2ecf20Sopenharmony_ci/* Read data from quotafile */ 20638c2ecf20Sopenharmony_cistatic ssize_t f2fs_quota_read(struct super_block *sb, int type, char *data, 20648c2ecf20Sopenharmony_ci size_t len, loff_t off) 20658c2ecf20Sopenharmony_ci{ 20668c2ecf20Sopenharmony_ci struct inode *inode = sb_dqopt(sb)->files[type]; 20678c2ecf20Sopenharmony_ci struct address_space *mapping = inode->i_mapping; 20688c2ecf20Sopenharmony_ci block_t blkidx = F2FS_BYTES_TO_BLK(off); 20698c2ecf20Sopenharmony_ci int offset = off & (sb->s_blocksize - 1); 20708c2ecf20Sopenharmony_ci int tocopy; 20718c2ecf20Sopenharmony_ci size_t toread; 20728c2ecf20Sopenharmony_ci loff_t i_size = i_size_read(inode); 20738c2ecf20Sopenharmony_ci struct page *page; 20748c2ecf20Sopenharmony_ci 20758c2ecf20Sopenharmony_ci if (off > i_size) 20768c2ecf20Sopenharmony_ci return 0; 20778c2ecf20Sopenharmony_ci 20788c2ecf20Sopenharmony_ci if (off + len > i_size) 20798c2ecf20Sopenharmony_ci len = i_size - off; 20808c2ecf20Sopenharmony_ci toread = len; 20818c2ecf20Sopenharmony_ci while (toread > 0) { 20828c2ecf20Sopenharmony_ci tocopy = min_t(unsigned long, sb->s_blocksize - offset, toread); 20838c2ecf20Sopenharmony_cirepeat: 20848c2ecf20Sopenharmony_ci page = read_cache_page_gfp(mapping, blkidx, GFP_NOFS); 20858c2ecf20Sopenharmony_ci if (IS_ERR(page)) { 20868c2ecf20Sopenharmony_ci if (PTR_ERR(page) == -ENOMEM) { 20878c2ecf20Sopenharmony_ci congestion_wait(BLK_RW_ASYNC, 20888c2ecf20Sopenharmony_ci DEFAULT_IO_TIMEOUT); 20898c2ecf20Sopenharmony_ci goto repeat; 20908c2ecf20Sopenharmony_ci } 20918c2ecf20Sopenharmony_ci set_sbi_flag(F2FS_SB(sb), SBI_QUOTA_NEED_REPAIR); 20928c2ecf20Sopenharmony_ci return PTR_ERR(page); 20938c2ecf20Sopenharmony_ci } 20948c2ecf20Sopenharmony_ci 20958c2ecf20Sopenharmony_ci lock_page(page); 20968c2ecf20Sopenharmony_ci 20978c2ecf20Sopenharmony_ci if (unlikely(page->mapping != mapping)) { 20988c2ecf20Sopenharmony_ci f2fs_put_page(page, 1); 20998c2ecf20Sopenharmony_ci goto repeat; 21008c2ecf20Sopenharmony_ci } 21018c2ecf20Sopenharmony_ci if (unlikely(!PageUptodate(page))) { 21028c2ecf20Sopenharmony_ci f2fs_put_page(page, 1); 21038c2ecf20Sopenharmony_ci set_sbi_flag(F2FS_SB(sb), SBI_QUOTA_NEED_REPAIR); 21048c2ecf20Sopenharmony_ci return -EIO; 21058c2ecf20Sopenharmony_ci } 21068c2ecf20Sopenharmony_ci 21078c2ecf20Sopenharmony_ci memcpy_from_page(data, page, offset, tocopy); 21088c2ecf20Sopenharmony_ci f2fs_put_page(page, 1); 21098c2ecf20Sopenharmony_ci 21108c2ecf20Sopenharmony_ci offset = 0; 21118c2ecf20Sopenharmony_ci toread -= tocopy; 21128c2ecf20Sopenharmony_ci data += tocopy; 21138c2ecf20Sopenharmony_ci blkidx++; 21148c2ecf20Sopenharmony_ci } 21158c2ecf20Sopenharmony_ci return len; 21168c2ecf20Sopenharmony_ci} 21178c2ecf20Sopenharmony_ci 21188c2ecf20Sopenharmony_ci/* Write to quotafile */ 21198c2ecf20Sopenharmony_cistatic ssize_t f2fs_quota_write(struct super_block *sb, int type, 21208c2ecf20Sopenharmony_ci const char *data, size_t len, loff_t off) 21218c2ecf20Sopenharmony_ci{ 21228c2ecf20Sopenharmony_ci struct inode *inode = sb_dqopt(sb)->files[type]; 21238c2ecf20Sopenharmony_ci struct address_space *mapping = inode->i_mapping; 21248c2ecf20Sopenharmony_ci const struct address_space_operations *a_ops = mapping->a_ops; 21258c2ecf20Sopenharmony_ci int offset = off & (sb->s_blocksize - 1); 21268c2ecf20Sopenharmony_ci size_t towrite = len; 21278c2ecf20Sopenharmony_ci struct page *page; 21288c2ecf20Sopenharmony_ci void *fsdata = NULL; 21298c2ecf20Sopenharmony_ci int err = 0; 21308c2ecf20Sopenharmony_ci int tocopy; 21318c2ecf20Sopenharmony_ci 21328c2ecf20Sopenharmony_ci while (towrite > 0) { 21338c2ecf20Sopenharmony_ci tocopy = min_t(unsigned long, sb->s_blocksize - offset, 21348c2ecf20Sopenharmony_ci towrite); 21358c2ecf20Sopenharmony_ciretry: 21368c2ecf20Sopenharmony_ci err = a_ops->write_begin(NULL, mapping, off, tocopy, 0, 21378c2ecf20Sopenharmony_ci &page, &fsdata); 21388c2ecf20Sopenharmony_ci if (unlikely(err)) { 21398c2ecf20Sopenharmony_ci if (err == -ENOMEM) { 21408c2ecf20Sopenharmony_ci congestion_wait(BLK_RW_ASYNC, 21418c2ecf20Sopenharmony_ci DEFAULT_IO_TIMEOUT); 21428c2ecf20Sopenharmony_ci goto retry; 21438c2ecf20Sopenharmony_ci } 21448c2ecf20Sopenharmony_ci set_sbi_flag(F2FS_SB(sb), SBI_QUOTA_NEED_REPAIR); 21458c2ecf20Sopenharmony_ci break; 21468c2ecf20Sopenharmony_ci } 21478c2ecf20Sopenharmony_ci 21488c2ecf20Sopenharmony_ci memcpy_to_page(page, offset, data, tocopy); 21498c2ecf20Sopenharmony_ci 21508c2ecf20Sopenharmony_ci a_ops->write_end(NULL, mapping, off, tocopy, tocopy, 21518c2ecf20Sopenharmony_ci page, fsdata); 21528c2ecf20Sopenharmony_ci offset = 0; 21538c2ecf20Sopenharmony_ci towrite -= tocopy; 21548c2ecf20Sopenharmony_ci off += tocopy; 21558c2ecf20Sopenharmony_ci data += tocopy; 21568c2ecf20Sopenharmony_ci cond_resched(); 21578c2ecf20Sopenharmony_ci } 21588c2ecf20Sopenharmony_ci 21598c2ecf20Sopenharmony_ci if (len == towrite) 21608c2ecf20Sopenharmony_ci return err; 21618c2ecf20Sopenharmony_ci inode->i_mtime = inode->i_ctime = current_time(inode); 21628c2ecf20Sopenharmony_ci f2fs_mark_inode_dirty_sync(inode, false); 21638c2ecf20Sopenharmony_ci return len - towrite; 21648c2ecf20Sopenharmony_ci} 21658c2ecf20Sopenharmony_ci 21668c2ecf20Sopenharmony_cistatic struct dquot **f2fs_get_dquots(struct inode *inode) 21678c2ecf20Sopenharmony_ci{ 21688c2ecf20Sopenharmony_ci return F2FS_I(inode)->i_dquot; 21698c2ecf20Sopenharmony_ci} 21708c2ecf20Sopenharmony_ci 21718c2ecf20Sopenharmony_cistatic qsize_t *f2fs_get_reserved_space(struct inode *inode) 21728c2ecf20Sopenharmony_ci{ 21738c2ecf20Sopenharmony_ci return &F2FS_I(inode)->i_reserved_quota; 21748c2ecf20Sopenharmony_ci} 21758c2ecf20Sopenharmony_ci 21768c2ecf20Sopenharmony_cistatic int f2fs_quota_on_mount(struct f2fs_sb_info *sbi, int type) 21778c2ecf20Sopenharmony_ci{ 21788c2ecf20Sopenharmony_ci if (is_set_ckpt_flags(sbi, CP_QUOTA_NEED_FSCK_FLAG)) { 21798c2ecf20Sopenharmony_ci f2fs_err(sbi, "quota sysfile may be corrupted, skip loading it"); 21808c2ecf20Sopenharmony_ci return 0; 21818c2ecf20Sopenharmony_ci } 21828c2ecf20Sopenharmony_ci 21838c2ecf20Sopenharmony_ci return dquot_quota_on_mount(sbi->sb, F2FS_OPTION(sbi).s_qf_names[type], 21848c2ecf20Sopenharmony_ci F2FS_OPTION(sbi).s_jquota_fmt, type); 21858c2ecf20Sopenharmony_ci} 21868c2ecf20Sopenharmony_ci 21878c2ecf20Sopenharmony_ciint f2fs_enable_quota_files(struct f2fs_sb_info *sbi, bool rdonly) 21888c2ecf20Sopenharmony_ci{ 21898c2ecf20Sopenharmony_ci int enabled = 0; 21908c2ecf20Sopenharmony_ci int i, err; 21918c2ecf20Sopenharmony_ci 21928c2ecf20Sopenharmony_ci if (f2fs_sb_has_quota_ino(sbi) && rdonly) { 21938c2ecf20Sopenharmony_ci err = f2fs_enable_quotas(sbi->sb); 21948c2ecf20Sopenharmony_ci if (err) { 21958c2ecf20Sopenharmony_ci f2fs_err(sbi, "Cannot turn on quota_ino: %d", err); 21968c2ecf20Sopenharmony_ci return 0; 21978c2ecf20Sopenharmony_ci } 21988c2ecf20Sopenharmony_ci return 1; 21998c2ecf20Sopenharmony_ci } 22008c2ecf20Sopenharmony_ci 22018c2ecf20Sopenharmony_ci for (i = 0; i < MAXQUOTAS; i++) { 22028c2ecf20Sopenharmony_ci if (F2FS_OPTION(sbi).s_qf_names[i]) { 22038c2ecf20Sopenharmony_ci err = f2fs_quota_on_mount(sbi, i); 22048c2ecf20Sopenharmony_ci if (!err) { 22058c2ecf20Sopenharmony_ci enabled = 1; 22068c2ecf20Sopenharmony_ci continue; 22078c2ecf20Sopenharmony_ci } 22088c2ecf20Sopenharmony_ci f2fs_err(sbi, "Cannot turn on quotas: %d on %d", 22098c2ecf20Sopenharmony_ci err, i); 22108c2ecf20Sopenharmony_ci } 22118c2ecf20Sopenharmony_ci } 22128c2ecf20Sopenharmony_ci return enabled; 22138c2ecf20Sopenharmony_ci} 22148c2ecf20Sopenharmony_ci 22158c2ecf20Sopenharmony_cistatic int f2fs_quota_enable(struct super_block *sb, int type, int format_id, 22168c2ecf20Sopenharmony_ci unsigned int flags) 22178c2ecf20Sopenharmony_ci{ 22188c2ecf20Sopenharmony_ci struct inode *qf_inode; 22198c2ecf20Sopenharmony_ci unsigned long qf_inum; 22208c2ecf20Sopenharmony_ci int err; 22218c2ecf20Sopenharmony_ci 22228c2ecf20Sopenharmony_ci BUG_ON(!f2fs_sb_has_quota_ino(F2FS_SB(sb))); 22238c2ecf20Sopenharmony_ci 22248c2ecf20Sopenharmony_ci qf_inum = f2fs_qf_ino(sb, type); 22258c2ecf20Sopenharmony_ci if (!qf_inum) 22268c2ecf20Sopenharmony_ci return -EPERM; 22278c2ecf20Sopenharmony_ci 22288c2ecf20Sopenharmony_ci qf_inode = f2fs_iget(sb, qf_inum); 22298c2ecf20Sopenharmony_ci if (IS_ERR(qf_inode)) { 22308c2ecf20Sopenharmony_ci f2fs_err(F2FS_SB(sb), "Bad quota inode %u:%lu", type, qf_inum); 22318c2ecf20Sopenharmony_ci return PTR_ERR(qf_inode); 22328c2ecf20Sopenharmony_ci } 22338c2ecf20Sopenharmony_ci 22348c2ecf20Sopenharmony_ci /* Don't account quota for quota files to avoid recursion */ 22358c2ecf20Sopenharmony_ci qf_inode->i_flags |= S_NOQUOTA; 22368c2ecf20Sopenharmony_ci err = dquot_load_quota_inode(qf_inode, type, format_id, flags); 22378c2ecf20Sopenharmony_ci iput(qf_inode); 22388c2ecf20Sopenharmony_ci return err; 22398c2ecf20Sopenharmony_ci} 22408c2ecf20Sopenharmony_ci 22418c2ecf20Sopenharmony_cistatic int f2fs_enable_quotas(struct super_block *sb) 22428c2ecf20Sopenharmony_ci{ 22438c2ecf20Sopenharmony_ci struct f2fs_sb_info *sbi = F2FS_SB(sb); 22448c2ecf20Sopenharmony_ci int type, err = 0; 22458c2ecf20Sopenharmony_ci unsigned long qf_inum; 22468c2ecf20Sopenharmony_ci bool quota_mopt[MAXQUOTAS] = { 22478c2ecf20Sopenharmony_ci test_opt(sbi, USRQUOTA), 22488c2ecf20Sopenharmony_ci test_opt(sbi, GRPQUOTA), 22498c2ecf20Sopenharmony_ci test_opt(sbi, PRJQUOTA), 22508c2ecf20Sopenharmony_ci }; 22518c2ecf20Sopenharmony_ci 22528c2ecf20Sopenharmony_ci if (is_set_ckpt_flags(F2FS_SB(sb), CP_QUOTA_NEED_FSCK_FLAG)) { 22538c2ecf20Sopenharmony_ci f2fs_err(sbi, "quota file may be corrupted, skip loading it"); 22548c2ecf20Sopenharmony_ci return 0; 22558c2ecf20Sopenharmony_ci } 22568c2ecf20Sopenharmony_ci 22578c2ecf20Sopenharmony_ci sb_dqopt(sb)->flags |= DQUOT_QUOTA_SYS_FILE; 22588c2ecf20Sopenharmony_ci 22598c2ecf20Sopenharmony_ci for (type = 0; type < MAXQUOTAS; type++) { 22608c2ecf20Sopenharmony_ci qf_inum = f2fs_qf_ino(sb, type); 22618c2ecf20Sopenharmony_ci if (qf_inum) { 22628c2ecf20Sopenharmony_ci err = f2fs_quota_enable(sb, type, QFMT_VFS_V1, 22638c2ecf20Sopenharmony_ci DQUOT_USAGE_ENABLED | 22648c2ecf20Sopenharmony_ci (quota_mopt[type] ? DQUOT_LIMITS_ENABLED : 0)); 22658c2ecf20Sopenharmony_ci if (err) { 22668c2ecf20Sopenharmony_ci f2fs_err(sbi, "Failed to enable quota tracking (type=%d, err=%d). Please run fsck to fix.", 22678c2ecf20Sopenharmony_ci type, err); 22688c2ecf20Sopenharmony_ci for (type--; type >= 0; type--) 22698c2ecf20Sopenharmony_ci dquot_quota_off(sb, type); 22708c2ecf20Sopenharmony_ci set_sbi_flag(F2FS_SB(sb), 22718c2ecf20Sopenharmony_ci SBI_QUOTA_NEED_REPAIR); 22728c2ecf20Sopenharmony_ci return err; 22738c2ecf20Sopenharmony_ci } 22748c2ecf20Sopenharmony_ci } 22758c2ecf20Sopenharmony_ci } 22768c2ecf20Sopenharmony_ci return 0; 22778c2ecf20Sopenharmony_ci} 22788c2ecf20Sopenharmony_ci 22798c2ecf20Sopenharmony_cistatic int f2fs_quota_sync_file(struct f2fs_sb_info *sbi, int type) 22808c2ecf20Sopenharmony_ci{ 22818c2ecf20Sopenharmony_ci struct quota_info *dqopt = sb_dqopt(sbi->sb); 22828c2ecf20Sopenharmony_ci struct address_space *mapping = dqopt->files[type]->i_mapping; 22838c2ecf20Sopenharmony_ci int ret = 0; 22848c2ecf20Sopenharmony_ci 22858c2ecf20Sopenharmony_ci ret = dquot_writeback_dquots(sbi->sb, type); 22868c2ecf20Sopenharmony_ci if (ret) 22878c2ecf20Sopenharmony_ci goto out; 22888c2ecf20Sopenharmony_ci 22898c2ecf20Sopenharmony_ci ret = filemap_fdatawrite(mapping); 22908c2ecf20Sopenharmony_ci if (ret) 22918c2ecf20Sopenharmony_ci goto out; 22928c2ecf20Sopenharmony_ci 22938c2ecf20Sopenharmony_ci /* if we are using journalled quota */ 22948c2ecf20Sopenharmony_ci if (is_journalled_quota(sbi)) 22958c2ecf20Sopenharmony_ci goto out; 22968c2ecf20Sopenharmony_ci 22978c2ecf20Sopenharmony_ci ret = filemap_fdatawait(mapping); 22988c2ecf20Sopenharmony_ci 22998c2ecf20Sopenharmony_ci truncate_inode_pages(&dqopt->files[type]->i_data, 0); 23008c2ecf20Sopenharmony_ciout: 23018c2ecf20Sopenharmony_ci if (ret) 23028c2ecf20Sopenharmony_ci set_sbi_flag(sbi, SBI_QUOTA_NEED_REPAIR); 23038c2ecf20Sopenharmony_ci return ret; 23048c2ecf20Sopenharmony_ci} 23058c2ecf20Sopenharmony_ci 23068c2ecf20Sopenharmony_ciint f2fs_quota_sync(struct super_block *sb, int type) 23078c2ecf20Sopenharmony_ci{ 23088c2ecf20Sopenharmony_ci struct f2fs_sb_info *sbi = F2FS_SB(sb); 23098c2ecf20Sopenharmony_ci struct quota_info *dqopt = sb_dqopt(sb); 23108c2ecf20Sopenharmony_ci int cnt; 23118c2ecf20Sopenharmony_ci int ret = 0; 23128c2ecf20Sopenharmony_ci 23138c2ecf20Sopenharmony_ci /* 23148c2ecf20Sopenharmony_ci * Now when everything is written we can discard the pagecache so 23158c2ecf20Sopenharmony_ci * that userspace sees the changes. 23168c2ecf20Sopenharmony_ci */ 23178c2ecf20Sopenharmony_ci for (cnt = 0; cnt < MAXQUOTAS; cnt++) { 23188c2ecf20Sopenharmony_ci 23198c2ecf20Sopenharmony_ci if (type != -1 && cnt != type) 23208c2ecf20Sopenharmony_ci continue; 23218c2ecf20Sopenharmony_ci 23228c2ecf20Sopenharmony_ci if (!sb_has_quota_active(sb, cnt)) 23238c2ecf20Sopenharmony_ci continue; 23248c2ecf20Sopenharmony_ci 23258c2ecf20Sopenharmony_ci if (!f2fs_sb_has_quota_ino(sbi)) 23268c2ecf20Sopenharmony_ci inode_lock(dqopt->files[cnt]); 23278c2ecf20Sopenharmony_ci 23288c2ecf20Sopenharmony_ci /* 23298c2ecf20Sopenharmony_ci * do_quotactl 23308c2ecf20Sopenharmony_ci * f2fs_quota_sync 23318c2ecf20Sopenharmony_ci * down_read(quota_sem) 23328c2ecf20Sopenharmony_ci * dquot_writeback_dquots() 23338c2ecf20Sopenharmony_ci * f2fs_dquot_commit 23348c2ecf20Sopenharmony_ci * block_operation 23358c2ecf20Sopenharmony_ci * down_read(quota_sem) 23368c2ecf20Sopenharmony_ci */ 23378c2ecf20Sopenharmony_ci f2fs_lock_op(sbi); 23388c2ecf20Sopenharmony_ci down_read(&sbi->quota_sem); 23398c2ecf20Sopenharmony_ci 23408c2ecf20Sopenharmony_ci ret = f2fs_quota_sync_file(sbi, cnt); 23418c2ecf20Sopenharmony_ci 23428c2ecf20Sopenharmony_ci up_read(&sbi->quota_sem); 23438c2ecf20Sopenharmony_ci f2fs_unlock_op(sbi); 23448c2ecf20Sopenharmony_ci 23458c2ecf20Sopenharmony_ci if (!f2fs_sb_has_quota_ino(sbi)) 23468c2ecf20Sopenharmony_ci inode_unlock(dqopt->files[cnt]); 23478c2ecf20Sopenharmony_ci 23488c2ecf20Sopenharmony_ci if (ret) 23498c2ecf20Sopenharmony_ci break; 23508c2ecf20Sopenharmony_ci } 23518c2ecf20Sopenharmony_ci return ret; 23528c2ecf20Sopenharmony_ci} 23538c2ecf20Sopenharmony_ci 23548c2ecf20Sopenharmony_cistatic int f2fs_quota_on(struct super_block *sb, int type, int format_id, 23558c2ecf20Sopenharmony_ci const struct path *path) 23568c2ecf20Sopenharmony_ci{ 23578c2ecf20Sopenharmony_ci struct inode *inode; 23588c2ecf20Sopenharmony_ci int err; 23598c2ecf20Sopenharmony_ci 23608c2ecf20Sopenharmony_ci /* if quota sysfile exists, deny enabling quota with specific file */ 23618c2ecf20Sopenharmony_ci if (f2fs_sb_has_quota_ino(F2FS_SB(sb))) { 23628c2ecf20Sopenharmony_ci f2fs_err(F2FS_SB(sb), "quota sysfile already exists"); 23638c2ecf20Sopenharmony_ci return -EBUSY; 23648c2ecf20Sopenharmony_ci } 23658c2ecf20Sopenharmony_ci 23668c2ecf20Sopenharmony_ci err = f2fs_quota_sync(sb, type); 23678c2ecf20Sopenharmony_ci if (err) 23688c2ecf20Sopenharmony_ci return err; 23698c2ecf20Sopenharmony_ci 23708c2ecf20Sopenharmony_ci err = dquot_quota_on(sb, type, format_id, path); 23718c2ecf20Sopenharmony_ci if (err) 23728c2ecf20Sopenharmony_ci return err; 23738c2ecf20Sopenharmony_ci 23748c2ecf20Sopenharmony_ci inode = d_inode(path->dentry); 23758c2ecf20Sopenharmony_ci 23768c2ecf20Sopenharmony_ci inode_lock(inode); 23778c2ecf20Sopenharmony_ci F2FS_I(inode)->i_flags |= F2FS_NOATIME_FL | F2FS_IMMUTABLE_FL; 23788c2ecf20Sopenharmony_ci f2fs_set_inode_flags(inode); 23798c2ecf20Sopenharmony_ci inode_unlock(inode); 23808c2ecf20Sopenharmony_ci f2fs_mark_inode_dirty_sync(inode, false); 23818c2ecf20Sopenharmony_ci 23828c2ecf20Sopenharmony_ci return 0; 23838c2ecf20Sopenharmony_ci} 23848c2ecf20Sopenharmony_ci 23858c2ecf20Sopenharmony_cistatic int __f2fs_quota_off(struct super_block *sb, int type) 23868c2ecf20Sopenharmony_ci{ 23878c2ecf20Sopenharmony_ci struct inode *inode = sb_dqopt(sb)->files[type]; 23888c2ecf20Sopenharmony_ci int err; 23898c2ecf20Sopenharmony_ci 23908c2ecf20Sopenharmony_ci if (!inode || !igrab(inode)) 23918c2ecf20Sopenharmony_ci return dquot_quota_off(sb, type); 23928c2ecf20Sopenharmony_ci 23938c2ecf20Sopenharmony_ci err = f2fs_quota_sync(sb, type); 23948c2ecf20Sopenharmony_ci if (err) 23958c2ecf20Sopenharmony_ci goto out_put; 23968c2ecf20Sopenharmony_ci 23978c2ecf20Sopenharmony_ci err = dquot_quota_off(sb, type); 23988c2ecf20Sopenharmony_ci if (err || f2fs_sb_has_quota_ino(F2FS_SB(sb))) 23998c2ecf20Sopenharmony_ci goto out_put; 24008c2ecf20Sopenharmony_ci 24018c2ecf20Sopenharmony_ci inode_lock(inode); 24028c2ecf20Sopenharmony_ci F2FS_I(inode)->i_flags &= ~(F2FS_NOATIME_FL | F2FS_IMMUTABLE_FL); 24038c2ecf20Sopenharmony_ci f2fs_set_inode_flags(inode); 24048c2ecf20Sopenharmony_ci inode_unlock(inode); 24058c2ecf20Sopenharmony_ci f2fs_mark_inode_dirty_sync(inode, false); 24068c2ecf20Sopenharmony_ciout_put: 24078c2ecf20Sopenharmony_ci iput(inode); 24088c2ecf20Sopenharmony_ci return err; 24098c2ecf20Sopenharmony_ci} 24108c2ecf20Sopenharmony_ci 24118c2ecf20Sopenharmony_cistatic int f2fs_quota_off(struct super_block *sb, int type) 24128c2ecf20Sopenharmony_ci{ 24138c2ecf20Sopenharmony_ci struct f2fs_sb_info *sbi = F2FS_SB(sb); 24148c2ecf20Sopenharmony_ci int err; 24158c2ecf20Sopenharmony_ci 24168c2ecf20Sopenharmony_ci err = __f2fs_quota_off(sb, type); 24178c2ecf20Sopenharmony_ci 24188c2ecf20Sopenharmony_ci /* 24198c2ecf20Sopenharmony_ci * quotactl can shutdown journalled quota, result in inconsistence 24208c2ecf20Sopenharmony_ci * between quota record and fs data by following updates, tag the 24218c2ecf20Sopenharmony_ci * flag to let fsck be aware of it. 24228c2ecf20Sopenharmony_ci */ 24238c2ecf20Sopenharmony_ci if (is_journalled_quota(sbi)) 24248c2ecf20Sopenharmony_ci set_sbi_flag(sbi, SBI_QUOTA_NEED_REPAIR); 24258c2ecf20Sopenharmony_ci return err; 24268c2ecf20Sopenharmony_ci} 24278c2ecf20Sopenharmony_ci 24288c2ecf20Sopenharmony_civoid f2fs_quota_off_umount(struct super_block *sb) 24298c2ecf20Sopenharmony_ci{ 24308c2ecf20Sopenharmony_ci int type; 24318c2ecf20Sopenharmony_ci int err; 24328c2ecf20Sopenharmony_ci 24338c2ecf20Sopenharmony_ci for (type = 0; type < MAXQUOTAS; type++) { 24348c2ecf20Sopenharmony_ci err = __f2fs_quota_off(sb, type); 24358c2ecf20Sopenharmony_ci if (err) { 24368c2ecf20Sopenharmony_ci int ret = dquot_quota_off(sb, type); 24378c2ecf20Sopenharmony_ci 24388c2ecf20Sopenharmony_ci f2fs_err(F2FS_SB(sb), "Fail to turn off disk quota (type: %d, err: %d, ret:%d), Please run fsck to fix it.", 24398c2ecf20Sopenharmony_ci type, err, ret); 24408c2ecf20Sopenharmony_ci set_sbi_flag(F2FS_SB(sb), SBI_QUOTA_NEED_REPAIR); 24418c2ecf20Sopenharmony_ci } 24428c2ecf20Sopenharmony_ci } 24438c2ecf20Sopenharmony_ci /* 24448c2ecf20Sopenharmony_ci * In case of checkpoint=disable, we must flush quota blocks. 24458c2ecf20Sopenharmony_ci * This can cause NULL exception for node_inode in end_io, since 24468c2ecf20Sopenharmony_ci * put_super already dropped it. 24478c2ecf20Sopenharmony_ci */ 24488c2ecf20Sopenharmony_ci sync_filesystem(sb); 24498c2ecf20Sopenharmony_ci} 24508c2ecf20Sopenharmony_ci 24518c2ecf20Sopenharmony_cistatic void f2fs_truncate_quota_inode_pages(struct super_block *sb) 24528c2ecf20Sopenharmony_ci{ 24538c2ecf20Sopenharmony_ci struct quota_info *dqopt = sb_dqopt(sb); 24548c2ecf20Sopenharmony_ci int type; 24558c2ecf20Sopenharmony_ci 24568c2ecf20Sopenharmony_ci for (type = 0; type < MAXQUOTAS; type++) { 24578c2ecf20Sopenharmony_ci if (!dqopt->files[type]) 24588c2ecf20Sopenharmony_ci continue; 24598c2ecf20Sopenharmony_ci f2fs_inode_synced(dqopt->files[type]); 24608c2ecf20Sopenharmony_ci } 24618c2ecf20Sopenharmony_ci} 24628c2ecf20Sopenharmony_ci 24638c2ecf20Sopenharmony_cistatic int f2fs_dquot_commit(struct dquot *dquot) 24648c2ecf20Sopenharmony_ci{ 24658c2ecf20Sopenharmony_ci struct f2fs_sb_info *sbi = F2FS_SB(dquot->dq_sb); 24668c2ecf20Sopenharmony_ci int ret; 24678c2ecf20Sopenharmony_ci 24688c2ecf20Sopenharmony_ci down_read_nested(&sbi->quota_sem, SINGLE_DEPTH_NESTING); 24698c2ecf20Sopenharmony_ci ret = dquot_commit(dquot); 24708c2ecf20Sopenharmony_ci if (ret < 0) 24718c2ecf20Sopenharmony_ci set_sbi_flag(sbi, SBI_QUOTA_NEED_REPAIR); 24728c2ecf20Sopenharmony_ci up_read(&sbi->quota_sem); 24738c2ecf20Sopenharmony_ci return ret; 24748c2ecf20Sopenharmony_ci} 24758c2ecf20Sopenharmony_ci 24768c2ecf20Sopenharmony_cistatic int f2fs_dquot_acquire(struct dquot *dquot) 24778c2ecf20Sopenharmony_ci{ 24788c2ecf20Sopenharmony_ci struct f2fs_sb_info *sbi = F2FS_SB(dquot->dq_sb); 24798c2ecf20Sopenharmony_ci int ret; 24808c2ecf20Sopenharmony_ci 24818c2ecf20Sopenharmony_ci down_read(&sbi->quota_sem); 24828c2ecf20Sopenharmony_ci ret = dquot_acquire(dquot); 24838c2ecf20Sopenharmony_ci if (ret < 0) 24848c2ecf20Sopenharmony_ci set_sbi_flag(sbi, SBI_QUOTA_NEED_REPAIR); 24858c2ecf20Sopenharmony_ci up_read(&sbi->quota_sem); 24868c2ecf20Sopenharmony_ci return ret; 24878c2ecf20Sopenharmony_ci} 24888c2ecf20Sopenharmony_ci 24898c2ecf20Sopenharmony_cistatic int f2fs_dquot_release(struct dquot *dquot) 24908c2ecf20Sopenharmony_ci{ 24918c2ecf20Sopenharmony_ci struct f2fs_sb_info *sbi = F2FS_SB(dquot->dq_sb); 24928c2ecf20Sopenharmony_ci int ret = dquot_release(dquot); 24938c2ecf20Sopenharmony_ci 24948c2ecf20Sopenharmony_ci if (ret < 0) 24958c2ecf20Sopenharmony_ci set_sbi_flag(sbi, SBI_QUOTA_NEED_REPAIR); 24968c2ecf20Sopenharmony_ci return ret; 24978c2ecf20Sopenharmony_ci} 24988c2ecf20Sopenharmony_ci 24998c2ecf20Sopenharmony_cistatic int f2fs_dquot_mark_dquot_dirty(struct dquot *dquot) 25008c2ecf20Sopenharmony_ci{ 25018c2ecf20Sopenharmony_ci struct super_block *sb = dquot->dq_sb; 25028c2ecf20Sopenharmony_ci struct f2fs_sb_info *sbi = F2FS_SB(sb); 25038c2ecf20Sopenharmony_ci int ret = dquot_mark_dquot_dirty(dquot); 25048c2ecf20Sopenharmony_ci 25058c2ecf20Sopenharmony_ci /* if we are using journalled quota */ 25068c2ecf20Sopenharmony_ci if (is_journalled_quota(sbi)) 25078c2ecf20Sopenharmony_ci set_sbi_flag(sbi, SBI_QUOTA_NEED_FLUSH); 25088c2ecf20Sopenharmony_ci 25098c2ecf20Sopenharmony_ci return ret; 25108c2ecf20Sopenharmony_ci} 25118c2ecf20Sopenharmony_ci 25128c2ecf20Sopenharmony_cistatic int f2fs_dquot_commit_info(struct super_block *sb, int type) 25138c2ecf20Sopenharmony_ci{ 25148c2ecf20Sopenharmony_ci struct f2fs_sb_info *sbi = F2FS_SB(sb); 25158c2ecf20Sopenharmony_ci int ret = dquot_commit_info(sb, type); 25168c2ecf20Sopenharmony_ci 25178c2ecf20Sopenharmony_ci if (ret < 0) 25188c2ecf20Sopenharmony_ci set_sbi_flag(sbi, SBI_QUOTA_NEED_REPAIR); 25198c2ecf20Sopenharmony_ci return ret; 25208c2ecf20Sopenharmony_ci} 25218c2ecf20Sopenharmony_ci 25228c2ecf20Sopenharmony_cistatic int f2fs_get_projid(struct inode *inode, kprojid_t *projid) 25238c2ecf20Sopenharmony_ci{ 25248c2ecf20Sopenharmony_ci *projid = F2FS_I(inode)->i_projid; 25258c2ecf20Sopenharmony_ci return 0; 25268c2ecf20Sopenharmony_ci} 25278c2ecf20Sopenharmony_ci 25288c2ecf20Sopenharmony_cistatic const struct dquot_operations f2fs_quota_operations = { 25298c2ecf20Sopenharmony_ci .get_reserved_space = f2fs_get_reserved_space, 25308c2ecf20Sopenharmony_ci .write_dquot = f2fs_dquot_commit, 25318c2ecf20Sopenharmony_ci .acquire_dquot = f2fs_dquot_acquire, 25328c2ecf20Sopenharmony_ci .release_dquot = f2fs_dquot_release, 25338c2ecf20Sopenharmony_ci .mark_dirty = f2fs_dquot_mark_dquot_dirty, 25348c2ecf20Sopenharmony_ci .write_info = f2fs_dquot_commit_info, 25358c2ecf20Sopenharmony_ci .alloc_dquot = dquot_alloc, 25368c2ecf20Sopenharmony_ci .destroy_dquot = dquot_destroy, 25378c2ecf20Sopenharmony_ci .get_projid = f2fs_get_projid, 25388c2ecf20Sopenharmony_ci .get_next_id = dquot_get_next_id, 25398c2ecf20Sopenharmony_ci}; 25408c2ecf20Sopenharmony_ci 25418c2ecf20Sopenharmony_cistatic const struct quotactl_ops f2fs_quotactl_ops = { 25428c2ecf20Sopenharmony_ci .quota_on = f2fs_quota_on, 25438c2ecf20Sopenharmony_ci .quota_off = f2fs_quota_off, 25448c2ecf20Sopenharmony_ci .quota_sync = f2fs_quota_sync, 25458c2ecf20Sopenharmony_ci .get_state = dquot_get_state, 25468c2ecf20Sopenharmony_ci .set_info = dquot_set_dqinfo, 25478c2ecf20Sopenharmony_ci .get_dqblk = dquot_get_dqblk, 25488c2ecf20Sopenharmony_ci .set_dqblk = dquot_set_dqblk, 25498c2ecf20Sopenharmony_ci .get_nextdqblk = dquot_get_next_dqblk, 25508c2ecf20Sopenharmony_ci}; 25518c2ecf20Sopenharmony_ci#else 25528c2ecf20Sopenharmony_ciint f2fs_quota_sync(struct super_block *sb, int type) 25538c2ecf20Sopenharmony_ci{ 25548c2ecf20Sopenharmony_ci return 0; 25558c2ecf20Sopenharmony_ci} 25568c2ecf20Sopenharmony_ci 25578c2ecf20Sopenharmony_civoid f2fs_quota_off_umount(struct super_block *sb) 25588c2ecf20Sopenharmony_ci{ 25598c2ecf20Sopenharmony_ci} 25608c2ecf20Sopenharmony_ci#endif 25618c2ecf20Sopenharmony_ci 25628c2ecf20Sopenharmony_cistatic const struct super_operations f2fs_sops = { 25638c2ecf20Sopenharmony_ci .alloc_inode = f2fs_alloc_inode, 25648c2ecf20Sopenharmony_ci .free_inode = f2fs_free_inode, 25658c2ecf20Sopenharmony_ci .drop_inode = f2fs_drop_inode, 25668c2ecf20Sopenharmony_ci .write_inode = f2fs_write_inode, 25678c2ecf20Sopenharmony_ci .dirty_inode = f2fs_dirty_inode, 25688c2ecf20Sopenharmony_ci .show_options = f2fs_show_options, 25698c2ecf20Sopenharmony_ci#ifdef CONFIG_QUOTA 25708c2ecf20Sopenharmony_ci .quota_read = f2fs_quota_read, 25718c2ecf20Sopenharmony_ci .quota_write = f2fs_quota_write, 25728c2ecf20Sopenharmony_ci .get_dquots = f2fs_get_dquots, 25738c2ecf20Sopenharmony_ci#endif 25748c2ecf20Sopenharmony_ci .evict_inode = f2fs_evict_inode, 25758c2ecf20Sopenharmony_ci .put_super = f2fs_put_super, 25768c2ecf20Sopenharmony_ci .sync_fs = f2fs_sync_fs, 25778c2ecf20Sopenharmony_ci .freeze_fs = f2fs_freeze, 25788c2ecf20Sopenharmony_ci .unfreeze_fs = f2fs_unfreeze, 25798c2ecf20Sopenharmony_ci .statfs = f2fs_statfs, 25808c2ecf20Sopenharmony_ci .remount_fs = f2fs_remount, 25818c2ecf20Sopenharmony_ci}; 25828c2ecf20Sopenharmony_ci 25838c2ecf20Sopenharmony_ci#ifdef CONFIG_FS_ENCRYPTION 25848c2ecf20Sopenharmony_cistatic int f2fs_get_context(struct inode *inode, void *ctx, size_t len) 25858c2ecf20Sopenharmony_ci{ 25868c2ecf20Sopenharmony_ci return f2fs_getxattr(inode, F2FS_XATTR_INDEX_ENCRYPTION, 25878c2ecf20Sopenharmony_ci F2FS_XATTR_NAME_ENCRYPTION_CONTEXT, 25888c2ecf20Sopenharmony_ci ctx, len, NULL); 25898c2ecf20Sopenharmony_ci} 25908c2ecf20Sopenharmony_ci 25918c2ecf20Sopenharmony_cistatic int f2fs_set_context(struct inode *inode, const void *ctx, size_t len, 25928c2ecf20Sopenharmony_ci void *fs_data) 25938c2ecf20Sopenharmony_ci{ 25948c2ecf20Sopenharmony_ci struct f2fs_sb_info *sbi = F2FS_I_SB(inode); 25958c2ecf20Sopenharmony_ci 25968c2ecf20Sopenharmony_ci /* 25978c2ecf20Sopenharmony_ci * Encrypting the root directory is not allowed because fsck 25988c2ecf20Sopenharmony_ci * expects lost+found directory to exist and remain unencrypted 25998c2ecf20Sopenharmony_ci * if LOST_FOUND feature is enabled. 26008c2ecf20Sopenharmony_ci * 26018c2ecf20Sopenharmony_ci */ 26028c2ecf20Sopenharmony_ci if (f2fs_sb_has_lost_found(sbi) && 26038c2ecf20Sopenharmony_ci inode->i_ino == F2FS_ROOT_INO(sbi)) 26048c2ecf20Sopenharmony_ci return -EPERM; 26058c2ecf20Sopenharmony_ci 26068c2ecf20Sopenharmony_ci return f2fs_setxattr(inode, F2FS_XATTR_INDEX_ENCRYPTION, 26078c2ecf20Sopenharmony_ci F2FS_XATTR_NAME_ENCRYPTION_CONTEXT, 26088c2ecf20Sopenharmony_ci ctx, len, fs_data, XATTR_CREATE); 26098c2ecf20Sopenharmony_ci} 26108c2ecf20Sopenharmony_ci 26118c2ecf20Sopenharmony_cistatic const union fscrypt_policy *f2fs_get_dummy_policy(struct super_block *sb) 26128c2ecf20Sopenharmony_ci{ 26138c2ecf20Sopenharmony_ci return F2FS_OPTION(F2FS_SB(sb)).dummy_enc_policy.policy; 26148c2ecf20Sopenharmony_ci} 26158c2ecf20Sopenharmony_ci 26168c2ecf20Sopenharmony_cistatic bool f2fs_has_stable_inodes(struct super_block *sb) 26178c2ecf20Sopenharmony_ci{ 26188c2ecf20Sopenharmony_ci return true; 26198c2ecf20Sopenharmony_ci} 26208c2ecf20Sopenharmony_ci 26218c2ecf20Sopenharmony_cistatic void f2fs_get_ino_and_lblk_bits(struct super_block *sb, 26228c2ecf20Sopenharmony_ci int *ino_bits_ret, int *lblk_bits_ret) 26238c2ecf20Sopenharmony_ci{ 26248c2ecf20Sopenharmony_ci *ino_bits_ret = 8 * sizeof(nid_t); 26258c2ecf20Sopenharmony_ci *lblk_bits_ret = 8 * sizeof(block_t); 26268c2ecf20Sopenharmony_ci} 26278c2ecf20Sopenharmony_ci 26288c2ecf20Sopenharmony_cistatic int f2fs_get_num_devices(struct super_block *sb) 26298c2ecf20Sopenharmony_ci{ 26308c2ecf20Sopenharmony_ci struct f2fs_sb_info *sbi = F2FS_SB(sb); 26318c2ecf20Sopenharmony_ci 26328c2ecf20Sopenharmony_ci if (f2fs_is_multi_device(sbi)) 26338c2ecf20Sopenharmony_ci return sbi->s_ndevs; 26348c2ecf20Sopenharmony_ci return 1; 26358c2ecf20Sopenharmony_ci} 26368c2ecf20Sopenharmony_ci 26378c2ecf20Sopenharmony_cistatic void f2fs_get_devices(struct super_block *sb, 26388c2ecf20Sopenharmony_ci struct request_queue **devs) 26398c2ecf20Sopenharmony_ci{ 26408c2ecf20Sopenharmony_ci struct f2fs_sb_info *sbi = F2FS_SB(sb); 26418c2ecf20Sopenharmony_ci int i; 26428c2ecf20Sopenharmony_ci 26438c2ecf20Sopenharmony_ci for (i = 0; i < sbi->s_ndevs; i++) 26448c2ecf20Sopenharmony_ci devs[i] = bdev_get_queue(FDEV(i).bdev); 26458c2ecf20Sopenharmony_ci} 26468c2ecf20Sopenharmony_ci 26478c2ecf20Sopenharmony_cistatic const struct fscrypt_operations f2fs_cryptops = { 26488c2ecf20Sopenharmony_ci .key_prefix = "f2fs:", 26498c2ecf20Sopenharmony_ci .get_context = f2fs_get_context, 26508c2ecf20Sopenharmony_ci .set_context = f2fs_set_context, 26518c2ecf20Sopenharmony_ci .get_dummy_policy = f2fs_get_dummy_policy, 26528c2ecf20Sopenharmony_ci .empty_dir = f2fs_empty_dir, 26538c2ecf20Sopenharmony_ci .max_namelen = F2FS_NAME_LEN, 26548c2ecf20Sopenharmony_ci .has_stable_inodes = f2fs_has_stable_inodes, 26558c2ecf20Sopenharmony_ci .get_ino_and_lblk_bits = f2fs_get_ino_and_lblk_bits, 26568c2ecf20Sopenharmony_ci .get_num_devices = f2fs_get_num_devices, 26578c2ecf20Sopenharmony_ci .get_devices = f2fs_get_devices, 26588c2ecf20Sopenharmony_ci}; 26598c2ecf20Sopenharmony_ci#endif 26608c2ecf20Sopenharmony_ci 26618c2ecf20Sopenharmony_cistatic struct inode *f2fs_nfs_get_inode(struct super_block *sb, 26628c2ecf20Sopenharmony_ci u64 ino, u32 generation) 26638c2ecf20Sopenharmony_ci{ 26648c2ecf20Sopenharmony_ci struct f2fs_sb_info *sbi = F2FS_SB(sb); 26658c2ecf20Sopenharmony_ci struct inode *inode; 26668c2ecf20Sopenharmony_ci 26678c2ecf20Sopenharmony_ci if (f2fs_check_nid_range(sbi, ino)) 26688c2ecf20Sopenharmony_ci return ERR_PTR(-ESTALE); 26698c2ecf20Sopenharmony_ci 26708c2ecf20Sopenharmony_ci /* 26718c2ecf20Sopenharmony_ci * f2fs_iget isn't quite right if the inode is currently unallocated! 26728c2ecf20Sopenharmony_ci * However f2fs_iget currently does appropriate checks to handle stale 26738c2ecf20Sopenharmony_ci * inodes so everything is OK. 26748c2ecf20Sopenharmony_ci */ 26758c2ecf20Sopenharmony_ci inode = f2fs_iget(sb, ino); 26768c2ecf20Sopenharmony_ci if (IS_ERR(inode)) 26778c2ecf20Sopenharmony_ci return ERR_CAST(inode); 26788c2ecf20Sopenharmony_ci if (unlikely(generation && inode->i_generation != generation)) { 26798c2ecf20Sopenharmony_ci /* we didn't find the right inode.. */ 26808c2ecf20Sopenharmony_ci iput(inode); 26818c2ecf20Sopenharmony_ci return ERR_PTR(-ESTALE); 26828c2ecf20Sopenharmony_ci } 26838c2ecf20Sopenharmony_ci return inode; 26848c2ecf20Sopenharmony_ci} 26858c2ecf20Sopenharmony_ci 26868c2ecf20Sopenharmony_cistatic struct dentry *f2fs_fh_to_dentry(struct super_block *sb, struct fid *fid, 26878c2ecf20Sopenharmony_ci int fh_len, int fh_type) 26888c2ecf20Sopenharmony_ci{ 26898c2ecf20Sopenharmony_ci return generic_fh_to_dentry(sb, fid, fh_len, fh_type, 26908c2ecf20Sopenharmony_ci f2fs_nfs_get_inode); 26918c2ecf20Sopenharmony_ci} 26928c2ecf20Sopenharmony_ci 26938c2ecf20Sopenharmony_cistatic struct dentry *f2fs_fh_to_parent(struct super_block *sb, struct fid *fid, 26948c2ecf20Sopenharmony_ci int fh_len, int fh_type) 26958c2ecf20Sopenharmony_ci{ 26968c2ecf20Sopenharmony_ci return generic_fh_to_parent(sb, fid, fh_len, fh_type, 26978c2ecf20Sopenharmony_ci f2fs_nfs_get_inode); 26988c2ecf20Sopenharmony_ci} 26998c2ecf20Sopenharmony_ci 27008c2ecf20Sopenharmony_cistatic const struct export_operations f2fs_export_ops = { 27018c2ecf20Sopenharmony_ci .fh_to_dentry = f2fs_fh_to_dentry, 27028c2ecf20Sopenharmony_ci .fh_to_parent = f2fs_fh_to_parent, 27038c2ecf20Sopenharmony_ci .get_parent = f2fs_get_parent, 27048c2ecf20Sopenharmony_ci}; 27058c2ecf20Sopenharmony_ci 27068c2ecf20Sopenharmony_cistatic loff_t max_file_blocks(void) 27078c2ecf20Sopenharmony_ci{ 27088c2ecf20Sopenharmony_ci loff_t result = 0; 27098c2ecf20Sopenharmony_ci loff_t leaf_count = DEF_ADDRS_PER_BLOCK; 27108c2ecf20Sopenharmony_ci 27118c2ecf20Sopenharmony_ci /* 27128c2ecf20Sopenharmony_ci * note: previously, result is equal to (DEF_ADDRS_PER_INODE - 27138c2ecf20Sopenharmony_ci * DEFAULT_INLINE_XATTR_ADDRS), but now f2fs try to reserve more 27148c2ecf20Sopenharmony_ci * space in inode.i_addr, it will be more safe to reassign 27158c2ecf20Sopenharmony_ci * result as zero. 27168c2ecf20Sopenharmony_ci */ 27178c2ecf20Sopenharmony_ci 27188c2ecf20Sopenharmony_ci /* two direct node blocks */ 27198c2ecf20Sopenharmony_ci result += (leaf_count * 2); 27208c2ecf20Sopenharmony_ci 27218c2ecf20Sopenharmony_ci /* two indirect node blocks */ 27228c2ecf20Sopenharmony_ci leaf_count *= NIDS_PER_BLOCK; 27238c2ecf20Sopenharmony_ci result += (leaf_count * 2); 27248c2ecf20Sopenharmony_ci 27258c2ecf20Sopenharmony_ci /* one double indirect node block */ 27268c2ecf20Sopenharmony_ci leaf_count *= NIDS_PER_BLOCK; 27278c2ecf20Sopenharmony_ci result += leaf_count; 27288c2ecf20Sopenharmony_ci 27298c2ecf20Sopenharmony_ci return result; 27308c2ecf20Sopenharmony_ci} 27318c2ecf20Sopenharmony_ci 27328c2ecf20Sopenharmony_cistatic int __f2fs_commit_super(struct buffer_head *bh, 27338c2ecf20Sopenharmony_ci struct f2fs_super_block *super) 27348c2ecf20Sopenharmony_ci{ 27358c2ecf20Sopenharmony_ci lock_buffer(bh); 27368c2ecf20Sopenharmony_ci if (super) 27378c2ecf20Sopenharmony_ci memcpy(bh->b_data + F2FS_SUPER_OFFSET, super, sizeof(*super)); 27388c2ecf20Sopenharmony_ci set_buffer_dirty(bh); 27398c2ecf20Sopenharmony_ci unlock_buffer(bh); 27408c2ecf20Sopenharmony_ci 27418c2ecf20Sopenharmony_ci /* it's rare case, we can do fua all the time */ 27428c2ecf20Sopenharmony_ci return __sync_dirty_buffer(bh, REQ_SYNC | REQ_PREFLUSH | REQ_FUA); 27438c2ecf20Sopenharmony_ci} 27448c2ecf20Sopenharmony_ci 27458c2ecf20Sopenharmony_cistatic inline bool sanity_check_area_boundary(struct f2fs_sb_info *sbi, 27468c2ecf20Sopenharmony_ci struct buffer_head *bh) 27478c2ecf20Sopenharmony_ci{ 27488c2ecf20Sopenharmony_ci struct f2fs_super_block *raw_super = (struct f2fs_super_block *) 27498c2ecf20Sopenharmony_ci (bh->b_data + F2FS_SUPER_OFFSET); 27508c2ecf20Sopenharmony_ci struct super_block *sb = sbi->sb; 27518c2ecf20Sopenharmony_ci u32 segment0_blkaddr = le32_to_cpu(raw_super->segment0_blkaddr); 27528c2ecf20Sopenharmony_ci u32 cp_blkaddr = le32_to_cpu(raw_super->cp_blkaddr); 27538c2ecf20Sopenharmony_ci u32 sit_blkaddr = le32_to_cpu(raw_super->sit_blkaddr); 27548c2ecf20Sopenharmony_ci u32 nat_blkaddr = le32_to_cpu(raw_super->nat_blkaddr); 27558c2ecf20Sopenharmony_ci u32 ssa_blkaddr = le32_to_cpu(raw_super->ssa_blkaddr); 27568c2ecf20Sopenharmony_ci u32 main_blkaddr = le32_to_cpu(raw_super->main_blkaddr); 27578c2ecf20Sopenharmony_ci u32 segment_count_ckpt = le32_to_cpu(raw_super->segment_count_ckpt); 27588c2ecf20Sopenharmony_ci u32 segment_count_sit = le32_to_cpu(raw_super->segment_count_sit); 27598c2ecf20Sopenharmony_ci u32 segment_count_nat = le32_to_cpu(raw_super->segment_count_nat); 27608c2ecf20Sopenharmony_ci u32 segment_count_ssa = le32_to_cpu(raw_super->segment_count_ssa); 27618c2ecf20Sopenharmony_ci u32 segment_count_main = le32_to_cpu(raw_super->segment_count_main); 27628c2ecf20Sopenharmony_ci u32 segment_count = le32_to_cpu(raw_super->segment_count); 27638c2ecf20Sopenharmony_ci u32 log_blocks_per_seg = le32_to_cpu(raw_super->log_blocks_per_seg); 27648c2ecf20Sopenharmony_ci u64 main_end_blkaddr = main_blkaddr + 27658c2ecf20Sopenharmony_ci (segment_count_main << log_blocks_per_seg); 27668c2ecf20Sopenharmony_ci u64 seg_end_blkaddr = segment0_blkaddr + 27678c2ecf20Sopenharmony_ci (segment_count << log_blocks_per_seg); 27688c2ecf20Sopenharmony_ci 27698c2ecf20Sopenharmony_ci if (segment0_blkaddr != cp_blkaddr) { 27708c2ecf20Sopenharmony_ci f2fs_info(sbi, "Mismatch start address, segment0(%u) cp_blkaddr(%u)", 27718c2ecf20Sopenharmony_ci segment0_blkaddr, cp_blkaddr); 27728c2ecf20Sopenharmony_ci return true; 27738c2ecf20Sopenharmony_ci } 27748c2ecf20Sopenharmony_ci 27758c2ecf20Sopenharmony_ci if (cp_blkaddr + (segment_count_ckpt << log_blocks_per_seg) != 27768c2ecf20Sopenharmony_ci sit_blkaddr) { 27778c2ecf20Sopenharmony_ci f2fs_info(sbi, "Wrong CP boundary, start(%u) end(%u) blocks(%u)", 27788c2ecf20Sopenharmony_ci cp_blkaddr, sit_blkaddr, 27798c2ecf20Sopenharmony_ci segment_count_ckpt << log_blocks_per_seg); 27808c2ecf20Sopenharmony_ci return true; 27818c2ecf20Sopenharmony_ci } 27828c2ecf20Sopenharmony_ci 27838c2ecf20Sopenharmony_ci if (sit_blkaddr + (segment_count_sit << log_blocks_per_seg) != 27848c2ecf20Sopenharmony_ci nat_blkaddr) { 27858c2ecf20Sopenharmony_ci f2fs_info(sbi, "Wrong SIT boundary, start(%u) end(%u) blocks(%u)", 27868c2ecf20Sopenharmony_ci sit_blkaddr, nat_blkaddr, 27878c2ecf20Sopenharmony_ci segment_count_sit << log_blocks_per_seg); 27888c2ecf20Sopenharmony_ci return true; 27898c2ecf20Sopenharmony_ci } 27908c2ecf20Sopenharmony_ci 27918c2ecf20Sopenharmony_ci if (nat_blkaddr + (segment_count_nat << log_blocks_per_seg) != 27928c2ecf20Sopenharmony_ci ssa_blkaddr) { 27938c2ecf20Sopenharmony_ci f2fs_info(sbi, "Wrong NAT boundary, start(%u) end(%u) blocks(%u)", 27948c2ecf20Sopenharmony_ci nat_blkaddr, ssa_blkaddr, 27958c2ecf20Sopenharmony_ci segment_count_nat << log_blocks_per_seg); 27968c2ecf20Sopenharmony_ci return true; 27978c2ecf20Sopenharmony_ci } 27988c2ecf20Sopenharmony_ci 27998c2ecf20Sopenharmony_ci if (ssa_blkaddr + (segment_count_ssa << log_blocks_per_seg) != 28008c2ecf20Sopenharmony_ci main_blkaddr) { 28018c2ecf20Sopenharmony_ci f2fs_info(sbi, "Wrong SSA boundary, start(%u) end(%u) blocks(%u)", 28028c2ecf20Sopenharmony_ci ssa_blkaddr, main_blkaddr, 28038c2ecf20Sopenharmony_ci segment_count_ssa << log_blocks_per_seg); 28048c2ecf20Sopenharmony_ci return true; 28058c2ecf20Sopenharmony_ci } 28068c2ecf20Sopenharmony_ci 28078c2ecf20Sopenharmony_ci if (main_end_blkaddr > seg_end_blkaddr) { 28088c2ecf20Sopenharmony_ci f2fs_info(sbi, "Wrong MAIN_AREA boundary, start(%u) end(%llu) block(%u)", 28098c2ecf20Sopenharmony_ci main_blkaddr, seg_end_blkaddr, 28108c2ecf20Sopenharmony_ci segment_count_main << log_blocks_per_seg); 28118c2ecf20Sopenharmony_ci return true; 28128c2ecf20Sopenharmony_ci } else if (main_end_blkaddr < seg_end_blkaddr) { 28138c2ecf20Sopenharmony_ci int err = 0; 28148c2ecf20Sopenharmony_ci char *res; 28158c2ecf20Sopenharmony_ci 28168c2ecf20Sopenharmony_ci /* fix in-memory information all the time */ 28178c2ecf20Sopenharmony_ci raw_super->segment_count = cpu_to_le32((main_end_blkaddr - 28188c2ecf20Sopenharmony_ci segment0_blkaddr) >> log_blocks_per_seg); 28198c2ecf20Sopenharmony_ci 28208c2ecf20Sopenharmony_ci if (f2fs_readonly(sb) || bdev_read_only(sb->s_bdev)) { 28218c2ecf20Sopenharmony_ci set_sbi_flag(sbi, SBI_NEED_SB_WRITE); 28228c2ecf20Sopenharmony_ci res = "internally"; 28238c2ecf20Sopenharmony_ci } else { 28248c2ecf20Sopenharmony_ci err = __f2fs_commit_super(bh, NULL); 28258c2ecf20Sopenharmony_ci res = err ? "failed" : "done"; 28268c2ecf20Sopenharmony_ci } 28278c2ecf20Sopenharmony_ci f2fs_info(sbi, "Fix alignment : %s, start(%u) end(%llu) block(%u)", 28288c2ecf20Sopenharmony_ci res, main_blkaddr, seg_end_blkaddr, 28298c2ecf20Sopenharmony_ci segment_count_main << log_blocks_per_seg); 28308c2ecf20Sopenharmony_ci if (err) 28318c2ecf20Sopenharmony_ci return true; 28328c2ecf20Sopenharmony_ci } 28338c2ecf20Sopenharmony_ci return false; 28348c2ecf20Sopenharmony_ci} 28358c2ecf20Sopenharmony_ci 28368c2ecf20Sopenharmony_cistatic int sanity_check_raw_super(struct f2fs_sb_info *sbi, 28378c2ecf20Sopenharmony_ci struct buffer_head *bh) 28388c2ecf20Sopenharmony_ci{ 28398c2ecf20Sopenharmony_ci block_t segment_count, segs_per_sec, secs_per_zone, segment_count_main; 28408c2ecf20Sopenharmony_ci block_t total_sections, blocks_per_seg; 28418c2ecf20Sopenharmony_ci struct f2fs_super_block *raw_super = (struct f2fs_super_block *) 28428c2ecf20Sopenharmony_ci (bh->b_data + F2FS_SUPER_OFFSET); 28438c2ecf20Sopenharmony_ci size_t crc_offset = 0; 28448c2ecf20Sopenharmony_ci __u32 crc = 0; 28458c2ecf20Sopenharmony_ci 28468c2ecf20Sopenharmony_ci if (le32_to_cpu(raw_super->magic) != F2FS_SUPER_MAGIC) { 28478c2ecf20Sopenharmony_ci f2fs_info(sbi, "Magic Mismatch, valid(0x%x) - read(0x%x)", 28488c2ecf20Sopenharmony_ci F2FS_SUPER_MAGIC, le32_to_cpu(raw_super->magic)); 28498c2ecf20Sopenharmony_ci return -EINVAL; 28508c2ecf20Sopenharmony_ci } 28518c2ecf20Sopenharmony_ci 28528c2ecf20Sopenharmony_ci /* Check checksum_offset and crc in superblock */ 28538c2ecf20Sopenharmony_ci if (__F2FS_HAS_FEATURE(raw_super, F2FS_FEATURE_SB_CHKSUM)) { 28548c2ecf20Sopenharmony_ci crc_offset = le32_to_cpu(raw_super->checksum_offset); 28558c2ecf20Sopenharmony_ci if (crc_offset != 28568c2ecf20Sopenharmony_ci offsetof(struct f2fs_super_block, crc)) { 28578c2ecf20Sopenharmony_ci f2fs_info(sbi, "Invalid SB checksum offset: %zu", 28588c2ecf20Sopenharmony_ci crc_offset); 28598c2ecf20Sopenharmony_ci return -EFSCORRUPTED; 28608c2ecf20Sopenharmony_ci } 28618c2ecf20Sopenharmony_ci crc = le32_to_cpu(raw_super->crc); 28628c2ecf20Sopenharmony_ci if (!f2fs_crc_valid(sbi, crc, raw_super, crc_offset)) { 28638c2ecf20Sopenharmony_ci f2fs_info(sbi, "Invalid SB checksum value: %u", crc); 28648c2ecf20Sopenharmony_ci return -EFSCORRUPTED; 28658c2ecf20Sopenharmony_ci } 28668c2ecf20Sopenharmony_ci } 28678c2ecf20Sopenharmony_ci 28688c2ecf20Sopenharmony_ci /* Currently, support only 4KB page cache size */ 28698c2ecf20Sopenharmony_ci if (F2FS_BLKSIZE != PAGE_SIZE) { 28708c2ecf20Sopenharmony_ci f2fs_info(sbi, "Invalid page_cache_size (%lu), supports only 4KB", 28718c2ecf20Sopenharmony_ci PAGE_SIZE); 28728c2ecf20Sopenharmony_ci return -EFSCORRUPTED; 28738c2ecf20Sopenharmony_ci } 28748c2ecf20Sopenharmony_ci 28758c2ecf20Sopenharmony_ci /* Currently, support only 4KB block size */ 28768c2ecf20Sopenharmony_ci if (le32_to_cpu(raw_super->log_blocksize) != F2FS_BLKSIZE_BITS) { 28778c2ecf20Sopenharmony_ci f2fs_info(sbi, "Invalid log_blocksize (%u), supports only %u", 28788c2ecf20Sopenharmony_ci le32_to_cpu(raw_super->log_blocksize), 28798c2ecf20Sopenharmony_ci F2FS_BLKSIZE_BITS); 28808c2ecf20Sopenharmony_ci return -EFSCORRUPTED; 28818c2ecf20Sopenharmony_ci } 28828c2ecf20Sopenharmony_ci 28838c2ecf20Sopenharmony_ci /* check log blocks per segment */ 28848c2ecf20Sopenharmony_ci if (le32_to_cpu(raw_super->log_blocks_per_seg) != 9) { 28858c2ecf20Sopenharmony_ci f2fs_info(sbi, "Invalid log blocks per segment (%u)", 28868c2ecf20Sopenharmony_ci le32_to_cpu(raw_super->log_blocks_per_seg)); 28878c2ecf20Sopenharmony_ci return -EFSCORRUPTED; 28888c2ecf20Sopenharmony_ci } 28898c2ecf20Sopenharmony_ci 28908c2ecf20Sopenharmony_ci /* Currently, support 512/1024/2048/4096 bytes sector size */ 28918c2ecf20Sopenharmony_ci if (le32_to_cpu(raw_super->log_sectorsize) > 28928c2ecf20Sopenharmony_ci F2FS_MAX_LOG_SECTOR_SIZE || 28938c2ecf20Sopenharmony_ci le32_to_cpu(raw_super->log_sectorsize) < 28948c2ecf20Sopenharmony_ci F2FS_MIN_LOG_SECTOR_SIZE) { 28958c2ecf20Sopenharmony_ci f2fs_info(sbi, "Invalid log sectorsize (%u)", 28968c2ecf20Sopenharmony_ci le32_to_cpu(raw_super->log_sectorsize)); 28978c2ecf20Sopenharmony_ci return -EFSCORRUPTED; 28988c2ecf20Sopenharmony_ci } 28998c2ecf20Sopenharmony_ci if (le32_to_cpu(raw_super->log_sectors_per_block) + 29008c2ecf20Sopenharmony_ci le32_to_cpu(raw_super->log_sectorsize) != 29018c2ecf20Sopenharmony_ci F2FS_MAX_LOG_SECTOR_SIZE) { 29028c2ecf20Sopenharmony_ci f2fs_info(sbi, "Invalid log sectors per block(%u) log sectorsize(%u)", 29038c2ecf20Sopenharmony_ci le32_to_cpu(raw_super->log_sectors_per_block), 29048c2ecf20Sopenharmony_ci le32_to_cpu(raw_super->log_sectorsize)); 29058c2ecf20Sopenharmony_ci return -EFSCORRUPTED; 29068c2ecf20Sopenharmony_ci } 29078c2ecf20Sopenharmony_ci 29088c2ecf20Sopenharmony_ci segment_count = le32_to_cpu(raw_super->segment_count); 29098c2ecf20Sopenharmony_ci segment_count_main = le32_to_cpu(raw_super->segment_count_main); 29108c2ecf20Sopenharmony_ci segs_per_sec = le32_to_cpu(raw_super->segs_per_sec); 29118c2ecf20Sopenharmony_ci secs_per_zone = le32_to_cpu(raw_super->secs_per_zone); 29128c2ecf20Sopenharmony_ci total_sections = le32_to_cpu(raw_super->section_count); 29138c2ecf20Sopenharmony_ci 29148c2ecf20Sopenharmony_ci /* blocks_per_seg should be 512, given the above check */ 29158c2ecf20Sopenharmony_ci blocks_per_seg = 1 << le32_to_cpu(raw_super->log_blocks_per_seg); 29168c2ecf20Sopenharmony_ci 29178c2ecf20Sopenharmony_ci if (segment_count > F2FS_MAX_SEGMENT || 29188c2ecf20Sopenharmony_ci segment_count < F2FS_MIN_SEGMENTS) { 29198c2ecf20Sopenharmony_ci f2fs_info(sbi, "Invalid segment count (%u)", segment_count); 29208c2ecf20Sopenharmony_ci return -EFSCORRUPTED; 29218c2ecf20Sopenharmony_ci } 29228c2ecf20Sopenharmony_ci 29238c2ecf20Sopenharmony_ci if (total_sections > segment_count_main || total_sections < 1 || 29248c2ecf20Sopenharmony_ci segs_per_sec > segment_count || !segs_per_sec) { 29258c2ecf20Sopenharmony_ci f2fs_info(sbi, "Invalid segment/section count (%u, %u x %u)", 29268c2ecf20Sopenharmony_ci segment_count, total_sections, segs_per_sec); 29278c2ecf20Sopenharmony_ci return -EFSCORRUPTED; 29288c2ecf20Sopenharmony_ci } 29298c2ecf20Sopenharmony_ci 29308c2ecf20Sopenharmony_ci if (segment_count_main != total_sections * segs_per_sec) { 29318c2ecf20Sopenharmony_ci f2fs_info(sbi, "Invalid segment/section count (%u != %u * %u)", 29328c2ecf20Sopenharmony_ci segment_count_main, total_sections, segs_per_sec); 29338c2ecf20Sopenharmony_ci return -EFSCORRUPTED; 29348c2ecf20Sopenharmony_ci } 29358c2ecf20Sopenharmony_ci 29368c2ecf20Sopenharmony_ci if ((segment_count / segs_per_sec) < total_sections) { 29378c2ecf20Sopenharmony_ci f2fs_info(sbi, "Small segment_count (%u < %u * %u)", 29388c2ecf20Sopenharmony_ci segment_count, segs_per_sec, total_sections); 29398c2ecf20Sopenharmony_ci return -EFSCORRUPTED; 29408c2ecf20Sopenharmony_ci } 29418c2ecf20Sopenharmony_ci 29428c2ecf20Sopenharmony_ci if (segment_count > (le64_to_cpu(raw_super->block_count) >> 9)) { 29438c2ecf20Sopenharmony_ci f2fs_info(sbi, "Wrong segment_count / block_count (%u > %llu)", 29448c2ecf20Sopenharmony_ci segment_count, le64_to_cpu(raw_super->block_count)); 29458c2ecf20Sopenharmony_ci return -EFSCORRUPTED; 29468c2ecf20Sopenharmony_ci } 29478c2ecf20Sopenharmony_ci 29488c2ecf20Sopenharmony_ci if (RDEV(0).path[0]) { 29498c2ecf20Sopenharmony_ci block_t dev_seg_count = le32_to_cpu(RDEV(0).total_segments); 29508c2ecf20Sopenharmony_ci int i = 1; 29518c2ecf20Sopenharmony_ci 29528c2ecf20Sopenharmony_ci while (i < MAX_DEVICES && RDEV(i).path[0]) { 29538c2ecf20Sopenharmony_ci dev_seg_count += le32_to_cpu(RDEV(i).total_segments); 29548c2ecf20Sopenharmony_ci i++; 29558c2ecf20Sopenharmony_ci } 29568c2ecf20Sopenharmony_ci if (segment_count != dev_seg_count) { 29578c2ecf20Sopenharmony_ci f2fs_info(sbi, "Segment count (%u) mismatch with total segments from devices (%u)", 29588c2ecf20Sopenharmony_ci segment_count, dev_seg_count); 29598c2ecf20Sopenharmony_ci return -EFSCORRUPTED; 29608c2ecf20Sopenharmony_ci } 29618c2ecf20Sopenharmony_ci } else { 29628c2ecf20Sopenharmony_ci if (__F2FS_HAS_FEATURE(raw_super, F2FS_FEATURE_BLKZONED) && 29638c2ecf20Sopenharmony_ci !bdev_is_zoned(sbi->sb->s_bdev)) { 29648c2ecf20Sopenharmony_ci f2fs_info(sbi, "Zoned block device path is missing"); 29658c2ecf20Sopenharmony_ci return -EFSCORRUPTED; 29668c2ecf20Sopenharmony_ci } 29678c2ecf20Sopenharmony_ci } 29688c2ecf20Sopenharmony_ci 29698c2ecf20Sopenharmony_ci if (secs_per_zone > total_sections || !secs_per_zone) { 29708c2ecf20Sopenharmony_ci f2fs_info(sbi, "Wrong secs_per_zone / total_sections (%u, %u)", 29718c2ecf20Sopenharmony_ci secs_per_zone, total_sections); 29728c2ecf20Sopenharmony_ci return -EFSCORRUPTED; 29738c2ecf20Sopenharmony_ci } 29748c2ecf20Sopenharmony_ci if (le32_to_cpu(raw_super->extension_count) > F2FS_MAX_EXTENSION || 29758c2ecf20Sopenharmony_ci raw_super->hot_ext_count > F2FS_MAX_EXTENSION || 29768c2ecf20Sopenharmony_ci (le32_to_cpu(raw_super->extension_count) + 29778c2ecf20Sopenharmony_ci raw_super->hot_ext_count) > F2FS_MAX_EXTENSION) { 29788c2ecf20Sopenharmony_ci f2fs_info(sbi, "Corrupted extension count (%u + %u > %u)", 29798c2ecf20Sopenharmony_ci le32_to_cpu(raw_super->extension_count), 29808c2ecf20Sopenharmony_ci raw_super->hot_ext_count, 29818c2ecf20Sopenharmony_ci F2FS_MAX_EXTENSION); 29828c2ecf20Sopenharmony_ci return -EFSCORRUPTED; 29838c2ecf20Sopenharmony_ci } 29848c2ecf20Sopenharmony_ci 29858c2ecf20Sopenharmony_ci if (le32_to_cpu(raw_super->cp_payload) >= 29868c2ecf20Sopenharmony_ci (blocks_per_seg - F2FS_CP_PACKS - 29878c2ecf20Sopenharmony_ci NR_CURSEG_PERSIST_TYPE)) { 29888c2ecf20Sopenharmony_ci f2fs_info(sbi, "Insane cp_payload (%u >= %u)", 29898c2ecf20Sopenharmony_ci le32_to_cpu(raw_super->cp_payload), 29908c2ecf20Sopenharmony_ci blocks_per_seg - F2FS_CP_PACKS - 29918c2ecf20Sopenharmony_ci NR_CURSEG_PERSIST_TYPE); 29928c2ecf20Sopenharmony_ci return -EFSCORRUPTED; 29938c2ecf20Sopenharmony_ci } 29948c2ecf20Sopenharmony_ci 29958c2ecf20Sopenharmony_ci /* check reserved ino info */ 29968c2ecf20Sopenharmony_ci if (le32_to_cpu(raw_super->node_ino) != 1 || 29978c2ecf20Sopenharmony_ci le32_to_cpu(raw_super->meta_ino) != 2 || 29988c2ecf20Sopenharmony_ci le32_to_cpu(raw_super->root_ino) != 3) { 29998c2ecf20Sopenharmony_ci f2fs_info(sbi, "Invalid Fs Meta Ino: node(%u) meta(%u) root(%u)", 30008c2ecf20Sopenharmony_ci le32_to_cpu(raw_super->node_ino), 30018c2ecf20Sopenharmony_ci le32_to_cpu(raw_super->meta_ino), 30028c2ecf20Sopenharmony_ci le32_to_cpu(raw_super->root_ino)); 30038c2ecf20Sopenharmony_ci return -EFSCORRUPTED; 30048c2ecf20Sopenharmony_ci } 30058c2ecf20Sopenharmony_ci 30068c2ecf20Sopenharmony_ci /* check CP/SIT/NAT/SSA/MAIN_AREA area boundary */ 30078c2ecf20Sopenharmony_ci if (sanity_check_area_boundary(sbi, bh)) 30088c2ecf20Sopenharmony_ci return -EFSCORRUPTED; 30098c2ecf20Sopenharmony_ci 30108c2ecf20Sopenharmony_ci return 0; 30118c2ecf20Sopenharmony_ci} 30128c2ecf20Sopenharmony_ci 30138c2ecf20Sopenharmony_ciint f2fs_sanity_check_ckpt(struct f2fs_sb_info *sbi) 30148c2ecf20Sopenharmony_ci{ 30158c2ecf20Sopenharmony_ci unsigned int total, fsmeta; 30168c2ecf20Sopenharmony_ci struct f2fs_super_block *raw_super = F2FS_RAW_SUPER(sbi); 30178c2ecf20Sopenharmony_ci struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi); 30188c2ecf20Sopenharmony_ci unsigned int ovp_segments, reserved_segments; 30198c2ecf20Sopenharmony_ci unsigned int main_segs, blocks_per_seg; 30208c2ecf20Sopenharmony_ci unsigned int sit_segs, nat_segs; 30218c2ecf20Sopenharmony_ci unsigned int sit_bitmap_size, nat_bitmap_size; 30228c2ecf20Sopenharmony_ci unsigned int log_blocks_per_seg; 30238c2ecf20Sopenharmony_ci unsigned int segment_count_main; 30248c2ecf20Sopenharmony_ci unsigned int cp_pack_start_sum, cp_payload; 30258c2ecf20Sopenharmony_ci block_t user_block_count, valid_user_blocks; 30268c2ecf20Sopenharmony_ci block_t avail_node_count, valid_node_count; 30278c2ecf20Sopenharmony_ci unsigned int nat_blocks, nat_bits_bytes, nat_bits_blocks; 30288c2ecf20Sopenharmony_ci int i, j; 30298c2ecf20Sopenharmony_ci 30308c2ecf20Sopenharmony_ci total = le32_to_cpu(raw_super->segment_count); 30318c2ecf20Sopenharmony_ci fsmeta = le32_to_cpu(raw_super->segment_count_ckpt); 30328c2ecf20Sopenharmony_ci sit_segs = le32_to_cpu(raw_super->segment_count_sit); 30338c2ecf20Sopenharmony_ci fsmeta += sit_segs; 30348c2ecf20Sopenharmony_ci nat_segs = le32_to_cpu(raw_super->segment_count_nat); 30358c2ecf20Sopenharmony_ci fsmeta += nat_segs; 30368c2ecf20Sopenharmony_ci fsmeta += le32_to_cpu(ckpt->rsvd_segment_count); 30378c2ecf20Sopenharmony_ci fsmeta += le32_to_cpu(raw_super->segment_count_ssa); 30388c2ecf20Sopenharmony_ci 30398c2ecf20Sopenharmony_ci if (unlikely(fsmeta >= total)) 30408c2ecf20Sopenharmony_ci return 1; 30418c2ecf20Sopenharmony_ci 30428c2ecf20Sopenharmony_ci ovp_segments = le32_to_cpu(ckpt->overprov_segment_count); 30438c2ecf20Sopenharmony_ci reserved_segments = le32_to_cpu(ckpt->rsvd_segment_count); 30448c2ecf20Sopenharmony_ci 30458c2ecf20Sopenharmony_ci if (unlikely(fsmeta < F2FS_MIN_META_SEGMENTS || 30468c2ecf20Sopenharmony_ci ovp_segments == 0 || reserved_segments == 0)) { 30478c2ecf20Sopenharmony_ci f2fs_err(sbi, "Wrong layout: check mkfs.f2fs version"); 30488c2ecf20Sopenharmony_ci return 1; 30498c2ecf20Sopenharmony_ci } 30508c2ecf20Sopenharmony_ci 30518c2ecf20Sopenharmony_ci user_block_count = le64_to_cpu(ckpt->user_block_count); 30528c2ecf20Sopenharmony_ci segment_count_main = le32_to_cpu(raw_super->segment_count_main); 30538c2ecf20Sopenharmony_ci log_blocks_per_seg = le32_to_cpu(raw_super->log_blocks_per_seg); 30548c2ecf20Sopenharmony_ci if (!user_block_count || user_block_count >= 30558c2ecf20Sopenharmony_ci segment_count_main << log_blocks_per_seg) { 30568c2ecf20Sopenharmony_ci f2fs_err(sbi, "Wrong user_block_count: %u", 30578c2ecf20Sopenharmony_ci user_block_count); 30588c2ecf20Sopenharmony_ci return 1; 30598c2ecf20Sopenharmony_ci } 30608c2ecf20Sopenharmony_ci 30618c2ecf20Sopenharmony_ci valid_user_blocks = le64_to_cpu(ckpt->valid_block_count); 30628c2ecf20Sopenharmony_ci if (valid_user_blocks > user_block_count) { 30638c2ecf20Sopenharmony_ci f2fs_err(sbi, "Wrong valid_user_blocks: %u, user_block_count: %u", 30648c2ecf20Sopenharmony_ci valid_user_blocks, user_block_count); 30658c2ecf20Sopenharmony_ci return 1; 30668c2ecf20Sopenharmony_ci } 30678c2ecf20Sopenharmony_ci 30688c2ecf20Sopenharmony_ci valid_node_count = le32_to_cpu(ckpt->valid_node_count); 30698c2ecf20Sopenharmony_ci avail_node_count = sbi->total_node_count - F2FS_RESERVED_NODE_NUM; 30708c2ecf20Sopenharmony_ci if (valid_node_count > avail_node_count) { 30718c2ecf20Sopenharmony_ci f2fs_err(sbi, "Wrong valid_node_count: %u, avail_node_count: %u", 30728c2ecf20Sopenharmony_ci valid_node_count, avail_node_count); 30738c2ecf20Sopenharmony_ci return 1; 30748c2ecf20Sopenharmony_ci } 30758c2ecf20Sopenharmony_ci 30768c2ecf20Sopenharmony_ci main_segs = le32_to_cpu(raw_super->segment_count_main); 30778c2ecf20Sopenharmony_ci blocks_per_seg = sbi->blocks_per_seg; 30788c2ecf20Sopenharmony_ci 30798c2ecf20Sopenharmony_ci for (i = 0; i < NR_CURSEG_NODE_TYPE; i++) { 30808c2ecf20Sopenharmony_ci if (le32_to_cpu(ckpt->cur_node_segno[i]) >= main_segs || 30818c2ecf20Sopenharmony_ci le16_to_cpu(ckpt->cur_node_blkoff[i]) >= blocks_per_seg) 30828c2ecf20Sopenharmony_ci return 1; 30838c2ecf20Sopenharmony_ci for (j = i + 1; j < NR_CURSEG_NODE_TYPE; j++) { 30848c2ecf20Sopenharmony_ci if (le32_to_cpu(ckpt->cur_node_segno[i]) == 30858c2ecf20Sopenharmony_ci le32_to_cpu(ckpt->cur_node_segno[j])) { 30868c2ecf20Sopenharmony_ci f2fs_err(sbi, "Node segment (%u, %u) has the same segno: %u", 30878c2ecf20Sopenharmony_ci i, j, 30888c2ecf20Sopenharmony_ci le32_to_cpu(ckpt->cur_node_segno[i])); 30898c2ecf20Sopenharmony_ci return 1; 30908c2ecf20Sopenharmony_ci } 30918c2ecf20Sopenharmony_ci } 30928c2ecf20Sopenharmony_ci } 30938c2ecf20Sopenharmony_ci for (i = 0; i < NR_CURSEG_DATA_TYPE; i++) { 30948c2ecf20Sopenharmony_ci if (le32_to_cpu(ckpt->cur_data_segno[i]) >= main_segs || 30958c2ecf20Sopenharmony_ci le16_to_cpu(ckpt->cur_data_blkoff[i]) >= blocks_per_seg) 30968c2ecf20Sopenharmony_ci return 1; 30978c2ecf20Sopenharmony_ci for (j = i + 1; j < NR_CURSEG_DATA_TYPE; j++) { 30988c2ecf20Sopenharmony_ci if (le32_to_cpu(ckpt->cur_data_segno[i]) == 30998c2ecf20Sopenharmony_ci le32_to_cpu(ckpt->cur_data_segno[j])) { 31008c2ecf20Sopenharmony_ci f2fs_err(sbi, "Data segment (%u, %u) has the same segno: %u", 31018c2ecf20Sopenharmony_ci i, j, 31028c2ecf20Sopenharmony_ci le32_to_cpu(ckpt->cur_data_segno[i])); 31038c2ecf20Sopenharmony_ci return 1; 31048c2ecf20Sopenharmony_ci } 31058c2ecf20Sopenharmony_ci } 31068c2ecf20Sopenharmony_ci } 31078c2ecf20Sopenharmony_ci for (i = 0; i < NR_CURSEG_NODE_TYPE; i++) { 31088c2ecf20Sopenharmony_ci for (j = 0; j < NR_CURSEG_DATA_TYPE; j++) { 31098c2ecf20Sopenharmony_ci if (le32_to_cpu(ckpt->cur_node_segno[i]) == 31108c2ecf20Sopenharmony_ci le32_to_cpu(ckpt->cur_data_segno[j])) { 31118c2ecf20Sopenharmony_ci f2fs_err(sbi, "Node segment (%u) and Data segment (%u) has the same segno: %u", 31128c2ecf20Sopenharmony_ci i, j, 31138c2ecf20Sopenharmony_ci le32_to_cpu(ckpt->cur_node_segno[i])); 31148c2ecf20Sopenharmony_ci return 1; 31158c2ecf20Sopenharmony_ci } 31168c2ecf20Sopenharmony_ci } 31178c2ecf20Sopenharmony_ci } 31188c2ecf20Sopenharmony_ci 31198c2ecf20Sopenharmony_ci sit_bitmap_size = le32_to_cpu(ckpt->sit_ver_bitmap_bytesize); 31208c2ecf20Sopenharmony_ci nat_bitmap_size = le32_to_cpu(ckpt->nat_ver_bitmap_bytesize); 31218c2ecf20Sopenharmony_ci 31228c2ecf20Sopenharmony_ci if (sit_bitmap_size != ((sit_segs / 2) << log_blocks_per_seg) / 8 || 31238c2ecf20Sopenharmony_ci nat_bitmap_size != ((nat_segs / 2) << log_blocks_per_seg) / 8) { 31248c2ecf20Sopenharmony_ci f2fs_err(sbi, "Wrong bitmap size: sit: %u, nat:%u", 31258c2ecf20Sopenharmony_ci sit_bitmap_size, nat_bitmap_size); 31268c2ecf20Sopenharmony_ci return 1; 31278c2ecf20Sopenharmony_ci } 31288c2ecf20Sopenharmony_ci 31298c2ecf20Sopenharmony_ci cp_pack_start_sum = __start_sum_addr(sbi); 31308c2ecf20Sopenharmony_ci cp_payload = __cp_payload(sbi); 31318c2ecf20Sopenharmony_ci if (cp_pack_start_sum < cp_payload + 1 || 31328c2ecf20Sopenharmony_ci cp_pack_start_sum > blocks_per_seg - 1 - 31338c2ecf20Sopenharmony_ci NR_CURSEG_PERSIST_TYPE) { 31348c2ecf20Sopenharmony_ci f2fs_err(sbi, "Wrong cp_pack_start_sum: %u", 31358c2ecf20Sopenharmony_ci cp_pack_start_sum); 31368c2ecf20Sopenharmony_ci return 1; 31378c2ecf20Sopenharmony_ci } 31388c2ecf20Sopenharmony_ci 31398c2ecf20Sopenharmony_ci if (__is_set_ckpt_flags(ckpt, CP_LARGE_NAT_BITMAP_FLAG) && 31408c2ecf20Sopenharmony_ci le32_to_cpu(ckpt->checksum_offset) != CP_MIN_CHKSUM_OFFSET) { 31418c2ecf20Sopenharmony_ci f2fs_warn(sbi, "using deprecated layout of large_nat_bitmap, " 31428c2ecf20Sopenharmony_ci "please run fsck v1.13.0 or higher to repair, chksum_offset: %u, " 31438c2ecf20Sopenharmony_ci "fixed with patch: \"f2fs-tools: relocate chksum_offset for large_nat_bitmap feature\"", 31448c2ecf20Sopenharmony_ci le32_to_cpu(ckpt->checksum_offset)); 31458c2ecf20Sopenharmony_ci return 1; 31468c2ecf20Sopenharmony_ci } 31478c2ecf20Sopenharmony_ci 31488c2ecf20Sopenharmony_ci nat_blocks = nat_segs << log_blocks_per_seg; 31498c2ecf20Sopenharmony_ci nat_bits_bytes = nat_blocks / BITS_PER_BYTE; 31508c2ecf20Sopenharmony_ci nat_bits_blocks = F2FS_BLK_ALIGN((nat_bits_bytes << 1) + 8); 31518c2ecf20Sopenharmony_ci if (__is_set_ckpt_flags(ckpt, CP_NAT_BITS_FLAG) && 31528c2ecf20Sopenharmony_ci (cp_payload + F2FS_CP_PACKS + 31538c2ecf20Sopenharmony_ci NR_CURSEG_PERSIST_TYPE + nat_bits_blocks >= blocks_per_seg)) { 31548c2ecf20Sopenharmony_ci f2fs_warn(sbi, "Insane cp_payload: %u, nat_bits_blocks: %u)", 31558c2ecf20Sopenharmony_ci cp_payload, nat_bits_blocks); 31568c2ecf20Sopenharmony_ci return 1; 31578c2ecf20Sopenharmony_ci } 31588c2ecf20Sopenharmony_ci 31598c2ecf20Sopenharmony_ci if (unlikely(f2fs_cp_error(sbi))) { 31608c2ecf20Sopenharmony_ci f2fs_err(sbi, "A bug case: need to run fsck"); 31618c2ecf20Sopenharmony_ci return 1; 31628c2ecf20Sopenharmony_ci } 31638c2ecf20Sopenharmony_ci return 0; 31648c2ecf20Sopenharmony_ci} 31658c2ecf20Sopenharmony_ci 31668c2ecf20Sopenharmony_cistatic void init_sb_info(struct f2fs_sb_info *sbi) 31678c2ecf20Sopenharmony_ci{ 31688c2ecf20Sopenharmony_ci struct f2fs_super_block *raw_super = sbi->raw_super; 31698c2ecf20Sopenharmony_ci int i; 31708c2ecf20Sopenharmony_ci 31718c2ecf20Sopenharmony_ci sbi->log_sectors_per_block = 31728c2ecf20Sopenharmony_ci le32_to_cpu(raw_super->log_sectors_per_block); 31738c2ecf20Sopenharmony_ci sbi->log_blocksize = le32_to_cpu(raw_super->log_blocksize); 31748c2ecf20Sopenharmony_ci sbi->blocksize = 1 << sbi->log_blocksize; 31758c2ecf20Sopenharmony_ci sbi->log_blocks_per_seg = le32_to_cpu(raw_super->log_blocks_per_seg); 31768c2ecf20Sopenharmony_ci sbi->blocks_per_seg = 1 << sbi->log_blocks_per_seg; 31778c2ecf20Sopenharmony_ci sbi->segs_per_sec = le32_to_cpu(raw_super->segs_per_sec); 31788c2ecf20Sopenharmony_ci sbi->secs_per_zone = le32_to_cpu(raw_super->secs_per_zone); 31798c2ecf20Sopenharmony_ci sbi->total_sections = le32_to_cpu(raw_super->section_count); 31808c2ecf20Sopenharmony_ci sbi->total_node_count = 31818c2ecf20Sopenharmony_ci (le32_to_cpu(raw_super->segment_count_nat) / 2) 31828c2ecf20Sopenharmony_ci * sbi->blocks_per_seg * NAT_ENTRY_PER_BLOCK; 31838c2ecf20Sopenharmony_ci sbi->root_ino_num = le32_to_cpu(raw_super->root_ino); 31848c2ecf20Sopenharmony_ci sbi->node_ino_num = le32_to_cpu(raw_super->node_ino); 31858c2ecf20Sopenharmony_ci sbi->meta_ino_num = le32_to_cpu(raw_super->meta_ino); 31868c2ecf20Sopenharmony_ci sbi->cur_victim_sec = NULL_SECNO; 31878c2ecf20Sopenharmony_ci sbi->next_victim_seg[BG_GC] = NULL_SEGNO; 31888c2ecf20Sopenharmony_ci sbi->next_victim_seg[FG_GC] = NULL_SEGNO; 31898c2ecf20Sopenharmony_ci sbi->max_victim_search = DEF_MAX_VICTIM_SEARCH; 31908c2ecf20Sopenharmony_ci sbi->migration_granularity = sbi->segs_per_sec; 31918c2ecf20Sopenharmony_ci 31928c2ecf20Sopenharmony_ci sbi->dir_level = DEF_DIR_LEVEL; 31938c2ecf20Sopenharmony_ci sbi->interval_time[CP_TIME] = DEF_CP_INTERVAL; 31948c2ecf20Sopenharmony_ci sbi->interval_time[REQ_TIME] = DEF_IDLE_INTERVAL; 31958c2ecf20Sopenharmony_ci sbi->interval_time[DISCARD_TIME] = DEF_IDLE_INTERVAL; 31968c2ecf20Sopenharmony_ci sbi->interval_time[GC_TIME] = DEF_IDLE_INTERVAL; 31978c2ecf20Sopenharmony_ci sbi->interval_time[DISABLE_TIME] = DEF_DISABLE_INTERVAL; 31988c2ecf20Sopenharmony_ci sbi->interval_time[UMOUNT_DISCARD_TIMEOUT] = 31998c2ecf20Sopenharmony_ci DEF_UMOUNT_DISCARD_TIMEOUT; 32008c2ecf20Sopenharmony_ci clear_sbi_flag(sbi, SBI_NEED_FSCK); 32018c2ecf20Sopenharmony_ci 32028c2ecf20Sopenharmony_ci for (i = 0; i < NR_COUNT_TYPE; i++) 32038c2ecf20Sopenharmony_ci atomic_set(&sbi->nr_pages[i], 0); 32048c2ecf20Sopenharmony_ci 32058c2ecf20Sopenharmony_ci for (i = 0; i < META; i++) 32068c2ecf20Sopenharmony_ci atomic_set(&sbi->wb_sync_req[i], 0); 32078c2ecf20Sopenharmony_ci 32088c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&sbi->s_list); 32098c2ecf20Sopenharmony_ci mutex_init(&sbi->umount_mutex); 32108c2ecf20Sopenharmony_ci init_rwsem(&sbi->io_order_lock); 32118c2ecf20Sopenharmony_ci spin_lock_init(&sbi->cp_lock); 32128c2ecf20Sopenharmony_ci 32138c2ecf20Sopenharmony_ci sbi->dirty_device = 0; 32148c2ecf20Sopenharmony_ci spin_lock_init(&sbi->dev_lock); 32158c2ecf20Sopenharmony_ci 32168c2ecf20Sopenharmony_ci init_rwsem(&sbi->sb_lock); 32178c2ecf20Sopenharmony_ci init_rwsem(&sbi->pin_sem); 32188c2ecf20Sopenharmony_ci} 32198c2ecf20Sopenharmony_ci 32208c2ecf20Sopenharmony_cistatic int init_percpu_info(struct f2fs_sb_info *sbi) 32218c2ecf20Sopenharmony_ci{ 32228c2ecf20Sopenharmony_ci int err; 32238c2ecf20Sopenharmony_ci 32248c2ecf20Sopenharmony_ci err = percpu_counter_init(&sbi->alloc_valid_block_count, 0, GFP_KERNEL); 32258c2ecf20Sopenharmony_ci if (err) 32268c2ecf20Sopenharmony_ci return err; 32278c2ecf20Sopenharmony_ci 32288c2ecf20Sopenharmony_ci err = percpu_counter_init(&sbi->total_valid_inode_count, 0, 32298c2ecf20Sopenharmony_ci GFP_KERNEL); 32308c2ecf20Sopenharmony_ci if (err) 32318c2ecf20Sopenharmony_ci percpu_counter_destroy(&sbi->alloc_valid_block_count); 32328c2ecf20Sopenharmony_ci 32338c2ecf20Sopenharmony_ci return err; 32348c2ecf20Sopenharmony_ci} 32358c2ecf20Sopenharmony_ci 32368c2ecf20Sopenharmony_ci#ifdef CONFIG_BLK_DEV_ZONED 32378c2ecf20Sopenharmony_ci 32388c2ecf20Sopenharmony_cistruct f2fs_report_zones_args { 32398c2ecf20Sopenharmony_ci struct f2fs_sb_info *sbi; 32408c2ecf20Sopenharmony_ci struct f2fs_dev_info *dev; 32418c2ecf20Sopenharmony_ci}; 32428c2ecf20Sopenharmony_ci 32438c2ecf20Sopenharmony_cistatic int f2fs_report_zone_cb(struct blk_zone *zone, unsigned int idx, 32448c2ecf20Sopenharmony_ci void *data) 32458c2ecf20Sopenharmony_ci{ 32468c2ecf20Sopenharmony_ci struct f2fs_report_zones_args *rz_args = data; 32478c2ecf20Sopenharmony_ci block_t unusable_blocks = (zone->len - zone->capacity) >> 32488c2ecf20Sopenharmony_ci F2FS_LOG_SECTORS_PER_BLOCK; 32498c2ecf20Sopenharmony_ci 32508c2ecf20Sopenharmony_ci if (zone->type == BLK_ZONE_TYPE_CONVENTIONAL) 32518c2ecf20Sopenharmony_ci return 0; 32528c2ecf20Sopenharmony_ci 32538c2ecf20Sopenharmony_ci set_bit(idx, rz_args->dev->blkz_seq); 32548c2ecf20Sopenharmony_ci if (!rz_args->sbi->unusable_blocks_per_sec) { 32558c2ecf20Sopenharmony_ci rz_args->sbi->unusable_blocks_per_sec = unusable_blocks; 32568c2ecf20Sopenharmony_ci return 0; 32578c2ecf20Sopenharmony_ci } 32588c2ecf20Sopenharmony_ci if (rz_args->sbi->unusable_blocks_per_sec != unusable_blocks) { 32598c2ecf20Sopenharmony_ci f2fs_err(rz_args->sbi, "F2FS supports single zone capacity\n"); 32608c2ecf20Sopenharmony_ci return -EINVAL; 32618c2ecf20Sopenharmony_ci } 32628c2ecf20Sopenharmony_ci return 0; 32638c2ecf20Sopenharmony_ci} 32648c2ecf20Sopenharmony_ci 32658c2ecf20Sopenharmony_cistatic int init_blkz_info(struct f2fs_sb_info *sbi, int devi) 32668c2ecf20Sopenharmony_ci{ 32678c2ecf20Sopenharmony_ci struct block_device *bdev = FDEV(devi).bdev; 32688c2ecf20Sopenharmony_ci sector_t nr_sectors = bdev->bd_part->nr_sects; 32698c2ecf20Sopenharmony_ci struct f2fs_report_zones_args rep_zone_arg; 32708c2ecf20Sopenharmony_ci int ret; 32718c2ecf20Sopenharmony_ci 32728c2ecf20Sopenharmony_ci if (!f2fs_sb_has_blkzoned(sbi)) 32738c2ecf20Sopenharmony_ci return 0; 32748c2ecf20Sopenharmony_ci 32758c2ecf20Sopenharmony_ci if (sbi->blocks_per_blkz && sbi->blocks_per_blkz != 32768c2ecf20Sopenharmony_ci SECTOR_TO_BLOCK(bdev_zone_sectors(bdev))) 32778c2ecf20Sopenharmony_ci return -EINVAL; 32788c2ecf20Sopenharmony_ci sbi->blocks_per_blkz = SECTOR_TO_BLOCK(bdev_zone_sectors(bdev)); 32798c2ecf20Sopenharmony_ci if (sbi->log_blocks_per_blkz && sbi->log_blocks_per_blkz != 32808c2ecf20Sopenharmony_ci __ilog2_u32(sbi->blocks_per_blkz)) 32818c2ecf20Sopenharmony_ci return -EINVAL; 32828c2ecf20Sopenharmony_ci sbi->log_blocks_per_blkz = __ilog2_u32(sbi->blocks_per_blkz); 32838c2ecf20Sopenharmony_ci FDEV(devi).nr_blkz = SECTOR_TO_BLOCK(nr_sectors) >> 32848c2ecf20Sopenharmony_ci sbi->log_blocks_per_blkz; 32858c2ecf20Sopenharmony_ci if (nr_sectors & (bdev_zone_sectors(bdev) - 1)) 32868c2ecf20Sopenharmony_ci FDEV(devi).nr_blkz++; 32878c2ecf20Sopenharmony_ci 32888c2ecf20Sopenharmony_ci FDEV(devi).blkz_seq = f2fs_kvzalloc(sbi, 32898c2ecf20Sopenharmony_ci BITS_TO_LONGS(FDEV(devi).nr_blkz) 32908c2ecf20Sopenharmony_ci * sizeof(unsigned long), 32918c2ecf20Sopenharmony_ci GFP_KERNEL); 32928c2ecf20Sopenharmony_ci if (!FDEV(devi).blkz_seq) 32938c2ecf20Sopenharmony_ci return -ENOMEM; 32948c2ecf20Sopenharmony_ci 32958c2ecf20Sopenharmony_ci rep_zone_arg.sbi = sbi; 32968c2ecf20Sopenharmony_ci rep_zone_arg.dev = &FDEV(devi); 32978c2ecf20Sopenharmony_ci 32988c2ecf20Sopenharmony_ci ret = blkdev_report_zones(bdev, 0, BLK_ALL_ZONES, f2fs_report_zone_cb, 32998c2ecf20Sopenharmony_ci &rep_zone_arg); 33008c2ecf20Sopenharmony_ci if (ret < 0) 33018c2ecf20Sopenharmony_ci return ret; 33028c2ecf20Sopenharmony_ci return 0; 33038c2ecf20Sopenharmony_ci} 33048c2ecf20Sopenharmony_ci#endif 33058c2ecf20Sopenharmony_ci 33068c2ecf20Sopenharmony_ci/* 33078c2ecf20Sopenharmony_ci * Read f2fs raw super block. 33088c2ecf20Sopenharmony_ci * Because we have two copies of super block, so read both of them 33098c2ecf20Sopenharmony_ci * to get the first valid one. If any one of them is broken, we pass 33108c2ecf20Sopenharmony_ci * them recovery flag back to the caller. 33118c2ecf20Sopenharmony_ci */ 33128c2ecf20Sopenharmony_cistatic int read_raw_super_block(struct f2fs_sb_info *sbi, 33138c2ecf20Sopenharmony_ci struct f2fs_super_block **raw_super, 33148c2ecf20Sopenharmony_ci int *valid_super_block, int *recovery) 33158c2ecf20Sopenharmony_ci{ 33168c2ecf20Sopenharmony_ci struct super_block *sb = sbi->sb; 33178c2ecf20Sopenharmony_ci int block; 33188c2ecf20Sopenharmony_ci struct buffer_head *bh; 33198c2ecf20Sopenharmony_ci struct f2fs_super_block *super; 33208c2ecf20Sopenharmony_ci int err = 0; 33218c2ecf20Sopenharmony_ci 33228c2ecf20Sopenharmony_ci super = kzalloc(sizeof(struct f2fs_super_block), GFP_KERNEL); 33238c2ecf20Sopenharmony_ci if (!super) 33248c2ecf20Sopenharmony_ci return -ENOMEM; 33258c2ecf20Sopenharmony_ci 33268c2ecf20Sopenharmony_ci for (block = 0; block < 2; block++) { 33278c2ecf20Sopenharmony_ci bh = sb_bread(sb, block); 33288c2ecf20Sopenharmony_ci if (!bh) { 33298c2ecf20Sopenharmony_ci f2fs_err(sbi, "Unable to read %dth superblock", 33308c2ecf20Sopenharmony_ci block + 1); 33318c2ecf20Sopenharmony_ci err = -EIO; 33328c2ecf20Sopenharmony_ci *recovery = 1; 33338c2ecf20Sopenharmony_ci continue; 33348c2ecf20Sopenharmony_ci } 33358c2ecf20Sopenharmony_ci 33368c2ecf20Sopenharmony_ci /* sanity checking of raw super */ 33378c2ecf20Sopenharmony_ci err = sanity_check_raw_super(sbi, bh); 33388c2ecf20Sopenharmony_ci if (err) { 33398c2ecf20Sopenharmony_ci f2fs_err(sbi, "Can't find valid F2FS filesystem in %dth superblock", 33408c2ecf20Sopenharmony_ci block + 1); 33418c2ecf20Sopenharmony_ci brelse(bh); 33428c2ecf20Sopenharmony_ci *recovery = 1; 33438c2ecf20Sopenharmony_ci continue; 33448c2ecf20Sopenharmony_ci } 33458c2ecf20Sopenharmony_ci 33468c2ecf20Sopenharmony_ci if (!*raw_super) { 33478c2ecf20Sopenharmony_ci memcpy(super, bh->b_data + F2FS_SUPER_OFFSET, 33488c2ecf20Sopenharmony_ci sizeof(*super)); 33498c2ecf20Sopenharmony_ci *valid_super_block = block; 33508c2ecf20Sopenharmony_ci *raw_super = super; 33518c2ecf20Sopenharmony_ci } 33528c2ecf20Sopenharmony_ci brelse(bh); 33538c2ecf20Sopenharmony_ci } 33548c2ecf20Sopenharmony_ci 33558c2ecf20Sopenharmony_ci /* No valid superblock */ 33568c2ecf20Sopenharmony_ci if (!*raw_super) 33578c2ecf20Sopenharmony_ci kfree(super); 33588c2ecf20Sopenharmony_ci else 33598c2ecf20Sopenharmony_ci err = 0; 33608c2ecf20Sopenharmony_ci 33618c2ecf20Sopenharmony_ci return err; 33628c2ecf20Sopenharmony_ci} 33638c2ecf20Sopenharmony_ci 33648c2ecf20Sopenharmony_ciint f2fs_commit_super(struct f2fs_sb_info *sbi, bool recover) 33658c2ecf20Sopenharmony_ci{ 33668c2ecf20Sopenharmony_ci struct buffer_head *bh; 33678c2ecf20Sopenharmony_ci __u32 crc = 0; 33688c2ecf20Sopenharmony_ci int err; 33698c2ecf20Sopenharmony_ci 33708c2ecf20Sopenharmony_ci if ((recover && f2fs_readonly(sbi->sb)) || 33718c2ecf20Sopenharmony_ci bdev_read_only(sbi->sb->s_bdev)) { 33728c2ecf20Sopenharmony_ci set_sbi_flag(sbi, SBI_NEED_SB_WRITE); 33738c2ecf20Sopenharmony_ci return -EROFS; 33748c2ecf20Sopenharmony_ci } 33758c2ecf20Sopenharmony_ci 33768c2ecf20Sopenharmony_ci /* we should update superblock crc here */ 33778c2ecf20Sopenharmony_ci if (!recover && f2fs_sb_has_sb_chksum(sbi)) { 33788c2ecf20Sopenharmony_ci crc = f2fs_crc32(sbi, F2FS_RAW_SUPER(sbi), 33798c2ecf20Sopenharmony_ci offsetof(struct f2fs_super_block, crc)); 33808c2ecf20Sopenharmony_ci F2FS_RAW_SUPER(sbi)->crc = cpu_to_le32(crc); 33818c2ecf20Sopenharmony_ci } 33828c2ecf20Sopenharmony_ci 33838c2ecf20Sopenharmony_ci /* write back-up superblock first */ 33848c2ecf20Sopenharmony_ci bh = sb_bread(sbi->sb, sbi->valid_super_block ? 0 : 1); 33858c2ecf20Sopenharmony_ci if (!bh) 33868c2ecf20Sopenharmony_ci return -EIO; 33878c2ecf20Sopenharmony_ci err = __f2fs_commit_super(bh, F2FS_RAW_SUPER(sbi)); 33888c2ecf20Sopenharmony_ci brelse(bh); 33898c2ecf20Sopenharmony_ci 33908c2ecf20Sopenharmony_ci /* if we are in recovery path, skip writing valid superblock */ 33918c2ecf20Sopenharmony_ci if (recover || err) 33928c2ecf20Sopenharmony_ci return err; 33938c2ecf20Sopenharmony_ci 33948c2ecf20Sopenharmony_ci /* write current valid superblock */ 33958c2ecf20Sopenharmony_ci bh = sb_bread(sbi->sb, sbi->valid_super_block); 33968c2ecf20Sopenharmony_ci if (!bh) 33978c2ecf20Sopenharmony_ci return -EIO; 33988c2ecf20Sopenharmony_ci err = __f2fs_commit_super(bh, F2FS_RAW_SUPER(sbi)); 33998c2ecf20Sopenharmony_ci brelse(bh); 34008c2ecf20Sopenharmony_ci return err; 34018c2ecf20Sopenharmony_ci} 34028c2ecf20Sopenharmony_ci 34038c2ecf20Sopenharmony_cistatic int f2fs_scan_devices(struct f2fs_sb_info *sbi) 34048c2ecf20Sopenharmony_ci{ 34058c2ecf20Sopenharmony_ci struct f2fs_super_block *raw_super = F2FS_RAW_SUPER(sbi); 34068c2ecf20Sopenharmony_ci unsigned int max_devices = MAX_DEVICES; 34078c2ecf20Sopenharmony_ci int i; 34088c2ecf20Sopenharmony_ci 34098c2ecf20Sopenharmony_ci /* Initialize single device information */ 34108c2ecf20Sopenharmony_ci if (!RDEV(0).path[0]) { 34118c2ecf20Sopenharmony_ci if (!bdev_is_zoned(sbi->sb->s_bdev)) 34128c2ecf20Sopenharmony_ci return 0; 34138c2ecf20Sopenharmony_ci max_devices = 1; 34148c2ecf20Sopenharmony_ci } 34158c2ecf20Sopenharmony_ci 34168c2ecf20Sopenharmony_ci /* 34178c2ecf20Sopenharmony_ci * Initialize multiple devices information, or single 34188c2ecf20Sopenharmony_ci * zoned block device information. 34198c2ecf20Sopenharmony_ci */ 34208c2ecf20Sopenharmony_ci sbi->devs = f2fs_kzalloc(sbi, 34218c2ecf20Sopenharmony_ci array_size(max_devices, 34228c2ecf20Sopenharmony_ci sizeof(struct f2fs_dev_info)), 34238c2ecf20Sopenharmony_ci GFP_KERNEL); 34248c2ecf20Sopenharmony_ci if (!sbi->devs) 34258c2ecf20Sopenharmony_ci return -ENOMEM; 34268c2ecf20Sopenharmony_ci 34278c2ecf20Sopenharmony_ci for (i = 0; i < max_devices; i++) { 34288c2ecf20Sopenharmony_ci 34298c2ecf20Sopenharmony_ci if (i > 0 && !RDEV(i).path[0]) 34308c2ecf20Sopenharmony_ci break; 34318c2ecf20Sopenharmony_ci 34328c2ecf20Sopenharmony_ci if (max_devices == 1) { 34338c2ecf20Sopenharmony_ci /* Single zoned block device mount */ 34348c2ecf20Sopenharmony_ci FDEV(0).bdev = 34358c2ecf20Sopenharmony_ci blkdev_get_by_dev(sbi->sb->s_bdev->bd_dev, 34368c2ecf20Sopenharmony_ci sbi->sb->s_mode, sbi->sb->s_type); 34378c2ecf20Sopenharmony_ci } else { 34388c2ecf20Sopenharmony_ci /* Multi-device mount */ 34398c2ecf20Sopenharmony_ci memcpy(FDEV(i).path, RDEV(i).path, MAX_PATH_LEN); 34408c2ecf20Sopenharmony_ci FDEV(i).total_segments = 34418c2ecf20Sopenharmony_ci le32_to_cpu(RDEV(i).total_segments); 34428c2ecf20Sopenharmony_ci if (i == 0) { 34438c2ecf20Sopenharmony_ci FDEV(i).start_blk = 0; 34448c2ecf20Sopenharmony_ci FDEV(i).end_blk = FDEV(i).start_blk + 34458c2ecf20Sopenharmony_ci (FDEV(i).total_segments << 34468c2ecf20Sopenharmony_ci sbi->log_blocks_per_seg) - 1 + 34478c2ecf20Sopenharmony_ci le32_to_cpu(raw_super->segment0_blkaddr); 34488c2ecf20Sopenharmony_ci } else { 34498c2ecf20Sopenharmony_ci FDEV(i).start_blk = FDEV(i - 1).end_blk + 1; 34508c2ecf20Sopenharmony_ci FDEV(i).end_blk = FDEV(i).start_blk + 34518c2ecf20Sopenharmony_ci (FDEV(i).total_segments << 34528c2ecf20Sopenharmony_ci sbi->log_blocks_per_seg) - 1; 34538c2ecf20Sopenharmony_ci } 34548c2ecf20Sopenharmony_ci FDEV(i).bdev = blkdev_get_by_path(FDEV(i).path, 34558c2ecf20Sopenharmony_ci sbi->sb->s_mode, sbi->sb->s_type); 34568c2ecf20Sopenharmony_ci } 34578c2ecf20Sopenharmony_ci if (IS_ERR(FDEV(i).bdev)) 34588c2ecf20Sopenharmony_ci return PTR_ERR(FDEV(i).bdev); 34598c2ecf20Sopenharmony_ci 34608c2ecf20Sopenharmony_ci /* to release errored devices */ 34618c2ecf20Sopenharmony_ci sbi->s_ndevs = i + 1; 34628c2ecf20Sopenharmony_ci 34638c2ecf20Sopenharmony_ci#ifdef CONFIG_BLK_DEV_ZONED 34648c2ecf20Sopenharmony_ci if (bdev_zoned_model(FDEV(i).bdev) == BLK_ZONED_HM && 34658c2ecf20Sopenharmony_ci !f2fs_sb_has_blkzoned(sbi)) { 34668c2ecf20Sopenharmony_ci f2fs_err(sbi, "Zoned block device feature not enabled\n"); 34678c2ecf20Sopenharmony_ci return -EINVAL; 34688c2ecf20Sopenharmony_ci } 34698c2ecf20Sopenharmony_ci if (bdev_zoned_model(FDEV(i).bdev) != BLK_ZONED_NONE) { 34708c2ecf20Sopenharmony_ci if (init_blkz_info(sbi, i)) { 34718c2ecf20Sopenharmony_ci f2fs_err(sbi, "Failed to initialize F2FS blkzone information"); 34728c2ecf20Sopenharmony_ci return -EINVAL; 34738c2ecf20Sopenharmony_ci } 34748c2ecf20Sopenharmony_ci if (max_devices == 1) 34758c2ecf20Sopenharmony_ci break; 34768c2ecf20Sopenharmony_ci f2fs_info(sbi, "Mount Device [%2d]: %20s, %8u, %8x - %8x (zone: %s)", 34778c2ecf20Sopenharmony_ci i, FDEV(i).path, 34788c2ecf20Sopenharmony_ci FDEV(i).total_segments, 34798c2ecf20Sopenharmony_ci FDEV(i).start_blk, FDEV(i).end_blk, 34808c2ecf20Sopenharmony_ci bdev_zoned_model(FDEV(i).bdev) == BLK_ZONED_HA ? 34818c2ecf20Sopenharmony_ci "Host-aware" : "Host-managed"); 34828c2ecf20Sopenharmony_ci continue; 34838c2ecf20Sopenharmony_ci } 34848c2ecf20Sopenharmony_ci#endif 34858c2ecf20Sopenharmony_ci f2fs_info(sbi, "Mount Device [%2d]: %20s, %8u, %8x - %8x", 34868c2ecf20Sopenharmony_ci i, FDEV(i).path, 34878c2ecf20Sopenharmony_ci FDEV(i).total_segments, 34888c2ecf20Sopenharmony_ci FDEV(i).start_blk, FDEV(i).end_blk); 34898c2ecf20Sopenharmony_ci } 34908c2ecf20Sopenharmony_ci f2fs_info(sbi, 34918c2ecf20Sopenharmony_ci "IO Block Size: %8d KB", F2FS_IO_SIZE_KB(sbi)); 34928c2ecf20Sopenharmony_ci return 0; 34938c2ecf20Sopenharmony_ci} 34948c2ecf20Sopenharmony_ci 34958c2ecf20Sopenharmony_cistatic int f2fs_setup_casefold(struct f2fs_sb_info *sbi) 34968c2ecf20Sopenharmony_ci{ 34978c2ecf20Sopenharmony_ci#ifdef CONFIG_UNICODE 34988c2ecf20Sopenharmony_ci if (f2fs_sb_has_casefold(sbi) && !sbi->sb->s_encoding) { 34998c2ecf20Sopenharmony_ci const struct f2fs_sb_encodings *encoding_info; 35008c2ecf20Sopenharmony_ci struct unicode_map *encoding; 35018c2ecf20Sopenharmony_ci __u16 encoding_flags; 35028c2ecf20Sopenharmony_ci 35038c2ecf20Sopenharmony_ci if (f2fs_sb_has_encrypt(sbi)) { 35048c2ecf20Sopenharmony_ci f2fs_err(sbi, 35058c2ecf20Sopenharmony_ci "Can't mount with encoding and encryption"); 35068c2ecf20Sopenharmony_ci return -EINVAL; 35078c2ecf20Sopenharmony_ci } 35088c2ecf20Sopenharmony_ci 35098c2ecf20Sopenharmony_ci if (f2fs_sb_read_encoding(sbi->raw_super, &encoding_info, 35108c2ecf20Sopenharmony_ci &encoding_flags)) { 35118c2ecf20Sopenharmony_ci f2fs_err(sbi, 35128c2ecf20Sopenharmony_ci "Encoding requested by superblock is unknown"); 35138c2ecf20Sopenharmony_ci return -EINVAL; 35148c2ecf20Sopenharmony_ci } 35158c2ecf20Sopenharmony_ci 35168c2ecf20Sopenharmony_ci encoding = utf8_load(encoding_info->version); 35178c2ecf20Sopenharmony_ci if (IS_ERR(encoding)) { 35188c2ecf20Sopenharmony_ci f2fs_err(sbi, 35198c2ecf20Sopenharmony_ci "can't mount with superblock charset: %s-%s " 35208c2ecf20Sopenharmony_ci "not supported by the kernel. flags: 0x%x.", 35218c2ecf20Sopenharmony_ci encoding_info->name, encoding_info->version, 35228c2ecf20Sopenharmony_ci encoding_flags); 35238c2ecf20Sopenharmony_ci return PTR_ERR(encoding); 35248c2ecf20Sopenharmony_ci } 35258c2ecf20Sopenharmony_ci f2fs_info(sbi, "Using encoding defined by superblock: " 35268c2ecf20Sopenharmony_ci "%s-%s with flags 0x%hx", encoding_info->name, 35278c2ecf20Sopenharmony_ci encoding_info->version?:"\b", encoding_flags); 35288c2ecf20Sopenharmony_ci 35298c2ecf20Sopenharmony_ci sbi->sb->s_encoding = encoding; 35308c2ecf20Sopenharmony_ci sbi->sb->s_encoding_flags = encoding_flags; 35318c2ecf20Sopenharmony_ci sbi->sb->s_d_op = &f2fs_dentry_ops; 35328c2ecf20Sopenharmony_ci } 35338c2ecf20Sopenharmony_ci#else 35348c2ecf20Sopenharmony_ci if (f2fs_sb_has_casefold(sbi)) { 35358c2ecf20Sopenharmony_ci f2fs_err(sbi, "Filesystem with casefold feature cannot be mounted without CONFIG_UNICODE"); 35368c2ecf20Sopenharmony_ci return -EINVAL; 35378c2ecf20Sopenharmony_ci } 35388c2ecf20Sopenharmony_ci#endif 35398c2ecf20Sopenharmony_ci return 0; 35408c2ecf20Sopenharmony_ci} 35418c2ecf20Sopenharmony_ci 35428c2ecf20Sopenharmony_cistatic void f2fs_tuning_parameters(struct f2fs_sb_info *sbi) 35438c2ecf20Sopenharmony_ci{ 35448c2ecf20Sopenharmony_ci struct f2fs_sm_info *sm_i = SM_I(sbi); 35458c2ecf20Sopenharmony_ci 35468c2ecf20Sopenharmony_ci /* adjust parameters according to the volume size */ 35478c2ecf20Sopenharmony_ci if (sm_i->main_segments <= SMALL_VOLUME_SEGMENTS) { 35488c2ecf20Sopenharmony_ci F2FS_OPTION(sbi).alloc_mode = ALLOC_MODE_REUSE; 35498c2ecf20Sopenharmony_ci sm_i->dcc_info->discard_granularity = 1; 35508c2ecf20Sopenharmony_ci sm_i->ipu_policy = 1 << F2FS_IPU_FORCE; 35518c2ecf20Sopenharmony_ci } 35528c2ecf20Sopenharmony_ci 35538c2ecf20Sopenharmony_ci sbi->readdir_ra = 1; 35548c2ecf20Sopenharmony_ci} 35558c2ecf20Sopenharmony_ci 35568c2ecf20Sopenharmony_ci#ifdef CONFIG_F2FS_GRADING_SSR 35578c2ecf20Sopenharmony_cistatic void f2fs_init_grading_ssr(struct f2fs_sb_info *sbi) 35588c2ecf20Sopenharmony_ci{ 35598c2ecf20Sopenharmony_ci u32 total_blocks = le64_to_cpu(sbi->raw_super->block_count) >> 18; 35608c2ecf20Sopenharmony_ci 35618c2ecf20Sopenharmony_ci if (total_blocks > 64) { /* 64G */ 35628c2ecf20Sopenharmony_ci sbi->hot_cold_params.hot_data_lower_limit = SSR_HD_SAPCE_LIMIT_128G; 35638c2ecf20Sopenharmony_ci sbi->hot_cold_params.hot_data_waterline = SSR_HD_WATERLINE_128G; 35648c2ecf20Sopenharmony_ci sbi->hot_cold_params.warm_data_lower_limit = SSR_WD_SAPCE_LIMIT_128G; 35658c2ecf20Sopenharmony_ci sbi->hot_cold_params.warm_data_waterline = SSR_WD_WATERLINE_128G; 35668c2ecf20Sopenharmony_ci sbi->hot_cold_params.hot_node_lower_limit = SSR_HD_SAPCE_LIMIT_128G; 35678c2ecf20Sopenharmony_ci sbi->hot_cold_params.hot_node_waterline = SSR_HN_WATERLINE_128G; 35688c2ecf20Sopenharmony_ci sbi->hot_cold_params.warm_node_lower_limit = SSR_WN_SAPCE_LIMIT_128G; 35698c2ecf20Sopenharmony_ci sbi->hot_cold_params.warm_node_waterline = SSR_WN_WATERLINE_128G; 35708c2ecf20Sopenharmony_ci sbi->hot_cold_params.enable = GRADING_SSR_OFF; 35718c2ecf20Sopenharmony_ci } else { 35728c2ecf20Sopenharmony_ci sbi->hot_cold_params.hot_data_lower_limit = SSR_DEFALT_SPACE_LIMIT; 35738c2ecf20Sopenharmony_ci sbi->hot_cold_params.hot_data_waterline = SSR_DEFALT_WATERLINE; 35748c2ecf20Sopenharmony_ci sbi->hot_cold_params.warm_data_lower_limit = SSR_DEFALT_SPACE_LIMIT; 35758c2ecf20Sopenharmony_ci sbi->hot_cold_params.warm_data_waterline = SSR_DEFALT_WATERLINE; 35768c2ecf20Sopenharmony_ci sbi->hot_cold_params.hot_node_lower_limit = SSR_DEFALT_SPACE_LIMIT; 35778c2ecf20Sopenharmony_ci sbi->hot_cold_params.hot_node_waterline = SSR_DEFALT_WATERLINE; 35788c2ecf20Sopenharmony_ci sbi->hot_cold_params.warm_node_lower_limit = SSR_DEFALT_SPACE_LIMIT; 35798c2ecf20Sopenharmony_ci sbi->hot_cold_params.warm_node_waterline = SSR_DEFALT_WATERLINE; 35808c2ecf20Sopenharmony_ci sbi->hot_cold_params.enable = GRADING_SSR_OFF; 35818c2ecf20Sopenharmony_ci } 35828c2ecf20Sopenharmony_ci} 35838c2ecf20Sopenharmony_ci#endif 35848c2ecf20Sopenharmony_ci 35858c2ecf20Sopenharmony_cistatic int f2fs_fill_super(struct super_block *sb, void *data, int silent) 35868c2ecf20Sopenharmony_ci{ 35878c2ecf20Sopenharmony_ci struct f2fs_sb_info *sbi; 35888c2ecf20Sopenharmony_ci struct f2fs_super_block *raw_super; 35898c2ecf20Sopenharmony_ci struct inode *root; 35908c2ecf20Sopenharmony_ci int err; 35918c2ecf20Sopenharmony_ci bool skip_recovery = false, need_fsck = false; 35928c2ecf20Sopenharmony_ci char *options = NULL; 35938c2ecf20Sopenharmony_ci int recovery, i, valid_super_block; 35948c2ecf20Sopenharmony_ci struct curseg_info *seg_i; 35958c2ecf20Sopenharmony_ci int retry_cnt = 1; 35968c2ecf20Sopenharmony_ci 35978c2ecf20Sopenharmony_citry_onemore: 35988c2ecf20Sopenharmony_ci err = -EINVAL; 35998c2ecf20Sopenharmony_ci raw_super = NULL; 36008c2ecf20Sopenharmony_ci valid_super_block = -1; 36018c2ecf20Sopenharmony_ci recovery = 0; 36028c2ecf20Sopenharmony_ci 36038c2ecf20Sopenharmony_ci /* allocate memory for f2fs-specific super block info */ 36048c2ecf20Sopenharmony_ci sbi = kzalloc(sizeof(struct f2fs_sb_info), GFP_KERNEL); 36058c2ecf20Sopenharmony_ci if (!sbi) 36068c2ecf20Sopenharmony_ci return -ENOMEM; 36078c2ecf20Sopenharmony_ci 36088c2ecf20Sopenharmony_ci sbi->sb = sb; 36098c2ecf20Sopenharmony_ci 36108c2ecf20Sopenharmony_ci /* Load the checksum driver */ 36118c2ecf20Sopenharmony_ci sbi->s_chksum_driver = crypto_alloc_shash("crc32", 0, 0); 36128c2ecf20Sopenharmony_ci if (IS_ERR(sbi->s_chksum_driver)) { 36138c2ecf20Sopenharmony_ci f2fs_err(sbi, "Cannot load crc32 driver."); 36148c2ecf20Sopenharmony_ci err = PTR_ERR(sbi->s_chksum_driver); 36158c2ecf20Sopenharmony_ci sbi->s_chksum_driver = NULL; 36168c2ecf20Sopenharmony_ci goto free_sbi; 36178c2ecf20Sopenharmony_ci } 36188c2ecf20Sopenharmony_ci 36198c2ecf20Sopenharmony_ci /* set a block size */ 36208c2ecf20Sopenharmony_ci if (unlikely(!sb_set_blocksize(sb, F2FS_BLKSIZE))) { 36218c2ecf20Sopenharmony_ci f2fs_err(sbi, "unable to set blocksize"); 36228c2ecf20Sopenharmony_ci goto free_sbi; 36238c2ecf20Sopenharmony_ci } 36248c2ecf20Sopenharmony_ci 36258c2ecf20Sopenharmony_ci err = read_raw_super_block(sbi, &raw_super, &valid_super_block, 36268c2ecf20Sopenharmony_ci &recovery); 36278c2ecf20Sopenharmony_ci if (err) 36288c2ecf20Sopenharmony_ci goto free_sbi; 36298c2ecf20Sopenharmony_ci 36308c2ecf20Sopenharmony_ci sb->s_fs_info = sbi; 36318c2ecf20Sopenharmony_ci sbi->raw_super = raw_super; 36328c2ecf20Sopenharmony_ci 36338c2ecf20Sopenharmony_ci /* precompute checksum seed for metadata */ 36348c2ecf20Sopenharmony_ci if (f2fs_sb_has_inode_chksum(sbi)) 36358c2ecf20Sopenharmony_ci sbi->s_chksum_seed = f2fs_chksum(sbi, ~0, raw_super->uuid, 36368c2ecf20Sopenharmony_ci sizeof(raw_super->uuid)); 36378c2ecf20Sopenharmony_ci 36388c2ecf20Sopenharmony_ci default_options(sbi); 36398c2ecf20Sopenharmony_ci /* parse mount options */ 36408c2ecf20Sopenharmony_ci options = kstrdup((const char *)data, GFP_KERNEL); 36418c2ecf20Sopenharmony_ci if (data && !options) { 36428c2ecf20Sopenharmony_ci err = -ENOMEM; 36438c2ecf20Sopenharmony_ci goto free_sb_buf; 36448c2ecf20Sopenharmony_ci } 36458c2ecf20Sopenharmony_ci 36468c2ecf20Sopenharmony_ci err = parse_options(sb, options, false); 36478c2ecf20Sopenharmony_ci if (err) 36488c2ecf20Sopenharmony_ci goto free_options; 36498c2ecf20Sopenharmony_ci 36508c2ecf20Sopenharmony_ci sbi->max_file_blocks = max_file_blocks(); 36518c2ecf20Sopenharmony_ci sb->s_maxbytes = sbi->max_file_blocks << 36528c2ecf20Sopenharmony_ci le32_to_cpu(raw_super->log_blocksize); 36538c2ecf20Sopenharmony_ci sb->s_max_links = F2FS_LINK_MAX; 36548c2ecf20Sopenharmony_ci 36558c2ecf20Sopenharmony_ci err = f2fs_setup_casefold(sbi); 36568c2ecf20Sopenharmony_ci if (err) 36578c2ecf20Sopenharmony_ci goto free_options; 36588c2ecf20Sopenharmony_ci 36598c2ecf20Sopenharmony_ci#ifdef CONFIG_QUOTA 36608c2ecf20Sopenharmony_ci sb->dq_op = &f2fs_quota_operations; 36618c2ecf20Sopenharmony_ci sb->s_qcop = &f2fs_quotactl_ops; 36628c2ecf20Sopenharmony_ci sb->s_quota_types = QTYPE_MASK_USR | QTYPE_MASK_GRP | QTYPE_MASK_PRJ; 36638c2ecf20Sopenharmony_ci 36648c2ecf20Sopenharmony_ci if (f2fs_sb_has_quota_ino(sbi)) { 36658c2ecf20Sopenharmony_ci for (i = 0; i < MAXQUOTAS; i++) { 36668c2ecf20Sopenharmony_ci if (f2fs_qf_ino(sbi->sb, i)) 36678c2ecf20Sopenharmony_ci sbi->nquota_files++; 36688c2ecf20Sopenharmony_ci } 36698c2ecf20Sopenharmony_ci } 36708c2ecf20Sopenharmony_ci#endif 36718c2ecf20Sopenharmony_ci 36728c2ecf20Sopenharmony_ci sb->s_op = &f2fs_sops; 36738c2ecf20Sopenharmony_ci#ifdef CONFIG_FS_ENCRYPTION 36748c2ecf20Sopenharmony_ci sb->s_cop = &f2fs_cryptops; 36758c2ecf20Sopenharmony_ci#endif 36768c2ecf20Sopenharmony_ci#ifdef CONFIG_FS_VERITY 36778c2ecf20Sopenharmony_ci sb->s_vop = &f2fs_verityops; 36788c2ecf20Sopenharmony_ci#endif 36798c2ecf20Sopenharmony_ci sb->s_xattr = f2fs_xattr_handlers; 36808c2ecf20Sopenharmony_ci sb->s_export_op = &f2fs_export_ops; 36818c2ecf20Sopenharmony_ci sb->s_magic = F2FS_SUPER_MAGIC; 36828c2ecf20Sopenharmony_ci sb->s_time_gran = 1; 36838c2ecf20Sopenharmony_ci sb->s_flags = (sb->s_flags & ~SB_POSIXACL) | 36848c2ecf20Sopenharmony_ci (test_opt(sbi, POSIX_ACL) ? SB_POSIXACL : 0); 36858c2ecf20Sopenharmony_ci memcpy(&sb->s_uuid, raw_super->uuid, sizeof(raw_super->uuid)); 36868c2ecf20Sopenharmony_ci sb->s_iflags |= SB_I_CGROUPWB; 36878c2ecf20Sopenharmony_ci 36888c2ecf20Sopenharmony_ci /* init f2fs-specific super block info */ 36898c2ecf20Sopenharmony_ci sbi->valid_super_block = valid_super_block; 36908c2ecf20Sopenharmony_ci init_rwsem(&sbi->gc_lock); 36918c2ecf20Sopenharmony_ci mutex_init(&sbi->writepages); 36928c2ecf20Sopenharmony_ci mutex_init(&sbi->cp_mutex); 36938c2ecf20Sopenharmony_ci init_rwsem(&sbi->node_write); 36948c2ecf20Sopenharmony_ci init_rwsem(&sbi->node_change); 36958c2ecf20Sopenharmony_ci 36968c2ecf20Sopenharmony_ci /* disallow all the data/node/meta page writes */ 36978c2ecf20Sopenharmony_ci set_sbi_flag(sbi, SBI_POR_DOING); 36988c2ecf20Sopenharmony_ci spin_lock_init(&sbi->stat_lock); 36998c2ecf20Sopenharmony_ci 37008c2ecf20Sopenharmony_ci /* init iostat info */ 37018c2ecf20Sopenharmony_ci spin_lock_init(&sbi->iostat_lock); 37028c2ecf20Sopenharmony_ci sbi->iostat_enable = false; 37038c2ecf20Sopenharmony_ci sbi->iostat_period_ms = DEFAULT_IOSTAT_PERIOD_MS; 37048c2ecf20Sopenharmony_ci 37058c2ecf20Sopenharmony_ci for (i = 0; i < NR_PAGE_TYPE; i++) { 37068c2ecf20Sopenharmony_ci int n = (i == META) ? 1: NR_TEMP_TYPE; 37078c2ecf20Sopenharmony_ci int j; 37088c2ecf20Sopenharmony_ci 37098c2ecf20Sopenharmony_ci sbi->write_io[i] = 37108c2ecf20Sopenharmony_ci f2fs_kmalloc(sbi, 37118c2ecf20Sopenharmony_ci array_size(n, 37128c2ecf20Sopenharmony_ci sizeof(struct f2fs_bio_info)), 37138c2ecf20Sopenharmony_ci GFP_KERNEL); 37148c2ecf20Sopenharmony_ci if (!sbi->write_io[i]) { 37158c2ecf20Sopenharmony_ci err = -ENOMEM; 37168c2ecf20Sopenharmony_ci goto free_bio_info; 37178c2ecf20Sopenharmony_ci } 37188c2ecf20Sopenharmony_ci 37198c2ecf20Sopenharmony_ci for (j = HOT; j < n; j++) { 37208c2ecf20Sopenharmony_ci init_rwsem(&sbi->write_io[i][j].io_rwsem); 37218c2ecf20Sopenharmony_ci sbi->write_io[i][j].sbi = sbi; 37228c2ecf20Sopenharmony_ci sbi->write_io[i][j].bio = NULL; 37238c2ecf20Sopenharmony_ci spin_lock_init(&sbi->write_io[i][j].io_lock); 37248c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&sbi->write_io[i][j].io_list); 37258c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&sbi->write_io[i][j].bio_list); 37268c2ecf20Sopenharmony_ci init_rwsem(&sbi->write_io[i][j].bio_list_lock); 37278c2ecf20Sopenharmony_ci } 37288c2ecf20Sopenharmony_ci } 37298c2ecf20Sopenharmony_ci 37308c2ecf20Sopenharmony_ci init_rwsem(&sbi->cp_rwsem); 37318c2ecf20Sopenharmony_ci init_rwsem(&sbi->quota_sem); 37328c2ecf20Sopenharmony_ci init_waitqueue_head(&sbi->cp_wait); 37338c2ecf20Sopenharmony_ci init_sb_info(sbi); 37348c2ecf20Sopenharmony_ci 37358c2ecf20Sopenharmony_ci err = init_percpu_info(sbi); 37368c2ecf20Sopenharmony_ci if (err) 37378c2ecf20Sopenharmony_ci goto free_bio_info; 37388c2ecf20Sopenharmony_ci 37398c2ecf20Sopenharmony_ci if (F2FS_IO_ALIGNED(sbi)) { 37408c2ecf20Sopenharmony_ci sbi->write_io_dummy = 37418c2ecf20Sopenharmony_ci mempool_create_page_pool(2 * (F2FS_IO_SIZE(sbi) - 1), 0); 37428c2ecf20Sopenharmony_ci if (!sbi->write_io_dummy) { 37438c2ecf20Sopenharmony_ci err = -ENOMEM; 37448c2ecf20Sopenharmony_ci goto free_percpu; 37458c2ecf20Sopenharmony_ci } 37468c2ecf20Sopenharmony_ci } 37478c2ecf20Sopenharmony_ci 37488c2ecf20Sopenharmony_ci /* init per sbi slab cache */ 37498c2ecf20Sopenharmony_ci err = f2fs_init_xattr_caches(sbi); 37508c2ecf20Sopenharmony_ci if (err) 37518c2ecf20Sopenharmony_ci goto free_io_dummy; 37528c2ecf20Sopenharmony_ci err = f2fs_init_page_array_cache(sbi); 37538c2ecf20Sopenharmony_ci if (err) 37548c2ecf20Sopenharmony_ci goto free_xattr_cache; 37558c2ecf20Sopenharmony_ci 37568c2ecf20Sopenharmony_ci /* get an inode for meta space */ 37578c2ecf20Sopenharmony_ci sbi->meta_inode = f2fs_iget(sb, F2FS_META_INO(sbi)); 37588c2ecf20Sopenharmony_ci if (IS_ERR(sbi->meta_inode)) { 37598c2ecf20Sopenharmony_ci f2fs_err(sbi, "Failed to read F2FS meta data inode"); 37608c2ecf20Sopenharmony_ci err = PTR_ERR(sbi->meta_inode); 37618c2ecf20Sopenharmony_ci goto free_page_array_cache; 37628c2ecf20Sopenharmony_ci } 37638c2ecf20Sopenharmony_ci 37648c2ecf20Sopenharmony_ci err = f2fs_get_valid_checkpoint(sbi); 37658c2ecf20Sopenharmony_ci if (err) { 37668c2ecf20Sopenharmony_ci f2fs_err(sbi, "Failed to get valid F2FS checkpoint"); 37678c2ecf20Sopenharmony_ci goto free_meta_inode; 37688c2ecf20Sopenharmony_ci } 37698c2ecf20Sopenharmony_ci 37708c2ecf20Sopenharmony_ci if (__is_set_ckpt_flags(F2FS_CKPT(sbi), CP_QUOTA_NEED_FSCK_FLAG)) 37718c2ecf20Sopenharmony_ci set_sbi_flag(sbi, SBI_QUOTA_NEED_REPAIR); 37728c2ecf20Sopenharmony_ci if (__is_set_ckpt_flags(F2FS_CKPT(sbi), CP_DISABLED_QUICK_FLAG)) { 37738c2ecf20Sopenharmony_ci set_sbi_flag(sbi, SBI_CP_DISABLED_QUICK); 37748c2ecf20Sopenharmony_ci sbi->interval_time[DISABLE_TIME] = DEF_DISABLE_QUICK_INTERVAL; 37758c2ecf20Sopenharmony_ci } 37768c2ecf20Sopenharmony_ci 37778c2ecf20Sopenharmony_ci if (__is_set_ckpt_flags(F2FS_CKPT(sbi), CP_FSCK_FLAG)) 37788c2ecf20Sopenharmony_ci set_sbi_flag(sbi, SBI_NEED_FSCK); 37798c2ecf20Sopenharmony_ci 37808c2ecf20Sopenharmony_ci /* Initialize device list */ 37818c2ecf20Sopenharmony_ci err = f2fs_scan_devices(sbi); 37828c2ecf20Sopenharmony_ci if (err) { 37838c2ecf20Sopenharmony_ci f2fs_err(sbi, "Failed to find devices"); 37848c2ecf20Sopenharmony_ci goto free_devices; 37858c2ecf20Sopenharmony_ci } 37868c2ecf20Sopenharmony_ci 37878c2ecf20Sopenharmony_ci err = f2fs_init_post_read_wq(sbi); 37888c2ecf20Sopenharmony_ci if (err) { 37898c2ecf20Sopenharmony_ci f2fs_err(sbi, "Failed to initialize post read workqueue"); 37908c2ecf20Sopenharmony_ci goto free_devices; 37918c2ecf20Sopenharmony_ci } 37928c2ecf20Sopenharmony_ci 37938c2ecf20Sopenharmony_ci sbi->total_valid_node_count = 37948c2ecf20Sopenharmony_ci le32_to_cpu(sbi->ckpt->valid_node_count); 37958c2ecf20Sopenharmony_ci percpu_counter_set(&sbi->total_valid_inode_count, 37968c2ecf20Sopenharmony_ci le32_to_cpu(sbi->ckpt->valid_inode_count)); 37978c2ecf20Sopenharmony_ci sbi->user_block_count = le64_to_cpu(sbi->ckpt->user_block_count); 37988c2ecf20Sopenharmony_ci sbi->total_valid_block_count = 37998c2ecf20Sopenharmony_ci le64_to_cpu(sbi->ckpt->valid_block_count); 38008c2ecf20Sopenharmony_ci sbi->last_valid_block_count = sbi->total_valid_block_count; 38018c2ecf20Sopenharmony_ci sbi->reserved_blocks = 0; 38028c2ecf20Sopenharmony_ci sbi->current_reserved_blocks = 0; 38038c2ecf20Sopenharmony_ci limit_reserve_root(sbi); 38048c2ecf20Sopenharmony_ci adjust_unusable_cap_perc(sbi); 38058c2ecf20Sopenharmony_ci 38068c2ecf20Sopenharmony_ci for (i = 0; i < NR_INODE_TYPE; i++) { 38078c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&sbi->inode_list[i]); 38088c2ecf20Sopenharmony_ci spin_lock_init(&sbi->inode_lock[i]); 38098c2ecf20Sopenharmony_ci } 38108c2ecf20Sopenharmony_ci mutex_init(&sbi->flush_lock); 38118c2ecf20Sopenharmony_ci 38128c2ecf20Sopenharmony_ci f2fs_init_extent_cache_info(sbi); 38138c2ecf20Sopenharmony_ci 38148c2ecf20Sopenharmony_ci f2fs_init_ino_entry_info(sbi); 38158c2ecf20Sopenharmony_ci 38168c2ecf20Sopenharmony_ci f2fs_init_fsync_node_info(sbi); 38178c2ecf20Sopenharmony_ci 38188c2ecf20Sopenharmony_ci /* setup f2fs internal modules */ 38198c2ecf20Sopenharmony_ci err = f2fs_build_segment_manager(sbi); 38208c2ecf20Sopenharmony_ci if (err) { 38218c2ecf20Sopenharmony_ci f2fs_err(sbi, "Failed to initialize F2FS segment manager (%d)", 38228c2ecf20Sopenharmony_ci err); 38238c2ecf20Sopenharmony_ci goto free_sm; 38248c2ecf20Sopenharmony_ci } 38258c2ecf20Sopenharmony_ci err = f2fs_build_node_manager(sbi); 38268c2ecf20Sopenharmony_ci if (err) { 38278c2ecf20Sopenharmony_ci f2fs_err(sbi, "Failed to initialize F2FS node manager (%d)", 38288c2ecf20Sopenharmony_ci err); 38298c2ecf20Sopenharmony_ci goto free_nm; 38308c2ecf20Sopenharmony_ci } 38318c2ecf20Sopenharmony_ci 38328c2ecf20Sopenharmony_ci err = adjust_reserved_segment(sbi); 38338c2ecf20Sopenharmony_ci if (err) 38348c2ecf20Sopenharmony_ci goto free_nm; 38358c2ecf20Sopenharmony_ci 38368c2ecf20Sopenharmony_ci /* For write statistics */ 38378c2ecf20Sopenharmony_ci if (sb->s_bdev->bd_part) 38388c2ecf20Sopenharmony_ci sbi->sectors_written_start = 38398c2ecf20Sopenharmony_ci (u64)part_stat_read(sb->s_bdev->bd_part, 38408c2ecf20Sopenharmony_ci sectors[STAT_WRITE]); 38418c2ecf20Sopenharmony_ci 38428c2ecf20Sopenharmony_ci /* Read accumulated write IO statistics if exists */ 38438c2ecf20Sopenharmony_ci seg_i = CURSEG_I(sbi, CURSEG_HOT_NODE); 38448c2ecf20Sopenharmony_ci if (__exist_node_summaries(sbi)) 38458c2ecf20Sopenharmony_ci sbi->kbytes_written = 38468c2ecf20Sopenharmony_ci le64_to_cpu(seg_i->journal->info.kbytes_written); 38478c2ecf20Sopenharmony_ci 38488c2ecf20Sopenharmony_ci f2fs_build_gc_manager(sbi); 38498c2ecf20Sopenharmony_ci 38508c2ecf20Sopenharmony_ci err = f2fs_build_stats(sbi); 38518c2ecf20Sopenharmony_ci if (err) 38528c2ecf20Sopenharmony_ci goto free_nm; 38538c2ecf20Sopenharmony_ci 38548c2ecf20Sopenharmony_ci /* get an inode for node space */ 38558c2ecf20Sopenharmony_ci sbi->node_inode = f2fs_iget(sb, F2FS_NODE_INO(sbi)); 38568c2ecf20Sopenharmony_ci if (IS_ERR(sbi->node_inode)) { 38578c2ecf20Sopenharmony_ci f2fs_err(sbi, "Failed to read node inode"); 38588c2ecf20Sopenharmony_ci err = PTR_ERR(sbi->node_inode); 38598c2ecf20Sopenharmony_ci goto free_stats; 38608c2ecf20Sopenharmony_ci } 38618c2ecf20Sopenharmony_ci 38628c2ecf20Sopenharmony_ci /* read root inode and dentry */ 38638c2ecf20Sopenharmony_ci root = f2fs_iget(sb, F2FS_ROOT_INO(sbi)); 38648c2ecf20Sopenharmony_ci if (IS_ERR(root)) { 38658c2ecf20Sopenharmony_ci f2fs_err(sbi, "Failed to read root inode"); 38668c2ecf20Sopenharmony_ci err = PTR_ERR(root); 38678c2ecf20Sopenharmony_ci goto free_node_inode; 38688c2ecf20Sopenharmony_ci } 38698c2ecf20Sopenharmony_ci if (!S_ISDIR(root->i_mode) || !root->i_blocks || 38708c2ecf20Sopenharmony_ci !root->i_size || !root->i_nlink) { 38718c2ecf20Sopenharmony_ci iput(root); 38728c2ecf20Sopenharmony_ci err = -EINVAL; 38738c2ecf20Sopenharmony_ci goto free_node_inode; 38748c2ecf20Sopenharmony_ci } 38758c2ecf20Sopenharmony_ci 38768c2ecf20Sopenharmony_ci sb->s_root = d_make_root(root); /* allocate root dentry */ 38778c2ecf20Sopenharmony_ci if (!sb->s_root) { 38788c2ecf20Sopenharmony_ci err = -ENOMEM; 38798c2ecf20Sopenharmony_ci goto free_node_inode; 38808c2ecf20Sopenharmony_ci } 38818c2ecf20Sopenharmony_ci#ifdef CONFIG_F2FS_GRADING_SSR 38828c2ecf20Sopenharmony_ci f2fs_init_grading_ssr(sbi); 38838c2ecf20Sopenharmony_ci#endif 38848c2ecf20Sopenharmony_ci err = f2fs_register_sysfs(sbi); 38858c2ecf20Sopenharmony_ci if (err) 38868c2ecf20Sopenharmony_ci goto free_root_inode; 38878c2ecf20Sopenharmony_ci 38888c2ecf20Sopenharmony_ci#ifdef CONFIG_QUOTA 38898c2ecf20Sopenharmony_ci /* Enable quota usage during mount */ 38908c2ecf20Sopenharmony_ci if (f2fs_sb_has_quota_ino(sbi) && !f2fs_readonly(sb)) { 38918c2ecf20Sopenharmony_ci err = f2fs_enable_quotas(sb); 38928c2ecf20Sopenharmony_ci if (err) 38938c2ecf20Sopenharmony_ci f2fs_err(sbi, "Cannot turn on quotas: error %d", err); 38948c2ecf20Sopenharmony_ci } 38958c2ecf20Sopenharmony_ci#endif 38968c2ecf20Sopenharmony_ci /* if there are any orphan inodes, free them */ 38978c2ecf20Sopenharmony_ci err = f2fs_recover_orphan_inodes(sbi); 38988c2ecf20Sopenharmony_ci if (err) 38998c2ecf20Sopenharmony_ci goto free_meta; 39008c2ecf20Sopenharmony_ci 39018c2ecf20Sopenharmony_ci if (unlikely(is_set_ckpt_flags(sbi, CP_DISABLED_FLAG))) 39028c2ecf20Sopenharmony_ci goto reset_checkpoint; 39038c2ecf20Sopenharmony_ci 39048c2ecf20Sopenharmony_ci /* recover fsynced data */ 39058c2ecf20Sopenharmony_ci if (!test_opt(sbi, DISABLE_ROLL_FORWARD) && 39068c2ecf20Sopenharmony_ci !test_opt(sbi, NORECOVERY)) { 39078c2ecf20Sopenharmony_ci /* 39088c2ecf20Sopenharmony_ci * mount should be failed, when device has readonly mode, and 39098c2ecf20Sopenharmony_ci * previous checkpoint was not done by clean system shutdown. 39108c2ecf20Sopenharmony_ci */ 39118c2ecf20Sopenharmony_ci if (f2fs_hw_is_readonly(sbi)) { 39128c2ecf20Sopenharmony_ci if (!is_set_ckpt_flags(sbi, CP_UMOUNT_FLAG)) { 39138c2ecf20Sopenharmony_ci err = -EROFS; 39148c2ecf20Sopenharmony_ci f2fs_err(sbi, "Need to recover fsync data, but write access unavailable"); 39158c2ecf20Sopenharmony_ci goto free_meta; 39168c2ecf20Sopenharmony_ci } 39178c2ecf20Sopenharmony_ci f2fs_info(sbi, "write access unavailable, skipping recovery"); 39188c2ecf20Sopenharmony_ci goto reset_checkpoint; 39198c2ecf20Sopenharmony_ci } 39208c2ecf20Sopenharmony_ci 39218c2ecf20Sopenharmony_ci if (need_fsck) 39228c2ecf20Sopenharmony_ci set_sbi_flag(sbi, SBI_NEED_FSCK); 39238c2ecf20Sopenharmony_ci 39248c2ecf20Sopenharmony_ci if (skip_recovery) 39258c2ecf20Sopenharmony_ci goto reset_checkpoint; 39268c2ecf20Sopenharmony_ci 39278c2ecf20Sopenharmony_ci err = f2fs_recover_fsync_data(sbi, false); 39288c2ecf20Sopenharmony_ci if (err < 0) { 39298c2ecf20Sopenharmony_ci if (err != -ENOMEM) 39308c2ecf20Sopenharmony_ci skip_recovery = true; 39318c2ecf20Sopenharmony_ci need_fsck = true; 39328c2ecf20Sopenharmony_ci f2fs_err(sbi, "Cannot recover all fsync data errno=%d", 39338c2ecf20Sopenharmony_ci err); 39348c2ecf20Sopenharmony_ci goto free_meta; 39358c2ecf20Sopenharmony_ci } 39368c2ecf20Sopenharmony_ci } else { 39378c2ecf20Sopenharmony_ci err = f2fs_recover_fsync_data(sbi, true); 39388c2ecf20Sopenharmony_ci 39398c2ecf20Sopenharmony_ci if (!f2fs_readonly(sb) && err > 0) { 39408c2ecf20Sopenharmony_ci err = -EINVAL; 39418c2ecf20Sopenharmony_ci f2fs_err(sbi, "Need to recover fsync data"); 39428c2ecf20Sopenharmony_ci goto free_meta; 39438c2ecf20Sopenharmony_ci } 39448c2ecf20Sopenharmony_ci } 39458c2ecf20Sopenharmony_ci 39468c2ecf20Sopenharmony_ci /* 39478c2ecf20Sopenharmony_ci * If the f2fs is not readonly and fsync data recovery succeeds, 39488c2ecf20Sopenharmony_ci * check zoned block devices' write pointer consistency. 39498c2ecf20Sopenharmony_ci */ 39508c2ecf20Sopenharmony_ci if (!err && !f2fs_readonly(sb) && f2fs_sb_has_blkzoned(sbi)) { 39518c2ecf20Sopenharmony_ci err = f2fs_check_write_pointer(sbi); 39528c2ecf20Sopenharmony_ci if (err) 39538c2ecf20Sopenharmony_ci goto free_meta; 39548c2ecf20Sopenharmony_ci } 39558c2ecf20Sopenharmony_ci 39568c2ecf20Sopenharmony_cireset_checkpoint: 39578c2ecf20Sopenharmony_ci f2fs_init_inmem_curseg(sbi); 39588c2ecf20Sopenharmony_ci 39598c2ecf20Sopenharmony_ci /* f2fs_recover_fsync_data() cleared this already */ 39608c2ecf20Sopenharmony_ci clear_sbi_flag(sbi, SBI_POR_DOING); 39618c2ecf20Sopenharmony_ci 39628c2ecf20Sopenharmony_ci if (test_opt(sbi, DISABLE_CHECKPOINT)) { 39638c2ecf20Sopenharmony_ci err = f2fs_disable_checkpoint(sbi); 39648c2ecf20Sopenharmony_ci if (err) 39658c2ecf20Sopenharmony_ci goto sync_free_meta; 39668c2ecf20Sopenharmony_ci } else if (is_set_ckpt_flags(sbi, CP_DISABLED_FLAG)) { 39678c2ecf20Sopenharmony_ci f2fs_enable_checkpoint(sbi); 39688c2ecf20Sopenharmony_ci } 39698c2ecf20Sopenharmony_ci 39708c2ecf20Sopenharmony_ci /* 39718c2ecf20Sopenharmony_ci * If filesystem is not mounted as read-only then 39728c2ecf20Sopenharmony_ci * do start the gc_thread. 39738c2ecf20Sopenharmony_ci */ 39748c2ecf20Sopenharmony_ci if ((F2FS_OPTION(sbi).bggc_mode != BGGC_MODE_OFF || 39758c2ecf20Sopenharmony_ci test_opt(sbi, GC_MERGE)) && !f2fs_readonly(sb)) { 39768c2ecf20Sopenharmony_ci /* After POR, we can run background GC thread.*/ 39778c2ecf20Sopenharmony_ci err = f2fs_start_gc_thread(sbi); 39788c2ecf20Sopenharmony_ci if (err) 39798c2ecf20Sopenharmony_ci goto sync_free_meta; 39808c2ecf20Sopenharmony_ci } 39818c2ecf20Sopenharmony_ci kvfree(options); 39828c2ecf20Sopenharmony_ci 39838c2ecf20Sopenharmony_ci /* recover broken superblock */ 39848c2ecf20Sopenharmony_ci if (recovery) { 39858c2ecf20Sopenharmony_ci err = f2fs_commit_super(sbi, true); 39868c2ecf20Sopenharmony_ci f2fs_info(sbi, "Try to recover %dth superblock, ret: %d", 39878c2ecf20Sopenharmony_ci sbi->valid_super_block ? 1 : 2, err); 39888c2ecf20Sopenharmony_ci } 39898c2ecf20Sopenharmony_ci 39908c2ecf20Sopenharmony_ci f2fs_join_shrinker(sbi); 39918c2ecf20Sopenharmony_ci 39928c2ecf20Sopenharmony_ci f2fs_tuning_parameters(sbi); 39938c2ecf20Sopenharmony_ci 39948c2ecf20Sopenharmony_ci f2fs_notice(sbi, "Mounted with checkpoint version = %llx", 39958c2ecf20Sopenharmony_ci cur_cp_version(F2FS_CKPT(sbi))); 39968c2ecf20Sopenharmony_ci f2fs_update_time(sbi, CP_TIME); 39978c2ecf20Sopenharmony_ci f2fs_update_time(sbi, REQ_TIME); 39988c2ecf20Sopenharmony_ci clear_sbi_flag(sbi, SBI_CP_DISABLED_QUICK); 39998c2ecf20Sopenharmony_ci return 0; 40008c2ecf20Sopenharmony_ci 40018c2ecf20Sopenharmony_cisync_free_meta: 40028c2ecf20Sopenharmony_ci /* safe to flush all the data */ 40038c2ecf20Sopenharmony_ci sync_filesystem(sbi->sb); 40048c2ecf20Sopenharmony_ci retry_cnt = 0; 40058c2ecf20Sopenharmony_ci 40068c2ecf20Sopenharmony_cifree_meta: 40078c2ecf20Sopenharmony_ci#ifdef CONFIG_QUOTA 40088c2ecf20Sopenharmony_ci f2fs_truncate_quota_inode_pages(sb); 40098c2ecf20Sopenharmony_ci if (f2fs_sb_has_quota_ino(sbi) && !f2fs_readonly(sb)) 40108c2ecf20Sopenharmony_ci f2fs_quota_off_umount(sbi->sb); 40118c2ecf20Sopenharmony_ci#endif 40128c2ecf20Sopenharmony_ci /* 40138c2ecf20Sopenharmony_ci * Some dirty meta pages can be produced by f2fs_recover_orphan_inodes() 40148c2ecf20Sopenharmony_ci * failed by EIO. Then, iput(node_inode) can trigger balance_fs_bg() 40158c2ecf20Sopenharmony_ci * followed by f2fs_write_checkpoint() through f2fs_write_node_pages(), which 40168c2ecf20Sopenharmony_ci * falls into an infinite loop in f2fs_sync_meta_pages(). 40178c2ecf20Sopenharmony_ci */ 40188c2ecf20Sopenharmony_ci truncate_inode_pages_final(META_MAPPING(sbi)); 40198c2ecf20Sopenharmony_ci /* evict some inodes being cached by GC */ 40208c2ecf20Sopenharmony_ci evict_inodes(sb); 40218c2ecf20Sopenharmony_ci f2fs_unregister_sysfs(sbi); 40228c2ecf20Sopenharmony_cifree_root_inode: 40238c2ecf20Sopenharmony_ci dput(sb->s_root); 40248c2ecf20Sopenharmony_ci sb->s_root = NULL; 40258c2ecf20Sopenharmony_cifree_node_inode: 40268c2ecf20Sopenharmony_ci f2fs_release_ino_entry(sbi, true); 40278c2ecf20Sopenharmony_ci truncate_inode_pages_final(NODE_MAPPING(sbi)); 40288c2ecf20Sopenharmony_ci iput(sbi->node_inode); 40298c2ecf20Sopenharmony_ci sbi->node_inode = NULL; 40308c2ecf20Sopenharmony_cifree_stats: 40318c2ecf20Sopenharmony_ci f2fs_destroy_stats(sbi); 40328c2ecf20Sopenharmony_cifree_nm: 40338c2ecf20Sopenharmony_ci f2fs_destroy_node_manager(sbi); 40348c2ecf20Sopenharmony_cifree_sm: 40358c2ecf20Sopenharmony_ci f2fs_destroy_segment_manager(sbi); 40368c2ecf20Sopenharmony_ci f2fs_destroy_post_read_wq(sbi); 40378c2ecf20Sopenharmony_cifree_devices: 40388c2ecf20Sopenharmony_ci destroy_device_list(sbi); 40398c2ecf20Sopenharmony_ci kvfree(sbi->ckpt); 40408c2ecf20Sopenharmony_cifree_meta_inode: 40418c2ecf20Sopenharmony_ci make_bad_inode(sbi->meta_inode); 40428c2ecf20Sopenharmony_ci iput(sbi->meta_inode); 40438c2ecf20Sopenharmony_ci sbi->meta_inode = NULL; 40448c2ecf20Sopenharmony_cifree_page_array_cache: 40458c2ecf20Sopenharmony_ci f2fs_destroy_page_array_cache(sbi); 40468c2ecf20Sopenharmony_cifree_xattr_cache: 40478c2ecf20Sopenharmony_ci f2fs_destroy_xattr_caches(sbi); 40488c2ecf20Sopenharmony_cifree_io_dummy: 40498c2ecf20Sopenharmony_ci mempool_destroy(sbi->write_io_dummy); 40508c2ecf20Sopenharmony_cifree_percpu: 40518c2ecf20Sopenharmony_ci destroy_percpu_info(sbi); 40528c2ecf20Sopenharmony_cifree_bio_info: 40538c2ecf20Sopenharmony_ci for (i = 0; i < NR_PAGE_TYPE; i++) 40548c2ecf20Sopenharmony_ci kvfree(sbi->write_io[i]); 40558c2ecf20Sopenharmony_ci 40568c2ecf20Sopenharmony_ci#ifdef CONFIG_UNICODE 40578c2ecf20Sopenharmony_ci utf8_unload(sb->s_encoding); 40588c2ecf20Sopenharmony_ci sb->s_encoding = NULL; 40598c2ecf20Sopenharmony_ci#endif 40608c2ecf20Sopenharmony_cifree_options: 40618c2ecf20Sopenharmony_ci#ifdef CONFIG_QUOTA 40628c2ecf20Sopenharmony_ci for (i = 0; i < MAXQUOTAS; i++) 40638c2ecf20Sopenharmony_ci kfree(F2FS_OPTION(sbi).s_qf_names[i]); 40648c2ecf20Sopenharmony_ci#endif 40658c2ecf20Sopenharmony_ci fscrypt_free_dummy_policy(&F2FS_OPTION(sbi).dummy_enc_policy); 40668c2ecf20Sopenharmony_ci kvfree(options); 40678c2ecf20Sopenharmony_cifree_sb_buf: 40688c2ecf20Sopenharmony_ci kfree(raw_super); 40698c2ecf20Sopenharmony_cifree_sbi: 40708c2ecf20Sopenharmony_ci if (sbi->s_chksum_driver) 40718c2ecf20Sopenharmony_ci crypto_free_shash(sbi->s_chksum_driver); 40728c2ecf20Sopenharmony_ci kfree(sbi); 40738c2ecf20Sopenharmony_ci 40748c2ecf20Sopenharmony_ci /* give only one another chance */ 40758c2ecf20Sopenharmony_ci if (retry_cnt > 0 && skip_recovery) { 40768c2ecf20Sopenharmony_ci retry_cnt--; 40778c2ecf20Sopenharmony_ci shrink_dcache_sb(sb); 40788c2ecf20Sopenharmony_ci goto try_onemore; 40798c2ecf20Sopenharmony_ci } 40808c2ecf20Sopenharmony_ci return err; 40818c2ecf20Sopenharmony_ci} 40828c2ecf20Sopenharmony_ci 40838c2ecf20Sopenharmony_cistatic struct dentry *f2fs_mount(struct file_system_type *fs_type, int flags, 40848c2ecf20Sopenharmony_ci const char *dev_name, void *data) 40858c2ecf20Sopenharmony_ci{ 40868c2ecf20Sopenharmony_ci return mount_bdev(fs_type, flags, dev_name, data, f2fs_fill_super); 40878c2ecf20Sopenharmony_ci} 40888c2ecf20Sopenharmony_ci 40898c2ecf20Sopenharmony_cistatic void kill_f2fs_super(struct super_block *sb) 40908c2ecf20Sopenharmony_ci{ 40918c2ecf20Sopenharmony_ci if (sb->s_root) { 40928c2ecf20Sopenharmony_ci struct f2fs_sb_info *sbi = F2FS_SB(sb); 40938c2ecf20Sopenharmony_ci 40948c2ecf20Sopenharmony_ci set_sbi_flag(sbi, SBI_IS_CLOSE); 40958c2ecf20Sopenharmony_ci f2fs_stop_gc_thread(sbi); 40968c2ecf20Sopenharmony_ci f2fs_stop_discard_thread(sbi); 40978c2ecf20Sopenharmony_ci 40988c2ecf20Sopenharmony_ci if (is_sbi_flag_set(sbi, SBI_IS_DIRTY) || 40998c2ecf20Sopenharmony_ci !is_set_ckpt_flags(sbi, CP_UMOUNT_FLAG)) { 41008c2ecf20Sopenharmony_ci struct cp_control cpc = { 41018c2ecf20Sopenharmony_ci .reason = CP_UMOUNT, 41028c2ecf20Sopenharmony_ci }; 41038c2ecf20Sopenharmony_ci f2fs_write_checkpoint(sbi, &cpc); 41048c2ecf20Sopenharmony_ci } 41058c2ecf20Sopenharmony_ci 41068c2ecf20Sopenharmony_ci if (is_sbi_flag_set(sbi, SBI_IS_RECOVERED) && f2fs_readonly(sb)) 41078c2ecf20Sopenharmony_ci sb->s_flags &= ~SB_RDONLY; 41088c2ecf20Sopenharmony_ci } 41098c2ecf20Sopenharmony_ci kill_block_super(sb); 41108c2ecf20Sopenharmony_ci} 41118c2ecf20Sopenharmony_ci 41128c2ecf20Sopenharmony_cistatic struct file_system_type f2fs_fs_type = { 41138c2ecf20Sopenharmony_ci .owner = THIS_MODULE, 41148c2ecf20Sopenharmony_ci .name = "f2fs", 41158c2ecf20Sopenharmony_ci .mount = f2fs_mount, 41168c2ecf20Sopenharmony_ci .kill_sb = kill_f2fs_super, 41178c2ecf20Sopenharmony_ci .fs_flags = FS_REQUIRES_DEV, 41188c2ecf20Sopenharmony_ci}; 41198c2ecf20Sopenharmony_ciMODULE_ALIAS_FS("f2fs"); 41208c2ecf20Sopenharmony_ci 41218c2ecf20Sopenharmony_cistatic int __init init_inodecache(void) 41228c2ecf20Sopenharmony_ci{ 41238c2ecf20Sopenharmony_ci f2fs_inode_cachep = kmem_cache_create("f2fs_inode_cache", 41248c2ecf20Sopenharmony_ci sizeof(struct f2fs_inode_info), 0, 41258c2ecf20Sopenharmony_ci SLAB_RECLAIM_ACCOUNT|SLAB_ACCOUNT, NULL); 41268c2ecf20Sopenharmony_ci if (!f2fs_inode_cachep) 41278c2ecf20Sopenharmony_ci return -ENOMEM; 41288c2ecf20Sopenharmony_ci return 0; 41298c2ecf20Sopenharmony_ci} 41308c2ecf20Sopenharmony_ci 41318c2ecf20Sopenharmony_cistatic void destroy_inodecache(void) 41328c2ecf20Sopenharmony_ci{ 41338c2ecf20Sopenharmony_ci /* 41348c2ecf20Sopenharmony_ci * Make sure all delayed rcu free inodes are flushed before we 41358c2ecf20Sopenharmony_ci * destroy cache. 41368c2ecf20Sopenharmony_ci */ 41378c2ecf20Sopenharmony_ci rcu_barrier(); 41388c2ecf20Sopenharmony_ci kmem_cache_destroy(f2fs_inode_cachep); 41398c2ecf20Sopenharmony_ci} 41408c2ecf20Sopenharmony_ci 41418c2ecf20Sopenharmony_cistatic int __init init_f2fs_fs(void) 41428c2ecf20Sopenharmony_ci{ 41438c2ecf20Sopenharmony_ci int err; 41448c2ecf20Sopenharmony_ci 41458c2ecf20Sopenharmony_ci if (PAGE_SIZE != F2FS_BLKSIZE) { 41468c2ecf20Sopenharmony_ci printk("F2FS not supported on PAGE_SIZE(%lu) != %d\n", 41478c2ecf20Sopenharmony_ci PAGE_SIZE, F2FS_BLKSIZE); 41488c2ecf20Sopenharmony_ci return -EINVAL; 41498c2ecf20Sopenharmony_ci } 41508c2ecf20Sopenharmony_ci 41518c2ecf20Sopenharmony_ci f2fs_build_trace_ios(); 41528c2ecf20Sopenharmony_ci 41538c2ecf20Sopenharmony_ci err = init_inodecache(); 41548c2ecf20Sopenharmony_ci if (err) 41558c2ecf20Sopenharmony_ci goto fail; 41568c2ecf20Sopenharmony_ci err = f2fs_create_node_manager_caches(); 41578c2ecf20Sopenharmony_ci if (err) 41588c2ecf20Sopenharmony_ci goto free_inodecache; 41598c2ecf20Sopenharmony_ci err = f2fs_create_segment_manager_caches(); 41608c2ecf20Sopenharmony_ci if (err) 41618c2ecf20Sopenharmony_ci goto free_node_manager_caches; 41628c2ecf20Sopenharmony_ci err = f2fs_create_checkpoint_caches(); 41638c2ecf20Sopenharmony_ci if (err) 41648c2ecf20Sopenharmony_ci goto free_segment_manager_caches; 41658c2ecf20Sopenharmony_ci err = f2fs_create_recovery_cache(); 41668c2ecf20Sopenharmony_ci if (err) 41678c2ecf20Sopenharmony_ci goto free_checkpoint_caches; 41688c2ecf20Sopenharmony_ci err = f2fs_create_extent_cache(); 41698c2ecf20Sopenharmony_ci if (err) 41708c2ecf20Sopenharmony_ci goto free_recovery_cache; 41718c2ecf20Sopenharmony_ci err = f2fs_create_garbage_collection_cache(); 41728c2ecf20Sopenharmony_ci if (err) 41738c2ecf20Sopenharmony_ci goto free_extent_cache; 41748c2ecf20Sopenharmony_ci err = f2fs_init_sysfs(); 41758c2ecf20Sopenharmony_ci if (err) 41768c2ecf20Sopenharmony_ci goto free_garbage_collection_cache; 41778c2ecf20Sopenharmony_ci err = register_shrinker(&f2fs_shrinker_info); 41788c2ecf20Sopenharmony_ci if (err) 41798c2ecf20Sopenharmony_ci goto free_sysfs; 41808c2ecf20Sopenharmony_ci err = register_filesystem(&f2fs_fs_type); 41818c2ecf20Sopenharmony_ci if (err) 41828c2ecf20Sopenharmony_ci goto free_shrinker; 41838c2ecf20Sopenharmony_ci f2fs_create_root_stats(); 41848c2ecf20Sopenharmony_ci err = f2fs_init_post_read_processing(); 41858c2ecf20Sopenharmony_ci if (err) 41868c2ecf20Sopenharmony_ci goto free_root_stats; 41878c2ecf20Sopenharmony_ci err = f2fs_init_bio_entry_cache(); 41888c2ecf20Sopenharmony_ci if (err) 41898c2ecf20Sopenharmony_ci goto free_post_read; 41908c2ecf20Sopenharmony_ci err = f2fs_init_bioset(); 41918c2ecf20Sopenharmony_ci if (err) 41928c2ecf20Sopenharmony_ci goto free_bio_enrty_cache; 41938c2ecf20Sopenharmony_ci err = f2fs_init_compress_mempool(); 41948c2ecf20Sopenharmony_ci if (err) 41958c2ecf20Sopenharmony_ci goto free_bioset; 41968c2ecf20Sopenharmony_ci err = f2fs_init_compress_cache(); 41978c2ecf20Sopenharmony_ci if (err) 41988c2ecf20Sopenharmony_ci goto free_compress_mempool; 41998c2ecf20Sopenharmony_ci return 0; 42008c2ecf20Sopenharmony_cifree_compress_mempool: 42018c2ecf20Sopenharmony_ci f2fs_destroy_compress_mempool(); 42028c2ecf20Sopenharmony_cifree_bioset: 42038c2ecf20Sopenharmony_ci f2fs_destroy_bioset(); 42048c2ecf20Sopenharmony_cifree_bio_enrty_cache: 42058c2ecf20Sopenharmony_ci f2fs_destroy_bio_entry_cache(); 42068c2ecf20Sopenharmony_cifree_post_read: 42078c2ecf20Sopenharmony_ci f2fs_destroy_post_read_processing(); 42088c2ecf20Sopenharmony_cifree_root_stats: 42098c2ecf20Sopenharmony_ci f2fs_destroy_root_stats(); 42108c2ecf20Sopenharmony_ci unregister_filesystem(&f2fs_fs_type); 42118c2ecf20Sopenharmony_cifree_shrinker: 42128c2ecf20Sopenharmony_ci unregister_shrinker(&f2fs_shrinker_info); 42138c2ecf20Sopenharmony_cifree_sysfs: 42148c2ecf20Sopenharmony_ci f2fs_exit_sysfs(); 42158c2ecf20Sopenharmony_cifree_garbage_collection_cache: 42168c2ecf20Sopenharmony_ci f2fs_destroy_garbage_collection_cache(); 42178c2ecf20Sopenharmony_cifree_extent_cache: 42188c2ecf20Sopenharmony_ci f2fs_destroy_extent_cache(); 42198c2ecf20Sopenharmony_cifree_recovery_cache: 42208c2ecf20Sopenharmony_ci f2fs_destroy_recovery_cache(); 42218c2ecf20Sopenharmony_cifree_checkpoint_caches: 42228c2ecf20Sopenharmony_ci f2fs_destroy_checkpoint_caches(); 42238c2ecf20Sopenharmony_cifree_segment_manager_caches: 42248c2ecf20Sopenharmony_ci f2fs_destroy_segment_manager_caches(); 42258c2ecf20Sopenharmony_cifree_node_manager_caches: 42268c2ecf20Sopenharmony_ci f2fs_destroy_node_manager_caches(); 42278c2ecf20Sopenharmony_cifree_inodecache: 42288c2ecf20Sopenharmony_ci destroy_inodecache(); 42298c2ecf20Sopenharmony_cifail: 42308c2ecf20Sopenharmony_ci return err; 42318c2ecf20Sopenharmony_ci} 42328c2ecf20Sopenharmony_ci 42338c2ecf20Sopenharmony_cistatic void __exit exit_f2fs_fs(void) 42348c2ecf20Sopenharmony_ci{ 42358c2ecf20Sopenharmony_ci f2fs_destroy_compress_cache(); 42368c2ecf20Sopenharmony_ci f2fs_destroy_compress_mempool(); 42378c2ecf20Sopenharmony_ci f2fs_destroy_bioset(); 42388c2ecf20Sopenharmony_ci f2fs_destroy_bio_entry_cache(); 42398c2ecf20Sopenharmony_ci f2fs_destroy_post_read_processing(); 42408c2ecf20Sopenharmony_ci f2fs_destroy_root_stats(); 42418c2ecf20Sopenharmony_ci unregister_filesystem(&f2fs_fs_type); 42428c2ecf20Sopenharmony_ci unregister_shrinker(&f2fs_shrinker_info); 42438c2ecf20Sopenharmony_ci f2fs_exit_sysfs(); 42448c2ecf20Sopenharmony_ci f2fs_destroy_garbage_collection_cache(); 42458c2ecf20Sopenharmony_ci f2fs_destroy_extent_cache(); 42468c2ecf20Sopenharmony_ci f2fs_destroy_recovery_cache(); 42478c2ecf20Sopenharmony_ci f2fs_destroy_checkpoint_caches(); 42488c2ecf20Sopenharmony_ci f2fs_destroy_segment_manager_caches(); 42498c2ecf20Sopenharmony_ci f2fs_destroy_node_manager_caches(); 42508c2ecf20Sopenharmony_ci destroy_inodecache(); 42518c2ecf20Sopenharmony_ci f2fs_destroy_trace_ios(); 42528c2ecf20Sopenharmony_ci} 42538c2ecf20Sopenharmony_ci 42548c2ecf20Sopenharmony_cimodule_init(init_f2fs_fs) 42558c2ecf20Sopenharmony_cimodule_exit(exit_f2fs_fs) 42568c2ecf20Sopenharmony_ci 42578c2ecf20Sopenharmony_ciMODULE_AUTHOR("Samsung Electronics's Praesto Team"); 42588c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("Flash Friendly File System"); 42598c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL"); 42608c2ecf20Sopenharmony_ciMODULE_SOFTDEP("pre: crc32"); 42618c2ecf20Sopenharmony_ci 4262