4 * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
5 * Copyright (C) 2004-2009 Red Hat, Inc. All rights reserved.
7 * This file is part of LVM2.
9 * This copyrighted material is made available to anyone wishing to use,
10 * modify, copy, or redistribute it subject to the terms and conditions
11 * of the GNU Lesser General Public License v.2.1.
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program; if not, write to the Free Software Foundation,
15 * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 static int _vgs_single(struct cmd_context
*cmd
__attribute((unused
)),
22 const char *vg_name
, struct volume_group
*vg
,
25 if (!report_object(handle
, vg
, NULL
, NULL
, NULL
, NULL
)) {
30 check_current_backup(vg
);
32 return ECMD_PROCESSED
;
35 static int _lvs_single(struct cmd_context
*cmd
, struct logical_volume
*lv
,
38 if (!arg_count(cmd
, all_ARG
) && !lv_is_visible(lv
))
39 return ECMD_PROCESSED
;
41 if (!report_object(handle
, lv
->vg
, lv
, NULL
, NULL
, NULL
)) {
46 return ECMD_PROCESSED
;
49 static int _segs_single(struct cmd_context
*cmd
__attribute((unused
)),
50 struct lv_segment
*seg
, void *handle
)
52 if (!report_object(handle
, seg
->lv
->vg
, seg
->lv
, NULL
, seg
, NULL
)) {
57 return ECMD_PROCESSED
;
60 static int _pvsegs_sub_single(struct cmd_context
*cmd
,
61 struct volume_group
*vg
,
62 struct pv_segment
*pvseg
, void *handle
)
64 int ret
= ECMD_PROCESSED
;
65 struct lv_segment
*seg
= pvseg
->lvseg
;
67 struct volume_group _free_vg
= {
72 struct logical_volume _free_logical_volume
= {
73 .vg
= vg
?: &_free_vg
,
81 struct lv_segment _free_lv_segment
= {
82 .lv
= &_free_logical_volume
,
97 _free_lv_segment
.segtype
= get_segtype_from_string(cmd
, "free");
98 _free_lv_segment
.len
= pvseg
->len
;
99 dm_list_init(&_free_vg
.pvs
);
100 dm_list_init(&_free_vg
.lvs
);
101 dm_list_init(&_free_vg
.tags
);
102 dm_list_init(&_free_lv_segment
.tags
);
103 dm_list_init(&_free_lv_segment
.origin_list
);
104 dm_list_init(&_free_logical_volume
.tags
);
105 dm_list_init(&_free_logical_volume
.segments
);
106 dm_list_init(&_free_logical_volume
.segs_using_this_lv
);
107 dm_list_init(&_free_logical_volume
.snapshot_segs
);
109 if (!report_object(handle
, vg
, seg
? seg
->lv
: &_free_logical_volume
, pvseg
->pv
,
110 seg
? : &_free_lv_segment
, pvseg
)) {
118 static int _lvsegs_single(struct cmd_context
*cmd
, struct logical_volume
*lv
,
121 if (!arg_count(cmd
, all_ARG
) && !lv_is_visible(lv
))
122 return ECMD_PROCESSED
;
124 return process_each_segment_in_lv(cmd
, lv
, handle
, _segs_single
);
127 static int _pvsegs_single(struct cmd_context
*cmd
, struct volume_group
*vg
,
128 struct physical_volume
*pv
, void *handle
)
130 return process_each_segment_in_pv(cmd
, vg
, pv
, handle
,
134 static int _pvs_single(struct cmd_context
*cmd
, struct volume_group
*vg
,
135 struct physical_volume
*pv
, void *handle
)
138 int ret
= ECMD_PROCESSED
;
139 const char *vg_name
= NULL
;
140 struct volume_group
*old_vg
= vg
;
142 if (is_pv(pv
) && !is_orphan(pv
) && !vg
) {
143 vg_name
= pv_vg_name(pv
);
145 vg
= vg_read(cmd
, vg_name
, (char *)&pv
->vgid
, 0);
146 if (vg_read_error(vg
)) {
147 log_error("Skipping volume group %s", vg_name
);
153 * Replace possibly incomplete PV structure with new one
154 * allocated in vg_read_internal() path.
156 if (!(pvl
= find_pv_in_vg(vg
, pv_dev_name(pv
)))) {
157 log_error("Unable to find \"%s\" in volume group \"%s\"",
158 pv_dev_name(pv
), vg
->name
);
166 if (!report_object(handle
, vg
, NULL
, pv
, NULL
, NULL
)) {
173 unlock_vg(cmd
, vg_name
);
181 static int _label_single(struct cmd_context
*cmd
, struct volume_group
*vg
,
182 struct physical_volume
*pv
, void *handle
)
184 if (!report_object(handle
, vg
, NULL
, pv
, NULL
, NULL
)) {
189 return ECMD_PROCESSED
;
192 static int _pvs_in_vg(struct cmd_context
*cmd
, const char *vg_name
,
193 struct volume_group
*vg
,
196 if (vg_read_error(vg
)) {
201 return process_each_pv_in_vg(cmd
, vg
, NULL
, handle
, &_pvs_single
);
204 static int _pvsegs_in_vg(struct cmd_context
*cmd
, const char *vg_name
,
205 struct volume_group
*vg
,
208 if (vg_read_error(vg
)) {
213 return process_each_pv_in_vg(cmd
, vg
, NULL
, handle
, &_pvsegs_single
);
216 static int _report(struct cmd_context
*cmd
, int argc
, char **argv
,
217 report_type_t report_type
)
222 const char *keys
= NULL
, *options
= NULL
, *separator
;
223 int r
= ECMD_PROCESSED
;
224 int aligned
, buffered
, headings
, field_prefixes
, quoted
;
226 unsigned args_are_pvs
;
228 aligned
= find_config_tree_int(cmd
, "report/aligned",
229 DEFAULT_REP_ALIGNED
);
230 buffered
= find_config_tree_int(cmd
, "report/buffered",
231 DEFAULT_REP_BUFFERED
);
232 headings
= find_config_tree_int(cmd
, "report/headings",
233 DEFAULT_REP_HEADINGS
);
234 separator
= find_config_tree_str(cmd
, "report/separator",
235 DEFAULT_REP_SEPARATOR
);
236 field_prefixes
= find_config_tree_int(cmd
, "report/prefixes",
237 DEFAULT_REP_PREFIXES
);
238 quoted
= find_config_tree_int(cmd
, "report/quoted",
240 columns_as_rows
= find_config_tree_int(cmd
, "report/columns_as_rows",
241 DEFAULT_REP_COLUMNS_AS_ROWS
);
243 args_are_pvs
= (report_type
== PVS
||
244 report_type
== LABEL
||
245 report_type
== PVSEGS
) ? 1 : 0;
247 switch (report_type
) {
249 keys
= find_config_tree_str(cmd
, "report/lvs_sort",
251 if (!arg_count(cmd
, verbose_ARG
))
252 options
= find_config_tree_str(cmd
,
256 options
= find_config_tree_str(cmd
,
257 "report/lvs_cols_verbose",
258 DEFAULT_LVS_COLS_VERB
);
261 keys
= find_config_tree_str(cmd
, "report/vgs_sort",
263 if (!arg_count(cmd
, verbose_ARG
))
264 options
= find_config_tree_str(cmd
,
268 options
= find_config_tree_str(cmd
,
269 "report/vgs_cols_verbose",
270 DEFAULT_VGS_COLS_VERB
);
274 keys
= find_config_tree_str(cmd
, "report/pvs_sort",
276 if (!arg_count(cmd
, verbose_ARG
))
277 options
= find_config_tree_str(cmd
,
281 options
= find_config_tree_str(cmd
,
282 "report/pvs_cols_verbose",
283 DEFAULT_PVS_COLS_VERB
);
286 keys
= find_config_tree_str(cmd
, "report/segs_sort",
288 if (!arg_count(cmd
, verbose_ARG
))
289 options
= find_config_tree_str(cmd
,
293 options
= find_config_tree_str(cmd
,
294 "report/segs_cols_verbose",
295 DEFAULT_SEGS_COLS_VERB
);
298 keys
= find_config_tree_str(cmd
, "report/pvsegs_sort",
299 DEFAULT_PVSEGS_SORT
);
300 if (!arg_count(cmd
, verbose_ARG
))
301 options
= find_config_tree_str(cmd
,
302 "report/pvsegs_cols",
303 DEFAULT_PVSEGS_COLS
);
305 options
= find_config_tree_str(cmd
,
306 "report/pvsegs_cols_verbose",
307 DEFAULT_PVSEGS_COLS_VERB
);
311 /* If -o supplied use it, else use default for report_type */
312 if (arg_count(cmd
, options_ARG
)) {
313 opts
= arg_str_value(cmd
, options_ARG
, "");
314 if (!opts
|| !*opts
) {
315 log_error("Invalid options string: %s", opts
);
316 return EINVALID_CMD_LINE
;
319 if (!(str
= dm_pool_alloc(cmd
->mem
,
320 strlen(options
) + strlen(opts
) + 1))) {
321 log_error("options string allocation failed");
324 strcpy(str
, options
);
326 strcat(str
, opts
+ 1);
332 /* -O overrides default sort settings */
333 keys
= arg_str_value(cmd
, sort_ARG
, keys
);
335 separator
= arg_str_value(cmd
, separator_ARG
, separator
);
336 if (arg_count(cmd
, separator_ARG
))
338 if (arg_count(cmd
, aligned_ARG
))
340 if (arg_count(cmd
, unbuffered_ARG
) && !arg_count(cmd
, sort_ARG
))
342 if (arg_count(cmd
, noheadings_ARG
))
344 if (arg_count(cmd
, nameprefixes_ARG
)) {
348 if (arg_count(cmd
, unquoted_ARG
))
350 if (arg_count(cmd
, rows_ARG
))
353 if (!(report_handle
= report_init(cmd
, options
, keys
, &report_type
,
354 separator
, aligned
, buffered
,
355 headings
, field_prefixes
, quoted
,
361 /* Ensure options selected are compatible */
362 if (report_type
& SEGS
)
364 if (report_type
& PVSEGS
)
366 if ((report_type
& LVS
) && (report_type
& (PVS
| LABEL
)) && !args_are_pvs
) {
367 log_error("Can't report LV and PV fields at the same time");
368 dm_report_free(report_handle
);
372 /* Change report type if fields specified makes this necessary */
373 if ((report_type
& PVSEGS
) ||
374 ((report_type
& (PVS
| LABEL
)) && (report_type
& LVS
)))
375 report_type
= PVSEGS
;
376 else if ((report_type
& LABEL
) && (report_type
& VGS
))
378 else if (report_type
& PVS
)
380 else if (report_type
& SEGS
)
382 else if (report_type
& LVS
)
385 switch (report_type
) {
387 r
= process_each_lv(cmd
, argc
, argv
, 0, report_handle
,
391 r
= process_each_vg(cmd
, argc
, argv
, 0,
392 report_handle
, &_vgs_single
);
395 r
= process_each_pv(cmd
, argc
, argv
, NULL
, READ_WITHOUT_LOCK
,
396 1, report_handle
, &_label_single
);
400 r
= process_each_pv(cmd
, argc
, argv
, NULL
, 0,
401 0, report_handle
, &_pvs_single
);
403 r
= process_each_vg(cmd
, argc
, argv
, 0,
404 report_handle
, &_pvs_in_vg
);
407 r
= process_each_lv(cmd
, argc
, argv
, 0, report_handle
,
412 r
= process_each_pv(cmd
, argc
, argv
, NULL
, 0,
413 0, report_handle
, &_pvsegs_single
);
415 r
= process_each_vg(cmd
, argc
, argv
, 0,
416 report_handle
, &_pvsegs_in_vg
);
420 dm_report_output(report_handle
);
422 dm_report_free(report_handle
);
426 int lvs(struct cmd_context
*cmd
, int argc
, char **argv
)
430 if (arg_count(cmd
, segments_ARG
))
435 return _report(cmd
, argc
, argv
, type
);
438 int vgs(struct cmd_context
*cmd
, int argc
, char **argv
)
440 return _report(cmd
, argc
, argv
, VGS
);
443 int pvs(struct cmd_context
*cmd
, int argc
, char **argv
)
447 if (arg_count(cmd
, segments_ARG
))
452 return _report(cmd
, argc
, argv
, type
);