Fallocate System Call

- - | Comments

嵌入式系統的儲存空間相當有限, 如果在下載檔案前, 先把檔案按預期的大小給建立起來, 下載時再來寫入真正的檔案內容, 這樣便能保證不會發生下載到一半卻出現Disk Full的狀況.

Linux系統有個fallocate system call可以讓我們快速建立內容全為0x00的檔案, 相當適合用來處理這樣的問題.

以下的程式會利用fallocate system call, 建立多個1GB大小的file, 直到無法再寫檔為止:

test.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#include <sys/stat.h>
#include <sys/syscall.h>
#include <sys/types.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <ctype.h>
#include <linux/falloc.h>

int main(int argc, char **argv)
{
 FILE* fh ;
 char fname[128] ;
 loff_t  length = 1024*1024*1024 ;
 loff_t  offset = 0 ;
 int falloc_mode = 0 ;
 int error;
 int i ;
 for( i = 0 ; i < 200 ; i ++ )
    {
     sprintf(fname,"./data%04d",i);
     fh = fopen( fname,"w+");
     if(fh)
       {
        error = syscall(SYS_fallocate, fileno(fh), falloc_mode, offset, length);
        if(error < 0)
          {
           printf("[*][error] no space !!!\n");
           perror("fallocate failed");
           exit(EXIT_FAILURE);
          }
        fclose(fh);
       }
    }
 return 0;
}

編譯與執行:

Terminal
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
bramante@matrix:~/test/fallocate$ gcc -o ./test ./test.c
bramante@matrix:~/test/fallocate$ time ./test
[*][error] no space !!!
fallocate failed: Disk quota exceeded

