系统:ubuntu 24.04

问题:
ossfs 挂载bucket后使用df -h 显示可用容量为16EB,致使部分应用软件无法识别可用空间。例如qbittorrent 显示可用空间为unknow、H@H 直接不认盘,导致静态块被删了一半😭……

解决:问AI 😅
编译安装ossfs,对源码中s3fs.cpp 文件中s3fs_statfs 的函数进行修改;将f_blocks改为1PB

原文件

static int s3fs_statfs(const char* _path, struct statvfs* stbuf)
{
    // WTF8_ENCODE(path)
    stbuf->f_bsize  = 16 * 1024 * 1024;
    stbuf->f_namemax = NAME_MAX;
#ifdef __MSYS__
    // WinFsp resolves the free space from f_bfree * f_frsize, and the total space from f_blocks * f_frsize (in bytes).
    stbuf->f_frsize = stbuf->f_bsize;
    stbuf->f_blocks = INT32_MAX;
    stbuf->f_bfree = INT32_MAX;
#else
    stbuf->f_blocks = static_cast<fsblkcnt_t>(~0) / stbuf->f_bsize;
    stbuf->f_bfree  = stbuf->f_blocks;
#endif
    stbuf->f_bavail = stbuf->f_blocks;
    return 0;
}

更改后的文件

static int s3fs_statfs(const char* _path, struct statvfs* stbuf)
{
    // WTF8_ENCODE(path)
    stbuf->f_bsize  = 16 * 1024 * 1024;
    stbuf->f_namemax = NAME_MAX;
    const uint64_t TOTAL_SIZE = 1ULL * 1024 * 1024 * 1024 * 1024 * 1024;//1PB
#ifdef __MSYS__
    // WinFsp resolves the free space from f_bfree * f_frsize, and the total space from f_blocks * f_frsize (in bytes).
    stbuf->f_frsize = stbuf->f_bsize;
    //stbuf->f_blocks = INT32_MAX;
    //stbuf->f_bfree = INT32_MAX;
#else
    stbuf->f_blocks = TOTAL_SIZE / stbuf->f_bsize;
    stbuf->f_bfree  = stbuf->f_blocks;
#endif
    stbuf->f_bavail = stbuf->f_blocks;

    return 0;
}

AI 对于此函数的解释

这段代码定义了一个名为 s3fs_statfs 的函数,它的作用是模拟文件系统的统计信息。它接受一个路径 _path (虽然在这个函数中没有实际使用) 和一个指向 statvfs 结构体的指针 stbuf 作为参数。statvfs 结构体用于存储文件系统的统计信息,例如总块数、可用块数、块大小等。

这段代码的主要目的是填充 stbuf 结构体,以便向调用者提供文件系统的信息。然而,它并没有真正去查询底层文件系统的信息,而是设置了一些固定的或近似的值,这在某种程度上模拟了一个无限大的文件系统。

下面是代码的详细解释:

stbuf->f_bsize = 16 * 1024 * 1024;: 设置块大小为 16MB。这是文件系统进行 I/O 操作的基本单位。

stbuf->f_namemax = NAME_MAX;: 设置文件名的最大长度。NAME_MAX 是一个宏,表示系统允许的最大文件名长度。

#ifdef __MSYS__ ... #else ... #endif: 这是一个条件编译块,用于区分不同的操作系统环境。__MSYS__ 通常用于 MinGW/MSYS 环境(Windows)。

#ifdef __MSYS__ (Windows):

stbuf->f_frsize = stbuf->f_bsize;: 设置碎片大小(最小分配单元)等于块大小。
stbuf->f_blocks = INT32_MAX;: 设置总块数为 INT32_MAX,即 32 位整数的最大值,表示一个非常大的值。
stbuf->f_bfree = INT32_MAX;: 设置可用块数也为 INT32_MAX,表示所有块都可用。
#else (非Windows):

stbuf->f_blocks = static_cast<fsblkcnt_t>(~0) / stbuf->f_bsize;: 这是一个计算总块数的技巧。~0 表示所有位都为 1 的整数,转换为 fsblkcnt_t 类型后,除以块大小,得到一个非常大的值。
stbuf->f_bfree = stbuf->f_blocks;: 设置可用块数等于总块数。
stbuf->f_bavail = stbuf->f_blocks;: 设置可用块数(对非特权用户)也等于总块数。

return 0;: 表示函数执行成功。

总结:

这段代码模拟了一个几乎无限大的文件系统,它的块大小为 16MB。  在 Windows 环境下,它直接使用 INT32_MAX 作为块数和可用块数。在其他环境下,它使用一种技巧来计算一个很大的值作为块数。  关键在于,它并没有实际去查询文件系统的真实信息,而是返回了一些预设的值。  这种做法可能用于测试、模拟或者在某些特定的文件系统实现中,例如 FUSE 文件系统,需要自定义 statfs 的行为。

需要注意的是,这种模拟可能会导致一些问题,例如如果应用程序依赖于 statfs 返回的真实信息,可能会出现意想不到的错误。  例如,如果程序尝试写入超过实际磁盘空间大小的数据,仍然会失败,即使 f_bfree 返回一个很大的值。

标签: none

添加新评论