Эх сурвалжийг харах

hugetlbfs: use lib/parser, fix docs

Use lib/parser.c to parse hugetlbfs mount options.  Correct docs in
hugetlbpage.txt.

old size of hugetlbfs_fill_super:  675 bytes
new size of hugetlbfs_fill_super:  686 bytes
(hugetlbfs_parse_options() is inlined)

Signed-off-by: Randy Dunlap <randy.dunlap@oracle.com>
Cc: Hugh Dickins <hugh@veritas.com>
Cc: David Gibson <david@gibson.dropbear.id.au>
Cc: Adam Litke <agl@us.ibm.com>
Acked-by: William Lee Irwin III <wli@holomorphy.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Randy Dunlap 18 жил өмнө
parent
commit
e73a75fa7f

+ 5 - 5
Documentation/vm/hugetlbpage.txt

@@ -77,8 +77,9 @@ If the user applications are going to request hugepages using mmap system
 call, then it is required that system administrator mount a file system of
 call, then it is required that system administrator mount a file system of
 type hugetlbfs:
 type hugetlbfs:
 
 
-	mount none /mnt/huge -t hugetlbfs <uid=value> <gid=value> <mode=value>
-		 <size=value> <nr_inodes=value>
+  mount -t hugetlbfs \
+	-o uid=<value>,gid=<value>,mode=<value>,size=<value>,nr_inodes=<value> \
+	none /mnt/huge
 
 
 This command mounts a (pseudo) filesystem of type hugetlbfs on the directory
 This command mounts a (pseudo) filesystem of type hugetlbfs on the directory
 /mnt/huge.  Any files created on /mnt/huge uses hugepages.  The uid and gid
 /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.
 By default the value 0755 is picked. The size option sets the maximum value of
 By default the value 0755 is picked. The size option sets the maximum value of
 memory (huge pages) allowed for that filesystem (/mnt/huge). The size is
 memory (huge pages) allowed for that filesystem (/mnt/huge). The size is
 rounded down to HPAGE_SIZE.  The option nr_inodes sets the maximum number of
 rounded down to HPAGE_SIZE.  The option nr_inodes sets the maximum number of
-inodes that /mnt/huge can use.  If the size or nr_inodes options are not
+inodes that /mnt/huge can use.  If the size or nr_inodes option is not
 provided on command line then no limits are set.  For size and nr_inodes
 provided on command line then no limits are set.  For size and nr_inodes
 options, you can use [G|g]/[M|m]/[K|k] to represent giga/mega/kilo. For
 options, you can use [G|g]/[M|m]/[K|k] to represent giga/mega/kilo. For
-example, size=2K has the same meaning as size=2048. An example is given at
-the end of this document.
+example, size=2K has the same meaning as size=2048.
 
 
 read and write system calls are not supported on files that reside on hugetlb
 read and write system calls are not supported on files that reside on hugetlb
 file systems.
 file systems.

+ 69 - 27
fs/hugetlbfs/inode.c

@@ -13,15 +13,18 @@
 #include <linux/fs.h>
 #include <linux/fs.h>
 #include <linux/mount.h>
 #include <linux/mount.h>
 #include <linux/file.h>
 #include <linux/file.h>
+#include <linux/kernel.h>
 #include <linux/writeback.h>
 #include <linux/writeback.h>
 #include <linux/pagemap.h>
 #include <linux/pagemap.h>
 #include <linux/highmem.h>
 #include <linux/highmem.h>
 #include <linux/init.h>
 #include <linux/init.h>
 #include <linux/string.h>
 #include <linux/string.h>
 #include <linux/capability.h>
 #include <linux/capability.h>
+#include <linux/ctype.h>
 #include <linux/backing-dev.h>
 #include <linux/backing-dev.h>
 #include <linux/hugetlb.h>
 #include <linux/hugetlb.h>
 #include <linux/pagevec.h>
 #include <linux/pagevec.h>
+#include <linux/parser.h>
 #include <linux/mman.h>
 #include <linux/mman.h>
 #include <linux/quotaops.h>
 #include <linux/quotaops.h>
 #include <linux/slab.h>
 #include <linux/slab.h>
