当文件系统没有覆盖整个分区时,如何找到文件系统在块设备上实际占用的空间?
考虑演示核心问题的基本示例:
dd if=/dev/zero bs=1024 count=20480 of=something.img
losetup -f $PWD/something.img
mke2fs /dev/loop0
mount /dev/loop0 /mnt
但是df -k /mnt
给出了这个输出:
Filesystem 1K-blocks Used Available Use% Mounted on
/dev/loop0 19827 172 18631 1% /mnt
我创建了一个精确为2048KB的设备,但是statvfs()
系统调用(以及上面显示的类似df
)报告文件系统只需要19827KB。
似乎statvfs()
仅报告可供用户使用的块,但不报告文件系统的完整实际大小。
到目前为止,我只能找到特定于ext2 / 3/4的 hacky 解决方案:tune2fs -l /dev/loop0 | grep 'Block count:'
或dumpe2fs -h /dev/loop0 | grep 'Block count:'
。更清洁的是使用libext2fs
库(e2fprogs
包的一部分)来读取超级块,但我更喜欢文件系统中立系统调用(如果可用)。
答案 0 :(得分:1)
如果您正在寻找POSIX系统调用来检索设备级信息,我相信没有。
对于文件系统级信息[便携式]通话,据我所知,您可以检索data blocks
的总数,但不能检索剩余的开销 (例如inode tables
等)。
statvfs(2)
和fstatvfs(2)
将检索"可用" (又名data blocks
)文件系统级信息(例如vfat
,ext2
,ext3
...),而不是底层设备级信息(例如/dev/loop0
},/dev/sda
,...)。
[编辑3 ]:不是OP正在寻找的(这是设备级别 仅供参考,不包括文件系统的情况 不映射整个设备大小。)
在Linux下(假设相对较新的内核版本),您可以使用ioctl(2)
来检索设备大小(以blockdev(8)
执行的相同方法):
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <linux/fs.h>
int main(void) {
int fd = 0;
unsigned long long size = 0;
if (getuid() != 0) {
puts("You need to be root.");
exit(EXIT_FAILURE);
}
if ((fd = open("/dev/loop0", O_RDONLY)) < 0) {
printf("open(): %s\n", strerror(errno));
exit(EXIT_FAILURE);
}
if (ioctl(fd, BLKGETSIZE64, &size) < 0) {
printf("ioctl(): %s\n", strerror(errno));
exit(EXIT_FAILURE);
}
printf("%llu\n", size);
return 0;
}
修改强>:
正如评论中所讨论的,这是
device level information
,所以 如果文件系统没有映射整个设备大小,它就不会解决 问题(我们仍然不知道文件系统的总大小 占据设备)。
我担心你真的,真的需要手工,一步一步。
。您需要了解确切的文件系统,了解其结构,并进行所有数学运算。例如,在您的示例中,您使用的是20MiB Ext2文件系统。因此,结构将如下所示(为了示例而简化):
第0块:
- 引导记录和额外引导记录数据: 1块(2 * 512字节)
阻止第0组:
超级块: 1块(1024字节)
块组描述符表,块位图和Inode位图: 3块
Inode表: 214块
......数据块......
第1组:
超级块(备份): 1块
块组描述符表(备份),块位图和Inode位图: 3块
Inode表: 214块
......数据块......
第2组:
阻止位图和Inode位图: 2个区块
Inode表: 214块
......数据块......
现在做数学:
- 1 + 1 + 3 + 214 + 1 + 3 + 214 + 2 + 214 == 653
将 653 汇总至 19827 (您可以使用
statvfs(2)
检索):
- 653 + 19827 == 20480阻止
编辑2 :
正如评论中所讨论的,ext2超级块block count
已经包含文件系统占用的总块(不仅仅是我之前想到的可用块)。一个简单的测试来观察它(跳过错误检查以简化[例子]):
#include <stdio.h>
#include <string.h>
#include <inttypes.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/types.h>
#include <fcntl.h>
struct ext2_super_block {
uint32_t s_inodes_count;
uint32_t s_blocks_count;
uint32_t s_r_blocks_count;
uint32_t s_free_blocks_count;
uint32_t s_free_inodes_count;
uint32_t s_first_data_block;
uint32_t s_log_block_size;
uint32_t s_dummy3[7];
unsigned char s_magic[2];
uint16_t s_state;
uint32_t s_dummy5[8];
uint32_t s_feature_compat;
uint32_t s_feature_incompat;
uint32_t s_feature_ro_compat;
unsigned char s_uuid[16];
char s_volume_name[16];
char s_last_mounted[64];
uint32_t s_algorithm_usage_bitmap;
uint8_t s_prealloc_blocks;
uint8_t s_prealloc_dir_blocks;
uint16_t s_reserved_gdt_blocks;
uint8_t s_journal_uuid[16];
uint32_t s_journal_inum;
uint32_t s_journal_dev;
uint32_t s_last_orphan;
uint32_t s_hash_seed[4];
uint8_t s_def_hash_version;
uint8_t s_jnl_backup_type;
uint16_t s_reserved_word_pad;
uint32_t s_default_mount_opts;
uint32_t s_first_meta_bg;
uint32_t s_mkfs_time;
uint32_t s_jnl_blocks[17];
uint32_t s_blocks_count_hi;
uint32_t s_r_blocks_count_hi;
uint32_t s_free_blocks_hi;
uint16_t s_min_extra_isize;
uint16_t s_want_extra_isize;
uint32_t s_flags;
uint16_t s_raid_stride;
uint16_t s_mmp_interval;
uint64_t s_mmp_block;
uint32_t s_raid_stripe_width;
uint32_t s_reserved[163];
};
int main(void) {
int fd = 0;
struct ext2_super_block sb;
/* Reset sb memory */
memset(&sb, 0, sizeof(struct ext2_super_block));
/*
* /tmp/loop.img created with:
*
* dd if=/dev/zero bs=1024 count=20480 of=/tmp/loop.img
*
* ... and the ext2 file system maps the entire device.
*
*/
fd = open("/tmp/loop.img", O_RDONLY);
/* Jump to superblock */
lseek(fd, 1024, SEEK_SET);
/* Read the superblock */
read(fd, &sb, sizeof(struct ext2_super_block));
/* Print the total block count */
printf("s_blocks_count: %" PRIu32 "\n", sb.s_blocks_count); /* Prints 20480 */
return 0;
}
blockdev --getsize64 /dev/loop0
,dumpe2fs
等等。