]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blobdiff - io/mmap.c
xfs: fix inverted return from xfs_btree_sblock_verify_crc
[thirdparty/xfsprogs-dev.git] / io / mmap.c
index 300eff08339a44e91f132c04112556fa74ab2b08..f9383e5e790de7b599671df21a981dd956306a43 100644 (file)
--- a/io/mmap.c
+++ b/io/mmap.c
@@ -1,40 +1,13 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
- * Copyright (c) 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) 2004-2005 Silicon Graphics, Inc.
+ * All Rights Reserved.
  */
 
-#include <xfs/libxfs.h>
-#include <sys/mman.h>
-#include <signal.h>
 #include "command.h"
 #include "input.h"
+#include <sys/mman.h>
+#include <signal.h>
 #include "init.h"
 #include "io.h"
 
@@ -43,6 +16,9 @@ static cmdinfo_t mread_cmd;
 static cmdinfo_t msync_cmd;
 static cmdinfo_t munmap_cmd;
 static cmdinfo_t mwrite_cmd;
+#ifdef HAVE_MREMAP
+static cmdinfo_t mremap_cmd;
+#endif /* HAVE_MREMAP */
 
 mmap_region_t  *maptable;
 int            mapcount;
@@ -54,7 +30,7 @@ print_mapping(
        int             index,
        int             braces)
 {
-       unsigned char   buffer[8] = { 0 };
+       char            buffer[8] = { 0 };
        int             i;
 
        static struct {
@@ -69,10 +45,14 @@ print_mapping(
 
        for (i = 0, p = pflags; p->prot != PROT_NONE; i++, p++)
                buffer[i] = (map->prot & p->prot) ? p->mode : '-';
-       printf("%c%d%c 0x%lx - 0x%lx %s  %14s (%lld : %ld)\n",
+
+       if (map->map_sync)
+               sprintf(&buffer[i], " S");
+
+       printf("%c%03d%c 0x%lx - 0x%lx %s  %14s (%lld : %ld)\n",
                braces? '[' : ' ', index, braces? ']' : ' ',
                (unsigned long)map->addr,
-               (unsigned long)(map->addr + map->length),
+               (unsigned long)((char *)map->addr + map->length),
                buffer, map->name ? map->name : "???",
                (long long)map->offset, (long)map->length);
 }
@@ -103,13 +83,13 @@ check_mapping_range(
                        (long long)mapping->offset, (long)mapping->length);
                return NULL;
        }
-       if (pagealign && (long)(mapping->addr + relative) % pagesize) {
+       if (pagealign && (long)((char *)mapping->addr + relative) % pagesize) {
                printf(_("offset address (%p) is not page aligned\n"),
-                       mapping->addr + relative);
+                       (char *)mapping->addr + relative);
                return NULL;
        }
 
-       return mapping->addr + relative;
+       return (char *)mapping->addr + relative;
 }
 
 int
@@ -158,6 +138,8 @@ mmap_help(void)
 " -r -- map with PROT_READ protection\n"
 " -w -- map with PROT_WRITE protection\n"
 " -x -- map with PROT_EXEC protection\n"
+" -S -- map with MAP_SYNC and MAP_SHARED_VALIDATE flags\n"
+" -s <size> -- first do mmap(size)/munmap(size), try to reserve some free space\n"
 " If no protection mode is specified, all are used by default.\n"
 "\n"));
 }
