diff mbox

xfs_io: changes to statx interface [ver #3]

Message ID 8127.1490802589@warthog.procyon.org.uk (mailing list archive)
State Superseded, archived
Headers show

Commit Message

David Howells March 29, 2017, 3:49 p.m. UTC
Here's my third attempt at changing Eric's statx patch.  I've got rid of the
compare option to statx and added a raw output option to stat.  They're still
not directly comparable since the stat output lacks some fields, but it will
hopefully be possible to load them into associative arrays in bash and compare
them that way.

---
--
To unsubscribe from this list: send the line "unsubscribe linux-xfs" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Comments

David Howells March 29, 2017, 4:40 p.m. UTC | #1
David Howells <dhowells@redhat.com> wrote:

> Here's my third attempt at changing Eric's statx patch.  I've got rid of the
> compare option to statx and added a raw output option to stat.  They're still
> not directly comparable since the stat output lacks some fields, but it will
> hopefully be possible to load them into associative arrays in bash and compare
> them that way.

Kind of like this:

function cmpstat () {
    file=$1
    declare -A st stx

    # Read the stat output
    coproc { xfs_io -c "open -P $file" -c "stat -r" | sed -e s/://; }
    while read tag val
    do
	st[$tag]=$val
    done <&${COPROC[0]}
    wait || exit $?

    # Read the statx output
    coproc { xfs_io -c "open -P $file" -c "statx" | sed -e s/://; }
    while read tag val
    do
	stx[$tag]=$val
    done <&${COPROC[0]}
    wait || exit $?

    # Compare them
    for key in ${!stx[*]}
    do
	if [ "${stx[$key]}" != "${st[$key]}" ]
	then
	    case $key in
		stat.mask|stat.attributes|stat.btime.tv_*)
		    # Not supported in stat
		    ;;
		*)
		    echo differ $key "${stx[$key]}" != "${st[$key]}"
		    ;;
	    esac
	fi
    done
}

cmpstat /
--
To unsubscribe from this list: send the line "unsubscribe linux-xfs" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Eric Sandeen March 29, 2017, 9:32 p.m. UTC | #2
On 3/29/17 11:49 AM, David Howells wrote:
> Here's my third attempt at changing Eric's statx patch.  I've got rid of the
> compare option to statx and added a raw output option to stat.  They're still
> not directly comparable since the stat output lacks some fields, but it will
> hopefully be possible to load them into associative arrays in bash and compare
> them that way.

Thanks for working on this; comments below.

But - do you plan to send this as (a) formal patch(es) with signed-off-by
etc?  Or do you want me to just fold this into my patch with some
sort of Changes-inspired-by: David Howells <dhowells@redhat.com> tag? ;)

The changes to stat_f should be their own standalone patch, I think.

