summaryrefslogtreecommitdiffstats
path: root/fs/xfs/linux-2.6/xfs_super.c
diff options
context:
space:
mode:
authorDavid Chinner2008-10-30 06:11:59 +0100
committerLachlan McIlroy2008-10-30 06:11:59 +0100
commit07c8f67587724b417f60bffb32c448dd94647b54 (patch)
tree01f6cf39be93dd5515481d09d282c503e05ef79f /fs/xfs/linux-2.6/xfs_super.c
parentMerge branch 'tracing-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/... (diff)
downloadkernel-qcow2-linux-07c8f67587724b417f60bffb32c448dd94647b54.tar.gz
kernel-qcow2-linux-07c8f67587724b417f60bffb32c448dd94647b54.tar.xz
kernel-qcow2-linux-07c8f67587724b417f60bffb32c448dd94647b54.zip
[XFS] Make use of the init-once slab optimisation.
To avoid having to initialise some fields of the XFS inode on every allocation, we can use the slab init-once feature to initialise them. All we have to guarantee is that when we free the inode, all it's entries are in the initial state. Add asserts where possible to ensure debug kernels check this initial state before freeing and after allocation. SGI-PV: 981498 SGI-Modid: xfs-linux-melb:xfs-kern:31925a Signed-off-by: David Chinner <david@fromorbit.com> Signed-off-by: Lachlan McIlroy <lachlan@sgi.com> Signed-off-by: Christoph Hellwig <hch@infradead.org>
Diffstat (limited to 'fs/xfs/linux-2.6/xfs_super.c')
-rw-r--r--fs/xfs/linux-2.6/xfs_super.c37
1 files changed, 36 insertions, 1 deletions
diff --git a/fs/xfs/linux-2.6/xfs_super.c b/fs/xfs/linux-2.6/xfs_super.c
index 37ebe36056eb..d1c4dec51a3b 100644
--- a/fs/xfs/linux-2.6/xfs_super.c
+++ b/fs/xfs/linux-2.6/xfs_super.c
@@ -887,6 +887,41 @@ xfs_fs_inode_init_once(
inode_init_once((struct inode *)vnode);
}
+
+/*
+ * Slab object creation initialisation for the XFS inode.
+ * This covers only the idempotent fields in the XFS inode;
+ * all other fields need to be initialised on allocation
+ * from the slab. This avoids the need to repeatedly intialise
+ * fields in the xfs inode that left in the initialise state
+ * when freeing the inode.
+ */
+void
+xfs_inode_init_once(
+ kmem_zone_t *zone,
+ void *inode)
+{
+ struct xfs_inode *ip = inode;
+
+ memset(ip, 0, sizeof(struct xfs_inode));
+ atomic_set(&ip->i_iocount, 0);
+ atomic_set(&ip->i_pincount, 0);
+ spin_lock_init(&ip->i_flags_lock);
+ INIT_LIST_HEAD(&ip->i_reclaim);
+ init_waitqueue_head(&ip->i_ipin_wait);
+ /*
+ * Because we want to use a counting completion, complete
+ * the flush completion once to allow a single access to
+ * the flush completion without blocking.
+ */
+ init_completion(&ip->i_flush);
+ complete(&ip->i_flush);
+
+ mrlock_init(&ip->i_lock, MRLOCK_ALLOW_EQUAL_PRI|MRLOCK_BARRIER,
+ "xfsino", ip->i_ino);
+ mrlock_init(&ip->i_iolock, MRLOCK_BARRIER, "xfsio", ip->i_ino);
+}
+
/*
* Attempt to flush the inode, this will actually fail
* if the inode is pinned, but we dirty the inode again
@@ -2018,7 +2053,7 @@ xfs_init_zones(void)
xfs_inode_zone =
kmem_zone_init_flags(sizeof(xfs_inode_t), "xfs_inode",
KM_ZONE_HWALIGN | KM_ZONE_RECLAIM |
- KM_ZONE_SPREAD, NULL);
+ KM_ZONE_SPREAD, xfs_inode_init_once);
if (!xfs_inode_zone)
goto out_destroy_efi_zone;