Whamcloud - gitweb
LU-4018 tests: improve racer file_create workload
[fs/lustre-release.git] / lustre / tests / checkfiemap.c
1 /* GPL HEADER START
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 only,
7  * as published by the Free Software Foundation.
8  *
9  * This program is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * General Public License version 2 for more details (a copy is included
13  * in the LICENSE file that accompanied this code).
14  *
15  * You should have received a copy of the GNU General Public License
16  * version 2 along with this program; If not, see http://www.gnu.org/licenses
17  *
18  * Please  visit http://www.xyratex.com/contact if you need additional
19  * information or have any questions.
20  *
21  * GPL HEADER END
22  */
23
24 /*
25  * Copyright 2013 Xyratex Technology Limited
26  *
27  * Author: Artem Blagodarenko <Artem_Blagodarenko@xyratex.com>
28  *
29  */
30
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <string.h>
34 #include <sys/ioctl.h>
35 #include <sys/types.h>
36 #include <sys/stat.h>
37 #include <fcntl.h>
38 #include <errno.h>
39 #include <unistd.h>
40 #include <getopt.h>
41
42 #ifndef HAVE_FIEMAP
43 # include <linux/types.h>
44 # include <linux/fiemap.h>
45 #endif
46
47 #ifdef __linux__
48 # ifndef FS_IOC_FIEMAP
49 #  define FS_IOC_FIEMAP (_IOWR('f', 11, struct fiemap))
50 # endif
51 #endif
52
53 #define ONEMB 1048576
54
55 /* This test executes fiemap ioctl and check
56  * a) there are no file ranges marked with FIEMAP_EXTENT_UNWRITTEN
57  * b) data ranges sizes sum is equal to given in second param */
58 int check_fiemap(int fd, long long orig_size)
59 {
60         /* This buffer is enougth for 1MB length file */
61         union { struct fiemap f; char c[4096]; } fiemap_buf;
62         struct fiemap *fiemap = &fiemap_buf.f;
63         struct fiemap_extent *fm_extents = &fiemap->fm_extents[0];
64         unsigned int count = (sizeof(fiemap_buf) - sizeof(*fiemap)) /
65                         sizeof(*fm_extents);
66         unsigned int i = 0;
67         long long file_size = 0;
68
69         memset(&fiemap_buf, 0, sizeof(fiemap_buf));
70
71         fiemap->fm_start = 0;
72         fiemap->fm_flags = FIEMAP_FLAG_SYNC;
73         fiemap->fm_extent_count = count;
74         fiemap->fm_length = FIEMAP_MAX_OFFSET;
75
76         if (ioctl(fd, FS_IOC_FIEMAP, fiemap) < 0) {
77                 fprintf(stderr, "error while ioctl %i\n",  errno);
78                 return -1;
79         }
80
81         for (i = 0; i < fiemap->fm_mapped_extents; i++) {
82                 printf("extent in "
83                         "offset %lu, length %lu\n"
84                         "flags: %x\n",
85                         (unsigned long)fm_extents[i].fe_logical,
86                         (unsigned long)fm_extents[i].fe_length,
87                         fm_extents[i].fe_flags);
88
89                 if (fm_extents[i].fe_flags & FIEMAP_EXTENT_UNWRITTEN) {
90                         fprintf(stderr, "Unwritten extent\n");
91                         return -2;
92                 } else {
93                         file_size += fm_extents[i].fe_length;
94                 }
95         }
96
97         printf("No unwritten extents, extents number %u, "
98                 "file size %lli, original size %lli\n",
99                 fiemap->fm_mapped_extents,
100                 file_size, orig_size);
101         return file_size != orig_size;
102 }
103
104 int main(int argc, char **argv)
105 {
106         int c;
107         struct option long_opts[] = {
108                 {"test", no_argument, 0, 't'},
109                 {NULL, 0, NULL, 0}
110         };
111         int fd;
112         int rc;
113
114         optind = 0;
115         while ((c = getopt_long(argc, argv, "t", long_opts, NULL)) != -1) {
116                 switch (c) {
117                 case 't':
118                         return 0;
119                 default:
120                         fprintf(stderr, "error: %s: option '%s' unrecognized\n",
121                                 argv[0], argv[optind - 1]);
122                 return -1;
123                 }
124         }
125
126         if (optind != argc - 2) {
127                 fprintf(stderr, "Usage: %s <filename> <filesize>\n", argv[0]);
128                 return -1;
129         }
130
131         fd = open(argv[optind], O_RDONLY);
132         if (fd < 0) {
133                 fprintf(stderr, "cannot open %s for reading, error %i",
134                         argv[optind], errno);
135                 return -1;
136         }
137
138         fprintf(stderr, "fd: %i\n", fd);
139
140         rc = check_fiemap(fd, atoll(argv[optind + 1]));
141
142         if (close(fd) < 0)
143                 fprintf(stderr, "closing %s, error %i", argv[optind], errno);
144
145         return rc;
146 }