• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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