Пример #1
0
static int freeze_fs(struct ploop_copy_handle *h)
{
	int ret;

	if (h->mntfd != -1) {
		/* Sync fs */
		ploop_dbg(4, "SYNCFS");
		if (sys_syncfs(h->mntfd)) {
			ploop_err(errno, "syncfs() failed");
			ret = SYSEXIT_FSYNC;
			goto err;
		}

		/* Flush journal and freeze fs (this also clears the fs dirty bit) */
		ploop_dbg(4, "FIFREEZE");
		ret = ioctl_device(h->mntfd, FIFREEZE, 0);
		if (ret)
			goto err;

		h->fs_frozen = 1;
	}

	ploop_dbg(4, "IOC_SYNC");
	ret = ioctl_device(h->devfd, PLOOP_IOC_SYNC, 0);
	if (ret)
		goto err;

	return 0;
err:
	ploop_copy_release(h);
	return ret;
}
Пример #2
0
int ploop_copy_start(struct ploop_copy_handle *h,
		struct ploop_copy_stat *stat)
{
	int ret;
	struct ploop_track_extent e;
	ssize_t n;
	__u64 pos;

	ret = pthread_create(&h->send_th, NULL, sender_thread, h);
	if (ret) {
		ploop_err(ret, "Can't create send thread");
		ret = SYSEXIT_SYS;
		goto err;
	}

	pthread_barrier_wait(&h->sd.barrier);

	ploop_dbg(3, "pcopy track init");
	ret = ioctl_device(h->devfd, PLOOP_IOC_TRACK_INIT, &e);
	if (ret)
		goto err;

	h->tracker_on = 1;
	h->trackend = e.end;
	ploop_log(3, "pcopy start %s e.end=%" PRIu64,
			h->async ? "async" : "", (uint64_t)e.end);
	for (pos = 0; pos <= h->trackend; ) {
		h->trackpos = pos + h->cluster;
		ret = ioctl_device(h->devfd, PLOOP_IOC_TRACK_SETPOS, &h->trackpos);
		if (ret)
			goto err;

		ret = send_image_block(h, h->cluster, pos, &n);
		if (ret)
			goto err;
		if (n == 0) /* EOF */
			break;

		pos += n;
		if (pos > h->eof_offset)
			h->eof_offset = pos;
	}

	wait_sender(h);

	stat->xferred_total = stat->xferred = pos;
	send_cmd(h, PCOPY_CMD_SYNC);
	ploop_dbg(3, "pcopy start finished");

	return 0;
err:
	ploop_copy_release(h);

	return ret;
}
Пример #3
0
static int freeze(struct ploop_copy_handle *h)
{
	int ret;

	ret = ioctl(h->partfd, PLOOP_IOC_FREEZE);
	if (ret) {
		if (errno == EINVAL)
			ret = freeze_fs(h);
		else
			ploop_err(errno, "Failed to freeze device");
		if (ret)
			goto err;

	} else {
		ploop_log(0, "Freezing device...");
		h->dev_frozen = 1;
	}

	ploop_dbg(3, "IOC_SYNC");
	ret = ioctl_device(h->devfd, PLOOP_IOC_SYNC, 0);
	if (ret)
		goto err;

	return 0;
err:
	ploop_copy_release(h);
	return ret;
}
Пример #4
0
static void *sender_thread(void *data)
{
	struct ploop_copy_handle *h = data;
	struct sender_data *sd = &h->sd;
	int done;

	pthread_mutex_lock(&sd->mutex);
	ploop_dbg(3, "start sender_thread");
	pthread_barrier_wait(&sd->barrier);
	do {
		pthread_cond_wait(&sd->cond, &sd->mutex);

		wakeup(&sd->wait_mutex, &sd->wait_cond);

		sd->ret = send_buf(h, sd->buf, sd->len, sd->pos);
		if (sd->ret)
			sd->err_no = errno;
		done = (sd->len == 0 && sd->pos == 0);
	} while (!done);

	pthread_mutex_unlock(&sd->mutex);

	ploop_log(3, "send_thread exited ret=%d", sd->ret);
	return NULL;
}
Пример #5
0
void ploop_copy_deinit(struct ploop_copy_handle *h)
{
	if (h == NULL)
		return;

	ploop_dbg(4, "pcopy deinit");

	pthread_mutex_unlock(&h->sd.wait_mutex);

	if (h->send_th) {
		pthread_cancel(h->send_th);
		pthread_join(h->send_th, NULL);
		h->send_th = 0;
	}

	ploop_copy_release(h);
	free_ploop_copy_handle(h);

	ploop_dbg(3, "pcopy deinit done");
}
Пример #6
0
static int send_image_block(struct ploop_copy_handle *h, __u64 size,
		__u64 pos, ssize_t *nread)
{
	struct delta *idelta = &h->idelta;
	void *iobuf = get_free_iobuf(h);

	ploop_dbg(4, "READ size=%llu pos=%llu", size, pos);
	*nread = pread(idelta->fd, iobuf, size, pos);
	if (*nread == 0)
		return 0;
	if (*nread < 0) {
		ploop_err(errno, "Error from read");
		return SYSEXIT_READ;
	}

	return send_async(h, iobuf, *nread, pos);
}
Пример #7
0
static int freeze_fs(struct ploop_copy_handle *h)
{
	int ret;

	if (h->mntfd != -1) {
		/* Sync fs */
		ploop_log(0, "Freezing fs...");
		if (sys_syncfs(h->mntfd)) {
			ploop_err(errno, "syncfs() failed");
			return SYSEXIT_FSYNC;
		}

		/* Flush journal and freeze fs (this also clears the fs dirty bit) */
		ploop_dbg(3, "FIFREEZE");
		ret = ioctl_device(h->mntfd, FIFREEZE, 0);
		if (ret)
			return ret;

		h->fs_frozen = 1;
	}

	return 0;
}
Пример #8
0
int ploop_copy_stop(struct ploop_copy_handle *h,
		struct ploop_copy_stat *stat)
{
	int ret;
	int iter;

