qemu-devel
[Top][All Lists]
Advanced

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

Re: [Qemu-devel] [PATCH 0/2][RFC] postcopy migration: Linux char device


From: Isaku Yamahata
Subject: Re: [Qemu-devel] [PATCH 0/2][RFC] postcopy migration: Linux char device for postcopy
Date: Thu, 29 Dec 2011 10:31:43 +0900
User-agent: Mutt/1.5.19 (2009-01-05)

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;
}



reply via email to

[Prev in Thread] Current Thread [Next in Thread]