1 /*
2 * kernel/lvm-fs.c
3 *
4 * Copyright (C) 2001-2002 Sistina Software
5 *
6 * January-May,December 2001
7 * May 2002
8 *
9 * LVM driver is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2, or (at your option)
12 * any later version.
13 *
14 * LVM driver is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with GNU CC; see the file COPYING. If not, write to
21 * the Free Software Foundation, 59 Temple Place - Suite 330,
22 * Boston, MA 02111-1307, USA.
23 *
24 */
25
26 /*
27 * Changelog
28 *
29 * 11/01/2001 - First version (Joe Thornber)
30 * 21/03/2001 - added display of stripes and stripe size (HM)
31 * 04/10/2001 - corrected devfs_register() call in lvm_init_fs()
32 * 11/04/2001 - don't devfs_register("lvm") as user-space always does it
33 * 10/05/2001 - show more of PV name in /proc/lvm/global
34 * 16/12/2001 - fix devfs unregister order and prevent duplicate unreg (REG)
35 *
36 */
37
38 #include <linux/config.h>
39 #include <linux/version.h>
40
41 #include <linux/kernel.h>
42 #include <linux/vmalloc.h>
43 #include <linux/smp_lock.h>
44
45 #include <linux/devfs_fs_kernel.h>
46 #include <linux/proc_fs.h>
47 #include <linux/init.h>
48 #include <linux/lvm.h>
49
50 #include "lvm-internal.h"
51
52
53 static int _proc_read_vg(char *page, char **start, off_t off,
54 int count, int *eof, void *data);
55 static int _proc_read_lv(char *page, char **start, off_t off,
56 int count, int *eof, void *data);
57 static int _proc_read_pv(char *page, char **start, off_t off,
58 int count, int *eof, void *data);
59 static int _proc_read_global(char *page, char **start, off_t off,
60 int count, int *eof, void *data);
61
62 static int _vg_info(vg_t * vg_ptr, char *buf);
63 static int _lv_info(vg_t * vg_ptr, lv_t * lv_ptr, char *buf);
64 static int _pv_info(pv_t * pv_ptr, char *buf);
65
66 static void _show_uuid(const char *src, char *b, char *e);
67
68 #if 0
69 static devfs_handle_t lvm_devfs_handle;
70 #endif
71 static devfs_handle_t vg_devfs_handle[MAX_VG];
72 static devfs_handle_t ch_devfs_handle[MAX_VG];
73 static devfs_handle_t lv_devfs_handle[MAX_LV];
74
75 static struct proc_dir_entry *lvm_proc_dir = NULL;
76 static struct proc_dir_entry *lvm_proc_vg_subdir = NULL;
77
78 /* inline functions */
79
80 /* public interface */
lvm_init_fs()81 void __init lvm_init_fs()
82 {
83 struct proc_dir_entry *pde;
84
85 /* User-space has already registered this */
86 #if 0
87 lvm_devfs_handle = devfs_register(0, "lvm", 0, LVM_CHAR_MAJOR, 0,
88 S_IFCHR | S_IRUSR | S_IWUSR |
89 S_IRGRP, &lvm_chr_fops, NULL);
90 #endif
91 lvm_proc_dir = create_proc_entry(LVM_DIR, S_IFDIR, &proc_root);
92 if (lvm_proc_dir) {
93 lvm_proc_vg_subdir =
94 create_proc_entry(LVM_VG_SUBDIR, S_IFDIR,
95 lvm_proc_dir);
96 pde = create_proc_entry(LVM_GLOBAL, S_IFREG, lvm_proc_dir);
97 if (pde != NULL)
98 pde->read_proc = _proc_read_global;
99 }
100 }
101
lvm_fin_fs()102 void lvm_fin_fs()
103 {
104 #if 0
105 devfs_unregister(lvm_devfs_handle);
106 #endif
107 remove_proc_entry(LVM_GLOBAL, lvm_proc_dir);
108 remove_proc_entry(LVM_VG_SUBDIR, lvm_proc_dir);
109 remove_proc_entry(LVM_DIR, &proc_root);
110 }
111
lvm_fs_create_vg(vg_t * vg_ptr)112 void lvm_fs_create_vg(vg_t * vg_ptr)
113 {
114 struct proc_dir_entry *pde;
115
116 if (!vg_ptr)
117 return;
118
119 vg_devfs_handle[vg_ptr->vg_number] =
120 devfs_mk_dir(0, vg_ptr->vg_name, NULL);
121
122 ch_devfs_handle[vg_ptr->vg_number] =
123 devfs_register(vg_devfs_handle[vg_ptr->vg_number], "group",
124 DEVFS_FL_DEFAULT, LVM_CHAR_MAJOR,
125 vg_ptr->vg_number,
126 S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP,
127 &lvm_chr_fops, NULL);
128
129 vg_ptr->vg_dir_pde = create_proc_entry(vg_ptr->vg_name, S_IFDIR,
130 lvm_proc_vg_subdir);
131
132 if ((pde =
133 create_proc_entry("group", S_IFREG, vg_ptr->vg_dir_pde))) {
134 pde->read_proc = _proc_read_vg;
135 pde->data = vg_ptr;
136 }
137
138 vg_ptr->lv_subdir_pde =
139 create_proc_entry(LVM_LV_SUBDIR, S_IFDIR, vg_ptr->vg_dir_pde);
140
141 vg_ptr->pv_subdir_pde =
142 create_proc_entry(LVM_PV_SUBDIR, S_IFDIR, vg_ptr->vg_dir_pde);
143 }
144
lvm_fs_remove_vg(vg_t * vg_ptr)145 void lvm_fs_remove_vg(vg_t * vg_ptr)
146 {
147 int i;
148
149 if (!vg_ptr)
150 return;
151
152 devfs_unregister(ch_devfs_handle[vg_ptr->vg_number]);
153 ch_devfs_handle[vg_ptr->vg_number] = NULL;
154
155 /* remove lv's */
156 for (i = 0; i < vg_ptr->lv_max; i++)
157 if (vg_ptr->lv[i])
158 lvm_fs_remove_lv(vg_ptr, vg_ptr->lv[i]);
159
160 /* must not remove directory before leaf nodes */
161 devfs_unregister(vg_devfs_handle[vg_ptr->vg_number]);
162 vg_devfs_handle[vg_ptr->vg_number] = NULL;
163
164 /* remove pv's */
165 for (i = 0; i < vg_ptr->pv_max; i++)
166 if (vg_ptr->pv[i])
167 lvm_fs_remove_pv(vg_ptr, vg_ptr->pv[i]);
168
169 if (vg_ptr->vg_dir_pde) {
170 remove_proc_entry(LVM_LV_SUBDIR, vg_ptr->vg_dir_pde);
171 vg_ptr->lv_subdir_pde = NULL;
172
173 remove_proc_entry(LVM_PV_SUBDIR, vg_ptr->vg_dir_pde);
174 vg_ptr->pv_subdir_pde = NULL;
175
176 remove_proc_entry("group", vg_ptr->vg_dir_pde);
177 vg_ptr->vg_dir_pde = NULL;
178
179 remove_proc_entry(vg_ptr->vg_name, lvm_proc_vg_subdir);
180 }
181 }
182
183
_basename(const char * str)184 static inline const char *_basename(const char *str)
185 {
186 const char *name = strrchr(str, '/');
187 name = name ? name + 1 : str;
188 return name;
189 }
190
lvm_fs_create_lv(vg_t * vg_ptr,lv_t * lv)191 devfs_handle_t lvm_fs_create_lv(vg_t * vg_ptr, lv_t * lv)
192 {
193 struct proc_dir_entry *pde;
194 const char *name;
195
196 if (!vg_ptr || !lv)
197 return NULL;
198
199 name = _basename(lv->lv_name);
200
201 lv_devfs_handle[MINOR(lv->lv_dev)] =
202 devfs_register(vg_devfs_handle[vg_ptr->vg_number], name,
203 DEVFS_FL_DEFAULT, LVM_BLK_MAJOR,
204 MINOR(lv->lv_dev),
205 S_IFBLK | S_IRUSR | S_IWUSR | S_IRGRP,
206 &lvm_blk_dops, NULL);
207
208 if (vg_ptr->lv_subdir_pde &&
209 (pde =
210 create_proc_entry(name, S_IFREG, vg_ptr->lv_subdir_pde))) {
211 pde->read_proc = _proc_read_lv;
212 pde->data = lv;
213 }
214 return lv_devfs_handle[MINOR(lv->lv_dev)];
215 }
216
lvm_fs_remove_lv(vg_t * vg_ptr,lv_t * lv)217 void lvm_fs_remove_lv(vg_t * vg_ptr, lv_t * lv)
218 {
219
220 if (!vg_ptr || !lv)
221 return;
222
223 devfs_unregister(lv_devfs_handle[MINOR(lv->lv_dev)]);
224 lv_devfs_handle[MINOR(lv->lv_dev)] = NULL;
225
226 if (vg_ptr->lv_subdir_pde) {
227 const char *name = _basename(lv->lv_name);
228 remove_proc_entry(name, vg_ptr->lv_subdir_pde);
229 }
230 }
231
232
_make_pv_name(const char * src,char * b,char * e)233 static inline void _make_pv_name(const char *src, char *b, char *e)
234 {
235 int offset = strlen(LVM_DIR_PREFIX);
236 if (strncmp(src, LVM_DIR_PREFIX, offset))
237 offset = 0;
238
239 e--;
240 src += offset;
241 while (*src && (b != e)) {
242 *b++ = (*src == '/') ? '_' : *src;
243 src++;
244 }
245 *b = '\0';
246 }
247
lvm_fs_create_pv(vg_t * vg_ptr,pv_t * pv)248 void lvm_fs_create_pv(vg_t * vg_ptr, pv_t * pv)
249 {
250 struct proc_dir_entry *pde;
251 char name[NAME_LEN];
252
253 if (!vg_ptr || !pv)
254 return;
255
256 if (!vg_ptr->pv_subdir_pde)
257 return;
258
259 _make_pv_name(pv->pv_name, name, name + sizeof(name));
260 if ((pde =
261 create_proc_entry(name, S_IFREG, vg_ptr->pv_subdir_pde))) {
262 pde->read_proc = _proc_read_pv;
263 pde->data = pv;
264 }
265 }
266
lvm_fs_remove_pv(vg_t * vg_ptr,pv_t * pv)267 void lvm_fs_remove_pv(vg_t * vg_ptr, pv_t * pv)
268 {
269 char name[NAME_LEN];
270
271 if (!vg_ptr || !pv)
272 return;
273
274 if (!vg_ptr->pv_subdir_pde)
275 return;
276
277 _make_pv_name(pv->pv_name, name, name + sizeof(name));
278 remove_proc_entry(name, vg_ptr->pv_subdir_pde);
279 }
280
281
_proc_read_vg(char * page,char ** start,off_t off,int count,int * eof,void * data)282 static int _proc_read_vg(char *page, char **start, off_t off,
283 int count, int *eof, void *data)
284 {
285 int sz = 0;
286 vg_t *vg_ptr = data;
287 char uuid[NAME_LEN];
288
289 sz += sprintf(page + sz, "name: %s\n", vg_ptr->vg_name);
290 sz += sprintf(page + sz, "size: %u\n",
291 vg_ptr->pe_total * vg_ptr->pe_size / 2);
292 sz += sprintf(page + sz, "access: %u\n", vg_ptr->vg_access);
293 sz += sprintf(page + sz, "status: %u\n", vg_ptr->vg_status);
294 sz += sprintf(page + sz, "number: %u\n", vg_ptr->vg_number);
295 sz += sprintf(page + sz, "LV max: %u\n", vg_ptr->lv_max);
296 sz += sprintf(page + sz, "LV current: %u\n", vg_ptr->lv_cur);
297 sz += sprintf(page + sz, "LV open: %u\n", vg_ptr->lv_open);
298 sz += sprintf(page + sz, "PV max: %u\n", vg_ptr->pv_max);
299 sz += sprintf(page + sz, "PV current: %u\n", vg_ptr->pv_cur);
300 sz += sprintf(page + sz, "PV active: %u\n", vg_ptr->pv_act);
301 sz +=
302 sprintf(page + sz, "PE size: %u\n", vg_ptr->pe_size / 2);
303 sz += sprintf(page + sz, "PE total: %u\n", vg_ptr->pe_total);
304 sz +=
305 sprintf(page + sz, "PE allocated: %u\n", vg_ptr->pe_allocated);
306
307 _show_uuid(vg_ptr->vg_uuid, uuid, uuid + sizeof(uuid));
308 sz += sprintf(page + sz, "uuid: %s\n", uuid);
309
310 return sz;
311 }
312
_proc_read_lv(char * page,char ** start,off_t off,int count,int * eof,void * data)313 static int _proc_read_lv(char *page, char **start, off_t off,
314 int count, int *eof, void *data)
315 {
316 int sz = 0;
317 lv_t *lv = data;
318
319 sz += sprintf(page + sz, "name: %s\n", lv->lv_name);
320 sz += sprintf(page + sz, "size: %u\n", lv->lv_size);
321 sz += sprintf(page + sz, "access: %u\n", lv->lv_access);
322 sz += sprintf(page + sz, "status: %u\n", lv->lv_status);
323 sz += sprintf(page + sz, "number: %u\n", lv->lv_number);
324 sz += sprintf(page + sz, "open: %u\n", lv->lv_open);
325 sz += sprintf(page + sz, "allocation: %u\n", lv->lv_allocation);
326 if (lv->lv_stripes > 1) {
327 sz += sprintf(page + sz, "stripes: %u\n",
328 lv->lv_stripes);
329 sz += sprintf(page + sz, "stripesize: %u\n",
330 lv->lv_stripesize);
331 }
332 sz += sprintf(page + sz, "device: %02u:%02u\n",
333 MAJOR(lv->lv_dev), MINOR(lv->lv_dev));
334
335 return sz;
336 }
337
_proc_read_pv(char * page,char ** start,off_t off,int count,int * eof,void * data)338 static int _proc_read_pv(char *page, char **start, off_t off,
339 int count, int *eof, void *data)
340 {
341 int sz = 0;
342 pv_t *pv = data;
343 char uuid[NAME_LEN];
344
345 sz += sprintf(page + sz, "name: %s\n", pv->pv_name);
346 sz += sprintf(page + sz, "size: %u\n", pv->pv_size);
347 sz += sprintf(page + sz, "status: %u\n", pv->pv_status);
348 sz += sprintf(page + sz, "number: %u\n", pv->pv_number);
349 sz += sprintf(page + sz, "allocatable: %u\n", pv->pv_allocatable);
350 sz += sprintf(page + sz, "LV current: %u\n", pv->lv_cur);
351 sz += sprintf(page + sz, "PE size: %u\n", pv->pe_size / 2);
352 sz += sprintf(page + sz, "PE total: %u\n", pv->pe_total);
353 sz += sprintf(page + sz, "PE allocated: %u\n", pv->pe_allocated);
354 sz += sprintf(page + sz, "device: %02u:%02u\n",
355 MAJOR(pv->pv_dev), MINOR(pv->pv_dev));
356
357 _show_uuid(pv->pv_uuid, uuid, uuid + sizeof(uuid));
358 sz += sprintf(page + sz, "uuid: %s\n", uuid);
359
360 return sz;
361 }
362
_proc_read_global(char * page,char ** start,off_t pos,int count,int * eof,void * data)363 static int _proc_read_global(char *page, char **start, off_t pos,
364 int count, int *eof, void *data)
365 {
366
367 #define LVM_PROC_BUF ( i == 0 ? dummy_buf : &buf[sz])
368
369 int c, i, l, p, v, vg_counter, pv_counter, lv_counter,
370 lv_open_counter, lv_open_total, pe_t_bytes, hash_table_bytes,
371 lv_block_exception_t_bytes, seconds;
372 static off_t sz;
373 off_t sz_last;
374 static char *buf = NULL;
375 static char dummy_buf[160]; /* sized for 2 lines */
376 vg_t *vg_ptr;
377 lv_t *lv_ptr;
378 pv_t *pv_ptr;
379
380
381 #ifdef DEBUG_LVM_PROC_GET_INFO
382 printk(KERN_DEBUG
383 "%s - lvm_proc_get_global_info CALLED pos: %lu count: %d\n",
384 lvm_name, pos, count);
385 #endif
386
387 if (pos != 0 && buf != NULL)
388 goto out;
389
390 sz_last = vg_counter = pv_counter = lv_counter = lv_open_counter =
391 lv_open_total = pe_t_bytes = hash_table_bytes =
392 lv_block_exception_t_bytes = 0;
393
394 /* get some statistics */
395 for (v = 0; v < ABS_MAX_VG; v++) {
396 if ((vg_ptr = vg[v]) != NULL) {
397 vg_counter++;
398 pv_counter += vg_ptr->pv_cur;
399 lv_counter += vg_ptr->lv_cur;
400 if (vg_ptr->lv_cur > 0) {
401 for (l = 0; l < vg[v]->lv_max; l++) {
402 if ((lv_ptr =
403 vg_ptr->lv[l]) != NULL) {
404 pe_t_bytes +=
405 lv_ptr->
406 lv_allocated_le;
407 hash_table_bytes +=
408 lv_ptr->
409 lv_snapshot_hash_table_size;
410 if (lv_ptr->
411 lv_block_exception !=
412 NULL)
413 lv_block_exception_t_bytes
414 +=
415 lv_ptr->
416 lv_remap_end;
417 if (lv_ptr->lv_open > 0) {
418 lv_open_counter++;
419 lv_open_total +=
420 lv_ptr->
421 lv_open;
422 }
423 }
424 }
425 }
426 }
427 }
428
429 pe_t_bytes *= sizeof(pe_t);
430 lv_block_exception_t_bytes *= sizeof(lv_block_exception_t);
431
432 if (buf != NULL) {
433 P_KFREE("%s -- vfree %d\n", lvm_name, __LINE__);
434 lock_kernel();
435 vfree(buf);
436 unlock_kernel();
437 buf = NULL;
438 }
439 /* 2 times: first to get size to allocate buffer,
440 2nd to fill the malloced buffer */
441 for (i = 0; i < 2; i++) {
442 sz = 0;
443 sz += sprintf(LVM_PROC_BUF, "LVM "
444 #ifdef MODULE
445 "module"
446 #else
447 "driver"
448 #endif
449 " %s\n\n"
450 "Total: %d VG%s %d PV%s %d LV%s ",
451 lvm_version,
452 vg_counter, vg_counter == 1 ? "" : "s",
453 pv_counter, pv_counter == 1 ? "" : "s",
454 lv_counter, lv_counter == 1 ? "" : "s");
455 sz += sprintf(LVM_PROC_BUF,
456 "(%d LV%s open",
457 lv_open_counter,
458 lv_open_counter == 1 ? "" : "s");
459 if (lv_open_total > 0)
460 sz += sprintf(LVM_PROC_BUF,
461 " %d times)\n", lv_open_total);
462 else
463 sz += sprintf(LVM_PROC_BUF, ")");
464 sz += sprintf(LVM_PROC_BUF,
465 "\nGlobal: %lu bytes malloced IOP version: %d ",
466 vg_counter * sizeof(vg_t) +
467 pv_counter * sizeof(pv_t) +
468 lv_counter * sizeof(lv_t) +
469 pe_t_bytes + hash_table_bytes +
470 lv_block_exception_t_bytes + sz_last,
471 lvm_iop_version);
472
473 seconds = CURRENT_TIME - loadtime;
474 if (seconds < 0)
475 loadtime = CURRENT_TIME + seconds;
476 if (seconds / 86400 > 0) {
477 sz += sprintf(LVM_PROC_BUF, "%d day%s ",
478 seconds / 86400,
479 seconds / 86400 == 0 ||
480 seconds / 86400 > 1 ? "s" : "");
481 }
482 sz += sprintf(LVM_PROC_BUF, "%d:%02d:%02d active\n",
483 (seconds % 86400) / 3600,
484 (seconds % 3600) / 60, seconds % 60);
485
486 if (vg_counter > 0) {
487 for (v = 0; v < ABS_MAX_VG; v++) {
488 /* volume group */
489 if ((vg_ptr = vg[v]) != NULL) {
490 sz +=
491 _vg_info(vg_ptr, LVM_PROC_BUF);
492
493 /* physical volumes */
494 sz += sprintf(LVM_PROC_BUF,
495 "\n PV%s ",
496 vg_ptr->pv_cur ==
497 1 ? ": " : "s:");
498 c = 0;
499 for (p = 0; p < vg_ptr->pv_max;
500 p++) {
501 if ((pv_ptr =
502 vg_ptr->pv[p]) !=
503 NULL) {
504 sz +=
505 _pv_info
506 (pv_ptr,
507 LVM_PROC_BUF);
508
509 c++;
510 if (c <
511 vg_ptr->pv_cur)
512 sz +=
513 sprintf
514 (LVM_PROC_BUF,
515 "\n ");
516 }
517 }
518
519 /* logical volumes */
520 sz += sprintf(LVM_PROC_BUF,
521 "\n LV%s ",
522 vg_ptr->lv_cur ==
523 1 ? ": " : "s:");
524 c = 0;
525 for (l = 0; l < vg_ptr->lv_max;
526 l++) {
527 if ((lv_ptr =
528 vg_ptr->lv[l]) !=
529 NULL) {
530 sz +=
531 _lv_info
532 (vg_ptr,
533 lv_ptr,
534 LVM_PROC_BUF);
535 c++;
536 if (c <
537 vg_ptr->lv_cur)
538 sz +=
539 sprintf
540 (LVM_PROC_BUF,
541 "\n ");
542 }
543 }
544 if (vg_ptr->lv_cur == 0)
545 sz +=
546 sprintf(LVM_PROC_BUF,
547 "none");
548 sz += sprintf(LVM_PROC_BUF, "\n");
549 }
550 }
551 }
552 if (buf == NULL) {
553 lock_kernel();
554 buf = vmalloc(sz);
555 unlock_kernel();
556 if (buf == NULL) {
557 sz = 0;
558 return sprintf(page,
559 "%s - vmalloc error at line %d\n",
560 lvm_name, __LINE__);
561 }
562 }
563 sz_last = sz;
564 }
565
566 out:
567 if (pos > sz - 1) {
568 lock_kernel();
569 vfree(buf);
570 unlock_kernel();
571 buf = NULL;
572 return 0;
573 }
574 *start = &buf[pos];
575 if (sz - pos < count)
576 return sz - pos;
577 else
578 return count;
579
580 #undef LVM_PROC_BUF
581 }
582
583 /*
584 * provide VG info for proc filesystem use (global)
585 */
_vg_info(vg_t * vg_ptr,char * buf)586 static int _vg_info(vg_t * vg_ptr, char *buf)
587 {
588 int sz = 0;
589 char inactive_flag = ' ';
590
591 if (!(vg_ptr->vg_status & VG_ACTIVE))
592 inactive_flag = 'I';
593 sz = sprintf(buf,
594 "\nVG: %c%s [%d PV, %d LV/%d open] "
595 " PE Size: %d KB\n"
596 " Usage [KB/PE]: %d /%d total "
597 "%d /%d used %d /%d free",
598 inactive_flag,
599 vg_ptr->vg_name,
600 vg_ptr->pv_cur,
601 vg_ptr->lv_cur,
602 vg_ptr->lv_open,
603 vg_ptr->pe_size >> 1,
604 vg_ptr->pe_size * vg_ptr->pe_total >> 1,
605 vg_ptr->pe_total,
606 vg_ptr->pe_allocated * vg_ptr->pe_size >> 1,
607 vg_ptr->pe_allocated,
608 (vg_ptr->pe_total - vg_ptr->pe_allocated) *
609 vg_ptr->pe_size >> 1,
610 vg_ptr->pe_total - vg_ptr->pe_allocated);
611 return sz;
612 }
613
614
615 /*
616 * provide LV info for proc filesystem use (global)
617 */
_lv_info(vg_t * vg_ptr,lv_t * lv_ptr,char * buf)618 static int _lv_info(vg_t * vg_ptr, lv_t * lv_ptr, char *buf)
619 {
620 int sz = 0;
621 char inactive_flag = 'A', allocation_flag = ' ',
622 stripes_flag = ' ', rw_flag = ' ', *basename;
623
624 if (!(lv_ptr->lv_status & LV_ACTIVE))
625 inactive_flag = 'I';
626 rw_flag = 'R';
627 if (lv_ptr->lv_access & LV_WRITE)
628 rw_flag = 'W';
629 allocation_flag = 'D';
630 if (lv_ptr->lv_allocation & LV_CONTIGUOUS)
631 allocation_flag = 'C';
632 stripes_flag = 'L';
633 if (lv_ptr->lv_stripes > 1)
634 stripes_flag = 'S';
635 sz += sprintf(buf + sz,
636 "[%c%c%c%c",
637 inactive_flag,
638 rw_flag, allocation_flag, stripes_flag);
639 if (lv_ptr->lv_stripes > 1)
640 sz += sprintf(buf + sz, "%-2d", lv_ptr->lv_stripes);
641 else
642 sz += sprintf(buf + sz, " ");
643
644 /* FIXME: use _basename */
645 basename = strrchr(lv_ptr->lv_name, '/');
646 if (basename == 0)
647 basename = lv_ptr->lv_name;
648 else
649 basename++;
650 sz += sprintf(buf + sz, "] %-25s", basename);
651 if (strlen(basename) > 25)
652 sz += sprintf(buf + sz,
653 "\n ");
654 sz += sprintf(buf + sz, "%9d /%-6d ",
655 lv_ptr->lv_size >> 1,
656 lv_ptr->lv_size / vg_ptr->pe_size);
657
658 if (lv_ptr->lv_open == 0)
659 sz += sprintf(buf + sz, "close");
660 else
661 sz += sprintf(buf + sz, "%dx open", lv_ptr->lv_open);
662
663 return sz;
664 }
665
666
667 /*
668 * provide PV info for proc filesystem use (global)
669 */
_pv_info(pv_t * pv,char * buf)670 static int _pv_info(pv_t * pv, char *buf)
671 {
672 int sz = 0;
673 char inactive_flag = 'A', allocation_flag = ' ';
674 char *pv_name = NULL;
675
676 if (!(pv->pv_status & PV_ACTIVE))
677 inactive_flag = 'I';
678 allocation_flag = 'A';
679 if (!(pv->pv_allocatable & PV_ALLOCATABLE))
680 allocation_flag = 'N';
681 pv_name = strchr(pv->pv_name + 1, '/');
682 if (pv_name == 0)
683 pv_name = pv->pv_name;
684 else
685 pv_name++;
686 sz = sprintf(buf,
687 "[%c%c] %-21s %8d /%-6d "
688 "%8d /%-6d %8d /%-6d",
689 inactive_flag,
690 allocation_flag,
691 pv_name,
692 pv->pe_total * pv->pe_size >> 1,
693 pv->pe_total,
694 pv->pe_allocated * pv->pe_size >> 1,
695 pv->pe_allocated,
696 (pv->pe_total - pv->pe_allocated) *
697 pv->pe_size >> 1, pv->pe_total - pv->pe_allocated);
698 return sz;
699 }
700
_show_uuid(const char * src,char * b,char * e)701 static void _show_uuid(const char *src, char *b, char *e)
702 {
703 int i;
704
705 e--;
706 for (i = 0; *src && (b != e); i++) {
707 if (i && !(i & 0x3))
708 *b++ = '-';
709 *b++ = *src++;
710 }
711 *b = '\0';
712 }
713