	ploop_log(3, "pcopy last");

	ret = freeze(h);
	if (ret)
		goto err;

	iter = 1;
	for (;;) {
		ret = ploop_copy_next_iteration(h, stat);
		if (ret)
			goto err;
		else if (stat->xferred == 0)
			break;
		if (iter++ > 2) {
			ploop_err(0, "Too many iterations on frozen FS, aborting");
			return SYSEXIT_LOOP;
		}
	}

	if (!h->raw) {
		/* Must clear dirty flag on ploop1 image. */
		struct ploop_pvd_header *vh = get_free_iobuf(h);

		if (PREAD(&h->idelta, vh, 4096, 0)) {
			ret = SYSEXIT_READ;
			goto err;
		}

		vh->m_DiskInUse = 0;

		ploop_dbg(3, "Update header");

		ret = send_buf(h, vh, 4096, 0);
		if (ret)
			goto err;

		ret = send_optional_header(h);
		if (ret)
			goto err;
	}

	ploop_dbg(4, "IOCTL TRACK_STOP");
	ret = ioctl(h->devfd, PLOOP_IOC_TRACK_STOP, 0);
	if (ret)
		goto err;

	h->tracker_on = 0;

	ploop_dbg(3, "SEND 0 0 (close)");
	send_async(h, NULL, 0, 0);

	pthread_join(h->send_th, NULL);
	h->send_th = 0;

	ploop_dbg(3, "pcopy stop done");

err:
	ploop_copy_release(h);

	return ret;
}
Пример #9
0
int ploop_copy_next_iteration(struct ploop_copy_handle *h,
		struct ploop_copy_stat *stat)
{
	struct ploop_track_extent e;
	int ret = 0;
	int done = 0;
	__u64 pos;
	__u64 iterpos = 0;

	stat->xferred = 0;
	ploop_dbg(3, "pcopy iter %d", h->niter);
	do {
		if (ioctl(h->devfd, PLOOP_IOC_TRACK_READ, &e)) {
			if (errno == EAGAIN) /* no more dirty blocks */
				break;

			ploop_err(errno, "PLOOP_IOC_TRACK_READ");
			ret = SYSEXIT_DEVIOC;
			goto err;
		}

		if (e.end > h->trackend)
			h->trackend = e.end;

		if (e.start < iterpos)
			done = 1;

		iterpos = e.end;
		stat->xferred += e.end - e.start;

		for (pos = e.start; pos < e.end; ) {
			ssize_t n;
			__u64 copy = e.end - pos;

			if (copy > h->cluster)
				copy = h->cluster;

			if (pos + copy > h->trackpos) {
				h->trackpos = pos + copy;
				if (ioctl(h->devfd, PLOOP_IOC_TRACK_SETPOS, &h->trackpos)) {
					ploop_err(errno, "PLOOP_IOC_TRACK_SETPOS");
					ret = SYSEXIT_DEVIOC;
					goto err;
				}
			}

			ret = send_image_block(h, copy, pos, &n);
			if (ret)
				goto err;
			if (n != copy) {
				ploop_err(errno, "Short read");
				ret = SYSEXIT_READ;
				goto err;
			}

			pos += n;
			if (pos > h->eof_offset)
				h->eof_offset = pos;
		}
	} while (!done);

