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