(meh, it's kind of unfortunate that the current stat_f does more
than just stat, isn't it?)

I may make further changes so that a bare "statx" prints exactly the
same info as a bare "stat", and a new "-r" to each one dumps the raw
stat[x] structure.  Just for some symmetry...

> ---
> diff --git a/io/stat.c b/io/stat.c
> index a7aebcd..d2ea854 100644
> --- a/io/stat.c
> +++ b/io/stat.c
> @@ -44,6 +44,35 @@ filesize(void)
>  	return st.st_size;
>  }
>  
> +static int
> +dump_raw_stat(struct stat *st)
> +{
> +	if (fstat(file->fd, st) < 0) {
> +		perror("fstat");
> +		return -1;
> +	}
> +
> +	printf("stat.blksize: %lu\n", st->st_blksize);
> +	printf("stat.nlink: %lu\n", st->st_nlink);
> +	printf("stat.uid: %u\n", st->st_uid);
> +	printf("stat.gid: %u\n", st->st_gid);
> +	printf("stat.mode: 0%o\n", st->st_mode);
> +	printf("stat.ino: %lu\n", st->st_ino);
> +	printf("stat.size: %lu\n", st->st_size);
> +	printf("stat.blocks: %lu\n", st->st_blocks);
> +	printf("stat.atime.tv_sec: %ld\n", st->st_atim.tv_sec);
> +	printf("stat.atime.tv_nsec: %ld\n", st->st_atim.tv_nsec);
> +	printf("stat.ctime.tv_sec: %ld\n", st->st_ctim.tv_sec);
> +	printf("stat.ctime.tv_nsec: %ld\n", st->st_ctim.tv_nsec);
> +	printf("stat.mtime.tv_sec: %ld\n", st->st_mtim.tv_sec);
> +	printf("stat.mtime.tv_nsec: %ld\n", st->st_mtim.tv_nsec);
> +	printf("stat.rdev_major: %u\n", major(st->st_rdev));
> +	printf("stat.rdev_minor: %u\n", minor(st->st_rdev));
> +	printf("stat.dev_major: %u\n", major(st->st_dev));
> +	printf("stat.dev_minor: %u\n", minor(st->st_dev));
> +	return 0;
> +}
> +
>  static char *
>  filetype(mode_t mode)
>  {
> @@ -74,7 +103,23 @@ stat_f(
>  	struct dioattr	dio;
>  	struct fsxattr	fsx, fsxa;
>  	struct stat	st;
> -	int		verbose = (argc == 2 && !strcmp(argv[1], "-v"));
> +	int		c, verbose = 0, raw = 0;
> +
> +	while ((c = getopt(argc, argv, "rv")) != EOF) {
> +		switch (c) {
> +		case 'r':
> +			raw = 1;
> +			break;
> +		case 'v':
> +			verbose = 1;
> +			break;
> +		default:
> +			return command_usage(&stat_cmd);
> +		}
> +	}
> +
> +	if (raw)
> +		return dump_raw_stat(&st);
>  
>  	printf(_("fd.path = \"%s\"\n"), file->name);
>  	printf(_("fd.flags = %s,%s,%s%s%s%s%s\n"),
> @@ -189,12 +234,9 @@ statx_help(void)
>  " Display extended file status.\n"
>  "\n"
>  " Options:\n"
> -" -m mask -- Specify the field mask for the statx call (default STATX_ALL)\n"
> -" -A -- Suppress terminal automount traversal\n"
> +" -m mask -- Specify the field mask for the statx call (can also be 'basic' or 'all'; default STATX_ALL)\n"
>  " -D -- Don't sync attributes with the server\n"
>  " -F -- Force the attributes to be sync'd with the server\n"
> -" -L -- Follow symlinks (statx link target)\n"
> -" -O -- Add only basic stats (STATX_BASIC_STATS) to default mask\n"

ok, I like the basic/all/mask better, yes.

>  "\n"));
>  }
>  
> @@ -202,28 +244,28 @@ statx_help(void)
>  static void
>  dump_statx(struct statx *stx)
>  {
> -	printf("stx_mask: 0x%x\n", stx->stx_mask);
> -	printf("stx_blksize: %u\n", stx->stx_blksize);
> -	printf("stx_attributes: 0x%llx\n", stx->stx_attributes);
> -	printf("stx_nlink: %u\n", stx->stx_nlink);
> -	printf("stx_uid: %u\n", stx->stx_uid);
> -	printf("stx_gid: %u\n", stx->stx_gid);
> -	printf("stx_mode: 0%o\n", stx->stx_mode);
> -	printf("stx_ino: %llu\n", stx->stx_ino);
> -	printf("stx_size: %llu\n", stx->stx_size);
> -	printf("stx_blocks: %llu\n", stx->stx_blocks);
> -	printf("stx_atime.tv_sec: %lld\n", stx->stx_atime.tv_sec);
> -	printf("stx_atime.tv_nsec: %d\n", stx->stx_atime.tv_nsec);
> -	printf("stx_btime.tv_sec: %lld\n", stx->stx_btime.tv_sec);
> -	printf("stx_btime.tv_nsec: %d\n", stx->stx_btime.tv_nsec);
> -	printf("stx_ctime.tv_sec: %lld\n", stx->stx_ctime.tv_sec);
> -	printf("stx_ctime.tv_nsec: %d\n", stx->stx_ctime.tv_nsec);
> -	printf("stx_mtime.tv_sec: %lld\n", stx->stx_mtime.tv_sec);
> -	printf("stx_mtime.tv_nsec: %d\n", stx->stx_mtime.tv_nsec);
> -	printf("stx_rdev_major: %u\n", stx->stx_rdev_major);
> -	printf("stx_rdev_minor: %u\n", stx->stx_rdev_minor);
> -	printf("stx_dev_major: %u\n", stx->stx_dev_major);
> -	printf("stx_dev_minor: %u\n", stx->stx_dev_minor);
> +	printf("stat.mask: 0x%x\n", stx->stx_mask);

Seems a little weird to be printing something that looks
like structure.member, when it's not actually the structure
or member name, but I suppose it facilitates parsing the output
for testing?

> +	printf("stat.blksize: %u\n", stx->stx_blksize);
> +	printf("stat.attributes: 0x%llx\n", stx->stx_attributes);
> +	printf("stat.nlink: %u\n", stx->stx_nlink);
> +	printf("stat.uid: %u\n", stx->stx_uid);
> +	printf("stat.gid: %u\n", stx->stx_gid);
> +	printf("stat.mode: 0%o\n", stx->stx_mode);
> +	printf("stat.ino: %llu\n", stx->stx_ino);
> +	printf("stat.size: %llu\n", stx->stx_size);
> +	printf("stat.blocks: %llu\n", stx->stx_blocks);
> +	printf("stat.atime.tv_sec: %lld\n", stx->stx_atime.tv_sec);
> +	printf("stat.atime.tv_nsec: %d\n", stx->stx_atime.tv_nsec);
> +	printf("stat.btime.tv_sec: %lld\n", stx->stx_btime.tv_sec);
> +	printf("stat.btime.tv_nsec: %d\n", stx->stx_btime.tv_nsec);
> +	printf("stat.ctime.tv_sec: %lld\n", stx->stx_ctime.tv_sec);
> +	printf("stat.ctime.tv_nsec: %d\n", stx->stx_ctime.tv_nsec);
> +	printf("stat.mtime.tv_sec: %lld\n", stx->stx_mtime.tv_sec);
> +	printf("stat.mtime.tv_nsec: %d\n", stx->stx_mtime.tv_nsec);
> +	printf("stat.rdev_major: %u\n", stx->stx_rdev_major);
> +	printf("stat.rdev_minor: %u\n", stx->stx_rdev_minor);
> +	printf("stat.dev_major: %u\n", stx->stx_dev_major);
> +	printf("stat.dev_minor: %u\n", stx->stx_dev_minor);
>  }
>  
>  /*
> @@ -239,16 +281,18 @@ statx_f(
>  {
>  	int		c;
>  	struct statx	stx;
> -	int		atflag = AT_SYMLINK_NOFOLLOW;
> -	unsigned int	m_mask = 0;	/* mask requested with -m */
> -	int		Oflag = 0, mflag = 0;	/* -O or -m was used */
> +	int		atflag = 0;
>  	unsigned int	mask = STATX_ALL;
>  
> -	while ((c = getopt(argc, argv, "m:FDLOA")) != EOF) {
> +	while ((c = getopt(argc, argv, "m:FD")) != EOF) {
>  		switch (c) {
>  		case 'm':
> -			m_mask = atoi(optarg);
> -			mflag = 1;
> +			if (strcmp(optarg, "basic") == 0)
> +				mask = STATX_BASIC_STATS;
> +			else if (strcmp(optarg, "all") == 0)
> +				mask = STATX_ALL;
> +			else
> +				mask = strtoul(optarg, NULL, 0);

best to check for failure here I suppose, but I've already got 
that in my current patch.

>  			break;
>  		case 'F':
>  			atflag &= ~AT_STATX_SYNC_TYPE;
> @@ -258,38 +302,19 @@ statx_f(
>  			atflag &= ~AT_STATX_SYNC_TYPE;
>  			atflag |= AT_STATX_DONT_SYNC;
>  			break;
> -		case 'L':
> -			atflag &= ~AT_SYMLINK_NOFOLLOW;
> -			break;
> -		case 'O':
> -			mask = STATX_BASIC_STATS;
> -			Oflag = 1;
> -			break;
> -		case 'A':
> -			atflag |= AT_NO_AUTOMOUNT;
> -			break;
>  		default:
>  			return command_usage(&statx_cmd);
>  		}
>  	}
>  
> -	if (Oflag && mflag) {
> -		printf("Cannot specify both -m mask and -O\n");
> -		return 0;
> -	}
> -
> -	/* -m overrides any other mask options */
> -	if (mflag)
> -		mask = m_mask;
> -
>  	memset(&stx, 0xbf, sizeof(stx));
> -	if (statx(AT_FDCWD, file->name, atflag, mask, &stx) < 0) {
> +
> +	if (statx(file->fd, NULL, atflag, mask, &stx) < 0) {
>  		perror("statx");
>  		return 0;
>  	}
> -
> +	

whitespace ;)

>  	dump_statx(&stx);
> -
>  	return 0;
>  }
>  
> @@ -301,7 +326,7 @@ stat_init(void)
>  	stat_cmd.argmin = 0;
>  	stat_cmd.argmax = 1;
>  	stat_cmd.flags = CMD_NOMAP_OK | CMD_FOREIGN_OK;
> -	stat_cmd.args = _("[-v]");
> +	stat_cmd.args = _("[-rv]");
>  	stat_cmd.oneline = _("information about the currently open file");
>  
>  	statfs_cmd.name = "statfs";
> @@ -315,7 +340,7 @@ stat_init(void)
>  	statx_cmd.argmin = 0;
>  	statx_cmd.argmax = -1;
>  	statx_cmd.flags = CMD_NOMAP_OK | CMD_FOREIGN_OK;
> -	statx_cmd.args = _("[-O | -m mask][-FDLAP]");
> +	statx_cmd.args = _("[-m basic | -m all | -m <mask>][-FD]");
>  	statx_cmd.oneline =
>   _("extended information about the currently open file");
>  	statx_cmd.help = statx_help;
> diff --git a/man/man8/xfs_io.8 b/man/man8/xfs_io.8
> index 77ba760..486ad11 100644
> --- a/man/man8/xfs_io.8
> +++ b/man/man8/xfs_io.8
> @@ -876,24 +876,29 @@ Only available in expert mode and requires privileges.
>  Force the filesystem to shutdown (with or without flushing the log).
>  Only available in expert mode and requires privileges.
>  .TP
> -.BR stat " [ " \-v " ]"
> +.BR stat " [ \-" rv " ]"
>  Selected statistics from
>  .BR stat (2)
>  and the XFS_IOC_GETXATTR system call on the current file. If the
>  .B \-v
>  option is specified, the atime (last access), mtime
> -(last modify), and ctime (last change) timestamps are also displayed.
> +(last modify), and ctime (last change) timestamps are also displayed. If the
> +.B \-r
> +option is specified, the raw output will be dumped in the same form as the
> +output for the statx command, but with some fields missing.
>  .TP
> -.BR statx " [ " \-O " | " "\-m mask" " ][ \-" FDLA " ]"
> +.BR statx " [ " "\-m mask" " ][ \-" FD " ]"
>  Extended information from the statx syscall.
>  .RS 1.0i
>  .PD 0
>  .TP 0.4i
>  .B \-m mask
> -Specify the field mask for the statx call (default STATX_ALL)
> -.TP
> -.B \-O
> -Add only basic stats (STATX_BASIC_STATS) to default mask
> +Specify the field mask for the statx call as an decimal, hex or octal integer
> +or
> +.RI \" basic "\" or \"" all \"
> +to specify the basic stats that
> +.IR stat ()
> +returns or all the stats known by the header file.  All is the default.
>  .TP
>  .B \-F
>  Force the attributes to be sync'd with the server
> @@ -901,12 +906,6 @@ Force the attributes to be sync'd with the server
>  .B \-D
>  Don't sync attributes with the server
>  .TP
> -.B \-L
> -Follow symlinks (statx link target)
> -.TP
> -.B \-A
> -Suppress terminal automount traversal
> -.TP
>  .RE
>  .IP
>  .TP
> --
> To unsubscribe from this list: send the line "unsubscribe linux-xfs" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 
--
To unsubscribe from this list: send the line "unsubscribe linux-xfs" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/io/stat.c b/io/stat.c
index a7aebcd..d2ea854 100644
--- a/io/stat.c
+++ b/io/stat.c
@@ -44,6 +44,35 @@  filesize(void)
 	return st.st_size;
 }
 
