http://oss.sgi.com/bugzilla/show_bug.cgi?id=428
Summary: xfs_freeze/thaw potential problem.
Product: Linux XFS
Version: Current
Platform: PC
OS/Version: Linux
Status: NEW
Severity: critical
Priority: P2
Component: XFS kernel code
AssignedTo: xfs-master@xxxxxxxxxxx
ReportedBy: loyogo@xxxxxxxxx
fs/xfs/linux-2.6/xfs_ioctl.c
case XFS_IOC_FREEZE:
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
if (inode->i_sb->s_frozen == SB_UNFROZEN)
freeze_bdev(inode->i_sb->s_bdev);
return 0;
case XFS_IOC_THAW:
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
if (inode->i_sb->s_frozen != SB_UNFROZEN)
thaw_bdev(inode->i_sb->s_bdev, inode->i_sb);
return 0;
fs/buffer.c
struct super_block *freeze_bdev(struct block_device *bdev)
{
struct super_block *sb;
down(&bdev->bd_mount_sem); //DownA
sb = get_super(bdev); //GetA
if (sb && !(sb->s_flags & MS_RDONLY)) {
sb->s_frozen = SB_FREEZE_WRITE; // A
smp_wmb();
sync_inodes_sb(sb, 0);
DQUOT_SYNC(sb);
lock_super(sb);
if (sb->s_dirt && sb->s_op->write_super)
sb->s_op->write_super(sb);
unlock_super(sb);
if (sb->s_op->sync_fs)
sb->s_op->sync_fs(sb, 1);
sync_blockdev(sb->s_bdev);
sync_inodes_sb(sb, 1);
sb->s_frozen = SB_FREEZE_TRANS; //B
smp_wmb();
sync_blockdev(sb->s_bdev);
if (sb->s_op->write_super_lockfs)
sb->s_op->write_super_lockfs(sb);
}
sync_blockdev(bdev);
return sb; /* thaw_bdev releases s->s_umount and bd_mount_sem */
}
void thaw_bdev(struct block_device *bdev, struct super_block *sb)
{
if (sb) {
BUG_ON(sb->s_bdev != bdev);
if (sb->s_op->unlockfs)
sb->s_op->unlockfs(sb);
sb->s_frozen = SB_UNFROZEN;
smp_wmb();
wake_up(&sb->s_wait_unfrozen);
drop_super(sb); /DropA
}
up(&bdev->bd_mount_sem); //UpA
}
if we do xfs_thaw between line A and line B. like this
xfs_freeze
|
|
| xfs_thaw
| |
| |
| |
| Done
|
|
Done
Do xfs_thaw later than xfs_freeze, but return before than it.
we need redo xfs_thaw after xfs_freeze to make fs writable.
this means we need to do one xfs_freeze but need to do twice xfs_thaw.
what will happen?
1. Line GetA is executed once. but DropA is executed twice.
2. DownA is executed once. but UpA is executed twice.
my advice:
--- fs/xfs/linux-2.6/xfs_ioctl.c 2005-11-11 18:54:36.000000000 -0500
+++ fs/xfs/linux-2.6/xfs_ioctl.c 2005-11-11 19:03:07.000000000 -0500
@@ -830,8 +830,15 @@
case XFS_IOC_THAW:
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
- if (inode->i_sb->s_frozen != SB_UNFROZEN)
+IS_UNFROZEN:
+ if (inode->i_sb->s_frozen != SB_UNFROZEN) {
+ // Make sure thaw is done after flag SB_FREEZE_TRANS is
set.
+ while (inode->i_sb->s_frozen != SB_FREEZE_TRANS ) {
+ delay(100);
+ goto IS_UNFROZEN;
+ }
thaw_bdev(inode->i_sb->s_bdev, inode->i_sb);
+ }
return 0;
--
Configure bugmail: http://oss.sgi.com/bugzilla/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
You are the assignee for the bug, or are watching the assignee.
|