aboutsummaryrefslogtreecommitdiffstats
path: root/fs/hugetlbfs/inode.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/hugetlbfs/inode.c')
-rw-r--r--fs/hugetlbfs/inode.c98
1 files changed, 71 insertions, 27 deletions
diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c
index e6b46b3ac2fe..c848a191525d 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,73 @@ 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) { 621
602 if (!*opt) 622 while ((p = strsep(&options, ",")) != NULL) {
623 int token;
624 if (!*p)
603 continue; 625 continue;
604 626
605 value = strchr(opt, '='); 627 token = match_token(p, tokens, args);
606 if (!value || !*value) 628 switch (token) {
607 return -EINVAL; 629 case Opt_uid:
608 else 630 if (match_int(&args[0], &option))
609 *value++ = '\0'; 631 goto bad_val;
610 632 pconfig->uid = option;
611 if (!strcmp(opt, "uid")) 633 break;
612 pconfig->uid = simple_strtoul(value, &value, 0); 634
613 else if (!strcmp(opt, "gid")) 635 case Opt_gid:
614 pconfig->gid = simple_strtoul(value, &value, 0); 636 if (match_int(&args[0], &option))
615 else if (!strcmp(opt, "mode")) 637 goto bad_val;
616 pconfig->mode = simple_strtoul(value,&value,0) & 0777U; 638 pconfig->gid = option;
617 else if (!strcmp(opt, "size")) { 639 break;
618 unsigned long long size = memparse(value, &rest); 640
641 case Opt_mode:
642 if (match_octal(&args[0], &option))
643 goto bad_val;
644 pconfig->mode = option & 0777U;
645 break;
646
647 case Opt_size: {
648 unsigned long long size;
649 /* memparse() will accept a K/M/G without a digit */
650 if (!isdigit(*args[0].from))
651 goto bad_val;
652 size = memparse(args[0].from, &rest);
619 if (*rest == '%') { 653 if (*rest == '%') {
620 size <<= HPAGE_SHIFT; 654 size <<= HPAGE_SHIFT;
621 size *= max_huge_pages; 655 size *= max_huge_pages;
622 do_div(size, 100); 656 do_div(size, 100);
623 rest++;
624 } 657 }
625 pconfig->nr_blocks = (size >> HPAGE_SHIFT); 658 pconfig->nr_blocks = (size >> HPAGE_SHIFT);
626 value = rest; 659 break;
627 } else if (!strcmp(opt,"nr_inodes")) { 660 }
628 pconfig->nr_inodes = memparse(value, &rest); 661
629 value = rest; 662 case Opt_nr_inodes:
630 } else 663 /* memparse() will accept a K/M/G without a digit */
631 return -EINVAL; 664 if (!isdigit(*args[0].from))
665 goto bad_val;
666 pconfig->nr_inodes = memparse(args[0].from, &rest);
667 break;
632 668
633 if (*value) 669 default:
670 printk(KERN_ERR "hugetlbfs: Bad mount option: \"%s\"\n",
671 p);
634 return -EINVAL; 672 return -EINVAL;
673 break;
674 }
635 } 675 }
636 return 0; 676 return 0;
677
678bad_val:
679 printk(KERN_ERR "hugetlbfs: Bad value '%s' for mount option '%s'\n",
680 args[0].from, p);
681 return 1;
637} 682}
638 683
639static int 684static int
@@ -651,7 +696,6 @@ hugetlbfs_fill_super(struct super_block *sb, void *data, int silent)
651 config.gid = current->fsgid; 696 config.gid = current->fsgid;
652 config.mode = 0755; 697 config.mode = 0755;
653 ret = hugetlbfs_parse_options(data, &config); 698 ret = hugetlbfs_parse_options(data, &config);
654
655 if (ret) 699 if (ret)
656 return ret; 700 return ret;
657 701
@@ -804,7 +848,7 @@ static int __init init_hugetlbfs_fs(void)
804 848
805 hugetlbfs_inode_cachep = kmem_cache_create("hugetlbfs_inode_cache", 849 hugetlbfs_inode_cachep = kmem_cache_create("hugetlbfs_inode_cache",
806 sizeof(struct hugetlbfs_inode_info), 850 sizeof(struct hugetlbfs_inode_info),
807 0, 0, init_once, NULL); 851 0, 0, init_once);
808 if (hugetlbfs_inode_cachep == NULL) 852 if (hugetlbfs_inode_cachep == NULL)
809 return -ENOMEM; 853 return -ENOMEM;
810 854