diff options
Diffstat (limited to 'drivers/block/xen-blkback/blkback.c')
| -rw-r--r-- | drivers/block/xen-blkback/blkback.c | 18 |
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, | |||
| 161 | static void make_response(struct xen_blkif *blkif, u64 id, | 161 | static 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 | ||
| 170 | static void add_persistent_gnt(struct rb_root *root, | 172 | static 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 | } |
