int vrt_rdev_replace(struct vrt_realdev *rdev, const exa_uuid_t *new_rdev_uuid) { blockdevice_t *new_blockdevice; int err; if (rdev_is_ok(rdev)) { exalog_error("Bad rdev status %d", rdev_get_compound_status(rdev)); return -VRT_ERR_CANT_DGDISKRECOVER; } new_blockdevice = client_get_blockdevice(new_rdev_uuid); if (new_blockdevice == NULL) { exalog_error("Could not open device "UUID_FMT, UUID_VAL(new_rdev_uuid)); return -ENODEV; } if (__get_block_aligned_bdev_size(new_blockdevice) < __get_block_aligned_bdev_size(rdev->blockdevice)) return -VRT_ERR_RDEV_TOO_SMALL; rdev->blockdevice = new_blockdevice; /* re-open the superblock stream */ vrt_rdev_close_superblock_streams(rdev); err = vrt_rdev_open_superblock_streams(rdev); if (err != 0) return err; uuid_copy(&rdev->nbd_uuid, new_rdev_uuid); return EXA_SUCCESS; }
exa_bool_t rain1_rdev_is_writable(const rain1_group_t *rxg, const struct vrt_realdev *rdev) { const rain1_realdev_t *lr = RAIN1_REALDEV(rxg, rdev); sync_tag_t sync_tag = rxg->sync_tag; return rdev_is_ok(rdev) && (rain1_rdev_is_uptodate(lr, sync_tag) || rain1_rdev_is_updating(lr)); }
/** * Predicate -- Does a SPOF group needs to be updated? * * @param[in] rxg the group layout * @param[in] spof_group SPOF group to check * * @return true if the SPOF group needs to be updated. */ static bool spof_group_needs_updating(const rain1_group_t *rxg, const spof_group_t *spof_group) { uint32_t i; for (i = 0; i < spof_group->nb_realdevs; i++) { const struct vrt_realdev *rdev = spof_group->realdevs[i]; const rain1_realdev_t *lr = RAIN1_REALDEV(rxg, rdev); sync_tag_t sync_tag = rxg->sync_tag; if (rdev_is_ok(rdev) && !rain1_rdev_is_uptodate(lr, sync_tag)) return true; } return false; }
/** * Tells that a unusable device is now available again. We'll put it * in the EXA_REALDEV_UPDATING state, which doesn't mean we can safely * use it, but that a rebuilding process must take place before * changing the status to EXA_REALDEV_OK. * * @param[in] rdev The real device which is now available again * * @return always EXA_SUCCESS */ int vrt_rdev_up(struct vrt_realdev *rdev) { uint64_t size; uint64_t required_size; int err; /* Admind can send an up message even if the device is not down */ if (rdev_is_ok(rdev)) return EXA_SUCCESS; rdev->up = TRUE; size = __get_block_aligned_bdev_size(rdev->blockdevice); err = vrt_rdev_set_real_size(rdev, size); if (err != EXA_SUCCESS) return err; /* Check that the size of the device correspond to the real size of the * device. * This test is also done at group start (see vrt_group_start) * * FIXME: This kind of verification could be done by the service in * charge of the devices */ required_size = rdev_chunk_based_size(rdev); if (vrt_realdev_get_usable_size(rdev) < required_size) { /* XXX Duplicate: same error in vrt_group_start() */ exalog_error("Real size of device "UUID_FMT" is too small: %"PRIu64" < %"PRIu64, UUID_VAL(&rdev->uuid), vrt_realdev_get_usable_size(rdev), required_size); rdev->corrupted = TRUE; rdev->real_size = 0; return EXA_SUCCESS; } rdev->corrupted = FALSE; return EXA_SUCCESS; }
bool rain1_spof_group_has_defect(const rain1_group_t *rxg, const spof_group_t *spof_group) { size_t i; /* The SPOF group has defect if any of its devices... */ for (i = 0; i < spof_group->nb_realdevs; i++) { const struct vrt_realdev *rdev = spof_group->realdevs[i]; const rain1_realdev_t *lr = RAIN1_REALDEV(rxg, rdev); sync_tag_t sync_tag = rxg->sync_tag; /* ... is down or corrupted */ if (! rdev_is_ok(rdev)) return true; /* ... or is not up-to-date */ if (!rain1_rdev_is_uptodate(lr, sync_tag)) return true; } return false; }
/** * Prepare an updating operation * * @param[in] ag assembly group * @param[in] lg rain1 group data * @param[in] spof_group The SPOF group to update */ static void rain1_group_prepare_updating(const struct assembly_group *ag, const rain1_group_t *lg, const spof_group_t *spof_group) { uint32_t i; for (i = 0; i < spof_group->nb_realdevs; i++) { struct vrt_realdev *rdev = spof_group->realdevs[i]; struct rain1_realdev *lr = RAIN1_REALDEV(lg, rdev); if (rdev_is_ok(rdev) && !rain1_rdev_is_uptodate(lr, lg->sync_tag)) { exalog_debug("New updating: update disk: index = %d, UUID = " UUID_FMT, rdev->index, UUID_VAL(&rdev->uuid)); rain1_rdev_init_rebuild_context(lr, EXA_RDEV_REBUILD_UPDATING, lg->sync_tag); } } }