2017-07-05 15:24:06

by David Howells

[permalink] [raw]
Subject: [RFC][PATCH 00/14] VFS: Make all filesystems implement ->show_options()


Here's a set of patches that:

(1) Removes calls to save/replace_mount_options() where the filesystem
then implements ->show_options() anyway, ignoring ->s_options.

(2) Makes all filesystems implement the ->show_options() superblock
operation rather than using generic_show_options(). If necessary,
extra information is stored in the superblock information.

(3) Deletes save_mount_options(), replace_mount_options(),
generic_show_options() and super_block::s_options.

This makes it easier to implement a context-based mount where the options
are passed individually over a file descriptor. It also allows duplicate
options, options that override each other and ignored options to be
resolved rather than storing irrelevant data.

Further, a lot of the time, all the information we want to display is
stored in the super block information anyway, so the option string is
redundant.

Some things I noted whilst doing this:

(1) A number of filesystems take uid/gid options. Should these be
reported relative to the observer's user namespace rather than init's
user namespace? After all, you can't then use those uid/gid options
if the numbers are interpreted incorrectly if you try and forge a
mount command from them.

(2) Should I provide a helper for displaying uid/gid options?

(3) How much do we need to worry about racing with remount? Some
filesystems happily give out the contents of the super_block without
regard to the fact that remount might be changing it simultaneously -
ext4, for example.

(4) What string options actually need 'munging'?

These patches can be found here:

https://git.kernel.org/pub/scm/linux/kernel/git/dhowells/linux-fs.git/log/?h=for-viro

on top of three other minor patches.

David
---
David Howells (14):
VFS: Don't use save/replace_mount_options if not using generic_show_options
hugetlbfs: Implement show_options
omfs: Implement show_options
pstore: Implement show_options
ramfs: Implement show_options
bpf: Implement show_options
spufs: Implement show_options
befs: Implement show_options
affs: Implement show_options
afs: Implement show_options
isofs: Implement show_options
9p: Implement show_options
orangefs: Implement show_options
VFS: Kill off s_options and helpers


Documentation/filesystems/vfs.txt | 6 --
arch/powerpc/platforms/cell/spufs/inode.c | 21 +++++++--
fs/9p/v9fs.c | 59 ++++++++++++++++++++++++
fs/9p/v9fs.h | 3 +
fs/9p/vfs_super.c | 6 +-
fs/affs/super.c | 42 +++++++++++++++--
fs/afs/super.c | 45 ++++++++++++++++++-
fs/befs/linuxvfs.c | 24 +++++++++-
fs/btrfs/super.c | 1
fs/debugfs/inode.c | 2 -
fs/efivarfs/super.c | 1
fs/hugetlbfs/inode.c | 70 +++++++++++++++++++++++------
fs/isofs/inode.c | 51 ++++++++++++++++++++-
fs/isofs/isofs.h | 3 +
fs/namespace.c | 59 ------------------------
fs/omfs/inode.c | 33 ++++++++++++--
fs/orangefs/super.c | 15 ++++++
fs/pstore/inode.c | 14 +++++-
fs/pstore/internal.h | 3 +
fs/pstore/platform.c | 2 -
fs/ramfs/inode.c | 32 +++++++++----
fs/reiserfs/super.c | 4 --
fs/super.c | 1
fs/tracefs/inode.c | 2 -
include/linux/fs.h | 9 ----
include/linux/hugetlb.h | 3 +
include/net/9p/client.h | 13 +++++
include/net/9p/transport.h | 1
kernel/bpf/inode.c | 16 +++++--
net/9p/client.c | 25 ++++++++++
net/9p/trans_fd.c | 31 ++++++++++++-
net/9p/trans_rdma.c | 31 ++++++++++++-
32 files changed, 481 insertions(+), 147 deletions(-)


2017-07-05 15:24:16

by David Howells

[permalink] [raw]
Subject: [PATCH 01/14] 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 <[email protected]>
cc: Chris Mason <[email protected]>
cc: Greg Kroah-Hartman <[email protected]>
cc: Steven Rostedt <[email protected]>
cc: [email protected]
cc: [email protected]
---

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) {

2017-07-05 15:24:25

by David Howells

[permalink] [raw]
Subject: [PATCH 02/14] 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 <[email protected]>
cc: Nadia Yvette Chambers <[email protected]>
---

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)

2017-07-05 15:24:40

by David Howells

