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

Commit 3cdf93f9 authored by Joe Thornber's avatar Joe Thornber Committed by Mike Snitzer
Browse files

dm bio prison: add dm_cell_promote_or_release()



Rather than always releasing the prisoners in a cell, the client may
want to promote one of them to be the new holder.  There is a race here
though between releasing an empty cell, and other threads adding new
inmates.  So this function makes the decision with its lock held.

This function can have two outcomes:
i)  An inmate is promoted to be the holder of the cell (return value of 0).
ii) The cell has no inmate for promotion and is released (return value of 1).

Signed-off-by: default avatarJoe Thornber <ejt@redhat.com>
Signed-off-by: default avatarMike Snitzer <snitzer@redhat.com>
parent 451b9e00
Loading
Loading
Loading
Loading
+26 −0
Original line number Diff line number Diff line
@@ -255,6 +255,32 @@ void dm_cell_visit_release(struct dm_bio_prison *prison,
}
EXPORT_SYMBOL_GPL(dm_cell_visit_release);

static int __promote_or_release(struct dm_bio_prison *prison,
				struct dm_bio_prison_cell *cell)
{
	if (bio_list_empty(&cell->bios)) {
		rb_erase(&cell->node, &prison->cells);
		return 1;
	}

	cell->holder = bio_list_pop(&cell->bios);
	return 0;
}

int dm_cell_promote_or_release(struct dm_bio_prison *prison,
			       struct dm_bio_prison_cell *cell)
{
	int r;
	unsigned long flags;

	spin_lock_irqsave(&prison->lock, flags);
	r = __promote_or_release(prison, cell);
	spin_unlock_irqrestore(&prison->lock, flags);

	return r;
}
EXPORT_SYMBOL_GPL(dm_cell_promote_or_release);

/*----------------------------------------------------------------*/

#define DEFERRED_SET_SIZE 64
+13 −0
Original line number Diff line number Diff line
@@ -101,6 +101,19 @@ void dm_cell_visit_release(struct dm_bio_prison *prison,
			   void (*visit_fn)(void *, struct dm_bio_prison_cell *),
			   void *context, struct dm_bio_prison_cell *cell);

/*
 * Rather than always releasing the prisoners in a cell, the client may
 * want to promote one of them to be the new holder.  There is a race here
 * though between releasing an empty cell, and other threads adding new
 * inmates.  So this function makes the decision with its lock held.
 *
 * This function can have two outcomes:
 * i) An inmate is promoted to be the holder of the cell (return value of 0).
 * ii) The cell has no inmate for promotion and is released (return value of 1).
 */
int dm_cell_promote_or_release(struct dm_bio_prison *prison,
			       struct dm_bio_prison_cell *cell);

/*----------------------------------------------------------------*/

/*