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

export: use radix_tree for write formatter

Replace use of dm_hash with radix_tree when making PV index names.

Store just the index number itself and use pv%d for outf() string.

For lookup up a PV - use just the PV pointer itself, it's faster then
converint for it's ID to UUID format.
This commit is contained in:
Zdenek Kabelac 2024-10-13 00:23:08 +02:00
parent 7c5cca600c
commit 4dc0ee8e56

View File

@ -25,6 +25,7 @@
#include "lib/commands/toolcontext.h" #include "lib/commands/toolcontext.h"
#include "lib/device/device_id.h" #include "lib/device/device_id.h"
#include "libdaemon/client/config-util.h" #include "libdaemon/client/config-util.h"
#include "base/data-struct/radix-tree.h"
#include <stdarg.h> #include <stdarg.h>
#include <time.h> #include <time.h>
@ -53,8 +54,7 @@ typedef int (*nl_fn) (struct formatter * f);
* exporting the vg, ie. writing it to a file. * exporting the vg, ie. writing it to a file.
*/ */
struct formatter { struct formatter {
struct dm_pool *mem; /* pv names allocated from here */ struct radix_tree *pv_idx; /* dev_name id -> pv_name (eg, pv1) */
struct dm_hash_table *pv_names; /* dev_name -> pv_name (eg, pv1) */
union { union {
FILE *fp; /* where we're writing to */ FILE *fp; /* where we're writing to */
@ -500,29 +500,18 @@ static int _print_vg(struct formatter *f, struct volume_group *vg)
return 1; return 1;
} }
/* /* Get the pv index %d name from the formatters radix tree. */
* Get the pv%d name from the formatters hash static int _get_pv_idx(const struct formatter *f, const struct physical_volume *pv)
* table.
*/
static const char *_get_pv_name_from_uuid(struct formatter *f, char *uuid)
{ {
const char *pv_name = dm_hash_lookup(f->pv_names, uuid); union radix_value idx;
if (!pv_name) if (!pv || !radix_tree_lookup(f->pv_idx, &pv, sizeof(pv), &idx)) {
log_error(INTERNAL_ERROR "PV name for uuid %s missing from text metadata export hash table.", log_error(INTERNAL_ERROR "PV name for %s missing in metadata export radix tree.",
uuid); pv_dev_name(pv));
return -1;
return pv_name;
} }
static const char *_get_pv_name(struct formatter *f, struct physical_volume *pv) return (int) idx.n;
{
char uuid[64] __attribute__((aligned(8)));
if (!pv || !id_write_format(&pv->id, uuid, sizeof(uuid)))
return_NULL;
return _get_pv_name_from_uuid(f, uuid);
} }
static int _print_pvs(struct formatter *f, struct volume_group *vg) static int _print_pvs(struct formatter *f, struct volume_group *vg)
@ -530,7 +519,7 @@ static int _print_pvs(struct formatter *f, struct volume_group *vg)
struct pv_list *pvl; struct pv_list *pvl;
struct physical_volume *pv; struct physical_volume *pv;
char buffer[PATH_MAX * 2]; char buffer[PATH_MAX * 2];
const char *name; int idx;
const char *idtype, *idname; const char *idtype, *idname;
outf(f, "physical_volumes {"); outf(f, "physical_volumes {");
@ -542,11 +531,11 @@ static int _print_pvs(struct formatter *f, struct volume_group *vg)
if (!id_write_format(&pv->id, buffer, sizeof(buffer))) if (!id_write_format(&pv->id, buffer, sizeof(buffer)))
return_0; return_0;
if (!(name = _get_pv_name_from_uuid(f, buffer))) if ((idx = _get_pv_idx(f, pv)) < 0)
return_0; return_0;
outnl(f); outnl(f);
outf(f, "%s {", name); outf(f, "pv%d {", idx);
_inc_indent(f); _inc_indent(f);
outf(f, "id = \"%s\"", buffer); outf(f, "id = \"%s\"", buffer);
@ -630,8 +619,8 @@ static int _print_segment(struct formatter *f, struct volume_group *vg,
int out_areas(struct formatter *f, const struct lv_segment *seg, int out_areas(struct formatter *f, const struct lv_segment *seg,
const char *type) const char *type)
{ {
const char *name;
unsigned int s; unsigned int s;
int idx;
struct physical_volume *pv; struct physical_volume *pv;
outnl(f); outnl(f);
@ -648,10 +637,10 @@ int out_areas(struct formatter *f, const struct lv_segment *seg,
return 0; return 0;
} }
if (!(name = _get_pv_name(f, pv))) if ((idx = _get_pv_idx(f, pv)) < 0)
return_0; return_0;
outf(f, "\"%s\", %u%s", name, outf(f, "\"pv%d\", %u%s", idx,
seg_pe(seg, s), seg_pe(seg, s),
(s == seg->area_count - 1) ? "" : ","); (s == seg->area_count - 1) ? "" : ",");
break; break;
@ -962,35 +951,22 @@ static int _print_historical_lvs(struct formatter *f, struct volume_group *vg)
* 'pv2' etc. This function builds a hash table * 'pv2' etc. This function builds a hash table
* to enable a quick lookup from device -> name. * to enable a quick lookup from device -> name.
*/ */
static int _build_pv_names(struct formatter *f, struct volume_group *vg) static int _build_pv_idx(struct formatter *f, struct volume_group *vg)
{ {
int count = 0; union radix_value count = { 0 };
struct pv_list *pvl; struct pv_list *pvl;
struct physical_volume *pv; struct physical_volume *pv;
char buffer[32], *name;
char uuid[64];
if (!(f->mem = dm_pool_create("text pv_names", 512))) if (!(f->pv_idx = radix_tree_create(NULL, NULL)))
return_0;
if (!(f->pv_names = dm_hash_create(115)))
return_0; return_0;
dm_list_iterate_items(pvl, &vg->pvs) { dm_list_iterate_items(pvl, &vg->pvs) {
pv = pvl->pv; pv = pvl->pv;
/* FIXME But skip if there's already an LV called pv%d ! */ /* FIXME But skip if there's already an LV called pv%d ! */
if (dm_snprintf(buffer, sizeof(buffer), "pv%d", count++) < 0) if (!radix_tree_insert(f->pv_idx, &pv, sizeof(pv), count))
return_0;
if (!(name = dm_pool_strdup(f->mem, buffer)))
return_0;
if (!id_write_format(&pv->id, uuid, sizeof(uuid)))
return_0;
if (!dm_hash_insert(f->pv_names, uuid, name))
return_0; return_0;
count.n++;
} }
return 1; return 1;
@ -1001,7 +977,7 @@ static int _text_vg_export(struct formatter *f,
{ {
int r = 0; int r = 0;
if (!_build_pv_names(f, vg)) if (!_build_pv_idx(f, vg))
goto_out; goto_out;
if (f->header && !_print_header(vg->cmd, f, desc)) if (f->header && !_print_header(vg->cmd, f, desc))
@ -1037,14 +1013,9 @@ static int _text_vg_export(struct formatter *f,
r = 1; r = 1;
out: out:
if (f->mem) { if (f->pv_idx) {
dm_pool_destroy(f->mem); radix_tree_destroy(f->pv_idx);
f->mem = NULL; f->pv_idx = NULL;
}
if (f->pv_names) {
dm_hash_destroy(f->pv_names);
f->pv_names = NULL;
} }
return r; return r;