diff options
-rw-r--r-- | Documentation/vm/hugetlbpage.txt | 10 | ||||
-rw-r--r-- | fs/hugetlbfs/inode.c | 96 |
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 | |||
77 | call, then it is required that system administrator mount a file system of | 77 | call, then it is required that system administrator mount a file system of |
78 | type hugetlbfs: | 78 | type 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 | ||
83 | This command mounts a (pseudo) filesystem of type hugetlbfs on the directory | 84 | This 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. | |||
88 | By default the value 0755 is picked. The size option sets the maximum value of | 89 | By default the value 0755 is picked. The size option sets the maximum value of |
89 | memory (huge pages) allowed for that filesystem (/mnt/huge). The size is | 90 | memory (huge pages) allowed for that filesystem (/mnt/huge). The size is |
90 | rounded down to HPAGE_SIZE. The option nr_inodes sets the maximum number of | 91 | rounded down to HPAGE_SIZE. The option nr_inodes sets the maximum number of |
91 | inodes that /mnt/huge can use. If the size or nr_inodes options are not | 92 | inodes that /mnt/huge can use. If the size or nr_inodes option is not |
92 | provided on command line then no limits are set. For size and nr_inodes | 93 | provided on command line then no limits are set. For size and nr_inodes |
93 | options, you can use [G|g]/[M|m]/[K|k] to represent giga/mega/kilo. For | 94 | options, you can use [G|g]/[M|m]/[K|k] to represent giga/mega/kilo. For |
94 | example, size=2K has the same meaning as size=2048. An example is given at | 95 | example, size=2K has the same meaning as size=2048. |
95 | the end of this document. | ||
96 | 96 | ||
97 | read and write system calls are not supported on files that reside on hugetlb | 97 | read and write system calls are not supported on files that reside on hugetlb |
98 | file systems. | 98 | file 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 | ||
48 | int sysctl_hugetlb_shm_group; | 51 | int sysctl_hugetlb_shm_group; |
49 | 52 | ||
53 | enum { | ||
54 | Opt_size, Opt_nr_inodes, | ||
55 | Opt_mode, Opt_uid, Opt_gid, | ||
56 | Opt_err, | ||
57 | }; | ||
58 | |||
59 | static 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 | |||
50 | static void huge_pagevec_release(struct pagevec *pvec) | 68 | static 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 = { | |||
594 | static int | 612 | static int |
595 | hugetlbfs_parse_options(char *options, struct hugetlbfs_config *pconfig) | 613 | hugetlbfs_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 | |||
675 | bad_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 | ||
639 | static int | 681 | static int |