Example #1
0
/**
 * Set oldest_lsid.
 *
 * @wdev walb dev.
 * @ctl ioctl data.
 * RETURN:
 *   0 in success, or -EFAULT.
 */
static int ioctl_wdev_set_oldest_lsid(struct walb_dev *wdev, struct walb_ctl *ctl)
{
	u64 lsid, oldest_lsid, written_lsid;

	LOGn("WALB_IOCTL_SET_OLDEST_LSID_SET\n");

	lsid = ctl->val_u64;

	spin_lock(&wdev->lsid_lock);
	written_lsid = wdev->lsids.written;
	oldest_lsid = wdev->lsids.oldest;
	spin_unlock(&wdev->lsid_lock);

	if (!(lsid == written_lsid ||
			(oldest_lsid <= lsid && lsid < written_lsid &&
				walb_check_lsid_valid(wdev, lsid)))) {
		LOGe("lsid %"PRIu64" is not valid.\n", lsid);
		LOGe("You shoud specify valid logpack header lsid"
			" (oldest_lsid (%"PRIu64") <= lsid <= written_lsid (%"PRIu64").\n",
			oldest_lsid, written_lsid);
		return -EFAULT;
	}

	spin_lock(&wdev->lsid_lock);
	wdev->lsids.oldest = lsid;
	spin_unlock(&wdev->lsid_lock);

	if (!walb_sync_super_block(wdev)) {
		LOGe("sync super block failed.\n");
		return -EFAULT;
	}
	return 0;
}
Example #2
0
/**
 * Resize walb device.
 *
 * @wdev walb dev.
 * @ctl ioctl data.
 * RETURN:
 *   0 in success, or -EFAULT.
 */
static int ioctl_wdev_resize(struct walb_dev *wdev, struct walb_ctl *ctl)
{
	u64 ddev_size;
	u64 new_size;
	u64 old_size;

	LOGn("WALB_IOCTL_RESIZE.\n");
	ASSERT(ctl->command == WALB_IOCTL_RESIZE);

	old_size = get_capacity(wdev->gd);
	new_size = ctl->val_u64;
	ddev_size = wdev->ddev->bd_part->nr_sects;

	if (new_size == 0) {
		new_size = ddev_size;
	}
	if (new_size < old_size) {
		LOGe("Shrink size from %"PRIu64" to %"PRIu64" is not supported.\n",
			old_size, new_size);
		return -EFAULT;
	}
	if (new_size > ddev_size) {
		LOGe("new_size %"PRIu64" > data device capacity %"PRIu64".\n",
			new_size, ddev_size);
		return -EFAULT;
	}
	if (new_size == old_size) {
		LOGn("No need to resize.\n");
		return 0;
	}

	spin_lock(&wdev->size_lock);
	wdev->size = new_size;
	wdev->ddev_size = ddev_size;
	spin_unlock(&wdev->size_lock);

	if (!resize_disk(wdev->gd, new_size)) {
		return -EFAULT;
	}

	/* Sync super block for super->device_size */
	if (!walb_sync_super_block(wdev)) {
		LOGe("superblock sync failed.\n");
		return -EFAULT;
	}
	return 0;
}
Example #3
0
/**
 * Take a checkpoint immediately.
 *
 * @cpd checkpoint data.
 *
 * RETURN:
 *   ture in success, or false.
 */
bool take_checkpoint(struct checkpoint_data *cpd)
{
    bool skip;
    struct walb_dev *wdev;

    ASSERT(cpd);
    wdev = get_wdev_from_checkpoint_data(cpd);
    ASSERT(wdev);

    /* Check the need of writing superblock. */
    spin_lock(&wdev->lsid_lock);
    skip = wdev->lsids.written == wdev->lsids.prev_written;
    spin_unlock(&wdev->lsid_lock);
    if (skip) {
        WLOG_(wdev, "skip superblock sync.\n");
        return true;
    }

    /* Write and flush super block at log device. */
    return walb_sync_super_block(wdev);
}
Example #4
0
/**
 * Clear log and detect resize of log device.
 *
 * @wdev walb dev.
 * @ctl ioctl data.
 * RETURN:
 *   0 in success, or -EFAULT.
 */
