]> xenbits.xensource.com Git - xenclient/kernel.git/commitdiff
imported patch blkback-pagemap CA-24784-resource-leak
authort_jeang <devnull@localhost>
Tue, 6 Jan 2009 12:06:01 +0000 (12:06 +0000)
committert_jeang <devnull@localhost>
Tue, 6 Jan 2009 12:06:01 +0000 (12:06 +0000)
drivers/xen/blkback/Makefile
drivers/xen/blkback/blkback-pagemap.c [new file with mode: 0644]
drivers/xen/blkback/blkback-pagemap.h [new file with mode: 0644]
drivers/xen/blkback/blkback.c
drivers/xen/blkback/common.h

index 8bab63da3b3e50d6cc2f61f5c07bed18e16d084b..466cdf0d2381d6f8f2f493b0b3a9223c9afda742 100644 (file)
@@ -1,3 +1,3 @@
 obj-$(CONFIG_XEN_BLKDEV_BACKEND) := blkbk.o
 
-blkbk-y        := blkback.o xenbus.o interface.o vbd.o
+blkbk-y        := blkback.o xenbus.o interface.o vbd.o blkback-pagemap.o
diff --git a/drivers/xen/blkback/blkback-pagemap.c b/drivers/xen/blkback/blkback-pagemap.c
new file mode 100644 (file)
index 0000000..77550b4
--- /dev/null
@@ -0,0 +1,91 @@
+#include "common.h"
+#include "blkback-pagemap.h"
+
+static int blkback_pagemap_size;
+static struct blkback_pagemap *blkback_pagemap;
+
+static inline int
+blkback_pagemap_entry_clear(struct blkback_pagemap *map)
+{
+       static struct blkback_pagemap zero;
+       return !memcmp(map, &zero, sizeof(zero));
+}
+
+int
+blkback_pagemap_init(int pages)
+{
+       blkback_pagemap = kzalloc(pages * sizeof(struct blkback_pagemap),
+                                 GFP_KERNEL);
+       if (!blkback_pagemap)
+               return -ENOMEM;
+
+       blkback_pagemap_size = pages;
+       return 0;
+}
+
+void
+blkback_pagemap_set(int idx, struct page *page,
+                   domid_t domid, busid_t busid, grant_ref_t gref)
+{
+       struct blkback_pagemap *entry;
+
+       BUG_ON(!blkback_pagemap);
+       BUG_ON(idx >= blkback_pagemap_size);
+
+       SetPageBlkback(page);
+       set_page_private(page, idx);
+
+       entry = blkback_pagemap + idx;
+       if (!blkback_pagemap_entry_clear(entry)) {
+               printk("overwriting pagemap %d: d %u b %u g %u\n",
+                      idx, entry->domid, entry->busid, entry->gref);
+               BUG();
+       }
+
+       entry->domid = domid;
+       entry->busid = busid;
+       entry->gref  = gref;
+}
+
+void
+blkback_pagemap_clear(struct page *page)
+{
+       int idx;
+       struct blkback_pagemap *entry;
+
+       idx = (int)page_private(page);
+
+       BUG_ON(!blkback_pagemap);
+       BUG_ON(!PageBlkback(page));
+       BUG_ON(idx >= blkback_pagemap_size);
+
+       entry = blkback_pagemap + idx;
+       if (blkback_pagemap_entry_clear(entry)) {
+               printk("clearing empty pagemap %d\n", idx);
+               BUG();
+       }
+
+       memset(entry, 0, sizeof(*entry));
+}
+
+struct blkback_pagemap
+blkback_pagemap_read(struct page *page)
+{
+       int idx;
+       struct blkback_pagemap *entry;
+
+       idx = (int)page_private(page);
+
+       BUG_ON(!blkback_pagemap);
+       BUG_ON(!PageBlkback(page));
+       BUG_ON(idx >= blkback_pagemap_size);
+
+       entry = blkback_pagemap + idx;
+       if (blkback_pagemap_entry_clear(entry)) {
+               printk("reading empty pagemap %d\n", idx);
+               BUG();
+       }
+
+       return *entry;
+}
+EXPORT_SYMBOL(blkback_pagemap_read);
diff --git a/drivers/xen/blkback/blkback-pagemap.h b/drivers/xen/blkback/blkback-pagemap.h
new file mode 100644 (file)
index 0000000..5e6809f
--- /dev/null
@@ -0,0 +1,17 @@
+#ifndef _BLKBACK_PAGEMAP_H_
+#define _BLKBACK_PAGEMAP_H_
+
+#include <xen/interface/xen.h>
+#include <xen/interface/grant_table.h>
+
+typedef unsigned int busid_t;
+
+struct blkback_pagemap {
+       domid_t          domid;
+       busid_t          busid;
+       grant_ref_t      gref;
+};
+
+struct blkback_pagemap blkback_pagemap_read(struct page *);
+
+#endif
index c326d88ec75e5886a1af4e9e1f36a347aad0389b..56a8cc5a81e0c7660702bd33b24753ede43f4e21 100644 (file)
@@ -174,6 +174,7 @@ static void fast_flush_area(pending_req_t *req)
                handle = pending_handle(req, i);
                if (handle == BLKBACK_INVALID_HANDLE)
                        continue;
+               blkback_pagemap_clear(virt_to_page(vaddr(req, i)));
                gnttab_set_unmap_op(&unmap[invcount], vaddr(req, i),
                                    GNTMAP_host_map, handle);
                pending_handle(req, i) = BLKBACK_INVALID_HANDLE;
@@ -571,6 +572,10 @@ static void dispatch_rw_block_io(blkif_t *blkif,
                        FOREIGN_FRAME(map[i].dev_bus_addr >> PAGE_SHIFT));
                seg[i].buf  = map[i].dev_bus_addr | 
                        (req->seg[i].first_sect << 9);
+               blkback_pagemap_set(vaddr_pagenr(pending_req, i),
+                                   virt_to_page(vaddr(pending_req, i)),
+                                   blkif->domid, req->handle,
+                                   req->seg[i].gref);
        }
 
        if (ret)
@@ -726,6 +731,9 @@ static int __init blkif_init(void)
        for(i = 0; i < mmap_pages; i++)
                SetPageBlkback(pending_pages[i]);
 
+       if (blkback_pagemap_init(mmap_pages))
+               goto out_of_memory;
+
        if (!pending_reqs || !pending_grant_handles || !pending_pages)
                goto out_of_memory;
 
index bd4e15487389da68a26168c50f3f226632efe147..3732114578d15fb2451d2116838930c790329cf1 100644 (file)
@@ -43,6 +43,8 @@
 #include <xen/gnttab.h>
 #include <xen/driver_util.h>
 #include <xen/xenbus.h>
+#include "blkback-pagemap.h"
+
 
 #define DPRINTK(_f, _a...)                     \
        pr_debug("(file=%s, line=%d) " _f,      \
@@ -167,4 +169,8 @@ void blkback_signal_resumed(blkif_t *blkif);
 
 void blkback_close(blkif_t *blkif);
 
+int blkback_pagemap_init(int);
+void blkback_pagemap_set(int, struct page *, domid_t, busid_t, grant_ref_t);
+void blkback_pagemap_clear(struct page *);
+
 #endif /* __BLKIF__BACKEND__COMMON_H__ */