hugetlbfs: Implement show_options
authorDavid Howells <dhowells@redhat.com>
Wed, 5 Jul 2017 15:24:18 +0000 (16:24 +0100)
committerAl Viro <viro@zeniv.linux.org.uk>
Thu, 6 Jul 2017 07:31:46 +0000 (03:31 -0400)
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 <dhowells@redhat.com>
cc: Nadia Yvette Chambers <nyc@holomorphy.com>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
fs/hugetlbfs/inode.c
include/linux/hugetlb.h

index d44f545..99b3b98 100644 (file)
@@ -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
index b857fc8..3b6eeaa 100644 (file)
@@ -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)