Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ebb351cf authored by Roger Pau Monne's avatar Roger Pau Monne Committed by Konrad Rzeszutek Wilk
Browse files

llist/xen-blkfront: implement safe version of llist_for_each_entry



Implement a safe version of llist_for_each_entry, and use it in
blkif_free. Previously grants where freed while iterating the list,
which lead to dereferences when trying to fetch the next item.

Reported-by: default avatarDan Carpenter <dan.carpenter@oracle.com>
Signed-off-by: default avatarRoger Pau Monné <roger.pau@citrix.com>
Acked-by: default avatarAndrew Morton <akpm@linux-foundation.org>
[v2: Move the llist_for_each_entry_safe in llist.h]
Signed-off-by: default avatarKonrad Rzeszutek Wilk <konrad.wilk@oracle.com>
parent 7dc34117
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -792,6 +792,7 @@ static void blkif_free(struct blkfront_info *info, int suspend)
{
	struct llist_node *all_gnts;
	struct grant *persistent_gnt;
	struct llist_node *n;

	/* Prevent new requests being issued until we fix things up. */
	spin_lock_irq(&info->io_lock);
@@ -804,7 +805,7 @@ static void blkif_free(struct blkfront_info *info, int suspend)
	/* Remove all persistent grants */
	if (info->persistent_gnts_c) {
		all_gnts = llist_del_all(&info->persistent_gnts);
		llist_for_each_entry(persistent_gnt, all_gnts, node) {
		llist_for_each_entry_safe(persistent_gnt, n, all_gnts, node) {
			gnttab_end_foreign_access(persistent_gnt->gref, 0, 0UL);
			__free_page(pfn_to_page(persistent_gnt->pfn));
			kfree(persistent_gnt);
+25 −0
Original line number Diff line number Diff line
@@ -124,6 +124,31 @@ static inline void init_llist_head(struct llist_head *list)
	     &(pos)->member != NULL;					\
	     (pos) = llist_entry((pos)->member.next, typeof(*(pos)), member))

/**
 * llist_for_each_entry_safe - iterate safely against remove over some entries
 * of lock-less list of given type.
 * @pos:	the type * to use as a loop cursor.
 * @n:		another type * to use as a temporary storage.
 * @node:	the fist entry of deleted list entries.
 * @member:	the name of the llist_node with the struct.
 *
 * In general, some entries of the lock-less list can be traversed
 * safely only after being removed from list, so start with an entry
 * instead of list head. This variant allows removal of entries
 * as we iterate.
 *
 * If being used on entries deleted from lock-less list directly, the
 * traverse order is from the newest to the oldest added entry.  If
 * you want to traverse from the oldest to the newest, you must
 * reverse the order by yourself before traversing.
 */
#define llist_for_each_entry_safe(pos, n, node, member)		\
	for ((pos) = llist_entry((node), typeof(*(pos)), member),	\
	     (n) = (pos)->member.next;					\
	     &(pos)->member != NULL;					\
	     (pos) = llist_entry(n, typeof(*(pos)), member),		\
	     (n) = (&(pos)->member != NULL) ? (pos)->member.next : NULL)

/**
 * llist_empty - tests whether a lock-less list is empty
 * @head:	the list to test