patch-2.4.15 linux/drivers/md/lvm-fs.c
Next file: linux/drivers/md/lvm-internal.h
Previous file: linux/drivers/md/Makefile
Back to the patch index
Back to the overall index
- Lines: 624
- Date:
Sun Nov 11 10:09:32 2001
- Orig file:
v2.4.14/linux/drivers/md/lvm-fs.c
- Orig date:
Wed Dec 31 16:00:00 1969
diff -u --recursive --new-file v2.4.14/linux/drivers/md/lvm-fs.c linux/drivers/md/lvm-fs.c
@@ -0,0 +1,623 @@
+/*
+ * kernel/lvm-fs.c
+ *
+ * Copyright (C) 2001 Sistina Software
+ *
+ * January,February 2001
+ *
+ * LVM driver is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * LVM driver is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU CC; see the file COPYING. If not, write to
+ * the Free Software Foundation, 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+
+/*
+ * Changelog
+ *
+ * 11/01/2001 - First version (Joe Thornber)
+ * 21/03/2001 - added display of stripes and stripe size (HM)
+ * 04/10/2001 - corrected devfs_register() call in lvm_init_fs()
+ * 11/04/2001 - don't devfs_register("lvm") as user-space always does it
+ * 10/05/2001 - show more of PV name in /proc/lvm/global
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/version.h>
+#include <linux/module.h>
+
+#include <linux/kernel.h>
+#include <linux/vmalloc.h>
+#include <linux/smp_lock.h>
+
+#include <linux/devfs_fs_kernel.h>
+#include <linux/proc_fs.h>
+#include <linux/init.h>
+#include <linux/lvm.h>
+
+#include "lvm-internal.h"
+
+
+static int _proc_read_vg(char *page, char **start, off_t off,
+ int count, int *eof, void *data);
+static int _proc_read_lv(char *page, char **start, off_t off,
+ int count, int *eof, void *data);
+static int _proc_read_pv(char *page, char **start, off_t off,
+ int count, int *eof, void *data);
+static int _proc_read_global(char *page, char **start, off_t off,
+ int count, int *eof, void *data);
+
+static int _vg_info(vg_t *vg_ptr, char *buf);
+static int _lv_info(vg_t *vg_ptr, lv_t *lv_ptr, char *buf);
+static int _pv_info(pv_t *pv_ptr, char *buf);
+
+static void _show_uuid(const char *src, char *b, char *e);
+
+#if 0
+static devfs_handle_t lvm_devfs_handle;
+#endif
+static devfs_handle_t vg_devfs_handle[MAX_VG];
+static devfs_handle_t ch_devfs_handle[MAX_VG];
+static devfs_handle_t lv_devfs_handle[MAX_LV];
+
+static struct proc_dir_entry *lvm_proc_dir = NULL;
+static struct proc_dir_entry *lvm_proc_vg_subdir = NULL;
+
+/* inline functions */
+
+/* public interface */
+void __init lvm_init_fs() {
+ struct proc_dir_entry *pde;
+
+/* User-space has already registered this */
+#if 0
+ lvm_devfs_handle = devfs_register(
+ 0 , "lvm", 0, LVM_CHAR_MAJOR, 0,
+ S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP,
+ &lvm_chr_fops, NULL);
+#endif
+
+ lvm_proc_dir = create_proc_entry(LVM_DIR, S_IFDIR, &proc_root);
+ if (lvm_proc_dir) {
+ lvm_proc_vg_subdir = create_proc_entry(LVM_VG_SUBDIR, S_IFDIR,
+ lvm_proc_dir);
+ pde = create_proc_entry(LVM_GLOBAL, S_IFREG, lvm_proc_dir);
+ if ( pde != NULL) pde->read_proc = _proc_read_global;
+ }
+}
+
+void lvm_fin_fs() {
+#if 0
+ devfs_unregister (lvm_devfs_handle);
+#endif
+
+ remove_proc_entry(LVM_GLOBAL, lvm_proc_dir);
+ remove_proc_entry(LVM_VG_SUBDIR, lvm_proc_dir);
+ remove_proc_entry(LVM_DIR, &proc_root);
+}
+
+void lvm_fs_create_vg(vg_t *vg_ptr) {
+ struct proc_dir_entry *pde;
+
+ vg_devfs_handle[vg_ptr->vg_number] =
+ devfs_mk_dir(0, vg_ptr->vg_name, NULL);
+
+ ch_devfs_handle[vg_ptr->vg_number] = devfs_register(
+ vg_devfs_handle[vg_ptr->vg_number] , "group",
+ DEVFS_FL_DEFAULT, LVM_CHAR_MAJOR, vg_ptr->vg_number,
+ S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP,
+ &lvm_chr_fops, NULL);
+
+ vg_ptr->vg_dir_pde = create_proc_entry(vg_ptr->vg_name, S_IFDIR,
+ lvm_proc_vg_subdir);
+
+ if((pde = create_proc_entry("group", S_IFREG, vg_ptr->vg_dir_pde))) {
+ pde->read_proc = _proc_read_vg;
+ pde->data = vg_ptr;
+ }
+
+ vg_ptr->lv_subdir_pde =
+ create_proc_entry(LVM_LV_SUBDIR, S_IFDIR, vg_ptr->vg_dir_pde);
+
+ vg_ptr->pv_subdir_pde =
+ create_proc_entry(LVM_PV_SUBDIR, S_IFDIR, vg_ptr->vg_dir_pde);
+}
+
+void lvm_fs_remove_vg(vg_t *vg_ptr) {
+ int i;
+
+ devfs_unregister(ch_devfs_handle[vg_ptr->vg_number]);
+ devfs_unregister(vg_devfs_handle[vg_ptr->vg_number]);
+
+ /* remove lv's */
+ for(i = 0; i < vg_ptr->lv_max; i++)
+ if(vg_ptr->lv[i]) lvm_fs_remove_lv(vg_ptr, vg_ptr->lv[i]);
+
+ /* remove pv's */
+ for(i = 0; i < vg_ptr->pv_max; i++)
+ if(vg_ptr->pv[i]) lvm_fs_remove_pv(vg_ptr, vg_ptr->pv[i]);
+
+ if(vg_ptr->vg_dir_pde) {
+ remove_proc_entry(LVM_LV_SUBDIR, vg_ptr->vg_dir_pde);
+ vg_ptr->lv_subdir_pde = NULL;
+
+ remove_proc_entry(LVM_PV_SUBDIR, vg_ptr->vg_dir_pde);
+ vg_ptr->pv_subdir_pde = NULL;
+
+ remove_proc_entry("group", vg_ptr->vg_dir_pde);
+ vg_ptr->vg_dir_pde = NULL;
+
+ remove_proc_entry(vg_ptr->vg_name, lvm_proc_vg_subdir);
+ }
+}
+
+
+static inline const char *_basename(const char *str) {
+ const char *name = strrchr(str, '/');
+ name = name ? name + 1 : str;
+ return name;
+}
+
+devfs_handle_t lvm_fs_create_lv(vg_t *vg_ptr, lv_t *lv) {
+ struct proc_dir_entry *pde;
+ const char *name = _basename(lv->lv_name);
+
+ lv_devfs_handle[MINOR(lv->lv_dev)] = devfs_register(
+ vg_devfs_handle[vg_ptr->vg_number], name,
+ DEVFS_FL_DEFAULT, LVM_BLK_MAJOR, MINOR(lv->lv_dev),
+ S_IFBLK | S_IRUSR | S_IWUSR | S_IRGRP,
+ &lvm_blk_dops, NULL);
+
+ if(vg_ptr->lv_subdir_pde &&
+ (pde = create_proc_entry(name, S_IFREG, vg_ptr->lv_subdir_pde))) {
+ pde->read_proc = _proc_read_lv;
+ pde->data = lv;
+ }
+ return lv_devfs_handle[MINOR(lv->lv_dev)];
+}
+
+void lvm_fs_remove_lv(vg_t *vg_ptr, lv_t *lv) {
+ devfs_unregister(lv_devfs_handle[MINOR(lv->lv_dev)]);
+
+ if(vg_ptr->lv_subdir_pde) {
+ const char *name = _basename(lv->lv_name);
+ remove_proc_entry(name, vg_ptr->lv_subdir_pde);
+ }
+}
+
+
+static inline void _make_pv_name(const char *src, char *b, char *e) {
+ int offset = strlen(LVM_DIR_PREFIX);
+ if(strncmp(src, LVM_DIR_PREFIX, offset))
+ offset = 0;
+
+ e--;
+ src += offset;
+ while(*src && (b != e)) {
+ *b++ = (*src == '/') ? '_' : *src;
+ src++;
+ }
+ *b = '\0';
+}
+
+void lvm_fs_create_pv(vg_t *vg_ptr, pv_t *pv) {
+ struct proc_dir_entry *pde;
+ char name[NAME_LEN];
+
+ if(!vg_ptr->pv_subdir_pde)
+ return;
+
+ _make_pv_name(pv->pv_name, name, name + sizeof(name));
+ if((pde = create_proc_entry(name, S_IFREG, vg_ptr->pv_subdir_pde))) {
+ pde->read_proc = _proc_read_pv;
+ pde->data = pv;
+ }
+}
+
+void lvm_fs_remove_pv(vg_t *vg_ptr, pv_t *pv) {
+ char name[NAME_LEN];
+
+ if(!vg_ptr->pv_subdir_pde)
+ return;
+
+ _make_pv_name(pv->pv_name, name, name + sizeof(name));
+ remove_proc_entry(name, vg_ptr->pv_subdir_pde);
+}
+
+
+static int _proc_read_vg(char *page, char **start, off_t off,
+ int count, int *eof, void *data) {
+ int sz = 0;
+ vg_t *vg_ptr = data;
+ char uuid[NAME_LEN];
+
+ sz += sprintf(page + sz, "name: %s\n", vg_ptr->vg_name);
+ sz += sprintf(page + sz, "size: %u\n",
+ vg_ptr->pe_total * vg_ptr->pe_size / 2);
+ sz += sprintf(page + sz, "access: %u\n", vg_ptr->vg_access);
+ sz += sprintf(page + sz, "status: %u\n", vg_ptr->vg_status);
+ sz += sprintf(page + sz, "number: %u\n", vg_ptr->vg_number);
+ sz += sprintf(page + sz, "LV max: %u\n", vg_ptr->lv_max);
+ sz += sprintf(page + sz, "LV current: %u\n", vg_ptr->lv_cur);
+ sz += sprintf(page + sz, "LV open: %u\n", vg_ptr->lv_open);
+ sz += sprintf(page + sz, "PV max: %u\n", vg_ptr->pv_max);
+ sz += sprintf(page + sz, "PV current: %u\n", vg_ptr->pv_cur);
+ sz += sprintf(page + sz, "PV active: %u\n", vg_ptr->pv_act);
+ sz += sprintf(page + sz, "PE size: %u\n", vg_ptr->pe_size / 2);
+ sz += sprintf(page + sz, "PE total: %u\n", vg_ptr->pe_total);
+ sz += sprintf(page + sz, "PE allocated: %u\n", vg_ptr->pe_allocated);
+
+ _show_uuid(vg_ptr->vg_uuid, uuid, uuid + sizeof(uuid));
+ sz += sprintf(page + sz, "uuid: %s\n", uuid);
+
+ return sz;
+}
+
+static int _proc_read_lv(char *page, char **start, off_t off,
+ int count, int *eof, void *data) {
+ int sz = 0;
+ lv_t *lv = data;
+
+ sz += sprintf(page + sz, "name: %s\n", lv->lv_name);
+ sz += sprintf(page + sz, "size: %u\n", lv->lv_size);
+ sz += sprintf(page + sz, "access: %u\n", lv->lv_access);
+ sz += sprintf(page + sz, "status: %u\n", lv->lv_status);
+ sz += sprintf(page + sz, "number: %u\n", lv->lv_number);
+ sz += sprintf(page + sz, "open: %u\n", lv->lv_open);
+ sz += sprintf(page + sz, "allocation: %u\n", lv->lv_allocation);
+ if(lv->lv_stripes > 1) {
+ sz += sprintf(page + sz, "stripes: %u\n",
+ lv->lv_stripes);
+ sz += sprintf(page + sz, "stripesize: %u\n",
+ lv->lv_stripesize);
+ }
+ sz += sprintf(page + sz, "device: %02u:%02u\n",
+ MAJOR(lv->lv_dev), MINOR(lv->lv_dev));
+
+ return sz;
+}
+
+static int _proc_read_pv(char *page, char **start, off_t off,
+ int count, int *eof, void *data) {
+ int sz = 0;
+ pv_t *pv = data;
+ char uuid[NAME_LEN];
+
+ sz += sprintf(page + sz, "name: %s\n", pv->pv_name);
+ sz += sprintf(page + sz, "size: %u\n", pv->pv_size);
+ sz += sprintf(page + sz, "status: %u\n", pv->pv_status);
+ sz += sprintf(page + sz, "number: %u\n", pv->pv_number);
+ sz += sprintf(page + sz, "allocatable: %u\n", pv->pv_allocatable);
+ sz += sprintf(page + sz, "LV current: %u\n", pv->lv_cur);
+ sz += sprintf(page + sz, "PE size: %u\n", pv->pe_size / 2);
+ sz += sprintf(page + sz, "PE total: %u\n", pv->pe_total);
+ sz += sprintf(page + sz, "PE allocated: %u\n", pv->pe_allocated);
+ sz += sprintf(page + sz, "device: %02u:%02u\n",
+ MAJOR(pv->pv_dev), MINOR(pv->pv_dev));
+
+ _show_uuid(pv->pv_uuid, uuid, uuid + sizeof(uuid));
+ sz += sprintf(page + sz, "uuid: %s\n", uuid);
+
+ return sz;
+}
+
+static int _proc_read_global(char *page, char **start, off_t pos, int count,
+ int *eof, void *data) {
+
+#define LVM_PROC_BUF ( i == 0 ? dummy_buf : &buf[sz])
+
+ int c, i, l, p, v, vg_counter, pv_counter, lv_counter, lv_open_counter,
+ lv_open_total, pe_t_bytes, hash_table_bytes, lv_block_exception_t_bytes, seconds;
+ static off_t sz;
+ off_t sz_last;
+ static char *buf = NULL;
+ static char dummy_buf[160]; /* sized for 2 lines */
+ vg_t *vg_ptr;
+ lv_t *lv_ptr;
+ pv_t *pv_ptr;
+
+
+#ifdef DEBUG_LVM_PROC_GET_INFO
+ printk(KERN_DEBUG
+ "%s - lvm_proc_get_global_info CALLED pos: %lu count: %d\n",
+ lvm_name, pos, count);
+#endif
+
+ if(pos != 0 && buf != NULL)
+ goto out;
+
+ sz_last = vg_counter = pv_counter = lv_counter = lv_open_counter = \
+ lv_open_total = pe_t_bytes = hash_table_bytes = \
+ lv_block_exception_t_bytes = 0;
+
+ /* get some statistics */
+ for (v = 0; v < ABS_MAX_VG; v++) {
+ if ((vg_ptr = vg[v]) != NULL) {
+ vg_counter++;
+ pv_counter += vg_ptr->pv_cur;
+ lv_counter += vg_ptr->lv_cur;
+ if (vg_ptr->lv_cur > 0) {
+ for (l = 0; l < vg[v]->lv_max; l++) {
+ if ((lv_ptr = vg_ptr->lv[l]) != NULL) {
+ pe_t_bytes += lv_ptr->lv_allocated_le;
+ hash_table_bytes += lv_ptr->lv_snapshot_hash_table_size;
+ if (lv_ptr->lv_block_exception != NULL)
+ lv_block_exception_t_bytes += lv_ptr->lv_remap_end;
+ if (lv_ptr->lv_open > 0) {
+ lv_open_counter++;
+ lv_open_total += lv_ptr->lv_open;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ pe_t_bytes *= sizeof(pe_t);
+ lv_block_exception_t_bytes *= sizeof(lv_block_exception_t);
+
+ if (buf != NULL) {
+ P_KFREE("%s -- vfree %d\n", lvm_name, __LINE__);
+ lock_kernel();
+ vfree(buf);
+ unlock_kernel();
+ buf = NULL;
+ }
+ /* 2 times: first to get size to allocate buffer,
+ 2nd to fill the malloced buffer */
+ for (i = 0; i < 2; i++) {
+ sz = 0;
+ sz += sprintf(LVM_PROC_BUF,
+ "LVM "
+#ifdef MODULE
+ "module"
+#else
+ "driver"
+#endif
+ " %s\n\n"
+ "Total: %d VG%s %d PV%s %d LV%s ",
+ lvm_version,
+ vg_counter, vg_counter == 1 ? "" : "s",
+ pv_counter, pv_counter == 1 ? "" : "s",
+ lv_counter, lv_counter == 1 ? "" : "s");
+ sz += sprintf(LVM_PROC_BUF,
+ "(%d LV%s open",
+ lv_open_counter,
+ lv_open_counter == 1 ? "" : "s");
+ if (lv_open_total > 0)
+ sz += sprintf(LVM_PROC_BUF,
+ " %d times)\n",
+ lv_open_total);
+ else
+ sz += sprintf(LVM_PROC_BUF, ")");
+ sz += sprintf(LVM_PROC_BUF,
+ "\nGlobal: %lu bytes malloced IOP version: %d ",
+ vg_counter * sizeof(vg_t) +
+ pv_counter * sizeof(pv_t) +
+ lv_counter * sizeof(lv_t) +
+ pe_t_bytes + hash_table_bytes + lv_block_exception_t_bytes + sz_last,
+ lvm_iop_version);
+
+ seconds = CURRENT_TIME - loadtime;
+ if (seconds < 0)
+ loadtime = CURRENT_TIME + seconds;
+ if (seconds / 86400 > 0) {
+ sz += sprintf(LVM_PROC_BUF, "%d day%s ",
+ seconds / 86400,
+ seconds / 86400 == 0 ||
+ seconds / 86400 > 1 ? "s" : "");
+ }
+ sz += sprintf(LVM_PROC_BUF, "%d:%02d:%02d active\n",
+ (seconds % 86400) / 3600,
+ (seconds % 3600) / 60,
+ seconds % 60);
+
+ if (vg_counter > 0) {
+ for (v = 0; v < ABS_MAX_VG; v++) {
+ /* volume group */
+ if ((vg_ptr = vg[v]) != NULL) {
+ sz += _vg_info(vg_ptr, LVM_PROC_BUF);
+
+ /* physical volumes */
+ sz += sprintf(LVM_PROC_BUF,
+ "\n PV%s ",
+ vg_ptr->pv_cur == 1 ? ": " : "s:");
+ c = 0;
+ for (p = 0; p < vg_ptr->pv_max; p++) {
+ if ((pv_ptr = vg_ptr->pv[p]) != NULL) {
+ sz += _pv_info(pv_ptr, LVM_PROC_BUF);
+
+ c++;
+ if (c < vg_ptr->pv_cur)
+ sz += sprintf(LVM_PROC_BUF,
+ "\n ");
+ }
+ }
+
+ /* logical volumes */
+ sz += sprintf(LVM_PROC_BUF,
+ "\n LV%s ",
+ vg_ptr->lv_cur == 1 ? ": " : "s:");
+ c = 0;
+ for (l = 0; l < vg_ptr->lv_max; l++) {
+ if ((lv_ptr = vg_ptr->lv[l]) != NULL) {
+ sz += _lv_info(vg_ptr, lv_ptr, LVM_PROC_BUF);
+ c++;
+ if (c < vg_ptr->lv_cur)
+ sz += sprintf(LVM_PROC_BUF,
+ "\n ");
+ }
+ }
+ if (vg_ptr->lv_cur == 0) sz += sprintf(LVM_PROC_BUF, "none");
+ sz += sprintf(LVM_PROC_BUF, "\n");
+ }
+ }
+ }
+ if (buf == NULL) {
+ lock_kernel();
+ buf = vmalloc(sz);
+ unlock_kernel();
+ if (buf == NULL) {
+ sz = 0;
+ return sprintf(page, "%s - vmalloc error at line %d\n",
+ lvm_name, __LINE__);
+ }
+ }
+ sz_last = sz;
+ }
+
+ out:
+ if (pos > sz - 1) {
+ lock_kernel();
+ vfree(buf);
+ unlock_kernel();
+ buf = NULL;
+ return 0;
+ }
+ *start = &buf[pos];
+ if (sz - pos < count)
+ return sz - pos;
+ else
+ return count;
+
+#undef LVM_PROC_BUF
+}
+
+/*
+ * provide VG info for proc filesystem use (global)
+ */
+static int _vg_info(vg_t *vg_ptr, char *buf) {
+ int sz = 0;
+ char inactive_flag = ' ';
+
+ if (!(vg_ptr->vg_status & VG_ACTIVE)) inactive_flag = 'I';
+ sz = sprintf(buf,
+ "\nVG: %c%s [%d PV, %d LV/%d open] "
+ " PE Size: %d KB\n"
+ " Usage [KB/PE]: %d /%d total "
+ "%d /%d used %d /%d free",
+ inactive_flag,
+ vg_ptr->vg_name,
+ vg_ptr->pv_cur,
+ vg_ptr->lv_cur,
+ vg_ptr->lv_open,
+ vg_ptr->pe_size >> 1,
+ vg_ptr->pe_size * vg_ptr->pe_total >> 1,
+ vg_ptr->pe_total,
+ vg_ptr->pe_allocated * vg_ptr->pe_size >> 1,
+ vg_ptr->pe_allocated,
+ (vg_ptr->pe_total - vg_ptr->pe_allocated) *
+ vg_ptr->pe_size >> 1,
+ vg_ptr->pe_total - vg_ptr->pe_allocated);
+ return sz;
+}
+
+
+/*
+ * provide LV info for proc filesystem use (global)
+ */
+static int _lv_info(vg_t *vg_ptr, lv_t *lv_ptr, char *buf) {
+ int sz = 0;
+ char inactive_flag = 'A', allocation_flag = ' ',
+ stripes_flag = ' ', rw_flag = ' ', *basename;
+
+ if (!(lv_ptr->lv_status & LV_ACTIVE))
+ inactive_flag = 'I';
+ rw_flag = 'R';
+ if (lv_ptr->lv_access & LV_WRITE)
+ rw_flag = 'W';
+ allocation_flag = 'D';
+ if (lv_ptr->lv_allocation & LV_CONTIGUOUS)
+ allocation_flag = 'C';
+ stripes_flag = 'L';
+ if (lv_ptr->lv_stripes > 1)
+ stripes_flag = 'S';
+ sz += sprintf(buf+sz,
+ "[%c%c%c%c",
+ inactive_flag,
+ rw_flag,
+ allocation_flag,
+ stripes_flag);
+ if (lv_ptr->lv_stripes > 1)
+ sz += sprintf(buf+sz, "%-2d",
+ lv_ptr->lv_stripes);
+ else
+ sz += sprintf(buf+sz, " ");
+
+ /* FIXME: use _basename */
+ basename = strrchr(lv_ptr->lv_name, '/');
+ if ( basename == 0) basename = lv_ptr->lv_name;
+ else basename++;
+ sz += sprintf(buf+sz, "] %-25s", basename);
+ if (strlen(basename) > 25)
+ sz += sprintf(buf+sz,
+ "\n ");
+ sz += sprintf(buf+sz, "%9d /%-6d ",
+ lv_ptr->lv_size >> 1,
+ lv_ptr->lv_size / vg_ptr->pe_size);
+
+ if (lv_ptr->lv_open == 0)
+ sz += sprintf(buf+sz, "close");
+ else
+ sz += sprintf(buf+sz, "%dx open",
+ lv_ptr->lv_open);
+
+ return sz;
+}
+
+
+/*
+ * provide PV info for proc filesystem use (global)
+ */
+static int _pv_info(pv_t *pv, char *buf) {
+ int sz = 0;
+ char inactive_flag = 'A', allocation_flag = ' ';
+ char *pv_name = NULL;
+
+ if (!(pv->pv_status & PV_ACTIVE))
+ inactive_flag = 'I';
+ allocation_flag = 'A';
+ if (!(pv->pv_allocatable & PV_ALLOCATABLE))
+ allocation_flag = 'N';
+ pv_name = strchr(pv->pv_name+1,'/');
+ if ( pv_name == 0) pv_name = pv->pv_name;
+ else pv_name++;
+ sz = sprintf(buf,
+ "[%c%c] %-21s %8d /%-6d "
+ "%8d /%-6d %8d /%-6d",
+ inactive_flag,
+ allocation_flag,
+ pv_name,
+ pv->pe_total * pv->pe_size >> 1,
+ pv->pe_total,
+ pv->pe_allocated * pv->pe_size >> 1,
+ pv->pe_allocated,
+ (pv->pe_total - pv->pe_allocated) *
+ pv->pe_size >> 1,
+ pv->pe_total - pv->pe_allocated);
+ return sz;
+}
+
+static void _show_uuid(const char *src, char *b, char *e) {
+ int i;
+
+ e--;
+ for(i = 0; *src && (b != e); i++) {
+ if(i && !(i & 0x3))
+ *b++ = '-';
+ *b++ = *src++;
+ }
+ *b = '\0';
+}
+MODULE_LICENSE("GPL");
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)