real    0m0.897s
user    0m0.000s
sys     0m0.100s
bramante@matrix:~/test/fallocate$ ll
total 92309096
drwxrwxr-x 2 bramante bramante       4096 Sep  8 19:04 ./
drwxr-xr-x 6 bramante bramante       4096 Sep  8 18:16 ../
-rw-rw-r-- 1 bramante bramante 1073741824 Sep  8 19:04 data0000
-rw-rw-r-- 1 bramante bramante 1073741824 Sep  8 19:04 data0001
-rw-rw-r-- 1 bramante bramante 1073741824 Sep  8 19:04 data0002
-rw-rw-r-- 1 bramante bramante 1073741824 Sep  8 19:04 data0003
-rw-rw-r-- 1 bramante bramante 1073741824 Sep  8 19:04 data0004
-rw-rw-r-- 1 bramante bramante 1073741824 Sep  8 19:04 data0005
-rw-rw-r-- 1 bramante bramante 1073741824 Sep  8 19:04 data0006
-rw-rw-r-- 1 bramante bramante 1073741824 Sep  8 19:04 data0007
-rw-rw-r-- 1 bramante bramante 1073741824 Sep  8 19:04 data0008
-rw-rw-r-- 1 bramante bramante 1073741824 Sep  8 19:04 data0009
-rw-rw-r-- 1 bramante bramante 1073741824 Sep  8 19:04 data0010
-rw-rw-r-- 1 bramante bramante 1073741824 Sep  8 19:04 data0011
-rw-rw-r-- 1 bramante bramante 1073741824 Sep  8 19:04 data0012
-rw-rw-r-- 1 bramante bramante 1073741824 Sep  8 19:04 data0013
-rw-rw-r-- 1 bramante bramante 1073741824 Sep  8 19:04 data0014
-rw-rw-r-- 1 bramante bramante 1073741824 Sep  8 19:04 data0015
-rw-rw-r-- 1 bramante bramante 1073741824 Sep  8 19:04 data0016
-rw-rw-r-- 1 bramante bramante 1073741824 Sep  8 19:04 data0017
-rw-rw-r-- 1 bramante bramante 1073741824 Sep  8 19:04 data0018
-rw-rw-r-- 1 bramante bramante 1073741824 Sep  8 19:04 data0019
-rw-rw-r-- 1 bramante bramante 1073741824 Sep  8 19:04 data0020
-rw-rw-r-- 1 bramante bramante 1073741824 Sep  8 19:04 data0021
-rw-rw-r-- 1 bramante bramante 1073741824 Sep  8 19:04 data0022
-rw-rw-r-- 1 bramante bramante 1073741824 Sep  8 19:04 data0023
-rw-rw-r-- 1 bramante bramante 1073741824 Sep  8 19:04 data0024
-rw-rw-r-- 1 bramante bramante 1073741824 Sep  8 19:04 data0025
-rw-rw-r-- 1 bramante bramante 1073741824 Sep  8 19:04 data0026
-rw-rw-r-- 1 bramante bramante 1073741824 Sep  8 19:04 data0027
-rw-rw-r-- 1 bramante bramante 1073741824 Sep  8 19:04 data0028
-rw-rw-r-- 1 bramante bramante 1073741824 Sep  8 19:04 data0029
-rw-rw-r-- 1 bramante bramante 1073741824 Sep  8 19:04 data0030
-rw-rw-r-- 1 bramante bramante 1073741824 Sep  8 19:04 data0031
-rw-rw-r-- 1 bramante bramante 1073741824 Sep  8 19:04 data0032
-rw-rw-r-- 1 bramante bramante 1073741824 Sep  8 19:04 data0033
-rw-rw-r-- 1 bramante bramante 1073741824 Sep  8 19:04 data0034
-rw-rw-r-- 1 bramante bramante 1073741824 Sep  8 19:04 data0035
-rw-rw-r-- 1 bramante bramante 1073741824 Sep  8 19:04 data0036
-rw-rw-r-- 1 bramante bramante 1073741824 Sep  8 19:04 data0037
-rw-rw-r-- 1 bramante bramante 1073741824 Sep  8 19:04 data0038
-rw-rw-r-- 1 bramante bramante 1073741824 Sep  8 19:04 data0039
-rw-rw-r-- 1 bramante bramante 1073741824 Sep  8 19:04 data0040
-rw-rw-r-- 1 bramante bramante 1073741824 Sep  8 19:04 data0041
-rw-rw-r-- 1 bramante bramante 1073741824 Sep  8 19:04 data0042
-rw-rw-r-- 1 bramante bramante 1073741824 Sep  8 19:04 data0043
-rw-rw-r-- 1 bramante bramante 1073741824 Sep  8 19:04 data0044
-rw-rw-r-- 1 bramante bramante 1073741824 Sep  8 19:04 data0045
-rw-rw-r-- 1 bramante bramante 1073741824 Sep  8 19:04 data0046
-rw-rw-r-- 1 bramante bramante 1073741824 Sep  8 19:04 data0047
-rw-rw-r-- 1 bramante bramante 1073741824 Sep  8 19:04 data0048
-rw-rw-r-- 1 bramante bramante 1073741824 Sep  8 19:04 data0049
-rw-rw-r-- 1 bramante bramante 1073741824 Sep  8 19:04 data0050
-rw-rw-r-- 1 bramante bramante 1073741824 Sep  8 19:04 data0051
-rw-rw-r-- 1 bramante bramante 1073741824 Sep  8 19:04 data0052
-rw-rw-r-- 1 bramante bramante 1073741824 Sep  8 19:04 data0053
-rw-rw-r-- 1 bramante bramante 1073741824 Sep  8 19:04 data0054
-rw-rw-r-- 1 bramante bramante 1073741824 Sep  8 19:04 data0055
-rw-rw-r-- 1 bramante bramante 1073741824 Sep  8 19:04 data0056
-rw-rw-r-- 1 bramante bramante 1073741824 Sep  8 19:04 data0057
-rw-rw-r-- 1 bramante bramante 1073741824 Sep  8 19:04 data0058
-rw-rw-r-- 1 bramante bramante 1073741824 Sep  8 19:04 data0059
-rw-rw-r-- 1 bramante bramante 1073741824 Sep  8 19:04 data0060
-rw-rw-r-- 1 bramante bramante 1073741824 Sep  8 19:04 data0061
-rw-rw-r-- 1 bramante bramante 1073741824 Sep  8 19:04 data0062
-rw-rw-r-- 1 bramante bramante 1073741824 Sep  8 19:04 data0063
-rw-rw-r-- 1 bramante bramante 1073741824 Sep  8 19:04 data0064
-rw-rw-r-- 1 bramante bramante 1073741824 Sep  8 19:04 data0065
-rw-rw-r-- 1 bramante bramante 1073741824 Sep  8 19:04 data0066
-rw-rw-r-- 1 bramante bramante 1073741824 Sep  8 19:04 data0067
-rw-rw-r-- 1 bramante bramante 1073741824 Sep  8 19:04 data0068
-rw-rw-r-- 1 bramante bramante 1073741824 Sep  8 19:04 data0069
-rw-rw-r-- 1 bramante bramante 1073741824 Sep  8 19:04 data0070
-rw-rw-r-- 1 bramante bramante 1073741824 Sep  8 19:04 data0071
-rw-rw-r-- 1 bramante bramante 1073741824 Sep  8 19:04 data0072
-rw-rw-r-- 1 bramante bramante 1073741824 Sep  8 19:04 data0073
-rw-rw-r-- 1 bramante bramante 1073741824 Sep  8 19:04 data0074
-rw-rw-r-- 1 bramante bramante 1073741824 Sep  8 19:04 data0075
-rw-rw-r-- 1 bramante bramante 1073741824 Sep  8 19:04 data0076
-rw-rw-r-- 1 bramante bramante 1073741824 Sep  8 19:04 data0077
-rw-rw-r-- 1 bramante bramante 1073741824 Sep  8 19:04 data0078
-rw-rw-r-- 1 bramante bramante 1073741824 Sep  8 19:04 data0079
-rw-rw-r-- 1 bramante bramante 1073741824 Sep  8 19:04 data0080
-rw-rw-r-- 1 bramante bramante 1073741824 Sep  8 19:04 data0081
-rw-rw-r-- 1 bramante bramante 1073741824 Sep  8 19:04 data0082
-rw-rw-r-- 1 bramante bramante 1073741824 Sep  8 19:04 data0083
-rw-rw-r-- 1 bramante bramante 1073741824 Sep  8 19:04 data0084
-rw-rw-r-- 1 bramante bramante 1073741824 Sep  8 19:04 data0085
-rw-rw-r-- 1 bramante bramante 1073741824 Sep  8 19:04 data0086
-rw-rw-r-- 1 bramante bramante 1073741824 Sep  8 19:04 data0087
-rw-rw-r-- 1 bramante bramante   34848768 Sep  8 19:04 data0088
-rwxrwxr-x 1 bramante bramante       8799 Sep  8 19:04 test*
-rw-rw-r-- 1 bramante bramante        721 Sep  8 19:04 test.c
bramante@matrix:~/test/fallocate$

