usr/src/cmd/zfs/zfs_iter.c
changeset 2676 5cee47eddab6
parent 2379 0ff8239b1e93
child 3635 63e2169c1249
equal deleted inserted replaced
2675:54d99ec6d12d 2676:5cee47eddab6
    57 typedef struct callback_data {
    57 typedef struct callback_data {
    58 	uu_avl_t	*cb_avl;
    58 	uu_avl_t	*cb_avl;
    59 	int		cb_recurse;
    59 	int		cb_recurse;
    60 	zfs_type_t	cb_types;
    60 	zfs_type_t	cb_types;
    61 	zfs_sort_column_t *cb_sortcol;
    61 	zfs_sort_column_t *cb_sortcol;
       
    62 	zfs_proplist_t	**cb_proplist;
    62 } callback_data_t;
    63 } callback_data_t;
    63 
    64 
    64 uu_avl_pool_t *avl_pool;
    65 uu_avl_pool_t *avl_pool;
    65 
    66 
    66 /*
    67 /*
    82 
    83 
    83 		node->zn_handle = zhp;
    84 		node->zn_handle = zhp;
    84 		uu_avl_node_init(node, &node->zn_avlnode, avl_pool);
    85 		uu_avl_node_init(node, &node->zn_avlnode, avl_pool);
    85 		if (uu_avl_find(cb->cb_avl, node, cb->cb_sortcol,
    86 		if (uu_avl_find(cb->cb_avl, node, cb->cb_sortcol,
    86 		    &idx) == NULL) {
    87 		    &idx) == NULL) {
       
    88 			if (cb->cb_proplist &&
       
    89 			    zfs_expand_proplist(zhp, cb->cb_proplist) != 0) {
       
    90 				free(node);
       
    91 				return (-1);
       
    92 			}
    87 			uu_avl_insert(cb->cb_avl, node, idx);
    93 			uu_avl_insert(cb->cb_avl, node, idx);
    88 			dontclose = 1;
    94 			dontclose = 1;
    89 		} else {
    95 		} else {
    90 			free(node);
    96 			free(node);
    91 		}
    97 		}
   103 		zfs_close(zhp);
   109 		zfs_close(zhp);
   104 
   110 
   105 	return (0);
   111 	return (0);
   106 }
   112 }
   107 
   113 
   108 void
   114 int
   109 zfs_add_sort_column(zfs_sort_column_t **sc, zfs_prop_t prop,
   115 zfs_add_sort_column(zfs_sort_column_t **sc, const char *name,
   110     boolean_t reverse)
   116     boolean_t reverse)
   111 {
   117 {
   112 	zfs_sort_column_t *col;
   118 	zfs_sort_column_t *col;
       
   119 	zfs_prop_t prop;
       
   120 
       
   121 	if ((prop = zfs_name_to_prop(name)) == ZFS_PROP_INVAL &&
       
   122 	    !zfs_prop_user(name))
       
   123 		return (-1);
   113 
   124 
   114 	col = safe_malloc(sizeof (zfs_sort_column_t));
   125 	col = safe_malloc(sizeof (zfs_sort_column_t));
   115 
   126 
   116 	col->sc_prop = prop;
   127 	col->sc_prop = prop;
   117 	col->sc_reverse = reverse;
   128 	col->sc_reverse = reverse;
   118 	col->sc_next = NULL;
   129 	if (prop == ZFS_PROP_INVAL) {
       
   130 		col->sc_user_prop = safe_malloc(strlen(name) + 1);
       
   131 		(void) strcpy(col->sc_user_prop, name);
       
   132 	}
   119 
   133 
   120 	if (*sc == NULL) {
   134 	if (*sc == NULL) {
   121 		col->sc_last = col;
   135 		col->sc_last = col;
   122 		*sc = col;
   136 		*sc = col;
   123 	} else {
   137 	} else {
   124 		(*sc)->sc_last->sc_next = col;
   138 		(*sc)->sc_last->sc_next = col;
   125 		(*sc)->sc_last = col;
   139 		(*sc)->sc_last = col;
   126 	}
   140 	}
       
   141 
       
   142 	return (0);
   127 }
   143 }
   128 
   144 
   129 void
   145 void
   130 zfs_free_sort_columns(zfs_sort_column_t *sc)
   146 zfs_free_sort_columns(zfs_sort_column_t *sc)
   131 {
   147 {
   132 	zfs_sort_column_t *col;
   148 	zfs_sort_column_t *col;
   133 
   149 
   134 	while (sc != NULL) {
   150 	while (sc != NULL) {
   135 		col = sc->sc_next;
   151 		col = sc->sc_next;
       
   152 		free(sc->sc_user_prop);
   136 		free(sc);
   153 		free(sc);
   137 		sc = col;
   154 		sc = col;
   138 	}
   155 	}
   139 }
   156 }
   140 
   157 
   212 	zfs_handle_t *r = ((zfs_node_t *)rarg)->zn_handle;
   229 	zfs_handle_t *r = ((zfs_node_t *)rarg)->zn_handle;
   213 	zfs_sort_column_t *sc = (zfs_sort_column_t *)data;
   230 	zfs_sort_column_t *sc = (zfs_sort_column_t *)data;
   214 	zfs_sort_column_t *psc;
   231 	zfs_sort_column_t *psc;
   215 
   232 
   216 	for (psc = sc; psc != NULL; psc = psc->sc_next) {
   233 	for (psc = sc; psc != NULL; psc = psc->sc_next) {
   217 		char lstr[ZFS_MAXPROPLEN], rstr[ZFS_MAXPROPLEN];
   234 		char lbuf[ZFS_MAXPROPLEN], rbuf[ZFS_MAXPROPLEN];
       
   235 		char *lstr, *rstr;
   218 		uint64_t lnum, rnum;
   236 		uint64_t lnum, rnum;
   219 		int lvalid, rvalid;
   237 		boolean_t lvalid, rvalid;
   220 		int ret = 0;
   238 		int ret = 0;
   221 
   239 
   222 		if (zfs_prop_is_string(psc->sc_prop)) {
   240 		/*
   223 			lvalid = zfs_prop_get(l, psc->sc_prop, lstr,
   241 		 * We group the checks below the generic code.  If 'lstr' and
   224 			    sizeof (lstr), NULL, NULL, 0, B_TRUE);
   242 		 * 'rstr' are non-NULL, then we do a string based comparison.
   225 			rvalid = zfs_prop_get(r, psc->sc_prop, rstr,
   243 		 * Otherwise, we compare 'lnum' and 'rnum'.
   226 			    sizeof (rstr), NULL, NULL, 0, B_TRUE);
   244 		 */
   227 
   245 		lstr = rstr = NULL;
   228 			if ((lvalid == -1) && (rvalid == -1))
   246 		if (psc->sc_prop == ZFS_PROP_INVAL) {
   229 				continue;
   247 			nvlist_t *luser, *ruser;
   230 			if (lvalid == -1)
   248 			nvlist_t *lval, *rval;
   231 				return (1);
   249 
   232 			else if (rvalid == -1)
   250 			luser = zfs_get_user_props(l);
   233 				return (-1);
   251 			ruser = zfs_get_user_props(r);
   234 
   252 
   235 			ret = strcmp(lstr, rstr);
   253 			lvalid = (nvlist_lookup_nvlist(luser,
       
   254 			    psc->sc_user_prop, &lval) == 0);
       
   255 			rvalid = (nvlist_lookup_nvlist(ruser,
       
   256 			    psc->sc_user_prop, &rval) == 0);
       
   257 
       
   258 			if (lvalid)
       
   259 				verify(nvlist_lookup_string(lval,
       
   260 				    ZFS_PROP_VALUE, &lstr) == 0);
       
   261 			if (rvalid)
       
   262 				verify(nvlist_lookup_string(rval,
       
   263 				    ZFS_PROP_VALUE, &rstr) == 0);
       
   264 
       
   265 		} else if (zfs_prop_is_string(psc->sc_prop)) {
       
   266 			lvalid = (zfs_prop_get(l, psc->sc_prop, lbuf,
       
   267 			    sizeof (lbuf), NULL, NULL, 0, B_TRUE) == 0);
       
   268 			rvalid = (zfs_prop_get(r, psc->sc_prop, rbuf,
       
   269 			    sizeof (rbuf), NULL, NULL, 0, B_TRUE) == 0);
       
   270 
       
   271 			lstr = lbuf;
       
   272 			rstr = rbuf;
   236 		} else {
   273 		} else {
   237 			lvalid = zfs_prop_valid_for_type(psc->sc_prop,
   274 			lvalid = zfs_prop_valid_for_type(psc->sc_prop,
   238 			    zfs_get_type(l));
   275 			    zfs_get_type(l));
   239 			rvalid = zfs_prop_valid_for_type(psc->sc_prop,
   276 			rvalid = zfs_prop_valid_for_type(psc->sc_prop,
   240 			    zfs_get_type(r));
   277 			    zfs_get_type(r));
   241 
   278 
   242 			if (!lvalid && !rvalid)
   279 			if (lvalid)
   243 				continue;
   280 				(void) zfs_prop_get_numeric(l, psc->sc_prop,
   244 			else if (!lvalid)
   281 				    &lnum, NULL, NULL, 0);
   245 				return (1);
   282 			if (rvalid)
   246 			else if (!rvalid)
   283 				(void) zfs_prop_get_numeric(r, psc->sc_prop,
   247 				return (-1);
   284 				    &rnum, NULL, NULL, 0);
   248 
   285 		}
   249 			(void) zfs_prop_get_numeric(l, psc->sc_prop, &lnum,
   286 
   250 			    NULL, NULL, 0);
   287 		if (!lvalid && !rvalid)
   251 			(void) zfs_prop_get_numeric(r, psc->sc_prop, &rnum,
   288 			continue;
   252 			    NULL, NULL, 0);
   289 		else if (!lvalid)
   253 
   290 			return (1);
   254 			if (lnum < rnum)
   291 		else if (!rvalid)
   255 				ret = -1;
   292 			return (-1);
   256 			else if (lnum > rnum)
   293 
   257 				ret = 1;
   294 		if (lstr)
   258 		}
   295 			ret = strcmp(lstr, rstr);
       
   296 		if (lnum < rnum)
       
   297 			ret = -1;
       
   298 		else if (lnum > rnum)
       
   299 			ret = 1;
   259 
   300 
   260 		if (ret != 0) {
   301 		if (ret != 0) {
   261 			if (psc->sc_reverse == B_TRUE)
   302 			if (psc->sc_reverse == B_TRUE)
   262 				ret = (ret < 0) ? 1 : -1;
   303 				ret = (ret < 0) ? 1 : -1;
   263 			return (ret);
   304 			return (ret);
   267 	return (zfs_compare(larg, rarg, NULL));
   308 	return (zfs_compare(larg, rarg, NULL));
   268 }
   309 }
   269 
   310 
   270 int
   311 int
   271 zfs_for_each(int argc, char **argv, boolean_t recurse, zfs_type_t types,
   312 zfs_for_each(int argc, char **argv, boolean_t recurse, zfs_type_t types,
   272     zfs_sort_column_t *sortcol, zfs_iter_f callback, void *data)
   313     zfs_sort_column_t *sortcol, zfs_proplist_t **proplist, zfs_iter_f callback,
       
   314     void *data)
   273 {
   315 {
   274 	callback_data_t cb;
   316 	callback_data_t cb;
   275 	int ret = 0;
   317 	int ret = 0;
   276 	zfs_node_t *node;
   318 	zfs_node_t *node;
   277 	uu_avl_walk_t *walk;
   319 	uu_avl_walk_t *walk;
   285 		exit(1);
   327 		exit(1);
   286 	}
   328 	}
   287 
   329 
   288 	cb.cb_sortcol = sortcol;
   330 	cb.cb_sortcol = sortcol;
   289 	cb.cb_recurse = recurse;
   331 	cb.cb_recurse = recurse;
       
   332 	cb.cb_proplist = proplist;
   290 	cb.cb_types = types;
   333 	cb.cb_types = types;
   291 	if ((cb.cb_avl = uu_avl_create(avl_pool, NULL, UU_DEFAULT)) == NULL) {
   334 	if ((cb.cb_avl = uu_avl_create(avl_pool, NULL, UU_DEFAULT)) == NULL) {
   292 		(void) fprintf(stderr,
   335 		(void) fprintf(stderr,
   293 		    gettext("internal error: out of memory\n"));
   336 		    gettext("internal error: out of memory\n"));
   294 		exit(1);
   337 		exit(1);