usr/src/uts/common/fs/zfs/vdev.c
changeset 1485 e971e58d18f6
parent 1199 6e3b7bca3574
child 1544 938876158511
equal deleted inserted replaced
1484:d330e98f8ed7 1485:e971e58d18f6
     1 /*
     1 /*
     2  * CDDL HEADER START
     2  * CDDL HEADER START
     3  *
     3  *
     4  * The contents of this file are subject to the terms of the
     4  * The contents of this file are subject to the terms of the
     5  * Common Development and Distribution License, Version 1.0 only
     5  * Common Development and Distribution License (the "License").
     6  * (the "License").  You may not use this file except in compliance
     6  * You may not use this file except in compliance with the License.
     7  * with the License.
       
     8  *
     7  *
     9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
     8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
    10  * or http://www.opensolaris.org/os/licensing.
     9  * or http://www.opensolaris.org/os/licensing.
    11  * See the License for the specific language governing permissions
    10  * See the License for the specific language governing permissions
    12  * and limitations under the License.
    11  * and limitations under the License.
   359 vdev_t *
   358 vdev_t *
   360 vdev_alloc(spa_t *spa, nvlist_t *nv, vdev_t *parent, uint_t id, int alloctype)
   359 vdev_alloc(spa_t *spa, nvlist_t *nv, vdev_t *parent, uint_t id, int alloctype)
   361 {
   360 {
   362 	vdev_ops_t *ops;
   361 	vdev_ops_t *ops;
   363 	char *type;
   362 	char *type;
   364 	uint64_t guid = 0;
   363 	uint64_t guid = 0, offline = 0;
   365 	vdev_t *vd;
   364 	vdev_t *vd;
   366 
   365 
   367 	ASSERT(spa_config_held(spa, RW_WRITER));
   366 	ASSERT(spa_config_held(spa, RW_WRITER));
   368 
   367 
   369 	if (nvlist_lookup_string(nv, ZPOOL_CONFIG_TYPE, &type) != 0)
   368 	if (nvlist_lookup_string(nv, ZPOOL_CONFIG_TYPE, &type) != 0)
   415 		(void) nvlist_lookup_uint64(nv, ZPOOL_CONFIG_ASIZE,
   414 		(void) nvlist_lookup_uint64(nv, ZPOOL_CONFIG_ASIZE,
   416 		    &vd->vdev_asize);
   415 		    &vd->vdev_asize);
   417 	}
   416 	}
   418 
   417 
   419 	/*
   418 	/*
   420 	 * If we're a leaf vdev, try to load the DTL object.
   419 	 * If we're a leaf vdev, try to load the DTL object
   421 	 */
   420 	 * and the offline state.
       
   421 	 */
       
   422 	vd->vdev_offline = B_FALSE;
   422 	if (vd->vdev_ops->vdev_op_leaf && alloctype == VDEV_ALLOC_LOAD) {
   423 	if (vd->vdev_ops->vdev_op_leaf && alloctype == VDEV_ALLOC_LOAD) {
   423 		(void) nvlist_lookup_uint64(nv, ZPOOL_CONFIG_DTL,
   424 		(void) nvlist_lookup_uint64(nv, ZPOOL_CONFIG_DTL,
   424 		    &vd->vdev_dtl.smo_object);
   425 		    &vd->vdev_dtl.smo_object);
       
   426 
       
   427 		if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_OFFLINE, &offline)
       
   428 		    == 0)
       
   429 			vd->vdev_offline = offline;
   425 	}
   430 	}
   426 
   431 
   427 	/*
   432 	/*
   428 	 * Add ourselves to the parent's list of children.
   433 	 * Add ourselves to the parent's list of children.
   429 	 */
   434 	 */
  1339 }
  1344 }
  1340 
  1345 
  1341 int
  1346 int
  1342 vdev_online(spa_t *spa, const char *path)
  1347 vdev_online(spa_t *spa, const char *path)
  1343 {
  1348 {
  1344 	vdev_t *vd;
  1349 	vdev_t *rvd, *vd;
  1345 
  1350 	uint64_t txg;
  1346 	spa_config_enter(spa, RW_WRITER);
  1351 
  1347 
  1352 	txg = spa_vdev_enter(spa);
  1348 	if ((vd = vdev_lookup_by_path(spa->spa_root_vdev, path)) == NULL) {
  1353 
  1349 		spa_config_exit(spa);
  1354 	rvd = spa->spa_root_vdev;
  1350 		return (ENODEV);
  1355 	if ((vd = vdev_lookup_by_path(rvd, path)) == NULL)
  1351 	}
  1356 		return (spa_vdev_exit(spa, NULL, txg, ENODEV));
  1352 
  1357 
  1353 	dprintf("ONLINE: %s\n", vdev_description(vd));
  1358 	dprintf("ONLINE: %s\n", vdev_description(vd));
  1354 
  1359 
  1355 	vd->vdev_offline = B_FALSE;
  1360 	vd->vdev_offline = B_FALSE;
       
  1361 	vd->vdev_tmpoffline = B_FALSE;
  1356 
  1362 
  1357 	/*
  1363 	/*
  1358 	 * Clear the error counts.  The idea is that you expect to see all
  1364 	 * Clear the error counts.  The idea is that you expect to see all
  1359 	 * zeroes when everything is working, so if you've just onlined a
  1365 	 * zeroes when everything is working, so if you've just onlined a
  1360 	 * device, you don't want to keep hearing about errors from before.
  1366 	 * device, you don't want to keep hearing about errors from before.
  1363 	vd->vdev_stat.vs_write_errors = 0;
  1369 	vd->vdev_stat.vs_write_errors = 0;
  1364 	vd->vdev_stat.vs_checksum_errors = 0;
  1370 	vd->vdev_stat.vs_checksum_errors = 0;
  1365 
  1371 
  1366 	vdev_reopen(vd->vdev_top, NULL);
  1372 	vdev_reopen(vd->vdev_top, NULL);
  1367 
  1373 
  1368 	spa_config_exit(spa);
  1374 	spa_config_set(spa, spa_config_generate(spa, rvd, txg, 0));
       
  1375 
       
  1376 	vdev_config_dirty(vd->vdev_top);
       
  1377 
       
  1378 	(void) spa_vdev_exit(spa, NULL, txg, 0);
  1369 
  1379 
  1370 	VERIFY(spa_scrub(spa, POOL_SCRUB_RESILVER, B_TRUE) == 0);
  1380 	VERIFY(spa_scrub(spa, POOL_SCRUB_RESILVER, B_TRUE) == 0);
  1371 
  1381 
  1372 	return (0);
  1382 	return (0);
  1373 }
  1383 }
  1374 
  1384 
  1375 int
  1385 int
  1376 vdev_offline(spa_t *spa, const char *path)
  1386 vdev_offline(spa_t *spa, const char *path, int istmp)
  1377 {
  1387 {
  1378 	vdev_t *vd;
  1388 	vdev_t *rvd, *vd;
  1379 
  1389 	uint64_t txg;
  1380 	spa_config_enter(spa, RW_WRITER);
  1390 
  1381 
  1391 	txg = spa_vdev_enter(spa);
  1382 	if ((vd = vdev_lookup_by_path(spa->spa_root_vdev, path)) == NULL) {
  1392 
  1383 		spa_config_exit(spa);
  1393 	rvd = spa->spa_root_vdev;
  1384 		return (ENODEV);
  1394 	if ((vd = vdev_lookup_by_path(rvd, path)) == NULL)
  1385 	}
  1395 		return (spa_vdev_exit(spa, NULL, txg, ENODEV));
  1386 
  1396 
  1387 	dprintf("OFFLINE: %s\n", vdev_description(vd));
  1397 	dprintf("OFFLINE: %s\n", vdev_description(vd));
       
  1398 
       
  1399 	/* vdev is already offlined, do nothing */
       
  1400 	if (vd->vdev_offline)
       
  1401 		return (spa_vdev_exit(spa, NULL, txg, 0));
  1388 
  1402 
  1389 	/*
  1403 	/*
  1390 	 * If this device's top-level vdev has a non-empty DTL,
  1404 	 * If this device's top-level vdev has a non-empty DTL,
  1391 	 * don't allow the device to be offlined.
  1405 	 * don't allow the device to be offlined.
  1392 	 *
  1406 	 *
  1393 	 * XXX -- we should make this more precise by allowing the offline
  1407 	 * XXX -- we should make this more precise by allowing the offline
  1394 	 * as long as the remaining devices don't have any DTL holes.
  1408 	 * as long as the remaining devices don't have any DTL holes.
  1395 	 */
  1409 	 */
  1396 	if (vd->vdev_top->vdev_dtl_map.sm_space != 0) {
  1410 	if (vd->vdev_top->vdev_dtl_map.sm_space != 0)
  1397 		spa_config_exit(spa);
  1411 		return (spa_vdev_exit(spa, NULL, txg, EBUSY));
  1398 		return (EBUSY);
       
  1399 	}
       
  1400 
  1412 
  1401 	/*
  1413 	/*
  1402 	 * Set this device to offline state and reopen its top-level vdev.
  1414 	 * Set this device to offline state and reopen its top-level vdev.
  1403 	 * If this action results in the top-level vdev becoming unusable,
  1415 	 * If this action results in the top-level vdev becoming unusable,
  1404 	 * undo it and fail the request.
  1416 	 * undo it and fail the request.
  1406 	vd->vdev_offline = B_TRUE;
  1418 	vd->vdev_offline = B_TRUE;
  1407 	vdev_reopen(vd->vdev_top, NULL);
  1419 	vdev_reopen(vd->vdev_top, NULL);
  1408 	if (vdev_is_dead(vd->vdev_top)) {
  1420 	if (vdev_is_dead(vd->vdev_top)) {
  1409 		vd->vdev_offline = B_FALSE;
  1421 		vd->vdev_offline = B_FALSE;
  1410 		vdev_reopen(vd->vdev_top, NULL);
  1422 		vdev_reopen(vd->vdev_top, NULL);
  1411 		spa_config_exit(spa);
  1423 		return (spa_vdev_exit(spa, NULL, txg, EBUSY));
  1412 		return (EBUSY);
  1424 	}
  1413 	}
  1425 
  1414 
  1426 	vd->vdev_tmpoffline = istmp;
  1415 	spa_config_exit(spa);
  1427 	if (istmp)
  1416 
  1428 		return (spa_vdev_exit(spa, NULL, txg, 0));
  1417 	return (0);
  1429 
       
  1430 	spa_config_set(spa, spa_config_generate(spa, rvd, txg, 0));
       
  1431 
       
  1432 	vdev_config_dirty(vd->vdev_top);
       
  1433 
       
  1434 	return (spa_vdev_exit(spa, NULL, txg, 0));
  1418 }
  1435 }
  1419 
  1436 
  1420 int
  1437 int
  1421 vdev_error_setup(spa_t *spa, const char *path, int mode, int mask, uint64_t arg)
  1438 vdev_error_setup(spa_t *spa, const char *path, int mode, int mask, uint64_t arg)
  1422 {
  1439 {