From 1ce7b61f29848cd71fc3a42d79392e076c16779b Mon Sep 17 00:00:00 2001 From: Andrea Mazzoleni Date: Fri, 29 Apr 2016 20:38:12 +0200 Subject: [PATCH] Convert null devices as first operation This ensure that all the usages are with the real device number. Also avoid to resolve device in spinup to suppor filesystem that cannot be resolved, like ZFS. --- cmdline/unix.c | 57 +++++++++++++++++++++++--------------------------- 1 file changed, 26 insertions(+), 31 deletions(-) diff --git a/cmdline/unix.c b/cmdline/unix.c index 438e3030..d2cfc8e5 100644 --- a/cmdline/unix.c +++ b/cmdline/unix.c @@ -144,6 +144,7 @@ static int devresolve_proc(uint64_t device, char* path, size_t path_size) mountsource = second_map[1]; /* accept only /dev/... mountsource */ + /* this excludes ZFS that has the bare label, like "tank" */ if (strncmp(mountsource, "/dev/", 5) != 0) continue; @@ -158,7 +159,7 @@ static int devresolve_proc(uint64_t device, char* path, size_t path_size) } /* get the device of the mount point */ - /* in btrfs it could be different than the one in mountinfo */ + /* in Btrfs it could be different than the one in mountinfo */ if (stat(mountpoint, &st) == 0 && st.st_dev == device) { pathcpy(path, path_size, mountsource); @@ -177,9 +178,15 @@ static int devresolve_proc(uint64_t device, char* path, size_t path_size) #endif /** - * Resolve and get again the device number. + * Get the device of a virtual superblock. * - * This is intended to resolve the case of null devices (major==0). + * This is intended to resolve the case of Btrfs filesystems that + * create a virtual superblock (major==0) not backed by any low + * level device. + * + * See: + * Bug 711881 - too funny btrfs st_dev numbers + * https://bugzilla.redhat.com/show_bug.cgi?id=711881 */ static int devdereference(uint64_t device, uint64_t* new_device) { @@ -283,17 +290,6 @@ static int devresolve_dev(dev_t device, char* path, size_t path_size) #if HAVE_LINUX_DEVICE static int devresolve(uint64_t device, char* path, size_t path_size) { - /* if the major is the null device */ - if (major(device) == 0) { - /* obtain the real device */ - if (devdereference(device, &device) != 0) { - /* LCOV_EXCL_START */ - log_fatal("Failed to map device %u:%u.\n", major(device), minor(device)); - return -1; - /* LCOV_EXCL_STOP */ - } - } - if (devresolve_dev(device, path, path_size) == 0) return 0; @@ -1134,26 +1130,13 @@ static void* thread_spinup(void* arg) /* set the device number for printing */ devinfo->device = st.st_dev; -#if HAVE_LINUX_DEVICE - /* get the device file, but only in Linux and only for the message */ - if (devresolve(devinfo->device, devinfo->file, sizeof(devinfo->file)) != 0) { - /* LCOV_EXCL_START */ - return (void*)-1; - /* LCOV_EXCL_STOP */ - } -#endif - if (devup(devinfo->mount) != 0) { /* LCOV_EXCL_START */ return (void*)-1; /* LCOV_EXCL_STOP */ } -#if HAVE_LINUX_DEVICE - msg_status("Spunup device '%s' for disk '%s' in %" PRIu64 " ms.\n", devinfo->file, devinfo->name, tick_ms() - start); -#else msg_status("Spunup device '%u:%u' for disk '%s' in %" PRIu64 " ms.\n", major(devinfo->device), minor(devinfo->device), devinfo->name, tick_ms() - start); -#endif return 0; } @@ -1270,19 +1253,31 @@ int devquery(tommy_list* high, tommy_list* low, int operation, int others) /* for each device */ for (i = tommy_list_head(high); i != 0; i = i->next) { devinfo_t* devinfo = i->data; + uint64_t device = devinfo->device; + + /* if the major is the null device, find the real one */ + if (major(device) == 0) { + /* obtain the real device */ + if (devdereference(device, &device) != 0) { + /* LCOV_EXCL_START */ + log_fatal("Failed to map device %u:%u.\n", major(device), minor(device)); + return -1; + /* LCOV_EXCL_STOP */ + } + } /* get the device file */ - if (devresolve(devinfo->device, devinfo->file, sizeof(devinfo->file)) != 0) { + if (devresolve(device, devinfo->file, sizeof(devinfo->file)) != 0) { /* LCOV_EXCL_START */ - log_fatal("Failed to resolve device '%u:%u'.\n", major(devinfo->device), minor(devinfo->device)); + log_fatal("Failed to resolve device '%u:%u'.\n", major(device), minor(device)); return -1; /* LCOV_EXCL_STOP */ } /* expand the tree of devices */ - if (devtree(devinfo->name, devinfo->smartctl, devinfo->device, devinfo, low) != 0) { + if (devtree(devinfo->name, devinfo->smartctl, device, devinfo, low) != 0) { /* LCOV_EXCL_START */ - log_fatal("Failed to expand device '%u:%u'.\n", major(devinfo->device), minor(devinfo->device)); + log_fatal("Failed to expand device '%u:%u'.\n", major(device), minor(device)); return -1; /* LCOV_EXCL_STOP */ }