From e246ba5f93896ac873d25f65c05496e6e2c69e34 Mon Sep 17 00:00:00 2001 From: Nathan Scott Date: Tue, 25 Mar 2003 03:48:48 +0000 Subject: [PATCH] Add xfs_io into xfsprogs, an xfs_db-alike program for the XFS IO path which knows about direct IO, space preallocation, realtime files, etc which the usual tools like dd don't unfortunately. This is a fixed-up version of a hacked tool that I found useful for coding, debugging and testing unwritten extents; hopefully it'll be useful for realtime too. --- Makefile | 4 +- VERSION | 2 +- configure.in | 9 +- db/Makefile | 5 + db/input.c | 46 ++++- debian/changelog | 9 +- debian/control | 4 +- debian/rules | 4 +- doc/CHANGES | 20 +- include/builddefs.in | 4 +- include/xfs_fs.h | 4 +- {bmap => io}/Makefile | 16 +- bmap/xfs_bmap.c => io/bmap.c | 245 ++++++++++-------------- io/command.c | 115 ++++++++++++ io/command.h | 75 ++++++++ io/help.c | 109 +++++++++++ io/init.c | 155 +++++++++++++++ io/init.h | 43 +++++ io/input.c | 106 +++++++++++ io/input.h | 35 ++++ io/open.c | 354 +++++++++++++++++++++++++++++++++++ io/pread.c | 202 ++++++++++++++++++++ io/prealloc.c | 170 +++++++++++++++++ io/pwrite.c | 187 ++++++++++++++++++ io/quit.c | 55 ++++++ io/resblks.c | 81 ++++++++ io/truncate.c | 72 +++++++ io/xfs_bmap.sh | 65 +++++++ man/man8/xfs_io.8 | 169 +++++++++++++++++ 29 files changed, 2197 insertions(+), 168 deletions(-) rename {bmap => io}/Makefile (77%) rename bmap/xfs_bmap.c => io/bmap.c (73%) create mode 100644 io/command.c create mode 100644 io/command.h create mode 100644 io/help.c create mode 100644 io/init.c create mode 100644 io/init.h create mode 100644 io/input.c create mode 100644 io/input.h create mode 100644 io/open.c create mode 100644 io/pread.c create mode 100644 io/prealloc.c create mode 100644 io/pwrite.c create mode 100644 io/quit.c create mode 100644 io/resblks.c create mode 100644 io/truncate.c create mode 100755 io/xfs_bmap.sh create mode 100644 man/man8/xfs_io.8 diff --git a/Makefile b/Makefile index fa0db078a..552b8fc13 100644 --- a/Makefile +++ b/Makefile @@ -44,7 +44,7 @@ LDIRT = config.log .dep config.status config.cache confdefs.h conftest* \ Logs/* built .census install.* install-dev.* *.gz SUBDIRS = include libxfs libxlog libhandle libdisk \ - bmap db freeze fsck growfs imap logprint mkfile mkfs repair rtcp \ + db freeze fsck growfs io imap logprint mkfile mkfs repair rtcp \ man doc po debian build default: $(CONFIGURE) @@ -60,7 +60,7 @@ else clean: # if configure hasn't run, nothing to clean endif -$(CONFIGURE): configure.in +$(CONFIGURE): autoconf ./configure \ --prefix=/ \ diff --git a/VERSION b/VERSION index 487da7931..cb5e8205c 100644 --- a/VERSION +++ b/VERSION @@ -3,5 +3,5 @@ # PKG_MAJOR=2 PKG_MINOR=4 -PKG_REVISION=1 +PKG_REVISION=2 PKG_BUILD=0 diff --git a/configure.in b/configure.in index 1b3da7b20..2f42861fc 100644 --- a/configure.in +++ b/configure.in @@ -160,9 +160,16 @@ dnl will we be making use of gettext? AC_ARG_ENABLE(gettext, [ --enable-gettext=[yes/no] Enable alternate language support [default=yes]],, enable_gettext=yes) -test $enable_gettext = "yes" && AC_DEFINE(ENABLE_GETTEXT) AC_SUBST(enable_gettext) +dnl will we be making use of readline? +AC_ARG_ENABLE(readline, + [ --enable-readline=[yes/no] Enable readline command editing [default=no]],, + enable_readline=no) +libreadline="-lreadline" +AC_SUBST(libreadline) +AC_SUBST(enable_readline) + dnl Checks for UUID header and library. AC_CHECK_HEADER(uuid/uuid.h,, [ echo diff --git a/db/Makefile b/db/Makefile index 54c24b34b..bede36fed 100644 --- a/db/Makefile +++ b/db/Makefile @@ -47,6 +47,11 @@ LLDLIBS = $(LIBXFS) $(LIBXLOG) $(LIBUUID) LTDEPENDENCIES = $(LIBXFS) $(LIBXLOG) LLDFLAGS += -static +ifeq ($(ENABLE_READLINE),yes) +LLDLIBS += $(LIBREADLINE) +CFLAGS += -DENABLE_READLINE +endif + default: $(LTCOMMAND) include $(BUILDRULES) diff --git a/db/input.c b/db/input.c index 0339985de..5cd6f4013 100644 --- a/db/input.c +++ b/db/input.c @@ -39,6 +39,11 @@ #include "malloc.h" #include "init.h" +#ifdef ENABLE_READLINE +# include +# include +#endif + int inputstacksize; FILE **inputstack; FILE *curinput; @@ -142,8 +147,8 @@ doneline( xfree(vec); } -char * -fetchline(void) +static char * +fetchline_internal(void) { char buf[1024]; int iscont; @@ -157,7 +162,7 @@ fetchline(void) if (iscont) dbprintf("... "); else - dbprintf("%s: ", progname); + dbprintf("%s> ", progname); fflush(stdin); } if (seenint() || @@ -214,11 +219,34 @@ fetchline(void) return rval; } -void -input_init(void) +#ifdef ENABLE_READLINE +char * +fetchline(void) { - add_command(&source_cmd); + static char prompt[FILENAME_MAX + 1]; + char *line; + + if (!prompt[0]) + snprintf(prompt, sizeof(prompt), "%s> ", progname); + + if (inputstacksize == 1) { + line = readline(prompt); + if (line && *line) + add_history(line); + else + logprintf("%s", line); + } else { + line = fetchline_internal(); + } + return line; +} +#else +char * +fetchline(void) +{ + return fetchline_internal(); } +#endif static void popfile(void) @@ -268,3 +296,9 @@ source_f( pushfile(f); return 0; } + +void +input_init(void) +{ + add_command(&source_cmd); +} diff --git a/debian/changelog b/debian/changelog index 6fde2d1f6..e54a931fa 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,7 +1,14 @@ +xfsprogs (2.4.2-1) unstable; urgency=low + + * New upstream release + + -- Nathan Scott Tue, 25 Mar 2003 11:25:02 +1100 + xfsprogs (2.4.1-1) unstable; urgency=low * New upstream release - * Note: unwritten extents are now enabled by default in mkfs.xfs. + * Updated policy version this package conforms to + * Note: unwritten extents are now enabled by default in mkfs.xfs -- Nathan Scott Tue, 18 Mar 2003 16:16:43 +1100 diff --git a/debian/control b/debian/control index 3aa81c465..15b7e7736 100644 --- a/debian/control +++ b/debian/control @@ -2,8 +2,8 @@ Source: xfsprogs Section: admin Priority: optional Maintainer: Nathan Scott -Build-Depends: uuid-dev, autoconf, debmake, gettext, libtool -Standards-Version: 3.5.5 +Build-Depends: uuid-dev, autoconf, debmake, gettext, libtool, libreadline4-dev +Standards-Version: 3.5.9 Package: xfsprogs Depends: ${shlibs:Depends} diff --git a/debian/rules b/debian/rules index f49b8bdf7..684624d2f 100755 --- a/debian/rules +++ b/debian/rules @@ -12,8 +12,8 @@ pkgdev = DIST_ROOT=`pwd`/$(dirdev); export DIST_ROOT; pkgbfs = DIST_ROOT=`pwd`/$(dirbfs); export DIST_ROOT; stdenv = @GZIP=-q; export GZIP; -options = DEBUG=-DNDEBUG; DISTRIBUTION=debian; export DEBUG DISTRIBUTION; -bfsopts = OPTIMIZER=-Os; LOCAL_CONFIGURE_OPTIONS="--enable-shared-uuid=yes --enable-gettext=no"; $(options) export OPTIMIZER LOCAL_CONFIGURE_OPTIONS; +options = DEBUG=-DNDEBUG; DISTRIBUTION=debian; LOCAL_CONFIGURE_OPTIONS=--enable-readline=yes; export DEBUG DISTRIBUTION LOCAL_CONFIGURE_OPTIONS; +bfsopts = $(options); OPTIMIZER=-Os; LOCAL_CONFIGURE_OPTIONS="--enable-shared-uuid=yes --enable-gettext=no"; export OPTIMIZER LOCAL_CONFIGURE_OPTIONS; checkdir = test -f debian/rules build: built diff --git a/doc/CHANGES b/doc/CHANGES index 8600ca6bc..e93cb37f5 100644 --- a/doc/CHANGES +++ b/doc/CHANGES @@ -1,4 +1,16 @@ -xfsprogs-2.4.1 (18 March 2002) +xfsprogs-2.4.2 (27 March 2003) + - Added the xfs_io(8) command, an xfs_db(8) alike command + for testing and debugging the XFS file IO path. + - Added an optional dependency on the GNU readline library + which is "off" by default and enabled with the configure + option --enable-readline=yes; it affects the interactive + tools only (xfs_db and now xfs_io). + - Implemented xfs_bmap(8) as a shell script wrapper. + - Documented the mkfs.xfs -f, -llogdev and -rrtdev options. + - Corrected size check for realtime summary inode (not the + same as the realtime bitmap inode) in xfs_repair. + +xfsprogs-2.4.1 (18 March 2003) - Fix error reporting when zeroing parts of the realtime device in phase6 of xfs_repair. - Add a mkfs.xfs check for Mac partitions before writing @@ -7,7 +19,7 @@ xfsprogs-2.4.1 (18 March 2002) - Minor fix to the xfs_bmap(8) man page. - Sync up user/kernel source in libxfs and headers. -xfsprogs-2.4.0 (06 March 2002) +xfsprogs-2.4.0 (06 March 2003) - Enable unwritten extents by default in mkfs.xfs. - Add a command to xfs_db to enable unwritten extents. - Add an option to xfs_admin to use the above command. @@ -22,10 +34,10 @@ xfsprogs-2.4.0 (06 March 2002) - Update man pages, fix a typo in the xfs_admin man page relating to the UUID options. -xfsprogs-2.3.11 (18 February 2002) +xfsprogs-2.3.11 (18 February 2003) - Missed a build dependency for the Debian build process. -xfsprogs-2.3.10 (17 February 2002) +xfsprogs-2.3.10 (17 February 2003) - Fix a divide-by-zero error in mkfs with certain stripe unit and/or width options specified. - Sync up user/kernel source in libxfs and headers. diff --git a/include/builddefs.in b/include/builddefs.in index a8caf6e0a..a224bc389 100644 --- a/include/builddefs.in +++ b/include/builddefs.in @@ -1,5 +1,5 @@ # -# Copyright (c) 2002 Silicon Graphics, Inc. All Rights Reserved. +# Copyright (c) 2003 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 @@ -40,6 +40,7 @@ OPTIMIZER = @opt_build@ MALLOCLIB = @malloc_lib@ LIBUUID = @libuuid@ +LIBREADLINE = @libreadline@ LIBXFS = $(TOPDIR)/libxfs/libxfs.la LIBXLOG = $(TOPDIR)/libxlog/libxlog.la LIBDISK = $(TOPDIR)/libdisk/libdisk.la @@ -87,6 +88,7 @@ RPM_VERSION = @rpm_version@ ENABLE_SHARED = @enable_shared@ ENABLE_GETTEXT = @enable_gettext@ +ENABLE_READLINE = @enable_readline@ HAVE_ZIPPED_MANPAGES = @have_zipped_manpages@ LCFLAGS += -DXFS_BIG_FILES=1 -DXFS_BIG_FILESYSTEMS=1 diff --git a/include/xfs_fs.h b/include/xfs_fs.h index c66ccc57e..c008c24d5 100644 --- a/include/xfs_fs.h +++ b/include/xfs_fs.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995-2002 Silicon Graphics, Inc. All Rights Reserved. + * Copyright (c) 1995-2003 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.1 of the GNU Lesser General Public License @@ -472,7 +472,7 @@ typedef struct xfs_handle { #define XFS_IOC_FSGROWFSLOG _IOW ('X', 111, struct xfs_growfs_log) #define XFS_IOC_FSGROWFSRT _IOW ('X', 112, struct xfs_growfs_rt) #define XFS_IOC_FSCOUNTS _IOR ('X', 113, struct xfs_fsop_counts) -#define XFS_IOC_SET_RESBLKS _IOR ('X', 114, struct xfs_fsop_resblks) +#define XFS_IOC_SET_RESBLKS _IOWR('X', 114, struct xfs_fsop_resblks) #define XFS_IOC_GET_RESBLKS _IOR ('X', 115, struct xfs_fsop_resblks) #define XFS_IOC_ERROR_INJECTION _IOW ('X', 116, struct xfs_error_injection) #define XFS_IOC_ERROR_CLEARALL _IOW ('X', 117, struct xfs_error_injection) diff --git a/bmap/Makefile b/io/Makefile similarity index 77% rename from bmap/Makefile rename to io/Makefile index 7da8012ad..6cf4c8d54 100644 --- a/bmap/Makefile +++ b/io/Makefile @@ -1,5 +1,5 @@ # -# Copyright (c) 2000-2001 Silicon Graphics, Inc. All Rights Reserved. +# Copyright (c) 2000-2003 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 @@ -33,8 +33,17 @@ TOPDIR = .. include $(TOPDIR)/include/builddefs -LTCOMMAND = xfs_bmap -CFILES = xfs_bmap.c +LTCOMMAND = xfs_io +HFILES = command.h input.h init.h +CFILES = command.c input.c init.c \ + bmap.c fsync.c help.c open.c pread.c prealloc.c pwrite.c \ + quit.c resblks.c truncate.c +LSRCFILES = xfs_bmap.sh + +ifeq ($(ENABLE_READLINE),yes) +LLDLIBS += $(LIBREADLINE) +CFLAGS += -DENABLE_READLINE +endif default: $(LTCOMMAND) @@ -43,4 +52,5 @@ include $(BUILDRULES) install: default $(INSTALL) -m 755 -d $(PKG_BIN_DIR) $(LTINSTALL) -m 755 $(LTCOMMAND) $(PKG_BIN_DIR) + $(LTINSTALL) -m 755 xfs_bmap.sh $(PKG_BIN_DIR)/xfs_bmap install-dev: diff --git a/bmap/xfs_bmap.c b/io/bmap.c similarity index 73% rename from bmap/xfs_bmap.c rename to io/bmap.c index a24dfb8f2..09d11a7c7 100644 --- a/bmap/xfs_bmap.c +++ b/io/bmap.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2002 Silicon Graphics, Inc. All Rights Reserved. + * Copyright (c) 2000-2003 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 @@ -30,47 +30,85 @@ * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/ */ -/* - * Bmap display utility for xfs. - */ - #include -#include -#include +#include "command.h" +#include "init.h" -int aflag = 0; /* Attribute fork. */ -int lflag = 0; /* list number of blocks with each extent */ -int nflag = 0; /* number of extents specified */ -int vflag = 0; /* Verbose output */ -int bmv_iflags = 0; /* Input flags for XFS_IOC_GETBMAPX */ -char *progname; +static cmdinfo_t bmap_cmd; -int dofile(char *); -off64_t file_size(int fd, char * fname); -int numlen(off64_t); +static int +usage(void) +{ + printf("%s %s\n", bmap_cmd.name, bmap_cmd.oneline); + return 0; +} -int -main(int argc, char **argv) +static void +bmap_help(void) { - char *fname; - int i = 0; - int option; + printf(_( +"\n" +" prints the block mapping for an XFS file's data or attribute forks" +"\n" +" Example:\n" +" 'bmap -vp' - tabular format verbose map, including unwritten extents\n" +"\n" +" bmap prints the map of disk blocks used by the current file.\n" +" The map lists each extent used by the file, as well as regions in the\n" +" file that do not have any corresponding blocks (holes).\n" +" By default, each line of the listing takes the following form:\n" +" extent: [startoffset..endoffset]: startblock..endblock\n" +" 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" +" -d -- suppresses a DMAPI read event, offline portions shown as holes.\n" +" -l -- also displays the length of each extent in 512-byte blocks.\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")); +} - progname = basename(argv[0]); - setlocale(LC_ALL, ""); - bindtextdomain(PACKAGE, LOCALEDIR); - textdomain(PACKAGE); +static int +numlen( + off64_t val) +{ + off64_t tmp; + int len; - while ((option = getopt(argc, argv, "adln:pvV")) != EOF) { - switch (option) { - case 'a': + for (len = 0, tmp = val; tmp > 0; tmp = tmp/10) + len++; + return (len == 0 ? 1 : len); +} + +int +bmap_f( + int argc, + char **argv) +{ + struct fsxattr fsx; + struct getbmapx *map; + struct xfs_fsop_geom_v1 fsgeo; + int map_size; + int loop = 0; + int flg = 0; + int aflag = 0; + int lflag = 0; + int nflag = 0; + int vflag = 0; + int bmv_iflags = 0; /* flags for XFS_IOC_GETBMAPX */ + int i = 0; + int c; + + while ((c = getopt(argc, argv, "adln:pv")) != EOF) { + switch (c) { + case 'a': /* Attribute fork. */ bmv_iflags |= BMV_IF_ATTRFORK; aflag = 1; break; - case 'l': + case 'l': /* list number of blocks with each extent */ lflag = 1; break; - case 'n': + case 'n': /* number of extents specified */ nflag = atoi(optarg); break; case 'd': @@ -81,105 +119,32 @@ main(int argc, char **argv) /* report unwritten preallocated blocks */ bmv_iflags |= BMV_IF_PREALLOC; break; - case 'v': + case 'v': /* Verbose output */ vflag++; break; - case 'V': - printf(_("%s version %s\n"), progname, VERSION); - exit(0); default: - fprintf(stderr, - _("Usage: %s [-adlpV] [-n nx] file...\n"), - progname); - exit(1); + return usage(); } } if (aflag) - bmv_iflags &= ~(BMV_IF_PREALLOC|BMV_IF_NO_DMAPI_READ); - while (optind < argc) { - fname = argv[optind]; - i += dofile(fname); - optind++; - } - return(i ? 1 : 0); -} - -off64_t -file_size(int fd, char *fname) -{ - struct stat64 st; - int i; - int errno_save; - - errno_save = errno; /* in case fstat64 fails */ - i = fstat64(fd, &st); - if (i < 0) { - fprintf(stderr, _("%s: fstat64 failed for %s: %s\n"), - progname, fname, strerror(errno)); - errno = errno_save; - return -1; - } - return st.st_size; -} - - -int -dofile(char *fname) -{ - int i; - int fd; - struct statfs buf; - struct fsxattr fsx; - struct getbmapx *map; - int map_size; - int loop = 0; - xfs_fsop_geom_v1_t fsgeo; - int flg = 0; - - fd = open(fname, O_RDONLY); - if (fd < 0) { - fprintf(stderr, _("%s: cannot open \"%s\": %s\n"), - progname, fname, strerror(errno)); - return 1; - } - fstatfs(fd, &buf); - if (statfstype(&buf) != XFS_SUPER_MAGIC) { - fprintf(stderr, _("%s: specified file " - "[\"%s\"] is not on an XFS filesystem\n"), - progname, fname); - close(fd); - return 1; - } + bmv_iflags &= ~(BMV_IF_PREALLOC|BMV_IF_NO_DMAPI_READ); if (vflag) { - if (ioctl(fd, XFS_IOC_FSGEOMETRY_V1, &fsgeo) < 0) { + if (ioctl(fdesc, XFS_IOC_FSGEOMETRY_V1, &fsgeo) < 0) { fprintf(stderr, _("%s: can't get geometry [\"%s\"]: %s\n"), progname, fname, strerror(errno)); - close(fd); - return 1; + exitcode = 1; + return 0; } - - if (vflag > 1) - printf(_( - "xfs_bmap: fsgeo.agblocks=%u, fsgeo.blocksize=%u, fsgeo.agcount=%u\n"), - fsgeo.agblocks, fsgeo.blocksize, - fsgeo.agcount); - - if ((ioctl(fd, XFS_IOC_FSGETXATTR, &fsx)) < 0) { + if ((ioctl(fdesc, XFS_IOC_FSGETXATTR, &fsx)) < 0) { fprintf(stderr, _("%s: cannot read attrs on \"%s\": %s\n"), progname, fname, strerror(errno)); - close(fd); - return 1; + exitcode = 1; + return 0; } - if (vflag > 1) - printf(_( - "xfs_bmap: fsx.dsx_xflags=%u, fsx.fsx_extsize=%u, fsx.fsx_nextents=%u\n"), - fsx.fsx_xflags, fsx.fsx_extsize, - fsx.fsx_nextents); - if (fsx.fsx_xflags == XFS_XFLAG_REALTIME) { /* * ag info not applicable to rt, continue @@ -189,13 +154,13 @@ dofile(char *fname) } } - map_size = nflag ? nflag+1 : 32; /* initial guess - 256 for checkin KCM */ + map_size = nflag ? nflag+1 : 32; /* initial guess - 256 */ map = malloc(map_size*sizeof(*map)); if (map == NULL) { fprintf(stderr, _("%s: malloc of %d bytes failed.\n"), progname, (int)(map_size * sizeof(*map))); - close(fd); - return 1; + exitcode = 1; + return 0; } @@ -234,28 +199,19 @@ dofile(char *fname) map->bmv_count = map_size; map->bmv_iflags = bmv_iflags; - i = ioctl(fd, XFS_IOC_GETBMAPX, map); - - if (vflag > 1) - printf(_( - "xfs_bmap: i=%d map.bmv_offset=%lld, map.bmv_block=%lld, " - "map.bmv_length=%lld, map.bmv_count=%d, map.bmv_entries=%d\n"), - i, (long long)map->bmv_offset, - (long long)map->bmv_block, - (long long)map->bmv_length, - map->bmv_count, map->bmv_entries); + i = ioctl(fdesc, XFS_IOC_GETBMAPX, map); if (i < 0) { if ( errno == EINVAL - && !aflag && file_size(fd, fname) == 0) { + && !aflag && filesize() == 0) { break; } else { fprintf(stderr, _("%s: ioctl(XFS_IOC_GETBMAPX) " "iflags=0x%x [\"%s\"]: %s\n"), progname, map->bmv_iflags, fname, strerror(errno)); - close(fd); free(map); - return 1; + exitcode = 1; + return 0; } } if (nflag) @@ -265,14 +221,15 @@ dofile(char *fname) /* Get number of extents from ioctl XFS_IOC_FSGETXATTR[A] * syscall. */ - i = ioctl(fd, aflag ? XFS_IOC_FSGETXATTRA : XFS_IOC_FSGETXATTR, &fsx); + i = ioctl(fdesc, aflag ? + XFS_IOC_FSGETXATTRA : XFS_IOC_FSGETXATTR, &fsx); if (i < 0) { fprintf(stderr, _("%s: ioctl(XFS_IOC_FSGETXATTR%s) " "[\"%s\"]: %s\n"), progname, aflag ? "A" : "", fname, strerror(errno)); - close(fd); free(map); - return 1; + exitcode = 1; + return 0; } if (fsx.fsx_nextents >= map_size-1) { map_size = 2*(fsx.fsx_nextents+1); @@ -281,20 +238,18 @@ dofile(char *fname) fprintf(stderr, _("%s: cannot realloc %d bytes\n"), progname, (int)(map_size*sizeof(*map))); - close(fd); - return 1; + exitcode = 1; + return 0; } } } while (++loop < 2); if (!nflag) { if (map->bmv_entries <= 0) { printf(_("%s: no extents\n"), fname); - close(fd); free(map); return 0; } } - close(fd); printf("%s:\n", fname); if (!vflag) { for (i = 0; i < map->bmv_entries; i++) { @@ -341,7 +296,7 @@ dofile(char *fname) foff_w = boff_w = aoff_w = MINRANGE_WIDTH; tot_w = MINTOT_WIDTH; bbperag = (off64_t)fsgeo.agblocks * - (off64_t)fsgeo.blocksize / BBSIZE; + (off64_t)fsgeo.blocksize / BBSIZE; sunit = fsgeo.sunit; swidth = fsgeo.swidth; @@ -423,7 +378,7 @@ dofile(char *fname) 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\n", + printf("%4d: %-*s %-*s %*d %-*s %*lld", i, foff_w, rbuf, boff_w, bbuf, @@ -453,12 +408,16 @@ dofile(char *fname) return 0; } -int -numlen(off64_t val) +void +bmap_init(void) { - off64_t tmp; - int len; + bmap_cmd.name = _("bmap"); + bmap_cmd.cfunc = bmap_f; + bmap_cmd.argmin = 0; + bmap_cmd.argmax = -1; + bmap_cmd.args = _("[-adlpv] [-n nx]"); + bmap_cmd.oneline = _("print block mapping for an XFS file"); + bmap_cmd.help = bmap_help; - for (len=0, tmp=val; tmp > 0; tmp=tmp/10) len++; - return(len == 0 ? 1 : len); + add_command(&bmap_cmd); } diff --git a/io/command.c b/io/command.c new file mode 100644 index 000000000..af7ea0e3f --- /dev/null +++ b/io/command.c @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2003 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/ + */ + +#include +#include "command.h" + +cmdinfo_t *cmdtab; +int ncmds; + +static int +cmd_compare(const void *a, const void *b) +{ + return strcmp(((const cmdinfo_t *)a)->name, + ((const cmdinfo_t *)b)->name); +} + +void +add_command( + const cmdinfo_t *ci) +{ + cmdtab = realloc((void *)cmdtab, ++ncmds * sizeof(*cmdtab)); + cmdtab[ncmds - 1] = *ci; + qsort(cmdtab, ncmds, sizeof(*cmdtab), cmd_compare); +} + +int +command( + int argc, + char **argv) +{ + char *cmd; + const cmdinfo_t *ct; + + cmd = argv[0]; + ct = find_command(cmd); + if (!ct) { + fprintf(stderr, _("command \"%s\" not found\n"), cmd); + return 0; + } + if (argc-1 < ct->argmin || (ct->argmax != -1 && argc-1 > ct->argmax)) { + if (ct->argmax == -1) + fprintf(stderr, + _("bad argument count %d to %s, expected at least %d arguments\n"), + argc-1, cmd, ct->argmin); + else if (ct->argmin == ct->argmax) + fprintf(stderr, + _("bad argument count %d to %s, expected %d arguments\n"), + argc-1, cmd, ct->argmin); + else + fprintf(stderr, + _("bad argument count %d to %s, expected between %d and %d arguments\n"), + argc-1, cmd, ct->argmin, ct->argmax); + return 0; + } + optind = 0; + return ct->cfunc(argc, argv); +} + +const cmdinfo_t * +find_command( + const char *cmd) +{ + cmdinfo_t *ct; + + for (ct = cmdtab; ct < &cmdtab[ncmds]; ct++) { + if (strcmp(ct->name, cmd) == 0 || + (ct->altname && strcmp(ct->altname, cmd) == 0)) + return (const cmdinfo_t *)ct; + } + return NULL; +} + +void +init_commands(void) +{ + bmap_init(); + help_init(); + open_init(); + pread_init(); + prealloc_init(); + pwrite_init(); + quit_init(); + resblks_init(); + fsync_init(); + truncate_init(); +} diff --git a/io/command.h b/io/command.h new file mode 100644 index 000000000..4890a8a96 --- /dev/null +++ b/io/command.h @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2000-2003 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/ + */ + +#define min(a,b) (((a)<(b))?(a):(b)) + +typedef int (*cfunc_t)(int argc, char **argv); +typedef void (*helpfunc_t)(void); + +typedef struct cmdinfo { + const char *name; + const char *altname; + cfunc_t cfunc; + int argmin; + int argmax; + int canpush; + const char *args; + const char *oneline; + helpfunc_t help; +} cmdinfo_t; + +extern cmdinfo_t *cmdtab; +extern int ncmds; + +extern void add_command(const cmdinfo_t *ci); +extern int command(int argc, char **argv); +extern const cmdinfo_t *find_command(const char *cmd); +extern void init_commands(void); + +extern void bmap_init(void); +extern void help_init(void); +extern void open_init(void); +extern void pread_init(void); +extern void prealloc_init(void); +extern void pwrite_init(void); +extern void quit_init(void); +extern void resblks_init(void); +extern void fsync_init(void); +extern void truncate_init(void); + +extern off64_t filesize(void); +extern int openfile(char *, int, int, int, int, int, int, int); + +extern void *buffer; +extern ssize_t buffersize; +extern int alloc_buffer(ssize_t, unsigned int); +extern int read_buffer(int, off64_t, ssize_t, ssize_t *, int, int); diff --git a/io/help.c b/io/help.c new file mode 100644 index 000000000..eca80eff2 --- /dev/null +++ b/io/help.c @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2003 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/ + */ + +#include +#include "command.h" + +static cmdinfo_t help_cmd; +static void help_onecmd(const char *cmd, const cmdinfo_t *ct); +static void help_oneline(const char *cmd, const cmdinfo_t *ct); + +static void +help_all(void) +{ + const cmdinfo_t *ct; + + for (ct = cmdtab; ct < &cmdtab[ncmds]; ct++) + help_oneline(ct->name, ct); + printf(_("\nUse 'help commandname' for extended help.\n")); +} + +static int +help_f( + int argc, + char **argv) +{ + const cmdinfo_t *ct; + + if (argc == 1) { + help_all(); + return 0; + } + ct = find_command(argv[1]); + if (ct == NULL) { + printf(_("command %s not found\n"), argv[1]); + return 0; + } + help_onecmd(argv[1], ct); + return 0; +} + +static void +help_onecmd( + const char *cmd, + const cmdinfo_t *ct) +{ + help_oneline(cmd, ct); + if (ct->help) + ct->help(); +} + +static void +help_oneline( + const char *cmd, + const cmdinfo_t *ct) +{ + if (cmd) + printf("%s ", cmd); + else { + printf("%s ", ct->name); + if (ct->altname) + printf("(or %s) ", ct->altname); + } + if (ct->args) + printf("%s ", ct->args); + printf("-- %s\n", ct->oneline); +} + +void +help_init(void) +{ + help_cmd.name = _("help"); + help_cmd.altname = _("?"); + help_cmd.cfunc = help_f; + help_cmd.argmin = 0; + help_cmd.argmax = 1; + help_cmd.args = _("[command]"); + help_cmd.oneline = _("help for one or all commands"); + + add_command(&help_cmd); +} diff --git a/io/init.c b/io/init.c new file mode 100644 index 000000000..8d4731c3f --- /dev/null +++ b/io/init.c @@ -0,0 +1,155 @@ +/* + * Copyright (c) 2003 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/ + */ + +#include +#include "input.h" +#include "command.h" + +int fdesc; +char *fname; +char *progname; +int exitcode; + +int readonly; +int directio; +int realtime; +int append; +int osync; +int trunc; + +static int ncmdline; +static char **cmdline; + +void +usage(void) +{ + fprintf(stderr, + _("Usage: %s [-r] [-p prog] [-c cmd]... file\n"), progname); + exit(1); +} + +void +init( + int argc, + char **argv) +{ + int c; + + progname = basename(argv[0]); + setlocale(LC_ALL, ""); + bindtextdomain(PACKAGE, LOCALEDIR); + textdomain(PACKAGE); + + while ((c = getopt(argc, argv, "ac:dfp:rstVx")) != EOF) { + switch (c) { + case 'a': /* append */ + append = 1; + break; + case 'c': /* commands */ + ncmdline++; + cmdline = realloc(cmdline, sizeof(char*) * (ncmdline)); + if (!cmdline) { + perror("realloc"); + exit(1); + } + cmdline[ncmdline-1] = optarg; + break; + case 'd': /* directIO */ + directio = 1; + break; + case 'f': /* ignore */ + break; + case 'p': /* progname */ + progname = optarg; + break; + case 'r': /* readonly */ + readonly = 1; + break; + case 's': /* sync */ + osync = 1; + break; + case 't': /* truncate */ + trunc = 1; + break; + case 'x': /* realtime */ + realtime = 1; + break; + case 'V': + printf(_("%s version %s\n"), progname, VERSION); + exit(0); + default: + usage(); + } + } + + if (optind != argc - 1) + usage(); + + fname = strdup(argv[optind]); + if ((fdesc = openfile(fname, append, 0, directio, + readonly, osync, trunc, realtime)) < 0) + exit(1); + + init_commands(); +} + +int +main( + int argc, + char **argv) +{ + int c, i, done = 0; + char *input; + char **v; + + init(argc, argv); + + for (i = 0; !done && i < ncmdline; i++) { + v = breakline(cmdline[i], &c); + if (c) + done = command(c, v); + free(v); + } + if (cmdline) { + free(cmdline); + return exitcode; + } + while (!done) { + if ((input = fetchline()) == NULL) + break; + v = breakline(input, &c); + if (c) + done = command(c, v); + doneline(input, v); + } + return exitcode; +} diff --git a/io/init.h b/io/init.h new file mode 100644 index 000000000..a49a15e8e --- /dev/null +++ b/io/init.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2003 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/ + */ + +extern int fdesc; +extern char *fname; +extern int exitcode; +extern char *progname; + +extern int readonly; +extern int directio; +extern int realtime; +extern int append; +extern int osync; +extern int trunc; diff --git a/io/input.c b/io/input.c new file mode 100644 index 000000000..c91e824da --- /dev/null +++ b/io/input.c @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2003 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/ + */ + +#include +#include "input.h" +#include "init.h" + +#ifdef ENABLE_READLINE +# include +# include +#else +# define MAXREADLINESZ 1024 +static char * +readline(char *prompt) +{ + char *p, *line = malloc(MAXREADLINESZ); + + if (!line) + return NULL; + printf(prompt); + fflush(stdout); + if (!fgets(line, MAXREADLINESZ, stdin)) { + free(line); + return NULL; + } + p = line + strlen(line); + if (p != line && p[-1] == '\n') + p[-1] = '\0'; + return line; +} +static void add_history(char *line) { } +# undef MAXREADLINESZ +#endif + +char * +fetchline(void) +{ + static char prompt[FILENAME_MAX + 1]; + char *line; + + if (!prompt[0]) + snprintf(prompt, sizeof(prompt), "%s> ", progname); + line = readline(prompt); + if (line && *line) + add_history(line); + return line; +} + +char ** +breakline( + char *input, + int *count) +{ + int c = 0; + char *p; + char **rval = calloc(sizeof(char *), 1); + + while ((p = strsep(&input, " ")) != NULL) { + if (!*p) + continue; + c++; + rval = realloc(rval, sizeof(*rval) * (c + 1)); + rval[c - 1] = p; + rval[c] = NULL; + } + *count = c; + return rval; +} + +void +doneline( + char *input, + char **vec) +{ + free(input); + free(vec); +} diff --git a/io/input.h b/io/input.h new file mode 100644 index 000000000..b4971466f --- /dev/null +++ b/io/input.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2000-2003 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/ + */ + +extern char **breakline(char *input, int *count); +extern void doneline(char *input, char **vec); +extern char *fetchline(void); diff --git a/io/open.c b/io/open.c new file mode 100644 index 000000000..c479a3be8 --- /dev/null +++ b/io/open.c @@ -0,0 +1,354 @@ +/* + * Copyright (c) 2003 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/ + */ + +#include +#include "command.h" +#include "init.h" + +static cmdinfo_t open_cmd; +static cmdinfo_t stat_cmd; +static cmdinfo_t statfs_cmd; +static int stat_f(int, char **); + +int +openfile( + char *filename, + int aflag, + int cflag, + int dflag, + int rflag, + int sflag, + int tflag, + int xflag) +{ + int fd; + int oflags; + struct statfs buf; + + oflags = (rflag ? O_RDONLY : O_RDWR); + if (aflag) + oflags |= O_APPEND; + if (cflag) + oflags |= O_CREAT; + if (dflag) + oflags |= O_DIRECT; + if (sflag) + oflags |= O_SYNC; + if (tflag) + oflags |= O_TRUNC; + + fd = open(filename, oflags, 0666); + if (fd < 0) { + perror(filename); + return -1; + } + fstatfs(fd, &buf); + if (statfstype(&buf) != XFS_SUPER_MAGIC) { + fprintf(stderr, _("%s: specified file " + "[\"%s\"] is not on an XFS filesystem\n"), + progname, fname); + close(fd); + return -1; + } + + if (!readonly && xflag) { /* read/write and realtime */ + struct fsxattr attr; + + if (ioctl(fd, XFS_IOC_FSGETXATTR, &attr) < 0) { + perror("XFS_IOC_FSGETXATTR"); + close(fd); + return -1; + } + if (!(attr.fsx_xflags & XFS_XFLAG_REALTIME)) { + attr.fsx_xflags |= XFS_XFLAG_REALTIME; + if (ioctl(fd, XFS_IOC_FSSETXATTR, &attr) < 0) { + perror("XFS_IOC_FSSETXATTR"); + close(fd); + return -1; + } + } + } + return fd; +} + +static int +usage(void) +{ + printf("%s %s\n", open_cmd.name, open_cmd.oneline); + return 0; +} + +static void +open_help(void) +{ + printf(_( +"\n" +" opens a new file in the requested mode, after closing the current file\n" +"\n" +" Example:\n" +" 'open -d /tmp/data' - opens data file read-write for direct IO\n" +"\n" +" Opens a file for subsequent use by all of the other xfs_io commands.\n" +" With no arguments, open uses the stat command to show the current file.\n" +" -a -- open with the O_APPEND flag (append-only mode)\n" +" -c -- open with O_CREAT (create the file if it doesn't exist)\n" +" -d -- open with O_DIRECT (non-buffered IO, note alignment constraints)\n" +" -r -- open with O_RDONLY, the default is O_RDWR\n" +" -s -- open with O_SYNC\n" +" -t -- open with O_TRUNC (truncate the file to zero length if it exists)\n" +" -x -- mark the file as a realtime XFS file immediately after opening it\n" +" Note1: read/write direct IO requests must be blocksize aligned.\n" +" Note2: 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 +open_f( + int argc, + char **argv) +{ + int aflag = 0; + int cflag = 0; + int dflag = 0; + int rflag = 0; + int sflag = 0; + int tflag = 0; + int xflag = 0; + char *filename; + int fd; + int c; + + if (argc == 1) + return stat_f(argc, argv); + + while ((c = getopt(argc, argv, "acdrstx")) != EOF) { + switch (c) { + case 'a': + aflag = 1; + break; + case 'c': + cflag = 1; + break; + case 'd': + dflag = 1; + break; + case 'r': + rflag = 1; + break; + case 's': + sflag = 1; + break; + case 't': + tflag = 1; + break; + case 'x': + xflag = 1; + break; + default: + return usage(); + } + } + + if (optind != argc - 1) + return usage(); + + fd = openfile(argv[optind], + aflag, cflag, dflag, rflag, sflag, tflag, xflag); + if (fd < 0) + return 0; + + filename = strdup(argv[optind]); + if (!filename) { + perror("strdup"); + close(fd); + return 0; + } + + /* + * All OK, proceed to make this the new global open file + */ + osync = sflag; + trunc = tflag; + append = aflag; + directio = dflag; + readonly = rflag; + realtime = xflag; + if (fname) { + close(fdesc); + free(fname); + } + fname = filename; + fdesc = fd; + return 0; +} + +off64_t +filesize(void) +{ + struct stat64 st; + + if (fstat64(fdesc, &st) < 0) { + perror("fstat64"); + return -1; + } + return st.st_size; +} + +static char * +filetype(mode_t mode) +{ + switch (mode & S_IFMT) { + case S_IFSOCK: + return _("socket"); + case S_IFDIR: + return _("directory"); + case S_IFCHR: + return _("char device"); + case S_IFBLK: + return _("block device"); + case S_IFREG: + return _("regular file"); + case S_IFLNK: + return _("symbolic link"); + case S_IFIFO: + return _("fifo"); + } + return NULL; +} + +static int +stat_f( + int argc, + char **argv) +{ + struct fsxattr fsx; + struct stat64 st; + char fullname[PATH_MAX + 1]; + + printf(_("fd.path = \"%s\"\n"), + realpath(fname, fullname) ? fullname : fname); + printf(_("fd.flags = %s,%s,%s%s%s\n"), + osync ? _("sync") : _("non-sync"), + directio ? _("direct") : _("non-direct"), + readonly ? _("read-only") : _("read-write"), + realtime ? _(",real-time") : "", + append ? _(",append-only") : ""); + if (fstat64(fdesc, &st) < 0) { + perror("fstat64"); + } else { + printf(_("stat.ino = %lld\n"), (long long)st.st_ino); + printf(_("stat.type = %s\n"), filetype(st.st_mode)); + printf(_("stat.size = %lld\n"), (long long)st.st_size); + printf(_("stat.blocks = %lld\n"), (long long)st.st_blocks); + if (argc == 2 && !strcmp(argv[1], "-v")) { + printf(_("stat.atime = %s"), ctime(&st.st_atime)); + printf(_("stat.mtime = %s"), ctime(&st.st_mtime)); + printf(_("stat.ctime = %s"), ctime(&st.st_ctime)); + } + } + if ((ioctl(fdesc, XFS_IOC_FSGETXATTR, &fsx)) < 0) { + perror("XFS_IOC_FSGETXATTR"); + } else { + printf(_("xattr.xflags = 0x%x\n"), fsx.fsx_xflags); + printf(_("xattr.nextents = %u\n"), fsx.fsx_nextents); + } + return 0; +} + +static int +statfs_f( + int argc, + char **argv) +{ + struct xfs_fsop_geom_v1 fsgeo; + struct statfs st; + char fullname[PATH_MAX + 1]; + + printf(_("fd.path = \"%s\"\n"), + realpath(fname, fullname) ? fullname : fname); + if (fstatfs(fdesc, &st) < 0) { + perror("fstatfs"); + } else { + printf(_("statfs.f_bsize = %lld\n"), (long long) st.f_bsize); + printf(_("statfs.f_blocks = %lld\n"), (long long) st.f_blocks); + printf(_("statfs.f_bavail = %lld\n"), (long long) st.f_bavail); + } + if ((ioctl(fdesc, XFS_IOC_FSGEOMETRY_V1, &fsgeo)) < 0) { + perror("XFS_IOC_FSGEOMETRY_V1"); + } else { + printf(_("geom.bsize = %u\n"), fsgeo.blocksize); + printf(_("geom.agcount = %u\n"), fsgeo.agcount); + printf(_("geom.agblocks = %u\n"), fsgeo.agblocks); + printf(_("geom.datablocks = %llu\n"), + (unsigned long long) fsgeo.datablocks); + printf(_("geom.rtblocks = %llu\n"), + (unsigned long long) fsgeo.rtblocks); + printf(_("geom.rtextents = %llu\n"), + (unsigned long long) fsgeo.rtextents); + printf(_("geom.rtextsize = %u\n"), fsgeo.rtextsize); + printf(_("geom.sunit = %u\n"), fsgeo.sunit); + printf(_("geom.swidth = %u\n"), fsgeo.swidth); + } + return 0; +} + +void +open_init(void) +{ + open_cmd.name = _("open"); + open_cmd.altname = _("o"); + open_cmd.cfunc = open_f; + open_cmd.argmin = 0; + open_cmd.argmax = -1; + open_cmd.args = _("[-acdrstx] [path]"); + open_cmd.oneline = + _("close the current file, open file specified by path"); + open_cmd.help = open_help; + + stat_cmd.name = _("stat"); + stat_cmd.cfunc = stat_f; + stat_cmd.argmin = 0; + stat_cmd.argmax = 1; + stat_cmd.args = _("[-v]"); + stat_cmd.oneline = + _("statistics on the currently open file"); + + statfs_cmd.name = _("statfs"); + statfs_cmd.cfunc = statfs_f; + statfs_cmd.oneline = + _("statistics on the filesystem of the currently open file"); + + add_command(&open_cmd); + add_command(&stat_cmd); + add_command(&statfs_cmd); +} diff --git a/io/pread.c b/io/pread.c new file mode 100644 index 000000000..1e69beaa2 --- /dev/null +++ b/io/pread.c @@ -0,0 +1,202 @@ +/* + * Copyright (c) 2003 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/ + */ + +#include +#include +#include "command.h" +#include "input.h" +#include "init.h" + +static cmdinfo_t pread_cmd; + +static void +pread_help(void) +{ + printf(_( +"\n" +" reads a range of bytes in a specified block size from the given offset\n" +"\n" +" Example:\n" +" 'read -v 512 20' - dumps 20 bytes read from 512 bytes into the file\n" +"\n" +" Reads a segment of the currently open file, optionally dumping it to the\n" +" standard output stream (with -v option) for subsequent inspection.\n" +" The reads are performed in sequential blocks starting at offset, with the\n" +" blocksize tunable using the -b option (default blocksize is 4096 bytes).\n" +"\n")); +} + +void *buffer; +ssize_t buffersize; + +int +alloc_buffer( + ssize_t bsize, + unsigned int seed) +{ + if (bsize > buffersize) { + buffer = realloc(buffer, buffersize = bsize); + if (!buffer) { + perror("realloc"); + buffersize = 0; + return 0; + } + } + memset(buffer, seed, buffersize); + return 1; +} + +static void +dump_buffer( + off64_t offset, + ssize_t len) +{ + int i, j; + char *p; + + for (i = 0, p = (char *)buffer; i < len; i += 16) { + char *s = p; + + printf("%08llx: ", (off64_t)i + offset); + for (j = 0; j < 16 && i + j < len; j++, p++) + printf("%02x ", *p); + printf(" "); + for (j = 0; j < 16 && i + j < len; j++, s++) { + if (isalnum(*s)) + printf("%c", *s); + else + printf("."); + } + printf("\n"); + } +} + +int +read_buffer( + int fd, + off64_t offset, + ssize_t count, + ssize_t *total, + int verbose, + int onlyone) +{ + ssize_t bytes; + + *total = 0; + while (count > 0) { + bytes = pread64(fd, buffer, min(count,buffersize), offset); + if (bytes == 0) + break; + if (bytes < 0) { + perror("pread64"); + return 0; + } + if (verbose) + dump_buffer(offset, bytes); + *total += bytes; + if (onlyone || bytes < count) + break; + offset += bytes; + count -= bytes; + } + return 1; +} + +static int +pread_f( + int argc, + char **argv) +{ + off64_t offset; + ssize_t count, total; + unsigned int bsize = 4096; + char *sp; + int vflag = 0; + int c; + + while ((c = getopt(argc, argv, "b:v")) != EOF) { + switch (c) { + case 'b': + bsize = strtoul(optarg, &sp, 0); + if (!sp || sp == optarg) { + printf(_("non-numeric bsize -- %s\n"), optarg); + return 0; + } + break; + case 'v': + vflag = 1; + break; + default: + printf("%s %s\n", pread_cmd.name, pread_cmd.oneline); + return 0; + } + } + if (optind != argc - 2) { + printf("%s %s\n", pread_cmd.name, pread_cmd.oneline); + return 0; + } + offset = strtoul(argv[optind], &sp, 0); + if (!sp || sp == argv[optind]) { + printf(_("non-numeric offset argument -- %s\n"), argv[optind]); + return 0; + } + optind++; + count = strtoul(argv[optind], &sp, 0); + if (!sp || sp == argv[optind]) { + printf(_("non-numeric length argument -- %s\n"), argv[optind]); + return 0; + } + + if (!alloc_buffer(bsize, 0xabababab)) + return 0; + + if (!read_buffer(fdesc, offset, count, &total, vflag, 0)) + return 0; + + printf(_("read %u/%u bytes at offset %llu\n"), total, count, offset); + return 0; +} + +void +pread_init(void) +{ + pread_cmd.name = _("pread"); + pread_cmd.altname = _("r"); + pread_cmd.cfunc = pread_f; + pread_cmd.argmin = 2; + pread_cmd.argmax = -1; + pread_cmd.args = _("[-b bs] [-v] off len"); + pread_cmd.oneline = _("reads a number of bytes at a specified offset"); + pread_cmd.help = pread_help; + + add_command(&pread_cmd); +} diff --git a/io/prealloc.c b/io/prealloc.c new file mode 100644 index 000000000..128bcd588 --- /dev/null +++ b/io/prealloc.c @@ -0,0 +1,170 @@ +/* + * Copyright (c) 2003 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/ + */ + +#include +#include "command.h" +#include "init.h" + +static cmdinfo_t allocsp_cmd; +static cmdinfo_t freesp_cmd; +static cmdinfo_t resvsp_cmd; +static cmdinfo_t unresvsp_cmd; + +static int +offset_length( + char *offset, + char *length, + xfs_flock64_t *segment) +{ + char *sp; + + memset(segment, 0, sizeof(*segment)); + segment->l_whence = SEEK_SET; + segment->l_start = strtoul(offset, &sp, 0); + if (!sp || sp == offset) { + printf(_("non-numeric offset argument -- %s\n"), offset); + return 0; + } + segment->l_len = strtoul(length, &sp, 0); + if (!sp || sp == length) { + printf(_("non-numeric length argument -- %s\n"), length); + return 0; + } + return 1; +} + +static int +allocsp_f( + int argc, + char **argv) +{ + xfs_flock64_t segment; + + if (!offset_length(argv[1], argv[2], &segment)) + return 0; + + if (ioctl(fdesc, XFS_IOC_ALLOCSP64, &segment) < 0) { + perror("XFS_IOC_ALLOCSP64"); + return 0; + } + return 0; +} + +static int +freesp_f( + int argc, + char **argv) +{ + xfs_flock64_t segment; + + if (!offset_length(argv[1], argv[2], &segment)) + return 0; + + if (ioctl(fdesc, XFS_IOC_FREESP64, &segment) < 0) { + perror("XFS_IOC_FREESP64"); + return 0; + } + return 0; +} + +static int +resvsp_f( + int argc, + char **argv) +{ + xfs_flock64_t segment; + + if (!offset_length(argv[1], argv[2], &segment)) + return 0; + + if (ioctl(fdesc, XFS_IOC_RESVSP64, &segment) < 0) { + perror("XFS_IOC_RESVSP64"); + return 0; + } + return 0; +} + +static int +unresvsp_f( + int argc, + char **argv) +{ + xfs_flock64_t segment; + + if (!offset_length(argv[1], argv[2], &segment)) + return 0; + + if (ioctl(fdesc, XFS_IOC_UNRESVSP64, &segment) < 0) { + perror("XFS_IOC_UNRESVSP64"); + return 0; + } + return 0; +} + +void +prealloc_init(void) +{ + allocsp_cmd.name = _("allocsp"); + allocsp_cmd.cfunc = allocsp_f; + allocsp_cmd.argmin = 2; + allocsp_cmd.argmax = 2; + allocsp_cmd.args = _("off len"); + allocsp_cmd.oneline = _("allocates zeroed space for part of a file"); + + freesp_cmd.name = _("freesp"); + freesp_cmd.cfunc = freesp_f; + freesp_cmd.argmin = 2; + freesp_cmd.argmax = 2; + freesp_cmd.args = _("off len"); + freesp_cmd.oneline = _("frees space associated with part of a file"); + + resvsp_cmd.name = _("resvsp"); + resvsp_cmd.cfunc = resvsp_f; + resvsp_cmd.argmin = 2; + resvsp_cmd.argmax = 2; + resvsp_cmd.args = _("off len"); + resvsp_cmd.oneline = + _("reserves space associated with part of a file"); + + unresvsp_cmd.name = _("unresvsp"); + unresvsp_cmd.cfunc = unresvsp_f; + unresvsp_cmd.argmin = 2; + unresvsp_cmd.argmax = 2; + unresvsp_cmd.args = _("off len"); + unresvsp_cmd.oneline = + _("frees reserved space associated with part of a file"); + + add_command(&allocsp_cmd); + add_command(&freesp_cmd); + add_command(&resvsp_cmd); + add_command(&unresvsp_cmd); +} diff --git a/io/pwrite.c b/io/pwrite.c new file mode 100644 index 000000000..bdf97475a --- /dev/null +++ b/io/pwrite.c @@ -0,0 +1,187 @@ +/* + * Copyright (c) 2003 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/ + */ + +#include +#include "command.h" +#include "input.h" +#include "init.h" + +static cmdinfo_t pwrite_cmd; + +static void +pwrite_help(void) +{ + printf(_( +"\n" +" writes a range of bytes (in block size increments) from the given offset\n" +"\n" +" Example:\n" +" 'write 512 20' - writes 20 bytes at 512 bytes into the open file\n" +"\n" +" Writes into a segment of the currently open file, using either a buffer\n" +" filled with a set pattern (0xcdcdcdcd) or data read from an input file.\n" +" -S -- use an alternate seed number\n" +" -i -- specifies an input file from which to source data to write\n" +" -d -- open the input file for direct IO\n" +" -s -- skip a number of bytes at the start of the input file\n" +" The writes are performed in sequential blocks starting at offset, with the\n" +" blocksize tunable using the -b option (default blocksize is 4096 bytes).\n" +"\n")); +} + +static int +write_buffer( + off64_t offset, + ssize_t count, + ssize_t bs, + int fd, + off64_t skip, + ssize_t *total) +{ + ssize_t bytes, itotal = min(bs,count); + + *total = 0; + while (count > 0) { + if (fd > 0) { /* input file given, read buffer first */ + if (!read_buffer(fd, skip + *total, bs, &itotal, 0, 1)) + break; + } + bytes = pwrite64(fdesc, buffer, min(itotal,count), offset); + if (bytes == 0) + break; + if (bytes < 0) { + perror("pwrite64"); + return 0; + } + *total += bytes; + if (bytes < count) + break; + offset += bytes; + count -= bytes; + } + return 1; +} + +static int +pwrite_f( + int argc, + char **argv) +{ + off64_t offset, skip = 0; + ssize_t count, total; + unsigned int seed = 0xcdcdcdcd; + unsigned int bsize = 4096; + char *sp, *infile = NULL; + int c, fd = -1, dflag = 0; + + while ((c = getopt(argc, argv, "b:df:i:s:S:")) != EOF) { + switch (c) { + case 'b': + bsize = strtoul(optarg, &sp, 0); + if (!sp || sp == optarg) { + printf(_("non-numeric bsize -- %s\n"), optarg); + return 0; + } + break; + case 'd': + dflag = 1; + break; + case 'f': + case 'i': + infile = optarg; + break; + case 's': + skip = strtoul(optarg, &sp, 0); + if (!sp || sp == optarg) { + printf(_("non-numeric skip -- %s\n"), optarg); + return 0; + } + break; + case 'S': + seed = strtoul(optarg, &sp, 0); + if (!sp || sp == optarg) { + printf(_("non-numeric seed -- %s\n"), optarg); + return 0; + } + break; + default: + printf("%s %s\n", pwrite_cmd.name, pwrite_cmd.oneline); + return 0; + } + } + if ( ((skip || dflag) && !infile) || (optind != argc - 2)) { + printf("%s %s\n", pwrite_cmd.name, pwrite_cmd.oneline); + return 0; + } + offset = strtoul(argv[optind], &sp, 0); + if (!sp || sp == argv[optind]) { + printf(_("non-numeric offset argument -- %s\n"), argv[optind]); + return 0; + } + optind++; + count = strtoul(argv[optind], &sp, 0); + if (!sp || sp == argv[optind]) { + printf(_("non-numeric length argument -- %s\n"), argv[optind]); + return 0; + } + + if (!alloc_buffer(bsize, seed)) + return 0; + + if (infile && ((fd = openfile(infile, 0, 0, dflag, 1, 0, 0, 0)) < 0)) + return 0; + + if (!write_buffer(offset, count, bsize, fd, skip, &total)) { + close(fd); + return 0; + } + printf(_("wrote %u/%u bytes at offset %llu\n"), count, total, offset); + close(fd); + return 0; +} + +void +pwrite_init(void) +{ + pwrite_cmd.name = _("pwrite"); + pwrite_cmd.altname = _("w"); + pwrite_cmd.cfunc = pwrite_f; + pwrite_cmd.argmin = 2; + pwrite_cmd.argmax = -1; + pwrite_cmd.args = + _("[-i infile [-d] [-s skip]] [-b bs] [-S seed] off len"); + pwrite_cmd.oneline = + _("writes a number of bytes at a specified offset"); + pwrite_cmd.help = pwrite_help; + + add_command(&pwrite_cmd); +} diff --git a/io/quit.c b/io/quit.c new file mode 100644 index 000000000..731eb3a29 --- /dev/null +++ b/io/quit.c @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2003 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/ + */ + +#include +#include "command.h" + +static cmdinfo_t quit_cmd; + +static int +quit_f( + int argc, + char **argv) +{ + return 1; +} + +void +quit_init(void) +{ + quit_cmd.name = _("quit"); + quit_cmd.altname = _("q"); + quit_cmd.cfunc = quit_f; + quit_cmd.oneline = _("exit xfs_io"); + + add_command(&quit_cmd); +} diff --git a/io/resblks.c b/io/resblks.c new file mode 100644 index 000000000..5191dca1d --- /dev/null +++ b/io/resblks.c @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2003 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/ + */ + +#include +#include "command.h" +#include "init.h" + +static cmdinfo_t resblks_cmd; +static int resblks_f(int argc, char **argv); + +static int +resblks_f( + int argc, + char **argv) +{ + xfs_fsop_resblks_t res; + char *sp; + + if (argc == 2) { + res.resblks = strtoul(argv[1], &sp, 10); + if (!sp || sp == argv[1]) { + printf(_("non-numeric argument -- %s\n"), argv[1]); + return 0; + } + if (ioctl(fdesc, XFS_IOC_SET_RESBLKS, &res) < 0) { + perror("XFS_IOC_SET_RESBLKS"); + return 0; + } + } else if (ioctl(fdesc, XFS_IOC_GET_RESBLKS, &res) < 0) { + perror("XFS_IOC_GET_RESBLKS"); + return 0; + } + printf(_("reserved blocks = %llu\n"), + (unsigned long long) res.resblks); + printf(_("available reserved blocks = %llu\n"), + (unsigned long long) res.resblks_avail); + return 0; +} + +void +resblks_init(void) +{ + resblks_cmd.name = _("resblks"); + resblks_cmd.cfunc = resblks_f; + resblks_cmd.argmin = 0; + resblks_cmd.argmax = 1; + resblks_cmd.args = _("[blocks]"); + resblks_cmd.oneline = + _("get and/or set count of reserved filesystem blocks"); + + add_command(&resblks_cmd); +} diff --git a/io/truncate.c b/io/truncate.c new file mode 100644 index 000000000..80bdce268 --- /dev/null +++ b/io/truncate.c @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2003 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/ + */ + +#include +#include "command.h" +#include "init.h" + +static cmdinfo_t truncate_cmd; + +static int +truncate_f( + int argc, + char **argv) +{ + off64_t offset; + char *sp; + + offset = strtoul(argv[1], &sp, 10); + if (!sp || sp == argv[1]) { + printf(_("non-numeric truncate argument -- %s\n"), argv[1]); + return 0; + } + + if (ftruncate64(fdesc, offset) < 0) { + perror("ftruncate"); + return 0; + } + return 0; +} + +void +truncate_init(void) +{ + truncate_cmd.name = _("truncate"); + truncate_cmd.cfunc = truncate_f; + truncate_cmd.argmin = 1; + truncate_cmd.argmax = 1; + truncate_cmd.args = _("off"); + truncate_cmd.oneline = + _("truncates the current file at the given offset"); + + add_command(&truncate_cmd); +} diff --git a/io/xfs_bmap.sh b/io/xfs_bmap.sh new file mode 100755 index 000000000..ed63122a7 --- /dev/null +++ b/io/xfs_bmap.sh @@ -0,0 +1,65 @@ +#!/bin/sh -f +# +# Copyright (c) 2003 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/ +# + +OPTS="" +VERSION=false +USAGE="Usage: xfs_bmap [-adlpvV] [-n nx] file..." + +while getopts "adln:pvV" c +do + case $c in + a) OPTS=$OPTS" -a";; + d) OPTS=$OPTS" -d";; + l) OPTS=$OPTS" -l";; + n) OPTS=$OPTS" '-n "$OPTARG"'";; + p) OPTS=$OPTS" -p";; + v) OPTS=$OPTS" -v";; + V) VERSION=true;; + \?) echo $USAGE 1>&2 + exit 2 + ;; + esac +done +$VERSION && xfs_io -p xfs_bmap -V + +set -- extra $@ +shift $OPTIND + +while [ "$1" != "" ] +do + eval xfs_io -r -p xfs_bmap -c 'bmap $OPTS' $1 + status=$? + [ $status -ne 0 ] && exit $status + shift $OPTIND +done +exit 0 diff --git a/man/man8/xfs_io.8 b/man/man8/xfs_io.8 new file mode 100644 index 000000000..d0f9cd647 --- /dev/null +++ b/man/man8/xfs_io.8 @@ -0,0 +1,169 @@ +.TH xfs_io 8 +.SH NAME +xfs_io \- debug the IO path of an XFS filesystem +.SH SYNOPSIS +.nf +\f3xfs_io\f1 [ \f3\-c\f1 cmd ] ... [ \f3\-p\f1 prog ] [ \f3\-r\f1 ] file +.fi +.SH DESCRIPTION +\f2xfs_io\f1 is a debugging tool like \f2xfs_db\f1(8), but is aimed +at examining the regular file IO path rather than the raw XFS volume +itself. +.PP +The options to \f2xfs_io\f1 are: +.TP 10 +\f3\-c\f1 \f2cmd\f1 +\f2xfs_io\f1 commands may be run interactively (the default) +or as arguments on the command line. +Multiple \f3\-c\f1 arguments may be given. +The commands are run in the sequence given, then the program exits. +This is the mechanism used to implement \f2xfs_bmap\f1(8). +.TP +\f3\-p\f1 \f2prog\f1 +Set the program name for prompts and some error messages, +the default value is \f2xfs_io\f1. +.TP +\f3\-r\f1 +Open \f2file\f1 read-only, initially. +.SH CONCEPTS +\f2xfs_io\f1 always maintains one current open file in the filesystem. +This is initially specified on the command line, but alternate files +can be specified later (one at a time \- see the ``open'' command). +.PP +\f2xfs_io\f1 commands can be broken up into two distinct classes. +Most commands are for doing IO to the file in some way - reads, writes, +or space preallocation. +Other commands are for the navigation and display of data structures +relating to the open file or the filesystem it resides in. +.SH COMMANDS +.PP +Many commands have extensive online help. +Use the \f3help\f1 command for more details on any command. +.TP 10 +\f3allocsp\f1 \f2offset\f1 \f2length\f1 +Allocates zeroed space for part of a file using the XFS_IOC_ALLOCSP +system call described in \f2xfs\f1(5). +.TP +\f3freesp\f1 \f2offset\f1 \f2length\f1 +Frees space for part of a file using the XFS_IOC_FREESP +system call described in \f2xfs\f1(5). +.TP +\f3bmap\f1 [ \f2-adlpv\f1 ] [ \f2-n nx\f1 ] +Prints the block mapping for the open file. +Refer to \f2xfs_bmap\f1(8) for complete documentation. +.TP +\f3fdatasync\f1 +Calls \f2fdatasync\f1(2) to flush the open file's in-core data to disk. +.TP +\f3fsync\f1 +Calls \f2fsync\f1(2) to flush all in-core file state to disk. +.TP +\f3o\f1 +See the \f3open\f1 command. +.TP +\f3open\f1 [ \f2-acdrstx\f1 ] [ \f2path\f1 ] +Closes the current file, and opens the file specified by \f2path\f1 instead. +Without any arguments, displays statistics about the currently open file \- +see the \f3stat\f1 command. +.br +The \f3\-a\f1 option opens append-only (O_APPEND). +.br +The \f3\-c\f1 option creates the file if it doesn't already exist (O_CREAT). +.br +The \f3\-d\f1 option opens for direct IO (O_DIRECT). +.br +The \f3\-r\f1 option opens read-only (O_RDONLY). +.br +The \f3\-s\f1 option opens for synchronous IO (O_SYNC). +.br +The \f3\-t\f1 option truncates on open (O_TRUNC). +.br +The \f3\-x\f1 option marks the file as a realtime XFS file after +opening it, if it is not already marked as such. +.TP +\f3pread\f1 +Reads a range of bytes in a specified blocksize from the given offset. +.br +The \f3\-b\f1 option can be used to set the blocksize into which the +\f2read\f1(2) requests will be split. +The default blocksize is 4096 bytes. +.br +The \f3\-v\f1 option will dump the contents of the buffer after reading, +by default only the count of bytes actually read is dumped. +.TP +\f3pwrite\f1 +Writes a range of bytes in a specified blocksize from the given offset. +The bytes written can be either a set pattern or read in from another +file before writing. +.br +The \f3\-i\f1 option allows an input file to be specified as the source +of the data to be written. +.br +The \f3\-d\f1 option will cause direct IO, rather than the usual buffered +IO, to be used when reading the input file. +.br +The \f3\-s\f1 options specifies the number of bytes to skip from the +start of the input file before starting to read. +.br +The \f3\-b\f1 option can be used to set the blocksize into which the +\f2read\f1(2) requests will be split. +The default blocksize is 4096 bytes. +The \f3\-S\f1 option is used to set the (repeated) fill pattern which +is used when the data to write is not coming from a file. +The default buffer fill pattern value is 0xcdcdcdcd. +.TP +\f3q\f1 +See the \f3quit\f1 command. +.TP +\f3quit\f1 +Exit \f2xfs_io\f1. +.TP +\f3r\f1 +See the \f3pread\f1 command. +.TP +\f3resblks\f1 [ \f2blocks\f1 ] +Get and/or set count of reserved filesystem blocks using the +XFS_IOC_GET_RESBLKS or XFS_IOC_SET_RESBLKS system calls, as +described in \f2xfs\f1(5). +Note \-\- this can be useful for exercising out of space behavior. +.TP +\f3resvsp\f1 \f2offset\f1 \f2length\f1 +Allocates reserved, unwritten space for part of a file using the XFS_IOC_RESVSP +system call described in \f2xfs\f1(5). +.TP +\f3unresvsp\f1 \f2offset\f1 \f2length\f1 +Frees reserved space for part of a file using the XFS_IOC_UNRESVSP +system call described in \f2xfs\f1(5). +.TP +\f3s\f1 +See the \f3fsync\f1 command. +.TP +\f3stat\f1 [ \f2-v\f1 ] +Selected statistics from \f2stat\f1(2) and the XFS_IOC_GETXATTR +system call from \f2xfs\f1(5) on the currently open file. +If the \f2-v\f1 option is specified, the atime (last access), mtime +(last modify), and ctime (last change) timestamps are also displayed. +.TP +\f3statfs\f1 +Selected statistics from \f2statfs\f1(2) and the XFS_IOC_FSGEOMETRY +system call from \f2xfs\f1(5) on the filesystem where the currently +open file resides. +.TP +\f3truncate\f1 \f2offset\f1 +Truncates the current file at the given offset using \f2ftruncate\f1(2). +.TP +\f3w\f1 +See the \f3pwrite\f1 command. +.SH SEE ALSO +fdatasync(2), +fstat(2), +fstatfs(2), +fsync(2), +ftruncate(2), +mkfs.xfs(8), +open(2), +pread(2), +pwrite(2), +xfs_bmap(8), +xfs_db(8), +xfs(5). -- 2.47.2