xfs-masters
[Top] [All Lists]

[xfs-masters] [Bug 428] New: xfs_freeze/thaw potential problem.

To: xfs-master@xxxxxxxxxxx
Subject: [xfs-masters] [Bug 428] New: xfs_freeze/thaw potential problem.
From: bugzilla-daemon@xxxxxxxxxxx
Date: Wed, 23 Nov 2005 18:39:26 -0800
Reply-to: xfs-masters@xxxxxxxxxxx
Sender: xfs-masters-bounce@xxxxxxxxxxx
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.


<Prev in Thread] Current Thread [Next in Thread>
  • [xfs-masters] [Bug 428] New: xfs_freeze/thaw potential problem., bugzilla-daemon <=