static int ioctl_wdev_clear_log(struct walb_dev *wdev, struct walb_ctl *ctl)
{
	u64 new_ldev_size, old_ldev_size;
	u8 new_uuid[UUID_SIZE], old_uuid[UUID_SIZE];
	unsigned int pbs = wdev->physical_bs;
	bool is_grown = false;
	struct walb_super_sector *super;
	u64 lsid0_off;
	struct lsid_set lsids;
	u64 old_ring_buffer_size;
	u32 new_salt;

	ASSERT(ctl->command == WALB_IOCTL_CLEAR_LOG);
	LOGn("WALB_IOCTL_CLEAR_LOG.\n");

	/* Freeze iocore and checkpointing.  */
	iocore_freeze(wdev);
	stop_checkpointing(&wdev->cpd);

	/* Get old/new log device size. */
	old_ldev_size = wdev->ldev_size;
	new_ldev_size = wdev->ldev->bd_part->nr_sects;

	if (old_ldev_size > new_ldev_size) {
		LOGe("Log device shrink not supported.\n");
		goto error0;
	}

	/* Backup variables. */
	old_ring_buffer_size = wdev->ring_buffer_size;
	backup_lsid_set(wdev, &lsids);

	/* Initialize lsid(s). */
	spin_lock(&wdev->lsid_lock);
	wdev->lsids.latest = 0;
	wdev->lsids.flush = 0;
	wdev->lsids.completed = 0;
	wdev->lsids.permanent = 0;
	wdev->lsids.written = 0;
	wdev->lsids.prev_written = 0;
	wdev->lsids.oldest = 0;
	spin_unlock(&wdev->lsid_lock);

	/* Grow the walblog device. */
	if (old_ldev_size < new_ldev_size) {
		LOGn("Detect log device size change.\n");

		/* Grow the disk. */
		is_grown = true;
		if (!resize_disk(wdev->log_gd, new_ldev_size)) {
			LOGe("grow disk failed.\n");
			iocore_set_readonly(wdev);
			goto error1;
		}
		LOGn("Grown log device size from %"PRIu64" to %"PRIu64".\n",
			old_ldev_size, new_ldev_size);
		wdev->ldev_size = new_ldev_size;

		/* Recalculate ring buffer size. */
		wdev->ring_buffer_size =
			addr_pb(pbs, new_ldev_size)
			- get_ring_buffer_offset(pbs);
	}

	/* Generate new uuid and salt. */
	get_random_bytes(new_uuid, 16);
	get_random_bytes(&new_salt, sizeof(new_salt));
	wdev->log_checksum_salt = new_salt;

	/* Update superblock image. */
	spin_lock(&wdev->lsuper0_lock);
	super = get_super_sector(wdev->lsuper0);
	memcpy(old_uuid, super->uuid, UUID_SIZE);
	memcpy(super->uuid, new_uuid, UUID_SIZE);
	super->ring_buffer_size = wdev->ring_buffer_size;
	super->log_checksum_salt = new_salt;
	/* super->metadata_size; */
	lsid0_off = get_offset_of_lsid_2(super, 0);
	spin_unlock(&wdev->lsuper0_lock);

	/* Sync super sector. */
	if (!walb_sync_super_block(wdev)) {
		LOGe("sync superblock failed.\n");
		iocore_set_readonly(wdev);
		goto error2;
	}

	/* Invalidate first logpack */
	if (!invalidate_lsid(wdev, 0)) {
		LOGe("invalidate lsid 0 failed.\n");
		iocore_set_readonly(wdev);
		goto error2;
	}

	/* Clear log overflow. */
	iocore_clear_log_overflow(wdev);

	/* Melt iocore and checkpointing. */
	start_checkpointing(&wdev->cpd);
	iocore_melt(wdev);

	return 0;

error2:
	restore_lsid_set(wdev, &lsids);
	wdev->ring_buffer_size = old_ring_buffer_size;
#if 0
	wdev->ldev_size = old_ldev_size;
	if (!resize_disk(wdev->log_gd, old_ldev_size)) {
		LOGe("resize_disk to shrink failed.\n");
	}
#endif
error1:
	start_checkpointing(&wdev->cpd);
	iocore_melt(wdev);
error0:
	return -EFAULT;
}