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