generic/223: port t_stripealign to FIEMAP
authorDarrick J. Wong <darrick.wong@oracle.com>
Wed, 13 Jun 2018 22:50:57 +0000 (15:50 -0700)
committerEryu Guan <guaneryu@gmail.com>
Fri, 15 Jun 2018 03:00:54 +0000 (11:00 +0800)
Since XFS has deprecated FIBMAP on FSDAX filesystems, we can't use
FIBMAP to verify stripe alignment anymore.  FIEMAP has existed for
quite some time now, so port it to use that instead, and only fall
back to FIBMAP if FIEMAP doesn't exist.

Tested-by: ross.zwisler@linux.intel.com
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Signed-off-by: Eryu Guan <guaneryu@gmail.com>
src/Makefile
src/t_stripealign.c

index 01fe99efbdad3503dc37bdced5d312d5cdc4397e..b06b7e252fd4f9be98e8477c4ad7671dc250c7c9 100644 (file)
@@ -19,7 +19,7 @@ TARGETS = dirstress fill fill2 getpagesize holes lstat64 \
 
 LINUX_TARGETS = xfsctl bstat t_mtab getdevicesize preallo_rw_pattern_reader \
        preallo_rw_pattern_writer ftrunc trunc fs_perms testx looptest \
-       locktest unwritten_mmap bulkstat_unlink_test t_stripealign \
+       locktest unwritten_mmap bulkstat_unlink_test \
        bulkstat_unlink_test_modified t_dir_offset t_futimens t_immutable \
        stale_handle pwrite_mmap_blocked t_dir_offset2 seek_sanity_test \
        seek_copy_test t_readdir_1 t_readdir_2 fsync-tester nsexec cloner \
@@ -37,7 +37,7 @@ LINUX_TARGETS += loggen
 endif
 
 ifeq ($(HAVE_FIEMAP), true)
-LINUX_TARGETS += fiemap-tester
+LINUX_TARGETS += fiemap-tester t_stripealign
 endif
 
 ifeq ($(HAVE_OPEN_BY_HANDLE_AT), true)
index 05ed36b5ba366113ec6049dfe226835e9ff5c9be..690f743ae9edc28192d40d0e411a058c1025d5e5 100644 (file)
 #include <fcntl.h>
 #include <stdio.h>
 #include <sys/ioctl.h>
+#include <linux/fiemap.h>
+#include <linux/fs.h>
 
-#define FIBMAP          _IO(0x00, 1)    /* bmap access */
+#define FIEMAP_EXTENT_ACCEPTABLE       (FIEMAP_EXTENT_LAST | \
+               FIEMAP_EXTENT_DATA_ENCRYPTED | FIEMAP_EXTENT_ENCODED | \
+               FIEMAP_EXTENT_UNWRITTEN | FIEMAP_EXTENT_MERGED | \
+               FIEMAP_EXTENT_SHARED)
 
 /*
  * If only filename given, print first block.
 
 int main(int argc, char ** argv)
 {
-       int     fd;
-       int     ret;
-       int     sunit = 0;      /* in blocks */
-       char    *filename;
-       unsigned int    block = 0;
+       struct stat             sb;
+       struct fiemap           *fie;
+       struct fiemap_extent    *fe;
+       int                     fd;
+       int                     ret;
+       int                     sunit = 0;      /* in blocks */
+       char                    *filename;
+       unsigned long long      block;
 
         if (argc < 3) {
                 printf("Usage: %s <filename> <sunit in blocks>\n", argv[0]);
@@ -48,21 +56,63 @@ int main(int argc, char ** argv)
                 return 1;
         }
 
-       ret = ioctl(fd, FIBMAP, &block);
-       if (ret < 0) {
+       ret = fstat(fd, &sb);
+       if (ret) {
+               perror(filename);
                close(fd);
-               perror("fibmap");
                return 1;
        }
 
-       close(fd);
+       fie = calloc(1, sizeof(struct fiemap) + sizeof(struct fiemap_extent));
+       if (!fie) {
+               close(fd);
+               perror("malloc");
+               return 1;
+       }
+       fie->fm_length = 1;
+       fie->fm_flags = FIEMAP_FLAG_SYNC;
+       fie->fm_extent_count = 1;
+
+       ret = ioctl(fd, FS_IOC_FIEMAP, fie);
+       if (ret < 0) {
+               unsigned int    bmap = 0;
+
+               ret = ioctl(fd, FIBMAP, &bmap);
+               if (ret < 0) {
+                       perror("fibmap");
+                       free(fie);
+                       close(fd);
+                       return 1;
+               }
+               block = bmap;
+               goto check;
+       }
 
+
+       if (fie->fm_mapped_extents != 1) {
+               printf("%s: no extents?\n", filename);
+               free(fie);
+               close(fd);
+               return 1;
+       }
+       fe = &fie->fm_extents[0];
+       if (fe->fe_flags & ~FIEMAP_EXTENT_ACCEPTABLE) {
+               printf("%s: bad flags 0x%x\n", filename, fe->fe_flags);
+               free(fie);
+               close(fd);
+               return 1;
+       }
+
+       block = fie->fm_extents[0].fe_physical / sb.st_blksize;
+check:
        if (block % sunit) {
-               printf("%s: Start block %u not multiple of sunit %u\n",
+               printf("%s: Start block %llu not multiple of sunit %u\n",
                        filename, block, sunit);
                return 1;
        } else
                printf("%s: well-aligned\n", filename);
+       free(fie);
+       close(fd);
 
        return 0;
 }