From f53d47cb5897a356bf6344edff3b1ac949e7ad54 Mon Sep 17 00:00:00 2001 From: Namjae Jeon Date: Tue, 4 Feb 2020 09:18:10 +0900 Subject: [PATCH] exfat: linux 4.16 kernel build support Signed-off-by: Namjae Jeon --- Makefile | 2 +- dir.c | 11 +++ file.c | 13 ++++ inode.c | 16 +++- namei.c | 110 ++++++++++++++++++++++++++ super.c | 229 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- 6 files changed, 376 insertions(+), 5 deletions(-) diff --git a/Makefile b/Makefile index e8bdca201a20..0dbdda3ba2ef 100644 --- a/Makefile +++ b/Makefile @@ -6,7 +6,7 @@ ifneq ($(KERNELRELEASE),) obj-$(CONFIG_EXFAT_FS) += exfat.o exfat-y := inode.o namei.o dir.o super.o fatent.o cache.o nls.o misc.o \ - file.o balloc.io + file.o balloc.o else # Called from external kernel module build diff --git a/dir.c b/dir.c index 4b91afb0f051..aefd8859a8f6 100644 --- a/dir.c +++ b/dir.c @@ -3,6 +3,7 @@ * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd. */ +#include #include #include #include @@ -443,7 +444,11 @@ int exfat_init_dir_entry(struct inode *inode, struct exfat_chain *p_dir, { struct super_block *sb = inode->i_sb; struct exfat_sb_info *sbi = EXFAT_SB(sb); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0) struct timespec64 ts = current_time(inode); +#else + struct timespec64 ts = CURRENT_TIME_SEC; +#endif sector_t sector; struct exfat_dentry *ep; struct buffer_head *bh; @@ -884,7 +889,13 @@ struct exfat_entry_set_cache *exfat_get_dentry_set(struct super_block *sb, num_entries = type == ES_ALL_ENTRIES ? ep->dentry.file.num_ext + 1 : type; + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 0, 0) es = kmalloc(struct_size(es, entries, num_entries), GFP_KERNEL); +#else + es = kmalloc((offsetof(struct exfat_entry_set_cache, entries) + + (num_entries) * sizeof(struct exfat_dentry)), GFP_KERNEL); +#endif if (!es) goto release_bh; diff --git a/file.c b/file.c index 483f683757aa..79fce874c8dc 100644 --- a/file.c +++ b/file.c @@ -3,6 +3,7 @@ * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd. */ +#include #include #include #include @@ -20,7 +21,11 @@ static int exfat_cont_expand(struct inode *inode, loff_t size) if (err) return err; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0) inode->i_ctime = inode->i_mtime = current_time(inode); +#else + inode->i_ctime = inode->i_mtime = CURRENT_TIME_SEC; +#endif mark_inode_dirty(inode); if (!IS_SYNC(inode)) @@ -160,7 +165,11 @@ int __exfat_truncate(struct inode *inode, loff_t new_size) return -EIO; ep2 = ep + 1; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0) ts = current_time(inode); +#else + ts = CURRENT_TIME_SEC; +#endif exfat_set_entry_time(sbi, &ts, &ep->dentry.file.modify_tz, &ep->dentry.file.modify_time, @@ -243,7 +252,11 @@ void exfat_truncate(struct inode *inode, loff_t size) if (err) goto write_size; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0) inode->i_ctime = inode->i_mtime = current_time(inode); +#else + inode->i_ctime = inode->i_mtime = CURRENT_TIME_SEC; +#endif if (IS_DIRSYNC(inode)) exfat_sync_inode(inode); else diff --git a/inode.c b/inode.c index 06887492f54b..45ac2e7f3e45 100644 --- a/inode.c +++ b/inode.c @@ -3,6 +3,7 @@ * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd. */ +#include #include #include #include @@ -12,8 +13,9 @@ #include #include #include +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 0, 0) #include - +#endif #include "exfat_raw.h" #include "exfat_fs.h" @@ -437,7 +439,11 @@ static int exfat_write_end(struct file *file, struct address_space *mapping, exfat_write_failed(mapping, pos+len); if (!(err < 0) && !(ei->attr & ATTR_ARCHIVE)) { +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0) inode->i_mtime = inode->i_ctime = current_time(inode); +#else + inode->i_mtime = inode->i_ctime = CURRENT_TIME_SEC; +#endif ei->attr |= ATTR_ARCHIVE; mark_inode_dirty(inode); } @@ -582,7 +588,11 @@ static int exfat_fill_inode(struct inode *inode, struct exfat_dir_entry *info) inode->i_uid = sbi->options.fs_uid; inode->i_gid = sbi->options.fs_gid; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 0, 0) inode_inc_iversion(inode); +#else + inode->i_version++; +#endif inode->i_generation = prandom_u32(); if (info->attr & ATTR_SUBDIR) { /* directory */ @@ -640,7 +650,11 @@ struct inode *exfat_build_inode(struct super_block *sb, goto out; } inode->i_ino = iunique(sb, EXFAT_ROOT_INO); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 0, 0) inode_set_iversion(inode, 1); +#else + inode->i_version = 1; +#endif err = exfat_fill_inode(inode, info); if (err) { iput(inode); diff --git a/namei.c b/namei.c index a8681d91f569..930ae52482d9 100644 --- a/namei.c +++ b/namei.c @@ -3,7 +3,10 @@ * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd. */ +#include +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 0, 0) #include +#endif #include #include #include @@ -59,8 +62,13 @@ static int exfat_d_revalidate(struct dentry *dentry, unsigned int flags) return 0; spin_lock(&dentry->d_lock); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 0, 0) ret = inode_eq_iversion(d_inode(dentry->d_parent), exfat_d_version(dentry)); +#else + if (dentry->d_parent->d_inode->i_version != exfat_d_version(dentry)) + ret = 0; +#endif spin_unlock(&dentry->d_lock); return ret; } @@ -580,8 +588,16 @@ static int exfat_create(struct inode *dir, struct dentry *dentry, umode_t mode, if (err) goto unlock; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 0, 0) inode_inc_iversion(dir); +#else + dir->i_version++; +#endif +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0) dir->i_ctime = dir->i_mtime = current_time(dir); +#else + dir->i_ctime = dir->i_mtime = CURRENT_TIME_SEC; +#endif if (IS_DIRSYNC(dir)) exfat_sync_inode(dir); else @@ -592,9 +608,19 @@ static int exfat_create(struct inode *dir, struct dentry *dentry, umode_t mode, if (IS_ERR(inode)) goto unlock; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 0, 0) inode_inc_iversion(inode); +#else + inode->i_version++; +#endif + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0) inode->i_mtime = inode->i_atime = inode->i_ctime = EXFAT_I(inode)->i_crtime = current_time(inode); +#else + inode->i_mtime = inode->i_atime = inode->i_ctime = + EXFAT_I(inode)->i_crtime = CURRENT_TIME_SEC; +#endif /* timestamp is already written, so mark_inode_dirty() is unneeded. */ d_instantiate(dentry, inode); @@ -629,10 +655,18 @@ static int exfat_find(struct inode *dir, struct qstr *qname, return num_entries; /* check the validation of hint_stat and initialize it if required */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 0, 0) if (ei->version != (inode_peek_iversion_raw(dir) & 0xffffffff)) { +#else + if (ei->version != (dir->i_version & 0xffffffff)) { +#endif ei->hint_stat.clu = cdir.dir; ei->hint_stat.eidx = 0; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 0, 0) ei->version = (inode_peek_iversion_raw(dir) & 0xffffffff); +#else + ei->version = (dir->i_version & 0xffffffff); +#endif ei->hint_femp.eidx = EXFAT_HINT_NONE; } @@ -798,7 +832,11 @@ static struct dentry *exfat_lookup(struct inode *dir, struct dentry *dentry, out: mutex_unlock(&EXFAT_SB(sb)->s_lock); if (!inode) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 0, 0) exfat_d_version_set(dentry, inode_query_iversion(dir)); +#else + exfat_d_version_set(dentry, dir->i_version); +#endif return d_splice_alias(inode, dentry); unlock: @@ -852,17 +890,33 @@ static int exfat_unlink(struct inode *dir, struct dentry *dentry) ei->dir.dir = DIR_DELETED; exfat_set_vol_flags(sb, VOL_CLEAN); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 0, 0) inode_inc_iversion(dir); +#else + dir->i_version++; +#endif +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0) dir->i_mtime = dir->i_atime = current_time(dir); +#else + dir->i_mtime = dir->i_atime = CURRENT_TIME_SEC; +#endif if (IS_DIRSYNC(dir)) exfat_sync_inode(dir); else mark_inode_dirty(dir); clear_nlink(inode); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0) inode->i_mtime = inode->i_atime = current_time(inode); +#else + inode->i_mtime = inode->i_atime = CURRENT_TIME_SEC; +#endif exfat_unhash_inode(inode); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 0, 0) exfat_d_version_set(dentry, inode_query_iversion(dir)); +#else + exfat_d_version_set(dentry, dir->i_version); +#endif unlock: mutex_unlock(&EXFAT_SB(sb)->s_lock); return err; @@ -885,8 +939,17 @@ static int exfat_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) if (err) goto unlock; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 0, 0) inode_inc_iversion(dir); +#else + dir->i_version++; +#endif + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0) dir->i_ctime = dir->i_mtime = current_time(dir); +#else + dir->i_ctime = dir->i_mtime = CURRENT_TIME_SEC; +#endif if (IS_DIRSYNC(dir)) exfat_sync_inode(dir); else @@ -900,9 +963,18 @@ static int exfat_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) goto unlock; } +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 0, 0) inode_inc_iversion(inode); +#else + inode->i_version++; +#endif +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0) inode->i_mtime = inode->i_atime = inode->i_ctime = EXFAT_I(inode)->i_crtime = current_time(inode); +#else + inode->i_mtime = inode->i_atime = inode->i_ctime = + EXFAT_I(inode)->i_crtime = CURRENT_TIME_SEC; +#endif /* timestamp is already written, so mark_inode_dirty() is unneeded. */ d_instantiate(dentry, inode); @@ -1017,8 +1089,16 @@ static int exfat_rmdir(struct inode *dir, struct dentry *dentry) ei->dir.dir = DIR_DELETED; exfat_set_vol_flags(sb, VOL_CLEAN); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 0, 0) inode_inc_iversion(dir); +#else + dir->i_version++; +#endif +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0) dir->i_mtime = dir->i_atime = current_time(dir); +#else + dir->i_mtime = dir->i_atime = CURRENT_TIME_SEC; +#endif if (IS_DIRSYNC(dir)) exfat_sync_inode(dir); else @@ -1026,9 +1106,17 @@ static int exfat_rmdir(struct inode *dir, struct dentry *dentry) drop_nlink(dir); clear_nlink(inode); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0) inode->i_mtime = inode->i_atime = current_time(inode); +#else + inode->i_mtime = inode->i_atime = CURRENT_TIME_SEC; +#endif exfat_unhash_inode(inode); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 0, 0) exfat_d_version_set(dentry, inode_query_iversion(dir)); +#else + exfat_d_version_set(dentry, dir->i_version); +#endif unlock: mutex_unlock(&EXFAT_SB(inode->i_sb)->s_lock); return err; @@ -1384,9 +1472,18 @@ static int exfat_rename(struct inode *old_dir, struct dentry *old_dentry, if (err) goto unlock; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 0, 0) inode_inc_iversion(new_dir); +#else + new_dir->i_version++; +#endif +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0) new_dir->i_ctime = new_dir->i_mtime = new_dir->i_atime = EXFAT_I(new_dir)->i_crtime = current_time(new_dir); +#else + new_dir->i_ctime = new_dir->i_mtime = new_dir->i_atime = + EXFAT_I(new_dir)->i_crtime = CURRENT_TIME_SEC; +#endif if (IS_DIRSYNC(new_dir)) exfat_sync_inode(new_dir); else @@ -1407,8 +1504,16 @@ static int exfat_rename(struct inode *old_dir, struct dentry *old_dentry, inc_nlink(new_dir); } +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 0, 0) inode_inc_iversion(old_dir); +#else + old_dir->i_version++; +#endif +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0) old_dir->i_ctime = old_dir->i_mtime = current_time(old_dir); +#else + old_dir->i_ctime = old_dir->i_mtime = CURRENT_TIME_SEC; +#endif if (IS_DIRSYNC(old_dir)) exfat_sync_inode(old_dir); else @@ -1427,8 +1532,13 @@ static int exfat_rename(struct inode *old_dir, struct dentry *old_dentry, "abnormal access to an inode dropped"); WARN_ON(new_inode->i_nlink == 0); } +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0) new_inode->i_ctime = EXFAT_I(new_inode)->i_crtime = current_time(new_inode); +#else + new_inode->i_ctime = EXFAT_I(new_inode)->i_crtime = + CURRENT_TIME_SEC; +#endif } unlock: diff --git a/super.c b/super.c index f06e0b53e393..d805bf57c646 100644 --- a/super.c +++ b/super.c @@ -3,8 +3,14 @@ * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd. */ +#include +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 0) #include #include +#else +#include +#include +#endif #include #include #include @@ -14,13 +20,20 @@ #include #include #include -#include #include #include +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 0, 0) +#include +#endif + #include "exfat_raw.h" #include "exfat_fs.h" +#ifndef CONFIG_EXFAT_DEFAULT_IOCHARSET /* if Kconfig lacked iocharset */ +#define CONFIG_EXFAT_DEFAULT_IOCHARSET "utf8" +#endif + static char exfat_default_iocharset[] = CONFIG_EXFAT_DEFAULT_IOCHARSET; static struct kmem_cache *exfat_inode_cachep; @@ -185,14 +198,31 @@ static struct inode *exfat_alloc_inode(struct super_block *sb) return &ei->vfs_inode; } +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 0) static void exfat_free_inode(struct inode *inode) { kmem_cache_free(exfat_inode_cachep, EXFAT_I(inode)); } +#else +static void exfat_i_callback(struct rcu_head *head) +{ + struct inode *inode = container_of(head, struct inode, i_rcu); + kmem_cache_free(exfat_inode_cachep, EXFAT_I(inode)); +} + +static void exfat_destroy_inode(struct inode *inode) +{ + call_rcu(&inode->i_rcu, exfat_i_callback); +} +#endif static const struct super_operations exfat_sops = { .alloc_inode = exfat_alloc_inode, +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 0) .free_inode = exfat_free_inode, +#else + .destroy_inode = exfat_destroy_inode, +#endif .write_inode = exfat_write_inode, .evict_inode = exfat_evict_inode, .put_super = exfat_put_super, @@ -201,6 +231,7 @@ static const struct super_operations exfat_sops = { .show_options = exfat_show_options, }; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 0) enum { Opt_uid, Opt_gid, @@ -299,6 +330,137 @@ static int exfat_parse_param(struct fs_context *fc, struct fs_parameter *param) return 0; } +#else +enum { + Opt_uid, + Opt_gid, + Opt_umask, + Opt_dmask, + Opt_fmask, + Opt_allow_utime, + Opt_charset, + Opt_err_cont, + Opt_err_panic, + Opt_err_ro, + Opt_err, + Opt_discard, + Opt_fs, +}; + +static const match_table_t exfat_tokens = { + {Opt_uid, "uid=%u"}, + {Opt_gid, "gid=%u"}, + {Opt_umask, "umask=%o"}, + {Opt_dmask, "dmask=%o"}, + {Opt_fmask, "fmask=%o"}, + {Opt_allow_utime, "allow_utime=%o"}, + {Opt_charset, "iocharset=%s"}, + {Opt_err_cont, "errors=continue"}, + {Opt_err_panic, "errors=panic"}, + {Opt_err_ro, "errors=remount-ro"}, + {Opt_discard, "discard"}, + {Opt_err, NULL} +}; + +static int parse_options(struct super_block *sb, char *options, int silent, + struct exfat_mount_options *opts) +{ + char *p; + substring_t args[MAX_OPT_ARGS]; + int option; + char *tmpstr; + + opts->fs_uid = current_uid(); + opts->fs_gid = current_gid(); + opts->fs_fmask = opts->fs_dmask = current->fs->umask; + opts->allow_utime = -1; + opts->iocharset = exfat_default_iocharset; + opts->utf8 = 0; + opts->errors = EXFAT_ERRORS_RO; + opts->discard = 0; + + if (!options) + goto out; + + while ((p = strsep(&options, ",")) != NULL) { + int token; + + if (!*p) + continue; + token = match_token(p, exfat_tokens, args); + switch (token) { + case Opt_uid: + if (match_int(&args[0], &option)) + return 0; + opts->fs_uid = make_kuid(current_user_ns(), option); + break; + case Opt_gid: + if (match_int(&args[0], &option)) + return 0; + opts->fs_gid = make_kgid(current_user_ns(), option); + break; + case Opt_umask: + case Opt_dmask: + case Opt_fmask: + if (match_octal(&args[0], &option)) + return 0; + if (token != Opt_dmask) + opts->fs_fmask = option; + if (token != Opt_fmask) + opts->fs_dmask = option; + break; + case Opt_allow_utime: + if (match_octal(&args[0], &option)) + return 0; + opts->allow_utime = option & (0022); + break; + case Opt_charset: + if (opts->iocharset != exfat_default_iocharset) + kfree(opts->iocharset); + tmpstr = match_strdup(&args[0]); + if (!tmpstr) + return -ENOMEM; + opts->iocharset = tmpstr; + break; + case Opt_err_cont: + opts->errors = EXFAT_ERRORS_CONT; + break; + case Opt_err_panic: + opts->errors = EXFAT_ERRORS_PANIC; + break; + case Opt_err_ro: + opts->errors = EXFAT_ERRORS_RO; + break; + case Opt_discard: + opts->discard = 1; + break; + default: + if (!silent) { + exfat_msg(sb, KERN_ERR, + "unrecognized mount option \"%s\" or missing value", + p); + } + return -EINVAL; + } + } + +out: + if (opts->allow_utime == -1) + opts->allow_utime = ~opts->fs_dmask & (0022); + + if (opts->discard) { + struct request_queue *q = bdev_get_queue(sb->s_bdev); + + if (!blk_queue_discard(q)) + exfat_msg(sb, KERN_WARNING, + "mounting with \"discard\" option, but the device does not support discard"); + opts->discard = 0; + } + + return 0; +} +#endif + static void exfat_hash_init(struct super_block *sb) { @@ -342,7 +504,12 @@ static int exfat_read_root(struct inode *inode) inode->i_uid = sbi->options.fs_uid; inode->i_gid = sbi->options.fs_gid; + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 0, 0) inode_inc_iversion(inode); +#else + inode->i_version++; +#endif inode->i_generation = 0; inode->i_mode = exfat_make_mode(sbi, ATTR_SUBDIR, 0777); inode->i_op = &exfat_dir_inode_operations; @@ -355,8 +522,13 @@ static int exfat_read_root(struct inode *inode) EXFAT_I(inode)->i_size_ondisk = i_size_read(inode); exfat_save_attr(inode, ATTR_SUBDIR); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0) inode->i_mtime = inode->i_atime = inode->i_ctime = ei->i_crtime = current_time(inode); +#else + inode->i_mtime = inode->i_atime = inode->i_ctime = ei->i_crtime = + CURRENT_TIME_SEC; +#endif exfat_cache_init_inode(inode); return 0; } @@ -524,12 +696,17 @@ free_bh: return ret; } +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 0) static int exfat_fill_super(struct super_block *sb, struct fs_context *fc) +#else +static int exfat_fill_super(struct super_block *sb, void *data, int silent) +#endif { - struct exfat_sb_info *sbi = sb->s_fs_info; - struct exfat_mount_options *opts = &sbi->options; struct inode *root_inode; int err; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 0) + struct exfat_sb_info *sbi = sb->s_fs_info; + struct exfat_mount_options *opts = &sbi->options; if (opts->allow_utime == (unsigned short)-1) opts->allow_utime = ~opts->fs_dmask & 0022; @@ -542,14 +719,39 @@ static int exfat_fill_super(struct super_block *sb, struct fs_context *fc) "mounting with \"discard\" option, but the device does not support discard"); opts->discard = 0; } +#else + struct exfat_sb_info *sbi; + + /* + * GFP_KERNEL is ok here, because while we do hold the + * supeblock lock, memory pressure can't call back into + * the filesystem, since we're only just about to mount + * it and have no inodes etc active! + */ + sbi = kzalloc(sizeof(struct exfat_sb_info), GFP_KERNEL); + if (!sbi) + return -ENOMEM; + + mutex_init(&sbi->s_lock); + sb->s_fs_info = sbi; + ratelimit_state_init(&sbi->ratelimit, DEFAULT_RATELIMIT_INTERVAL, + DEFAULT_RATELIMIT_BURST); + err = parse_options(sb, data, silent, &sbi->options); + if (err) { + exfat_msg(sb, KERN_ERR, "failed to parse options"); + goto check_nls_io; + } +#endif sb->s_flags |= SB_NODIRATIME; sb->s_magic = EXFAT_SUPER_MAGIC; sb->s_op = &exfat_sops; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 0, 0) sb->s_time_gran = 1; sb->s_time_min = EXFAT_MIN_TIMESTAMP_SECS; sb->s_time_max = EXFAT_MAX_TIMESTAMP_SECS; +#endif err = __exfat_fill_super(sb); if (err) { @@ -561,7 +763,11 @@ static int exfat_fill_super(struct super_block *sb, struct fs_context *fc) exfat_hash_init(sb); if (!strcmp(sbi->options.iocharset, "utf8")) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 0) opts->utf8 = 1; +#else + sbi->options.utf8 = 1; +#endif else { sbi->nls_io = load_nls(sbi->options.iocharset); if (!sbi->nls_io) { @@ -585,7 +791,12 @@ static int exfat_fill_super(struct super_block *sb, struct fs_context *fc) } root_inode->i_ino = EXFAT_ROOT_INO; + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 0, 0) inode_set_iversion(root_inode, 1); +#else + root_inode->i_version = 1; +#endif err = exfat_read_root(root_inode); if (err) { exfat_msg(sb, KERN_ERR, "failed to initialize root inode."); @@ -620,6 +831,7 @@ check_nls_io: return err; } +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 0) static int exfat_get_tree(struct fs_context *fc) { return get_tree_bdev(fc, exfat_fill_super); @@ -660,12 +872,23 @@ static int exfat_init_fs_context(struct fs_context *fc) fc->ops = &exfat_context_ops; return 0; } +#else +static struct dentry *exfat_fs_mount(struct file_system_type *fs_type, + int flags, const char *dev_name, void *data) +{ + return mount_bdev(fs_type, flags, dev_name, data, exfat_fill_super); +} +#endif static struct file_system_type exfat_fs_type = { .owner = THIS_MODULE, .name = "exfat", +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 0) .init_fs_context = exfat_init_fs_context, .parameters = &exfat_parameters, +#else + .mount = exfat_fs_mount, +#endif .kill_sb = kill_block_super, .fs_flags = FS_REQUIRES_DEV, };