+static int
+dump_raw_stat(struct stat *st)
+{
+	if (fstat(file->fd, st) < 0) {
+		perror("fstat");
+		return -1;
+	}
+
+	printf("stat.blksize: %lu\n", st->st_blksize);
+	printf("stat.nlink: %lu\n", st->st_nlink);
+	printf("stat.uid: %u\n", st->st_uid);
+	printf("stat.gid: %u\n", st->st_gid);
+	printf("stat.mode: 0%o\n", st->st_mode);
+	printf("stat.ino: %lu\n", st->st_ino);
+	printf("stat.size: %lu\n", st->st_size);
+	printf("stat.blocks: %lu\n", st->st_blocks);
+	printf("stat.atime.tv_sec: %ld\n", st->st_atim.tv_sec);
+	printf("stat.atime.tv_nsec: %ld\n", st->st_atim.tv_nsec);
+	printf("stat.ctime.tv_sec: %ld\n", st->st_ctim.tv_sec);
+	printf("stat.ctime.tv_nsec: %ld\n", st->st_ctim.tv_nsec);
+	printf("stat.mtime.tv_sec: %ld\n", st->st_mtim.tv_sec);
+	printf("stat.mtime.tv_nsec: %ld\n", st->st_mtim.tv_nsec);
+	printf("stat.rdev_major: %u\n", major(st->st_rdev));
+	printf("stat.rdev_minor: %u\n", minor(st->st_rdev));
+	printf("stat.dev_major: %u\n", major(st->st_dev));
+	printf("stat.dev_minor: %u\n", minor(st->st_dev));
+	return 0;
+}
+
 static char *
 filetype(mode_t mode)
 {
@@ -74,7 +103,23 @@  stat_f(
 	struct dioattr	dio;
 	struct fsxattr	fsx, fsxa;
 	struct stat	st;
-	int		verbose = (argc == 2 && !strcmp(argv[1], "-v"));
+	int		c, verbose = 0, raw = 0;
+
+	while ((c = getopt(argc, argv, "rv")) != EOF) {
+		switch (c) {
+		case 'r':
+			raw = 1;
+			break;
+		case 'v':
+			verbose = 1;
+			break;
+		default:
+			return command_usage(&stat_cmd);
+		}
+	}
+
+	if (raw)
+		return dump_raw_stat(&st);
 
 	printf(_("fd.path = \"%s\"\n"), file->name);
 	printf(_("fd.flags = %s,%s,%s%s%s%s%s\n"),
@@ -189,12 +234,9 @@  statx_help(void)
 " Display extended file status.\n"
 "\n"
 " Options:\n"
-" -m mask -- Specify the field mask for the statx call (default STATX_ALL)\n"
-" -A -- Suppress terminal automount traversal\n"
+" -m mask -- Specify the field mask for the statx call (can also be 'basic' or 'all'; default STATX_ALL)\n"
 " -D -- Don't sync attributes with the server\n"
 " -F -- Force the attributes to be sync'd with the server\n"
-" -L -- Follow symlinks (statx link target)\n"
-" -O -- Add only basic stats (STATX_BASIC_STATS) to default mask\n"
 "\n"));
 }
 
