aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/vm/hugetlbpage.txt10
-rw-r--r--fs/hugetlbfs/inode.c96
2 files changed, 74 insertions, 32 deletions
diff --git a/Documentation/vm/hugetlbpage.txt b/Documentation/vm/hugetlbpage.txt
index 687104bfd09a..51ccc48aa763 100644
--- a/Documentation/vm/hugetlbpage.txt
+++ b/Documentation/vm/hugetlbpage.txt
@@ -77,8 +77,9 @@ If the user applications are going to request hugepages using mmap system
77call, then it is required that system administrator mount a file system of 77call, then it is required that system administrator mount a file system of
78type hugetlbfs: 78type hugetlbfs:
79 79
80 mount none /mnt/huge -t hugetlbfs <uid=value> <gid=value> <mode=value> 80 mount -t hugetlbfs \
81 <size=value> <nr_inodes=value> 81 -o uid=<value>,gid=<value>,mode=<value>,size=<value>,nr_inodes=<value> \
82 none /mnt/huge
82 83
83This command mounts a (pseudo) filesystem of type hugetlbfs on the directory 84This command mounts a (pseudo) filesystem of type hugetlbfs on the directory
84/mnt/huge. Any files created on /mnt/huge uses hugepages. The uid and gid 85/mnt/huge. Any files created on /mnt/huge uses hugepages. The uid and gid
@@ -88,11 +89,10 @@ mode of root of file system to value & 0777. This value is given in octal.
88By default the value 0755 is picked. The size option sets the maximum value of 89By default the value 0755 is picked. The size option sets the maximum value of
89memory (huge pages) allowed for that filesystem (/mnt/huge). The size is 90memory (huge pages) allowed for that filesystem (/mnt/huge). The size is
90rounded down to HPAGE_SIZE. The option nr_inodes sets the maximum number of 91rounded down to HPAGE_SIZE. The option nr_inodes sets the maximum number of
91inodes that /mnt/huge can use. If the size or nr_inodes options are not 92inodes that /mnt/huge can use. If the size or nr_inodes option is not
92provided on command line then no limits are set. For size and nr_inodes 93provided on command line then no limits are set. For size and nr_inodes
93options, you can use [G|g]/[M|m]/[K|k] to represent giga/mega/kilo. For 94options, you can use [G|g]/[M|m]/[K|k] to represent giga/mega/kilo. For
94example, size=2K has the same meaning as size=2048. An example is given at 95example, size=2K has the same meaning as size=2048.
95the end of this document.
96 96
97read and write system calls are not supported on files that reside on hugetlb 97read and write system calls are not supported on files that reside on hugetlb
98file systems. 98file systems.
diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c
index e6b46b3ac2fe..711b801fbcdf 100644
--- a/fs/hugetlbfs/inode.c
+++ b/fs/hugetlbfs/inode.c
@@ -13,15 +13,18 @@
13#include <linux/fs.h> 13#include <linux/fs.h>
14#include <linux/mount.h> 14#include <linux/mount.h>
15#include <linux/file.h> 15#include <linux/file.h>
16#include <linux/kernel.h>
16#include <linux/writeback.h> 17#include <linux/writeback.h>
17#include <linux/pagemap.h> 18#include <linux/pagemap.h>
18#include <linux/highmem.h> 19#include <linux/highmem.h>
19#include <linux/init.h> 20#include <linux/init.h>
20#include <linux/string.h> 21#include <linux/string.h>
21#include <linux/capability.h> 22#include <linux/capability.h>
23#include <linux/ctype.h>
22#include <linux/backing-dev.h> 24#include <linux/backing-dev.h>
23#include <linux/hugetlb.h> 25#include <linux/hugetlb.h>
24#include <linux/pagevec.h> 26#include <linux/pagevec.h>
27#include <linux/parser.h>
25#include <linux/mman.h> 28#include <linux/mman.h>
26#include <linux/quotaops.h> 29#include <linux/quotaops.h>
27#include <linux/slab.h> 30#include <linux/slab.h>
@@ -47,6 +50,21 @@ static struct backing_dev_info hugetlbfs_backing_dev_info = {
47 50
48int sysctl_hugetlb_shm_group; 51int sysctl_hugetlb_shm_group;
49 52
53enum {
54 Opt_size, Opt_nr_inodes,
55 Opt_mode, Opt_uid, Opt_gid,
56 Opt_err,
57};
58
59static match_table_t tokens = {
60 {Opt_size, "size=%s"},
61 {Opt_nr_inodes, "nr_inodes=%s"},
62 {Opt_mode, "mode=%o"},
63 {Opt_uid, "uid=%u"},
64 {Opt_gid, "gid=%u"},
65 {Opt_err, NULL},
66};
67
50static void huge_pagevec_release(struct pagevec *pvec) 68static void huge_pagevec_release(struct pagevec *pvec)
51{ 69{
52 int i; 70 int i;
@@ -594,46 +612,70 @@ static const struct super_operations hugetlbfs_ops = {
594static int 612static int
595hugetlbfs_parse_options(char *options, struct hugetlbfs_config *pconfig) 613hugetlbfs_parse_options(char *options, struct hugetlbfs_config *pconfig)
596{ 614{
597 char *opt, *value, *rest; 615 char *p, *rest;
616 substring_t args[MAX_OPT_ARGS];
617 int option;
598 618
599 if (!options) 619 if (!options)
600 return 0; 620 return 0;
601 while ((opt = strsep(&options, ",")) != NULL) {
602 if (!*opt)
603 continue;
604 621
605 value = strchr(opt, '='); 622 while ((p = strsep(&options, ",")) != NULL) {
606 if (!value || !*value) 623 int token;
607 return -EINVAL; 624
608 else 625 token = match_token(p, tokens, args);
609 *value++ = '\0'; 626 switch (token) {
610 627 case Opt_uid:
611 if (!strcmp(opt, "uid")) 628 if (match_int(&args[0], &option))
612 pconfig->uid = simple_strtoul(value, &value, 0); 629 goto bad_val;
613 else if (!strcmp(opt, "gid")) 630 pconfig->uid = option;
614 pconfig->gid = simple_strtoul(value, &value, 0); 631 break;
615 else if (!strcmp(opt, "mode")) 632
616 pconfig->mode = simple_strtoul(value,&value,0) & 0777U; 633 case Opt_gid:
617 else if (!strcmp(opt, "size")) { 634 if (match_int(&args[0], &option))
618 unsigned long long size = memparse(value, &rest); 635 goto bad_val;
636 pconfig->gid = option;
637 break;
638
639 case Opt_mode:
640 if (match_octal(&args[0], &option))
641 goto bad_val;
642 pconfig->mode = option & 0777U;
643 break;
644
645 case Opt_size: {
646 unsigned long long size;
647 /* memparse() will accept a K/M/G without a digit */
648 if (!isdigit(*args[0].from))
649 goto bad_val;
650 size = memparse(args[0].from, &rest);
619 if (*rest == '%') { 651 if (*rest == '%') {
620 size <<= HPAGE_SHIFT; 652 size <<= HPAGE_SHIFT;
621 size *= max_huge_pages; 653 size *= max_huge_pages;
622 do_div(size, 100); 654 do_div(size, 100);
623 rest++;
624 } 655 }
625 pconfig->nr_blocks = (size >> HPAGE_SHIFT); 656 pconfig->nr_blocks = (size >> HPAGE_SHIFT);
626 value = rest; 657 break;
627 } else if (!strcmp(opt,"nr_inodes")) { 658 }
628 pconfig->nr_inodes = memparse(value, &rest);
629 value = rest;
630 } else
631 return -EINVAL;
632 659
633 if (*value) 660 case Opt_nr_inodes:
634 return -EINVAL; 661 /* memparse() will accept a K/M/G without a digit */
662 if (!isdigit(*args[0].from))
663 goto bad_val;
664 pconfig->nr_inodes = memparse(args[0].from, &rest);
665 break;
666
667 default:
668 printk(KERN_ERR "hugetlbfs: Bad mount option: %s\n", p);
669 return 1;
670 break;
671 }
635 } 672 }
636 return 0; 673 return 0;
674
675bad_val:
676 printk(KERN_ERR "hugetlbfs: Bad value '%s' for mount option '%s'\n",
677 args[0].from, p);
678 return 1;
637} 679}
638 680
639static int 681static int