[permalink] [raw]
Subject: [PATCH 04/14] 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 <[email protected]>
cc: Kees Cook <[email protected]>
cc: Anton Vorontsov <[email protected]>
cc: Colin Cross <[email protected]>
cc: Tony Luck <[email protected]>
---

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 <linux/time.h>
#include <linux/pstore.h>

+#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)
{

2017-07-05 15:24:44

by David Howells

[permalink] [raw]
Subject: [PATCH 03/14] 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 <[email protected]>
cc: Bob Copeland <[email protected]>
cc: [email protected]
---

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 <linux/buffer_head.h>
#include <linux/vmalloc.h>
#include <linux/writeback.h>
+#include <linux/seq_file.h>
#include <linux/crc-itu-t.h>
#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;

2017-07-05 15:25:00

by David Howells

[permalink] [raw]
Subject: [PATCH 06/14] 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 <[email protected]>
cc: Alexei Starovoitov <[email protected]>
cc: Daniel Borkmann <[email protected]>
cc: [email protected]
---

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;

2017-07-05 15:25:13

by David Howells

[permalink] [raw]
Subject: [PATCH 08/14] 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 <[email protected]>
cc: Luis de Bethencourt <[email protected]>
cc: Salah Triki <[email protected]>
---

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 <linux/sched.h>
#include <linux/cred.h>
#include <linux/exportfs.h>
+#include <linux/seq_file.h>

#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;

2017-07-05 15:25:02

by David Howells

[permalink] [raw]
Subject: [PATCH 07/14] 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 <[email protected]>
cc: Jeremy Kerr <[email protected]>
cc: [email protected]
---

arch/powerpc/platforms/cell/spufs/inode.c | 21 ++++++++++++++++++---
1 file changed, 18 insertions(+), 3 deletions(-)

diff --git a/arch/powerpc/platforms/cell/spufs/inode.c b/arch/powerpc/platforms/cell/spufs/inode.c
index d8af9bc0489f..27a51a60bc33 100644
--- a/arch/powerpc/platforms/cell/spufs/inode.c
+++ b/arch/powerpc/platforms/cell/spufs/inode.c
@@ -605,6 +605,23 @@ 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);
+
+ if (!uid_eq(root->i_uid, GLOBAL_ROOT_UID))
+ seq_printf(m, ",uid=%u",
+ from_kuid_munged(&init_user_ns, root->i_uid));
+ if (!gid_eq(root->i_gid, GLOBAL_ROOT_GID))
+ seq_printf(m, ",gid=%u",
+ from_kgid_munged(&init_user_ns, root->i_gid));
+ if (root->i_mode & S_IALLUGO != 0775)
+ seq_printf(m, ",mode=%o", root->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 +741,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;

2017-07-05 15:25:26

by David Howells

[permalink] [raw]
Subject: [PATCH 09/14] 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 <[email protected]>
---

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 <linux/slab.h>
#include <linux/writeback.h>
#include <linux/blkdev.h>
+#include <linux/seq_file.h>
#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;

2017-07-05 15:25:35

by David Howells

[permalink] [raw]
Subject: [PATCH 11/14] 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 <[email protected]>
cc: Jan Kara <[email protected]>
---

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 <linux/parser.h>
#include <linux/mpage.h>
#include <linux/user_namespace.h>
+#include <linux/seq_file.h>

#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,
};


@@ -473,6 +475,48 @@ static int parse_options(char *options, struct iso9660_options *popt)
}

