1
0
mirror of git://sourceware.org/git/lvm2.git synced 2024-12-21 13:34:40 +03:00

cache: check for cache fail during flush

Just WARN if the cache can't be flushed because it's failed.
This commit is contained in:
Zdenek Kabelac 2016-03-10 17:56:43 +01:00
parent 569ba79abf
commit 5c415afd85
5 changed files with 52 additions and 13 deletions

View File

@ -1,5 +1,6 @@
Version 2.02.146 -
=================================
Use new cache status info and skip flushing for failed cache.
Support --uncache with missing PVs.
Tidy report field names, headings and widths.
Add vgscan --notifydbus to send a dbus notification.

View File

@ -1334,12 +1334,18 @@ int dev_manager_cache_status(struct dev_manager *dm,
c = (*status)->cache;
(*status)->mem = dm->mem; /* User has to destroy this mem pool later */
(*status)->data_usage = dm_make_percent(c->used_blocks,
c->total_blocks);
(*status)->metadata_usage = dm_make_percent(c->metadata_used_blocks,
c->metadata_total_blocks);
(*status)->dirty_usage = dm_make_percent(c->dirty_blocks,
c->used_blocks);
if (c->fail || c->error) {
(*status)->data_usage =
(*status)->metadata_usage =
(*status)->dirty_usage = DM_PERCENT_INVALID;
} else {
(*status)->data_usage = dm_make_percent(c->used_blocks,
c->total_blocks);
(*status)->metadata_usage = dm_make_percent(c->metadata_used_blocks,
c->metadata_total_blocks);
(*status)->dirty_usage = dm_make_percent(c->dirty_blocks,
c->used_blocks);
}
r = 1;
out:
dm_task_destroy(dmt);

View File

@ -359,10 +359,16 @@ int lv_cache_remove(struct logical_volume *cache_lv)
*/
if (!lv_cache_status(cache_lv, &status))
return_0;
dirty_blocks = status->cache->dirty_blocks;
if (!(status->cache->feature_flags & DM_CACHE_FEATURE_WRITETHROUGH))
dirty_blocks++; /* Not writethrough - always dirty */
is_cleaner = !strcmp(status->cache->policy_name, "cleaner");
if (!status->cache->fail) {
is_cleaner = !strcmp(status->cache->policy_name, "cleaner");
dirty_blocks = status->cache->dirty_blocks;
if (!(status->cache->feature_flags & DM_CACHE_FEATURE_WRITETHROUGH))
dirty_blocks++; /* Not writethrough - always dirty */
} else {
log_warn("WARNING: Skippping flush for failed cache.");
is_cleaner = 0;
dirty_blocks = 0;
}
dm_pool_destroy(status->mem);
if (dirty_blocks && !is_cleaner) {
@ -378,6 +384,10 @@ int lv_cache_remove(struct logical_volume *cache_lv)
while (dirty_blocks) {
if (!lv_cache_status(cache_lv, &status))
return_0;
if (status->cache->fail) {
log_warn("WARNING: Flushing of failing cache skipped.");
break;
}
dirty_blocks = status->cache->dirty_blocks;
dm_pool_destroy(status->mem);
if (dirty_blocks) {

View File

@ -1137,10 +1137,12 @@ char *lv_attr_dup_with_info_and_seg_status(struct dm_pool *mem, const struct lv_
}
}
/* 'c' when thin-pool active with needs_check flag
/* 'c' when cache/thin-pool is active with needs_check flag
* 'C' for suspend */
if (lv_is_thin_pool(lv) &&
lvdm->seg_status.thin_pool->needs_check)
if ((lv_is_thin_pool(lv) &&
lvdm->seg_status.thin_pool->needs_check) ||
(lv_is_cache(lv) &&
lvdm->seg_status.cache->needs_check))
repstr[4] = lvdm->info.suspended ? 'C' : 'c';
/*
@ -1194,6 +1196,14 @@ char *lv_attr_dup_with_info_and_seg_status(struct dm_pool *mem, const struct lv_
repstr[8] = 'm'; /* RAID has 'm'ismatches */
} else if (lv->status & LV_WRITEMOSTLY)
repstr[8] = 'w'; /* sub-LV has 'w'ritemostly */
} else if (lv_is_cache(lv) &&
(lvdm->seg_status.type != SEG_STATUS_NONE)) {
if (lvdm->seg_status.type == SEG_STATUS_UNKNOWN)
repstr[8] = 'X'; /* Unknown */
else if (lvdm->seg_status.cache->fail)
repstr[8] = 'F';
else if (lvdm->seg_status.cache->read_only)
repstr[8] = 'M';
} else if (lv_is_thin_pool(lv) &&
(lvdm->seg_status.type != SEG_STATUS_NONE)) {
if (lvdm->seg_status.type == SEG_STATUS_UNKNOWN)

View File

@ -3487,6 +3487,14 @@ static int _lvhealthstatus_disp(struct dm_report *rh, struct dm_pool *mem,
health = "mismatches exist";
} else if (lv->status & LV_WRITEMOSTLY)
health = "writemostly";
} else if (lv_is_cache(lv) && (lvdm->seg_status.type != SEG_STATUS_NONE)) {
if (lvdm->seg_status.type != SEG_STATUS_CACHE)
return _field_set_value(field, GET_FIRST_RESERVED_NAME(health_undef),
GET_FIELD_RESERVED_VALUE(health_undef));
else if (lvdm->seg_status.cache->fail)
health = "failed";
else if (lvdm->seg_status.cache->read_only)
health = "metadata_read_only";
} else if (lv_is_thin_pool(lv) && (lvdm->seg_status.type != SEG_STATUS_NONE)) {
if (lvdm->seg_status.type != SEG_STATUS_THIN_POOL)
return _field_set_value(field, GET_FIRST_RESERVED_NAME(health_undef),
@ -3512,6 +3520,10 @@ static int _lvcheckneeded_disp(struct dm_report *rh, struct dm_pool *mem,
return _binary_disp(rh, mem, field, lvdm->seg_status.thin_pool->needs_check,
GET_FIRST_RESERVED_NAME(lv_check_needed_y), private);
if (lv_is_cache(lvdm->lv) && lvdm->seg_status.type == SEG_STATUS_CACHE)
return _binary_disp(rh, mem, field, lvdm->seg_status.cache->needs_check,
GET_FIRST_RESERVED_NAME(lv_check_needed_y), private);
return _binary_undef_disp(rh, mem, field, private);
}