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--