]>
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 llast
, lstart
- 1ULL);
72 printf(_(" %llu blocks\n"), lstart
- llast
);
76 snprintf(lbuf
, sizeof(lbuf
), "[%llu..%llu]:", llast
,
78 printf("%4d: %-*s %-*s %*llu\n", cur_extent
, foff_w
, lbuf
,
79 boff_w
, _("hole"), tot_w
, lstart
- llast
);
87 struct fiemap_extent
*extent
,
103 llast
= BTOBBT(last_logical
);
104 lstart
= BTOBBT(extent
->fe_logical
);
105 len
= BTOBBT(extent
->fe_length
);
106 block
= BTOBBT(extent
->fe_physical
);
108 memset(lbuf
, 0, sizeof(lbuf
));
109 memset(bbuf
, 0, sizeof(bbuf
));
111 if (cur_extent
== 0) {
112 printf("%4s: %-*s %-*s %*s %*s\n", _("EXT"),
113 foff_w
, _("FILE-OFFSET"),
114 boff_w
, _("BLOCK-RANGE"),
119 if (lstart
!= llast
) {
120 print_hole(foff_w
, boff_w
, tot_w
, cur_extent
, 0, false, llast
,
125 if (cur_extent
== max_extents
)
128 snprintf(lbuf
, sizeof(lbuf
), "[%llu..%llu]:", lstart
,
129 lstart
+ len
- 1ULL);
130 snprintf(bbuf
, sizeof(bbuf
), "%llu..%llu", block
, block
+ len
- 1ULL);
131 snprintf(flgbuf
, sizeof(flgbuf
), "0x%x", extent
->fe_flags
);
132 printf("%4d: %-*s %-*s %*llu %*s\n", cur_extent
, foff_w
, lbuf
,
133 boff_w
, bbuf
, tot_w
, len
, flg_w
, flgbuf
);
140 struct fiemap_extent
*extent
,
150 llast
= BTOBBT(last_logical
);
151 lstart
= BTOBBT(extent
->fe_logical
);
152 len
= BTOBBT(extent
->fe_length
);
153 block
= BTOBBT(extent
->fe_physical
);
155 if (lstart
!= llast
) {
156 print_hole(0, 0, 0, cur_extent
, lflag
, true, llast
, lstart
);
160 if (cur_extent
== max_extents
)
163 printf("\t%d: [%llu..%llu]: %llu..%llu", cur_extent
,
164 lstart
, lstart
+ len
- 1ULL, block
,
168 printf(_(" %llu blocks\n"), len
);
175 * Calculate the proper extent table format based on first
180 struct fiemap
*fiemap
,
192 struct fiemap_extent
*extent
;
194 for (i
= 0; i
< fiemap
->fm_mapped_extents
; i
++) {
196 extent
= &fiemap
->fm_extents
[i
];
197 logical
= BTOBBT(extent
->fe_logical
);
198 len
= BTOBBT(extent
->fe_length
);
199 block
= BTOBBT(extent
->fe_physical
);
201 snprintf(lbuf
, sizeof(lbuf
), "[%llu..%llu]", logical
,
203 snprintf(bbuf
, sizeof(bbuf
), "%llu..%llu", block
,
205 *foff_w
= max(*foff_w
, strlen(lbuf
));
206 *boff_w
= max(*boff_w
, strlen(bbuf
));
207 *tot_w
= max(*tot_w
, numlen(len
, 10));
208 *flg_w
= max(*flg_w
, numlen(extent
->fe_flags
, 16));
209 if (extent
->fe_flags
& FIEMAP_EXTENT_LAST
)
219 struct fiemap
*fiemap
;
223 int fiemap_flags
= FIEMAP_FLAG_SYNC
;
229 int foff_w
= 16; /* 16 just for a good minimum range */
231 int tot_w
= 5; /* 5 since its just one number */
233 __u64 last_logical
= 0;
236 while ((c
= getopt(argc
, argv
, "aln:v")) != EOF
) {
239 fiemap_flags
|= FIEMAP_FLAG_XATTR
;
245 max_extents
= atoi(optarg
);
251 return command_usage(&fiemap_cmd
);
255 map_size
= sizeof(struct fiemap
) +
256 (EXTENT_BATCH
* sizeof(struct fiemap_extent
));
257 fiemap
= malloc(map_size
);
259 fprintf(stderr
, _("%s: malloc of %d bytes failed.\n"),
265 printf("%s:\n", file
->name
);
267 while (!last
&& (cur_extent
!= max_extents
)) {
269 memset(fiemap
, 0, map_size
);
270 fiemap
->fm_flags
= fiemap_flags
;
271 fiemap
->fm_start
= last_logical
;
272 fiemap
->fm_length
= -1LL;
273 fiemap
->fm_extent_count
= EXTENT_BATCH
;
275 ret
= ioctl(file
->fd
, FS_IOC_FIEMAP
, (unsigned long)fiemap
);
277 fprintf(stderr
, "%s: ioctl(FS_IOC_FIEMAP) [\"%s\"]: "
278 "%s\n", progname
, file
->name
, strerror(errno
));
284 /* No more extents to map, exit */
285 if (!fiemap
->fm_mapped_extents
)
288 for (i
= 0; i
< fiemap
->fm_mapped_extents
; i
++) {
289 struct fiemap_extent
*extent
;
292 extent
= &fiemap
->fm_extents
[i
];
294 if (cur_extent
== 0) {
295 calc_print_format(fiemap
, &foff_w
,
300 num_printed
= print_verbose(extent
, foff_w
,
305 num_printed
= print_plain(extent
, lflag
,
309 cur_extent
+= num_printed
;
310 last_logical
= extent
->fe_logical
+ extent
->fe_length
;
312 if (extent
->fe_flags
& FIEMAP_EXTENT_LAST
) {
317 if (cur_extent
== max_extents
)
322 if (cur_extent
== max_extents
)
325 memset(&st
, 0, sizeof(st
));
326 if (fstat(file
->fd
, &st
)) {
327 fprintf(stderr
, "%s: fstat failed: %s\n", progname
,
334 if (cur_extent
&& last_logical
< st
.st_size
)
335 print_hole(foff_w
, boff_w
, tot_w
, cur_extent
, lflag
, !vflag
,
336 BTOBBT(last_logical
), BTOBBT(st
.st_size
));
346 fiemap_cmd
.name
= "fiemap";
347 fiemap_cmd
.cfunc
= fiemap_f
;
348 fiemap_cmd
.argmin
= 0;
349 fiemap_cmd
.argmax
= -1;
350 fiemap_cmd
.flags
= CMD_NOMAP_OK
| CMD_FOREIGN_OK
;
351 fiemap_cmd
.args
= _("[-alv] [-n nx]");
352 fiemap_cmd
.oneline
= _("print block mapping for a file");
353 fiemap_cmd
.help
= fiemap_help
;
355 add_command(&fiemap_cmd
);