dm: change ->end_io calling convention
Turn the error paramter into a pointer so that target drivers can change the value, and make sure only DM_ENDIO_* values are returned from the methods. Signed-off-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Mike Snitzer <snitzer@redhat.com> Signed-off-by: Jens Axboe <axboe@fb.com>
This commit is contained in:
Родитель
846785e6a5
Коммит
1be5690984
|
@ -2820,7 +2820,7 @@ static int cache_map(struct dm_target *ti, struct bio *bio)
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int cache_end_io(struct dm_target *ti, struct bio *bio, int error)
|
static int cache_end_io(struct dm_target *ti, struct bio *bio, int *error)
|
||||||
{
|
{
|
||||||
struct cache *cache = ti->private;
|
struct cache *cache = ti->private;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
@ -2838,7 +2838,7 @@ static int cache_end_io(struct dm_target *ti, struct bio *bio, int error)
|
||||||
bio_drop_shared_lock(cache, bio);
|
bio_drop_shared_lock(cache, bio);
|
||||||
accounted_complete(cache, bio);
|
accounted_complete(cache, bio);
|
||||||
|
|
||||||
return 0;
|
return DM_ENDIO_DONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int write_dirty_bitset(struct cache *cache)
|
static int write_dirty_bitset(struct cache *cache)
|
||||||
|
|
|
@ -358,12 +358,12 @@ map_bio:
|
||||||
return DM_MAPIO_REMAPPED;
|
return DM_MAPIO_REMAPPED;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int flakey_end_io(struct dm_target *ti, struct bio *bio, int error)
|
static int flakey_end_io(struct dm_target *ti, struct bio *bio, int *error)
|
||||||
{
|
{
|
||||||
struct flakey_c *fc = ti->private;
|
struct flakey_c *fc = ti->private;
|
||||||
struct per_bio_data *pb = dm_per_bio_data(bio, sizeof(struct per_bio_data));
|
struct per_bio_data *pb = dm_per_bio_data(bio, sizeof(struct per_bio_data));
|
||||||
|
|
||||||
if (!error && pb->bio_submitted && (bio_data_dir(bio) == READ)) {
|
if (!*error && pb->bio_submitted && (bio_data_dir(bio) == READ)) {
|
||||||
if (fc->corrupt_bio_byte && (fc->corrupt_bio_rw == READ) &&
|
if (fc->corrupt_bio_byte && (fc->corrupt_bio_rw == READ) &&
|
||||||
all_corrupt_bio_flags_match(bio, fc)) {
|
all_corrupt_bio_flags_match(bio, fc)) {
|
||||||
/*
|
/*
|
||||||
|
@ -377,11 +377,11 @@ static int flakey_end_io(struct dm_target *ti, struct bio *bio, int error)
|
||||||
* Error read during the down_interval if drop_writes
|
* Error read during the down_interval if drop_writes
|
||||||
* and error_writes were not configured.
|
* and error_writes were not configured.
|
||||||
*/
|
*/
|
||||||
return -EIO;
|
*error = -EIO;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return error;
|
return DM_ENDIO_DONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void flakey_status(struct dm_target *ti, status_type_t type,
|
static void flakey_status(struct dm_target *ti, status_type_t type,
|
||||||
|
|
|
@ -664,7 +664,7 @@ map_bio:
|
||||||
return DM_MAPIO_REMAPPED;
|
return DM_MAPIO_REMAPPED;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int normal_end_io(struct dm_target *ti, struct bio *bio, int error)
|
static int normal_end_io(struct dm_target *ti, struct bio *bio, int *error)
|
||||||
{
|
{
|
||||||
struct log_writes_c *lc = ti->private;
|
struct log_writes_c *lc = ti->private;
|
||||||
struct per_bio_data *pb = dm_per_bio_data(bio, sizeof(struct per_bio_data));
|
struct per_bio_data *pb = dm_per_bio_data(bio, sizeof(struct per_bio_data));
|
||||||
|
@ -686,7 +686,7 @@ static int normal_end_io(struct dm_target *ti, struct bio *bio, int error)
|
||||||
spin_unlock_irqrestore(&lc->blocks_lock, flags);
|
spin_unlock_irqrestore(&lc->blocks_lock, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
return error;
|
return DM_ENDIO_DONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -1517,14 +1517,15 @@ static int multipath_end_io(struct dm_target *ti, struct request *clone,
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int multipath_end_io_bio(struct dm_target *ti, struct bio *clone, int error)
|
static int multipath_end_io_bio(struct dm_target *ti, struct bio *clone, int *error)
|
||||||
{
|
{
|
||||||
struct multipath *m = ti->private;
|
struct multipath *m = ti->private;
|
||||||
struct dm_mpath_io *mpio = get_mpio_from_bio(clone);
|
struct dm_mpath_io *mpio = get_mpio_from_bio(clone);
|
||||||
struct pgpath *pgpath = mpio->pgpath;
|
struct pgpath *pgpath = mpio->pgpath;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
int r = DM_ENDIO_DONE;
|
||||||
|
|
||||||
if (!error || noretry_error(error))
|
if (!*error || noretry_error(*error))
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
if (pgpath)
|
if (pgpath)
|
||||||
|
@ -1533,7 +1534,7 @@ static int multipath_end_io_bio(struct dm_target *ti, struct bio *clone, int err
|
||||||
if (atomic_read(&m->nr_valid_paths) == 0 &&
|
if (atomic_read(&m->nr_valid_paths) == 0 &&
|
||||||
!test_bit(MPATHF_QUEUE_IF_NO_PATH, &m->flags)) {
|
!test_bit(MPATHF_QUEUE_IF_NO_PATH, &m->flags)) {
|
||||||
dm_report_EIO(m);
|
dm_report_EIO(m);
|
||||||
error = -EIO;
|
*error = -EIO;
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1546,7 +1547,7 @@ static int multipath_end_io_bio(struct dm_target *ti, struct bio *clone, int err
|
||||||
if (!test_bit(MPATHF_QUEUE_IO, &m->flags))
|
if (!test_bit(MPATHF_QUEUE_IO, &m->flags))
|
||||||
queue_work(kmultipathd, &m->process_queued_bios);
|
queue_work(kmultipathd, &m->process_queued_bios);
|
||||||
|
|
||||||
error = DM_ENDIO_INCOMPLETE;
|
r = DM_ENDIO_INCOMPLETE;
|
||||||
done:
|
done:
|
||||||
if (pgpath) {
|
if (pgpath) {
|
||||||
struct path_selector *ps = &pgpath->pg->ps;
|
struct path_selector *ps = &pgpath->pg->ps;
|
||||||
|
@ -1555,7 +1556,7 @@ done:
|
||||||
ps->type->end_io(ps, &pgpath->path, mpio->nr_bytes);
|
ps->type->end_io(ps, &pgpath->path, mpio->nr_bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
return error;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -1236,7 +1236,7 @@ static int mirror_map(struct dm_target *ti, struct bio *bio)
|
||||||
return DM_MAPIO_REMAPPED;
|
return DM_MAPIO_REMAPPED;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int mirror_end_io(struct dm_target *ti, struct bio *bio, int error)
|
static int mirror_end_io(struct dm_target *ti, struct bio *bio, int *error)
|
||||||
{
|
{
|
||||||
int rw = bio_data_dir(bio);
|
int rw = bio_data_dir(bio);
|
||||||
struct mirror_set *ms = (struct mirror_set *) ti->private;
|
struct mirror_set *ms = (struct mirror_set *) ti->private;
|
||||||
|
@ -1252,16 +1252,16 @@ static int mirror_end_io(struct dm_target *ti, struct bio *bio, int error)
|
||||||
if (!(bio->bi_opf & REQ_PREFLUSH) &&
|
if (!(bio->bi_opf & REQ_PREFLUSH) &&
|
||||||
bio_op(bio) != REQ_OP_DISCARD)
|
bio_op(bio) != REQ_OP_DISCARD)
|
||||||
dm_rh_dec(ms->rh, bio_record->write_region);
|
dm_rh_dec(ms->rh, bio_record->write_region);
|
||||||
return error;
|
return DM_ENDIO_DONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (error == -EOPNOTSUPP)
|
if (*error == -EOPNOTSUPP)
|
||||||
return error;
|
return DM_ENDIO_DONE;
|
||||||
|
|
||||||
if (bio->bi_opf & REQ_RAHEAD)
|
if (bio->bi_opf & REQ_RAHEAD)
|
||||||
return error;
|
return DM_ENDIO_DONE;
|
||||||
|
|
||||||
if (unlikely(error)) {
|
if (unlikely(*error)) {
|
||||||
m = bio_record->m;
|
m = bio_record->m;
|
||||||
|
|
||||||
DMERR("Mirror read failed from %s. Trying alternative device.",
|
DMERR("Mirror read failed from %s. Trying alternative device.",
|
||||||
|
@ -1285,7 +1285,7 @@ static int mirror_end_io(struct dm_target *ti, struct bio *bio, int error)
|
||||||
DMERR("All replicated volumes dead, failing I/O");
|
DMERR("All replicated volumes dead, failing I/O");
|
||||||
}
|
}
|
||||||
|
|
||||||
return error;
|
return DM_ENDIO_DONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void mirror_presuspend(struct dm_target *ti)
|
static void mirror_presuspend(struct dm_target *ti)
|
||||||
|
|
|
@ -1851,14 +1851,14 @@ out_unlock:
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int snapshot_end_io(struct dm_target *ti, struct bio *bio, int error)
|
static int snapshot_end_io(struct dm_target *ti, struct bio *bio, int *error)
|
||||||
{
|
{
|
||||||
struct dm_snapshot *s = ti->private;
|
struct dm_snapshot *s = ti->private;
|
||||||
|
|
||||||
if (is_bio_tracked(bio))
|
if (is_bio_tracked(bio))
|
||||||
stop_tracking_chunk(s, bio);
|
stop_tracking_chunk(s, bio);
|
||||||
|
|
||||||
return 0;
|
return DM_ENDIO_DONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void snapshot_merge_presuspend(struct dm_target *ti)
|
static void snapshot_merge_presuspend(struct dm_target *ti)
|
||||||
|
|
|
@ -375,20 +375,20 @@ static void stripe_status(struct dm_target *ti, status_type_t type,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int stripe_end_io(struct dm_target *ti, struct bio *bio, int error)
|
static int stripe_end_io(struct dm_target *ti, struct bio *bio, int *error)
|
||||||
{
|
{
|
||||||
unsigned i;
|
unsigned i;
|
||||||
char major_minor[16];
|
char major_minor[16];
|
||||||
struct stripe_c *sc = ti->private;
|
struct stripe_c *sc = ti->private;
|
||||||
|
|
||||||
if (!error)
|
if (!*error)
|
||||||
return 0; /* I/O complete */
|
return DM_ENDIO_DONE; /* I/O complete */
|
||||||
|
|
||||||
if (bio->bi_opf & REQ_RAHEAD)
|
if (bio->bi_opf & REQ_RAHEAD)
|
||||||
return error;
|
return DM_ENDIO_DONE;
|
||||||
|
|
||||||
if (error == -EOPNOTSUPP)
|
if (*error == -EOPNOTSUPP)
|
||||||
return error;
|
return DM_ENDIO_DONE;
|
||||||
|
|
||||||
memset(major_minor, 0, sizeof(major_minor));
|
memset(major_minor, 0, sizeof(major_minor));
|
||||||
sprintf(major_minor, "%d:%d",
|
sprintf(major_minor, "%d:%d",
|
||||||
|
@ -409,7 +409,7 @@ static int stripe_end_io(struct dm_target *ti, struct bio *bio, int error)
|
||||||
schedule_work(&sc->trigger_event);
|
schedule_work(&sc->trigger_event);
|
||||||
}
|
}
|
||||||
|
|
||||||
return error;
|
return DM_ENDIO_DONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int stripe_iterate_devices(struct dm_target *ti,
|
static int stripe_iterate_devices(struct dm_target *ti,
|
||||||
|
|
|
@ -4177,7 +4177,7 @@ static int thin_map(struct dm_target *ti, struct bio *bio)
|
||||||
return thin_bio_map(ti, bio);
|
return thin_bio_map(ti, bio);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int thin_endio(struct dm_target *ti, struct bio *bio, int err)
|
static int thin_endio(struct dm_target *ti, struct bio *bio, int *err)
|
||||||
{
|
{
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
struct dm_thin_endio_hook *h = dm_per_bio_data(bio, sizeof(struct dm_thin_endio_hook));
|
struct dm_thin_endio_hook *h = dm_per_bio_data(bio, sizeof(struct dm_thin_endio_hook));
|
||||||
|
@ -4212,7 +4212,7 @@ static int thin_endio(struct dm_target *ti, struct bio *bio, int err)
|
||||||
if (h->cell)
|
if (h->cell)
|
||||||
cell_defer_no_holder(h->tc, h->cell);
|
cell_defer_no_holder(h->tc, h->cell);
|
||||||
|
|
||||||
return 0;
|
return DM_ENDIO_DONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void thin_presuspend(struct dm_target *ti)
|
static void thin_presuspend(struct dm_target *ti)
|
||||||
|
|
|
@ -845,24 +845,7 @@ static void clone_endio(struct bio *bio)
|
||||||
struct mapped_device *md = tio->io->md;
|
struct mapped_device *md = tio->io->md;
|
||||||
dm_endio_fn endio = tio->ti->type->end_io;
|
dm_endio_fn endio = tio->ti->type->end_io;
|
||||||
|
|
||||||
if (endio) {
|
if (unlikely(error == -EREMOTEIO)) {
|
||||||
r = endio(tio->ti, bio, error);
|
|
||||||
if (r < 0 || r == DM_ENDIO_REQUEUE)
|
|
||||||
/*
|
|
||||||
* error and requeue request are handled
|
|
||||||
* in dec_pending().
|
|
||||||
*/
|
|
||||||
error = r;
|
|
||||||
else if (r == DM_ENDIO_INCOMPLETE)
|
|
||||||
/* The target will handle the io */
|
|
||||||
return;
|
|
||||||
else if (r) {
|
|
||||||
DMWARN("unimplemented target endio return value: %d", r);
|
|
||||||
BUG();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (unlikely(r == -EREMOTEIO)) {
|
|
||||||
if (bio_op(bio) == REQ_OP_WRITE_SAME &&
|
if (bio_op(bio) == REQ_OP_WRITE_SAME &&
|
||||||
!bdev_get_queue(bio->bi_bdev)->limits.max_write_same_sectors)
|
!bdev_get_queue(bio->bi_bdev)->limits.max_write_same_sectors)
|
||||||
disable_write_same(md);
|
disable_write_same(md);
|
||||||
|
@ -871,6 +854,23 @@ static void clone_endio(struct bio *bio)
|
||||||
disable_write_zeroes(md);
|
disable_write_zeroes(md);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (endio) {
|
||||||
|
r = endio(tio->ti, bio, &error);
|
||||||
|
switch (r) {
|
||||||
|
case DM_ENDIO_REQUEUE:
|
||||||
|
error = DM_ENDIO_REQUEUE;
|
||||||
|
/*FALLTHRU*/
|
||||||
|
case DM_ENDIO_DONE:
|
||||||
|
break;
|
||||||
|
case DM_ENDIO_INCOMPLETE:
|
||||||
|
/* The target will handle the io */
|
||||||
|
return;
|
||||||
|
default:
|
||||||
|
DMWARN("unimplemented target endio return value: %d", r);
|
||||||
|
BUG();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
free_tio(tio);
|
free_tio(tio);
|
||||||
dec_pending(io, error);
|
dec_pending(io, error);
|
||||||
}
|
}
|
||||||
|
|
|
@ -72,7 +72,7 @@ typedef void (*dm_release_clone_request_fn) (struct request *clone);
|
||||||
* 2 : The target wants to push back the io
|
* 2 : The target wants to push back the io
|
||||||
*/
|
*/
|
||||||
typedef int (*dm_endio_fn) (struct dm_target *ti,
|
typedef int (*dm_endio_fn) (struct dm_target *ti,
|
||||||
struct bio *bio, int error);
|
struct bio *bio, int *error);
|
||||||
typedef int (*dm_request_endio_fn) (struct dm_target *ti,
|
typedef int (*dm_request_endio_fn) (struct dm_target *ti,
|
||||||
struct request *clone, int error,
|
struct request *clone, int error,
|
||||||
union map_info *map_context);
|
union map_info *map_context);
|
||||||
|
|
Загрузка…
Ссылка в новой задаче