From f35157417215ec138c920320c746fdb3e04ef1d5 Mon Sep 17 00:00:00 2001 From: David Howells Date: Tue, 4 Jul 2017 17:25:02 +0100 Subject: Provide a function to create a NUL-terminated string from unterminated data Provide a function, kmemdup_nul(), that will create a NUL-terminated string from an unterminated character array where the length is known in advance. This is better than kstrndup() in situations where we already know the string length as the strnlen() in kstrndup() is superfluous. Signed-off-by: David Howells Signed-off-by: Al Viro --- include/linux/string.h | 1 + mm/util.c | 24 ++++++++++++++++++++++++ 2 files changed, 25 insertions(+) diff --git a/include/linux/string.h b/include/linux/string.h index 537918f8a98e..3dd944cfe171 100644 --- a/include/linux/string.h +++ b/include/linux/string.h @@ -131,6 +131,7 @@ extern char *kstrdup(const char *s, gfp_t gfp) __malloc; extern const char *kstrdup_const(const char *s, gfp_t gfp); extern char *kstrndup(const char *s, size_t len, gfp_t gfp); extern void *kmemdup(const void *src, size_t len, gfp_t gfp); +extern char *kmemdup_nul(const char *s, size_t len, gfp_t gfp); extern char **argv_split(gfp_t gfp, const char *str, int *argcp); extern void argv_free(char **argv); diff --git a/mm/util.c b/mm/util.c index 26be6407abd7..21ddf90f883d 100644 --- a/mm/util.c +++ b/mm/util.c @@ -83,6 +83,8 @@ EXPORT_SYMBOL(kstrdup_const); * @s: the string to duplicate * @max: read at most @max chars from @s * @gfp: the GFP mask used in the kmalloc() call when allocating memory + * + * Note: Use kmemdup_nul() instead if the size is known exactly. */ char *kstrndup(const char *s, size_t max, gfp_t gfp) { @@ -120,6 +122,28 @@ void *kmemdup(const void *src, size_t len, gfp_t gfp) } EXPORT_SYMBOL(kmemdup); +/** + * kmemdup_nul - Create a NUL-terminated string from unterminated data + * @s: The data to stringify + * @len: The size of the data + * @gfp: the GFP mask used in the kmalloc() call when allocating memory + */ +char *kmemdup_nul(const char *s, size_t len, gfp_t gfp) +{ + char *buf; + + if (!s) + return NULL; + + buf = kmalloc_track_caller(len + 1, gfp); + if (buf) { + memcpy(buf, s, len); + buf[len] = '\0'; + } + return buf; +} +EXPORT_SYMBOL(kmemdup_nul); + /** * memdup_user - duplicate memory region from user space * -- cgit v1.2.3-59-g8ed1b From dd111b31e951c4ffb3a525b51b11d240118693c1 Mon Sep 17 00:00:00 2001 From: David Howells Date: Tue, 4 Jul 2017 17:25:09 +0100 Subject: VFS: Clean up whitespace in fs/namespace.c and fs/super.c Clean up line terminal whitespace in fs/namespace.c and fs/super.c. Signed-off-by: David Howells Signed-off-by: Al Viro --- fs/namespace.c | 4 ++-- fs/super.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/fs/namespace.c b/fs/namespace.c index 5a4438445bf7..544ab84642eb 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -1656,7 +1656,7 @@ out_unlock: namespace_unlock(); } -/* +/* * Is the caller allowed to modify his namespace? */ static inline bool may_mount(void) @@ -2210,7 +2210,7 @@ static int do_loopback(struct path *path, const char *old_name, err = -EINVAL; if (mnt_ns_loop(old_path.dentry)) - goto out; + goto out; mp = lock_mount(path); err = PTR_ERR(mp); diff --git a/fs/super.c b/fs/super.c index adb0c0de428c..dfb56a9665d8 100644 --- a/fs/super.c +++ b/fs/super.c @@ -508,7 +508,7 @@ retry: return ERR_PTR(-ENOMEM); goto retry; } - + err = set(s, data); if (err) { spin_unlock(&sb_lock); @@ -771,7 +771,7 @@ restart: spin_unlock(&sb_lock); return NULL; } - + struct super_block *user_get_super(dev_t dev) { struct super_block *sb; -- cgit v1.2.3-59-g8ed1b From ee416bcdba9975065de571e09de1f7ebfde2156a Mon Sep 17 00:00:00 2001 From: David Howells Date: Tue, 4 Jul 2017 17:25:16 +0100 Subject: VFS: Make get_filesystem() return the affected filesystem Make get_filesystem() return a pointer to the filesystem on which it just got a ref. Suggested-by: Rasmus Villemoes Signed-off-by: David Howells Signed-off-by: Al Viro --- fs/filesystems.c | 3 ++- include/linux/fs.h | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/fs/filesystems.c b/fs/filesystems.c index cac75547d35c..591e52d23ed4 100644 --- a/fs/filesystems.c +++ b/fs/filesystems.c @@ -33,9 +33,10 @@ static struct file_system_type *file_systems; static DEFINE_RWLOCK(file_systems_lock); /* WARNING: This can be used only if we _already_ own a reference */ -void get_filesystem(struct file_system_type *fs) +struct file_system_type *get_filesystem(struct file_system_type *fs) { __module_get(fs->owner); + return fs; } void put_filesystem(struct file_system_type *fs) diff --git a/include/linux/fs.h b/include/linux/fs.h index 803e5a9b2654..bc0c054894b9 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -2956,7 +2956,7 @@ extern int generic_block_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, u64 start, u64 len, get_block_t *get_block); -extern void get_filesystem(struct file_system_type *fs); +extern struct file_system_type *get_filesystem(struct file_system_type *fs); extern void put_filesystem(struct file_system_type *fs); extern struct file_system_type *get_fs_type(const char *name); extern struct super_block *get_super(struct block_device *); -- cgit v1.2.3-59-g8ed1b From cdf01226b26e98c79c13b335fbe0cbbbe850cf44 Mon Sep 17 00:00:00 2001 From: David Howells Date: Tue, 4 Jul 2017 17:25:22 +0100 Subject: VFS: Provide empty name qstr Provide an empty name (ie. "") qstr for general use. Signed-off-by: David Howells Signed-off-by: Al Viro --- fs/dcache.c | 8 ++++++-- fs/gfs2/dir.c | 3 +-- fs/namei.c | 3 +-- fs/nsfs.c | 3 +-- fs/pipe.c | 3 +-- include/linux/dcache.h | 5 +++++ 6 files changed, 15 insertions(+), 10 deletions(-) diff --git a/fs/dcache.c b/fs/dcache.c index a9f995f6859e..95efb7b2bf84 100644 --- a/fs/dcache.c +++ b/fs/dcache.c @@ -90,6 +90,11 @@ EXPORT_SYMBOL(rename_lock); static struct kmem_cache *dentry_cache __read_mostly; +const struct qstr empty_name = QSTR_INIT("", 0); +EXPORT_SYMBOL(empty_name); +const struct qstr slash_name = QSTR_INIT("/", 1); +EXPORT_SYMBOL(slash_name); + /* * This is the single most critical data structure when it comes * to the dcache: the hashtable for lookups. Somebody should try @@ -1578,8 +1583,7 @@ struct dentry *__d_alloc(struct super_block *sb, const struct qstr *name) */ dentry->d_iname[DNAME_INLINE_LEN-1] = 0; if (unlikely(!name)) { - static const struct qstr anon = QSTR_INIT("/", 1); - name = &anon; + name = &slash_name; dname = dentry->d_iname; } else if (name->len > DNAME_INLINE_LEN-1) { size_t size = offsetof(struct external_name, name[1]); diff --git a/fs/gfs2/dir.c b/fs/gfs2/dir.c index 79113219be5f..a5dfff6a033e 100644 --- a/fs/gfs2/dir.c +++ b/fs/gfs2/dir.c @@ -872,7 +872,6 @@ static struct gfs2_leaf *new_leaf(struct inode *inode, struct buffer_head **pbh, struct buffer_head *bh; struct gfs2_leaf *leaf; struct gfs2_dirent *dent; - struct qstr name = { .name = "" }; struct timespec tv = current_time(inode); error = gfs2_alloc_blocks(ip, &bn, &n, 0, NULL); @@ -896,7 +895,7 @@ static struct gfs2_leaf *new_leaf(struct inode *inode, struct buffer_head **pbh, leaf->lf_sec = cpu_to_be64(tv.tv_sec); memset(leaf->lf_reserved2, 0, sizeof(leaf->lf_reserved2)); dent = (struct gfs2_dirent *)(leaf+1); - gfs2_qstr2dirent(&name, bh->b_size - sizeof(struct gfs2_leaf), dent); + gfs2_qstr2dirent(&empty_name, bh->b_size - sizeof(struct gfs2_leaf), dent); *pbh = bh; return leaf; } diff --git a/fs/namei.c b/fs/namei.c index 6571a5f5112e..0d35760fee00 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -3400,7 +3400,6 @@ out: struct dentry *vfs_tmpfile(struct dentry *dentry, umode_t mode, int open_flag) { - static const struct qstr name = QSTR_INIT("/", 1); struct dentry *child = NULL; struct inode *dir = dentry->d_inode; struct inode *inode; @@ -3414,7 +3413,7 @@ struct dentry *vfs_tmpfile(struct dentry *dentry, umode_t mode, int open_flag) if (!dir->i_op->tmpfile) goto out_err; error = -ENOMEM; - child = d_alloc(dentry, &name); + child = d_alloc(dentry, &slash_name); if (unlikely(!child)) goto out_err; error = dir->i_op->tmpfile(dir, child, mode); diff --git a/fs/nsfs.c b/fs/nsfs.c index f3db56e83dd2..08127a2b8559 100644 --- a/fs/nsfs.c +++ b/fs/nsfs.c @@ -53,7 +53,6 @@ static void nsfs_evict(struct inode *inode) static void *__ns_get_path(struct path *path, struct ns_common *ns) { struct vfsmount *mnt = nsfs_mnt; - struct qstr qname = { .name = "", }; struct dentry *dentry; struct inode *inode; unsigned long d; @@ -85,7 +84,7 @@ slow: inode->i_fop = &ns_file_operations; inode->i_private = ns; - dentry = d_alloc_pseudo(mnt->mnt_sb, &qname); + dentry = d_alloc_pseudo(mnt->mnt_sb, &empty_name); if (!dentry) { iput(inode); return ERR_PTR(-ENOMEM); diff --git a/fs/pipe.c b/fs/pipe.c index 73b84baf58f8..97e5be897753 100644 --- a/fs/pipe.c +++ b/fs/pipe.c @@ -739,13 +739,12 @@ int create_pipe_files(struct file **res, int flags) struct inode *inode = get_pipe_inode(); struct file *f; struct path path; - static struct qstr name = { .name = "" }; if (!inode) return -ENFILE; err = -ENOMEM; - path.dentry = d_alloc_pseudo(pipe_mnt->mnt_sb, &name); + path.dentry = d_alloc_pseudo(pipe_mnt->mnt_sb, &empty_name); if (!path.dentry) goto err_inode; path.mnt = mntget(pipe_mnt); diff --git a/include/linux/dcache.h b/include/linux/dcache.h index d2e38dc6172c..3f65a4fa72ed 100644 --- a/include/linux/dcache.h +++ b/include/linux/dcache.h @@ -55,6 +55,11 @@ struct qstr { #define QSTR_INIT(n,l) { { { .len = l } }, .name = n } +extern const char empty_string[]; +extern const struct qstr empty_name; +extern const char slash_string[]; +extern const struct qstr slash_name; + struct dentry_stat_t { long nr_dentry; long nr_unused; -- cgit v1.2.3-59-g8ed1b From c3d98ea08291ca26144780f601e1fd39e4f20f7e Mon Sep 17 00:00:00 2001 From: David Howells Date: Wed, 5 Jul 2017 16:24:09 +0100 Subject: VFS: Don't use save/replace_mount_options if not using generic_show_options btrfs, debugfs, reiserfs and tracefs call save_mount_options() and reiserfs calls replace_mount_options(), but they then implement their own ->show_options() methods and don't touch s_options, rendering the saved options unnecessary. I'm trying to eliminate s_options to make it easier to implement a context-based mount where the mount options can be passed individually over a file descriptor. Remove the calls to save/replace_mount_options() call in these cases. Signed-off-by: David Howells cc: Chris Mason cc: Greg Kroah-Hartman cc: Steven Rostedt cc: linux-btrfs@vger.kernel.org cc: reiserfs-devel@vger.kernel.org Signed-off-by: Al Viro --- fs/btrfs/super.c | 1 - fs/debugfs/inode.c | 2 -- fs/reiserfs/super.c | 4 ---- fs/tracefs/inode.c | 2 -- 4 files changed, 9 deletions(-) diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c index 4f1cdd5058f1..8e9758b3eb23 100644 --- a/fs/btrfs/super.c +++ b/fs/btrfs/super.c @@ -1164,7 +1164,6 @@ static int btrfs_fill_super(struct super_block *sb, goto fail_close; } - save_mount_options(sb, data); cleancache_init_fs(sb); sb->s_flags |= MS_ACTIVE; return 0; diff --git a/fs/debugfs/inode.c b/fs/debugfs/inode.c index e892ae7d89f8..0dc9e9c0e0f8 100644 --- a/fs/debugfs/inode.c +++ b/fs/debugfs/inode.c @@ -203,8 +203,6 @@ static int debug_fill_super(struct super_block *sb, void *data, int silent) struct debugfs_fs_info *fsi; int err; - save_mount_options(sb, data); - fsi = kzalloc(sizeof(struct debugfs_fs_info), GFP_KERNEL); sb->s_fs_info = fsi; if (!fsi) { diff --git a/fs/reiserfs/super.c b/fs/reiserfs/super.c index 685f1e056998..306e4e9d172d 100644 --- a/fs/reiserfs/super.c +++ b/fs/reiserfs/super.c @@ -1599,8 +1599,6 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg) } out_ok_unlocked: - if (new_opts) - replace_mount_options(s, new_opts); return 0; out_err_unlock: @@ -1916,8 +1914,6 @@ static int reiserfs_fill_super(struct super_block *s, void *data, int silent) char *qf_names[REISERFS_MAXQUOTAS] = {}; unsigned int qfmt = 0; - save_mount_options(s, data); - sbi = kzalloc(sizeof(struct reiserfs_sb_info), GFP_KERNEL); if (!sbi) return -ENOMEM; diff --git a/fs/tracefs/inode.c b/fs/tracefs/inode.c index 328e89c2cf83..bea8ad876bf9 100644 --- a/fs/tracefs/inode.c +++ b/fs/tracefs/inode.c @@ -270,8 +270,6 @@ static int trace_fill_super(struct super_block *sb, void *data, int silent) struct tracefs_fs_info *fsi; int err; - save_mount_options(sb, data); - fsi = kzalloc(sizeof(struct tracefs_fs_info), GFP_KERNEL); sb->s_fs_info = fsi; if (!fsi) { -- cgit v1.2.3-59-g8ed1b From 4a25220d4e43bb2461823dbc7eb1502a34087958 Mon Sep 17 00:00:00 2001 From: David Howells Date: Wed, 5 Jul 2017 16:24:18 +0100 Subject: hugetlbfs: Implement show_options Implement the show_options superblock op for hugetlbfs as part of a bid to get rid of s_options and generic_show_options() to make it easier to implement a context-based mount where the mount options can be passed individually over a file descriptor. Note that the uid and gid should possibly be displayed relative to the viewer's user namespace. Signed-off-by: David Howells cc: Nadia Yvette Chambers Signed-off-by: Al Viro --- fs/hugetlbfs/inode.c | 70 +++++++++++++++++++++++++++++++++++++++---------- include/linux/hugetlb.h | 3 +++ 2 files changed, 59 insertions(+), 14 deletions(-) diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c index d44f5456eb9b..99b3b9836575 100644 --- a/fs/hugetlbfs/inode.c +++ b/fs/hugetlbfs/inode.c @@ -46,13 +46,13 @@ static const struct inode_operations hugetlbfs_dir_inode_operations; static const struct inode_operations hugetlbfs_inode_operations; struct hugetlbfs_config { - kuid_t uid; - kgid_t gid; - umode_t mode; - long max_hpages; - long nr_inodes; - struct hstate *hstate; - long min_hpages; + struct hstate *hstate; + long max_hpages; + long nr_inodes; + long min_hpages; + kuid_t uid; + kgid_t gid; + umode_t mode; }; struct hugetlbfs_inode_info { @@ -851,6 +851,46 @@ static int hugetlbfs_migrate_page(struct address_space *mapping, return MIGRATEPAGE_SUCCESS; } +/* + * Display the mount options in /proc/mounts. + */ +static int hugetlbfs_show_options(struct seq_file *m, struct dentry *root) +{ + struct hugetlbfs_sb_info *sbinfo = HUGETLBFS_SB(root->d_sb); + struct hugepage_subpool *spool = sbinfo->spool; + unsigned long hpage_size = huge_page_size(sbinfo->hstate); + unsigned hpage_shift = huge_page_shift(sbinfo->hstate); + char mod; + + if (!uid_eq(sbinfo->uid, GLOBAL_ROOT_UID)) + seq_printf(m, ",uid=%u", + from_kuid_munged(&init_user_ns, sbinfo->uid)); + if (!gid_eq(sbinfo->gid, GLOBAL_ROOT_GID)) + seq_printf(m, ",gid=%u", + from_kgid_munged(&init_user_ns, sbinfo->gid)); + if (sbinfo->mode != 0755) + seq_printf(m, ",mode=%o", sbinfo->mode); + if (sbinfo->max_inodes != -1) + seq_printf(m, ",nr_inodes=%lu", sbinfo->max_inodes); + + hpage_size /= 1024; + mod = 'K'; + if (hpage_size >= 1024) { + hpage_size /= 1024; + mod = 'M'; + } + seq_printf(m, ",pagesize=%lu%c", hpage_size, mod); + if (spool) { + if (spool->max_hpages != -1) + seq_printf(m, ",size=%llu", + (unsigned long long)spool->max_hpages << hpage_shift); + if (spool->min_hpages != -1) + seq_printf(m, ",min_size=%llu", + (unsigned long long)spool->min_hpages << hpage_shift); + } + return 0; +} + static int hugetlbfs_statfs(struct dentry *dentry, struct kstatfs *buf) { struct hugetlbfs_sb_info *sbinfo = HUGETLBFS_SB(dentry->d_sb); @@ -1008,19 +1048,19 @@ static const struct super_operations hugetlbfs_ops = { .evict_inode = hugetlbfs_evict_inode, .statfs = hugetlbfs_statfs, .put_super = hugetlbfs_put_super, - .show_options = generic_show_options, + .show_options = hugetlbfs_show_options, }; -enum { NO_SIZE, SIZE_STD, SIZE_PERCENT }; +enum hugetlbfs_size_type { NO_SIZE, SIZE_STD, SIZE_PERCENT }; /* * Convert size option passed from command line to number of huge pages * in the pool specified by hstate. Size option could be in bytes * (val_type == SIZE_STD) or percentage of the pool (val_type == SIZE_PERCENT). */ -static long long +static long hugetlbfs_size_to_hpages(struct hstate *h, unsigned long long size_opt, - int val_type) + enum hugetlbfs_size_type val_type) { if (val_type == NO_SIZE) return -1; @@ -1042,7 +1082,7 @@ hugetlbfs_parse_options(char *options, struct hugetlbfs_config *pconfig) substring_t args[MAX_OPT_ARGS]; int option; unsigned long long max_size_opt = 0, min_size_opt = 0; - int max_val_type = NO_SIZE, min_val_type = NO_SIZE; + enum hugetlbfs_size_type max_val_type = NO_SIZE, min_val_type = NO_SIZE; if (!options) return 0; @@ -1156,8 +1196,6 @@ hugetlbfs_fill_super(struct super_block *sb, void *data, int silent) struct hugetlbfs_config config; struct hugetlbfs_sb_info *sbinfo; - save_mount_options(sb, data); - config.max_hpages = -1; /* No limit on size by default */ config.nr_inodes = -1; /* No limit on number of inodes by default */ config.uid = current_fsuid(); @@ -1178,6 +1216,10 @@ hugetlbfs_fill_super(struct super_block *sb, void *data, int silent) sbinfo->max_inodes = config.nr_inodes; sbinfo->free_inodes = config.nr_inodes; sbinfo->spool = NULL; + sbinfo->uid = config.uid; + sbinfo->gid = config.gid; + sbinfo->mode = config.mode; + /* * Allocate and initialize subpool if maximum or minimum size is * specified. Any needed reservations (for minimim size) are taken diff --git a/include/linux/hugetlb.h b/include/linux/hugetlb.h index b857fc8cc2ec..3b6eeaad2f77 100644 --- a/include/linux/hugetlb.h +++ b/include/linux/hugetlb.h @@ -262,6 +262,9 @@ struct hugetlbfs_sb_info { spinlock_t stat_lock; struct hstate *hstate; struct hugepage_subpool *spool; + kuid_t uid; + kgid_t gid; + umode_t mode; }; static inline struct hugetlbfs_sb_info *HUGETLBFS_SB(struct super_block *sb) -- cgit v1.2.3-59-g8ed1b From d86efb0df98afe0acdda7ed94963684c3fa7cccd Mon Sep 17 00:00:00 2001 From: David Howells Date: Wed, 5 Jul 2017 16:24:27 +0100 Subject: omfs: Implement show_options Implement the show_options superblock op for omfs as part of a bid to get rid of s_options and generic_show_options() to make it easier to implement a context-based mount where the mount options can be passed individually over a file descriptor. Note that the uid and gid should possibly be displayed relative to the viewer's user namespace. Signed-off-by: David Howells cc: Bob Copeland cc: linux-karma-devel@lists.sourceforge.net Signed-off-by: Al Viro --- fs/omfs/inode.c | 33 ++++++++++++++++++++++++++++++--- 1 file changed, 30 insertions(+), 3 deletions(-) diff --git a/fs/omfs/inode.c b/fs/omfs/inode.c index 8c9034ee7383..ee14af9e26f2 100644 --- a/fs/omfs/inode.c +++ b/fs/omfs/inode.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include "omfs.h" @@ -290,12 +291,40 @@ static int omfs_statfs(struct dentry *dentry, struct kstatfs *buf) return 0; } +/* + * Display the mount options in /proc/mounts. + */ +static int omfs_show_options(struct seq_file *m, struct dentry *root) +{ + struct omfs_sb_info *sbi = OMFS_SB(root->d_sb); + umode_t cur_umask = current_umask(); + + if (!uid_eq(sbi->s_uid, current_uid())) + seq_printf(m, ",uid=%u", + from_kuid_munged(&init_user_ns, sbi->s_uid)); + if (!gid_eq(sbi->s_gid, current_gid())) + seq_printf(m, ",gid=%u", + from_kgid_munged(&init_user_ns, sbi->s_gid)); + + if (sbi->s_dmask == sbi->s_fmask) { + if (sbi->s_fmask != cur_umask) + seq_printf(m, ",umask=%o", sbi->s_fmask); + } else { + if (sbi->s_dmask != cur_umask) + seq_printf(m, ",dmask=%o", sbi->s_dmask); + if (sbi->s_fmask != cur_umask) + seq_printf(m, ",fmask=%o", sbi->s_fmask); + } + + return 0; +} + static const struct super_operations omfs_sops = { .write_inode = omfs_write_inode, .evict_inode = omfs_evict_inode, .put_super = omfs_put_super, .statfs = omfs_statfs, - .show_options = generic_show_options, + .show_options = omfs_show_options, }; /* @@ -434,8 +463,6 @@ static int omfs_fill_super(struct super_block *sb, void *data, int silent) struct inode *root; int ret = -EINVAL; - save_mount_options(sb, (char *) data); - sbi = kzalloc(sizeof(struct omfs_sb_info), GFP_KERNEL); if (!sbi) return -ENOMEM; -- cgit v1.2.3-59-g8ed1b From 349d743895e2371bda9a02a5b465b50cc24d2825 Mon Sep 17 00:00:00 2001 From: David Howells Date: Wed, 5 Jul 2017 16:24:34 +0100 Subject: pstore: Implement show_options Implement the show_options superblock op for pstore as part of a bid to get rid of s_options and generic_show_options() to make it easier to implement a context-based mount where the mount options can be passed individually over a file descriptor. Signed-off-by: David Howells cc: Kees Cook cc: Anton Vorontsov cc: Colin Cross cc: Tony Luck Signed-off-by: Al Viro --- fs/pstore/inode.c | 14 +++++++++++--- fs/pstore/internal.h | 3 +++ fs/pstore/platform.c | 2 +- 3 files changed, 15 insertions(+), 4 deletions(-) diff --git a/fs/pstore/inode.c b/fs/pstore/inode.c index 792a4e5f9226..913e839ac1f5 100644 --- a/fs/pstore/inode.c +++ b/fs/pstore/inode.c @@ -283,6 +283,16 @@ static void parse_options(char *options) } } +/* + * Display the mount options in /proc/mounts. + */ +static int pstore_show_options(struct seq_file *m, struct dentry *root) +{ + if (kmsg_bytes != PSTORE_DEFAULT_KMSG_BYTES) + seq_printf(m, ",kmsg_bytes=%lu", kmsg_bytes); + return 0; +} + static int pstore_remount(struct super_block *sb, int *flags, char *data) { sync_filesystem(sb); @@ -296,7 +306,7 @@ static const struct super_operations pstore_ops = { .drop_inode = generic_delete_inode, .evict_inode = pstore_evict_inode, .remount_fs = pstore_remount, - .show_options = generic_show_options, + .show_options = pstore_show_options, }; static struct super_block *pstore_sb; @@ -448,8 +458,6 @@ static int pstore_fill_super(struct super_block *sb, void *data, int silent) { struct inode *inode; - save_mount_options(sb, data); - pstore_sb = sb; sb->s_maxbytes = MAX_LFS_FILESIZE; diff --git a/fs/pstore/internal.h b/fs/pstore/internal.h index c416e653dc4f..4d5913130580 100644 --- a/fs/pstore/internal.h +++ b/fs/pstore/internal.h @@ -5,6 +5,9 @@ #include #include +#define PSTORE_DEFAULT_KMSG_BYTES 10240 +extern unsigned long kmsg_bytes; + #ifdef CONFIG_PSTORE_FTRACE extern void pstore_register_ftrace(void); extern void pstore_unregister_ftrace(void); diff --git a/fs/pstore/platform.c b/fs/pstore/platform.c index d468eec9b8a6..6640df40908d 100644 --- a/fs/pstore/platform.c +++ b/fs/pstore/platform.c @@ -99,7 +99,7 @@ static char *big_oops_buf; static size_t big_oops_buf_sz; /* How much of the console log to snapshot */ -static unsigned long kmsg_bytes = 10240; +unsigned long kmsg_bytes = PSTORE_DEFAULT_KMSG_BYTES; void pstore_set_kmsg_bytes(int bytes) { -- cgit v1.2.3-59-g8ed1b From 604ecf4288933dec3c235ed1ee575a154670c882 Mon Sep 17 00:00:00 2001 From: David Howells Date: Wed, 5 Jul 2017 16:24:42 +0100 Subject: ramfs: Implement show_options Implement the show_options superblock op for ramfs as part of a bid to get rid of s_options and generic_show_options() to make it easier to implement a context-based mount where the mount options can be passed individually over a file descriptor. Signed-off-by: David Howells Signed-off-by: Al Viro --- fs/ramfs/inode.c | 32 +++++++++++++++++++++----------- 1 file changed, 21 insertions(+), 11 deletions(-) diff --git a/fs/ramfs/inode.c b/fs/ramfs/inode.c index 26e45863e499..11201b2d06b9 100644 --- a/fs/ramfs/inode.c +++ b/fs/ramfs/inode.c @@ -38,6 +38,14 @@ #include #include "internal.h" +struct ramfs_mount_opts { + umode_t mode; +}; + +struct ramfs_fs_info { + struct ramfs_mount_opts mount_opts; +}; + #define RAMFS_DEFAULT_MODE 0755 static const struct super_operations ramfs_ops; @@ -149,14 +157,22 @@ static const struct inode_operations ramfs_dir_inode_operations = { .rename = simple_rename, }; +/* + * Display the mount options in /proc/mounts. + */ +static int ramfs_show_options(struct seq_file *m, struct dentry *root) +{ + struct ramfs_fs_info *fsi = root->d_sb->s_fs_info; + + if (fsi->mount_opts.mode != RAMFS_DEFAULT_MODE) + seq_printf(m, ",mode=%o", fsi->mount_opts.mode); + return 0; +} + static const struct super_operations ramfs_ops = { .statfs = simple_statfs, .drop_inode = generic_delete_inode, - .show_options = generic_show_options, -}; - -struct ramfs_mount_opts { - umode_t mode; + .show_options = ramfs_show_options, }; enum { @@ -169,10 +185,6 @@ static const match_table_t tokens = { {Opt_err, NULL} }; -struct ramfs_fs_info { - struct ramfs_mount_opts mount_opts; -}; - static int ramfs_parse_options(char *data, struct ramfs_mount_opts *opts) { substring_t args[MAX_OPT_ARGS]; @@ -211,8 +223,6 @@ int ramfs_fill_super(struct super_block *sb, void *data, int silent) struct inode *inode; int err; - save_mount_options(sb, data); - fsi = kzalloc(sizeof(struct ramfs_fs_info), GFP_KERNEL); sb->s_fs_info = fsi; if (!fsi) -- cgit v1.2.3-59-g8ed1b From 4cc7c1864bbd4cf80f6bdc8ba3217de5aa5f4688 Mon Sep 17 00:00:00 2001 From: David Howells Date: Wed, 5 Jul 2017 16:24:49 +0100 Subject: bpf: Implement show_options Implement the show_options superblock op for bpf as part of a bid to get rid of s_options and generic_show_options() to make it easier to implement a context-based mount where the mount options can be passed individually over a file descriptor. Signed-off-by: David Howells cc: Alexei Starovoitov cc: Daniel Borkmann cc: netdev@vger.kernel.org Signed-off-by: Al Viro --- kernel/bpf/inode.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/kernel/bpf/inode.c b/kernel/bpf/inode.c index 9bbd33497d3d..e833ed914358 100644 --- a/kernel/bpf/inode.c +++ b/kernel/bpf/inode.c @@ -377,10 +377,22 @@ static void bpf_evict_inode(struct inode *inode) bpf_any_put(inode->i_private, type); } +/* + * Display the mount options in /proc/mounts. + */ +static int bpf_show_options(struct seq_file *m, struct dentry *root) +{ + umode_t mode = d_inode(root)->i_mode & S_IALLUGO & ~S_ISVTX; + + if (mode != S_IRWXUGO) + seq_printf(m, ",mode=%o", mode); + return 0; +} + static const struct super_operations bpf_super_ops = { .statfs = simple_statfs, .drop_inode = generic_delete_inode, - .show_options = generic_show_options, + .show_options = bpf_show_options, .evict_inode = bpf_evict_inode, }; @@ -434,8 +446,6 @@ static int bpf_fill_super(struct super_block *sb, void *data, int silent) struct inode *inode; int ret; - save_mount_options(sb, data); - ret = bpf_parse_options(data, &opts); if (ret) return ret; -- cgit v1.2.3-59-g8ed1b From a66ca4146f3f736ff968c099926ccb1c1761b1a4 Mon Sep 17 00:00:00 2001 From: David Howells Date: Wed, 5 Jul 2017 16:24:56 +0100 Subject: spufs: Implement show_options Implement the show_options superblock op for spufs as part of a bid to get rid of s_options and generic_show_options() to make it easier to implement a context-based mount where the mount options can be passed individually over a file descriptor. Signed-off-by: David Howells cc: Jeremy Kerr cc: linuxppc-dev@lists.ozlabs.org Signed-off-by: Al Viro --- arch/powerpc/platforms/cell/spufs/inode.c | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/arch/powerpc/platforms/cell/spufs/inode.c b/arch/powerpc/platforms/cell/spufs/inode.c index d8af9bc0489f..9558d725a99b 100644 --- a/arch/powerpc/platforms/cell/spufs/inode.c +++ b/arch/powerpc/platforms/cell/spufs/inode.c @@ -605,6 +605,24 @@ static const match_table_t spufs_tokens = { { Opt_err, NULL }, }; +static int spufs_show_options(struct seq_file *m, struct dentry *root) +{ + struct spufs_sb_info *sbi = spufs_get_sb_info(root->d_sb); + struct inode *inode = root->d_inode; + + if (!uid_eq(inode->i_uid, GLOBAL_ROOT_UID)) + seq_printf(m, ",uid=%u", + from_kuid_munged(&init_user_ns, inode->i_uid)); + if (!gid_eq(inode->i_gid, GLOBAL_ROOT_GID)) + seq_printf(m, ",gid=%u", + from_kgid_munged(&init_user_ns, inode->i_gid)); + if ((inode->i_mode & S_IALLUGO) != 0775) + seq_printf(m, ",mode=%o", inode->i_mode); + if (sbi->debug) + seq_puts(m, ",debug"); + return 0; +} + static int spufs_parse_options(struct super_block *sb, char *options, struct inode *root) { @@ -724,11 +742,9 @@ spufs_fill_super(struct super_block *sb, void *data, int silent) .destroy_inode = spufs_destroy_inode, .statfs = simple_statfs, .evict_inode = spufs_evict_inode, - .show_options = generic_show_options, + .show_options = spufs_show_options, }; - save_mount_options(sb, data); - info = kzalloc(sizeof(*info), GFP_KERNEL); if (!info) return -ENOMEM; -- cgit v1.2.3-59-g8ed1b From 3ab7947ac3b5cd625c186bb608678bffd881e472 Mon Sep 17 00:00:00 2001 From: David Howells Date: Wed, 5 Jul 2017 16:25:03 +0100 Subject: befs: Implement show_options Implement the show_options superblock op for befs as part of a bid to get rid of s_options and generic_show_options() to make it easier to implement a context-based mount where the mount options can be passed individually over a file descriptor. Signed-off-by: David Howells cc: Luis de Bethencourt cc: Salah Triki Signed-off-by: Al Viro --- fs/befs/linuxvfs.c | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/fs/befs/linuxvfs.c b/fs/befs/linuxvfs.c index 63e7c4760bfb..4a4a5a366158 100644 --- a/fs/befs/linuxvfs.c +++ b/fs/befs/linuxvfs.c @@ -20,6 +20,7 @@ #include #include #include +#include #include "befs.h" #include "btree.h" @@ -53,6 +54,7 @@ static int befs_nls2utf(struct super_block *sb, const char *in, int in_len, static void befs_put_super(struct super_block *); static int befs_remount(struct super_block *, int *, char *); static int befs_statfs(struct dentry *, struct kstatfs *); +static int befs_show_options(struct seq_file *, struct dentry *); static int parse_options(char *, struct befs_mount_options *); static struct dentry *befs_fh_to_dentry(struct super_block *sb, struct fid *fid, int fh_len, int fh_type); @@ -66,7 +68,7 @@ static const struct super_operations befs_sops = { .put_super = befs_put_super, /* uninit super */ .statfs = befs_statfs, /* statfs */ .remount_fs = befs_remount, - .show_options = generic_show_options, + .show_options = befs_show_options, }; /* slab cache for befs_inode_info objects */ @@ -771,6 +773,24 @@ parse_options(char *options, struct befs_mount_options *opts) return 1; } +static int befs_show_options(struct seq_file *m, struct dentry *root) +{ + struct befs_sb_info *befs_sb = BEFS_SB(root->d_sb); + struct befs_mount_options *opts = &befs_sb->mount_opts; + + if (!uid_eq(opts->uid, GLOBAL_ROOT_UID)) + seq_printf(m, ",uid=%u", + from_kuid_munged(&init_user_ns, opts->uid)); + if (!gid_eq(opts->gid, GLOBAL_ROOT_GID)) + seq_printf(m, ",gid=%u", + from_kgid_munged(&init_user_ns, opts->gid)); + if (opts->iocharset) + seq_printf(m, ",charset=%s", opts->iocharset); + if (opts->debug) + seq_puts(m, ",debug"); + return 0; +} + /* This function has the responsibiltiy of getting the * filesystem ready for unmounting. * Basically, we free everything that we allocated in @@ -804,8 +824,6 @@ befs_fill_super(struct super_block *sb, void *data, int silent) const off_t x86_sb_off = 512; int blocksize; - save_mount_options(sb, data); - sb->s_fs_info = kzalloc(sizeof(*befs_sb), GFP_KERNEL); if (sb->s_fs_info == NULL) goto unacquire_none; -- cgit v1.2.3-59-g8ed1b From 26a7655e6a55768a082336dac8a4563344e890a2 Mon Sep 17 00:00:00 2001 From: David Howells Date: Wed, 5 Jul 2017 16:25:16 +0100 Subject: affs: Implement show_options Implement the show_options superblock op for affs as part of a bid to get rid of s_options and generic_show_options() to make it easier to implement a context-based mount where the mount options can be passed individually over a file descriptor. Signed-off-by: David Howells Signed-off-by: Al Viro --- fs/affs/super.c | 42 +++++++++++++++++++++++++++++++++++++----- 1 file changed, 37 insertions(+), 5 deletions(-) diff --git a/fs/affs/super.c b/fs/affs/super.c index c2c27a8f128e..7bf47a41cb4f 100644 --- a/fs/affs/super.c +++ b/fs/affs/super.c @@ -20,9 +20,11 @@ #include #include #include +#include #include "affs.h" static int affs_statfs(struct dentry *dentry, struct kstatfs *buf); +static int affs_show_options(struct seq_file *m, struct dentry *root); static int affs_remount (struct super_block *sb, int *flags, char *data); static void @@ -159,7 +161,7 @@ static const struct super_operations affs_sops = { .sync_fs = affs_sync_fs, .statfs = affs_statfs, .remount_fs = affs_remount, - .show_options = generic_show_options, + .show_options = affs_show_options, }; enum { @@ -293,6 +295,40 @@ parse_options(char *options, kuid_t *uid, kgid_t *gid, int *mode, int *reserved, return 1; } +static int affs_show_options(struct seq_file *m, struct dentry *root) +{ + struct super_block *sb = root->d_sb; + struct affs_sb_info *sbi = AFFS_SB(sb); + + if (sb->s_blocksize) + seq_printf(m, ",bs=%lu", sb->s_blocksize); + if (affs_test_opt(sbi->s_flags, SF_SETMODE)) + seq_printf(m, ",mode=%o", sbi->s_mode); + if (affs_test_opt(sbi->s_flags, SF_MUFS)) + seq_puts(m, ",mufs"); + if (affs_test_opt(sbi->s_flags, SF_NO_TRUNCATE)) + seq_puts(m, ",nofilenametruncate"); + if (affs_test_opt(sbi->s_flags, SF_PREFIX)) + seq_printf(m, ",prefix=%s", sbi->s_prefix); + if (affs_test_opt(sbi->s_flags, SF_IMMUTABLE)) + seq_puts(m, ",protect"); + if (sbi->s_reserved != 2) + seq_printf(m, ",reserved=%u", sbi->s_reserved); + if (sbi->s_root_block != (sbi->s_reserved + sbi->s_partition_size - 1) / 2) + seq_printf(m, ",root=%u", sbi->s_root_block); + if (affs_test_opt(sbi->s_flags, SF_SETGID)) + seq_printf(m, ",setgid=%u", + from_kgid_munged(&init_user_ns, sbi->s_gid)); + if (affs_test_opt(sbi->s_flags, SF_SETUID)) + seq_printf(m, ",setuid=%u", + from_kuid_munged(&init_user_ns, sbi->s_uid)); + if (affs_test_opt(sbi->s_flags, SF_VERBOSE)) + seq_puts(m, ",verbose"); + if (sbi->s_volume[0]) + seq_printf(m, ",volume=%s", sbi->s_volume); + return 0; +} + /* This function definitely needs to be split up. Some fine day I'll * hopefully have the guts to do so. Until then: sorry for the mess. */ @@ -316,8 +352,6 @@ static int affs_fill_super(struct super_block *sb, void *data, int silent) u8 sig[4]; int ret; - save_mount_options(sb, data); - pr_debug("read_super(%s)\n", data ? (const char *)data : "no options"); sb->s_magic = AFFS_SUPER_MAGIC; @@ -548,8 +582,6 @@ affs_remount(struct super_block *sb, int *flags, char *data) } flush_delayed_work(&sbi->sb_work); - if (new_opts) - replace_mount_options(sb, new_opts); sbi->s_flags = mount_flags; sbi->s_mode = mode; -- cgit v1.2.3-59-g8ed1b From 677018a6ce620c8ca85abae1a07a41d66247d420 Mon Sep 17 00:00:00 2001 From: David Howells Date: Wed, 5 Jul 2017 16:25:23 +0100 Subject: afs: Implement show_options Implement the show_options superblock op for afs as part of a bid to get rid of s_options and generic_show_options() to make it easier to implement a context-based mount where the mount options can be passed individually over a file descriptor. Also implement the show_devname op to display the correct device name and thus avoid the need to display the cell= and volume= options. Signed-off-by: David Howells cc: linux-afs@lists.infradead.org Signed-off-by: Al Viro --- fs/afs/super.c | 45 +++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 43 insertions(+), 2 deletions(-) diff --git a/fs/afs/super.c b/fs/afs/super.c index c79633e5cfd8..35d7e550b29c 100644 --- a/fs/afs/super.c +++ b/fs/afs/super.c @@ -37,6 +37,8 @@ static void afs_kill_super(struct super_block *sb); static struct inode *afs_alloc_inode(struct super_block *sb); static void afs_destroy_inode(struct inode *inode); static int afs_statfs(struct dentry *dentry, struct kstatfs *buf); +static int afs_show_devname(struct seq_file *m, struct dentry *root); +static int afs_show_options(struct seq_file *m, struct dentry *root); struct file_system_type afs_fs_type = { .owner = THIS_MODULE, @@ -53,7 +55,8 @@ static const struct super_operations afs_super_ops = { .drop_inode = afs_drop_inode, .destroy_inode = afs_destroy_inode, .evict_inode = afs_evict_inode, - .show_options = generic_show_options, + .show_devname = afs_show_devname, + .show_options = afs_show_options, }; static struct kmem_cache *afs_inode_cachep; @@ -135,6 +138,45 @@ void __exit afs_fs_exit(void) _leave(""); } +/* + * Display the mount device name in /proc/mounts. + */ +static int afs_show_devname(struct seq_file *m, struct dentry *root) +{ + struct afs_super_info *as = root->d_sb->s_fs_info; + struct afs_volume *volume = as->volume; + struct afs_cell *cell = volume->cell; + const char *suf = ""; + char pref = '%'; + + switch (volume->type) { + case AFSVL_RWVOL: + break; + case AFSVL_ROVOL: + pref = '#'; + if (volume->type_force) + suf = ".readonly"; + break; + case AFSVL_BACKVOL: + pref = '#'; + suf = ".backup"; + break; + } + + seq_printf(m, "%c%s:%s%s", pref, cell->name, volume->vlocation->vldb.name, suf); + return 0; +} + +/* + * Display the mount options in /proc/mounts. + */ +static int afs_show_options(struct seq_file *m, struct dentry *root) +{ + if (test_bit(AFS_VNODE_AUTOCELL, &AFS_FS_I(d_inode(root))->flags)) + seq_puts(m, "autocell"); + return 0; +} + /* * parse the mount options * - this function has been shamelessly adapted from the ext3 fs which @@ -426,7 +468,6 @@ static struct dentry *afs_mount(struct file_system_type *fs_type, deactivate_locked_super(sb); goto error; } - save_mount_options(sb, new_opts); sb->s_flags |= MS_ACTIVE; } else { _debug("reuse"); -- cgit v1.2.3-59-g8ed1b From 86a1da6d30ad727c2a9cc5d6a51bff6d830036b5 Mon Sep 17 00:00:00 2001 From: David Howells Date: Wed, 5 Jul 2017 16:25:30 +0100 Subject: isofs: Implement show_options Implement the show_options superblock op for omfs as part of a bid to get rid of s_options and generic_show_options() to make it easier to implement a context-based mount where the mount options can be passed individually over a file descriptor. Signed-off-by: David Howells cc: Jan Kara Signed-off-by: Al Viro --- fs/isofs/inode.c | 51 ++++++++++++++++++++++++++++++++++++++++++++++++--- fs/isofs/isofs.h | 3 +++ 2 files changed, 51 insertions(+), 3 deletions(-) diff --git a/fs/isofs/inode.c b/fs/isofs/inode.c index 020ba0936146..f80ee600d1bc 100644 --- a/fs/isofs/inode.c +++ b/fs/isofs/inode.c @@ -23,6 +23,7 @@ #include #include #include +#include #include "isofs.h" #include "zisofs.h" @@ -57,6 +58,7 @@ static void isofs_put_super(struct super_block *sb) static int isofs_read_inode(struct inode *, int relocated); static int isofs_statfs (struct dentry *, struct kstatfs *); +static int isofs_show_options(struct seq_file *, struct dentry *); static struct kmem_cache *isofs_inode_cachep; @@ -123,7 +125,7 @@ static const struct super_operations isofs_sops = { .put_super = isofs_put_super, .statfs = isofs_statfs, .remount_fs = isofs_remount, - .show_options = generic_show_options, + .show_options = isofs_show_options, }; @@ -472,6 +474,48 @@ static int parse_options(char *options, struct iso9660_options *popt) return 1; } +/* + * Display the mount options in /proc/mounts. + */ +static int isofs_show_options(struct seq_file *m, struct dentry *root) +{ + struct isofs_sb_info *sbi = ISOFS_SB(root->d_sb); + + if (!sbi->s_rock) seq_puts(m, ",norock"); + else if (!sbi->s_joliet_level) seq_puts(m, ",nojoliet"); + if (sbi->s_cruft) seq_puts(m, ",cruft"); + if (sbi->s_hide) seq_puts(m, ",hide"); + if (sbi->s_nocompress) seq_puts(m, ",nocompress"); + if (sbi->s_overriderockperm) seq_puts(m, ",overriderockperm"); + if (sbi->s_showassoc) seq_puts(m, ",showassoc"); + if (sbi->s_utf8) seq_puts(m, ",utf8"); + + if (sbi->s_check) seq_printf(m, ",check=%c", sbi->s_check); + if (sbi->s_mapping) seq_printf(m, ",map=%c", sbi->s_mapping); + if (sbi->s_session != -1) seq_printf(m, ",session=%u", sbi->s_session); + if (sbi->s_sbsector != -1) seq_printf(m, ",sbsector=%u", sbi->s_sbsector); + + if (root->d_sb->s_blocksize != 1024) + seq_printf(m, ",blocksize=%lu", root->d_sb->s_blocksize); + + if (sbi->s_uid_set) + seq_printf(m, ",uid=%u", + from_kuid_munged(&init_user_ns, sbi->s_uid)); + if (sbi->s_gid_set) + seq_printf(m, ",gid=%u", + from_kgid_munged(&init_user_ns, sbi->s_gid)); + + if (sbi->s_dmode != ISOFS_INVALID_MODE) + seq_printf(m, ",dmode=%o", sbi->s_dmode); + if (sbi->s_fmode != ISOFS_INVALID_MODE) + seq_printf(m, ",fmode=%o", sbi->s_fmode); + + if (sbi->s_nls_iocharset && + strcmp(sbi->s_nls_iocharset->charset, CONFIG_NLS_DEFAULT) != 0) + seq_printf(m, ",iocharset=%s", sbi->s_nls_iocharset->charset); + return 0; +} + /* * look if the driver can tell the multi session redirection value * @@ -583,8 +627,6 @@ static int isofs_fill_super(struct super_block *s, void *data, int silent) int table, error = -EINVAL; unsigned int vol_desc_start; - save_mount_options(s, data); - sbi = kzalloc(sizeof(*sbi), GFP_KERNEL); if (!sbi) return -ENOMEM; @@ -605,6 +647,8 @@ static int isofs_fill_super(struct super_block *s, void *data, int silent) opt.blocksize = sb_min_blocksize(s, opt.blocksize); sbi->s_high_sierra = 0; /* default is iso9660 */ + sbi->s_session = opt.session; + sbi->s_sbsector = opt.sbsector; vol_desc_start = (opt.sbsector != -1) ? opt.sbsector : isofs_get_last_session(s,opt.session); @@ -911,6 +955,7 @@ root_found: table += 2; if (opt.check == 'r') table++; + sbi->s_check = opt.check; if (table) s->s_d_op = &isofs_dentry_ops[table - 1]; diff --git a/fs/isofs/isofs.h b/fs/isofs/isofs.h index 0ac4c1f73fbd..133a456b0425 100644 --- a/fs/isofs/isofs.h +++ b/fs/isofs/isofs.h @@ -36,8 +36,11 @@ struct isofs_sb_info { unsigned long s_max_size; int s_rock_offset; /* offset of SUSP fields within SU area */ + s32 s_sbsector; unsigned char s_joliet_level; unsigned char s_mapping; + unsigned char s_check; + unsigned char s_session; unsigned int s_high_sierra:1; unsigned int s_rock:2; unsigned int s_utf8:1; -- cgit v1.2.3-59-g8ed1b From c4fac9100456995c10b65c13be84554258ed7fc8 Mon Sep 17 00:00:00 2001 From: David Howells Date: Wed, 5 Jul 2017 16:25:37 +0100 Subject: 9p: Implement show_options Implement the show_options superblock op for 9p as part of a bid to get rid of s_options and generic_show_options() to make it easier to implement a context-based mount where the mount options can be passed individually over a file descriptor. Signed-off-by: David Howells cc: Eric Van Hensbergen cc: Ron Minnich cc: Latchesar Ionkov cc: v9fs-developer@lists.sourceforge.net Signed-off-by: Al Viro --- fs/9p/v9fs.c | 61 ++++++++++++++++++++++++++++++++++++++++++++++ fs/9p/v9fs.h | 3 +++ fs/9p/vfs_super.c | 6 ++--- include/net/9p/client.h | 13 ++++++++++ include/net/9p/transport.h | 1 + net/9p/client.c | 25 +++++++++++++++++++ net/9p/trans_fd.c | 31 ++++++++++++++++++++--- net/9p/trans_rdma.c | 31 ++++++++++++++++++++--- 8 files changed, 161 insertions(+), 10 deletions(-) diff --git a/fs/9p/v9fs.c b/fs/9p/v9fs.c index c202930086ed..8fb89ddc6cc7 100644 --- a/fs/9p/v9fs.c +++ b/fs/9p/v9fs.c @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include @@ -82,6 +83,13 @@ static const match_table_t tokens = { {Opt_err, NULL} }; +static const char *const v9fs_cache_modes[nr__p9_cache_modes] = { + [CACHE_NONE] = "none", + [CACHE_MMAP] = "mmap", + [CACHE_LOOSE] = "loose", + [CACHE_FSCACHE] = "fscache", +}; + /* Interpret mount options for cache mode */ static int get_cache_mode(char *s) { @@ -104,6 +112,58 @@ static int get_cache_mode(char *s) return version; } +/* + * Display the mount options in /proc/mounts. + */ +int v9fs_show_options(struct seq_file *m, struct dentry *root) +{ + struct v9fs_session_info *v9ses = root->d_sb->s_fs_info; + + if (v9ses->debug) + seq_printf(m, ",debug=%x", v9ses->debug); + if (!uid_eq(v9ses->dfltuid, V9FS_DEFUID)) + seq_printf(m, ",dfltuid=%u", + from_kuid_munged(&init_user_ns, v9ses->dfltuid)); + if (!gid_eq(v9ses->dfltgid, V9FS_DEFGID)) + seq_printf(m, ",dfltgid=%u", + from_kgid_munged(&init_user_ns, v9ses->dfltgid)); + if (v9ses->afid != ~0) + seq_printf(m, ",afid=%u", v9ses->afid); + if (strcmp(v9ses->uname, V9FS_DEFUSER) != 0) + seq_printf(m, ",uname=%s", v9ses->uname); + if (strcmp(v9ses->aname, V9FS_DEFANAME) != 0) + seq_printf(m, ",aname=%s", v9ses->aname); + if (v9ses->nodev) + seq_puts(m, ",nodevmap"); + if (v9ses->cache) + seq_printf(m, ",%s", v9fs_cache_modes[v9ses->cache]); +#ifdef CONFIG_9P_FSCACHE + if (v9ses->cachetag && v9ses->cache == CACHE_FSCACHE) + seq_printf(m, ",cachetag=%s", v9ses->cachetag); +#endif + + switch (v9ses->flags & V9FS_ACCESS_MASK) { + case V9FS_ACCESS_USER: + seq_puts(m, ",access=user"); + break; + case V9FS_ACCESS_ANY: + seq_puts(m, ",access=any"); + break; + case V9FS_ACCESS_CLIENT: + seq_puts(m, ",access=client"); + break; + case V9FS_ACCESS_SINGLE: + seq_printf(m, ",access=%u", + from_kuid_munged(&init_user_ns, v9ses->uid)); + break; + } + + if (v9ses->flags & V9FS_POSIX_ACL) + seq_puts(m, ",posixacl"); + + return p9_show_client_options(m, v9ses->clnt); +} + /** * v9fs_parse_options - parse mount options into session structure * @v9ses: existing v9fs session information @@ -230,6 +290,7 @@ static int v9fs_parse_options(struct v9fs_session_info *v9ses, char *opts) break; case Opt_cachetag: #ifdef CONFIG_9P_FSCACHE + kfree(v9ses->cachetag); v9ses->cachetag = match_strdup(&args[0]); #endif break; diff --git a/fs/9p/v9fs.h b/fs/9p/v9fs.h index 76eaf49abd3a..982e017acadb 100644 --- a/fs/9p/v9fs.h +++ b/fs/9p/v9fs.h @@ -67,6 +67,7 @@ enum p9_cache_modes { CACHE_MMAP, CACHE_LOOSE, CACHE_FSCACHE, + nr__p9_cache_modes }; /** @@ -137,6 +138,8 @@ static inline struct v9fs_inode *V9FS_I(const struct inode *inode) return container_of(inode, struct v9fs_inode, vfs_inode); } +extern int v9fs_show_options(struct seq_file *m, struct dentry *root); + struct p9_fid *v9fs_session_init(struct v9fs_session_info *, const char *, char *); extern void v9fs_session_close(struct v9fs_session_info *v9ses); diff --git a/fs/9p/vfs_super.c b/fs/9p/vfs_super.c index a0965fb587a5..8b75463cb211 100644 --- a/fs/9p/vfs_super.c +++ b/fs/9p/vfs_super.c @@ -33,7 +33,6 @@ #include #include #include -#include #include #include #include @@ -104,7 +103,6 @@ v9fs_fill_super(struct super_block *sb, struct v9fs_session_info *v9ses, sb->s_flags |= MS_POSIXACL; #endif - save_mount_options(sb, data); return 0; } @@ -349,7 +347,7 @@ static const struct super_operations v9fs_super_ops = { .destroy_inode = v9fs_destroy_inode, .statfs = simple_statfs, .evict_inode = v9fs_evict_inode, - .show_options = generic_show_options, + .show_options = v9fs_show_options, .umount_begin = v9fs_umount_begin, .write_inode = v9fs_write_inode, }; @@ -360,7 +358,7 @@ static const struct super_operations v9fs_super_ops_dotl = { .statfs = v9fs_statfs, .drop_inode = v9fs_drop_inode, .evict_inode = v9fs_evict_inode, - .show_options = generic_show_options, + .show_options = v9fs_show_options, .umount_begin = v9fs_umount_begin, .write_inode = v9fs_write_inode_dotl, }; diff --git a/include/net/9p/client.h b/include/net/9p/client.h index b582339ccef5..7af9d769b97d 100644 --- a/include/net/9p/client.h +++ b/include/net/9p/client.h @@ -157,6 +157,18 @@ struct p9_client { enum p9_trans_status status; void *trans; + union { + struct { + int rfd; + int wfd; + } fd; + struct { + u16 port; + bool privport; + + } tcp; + } trans_opts; + struct p9_idpool *fidpool; struct list_head fidlist; @@ -213,6 +225,7 @@ struct p9_dirent { struct iov_iter; +int p9_show_client_options(struct seq_file *m, struct p9_client *clnt); int p9_client_statfs(struct p9_fid *fid, struct p9_rstatfs *sb); int p9_client_rename(struct p9_fid *fid, struct p9_fid *newdirfid, const char *name); diff --git a/include/net/9p/transport.h b/include/net/9p/transport.h index 5122b5e40f78..1625fb842ac4 100644 --- a/include/net/9p/transport.h +++ b/include/net/9p/transport.h @@ -62,6 +62,7 @@ struct p9_trans_module { int (*cancelled)(struct p9_client *, struct p9_req_t *req); int (*zc_request)(struct p9_client *, struct p9_req_t *, struct iov_iter *, struct iov_iter *, int , int, int); + int (*show_options)(struct seq_file *, struct p9_client *); }; void v9fs_register_trans(struct p9_trans_module *m); diff --git a/net/9p/client.c b/net/9p/client.c index 1218fb3b52da..4674235b0d9b 100644 --- a/net/9p/client.c +++ b/net/9p/client.c @@ -37,6 +37,7 @@ #include #include #include +#include #include #include #include "protocol.h" @@ -77,6 +78,30 @@ inline int p9_is_proto_dotu(struct p9_client *clnt) } EXPORT_SYMBOL(p9_is_proto_dotu); +int p9_show_client_options(struct seq_file *m, struct p9_client *clnt) +{ + if (clnt->msize != 8192) + seq_printf(m, ",msize=%u", clnt->msize); + seq_printf(m, "trans=%s", clnt->trans_mod->name); + + switch (clnt->proto_version) { + case p9_proto_legacy: + seq_puts(m, ",noextend"); + break; + case p9_proto_2000u: + seq_puts(m, ",version=9p2000.u"); + break; + case p9_proto_2000L: + /* Default */ + break; + } + + if (clnt->trans_mod->show_options) + return clnt->trans_mod->show_options(m, clnt); + return 0; +} +EXPORT_SYMBOL(p9_show_client_options); + /* * Some error codes are taken directly from the server replies, * make sure they are valid. diff --git a/net/9p/trans_fd.c b/net/9p/trans_fd.c index 7bc2208b6cc4..f2e0eaf58018 100644 --- a/net/9p/trans_fd.c +++ b/net/9p/trans_fd.c @@ -41,6 +41,7 @@ #include #include #include +#include #include #include #include @@ -51,6 +52,9 @@ #define MAX_SOCK_BUF (64*1024) #define MAXPOLLWADDR 2 +static struct p9_trans_module p9_tcp_trans; +static struct p9_trans_module p9_fd_trans; + /** * struct p9_fd_opts - per-transport options * @rfd: file descriptor for reading (trans=fd) @@ -63,7 +67,7 @@ struct p9_fd_opts { int rfd; int wfd; u16 port; - int privport; + bool privport; }; /* @@ -720,6 +724,20 @@ static int p9_fd_cancelled(struct p9_client *client, struct p9_req_t *req) return 0; } +static int p9_fd_show_options(struct seq_file *m, struct p9_client *clnt) +{ + if (clnt->trans_mod == &p9_tcp_trans) { + if (clnt->trans_opts.tcp.port != P9_PORT) + seq_printf(m, "port=%u", clnt->trans_opts.tcp.port); + } else if (clnt->trans_mod == &p9_fd_trans) { + if (clnt->trans_opts.fd.rfd != ~0) + seq_printf(m, "rfd=%u", clnt->trans_opts.fd.rfd); + if (clnt->trans_opts.fd.wfd != ~0) + seq_printf(m, "wfd=%u", clnt->trans_opts.fd.wfd); + } + return 0; +} + /** * parse_opts - parse mount options into p9_fd_opts structure * @params: options string passed from mount @@ -738,7 +756,7 @@ static int parse_opts(char *params, struct p9_fd_opts *opts) opts->port = P9_PORT; opts->rfd = ~0; opts->wfd = ~0; - opts->privport = 0; + opts->privport = false; if (!params) return 0; @@ -776,7 +794,7 @@ static int parse_opts(char *params, struct p9_fd_opts *opts) opts->wfd = option; break; case Opt_privport: - opts->privport = 1; + opts->privport = true; break; default: continue; @@ -942,6 +960,8 @@ p9_fd_create_tcp(struct p9_client *client, const char *addr, char *args) csocket = NULL; + client->trans_opts.tcp.port = opts.port; + client->trans_opts.tcp.privport = opts.privport; sin_server.sin_family = AF_INET; sin_server.sin_addr.s_addr = in_aton(addr); sin_server.sin_port = htons(opts.port); @@ -1020,6 +1040,8 @@ p9_fd_create(struct p9_client *client, const char *addr, char *args) struct p9_fd_opts opts; parse_opts(args, &opts); + client->trans_opts.fd.rfd = opts.rfd; + client->trans_opts.fd.wfd = opts.wfd; if (opts.rfd == ~0 || opts.wfd == ~0) { pr_err("Insufficient options for proto=fd\n"); @@ -1044,6 +1066,7 @@ static struct p9_trans_module p9_tcp_trans = { .request = p9_fd_request, .cancel = p9_fd_cancel, .cancelled = p9_fd_cancelled, + .show_options = p9_fd_show_options, .owner = THIS_MODULE, }; @@ -1056,6 +1079,7 @@ static struct p9_trans_module p9_unix_trans = { .request = p9_fd_request, .cancel = p9_fd_cancel, .cancelled = p9_fd_cancelled, + .show_options = p9_fd_show_options, .owner = THIS_MODULE, }; @@ -1068,6 +1092,7 @@ static struct p9_trans_module p9_fd_trans = { .request = p9_fd_request, .cancel = p9_fd_cancel, .cancelled = p9_fd_cancelled, + .show_options = p9_fd_show_options, .owner = THIS_MODULE, }; diff --git a/net/9p/trans_rdma.c b/net/9p/trans_rdma.c index 553ed4ecb6a0..6d8e3031978f 100644 --- a/net/9p/trans_rdma.c +++ b/net/9p/trans_rdma.c @@ -43,6 +43,7 @@ #include #include #include +#include #include #include #include @@ -70,6 +71,8 @@ * @dm_mr: DMA Memory Region pointer * @lkey: The local access only memory region key * @timeout: Number of uSecs to wait for connection management events + * @privport: Whether a privileged port may be used + * @port: The port to use * @sq_depth: The depth of the Send Queue * @sq_sem: Semaphore for the SQ * @rq_depth: The depth of the Receive Queue. @@ -95,6 +98,8 @@ struct p9_trans_rdma { struct ib_qp *qp; struct ib_cq *cq; long timeout; + bool privport; + u16 port; int sq_depth; struct semaphore sq_sem; int rq_depth; @@ -133,10 +138,10 @@ struct p9_rdma_context { */ struct p9_rdma_opts { short port; + bool privport; int sq_depth; int rq_depth; long timeout; - int privport; }; /* @@ -159,6 +164,23 @@ static match_table_t tokens = { {Opt_err, NULL}, }; +static int p9_rdma_show_options(struct seq_file *m, struct p9_client *clnt) +{ + struct p9_trans_rdma *rdma = clnt->trans; + + if (rdma->port != P9_PORT) + seq_printf(m, ",port=%u", rdma->port); + if (rdma->sq_depth != P9_RDMA_SQ_DEPTH) + seq_printf(m, ",sq=%u", rdma->sq_depth); + if (rdma->rq_depth != P9_RDMA_RQ_DEPTH) + seq_printf(m, ",rq=%u", rdma->rq_depth); + if (rdma->timeout != P9_RDMA_TIMEOUT) + seq_printf(m, ",timeout=%lu", rdma->timeout); + if (rdma->privport) + seq_puts(m, ",privport"); + return 0; +} + /** * parse_opts - parse mount options into rdma options structure * @params: options string passed from mount @@ -177,7 +199,7 @@ static int parse_opts(char *params, struct p9_rdma_opts *opts) opts->sq_depth = P9_RDMA_SQ_DEPTH; opts->rq_depth = P9_RDMA_RQ_DEPTH; opts->timeout = P9_RDMA_TIMEOUT; - opts->privport = 0; + opts->privport = false; if (!params) return 0; @@ -218,7 +240,7 @@ static int parse_opts(char *params, struct p9_rdma_opts *opts) opts->timeout = option; break; case Opt_privport: - opts->privport = 1; + opts->privport = true; break; default: continue; @@ -560,6 +582,8 @@ static struct p9_trans_rdma *alloc_rdma(struct p9_rdma_opts *opts) if (!rdma) return NULL; + rdma->port = opts->port; + rdma->privport = opts->privport; rdma->sq_depth = opts->sq_depth; rdma->rq_depth = opts->rq_depth; rdma->timeout = opts->timeout; @@ -733,6 +757,7 @@ static struct p9_trans_module p9_rdma_trans = { .request = rdma_request, .cancel = rdma_cancel, .cancelled = rdma_cancelled, + .show_options = p9_rdma_show_options, }; /** -- cgit v1.2.3-59-g8ed1b From 4dfdb71307675b19a54723a556371dad5e3b0083 Mon Sep 17 00:00:00 2001 From: David Howells Date: Wed, 5 Jul 2017 16:25:45 +0100 Subject: orangefs: Implement show_options Implement the show_options superblock op for orangefs as part of a bid to rid of s_options and generic_show_options() to make it easier to implement a context-based mount where the mount options can be passed individually over a file descriptor. Signed-off-by: David Howells cc: Mike Marshall cc: pvfs2-developers@beowulf-underground.org Signed-off-by: Al Viro --- fs/orangefs/super.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/fs/orangefs/super.c b/fs/orangefs/super.c index 5c7c273e17ec..5a1bed6c8c6a 100644 --- a/fs/orangefs/super.c +++ b/fs/orangefs/super.c @@ -35,6 +35,19 @@ static const match_table_t tokens = { uint64_t orangefs_features; +static int orangefs_show_options(struct seq_file *m, struct dentry *root) +{ + struct orangefs_sb_info_s *orangefs_sb = ORANGEFS_SB(root->d_sb); + + if (root->d_sb->s_flags & MS_POSIXACL) + seq_puts(m, ",acl"); + if (orangefs_sb->flags & ORANGEFS_OPT_INTR) + seq_puts(m, ",intr"); + if (orangefs_sb->flags & ORANGEFS_OPT_LOCAL_LOCK) + seq_puts(m, ",local_lock"); + return 0; +} + static int parse_mount_options(struct super_block *sb, char *options, int silent) { @@ -305,7 +318,7 @@ static const struct super_operations orangefs_s_ops = { .drop_inode = generic_delete_inode, .statfs = orangefs_statfs, .remount_fs = orangefs_remount_fs, - .show_options = generic_show_options, + .show_options = orangefs_show_options, }; static struct dentry *orangefs_fh_to_dentry(struct super_block *sb, -- cgit v1.2.3-59-g8ed1b From 1d278a879081ddc40286500e58868aaee47de257 Mon Sep 17 00:00:00 2001 From: David Howells Date: Wed, 5 Jul 2017 16:25:53 +0100 Subject: VFS: Kill off s_options and helpers Kill off s_options, save/replace_mount_options() and generic_show_options() as all filesystems now implement ->show_options() for themselves. This should make it easier to implement a context-based mount where the mount options can be passed individually over a file descriptor. Signed-off-by: David Howells Signed-off-by: Al Viro --- Documentation/filesystems/vfs.txt | 6 ---- fs/efivarfs/super.c | 1 - fs/namespace.c | 59 --------------------------------------- fs/super.c | 1 - include/linux/fs.h | 9 ------ 5 files changed, 76 deletions(-) diff --git a/Documentation/filesystems/vfs.txt b/Documentation/filesystems/vfs.txt index f42b90687d40..ee56a7d10da9 100644 --- a/Documentation/filesystems/vfs.txt +++ b/Documentation/filesystems/vfs.txt @@ -1187,12 +1187,6 @@ The underlying reason for the above rules is to make sure, that a mount can be accurately replicated (e.g. umounting and mounting again) based on the information found in /proc/mounts. -A simple method of saving options at mount/remount time and showing -them is provided with the save_mount_options() and -generic_show_options() helper functions. Please note, that using -these may have drawbacks. For more info see header comments for these -functions in fs/namespace.c. - Resources ========= diff --git a/fs/efivarfs/super.c b/fs/efivarfs/super.c index d7a7c53803c1..5b68e4294faa 100644 --- a/fs/efivarfs/super.c +++ b/fs/efivarfs/super.c @@ -29,7 +29,6 @@ static const struct super_operations efivarfs_ops = { .statfs = simple_statfs, .drop_inode = generic_delete_inode, .evict_inode = efivarfs_evict_inode, - .show_options = generic_show_options, }; static struct super_block *efivarfs_sb; diff --git a/fs/namespace.c b/fs/namespace.c index 544ab84642eb..0e1fdb306133 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -1237,65 +1237,6 @@ struct vfsmount *mnt_clone_internal(const struct path *path) return &p->mnt; } -static inline void mangle(struct seq_file *m, const char *s) -{ - seq_escape(m, s, " \t\n\\"); -} - -/* - * Simple .show_options callback for filesystems which don't want to - * implement more complex mount option showing. - * - * See also save_mount_options(). - */ -int generic_show_options(struct seq_file *m, struct dentry *root) -{ - const char *options; - - rcu_read_lock(); - options = rcu_dereference(root->d_sb->s_options); - - if (options != NULL && options[0]) { - seq_putc(m, ','); - mangle(m, options); - } - rcu_read_unlock(); - - return 0; -} -EXPORT_SYMBOL(generic_show_options); - -/* - * If filesystem uses generic_show_options(), this function should be - * called from the fill_super() callback. - * - * The .remount_fs callback usually needs to be handled in a special - * way, to make sure, that previous options are not overwritten if the - * remount fails. - * - * Also note, that if the filesystem's .remount_fs function doesn't - * reset all options to their default value, but changes only newly - * given options, then the displayed options will not reflect reality - * any more. - */ -void save_mount_options(struct super_block *sb, char *options) -{ - BUG_ON(sb->s_options); - rcu_assign_pointer(sb->s_options, kstrdup(options, GFP_KERNEL)); -} -EXPORT_SYMBOL(save_mount_options); - -void replace_mount_options(struct super_block *sb, char *options) -{ - char *old = sb->s_options; - rcu_assign_pointer(sb->s_options, options); - if (old) { - synchronize_rcu(); - kfree(old); - } -} -EXPORT_SYMBOL(replace_mount_options); - #ifdef CONFIG_PROC_FS /* iterator; we want it to have access to namespace_sem, thus here... */ static void *m_start(struct seq_file *m, loff_t *pos) diff --git a/fs/super.c b/fs/super.c index dfb56a9665d8..6bc3352adcf3 100644 --- a/fs/super.c +++ b/fs/super.c @@ -168,7 +168,6 @@ static void destroy_super(struct super_block *s) WARN_ON(!list_empty(&s->s_mounts)); put_user_ns(s->s_user_ns); kfree(s->s_subtype); - kfree(s->s_options); call_rcu(&s->rcu, destroy_super_rcu); } diff --git a/include/linux/fs.h b/include/linux/fs.h index bc0c054894b9..e265b2ea72c6 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -1351,11 +1351,6 @@ struct super_block { */ char *s_subtype; - /* - * Saved mount options for lazy filesystems using - * generic_show_options() - */ - char __rcu *s_options; const struct dentry_operations *s_d_op; /* default d_op for dentries */ /* @@ -3033,10 +3028,6 @@ extern void setattr_copy(struct inode *inode, const struct iattr *attr); extern int file_update_time(struct file *file); -extern int generic_show_options(struct seq_file *m, struct dentry *root); -extern void save_mount_options(struct super_block *sb, char *options); -extern void replace_mount_options(struct super_block *sb, char *options); - static inline bool io_is_direct(struct file *filp) { return (filp->f_flags & O_DIRECT) || IS_DAX(filp->f_mapping->host); -- cgit v1.2.3-59-g8ed1b From fdb254db21bb4aed44a0bc7fe993e58d3848c926 Mon Sep 17 00:00:00 2001 From: David Howells Date: Tue, 11 Jul 2017 16:22:59 +0100 Subject: isofs: Fix isofs_show_options() The isofs patch needs a small fix to handle a signed/unsigned comparison that the compiler didn't flag - thanks to Dan for catching it. It should be noted, however, the session number handing appears to be incorrect between where it is parsed and where it is used. Signed-off-by: David Howells Signed-off-by: Al Viro --- fs/isofs/inode.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/isofs/inode.c b/fs/isofs/inode.c index f80ee600d1bc..8cf898a59730 100644 --- a/fs/isofs/inode.c +++ b/fs/isofs/inode.c @@ -492,7 +492,7 @@ static int isofs_show_options(struct seq_file *m, struct dentry *root) if (sbi->s_check) seq_printf(m, ",check=%c", sbi->s_check); if (sbi->s_mapping) seq_printf(m, ",map=%c", sbi->s_mapping); - if (sbi->s_session != -1) seq_printf(m, ",session=%u", sbi->s_session); + if (sbi->s_session != 255) seq_printf(m, ",session=%u", sbi->s_session - 1); if (sbi->s_sbsector != -1) seq_printf(m, ",sbsector=%u", sbi->s_sbsector); if (root->d_sb->s_blocksize != 1024) -- cgit v1.2.3-59-g8ed1b