aboutsummaryrefslogtreecommitdiffstats
path: root/fs/hugetlbfs
diff options
context:
space:
mode:
authorMike Kravetz <mike.kravetz@oracle.com>2015-04-15 19:13:42 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2015-04-15 19:35:18 -0400
commit7ca02d0ae586fe7df59632966a64f3f1a756ef05 (patch)
tree71a66a1c50afb8b8e47c48058695693b7f405cb3 /fs/hugetlbfs
parent1c5ecae3a93fa1ab51a784d77e9c9ed54e67c65f (diff)
hugetlbfs: accept subpool min_size mount option and setup accordingly
Make 'min_size=<value>' be an option when mounting a hugetlbfs. This option takes the same value as the 'size' option. min_size can be specified without specifying size. If both are specified, min_size must be less that or equal to size else the mount will fail. If min_size is specified, then at mount time an attempt is made to reserve min_size pages. If the reservation fails, the mount fails. At umount time, the reserved pages are released. Signed-off-by: Mike Kravetz <mike.kravetz@oracle.com> Cc: Davidlohr Bueso <dave@stgolabs.net> Cc: Aneesh Kumar <aneesh.kumar@linux.vnet.ibm.com> Cc: Joonsoo Kim <iamjoonsoo.kim@lge.com> Cc: Andi Kleen <andi@firstfloor.org> Cc: David Rientjes <rientjes@google.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs/hugetlbfs')
-rw-r--r--fs/hugetlbfs/inode.c90
1 files changed, 71 insertions, 19 deletions
diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c
index db76cec3ce21..3a8f12762821 100644
--- a/fs/hugetlbfs/inode.c
+++ b/fs/hugetlbfs/inode.c
@@ -47,9 +47,10 @@ struct hugetlbfs_config {
47 kuid_t uid; 47 kuid_t uid;
48 kgid_t gid; 48 kgid_t gid;
49 umode_t mode; 49 umode_t mode;
50 long nr_blocks; 50 long max_hpages;
51 long nr_inodes; 51 long nr_inodes;
52 struct hstate *hstate; 52 struct hstate *hstate;
53 long min_hpages;
53}; 54};
54 55
55struct hugetlbfs_inode_info { 56struct hugetlbfs_inode_info {
@@ -67,7 +68,7 @@ int sysctl_hugetlb_shm_group;
67enum { 68enum {
68 Opt_size, Opt_nr_inodes, 69 Opt_size, Opt_nr_inodes,
69 Opt_mode, Opt_uid, Opt_gid, 70 Opt_mode, Opt_uid, Opt_gid,
70 Opt_pagesize, 71 Opt_pagesize, Opt_min_size,
71 Opt_err, 72 Opt_err,
72}; 73};
73 74
@@ -78,6 +79,7 @@ static const match_table_t tokens = {
78 {Opt_uid, "uid=%u"}, 79 {Opt_uid, "uid=%u"},
79 {Opt_gid, "gid=%u"}, 80 {Opt_gid, "gid=%u"},
80 {Opt_pagesize, "pagesize=%s"}, 81 {Opt_pagesize, "pagesize=%s"},
82 {Opt_min_size, "min_size=%s"},
81 {Opt_err, NULL}, 83 {Opt_err, NULL},
82}; 84};
83 85
@@ -754,14 +756,38 @@ static const struct super_operations hugetlbfs_ops = {
754 .show_options = generic_show_options, 756 .show_options = generic_show_options,
755}; 757};
756 758
759enum { NO_SIZE, SIZE_STD, SIZE_PERCENT };
760
761/*
762 * Convert size option passed from command line to number of huge pages
763 * in the pool specified by hstate. Size option could be in bytes
764 * (val_type == SIZE_STD) or percentage of the pool (val_type == SIZE_PERCENT).
765 */
766static long long
767hugetlbfs_size_to_hpages(struct hstate *h, unsigned long long size_opt,
768 int val_type)
769{
770 if (val_type == NO_SIZE)
771 return -1;
772
773 if (val_type == SIZE_PERCENT) {
774 size_opt <<= huge_page_shift(h);
775 size_opt *= h->max_huge_pages;
776 do_div(size_opt, 100);
777 }
778
779 size_opt >>= huge_page_shift(h);
780 return size_opt;
781}
782
757static int 783static int
758hugetlbfs_parse_options(char *options, struct hugetlbfs_config *pconfig) 784hugetlbfs_parse_options(char *options, struct hugetlbfs_config *pconfig)
759{ 785{
760 char *p, *rest; 786 char *p, *rest;
761 substring_t args[MAX_OPT_ARGS]; 787 substring_t args[MAX_OPT_ARGS];
762 int option; 788 int option;
763 unsigned long long size = 0; 789 unsigned long long max_size_opt = 0, min_size_opt = 0;
764 enum { NO_SIZE, SIZE_STD, SIZE_PERCENT } setsize = NO_SIZE; 790 int max_val_type = NO_SIZE, min_val_type = NO_SIZE;
765 791
766 if (!options) 792 if (!options)
767 return 0; 793 return 0;
@@ -799,10 +825,10 @@ hugetlbfs_parse_options(char *options, struct hugetlbfs_config *pconfig)
799 /* memparse() will accept a K/M/G without a digit */ 825 /* memparse() will accept a K/M/G without a digit */
800 if (!isdigit(*args[0].from)) 826 if (!isdigit(*args[0].from))
801 goto bad_val; 827 goto bad_val;
802 size = memparse(args[0].from, &rest); 828 max_size_opt = memparse(args[0].from, &rest);
803 setsize = SIZE_STD; 829 max_val_type = SIZE_STD;
804 if (*rest == '%') 830 if (*rest == '%')
805 setsize = SIZE_PERCENT; 831 max_val_type = SIZE_PERCENT;
806 break; 832 break;
807 } 833 }
808 834
@@ -825,6 +851,17 @@ hugetlbfs_parse_options(char *options, struct hugetlbfs_config *pconfig)
825 break; 851 break;
826 } 852 }
827 853
854 case Opt_min_size: {
855 /* memparse() will accept a K/M/G without a digit */
856 if (!isdigit(*args[0].from))
857 goto bad_val;
858 min_size_opt = memparse(args[0].from, &rest);
859 min_val_type = SIZE_STD;
860 if (*rest == '%')
861 min_val_type = SIZE_PERCENT;
862 break;
863 }
864
828 default: 865 default:
829 pr_err("Bad mount option: \"%s\"\n", p); 866 pr_err("Bad mount option: \"%s\"\n", p);
830 return -EINVAL; 867 return -EINVAL;
@@ -832,15 +869,22 @@ hugetlbfs_parse_options(char *options, struct hugetlbfs_config *pconfig)
832 } 869 }
833 } 870 }
834 871
835 /* Do size after hstate is set up */ 872 /*
836 if (setsize > NO_SIZE) { 873 * Use huge page pool size (in hstate) to convert the size
837 struct hstate *h = pconfig->hstate; 874 * options to number of huge pages. If NO_SIZE, -1 is returned.
838 if (setsize == SIZE_PERCENT) { 875 */
839 size <<= huge_page_shift(h); 876 pconfig->max_hpages = hugetlbfs_size_to_hpages(pconfig->hstate,
840 size *= h->max_huge_pages; 877 max_size_opt, max_val_type);
841 do_div(size, 100); 878 pconfig->min_hpages = hugetlbfs_size_to_hpages(pconfig->hstate,
842 } 879 min_size_opt, min_val_type);
843 pconfig->nr_blocks = (size >> huge_page_shift(h)); 880
881 /*
882 * If max_size was specified, then min_size must be smaller
883 */
884 if (max_val_type > NO_SIZE &&
885 pconfig->min_hpages > pconfig->max_hpages) {
886 pr_err("minimum size can not be greater than maximum size\n");
887 return -EINVAL;
844 } 888 }
845 889
846 return 0; 890 return 0;
@@ -859,12 +903,13 @@ hugetlbfs_fill_super(struct super_block *sb, void *data, int silent)
859 903
860 save_mount_options(sb, data); 904 save_mount_options(sb, data);
861 905
862 config.nr_blocks = -1; /* No limit on size by default */ 906 config.max_hpages = -1; /* No limit on size by default */
863 config.nr_inodes = -1; /* No limit on number of inodes by default */ 907 config.nr_inodes = -1; /* No limit on number of inodes by default */
864 config.uid = current_fsuid(); 908 config.uid = current_fsuid();
865 config.gid = current_fsgid(); 909 config.gid = current_fsgid();
866 config.mode = 0755; 910 config.mode = 0755;
867 config.hstate = &default_hstate; 911 config.hstate = &default_hstate;
912 config.min_hpages = -1; /* No default minimum size */
868 ret = hugetlbfs_parse_options(data, &config); 913 ret = hugetlbfs_parse_options(data, &config);
869 if (ret) 914 if (ret)
870 return ret; 915 return ret;
@@ -878,8 +923,15 @@ hugetlbfs_fill_super(struct super_block *sb, void *data, int silent)
878 sbinfo->max_inodes = config.nr_inodes; 923 sbinfo->max_inodes = config.nr_inodes;
879 sbinfo->free_inodes = config.nr_inodes; 924 sbinfo->free_inodes = config.nr_inodes;
880 sbinfo->spool = NULL; 925 sbinfo->spool = NULL;
881 if (config.nr_blocks != -1) { 926 /*
882 sbinfo->spool = hugepage_new_subpool(config.nr_blocks); 927 * Allocate and initialize subpool if maximum or minimum size is
928 * specified. Any needed reservations (for minimim size) are taken
929 * taken when the subpool is created.
930 */
931 if (config.max_hpages != -1 || config.min_hpages != -1) {
932 sbinfo->spool = hugepage_new_subpool(config.hstate,
933 config.max_hpages,
934 config.min_hpages);
883 if (!sbinfo->spool) 935 if (!sbinfo->spool)
884 goto out_free; 936 goto out_free;
885 } 937 }