diff -urN 2.3.48pre2/drivers/block/Config.in 2.3.48pre2-lvm/drivers/block/Config.in --- 2.3.48pre2/drivers/block/Config.in Thu Feb 17 13:57:00 2000 +++ 2.3.48pre2-lvm/drivers/block/Config.in Sat Feb 26 04:22:17 2000 @@ -198,6 +198,10 @@ comment 'Additional Block Devices' +tristate 'Logical volume manager (LVM) support' CONFIG_BLK_DEV_LVM N +if [ "$CONFIG_BLK_DEV_LVM" != "n" ]; then + bool ' LVM information in proc filesystem' CONFIG_LVM_PROC_FS Y +fi tristate 'Loopback device support' CONFIG_BLK_DEV_LOOP if [ "$CONFIG_NET" = "y" ]; then tristate 'Network block device support' CONFIG_BLK_DEV_NBD diff -urN 2.3.48pre2/drivers/block/ll_rw_blk.c 2.3.48pre2-lvm/drivers/block/ll_rw_blk.c --- 2.3.48pre2/drivers/block/ll_rw_blk.c Sat Feb 26 02:58:02 2000 +++ 2.3.48pre2-lvm/drivers/block/ll_rw_blk.c Sat Feb 26 04:23:03 2000 @@ -952,15 +952,6 @@ bh->b_end_io(bh, test_bit(BH_Uptodate, &bh->b_state)); } -static inline void buffer_IO_error(struct buffer_head * bh) -{ - mark_buffer_clean(bh); - /* - * b_end_io has to clear the BH_Uptodate bitflag in the error case! - */ - bh->b_end_io(bh, 0); -} - int generic_make_request (request_queue_t *q, int rw, struct buffer_head * bh) { unsigned long flags; @@ -1240,6 +1231,9 @@ #ifdef CONFIG_SJCD sjcd_init(); #endif CONFIG_SJCD +#ifdef CONFIG_BLK_DEV_LVM + lvm_init(); +#endif #ifdef CONFIG_BLK_DEV_MD md_init(); #endif CONFIG_BLK_DEV_MD diff -urN 2.3.48pre2/drivers/block/lvm-snap.c 2.3.48pre2-lvm/drivers/block/lvm-snap.c --- 2.3.48pre2/drivers/block/lvm-snap.c Mon Feb 21 15:17:31 2000 +++ 2.3.48pre2-lvm/drivers/block/lvm-snap.c Sat Feb 26 04:27:53 2000 @@ -278,12 +278,12 @@ lvm_hash_link(lv_snap->lv_block_exception + idx, org_phys_dev, org_start, lv_snap); lv_snap->lv_remap_ptr = idx + 1; - return 0; + return 1; /* slow path */ out: lvm_drop_snapshot(lv_snap, reason); - return 1; + return -1; fail_out_of_space: reason = "out of space"; diff -urN 2.3.48pre2/drivers/block/lvm.c 2.3.48pre2-lvm/drivers/block/lvm.c --- 2.3.48pre2/drivers/block/lvm.c Sat Feb 26 02:58:02 2000 +++ 2.3.48pre2-lvm/drivers/block/lvm.c Sat Feb 26 04:27:58 2000 @@ -122,7 +122,7 @@ * - avoided "/dev/" in proc filesystem output * - avoided inline strings functions lvm_strlen etc. * 14/02/2000 - support for 2.3.43 - * - integrated Andrea Arcagnelli's snapshot code + * - integrated Andrea Arcangeli's snapshot code * */ @@ -171,9 +171,9 @@ #include #include -#define LVM_CORRECT_READ_AHEAD( a) \ - if ( a < LVM_MIN_READ_AHEAD || \ - a > LVM_MAX_READ_AHEAD) a = LVM_MAX_READ_AHEAD; +#define LVM_CORRECT_READ_AHEAD(a) \ + (((a) < LVM_MIN_READ_AHEAD || (a) > LVM_MAX_READ_AHEAD) \ + ? LVM_MAX_READ_AHEAD : (a)) #ifndef WRITEA # define WRITEA WRITE @@ -193,13 +193,11 @@ #define DEVICE_REQUEST lvm_dummy_device_request static int lvm_make_request_fn(request_queue_t *, int, struct buffer_head*); +static void lvm_plug_device_noop(request_queue_t *, kdev_t); static int lvm_blk_ioctl(struct inode *, struct file *, uint, ulong); static int lvm_blk_open(struct inode *, struct file *); -static ssize_t lvm_blk_read(struct file *, char *, size_t, loff_t *); -static ssize_t lvm_blk_write(struct file *, const char *, size_t, loff_t *); - static int lvm_chr_open(struct inode *, struct file *); static int lvm_chr_close(struct inode *, struct file *); @@ -287,7 +285,7 @@ static char pv_name[NAME_LEN]; /* static char rootvg[NAME_LEN] = { 0, }; */ static uint lv_open = 0; -static const char *const lvm_name = LVM_NAME; +const char *const lvm_name = LVM_NAME; static int lock = 0; static int loadtime = 0; static uint vg_count = 0; @@ -298,7 +296,6 @@ 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; static struct file_operations lvm_chr_fops = { @@ -307,18 +304,6 @@ ioctl: lvm_chr_ioctl, }; -static struct file_operations lvm_blk_fops = -{ - open: lvm_blk_open, - release: blkdev_close, - read: lvm_blk_read, - write: lvm_blk_write, - ioctl: lvm_blk_ioctl, - fsync: block_fsync, -}; - -#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, @@ -370,11 +355,7 @@ 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) @@ -410,6 +391,7 @@ blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), DEVICE_REQUEST); blk_queue_make_request(BLK_DEFAULT_QUEUE(MAJOR_NR), lvm_make_request_fn); + blk_queue_pluggable(BLK_DEFAULT_QUEUE(MAJOR_NR), lvm_plug_device_noop); /* optional read root VGDA */ /* if ( *rootvg != 0) vg_read_with_pv_and_lv ( rootvg, &vg); @@ -488,8 +470,6 @@ loadtime = CURRENT_TIME; - lvm_lock = lvm_snapshot_lock = SPIN_LOCK_UNLOCKED; - pe_lock_req.lock = UNLOCK_PE; pe_lock_req.data.lv_dev = \ pe_lock_req.data.pv_dev = \ @@ -724,8 +704,19 @@ sizeof(pv_flush_req)) != 0) return -EFAULT; - fsync_dev(pv_flush_req.pv_dev); - invalidate_buffers(pv_flush_req.pv_dev); + for ( v = 0; v < ABS_MAX_VG; v++) { + unsigned int p; + if ( vg[v] == NULL) continue; + for ( p = 0; p < vg[v]->pv_max; p++) { + if ( vg[v]->pv[p] != NULL && + strcmp ( vg[v]->pv[p]->pv_name, + pv_flush_req.pv_name) == 0) { + fsync_dev ( vg[v]->pv[p]->pv_dev); + invalidate_buffers ( vg[v]->pv[p]->pv_dev); + return 0; + } + } + } return 0; default: @@ -813,10 +804,6 @@ if (!(lv_ptr->lv_access & LV_WRITE)) return -EACCES; } -#ifdef 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++; lv_ptr->lv_open++; @@ -837,34 +824,6 @@ /* - * block device read - */ -static ssize_t lvm_blk_read(struct file *file, char *buffer, - size_t size, loff_t * offset) -{ - int minor = MINOR(file->f_dentry->d_inode->i_rdev); - - read_ahead[MAJOR(file->f_dentry->d_inode->i_rdev)] = - vg[VG_BLK(minor)]->lv[LV_BLK(minor)]->lv_read_ahead; - return block_read(file, buffer, size, offset); -} - - -/* - * block device write - */ -static ssize_t lvm_blk_write(struct file *file, const char *buffer, - size_t size, loff_t * offset) -{ - int minor = MINOR(file->f_dentry->d_inode->i_rdev); - - read_ahead[MAJOR(file->f_dentry->d_inode->i_rdev)] = - vg[VG_BLK(minor)]->lv[LV_BLK(minor)]->lv_read_ahead; - return block_write(file, buffer, size, offset); -} - - -/* * block device i/o-control routine */ static int lvm_blk_ioctl(struct inode *inode, struct file *file, @@ -906,6 +865,7 @@ "%s -- lvm_blk_ioctl -- BLKFLSBUF\n", lvm_name); #endif fsync_dev(inode->i_rdev); + invalidate_buffers(inode->i_rdev); break; @@ -921,7 +881,7 @@ if ((long) arg < LVM_MIN_READ_AHEAD || (long) arg > LVM_MAX_READ_AHEAD) return -EINVAL; - lv_ptr->lv_read_ahead = (long) arg; + read_ahead[MAJOR_NR] = lv_ptr->lv_read_ahead = (long) arg; break; @@ -1293,7 +1253,6 @@ static int lvm_map(struct buffer_head *bh, int rw) { int minor = MINOR(bh->b_rdev); - int ret = 0; ulong index; ulong pe_start; ulong size = bh->b_size >> 9; @@ -1308,7 +1267,7 @@ printk(KERN_ALERT "%s - lvm_map: ll_rw_blk for inactive LV %s\n", lvm_name, lv->lv_name); - return -1; + goto error; } /* if ( lv->lv_access & LV_SNAPSHOT) @@ -1323,7 +1282,7 @@ (rw == WRITEA || rw == WRITE)) { printk ( "%s -- doing snapshot write for %02d:%02d[%02d:%02d] b_blocknr: %lu b_rsector: %lu\n", lvm_name, MAJOR ( bh->b_dev), MINOR ( bh->b_dev), MAJOR ( bh->b_rdev), MINOR ( bh->b_rdev), bh->b_blocknr, bh->b_rsector); - return 0; + goto error; } if ((rw == WRITE || rw == WRITEA) && @@ -1331,7 +1290,7 @@ printk(KERN_CRIT "%s - lvm_map: ll_rw_blk write for readonly LV %s\n", lvm_name, lv->lv_name); - return -1; + goto error; } #ifdef DEBUG_MAP printk(KERN_DEBUG @@ -1347,7 +1306,7 @@ printk(KERN_ALERT "%s - lvm_map *rsector: %lu or size: %lu wrong for" " minor: %2d\n", lvm_name, rsector_tmp, size, minor); - return -1; + goto error; } rsector_sav = rsector_tmp; rdev_sav = rdev_tmp; @@ -1444,11 +1403,11 @@ pe_start, lv_ptr)) { /* create a new mapping */ - ret = lvm_snapshot_COW(rdev_tmp, - rsector_tmp, - pe_start, - rsector_sav, - lv_ptr); + lvm_snapshot_COW(rdev_tmp, + rsector_tmp, + pe_start, + rsector_sav, + lv_ptr); } rdev_tmp = rdev_sav; rsector_tmp = rsector_sav; @@ -1467,7 +1426,11 @@ bh->b_rdev = rdev_tmp; bh->b_rsector = rsector_tmp; - return ret; + return 1; + + error: + buffer_IO_error(bh); + return -1; } /* lvm_map() */ @@ -1519,6 +1482,12 @@ return 1; } +/* + * plug device function is a noop because plugging has to happen + * in the queue of the physical blockdevice to allow the + * elevator to do a better job. + */ +static void lvm_plug_device_noop(request_queue_t *q, kdev_t dev) { } /******************************************************************** * @@ -2090,7 +2059,7 @@ lvm_size[MINOR(lv_ptr->lv_dev)] = lv_ptr->lv_size >> 1; vg_lv_map[MINOR(lv_ptr->lv_dev)].vg_number = vg_ptr->vg_number; vg_lv_map[MINOR(lv_ptr->lv_dev)].lv_number = lv_ptr->lv_number; - LVM_CORRECT_READ_AHEAD(lv_ptr->lv_read_ahead); + read_ahead[MAJOR_NR] = lv_ptr->lv_read_ahead = LVM_CORRECT_READ_AHEAD(lv_ptr->lv_read_ahead); vg_ptr->lv_cur++; lv_ptr->lv_status = lv_status_save; @@ -2328,7 +2297,7 @@ lvm_size[MINOR(lv_ptr->lv_dev)] = lv_ptr->lv_size >> 1; /* vg_lv_map array doesn't have to be changed here */ - LVM_CORRECT_READ_AHEAD(lv_ptr->lv_read_ahead); + read_ahead[MAJOR_NR] = lv_ptr->lv_read_ahead = LVM_CORRECT_READ_AHEAD(lv_ptr->lv_read_ahead); lv_ptr->lv_status = lv_status_save; return 0; diff -urN 2.3.48pre2/drivers/block/md.c 2.3.48pre2-lvm/drivers/block/md.c --- 2.3.48pre2/drivers/block/md.c Sat Feb 26 02:58:02 2000 +++ 2.3.48pre2-lvm/drivers/block/md.c Sat Feb 26 04:32:07 2000 @@ -185,8 +185,7 @@ if (mddev && mddev->pers) return mddev->pers->make_request(q, mddev, rw, bh); else { - mark_buffer_clean(bh); - bh->b_end_io(bh, 0); + buffer_IO_error(bh); return -1; } } diff -urN 2.3.48pre2/include/linux/fs.h 2.3.48pre2-lvm/include/linux/fs.h --- 2.3.48pre2/include/linux/fs.h Sat Feb 26 02:58:05 2000 +++ 2.3.48pre2-lvm/include/linux/fs.h Sat Feb 26 04:31:42 2000 @@ -882,6 +882,21 @@ #define atomic_set_buffer_dirty(bh) test_and_set_bit(BH_Dirty, &(bh)->b_state) +/* + * If an error happens during the make_request, this function + * has to be recalled. It marks the buffer as clean and not + * uptodate, and it notifys the upper layer about the end + * of the I/O. + */ +static inline void buffer_IO_error(struct buffer_head * bh) +{ + mark_buffer_clean(bh); + /* + * b_end_io has to clear the BH_Uptodate bitflag in the error case! + */ + bh->b_end_io(bh, 0); +} + extern void balance_dirty(kdev_t); extern int check_disk_change(kdev_t); extern int invalidate_inodes(struct super_block *); diff -urN 2.3.48pre2/include/linux/lvm.h 2.3.48pre2-lvm/include/linux/lvm.h --- 2.3.48pre2/include/linux/lvm.h Mon Feb 21 15:17:35 2000 +++ 2.3.48pre2-lvm/include/linux/lvm.h Sat Feb 26 04:22:17 2000 @@ -65,7 +65,7 @@ #define LVM_TOTAL_RESET #define LVM_GET_INODE -#define LVM_HD_NAME +#undef LVM_HD_NAME /* lots of debugging output (see driver source) #define DEBUG_LVM_GET_INFO @@ -261,8 +261,8 @@ #define LVM_MAX_STRIPES 128 /* max # of stripes */ #define LVM_MAX_SIZE ( 1024LU * 1024 * 1024 * 2) /* 1TB[sectors] */ #define LVM_MAX_MIRRORS 2 /* future use */ -#define LVM_MIN_READ_AHEAD 2 /* minimum read ahead sectors */ -#define LVM_MAX_READ_AHEAD 120 /* maximum read ahead sectors */ +#define LVM_MIN_READ_AHEAD 0 /* minimum read ahead sectors */ +#define LVM_MAX_READ_AHEAD 256 /* maximum read ahead sectors */ #define LVM_MAX_LV_IO_TIMEOUT 60 /* seconds I/O timeout (future use) */ #define LVM_PARTITION 0xfe /* LVM partition id */ #define LVM_NEW_PARTITION 0x8e /* new LVM partition id (10/09/1999) */ @@ -590,6 +590,7 @@ struct lv_v2 *lv_snapshot_prev; struct lv_v2 *lv_snapshot_next; lv_block_exception_t *lv_block_exception; + uint8_t __unused; uint32_t lv_remap_ptr; uint32_t lv_remap_end; uint32_t lv_chunk_size; @@ -786,7 +787,6 @@ typedef struct { char pv_name[NAME_LEN]; - kdev_t pv_dev; } pv_flush_req_t;