]>
git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blob - io/fiemap.c
2 * Copyright (c) 2010 Red Hat, Inc.
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.
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.
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
19 #include "platform_defs.h"
22 #include <linux/fiemap.h>
26 #define EXTENT_BATCH 32
28 static cmdinfo_t fiemap_cmd
;
29 static int max_extents
= -1;
36 " prints the block mapping for a file's data or attribute forks"
39 " 'fiemap -v' - tabular format verbose map\n"
41 " fiemap prints the map of disk blocks used by the current file.\n"
42 " The map lists each extent used by the file, as well as regions in the\n"
43 " file that do not have any corresponding blocks (holes).\n"
44 " By default, each line of the listing takes the following form:\n"
45 " extent: [startoffset..endoffset]: startblock..endblock\n"
46 " Holes are marked by replacing the startblock..endblock with 'hole'.\n"
47 " All the file offsets and disk blocks are in units of 512-byte blocks.\n"
48 " -a -- prints the attribute fork map instead of the data fork.\n"
49 " -l -- also displays the length of each extent in 512-byte blocks.\n"
50 " -n -- query n extents.\n"
51 " -v -- Verbose information\n"
69 printf("\t%d: [%llu..%llu]: hole", cur_extent
,
70 (unsigned long long)llast
, lstart
- 1ULL);
72 printf(_(" %llu blocks\n"),
73 (unsigned long long)lstart
- llast
);
77 snprintf(lbuf
, sizeof(lbuf
), "[%llu..%llu]:",
78 (unsigned long long)llast
, lstart
- 1ULL);
79 printf("%4d: %-*s %-*s %*llu\n", cur_extent
, foff_w
, lbuf
,
80 boff_w
, _("hole"), tot_w
,
81 (unsigned long long)lstart
- llast
);
89 struct fiemap_extent
*extent
,
105 llast
= BTOBBT(last_logical
);
106 lstart
= BTOBBT(extent
->fe_logical
);
107 len
= BTOBBT(extent
->fe_length
);
108 block
= BTOBBT(extent
->fe_physical
);
110 memset(lbuf
, 0, sizeof(lbuf
));
111 memset(bbuf
, 0, sizeof(bbuf
));
113 if (cur_extent
== 0) {
114 printf("%4s: %-*s %-*s %*s %*s\n", _("EXT"),
115 foff_w
, _("FILE-OFFSET"),
116 boff_w
, _("BLOCK-RANGE"),
121 if (lstart
!= llast
) {
122 print_hole(foff_w
, boff_w
, tot_w
, cur_extent
, 0, false, llast
,
127 if (cur_extent
== max_extents
)
130 snprintf(lbuf
, sizeof(lbuf
), "[%llu..%llu]:",
131 (unsigned long long)lstart
, lstart
+ len
- 1ULL);
132 snprintf(bbuf
, sizeof(bbuf
), "%llu..%llu",
133 (unsigned long long)block
, block
+ len
- 1ULL);
134 snprintf(flgbuf
, sizeof(flgbuf
), "0x%x", extent
->fe_flags
);
135 printf("%4d: %-*s %-*s %*llu %*s\n", cur_extent
, foff_w
, lbuf
,
136 boff_w
, bbuf
, tot_w
, (unsigned long long)len
, flg_w
, flgbuf
);
143 struct fiemap_extent
*extent
,
153 llast
= BTOBBT(last_logical
);
154 lstart
= BTOBBT(extent
->fe_logical
);
155 len
= BTOBBT(extent
->fe_length
);
156 block
= BTOBBT(extent
->fe_physical
);
158 if (lstart
!= llast
) {
159 print_hole(0, 0, 0, cur_extent
, lflag
, true, llast
, lstart
);
163 if (cur_extent
== max_extents
)
166 printf("\t%d: [%llu..%llu]: %llu..%llu", cur_extent
,
167 (unsigned long long)lstart
, lstart
+ len
- 1ULL,
168 (unsigned long long)block
, block
+ len
- 1ULL);
171 printf(_(" %llu blocks\n"), (unsigned long long)len
);
178 * Calculate the proper extent table format based on first
183 struct fiemap
*fiemap
,
195 struct fiemap_extent
*extent
;
197 for (i
= 0; i
< fiemap
->fm_mapped_extents
; i
++) {
199 extent
= &fiemap
->fm_extents
[i
];
200 logical
= BTOBBT(extent
->fe_logical
);
201 len
= BTOBBT(extent
->fe_length
);
202 block
= BTOBBT(extent
->fe_physical
);
204 snprintf(lbuf
, sizeof(lbuf
), "[%llu..%llu]",
205 (unsigned long long)logical
,
206 (unsigned long long)logical
+ len
- 1);
207 snprintf(bbuf
, sizeof(bbuf
), "%llu..%llu",
208 (unsigned long long)block
,
209 (unsigned long long)block
+ len
- 1);
210 *foff_w
= max(*foff_w
, strlen(lbuf
));
211 *boff_w
= max(*boff_w
, strlen(bbuf
));
212 *tot_w
= max(*tot_w
, numlen(len
, 10));
213 *flg_w
= max(*flg_w
, numlen(extent
->fe_flags
, 16));
214 if (extent
->fe_flags
& FIEMAP_EXTENT_LAST
)
224 struct fiemap
*fiemap
;
228 int fiemap_flags
= FIEMAP_FLAG_SYNC
;
234 int foff_w
= 16; /* 16 just for a good minimum range */
236 int tot_w
= 5; /* 5 since its just one number */
238 __u64 last_logical
= 0;
241 while ((c
= getopt(argc
, argv
, "aln:v")) != EOF
) {
244 fiemap_flags
|= FIEMAP_FLAG_XATTR
;
250 max_extents
= atoi(optarg
);
256 return command_usage(&fiemap_cmd
);
260 map_size
= sizeof(struct fiemap
) +
261 (EXTENT_BATCH
* sizeof(struct fiemap_extent
));
262 fiemap
= malloc(map_size
);
264 fprintf(stderr
, _("%s: malloc of %d bytes failed.\n"),
270 printf("%s:\n", file
->name
);
272 while (!last
&& (cur_extent
!= max_extents
)) {
274 memset(fiemap
, 0, map_size
);
275 fiemap
->fm_flags
= fiemap_flags
;
276 fiemap
->fm_start
= last_logical
;
277 fiemap
->fm_length
= -1LL;
278 fiemap
->fm_extent_count
= EXTENT_BATCH
;
280 ret
= ioctl(file
->fd
, FS_IOC_FIEMAP
, (unsigned long)fiemap
);
282 fprintf(stderr
, "%s: ioctl(FS_IOC_FIEMAP) [\"%s\"]: "
283 "%s\n", progname
, file
->name
, strerror(errno
));
289 /* No more extents to map, exit */
290 if (!fiemap
->fm_mapped_extents
)
293 for (i
= 0; i
< fiemap
->fm_mapped_extents
; i
++) {
294 struct fiemap_extent
*extent
;
297 extent
= &fiemap
->fm_extents
[i
];
299 if (cur_extent
== 0) {
300 calc_print_format(fiemap
, &foff_w
,
305 num_printed
= print_verbose(extent
, foff_w
,
310 num_printed
= print_plain(extent
, lflag
,
314 cur_extent
+= num_printed
;
315 last_logical
= extent
->fe_logical
+ extent
->fe_length
;
317 if (extent
->fe_flags
& FIEMAP_EXTENT_LAST
) {
322 if (cur_extent
== max_extents
)
327 if (cur_extent
== max_extents
)
330 memset(&st
, 0, sizeof(st
));
331 if (fstat(file
->fd
, &st
)) {
332 fprintf(stderr
, "%s: fstat failed: %s\n", progname
,
339 if (cur_extent
&& last_logical
< st
.st_size
)
340 print_hole(foff_w
, boff_w
, tot_w
, cur_extent
, lflag
, !vflag
,
341 BTOBBT(last_logical
), BTOBBT(st
.st_size
));
351 fiemap_cmd
.name
= "fiemap";
352 fiemap_cmd
.cfunc
= fiemap_f
;
353 fiemap_cmd
.argmin
= 0;
354 fiemap_cmd
.argmax
= -1;
355 fiemap_cmd
.flags
= CMD_NOMAP_OK
| CMD_FOREIGN_OK
;
356 fiemap_cmd
.args
= _("[-alv] [-n nx]");
357 fiemap_cmd
.oneline
= _("print block mapping for a file");
358 fiemap_cmd
.help
= fiemap_help
;
360 add_command(&fiemap_cmd
);