@@ -202,28 +244,28 @@  statx_help(void)
 static void
 dump_statx(struct statx *stx)
 {
-	printf("stx_mask: 0x%x\n", stx->stx_mask);
-	printf("stx_blksize: %u\n", stx->stx_blksize);
-	printf("stx_attributes: 0x%llx\n", stx->stx_attributes);
-	printf("stx_nlink: %u\n", stx->stx_nlink);
-	printf("stx_uid: %u\n", stx->stx_uid);
-	printf("stx_gid: %u\n", stx->stx_gid);
-	printf("stx_mode: 0%o\n", stx->stx_mode);
-	printf("stx_ino: %llu\n", stx->stx_ino);
-	printf("stx_size: %llu\n", stx->stx_size);
-	printf("stx_blocks: %llu\n", stx->stx_blocks);
-	printf("stx_atime.tv_sec: %lld\n", stx->stx_atime.tv_sec);
-	printf("stx_atime.tv_nsec: %d\n", stx->stx_atime.tv_nsec);
-	printf("stx_btime.tv_sec: %lld\n", stx->stx_btime.tv_sec);
-	printf("stx_btime.tv_nsec: %d\n", stx->stx_btime.tv_nsec);
-	printf("stx_ctime.tv_sec: %lld\n", stx->stx_ctime.tv_sec);
-	printf("stx_ctime.tv_nsec: %d\n", stx->stx_ctime.tv_nsec);
-	printf("stx_mtime.tv_sec: %lld\n", stx->stx_mtime.tv_sec);
-	printf("stx_mtime.tv_nsec: %d\n", stx->stx_mtime.tv_nsec);
-	printf("stx_rdev_major: %u\n", stx->stx_rdev_major);
-	printf("stx_rdev_minor: %u\n", stx->stx_rdev_minor);
-	printf("stx_dev_major: %u\n", stx->stx_dev_major);
-	printf("stx_dev_minor: %u\n", stx->stx_dev_minor);
+	printf("stat.mask: 0x%x\n", stx->stx_mask);
+	printf("stat.blksize: %u\n", stx->stx_blksize);
+	printf("stat.attributes: 0x%llx\n", stx->stx_attributes);
+	printf("stat.nlink: %u\n", stx->stx_nlink);
+	printf("stat.uid: %u\n", stx->stx_uid);
+	printf("stat.gid: %u\n", stx->stx_gid);
+	printf("stat.mode: 0%o\n", stx->stx_mode);
+	printf("stat.ino: %llu\n", stx->stx_ino);
+	printf("stat.size: %llu\n", stx->stx_size);
+	printf("stat.blocks: %llu\n", stx->stx_blocks);
+	printf("stat.atime.tv_sec: %lld\n", stx->stx_atime.tv_sec);
+	printf("stat.atime.tv_nsec: %d\n", stx->stx_atime.tv_nsec);
+	printf("stat.btime.tv_sec: %lld\n", stx->stx_btime.tv_sec);
+	printf("stat.btime.tv_nsec: %d\n", stx->stx_btime.tv_nsec);
+	printf("stat.ctime.tv_sec: %lld\n", stx->stx_ctime.tv_sec);
+	printf("stat.ctime.tv_nsec: %d\n", stx->stx_ctime.tv_nsec);
+	printf("stat.mtime.tv_sec: %lld\n", stx->stx_mtime.tv_sec);
+	printf("stat.mtime.tv_nsec: %d\n", stx->stx_mtime.tv_nsec);
+	printf("stat.rdev_major: %u\n", stx->stx_rdev_major);
+	printf("stat.rdev_minor: %u\n", stx->stx_rdev_minor);
+	printf("stat.dev_major: %u\n", stx->stx_dev_major);
+	printf("stat.dev_minor: %u\n", stx->stx_dev_minor);
 }
 
 /*
@@ -239,16 +281,18 @@  statx_f(
 {
 	int		c;
 	struct statx	stx;
-	int		atflag = AT_SYMLINK_NOFOLLOW;
-	unsigned int	m_mask = 0;	/* mask requested with -m */
-	int		Oflag = 0, mflag = 0;	/* -O or -m was used */
+	int		atflag = 0;
 	unsigned int	mask = STATX_ALL;
 
