mirror of
https://github.com/edk2-porting/linux-next.git
synced 2024-12-23 20:53:53 +08:00
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>
This commit is contained in:
parent
07c540a0b5
commit
7dc341175a
@ -161,10 +161,12 @@ static int dispatch_rw_block_io(struct xen_blkif *blkif,
|
|||||||
static void make_response(struct xen_blkif *blkif, u64 id,
|
static void make_response(struct xen_blkif *blkif, u64 id,
|
||||||
unsigned short op, int st);
|
unsigned short op, int st);
|
||||||
|
|
||||||
#define foreach_grant(pos, rbtree, node) \
|
#define foreach_grant_safe(pos, n, rbtree, node) \
|
||||||
for ((pos) = container_of(rb_first((rbtree)), typeof(*(pos)), node); \
|
for ((pos) = container_of(rb_first((rbtree)), typeof(*(pos)), node), \
|
||||||
|
(n) = rb_next(&(pos)->node); \
|
||||||
&(pos)->node != NULL; \
|
&(pos)->node != NULL; \
|
||||||
(pos) = container_of(rb_next(&(pos)->node), typeof(*(pos)), node))
|
(pos) = container_of(n, typeof(*(pos)), node), \
|
||||||
|
(n) = (&(pos)->node != NULL) ? rb_next(&(pos)->node) : NULL)
|
||||||
|
|
||||||
|
|
||||||
static void add_persistent_gnt(struct rb_root *root,
|
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)
|
|||||||
struct gnttab_unmap_grant_ref unmap[BLKIF_MAX_SEGMENTS_PER_REQUEST];
|
struct gnttab_unmap_grant_ref unmap[BLKIF_MAX_SEGMENTS_PER_REQUEST];
|
||||||
struct page *pages[BLKIF_MAX_SEGMENTS_PER_REQUEST];
|
struct page *pages[BLKIF_MAX_SEGMENTS_PER_REQUEST];
|
||||||
struct persistent_gnt *persistent_gnt;
|
struct persistent_gnt *persistent_gnt;
|
||||||
|
struct rb_node *n;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
int segs_to_unmap = 0;
|
int segs_to_unmap = 0;
|
||||||
|
|
||||||
foreach_grant(persistent_gnt, root, node) {
|
foreach_grant_safe(persistent_gnt, n, root, node) {
|
||||||
BUG_ON(persistent_gnt->handle ==
|
BUG_ON(persistent_gnt->handle ==
|
||||||
BLKBACK_INVALID_HANDLE);
|
BLKBACK_INVALID_HANDLE);
|
||||||
gnttab_set_unmap_op(&unmap[segs_to_unmap],
|
gnttab_set_unmap_op(&unmap[segs_to_unmap],
|
||||||
@ -230,9 +233,6 @@ static void free_persistent_gnts(struct rb_root *root, unsigned int num)
|
|||||||
persistent_gnt->handle);
|
persistent_gnt->handle);
|
||||||
|
|
||||||
pages[segs_to_unmap] = persistent_gnt->page;
|
pages[segs_to_unmap] = persistent_gnt->page;
|
||||||
rb_erase(&persistent_gnt->node, root);
|
|
||||||
kfree(persistent_gnt);
|
|
||||||
num--;
|
|
||||||
|
|
||||||
if (++segs_to_unmap == BLKIF_MAX_SEGMENTS_PER_REQUEST ||
|
if (++segs_to_unmap == BLKIF_MAX_SEGMENTS_PER_REQUEST ||
|
||||||
!rb_next(&persistent_gnt->node)) {
|
!rb_next(&persistent_gnt->node)) {
|
||||||
@ -241,6 +241,10 @@ static void free_persistent_gnts(struct rb_root *root, unsigned int num)
|
|||||||
BUG_ON(ret);
|
BUG_ON(ret);
|
||||||
segs_to_unmap = 0;
|
segs_to_unmap = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rb_erase(&persistent_gnt->node, root);
|
||||||
|
kfree(persistent_gnt);
|
||||||
|
num--;
|
||||||
}
|
}
|
||||||
BUG_ON(num != 0);
|
BUG_ON(num != 0);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user