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: Joe Thornber <ejt@redhat.com> Signed-off-by: Mike Snitzer <snitzer@redhat.com>
This commit is contained in:
parent
451b9e0071
commit
3cdf93f9d8
2 changed files with 39 additions and 0 deletions
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
||||
/*----------------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
|
|
Loading…
Reference in a new issue