forked from Minki/linux
dm thin: return ENOSPC instead of EIO when error_if_no_space enabled
Update the DM thin provisioning target's allocation failure error to be
consistent with commit a9d6ceb8
("[SCSI] return ENOSPC on thin
provisioning failure").
The DM thin target now returns -ENOSPC rather than -EIO when
block allocation fails due to the pool being out of data space (and
the 'error_if_no_space' thin-pool feature is enabled).
Signed-off-by: Mike Snitzer <snitzer@redhat.com>
Acked-By: Joe Thornber <ejt@redhat.com>
This commit is contained in:
parent
e7a3e871d8
commit
af91805a49
@ -238,7 +238,7 @@ void dm_cell_release_no_holder(struct dm_bio_prison *prison,
|
|||||||
EXPORT_SYMBOL_GPL(dm_cell_release_no_holder);
|
EXPORT_SYMBOL_GPL(dm_cell_release_no_holder);
|
||||||
|
|
||||||
void dm_cell_error(struct dm_bio_prison *prison,
|
void dm_cell_error(struct dm_bio_prison *prison,
|
||||||
struct dm_bio_prison_cell *cell)
|
struct dm_bio_prison_cell *cell, int error)
|
||||||
{
|
{
|
||||||
struct bio_list bios;
|
struct bio_list bios;
|
||||||
struct bio *bio;
|
struct bio *bio;
|
||||||
@ -251,7 +251,7 @@ void dm_cell_error(struct dm_bio_prison *prison,
|
|||||||
spin_unlock_irqrestore(&prison->lock, flags);
|
spin_unlock_irqrestore(&prison->lock, flags);
|
||||||
|
|
||||||
while ((bio = bio_list_pop(&bios)))
|
while ((bio = bio_list_pop(&bios)))
|
||||||
bio_io_error(bio);
|
bio_endio(bio, error);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(dm_cell_error);
|
EXPORT_SYMBOL_GPL(dm_cell_error);
|
||||||
|
|
||||||
|
@ -85,7 +85,7 @@ void dm_cell_release_no_holder(struct dm_bio_prison *prison,
|
|||||||
struct dm_bio_prison_cell *cell,
|
struct dm_bio_prison_cell *cell,
|
||||||
struct bio_list *inmates);
|
struct bio_list *inmates);
|
||||||
void dm_cell_error(struct dm_bio_prison *prison,
|
void dm_cell_error(struct dm_bio_prison *prison,
|
||||||
struct dm_bio_prison_cell *cell);
|
struct dm_bio_prison_cell *cell, int error);
|
||||||
|
|
||||||
/*----------------------------------------------------------------*/
|
/*----------------------------------------------------------------*/
|
||||||
|
|
||||||
|
@ -310,13 +310,18 @@ static void cell_defer_no_holder_no_free(struct thin_c *tc,
|
|||||||
wake_worker(pool);
|
wake_worker(pool);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void cell_error(struct pool *pool,
|
static void cell_error_with_code(struct pool *pool,
|
||||||
struct dm_bio_prison_cell *cell)
|
struct dm_bio_prison_cell *cell, int error_code)
|
||||||
{
|
{
|
||||||
dm_cell_error(pool->prison, cell);
|
dm_cell_error(pool->prison, cell, error_code);
|
||||||
dm_bio_prison_free_cell(pool->prison, cell);
|
dm_bio_prison_free_cell(pool->prison, cell);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void cell_error(struct pool *pool, struct dm_bio_prison_cell *cell)
|
||||||
|
{
|
||||||
|
cell_error_with_code(pool, cell, -EIO);
|
||||||
|
}
|
||||||
|
|
||||||
/*----------------------------------------------------------------*/
|
/*----------------------------------------------------------------*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1027,7 +1032,7 @@ static void retry_on_resume(struct bio *bio)
|
|||||||
spin_unlock_irqrestore(&tc->lock, flags);
|
spin_unlock_irqrestore(&tc->lock, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool should_error_unserviceable_bio(struct pool *pool)
|
static int should_error_unserviceable_bio(struct pool *pool)
|
||||||
{
|
{
|
||||||
enum pool_mode m = get_pool_mode(pool);
|
enum pool_mode m = get_pool_mode(pool);
|
||||||
|
|
||||||
@ -1035,25 +1040,27 @@ static bool should_error_unserviceable_bio(struct pool *pool)
|
|||||||
case PM_WRITE:
|
case PM_WRITE:
|
||||||
/* Shouldn't get here */
|
/* Shouldn't get here */
|
||||||
DMERR_LIMIT("bio unserviceable, yet pool is in PM_WRITE mode");
|
DMERR_LIMIT("bio unserviceable, yet pool is in PM_WRITE mode");
|
||||||
return true;
|
return -EIO;
|
||||||
|
|
||||||
case PM_OUT_OF_DATA_SPACE:
|
case PM_OUT_OF_DATA_SPACE:
|
||||||
return pool->pf.error_if_no_space;
|
return pool->pf.error_if_no_space ? -ENOSPC : 0;
|
||||||
|
|
||||||
case PM_READ_ONLY:
|
case PM_READ_ONLY:
|
||||||
case PM_FAIL:
|
case PM_FAIL:
|
||||||
return true;
|
return -EIO;
|
||||||
default:
|
default:
|
||||||
/* Shouldn't get here */
|
/* Shouldn't get here */
|
||||||
DMERR_LIMIT("bio unserviceable, yet pool has an unknown mode");
|
DMERR_LIMIT("bio unserviceable, yet pool has an unknown mode");
|
||||||
return true;
|
return -EIO;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void handle_unserviceable_bio(struct pool *pool, struct bio *bio)
|
static void handle_unserviceable_bio(struct pool *pool, struct bio *bio)
|
||||||
{
|
{
|
||||||
if (should_error_unserviceable_bio(pool))
|
int error = should_error_unserviceable_bio(pool);
|
||||||
bio_io_error(bio);
|
|
||||||
|
if (error)
|
||||||
|
bio_endio(bio, error);
|
||||||
else
|
else
|
||||||
retry_on_resume(bio);
|
retry_on_resume(bio);
|
||||||
}
|
}
|
||||||
@ -1062,18 +1069,21 @@ static void retry_bios_on_resume(struct pool *pool, struct dm_bio_prison_cell *c
|
|||||||
{
|
{
|
||||||
struct bio *bio;
|
struct bio *bio;
|
||||||
struct bio_list bios;
|
struct bio_list bios;
|
||||||
|
int error;
|
||||||
|
|
||||||
if (should_error_unserviceable_bio(pool)) {
|
error = should_error_unserviceable_bio(pool);
|
||||||
cell_error(pool, cell);
|
if (error) {
|
||||||
|
cell_error_with_code(pool, cell, error);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
bio_list_init(&bios);
|
bio_list_init(&bios);
|
||||||
cell_release(pool, cell, &bios);
|
cell_release(pool, cell, &bios);
|
||||||
|
|
||||||
if (should_error_unserviceable_bio(pool))
|
error = should_error_unserviceable_bio(pool);
|
||||||
|
if (error)
|
||||||
while ((bio = bio_list_pop(&bios)))
|
while ((bio = bio_list_pop(&bios)))
|
||||||
bio_io_error(bio);
|
bio_endio(bio, error);
|
||||||
else
|
else
|
||||||
while ((bio = bio_list_pop(&bios)))
|
while ((bio = bio_list_pop(&bios)))
|
||||||
retry_on_resume(bio);
|
retry_on_resume(bio);
|
||||||
|
Loading…
Reference in New Issue
Block a user