[XFS] Fix inode reclaim scalability regression. When a filesystem has
millions of inodes cached and has sparse cluster population, removing inodes from the cluster hash consumes excessive amounts of CPU time. Reduce the CPU cost by making removal O(1) via use of a double linked list for the hash chains. SGI-PV: 951551 SGI-Modid: xfs-linux-melb:xfs-kern:25683a Signed-off-by: David Chinner <dgc@sgi.com> Signed-off-by: Nathan Scott <nathans@sgi.com>
This commit is contained in:
parent
8272145c05
commit
1fc5d959d8
2 changed files with 13 additions and 17 deletions
|
@ -421,7 +421,10 @@ xfs_iget_core(
|
||||||
ip->i_chash = chlnew;
|
ip->i_chash = chlnew;
|
||||||
chlnew->chl_ip = ip;
|
chlnew->chl_ip = ip;
|
||||||
chlnew->chl_blkno = ip->i_blkno;
|
chlnew->chl_blkno = ip->i_blkno;
|
||||||
|
if (ch->ch_list)
|
||||||
|
ch->ch_list->chl_prev = chlnew;
|
||||||
chlnew->chl_next = ch->ch_list;
|
chlnew->chl_next = ch->ch_list;
|
||||||
|
chlnew->chl_prev = NULL;
|
||||||
ch->ch_list = chlnew;
|
ch->ch_list = chlnew;
|
||||||
chlnew = NULL;
|
chlnew = NULL;
|
||||||
}
|
}
|
||||||
|
@ -723,23 +726,15 @@ xfs_iextract(
|
||||||
ASSERT(ip->i_cnext == ip && ip->i_cprev == ip);
|
ASSERT(ip->i_cnext == ip && ip->i_cprev == ip);
|
||||||
ASSERT(ip->i_chash != NULL);
|
ASSERT(ip->i_chash != NULL);
|
||||||
chm=NULL;
|
chm=NULL;
|
||||||
for (chl = ch->ch_list; chl != NULL; chl = chl->chl_next) {
|
chl = ip->i_chash;
|
||||||
if (chl->chl_blkno == ip->i_blkno) {
|
if (chl->chl_prev)
|
||||||
if (chm == NULL) {
|
chl->chl_prev->chl_next = chl->chl_next;
|
||||||
/* first item on the list */
|
else
|
||||||
ch->ch_list = chl->chl_next;
|
ch->ch_list = chl->chl_next;
|
||||||
} else {
|
if (chl->chl_next)
|
||||||
chm->chl_next = chl->chl_next;
|
chl->chl_next->chl_prev = chl->chl_prev;
|
||||||
}
|
kmem_zone_free(xfs_chashlist_zone, chl);
|
||||||
kmem_zone_free(xfs_chashlist_zone, chl);
|
} else {
|
||||||
break;
|
|
||||||
} else {
|
|
||||||
ASSERT(chl->chl_ip != ip);
|
|
||||||
chm = chl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ASSERT_ALWAYS(chl != NULL);
|
|
||||||
} else {
|
|
||||||
/* delete one inode from a non-empty list */
|
/* delete one inode from a non-empty list */
|
||||||
iq = ip->i_cnext;
|
iq = ip->i_cnext;
|
||||||
iq->i_cprev = ip->i_cprev;
|
iq->i_cprev = ip->i_cprev;
|
||||||
|
|
|
@ -189,6 +189,7 @@ typedef struct xfs_ihash {
|
||||||
*/
|
*/
|
||||||
typedef struct xfs_chashlist {
|
typedef struct xfs_chashlist {
|
||||||
struct xfs_chashlist *chl_next;
|
struct xfs_chashlist *chl_next;
|
||||||
|
struct xfs_chashlist *chl_prev;
|
||||||
struct xfs_inode *chl_ip;
|
struct xfs_inode *chl_ip;
|
||||||
xfs_daddr_t chl_blkno; /* starting block number of
|
xfs_daddr_t chl_blkno; /* starting block number of
|
||||||
* the cluster */
|
* the cluster */
|
||||||
|
|
Loading…
Reference in a new issue