]> git.proxmox.com Git - mirror_zfs-debian.git/blobdiff - lib/libzfs/libzfs_pool.c
Imported Upstream version 0.6.2+git20140204
[mirror_zfs-debian.git] / lib / libzfs / libzfs_pool.c
index a6cacd370c2c6945b7a42c8b08489ad220f65b43..b822ace688c950b5570c57a44a2c230e33f9db08 100644 (file)
@@ -34,6 +34,7 @@
 #include <stdlib.h>
 #include <strings.h>
 #include <unistd.h>
+#include <libgen.h>
 #include <zone.h>
 #include <sys/stat.h>
 #include <sys/efi_partition.h>
@@ -63,7 +64,7 @@ typedef struct prop_flags {
 static int
 zpool_get_all_props(zpool_handle_t *zhp)
 {
-       zfs_cmd_t zc = { "\0", "\0", "\0", "\0", 0 };
+       zfs_cmd_t zc = {"\0"};
        libzfs_handle_t *hdl = zhp->zpool_hdl;
 
        (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
@@ -235,12 +236,22 @@ zpool_pool_state_to_name(pool_state_t state)
 }
 
 /*
- * Get a zpool property value for 'prop' and return the value in
- * a pre-allocated buffer.
+ * API compatibility wrapper around zpool_get_prop_literal
  */
 int
 zpool_get_prop(zpool_handle_t *zhp, zpool_prop_t prop, char *buf, size_t len,
     zprop_source_t *srctype)
+{
+       return (zpool_get_prop_literal(zhp, prop, buf, len, srctype, B_FALSE));
+}
+
+/*
+ * Get a zpool property value for 'prop' and return the value in
+ * a pre-allocated buffer.
+ */
+int
+zpool_get_prop_literal(zpool_handle_t *zhp, zpool_prop_t prop, char *buf,
+    size_t len, zprop_source_t *srctype, boolean_t literal)
 {
        uint64_t intval;
        const char *strval;
@@ -307,7 +318,11 @@ zpool_get_prop(zpool_handle_t *zhp, zpool_prop_t prop, char *buf, size_t len,
                case ZPOOL_PROP_FREEING:
                case ZPOOL_PROP_EXPANDSZ:
                case ZPOOL_PROP_ASHIFT:
-                       (void) zfs_nicenum(intval, buf, len);
+                       if (literal)
+                               (void) snprintf(buf, len, "%llu",
+                                       (u_longlong_t)intval);
+                       else
+                               (void) zfs_nicenum(intval, buf, len);
                        break;
 
                case ZPOOL_PROP_CAPACITY:
@@ -691,7 +706,7 @@ error:
 int
 zpool_set_prop(zpool_handle_t *zhp, const char *propname, const char *propval)
 {
-       zfs_cmd_t zc = { "\0", "\0", "\0", "\0", 0 };
+       zfs_cmd_t zc = {"\0"};
        int ret = -1;
        char errbuf[1024];
        nvlist_t *nvl = NULL;
@@ -1140,11 +1155,10 @@ int
 zpool_create(libzfs_handle_t *hdl, const char *pool, nvlist_t *nvroot,
     nvlist_t *props, nvlist_t *fsprops)
 {
-       zfs_cmd_t zc = { "\0", "\0", "\0", "\0", 0 };
+       zfs_cmd_t zc = {"\0"};
        nvlist_t *zc_fsprops = NULL;
        nvlist_t *zc_props = NULL;
        char msg[1024];
-       char *altroot;
        int ret = -1;
 
        (void) snprintf(msg, sizeof (msg), dgettext(TEXT_DOMAIN,
@@ -1208,8 +1222,9 @@ zpool_create(libzfs_handle_t *hdl, const char *pool, nvlist_t *nvroot,
                         * part of an active md or lvm device.
                         */
                        zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
-                           "one or more vdevs refer to the same device, or one of\n"
-                           "the devices is part of an active md or lvm device"));
+                           "one or more vdevs refer to the same device, or "
+                           "one of\nthe devices is part of an active md or "
+                           "lvm device"));
                        return (zfs_error(hdl, EZFS_BADDEV, msg));
 
                case EOVERFLOW:
@@ -1245,21 +1260,6 @@ zpool_create(libzfs_handle_t *hdl, const char *pool, nvlist_t *nvroot,
                }
        }
 
-       /*
-        * If this is an alternate root pool, then we automatically set the
-        * mountpoint of the root dataset to be '/'.
-        */
-       if (nvlist_lookup_string(props, zpool_prop_to_name(ZPOOL_PROP_ALTROOT),
-           &altroot) == 0) {
-               zfs_handle_t *zhp;
-
-               verify((zhp = zfs_open(hdl, pool, ZFS_TYPE_DATASET)) != NULL);
-               verify(zfs_prop_set(zhp, zfs_prop_to_name(ZFS_PROP_MOUNTPOINT),
-                   "/") == 0);
-
-               zfs_close(zhp);
-       }
-
 create_failed:
        zcmd_free_nvlists(&zc);
        nvlist_free(zc_props);
@@ -1272,9 +1272,9 @@ create_failed:
  * datasets left in the pool.
  */
 int
-zpool_destroy(zpool_handle_t *zhp)
+zpool_destroy(zpool_handle_t *zhp, const char *log_str)
 {
-       zfs_cmd_t zc = { "\0", "\0", "\0", "\0", 0 };
+       zfs_cmd_t zc = {"\0"};
        zfs_handle_t *zfp = NULL;
        libzfs_handle_t *hdl = zhp->zpool_hdl;
        char msg[1024];
@@ -1284,6 +1284,7 @@ zpool_destroy(zpool_handle_t *zhp)
                return (-1);
 
        (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
+       zc.zc_history = (uint64_t)(uintptr_t)log_str;
 
        if (zfs_ioctl(hdl, ZFS_IOC_POOL_DESTROY, &zc) != 0) {
                (void) snprintf(msg, sizeof (msg), dgettext(TEXT_DOMAIN,
@@ -1317,7 +1318,7 @@ zpool_destroy(zpool_handle_t *zhp)
 int
 zpool_add(zpool_handle_t *zhp, nvlist_t *nvroot)
 {
-       zfs_cmd_t zc = { "\0", "\0", "\0", "\0", 0 };
+       zfs_cmd_t zc = {"\0"};
        int ret;
        libzfs_handle_t *hdl = zhp->zpool_hdl;
        char msg[1024];
@@ -1409,13 +1410,6 @@ zpool_add(zpool_handle_t *zhp, nvlist_t *nvroot)
                        (void) zfs_error(hdl, EZFS_BADVERSION, msg);
                        break;
 
-               case EDOM:
-                       zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
-                           "root pool can not have multiple vdevs"
-                           " or separate logs"));
-                       (void) zfs_error(hdl, EZFS_POOL_NOTSUP, msg);
-                       break;
-
                case ENOTBLK:
                        zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
                            "cache device must be a disk or disk slice"));
@@ -1440,10 +1434,11 @@ zpool_add(zpool_handle_t *zhp, nvlist_t *nvroot)
  * Exports the pool from the system.  The caller must ensure that there are no
  * mounted datasets in the pool.
  */
-int
-zpool_export_common(zpool_handle_t *zhp, boolean_t force, boolean_t hardforce)
+static int
+zpool_export_common(zpool_handle_t *zhp, boolean_t force, boolean_t hardforce,
+    const char *log_str)
 {
-       zfs_cmd_t zc = { "\0", "\0", "\0", "\0", 0 };
+       zfs_cmd_t zc = {"\0"};
        char msg[1024];
 
        (void) snprintf(msg, sizeof (msg), dgettext(TEXT_DOMAIN,
@@ -1452,6 +1447,7 @@ zpool_export_common(zpool_handle_t *zhp, boolean_t force, boolean_t hardforce)
        (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
        zc.zc_cookie = force;
        zc.zc_guid = hardforce;
+       zc.zc_history = (uint64_t)(uintptr_t)log_str;
 
        if (zfs_ioctl(zhp->zpool_hdl, ZFS_IOC_POOL_EXPORT, &zc) != 0) {
                switch (errno) {
@@ -1473,15 +1469,15 @@ zpool_export_common(zpool_handle_t *zhp, boolean_t force, boolean_t hardforce)
 }
 
 int
-zpool_export(zpool_handle_t *zhp, boolean_t force)
+zpool_export(zpool_handle_t *zhp, boolean_t force, const char *log_str)
 {
-       return (zpool_export_common(zhp, force, B_FALSE));
+       return (zpool_export_common(zhp, force, B_FALSE, log_str));
 }
 
 int
-zpool_export_force(zpool_handle_t *zhp)
+zpool_export_force(zpool_handle_t *zhp, const char *log_str)
 {
-       return (zpool_export_common(zhp, B_TRUE, B_TRUE));
+       return (zpool_export_common(zhp, B_TRUE, B_TRUE, log_str));
 }
 
 static void
@@ -1717,7 +1713,7 @@ int
 zpool_import_props(libzfs_handle_t *hdl, nvlist_t *config, const char *newname,
     nvlist_t *props, int flags)
 {
-       zfs_cmd_t zc = { "\0", "\0", "\0", "\0", 0 };
+       zfs_cmd_t zc = {"\0"};
        zpool_rewind_policy_t policy;
        nvlist_t *nv = NULL;
        nvlist_t *nvinfo = NULL;
@@ -1909,7 +1905,7 @@ zpool_import_props(libzfs_handle_t *hdl, nvlist_t *config, const char *newname,
 int
 zpool_scan(zpool_handle_t *zhp, pool_scan_func_t func)
 {
-       zfs_cmd_t zc = { "\0", "\0", "\0", "\0", 0 };
+       zfs_cmd_t zc = {"\0"};
        char msg[1024];
        libzfs_handle_t *hdl = zhp->zpool_hdl;
 
@@ -2385,7 +2381,7 @@ int
 zpool_vdev_online(zpool_handle_t *zhp, const char *path, int flags,
     vdev_state_t *newstate)
 {
-       zfs_cmd_t zc = { "\0", "\0", "\0", "\0", 0 };
+       zfs_cmd_t zc = {"\0"};
        char msg[1024];
        nvlist_t *tgt;
        boolean_t avail_spare, l2cache, islog;
@@ -2432,7 +2428,7 @@ zpool_vdev_online(zpool_handle_t *zhp, const char *path, int flags,
 
                        if (path[0] != '/') {
                                error = zfs_resolve_shortname(path, buf,
-                                   sizeof(buf));
+                                   sizeof (buf));
                                if (error != 0)
                                        return (zfs_error(hdl, EZFS_NODEVICE,
                                            msg));
@@ -2469,7 +2465,7 @@ zpool_vdev_online(zpool_handle_t *zhp, const char *path, int flags,
 int
 zpool_vdev_offline(zpool_handle_t *zhp, const char *path, boolean_t istmp)
 {
-       zfs_cmd_t zc = { "\0", "\0", "\0", "\0", 0 };
+       zfs_cmd_t zc = {"\0"};
        char msg[1024];
        nvlist_t *tgt;
        boolean_t avail_spare, l2cache;
@@ -2519,12 +2515,12 @@ zpool_vdev_offline(zpool_handle_t *zhp, const char *path, boolean_t istmp)
 int
 zpool_vdev_fault(zpool_handle_t *zhp, uint64_t guid, vdev_aux_t aux)
 {
-       zfs_cmd_t zc = { "\0", "\0", "\0", "\0", 0 };
+       zfs_cmd_t zc = {"\0"};
        char msg[1024];
        libzfs_handle_t *hdl = zhp->zpool_hdl;
 
        (void) snprintf(msg, sizeof (msg),
-           dgettext(TEXT_DOMAIN, "cannot fault %llu"), (u_longlong_t)guid);
+           dgettext(TEXT_DOMAIN, "cannot fault %llu"), (u_longlong_t)guid);
 
        (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
        zc.zc_guid = guid;
@@ -2554,12 +2550,12 @@ zpool_vdev_fault(zpool_handle_t *zhp, uint64_t guid, vdev_aux_t aux)
 int
 zpool_vdev_degrade(zpool_handle_t *zhp, uint64_t guid, vdev_aux_t aux)
 {
-       zfs_cmd_t zc = { "\0", "\0", "\0", "\0", 0 };
+       zfs_cmd_t zc = {"\0"};
        char msg[1024];
        libzfs_handle_t *hdl = zhp->zpool_hdl;
 
        (void) snprintf(msg, sizeof (msg),
-           dgettext(TEXT_DOMAIN, "cannot degrade %llu"), (u_longlong_t)guid);
+           dgettext(TEXT_DOMAIN, "cannot degrade %llu"), (u_longlong_t)guid);
 
        (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
        zc.zc_guid = guid;
@@ -2608,7 +2604,7 @@ int
 zpool_vdev_attach(zpool_handle_t *zhp,
     const char *old_disk, const char *new_disk, nvlist_t *nvroot, int replacing)
 {
-       zfs_cmd_t zc = { "\0", "\0", "\0", "\0", 0 };
+       zfs_cmd_t zc = {"\0"};
        char msg[1024];
        int ret;
        nvlist_t *tgt;
@@ -2784,7 +2780,7 @@ zpool_vdev_attach(zpool_handle_t *zhp,
 int
 zpool_vdev_detach(zpool_handle_t *zhp, const char *path)
 {
-       zfs_cmd_t zc = { "\0", "\0", "\0", "\0", 0 };
+       zfs_cmd_t zc = {"\0"};
        char msg[1024];
        nvlist_t *tgt;
        boolean_t avail_spare, l2cache;
@@ -2882,7 +2878,7 @@ int
 zpool_vdev_split(zpool_handle_t *zhp, char *newname, nvlist_t **newroot,
     nvlist_t *props, splitflags_t flags)
 {
-       zfs_cmd_t zc = { "\0", "\0", "\0", "\0", 0 };
+       zfs_cmd_t zc = {"\0"};
        char msg[1024];
        nvlist_t *tree, *config, **child, **newchild, *newconfig = NULL;
        nvlist_t **varray = NULL, *zc_props = NULL;
@@ -3093,7 +3089,7 @@ out:
 int
 zpool_vdev_remove(zpool_handle_t *zhp, const char *path)
 {
-       zfs_cmd_t zc = { "\0", "\0", "\0", "\0", 0 };
+       zfs_cmd_t zc = {"\0"};
        char msg[1024];
        nvlist_t *tgt;
        boolean_t avail_spare, l2cache, islog;
@@ -3138,7 +3134,7 @@ zpool_vdev_remove(zpool_handle_t *zhp, const char *path)
 int
 zpool_clear(zpool_handle_t *zhp, const char *path, nvlist_t *rewindnvl)
 {
-       zfs_cmd_t zc = { "\0", "\0", "\0", "\0", 0 };
+       zfs_cmd_t zc = {"\0"};
        char msg[1024];
        nvlist_t *tgt;
        zpool_rewind_policy_t policy;
@@ -3214,13 +3210,13 @@ zpool_clear(zpool_handle_t *zhp, const char *path, nvlist_t *rewindnvl)
 int
 zpool_vdev_clear(zpool_handle_t *zhp, uint64_t guid)
 {
-       zfs_cmd_t zc = { "\0", "\0", "\0", "\0", 0 };
+       zfs_cmd_t zc = {"\0"};
        char msg[1024];
        libzfs_handle_t *hdl = zhp->zpool_hdl;
 
        (void) snprintf(msg, sizeof (msg),
            dgettext(TEXT_DOMAIN, "cannot clear errors for %llx"),
-           (u_longlong_t)guid);
+           (u_longlong_t)guid);
 
        (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
        zc.zc_guid = guid;
@@ -3240,7 +3236,7 @@ zpool_reguid(zpool_handle_t *zhp)
 {
        char msg[1024];
        libzfs_handle_t *hdl = zhp->zpool_hdl;
-       zfs_cmd_t zc = { "\0", "\0", "\0", "\0", 0 };
+       zfs_cmd_t zc = {"\0"};
 
        (void) snprintf(msg, sizeof (msg),
            dgettext(TEXT_DOMAIN, "cannot reguid '%s'"), zhp->zpool_name);
@@ -3258,7 +3254,7 @@ zpool_reguid(zpool_handle_t *zhp)
 int
 zpool_reopen(zpool_handle_t *zhp)
 {
-       zfs_cmd_t zc = { "\0", "\0", "\0", "\0", 0 };
+       zfs_cmd_t zc = {"\0"};
        char msg[1024];
        libzfs_handle_t *hdl = zhp->zpool_hdl;
 
@@ -3338,7 +3334,7 @@ path_to_devid(const char *path)
 static void
 set_path(zpool_handle_t *zhp, nvlist_t *nv, const char *path)
 {
-       zfs_cmd_t zc = { "\0", "\0", "\0", "\0", 0 };
+       zfs_cmd_t zc = {"\0"};
 
        (void) strncpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
        (void) strncpy(zc.zc_value, path, sizeof (zc.zc_value));
@@ -3465,7 +3461,7 @@ zpool_vdev_name(libzfs_handle_t *hdl, zpool_handle_t *zhp, nvlist_t *nv,
                 */
                if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_WHOLE_DISK,
                    &value) == 0 && value) {
-                       return strip_partition(hdl, path);
+                       return (strip_partition(hdl, path));
                }
        } else {
                verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_TYPE, &path) == 0);
@@ -3513,7 +3509,7 @@ zbookmark_compare(const void *a, const void *b)
 int
 zpool_get_errlog(zpool_handle_t *zhp, nvlist_t **nverrlistp)
 {
-       zfs_cmd_t zc = { "\0", "\0", "\0", "\0", 0 };
+       zfs_cmd_t zc = {"\0"};
        uint64_t count;
        zbookmark_t *zb = NULL;
        int i;
@@ -3609,7 +3605,7 @@ nomem:
 int
 zpool_upgrade(zpool_handle_t *zhp, uint64_t new_version)
 {
-       zfs_cmd_t zc = { "\0", "\0", "\0", "\0", 0 };
+       zfs_cmd_t zc = {"\0"};
        libzfs_handle_t *hdl = zhp->zpool_hdl;
 
        (void) strcpy(zc.zc_name, zhp->zpool_name);
@@ -3623,40 +3619,32 @@ zpool_upgrade(zpool_handle_t *zhp, uint64_t new_version)
 }
 
 void
-zpool_set_history_str(const char *subcommand, int argc, char **argv,
-    char *history_str)
+zfs_save_arguments(int argc, char **argv, char *string, int len)
 {
        int i;
 
-       (void) strlcpy(history_str, subcommand, HIS_MAX_RECORD_LEN);
+       (void) strlcpy(string, basename(argv[0]), len);
        for (i = 1; i < argc; i++) {
-               if (strlen(history_str) + 1 + strlen(argv[i]) >
-                   HIS_MAX_RECORD_LEN)
-                       break;
-               (void) strlcat(history_str, " ", HIS_MAX_RECORD_LEN);
-               (void) strlcat(history_str, argv[i], HIS_MAX_RECORD_LEN);
+               (void) strlcat(string, " ", len);
+               (void) strlcat(string, argv[i], len);
        }
 }
 
-/*
- * Stage command history for logging.
- */
 int
-zpool_stage_history(libzfs_handle_t *hdl, const char *history_str)
+zpool_log_history(libzfs_handle_t *hdl, const char *message)
 {
-       if (history_str == NULL)
-               return (EINVAL);
-
-       if (strlen(history_str) > HIS_MAX_RECORD_LEN)
-               return (EINVAL);
-
-       if (hdl->libzfs_log_str != NULL)
-               free(hdl->libzfs_log_str);
-
-       if ((hdl->libzfs_log_str = strdup(history_str)) == NULL)
-               return (no_memory(hdl));
-
-       return (0);
+       zfs_cmd_t zc = {"\0"};
+       nvlist_t *args;
+       int err;
+
+       args = fnvlist_alloc();
+       fnvlist_add_string(args, "message", message);
+       err = zcmd_write_src_nvlist(hdl, &zc, args);
+       if (err == 0)
+               err = ioctl(hdl->libzfs_fd, ZFS_IOC_LOG_HISTORY, &zc);
+       nvlist_free(args);
+       zcmd_free_nvlists(&zc);
+       return (err);
 }
 
 /*
@@ -3671,7 +3659,7 @@ zpool_stage_history(libzfs_handle_t *hdl, const char *history_str)
 static int
 get_history(zpool_handle_t *zhp, char *buf, uint64_t *off, uint64_t *len)
 {
-       zfs_cmd_t zc = { "\0", "\0", "\0", "\0", 0 };
+       zfs_cmd_t zc = {"\0"};
        libzfs_handle_t *hdl = zhp->zpool_hdl;
 
        (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
@@ -3808,7 +3796,7 @@ int
 zpool_events_next(libzfs_handle_t *hdl, nvlist_t **nvp,
     int *dropped, int block, int cleanup_fd)
 {
-       zfs_cmd_t zc = { "\0", "\0", "\0", "\0", 0 };
+       zfs_cmd_t zc = {"\0"};
        int error = 0;
 
        *nvp = NULL;
@@ -3867,7 +3855,7 @@ out:
 int
 zpool_events_clear(libzfs_handle_t *hdl, int *count)
 {
-       zfs_cmd_t zc = { "\0", "\0", "\0", "\0", 0 };
+       zfs_cmd_t zc = {"\0"};
        char msg[1024];
 
        (void) snprintf(msg, sizeof (msg), dgettext(TEXT_DOMAIN,
@@ -3886,14 +3874,15 @@ void
 zpool_obj_to_path(zpool_handle_t *zhp, uint64_t dsobj, uint64_t obj,
     char *pathname, size_t len)
 {
-       zfs_cmd_t zc = { "\0", "\0", "\0", "\0", 0 };
+       zfs_cmd_t zc = {"\0"};
        boolean_t mounted = B_FALSE;
        char *mntpnt = NULL;
        char dsname[MAXNAMELEN];
 
        if (dsobj == 0) {
                /* special case for the MOS */
-               (void) snprintf(pathname, len, "<metadata>:<0x%llx>", (longlong_t)obj);
+               (void) snprintf(pathname, len, "<metadata>:<0x%llx>",
+                   (longlong_t)obj);
                return;
        }
 
@@ -3925,7 +3914,8 @@ zpool_obj_to_path(zpool_handle_t *zhp, uint64_t dsobj, uint64_t obj,
                            dsname, zc.zc_value);
                }
        } else {
-               (void) snprintf(pathname, len, "%s:<0x%llx>", dsname, (longlong_t)obj);
+               (void) snprintf(pathname, len, "%s:<0x%llx>", dsname,
+                   (longlong_t)obj);
        }
        free(mntpnt);
 }
@@ -4025,22 +4015,22 @@ zpool_label_disk_check(char *path)
        int fd, err;
 
        if ((fd = open(path, O_RDWR|O_DIRECT)) < 0)
-               return errno;
+               return (errno);
 
        if ((err = efi_alloc_and_read(fd, &vtoc)) != 0) {
                (void) close(fd);
-               return err;
+               return (err);
        }
 
        if (vtoc->efi_flags & EFI_GPT_PRIMARY_CORRUPT) {
                efi_free(vtoc);
                (void) close(fd);
-               return EIDRM;
+               return (EIDRM);
        }
 
        efi_free(vtoc);
        (void) close(fd);
-       return 0;
+       return (0);
 }
 
 /*
@@ -4180,5 +4170,5 @@ zpool_label_disk(libzfs_handle_t *hdl, zpool_handle_t *zhp, char *name)
                return (zfs_error(hdl, EZFS_LABELFAILED, errbuf));
        }
 
-       return 0;
+       return (0);
 }