1 /*
2 * Copyright (c) 2017 Cyril Hrubis <chrubis@suse.cz>
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18 /*
19 * Tests that writing to fallocated file works when filesystem is full.
20 */
21
22 #define _GNU_SOURCE
23
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <errno.h>
27 #include <fcntl.h>
28 #include "tst_test.h"
29 #include "lapi/fallocate.h"
30
31 #define MNTPOINT "mntpoint"
32 #define FALLOCATE_SIZE 8192
33 #define TESTED_FLAGS "fallocate(FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE)"
34
35 static int fd;
36
run(void)37 static void run(void)
38 {
39 char buf[FALLOCATE_SIZE];
40 ssize_t ret;
41
42 fd = SAFE_OPEN(MNTPOINT "/test_file", O_WRONLY | O_CREAT);
43
44 if (fallocate(fd, 0, 0, FALLOCATE_SIZE)) {
45 if (errno == EOPNOTSUPP) {
46 tst_res(TCONF | TERRNO, "fallocate() not supported");
47 SAFE_CLOSE(fd);
48 return;
49 }
50
51 tst_brk(TBROK | TERRNO,
52 "fallocate(fd, 0, 0, %i)", FALLOCATE_SIZE);
53 }
54
55 tst_fill_fs(MNTPOINT, 1);
56
57 ret = write(fd, buf, sizeof(buf));
58
59 if (ret < 0)
60 tst_res(TFAIL | TERRNO, "write() failed unexpectedly");
61 else
62 tst_res(TPASS, "write() wrote %zu bytes", ret);
63
64 ret = fallocate(fd, 0, FALLOCATE_SIZE, FALLOCATE_SIZE);
65 if (ret != -1)
66 tst_brk(TFAIL, "fallocate() succeeded unexpectedly");
67
68 if (errno != ENOSPC)
69 tst_brk(TFAIL | TERRNO, "fallocate() should fail with ENOSPC");
70
71 tst_res(TPASS | TERRNO, "fallocate() on full FS");
72
73 ret = fallocate(fd, FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE, 0, FALLOCATE_SIZE);
74 if (ret == -1) {
75 if (errno == EOPNOTSUPP)
76 tst_brk(TCONF, TESTED_FLAGS);
77
78 tst_brk(TBROK | TERRNO, TESTED_FLAGS);
79 }
80 tst_res(TPASS, TESTED_FLAGS);
81
82 ret = write(fd, buf, 10);
83 if (ret == -1)
84 tst_res(TFAIL | TERRNO, "write()");
85 else
86 tst_res(TPASS, "write()");
87
88 SAFE_CLOSE(fd);
89 }
90
cleanup(void)91 static void cleanup(void)
92 {
93 if (fd > 0)
94 SAFE_CLOSE(fd);
95 }
96
97 static struct tst_test test = {
98 .needs_root = 1,
99 .needs_tmpdir = 1,
100 .mount_device = 1,
101 .mntpoint = MNTPOINT,
102 .all_filesystems = 1,
103 .cleanup = cleanup,
104 .test_all = run,
105 };
106