1719c1e18SNamjae Jeon // SPDX-License-Identifier: GPL-2.0-or-later 2719c1e18SNamjae Jeon /* 3719c1e18SNamjae Jeon * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd. 4719c1e18SNamjae Jeon */ 5719c1e18SNamjae Jeon 6719c1e18SNamjae Jeon #include <linux/fs_context.h> 7719c1e18SNamjae Jeon #include <linux/fs_parser.h> 8719c1e18SNamjae Jeon #include <linux/module.h> 9719c1e18SNamjae Jeon #include <linux/init.h> 10719c1e18SNamjae Jeon #include <linux/time.h> 11719c1e18SNamjae Jeon #include <linux/mount.h> 12719c1e18SNamjae Jeon #include <linux/cred.h> 13719c1e18SNamjae Jeon #include <linux/statfs.h> 14719c1e18SNamjae Jeon #include <linux/seq_file.h> 15719c1e18SNamjae Jeon #include <linux/blkdev.h> 16719c1e18SNamjae Jeon #include <linux/fs_struct.h> 17719c1e18SNamjae Jeon #include <linux/iversion.h> 18719c1e18SNamjae Jeon #include <linux/nls.h> 19719c1e18SNamjae Jeon #include <linux/buffer_head.h> 20719c1e18SNamjae Jeon 21719c1e18SNamjae Jeon #include "exfat_raw.h" 22719c1e18SNamjae Jeon #include "exfat_fs.h" 23719c1e18SNamjae Jeon 24719c1e18SNamjae Jeon static char exfat_default_iocharset[] = CONFIG_EXFAT_DEFAULT_IOCHARSET; 25719c1e18SNamjae Jeon static struct kmem_cache *exfat_inode_cachep; 26719c1e18SNamjae Jeon 27719c1e18SNamjae Jeon static void exfat_free_iocharset(struct exfat_sb_info *sbi) 28719c1e18SNamjae Jeon { 29719c1e18SNamjae Jeon if (sbi->options.iocharset != exfat_default_iocharset) 30719c1e18SNamjae Jeon kfree(sbi->options.iocharset); 31719c1e18SNamjae Jeon } 32719c1e18SNamjae Jeon 33719c1e18SNamjae Jeon static void exfat_delayed_free(struct rcu_head *p) 34719c1e18SNamjae Jeon { 35719c1e18SNamjae Jeon struct exfat_sb_info *sbi = container_of(p, struct exfat_sb_info, rcu); 36719c1e18SNamjae Jeon 37719c1e18SNamjae Jeon unload_nls(sbi->nls_io); 38719c1e18SNamjae Jeon exfat_free_iocharset(sbi); 39719c1e18SNamjae Jeon exfat_free_upcase_table(sbi); 40719c1e18SNamjae Jeon kfree(sbi); 41719c1e18SNamjae Jeon } 42719c1e18SNamjae Jeon 43719c1e18SNamjae Jeon static void exfat_put_super(struct super_block *sb) 44719c1e18SNamjae Jeon { 45719c1e18SNamjae Jeon struct exfat_sb_info *sbi = EXFAT_SB(sb); 46719c1e18SNamjae Jeon 47719c1e18SNamjae Jeon mutex_lock(&sbi->s_lock); 48719c1e18SNamjae Jeon if (test_and_clear_bit(EXFAT_SB_DIRTY, &sbi->s_state)) 49719c1e18SNamjae Jeon sync_blockdev(sb->s_bdev); 50719c1e18SNamjae Jeon exfat_set_vol_flags(sb, VOL_CLEAN); 51719c1e18SNamjae Jeon exfat_free_bitmap(sbi); 52181a9e80STetsuhiro Kohada brelse(sbi->boot_bh); 53719c1e18SNamjae Jeon mutex_unlock(&sbi->s_lock); 54719c1e18SNamjae Jeon 55719c1e18SNamjae Jeon call_rcu(&sbi->rcu, exfat_delayed_free); 56719c1e18SNamjae Jeon } 57719c1e18SNamjae Jeon 58719c1e18SNamjae Jeon static int exfat_sync_fs(struct super_block *sb, int wait) 59719c1e18SNamjae Jeon { 60719c1e18SNamjae Jeon struct exfat_sb_info *sbi = EXFAT_SB(sb); 61719c1e18SNamjae Jeon int err = 0; 62719c1e18SNamjae Jeon 63719c1e18SNamjae Jeon /* If there are some dirty buffers in the bdev inode */ 64719c1e18SNamjae Jeon mutex_lock(&sbi->s_lock); 65719c1e18SNamjae Jeon if (test_and_clear_bit(EXFAT_SB_DIRTY, &sbi->s_state)) { 66719c1e18SNamjae Jeon sync_blockdev(sb->s_bdev); 67719c1e18SNamjae Jeon if (exfat_set_vol_flags(sb, VOL_CLEAN)) 68719c1e18SNamjae Jeon err = -EIO; 69719c1e18SNamjae Jeon } 70719c1e18SNamjae Jeon mutex_unlock(&sbi->s_lock); 71719c1e18SNamjae Jeon return err; 72719c1e18SNamjae Jeon } 73719c1e18SNamjae Jeon 74719c1e18SNamjae Jeon static int exfat_statfs(struct dentry *dentry, struct kstatfs *buf) 75719c1e18SNamjae Jeon { 76719c1e18SNamjae Jeon struct super_block *sb = dentry->d_sb; 77719c1e18SNamjae Jeon struct exfat_sb_info *sbi = EXFAT_SB(sb); 78719c1e18SNamjae Jeon unsigned long long id = huge_encode_dev(sb->s_bdev->bd_dev); 79719c1e18SNamjae Jeon 80719c1e18SNamjae Jeon if (sbi->used_clusters == EXFAT_CLUSTERS_UNTRACKED) { 81719c1e18SNamjae Jeon mutex_lock(&sbi->s_lock); 82719c1e18SNamjae Jeon if (exfat_count_used_clusters(sb, &sbi->used_clusters)) { 83719c1e18SNamjae Jeon mutex_unlock(&sbi->s_lock); 84719c1e18SNamjae Jeon return -EIO; 85719c1e18SNamjae Jeon } 86719c1e18SNamjae Jeon mutex_unlock(&sbi->s_lock); 87719c1e18SNamjae Jeon } 88719c1e18SNamjae Jeon 89719c1e18SNamjae Jeon buf->f_type = sb->s_magic; 90719c1e18SNamjae Jeon buf->f_bsize = sbi->cluster_size; 91719c1e18SNamjae Jeon buf->f_blocks = sbi->num_clusters - 2; /* clu 0 & 1 */ 92719c1e18SNamjae Jeon buf->f_bfree = buf->f_blocks - sbi->used_clusters; 93719c1e18SNamjae Jeon buf->f_bavail = buf->f_bfree; 94719c1e18SNamjae Jeon buf->f_fsid.val[0] = (unsigned int)id; 95719c1e18SNamjae Jeon buf->f_fsid.val[1] = (unsigned int)(id >> 32); 96719c1e18SNamjae Jeon /* Unicode utf16 255 characters */ 97719c1e18SNamjae Jeon buf->f_namelen = EXFAT_MAX_FILE_LEN * NLS_MAX_CHARSET_SIZE; 98719c1e18SNamjae Jeon return 0; 99719c1e18SNamjae Jeon } 100719c1e18SNamjae Jeon 101719c1e18SNamjae Jeon int exfat_set_vol_flags(struct super_block *sb, unsigned short new_flag) 102719c1e18SNamjae Jeon { 103719c1e18SNamjae Jeon struct exfat_sb_info *sbi = EXFAT_SB(sb); 104181a9e80STetsuhiro Kohada struct boot_sector *p_boot = (struct boot_sector *)sbi->boot_bh->b_data; 105cdc06129SJason Yan bool sync; 106719c1e18SNamjae Jeon 107719c1e18SNamjae Jeon /* flags are not changed */ 108719c1e18SNamjae Jeon if (sbi->vol_flag == new_flag) 109719c1e18SNamjae Jeon return 0; 110719c1e18SNamjae Jeon 111719c1e18SNamjae Jeon sbi->vol_flag = new_flag; 112719c1e18SNamjae Jeon 113719c1e18SNamjae Jeon /* skip updating volume dirty flag, 114719c1e18SNamjae Jeon * if this volume has been mounted with read-only 115719c1e18SNamjae Jeon */ 116719c1e18SNamjae Jeon if (sb_rdonly(sb)) 117719c1e18SNamjae Jeon return 0; 118719c1e18SNamjae Jeon 119181a9e80STetsuhiro Kohada p_boot->vol_flags = cpu_to_le16(new_flag); 120719c1e18SNamjae Jeon 121181a9e80STetsuhiro Kohada if (new_flag == VOL_DIRTY && !buffer_dirty(sbi->boot_bh)) 122719c1e18SNamjae Jeon sync = true; 123719c1e18SNamjae Jeon else 124719c1e18SNamjae Jeon sync = false; 125719c1e18SNamjae Jeon 126181a9e80STetsuhiro Kohada set_buffer_uptodate(sbi->boot_bh); 127181a9e80STetsuhiro Kohada mark_buffer_dirty(sbi->boot_bh); 128719c1e18SNamjae Jeon 129719c1e18SNamjae Jeon if (sync) 130181a9e80STetsuhiro Kohada sync_dirty_buffer(sbi->boot_bh); 131719c1e18SNamjae Jeon return 0; 132719c1e18SNamjae Jeon } 133719c1e18SNamjae Jeon 134719c1e18SNamjae Jeon static int exfat_show_options(struct seq_file *m, struct dentry *root) 135719c1e18SNamjae Jeon { 136719c1e18SNamjae Jeon struct super_block *sb = root->d_sb; 137719c1e18SNamjae Jeon struct exfat_sb_info *sbi = EXFAT_SB(sb); 138719c1e18SNamjae Jeon struct exfat_mount_options *opts = &sbi->options; 139719c1e18SNamjae Jeon 140719c1e18SNamjae Jeon /* Show partition info */ 141719c1e18SNamjae Jeon if (!uid_eq(opts->fs_uid, GLOBAL_ROOT_UID)) 142719c1e18SNamjae Jeon seq_printf(m, ",uid=%u", 143719c1e18SNamjae Jeon from_kuid_munged(&init_user_ns, opts->fs_uid)); 144719c1e18SNamjae Jeon if (!gid_eq(opts->fs_gid, GLOBAL_ROOT_GID)) 145719c1e18SNamjae Jeon seq_printf(m, ",gid=%u", 146719c1e18SNamjae Jeon from_kgid_munged(&init_user_ns, opts->fs_gid)); 147719c1e18SNamjae Jeon seq_printf(m, ",fmask=%04o,dmask=%04o", opts->fs_fmask, opts->fs_dmask); 148719c1e18SNamjae Jeon if (opts->allow_utime) 149719c1e18SNamjae Jeon seq_printf(m, ",allow_utime=%04o", opts->allow_utime); 150719c1e18SNamjae Jeon if (opts->utf8) 151719c1e18SNamjae Jeon seq_puts(m, ",iocharset=utf8"); 152719c1e18SNamjae Jeon else if (sbi->nls_io) 153719c1e18SNamjae Jeon seq_printf(m, ",iocharset=%s", sbi->nls_io->charset); 154719c1e18SNamjae Jeon if (opts->errors == EXFAT_ERRORS_CONT) 155719c1e18SNamjae Jeon seq_puts(m, ",errors=continue"); 156719c1e18SNamjae Jeon else if (opts->errors == EXFAT_ERRORS_PANIC) 157719c1e18SNamjae Jeon seq_puts(m, ",errors=panic"); 158719c1e18SNamjae Jeon else 159719c1e18SNamjae Jeon seq_puts(m, ",errors=remount-ro"); 160719c1e18SNamjae Jeon if (opts->discard) 161719c1e18SNamjae Jeon seq_puts(m, ",discard"); 162719c1e18SNamjae Jeon if (opts->time_offset) 163719c1e18SNamjae Jeon seq_printf(m, ",time_offset=%d", opts->time_offset); 164719c1e18SNamjae Jeon return 0; 165719c1e18SNamjae Jeon } 166719c1e18SNamjae Jeon 167719c1e18SNamjae Jeon static struct inode *exfat_alloc_inode(struct super_block *sb) 168719c1e18SNamjae Jeon { 169719c1e18SNamjae Jeon struct exfat_inode_info *ei; 170719c1e18SNamjae Jeon 171719c1e18SNamjae Jeon ei = kmem_cache_alloc(exfat_inode_cachep, GFP_NOFS); 172719c1e18SNamjae Jeon if (!ei) 173719c1e18SNamjae Jeon return NULL; 174719c1e18SNamjae Jeon 175719c1e18SNamjae Jeon init_rwsem(&ei->truncate_lock); 176719c1e18SNamjae Jeon return &ei->vfs_inode; 177719c1e18SNamjae Jeon } 178719c1e18SNamjae Jeon 179719c1e18SNamjae Jeon static void exfat_free_inode(struct inode *inode) 180719c1e18SNamjae Jeon { 181719c1e18SNamjae Jeon kmem_cache_free(exfat_inode_cachep, EXFAT_I(inode)); 182719c1e18SNamjae Jeon } 183719c1e18SNamjae Jeon 184719c1e18SNamjae Jeon static const struct super_operations exfat_sops = { 185719c1e18SNamjae Jeon .alloc_inode = exfat_alloc_inode, 186719c1e18SNamjae Jeon .free_inode = exfat_free_inode, 187719c1e18SNamjae Jeon .write_inode = exfat_write_inode, 188719c1e18SNamjae Jeon .evict_inode = exfat_evict_inode, 189719c1e18SNamjae Jeon .put_super = exfat_put_super, 190719c1e18SNamjae Jeon .sync_fs = exfat_sync_fs, 191719c1e18SNamjae Jeon .statfs = exfat_statfs, 192719c1e18SNamjae Jeon .show_options = exfat_show_options, 193719c1e18SNamjae Jeon }; 194719c1e18SNamjae Jeon 195719c1e18SNamjae Jeon enum { 196719c1e18SNamjae Jeon Opt_uid, 197719c1e18SNamjae Jeon Opt_gid, 198719c1e18SNamjae Jeon Opt_umask, 199719c1e18SNamjae Jeon Opt_dmask, 200719c1e18SNamjae Jeon Opt_fmask, 201719c1e18SNamjae Jeon Opt_allow_utime, 202719c1e18SNamjae Jeon Opt_charset, 203719c1e18SNamjae Jeon Opt_errors, 204719c1e18SNamjae Jeon Opt_discard, 205719c1e18SNamjae Jeon Opt_time_offset, 206907fa893SNamjae Jeon 207907fa893SNamjae Jeon /* Deprecated options */ 208907fa893SNamjae Jeon Opt_utf8, 209907fa893SNamjae Jeon Opt_debug, 210907fa893SNamjae Jeon Opt_namecase, 211907fa893SNamjae Jeon Opt_codepage, 212719c1e18SNamjae Jeon }; 213719c1e18SNamjae Jeon 2149acd0d53SValdis Kletnieks static const struct constant_table exfat_param_enums[] = { 2159acd0d53SValdis Kletnieks { "continue", EXFAT_ERRORS_CONT }, 2169acd0d53SValdis Kletnieks { "panic", EXFAT_ERRORS_PANIC }, 2179acd0d53SValdis Kletnieks { "remount-ro", EXFAT_ERRORS_RO }, 2189acd0d53SValdis Kletnieks {} 2199acd0d53SValdis Kletnieks }; 2209acd0d53SValdis Kletnieks 2219acd0d53SValdis Kletnieks static const struct fs_parameter_spec exfat_parameters[] = { 222719c1e18SNamjae Jeon fsparam_u32("uid", Opt_uid), 223719c1e18SNamjae Jeon fsparam_u32("gid", Opt_gid), 224719c1e18SNamjae Jeon fsparam_u32oct("umask", Opt_umask), 225719c1e18SNamjae Jeon fsparam_u32oct("dmask", Opt_dmask), 226719c1e18SNamjae Jeon fsparam_u32oct("fmask", Opt_fmask), 227719c1e18SNamjae Jeon fsparam_u32oct("allow_utime", Opt_allow_utime), 228719c1e18SNamjae Jeon fsparam_string("iocharset", Opt_charset), 2299acd0d53SValdis Kletnieks fsparam_enum("errors", Opt_errors, exfat_param_enums), 230719c1e18SNamjae Jeon fsparam_flag("discard", Opt_discard), 231719c1e18SNamjae Jeon fsparam_s32("time_offset", Opt_time_offset), 232907fa893SNamjae Jeon __fsparam(NULL, "utf8", Opt_utf8, fs_param_deprecated, 233907fa893SNamjae Jeon NULL), 234907fa893SNamjae Jeon __fsparam(NULL, "debug", Opt_debug, fs_param_deprecated, 235907fa893SNamjae Jeon NULL), 236907fa893SNamjae Jeon __fsparam(fs_param_is_u32, "namecase", Opt_namecase, 237907fa893SNamjae Jeon fs_param_deprecated, NULL), 238907fa893SNamjae Jeon __fsparam(fs_param_is_u32, "codepage", Opt_codepage, 239907fa893SNamjae Jeon fs_param_deprecated, NULL), 240719c1e18SNamjae Jeon {} 241719c1e18SNamjae Jeon }; 242719c1e18SNamjae Jeon 243719c1e18SNamjae Jeon static int exfat_parse_param(struct fs_context *fc, struct fs_parameter *param) 244719c1e18SNamjae Jeon { 245719c1e18SNamjae Jeon struct exfat_sb_info *sbi = fc->s_fs_info; 246719c1e18SNamjae Jeon struct exfat_mount_options *opts = &sbi->options; 247719c1e18SNamjae Jeon struct fs_parse_result result; 248719c1e18SNamjae Jeon int opt; 249719c1e18SNamjae Jeon 2509acd0d53SValdis Kletnieks opt = fs_parse(fc, exfat_parameters, param, &result); 251719c1e18SNamjae Jeon if (opt < 0) 252719c1e18SNamjae Jeon return opt; 253719c1e18SNamjae Jeon 254719c1e18SNamjae Jeon switch (opt) { 255719c1e18SNamjae Jeon case Opt_uid: 256719c1e18SNamjae Jeon opts->fs_uid = make_kuid(current_user_ns(), result.uint_32); 257719c1e18SNamjae Jeon break; 258719c1e18SNamjae Jeon case Opt_gid: 259719c1e18SNamjae Jeon opts->fs_gid = make_kgid(current_user_ns(), result.uint_32); 260719c1e18SNamjae Jeon break; 261719c1e18SNamjae Jeon case Opt_umask: 262719c1e18SNamjae Jeon opts->fs_fmask = result.uint_32; 263719c1e18SNamjae Jeon opts->fs_dmask = result.uint_32; 264719c1e18SNamjae Jeon break; 265719c1e18SNamjae Jeon case Opt_dmask: 266719c1e18SNamjae Jeon opts->fs_dmask = result.uint_32; 267719c1e18SNamjae Jeon break; 268719c1e18SNamjae Jeon case Opt_fmask: 269719c1e18SNamjae Jeon opts->fs_fmask = result.uint_32; 270719c1e18SNamjae Jeon break; 271719c1e18SNamjae Jeon case Opt_allow_utime: 272719c1e18SNamjae Jeon opts->allow_utime = result.uint_32 & 0022; 273719c1e18SNamjae Jeon break; 274719c1e18SNamjae Jeon case Opt_charset: 275719c1e18SNamjae Jeon exfat_free_iocharset(sbi); 276719c1e18SNamjae Jeon opts->iocharset = kstrdup(param->string, GFP_KERNEL); 277719c1e18SNamjae Jeon if (!opts->iocharset) 278719c1e18SNamjae Jeon return -ENOMEM; 279719c1e18SNamjae Jeon break; 280719c1e18SNamjae Jeon case Opt_errors: 281719c1e18SNamjae Jeon opts->errors = result.uint_32; 282719c1e18SNamjae Jeon break; 283719c1e18SNamjae Jeon case Opt_discard: 284719c1e18SNamjae Jeon opts->discard = 1; 285719c1e18SNamjae Jeon break; 286719c1e18SNamjae Jeon case Opt_time_offset: 287719c1e18SNamjae Jeon /* 288719c1e18SNamjae Jeon * Make the limit 24 just in case someone invents something 289719c1e18SNamjae Jeon * unusual. 290719c1e18SNamjae Jeon */ 291719c1e18SNamjae Jeon if (result.int_32 < -24 * 60 || result.int_32 > 24 * 60) 292719c1e18SNamjae Jeon return -EINVAL; 293719c1e18SNamjae Jeon opts->time_offset = result.int_32; 294719c1e18SNamjae Jeon break; 295907fa893SNamjae Jeon case Opt_utf8: 296907fa893SNamjae Jeon case Opt_debug: 297907fa893SNamjae Jeon case Opt_namecase: 298907fa893SNamjae Jeon case Opt_codepage: 299907fa893SNamjae Jeon break; 300719c1e18SNamjae Jeon default: 301719c1e18SNamjae Jeon return -EINVAL; 302719c1e18SNamjae Jeon } 303719c1e18SNamjae Jeon 304719c1e18SNamjae Jeon return 0; 305719c1e18SNamjae Jeon } 306719c1e18SNamjae Jeon 307719c1e18SNamjae Jeon static void exfat_hash_init(struct super_block *sb) 308719c1e18SNamjae Jeon { 309719c1e18SNamjae Jeon struct exfat_sb_info *sbi = EXFAT_SB(sb); 310719c1e18SNamjae Jeon int i; 311719c1e18SNamjae Jeon 312719c1e18SNamjae Jeon spin_lock_init(&sbi->inode_hash_lock); 313719c1e18SNamjae Jeon for (i = 0; i < EXFAT_HASH_SIZE; i++) 314719c1e18SNamjae Jeon INIT_HLIST_HEAD(&sbi->inode_hashtable[i]); 315719c1e18SNamjae Jeon } 316719c1e18SNamjae Jeon 317719c1e18SNamjae Jeon static int exfat_read_root(struct inode *inode) 318719c1e18SNamjae Jeon { 319719c1e18SNamjae Jeon struct super_block *sb = inode->i_sb; 320719c1e18SNamjae Jeon struct exfat_sb_info *sbi = EXFAT_SB(sb); 321719c1e18SNamjae Jeon struct exfat_inode_info *ei = EXFAT_I(inode); 322719c1e18SNamjae Jeon struct exfat_chain cdir; 323719c1e18SNamjae Jeon int num_subdirs, num_clu = 0; 324719c1e18SNamjae Jeon 325719c1e18SNamjae Jeon exfat_chain_set(&ei->dir, sbi->root_dir, 0, ALLOC_FAT_CHAIN); 326719c1e18SNamjae Jeon ei->entry = -1; 327719c1e18SNamjae Jeon ei->start_clu = sbi->root_dir; 328719c1e18SNamjae Jeon ei->flags = ALLOC_FAT_CHAIN; 329719c1e18SNamjae Jeon ei->type = TYPE_DIR; 330719c1e18SNamjae Jeon ei->version = 0; 331719c1e18SNamjae Jeon ei->rwoffset = 0; 332719c1e18SNamjae Jeon ei->hint_bmap.off = EXFAT_EOF_CLUSTER; 333719c1e18SNamjae Jeon ei->hint_stat.eidx = 0; 334719c1e18SNamjae Jeon ei->hint_stat.clu = sbi->root_dir; 335719c1e18SNamjae Jeon ei->hint_femp.eidx = EXFAT_HINT_NONE; 336719c1e18SNamjae Jeon 337719c1e18SNamjae Jeon exfat_chain_set(&cdir, sbi->root_dir, 0, ALLOC_FAT_CHAIN); 338719c1e18SNamjae Jeon if (exfat_count_num_clusters(sb, &cdir, &num_clu)) 339719c1e18SNamjae Jeon return -EIO; 340719c1e18SNamjae Jeon i_size_write(inode, num_clu << sbi->cluster_size_bits); 341719c1e18SNamjae Jeon 342719c1e18SNamjae Jeon num_subdirs = exfat_count_dir_entries(sb, &cdir); 343719c1e18SNamjae Jeon if (num_subdirs < 0) 344719c1e18SNamjae Jeon return -EIO; 345719c1e18SNamjae Jeon set_nlink(inode, num_subdirs + EXFAT_MIN_SUBDIR); 346719c1e18SNamjae Jeon 347719c1e18SNamjae Jeon inode->i_uid = sbi->options.fs_uid; 348719c1e18SNamjae Jeon inode->i_gid = sbi->options.fs_gid; 349719c1e18SNamjae Jeon inode_inc_iversion(inode); 350719c1e18SNamjae Jeon inode->i_generation = 0; 351719c1e18SNamjae Jeon inode->i_mode = exfat_make_mode(sbi, ATTR_SUBDIR, 0777); 352719c1e18SNamjae Jeon inode->i_op = &exfat_dir_inode_operations; 353719c1e18SNamjae Jeon inode->i_fop = &exfat_dir_operations; 354719c1e18SNamjae Jeon 355719c1e18SNamjae Jeon inode->i_blocks = ((i_size_read(inode) + (sbi->cluster_size - 1)) 356719c1e18SNamjae Jeon & ~(sbi->cluster_size - 1)) >> inode->i_blkbits; 357719c1e18SNamjae Jeon EXFAT_I(inode)->i_pos = ((loff_t)sbi->root_dir << 32) | 0xffffffff; 358719c1e18SNamjae Jeon EXFAT_I(inode)->i_size_aligned = i_size_read(inode); 359719c1e18SNamjae Jeon EXFAT_I(inode)->i_size_ondisk = i_size_read(inode); 360719c1e18SNamjae Jeon 361719c1e18SNamjae Jeon exfat_save_attr(inode, ATTR_SUBDIR); 362719c1e18SNamjae Jeon inode->i_mtime = inode->i_atime = inode->i_ctime = ei->i_crtime = 363719c1e18SNamjae Jeon current_time(inode); 36481df1ad4SEric Sandeen exfat_truncate_atime(&inode->i_atime); 365719c1e18SNamjae Jeon exfat_cache_init_inode(inode); 366719c1e18SNamjae Jeon return 0; 367719c1e18SNamjae Jeon } 368719c1e18SNamjae Jeon 36933404a15STetsuhiro Kohada static int exfat_calibrate_blocksize(struct super_block *sb, int logical_sect) 370719c1e18SNamjae Jeon { 371b0516833STetsuhiro Kohada struct exfat_sb_info *sbi = EXFAT_SB(sb); 372719c1e18SNamjae Jeon 373719c1e18SNamjae Jeon if (!is_power_of_2(logical_sect) || 374719c1e18SNamjae Jeon logical_sect < 512 || logical_sect > 4096) { 375d1727d55SJoe Perches exfat_err(sb, "bogus logical sector size %u", logical_sect); 37633404a15STetsuhiro Kohada return -EIO; 377719c1e18SNamjae Jeon } 378719c1e18SNamjae Jeon 379719c1e18SNamjae Jeon if (logical_sect < sb->s_blocksize) { 380d1727d55SJoe Perches exfat_err(sb, "logical sector size too small for device (logical sector size = %u)", 381719c1e18SNamjae Jeon logical_sect); 38233404a15STetsuhiro Kohada return -EIO; 383719c1e18SNamjae Jeon } 384719c1e18SNamjae Jeon 385719c1e18SNamjae Jeon if (logical_sect > sb->s_blocksize) { 386181a9e80STetsuhiro Kohada brelse(sbi->boot_bh); 387181a9e80STetsuhiro Kohada sbi->boot_bh = NULL; 388719c1e18SNamjae Jeon 389719c1e18SNamjae Jeon if (!sb_set_blocksize(sb, logical_sect)) { 390d1727d55SJoe Perches exfat_err(sb, "unable to set blocksize %u", 391d1727d55SJoe Perches logical_sect); 39233404a15STetsuhiro Kohada return -EIO; 393719c1e18SNamjae Jeon } 394181a9e80STetsuhiro Kohada sbi->boot_bh = sb_bread(sb, 0); 395181a9e80STetsuhiro Kohada if (!sbi->boot_bh) { 396d1727d55SJoe Perches exfat_err(sb, "unable to read boot sector (logical sector size = %lu)", 397719c1e18SNamjae Jeon sb->s_blocksize); 39833404a15STetsuhiro Kohada return -EIO; 39933404a15STetsuhiro Kohada } 40033404a15STetsuhiro Kohada } 40133404a15STetsuhiro Kohada return 0; 402719c1e18SNamjae Jeon } 403719c1e18SNamjae Jeon 40433404a15STetsuhiro Kohada static int exfat_read_boot_sector(struct super_block *sb) 405719c1e18SNamjae Jeon { 406181a9e80STetsuhiro Kohada struct boot_sector *p_boot; 407719c1e18SNamjae Jeon struct exfat_sb_info *sbi = EXFAT_SB(sb); 408719c1e18SNamjae Jeon 409719c1e18SNamjae Jeon /* set block size to read super block */ 410719c1e18SNamjae Jeon sb_min_blocksize(sb, 512); 411719c1e18SNamjae Jeon 412719c1e18SNamjae Jeon /* read boot sector */ 413181a9e80STetsuhiro Kohada sbi->boot_bh = sb_bread(sb, 0); 414181a9e80STetsuhiro Kohada if (!sbi->boot_bh) { 415d1727d55SJoe Perches exfat_err(sb, "unable to read boot sector"); 416719c1e18SNamjae Jeon return -EIO; 417719c1e18SNamjae Jeon } 418181a9e80STetsuhiro Kohada p_boot = (struct boot_sector *)sbi->boot_bh->b_data; 419719c1e18SNamjae Jeon 420181a9e80STetsuhiro Kohada /* check the validity of BOOT */ 421181a9e80STetsuhiro Kohada if (le16_to_cpu((p_boot->signature)) != BOOT_SIGNATURE) { 422d1727d55SJoe Perches exfat_err(sb, "invalid boot record signature"); 42333404a15STetsuhiro Kohada return -EINVAL; 424719c1e18SNamjae Jeon } 425719c1e18SNamjae Jeon 42633404a15STetsuhiro Kohada if (memcmp(p_boot->fs_name, STR_EXFAT, BOOTSEC_FS_NAME_LEN)) { 42733404a15STetsuhiro Kohada exfat_err(sb, "invalid fs_name"); /* fs_name may unprintable */ 42833404a15STetsuhiro Kohada return -EINVAL; 429719c1e18SNamjae Jeon } 430719c1e18SNamjae Jeon 431719c1e18SNamjae Jeon /* 43233404a15STetsuhiro Kohada * must_be_zero field must be filled with zero to prevent mounting 433719c1e18SNamjae Jeon * from FAT volume. 434719c1e18SNamjae Jeon */ 43533404a15STetsuhiro Kohada if (memchr_inv(p_boot->must_be_zero, 0, sizeof(p_boot->must_be_zero))) 43633404a15STetsuhiro Kohada return -EINVAL; 437719c1e18SNamjae Jeon 43833404a15STetsuhiro Kohada if (p_boot->num_fats != 1 && p_boot->num_fats != 2) { 439d1727d55SJoe Perches exfat_err(sb, "bogus number of FAT structure"); 44033404a15STetsuhiro Kohada return -EINVAL; 441719c1e18SNamjae Jeon } 442719c1e18SNamjae Jeon 443181a9e80STetsuhiro Kohada sbi->sect_per_clus = 1 << p_boot->sect_per_clus_bits; 444181a9e80STetsuhiro Kohada sbi->sect_per_clus_bits = p_boot->sect_per_clus_bits; 44533404a15STetsuhiro Kohada sbi->cluster_size_bits = p_boot->sect_per_clus_bits + 44633404a15STetsuhiro Kohada p_boot->sect_size_bits; 447719c1e18SNamjae Jeon sbi->cluster_size = 1 << sbi->cluster_size_bits; 448181a9e80STetsuhiro Kohada sbi->num_FAT_sectors = le32_to_cpu(p_boot->fat_length); 449181a9e80STetsuhiro Kohada sbi->FAT1_start_sector = le32_to_cpu(p_boot->fat_offset); 45033404a15STetsuhiro Kohada sbi->FAT2_start_sector = le32_to_cpu(p_boot->fat_offset); 45133404a15STetsuhiro Kohada if (p_boot->num_fats == 2) 45233404a15STetsuhiro Kohada sbi->FAT2_start_sector += sbi->num_FAT_sectors; 453181a9e80STetsuhiro Kohada sbi->data_start_sector = le32_to_cpu(p_boot->clu_offset); 454181a9e80STetsuhiro Kohada sbi->num_sectors = le64_to_cpu(p_boot->vol_length); 455719c1e18SNamjae Jeon /* because the cluster index starts with 2 */ 456181a9e80STetsuhiro Kohada sbi->num_clusters = le32_to_cpu(p_boot->clu_count) + 457719c1e18SNamjae Jeon EXFAT_RESERVED_CLUSTERS; 458719c1e18SNamjae Jeon 459181a9e80STetsuhiro Kohada sbi->root_dir = le32_to_cpu(p_boot->root_cluster); 460719c1e18SNamjae Jeon sbi->dentries_per_clu = 1 << 461719c1e18SNamjae Jeon (sbi->cluster_size_bits - DENTRY_SIZE_BITS); 462719c1e18SNamjae Jeon 463181a9e80STetsuhiro Kohada sbi->vol_flag = le16_to_cpu(p_boot->vol_flags); 464719c1e18SNamjae Jeon sbi->clu_srch_ptr = EXFAT_FIRST_CLUSTER; 465719c1e18SNamjae Jeon sbi->used_clusters = EXFAT_CLUSTERS_UNTRACKED; 466719c1e18SNamjae Jeon 46733404a15STetsuhiro Kohada /* check consistencies */ 46833404a15STetsuhiro Kohada if (sbi->num_FAT_sectors << p_boot->sect_size_bits < 46933404a15STetsuhiro Kohada sbi->num_clusters * 4) { 47033404a15STetsuhiro Kohada exfat_err(sb, "bogus fat length"); 47133404a15STetsuhiro Kohada return -EINVAL; 472719c1e18SNamjae Jeon } 47333404a15STetsuhiro Kohada if (sbi->data_start_sector < 47433404a15STetsuhiro Kohada sbi->FAT1_start_sector + sbi->num_FAT_sectors * p_boot->num_fats) { 47533404a15STetsuhiro Kohada exfat_err(sb, "bogus data start sector"); 47633404a15STetsuhiro Kohada return -EINVAL; 47733404a15STetsuhiro Kohada } 47833404a15STetsuhiro Kohada if (sbi->vol_flag & VOL_DIRTY) 47933404a15STetsuhiro Kohada exfat_warn(sb, "Volume was not properly unmounted. Some data may be corrupt. Please run fsck."); 48033404a15STetsuhiro Kohada if (sbi->vol_flag & ERR_MEDIUM) 48133404a15STetsuhiro Kohada exfat_warn(sb, "Medium has reported failures. Some data may be lost."); 482719c1e18SNamjae Jeon 483719c1e18SNamjae Jeon /* exFAT file size is limited by a disk volume size */ 484719c1e18SNamjae Jeon sb->s_maxbytes = (u64)(sbi->num_clusters - EXFAT_RESERVED_CLUSTERS) << 485719c1e18SNamjae Jeon sbi->cluster_size_bits; 486719c1e18SNamjae Jeon 48733404a15STetsuhiro Kohada /* check logical sector size */ 48833404a15STetsuhiro Kohada if (exfat_calibrate_blocksize(sb, 1 << p_boot->sect_size_bits)) 48933404a15STetsuhiro Kohada return -EIO; 49033404a15STetsuhiro Kohada 49133404a15STetsuhiro Kohada return 0; 49233404a15STetsuhiro Kohada } 49333404a15STetsuhiro Kohada 494*476189c0STetsuhiro Kohada static int exfat_verify_boot_region(struct super_block *sb) 495*476189c0STetsuhiro Kohada { 496*476189c0STetsuhiro Kohada struct buffer_head *bh = NULL; 497*476189c0STetsuhiro Kohada u32 chksum = 0; 498*476189c0STetsuhiro Kohada __le32 *p_sig, *p_chksum; 499*476189c0STetsuhiro Kohada int sn, i; 500*476189c0STetsuhiro Kohada 501*476189c0STetsuhiro Kohada /* read boot sector sub-regions */ 502*476189c0STetsuhiro Kohada for (sn = 0; sn < 11; sn++) { 503*476189c0STetsuhiro Kohada bh = sb_bread(sb, sn); 504*476189c0STetsuhiro Kohada if (!bh) 505*476189c0STetsuhiro Kohada return -EIO; 506*476189c0STetsuhiro Kohada 507*476189c0STetsuhiro Kohada if (sn != 0 && sn <= 8) { 508*476189c0STetsuhiro Kohada /* extended boot sector sub-regions */ 509*476189c0STetsuhiro Kohada p_sig = (__le32 *)&bh->b_data[sb->s_blocksize - 4]; 510*476189c0STetsuhiro Kohada if (le32_to_cpu(*p_sig) != EXBOOT_SIGNATURE) 511*476189c0STetsuhiro Kohada exfat_warn(sb, "Invalid exboot-signature(sector = %d): 0x%08x", 512*476189c0STetsuhiro Kohada sn, le32_to_cpu(*p_sig)); 513*476189c0STetsuhiro Kohada } 514*476189c0STetsuhiro Kohada 515*476189c0STetsuhiro Kohada chksum = exfat_calc_chksum32(bh->b_data, sb->s_blocksize, 516*476189c0STetsuhiro Kohada chksum, sn ? CS_DEFAULT : CS_BOOT_SECTOR); 517*476189c0STetsuhiro Kohada brelse(bh); 518*476189c0STetsuhiro Kohada } 519*476189c0STetsuhiro Kohada 520*476189c0STetsuhiro Kohada /* boot checksum sub-regions */ 521*476189c0STetsuhiro Kohada bh = sb_bread(sb, sn); 522*476189c0STetsuhiro Kohada if (!bh) 523*476189c0STetsuhiro Kohada return -EIO; 524*476189c0STetsuhiro Kohada 525*476189c0STetsuhiro Kohada for (i = 0; i < sb->s_blocksize; i += sizeof(u32)) { 526*476189c0STetsuhiro Kohada p_chksum = (__le32 *)&bh->b_data[i]; 527*476189c0STetsuhiro Kohada if (le32_to_cpu(*p_chksum) != chksum) { 528*476189c0STetsuhiro Kohada exfat_err(sb, "Invalid boot checksum (boot checksum : 0x%08x, checksum : 0x%08x)", 529*476189c0STetsuhiro Kohada le32_to_cpu(*p_chksum), chksum); 530*476189c0STetsuhiro Kohada brelse(bh); 531*476189c0STetsuhiro Kohada return -EINVAL; 532*476189c0STetsuhiro Kohada } 533*476189c0STetsuhiro Kohada } 534*476189c0STetsuhiro Kohada brelse(bh); 535*476189c0STetsuhiro Kohada return 0; 536*476189c0STetsuhiro Kohada } 537*476189c0STetsuhiro Kohada 53833404a15STetsuhiro Kohada /* mount the file system volume */ 53933404a15STetsuhiro Kohada static int __exfat_fill_super(struct super_block *sb) 54033404a15STetsuhiro Kohada { 54133404a15STetsuhiro Kohada int ret; 54233404a15STetsuhiro Kohada struct exfat_sb_info *sbi = EXFAT_SB(sb); 54333404a15STetsuhiro Kohada 54433404a15STetsuhiro Kohada ret = exfat_read_boot_sector(sb); 54533404a15STetsuhiro Kohada if (ret) { 54633404a15STetsuhiro Kohada exfat_err(sb, "failed to read boot sector"); 54733404a15STetsuhiro Kohada goto free_bh; 54833404a15STetsuhiro Kohada } 54933404a15STetsuhiro Kohada 550*476189c0STetsuhiro Kohada ret = exfat_verify_boot_region(sb); 551*476189c0STetsuhiro Kohada if (ret) { 552*476189c0STetsuhiro Kohada exfat_err(sb, "invalid boot region"); 553*476189c0STetsuhiro Kohada goto free_bh; 554*476189c0STetsuhiro Kohada } 555*476189c0STetsuhiro Kohada 556719c1e18SNamjae Jeon ret = exfat_create_upcase_table(sb); 557719c1e18SNamjae Jeon if (ret) { 558d1727d55SJoe Perches exfat_err(sb, "failed to load upcase table"); 559719c1e18SNamjae Jeon goto free_bh; 560719c1e18SNamjae Jeon } 561719c1e18SNamjae Jeon 562719c1e18SNamjae Jeon ret = exfat_load_bitmap(sb); 563719c1e18SNamjae Jeon if (ret) { 564d1727d55SJoe Perches exfat_err(sb, "failed to load alloc-bitmap"); 565719c1e18SNamjae Jeon goto free_upcase_table; 566719c1e18SNamjae Jeon } 567719c1e18SNamjae Jeon 568719c1e18SNamjae Jeon ret = exfat_count_used_clusters(sb, &sbi->used_clusters); 569719c1e18SNamjae Jeon if (ret) { 570d1727d55SJoe Perches exfat_err(sb, "failed to scan clusters"); 571719c1e18SNamjae Jeon goto free_alloc_bitmap; 572719c1e18SNamjae Jeon } 573719c1e18SNamjae Jeon 574719c1e18SNamjae Jeon return 0; 575719c1e18SNamjae Jeon 576719c1e18SNamjae Jeon free_alloc_bitmap: 577719c1e18SNamjae Jeon exfat_free_bitmap(sbi); 578719c1e18SNamjae Jeon free_upcase_table: 579719c1e18SNamjae Jeon exfat_free_upcase_table(sbi); 580719c1e18SNamjae Jeon free_bh: 581181a9e80STetsuhiro Kohada brelse(sbi->boot_bh); 582719c1e18SNamjae Jeon return ret; 583719c1e18SNamjae Jeon } 584719c1e18SNamjae Jeon 585719c1e18SNamjae Jeon static int exfat_fill_super(struct super_block *sb, struct fs_context *fc) 586719c1e18SNamjae Jeon { 587719c1e18SNamjae Jeon struct exfat_sb_info *sbi = sb->s_fs_info; 588719c1e18SNamjae Jeon struct exfat_mount_options *opts = &sbi->options; 589719c1e18SNamjae Jeon struct inode *root_inode; 590719c1e18SNamjae Jeon int err; 591719c1e18SNamjae Jeon 592719c1e18SNamjae Jeon if (opts->allow_utime == (unsigned short)-1) 593719c1e18SNamjae Jeon opts->allow_utime = ~opts->fs_dmask & 0022; 594719c1e18SNamjae Jeon 595719c1e18SNamjae Jeon if (opts->discard) { 596719c1e18SNamjae Jeon struct request_queue *q = bdev_get_queue(sb->s_bdev); 597719c1e18SNamjae Jeon 598b7e038a9SPali Rohár if (!blk_queue_discard(q)) { 599d1727d55SJoe Perches exfat_warn(sb, "mounting with \"discard\" option, but the device does not support discard"); 600719c1e18SNamjae Jeon opts->discard = 0; 601719c1e18SNamjae Jeon } 602b7e038a9SPali Rohár } 603719c1e18SNamjae Jeon 604719c1e18SNamjae Jeon sb->s_flags |= SB_NODIRATIME; 605719c1e18SNamjae Jeon sb->s_magic = EXFAT_SUPER_MAGIC; 606719c1e18SNamjae Jeon sb->s_op = &exfat_sops; 607719c1e18SNamjae Jeon 608674a9985SEric Sandeen sb->s_time_gran = 10 * NSEC_PER_MSEC; 609719c1e18SNamjae Jeon sb->s_time_min = EXFAT_MIN_TIMESTAMP_SECS; 610719c1e18SNamjae Jeon sb->s_time_max = EXFAT_MAX_TIMESTAMP_SECS; 611719c1e18SNamjae Jeon 612719c1e18SNamjae Jeon err = __exfat_fill_super(sb); 613719c1e18SNamjae Jeon if (err) { 614d1727d55SJoe Perches exfat_err(sb, "failed to recognize exfat type"); 615719c1e18SNamjae Jeon goto check_nls_io; 616719c1e18SNamjae Jeon } 617719c1e18SNamjae Jeon 618719c1e18SNamjae Jeon /* set up enough so that it can read an inode */ 619719c1e18SNamjae Jeon exfat_hash_init(sb); 620719c1e18SNamjae Jeon 621719c1e18SNamjae Jeon if (!strcmp(sbi->options.iocharset, "utf8")) 622719c1e18SNamjae Jeon opts->utf8 = 1; 623719c1e18SNamjae Jeon else { 624719c1e18SNamjae Jeon sbi->nls_io = load_nls(sbi->options.iocharset); 625719c1e18SNamjae Jeon if (!sbi->nls_io) { 626d1727d55SJoe Perches exfat_err(sb, "IO charset %s not found", 627719c1e18SNamjae Jeon sbi->options.iocharset); 628719c1e18SNamjae Jeon err = -EINVAL; 629719c1e18SNamjae Jeon goto free_table; 630719c1e18SNamjae Jeon } 631719c1e18SNamjae Jeon } 632719c1e18SNamjae Jeon 633719c1e18SNamjae Jeon if (sbi->options.utf8) 634719c1e18SNamjae Jeon sb->s_d_op = &exfat_utf8_dentry_ops; 635719c1e18SNamjae Jeon else 636719c1e18SNamjae Jeon sb->s_d_op = &exfat_dentry_ops; 637719c1e18SNamjae Jeon 638719c1e18SNamjae Jeon root_inode = new_inode(sb); 639719c1e18SNamjae Jeon if (!root_inode) { 640d1727d55SJoe Perches exfat_err(sb, "failed to allocate root inode"); 641719c1e18SNamjae Jeon err = -ENOMEM; 642719c1e18SNamjae Jeon goto free_table; 643719c1e18SNamjae Jeon } 644719c1e18SNamjae Jeon 645719c1e18SNamjae Jeon root_inode->i_ino = EXFAT_ROOT_INO; 646719c1e18SNamjae Jeon inode_set_iversion(root_inode, 1); 647719c1e18SNamjae Jeon err = exfat_read_root(root_inode); 648719c1e18SNamjae Jeon if (err) { 649d1727d55SJoe Perches exfat_err(sb, "failed to initialize root inode"); 650719c1e18SNamjae Jeon goto put_inode; 651719c1e18SNamjae Jeon } 652719c1e18SNamjae Jeon 653719c1e18SNamjae Jeon exfat_hash_inode(root_inode, EXFAT_I(root_inode)->i_pos); 654719c1e18SNamjae Jeon insert_inode_hash(root_inode); 655719c1e18SNamjae Jeon 656719c1e18SNamjae Jeon sb->s_root = d_make_root(root_inode); 657719c1e18SNamjae Jeon if (!sb->s_root) { 658d1727d55SJoe Perches exfat_err(sb, "failed to get the root dentry"); 659719c1e18SNamjae Jeon err = -ENOMEM; 660719c1e18SNamjae Jeon goto put_inode; 661719c1e18SNamjae Jeon } 662719c1e18SNamjae Jeon 663719c1e18SNamjae Jeon return 0; 664719c1e18SNamjae Jeon 665719c1e18SNamjae Jeon put_inode: 666719c1e18SNamjae Jeon iput(root_inode); 667719c1e18SNamjae Jeon sb->s_root = NULL; 668719c1e18SNamjae Jeon 669719c1e18SNamjae Jeon free_table: 670719c1e18SNamjae Jeon exfat_free_upcase_table(sbi); 671719c1e18SNamjae Jeon exfat_free_bitmap(sbi); 672181a9e80STetsuhiro Kohada brelse(sbi->boot_bh); 673719c1e18SNamjae Jeon 674719c1e18SNamjae Jeon check_nls_io: 675719c1e18SNamjae Jeon unload_nls(sbi->nls_io); 676719c1e18SNamjae Jeon exfat_free_iocharset(sbi); 677719c1e18SNamjae Jeon sb->s_fs_info = NULL; 678719c1e18SNamjae Jeon kfree(sbi); 679719c1e18SNamjae Jeon return err; 680719c1e18SNamjae Jeon } 681719c1e18SNamjae Jeon 682719c1e18SNamjae Jeon static int exfat_get_tree(struct fs_context *fc) 683719c1e18SNamjae Jeon { 684719c1e18SNamjae Jeon return get_tree_bdev(fc, exfat_fill_super); 685719c1e18SNamjae Jeon } 686719c1e18SNamjae Jeon 687719c1e18SNamjae Jeon static void exfat_free(struct fs_context *fc) 688719c1e18SNamjae Jeon { 689719c1e18SNamjae Jeon kfree(fc->s_fs_info); 690719c1e18SNamjae Jeon } 691719c1e18SNamjae Jeon 692719c1e18SNamjae Jeon static const struct fs_context_operations exfat_context_ops = { 693719c1e18SNamjae Jeon .parse_param = exfat_parse_param, 694719c1e18SNamjae Jeon .get_tree = exfat_get_tree, 695719c1e18SNamjae Jeon .free = exfat_free, 696719c1e18SNamjae Jeon }; 697719c1e18SNamjae Jeon 698719c1e18SNamjae Jeon static int exfat_init_fs_context(struct fs_context *fc) 699719c1e18SNamjae Jeon { 700719c1e18SNamjae Jeon struct exfat_sb_info *sbi; 701719c1e18SNamjae Jeon 702719c1e18SNamjae Jeon sbi = kzalloc(sizeof(struct exfat_sb_info), GFP_KERNEL); 703719c1e18SNamjae Jeon if (!sbi) 704719c1e18SNamjae Jeon return -ENOMEM; 705719c1e18SNamjae Jeon 706719c1e18SNamjae Jeon mutex_init(&sbi->s_lock); 707719c1e18SNamjae Jeon ratelimit_state_init(&sbi->ratelimit, DEFAULT_RATELIMIT_INTERVAL, 708719c1e18SNamjae Jeon DEFAULT_RATELIMIT_BURST); 709719c1e18SNamjae Jeon 710719c1e18SNamjae Jeon sbi->options.fs_uid = current_uid(); 711719c1e18SNamjae Jeon sbi->options.fs_gid = current_gid(); 712719c1e18SNamjae Jeon sbi->options.fs_fmask = current->fs->umask; 713719c1e18SNamjae Jeon sbi->options.fs_dmask = current->fs->umask; 714719c1e18SNamjae Jeon sbi->options.allow_utime = -1; 715719c1e18SNamjae Jeon sbi->options.iocharset = exfat_default_iocharset; 716719c1e18SNamjae Jeon sbi->options.errors = EXFAT_ERRORS_RO; 717719c1e18SNamjae Jeon 718719c1e18SNamjae Jeon fc->s_fs_info = sbi; 719719c1e18SNamjae Jeon fc->ops = &exfat_context_ops; 720719c1e18SNamjae Jeon return 0; 721719c1e18SNamjae Jeon } 722719c1e18SNamjae Jeon 723719c1e18SNamjae Jeon static struct file_system_type exfat_fs_type = { 724719c1e18SNamjae Jeon .owner = THIS_MODULE, 725719c1e18SNamjae Jeon .name = "exfat", 726719c1e18SNamjae Jeon .init_fs_context = exfat_init_fs_context, 7279acd0d53SValdis Kletnieks .parameters = exfat_parameters, 728719c1e18SNamjae Jeon .kill_sb = kill_block_super, 729719c1e18SNamjae Jeon .fs_flags = FS_REQUIRES_DEV, 730719c1e18SNamjae Jeon }; 731719c1e18SNamjae Jeon 732719c1e18SNamjae Jeon static void exfat_inode_init_once(void *foo) 733719c1e18SNamjae Jeon { 734719c1e18SNamjae Jeon struct exfat_inode_info *ei = (struct exfat_inode_info *)foo; 735719c1e18SNamjae Jeon 736719c1e18SNamjae Jeon INIT_HLIST_NODE(&ei->i_hash_fat); 737719c1e18SNamjae Jeon inode_init_once(&ei->vfs_inode); 738719c1e18SNamjae Jeon } 739719c1e18SNamjae Jeon 740719c1e18SNamjae Jeon static int __init init_exfat_fs(void) 741719c1e18SNamjae Jeon { 742719c1e18SNamjae Jeon int err; 743719c1e18SNamjae Jeon 744719c1e18SNamjae Jeon err = exfat_cache_init(); 745719c1e18SNamjae Jeon if (err) 746719c1e18SNamjae Jeon return err; 747719c1e18SNamjae Jeon 748719c1e18SNamjae Jeon exfat_inode_cachep = kmem_cache_create("exfat_inode_cache", 749719c1e18SNamjae Jeon sizeof(struct exfat_inode_info), 750719c1e18SNamjae Jeon 0, SLAB_RECLAIM_ACCOUNT | SLAB_MEM_SPREAD, 751719c1e18SNamjae Jeon exfat_inode_init_once); 752719c1e18SNamjae Jeon if (!exfat_inode_cachep) { 753719c1e18SNamjae Jeon err = -ENOMEM; 754719c1e18SNamjae Jeon goto shutdown_cache; 755719c1e18SNamjae Jeon } 756719c1e18SNamjae Jeon 757719c1e18SNamjae Jeon err = register_filesystem(&exfat_fs_type); 758719c1e18SNamjae Jeon if (err) 759719c1e18SNamjae Jeon goto destroy_cache; 760719c1e18SNamjae Jeon 761719c1e18SNamjae Jeon return 0; 762719c1e18SNamjae Jeon 763719c1e18SNamjae Jeon destroy_cache: 764719c1e18SNamjae Jeon kmem_cache_destroy(exfat_inode_cachep); 765719c1e18SNamjae Jeon shutdown_cache: 766719c1e18SNamjae Jeon exfat_cache_shutdown(); 767719c1e18SNamjae Jeon return err; 768719c1e18SNamjae Jeon } 769719c1e18SNamjae Jeon 770719c1e18SNamjae Jeon static void __exit exit_exfat_fs(void) 771719c1e18SNamjae Jeon { 772719c1e18SNamjae Jeon /* 773719c1e18SNamjae Jeon * Make sure all delayed rcu free inodes are flushed before we 774719c1e18SNamjae Jeon * destroy cache. 775719c1e18SNamjae Jeon */ 776719c1e18SNamjae Jeon rcu_barrier(); 777719c1e18SNamjae Jeon kmem_cache_destroy(exfat_inode_cachep); 778719c1e18SNamjae Jeon unregister_filesystem(&exfat_fs_type); 779719c1e18SNamjae Jeon exfat_cache_shutdown(); 780719c1e18SNamjae Jeon } 781719c1e18SNamjae Jeon 782719c1e18SNamjae Jeon module_init(init_exfat_fs); 783719c1e18SNamjae Jeon module_exit(exit_exfat_fs); 784719c1e18SNamjae Jeon 785cd76ac25SThomas Backlund MODULE_ALIAS_FS("exfat"); 786719c1e18SNamjae Jeon MODULE_LICENSE("GPL"); 787719c1e18SNamjae Jeon MODULE_DESCRIPTION("exFAT filesystem support"); 788719c1e18SNamjae Jeon MODULE_AUTHOR("Samsung Electronics Co., Ltd."); 789