1
0
mirror of git://sourceware.org/git/lvm2.git synced 2024-12-21 13:34:40 +03:00

Fix default dmsetup report buffering and add --unbuffered.

Add tree-based and dependency fields to dmsetup reports.
This commit is contained in:
Alasdair Kergon 2007-06-15 18:20:28 +00:00
parent 1471bc871b
commit 117d85978a
2 changed files with 257 additions and 4 deletions

View File

@ -1,6 +1,7 @@
Version 1.02.20 - Version 1.02.20 -
================================= =================================
Add capability for tree-based fields to dmsetup reports. Fix default dmsetup report buffering and add --unbuffered.
Add tree-based and dependency fields to dmsetup reports.
Version 1.02.19 - 27th April 2007 Version 1.02.19 - 27th April 2007
================================= =================================

View File

@ -90,6 +90,11 @@ extern char *optarg;
#define ARGS_MAX 256 #define ARGS_MAX 256
#define LOOP_TABLE_SIZE (PATH_MAX + 255) #define LOOP_TABLE_SIZE (PATH_MAX + 255)
/* FIXME Should be imported */
#ifndef DM_MAX_TYPE_NAME
# define DM_MAX_TYPE_NAME 16
#endif
/* FIXME Should be elsewhere */ /* FIXME Should be elsewhere */
#define SECTOR_SHIFT 9L #define SECTOR_SHIFT 9L
#define DEV_PATH "/dev/" #define DEV_PATH "/dev/"
@ -121,6 +126,7 @@ enum {
TARGET_ARG, TARGET_ARG,
TREE_ARG, TREE_ARG,
UID_ARG, UID_ARG,
UNBUFFERED_ARG,
UUID_ARG, UUID_ARG,
VERBOSE_ARG, VERBOSE_ARG,
VERSION_ARG, VERSION_ARG,
@ -130,6 +136,7 @@ enum {
typedef enum { typedef enum {
DR_TASK = 1, DR_TASK = 1,
DR_INFO = 2, DR_INFO = 2,
DR_DEPS = 4,
DR_TREE = 8 /* Complete dependency tree required */ DR_TREE = 8 /* Complete dependency tree required */
} report_type_t; } report_type_t;
@ -247,9 +254,41 @@ static int _parse_file(struct dm_task *dmt, const char *file)
struct dmsetup_report_obj { struct dmsetup_report_obj {
struct dm_task *task; struct dm_task *task;
struct dm_info *info; struct dm_info *info;
struct dm_task *deps_task;
struct dm_tree_node *tree_node; struct dm_tree_node *tree_node;
}; };
static struct dm_task *_get_deps_task(int major, int minor)
{
struct dm_task *dmt;
struct dm_info info;
if (!(dmt = dm_task_create(DM_DEVICE_DEPS)))
return NULL;
if (!dm_task_set_major(dmt, major) ||
!dm_task_set_minor(dmt, minor))
goto err;
if (_switches[NOOPENCOUNT_ARG] && !dm_task_no_open_count(dmt))
goto err;
if (!dm_task_run(dmt))
goto err;
if (!dm_task_get_info(dmt, &info))
goto err;
if (!info.exists)
goto err;
return dmt;
err:
dm_task_destroy(dmt);
return NULL;
}
static int _display_info_cols(struct dm_task *dmt, struct dm_info *info) static int _display_info_cols(struct dm_task *dmt, struct dm_info *info)
{ {
struct dmsetup_report_obj obj; struct dmsetup_report_obj obj;
@ -262,16 +301,22 @@ static int _display_info_cols(struct dm_task *dmt, struct dm_info *info)
obj.task = dmt; obj.task = dmt;
obj.info = info; obj.info = info;
obj.deps_task = NULL;
if (_report_type & DR_TREE) if (_report_type & DR_TREE)
obj.tree_node = dm_tree_find_node(_dtree, info->major, info->minor); obj.tree_node = dm_tree_find_node(_dtree, info->major, info->minor);
if (_report_type & DR_DEPS)
obj.deps_task = _get_deps_task(info->major, info->minor);
if (!dm_report_object(_report, &obj)) if (!dm_report_object(_report, &obj))
goto out; goto out;
r = 1; r = 1;
out: out:
if (obj.deps_task)
dm_task_destroy(obj.deps_task);
return r; return r;
} }
@ -1566,6 +1611,149 @@ static int _dm_info_status_disp(struct dm_report *rh,
return dm_report_field_string(rh, field, &s); return dm_report_field_string(rh, field, &s);
} }
static int _dm_info_devno_disp(struct dm_report *rh, struct dm_pool *mem,
struct dm_report_field *field, const void *data,
void *private)
{
char buf[DM_MAX_TYPE_NAME], *repstr;
struct dm_info *info = (struct dm_info *) data;
if (!dm_pool_begin_object(mem, 8)) {
log_error("dm_pool_begin_object failed");
return 0;
}
if (dm_snprintf(buf, sizeof(buf), "%d:%d",
info->major, info->minor) < 0) {
log_error("dm_pool_alloc failed");
goto out_abandon;
}
if (!dm_pool_grow_object(mem, buf, strlen(buf))) {
log_error("dm_pool_grow_object failed");
goto out_abandon;
}
repstr = dm_pool_end_object(mem);
dm_report_field_set_value(field, repstr, repstr);
return 1;
out_abandon:
dm_pool_abandon_object(mem);
return 0;
}
static int _dm_tree_names(struct dm_report *rh, struct dm_pool *mem,
struct dm_report_field *field, const void *data,
void *private, unsigned inverted)
{
struct dm_tree_node *node = (struct dm_tree_node *) data, *parent;
void *t = NULL;
const char *name;
int first_node = 1;
char *repstr;
if (!dm_pool_begin_object(mem, 16)) {
log_error("dm_pool_begin_object failed");
return 0;
}
while ((parent = dm_tree_next_child(&t, node, inverted))) {
name = dm_tree_node_get_name(parent);
if (!name || !*name)
continue;
if (!first_node && !dm_pool_grow_object(mem, ",", 1)) {
log_error("dm_pool_grow_object failed");
goto out_abandon;
}
if (!dm_pool_grow_object(mem, name, strlen(name))) {
log_error("dm_pool_grow_object failed");
goto out_abandon;
}
if (first_node)
first_node = 0;
}
if (!dm_pool_grow_object(mem, "\0", 1)) {
log_error("dm_pool_grow_object failed");
goto out_abandon;
}
repstr = dm_pool_end_object(mem);
dm_report_field_set_value(field, repstr, repstr);
return 1;
out_abandon:
dm_pool_abandon_object(mem);
return 0;
}
static int _dm_deps_names_disp(struct dm_report *rh,
struct dm_pool *mem,
struct dm_report_field *field,
const void *data, void *private)
{
return _dm_tree_names(rh, mem, field, data, private, 0);
}
static int _dm_tree_parents_names_disp(struct dm_report *rh,
struct dm_pool *mem,
struct dm_report_field *field,
const void *data, void *private)
{
return _dm_tree_names(rh, mem, field, data, private, 1);
}
static int _dm_tree_parents_devs_disp(struct dm_report *rh, struct dm_pool *mem,
struct dm_report_field *field,
const void *data, void *private)
{
struct dm_tree_node *node = (struct dm_tree_node *) data, *parent;
void *t = NULL;
const struct dm_info *info;
int first_node = 1;
char buf[DM_MAX_TYPE_NAME], *repstr;
if (!dm_pool_begin_object(mem, 16)) {
log_error("dm_pool_begin_object failed");
return 0;
}
while ((parent = dm_tree_next_child(&t, node, 1))) {
info = dm_tree_node_get_info(parent);
if (!info->major && !info->minor)
continue;
if (!first_node && !dm_pool_grow_object(mem, ",", 1)) {
log_error("dm_pool_grow_object failed");
goto out_abandon;
}
if (dm_snprintf(buf, sizeof(buf), "%d:%d",
info->major, info->minor) < 0) {
log_error("dm_snprintf failed");
goto out_abandon;
}
if (!dm_pool_grow_object(mem, buf, strlen(buf))) {
log_error("dm_pool_grow_object failed");
goto out_abandon;
}
if (first_node)
first_node = 0;
}
if (!dm_pool_grow_object(mem, "\0", 1)) {
log_error("dm_pool_grow_object failed");
goto out_abandon;
}
repstr = dm_pool_end_object(mem);
dm_report_field_set_value(field, repstr, repstr);
return 1;
out_abandon:
dm_pool_abandon_object(mem);
return 0;
}
static int _dm_tree_parents_count_disp(struct dm_report *rh, static int _dm_tree_parents_count_disp(struct dm_report *rh,
struct dm_pool *mem, struct dm_pool *mem,
struct dm_report_field *field, struct dm_report_field *field,
@ -1577,6 +1765,50 @@ static int _dm_tree_parents_count_disp(struct dm_report *rh,
return dm_report_field_int(rh, field, &num_parent); return dm_report_field_int(rh, field, &num_parent);
} }
static int _dm_deps_disp(struct dm_report *rh, struct dm_pool *mem,
struct dm_report_field *field, const void *data,
void *private)
{
struct dm_deps *deps = (struct dm_deps *) data;
int i;
char buf[DM_MAX_TYPE_NAME], *repstr;
if (!dm_pool_begin_object(mem, 16)) {
log_error("dm_pool_begin_object failed");
return 0;
}
for (i = 0; i < deps->count; i++) {
if (dm_snprintf(buf, sizeof(buf), "%d:%d",
(int) MAJOR(deps->device[i]),
(int) MINOR(deps->device[i])) < 0) {
log_error("dm_snprintf failed");
goto out_abandon;
}
if (!dm_pool_grow_object(mem, buf, strlen(buf))) {
log_error("dm_pool_grow_object failed");
goto out_abandon;
}
if (i + 1 < deps->count && !dm_pool_grow_object(mem, ",", 1)) {
log_error("dm_pool_grow_object failed");
goto out_abandon;
}
}
if (!dm_pool_grow_object(mem, "\0", 1)) {
log_error("dm_pool_grow_object failed");
goto out_abandon;
}
repstr = dm_pool_end_object(mem);
dm_report_field_set_value(field, repstr, repstr);
return 1;
out_abandon:
dm_pool_abandon_object(mem);
return 0;
}
static void *_task_get_obj(void *obj) static void *_task_get_obj(void *obj)
{ {
return ((struct dmsetup_report_obj *)obj)->task; return ((struct dmsetup_report_obj *)obj)->task;
@ -1587,6 +1819,11 @@ static void *_info_get_obj(void *obj)
return ((struct dmsetup_report_obj *)obj)->info; return ((struct dmsetup_report_obj *)obj)->info;
} }
static void *_deps_get_obj(void *obj)
{
return dm_task_get_deps(((struct dmsetup_report_obj *)obj)->deps_task);
}
static void *_tree_get_obj(void *obj) static void *_tree_get_obj(void *obj)
{ {
return ((struct dmsetup_report_obj *)obj)->tree_node; return ((struct dmsetup_report_obj *)obj)->tree_node;
@ -1595,7 +1832,8 @@ static void *_tree_get_obj(void *obj)
static const struct dm_report_object_type _report_types[] = { static const struct dm_report_object_type _report_types[] = {
{ DR_TASK, "Mapped Device Name", "", _task_get_obj }, { DR_TASK, "Mapped Device Name", "", _task_get_obj },
{ DR_INFO, "Mapped Device Information", "", _info_get_obj }, { DR_INFO, "Mapped Device Information", "", _info_get_obj },
{ DR_TREE, "Mapped Device Dependency", "", _tree_get_obj }, { DR_DEPS, "Mapped Device Relationship Information", "", _deps_get_obj },
{ DR_TREE, "Mapped Device Relationship Information", "", _tree_get_obj },
{ 0, "", "", NULL }, { 0, "", "", NULL },
}; };
@ -1611,12 +1849,20 @@ static const struct dm_report_field_type _report_fields[] = {
FIELD_F(TASK, STR, "Name", 16, dm_name, "name", "Name of mapped device.") FIELD_F(TASK, STR, "Name", 16, dm_name, "name", "Name of mapped device.")
FIELD_F(TASK, STR, "UUID", 32, dm_uuid, "uuid", "Unique (optional) identifier for mapped device.") FIELD_F(TASK, STR, "UUID", 32, dm_uuid, "uuid", "Unique (optional) identifier for mapped device.")
FIELD_F(INFO, STR, "Stat", 4, dm_info_status, "attr", "(L)ive, (I)nactive, (s)uspended, (r)ead-only, read-(w)rite.") FIELD_F(INFO, STR, "Stat", 4, dm_info_status, "attr", "(L)ive, (I)nactive, (s)uspended, (r)ead-only, read-(w)rite.")
FIELD_F(INFO, STR, "DevNo", 5, dm_info_devno, "devno", "Device major and minor numbers")
FIELD_O(INFO, dm_info, NUM, "Maj", major, 3, int32, "major", "Block device major number.") FIELD_O(INFO, dm_info, NUM, "Maj", major, 3, int32, "major", "Block device major number.")
FIELD_O(INFO, dm_info, NUM, "Min", minor, 3, int32, "minor", "Block device minor number.") FIELD_O(INFO, dm_info, NUM, "Min", minor, 3, int32, "minor", "Block device minor number.")
FIELD_O(INFO, dm_info, NUM, "Open", open_count, 4, int32, "open", "Number of references to open device, if requested.") FIELD_O(INFO, dm_info, NUM, "Open", open_count, 4, int32, "open", "Number of references to open device, if requested.")
FIELD_O(INFO, dm_info, NUM, "Targ", target_count, 4, int32, "segments", "Number of segments in live table, if present.") FIELD_O(INFO, dm_info, NUM, "Targ", target_count, 4, int32, "segments", "Number of segments in live table, if present.")
FIELD_O(INFO, dm_info, NUM, "Event", event_nr, 6, uint32, "events", "Number of most recent event.") FIELD_O(INFO, dm_info, NUM, "Event", event_nr, 6, uint32, "events", "Number of most recent event.")
FIELD_F(TREE, NUM, "#DevsUsing", 10, dm_tree_parents_count, "devs_using_count", "Number of devices using this one.")
FIELD_O(DEPS, dm_deps, NUM, "#Devs", count, 5, int32, "device_count", "Number of devices used by this one.")
FIELD_F(TREE, STR, "DevNames", 8, dm_deps_names, "devs_used", "List of names of mapped devices used by this one.")
FIELD_F(DEPS, STR, "DevNos", 6, dm_deps, "devnos_used", "List of device numbers of devices used by this one.")
FIELD_F(TREE, NUM, "#Refs", 5, dm_tree_parents_count, "device_ref_count", "Number of mapped devices referencing this one.")
FIELD_F(TREE, STR, "RefNames", 8, dm_tree_parents_names, "names_using_dev", "List of names of mapped devices using this one.")
FIELD_F(TREE, STR, "RefDevNos", 9, dm_tree_parents_devs, "devnos_using_dev", "List of device numbers of mapped devices using this one.")
{0, 0, 0, 0, "", "", NULL, NULL}, {0, 0, 0, 0, "", "", NULL, NULL},
/* *INDENT-ON* */ /* *INDENT-ON* */
}; };
@ -1633,7 +1879,7 @@ static int _report_init(struct command *c)
char *options = (char *) default_report_options; char *options = (char *) default_report_options;
const char *keys = ""; const char *keys = "";
const char *separator = " "; const char *separator = " ";
int aligned = 1, headings = 1, buffered = 0; int aligned = 1, headings = 1, buffered = 1;
uint32_t flags = 0; uint32_t flags = 0;
size_t len = 0; size_t len = 0;
int r = 0; int r = 0;
@ -1645,6 +1891,9 @@ static int _report_init(struct command *c)
headings = 0; headings = 0;
} }
if (_switches[UNBUFFERED_ARG])
buffered = 0;
if (_switches[OPTIONS_ARG] && _string_args[OPTIONS_ARG]) { if (_switches[OPTIONS_ARG] && _string_args[OPTIONS_ARG]) {
if (*_string_args[OPTIONS_ARG] != '+') if (*_string_args[OPTIONS_ARG] != '+')
options = _string_args[OPTIONS_ARG]; options = _string_args[OPTIONS_ARG];
@ -2125,6 +2374,7 @@ static int _process_switches(int *argc, char ***argv)
{"tree", 0, &ind, TREE_ARG}, {"tree", 0, &ind, TREE_ARG},
{"uid", 1, &ind, UID_ARG}, {"uid", 1, &ind, UID_ARG},
{"uuid", 1, &ind, UUID_ARG}, {"uuid", 1, &ind, UUID_ARG},
{"unbuffered", 0, &ind, UNBUFFERED_ARG},
{"verbose", 1, &ind, VERBOSE_ARG}, {"verbose", 1, &ind, VERBOSE_ARG},
{"version", 0, &ind, VERSION_ARG}, {"version", 0, &ind, VERSION_ARG},
{0, 0, 0, 0} {0, 0, 0, 0}
@ -2256,6 +2506,8 @@ static int _process_switches(int *argc, char ***argv)
} }
if ((ind == TREE_ARG)) if ((ind == TREE_ARG))
_switches[TREE_ARG]++; _switches[TREE_ARG]++;
if ((ind == UNBUFFERED_ARG))
_switches[UNBUFFERED_ARG]++;
if ((ind == VERSION_ARG)) if ((ind == VERSION_ARG))
_switches[VERSION_ARG]++; _switches[VERSION_ARG]++;
} }