Commit b88beb9a authored by Andreas Gruenbacher's avatar Andreas Gruenbacher

gfs2: Evict inodes cooperatively

Add a gfs2_evict_inodes() helper that evicts inodes cooperatively across
the cluster.  This avoids running into timeouts during unmount
unnecessarily.
Signed-off-by: default avatarAndreas Gruenbacher <agruenba@redhat.com>
parent 6b388abc
...@@ -607,6 +607,7 @@ enum { ...@@ -607,6 +607,7 @@ enum {
SDF_WITHDRAW_RECOVERY = 14, /* Wait for journal recovery when we are SDF_WITHDRAW_RECOVERY = 14, /* Wait for journal recovery when we are
withdrawing */ withdrawing */
SDF_DEACTIVATING = 15, SDF_DEACTIVATING = 15,
SDF_EVICTING = 16,
}; };
enum gfs2_freeze_state { enum gfs2_freeze_state {
......
...@@ -1728,6 +1728,55 @@ static int gfs2_meta_init_fs_context(struct fs_context *fc) ...@@ -1728,6 +1728,55 @@ static int gfs2_meta_init_fs_context(struct fs_context *fc)
return 0; return 0;
} }
/**
* gfs2_evict_inodes - evict inodes cooperatively
* @sb: the superblock
*
* When evicting an inode with a zero link count, we are trying to upgrade the
* inode's iopen glock from SH to EX mode in order to determine if we can
* delete the inode. The other nodes are supposed to evict the inode from
* their caches if they can, and to poke the inode's inode glock if they cannot
* do so. Either behavior allows gfs2_upgrade_iopen_glock() to proceed
* quickly, but if the other nodes are not cooperating, the lock upgrading
* attempt will time out. Since inodes are evicted sequentially, this can add
* up quickly.
*
* Function evict_inodes() tries to keep the s_inode_list_lock list locked over
* a long time, which prevents other inodes from being evicted concurrently.
* This precludes the cooperative behavior we are looking for. This special
* version of evict_inodes() avoids that.
*
* Modeled after drop_pagecache_sb().
*/
static void gfs2_evict_inodes(struct super_block *sb)
{
struct inode *inode, *toput_inode = NULL;
struct gfs2_sbd *sdp = sb->s_fs_info;
set_bit(SDF_EVICTING, &sdp->sd_flags);
spin_lock(&sb->s_inode_list_lock);
list_for_each_entry(inode, &sb->s_inodes, i_sb_list) {
spin_lock(&inode->i_lock);
if ((inode->i_state & (I_FREEING|I_WILL_FREE|I_NEW)) &&
!need_resched()) {
spin_unlock(&inode->i_lock);
continue;
}
atomic_inc(&inode->i_count);
spin_unlock(&inode->i_lock);
spin_unlock(&sb->s_inode_list_lock);
iput(toput_inode);
toput_inode = inode;
cond_resched();
spin_lock(&sb->s_inode_list_lock);
}
spin_unlock(&sb->s_inode_list_lock);
iput(toput_inode);
}
static void gfs2_kill_sb(struct super_block *sb) static void gfs2_kill_sb(struct super_block *sb)
{ {
struct gfs2_sbd *sdp = sb->s_fs_info; struct gfs2_sbd *sdp = sb->s_fs_info;
...@@ -1744,6 +1793,8 @@ static void gfs2_kill_sb(struct super_block *sb) ...@@ -1744,6 +1793,8 @@ static void gfs2_kill_sb(struct super_block *sb)
sdp->sd_master_dir = NULL; sdp->sd_master_dir = NULL;
shrink_dcache_sb(sb); shrink_dcache_sb(sb);
gfs2_evict_inodes(sb);
/* /*
* Flush and then drain the delete workqueue here (via * Flush and then drain the delete workqueue here (via
* destroy_workqueue()) to ensure that any delete work that * destroy_workqueue()) to ensure that any delete work that
......
...@@ -935,6 +935,7 @@ static int gfs2_statfs(struct dentry *dentry, struct kstatfs *buf) ...@@ -935,6 +935,7 @@ static int gfs2_statfs(struct dentry *dentry, struct kstatfs *buf)
static int gfs2_drop_inode(struct inode *inode) static int gfs2_drop_inode(struct inode *inode)
{ {
struct gfs2_inode *ip = GFS2_I(inode); struct gfs2_inode *ip = GFS2_I(inode);
struct gfs2_sbd *sdp = GFS2_SB(inode);
if (inode->i_nlink && if (inode->i_nlink &&
gfs2_holder_initialized(&ip->i_iopen_gh)) { gfs2_holder_initialized(&ip->i_iopen_gh)) {
...@@ -959,6 +960,12 @@ static int gfs2_drop_inode(struct inode *inode) ...@@ -959,6 +960,12 @@ static int gfs2_drop_inode(struct inode *inode)
return 0; return 0;
} }
/*
* No longer cache inodes when trying to evict them all.
*/
if (test_bit(SDF_EVICTING, &sdp->sd_flags))
return 1;
return generic_drop_inode(inode); return generic_drop_inode(inode);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment