Skip to content

Commit

Permalink
Merge tag 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/gi…
Browse files Browse the repository at this point in the history
…t/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
  • Loading branch information
Linus Torvalds committed Apr 17, 2012
2 parents a6cb9ee + 3ccc937 commit cdd5983
Show file tree
Hide file tree
Showing 3 changed files with 76 additions and 25 deletions.
41 changes: 29 additions & 12 deletions drivers/block/virtio_blk.c
Original file line number Diff line number Diff line change
Expand Up @@ -375,6 +375,34 @@ static int init_vq(struct virtio_blk *vblk)
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)
{
struct virtio_blk *vblk;
Expand Down Expand Up @@ -443,18 +471,7 @@ static int __devinit virtblk_probe(struct virtio_device *vdev)

q->queuedata = vblk;

if (index < 26) {
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);
}
virtblk_name_format("vd", index, vblk->disk->disk_name, DISK_NAME_LEN);

vblk->disk->major = major;
vblk->disk->first_minor = index_to_minor(index);
Expand Down
2 changes: 1 addition & 1 deletion drivers/vhost/test.c
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ static int vhost_test_release(struct inode *inode, struct file *f)

vhost_test_stop(n, &private);
vhost_test_flush(n);
vhost_dev_cleanup(&n->dev);
vhost_dev_cleanup(&n->dev, false);
/* We do an extra flush before freeing memory,
* since jobs can re-queue themselves. */
vhost_test_flush(n);
Expand Down
58 changes: 46 additions & 12 deletions drivers/virtio/virtio_balloon.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,13 @@
#include <linux/slab.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_device *vdev;
Expand All @@ -42,8 +49,13 @@ struct virtio_balloon
/* Waiting for host to ack the pages we released. */
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;
/*
* 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;

/* The array of pfns we tell the Host about. */
Expand All @@ -66,7 +78,13 @@ static u32 page_to_balloon_pfn(struct page *page)

BUILD_BUG_ON(PAGE_SHIFT < VIRTIO_BALLOON_PFN_SHIFT);
/* 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)
Expand Down Expand Up @@ -96,12 +114,23 @@ static void tell_host(struct virtio_balloon *vb, struct virtqueue *vq)
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)
{
/* We can only do one array worth at a time. */
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 |
__GFP_NOMEMALLOC | __GFP_NOWARN);
if (!page) {
Expand All @@ -113,9 +142,9 @@ static void fill_balloon(struct virtio_balloon *vb, size_t num)
msleep(200);
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--;
vb->num_pages++;
list_add(&page->lru, &vb->pages);
}

Expand All @@ -130,8 +159,9 @@ static void release_pages_by_pfn(const u32 pfns[], unsigned int num)
{
unsigned int i;

for (i = 0; i < num; i++) {
__free_page(pfn_to_page(pfns[i]));
/* Find pfns pointing at start of each page, get pages and free them. */
for (i = 0; i < num; i += VIRTIO_BALLOON_PAGES_PER_PAGE) {
__free_page(balloon_pfn_to_page(pfns[i]));
totalram_pages++;
}
}
Expand All @@ -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. */
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);
list_del(&page->lru);
vb->pfns[vb->num_pfns] = page_to_balloon_pfn(page);
vb->num_pages--;
set_page_pfns(vb->pfns + vb->num_pfns, page);
vb->num_pages -= VIRTIO_BALLOON_PAGES_PER_PAGE;
}

/*
Expand Down Expand Up @@ -234,11 +265,14 @@ static void virtballoon_changed(struct virtio_device *vdev)

static inline s64 towards_target(struct virtio_balloon *vb)
{
u32 v;
__le32 v;
s64 target;

vb->vdev->config->get(vb->vdev,
offsetof(struct virtio_balloon_config, num_pages),
&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)
Expand Down

0 comments on commit cdd5983

Please sign in to comment.