如何确定文件系统的冻结/解冻状态?

如何确定文件系统的冻结/解冻状态?

我用来xfs_freeze冻结和解冻我的 xfs 文件系统:

xfs_freeze -f /blahblah

xfs_freeze -u /blahblah

运行解冻命令后,我想确保文件系统没有被冻结。该命令不返回任何值或消息。

我知道我可以尝试重新安装文件系统,但这并不是完全可靠的。

另外,如果我在未冻结的文件系统上再次运行 unfreeze 命令,我将得到如下信息:

xfs_freeze: cannot unfreeze filesystem mounted at /blahblah: Invalid
argument

这种方法也不是万无一失的,因为消息不准确。

我是否可以使用一个命令来告诉我文件系统的冻结状态,或者是否有一种万无一失的方法可以用来确定这一点?

有什么提示吗?

答案1

长话短说:

虽然没有直接的方法来查询文件系统是否被冻结,但您可以滥用嵌套冻结尝试不起作用的事实。例如,我在 /xfs_test 处安装了一个 XFS 文件系统:

[root@testvm1 ~]# mount | grep xfs_test
/dev/sdb1 on /xfs_test type xfs (rw,relatime,seclabel,attr2,inode64,noquota)

[root@testvm1 ~]# xfs_freeze -f /xfs_test/      # Initial freeze
[root@testvm1 ~]# echo $?
0

[root@testvm1 ~]# xfs_freeze -f /xfs_test/      # Subsequent freeze attempt
xfs_freeze: cannot freeze filesystem at /xfs_test/: Device or resource busy
[root@testvm1 ~]# echo $?
1

同样的类比也适用于解冻或解冻文件系统:

[root@testvm1 ~]# xfs_freeze -u /xfs_test/      # Same filesystem, currently frozen
[root@testvm1 ~]# echo $?
0

[root@testvm1 ~]# xfs_freeze -u /xfs_test/      # Thawed filesystem
xfs_freeze: cannot unfreeze filesystem mounted at /xfs_test/: Invalid argument
[root@testvm1 ~]# echo $?
1

我必须进行一些挖掘才能查明冻结/解冻状态查询是否可能。虽然技术细节有点超出我的理解,但这就是我整理的。

冻结和解冻文件系统是最初为 XFS 构建的一项功能。它最终被引入 Linux 内核,允许该功能也适用于其他文件系统。作为这篇 LWN 文章解释:

Takashi Sato 建议采用 XFS 特定功能并将其移至文件系统代码中。该补丁将提供一个 ioctl() 用于暂停对文件系统的写入访问、冻结以及恢复写入的解冻选项。

...

本质上,该补丁只是以用户可访问的方式导出 freeze_bdev() 内核函数。freeze_bdev() 通过刷新超级块并同步设备来将文件系统锁定为一致状态。该补丁还将对冻结状态的跟踪添加到 struct block_device 状态字段中。

此时,嵌套冷冻和解冻是可能的。据我了解,代码中的计数器变量跟踪嵌套的冻结和解冻尝试。冻结时该变量会增加,解冻时该变量会减少。只有当计数器为 0 时,文件系统才会真正解冻。

之后,我找到了 2016 年的这个补丁讨论,它是关于添加一个新的 ioctl 调用来查询文件系统的状态:fs:添加FIGETFROZEN ioctl 调用。据我所知,这个补丁还没有合并到内核中。

补丁讨论提供了几个要点:

此外,从用户空间轮询冻结状态本质上是很危险的 - 当系统调用返回时,信息可能不正确,因此您不能依赖它来在用户空间中做出决策。

进而:

我[原文如此]快速挖掘显示,5 年前,为了使 freeze ioctl 在 btrfs 上工作,嵌套被故意破坏。

这导致我想到了上面所示的解决方案。


另一种可能性包含在这个答案在 StackOverflow。如果您尝试重新挂载冻结的文件系统,则尝试将失败并出现“设备正忙”错误。由于许多其他原因,安装座也可能很忙,因此该解决方案诚然不是万无一失的。

答案2

我认为你必须编写自己的命令来进行检查。

#!/bin/bash

function touchFs() {
    echo "mp: $1";
    touch "$1/frzn-5tst";
    if [ -f "$1/frzn-5tst" ]; then
            rm "$1/frzn-5tst" &> /dev/null;
    fi
}

function usage() {
    echo "$0 <mountpoint>";
    exit 1;
}

if [ -z $1 ]; then
   usage;
fi

touchFs $1&
ppid=$!;
state=`ps -o s= -p $ppid`;

if [ -z "$state" ]; then
    echo "device is unfrozen";
elif [ "$state" == "S" ]; then
    echo "device is frozen";
fi

相关内容