Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/fs/tmpfs tmpfs: replace the broken tmpfs_dircookie() log...
details: https://anonhg.NetBSD.org/src/rev/4ba0b2db68f0
branches: trunk
changeset: 791206:4ba0b2db68f0
user: rmind <rmind%NetBSD.org@localhost>
date: Fri Nov 08 15:44:23 2013 +0000
description:
tmpfs: replace the broken tmpfs_dircookie() logic which uses the node
address truncated to 31 bits (required for 32-bit readdir compatibility,
e.g. linux32). Instead, assign 2^31 range using the following logic:
- The first half of the 2^31 is assigned incrementally (the fast path).
- When exceeded, use the second half of 2^31, but manage with vmem(9).
It will require 2 billion files per-directory to trigger vmem(9) usage.
Also, while here, add some fixes for tmpfs_unmount().
Should fix PR/47739, PR/47480, PR/46088 and PR/41068.
Thanks to wiz@ for stress testing.
diffstat:
sys/fs/tmpfs/tmpfs.h | 88 +++-----
sys/fs/tmpfs/tmpfs_rename.c | 18 +-
sys/fs/tmpfs/tmpfs_subr.c | 409 ++++++++++++++++++++++++-------------------
sys/fs/tmpfs/tmpfs_vfsops.c | 45 ++--
sys/fs/tmpfs/tmpfs_vnops.c | 79 +++-----
5 files changed, 335 insertions(+), 304 deletions(-)
diffs (truncated from 1071 to 300 lines):
diff -r fdee5335d79e -r 4ba0b2db68f0 sys/fs/tmpfs/tmpfs.h
--- a/sys/fs/tmpfs/tmpfs.h Fri Nov 08 13:17:45 2013 +0000
+++ b/sys/fs/tmpfs/tmpfs.h Fri Nov 08 15:44:23 2013 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: tmpfs.h,v 1.45 2011/09/27 01:10:43 christos Exp $ */
+/* $NetBSD: tmpfs.h,v 1.46 2013/11/08 15:44:23 rmind Exp $ */
/*
* Copyright (c) 2005, 2006, 2007 The NetBSD Foundation, Inc.
@@ -54,6 +54,9 @@
/* Pointer to the inode this entry refers to. */
struct tmpfs_node * td_node;
+ /* Sequence number, see tmpfs_dir_getseq(). */
+ uint32_t td_seq;
+
/* Name and its length. */
char * td_name;
uint16_t td_namelen;
@@ -61,47 +64,10 @@
TAILQ_HEAD(tmpfs_dir, tmpfs_dirent);
-#if defined(_KERNEL)
-
-#define TMPFS_MAXNAMLEN 255
-/* Validate maximum td_namelen length. */
-CTASSERT(TMPFS_MAXNAMLEN < UINT16_MAX);
-
-#define TMPFS_DIRCOOKIE_DOT 0
-#define TMPFS_DIRCOOKIE_DOTDOT 1
-#define TMPFS_DIRCOOKIE_EOF 2
-
-/*
- * Each entry in a directory has a cookie that identifies it. Cookies
- * supersede offsets within directories, as tmpfs has no offsets as such.
- *
- * The '.', '..' and the end of directory markers have fixed cookies,
- * which cannot collide with the cookies generated by other entries.
- *
- * The cookies for the other entries are generated based on the memory
- * address of their representative meta-data structure.
- *
- * XXX: Truncating directory cookies to 31 bits now - workaround for
- * problem with Linux compat, see PR/32034.
- */
-static inline off_t
-tmpfs_dircookie(tmpfs_dirent_t *de)
-{
- off_t cookie;
-
- cookie = ((off_t)(uintptr_t)de >> 1) & 0x7FFFFFFF;
- KASSERT(cookie != TMPFS_DIRCOOKIE_DOT);
- KASSERT(cookie != TMPFS_DIRCOOKIE_DOTDOT);
- KASSERT(cookie != TMPFS_DIRCOOKIE_EOF);
-
- return cookie;
-}
-#endif
-
/*
* Internal representation of a tmpfs file system node -- inode.
*
- * This structure is splitted in two parts: one holds attributes common
+ * This structure is split in two parts: one holds attributes common
* to all file types and the other holds data that is only applicable to
* a particular type.
*
@@ -169,11 +135,14 @@
/* List of directory entries. */
struct tmpfs_dir tn_dir;
+ /* Last given sequence number and their arena. */
+ uint32_t tn_next_seq;
+ void * tn_seq_arena;
+
/*
- * Number and pointer of the last directory entry
- * returned by the readdir(3) operation.
+ * Pointer of the last directory entry returned
+ * by the readdir(3) operation.
*/
- off_t tn_readdir_lastn;
struct tmpfs_dirent * tn_readdir_lastp;
} tn_dir;
@@ -196,6 +165,24 @@
LIST_HEAD(tmpfs_node_list, tmpfs_node);
+#define TMPFS_MAXNAMLEN 255
+/* Validate maximum td_namelen length. */
+CTASSERT(TMPFS_MAXNAMLEN < UINT16_MAX);
+
+/*
+ * Reserved values for the virtual entries (the first must be 0) and EOF.
+ * The start/end of the incremental range, see tmpfs_dir_getseq().
+ */
+#define TMPFS_DIRSEQ_DOT 0
+#define TMPFS_DIRSEQ_DOTDOT 1
+#define TMPFS_DIRSEQ_EOF 2
+
+#define TMPFS_DIRSEQ_START 3 /* inclusive */
+#define TMPFS_DIRSEQ_END (1U << 30) /* exclusive */
+
+/* Mark to indicate that the number is not set. */
+#define TMPFS_DIRSEQ_NONE (1U << 31)
+
/* Status flags. */
#define TMPFS_NODE_ACCESSED 0x01
#define TMPFS_NODE_MODIFIED 0x02
@@ -270,15 +257,14 @@
int tmpfs_alloc_dirent(tmpfs_mount_t *, const char *, uint16_t,
tmpfs_dirent_t **);
void tmpfs_free_dirent(tmpfs_mount_t *, tmpfs_dirent_t *);
-void tmpfs_dir_attach(vnode_t *, tmpfs_dirent_t *, tmpfs_node_t *);
-void tmpfs_dir_detach(vnode_t *, tmpfs_dirent_t *);
+void tmpfs_dir_attach(tmpfs_node_t *, tmpfs_dirent_t *, tmpfs_node_t *);
+void tmpfs_dir_detach(tmpfs_node_t *, tmpfs_dirent_t *);
tmpfs_dirent_t *tmpfs_dir_lookup(tmpfs_node_t *, struct componentname *);
tmpfs_dirent_t *tmpfs_dir_cached(tmpfs_node_t *);
-int tmpfs_dir_getdotdent(tmpfs_node_t *, struct uio *);
-int tmpfs_dir_getdotdotdent(tmpfs_node_t *, struct uio *);
-tmpfs_dirent_t *tmpfs_dir_lookupbycookie(tmpfs_node_t *, off_t);
+uint32_t tmpfs_dir_getseq(tmpfs_node_t *, tmpfs_dirent_t *);
+tmpfs_dirent_t *tmpfs_dir_lookupbyseq(tmpfs_node_t *, off_t);
int tmpfs_dir_getdents(tmpfs_node_t *, struct uio *, off_t *);
int tmpfs_reg_resize(vnode_t *, off_t);
@@ -321,12 +307,10 @@
* Ensures that the node pointed by 'node' is a directory and that its
* contents are consistent with respect to directories.
*/
-#define TMPFS_VALIDATE_DIR(node) \
+#define TMPFS_VALIDATE_DIR(node) \
+ KASSERT((node)->tn_vnode == NULL || VOP_ISLOCKED((node)->tn_vnode)); \
KASSERT((node)->tn_type == VDIR); \
- KASSERT((node)->tn_size % sizeof(tmpfs_dirent_t) == 0); \
- KASSERT((node)->tn_spec.tn_dir.tn_readdir_lastp == NULL || \
- tmpfs_dircookie((node)->tn_spec.tn_dir.tn_readdir_lastp) == \
- (node)->tn_spec.tn_dir.tn_readdir_lastn);
+ KASSERT((node)->tn_size % sizeof(tmpfs_dirent_t) == 0);
/*
* Memory management stuff.
diff -r fdee5335d79e -r 4ba0b2db68f0 sys/fs/tmpfs/tmpfs_rename.c
--- a/sys/fs/tmpfs/tmpfs_rename.c Fri Nov 08 13:17:45 2013 +0000
+++ b/sys/fs/tmpfs/tmpfs_rename.c Fri Nov 08 15:44:23 2013 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: tmpfs_rename.c,v 1.4 2012/09/27 17:40:51 riastradh Exp $ */
+/* $NetBSD: tmpfs_rename.c,v 1.5 2013/11/08 15:44:23 rmind Exp $ */
/*-
* Copyright (c) 2012 The NetBSD Foundation, Inc.
@@ -34,7 +34,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: tmpfs_rename.c,v 1.4 2012/09/27 17:40:51 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: tmpfs_rename.c,v 1.5 2013/11/08 15:44:23 rmind Exp $");
#include <sys/param.h>
#include <sys/errno.h>
@@ -313,8 +313,11 @@
* source entry and reattach it to the target directory.
*/
if (fdvp != tdvp) {
- tmpfs_dir_detach(fdvp, *fdep);
- tmpfs_dir_attach(tdvp, *fdep, VP_TO_TMPFS_NODE(fvp));
+ tmpfs_node_t *fdnode = VP_TO_TMPFS_DIR(fdvp);
+ tmpfs_node_t *tdnode = VP_TO_TMPFS_DIR(tdvp);
+
+ tmpfs_dir_detach(fdnode, *fdep);
+ tmpfs_dir_attach(tdnode, *fdep, VP_TO_TMPFS_NODE(fvp));
} else if (tvp == NULL) {
/*
* We are changing the directory. tmpfs_dir_attach and
@@ -331,6 +334,8 @@
* XXX What if the target is a directory with whiteout entries?
*/
if (tvp != NULL) {
+ tmpfs_node_t *tdnode = VP_TO_TMPFS_DIR(tdvp);
+
KASSERT((*tdep) != NULL);
KASSERT((*tdep)->td_node == VP_TO_TMPFS_NODE(tvp));
KASSERT((fvp->v_type == VDIR) == (tvp->v_type == VDIR));
@@ -349,7 +354,7 @@
*/
VP_TO_TMPFS_NODE(tvp)->tn_links--;
}
- tmpfs_dir_detach(tdvp, *tdep);
+ tmpfs_dir_detach(tdnode, *tdep);
tmpfs_free_dirent(VFS_TO_TMPFS(mp), *tdep);
}
@@ -388,6 +393,7 @@
tmpfs_gro_remove(struct mount *mp, kauth_cred_t cred,
struct vnode *dvp, struct componentname *cnp, void *de, struct vnode *vp)
{
+ tmpfs_node_t *dnode = VP_TO_TMPFS_DIR(dvp);
struct tmpfs_dirent **dep = de;
(void)vp;
@@ -404,7 +410,7 @@
KASSERT(VOP_ISLOCKED(dvp) == LK_EXCLUSIVE);
KASSERT(VOP_ISLOCKED(vp) == LK_EXCLUSIVE);
- tmpfs_dir_detach(dvp, *dep);
+ tmpfs_dir_detach(dnode, *dep);
tmpfs_free_dirent(VFS_TO_TMPFS(mp), *dep);
return 0;
diff -r fdee5335d79e -r 4ba0b2db68f0 sys/fs/tmpfs/tmpfs_subr.c
--- a/sys/fs/tmpfs/tmpfs_subr.c Fri Nov 08 13:17:45 2013 +0000
+++ b/sys/fs/tmpfs/tmpfs_subr.c Fri Nov 08 15:44:23 2013 +0000
@@ -1,7 +1,7 @@
-/* $NetBSD: tmpfs_subr.c,v 1.82 2013/11/01 15:38:45 rmind Exp $ */
+/* $NetBSD: tmpfs_subr.c,v 1.83 2013/11/08 15:44:23 rmind Exp $ */
/*
- * Copyright (c) 2005-2011 The NetBSD Foundation, Inc.
+ * Copyright (c) 2005-2013 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
@@ -74,7 +74,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: tmpfs_subr.c,v 1.82 2013/11/01 15:38:45 rmind Exp $");
+__KERNEL_RCSID(0, "$NetBSD: tmpfs_subr.c,v 1.83 2013/11/08 15:44:23 rmind Exp $");
#include <sys/param.h>
#include <sys/dirent.h>
@@ -98,6 +98,8 @@
#include <fs/tmpfs/tmpfs_specops.h>
#include <fs/tmpfs/tmpfs_vnops.h>
+static void tmpfs_dir_putseq(tmpfs_node_t *, tmpfs_dirent_t *);
+
/*
* tmpfs_alloc_node: allocate a new inode of a specified type and
* insert it into the list of specified mount point.
@@ -155,7 +157,8 @@
/* Directory. */
TAILQ_INIT(&nnode->tn_spec.tn_dir.tn_dir);
nnode->tn_spec.tn_dir.tn_parent = NULL;
- nnode->tn_spec.tn_dir.tn_readdir_lastn = 0;
+ nnode->tn_spec.tn_dir.tn_seq_arena = NULL;
+ nnode->tn_spec.tn_dir.tn_next_seq = TMPFS_DIRSEQ_START;
nnode->tn_spec.tn_dir.tn_readdir_lastp = NULL;
/* Extra link count for the virtual '.' entry. */
@@ -240,11 +243,10 @@
}
break;
case VDIR:
- /*
- * KASSERT(TAILQ_EMPTY(&node->tn_spec.tn_dir.tn_dir));
- * KASSERT(node->tn_spec.tn_dir.tn_parent == NULL ||
- * node == tmp->tm_root);
- */
+ KASSERT(node->tn_spec.tn_dir.tn_seq_arena == NULL);
+ KASSERT(TAILQ_EMPTY(&node->tn_spec.tn_dir.tn_dir));
+ KASSERT(node->tn_spec.tn_dir.tn_parent == NULL ||
+ node == tmp->tm_root);
break;
default:
break;
@@ -390,12 +392,12 @@
if (cnp->cn_flags & ISWHITEOUT) {
wde = tmpfs_dir_lookup(dnode, cnp);
KASSERT(wde != NULL && wde->td_node == TMPFS_NODE_WHITEOUT);
- tmpfs_dir_detach(dvp, wde);
+ tmpfs_dir_detach(dnode, wde);
tmpfs_free_dirent(tmp, wde);
}
/* Associate inode and attach the entry into the directory. */
- tmpfs_dir_attach(dvp, de, node);
+ tmpfs_dir_attach(dnode, de, node);
/* Make node opaque if requested. */
if (cnp->cn_flags & ISWHITEOUT)
@@ -426,6 +428,7 @@
}
nde->td_namelen = len;
memcpy(nde->td_name, name, len);
+ nde->td_seq = TMPFS_DIRSEQ_NONE;
*de = nde;
return 0;
@@ -437,8 +440,8 @@
void
tmpfs_free_dirent(tmpfs_mount_t *tmp, tmpfs_dirent_t *de)
{
-
- /* KASSERT(de->td_node == NULL); */
Home |
Main Index |
Thread Index |
Old Index