]>
git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blob - io/fsmap.c
0bc8ae64bebe660af28ce6f0af4f7ad2bf930b46
1 // SPDX-License-Identifier: GPL-2.0+
3 * Copyright (C) 2017 Oracle. All Rights Reserved.
4 * Author: Darrick J. Wong <darrick.wong@oracle.com>
6 #include "platform_defs.h"
13 static cmdinfo_t fsmap_cmd
;
14 static dev_t xfs_data_dev
;
21 " Prints the block mapping for the filesystem hosting the current file"
23 " fsmap prints the map of disk blocks used by the whole filesystem.\n"
24 " When possible, owner and offset information will be included in the\n"
27 " By default, each line of the listing takes the following form:\n"
28 " extent: major:minor [startblock..endblock]: owner startoffset..endoffset length\n"
29 " The owner field is either an inode number or a special value.\n"
30 " All the file offsets and disk blocks are in units of 512-byte blocks.\n"
31 " -d -- query only the data device (default).\n"
32 " -l -- query only the log device.\n"
33 " -r -- query only the realtime device.\n"
34 " -n -- query n extents at a time.\n"
35 " -m -- output machine-readable format.\n"
36 " -v -- Verbose information, show AG and offsets. Show flags legend on 2nd -v\n"
38 "The optional start and end arguments require one of -d, -l, or -r to be set.\n"
42 #define OWNER_BUF_SZ 32
49 case XFS_FMR_OWN_FREE
:
50 return _("free space");
51 case XFS_FMR_OWN_UNKNOWN
:
54 return _("static fs metadata");
56 return _("journalling log");
58 return _("per-AG metadata");
59 case XFS_FMR_OWN_INOBT
:
60 return _("inode btree");
61 case XFS_FMR_OWN_INODES
:
63 case XFS_FMR_OWN_REFC
:
64 return _("refcount btree");
66 return _("cow reservation");
67 case XFS_FMR_OWN_DEFECTIVE
:
68 return _("defective");
70 snprintf(buf
, OWNER_BUF_SZ
, _("special %u:%u"),
71 FMR_OWNER_TYPE(owner
), FMR_OWNER_CODE(owner
));
78 unsigned long long *nr
,
79 struct fsmap_head
*head
)
83 char owner
[OWNER_BUF_SZ
];
86 for (i
= 0, p
= head
->fmh_recs
; i
< head
->fmh_entries
; i
++, p
++) {
87 printf("\t%llu: %u:%u [%lld..%lld]: ", i
+ (*nr
),
88 major(p
->fmr_device
), minor(p
->fmr_device
),
89 (long long)BTOBBT(p
->fmr_physical
),
90 (long long)BTOBBT(p
->fmr_physical
+ p
->fmr_length
- 1));
91 fork
= (p
->fmr_flags
& FMR_OF_ATTR_FORK
) ? _("attr") : _("data");
92 if (p
->fmr_flags
& FMR_OF_SPECIAL_OWNER
)
93 printf("%s", special_owner(p
->fmr_owner
, owner
));
94 else if (p
->fmr_flags
& FMR_OF_EXTENT_MAP
)
95 printf(_("inode %lld %s extent map"),
96 (long long) p
->fmr_owner
, fork
);
98 printf(_("inode %lld %s %lld..%lld"),
99 (long long)p
->fmr_owner
, fork
,
100 (long long)BTOBBT(p
->fmr_offset
),
101 (long long)BTOBBT(p
->fmr_offset
+ p
->fmr_length
- 1));
103 (long long)BTOBBT(p
->fmr_length
));
106 (*nr
) += head
->fmh_entries
;
111 unsigned long long *nr
,
112 struct fsmap_head
*head
)
114 unsigned long long i
;
118 printf(_("EXT,MAJOR,MINOR,PSTART,PEND,OWNER,OSTART,OEND,LENGTH\n"));
119 for (i
= 0, p
= head
->fmh_recs
; i
< head
->fmh_entries
; i
++, p
++) {
120 printf("%llu,%u,%u,%lld,%lld,", i
+ (*nr
),
121 major(p
->fmr_device
), minor(p
->fmr_device
),
122 (long long)BTOBBT(p
->fmr_physical
),
123 (long long)BTOBBT(p
->fmr_physical
+ p
->fmr_length
- 1));
124 fork
= (p
->fmr_flags
& FMR_OF_ATTR_FORK
) ? "attr" : "data";
125 if (p
->fmr_flags
& FMR_OF_SPECIAL_OWNER
)
126 printf("special_%u:%u,,,", FMR_OWNER_TYPE(p
->fmr_owner
),
127 FMR_OWNER_CODE(p
->fmr_owner
));
128 else if (p
->fmr_flags
& FMR_OF_EXTENT_MAP
)
129 printf(_("inode_%lld_%s_bmbt,,,"),
130 (long long) p
->fmr_owner
, fork
);
132 printf(_("inode_%lld_%s,%lld,%lld,"),
133 (long long)p
->fmr_owner
, fork
,
134 (long long)BTOBBT(p
->fmr_offset
),
135 (long long)BTOBBT(p
->fmr_offset
+ p
->fmr_length
- 1));
137 (long long)BTOBBT(p
->fmr_length
));
140 (*nr
) += head
->fmh_entries
;
144 * Verbose mode displays:
145 * extent: major:minor [startblock..endblock]: startoffset..endoffset \
146 * ag# (agoffset..agendoffset) totalbbs flags
148 #define MINRANGE_WIDTH 16
149 #define MINAG_WIDTH 2
150 #define MINTOT_WIDTH 5
151 #define NFLG 7 /* count of flags */
152 #define FLG_NULL 00000000 /* Null flag */
153 #define FLG_ATTR_FORK 01000000 /* attribute fork */
154 #define FLG_SHARED 00100000 /* shared extent */
155 #define FLG_PRE 00010000 /* Unwritten extent */
156 #define FLG_BSU 00001000 /* Not on begin of stripe unit */
157 #define FLG_ESU 00000100 /* Not on end of stripe unit */
158 #define FLG_BSW 00000010 /* Not on begin of stripe width */
159 #define FLG_ESW 00000001 /* Not on end of stripe width */
162 unsigned long long *nr
,
163 struct fsmap_head
*head
,
165 struct xfs_fsop_geom
*fsgeo
)
167 unsigned long long i
;
170 off64_t agoff
, bperag
;
171 int foff_w
, boff_w
, aoff_w
, tot_w
, agno_w
, own_w
;
173 char rbuf
[40], bbuf
[40], abuf
[40], obuf
[40];
174 char nbuf
[40], dbuf
[40], gbuf
[40];
175 char owner
[OWNER_BUF_SZ
];
179 foff_w
= boff_w
= aoff_w
= own_w
= MINRANGE_WIDTH
;
182 tot_w
= MINTOT_WIDTH
;
183 bperag
= (off64_t
)fsgeo
->agblocks
*
184 (off64_t
)fsgeo
->blocksize
;
185 sunit
= (fsgeo
->sunit
* fsgeo
->blocksize
);
186 swidth
= (fsgeo
->swidth
* fsgeo
->blocksize
);
189 * Go through the extents and figure out the width
190 * needed for all columns.
192 for (i
= 0, p
= head
->fmh_recs
; i
< head
->fmh_entries
; i
++, p
++) {
193 if (p
->fmr_flags
& FMR_OF_PREALLOC
||
194 p
->fmr_flags
& FMR_OF_ATTR_FORK
||
195 p
->fmr_flags
& FMR_OF_SHARED
)
198 (p
->fmr_physical
% sunit
!= 0 ||
199 ((p
->fmr_physical
+ p
->fmr_length
) % sunit
) != 0 ||
200 p
->fmr_physical
% swidth
!= 0 ||
201 ((p
->fmr_physical
+ p
->fmr_length
) % swidth
) != 0))
204 *dumped_flags
= true;
205 snprintf(nbuf
, sizeof(nbuf
), "%llu", (*nr
) + i
);
206 nr_w
= max(nr_w
, strlen(nbuf
));
207 if (head
->fmh_oflags
& FMH_OF_DEV_T
)
208 snprintf(dbuf
, sizeof(dbuf
), "%u:%u",
209 major(p
->fmr_device
),
210 minor(p
->fmr_device
));
212 snprintf(dbuf
, sizeof(dbuf
), "0x%x", p
->fmr_device
);
213 dev_w
= max(dev_w
, strlen(dbuf
));
214 snprintf(bbuf
, sizeof(bbuf
), "[%lld..%lld]:",
215 (long long)BTOBBT(p
->fmr_physical
),
216 (long long)BTOBBT(p
->fmr_physical
+ p
->fmr_length
- 1));
217 boff_w
= max(boff_w
, strlen(bbuf
));
218 if (p
->fmr_flags
& FMR_OF_SPECIAL_OWNER
)
219 own_w
= max(own_w
, strlen(
220 special_owner(p
->fmr_owner
, owner
)));
222 snprintf(obuf
, sizeof(obuf
), "%lld",
223 (long long)p
->fmr_owner
);
224 own_w
= max(own_w
, strlen(obuf
));
226 if (p
->fmr_flags
& FMR_OF_EXTENT_MAP
)
227 foff_w
= max(foff_w
, strlen(_("extent_map")));
228 else if (p
->fmr_flags
& FMR_OF_SPECIAL_OWNER
)
231 snprintf(rbuf
, sizeof(rbuf
), "%lld..%lld",
232 (long long)BTOBBT(p
->fmr_offset
),
233 (long long)BTOBBT(p
->fmr_offset
+ p
->fmr_length
- 1));
234 foff_w
= max(foff_w
, strlen(rbuf
));
236 if (p
->fmr_device
== xfs_data_dev
) {
237 agno
= p
->fmr_physical
/ bperag
;
238 agoff
= p
->fmr_physical
- (agno
* bperag
);
239 snprintf(abuf
, sizeof(abuf
),
241 (long long)BTOBBT(agoff
),
242 (long long)BTOBBT(agoff
+ p
->fmr_length
- 1));
245 aoff_w
= max(aoff_w
, strlen(abuf
));
247 numlen(BTOBBT(p
->fmr_length
), 10));
249 agno_w
= max(MINAG_WIDTH
, numlen(fsgeo
->agcount
, 10));
251 printf("%*s: %-*s %-*s %-*s %-*s %*s %-*s %*s%s\n",
254 boff_w
, _("BLOCK-RANGE"),
256 foff_w
, _("FILE-OFFSET"),
258 aoff_w
, _("AG-OFFSET"),
260 flg
? _(" FLAGS") : "");
261 for (i
= 0, p
= head
->fmh_recs
; i
< head
->fmh_entries
; i
++, p
++) {
263 if (p
->fmr_flags
& FMR_OF_PREALLOC
)
265 if (p
->fmr_flags
& FMR_OF_ATTR_FORK
)
266 flg
|= FLG_ATTR_FORK
;
267 if (p
->fmr_flags
& FMR_OF_SHARED
)
270 * If striping enabled, determine if extent starts/ends
271 * on a stripe unit boundary.
274 if (p
->fmr_physical
% sunit
!= 0)
276 if (((p
->fmr_physical
+
277 p
->fmr_length
) % sunit
) != 0)
279 if (p
->fmr_physical
% swidth
!= 0)
281 if (((p
->fmr_physical
+
282 p
->fmr_length
) % swidth
) != 0)
285 if (head
->fmh_oflags
& FMH_OF_DEV_T
)
286 snprintf(dbuf
, sizeof(dbuf
), "%u:%u",
287 major(p
->fmr_device
),
288 minor(p
->fmr_device
));
290 snprintf(dbuf
, sizeof(dbuf
), "0x%x", p
->fmr_device
);
291 snprintf(bbuf
, sizeof(bbuf
), "[%lld..%lld]:",
292 (long long)BTOBBT(p
->fmr_physical
),
293 (long long)BTOBBT(p
->fmr_physical
+ p
->fmr_length
- 1));
294 if (p
->fmr_flags
& FMR_OF_SPECIAL_OWNER
) {
295 snprintf(obuf
, sizeof(obuf
), "%s",
296 special_owner(p
->fmr_owner
, owner
));
297 snprintf(rbuf
, sizeof(rbuf
), " ");
299 snprintf(obuf
, sizeof(obuf
), "%lld",
300 (long long)p
->fmr_owner
);
301 snprintf(rbuf
, sizeof(rbuf
), "%lld..%lld",
302 (long long)BTOBBT(p
->fmr_offset
),
303 (long long)BTOBBT(p
->fmr_offset
+ p
->fmr_length
- 1));
305 if (p
->fmr_device
== xfs_data_dev
) {
306 agno
= p
->fmr_physical
/ bperag
;
307 agoff
= p
->fmr_physical
- (agno
* bperag
);
308 snprintf(abuf
, sizeof(abuf
),
310 (long long)BTOBBT(agoff
),
311 (long long)BTOBBT(agoff
+ p
->fmr_length
- 1));
312 snprintf(gbuf
, sizeof(gbuf
),
319 if (p
->fmr_flags
& FMR_OF_EXTENT_MAP
)
320 printf("%*llu: %-*s %-*s %-*s %-*s %-*s %-*s %*lld\n",
325 foff_w
, _("extent map"),
328 tot_w
, (long long)BTOBBT(p
->fmr_length
));
330 printf("%*llu: %-*s %-*s %-*s %-*s", nr_w
, (*nr
) + i
,
331 dev_w
, dbuf
, boff_w
, bbuf
, own_w
, obuf
,
333 printf(" %-*s %-*s", agno_w
, gbuf
,
335 printf(" %*lld", tot_w
,
336 (long long)BTOBBT(p
->fmr_length
));
340 printf(" %-*.*o\n", NFLG
, NFLG
, flg
);
344 (*nr
) += head
->fmh_entries
;
348 dump_verbose_key(void)
350 printf(_(" FLAG Values:\n"));
351 printf(_(" %*.*o Attribute fork\n"),
352 NFLG
+1, NFLG
+1, FLG_ATTR_FORK
);
353 printf(_(" %*.*o Shared extent\n"),
354 NFLG
+1, NFLG
+1, FLG_SHARED
);
355 printf(_(" %*.*o Unwritten preallocated extent\n"),
356 NFLG
+1, NFLG
+1, FLG_PRE
);
357 printf(_(" %*.*o Doesn't begin on stripe unit\n"),
358 NFLG
+1, NFLG
+1, FLG_BSU
);
359 printf(_(" %*.*o Doesn't end on stripe unit\n"),
360 NFLG
+1, NFLG
+1, FLG_ESU
);
361 printf(_(" %*.*o Doesn't begin on stripe width\n"),
362 NFLG
+1, NFLG
+1, FLG_BSW
);
363 printf(_(" %*.*o Doesn't end on stripe width\n"),
364 NFLG
+1, NFLG
+1, FLG_ESW
);
373 struct fsmap_head
*nhead
;
374 struct fsmap_head
*head
;
376 struct xfs_fsop_geom fsgeo
;
386 unsigned long long nr
= 0;
387 size_t fsblocksize
, fssectsize
;
389 static bool tab_init
;
390 bool dumped_flags
= false;
391 int dflag
, lflag
, rflag
;
393 init_cvtnum(&fsblocksize
, &fssectsize
);
395 dflag
= lflag
= rflag
= 0;
396 while ((c
= getopt(argc
, argv
, "dlmn:rv")) != EOF
) {
398 case 'd': /* data device */
401 case 'l': /* log device */
404 case 'm': /* machine readable format */
407 case 'n': /* number of extents specified */
408 nflag
= cvt_u32(optarg
, 10);
410 return command_usage(&fsmap_cmd
);
412 case 'r': /* rt device */
415 case 'v': /* Verbose output */
419 return command_usage(&fsmap_cmd
);
423 if ((dflag
+ lflag
+ rflag
> 1) || (mflag
> 0 && vflag
> 0) ||
424 (argc
> optind
&& dflag
+ lflag
+ rflag
== 0))
425 return command_usage(&fsmap_cmd
);
428 start
= cvtnum(fsblocksize
, fssectsize
, argv
[optind
]);
431 _("Bad rmap start_bblock %s.\n"),
438 if (argc
> optind
+ 1) {
439 end
= cvtnum(fsblocksize
, fssectsize
, argv
[optind
+ 1]);
442 _("Bad rmap end_bblock %s.\n"),
450 c
= ioctl(file
->fd
, XFS_IOC_FSGEOMETRY
, &fsgeo
);
453 _("%s: can't get geometry [\"%s\"]: %s\n"),
454 progname
, file
->name
, strerror(errno
));
460 map_size
= nflag
? nflag
: 131072 / sizeof(struct fsmap
);
461 head
= malloc(fsmap_sizeof(map_size
));
463 fprintf(stderr
, _("%s: malloc of %zu bytes failed.\n"),
464 progname
, fsmap_sizeof(map_size
));
469 memset(head
, 0, sizeof(*head
));
471 h
= head
->fmh_keys
+ 1;
473 l
->fmr_device
= h
->fmr_device
= file
->fs_path
.fs_datadev
;
475 l
->fmr_device
= h
->fmr_device
= file
->fs_path
.fs_logdev
;
477 l
->fmr_device
= h
->fmr_device
= file
->fs_path
.fs_rtdev
;
480 h
->fmr_device
= UINT_MAX
;
482 l
->fmr_physical
= start
;
483 h
->fmr_physical
= end
;
484 h
->fmr_owner
= ULLONG_MAX
;
485 h
->fmr_flags
= UINT_MAX
;
486 h
->fmr_offset
= ULLONG_MAX
;
491 i
= ioctl(file
->fd
, FS_IOC_GETFSMAP
, head
);
493 fprintf(stderr
, _("%s: xfsctl(XFS_IOC_GETFSMAP)"
494 " iflags=0x%x [\"%s\"]: %s\n"),
495 progname
, head
->fmh_iflags
, file
->name
,
501 if (head
->fmh_entries
> map_size
+ 2) {
502 map_size
= 11ULL * head
->fmh_entries
/ 10;
503 nmap_size
= map_size
> (1 << 24) ? (1 << 24) : map_size
;
504 nhead
= realloc(head
, fsmap_sizeof(nmap_size
));
507 _("%s: cannot realloc %zu bytes\n"),
508 progname
, fsmap_sizeof(nmap_size
));
511 map_size
= nmap_size
;
517 * If this is an XFS filesystem, remember the data device.
518 * (We report AG number/block for data device extents on XFS).
521 fs_table_initialise(0, NULL
, 0, NULL
);
524 fs
= fs_table_lookup(file
->name
, FS_MOUNT_POINT
);
525 xfs_data_dev
= fs
? fs
->fs_datadev
: 0;
527 head
->fmh_count
= map_size
;
529 /* Get some extents */
530 i
= ioctl(file
->fd
, FS_IOC_GETFSMAP
, head
);
532 fprintf(stderr
, _("%s: xfsctl(XFS_IOC_GETFSMAP)"
533 " iflags=0x%x [\"%s\"]: %s\n"),
534 progname
, head
->fmh_iflags
, file
->name
,
541 if (head
->fmh_entries
== 0)
545 dump_map_verbose(&nr
, head
, &dumped_flags
, &fsgeo
);
547 dump_map_machine(&nr
, head
);
551 p
= &head
->fmh_recs
[head
->fmh_entries
- 1];
552 if (p
->fmr_flags
& FMR_OF_LAST
)
567 fsmap_cmd
.name
= "fsmap";
568 fsmap_cmd
.cfunc
= fsmap_f
;
569 fsmap_cmd
.argmin
= 0;
570 fsmap_cmd
.argmax
= -1;
571 fsmap_cmd
.flags
= CMD_NOMAP_OK
| CMD_FLAG_FOREIGN_OK
;
572 fsmap_cmd
.args
= _("[-d|-l|-r] [-m|-v] [-n nx] [start] [end]");
573 fsmap_cmd
.oneline
= _("print filesystem mapping for a range of blocks");
574 fsmap_cmd
.help
= fsmap_help
;
576 add_command(&fsmap_cmd
);