Subject: Re: /dev on tmpfs problem
To: None <dyoung@pobox.com>
From: YAMAMOTO Takashi <yamt@mwd.biglobe.ne.jp>
List: tech-kern
Date: 11/13/2005 06:09:29
--NextPart-20051113060254-0980000
Content-Type: Text/Plain; charset=us-ascii

> > IMO removing tmpfs auto-sizing feature is a way to go.
> > ie. mandate -s option of mount_tmpfs and trust it.
> 
> Can you provide some implementation advice for "trusting" a mandatory
> -s option?  I need to fix the ENOSPC bug or switch back to mfs (ugh!),
> because the bug makes tmpfs capacity unpredictable.

like the attached patch.  (not tested at all.)

btw, switching back to mfs (and fix its own problems) is not
a very bad bet, i guess. :-)

YAMAMOTO Takashi

--NextPart-20051113060254-0980000
Content-Type: Text/Plain; charset=us-ascii
Content-Disposition: attachment; filename="a.diff"

Index: fs/tmpfs/tmpfs.h
===================================================================
--- fs/tmpfs/tmpfs.h	(revision 1419)
+++ fs/tmpfs/tmpfs.h	(working copy)
@@ -323,7 +323,6 @@ int	tmpfs_dir_getdotdotdent(struct tmpfs
 struct tmpfs_dirent *	tmpfs_dir_lookupbycookie(struct tmpfs_node *, off_t);
 int	tmpfs_dir_getdents(struct tmpfs_node *, struct uio *, off_t *);
 int	tmpfs_reg_resize(struct vnode *, off_t);
-size_t	tmpfs_mem_info(boolean_t);
 int	tmpfs_chflags(struct vnode *, int, struct ucred *, struct proc *);
 int	tmpfs_chmod(struct vnode *, mode_t, struct ucred *, struct proc *);
 int	tmpfs_chown(struct vnode *, uid_t, gid_t, struct ucred *,
@@ -374,33 +373,12 @@ int	tmpfs_truncate(struct vnode *, off_t
  * Memory management stuff.
  */
 
-/* Amount of memory pages to reserve for the system (e.g., to not use by
- * tmpfs).
- * XXX: Should this be tunable through sysctl, for instance? */
-#define TMPFS_PAGES_RESERVED (4 * 1024 * 1024 / PAGE_SIZE)
-
-/* Returns the maximum size allowed for a tmpfs file system.  This macro
- * must be used instead of directly retrieving the value from tm_pages_max.
- * The reason is that the size of a tmpfs file system is dynamic: it lets
- * the user store files as long as there is enough free memory (including
- * physical memory and swap space).  Therefore, the amount of memory to be
- * used is either the limit imposed by the user during mount time or the
- * amount of available memory, whichever is lower.  To avoid consuming all
- * the memory for a given mount point, the system will always reserve a
- * minimum of TMPFS_PAGES_RESERVED pages, which is also taken into account
- * by this macro (see above). */
+/* Returns the maximum size allowed for a tmpfs file system. */
 static inline size_t
 TMPFS_PAGES_MAX(struct tmpfs_mount *tmp)
 {
-	size_t freepages;
 
-	freepages = tmpfs_mem_info(FALSE);
-	if (freepages < TMPFS_PAGES_RESERVED)
-		freepages = 0;
-	else
-		freepages -= TMPFS_PAGES_RESERVED;
-
-	return MIN(tmp->tm_pages_max, freepages + tmp->tm_pages_used);
+	return tmp->tm_pages_max;
 }
 
 /* Returns the available space for the given file system. */
Index: fs/tmpfs/tmpfs_subr.c
===================================================================
--- fs/tmpfs/tmpfs_subr.c	(revision 1434)
+++ fs/tmpfs/tmpfs_subr.c	(working copy)
@@ -909,57 +909,6 @@ out:
 /* --------------------------------------------------------------------- */
 
 /*
- * Returns information about the number of available memory pages,
- * including physical and virtual ones.
- *
- * If 'total' is TRUE, the value returned is the total amount of memory 
- * pages configured for the system (either in use or free).
- * If it is FALSE, the value returned is the amount of free memory pages.
- *
- * Remember to remove TMPFS_PAGES_RESERVED from the returned value to avoid
- * excessive memory usage.
- *
- * XXX: This function is used every time TMPFS_PAGES_MAX is called to gather
- * the amount of free memory, something that happens during _each_
- * object allocation.  The time it takes to run this function so many
- * times is not negligible, so this value should be stored as an
- * aggregate somewhere, possibly within UVM (we cannot do it ourselves
- * because we can't get notifications on memory usage changes).
- */
-size_t
-tmpfs_mem_info(boolean_t total)
-{
-	int i, sec;
-	register_t retval;
-	size_t size;
-	struct swapent *sep;
-
-	sec = uvmexp.nswapdev;
-	sep = (struct swapent *)malloc(sizeof(struct swapent) * sec, M_TEMP,
-	    M_WAITOK);
-	KASSERT(sep != NULL);
-	uvm_swap_stats(SWAP_STATS, sep, sec, &retval);
-	KASSERT(retval == sec);
-
-	size = 0;
-	if (total) {
-		for (i = 0; i < sec; i++)
-			size += dbtob(sep[i].se_nblks) / PAGE_SIZE;
-	} else {
-		for (i = 0; i < sec; i++)
-			size += dbtob(sep[i].se_nblks - sep[i].se_inuse) /
-			    PAGE_SIZE;
-	}
-	size += uvmexp.free;
-
-	free(sep, M_TEMP);
-
-	return size;
-}
-
-/* --------------------------------------------------------------------- */
-
-/*
  * Change flags of the given vnode.
  * Caller should execute tmpfs_update on vp after a successful execution.
  * The vnode must be locked on entry and remain locked on exit.
Index: fs/tmpfs/tmpfs_vfsops.c
===================================================================
--- fs/tmpfs/tmpfs_vfsops.c	(revision 1407)
+++ fs/tmpfs/tmpfs_vfsops.c	(working copy)
@@ -132,20 +132,12 @@ tmpfs_mount(struct mount *mp, const char
 	if (args.ta_version != TMPFS_ARGS_VERSION)
 		return EINVAL;
 
-	/* Do not allow mounts if we do not have enough memory to preserve
-	 * the minimum reserved pages. */
-	if (tmpfs_mem_info(TRUE) < TMPFS_PAGES_RESERVED)
-		return EINVAL;
-
 	/* Get the maximum number of memory pages this file system is
 	 * 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. */
+	 * the mount structure. */
 	if (args.ta_size_max < PAGE_SIZE || args.ta_size_max >= SIZE_MAX)
-		pages = SIZE_MAX;
-	else
-		pages = args.ta_size_max / PAGE_SIZE +
-		    (args.ta_size_max % PAGE_SIZE == 0 ? 0 : 1);
+		return EINVAL;
+	pages = howmany(args.ta_size_max, PAGE_SIZE);
 	KASSERT(pages > 0);
 
 	if (args.ta_nodes_max <= 3)

--NextPart-20051113060254-0980000--