From a7a8f4a1e6b309b5365be784a07bbda1ceab2d9e Mon Sep 17 00:00:00 2001 From: Martin Kaistra Date: Tue, 7 Jul 2020 12:31:59 +0200 Subject: ubifs: add option to specify version for new file systems Instead of creating ubifs file systems with UBIFS_FORMAT_VERSION by default, add a module parameter ubifs.default_version to allow the user to specify the desired version. Valid values are 4 to UBIFS_FORMAT_VERSION (currently 5). This way, one can for example create a file system with version 4 on kernel 4.19 which can still be mounted rw when downgrading to kernel 4.9. Signed-off-by: Martin Kaistra Signed-off-by: Richard Weinberger --- fs/ubifs/sb.c | 5 +++-- fs/ubifs/super.c | 18 ++++++++++++++++++ fs/ubifs/ubifs.h | 1 + 3 files changed, 22 insertions(+), 2 deletions(-) diff --git a/fs/ubifs/sb.c b/fs/ubifs/sb.c index 4b4b65b48c57..c0d3e4008d23 100644 --- a/fs/ubifs/sb.c +++ b/fs/ubifs/sb.c @@ -174,7 +174,8 @@ static int create_default_filesystem(struct ubifs_info *c) tmp64 = (long long)max_buds * c->leb_size; if (big_lpt) sup_flags |= UBIFS_FLG_BIGLPT; - sup_flags |= UBIFS_FLG_DOUBLE_HASH; + if (ubifs_default_version > 4) + sup_flags |= UBIFS_FLG_DOUBLE_HASH; if (ubifs_authenticated(c)) { sup_flags |= UBIFS_FLG_AUTHENTICATION; @@ -200,7 +201,7 @@ static int create_default_filesystem(struct ubifs_info *c) sup->jhead_cnt = cpu_to_le32(DEFAULT_JHEADS_CNT); sup->fanout = cpu_to_le32(DEFAULT_FANOUT); sup->lsave_cnt = cpu_to_le32(c->lsave_cnt); - sup->fmt_version = cpu_to_le32(UBIFS_FORMAT_VERSION); + sup->fmt_version = cpu_to_le32(ubifs_default_version); sup->time_gran = cpu_to_le32(DEFAULT_TIME_GRAN); if (c->mount_opts.override_compr) sup->default_compr = cpu_to_le16(c->mount_opts.compr_type); diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c index 7fc2f3f07c16..a2420c900275 100644 --- a/fs/ubifs/super.c +++ b/fs/ubifs/super.c @@ -26,6 +26,24 @@ #include #include "ubifs.h" +static int ubifs_default_version_set(const char *val, const struct kernel_param *kp) +{ + int n = 0, ret; + + ret = kstrtoint(val, 10, &n); + if (ret != 0 || n < 4 || n > UBIFS_FORMAT_VERSION) + return -EINVAL; + return param_set_int(val, kp); +} + +static const struct kernel_param_ops ubifs_default_version_ops = { + .set = ubifs_default_version_set, + .get = param_get_int, +}; + +int ubifs_default_version = UBIFS_FORMAT_VERSION; +module_param_cb(default_version, &ubifs_default_version_ops, &ubifs_default_version, 0600); + /* * Maximum amount of memory we may 'kmalloc()' without worrying that we are * allocating too much. diff --git a/fs/ubifs/ubifs.h b/fs/ubifs/ubifs.h index bff682309fbe..4ffd832e3b93 100644 --- a/fs/ubifs/ubifs.h +++ b/fs/ubifs/ubifs.h @@ -1504,6 +1504,7 @@ extern const struct file_operations ubifs_dir_operations; extern const struct inode_operations ubifs_dir_inode_operations; extern const struct inode_operations ubifs_symlink_inode_operations; extern struct ubifs_compressor *ubifs_compressors[UBIFS_COMPR_TYPES_CNT]; +extern int ubifs_default_version; /* auth.c */ static inline int ubifs_authenticated(const struct ubifs_info *c) -- cgit v1.2.3