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 53static int _proc_read_vg(char *page, char **start, off_t off, 54 int count, int *eof, void *data); 55static int _proc_read_lv(char *page, char **start, off_t off, 56 int count, int *eof, void *data); 57static int _proc_read_pv(char *page, char **start, off_t off, 58 int count, int *eof, void *data); 59static int _proc_read_global(char *page, char **start, off_t off, 60 int count, int *eof, void *data); 61 62static int _vg_info(vg_t *vg_ptr, char *buf); 63static int _lv_info(vg_t *vg_ptr, lv_t *lv_ptr, char *buf); 64static int _pv_info(pv_t *pv_ptr, char *buf); 65 66static void _show_uuid(const char *src, char *b, char *e); 67 68static devfs_handle_t vg_devfs_handle[MAX_VG]; 69static devfs_handle_t ch_devfs_handle[MAX_VG]; 70static devfs_handle_t lv_devfs_handle[MAX_LV]; 71 72static struct proc_dir_entry *lvm_proc_dir = NULL; 73static struct proc_dir_entry *lvm_proc_vg_subdir = NULL; 74 75/* inline functions */ 76 77/* public interface */ 78void __init lvm_init_fs() { 79 struct proc_dir_entry *pde; 80 81/* User-space has already registered this */ 82 lvm_proc_dir = create_proc_entry(LVM_DIR, S_IFDIR, &proc_root); 83 if (lvm_proc_dir) { 84 lvm_proc_vg_subdir = create_proc_entry(LVM_VG_SUBDIR, S_IFDIR, 85 lvm_proc_dir); 86 pde = create_proc_entry(LVM_GLOBAL, S_IFREG, lvm_proc_dir); 87 if ( pde != NULL) pde->read_proc = _proc_read_global; 88 } 89} 90 91void lvm_fin_fs() { 92 remove_proc_entry(LVM_GLOBAL, lvm_proc_dir); 93 remove_proc_entry(LVM_VG_SUBDIR, lvm_proc_dir); 94 remove_proc_entry(LVM_DIR, &proc_root); 95} 96 97void lvm_fs_create_vg(vg_t *vg_ptr) { 98 struct proc_dir_entry *pde; 99 100 if (!vg_ptr) 101 return; 102 103 vg_devfs_handle[vg_ptr->vg_number] = 104 devfs_mk_dir(0, vg_ptr->vg_name, NULL); 105 106 ch_devfs_handle[vg_ptr->vg_number] = devfs_register( 107 vg_devfs_handle[vg_ptr->vg_number] , "group", 108 DEVFS_FL_DEFAULT, LVM_CHAR_MAJOR, vg_ptr->vg_number, 109 S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP, 110 &lvm_chr_fops, NULL); 111 112 vg_ptr->vg_dir_pde = create_proc_entry(vg_ptr->vg_name, S_IFDIR, 113 lvm_proc_vg_subdir); 114 115 if((pde = create_proc_entry("group", S_IFREG, vg_ptr->vg_dir_pde))) { 116 pde->read_proc = _proc_read_vg; 117 pde->data = vg_ptr; 118 } 119 120 vg_ptr->lv_subdir_pde = 121 create_proc_entry(LVM_LV_SUBDIR, S_IFDIR, vg_ptr->vg_dir_pde); 122 123 vg_ptr->pv_subdir_pde = 124 create_proc_entry(LVM_PV_SUBDIR, S_IFDIR, vg_ptr->vg_dir_pde); 125} 126 127void lvm_fs_remove_vg(vg_t *vg_ptr) { 128 int i; 129 130 if (!vg_ptr) 131 return; 132 133 devfs_unregister(ch_devfs_handle[vg_ptr->vg_number]); 134 ch_devfs_handle[vg_ptr->vg_number] = NULL; 135 136 /* remove lv's */ 137 for(i = 0; i < vg_ptr->lv_max; i++) 138 if(vg_ptr->lv[i]) lvm_fs_remove_lv(vg_ptr, vg_ptr->lv[i]); 139 140 /* must not remove directory before leaf nodes */ 141 devfs_unregister(vg_devfs_handle[vg_ptr->vg_number]); 142 vg_devfs_handle[vg_ptr->vg_number] = NULL; 143 144 /* remove pv's */ 145 for(i = 0; i < vg_ptr->pv_max; i++) 146 if(vg_ptr->pv[i]) lvm_fs_remove_pv(vg_ptr, vg_ptr->pv[i]); 147 148 if(vg_ptr->vg_dir_pde) { 149 remove_proc_entry(LVM_LV_SUBDIR, vg_ptr->vg_dir_pde); 150 vg_ptr->lv_subdir_pde = NULL; 151 152 remove_proc_entry(LVM_PV_SUBDIR, vg_ptr->vg_dir_pde); 153 vg_ptr->pv_subdir_pde = NULL; 154 155 remove_proc_entry("group", vg_ptr->vg_dir_pde); 156 vg_ptr->vg_dir_pde = NULL; 157 158 remove_proc_entry(vg_ptr->vg_name, lvm_proc_vg_subdir); 159 } 160} 161 162 163static inline const char *_basename(const char *str) { 164 const char *name = strrchr(str, '/'); 165 name = name ? name + 1 : str; 166 return name; 167} 168 169devfs_handle_t lvm_fs_create_lv(vg_t *vg_ptr, lv_t *lv) { 170 struct proc_dir_entry *pde; 171 const char *name; 172 173 if (!vg_ptr || !lv) 174 return NULL; 175 176 name = _basename(lv->lv_name); 177 178 lv_devfs_handle[MINOR(lv->lv_dev)] = devfs_register( 179 vg_devfs_handle[vg_ptr->vg_number], name, 180 DEVFS_FL_DEFAULT, LVM_BLK_MAJOR, MINOR(lv->lv_dev), 181 S_IFBLK | S_IRUSR | S_IWUSR | S_IRGRP, 182 &lvm_blk_dops, NULL); 183 184 if(vg_ptr->lv_subdir_pde && 185 (pde = create_proc_entry(name, S_IFREG, vg_ptr->lv_subdir_pde))) { 186 pde->read_proc = _proc_read_lv; 187 pde->data = lv; 188 } 189 return lv_devfs_handle[MINOR(lv->lv_dev)]; 190} 191 192void lvm_fs_remove_lv(vg_t *vg_ptr, lv_t *lv) { 193 194 if (!vg_ptr || !lv) 195 return; 196 197 devfs_unregister(lv_devfs_handle[MINOR(lv->lv_dev)]); 198 lv_devfs_handle[MINOR(lv->lv_dev)] = NULL; 199 200 if(vg_ptr->lv_subdir_pde) { 201 const char *name = _basename(lv->lv_name); 202 remove_proc_entry(name, vg_ptr->lv_subdir_pde); 203 } 204} 205 206 207static inline void _make_pv_name(const char *src, char *b, char *e) { 208 int offset = strlen(LVM_DIR_PREFIX); 209 if(strncmp(src, LVM_DIR_PREFIX, offset)) 210 offset = 0; 211 212 e--; 213 src += offset; 214 while(*src && (b != e)) { 215 *b++ = (*src == '/') ? '_' : *src; 216 src++; 217 } 218 *b = '\0'; 219} 220 221void lvm_fs_create_pv(vg_t *vg_ptr, pv_t *pv) { 222 struct proc_dir_entry *pde; 223 char name[NAME_LEN]; 224 225 if (!vg_ptr || !pv) 226 return; 227 228 if(!vg_ptr->pv_subdir_pde) 229 return; 230 231 _make_pv_name(pv->pv_name, name, name + sizeof(name)); 232 if((pde = create_proc_entry(name, S_IFREG, vg_ptr->pv_subdir_pde))) { 233 pde->read_proc = _proc_read_pv; 234 pde->data = pv; 235 } 236} 237 238void lvm_fs_remove_pv(vg_t *vg_ptr, pv_t *pv) { 239 char name[NAME_LEN]; 240 241 if (!vg_ptr || !pv) 242 return; 243 244 if(!vg_ptr->pv_subdir_pde) 245 return; 246 247 _make_pv_name(pv->pv_name, name, name + sizeof(name)); 248 remove_proc_entry(name, vg_ptr->pv_subdir_pde); 249} 250 251 252static int _proc_read_vg(char *page, char **start, off_t off, 253 int count, int *eof, void *data) { 254 int sz = 0; 255 vg_t *vg_ptr = data; 256 char uuid[NAME_LEN]; 257 258 sz += sprintf(page + sz, "name: %s\n", vg_ptr->vg_name); 259 sz += sprintf(page + sz, "size: %u\n", 260 vg_ptr->pe_total * vg_ptr->pe_size / 2); 261 sz += sprintf(page + sz, "access: %u\n", vg_ptr->vg_access); 262 sz += sprintf(page + sz, "status: %u\n", vg_ptr->vg_status); 263 sz += sprintf(page + sz, "number: %u\n", vg_ptr->vg_number); 264 sz += sprintf(page + sz, "LV max: %u\n", vg_ptr->lv_max); 265 sz += sprintf(page + sz, "LV current: %u\n", vg_ptr->lv_cur); 266 sz += sprintf(page + sz, "LV open: %u\n", vg_ptr->lv_open); 267 sz += sprintf(page + sz, "PV max: %u\n", vg_ptr->pv_max); 268 sz += sprintf(page + sz, "PV current: %u\n", vg_ptr->pv_cur); 269 sz += sprintf(page + sz, "PV active: %u\n", vg_ptr->pv_act); 270 sz += sprintf(page + sz, "PE size: %u\n", vg_ptr->pe_size / 2); 271 sz += sprintf(page + sz, "PE total: %u\n", vg_ptr->pe_total); 272 sz += sprintf(page + sz, "PE allocated: %u\n", vg_ptr->pe_allocated); 273 274 _show_uuid(vg_ptr->vg_uuid, uuid, uuid + sizeof(uuid)); 275 sz += sprintf(page + sz, "uuid: %s\n", uuid); 276 277 return sz; 278} 279 280static int _proc_read_lv(char *page, char **start, off_t off, 281 int count, int *eof, void *data) { 282 int sz = 0; 283 lv_t *lv = data; 284 285 sz += sprintf(page + sz, "name: %s\n", lv->lv_name); 286 sz += sprintf(page + sz, "size: %u\n", lv->lv_size); 287 sz += sprintf(page + sz, "access: %u\n", lv->lv_access); 288 sz += sprintf(page + sz, "status: %u\n", lv->lv_status); 289 sz += sprintf(page + sz, "number: %u\n", lv->lv_number); 290 sz += sprintf(page + sz, "open: %u\n", lv->lv_open); 291 sz += sprintf(page + sz, "allocation: %u\n", lv->lv_allocation); 292 if(lv->lv_stripes > 1) { 293 sz += sprintf(page + sz, "stripes: %u\n", 294 lv->lv_stripes); 295 sz += sprintf(page + sz, "stripesize: %u\n", 296 lv->lv_stripesize); 297 } 298 sz += sprintf(page + sz, "device: %02u:%02u\n", 299 MAJOR(lv->lv_dev), MINOR(lv->lv_dev)); 300 301 return sz; 302} 303 304static int _proc_read_pv(char *page, char **start, off_t off, 305 int count, int *eof, void *data) { 306 int sz = 0; 307 pv_t *pv = data; 308 char uuid[NAME_LEN]; 309 310 sz += sprintf(page + sz, "name: %s\n", pv->pv_name); 311 sz += sprintf(page + sz, "size: %u\n", pv->pv_size); 312 sz += sprintf(page + sz, "status: %u\n", pv->pv_status); 313 sz += sprintf(page + sz, "number: %u\n", pv->pv_number); 314 sz += sprintf(page + sz, "allocatable: %u\n", pv->pv_allocatable); 315 sz += sprintf(page + sz, "LV current: %u\n", pv->lv_cur); 316 sz += sprintf(page + sz, "PE size: %u\n", pv->pe_size / 2); 317 sz += sprintf(page + sz, "PE total: %u\n", pv->pe_total); 318 sz += sprintf(page + sz, "PE allocated: %u\n", pv->pe_allocated); 319 sz += sprintf(page + sz, "device: %02u:%02u\n", 320 MAJOR(pv->pv_dev), MINOR(pv->pv_dev)); 321 322 _show_uuid(pv->pv_uuid, uuid, uuid + sizeof(uuid)); 323 sz += sprintf(page + sz, "uuid: %s\n", uuid); 324 325 return sz; 326} 327 328static int _proc_read_global(char *page, char **start, off_t pos, int count, 329 int *eof, void *data) { 330 331#define LVM_PROC_BUF ( i == 0 ? dummy_buf : &buf[sz]) 332 333 int c, i, l, p, v, vg_counter, pv_counter, lv_counter, lv_open_counter, 334 lv_open_total, pe_t_bytes, hash_table_bytes, lv_block_exception_t_bytes, seconds; 335 static off_t sz; 336 off_t sz_last; 337 static char *buf = NULL; 338 static char dummy_buf[160]; /* sized for 2 lines */ 339 vg_t *vg_ptr; 340 lv_t *lv_ptr; 341 pv_t *pv_ptr; 342 343 344#ifdef DEBUG_LVM_PROC_GET_INFO 345 printk(KERN_DEBUG 346 "%s - lvm_proc_get_global_info CALLED pos: %lu count: %d\n", 347 lvm_name, pos, count); 348#endif 349 350 if(pos != 0 && buf != NULL) 351 goto out; 352 353 sz_last = vg_counter = pv_counter = lv_counter = lv_open_counter = \ 354 lv_open_total = pe_t_bytes = hash_table_bytes = \ 355 lv_block_exception_t_bytes = 0; 356 357 /* get some statistics */ 358 for (v = 0; v < ABS_MAX_VG; v++) { 359 if ((vg_ptr = vg[v]) != NULL) { 360 vg_counter++; 361 pv_counter += vg_ptr->pv_cur; 362 lv_counter += vg_ptr->lv_cur; 363 if (vg_ptr->lv_cur > 0) { 364 for (l = 0; l < vg[v]->lv_max; l++) { 365 if ((lv_ptr = vg_ptr->lv[l]) != NULL) { 366 pe_t_bytes += lv_ptr->lv_allocated_le; 367 hash_table_bytes += lv_ptr->lv_snapshot_hash_table_size; 368 if (lv_ptr->lv_block_exception != NULL) 369 lv_block_exception_t_bytes += lv_ptr->lv_remap_end; 370 if (lv_ptr->lv_open > 0) { 371 lv_open_counter++; 372 lv_open_total += lv_ptr->lv_open; 373 } 374 } 375 } 376 } 377 } 378 } 379 380 pe_t_bytes *= sizeof(pe_t); 381 lv_block_exception_t_bytes *= sizeof(lv_block_exception_t); 382 383 if (buf != NULL) { 384 P_KFREE("%s -- vfree %d\n", lvm_name, __LINE__); 385 lock_kernel(); 386 vfree(buf); 387 unlock_kernel(); 388 buf = NULL; 389 } 390 /* 2 times: first to get size to allocate buffer, 391 2nd to fill the malloced buffer */ 392 for (i = 0; i < 2; i++) { 393 sz = 0; 394 sz += sprintf(LVM_PROC_BUF, 395 "LVM " 396#ifdef MODULE 397 "module" 398#else 399 "driver" 400#endif 401 " %s\n\n" 402 "Total: %d VG%s %d PV%s %d LV%s ", 403 lvm_version, 404 vg_counter, vg_counter == 1 ? "" : "s", 405 pv_counter, pv_counter == 1 ? "" : "s", 406 lv_counter, lv_counter == 1 ? "" : "s"); 407 sz += sprintf(LVM_PROC_BUF, 408 "(%d LV%s open", 409 lv_open_counter, 410 lv_open_counter == 1 ? "" : "s"); 411 if (lv_open_total > 0) 412 sz += sprintf(LVM_PROC_BUF, 413 " %d times)\n", 414 lv_open_total); 415 else 416 sz += sprintf(LVM_PROC_BUF, ")"); 417 sz += sprintf(LVM_PROC_BUF, 418 "\nGlobal: %lu bytes malloced IOP version: %d ", 419 vg_counter * sizeof(vg_t) + 420 pv_counter * sizeof(pv_t) + 421 lv_counter * sizeof(lv_t) + 422 pe_t_bytes + hash_table_bytes + lv_block_exception_t_bytes + sz_last, 423 lvm_iop_version); 424 425 seconds = CURRENT_TIME - loadtime; 426 if (seconds < 0) 427 loadtime = CURRENT_TIME + seconds; 428 if (seconds / 86400 > 0) { 429 sz += sprintf(LVM_PROC_BUF, "%d day%s ", 430 seconds / 86400, 431 seconds / 86400 == 0 || 432 seconds / 86400 > 1 ? "s" : ""); 433 } 434 sz += sprintf(LVM_PROC_BUF, "%d:%02d:%02d active\n", 435 (seconds % 86400) / 3600, 436 (seconds % 3600) / 60, 437 seconds % 60); 438 439 if (vg_counter > 0) { 440 for (v = 0; v < ABS_MAX_VG; v++) { 441 /* volume group */ 442 if ((vg_ptr = vg[v]) != NULL) { 443 sz += _vg_info(vg_ptr, LVM_PROC_BUF); 444 445 /* physical volumes */ 446 sz += sprintf(LVM_PROC_BUF, 447 "\n PV%s ", 448 vg_ptr->pv_cur == 1 ? ": " : "s:"); 449 c = 0; 450 for (p = 0; p < vg_ptr->pv_max; p++) { 451 if ((pv_ptr = vg_ptr->pv[p]) != NULL) { 452 sz += _pv_info(pv_ptr, LVM_PROC_BUF); 453 454 c++; 455 if (c < vg_ptr->pv_cur) 456 sz += sprintf(LVM_PROC_BUF, 457 "\n "); 458 } 459 } 460 461 /* logical volumes */ 462 sz += sprintf(LVM_PROC_BUF, 463 "\n LV%s ", 464 vg_ptr->lv_cur == 1 ? ": " : "s:"); 465 c = 0; 466 for (l = 0; l < vg_ptr->lv_max; l++) { 467 if ((lv_ptr = vg_ptr->lv[l]) != NULL) { 468 sz += _lv_info(vg_ptr, lv_ptr, LVM_PROC_BUF); 469 c++; 470 if (c < vg_ptr->lv_cur) 471 sz += sprintf(LVM_PROC_BUF, 472 "\n "); 473 } 474 } 475 if (vg_ptr->lv_cur == 0) sz += sprintf(LVM_PROC_BUF, "none"); 476 sz += sprintf(LVM_PROC_BUF, "\n"); 477 } 478 } 479 } 480 if (buf == NULL) { 481 lock_kernel(); 482 buf = vmalloc(sz); 483 unlock_kernel(); 484 if (buf == NULL) { 485 sz = 0; 486 return sprintf(page, "%s - vmalloc error at line %d\n", 487 lvm_name, __LINE__); 488 } 489 } 490 sz_last = sz; 491 } 492 493 out: 494 if (pos > sz - 1) { 495 lock_kernel(); 496 vfree(buf); 497 unlock_kernel(); 498 buf = NULL; 499 return 0; 500 } 501 *start = &buf[pos]; 502 if (sz - pos < count) 503 return sz - pos; 504 else 505 return count; 506 507#undef LVM_PROC_BUF 508} 509 510/* 511 * provide VG info for proc filesystem use (global) 512 */ 513static int _vg_info(vg_t *vg_ptr, char *buf) { 514 int sz = 0; 515 char inactive_flag = ' '; 516 517 if (!(vg_ptr->vg_status & VG_ACTIVE)) inactive_flag = 'I'; 518 sz = sprintf(buf, 519 "\nVG: %c%s [%d PV, %d LV/%d open] " 520 " PE Size: %d KB\n" 521 " Usage [KB/PE]: %d /%d total " 522 "%d /%d used %d /%d free", 523 inactive_flag, 524 vg_ptr->vg_name, 525 vg_ptr->pv_cur, 526 vg_ptr->lv_cur, 527 vg_ptr->lv_open, 528 vg_ptr->pe_size >> 1, 529 vg_ptr->pe_size * vg_ptr->pe_total >> 1, 530 vg_ptr->pe_total, 531 vg_ptr->pe_allocated * vg_ptr->pe_size >> 1, 532 vg_ptr->pe_allocated, 533 (vg_ptr->pe_total - vg_ptr->pe_allocated) * 534 vg_ptr->pe_size >> 1, 535 vg_ptr->pe_total - vg_ptr->pe_allocated); 536 return sz; 537} 538 539 540/* 541 * provide LV info for proc filesystem use (global) 542 */ 543static int _lv_info(vg_t *vg_ptr, lv_t *lv_ptr, char *buf) { 544 int sz = 0; 545 char inactive_flag = 'A', allocation_flag = ' ', 546 stripes_flag = ' ', rw_flag = ' ', *basename; 547 548 if (!(lv_ptr->lv_status & LV_ACTIVE)) 549 inactive_flag = 'I'; 550 rw_flag = 'R'; 551 if (lv_ptr->lv_access & LV_WRITE) 552 rw_flag = 'W'; 553 allocation_flag = 'D'; 554 if (lv_ptr->lv_allocation & LV_CONTIGUOUS) 555 allocation_flag = 'C'; 556 stripes_flag = 'L'; 557 if (lv_ptr->lv_stripes > 1) 558 stripes_flag = 'S'; 559 sz += sprintf(buf+sz, 560 "[%c%c%c%c", 561 inactive_flag, 562 rw_flag, 563 allocation_flag, 564 stripes_flag); 565 if (lv_ptr->lv_stripes > 1) 566 sz += sprintf(buf+sz, "%-2d", 567 lv_ptr->lv_stripes); 568 else 569 sz += sprintf(buf+sz, " "); 570 571 basename = strrchr(lv_ptr->lv_name, '/'); 572 if ( basename == 0) basename = lv_ptr->lv_name; 573 else basename++; 574 sz += sprintf(buf+sz, "] %-25s", basename); 575 if (strlen(basename) > 25) 576 sz += sprintf(buf+sz, 577 "\n "); 578 sz += sprintf(buf+sz, "%9d /%-6d ", 579 lv_ptr->lv_size >> 1, 580 lv_ptr->lv_size / vg_ptr->pe_size); 581 582 if (lv_ptr->lv_open == 0) 583 sz += sprintf(buf+sz, "close"); 584 else 585 sz += sprintf(buf+sz, "%dx open", 586 lv_ptr->lv_open); 587 588 return sz; 589} 590 591 592/* 593 * provide PV info for proc filesystem use (global) 594 */ 595static int _pv_info(pv_t *pv, char *buf) { 596 int sz = 0; 597 char inactive_flag = 'A', allocation_flag = ' '; 598 char *pv_name = NULL; 599 600 if (!(pv->pv_status & PV_ACTIVE)) 601 inactive_flag = 'I'; 602 allocation_flag = 'A'; 603 if (!(pv->pv_allocatable & PV_ALLOCATABLE)) 604 allocation_flag = 'N'; 605 pv_name = strchr(pv->pv_name+1,'/'); 606 if ( pv_name == 0) pv_name = pv->pv_name; 607 else pv_name++; 608 sz = sprintf(buf, 609 "[%c%c] %-21s %8d /%-6d " 610 "%8d /%-6d %8d /%-6d", 611 inactive_flag, 612 allocation_flag, 613 pv_name, 614 pv->pe_total * pv->pe_size >> 1, 615 pv->pe_total, 616 pv->pe_allocated * pv->pe_size >> 1, 617 pv->pe_allocated, 618 (pv->pe_total - pv->pe_allocated) * 619 pv->pe_size >> 1, 620 pv->pe_total - pv->pe_allocated); 621 return sz; 622} 623 624static void _show_uuid(const char *src, char *b, char *e) { 625 int i; 626 627 e--; 628 for(i = 0; *src && (b != e); i++) { 629 if(i && !(i & 0x3)) 630 *b++ = '-'; 631 *b++ = *src++; 632 } 633 *b = '\0'; 634} 635