1 /*
2 * Copyright (C) 2014 Cyril Hrubis chrubis@suse.cz
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of version 2 of the GNU General Public License as
6 * published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it would be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11 *
12 * Further, this software is distributed without any warranty that it is
13 * free of the rightful claim of any third person regarding infringement
14 * or the like. Any license provided herein, whether implied or
15 * otherwise, applies only to this software file. Patent licenses, if
16 * any, provided herein do not apply to combinations of this program with
17 * other software, or any other product whatsoever.
18 *
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, write the Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22 */
23
24 #include <sys/types.h>
25 #include <sys/stat.h>
26 #include <sys/ioctl.h>
27 #include <sys/mount.h>
28 #include <errno.h>
29 #include <unistd.h>
30 #include <stdlib.h>
31 #include <linux/loop.h>
32 #include <stdint.h>
33 #include <inttypes.h>
34 #include "test.h"
35 #include "safe_macros.h"
36
37 #ifndef LOOP_CTL_GET_FREE
38 # define LOOP_CTL_GET_FREE 0x4C82
39 #endif
40
41 #define LOOP_CONTROL_FILE "/dev/loop-control"
42
43 #define DEV_FILE "test_dev.img"
44 #define DEV_SIZE_MB 256u
45
46 static char dev_path[1024];
47 static int device_acquired;
48
49 static const char *dev_variants[] = {
50 "/dev/loop%i",
51 "/dev/loop/%i",
52 "/dev/block/loop%i"
53 };
54
set_dev_path(int dev)55 static int set_dev_path(int dev)
56 {
57 unsigned int i;
58 struct stat st;
59
60 for (i = 0; i < ARRAY_SIZE(dev_variants); i++) {
61 snprintf(dev_path, sizeof(dev_path), dev_variants[i], dev);
62
63 if (stat(dev_path, &st) == 0 && S_ISBLK(st.st_mode))
64 return 1;
65 }
66
67 return 0;
68 }
69
find_free_loopdev(void)70 static int find_free_loopdev(void)
71 {
72 int ctl_fd, dev_fd, rc, i;
73 struct loop_info loopinfo;
74
75 /* since Linux 3.1 */
76 ctl_fd = open(LOOP_CONTROL_FILE, O_RDWR);
77
78 if (ctl_fd > 0) {
79 rc = ioctl(ctl_fd, LOOP_CTL_GET_FREE);
80 close(ctl_fd);
81 if (rc >= 0) {
82 set_dev_path(rc);
83 tst_resm(TINFO, "Found free device '%s'", dev_path);
84 return 0;
85 }
86 tst_resm(TINFO, "Couldn't find free loop device");
87 return 1;
88 }
89
90 switch (errno) {
91 case ENOENT:
92 break;
93 case EACCES:
94 tst_resm(TINFO | TERRNO,
95 "Not allowed to open " LOOP_CONTROL_FILE ". "
96 "Are you root?");
97 break;
98 default:
99 tst_resm(TBROK | TERRNO, "Failed to open " LOOP_CONTROL_FILE);
100 }
101
102 /*
103 * Older way is to iterate over /dev/loop%i and /dev/loop/%i and try
104 * LOOP_GET_STATUS ioctl() which fails for free loop devices.
105 */
106 for (i = 0; i < 256; i++) {
107
108 if (!set_dev_path(i))
109 continue;
110
111 dev_fd = open(dev_path, O_RDONLY);
112
113 if (dev_fd < 0)
114 continue;
115
116 if (ioctl(dev_fd, LOOP_GET_STATUS, &loopinfo) == 0) {
117 tst_resm(TINFO, "Device '%s' in use", dev_path);
118 } else {
119 if (errno != ENXIO)
120 continue;
121 tst_resm(TINFO, "Found free device '%s'", dev_path);
122 close(dev_fd);
123 return 0;
124 }
125
126 close(dev_fd);
127 }
128
129 tst_resm(TINFO, "No free devices found");
130
131 return 1;
132 }
133
attach_device(const char * dev,const char * file)134 static int attach_device(const char *dev, const char *file)
135 {
136 int dev_fd, file_fd;
137 struct loop_info loopinfo;
138
139 dev_fd = open(dev, O_RDWR);
140 if (dev_fd < 0) {
141 tst_resm(TWARN | TERRNO, "open('%s', O_RDWR) failed", dev);
142 return 1;
143 }
144
145 file_fd = open(file, O_RDWR);
146 if (file_fd < 0) {
147 tst_resm(TWARN | TERRNO, "open('%s', O_RDWR) failed", file);
148 close(dev_fd);
149 return 1;
150 }
151
152 if (ioctl(dev_fd, LOOP_SET_FD, file_fd) < 0) {
153 close(dev_fd);
154 close(file_fd);
155 tst_resm(TWARN | TERRNO, "ioctl(%s, LOOP_SET_FD, %s) failed",
156 dev, file);
157 return 1;
158 }
159
160 /* Old mkfs.btrfs use LOOP_GET_STATUS instead of backing_file to get
161 * associated filename, so we need to set up the device by calling
162 * LOOP_SET_FD and LOOP_SET_STATUS.
163 */
164 memset(&loopinfo, 0, sizeof(loopinfo));
165 strcpy(loopinfo.lo_name, file);
166
167 if (ioctl(dev_fd, LOOP_SET_STATUS, &loopinfo)) {
168 close(dev_fd);
169 close(file_fd);
170 tst_resm(TWARN | TERRNO,
171 "ioctl(%s, LOOP_SET_STATUS, %s) failed", dev, file);
172 return 1;
173 }
174
175 close(dev_fd);
176 close(file_fd);
177 return 0;
178 }
179
detach_device(const char * dev)180 static int detach_device(const char *dev)
181 {
182 int dev_fd, ret, i;
183
184 dev_fd = open(dev, O_RDONLY);
185 if (dev_fd < 0) {
186 tst_resm(TWARN | TERRNO, "open(%s) failed", dev);
187 return 1;
188 }
189
190 /* keep trying to clear LOOPDEV until we get ENXIO, a quick succession
191 * of attach/detach might not give udev enough time to complete */
192 for (i = 0; i < 40; i++) {
193 ret = ioctl(dev_fd, LOOP_CLR_FD, 0);
194
195 if (ret && (errno == ENXIO)) {
196 close(dev_fd);
197 return 0;
198 }
199
200 if (ret && (errno != EBUSY)) {
201 tst_resm(TWARN,
202 "ioctl(%s, LOOP_CLR_FD, 0) unexpectedly failed with: %s",
203 dev, tst_strerrno(errno));
204 close(dev_fd);
205 return 1;
206 }
207
208 usleep(50000);
209 }
210
211 close(dev_fd);
212 tst_resm(TWARN,
213 "ioctl(%s, LOOP_CLR_FD, 0) no ENXIO for too long", dev);
214 return 1;
215 }
216
tst_acquire_device__(unsigned int size)217 const char *tst_acquire_device__(unsigned int size)
218 {
219 int fd;
220 char *dev;
221 struct stat st;
222 unsigned int acq_dev_size;
223 uint64_t ltp_dev_size;
224
225 acq_dev_size = MAX(size, DEV_SIZE_MB);
226
227 dev = getenv("LTP_DEV");
228
229 if (dev) {
230 tst_resm(TINFO, "Using test device LTP_DEV='%s'", dev);
231
232 if (stat(dev, &st)) {
233 tst_resm(TWARN | TERRNO, "stat() failed");
234 return NULL;
235 }
236
237 if (!S_ISBLK(st.st_mode)) {
238 tst_resm(TWARN, "%s is not a block device", dev);
239 return NULL;
240 }
241
242 fd = open(dev, O_RDONLY);
243 if (fd < 0) {
244 tst_resm(TWARN | TERRNO,
245 "open(%s, O_RDONLY) failed", dev);
246 return NULL;
247 }
248
249 if (ioctl(fd, BLKGETSIZE64, <p_dev_size)) {
250 tst_resm(TWARN | TERRNO,
251 "ioctl(fd, BLKGETSIZE64, ...) failed");
252 close(fd);
253 return NULL;
254 }
255
256 if (close(fd)) {
257 tst_resm(TWARN | TERRNO,
258 "close(fd) failed");
259 return NULL;
260 }
261
262 ltp_dev_size = ltp_dev_size/1024/1024;
263
264 if (acq_dev_size <= ltp_dev_size)
265 return dev;
266
267 tst_resm(TINFO, "Skipping $LTP_DEV size %"PRIu64"MB, requested size %uMB",
268 ltp_dev_size, acq_dev_size);
269 }
270
271 if (tst_fill_file(DEV_FILE, 0, 1024, 1024 * acq_dev_size)) {
272 tst_resm(TWARN | TERRNO, "Failed to create " DEV_FILE);
273 return NULL;
274 }
275
276 if (find_free_loopdev())
277 return NULL;
278
279 if (attach_device(dev_path, DEV_FILE))
280 return NULL;
281
282 device_acquired = 1;
283
284 return dev_path;
285 }
286
tst_acquire_device_(void (cleanup_fn)(void),unsigned int size)287 const char *tst_acquire_device_(void (cleanup_fn)(void), unsigned int size)
288 {
289 const char *device;
290
291 if (device_acquired) {
292 tst_brkm(TBROK, cleanup_fn, "Device already acquired");
293 return NULL;
294 }
295
296 if (!tst_tmpdir_created()) {
297 tst_brkm(TBROK, cleanup_fn,
298 "Cannot acquire device without tmpdir() created");
299 return NULL;
300 }
301
302 device = tst_acquire_device__(size);
303
304 if (!device) {
305 tst_brkm(TBROK, cleanup_fn, "Failed to acquire device");
306 return NULL;
307 }
308
309 return device;
310 }
311
tst_release_device(const char * dev)312 int tst_release_device(const char *dev)
313 {
314 int ret;
315
316 if (getenv("LTP_DEV"))
317 return 0;
318
319 /*
320 * Loop device was created -> we need to detach it.
321 *
322 * The file image is deleted in tst_rmdir();
323 */
324 ret = detach_device(dev);
325
326 device_acquired = 0;
327
328 return ret;
329 }
330
tst_clear_device(const char * dev)331 int tst_clear_device(const char *dev)
332 {
333 if (tst_fill_file(dev, 0, 1024, 512)) {
334 tst_resm(TWARN, "Failed to clear 512k block on %s", dev);
335 return 1;
336 }
337
338 return 0;
339 }
340
tst_umount(const char * path)341 int tst_umount(const char *path)
342 {
343 int err, ret, i;
344
345 for (i = 0; i < 50; i++) {
346 ret = umount(path);
347 err = errno;
348
349 if (!ret)
350 return 0;
351
352 tst_resm(TINFO, "umount('%s') failed with %s, try %2i...",
353 path, tst_strerrno(err), i+1);
354
355 if (i == 0 && err == EBUSY) {
356 tst_resm(TINFO, "Likely gvfsd-trash is probing newly "
357 "mounted fs, kill it to speed up tests.");
358 }
359
360 usleep(100000);
361 }
362
363 tst_resm(TWARN, "Failed to umount('%s') after 50 retries", path);
364 errno = err;
365 return -1;
366 }
367