@@ -168,17 +150,17 @@ mmap_f(
        char            **argv)
 {
        off64_t         offset;
-       size_t          length;
-       void            *address;
+       ssize_t         length = 0, length2 = 0;
+       void            *address = NULL;
        char            *filename;
-       int             blocksize, sectsize;
-       int             c, prot = 0;
+       size_t          blocksize, sectsize;
+       int             c, prot = 0, flags = MAP_SHARED;
 
        if (argc == 1) {
                if (mapping)
                        return maplist_f();
                fprintf(stderr, file ?
-                       _("no mapped regions, try 'help mmap'\n") : 
+                       _("no mapped regions, try 'help mmap'\n") :
                        _("no files are open, try 'help open'\n"));
                return 0;
        } else if (argc == 2) {
@@ -193,7 +175,9 @@ mmap_f(
                return 0;
        }
 
-       while ((c = getopt(argc, argv, "rwx")) != EOF) {
+       init_cvtnum(&blocksize, &sectsize);
+
+       while ((c = getopt(argc, argv, "rwxSs:")) != EOF) {
                switch (c) {
                case 'r':
                        prot |= PROT_READ;
@@ -204,6 +188,22 @@ mmap_f(
                case 'x':
                        prot |= PROT_EXEC;
                        break;
+               case 'S':
+                       flags = MAP_SYNC | MAP_SHARED_VALIDATE;
+
+                       /*
+                        * If MAP_SYNC and MAP_SHARED_VALIDATE aren't defined
+                        * in the system headers we will have defined them
+                        * both as 0.
+                        */
+                       if (!flags) {
+                               printf("MAP_SYNC not supported\n");
+                               return 0;
+                       }
+                       break;
+               case 's':
+                       length2 = cvtnum(blocksize, sectsize, optarg);
+                       break;
                default:
                        return command_usage(&mmap_cmd);
                }
@@ -214,7 +214,6 @@ mmap_f(
        if (optind != argc - 2)
                return command_usage(&mmap_cmd);
 
-       init_cvtnum(&blocksize, &sectsize);
        offset = cvtnum(blocksize, sectsize, argv[optind]);
        if (offset < 0) {
                printf(_("non-numeric offset argument -- %s\n"), argv[optind]);
@@ -233,7 +232,19 @@ mmap_f(
                return 0;
        }
 
-       address = mmap(NULL, length, prot, MAP_SHARED, file->fd, offset);
+       /*
+        * mmap and munmap memory area of length2 region is helpful to
+        * make a region of extendible free memory. It's generally used
+        * for later mremap operation(no MREMAP_MAYMOVE flag). But there
+        * isn't guarantee that the memory after length (up to length2)
+        * will stay free.
+        */
+       if (length2 > length) {
+               address = mmap(NULL, length2, prot,
+                              MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+               munmap(address, length2);
+       }
+       address = mmap(address, length, prot, flags, file->fd, offset);
        if (address == MAP_FAILED) {
                perror("mmap");
                free(filename);
@@ -258,6 +269,7 @@ mmap_f(
        mapping->offset = offset;
        mapping->name = filename;
        mapping->prot = prot;
+       mapping->map_sync = (flags == (MAP_SYNC | MAP_SHARED_VALIDATE));
        return 0;
 }
 
@@ -278,15 +290,16 @@ msync_help(void)
 "\n"));
 }
 
-int
+static int
 msync_f(
        int             argc,
        char            **argv)
 {
        off64_t         offset;
-       size_t          length;
+       ssize_t         length;
        void            *start;
-       int             c, flags = 0, blocksize, sectsize;
+       int             c, flags = 0;
+       size_t          blocksize, sectsize;
 
        while ((c = getopt(argc, argv, "ais")) != EOF) {
                switch (c) {
@@ -336,26 +349,6 @@ msync_f(
        return 0;
 }
 
-static int
-read_mapping(
-       char            *dest,
-       off64_t         offset,
-       int             dump,
-       off64_t         dumpoffset,
-       size_t          dumplength)
-{
-       *dest = *(((char *)mapping->addr) + offset);
-
-       if (offset % pagesize == 0) {
-               if (dump == 2)
-                       dumpoffset += mapping->offset;
-               if (dump)
-                       dump_buffer(dumpoffset, dumplength);
-               return 1;
-       }
-       return 0;
-}
-
 static void
 mread_help(void)
 {
@@ -369,7 +362,7 @@ mread_help(void)
 " Accesses a range of the current memory mapping, optionally dumping it to\n"
 " the standard output stream (with -v option) for subsequent inspection.\n"
 " -f -- verbose mode, dump bytes with offsets relative to start of file.\n"
-" -r -- reverse order; start accessing fom the end of range, moving backward\n"
+" -r -- reverse order; start accessing from the end of range, moving backward\n"
 " -v -- verbose mode, dump bytes with offsets relative to start of mapping.\n"
 " The accesses are performed sequentially from the start offset by default.\n"
 " Notes:\n"
@@ -381,17 +374,18 @@ mread_help(void)
 "\n"));
 }
 
-int
+static int
 mread_f(
        int             argc,
        char            **argv)
 {
-       off64_t         offset, tmp;
-       size_t          length, dumplen;
+       off64_t         offset, tmp, dumpoffset, printoffset;
+       ssize_t         length;
+       size_t          dumplen, cnt = 0;
        char            *bp;
        void            *start;
-       int             dump = 0, rflag = 0;
-       int             c, blocksize, sectsize;
+       int             dump = 0, rflag = 0, c;
+       size_t          blocksize, sectsize;
 
        while ((c = getopt(argc, argv, "frv")) != EOF) {
                switch (c) {
@@ -434,49 +428,61 @@ mread_f(
        start = check_mapping_range(mapping, offset, length, 0);
        if (!start)
                return 0;
+       dumpoffset = offset - mapping->offset;
+       if (dump == 2)
+               printoffset = offset;
+       else
+               printoffset = dumpoffset;
 
        if (alloc_buffer(pagesize, 0, 0) < 0)
                return 0;
-       bp = (char *)buffer;
+       bp = (char *)io_buffer;
 
        dumplen = length % pagesize;
        if (!dumplen)
                dumplen = pagesize;
 
        if (rflag) {
-               for (tmp = length, c = 0; tmp > 0; tmp--, bp++, c = 1)
-                       if (read_mapping(bp, tmp, c? dump:0, offset, dumplen)) {
-                               bp = (char *)buffer;
+               for (tmp = length - 1, c = 0; tmp >= 0; tmp--, c = 1) {
+                       *bp = *(((char *)mapping->addr) + dumpoffset + tmp);
+                       cnt++;
+                       if (c && cnt == dumplen) {
+                               if (dump) {
+                                       dump_buffer(printoffset, dumplen);
+                                       printoffset += dumplen;
+                               }
+                               bp = (char *)io_buffer;
                                dumplen = pagesize;
+                               cnt = 0;
+                       } else {
+                               bp++;
                        }
+               }
        } else {
-               for (tmp = 0, c = 0; tmp < length; tmp++, bp++, c = 1)
-                       if (read_mapping(bp, tmp, c? dump:0, offset, dumplen)) {
-                               bp = (char *)buffer;
+               for (tmp = 0, c = 0; tmp < length; tmp++, c = 1) {
+                       *bp = *(((char *)mapping->addr) + dumpoffset + tmp);
+                       cnt++;
+                       if (c && cnt == dumplen) {
+                               if (dump)
+                                       dump_buffer(printoffset + tmp -
+                                               (dumplen - 1), dumplen);
+                               bp = (char *)io_buffer;
                                dumplen = pagesize;
+                               cnt = 0;
+                       } else {
+                               bp++;
                        }
-       }
-       /* dump the remaining (partial page) part of the read buffer */
-       if (dump) {
-               if (rflag)
-                       dumplen = length % pagesize;
-               else
-                       dumplen = tmp % pagesize;
-               if (dumplen) {
-                       if (dump == 2)
-                               tmp += mapping->offset;
-                       dump_buffer(tmp, dumplen);
                }
        }
        return 0;
 }
 
-int
+static int
 munmap_f(
        int             argc,
        char            **argv)
 {
-       size_t          length;
+       ssize_t         length;
        unsigned int    offset;
 
        if (munmap(mapping->addr, mapping->length) < 0) {
@@ -520,23 +526,24 @@ mwrite_help(void)
 " Stores a byte into memory for a range within a mapping.\n"
 " The default stored value is 'X', repeated to fill the range specified.\n"
 " -S -- use an alternate seed character\n"
-" -r -- reverse order; start storing fom the end of range, moving backward\n"
+" -r -- reverse order; start storing from the end of range, moving backward\n"
 " The stores are performed sequentially from the start offset by default.\n"
 "\n"));
 }
 
-int
+static int
 mwrite_f(
        int             argc,
        char            **argv)
 {
        off64_t         offset, tmp;
-       size_t          length;
+       ssize_t         length;
        void            *start;
        char            *sp;
        int             seed = 'X';
        int             rflag = 0;
-       int             c, blocksize, sectsize;
+       int             c;
+       size_t          blocksize, sectsize;
 
        while ((c = getopt(argc, argv, "rS:")) != EOF) {
                switch (c) {
@@ -581,8 +588,9 @@ mwrite_f(
        if (!start)
                return 0;
 
+       offset -= mapping->offset;
        if (rflag) {
-               for (tmp = offset + length; tmp > offset; tmp--)
+               for (tmp = offset + length -1; tmp >= offset; tmp--)
                        ((char *)mapping->addr)[tmp] = seed;
        } else {
                for (tmp = offset; tmp < offset + length; tmp++)
@@ -592,22 +600,96 @@ mwrite_f(
        return 0;
 }
 
+#ifdef HAVE_MREMAP
+static void
+mremap_help(void)
+{
+       printf(_(
+"\n"
+" resizes the current memory mapping\n"
+"\n"
+" Examples:\n"
+" 'mremap 8192' - resizes the current mapping to 8192 bytes.\n"
+"\n"
+" Resizes the mapping, growing or shrinking from the current size.\n"
+" The default stored value is 'X', repeated to fill the range specified.\n"
+" -f <new_address> -- use MREMAP_FIXED flag to mremap on new_address\n"
+" -m -- use the MREMAP_MAYMOVE flag\n"
+"\n"));
+}
+
+static int
+mremap_f(
+       int             argc,
+       char            **argv)
+{
+       ssize_t         new_length;
+       void            *new_addr = NULL;
+       int             flags = 0;
+       int             c;
+       size_t          blocksize, sectsize;
+
+       init_cvtnum(&blocksize, &sectsize);
+
+       while ((c = getopt(argc, argv, "f:m")) != EOF) {
+               switch (c) {
+               case 'f':
+                       flags = MREMAP_FIXED|MREMAP_MAYMOVE;
+                       new_addr = (void *)(unsigned long)cvtnum(blocksize,
+                                                 sectsize, optarg);
+                       break;
+               case 'm':
+                       flags = MREMAP_MAYMOVE;
+                       break;
+               default:
+                       return command_usage(&mremap_cmd);
+               }
+       }
+
+       if (optind != argc - 1)
+               return command_usage(&mremap_cmd);
+
+       new_length = cvtnum(blocksize, sectsize, argv[optind]);
+       if (new_length < 0) {
+               printf(_("non-numeric offset argument -- %s\n"),
+                       argv[optind]);
+               return 0;
+       }
+
+       if (!new_addr)
+               new_addr = mremap(mapping->addr, mapping->length,
+                                 new_length, flags);
+       else
+               new_addr = mremap(mapping->addr, mapping->length,
+                                 new_length, flags, new_addr);
+       if (new_addr == MAP_FAILED)
+               perror("mremap");
+       else {
+               mapping->addr = new_addr;
+               mapping->length = new_length;
+       }
+
+       return 0;
+}
+#endif /* HAVE_MREMAP */
+
 void
 mmap_init(void)
 {
-       mmap_cmd.name = _("mmap");
-       mmap_cmd.altname = _("mm");
+       mmap_cmd.name = "mmap";
+       mmap_cmd.altname = "mm";
        mmap_cmd.cfunc = mmap_f;
        mmap_cmd.argmin = 0;
        mmap_cmd.argmax = -1;
-       mmap_cmd.flags = CMD_NOMAP_OK | CMD_NOFILE_OK | CMD_FOREIGN_OK;
-       mmap_cmd.args = _("[N] | [-rwx] [off len]");
+       mmap_cmd.flags = CMD_NOMAP_OK | CMD_NOFILE_OK |
+                        CMD_FOREIGN_OK | CMD_FLAG_ONESHOT;
+       mmap_cmd.args = _("[N] | [-rwxS] [-s size] [off len]");
        mmap_cmd.oneline =
                _("mmap a range in the current file, show mappings");
        mmap_cmd.help = mmap_help;
 
-       mread_cmd.name = _("mread");
-       mread_cmd.altname = _("mr");
+       mread_cmd.name = "mread";
+       mread_cmd.altname = "mr";
        mread_cmd.cfunc = mread_f;
        mread_cmd.argmin = 0;
        mread_cmd.argmax = -1;
@@ -617,8 +699,8 @@ mmap_init(void)
                _("reads data from a region in the current memory mapping");
        mread_cmd.help = mread_help;
 
-       msync_cmd.name = _("msync");
-       msync_cmd.altname = _("ms");
+       msync_cmd.name = "msync";
+       msync_cmd.altname = "ms";
        msync_cmd.cfunc = msync_f;
        msync_cmd.argmin = 0;
        msync_cmd.argmax = -1;
@@ -627,16 +709,16 @@ mmap_init(void)
        msync_cmd.oneline = _("flush a region in the current memory mapping");
        msync_cmd.help = msync_help;
 
-       munmap_cmd.name = _("munmap");
-       munmap_cmd.altname = _("mu");
+       munmap_cmd.name = "munmap";
+       munmap_cmd.altname = "mu";
        munmap_cmd.cfunc = munmap_f;
        munmap_cmd.argmin = 0;
        munmap_cmd.argmax = 0;
        munmap_cmd.flags = CMD_NOFILE_OK | CMD_FOREIGN_OK;
        munmap_cmd.oneline = _("unmaps the current memory mapping");
 
-       mwrite_cmd.name = _("mwrite");
-       mwrite_cmd.altname = _("mw");
+       mwrite_cmd.name = "mwrite";
+       mwrite_cmd.altname = "mw";
        mwrite_cmd.cfunc = mwrite_f;
        mwrite_cmd.argmin = 0;
        mwrite_cmd.argmax = -1;
@@ -646,9 +728,25 @@ mmap_init(void)
                _("writes data into a region in the current memory mapping");
        mwrite_cmd.help = mwrite_help;
 
+#ifdef HAVE_MREMAP
+       mremap_cmd.name = "mremap";
+       mremap_cmd.altname = "mrm";
+       mremap_cmd.cfunc = mremap_f;
+       mremap_cmd.argmin = 1;
+       mremap_cmd.argmax = 3;
+       mremap_cmd.flags = CMD_NOFILE_OK | CMD_FOREIGN_OK;
+       mremap_cmd.args = _("[-m|-f <new_address>] newsize");
+       mremap_cmd.oneline =
+               _("alters the size of the current memory mapping");
+       mremap_cmd.help = mremap_help;
+#endif /* HAVE_MREMAP */
+
        add_command(&mmap_cmd);
        add_command(&mread_cmd);
        add_command(&msync_cmd);
        add_command(&munmap_cmd);
        add_command(&mwrite_cmd);
+#ifdef HAVE_MREMAP
+       add_command(&mremap_cmd);
+#endif /* HAVE_MREMAP */
 }