aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRoger Pau Monne <roger.pau@citrix.com>2012-12-04 09:21:52 -0500
committerKonrad Rzeszutek Wilk <konrad.wilk@oracle.com>2012-12-07 15:13:09 -0500
commit7dc341175af5e7361af81499ea192c7b274b6357 (patch)
tree95afffaad2e185fdc8cb69a074c42c8ba263dd64
parent07c540a0b5f4674538b57ad85bc9306e44fb45dd (diff)
xen-blkback: implement safe iterator for the list of persistent grants
Change foreach_grant iterator to a safe version, that allows freeing the element while iterating. Also move the free code in free_persistent_gnts to prevent freeing the element before the rb_next call. Reported-by: Dan Carpenter <dan.carpenter@oracle.com> Signed-off-by: Roger Pau Monné <roger.pau@citrix.com> Cc: Konrad Rzeszutek Wilk <konrad@kernel.org> Cc: xen-devel@lists.xen.org Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
-rw-r--r--drivers/block/xen-blkback/blkback.c18
1 files changed, 11 insertions, 7 deletions
diff --git a/drivers/block/xen-blkback/blkback.c b/drivers/block/xen-blkback/blkback.c
index 74374fb762aa..5ac841ff6cc7 100644
--- a/drivers/block/xen-blkback/blkback.c
+++ b/drivers/block/xen-blkback/blkback.c
@@ -161,10 +161,12 @@ static int dispatch_rw_block_io(struct xen_blkif *blkif,
161static void make_response(struct xen_blkif *blkif, u64 id, 161static void make_response(struct xen_blkif *blkif, u64 id,
162 unsigned short op, int st); 162 unsigned short op, int st);
163 163
164#define foreach_grant(pos, rbtree, node) \ 164#define foreach_grant_safe(pos, n, rbtree, node) \
165 for ((pos) = container_of(rb_first((rbtree)), typeof(*(pos)), node); \ 165 for ((pos) = container_of(rb_first((rbtree)), typeof(*(pos)), node), \
166 (n) = rb_next(&(pos)->node); \
166 &(pos)->node != NULL; \ 167 &(pos)->node != NULL; \
167 (pos) = container_of(rb_next(&(pos)->node), typeof(*(pos)), node)) 168 (pos) = container_of(n, typeof(*(pos)), node), \
169 (n) = (&(pos)->node != NULL) ? rb_next(&(pos)->node) : NULL)
168 170
169 171
170static void add_persistent_gnt(struct rb_root *root, 172static void add_persistent_gnt(struct rb_root *root,
@@ -217,10 +219,11 @@ static void free_persistent_gnts(struct rb_root *root, unsigned int num)
217 struct gnttab_unmap_grant_ref unmap[BLKIF_MAX_SEGMENTS_PER_REQUEST]; 219 struct gnttab_unmap_grant_ref unmap[BLKIF_MAX_SEGMENTS_PER_REQUEST];
218 struct page *pages[BLKIF_MAX_SEGMENTS_PER_REQUEST]; 220 struct page *pages[BLKIF_MAX_SEGMENTS_PER_REQUEST];
219 struct persistent_gnt *persistent_gnt; 221 struct persistent_gnt *persistent_gnt;
222 struct rb_node *n;
220 int ret = 0; 223 int ret = 0;
221 int segs_to_unmap = 0; 224 int segs_to_unmap = 0;
222 225
223 foreach_grant(persistent_gnt, root, node) { 226 foreach_grant_safe(persistent_gnt, n, root, node) {
224 BUG_ON(persistent_gnt->handle == 227 BUG_ON(persistent_gnt->handle ==
225 BLKBACK_INVALID_HANDLE); 228 BLKBACK_INVALID_HANDLE);
226 gnttab_set_unmap_op(&unmap[segs_to_unmap], 229 gnttab_set_unmap_op(&unmap[segs_to_unmap],
@@ -230,9 +233,6 @@ static void free_persistent_gnts(struct rb_root *root, unsigned int num)
230 persistent_gnt->handle); 233 persistent_gnt->handle);
231 234
232 pages[segs_to_unmap] = persistent_gnt->page; 235 pages[segs_to_unmap] = persistent_gnt->page;
233 rb_erase(&persistent_gnt->node, root);
234 kfree(persistent_gnt);
235 num--;
236 236
237 if (++segs_to_unmap == BLKIF_MAX_SEGMENTS_PER_REQUEST || 237 if (++segs_to_unmap == BLKIF_MAX_SEGMENTS_PER_REQUEST ||
238 !rb_next(&persistent_gnt->node)) { 238 !rb_next(&persistent_gnt->node)) {
@@ -241,6 +241,10 @@ static void free_persistent_gnts(struct rb_root *root, unsigned int num)
241 BUG_ON(ret); 241 BUG_ON(ret);
242 segs_to_unmap = 0; 242 segs_to_unmap = 0;
243 } 243 }
244
245 rb_erase(&persistent_gnt->node, root);
246 kfree(persistent_gnt);
247 num--;
244 } 248 }
245 BUG_ON(num != 0); 249 BUG_ON(num != 0);
246} 250}