Print this page
5679 be_sort_list(): Possible null pointer dereference
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/lib/libbe/common/be_list.c
+++ new/usr/src/lib/libbe/common/be_list.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
↓ open down ↓ |
18 lines elided |
↑ open up ↑ |
19 19 * CDDL HEADER END
20 20 */
21 21
22 22 /*
23 23 * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
24 24 */
25 25
26 26 /*
27 27 * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
28 28 * Copyright 2015 Toomas Soome <tsoome@me.com>
29 + * Copyright 2015 Gary Mills
29 30 */
30 31
31 32 #include <assert.h>
32 33 #include <libintl.h>
33 34 #include <libnvpair.h>
34 35 #include <libzfs.h>
35 36 #include <stdio.h>
36 37 #include <stdlib.h>
37 38 #include <string.h>
38 39 #include <strings.h>
39 40 #include <sys/types.h>
40 41 #include <sys/stat.h>
41 42 #include <unistd.h>
42 43 #include <errno.h>
43 44
44 45 #include <libbe.h>
45 46 #include <libbe_priv.h>
46 47
47 48 /*
48 49 * Callback data used for zfs_iter calls.
49 50 */
50 51 typedef struct list_callback_data {
51 52 char *zpool_name;
52 53 char *be_name;
53 54 be_node_list_t *be_nodes_head;
54 55 be_node_list_t *be_nodes;
55 56 char current_be[MAXPATHLEN];
56 57 } list_callback_data_t;
57 58
58 59 /*
59 60 * Private function prototypes
↓ open down ↓ |
21 lines elided |
↑ open up ↑ |
60 61 */
61 62 static int be_add_children_callback(zfs_handle_t *zhp, void *data);
62 63 static int be_get_list_callback(zpool_handle_t *, void *);
63 64 static int be_get_node_data(zfs_handle_t *, be_node_list_t *, char *,
64 65 const char *, char *, char *);
65 66 static int be_get_zone_node_data(be_node_list_t *, char *);
66 67 static int be_get_ds_data(zfs_handle_t *, char *, be_dataset_list_t *,
67 68 be_node_list_t *);
68 69 static int be_get_ss_data(zfs_handle_t *, char *, be_snapshot_list_t *,
69 70 be_node_list_t *);
70 -static void be_sort_list(be_node_list_t **,
71 +static int be_sort_list(be_node_list_t **,
71 72 int (*)(const void *, const void *));
72 73 static int be_qsort_compare_BEs_name(const void *, const void *);
73 74 static int be_qsort_compare_BEs_name_rev(const void *, const void *);
74 75 static int be_qsort_compare_BEs_date(const void *, const void *);
75 76 static int be_qsort_compare_BEs_date_rev(const void *, const void *);
76 77 static int be_qsort_compare_BEs_space(const void *, const void *);
77 78 static int be_qsort_compare_BEs_space_rev(const void *, const void *);
78 79 static int be_qsort_compare_snapshots(const void *x, const void *y);
79 80 static int be_qsort_compare_datasets(const void *x, const void *y);
80 81 static void *be_list_alloc(int *, size_t);
81 82
82 83 /*
83 84 * Private data.
84 85 */
85 86 static char be_container_ds[MAXPATHLEN];
86 87 static boolean_t zone_be = B_FALSE;
87 88
88 89 /* ******************************************************************** */
89 90 /* Public Functions */
90 91 /* ******************************************************************** */
91 92
92 93 /*
93 94 * Function: be_list
94 95 * Description: Calls _be_list which finds all the BEs on the system and
95 96 * returns the datasets and snapshots belonging to each BE.
96 97 * Also data, such as dataset and snapshot properties,
97 98 * for each BE and their snapshots and datasets is
98 99 * returned. The data returned is as described in the
99 100 * be_dataset_list_t, be_snapshot_list_t and be_node_list_t
100 101 * structures.
101 102 * Parameters:
102 103 * be_name - The name of the BE to look up.
103 104 * If NULL a list of all BEs will be returned.
104 105 * be_nodes - A reference pointer to the list of BEs. The list
105 106 * structure will be allocated by _be_list and must
106 107 * be freed by a call to be_free_list. If there are no
107 108 * BEs found on the system this reference will be
108 109 * set to NULL.
109 110 * Return:
110 111 * BE_SUCCESS - Success
111 112 * be_errno_t - Failure
112 113 * Scope:
113 114 * Public
114 115 */
115 116 int
116 117 be_list(char *be_name, be_node_list_t **be_nodes)
117 118 {
118 119 int ret = BE_SUCCESS;
119 120
120 121 /* Initialize libzfs handle */
121 122 if (!be_zfs_init())
122 123 return (BE_ERR_INIT);
123 124
124 125 /* Validate be_name if its not NULL */
125 126 if (be_name != NULL) {
126 127 if (!be_valid_be_name(be_name)) {
127 128 be_print_err(gettext("be_list: "
128 129 "invalid BE name %s\n"), be_name);
129 130 return (BE_ERR_INVAL);
130 131 }
131 132 }
132 133
133 134 ret = _be_list(be_name, be_nodes);
134 135
135 136 be_zfs_fini();
↓ open down ↓ |
55 lines elided |
↑ open up ↑ |
136 137
137 138 return (ret);
138 139 }
139 140
140 141 /*
141 142 * Function: be_sort
142 143 * Description: Sort BE node list
143 144 * Parameters:
144 145 * pointer to address of list head
145 146 * sort order type
146 - * Returns:
147 - * nothing
147 + * Return:
148 + * BE_SUCCESS - Success
149 + * be_errno_t - Failure
148 150 * Side effect:
149 151 * node list sorted by name
150 152 * Scope:
151 153 * Public
152 154 */
153 -void
155 +int
154 156 be_sort(be_node_list_t **be_nodes, int order)
155 157 {
156 158 int (*compar)(const void *, const void *) = be_qsort_compare_BEs_date;
157 159
158 160 if (be_nodes == NULL)
159 - return;
161 + return (BE_ERR_INVAL);
160 162
161 163 switch (order) {
162 164 case BE_SORT_UNSPECIFIED:
163 165 case BE_SORT_DATE:
164 166 compar = be_qsort_compare_BEs_date;
165 167 break;
166 168 case BE_SORT_DATE_REV:
167 169 compar = be_qsort_compare_BEs_date_rev;
168 170 break;
169 171 case BE_SORT_NAME:
170 172 compar = be_qsort_compare_BEs_name;
171 173 break;
172 174 case BE_SORT_NAME_REV:
173 175 compar = be_qsort_compare_BEs_name_rev;
↓ open down ↓ |
4 lines elided |
↑ open up ↑ |
174 176 break;
175 177 case BE_SORT_SPACE:
176 178 compar = be_qsort_compare_BEs_space;
177 179 break;
178 180 case BE_SORT_SPACE_REV:
179 181 compar = be_qsort_compare_BEs_space_rev;
180 182 break;
181 183 default:
182 184 be_print_err(gettext("be_sort: invalid sort order %d\n"),
183 185 order);
184 - return;
186 + return (BE_ERR_INVAL);
185 187 }
186 188
187 - be_sort_list(be_nodes, compar);
189 + return (be_sort_list(be_nodes, compar));
188 190 }
189 191
190 192 /* ******************************************************************** */
191 193 /* Semi-Private Functions */
192 194 /* ******************************************************************** */
193 195
194 196 /*
195 197 * Function: _be_list
196 198 * Description: This does the actual work described in be_list.
197 199 * Parameters:
198 200 * be_name - The name of the BE to look up.
199 201 * If NULL a list of all BEs will be returned.
200 202 * be_nodes - A reference pointer to the list of BEs. The list
201 203 * structure will be allocated here and must
202 204 * be freed by a call to be_free_list. If there are no
203 205 * BEs found on the system this reference will be
204 206 * set to NULL.
205 207 * Return:
206 208 * BE_SUCCESS - Success
↓ open down ↓ |
9 lines elided |
↑ open up ↑ |
207 209 * be_errno_t - Failure
208 210 * Scope:
209 211 * Semi-private (library wide use only)
210 212 */
211 213 int
212 214 _be_list(char *be_name, be_node_list_t **be_nodes)
213 215 {
214 216 list_callback_data_t cb = { 0 };
215 217 be_transaction_data_t bt = { 0 };
216 218 int ret = BE_SUCCESS;
219 + int sret;
217 220 zpool_handle_t *zphp;
218 221 char *rpool = NULL;
219 222 struct be_defaults be_defaults;
220 223
221 224 if (be_nodes == NULL)
222 225 return (BE_ERR_INVAL);
223 226
224 227 be_get_defaults(&be_defaults);
225 228
226 229 if (be_find_current_be(&bt) != BE_SUCCESS) {
227 230 /*
228 231 * We were unable to find a currently booted BE which
229 232 * probably means that we're not booted in a BE envoronment.
230 233 * None of the BE's will be marked as the active BE.
231 234 */
232 235 (void) strcpy(cb.current_be, "-");
233 236 } else {
234 237 (void) strncpy(cb.current_be, bt.obe_name,
235 238 sizeof (cb.current_be));
236 239 rpool = bt.obe_zpool;
237 240 }
238 241
239 242 /*
240 243 * If be_name is NULL we'll look for all BE's on the system.
241 244 * If not then we will only return data for the specified BE.
242 245 */
243 246 if (be_name != NULL)
244 247 cb.be_name = strdup(be_name);
245 248
246 249 if (be_defaults.be_deflt_rpool_container && rpool != NULL) {
247 250 if ((zphp = zpool_open(g_zfs, rpool)) == NULL) {
248 251 be_print_err(gettext("be_list: failed to "
249 252 "open rpool (%s): %s\n"), rpool,
250 253 libzfs_error_description(g_zfs));
251 254 free(cb.be_name);
252 255 return (zfs_err_to_be_err(g_zfs));
253 256 }
254 257
255 258 ret = be_get_list_callback(zphp, &cb);
256 259 } else {
257 260 if ((zpool_iter(g_zfs, be_get_list_callback, &cb)) != 0) {
258 261 if (cb.be_nodes_head != NULL) {
259 262 be_free_list(cb.be_nodes_head);
260 263 cb.be_nodes_head = NULL;
261 264 cb.be_nodes = NULL;
262 265 }
263 266 ret = BE_ERR_BE_NOENT;
264 267 }
265 268 }
266 269
267 270 if (cb.be_nodes_head == NULL) {
268 271 if (be_name != NULL)
269 272 be_print_err(gettext("be_list: BE (%s) does not "
↓ open down ↓ |
43 lines elided |
↑ open up ↑ |
270 273 "exist\n"), be_name);
271 274 else
272 275 be_print_err(gettext("be_list: No BE's found\n"));
273 276 ret = BE_ERR_BE_NOENT;
274 277 }
275 278
276 279 *be_nodes = cb.be_nodes_head;
277 280
278 281 free(cb.be_name);
279 282
280 - be_sort(be_nodes, BE_SORT_DATE);
283 + sret = be_sort(be_nodes, BE_SORT_DATE);
281 284
282 - return (ret);
285 + return ((ret == BE_SUCCESS) ? sret : ret);
283 286 }
284 287
285 288 /*
286 289 * Function: be_free_list
287 290 * Description: Frees up all the data allocated for the list of BEs,
288 291 * datasets and snapshots returned by be_list.
289 292 * Parameters:
290 293 * be_node - be_nodes_t structure returned from call to be_list.
291 294 * Returns:
292 295 * none
293 296 * Scope:
294 297 * Semi-private (library wide use only)
295 298 */
296 299 void
297 300 be_free_list(be_node_list_t *be_nodes)
298 301 {
299 302 be_node_list_t *temp_node = NULL;
300 303 be_node_list_t *list = be_nodes;
301 304
302 305 while (list != NULL) {
303 306 be_dataset_list_t *datasets = list->be_node_datasets;
304 307 be_snapshot_list_t *snapshots = list->be_node_snapshots;
305 308
306 309 while (datasets != NULL) {
307 310 be_dataset_list_t *temp_ds = datasets;
308 311 datasets = datasets->be_next_dataset;
309 312 free(temp_ds->be_dataset_name);
310 313 free(temp_ds->be_ds_mntpt);
311 314 free(temp_ds->be_ds_plcy_type);
312 315 free(temp_ds);
313 316 }
314 317
315 318 while (snapshots != NULL) {
316 319 be_snapshot_list_t *temp_ss = snapshots;
317 320 snapshots = snapshots->be_next_snapshot;
318 321 free(temp_ss->be_snapshot_name);
319 322 free(temp_ss->be_snapshot_type);
320 323 free(temp_ss);
321 324 }
322 325
323 326 temp_node = list;
324 327 list = list->be_next_node;
325 328 free(temp_node->be_node_name);
326 329 free(temp_node->be_root_ds);
327 330 free(temp_node->be_rpool);
328 331 free(temp_node->be_mntpt);
329 332 free(temp_node->be_policy_type);
330 333 free(temp_node->be_uuid_str);
331 334 free(temp_node);
332 335 }
333 336 }
334 337
335 338 /*
336 339 * Function: be_get_zone_be_list
337 340 * Description: Finds all the BEs for this zone on the system.
338 341 * Parameters:
339 342 * zone_be_name - The name of the BE to look up.
340 343 * zone_be_container_ds - The dataset for the zone.
341 344 * zbe_nodes - A reference pointer to the list of BEs. The list
342 345 * structure will be allocated here and must
343 346 * be freed by a call to be_free_list. If there are no
344 347 * BEs found on the system this reference will be
345 348 * set to NULL.
346 349 * Return:
347 350 * BE_SUCCESS - Success
348 351 * be_errno_t - Failure
349 352 * Scope:
350 353 * Semi-private (library wide use only)
351 354 */
352 355 int
353 356 be_get_zone_be_list(
354 357 /* LINTED */
355 358 char *zone_be_name,
356 359 char *zone_be_container_ds,
357 360 be_node_list_t **zbe_nodes)
358 361 {
359 362 zfs_handle_t *zhp = NULL;
360 363 list_callback_data_t cb = { 0 };
361 364 int ret = BE_SUCCESS;
362 365
363 366 if (zbe_nodes == NULL)
364 367 return (BE_ERR_INVAL);
365 368
366 369 if (!zfs_dataset_exists(g_zfs, zone_be_container_ds,
367 370 ZFS_TYPE_FILESYSTEM)) {
368 371 return (BE_ERR_BE_NOENT);
369 372 }
370 373
371 374 zone_be = B_TRUE;
372 375
373 376 if ((zhp = zfs_open(g_zfs, zone_be_container_ds,
374 377 ZFS_TYPE_FILESYSTEM)) == NULL) {
375 378 be_print_err(gettext("be_get_zone_be_list: failed to open "
376 379 "the zone BE dataset %s: %s\n"), zone_be_container_ds,
377 380 libzfs_error_description(g_zfs));
378 381 ret = zfs_err_to_be_err(g_zfs);
379 382 goto cleanup;
380 383 }
381 384
382 385 (void) strcpy(be_container_ds, zone_be_container_ds);
383 386
384 387 if (cb.be_nodes_head == NULL) {
385 388 if ((cb.be_nodes_head = be_list_alloc(&ret,
386 389 sizeof (be_node_list_t))) == NULL) {
387 390 ZFS_CLOSE(zhp);
388 391 goto cleanup;
389 392 }
390 393 cb.be_nodes = cb.be_nodes_head;
391 394 }
392 395 if (ret == 0)
393 396 ret = zfs_iter_filesystems(zhp, be_add_children_callback, &cb);
394 397 ZFS_CLOSE(zhp);
395 398
396 399 *zbe_nodes = cb.be_nodes_head;
397 400
398 401 cleanup:
399 402 zone_be = B_FALSE;
400 403
401 404 return (ret);
402 405 }
403 406
404 407 /* ******************************************************************** */
405 408 /* Private Functions */
406 409 /* ******************************************************************** */
407 410
408 411 /*
409 412 * Function: be_get_list_callback
410 413 * Description: Callback function used by zfs_iter to look through all
411 414 * the pools on the system looking for BEs. If a BE name was
412 415 * specified only that BE's information will be collected and
413 416 * returned.
414 417 * Parameters:
415 418 * zlp - handle to the first zfs dataset. (provided by the
416 419 * zfs_iter_* call)
417 420 * data - pointer to the callback data and where we'll pass
418 421 * the BE information back.
419 422 * Returns:
420 423 * 0 - Success
421 424 * be_errno_t - Failure
422 425 * Scope:
423 426 * Private
424 427 */
425 428 static int
426 429 be_get_list_callback(zpool_handle_t *zlp, void *data)
427 430 {
428 431 list_callback_data_t *cb = (list_callback_data_t *)data;
429 432 char be_ds[MAXPATHLEN];
430 433 char *open_ds = NULL;
431 434 char *rpool = NULL;
432 435 zfs_handle_t *zhp = NULL;
433 436 int ret = 0;
434 437
435 438 cb->zpool_name = rpool = (char *)zpool_get_name(zlp);
436 439
437 440 /*
438 441 * Generate string for the BE container dataset
439 442 */
440 443 be_make_container_ds(rpool, be_container_ds,
441 444 sizeof (be_container_ds));
442 445
443 446 /*
444 447 * If a BE name was specified we use it's root dataset in place of
445 448 * the container dataset. This is because we only want to collect
446 449 * the information for the specified BE.
447 450 */
448 451 if (cb->be_name != NULL) {
449 452 if (!be_valid_be_name(cb->be_name))
450 453 return (BE_ERR_INVAL);
451 454 /*
452 455 * Generate string for the BE root dataset
453 456 */
454 457 be_make_root_ds(rpool, cb->be_name, be_ds, sizeof (be_ds));
455 458 open_ds = be_ds;
456 459 } else {
457 460 open_ds = be_container_ds;
458 461 }
459 462
460 463 /*
461 464 * Check if the dataset exists
462 465 */
463 466 if (!zfs_dataset_exists(g_zfs, open_ds,
464 467 ZFS_TYPE_FILESYSTEM)) {
465 468 /*
466 469 * The specified dataset does not exist in this pool or
467 470 * there are no valid BE's in this pool. Try the next zpool.
468 471 */
469 472 zpool_close(zlp);
470 473 return (0);
471 474 }
472 475
473 476 if ((zhp = zfs_open(g_zfs, open_ds, ZFS_TYPE_FILESYSTEM)) == NULL) {
474 477 be_print_err(gettext("be_get_list_callback: failed to open "
475 478 "the BE dataset %s: %s\n"), open_ds,
476 479 libzfs_error_description(g_zfs));
477 480 ret = zfs_err_to_be_err(g_zfs);
478 481 zpool_close(zlp);
479 482 return (ret);
480 483 }
481 484
482 485 /*
483 486 * If a BE name was specified we iterate through the datasets
484 487 * and snapshots for this BE only. Otherwise we will iterate
485 488 * through the next level of datasets to find all the BE's
486 489 * within the pool
487 490 */
488 491 if (cb->be_name != NULL) {
489 492 if (cb->be_nodes_head == NULL) {
490 493 if ((cb->be_nodes_head = be_list_alloc(&ret,
491 494 sizeof (be_node_list_t))) == NULL) {
492 495 ZFS_CLOSE(zhp);
493 496 zpool_close(zlp);
494 497 return (ret);
495 498 }
496 499 cb->be_nodes = cb->be_nodes_head;
497 500 }
498 501
499 502 if ((ret = be_get_node_data(zhp, cb->be_nodes, cb->be_name,
500 503 rpool, cb->current_be, be_ds)) != BE_SUCCESS) {
501 504 ZFS_CLOSE(zhp);
502 505 zpool_close(zlp);
503 506 return (ret);
504 507 }
505 508 ret = zfs_iter_snapshots(zhp, be_add_children_callback, cb);
506 509 }
507 510
508 511 if (ret == 0)
509 512 ret = zfs_iter_filesystems(zhp, be_add_children_callback, cb);
510 513 ZFS_CLOSE(zhp);
511 514
512 515 zpool_close(zlp);
513 516 return (ret);
514 517 }
515 518
516 519 /*
517 520 * Function: be_add_children_callback
518 521 * Description: Callback function used by zfs_iter to look through all
519 522 * the datasets and snapshots for each BE and add them to
520 523 * the lists of information to be passed back.
521 524 * Parameters:
522 525 * zhp - handle to the first zfs dataset. (provided by the
523 526 * zfs_iter_* call)
524 527 * data - pointer to the callback data and where we'll pass
525 528 * the BE information back.
526 529 * Returns:
527 530 * 0 - Success
528 531 * be_errno_t - Failure
529 532 * Scope:
530 533 * Private
531 534 */
532 535 static int
533 536 be_add_children_callback(zfs_handle_t *zhp, void *data)
534 537 {
535 538 list_callback_data_t *cb = (list_callback_data_t *)data;
536 539 char *str = NULL, *ds_path = NULL;
537 540 int ret = 0;
538 541 struct be_defaults be_defaults;
539 542
540 543 be_get_defaults(&be_defaults);
541 544
542 545 ds_path = str = strdup(zfs_get_name(zhp));
543 546
544 547 /*
545 548 * get past the end of the container dataset plus the trailing "/"
546 549 */
547 550 str = str + (strlen(be_container_ds) + 1);
548 551 if (be_defaults.be_deflt_rpool_container) {
549 552 /* just skip if invalid */
550 553 if (!be_valid_be_name(str))
551 554 return (BE_SUCCESS);
552 555 }
553 556
554 557 if (cb->be_nodes_head == NULL) {
555 558 if ((cb->be_nodes_head = be_list_alloc(&ret,
556 559 sizeof (be_node_list_t))) == NULL) {
557 560 ZFS_CLOSE(zhp);
558 561 return (ret);
559 562 }
560 563 cb->be_nodes = cb->be_nodes_head;
561 564 }
562 565
563 566 if (zfs_get_type(zhp) == ZFS_TYPE_SNAPSHOT && !zone_be) {
564 567 be_snapshot_list_t *snapshots = NULL;
565 568 if (cb->be_nodes->be_node_snapshots == NULL) {
566 569 if ((cb->be_nodes->be_node_snapshots =
567 570 be_list_alloc(&ret, sizeof (be_snapshot_list_t)))
568 571 == NULL || ret != BE_SUCCESS) {
569 572 ZFS_CLOSE(zhp);
570 573 return (ret);
571 574 }
572 575 cb->be_nodes->be_node_snapshots->be_next_snapshot =
573 576 NULL;
574 577 snapshots = cb->be_nodes->be_node_snapshots;
575 578 } else {
576 579 for (snapshots = cb->be_nodes->be_node_snapshots;
577 580 snapshots != NULL;
578 581 snapshots = snapshots->be_next_snapshot) {
579 582 if (snapshots->be_next_snapshot != NULL)
580 583 continue;
581 584 /*
582 585 * We're at the end of the list add the
583 586 * new snapshot.
584 587 */
585 588 if ((snapshots->be_next_snapshot =
586 589 be_list_alloc(&ret,
587 590 sizeof (be_snapshot_list_t))) == NULL ||
588 591 ret != BE_SUCCESS) {
589 592 ZFS_CLOSE(zhp);
590 593 return (ret);
591 594 }
592 595 snapshots = snapshots->be_next_snapshot;
593 596 snapshots->be_next_snapshot = NULL;
594 597 break;
595 598 }
596 599 }
597 600 if ((ret = be_get_ss_data(zhp, str, snapshots,
598 601 cb->be_nodes)) != BE_SUCCESS) {
599 602 ZFS_CLOSE(zhp);
600 603 return (ret);
601 604 }
602 605 } else if (strchr(str, '/') == NULL) {
603 606 if (cb->be_nodes->be_node_name != NULL) {
604 607 if ((cb->be_nodes->be_next_node =
605 608 be_list_alloc(&ret, sizeof (be_node_list_t))) ==
606 609 NULL || ret != BE_SUCCESS) {
607 610 ZFS_CLOSE(zhp);
608 611 return (ret);
609 612 }
610 613 cb->be_nodes = cb->be_nodes->be_next_node;
611 614 cb->be_nodes->be_next_node = NULL;
612 615 }
613 616
614 617 /*
615 618 * If this is a zone root dataset then we only need
616 619 * the name of the zone BE at this point. We grab that
617 620 * and return.
618 621 */
619 622 if (zone_be) {
620 623 ret = be_get_zone_node_data(cb->be_nodes, str);
621 624 ZFS_CLOSE(zhp);
622 625 return (ret);
623 626 }
624 627
625 628 if ((ret = be_get_node_data(zhp, cb->be_nodes, str,
626 629 cb->zpool_name, cb->current_be, ds_path)) != BE_SUCCESS) {
627 630 ZFS_CLOSE(zhp);
628 631 return (ret);
629 632 }
630 633 } else if (strchr(str, '/') != NULL && !zone_be) {
631 634 be_dataset_list_t *datasets = NULL;
632 635 if (cb->be_nodes->be_node_datasets == NULL) {
633 636 if ((cb->be_nodes->be_node_datasets =
634 637 be_list_alloc(&ret, sizeof (be_dataset_list_t)))
635 638 == NULL || ret != BE_SUCCESS) {
636 639 ZFS_CLOSE(zhp);
637 640 return (ret);
638 641 }
639 642 cb->be_nodes->be_node_datasets->be_next_dataset = NULL;
640 643 datasets = cb->be_nodes->be_node_datasets;
641 644 } else {
642 645 for (datasets = cb->be_nodes->be_node_datasets;
643 646 datasets != NULL;
644 647 datasets = datasets->be_next_dataset) {
645 648 if (datasets->be_next_dataset != NULL)
646 649 continue;
647 650 /*
648 651 * We're at the end of the list add
649 652 * the new dataset.
650 653 */
651 654 if ((datasets->be_next_dataset =
652 655 be_list_alloc(&ret,
653 656 sizeof (be_dataset_list_t)))
654 657 == NULL || ret != BE_SUCCESS) {
655 658 ZFS_CLOSE(zhp);
656 659 return (ret);
657 660 }
658 661 datasets = datasets->be_next_dataset;
659 662 datasets->be_next_dataset = NULL;
660 663 break;
661 664 }
662 665 }
663 666
664 667 if ((ret = be_get_ds_data(zhp, str,
665 668 datasets, cb->be_nodes)) != BE_SUCCESS) {
666 669 ZFS_CLOSE(zhp);
667 670 return (ret);
668 671 }
669 672 }
670 673 ret = zfs_iter_children(zhp, be_add_children_callback, cb);
671 674 if (ret != 0) {
672 675 be_print_err(gettext("be_add_children_callback: "
673 676 "encountered error: %s\n"),
674 677 libzfs_error_description(g_zfs));
675 678 ret = zfs_err_to_be_err(g_zfs);
676 679 }
↓ open down ↓ |
384 lines elided |
↑ open up ↑ |
677 680 ZFS_CLOSE(zhp);
678 681 return (ret);
679 682 }
680 683
681 684 /*
682 685 * Function: be_sort_list
683 686 * Description: Sort BE node list
684 687 * Parameters:
685 688 * pointer to address of list head
686 689 * compare function
687 - * Returns:
688 - * nothing
690 + * Return:
691 + * BE_SUCCESS - Success
692 + * be_errno_t - Failure
689 693 * Side effect:
690 694 * node list sorted by name
691 695 * Scope:
692 696 * Private
693 697 */
694 -static void
698 +static int
695 699 be_sort_list(be_node_list_t **pstart, int (*compar)(const void *, const void *))
696 700 {
701 + int ret = BE_SUCCESS;
697 702 size_t ibe, nbe;
698 703 be_node_list_t *p = NULL;
699 704 be_node_list_t **ptrlist = NULL;
705 + be_node_list_t **ptrtmp;
700 706
701 - if (pstart == NULL)
702 - return;
707 + if (pstart == NULL) /* Nothing to sort */
708 + return (BE_SUCCESS);
703 709 /* build array of linked list BE struct pointers */
704 710 for (p = *pstart, nbe = 0; p != NULL; nbe++, p = p->be_next_node) {
705 - ptrlist = realloc(ptrlist,
711 + ptrtmp = realloc(ptrlist,
706 712 sizeof (be_node_list_t *) * (nbe + 2));
713 + if (ptrtmp == NULL) { /* out of memory */
714 + be_print_err(gettext("be_sort_list: memory "
715 + "allocation failed\n"));
716 + ret = BE_ERR_NOMEM;
717 + goto free;
718 + }
719 + ptrlist = ptrtmp;
707 720 ptrlist[nbe] = p;
708 721 }
709 - if (nbe == 0)
710 - return;
722 + if (nbe == 0) /* Nothing to sort */
723 + return (BE_SUCCESS);
711 724 /* in-place list quicksort using qsort(3C) */
712 725 if (nbe > 1) /* no sort if less than 2 BEs */
713 726 qsort(ptrlist, nbe, sizeof (be_node_list_t *), compar);
714 727
715 728 ptrlist[nbe] = NULL; /* add linked list terminator */
716 729 *pstart = ptrlist[0]; /* set new linked list header */
717 730 /* for each BE in list */
718 731 for (ibe = 0; ibe < nbe; ibe++) {
719 732 size_t k, ns; /* subordinate index, count */
720 733
721 734 /* rewrite list pointer chain, including terminator */
722 735 ptrlist[ibe]->be_next_node = ptrlist[ibe + 1];
723 736 /* sort subordinate snapshots */
724 737 if (ptrlist[ibe]->be_node_num_snapshots > 1) {
725 738 const size_t nmax = ptrlist[ibe]->be_node_num_snapshots;
726 739 be_snapshot_list_t ** const slist =
727 740 malloc(sizeof (be_snapshot_list_t *) * (nmax + 1));
728 741 be_snapshot_list_t *p;
729 742
730 - if (slist == NULL)
743 + if (slist == NULL) {
744 + ret = BE_ERR_NOMEM;
731 745 continue;
746 + }
732 747 /* build array of linked list snapshot struct ptrs */
733 748 for (ns = 0, p = ptrlist[ibe]->be_node_snapshots;
734 749 ns < nmax && p != NULL;
735 750 ns++, p = p->be_next_snapshot) {
736 751 slist[ns] = p;
737 752 }
738 753 if (ns < 2)
739 754 goto end_snapshot;
740 755 slist[ns] = NULL; /* add terminator */
741 756 /* in-place list quicksort using qsort(3C) */
742 757 qsort(slist, ns, sizeof (be_snapshot_list_t *),
743 758 be_qsort_compare_snapshots);
744 759 /* rewrite list pointer chain, including terminator */
745 760 ptrlist[ibe]->be_node_snapshots = slist[0];
746 761 for (k = 0; k < ns; k++)
747 762 slist[k]->be_next_snapshot = slist[k + 1];
↓ open down ↓ |
6 lines elided |
↑ open up ↑ |
748 763 end_snapshot:
749 764 free(slist);
750 765 }
751 766 /* sort subordinate datasets */
752 767 if (ptrlist[ibe]->be_node_num_datasets > 1) {
753 768 const size_t nmax = ptrlist[ibe]->be_node_num_datasets;
754 769 be_dataset_list_t ** const slist =
755 770 malloc(sizeof (be_dataset_list_t *) * (nmax + 1));
756 771 be_dataset_list_t *p;
757 772
758 - if (slist == NULL)
773 + if (slist == NULL) {
774 + ret = BE_ERR_NOMEM;
759 775 continue;
776 + }
760 777 /* build array of linked list dataset struct ptrs */
761 778 for (ns = 0, p = ptrlist[ibe]->be_node_datasets;
762 779 ns < nmax && p != NULL;
763 780 ns++, p = p->be_next_dataset) {
764 781 slist[ns] = p;
765 782 }
766 783 if (ns < 2) /* subordinate datasets < 2 - no sort */
767 784 goto end_dataset;
768 785 slist[ns] = NULL; /* add terminator */
769 786 /* in-place list quicksort using qsort(3C) */
770 787 qsort(slist, ns, sizeof (be_dataset_list_t *),
771 788 be_qsort_compare_datasets);
↓ open down ↓ |
2 lines elided |
↑ open up ↑ |
772 789 /* rewrite list pointer chain, including terminator */
773 790 ptrlist[ibe]->be_node_datasets = slist[0];
774 791 for (k = 0; k < ns; k++)
775 792 slist[k]->be_next_dataset = slist[k + 1];
776 793 end_dataset:
777 794 free(slist);
778 795 }
779 796 }
780 797 free:
781 798 free(ptrlist);
799 + return (ret);
782 800 }
783 801
784 802 /*
785 803 * Function: be_qsort_compare_BEs_date
786 804 * Description: compare BE creation times for qsort(3C)
787 805 * will sort BE list from oldest to most recent
788 806 * Parameters:
789 807 * x,y - BEs with names to compare
790 808 * Returns:
791 809 * positive if x>y, negative if y>x, 0 if equal
792 810 * Scope:
793 811 * Private
794 812 */
795 813 static int
796 814 be_qsort_compare_BEs_date(const void *x, const void *y)
797 815 {
798 816 be_node_list_t *p = *(be_node_list_t **)x;
799 817 be_node_list_t *q = *(be_node_list_t **)y;
800 818
801 819 assert(p != NULL);
802 820 assert(q != NULL);
803 821
804 822 if (p->be_node_creation > q->be_node_creation)
805 823 return (1);
806 824 if (p->be_node_creation < q->be_node_creation)
807 825 return (-1);
808 826 return (0);
809 827 }
810 828
811 829 /*
812 830 * Function: be_qsort_compare_BEs_date_rev
813 831 * Description: compare BE creation times for qsort(3C)
814 832 * will sort BE list from recent to oldest
815 833 * Parameters:
816 834 * x,y - BEs with names to compare
817 835 * Returns:
818 836 * positive if y>x, negative if x>y, 0 if equal
819 837 * Scope:
820 838 * Private
821 839 */
822 840 static int
823 841 be_qsort_compare_BEs_date_rev(const void *x, const void *y)
824 842 {
825 843 return (be_qsort_compare_BEs_date(y, x));
826 844 }
827 845
828 846 /*
829 847 * Function: be_qsort_compare_BEs_name
830 848 * Description: lexical compare of BE names for qsort(3C)
831 849 * Parameters:
832 850 * x,y - BEs with names to compare
833 851 * Returns:
834 852 * positive if x>y, negative if y>x, 0 if equal
835 853 * Scope:
836 854 * Private
837 855 */
838 856 static int
839 857 be_qsort_compare_BEs_name(const void *x, const void *y)
840 858 {
841 859 be_node_list_t *p = *(be_node_list_t **)x;
842 860 be_node_list_t *q = *(be_node_list_t **)y;
843 861
844 862 assert(p != NULL);
845 863 assert(p->be_node_name != NULL);
846 864 assert(q != NULL);
847 865 assert(q->be_node_name != NULL);
848 866
849 867 return (strcmp(p->be_node_name, q->be_node_name));
850 868 }
851 869
852 870 /*
853 871 * Function: be_qsort_compare_BEs_name_rev
854 872 * Description: reverse lexical compare of BE names for qsort(3C)
855 873 * Parameters:
856 874 * x,y - BEs with names to compare
857 875 * Returns:
858 876 * positive if y>x, negative if x>y, 0 if equal
859 877 * Scope:
860 878 * Private
861 879 */
862 880 static int
863 881 be_qsort_compare_BEs_name_rev(const void *x, const void *y)
864 882 {
865 883 return (be_qsort_compare_BEs_name(y, x));
866 884 }
867 885
868 886 /*
869 887 * Function: be_qsort_compare_BEs_space
870 888 * Description: compare BE sizes for qsort(3C)
871 889 * will sort BE list in growing order
872 890 * Parameters:
873 891 * x,y - BEs with names to compare
874 892 * Returns:
875 893 * positive if x>y, negative if y>x, 0 if equal
876 894 * Scope:
877 895 * Private
878 896 */
879 897 static int
880 898 be_qsort_compare_BEs_space(const void *x, const void *y)
881 899 {
882 900 be_node_list_t *p = *(be_node_list_t **)x;
883 901 be_node_list_t *q = *(be_node_list_t **)y;
884 902
885 903 assert(p != NULL);
886 904 assert(q != NULL);
887 905
888 906 if (p->be_space_used > q->be_space_used)
889 907 return (1);
890 908 if (p->be_space_used < q->be_space_used)
891 909 return (-1);
892 910 return (0);
893 911 }
894 912
895 913 /*
896 914 * Function: be_qsort_compare_BEs_space_rev
897 915 * Description: compare BE sizes for qsort(3C)
898 916 * will sort BE list in shrinking
899 917 * Parameters:
900 918 * x,y - BEs with names to compare
901 919 * Returns:
902 920 * positive if y>x, negative if x>y, 0 if equal
903 921 * Scope:
904 922 * Private
905 923 */
906 924 static int
907 925 be_qsort_compare_BEs_space_rev(const void *x, const void *y)
908 926 {
909 927 return (be_qsort_compare_BEs_space(y, x));
910 928 }
911 929
912 930 /*
913 931 * Function: be_qsort_compare_snapshots
914 932 * Description: lexical compare of BE names for qsort(3C)
915 933 * Parameters:
916 934 * x,y - BE snapshots with names to compare
917 935 * Returns:
918 936 * positive if y>x, negative if x>y, 0 if equal
919 937 * Scope:
920 938 * Private
921 939 */
922 940 static int
923 941 be_qsort_compare_snapshots(const void *x, const void *y)
924 942 {
925 943 be_snapshot_list_t *p = *(be_snapshot_list_t **)x;
926 944 be_snapshot_list_t *q = *(be_snapshot_list_t **)y;
927 945
928 946 if (p == NULL || p->be_snapshot_name == NULL)
929 947 return (1);
930 948 if (q == NULL || q->be_snapshot_name == NULL)
931 949 return (-1);
932 950 return (strcmp(p->be_snapshot_name, q->be_snapshot_name));
933 951 }
934 952
935 953 /*
936 954 * Function: be_qsort_compare_datasets
937 955 * Description: lexical compare of dataset names for qsort(3C)
938 956 * Parameters:
939 957 * x,y - BE snapshots with names to compare
940 958 * Returns:
941 959 * positive if y>x, negative if x>y, 0 if equal
942 960 * Scope:
943 961 * Private
944 962 */
945 963 static int
946 964 be_qsort_compare_datasets(const void *x, const void *y)
947 965 {
948 966 be_dataset_list_t *p = *(be_dataset_list_t **)x;
949 967 be_dataset_list_t *q = *(be_dataset_list_t **)y;
950 968
951 969 if (p == NULL || p->be_dataset_name == NULL)
952 970 return (1);
953 971 if (q == NULL || q->be_dataset_name == NULL)
954 972 return (-1);
955 973 return (strcmp(p->be_dataset_name, q->be_dataset_name));
956 974 }
957 975
958 976 /*
959 977 * Function: be_get_node_data
960 978 * Description: Helper function used to collect all the information to fill
961 979 * in the be_node_list structure to be returned by be_list.
962 980 * Parameters:
963 981 * zhp - Handle to the root dataset for the BE whose information
964 982 * we're collecting.
965 983 * be_node - a pointer to the node structure we're filling in.
966 984 * be_name - The BE name of the node whose information we're
967 985 * collecting.
968 986 * current_be - the name of the currently active BE.
969 987 * be_ds - The dataset name for the BE.
970 988 *
971 989 * Returns:
972 990 * BE_SUCCESS - Success
973 991 * be_errno_t - Failure
974 992 * Scope:
975 993 * Private
976 994 */
977 995 static int
978 996 be_get_node_data(
979 997 zfs_handle_t *zhp,
980 998 be_node_list_t *be_node,
981 999 char *be_name,
982 1000 const char *rpool,
983 1001 char *current_be,
984 1002 char *be_ds)
985 1003 {
986 1004 char prop_buf[MAXPATHLEN];
987 1005 nvlist_t *userprops = NULL;
988 1006 nvlist_t *propval = NULL;
989 1007 nvlist_t *zone_propval = NULL;
990 1008 char *prop_str = NULL;
991 1009 char *zone_prop_str = NULL;
992 1010 char *grub_default_bootfs = NULL;
993 1011 zpool_handle_t *zphp = NULL;
994 1012 int err = 0;
995 1013
996 1014 if (be_node == NULL || be_name == NULL || current_be == NULL ||
997 1015 be_ds == NULL) {
998 1016 be_print_err(gettext("be_get_node_data: invalid arguments, "
999 1017 "can not be NULL\n"));
1000 1018 return (BE_ERR_INVAL);
1001 1019 }
1002 1020
1003 1021 errno = 0;
1004 1022
1005 1023 be_node->be_root_ds = strdup(be_ds);
1006 1024 if ((err = errno) != 0 || be_node->be_root_ds == NULL) {
1007 1025 be_print_err(gettext("be_get_node_data: failed to "
1008 1026 "copy root dataset name\n"));
1009 1027 return (errno_to_be_err(err));
1010 1028 }
1011 1029
1012 1030 be_node->be_node_name = strdup(be_name);
1013 1031 if ((err = errno) != 0 || be_node->be_node_name == NULL) {
1014 1032 be_print_err(gettext("be_get_node_data: failed to "
1015 1033 "copy BE name\n"));
1016 1034 return (errno_to_be_err(err));
1017 1035 }
1018 1036 if (strncmp(be_name, current_be, MAXPATHLEN) == 0)
1019 1037 be_node->be_active = B_TRUE;
1020 1038 else
1021 1039 be_node->be_active = B_FALSE;
1022 1040
1023 1041 be_node->be_rpool = strdup(rpool);
1024 1042 if (be_node->be_rpool == NULL || (err = errno) != 0) {
1025 1043 be_print_err(gettext("be_get_node_data: failed to "
1026 1044 "copy root pool name\n"));
1027 1045 return (errno_to_be_err(err));
1028 1046 }
1029 1047
1030 1048 be_node->be_space_used = zfs_prop_get_int(zhp, ZFS_PROP_USED);
1031 1049
1032 1050 if (getzoneid() == GLOBAL_ZONEID) {
1033 1051 if ((zphp = zpool_open(g_zfs, rpool)) == NULL) {
1034 1052 be_print_err(gettext("be_get_node_data: failed to open "
1035 1053 "pool (%s): %s\n"), rpool,
1036 1054 libzfs_error_description(g_zfs));
1037 1055 return (zfs_err_to_be_err(g_zfs));
1038 1056 }
1039 1057
1040 1058 (void) zpool_get_prop(zphp, ZPOOL_PROP_BOOTFS, prop_buf,
1041 1059 ZFS_MAXPROPLEN, NULL, B_FALSE);
1042 1060 if (be_has_grub() && (be_default_grub_bootfs(rpool,
1043 1061 &grub_default_bootfs) == BE_SUCCESS) &&
1044 1062 grub_default_bootfs != NULL)
1045 1063 if (strcmp(grub_default_bootfs, be_ds) == 0)
1046 1064 be_node->be_active_on_boot = B_TRUE;
1047 1065 else
1048 1066 be_node->be_active_on_boot = B_FALSE;
1049 1067 else if (prop_buf != NULL && strcmp(prop_buf, be_ds) == 0)
1050 1068 be_node->be_active_on_boot = B_TRUE;
1051 1069 else
1052 1070 be_node->be_active_on_boot = B_FALSE;
1053 1071
1054 1072 be_node->be_global_active = B_TRUE;
1055 1073
1056 1074 free(grub_default_bootfs);
1057 1075 zpool_close(zphp);
1058 1076 } else {
1059 1077 if (be_zone_compare_uuids(be_node->be_root_ds))
1060 1078 be_node->be_global_active = B_TRUE;
1061 1079 else
1062 1080 be_node->be_global_active = B_FALSE;
1063 1081 }
1064 1082
1065 1083 /*
1066 1084 * If the dataset is mounted use the mount point
1067 1085 * returned from the zfs_is_mounted call. If the
1068 1086 * dataset is not mounted then pull the mount
1069 1087 * point information out of the zfs properties.
1070 1088 */
1071 1089 be_node->be_mounted = zfs_is_mounted(zhp,
1072 1090 &(be_node->be_mntpt));
1073 1091 if (!be_node->be_mounted) {
1074 1092 if (zfs_prop_get(zhp, ZFS_PROP_MOUNTPOINT, prop_buf,
1075 1093 ZFS_MAXPROPLEN, NULL, NULL, 0, B_FALSE) == 0)
1076 1094 be_node->be_mntpt = strdup(prop_buf);
1077 1095 else
1078 1096 return (zfs_err_to_be_err(g_zfs));
1079 1097 }
1080 1098
1081 1099 be_node->be_node_creation = (time_t)zfs_prop_get_int(zhp,
1082 1100 ZFS_PROP_CREATION);
1083 1101
1084 1102 /* Get all user properties used for libbe */
1085 1103 if ((userprops = zfs_get_user_props(zhp)) == NULL) {
1086 1104 be_node->be_policy_type = strdup(be_default_policy());
1087 1105 } else {
1088 1106 if (getzoneid() != GLOBAL_ZONEID) {
1089 1107 if (nvlist_lookup_nvlist(userprops,
1090 1108 BE_ZONE_ACTIVE_PROPERTY, &zone_propval) != 0 ||
1091 1109 zone_propval == NULL) {
1092 1110 be_node->be_active_on_boot = B_FALSE;
1093 1111 } else {
1094 1112 verify(nvlist_lookup_string(zone_propval,
1095 1113 ZPROP_VALUE, &zone_prop_str) == 0);
1096 1114 if (strcmp(zone_prop_str, "on") == 0) {
1097 1115 be_node->be_active_on_boot = B_TRUE;
1098 1116 } else {
1099 1117 be_node->be_active_on_boot = B_FALSE;
1100 1118 }
1101 1119 }
1102 1120 }
1103 1121
1104 1122 if (nvlist_lookup_nvlist(userprops, BE_POLICY_PROPERTY,
1105 1123 &propval) != 0 || propval == NULL) {
1106 1124 be_node->be_policy_type =
1107 1125 strdup(be_default_policy());
1108 1126 } else {
1109 1127 verify(nvlist_lookup_string(propval, ZPROP_VALUE,
1110 1128 &prop_str) == 0);
1111 1129 if (prop_str == NULL || strcmp(prop_str, "-") == 0 ||
1112 1130 strcmp(prop_str, "") == 0)
1113 1131 be_node->be_policy_type =
1114 1132 strdup(be_default_policy());
1115 1133 else
1116 1134 be_node->be_policy_type = strdup(prop_str);
1117 1135 }
1118 1136 if (getzoneid() != GLOBAL_ZONEID) {
1119 1137 if (nvlist_lookup_nvlist(userprops,
1120 1138 BE_ZONE_PARENTBE_PROPERTY, &propval) != 0 &&
1121 1139 nvlist_lookup_string(propval, ZPROP_VALUE,
1122 1140 &prop_str) == 0) {
1123 1141 be_node->be_uuid_str = strdup(prop_str);
1124 1142 }
1125 1143 } else {
1126 1144 if (nvlist_lookup_nvlist(userprops, BE_UUID_PROPERTY,
1127 1145 &propval) == 0 && nvlist_lookup_string(propval,
1128 1146 ZPROP_VALUE, &prop_str) == 0) {
1129 1147 be_node->be_uuid_str = strdup(prop_str);
1130 1148 }
1131 1149 }
1132 1150 }
1133 1151
1134 1152 /*
1135 1153 * Increment the dataset counter to include the root dataset
1136 1154 * of the BE.
1137 1155 */
1138 1156 be_node->be_node_num_datasets++;
1139 1157
1140 1158 return (BE_SUCCESS);
1141 1159 }
1142 1160
1143 1161 /*
1144 1162 * Function: be_get_ds_data
1145 1163 * Description: Helper function used by be_add_children_callback to collect
1146 1164 * the dataset related information that will be returned by
1147 1165 * be_list.
1148 1166 * Parameters:
1149 1167 * zhp - Handle to the zfs dataset whose information we're
1150 1168 * collecting.
1151 1169 * name - The name of the dataset we're processing.
1152 1170 * dataset - A pointer to the be_dataset_list structure
1153 1171 * we're filling in.
1154 1172 * node - The node structure that this dataset belongs to.
1155 1173 * Return:
1156 1174 * BE_SUCCESS - Success
1157 1175 * be_errno_t - Failure
1158 1176 * Scope:
1159 1177 * Private
1160 1178 */
1161 1179 static int
1162 1180 be_get_ds_data(
1163 1181 zfs_handle_t *zfshp,
1164 1182 char *name,
1165 1183 be_dataset_list_t *dataset,
1166 1184 be_node_list_t *node)
1167 1185 {
1168 1186 char prop_buf[ZFS_MAXPROPLEN];
1169 1187 nvlist_t *propval = NULL;
1170 1188 nvlist_t *userprops = NULL;
1171 1189 char *prop_str = NULL;
1172 1190 int err = 0;
1173 1191
1174 1192 if (zfshp == NULL || name == NULL || dataset == NULL || node == NULL) {
1175 1193 be_print_err(gettext("be_get_ds_data: invalid arguments, "
1176 1194 "can not be NULL\n"));
1177 1195 return (BE_ERR_INVAL);
1178 1196 }
1179 1197
1180 1198 errno = 0;
1181 1199
1182 1200 dataset->be_dataset_name = strdup(name);
1183 1201 if ((err = errno) != 0) {
1184 1202 be_print_err(gettext("be_get_ds_data: failed to copy "
1185 1203 "dataset name\n"));
1186 1204 return (errno_to_be_err(err));
1187 1205 }
1188 1206
1189 1207 dataset->be_ds_space_used = zfs_prop_get_int(zfshp, ZFS_PROP_USED);
1190 1208
1191 1209 /*
1192 1210 * If the dataset is mounted use the mount point
1193 1211 * returned from the zfs_is_mounted call. If the
1194 1212 * dataset is not mounted then pull the mount
1195 1213 * point information out of the zfs properties.
1196 1214 */
1197 1215 if (!(dataset->be_ds_mounted = zfs_is_mounted(zfshp,
1198 1216 &(dataset->be_ds_mntpt)))) {
1199 1217 if (zfs_prop_get(zfshp, ZFS_PROP_MOUNTPOINT,
1200 1218 prop_buf, ZFS_MAXPROPLEN, NULL, NULL, 0,
1201 1219 B_FALSE) == 0)
1202 1220 dataset->be_ds_mntpt = strdup(prop_buf);
1203 1221 else
1204 1222 return (zfs_err_to_be_err(g_zfs));
1205 1223 }
1206 1224 dataset->be_ds_creation =
1207 1225 (time_t)zfs_prop_get_int(zfshp, ZFS_PROP_CREATION);
1208 1226
1209 1227 /*
1210 1228 * Get the user property used for the libbe
1211 1229 * cleaup policy
1212 1230 */
1213 1231 if ((userprops = zfs_get_user_props(zfshp)) == NULL) {
1214 1232 dataset->be_ds_plcy_type =
1215 1233 strdup(node->be_policy_type);
1216 1234 } else {
1217 1235 if (nvlist_lookup_nvlist(userprops,
1218 1236 BE_POLICY_PROPERTY, &propval) != 0 ||
1219 1237 propval == NULL) {
1220 1238 dataset->be_ds_plcy_type =
1221 1239 strdup(node->be_policy_type);
1222 1240 } else {
1223 1241 verify(nvlist_lookup_string(propval,
1224 1242 ZPROP_VALUE, &prop_str) == 0);
1225 1243 if (prop_str == NULL ||
1226 1244 strcmp(prop_str, "-") == 0 ||
1227 1245 strcmp(prop_str, "") == 0)
1228 1246 dataset->be_ds_plcy_type
1229 1247 = strdup(node->be_policy_type);
1230 1248 else
1231 1249 dataset->be_ds_plcy_type = strdup(prop_str);
1232 1250 }
1233 1251 }
1234 1252
1235 1253 node->be_node_num_datasets++;
1236 1254 return (BE_SUCCESS);
1237 1255 }
1238 1256
1239 1257 /*
1240 1258 * Function: be_get_ss_data
1241 1259 * Description: Helper function used by be_add_children_callback to collect
1242 1260 * the dataset related information that will be returned by
1243 1261 * be_list.
1244 1262 * Parameters:
1245 1263 * zhp - Handle to the zfs snapshot whose information we're
1246 1264 * collecting.
1247 1265 * name - The name of the snapshot we're processing.
1248 1266 * shapshot - A pointer to the be_snapshot_list structure
1249 1267 * we're filling in.
1250 1268 * node - The node structure that this snapshot belongs to.
1251 1269 * Returns:
1252 1270 * BE_SUCCESS - Success
1253 1271 * be_errno_t - Failure
1254 1272 * Scope:
1255 1273 * Private
1256 1274 */
1257 1275 static int
1258 1276 be_get_ss_data(
1259 1277 zfs_handle_t *zfshp,
1260 1278 char *name,
1261 1279 be_snapshot_list_t *snapshot,
1262 1280 be_node_list_t *node)
1263 1281 {
1264 1282 nvlist_t *propval = NULL;
1265 1283 nvlist_t *userprops = NULL;
1266 1284 char *prop_str = NULL;
1267 1285 int err = 0;
1268 1286
1269 1287 if (zfshp == NULL || name == NULL || snapshot == NULL || node == NULL) {
1270 1288 be_print_err(gettext("be_get_ss_data: invalid arguments, "
1271 1289 "can not be NULL\n"));
1272 1290 return (BE_ERR_INVAL);
1273 1291 }
1274 1292
1275 1293 errno = 0;
1276 1294
1277 1295 snapshot->be_snapshot_name = strdup(name);
1278 1296 if ((err = errno) != 0) {
1279 1297 be_print_err(gettext("be_get_ss_data: failed to copy name\n"));
1280 1298 return (errno_to_be_err(err));
1281 1299 }
1282 1300
1283 1301 snapshot->be_snapshot_creation = (time_t)zfs_prop_get_int(zfshp,
1284 1302 ZFS_PROP_CREATION);
1285 1303
1286 1304 /*
1287 1305 * Try to get this snapshot's cleanup policy from its
1288 1306 * user properties first. If not there, use default
1289 1307 * cleanup policy.
1290 1308 */
1291 1309 if ((userprops = zfs_get_user_props(zfshp)) != NULL &&
1292 1310 nvlist_lookup_nvlist(userprops, BE_POLICY_PROPERTY,
1293 1311 &propval) == 0 && nvlist_lookup_string(propval,
1294 1312 ZPROP_VALUE, &prop_str) == 0) {
1295 1313 snapshot->be_snapshot_type =
1296 1314 strdup(prop_str);
1297 1315 } else {
1298 1316 snapshot->be_snapshot_type =
1299 1317 strdup(be_default_policy());
1300 1318 }
1301 1319
1302 1320 snapshot->be_snapshot_space_used = zfs_prop_get_int(zfshp,
1303 1321 ZFS_PROP_USED);
1304 1322
1305 1323 node->be_node_num_snapshots++;
1306 1324 return (BE_SUCCESS);
1307 1325 }
1308 1326
1309 1327 /*
1310 1328 * Function: be_list_alloc
1311 1329 * Description: Helper function used to allocate memory for the various
1312 1330 * sructures that make up a BE node.
1313 1331 * Parameters:
1314 1332 * err - Used to return any errors encountered.
1315 1333 * BE_SUCCESS - Success
1316 1334 * BE_ERR_NOMEM - Allocation failure
1317 1335 * size - The size of memory to allocate.
1318 1336 * Returns:
1319 1337 * Success - A pointer to the allocated memory
1320 1338 * Failure - NULL
1321 1339 * Scope:
1322 1340 * Private
1323 1341 */
1324 1342 static void*
1325 1343 be_list_alloc(int *err, size_t size)
1326 1344 {
1327 1345 void *bep = NULL;
1328 1346
1329 1347 bep = calloc(1, size);
1330 1348 if (bep == NULL) {
1331 1349 be_print_err(gettext("be_list_alloc: memory "
1332 1350 "allocation failed\n"));
1333 1351 *err = BE_ERR_NOMEM;
1334 1352 }
1335 1353 *err = BE_SUCCESS;
1336 1354 return (bep);
1337 1355 }
1338 1356
1339 1357 /*
1340 1358 * Function: be_get_zone_node_data
1341 1359 * Description: Helper function used to collect all the information to
1342 1360 * fill in the be_node_list structure to be returned by
1343 1361 * be_get_zone_list.
1344 1362 * Parameters:
1345 1363 * be_node - a pointer to the node structure we're filling in.
1346 1364 * be_name - The BE name of the node whose information we're
1347 1365 * Returns:
1348 1366 * BE_SUCCESS - Success
1349 1367 * be_errno_t - Failure
1350 1368 * Scope:
1351 1369 * Private
1352 1370 *
1353 1371 * NOTE: This function currently only collects the zone BE name but when
1354 1372 * support for beadm/libbe in a zone is provided it will need to fill
1355 1373 * in the rest of the information needed for a zone BE.
1356 1374 */
1357 1375 static int
1358 1376 be_get_zone_node_data(be_node_list_t *be_node, char *be_name)
1359 1377 {
1360 1378 if ((be_node->be_node_name = strdup(be_name)) != NULL)
1361 1379 return (BE_SUCCESS);
1362 1380 return (BE_ERR_NOMEM);
1363 1381 }
↓ open down ↓ |
572 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX