]>
git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blob - io/fiemap.c
8482c9920ea3a006f410b319f52244ea7f3e2984
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
21 #include <linux/fiemap.h>
26 static cmdinfo_t fiemap_cmd
;
33 " prints the block mapping for a file's data or attribute forks"
36 " 'fiemap -v' - tabular format verbose map\n"
38 " fiemap prints the map of disk blocks used by the current file.\n"
39 " The map lists each extent used by the file, as well as regions in the\n"
40 " file that do not have any corresponding blocks (holes).\n"
41 " By default, each line of the listing takes the following form:\n"
42 " extent: [startoffset..endoffset]: startblock..endblock\n"
43 " Holes are marked by replacing the startblock..endblock with 'hole'.\n"
44 " All the file offsets and disk blocks are in units of 512-byte blocks.\n"
45 " -a -- prints the attribute fork map instead of the data fork.\n"
46 " -l -- also displays the length of each extent in 512-byte blocks.\n"
47 " -n -- query n extents.\n"
48 " -v -- Verbose information\n"
60 for (len
= 0, tmp
= val
; tmp
> 0; tmp
= tmp
/base
)
62 return (len
== 0 ? 1 : len
);
67 struct fiemap_extent
*extent
,
85 llast
= *last_logical
/ blocksize
;
86 lstart
= extent
->fe_logical
/ blocksize
;
87 len
= extent
->fe_length
/ blocksize
;
88 block
= extent
->fe_physical
/ blocksize
;
90 memset(lbuf
, 0, sizeof(lbuf
));
91 memset(bbuf
, 0, sizeof(bbuf
));
93 if (*cur_extent
== 0) {
94 printf("%4s: %-*s %-*s %*s %*s\n", _("EXT"),
95 foff_w
, _("FILE-OFFSET"),
96 boff_w
, _("BLOCK-RANGE"),
101 if (lstart
!= llast
) {
102 snprintf(lbuf
, sizeof(lbuf
), "[%llu..%llu]:", llast
,
104 printf("%4d: %-*s %-*s %*llu\n", *cur_extent
, foff_w
, lbuf
,
105 boff_w
, _("hole"), tot_w
, lstart
- llast
);
107 memset(lbuf
, 0, sizeof(lbuf
));
110 if ((*cur_extent
+ 1) == max_extents
)
113 snprintf(lbuf
, sizeof(lbuf
), "[%llu..%llu]:", lstart
,
114 lstart
+ len
- 1ULL);
115 snprintf(bbuf
, sizeof(bbuf
), "%llu..%llu", block
, block
+ len
- 1ULL);
116 snprintf(flgbuf
, sizeof(flgbuf
), "0x%x", extent
->fe_flags
);
117 printf("%4d: %-*s %-*s %*llu %*s\n", *cur_extent
, foff_w
, lbuf
,
118 boff_w
, bbuf
, tot_w
, len
, flg_w
, flgbuf
);
121 *last_logical
= extent
->fe_logical
+ extent
->fe_length
;
126 struct fiemap_extent
*extent
,
138 llast
= *last_logical
/ blocksize
;
139 lstart
= extent
->fe_logical
/ blocksize
;
140 len
= extent
->fe_length
/ blocksize
;
141 block
= extent
->fe_physical
/ blocksize
;
143 if (lstart
!= llast
) {
144 printf("\t%d: [%llu..%llu]: hole", *cur_extent
,
145 llast
, lstart
- 1ULL);
147 printf(_(" %llu blocks\n"), lstart
- llast
);
153 if ((*cur_extent
+ 1) == max_extents
)
156 printf("\t%d: [%llu..%llu]: %llu..%llu", *cur_extent
,
157 lstart
, lstart
+ len
- 1ULL, block
,
161 printf(_(" %llu blocks\n"), len
);
165 *last_logical
= extent
->fe_logical
+ extent
->fe_length
;
169 * Calculate the proper extent table format based on first
174 struct fiemap
*fiemap
,
187 struct fiemap_extent
*extent
;
189 for (i
= 0; i
< fiemap
->fm_mapped_extents
; i
++) {
191 extent
= &fiemap
->fm_extents
[i
];
192 logical
= extent
->fe_logical
/ blocksize
;
193 len
= extent
->fe_length
/ blocksize
;
194 block
= extent
->fe_physical
/ blocksize
;
196 snprintf(lbuf
, sizeof(lbuf
), "[%llu..%llu]", logical
,
198 snprintf(bbuf
, sizeof(bbuf
), "%llu..%llu", block
,
200 *foff_w
= max(*foff_w
, strlen(lbuf
));
201 *boff_w
= max(*boff_w
, strlen(bbuf
));
202 *tot_w
= max(*tot_w
, numlen(len
, 10));
203 *flg_w
= max(*flg_w
, numlen(extent
->fe_flags
, 16));
204 if (extent
->fe_flags
& FIEMAP_EXTENT_LAST
)
214 struct fiemap
*fiemap
;
216 int num_extents
= 32;
220 int fiemap_flags
= FIEMAP_FLAG_SYNC
;
226 int foff_w
= 16; /* 16 just for a good minimum range */
228 int tot_w
= 5; /* 5 since its just one number */
230 __u64 blocksize
= 512;
231 __u64 last_logical
= 0;
234 while ((c
= getopt(argc
, argv
, "aln:v")) != EOF
) {
237 fiemap_flags
|= FIEMAP_FLAG_XATTR
;
243 max_extents
= atoi(optarg
);
249 return command_usage(&fiemap_cmd
);
254 num_extents
= min(num_extents
, max_extents
);
255 map_size
= sizeof(struct fiemap
) +
256 (num_extents
* 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
+ 1) != max_extents
)) {
269 num_extents
= min(num_extents
,
270 max_extents
- (cur_extent
+ 1));
272 memset(fiemap
, 0, map_size
);
273 fiemap
->fm_flags
= fiemap_flags
;
274 fiemap
->fm_start
= last_logical
;
275 fiemap
->fm_length
= -1LL;
276 fiemap
->fm_extent_count
= num_extents
;
278 ret
= ioctl(file
->fd
, FS_IOC_FIEMAP
, (unsigned long)fiemap
);
280 fprintf(stderr
, "%s: ioctl(FS_IOC_FIEMAP) [\"%s\"]: "
281 "%s\n", progname
, file
->name
, strerror(errno
));
287 /* No more extents to map, exit */
288 if (!fiemap
->fm_mapped_extents
)
291 for (i
= 0; i
< fiemap
->fm_mapped_extents
; i
++) {
292 struct fiemap_extent
*extent
;
294 extent
= &fiemap
->fm_extents
[i
];
296 if (cur_extent
== 0) {
297 calc_print_format(fiemap
, blocksize
,
302 print_verbose(extent
, blocksize
, foff_w
,
303 boff_w
, tot_w
, flg_w
,
304 max_extents
, &cur_extent
,
307 print_plain(extent
, lflag
, blocksize
,
308 max_extents
, &cur_extent
,
311 if (extent
->fe_flags
& FIEMAP_EXTENT_LAST
) {
316 if ((cur_extent
+ 1) == max_extents
)
321 if ((cur_extent
+ 1) == max_extents
)
324 memset(&st
, 0, sizeof(st
));
325 if (fstat(file
->fd
, &st
)) {
326 fprintf(stderr
, "%s: fstat failed: %s\n", progname
,
333 if (cur_extent
&& last_logical
< st
.st_size
) {
336 snprintf(lbuf
, sizeof(lbuf
), "[%llu..%llu]:",
337 last_logical
/ blocksize
, (st
.st_size
/ blocksize
) - 1);
339 printf("%4d: %-*s %-*s %*llu\n", cur_extent
,
340 foff_w
, lbuf
, boff_w
, _("hole"), tot_w
,
341 (st
.st_size
- last_logical
) / blocksize
);
343 printf("\t%d: %s %s", cur_extent
, lbuf
,
346 printf(_(" %llu blocks\n"),
347 (st
.st_size
- last_logical
) / blocksize
);
361 fiemap_cmd
.name
= "fiemap";
362 fiemap_cmd
.cfunc
= fiemap_f
;
363 fiemap_cmd
.argmin
= 0;
364 fiemap_cmd
.argmax
= -1;
365 fiemap_cmd
.flags
= CMD_NOMAP_OK
| CMD_FOREIGN_OK
;
366 fiemap_cmd
.args
= _("[-alv] [-n nx]");
367 fiemap_cmd
.oneline
= _("print block mapping for a file");
368 fiemap_cmd
.help
= fiemap_help
;
370 add_command(&fiemap_cmd
);