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