/*
+ * 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
*
* don't change this if you don't know what you do, please!
@@ -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 @@ static int isofs_fill_super(struct super_block *s, void *data, int silent)
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;

2017-07-05 15:25:43

by David Howells

[permalink] [raw]
Subject: [PATCH 10/14] 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 <[email protected]>
cc: [email protected]
---

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;
@@ -136,6 +139,45 @@ void __exit afs_fs_exit(void)
}

/*
+ * 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
* shamelessly adapted it from the msdos fs
@@ -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");

2017-07-05 15:25:49

by David Howells

[permalink] [raw]
Subject: [PATCH 12/14] 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 <[email protected]>
cc: Eric Van Hensbergen <[email protected]>
cc: Ron Minnich <[email protected]>
cc: Latchesar Ionkov <[email protected]>
cc: [email protected]
---

fs/9p/v9fs.c | 59 ++++++++++++++++++++++++++++++++++++++++++++
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, 159 insertions(+), 10 deletions(-)

diff --git a/fs/9p/v9fs.c b/fs/9p/v9fs.c
index c202930086ed..d69046650a36 100644
--- a/fs/9p/v9fs.c
+++ b/fs/9p/v9fs.c
@@ -33,6 +33,7 @@
#include <linux/parser.h>
#include <linux/idr.h>
#include <linux/slab.h>
+#include <linux/seq_file.h>
#include <net/9p/9p.h>
#include <net/9p/client.h>
#include <net/9p/transport.h>
@@ -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,56 @@ 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]);
+ if (v9ses->cachetag && v9ses->cache == CACHE_FSCACHE)
+ seq_printf(m, ",cachetag=%s", v9ses->cachetag);
+
+ 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 +288,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 <linux/string.h>
#include <linux/inet.h>
#include <linux/pagemap.h>
-#include <linux/seq_file.h>
#include <linux/mount.h>
#include <linux/idr.h>
#include <linux/sched.h>
@@ -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..7a8395f75800 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 <linux/uio.h>
#include <net/9p/9p.h>
#include <linux/parser.h>
+#include <linux/seq_file.h>
#include <net/9p/client.h>
#include <net/9p/transport.h>
#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 dca3cdd1a014..ddfa86648f95 100644
--- a/net/9p/trans_fd.c
+++ b/net/9p/trans_fd.c
@@ -41,6 +41,7 @@
#include <linux/file.h>
#include <linux/parser.h>
#include <linux/slab.h>
+#include <linux/seq_file.h>
#include <net/9p/9p.h>
#include <net/9p/client.h>
#include <net/9p/transport.h>
@@ -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 <linux/parser.h>
#include <linux/semaphore.h>
#include <linux/slab.h>
+#include <linux/seq_file.h>
#include <net/9p/9p.h>
#include <net/9p/client.h>
#include <net/9p/transport.h>
@@ -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,
};

/**

2017-07-05 15:26:04

by David Howells

[permalink] [raw]
Subject: [PATCH 13/14] 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 <[email protected]>
cc: Mike Marshall <[email protected]>
cc: [email protected]
---

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,

2017-07-05 15:26:03

by David Howells

[permalink] [raw]
Subject: [PATCH 14/14] 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 <[email protected]>
---

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 9f17f21d25fa..f44325610033 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -1360,11 +1360,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 */

