Re: [PATCH 0/2][RFC] postcopy migration: Linux char device for postcopy

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Thu, Dec 29, 2011 at 10:26:16AM +0900, Isaku Yamahata wrote:

> UMEM_DEV_LIST: list created umem devices
> UMEM_DEV_REATTACH: re-attach the created umem device
> 		  UMEM_DEV_LIST and UMEM_DEV_REATTACH are used when
> 		  the process that services page fault disappears or get stack.
> 		  Then, administrator can list the umem devices and unblock
> 		  the process which is waiting for page.

Here is a simple utility which cleans up umem devices.

---------------------------------------------------------------------------

/*
 * simple clean up utility of for umem devices
 *
 * Copyright (c) 2011,
 * National Institute of Advanced Industrial Science and Technology
 *
 * https://sites.google.com/site/grivonhome/quick-kvm-migration
 * Author: Isaku Yamahata <yamahata at valinux co jp>
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms and conditions of the GNU General Public License,
 * version 2, as published by the Free Software Foundation.
 *
 * This program is distributed in the hope it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 * more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, see <http://www.gnu.org/licenses/>.
 */

#include <err.h>
#include <errno.h>
#include <inttypes.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <fcntl.h>

#include <linux/umem.h>

void mark_all_pages_cached(int umem_dev_fd, const char *id, const char *name)
{
	struct umem_create create;
	memset(&create, 0, sizeof(create));
	strncpy(create.name.id, id, sizeof(create.name.id));
	strncpy(create.name.name, name, sizeof(create.name.name));

	if (ioctl(umem_dev_fd, UMEM_DEV_REATTACH, &create) < 0) {
		err(EXIT_FAILURE, "UMEM_DEV_REATTACH");
	}

	close(create.shmem_fd);
	long page_size = sysconf(_SC_PAGESIZE);
	int page_shift = ffs(page_size) - 1;
	int umem_fd = create.umem_fd;
	printf("umem_fd %d size %"PRId64"\n", umem_fd, (uint64_t)create.size);

	__u64 i;
	__u64 e_pgoff = (create.size + page_size - 1) >> page_shift;
#define UMEM_CACHED_MAX	512
	__u64 pgoffs[UMEM_CACHED_MAX];
	struct umem_page_cached page_cached = {
		.nr = 0,
		.pgoffs = pgoffs,
	};

	for (i = 0; i < e_pgoff; i++) {
		page_cached.pgoffs[page_cached.nr] = i;
		page_cached.nr++;
		if (page_cached.nr == UMEM_CACHED_MAX) {
			if (ioctl(umem_fd, UMEM_MARK_PAGE_CACHED,
				  &page_cached) < 0) {
				err(EXIT_FAILURE, "UMEM_MARK_PAGE_CACHED");
			}
			page_cached.nr = 0;
		}
	}
	if (page_cached.nr > 0) {
		if (ioctl(umem_fd, UMEM_MARK_PAGE_CACHED, &page_cached) < 0) {
			err(EXIT_FAILURE, "UMEM_MARK_PAGE_CACHED");
		}
	}
	close(umem_fd);
}

#define DEV_UMEM	"/dev/umem"

int main(int argc, char **argv)
{
	const char *id = NULL;
	const char *name = NULL;
	if (argc >= 2) {
		id = argv[1];
	}
	if (argc >= 3) {
		name = argv[2];
	}

	int umem_dev_fd = open(DEV_UMEM, O_RDWR);
	if (umem_dev_fd < 0) {
		perror("can't open "DEV_UMEM);
		exit(EXIT_FAILURE);
	}

	struct umem_list tmp_ulist = {
		.nr = 0,
	};
	if (ioctl(umem_dev_fd, UMEM_DEV_LIST, &tmp_ulist) < 0) {
		err(EXIT_FAILURE, "UMEM_DEV_LIST");
	}
	if (tmp_ulist.nr == 0) {
		printf("no umem files\n");
		exit(EXIT_SUCCESS);
	}
	struct umem_list *ulist = malloc(
		sizeof(*ulist) + sizeof(ulist->names[0]) * tmp_ulist.nr);
	ulist->nr = tmp_ulist.nr;
	if (ioctl(umem_dev_fd, UMEM_DEV_LIST, ulist) < 0) {
		err(EXIT_FAILURE, "UMEM_DEV_LIST");
	}

	uint32_t i;
	for (i = 0; i < ulist->nr; ++i) {
		char *u_id = ulist->names[i].id;
		char *u_name = ulist->names[i].name;

		char tmp_id_c = u_id[UMEM_ID_MAX - 1];
		char tmp_name_c = u_name[UMEM_NAME_MAX - 1];
		u_id[UMEM_ID_MAX - 1] = '\0';
		u_name[UMEM_NAME_MAX - 1] = '\0';
		printf("%d: id: %s name: %s\n", i, u_id, u_name);

		if ((id != NULL || name != NULL) &&
		    (id == NULL || strncmp(id, u_id, UMEM_ID_MAX) == 0) &&
		    (name == NULL ||
		     strncmp(name, u_name, UMEM_NAME_MAX) == 0)) {
			printf("marking cached: %d: id: %s name: %s\n",
			       i, u_id, u_name);
			u_id[UMEM_ID_MAX - 1] = tmp_id_c;
			u_name[UMEM_NAME_MAX - 1] = tmp_name_c;
			mark_all_pages_cached(umem_dev_fd, u_id, u_name);
		}
	}

	close(umem_dev_fd);
	return 0;
}
--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [KVM ARM]     [KVM ia64]     [KVM ppc]     [Virtualization Tools]     [Spice Development]     [Libvirt]     [Libvirt Users]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite Questions]     [Linux Kernel]     [Linux SCSI]     [XFree86]
  Powered by Linux