Illumos #734: Use taskq_dispatch_ent() interface
[zfs.git] / lib / libzfs / libzfs_util.c
index d72b7c0..5f6763c 100644 (file)
@@ -631,16 +631,27 @@ libzfs_module_loaded(const char *module)
        return result;
 }
 
-static int
-libzfs_run_process(const char *path, char *argv[])
+int
+libzfs_run_process(const char *path, char *argv[], int flags)
 {
        pid_t pid;
-       int rc;
+       int rc, devnull_fd;
 
        pid = vfork();
        if (pid == 0) {
-               close(1);
-               close(2);
+               devnull_fd = open("/dev/null", O_WRONLY);
+
+               if (devnull_fd < 0)
+                       _exit(-1);
+
+               if (!(flags & STDOUT_VERBOSE))
+                       (void) dup2(devnull_fd, STDOUT_FILENO);
+
+               if (!(flags & STDERR_VERBOSE))
+                       (void) dup2(devnull_fd, STDERR_FILENO);
+
+               close(devnull_fd);
+
                (void) execvp(path, argv);
                _exit(-1);
        } else if (pid > 0) {
@@ -657,14 +668,15 @@ libzfs_run_process(const char *path, char *argv[])
        return -1;
 }
 
-static int
+int
 libzfs_load_module(const char *module)
 {
        char *argv[4] = {"/sbin/modprobe", "-q", (char *)module, (char *)0};
 
        if (libzfs_module_loaded(module))
                return 0;
-       return libzfs_run_process("modprobe", argv);
+
+       return libzfs_run_process("/sbin/modprobe", argv, 0);
 }
 
 libzfs_handle_t *
@@ -726,9 +738,7 @@ libzfs_fini(libzfs_handle_t *hdl)
 #endif
        if (hdl->libzfs_sharetab)
                (void) fclose(hdl->libzfs_sharetab);
-#ifdef HAVE_ZPL
        zfs_uninit_libshare(hdl);
-#endif
        if (hdl->libzfs_log_str)
                (void) free(hdl->libzfs_log_str);
        zpool_free_handles(hdl);
@@ -802,6 +812,46 @@ zfs_path_to_zhandle(libzfs_handle_t *hdl, char *path, zfs_type_t argtype)
 }
 
 /*
+ * Given a shorthand device name, check if a file by that name exists in a list
+ * of directories under /dev.  If one is found, store its full path in the
+ * buffer pointed to by the path argument and return 0, else return -1.  The
+ * path buffer must be allocated by the caller.
+ */
+int
+zfs_resolve_shortname(const char *name, char *path, size_t pathlen)
+{
+       int i, err;
+       char dirs[5][9] = {"by-id", "by-label", "by-path", "by-uuid", "zpool"};
+
+       (void) snprintf(path, pathlen, "%s/%s", DISK_ROOT, name);
+       err = access(path, F_OK);
+       for (i = 0; i < 5 && err < 0; i++) {
+               (void) snprintf(path, pathlen, "%s/%s/%s",
+                   UDISK_ROOT, dirs[i], name);
+               err = access(path, F_OK);
+       }
+       return err;
+}
+
+/*
+ * Append partition suffix to a device path.  This should be used to generate
+ * the name of a whole disk as it is stored in the vdev label.  The
+ * user-visible names of whole disks do not contain the partition information.
+ * Modifies buf which must be allocated by the caller.
+ */
+void
+zfs_append_partition(const char *path, char *buf, size_t buflen)
+{
+       if (strncmp(path, UDISK_ROOT, strlen(UDISK_ROOT)) == 0)
+               (void) snprintf(buf, buflen, "%s%s%s", path, "-part",
+                       FIRST_SLICE);
+       else
+               (void) snprintf(buf, buflen, "%s%s%s", path,
+                       isdigit(path[strlen(path)-1]) ?  "p" : "",
+                       FIRST_SLICE);
+}
+
+/*
  * Initialize the zc_nvlist_dst member to prepare for receiving an nvlist from
  * an ioctl().
  */
@@ -1143,11 +1193,14 @@ str2shift(libzfs_handle_t *hdl, const char *buf)
        }
 
        /*
-        * We want to allow trailing 'b' characters for 'GB' or 'Mb'.  But don't
-        * allow 'BB' - that's just weird.
+        * Allow 'G' = 'GB' = 'GiB', case-insensitively.
+        * However, 'BB' and 'BiB' are disallowed.
         */
-       if (buf[1] == '\0' || (toupper(buf[1]) == 'B' && buf[2] == '\0' &&
-           toupper(buf[0]) != 'B'))
+       if (buf[1] == '\0' ||
+           (toupper(buf[0]) != 'B' &&
+            ((toupper(buf[1]) == 'B' && buf[2] == '\0') ||
+             (toupper(buf[1]) == 'I' && toupper(buf[2]) == 'B' &&
+              buf[3] == '\0'))))
                return (10*i);
 
        zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,