@@ -47,6 +50,21 @@ static struct backing_dev_info hugetlbfs_backing_dev_info = {
 
 
 int sysctl_hugetlb_shm_group;
 int sysctl_hugetlb_shm_group;
 
 
+enum {
+	Opt_size, Opt_nr_inodes,
+	Opt_mode, Opt_uid, Opt_gid,
+	Opt_err,
+};
+
+static match_table_t tokens = {
+	{Opt_size,	"size=%s"},
+	{Opt_nr_inodes,	"nr_inodes=%s"},
+	{Opt_mode,	"mode=%o"},
+	{Opt_uid,	"uid=%u"},
+	{Opt_gid,	"gid=%u"},
+	{Opt_err,	NULL},
+};
+
 static void huge_pagevec_release(struct pagevec *pvec)
 static void huge_pagevec_release(struct pagevec *pvec)
 {
 {
 	int i;
 	int i;
@@ -594,46 +612,70 @@ static const struct super_operations hugetlbfs_ops = {
 static int
 static int
 hugetlbfs_parse_options(char *options, struct hugetlbfs_config *pconfig)
 hugetlbfs_parse_options(char *options, struct hugetlbfs_config *pconfig)
 {
 {
-	char *opt, *value, *rest;
+	char *p, *rest;
+	substring_t args[MAX_OPT_ARGS];
+	int option;
 
 
 	if (!options)
 	if (!options)
 		return 0;
 		return 0;
-	while ((opt = strsep(&options, ",")) != NULL) {
-		if (!*opt)
-			continue;
 
 
-		value = strchr(opt, '=');
-		if (!value || !*value)
-			return -EINVAL;
-		else
-			*value++ = '\0';
-
-		if (!strcmp(opt, "uid"))
-			pconfig->uid = simple_strtoul(value, &value, 0);
-		else if (!strcmp(opt, "gid"))
-			pconfig->gid = simple_strtoul(value, &value, 0);
-		else if (!strcmp(opt, "mode"))
-			pconfig->mode = simple_strtoul(value,&value,0) & 0777U;
-		else if (!strcmp(opt, "size")) {
-			unsigned long long size = memparse(value, &rest);
+	while ((p = strsep(&options, ",")) != NULL) {
+		int token;
+
+		token = match_token(p, tokens, args);
+		switch (token) {
+		case Opt_uid:
+			if (match_int(&args[0], &option))
+ 				goto bad_val;
+			pconfig->uid = option;
+			break;
+
+		case Opt_gid:
+			if (match_int(&args[0], &option))
+ 				goto bad_val;
+			pconfig->gid = option;
+			break;
+
+		case Opt_mode:
+			if (match_octal(&args[0], &option))
+ 				goto bad_val;
+			pconfig->mode = option & 0777U;
+			break;
+
+		case Opt_size: {
+ 			unsigned long long size;
+			/* memparse() will accept a K/M/G without a digit */
+			if (!isdigit(*args[0].from))
+				goto bad_val;
+			size = memparse(args[0].from, &rest);
 			if (*rest == '%') {
 			if (*rest == '%') {
 				size <<= HPAGE_SHIFT;
 				size <<= HPAGE_SHIFT;
 				size *= max_huge_pages;
 				size *= max_huge_pages;
 				do_div(size, 100);
 				do_div(size, 100);
-				rest++;
 			}
 			}
 			pconfig->nr_blocks = (size >> HPAGE_SHIFT);
 			pconfig->nr_blocks = (size >> HPAGE_SHIFT);
-			value = rest;
-		} else if (!strcmp(opt,"nr_inodes")) {
-			pconfig->nr_inodes = memparse(value, &rest);
-			value = rest;
-		} else
-			return -EINVAL;
+			break;
+		}
 
 
-		if (*value)
-			return -EINVAL;
+		case Opt_nr_inodes:
+			/* memparse() will accept a K/M/G without a digit */
+			if (!isdigit(*args[0].from))
+				goto bad_val;
+			pconfig->nr_inodes = memparse(args[0].from, &rest);
+			break;
+
+		default:
+			printk(KERN_ERR "hugetlbfs: Bad mount option: %s\n", p);
+ 			return 1;
+			break;
+		}
 	}
 	}
 	return 0;
 	return 0;
+
+bad_val:
+ 	printk(KERN_ERR "hugetlbfs: Bad value '%s' for mount option '%s'\n",
+	       args[0].from, p);
+ 	return 1;
 }
 }
 
 
 static int
 static int