2
* Copyright (c) 2004 Silicon Graphics, Inc. All Rights Reserved.
4
* This program is free software; you can redistribute it and/or modify it
5
* under the terms of version 2 of the GNU General Public License as
6
* published by the Free Software Foundation.
8
* This program is distributed in the hope that it would be useful, but
9
* WITHOUT ANY WARRANTY; without even the implied warranty of
10
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
* Further, this software is distributed without any warranty that it is
13
* free of the rightful claim of any third person regarding infringement
14
* or the like. Any license provided herein, whether implied or
15
* otherwise, applies only to this software file. Patent licenses, if
16
* any, provided herein do not apply to combinations of this program with
17
* other software, or any other product whatsoever.
19
* You should have received a copy of the GNU General Public License along
20
* with this program; if not, write the Free Software Foundation, Inc., 59
21
* Temple Place - Suite 330, Boston MA 02111-1307, USA.
23
* Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
24
* Mountain View, CA 94043, or:
28
* For further information regarding this notice, see:
30
* http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
33
#include <xfs/libxfs.h>
41
static cmdinfo_t mmap_cmd;
42
static cmdinfo_t mread_cmd;
43
static cmdinfo_t msync_cmd;
44
static cmdinfo_t munmap_cmd;
45
static cmdinfo_t mwrite_cmd;
46
static cmdinfo_t madvise_cmd;
47
static cmdinfo_t mincore_cmd;
49
mmap_region_t *maptable;
51
mmap_region_t *mapping;
59
unsigned char buffer[8] = { 0 };
72
for (i = 0, p = pflags; p->prot != PROT_NONE; i++, p++)
73
buffer[i] = (map->prot & p->prot) ? p->mode : '-';
74
printf("%c%d%c 0x%lx - 0x%lx %s %14s (%lld : %ld)\n",
75
braces? '[' : ' ', index, braces? ']' : ' ',
76
(unsigned long)map->addr,
77
(unsigned long)(map->addr + map->length),
78
buffer, map->name ? map->name : "???",
79
(long long)map->offset, (long)map->length);
91
if (offset < mapping->offset) {
92
printf(_("offset (%lld) is before start of mapping (%lld)\n"),
93
(long long)offset, (long long)mapping->offset);
96
relative = offset - mapping->offset;
97
if (relative > mapping->length) {
98
printf(_("offset (%lld) is beyond end of mapping (%lld)\n"),
99
(long long)relative, (long long)mapping->offset);
102
if ((relative + length) > (mapping->offset + mapping->length)) {
103
printf(_("range (%lld:%lld) is beyond mapping (%lld:%ld)\n"),
104
(long long)offset, (long long)relative,
105
(long long)mapping->offset, (long)mapping->length);
108
if (pagealign && (long)(mapping->addr + relative) % pagesize) {
109
printf(_("offset address (%p) is not page aligned\n"),
110
mapping->addr + relative);
114
return mapping->addr + relative;
122
for (i = 0; i < mapcount; i++)
123
print_mapping(&maptable[i], i, &maptable[i] == mapping);
136
if (i < 0 || i >= mapcount) {
137
printf("value %d is out of range (0-%d)\n", i, mapcount);
139
mapping = &maptable[i];
150
" maps a range within the current file into memory\n"
153
" 'mmap -rw 0 1m' - maps one megabyte from the start of the current file\n"
155
" Memory maps a range of a file for subsequent use by other xfs_io commands.\n"
156
" With no arguments, mmap shows the current mappings. The current mapping\n"
157
" can be set by using the single argument form (mapping number or address).\n"
158
" If two arguments are specified (a range), a new mapping is created and the\n"
159
" following options are available:\n"
160
" -r -- map with PROT_READ protection\n"
161
" -w -- map with PROT_WRITE protection\n"
162
" -x -- map with PROT_EXEC protection\n"
163
" If no protection mode is specified, all are used by default.\n"
176
int blocksize, sectsize;
182
fprintf(stderr, file ?
183
_("no mapped regions, try 'help mmap'\n") :
184
_("no files are open, try 'help open'\n"));
186
} else if (argc == 2) {
188
return mapset_f(argc, argv);
189
fprintf(stderr, file ?
190
_("no mapped regions, try 'help mmap'\n") :
191
_("no files are open, try 'help open'\n"));
194
fprintf(stderr, _("no files are open, try 'help open'\n"));
198
while ((c = getopt(argc, argv, "rwx")) != EOF) {
210
return command_usage(&mmap_cmd);
214
prot = PROT_READ | PROT_WRITE | PROT_EXEC;
216
if (optind != argc - 2)
217
return command_usage(&mmap_cmd);
219
init_cvtnum(&blocksize, §size);
220
offset = cvtnum(blocksize, sectsize, argv[optind]);
222
printf(_("non-numeric offset argument -- %s\n"), argv[optind]);
226
length = cvtnum(blocksize, sectsize, argv[optind]);
228
printf(_("non-numeric length argument -- %s\n"), argv[optind]);
232
filename = strdup(file->name);
238
address = mmap(NULL, length, prot, MAP_SHARED, file->fd, offset);
239
if (address == MAP_FAILED) {
245
/* Extend the control array of mmap'd regions */
246
maptable = (mmap_region_t *)realloc(maptable, /* growing */
247
++mapcount * sizeof(mmap_region_t));
251
munmap(address, length);
256
/* Finally, make this the new active mapping */
257
mapping = &maptable[mapcount - 1];
258
mapping->addr = address;
259
mapping->length = length;
260
mapping->offset = offset;
261
mapping->name = filename;
262
mapping->prot = prot;
271
" flushes a range of bytes in the current memory mapping\n"
273
" Writes all modified copies of pages over the specified range (or entire\n"
274
" mapping if no range specified) to their backing storage locations. Also,\n"
275
" optionally invalidates so that subsequent references to the pages will be\n"
276
" obtained from their backing storage locations (instead of cached copies).\n"
277
" -a -- perform asynchronous writes (MS_ASYNC)\n"
278
" -i -- invalidate mapped pages (MS_INVALIDATE)\n"
279
" -s -- perform synchronous writes (MS_SYNC)\n"
291
int c, flags = 0, blocksize, sectsize;
293
while ((c = getopt(argc, argv, "ais")) != EOF) {
299
flags |= MS_INVALIDATE;
305
return command_usage(&msync_cmd);
309
if (optind == argc) {
310
offset = mapping->offset;
311
length = mapping->length;
312
} else if (optind == argc - 2) {
313
init_cvtnum(&blocksize, §size);
314
offset = cvtnum(blocksize, sectsize, argv[optind]);
316
printf(_("non-numeric offset argument -- %s\n"),
321
length = cvtnum(blocksize, sectsize, argv[optind]);
323
printf(_("non-numeric length argument -- %s\n"),
328
return command_usage(&msync_cmd);
331
start = check_mapping_range(mapping, offset, length, 1);
335
if (msync(start, length, flags) < 0)
349
*dest = *(((char *)mapping->addr) + offset);
351
if (offset % pagesize == 0) {
353
dumpoffset += mapping->offset;
355
dump_buffer(dumpoffset, dumplength);
366
" reads a range of bytes in the current memory mapping\n"
369
" 'mread -v 512 20' - dumps 20 bytes read from 512 bytes into the mapping\n"
371
" Accesses a range of the current memory mapping, optionally dumping it to\n"
372
" the standard output stream (with -v option) for subsequent inspection.\n"
373
" -f -- verbose mode, dump bytes with offsets relative to start of file.\n"
374
" -r -- reverse order; start accessing fom the end of range, moving backward\n"
375
" -v -- verbose mode, dump bytes with offsets relative to start of mapping.\n"
376
" The accesses are performed sequentially from the start offset by default.\n"
378
" References to whole pages following the end of the backing file results\n"
379
" in delivery of the SIGBUS signal. SIGBUS signals may also be delivered\n"
380
" on various filesystem conditions, including quota exceeded errors, and\n"
381
" for physical device errors (such as unreadable disk blocks). No attempt\n"
382
" has been made to catch signals at this stage...\n"
392
size_t length, dumplen;
395
int dump = 0, rflag = 0;
396
int c, blocksize, sectsize;
398
while ((c = getopt(argc, argv, "frv")) != EOF) {
401
dump = 2; /* file offset dump */
404
rflag = 1; /* read in reverse */
407
dump = 1; /* mapping offset dump */
410
return command_usage(&mread_cmd);
414
if (optind == argc) {
415
offset = mapping->offset;
416
length = mapping->length;
417
} else if (optind == argc - 2) {
418
init_cvtnum(&blocksize, §size);
419
offset = cvtnum(blocksize, sectsize, argv[optind]);
421
printf(_("non-numeric offset argument -- %s\n"),
426
length = cvtnum(blocksize, sectsize, argv[optind]);
428
printf(_("non-numeric length argument -- %s\n"),
433
return command_usage(&mread_cmd);
436
start = check_mapping_range(mapping, offset, length, 0);
440
if (alloc_buffer(pagesize, 0, 0) < 0)
444
dumplen = length % pagesize;
449
for (tmp = length, c = 0; tmp > 0; tmp--, bp++, c = 1)
450
if (read_mapping(bp, tmp, c? dump:0, offset, dumplen)) {
455
for (tmp = 0, c = 0; tmp < length; tmp++, bp++, c = 1)
456
if (read_mapping(bp, tmp, c? dump:0, offset, dumplen)) {
461
/* dump the remaining (partial page) part of the read buffer */
464
dumplen = length % pagesize;
466
dumplen = tmp % pagesize;
469
tmp += mapping->offset;
470
dump_buffer(tmp, dumplen);
484
if (munmap(mapping->addr, mapping->length) < 0) {
490
/* Shuffle the mapping table entries down over the removed entry */
491
offset = mapping - &maptable[0];
492
length = mapcount * sizeof(mmap_region_t);
493
length -= (offset + 1) * sizeof(mmap_region_t);
495
memmove(mapping, mapping + 1, length);
497
/* Resize the memory allocated for the table, possibly freeing */
499
maptable = (mmap_region_t *)realloc(maptable, /* shrinking */
500
mapcount * sizeof(mmap_region_t));
501
if (offset == mapcount)
503
mapping = maptable + offset;
506
mapping = maptable = NULL;
517
" dirties a range of bytes in the current memory mapping\n"
520
" 'mwrite 512 20 - writes 20 bytes at 512 bytes into the current mapping.\n"
522
" Stores a byte into memory for a range within a mapping.\n"
523
" The default stored value is 'X', repeated to fill the range specified.\n"
524
" -S -- use an alternate seed character\n"
525
" -r -- reverse order; start storing fom the end of range, moving backward\n"
526
" The stores are performed sequentially from the start offset by default.\n"
541
int c, blocksize, sectsize;
543
while ((c = getopt(argc, argv, "rS:")) != EOF) {
549
seed = (int)strtol(optarg, &sp, 0);
550
if (!sp || sp == optarg) {
551
printf(_("non-numeric seed -- %s\n"), optarg);
556
return command_usage(&mwrite_cmd);
560
if (optind == argc) {
561
offset = mapping->offset;
562
length = mapping->length;
563
} else if (optind == argc - 2) {
564
init_cvtnum(&blocksize, §size);
565
offset = cvtnum(blocksize, sectsize, argv[optind]);
567
printf(_("non-numeric offset argument -- %s\n"),
572
length = cvtnum(blocksize, sectsize, argv[optind]);
574
printf(_("non-numeric length argument -- %s\n"),
579
return command_usage(&mwrite_cmd);
582
start = check_mapping_range(mapping, offset, length, 0);
587
for (tmp = offset + length; tmp > offset; tmp--)
588
((char *)mapping->addr)[tmp] = seed;
590
for (tmp = offset; tmp < offset + length; tmp++)
591
((char *)mapping->addr)[tmp] = seed;
602
" advise the page cache about access patterns expected for a mapping\n"
604
" Modifies page cache behavior when operating on the current mapping.\n"
605
" The range arguments are required by some advise commands ([*] below).\n"
606
" With no arguments, the POSIX_MADV_NORMAL advice is implied.\n"
607
" -d -- don't need these pages (POSIX_MADV_DONTNEED) [*]\n"
608
" -r -- expect random page references (POSIX_MADV_RANDOM)\n"
609
" -s -- expect sequential page references (POSIX_MADV_SEQUENTIAL)\n"
610
" -w -- will need these pages (POSIX_MADV_WILLNEED) [*]\n"
612
" NORMAL sets the default readahead setting on the file.\n"
613
" RANDOM sets the readahead setting on the file to zero.\n"
614
" SEQUENTIAL sets double the default readahead setting on the file.\n"
615
" WILLNEED forces the maximum readahead.\n"
627
int advise = MADV_NORMAL;
628
int c, blocksize, sectsize;
630
while ((c = getopt(argc, argv, "drsw")) != EOF) {
632
case 'd': /* Don't need these pages */
633
advise = MADV_DONTNEED;
635
case 'r': /* Expect random page references */
636
advise = MADV_RANDOM;
638
case 's': /* Expect sequential page references */
639
advise = MADV_SEQUENTIAL;
641
case 'w': /* Will need these pages */
642
advise = MADV_WILLNEED;
645
return command_usage(&madvise_cmd);
649
if (optind == argc) {
650
offset = mapping->offset;
651
length = mapping->length;
652
} else if (optind == argc - 2) {
653
init_cvtnum(&blocksize, §size);
654
offset = cvtnum(blocksize, sectsize, argv[optind]);
656
printf(_("non-numeric offset argument -- %s\n"),
661
length = cvtnum(blocksize, sectsize, argv[optind]);
663
printf(_("non-numeric length argument -- %s\n"),
668
return command_usage(&madvise_cmd);
671
start = check_mapping_range(mapping, offset, length, 1);
675
if (madvise(start, length, advise) < 0) {
683
int mincore(caddr_t p, size_t s, char *v) { errno = ENOSYS; return -1; }
694
void *current, *previous;
696
int i, blocksize, sectsize;
699
offset = mapping->offset;
700
length = mapping->length;
701
} else if (argc == 3) {
702
init_cvtnum(&blocksize, §size);
703
offset = cvtnum(blocksize, sectsize, argv[1]);
705
printf(_("non-numeric offset argument -- %s\n"),
709
length = cvtnum(blocksize, sectsize, argv[2]);
711
printf(_("non-numeric length argument -- %s\n"),
716
return command_usage(&mincore_cmd);
719
start = check_mapping_range(mapping, offset, length, 1);
723
vec = calloc(length/pagesize, sizeof(unsigned char));
729
if (mincore(start, length, vec) < 0) {
737
for (i = 0; i < length/pagesize; i++, current += pagesize) {
739
if (!previous) { /* print start address */
740
printf("0x%lx - ", (unsigned long)current);
741
previous = start + (i * pagesize);
743
} else if (previous) { /* print end and page count */
744
printf(_("0x%lx %lu pages (%llu : %lu)\n"),
745
(unsigned long)current,
746
(unsigned long)(current - previous) / pagesize,
747
(unsigned long long)offset +
748
(unsigned long long)(previous - start),
749
(unsigned long)(current - previous));
754
printf(_("0x%lx %lu pages (%llu : %lu)\n"),
755
(unsigned long)current,
756
(unsigned long)(current - previous) / pagesize,
757
(unsigned long long)offset +
758
(unsigned long long)(previous - start),
759
(unsigned long)(current - previous));
768
mmap_cmd.name = _("mmap");
769
mmap_cmd.altname = _("mm");
770
mmap_cmd.cfunc = mmap_f;
772
mmap_cmd.argmax = -1;
773
mmap_cmd.flags = CMD_NOMAP_OK | CMD_NOFILE_OK | CMD_FOREIGN_OK;
774
mmap_cmd.args = _("[N] | [-rwx] [off len]");
776
_("mmap a range in the current file, show mappings");
777
mmap_cmd.help = mmap_help;
779
mread_cmd.name = _("mread");
780
mread_cmd.altname = _("mr");
781
mread_cmd.cfunc = mread_f;
782
mread_cmd.argmin = 0;
783
mread_cmd.argmax = -1;
784
mread_cmd.flags = CMD_NOFILE_OK | CMD_FOREIGN_OK;
785
mread_cmd.args = _("[-r] [off len]");
787
_("reads data from a region in the current memory mapping");
788
mread_cmd.help = mread_help;
790
msync_cmd.name = _("msync");
791
msync_cmd.altname = _("ms");
792
msync_cmd.cfunc = msync_f;
793
msync_cmd.argmin = 0;
794
msync_cmd.argmax = -1;
795
msync_cmd.flags = CMD_NOFILE_OK | CMD_FOREIGN_OK;
796
msync_cmd.args = _("[-ais] [off len]");
797
msync_cmd.oneline = _("flush a region in the current memory mapping");
798
msync_cmd.help = msync_help;
800
munmap_cmd.name = _("munmap");
801
munmap_cmd.altname = _("mu");
802
munmap_cmd.cfunc = munmap_f;
803
munmap_cmd.argmin = 0;
804
munmap_cmd.argmax = 0;
805
munmap_cmd.flags = CMD_NOFILE_OK | CMD_FOREIGN_OK;
806
munmap_cmd.oneline = _("unmaps the current memory mapping");
808
mwrite_cmd.name = _("mwrite");
809
mwrite_cmd.altname = _("mw");
810
mwrite_cmd.cfunc = mwrite_f;
811
mwrite_cmd.argmin = 0;
812
mwrite_cmd.argmax = -1;
813
mwrite_cmd.flags = CMD_NOFILE_OK | CMD_FOREIGN_OK;
814
mwrite_cmd.args = _("[-r] [-S seed] [off len]");
816
_("writes data into a region in the current memory mapping");
817
mwrite_cmd.help = mwrite_help;
819
madvise_cmd.name = _("madvise");
820
madvise_cmd.altname = _("ma");
821
madvise_cmd.cfunc = madvise_f;
822
madvise_cmd.argmin = 0;
823
madvise_cmd.argmax = -1;
824
madvise_cmd.flags = CMD_NOFILE_OK | CMD_FOREIGN_OK;
825
madvise_cmd.args = _("[-drsw] [off len]");
826
madvise_cmd.oneline = _("give advice about use of memory");
827
madvise_cmd.help = madvise_help;
829
mincore_cmd.name = _("mincore");
830
mincore_cmd.altname = _("mi");
831
mincore_cmd.cfunc = mincore_f;
832
mincore_cmd.argmin = 0;
833
mincore_cmd.argmax = 2;
834
mincore_cmd.flags = CMD_NOFILE_OK | CMD_FOREIGN_OK;
835
mincore_cmd.args = _("[off len]");
836
mincore_cmd.oneline = _("find mapping pages that are memory resident");
838
add_command(&mmap_cmd);
839
add_command(&mread_cmd);
840
add_command(&msync_cmd);
841
add_command(&munmap_cmd);
842
add_command(&mwrite_cmd);
843
add_command(&madvise_cmd);
844
add_command(&mincore_cmd);