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