usr/src/cmd/zfs/zfs_iter.c
changeset 2676 5cee47eddab6
parent 2379 0ff8239b1e93
child 3635 63e2169c1249
--- a/usr/src/cmd/zfs/zfs_iter.c	Mon Sep 04 19:32:13 2006 -0700
+++ b/usr/src/cmd/zfs/zfs_iter.c	Tue Sep 05 11:37:36 2006 -0700
@@ -59,6 +59,7 @@
 	int		cb_recurse;
 	zfs_type_t	cb_types;
 	zfs_sort_column_t *cb_sortcol;
+	zfs_proplist_t	**cb_proplist;
 } callback_data_t;
 
 uu_avl_pool_t *avl_pool;
@@ -84,6 +85,11 @@
 		uu_avl_node_init(node, &node->zn_avlnode, avl_pool);
 		if (uu_avl_find(cb->cb_avl, node, cb->cb_sortcol,
 		    &idx) == NULL) {
+			if (cb->cb_proplist &&
+			    zfs_expand_proplist(zhp, cb->cb_proplist) != 0) {
+				free(node);
+				return (-1);
+			}
 			uu_avl_insert(cb->cb_avl, node, idx);
 			dontclose = 1;
 		} else {
@@ -105,17 +111,25 @@
 	return (0);
 }
 
-void
-zfs_add_sort_column(zfs_sort_column_t **sc, zfs_prop_t prop,
+int
+zfs_add_sort_column(zfs_sort_column_t **sc, const char *name,
     boolean_t reverse)
 {
 	zfs_sort_column_t *col;
+	zfs_prop_t prop;
+
+	if ((prop = zfs_name_to_prop(name)) == ZFS_PROP_INVAL &&
+	    !zfs_prop_user(name))
+		return (-1);
 
 	col = safe_malloc(sizeof (zfs_sort_column_t));
 
 	col->sc_prop = prop;
 	col->sc_reverse = reverse;
-	col->sc_next = NULL;
+	if (prop == ZFS_PROP_INVAL) {
+		col->sc_user_prop = safe_malloc(strlen(name) + 1);
+		(void) strcpy(col->sc_user_prop, name);
+	}
 
 	if (*sc == NULL) {
 		col->sc_last = col;
@@ -124,6 +138,8 @@
 		(*sc)->sc_last->sc_next = col;
 		(*sc)->sc_last = col;
 	}
+
+	return (0);
 }
 
 void
@@ -133,6 +149,7 @@
 
 	while (sc != NULL) {
 		col = sc->sc_next;
+		free(sc->sc_user_prop);
 		free(sc);
 		sc = col;
 	}
@@ -214,48 +231,72 @@
 	zfs_sort_column_t *psc;
 
 	for (psc = sc; psc != NULL; psc = psc->sc_next) {
-		char lstr[ZFS_MAXPROPLEN], rstr[ZFS_MAXPROPLEN];
+		char lbuf[ZFS_MAXPROPLEN], rbuf[ZFS_MAXPROPLEN];
+		char *lstr, *rstr;
 		uint64_t lnum, rnum;
-		int lvalid, rvalid;
+		boolean_t lvalid, rvalid;
 		int ret = 0;
 
-		if (zfs_prop_is_string(psc->sc_prop)) {
-			lvalid = zfs_prop_get(l, psc->sc_prop, lstr,
-			    sizeof (lstr), NULL, NULL, 0, B_TRUE);
-			rvalid = zfs_prop_get(r, psc->sc_prop, rstr,
-			    sizeof (rstr), NULL, NULL, 0, B_TRUE);
+		/*
+		 * We group the checks below the generic code.  If 'lstr' and
+		 * 'rstr' are non-NULL, then we do a string based comparison.
+		 * Otherwise, we compare 'lnum' and 'rnum'.
+		 */
+		lstr = rstr = NULL;
+		if (psc->sc_prop == ZFS_PROP_INVAL) {
+			nvlist_t *luser, *ruser;
+			nvlist_t *lval, *rval;
+
+			luser = zfs_get_user_props(l);
+			ruser = zfs_get_user_props(r);
 
-			if ((lvalid == -1) && (rvalid == -1))
-				continue;
-			if (lvalid == -1)
-				return (1);
-			else if (rvalid == -1)
-				return (-1);
+			lvalid = (nvlist_lookup_nvlist(luser,
+			    psc->sc_user_prop, &lval) == 0);
+			rvalid = (nvlist_lookup_nvlist(ruser,
+			    psc->sc_user_prop, &rval) == 0);
 
-			ret = strcmp(lstr, rstr);
+			if (lvalid)
+				verify(nvlist_lookup_string(lval,
+				    ZFS_PROP_VALUE, &lstr) == 0);
+			if (rvalid)
+				verify(nvlist_lookup_string(rval,
+				    ZFS_PROP_VALUE, &rstr) == 0);
+
+		} else if (zfs_prop_is_string(psc->sc_prop)) {
+			lvalid = (zfs_prop_get(l, psc->sc_prop, lbuf,
+			    sizeof (lbuf), NULL, NULL, 0, B_TRUE) == 0);
+			rvalid = (zfs_prop_get(r, psc->sc_prop, rbuf,
+			    sizeof (rbuf), NULL, NULL, 0, B_TRUE) == 0);
+
+			lstr = lbuf;
+			rstr = rbuf;
 		} else {
 			lvalid = zfs_prop_valid_for_type(psc->sc_prop,
 			    zfs_get_type(l));
 			rvalid = zfs_prop_valid_for_type(psc->sc_prop,
 			    zfs_get_type(r));
 
-			if (!lvalid && !rvalid)
-				continue;
-			else if (!lvalid)
-				return (1);
-			else if (!rvalid)
-				return (-1);
+			if (lvalid)
+				(void) zfs_prop_get_numeric(l, psc->sc_prop,
+				    &lnum, NULL, NULL, 0);
+			if (rvalid)
+				(void) zfs_prop_get_numeric(r, psc->sc_prop,
+				    &rnum, NULL, NULL, 0);
+		}
 
-			(void) zfs_prop_get_numeric(l, psc->sc_prop, &lnum,
-			    NULL, NULL, 0);
-			(void) zfs_prop_get_numeric(r, psc->sc_prop, &rnum,
-			    NULL, NULL, 0);
+		if (!lvalid && !rvalid)
+			continue;
+		else if (!lvalid)
+			return (1);
+		else if (!rvalid)
+			return (-1);
 
-			if (lnum < rnum)
-				ret = -1;
-			else if (lnum > rnum)
-				ret = 1;
-		}
+		if (lstr)
+			ret = strcmp(lstr, rstr);
+		if (lnum < rnum)
+			ret = -1;
+		else if (lnum > rnum)
+			ret = 1;
 
 		if (ret != 0) {
 			if (psc->sc_reverse == B_TRUE)
@@ -269,7 +310,8 @@
 
 int
 zfs_for_each(int argc, char **argv, boolean_t recurse, zfs_type_t types,
-    zfs_sort_column_t *sortcol, zfs_iter_f callback, void *data)
+    zfs_sort_column_t *sortcol, zfs_proplist_t **proplist, zfs_iter_f callback,
+    void *data)
 {
 	callback_data_t cb;
 	int ret = 0;
@@ -287,6 +329,7 @@
 
 	cb.cb_sortcol = sortcol;
 	cb.cb_recurse = recurse;
+	cb.cb_proplist = proplist;
 	cb.cb_types = types;
 	if ((cb.cb_avl = uu_avl_create(avl_pool, NULL, UU_DEFAULT)) == NULL) {
 		(void) fprintf(stderr,