dm thin: add error_if_no_space feature
If the pool runs out of data or metadata space, the pool can either queue or error the IO destined to the data device. The default is to queue the IO until more space is added. An admin may now configure the pool to error IO when no space is available by setting the 'error_if_no_space' feature when loading the thin-pool table. Signed-off-by: Mike Snitzer <snitzer@redhat.com> Acked-by: Joe Thornber <ejt@redhat.com>
This commit is contained in:
Родитель
8c0f0e8c9f
Коммит
787a996cb2
|
@ -235,6 +235,8 @@ i) Constructor
|
||||||
read_only: Don't allow any changes to be made to the pool
|
read_only: Don't allow any changes to be made to the pool
|
||||||
metadata.
|
metadata.
|
||||||
|
|
||||||
|
error_if_no_space: Error IOs, instead of queueing, if no space.
|
||||||
|
|
||||||
Data block size must be between 64KB (128 sectors) and 1GB
|
Data block size must be between 64KB (128 sectors) and 1GB
|
||||||
(2097152 sectors) inclusive.
|
(2097152 sectors) inclusive.
|
||||||
|
|
||||||
|
@ -276,6 +278,11 @@ ii) Status
|
||||||
contain the string 'Fail'. The userspace recovery tools
|
contain the string 'Fail'. The userspace recovery tools
|
||||||
should then be used.
|
should then be used.
|
||||||
|
|
||||||
|
error_if_no_space|queue_if_no_space
|
||||||
|
If the pool runs out of data or metadata space, the pool will
|
||||||
|
either queue or error the IO destined to the data device. The
|
||||||
|
default is to queue the IO until more space is added.
|
||||||
|
|
||||||
iii) Messages
|
iii) Messages
|
||||||
|
|
||||||
create_thin <dev id>
|
create_thin <dev id>
|
||||||
|
|
|
@ -144,6 +144,7 @@ struct pool_features {
|
||||||
bool zero_new_blocks:1;
|
bool zero_new_blocks:1;
|
||||||
bool discard_enabled:1;
|
bool discard_enabled:1;
|
||||||
bool discard_passdown:1;
|
bool discard_passdown:1;
|
||||||
|
bool error_if_no_space:1;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct thin_c;
|
struct thin_c;
|
||||||
|
@ -1440,6 +1441,9 @@ static void set_no_free_space(struct pool *pool)
|
||||||
{
|
{
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
|
if (pool->pf.error_if_no_space)
|
||||||
|
return;
|
||||||
|
|
||||||
spin_lock_irqsave(&pool->lock, flags);
|
spin_lock_irqsave(&pool->lock, flags);
|
||||||
pool->no_free_space = true;
|
pool->no_free_space = true;
|
||||||
spin_unlock_irqrestore(&pool->lock, flags);
|
spin_unlock_irqrestore(&pool->lock, flags);
|
||||||
|
@ -1723,6 +1727,7 @@ static void pool_features_init(struct pool_features *pf)
|
||||||
pf->zero_new_blocks = true;
|
pf->zero_new_blocks = true;
|
||||||
pf->discard_enabled = true;
|
pf->discard_enabled = true;
|
||||||
pf->discard_passdown = true;
|
pf->discard_passdown = true;
|
||||||
|
pf->error_if_no_space = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __pool_destroy(struct pool *pool)
|
static void __pool_destroy(struct pool *pool)
|
||||||
|
@ -1968,6 +1973,9 @@ static int parse_pool_features(struct dm_arg_set *as, struct pool_features *pf,
|
||||||
else if (!strcasecmp(arg_name, "read_only"))
|
else if (!strcasecmp(arg_name, "read_only"))
|
||||||
pf->mode = PM_READ_ONLY;
|
pf->mode = PM_READ_ONLY;
|
||||||
|
|
||||||
|
else if (!strcasecmp(arg_name, "error_if_no_space"))
|
||||||
|
pf->error_if_no_space = true;
|
||||||
|
|
||||||
else {
|
else {
|
||||||
ti->error = "Unrecognised pool feature requested";
|
ti->error = "Unrecognised pool feature requested";
|
||||||
r = -EINVAL;
|
r = -EINVAL;
|
||||||
|
@ -2038,6 +2046,8 @@ static dm_block_t calc_metadata_threshold(struct pool_c *pt)
|
||||||
* skip_block_zeroing: skips the zeroing of newly-provisioned blocks.
|
* skip_block_zeroing: skips the zeroing of newly-provisioned blocks.
|
||||||
* ignore_discard: disable discard
|
* ignore_discard: disable discard
|
||||||
* no_discard_passdown: don't pass discards down to the data device
|
* no_discard_passdown: don't pass discards down to the data device
|
||||||
|
* read_only: Don't allow any changes to be made to the pool metadata.
|
||||||
|
* error_if_no_space: error IOs, instead of queueing, if no space.
|
||||||
*/
|
*/
|
||||||
static int pool_ctr(struct dm_target *ti, unsigned argc, char **argv)
|
static int pool_ctr(struct dm_target *ti, unsigned argc, char **argv)
|
||||||
{
|
{
|
||||||
|
@ -2555,7 +2565,8 @@ static void emit_flags(struct pool_features *pf, char *result,
|
||||||
unsigned sz, unsigned maxlen)
|
unsigned sz, unsigned maxlen)
|
||||||
{
|
{
|
||||||
unsigned count = !pf->zero_new_blocks + !pf->discard_enabled +
|
unsigned count = !pf->zero_new_blocks + !pf->discard_enabled +
|
||||||
!pf->discard_passdown + (pf->mode == PM_READ_ONLY);
|
!pf->discard_passdown + (pf->mode == PM_READ_ONLY) +
|
||||||
|
pf->error_if_no_space;
|
||||||
DMEMIT("%u ", count);
|
DMEMIT("%u ", count);
|
||||||
|
|
||||||
if (!pf->zero_new_blocks)
|
if (!pf->zero_new_blocks)
|
||||||
|
@ -2569,6 +2580,9 @@ static void emit_flags(struct pool_features *pf, char *result,
|
||||||
|
|
||||||
if (pf->mode == PM_READ_ONLY)
|
if (pf->mode == PM_READ_ONLY)
|
||||||
DMEMIT("read_only ");
|
DMEMIT("read_only ");
|
||||||
|
|
||||||
|
if (pf->error_if_no_space)
|
||||||
|
DMEMIT("error_if_no_space ");
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -2663,11 +2677,16 @@ static void pool_status(struct dm_target *ti, status_type_t type,
|
||||||
DMEMIT("rw ");
|
DMEMIT("rw ");
|
||||||
|
|
||||||
if (!pool->pf.discard_enabled)
|
if (!pool->pf.discard_enabled)
|
||||||
DMEMIT("ignore_discard");
|
DMEMIT("ignore_discard ");
|
||||||
else if (pool->pf.discard_passdown)
|
else if (pool->pf.discard_passdown)
|
||||||
DMEMIT("discard_passdown");
|
DMEMIT("discard_passdown ");
|
||||||
else
|
else
|
||||||
DMEMIT("no_discard_passdown");
|
DMEMIT("no_discard_passdown ");
|
||||||
|
|
||||||
|
if (pool->pf.error_if_no_space)
|
||||||
|
DMEMIT("error_if_no_space ");
|
||||||
|
else
|
||||||
|
DMEMIT("queue_if_no_space ");
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -2766,7 +2785,7 @@ static struct target_type pool_target = {
|
||||||
.name = "thin-pool",
|
.name = "thin-pool",
|
||||||
.features = DM_TARGET_SINGLETON | DM_TARGET_ALWAYS_WRITEABLE |
|
.features = DM_TARGET_SINGLETON | DM_TARGET_ALWAYS_WRITEABLE |
|
||||||
DM_TARGET_IMMUTABLE,
|
DM_TARGET_IMMUTABLE,
|
||||||
.version = {1, 9, 0},
|
.version = {1, 10, 0},
|
||||||
.module = THIS_MODULE,
|
.module = THIS_MODULE,
|
||||||
.ctr = pool_ctr,
|
.ctr = pool_ctr,
|
||||||
.dtr = pool_dtr,
|
.dtr = pool_dtr,
|
||||||
|
@ -3053,7 +3072,7 @@ static int thin_iterate_devices(struct dm_target *ti,
|
||||||
|
|
||||||
static struct target_type thin_target = {
|
static struct target_type thin_target = {
|
||||||
.name = "thin",
|
.name = "thin",
|
||||||
.version = {1, 9, 0},
|
.version = {1, 10, 0},
|
||||||
.module = THIS_MODULE,
|
.module = THIS_MODULE,
|
||||||
.ctr = thin_ctr,
|
.ctr = thin_ctr,
|
||||||
.dtr = thin_dtr,
|
.dtr = thin_dtr,
|
||||||
|
|
Загрузка…
Ссылка в новой задаче