Пример #1
0
void free_ploop_copy_handle(struct ploop_copy_handle *h)
{
	if (h == NULL)
		return;

	pthread_mutex_destroy(&h->sd.mutex);
	pthread_cond_destroy(&h->sd.cond);
	pthread_mutex_destroy(&h->sd.wait_mutex);
	pthread_cond_destroy(&h->sd.wait_cond);

	unregister_cleanup_hook(h->cl);

	free(h->iobuf[0]);
	free(h->iobuf[1]);

	free(h);
}
Пример #2
0
static int __ploop_discard(struct ploop_disk_images_data *di, int fd,
			const char *device, const char *mount_point,
			__u64 minlen_b, __u32 cluster, __u32 to_free,
			__u64 blk_discard_range[2], const int *stop)
{
	pid_t tpid;
	int err = 0, ret, status;
	__u32 size = 0;
	struct ploop_cleanup_hook *h;

	if (blk_discard_range != NULL)
		ploop_log(0, "Discard %s start=%" PRIu64 " length=%" PRIu64,
				device, (uint64_t)blk_discard_range[0], (uint64_t)blk_discard_range[1]);
	else
		ploop_log(3, "Trying to find free extents bigger than %" PRIu64 " bytes", (uint64_t)minlen_b);

	if (ploop_lock_di(di))
		return SYSEXIT_LOCK;
	ret = ioctl_device(fd, PLOOP_IOC_DISCARD_INIT, NULL);
	ploop_unlock_di(di);
	if (ret) {
		ploop_err(errno, "Can't initialize discard mode");
		return ret;
	}

	tpid = fork();
	if (tpid < 0) {
		ploop_err(errno, "Can't fork");
		ret = ioctl_device(fd, PLOOP_IOC_DISCARD_FINI, NULL);
		if (ret) {
			ploop_err(errno, "Can't finalize discard mode");
			return ret;
		}
	}

	h = register_cleanup_hook(cancel_discard, (void *) device);

	if (tpid == 0) {
		if (blk_discard_range != NULL)
			ret = blk_discard(fd, cluster, blk_discard_range[0], blk_discard_range[1]);
		else
			ret = ploop_trim(mount_point, minlen_b, cluster);
		if (ioctl_device(fd, PLOOP_IOC_DISCARD_FINI, NULL))
			ploop_err(errno, "Can't finalize discard mode");

		exit(ret != 0);
	}

	while (1) {
		struct ploop_balloon_ctl b_ctl;

		ploop_log(3, "Waiting");
		ret = ioctl(fd, PLOOP_IOC_DISCARD_WAIT, NULL);
		if (ret < 0) {
			ploop_err(errno, "Waiting for a discard request failed");
			break;
		} else if (ret == 0)
			break;

		/* FIXME PLOOP_IOC_DISCARD_WAIT should return size */
		ret = ioctl(fd, PLOOP_IOC_FBFILTER, 0);
		if (ret < 0) {
			ploop_err(errno, "Can't filter free blocks");
			break;
		} else if (ret == 0) {
			/* Nothing to do */
			ret = ioctl_device(fd, PLOOP_IOC_FBDROP, 0);
			if (ret)
				break;
			continue;
		} else
			size += ret;
		/* serialize ploop operations vs ploop_complete_running_operation()
		 * NB: PLOOP_IOC_BALLOON may change mntn from PLOOP_MNTN_DISCARD:
		 * to PLOOP_MNTN_FBLOADED
		 */
		if (ploop_lock_di(di)) {
			ret = SYSEXIT_LOCK;
			break;
		}

		memset(&b_ctl, 0, sizeof(b_ctl));
		b_ctl.keep_intact = 1;
		ret = ioctl_device(fd, PLOOP_IOC_BALLOON, &b_ctl);
		if (ret) {
			ploop_unlock_di(di);
			break;
		}

		if (b_ctl.mntn_type == PLOOP_MNTN_OFF) {
			ploop_log(0, "Unexpected maintenance type 0x%x", b_ctl.mntn_type);
			ret = -1;
			ploop_unlock_di(di);
			break;
		}

		if (size >= to_free || (stop && *stop)) {
			ploop_log(3, "Killing the trim process %d", tpid);
			kill(tpid, SIGUSR1);
			ret = ioctl(fd, PLOOP_IOC_DISCARD_FINI);
			if (ret < 0 && errno != EBUSY)
				ploop_err(errno, "Can't finalize a discard mode");
		}

		ploop_log(0, "Starting relocation");
		ret = ploop_balloon_relocation(fd, &b_ctl, device);
		ploop_unlock_di(di);
		if (ret)
			break;
	}

	if (ret) {
		err = -1;

		ret = ioctl(fd, PLOOP_IOC_DISCARD_FINI);
		if (ret < 0) {
			if (errno == EBUSY)
				ploop_log(-1, "Discard finalized, but "
					"relocation is still not completed");
			else
				ploop_err(errno, "Can't finalize discard mode");
		}

		kill(tpid, SIGKILL);
	} else {
		ploop_log(0, "%d clusters have been relocated", size);
	}

	unregister_cleanup_hook(h);

	while ((ret = waitpid(tpid, &status, 0)))
		 if (errno != EINTR)
			break;
	if (ret == -1) {
		if (errno != ECHILD)
			ploop_err(errno, "wait() failed");
		err = -1;
	} else if (WIFEXITED(status)) {
		ret = WEXITSTATUS(status);
		if (ret) {
			ploop_err(0, "The trim process failed with code %d", ret);
			err = -1;
		}
	} else if (WIFSIGNALED(status)) {
		ploop_err(0, "The trim process killed by signal %d", WTERMSIG(status));
		err = -1;
	} else {
		ploop_err(0, "The trim process died abnormally");
		err = -1;
	}

	return err;
}