	wait_sender(h);

	/* sync after each iteration */
	ret = send_cmd(h, PCOPY_CMD_SYNC);
	if (ret)
		goto err;

	stat->xferred_total += stat->xferred;

	ploop_log(3, "pcopy iter %d xferred=%" PRIu64,
			h->niter++, (uint64_t)stat->xferred);

	return 0;

err:
	ploop_copy_release(h);
	return ret;
}
Пример #10
0
int ploop_copy_receiver(struct ploop_copy_receive_param *arg)
{
	int ofd, ret;
	__u64 cluster = 0;
	void *iobuf = NULL;
	int n;
	struct pcopy_pkt_desc desc;

	if (!arg)
		return SYSEXIT_PARAM;

	if (is_fd_socket(arg->ifd) != 1) {
		ploop_err(errno, "Invalid input fd %d: must be "
				"a pipe or a socket", arg->ifd);
		return SYSEXIT_PARAM;
	}

	ofd = open(arg->file, O_WRONLY|O_CREAT|O_TRUNC, 0600);
	if (ofd < 0) {
		ploop_err(errno, "Can't open %s", arg->file);
		return SYSEXIT_CREAT;
	}

	ploop_dbg(3, "RCV start %s", arg->file);
	for (;;) {
		if (nread(arg->ifd, &desc, sizeof(desc)) < 0) {
			ploop_err(errno, "Error in nread(desc)");
			ret = SYSEXIT_READ;
			goto out;
		}

		if (desc.marker != PCOPY_MARKER) {
			ploop_err(0, "Stream corrupted");
			ret = SYSEXIT_PROTOCOL;
			goto out;
		}

		if (desc.size > cluster) {
			free(iobuf);
			iobuf = NULL;
			cluster = desc.size;
			if (p_memalign(&iobuf, 4096, cluster)) {
				ret = SYSEXIT_MALLOC;
				goto out;
			}
		}

		if (desc.size == 0)
			break;

		if (nread(arg->ifd, iobuf, desc.size)) {
			ploop_err(errno, "Error in nread data");
			ret = SYSEXIT_READ;
			goto out;
		}

		ploop_log(3, "RCV type=%d len=%d pos=%" PRIu64,
				desc.type, desc.size, (uint64_t)desc.pos);
		ret = 0;
		switch (desc.type) {
		case PCOPY_PKT_DATA:
		case PCOPY_PKT_DATA_ASYNC: {
			n = TEMP_FAILURE_RETRY(pwrite(ofd, iobuf, desc.size, desc.pos));
			if (n != desc.size) {
				if (n < 0)
					ploop_err(errno, "Error in pwrite");
				else
					ploop_err(0, "Error: short pwrite");
				ret = SYSEXIT_WRITE;
				goto out;
			}
			break;
		}
		case PCOPY_PKT_CMD: {
			unsigned int cmd = ((unsigned int *) iobuf)[0];
			switch(cmd) {
			case PCOPY_CMD_SYNC:
				ret = data_sync(ofd);
				if (ret)
					goto out;
				break;
			default:
				ploop_err(0, "ploop_copy_receiver: unsupported command %d",
						cmd);
				ret = SYSEXIT_PARAM;
			}
			break;
		}
		default:
			ploop_err(0, "ploop_copy_receiver: unsupported command type%d",
						desc.type);
			ret = SYSEXIT_PARAM;
			break;
		}

		/* send reply */
		if (desc.type != PCOPY_PKT_DATA_ASYNC &&
				nwrite(arg->ifd, &ret, sizeof(int))) {
			ret = SYSEXIT_WRITE;
			ploop_err(errno, "failed to send reply");
			goto out;
		}
	}

	ret = data_sync(ofd);
	if (ret)
		goto out;

	ploop_dbg(3, "RCV exited");
	/* send final reply */
	ret = 0;
	if (nwrite(arg->ifd, &ret, sizeof(int))) {
		ret = SYSEXIT_WRITE;
		ploop_err(errno, "failed to send reply");
		goto out;
	}

out:
	if (close(ofd)) {
		ploop_err(errno, "Error in close");
		if (!ret)
			ret = SYSEXIT_WRITE;
	}
	if (ret)
		unlink(arg->file);
	free(iobuf);

	return ret;
}