1// SPDX-License-Identifier: GPL-2.0-or-later 2/* 3 * Copyright (C) 2014 Cyril Hrubis chrubis@suse.cz 4 */ 5 6#include <sys/types.h> 7#include <sys/stat.h> 8#include <sys/ioctl.h> 9#include <sys/mount.h> 10#include <mntent.h> 11#include <errno.h> 12#include <unistd.h> 13#include <stdlib.h> 14#include <linux/loop.h> 15#include <stdint.h> 16#include <inttypes.h> 17#include <sys/sysmacros.h> 18#include <linux/btrfs.h> 19#include <linux/limits.h> 20#include "lapi/syscalls.h" 21#include "test.h" 22#include "safe_macros.h" 23#include "tst_device.h" 24 25#ifndef LOOP_CTL_GET_FREE 26# define LOOP_CTL_GET_FREE 0x4C82 27#endif 28 29#define LOOP_CONTROL_FILE "/dev/loop-control" 30 31#define DEV_FILE "test_dev.img" 32#define DEV_SIZE_MB 300u 33#define UUID_STR_SZ 37 34#define UUID_FMT "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x" 35 36static char dev_path[PATH_MAX]; 37static int device_acquired; 38static unsigned long prev_dev_sec_write; 39 40static const char * const dev_loop_variants[] = { 41 "/dev/loop%i", 42 "/dev/loop/%i", 43 "/dev/block/loop%i" 44}; 45 46static const char * const dev_variants[] = { 47 "/dev/%s", 48 "/dev/block/%s" 49}; 50 51static int set_dev_loop_path(int dev, char *path, size_t path_len) 52{ 53 unsigned int i; 54 struct stat st; 55 56 for (i = 0; i < ARRAY_SIZE(dev_loop_variants); i++) { 57 snprintf(path, path_len, dev_loop_variants[i], dev); 58 59 if (stat(path, &st) == 0 && S_ISBLK(st.st_mode)) 60 return 0; 61 } 62 63 return 1; 64} 65 66static int set_dev_path(char *dev, char *path, size_t path_len) 67{ 68 unsigned int i; 69 struct stat st; 70 71 for (i = 0; i < ARRAY_SIZE(dev_variants); i++) { 72 snprintf(path, path_len, dev_variants[i], dev); 73 74 if (stat(path, &st) == 0 && S_ISBLK(st.st_mode)) 75 return 0; 76 } 77 78 return 1; 79} 80 81int tst_find_free_loopdev(char *path, size_t path_len) 82{ 83 int ctl_fd, dev_fd, rc, i; 84 struct loop_info loopinfo; 85 char buf[PATH_MAX]; 86 87 /* since Linux 3.1 */ 88 ctl_fd = open(LOOP_CONTROL_FILE, O_RDWR); 89 90 if (ctl_fd > 0) { 91 rc = ioctl(ctl_fd, LOOP_CTL_GET_FREE); 92 close(ctl_fd); 93 if (rc >= 0) { 94 if (path && set_dev_loop_path(rc, path, path_len)) 95 tst_brkm(TBROK, NULL, "Could not stat loop device %i", rc); 96 tst_resm(TINFO, "Found free device %d '%s'", 97 rc, path ?: ""); 98 return rc; 99 } 100 tst_resm(TINFO, "Couldn't find free loop device"); 101 return -1; 102 } 103 104 switch (errno) { 105 case ENOENT: 106 break; 107 case EACCES: 108 tst_resm(TINFO | TERRNO, 109 "Not allowed to open " LOOP_CONTROL_FILE ". " 110 "Are you root?"); 111 break; 112 default: 113 tst_resm(TBROK | TERRNO, "Failed to open " LOOP_CONTROL_FILE); 114 } 115 116 /* 117 * Older way is to iterate over /dev/loop%i and /dev/loop/%i and try 118 * LOOP_GET_STATUS ioctl() which fails for free loop devices. 119 */ 120 for (i = 0; i < 256; i++) { 121 122 if (set_dev_loop_path(i, buf, sizeof(buf))) 123 continue; 124 125 dev_fd = open(buf, O_RDONLY); 126 127 if (dev_fd < 0) 128 continue; 129 130 if (ioctl(dev_fd, LOOP_GET_STATUS, &loopinfo) == 0) { 131 tst_resm(TINFO, "Device '%s' in use", buf); 132 } else { 133 if (errno != ENXIO) 134 continue; 135 tst_resm(TINFO, "Found free device '%s'", buf); 136 close(dev_fd); 137 if (path != NULL) { 138 strncpy(path, buf, path_len); 139 path[path_len-1] = '\0'; 140 } 141 return i; 142 } 143 144 close(dev_fd); 145 } 146 147 tst_resm(TINFO, "No free devices found"); 148 149 return -1; 150} 151 152int tst_attach_device(const char *dev, const char *file) 153{ 154 int dev_fd, file_fd; 155 struct loop_info loopinfo; 156 157 dev_fd = open(dev, O_RDWR); 158 if (dev_fd < 0) { 159 tst_resm(TWARN | TERRNO, "open('%s', O_RDWR) failed", dev); 160 return 1; 161 } 162 163 file_fd = open(file, O_RDWR); 164 if (file_fd < 0) { 165 tst_resm(TWARN | TERRNO, "open('%s', O_RDWR) failed", file); 166 close(dev_fd); 167 return 1; 168 } 169 170 if (ioctl(dev_fd, LOOP_SET_FD, file_fd) < 0) { 171 close(dev_fd); 172 close(file_fd); 173 tst_resm(TWARN | TERRNO, "ioctl(%s, LOOP_SET_FD, %s) failed", 174 dev, file); 175 return 1; 176 } 177 178 /* Old mkfs.btrfs use LOOP_GET_STATUS instead of backing_file to get 179 * associated filename, so we need to set up the device by calling 180 * LOOP_SET_FD and LOOP_SET_STATUS. 181 */ 182 memset(&loopinfo, 0, sizeof(loopinfo)); 183 strcpy(loopinfo.lo_name, file); 184 185 if (ioctl(dev_fd, LOOP_SET_STATUS, &loopinfo)) { 186 close(dev_fd); 187 close(file_fd); 188 tst_resm(TWARN | TERRNO, 189 "ioctl(%s, LOOP_SET_STATUS, %s) failed", dev, file); 190 return 1; 191 } 192 193 close(dev_fd); 194 close(file_fd); 195 return 0; 196} 197 198uint64_t tst_get_device_size(const char *dev_path) 199{ 200 int fd; 201 uint64_t size; 202 struct stat st; 203 204 if (!dev_path) 205 tst_brkm(TBROK, NULL, "No block device path"); 206 207 if (stat(dev_path, &st)) { 208 tst_resm(TWARN | TERRNO, "stat() failed"); 209 return -1; 210 } 211 212 if (!S_ISBLK(st.st_mode)) { 213 tst_resm(TWARN, "%s is not a block device", dev_path); 214 return -1; 215 } 216 217 fd = open(dev_path, O_RDONLY); 218 if (fd < 0) { 219 tst_resm(TWARN | TERRNO, 220 "open(%s, O_RDONLY) failed", dev_path); 221 return -1; 222 } 223 224 if (ioctl(fd, BLKGETSIZE64, &size)) { 225 tst_resm(TWARN | TERRNO, 226 "ioctl(fd, BLKGETSIZE64, ...) failed"); 227 close(fd); 228 return -1; 229 } 230 231 if (close(fd)) { 232 tst_resm(TWARN | TERRNO, 233 "close(fd) failed"); 234 return -1; 235 } 236 237 return size/1024/1024; 238} 239 240int tst_detach_device_by_fd(const char *dev, int dev_fd) 241{ 242 int ret, i; 243 244 /* keep trying to clear LOOPDEV until we get ENXIO, a quick succession 245 * of attach/detach might not give udev enough time to complete 246 */ 247 for (i = 0; i < 40; i++) { 248 ret = ioctl(dev_fd, LOOP_CLR_FD, 0); 249 250 if (ret && (errno == ENXIO)) 251 return 0; 252 253 if (ret && (errno != EBUSY)) { 254 tst_resm(TWARN, 255 "ioctl(%s, LOOP_CLR_FD, 0) unexpectedly failed with: %s", 256 dev, tst_strerrno(errno)); 257 return 1; 258 } 259 260 usleep(50000); 261 } 262 263 tst_resm(TWARN, 264 "ioctl(%s, LOOP_CLR_FD, 0) no ENXIO for too long", dev); 265 return 1; 266} 267 268int tst_detach_device(const char *dev) 269{ 270 int dev_fd, ret; 271 272 dev_fd = open(dev, O_RDONLY); 273 if (dev_fd < 0) { 274 tst_resm(TWARN | TERRNO, "open(%s) failed", dev); 275 return 1; 276 } 277 278 ret = tst_detach_device_by_fd(dev, dev_fd); 279 close(dev_fd); 280 return ret; 281} 282 283int tst_dev_sync(int fd) 284{ 285 return syscall(__NR_syncfs, fd); 286} 287 288const char *tst_acquire_loop_device(unsigned int size, const char *filename) 289{ 290 unsigned int acq_dev_size = size ? size : DEV_SIZE_MB; 291 292 if (tst_prealloc_file(filename, 1024 * 1024, acq_dev_size)) { 293 tst_resm(TWARN | TERRNO, "Failed to create %s", filename); 294 return NULL; 295 } 296 297 if (tst_find_free_loopdev(dev_path, sizeof(dev_path)) == -1) 298 return NULL; 299 300 if (tst_attach_device(dev_path, filename)) 301 return NULL; 302 303 return dev_path; 304} 305 306const char *tst_acquire_device__(unsigned int size) 307{ 308 const char *dev; 309 unsigned int acq_dev_size; 310 uint64_t ltp_dev_size; 311 312 acq_dev_size = size ? size : DEV_SIZE_MB; 313 314 dev = getenv("LTP_DEV"); 315 316 if (dev) { 317 tst_resm(TINFO, "Using test device LTP_DEV='%s'", dev); 318 319 ltp_dev_size = tst_get_device_size(dev); 320 321 if (acq_dev_size <= ltp_dev_size) 322 return dev; 323 324 tst_resm(TINFO, "Skipping $LTP_DEV size %"PRIu64"MB, requested size %uMB", 325 ltp_dev_size, acq_dev_size); 326 } 327 328 dev = tst_acquire_loop_device(acq_dev_size, DEV_FILE); 329 330 if (dev) 331 device_acquired = 1; 332 333 return dev; 334} 335 336const char *tst_acquire_device_(void (cleanup_fn)(void), unsigned int size) 337{ 338 const char *device; 339 340 if (device_acquired) { 341 tst_brkm(TBROK, cleanup_fn, "Device already acquired"); 342 return NULL; 343 } 344 345 if (!tst_tmpdir_created()) { 346 tst_brkm(TBROK, cleanup_fn, 347 "Cannot acquire device without tmpdir() created"); 348 return NULL; 349 } 350 351 device = tst_acquire_device__(size); 352 353 if (!device) { 354 tst_brkm(TBROK, cleanup_fn, "Failed to acquire device"); 355 return NULL; 356 } 357 358 return device; 359} 360 361int tst_release_device(const char *dev) 362{ 363 int ret; 364 365 if (!device_acquired) 366 return 0; 367 368 /* 369 * Loop device was created -> we need to detach it. 370 * 371 * The file image is deleted in tst_rmdir(); 372 */ 373 ret = tst_detach_device(dev); 374 375 device_acquired = 0; 376 377 return ret; 378} 379 380int tst_clear_device(const char *dev) 381{ 382 if (tst_fill_file(dev, 0, 1024, 512)) { 383 tst_resm(TWARN, "Failed to clear 512k block on %s", dev); 384 return 1; 385 } 386 387 return 0; 388} 389 390int tst_umount(const char *path) 391{ 392 int err, ret, i; 393 394 for (i = 0; i < 50; i++) { 395 ret = umount(path); 396 err = errno; 397 398 if (!ret) 399 return 0; 400 401 if (err != EBUSY) { 402 tst_resm(TWARN, "umount('%s') failed with %s", 403 path, tst_strerrno(err)); 404 errno = err; 405 return ret; 406 } 407 408 tst_resm(TINFO, "umount('%s') failed with %s, try %2i...", 409 path, tst_strerrno(err), i+1); 410 411 if (i == 0) { 412 tst_resm(TINFO, "Likely gvfsd-trash is probing newly " 413 "mounted fs, kill it to speed up tests."); 414 } 415 416 usleep(100000); 417 } 418 419 tst_resm(TWARN, "Failed to umount('%s') after 50 retries", path); 420 errno = err; 421 return -1; 422} 423 424int tst_is_mounted(const char *path) 425{ 426 char line[PATH_MAX]; 427 FILE *file; 428 int ret = 0; 429 430 file = SAFE_FOPEN(NULL, "/proc/mounts", "r"); 431 432 while (fgets(line, sizeof(line), file)) { 433 if (strstr(line, path) != NULL) { 434 ret = 1; 435 break; 436 } 437 } 438 439 SAFE_FCLOSE(NULL, file); 440 441 if (!ret) 442 tst_resm(TINFO, "No device is mounted at %s", path); 443 444 return ret; 445} 446 447int tst_is_mounted_at_tmpdir(const char *path) 448{ 449 char cdir[PATH_MAX], mpath[PATH_MAX]; 450 int ret; 451 452 if (!getcwd(cdir, PATH_MAX)) { 453 tst_resm(TWARN | TERRNO, "Failed to find current directory"); 454 return 0; 455 } 456 457 ret = snprintf(mpath, PATH_MAX, "%s/%s", cdir, path); 458 if (ret < 0 || ret >= PATH_MAX) { 459 tst_resm(TWARN | TERRNO, 460 "snprintf() should have returned %d instead of %d", 461 PATH_MAX, ret); 462 return 0; 463 } 464 465 return tst_is_mounted(mpath); 466} 467 468static int find_stat_file(const char *dev, char *path, size_t path_len) 469{ 470 const char *devname = strrchr(dev, '/') + 1; 471 472 snprintf(path, path_len, "/sys/block/%s/stat", devname); 473 474 if (!access(path, F_OK)) 475 return 1; 476 477 DIR *dir = SAFE_OPENDIR(NULL, "/sys/block/"); 478 struct dirent *ent; 479 480 while ((ent = readdir(dir))) { 481 snprintf(path, path_len, "/sys/block/%s/%s/stat", ent->d_name, devname); 482 483 if (!access(path, F_OK)) { 484 SAFE_CLOSEDIR(NULL, dir); 485 return 1; 486 } 487 } 488 489 SAFE_CLOSEDIR(NULL, dir); 490 return 0; 491} 492 493unsigned long tst_dev_bytes_written(const char *dev) 494{ 495 unsigned long dev_sec_write = 0, dev_bytes_written, io_ticks = 0; 496 char dev_stat_path[PATH_MAX]; 497 498 if (!find_stat_file(dev, dev_stat_path, sizeof(dev_stat_path))) 499 tst_brkm(TCONF, NULL, "Test device stat file: %s not found", 500 dev_stat_path); 501 502 SAFE_FILE_SCANF(NULL, dev_stat_path, 503 "%*s %*s %*s %*s %*s %*s %lu %*s %*s %lu", 504 &dev_sec_write, &io_ticks); 505 506 if (!io_ticks) 507 tst_brkm(TCONF, NULL, "Test device stat file: %s broken", 508 dev_stat_path); 509 510 dev_bytes_written = (dev_sec_write - prev_dev_sec_write) * 512; 511 512 prev_dev_sec_write = dev_sec_write; 513 514 return dev_bytes_written; 515} 516 517__attribute__((nonnull)) 518void tst_find_backing_dev(const char *path, char *dev, size_t dev_size) 519{ 520 struct stat buf; 521 struct btrfs_ioctl_fs_info_args args = {0}; 522 struct dirent *d; 523 char uevent_path[PATH_MAX+PATH_MAX+10]; //10 is for the static uevent path 524 char dev_name[NAME_MAX]; 525 char bdev_path[PATH_MAX]; 526 char tmp_path[PATH_MAX]; 527 char btrfs_uuid_str[UUID_STR_SZ]; 528 DIR *dir; 529 unsigned int dev_major, dev_minor; 530 int fd; 531 532 if (stat(path, &buf) < 0) 533 tst_brkm(TWARN | TERRNO, NULL, "stat() failed"); 534 535 strncpy(tmp_path, path, PATH_MAX-1); 536 tmp_path[PATH_MAX-1] = '\0'; 537 if (S_ISREG(buf.st_mode)) 538 dirname(tmp_path); 539 540 dev_major = major(buf.st_dev); 541 dev_minor = minor(buf.st_dev); 542 *dev = '\0'; 543 544 if (dev_major == 0) { 545 tst_resm(TINFO, "Use BTRFS specific strategy"); 546 547 fd = SAFE_OPEN(NULL, tmp_path, O_DIRECTORY); 548 if (!ioctl(fd, BTRFS_IOC_FS_INFO, &args)) { 549 sprintf(btrfs_uuid_str, 550 UUID_FMT, 551 args.fsid[0], args.fsid[1], 552 args.fsid[2], args.fsid[3], 553 args.fsid[4], args.fsid[5], 554 args.fsid[6], args.fsid[7], 555 args.fsid[8], args.fsid[9], 556 args.fsid[10], args.fsid[11], 557 args.fsid[12], args.fsid[13], 558 args.fsid[14], args.fsid[15]); 559 sprintf(bdev_path, 560 "/sys/fs/btrfs/%s/devices", btrfs_uuid_str); 561 } else { 562 if (errno == ENOTTY) 563 tst_brkm(TBROK | TERRNO, NULL, "BTRFS ioctl failed. Is %s on a tmpfs?", path); 564 565 tst_brkm(TBROK | TERRNO, NULL, "BTRFS ioctl on %s failed.", tmp_path); 566 } 567 SAFE_CLOSE(NULL, fd); 568 569 dir = SAFE_OPENDIR(NULL, bdev_path); 570 while ((d = SAFE_READDIR(NULL, dir))) { 571 if (d->d_name[0] != '.') 572 break; 573 } 574 575 uevent_path[0] = '\0'; 576 577 if (d) { 578 sprintf(uevent_path, "%s/%s/uevent", 579 bdev_path, d->d_name); 580 } else { 581 tst_brkm(TBROK | TERRNO, NULL, "No backing device found while looking in %s.", bdev_path); 582 } 583 584 if (SAFE_READDIR(NULL, dir)) 585 tst_resm(TINFO, "Warning: used first of multiple backing device."); 586 587 SAFE_CLOSEDIR(NULL, dir); 588 } else { 589 tst_resm(TINFO, "Use uevent strategy"); 590 sprintf(uevent_path, 591 "/sys/dev/block/%d:%d/uevent", dev_major, dev_minor); 592 } 593 594 if (!access(uevent_path, R_OK)) { 595 FILE_LINES_SCANF(NULL, uevent_path, "DEVNAME=%s", dev_name); 596 597 if (!dev_name[0] || set_dev_path(dev_name, dev, dev_size)) 598 tst_brkm(TBROK, NULL, "Could not stat backing device %s", dev); 599 600 } else { 601 tst_brkm(TBROK, NULL, "uevent file (%s) access failed", uevent_path); 602 } 603} 604 605void tst_stat_mount_dev(const char *const mnt_path, struct stat *const st) 606{ 607 struct mntent *mnt; 608 FILE *mntf = setmntent("/proc/self/mounts", "r"); 609 610 if (!mntf) { 611 tst_brkm(TBROK | TERRNO, NULL, "Can't open /proc/self/mounts"); 612 return; 613 } 614 615 mnt = getmntent(mntf); 616 if (!mnt) { 617 tst_brkm(TBROK | TERRNO, NULL, "Can't read mounts or no mounts?"); 618 return; 619 } 620 621 do { 622 if (strcmp(mnt->mnt_dir, mnt_path)) { 623 mnt = getmntent(mntf); 624 continue; 625 } 626 627 if (stat(mnt->mnt_fsname, st)) { 628 tst_brkm(TBROK | TERRNO, NULL, 629 "Can't stat '%s', mounted at '%s'", 630 mnt->mnt_fsname, mnt_path); 631 } 632 633 return; 634 } while (mnt); 635 636 tst_brkm(TBROK, NULL, "Could not find mount device"); 637} 638 639int tst_dev_block_size(const char *path) 640{ 641 int fd; 642 int size; 643 char dev_name[PATH_MAX]; 644 645 tst_find_backing_dev(path, dev_name, sizeof(dev_name)); 646 647 fd = SAFE_OPEN(NULL, dev_name, O_RDONLY); 648 SAFE_IOCTL(NULL, fd, BLKSSZGET, &size); 649 SAFE_CLOSE(NULL, fd); 650 651 return size; 652} 653