/*
- * Copyright (c) 2003 Silicon Graphics, Inc. All Rights Reserved.
+ * Copyright (c) 2003-2005 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
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation.
*
- * This program is distributed in the hope that it would be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * This program is distributed in the hope that it would be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
*
- * 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/
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
-#include <xfs/libxfs.h>
#include "command.h"
+#include "input.h"
#include "init.h"
+#include "io.h"
+#include "libxfs.h"
+
+#ifndef __O_TMPFILE
+#if defined __alpha__
+#define __O_TMPFILE 0100000000
+#elif defined(__hppa__)
+#define __O_TMPFILE 040000000
+#elif defined(__sparc__)
+#define __O_TMPFILE 0x2000000
+#else
+#define __O_TMPFILE 020000000
+#endif
+#endif /* __O_TMPFILE */
+
+#ifndef O_TMPFILE
+#define O_TMPFILE (__O_TMPFILE | O_DIRECTORY)
+#endif
static cmdinfo_t open_cmd;
static cmdinfo_t stat_cmd;
-static cmdinfo_t setfl_cmd;
+static cmdinfo_t close_cmd;
static cmdinfo_t statfs_cmd;
+static cmdinfo_t chproj_cmd;
+static cmdinfo_t lsproj_cmd;
static cmdinfo_t extsize_cmd;
-static int stat_f(int, char **);
+static cmdinfo_t inode_cmd;
+static prid_t prid;
+static long extsize;
+
+off64_t
+filesize(void)
+{
+ struct stat64 st;
+
+ if (fstat64(file->fd, &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 dioattr dio;
+ struct fsxattr fsx, fsxa;
+ struct stat64 st;
+ int verbose = (argc == 2 && !strcmp(argv[1], "-v"));
+
+ printf(_("fd.path = \"%s\"\n"), file->name);
+ printf(_("fd.flags = %s,%s,%s%s%s%s%s\n"),
+ file->flags & IO_OSYNC ? _("sync") : _("non-sync"),
+ file->flags & IO_DIRECT ? _("direct") : _("non-direct"),
+ file->flags & IO_READONLY ? _("read-only") : _("read-write"),
+ file->flags & IO_REALTIME ? _(",real-time") : "",
+ file->flags & IO_APPEND ? _(",append-only") : "",
+ file->flags & IO_NONBLOCK ? _(",non-block") : "",
+ file->flags & IO_TMPFILE ? _(",tmpfile") : "");
+ if (fstat64(file->fd, &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 (verbose) {
+ 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 (file->flags & IO_FOREIGN)
+ return 0;
+ if ((xfsctl(file->name, file->fd, FS_IOC_FSGETXATTR, &fsx)) < 0 ||
+ (xfsctl(file->name, file->fd, XFS_IOC_FSGETXATTRA, &fsxa)) < 0) {
+ perror("FS_IOC_FSGETXATTR");
+ } else {
+ printf(_("fsxattr.xflags = 0x%x "), fsx.fsx_xflags);
+ printxattr(fsx.fsx_xflags, verbose, 0, file->name, 1, 1);
+ printf(_("fsxattr.projid = %u\n"), fsx.fsx_projid);
+ printf(_("fsxattr.extsize = %u\n"), fsx.fsx_extsize);
+ printf(_("fsxattr.nextents = %u\n"), fsx.fsx_nextents);
+ printf(_("fsxattr.naextents = %u\n"), fsxa.fsx_nextents);
+ }
+ if ((xfsctl(file->name, file->fd, XFS_IOC_DIOINFO, &dio)) < 0) {
+ perror("XFS_IOC_DIOINFO");
+ } else {
+ printf(_("dioattr.mem = 0x%x\n"), dio.d_mem);
+ printf(_("dioattr.miniosz = %u\n"), dio.d_miniosz);
+ printf(_("dioattr.maxiosz = %u\n"), dio.d_maxiosz);
+ }
+ return 0;
+}
int
openfile(
char *path,
- int aflag,
- int cflag,
- int dflag,
- int rflag,
- int sflag,
- int tflag,
- int xflag)
+ xfs_fsop_geom_t *geom,
+ int flags,
+ mode_t mode)
{
int fd;
int oflags;
- oflags = (rflag ? O_RDONLY : O_RDWR);
- if (aflag)
+ oflags = flags & IO_READONLY ? O_RDONLY : O_RDWR;
+ if (flags & IO_APPEND)
oflags |= O_APPEND;
- if (cflag)
+ if (flags & IO_CREAT)
oflags |= O_CREAT;
- if (dflag)
+ if (flags & IO_DIRECT)
oflags |= O_DIRECT;
- if (sflag)
+ if (flags & IO_OSYNC)
oflags |= O_SYNC;
- if (tflag)
+ if (flags & IO_TRUNC)
oflags |= O_TRUNC;
+ if (flags & IO_NONBLOCK)
+ oflags |= O_NONBLOCK;
+ if (flags & IO_TMPFILE)
+ oflags |= O_TMPFILE;
- fd = open(path, oflags, 0644);
+ fd = open(path, oflags, mode);
if (fd < 0) {
- perror(path);
- return -1;
+ if (errno == EISDIR &&
+ ((oflags & (O_RDWR|O_TMPFILE)) == O_RDWR)) {
+ /* make it as if we asked for O_RDONLY & try again */
+ oflags &= ~O_RDWR;
+ oflags |= O_RDONLY;
+ flags |= IO_READONLY;
+ fd = open(path, oflags, mode);
+ if (fd < 0) {
+ perror(path);
+ return -1;
+ }
+ } else {
+ perror(path);
+ return -1;
+ }
}
- if (!platform_test_xfs_fd(fd)) {
- fprintf(stderr, _("%s: specified file "
- "[\"%s\"] is not on an XFS filesystem\n"),
- progname, fname);
+
+ if (!geom || !platform_test_xfs_fd(fd))
+ return fd;
+
+ if (xfsctl(path, fd, XFS_IOC_FSGEOMETRY, geom) < 0) {
+ perror("XFS_IOC_FSGEOMETRY");
close(fd);
return -1;
}
- if (!readonly && xflag) { /* read/write and realtime */
+ if (!(flags & IO_READONLY) && (flags & IO_REALTIME)) {
struct fsxattr attr;
- if (xfsctl(path, fd, XFS_IOC_FSGETXATTR, &attr) < 0) {
- perror("XFS_IOC_FSGETXATTR");
+ if (xfsctl(path, fd, FS_IOC_FSGETXATTR, &attr) < 0) {
+ perror("FS_IOC_FSGETXATTR");
close(fd);
return -1;
}
- if (!(attr.fsx_xflags & XFS_XFLAG_REALTIME)) {
- attr.fsx_xflags |= XFS_XFLAG_REALTIME;
- if (xfsctl(path, fd, XFS_IOC_FSSETXATTR, &attr) < 0) {
- perror("XFS_IOC_FSSETXATTR");
+ if (!(attr.fsx_xflags & FS_XFLAG_REALTIME)) {
+ attr.fsx_xflags |= FS_XFLAG_REALTIME;
+ if (xfsctl(path, fd, FS_IOC_FSSETXATTR, &attr) < 0) {
+ perror("FS_IOC_FSSETXATTR");
close(fd);
return -1;
}
return fd;
}
-static int
-usage(void)
+int
+addfile(
+ char *name,
+ int fd,
+ xfs_fsop_geom_t *geometry,
+ int flags)
{
- printf("%s %s\n", open_cmd.name, open_cmd.oneline);
+ char *filename;
+
+ filename = strdup(name);
+ if (!filename) {
+ perror("strdup");
+ close(fd);
+ return -1;
+ }
+
+ /* Extend the table of currently open files */
+ filetable = (fileio_t *)realloc(filetable, /* growing */
+ ++filecount * sizeof(fileio_t));
+ if (!filetable) {
+ perror("realloc");
+ filecount = 0;
+ free(filename);
+ close(fd);
+ return -1;
+ }
+
+ /* Finally, make this the new active open file */
+ file = &filetable[filecount - 1];
+ file->fd = fd;
+ file->flags = flags;
+ file->name = filename;
+ file->geom = *geometry;
return 0;
}
{
printf(_(
"\n"
-" opens a new file in the requested mode, after closing the current file\n"
+" opens a new file in the requested mode\n"
"\n"
" Example:\n"
-" 'open -d /tmp/data' - opens data file read-write for direct IO\n"
+" 'open -cd /tmp/data' - creates/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"
+" -f -- open with O_CREAT (create the file if it doesn't exist)\n"
+" -m -- permissions to use in case a new file is created (default 0600)\n"
+" -n -- open with O_NONBLOCK\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"
+" -R -- mark the file as a realtime XFS file immediately after opening it\n"
+" -T -- open with O_TMPFILE (create a file not visible in the namespace)\n"
+" Note1: usually read/write direct IO requests must be blocksize aligned;\n"
+" some kernels, however, allow sectorsize alignment for direct IO.\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"
+" was opened correctly (in particular, must be opened read-only).\n"
"\n"));
}
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);
+ int c, fd, flags = 0;
+ char *sp;
+ mode_t mode = 0600;
+ xfs_fsop_geom_t geometry = { 0 };
+
+ if (argc == 1) {
+ if (file)
+ return stat_f(argc, argv);
+ fprintf(stderr, _("no files are open, try 'help open'\n"));
+ return 0;
+ }
- while ((c = getopt(argc, argv, "acdrstx")) != EOF) {
+ while ((c = getopt(argc, argv, "FRTacdfm:nrstx")) != EOF) {
switch (c) {
+ case 'F':
+ /* Ignored / deprecated now, handled automatically */
+ break;
case 'a':
- aflag = 1;
+ flags |= IO_APPEND;
break;
case 'c':
- cflag = 1;
+ case 'f':
+ flags |= IO_CREAT;
break;
case 'd':
- dflag = 1;
+ flags |= IO_DIRECT;
+ break;
+ case 'm':
+ mode = strtoul(optarg, &sp, 0);
+ if (!sp || sp == optarg) {
+ printf(_("non-numeric mode -- %s\n"), optarg);
+ return 0;
+ }
+ break;
+ case 'n':
+ flags |= IO_NONBLOCK;
break;
case 'r':
- rflag = 1;
+ flags |= IO_READONLY;
break;
case 's':
- sflag = 1;
+ flags |= IO_OSYNC;
break;
case 't':
- tflag = 1;
+ flags |= IO_TRUNC;
break;
- case 'x':
- xflag = 1;
+ case 'R':
+ case 'x': /* backwards compatibility */
+ flags |= IO_REALTIME;
+ break;
+ case 'T':
+ flags |= IO_TMPFILE;
break;
default:
- return usage();
+ return command_usage(&open_cmd);
}
}
if (optind != argc - 1)
- return usage();
+ return command_usage(&open_cmd);
+
+ if ((flags & (IO_READONLY|IO_TMPFILE)) == (IO_READONLY|IO_TMPFILE)) {
+ fprintf(stderr, _("-T and -r options are incompatible\n"));
+ return -1;
+ }
- fd = openfile(argv[optind],
- aflag, cflag, dflag, rflag, sflag, tflag, xflag);
+ fd = openfile(argv[optind], &geometry, flags, mode);
if (fd < 0)
return 0;
- filename = strdup(argv[optind]);
- if (!filename) {
- perror("strdup");
- close(fd);
- return 0;
- }
+ if (!platform_test_xfs_fd(fd))
+ flags |= IO_FOREIGN;
- /*
- * 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;
+ addfile(argv[optind], fd, &geometry, flags);
return 0;
}
-off64_t
-filesize(void)
+static int
+close_f(
+ int argc,
+ char **argv)
{
- struct stat64 st;
+ size_t length;
+ unsigned int offset;
- if (fstat64(fdesc, &st) < 0) {
- perror("fstat64");
- return -1;
+ if (close(file->fd) < 0) {
+ perror("close");
+ return 0;
}
- return st.st_size;
+ free(file->name);
+
+ /* Shuffle the file table entries down over the removed entry */
+ offset = file - &filetable[0];
+ length = filecount * sizeof(fileio_t);
+ length -= (offset + 1) * sizeof(fileio_t);
+ if (length)
+ memmove(file, file + 1, length);
+
+ /* Resize the memory allocated for the table, possibly freeing */
+ if (--filecount) {
+ filetable = (fileio_t *)realloc(filetable, /* shrinking */
+ filecount * sizeof(fileio_t));
+ if (offset == filecount)
+ offset--;
+ file = filetable + offset;
+ } else {
+ free(filetable);
+ file = filetable = NULL;
+ }
+ filelist_f();
+ return 0;
}
-static char *
-filetype(mode_t mode)
+static void
+lsproj_help(void)
{
- 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");
+ printf(_(
+"\n"
+" displays the project identifier associated with the current path\n"
+"\n"
+" Options:\n"
+" -R -- recursively descend (useful when current path is a directory)\n"
+" -D -- recursively descend, but only list projects on directories\n"
+"\n"));
+}
+
+static int
+lsproj_callback(
+ const char *path,
+ const struct stat *stat,
+ int status,
+ struct FTW *data)
+{
+ prid_t projid;
+ int fd;
+
+ if (recurse_dir && !S_ISDIR(stat->st_mode))
+ return 0;
+
+ if ((fd = open(path, O_RDONLY)) == -1) {
+ fprintf(stderr, _("%s: cannot open %s: %s\n"),
+ progname, path, strerror(errno));
+ } else {
+ if (getprojid(path, fd, &projid) == 0)
+ printf("[%u] %s\n", (unsigned int)projid, path);
+ close(fd);
}
- return NULL;
+ return 0;
}
static int
-stat_f(
+lsproj_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));
+ prid_t projid;
+ int c;
+
+ recurse_all = recurse_dir = 0;
+ while ((c = getopt(argc, argv, "DR")) != EOF) {
+ switch (c) {
+ case 'D':
+ recurse_all = 0;
+ recurse_dir = 1;
+ break;
+ case 'R':
+ recurse_all = 1;
+ recurse_dir = 0;
+ break;
+ default:
+ return command_usage(&lsproj_cmd);
}
}
- if ((xfsctl(fname, fdesc, XFS_IOC_FSGETXATTR, &fsx)) < 0) {
- perror("xfsctl(XFS_IOC_FSGETXATTR)");
- } else {
- printf(_("xattr.xflags = 0x%x\n"), fsx.fsx_xflags);
- printf(_("xattr.extsize = %u\n"), fsx.fsx_extsize);
- printf(_("xattr.nextents = %u\n"), fsx.fsx_nextents);
- }
+
+ if (argc != optind)
+ return command_usage(&lsproj_cmd);
+
+ if (recurse_all || recurse_dir)
+ nftw(file->name, lsproj_callback,
+ 100, FTW_PHYS | FTW_MOUNT | FTW_DEPTH);
+ else if (getprojid(file->name, file->fd, &projid) < 0)
+ perror("getprojid");
+ else
+ printf(_("projid = %u\n"), (unsigned int)projid);
return 0;
}
+static void
+chproj_help(void)
+{
+ printf(_(
+"\n"
+" modifies the project identifier associated with the current path\n"
+"\n"
+" -R -- recursively descend (useful when current path is a directory)\n"
+" -D -- recursively descend, only modifying projects on directories\n"
+"\n"));
+}
+
static int
-setfl_f(
- int argc,
- char **argv)
+chproj_callback(
+ const char *path,
+ const struct stat *stat,
+ int status,
+ struct FTW *data)
{
- int c, flags;
+ int fd;
- flags = fcntl(fdesc, F_GETFL, 0);
- if (flags < 0) {
- perror("fcntl(F_GETFL)");
+ if (recurse_dir && !S_ISDIR(stat->st_mode))
return 0;
+
+ if ((fd = open(path, O_RDONLY)) == -1) {
+ fprintf(stderr, _("%s: cannot open %s: %s\n"),
+ progname, path, strerror(errno));
+ } else {
+ if (setprojid(path, fd, prid) < 0)
+ perror("setprojid");
+ close(fd);
}
+ return 0;
+}
- while ((c = getopt(argc, argv, "ad")) != EOF) {
+static int
+chproj_f(
+ int argc,
+ char **argv)
+{
+ int c;
+
+ recurse_all = recurse_dir = 0;
+ while ((c = getopt(argc, argv, "DR")) != EOF) {
switch (c) {
- case 'a':
- if (flags & O_APPEND)
- flags |= O_APPEND;
- else
- flags &= ~O_APPEND;
+ case 'D':
+ recurse_all = 0;
+ recurse_dir = 1;
break;
- case 'd':
- if (flags & O_DIRECT)
- flags |= O_DIRECT;
- else
- flags &= ~O_DIRECT;
+ case 'R':
+ recurse_all = 1;
+ recurse_dir = 0;
break;
default:
- printf(_("invalid setfl argument -- '%c'\n"), c);
- return 0;
+ return command_usage(&chproj_cmd);
}
}
- if (fcntl(fdesc, F_SETFL, flags) < 0)
- perror("fcntl(F_SETFL)");
+ if (argc != optind + 1)
+ return command_usage(&chproj_cmd);
+
+ prid = prid_from_string(argv[optind]);
+ if (prid == -1) {
+ printf(_("invalid project ID -- %s\n"), argv[optind]);
+ return 0;
+ }
+ if (recurse_all || recurse_dir)
+ nftw(file->name, chproj_callback,
+ 100, FTW_PHYS | FTW_MOUNT | FTW_DEPTH);
+ else if (setprojid(file->name, file->fd, prid) < 0)
+ perror("setprojid");
return 0;
}
+static void
+extsize_help(void)
+{
+ printf(_(
+"\n"
+" report or modify preferred extent size (in bytes) for the current path\n"
+"\n"
+" -R -- recursively descend (useful when current path is a directory)\n"
+" -D -- recursively descend, only modifying extsize on directories\n"
+"\n"));
+}
+
static int
-extsize_f(
- int argc,
- char **argv)
+get_extsize(const char *path, int fd)
{
- struct fsxattr fsx;
- unsigned int extsize;
- char *sp;
+ struct fsxattr fsx;
- extsize = strtoul(argv[1], &sp, 0);
- if (!sp || sp == argv[1]) {
- printf(_("non-numeric extsize argument -- %s\n"), argv[1]);
+ if ((xfsctl(path, fd, FS_IOC_FSGETXATTR, &fsx)) < 0) {
+ printf("%s: FS_IOC_FSGETXATTR %s: %s\n",
+ progname, path, strerror(errno));
return 0;
}
- if ((xfsctl(fname, fdesc, XFS_IOC_FSGETXATTR, &fsx)) < 0) {
- perror("xfsctl(XFS_IOC_FSGETXATTR)");
+ printf("[%u] %s\n", fsx.fsx_extsize, path);
+ return 0;
+}
+
+static int
+set_extsize(const char *path, int fd, long extsz)
+{
+ struct fsxattr fsx;
+ struct stat64 stat;
+
+ if (fstat64(fd, &stat) < 0) {
+ perror("fstat64");
+ return 0;
+ }
+ if ((xfsctl(path, fd, FS_IOC_FSGETXATTR, &fsx)) < 0) {
+ printf("%s: FS_IOC_FSGETXATTR %s: %s\n",
+ progname, path, strerror(errno));
return 0;
}
- fsx.fsx_extsize = extsize;
- if ((xfsctl(fname, fdesc, XFS_IOC_FSSETXATTR, &fsx)) < 0) {
- perror("xfsctl(XFS_IOC_FSSETXATTR)");
+
+ if (S_ISREG(stat.st_mode)) {
+ fsx.fsx_xflags |= FS_XFLAG_EXTSIZE;
+ } else if (S_ISDIR(stat.st_mode)) {
+ fsx.fsx_xflags |= FS_XFLAG_EXTSZINHERIT;
+ } else {
+ printf(_("invalid target file type - file %s\n"), path);
+ return 0;
+ }
+ fsx.fsx_extsize = extsz;
+
+ if ((xfsctl(path, fd, FS_IOC_FSSETXATTR, &fsx)) < 0) {
+ printf("%s: FS_IOC_FSSETXATTR %s: %s\n",
+ progname, path, strerror(errno));
+ return 0;
+ }
+
+ return 0;
+}
+
+static int
+get_extsize_callback(
+ const char *path,
+ const struct stat *stat,
+ int status,
+ struct FTW *data)
+{
+ int fd;
+
+ if (recurse_dir && !S_ISDIR(stat->st_mode))
+ return 0;
+
+ if ((fd = open(path, O_RDONLY)) == -1) {
+ fprintf(stderr, _("%s: cannot open %s: %s\n"),
+ progname, path, strerror(errno));
+ } else {
+ get_extsize(path, fd);
+ close(fd);
+ }
+ return 0;
+}
+
+static int
+set_extsize_callback(
+ const char *path,
+ const struct stat *stat,
+ int status,
+ struct FTW *data)
+{
+ int fd;
+
+ if (recurse_dir && !S_ISDIR(stat->st_mode))
return 0;
+
+ if ((fd = open(path, O_RDONLY)) == -1) {
+ fprintf(stderr, _("%s: cannot open %s: %s\n"),
+ progname, path, strerror(errno));
+ } else {
+ set_extsize(path, fd, extsize);
+ close(fd);
+ }
+ return 0;
+}
+
+static int
+extsize_f(
+ int argc,
+ char **argv)
+{
+ size_t blocksize, sectsize;
+ int c;
+
+ recurse_all = recurse_dir = 0;
+ init_cvtnum(&blocksize, §size);
+ while ((c = getopt(argc, argv, "DR")) != EOF) {
+ switch (c) {
+ case 'D':
+ recurse_all = 0;
+ recurse_dir = 1;
+ break;
+ case 'R':
+ recurse_all = 1;
+ recurse_dir = 0;
+ break;
+ default:
+ return command_usage(&extsize_cmd);
+ }
}
+ if (optind < argc) {
+ extsize = (long)cvtnum(blocksize, sectsize, argv[optind]);
+ if (extsize < 0) {
+ printf(_("non-numeric extsize argument -- %s\n"),
+ argv[optind]);
+ return 0;
+ }
+ } else {
+ extsize = -1;
+ }
+
+ if (recurse_all || recurse_dir)
+ nftw(file->name, (extsize >= 0) ?
+ set_extsize_callback : get_extsize_callback,
+ 100, FTW_PHYS | FTW_MOUNT | FTW_DEPTH);
+ else if (extsize >= 0)
+ set_extsize(file->name, file->fd, extsize);
+ else
+ get_extsize(file->name, file->fd);
return 0;
}
int argc,
char **argv)
{
- struct xfs_fsop_geom_v1 fsgeo;
+ struct xfs_fsop_counts fscounts;
+ struct xfs_fsop_geom fsgeo;
struct statfs st;
- char fullname[PATH_MAX + 1];
- printf(_("fd.path = \"%s\"\n"),
- realpath(fname, fullname) ? fullname : fname);
- if (platform_fstatfs(fdesc, &st) < 0) {
+ printf(_("fd.path = \"%s\"\n"), file->name);
+ if (platform_fstatfs(file->fd, &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);
-#if !defined(__sgi__)
+#if defined(__sgi__)
+ printf(_("statfs.f_frsize = %lld\n"), (long long) st.f_frsize);
+#else
printf(_("statfs.f_bavail = %lld\n"), (long long) st.f_bavail);
#endif
+ printf(_("statfs.f_files = %lld\n"), (long long) st.f_files);
+ printf(_("statfs.f_ffree = %lld\n"), (long long) st.f_ffree);
}
- if ((xfsctl(fname, fdesc, XFS_IOC_FSGEOMETRY_V1, &fsgeo)) < 0) {
- perror("xfsctl(XFS_IOC_FSGEOMETRY_V1)");
+ if (file->flags & IO_FOREIGN)
+ return 0;
+ if ((xfsctl(file->name, file->fd, 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.sunit = %u\n"), fsgeo.sunit);
printf(_("geom.swidth = %u\n"), fsgeo.swidth);
}
+ if ((xfsctl(file->name, file->fd, XFS_IOC_FSCOUNTS, &fscounts)) < 0) {
+ perror("XFS_IOC_FSCOUNTS");
+ } else {
+ printf(_("counts.freedata = %llu\n"),
+ (unsigned long long) fscounts.freedata);
+ printf(_("counts.freertx = %llu\n"),
+ (unsigned long long) fscounts.freertx);
+ printf(_("counts.freeino = %llu\n"),
+ (unsigned long long) fscounts.freeino);
+ printf(_("counts.allocino = %llu\n"),
+ (unsigned long long) fscounts.allocino);
+ }
+ return 0;
+}
+
+static void
+inode_help(void)
+{
+ printf(_(
+"\n"
+"Query physical information about an inode"
+"\n"
+" Default: -- Return 1 if any inode number greater than 32 bits exists in\n"
+" the filesystem, or 0 if none exist\n"
+" num -- Return inode number [num] if in use, or 0 if not in use\n"
+" -n num -- Return the next used inode after [num]\n"
+" -v -- Verbose mode - display returned inode number's size in bits\n"
+"\n"));
+}
+
+static __u64
+get_last_inode(void)
+{
+ __u64 lastip = 0;
+ __u64 lastgrp = 0;
+ __s32 ocount = 0;
+ __u64 last_ino;
+ struct xfs_inogrp igroup[1024];
+ struct xfs_fsop_bulkreq bulkreq;
+
+ bulkreq.lastip = &lastip;
+ bulkreq.ubuffer = &igroup;
+ bulkreq.icount = sizeof(igroup) / sizeof(struct xfs_inogrp);
+ bulkreq.ocount = &ocount;
+
+ for (;;) {
+ if (xfsctl(file->name, file->fd, XFS_IOC_FSINUMBERS,
+ &bulkreq)) {
+ perror("XFS_IOC_FSINUMBERS");
+ return 0;
+ }
+
+ /* Did we reach the last inode? */
+ if (ocount == 0)
+ break;
+
+ /* last inode in igroup table */
+ lastgrp = ocount;
+ }
+
+ lastgrp--;
+
+ /* The last inode number in use */
+ last_ino = igroup[lastgrp].xi_startino +
+ libxfs_highbit64(igroup[lastgrp].xi_allocmask);
+
+ return last_ino;
+}
+
+static int
+inode_f(
+ int argc,
+ char **argv)
+{
+ __s32 count = 0;
+ __u64 lastino = 0;
+ __u64 userino = 0;
+ char *p;
+ int c;
+ int verbose = 0;
+ int ret_next = 0;
+ int cmd = 0;
+ struct xfs_fsop_bulkreq bulkreq;
+ struct xfs_bstat bstat;
+
+ while ((c = getopt(argc, argv, "nv")) != EOF) {
+ switch (c) {
+ case 'v':
+ verbose = 1;
+ break;
+ case 'n':
+ ret_next = 1;
+ break;
+ default:
+ return command_usage(&inode_cmd);
+ }
+ }
+
+ /*
+ * Inode number can be passed with or without extra arguments, so we
+ * should handle inode numbers passed by user out of getopt()
+ */
+ if (optind < argc) {
+
+ if (ret_next) {
+ cmd = XFS_IOC_FSBULKSTAT;
+ } else {
+ if ((argc > 2) && !verbose)
+ return command_usage(&inode_cmd);
+ else
+ cmd = XFS_IOC_FSBULKSTAT_SINGLE;
+ }
+
+ userino = strtoull(argv[optind], &p, 10);
+ if ((*p != '\0')) {
+ printf(_("[num] must be a numeric value\n"));
+ exitcode = 1;
+ return 0;
+ }
+
+ bulkreq.lastip = &userino;
+ bulkreq.icount = 1;
+ bulkreq.ubuffer = &bstat;
+ bulkreq.ocount = &count;
+
+ if (xfsctl(file->name, file->fd, cmd, &bulkreq)) {
+ if (errno == EINVAL) {
+ if (!ret_next)
+ printf("0\n");
+ } else {
+ perror("xfsctl");
+ }
+ exitcode = 1;
+ return 0;
+ }
+
+ if (ret_next)
+ userino = bstat.bs_ino;
+
+ if (verbose)
+ printf("%llu:%d\n",
+ userino,
+ userino > XFS_MAXINUMBER_32 ? 64 : 32);
+ else
+ /* Inode in use */
+ printf("%llu\n", userino);
+ return 0;
+
+ /* -n option must not be used stand alone */
+ } else if (ret_next) {
+ return command_usage(&inode_cmd);
+ }
+
+ /* We are finding last inode in use */
+ lastino = get_last_inode();
+ if (!lastino) {
+ exitcode = 1;
+ return 0;
+ }
+
+ if (verbose)
+ printf("%llu:%d\n", lastino,
+ lastino > XFS_MAXINUMBER_32 ? 64 : 32);
+ else
+ printf("%d\n", lastino > XFS_MAXINUMBER_32 ? 1 : 0);
+
return 0;
}
void
open_init(void)
{
- open_cmd.name = _("open");
- open_cmd.altname = _("o");
+ 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.flags = CMD_NOMAP_OK | CMD_NOFILE_OK | CMD_FOREIGN_OK;
+ open_cmd.args = _("[-acdrstxT] [path]");
+ open_cmd.oneline = _("open the file specified by path");
open_cmd.help = open_help;
- stat_cmd.name = _("stat");
+ stat_cmd.name = "stat";
stat_cmd.cfunc = stat_f;
stat_cmd.argmin = 0;
stat_cmd.argmax = 1;
+ stat_cmd.flags = CMD_NOMAP_OK | CMD_FOREIGN_OK;
stat_cmd.args = _("[-v]");
- stat_cmd.oneline =
- _("statistics on the currently open file");
+ stat_cmd.oneline = _("statistics on the currently open file");
- setfl_cmd.name = _("setfl");
- setfl_cmd.cfunc = setfl_f;
- setfl_cmd.args = _("[-adx]");
- setfl_cmd.oneline =
- _("set/clear append/direct flags on the open file");
+ close_cmd.name = "close";
+ close_cmd.altname = "c";
+ close_cmd.cfunc = close_f;
+ close_cmd.argmin = 0;
+ close_cmd.argmax = 0;
+ close_cmd.flags = CMD_NOMAP_OK | CMD_FOREIGN_OK;
+ close_cmd.oneline = _("close the current open file");
- statfs_cmd.name = _("statfs");
+ statfs_cmd.name = "statfs";
statfs_cmd.cfunc = statfs_f;
+ statfs_cmd.flags = CMD_NOMAP_OK | CMD_FOREIGN_OK;
statfs_cmd.oneline =
_("statistics on the filesystem of the currently open file");
- extsize_cmd.name = _("extsize");
+ chproj_cmd.name = "chproj";
+ chproj_cmd.cfunc = chproj_f;
+ chproj_cmd.args = _("[-D | -R] projid");
+ chproj_cmd.argmin = 1;
+ chproj_cmd.argmax = -1;
+ chproj_cmd.flags = CMD_NOMAP_OK | CMD_FOREIGN_OK;
+ chproj_cmd.oneline =
+ _("change project identifier on the currently open file");
+ chproj_cmd.help = chproj_help;
+
+ lsproj_cmd.name = "lsproj";
+ lsproj_cmd.cfunc = lsproj_f;
+ lsproj_cmd.args = _("[-D | -R]");
+ lsproj_cmd.argmin = 0;
+ lsproj_cmd.argmax = -1;
+ lsproj_cmd.flags = CMD_NOMAP_OK;
+ lsproj_cmd.oneline =
+ _("list project identifier set on the currently open file");
+ lsproj_cmd.help = lsproj_help;
+
+ extsize_cmd.name = "extsize";
extsize_cmd.cfunc = extsize_f;
- extsize_cmd.argmin = 1;
- extsize_cmd.argmax = 1;
+ extsize_cmd.args = _("[-D | -R] [extsize]");
+ extsize_cmd.argmin = 0;
+ extsize_cmd.argmax = -1;
+ extsize_cmd.flags = CMD_NOMAP_OK;
extsize_cmd.oneline =
- _("set prefered extent size (in bytes) for the open file");
+ _("get/set preferred extent size (in bytes) for the open file");
+ extsize_cmd.help = extsize_help;
+
+ inode_cmd.name = "inode";
+ inode_cmd.cfunc = inode_f;
+ inode_cmd.args = _("[-nv] [num]");
+ inode_cmd.argmin = 0;
+ inode_cmd.argmax = 3;
+ inode_cmd.flags = CMD_NOMAP_OK;
+ inode_cmd.oneline =
+ _("Query inode number usage in the filesystem");
+ inode_cmd.help = inode_help;
add_command(&open_cmd);
add_command(&stat_cmd);
- add_command(&setfl_cmd);
+ add_command(&close_cmd);
add_command(&statfs_cmd);
+ add_command(&chproj_cmd);
+ add_command(&lsproj_cmd);
add_command(&extsize_cmd);
+ add_command(&inode_cmd);
}