main - device_mapper: reduce min_size for flatten
by Zdenek Kabelac
Gitweb: https://sourceware.org/git/?p=lvm2.git;a=commitdiff;h=67790d7e3bcfb202eb4...
Commit: 67790d7e3bcfb202eb42d23ab36dfdfe31713996
Parent: 73bea16c92cf6702a05634d80218297cb953ff36
Author: Zdenek Kabelac <zkabelac(a)redhat.com>
AuthorDate: Sat Feb 27 21:22:41 2021 +0100
Committer: Zdenek Kabelac <zkabelac(a)redhat.com>
CommitterDate: Tue Mar 2 22:57:35 2021 +0100
device_mapper: reduce min_size for flatten
For most ioctl() we do not need to pass so big buffers
and we can reduce amount of zeroed memory blocks.
---
device_mapper/ioctl/libdm-iface.c | 14 +++++++++++++-
1 file changed, 13 insertions(+), 1 deletion(-)
diff --git a/device_mapper/ioctl/libdm-iface.c b/device_mapper/ioctl/libdm-iface.c
index 116fa3dc1..906d84b4e 100644
--- a/device_mapper/ioctl/libdm-iface.c
+++ b/device_mapper/ioctl/libdm-iface.c
@@ -1118,7 +1118,7 @@ static int _add_params(int type)
static struct dm_ioctl *_flatten(struct dm_task *dmt, unsigned repeat_count)
{
- const size_t min_size = 16 * 1024;
+ size_t min_size;
const int (*version)[3];
struct dm_ioctl *dmi;
@@ -1137,6 +1137,18 @@ static struct dm_ioctl *_flatten(struct dm_task *dmt, unsigned repeat_count)
else if (dmt->head)
log_debug_activation(INTERNAL_ERROR "dm '%s' ioctl should not define parameters.",
_cmd_data_v4[dmt->type].name);
+ switch (dmt->type) {
+ case DM_DEVICE_CREATE:
+ case DM_DEVICE_DEPS:
+ case DM_DEVICE_INFO:
+ case DM_DEVICE_LIST:
+ case DM_DEVICE_STATUS:
+ case DM_DEVICE_TABLE:
+ case DM_DEVICE_TARGET_MSG:
+ min_size = 16 * 1024;
+ default:
+ min_size = 2 * 1024;
+ }
if (count && (dmt->sector || dmt->message)) {
log_error("targets and message are incompatible");
3 years, 2 months
main - device_mapper: zero only secure buffers
by Zdenek Kabelac
Gitweb: https://sourceware.org/git/?p=lvm2.git;a=commitdiff;h=73bea16c92cf6702a05...
Commit: 73bea16c92cf6702a05634d80218297cb953ff36
Parent: 00531186fc4ebc3cfeb934c5cb30b54d2f34d30d
Author: Zdenek Kabelac <zkabelac(a)redhat.com>
AuthorDate: Sat Feb 27 17:08:26 2021 +0100
Committer: Zdenek Kabelac <zkabelac(a)redhat.com>
CommitterDate: Tue Mar 2 22:56:32 2021 +0100
device_mapper: zero only secure buffers
Securely erase before free() only dm_tasks marked as secure_data.
TODO: think about also using this for libdm/.
---
device_mapper/ioctl/libdm-iface.c | 10 ++++++++--
1 file changed, 8 insertions(+), 2 deletions(-)
diff --git a/device_mapper/ioctl/libdm-iface.c b/device_mapper/ioctl/libdm-iface.c
index 1140798e6..116fa3dc1 100644
--- a/device_mapper/ioctl/libdm-iface.c
+++ b/device_mapper/ioctl/libdm-iface.c
@@ -493,7 +493,10 @@ static void _dm_task_free_targets(struct dm_task *dmt)
for (t = dmt->head; t; t = n) {
n = t->next;
- _dm_zfree_string(t->params);
+ if (dmt->secure_data)
+ _dm_zfree_string(t->params);
+ else
+ free(t->params);
free(t->type);
free(t);
}
@@ -504,7 +507,10 @@ static void _dm_task_free_targets(struct dm_task *dmt)
void dm_task_destroy(struct dm_task *dmt)
{
_dm_task_free_targets(dmt);
- _dm_zfree_dmi(dmt->dmi.v4);
+ if (dmt->secure_data)
+ _dm_zfree_dmi(dmt->dmi.v4);
+ else
+ free(dmt->dmi.v4);
free(dmt->dev_name);
free(dmt->mangled_dev_name);
free(dmt->newname);
3 years, 2 months
main - label: check only with active device for rescan
by Zdenek Kabelac
Gitweb: https://sourceware.org/git/?p=lvm2.git;a=commitdiff;h=00531186fc4ebc3cfeb...
Commit: 00531186fc4ebc3cfeb934c5cb30b54d2f34d30d
Parent: 56620b903955e245d4a257847f5825bb44d6db1e
Author: Zdenek Kabelac <zkabelac(a)redhat.com>
AuthorDate: Sat Feb 27 21:20:37 2021 +0100
Committer: Zdenek Kabelac <zkabelac(a)redhat.com>
CommitterDate: Tue Mar 2 22:54:40 2021 +0100
label: check only with active device for rescan
When 'lv_info()' is called with &info structure,
the presence of node has to be checked from this structure.
Without this we were needlesly trying to look out 0:0 device.
---
lib/label/label.c | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/lib/label/label.c b/lib/label/label.c
index 318cf4d6c..8cbed7dd8 100644
--- a/lib/label/label.c
+++ b/lib/label/label.c
@@ -1424,12 +1424,12 @@ void label_scan_invalidate_lv(struct cmd_context *cmd, struct logical_volume *lv
struct device *dev;
dev_t devt;
- if (!lv_info(cmd, lv, 0, &lvinfo, 0, 0))
- return;
-
- devt = MKDEV(lvinfo.major, lvinfo.minor);
- if ((dev = dev_cache_get_by_devt(cmd, devt, NULL, NULL)))
- label_scan_invalidate(dev);
+ if (lv_info(cmd, lv, 0, &lvinfo, 0, 0) && lvinfo.exists) {
+ /* FIXME: Still unclear what is it supposed to find */
+ devt = MKDEV(lvinfo.major, lvinfo.minor);
+ if ((dev = dev_cache_get_by_devt(cmd, devt, NULL, NULL)))
+ label_scan_invalidate(dev);
+ }
}
/*
3 years, 2 months
main - toolib: move sigint_caught
by Zdenek Kabelac
Gitweb: https://sourceware.org/git/?p=lvm2.git;a=commitdiff;h=56620b903955e245d4a...
Commit: 56620b903955e245d4a257847f5825bb44d6db1e
Parent: 2a9a3346e74c1327eafb03c44f2579eb6119943f
Author: Zdenek Kabelac <zkabelac(a)redhat.com>
AuthorDate: Sat Feb 27 19:22:11 2021 +0100
Committer: Zdenek Kabelac <zkabelac(a)redhat.com>
CommitterDate: Tue Mar 2 22:54:40 2021 +0100
toolib: move sigint_caught
Move the check for catched signal to the loop front.
Currently not much usable - but we can improve it later.
---
tools/toollib.c | 44 +++++++++++++++++++++++---------------------
1 file changed, 23 insertions(+), 21 deletions(-)
diff --git a/tools/toollib.c b/tools/toollib.c
index 9c026d9e5..67422e3b4 100644
--- a/tools/toollib.c
+++ b/tools/toollib.c
@@ -1407,6 +1407,12 @@ int process_each_label(struct cmd_context *cmd, int argc, char **argv,
if (argc) {
for (; opt < argc; opt++) {
+ if (sigint_caught()) {
+ log_error("Interrupted.");
+ ret_max = ECMD_FAILED;
+ goto out;
+ }
+
if (!(dev = dev_cache_get(cmd, argv[opt], cmd->filter))) {
log_error("Failed to find device "
"\"%s\".", argv[opt]);
@@ -1436,12 +1442,14 @@ int process_each_label(struct cmd_context *cmd, int argc, char **argv,
ret_max = ret;
log_set_report_object_name_and_id(NULL, NULL);
-
- if (sigint_caught())
- break;
}
dm_list_iterate_items(devl, &process_duplicates) {
+ if (sigint_caught()) {
+ log_error("Interrupted.");
+ ret_max = ECMD_FAILED;
+ goto out;
+ }
/*
* remove the existing dev for this pvid from lvmcache
* so that the duplicate dev can replace it.
@@ -1470,9 +1478,6 @@ int process_each_label(struct cmd_context *cmd, int argc, char **argv,
ret_max = ret;
log_set_report_object_name_and_id(NULL, NULL);
-
- if (sigint_caught())
- break;
}
goto out;
@@ -1484,8 +1489,13 @@ int process_each_label(struct cmd_context *cmd, int argc, char **argv,
goto out;
}
- while ((dev = dev_iter_get(cmd, iter)))
- {
+ while ((dev = dev_iter_get(cmd, iter))) {
+ if (sigint_caught()) {
+ log_error("Interrupted.");
+ ret_max = ECMD_FAILED;
+ break;
+ }
+
if (!(label = lvmcache_get_dev_label(dev)))
continue;
@@ -1498,9 +1508,6 @@ int process_each_label(struct cmd_context *cmd, int argc, char **argv,
ret_max = ret;
log_set_report_object_name_and_id(NULL, NULL);
-
- if (sigint_caught())
- break;
}
dev_iter_destroy(iter);
@@ -3064,11 +3071,6 @@ int process_each_lv_in_vg(struct cmd_context *cmd, struct volume_group *vg,
process_lv = process_lv && select_match_lv(cmd, handle, vg, lvl->lv) && _select_matches(handle);
- if (sigint_caught()) {
- ret_max = ECMD_FAILED;
- goto_out;
- }
-
if (!process_lv)
continue;
@@ -3174,6 +3176,11 @@ int process_each_lv_in_vg(struct cmd_context *cmd, struct volume_group *vg,
log_set_report_object_name_and_id(glvl->glv->historical->name, lv_uuid);
+ if (sigint_caught()) {
+ ret_max = ECMD_FAILED;
+ goto_out;
+ }
+
process_lv = process_all;
if (lvargs_supplied &&
@@ -3185,11 +3192,6 @@ int process_each_lv_in_vg(struct cmd_context *cmd, struct volume_group *vg,
process_lv = process_lv && select_match_lv(cmd, handle, vg, lvl->lv) && _select_matches(handle);
- if (sigint_caught()) {
- ret_max = ECMD_FAILED;
- goto_out;
- }
-
if (!process_lv)
continue;
3 years, 2 months
main - archive: support interruption
by Zdenek Kabelac
Gitweb: https://sourceware.org/git/?p=lvm2.git;a=commitdiff;h=2a9a3346e74c1327eaf...
Commit: 2a9a3346e74c1327eafb03c44f2579eb6119943f
Parent: eb1160ee4230e6f37707b19eb5b46d2446257500
Author: Zdenek Kabelac <zkabelac(a)redhat.com>
AuthorDate: Fri Feb 26 01:23:50 2021 +0100
Committer: Zdenek Kabelac <zkabelac(a)redhat.com>
CommitterDate: Tue Mar 2 22:54:40 2021 +0100
archive: support interruption
When lvm2 calls archive() or backup() it can be useful to allow handling
break signal so the command can be interrupted at some consistent point.
Signal is accepted during processing these calls - and can be evaluated
later during even lengthy processing loops.
So now user can interrupt lengthy lvremove().
---
lib/format_text/archiver.c | 16 ++++++++++++++--
1 file changed, 14 insertions(+), 2 deletions(-)
diff --git a/lib/format_text/archiver.c b/lib/format_text/archiver.c
index cb8fc07de..932f97da3 100644
--- a/lib/format_text/archiver.c
+++ b/lib/format_text/archiver.c
@@ -17,6 +17,7 @@
#include "lib/format_text/archiver.h"
#include "lib/format_text/format-text.h"
#include "lib/misc/lvm-string.h"
+#include "lib/misc/lvm-signal.h"
#include "lib/cache/lvmcache.h"
#include "lib/mm/memlock.h"
#include "lib/commands/toolcontext.h"
@@ -155,7 +156,13 @@ static int _archive(struct volume_group *vg, int compulsory)
int archive(struct volume_group *vg)
{
- return _archive(vg, 1);
+ int r;
+
+ sigint_allow();
+ r = _archive(vg, 1);
+ sigint_restore();
+
+ return r;
}
int archive_display(struct cmd_context *cmd, const char *vg_name)
@@ -218,6 +225,7 @@ static int _backup(struct volume_group *vg)
{
char name[PATH_MAX];
char *desc;
+ int r;
if (!(desc = _build_desc(vg->cmd->mem, vg->cmd->cmd_line, 0)))
return_0;
@@ -229,7 +237,11 @@ static int _backup(struct volume_group *vg)
return 0;
}
- return backup_to_file(name, desc, vg);
+ sigint_allow();
+ r = backup_to_file(name, desc, vg);
+ sigint_restore();
+
+ return r;
}
int backup_locally(struct volume_group *vg)
3 years, 2 months
main - lvremove: backup at the end of loop
by Zdenek Kabelac
Gitweb: https://sourceware.org/git/?p=lvm2.git;a=commitdiff;h=eb1160ee4230e6f3770...
Commit: eb1160ee4230e6f37707b19eb5b46d2446257500
Parent: fa64c51428ca20e860bbe21338d916329b8aaf25
Author: Zdenek Kabelac <zkabelac(a)redhat.com>
AuthorDate: Fri Feb 26 01:01:29 2021 +0100
Committer: Zdenek Kabelac <zkabelac(a)redhat.com>
CommitterDate: Tue Mar 2 22:54:40 2021 +0100
lvremove: backup at the end of loop
Taking backup with each removed LV is slowing down the process
considerable and is largerly uneeded. We are supposed to take
backup only on significant points and making sure the backup
is correct when the command is finished.
TODO: check how many other commands can be improved.
---
lib/format_text/archiver.c | 2 ++
lib/metadata/lv_manip.c | 2 +-
lib/metadata/vg.h | 1 +
tools/toollib.c | 3 +++
4 files changed, 7 insertions(+), 1 deletion(-)
diff --git a/lib/format_text/archiver.c b/lib/format_text/archiver.c
index 07e9b04e4..cb8fc07de 100644
--- a/lib/format_text/archiver.c
+++ b/lib/format_text/archiver.c
@@ -267,6 +267,8 @@ int backup_locally(struct volume_group *vg)
int backup(struct volume_group *vg)
{
+ vg->needs_backup = 0;
+
/* Unlock memory if possible */
memlock_unlock(vg->cmd);
diff --git a/lib/metadata/lv_manip.c b/lib/metadata/lv_manip.c
index 9bcab7477..4ac95063c 100644
--- a/lib/metadata/lv_manip.c
+++ b/lib/metadata/lv_manip.c
@@ -6780,7 +6780,7 @@ int lv_remove_single(struct cmd_context *cmd, struct logical_volume *lv,
display_lvname(pool_lv));
}
- backup(vg);
+ vg->needs_backup = 1;
lockd_lv(cmd, lock_lv, "un", LDLV_PERSISTENT);
lockd_free_lv(cmd, vg, lv->name, &lv->lvid.id[1], lv->lock_args);
diff --git a/lib/metadata/vg.h b/lib/metadata/vg.h
index 2e2146169..386d5b450 100644
--- a/lib/metadata/vg.h
+++ b/lib/metadata/vg.h
@@ -42,6 +42,7 @@ struct volume_group {
struct lvmcache_vginfo *vginfo;
uint32_t seqno; /* Metadata sequence number */
unsigned skip_validate_lock_args : 1;
+ unsigned needs_backup : 1;
uint32_t write_count; /* count the number of vg_write calls */
/*
diff --git a/tools/toollib.c b/tools/toollib.c
index 5c9ccb6f2..9c026d9e5 100644
--- a/tools/toollib.c
+++ b/tools/toollib.c
@@ -3214,6 +3214,9 @@ int process_each_lv_in_vg(struct cmd_context *cmd, struct volume_group *vg,
log_set_report_object_name_and_id(NULL, NULL);
}
+ if (vg->needs_backup)
+ backup(vg);
+
if (lvargs_supplied) {
/*
* FIXME: lvm supports removal of LV with all its dependencies
3 years, 2 months
main - dev-cache: optimize dir scanning
by Zdenek Kabelac
Gitweb: https://sourceware.org/git/?p=lvm2.git;a=commitdiff;h=fa64c51428ca20e860b...
Commit: fa64c51428ca20e860bbe21338d916329b8aaf25
Parent: 9dd759c6b1c0e25e785485f823b09c59ef5b2583
Author: Zdenek Kabelac <zkabelac(a)redhat.com>
AuthorDate: Sat Feb 27 17:09:38 2021 +0100
Committer: Zdenek Kabelac <zkabelac(a)redhat.com>
CommitterDate: Tue Mar 2 22:54:40 2021 +0100
dev-cache: optimize dir scanning
Use 'C' for alphasort - there is no need to use localized and slower
sorting for internal directory scanning.
Ensure on all code paths allocated dirent entries are released.
Optimize full path construction.
---
lib/device/dev-cache.c | 41 ++++++++++++++++++++++-------------------
1 file changed, 22 insertions(+), 19 deletions(-)
diff --git a/lib/device/dev-cache.c b/lib/device/dev-cache.c
index 21c9ef0ea..bbf6ce833 100644
--- a/lib/device/dev-cache.c
+++ b/lib/device/dev-cache.c
@@ -28,6 +28,7 @@
#endif
#include <unistd.h>
#include <dirent.h>
+#include <locale.h>
struct dev_iter {
struct btree_iter *current;
@@ -809,16 +810,6 @@ static int _insert_dev(const char *path, dev_t d)
return 0;
}
-static char *_join(const char *dir, const char *name)
-{
- size_t len = strlen(dir) + strlen(name) + 2;
- char *r = malloc(len);
- if (r)
- snprintf(r, len, "%s/%s", dir, name);
-
- return r;
-}
-
/*
* Get rid of extra slashes in the path string.
*/
@@ -845,27 +836,39 @@ static int _insert_dir(const char *dir)
{
int n, dirent_count, r = 1;
struct dirent **dirent;
- char *path;
+ char path[PATH_MAX];
+ size_t len;
+
+ if (!dm_strncpy(path, dir, sizeof(path) - 1)) {
+ log_debug_devs("Dir path %s is too long", path);
+ return 0;
+ }
+ _collapse_slashes(path);
+ len = strlen(path);
+ if (len && path[len - 1] != '/')
+ path[len++] = '/';
+ setlocale(LC_COLLATE, "C"); /* Avoid sorting by locales */
dirent_count = scandir(dir, &dirent, NULL, alphasort);
if (dirent_count > 0) {
for (n = 0; n < dirent_count; n++) {
- if (dirent[n]->d_name[0] == '.') {
- free(dirent[n]);
+ if (dirent[n]->d_name[0] == '.')
continue;
- }
- if (!(path = _join(dir, dirent[n]->d_name)))
- return_0;
+ if (!dm_strncpy(path + len, dirent[n]->d_name, sizeof(path) - len)) {
+ log_debug_devs("Path %s/%s is too long.", dir, dirent[n]->d_name);
+ r = 0;
+ continue;
+ }
- _collapse_slashes(path);
r &= _insert(path, NULL, 1, 0);
- free(path);
+ }
+ for (n = 0; n < dirent_count; n++)
free(dirent[n]);
- }
free(dirent);
}
+ setlocale(LC_COLLATE, "");
return r;
}
3 years, 2 months
main - dev-cache: replace inefficient looking for dev
by Zdenek Kabelac
Gitweb: https://sourceware.org/git/?p=lvm2.git;a=commitdiff;h=9dd759c6b1c0e25e785...
Commit: 9dd759c6b1c0e25e785485f823b09c59ef5b2583
Parent: 081e47912e6c80f233fec5d472e32e1ac4f19a78
Author: Zdenek Kabelac <zkabelac(a)redhat.com>
AuthorDate: Fri Feb 26 00:21:41 2021 +0100
Committer: Zdenek Kabelac <zkabelac(a)redhat.com>
CommitterDate: Tue Mar 2 22:54:40 2021 +0100
dev-cache: replace inefficient looking for dev
Use btree loopkup to find dev structure by major:minor.
This could have slow down lvm2 commands significantly with
higher amount of LVs.
---
lib/device/dev-cache.c | 21 ++-------------------
1 file changed, 2 insertions(+), 19 deletions(-)
diff --git a/lib/device/dev-cache.c b/lib/device/dev-cache.c
index 8dd069c79..21c9ef0ea 100644
--- a/lib/device/dev-cache.c
+++ b/lib/device/dev-cache.c
@@ -1549,29 +1549,12 @@ struct device *dev_cache_get(struct cmd_context *cmd, const char *name, struct d
return dev;
}
-static struct device *_dev_cache_seek_devt(dev_t dev)
-{
- struct device *d = NULL;
- struct dm_hash_node *n = dm_hash_get_first(_cache.names);
- while (n) {
- d = dm_hash_get_data(_cache.names, n);
- if (d->dev == dev)
- return d;
- n = dm_hash_get_next(_cache.names, n);
- }
- return NULL;
-}
-
-/*
- * TODO This is very inefficient. We probably want a hash table indexed by
- * major:minor for keys to speed up these lookups.
- */
struct device *dev_cache_get_by_devt(struct cmd_context *cmd, dev_t dev, struct dev_filter *f, int *filtered)
{
char path[PATH_MAX];
const char *sysfs_dir;
struct stat info;
- struct device *d = _dev_cache_seek_devt(dev);
+ struct device *d = (struct device *) btree_lookup(_cache.devices, (uint32_t) dev);
int ret;
if (filtered)
@@ -1600,7 +1583,7 @@ struct device *dev_cache_get_by_devt(struct cmd_context *cmd, dev_t dev, struct
log_debug_devs("Device num not found in dev_cache repeat dev_cache_scan for %d:%d",
(int)MAJOR(dev), (int)MINOR(dev));
dev_cache_scan();
- d = _dev_cache_seek_devt(dev);
+ d = (struct device *) btree_lookup(_cache.devices, (uint32_t) dev);
}
if (!d)
3 years, 2 months
main - cmdline: use binary search
by Zdenek Kabelac
Gitweb: https://sourceware.org/git/?p=lvm2.git;a=commitdiff;h=081e47912e6c80f233f...
Commit: 081e47912e6c80f233fec5d472e32e1ac4f19a78
Parent: 589c6545627cdc5a90bf4c2e4640c42d9623bb47
Author: Zdenek Kabelac <zkabelac(a)redhat.com>
AuthorDate: Thu Feb 25 18:09:52 2021 +0100
Committer: Zdenek Kabelac <zkabelac(a)redhat.com>
CommitterDate: Tue Mar 2 22:54:40 2021 +0100
cmdline: use binary search
Reduce strcmp() call count by using binary search to find
commands in cmd_names[] and command_names[] arrays.
---
tools/command.c | 56 ++++++++++++++++++++++++++++++++-------
tools/command.h | 1 +
tools/lvmcmdline.c | 77 ++++++++++++++++++++++++++++++++----------------------
3 files changed, 94 insertions(+), 40 deletions(-)
diff --git a/tools/command.c b/tools/command.c
index 131d2d3d3..282c9fa43 100644
--- a/tools/command.c
+++ b/tools/command.c
@@ -426,12 +426,19 @@ static int _opt_str_to_num(struct command *cmd, char *str)
int command_id_to_enum(const char *str)
{
int i;
+ int first = 1, last = CMD_COUNT - 1, middle;
- for (i = 1; i < CMD_COUNT; i++) {
- if (!strcmp(str, cmd_names[i].name))
- return cmd_names[i].cmd_enum;
+ while (first <= last) {
+ middle = first + (last - first) / 2;
+ if ((i = strcmp(cmd_names[middle].name, str)) < 0)
+ first = middle + 1;
+ else if (i > 0)
+ last = middle - 1;
+ else
+ return cmd_names[middle].cmd_enum;
}
+ log_error("Cannot find command %s.", str);
return CMD_NONE;
}
@@ -509,20 +516,51 @@ static uint64_t _lv_to_bits(struct command *cmd, char *name)
return lvt_bits;
}
-static struct command_name *_find_command_name(const char *name)
+struct command_name *find_command_name(const char *name)
{
+ static int _command_names_count = -1;
+ int first = 0, last, middle;
int i;
- if (!islower(name[0]))
- return NULL; /* Commands starts with lower-case */
+ if (_command_names_count == -1) {
+ /* Validate cmd_names & command_names arrays are properly sorted */
+ for (i = 1; i < CMD_COUNT - 2; i++)
+ if (strcmp(cmd_names[i].name, cmd_names[i + 1].name) > 0) {
+ log_error("File cmds.h has unsorted name entry %s.",
+ cmd_names[i].name);
+ return 0;
+ }
+ for (i = 1; command_names[i].name; i++) /* assume > 1 */
+ if (strcmp(command_names[i - 1].name, command_names[i].name) > 0) {
+ log_error("File commands.h has unsorted name entry %s.",
+ command_names[i].name);
+ return 0;
+ }
+ _command_names_count = i - 1;
+ }
+ last = _command_names_count;
- for (i = 0; command_names[i].name; i++)
- if (!strcmp(command_names[i].name, name))
- return &command_names[i];
+ while (first <= last) {
+ middle = first + (last - first) / 2;
+ if ((i = strcmp(command_names[middle].name, name)) < 0)
+ first = middle + 1;
+ else if (i > 0)
+ last = middle - 1;
+ else
+ return &command_names[middle];
+ }
return NULL;
}
+static struct command_name *_find_command_name(const char *name)
+{
+ if (!islower(name[0]))
+ return NULL; /* Commands starts with lower-case */
+
+ return find_command_name(name);
+}
+
static const char *_is_command_name(char *str)
{
const struct command_name *c;
diff --git a/tools/command.h b/tools/command.h
index c0d7977dc..325ad1dd0 100644
--- a/tools/command.h
+++ b/tools/command.h
@@ -272,5 +272,6 @@ void print_usage_notes(struct command_name *cname);
void factor_common_options(void);
int command_has_alternate_extents(const char *name);
void configure_command_option_values(const char *name);
+struct command_name *find_command_name(const char *name);
#endif
diff --git a/tools/lvmcmdline.c b/tools/lvmcmdline.c
index 8ad1f5e99..588c78d72 100644
--- a/tools/lvmcmdline.c
+++ b/tools/lvmcmdline.c
@@ -80,6 +80,7 @@ extern struct command_name command_names[];
* Table of commands (as defined in command-lines.in)
*/
struct command commands[COMMAND_COUNT];
+struct command *commands_idx[COMMAND_COUNT];
static struct cmdline_context _cmdline;
@@ -1216,19 +1217,35 @@ static void _set_valid_args_for_command_name(int ci)
int opt_enum; /* foo_ARG from args.h */
int opt_syn;
int i, ro, oo, io;
+ int first = 0, last = COMMAND_COUNT - 1, middle;
+ const char *name = command_names[ci].name;
+
+ /* all_args is indexed by the foo_ARG enum vals */
+ /* Binary search in sorted array of long options (with duplicates) */
+ while (first <= last) {
+ middle = first + (last - first) / 2;
+ if ((i = strcmp(commands_idx[middle]->name, name)) < 0)
+ first = middle + 1;
+ else if (i > 0)
+ last = middle - 1;
+ else {
+ /* Matching command found.
+ * As sorted array contains duplicates, found 1st. and last such cmd. */
+ i = middle;
+ while (middle > first && !strcmp(commands_idx[middle - 1]->name, name))
+ middle--;
+ while (i < last && !strcmp(commands_idx[i + 1]->name, name))
+ i++;
+ last = i;
+ break;
+ }
+ }
- /*
- * all_args is indexed by the foo_ARG enum vals
- */
-
- for (i = 0; i < COMMAND_COUNT; i++) {
- if (strcmp(commands[i].name, command_names[ci].name))
- continue;
-
+ while (middle <= last) {
+ i = commands_idx[middle++]->command_index;
for (ro = 0; ro < (commands[i].ro_count + commands[i].any_ro_count); ro++) {
opt_enum = commands[i].required_opt_args[ro].opt;
all_args[opt_enum] = 1;
-
}
for (oo = 0; oo < commands[i].oo_count; oo++) {
opt_enum = commands[i].optional_opt_args[oo].opt;
@@ -1275,17 +1292,6 @@ static void _set_valid_args_for_command_name(int ci)
command_names[ci].num_args = num_args;
}
-static struct command_name *_find_command_name(const char *name)
-{
- int i;
-
- for (i = 0; command_names[i].name; i++)
- if (!strcmp(command_names[i].name, name))
- return &command_names[i];
-
- return NULL;
-}
-
static const struct command_function *_find_command_id_function(int command_enum)
{
int i;
@@ -1309,6 +1315,14 @@ static void _unregister_commands(void)
memset(&commands, 0, sizeof(commands));
}
+static int _command_name_compare(const void *on1, const void *on2)
+{
+ const struct command * const *optname1 = on1;
+ const struct command * const *optname2 = on2;
+
+ return strcmp((*optname1)->name, (*optname2)->name);
+}
+
int lvm_register_commands(struct cmd_context *cmd, const char *run_name)
{
int i;
@@ -1332,6 +1346,8 @@ int lvm_register_commands(struct cmd_context *cmd, const char *run_name)
_cmdline.num_commands = COMMAND_COUNT;
for (i = 0; i < COMMAND_COUNT; i++) {
+ commands_idx[i] = &commands[i];
+ commands[i].command_index = i;
commands[i].command_enum = command_id_to_enum(commands[i].command_id);
if (!commands[i].command_enum) {
@@ -1346,22 +1362,21 @@ int lvm_register_commands(struct cmd_context *cmd, const char *run_name)
/* old style */
if (!commands[i].functions) {
- struct command_name *cname = _find_command_name(commands[i].name);
+ struct command_name *cname = find_command_name(commands[i].name);
if (cname)
commands[i].fn = cname->fn;
}
}
- /* Check how many command entries we have */
+ /* Sort all commands by its name for quick binary search */
+ qsort(commands_idx, COMMAND_COUNT, sizeof(long), _command_name_compare);
+
for (i = 0; command_names[i].name; i++)
- ;
+ _set_valid_args_for_command_name(i);
- _cmdline.num_command_names = i;
+ _cmdline.num_command_names = i; /* Also counted how many command entries we have */
_cmdline.command_names = command_names;
- for (i = 0; i < _cmdline.num_command_names; i++)
- _set_valid_args_for_command_name(i);
-
return 1;
}
@@ -2002,7 +2017,7 @@ static void _short_usage(const char *name)
static int _usage(const char *name, int longhelp, int skip_notes)
{
- struct command_name *cname = _find_command_name(name);
+ struct command_name *cname = find_command_name(name);
struct command *cmd = NULL;
int show_full = longhelp;
int i;
@@ -2163,7 +2178,7 @@ static int _find_arg(const char *cmd_name, int goval)
int arg_enum;
int i;
- if (!(cname = _find_command_name(cmd_name)))
+ if (!(cname = find_command_name(cmd_name)))
return -1;
for (i = 0; i < cname->num_args; i++) {
@@ -3051,7 +3066,7 @@ int lvm_run_command(struct cmd_context *cmd, int argc, char **argv)
return_ECMD_FAILED;
/* Look up command - will be NULL if not recognised */
- if (!(cmd->cname = _find_command_name(cmd->name)))
+ if (!(cmd->cname = find_command_name(cmd->name)))
return ENO_SUCH_CMD;
if (!_process_command_line(cmd, &argc, &argv)) {
@@ -3699,7 +3714,7 @@ int lvm2_main(int argc, char **argv)
*/
if (!run_name)
run_shell = 1;
- else if (!_find_command_name(run_name))
+ else if (!find_command_name(run_name))
run_script = 1;
else
run_command_name = run_name;
3 years, 2 months
main - cmdline: drop MAX and check NULL
by Zdenek Kabelac
Gitweb: https://sourceware.org/git/?p=lvm2.git;a=commitdiff;h=589c6545627cdc5a90b...
Commit: 589c6545627cdc5a90bf4c2e4640c42d9623bb47
Parent: e946a5e6904455284ae4eeaa1d149a9324b0f00e
Author: Zdenek Kabelac <zkabelac(a)redhat.com>
AuthorDate: Thu Feb 25 18:09:33 2021 +0100
Committer: Zdenek Kabelac <zkabelac(a)redhat.com>
CommitterDate: Tue Mar 2 22:54:40 2021 +0100
cmdline: drop MAX and check NULL
Remove MAX_COMMAND_NAMES and check for the last element as NULL pointer.
---
tools/command.c | 16 ++++++----------
tools/command.h | 2 --
tools/lvmcmdline.c | 27 ++++++++++-----------------
3 files changed, 16 insertions(+), 29 deletions(-)
diff --git a/tools/command.c b/tools/command.c
index dd1f94194..131d2d3d3 100644
--- a/tools/command.c
+++ b/tools/command.c
@@ -246,19 +246,21 @@ struct cmd_name cmd_names[CMD_COUNT + 1] = {
#ifdef MAN_PAGE_GENERATOR
-struct command_name command_names[MAX_COMMAND_NAMES] = {
+struct command_name command_names[] = {
#define xx(a, b, c...) { # a, b, c },
#include "commands.h"
#undef xx
+ { .name = NULL }
};
struct command commands[COMMAND_COUNT];
#else /* MAN_PAGE_GENERATOR */
-struct command_name command_names[MAX_COMMAND_NAMES] = {
+struct command_name command_names[] = {
#define xx(a, b, c...) { # a, b, c, a},
#include "commands.h"
#undef xx
+ { .name = NULL }
};
extern struct command commands[COMMAND_COUNT]; /* defined in lvmcmdline.c */
@@ -514,12 +516,9 @@ static struct command_name *_find_command_name(const char *name)
if (!islower(name[0]))
return NULL; /* Commands starts with lower-case */
- for (i = 0; i < MAX_COMMAND_NAMES; i++) {
- if (!command_names[i].name)
- break;
+ for (i = 0; command_names[i].name; i++)
if (!strcmp(command_names[i].name, name))
return &command_names[i];
- }
return NULL;
}
@@ -1270,10 +1269,7 @@ void factor_common_options(void)
int cn, opt_enum, ci, oo, ro, found;
struct command *cmd;
- for (cn = 0; cn < MAX_COMMAND_NAMES; cn++) {
- if (!command_names[cn].name)
- break;
-
+ for (cn = 0; command_names[cn].name; cn++) {
/* already factored */
if (command_names[cn].variants)
continue;
diff --git a/tools/command.h b/tools/command.h
index dae3d0570..c0d7977dc 100644
--- a/tools/command.h
+++ b/tools/command.h
@@ -30,8 +30,6 @@ struct command_function {
command_id_fn fn;
};
-#define MAX_COMMAND_NAMES 64
-
struct command_name {
const char *name;
const char *desc; /* general command description from commands.h */
diff --git a/tools/lvmcmdline.c b/tools/lvmcmdline.c
index b6ad66d62..8ad1f5e99 100644
--- a/tools/lvmcmdline.c
+++ b/tools/lvmcmdline.c
@@ -74,7 +74,7 @@ extern struct lv_type lv_types[LVT_COUNT + 1];
/*
* Table of command names
*/
-extern struct command_name command_names[MAX_COMMAND_NAMES];
+extern struct command_name command_names[];
/*
* Table of commands (as defined in command-lines.in)
@@ -1278,13 +1278,11 @@ static void _set_valid_args_for_command_name(int ci)
static struct command_name *_find_command_name(const char *name)
{
int i;
-
- for (i = 0; i < MAX_COMMAND_NAMES; i++) {
- if (!command_names[i].name)
- break;
+
+ for (i = 0; command_names[i].name; i++)
if (!strcmp(command_names[i].name, name))
return &command_names[i];
- }
+
return NULL;
}
@@ -1354,14 +1352,12 @@ int lvm_register_commands(struct cmd_context *cmd, const char *run_name)
}
}
- _cmdline.command_names = command_names;
- _cmdline.num_command_names = 0;
+ /* Check how many command entries we have */
+ for (i = 0; command_names[i].name; i++)
+ ;
- for (i = 0; i < MAX_COMMAND_NAMES; i++) {
- if (!command_names[i].name)
- break;
- _cmdline.num_command_names++;
- }
+ _cmdline.num_command_names = i;
+ _cmdline.command_names = command_names;
for (i = 0; i < _cmdline.num_command_names; i++)
_set_valid_args_for_command_name(i);
@@ -2074,11 +2070,8 @@ static void _usage_all(void)
{
int i;
- for (i = 0; i < MAX_COMMAND_NAMES; i++) {
- if (!command_names[i].name)
- break;
+ for (i = 0; command_names[i].name; i++)
_usage(command_names[i].name, 1, 1);
- }
print_usage_notes(NULL);
}
3 years, 2 months