2 * Copyright (c) 2003-2005 Silicon Graphics, Inc.
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation.
9 * This program is distributed in the hope that it would be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write the Free Software Foundation,
16 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
27 #define __O_TMPFILE 0100000000
28 #elif defined(__hppa__)
29 #define __O_TMPFILE 040000000
30 #elif defined(__sparc__)
31 #define __O_TMPFILE 0x2000000
33 #define __O_TMPFILE 020000000
35 #endif /* __O_TMPFILE */
38 #define O_TMPFILE (__O_TMPFILE | O_DIRECTORY)
41 static cmdinfo_t open_cmd
;
42 static cmdinfo_t stat_cmd
;
43 static cmdinfo_t close_cmd
;
44 static cmdinfo_t statfs_cmd
;
45 static cmdinfo_t chproj_cmd
;
46 static cmdinfo_t lsproj_cmd
;
47 static cmdinfo_t extsize_cmd
;
48 static cmdinfo_t inode_cmd
;
57 if (fstat64(file
->fd
, &st
) < 0) {
67 switch (mode
& S_IFMT
) {
71 return _("directory");
73 return _("char device");
75 return _("block device");
77 return _("regular file");
79 return _("symbolic link");
92 struct fsxattr fsx
, fsxa
;
94 int verbose
= (argc
== 2 && !strcmp(argv
[1], "-v"));
96 printf(_("fd.path = \"%s\"\n"), file
->name
);
97 printf(_("fd.flags = %s,%s,%s%s%s%s%s\n"),
98 file
->flags
& IO_OSYNC
? _("sync") : _("non-sync"),
99 file
->flags
& IO_DIRECT
? _("direct") : _("non-direct"),
100 file
->flags
& IO_READONLY
? _("read-only") : _("read-write"),
101 file
->flags
& IO_REALTIME
? _(",real-time") : "",
102 file
->flags
& IO_APPEND
? _(",append-only") : "",
103 file
->flags
& IO_NONBLOCK
? _(",non-block") : "",
104 file
->flags
& IO_TMPFILE
? _(",tmpfile") : "");
105 if (fstat64(file
->fd
, &st
) < 0) {
108 printf(_("stat.ino = %lld\n"), (long long)st
.st_ino
);
109 printf(_("stat.type = %s\n"), filetype(st
.st_mode
));
110 printf(_("stat.size = %lld\n"), (long long)st
.st_size
);
111 printf(_("stat.blocks = %lld\n"), (long long)st
.st_blocks
);
113 printf(_("stat.atime = %s"), ctime(&st
.st_atime
));
114 printf(_("stat.mtime = %s"), ctime(&st
.st_mtime
));
115 printf(_("stat.ctime = %s"), ctime(&st
.st_ctime
));
118 if (file
->flags
& IO_FOREIGN
)
120 if ((xfsctl(file
->name
, file
->fd
, FS_IOC_FSGETXATTR
, &fsx
)) < 0 ||
121 (xfsctl(file
->name
, file
->fd
, XFS_IOC_FSGETXATTRA
, &fsxa
)) < 0) {
122 perror("FS_IOC_FSGETXATTR");
124 printf(_("fsxattr.xflags = 0x%x "), fsx
.fsx_xflags
);
125 printxattr(fsx
.fsx_xflags
, verbose
, 0, file
->name
, 1, 1);
126 printf(_("fsxattr.projid = %u\n"), fsx
.fsx_projid
);
127 printf(_("fsxattr.extsize = %u\n"), fsx
.fsx_extsize
);
128 printf(_("fsxattr.nextents = %u\n"), fsx
.fsx_nextents
);
129 printf(_("fsxattr.naextents = %u\n"), fsxa
.fsx_nextents
);
131 if ((xfsctl(file
->name
, file
->fd
, XFS_IOC_DIOINFO
, &dio
)) < 0) {
132 perror("XFS_IOC_DIOINFO");
134 printf(_("dioattr.mem = 0x%x\n"), dio
.d_mem
);
135 printf(_("dioattr.miniosz = %u\n"), dio
.d_miniosz
);
136 printf(_("dioattr.maxiosz = %u\n"), dio
.d_maxiosz
);
144 xfs_fsop_geom_t
*geom
,
151 oflags
= flags
& IO_READONLY
? O_RDONLY
: O_RDWR
;
152 if (flags
& IO_APPEND
)
154 if (flags
& IO_CREAT
)
156 if (flags
& IO_DIRECT
)
158 if (flags
& IO_OSYNC
)
160 if (flags
& IO_TRUNC
)
162 if (flags
& IO_NONBLOCK
)
163 oflags
|= O_NONBLOCK
;
164 if (flags
& IO_TMPFILE
)
167 fd
= open(path
, oflags
, mode
);
169 if (errno
== EISDIR
&&
170 ((oflags
& (O_RDWR
|O_TMPFILE
)) == O_RDWR
)) {
171 /* make it as if we asked for O_RDONLY & try again */
174 flags
|= IO_READONLY
;
175 fd
= open(path
, oflags
, mode
);
186 if (!geom
|| !platform_test_xfs_fd(fd
))
189 if (xfsctl(path
, fd
, XFS_IOC_FSGEOMETRY
, geom
) < 0) {
190 perror("XFS_IOC_FSGEOMETRY");
195 if (!(flags
& IO_READONLY
) && (flags
& IO_REALTIME
)) {
198 if (xfsctl(path
, fd
, FS_IOC_FSGETXATTR
, &attr
) < 0) {
199 perror("FS_IOC_FSGETXATTR");
203 if (!(attr
.fsx_xflags
& FS_XFLAG_REALTIME
)) {
204 attr
.fsx_xflags
|= FS_XFLAG_REALTIME
;
205 if (xfsctl(path
, fd
, FS_IOC_FSSETXATTR
, &attr
) < 0) {
206 perror("FS_IOC_FSSETXATTR");
219 xfs_fsop_geom_t
*geometry
,
224 filename
= strdup(name
);
231 /* Extend the table of currently open files */
232 filetable
= (fileio_t
*)realloc(filetable
, /* growing */
233 ++filecount
* sizeof(fileio_t
));
242 /* Finally, make this the new active open file */
243 file
= &filetable
[filecount
- 1];
246 file
->name
= filename
;
247 file
->geom
= *geometry
;
256 " opens a new file in the requested mode\n"
259 " 'open -cd /tmp/data' - creates/opens data file read-write for direct IO\n"
261 " Opens a file for subsequent use by all of the other xfs_io commands.\n"
262 " With no arguments, open uses the stat command to show the current file.\n"
263 " -a -- open with the O_APPEND flag (append-only mode)\n"
264 " -d -- open with O_DIRECT (non-buffered IO, note alignment constraints)\n"
265 " -f -- open with O_CREAT (create the file if it doesn't exist)\n"
266 " -m -- permissions to use in case a new file is created (default 0600)\n"
267 " -n -- open with O_NONBLOCK\n"
268 " -r -- open with O_RDONLY, the default is O_RDWR\n"
269 " -s -- open with O_SYNC\n"
270 " -t -- open with O_TRUNC (truncate the file to zero length if it exists)\n"
271 " -R -- mark the file as a realtime XFS file immediately after opening it\n"
272 " -T -- open with O_TMPFILE (create a file not visible in the namespace)\n"
273 " Note1: usually read/write direct IO requests must be blocksize aligned;\n"
274 " some kernels, however, allow sectorsize alignment for direct IO.\n"
275 " Note2: the bmap for non-regular files can be obtained provided the file\n"
276 " was opened correctly (in particular, must be opened read-only).\n"
285 int c
, fd
, flags
= 0;
288 xfs_fsop_geom_t geometry
= { 0 };
292 return stat_f(argc
, argv
);
293 fprintf(stderr
, _("no files are open, try 'help open'\n"));
297 while ((c
= getopt(argc
, argv
, "FRTacdfm:nrstx")) != EOF
) {
300 /* Ignored / deprecated now, handled automatically */
313 mode
= strtoul(optarg
, &sp
, 0);
314 if (!sp
|| sp
== optarg
) {
315 printf(_("non-numeric mode -- %s\n"), optarg
);
320 flags
|= IO_NONBLOCK
;
323 flags
|= IO_READONLY
;
332 case 'x': /* backwards compatibility */
333 flags
|= IO_REALTIME
;
339 return command_usage(&open_cmd
);
343 if (optind
!= argc
- 1)
344 return command_usage(&open_cmd
);
346 if ((flags
& (IO_READONLY
|IO_TMPFILE
)) == (IO_READONLY
|IO_TMPFILE
)) {
347 fprintf(stderr
, _("-T and -r options are incompatible\n"));
351 fd
= openfile(argv
[optind
], &geometry
, flags
, mode
);
355 if (!platform_test_xfs_fd(fd
))
358 addfile(argv
[optind
], fd
, &geometry
, flags
);
370 if (close(file
->fd
) < 0) {
376 /* Shuffle the file table entries down over the removed entry */
377 offset
= file
- &filetable
[0];
378 length
= filecount
* sizeof(fileio_t
);
379 length
-= (offset
+ 1) * sizeof(fileio_t
);
381 memmove(file
, file
+ 1, length
);
383 /* Resize the memory allocated for the table, possibly freeing */
385 filetable
= (fileio_t
*)realloc(filetable
, /* shrinking */
386 filecount
* sizeof(fileio_t
));
387 if (offset
== filecount
)
389 file
= filetable
+ offset
;
392 file
= filetable
= NULL
;
403 " displays the project identifier associated with the current path\n"
406 " -R -- recursively descend (useful when current path is a directory)\n"
407 " -D -- recursively descend, but only list projects on directories\n"
414 const struct stat
*stat
,
421 if (recurse_dir
&& !S_ISDIR(stat
->st_mode
))
424 if ((fd
= open(path
, O_RDONLY
)) == -1) {
425 fprintf(stderr
, _("%s: cannot open %s: %s\n"),
426 progname
, path
, strerror(errno
));
428 if (getprojid(path
, fd
, &projid
) == 0)
429 printf("[%u] %s\n", (unsigned int)projid
, path
);
443 recurse_all
= recurse_dir
= 0;
444 while ((c
= getopt(argc
, argv
, "DR")) != EOF
) {
455 return command_usage(&lsproj_cmd
);
460 return command_usage(&lsproj_cmd
);
462 if (recurse_all
|| recurse_dir
)
463 nftw(file
->name
, lsproj_callback
,
464 100, FTW_PHYS
| FTW_MOUNT
| FTW_DEPTH
);
465 else if (getprojid(file
->name
, file
->fd
, &projid
) < 0)
468 printf(_("projid = %u\n"), (unsigned int)projid
);
477 " modifies the project identifier associated with the current path\n"
479 " -R -- recursively descend (useful when current path is a directory)\n"
480 " -D -- recursively descend, only modifying projects on directories\n"
487 const struct stat
*stat
,
493 if (recurse_dir
&& !S_ISDIR(stat
->st_mode
))
496 if ((fd
= open(path
, O_RDONLY
)) == -1) {
497 fprintf(stderr
, _("%s: cannot open %s: %s\n"),
498 progname
, path
, strerror(errno
));
500 if (setprojid(path
, fd
, prid
) < 0)
514 recurse_all
= recurse_dir
= 0;
515 while ((c
= getopt(argc
, argv
, "DR")) != EOF
) {
526 return command_usage(&chproj_cmd
);
530 if (argc
!= optind
+ 1)
531 return command_usage(&chproj_cmd
);
533 prid
= prid_from_string(argv
[optind
]);
535 printf(_("invalid project ID -- %s\n"), argv
[optind
]);
539 if (recurse_all
|| recurse_dir
)
540 nftw(file
->name
, chproj_callback
,
541 100, FTW_PHYS
| FTW_MOUNT
| FTW_DEPTH
);
542 else if (setprojid(file
->name
, file
->fd
, prid
) < 0)
552 " report or modify preferred extent size (in bytes) for the current path\n"
554 " -R -- recursively descend (useful when current path is a directory)\n"
555 " -D -- recursively descend, only modifying extsize on directories\n"
560 get_extsize(const char *path
, int fd
)
564 if ((xfsctl(path
, fd
, FS_IOC_FSGETXATTR
, &fsx
)) < 0) {
565 printf("%s: FS_IOC_FSGETXATTR %s: %s\n",
566 progname
, path
, strerror(errno
));
569 printf("[%u] %s\n", fsx
.fsx_extsize
, path
);
574 set_extsize(const char *path
, int fd
, long extsz
)
579 if (fstat64(fd
, &stat
) < 0) {
583 if ((xfsctl(path
, fd
, FS_IOC_FSGETXATTR
, &fsx
)) < 0) {
584 printf("%s: FS_IOC_FSGETXATTR %s: %s\n",
585 progname
, path
, strerror(errno
));
589 if (S_ISREG(stat
.st_mode
)) {
590 fsx
.fsx_xflags
|= FS_XFLAG_EXTSIZE
;
591 } else if (S_ISDIR(stat
.st_mode
)) {
592 fsx
.fsx_xflags
|= FS_XFLAG_EXTSZINHERIT
;
594 printf(_("invalid target file type - file %s\n"), path
);
597 fsx
.fsx_extsize
= extsz
;
599 if ((xfsctl(path
, fd
, FS_IOC_FSSETXATTR
, &fsx
)) < 0) {
600 printf("%s: FS_IOC_FSSETXATTR %s: %s\n",
601 progname
, path
, strerror(errno
));
609 get_extsize_callback(
611 const struct stat
*stat
,
617 if (recurse_dir
&& !S_ISDIR(stat
->st_mode
))
620 if ((fd
= open(path
, O_RDONLY
)) == -1) {
621 fprintf(stderr
, _("%s: cannot open %s: %s\n"),
622 progname
, path
, strerror(errno
));
624 get_extsize(path
, fd
);
631 set_extsize_callback(
633 const struct stat
*stat
,
639 if (recurse_dir
&& !S_ISDIR(stat
->st_mode
))
642 if ((fd
= open(path
, O_RDONLY
)) == -1) {
643 fprintf(stderr
, _("%s: cannot open %s: %s\n"),
644 progname
, path
, strerror(errno
));
646 set_extsize(path
, fd
, extsize
);
657 size_t blocksize
, sectsize
;
660 recurse_all
= recurse_dir
= 0;
661 init_cvtnum(&blocksize
, §size
);
662 while ((c
= getopt(argc
, argv
, "DR")) != EOF
) {
673 return command_usage(&extsize_cmd
);
678 extsize
= (long)cvtnum(blocksize
, sectsize
, argv
[optind
]);
680 printf(_("non-numeric extsize argument -- %s\n"),
688 if (recurse_all
|| recurse_dir
)
689 nftw(file
->name
, (extsize
>= 0) ?
690 set_extsize_callback
: get_extsize_callback
,
691 100, FTW_PHYS
| FTW_MOUNT
| FTW_DEPTH
);
692 else if (extsize
>= 0)
693 set_extsize(file
->name
, file
->fd
, extsize
);
695 get_extsize(file
->name
, file
->fd
);
704 struct xfs_fsop_counts fscounts
;
705 struct xfs_fsop_geom fsgeo
;
708 printf(_("fd.path = \"%s\"\n"), file
->name
);
709 if (platform_fstatfs(file
->fd
, &st
) < 0) {
712 printf(_("statfs.f_bsize = %lld\n"), (long long) st
.f_bsize
);
713 printf(_("statfs.f_blocks = %lld\n"), (long long) st
.f_blocks
);
715 printf(_("statfs.f_frsize = %lld\n"), (long long) st
.f_frsize
);
717 printf(_("statfs.f_bavail = %lld\n"), (long long) st
.f_bavail
);
719 printf(_("statfs.f_files = %lld\n"), (long long) st
.f_files
);
720 printf(_("statfs.f_ffree = %lld\n"), (long long) st
.f_ffree
);
722 if (file
->flags
& IO_FOREIGN
)
724 if ((xfsctl(file
->name
, file
->fd
, XFS_IOC_FSGEOMETRY_V1
, &fsgeo
)) < 0) {
725 perror("XFS_IOC_FSGEOMETRY_V1");
727 printf(_("geom.bsize = %u\n"), fsgeo
.blocksize
);
728 printf(_("geom.agcount = %u\n"), fsgeo
.agcount
);
729 printf(_("geom.agblocks = %u\n"), fsgeo
.agblocks
);
730 printf(_("geom.datablocks = %llu\n"),
731 (unsigned long long) fsgeo
.datablocks
);
732 printf(_("geom.rtblocks = %llu\n"),
733 (unsigned long long) fsgeo
.rtblocks
);
734 printf(_("geom.rtextents = %llu\n"),
735 (unsigned long long) fsgeo
.rtextents
);
736 printf(_("geom.rtextsize = %u\n"), fsgeo
.rtextsize
);
737 printf(_("geom.sunit = %u\n"), fsgeo
.sunit
);
738 printf(_("geom.swidth = %u\n"), fsgeo
.swidth
);
740 if ((xfsctl(file
->name
, file
->fd
, XFS_IOC_FSCOUNTS
, &fscounts
)) < 0) {
741 perror("XFS_IOC_FSCOUNTS");
743 printf(_("counts.freedata = %llu\n"),
744 (unsigned long long) fscounts
.freedata
);
745 printf(_("counts.freertx = %llu\n"),
746 (unsigned long long) fscounts
.freertx
);
747 printf(_("counts.freeino = %llu\n"),
748 (unsigned long long) fscounts
.freeino
);
749 printf(_("counts.allocino = %llu\n"),
750 (unsigned long long) fscounts
.allocino
);
760 "Query physical information about an inode"
762 " Default: -- Return 1 if any inode number greater than 32 bits exists in\n"
763 " the filesystem, or 0 if none exist\n"
764 " num -- Return inode number [num] if in use, or 0 if not in use\n"
765 " -n num -- Return the next used inode after [num]\n"
766 " -v -- Verbose mode - display returned inode number's size in bits\n"
785 struct xfs_inogrp igroup
[1024];
786 struct xfs_fsop_bulkreq bulkreq
;
787 struct xfs_bstat bstat
;
789 while ((c
= getopt(argc
, argv
, "nv")) != EOF
) {
798 return command_usage(&inode_cmd
);
803 * Inode number can be passed with or without extra arguments, so we
804 * should handle inode numbers passed by user out of getopt()
809 cmd
= XFS_IOC_FSBULKSTAT
;
811 if ((argc
> 2) && !verbose
)
812 return command_usage(&inode_cmd
);
814 cmd
= XFS_IOC_FSBULKSTAT_SINGLE
;
817 userino
= strtoull(argv
[optind
], &p
, 10);
819 printf(_("[num] must be a numeric value\n"));
824 bulkreq
.lastip
= &userino
;
826 bulkreq
.ubuffer
= &bstat
;
827 bulkreq
.ocount
= &count
;
829 if (xfsctl(file
->name
, file
->fd
, cmd
, &bulkreq
)) {
830 if (errno
== EINVAL
) {
841 userino
= bstat
.bs_ino
;
846 userino
> XFS_MAXINUMBER_32
? 64 : 32);
849 printf("%llu\n", userino
);
852 /* -n option must not be used stand alone */
853 } else if (ret_next
) {
854 return command_usage(&inode_cmd
);
857 bulkreq
.lastip
= &last
;
858 bulkreq
.icount
= 1024; /* User-defined maybe!? */
859 bulkreq
.ubuffer
= &igroup
;
860 bulkreq
.ocount
= &count
;
863 if (xfsctl(file
->name
, file
->fd
, XFS_IOC_FSINUMBERS
,
865 perror("XFS_IOC_FSINUMBERS");
877 lastino
= igroup
[lastgrp
].xi_startino
+
878 libxfs_highbit64(igroup
[lastgrp
].xi_allocmask
);
881 printf("%llu:%d\n", lastino
,
882 lastino
> XFS_MAXINUMBER_32
? 64 : 32);
884 printf("%d\n", lastino
> XFS_MAXINUMBER_32
? 1 : 0);
892 open_cmd
.name
= "open";
893 open_cmd
.altname
= "o";
894 open_cmd
.cfunc
= open_f
;
896 open_cmd
.argmax
= -1;
897 open_cmd
.flags
= CMD_NOMAP_OK
| CMD_NOFILE_OK
| CMD_FOREIGN_OK
;
898 open_cmd
.args
= _("[-acdrstxT] [path]");
899 open_cmd
.oneline
= _("open the file specified by path");
900 open_cmd
.help
= open_help
;
902 stat_cmd
.name
= "stat";
903 stat_cmd
.cfunc
= stat_f
;
906 stat_cmd
.flags
= CMD_NOMAP_OK
| CMD_FOREIGN_OK
;
907 stat_cmd
.args
= _("[-v]");
908 stat_cmd
.oneline
= _("statistics on the currently open file");
910 close_cmd
.name
= "close";
911 close_cmd
.altname
= "c";
912 close_cmd
.cfunc
= close_f
;
913 close_cmd
.argmin
= 0;
914 close_cmd
.argmax
= 0;
915 close_cmd
.flags
= CMD_NOMAP_OK
| CMD_FOREIGN_OK
;
916 close_cmd
.oneline
= _("close the current open file");
918 statfs_cmd
.name
= "statfs";
919 statfs_cmd
.cfunc
= statfs_f
;
920 statfs_cmd
.flags
= CMD_NOMAP_OK
| CMD_FOREIGN_OK
;
922 _("statistics on the filesystem of the currently open file");
924 chproj_cmd
.name
= "chproj";
925 chproj_cmd
.cfunc
= chproj_f
;
926 chproj_cmd
.args
= _("[-D | -R] projid");
927 chproj_cmd
.argmin
= 1;
928 chproj_cmd
.argmax
= -1;
929 chproj_cmd
.flags
= CMD_NOMAP_OK
| CMD_FOREIGN_OK
;
931 _("change project identifier on the currently open file");
932 chproj_cmd
.help
= chproj_help
;
934 lsproj_cmd
.name
= "lsproj";
935 lsproj_cmd
.cfunc
= lsproj_f
;
936 lsproj_cmd
.args
= _("[-D | -R]");
937 lsproj_cmd
.argmin
= 0;
938 lsproj_cmd
.argmax
= -1;
939 lsproj_cmd
.flags
= CMD_NOMAP_OK
;
941 _("list project identifier set on the currently open file");
942 lsproj_cmd
.help
= lsproj_help
;
944 extsize_cmd
.name
= "extsize";
945 extsize_cmd
.cfunc
= extsize_f
;
946 extsize_cmd
.args
= _("[-D | -R] [extsize]");
947 extsize_cmd
.argmin
= 0;
948 extsize_cmd
.argmax
= -1;
949 extsize_cmd
.flags
= CMD_NOMAP_OK
;
950 extsize_cmd
.oneline
=
951 _("get/set preferred extent size (in bytes) for the open file");
952 extsize_cmd
.help
= extsize_help
;
954 inode_cmd
.name
= "inode";
955 inode_cmd
.cfunc
= inode_f
;
956 inode_cmd
.args
= _("[-nv] [num]");
957 inode_cmd
.argmin
= 0;
958 inode_cmd
.argmax
= 3;
959 inode_cmd
.flags
= CMD_NOMAP_OK
;
961 _("Query inode number usage in the filesystem");
962 inode_cmd
.help
= inode_help
;
964 add_command(&open_cmd
);
965 add_command(&stat_cmd
);
966 add_command(&close_cmd
);
967 add_command(&statfs_cmd
);
968 add_command(&chproj_cmd
);
969 add_command(&lsproj_cmd
);
970 add_command(&extsize_cmd
);
971 add_command(&inode_cmd
);