Loading drivers/md/dm.c +55 −0 Original line number Diff line number Diff line Loading @@ -972,10 +972,61 @@ void dm_accept_partial_bio(struct bio *bio, unsigned n_sectors) } EXPORT_SYMBOL_GPL(dm_accept_partial_bio); /* * Flush current->bio_list when the target map method blocks. * This fixes deadlocks in snapshot and possibly in other targets. */ struct dm_offload { struct blk_plug plug; struct blk_plug_cb cb; }; static void flush_current_bio_list(struct blk_plug_cb *cb, bool from_schedule) { struct dm_offload *o = container_of(cb, struct dm_offload, cb); struct bio_list list; struct bio *bio; INIT_LIST_HEAD(&o->cb.list); if (unlikely(!current->bio_list)) return; list = *current->bio_list; bio_list_init(current->bio_list); while ((bio = bio_list_pop(&list))) { struct bio_set *bs = bio->bi_pool; if (unlikely(!bs) || bs == fs_bio_set) { bio_list_add(current->bio_list, bio); continue; } spin_lock(&bs->rescue_lock); bio_list_add(&bs->rescue_list, bio); queue_work(bs->rescue_workqueue, &bs->rescue_work); spin_unlock(&bs->rescue_lock); } } static void dm_offload_start(struct dm_offload *o) { blk_start_plug(&o->plug); o->cb.callback = flush_current_bio_list; list_add(&o->cb.list, ¤t->plug->cb_list); } static void dm_offload_end(struct dm_offload *o) { list_del(&o->cb.list); blk_finish_plug(&o->plug); } static void __map_bio(struct dm_target_io *tio) { int r; sector_t sector; struct dm_offload o; struct bio *clone = &tio->clone; struct dm_target *ti = tio->ti; Loading @@ -988,7 +1039,11 @@ static void __map_bio(struct dm_target_io *tio) */ atomic_inc(&tio->io->io_count); sector = clone->bi_iter.bi_sector; dm_offload_start(&o); r = ti->type->map(ti, clone); dm_offload_end(&o); if (r == DM_MAPIO_REMAPPED) { /* the bio has been remapped so dispatch it */ Loading Loading
drivers/md/dm.c +55 −0 Original line number Diff line number Diff line Loading @@ -972,10 +972,61 @@ void dm_accept_partial_bio(struct bio *bio, unsigned n_sectors) } EXPORT_SYMBOL_GPL(dm_accept_partial_bio); /* * Flush current->bio_list when the target map method blocks. * This fixes deadlocks in snapshot and possibly in other targets. */ struct dm_offload { struct blk_plug plug; struct blk_plug_cb cb; }; static void flush_current_bio_list(struct blk_plug_cb *cb, bool from_schedule) { struct dm_offload *o = container_of(cb, struct dm_offload, cb); struct bio_list list; struct bio *bio; INIT_LIST_HEAD(&o->cb.list); if (unlikely(!current->bio_list)) return; list = *current->bio_list; bio_list_init(current->bio_list); while ((bio = bio_list_pop(&list))) { struct bio_set *bs = bio->bi_pool; if (unlikely(!bs) || bs == fs_bio_set) { bio_list_add(current->bio_list, bio); continue; } spin_lock(&bs->rescue_lock); bio_list_add(&bs->rescue_list, bio); queue_work(bs->rescue_workqueue, &bs->rescue_work); spin_unlock(&bs->rescue_lock); } } static void dm_offload_start(struct dm_offload *o) { blk_start_plug(&o->plug); o->cb.callback = flush_current_bio_list; list_add(&o->cb.list, ¤t->plug->cb_list); } static void dm_offload_end(struct dm_offload *o) { list_del(&o->cb.list); blk_finish_plug(&o->plug); } static void __map_bio(struct dm_target_io *tio) { int r; sector_t sector; struct dm_offload o; struct bio *clone = &tio->clone; struct dm_target *ti = tio->ti; Loading @@ -988,7 +1039,11 @@ static void __map_bio(struct dm_target_io *tio) */ atomic_inc(&tio->io->io_count); sector = clone->bi_iter.bi_sector; dm_offload_start(&o); r = ti->type->map(ti, clone); dm_offload_end(&o); if (r == DM_MAPIO_REMAPPED) { /* the bio has been remapped so dispatch it */ Loading