O(1) sb list traversing on syncs
PATCH 1/1 O(1) sb list traversing on syncs
against 2.6.12-rc4
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.
The patch was heavilly tested on 2.6.8 during 3 months, this forward-ported version boots and works ok as well.
Signed-off-by Kirill Korotaev <[email protected]>
fs/fs-writeback.c renamed from fs/fs-writeback.c.sbsync +27 -37
@@ -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 ); } }
fs/quota.c renamed from fs/quota.c.sbsync +24 -36
77 lines not on this page · raw message
fs/super.c renamed from fs/super.c.sbsync +45 -38
134 lines not on this page · raw message