|
@@ -53,6 +53,7 @@ int sysctl_hugetlb_shm_group;
|
|
enum {
|
|
enum {
|
|
Opt_size, Opt_nr_inodes,
|
|
Opt_size, Opt_nr_inodes,
|
|
Opt_mode, Opt_uid, Opt_gid,
|
|
Opt_mode, Opt_uid, Opt_gid,
|
|
|
|
+ Opt_pagesize,
|
|
Opt_err,
|
|
Opt_err,
|
|
};
|
|
};
|
|
|
|
|
|
@@ -62,6 +63,7 @@ static match_table_t tokens = {
|
|
{Opt_mode, "mode=%o"},
|
|
{Opt_mode, "mode=%o"},
|
|
{Opt_uid, "uid=%u"},
|
|
{Opt_uid, "uid=%u"},
|
|
{Opt_gid, "gid=%u"},
|
|
{Opt_gid, "gid=%u"},
|
|
|
|
+ {Opt_pagesize, "pagesize=%s"},
|
|
{Opt_err, NULL},
|
|
{Opt_err, NULL},
|
|
};
|
|
};
|
|
|
|
|
|
@@ -750,6 +752,8 @@ hugetlbfs_parse_options(char *options, struct hugetlbfs_config *pconfig)
|
|
char *p, *rest;
|
|
char *p, *rest;
|
|
substring_t args[MAX_OPT_ARGS];
|
|
substring_t args[MAX_OPT_ARGS];
|
|
int option;
|
|
int option;
|
|
|
|
+ unsigned long long size = 0;
|
|
|
|
+ enum { NO_SIZE, SIZE_STD, SIZE_PERCENT } setsize = NO_SIZE;
|
|
|
|
|
|
if (!options)
|
|
if (!options)
|
|
return 0;
|
|
return 0;
|
|
@@ -780,17 +784,13 @@ hugetlbfs_parse_options(char *options, struct hugetlbfs_config *pconfig)
|
|
break;
|
|
break;
|
|
|
|
|
|
case Opt_size: {
|
|
case Opt_size: {
|
|
- unsigned long long size;
|
|
|
|
/* memparse() will accept a K/M/G without a digit */
|
|
/* memparse() will accept a K/M/G without a digit */
|
|
if (!isdigit(*args[0].from))
|
|
if (!isdigit(*args[0].from))
|
|
goto bad_val;
|
|
goto bad_val;
|
|
size = memparse(args[0].from, &rest);
|
|
size = memparse(args[0].from, &rest);
|
|
- if (*rest == '%') {
|
|
|
|
- size <<= HPAGE_SHIFT;
|
|
|
|
- size *= max_huge_pages;
|
|
|
|
- do_div(size, 100);
|
|
|
|
- }
|
|
|
|
- pconfig->nr_blocks = (size >> HPAGE_SHIFT);
|
|
|
|
|
|
+ setsize = SIZE_STD;
|
|
|
|
+ if (*rest == '%')
|
|
|
|
+ setsize = SIZE_PERCENT;
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -801,6 +801,19 @@ hugetlbfs_parse_options(char *options, struct hugetlbfs_config *pconfig)
|
|
pconfig->nr_inodes = memparse(args[0].from, &rest);
|
|
pconfig->nr_inodes = memparse(args[0].from, &rest);
|
|
break;
|
|
break;
|
|
|
|
|
|
|
|
+ case Opt_pagesize: {
|
|
|
|
+ unsigned long ps;
|
|
|
|
+ ps = memparse(args[0].from, &rest);
|
|
|
|
+ pconfig->hstate = size_to_hstate(ps);
|
|
|
|
+ if (!pconfig->hstate) {
|
|
|
|
+ printk(KERN_ERR
|
|
|
|
+ "hugetlbfs: Unsupported page size %lu MB\n",
|
|
|
|
+ ps >> 20);
|
|
|
|
+ return -EINVAL;
|
|
|
|
+ }
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+
|
|
default:
|
|
default:
|
|
printk(KERN_ERR "hugetlbfs: Bad mount option: \"%s\"\n",
|
|
printk(KERN_ERR "hugetlbfs: Bad mount option: \"%s\"\n",
|
|
p);
|
|
p);
|
|
@@ -808,6 +821,18 @@ hugetlbfs_parse_options(char *options, struct hugetlbfs_config *pconfig)
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+ /* Do size after hstate is set up */
|
|
|
|
+ if (setsize > NO_SIZE) {
|
|
|
|
+ struct hstate *h = pconfig->hstate;
|
|
|
|
+ if (setsize == SIZE_PERCENT) {
|
|
|
|
+ size <<= huge_page_shift(h);
|
|
|
|
+ size *= h->max_huge_pages;
|
|
|
|
+ do_div(size, 100);
|
|
|
|
+ }
|
|
|
|
+ pconfig->nr_blocks = (size >> huge_page_shift(h));
|
|
|
|
+ }
|
|
|
|
+
|
|
return 0;
|
|
return 0;
|
|
|
|
|
|
bad_val:
|
|
bad_val:
|
|
@@ -832,6 +857,7 @@ hugetlbfs_fill_super(struct super_block *sb, void *data, int silent)
|
|
config.uid = current->fsuid;
|
|
config.uid = current->fsuid;
|
|
config.gid = current->fsgid;
|
|
config.gid = current->fsgid;
|
|
config.mode = 0755;
|
|
config.mode = 0755;
|
|
|
|
+ config.hstate = &default_hstate;
|
|
ret = hugetlbfs_parse_options(data, &config);
|
|
ret = hugetlbfs_parse_options(data, &config);
|
|
if (ret)
|
|
if (ret)
|
|
return ret;
|
|
return ret;
|
|
@@ -840,14 +866,15 @@ hugetlbfs_fill_super(struct super_block *sb, void *data, int silent)
|
|
if (!sbinfo)
|
|
if (!sbinfo)
|
|
return -ENOMEM;
|
|
return -ENOMEM;
|
|
sb->s_fs_info = sbinfo;
|
|
sb->s_fs_info = sbinfo;
|
|
|
|
+ sbinfo->hstate = config.hstate;
|
|
spin_lock_init(&sbinfo->stat_lock);
|
|
spin_lock_init(&sbinfo->stat_lock);
|
|
sbinfo->max_blocks = config.nr_blocks;
|
|
sbinfo->max_blocks = config.nr_blocks;
|
|
sbinfo->free_blocks = config.nr_blocks;
|
|
sbinfo->free_blocks = config.nr_blocks;
|
|
sbinfo->max_inodes = config.nr_inodes;
|
|
sbinfo->max_inodes = config.nr_inodes;
|
|
sbinfo->free_inodes = config.nr_inodes;
|
|
sbinfo->free_inodes = config.nr_inodes;
|
|
sb->s_maxbytes = MAX_LFS_FILESIZE;
|
|
sb->s_maxbytes = MAX_LFS_FILESIZE;
|
|
- sb->s_blocksize = HPAGE_SIZE;
|
|
|
|
- sb->s_blocksize_bits = HPAGE_SHIFT;
|
|
|
|
|
|
+ sb->s_blocksize = huge_page_size(config.hstate);
|
|
|
|
+ sb->s_blocksize_bits = huge_page_shift(config.hstate);
|
|
sb->s_magic = HUGETLBFS_MAGIC;
|
|
sb->s_magic = HUGETLBFS_MAGIC;
|
|
sb->s_op = &hugetlbfs_ops;
|
|
sb->s_op = &hugetlbfs_ops;
|
|
sb->s_time_gran = 1;
|
|
sb->s_time_gran = 1;
|