--- v2.4.10/linux/fs/buffer.c Mon Sep 24 14:04:05 2001 +++ linux/fs/buffer.c Mon Sep 24 14:00:14 2001 @@ -359,7 +359,7 @@ lock_kernel(); sync_inodes(dev); DQUOT_SYNC(dev); - sync_supers(dev); + sync_supers(dev, 0); unlock_kernel(); return sync_buffers(dev, 1); @@ -2753,7 +2753,7 @@ { lock_kernel(); sync_unlocked_inodes(); - sync_supers(0); + sync_supers(0, 1); unlock_kernel(); for (;;) { --- v2.4.10/linux/fs/super.c Mon Sep 24 14:04:07 2001 +++ linux/fs/super.c Mon Sep 24 13:40:45 2001 @@ -688,13 +688,32 @@ sb->s_op->write_super(sb); unlock_super(sb); } - + +/* This is used for kupdated super-block updating + * it trys to use the specific super update function, + * and if it fails, falls back to using write_super + */ + +static inline void update_super(struct super_block *sb) +{ + lock_super(sb); + if (sb->s_root && sb->s_dirt) + if (sb->s_op) + { + if (sb->s_op->write_super_kupdated) + sb->s_op->write_super_kupdated(sb); + else if (sb->s_op->write_super) + sb->s_op->write_super(sb); + } + unlock_super(sb); +} + /* * Note: check the dirty flag before waiting, so we don't * hold up the sync while mounting a device. (The newly * mounted device won't need syncing.) */ -void sync_supers(kdev_t dev) +void sync_supers(kdev_t dev, int kupdated) { struct super_block * sb; @@ -708,18 +727,34 @@ return; } restart: + // since reiserfs does not garrentee super is not dirty (journal may + // be dirty still with kupdated), have to do this the hard way spin_lock(&sb_lock); sb = sb_entry(super_blocks.next); while (sb != sb_entry(&super_blocks)) - if (sb->s_dirt) { + if (sb->s_dirt && !(sb->s_flushed)) { sb->s_count++; + sb->s_flushed = 1; spin_unlock(&sb_lock); down_read(&sb->s_umount); - write_super(sb); + if (kupdated) + update_super(sb); + else + write_super(sb); drop_super(sb); goto restart; } else sb = sb_entry(sb->s_list.next); + + // now unflush all supers + + sb = sb_entry(super_blocks.next); + while (sb != sb_entry(&super_blocks)) + { + sb->s_flushed = 0; + sb = sb_entry(sb->s_list.next); + } + spin_unlock(&sb_lock); } @@ -805,6 +840,7 @@ sema_init(&s->s_dquot.dqio_sem, 1); sema_init(&s->s_dquot.dqoff_sem, 1); s->s_maxbytes = MAX_NON_LFS; + s->s_flushed = 0; } return s; } --- v2.4.10/linux/include/linux/fs.h Mon Sep 24 14:04:10 2001 +++ linux/include/linux/fs.h Mon Sep 24 13:01:34 2001 @@ -689,6 +689,7 @@ unsigned long s_blocksize; unsigned char s_blocksize_bits; unsigned char s_dirt; + unsigned char s_flushed; unsigned long long s_maxbytes; /* Max file size */ struct file_system_type *s_type; struct super_operations *s_op; @@ -859,6 +860,7 @@ void (*delete_inode) (struct inode *); void (*put_super) (struct super_block *); void (*write_super) (struct super_block *); + void (*write_super_kupdated) (struct super_block *); void (*write_super_lockfs) (struct super_block *); void (*unlockfs) (struct super_block *); int (*statfs) (struct super_block *, struct statfs *); @@ -1198,7 +1200,7 @@ extern int inode_has_buffers(struct inode *); extern void filemap_fdatasync(struct address_space *); extern void filemap_fdatawait(struct address_space *); -extern void sync_supers(kdev_t); +extern void sync_supers(kdev_t, int); extern int bmap(struct inode *, int); extern int notify_change(struct dentry *, struct iattr *); extern int permission(struct inode *, int); --- v2.4.10/linux/fs/reiserfs/super.c Mon Sep 24 14:04:07 2001 +++ linux/fs/reiserfs/super.c Mon Sep 24 13:08:05 2001 @@ -32,18 +31,28 @@ // at the ext2 code and comparing. It's subfunctions contain no code // used as a template unless they are so labeled. // -void reiserfs_write_super (struct super_block * s) +void reiserfs_write_super_ex (struct super_block * s, int immediate) { int dirty = 0 ; lock_kernel() ; if (!(s->s_flags & MS_RDONLY)) { - dirty = flush_old_commits(s, 1) ; + dirty = flush_old_commits(s, immediate) ; } s->s_dirt = dirty; unlock_kernel() ; } +void reiserfs_write_super_kupdated (struct super_block * s) +{ + reiserfs_write_super_ex(s, 0); +} + +void reiserfs_write_super (struct super_block * s) +{ + reiserfs_write_super_ex(s, 1); +} + // // a portion of this function, particularly the VFS interface portion, // was derived from minix or ext2's analog and evolved as the @@ -125,6 +134,7 @@ dirty_inode: reiserfs_dirty_inode, delete_inode: reiserfs_delete_inode, put_super: reiserfs_put_super, + write_super_kupdated: reiserfs_write_super_kupdated, write_super: reiserfs_write_super, write_super_lockfs: reiserfs_write_super_lockfs, unlockfs: reiserfs_unlockfs,