Commit 4a25220d authored by David Howells's avatar David Howells Committed by Al Viro

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: default avatarDavid Howells <dhowells@redhat.com>
cc: Nadia Yvette Chambers <nyc@holomorphy.com>
Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent c3d98ea0
...@@ -46,13 +46,13 @@ static const struct inode_operations hugetlbfs_dir_inode_operations; ...@@ -46,13 +46,13 @@ static const struct inode_operations hugetlbfs_dir_inode_operations;
static const struct inode_operations hugetlbfs_inode_operations; static const struct inode_operations hugetlbfs_inode_operations;
struct hugetlbfs_config { struct hugetlbfs_config {
kuid_t uid; struct hstate *hstate;
kgid_t gid;
umode_t mode;
long max_hpages; long max_hpages;
long nr_inodes; long nr_inodes;
struct hstate *hstate;
long min_hpages; long min_hpages;
kuid_t uid;
kgid_t gid;
umode_t mode;
}; };
struct hugetlbfs_inode_info { struct hugetlbfs_inode_info {
...@@ -851,6 +851,46 @@ static int hugetlbfs_migrate_page(struct address_space *mapping, ...@@ -851,6 +851,46 @@ static int hugetlbfs_migrate_page(struct address_space *mapping,
return MIGRATEPAGE_SUCCESS; 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) static int hugetlbfs_statfs(struct dentry *dentry, struct kstatfs *buf)
{ {
struct hugetlbfs_sb_info *sbinfo = HUGETLBFS_SB(dentry->d_sb); struct hugetlbfs_sb_info *sbinfo = HUGETLBFS_SB(dentry->d_sb);
...@@ -1008,19 +1048,19 @@ static const struct super_operations hugetlbfs_ops = { ...@@ -1008,19 +1048,19 @@ static const struct super_operations hugetlbfs_ops = {
.evict_inode = hugetlbfs_evict_inode, .evict_inode = hugetlbfs_evict_inode,
.statfs = hugetlbfs_statfs, .statfs = hugetlbfs_statfs,
.put_super = hugetlbfs_put_super, .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 * Convert size option passed from command line to number of huge pages
* in the pool specified by hstate. Size option could be in bytes * 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). * (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, 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) if (val_type == NO_SIZE)
return -1; return -1;
...@@ -1042,7 +1082,7 @@ hugetlbfs_parse_options(char *options, struct hugetlbfs_config *pconfig) ...@@ -1042,7 +1082,7 @@ hugetlbfs_parse_options(char *options, struct hugetlbfs_config *pconfig)
substring_t args[MAX_OPT_ARGS]; substring_t args[MAX_OPT_ARGS];
int option; int option;
unsigned long long max_size_opt = 0, min_size_opt = 0; 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) if (!options)
return 0; return 0;
...@@ -1156,8 +1196,6 @@ hugetlbfs_fill_super(struct super_block *sb, void *data, int silent) ...@@ -1156,8 +1196,6 @@ hugetlbfs_fill_super(struct super_block *sb, void *data, int silent)
struct hugetlbfs_config config; struct hugetlbfs_config config;
struct hugetlbfs_sb_info *sbinfo; struct hugetlbfs_sb_info *sbinfo;
save_mount_options(sb, data);
config.max_hpages = -1; /* No limit on size by default */ config.max_hpages = -1; /* No limit on size by default */
config.nr_inodes = -1; /* No limit on number of inodes by default */ config.nr_inodes = -1; /* No limit on number of inodes by default */
config.uid = current_fsuid(); config.uid = current_fsuid();
...@@ -1178,6 +1216,10 @@ hugetlbfs_fill_super(struct super_block *sb, void *data, int silent) ...@@ -1178,6 +1216,10 @@ hugetlbfs_fill_super(struct super_block *sb, void *data, int silent)
sbinfo->max_inodes = config.nr_inodes; sbinfo->max_inodes = config.nr_inodes;
sbinfo->free_inodes = config.nr_inodes; sbinfo->free_inodes = config.nr_inodes;
sbinfo->spool = NULL; 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 * Allocate and initialize subpool if maximum or minimum size is
* specified. Any needed reservations (for minimim size) are taken * specified. Any needed reservations (for minimim size) are taken
......
...@@ -262,6 +262,9 @@ struct hugetlbfs_sb_info { ...@@ -262,6 +262,9 @@ struct hugetlbfs_sb_info {
spinlock_t stat_lock; spinlock_t stat_lock;
struct hstate *hstate; struct hstate *hstate;
struct hugepage_subpool *spool; 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) static inline struct hugetlbfs_sb_info *HUGETLBFS_SB(struct super_block *sb)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment