Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys Replace tmpfs_pool custom allocator code with a simpler ...



details:   https://anonhg.NetBSD.org/src/rev/f883be421a04
branches:  trunk
changeset: 755811:f883be421a04
user:      rmind <rmind%NetBSD.org@localhost>
date:      Tue Jun 22 18:32:07 2010 +0000

description:
Replace tmpfs_pool custom allocator code with a simpler layer for memory
accounting.  Use wired memory (which can be limited) for meta-data, and
kmem(9) for string allocations.

Close PR/31944.  Fix PR/38361 while here.  OK ad@.

diffstat:

 sys/fs/tmpfs/TODO                 |    5 -
 sys/fs/tmpfs/files.tmpfs          |    4 +-
 sys/fs/tmpfs/tmpfs.h              |   91 ++++-------
 sys/fs/tmpfs/tmpfs_mem.c          |  219 +++++++++++++++++++++++++++++
 sys/fs/tmpfs/tmpfs_pool.c         |  285 --------------------------------------
 sys/fs/tmpfs/tmpfs_pool.h         |  112 --------------
 sys/fs/tmpfs/tmpfs_subr.c         |  124 +++++-----------
 sys/fs/tmpfs/tmpfs_vfsops.c       |   69 +++-----
 sys/fs/tmpfs/tmpfs_vnops.c        |   35 ++--
 sys/modules/tmpfs/Makefile        |    4 +-
 sys/rump/fs/lib/libtmpfs/Makefile |    4 +-
 11 files changed, 339 insertions(+), 613 deletions(-)

diffs (truncated from 1299 to 300 lines):

diff -r 6e953268ade3 -r f883be421a04 sys/fs/tmpfs/TODO
--- a/sys/fs/tmpfs/TODO Tue Jun 22 18:30:20 2010 +0000
+++ b/sys/fs/tmpfs/TODO Tue Jun 22 18:32:07 2010 +0000
@@ -1,8 +1,3 @@
-- File meta-data is stored using memory pools.  These use, at the moment,
-  wired kernel memory, which is not acceptable because it is easy to turn
-  the system unstable by exhausting it.  Therefore, a pool allocator that
-  uses anonymous memory has to be written.
-
 - Verify that file holes work (they should, but must be checked).  Add a
   regression test for this feature.
 
diff -r 6e953268ade3 -r f883be421a04 sys/fs/tmpfs/files.tmpfs
--- a/sys/fs/tmpfs/files.tmpfs  Tue Jun 22 18:30:20 2010 +0000
+++ b/sys/fs/tmpfs/files.tmpfs  Tue Jun 22 18:32:07 2010 +0000
@@ -1,9 +1,9 @@
-#      $NetBSD: files.tmpfs,v 1.3 2010/03/02 16:43:48 pooka Exp $
+#      $NetBSD: files.tmpfs,v 1.4 2010/06/22 18:32:07 rmind Exp $
 
 deffs  TMPFS
 
 file   fs/tmpfs/tmpfs_fifoops.c        tmpfs
-file   fs/tmpfs/tmpfs_pool.c           tmpfs
+file   fs/tmpfs/tmpfs_mem.c            tmpfs
 file   fs/tmpfs/tmpfs_specops.c        tmpfs
 file   fs/tmpfs/tmpfs_subr.c           tmpfs
 file   fs/tmpfs/tmpfs_vfsops.c         tmpfs
diff -r 6e953268ade3 -r f883be421a04 sys/fs/tmpfs/tmpfs.h
--- a/sys/fs/tmpfs/tmpfs.h      Tue Jun 22 18:30:20 2010 +0000
+++ b/sys/fs/tmpfs/tmpfs.h      Tue Jun 22 18:32:07 2010 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: tmpfs.h,v 1.37 2008/07/29 09:10:09 pooka Exp $ */
+/*     $NetBSD: tmpfs.h,v 1.38 2010/06/22 18:32:07 rmind Exp $ */
 
 /*
  * Copyright (c) 2005, 2006, 2007 The NetBSD Foundation, Inc.
@@ -35,19 +35,10 @@
 
 #include <sys/dirent.h>
 #include <sys/mount.h>
+#include <sys/pool.h>
 #include <sys/queue.h>
 #include <sys/vnode.h>
 
-/* --------------------------------------------------------------------- */
-/* For the kernel and anyone who likes peeking into kernel memory        */
-/* --------------------------------------------------------------------- */
-
-#if defined(_KERNEL)
-#include <fs/tmpfs/tmpfs_pool.h>
-#endif /* defined(_KERNEL) */
-
-/* --------------------------------------------------------------------- */
-
 /*
  * Internal representation of a tmpfs directory entry.
  */
@@ -281,16 +272,10 @@
  * Internal representation of a tmpfs mount point.
  */
 struct tmpfs_mount {
-       /* Maximum number of memory pages available for use by the file
-        * system, set during mount time.  This variable must never be
-        * used directly as it may be bigger than the current amount of
-        * free memory; in the extreme case, it will hold the SIZE_MAX
-        * value.  Instead, use the TMPFS_PAGES_MAX macro. */
-       unsigned int            tm_pages_max;
-
-       /* Number of pages in use by the file system.  Cannot be bigger
-        * than the value returned by TMPFS_PAGES_MAX in any case. */
-       unsigned int            tm_pages_used;
+       /* Limit and number of bytes in use by the file system. */
+       uint64_t                tm_mem_limit;
+       uint64_t                tm_bytes_used;
+       kmutex_t                tm_acc_lock;
 
        /* Pointer to the node representing the root directory of this
         * file system. */
@@ -313,12 +298,10 @@
        kmutex_t                tm_lock;
        struct tmpfs_node_list  tm_nodes;
 
-       /* Pools used to store file system meta data.  These are not shared
-        * across several instances of tmpfs for the reasons described in
-        * tmpfs_pool.c. */
-       struct tmpfs_pool       tm_dirent_pool;
-       struct tmpfs_pool       tm_node_pool;
-       struct tmpfs_str_pool   tm_str_pool;
+       char                    tm_dwchan[32];
+       struct pool             tm_dirent_pool;
+       char                    tm_nwchan[32];
+       struct pool             tm_node_pool;
 };
 
 /* --------------------------------------------------------------------- */
@@ -361,7 +344,6 @@
 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(bool);
 int    tmpfs_chflags(struct vnode *, int, kauth_cred_t, struct lwp *);
 int    tmpfs_chmod(struct vnode *, mode_t, kauth_cred_t, struct lwp *);
 int    tmpfs_chown(struct vnode *, uid_t, gid_t, kauth_cred_t, struct lwp *);
@@ -376,6 +358,29 @@
            const struct timespec *, const struct timespec *, int);
 int    tmpfs_truncate(struct vnode *, off_t);
 
+/*
+ * Prototypes for tmpfs_mem.c.
+ */
+
+void           tmpfs_mntmem_init(struct tmpfs_mount *, uint64_t);
+void           tmpfs_mntmem_destroy(struct tmpfs_mount *);
+
+size_t         tmpfs_mem_info(bool);
+uint64_t       tmpfs_bytes_max(struct tmpfs_mount *);
+size_t         tmpfs_pages_avail(struct tmpfs_mount *);
+bool           tmpfs_mem_incr(struct tmpfs_mount *, size_t);
+void           tmpfs_mem_decr(struct tmpfs_mount *, size_t);
+
+struct tmpfs_dirent *tmpfs_dirent_get(struct tmpfs_mount *);
+void           tmpfs_dirent_put(struct tmpfs_mount *, struct tmpfs_dirent *);
+
+struct tmpfs_node *tmpfs_node_get(struct tmpfs_mount *);
+void           tmpfs_node_put(struct tmpfs_mount *, struct tmpfs_node *);
+
+char *         tmpfs_strname_alloc(struct tmpfs_mount *, size_t);
+void           tmpfs_strname_free(struct tmpfs_mount *, char *, size_t);
+bool           tmpfs_strname_neqlen(struct componentname *, struct componentname *);
+
 /* --------------------------------------------------------------------- */
 
 /*
@@ -418,36 +423,6 @@
  * 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). */
