static void punt_bios_to_rescuer(struct bio_set *bs) { struct bio_list punt, nopunt; struct bio *bio; /* * In order to guarantee forward progress we must punt only bios that * were allocated from this bio_set; otherwise, if there was a bio on * there for a stacking driver higher up in the stack, processing it * could require allocating bios from this bio_set, and doing that from * our own rescuer would be bad. * * Since bio lists are singly linked, pop them all instead of trying to * remove from the middle of the list: */ bio_list_init(&punt); bio_list_init(&nopunt); while ((bio = bio_list_pop(current->bio_list))) bio_list_add(bio->bi_pool == bs ? &punt : &nopunt, bio); *current->bio_list = nopunt; spin_lock(&bs->rescue_lock); bio_list_merge(&bs->rescue_list, &punt); spin_unlock(&bs->rescue_lock); queue_work(bs->rescue_workqueue, &bs->rescue_work); }
/* * @inmates must have been initialised prior to this call */ static void __cell_release(struct dm_bio_prison_cell *cell, struct bio_list *inmates) { hlist_del(&cell->list); if (inmates) { if (cell->holder) bio_list_add(inmates, cell->holder); bio_list_merge(inmates, &cell->bios); } }
static void rrpc_requeue(struct work_struct *work) { struct rrpc *rrpc = container_of(work, struct rrpc, ws_requeue); struct bio_list bios; struct bio *bio; bio_list_init(&bios); spin_lock(&rrpc->bio_lock); bio_list_merge(&bios, &rrpc->requeue_bios); bio_list_init(&rrpc->requeue_bios); spin_unlock(&rrpc->bio_lock); while ((bio = bio_list_pop(&bios))) rrpc_make_rq(rrpc->disk->queue, bio); }
/* * Sometimes we don't want the holder, just the additional bios. */ static void __cell_release_no_holder(struct dm_bio_prison_cell *cell, struct bio_list *inmates) { hlist_del(&cell->list); bio_list_merge(inmates, &cell->bios); }