]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blob - io/prealloc.c
xfs_io: hook up statx
[thirdparty/xfsprogs-dev.git] / io / prealloc.c
1 /*
2 * Copyright (c) 2003-2005 Silicon Graphics, Inc.
3 * All Rights Reserved.
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it would 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, write the Free Software Foundation,
16 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17 */
18
19 #if defined(HAVE_FALLOCATE)
20 #include <linux/falloc.h>
21 #endif
22 #include "command.h"
23 #include "input.h"
24 #include "init.h"
25 #include "io.h"
26
27 #ifndef FALLOC_FL_PUNCH_HOLE
28 #define FALLOC_FL_PUNCH_HOLE 0x02
29 #endif
30
31 #ifndef FALLOC_FL_COLLAPSE_RANGE
32 #define FALLOC_FL_COLLAPSE_RANGE 0x08
33 #endif
34
35 #ifndef FALLOC_FL_ZERO_RANGE
36 #define FALLOC_FL_ZERO_RANGE 0x10
37 #endif
38
39 #ifndef FALLOC_FL_INSERT_RANGE
40 #define FALLOC_FL_INSERT_RANGE 0x20
41 #endif
42
43 #ifndef FALLOC_FL_UNSHARE_RANGE
44 #define FALLOC_FL_UNSHARE_RANGE 0x40
45 #endif
46
47 static cmdinfo_t allocsp_cmd;
48 static cmdinfo_t freesp_cmd;
49 static cmdinfo_t resvsp_cmd;
50 static cmdinfo_t unresvsp_cmd;
51 static cmdinfo_t zero_cmd;
52 #if defined(HAVE_FALLOCATE)
53 static cmdinfo_t falloc_cmd;
54 static cmdinfo_t fpunch_cmd;
55 static cmdinfo_t fcollapse_cmd;
56 static cmdinfo_t finsert_cmd;
57 static cmdinfo_t fzero_cmd;
58 #endif
59
60 static int
61 offset_length(
62 char *offset,
63 char *length,
64 xfs_flock64_t *segment)
65 {
66 size_t blocksize, sectsize;
67
68 init_cvtnum(&blocksize, &sectsize);
69 memset(segment, 0, sizeof(*segment));
70 segment->l_whence = SEEK_SET;
71 segment->l_start = cvtnum(blocksize, sectsize, offset);
72 if (segment->l_start < 0) {
73 printf(_("non-numeric offset argument -- %s\n"), offset);
74 return 0;
75 }
76 segment->l_len = cvtnum(blocksize, sectsize, length);
77 if (segment->l_len < 0) {
78 printf(_("non-numeric length argument -- %s\n"), length);
79 return 0;
80 }
81 return 1;
82 }
83
84 static int
85 allocsp_f(
86 int argc,
87 char **argv)
88 {
89 xfs_flock64_t segment;
90
91 if (!offset_length(argv[1], argv[2], &segment))
92 return 0;
93
94 if (xfsctl(file->name, file->fd, XFS_IOC_ALLOCSP64, &segment) < 0) {
95 perror("XFS_IOC_ALLOCSP64");
96 return 0;
97 }
98 return 0;
99 }
100
101 static int
102 freesp_f(
103 int argc,
104 char **argv)
105 {
106 xfs_flock64_t segment;
107
108 if (!offset_length(argv[1], argv[2], &segment))
109 return 0;
110
111 if (xfsctl(file->name, file->fd, XFS_IOC_FREESP64, &segment) < 0) {
112 perror("XFS_IOC_FREESP64");
113 return 0;
114 }
115 return 0;
116 }
117
118 static int
119 resvsp_f(
120 int argc,
121 char **argv)
122 {
123 xfs_flock64_t segment;
124
125 if (!offset_length(argv[1], argv[2], &segment))
126 return 0;
127
128 if (xfsctl(file->name, file->fd, XFS_IOC_RESVSP64, &segment) < 0) {
129 perror("XFS_IOC_RESVSP64");
130 return 0;
131 }
132 return 0;
133 }
134
135 static int
136 unresvsp_f(
137 int argc,
138 char **argv)
139 {
140 xfs_flock64_t segment;
141
142 if (!offset_length(argv[1], argv[2], &segment))
143 return 0;
144
145 if (xfsctl(file->name, file->fd, XFS_IOC_UNRESVSP64, &segment) < 0) {
146 perror("XFS_IOC_UNRESVSP64");
147 return 0;
148 }
149 return 0;
150 }
151
152 static int
153 zero_f(
154 int argc,
155 char **argv)
156 {
157 xfs_flock64_t segment;
158
159 if (!offset_length(argv[1], argv[2], &segment))
160 return 0;
161
162 if (xfsctl(file->name, file->fd, XFS_IOC_ZERO_RANGE, &segment) < 0) {
163 perror("XFS_IOC_ZERO_RANGE");
164 return 0;
165 }
166 return 0;
167 }
168
169
170 #if defined (HAVE_FALLOCATE)
171 static void
172 falloc_help(void)
173 {
174 printf(_(
175 "\n"
176 " modifies space associated with part of a file via fallocate"
177 "\n"
178 " Example:\n"
179 " 'falloc 0 1m' - fills all holes within the first megabyte\n"
180 "\n"
181 " falloc uses the fallocate system call to alter space allocations in the\n"
182 " open file. The following operations are supported:\n"
183 " All the file offsets are in units of bytes.\n"
184 " -c -- collapses the given range.\n"
185 " -i -- inserts a hole into the given range of the file.\n"
186 " -k -- do not change file size.\n"
187 " -p -- unmap the given range from the file.\n"
188 " -u -- unshare shared extents in the given range.\n"
189 "\n"));
190 }
191
192 static int
193 fallocate_f(
194 int argc,
195 char **argv)
196 {
197 xfs_flock64_t segment;
198 int mode = 0;
199 int c;
200
201 while ((c = getopt(argc, argv, "cikpu")) != EOF) {
202 switch (c) {
203 case 'c':
204 mode = FALLOC_FL_COLLAPSE_RANGE;
205 break;
206 case 'i':
207 mode = FALLOC_FL_INSERT_RANGE;
208 break;
209 case 'k':
210 mode = FALLOC_FL_KEEP_SIZE;
211 break;
212 case 'p':
213 mode = FALLOC_FL_PUNCH_HOLE|FALLOC_FL_KEEP_SIZE;
214 break;
215 case 'u':
216 mode = FALLOC_FL_UNSHARE_RANGE;
217 break;
218 default:
219 command_usage(&falloc_cmd);
220 }
221 }
222 if (optind != argc - 2)
223 return command_usage(&falloc_cmd);
224
225 if (!offset_length(argv[optind], argv[optind+1], &segment))
226 return 0;
227
228 if (fallocate(file->fd, mode,
229 segment.l_start, segment.l_len)) {
230 perror("fallocate");
231 return 0;
232 }
233 return 0;
234 }
235
236 static int
237 fpunch_f(
238 int argc,
239 char **argv)
240 {
241 xfs_flock64_t segment;
242 int mode = FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE;
243
244 if (!offset_length(argv[1], argv[2], &segment))
245 return 0;
246
247 if (fallocate(file->fd, mode,
248 segment.l_start, segment.l_len)) {
249 perror("fallocate");
250 return 0;
251 }
252 return 0;
253 }
254
255 static int
256 fcollapse_f(
257 int argc,
258 char **argv)
259 {
260 xfs_flock64_t segment;
261 int mode = FALLOC_FL_COLLAPSE_RANGE;
262
263 if (!offset_length(argv[1], argv[2], &segment))
264 return 0;
265
266 if (fallocate(file->fd, mode,
267 segment.l_start, segment.l_len)) {
268 perror("fallocate");
269 return 0;
270 }
271 return 0;
272 }
273
274 static int
275 finsert_f(
276 int argc,
277 char **argv)
278 {
279 xfs_flock64_t segment;
280 int mode = FALLOC_FL_INSERT_RANGE;
281
282 if (!offset_length(argv[1], argv[2], &segment))
283 return 0;
284
285 if (fallocate(file->fd, mode,
286 segment.l_start, segment.l_len)) {
287 perror("fallocate");
288 return 0;
289 }
290 return 0;
291 }
292
293 static int
294 fzero_f(
295 int argc,
296 char **argv)
297 {
298 xfs_flock64_t segment;
299 int mode = FALLOC_FL_ZERO_RANGE;
300 int index = 1;
301
302 if (strncmp(argv[index], "-k", 3) == 0) {
303 mode |= FALLOC_FL_KEEP_SIZE;
304 index++;
305 }
306
307 if (!offset_length(argv[index], argv[index + 1], &segment))
308 return 0;
309
310 if (fallocate(file->fd, mode,
311 segment.l_start, segment.l_len)) {
312 perror("fallocate");
313 return 0;
314 }
315 return 0;
316 }
317
318 static int
319 funshare_f(
320 int argc,
321 char **argv)
322 {
323 xfs_flock64_t segment;
324 int mode = FALLOC_FL_UNSHARE_RANGE;
325 int index = 1;
326
327 if (!offset_length(argv[index], argv[index + 1], &segment))
328 return 0;
329
330 if (fallocate(file->fd, mode,
331 segment.l_start, segment.l_len)) {
332 perror("fallocate");
333 return 0;
334 }
335 return 0;
336 }
337 #endif /* HAVE_FALLOCATE */
338
339 void
340 prealloc_init(void)
341 {
342 allocsp_cmd.name = "allocsp";
343 allocsp_cmd.cfunc = allocsp_f;
344 allocsp_cmd.argmin = 2;
345 allocsp_cmd.argmax = 2;
346 allocsp_cmd.flags = CMD_NOMAP_OK;
347 allocsp_cmd.args = _("off len");
348 allocsp_cmd.oneline = _("allocates zeroed space for part of a file");
349
350 freesp_cmd.name = "freesp";
351 freesp_cmd.cfunc = freesp_f;
352 freesp_cmd.argmin = 2;
353 freesp_cmd.argmax = 2;
354 freesp_cmd.flags = CMD_NOMAP_OK;
355 freesp_cmd.args = _("off len");
356 freesp_cmd.oneline = _("frees space associated with part of a file");
357
358 resvsp_cmd.name = "resvsp";
359 resvsp_cmd.cfunc = resvsp_f;
360 resvsp_cmd.argmin = 2;
361 resvsp_cmd.argmax = 2;
362 resvsp_cmd.flags = CMD_NOMAP_OK | CMD_FOREIGN_OK;
363 resvsp_cmd.args = _("off len");
364 resvsp_cmd.oneline =
365 _("reserves space associated with part of a file");
366
367 unresvsp_cmd.name = "unresvsp";
368 unresvsp_cmd.cfunc = unresvsp_f;
369 unresvsp_cmd.argmin = 2;
370 unresvsp_cmd.argmax = 2;
371 unresvsp_cmd.args = _("off len");
372 unresvsp_cmd.flags = CMD_NOMAP_OK;
373 unresvsp_cmd.oneline =
374 _("frees reserved space associated with part of a file");
375
376 zero_cmd.name = "zero";
377 zero_cmd.cfunc = zero_f;
378 zero_cmd.argmin = 2;
379 zero_cmd.argmax = 2;
380 zero_cmd.flags = CMD_NOMAP_OK;
381 zero_cmd.args = _("off len");
382 zero_cmd.oneline =
383 _("Converts the given range of a file to allocated zeros");
384
385 add_command(&allocsp_cmd);
386 add_command(&freesp_cmd);
387 add_command(&resvsp_cmd);
388 add_command(&unresvsp_cmd);
389 add_command(&zero_cmd);
390
391 #if defined (HAVE_FALLOCATE)
392 falloc_cmd.name = "falloc";
393 falloc_cmd.cfunc = fallocate_f;
394 falloc_cmd.argmin = 2;
395 falloc_cmd.argmax = -1;
396 falloc_cmd.flags = CMD_NOMAP_OK | CMD_FOREIGN_OK;
397 falloc_cmd.args = _("[-c] [-k] [-p] [-u] off len");
398 falloc_cmd.oneline =
399 _("allocates space associated with part of a file via fallocate");
400 falloc_cmd.help = falloc_help;
401 add_command(&falloc_cmd);
402
403 fpunch_cmd.name = "fpunch";
404 fpunch_cmd.cfunc = fpunch_f;
405 fpunch_cmd.argmin = 2;
406 fpunch_cmd.argmax = 2;
407 fpunch_cmd.flags = CMD_NOMAP_OK | CMD_FOREIGN_OK;
408 fpunch_cmd.args = _("off len");
409 fpunch_cmd.oneline =
410 _("de-allocates space assocated with part of a file via fallocate");
411 add_command(&fpunch_cmd);
412
413 fcollapse_cmd.name = "fcollapse";
414 fcollapse_cmd.cfunc = fcollapse_f;
415 fcollapse_cmd.argmin = 2;
416 fcollapse_cmd.argmax = 2;
417 fcollapse_cmd.flags = CMD_NOMAP_OK | CMD_FOREIGN_OK;
418 fcollapse_cmd.args = _("off len");
419 fcollapse_cmd.oneline =
420 _("de-allocates space and eliminates the hole by shifting extents");
421 add_command(&fcollapse_cmd);
422
423 finsert_cmd.name = "finsert";
424 finsert_cmd.cfunc = finsert_f;
425 finsert_cmd.argmin = 2;
426 finsert_cmd.argmax = 2;
427 finsert_cmd.flags = CMD_NOMAP_OK | CMD_FOREIGN_OK;
428 finsert_cmd.args = _("off len");
429 finsert_cmd.oneline =
430 _("creates new space for writing within file by shifting extents");
431 add_command(&finsert_cmd);
432
433 fzero_cmd.name = "fzero";
434 fzero_cmd.cfunc = fzero_f;
435 fzero_cmd.argmin = 2;
436 fzero_cmd.argmax = 3;
437 fzero_cmd.flags = CMD_NOMAP_OK | CMD_FOREIGN_OK;
438 fzero_cmd.args = _("[-k] off len");
439 fzero_cmd.oneline =
440 _("zeroes space and eliminates holes by preallocating");
441 add_command(&fzero_cmd);
442
443 fzero_cmd.name = "funshare";
444 fzero_cmd.cfunc = funshare_f;
445 fzero_cmd.argmin = 2;
446 fzero_cmd.argmax = 2;
447 fzero_cmd.flags = CMD_NOMAP_OK | CMD_FOREIGN_OK;
448 fzero_cmd.args = _("off len");
449 fzero_cmd.oneline =
450 _("unshares shared blocks within the range");
451 add_command(&fzero_cmd);
452 #endif /* HAVE_FALLOCATE */
453 }