};
static enum pool_mode get_pool_mode(struct pool *pool);
+static void out_of_data_space(struct pool *pool);
static void metadata_operation_failed(struct pool *pool, const char *op, int r);
/*
{
int r;
dm_block_t free_blocks;
- unsigned long flags;
struct pool *pool = tc->pool;
- /*
- * Once no_free_space is set we must not allow allocation to succeed.
- * Otherwise it is difficult to explain, debug, test and support.
- */
- if (pool->no_free_space)
- return -ENOSPC;
-
if (get_pool_mode(pool) != PM_WRITE)
return -EINVAL;
return r;
}
- /*
- * If we still have no space we set a flag to avoid
- * doing all this checking and return -ENOSPC. This
- * flag serves as a latch that disallows allocations from
- * this pool until the admin takes action (e.g. resize or
- * table reload).
- */
if (!free_blocks) {
- DMWARN("%s: no free data space available.",
- dm_device_name(pool->pool_md));
- spin_lock_irqsave(&pool->lock, flags);
- pool->no_free_space = true;
- spin_unlock_irqrestore(&pool->lock, flags);
+ out_of_data_space(pool);
return -ENOSPC;
}
}
r = dm_pool_alloc_data_block(pool->pmd, result);
if (r) {
- if (r == -ENOSPC &&
- !dm_pool_get_free_metadata_block_count(pool->pmd, &free_blocks) &&
- !free_blocks)
- DMWARN("%s: no free metadata space available.",
- dm_device_name(pool->pool_md));
-
metadata_operation_failed(pool, "dm_pool_alloc_data_block", r);
return r;
}
spin_unlock_irqrestore(&pool->lock, flags);
}
-static void no_space(struct pool *pool, struct dm_bio_prison_cell *cell)
+static void retry_bios_on_resume(struct pool *pool, struct dm_bio_prison_cell *cell)
{
struct bio *bio;
struct bio_list bios;
break;
case -ENOSPC:
- no_space(pool, cell);
+ retry_bios_on_resume(pool, cell);
break;
default:
break;
case -ENOSPC:
- no_space(pool, cell);
+ retry_bios_on_resume(pool, cell);
break;
default:
}
}
+static void set_no_free_space(struct pool *pool)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&pool->lock, flags);
+ pool->no_free_space = true;
+ spin_unlock_irqrestore(&pool->lock, flags);
+}
+
/*
* Rather than calling set_pool_mode directly, use these which describe the
* reason for mode degradation.
*/
+static void out_of_data_space(struct pool *pool)
+{
+ DMERR_LIMIT("%s: no free data space available.",
+ dm_device_name(pool->pool_md));
+ set_no_free_space(pool);
+ set_pool_mode(pool, PM_READ_ONLY);
+}
+
static void metadata_operation_failed(struct pool *pool, const char *op, int r)
{
+ dm_block_t free_blocks;
+
DMERR_LIMIT("%s: metadata operation '%s' failed: error = %d",
dm_device_name(pool->pool_md), op, r);
+ if (r == -ENOSPC &&
+ !dm_pool_get_free_metadata_block_count(pool->pmd, &free_blocks) &&
+ !free_blocks) {
+ DMERR_LIMIT("%s: no free metadata space available.",
+ dm_device_name(pool->pool_md));
+ set_no_free_space(pool);
+ }
+
set_pool_mode(pool, PM_READ_ONLY);
}