mirror of
https://github.com/Fishwaldo/Star64_linux.git
synced 2025-06-23 15:11:16 +00:00
[PATCH] O(1) sb list traversing on syncs
This patch removes O(n^2) super block loops in sync_inodes(), sync_filesystems() etc. in favour of using __put_super_and_need_restart() which I introduced earlier. We faced a noticably long freezes on sb syncing when there are thousands of super blocks in the system. Signed-Off-By: Kirill Korotaev <dev@sw.ru> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
This commit is contained in:
parent
4fea2838aa
commit
618f06362a
3 changed files with 96 additions and 111 deletions
|
@ -485,32 +485,6 @@ static void set_sb_syncing(int val)
|
|||
spin_unlock(&sb_lock);
|
||||
}
|
||||
|
||||
/*
|
||||
* Find a superblock with inodes that need to be synced
|
||||
*/
|
||||
static struct super_block *get_super_to_sync(void)
|
||||
{
|
||||
struct super_block *sb;
|
||||
restart:
|
||||
spin_lock(&sb_lock);
|
||||
sb = sb_entry(super_blocks.prev);
|
||||
for (; sb != sb_entry(&super_blocks); sb = sb_entry(sb->s_list.prev)) {
|
||||
if (sb->s_syncing)
|
||||
continue;
|
||||
sb->s_syncing = 1;
|
||||
sb->s_count++;
|
||||
spin_unlock(&sb_lock);
|
||||
down_read(&sb->s_umount);
|
||||
if (!sb->s_root) {
|
||||
drop_super(sb);
|
||||
goto restart;
|
||||
}
|
||||
return sb;
|
||||
}
|
||||
spin_unlock(&sb_lock);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* sync_inodes - writes all inodes to disk
|
||||
* @wait: wait for completion
|
||||
|
@ -530,23 +504,39 @@ restart:
|
|||
* outstanding dirty inodes, the writeback goes block-at-a-time within the
|
||||
* filesystem's write_inode(). This is extremely slow.
|
||||
*/
|
||||
void sync_inodes(int wait)
|
||||
static void __sync_inodes(int wait)
|
||||
{
|
||||
struct super_block *sb;
|
||||
|
||||
set_sb_syncing(0);
|
||||
while ((sb = get_super_to_sync()) != NULL) {
|
||||
sync_inodes_sb(sb, 0);
|
||||
sync_blockdev(sb->s_bdev);
|
||||
drop_super(sb);
|
||||
spin_lock(&sb_lock);
|
||||
restart:
|
||||
list_for_each_entry(sb, &super_blocks, s_list) {
|
||||
if (sb->s_syncing)
|
||||
continue;
|
||||
sb->s_syncing = 1;
|
||||
sb->s_count++;
|
||||
spin_unlock(&sb_lock);
|
||||
down_read(&sb->s_umount);
|
||||
if (sb->s_root) {
|
||||
sync_inodes_sb(sb, wait);
|
||||
sync_blockdev(sb->s_bdev);
|
||||
}
|
||||
up_read(&sb->s_umount);
|
||||
spin_lock(&sb_lock);
|
||||
if (__put_super_and_need_restart(sb))
|
||||
goto restart;
|
||||
}
|
||||
spin_unlock(&sb_lock);
|
||||
}
|
||||
|
||||
void sync_inodes(int wait)
|
||||
{
|
||||
set_sb_syncing(0);
|
||||
__sync_inodes(0);
|
||||
|
||||
if (wait) {
|
||||
set_sb_syncing(0);
|
||||
while ((sb = get_super_to_sync()) != NULL) {
|
||||
sync_inodes_sb(sb, 1);
|
||||
sync_blockdev(sb->s_bdev);
|
||||
drop_super(sb);
|
||||
}
|
||||
__sync_inodes(1);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue