diff options
-rw-r--r-- | WHATS_NEW | 22 | ||||
-rw-r--r-- | doc/example.conf | 8 | ||||
-rw-r--r-- | lib/activate/dev_manager.c | 12 | ||||
-rw-r--r-- | lib/commands/toolcontext.c | 6 | ||||
-rw-r--r-- | lib/device/dev-cache.c | 103 | ||||
-rw-r--r-- | lib/device/dev-cache.h | 5 | ||||
-rw-r--r-- | lib/filters/filter-persistent.c | 13 | ||||
-rw-r--r-- | lib/filters/filter-regex.c | 44 | ||||
-rw-r--r-- | lib/filters/filter-sysfs.c | 6 | ||||
-rw-r--r-- | lib/format1/disk-rep.c | 6 | ||||
-rw-r--r-- | lib/format1/format1.c | 47 | ||||
-rw-r--r-- | lib/format1/import-extents.c | 18 | ||||
-rw-r--r-- | lib/format_text/import_vsn1.c | 12 | ||||
-rw-r--r-- | lib/log/log.h | 1 | ||||
-rw-r--r-- | lib/metadata/metadata.c | 15 | ||||
-rw-r--r-- | lib/misc/lvm-file.c | 6 | ||||
-rw-r--r-- | lib/regex/matcher.c | 23 | ||||
-rw-r--r-- | tools/lvmcmdline.c | 12 |
18 files changed, 211 insertions, 148 deletions
@@ -1,15 +1,20 @@ Version 2.02.25 - ================================= - Fix warnings on x86_64 involving ptrdiff_t in log_error messages - Update pvck to include text metadata area and record detection - Add support functions for analysis of config sections - Update pvck to read labels on disk, with --labelsector parameter - Add count_chars and count_chars_len functions - Add /sys/block listings to lvm_dump.sh - Make lvm_dump.sh list /dev recursively + Add devices/preferred_names config regex list for displayed device names. + Free a temporary dir string in fcntl_lock_file() after use. + Fix a dm_pool_destroy() in matcher_create(). + Introduce goto_bad macro. + Fix warnings on x86_64 involving ptrdiff_t in log_error messages. + Update pvck to include text metadata area and record detection. + Add support functions for token counting in config file extracts. + Update pvck to read labels on disk, with --labelsector parameter. + Add count_chars and count_chars_len functions. + Add /sys/block listings to lvm_dump.sh. + Make lvm_dump.sh list /dev recursively. Fix thread race in clvmd. Add scan_sector param to label_read and _find_labeller. - Make clvmd cope with quorum devices on RHEL5 + Make clvmd cope with quorum devices. + Add extra internal error checking to clvmd. Add dev_read_circular. Add pvck command stub. Update lists of attribute characters in man pages. @@ -17,7 +22,6 @@ Version 2.02.25 - Fix creation and conversion of mirrors with tags. Fix vgsplit for lvm1 format (set and validate VG name in PVs metadata). Split metadata areas in vgsplit properly. - Add extra internal error checking to clvmd Version 2.02.24 - 19th March 2007 ================================= diff --git a/doc/example.conf b/doc/example.conf index 5f4d089c..65195537 100644 --- a/doc/example.conf +++ b/doc/example.conf @@ -19,6 +19,14 @@ devices { # to use with LVM2. scan = [ "/dev" ] + # If several entries in the scanned directories correspond to the + # same block device and the tools need to display a name for device, + # all the pathnames are matched against each item in the following + # list of regular expressions in turn and the first match is used. + preferred_names = [ ] + + # preferred_names = [ "^/dev/mpath/", "^/dev/[hs]d" ] + # A filter that tells LVM2 to only use a restricted set of devices. # The filter consists of an array of regular expressions. These # expressions can be delimited by a character of your choice, and diff --git a/lib/activate/dev_manager.c b/lib/activate/dev_manager.c index 7d9b7c23..6f5e735e 100644 --- a/lib/activate/dev_manager.c +++ b/lib/activate/dev_manager.c @@ -435,10 +435,8 @@ struct dev_manager *dev_manager_create(struct cmd_context *cmd, return NULL; } - if (!(dm = dm_pool_alloc(mem, sizeof(*dm)))) { - stack; - goto bad; - } + if (!(dm = dm_pool_alloc(mem, sizeof(*dm)))) + goto_bad; dm->cmd = cmd; dm->mem = mem; @@ -450,10 +448,8 @@ struct dev_manager *dev_manager_create(struct cmd_context *cmd, } dm->stripe_filler = stripe_filler; - if (!(dm->vg_name = dm_pool_strdup(dm->mem, vg_name))) { - stack; - goto bad; - } + if (!(dm->vg_name = dm_pool_strdup(dm->mem, vg_name))) + goto_bad; dm->target_state = NULL; diff --git a/lib/commands/toolcontext.c b/lib/commands/toolcontext.c index 8a4074a7..13bbdc03 100644 --- a/lib/commands/toolcontext.c +++ b/lib/commands/toolcontext.c @@ -465,10 +465,8 @@ static int _init_dev_cache(struct cmd_context *cmd) const struct config_node *cn; struct config_value *cv; - if (!dev_cache_init()) { - stack; - return 0; - } + if (!dev_cache_init(cmd)) + return_0; if (!(cn = find_config_tree_node(cmd, "devices/scan"))) { if (!dev_cache_add_dir("/dev")) { diff --git a/lib/device/dev-cache.c b/lib/device/dev-cache.c index bc8f8226..55c2dac5 100644 --- a/lib/device/dev-cache.c +++ b/lib/device/dev-cache.c @@ -19,6 +19,8 @@ #include "btree.h" #include "filter.h" #include "filter-persistent.h" +#include "matcher.h" +#include "toolcontext.h" #include <unistd.h> #include <sys/param.h> @@ -38,6 +40,7 @@ static struct { struct dm_pool *mem; struct dm_hash_table *names; struct btree *devices; + struct matcher *preferred_names_matcher; int has_scanned; struct list dirs; @@ -129,15 +132,49 @@ static struct device *_dev_create(dev_t d) return dev; } +void dev_set_preferred_name(struct str_list *sl, struct device *dev) +{ + /* + * Don't interfere with ordering specified in config file. + */ + if (_cache.preferred_names_matcher) + return; + + log_debug("%s: New preferred name", sl->str); + list_del(&sl->list); + list_add_h(&dev->aliases, &sl->list); +} + /* Return 1 if we prefer path1 else return 0 */ static int _compare_paths(const char *path0, const char *path1) { int slash0 = 0, slash1 = 0; + int m0, m1; const char *p; char p0[PATH_MAX], p1[PATH_MAX]; char *s0, *s1; struct stat stat0, stat1; + if (_cache.preferred_names_matcher) { + m0 = matcher_run(_cache.preferred_names_matcher, path0); + m1 = matcher_run(_cache.preferred_names_matcher, path1); + + if (m0 != m1) { + if (m0 < 0) + return 1; + if (m1 < 0) + return 0; + if (m0 < m1) + return 1; + if (m1 < m0) + return 0; + } + } + + /* + * Built-in rules. + */ + /* Return the path with fewer slashes */ for (p = path0; p++; p = (const char *) strchr(p, '/')) slash0++; @@ -441,7 +478,65 @@ void dev_cache_scan(int do_scan) _full_scan(1); } -int dev_cache_init(void) +static int _init_preferred_names(struct cmd_context *cmd) +{ + const struct config_node *cn; + struct config_value *v; + struct dm_pool *scratch = NULL; + char **regex; + unsigned count = 0; + int i, r = 0; + + _cache.preferred_names_matcher = NULL; + + if (!(cn = find_config_tree_node(cmd, "devices/preferred_names")) || + cn->v->type == CFG_EMPTY_ARRAY) { + log_very_verbose("devices/preferred_names not found in config file: " + "using built-in preferences"); + return 1; + } + + for (v = cn->v; v; v = v->next) { + if (v->type != CFG_STRING) { + log_error("preferred_names patterns must be enclosed in quotes"); + return 0; + } + + count++; + } + + if (!(scratch = dm_pool_create("preferred device name matcher", 1024))) + return_0; + + if (!(regex = dm_pool_alloc(scratch, sizeof(*regex) * count))) { + log_error("Failed to allocate preferred device name " + "pattern list."); + goto out; + } + + for (v = cn->v, i = count - 1; v; v = v->next, i--) { + if (!(regex[i] = dm_pool_strdup(scratch, v->v.str))) { + log_error("Failed to allocate a preferred device name " + "pattern."); + goto out; + } + } + + if (!(_cache.preferred_names_matcher = + matcher_create(_cache.mem,(const char **) regex, count))) { + log_error("Preferred device name pattern matcher creation failed."); + goto out; + } + + r = 1; + +out: + dm_pool_destroy(scratch); + + return r; +} + +int dev_cache_init(struct cmd_context *cmd) { _cache.names = NULL; _cache.has_scanned = 0; @@ -466,6 +561,9 @@ int dev_cache_init(void) list_init(&_cache.dirs); list_init(&_cache.files); + if (!_init_preferred_names(cmd)) + goto_bad; + return 1; bad: @@ -489,6 +587,9 @@ void dev_cache_exit(void) if (_cache.names) _check_for_open_devices(); + if (_cache.preferred_names_matcher) + _cache.preferred_names_matcher = NULL; + if (_cache.mem) { dm_pool_destroy(_cache.mem); _cache.mem = NULL; diff --git a/lib/device/dev-cache.h b/lib/device/dev-cache.h index 631d63bf..aa1907c1 100644 --- a/lib/device/dev-cache.h +++ b/lib/device/dev-cache.h @@ -30,7 +30,8 @@ struct dev_filter { /* * The global device cache. */ -int dev_cache_init(void); +struct cmd_context; +int dev_cache_init(struct cmd_context *cmd); void dev_cache_exit(void); /* Trigger(1) or avoid(0) a scan */ @@ -41,6 +42,8 @@ int dev_cache_add_dir(const char *path); int dev_cache_add_loopfile(const char *path); struct device *dev_cache_get(const char *name, struct dev_filter *f); +void dev_set_preferred_name(struct str_list *sl, struct device *dev); + /* * Object for iterating through the cache. */ diff --git a/lib/filters/filter-persistent.c b/lib/filters/filter-persistent.c index 5849accb..91e71478 100644 --- a/lib/filters/filter-persistent.c +++ b/lib/filters/filter-persistent.c @@ -301,10 +301,9 @@ struct dev_filter *persistent_filter_create(struct dev_filter *real, } memset(pf, 0, sizeof(*pf)); - if (!(pf->file = dm_malloc(strlen(file) + 1))) { - stack; - goto bad; - } + if (!(pf->file = dm_malloc(strlen(file) + 1))) + goto_bad; + strcpy(pf->file, file); pf->real = real; @@ -313,10 +312,8 @@ struct dev_filter *persistent_filter_create(struct dev_filter *real, goto bad; } - if (!(f = dm_malloc(sizeof(*f)))) { - stack; - goto bad; - } + if (!(f = dm_malloc(sizeof(*f)))) + goto_bad; f->passes_filter = _lookup_p; f->destroy = _persistent_destroy; diff --git a/lib/filters/filter-regex.c b/lib/filters/filter-regex.c index d6cca7b0..10b4f0fb 100644 --- a/lib/filters/filter-regex.c +++ b/lib/filters/filter-regex.c @@ -98,18 +98,15 @@ static int _build_matcher(struct rfilter *rf, struct config_value *val) unsigned count = 0; int i, r = 0; - if (!(scratch = dm_pool_create("filter matcher", 1024))) { - stack; - return 0; - } + if (!(scratch = dm_pool_create("filter matcher", 1024))) + return_0; /* * count how many patterns we have. */ for (v = val; v; v = v->next) { - if (v->type != CFG_STRING) { - log_info("filter patterns must be enclosed in quotes"); + log_error("filter patterns must be enclosed in quotes"); goto out; } @@ -119,10 +116,8 @@ static int _build_matcher(struct rfilter *rf, struct config_value *val) /* * allocate space for them */ - if (!(regex = dm_pool_alloc(scratch, sizeof(*regex) * count))) { - stack; - goto out; - } + if (!(regex = dm_pool_alloc(scratch, sizeof(*regex) * count))) + goto_out; /* * create the accept/reject bitset @@ -136,7 +131,7 @@ static int _build_matcher(struct rfilter *rf, struct config_value *val) */ for (v = val, i = count - 1; v; v = v->next, i--) if (!_extract_pattern(scratch, v->v.str, regex, rf->accept, i)) { - log_info("invalid filter pattern"); + log_error("invalid filter pattern"); goto out; } @@ -164,13 +159,8 @@ static int _accept_p(struct dev_filter *f, struct device *dev) if (m >= 0) { if (dm_bit(rf->accept, m)) { - - if (!first) { - log_debug("%s: New preferred name", - sl->str); - list_del(&sl->list); - list_add_h(&dev->aliases, &sl->list); - } + if (!first) + dev_set_preferred_name(sl, dev); return 1; } @@ -208,22 +198,16 @@ struct dev_filter *regex_filter_create(struct config_value *patterns) return NULL; } - if (!(rf = dm_pool_alloc(mem, sizeof(*rf)))) { - stack; - goto bad; - } + if (!(rf = dm_pool_alloc(mem, sizeof(*rf)))) + goto_bad; rf->mem = mem; - if (!_build_matcher(rf, patterns)) { - stack; - goto bad; - } + if (!_build_matcher(rf, patterns)) + goto_bad; - if (!(f = dm_pool_zalloc(mem, sizeof(*f)))) { - stack; - goto bad; - } + if (!(f = dm_pool_zalloc(mem, sizeof(*f)))) + goto_bad; f->passes_filter = _accept_p; f->destroy = _regex_destroy; diff --git a/lib/filters/filter-sysfs.c b/lib/filters/filter-sysfs.c index ca246292..e678ad1f 100644 --- a/lib/filters/filter-sysfs.c +++ b/lib/filters/filter-sysfs.c @@ -284,10 +284,8 @@ struct dev_filter *sysfs_filter_create(const char *proc) goto bad; } - if (!(f = dm_pool_zalloc(mem, sizeof(*f)))) { - stack; - goto bad; - } + if (!(f = dm_pool_zalloc(mem, sizeof(*f)))) + goto_bad; f->passes_filter = _accept_p; f->destroy = _destroy; diff --git a/lib/format1/disk-rep.c b/lib/format1/disk-rep.c index 81f39f8b..39efd6a8 100644 --- a/lib/format1/disk-rep.c +++ b/lib/format1/disk-rep.c @@ -357,10 +357,8 @@ static struct disk_list *__read_disk(const struct format_type *fmt, list_init(&dl->uuids); list_init(&dl->lvds); - if (!_read_pvd(dev, &dl->pvd)) { - stack; - goto bad; - } + if (!_read_pvd(dev, &dl->pvd)) + goto_bad; /* * is it an orphan ? diff --git a/lib/format1/format1.c b/lib/format1/format1.c index 3f1d28f4..264b75e2 100644 --- a/lib/format1/format1.c +++ b/lib/format1/format1.c @@ -131,10 +131,10 @@ static struct volume_group *_build_vg(struct format_instance *fid, int partial; if (!vg) - goto bad; + goto_bad; if (list_empty(pvs)) - goto bad; + goto_bad; memset(vg, 0, sizeof(*vg)); @@ -146,24 +146,24 @@ static struct volume_group *_build_vg(struct format_instance *fid, list_init(&vg->tags); if (!_check_vgs(pvs, &partial)) - goto bad; + goto_bad; dl = list_item(pvs->n, struct disk_list); if (!import_vg(mem, vg, dl, partial)) - goto bad; + goto_bad; if (!import_pvs(fid->fmt, mem, vg, pvs, &vg->pvs, &vg->pv_count)) - goto bad; + goto_bad; if (!import_lvs(mem, vg, pvs)) - goto bad; + goto_bad; if (!import_extents(fid->fmt->cmd, vg, pvs)) - goto bad; + goto_bad; if (!import_snapshots(mem, vg, pvs)) - goto bad; + goto_bad; return vg; @@ -191,15 +191,11 @@ static struct volume_group *_format1_vg_read(struct format_instance *fid, vg_name = strip_dir(vg_name, fid->fmt->cmd->dev_dir); if (!read_pvs_in_vg - (fid->fmt, vg_name, fid->fmt->cmd->filter, mem, &pvs)) { - stack; - goto bad; - } + (fid->fmt, vg_name, fid->fmt->cmd->filter, mem, &pvs)) + goto_bad; - if (!(vg = _build_vg(fid, &pvs))) { - stack; - goto bad; - } + if (!(vg = _build_vg(fid, &pvs))) + goto_bad; bad: dm_pool_destroy(mem); @@ -415,17 +411,14 @@ static int _format1_pv_write(const struct format_type *fmt, struct physical_volu return 0; } - if (!(dl = dm_pool_alloc(mem, sizeof(*dl)))) { - stack; - goto bad; - } + if (!(dl = dm_pool_alloc(mem, sizeof(*dl)))) + goto_bad; + dl->mem = mem; dl->dev = pv->dev; - if (!export_pv(fmt->cmd, mem, NULL, &dl->pvd, pv)) { - stack; - goto bad; - } + if (!export_pv(fmt->cmd, mem, NULL, &dl->pvd, pv)) + goto_bad; /* must be set to be able to zero gap after PV structure in dev_write in order to make other disk tools happy */ @@ -434,10 +427,8 @@ static int _format1_pv_write(const struct format_type *fmt, struct physical_volu dl->pvd.pe_on_disk.base = LVM1_PE_ALIGN << SECTOR_SHIFT; list_add(&pvs, &dl->list); - if (!write_disks(fmt, &pvs)) { - stack; - goto bad; - } + if (!write_disks(fmt, &pvs)) + goto_bad; dm_pool_destroy(mem); return 1; diff --git a/lib/format1/import-extents.c b/lib/format1/import-extents.c index 0928af40..52ec0757 100644 --- a/lib/format1/import-extents.c +++ b/lib/format1/import-extents.c @@ -59,22 +59,16 @@ static struct dm_hash_table *_create_lv_maps(struct dm_pool *mem, if (ll->lv->status & SNAPSHOT) continue; - if (!(lvm = dm_pool_alloc(mem, sizeof(*lvm)))) { - stack; - goto bad; - } + if (!(lvm = dm_pool_alloc(mem, sizeof(*lvm)))) + goto_bad; lvm->lv = ll->lv; if (!(lvm->map = dm_pool_zalloc(mem, sizeof(*lvm->map) - * ll->lv->le_count))) { - stack; - goto bad; - } + * ll->lv->le_count))) + goto_bad; - if (!dm_hash_insert(maps, ll->lv->name, lvm)) { - stack; - goto bad; - } + if (!dm_hash_insert(maps, ll->lv->name, lvm)) + goto_bad; } return maps; diff --git a/lib/format_text/import_vsn1.c b/lib/format_text/import_vsn1.c index c1b52944..04770665 100644 --- a/lib/format_text/import_vsn1.c +++ b/lib/format_text/import_vsn1.c @@ -660,15 +660,11 @@ static struct volume_group *_read_vg(struct format_instance *fid, /* eg Set to instance of fmt1 here if reading a format1 backup? */ vg->fid = fid; - if (!(vg->name = dm_pool_strdup(mem, vgn->key))) { - stack; - goto bad; - } + if (!(vg->name = dm_pool_strdup(mem, vgn->key))) + goto_bad; - if (!(vg->system_id = dm_pool_zalloc(mem, NAME_LEN))) { - stack; - goto bad; - } + if (!(vg->system_id = dm_pool_zalloc(mem, NAME_LEN))) + goto_bad; vgn = vgn->child; diff --git a/lib/log/log.h b/lib/log/log.h index 1c75cbef..925d0f99 100644 --- a/lib/log/log.h +++ b/lib/log/log.h @@ -138,5 +138,6 @@ void print_log(int level, const char *file, int line, const char *format, ...) #define return_0 do { stack; return 0; } while (0) #define return_NULL do { stack; return NULL; } while (0) #define goto_out do { stack; goto out; } while (0) +#define goto_bad do { stack; goto bad; } while (0) #endif diff --git a/lib/metadata/metadata.c b/lib/metadata/metadata.c index 7828cbfc..e75a6cd7 100644 --- a/lib/metadata/metadata.c +++ b/lib/metadata/metadata.c @@ -280,10 +280,9 @@ struct volume_group *vg_create(struct cmd_context *cmd, const char *vg_name, vg->seqno = 0; vg->status = (RESIZEABLE_VG | LVM_READ | LVM_WRITE); - if (!(vg->system_id = dm_pool_alloc(mem, NAME_LEN))) { - stack; - goto bad; - } + if (!(vg->system_id = dm_pool_alloc(mem, NAME_LEN))) + goto_bad; + *vg->system_id = '\0'; vg->extent_size = extent_size; @@ -320,7 +319,7 @@ struct volume_group *vg_create(struct cmd_context *cmd, const char *vg_name, /* attach the pv's */ if (!vg_extend(vg->fid, vg, pv_count, pv_names)) - goto bad; + goto_bad; return vg; @@ -561,10 +560,8 @@ struct physical_volume *pv_create(const struct format_type *fmt, pv->dev = dev; - if (!(pv->vg_name = dm_pool_zalloc(mem, NAME_LEN))) { - stack; - goto bad; - } + if (!(pv->vg_name = dm_pool_zalloc(mem, NAME_LEN))) + goto_bad; pv->status = ALLOCATABLE_PV; diff --git a/lib/misc/lvm-file.c b/lib/misc/lvm-file.c index c1ec8e30..d2c5f3d5 100644 --- a/lib/misc/lvm-file.c +++ b/lib/misc/lvm-file.c @@ -273,8 +273,12 @@ int fcntl_lock_file(const char *file, short lock_type, int warn_if_read_only) if ((c = strrchr(dir, '/'))) *c = '\0'; - if (!create_dir(dir)) + if (!create_dir(dir)) { + dm_free(dir); return -1; + } + + dm_free(dir); log_very_verbose("Locking %s (%s, %hd)", file, (lock_type == F_WRLCK) ? "F_WRLCK" : "F_RDLCK", diff --git a/lib/regex/matcher.c b/lib/regex/matcher.c index a21e253e..b26b33c1 100644 --- a/lib/regex/matcher.c +++ b/lib/regex/matcher.c @@ -273,15 +273,12 @@ struct matcher *matcher_create(struct dm_pool *mem, const char **patterns, struct dm_pool *scratch = dm_pool_create("regex matcher", 10 * 1024); struct matcher *m; - if (!scratch) { - stack; - return NULL; - } + if (!scratch) + return_NULL; if (!(m = dm_pool_alloc(mem, sizeof(*m)))) { - stack; dm_pool_destroy(scratch); - return NULL; + return_NULL; } memset(m, 0, sizeof(*m)); @@ -292,10 +289,8 @@ struct matcher *matcher_create(struct dm_pool *mem, const char **patterns, ptr = all = dm_pool_alloc(scratch, len + 1); - if (!all) { - stack; - goto bad; - } + if (!all) + goto_bad; for (i = 0; i < num; i++) { ptr += sprintf(ptr, "(.*(%s)%c)", patterns[i], TARGET_TRANS); @@ -314,10 +309,8 @@ struct matcher *matcher_create(struct dm_pool *mem, const char **patterns, m->num_nodes = _count_nodes(rx); m->nodes = dm_pool_alloc(scratch, sizeof(*m->nodes) * m->num_nodes); - if (!m->nodes) { - stack; - goto bad; - } + if (!m->nodes) + goto_bad; _fill_table(m, rx); _create_bitsets(m); @@ -330,7 +323,7 @@ struct matcher *matcher_create(struct dm_pool *mem, const char **patterns, bad: dm_pool_destroy(scratch); - dm_pool_destroy(mem); + dm_pool_free(mem, m); return NULL; } diff --git a/tools/lvmcmdline.c b/tools/lvmcmdline.c index 50cc9468..390771e2 100644 --- a/tools/lvmcmdline.c +++ b/tools/lvmcmdline.c @@ -827,30 +827,30 @@ static char *_copy_command_line(struct cmd_context *cmd, int argc, char **argv) * description for backups. */ if (!dm_pool_begin_object(cmd->mem, 128)) - goto bad; + goto_bad; for (i = 0; i < argc; i++) { space = strchr(argv[i], ' ') ? 1 : 0; if (space && !dm_pool_grow_object(cmd->mem, "'", 1)) - goto bad; + goto_bad; if (!dm_pool_grow_object(cmd->mem, argv[i], strlen(argv[i]))) - goto bad; + goto_bad; if (space && !dm_pool_grow_object(cmd->mem, "'", 1)) - goto bad; + goto_bad; if (i < (argc - 1)) if (!dm_pool_grow_object(cmd->mem, " ", 1)) - goto bad; + goto_bad; } /* * Terminate. */ if (!dm_pool_grow_object(cmd->mem, "\0", 1)) - goto bad; + goto_bad; return dm_pool_end_object(cmd->mem); |