--- a/usr/src/lib/libbe/be_list.c Tue Feb 03 15:49:13 2009 -0800
+++ b/usr/src/lib/libbe/be_list.c Wed Feb 04 12:39:55 2009 -0700
@@ -20,7 +20,7 @@
*/
/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -35,6 +35,7 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
+#include <errno.h>
#include "libbe.h"
#include "libbe_priv.h"
@@ -51,21 +52,26 @@
} list_callback_data_t;
/*
- * Private callback function prototypes
+ * Private function prototypes
*/
-static int be_get_list_all_callback(zpool_handle_t *zhp, void *data);
+static int be_add_children_callback(zfs_handle_t *zhp, void *data);
static int be_get_list_callback(zpool_handle_t *, void *);
-static int be_add_children_callback(zfs_handle_t *zhp, void *data);
+static int be_get_node_data(zfs_handle_t *, be_node_list_t *, char *,
+ const char *, char *, char *);
+static int be_get_ds_data(zfs_handle_t *, char *, be_dataset_list_t *,
+ be_node_list_t *);
+static int be_get_ss_data(zfs_handle_t *, char *, be_snapshot_list_t *,
+ be_node_list_t *);
static void be_sort_list(be_node_list_t **);
static int be_qsort_compare_BEs(const void *, const void *);
static int be_qsort_compare_snapshots(const void *x, const void *y);
static int be_qsort_compare_datasets(const void *x, const void *y);
+static void *be_list_alloc(int *, size_t);
/*
* Private data.
*/
static char be_container_ds[MAXPATHLEN];
-const char *rpool;
/* ******************************************************************** */
/* Public Functions */
@@ -116,8 +122,6 @@
be_zfs_fini();
- be_sort_list(be_nodes);
-
return (ret);
}
@@ -168,40 +172,34 @@
* If be_name is NULL we'll look for all BE's on the system.
* If not then we will only return data for the specified BE.
*/
- if (be_name == NULL) {
- err = zpool_iter(g_zfs, be_get_list_all_callback, &cb);
- if (err != 0) {
- if (cb.be_nodes_head != NULL) {
- be_free_list(cb.be_nodes_head);
- cb.be_nodes_head = NULL;
- cb.be_nodes = NULL;
- }
- err = BE_ERR_BE_NOENT;
- } else if (cb.be_nodes_head == NULL) {
- be_print_err(gettext("be_list: "
- "No BE's found\n"));
- err = BE_ERR_BE_NOENT;
+ if (be_name != NULL)
+ cb.be_name = strdup(be_name);
+
+ err = zpool_iter(g_zfs, be_get_list_callback, &cb);
+ if (err != 0) {
+ if (cb.be_nodes_head != NULL) {
+ be_free_list(cb.be_nodes_head);
+ cb.be_nodes_head = NULL;
+ cb.be_nodes = NULL;
}
- } else {
- cb.be_name = be_name;
- err = zpool_iter(g_zfs, be_get_list_callback, &cb);
- if (err != 0) {
- if (cb.be_nodes_head != NULL) {
- be_free_list(cb.be_nodes_head);
- cb.be_nodes_head = NULL;
- cb.be_nodes = NULL;
- }
- err = BE_ERR_BE_NOENT;
- } else if (cb.be_nodes_head == NULL) {
- be_print_err(gettext("be_list: "
- "BE (%s) does not exist\n"),
- be_name);
- err = BE_ERR_BE_NOENT;
- }
+ err = BE_ERR_BE_NOENT;
+ }
+
+ if (cb.be_nodes_head == NULL) {
+ if (be_name != NULL)
+ be_print_err(gettext("be_list: BE (%s) does not "
+ "exist\n"), be_name);
+ else
+ be_print_err(gettext("be_list: No BE's found\n"));
+ err = BE_ERR_BE_NOENT;
}
*be_nodes = cb.be_nodes_head;
+ free(cb.be_name);
+
+ be_sort_list(be_nodes);
+
return (err);
}
@@ -260,88 +258,11 @@
/* ******************************************************************** */
/*
- * Function: be_get_list_all_callback
- * Description: Callback function used by zpool_iter to look through all
- * the pools on the system looking for BEs. This function is
- * used when no BE is specified and we want to return a list
- * of all BEs on the system.
- * Parameters:
- * zlp - handle to the first zpool. (provided by the
- * zpool_iter call)
- * data - pointer to the callback data and where we'll pass
- * the list of BE back.
- * Returns:
- * 0 - Success
- * be_errno_t - Failure
- * Scope:
- * Private
- */
-static int
-be_get_list_all_callback(zpool_handle_t *zlp, void *data)
-{
- list_callback_data_t *cb = (list_callback_data_t *)data;
- zfs_handle_t *zhp = NULL;
- int err = 0;
-
- rpool = zpool_get_name(zlp);
-
- /*
- * Generate string for the BE container dataset
- */
- be_make_container_ds(rpool, be_container_ds,
- sizeof (be_container_ds));
-
- /*
- * Check if main BE container dataset exists
- */
- if (!zfs_dataset_exists(g_zfs, be_container_ds,
- ZFS_TYPE_FILESYSTEM)) {
- /*
- * No BE container dataset exists in this pool,
- * no valid BE's in this pool, try the next pool.
- */
- zpool_close(zlp);
- return (0);
- }
-
- if ((zhp = zfs_open(g_zfs, be_container_ds, ZFS_TYPE_FILESYSTEM)) ==
- NULL) {
- be_print_err(gettext("be_get_list_all_callback: failed to "
- "open BE container dataset %s: %s\n"),
- be_container_ds, libzfs_error_description(g_zfs));
- err = zfs_err_to_be_err(g_zfs);
- zpool_close(zlp);
- return (err);
- }
-
- if (cb->be_nodes_head == NULL) {
- cb->be_nodes_head = cb->be_nodes =
- calloc(1, sizeof (be_node_list_t));
- if (cb->be_nodes == NULL) {
- ZFS_CLOSE(zhp);
- zpool_close(zlp);
- be_print_err(gettext("be_get_list_all_callback: memory "
- "allocation failed\n"));
- return (BE_ERR_NOMEM);
- }
- }
-
- /*
- * iterate through the next level of datasets to find the BE's
- * within the pool
- */
- err = zfs_iter_filesystems(zhp, be_add_children_callback, cb);
- ZFS_CLOSE(zhp);
- zpool_close(zlp);
-
- return (err);
-}
-
-/*
* Function: be_get_list_callback
* Description: Callback function used by zfs_iter to look through all
- * the datasets and snapshots for the named BE. This function
- * is used when a BE name has been specified.
+ * the pools on the system looking for BEs. If a BE name was
+ * specified only that BE's information will be collected and
+ * returned.
* Parameters:
* zlp - handle to the first zfs dataset. (provided by the
* zfs_iter_* call)
@@ -358,140 +279,85 @@
{
list_callback_data_t *cb = (list_callback_data_t *)data;
char be_ds[MAXPATHLEN];
- char prop_buf[MAXPATHLEN];
- nvlist_t *userprops;
- nvlist_t *propval;
- char *prop_str = NULL;
- char *grub_default_bootfs = NULL;
+ char *open_ds = NULL;
+ char *rpool = NULL;
zfs_handle_t *zhp = NULL;
- zpool_handle_t *zphp = NULL;
int err = 0;
- rpool = zpool_get_name(zlp);
+ cb->zpool_name = rpool = (char *)zpool_get_name(zlp);
/*
* Generate string for the BE container dataset
*/
be_make_container_ds(rpool, be_container_ds,
sizeof (be_container_ds));
- be_make_root_ds(rpool, cb->be_name, be_ds, sizeof (be_ds));
/*
- * Check if main BE dataset exists
+ * If a BE name was specified we use it's root dataset in place of
+ * the container dataset. This is because we only want to collect
+ * the information for the specified BE.
*/
- if (!zfs_dataset_exists(g_zfs, be_ds,
+ if (cb->be_name != NULL) {
+ /*
+ * Generate string for the BE root dataset
+ */
+ be_make_root_ds(rpool, cb->be_name, be_ds, sizeof (be_ds));
+ open_ds = be_ds;
+ } else {
+ open_ds = be_container_ds;
+ }
+
+ /*
+ * Check if the dataset exists
+ */
+ if (!zfs_dataset_exists(g_zfs, open_ds,
ZFS_TYPE_FILESYSTEM)) {
/*
- * No BE root dataset exists in this pool,
- * no valid BE's in this pool. Try the
- * next zpool.
+ * The specified dataset does not exist in this pool or
+ * there are no valid BE's in this pool. Try the next zpool.
*/
zpool_close(zlp);
return (BE_SUCCESS);
}
- if ((zhp = zfs_open(g_zfs, be_ds, ZFS_TYPE_FILESYSTEM)) == NULL) {
+ if ((zhp = zfs_open(g_zfs, open_ds, ZFS_TYPE_FILESYSTEM)) == NULL) {
be_print_err(gettext("be_get_list_callback: failed to open "
- "BE root dataset %s: %s\n"), be_ds,
+ "the BE dataset %s: %s\n"), open_ds,
libzfs_error_description(g_zfs));
err = zfs_err_to_be_err(g_zfs);
zpool_close(zlp);
return (err);
}
- cb->be_nodes_head = cb->be_nodes = calloc(1, sizeof (be_node_list_t));
- if (cb->be_nodes == NULL) {
- ZFS_CLOSE(zhp);
- zpool_close(zlp);
- be_print_err(gettext("be_get_list_callback: memory allocation "
- "failed\n"));
- return (BE_ERR_NOMEM);
+ if (cb->be_nodes_head == NULL) {
+ if ((cb->be_nodes_head = be_list_alloc(&err,
+ sizeof (be_node_list_t))) == NULL) {
+ ZFS_CLOSE(zhp);
+ zpool_close(zlp);
+ return (err);
+ }
+ cb->be_nodes = cb->be_nodes_head;
}
- cb->be_nodes->be_root_ds = strdup(be_ds);
-
- cb->be_nodes->be_node_name = strdup(cb->be_name);
- if (strncmp(cb->be_name, cb->current_be, MAXPATHLEN) == 0)
- cb->be_nodes->be_active = B_TRUE;
- else
- cb->be_nodes->be_active = B_FALSE;
-
- cb->be_nodes->be_rpool = strdup(rpool);
-
- zphp = zpool_open(g_zfs, rpool);
- cb->be_nodes->be_space_used = zfs_prop_get_int(zhp, ZFS_PROP_USED);
- zpool_get_prop(zphp, ZPOOL_PROP_BOOTFS, prop_buf, ZFS_MAXPROPLEN,
- NULL);
- if (be_has_grub() &&
- (be_default_grub_bootfs(rpool, &grub_default_bootfs) == 0) &&
- grub_default_bootfs != NULL)
- if (strcmp(grub_default_bootfs, be_ds) == 0)
- cb->be_nodes->be_active_on_boot = B_TRUE;
- else
- cb->be_nodes->be_active_on_boot = B_FALSE;
- else if (prop_buf != NULL && strcmp(prop_buf, be_ds) == 0)
- cb->be_nodes->be_active_on_boot = B_TRUE;
- else
- cb->be_nodes->be_active_on_boot = B_FALSE;
- free(grub_default_bootfs);
/*
- * If the dataset is mounted use the mount point
- * returned from the zfs_is_mounted call. If the
- * dataset is not mounted then pull the mount
- * point information out of the zfs properties.
+ * If a BE name was specified we iterate through the datasets
+ * and snapshots for this BE only. Otherwise we will iterate
+ * through the next level of datasets to find all the BE's
+ * within the pool
*/
- cb->be_nodes->be_mounted = zfs_is_mounted(zhp,
- &(cb->be_nodes->be_mntpt));
- if (!cb->be_nodes->be_mounted) {
- err = zfs_prop_get(zhp, ZFS_PROP_MOUNTPOINT, prop_buf,
- ZFS_MAXPROPLEN, NULL, NULL, 0, B_FALSE);
- if (err)
- cb->be_nodes->be_mntpt = NULL;
- else
- cb->be_nodes->be_mntpt = strdup(prop_buf);
- }
- cb->be_nodes->be_node_creation = (time_t)zfs_prop_get_int(zhp,
- ZFS_PROP_CREATION);
-
- /* Get all user properties used for libbe */
- if ((userprops = zfs_get_user_props(zhp)) == NULL) {
- cb->be_nodes->be_policy_type = strdup(be_default_policy());
- } else {
- if (nvlist_lookup_nvlist(userprops, BE_POLICY_PROPERTY,
- &propval) != 0 || propval == NULL) {
- cb->be_nodes->be_policy_type =
- strdup(be_default_policy());
- } else {
- verify(nvlist_lookup_string(propval, ZPROP_VALUE,
- &prop_str) == 0);
- if (prop_str == NULL || strcmp(prop_str, "-") == 0 ||
- strcmp(prop_str, "") == 0)
- cb->be_nodes->be_policy_type =
- strdup(be_default_policy());
- else
- cb->be_nodes->be_policy_type = strdup(prop_str);
+ if (cb->be_name != NULL) {
+ if ((err = be_get_node_data(zhp, cb->be_nodes, cb->be_name,
+ rpool, cb->current_be, be_ds)) != 0) {
+ ZFS_CLOSE(zhp);
+ zpool_close(zlp);
+ return (err);
}
-
- if (nvlist_lookup_nvlist(userprops, BE_UUID_PROPERTY, &propval)
- == 0 && nvlist_lookup_string(propval, ZPROP_VALUE,
- &prop_str) == 0) {
- cb->be_nodes->be_uuid_str = strdup(prop_str);
- }
+ err = zfs_iter_snapshots(zhp, be_add_children_callback, cb);
}
- zpool_close(zphp);
- /*
- * Increment the dataset counter to include the root dataset
- * of the BE.
- */
- cb->be_nodes->be_node_num_datasets++;
-
- /*
- * iterate through the next level of datasets to find the BE's
- * within the pool
- */
- err = zfs_iter_children(zhp, be_add_children_callback, cb);
+ if (err == 0)
+ err = zfs_iter_filesystems(zhp, be_add_children_callback, cb);
ZFS_CLOSE(zhp);
zpool_close(zlp);
return (err);
@@ -517,539 +383,108 @@
be_add_children_callback(zfs_handle_t *zhp, void *data)
{
list_callback_data_t *cb = (list_callback_data_t *)data;
- char prop_buf[ZFS_MAXPROPLEN];
char *str = NULL, *ds_path = NULL;
- nvlist_t *propval;
- nvlist_t *userprops;
- char *prop_str = NULL;
- char *grub_default_bootfs = NULL;
int err = 0;
ds_path = str = strdup(zfs_get_name(zhp));
- if (strncmp(str + strlen(be_container_ds), "@", 1) == 0) {
- /*
- * This is a snapshot created by the installer and not a BE.
- */
- ZFS_CLOSE(zhp);
- return (BE_SUCCESS);
- }
/*
* get past the end of the container dataset plus the trailing "/"
*/
str = str + (strlen(be_container_ds) + 1);
- if (strchr(str, '/') == NULL && strchr(str, '@') == NULL) {
- if (cb->be_nodes->be_node_name == NULL) {
- zpool_handle_t *zphp = zpool_open(g_zfs, rpool);
- zfs_handle_t *zfshp = zfs_open(g_zfs, ds_path,
- ZFS_TYPE_DATASET);
- cb->be_nodes->be_node_name = strdup(str);
- if (strncmp(str, cb->current_be, MAXPATHLEN) == 0)
- cb->be_nodes->be_active = B_TRUE;
- else
- cb->be_nodes->be_active = B_FALSE;
- cb->be_nodes->be_root_ds = strdup(ds_path);
- cb->be_nodes->be_rpool = strdup(rpool);
- cb->be_nodes->be_space_used = zfs_prop_get_int(zfshp,
- ZFS_PROP_USED);
- zpool_get_prop(zphp, ZPOOL_PROP_BOOTFS, prop_buf,
- ZFS_MAXPROPLEN, NULL);
- if (be_has_grub() &&
- (be_default_grub_bootfs(rpool,
- &grub_default_bootfs) == 0) &&
- grub_default_bootfs != NULL) {
- if (strcmp(grub_default_bootfs, ds_path) == 0)
- cb->be_nodes->be_active_on_boot =
- B_TRUE;
- else
- cb->be_nodes->be_active_on_boot =
- B_FALSE;
- } else if (prop_buf != NULL &&
- strcmp(prop_buf, ds_path) == 0)
- cb->be_nodes->be_active_on_boot = B_TRUE;
- else
- cb->be_nodes->be_active_on_boot =
- B_FALSE;
- free(grub_default_bootfs);
- /*
- * If the dataset is mounted use the mount point
- * returned from the zfs_is_mounted call. If the
- * dataset is not mounted then pull the mount
- * point information out of the zfs properties.
- */
- cb->be_nodes->be_mounted = zfs_is_mounted(zfshp,
- &(cb->be_nodes->be_mntpt));
- if (!cb->be_nodes->be_mounted) {
- err = zfs_prop_get(zfshp, ZFS_PROP_MOUNTPOINT,
- prop_buf, ZFS_MAXPROPLEN, NULL, NULL, 0,
- B_FALSE);
- if (err)
- cb->be_nodes->be_mntpt = NULL;
- else
- cb->be_nodes->be_mntpt =
- strdup(prop_buf);
+ if (zfs_get_type(zhp) == ZFS_TYPE_SNAPSHOT) {
+ be_snapshot_list_t *snapshots = NULL;
+ if (cb->be_nodes->be_node_snapshots == NULL) {
+ if ((cb->be_nodes->be_node_snapshots =
+ be_list_alloc(&err, sizeof (be_snapshot_list_t)))
+ == NULL || err != 0) {
+ ZFS_CLOSE(zhp);
+ return (err);
}
- cb->be_nodes->be_node_creation =
- (time_t)zfs_prop_get_int(zfshp,
- ZFS_PROP_CREATION);
-
- /* Get all user properties used for libbe */
- if ((userprops = zfs_get_user_props(zfshp)) == NULL) {
- cb->be_nodes->be_policy_type =
- strdup(be_default_policy());
- } else {
- if (nvlist_lookup_nvlist(userprops,
- BE_POLICY_PROPERTY, &propval) != 0 ||
- propval == NULL) {
- cb->be_nodes->be_policy_type =
- strdup(be_default_policy());
- } else {
- verify(nvlist_lookup_string(propval,
- ZPROP_VALUE, &prop_str) == 0);
- if (prop_str == NULL ||
- strcmp(prop_str, "-") == 0 ||
- strcmp(prop_str, "") == 0)
- cb->be_nodes->be_policy_type =
- strdup(be_default_policy());
- else
- cb->be_nodes->be_policy_type =
- strdup(prop_str);
+ cb->be_nodes->be_node_snapshots->be_next_snapshot =
+ NULL;
+ snapshots = cb->be_nodes->be_node_snapshots;
+ } else {
+ for (snapshots = cb->be_nodes->be_node_snapshots;
+ snapshots != NULL;
+ snapshots = snapshots->be_next_snapshot) {
+ if (snapshots->be_next_snapshot != NULL)
+ continue;
+ /*
+ * We're at the end of the list add the
+ * new snapshot.
+ */
+ if ((snapshots->be_next_snapshot =
+ be_list_alloc(&err,
+ sizeof (be_snapshot_list_t))) == NULL ||
+ err != 0) {
+ ZFS_CLOSE(zhp);
+ return (err);
}
-
- if (nvlist_lookup_nvlist(userprops,
- BE_UUID_PROPERTY, &propval) == 0 &&
- nvlist_lookup_string(propval,
- ZPROP_VALUE, &prop_str) == 0) {
- cb->be_nodes->be_uuid_str =
- strdup(prop_str);
- }
-
+ snapshots = snapshots->be_next_snapshot;
+ snapshots->be_next_snapshot = NULL;
+ break;
}
-
- cb->be_nodes->be_node_num_datasets++;
- ZFS_CLOSE(zfshp);
- zpool_close(zphp);
- } else {
- zpool_handle_t *zphp = zpool_open(g_zfs, rpool);
- zfs_handle_t *zfshp = zfs_open(g_zfs, ds_path,
- ZFS_TYPE_DATASET);
- cb->be_nodes->be_next_node = calloc(1,
- sizeof (be_node_list_t));
- if (cb->be_nodes->be_next_node == NULL) {
+ }
+ if ((err = be_get_ss_data(zhp, str, snapshots,
+ cb->be_nodes)) != 0) {
+ ZFS_CLOSE(zhp);
+ return (err);
+ }
+ } else if (strchr(str, '/') == NULL) {
+ if (cb->be_nodes->be_node_name != NULL) {
+ if ((cb->be_nodes->be_next_node =
+ be_list_alloc(&err, sizeof (be_node_list_t))) ==
+ NULL || err != 0) {
ZFS_CLOSE(zhp);
- ZFS_CLOSE(zfshp);
- zpool_close(zphp);
- be_print_err(gettext(
- "be_add_children_callback: memory "
- "allocation failed\n"));
- return (BE_ERR_NOMEM);
+ return (err);
}
cb->be_nodes = cb->be_nodes->be_next_node;
cb->be_nodes->be_next_node = NULL;
- cb->be_nodes->be_node_name = strdup(str);
- if (strncmp(str, cb->current_be, MAXPATHLEN) == 0)
- cb->be_nodes->be_active = B_TRUE;
- else
- cb->be_nodes->be_active = B_FALSE;
- cb->be_nodes->be_root_ds = strdup(ds_path);
- cb->be_nodes->be_rpool = strdup(rpool);
- cb->be_nodes->be_space_used = zfs_prop_get_int(zfshp,
- ZFS_PROP_USED);
- zpool_get_prop(zphp, ZPOOL_PROP_BOOTFS, prop_buf,
- ZFS_MAXPROPLEN, NULL);
- if (be_has_grub() &&
- (be_default_grub_bootfs(rpool,
- &grub_default_bootfs) == 0) &&
- grub_default_bootfs != NULL) {
- if (strcmp(grub_default_bootfs, ds_path) == 0)
- cb->be_nodes->be_active_on_boot
- = B_TRUE;
- else
- cb->be_nodes->be_active_on_boot
- = B_FALSE;
- } else if (prop_buf != NULL &&
- strcmp(prop_buf, ds_path) == 0)
- cb->be_nodes->be_active_on_boot =
- B_TRUE;
- else
- cb->be_nodes->be_active_on_boot =
- B_FALSE;
- free(grub_default_bootfs);
- /*
- * If the dataset is mounted use the mount point
- * returned from the zfs_is_mounted call. If the
- * dataset is not mounted then pull the mount
- * point information out of the zfs properties.
- */
- cb->be_nodes->be_mounted = zfs_is_mounted(zfshp,
- &(cb->be_nodes->be_mntpt));
- if (!cb->be_nodes->be_mounted) {
- err = zfs_prop_get(zfshp, ZFS_PROP_MOUNTPOINT,
- prop_buf, ZFS_MAXPROPLEN, NULL, NULL, 0,
- B_FALSE);
- if (err)
- cb->be_nodes->be_mntpt = NULL;
- else
- cb->be_nodes->be_mntpt =
- strdup(prop_buf);
- }
- cb->be_nodes->be_node_creation =
- (time_t)zfs_prop_get_int(zfshp,
- ZFS_PROP_CREATION);
-
- /* Get all user properties used for libbe */
- if ((userprops = zfs_get_user_props(zfshp)) == NULL) {
- cb->be_nodes->be_policy_type =
- strdup(be_default_policy());
- } else {
- if (nvlist_lookup_nvlist(userprops,
- BE_POLICY_PROPERTY, &propval) != 0 ||
- propval == NULL) {
- cb->be_nodes->be_policy_type =
- strdup(be_default_policy());
- } else {
- verify(nvlist_lookup_string(propval,
- ZPROP_VALUE, &prop_str) == 0);
- if (prop_str == NULL || strcmp(prop_str,
- "-") == 0 || strcmp(prop_str,
- "") == 0)
- cb->be_nodes->be_policy_type =
- strdup(be_default_policy());
- else
- cb->be_nodes->be_policy_type =
- strdup(prop_str);
- }
-
- if (nvlist_lookup_nvlist(userprops,
- BE_UUID_PROPERTY, &propval) == 0 &&
- nvlist_lookup_string(propval,
- ZPROP_VALUE, &prop_str) == 0) {
- cb->be_nodes->be_uuid_str =
- strdup(prop_str);
- }
-
- }
-
- cb->be_nodes->be_node_num_datasets++;
- ZFS_CLOSE(zfshp);
- zpool_close(zphp);
+ }
+ if ((err = be_get_node_data(zhp, cb->be_nodes, str,
+ cb->zpool_name, cb->current_be, ds_path)) != 0) {
+ ZFS_CLOSE(zhp);
+ return (err);
}
- } else if (strchr(str, '/') != NULL && strchr(str, '@') == NULL) {
+ } else if (strchr(str, '/') != NULL) {
+ be_dataset_list_t *datasets = NULL;
if (cb->be_nodes->be_node_datasets == NULL) {
- zfs_handle_t *zfshp = zfs_open(g_zfs, ds_path,
- ZFS_TYPE_DATASET);
- cb->be_nodes->be_node_datasets = calloc(1,
- sizeof (be_dataset_list_t));
- if (cb->be_nodes->be_node_datasets == NULL) {
+ if ((cb->be_nodes->be_node_datasets =
+ be_list_alloc(&err, sizeof (be_dataset_list_t)))
+ == NULL || err != 0) {
ZFS_CLOSE(zhp);
- ZFS_CLOSE(zfshp);
- be_print_err(gettext(
- "be_add_children_callback: memory "
- "allocation failed\n"));
- return (BE_ERR_NOMEM);
- }
- cb->be_nodes->be_node_datasets->be_dataset_name =
- strdup(str);
- cb->be_nodes->be_node_datasets->be_ds_space_used =
- zfs_prop_get_int(zfshp, ZFS_PROP_USED);
- /*
- * If the dataset is mounted use the mount point
- * returned from the zfs_is_mounted call. If the
- * dataset is not mounted then pull the mount
- * point information out of the zfs properties.
- */
- cb->be_nodes->be_node_datasets->be_ds_mounted =
- zfs_is_mounted(zfshp,
- &(cb->be_nodes->be_node_datasets->be_ds_mntpt));
- if (!cb->be_nodes->be_node_datasets->be_ds_mounted) {
- err = zfs_prop_get(zfshp, ZFS_PROP_MOUNTPOINT,
- prop_buf, ZFS_MAXPROPLEN, NULL, NULL, 0,
- B_FALSE);
- if (err)
- cb->be_nodes->be_node_datasets->be_ds_mntpt =
- NULL;
- else
- cb->be_nodes->be_node_datasets->be_ds_mntpt =
- strdup(prop_buf);
+ return (err);
}
- cb->be_nodes->be_node_datasets->be_ds_creation =
- (time_t)zfs_prop_get_int(zfshp, ZFS_PROP_CREATION);
-
- /*
- * Get the user property used for the libbe
- * cleaup policy
- */
- if ((userprops = zfs_get_user_props(zfshp)) == NULL) {
- cb->be_nodes->be_node_datasets->be_ds_plcy_type =
- strdup(cb->be_nodes->be_policy_type);
- } else {
- if (nvlist_lookup_nvlist(userprops,
- BE_POLICY_PROPERTY, &propval) != 0 ||
- propval == NULL) {
- cb->be_nodes->be_node_datasets->be_ds_plcy_type =
- strdup(cb->be_nodes->be_policy_type);
- } else {
- verify(nvlist_lookup_string(propval,
- ZPROP_VALUE, &prop_str) == 0);
- if (prop_str == NULL ||
- strcmp(prop_str, "-") == 0 ||
- strcmp(prop_str, "") == 0)
- cb->be_nodes->be_node_datasets->be_ds_plcy_type
- = strdup(cb->be_nodes->be_policy_type);
- else
- cb->be_nodes->be_node_datasets->be_ds_plcy_type
- = strdup(prop_str);
- }
- }
-
- cb->be_nodes->be_node_datasets->be_next_dataset =
- NULL;
- cb->be_nodes->be_node_num_datasets++;
- ZFS_CLOSE(zfshp);
- } else if (strcmp(
- cb->be_nodes->be_node_datasets->be_dataset_name,
- str) != 0) {
- be_dataset_list_t *datasets =
- cb->be_nodes->be_node_datasets;
- while (datasets != NULL) {
- if (strcmp(datasets->be_dataset_name, str) ==
- 0) {
- /*
- * We already have this dataset, move
- * on to the next one.
- */
- datasets = datasets->be_next_dataset;
+ cb->be_nodes->be_node_datasets->be_next_dataset = NULL;
+ datasets = cb->be_nodes->be_node_datasets;
+ } else {
+ for (datasets = cb->be_nodes->be_node_datasets;
+ datasets != NULL;
+ datasets = datasets->be_next_dataset) {
+ if (datasets->be_next_dataset != NULL)
continue;
- } else if (datasets->be_next_dataset == NULL) {
- /*
- * We're at the end of the list add
- * the new dataset.
- */
- zfs_handle_t *zfshp = zfs_open(g_zfs,
- ds_path, ZFS_TYPE_DATASET);
- datasets->be_next_dataset = calloc(1,
- sizeof (be_dataset_list_t));
- if (datasets->be_next_dataset ==
- NULL) {
- ZFS_CLOSE(zhp);
- ZFS_CLOSE(zfshp);
- be_print_err(gettext(
- "be_add_children_callback: "
- "memory allocation "
- "failed\n"));
- return (BE_ERR_NOMEM);
- }
- datasets = datasets->be_next_dataset;
- datasets->be_dataset_name = strdup(str);
- datasets->be_ds_space_used =
- zfs_prop_get_int(zfshp,
- ZFS_PROP_USED);
- /*
- * If the dataset is mounted use
- * the mount point returned from the
- * zfs_is_mounted call. If the
- * dataset is not mounted then pull
- * the mount point information out
- * of the zfs properties.
- */
- datasets->be_ds_mounted =
- zfs_is_mounted(zfshp,
- &(datasets->be_ds_mntpt));
- if (!datasets->be_ds_mounted) {
- err = zfs_prop_get(zfshp,
- ZFS_PROP_MOUNTPOINT,
- prop_buf, ZFS_MAXPROPLEN,
- NULL, NULL, 0, B_FALSE);
- if (err)
- datasets->be_ds_mntpt =
- NULL;
- else
- datasets->be_ds_mntpt =
- strdup(prop_buf);
- }
- datasets->be_ds_creation =
- (time_t)zfs_prop_get_int(zfshp,
- ZFS_PROP_CREATION);
-
- /*
- * Get the user properties used for
- * the libbe cleanup policy.
- */
- if ((userprops = zfs_get_user_props(
- zfshp)) == NULL) {
- datasets->be_ds_plcy_type =
- strdup(
- cb->be_nodes->be_policy_type);
- } else {
- if (nvlist_lookup_nvlist(
- userprops,
- BE_POLICY_PROPERTY,
- &propval) != 0 ||
- propval == NULL) {
- datasets->be_ds_plcy_type =
- strdup(
- cb->be_nodes->be_policy_type);
- } else {
- verify(nvlist_lookup_string(
- propval, ZPROP_VALUE,
- &prop_str) == 0);
- if (prop_str == NULL ||
- strcmp(prop_str, "-")
- == 0 || strcmp(prop_str,
- "") == 0)
- datasets->be_ds_plcy_type =
- strdup(
- cb->be_nodes->be_policy_type);
- else
- datasets->be_ds_plcy_type =
- strdup(prop_str);
- }
- }
- cb->be_nodes->be_node_num_datasets++;
- datasets->be_next_dataset = NULL;
- ZFS_CLOSE(zfshp);
+ /*
+ * We're at the end of the list add
+ * the new dataset.
+ */
+ if ((datasets->be_next_dataset =
+ be_list_alloc(&err,
+ sizeof (be_dataset_list_t)))
+ == NULL || err != 0) {
+ ZFS_CLOSE(zhp);
+ return (err);
}
datasets = datasets->be_next_dataset;
+ datasets->be_next_dataset = NULL;
+ break;
}
}
- } else {
- if (cb->be_nodes->be_node_snapshots == NULL) {
- uint64_t space_used;
- zfs_handle_t *zfshp;
- zfshp = zfs_open(g_zfs, ds_path, ZFS_TYPE_SNAPSHOT);
- cb->be_nodes->be_node_snapshots =
- calloc(1, sizeof (be_snapshot_list_t));
- if (cb->be_nodes->be_node_snapshots == NULL) {
- ZFS_CLOSE(zhp);
- ZFS_CLOSE(zfshp);
- be_print_err(gettext(
- "be_add_children_callback: memory "
- "allocation failed\n"));
- return (BE_ERR_NOMEM);
- }
- cb->be_nodes->be_node_snapshots->be_snapshot_name =
- strdup(str);
- cb->be_nodes->be_node_snapshots->be_snapshot_creation
- = (time_t)zfs_prop_get_int(zfshp,
- ZFS_PROP_CREATION);
-
- /*
- * Try to get this snapshot's cleanup policy from its
- * user properties first. If not there, use default
- * cleanup policy.
- */
- if ((userprops = zfs_get_user_props(zfshp)) != NULL &&
- nvlist_lookup_nvlist(userprops, BE_POLICY_PROPERTY,
- &propval) == 0 && nvlist_lookup_string(propval,
- ZPROP_VALUE, &prop_str) == 0) {
- cb->be_nodes->be_node_snapshots->be_snapshot_type =
- strdup(prop_str);
- } else {
- cb->be_nodes->be_node_snapshots->be_snapshot_type =
- strdup(be_default_policy());
- }
-
- space_used = zfs_prop_get_int(zfshp, ZFS_PROP_USED);
- if ((err = zfs_err_to_be_err(g_zfs)) != 0) {
- ZFS_CLOSE(zhp);
- ZFS_CLOSE(zfshp);
- be_print_err(gettext(
- "be_add_children_callback: get space "
- "used failed (%d)\n"), err);
- return (err);
- }
- cb->be_nodes->be_node_snapshots->be_snapshot_space_used
- = space_used;
- cb->be_nodes->be_node_snapshots->be_next_snapshot =
- NULL;
- cb->be_nodes->be_node_num_snapshots++;
- ZFS_CLOSE(zfshp);
- } else if (
- strcmp(cb->be_nodes->be_node_snapshots->be_snapshot_name,
- str) != 0) {
- be_snapshot_list_t *snapshots =
- cb->be_nodes->be_node_snapshots;
- while (snapshots != NULL) {
- if (strcmp(snapshots->be_snapshot_name,
- str) == 0) {
- /*
- * We already have this snapshot
- * move on
- */
- snapshots = snapshots->be_next_snapshot;
- continue;
- } else if (snapshots->be_next_snapshot ==
- NULL) {
- uint64_t space_used;
- zfs_handle_t *zfshp;
-
- /*
- * We're at the end of the list add the
- * new snapshot.
- */
- zfshp = zfs_open(g_zfs, ds_path,
- ZFS_TYPE_SNAPSHOT);
- snapshots->be_next_snapshot = calloc(1,
- sizeof (be_snapshot_list_t));
- if (snapshots->be_next_snapshot ==
- NULL) {
- ZFS_CLOSE(zhp);
- ZFS_CLOSE(zfshp);
- be_print_err(gettext(
- "be_add_children_callback: "
- "memory allocation "
- "failed\n"));
- return (BE_ERR_NOMEM);
- }
- snapshots = snapshots->be_next_snapshot;
- snapshots->be_snapshot_name =
- strdup(str);
- snapshots->be_snapshot_creation =
- (time_t)zfs_prop_get_int(zfshp,
- ZFS_PROP_CREATION);
-
- /*
- * Try to get this snapshot's cleanup
- * policy from its user properties
- * first. If not there, use default
- * cleanup policy.
- */
- if ((userprops =
- zfs_get_user_props(zfshp))
- != NULL &&
- nvlist_lookup_nvlist(userprops,
- BE_POLICY_PROPERTY, &propval)
- == 0 &&
- nvlist_lookup_string(propval,
- ZPROP_VALUE, &prop_str) == 0) {
- snapshots->be_snapshot_type =
- strdup(prop_str);
- } else {
- snapshots->be_snapshot_type =
- strdup(be_default_policy());
- }
-
- space_used = zfs_prop_get_int(zfshp,
- ZFS_PROP_USED);
- if ((err = zfs_err_to_be_err(g_zfs)) !=
- BE_SUCCESS) {
- ZFS_CLOSE(zhp);
- ZFS_CLOSE(zfshp);
- be_print_err(gettext(
- "be_add_children_callback: "
- "get space used failed "
- "(%d)\n"), err);
- return (err);
- }
- snapshots->be_snapshot_space_used =
- space_used;
- cb->be_nodes->be_node_num_snapshots++;
- snapshots->be_next_snapshot = NULL;
- ZFS_CLOSE(zfshp);
- }
- snapshots = snapshots->be_next_snapshot;
- }
+ if ((err = be_get_ds_data(zhp, str,
+ datasets, cb->be_nodes)) != 0) {
+ ZFS_CLOSE(zhp);
+ return (err);
}
}
err = zfs_iter_children(zhp, be_add_children_callback, cb);
@@ -1234,3 +669,381 @@
return (-1);
return (strcmp(p->be_dataset_name, q->be_dataset_name));
}
+
+/*
+ * Function: be_get_node_data
+ * Description: Helper function used to collect all the information to fill
+ * in the be_node_list structure to be returned by be_list.
+ * Parameters:
+ * zhp - Handle to the root dataset for the BE whose information
+ * we're collecting.
+ * be_node - a pointer to the node structure we're filling in.
+ * be_name - The BE name of the node whose information we're
+ * collecting.
+ * current_be - the name of the currently active BE.
+ * be_ds - The dataset name for the BE.
+ *
+ * Returns:
+ * 0 - Success
+ * be_errno_t - Failure
+ * Scope:
+ * Private
+ */
+static int
+be_get_node_data(
+ zfs_handle_t *zhp,
+ be_node_list_t *be_node,
+ char *be_name,
+ const char *rpool,
+ char *current_be,
+ char *be_ds)
+{
+ char prop_buf[MAXPATHLEN];
+ nvlist_t *userprops = NULL;
+ nvlist_t *propval = NULL;
+ char *prop_str = NULL;
+ char *grub_default_bootfs = NULL;
+ zpool_handle_t *zphp = NULL;
+ int err = 0;
+
+ if (be_node == NULL || be_name == NULL || current_be == NULL ||
+ be_ds == NULL) {
+ be_print_err(gettext("be_get_node_data: invalid arguments, "
+ "can not be NULL\n"));
+ return (BE_ERR_INVAL);
+ }
+
+ errno = 0;
+
+ be_node->be_root_ds = strdup(be_ds);
+ if ((err = errno) != 0 || be_node->be_root_ds == NULL) {
+ be_print_err(gettext("be_get_node_data: failed to "
+ "copy root dataset name\n"));
+ return (errno_to_be_err(err));
+ }
+
+ be_node->be_node_name = strdup(be_name);
+ if ((err = errno) != 0 || be_node->be_node_name == NULL) {
+ be_print_err(gettext("be_get_node_data: failed to "
+ "copy BE name\n"));
+ return (errno_to_be_err(err));
+ }
+ if (strncmp(be_name, current_be, MAXPATHLEN) == 0)
+ be_node->be_active = B_TRUE;
+ else
+ be_node->be_active = B_FALSE;
+
+ be_node->be_rpool = strdup(rpool);
+ if ((err = errno) != 0 || be_node->be_rpool == NULL) {
+ be_print_err(gettext("be_get_node_data: failed to "
+ "copy root pool name\n"));
+ return (errno_to_be_err(err));
+ }
+
+ be_node->be_space_used = zfs_prop_get_int(zhp, ZFS_PROP_USED);
+ if ((err = zfs_err_to_be_err(g_zfs)) != 0) {
+ be_print_err(gettext(
+ "be_get_node_data: get space used failed (%d)\n"), err);
+ return (err);
+ }
+
+ if ((zphp = zpool_open(g_zfs, rpool)) == NULL) {
+ be_print_err(gettext("be_get_node_data: failed to open pool "
+ "(%s): %s\n"), rpool, libzfs_error_description(g_zfs));
+ err = zfs_err_to_be_err(g_zfs);
+ return (err);
+ }
+
+ zpool_get_prop(zphp, ZPOOL_PROP_BOOTFS, prop_buf, ZFS_MAXPROPLEN,
+ NULL);
+ if (be_has_grub() &&
+ (be_default_grub_bootfs(rpool, &grub_default_bootfs) == 0) &&
+ grub_default_bootfs != NULL)
+ if (strcmp(grub_default_bootfs, be_ds) == 0)
+ be_node->be_active_on_boot = B_TRUE;
+ else
+ be_node->be_active_on_boot = B_FALSE;
+ else if (prop_buf != NULL && strcmp(prop_buf, be_ds) == 0)
+ be_node->be_active_on_boot = B_TRUE;
+ else
+ be_node->be_active_on_boot = B_FALSE;
+ free(grub_default_bootfs);
+ zpool_close(zphp);
+
+ /*
+ * If the dataset is mounted use the mount point
+ * returned from the zfs_is_mounted call. If the
+ * dataset is not mounted then pull the mount
+ * point information out of the zfs properties.
+ */
+ be_node->be_mounted = zfs_is_mounted(zhp,
+ &(be_node->be_mntpt));
+ if (!be_node->be_mounted) {
+ err = zfs_prop_get(zhp, ZFS_PROP_MOUNTPOINT, prop_buf,
+ ZFS_MAXPROPLEN, NULL, NULL, 0, B_FALSE);
+ if (err)
+ be_node->be_mntpt = NULL;
+ else
+ be_node->be_mntpt = strdup(prop_buf);
+ }
+
+ be_node->be_node_creation = (time_t)zfs_prop_get_int(zhp,
+ ZFS_PROP_CREATION);
+ if ((err = zfs_err_to_be_err(g_zfs)) != 0) {
+ be_print_err(gettext(
+ "be_get_node_data: get creation time failed (%d)\n"), err);
+ return (err);
+ }
+
+ /* Get all user properties used for libbe */
+ if ((userprops = zfs_get_user_props(zhp)) == NULL) {
+ be_node->be_policy_type = strdup(be_default_policy());
+ } else {
+ if (nvlist_lookup_nvlist(userprops, BE_POLICY_PROPERTY,
+ &propval) != 0 || propval == NULL) {
+ be_node->be_policy_type =
+ strdup(be_default_policy());
+ } else {
+ verify(nvlist_lookup_string(propval, ZPROP_VALUE,
+ &prop_str) == 0);
+ if (prop_str == NULL || strcmp(prop_str, "-") == 0 ||
+ strcmp(prop_str, "") == 0)
+ be_node->be_policy_type =
+ strdup(be_default_policy());
+ else
+ be_node->be_policy_type = strdup(prop_str);
+ }
+
+ if (nvlist_lookup_nvlist(userprops, BE_UUID_PROPERTY, &propval)
+ == 0 && nvlist_lookup_string(propval, ZPROP_VALUE,
+ &prop_str) == 0) {
+ be_node->be_uuid_str = strdup(prop_str);
+ }
+ }
+
+ /*
+ * Increment the dataset counter to include the root dataset
+ * of the BE.
+ */
+ be_node->be_node_num_datasets++;
+
+ return (err);
+}
+
+/*
+ * Function: be_get_ds_data
+ * Description: Helper function used by be_add_children_callback to collect
+ * the dataset related information that will be returned by
+ * be_list.
+ * Parameters:
+ * zhp - Handle to the zfs dataset whose information we're
+ * collecting.
+ * name - The name of the dataset we're processing.
+ * dataset - A pointer to the be_dataset_list structure
+ * we're filling in.
+ * node - The node structure that this dataset belongs to.
+ * Return:
+ * 0 - Success
+ * be_errno_t - Failure
+ * Scope:
+ * Private
+ */
+static int
+be_get_ds_data(
+ zfs_handle_t *zfshp,
+ char *name,
+ be_dataset_list_t *dataset,
+ be_node_list_t *node)
+{
+ char prop_buf[ZFS_MAXPROPLEN];
+ nvlist_t *propval = NULL;
+ nvlist_t *userprops = NULL;
+ char *prop_str = NULL;
+ int err = 0;
+
+ if (zfshp == NULL || name == NULL || dataset == NULL || node == NULL) {
+ be_print_err(gettext("be_get_ds_data: invalid arguments, "
+ "can not be NULL\n"));
+ return (BE_ERR_INVAL);
+ }
+
+ errno = 0;
+
+ dataset->be_dataset_name = strdup(name);
+ if ((err = errno) != 0) {
+ be_print_err(gettext("be_get_ds_data: failed to copy "
+ "dataset name\n"));
+ return (errno_to_be_err(err));
+ }
+
+ dataset->be_ds_space_used = zfs_prop_get_int(zfshp, ZFS_PROP_USED);
+ if ((err = zfs_err_to_be_err(g_zfs)) != 0) {
+ be_print_err(gettext(
+ "be_get_ds_data: get space used failed (%d)\n"), err);
+ return (err);
+ }
+
+ /*
+ * If the dataset is mounted use the mount point
+ * returned from the zfs_is_mounted call. If the
+ * dataset is not mounted then pull the mount
+ * point information out of the zfs properties.
+ */
+ if (!(dataset->be_ds_mounted = zfs_is_mounted(zfshp,
+ &(dataset->be_ds_mntpt)))) {
+ err = zfs_prop_get(zfshp, ZFS_PROP_MOUNTPOINT,
+ prop_buf, ZFS_MAXPROPLEN, NULL, NULL, 0,
+ B_FALSE);
+ if (err != 0)
+ dataset->be_ds_mntpt = NULL;
+ else
+ dataset->be_ds_mntpt = strdup(prop_buf);
+ }
+ dataset->be_ds_creation =
+ (time_t)zfs_prop_get_int(zfshp, ZFS_PROP_CREATION);
+ if ((err = zfs_err_to_be_err(g_zfs)) != 0) {
+ be_print_err(gettext(
+ "be_get_ds_data: get creation time failed (%d)\n"), err);
+ return (err);
+ }
+
+ /*
+ * Get the user property used for the libbe
+ * cleaup policy
+ */
+ if ((userprops = zfs_get_user_props(zfshp)) == NULL) {
+ dataset->be_ds_plcy_type =
+ strdup(node->be_policy_type);
+ } else {
+ if (nvlist_lookup_nvlist(userprops,
+ BE_POLICY_PROPERTY, &propval) != 0 ||
+ propval == NULL) {
+ dataset->be_ds_plcy_type =
+ strdup(node->be_policy_type);
+ } else {
+ verify(nvlist_lookup_string(propval,
+ ZPROP_VALUE, &prop_str) == 0);
+ if (prop_str == NULL ||
+ strcmp(prop_str, "-") == 0 ||
+ strcmp(prop_str, "") == 0)
+ dataset->be_ds_plcy_type
+ = strdup(node->be_policy_type);
+ else
+ dataset->be_ds_plcy_type = strdup(prop_str);
+ }
+ }
+
+ node->be_node_num_datasets++;
+ return (err);
+}
+
+/*
+ * Function: be_get_ss_data
+ * Description: Helper function used by be_add_children_callback to collect
+ * the dataset related information that will be returned by
+ * be_list.
+ * Parameters:
+ * zhp - Handle to the zfs snapshot whose information we're
+ * collecting.
+ * name - The name of the snapshot we're processing.
+ * shapshot - A pointer to the be_snapshot_list structure
+ * we're filling in.
+ * node - The node structure that this snapshot belongs to.
+ * Returns:
+ * 0 - Success
+ * be_errno_t - Failure
+ * Scope:
+ * Private
+ */
+static int
+be_get_ss_data(
+ zfs_handle_t *zfshp,
+ char *name,
+ be_snapshot_list_t *snapshot,
+ be_node_list_t *node)
+{
+ nvlist_t *propval = NULL;
+ nvlist_t *userprops = NULL;
+ char *prop_str = NULL;
+ int err = 0;
+
+ if (zfshp == NULL || name == NULL || snapshot == NULL || node == NULL) {
+ be_print_err(gettext("be_get_ss_data: invalid arguments, "
+ "can not be NULL\n"));
+ return (BE_ERR_INVAL);
+ }
+
+ errno = 0;
+
+ snapshot->be_snapshot_name = strdup(name);
+ if ((err = errno) != 0) {
+ be_print_err(gettext("be_get_ss_data: failed to copy name\n"));
+ return (errno_to_be_err(err));
+ }
+
+ snapshot->be_snapshot_creation = (time_t)zfs_prop_get_int(zfshp,
+ ZFS_PROP_CREATION);
+ if ((err = zfs_err_to_be_err(g_zfs)) != 0) {
+ be_print_err(gettext(
+ "be_get_ss_data: get creation "
+ "time failed (%d)\n"), err);
+ return (err);
+ }
+
+ /*
+ * Try to get this snapshot's cleanup policy from its
+ * user properties first. If not there, use default
+ * cleanup policy.
+ */
+ if ((userprops = zfs_get_user_props(zfshp)) != NULL &&
+ nvlist_lookup_nvlist(userprops, BE_POLICY_PROPERTY,
+ &propval) == 0 && nvlist_lookup_string(propval,
+ ZPROP_VALUE, &prop_str) == 0) {
+ snapshot->be_snapshot_type =
+ strdup(prop_str);
+ } else {
+ snapshot->be_snapshot_type =
+ strdup(be_default_policy());
+ }
+
+ snapshot->be_snapshot_space_used = zfs_prop_get_int(zfshp,
+ ZFS_PROP_USED);
+ if ((err = zfs_err_to_be_err(g_zfs)) != 0) {
+ be_print_err(gettext(
+ "be_get_ss_data: get space "
+ "used failed (%d)\n"), err);
+ return (err);
+ }
+ node->be_node_num_snapshots++;
+ return (err);
+}
+
+/*
+ * Function: be_list_alloc
+ * Description: Helper function used to allocate memory for the various
+ * sructures that make up a BE node.
+ * Parameters:
+ * err - Used to return any errors encountered.
+ * BE_SUCCESS - Success
+ * BE_ERR_NOMEM - Allocation failure
+ * size - The size of memory to allocate.
+ * Returns:
+ * Success - A pointer to the allocated memory
+ * Failure - NULL
+ * Scope:
+ * Private
+ */
+static void*
+be_list_alloc(int *err, size_t size)
+{
+ void *bep = NULL;
+
+ bep = calloc(1, size);
+ if (bep == NULL) {
+ be_print_err(gettext("be_list_alloc: memory "
+ "allocation failed\n"));
+ *err = BE_ERR_NOMEM;
+ }
+ *err = BE_SUCCESS;
+ return (bep);
+}