Commit cdd59830 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mst/vhost

Pull virtio fixes from Michael S. Tsirkin:
 "Here are some virtio fixes for 3.4: a test build fix, a patch by Ren
  fixing naming for systems with a massive number of virtio blk devices,
  and balloon fixes for powerpc by David Gibson.

  There was some discussion about Ren's patch for virtio disc naming:
  some people wanted to move the legacy name mangling function to the
  block core.  But there's no concensus on that yet, and we can always
  deduplicate later.  Added comments in the hope that this will stop
  people from copying this legacy naming scheme into future drivers."

* tag 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mst/vhost:
  virtio_balloon: fix handling of PAGE_SIZE != 4k
  virtio_balloon: Fix endian bug
  virtio_blk: helper function to format disk names
  tools/virtio: fix up vhost/test module build
parents a6cb9ee7 3ccc9372
...@@ -375,6 +375,34 @@ static int init_vq(struct virtio_blk *vblk) ...@@ -375,6 +375,34 @@ static int init_vq(struct virtio_blk *vblk)
return err; return err;
} }
/*
* Legacy naming scheme used for virtio devices. We are stuck with it for
* virtio blk but don't ever use it for any new driver.
*/
static int virtblk_name_format(char *prefix, int index, char *buf, int buflen)
{
const int base = 'z' - 'a' + 1;
char *begin = buf + strlen(prefix);
char *end = buf + buflen;
char *p;
int unit;
p = end - 1;
*p = '\0';
unit = base;
do {
if (p == begin)
return -EINVAL;
*--p = 'a' + (index % unit);
index = (index / unit) - 1;
} while (index >= 0);
memmove(begin, p, end - p);
memcpy(buf, prefix, strlen(prefix));
return 0;
}
static int __devinit virtblk_probe(struct virtio_device *vdev) static int __devinit virtblk_probe(struct virtio_device *vdev)
{ {
struct virtio_blk *vblk; struct virtio_blk *vblk;
...@@ -443,18 +471,7 @@ static int __devinit virtblk_probe(struct virtio_device *vdev) ...@@ -443,18 +471,7 @@ static int __devinit virtblk_probe(struct virtio_device *vdev)
q->queuedata = vblk; q->queuedata = vblk;
if (index < 26) { virtblk_name_format("vd", index, vblk->disk->disk_name, DISK_NAME_LEN);
sprintf(vblk->disk->disk_name, "vd%c", 'a' + index % 26);
} else if (index < (26 + 1) * 26) {
sprintf(vblk->disk->disk_name, "vd%c%c",
'a' + index / 26 - 1, 'a' + index % 26);
} else {
const unsigned int m1 = (index / 26 - 1) / 26 - 1;
const unsigned int m2 = (index / 26 - 1) % 26;
const unsigned int m3 = index % 26;
sprintf(vblk->disk->disk_name, "vd%c%c%c",
'a' + m1, 'a' + m2, 'a' + m3);
}
vblk->disk->major = major; vblk->disk->major = major;
vblk->disk->first_minor = index_to_minor(index); vblk->disk->first_minor = index_to_minor(index);
......
...@@ -155,7 +155,7 @@ static int vhost_test_release(struct inode *inode, struct file *f) ...@@ -155,7 +155,7 @@ static int vhost_test_release(struct inode *inode, struct file *f)
vhost_test_stop(n, &private); vhost_test_stop(n, &private);
vhost_test_flush(n); vhost_test_flush(n);
vhost_dev_cleanup(&n->dev); vhost_dev_cleanup(&n->dev, false);
/* We do an extra flush before freeing memory, /* We do an extra flush before freeing memory,
* since jobs can re-queue themselves. */ * since jobs can re-queue themselves. */
vhost_test_flush(n); vhost_test_flush(n);
......
...@@ -28,6 +28,13 @@ ...@@ -28,6 +28,13 @@
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/module.h> #include <linux/module.h>
/*
* Balloon device works in 4K page units. So each page is pointed to by
* multiple balloon pages. All memory counters in this driver are in balloon
* page units.
*/
#define VIRTIO_BALLOON_PAGES_PER_PAGE (PAGE_SIZE >> VIRTIO_BALLOON_PFN_SHIFT)
struct virtio_balloon struct virtio_balloon
{ {
struct virtio_device *vdev; struct virtio_device *vdev;
...@@ -42,8 +49,13 @@ struct virtio_balloon ...@@ -42,8 +49,13 @@ struct virtio_balloon
/* Waiting for host to ack the pages we released. */ /* Waiting for host to ack the pages we released. */
struct completion acked; struct completion acked;
/* The pages we've told the Host we're not using. */ /* Number of balloon pages we've told the Host we're not using. */
unsigned int num_pages; unsigned int num_pages;
/*
* The pages we've told the Host we're not using.
* Each page on this list adds VIRTIO_BALLOON_PAGES_PER_PAGE
* to num_pages above.
*/
struct list_head pages; struct list_head pages;
/* The array of pfns we tell the Host about. */ /* The array of pfns we tell the Host about. */
...@@ -66,7 +78,13 @@ static u32 page_to_balloon_pfn(struct page *page) ...@@ -66,7 +78,13 @@ static u32 page_to_balloon_pfn(struct page *page)
BUILD_BUG_ON(PAGE_SHIFT < VIRTIO_BALLOON_PFN_SHIFT); BUILD_BUG_ON(PAGE_SHIFT < VIRTIO_BALLOON_PFN_SHIFT);
/* Convert pfn from Linux page size to balloon page size. */ /* Convert pfn from Linux page size to balloon page size. */
return pfn >> (PAGE_SHIFT - VIRTIO_BALLOON_PFN_SHIFT); return pfn * VIRTIO_BALLOON_PAGES_PER_PAGE;
}
static struct page *balloon_pfn_to_page(u32 pfn)
{
BUG_ON(pfn % VIRTIO_BALLOON_PAGES_PER_PAGE);
return pfn_to_page(pfn / VIRTIO_BALLOON_PAGES_PER_PAGE);
} }
static void balloon_ack(struct virtqueue *vq) static void balloon_ack(struct virtqueue *vq)
...@@ -96,12 +114,23 @@ static void tell_host(struct virtio_balloon *vb, struct virtqueue *vq) ...@@ -96,12 +114,23 @@ static void tell_host(struct virtio_balloon *vb, struct virtqueue *vq)
wait_for_completion(&vb->acked); wait_for_completion(&vb->acked);
} }
static void set_page_pfns(u32 pfns[], struct page *page)
{
unsigned int i;
/* Set balloon pfns pointing at this page.
* Note that the first pfn points at start of the page. */
for (i = 0; i < VIRTIO_BALLOON_PAGES_PER_PAGE; i++)
pfns[i] = page_to_balloon_pfn(page) + i;
}
static void fill_balloon(struct virtio_balloon *vb, size_t num) static void fill_balloon(struct virtio_balloon *vb, size_t num)
{ {
/* We can only do one array worth at a time. */ /* We can only do one array worth at a time. */
num = min(num, ARRAY_SIZE(vb->pfns)); num = min(num, ARRAY_SIZE(vb->pfns));
for (vb->num_pfns = 0; vb->num_pfns < num; vb->num_pfns++) { for (vb->num_pfns = 0; vb->num_pfns < num;
vb->num_pfns += VIRTIO_BALLOON_PAGES_PER_PAGE) {
struct page *page = alloc_page(GFP_HIGHUSER | __GFP_NORETRY | struct page *page = alloc_page(GFP_HIGHUSER | __GFP_NORETRY |
__GFP_NOMEMALLOC | __GFP_NOWARN); __GFP_NOMEMALLOC | __GFP_NOWARN);
if (!page) { if (!page) {
...@@ -113,9 +142,9 @@ static void fill_balloon(struct virtio_balloon *vb, size_t num) ...@@ -113,9 +142,9 @@ static void fill_balloon(struct virtio_balloon *vb, size_t num)
msleep(200); msleep(200);
break; break;
} }
vb->pfns[vb->num_pfns] = page_to_balloon_pfn(page); set_page_pfns(vb->pfns + vb->num_pfns, page);
vb->num_pages += VIRTIO_BALLOON_PAGES_PER_PAGE;
totalram_pages--; totalram_pages--;
vb->num_pages++;
list_add(&page->lru, &vb->pages); list_add(&page->lru, &vb->pages);
} }
...@@ -130,8 +159,9 @@ static void release_pages_by_pfn(const u32 pfns[], unsigned int num) ...@@ -130,8 +159,9 @@ static void release_pages_by_pfn(const u32 pfns[], unsigned int num)
{ {
unsigned int i; unsigned int i;
for (i = 0; i < num; i++) { /* Find pfns pointing at start of each page, get pages and free them. */
__free_page(pfn_to_page(pfns[i])); for (i = 0; i < num; i += VIRTIO_BALLOON_PAGES_PER_PAGE) {
__free_page(balloon_pfn_to_page(pfns[i]));
totalram_pages++; totalram_pages++;
} }
} }
...@@ -143,11 +173,12 @@ static void leak_balloon(struct virtio_balloon *vb, size_t num) ...@@ -143,11 +173,12 @@ static void leak_balloon(struct virtio_balloon *vb, size_t num)
/* We can only do one array worth at a time. */ /* We can only do one array worth at a time. */
num = min(num, ARRAY_SIZE(vb->pfns)); num = min(num, ARRAY_SIZE(vb->pfns));
for (vb->num_pfns = 0; vb->num_pfns < num; vb->num_pfns++) { for (vb->num_pfns = 0; vb->num_pfns < num;
vb->num_pfns += VIRTIO_BALLOON_PAGES_PER_PAGE) {
page = list_first_entry(&vb->pages, struct page, lru); page = list_first_entry(&vb->pages, struct page, lru);
list_del(&page->lru); list_del(&page->lru);
vb->pfns[vb->num_pfns] = page_to_balloon_pfn(page); set_page_pfns(vb->pfns + vb->num_pfns, page);
vb->num_pages--; vb->num_pages -= VIRTIO_BALLOON_PAGES_PER_PAGE;
} }
/* /*
...@@ -234,11 +265,14 @@ static void virtballoon_changed(struct virtio_device *vdev) ...@@ -234,11 +265,14 @@ static void virtballoon_changed(struct virtio_device *vdev)
static inline s64 towards_target(struct virtio_balloon *vb) static inline s64 towards_target(struct virtio_balloon *vb)
{ {
u32 v; __le32 v;
s64 target;
vb->vdev->config->get(vb->vdev, vb->vdev->config->get(vb->vdev,
offsetof(struct virtio_balloon_config, num_pages), offsetof(struct virtio_balloon_config, num_pages),
&v, sizeof(v)); &v, sizeof(v));
return (s64)v - vb->num_pages; target = le32_to_cpu(v);
return target - vb->num_pages;
} }
static void update_balloon_size(struct virtio_balloon *vb) static void update_balloon_size(struct virtio_balloon *vb)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment