diff options
author | Ralf Baechle <ralf@linux-mips.org> | 2001-01-31 22:22:27 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2001-01-31 22:22:27 +0000 |
commit | 825423e4c4f18289df2393951cfd2a7a31fc0464 (patch) | |
tree | 4ad80e981c3d9effa910d2247d118d254f9a5d09 /drivers/md | |
parent | c4693dc4856ab907a5c02187a8d398861bebfc7e (diff) |
Merge with Linux 2.4.1.
Diffstat (limited to 'drivers/md')
-rw-r--r-- | drivers/md/Config.in | 5 | ||||
-rw-r--r-- | drivers/md/lvm-snap.c | 32 | ||||
-rw-r--r-- | drivers/md/lvm-snap.h | 47 | ||||
-rw-r--r-- | drivers/md/lvm.c | 632 | ||||
-rw-r--r-- | drivers/md/md.c | 112 | ||||
-rw-r--r-- | drivers/md/raid5.c | 5 | ||||
-rw-r--r-- | drivers/md/xor.c | 3 |
7 files changed, 380 insertions, 456 deletions
diff --git a/drivers/md/Config.in b/drivers/md/Config.in index 565055a68..30438c77f 100644 --- a/drivers/md/Config.in +++ b/drivers/md/Config.in @@ -11,12 +11,7 @@ dep_tristate ' Linear (append) mode' CONFIG_MD_LINEAR $CONFIG_BLK_DEV_MD dep_tristate ' RAID-0 (striping) mode' CONFIG_MD_RAID0 $CONFIG_BLK_DEV_MD dep_tristate ' RAID-1 (mirroring) mode' CONFIG_MD_RAID1 $CONFIG_BLK_DEV_MD dep_tristate ' RAID-4/RAID-5 mode' CONFIG_MD_RAID5 $CONFIG_BLK_DEV_MD -if [ "$CONFIG_MD_LINEAR" = "y" -o "$CONFIG_MD_RAID0" = "y" -o "$CONFIG_MD_RAID1" = "y" -o "$CONFIG_MD_RAID5" = "y" ]; then - bool ' Boot support' CONFIG_MD_BOOT - bool ' Auto Detect support' CONFIG_AUTODETECT_RAID -fi dep_tristate ' Logical volume manager (LVM) support' CONFIG_BLK_DEV_LVM $CONFIG_MD -dep_mbool ' LVM information in proc filesystem' CONFIG_LVM_PROC_FS $CONFIG_BLK_DEV_LVM endmenu diff --git a/drivers/md/lvm-snap.c b/drivers/md/lvm-snap.c index 980694ee3..e28ffdbe9 100644 --- a/drivers/md/lvm-snap.c +++ b/drivers/md/lvm-snap.c @@ -21,6 +21,14 @@ * */ +/* + * Changelog + * + * 05/07/2000 - implemented persistent snapshot support + * 23/11/2000 - used cpu_to_le64 rather than my own macro + * + */ + #include <linux/kernel.h> #include <linux/vmalloc.h> #include <linux/blkdev.h> @@ -30,7 +38,9 @@ #include <linux/lvm.h> -static char *lvm_snap_version __attribute__ ((unused)) = "LVM 0.9 snapshot code (13/11/2000)\n"; +#include "lvm-snap.h" + +static char *lvm_snap_version __attribute__ ((unused)) = "LVM 0.9.1_beta2 snapshot code (18/01/2001)\n"; extern const char *const lvm_name; extern int lvm_blocksizes[]; @@ -214,10 +224,10 @@ void lvm_snapshot_fill_COW_page(vg_t * vg, lv_t * lv_snap) memset(lv_COW_table, 0, blksize_snap); for ( ; is < lv_snap->lv_remap_ptr; is++, id++) { /* store new COW_table entry */ - lv_COW_table[id].pv_org_number = LVM_TO_DISK64(lvm_pv_get_number(vg, lv_snap->lv_block_exception[is].rdev_org)); - lv_COW_table[id].pv_org_rsector = LVM_TO_DISK64(lv_snap->lv_block_exception[is].rsector_org); - lv_COW_table[id].pv_snap_number = LVM_TO_DISK64(lvm_pv_get_number(vg, lv_snap->lv_block_exception[is].rdev_new)); - lv_COW_table[id].pv_snap_rsector = LVM_TO_DISK64(lv_snap->lv_block_exception[is].rsector_new); + lv_COW_table[id].pv_org_number = cpu_to_le64(lvm_pv_get_number(vg, lv_snap->lv_block_exception[is].rdev_org)); + lv_COW_table[id].pv_org_rsector = cpu_to_le64(lv_snap->lv_block_exception[is].rsector_org); + lv_COW_table[id].pv_snap_number = cpu_to_le64(lvm_pv_get_number(vg, lv_snap->lv_block_exception[is].rdev_new)); + lv_COW_table[id].pv_snap_rsector = cpu_to_le64(lv_snap->lv_block_exception[is].rsector_new); } } @@ -227,8 +237,7 @@ void lvm_snapshot_fill_COW_page(vg_t * vg, lv_t * lv_snap) * */ -int lvm_write_COW_table_block(vg_t * vg, - lv_t * lv_snap) +int lvm_write_COW_table_block(vg_t * vg, lv_t * lv_snap) { int blksize_snap; int end_of_table; @@ -268,10 +277,10 @@ int lvm_write_COW_table_block(vg_t * vg, blocks[0] = (snap_pe_start + COW_table_sector_offset) >> (blksize_snap >> 10); /* store new COW_table entry */ - lv_COW_table[idx_COW_table].pv_org_number = LVM_TO_DISK64(lvm_pv_get_number(vg, lv_snap->lv_block_exception[idx].rdev_org)); - lv_COW_table[idx_COW_table].pv_org_rsector = LVM_TO_DISK64(lv_snap->lv_block_exception[idx].rsector_org); - lv_COW_table[idx_COW_table].pv_snap_number = LVM_TO_DISK64(lvm_pv_get_number(vg, snap_phys_dev)); - lv_COW_table[idx_COW_table].pv_snap_rsector = LVM_TO_DISK64(lv_snap->lv_block_exception[idx].rsector_new); + lv_COW_table[idx_COW_table].pv_org_number = cpu_to_le64(lvm_pv_get_number(vg, lv_snap->lv_block_exception[idx].rdev_org)); + lv_COW_table[idx_COW_table].pv_org_rsector = cpu_to_le64(lv_snap->lv_block_exception[idx].rsector_org); + lv_COW_table[idx_COW_table].pv_snap_number = cpu_to_le64(lvm_pv_get_number(vg, snap_phys_dev)); + lv_COW_table[idx_COW_table].pv_snap_rsector = cpu_to_le64(lv_snap->lv_block_exception[idx].rsector_new); length_tmp = iobuf->length; iobuf->length = blksize_snap; @@ -568,6 +577,7 @@ void lvm_snapshot_release(lv_t * lv) } if (lv->lv_iobuf) { + kiobuf_wait_for_io(lv->lv_iobuf); unmap_kiobuf(lv->lv_iobuf); free_kiovec(1, &lv->lv_iobuf); lv->lv_iobuf = NULL; diff --git a/drivers/md/lvm-snap.h b/drivers/md/lvm-snap.h new file mode 100644 index 000000000..23538a1b7 --- /dev/null +++ b/drivers/md/lvm-snap.h @@ -0,0 +1,47 @@ +/* + * kernel/lvm-snap.h + * + * Copyright (C) 2001 Sistina Software + * + * + * 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 + * + * 05/01/2001:Joe Thornber - Factored this file out of lvm.c + * + */ + +#ifndef LVM_SNAP_H +#define LVM_SNAP_H + +/* 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 *, const char *); + +#endif diff --git a/drivers/md/lvm.c b/drivers/md/lvm.c index ea276c57c..a4ca05e90 100644 --- a/drivers/md/lvm.c +++ b/drivers/md/lvm.c @@ -7,22 +7,23 @@ * April-May,July-August,November 1998 * January-March,May,July,September,October 1999 * January,February,July,September-November 2000 + * January 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. + * Boston, MA 02111-1307, USA. * */ @@ -138,13 +139,21 @@ * 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 + * 22/11/2000 - changed lvm_do_create_proc_entry_of_pv () to work + * with devfs + * 26/11/2000 - corrected #ifdef locations for PROC_FS + * 28/11/2000 - fixed lvm_do_vg_extend() NULL pointer BUG + * - fixed lvm_do_create_proc_entry_of_pv() buffer tampering BUG + * 08/01/2001 - Removed conditional compiles related to PROC_FS, + * procfs is always supported now. (JT) + * 12/01/2001 - avoided flushing logical volume in case of shrinking + * because of unecessary overhead in case of heavy updates * */ -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)"; +static char *lvm_version = "LVM version 0.9.1_beta2 by Heinz Mauelshagen (18/01/2001)\n"; +static char *lvm_short_version = "version 0.9.1_beta2 (18/01/2001)"; #define MAJOR_NR LVM_BLK_MAJOR #define DEVICE_OFF(device) @@ -190,6 +199,8 @@ static char *lvm_short_version = "version 0.9 (13/11/2000)"; #include <linux/errno.h> #include <linux/lvm.h> +#include "lvm-snap.h" + #define LVM_CORRECT_READ_AHEAD( a) \ if ( a < LVM_MIN_READ_AHEAD || \ a > LVM_MAX_READ_AHEAD) a = LVM_MAX_READ_AHEAD; @@ -198,19 +209,28 @@ static char *lvm_short_version = "version 0.9 (13/11/2000)"; # define WRITEA WRITE #endif -/* - * External function prototypes - */ -#ifdef MODULE -int init_module(void); -void cleanup_module(void); +/* debug macros */ +#ifdef DEBUG_IOCTL +#define P_IOCTL(fmt, args...) printk(KERN_DEBUG "lvm ioctl: " fmt, ## args) #else -extern int lvm_init(void); +#define P_IOCTL(fmt, args...) #endif -static void lvm_dummy_device_request(request_queue_t *); -#define DEVICE_REQUEST lvm_dummy_device_request +#ifdef DEBUG_MAP +#define P_MAP(fmt, args...) printk(KERN_DEBUG "lvm map: " fmt, ## args) +#else +#define P_MAP(fmt, args...) +#endif + +#ifdef DEBUG_KFREE +#define P_KFREE(fmt, args...) printk(KERN_DEBUG "lvm kfree: " fmt, ## args) +#else +#define P_KFREE(fmt, args...) +#endif +/* + * External function prototypes + */ static int lvm_make_request_fn(request_queue_t*, int, struct buffer_head*); static int lvm_blk_ioctl(struct inode *, struct file *, uint, ulong); @@ -224,42 +244,29 @@ 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_FS int 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_devfs_entry_of_vg ( vg_t *); + 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 +void lvm_do_remove_proc_entry_of_vg ( vg_t *); +void lvm_do_create_proc_entry_of_lv ( vg_t *, lv_t *); +void lvm_do_remove_proc_entry_of_lv ( vg_t *, lv_t *); +void lvm_do_create_proc_entry_of_pv ( vg_t *, pv_t *); +void lvm_do_remove_proc_entry_of_pv ( vg_t *, pv_t *); -#ifdef LVM_HD_NAME -void lvm_hd_name(char *, int); -#endif /* End external function prototypes */ /* * Internal function prototypes */ +static void lvm_cleanup(void); 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_NAME extern void (*lvm_hd_name_ptr) (char *, int); #endif @@ -288,9 +295,9 @@ 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_INODE -static struct inode *lvm_get_inode(int); -void lvm_clear_inode(struct inode *); +static char *lvm_show_uuid ( char *); +#ifdef LVM_HD_NAME +void lvm_hd_name(char *, int); #endif /* END Internal function prototypes */ @@ -298,12 +305,10 @@ void lvm_clear_inode(struct inode *); /* volume group descriptor area pointers */ static vg_t *vg[ABS_MAX_VG]; -#ifdef CONFIG_DEVFS_FS 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]; -#endif static pv_t *pvp = NULL; static lv_t *lvp = NULL; @@ -340,18 +345,15 @@ 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_FS static struct proc_dir_entry *lvm_proc_dir = NULL; static struct proc_dir_entry *lvm_proc_vg_subdir = NULL; struct proc_dir_entry *pde = NULL; -#endif static struct file_operations lvm_chr_fops = { @@ -360,7 +362,7 @@ static struct file_operations lvm_chr_fops = 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 = { @@ -391,22 +393,10 @@ static struct gendisk lvm_gendisk = 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)) -#else -int __init lvm_init(void) -#endif -#endif /* #ifdef MODULE */ +int lvm_init(void) { struct gendisk *gendisk_ptr = NULL; @@ -414,11 +404,7 @@ int __init lvm_init(void) 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) @@ -426,21 +412,17 @@ int __init lvm_init(void) 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); @@ -464,9 +446,9 @@ int __init lvm_init(void) 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); @@ -483,20 +465,17 @@ int __init lvm_init(void) lvm_version, lvm_name); return 0; -} /* init_module() / lvm_init() */ +} /* lvm_init() */ -#ifdef MODULE /* - * Module cleanup... + * cleanup... */ -void cleanup_module(void) +static void lvm_cleanup(void) { struct gendisk *gendisk_ptr = NULL, *gendisk_ptr_prev = NULL; -#ifdef CONFIG_DEVFS_FS devfs_unregister (lvm_devfs_handle); -#endif if (unregister_chrdev(LVM_CHAR_MAJOR, lvm_name) < 0) { printk(KERN_ERR "%s -- unregister_chrdev failed\n", lvm_name); @@ -504,7 +483,7 @@ void cleanup_module(void) if (unregister_blkdev(MAJOR_NR, lvm_name) < 0) { printk(KERN_ERR "%s -- unregister_blkdev failed\n", lvm_name); } - blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR)); + gendisk_ptr = gendisk_ptr_prev = gendisk_head; while (gendisk_ptr != NULL) { @@ -521,11 +500,9 @@ void cleanup_module(void) blksize_size[MAJOR_NR] = NULL; hardsect_size[MAJOR_NR] = NULL; -#if defined CONFIG_LVM_PROC_FS && defined CONFIG_PROC_FS remove_proc_entry(LVM_GLOBAL, lvm_proc_dir); remove_proc_entry(LVM_VG_SUBDIR, lvm_proc_dir); remove_proc_entry(LVM_DIR, &proc_root); -#endif #ifdef LVM_HD_NAME /* reference from linux/drivers/block/genhd.c */ @@ -535,18 +512,13 @@ void cleanup_module(void) printk(KERN_INFO "%s -- Module successfully deactivated\n", lvm_name); return; -} /* void cleanup_module() */ -#endif /* #ifdef MODULE */ +} /* lvm_cleanup() */ /* * support function to initialize lvm variables */ -#ifdef __initfunc -__initfunc(void lvm_init_vars(void)) -#else void __init lvm_init_vars(void) -#endif { int v; @@ -626,13 +598,9 @@ static int lvm_chr_ioctl(struct inode *inode, struct file *file, /* otherwise cc will complain about unused variables */ (void) lvm_lock; - -#ifdef DEBUG_IOCTL - printk(KERN_DEBUG - "%s -- lvm_chr_ioctl: command: 0x%X MINOR: %d " - "VG#: %d mode: 0x%X\n", - lvm_name, command, minor, VG_CHR(minor), file->f_mode); -#endif + P_IOCTL("%s -- lvm_chr_ioctl: command: 0x%X MINOR: %d " + "VG#: %d mode: 0x%X\n", + lvm_name, command, minor, VG_CHR(minor), file->f_mode); #ifdef LVM_TOTAL_RESET if (lvm_reset_spindown > 0) return -EACCES; @@ -890,14 +858,12 @@ static int lvm_blk_open(struct inode *inode, struct file *file) if (lv_ptr->lv_status & LV_SPINDOWN) return -EPERM; /* Check inactive LV and open for read/write */ - if (file->f_mode & O_RDWR) { - if (!(lv_ptr->lv_status & LV_ACTIVE)) return -EPERM; - if (!(lv_ptr->lv_access & LV_WRITE)) return -EACCES; - } + if (!(lv_ptr->lv_status & LV_ACTIVE)) + return -EPERM; + if (!(lv_ptr->lv_access & LV_WRITE) && + (file->f_mode & FMODE_WRITE)) + return -EACCES; -#ifndef BLOCK_DEVICE_OPERATIONS - file->f_op = &lvm_blk_fops; -#endif /* be sure to increment VG counter */ if (lv_ptr->lv_open == 0) vg_ptr->lv_open++; @@ -930,24 +896,18 @@ static int lvm_blk_ioctl(struct inode *inode, struct file *file, void *arg = (void *) a; struct hd_geometry *hd = (struct hd_geometry *) a; -#ifdef DEBUG_IOCTL - printk(KERN_DEBUG - "%s -- lvm_blk_ioctl MINOR: %d command: 0x%X arg: %X " - "VG#: %dl LV#: %d\n", - lvm_name, minor, command, (ulong) arg, - VG_BLK(minor), LV_BLK(minor)); -#endif + P_IOCTL("%s -- lvm_blk_ioctl MINOR: %d command: 0x%X arg: %X " + "VG#: %dl LV#: %d\n", + lvm_name, minor, command, (ulong) arg, + VG_BLK(minor), LV_BLK(minor)); switch (command) { case BLKGETSIZE: /* return device size */ -#ifdef DEBUG_IOCTL - printk(KERN_DEBUG - "%s -- lvm_blk_ioctl -- BLKGETSIZE: %u\n", - lvm_name, lv_ptr->lv_size); -#endif + P_IOCTL("%s -- lvm_blk_ioctl -- BLKGETSIZE: %u\n", + lvm_name, lv_ptr->lv_size); if (put_user(lv_ptr->lv_size, (long *)arg)) - return -EFAULT; + return -EFAULT; break; @@ -955,10 +915,8 @@ static int lvm_blk_ioctl(struct inode *inode, struct file *file, /* flush buffer cache */ if (!capable(CAP_SYS_ADMIN)) return -EACCES; -#ifdef DEBUG_IOCTL - printk(KERN_DEBUG - "%s -- lvm_blk_ioctl -- BLKFLSBUF\n", lvm_name); -#endif + P_IOCTL("%s -- lvm_blk_ioctl -- BLKFLSBUF\n", lvm_name); + fsync_dev(inode->i_rdev); invalidate_buffers(inode->i_rdev); break; @@ -968,11 +926,9 @@ static int lvm_blk_ioctl(struct inode *inode, struct file *file, /* set read ahead for block device */ if (!capable(CAP_SYS_ADMIN)) return -EACCES; -#ifdef DEBUG_IOCTL - printk(KERN_DEBUG - "%s -- lvm_blk_ioctl -- BLKRASET: %d sectors for %02X:%02X\n", - lvm_name, (long) arg, MAJOR(inode->i_rdev), minor); -#endif + P_IOCTL("%s -- lvm_blk_ioctl -- BLKRASET: %d sectors for %02X:%02X\n", + lvm_name, (long) arg, MAJOR(inode->i_rdev), minor); + if ((long) arg < LVM_MIN_READ_AHEAD || (long) arg > LVM_MAX_READ_AHEAD) return -EINVAL; @@ -982,10 +938,7 @@ static int lvm_blk_ioctl(struct inode *inode, struct file *file, case BLKRAGET: /* get current read ahead setting */ -#ifdef DEBUG_IOCTL - printk(KERN_DEBUG - "%s -- lvm_blk_ioctl -- BLKRAGET\n", lvm_name); -#endif + P_IOCTL("%s -- lvm_blk_ioctl -- BLKRAGET\n", lvm_name); if (put_user(lv_ptr->lv_read_ahead, (long *)arg)) return -EFAULT; break; @@ -993,10 +946,7 @@ static int lvm_blk_ioctl(struct inode *inode, struct file *file, case HDIO_GETGEO: /* get disk geometry */ -#ifdef DEBUG_IOCTL - printk(KERN_DEBUG - "%s -- lvm_blk_ioctl -- HDIO_GETGEO\n", lvm_name); -#endif + P_IOCTL("%s -- lvm_blk_ioctl -- HDIO_GETGEO\n", lvm_name); if (hd == NULL) return -EINVAL; { @@ -1016,11 +966,8 @@ static int lvm_blk_ioctl(struct inode *inode, struct file *file, return -EFAULT; } -#ifdef DEBUG_IOCTL - printk(KERN_DEBUG - "%s -- lvm_blk_ioctl -- cylinders: %d\n", - lvm_name, lv_ptr->lv_size / heads / sectors); -#endif + P_IOCTL("%s -- lvm_blk_ioctl -- cylinders: %d\n", + lvm_name, lv_ptr->lv_size / heads / sectors); break; @@ -1127,22 +1074,22 @@ static int lvm_user_bmap(struct inode *inode, struct lv_bmap *user_result) struct buffer_head bh; unsigned long block; int err; - + if (get_user(block, &user_result->lv_block)) - return -EFAULT; - + return -EFAULT; + memset(&bh,0,sizeof bh); bh.b_rsector = block; bh.b_dev = bh.b_rdev = inode->i_dev; bh.b_size = lvm_get_blksize(bh.b_dev); if ((err=lvm_map(&bh, READ)) < 0) { - printk("lvm map failed: %d\n", err); - return -EINVAL; + printk("lvm map failed: %d\n", err); + return -EINVAL; } - - return put_user( kdev_t_to_nr(bh.b_rdev), &user_result->lv_dev) || + + return put_user(kdev_t_to_nr(bh.b_rdev), &user_result->lv_dev) || put_user(bh.b_rsector, &user_result->lv_block) ? -EFAULT : 0; -} +} /* @@ -1168,7 +1115,7 @@ int lvm_vg_info(vg_t *vg_ptr, char *buf) { 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_total - vg_ptr->pe_allocated) * vg_ptr->pe_size >> 1, vg_ptr->pe_total - vg_ptr->pe_allocated); return sz; @@ -1263,7 +1210,6 @@ int lvm_pv_info(pv_t *pv_ptr, char *buf) { } -#if defined CONFIG_LVM_PROC_FS && defined CONFIG_PROC_FS /* * Support functions /proc-Filesystem */ @@ -1325,10 +1271,7 @@ static int lvm_proc_get_global_info(char *page, char **start, off_t pos, int cou lv_block_exception_t_bytes *= sizeof(lv_block_exception_t); if (buf != NULL) { -#ifdef DEBUG_KFREE - printk(KERN_DEBUG - "%s -- vfree %d\n", lvm_name, __LINE__); -#endif + P_KFREE("%s -- vfree %d\n", lvm_name, __LINE__); lock_kernel(); vfree(buf); unlock_kernel(); @@ -1452,7 +1395,6 @@ static int lvm_proc_get_global_info(char *page, char **start, off_t pos, int cou else return count; } /* lvm_proc_get_global_info() */ -#endif /* #if defined CONFIG_LVM_PROC_FS && defined CONFIG_PROC_FS */ /* @@ -1478,7 +1420,7 @@ int lvm_proc_read_vg_info(char *page, char **start, off_t off, sz += sprintf ( page+sz, "PE size: %u\n", vg->pe_size / 2); sz += sprintf ( page+sz, "PE total: %u\n", vg->pe_total); sz += sprintf ( page+sz, "PE allocated: %u\n", vg->pe_allocated); - sz += sprintf ( page+sz, "uuid: %s\n", vg->vg_uuid); + sz += sprintf ( page+sz, "uuid: %s\n", lvm_show_uuid(vg->vg_uuid)); return sz; } @@ -1525,7 +1467,7 @@ int lvm_proc_read_pv_info(char *page, char **start, off_t off, 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)); - sz += sprintf ( page+sz, "uuid: %s\n", pv->pv_uuid); + sz += sprintf ( page+sz, "uuid: %s\n", lvm_show_uuid(pv->pv_uuid)); return sz; @@ -1565,15 +1507,13 @@ static int lvm_map(struct buffer_head *bh, int rw) lvm_name, lv->lv_name); return -1; } -#ifdef DEBUG_MAP - printk(KERN_DEBUG - "%s - lvm_map minor:%d *rdev: %02d:%02d *rsector: %lu " - "size:%lu\n", - lvm_name, minor, - MAJOR(rdev_tmp), - MINOR(rdev_tmp), - rsector_tmp, size); -#endif + + P_MAP("%s - lvm_map minor:%d *rdev: %02d:%02d *rsector: %lu " + "size:%lu\n", + lvm_name, minor, + MAJOR(rdev_tmp), + MINOR(rdev_tmp), + rsector_tmp, size); if (rsector_tmp + size > lv->lv_size) { printk(KERN_ALERT @@ -1595,15 +1535,13 @@ lvm_second_remap: (rsector_tmp % vg_this->pe_size); rdev_tmp = lv->lv_current_pe[index].dev; -#ifdef DEBUG_MAP - printk(KERN_DEBUG - "lv_current_pe[%ld].pe: %ld rdev: %02d:%02d rsector:%ld\n", + P_MAP("lv_current_pe[%ld].pe: %ld rdev: %02d:%02d " + "rsector:%ld\n", index, lv->lv_current_pe[index].pe, MAJOR(rdev_tmp), MINOR(rdev_tmp), rsector_tmp); -#endif /* striped mapping */ } else { @@ -1624,9 +1562,7 @@ lvm_second_remap: rdev_tmp = lv->lv_current_pe[index].dev; } -#ifdef DEBUG_MAP - printk(KERN_DEBUG - "lv_current_pe[%ld].pe: %ld rdev: %02d:%02d rsector:%ld\n" + P_MAP("lv_current_pe[%ld].pe: %ld rdev: %02d:%02d rsector:%ld\n" "stripe_length: %ld stripe_index: %ld\n", index, lv->lv_current_pe[index].pe, @@ -1635,7 +1571,6 @@ lvm_second_remap: rsector_tmp, stripe_length, stripe_index); -#endif /* handle physical extents on the move */ if (pe_lock_req.lock == LOCK_PE) { @@ -1659,6 +1594,8 @@ lvm_second_remap: if (lv->lv_access & (LV_SNAPSHOT|LV_SNAPSHOT_ORG)) { /* original logical volume */ if (lv->lv_access & LV_SNAPSHOT_ORG) { + /* Serializes the access to the lv_snapshot_next list */ + down(&lv->lv_snapshot_sem); if (rw == WRITE || rw == WRITEA) { lv_t *lv_ptr; @@ -1669,7 +1606,8 @@ lvm_second_remap: lv_ptr = lv_ptr->lv_snapshot_next) { /* Check for inactive snapshot */ if (!(lv_ptr->lv_status & LV_ACTIVE)) continue; - down(&lv->lv_snapshot_org->lv_snapshot_sem); + /* Serializes the COW with the accesses to the snapshot device */ + down(&lv_ptr->lv_snapshot_sem); /* do we still have exception storage for this snapshot free? */ if (lv_ptr->lv_block_exception != NULL) { rdev_sav = rdev_tmp; @@ -1690,9 +1628,10 @@ lvm_second_remap: rdev_tmp = rdev_sav; rsector_tmp = rsector_sav; } - up(&lv->lv_snapshot_org->lv_snapshot_sem); + up(&lv_ptr->lv_snapshot_sem); } } + up(&lv->lv_snapshot_sem); } else { /* remap snapshot logical volume */ down(&lv->lv_snapshot_sem); @@ -1733,31 +1672,12 @@ void lvm_hd_name(char *buf, int minor) /* - * this one never should be called... - */ -static void lvm_dummy_device_request(request_queue_t * t) -{ - printk(KERN_EMERG - "%s -- oops, got lvm request for %02d:%02d [sector: %lu]\n", - lvm_name, - MAJOR(CURRENT->rq_dev), - MINOR(CURRENT->rq_dev), - CURRENT->sector); - return; -} - - -/* * make request function */ static int lvm_make_request_fn(request_queue_t *q, int rw, - struct buffer_head *bh) -{ - if (lvm_map(bh, rw)<0) - return 0; /* failure, buffer_IO_error has been called, don't recurse */ - else - return 1; /* all ok, mapping done, call lower level driver */ + struct buffer_head *bh) { + return (lvm_map(bh, rw) < 0) ? 0 : 1; } @@ -1774,10 +1694,8 @@ static int lvm_do_lock_lvm(void) lock_try_again: spin_lock(&lvm_lock); if (lock != 0 && lock != current->pid) { -#ifdef DEBUG_IOCTL - printk(KERN_INFO "lvm_do_lock_lvm: %s is locked by pid %d ...\n", - lvm_name, lock); -#endif + P_IOCTL("lvm_do_lock_lvm: %s is locked by pid %d ...\n", + lvm_name, lock); spin_unlock(&lvm_lock); interruptible_sleep_on(&lvm_wait); if (current->sigpending != 0) @@ -1966,6 +1884,8 @@ int lvm_do_vg_create(int minor, void *arg) } } + lvm_do_create_devfs_entry_of_vg ( vg_ptr); + /* Second path to correct snapshot logical volumes which are not in place during first path above */ for (l = 0; l < ls; l++) { @@ -1980,18 +1900,7 @@ int lvm_do_vg_create(int minor, void *arg) } } -#ifdef CONFIG_DEVFS_FS - 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); -#endif - -#if defined CONFIG_LVM_PROC_FS && defined CONFIG_PROC_FS lvm_do_create_proc_entry_of_vg ( vg_ptr); -#endif vfree(snap_lv_ptr); @@ -2021,25 +1930,15 @@ static int lvm_do_vg_extend(vg_t *vg_ptr, void *arg) for (p = 0; p < vg_ptr->pv_max; p++) { if ( ( pv_ptr = vg_ptr->pv[p]) == NULL) { ret = lvm_do_pv_create(arg, vg_ptr, p); - lvm_do_create_proc_entry_of_pv ( vg_ptr, pv_ptr); if ( ret != 0) return ret; - - /* We don't need the PE list - in kernel space like LVs pe_t list */ - pv_ptr->pe = NULL; - vg_ptr->pv_cur++; - vg_ptr->pv_act++; - vg_ptr->pe_total += - pv_ptr->pe_total; -#ifdef LVM_GET_INODE - /* insert a dummy inode for fs_may_mount */ - pv_ptr->inode = lvm_get_inode(pv_ptr->pv_dev); -#endif + pv_ptr = vg_ptr->pv[p]; + vg_ptr->pe_total += pv_ptr->pe_total; + lvm_do_create_proc_entry_of_pv(vg_ptr, pv_ptr); return 0; } } } -return -EPERM; + return -EPERM; } /* lvm_do_vg_extend() */ @@ -2060,10 +1959,6 @@ static int lvm_do_vg_reduce(vg_t *vg_ptr, void *arg) { strcmp(pv_ptr->pv_name, pv_name) == 0) { if (pv_ptr->lv_cur > 0) return -EPERM; - vg_ptr->pe_total -= - pv_ptr->pe_total; - vg_ptr->pv_cur--; - vg_ptr->pv_act--; lvm_do_pv_remove(vg_ptr, p); /* Make PV pointer array contiguous */ for (; p < vg_ptr->pv_max - 1; p++) @@ -2091,9 +1986,7 @@ static int lvm_do_vg_rename(vg_t *vg_ptr, void *arg) if (copy_from_user(vg_name, arg, sizeof(vg_name)) != 0) return -EFAULT; -#if defined CONFIG_LVM_PROC_FS && defined CONFIG_PROC_FS lvm_do_remove_proc_entry_of_vg ( vg_ptr); -#endif strncpy ( vg_ptr->vg_name, vg_name, sizeof ( vg_name)-1); for ( l = 0; l < vg_ptr->lv_max; l++) @@ -2115,9 +2008,7 @@ static int lvm_do_vg_rename(vg_t *vg_ptr, void *arg) strncpy(pv_ptr->vg_name, vg_name, NAME_LEN); } -#if defined CONFIG_LVM_PROC_FS && defined CONFIG_PROC_FS lvm_do_create_proc_entry_of_vg ( vg_ptr); -#endif return 0; } /* lvm_do_vg_rename */ @@ -2166,27 +2057,17 @@ static int lvm_do_vg_remove(int minor) /* free PVs */ for (i = 0; i < vg_ptr->pv_max; i++) { if ((pv_ptr = vg_ptr->pv[i]) != NULL) { -#ifdef DEBUG_KFREE - printk(KERN_DEBUG - "%s -- kfree %d\n", lvm_name, __LINE__); -#endif + P_KFREE("%s -- kfree %d\n", lvm_name, __LINE__); lvm_do_pv_remove(vg_ptr, i); } } -#ifdef CONFIG_DEVFS_FS devfs_unregister (ch_devfs_handle[vg_ptr->vg_number]); devfs_unregister (vg_devfs_handle[vg_ptr->vg_number]); -#endif -#if defined CONFIG_LVM_PROC_FS && defined CONFIG_PROC_FS lvm_do_remove_proc_entry_of_vg ( vg_ptr); -#endif - -#ifdef DEBUG_KFREE - printk(KERN_DEBUG "%s -- kfree %d\n", lvm_name, __LINE__); -#endif + P_KFREE("%s -- kfree %d\n", lvm_name, __LINE__); kfree(vg_ptr); vg[VG_CHR(minor)] = NULL; @@ -2222,11 +2103,6 @@ static int lvm_do_pv_create(pv_t *pvp, vg_t *vg_ptr, ulong p) { vg_ptr->pv_act++; vg_ptr->pv_cur++; -#ifdef LVM_GET_INODE - /* insert a dummy inode for fs_may_mount */ - pv_ptr->inode = lvm_get_inode(pv_ptr->pv_dev); -#endif - return 0; } /* lvm_do_pv_create() */ @@ -2237,11 +2113,8 @@ static int lvm_do_pv_create(pv_t *pvp, vg_t *vg_ptr, ulong p) { static int lvm_do_pv_remove(vg_t *vg_ptr, ulong p) { pv_t *pv_ptr = vg_ptr->pv[p]; -#if defined CONFIG_LVM_PROC_FS && defined CONFIG_PROC_FS lvm_do_remove_proc_entry_of_pv ( vg_ptr, pv_ptr); -#endif - vg_ptr->pe_total -= - pv_ptr->pe_total; + vg_ptr->pe_total -= pv_ptr->pe_total; vg_ptr->pv_cur--; vg_ptr->pv_act--; #ifdef LVM_GET_INODE @@ -2320,11 +2193,9 @@ static int lvm_do_lv_create(int minor, char *lv_name, lv_t *lv) "%s -- LV_CREATE: vmalloc error LV_CURRENT_PE of %d Byte " "at line %d\n", lvm_name, size, __LINE__); -#ifdef DEBUG_KFREE - printk(KERN_DEBUG "%s -- kfree %d\n", lvm_name, __LINE__); -#endif + P_KFREE("%s -- kfree %d\n", lvm_name, __LINE__); kfree(lv_ptr); - vg[VG_CHR(minor)]->lv[l] = NULL; + vg_ptr->lv[l] = NULL; return -ENOMEM; } if (copy_from_user(lv_ptr->lv_current_pe, pep, size)) { @@ -2354,9 +2225,8 @@ static int lvm_do_lv_create(int minor, char *lv_name, lv_t *lv) "%s -- lvm_do_lv_create: vmalloc error LV_BLOCK_EXCEPTION " "of %d byte at line %d\n", lvm_name, size, __LINE__); -#ifdef DEBUG_KFREE - printk(KERN_DEBUG "%s -- kfree %d\n", lvm_name, __LINE__); -#endif + P_KFREE("%s -- kfree %d\n", lvm_name, + __LINE__); kfree(lv_ptr); vg_ptr->lv[l] = NULL; return -ENOMEM; @@ -2364,7 +2234,7 @@ static int lvm_do_lv_create(int minor, char *lv_name, lv_t *lv) if (copy_from_user(lv_ptr->lv_block_exception, lvbe, size)) { vfree(lv_ptr->lv_block_exception); kfree(lv_ptr); - vg[VG_CHR(minor)]->lv[l] = NULL; + vg_ptr->lv[l] = NULL; return -EFAULT; } /* point to the original logical volume */ @@ -2372,33 +2242,32 @@ static int lvm_do_lv_create(int minor, char *lv_name, lv_t *lv) lv_ptr->lv_snapshot_minor = 0; lv_ptr->lv_snapshot_org = lv_ptr; - lv_ptr->lv_snapshot_prev = NULL; - /* walk thrugh the snapshot list */ - while (lv_ptr->lv_snapshot_next != NULL) - lv_ptr = lv_ptr->lv_snapshot_next; - /* now lv_ptr points to the last existing snapshot in the chain */ - vg_ptr->lv[l]->lv_snapshot_prev = lv_ptr; /* our new one now back points to the previous last in the chain which can be the original logical volume */ lv_ptr = vg_ptr->lv[l]; /* now lv_ptr points to our new last snapshot logical volume */ - lv_ptr->lv_snapshot_org = lv_ptr->lv_snapshot_prev->lv_snapshot_org; - lv_ptr->lv_snapshot_next = NULL; lv_ptr->lv_current_pe = lv_ptr->lv_snapshot_org->lv_current_pe; + lv_ptr->lv_allocated_snapshot_le = lv_ptr->lv_allocated_le; lv_ptr->lv_allocated_le = lv_ptr->lv_snapshot_org->lv_allocated_le; lv_ptr->lv_current_le = lv_ptr->lv_snapshot_org->lv_current_le; lv_ptr->lv_size = lv_ptr->lv_snapshot_org->lv_size; lv_ptr->lv_stripes = lv_ptr->lv_snapshot_org->lv_stripes; lv_ptr->lv_stripesize = lv_ptr->lv_snapshot_org->lv_stripesize; + + /* Update the VG PE(s) used by snapshot reserve space. */ + vg_ptr->pe_allocated += lv_ptr->lv_allocated_snapshot_le; + if ((ret = lvm_snapshot_alloc(lv_ptr)) != 0) { vfree(lv_ptr->lv_block_exception); kfree(lv_ptr); - vg[VG_CHR(minor)]->lv[l] = NULL; + vg_ptr->lv[l] = NULL; return ret; } for ( e = 0; e < lv_ptr->lv_remap_ptr; e++) - lvm_hash_link (lv_ptr->lv_block_exception + e, lv_ptr->lv_block_exception[e].rdev_org, lv_ptr->lv_block_exception[e].rsector_org, lv_ptr); + lvm_hash_link (lv_ptr->lv_block_exception + e, + lv_ptr->lv_block_exception[e].rdev_org, + lv_ptr->lv_block_exception[e].rsector_org, lv_ptr); /* need to fill the COW exception table data into the page for disk i/o */ lvm_snapshot_fill_COW_page(vg_ptr, lv_ptr); @@ -2426,9 +2295,8 @@ static int lvm_do_lv_create(int minor, char *lv_name, lv_t *lv) vg_ptr->lv_cur++; lv_ptr->lv_status = lv_status_save; -#ifdef CONFIG_DEVFS_FS { - char *lv_tmp, *lv_buf = NULL; + char *lv_tmp, *lv_buf = lv->lv_name; strtok(lv->lv_name, "/"); /* /dev */ while((lv_tmp = strtok(NULL, "/")) != NULL) @@ -2440,24 +2308,29 @@ static int lvm_do_lv_create(int minor, char *lv_name, lv_t *lv) S_IFBLK | S_IRUSR | S_IWUSR | S_IRGRP, &lvm_blk_dops, NULL); } -#endif -#if defined CONFIG_LVM_PROC_FS && defined CONFIG_PROC_FS lvm_do_create_proc_entry_of_lv ( vg_ptr, lv_ptr); -#endif /* optionally add our new snapshot LV */ if (lv_ptr->lv_access & LV_SNAPSHOT) { + lv_t *org = lv_ptr->lv_snapshot_org, *last; + /* sync the original logical volume */ - fsync_dev(lv_ptr->lv_snapshot_org->lv_dev); + fsync_dev(org->lv_dev); #ifdef LVM_VFS_ENHANCEMENT /* VFS function call to sync and lock the filesystem */ - fsync_dev_lockfs(lv_ptr->lv_snapshot_org->lv_dev); + fsync_dev_lockfs(org->lv_dev); #endif - lv_ptr->lv_snapshot_org->lv_access |= LV_SNAPSHOT_ORG; - lv_ptr->lv_access &= ~LV_SNAPSHOT_ORG; - /* put ourselve into the chain */ - lv_ptr->lv_snapshot_prev->lv_snapshot_next = lv_ptr; + + down(&org->lv_snapshot_sem); + org->lv_access |= LV_SNAPSHOT_ORG; + lv_ptr->lv_access &= ~LV_SNAPSHOT_ORG; /* this can only hide an userspace bug */ + + /* Link in the list of snapshot volumes */ + for (last = org; last->lv_snapshot_next; last = last->lv_snapshot_next); + lv_ptr->lv_snapshot_prev = last; + last->lv_snapshot_next = lv_ptr; + up(&org->lv_snapshot_sem); } /* activate the logical volume */ @@ -2513,6 +2386,31 @@ static int lvm_do_lv_remove(int minor, char *lv_name, int l) lv_ptr->lv_snapshot_next != NULL) return -EPERM; + if (lv_ptr->lv_access & LV_SNAPSHOT) { + /* + * Atomically make the the snapshot invisible + * to the original lv before playing with it. + */ + lv_t * org = lv_ptr->lv_snapshot_org; + down(&org->lv_snapshot_sem); + + /* remove this snapshot logical volume from the chain */ + lv_ptr->lv_snapshot_prev->lv_snapshot_next = lv_ptr->lv_snapshot_next; + if (lv_ptr->lv_snapshot_next != NULL) { + lv_ptr->lv_snapshot_next->lv_snapshot_prev = + lv_ptr->lv_snapshot_prev; + } + up(&org->lv_snapshot_sem); + + /* no more snapshots? */ + if (!org->lv_snapshot_next) + org->lv_access &= ~LV_SNAPSHOT_ORG; + lvm_snapshot_release(lv_ptr); + + /* Update the VG PE(s) used by snapshot reserve space. */ + vg_ptr->pe_allocated -= lv_ptr->lv_allocated_snapshot_le; + } + lv_ptr->lv_status |= LV_SPINDOWN; /* sync the buffers */ @@ -2532,7 +2430,8 @@ static int lvm_do_lv_remove(int minor, char *lv_name, int l) vg_lv_map[MINOR(lv_ptr->lv_dev)].vg_number = ABS_MAX_VG; vg_lv_map[MINOR(lv_ptr->lv_dev)].lv_number = -1; - /* correct the PE count in PVs if this is no snapshot logical volume */ + /* correct the PE count in PVs if this is not a snapshot + logical volume */ if (!(lv_ptr->lv_access & LV_SNAPSHOT)) { /* only if this is no snapshot logical volume because we share the lv_current_pe[] structs with the @@ -2546,31 +2445,13 @@ static int lvm_do_lv_remove(int minor, char *lv_name, int l) } } vfree(lv_ptr->lv_current_pe); - /* LV_SNAPSHOT */ - } else { - /* remove this snapshot logical volume from the chain */ - lv_ptr->lv_snapshot_prev->lv_snapshot_next = lv_ptr->lv_snapshot_next; - if (lv_ptr->lv_snapshot_next != NULL) { - lv_ptr->lv_snapshot_next->lv_snapshot_prev = - lv_ptr->lv_snapshot_prev; - } - /* no more snapshots? */ - if (lv_ptr->lv_snapshot_org->lv_snapshot_next == NULL) - lv_ptr->lv_snapshot_org->lv_access &= ~LV_SNAPSHOT_ORG; - lvm_snapshot_release(lv_ptr); } -#ifdef CONFIG_DEVFS_FS devfs_unregister(lv_devfs_handle[lv_ptr->lv_number]); -#endif -#if defined CONFIG_LVM_PROC_FS && defined CONFIG_PROC_FS lvm_do_remove_proc_entry_of_lv ( vg_ptr, lv_ptr); -#endif -#ifdef DEBUG_KFREE - printk(KERN_DEBUG "%s -- kfree %d\n", lvm_name, __LINE__); -#endif + P_KFREE("%s -- kfree %d\n", lvm_name, __LINE__); kfree(lv_ptr); vg_ptr->lv[l] = NULL; vg_ptr->lv_cur--; @@ -2638,21 +2519,24 @@ static int lvm_do_lv_extend_reduce(int minor, char *lv_name, lv_t *lv) } memcpy(lvbe, lv_ptr->lv_block_exception, - (lv->lv_remap_end > lv_ptr->lv_remap_end ? lv_ptr->lv_remap_ptr : lv->lv_remap_end) * sizeof(lv_block_exception_t)); + (lv->lv_remap_end > lv_ptr->lv_remap_end ? + lv_ptr->lv_remap_ptr : lv->lv_remap_end) * sizeof(lv_block_exception_t)); lv_ptr->lv_block_exception = lvbe; lv_ptr->lv_remap_end = lv->lv_remap_end; if (lvm_snapshot_alloc_hash_table(lv_ptr) != 0) { - lvm_drop_snapshot(lv_ptr, "hash_alloc"); + lvm_drop_snapshot(lv_ptr, "no memory for hash table"); up(&lv_ptr->lv_snapshot_org->lv_snapshot_sem); vfree(lvbe_old); vfree(lvs_hash_table_old); - return 1; + return -ENOMEM; } for (e = 0; e < lv_ptr->lv_remap_ptr; e++) - lvm_hash_link (lv_ptr->lv_block_exception + e, lv_ptr->lv_block_exception[e].rdev_org, lv_ptr->lv_block_exception[e].rsector_org, lv_ptr); + lvm_hash_link (lv_ptr->lv_block_exception + e, + lv_ptr->lv_block_exception[e].rdev_org, + lv_ptr->lv_block_exception[e].rsector_org, lv_ptr); up(&lv_ptr->lv_snapshot_org->lv_snapshot_sem); @@ -2677,15 +2561,6 @@ static int lvm_do_lv_extend_reduce(int minor, char *lv_name, lv_t *lv) return -EFAULT; } -#ifdef DEBUG - printk(KERN_DEBUG - "%s -- fsync_dev and " - "invalidate_buffers for %s [%s] in %s\n", - lvm_name, lv_ptr->lv_name, - kdevname(lv_ptr->lv_dev), - vg_ptr->vg_name); -#endif - /* reduce allocation counters on PV(s) */ for (le = 0; le < lv_ptr->lv_allocated_le; le++) { vg_ptr->pe_allocated--; @@ -2714,9 +2589,6 @@ static int lvm_do_lv_extend_reduce(int minor, char *lv_name, lv_t *lv) /* save # of old allocated logical extents */ old_allocated_le = lv_ptr->lv_allocated_le; - /* in case of shrinking -> let's flush */ - if ( end > lv->lv_current_le) fsync_dev(lv_ptr->lv_dev); - /* copy preloaded LV */ memcpy((char *) lv_ptr, (char *) lv, sizeof(lv_t)); @@ -2914,15 +2786,11 @@ static int lvm_do_lv_rename(vg_t *vg_ptr, lv_req_t *lv_req, lv_t *lv) if ( (lv_ptr = vg_ptr->lv[l]) == NULL) continue; if (lv_ptr->lv_dev == lv->lv_dev) { -#if defined CONFIG_LVM_PROC_FS && defined CONFIG_PROC_FS lvm_do_remove_proc_entry_of_lv ( vg_ptr, lv_ptr); -#endif strncpy(lv_ptr->lv_name, lv_req->lv_name, NAME_LEN); -#if defined CONFIG_LVM_PROC_FS && defined CONFIG_PROC_FS lvm_do_create_proc_entry_of_lv ( vg_ptr, lv_ptr); -#endif break; } } @@ -3004,9 +2872,22 @@ static int lvm_do_pv_status(vg_t *vg_ptr, void *arg) /* + * create a devfs entry for a volume group + */ +void lvm_do_create_devfs_entry_of_vg ( vg_t *vg_ptr) { + 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); +} + + +/* * create a /proc entry for a logical volume */ -inline void lvm_do_create_proc_entry_of_lv ( vg_t *vg_ptr, lv_t *lv_ptr) { +void lvm_do_create_proc_entry_of_lv ( vg_t *vg_ptr, lv_t *lv_ptr) { char *basename; if ( vg_ptr->lv_subdir_pde != NULL) { @@ -3026,7 +2907,7 @@ inline void lvm_do_create_proc_entry_of_lv ( vg_t *vg_ptr, lv_t *lv_ptr) { /* * remove a /proc entry for a logical volume */ -inline void lvm_do_remove_proc_entry_of_lv ( vg_t *vg_ptr, lv_t *lv_ptr) { +void lvm_do_remove_proc_entry_of_lv ( vg_t *vg_ptr, lv_t *lv_ptr) { char *basename; if ( vg_ptr->lv_subdir_pde != NULL) { @@ -3041,13 +2922,17 @@ inline void lvm_do_remove_proc_entry_of_lv ( vg_t *vg_ptr, lv_t *lv_ptr) { /* * create a /proc entry for a physical volume */ -inline void lvm_do_create_proc_entry_of_pv ( vg_t *vg_ptr, pv_t *pv_ptr) { +void lvm_do_create_proc_entry_of_pv ( vg_t *vg_ptr, pv_t *pv_ptr) { + int offset = 0; char *basename; - - basename = strrchr(pv_ptr->pv_name, '/'); - if (basename == NULL) basename = pv_ptr->pv_name; - else basename++; - pde = create_proc_entry(basename, S_IFREG, vg_ptr->pv_subdir_pde); + char buffer[NAME_LEN]; + + basename = pv_ptr->pv_name; + if (strncmp(basename, "/dev/", 5) == 0) offset = 5; + strncpy(buffer, basename + offset, sizeof(buffer)); + basename = buffer; + while ( ( basename = strchr ( basename, '/')) != NULL) *basename = '_'; + pde = create_proc_entry(buffer, S_IFREG, vg_ptr->pv_subdir_pde); if ( pde != NULL) { pde->read_proc = lvm_proc_read_pv_info; pde->data = pv_ptr; @@ -3058,7 +2943,7 @@ inline void lvm_do_create_proc_entry_of_pv ( vg_t *vg_ptr, pv_t *pv_ptr) { /* * remove a /proc entry for a physical volume */ -inline void lvm_do_remove_proc_entry_of_pv ( vg_t *vg_ptr, pv_t *pv_ptr) { +void lvm_do_remove_proc_entry_of_pv ( vg_t *vg_ptr, pv_t *pv_ptr) { char *basename; basename = strrchr(pv_ptr->pv_name, '/'); @@ -3074,7 +2959,6 @@ inline void lvm_do_remove_proc_entry_of_pv ( vg_t *vg_ptr, pv_t *pv_ptr) { /* * create a /proc entry for a volume group */ -#if defined CONFIG_LVM_PROC_FS && defined CONFIG_PROC_FS void lvm_do_create_proc_entry_of_vg ( vg_t *vg_ptr) { int l, p; pv_t *pv_ptr; @@ -3090,24 +2974,25 @@ void lvm_do_create_proc_entry_of_vg ( vg_t *vg_ptr) { pde->read_proc = lvm_proc_read_vg_info; 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); - } - - if ( vg_ptr->pv_subdir_pde != NULL) { - for ( l = 0; l < vg_ptr->lv_max; l++) { - if ( ( lv_ptr = vg_ptr->lv[l]) == NULL) continue; - lvm_do_create_proc_entry_of_lv ( vg_ptr, lv_ptr); - } - for ( p = 0; p < vg_ptr->pv_max; p++) { - if ( ( pv_ptr = vg_ptr->pv[p]) == NULL) continue; - lvm_do_create_proc_entry_of_pv ( vg_ptr, pv_ptr); - } - } + pde = create_proc_entry(LVM_LV_SUBDIR, S_IFDIR, + vg_ptr->vg_dir_pde); + if ( pde != NULL) { + vg_ptr->lv_subdir_pde = pde; + for ( l = 0; l < vg_ptr->lv_max; l++) { + if ( ( lv_ptr = vg_ptr->lv[l]) == NULL) continue; + lvm_do_create_proc_entry_of_lv ( vg_ptr, lv_ptr); + } + } + pde = create_proc_entry(LVM_PV_SUBDIR, S_IFDIR, + vg_ptr->vg_dir_pde); + if ( pde != NULL) { + vg_ptr->pv_subdir_pde = pde; + for ( p = 0; p < vg_ptr->pv_max; p++) { + if ( ( pv_ptr = vg_ptr->pv[p]) == NULL) continue; + lvm_do_create_proc_entry_of_pv ( vg_ptr, pv_ptr); + } + } + } } /* @@ -3133,18 +3018,12 @@ void lvm_do_remove_proc_entry_of_vg ( vg_t *vg_ptr) { remove_proc_entry(vg_ptr->vg_name, lvm_proc_vg_subdir); } } -#endif /* * support function initialize gendisk variables */ -#ifdef __initfunc -__initfunc(void lvm_geninit(struct gendisk *lvm_gdisk)) -#else -void __init - lvm_geninit(struct gendisk *lvm_gdisk) -#endif +void __init lvm_geninit(struct gendisk *lvm_gdisk) { int i = 0; @@ -3166,39 +3045,30 @@ void __init } /* lvm_gen_init() */ -#ifdef LVM_GET_INODE /* - * support function to get an empty inode - * - * Gets an empty inode to be inserted into the inode hash, - * so that a physical volume can't be mounted. - * This is analog to drivers/block/md.c - * - * Is this the real thing? - * + * return a pointer to a '-' padded uuid */ -struct inode *lvm_get_inode(int dev) -{ - struct inode *inode_this = NULL; +static char *lvm_show_uuid ( char *uuidstr) { + int i, j; + static char uuid[NAME_LEN] = { 0, }; - /* Lock the device by inserting a dummy inode. */ - inode_this = get_empty_inode(); - inode_this->i_dev = dev; - insert_inode_hash(inode_this); - return inode_this; -} + memset ( uuid, 0, NAME_LEN); + i = 6; + memcpy ( uuid, uuidstr, i); + uuidstr += i; -/* - * support function to clear an inode - * - */ -void lvm_clear_inode(struct inode *inode) -{ -#ifdef I_FREEING - inode->i_state |= I_FREEING; -#endif - clear_inode(inode); - return; + for ( j = 0; j < 6; j++) { + uuid[i++] = '-'; + memcpy ( &uuid[i], uuidstr, 4); + uuidstr += 4; + i += 4; + } + + memcpy ( &uuid[i], uuidstr, 2 ); + + return uuid; } -#endif /* #ifdef LVM_GET_INODE */ + +module_init(lvm_init); +module_exit(lvm_cleanup); diff --git a/drivers/md/md.c b/drivers/md/md.c index 8542bc2b0..5d4bab6c9 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -2033,68 +2033,65 @@ abort: struct { int set; int noautodetect; +} raid_setup_args md__initdata; -} raid_setup_args md__initdata = { 0, 0 }; - -void md_setup_drive(void) md__init; +void md_setup_drive (void) md__init; /* * Searches all registered partitions for autorun RAID arrays * at boot time. */ -#ifdef CONFIG_AUTODETECT_RAID -static int detected_devices[128] md__initdata = { 0, }; -static int dev_cnt=0; +static int detected_devices[128] md__initdata; +static int dev_cnt; + void md_autodetect_dev(kdev_t dev) { if (dev_cnt >= 0 && dev_cnt < 127) detected_devices[dev_cnt++] = dev; } -#endif -int md__init md_run_setup(void) + +static void autostart_arrays (void) { -#ifdef CONFIG_AUTODETECT_RAID mdk_rdev_t *rdev; int i; - if (raid_setup_args.noautodetect) - printk(KERN_INFO "skipping autodetection of RAID arrays\n"); - else { - - printk(KERN_INFO "autodetecting RAID arrays\n"); + printk(KERN_INFO "autodetecting RAID arrays\n"); - for (i=0; i<dev_cnt; i++) { - kdev_t dev = detected_devices[i]; + for (i=0; i<dev_cnt; i++) { + kdev_t dev = detected_devices[i]; - if (md_import_device(dev,1)) { - printk(KERN_ALERT "could not import %s!\n", - partition_name(dev)); - continue; - } - /* - * Sanity checks: - */ - rdev = find_rdev_all(dev); - if (!rdev) { - MD_BUG(); - continue; - } - if (rdev->faulty) { - MD_BUG(); - continue; - } - md_list_add(&rdev->pending, &pending_raid_disks); + if (md_import_device(dev,1)) { + printk(KERN_ALERT "could not import %s!\n", + partition_name(dev)); + continue; } - - autorun_devices(-1); + /* + * Sanity checks: + */ + rdev = find_rdev_all(dev); + if (!rdev) { + MD_BUG(); + continue; + } + if (rdev->faulty) { + MD_BUG(); + continue; + } + md_list_add(&rdev->pending, &pending_raid_disks); } + autorun_devices(-1); +} + +int md__init md_run_setup(void) +{ + if (raid_setup_args.noautodetect) + printk(KERN_INFO "skipping autodetection of RAID arrays\n"); + else + autostart_arrays(); dev_cnt = -1; /* make sure further calls to md_autodetect_dev are ignored */ -#endif -#ifdef CONFIG_MD_BOOT md_setup_drive(); -#endif return 0; } @@ -2558,6 +2555,11 @@ static int md_ioctl (struct inode *inode, struct file *file, md_print_devices(); goto done_unlock; + case RAID_AUTORUN: + err = 0; + autostart_arrays(); + goto done; + case BLKGETSIZE: /* Return device size */ if (!arg) { err = -EINVAL; @@ -3639,14 +3641,12 @@ int md__init md_init (void) return (0); } -#ifdef CONFIG_MD_BOOT -#define MAX_MD_BOOT_DEVS 8 -struct { - unsigned long set; - int pers[MAX_MD_BOOT_DEVS]; - int chunk[MAX_MD_BOOT_DEVS]; - kdev_t devices[MAX_MD_BOOT_DEVS][MD_SB_DISKS]; -} md_setup_args md__initdata = { 0, }; +static struct { + char device_set [MAX_MD_DEVS]; + int pers[MAX_MD_DEVS]; + int chunk[MAX_MD_DEVS]; + kdev_t devices[MAX_MD_DEVS][MD_SB_DISKS]; +} md_setup_args md__initdata; /* * Parse the command-line parameters given our kernel, but do not @@ -3676,10 +3676,10 @@ static int md__init md_setup(char *str) printk("md: Too few arguments supplied to md=.\n"); return 0; } - if (minor >= MAX_MD_BOOT_DEVS) { + if (minor >= MAX_MD_DEVS) { printk ("md: Minor device number too high.\n"); return 0; - } else if (md_setup_args.set & (1 << minor)) { + } else if (md_setup_args.device_set[minor]) { printk ("md: Warning - md=%d,... has been specified twice;\n" " will discard the first definition.\n", minor); } @@ -3737,7 +3737,7 @@ static int md__init md_setup(char *str) printk ("md: Will configure md%d (%s) from %s, below.\n", minor, pername, devnames); md_setup_args.devices[minor][i] = (kdev_t) 0; - md_setup_args.set |= (1 << minor); + md_setup_args.device_set[minor] = 1; return 1; } @@ -3747,10 +3747,11 @@ void md__init md_setup_drive(void) kdev_t dev; mddev_t*mddev; - for (minor = 0; minor < MAX_MD_BOOT_DEVS; minor++) { + for (minor = 0; minor < MAX_MD_DEVS; minor++) { mdu_disk_info_t dinfo; - int err=0; - if (!(md_setup_args.set & (1 << minor))) + + int err = 0; + if (!md_setup_args.device_set[minor]) continue; printk("md: Loading md%d.\n", minor); if (mddev_map[minor].mddev) { @@ -3776,7 +3777,7 @@ void md__init md_setup_drive(void) ainfo.layout = 0; ainfo.chunk_size = md_setup_args.chunk[minor]; err = set_array_info(mddev, &ainfo); - for (i=0; !err && (dev = md_setup_args.devices[minor][i]); i++) { + for (i = 0; !err && (dev = md_setup_args.devices[minor][i]); i++) { dinfo.number = i; dinfo.raid_disk = i; dinfo.state = (1<<MD_DISK_ACTIVE)|(1<<MD_DISK_SYNC); @@ -3807,7 +3808,6 @@ void md__init md_setup_drive(void) } __setup("md=", md_setup); -#endif #ifdef MODULE int init_module (void) @@ -3859,9 +3859,7 @@ void cleanup_module (void) #endif __initcall(md_init); -#if defined(CONFIG_AUTODETECT_RAID) || defined(CONFIG_MD_BOOT) __initcall(md_run_setup); -#endif MD_EXPORT_SYMBOL(md_size); MD_EXPORT_SYMBOL(register_md_personality); diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index 7981fe764..3ad3940a9 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -714,6 +714,11 @@ static void compute_parity(struct stripe_head *sh, int method) break; } spin_unlock_irq(&conf->device_lock); + if (count>1) { + xor_block(count, bh_ptr); + count = 1; + } + for (i = disks; i--;) if (chosen[i]) { struct buffer_head *bh = sh->bh_cache[i]; diff --git a/drivers/md/xor.c b/drivers/md/xor.c index b9b1cefe9..f0b76d466 100644 --- a/drivers/md/xor.c +++ b/drivers/md/xor.c @@ -57,8 +57,7 @@ xor_block(unsigned int count, struct buffer_head **bh_ptr) /* Set of all registered templates. */ static struct xor_block_template *template_list; -/* The -6*32 shift factor colors the cache. */ -#define BENCH_SIZE (PAGE_SIZE-6*32) +#define BENCH_SIZE (PAGE_SIZE) static void do_xor_speed(struct xor_block_template *tmpl, void *b1, void *b2) |