Skip to content

Commit

Permalink
dm thin: return ENOSPC instead of EIO when error_if_no_space enabled
Browse files Browse the repository at this point in the history
Update the DM thin provisioning target's allocation failure error to be
consistent with commit a9d6ceb ("[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 <[email protected]>
Acked-By: Joe Thornber <[email protected]>
  • Loading branch information
snitm committed Jun 3, 2014
1 parent e7a3e87 commit af91805
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 17 deletions.
4 changes: 2 additions & 2 deletions drivers/md/dm-bio-prison.c
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,7 @@ void dm_cell_release_no_holder(struct dm_bio_prison *prison,
EXPORT_SYMBOL_GPL(dm_cell_release_no_holder);

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 *bio;
Expand All @@ -251,7 +251,7 @@ void dm_cell_error(struct dm_bio_prison *prison,
spin_unlock_irqrestore(&prison->lock, flags);

while ((bio = bio_list_pop(&bios)))
bio_io_error(bio);
bio_endio(bio, error);
}
EXPORT_SYMBOL_GPL(dm_cell_error);

Expand Down
2 changes: 1 addition & 1 deletion drivers/md/dm-bio-prison.h
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ void dm_cell_release_no_holder(struct dm_bio_prison *prison,
struct dm_bio_prison_cell *cell,
struct bio_list *inmates);
void dm_cell_error(struct dm_bio_prison *prison,
struct dm_bio_prison_cell *cell);
struct dm_bio_prison_cell *cell, int error);

/*----------------------------------------------------------------*/

Expand Down
38 changes: 24 additions & 14 deletions drivers/md/dm-thin.c
Original file line number Diff line number Diff line change
Expand Up @@ -310,13 +310,18 @@ static void cell_defer_no_holder_no_free(struct thin_c *tc,
wake_worker(pool);
}

static void cell_error(struct pool *pool,
struct dm_bio_prison_cell *cell)
static void cell_error_with_code(struct pool *pool,
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);
}

static void cell_error(struct pool *pool, struct dm_bio_prison_cell *cell)
{
cell_error_with_code(pool, cell, -EIO);
}

/*----------------------------------------------------------------*/

/*
Expand Down Expand Up @@ -1027,33 +1032,35 @@ static void retry_on_resume(struct bio *bio)
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);

switch (m) {
case PM_WRITE:
/* Shouldn't get here */
DMERR_LIMIT("bio unserviceable, yet pool is in PM_WRITE mode");
return true;
return -EIO;

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_FAIL:
return true;
return -EIO;
default:
/* Shouldn't get here */
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)
{
if (should_error_unserviceable_bio(pool))
bio_io_error(bio);
int error = should_error_unserviceable_bio(pool);

if (error)
bio_endio(bio, error);
else
retry_on_resume(bio);
}
Expand All @@ -1062,18 +1069,21 @@ static void retry_bios_on_resume(struct pool *pool, struct dm_bio_prison_cell *c
{
struct bio *bio;
struct bio_list bios;
int error;

if (should_error_unserviceable_bio(pool)) {
cell_error(pool, cell);
error = should_error_unserviceable_bio(pool);
if (error) {
cell_error_with_code(pool, cell, error);
return;
}

bio_list_init(&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)))
bio_io_error(bio);
bio_endio(bio, error);
else
while ((bio = bio_list_pop(&bios)))
retry_on_resume(bio);
Expand Down

0 comments on commit af91805

Please sign in to comment.