📄 lvm-fs.c
字号:
/* * 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 * 16/12/2001 - fix devfs unregister order and prevent duplicate unreg (REG) * */#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);static devfs_handle_t lvm_devfs_handle;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; /* Must create device node. Think about "devfs=only" situation */ lvm_devfs_handle = devfs_register( 0 , "lvm", 0, LVM_CHAR_MAJOR, 0, S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP, &lvm_chr_fops, NULL); 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() { devfs_unregister (lvm_devfs_handle); 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]); ch_devfs_handle[vg_ptr->vg_number] = NULL; /* 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]); /* must not remove directory before leaf nodes */ devfs_unregister(vg_devfs_handle[vg_ptr->vg_number]); vg_devfs_handle[vg_ptr->vg_number] = NULL; 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)]); lv_devfs_handle[MINOR(lv->lv_dev)] = NULL; 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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -