public inbox for kvm@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/9] kvm tools: Don't dynamically allocate threadpool jobs
@ 2011-06-29 18:02 Sasha Levin
  2011-06-29 18:02 ` [PATCH 2/9] kvm tools: Process virtio-blk requests in parallel Sasha Levin
                   ` (7 more replies)
  0 siblings, 8 replies; 14+ messages in thread
From: Sasha Levin @ 2011-06-29 18:02 UTC (permalink / raw)
  To: penberg; +Cc: kvm, mingo, asias.hejun, gorcunov, prasadjoshi124, Sasha Levin

To allow efficient use of shorter-term threadpool jobs, don't
allocate them dynamically upon creation. Instead, store them
within 'job' structures.

This will prevent some overhead creating/destroying jobs which live
for a short time.

Signed-off-by: Sasha Levin <levinsasha928@gmail.com>
---
 tools/kvm/include/kvm/threadpool.h |   29 ++++++++++++++++++++++++++---
 tools/kvm/threadpool.c             |   30 ++----------------------------
 tools/kvm/virtio/9p.c              |   12 ++++++------
 tools/kvm/virtio/blk.c             |    8 ++++----
 tools/kvm/virtio/console.c         |   10 +++++-----
 tools/kvm/virtio/rng.c             |   16 ++++++++--------
 6 files changed, 51 insertions(+), 54 deletions(-)

diff --git a/tools/kvm/include/kvm/threadpool.h b/tools/kvm/include/kvm/threadpool.h
index 62826a6..768239f 100644
--- a/tools/kvm/include/kvm/threadpool.h
+++ b/tools/kvm/include/kvm/threadpool.h
@@ -1,14 +1,37 @@
 #ifndef KVM__THREADPOOL_H
 #define KVM__THREADPOOL_H
 
+#include "kvm/mutex.h"
+
+#include <linux/list.h>
+
 struct kvm;
 
 typedef void (*kvm_thread_callback_fn_t)(struct kvm *kvm, void *data);
 
-int thread_pool__init(unsigned long thread_count);
+struct thread_pool__job {
+	kvm_thread_callback_fn_t	callback;
+	struct kvm			*kvm;
+	void				*data;
+
+	int				signalcount;
+	pthread_mutex_t			mutex;
 
-void *thread_pool__add_job(struct kvm *kvm, kvm_thread_callback_fn_t callback, void *data);
+	struct list_head		queue;
+};
+
+static inline void thread_pool__init_job(struct thread_pool__job *job, struct kvm *kvm, kvm_thread_callback_fn_t callback, void *data)
+{
+	*job = (struct thread_pool__job) {
+		.kvm		= kvm,
+		.callback	= callback,
+		.data		= data,
+		.mutex		= PTHREAD_MUTEX_INITIALIZER,
+	};
+}
+
+int thread_pool__init(unsigned long thread_count);
 
-void thread_pool__do_job(void *job);
+void thread_pool__do_job(struct thread_pool__job *job);
 
 #endif
diff --git a/tools/kvm/threadpool.c b/tools/kvm/threadpool.c
index 2db02184..fdc5fa7 100644
--- a/tools/kvm/threadpool.c
+++ b/tools/kvm/threadpool.c
@@ -6,17 +6,6 @@
 #include <pthread.h>
 #include <stdbool.h>
 
-struct thread_pool__job {
-	kvm_thread_callback_fn_t	callback;
-	struct kvm			*kvm;
-	void				*data;
-
-	int				signalcount;
-	pthread_mutex_t			mutex;
-
-	struct list_head		queue;
-};
-
 static pthread_mutex_t	job_mutex	= PTHREAD_MUTEX_INITIALIZER;
 static pthread_mutex_t	thread_mutex	= PTHREAD_MUTEX_INITIALIZER;
 static pthread_cond_t	job_cond	= PTHREAD_COND_INITIALIZER;
@@ -139,26 +128,11 @@ int thread_pool__init(unsigned long thread_count)
 	return i;
 }
 
