+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2004-2005 Silicon Graphics, Inc.
* All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms 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. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
-#include "xfs/xfs.h"
-#include "xfs/command.h"
-#include "xfs/input.h"
+#include "command.h"
+#include "input.h"
#include <sys/mman.h>
#include <signal.h>
#include "init.h"
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;
int index,
int braces)
{
- unsigned char buffer[8] = { 0 };
+ char buffer[8] = { 0 };
int i;
static struct {
for (i = 0, p = pflags; p->prot != PROT_NONE; i++, p++)
buffer[i] = (map->prot & p->prot) ? p->mode : '-';
+
+ 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,
" -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"));
}
char **argv)
{
off64_t offset;
- ssize_t length;
- void *address;
+ ssize_t length = 0, length2 = 0;
+ void *address = NULL;
char *filename;
size_t blocksize, sectsize;
- int c, prot = 0;
+ 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) {
return 0;
}
- while ((c = getopt(argc, argv, "rwx")) != EOF) {
+ init_cvtnum(&blocksize, §size);
+
+ while ((c = getopt(argc, argv, "rwxSs:")) != EOF) {
switch (c) {
case 'r':
prot |= PROT_READ;
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);
}
if (optind != argc - 2)
return command_usage(&mmap_cmd);
- init_cvtnum(&blocksize, §size);
offset = cvtnum(blocksize, sectsize, argv[optind]);
if (offset < 0) {
printf(_("non-numeric offset argument -- %s\n"), argv[optind]);
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);
mapping->offset = offset;
mapping->name = filename;
mapping->prot = prot;
+ mapping->map_sync = (flags == (MAP_SYNC | MAP_SHARED_VALIDATE));
return 0;
}
"\n"));
}
-int
+static int
msync_f(
int argc,
char **argv)
"\n"));
}
-int
+static int
mread_f(
int argc,
char **argv)
if (alloc_buffer(pagesize, 0, 0) < 0)
return 0;
- bp = (char *)buffer;
+ bp = (char *)io_buffer;
dumplen = length % pagesize;
if (!dumplen)
dump_buffer(printoffset, dumplen);
printoffset += dumplen;
}
- bp = (char *)buffer;
+ bp = (char *)io_buffer;
dumplen = pagesize;
cnt = 0;
} else {
if (dump)
dump_buffer(printoffset + tmp -
(dumplen - 1), dumplen);
- bp = (char *)buffer;
+ bp = (char *)io_buffer;
dumplen = pagesize;
cnt = 0;
} else {
return 0;
}
-int
+static int
munmap_f(
int argc,
char **argv)
"\n"));
}
-int
+static int
mwrite_f(
int argc,
char **argv)
return 0;
}
+#ifdef HAVE_MREMAP
static void
mremap_help(void)
{
" Examples:\n"
" 'mremap 8192' - resizes the current mapping to 8192 bytes.\n"
"\n"
-" Resizes the mappping, growing or shrinking from the current size.\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 -- use the MREMAP_FIXED flag\n"
+" -f <new_address> -- use MREMAP_FIXED flag to mremap on new_address\n"
" -m -- use the MREMAP_MAYMOVE flag\n"
"\n"));
}
-int
+static int
mremap_f(
int argc,
char **argv)
{
ssize_t new_length;
- void *new_addr;
+ void *new_addr = NULL;
int flags = 0;
int c;
size_t blocksize, sectsize;
- while ((c = getopt(argc, argv, "fm")) != EOF) {
+ init_cvtnum(&blocksize, §size);
+
+ 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;
}
}
- init_cvtnum(&blocksize, §size);
+ 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"),
return 0;
}
- new_addr = mremap(mapping->addr, mapping->length, new_length, flags);
+ 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 {
return 0;
}
+#endif /* HAVE_MREMAP */
void
mmap_init(void)
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;
_("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 = 2;
+ mremap_cmd.argmax = 3;
mremap_cmd.flags = CMD_NOFILE_OK | CMD_FOREIGN_OK;
- mremap_cmd.args = _("[-m|-f] newsize");
+ 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 */
}