Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 7 Apr 2012 15:27:34 +0000 (UTC)
From:      Gleb Kurtsou <gleb@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r233999 - in head/sys: fs/tmpfs kern sys
Message-ID:  <201204071527.q37FRYJ9067798@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: gleb
Date: Sat Apr  7 15:27:34 2012
New Revision: 233999
URL: http://svn.freebsd.org/changeset/base/233999

Log:
  Add vfs_getopt_size. Support human readable file system options in tmpfs.
  
  Increase maximum tmpfs file system size to 4GB*PAGE_SIZE on 32 bit archs.
  
  Discussed with:	delphij
  MFC after:	2 weeks

Modified:
  head/sys/fs/tmpfs/tmpfs_vfsops.c
  head/sys/kern/vfs_mount.c
  head/sys/sys/mount.h

Modified: head/sys/fs/tmpfs/tmpfs_vfsops.c
==============================================================================
--- head/sys/fs/tmpfs/tmpfs_vfsops.c	Sat Apr  7 15:23:51 2012	(r233998)
+++ head/sys/fs/tmpfs/tmpfs_vfsops.c	Sat Apr  7 15:27:34 2012	(r233999)
@@ -132,12 +132,10 @@ tmpfs_mount(struct mount *mp)
 {
 	struct tmpfs_mount *tmp;
 	struct tmpfs_node *root;
-	size_t pages;
-	uint32_t nodes;
 	int error;
 	/* Size counters. */
-	u_int nodes_max;
-	u_quad_t size_max, maxfilesize;
+	u_quad_t pages;
+	off_t nodes_max, size_max, maxfilesize;
 
 	/* Root node attributes. */
 	uid_t root_uid;
@@ -173,12 +171,11 @@ tmpfs_mount(struct mount *mp)
 	if (mp->mnt_cred->cr_ruid != 0 ||
 	    vfs_scanopt(mp->mnt_optnew, "mode", "%ho", &root_mode) != 1)
 		root_mode = va.va_mode;
-	if (vfs_scanopt(mp->mnt_optnew, "inodes", "%u", &nodes_max) != 1)
+	if (vfs_getopt_size(mp->mnt_optnew, "inodes", &nodes_max) != 0)
 		nodes_max = 0;
-	if (vfs_scanopt(mp->mnt_optnew, "size", "%qu", &size_max) != 1)
+	if (vfs_getopt_size(mp->mnt_optnew, "size", &size_max) != 0)
 		size_max = 0;
-	if (vfs_scanopt(mp->mnt_optnew, "maxfilesize", "%qu",
-	    &maxfilesize) != 1)
+	if (vfs_getopt_size(mp->mnt_optnew, "maxfilesize", &maxfilesize) != 0)
 		maxfilesize = 0;
 
 	/* Do not allow mounts if we do not have enough memory to preserve
@@ -190,7 +187,8 @@ tmpfs_mount(struct mount *mp)
 	 * allowed to use, based on the maximum size the user passed in
 	 * the mount structure.  A value of zero is treated as if the
 	 * maximum available space was requested. */
-	if (size_max < PAGE_SIZE || size_max > SIZE_MAX - PAGE_SIZE)
+	if (size_max < PAGE_SIZE || size_max > OFF_MAX - PAGE_SIZE ||
+	    (SIZE_MAX < OFF_MAX && size_max / PAGE_SIZE >= SIZE_MAX))
 		pages = SIZE_MAX;
 	else
 		pages = howmany(size_max, PAGE_SIZE);
@@ -198,21 +196,20 @@ tmpfs_mount(struct mount *mp)
 
 	if (nodes_max <= 3) {
 		if (pages > UINT32_MAX - 3)
-			nodes = UINT32_MAX;
+			nodes_max = UINT32_MAX;
 		else
-			nodes = pages + 3;
-	} else
-		nodes = nodes_max;
-	MPASS(nodes >= 3);
+			nodes_max = pages + 3;
+	}
+	MPASS(nodes_max >= 3);
 
 	/* Allocate the tmpfs mount structure and fill it. */
 	tmp = (struct tmpfs_mount *)malloc(sizeof(struct tmpfs_mount),
 	    M_TMPFSMNT, M_WAITOK | M_ZERO);
 
 	mtx_init(&tmp->allnode_lock, "tmpfs allnode lock", NULL, MTX_DEF);
-	tmp->tm_nodes_max = nodes;
+	tmp->tm_nodes_max = nodes_max;
 	tmp->tm_nodes_inuse = 0;
-	tmp->tm_maxfilesize = maxfilesize > 0 ? maxfilesize : UINT64_MAX;
+	tmp->tm_maxfilesize = maxfilesize > 0 ? maxfilesize : OFF_MAX;
 	LIST_INIT(&tmp->tm_nodes_used);
 
 	tmp->tm_pages_max = pages;

Modified: head/sys/kern/vfs_mount.c
==============================================================================
--- head/sys/kern/vfs_mount.c	Sat Apr  7 15:23:51 2012	(r233998)
+++ head/sys/kern/vfs_mount.c	Sat Apr  7 15:27:34 2012	(r233999)
@@ -1520,6 +1520,48 @@ vfs_getopt_pos(struct vfsoptlist *opts, 
 	return (-1);
 }
 
+int
+vfs_getopt_size(struct vfsoptlist *opts, const char *name, off_t *value)
+{
+	char *opt_value, *vtp;
+	quad_t iv;
+	int error, opt_len;
+
+	error = vfs_getopt(opts, name, (void **)&opt_value, &opt_len);
+	if (error != 0)
+		return (error);
+	if (opt_len == 0 || opt_value == NULL)
+		return (EINVAL);
+	if (opt_value[0] == '\0' || opt_value[opt_len - 1] != '\0')
+		return (EINVAL);
+	iv = strtoq(opt_value, &vtp, 0);
+	if (vtp == opt_value || (vtp[0] != '\0' && vtp[1] != '\0'))
+		return (EINVAL);
+	if (iv < 0)
+		return (EINVAL);
+	switch (vtp[0]) {
+	case 't':
+	case 'T':
+		iv *= 1024;
+	case 'g':
+	case 'G':
+		iv *= 1024;
+	case 'm':
+	case 'M':
+		iv *= 1024;
+	case 'k':
+	case 'K':
+		iv *= 1024;
+	case '\0':
+		break;
+	default:
+		return (EINVAL);
+	}
+	*value = iv;
+
+	return (0);
+}
+
 char *
 vfs_getopts(struct vfsoptlist *opts, const char *name, int *error)
 {

Modified: head/sys/sys/mount.h
==============================================================================
--- head/sys/sys/mount.h	Sat Apr  7 15:23:51 2012	(r233998)
+++ head/sys/sys/mount.h	Sat Apr  7 15:27:34 2012	(r233999)
@@ -718,6 +718,8 @@ int	vfs_flagopt(struct vfsoptlist *opts,
 	    uint64_t val);
 int	vfs_getopt(struct vfsoptlist *, const char *, void **, int *);
 int	vfs_getopt_pos(struct vfsoptlist *opts, const char *name);
+int	vfs_getopt_size(struct vfsoptlist *opts, const char *name,
+	    off_t *value);
 char	*vfs_getopts(struct vfsoptlist *, const char *, int *error);
 int	vfs_copyopt(struct vfsoptlist *, const char *, void *, int);
 int	vfs_filteropt(struct vfsoptlist *, const char **legal);



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201204071527.q37FRYJ9067798>