1
0
mirror of git://sourceware.org/git/lvm2.git synced 2025-01-03 05:18:29 +03:00

dev_manager: add lv_raid_status

Just like with other segtype use this function to get whole
raid status info available per a single ioctl call.

Also it nicely simplifies read of percentage info about
in_sync portion of raid volume.

TODO: drop use of other calls then lv_raid_status call,
since all such calls could already use status - so it just
adds unnecessary duplication.
This commit is contained in:
Zdenek Kabelac 2021-03-17 09:50:09 +01:00
parent e5a600860c
commit a9b4acd511
5 changed files with 88 additions and 73 deletions

View File

@ -972,35 +972,28 @@ int lv_raid_percent(const struct logical_volume *lv, dm_percent_t *percent)
int lv_raid_data_offset(const struct logical_volume *lv, uint64_t *data_offset) int lv_raid_data_offset(const struct logical_volume *lv, uint64_t *data_offset)
{ {
int r; struct lv_status_raid *raid_status;
struct dev_manager *dm;
struct dm_status_raid *status;
if (!lv_info(lv->vg->cmd, lv, 0, NULL, 0, 0)) if (!lv_info(lv->vg->cmd, lv, 0, NULL, 0, 0))
return 0; return 0;
log_debug_activation("Checking raid data offset and dev sectors for LV %s/%s", log_debug_activation("Checking raid data offset and dev sectors for LV %s/%s",
lv->vg->name, lv->name); lv->vg->name, lv->name);
if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name, 1)))
if (!lv_raid_status(lv, &raid_status))
return_0; return_0;
if (!(r = dev_manager_raid_status(dm, lv, &status))) { *data_offset = raid_status->raid->data_offset;
dev_manager_destroy(dm);
return_0;
}
*data_offset = status->data_offset; dm_pool_destroy(raid_status->mem);
dev_manager_destroy(dm); return 1;
return r;
} }
int lv_raid_dev_health(const struct logical_volume *lv, char **dev_health) int lv_raid_dev_health(const struct logical_volume *lv, char **dev_health)
{ {
int r; int r = 1;
struct dev_manager *dm; struct lv_status_raid *raid_status;
struct dm_status_raid *status;
*dev_health = NULL; *dev_health = NULL;
@ -1010,25 +1003,23 @@ int lv_raid_dev_health(const struct logical_volume *lv, char **dev_health)
log_debug_activation("Checking raid device health for LV %s.", log_debug_activation("Checking raid device health for LV %s.",
display_lvname(lv)); display_lvname(lv));
if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name, 1))) if (!lv_raid_status(lv, &raid_status))
return_0; return_0;
if (!(r = dev_manager_raid_status(dm, lv, &status)) || if (!(*dev_health = dm_pool_strdup(lv->vg->cmd->mem,
!(*dev_health = dm_pool_strdup(lv->vg->cmd->mem, raid_status->raid->dev_health))) {
status->dev_health))) { stack;
dev_manager_destroy(dm); r = 0;
return_0;
} }
dev_manager_destroy(dm); dm_pool_destroy(raid_status->mem);
return r; return r;
} }
int lv_raid_dev_count(const struct logical_volume *lv, uint32_t *dev_cnt) int lv_raid_dev_count(const struct logical_volume *lv, uint32_t *dev_cnt)
{ {
struct dev_manager *dm; struct lv_status_raid *raid_status;
struct dm_status_raid *status;
*dev_cnt = 0; *dev_cnt = 0;
@ -1037,24 +1028,20 @@ int lv_raid_dev_count(const struct logical_volume *lv, uint32_t *dev_cnt)
log_debug_activation("Checking raid device count for LV %s/%s", log_debug_activation("Checking raid device count for LV %s/%s",
lv->vg->name, lv->name); lv->vg->name, lv->name);
if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name, 1)))
if (!lv_raid_status(lv, &raid_status))
return_0; return_0;
if (!dev_manager_raid_status(dm, lv, &status)) { *dev_cnt = raid_status->raid->dev_count;
dev_manager_destroy(dm);
return_0;
}
*dev_cnt = status->dev_count;
dev_manager_destroy(dm); dm_pool_destroy(raid_status->mem);
return 1; return 1;
} }
int lv_raid_mismatch_count(const struct logical_volume *lv, uint64_t *cnt) int lv_raid_mismatch_count(const struct logical_volume *lv, uint64_t *cnt)
{ {
struct dev_manager *dm; struct lv_status_raid *raid_status;
struct dm_status_raid *status;
*cnt = 0; *cnt = 0;
@ -1064,25 +1051,20 @@ int lv_raid_mismatch_count(const struct logical_volume *lv, uint64_t *cnt)
log_debug_activation("Checking raid mismatch count for LV %s.", log_debug_activation("Checking raid mismatch count for LV %s.",
display_lvname(lv)); display_lvname(lv));
if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name, 1))) if (!lv_raid_status(lv, &raid_status))
return_0; return_0;
if (!dev_manager_raid_status(dm, lv, &status)) { *cnt = raid_status->raid->mismatch_count;
dev_manager_destroy(dm);
return_0;
}
*cnt = status->mismatch_count;
dev_manager_destroy(dm); dm_pool_destroy(raid_status->mem);
return 1; return 1;
} }
int lv_raid_sync_action(const struct logical_volume *lv, char **sync_action) int lv_raid_sync_action(const struct logical_volume *lv, char **sync_action)
{ {
struct dev_manager *dm; struct lv_status_raid *raid_status;
struct dm_status_raid *status; int r = 1;
char *action;
*sync_action = NULL; *sync_action = NULL;
@ -1092,30 +1074,27 @@ int lv_raid_sync_action(const struct logical_volume *lv, char **sync_action)
log_debug_activation("Checking raid sync_action for LV %s.", log_debug_activation("Checking raid sync_action for LV %s.",
display_lvname(lv)); display_lvname(lv));
if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name, 1))) if (!lv_raid_status(lv, &raid_status))
return_0; return_0;
/* status->sync_action can be NULL if dm-raid version < 1.5.0 */ /* status->sync_action can be NULL if dm-raid version < 1.5.0 */
if (!dev_manager_raid_status(dm, lv, &status) || if (!raid_status->raid->sync_action ||
!status->sync_action || !(*sync_action = dm_pool_strdup(lv->vg->cmd->mem,
!(action = dm_pool_strdup(lv->vg->cmd->mem, raid_status->raid->sync_action))) {
status->sync_action))) { stack;
dev_manager_destroy(dm); r = 0;
return_0;
} }
*sync_action = action; dm_pool_destroy(raid_status->mem);
dev_manager_destroy(dm); return r;
return 1;
} }
int lv_raid_message(const struct logical_volume *lv, const char *msg) int lv_raid_message(const struct logical_volume *lv, const char *msg)
{ {
struct lv_status_raid *raid_status;
struct dev_manager *dm = NULL;
int r = 0; int r = 0;
struct dev_manager *dm;
struct dm_status_raid *status;
if (!seg_is_raid(first_seg(lv))) { if (!seg_is_raid(first_seg(lv))) {
/* /*
@ -1140,16 +1119,10 @@ int lv_raid_message(const struct logical_volume *lv, const char *msg)
return 0; return 0;
} }
if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name, 1))) if (!lv_raid_status(lv, &raid_status))
return_0; return_0;
if (!(r = dev_manager_raid_status(dm, lv, &status))) { if (!raid_status->raid->sync_action) {
log_error("Failed to retrieve status of %s.",
display_lvname(lv));
goto out;
}
if (!status->sync_action) {
log_error("Kernel driver does not support this action: %s", msg); log_error("Kernel driver does not support this action: %s", msg);
goto out; goto out;
} }
@ -1171,19 +1144,43 @@ int lv_raid_message(const struct logical_volume *lv, const char *msg)
log_error("\"%s\" is not a supported sync operation.", msg); log_error("\"%s\" is not a supported sync operation.", msg);
goto out; goto out;
} }
if (strcmp(status->sync_action, "idle")) { if (strcmp(raid_status->raid->sync_action, "idle")) {
log_error("%s state is currently \"%s\". Unable to switch to \"%s\".", log_error("%s state is currently \"%s\". Unable to switch to \"%s\".",
display_lvname(lv), status->sync_action, msg); display_lvname(lv), raid_status->raid->sync_action, msg);
goto out; goto out;
} }
if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name, 1)))
return_0;
r = dev_manager_raid_message(dm, lv, msg); r = dev_manager_raid_message(dm, lv, msg);
out: out:
if (dm)
dev_manager_destroy(dm); dev_manager_destroy(dm);
dm_pool_destroy(raid_status->mem);
return r; return r;
} }
int lv_raid_status(const struct logical_volume *lv, struct lv_status_raid **status)
{
struct dev_manager *dm;
int exists;
if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name, 1)))
return_0;
if (!dev_manager_raid_status(dm, lv, status, &exists)) {
dev_manager_destroy(dm);
if (exists)
stack;
return 0;
}
/* User has to call dm_pool_destroy(status->mem)! */
return 1;
}
int lv_writecache_message(const struct logical_volume *lv, const char *msg) int lv_writecache_message(const struct logical_volume *lv, const char *msg)
{ {
int r = 0; int r = 0;

View File

@ -188,6 +188,7 @@ int lv_raid_dev_health(const struct logical_volume *lv, char **dev_health);
int lv_raid_mismatch_count(const struct logical_volume *lv, uint64_t *cnt); int lv_raid_mismatch_count(const struct logical_volume *lv, uint64_t *cnt);
int lv_raid_sync_action(const struct logical_volume *lv, char **sync_action); int lv_raid_sync_action(const struct logical_volume *lv, char **sync_action);
int lv_raid_message(const struct logical_volume *lv, const char *msg); int lv_raid_message(const struct logical_volume *lv, const char *msg);
int lv_raid_status(const struct logical_volume *lv, struct lv_status_raid **status);
int lv_writecache_message(const struct logical_volume *lv, const char *msg); int lv_writecache_message(const struct logical_volume *lv, const char *msg);
int lv_cache_status(const struct logical_volume *cache_lv, int lv_cache_status(const struct logical_volume *cache_lv,
struct lv_status_cache **status); struct lv_status_cache **status);

View File

@ -1437,7 +1437,7 @@ int dev_manager_mirror_percent(struct dev_manager *dm,
int dev_manager_raid_status(struct dev_manager *dm, int dev_manager_raid_status(struct dev_manager *dm,
const struct logical_volume *lv, const struct logical_volume *lv,
struct dm_status_raid **status) struct lv_status_raid **status, int *exists)
{ {
int r = 0; int r = 0;
const char *dlid; const char *dlid;
@ -1447,6 +1447,11 @@ int dev_manager_raid_status(struct dev_manager *dm,
char *type = NULL; char *type = NULL;
char *params = NULL; char *params = NULL;
const char *layer = lv_layer(lv); const char *layer = lv_layer(lv);
struct dm_status_raid *sr;
*exists = -1;
if (!(*status = dm_pool_zalloc(dm->mem, sizeof(struct lv_status_cache))))
return_0;
if (!(dlid = build_dm_uuid(dm->mem, lv, layer))) if (!(dlid = build_dm_uuid(dm->mem, lv, layer)))
return_0; return_0;
@ -1454,8 +1459,11 @@ int dev_manager_raid_status(struct dev_manager *dm,
if (!(dmt = _setup_task_run(DM_DEVICE_STATUS, &info, NULL, dlid, 0, 0, 0, 0, 0, 0))) if (!(dmt = _setup_task_run(DM_DEVICE_STATUS, &info, NULL, dlid, 0, 0, 0, 0, 0, 0)))
return_0; return_0;
if (!info.exists) if (!(*exists = info.exists))
goto_out; goto out;
log_debug_activation("Checking raid status for volume %s.",
display_lvname(lv));
dm_get_next_target(dmt, NULL, &start, &length, &type, &params); dm_get_next_target(dmt, NULL, &start, &length, &type, &params);
@ -1467,9 +1475,13 @@ int dev_manager_raid_status(struct dev_manager *dm,
/* FIXME Check there's only one target */ /* FIXME Check there's only one target */
if (!dm_get_status_raid(dm->mem, params, status)) if (!dm_get_status_raid(dm->mem, params, &sr))
goto_out; goto_out;
(*status)->mem = dm->mem; /* User has to destroy this mem pool later */
(*status)->raid = sr;
(*status)->in_sync = dm_make_percent(sr->insync_regions, sr->total_regions);
r = 1; r = 1;
out: out:
dm_task_destroy(dmt); dm_task_destroy(dmt);

View File

@ -59,7 +59,7 @@ int dev_manager_mirror_percent(struct dev_manager *dm,
dm_percent_t *percent, uint32_t *event_nr); dm_percent_t *percent, uint32_t *event_nr);
int dev_manager_raid_status(struct dev_manager *dm, int dev_manager_raid_status(struct dev_manager *dm,
const struct logical_volume *lv, const struct logical_volume *lv,
struct dm_status_raid **status); struct lv_status_raid **status, int *exists);
int dev_manager_raid_message(struct dev_manager *dm, int dev_manager_raid_message(struct dev_manager *dm,
const struct logical_volume *lv, const struct logical_volume *lv,
const char *msg); const char *msg);

View File

@ -1239,6 +1239,11 @@ int collapse_mirrored_lv(struct logical_volume *lv);
int shift_mirror_images(struct lv_segment *mirrored_seg, unsigned mimage); int shift_mirror_images(struct lv_segment *mirrored_seg, unsigned mimage);
/* ++ metadata/raid_manip.c */ /* ++ metadata/raid_manip.c */
struct lv_status_raid {
struct dm_pool *mem;
struct dm_status_raid *raid;
dm_percent_t in_sync;
};
int lv_is_raid_with_tracking(const struct logical_volume *lv); int lv_is_raid_with_tracking(const struct logical_volume *lv);
uint32_t lv_raid_image_count(const struct logical_volume *lv); uint32_t lv_raid_image_count(const struct logical_volume *lv);
int lv_raid_change_image_count(struct logical_volume *lv, int lv_raid_change_image_count(struct logical_volume *lv,