⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 lvm.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
/* * kernel/lvm.c * * Copyright (C) 1997 - 2000  Heinz Mauelshagen, Sistina Software * * February-November 1997 * April-May,July-August,November 1998 * January-March,May,July,September,October 1999 * January,February,July,September-November 2000 * * * 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 * *    09/11/1997 - added chr ioctls VG_STATUS_GET_COUNT *                 and VG_STATUS_GET_NAMELIST *    18/01/1998 - change lvm_chr_open/close lock handling *    30/04/1998 - changed LV_STATUS ioctl to LV_STATUS_BYNAME and *               - added   LV_STATUS_BYINDEX ioctl *               - used lvm_status_byname_req_t and *                      lvm_status_byindex_req_t vars *    04/05/1998 - added multiple device support *    08/05/1998 - added support to set/clear extendable flag in volume group *    09/05/1998 - changed output of lvm_proc_get_global_info() because of *                 support for free (eg. longer) logical volume names *    12/05/1998 - added spin_locks (thanks to Pascal van Dam *                 <pascal@ramoth.xs4all.nl>) *    25/05/1998 - fixed handling of locked PEs in lvm_map() and lvm_chr_ioctl() *    26/05/1998 - reactivated verify_area by access_ok *    07/06/1998 - used vmalloc/vfree instead of kmalloc/kfree to go *                 beyond 128/256 KB max allocation limit per call *               - #ifdef blocked spin_lock calls to avoid compile errors *                 with 2.0.x *    11/06/1998 - another enhancement to spinlock code in lvm_chr_open() *                 and use of LVM_VERSION_CODE instead of my own macros *                 (thanks to  Michael Marxmeier <mike@msede.com>) *    07/07/1998 - added statistics in lvm_map() *    08/07/1998 - saved statistics in lvm_do_lv_extend_reduce() *    25/07/1998 - used __initfunc macro *    02/08/1998 - changes for official char/block major numbers *    07/08/1998 - avoided init_module() and cleanup_module() to be static *    30/08/1998 - changed VG lv_open counter from sum of LV lv_open counters *                 to sum of LVs open (no matter how often each is) *    01/09/1998 - fixed lvm_gendisk.part[] index error *    07/09/1998 - added copying of lv_current_pe-array *                 in LV_STATUS_BYINDEX ioctl *    17/11/1998 - added KERN_* levels to printk *    13/01/1999 - fixed LV index bug in lvm_do_lv_create() which hit lvrename *    07/02/1999 - fixed spinlock handling bug in case of LVM_RESET *                 by moving spinlock code from lvm_chr_open() *                 to lvm_chr_ioctl() *               - added LVM_LOCK_LVM ioctl to lvm_chr_ioctl() *               - allowed LVM_RESET and retrieval commands to go ahead; *                 only other update ioctls are blocked now *               - fixed pv->pe to NULL for pv_status *               - using lv_req structure in lvm_chr_ioctl() now *               - fixed NULL ptr reference bug in lvm_do_lv_extend_reduce() *                 caused by uncontiguous PV array in lvm_chr_ioctl(VG_REDUCE) *    09/02/1999 - changed BLKRASET and BLKRAGET in lvm_chr_ioctl() to *                 handle lgoical volume private read ahead sector *               - implemented LV read_ahead handling with lvm_blk_read() *                 and lvm_blk_write() *    10/02/1999 - implemented 2.[12].* support function lvm_hd_name() *                 to be used in drivers/block/genhd.c by disk_name() *    12/02/1999 - fixed index bug in lvm_blk_ioctl(), HDIO_GETGEO *               - enhanced gendisk insert/remove handling *    16/02/1999 - changed to dynamic block minor number allocation to *                 have as much as 99 volume groups with 256 logical volumes *                 as the grand total; this allows having 1 volume group with *                 up to 256 logical volumes in it *    21/02/1999 - added LV open count information to proc filesystem *               - substituted redundant LVM_RESET code by calls *                 to lvm_do_vg_remove() *    22/02/1999 - used schedule_timeout() to be more responsive *                 in case of lvm_do_vg_remove() with lots of logical volumes *    19/03/1999 - fixed NULL pointer bug in module_init/lvm_init *    17/05/1999 - used DECLARE_WAIT_QUEUE_HEAD macro (>2.3.0) *               - enhanced lvm_hd_name support *    03/07/1999 - avoided use of KERNEL_VERSION macro based ifdefs and *                 memcpy_tofs/memcpy_fromfs macro redefinitions *    06/07/1999 - corrected reads/writes statistic counter copy in case *                 of striped logical volume *    28/07/1999 - implemented snapshot logical volumes *                 - lvm_chr_ioctl *                   - LV_STATUS_BYINDEX *                   - LV_STATUS_BYNAME *                 - lvm_do_lv_create *                 - lvm_do_lv_remove *                 - lvm_map *                 - new lvm_snapshot_remap_block *                 - new lvm_snapshot_remap_new_block *    08/10/1999 - implemented support for multiple snapshots per *                 original logical volume *    12/10/1999 - support for 2.3.19 *    11/11/1999 - support for 2.3.28 *    21/11/1999 - changed lvm_map() interface to buffer_head based *    19/12/1999 - support for 2.3.33 *    01/01/2000 - changed locking concept in lvm_map(), *                 lvm_do_vg_create() and lvm_do_lv_remove() *    15/01/2000 - fixed PV_FLUSH bug in lvm_chr_ioctl() *    24/01/2000 - ported to 2.3.40 including Alan Cox's pointer changes etc. *    29/01/2000 - used kmalloc/kfree again for all small structures *    20/01/2000 - cleaned up lvm_chr_ioctl by moving code *                 to seperated functions *               - avoided "/dev/" in proc filesystem output *               - avoided inline strings functions lvm_strlen etc. *    14/02/2000 - support for 2.3.43 *               - integrated Andrea Arcagneli's snapshot code *    25/06/2000 - james (chip) , IKKHAYD! roffl *    26/06/2000 - enhanced lv_extend_reduce for snapshot logical volume support *    06/09/2000 - added devfs support *    07/09/2000 - changed IOP version to 9 *               - started to add new char ioctl LV_STATUS_BYDEV_T to support *                 getting an lv_t based on the dev_t of the Logical Volume *    14/09/2000 - enhanced lvm_do_lv_create to upcall VFS functions *                 to sync and lock, activate snapshot and unlock the FS *                 (to support journaled filesystems) *    18/09/2000 - hardsector size support *    27/09/2000 - implemented lvm_do_lv_rename() and lvm_do_vg_rename() *    30/10/2000 - added Andi Kleen's LV_BMAP ioctl to support LILO *    01/11/2000 - added memory information on hash tables to *                 lvm_proc_get_global_info() *    02/11/2000 - implemented /proc/lvm/ hierarchy *    07/12/2000 - make sure lvm_make_request_fn returns correct value - 0 or 1 - NeilBrown * */static char *lvm_version = "LVM version 0.9  by Heinz Mauelshagen  (13/11/2000)\n";static char *lvm_short_version = "version 0.9 (13/11/2000)";#define MAJOR_NR	LVM_BLK_MAJOR#define	DEVICE_OFF(device)/* lvm_do_lv_create calls fsync_dev_lockfs()/unlockfs() *//* #define	LVM_VFS_ENHANCEMENT */#include <linux/config.h>#include <linux/version.h>#ifdef MODVERSIONS#undef MODULE#define MODULE#include <linux/modversions.h>#endif#include <linux/module.h>#include <linux/kernel.h>#include <linux/vmalloc.h>#include <linux/slab.h>#include <linux/init.h>#include <linux/hdreg.h>#include <linux/stat.h>#include <linux/fs.h>#include <linux/proc_fs.h>#include <linux/blkdev.h>#include <linux/genhd.h>#include <linux/locks.h>#include <linux/smp_lock.h>#include <asm/ioctl.h>#include <asm/segment.h>#include <asm/uaccess.h>#ifdef CONFIG_KERNELD#include <linux/kerneld.h>#endif#include <linux/blk.h>#include <linux/blkpg.h>#include <linux/errno.h>#include <linux/lvm.h>#define	LVM_CORRECT_READ_AHEAD( a) \   if      ( a < LVM_MIN_READ_AHEAD || \             a > LVM_MAX_READ_AHEAD) a = LVM_MAX_READ_AHEAD;#ifndef WRITEA#  define WRITEA WRITE#endif/* * External function prototypes */#ifdef MODULEint init_module(void);void cleanup_module(void);#elseextern int lvm_init(void);#endifstatic void lvm_dummy_device_request(request_queue_t *);#define	DEVICE_REQUEST	lvm_dummy_device_requeststatic int lvm_make_request_fn(request_queue_t*, int, struct buffer_head*);static int lvm_blk_ioctl(struct inode *, struct file *, uint, ulong);static int lvm_blk_open(struct inode *, struct file *);static int lvm_chr_open(struct inode *, struct file *);static int lvm_chr_close(struct inode *, struct file *);static int lvm_blk_close(struct inode *, struct file *);static int lvm_user_bmap(struct inode *, struct lv_bmap *);static int lvm_chr_ioctl(struct inode *, struct file *, uint, ulong);#if defined CONFIG_LVM_PROC_FS && defined CONFIG_PROC_FSint lvm_proc_read_vg_info(char *, char **, off_t, int, int *, void *);int lvm_proc_read_lv_info(char *, char **, off_t, int, int *, void *);int lvm_proc_read_pv_info(char *, char **, off_t, int, int *, void *);static int lvm_proc_get_global_info(char *, char **, off_t, int, int *, void *);void lvm_do_create_proc_entry_of_vg ( vg_t *);inline void lvm_do_remove_proc_entry_of_vg ( vg_t *);inline void lvm_do_create_proc_entry_of_lv ( vg_t *, lv_t *);inline void lvm_do_remove_proc_entry_of_lv ( vg_t *, lv_t *);inline void lvm_do_create_proc_entry_of_pv ( vg_t *, pv_t *);inline void lvm_do_remove_proc_entry_of_pv ( vg_t *, pv_t *);#endif#ifdef LVM_HD_NAMEvoid lvm_hd_name(char *, int);#endif/* End external function prototypes *//* * Internal function prototypes */static void lvm_init_vars(void);/* external snapshot calls */extern inline int lvm_get_blksize(kdev_t);extern int lvm_snapshot_alloc(lv_t *);extern void lvm_snapshot_fill_COW_page(vg_t *, lv_t *);extern int lvm_snapshot_COW(kdev_t, ulong, ulong, ulong, lv_t *);extern int lvm_snapshot_remap_block(kdev_t *, ulong *, ulong, lv_t *);extern void lvm_snapshot_release(lv_t *); extern int lvm_write_COW_table_block(vg_t *, lv_t *);extern inline void lvm_hash_link(lv_block_exception_t *, kdev_t, ulong, lv_t *);extern int lvm_snapshot_alloc_hash_table(lv_t *);extern void lvm_drop_snapshot(lv_t *, char *);#ifdef LVM_HD_NAMEextern void (*lvm_hd_name_ptr) (char *, int);#endifstatic int lvm_map(struct buffer_head *, int);static int lvm_do_lock_lvm(void);static int lvm_do_le_remap(vg_t *, void *);static int lvm_do_pv_create(pv_t *, vg_t *, ulong);static int lvm_do_pv_remove(vg_t *, ulong);static int lvm_do_lv_create(int, char *, lv_t *);static int lvm_do_lv_extend_reduce(int, char *, lv_t *);static int lvm_do_lv_remove(int, char *, int);static int lvm_do_lv_rename(vg_t *, lv_req_t *, lv_t *);static int lvm_do_lv_status_byname(vg_t *r, void *);static int lvm_do_lv_status_byindex(vg_t *, void *);static int lvm_do_lv_status_bydev(vg_t *, void *);static int lvm_do_pe_lock_unlock(vg_t *r, void *);static int lvm_do_pv_change(vg_t*, void*);static int lvm_do_pv_status(vg_t *, void *);static int lvm_do_vg_create(int, void *);static int lvm_do_vg_extend(vg_t *, void *);static int lvm_do_vg_reduce(vg_t *, void *);static int lvm_do_vg_rename(vg_t *, void *);static int lvm_do_vg_remove(int);static void lvm_geninit(struct gendisk *);#ifdef LVM_GET_INODEstatic struct inode *lvm_get_inode(int);void lvm_clear_inode(struct inode *);#endif/* END Internal function prototypes *//* volume group descriptor area pointers */static vg_t *vg[ABS_MAX_VG];#ifdef	CONFIG_DEVFS_FSstatic 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];#endifstatic pv_t *pvp = NULL;static lv_t *lvp = NULL;static pe_t *pep = NULL;static pe_t *pep1 = NULL;static char *basename = NULL;/* map from block minor number to VG and LV numbers */typedef struct {	int vg_number;	int lv_number;} vg_lv_map_t;static vg_lv_map_t vg_lv_map[ABS_MAX_LV];/* Request structures (lvm_chr_ioctl()) */static pv_change_req_t pv_change_req;static pv_flush_req_t pv_flush_req;static pv_status_req_t pv_status_req;static pe_lock_req_t pe_lock_req;static le_remap_req_t le_remap_req;static lv_req_t lv_req;#ifdef LVM_TOTAL_RESETstatic int lvm_reset_spindown = 0;#endifstatic char pv_name[NAME_LEN];/* static char rootvg[NAME_LEN] = { 0, }; */const char *const lvm_name = LVM_NAME;static int lock = 0;static int loadtime = 0;static uint vg_count = 0;static long lvm_chr_open_count = 0;static ushort lvm_iop_version = LVM_DRIVER_IOP_VERSION;static DECLARE_WAIT_QUEUE_HEAD(lvm_snapshot_wait);static DECLARE_WAIT_QUEUE_HEAD(lvm_wait);static DECLARE_WAIT_QUEUE_HEAD(lvm_map_wait);static spinlock_t lvm_lock = SPIN_LOCK_UNLOCKED;static spinlock_t lvm_snapshot_lock = SPIN_LOCK_UNLOCKED;#if defined CONFIG_LVM_PROC_FS && defined CONFIG_PROC_FSstatic struct proc_dir_entry *lvm_proc_dir = NULL;static struct proc_dir_entry *lvm_proc_vg_subdir = NULL;struct proc_dir_entry *pde = NULL;#endifstatic struct file_operations lvm_chr_fops ={	open:		lvm_chr_open,	release:	lvm_chr_close,	ioctl:		lvm_chr_ioctl,};#define BLOCK_DEVICE_OPERATIONS/* block device operations structure needed for 2.3.38? and above */static struct block_device_operations lvm_blk_dops ={	open: 		lvm_blk_open,	release:	lvm_blk_close,	ioctl:		lvm_blk_ioctl,};/* gendisk structures */static struct hd_struct lvm_hd_struct[MAX_LV];static int lvm_blocksizes[MAX_LV] ={0,};static int lvm_size[MAX_LV] ={0,};static struct gendisk lvm_gendisk ={	MAJOR_NR,		/* major # */	LVM_NAME,		/* name of major */	0,			/* number of times minor is shifted				   to get real minor */	1,			/* maximum partitions per device */	lvm_hd_struct,		/* partition table */	lvm_size,		/* device size in blocks, copied				   to block_size[] */	MAX_LV,			/* number or real devices */	NULL,			/* internal */	NULL,			/* pointer to next gendisk struct (internal) */};#ifdef MODULE/* * Module initialization... */int init_module(void)#else/* * Driver initialization... */#ifdef __initfunc__initfunc(int lvm_init(void))#elseint __init lvm_init(void)#endif#endif				/* #ifdef MODULE */{	struct gendisk *gendisk_ptr = NULL;	if (register_chrdev(LVM_CHAR_MAJOR, lvm_name, &lvm_chr_fops) < 0) {		printk(KERN_ERR "%s -- register_chrdev failed\n", lvm_name);		return -EIO;	}#ifdef BLOCK_DEVICE_OPERATIONS	if (register_blkdev(MAJOR_NR, lvm_name, &lvm_blk_dops) < 0)#else	if (register_blkdev(MAJOR_NR, lvm_name, &lvm_blk_fops) < 0)#endif	{		printk("%s -- register_blkdev failed\n", lvm_name);		if (unregister_chrdev(LVM_CHAR_MAJOR, lvm_name) < 0)			printk(KERN_ERR "%s -- unregister_chrdev failed\n", lvm_name);		return -EIO;	}#ifdef	CONFIG_DEVFS_FS	lvm_devfs_handle = devfs_register(		0 , "lvm", 0, 0, LVM_CHAR_MAJOR,		S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP,		&lvm_chr_fops, NULL);#endif#if defined CONFIG_LVM_PROC_FS && defined CONFIG_PROC_FS	lvm_proc_dir = create_proc_entry (LVM_DIR, S_IFDIR, &proc_root);	if (lvm_proc_dir != NULL) {		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 = &lvm_proc_get_global_info;	}#endif	lvm_init_vars();	lvm_geninit(&lvm_gendisk);	/* insert our gendisk at the corresponding major */	if (gendisk_head != NULL) {		gendisk_ptr = gendisk_head;		while (gendisk_ptr->next != NULL &&		       gendisk_ptr->major > lvm_gendisk.major) {			gendisk_ptr = gendisk_ptr->next;		}		lvm_gendisk.next = gendisk_ptr->next;		gendisk_ptr->next = &lvm_gendisk;	} else {		gendisk_head = &lvm_gendisk;		lvm_gendisk.next = NULL;	}#ifdef LVM_HD_NAME	/* reference from drivers/block/genhd.c */	lvm_hd_name_ptr = lvm_hd_name;#endif	blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), DEVICE_REQUEST);	blk_queue_make_request(BLK_DEFAULT_QUEUE(MAJOR_NR), lvm_make_request_fn);	/* optional read root VGDA *//*   if ( *rootvg != 0) vg_read_with_pv_and_lv ( rootvg, &vg);*/	printk(KERN_INFO	       "%s%s -- "#ifdef MODULE	       "Module"

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -