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:
Родитель
451b9e0071
Коммит
3cdf93f9d8
|
@ -255,6 +255,32 @@ void dm_cell_visit_release(struct dm_bio_prison *prison,
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(dm_cell_visit_release);
|
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
|
#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 (*visit_fn)(void *, struct dm_bio_prison_cell *),
|
||||||
void *context, struct dm_bio_prison_cell *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);
|
||||||
|
|
||||||
/*----------------------------------------------------------------*/
|
/*----------------------------------------------------------------*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
Загрузка…
Ссылка в новой задаче