-void *thread_pool__add_job(struct kvm *kvm,
-			       kvm_thread_callback_fn_t callback, void *data)
-{
-	struct thread_pool__job *job = calloc(1, sizeof(*job));
-
-	*job = (struct thread_pool__job) {
-		.kvm		= kvm,
-		.data		= data,
-		.callback	= callback,
-		.mutex		= PTHREAD_MUTEX_INITIALIZER
-	};
-
-	return job;
-}
-
-void thread_pool__do_job(void *job)
+void thread_pool__do_job(struct thread_pool__job *job)
 {
 	struct thread_pool__job *jobinfo = job;
 
-	if (jobinfo == NULL)
+	if (jobinfo == NULL || jobinfo->callback == NULL)
 		return;
 
 	mutex_lock(&jobinfo->mutex);
diff --git a/tools/kvm/virtio/9p.c b/tools/kvm/virtio/9p.c
index d2d738d..b1a8c01 100644
--- a/tools/kvm/virtio/9p.c
+++ b/tools/kvm/virtio/9p.c
@@ -46,9 +46,9 @@ struct p9_fid {
 };
 
 struct p9_dev_job {
-	struct virt_queue		*vq;
-	struct p9_dev			*p9dev;
-	void				*job_id;
+	struct virt_queue	*vq;
+	struct p9_dev		*p9dev;
+	struct thread_pool__job	job_id;
 };
 
 struct p9_dev {
@@ -696,7 +696,7 @@ static void ioevent_callback(struct kvm *kvm, void *param)
 {
 	struct p9_dev_job *job = param;
 
-	thread_pool__do_job(job->job_id);
+	thread_pool__do_job(&job->job_id);
 }
 
 static bool virtio_p9_pci_io_out(struct ioport *ioport, struct kvm *kvm,
@@ -731,7 +731,7 @@ static bool virtio_p9_pci_io_out(struct ioport *ioport, struct kvm *kvm,
 			.vq			= queue,
 			.p9dev			= p9dev,
 		};
-		job->job_id = thread_pool__add_job(kvm, virtio_p9_do_io, job);
+		thread_pool__init_job(&job->job_id, kvm, virtio_p9_do_io, job);
 
 		ioevent = (struct ioevent) {
 			.io_addr		= p9dev->base_addr + VIRTIO_PCI_QUEUE_NOTIFY,
@@ -754,7 +754,7 @@ static bool virtio_p9_pci_io_out(struct ioport *ioport, struct kvm *kvm,
 		u16 queue_index;
 
 		queue_index		= ioport__read16(data);
-		thread_pool__do_job(p9dev->jobs[queue_index].job_id);
+		thread_pool__do_job(&p9dev->jobs[queue_index].job_id);
 		break;
 	}
 	case VIRTIO_PCI_STATUS:
diff --git a/tools/kvm/virtio/blk.c b/tools/kvm/virtio/blk.c
index 8d54f5a..1fdfc1e 100644
--- a/tools/kvm/virtio/blk.c
+++ b/tools/kvm/virtio/blk.c
@@ -31,7 +31,7 @@
 struct blk_dev_job {
 	struct virt_queue		*vq;
 	struct blk_dev			*bdev;
-	void				*job_id;
+	struct thread_pool__job		job_id;
 };
 
 struct blk_dev {
@@ -206,7 +206,7 @@ static bool virtio_blk_pci_io_out(struct ioport *ioport, struct kvm *kvm, u16 po
 			.bdev			= bdev,
 		};
 
-		job->job_id = thread_pool__add_job(kvm, virtio_blk_do_io, job);
+		thread_pool__init_job(&job->job_id, kvm, virtio_blk_do_io, job);
 
 		break;
 	}
@@ -217,7 +217,7 @@ static bool virtio_blk_pci_io_out(struct ioport *ioport, struct kvm *kvm, u16 po
 		u16 queue_index;
 
 		queue_index		= ioport__read16(data);
-		thread_pool__do_job(bdev->jobs[queue_index].job_id);
+		thread_pool__do_job(&bdev->jobs[queue_index].job_id);
 
 		break;
 	}
@@ -248,7 +248,7 @@ static void ioevent_callback(struct kvm *kvm, void *param)
 {
 	struct blk_dev_job *job = param;
 
-	thread_pool__do_job(job->job_id);
+	thread_pool__do_job(&job->job_id);
 }
 
 void virtio_blk__init(struct kvm *kvm, struct disk_image *disk)
diff --git a/tools/kvm/virtio/console.c b/tools/kvm/virtio/console.c
index 038e53f..e5d59c0 100644
--- a/tools/kvm/virtio/console.c
+++ b/tools/kvm/virtio/console.c
@@ -51,7 +51,7 @@ struct con_dev {
 	u16				queue_selector;
 	u16				base_addr;
 
-	void				*jobs[VIRTIO_CONSOLE_NUM_QUEUES];
+	struct thread_pool__job		jobs[VIRTIO_CONSOLE_NUM_QUEUES];
 };
 
 static struct con_dev cdev = {
@@ -93,7 +93,7 @@ static void virtio_console__inject_interrupt_callback(struct kvm *kvm, void *par
 
 void virtio_console__inject_interrupt(struct kvm *kvm)
 {
-	thread_pool__do_job(cdev.jobs[VIRTIO_CONSOLE_RX_QUEUE]);
+	thread_pool__do_job(&cdev.jobs[VIRTIO_CONSOLE_RX_QUEUE]);
 }
 
 static bool virtio_console_pci_io_device_specific_in(void *data, unsigned long offset, int size, u32 count)
@@ -203,9 +203,9 @@ static bool virtio_console_pci_io_out(struct ioport *ioport, struct kvm *kvm, u1
 		vring_init(&queue->vring, VIRTIO_CONSOLE_QUEUE_SIZE, p, VIRTIO_PCI_VRING_ALIGN);
 
 		if (cdev.queue_selector == VIRTIO_CONSOLE_TX_QUEUE)
-			cdev.jobs[cdev.queue_selector] = thread_pool__add_job(kvm, virtio_console_handle_callback, queue);
+			thread_pool__init_job(&cdev.jobs[cdev.queue_selector], kvm, virtio_console_handle_callback, queue);
 		else if (cdev.queue_selector == VIRTIO_CONSOLE_RX_QUEUE)
-			cdev.jobs[cdev.queue_selector] = thread_pool__add_job(kvm, virtio_console__inject_interrupt_callback, queue);
+			thread_pool__init_job(&cdev.jobs[cdev.queue_selector], kvm, virtio_console__inject_interrupt_callback, queue);
 
 		break;
 	}
@@ -214,7 +214,7 @@ static bool virtio_console_pci_io_out(struct ioport *ioport, struct kvm *kvm, u1
 		break;
 	case VIRTIO_PCI_QUEUE_NOTIFY: {
 		u16 queue_index		= ioport__read16(data);
-		thread_pool__do_job(cdev.jobs[queue_index]);
+		thread_pool__do_job(&cdev.jobs[queue_index]);
 		break;
 	}
 	case VIRTIO_PCI_STATUS:
diff --git a/tools/kvm/virtio/rng.c b/tools/kvm/virtio/rng.c
index ede0e2b..1a7f569 100644
--- a/tools/kvm/virtio/rng.c
+++ b/tools/kvm/virtio/rng.c
@@ -21,13 +21,13 @@
 #include <sys/stat.h>
 #include <pthread.h>
 
-#define NUM_VIRT_QUEUES				1
-#define VIRTIO_RNG_QUEUE_SIZE			128
+#define NUM_VIRT_QUEUES		1
+#define VIRTIO_RNG_QUEUE_SIZE	128
 
 struct rng_dev_job {
-	struct virt_queue		*vq;
-	struct rng_dev			*rdev;
-	void				*job_id;
+	struct virt_queue	*vq;
+	struct rng_dev		*rdev;
+	struct thread_pool__job	job_id;
 };
 
 struct rng_dev {
@@ -146,7 +146,7 @@ static bool virtio_rng_pci_io_out(struct ioport *ioport, struct kvm *kvm, u16 po
 			.rdev			= rdev,
 		};
 
-		job->job_id = thread_pool__add_job(kvm, virtio_rng_do_io, job);
+		thread_pool__init_job(&job->job_id, kvm, virtio_rng_do_io, job);
 
 		break;
 	}
@@ -156,7 +156,7 @@ static bool virtio_rng_pci_io_out(struct ioport *ioport, struct kvm *kvm, u16 po
 	case VIRTIO_PCI_QUEUE_NOTIFY: {
 		u16 queue_index;
 		queue_index		= ioport__read16(data);
-		thread_pool__do_job(rdev->jobs[queue_index].job_id);
+		thread_pool__do_job(&rdev->jobs[queue_index].job_id);
 		break;
 	}
 	case VIRTIO_PCI_STATUS:
@@ -182,7 +182,7 @@ static void ioevent_callback(struct kvm *kvm, void *param)
 {
 	struct rng_dev_job *job = param;
 
-	thread_pool__do_job(job->job_id);
+	thread_pool__do_job(&job->job_id);
 }
 
 void virtio_rng__init(struct kvm *kvm)
-- 
1.7.6


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 2/9] kvm tools: Process virtio-blk requests in parallel
  2011-06-29 18:02 [PATCH 1/9] kvm tools: Don't dynamically allocate threadpool jobs Sasha Levin
@ 2011-06-29 18:02 ` Sasha Levin
  2011-06-29 18:02 ` [PATCH 3/9] kvm tools: Allow giving instance names Sasha Levin
                   ` (6 subsequent siblings)
  7 siblings, 0 replies; 14+ messages in thread
From: Sasha Levin @ 2011-06-29 18:02 UTC (permalink / raw)
  To: penberg; +Cc: kvm, mingo, asias.hejun, gorcunov, prasadjoshi124, Sasha Levin

Process multiple requests within a virtio-blk device's vring
in parallel.

Doing so may improve performance in cases when a request which can
be completed using data which is present in a cache is queued after
a request with un-cached data.

bonnie++ benchmarks have shown a 6% improvement with reads, and 2%
improvement in writes.

Suggested-by: Anthony Liguori <aliguori@us.ibm.com>
Signed-off-by: Sasha Levin <levinsasha928@gmail.com>
---
 tools/kvm/virtio/blk.c |   74 ++++++++++++++++++++++++-----------------------
 1 files changed, 38 insertions(+), 36 deletions(-)

diff --git a/tools/kvm/virtio/blk.c b/tools/kvm/virtio/blk.c
index 1fdfc1e..f2a728c 100644
--- a/tools/kvm/virtio/blk.c
+++ b/tools/kvm/virtio/blk.c
@@ -31,6 +31,8 @@
 struct blk_dev_job {
 	struct virt_queue		*vq;
 	struct blk_dev			*bdev;
+	struct iovec			iov[VIRTIO_BLK_QUEUE_SIZE];
+	u16				out, in, head;
 	struct thread_pool__job		job_id;
 };
 
@@ -51,7 +53,8 @@ struct blk_dev {
 	u16				queue_selector;
 
 	struct virt_queue		vqs[NUM_VIRT_QUEUES];
-	struct blk_dev_job		jobs[NUM_VIRT_QUEUES];
+	struct blk_dev_job		jobs[VIRTIO_BLK_QUEUE_SIZE];
+	u16				job_idx;
 	struct pci_device_header	pci_hdr;
 };
 
@@ -118,20 +121,26 @@ static bool virtio_blk_pci_io_in(struct ioport *ioport, struct kvm *kvm, u16 por
 	return ret;
 }
 
-static bool virtio_blk_do_io_request(struct kvm *kvm,
-					struct blk_dev *bdev,
-					struct virt_queue *queue)
+static void virtio_blk_do_io_request(struct kvm *kvm, void *param)
 {
-	struct iovec iov[VIRTIO_BLK_QUEUE_SIZE];
 	struct virtio_blk_outhdr *req;
-	ssize_t block_cnt = -1;
-	u16 out, in, head;
 	u8 *status;
+	ssize_t block_cnt;
+	struct blk_dev_job *job;
+	struct blk_dev *bdev;
+	struct virt_queue *queue;
+	struct iovec *iov;
+	u16 out, in, head;
 
-	head			= virt_queue__get_iov(queue, iov, &out, &in, kvm);
-
-	/* head */
-	req			= iov[0].iov_base;
+	block_cnt	= -1;
+	job		= param;
+	bdev		= job->bdev;
+	queue		= job->vq;
+	iov		= job->iov;
+	out		= job->out;
+	in		= job->in;
+	head		= job->head;
+	req		= iov[0].iov_base;
 
 	switch (req->type) {
 	case VIRTIO_BLK_T_IN:
@@ -153,24 +162,27 @@ static bool virtio_blk_do_io_request(struct kvm *kvm,
 	status			= iov[out + in - 1].iov_base;
 	*status			= (block_cnt < 0) ? VIRTIO_BLK_S_IOERR : VIRTIO_BLK_S_OK;
 
+	mutex_lock(&bdev->mutex);
 	virt_queue__set_used_elem(queue, head, block_cnt);
+	mutex_unlock(&bdev->mutex);
 
-	return true;
+	virt_queue__trigger_irq(queue, bdev->pci_hdr.irq_line, &bdev->isr, kvm);
 }
 
-static void virtio_blk_do_io(struct kvm *kvm, void *param)
+static void virtio_blk_do_io(struct kvm *kvm, struct virt_queue *vq, struct blk_dev *bdev)
 {
-	struct blk_dev_job *job	= param;
-	struct virt_queue *vq;
-	struct blk_dev *bdev;
+	while (virt_queue__available(vq)) {
+		struct blk_dev_job *job = &bdev->jobs[bdev->job_idx++ % VIRTIO_BLK_QUEUE_SIZE];
 
-	vq			= job->vq;
-	bdev			= job->bdev;
-
-	while (virt_queue__available(vq))
-		virtio_blk_do_io_request(kvm, bdev, vq);
+		*job			= (struct blk_dev_job) {
+			.vq			= vq,
+			.bdev			= bdev,
+		};
+		job->head = virt_queue__get_iov(vq, job->iov, &job->out, &job->in, kvm);
 
-	virt_queue__trigger_irq(vq, bdev->pci_hdr.irq_line, &bdev->isr, kvm);
+		thread_pool__init_job(&job->job_id, kvm, virtio_blk_do_io_request, job);
+		thread_pool__do_job(&job->job_id);
+	}
 }
 
 static bool virtio_blk_pci_io_out(struct ioport *ioport, struct kvm *kvm, u16 port, void *data, int size, u32 count)
@@ -190,24 +202,14 @@ static bool virtio_blk_pci_io_out(struct ioport *ioport, struct kvm *kvm, u16 po
 		break;
 	case VIRTIO_PCI_QUEUE_PFN: {
 		struct virt_queue *queue;
-		struct blk_dev_job *job;
 		void *p;
 
-		job = &bdev->jobs[bdev->queue_selector];
-
 		queue			= &bdev->vqs[bdev->queue_selector];
 		queue->pfn		= ioport__read32(data);
 		p			= guest_pfn_to_host(kvm, queue->pfn);
 
 		vring_init(&queue->vring, VIRTIO_BLK_QUEUE_SIZE, p, VIRTIO_PCI_VRING_ALIGN);
 
-		*job			= (struct blk_dev_job) {
-			.vq			= queue,
-			.bdev			= bdev,
-		};
-
-		thread_pool__init_job(&job->job_id, kvm, virtio_blk_do_io, job);
-
 		break;
 	}
 	case VIRTIO_PCI_QUEUE_SEL:
@@ -217,7 +219,7 @@ static bool virtio_blk_pci_io_out(struct ioport *ioport, struct kvm *kvm, u16 po
 		u16 queue_index;
 
 		queue_index		= ioport__read16(data);
-		thread_pool__do_job(&bdev->jobs[queue_index].job_id);
+		virtio_blk_do_io(kvm, &bdev->vqs[queue_index], bdev);
 
 		break;
 	}
@@ -246,9 +248,9 @@ static struct ioport_operations virtio_blk_io_ops = {
 
 static void ioevent_callback(struct kvm *kvm, void *param)
 {
-	struct blk_dev_job *job = param;
+	struct blk_dev *bdev = param;
 
-	thread_pool__do_job(&job->job_id);
+	virtio_blk_do_io(kvm, &bdev->vqs[0], bdev);
 }
 
 void virtio_blk__init(struct kvm *kvm, struct disk_image *disk)
@@ -309,7 +311,7 @@ void virtio_blk__init(struct kvm *kvm, struct disk_image *disk)
 			.io_len			= sizeof(u16),
 			.fn			= ioevent_callback,
 			.datamatch		= i,
-			.fn_ptr			= &bdev->jobs[i],
+			.fn_ptr			= bdev,
 			.fn_kvm			= kvm,
 			.fd			= eventfd(0, 0),
 		};
-- 
1.7.6


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 3/9] kvm tools: Allow giving instance names
  2011-06-29 18:02 [PATCH 1/9] kvm tools: Don't dynamically allocate threadpool jobs Sasha Levin
  2011-06-29 18:02 ` [PATCH 2/9] kvm tools: Process virtio-blk requests in parallel Sasha Levin
@ 2011-06-29 18:02 ` Sasha Levin
  2011-06-30  7:53   ` Pekka Enberg
  2011-06-29 18:02 ` [PATCH 4/9] kvm tools: Provide instance name when running 'kvm debug' Sasha Levin
                   ` (5 subsequent siblings)
  7 siblings, 1 reply; 14+ messages in thread
From: Sasha Levin @ 2011-06-29 18:02 UTC (permalink / raw)
  To: penberg; +Cc: kvm, mingo, asias.hejun, gorcunov, prasadjoshi124, Sasha Levin

This will allow tracking instance names and sending commands
to specific instances if multiple instances are running.

Signed-off-by: Sasha Levin <levinsasha928@gmail.com>
---
 tools/kvm/include/kvm/kvm.h |    5 +++-
 tools/kvm/kvm-run.c         |    5 +++-
 tools/kvm/kvm.c             |   55 ++++++++++++++++++++++++++++++++++++++++++-
 tools/kvm/term.c            |    3 ++
 4 files changed, 65 insertions(+), 3 deletions(-)

diff --git a/tools/kvm/include/kvm/kvm.h b/tools/kvm/include/kvm/kvm.h
index 7d90d35..5ad3236 100644
--- a/tools/kvm/include/kvm/kvm.h
+++ b/tools/kvm/include/kvm/kvm.h
@@ -41,9 +41,11 @@ struct kvm {
 	const char		*vmlinux;
 	struct disk_image       **disks;
 	int                     nr_disks;
+
+	const char		*name;
 };
 
-struct kvm *kvm__init(const char *kvm_dev, u64 ram_size);
+struct kvm *kvm__init(const char *kvm_dev, u64 ram_size, const char *name);
 int kvm__max_cpus(struct kvm *kvm);
 void kvm__init_ram(struct kvm *kvm);
 void kvm__delete(struct kvm *kvm);
@@ -61,6 +63,7 @@ bool kvm__deregister_mmio(struct kvm *kvm, u64 phys_addr);
 void kvm__pause(void);
 void kvm__continue(void);
 void kvm__notify_paused(void);
+int kvm__get_pid_by_instance(const char *name);
 
 /*
  * Debugging
diff --git a/tools/kvm/kvm-run.c b/tools/kvm/kvm-run.c
index 0dece2d..a4abf76 100644
--- a/tools/kvm/kvm-run.c
+++ b/tools/kvm/kvm-run.c
@@ -69,6 +69,7 @@ static const char *network;
 static const char *host_ip_addr;
 static const char *guest_mac;
 static const char *script;
+static const char *guest_name;
 static bool single_step;
 static bool readonly_image[MAX_DISK_IMAGES];
 static bool vnc;
@@ -132,6 +133,8 @@ static int virtio_9p_rootdir_parser(const struct option *opt, const char *arg, i
 
 static const struct option options[] = {
 	OPT_GROUP("Basic options:"),
+	OPT_STRING('\0', "name", &guest_name, "guest name",
+			"A name for the guest"),
 	OPT_INTEGER('c', "cpus", &nrcpus, "Number of CPUs"),
 	OPT_U64('m', "mem", &ram_size, "Virtual machine memory size in MiB."),
 	OPT_CALLBACK('d', "disk", NULL, "image", "Disk image", img_name_parser),
@@ -546,7 +549,7 @@ int kvm_cmd_run(int argc, const char **argv, const char *prefix)
 
 	term_init();
 
-	kvm = kvm__init(kvm_dev, ram_size);
+	kvm = kvm__init(kvm_dev, ram_size, guest_name);
 
 	ioeventfd__init();
 
diff --git a/tools/kvm/kvm.c b/tools/kvm/kvm.c
index c400c70..4f723a6 100644
--- a/tools/kvm/kvm.c
+++ b/tools/kvm/kvm.c
@@ -113,11 +113,60 @@ static struct kvm *kvm__new(void)
 	return kvm;
 }
 
+static void kvm__create_pidfile(struct kvm *kvm)
+{
+	int fd;
+	char full_name[PATH_MAX], pid[10];
+
+	if (!kvm->name)
+		return;
+
+	mkdir("/var/run/kvm-tools", 0777);
+	sprintf(full_name, "/var/run/kvm-tools/%s.pid", kvm->name);
+	fd = open(full_name, O_CREAT | O_WRONLY, 0666);
+	sprintf(pid, "%u\n", getpid());
+	if (write(fd, pid, strlen(pid)) <= 0)
+		die("Failed creating PID file");
+	close(fd);
+}
+
+static void kvm__remove_pidfile(struct kvm *kvm)
+{
+	char full_name[PATH_MAX];
+
+	if (!kvm->name)
+		return;
+
+	sprintf(full_name, "/var/run/kvm-tools/%s.pid", kvm->name);
+	unlink(full_name);
+}
+
+int kvm__get_pid_by_instance(const char *name)
+{
+	int fd, pid;
+	char pid_str[10], pid_file[PATH_MAX];
+
+	sprintf(pid_file, "/var/run/kvm-tools/%s.pid", name);
+	fd = open(pid_file, O_RDONLY);
+	if (fd < 0)
+		return -1;
+
+	if (read(fd, pid_str, 10) == 0)
+		return -1;
+
+	pid = atoi(pid_str);
+	if (pid < 0)
+		return -1;
+
+	return pid;
+}
+
 void kvm__delete(struct kvm *kvm)
 {
 	kvm__stop_timer(kvm);
 
 	munmap(kvm->ram_start, kvm->ram_size);
+	kvm__remove_pidfile(kvm);
 	free(kvm);
 }
 
@@ -237,7 +286,7 @@ int kvm__max_cpus(struct kvm *kvm)
 	return ret;
 }
 
-struct kvm *kvm__init(const char *kvm_dev, u64 ram_size)
+struct kvm *kvm__init(const char *kvm_dev, u64 ram_size, const char *name)
 {
 	struct kvm_pit_config pit_config = { .flags = 0, };
 	struct kvm *kvm;
@@ -300,6 +349,10 @@ struct kvm *kvm__init(const char *kvm_dev, u64 ram_size)
 	if (ret < 0)
 		die_perror("KVM_CREATE_IRQCHIP ioctl");
 
+	kvm->name = name;
+
+	kvm__create_pidfile(kvm);
+
 	return kvm;
 }
 
diff --git a/tools/kvm/term.c b/tools/kvm/term.c
index 9947223..a0cb03f 100644
--- a/tools/kvm/term.c
+++ b/tools/kvm/term.c
@@ -9,7 +9,9 @@
 #include "kvm/read-write.h"
 #include "kvm/term.h"
 #include "kvm/util.h"
+#include "kvm/kvm.h"
 
+extern struct kvm *kvm;
 static struct termios	orig_term;
 
 int term_escape_char	= 0x01; /* ctrl-a is used for escape */
@@ -32,6 +34,7 @@ int term_getc(int who)
 	if (term_got_escape) {
 		term_got_escape = false;
 		if (c == 'x') {
+			kvm__delete(kvm);
 			printf("\n  # KVM session terminated.\n");
 			exit(1);
 		}
-- 
1.7.6


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 4/9] kvm tools: Provide instance name when running 'kvm debug'
  2011-06-29 18:02 [PATCH 1/9] kvm tools: Don't dynamically allocate threadpool jobs Sasha Levin
  2011-06-29 18:02 ` [PATCH 2/9] kvm tools: Process virtio-blk requests in parallel Sasha Levin
  2011-06-29 18:02 ` [PATCH 3/9] kvm tools: Allow giving instance names Sasha Levin
@ 2011-06-29 18:02 ` Sasha Levin
  2011-06-29 18:02 ` [PATCH 5/9] kvm tools: Provide instance name when running 'kvm pause' Sasha Levin
                   ` (4 subsequent siblings)
  7 siblings, 0 replies; 14+ messages in thread
From: Sasha Levin @ 2011-06-29 18:02 UTC (permalink / raw)
  To: penberg; +Cc: kvm, mingo, asias.hejun, gorcunov, prasadjoshi124, Sasha Levin

Instead of sending a signal to the first instance found, send it
to a specific instance.

Signed-off-by: Sasha Levin <levinsasha928@gmail.com>
---
 tools/kvm/kvm-debug.c |   19 +++++++++++++++----
 1 files changed, 15 insertions(+), 4 deletions(-)

diff --git a/tools/kvm/kvm-debug.c b/tools/kvm/kvm-debug.c
index 58782dd..432ae84 100644
--- a/tools/kvm/kvm-debug.c
+++ b/tools/kvm/kvm-debug.c
@@ -1,11 +1,22 @@
-#include <stdio.h>
-#include <string.h>
-
 #include <kvm/util.h>
 #include <kvm/kvm-cmd.h>
 #include <kvm/kvm-debug.h>
+#include <kvm/kvm.h>
+
+#include <stdio.h>
+#include <string.h>
+#include <signal.h>
 
 int kvm_cmd_debug(int argc, const char **argv, const char *prefix)
 {
-	return system("kill -3 $(pidof kvm)");
+	int pid;
+
+	if (argc != 1)
+		die("Usage: kvm debug [instance name]\n");
+
+	pid = kvm__get_pid_by_instance(argv[0]);
+	if (pid < 0)
+		die("Failed locating instance name");
+
+	return kill(pid, SIGQUIT);
 }
-- 
1.7.6


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 5/9] kvm tools: Provide instance name when running 'kvm pause'
  2011-06-29 18:02 [PATCH 1/9] kvm tools: Don't dynamically allocate threadpool jobs Sasha Levin
                   ` (2 preceding siblings ...)
  2011-06-29 18:02 ` [PATCH 4/9] kvm tools: Provide instance name when running 'kvm debug' Sasha Levin
@ 2011-06-29 18:02 ` Sasha Levin
  2011-06-29 18:02 ` [PATCH 6/9] kvm tools: Add virtio-balloon device Sasha Levin
                   ` (3 subsequent siblings)
  7 siblings, 0 replies; 14+ messages in thread
From: Sasha Levin @ 2011-06-29 18:02 UTC (permalink / raw)
  To: penberg; +Cc: kvm, mingo, asias.hejun, gorcunov, prasadjoshi124, Sasha Levin

Instead of sending a signal to the first instance found, send it
to a specific instance.

Signed-off-by: Sasha Levin <levinsasha928@gmail.com>
---
 tools/kvm/kvm-pause.c |   13 +++++++++++--
 1 files changed, 11 insertions(+), 2 deletions(-)

diff --git a/tools/kvm/kvm-pause.c b/tools/kvm/kvm-pause.c
index fdf8714..0cb6f29 100644
--- a/tools/kvm/kvm-pause.c
+++ b/tools/kvm/kvm-pause.c
@@ -5,9 +5,18 @@
 #include <kvm/util.h>
 #include <kvm/kvm-cmd.h>
 #include <kvm/kvm-pause.h>
+#include <kvm/kvm.h>
 
 int kvm_cmd_pause(int argc, const char **argv, const char *prefix)
 {
-	signal(SIGUSR2, SIG_IGN);
-	return system("kill -USR2 $(pidof kvm)");
+	int pid;
+
+	if (argc != 1)
+		die("Usage: kvm debug [instance name]\n");
+
+	pid = kvm__get_pid_by_instance(argv[0]);
+	if (pid < 0)
+		die("Failed locating instance name");
+
+	return kill(pid, SIGUSR2);
 }
-- 
1.7.6


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 6/9] kvm tools: Add virtio-balloon device
  2011-06-29 18:02 [PATCH 1/9] kvm tools: Don't dynamically allocate threadpool jobs Sasha Levin
                   ` (3 preceding siblings ...)
  2011-06-29 18:02 ` [PATCH 5/9] kvm tools: Provide instance name when running 'kvm pause' Sasha Levin
@ 2011-06-29 18:02 ` Sasha Levin
  2011-06-29 18:02 ` [PATCH 7/9] kvm tools: Advise memory allocated for guest RAM as KSM mergable Sasha Levin
                   ` (2 subsequent siblings)
  7 siblings, 0 replies; 14+ messages in thread
From: Sasha Levin @ 2011-06-29 18:02 UTC (permalink / raw)
  To: penberg; +Cc: kvm, mingo, asias.hejun, gorcunov, prasadjoshi124, Sasha Levin

>From the virtio spec:

The virtio memory balloon device is a primitive device for managing guest
memory: the device asks for a certain amount of memory, and the guest supplies
it (or withdraws it, if the device has more than it asks for). This allows the
guest to adapt to changes in allowance of underlying physical memory.

To activate the virtio-balloon device run kvm tools with the '--balloon'
command line parameter.

Current implementation listens for two signals:

 - SIGKVMADDMEM: Adds 1M to the balloon driver (inflate). This will decrease
available memory within the guest.
 - SIGKVMDELMEM: Remove 1M from the balloon driver (deflate). This will
increase available memory within the guest.

Signed-off-by: Sasha Levin <levinsasha928@gmail.com>
---
 tools/kvm/Makefile                     |    1 +
 tools/kvm/include/kvm/kvm.h            |    3 +
 tools/kvm/include/kvm/virtio-balloon.h |    8 +
 tools/kvm/include/kvm/virtio-pci-dev.h |    1 +
 tools/kvm/kvm-run.c                    |    6 +
 tools/kvm/virtio/balloon.c             |  265 ++++++++++++++++++++++++++++++++
 6 files changed, 284 insertions(+), 0 deletions(-)
 create mode 100644 tools/kvm/include/kvm/virtio-balloon.h
 create mode 100644 tools/kvm/virtio/balloon.c

diff --git a/tools/kvm/Makefile b/tools/kvm/Makefile
index d368c22..a1b2f4c 100644
--- a/tools/kvm/Makefile
+++ b/tools/kvm/Makefile
@@ -40,6 +40,7 @@ OBJS	+= virtio/console.o
 OBJS	+= virtio/core.o
 OBJS	+= virtio/net.o
 OBJS	+= virtio/rng.o
+OBJS    += virtio/balloon.o
 OBJS	+= disk/blk.o
 OBJS	+= disk/qcow.o
 OBJS	+= disk/raw.o
diff --git a/tools/kvm/include/kvm/kvm.h b/tools/kvm/include/kvm/kvm.h
index 5ad3236..1fdfcf7 100644
--- a/tools/kvm/include/kvm/kvm.h
+++ b/tools/kvm/include/kvm/kvm.h
@@ -6,6 +6,7 @@
 #include <stdbool.h>
 #include <linux/types.h>
 #include <time.h>
+#include <signal.h>
 
 #define KVM_NR_CPUS		(255)
 
@@ -17,6 +18,8 @@
 
 #define SIGKVMEXIT		(SIGRTMIN + 0)
 #define SIGKVMPAUSE		(SIGRTMIN + 1)
+#define SIGKVMADDMEM		(SIGRTMIN + 2)
+#define SIGKVMDELMEM		(SIGRTMIN + 3)
 
 struct kvm {
 	int			sys_fd;		/* For system ioctls(), i.e. /dev/kvm */
diff --git a/tools/kvm/include/kvm/virtio-balloon.h b/tools/kvm/include/kvm/virtio-balloon.h
new file mode 100644
index 0000000..eb49fd4
--- /dev/null
+++ b/tools/kvm/include/kvm/virtio-balloon.h
@@ -0,0 +1,8 @@
+#ifndef KVM__BLN_VIRTIO_H
+#define KVM__BLN_VIRTIO_H
+
+struct kvm;
+
+void virtio_bln__init(struct kvm *kvm);
+
+#endif /* KVM__BLN_VIRTIO_H */
diff --git a/tools/kvm/include/kvm/virtio-pci-dev.h b/tools/kvm/include/kvm/virtio-pci-dev.h
index ca373df..4eee831 100644
--- a/tools/kvm/include/kvm/virtio-pci-dev.h
+++ b/tools/kvm/include/kvm/virtio-pci-dev.h
@@ -12,6 +12,7 @@
 #define PCI_DEVICE_ID_VIRTIO_BLK		0x1001
 #define PCI_DEVICE_ID_VIRTIO_CONSOLE		0x1003
 #define PCI_DEVICE_ID_VIRTIO_RNG		0x1004
+#define PCI_DEVICE_ID_VIRTIO_BLN		0x1005
 #define PCI_DEVICE_ID_VIRTIO_P9			0x1009
 #define PCI_DEVICE_ID_VESA			0x2000
 
diff --git a/tools/kvm/kvm-run.c b/tools/kvm/kvm-run.c
index a4abf76..3b1d586 100644
--- a/tools/kvm/kvm-run.c
+++ b/tools/kvm/kvm-run.c
@@ -18,6 +18,7 @@
 #include <kvm/virtio-net.h>
 #include <kvm/virtio-console.h>
 #include <kvm/virtio-rng.h>
+#include <kvm/virtio-balloon.h>
 #include <kvm/disk-image.h>
 #include <kvm/util.h>
 #include <kvm/pci.h>
@@ -74,6 +75,7 @@ static bool single_step;
 static bool readonly_image[MAX_DISK_IMAGES];
 static bool vnc;
 static bool sdl;
+static bool balloon;
 extern bool ioport_debug;
 extern int  active_console;
 extern int  debug_iodelay;
@@ -145,6 +147,7 @@ static const struct option options[] = {
 	OPT_STRING('\0', "kvm-dev", &kvm_dev, "kvm-dev", "KVM device file"),
 	OPT_CALLBACK('\0', "virtio-9p", NULL, "dirname,tag_name",
 		     "Enable 9p over virtio", virtio_9p_rootdir_parser),
+	OPT_BOOLEAN('\0', "balloon", &balloon, "Enable virtio balloon"),
 	OPT_BOOLEAN('\0', "vnc", &vnc, "Enable VNC framebuffer"),
 	OPT_BOOLEAN('\0', "sdl", &sdl, "Enable SDL framebuffer"),
 
@@ -629,6 +632,9 @@ int kvm_cmd_run(int argc, const char **argv, const char *prefix)
 		while (virtio_rng--)
 			virtio_rng__init(kvm);
 
+	if (balloon)
+		virtio_bln__init(kvm);
+
 	if (!network)
 		network = DEFAULT_NETWORK;
 
diff --git a/tools/kvm/virtio/balloon.c b/tools/kvm/virtio/balloon.c
new file mode 100644
index 0000000..ab9ccb7
--- /dev/null
+++ b/tools/kvm/virtio/balloon.c
@@ -0,0 +1,265 @@
+#include "kvm/virtio-balloon.h"
+
+#include "kvm/virtio-pci-dev.h"
+
+#include "kvm/disk-image.h"
+#include "kvm/virtio.h"
+#include "kvm/ioport.h"
+#include "kvm/util.h"
+#include "kvm/kvm.h"
+#include "kvm/pci.h"
+#include "kvm/threadpool.h"
+#include "kvm/irq.h"
+#include "kvm/ioeventfd.h"
+
+#include <linux/virtio_ring.h>
+#include <linux/virtio_balloon.h>
+
+#include <linux/list.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <pthread.h>
+
+#define NUM_VIRT_QUEUES		2
+#define VIRTIO_BLN_QUEUE_SIZE	128
+#define VIRTIO_BLN_INFLATE	0
+#define VIRTIO_BLN_DEFLATE	1
+
+struct bln_dev {
+	struct pci_device_header pci_hdr;
+	struct list_head	list;
+
+	u16			base_addr;
+	u8			status;
+	u8			isr;
+	u16			config_vector;
+	u32			host_features;
+
+	/* virtio queue */
+	u16			queue_selector;
+	struct virt_queue	vqs[NUM_VIRT_QUEUES];
+	void			*jobs[NUM_VIRT_QUEUES];
+
+	struct virtio_balloon_config config;
+};
+
+static struct bln_dev bdev;
+extern struct kvm *kvm;
+
+static bool virtio_bln_dev_in(void *data, unsigned long offset, int size, u32 count)
+{
+	u8 *config_space = (u8 *) &bdev.config;
+
+	if (size != 1 || count != 1)
+		return false;
+
+	ioport__write8(data, config_space[offset - VIRTIO_MSI_CONFIG_VECTOR]);
+
+	return true;
+}
+
+static bool virtio_bln_dev_out(void *data, unsigned long offset, int size, u32 count)
+{
+	u8 *config_space = (u8 *) &bdev.config;
+
+	if (size != 1 || count != 1)
+		return false;
+
+	config_space[offset - VIRTIO_MSI_CONFIG_VECTOR] = *(u8 *)data;
+
+	return true;
+}
+
+static bool virtio_bln_pci_io_in(struct ioport *ioport, struct kvm *kvm, u16 port, void *data, int size, u32 count)
+{
+	unsigned long offset;
+	bool ret = true;
+
+	offset = port - bdev.base_addr;
+
+	switch (offset) {
+	case VIRTIO_PCI_HOST_FEATURES:
+		ioport__write32(data, bdev.host_features);
+		break;
+	case VIRTIO_PCI_GUEST_FEATURES:
+	case VIRTIO_PCI_QUEUE_SEL:
+	case VIRTIO_PCI_QUEUE_NOTIFY:
+		ret		= false;
+		break;
+	case VIRTIO_PCI_QUEUE_PFN:
+		ioport__write32(data, bdev.vqs[bdev.queue_selector].pfn);
+		break;
+	case VIRTIO_PCI_QUEUE_NUM:
+		ioport__write16(data, VIRTIO_BLN_QUEUE_SIZE);
+		break;
+	case VIRTIO_PCI_STATUS:
+		ioport__write8(data, bdev.status);
+		break;
+	case VIRTIO_PCI_ISR:
+		ioport__write8(data, bdev.isr);
+		kvm__irq_line(kvm, bdev.pci_hdr.irq_line, VIRTIO_IRQ_LOW);
+		bdev.isr = VIRTIO_IRQ_LOW;
+		break;
+	default:
+		ret = virtio_bln_dev_in(data, offset, size, count);
+		break;
+	};
+
+	return ret;
+}
+
+static bool virtio_bln_do_io_request(struct kvm *kvm, struct bln_dev *bdev, struct virt_queue *queue)
+{
+	struct iovec iov[VIRTIO_BLN_QUEUE_SIZE];
+	unsigned int len = 0;
+	u16 out, in, head;
+	u32 *ptrs, i;
+
+	head		= virt_queue__get_iov(queue, iov, &out, &in, kvm);
+	ptrs		= iov[0].iov_base;
+	len		= iov[0].iov_len / sizeof(u32);
+
+	for (i = 0 ; i < len ; i++) {
+		void *guest_ptr;
+
+		guest_ptr = guest_flat_to_host(kvm, ptrs[i] << VIRTIO_BALLOON_PFN_SHIFT);
+		if (queue == &bdev->vqs[VIRTIO_BLN_INFLATE]) {
+			madvise(guest_ptr, 1 << VIRTIO_BALLOON_PFN_SHIFT, MADV_DONTNEED);
+			bdev->config.actual++;
+		} else {
+			bdev->config.actual--;
+		}
+	}
+
+	virt_queue__set_used_elem(queue, head, len);
+
+	return true;
+}
+
+static void virtio_bln_do_io(struct kvm *kvm, void *param)
+{
+	struct virt_queue *vq = param;
+
+	while (virt_queue__available(vq)) {
+		virtio_bln_do_io_request(kvm, &bdev, vq);
+		virt_queue__trigger_irq(vq, bdev.pci_hdr.irq_line, &bdev.isr, kvm);
+	}
+}
+
+static void ioevent_callback(struct kvm *kvm, void *param)
+{
+	thread_pool__do_job(param);
+}
+
+static bool virtio_bln_pci_io_out(struct ioport *ioport, struct kvm *kvm, u16 port, void *data, int size, u32 count)
+{
+	unsigned long offset;
+	bool ret = true;
+	struct ioevent ioevent;
+
+	offset = port - bdev.base_addr;
+
+	switch (offset) {
+	case VIRTIO_MSI_QUEUE_VECTOR:
+	case VIRTIO_PCI_GUEST_FEATURES:
+		break;
+	case VIRTIO_PCI_QUEUE_PFN: {
+		struct virt_queue *queue;
+		void *p;
+
+		queue			= &bdev.vqs[bdev.queue_selector];
+		queue->pfn		= ioport__read32(data);
+		p			= guest_pfn_to_host(kvm, queue->pfn);
+
+		vring_init(&queue->vring, VIRTIO_BLN_QUEUE_SIZE, p, VIRTIO_PCI_VRING_ALIGN);
+
+		bdev.jobs[bdev.queue_selector] = thread_pool__add_job(kvm, virtio_bln_do_io, queue);
+
+		ioevent = (struct ioevent) {
+			.io_addr		= bdev.base_addr + VIRTIO_PCI_QUEUE_NOTIFY,
+			.io_len			= sizeof(u16),
+			.fn			= ioevent_callback,
+			.fn_ptr			= bdev.jobs[bdev.queue_selector],
+			.datamatch		= bdev.queue_selector,
+			.fn_kvm			= kvm,
+			.fd			= eventfd(0, 0),
+		};
+
+		ioeventfd__add_event(&ioevent);
+
+		break;
+	}
+	case VIRTIO_PCI_QUEUE_SEL:
+		bdev.queue_selector	= ioport__read16(data);
+		break;
+	case VIRTIO_PCI_QUEUE_NOTIFY: {
+		u16 queue_index;
+		queue_index		= ioport__read16(data);
+		thread_pool__do_job(bdev.jobs[queue_index]);
+		break;
+	}
+	case VIRTIO_PCI_STATUS:
+		bdev.status		= ioport__read8(data);
+		break;
+	case VIRTIO_MSI_CONFIG_VECTOR:
+		bdev.config_vector	= VIRTIO_MSI_NO_VECTOR;
+		break;
+	default:
+		ret = virtio_bln_dev_out(data, offset, size, count);
+		break;
+	};
+
+	return ret;
+}
+
+static struct ioport_operations virtio_bln_io_ops = {
+	.io_in				= virtio_bln_pci_io_in,
+	.io_out				= virtio_bln_pci_io_out,
+};
+
+static void handle_sigmem(int sig)
+{
+	if (sig == SIGKVMADDMEM)
+		bdev.config.num_pages += 256;
+	else
+		bdev.config.num_pages -= 256;
+
+	/* Notify that the configuration space has changed */
+	bdev.isr = VIRTIO_PCI_ISR_CONFIG;
+	kvm__irq_line(kvm, bdev.pci_hdr.irq_line, 1);
+}
+
+void virtio_bln__init(struct kvm *kvm)
+{
+	u8 pin, line, dev;
+	u16 bdev_base_addr;
+
+	signal(SIGKVMADDMEM, handle_sigmem);
+	signal(SIGKVMDELMEM, handle_sigmem);
+
+	bdev_base_addr = ioport__register(IOPORT_EMPTY, &virtio_bln_io_ops, IOPORT_SIZE, &bdev);
+
+	bdev.pci_hdr = (struct pci_device_header) {
+		.vendor_id		= PCI_VENDOR_ID_REDHAT_QUMRANET,
+		.device_id		= PCI_DEVICE_ID_VIRTIO_BLN,
+		.header_type		= PCI_HEADER_TYPE_NORMAL,
+		.revision_id		= 0,
+		.class			= 0x010000,
+		.subsys_vendor_id	= PCI_SUBSYSTEM_VENDOR_ID_REDHAT_QUMRANET,
+		.subsys_id		= VIRTIO_ID_BALLOON,
+		.bar[0]			= bdev_base_addr | PCI_BASE_ADDRESS_SPACE_IO,
+	};
+
+	bdev.base_addr = bdev_base_addr;
+
+	if (irq__register_device(VIRTIO_ID_RNG, &dev, &pin, &line) < 0)
+		return;
+
+	bdev.pci_hdr.irq_pin	= pin;
+	bdev.pci_hdr.irq_line	= line;
+	bdev.host_features	= 0;
+	memset(&bdev.config, 0, sizeof(struct virtio_balloon_config));
+
+	pci__register(&bdev.pci_hdr, dev);
+}
-- 
1.7.6


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 7/9] kvm tools: Advise memory allocated for guest RAM as KSM mergable
  2011-06-29 18:02 [PATCH 1/9] kvm tools: Don't dynamically allocate threadpool jobs Sasha Levin
                   ` (4 preceding siblings ...)
  2011-06-29 18:02 ` [PATCH 6/9] kvm tools: Add virtio-balloon device Sasha Levin
@ 2011-06-29 18:02 ` Sasha Levin
  2011-06-29 18:02 ` [PATCH 8/9] kvm tools: Add 'kvm balloon' command Sasha Levin
  2011-06-29 18:02 ` [PATCH 9/9] kvm tools: Stop VCPUs before freeing struct kvm Sasha Levin
  7 siblings, 0 replies; 14+ messages in thread
From: Sasha Levin @ 2011-06-29 18:02 UTC (permalink / raw)
  To: penberg; +Cc: kvm, mingo, asias.hejun, gorcunov, prasadjoshi124, Sasha Levin

Signed-off-by: Sasha Levin <levinsasha928@gmail.com>
---
 tools/kvm/kvm.c |    2 ++
 1 files changed, 2 insertions(+), 0 deletions(-)

diff --git a/tools/kvm/kvm.c b/tools/kvm/kvm.c
index 4f723a6..15bcf08 100644
--- a/tools/kvm/kvm.c
+++ b/tools/kvm/kvm.c
@@ -345,6 +345,8 @@ struct kvm *kvm__init(const char *kvm_dev, u64 ram_size, const char *name)
 	if (kvm->ram_start == MAP_FAILED)
 		die("out of memory");
 
+	madvise(kvm->ram_start, kvm->ram_size, MADV_MERGEABLE);
+
 	ret = ioctl(kvm->vm_fd, KVM_CREATE_IRQCHIP);
 	if (ret < 0)
 		die_perror("KVM_CREATE_IRQCHIP ioctl");
-- 
1.7.6


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 8/9] kvm tools: Add 'kvm balloon' command
  2011-06-29 18:02 [PATCH 1/9] kvm tools: Don't dynamically allocate threadpool jobs Sasha Levin
                   ` (5 preceding siblings ...)
  2011-06-29 18:02 ` [PATCH 7/9] kvm tools: Advise memory allocated for guest RAM as KSM mergable Sasha Levin
@ 2011-06-29 18:02 ` Sasha Levin
  2011-06-29 18:02 ` [PATCH 9/9] kvm tools: Stop VCPUs before freeing struct kvm Sasha Levin
  7 siblings, 0 replies; 14+ messages in thread
From: Sasha Levin @ 2011-06-29 18:02 UTC (permalink / raw)
  To: penberg; +Cc: kvm, mingo, asias.hejun, gorcunov, prasadjoshi124, Sasha Levin

Add a command to allow easily inflate/deflate the balloon driver in running
instances.

Usage:
kvm balloon [command] [instance name] [size]

command is either inflate or deflate, and size is represented in MB.
Target instance must be named (started with '--name').

Signed-off-by: Sasha Levin <levinsasha928@gmail.com>
---
 tools/kvm/Makefile                  |    1 +
 tools/kvm/include/kvm/kvm-balloon.h |    6 ++++++
 tools/kvm/kvm-balloon.c             |   34 ++++++++++++++++++++++++++++++++++
 tools/kvm/kvm-cmd.c                 |   12 +++++++-----
 tools/kvm/virtio/balloon.c          |    8 ++++----
 5 files changed, 52 insertions(+), 9 deletions(-)
 create mode 100644 tools/kvm/include/kvm/kvm-balloon.h
 create mode 100644 tools/kvm/kvm-balloon.c

diff --git a/tools/kvm/Makefile b/tools/kvm/Makefile
index a1b2f4c..4823c77 100644
--- a/tools/kvm/Makefile
+++ b/tools/kvm/Makefile
@@ -50,6 +50,7 @@ OBJS	+= kvm-cmd.o
 OBJS	+= kvm-debug.o
 OBJS	+= kvm-help.o
 OBJS    += kvm-pause.o
+OBJS    += kvm-balloon.o
 OBJS	+= kvm-run.o
 OBJS	+= mptable.o
 OBJS	+= rbtree.o
diff --git a/tools/kvm/include/kvm/kvm-balloon.h b/tools/kvm/include/kvm/kvm-balloon.h
new file mode 100644
index 0000000..f5f92b9
--- /dev/null
+++ b/tools/kvm/include/kvm/kvm-balloon.h
@@ -0,0 +1,6 @@
+#ifndef KVM__BALLOON_H
+#define KVM__BALLOON_H
+
+int kvm_cmd_balloon(int argc, const char **argv, const char *prefix);
+
+#endif
diff --git a/tools/kvm/kvm-balloon.c b/tools/kvm/kvm-balloon.c
new file mode 100644
index 0000000..277cada
--- /dev/null
+++ b/tools/kvm/kvm-balloon.c
@@ -0,0 +1,34 @@
+#include <stdio.h>
+#include <string.h>
+#include <signal.h>
+
+#include <kvm/util.h>
+#include <kvm/kvm-cmd.h>
+#include <kvm/kvm-balloon.h>
+#include <kvm/kvm.h>
+
+int kvm_cmd_balloon(int argc, const char **argv, const char *prefix)
+{
+	int pid;
+	int amount, i;
+	int inflate = 0;
+
+	if (argc != 3)
+		die("Usage: kvm balloon [command] [instance name] [amount]\n");
+
+	pid = kvm__get_pid_by_instance(argv[1]);
+	if (pid < 0)
+		die("Failed locating instance name");
+
+	if (strcmp(argv[0], "inflate") == 0)
+		inflate = 1;
+	else if (strcmp(argv[0], "deflate"))
+		die("command can be either 'inflate' or 'deflate'");
+
+	amount = atoi(argv[2]);
+
+	for (i = 0; i < amount; i++)
+		kill(pid, inflate ? SIGKVMADDMEM : SIGKVMDELMEM);
+
+	return 0;
+}
diff --git a/tools/kvm/kvm-cmd.c b/tools/kvm/kvm-cmd.c
index ffbc4ff..1598781 100644
--- a/tools/kvm/kvm-cmd.c
+++ b/tools/kvm/kvm-cmd.c
@@ -7,16 +7,18 @@
 /* user defined header files */
 #include "kvm/kvm-debug.h"
 #include "kvm/kvm-pause.h"
+#include "kvm/kvm-balloon.h"
 #include "kvm/kvm-help.h"
 #include "kvm/kvm-cmd.h"
 #include "kvm/kvm-run.h"
 
 struct cmd_struct kvm_commands[] = {
-	{ "pause", kvm_cmd_pause, NULL,         0 },
-	{ "debug", kvm_cmd_debug, NULL,         0 },
-	{ "help",  kvm_cmd_help,  NULL,         0 },
-	{ "run",   kvm_cmd_run,   kvm_run_help, 0 },
-	{ NULL,    NULL,          NULL,         0 },
+	{ "pause",	kvm_cmd_pause,		NULL,         0 },
+	{ "debug",	kvm_cmd_debug,		NULL,         0 },
+	{ "balloon",	kvm_cmd_balloon,	NULL,         0 },
+	{ "help",	kvm_cmd_help,		NULL,         0 },
+	{ "run",	kvm_cmd_run,		kvm_run_help, 0 },
+	{ NULL,		NULL,			NULL,         0 },
 };
 
 /*
diff --git a/tools/kvm/virtio/balloon.c b/tools/kvm/virtio/balloon.c
index ab9ccb7..854d04b 100644
--- a/tools/kvm/virtio/balloon.c
+++ b/tools/kvm/virtio/balloon.c
@@ -39,7 +39,7 @@ struct bln_dev {
 	/* virtio queue */
 	u16			queue_selector;
 	struct virt_queue	vqs[NUM_VIRT_QUEUES];
-	void			*jobs[NUM_VIRT_QUEUES];
+	struct thread_pool__job	jobs[NUM_VIRT_QUEUES];
 
 	struct virtio_balloon_config config;
 };
@@ -174,13 +174,13 @@ static bool virtio_bln_pci_io_out(struct ioport *ioport, struct kvm *kvm, u16 po
 
 		vring_init(&queue->vring, VIRTIO_BLN_QUEUE_SIZE, p, VIRTIO_PCI_VRING_ALIGN);
 
-		bdev.jobs[bdev.queue_selector] = thread_pool__add_job(kvm, virtio_bln_do_io, queue);
+		thread_pool__init_job(&bdev.jobs[bdev.queue_selector], kvm, virtio_bln_do_io, queue);
 
 		ioevent = (struct ioevent) {
 			.io_addr		= bdev.base_addr + VIRTIO_PCI_QUEUE_NOTIFY,
 			.io_len			= sizeof(u16),
 			.fn			= ioevent_callback,
-			.fn_ptr			= bdev.jobs[bdev.queue_selector],
+			.fn_ptr			= &bdev.jobs[bdev.queue_selector],
 			.datamatch		= bdev.queue_selector,
 			.fn_kvm			= kvm,
 			.fd			= eventfd(0, 0),
@@ -196,7 +196,7 @@ static bool virtio_bln_pci_io_out(struct ioport *ioport, struct kvm *kvm, u16 po
 	case VIRTIO_PCI_QUEUE_NOTIFY: {
 		u16 queue_index;
 		queue_index		= ioport__read16(data);
-		thread_pool__do_job(bdev.jobs[queue_index]);
+		thread_pool__do_job(&bdev.jobs[queue_index]);
 		break;
 	}
 	case VIRTIO_PCI_STATUS:
-- 
1.7.6


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 9/9] kvm tools: Stop VCPUs before freeing struct kvm
  2011-06-29 18:02 [PATCH 1/9] kvm tools: Don't dynamically allocate threadpool jobs Sasha Levin
                   ` (6 preceding siblings ...)
  2011-06-29 18:02 ` [PATCH 8/9] kvm tools: Add 'kvm balloon' command Sasha Levin
@ 2011-06-29 18:02 ` Sasha Levin
  7 siblings, 0 replies; 14+ messages in thread
From: Sasha Levin @ 2011-06-29 18:02 UTC (permalink / raw)
  To: penberg; +Cc: kvm, mingo, asias.hejun, gorcunov, prasadjoshi124, Sasha Levin

Not stopping VCPUs before leads to seg faults and other errors due to
synchronization between threads.

Signed-off-by: Sasha Levin <levinsasha928@gmail.com>
---
 tools/kvm/term.c |    2 ++
 1 files changed, 2 insertions(+), 0 deletions(-)

diff --git a/tools/kvm/term.c b/tools/kvm/term.c
index a0cb03f..2a3e1f0 100644
--- a/tools/kvm/term.c
+++ b/tools/kvm/term.c
@@ -10,6 +10,7 @@
 #include "kvm/term.h"
 #include "kvm/util.h"
 #include "kvm/kvm.h"
+#include "kvm/kvm-cpu.h"
 
 extern struct kvm *kvm;
 static struct termios	orig_term;
@@ -34,6 +35,7 @@ int term_getc(int who)
 	if (term_got_escape) {
 		term_got_escape = false;
 		if (c == 'x') {
+			kvm_cpu__reboot();
 			kvm__delete(kvm);
 			printf("\n  # KVM session terminated.\n");
 			exit(1);
-- 
1.7.6


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* Re: [PATCH 3/9] kvm tools: Allow giving instance names
  2011-06-29 18:02 ` [PATCH 3/9] kvm tools: Allow giving instance names Sasha Levin
@ 2011-06-30  7:53   ` Pekka Enberg
  2011-06-30  8:30     ` Avi Kivity
  2011-06-30 15:03     ` Sasha Levin
  0 siblings, 2 replies; 14+ messages in thread
From: Pekka Enberg @ 2011-06-30  7:53 UTC (permalink / raw)
  To: Sasha Levin; +Cc: kvm, mingo, asias.hejun, gorcunov, prasadjoshi124

On Wed, 29 Jun 2011, Sasha Levin wrote:
> This will allow tracking instance names and sending commands
> to specific instances if multiple instances are running.
>
> Signed-off-by: Sasha Levin <levinsasha928@gmail.com>

I skipped this and related patches because I really would like to hear 
what Ingo thinks about the '/var/run/kvm-tools/' pidfile mechanism.

> ---
> tools/kvm/include/kvm/kvm.h |    5 +++-
> tools/kvm/kvm-run.c         |    5 +++-
> tools/kvm/kvm.c             |   55 ++++++++++++++++++++++++++++++++++++++++++-
> tools/kvm/term.c            |    3 ++
> 4 files changed, 65 insertions(+), 3 deletions(-)
>
> diff --git a/tools/kvm/include/kvm/kvm.h b/tools/kvm/include/kvm/kvm.h
> index 7d90d35..5ad3236 100644
> --- a/tools/kvm/include/kvm/kvm.h
> +++ b/tools/kvm/include/kvm/kvm.h
> @@ -41,9 +41,11 @@ struct kvm {
> 	const char		*vmlinux;
> 	struct disk_image       **disks;
> 	int                     nr_disks;
> +
> +	const char		*name;
> };
>
> -struct kvm *kvm__init(const char *kvm_dev, u64 ram_size);
> +struct kvm *kvm__init(const char *kvm_dev, u64 ram_size, const char *name);
> int kvm__max_cpus(struct kvm *kvm);
> void kvm__init_ram(struct kvm *kvm);
> void kvm__delete(struct kvm *kvm);
> @@ -61,6 +63,7 @@ bool kvm__deregister_mmio(struct kvm *kvm, u64 phys_addr);
> void kvm__pause(void);
> void kvm__continue(void);
> void kvm__notify_paused(void);
> +int kvm__get_pid_by_instance(const char *name);
>
> /*
>  * Debugging
> diff --git a/tools/kvm/kvm-run.c b/tools/kvm/kvm-run.c
> index 0dece2d..a4abf76 100644
> --- a/tools/kvm/kvm-run.c
> +++ b/tools/kvm/kvm-run.c
> @@ -69,6 +69,7 @@ static const char *network;
> static const char *host_ip_addr;
> static const char *guest_mac;
> static const char *script;
> +static const char *guest_name;
> static bool single_step;
> static bool readonly_image[MAX_DISK_IMAGES];
> static bool vnc;
> @@ -132,6 +133,8 @@ static int virtio_9p_rootdir_parser(const struct option *opt, const char *arg, i
>
> static const struct option options[] = {
> 	OPT_GROUP("Basic options:"),
> +	OPT_STRING('\0', "name", &guest_name, "guest name",
> +			"A name for the guest"),
> 	OPT_INTEGER('c', "cpus", &nrcpus, "Number of CPUs"),
> 	OPT_U64('m', "mem", &ram_size, "Virtual machine memory size in MiB."),
> 	OPT_CALLBACK('d', "disk", NULL, "image", "Disk image", img_name_parser),
> @@ -546,7 +549,7 @@ int kvm_cmd_run(int argc, const char **argv, const char *prefix)
>
> 	term_init();
>
> -	kvm = kvm__init(kvm_dev, ram_size);
> +	kvm = kvm__init(kvm_dev, ram_size, guest_name);
>
> 	ioeventfd__init();
>
> diff --git a/tools/kvm/kvm.c b/tools/kvm/kvm.c
> index c400c70..4f723a6 100644
> --- a/tools/kvm/kvm.c
> +++ b/tools/kvm/kvm.c
> @@ -113,11 +113,60 @@ static struct kvm *kvm__new(void)
> 	return kvm;
> }
>
> +static void kvm__create_pidfile(struct kvm *kvm)
> +{
> +	int fd;
> +	char full_name[PATH_MAX], pid[10];
> +
> +	if (!kvm->name)
> +		return;
> +
> +	mkdir("/var/run/kvm-tools", 0777);

mkdir() can fail

> +	sprintf(full_name, "/var/run/kvm-tools/%s.pid", kvm->name);
> +	fd = open(full_name, O_CREAT | O_WRONLY, 0666);
> +	sprintf(pid, "%u\n", getpid());
> +	if (write(fd, pid, strlen(pid)) <= 0)
> +		die("Failed creating PID file");
> +	close(fd);
> +}
> +
> +static void kvm__remove_pidfile(struct kvm *kvm)
> +{
> +	char full_name[PATH_MAX];
> +
> +	if (!kvm->name)
> +		return;
> +
> +	sprintf(full_name, "/var/run/kvm-tools/%s.pid", kvm->name);
> +	unlink(full_name);

unlink() can fail too - dunno if it matters in practice but there 
shouldn't be harm in checking for it?

> +}
> +
> +int kvm__get_pid_by_instance(const char *name)
> +{
> +	int fd, pid;
> +	char pid_str[10], pid_file[PATH_MAX];
> +
> +	sprintf(pid_file, "/var/run/kvm-tools/%s.pid", name);
> +	fd = open(pid_file, O_RDONLY);
> +	if (fd < 0)
> +		return -1;
> +
> +	if (read(fd, pid_str, 10) == 0)
> +		return -1;
> +
> +	pid = atoi(pid_str);
> +	if (pid < 0)
> +		return -1;
> +
> +	return pid;
> +}
> +
> void kvm__delete(struct kvm *kvm)
> {
> 	kvm__stop_timer(kvm);
>
> 	munmap(kvm->ram_start, kvm->ram_size);
> +	kvm__remove_pidfile(kvm);
> 	free(kvm);
> }
>
> @@ -237,7 +286,7 @@ int kvm__max_cpus(struct kvm *kvm)
> 	return ret;
> }
>
> -struct kvm *kvm__init(const char *kvm_dev, u64 ram_size)
> +struct kvm *kvm__init(const char *kvm_dev, u64 ram_size, const char *name)
> {
> 	struct kvm_pit_config pit_config = { .flags = 0, };
> 	struct kvm *kvm;
> @@ -300,6 +349,10 @@ struct kvm *kvm__init(const char *kvm_dev, u64 ram_size)
> 	if (ret < 0)
> 		die_perror("KVM_CREATE_IRQCHIP ioctl");
>
> +	kvm->name = name;
> +
> +	kvm__create_pidfile(kvm);
> +
> 	return kvm;
> }
>
> diff --git a/tools/kvm/term.c b/tools/kvm/term.c
> index 9947223..a0cb03f 100644
> --- a/tools/kvm/term.c
> +++ b/tools/kvm/term.c
> @@ -9,7 +9,9 @@
> #include "kvm/read-write.h"
> #include "kvm/term.h"
> #include "kvm/util.h"
> +#include "kvm/kvm.h"
>
> +extern struct kvm *kvm;
> static struct termios	orig_term;
>
> int term_escape_char	= 0x01; /* ctrl-a is used for escape */
> @@ -32,6 +34,7 @@ int term_getc(int who)
> 	if (term_got_escape) {
> 		term_got_escape = false;
> 		if (c == 'x') {
> +			kvm__delete(kvm);
> 			printf("\n  # KVM session terminated.\n");
> 			exit(1);
> 		}
> -- 
> 1.7.6
>
>

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 3/9] kvm tools: Allow giving instance names
  2011-06-30  7:53   ` Pekka Enberg
@ 2011-06-30  8:30     ` Avi Kivity
  2011-06-30 15:00       ` Sasha Levin
  2011-06-30 15:03     ` Sasha Levin
  1 sibling, 1 reply; 14+ messages in thread
From: Avi Kivity @ 2011-06-30  8:30 UTC (permalink / raw)
  To: Pekka Enberg
  Cc: Sasha Levin, kvm, mingo, asias.hejun, gorcunov, prasadjoshi124

On 06/30/2011 10:53 AM, Pekka Enberg wrote:
> On Wed, 29 Jun 2011, Sasha Levin wrote:
>> This will allow tracking instance names and sending commands
>> to specific instances if multiple instances are running.
>>
>> Signed-off-by: Sasha Levin <levinsasha928@gmail.com>
>
> I skipped this and related patches because I really would like to hear 
> what Ingo thinks about the '/var/run/kvm-tools/' pidfile mechanism.

Isn't it root-only?  I think something like ~/.kvm-tools/ is better.

-- 
error compiling committee.c: too many arguments to function


^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 3/9] kvm tools: Allow giving instance names
  2011-06-30  8:30     ` Avi Kivity
@ 2011-06-30 15:00       ` Sasha Levin
  2011-06-30 15:03         ` Avi Kivity
  0 siblings, 1 reply; 14+ messages in thread
From: Sasha Levin @ 2011-06-30 15:00 UTC (permalink / raw)
  To: Avi Kivity
  Cc: Pekka Enberg, kvm, mingo, asias.hejun, gorcunov, prasadjoshi124

On Thu, 2011-06-30 at 11:30 +0300, Avi Kivity wrote:
> On 06/30/2011 10:53 AM, Pekka Enberg wrote:
> > On Wed, 29 Jun 2011, Sasha Levin wrote:
> >> This will allow tracking instance names and sending commands
> >> to specific instances if multiple instances are running.
> >>
> >> Signed-off-by: Sasha Levin <levinsasha928@gmail.com>
> >
> > I skipped this and related patches because I really would like to hear 
> > what Ingo thinks about the '/var/run/kvm-tools/' pidfile mechanism.
> 
> Isn't it root-only?  I think something like ~/.kvm-tools/ is better.
> 

Yes. I completely forgot about permissions required for /var/run.

-- 

Sasha.


^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 3/9] kvm tools: Allow giving instance names
  2011-06-30 15:00       ` Sasha Levin
@ 2011-06-30 15:03         ` Avi Kivity
  0 siblings, 0 replies; 14+ messages in thread
From: Avi Kivity @ 2011-06-30 15:03 UTC (permalink / raw)
  To: Sasha Levin
  Cc: Pekka Enberg, kvm, mingo, asias.hejun, gorcunov, prasadjoshi124

On 06/30/2011 06:00 PM, Sasha Levin wrote:
> On Thu, 2011-06-30 at 11:30 +0300, Avi Kivity wrote:
> >  On 06/30/2011 10:53 AM, Pekka Enberg wrote:
> >  >  On Wed, 29 Jun 2011, Sasha Levin wrote:
> >  >>  This will allow tracking instance names and sending commands
> >  >>  to specific instances if multiple instances are running.
> >  >>
> >  >>  Signed-off-by: Sasha Levin<levinsasha928@gmail.com>
> >  >
> >  >  I skipped this and related patches because I really would like to hear
> >  >  what Ingo thinks about the '/var/run/kvm-tools/' pidfile mechanism.
> >
> >  Isn't it root-only?  I think something like ~/.kvm-tools/ is better.
> >
>
> Yes. I completely forgot about permissions required for /var/run.

It's best to run kvm as an ordinary user, so your users don't get surprised.

-- 
error compiling committee.c: too many arguments to function


^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 3/9] kvm tools: Allow giving instance names
  2011-06-30  7:53   ` Pekka Enberg
  2011-06-30  8:30     ` Avi Kivity
@ 2011-06-30 15:03     ` Sasha Levin
  1 sibling, 0 replies; 14+ messages in thread
From: Sasha Levin @ 2011-06-30 15:03 UTC (permalink / raw)
  To: Pekka Enberg; +Cc: kvm, mingo, asias.hejun, gorcunov, prasadjoshi124

On Thu, 2011-06-30 at 10:53 +0300, Pekka Enberg wrote:
> On Wed, 29 Jun 2011, Sasha Levin wrote:
> > This will allow tracking instance names and sending commands
> > to specific instances if multiple instances are running.
> >
> > Signed-off-by: Sasha Levin <levinsasha928@gmail.com>
> 
> I skipped this and related patches because I really would like to hear 
> what Ingo thinks about the '/var/run/kvm-tools/' pidfile mechanism.
> 
> > ---
> > tools/kvm/include/kvm/kvm.h |    5 +++-
> > tools/kvm/kvm-run.c         |    5 +++-
> > tools/kvm/kvm.c             |   55 ++++++++++++++++++++++++++++++++++++++++++-
> > tools/kvm/term.c            |    3 ++
> > 4 files changed, 65 insertions(+), 3 deletions(-)
> >
> > diff --git a/tools/kvm/include/kvm/kvm.h b/tools/kvm/include/kvm/kvm.h
> > index 7d90d35..5ad3236 100644
> > --- a/tools/kvm/include/kvm/kvm.h
> > +++ b/tools/kvm/include/kvm/kvm.h
> > @@ -41,9 +41,11 @@ struct kvm {
> > 	const char		*vmlinux;
> > 	struct disk_image       **disks;
> > 	int                     nr_disks;
> > +
> > +	const char		*name;
> > };
> >
> > -struct kvm *kvm__init(const char *kvm_dev, u64 ram_size);
> > +struct kvm *kvm__init(const char *kvm_dev, u64 ram_size, const char *name);
> > int kvm__max_cpus(struct kvm *kvm);
> > void kvm__init_ram(struct kvm *kvm);
> > void kvm__delete(struct kvm *kvm);
> > @@ -61,6 +63,7 @@ bool kvm__deregister_mmio(struct kvm *kvm, u64 phys_addr);
> > void kvm__pause(void);
> > void kvm__continue(void);
> > void kvm__notify_paused(void);
> > +int kvm__get_pid_by_instance(const char *name);
> >
> > /*
> >  * Debugging
> > diff --git a/tools/kvm/kvm-run.c b/tools/kvm/kvm-run.c
> > index 0dece2d..a4abf76 100644
> > --- a/tools/kvm/kvm-run.c
> > +++ b/tools/kvm/kvm-run.c
> > @@ -69,6 +69,7 @@ static const char *network;
> > static const char *host_ip_addr;
> > static const char *guest_mac;
> > static const char *script;
> > +static const char *guest_name;
> > static bool single_step;
> > static bool readonly_image[MAX_DISK_IMAGES];
> > static bool vnc;
> > @@ -132,6 +133,8 @@ static int virtio_9p_rootdir_parser(const struct option *opt, const char *arg, i
> >
> > static const struct option options[] = {
> > 	OPT_GROUP("Basic options:"),
> > +	OPT_STRING('\0', "name", &guest_name, "guest name",
> > +			"A name for the guest"),
> > 	OPT_INTEGER('c', "cpus", &nrcpus, "Number of CPUs"),
> > 	OPT_U64('m', "mem", &ram_size, "Virtual machine memory size in MiB."),
> > 	OPT_CALLBACK('d', "disk", NULL, "image", "Disk image", img_name_parser),
> > @@ -546,7 +549,7 @@ int kvm_cmd_run(int argc, const char **argv, const char *prefix)
> >
> > 	term_init();
> >
> > -	kvm = kvm__init(kvm_dev, ram_size);
> > +	kvm = kvm__init(kvm_dev, ram_size, guest_name);
> >
> > 	ioeventfd__init();
> >
> > diff --git a/tools/kvm/kvm.c b/tools/kvm/kvm.c
> > index c400c70..4f723a6 100644
> > --- a/tools/kvm/kvm.c
> > +++ b/tools/kvm/kvm.c
> > @@ -113,11 +113,60 @@ static struct kvm *kvm__new(void)
> > 	return kvm;
> > }
> >
> > +static void kvm__create_pidfile(struct kvm *kvm)
> > +{
> > +	int fd;
> > +	char full_name[PATH_MAX], pid[10];
> > +
> > +	if (!kvm->name)
> > +		return;
> > +
> > +	mkdir("/var/run/kvm-tools", 0777);
> 
> mkdir() can fail

My assumption here is that it would indeed fail most of the time, My
idea here was to try to create the directory anyway - even if it's
already there.

> 
> > +	sprintf(full_name, "/var/run/kvm-tools/%s.pid", kvm->name);
> > +	fd = open(full_name, O_CREAT | O_WRONLY, 0666);
> > +	sprintf(pid, "%u\n", getpid());
> > +	if (write(fd, pid, strlen(pid)) <= 0)
> > +		die("Failed creating PID file");
> > +	close(fd);
> > +}
> > +
> > +static void kvm__remove_pidfile(struct kvm *kvm)
> > +{
> > +	char full_name[PATH_MAX];
> > +
> > +	if (!kvm->name)
> > +		return;
> > +
> > +	sprintf(full_name, "/var/run/kvm-tools/%s.pid", kvm->name);
> > +	unlink(full_name);
> 
> unlink() can fail too - dunno if it matters in practice but there 
> shouldn't be harm in checking for it?

I can check for it, but what should I do if it indeed fails? The code is
located on the exit patch, so die() here would do more harm than good.

> 
> > +}
> > +
> > +int kvm__get_pid_by_instance(const char *name)
> > +{
> > +	int fd, pid;
> > +	char pid_str[10], pid_file[PATH_MAX];
> > +
> > +	sprintf(pid_file, "/var/run/kvm-tools/%s.pid", name);
> > +	fd = open(pid_file, O_RDONLY);
> > +	if (fd < 0)
> > +		return -1;
> > +
> > +	if (read(fd, pid_str, 10) == 0)
> > +		return -1;
> > +
> > +	pid = atoi(pid_str);
> > +	if (pid < 0)
> > +		return -1;
> > +
> > +	return pid;
> > +}
> > +
> > void kvm__delete(struct kvm *kvm)
> > {
> > 	kvm__stop_timer(kvm);
> >
> > 	munmap(kvm->ram_start, kvm->ram_size);
> > +	kvm__remove_pidfile(kvm);
> > 	free(kvm);
> > }
> >
> > @@ -237,7 +286,7 @@ int kvm__max_cpus(struct kvm *kvm)
> > 	return ret;
> > }
> >
> > -struct kvm *kvm__init(const char *kvm_dev, u64 ram_size)
> > +struct kvm *kvm__init(const char *kvm_dev, u64 ram_size, const char *name)
> > {
> > 	struct kvm_pit_config pit_config = { .flags = 0, };
> > 	struct kvm *kvm;
> > @@ -300,6 +349,10 @@ struct kvm *kvm__init(const char *kvm_dev, u64 ram_size)
> > 	if (ret < 0)
> > 		die_perror("KVM_CREATE_IRQCHIP ioctl");
> >
> > +	kvm->name = name;
> > +
> > +	kvm__create_pidfile(kvm);
> > +
> > 	return kvm;
> > }
> >
> > diff --git a/tools/kvm/term.c b/tools/kvm/term.c
> > index 9947223..a0cb03f 100644
> > --- a/tools/kvm/term.c
> > +++ b/tools/kvm/term.c
> > @@ -9,7 +9,9 @@
> > #include "kvm/read-write.h"
> > #include "kvm/term.h"
> > #include "kvm/util.h"
> > +#include "kvm/kvm.h"
> >
> > +extern struct kvm *kvm;
> > static struct termios	orig_term;
> >
> > int term_escape_char	= 0x01; /* ctrl-a is used for escape */
> > @@ -32,6 +34,7 @@ int term_getc(int who)
> > 	if (term_got_escape) {
> > 		term_got_escape = false;
> > 		if (c == 'x') {
> > +			kvm__delete(kvm);
> > 			printf("\n  # KVM session terminated.\n");
> > 			exit(1);
> > 		}
> > -- 
> > 1.7.6
> >
> >

-- 

Sasha.


^ permalink raw reply	[flat|nested] 14+ messages in thread

end of thread, other threads:[~2011-06-30 15:03 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-06-29 18:02 [PATCH 1/9] kvm tools: Don't dynamically allocate threadpool jobs Sasha Levin
2011-06-29 18:02 ` [PATCH 2/9] kvm tools: Process virtio-blk requests in parallel Sasha Levin
2011-06-29 18:02 ` [PATCH 3/9] kvm tools: Allow giving instance names Sasha Levin
2011-06-30  7:53   ` Pekka Enberg
2011-06-30  8:30     ` Avi Kivity
2011-06-30 15:00       ` Sasha Levin
2011-06-30 15:03         ` Avi Kivity
2011-06-30 15:03     ` Sasha Levin
2011-06-29 18:02 ` [PATCH 4/9] kvm tools: Provide instance name when running 'kvm debug' Sasha Levin
2011-06-29 18:02 ` [PATCH 5/9] kvm tools: Provide instance name when running 'kvm pause' Sasha Levin
2011-06-29 18:02 ` [PATCH 6/9] kvm tools: Add virtio-balloon device Sasha Levin
2011-06-29 18:02 ` [PATCH 7/9] kvm tools: Advise memory allocated for guest RAM as KSM mergable Sasha Levin
2011-06-29 18:02 ` [PATCH 8/9] kvm tools: Add 'kvm balloon' command Sasha Levin
2011-06-29 18:02 ` [PATCH 9/9] kvm tools: Stop VCPUs before freeing struct kvm Sasha Levin

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox