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 static unsigned long prev_dev_sec_write;
49 
50 static const char *dev_variants[] = {
51 	"/dev/loop%i",
52 	"/dev/loop/%i",
53 	"/dev/block/loop%i"
54 };
55 
set_dev_path(int dev)56 static int set_dev_path(int dev)
57 {
58 	unsigned int i;
59 	struct stat st;
60 
61 	for (i = 0; i < ARRAY_SIZE(dev_variants); i++) {
62 		snprintf(dev_path, sizeof(dev_path), dev_variants[i], dev);
63 
64 		if (stat(dev_path, &st) == 0 && S_ISBLK(st.st_mode))
65 			return 1;
66 	}
67 
68 	return 0;
69 }
70 
find_free_loopdev(void)71 static int find_free_loopdev(void)
72 {
73 	int ctl_fd, dev_fd, rc, i;
74 	struct loop_info loopinfo;
75 
76 	/* since Linux 3.1 */
77 	ctl_fd = open(LOOP_CONTROL_FILE, O_RDWR);
78 
79 	if (ctl_fd > 0) {
80 		rc = ioctl(ctl_fd, LOOP_CTL_GET_FREE);
81 		close(ctl_fd);
82 		if (rc >= 0) {
83 			set_dev_path(rc);
84 			tst_resm(TINFO, "Found free device '%s'", dev_path);
85 			return 0;
86 		}
87 		tst_resm(TINFO, "Couldn't find free loop device");
88 		return 1;
89 	}
90 
91 	switch (errno) {
92 	case ENOENT:
93 	break;
94 	case EACCES:
95 		tst_resm(TINFO | TERRNO,
96 		         "Not allowed to open " LOOP_CONTROL_FILE ". "
97 			 "Are you root?");
98 	break;
99 	default:
100 		tst_resm(TBROK | TERRNO, "Failed to open " LOOP_CONTROL_FILE);
101 	}
102 
103 	/*
104 	 * Older way is to iterate over /dev/loop%i and /dev/loop/%i and try
105 	 * LOOP_GET_STATUS ioctl() which fails for free loop devices.
106 	 */
107 	for (i = 0; i < 256; i++) {
108 
109 		if (!set_dev_path(i))
110 			continue;
111 
112 		dev_fd = open(dev_path, O_RDONLY);
113 
114 		if (dev_fd < 0)
115 			continue;
116 
117 		if (ioctl(dev_fd, LOOP_GET_STATUS, &loopinfo) == 0) {
118 			tst_resm(TINFO, "Device '%s' in use", dev_path);
119 		} else {
120 			if (errno != ENXIO)
121 				continue;
122 			tst_resm(TINFO, "Found free device '%s'", dev_path);
123 			close(dev_fd);
124 			return 0;
125 		}
126 
127 		close(dev_fd);
128 	}
129 
130 	tst_resm(TINFO, "No free devices found");
131 
132 	return 1;
133 }
134 
attach_device(const char * dev,const char * file)135 static int attach_device(const char *dev, const char *file)
136 {
137 	int dev_fd, file_fd;
138 	struct loop_info loopinfo;
139 
140 	dev_fd = open(dev, O_RDWR);
141 	if (dev_fd < 0) {
142 		tst_resm(TWARN | TERRNO, "open('%s', O_RDWR) failed", dev);
143 		return 1;
144 	}
145 
146 	file_fd = open(file, O_RDWR);
147 	if (file_fd < 0) {
148 		tst_resm(TWARN | TERRNO, "open('%s', O_RDWR) failed", file);
149 		close(dev_fd);
150 		return 1;
151 	}
152 
153 	if (ioctl(dev_fd, LOOP_SET_FD, file_fd) < 0) {
154 		close(dev_fd);
155 		close(file_fd);
156 		tst_resm(TWARN | TERRNO, "ioctl(%s, LOOP_SET_FD, %s) failed",
157 			 dev, file);
158 		return 1;
159 	}
160 
161 	/* Old mkfs.btrfs use LOOP_GET_STATUS instead of backing_file to get
162 	 * associated filename, so we need to set up the device by calling
163 	 * LOOP_SET_FD and LOOP_SET_STATUS.
164 	 */
165 	memset(&loopinfo, 0, sizeof(loopinfo));
166 	strcpy(loopinfo.lo_name, file);
167 
168 	if (ioctl(dev_fd, LOOP_SET_STATUS, &loopinfo)) {
169 		close(dev_fd);
170 		close(file_fd);
171 		tst_resm(TWARN | TERRNO,
172 			 "ioctl(%s, LOOP_SET_STATUS, %s) failed", dev, file);
173 		return 1;
174 	}
175 
176 	close(dev_fd);
177 	close(file_fd);
178 	return 0;
179 }
180 
detach_device(const char * dev)181 static int detach_device(const char *dev)
182 {
183 	int dev_fd, ret, i;
184 
185 	dev_fd = open(dev, O_RDONLY);
186 	if (dev_fd < 0) {
187 		tst_resm(TWARN | TERRNO, "open(%s) failed", dev);
188 		return 1;
189 	}
190 
191 	/* keep trying to clear LOOPDEV until we get ENXIO, a quick succession
192 	 * of attach/detach might not give udev enough time to complete */
193 	for (i = 0; i < 40; i++) {
194 		ret = ioctl(dev_fd, LOOP_CLR_FD, 0);
195 
196 		if (ret && (errno == ENXIO)) {
197 			close(dev_fd);
198 			return 0;
199 		}
200 
201 		if (ret && (errno != EBUSY)) {
202 			tst_resm(TWARN,
203 				 "ioctl(%s, LOOP_CLR_FD, 0) unexpectedly failed with: %s",
204 				 dev, tst_strerrno(errno));
205 			close(dev_fd);
206 			return 1;
207 		}
208 
209 		usleep(50000);
210 	}
211 
212 	close(dev_fd);
213 	tst_resm(TWARN,
214 		"ioctl(%s, LOOP_CLR_FD, 0) no ENXIO for too long", dev);
215 	return 1;
216 }
217 
tst_acquire_device__(unsigned int size)218 const char *tst_acquire_device__(unsigned int size)
219 {
220 	int fd;
221 	char *dev;
222 	struct stat st;
223 	unsigned int acq_dev_size;
224 	uint64_t ltp_dev_size;
225 
226 	acq_dev_size = MAX(size, DEV_SIZE_MB);
227 
228 	dev = getenv("LTP_DEV");
229 
230 	if (dev) {
231 		tst_resm(TINFO, "Using test device LTP_DEV='%s'", dev);
232 
233 		if (stat(dev, &st)) {
234 			tst_resm(TWARN | TERRNO, "stat() failed");
235 			return NULL;
236 		}
237 
238 		if (!S_ISBLK(st.st_mode)) {
239 			tst_resm(TWARN, "%s is not a block device", dev);
240 			return NULL;
241 		}
242 
243 		fd = open(dev, O_RDONLY);
244 		if (fd < 0) {
245 			tst_resm(TWARN | TERRNO,
246 				 "open(%s, O_RDONLY) failed", dev);
247 			return NULL;
248 		}
249 
250 		if (ioctl(fd, BLKGETSIZE64, &ltp_dev_size)) {
251 			tst_resm(TWARN | TERRNO,
252 				 "ioctl(fd, BLKGETSIZE64, ...) failed");
253 			close(fd);
254 			return NULL;
255 		}
256 
257 		if (close(fd)) {
258 			tst_resm(TWARN | TERRNO,
259 				 "close(fd) failed");
260 			return NULL;
261 		}
262 
263 		ltp_dev_size = ltp_dev_size/1024/1024;
264 
265 		if (acq_dev_size <= ltp_dev_size)
266 			return dev;
267 
268 		tst_resm(TINFO, "Skipping $LTP_DEV size %"PRIu64"MB, requested size %uMB",
269 				ltp_dev_size, acq_dev_size);
270 	}
271 
272 	if (tst_fill_file(DEV_FILE, 0, 1024 * 1024, acq_dev_size)) {
273 		tst_resm(TWARN | TERRNO, "Failed to create " DEV_FILE);
274 		return NULL;
275 	}
276 
277 	if (find_free_loopdev())
278 		return NULL;
279 
280 	if (attach_device(dev_path, DEV_FILE))
281 		return NULL;
282 
283 	device_acquired = 1;
284 
285 	return dev_path;
286 }
287 
tst_acquire_device_(void (cleanup_fn)(void),unsigned int size)288 const char *tst_acquire_device_(void (cleanup_fn)(void), unsigned int size)
289 {
290 	const char *device;
291 
292 	if (device_acquired) {
293 		tst_brkm(TBROK, cleanup_fn, "Device already acquired");
294 		return NULL;
295 	}
296 
297 	if (!tst_tmpdir_created()) {
298 		tst_brkm(TBROK, cleanup_fn,
299 		         "Cannot acquire device without tmpdir() created");
300 		return NULL;
301 	}
302 
303 	device = tst_acquire_device__(size);
304 
305 	if (!device) {
306 		tst_brkm(TBROK, cleanup_fn, "Failed to acquire device");
307 		return NULL;
308 	}
309 
310 	return device;
311 }
312 
tst_release_device(const char * dev)313 int tst_release_device(const char *dev)
314 {
315 	int ret;
316 
317 	if (!device_acquired)
318 		return 0;
319 
320 	/*
321 	 * Loop device was created -> we need to detach it.
322 	 *
323 	 * The file image is deleted in tst_rmdir();
324 	 */
325 	ret = detach_device(dev);
326 
327 	device_acquired = 0;
328 
329 	return ret;
330 }
331 
tst_clear_device(const char * dev)332 int tst_clear_device(const char *dev)
333 {
334 	if (tst_fill_file(dev, 0, 1024, 512)) {
335 		tst_resm(TWARN, "Failed to clear 512k block on %s", dev);
336 		return 1;
337 	}
338 
339 	return 0;
340 }
341 
tst_umount(const char * path)342 int tst_umount(const char *path)
343 {
344 	int err, ret, i;
345 
346 	for (i = 0; i < 50; i++) {
347 		ret = umount(path);
348 		err = errno;
349 
350 		if (!ret)
351 			return 0;
352 
353 		tst_resm(TINFO, "umount('%s') failed with %s, try %2i...",
354 		         path, tst_strerrno(err), i+1);
355 
356 		if (i == 0 && err == EBUSY) {
357 			tst_resm(TINFO, "Likely gvfsd-trash is probing newly "
358 			         "mounted fs, kill it to speed up tests.");
359 		}
360 
361 		usleep(100000);
362 	}
363 
364 	tst_resm(TWARN, "Failed to umount('%s') after 50 retries", path);
365 	errno = err;
366 	return -1;
367 }
368 
tst_dev_bytes_written(const char * dev)369 unsigned long tst_dev_bytes_written(const char *dev)
370 {
371 	struct stat st;
372 	unsigned long dev_sec_write = 0, dev_bytes_written, io_ticks = 0;
373 	char dev_stat_path[1024];
374 
375 	snprintf(dev_stat_path, sizeof(dev_stat_path), "/sys/block/%s/stat",
376 		 strrchr(dev, '/') + 1);
377 
378 	if (stat(dev_stat_path, &st) != 0)
379 		tst_brkm(TCONF, NULL, "Test device stat file: %s not found",
380 			 dev_stat_path);
381 
382 	SAFE_FILE_SCANF(NULL, dev_stat_path,
383 			"%*s %*s %*s %*s %*s %*s %lu %*s %*s %lu",
384 			&dev_sec_write, &io_ticks);
385 
386 	if (!io_ticks)
387 		tst_brkm(TCONF, NULL, "Test device stat file: %s broken",
388 			 dev_stat_path);
389 
390 	dev_bytes_written = (dev_sec_write - prev_dev_sec_write) * 512;
391 
392 	prev_dev_sec_write = dev_sec_write;
393 
394 	return dev_bytes_written;
395 }
396