不到1 sec可以建立出超過88 GB的檔案, 真的是好快, 而且disk quota用盡時, 程式還能順利停下來, 實在是很不錯.

從以下的執行範例, 可以看出建檔與砍檔都很快, 都不用1 sec, 而且檔案的確有內容, 內容都為0x00 :

Terminal
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
bramante@matrix:~/test/fallocate$ time ./test
[*][error] no space !!!
fallocate failed: Disk quota exceeded

real    0m0.741s
user    0m0.000s
sys     0m0.100s
bramante@matrix:~/test/fallocate$ hexdump -C data0087
00000000  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
40000000
bramante@matrix:~/test/fallocate$ hexdump -C data0088
00000000  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
0213a000
bramante@matrix:~/test/fallocate$ hexdump -C data0001
00000000  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
40000000
bramante@matrix:~/test/fallocate$ time rm data0*

real    0m0.864s
user    0m0.004s
sys     0m0.820s
bramante@matrix:~/test/fallocate$

另外要提一下, fallocate其實也可以用來把file裡的內容給刪掉一段, 例如, 刪除file開頭的4096 byte:

syscall(SYS_fallocate, fileno(fh), FALLOC_FL_COLLAPSE_RANGE, 0, 4096);

這個功能滿強大的, 如果能用的話, 刪除檔案裡一些不需要的內容會很快, 只可惜我的Linux server太舊了, 這個功能沒有試成功.

Comments