From d4623db37d5f02efd8bc2253c289e7d6a1f77e7d Mon Sep 17 00:00:00 2001 From: Matthew Dillon Date: Sat, 20 Feb 2010 15:03:41 -0800 Subject: [PATCH] kernel - TMPFS - Features, don't sync on umount, enforce snocache on root * The umount code was syncing the contents of tmpfs to swap. Fix it so it doesn't. * Set the snocache flag on the tmpfs root node and silently enforce it on any chflags operation. This prevents swapcache from trying to pageout file data from tmpfs (which is already backed by swap). --- sys/vfs/tmpfs/tmpfs.h | 2 -- sys/vfs/tmpfs/tmpfs_subr.c | 5 +++++ sys/vfs/tmpfs/tmpfs_vfsops.c | 31 +++++++++++++++++++++++++------ sys/vfs/tmpfs/tmpfs_vnops.c | 4 +--- 4 files changed, 31 insertions(+), 11 deletions(-) diff --git a/sys/vfs/tmpfs/tmpfs.h b/sys/vfs/tmpfs/tmpfs.h index 38aab4a0a5..343e931d83 100644 --- a/sys/vfs/tmpfs/tmpfs.h +++ b/sys/vfs/tmpfs/tmpfs.h @@ -397,8 +397,6 @@ struct tmpfs_mount { #define TMPFS_LOCK(tm) lockmgr(&(tm)->allnode_lock, LK_EXCLUSIVE|LK_RETRY) #define TMPFS_UNLOCK(tm) lockmgr(&(tm)->allnode_lock, LK_RELEASE) -#define TMPFS_FLAG_UNMOUNTING 0x0001 - /* --------------------------------------------------------------------- */ /* diff --git a/sys/vfs/tmpfs/tmpfs_subr.c b/sys/vfs/tmpfs/tmpfs_subr.c index 9c928a6d5c..4aabbf3f74 100644 --- a/sys/vfs/tmpfs/tmpfs_subr.c +++ b/sys/vfs/tmpfs/tmpfs_subr.c @@ -1041,6 +1041,9 @@ tmpfs_chflags(struct vnode *vp, int flags, struct ucred *cred) /* * Unprivileged processes are not permitted to unset system * flags, or modify flags if any system flags are set. + * + * Silently enforce SF_NOCACHE on the root tmpfs vnode so + * tmpfs data is not double-cached by swapcache. */ TMPFS_NODE_LOCK(node); if (!priv_check_cred(cred, PRIV_VFS_SYSFLAGS, 0)) { @@ -1058,6 +1061,8 @@ tmpfs_chflags(struct vnode *vp, int flags, struct ucred *cred) (node->tn_flags & SF_SNAPSHOT) != 0)) return (EPERM); #endif + if (vp->v_flag & VROOT) + flags |= SF_NOCACHE; node->tn_flags = flags; } else { if (node->tn_flags diff --git a/sys/vfs/tmpfs/tmpfs_vfsops.c b/sys/vfs/tmpfs/tmpfs_vfsops.c index b63c34985f..5fd5d38357 100644 --- a/sys/vfs/tmpfs/tmpfs_vfsops.c +++ b/sys/vfs/tmpfs/tmpfs_vfsops.c @@ -227,9 +227,15 @@ tmpfs_mount(struct mount *mp, char *path, caddr_t data, struct ucred *cred) &tmpfs_node_pool_malloc_args); /* Allocate the root node. */ - error = tmpfs_alloc_node(tmp, VDIR, root_uid, - root_gid, root_mode & ALLPERMS, NULL, NULL, - VNOVAL, VNOVAL, &root); + error = tmpfs_alloc_node(tmp, VDIR, root_uid, root_gid, + root_mode & ALLPERMS, NULL, NULL, + VNOVAL, VNOVAL, &root); + + /* + * We are backed by swap, set snocache chflags flag so we + * don't trip over swapcache. + */ + root->tn_flags = SF_NOCACHE; if (error != 0 || root == NULL) { objcache_destroy(tmp->tm_node_pool); @@ -281,11 +287,24 @@ tmpfs_unmount(struct mount *mp, int mntflags) if (mntflags & MNT_FORCE) flags |= FORCECLOSE; - /* Tell vflush->vinvalbuf->fsync to throw away data */ tmp = VFS_TO_TMPFS(mp); - tmp->tm_flags |= TMPFS_FLAG_UNMOUNTING; - /* Finalize all pending I/O. */ + /* + * Finalize all pending I/O. In the case of tmpfs we want + * to throw all the data away so clean out the buffer cache + * and vm objects before calling vflush(). + */ + LIST_FOREACH(node, &tmp->tm_nodes_used, tn_entries) { + if (node->tn_type == VREG && node->tn_vnode) { + ++node->tn_links; + TMPFS_NODE_LOCK(node); + vx_get(node->tn_vnode); + tmpfs_truncate(node->tn_vnode, 0); + vx_put(node->tn_vnode); + TMPFS_NODE_UNLOCK(node); + --node->tn_links; + } + } error = vflush(mp, 0, flags); if (error != 0) return error; diff --git a/sys/vfs/tmpfs/tmpfs_vnops.c b/sys/vfs/tmpfs/tmpfs_vnops.c index e8ba5b1490..ec4e553e56 100644 --- a/sys/vfs/tmpfs/tmpfs_vnops.c +++ b/sys/vfs/tmpfs/tmpfs_vnops.c @@ -381,9 +381,7 @@ tmpfs_fsync(struct vop_fsync_args *v) tmpfs_update(vp); if (vp->v_type == VREG) { - if (tmp->tm_flags & TMPFS_FLAG_UNMOUNTING) { - tmpfs_truncate(vp, 0); - } else if (vp->v_flag & VRECLAIMED) { + if (vp->v_flag & VRECLAIMED) { if (node->tn_links == 0) tmpfs_truncate(vp, 0); else -- 2.11.4.GIT