1
0
mirror of git://sourceware.org/git/lvm2.git synced 2025-09-27 05:44:18 +03:00

Compare commits

...

1 Commits

Author SHA1 Message Date
Alasdair G Kergon
60e50072e5 report: Demo mount/fs fields a bit like df.
./lvm pvs -a -opv_name,fs_size,fs_used,fs_free,mount_all -S 'fs_size>0' --units k

./lvm pvs -a -opv_name,fs_size,fs_used,fs_free,fs_avail,mount_all -S
'fs_size>0' --units b --reportformat json --nosuffix
2017-03-08 14:57:35 +00:00
5 changed files with 200 additions and 19 deletions

View File

@@ -283,4 +283,26 @@ FIELD(PVSEGS, pvseg, NUM, "SSize", len, 0, uint32, pvseg_size, "Number of extent
/*
* End of PVSEGS type fields
*/
/*
* MOUNTINFO type fields
*/
FIELD(MOUNTINFO, mountinfo, STR, "Mounted on", mountpoint, 0, string, mount_point, "Mount point of filesystem on device.", 0)
/*
* End of MOUNTINFO type fields
*/
/*
* FSINFO type fields
*/
FIELD(FSINFO, fsinfo, SIZ, "FSUsed", fs_used, 0, size64, fs_used, "Space used in mounted filesystem on device.", 0)
FIELD(FSINFO, fsinfo, SIZ, "FSSize", fs_size, 0, size64, fs_size, "Size of mounted filesystem on device.", 0)
FIELD(FSINFO, fsinfo, SIZ, "FSFree", fs_free, 0, size64, fs_free, "Free space in mounted filesystem on device.", 0)
FIELD(FSINFO, fsinfo, SIZ, "FSAvail", fs_avail, 0, size64, fs_avail, "Available space in mounted filesystem on device.", 0)
/*
* End of FSINFO type fields
*/
/* *INDENT-ON* */

View File

@@ -520,6 +520,16 @@ GET_PVSEG_NUM_PROPERTY_FN(pvseg_start, pvseg->pe)
GET_PVSEG_NUM_PROPERTY_FN(pvseg_size, (SECTOR_SIZE * pvseg->len))
#define _pvseg_size_set prop_not_implemented_set
#define _mount_point_get prop_not_implemented_get
#define _mount_point_set prop_not_implemented_set
#define _fs_used_get prop_not_implemented_get
#define _fs_used_set prop_not_implemented_set
#define _fs_size_get prop_not_implemented_get
#define _fs_size_set prop_not_implemented_set
#define _fs_free_get prop_not_implemented_get
#define _fs_free_set prop_not_implemented_set
#define _fs_avail_get prop_not_implemented_get
#define _fs_avail_set prop_not_implemented_set
struct lvm_property_type _properties[] = {
#include "columns.h"

View File

@@ -36,6 +36,8 @@ struct lvm_report_object {
struct lv_segment *seg;
struct pv_segment *pvseg;
struct label *label;
struct lvm_mountinfo *mountinfo;
struct lvm_fsinfo *fsinfo;
};
static uint32_t log_seqnum = 1;
@@ -3791,6 +3793,13 @@ static struct volume_group _unknown_vg = {
.tags = DM_LIST_HEAD_INIT(_unknown_vg.tags),
};
static struct lvm_mountinfo _unknown_mountinfo = {
.mountpoint = ""
};
static struct lvm_fsinfo _unknown_fsinfo = {
};
static void *_obj_get_vg(void *obj)
{
struct volume_group *vg = ((struct lvm_report_object *)obj)->vg;
@@ -3828,6 +3837,16 @@ static void *_obj_get_pvseg(void *obj)
return ((struct lvm_report_object *)obj)->pvseg;
}
static void *_obj_get_mountinfo(void *obj)
{
return ((struct lvm_report_object *)obj)->mountinfo;
}
static void *_obj_get_fsinfo(void *obj)
{
return ((struct lvm_report_object *)obj)->fsinfo;
}
static void *_obj_get_devtypes(void *obj)
{
return obj;
@@ -3853,6 +3872,8 @@ static const struct dm_report_object_type _report_types[] = {
{ LABEL, "Physical Volume Label", "pv_", _obj_get_label },
{ SEGS, "Logical Volume Segment", "seg_", _obj_get_seg },
{ PVSEGS, "Physical Volume Segment", "pvseg_", _obj_get_pvseg },
{ MOUNTINFO, "Mount Point", "mount_", _obj_get_mountinfo },
{ FSINFO, "Filesystem", "fs_", _obj_get_fsinfo },
{ 0, "", "", NULL },
};
@@ -3885,6 +3906,8 @@ typedef struct volume_group type_vg;
typedef struct lv_segment type_seg;
typedef struct pv_segment type_pvseg;
typedef struct label type_label;
typedef struct lvm_mountinfo type_mountinfo;
typedef struct lvm_fsinfo type_fsinfo;
typedef dev_known_type_t type_devtype;
@@ -4012,7 +4035,8 @@ int report_object(void *handle, int selection_only, const struct volume_group *v
const struct logical_volume *lv, const struct physical_volume *pv,
const struct lv_segment *seg, const struct pv_segment *pvseg,
const struct lv_with_info_and_seg_status *lvdm,
const struct label *label)
const struct label *label,
const struct lvm_mountinfo *mountinfo, const struct lvm_fsinfo *fsinfo)
{
struct selection_handle *sh = selection_only ? (struct selection_handle *) handle : NULL;
struct device dummy_device = { .dev = 0 };
@@ -4023,7 +4047,9 @@ int report_object(void *handle, int selection_only, const struct volume_group *v
.pv = (struct physical_volume *) pv,
.seg = (struct lv_segment *) seg,
.pvseg = (struct pv_segment *) pvseg,
.label = (struct label *) (label ? : (pv ? pv_label(pv) : NULL))
.label = (struct label *) (label ? : (pv ? pv_label(pv) : NULL)),
.mountinfo = (struct lvm_mountinfo *) mountinfo ? : &_unknown_mountinfo,
.fsinfo = (struct lvm_fsinfo *) fsinfo ? : &_unknown_fsinfo,
};
/* FIXME workaround for pv_label going through cache; remove once struct

View File

@@ -32,9 +32,22 @@ typedef enum {
SEGS = 256,
PVSEGS = 512,
LABEL = 1024,
DEVTYPES = 2048
DEVTYPES = 2048,
MOUNTINFO = 4096,
FSINFO = 8192
} report_type_t;
struct lvm_mountinfo {
const char *mountpoint;
};
struct lvm_fsinfo {
uint64_t fs_used;
uint64_t fs_size;
uint64_t fs_free;
uint64_t fs_avail;
};
/*
* The "struct selection_handle" is used only for selection
* of items that should be processed further (not for display!).
@@ -104,7 +117,8 @@ int report_object(void *handle, int selection_only, const struct volume_group *v
const struct logical_volume *lv, const struct physical_volume *pv,
const struct lv_segment *seg, const struct pv_segment *pvseg,
const struct lv_with_info_and_seg_status *lvdm,
const struct label *label);
const struct label *label,
const struct lvm_mountinfo *mountinfo, const struct lvm_fsinfo *fsinfo);
int report_devtypes(void *handle);
int report_cmdlog(void *handle, const char *type, const char *context,
const char *object_type_name, const char *object_name,

View File

@@ -17,6 +17,8 @@
#include "report.h"
#include <sys/vfs.h>
typedef enum {
REPORT_IDX_NULL = -1,
REPORT_IDX_SINGLE,
@@ -79,7 +81,7 @@ static int _vgs_single(struct cmd_context *cmd __attribute__((unused)),
struct selection_handle *sh = handle->selection_handle;
if (!report_object(sh ? : handle->custom_handle, sh != NULL,
vg, NULL, NULL, NULL, NULL, NULL, NULL))
vg, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL))
return_ECMD_FAILED;
check_current_backup(vg);
@@ -177,7 +179,7 @@ static int _do_lvs_with_info_and_status_single(struct cmd_context *cmd,
}
if (!report_object(sh ? : handle->custom_handle, sh != NULL,
lv->vg, lv, NULL, NULL, NULL, &status, NULL))
lv->vg, lv, NULL, NULL, NULL, &status, NULL, NULL, NULL))
goto out;
r = ECMD_PROCESSED;
@@ -239,7 +241,7 @@ static int _do_segs_with_info_and_status_single(struct cmd_context *cmd,
}
if (!report_object(sh ? : handle->custom_handle, sh != NULL,
seg->lv->vg, seg->lv, NULL, seg, NULL, &status, NULL))
seg->lv->vg, seg->lv, NULL, seg, NULL, &status, NULL, NULL, NULL))
goto_out;
r = ECMD_PROCESSED;
@@ -367,7 +369,7 @@ static int _do_pvsegs_sub_single(struct cmd_context *cmd,
if (!report_object(sh ? : handle->custom_handle, sh != NULL,
vg, seg ? seg->lv : &_free_logical_volume,
pvseg->pv, seg ? : &_free_lv_segment, pvseg,
&status, pv_label(pvseg->pv))) {
&status, pv_label(pvseg->pv), NULL, NULL)) {
ret = ECMD_FAILED;
goto_out;
}
@@ -443,17 +445,101 @@ static int _pvsegs_with_lv_info_and_status_single(struct cmd_context *cmd,
return process_each_segment_in_pv(cmd, vg, pv, handle, _pvsegs_with_lv_info_and_status_sub_single);
}
struct mountinfo_s { // FIXME
unsigned maj; //FIXME
unsigned min; //FIXME
const char *mountpoint;
};
static int _get_mountpoint(char *buffer, unsigned major, unsigned minor,
char *target, void *cb_data)
{
struct mountinfo_s *data = cb_data;
if ((major == data->maj) && (minor == data->min))
data->mountpoint = dm_strdup(target); // FIXME error/pool
return 1;
}
static int _populate_mount_info(struct physical_volume *pv, struct lvm_mountinfo *mountinfo)
{
struct mountinfo_s data = {
.maj = MAJOR(pv->dev->dev),
.min = MINOR(pv->dev->dev),
};
if (!dm_mountinfo_read(_get_mountpoint, &data))
return 0;
if (data.mountpoint)
mountinfo->mountpoint = data.mountpoint;
else
mountinfo->mountpoint = "";
return 1;
}
static int _populate_fs_info(const char *mountpoint, struct lvm_fsinfo *fsinfo)
{
struct statfs buf;
if (statfs(mountpoint, &buf)) {
log_sys_error("statfs", mountpoint);
return 0;
}
fsinfo->fs_size = (buf.f_blocks * buf.f_bsize) >> SECTOR_SHIFT;
fsinfo->fs_free = (buf.f_bfree * buf.f_bsize) >> SECTOR_SHIFT;
fsinfo->fs_avail = (buf.f_bavail * buf.f_bsize) >> SECTOR_SHIFT;
fsinfo->fs_used = ((buf.f_blocks - buf.f_bfree) * buf.f_bsize) >> SECTOR_SHIFT;
return 1;
}
static int _do_pvs_with_mount_and_fs_info_single(struct cmd_context *cmd, struct volume_group *vg,
struct physical_volume *pv,
struct processing_handle *handle,
int do_mount_info, int do_fs_info)
{
struct selection_handle *sh = handle->selection_handle;
struct lvm_mountinfo mountinfo;
struct lvm_fsinfo fsinfo;
if (do_mount_info)
if (!_populate_mount_info(pv, &mountinfo))
return_0;
if (do_fs_info && *mountinfo.mountpoint)
if (!_populate_fs_info(mountinfo.mountpoint, &fsinfo))
return_0;
if (!report_object(sh ? : handle->custom_handle, sh != NULL,
vg, NULL, pv, NULL, NULL, NULL, NULL, do_mount_info ? &mountinfo : NULL, do_fs_info && *mountinfo.mountpoint ? &fsinfo : NULL))
return_ECMD_FAILED;
return ECMD_PROCESSED;
}
static int _pvs_single(struct cmd_context *cmd, struct volume_group *vg,
struct physical_volume *pv,
struct processing_handle *handle)
{
struct selection_handle *sh = handle->selection_handle;
return _do_pvs_with_mount_and_fs_info_single(cmd, vg, pv, handle, 0, 0);
}
if (!report_object(sh ? : handle->custom_handle, sh != NULL,
vg, NULL, pv, NULL, NULL, NULL, NULL))
return_ECMD_FAILED;
static int _pvs_with_mount_info_single(struct cmd_context *cmd, struct volume_group *vg,
struct physical_volume *pv,
struct processing_handle *handle)
{
return _do_pvs_with_mount_and_fs_info_single(cmd, vg, pv, handle, 1, 0);
}
return ECMD_PROCESSED;
static int _pvs_with_fs_info_single(struct cmd_context *cmd, struct volume_group *vg,
struct physical_volume *pv,
struct processing_handle *handle)
{
return _do_pvs_with_mount_and_fs_info_single(cmd, vg, pv, handle, 1, 1);
}
static int _label_single(struct cmd_context *cmd, struct label *label,
@@ -462,7 +548,7 @@ static int _label_single(struct cmd_context *cmd, struct label *label,
struct selection_handle *sh = handle->selection_handle;
if (!report_object(sh ? : handle->custom_handle, sh != NULL,
NULL, NULL, NULL, NULL, NULL, NULL, label))
NULL, NULL, NULL, NULL, NULL, NULL, label, NULL, NULL))
return_ECMD_FAILED;
return ECMD_PROCESSED;
@@ -487,6 +573,8 @@ static int _get_final_report_type(struct report_args *args,
report_type_t report_type,
int *lv_info_needed,
int *lv_segment_status_needed,
int *mountinfo_needed,
int *fsinfo_needed,
report_type_t *final_report_type)
{
/* Do we need to acquire LV device info in addition? */
@@ -498,8 +586,16 @@ static int _get_final_report_type(struct report_args *args,
/* Ensure options selected are compatible */
if (report_type & SEGS)
report_type |= LVS;
if (report_type & PVSEGS)
report_type |= PVS;
if (report_type & FSINFO)
report_type |= MOUNTINFO;
if (report_type & MOUNTINFO)
report_type |= PVS; // FIXME Temporarily drive fs and mount from pvs
if ((report_type & (LVS | LVSINFO | LVSSTATUS | LVSINFOSTATUS)) &&
(report_type & (PVS | LABEL)) && !(single_args->args_are_pvs || (args->full_report_vg && single_args->report_type == PVSEGS))) {
log_error("Can't report LV and PV fields at the same time in %sreport type \"%s\"%s%s.",
@@ -509,6 +605,12 @@ static int _get_final_report_type(struct report_args *args,
return 0;
}
/* Do we need to acquire mount point information? */
*mountinfo_needed = (report_type & MOUNTINFO) ? 1 : 0;
/* Do we need to acquire mounted filesystem information? */
*fsinfo_needed = (report_type & FSINFO) ? 1 : 0;
/* Change report type if fields specified makes this necessary */
if (report_type & FULL)
report_type = FULL;
@@ -603,7 +705,7 @@ static int _report_all_in_lv(struct cmd_context *cmd, struct processing_handle *
static int _report_all_in_pv(struct cmd_context *cmd, struct processing_handle *handle,
struct physical_volume *pv, report_type_t type,
int do_lv_info, int do_lv_seg_status)
int do_lv_info, int do_lv_seg_status, int do_mount_info, int do_fs_info)
{
int r = 0;
@@ -635,7 +737,7 @@ int report_for_selection(struct cmd_context *cmd,
struct selection_handle *sh = parent_handle->selection_handle;
struct report_args args = {0};
struct single_report_args *single_args = &args.single_args[REPORT_IDX_SINGLE];
int do_lv_info, do_lv_seg_status;
int do_lv_info, do_lv_seg_status, do_mount_info, do_fs_info;
struct processing_handle *handle;
int r = 0;
@@ -645,6 +747,7 @@ int report_for_selection(struct cmd_context *cmd,
if (!_get_final_report_type(&args, single_args,
single_args->report_type,
&do_lv_info, &do_lv_seg_status,
&do_mount_info, &do_fs_info,
&sh->report_type))
return_0;
@@ -688,7 +791,7 @@ int report_for_selection(struct cmd_context *cmd,
r = _report_all_in_vg(cmd, handle, vg, sh->report_type, do_lv_info, do_lv_seg_status);
break;
case PVS:
r = _report_all_in_pv(cmd, handle, pv, sh->report_type, do_lv_info, do_lv_seg_status);
r = _report_all_in_pv(cmd, handle, pv, sh->report_type, do_lv_info, do_lv_seg_status, do_mount_info, do_fs_info);
break;
default:
log_error(INTERNAL_ERROR "report_for_selection: incorrect report type");
@@ -1079,6 +1182,7 @@ static int _do_report(struct cmd_context *cmd, struct processing_handle *handle,
int lock_global = 0;
int lv_info_needed;
int lv_segment_status_needed;
int do_mount_info, do_fs_info;
int report_in_group = 0;
int r = ECMD_FAILED;
@@ -1091,7 +1195,9 @@ static int _do_report(struct cmd_context *cmd, struct processing_handle *handle,
handle->custom_handle = report_handle;
if (!_get_final_report_type(args, single_args, report_type, &lv_info_needed,
&lv_segment_status_needed, &report_type))
&lv_segment_status_needed,
&do_mount_info, &do_fs_info,
&report_type))
goto_out;
if (!(args->log_only && (single_args->report_type != CMDLOG))) {
@@ -1151,7 +1257,10 @@ static int _do_report(struct cmd_context *cmd, struct processing_handle *handle,
if (single_args->args_are_pvs)
r = process_each_pv(cmd, args->argc, args->argv, NULL,
arg_is_set(cmd, all_ARG), 0,
handle, &_pvs_single);
handle,
do_fs_info ? &_pvs_with_fs_info_single :
do_mount_info ? &_pvs_with_mount_info_single :
&_pvs_single);
else
r = process_each_vg(cmd, args->argc, args->argv, NULL, NULL,
0, 0, handle, &_pvs_in_vg);