Hi, Here are some patches related to DM_DEVICE_STATUS ioctl handling in dm-thin. ------------------------------------------------------------------ 1. Fix incorrect no_flush flag settings when querying device utilization The parameter lv is NULL when querying thin-pool metadata percent (and also the dlid parameter), thus I use the target_type string instead. diff --git a/lib/activate/dev_manager.c b/lib/activate/dev_manager.c index 8e56b7a..4a96d1e 100644 --- a/lib/activate/dev_manager.c +++ b/lib/activate/dev_manager.c @@ -897,7 +897,8 @@ static int _percent_run(struct dev_manager *dm, const char *name, return_0; /* No freeze on overfilled thin-pool, read existing slightly outdated data */ - if (lv && lv_is_thin_pool(lv) && + if ((segtype = get_segtype_from_string(dm->cmd, target_type)) && + segtype_is_thin_pool(segtype) && !dm_task_no_flush(dmt)) log_warn("Can't set no_flush flag."); /* Non fatal */ @@ -926,7 +927,7 @@ static int _percent_run(struct dev_manager *dm, const char *name, if (!type || !params) continue; - if (!(segtype = get_segtype_from_string(dm->cmd, target_type))) + if (!segtype) continue; if (strcmp(type, target_type)) { ------------------------------------------------------------------ 2. Set no_flush flag when querying device info to avoid freeze Same as 872ea3b98, we should set the no_flush flag in _info_run() to avoid freeze and performance impact. We might need to patch all other functions running DM_DEVICE_STATUS, like device_is_usable(), lv_has_target_type(), etc. diff --git a/lib/activate/dev_manager.c b/lib/activate/dev_manager.c index 4a96d1e..67c476e 100644 --- a/lib/activate/dev_manager.c +++ b/lib/activate/dev_manager.c @@ -212,6 +212,12 @@ static int _info_run(info_type_t type, const char *name, const char *dlid, major, minor, with_open_count))) return_0; + /* No freeze on overfilled thin-pool, read existing slightly outdated data */ + if (type == STATUS && + segtype_is_thin_pool(seg_status->seg->segtype) && + !dm_task_no_flush(dmt)) + log_warn("Can't set no_flush flag."); /* Non fatal */ + if (!dm_task_run(dmt)) goto_out; ------------------------------------------------------------------ 3. Fix _metadatapercent_disp to not to handle thin volumes "lvs vg1/thin_lvol0 -o metadata_percent" should not send ioctls. diff --git a/lib/report/report.c b/lib/report/report.c index 7070092..8ae565e 100644 --- a/lib/report/report.c +++ b/lib/report/report.c @@ -2961,8 +2961,6 @@ static int _metadatapercent_disp(struct dm_report *rh, if (lv_is_thin_pool(lv)) (void) lv_thin_pool_percent(lv, 1, &percent); - else if (lv_is_thin_volume(lv)) - (void) lv_thin_percent(lv, 1, &percent); else if (lv_is_cache(lv) || lv_is_cache_pool(lv)) { if (lv_cache_status(lv, &status)) { percent = status->metadata_usage; ------------------------------------------------------------------ 4. Remove unused parameter from lv_thin_percent diff --git a/lib/activate/activate.c b/lib/activate/activate.c index 2eb24d4..0b8bebf 100644 --- a/lib/activate/activate.c +++ b/lib/activate/activate.c @@ -304,8 +304,7 @@ int lv_thin_pool_percent(const struct logical_volume *lv, int metadata, { return 0; } -int lv_thin_percent(const struct logical_volume *lv, int mapped, - dm_percent_t *percent) +int lv_thin_percent(const struct logical_volume *lv, dm_percent_t *percent) { return 0; } @@ -1124,8 +1123,7 @@ int lv_thin_pool_percent(const struct logical_volume *lv, int metadata, /* * Returns 1 if percent set, else 0 on failure. */ -int lv_thin_percent(const struct logical_volume *lv, - int mapped, dm_percent_t *percent) +int lv_thin_percent(const struct logical_volume *lv, dm_percent_t *percent) { int r; struct dev_manager *dm; @@ -1139,7 +1137,7 @@ int lv_thin_percent(const struct logical_volume *lv, if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name, 1))) return_0; - if (!(r = dev_manager_thin_percent(dm, lv, mapped, percent))) + if (!(r = dev_manager_thin_percent(dm, lv, percent))) stack; dev_manager_destroy(dm); diff --git a/lib/activate/activate.h b/lib/activate/activate.h index 74afb95..c01fedd 100644 --- a/lib/activate/activate.h +++ b/lib/activate/activate.h @@ -175,8 +175,7 @@ int lv_cache_status(const struct logical_volume *lv, struct lv_status_cache **status); int lv_thin_pool_percent(const struct logical_volume *lv, int metadata, dm_percent_t *percent); -int lv_thin_percent(const struct logical_volume *lv, int mapped, - dm_percent_t *percent); +int lv_thin_percent(const struct logical_volume *lv, dm_percent_t *percent); int lv_thin_pool_transaction_id(const struct logical_volume *lv, uint64_t *transaction_id); int lv_thin_device_id(const struct logical_volume *lv, uint32_t *device_id); diff --git a/lib/activate/dev_manager.c b/lib/activate/dev_manager.c index 67c476e..753f188 100644 --- a/lib/activate/dev_manager.c +++ b/lib/activate/dev_manager.c @@ -1428,7 +1428,7 @@ int dev_manager_thin_pool_percent(struct dev_manager *dm, int dev_manager_thin_percent(struct dev_manager *dm, const struct logical_volume *lv, - int mapped, dm_percent_t *percent) + dm_percent_t *percent) { char *name; const char *dlid; @@ -1443,7 +1443,7 @@ int dev_manager_thin_percent(struct dev_manager *dm, log_debug_activation("Getting device status percentage for %s", name); if (!(_percent(dm, name, dlid, "thin", 0, - (mapped) ? NULL : lv, percent, NULL, 1))) + lv, percent, NULL, 1))) return_0; return 1; diff --git a/lib/activate/dev_manager.h b/lib/activate/dev_manager.h index bcfb226..3cf8b90 100644 --- a/lib/activate/dev_manager.h +++ b/lib/activate/dev_manager.h @@ -74,7 +74,7 @@ int dev_manager_thin_pool_percent(struct dev_manager *dm, int metadata, dm_percent_t *percent); int dev_manager_thin_percent(struct dev_manager *dm, const struct logical_volume *lv, - int mapped, dm_percent_t *percent); + dm_percent_t *percent); int dev_manager_thin_device_id(struct dev_manager *dm, const struct logical_volume *lv, uint32_t *device_id); diff --git a/lib/display/display.c b/lib/display/display.c index a6387c6..27d09f0 100644 --- a/lib/display/display.c +++ b/lib/display/display.c @@ -468,7 +468,7 @@ int lvdisplay_full(struct cmd_context *cmd, log_print("LV merging to %s", seg->merge_lv->name); if (inkernel) - thin_active = lv_thin_percent(lv, 0, &thin_percent); + thin_active = lv_thin_percent(lv, &thin_percent); if (lv_is_merging_origin(lv)) log_print("LV merged with %s", find_snapshot(lv)->lv->name); diff --git a/lib/report/properties.c b/lib/report/properties.c index 62c81b9..69e8552 100644 --- a/lib/report/properties.c +++ b/lib/report/properties.c @@ -120,7 +120,7 @@ static dm_percent_t _data_percent(const struct logical_volume *lv) } if (lv_is_thin_volume(lv)) - return lv_thin_percent(lv, 0, &percent) ? percent : DM_PERCENT_INVALID; + return lv_thin_percent(lv, &percent) ? percent : DM_PERCENT_INVALID; return lv_thin_pool_percent(lv, 0, &percent) ? percent : DM_PERCENT_INVALID; } diff --git a/lib/report/report.c b/lib/report/report.c index 8ae565e..9970f7c 100644 --- a/lib/report/report.c +++ b/lib/report/report.c @@ -2939,7 +2939,7 @@ static int _datapercent_disp(struct dm_report *rh, struct dm_pool *mem, else if (lv_is_thin_pool(lv)) (void) lv_thin_pool_percent(lv, 0, &percent); else if (lv_is_thin_volume(lv)) - (void) lv_thin_percent(lv, 0, &percent); + (void) lv_thin_percent(lv, &percent); else if (lv_is_cache(lv) || lv_is_cache_pool(lv)) { if (lv_cache_status(lv, &status)) { percent = status->data_usage; ------------------------------------------------------------------ Beside these patches, I think that the mechanism to obtain lv data utilization should be revised. Given a thin pool vg1/tp1, I hope that the command # lvs vg1/tp1 -o lv_attr,data_percent,metadata_percent should run DM_DEVICE_STATUS ioctl only once. To achieve this, we should calculate the percents in early phase, then cache the calculated percents in struct lv_with_info_and_seg_status, thus the column handlers _datapercent_disp() and _metadatapercent_disp() could obtain the cached percents. The follow is my proposed approach, inspired by lvm-cache's implementation: (1) Declare a new structure for cache percents: struct lv_status_thin_pool { struct dm_pool *mem; struct dm_status_thin_pool *status; dm_percent_t data_usage; dm_percent_t metadata_usage; }; (2) int lv_thin_pool_status(const struct logical_volume *pool_lv, lv_status_thin_pool **status): Allocates lv_status_thin_pool, obtains dm_status_thin_pool by using dev_manager_thin_pool_status(), then calculates data/metadata percents. (3) int dev_manager_thin_pool_status(struct dev_manager *dm, const struct logical_volume *lv, struct dm_status_thin_pool **status, int noflush): Allocates dm_status_thin_pool, run ioctl, then transform the status string to dm_status_thin_pool by using dm_get_status_thin_pool(). (4) Stores lv_status_<segtype> in lv_seg_status: struct lv_seg_status { struct dm_pool *mem; /* input */ const struct lv_segment *seg; /* input */ lv_seg_status_type_t type; /* output */ union { struct lv_status_cache *cache; struct lv_status_raid *raid; struct lv_status_mirror *mirror; // is dm-mirror required? struct lv_status_snapshot *snapshot; struct lv_status_thin *thin; struct lv_status_thin_pool *thin_pool; }; }; (5) Change the colume type of "data_percent" and "metadata_percent" to LVSSTATUS. (6) Also apply this approach to lvdisplay: Now lvdisplay_full() sends DM_DEVICE_STATUS twice (lv_thin_pool_percent() twice) Finally, we could remove segtype_handler::target_percent in all the segtypes. It need some efforts to do the above patches. How do you think about it? Thanks, Ming-Hung Tsai _______________________________________________ linux-lvm mailing list linux-lvm@redhat.com https://www.redhat.com/mailman/listinfo/linux-lvm read the LVM HOW-TO at http://tldp.org/HOWTO/LVM-HOWTO/