ext3 deadlock fix
Subsystems (2)
PATCH 1/1 ext3 deadlock fix
My recent fix for the ext3 data=journal umount data loss problem has a bug. The filesystem can deadlock if someone runs mount -o remount' while the filesystem is under load. Everything which writes to that filesystem gets stuck in D' state.
This is because:
a) ext3_sync_fs() has to wait until a transaction has finished.
b) a transaction cannot finish when someone else holds lock_super(). Because lock_super() is used in the block allocator.
The patch ensures that ->sync_fs is never run under lock_super().
Documentation/filesystems/Locking | 2 ++ fs/buffer.c | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-)
Documentation/filesystems/Locking renamed from Documentation/filesystems/Locking~sync_fs-fix +2 -0
@@ -93,6 +93,7 @@ prototypes: void (*delete_inode) (struct inode *); void (*put_super) (struct super_block *); void (*write_super) (struct super_block *); + int (*sync_fs) (struct super_block *); int (*statfs) (struct super_block *, struct statfs *); int (*remount_fs) (struct super_block *, int *, char *); void (*clear_inode) (struct inode *);
@@ -108,6 +109,7 @@ delete_inode: no clear_inode: no put_super: yes yes maybe (see below) write_super: yes yes maybe (see below) +write_super: yes no maybe (see below) statfs: yes no no remount_fs: yes yes maybe (see below) umount_begin: yes no maybe (see below)
fs/buffer.c renamed from fs/buffer.c~sync_fs-fix +1 -1
@@ -327,9 +327,9 @@ int fsync_super(struct super_block *sb)lock_super (sb);if (sb->s_dirt && sb->s_op && sb->s_op->write_super) sb->s_op->write_super (sb); +unlock_super (sb);if (sb->s_op && sb->s_op->sync_fs) sb->s_op->sync_fs (sb); -unlock_super (sb);unlock_kernel ();return sync_buffers (dev,1 );
_
Hi,
Quoted 13 lines · Andrew Morton
The patch ensures that ->sync_fs is never run under
lock_super().Documentation/filesystems/Locking renamed from Documentation/filesystems/Locking~sync_fs-fix +1
-0@@ -93,6 +93,7 @@ prototypes: void (*delete_inode) (struct inode *); void (*put_super) (struct super_block *); void (*write_super) (struct super_block *); + int (*sync_fs) (struct super_block *); int (*statfs) (struct super_block *, struct statfs *); int (*remount_fs) (struct super_block *, int *, char *); void (*clear_inode) (struct inode *);
Documentation/filesystems/Locking delete_inode: no · line 112
Quoted 4 lines
Documentation/filesystems/Locking renamed from Documentation/filesystems/Locking~sync_fs-fix +1
-0@@ -108,6 +109,7 @@ delete_inode: no clear_inode: no put_super: yes yes maybe (see below) write_super: yes yes maybe (see below) +write_super: yes no maybe (see below)
~~~~~~~~~~~
A small typo in the documentation.
Quoted 3 lines
Documentation/filesystems/Locking renamed from Documentation/filesystems/Locking~sync_fs-fix +0
-0statfs: yes no no remount_fs: yes yes maybe (see below) umount_begin: yes no maybe (see below)
Signature · 2 lines
Best regards, Pierre