mirror of
git://sourceware.org/git/lvm2.git
synced 2025-01-17 06:04:23 +03:00
dev_manager: enhance dev_manager_info to acquire LV segment status if requested, add lv_info_with_seg_status fn
This commit is contained in:
parent
7f90ad84c1
commit
a2c1024f6a
@ -617,17 +617,12 @@ int target_present(struct cmd_context *cmd, const char *target_name,
|
||||
return target_version(target_name, &maj, &min, &patchlevel);
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns 1 if info structure populated, else 0 on failure.
|
||||
* When lvinfo* is NULL, it returns 1 if the device is locally active, 0 otherwise.
|
||||
*/
|
||||
int lv_info(struct cmd_context *cmd, const struct logical_volume *lv, int use_layer,
|
||||
struct lvinfo *info, int with_open_count, int with_read_ahead)
|
||||
static int _lv_info(struct cmd_context *cmd, const struct logical_volume *lv,
|
||||
int use_layer, struct lvinfo *info, struct lv_seg_status *seg_status,
|
||||
int with_open_count, int with_read_ahead)
|
||||
{
|
||||
struct dm_info dminfo;
|
||||
|
||||
if (!activation())
|
||||
return 0;
|
||||
/*
|
||||
* If open_count info is requested and we have to be sure our own udev
|
||||
* transactions are finished
|
||||
@ -648,7 +643,8 @@ int lv_info(struct cmd_context *cmd, const struct logical_volume *lv, int use_la
|
||||
if (!dev_manager_info(cmd->mem, lv,
|
||||
(use_layer) ? lv_layer(lv) : NULL,
|
||||
with_open_count, with_read_ahead,
|
||||
&dminfo, (info) ? &info->read_ahead : NULL))
|
||||
&dminfo, (info) ? &info->read_ahead : NULL,
|
||||
seg_status))
|
||||
return_0;
|
||||
|
||||
if (!info)
|
||||
@ -666,6 +662,19 @@ int lv_info(struct cmd_context *cmd, const struct logical_volume *lv, int use_la
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns 1 if info structure populated, else 0 on failure.
|
||||
* When lvinfo* is NULL, it returns 1 if the device is locally active, 0 otherwise.
|
||||
*/
|
||||
int lv_info(struct cmd_context *cmd, const struct logical_volume *lv, int use_layer,
|
||||
struct lvinfo *info, int with_open_count, int with_read_ahead)
|
||||
{
|
||||
if (!activation())
|
||||
return 0;
|
||||
|
||||
return _lv_info(cmd, lv, use_layer, info, NULL, with_open_count, with_read_ahead);
|
||||
}
|
||||
|
||||
int lv_info_by_lvid(struct cmd_context *cmd, const char *lvid_s, int use_layer,
|
||||
struct lvinfo *info, int with_open_count, int with_read_ahead)
|
||||
{
|
||||
@ -681,6 +690,21 @@ int lv_info_by_lvid(struct cmd_context *cmd, const char *lvid_s, int use_layer,
|
||||
return r;
|
||||
}
|
||||
|
||||
int lv_info_with_seg_status(struct cmd_context *cmd, const struct logical_volume *lv,
|
||||
const struct lv_segment *lv_seg, int use_layer,
|
||||
struct lv_with_info_and_seg_status *lvdm,
|
||||
int with_open_count, int with_read_ahead)
|
||||
{
|
||||
if (!activation())
|
||||
return 0;
|
||||
|
||||
if (!_lv_info(cmd, lv, use_layer, lvdm->info, lvdm->seg_status,
|
||||
with_open_count, with_read_ahead))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
#define OPEN_COUNT_CHECK_RETRIES 25
|
||||
#define OPEN_COUNT_CHECK_USLEEP_DELAY 200000
|
||||
|
||||
|
@ -118,6 +118,11 @@ int lv_info(struct cmd_context *cmd, const struct logical_volume *lv, int use_la
|
||||
int lv_info_by_lvid(struct cmd_context *cmd, const char *lvid_s, int use_layer,
|
||||
struct lvinfo *info, int with_open_count, int with_read_ahead);
|
||||
|
||||
int lv_info_with_seg_status(struct cmd_context *cmd, const struct logical_volume *lv,
|
||||
const struct lv_segment *lv_seg, int use_layer,
|
||||
struct lv_with_info_and_seg_status *lvdm,
|
||||
int with_open_count, int with_read_ahead);
|
||||
|
||||
int lv_check_not_in_use(const struct logical_volume *lv);
|
||||
|
||||
/*
|
||||
|
@ -106,32 +106,122 @@ static struct dm_task *_setup_task(const char *name, const char *uuid,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int _info_run(const char *name, const char *dlid, struct dm_info *info,
|
||||
uint32_t *read_ahead, int mknodes, int with_open_count,
|
||||
int with_read_ahead, uint32_t major, uint32_t minor)
|
||||
static int _get_segment_status_from_target_params(const char *target_name,
|
||||
const char *params,
|
||||
struct lv_seg_status *seg_status)
|
||||
{
|
||||
struct segment_type *segtype;
|
||||
|
||||
/* FIXME: linear is also represented as striped with stripe count 1.
|
||||
We're not reporting linear or striped status anyway, so
|
||||
just skip the error here till this is properly resolved.*/
|
||||
if (!strcmp(target_name, "linear") || !strcmp(target_name, "striped"))
|
||||
return 1;
|
||||
|
||||
segtype = get_segtype_from_string(seg_status->seg->lv->vg->cmd, target_name);
|
||||
|
||||
if (segtype != seg_status->seg->segtype) {
|
||||
log_error(INTERNAL_ERROR "_get_segment_status_from_target_params: "
|
||||
"segment type %s found does not match expected segment type %s",
|
||||
segtype->name, seg_status->seg->segtype->name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!strcmp(segtype->name, "cache")) {
|
||||
if (!dm_get_status_cache(seg_status->mem, params,
|
||||
(struct dm_status_cache **) &seg_status->status))
|
||||
return_0;
|
||||
seg_status->type = SEG_STATUS_CACHE;
|
||||
} else if (!strcmp(segtype->name, "raid")) {
|
||||
if (!dm_get_status_raid(seg_status->mem, params,
|
||||
(struct dm_status_raid **) &seg_status->status))
|
||||
return_0;
|
||||
seg_status->type = SEG_STATUS_RAID;
|
||||
} else if (!strcmp(segtype->name, "thin")) {
|
||||
if (!dm_get_status_thin(seg_status->mem, params,
|
||||
(struct dm_status_thin **) &seg_status->status))
|
||||
return_0;
|
||||
seg_status->type = SEG_STATUS_THIN;
|
||||
} else if (!strcmp(segtype->name, "thin-pool")) {
|
||||
if (!dm_get_status_thin_pool(seg_status->mem, params,
|
||||
(struct dm_status_thin_pool **) &seg_status->status))
|
||||
return_0;
|
||||
seg_status->type = SEG_STATUS_THIN_POOL;
|
||||
} else if (!strcmp(segtype->name, "snapshot")) {
|
||||
if (!dm_get_status_snapshot(seg_status->mem, params,
|
||||
(struct dm_status_snapshot **) &seg_status->status))
|
||||
return_0;
|
||||
seg_status->type = SEG_STATUS_SNAPSHOT;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
typedef enum {
|
||||
INFO, /* DM_DEVICE_INFO ioctl */
|
||||
STATUS, /* DM_DEVICE_STATUS ioctl */
|
||||
MKNODES
|
||||
} info_type_t;
|
||||
|
||||
static int _info_run(info_type_t type, const char *name, const char *dlid,
|
||||
struct dm_info *dminfo, uint32_t *read_ahead,
|
||||
struct lv_seg_status *seg_status,
|
||||
int with_open_count, int with_read_ahead,
|
||||
uint32_t major, uint32_t minor)
|
||||
{
|
||||
int r = 0;
|
||||
struct dm_task *dmt;
|
||||
int dmtask;
|
||||
void *target = NULL;
|
||||
uint64_t target_start, target_length;
|
||||
char *target_name, *target_params, *params_to_process = NULL;
|
||||
uint32_t extent_size;
|
||||
|
||||
dmtask = mknodes ? DM_DEVICE_MKNODES : DM_DEVICE_INFO;
|
||||
switch (type) {
|
||||
case INFO:
|
||||
dmtask = DM_DEVICE_INFO;
|
||||
break;
|
||||
case STATUS:
|
||||
dmtask = DM_DEVICE_STATUS;
|
||||
break;
|
||||
case MKNODES:
|
||||
dmtask = DM_DEVICE_MKNODES;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!(dmt = _setup_task(mknodes ? name : NULL, dlid, 0, dmtask, major, minor,
|
||||
with_open_count)))
|
||||
if (!(dmt = _setup_task(type != MKNODES ? name : NULL, dlid, 0, dmtask,
|
||||
major, minor, with_open_count)))
|
||||
return_0;
|
||||
|
||||
if (!dm_task_run(dmt))
|
||||
goto_out;
|
||||
|
||||
if (!dm_task_get_info(dmt, info))
|
||||
if (!dm_task_get_info(dmt, dminfo))
|
||||
goto_out;
|
||||
|
||||
if (with_read_ahead && info->exists) {
|
||||
if (with_read_ahead && dminfo->exists) {
|
||||
if (!dm_task_get_read_ahead(dmt, read_ahead))
|
||||
goto_out;
|
||||
} else if (read_ahead)
|
||||
*read_ahead = DM_READ_AHEAD_NONE;
|
||||
|
||||
if (type == STATUS) {
|
||||
extent_size = seg_status->seg->lv->vg->extent_size;
|
||||
do {
|
||||
target = dm_get_next_target(dmt, target, &target_start,
|
||||
&target_length, &target_name, &target_params);
|
||||
if ((seg_status->seg->le * extent_size == target_start) &&
|
||||
(seg_status->seg->len * extent_size == target_length)) {
|
||||
params_to_process = target_params;
|
||||
break;
|
||||
}
|
||||
} while (target);
|
||||
|
||||
if (params_to_process &&
|
||||
!_get_segment_status_from_target_params(target_name, params_to_process, seg_status))
|
||||
goto_out;
|
||||
}
|
||||
|
||||
r = 1;
|
||||
|
||||
out:
|
||||
@ -476,7 +566,8 @@ int device_is_usable(struct device *dev, struct dev_usable_check_params check)
|
||||
}
|
||||
|
||||
static int _info(const char *dlid, int with_open_count, int with_read_ahead,
|
||||
struct dm_info *info, uint32_t *read_ahead)
|
||||
struct dm_info *dminfo, uint32_t *read_ahead,
|
||||
struct lv_seg_status *seg_status)
|
||||
{
|
||||
int r = 0;
|
||||
char old_style_dlid[sizeof(UUID_PREFIX) + 2 * ID_LEN];
|
||||
@ -484,8 +575,8 @@ static int _info(const char *dlid, int with_open_count, int with_read_ahead,
|
||||
unsigned i = 0;
|
||||
|
||||
/* Check for dlid */
|
||||
if ((r = _info_run(NULL, dlid, info, read_ahead, 0, with_open_count,
|
||||
with_read_ahead, 0, 0)) && info->exists)
|
||||
if ((r = _info_run(seg_status ? STATUS : INFO, NULL, dlid, dminfo, read_ahead,
|
||||
seg_status, with_open_count, with_read_ahead, 0, 0)) && dminfo->exists)
|
||||
return 1;
|
||||
|
||||
/* Check for original version of dlid before the suffixes got added in 2.02.106 */
|
||||
@ -496,16 +587,17 @@ static int _info(const char *dlid, int with_open_count, int with_read_ahead,
|
||||
|
||||
(void) strncpy(old_style_dlid, dlid, sizeof(old_style_dlid));
|
||||
old_style_dlid[sizeof(old_style_dlid) - 1] = '\0';
|
||||
if ((r = _info_run(NULL, old_style_dlid, info, read_ahead, 0, with_open_count,
|
||||
with_read_ahead, 0, 0)) && info->exists)
|
||||
if ((r = _info_run(seg_status ? STATUS : INFO, NULL, old_style_dlid, dminfo,
|
||||
read_ahead, seg_status, with_open_count,
|
||||
with_read_ahead, 0, 0)) && dminfo->exists)
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check for dlid before UUID_PREFIX was added */
|
||||
if ((r = _info_run(NULL, dlid + sizeof(UUID_PREFIX) - 1, info,
|
||||
read_ahead, 0, with_open_count,
|
||||
with_read_ahead, 0, 0)) && info->exists)
|
||||
if ((r = _info_run(seg_status ? STATUS : INFO, NULL, dlid + sizeof(UUID_PREFIX) - 1,
|
||||
dminfo, read_ahead, seg_status, with_open_count,
|
||||
with_read_ahead, 0, 0)) && dminfo->exists)
|
||||
return 1;
|
||||
|
||||
return r;
|
||||
@ -513,13 +605,14 @@ static int _info(const char *dlid, int with_open_count, int with_read_ahead,
|
||||
|
||||
static int _info_by_dev(uint32_t major, uint32_t minor, struct dm_info *info)
|
||||
{
|
||||
return _info_run(NULL, NULL, info, NULL, 0, 0, 0, major, minor);
|
||||
return _info_run(INFO, NULL, NULL, info, NULL, 0, 0, 0, major, minor);
|
||||
}
|
||||
|
||||
int dev_manager_info(struct dm_pool *mem, const struct logical_volume *lv,
|
||||
const char *layer,
|
||||
int with_open_count, int with_read_ahead,
|
||||
struct dm_info *info, uint32_t *read_ahead)
|
||||
struct dm_info *dminfo, uint32_t *read_ahead,
|
||||
struct lv_seg_status *seg_status)
|
||||
{
|
||||
char *dlid, *name;
|
||||
int r;
|
||||
@ -536,7 +629,8 @@ int dev_manager_info(struct dm_pool *mem, const struct logical_volume *lv,
|
||||
}
|
||||
|
||||
log_debug_activation("Getting device info for %s [%s]", name, dlid);
|
||||
r = _info(dlid, with_open_count, with_read_ahead, info, read_ahead);
|
||||
r = _info(dlid, with_open_count, with_read_ahead,
|
||||
dminfo, read_ahead, seg_status);
|
||||
out:
|
||||
dm_pool_free(mem, name);
|
||||
|
||||
@ -1447,7 +1541,7 @@ int dev_manager_mknodes(const struct logical_volume *lv)
|
||||
if (!(name = dm_build_dm_name(lv->vg->cmd->mem, lv->vg->name, lv->name, NULL)))
|
||||
return_0;
|
||||
|
||||
if ((r = _info_run(name, NULL, &dminfo, NULL, 1, 0, 0, 0, 0))) {
|
||||
if ((r = _info_run(MKNODES, name, NULL, &dminfo, NULL, NULL, 0, 0, 0, 0))) {
|
||||
if (dminfo.exists) {
|
||||
if (lv_is_visible(lv))
|
||||
r = _dev_manager_lv_mknodes(lv);
|
||||
@ -1589,7 +1683,7 @@ static int _add_dev_to_dtree(struct dev_manager *dm, struct dm_tree *dtree,
|
||||
return_0;
|
||||
|
||||
log_debug_activation("Getting device info for %s [%s]", name, dlid);
|
||||
if (!_info(dlid, 1, 0, &info, NULL)) {
|
||||
if (!_info(dlid, 1, 0, &info, NULL, NULL)) {
|
||||
log_error("Failed to get info for %s [%s].", name, dlid);
|
||||
return 0;
|
||||
}
|
||||
@ -2078,7 +2172,7 @@ static char *_add_error_device(struct dev_manager *dm, struct dm_tree *dtree,
|
||||
return_NULL;
|
||||
|
||||
log_debug_activation("Getting device info for %s [%s]", name, dlid);
|
||||
if (!_info(dlid, 1, 0, &info, NULL)) {
|
||||
if (!_info(dlid, 1, 0, &info, NULL, NULL)) {
|
||||
log_error("Failed to get info for %s [%s].", name, dlid);
|
||||
return 0;
|
||||
}
|
||||
|
@ -25,6 +25,7 @@ struct cmd_context;
|
||||
struct dev_manager;
|
||||
struct dm_info;
|
||||
struct device;
|
||||
struct lv_seg_status;
|
||||
|
||||
int read_only_lv(const struct logical_volume *lv, const struct lv_activate_opts *laopts);
|
||||
|
||||
@ -47,7 +48,8 @@ void dev_manager_exit(void);
|
||||
int dev_manager_info(struct dm_pool *mem, const struct logical_volume *lv,
|
||||
const char *layer,
|
||||
int with_open_count, int with_read_ahead,
|
||||
struct dm_info *info, uint32_t *read_ahead);
|
||||
struct dm_info *dminfo, uint32_t *read_ahead,
|
||||
struct lv_seg_status *seg_status);
|
||||
int dev_manager_snapshot_percent(struct dev_manager *dm,
|
||||
const struct logical_volume *lv,
|
||||
dm_percent_t *percent);
|
||||
|
@ -59,6 +59,8 @@ static void _get_lv_info_for_report(struct cmd_context *cmd,
|
||||
static void _get_lv_info_with_segment_status_for_report(struct cmd_context *cmd,
|
||||
struct lv_with_info_and_seg_status *lvdm)
|
||||
{
|
||||
if (!lv_info_with_seg_status(cmd, lvdm->seg_status->seg->lv, lvdm->seg_status->seg, 0, lvdm, 1, 1))
|
||||
lvdm->info->exists = 0;
|
||||
}
|
||||
|
||||
static int _lvs_with_info_single(struct cmd_context *cmd, struct logical_volume *lv,
|
||||
|
Loading…
x
Reference in New Issue
Block a user