-	while ((c = getopt(argc, argv, "m:FDLOA")) != EOF) {
+	while ((c = getopt(argc, argv, "m:FD")) != EOF) {
 		switch (c) {
 		case 'm':
-			m_mask = atoi(optarg);
-			mflag = 1;
+			if (strcmp(optarg, "basic") == 0)
+				mask = STATX_BASIC_STATS;
+			else if (strcmp(optarg, "all") == 0)
+				mask = STATX_ALL;
+			else
+				mask = strtoul(optarg, NULL, 0);
 			break;
 		case 'F':
 			atflag &= ~AT_STATX_SYNC_TYPE;
@@ -258,38 +302,19 @@  statx_f(
 			atflag &= ~AT_STATX_SYNC_TYPE;
 			atflag |= AT_STATX_DONT_SYNC;
 			break;
-		case 'L':
-			atflag &= ~AT_SYMLINK_NOFOLLOW;
-			break;
-		case 'O':
-			mask = STATX_BASIC_STATS;
-			Oflag = 1;
-			break;
-		case 'A':
-			atflag |= AT_NO_AUTOMOUNT;
-			break;
 		default:
 			return command_usage(&statx_cmd);
 		}
 	}
 
-	if (Oflag && mflag) {
-		printf("Cannot specify both -m mask and -O\n");
-		return 0;
-	}
-
-	/* -m overrides any other mask options */
-	if (mflag)
-		mask = m_mask;
-
 	memset(&stx, 0xbf, sizeof(stx));
-	if (statx(AT_FDCWD, file->name, atflag, mask, &stx) < 0) {
+
+	if (statx(file->fd, NULL, atflag, mask, &stx) < 0) {
 		perror("statx");
 		return 0;
 	}
-
+	
 	dump_statx(&stx);
-
 	return 0;
 }
 
@@ -301,7 +326,7 @@  stat_init(void)
 	stat_cmd.argmin = 0;
 	stat_cmd.argmax = 1;
 	stat_cmd.flags = CMD_NOMAP_OK | CMD_FOREIGN_OK;
-	stat_cmd.args = _("[-v]");
+	stat_cmd.args = _("[-rv]");
 	stat_cmd.oneline = _("information about the currently open file");
 
 	statfs_cmd.name = "statfs";
@@ -315,7 +340,7 @@  stat_init(void)
 	statx_cmd.argmin = 0;
 	statx_cmd.argmax = -1;
 	statx_cmd.flags = CMD_NOMAP_OK | CMD_FOREIGN_OK;
-	statx_cmd.args = _("[-O | -m mask][-FDLAP]");
+	statx_cmd.args = _("[-m basic | -m all | -m <mask>][-FD]");
 	statx_cmd.oneline =
  _("extended information about the currently open file");
 	statx_cmd.help = statx_help;
diff --git a/man/man8/xfs_io.8 b/man/man8/xfs_io.8
index 77ba760..486ad11 100644
--- a/man/man8/xfs_io.8
+++ b/man/man8/xfs_io.8
@@ -876,24 +876,29 @@  Only available in expert mode and requires privileges.
 Force the filesystem to shutdown (with or without flushing the log).
 Only available in expert mode and requires privileges.
 .TP
-.BR stat " [ " \-v " ]"
+.BR stat " [ \-" rv " ]"
 Selected statistics from
 .BR stat (2)
 and the XFS_IOC_GETXATTR system call on the current file. If the
 .B \-v
 option is specified, the atime (last access), mtime
-(last modify), and ctime (last change) timestamps are also displayed.
+(last modify), and ctime (last change) timestamps are also displayed. If the
+.B \-r
+option is specified, the raw output will be dumped in the same form as the
+output for the statx command, but with some fields missing.
 .TP
-.BR statx " [ " \-O " | " "\-m mask" " ][ \-" FDLA " ]"
+.BR statx " [ " "\-m mask" " ][ \-" FD " ]"
 Extended information from the statx syscall.
 .RS 1.0i
 .PD 0
 .TP 0.4i
 .B \-m mask
-Specify the field mask for the statx call (default STATX_ALL)
-.TP
-.B \-O
-Add only basic stats (STATX_BASIC_STATS) to default mask
+Specify the field mask for the statx call as an decimal, hex or octal integer
+or
+.RI \" basic "\" or \"" all \"
+to specify the basic stats that
+.IR stat ()
+returns or all the stats known by the header file.  All is the default.
 .TP
 .B \-F
 Force the attributes to be sync'd with the server
@@ -901,12 +906,6 @@  Force the attributes to be sync'd with the server
 .B \-D
 Don't sync attributes with the server
 .TP
-.B \-L
-Follow symlinks (statx link target)
-.TP
-.B \-A
-Suppress terminal automount traversal
-.TP
 .RE
 .IP
 .TP