Convert the xfs_icluster inode list to use hlist constructs.
Use a hlist as we only need a single list head pointer and that
keeps the memory usage of these structures down.
Signed-off-by: Dave Chinner <dgc@xxxxxxx>
---
fs/xfs/xfs_iget.c | 61 +++++++++++++----------------------------------------
fs/xfs/xfs_inode.c | 6 ++++-
fs/xfs/xfs_inode.h | 5 +---
fs/xfs/xfsidbg.c | 4 +--
4 files changed, 24 insertions(+), 52 deletions(-)
Index: 2.6.x-xfs-new/fs/xfs/xfs_inode.h
===================================================================
--- 2.6.x-xfs-new.orig/fs/xfs/xfs_inode.h 2007-08-09 13:03:53.000000000
+1000
+++ 2.6.x-xfs-new/fs/xfs/xfs_inode.h 2007-08-09 18:14:29.650646277 +1000
@@ -178,7 +178,7 @@ extern void xfs_iocore_inode_reinit(stru
* the same time.
*/
typedef struct xfs_icluster {
- struct xfs_inode *icl_ip;
+ struct hlist_head icl_inodes; /* list of inodes on cluster */
xfs_daddr_t icl_blkno; /* starting block number of
* the cluster */
struct xfs_buf *icl_buf; /* the inode buffer */
@@ -296,8 +296,7 @@ typedef struct xfs_inode {
xfs_icdinode_t i_d; /* most of ondisk inode */
xfs_icluster_t *i_cluster; /* cluster list header */
- struct xfs_inode *i_cnext; /* cluster link forward */
- struct xfs_inode *i_cprev; /* cluster link backward */
+ struct hlist_node i_cnode; /* cluster link node */
xfs_fsize_t i_size; /* in-memory size */
/* Trace buffers per inode. */
Index: 2.6.x-xfs-new/fs/xfs/xfs_iget.c
===================================================================
--- 2.6.x-xfs-new.orig/fs/xfs/xfs_iget.c 2007-08-09 13:03:53.000000000
+1000
+++ 2.6.x-xfs-new/fs/xfs/xfs_iget.c 2007-08-09 18:15:16.832572205 +1000
@@ -290,31 +290,21 @@ finish_inode:
ip->i_udquot = ip->i_gdquot = NULL;
xfs_iflags_set(ip, XFS_INEW);
- ASSERT(ip->i_cluster == NULL && ip->i_cprev == NULL &&
- ip->i_cnext == NULL);
+ ASSERT(ip->i_cluster == NULL);
- if (icl) {
- /* insert this inode into the doubly-linked list
- * where icl points. lock the icl to protect against
- * others traversing the icl list */
- spin_lock(&icl->icl_lock);
- ASSERT(icl->icl_ip != NULL);
- iq = icl->icl_ip;
- ip->i_cprev = iq->i_cprev;
- iq->i_cprev->i_cnext = ip;
- iq->i_cprev = ip;
- ip->i_cnext = iq;
- icl->icl_ip = ip;
- ip->i_cluster = icl;
- spin_unlock(&icl->icl_lock);
- } else {
- ip->i_cnext = ip;
- ip->i_cprev = ip;
- ip->i_cluster = new_icl;
- new_icl->icl_ip = ip;
+ if (!icl) {
spin_lock_init(&new_icl->icl_lock);
+ INIT_HLIST_HEAD(&new_icl->icl_inodes);
+ icl = new_icl;
new_icl = NULL;
+ } else {
+ ASSERT(!hlist_empty(&icl->icl_inodes));
}
+ spin_lock(&icl->icl_lock);
+ hlist_add_head(&ip->i_cnode, &icl->icl_inodes);
+ ip->i_cluster = icl;
+ spin_unlock(&icl->icl_lock);
+
write_unlock(&pag->pag_ici_lock);
radix_tree_preload_end();
if (new_icl)
@@ -579,33 +569,12 @@ xfs_iextract(
*/
mp = ip->i_mount;
spin_lock(&ip->i_cluster->icl_lock);
- if (unlikely(ip->i_cnext == ip)) {
- /*
- * Last inode in cluster object.
- *
- * We've been removed from the inode radix tree, and
- * we are the last inode to reference the cluster.
- * We can simply drop our loks and free it at this point
- * because nothing can find us or the cluster.
- */
- ASSERT(ip->i_cnext == ip && ip->i_cprev == ip);
- ASSERT(ip->i_cluster != NULL);
+ hlist_del(&ip->i_cnode);
+ spin_unlock(&ip->i_cluster->icl_lock);
- spin_unlock(&ip->i_cluster->icl_lock);
+ /* was last inode in cluster? */
+ if (hlist_empty(&ip->i_cluster->icl_inodes))
kmem_zone_free(xfs_icluster_zone, ip->i_cluster);
- } else {
- /* delete one inode from a non-empty list */
- iq = ip->i_cnext;
- iq->i_cprev = ip->i_cprev;
- ip->i_cprev->i_cnext = iq;
- if (ip->i_cluster->icl_ip == ip) {
- ip->i_cluster->icl_ip = iq;
- }
- spin_unlock(&ip->i_cluster->icl_lock);
- ip->i_cluster = __return_address;
- ip->i_cprev = __return_address;
- ip->i_cnext = __return_address;
- }
/*
* Remove from mount's inode list.
Index: 2.6.x-xfs-new/fs/xfs/xfs_inode.c
===================================================================
--- 2.6.x-xfs-new.orig/fs/xfs/xfs_inode.c 2007-08-09 13:03:53.000000000
+1000
+++ 2.6.x-xfs-new/fs/xfs/xfs_inode.c 2007-08-09 18:11:14.059874991 +1000
@@ -3050,6 +3050,7 @@ xfs_iflush(
xfs_inode_t *iq;
int clcount; /* count of inodes clustered */
int bufwasdelwri;
+ struct hlist_node *entry;
enum { INT_DELWRI = (1 << 0), INT_ASYNC = (1 << 1) };
XFS_STATS_INC(xs_iflush_count);
@@ -3168,7 +3169,10 @@ xfs_iflush(
ip->i_cluster->icl_buf = bp;
clcount = 0;
- for (iq = ip->i_cnext; iq != ip; iq = iq->i_cnext) {
+ hlist_for_each_entry(iq, entry, &ip->i_cluster->icl_inodes, i_cnode) {
+ if (iq == ip)
+ continue;
+
/*
* Do an un-protected check to see if the inode is dirty and
* is a candidate for flushing. These checks will be repeated
Index: 2.6.x-xfs-new/fs/xfs/xfsidbg.c
===================================================================
--- 2.6.x-xfs-new.orig/fs/xfs/xfsidbg.c 2007-08-09 13:03:53.000000000 +1000
+++ 2.6.x-xfs-new/fs/xfs/xfsidbg.c 2007-08-09 18:16:46.581017645 +1000
@@ -6755,8 +6755,8 @@ xfsidbg_xnode(xfs_inode_t *ip)
kdb_printf("\n");
kdb_printf("icluster 0x%p cnext 0x%p cprev 0x%p\n",
ip->i_cluster,
- ip->i_cnext,
- ip->i_cprev);
+ ip->i_cnode.next,
+ ip->i_cnode.pprev);
xfs_xnode_fork("data", &ip->i_df);
xfs_xnode_fork("attr", ip->i_afp);
kdb_printf("\n");
|