给定一个文件描述符或文件名,如何知道我是否可以写入任意位置而无需等待干预部分在磁盘上明确归零?
答案 0 :(得分:3)
您可以stat()
该文件获取文件大小和磁盘块数,在文件末尾搜索相对较少数量的磁盘块,写入已知数量的块,然后再次对文件进行统计。将原始磁盘块数与最终数进行比较。如果文件系统不支持稀疏文件,只需几个磁盘块就不需要花太长时间。
给定原始和最终的磁盘块数,然后尝试确定文件系统是否支持稀疏文件。我说“尝试”,因为一些文件系统可以使这很难 - 例如,ZFS启用了压缩。
这样的事情:
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
int check( const char *filename )
{
struct stat sb;
long blocksize;
off_t filesize;
blkcnt_t origblocks;
char *buffer;
int fd;
fd = open( filename, O_CREAT | O_RDWR, 0644 );
fstat( fd, &sb );
blocksize = sb.st_blksize;
filesize = sb.st_size;
origblocks = sb.st_blocks;
lseek( fd, 16UL * blocksize, SEEK_END );
buffer = malloc( blocksize );
memset( buffer, 0xAA, blocksize );
write( fd, buffer, blocksize );
fsync( fd );
free( buffer );
// kludge to give ZFS time to update metadata
for ( ;; )
{
stat( filename, &sb );
if ( sb.st_blocks != origblocks )
{
break;
}
}
printf( "file: %s\n filesystem: %s\n blocksize: %d\n size: %zd\n"
" blocks: %zd\n orig blocks: %zd\n disk space: %zd\n",
filename, sb.st_fstype, blocksize, sb.st_size,
( size_t ) sb.st_blocks, ( size_t ) origblocks,
( size_t ) ( 512UL * sb.st_blocks ) );
// return file to original size
ftruncate( fd, filesize );
return( 0 );
}
int main( int argc, char **argv )
{
for ( int ii = 1; ii < argc; ii++ )
{
check( argv[ ii ] );
}
return( 0 );
}
(为清楚起见,省略了错误检查)
启用压缩的ZFS似乎不会快速更新文件元数据,因此会等待更改显示。
在具有文件asdf
(ZFS文件系统,已启用压缩)/tmp/asdf
(tmpfs文件系统)和/var/tmp/asdf
(ZFS,无压缩)的Solaris 11机箱上运行时,代码生成以下输出:
file: asdf
filesystem: zfs
blocksize: 131072
size: 2228224
blocks: 10
orig blocks: 1
disk space: 5120
file: /tmp/asdf
filesystem: tmpfs
blocksize: 4096
size: 69632
blocks: 136
orig blocks: 0
disk space: 69632
file: /var/tmp/asdf
filesystem: zfs
blocksize: 131072
size: 2228224
blocks: 257
orig blocks: 1
disk space: 131584
从该输出中可以明显看出,/tmp/asdf
位于不支持稀疏文件的文件系统上,/var/tmp/asdf
位于支持此类文件的文件系统中。
普通asdf
完全是另一回事,写入128 kB数据会增加所有9个512字节磁盘块。从那里,你可以推断文件系统中正在进行某种压缩。另外,我怀疑假设任何支持这种本机压缩的文件系统也支持稀疏文件是非常安全的。
在给出文件名或打开文件描述符时,确定文件系统是否支持稀疏文件的最快方法是在文件名上调用stat()
或在文件描述符上调用fstat()
,获取{{1来自st_fstype
的字段,并将文件的文件系统类型与已知支持稀疏文件的一组文件系统类型的字符串进行比较。
答案 1 :(得分:0)
这是一个非常幼稚的CLI交互式测试,但是如果du
和du --apparent
不同,则可以确定文件系统支持稀疏文件。
例如在ext4分区上,当我这样做时:
dd seek=1G if=/dev/zero of=f bs=1 count=1 status=none
du --block-size=1 f
du --block-size=1 --apparent f
它给了我
8192 f
1073741825 f
因此1GB的外观大小文件实际上只占用了8KB,这意味着创建了一个稀疏文件。
另请参阅:why is the output of `du` often so different from `du -b`