diff options
Diffstat (limited to 'fs/hugetlbfs/inode.c')
-rw-r--r-- | fs/hugetlbfs/inode.c | 96 |
1 files changed, 69 insertions, 27 deletions
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 |