649aa285d658d08dc0059b49686c829e0f377c9e
[xfstests-dev.git] / src / t_stripealign.c
1 /*
2  * t_stripealign.c
3  *
4  * Print whether the file start block is stripe-aligned.
5  *
6  * Copyright (c) 2010 Eric Sandeen <sandeen@sandeen.net>
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2, or (at your option)
11  * any later version.
12  */
13 #include <unistd.h>
14 #include <stdlib.h>
15 #include <sys/types.h>
16 #include <sys/stat.h>
17 #include <fcntl.h>
18 #include <stdio.h>
19 #include <sys/ioctl.h>
20 #include <linux/fiemap.h>
21 #include <linux/fs.h>
22
23 #ifndef FIEMAP_EXTENT_SHARED
24 # define FIEMAP_EXTENT_SHARED   0x00002000
25 #endif
26
27 #define FIEMAP_EXTENT_ACCEPTABLE        (FIEMAP_EXTENT_LAST | \
28                 FIEMAP_EXTENT_DATA_ENCRYPTED | FIEMAP_EXTENT_ENCODED | \
29                 FIEMAP_EXTENT_UNWRITTEN | FIEMAP_EXTENT_MERGED | \
30                 FIEMAP_EXTENT_SHARED)
31
32 /*
33  * If only filename given, print first block.
34  *
35  * If filename & sunit (in blocks) given, print whether we are well-aligned
36  */
37
38 int main(int argc, char ** argv)
39 {
40         struct stat             sb;
41         struct fiemap           *fie;
42         struct fiemap_extent    *fe;
43         int                     fd;
44         int                     ret;
45         int                     sunit = 0;      /* in blocks */
46         char                    *filename;
47         unsigned long long      block;
48
49         if (argc < 3) {
50                 printf("Usage: %s <filename> <sunit in blocks>\n", argv[0]);
51                 return 1;
52         }
53
54         filename = argv[1];
55         sunit = atoi(argv[2]);
56
57         fd = open(filename, O_RDONLY);
58         if (fd < 0) {
59                 perror("can't open file\n");
60                 return 1;
61         }
62
63         ret = fstat(fd, &sb);
64         if (ret) {
65                 perror(filename);
66                 close(fd);
67                 return 1;
68         }
69
70         fie = calloc(1, sizeof(struct fiemap) + sizeof(struct fiemap_extent));
71         if (!fie) {
72                 close(fd);
73                 perror("malloc");
74                 return 1;
75         }
76         fie->fm_length = 1;
77         fie->fm_flags = FIEMAP_FLAG_SYNC;
78         fie->fm_extent_count = 1;
79
80         ret = ioctl(fd, FS_IOC_FIEMAP, fie);
81         if (ret < 0) {
82                 unsigned int    bmap = 0;
83
84                 ret = ioctl(fd, FIBMAP, &bmap);
85                 if (ret < 0) {
86                         perror("fibmap");
87                         free(fie);
88                         close(fd);
89                         return 1;
90                 }
91                 block = bmap;
92                 goto check;
93         }
94
95
96         if (fie->fm_mapped_extents != 1) {
97                 printf("%s: no extents?\n", filename);
98                 free(fie);
99                 close(fd);
100                 return 1;
101         }
102         fe = &fie->fm_extents[0];
103         if (fe->fe_flags & ~FIEMAP_EXTENT_ACCEPTABLE) {
104                 printf("%s: bad flags 0x%x\n", filename, fe->fe_flags);
105                 free(fie);
106                 close(fd);
107                 return 1;
108         }
109
110         block = fie->fm_extents[0].fe_physical / sb.st_blksize;
111 check:
112         if (block % sunit) {
113                 printf("%s: Start block %llu not multiple of sunit %u\n",
114                         filename, block, sunit);
115                 return 1;
116         } else
117                 printf("%s: well-aligned\n", filename);
118         free(fie);
119         close(fd);
120
121         return 0;
122 }