* Synchronize pool configuration to disk. This must be called with the * namespace lock held. Synchronizing the pool cache is typically done after * the configuration has been synced to the MOS. This exposes a window where * the MOS config will have been updated but the cache file has not. If * the system were to crash at that instant then the cached config may not * contain the correct info
| 237 | * would be required. |
| 238 | */ |
| 239 | void |
| 240 | spa_write_cachefile(spa_t *target, boolean_t removing, boolean_t postsysevent) |
| 241 | { |
| 242 | spa_config_dirent_t *dp, *tdp; |
| 243 | nvlist_t *nvl; |
| 244 | char *pool_name; |
| 245 | boolean_t ccw_failure; |
| 246 | int error = 0; |
| 247 | |
| 248 | ASSERT(MUTEX_HELD(&spa_namespace_lock)); |
| 249 | |
| 250 | if (!(spa_mode_global & SPA_MODE_WRITE)) |
| 251 | return; |
| 252 | |
| 253 | /* |
| 254 | * Iterate over all cachefiles for the pool, past or present. When the |
| 255 | * cachefile is changed, the new one is pushed onto this list, allowing |
| 256 | * us to update previous cachefiles that no longer contain this pool. |
| 257 | */ |
| 258 | ccw_failure = B_FALSE; |
| 259 | for (dp = list_head(&target->spa_config_list); dp != NULL; |
| 260 | dp = list_next(&target->spa_config_list, dp)) { |
| 261 | spa_t *spa = NULL; |
| 262 | if (dp->scd_path == NULL) |
| 263 | continue; |
| 264 | |
| 265 | /* |
| 266 | * Iterate over all pools, adding any matching pools to 'nvl'. |
| 267 | */ |
| 268 | nvl = NULL; |
| 269 | while ((spa = spa_next(spa)) != NULL) { |
| 270 | /* |
| 271 | * Skip over our own pool if we're about to remove |
| 272 | * ourselves from the spa namespace or any pool that |
| 273 | * is readonly. Since we cannot guarantee that a |
| 274 | * readonly pool would successfully import upon reboot, |
| 275 | * we don't allow them to be written to the cache file. |
| 276 | */ |
| 277 | if ((spa == target && removing) || |
| 278 | !spa_writeable(spa)) |
| 279 | continue; |
| 280 | |
| 281 | mutex_enter(&spa->spa_props_lock); |
| 282 | tdp = list_head(&spa->spa_config_list); |
| 283 | if (spa->spa_config == NULL || |
| 284 | tdp == NULL || |
| 285 | tdp->scd_path == NULL || |
| 286 | strcmp(tdp->scd_path, dp->scd_path) != 0) { |
| 287 | mutex_exit(&spa->spa_props_lock); |
| 288 | continue; |
| 289 | } |
| 290 | |
| 291 | if (nvl == NULL) |
| 292 | nvl = fnvlist_alloc(); |
| 293 | |
| 294 | if (spa->spa_import_flags & ZFS_IMPORT_TEMP_NAME) |
| 295 | pool_name = fnvlist_lookup_string( |
| 296 | spa->spa_config, ZPOOL_CONFIG_POOL_NAME); |