aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Chinner <david@fromorbit.com>2008-10-30 01:11:59 -0400
committerLachlan McIlroy <lachlan@sgi.com>2008-10-30 01:11:59 -0400
commit07c8f67587724b417f60bffb32c448dd94647b54 (patch)
tree01f6cf39be93dd5515481d09d282c503e05ef79f
parente946217e4fdaa67681bbabfa8e6b18641921f750 (diff)
[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>
-rw-r--r--fs/xfs/linux-2.6/xfs_super.c37
-rw-r--r--fs/xfs/xfs_iget.c15
-rw-r--r--fs/xfs/xfs_inode.c111
-rw-r--r--fs/xfs/xfs_inode.h1
-rw-r--r--fs/xfs/xfs_itable.c14
5 files changed, 119 insertions, 59 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(
887 inode_init_once((struct inode *)vnode); 887 inode_init_once((struct inode *)vnode);
888} 888}
889 889
890
891/*
892 * Slab object creation initialisation for the XFS inode.
893 * This covers only the idempotent fields in the XFS inode;
894 * all other fields need to be initialised on allocation
895 * from the slab. This avoids the need to repeatedly intialise
896 * fields in the xfs inode that left in the initialise state
897 * when freeing the inode.
898 */
899void
900xfs_inode_init_once(
901 kmem_zone_t *zone,
902 void *inode)
903{
904 struct xfs_inode *ip = inode;
905
906 memset(ip, 0, sizeof(struct xfs_inode));
907 atomic_set(&ip->i_iocount, 0);
908 atomic_set(&ip->i_pincount, 0);
909 spin_lock_init(&ip->i_flags_lock);
910 INIT_LIST_HEAD(&ip->i_reclaim);
911 init_waitqueue_head(&ip->i_ipin_wait);
912 /*
913 * Because we want to use a counting completion, complete
914 * the flush completion once to allow a single access to
915 * the flush completion without blocking.
916 */
917 init_completion(&ip->i_flush);
918 complete(&ip->i_flush);
919
920 mrlock_init(&ip->i_lock, MRLOCK_ALLOW_EQUAL_PRI|MRLOCK_BARRIER,
921 "xfsino", ip->i_ino);
922 mrlock_init(&ip->i_iolock, MRLOCK_BARRIER, "xfsio", ip->i_ino);
923}
924
890/* 925/*
891 * Attempt to flush the inode, this will actually fail 926 * Attempt to flush the inode, this will actually fail
892 * if the inode is pinned, but we dirty the inode again 927 * if the inode is pinned, but we dirty the inode again
@@ -2018,7 +2053,7 @@ xfs_init_zones(void)
2018 xfs_inode_zone = 2053 xfs_inode_zone =
2019 kmem_zone_init_flags(sizeof(xfs_inode_t), "xfs_inode", 2054 kmem_zone_init_flags(sizeof(xfs_inode_t), "xfs_inode",
2020 KM_ZONE_HWALIGN | KM_ZONE_RECLAIM | 2055 KM_ZONE_HWALIGN | KM_ZONE_RECLAIM |
2021 KM_ZONE_SPREAD, NULL); 2056 KM_ZONE_SPREAD, xfs_inode_init_once);
2022 if (!xfs_inode_zone) 2057 if (!xfs_inode_zone)
2023 goto out_destroy_efi_zone; 2058 goto out_destroy_efi_zone;
2024 2059
diff --git a/fs/xfs/xfs_iget.c b/fs/xfs/xfs_iget.c
index e229e9e001c2..5be89d760a9a 100644
--- a/fs/xfs/xfs_iget.c
+++ b/fs/xfs/xfs_iget.c
@@ -210,21 +210,6 @@ finish_inode:
210 210
211 xfs_itrace_exit_tag(ip, "xfs_iget.alloc"); 211 xfs_itrace_exit_tag(ip, "xfs_iget.alloc");
212 212
213
214 mrlock_init(&ip->i_lock, MRLOCK_ALLOW_EQUAL_PRI|MRLOCK_BARRIER,
215 "xfsino", ip->i_ino);
216 mrlock_init(&ip->i_iolock, MRLOCK_BARRIER, "xfsio", ip->i_ino);
217 init_waitqueue_head(&ip->i_ipin_wait);
218 atomic_set(&ip->i_pincount, 0);
219
220 /*
221 * Because we want to use a counting completion, complete
222 * the flush completion once to allow a single access to
223 * the flush completion without blocking.
224 */
225 init_completion(&ip->i_flush);
226 complete(&ip->i_flush);
227
228 if (lock_flags) 213 if (lock_flags)
229 xfs_ilock(ip, lock_flags); 214 xfs_ilock(ip, lock_flags);
230 215
diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c
index dbd9cef852ec..b0c604e1bd47 100644
--- a/fs/xfs/xfs_inode.c
+++ b/fs/xfs/xfs_inode.c
@@ -788,6 +788,70 @@ xfs_dic2xflags(
788} 788}
789 789
790/* 790/*
791 * Allocate and initialise an xfs_inode.
792 */
793struct xfs_inode *
794xfs_inode_alloc(
795 struct xfs_mount *mp,
796 xfs_ino_t ino)
797{
798 struct xfs_inode *ip;
799
800 /*
801 * if this didn't occur in transactions, we could use
802 * KM_MAYFAIL and return NULL here on ENOMEM. Set the
803 * code up to do this anyway.
804 */
805 ip = kmem_zone_alloc(xfs_inode_zone, KM_SLEEP);
806 if (!ip)
807 return NULL;
808
809 ASSERT(atomic_read(&ip->i_iocount) == 0);
810 ASSERT(atomic_read(&ip->i_pincount) == 0);
811 ASSERT(!spin_is_locked(&ip->i_flags_lock));
812 ASSERT(list_empty(&ip->i_reclaim));
813
814 ip->i_ino = ino;
815 ip->i_mount = mp;
816 ip->i_blkno = 0;
817 ip->i_len = 0;
818 ip->i_boffset =0;
819 ip->i_afp = NULL;
820 memset(&ip->i_df, 0, sizeof(xfs_ifork_t));
821 ip->i_flags = 0;
822 ip->i_update_core = 0;
823 ip->i_update_size = 0;
824 ip->i_delayed_blks = 0;
825 memset(&ip->i_d, 0, sizeof(xfs_icdinode_t));
826 ip->i_size = 0;
827 ip->i_new_size = 0;
828
829 /*
830 * Initialize inode's trace buffers.
831 */
832#ifdef XFS_INODE_TRACE
833 ip->i_trace = ktrace_alloc(INODE_TRACE_SIZE, KM_NOFS);
834#endif
835#ifdef XFS_BMAP_TRACE
836 ip->i_xtrace = ktrace_alloc(XFS_BMAP_KTRACE_SIZE, KM_NOFS);
837#endif
838#ifdef XFS_BMBT_TRACE
839 ip->i_btrace = ktrace_alloc(XFS_BMBT_KTRACE_SIZE, KM_NOFS);
840#endif
841#ifdef XFS_RW_TRACE
842 ip->i_rwtrace = ktrace_alloc(XFS_RW_KTRACE_SIZE, KM_NOFS);
843#endif
844#ifdef XFS_ILOCK_TRACE
845 ip->i_lock_trace = ktrace_alloc(XFS_ILOCK_KTRACE_SIZE, KM_NOFS);
846#endif
847#ifdef XFS_DIR2_TRACE
848 ip->i_dir_trace = ktrace_alloc(XFS_DIR2_KTRACE_SIZE, KM_NOFS);
849#endif
850
851 return ip;
852}
853
854/*
791 * Given a mount structure and an inode number, return a pointer 855 * Given a mount structure and an inode number, return a pointer
792 * to a newly allocated in-core inode corresponding to the given 856 * to a newly allocated in-core inode corresponding to the given
793 * inode number. 857 * inode number.
@@ -809,13 +873,9 @@ xfs_iread(
809 xfs_inode_t *ip; 873 xfs_inode_t *ip;
810 int error; 874 int error;
811 875
812 ASSERT(xfs_inode_zone != NULL); 876 ip = xfs_inode_alloc(mp, ino);
813 877 if (!ip)
814 ip = kmem_zone_zalloc(xfs_inode_zone, KM_SLEEP); 878 return ENOMEM;
815 ip->i_ino = ino;
816 ip->i_mount = mp;
817 atomic_set(&ip->i_iocount, 0);
818 spin_lock_init(&ip->i_flags_lock);
819 879
820 /* 880 /*
821 * Get pointer's to the on-disk inode and the buffer containing it. 881 * Get pointer's to the on-disk inode and the buffer containing it.
@@ -831,34 +891,11 @@ xfs_iread(
831 } 891 }
832 892
833 /* 893 /*
834 * Initialize inode's trace buffers.
835 * Do this before xfs_iformat in case it adds entries.
836 */
837#ifdef XFS_INODE_TRACE
838 ip->i_trace = ktrace_alloc(INODE_TRACE_SIZE, KM_NOFS);
839#endif
840#ifdef XFS_BMAP_TRACE
841 ip->i_xtrace = ktrace_alloc(XFS_BMAP_KTRACE_SIZE, KM_NOFS);
842#endif
843#ifdef XFS_BMBT_TRACE
844 ip->i_btrace = ktrace_alloc(XFS_BMBT_KTRACE_SIZE, KM_NOFS);
845#endif
846#ifdef XFS_RW_TRACE
847 ip->i_rwtrace = ktrace_alloc(XFS_RW_KTRACE_SIZE, KM_NOFS);
848#endif
849#ifdef XFS_ILOCK_TRACE
850 ip->i_lock_trace = ktrace_alloc(XFS_ILOCK_KTRACE_SIZE, KM_NOFS);
851#endif
852#ifdef XFS_DIR2_TRACE
853 ip->i_dir_trace = ktrace_alloc(XFS_DIR2_KTRACE_SIZE, KM_NOFS);
854#endif
855
856 /*
857 * If we got something that isn't an inode it means someone 894 * If we got something that isn't an inode it means someone
858 * (nfs or dmi) has a stale handle. 895 * (nfs or dmi) has a stale handle.
859 */ 896 */
860 if (be16_to_cpu(dip->di_core.di_magic) != XFS_DINODE_MAGIC) { 897 if (be16_to_cpu(dip->di_core.di_magic) != XFS_DINODE_MAGIC) {
861 kmem_zone_free(xfs_inode_zone, ip); 898 xfs_idestroy(ip);
862 xfs_trans_brelse(tp, bp); 899 xfs_trans_brelse(tp, bp);
863#ifdef DEBUG 900#ifdef DEBUG
864 xfs_fs_cmn_err(CE_ALERT, mp, "xfs_iread: " 901 xfs_fs_cmn_err(CE_ALERT, mp, "xfs_iread: "
@@ -881,7 +918,7 @@ xfs_iread(
881 xfs_dinode_from_disk(&ip->i_d, &dip->di_core); 918 xfs_dinode_from_disk(&ip->i_d, &dip->di_core);
882 error = xfs_iformat(ip, dip); 919 error = xfs_iformat(ip, dip);
883 if (error) { 920 if (error) {
884 kmem_zone_free(xfs_inode_zone, ip); 921 xfs_idestroy(ip);
885 xfs_trans_brelse(tp, bp); 922 xfs_trans_brelse(tp, bp);
886#ifdef DEBUG 923#ifdef DEBUG
887 xfs_fs_cmn_err(CE_ALERT, mp, "xfs_iread: " 924 xfs_fs_cmn_err(CE_ALERT, mp, "xfs_iread: "
@@ -911,8 +948,6 @@ xfs_iread(
911 XFS_IFORK_DSIZE(ip) / (uint)sizeof(xfs_bmbt_rec_t); 948 XFS_IFORK_DSIZE(ip) / (uint)sizeof(xfs_bmbt_rec_t);
912 } 949 }
913 950
914 INIT_LIST_HEAD(&ip->i_reclaim);
915
916 /* 951 /*
917 * The inode format changed when we moved the link count and 952 * The inode format changed when we moved the link count and
918 * made it 32 bits long. If this is an old format inode, 953 * made it 32 bits long. If this is an old format inode,
@@ -2631,8 +2666,6 @@ xfs_idestroy(
2631 } 2666 }
2632 if (ip->i_afp) 2667 if (ip->i_afp)
2633 xfs_idestroy_fork(ip, XFS_ATTR_FORK); 2668 xfs_idestroy_fork(ip, XFS_ATTR_FORK);
2634 mrfree(&ip->i_lock);
2635 mrfree(&ip->i_iolock);
2636 2669
2637#ifdef XFS_INODE_TRACE 2670#ifdef XFS_INODE_TRACE
2638 ktrace_free(ip->i_trace); 2671 ktrace_free(ip->i_trace);
@@ -2671,7 +2704,13 @@ xfs_idestroy(
2671 spin_unlock(&mp->m_ail_lock); 2704 spin_unlock(&mp->m_ail_lock);
2672 } 2705 }
2673 xfs_inode_item_destroy(ip); 2706 xfs_inode_item_destroy(ip);
2707 ip->i_itemp = NULL;
2674 } 2708 }
2709 /* asserts to verify all state is correct here */
2710 ASSERT(atomic_read(&ip->i_iocount) == 0);
2711 ASSERT(atomic_read(&ip->i_pincount) == 0);
2712 ASSERT(!spin_is_locked(&ip->i_flags_lock));
2713 ASSERT(list_empty(&ip->i_reclaim));
2675 kmem_zone_free(xfs_inode_zone, ip); 2714 kmem_zone_free(xfs_inode_zone, ip);
2676} 2715}
2677 2716
diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h
index 1420c49674d7..3af1f6dd1498 100644
--- a/fs/xfs/xfs_inode.h
+++ b/fs/xfs/xfs_inode.h
@@ -513,6 +513,7 @@ int xfs_itruncate_finish(struct xfs_trans **, xfs_inode_t *,
513 xfs_fsize_t, int, int); 513 xfs_fsize_t, int, int);
514int xfs_iunlink(struct xfs_trans *, xfs_inode_t *); 514int xfs_iunlink(struct xfs_trans *, xfs_inode_t *);
515 515
516struct xfs_inode * xfs_inode_alloc(struct xfs_mount *, xfs_ino_t);
516void xfs_idestroy_fork(xfs_inode_t *, int); 517void xfs_idestroy_fork(xfs_inode_t *, int);
517void xfs_idestroy(xfs_inode_t *); 518void xfs_idestroy(xfs_inode_t *);
518void xfs_idata_realloc(xfs_inode_t *, int, int); 519void xfs_idata_realloc(xfs_inode_t *, int, int);
diff --git a/fs/xfs/xfs_itable.c b/fs/xfs/xfs_itable.c
index cf6754a3c5b3..4f4c93941067 100644
--- a/fs/xfs/xfs_itable.c
+++ b/fs/xfs/xfs_itable.c
@@ -594,21 +594,21 @@ xfs_bulkstat(
594 /* 594 /*
595 * Get the inode cluster buffer 595 * Get the inode cluster buffer
596 */ 596 */
597 ASSERT(xfs_inode_zone != NULL);
598 ip = kmem_zone_zalloc(xfs_inode_zone,
599 KM_SLEEP);
600 ip->i_ino = ino;
601 ip->i_mount = mp;
602 spin_lock_init(&ip->i_flags_lock);
603 if (bp) 597 if (bp)
604 xfs_buf_relse(bp); 598 xfs_buf_relse(bp);
599 ip = xfs_inode_alloc(mp, ino);
600 if (!ip) {
601 bp = NULL;
602 rval = ENOMEM;
603 break;
604 }
605 error = xfs_itobp(mp, NULL, ip, 605 error = xfs_itobp(mp, NULL, ip,
606 &dip, &bp, bno, 606 &dip, &bp, bno,
607 XFS_IMAP_BULKSTAT, 607 XFS_IMAP_BULKSTAT,
608 XFS_BUF_LOCK); 608 XFS_BUF_LOCK);
609 if (!error) 609 if (!error)
610 clustidx = ip->i_boffset / mp->m_sb.sb_inodesize; 610 clustidx = ip->i_boffset / mp->m_sb.sb_inodesize;
611 kmem_zone_free(xfs_inode_zone, ip); 611 xfs_idestroy(ip);
612 if (XFS_TEST_ERROR(error != 0, 612 if (XFS_TEST_ERROR(error != 0,
613 mp, XFS_ERRTAG_BULKSTAT_READ_CHUNK, 613 mp, XFS_ERRTAG_BULKSTAT_READ_CHUNK,
614 XFS_RANDOM_BULKSTAT_READ_CHUNK)) { 614 XFS_RANDOM_BULKSTAT_READ_CHUNK)) {