Whamcloud - gitweb
074f1453bab800dfbdc222c1702dea1c1f452571
[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/fiemap.h>
44 #endif
45
46 #ifdef __linux__
47 # ifndef FS_IOC_FIEMAP
48 #  define FS_IOC_FIEMAP (_IOWR('f', 11, struct fiemap))
49 # endif
50 #endif
51
52 #define ONEMB 1048576
53
54 /* This test executes fiemap ioctl and check
55  * a) there are no file ranges marked with FIEMAP_EXTENT_UNWRITTEN
56  * b) data ranges sizes sum is equal to given in second param */
57 int check_fiemap(int fd, long long orig_size)
58 {
59         /* This buffer is enougth for 1MB length file */
60         union { struct fiemap f; char c[4096]; } fiemap_buf;
61         struct fiemap *fiemap = &fiemap_buf.f;
62         struct fiemap_extent *fm_extents = &fiemap->fm_extents[0];
63         unsigned int count = (sizeof(fiemap_buf) - sizeof(*fiemap)) /
64                         sizeof(*fm_extents);
65         unsigned int i = 0;
66         long long file_size = 0;
67
68         memset(&fiemap_buf, 0, sizeof(fiemap_buf));
69
70         fiemap->fm_start = 0;
71         fiemap->fm_flags = FIEMAP_FLAG_SYNC;
72         fiemap->fm_extent_count = count;
73         fiemap->fm_length = FIEMAP_MAX_OFFSET;
74
75         if (ioctl(fd, FS_IOC_FIEMAP, fiemap) < 0) {
76                 fprintf(stderr, "error while ioctl %i\n",  errno);
77                 return -1;
78         }
79
80         for (i = 0; i < fiemap->fm_mapped_extents; i++) {
81                 printf("extent in "
82                         "offset %lu, length %lu\n"
83                         "flags: %x\n",
84                         (unsigned long)fm_extents[i].fe_logical,
85                         (unsigned long)fm_extents[i].fe_length,
86                         fm_extents[i].fe_flags);
87
88                 if (fm_extents[i].fe_flags & FIEMAP_EXTENT_UNWRITTEN) {
89                         fprintf(stderr, "Unwritten extent\n");
90                         return -2;
91                 } else {
92                         file_size += fm_extents[i].fe_length;
93                 }
94         }
95
96         printf("No unwritten extents, extents number %u, "
97                 "file size %lli, original size %lli\n",
98                 fiemap->fm_mapped_extents,
99                 file_size, orig_size);
100         return file_size != orig_size;
101 }
102
103 int main(int argc, char **argv)
104 {
105         int c;
106         struct option long_opts[] = {
107                 {"test", no_argument, 0, 't'},
108                 {NULL, 0, NULL, 0}
109         };
110         int fd;
111         int rc;
112
113         optind = 0;
114         while ((c = getopt_long(argc, argv, "t", long_opts, NULL)) != -1) {
115                 switch (c) {
116                 case 't':
117                         return 0;
118                 default:
119                         fprintf(stderr, "error: %s: option '%s' unrecognized\n",
120                                 argv[0], argv[optind - 1]);
121                 return -1;
122                 }
123         }
124
125         if (optind != argc - 2) {
126                 fprintf(stderr, "Usage: %s <filename> <filesize>\n", argv[0]);
127                 return -1;
128         }
129
130         fd = open(argv[optind], O_RDONLY);
131         if (fd < 0) {
132                 fprintf(stderr, "cannot open %s for reading, error %i",
133                         argv[optind], errno);
134                 return -1;
135         }
136
137         fprintf(stderr, "fd: %i\n", fd);
138
139         rc = check_fiemap(fd, atoll(argv[optind + 1]));
140
141         if (close(fd) < 0)
142                 fprintf(stderr, "closing %s, error %i", argv[optind], errno);
143
144         return rc;
145 }