Update to 3.4-final.
[linux-flexiantxendom0-3.2.10.git] / drivers / xen / blkback / blkback-pagemap.c
1 #include <linux/module.h>
2 #include <linux/slab.h>
3 #include "blkback-pagemap.h"
4
5 static int blkback_pagemap_size;
6 static struct blkback_pagemap *blkback_pagemap;
7
8 static inline int
9 blkback_pagemap_entry_clear(struct blkback_pagemap *map)
10 {
11         static struct blkback_pagemap zero;
12         return !memcmp(map, &zero, sizeof(zero));
13 }
14
15 int
16 blkback_pagemap_init(int pages)
17 {
18         blkback_pagemap = kzalloc(pages * sizeof(struct blkback_pagemap),
19                                   GFP_KERNEL);
20         if (!blkback_pagemap)
21                 return -ENOMEM;
22
23         blkback_pagemap_size = pages;
24         return 0;
25 }
26 EXPORT_SYMBOL_GPL(blkback_pagemap_init);
27
28 void
29 blkback_pagemap_set(int idx, struct page *page,
30                     domid_t domid, busid_t busid, grant_ref_t gref)
31 {
32         struct blkback_pagemap *entry;
33
34         BUG_ON(!blkback_pagemap);
35         BUG_ON(idx >= blkback_pagemap_size);
36
37         SetPageBlkback(page);
38         set_page_private(page, idx);
39
40         entry = blkback_pagemap + idx;
41         if (!blkback_pagemap_entry_clear(entry)) {
42                 pr_emerg("overwriting pagemap %d: d %u b %u g %u\n",
43                          idx, entry->domid, entry->busid, entry->gref);
44                 BUG();
45         }
46
47         entry->domid = domid;
48         entry->busid = busid;
49         entry->gref  = gref;
50 }
51 EXPORT_SYMBOL_GPL(blkback_pagemap_set);
52
53 void
54 blkback_pagemap_clear(struct page *page)
55 {
56         int idx;
57         struct blkback_pagemap *entry;
58
59         idx = (int)page_private(page);
60
61         BUG_ON(!blkback_pagemap);
62         BUG_ON(!PageBlkback(page));
63         BUG_ON(idx >= blkback_pagemap_size);
64
65         entry = blkback_pagemap + idx;
66         if (blkback_pagemap_entry_clear(entry)) {
67                 pr_emerg("clearing empty pagemap %d\n", idx);
68                 BUG();
69         }
70
71         memset(entry, 0, sizeof(*entry));
72 }
73 EXPORT_SYMBOL_GPL(blkback_pagemap_clear);
74
75 struct blkback_pagemap
76 blkback_pagemap_read(struct page *page)
77 {
78         int idx;
79         struct blkback_pagemap *entry;
80
81         idx = (int)page_private(page);
82
83         BUG_ON(!blkback_pagemap);
84         BUG_ON(!PageBlkback(page));
85         BUG_ON(idx >= blkback_pagemap_size);
86
87         entry = blkback_pagemap + idx;
88         if (blkback_pagemap_entry_clear(entry)) {
89                 pr_emerg("reading empty pagemap %d\n", idx);
90                 BUG();
91         }
92
93         return *entry;
94 }
95 EXPORT_SYMBOL(blkback_pagemap_read);
96
97 MODULE_LICENSE("Dual BSD/GPL");