-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);
-}
-
-/* Returns the available space for the given file system. */
-#define TMPFS_PAGES_AVAIL(tmp)         \
-    ((ssize_t)(TMPFS_PAGES_MAX(tmp) - (tmp)->tm_pages_used))
-
-/* --------------------------------------------------------------------- */
-
 /*
  * Macros/functions to convert from generic data structures to tmpfs
  * specific ones.
diff -r 6e953268ade3 -r f883be421a04 sys/fs/tmpfs/tmpfs_mem.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/fs/tmpfs/tmpfs_mem.c  Tue Jun 22 18:32:07 2010 +0000
@@ -0,0 +1,219 @@
+/*     $NetBSD: tmpfs_mem.c,v 1.1 2010/06/22 18:32:07 rmind Exp $      */
+
+/*
+ * Copyright (c) 2010 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * tmpfs memory allocation routines.
+ * Implements memory usage accounting and limiting.
+ */
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: tmpfs_mem.c,v 1.1 2010/06/22 18:32:07 rmind Exp $");
+
+#include <sys/param.h>
+#include <sys/atomic.h>
+#include <sys/kmem.h>
+#include <sys/namei.h>
+#include <sys/pool.h>
+
+#include <fs/tmpfs/tmpfs.h>
+
+void
+tmpfs_mntmem_init(struct tmpfs_mount *mp, uint64_t memlimit)
+{
+
+       sprintf(mp->tm_dwchan, "tmpfs_dirent_%p", mp);
+       pool_init(&mp->tm_dirent_pool, sizeof(struct tmpfs_dirent), 0, 0, 0,
+           mp->tm_dwchan, &pool_allocator_nointr, IPL_NONE);
+
+       sprintf(mp->tm_nwchan, "tmpfs_node_%p", mp);
+       pool_init(&mp->tm_node_pool, sizeof(struct tmpfs_node), 0, 0, 0,
+           mp->tm_dwchan, &pool_allocator_nointr, IPL_NONE);
+
+       mutex_init(&mp->tm_acc_lock, MUTEX_DEFAULT, IPL_NONE);
+       mp->tm_mem_limit = memlimit;
+       mp->tm_bytes_used = 0;
+}
+
+void
+tmpfs_mntmem_destroy(struct tmpfs_mount *mp)
+{
+
+       KASSERT(mp->tm_bytes_used == 0);
+       mutex_destroy(&mp->tm_acc_lock);
+       pool_destroy(&mp->tm_dirent_pool);
+       pool_destroy(&mp->tm_node_pool);
+}
+
+/*
+ * tmpfs_mem_info: return the number of available memory pages.
+ *
+ * => If 'total' is true, then return _total_ amount of pages.
+ * => If false, then return the amount of _free_ memory pages.
+ *
+ * Remember to remove TMPFS_PAGES_RESERVED from the returned value to avoid
+ * excessive memory usage.
+ */
+size_t
+tmpfs_mem_info(bool total)
+{
+       size_t size = 0;
+
+       /* XXX: unlocked */
+       size += uvmexp.swpgavail;
+       if (!total) {
+               size -= uvmexp.swpgonly;
+       }
+       size += uvmexp.free;
+       size += uvmexp.filepages;
+       if (size > uvmexp.wired) {
+               size -= uvmexp.wired;
+       } else {
+               size = 0;
+       }
+       return size;
+}
+
+uint64_t
+tmpfs_bytes_max(struct tmpfs_mount *mp)
+{
+       size_t freepages = tmpfs_mem_info(false);
+       uint64_t avail_mem;
+
+       if (freepages < TMPFS_PAGES_RESERVED) {
+               freepages = 0;
+       } else {
+               freepages -= TMPFS_PAGES_RESERVED;
+       }
+       avail_mem = round_page(mp->tm_bytes_used) + (freepages << PAGE_SHIFT);
+       return min(mp->tm_mem_limit, avail_mem);
+}
+
+size_t
+tmpfs_pages_avail(struct tmpfs_mount *mp)
+{
+
+       return (tmpfs_bytes_max(mp) - mp->tm_bytes_used) >> PAGE_SHIFT;
+}
+
+bool
+tmpfs_mem_incr(struct tmpfs_mount *mp, size_t sz)
+{
+       const uint64_t lim = tmpfs_bytes_max(mp);



Home | Main Index | Thread Index | Old Index