/*
@@ -3063,10 +3058,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);

2017-07-05 15:27:47

by David Howells

[permalink] [raw]
Subject: [PATCH 05/14] 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 <[email protected]>
---

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 <linux/uaccess.h>
#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)

2017-07-05 15:30:27

by Steven Rostedt

[permalink] [raw]
Subject: Re: [PATCH 01/14] VFS: Don't use save/replace_mount_options if not using generic_show_options

On Wed, 05 Jul 2017 16:24:09 +0100
David Howells <[email protected]> wrote:

> 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.
>

As this is patch 1/14, is there any dependency on this working? That
is, it is safe to simply remove this caller from those locations? Or
are there dependencies on having any of the 2-14 patches added to make
it not cause issues?

-- Steve

2017-07-05 15:33:40

by David Howells

[permalink] [raw]
Subject: Re: [PATCH 01/14] VFS: Don't use save/replace_mount_options if not using generic_show_options

Steven Rostedt <[email protected]> wrote:

> As this is patch 1/14, is there any dependency on this working? That
> is, it is safe to simply remove this caller from those locations? Or
> are there dependencies on having any of the 2-14 patches added to make
> it not cause issues?

Patch 14 removes the then-unused helpers, but patches 1-13 otherwise are
independent of each other and have no dependencies on earlier patches.

David

2017-07-05 16:42:19

by Eric W. Biederman

[permalink] [raw]
Subject: Re: [RFC][PATCH 00/14] VFS: Make all filesystems implement ->show_options()

David Howells <[email protected]> writes:

> Here's a set of patches that:
>
> (1) Removes calls to save/replace_mount_options() where the filesystem
> then implements ->show_options() anyway, ignoring ->s_options.
>
> (2) Makes all filesystems implement the ->show_options() superblock
> operation rather than using generic_show_options(). If necessary,
> extra information is stored in the superblock information.
>
> (3) Deletes save_mount_options(), replace_mount_options(),
> generic_show_options() and super_block::s_options.
>
> This makes it easier to implement a context-based mount where the options
> are passed individually over a file descriptor. It also allows duplicate
> options, options that override each other and ignored options to be
> resolved rather than storing irrelevant data.

This makes me a little nervous but is probably fine. But we do need
to be careful with remount. Today the rule is all options that need
to be preserved need to be passed to remount. Passing options in one by
one looks like it may make it easy to get that confused while you are
developing your patches.

> Further, a lot of the time, all the information we want to display is
> stored in the super block information anyway, so the option string is
> redundant.
>
> Some things I noted whilst doing this:
>
> (1) A number of filesystems take uid/gid options. Should these be
> reported relative to the observer's user namespace rather than init's
> user namespace? After all, you can't then use those uid/gid options
> if the numbers are interpreted incorrectly if you try and forge a
> mount command from them.

Options should be relative to the mount call. Which is almost always
&init_user_ns and in the general case would be sb->s_user_ns.

Which I believe becomes the creator of the mount context in the model
you are working towards.

> (2) Should I provide a helper for displaying uid/gid options?
>
> (3) How much do we need to worry about racing with remount? Some
> filesystems happily give out the contents of the super_block without
> regard to the fact that remount might be changing it simultaneously -
> ext4, for example.
>
> (4) What string options actually need 'munging'?
>
> These patches can be found here:
>
> https://git.kernel.org/pub/scm/linux/kernel/git/dhowells/linux-fs.git/log/?h=for-viro
>
> on top of three other minor patches.
>
> David
> ---
> David Howells (14):
> VFS: Don't use save/replace_mount_options if not using generic_show_options
> hugetlbfs: Implement show_options
> omfs: Implement show_options
> pstore: Implement show_options
> ramfs: Implement show_options
> bpf: Implement show_options
> spufs: Implement show_options
> befs: Implement show_options
> affs: Implement show_options
> afs: Implement show_options
> isofs: Implement show_options
> 9p: Implement show_options
> orangefs: Implement show_options
> VFS: Kill off s_options and helpers
>
>
> Documentation/filesystems/vfs.txt | 6 --
> arch/powerpc/platforms/cell/spufs/inode.c | 21 +++++++--
> fs/9p/v9fs.c | 59 ++++++++++++++++++++++++
> fs/9p/v9fs.h | 3 +
> fs/9p/vfs_super.c | 6 +-
> fs/affs/super.c | 42 +++++++++++++++--
> fs/afs/super.c | 45 ++++++++++++++++++-
> fs/befs/linuxvfs.c | 24 +++++++++-
> fs/btrfs/super.c | 1
> fs/debugfs/inode.c | 2 -
> fs/efivarfs/super.c | 1
> fs/hugetlbfs/inode.c | 70 +++++++++++++++++++++++------
> fs/isofs/inode.c | 51 ++++++++++++++++++++-
> fs/isofs/isofs.h | 3 +
> fs/namespace.c | 59 ------------------------
> fs/omfs/inode.c | 33 ++++++++++++--
> fs/orangefs/super.c | 15 ++++++
> fs/pstore/inode.c | 14 +++++-
> fs/pstore/internal.h | 3 +
> fs/pstore/platform.c | 2 -
> fs/ramfs/inode.c | 32 +++++++++----
> fs/reiserfs/super.c | 4 --
> fs/super.c | 1
> fs/tracefs/inode.c | 2 -
> include/linux/fs.h | 9 ----
> include/linux/hugetlb.h | 3 +
> include/net/9p/client.h | 13 +++++
> include/net/9p/transport.h | 1
> kernel/bpf/inode.c | 16 +++++--
> net/9p/client.c | 25 ++++++++++
> net/9p/trans_fd.c | 31 ++++++++++++-
> net/9p/trans_rdma.c | 31 ++++++++++++-
> 32 files changed, 481 insertions(+), 147 deletions(-)

2017-07-05 17:11:03

by Kees Cook

[permalink] [raw]
Subject: Re: [PATCH 04/14] pstore: Implement show_options

On Wed, Jul 5, 2017 at 8:24 AM, David Howells <[email protected]> wrote:
> 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 <[email protected]>
> cc: Kees Cook <[email protected]>
> cc: Anton Vorontsov <[email protected]>
> cc: Colin Cross <[email protected]>
> cc: Tony Luck <[email protected]>

Acked-by: Kees Cook <[email protected]>

Do you want me to take this into the pstore tree or do you want to
push it via a separate tree?

-Kees

> ---
>
> 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 <linux/time.h>
> #include <linux/pstore.h>
>
> +#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)
> {
>



--
Kees Cook
Pixel Security

2017-07-05 18:50:27

by Greg KH

[permalink] [raw]
Subject: Re: [PATCH 01/14] VFS: Don't use save/replace_mount_options if not using generic_show_options

On Wed, Jul 05, 2017 at 04:24:09PM +0100, David Howells wrote:
> 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 <[email protected]>
> cc: Chris Mason <[email protected]>
> cc: Greg Kroah-Hartman <[email protected]>
> cc: Steven Rostedt <[email protected]>
> cc: [email protected]
> cc: [email protected]

For debugfs:
Acked-by: Greg Kroah-Hartman <[email protected]>

2017-07-05 18:54:51

by Steven Rostedt

[permalink] [raw]
Subject: Re: [PATCH 01/14] VFS: Don't use save/replace_mount_options if not using generic_show_options

On Wed, 05 Jul 2017 16:33:29 +0100
David Howells <[email protected]> wrote:

> Steven Rostedt <[email protected]> wrote:
>
> > As this is patch 1/14, is there any dependency on this working? That
> > is, it is safe to simply remove this caller from those locations? Or
> > are there dependencies on having any of the 2-14 patches added to make
> > it not cause issues?
>
> Patch 14 removes the then-unused helpers, but patches 1-13 otherwise are
> independent of each other and have no dependencies on earlier patches.
>

So basically it's an useless function call wrt tracefs. In that case...

Acked-by: Steven Rostedt (VMware) <[email protected]>

-- Steve

2017-07-06 08:01:08

by Daniel Borkmann

[permalink] [raw]
Subject: Re: [PATCH 06/14] bpf: Implement show_options

On 07/05/2017 05:24 PM, David Howells wrote:
> 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 <[email protected]>
> cc: Alexei Starovoitov <[email protected]>
> cc: Daniel Borkmann <[email protected]>
> cc: [email protected]

Acked-by: Daniel Borkmann <[email protected]>

2017-07-07 15:59:03

by David Howells

[permalink] [raw]
Subject: Re: [RFC][PATCH 00/14] VFS: Make all filesystems implement ->show_options()

Eric W. Biederman <[email protected]> wrote:

> > This makes it easier to implement a context-based mount where the options
> > are passed individually over a file descriptor. It also allows duplicate
> > options, options that override each other and ignored options to be
> > resolved rather than storing irrelevant data.
>
> This makes me a little nervous but is probably fine. But we do need
> to be careful with remount. Today the rule is all options that need
> to be preserved need to be passed to remount. Passing options in one by
> one looks like it may make it easy to get that confused while you are
> developing your patches.

Yeah. We actually currently get this *wrong* in both ext4 and btrfs - and
probably other disk filesystems too. During ext4 remount and btrfs remount,
the options are parsed directly into the live xxx_fs_info struct, but if
there's a parse error mid-way, we only partially apply the options and have no
idea where it went wrong and what the current state is.

What I'm looking it is breaking it down into a number of steps:

(1) Parse the options one at a time into a context struct.

(2) Once we've got all the options, validate the options we've been given
with respect to themselves.

(3) Under lock:

(a) Check the coherency of the options we've been given with respect to
the superblock (if new mount) or the current live state (if remount).

(b) Apply the options. This is not permitted to fail.

This gets more complicated under ext4 as you've got an extra option string
stored on disk that you also have to apply and combine with the options
presented to the mount interface.

> Options should be relative to the mount call. Which is almost always
> &init_user_ns and in the general case would be sb->s_user_ns.

I generally agree with this - my only doubt is that it might leak external
user/group IDs into a container. Not sure if that's really worth worrying
about, though.

'user' permitted mounts are handled in userspace by a SUID mount program,
right?

David

2017-07-07 16:00:11

by David Howells

[permalink] [raw]
Subject: Re: [PATCH 04/14] pstore: Implement show_options

Kees Cook <[email protected]> wrote:

> Do you want me to take this into the pstore tree or do you want to
> push it via a separate tree?

I really want to punt that question to Al. These are a prerequisite for my
fs_context patches.

David

2017-07-07 18:29:46

by Bob Copeland

[permalink] [raw]
Subject: Re: [PATCH 03/14] omfs: Implement show_options

On Wed, Jul 05, 2017 at 04:24:27PM +0100, David Howells wrote:
> 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 <[email protected]>
> cc: Bob Copeland <[email protected]>

Acked-by: Bob Copeland <[email protected]>

--
Bob Copeland %% https://bobcopeland.com/

2017-07-08 15:33:46

by Theodore Ts'o

[permalink] [raw]
Subject: Re: [RFC][PATCH 00/14] VFS: Make all filesystems implement ->show_options()

On Fri, Jul 07, 2017 at 04:58:56PM +0100, David Howells wrote:
> Yeah. We actually currently get this *wrong* in both ext4 and btrfs - and
> probably other disk filesystems too. During ext4 remount and btrfs remount,
> the options are parsed directly into the live xxx_fs_info struct, but if
> there's a parse error mid-way, we only partially apply the options and have no
> idea where it went wrong and what the current state is.
>
> What I'm looking it is breaking it down into a number of steps:
>
> (1) Parse the options one at a time into a context struct.
>
> (2) Once we've got all the options, validate the options we've been given
> with respect to themselves.
>
> (3) Under lock:
>
> (a) Check the coherency of the options we've been given with respect to
> the superblock (if new mount) or the current live state (if remount).
>
> (b) Apply the options. This is not permitted to fail.
>
> This gets more complicated under ext4 as you've got an extra option string
> stored on disk that you also have to apply and combine with the options
> presented to the mount interface.

Remounts aren't really performance critical, so it might be simpler
just to do one pass which just checks the options, applying the
options to a scratch xx_fs_info struct, and if it seeded, redo the
parse from scratch, this time applying to the live xxx_fs_info struct.

- Ted


2017-07-10 16:16:29

by David Sterba

[permalink] [raw]
Subject: Re: [PATCH 01/14] VFS: Don't use save/replace_mount_options if not using generic_show_options

On Wed, Jul 05, 2017 at 04:24:09PM +0100, David Howells wrote:
> 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 <[email protected]>
> cc: Chris Mason <[email protected]>
> cc: Greg Kroah-Hartman <[email protected]>
> cc: Steven Rostedt <[email protected]>
> cc: [email protected]
> cc: [email protected]
> ---

For

> fs/btrfs/super.c | 1 -

Acked-by: David Sterba <[email protected]>

2017-07-11 15:23:10

by David Howells

[permalink] [raw]
Subject: [PATCH] isofs: Fix isofs_show_options()

Hi Al,

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, as mentioned in a previous email, the session
number handing appears to be incorrect between where it is parsed and where it
is used.

David
---
isofs: Fix isofs_show_options()

isofs_show_options() compares sbi->s_session to -1, but s_session is an
unsigned char, so the comparison isn't right. Compare against 255 instead.

Further, 1 needs subtracting from the session number to counteract the
increment in the option parser.

Reported-by: Dan Carpenter <[email protected]>
Signed-off-by: David Howells <[email protected]>
---
diff --git a/fs/isofs/inode.c b/fs/isofs/inode.c
index f80ee600d1bc..add72c995f90 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)

2017-07-11 22:34:54

by Yury Norov

[permalink] [raw]
Subject: Re: [PATCH 12/14] 9p: Implement show_options

On Wed, Jul 05, 2017 at 04:25:37PM +0100, David Howells wrote:
> 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 <[email protected]>
> cc: Eric Van Hensbergen <[email protected]>
> cc: Ron Minnich <[email protected]>
> cc: Latchesar Ionkov <[email protected]>
> cc: [email protected]
> ---

[...]

> +/*
> + * 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]);
> + if (v9ses->cachetag && v9ses->cache == CACHE_FSCACHE)
> + seq_printf(m, ",cachetag=%s", v9ses->cachetag);

Hi David,

I just found that this patch breaks the next-20170711 build for me:
fs/9p/v9fs.c: In function ‘v9fs_show_options’:
fs/9p/v9fs.c:140:13: error: ‘struct v9fs_session_info’ has no member
named ‘cachetag’; did you mean ‘cache’?
if (v9ses->cachetag && v9ses->cache == CACHE_FSCACHE)
^~~~~~~~
cache
fs/9p/v9fs.c:141:40: error: ‘struct v9fs_session_info’ has no member named ‘cachetag’; did you mean ‘cache’?
seq_printf(m, ",cachetag=%s", v9ses->cachetag);
^~~~~~~~
cache
It seems you forgot to wrap it with #ifdef CONFIG_9P_FSCACHE

Yury

2017-07-11 23:34:21

by David Howells

[permalink] [raw]
Subject: Re: [PATCH 12/14] 9p: Implement show_options

Yury Norov <[email protected]> wrote:

> It seems you forgot to wrap it with #ifdef CONFIG_9P_FSCACHE

Yeah. Arnd proposed a patch for this.

David