Print this page
NEX-5736 implement autoreplace matching based on FRU slot number
NEX-6200 hot spares are not reactivated after reinserting into enclosure
NEX-9403 need to update FRU for spare and l2cache devices
NEX-9404 remove lofi autoreplace support from syseventd
NEX-9409 hotsparing doesn't work for vdevs without FRU
NEX-9424 zfs`vdev_online() needs better notification about state changes
Portions contributed by: Alek Pinchuk <alek@nexenta.com>
Portions contributed by: Josef 'Jeff' Sipek <josef.sipek@nexenta.com>
Reviewed by: Roman Strashkin <roman.strashkin@nexenta.com>
Reviewed by: Steve Peng <steve.peng@nexenta.com>
Reviewed by: Sanjay Nadkarni <sanjay.nadkarni@nexenta.com>
NEX-9228 libzfs`add_config() leaks config nvl when reading spare/l2cache devices
Reviewed by: Hans Rosenfeld <hans.rosenfeld@nexenta.com>
Reviewed by: Roman Strashkin <roman.strashkin@nexenta.com>
Reviewed by: Sanjay Nadkarni <sanjay.nadkarni@nexenta.com>
1778 Assertion failed: rn->rn_nozpool == B_FALSE, file ../common/libzfs_import.c, line 1077, function zpool_open_func
Reviewed by: Matthew Ahrens <mahrens@delphix.com>
Reviewed by: George Wilson <george@delphix.com>
Reviewed by: Richard Elling <richard.elling@richardelling.com>
Approved by: Gordon Ross <gordon.ross@nexenta.com>
NEX-2997 Memory leaks in libzfs import implementation
Reviewed by: Dan Fields <dan.fields@nexenta.com>
NEX-1557 Parallel mount during HA Failover sometimes doesn't share the dataset, causes shares to go offline


 395 boolean_t
 396 vdev_is_hole(uint64_t *hole_array, uint_t holes, uint_t id)
 397 {
 398         for (int c = 0; c < holes; c++) {
 399 
 400                 /* Top-level is a hole */
 401                 if (hole_array[c] == id)
 402                         return (B_TRUE);
 403         }
 404         return (B_FALSE);
 405 }
 406 
 407 /*
 408  * Convert our list of pools into the definitive set of configurations.  We
 409  * start by picking the best config for each toplevel vdev.  Once that's done,
 410  * we assemble the toplevel vdevs into a full config for the pool.  We make a
 411  * pass to fix up any incorrect paths, and then add it to the main list to
 412  * return to the user.
 413  */
 414 static nvlist_t *
 415 get_configs(libzfs_handle_t *hdl, pool_list_t *pl, boolean_t active_ok,
 416     nvlist_t *policy)
 417 {
 418         pool_entry_t *pe;
 419         vdev_entry_t *ve;
 420         config_entry_t *ce;
 421         nvlist_t *ret = NULL, *config = NULL, *tmp = NULL, *nvtop, *nvroot;
 422         nvlist_t **spares, **l2cache;
 423         uint_t i, nspares, nl2cache;
 424         boolean_t config_seen;
 425         uint64_t best_txg;
 426         char *name, *hostname = NULL;
 427         uint64_t guid;
 428         uint_t children = 0;
 429         nvlist_t **child = NULL;
 430         uint_t holes;
 431         uint64_t *hole_array, max_id;
 432         uint_t c;
 433         boolean_t isactive;
 434         uint64_t hostid;
 435         nvlist_t *nvl;
 436         boolean_t found_one = B_FALSE;


 730                         goto add_pool;
 731 
 732                 /*
 733                  * Determine if this pool is currently active, in which case we
 734                  * can't actually import it.
 735                  */
 736                 verify(nvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME,
 737                     &name) == 0);
 738                 verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_GUID,
 739                     &guid) == 0);
 740 
 741                 if (pool_active(hdl, name, guid, &isactive) != 0)
 742                         goto error;
 743 
 744                 if (isactive) {
 745                         nvlist_free(config);
 746                         config = NULL;
 747                         continue;
 748                 }
 749 
 750                 if (policy != NULL) {
 751                         if (nvlist_add_nvlist(config, ZPOOL_REWIND_POLICY,
 752                             policy) != 0)
 753                                 goto nomem;
 754                 }
 755 
 756                 if ((nvl = refresh_config(hdl, config)) == NULL) {
 757                         nvlist_free(config);
 758                         config = NULL;
 759                         continue;
 760                 }
 761 
 762                 nvlist_free(config);
 763                 config = nvl;
 764 
 765                 /*
 766                  * Go through and update the paths for spares, now that we have
 767                  * them.
 768                  */
 769                 verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
 770                     &nvroot) == 0);
 771                 if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_SPARES,
 772                     &spares, &nspares) == 0) {
 773                         for (i = 0; i < nspares; i++) {
 774                                 if (fix_paths(spares[i], pl->names) != 0)
 775                                         goto nomem;


 847 
 848 /*
 849  * Given a file descriptor, read the label information and return an nvlist
 850  * describing the configuration, if there is one.
 851  * Return 0 on success, or -1 on failure
 852  */
 853 int
 854 zpool_read_label(int fd, nvlist_t **config)
 855 {
 856         struct stat64 statbuf;
 857         int l;
 858         vdev_label_t *label;
 859         uint64_t state, txg, size;
 860 
 861         *config = NULL;
 862 
 863         if (fstat64(fd, &statbuf) == -1)
 864                 return (-1);
 865         size = P2ALIGN_TYPED(statbuf.st_size, sizeof (vdev_label_t), uint64_t);
 866 
 867         if ((label = malloc(sizeof (vdev_label_t))) == NULL)
 868                 return (-1);
 869 
 870         for (l = 0; l < VDEV_LABELS; l++) {
 871                 if (pread64(fd, label, sizeof (vdev_label_t),
 872                     label_offset(size, l)) != sizeof (vdev_label_t))
 873                         continue;
 874 
 875                 if (nvlist_unpack(label->vl_vdev_phys.vp_nvlist,
 876                     sizeof (label->vl_vdev_phys.vp_nvlist), config, 0) != 0)
 877                         continue;
 878 
 879                 if (nvlist_lookup_uint64(*config, ZPOOL_CONFIG_POOL_STATE,
 880                     &state) != 0 || state > POOL_STATE_L2CACHE) {
 881                         nvlist_free(*config);
 882                         continue;
 883                 }
 884 
 885                 if (state != POOL_STATE_SPARE && state != POOL_STATE_L2CACHE &&
 886                     (nvlist_lookup_uint64(*config, ZPOOL_CONFIG_POOL_TXG,
 887                     &txg) != 0 || txg == 0)) {


1241                                          * use the non-raw path for the config
1242                                          */
1243                                         (void) strlcpy(end, slice->rn_name,
1244                                             pathleft);
1245                                         if (add_config(hdl, &pools, path,
1246                                             config) != 0)
1247                                                 config_failed = B_TRUE;
1248                                 }
1249                         }
1250                         free(slice->rn_name);
1251                         free(slice);
1252                 }
1253                 avl_destroy(&slice_cache);
1254 
1255                 (void) closedir(dirp);
1256 
1257                 if (config_failed)
1258                         goto error;
1259         }
1260 
1261         ret = get_configs(hdl, &pools, iarg->can_be_active, iarg->policy);
1262 
1263 error:
1264         for (pe = pools.pools; pe != NULL; pe = penext) {
1265                 penext = pe->pe_next;
1266                 for (ve = pe->pe_vdevs; ve != NULL; ve = venext) {
1267                         venext = ve->ve_next;
1268                         for (ce = ve->ve_configs; ce != NULL; ce = cenext) {
1269                                 cenext = ce->ce_next;
1270                                 nvlist_free(ce->ce_config);
1271                                 free(ce);
1272                         }
1273                         free(ve);
1274                 }
1275                 free(pe);
1276         }
1277 
1278         for (ne = pools.names; ne != NULL; ne = nenext) {
1279                 nenext = ne->ne_next;
1280                 free(ne->ne_name);
1281                 free(ne);


1371         while ((elem = nvlist_next_nvpair(raw, elem)) != NULL) {
1372                 src = fnvpair_value_nvlist(elem);
1373 
1374                 name = fnvlist_lookup_string(src, ZPOOL_CONFIG_POOL_NAME);
1375                 if (poolname != NULL && strcmp(poolname, name) != 0)
1376                         continue;
1377 
1378                 this_guid = fnvlist_lookup_uint64(src, ZPOOL_CONFIG_POOL_GUID);
1379                 if (guid != 0 && guid != this_guid)
1380                         continue;
1381 
1382                 if (pool_active(hdl, name, this_guid, &active) != 0) {
1383                         nvlist_free(raw);
1384                         nvlist_free(pools);
1385                         return (NULL);
1386                 }
1387 
1388                 if (active)
1389                         continue;
1390 
1391                 if (nvlist_add_string(src, ZPOOL_CONFIG_CACHEFILE,
1392                     cachefile) != 0) {
1393                         (void) no_memory(hdl);
1394                         nvlist_free(raw);
1395                         nvlist_free(pools);
1396                         return (NULL);
1397                 }
1398 
1399                 if ((dst = refresh_config(hdl, src)) == NULL) {
1400                         nvlist_free(raw);
1401                         nvlist_free(pools);
1402                         return (NULL);
1403                 }
1404 
1405                 if (nvlist_add_nvlist(pools, nvpair_name(elem), dst) != 0) {
1406                         (void) no_memory(hdl);
1407                         nvlist_free(dst);
1408                         nvlist_free(raw);
1409                         nvlist_free(pools);
1410                         return (NULL);
1411                 }
1412                 nvlist_free(dst);
1413         }
1414 
1415         nvlist_free(raw);
1416         return (pools);
1417 }
1418 




 395 boolean_t
 396 vdev_is_hole(uint64_t *hole_array, uint_t holes, uint_t id)
 397 {
 398         for (int c = 0; c < holes; c++) {
 399 
 400                 /* Top-level is a hole */
 401                 if (hole_array[c] == id)
 402                         return (B_TRUE);
 403         }
 404         return (B_FALSE);
 405 }
 406 
 407 /*
 408  * Convert our list of pools into the definitive set of configurations.  We
 409  * start by picking the best config for each toplevel vdev.  Once that's done,
 410  * we assemble the toplevel vdevs into a full config for the pool.  We make a
 411  * pass to fix up any incorrect paths, and then add it to the main list to
 412  * return to the user.
 413  */
 414 static nvlist_t *
 415 get_configs(libzfs_handle_t *hdl, pool_list_t *pl, boolean_t active_ok)

 416 {
 417         pool_entry_t *pe;
 418         vdev_entry_t *ve;
 419         config_entry_t *ce;
 420         nvlist_t *ret = NULL, *config = NULL, *tmp = NULL, *nvtop, *nvroot;
 421         nvlist_t **spares, **l2cache;
 422         uint_t i, nspares, nl2cache;
 423         boolean_t config_seen;
 424         uint64_t best_txg;
 425         char *name, *hostname = NULL;
 426         uint64_t guid;
 427         uint_t children = 0;
 428         nvlist_t **child = NULL;
 429         uint_t holes;
 430         uint64_t *hole_array, max_id;
 431         uint_t c;
 432         boolean_t isactive;
 433         uint64_t hostid;
 434         nvlist_t *nvl;
 435         boolean_t found_one = B_FALSE;


 729                         goto add_pool;
 730 
 731                 /*
 732                  * Determine if this pool is currently active, in which case we
 733                  * can't actually import it.
 734                  */
 735                 verify(nvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME,
 736                     &name) == 0);
 737                 verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_GUID,
 738                     &guid) == 0);
 739 
 740                 if (pool_active(hdl, name, guid, &isactive) != 0)
 741                         goto error;
 742 
 743                 if (isactive) {
 744                         nvlist_free(config);
 745                         config = NULL;
 746                         continue;
 747                 }
 748 






 749                 if ((nvl = refresh_config(hdl, config)) == NULL) {
 750                         nvlist_free(config);
 751                         config = NULL;
 752                         continue;
 753                 }
 754 
 755                 nvlist_free(config);
 756                 config = nvl;
 757 
 758                 /*
 759                  * Go through and update the paths for spares, now that we have
 760                  * them.
 761                  */
 762                 verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
 763                     &nvroot) == 0);
 764                 if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_SPARES,
 765                     &spares, &nspares) == 0) {
 766                         for (i = 0; i < nspares; i++) {
 767                                 if (fix_paths(spares[i], pl->names) != 0)
 768                                         goto nomem;


 840 
 841 /*
 842  * Given a file descriptor, read the label information and return an nvlist
 843  * describing the configuration, if there is one.
 844  * Return 0 on success, or -1 on failure
 845  */
 846 int
 847 zpool_read_label(int fd, nvlist_t **config)
 848 {
 849         struct stat64 statbuf;
 850         int l;
 851         vdev_label_t *label;
 852         uint64_t state, txg, size;
 853 
 854         *config = NULL;
 855 
 856         if (fstat64(fd, &statbuf) == -1)
 857                 return (-1);
 858         size = P2ALIGN_TYPED(statbuf.st_size, sizeof (vdev_label_t), uint64_t);
 859 
 860         if ((label = calloc(sizeof (vdev_label_t), 1)) == NULL)
 861                 return (-1);
 862 
 863         for (l = 0; l < VDEV_LABELS; l++) {
 864                 if (pread64(fd, label, sizeof (vdev_label_t),
 865                     label_offset(size, l)) != sizeof (vdev_label_t))
 866                         continue;
 867 
 868                 if (nvlist_unpack(label->vl_vdev_phys.vp_nvlist,
 869                     sizeof (label->vl_vdev_phys.vp_nvlist), config, 0) != 0)
 870                         continue;
 871 
 872                 if (nvlist_lookup_uint64(*config, ZPOOL_CONFIG_POOL_STATE,
 873                     &state) != 0 || state > POOL_STATE_L2CACHE) {
 874                         nvlist_free(*config);
 875                         continue;
 876                 }
 877 
 878                 if (state != POOL_STATE_SPARE && state != POOL_STATE_L2CACHE &&
 879                     (nvlist_lookup_uint64(*config, ZPOOL_CONFIG_POOL_TXG,
 880                     &txg) != 0 || txg == 0)) {


1234                                          * use the non-raw path for the config
1235                                          */
1236                                         (void) strlcpy(end, slice->rn_name,
1237                                             pathleft);
1238                                         if (add_config(hdl, &pools, path,
1239                                             config) != 0)
1240                                                 config_failed = B_TRUE;
1241                                 }
1242                         }
1243                         free(slice->rn_name);
1244                         free(slice);
1245                 }
1246                 avl_destroy(&slice_cache);
1247 
1248                 (void) closedir(dirp);
1249 
1250                 if (config_failed)
1251                         goto error;
1252         }
1253 
1254         ret = get_configs(hdl, &pools, iarg->can_be_active);
1255 
1256 error:
1257         for (pe = pools.pools; pe != NULL; pe = penext) {
1258                 penext = pe->pe_next;
1259                 for (ve = pe->pe_vdevs; ve != NULL; ve = venext) {
1260                         venext = ve->ve_next;
1261                         for (ce = ve->ve_configs; ce != NULL; ce = cenext) {
1262                                 cenext = ce->ce_next;
1263                                 nvlist_free(ce->ce_config);
1264                                 free(ce);
1265                         }
1266                         free(ve);
1267                 }
1268                 free(pe);
1269         }
1270 
1271         for (ne = pools.names; ne != NULL; ne = nenext) {
1272                 nenext = ne->ne_next;
1273                 free(ne->ne_name);
1274                 free(ne);


1364         while ((elem = nvlist_next_nvpair(raw, elem)) != NULL) {
1365                 src = fnvpair_value_nvlist(elem);
1366 
1367                 name = fnvlist_lookup_string(src, ZPOOL_CONFIG_POOL_NAME);
1368                 if (poolname != NULL && strcmp(poolname, name) != 0)
1369                         continue;
1370 
1371                 this_guid = fnvlist_lookup_uint64(src, ZPOOL_CONFIG_POOL_GUID);
1372                 if (guid != 0 && guid != this_guid)
1373                         continue;
1374 
1375                 if (pool_active(hdl, name, this_guid, &active) != 0) {
1376                         nvlist_free(raw);
1377                         nvlist_free(pools);
1378                         return (NULL);
1379                 }
1380 
1381                 if (active)
1382                         continue;
1383 








1384                 if ((dst = refresh_config(hdl, src)) == NULL) {
1385                         nvlist_free(raw);
1386                         nvlist_free(pools);
1387                         return (NULL);
1388                 }
1389 
1390                 if (nvlist_add_nvlist(pools, nvpair_name(elem), dst) != 0) {
1391                         (void) no_memory(hdl);
1392                         nvlist_free(dst);
1393                         nvlist_free(raw);
1394                         nvlist_free(pools);
1395                         return (NULL);
1396                 }
1397                 nvlist_free(dst);
1398         }
1399 
1400         nvlist_free(raw);
1401         return (pools);
1402 }
1403