]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blobdiff - io/bmap.c
xfsprogs: document environment variables
[thirdparty/xfsprogs-dev.git] / io / bmap.c
index 75fc32e9d7d9774275e348e2c8ad77c6d95a784d..f917831b8a0560e1ecf94f071b883bae0f38e0d9 100644 (file)
--- a/io/bmap.c
+++ b/io/bmap.c
@@ -1,37 +1,12 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
- * Copyright (c) 2000-2004 Silicon Graphics, Inc.  All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- *
- * Further, this software is distributed without any warranty that it is
- * free of the rightful claim of any third person regarding infringement
- * or the like.  Any license provided herein, whether implied or
- * otherwise, applies only to this software file.  Patent licenses, if
- * any, provided herein do not apply to combinations of this program with
- * other software, or any other product whatsoever.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write the Free Software Foundation, Inc., 59
- * Temple Place - Suite 330, Boston MA 02111-1307, USA.
- *
- * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
- * Mountain View, CA  94043, or:
- *
- * http://www.sgi.com
- *
- * For further information regarding this notice, see:
- *
- * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+ * Copyright (c) 2000-2005 Silicon Graphics, Inc.
+ * All Rights Reserved.
  */
 
-#include <xfs/libxfs.h>
+#include "platform_defs.h"
 #include "command.h"
+#include "input.h"
 #include "init.h"
 #include "io.h"
 
@@ -55,25 +30,19 @@ bmap_help(void)
 " Holes are marked by replacing the startblock..endblock with 'hole'.\n"
 " All the file offsets and disk blocks are in units of 512-byte blocks.\n"
 " -a -- prints the attribute fork map instead of the data fork.\n"
+" -c -- prints the copy-on-write fork map instead of the data fork.\n"
+"       This works only if the kernel was compiled in debug mode.\n"
 " -d -- suppresses a DMAPI read event, offline portions shown as holes.\n"
+" -e -- print delayed allocation extents.\n"
 " -l -- also displays the length of each extent in 512-byte blocks.\n"
+" -n -- query n extents.\n"
+" -p -- obtain all unwritten extents as well (w/ -v show which are unwritten.)\n"
+" -v -- Verbose information, specify ag info.  Show flags legend on 2nd -v\n"
 " Note: the bmap for non-regular files can be obtained provided the file\n"
 " was opened appropriately (in particular, must be opened read-only).\n"
 "\n"));
 }
 
-static int
-numlen(
-       off64_t val)
-{
-       off64_t tmp;
-       int     len;
-
-       for (len = 0, tmp = val; tmp > 0; tmp = tmp/10)
-               len++;
-       return (len == 0 ? 1 : len);
-}
-
 int
 bmap_f(
        int                     argc,
@@ -86,19 +55,30 @@ bmap_f(
        int                     loop = 0;
        int                     flg = 0;
        int                     aflag = 0;
+       int                     cflag = 0;
        int                     lflag = 0;
        int                     nflag = 0;
+       int                     pflag = 0;
        int                     vflag = 0;
+       int                     is_rt = 0;
        int                     bmv_iflags = 0; /* flags for XFS_IOC_GETBMAPX */
        int                     i = 0;
        int                     c;
+       int                     egcnt;
 
-       while ((c = getopt(argc, argv, "adln:pv")) != EOF) {
+       while ((c = getopt(argc, argv, "acdeln:pv")) != EOF) {
                switch (c) {
                case 'a':       /* Attribute fork. */
                        bmv_iflags |= BMV_IF_ATTRFORK;
                        aflag = 1;
                        break;
+               case 'c':       /* CoW fork. */
+                       bmv_iflags |= BMV_IF_COWFORK | BMV_IF_DELALLOC;
+                       cflag = 1;
+                       break;
+               case 'e':
+                       bmv_iflags |= BMV_IF_DELALLOC;
+                       break;
                case 'l':       /* list number of blocks with each extent */
                        lflag = 1;
                        break;
@@ -111,6 +91,7 @@ bmap_f(
                        break;
                case 'p':
                /* report unwritten preallocated blocks */
+                       pflag = 1;
                        bmv_iflags |= BMV_IF_PREALLOC;
                        break;
                case 'v':       /* Verbose output */
@@ -120,7 +101,7 @@ bmap_f(
                        return command_usage(&bmap_cmd);
                }
        }
-       if (aflag)
+       if (aflag || cflag)
                bmv_iflags &= ~(BMV_IF_PREALLOC|BMV_IF_NO_DMAPI_READ);
 
        if (vflag) {
@@ -132,7 +113,7 @@ bmap_f(
                        exitcode = 1;
                        return 0;
                }
-               c = xfsctl(file->name, file->fd, XFS_IOC_FSGETXATTR, &fsx);
+               c = xfsctl(file->name, file->fd, FS_IOC_FSGETXATTR, &fsx);
                if (c < 0) {
                        fprintf(stderr,
                                _("%s: cannot read attrs on \"%s\": %s\n"),
@@ -141,16 +122,16 @@ bmap_f(
                        return 0;
                }
 
-               if (fsx.fsx_xflags == XFS_XFLAG_REALTIME) {
+               if (fsx.fsx_xflags == FS_XFLAG_REALTIME) {
                        /*
                         * ag info not applicable to rt, continue
                         * without ag output.
                         */
-                       vflag = 0;
+                       is_rt = 1;
                }
        }
 
-       map_size = nflag ? nflag+1 : 32;        /* initial guess - 256 */
+       map_size = nflag ? nflag+2 : 32;        /* initial guess - 32 */
        map = malloc(map_size*sizeof(*map));
        if (map == NULL) {
                fprintf(stderr, _("%s: malloc of %d bytes failed.\n"),
@@ -161,10 +142,10 @@ bmap_f(
 
 
 /*     Try the xfsctl(XFS_IOC_GETBMAPX) for the number of extents specified
- *     by nflag, or the initial guess number of extents (256).
+ *     by nflag, or the initial guess number of extents (32).
  *
  *     If there are more extents than we guessed, use xfsctl
- *     (XFS_IOC_FSGETXATTR[A]) to get the extent count, realloc some more
+ *     (FS_IOC_FSGETXATTR[A]) to get the extent count, realloc some more
  *     space based on this count, and try again.
  *
  *     If the initial FGETBMAPX attempt returns EINVAL, this may mean
@@ -172,13 +153,13 @@ bmap_f(
  *     EINVAL, check the length with fstat() and return "no extents"
  *     if the length == 0.
  *
- *     Why not do the xfsctl(XFS_IOC_FSGETXATTR[A]) first?  Two reasons:
+ *     Why not do the xfsctl(FS_IOC_FSGETXATTR[A]) first?  Two reasons:
  *     (1)     The extent count may be wrong for a file with delayed
  *             allocation blocks.  The XFS_IOC_GETBMAPX forces the real
  *             allocation and fixes up the extent count.
  *     (2)     For XFS_IOC_GETBMAP[X] on a DMAPI file that has been moved
  *             offline by a DMAPI application (e.g., DMF) the
- *             XFS_IOC_FSGETXATTR only reflects the extents actually online.
+ *             FS_IOC_FSGETXATTR only reflects the extents actually online.
  *             Doing XFS_IOC_GETBMAPX call first forces that data blocks online
  *             and then everything proceeds normally (see PV #545725).
  *
@@ -189,7 +170,7 @@ bmap_f(
 
        do {    /* loop a miximum of two times */
 
-               bzero(map, sizeof(*map));       /* zero header */
+               memset(map, 0, sizeof(*map));   /* zero header */
 
                map->bmv_length = -1;
                map->bmv_count = map_size;
@@ -214,21 +195,21 @@ bmap_f(
                        break;
                if (map->bmv_entries < map->bmv_count-1)
                        break;
-               /* Get number of extents from xfsctl XFS_IOC_FSGETXATTR[A]
+               /* Get number of extents from xfsctl FS_IOC_FSGETXATTR[A]
                 * syscall.
                 */
                i = xfsctl(file->name, file->fd, aflag ?
-                               XFS_IOC_FSGETXATTRA : XFS_IOC_FSGETXATTR, &fsx);
+                               XFS_IOC_FSGETXATTRA : FS_IOC_FSGETXATTR, &fsx);
                if (i < 0) {
-                       fprintf(stderr, "%s: xfsctl(XFS_IOC_FSGETXATTR%s) "
+                       fprintf(stderr, "%s: xfsctl(FS_IOC_FSGETXATTR%s) "
                                "[\"%s\"]: %s\n", progname, aflag ? "A" : "",
                                file->name, strerror(errno));
                        free(map);
                        exitcode = 1;
                        return 0;
                }
-               if (fsx.fsx_nextents >= map_size-1) {
-                       map_size = 2*(fsx.fsx_nextents+1);
+               if (2 * fsx.fsx_nextents > map_size) {
+                       map_size = 2 * fsx.fsx_nextents + 1;
                        map = realloc(map, map_size*sizeof(*map));
                        if (map == NULL) {
                                fprintf(stderr,
@@ -246,15 +227,18 @@ bmap_f(
                        return 0;
                }
        }
+       egcnt = nflag ? min(nflag, map->bmv_entries) : map->bmv_entries;
        printf("%s:\n", file->name);
        if (!vflag) {
-               for (i = 0; i < map->bmv_entries; i++) {
+               for (i = 0; i < egcnt; i++) {
                        printf("\t%d: [%lld..%lld]: ", i,
                                (long long) map[i + 1].bmv_offset,
                                (long long)(map[i + 1].bmv_offset +
                                map[i + 1].bmv_length - 1LL));
                        if (map[i + 1].bmv_block == -1)
                                printf(_("hole"));
+                       else if (map[i + 1].bmv_block == -2)
+                               printf(_("delalloc"));
                        else {
                                printf("%lld..%lld",
                                        (long long) map[i + 1].bmv_block,
@@ -277,14 +261,14 @@ bmap_f(
 #define MINRANGE_WIDTH 16
 #define MINAG_WIDTH    2
 #define MINTOT_WIDTH   5
-#define        max(a,b)        (a > b ? a : b)
-#define NFLG           5       /* count of flags */
-#define        FLG_NULL        000000  /* Null flag */
-#define        FLG_PRE         010000  /* Unwritten extent */
-#define        FLG_BSU         001000  /* Not on begin of stripe unit  */
-#define        FLG_ESU         000100  /* Not on end   of stripe unit  */
-#define        FLG_BSW         000010  /* Not on begin of stripe width */
-#define        FLG_ESW         00000 /* Not on end   of stripe width */
+#define NFLG           6       /* count of flags */
+#define        FLG_NULL        0000000 /* Null flag */
+#define        FLG_SHARED      0100000 /* shared extent */
+#define        FLG_PRE         0010000 /* Unwritten extent */
+#define        FLG_BSU         0001000 /* Not on begin of stripe unit  */
+#define        FLG_ESU         0000100 /* Not on end   of stripe unit  */
+#define        FLG_BSW         0000010 /* Not on begin of stripe width */
+#define        FLG_ESW         0000001 /* Not on end   of stripe width */
                int     agno;
                off64_t agoff, bbperag;
                int     foff_w, boff_w, aoff_w, tot_w, agno_w;
@@ -293,17 +277,21 @@ bmap_f(
 
                foff_w = boff_w = aoff_w = MINRANGE_WIDTH;
                tot_w = MINTOT_WIDTH;
-               bbperag = (off64_t)fsgeo.agblocks *
-                         (off64_t)fsgeo.blocksize / BBSIZE;
-               sunit = (fsgeo.sunit * fsgeo.blocksize) / BBSIZE;
-               swidth = (fsgeo.swidth * fsgeo.blocksize) / BBSIZE;
-               flg = sunit;
+               if (is_rt)
+                       sunit = swidth = bbperag = 0;
+               else {
+                       bbperag = (off64_t)fsgeo.agblocks *
+                                 (off64_t)fsgeo.blocksize / BBSIZE;
+                       sunit = (fsgeo.sunit * fsgeo.blocksize) / BBSIZE;
+                       swidth = (fsgeo.swidth * fsgeo.blocksize) / BBSIZE;
+               }
+               flg = sunit | pflag;
 
                /*
                 * Go through the extents and figure out the width
                 * needed for all columns.
                 */
-               for (i = 0; i < map->bmv_entries; i++) {
+               for (i = 0; i < egcnt; i++) {
                        snprintf(rbuf, sizeof(rbuf), "[%lld..%lld]:",
                                (long long) map[i + 1].bmv_offset,
                                (long long)(map[i + 1].bmv_offset +
@@ -313,38 +301,48 @@ bmap_f(
                        if (map[i + 1].bmv_block == -1) {
                                foff_w = max(foff_w, strlen(rbuf));
                                tot_w = max(tot_w,
-                                       numlen(map[i+1].bmv_length));
+                                       numlen(map[i+1].bmv_length, 10));
                        } else {
                                snprintf(bbuf, sizeof(bbuf), "%lld..%lld",
                                        (long long) map[i + 1].bmv_block,
                                        (long long)(map[i + 1].bmv_block +
                                                map[i + 1].bmv_length - 1LL));
-                               agno = map[i + 1].bmv_block / bbperag;
-                               agoff = map[i + 1].bmv_block - (agno * bbperag);
-                               snprintf(abuf, sizeof(abuf), "(%lld..%lld)",
-                                       (long long)agoff,  (long long)
-                                       (agoff + map[i + 1].bmv_length - 1LL));
-                               foff_w = max(foff_w, strlen(rbuf));
                                boff_w = max(boff_w, strlen(bbuf));
-                               aoff_w = max(aoff_w, strlen(abuf));
+                               if (!is_rt) {
+                                       agno = map[i + 1].bmv_block / bbperag;
+                                       agoff = map[i + 1].bmv_block -
+                                                       (agno * bbperag);
+                                       snprintf(abuf, sizeof(abuf),
+                                               "(%lld..%lld)",
+                                               (long long)agoff,
+                                               (long long)(agoff +
+                                                map[i + 1].bmv_length - 1LL));
+                                       aoff_w = max(aoff_w, strlen(abuf));
+                               } else
+                                       aoff_w = 0;
+                               foff_w = max(foff_w, strlen(rbuf));
                                tot_w = max(tot_w,
-                                       numlen(map[i+1].bmv_length));
+                                       numlen(map[i+1].bmv_length, 10));
                        }
                }
-               agno_w = max(MINAG_WIDTH, numlen(fsgeo.agcount));
+               agno_w = is_rt ? 0 : max(MINAG_WIDTH, numlen(fsgeo.agcount, 10));
                printf("%4s: %-*s %-*s %*s %-*s %*s%s\n",
                        _("EXT"),
                        foff_w, _("FILE-OFFSET"),
-                       boff_w, _("BLOCK-RANGE"),
-                       agno_w, _("AG"),
-                       aoff_w, _("AG-OFFSET"),
+                       boff_w, is_rt ? _("RT-BLOCK-RANGE") : _("BLOCK-RANGE"),
+                       agno_w, is_rt ? "" : _("AG"),
+                       aoff_w, is_rt ? "" : _("AG-OFFSET"),
                        tot_w, _("TOTAL"),
                        flg ? _(" FLAGS") : "");
-               for (i = 0; i < map->bmv_entries; i++) {
+               for (i = 0; i < egcnt; i++) {
                        flg = FLG_NULL;
                        if (map[i + 1].bmv_oflags & BMV_OF_PREALLOC) {
                                flg |= FLG_PRE;
                        }
+                       if (map[i + 1].bmv_oflags & BMV_OF_SHARED)
+                               flg |= FLG_SHARED;
+                       if (map[i + 1].bmv_oflags & BMV_OF_DELALLOC)
+                               map[i + 1].bmv_block = -2;
                        /*
                         * If striping enabled, determine if extent starts/ends
                         * on a stripe unit boundary.
@@ -377,32 +375,47 @@ bmap_f(
                                        agno_w, "",
                                        aoff_w, "",
                                        tot_w, (long long)map[i+1].bmv_length);
+                       } else if (map[i + 1].bmv_block == -2) {
+                               printf("%4d: %-*s %-*s %*s %-*s %*lld\n",
+                                       i,
+                                       foff_w, rbuf,
+                                       boff_w, _("delalloc"),
+                                       agno_w, "",
+                                       aoff_w, "",
+                                       tot_w, (long long)map[i+1].bmv_length);
                        } else {
                                snprintf(bbuf, sizeof(bbuf), "%lld..%lld",
                                        (long long) map[i + 1].bmv_block,
                                        (long long)(map[i + 1].bmv_block +
                                                map[i + 1].bmv_length - 1LL));
-                               agno = map[i + 1].bmv_block / bbperag;
-                               agoff = map[i + 1].bmv_block - (agno * bbperag);
-                               snprintf(abuf, sizeof(abuf), "(%lld..%lld)",
-                                       (long long)agoff,  (long long)
-                                       (agoff + map[i + 1].bmv_length - 1LL));
-                               printf("%4d: %-*s %-*s %*d %-*s %*lld",
-                                       i,
-                                       foff_w, rbuf,
-                                       boff_w, bbuf,
-                                       agno_w, agno,
-                                       aoff_w, abuf,
-                                       tot_w, (long long)map[i+1].bmv_length);
-                               if (flg == FLG_NULL) {
+                               printf("%4d: %-*s %-*s", i, foff_w, rbuf,
+                                       boff_w, bbuf);
+                               if (!is_rt) {
+                                       agno = map[i + 1].bmv_block / bbperag;
+                                       agoff = map[i + 1].bmv_block -
+                                                       (agno * bbperag);
+                                       snprintf(abuf, sizeof(abuf),
+                                               "(%lld..%lld)",
+                                               (long long)agoff,
+                                               (long long)(agoff +
+                                                map[i + 1].bmv_length - 1LL));
+                                       printf(" %*d %-*s", agno_w, agno,
+                                               aoff_w, abuf);
+                               } else
+                                       printf("  ");
+                               printf(" %*lld", tot_w,
+                                       (long long)map[i+1].bmv_length);
+                               if (flg == FLG_NULL && !pflag) {
                                        printf("\n");
                                } else {
                                        printf(" %-*.*o\n", NFLG, NFLG, flg);
                                }
                        }
                }
-               if (flg && vflag > 1) {
+               if ((flg || pflag) && vflag > 1) {
                        printf(_(" FLAG Values:\n"));
+                       printf(_("    %*.*o Shared extent\n"),
+                               NFLG+1, NFLG+1, FLG_SHARED);
                        printf(_("    %*.*o Unwritten preallocated extent\n"),
                                NFLG+1, NFLG+1, FLG_PRE);
                        printf(_("    %*.*o Doesn't begin on stripe unit\n"),
@@ -422,7 +435,7 @@ bmap_f(
 void
 bmap_init(void)
 {
-       bmap_cmd.name = _("bmap");
+       bmap_cmd.name = "bmap";
        bmap_cmd.cfunc = bmap_f;
        bmap_cmd.argmin = 0;
        bmap_cmd.argmax = -1;