1 --- linux/include/linux/lvm.h.orig Sun Nov 11 18:09:32 2001
2 +++ linux/include/linux/lvm.h Thu Jan 10 12:24:08 2002
7 - * Copyright (C) 1997 - 2000 Heinz Mauelshagen, Sistina Software
8 + * Copyright (C) 1997 - 2001 Heinz Mauelshagen, Sistina Software
10 * February-November 1997
12 * January-March,July,September,October,Dezember 1999
13 * January,February,July,November 2000
15 + * January-March,June,July 2001
17 * lvm is free software; you can redistribute it and/or modify
18 * it under the terms of the GNU General Public License as published by
19 * the Free Software Foundation; either version 2, or (at your option)
23 * lvm is distributed in the hope that it will be useful,
24 * but WITHOUT ANY WARRANTY; without even the implied warranty of
25 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26 * GNU General Public License for more details.
29 * You should have received a copy of the GNU General Public License
30 * along with GNU CC; see the file COPYING. If not, write to
31 * the Free Software Foundation, 59 Temple Place - Suite 330,
32 - * Boston, MA 02111-1307, USA.
33 + * Boston, MA 02111-1307, USA.
38 * 08/12/1999 - changed LVM_LV_SIZE_MAX macro to reflect current 1TB limit
39 * 01/01/2000 - extended lv_v2 core structure by wait_queue member
40 * 12/02/2000 - integrated Andrea Arcagnelli's snapshot work
41 - * 14/02/2001 - changed LVM_SNAPSHOT_MIN_CHUNK to 1 page
42 - * 18/02/2000 - seperated user and kernel space parts by
43 + * 18/02/2000 - seperated user and kernel space parts by
44 * #ifdef them with __KERNEL__
45 * 08/03/2000 - implemented cluster/shared bits for vg_access
46 * 26/06/2000 - implemented snapshot persistency and resizing support
48 * 12/11/2000 - removed unneeded timestamp definitions
49 * 24/12/2000 - removed LVM_TO_{CORE,DISK}*, use cpu_{from, to}_le*
50 * instead - Christoph Hellwig
51 - * 01/03/2001 - Rename VG_CREATE to VG_CREATE_OLD and add new VG_CREATE
52 + * 22/01/2001 - Change ulong to uint32_t
53 + * 14/02/2001 - changed LVM_SNAPSHOT_MIN_CHUNK to 1 page
54 + * 20/02/2001 - incremented IOP version to 11 because of incompatible
55 + * change in VG activation (in order to support devfs better)
56 + * 01/03/2001 - Revert to IOP10 and add VG_CREATE_OLD call for compatibility
57 * 08/03/2001 - new lv_t (in core) version number 5: changed page member
58 * to (struct kiobuf *) to use for COW exception table io
59 - * 23/03/2001 - Change a (presumably) mistyped pv_t* to an lv_t*
60 - * 26/03/2001 - changed lv_v4 to lv_v5 in structure definition [HM]
61 + * 26/03/2001 - changed lv_v4 to lv_v5 in structure definition (HM)
62 + * 21/06/2001 - changed BLOCK_SIZE back to 1024 for non S/390
63 + * 22/06/2001 - added Andreas Dilger's PE on 4k boundary alignment enhancements
64 + * 19/07/2001 - added rwsem compatibility macros for 2.2 kernels
65 + * 13/11/2001 - reduced userspace inclusion of kernel headers to a minimum
70 #ifndef _LVM_H_INCLUDE
71 #define _LVM_H_INCLUDE
73 -#define LVM_RELEASE_NAME "1.0.1-rc4(ish)"
74 -#define LVM_RELEASE_DATE "03/10/2001"
75 +#define LVM_RELEASE_NAME "1.0.1"
76 +#define LVM_RELEASE_DATE "26/11/2001"
78 -#define _LVM_KERNEL_H_VERSION "LVM "LVM_RELEASE_NAME" ("LVM_RELEASE_DATE")"
79 +#define _LVM_KERNEL_H_VERSION "LVM "LVM_RELEASE_NAME" ("LVM_RELEASE_DATE")"
81 #include <linux/version.h>
86 #define DEBUG_VG_CREATE
87 - #define DEBUG_LVM_BLK_OPEN
88 + #define DEBUG_DEVICE
91 -#endif /* #ifdef __KERNEL__ */
93 #include <linux/kdev_t.h>
94 #include <linux/list.h>
96 #include <asm/types.h>
97 #include <linux/major.h>
99 +/* This prevents the need to include <linux/list.h> which
100 + causes problems on some platforms. It's not nice but then
101 + neither is the alternative. */
103 + struct list_head *next, *prev;
106 +#include <linux/kdev_t.h>
108 +#endif /* #ifndef __KERNEL__ */
112 #include <linux/spinlock.h>
114 #include <asm/semaphore.h>
115 #endif /* #ifdef __KERNEL__ */
118 #include <asm/page.h>
120 #if !defined ( LVM_BLK_MAJOR) || !defined ( LVM_CHAR_MAJOR)
125 -#ifdef CONFIG_ARCH_S390
126 +#ifdef CONFIG_ARCH_S390
127 #define BLOCK_SIZE 4096
129 #define BLOCK_SIZE 1024
134 + * VGDA: default disk spaces and offsets
136 + * there's space after the structures for later extensions.
139 + * --------------- ---------------------------------- ------------
140 + * 0 physical volume structure ~500 byte
142 + * 1K volume group structure ~200 byte
144 + * 6K namelist of physical volumes 128 byte each
146 + * 6k + n * ~300byte n logical volume structures ~300 byte each
148 + * + m * 4byte m physical extent alloc. structs 4 byte each
150 + * End of disk - first physical extent typically 4 megabyte
157 +/* DONT TOUCH THESE !!! */
166 * LVM_PE_T_MAX corresponds to:
168 * 8KB PE size can map a ~512 MB logical volume at the cost of 1MB memory,
170 #define LVM_MAX_STRIPES 128 /* max # of stripes */
171 #define LVM_MAX_SIZE ( 1024LU * 1024 / SECTOR_SIZE * 1024 * 1024) /* 1TB[sectors] */
172 #define LVM_MAX_MIRRORS 2 /* future use */
173 -#define LVM_MIN_READ_AHEAD 2 /* minimum read ahead sectors */
174 -#define LVM_MAX_READ_AHEAD 120 /* maximum read ahead sectors */
175 +#define LVM_MIN_READ_AHEAD 0 /* minimum read ahead sectors */
176 +#define LVM_DEFAULT_READ_AHEAD 1024 /* sectors for 512k scsi segments */
177 +#define LVM_MAX_READ_AHEAD 10000 /* maximum read ahead sectors */
178 #define LVM_MAX_LV_IO_TIMEOUT 60 /* seconds I/O timeout (future use) */
179 #define LVM_PARTITION 0xfe /* LVM partition id */
180 #define LVM_NEW_PARTITION 0x8e /* new LVM partition id (10/09/1999) */
184 /* lock the logical volume manager */
185 +#if LVM_DRIVER_IOP_VERSION > 11
186 +#define LVM_LOCK_LVM _IO ( 0xfe, 0x9A)
188 +/* This is actually the same as _IO ( 0xff, 0x00), oops. Remove for IOP 12+ */
189 #define LVM_LOCK_LVM _IO ( 0xfe, 0x100)
197 /* delta to version 1 starts here */
198 - struct lv_v5 *lv_snapshot_org;
199 - struct lv_v5 *lv_snapshot_prev;
200 - struct lv_v5 *lv_snapshot_next;
201 + struct lv_v5 *lv_snapshot_org;
202 + struct lv_v5 *lv_snapshot_prev;
203 + struct lv_v5 *lv_snapshot_next;
204 lv_block_exception_t *lv_block_exception;
208 } lv_snapshot_use_rate_req_t;
213 static inline ulong round_up(ulong n, ulong size) {
216 return round_up(n, size) / size;
219 +/* FIXME: nasty capital letters */
220 static int inline LVM_GET_COW_TABLE_CHUNKS_PER_PE(vg_t *vg, lv_t *lv) {
221 return vg->pe_size / lv->lv_chunk_size;
228 #endif /* #ifndef _LVM_H_INCLUDE */
230 --- linux/drivers/md/lvm.c.orig Mon Nov 19 17:56:04 2001
231 +++ linux/drivers/md/lvm.c Thu Jan 10 12:24:08 2002
236 - * Copyright (C) 1997 - 2000 Heinz Mauelshagen, Sistina Software
237 + * Copyright (C) 1997 - 2001 Heinz Mauelshagen, Sistina Software
239 * February-November 1997
240 * April-May,July-August,November 1998
241 * January-March,May,July,September,October 1999
242 * January,February,July,September-November 2000
244 + * January-April 2001
247 * LVM driver is free software; you can redistribute it and/or modify
249 * support for free (eg. longer) logical volume names
250 * 12/05/1998 - added spin_locks (thanks to Pascal van Dam
251 * <pascal@ramoth.xs4all.nl>)
252 - * 25/05/1998 - fixed handling of locked PEs in lvm_map() and lvm_chr_ioctl()
253 + * 25/05/1998 - fixed handling of locked PEs in lvm_map() and
255 * 26/05/1998 - reactivated verify_area by access_ok
256 * 07/06/1998 - used vmalloc/vfree instead of kmalloc/kfree to go
257 * beyond 128/256 KB max allocation limit per call
259 * 14/02/2000 - support for 2.3.43
260 * - integrated Andrea Arcagneli's snapshot code
261 * 25/06/2000 - james (chip) , IKKHAYD! roffl
262 - * 26/06/2000 - enhanced lv_extend_reduce for snapshot logical volume support
263 + * 26/06/2000 - enhanced lv_extend_reduce for snapshot logical volume
265 * 06/09/2000 - added devfs support
266 * 07/09/2000 - changed IOP version to 9
267 * - started to add new char ioctl LV_STATUS_BYDEV_T to support
268 @@ -147,15 +149,24 @@
269 * 08/01/2001 - Removed conditional compiles related to PROC_FS,
270 * procfs is always supported now. (JT)
271 * 12/01/2001 - avoided flushing logical volume in case of shrinking
272 - * because of unnecessary overhead in case of heavy updates
273 + * because of unecessary overhead in case of heavy updates
274 * 25/01/2001 - Allow RO open of an inactive LV so it can be reactivated.
275 - * 31/01/2001 - If you try and BMAP a snapshot you now get an -EPERM
276 - * 01/02/2001 - factored __remap_snapshot out of lvm_map
277 + * 31/01/2001 - removed blk_init_queue/blk_cleanup_queue queueing will be
278 + * handled by the proper devices.
279 + * - If you try and BMAP a snapshot you now get an -EPERM
280 + * 01/01/2001 - lvm_map() now calls buffer_IO_error on error for 2.4
281 + * - factored __remap_snapshot out of lvm_map
282 * 12/02/2001 - move devfs code to create VG before LVs
283 - * 14/02/2001 - tidied device defines for blk.h
284 + * 13/02/2001 - allow VG_CREATE on /dev/lvm
285 + * 14/02/2001 - removed modversions.h
286 + * - tidied device defines for blk.h
287 * - tidied debug statements
288 + * - bug: vg[] member not set back to NULL if activation fails
289 * - more lvm_map tidying
290 - * 14/02/2001 - bug: vg[] member not set back to NULL if activation fails
291 + * 15/02/2001 - register /dev/lvm with devfs correctly (major/minor
293 + * 19/02/2001 - preallocated buffer_heads for rawio when using
295 * 28/02/2001 - introduced the P_DEV macro and changed some internel
296 * functions to be static [AD]
297 * 28/02/2001 - factored lvm_get_snapshot_use_rate out of blk_ioctl [AD]
298 @@ -163,25 +174,50 @@
299 * where the check for an existing LV takes place right at
301 * 01/03/2001 - Add VG_CREATE_OLD for IOP 10 compatibility
302 - * 02/03/2001 - Don't destroy usermode pointers in lv_t structures duing LV_
303 - * STATUS_BYxxx and remove redundant lv_t variables from same.
304 + * 02/03/2001 - Don't destroy usermode pointers in lv_t structures duing
306 + * and remove redundant lv_t variables from same.
307 + * - avoid compilation of lvm_dummy_device_request in case of
308 + * Linux >= 2.3.0 to avoid a warning
309 + * - added lvm_name argument to printk in buffer allocation
310 + * in order to avoid a warning
311 + * 04/03/2001 - moved linux/version.h above first use of KERNEL_VERSION
313 * 05/03/2001 - restore copying pe_t array in lvm_do_lv_status_byname. For
315 * - restore copying pe_t array in lvm_do_lv_status_byindex (HM)
316 * - added copying pe_t array in lvm_do_lv_status_bydev (HM)
317 * - enhanced lvm_do_lv_status_by{name,index,dev} to be capable
318 * to copy the lv_block_exception_t array to userspace (HM)
319 - * 08/03/2001 - factored lvm_do_pv_flush out of lvm_chr_ioctl [HM]
320 + * 08/03/2001 - initialize new lv_ptr->lv_COW_table_iobuf for snapshots;
321 + * removed obsolete lv_ptr->lv_COW_table_page initialization
322 + * - factored lvm_do_pv_flush out of lvm_chr_ioctl (HM)
323 * 09/03/2001 - Added _lock_open_count to ensure we only drop the lock
324 * when the locking process closes.
325 - * 05/04/2001 - lvm_map bugs: don't use b_blocknr/b_dev in lvm_map, it
326 - * destroys stacking devices. call b_end_io on failed maps.
328 - * - Defer writes to an extent that is being moved [JT + AD]
329 - * 28/05/2001 - implemented missing BLKSSZGET ioctl [AD]
330 + * 05/04/2001 - Defer writes to an extent that is being moved [JT]
331 + * 05/04/2001 - use b_rdev and b_rsector rather than b_dev and b_blocknr in
332 + * lvm_map() in order to make stacking devices more happy (HM)
333 + * 11/04/2001 - cleaned up the pvmove queue code. I no longer retain the
334 + * rw flag, instead WRITEA's are just dropped [JT]
335 + * 30/04/2001 - added KERNEL_VERSION > 2.4.3 get_hardsect_size() rather
336 + * than get_hardblocksize() call
337 + * 03/05/2001 - Use copy_to/from_user to preserve pointers in
338 + * lvm_do_status_by*
339 + * 11/05/2001 - avoid accesses to inactive snapshot data in
340 + * __update_hardsectsize() and lvm_do_lv_extend_reduce() (JW)
341 + * 28/05/2001 - implemented missing BLKSSZGET ioctl
342 + * 05/06/2001 - Move _pe_lock out of fast path for lvm_map when no PEs
343 + * locked. Make buffer queue flush not need locking.
344 + * Fix lvm_user_bmap() to set b_rsector for new lvm_map(). [AED]
345 + * 30/06/2001 - Speed up __update_hardsectsize() by checking if PVs have
346 + * the same hardsectsize (very likely) before scanning all LEs
347 + * in the LV each time. [AED]
348 + * 12/10/2001 - Use add/del_gendisk() routines in 2.4.10+
349 + * 01/11/2001 - Backport read_ahead change from Linus kernel [AED]
353 +#include <linux/version.h>
355 #define MAJOR_NR LVM_BLK_MAJOR
356 #define DEVICE_OFF(device)
357 @@ -191,11 +227,10 @@
358 /* #define LVM_VFS_ENHANCEMENT */
360 #include <linux/config.h>
362 #include <linux/module.h>
364 #include <linux/kernel.h>
365 #include <linux/vmalloc.h>
367 #include <linux/slab.h>
368 #include <linux/init.h>
371 #include <linux/blkdev.h>
372 #include <linux/genhd.h>
373 #include <linux/locks.h>
376 #include <linux/devfs_fs_kernel.h>
377 #include <linux/smp_lock.h>
378 #include <asm/ioctl.h>
381 #include "lvm-internal.h"
383 -#define LVM_CORRECT_READ_AHEAD( a) \
384 - if ( a < LVM_MIN_READ_AHEAD || \
385 - a > LVM_MAX_READ_AHEAD) a = LVM_MAX_READ_AHEAD;
386 +#define LVM_CORRECT_READ_AHEAD(a) \
388 + if ((a) < LVM_MIN_READ_AHEAD || \
389 + (a) > LVM_MAX_READ_AHEAD) \
390 + (a) = LVM_DEFAULT_READ_AHEAD; \
391 + read_ahead[MAJOR_NR] = (a); \
395 # define WRITEA WRITE
399 struct file_operations lvm_chr_fops = {
400 + owner: THIS_MODULE,
402 release: lvm_chr_close,
403 ioctl: lvm_chr_ioctl,
405 struct block_device_operations lvm_blk_dops =
408 - open: lvm_blk_open,
409 + open: lvm_blk_open,
410 release: lvm_blk_close,
411 ioctl: lvm_blk_ioctl,
419 * Driver initialization...
426 if (devfs_register_blkdev(MAJOR_NR, lvm_name, &lvm_blk_dops) < 0)
428 printk("%s -- devfs_register_blkdev failed\n", lvm_name);
431 lvm_geninit(&lvm_gendisk);
433 + /* insert our gendisk at the corresponding major */
434 add_gendisk(&lvm_gendisk);
437 @@ -436,10 +479,10 @@
446 static void lvm_cleanup(void)
448 if (devfs_unregister_chrdev(LVM_CHAR_MAJOR, lvm_name) < 0)
450 printk(KERN_ERR "%s -- devfs_unregister_blkdev failed\n",
455 + /* delete our gendisk from chain */
456 del_gendisk(&lvm_gendisk);
458 blk_size[MAJOR_NR] = NULL;
461 static int lvm_chr_open(struct inode *inode, struct file *file)
463 - unsigned int minor = MINOR(inode->i_rdev);
464 + int minor = MINOR(inode->i_rdev);
466 P_DEV("chr_open MINOR: %d VG#: %d mode: %s%s lock: %d\n",
467 minor, VG_CHR(minor), MODE_TO_STR(file->f_mode), lock);
468 @@ -525,10 +571,10 @@
469 /* Group special file open */
470 if (VG_CHR(minor) > MAX_VG) return -ENXIO;
472 - spin_lock(&lvm_lock);
473 - if(lock == current->pid)
474 - _lock_open_count++;
475 - spin_unlock(&lvm_lock);
476 + spin_lock(&lvm_lock);
477 + if(lock == current->pid)
478 + _lock_open_count++;
479 + spin_unlock(&lvm_lock);
481 lvm_chr_open_count++;
486 static int lvm_chr_ioctl(struct inode *inode, struct file *file,
487 - uint command, ulong a)
488 + uint command, ulong a)
490 int minor = MINOR(inode->i_rdev);
491 uint extendable, l, v;
494 return lvm_do_vg_create(arg, minor);
497 - /* create a VGDA, assume VG number is filled in */
499 + /* create a VGDA, assume VG number is filled in */
500 return lvm_do_vg_create(arg, -1);
506 /* physical volume buffer flush/invalidate */
507 - return lvm_do_pv_flush(arg);
508 + return lvm_do_pv_flush(arg);
512 @@ -765,16 +811,16 @@
514 if (lvm_chr_open_count > 0) lvm_chr_open_count--;
516 - spin_lock(&lvm_lock);
517 - if(lock == current->pid) {
518 - if(!_lock_open_count) {
519 + spin_lock(&lvm_lock);
520 + if(lock == current->pid) {
521 + if(!_lock_open_count) {
522 P_DEV("chr_close: unlocking LVM for pid %d\n", lock);
524 - wake_up_interruptible(&lvm_wait);
526 - _lock_open_count--;
528 + wake_up_interruptible(&lvm_wait);
530 + _lock_open_count--;
532 - spin_unlock(&lvm_lock);
533 + spin_unlock(&lvm_lock);
540 /* get block device sector size as needed e.g. by fdisk */
541 - return put_user(get_hardsect_size(inode->i_rdev), (int *) arg);
542 + return put_user(lvm_sectsize(inode->i_rdev), (int *) arg);
545 /* return device size */
546 @@ -869,11 +915,12 @@
552 if (put_user((u64)lv_ptr->lv_size << 9, (u64 *)arg))
559 /* flush buffer cache */
561 (long) arg > LVM_MAX_READ_AHEAD)
563 lv_ptr->lv_read_ahead = (long) arg;
564 + read_ahead[MAJOR_NR] = lv_ptr->lv_read_ahead;
568 @@ -955,12 +1003,13 @@
572 - /* turn logical block into (dev_t, block). non privileged. */
573 - /* don't bmap a snapshot, since the mapping can change */
574 - if(lv_ptr->lv_access & LV_SNAPSHOT)
575 + /* turn logical block into (dev_t, block). non privileged. */
576 + /* don't bmap a snapshot, since the mapping can change */
577 + if (lv_ptr->lv_access & LV_SNAPSHOT)
580 return lvm_user_bmap(inode, (struct lv_bmap *) arg);
583 case LV_SET_ALLOCATION:
584 /* set allocation flags of a logical volume */
585 @@ -1048,7 +1097,7 @@
586 bh.b_blocknr = block;
587 bh.b_dev = bh.b_rdev = inode->i_rdev;
588 bh.b_size = lvm_get_blksize(bh.b_dev);
589 - bh.b_rsector = block * (bh.b_size >> 9);
590 + bh.b_rsector = block * (bh.b_size >> 9);
591 if ((err=lvm_map(&bh, READ)) < 0) {
592 printk("lvm map failed: %d\n", err);
594 @@ -1056,7 +1105,7 @@
596 return put_user(kdev_t_to_nr(bh.b_rdev), &user_result->lv_dev) ||
597 put_user(bh.b_rsector/(bh.b_size>>9), &user_result->lv_block) ?
603 @@ -1065,7 +1114,7 @@
604 * (see init_module/lvm_init)
606 static void __remap_snapshot(kdev_t rdev, ulong rsector,
607 - ulong pe_start, lv_t *lv, vg_t *vg) {
608 + ulong pe_start, lv_t *lv, vg_t *vg) {
610 /* copy a chunk from the origin to a snapshot device */
611 down_write(&lv->lv_lock);
612 @@ -1122,6 +1171,7 @@
617 static int lvm_map(struct buffer_head *bh, int rw)
619 int minor = MINOR(bh->b_rdev);
620 @@ -1223,10 +1273,8 @@
623 if (lv->lv_access & LV_SNAPSHOT) { /* remap snapshot */
624 - if (lv->lv_block_exception)
625 - lvm_snapshot_remap_block(&rdev_map, &rsector_map,
628 + if (lvm_snapshot_remap_block(&rdev_map, &rsector_map,
632 } else if (rw == WRITE || rw == WRITEA) { /* snapshot origin */
633 @@ -1245,7 +1293,7 @@
634 _remap_snapshot(rdev_map, rsector_map,
635 pe_start, snap, vg_this);
641 bh->b_rdev = rdev_map;
642 @@ -1284,12 +1332,15 @@
649 * make request function
651 static int lvm_make_request_fn(request_queue_t *q,
653 - struct buffer_head *bh) {
654 + struct buffer_head *bh)
656 return (lvm_map(bh, rw) <= 0) ? 0 : 1;
659 @@ -1457,14 +1508,14 @@
663 - /* VG_CREATE now uses minor number in VG structure */
664 - if (minor == -1) minor = vg_ptr->vg_number;
665 + /* VG_CREATE now uses minor number in VG structure */
666 + if (minor == -1) minor = vg_ptr->vg_number;
669 - if (vg[VG_CHR(minor)] != NULL) {
670 + if (vg[VG_CHR(minor)] != NULL) {
671 P_IOCTL("lvm_do_vg_create ERROR: VG %d in use\n", minor);
677 /* we are not that active so far... */
678 @@ -1637,7 +1688,8 @@
682 - if (vg_ptr == NULL) return -ENXIO;
683 + /* If the VG doesn't exist in the kernel then just exit */
684 + if (!vg_ptr) return 0;
686 if (copy_from_user(vg_name, arg, sizeof(vg_name)) != 0)
688 @@ -1797,30 +1849,56 @@
692 -static void __update_hardsectsize(lv_t *lv) {
694 - int max_hardsectsize = 0, hardsectsize;
696 - for (le = 0; le < lv->lv_allocated_le; le++) {
697 - hardsectsize = get_hardsect_size(lv->lv_current_pe[le].dev);
698 - if (hardsectsize == 0)
699 - hardsectsize = 512;
700 - if (hardsectsize > max_hardsectsize)
701 - max_hardsectsize = hardsectsize;
704 - /* only perform this operation on active snapshots */
705 - if ((lv->lv_access & LV_SNAPSHOT) &&
706 - (lv->lv_status & LV_ACTIVE)) {
707 - for (e = 0; e < lv->lv_remap_end; e++) {
708 - hardsectsize = get_hardsect_size( lv->lv_block_exception[e].rdev_new);
709 - if (hardsectsize == 0)
710 - hardsectsize = 512;
711 - if (hardsectsize > max_hardsectsize)
712 +static void __update_hardsectsize(lv_t *lv)
714 + int max_hardsectsize = 0, hardsectsize = 0;
717 + /* Check PVs first to see if they all have same sector size */
718 + for (p = 0; p < lv->vg->pv_cur; p++) {
719 + pv_t *pv = lv->vg->pv[p];
720 + if (pv && (hardsectsize = lvm_sectsize(pv->pv_dev))) {
721 + if (max_hardsectsize == 0)
722 max_hardsectsize = hardsectsize;
723 + else if (hardsectsize != max_hardsectsize) {
724 + P_DEV("%s PV[%d] (%s) sector size %d, not %d\n",
725 + lv->lv_name, p, kdevname(pv->pv_dev),
726 + hardsectsize, max_hardsectsize);
732 + /* PVs have different block size, need to check each LE sector size */
733 + if (hardsectsize != max_hardsectsize) {
735 + for (le = 0; le < lv->lv_allocated_le; le++) {
736 + hardsectsize = lvm_sectsize(lv->lv_current_pe[le].dev);
737 + if (hardsectsize > max_hardsectsize) {
738 + P_DEV("%s LE[%d] (%s) blocksize %d not %d\n",
740 + kdevname(lv->lv_current_pe[le].dev),
741 + hardsectsize, max_hardsectsize);
742 + max_hardsectsize = hardsectsize;
746 + /* only perform this operation on active snapshots */
747 + if ((lv->lv_access & LV_SNAPSHOT) &&
748 + (lv->lv_status & LV_ACTIVE)) {
750 + for (e = 0; e < lv->lv_remap_end; e++) {
751 + hardsectsize = lvm_sectsize(lv->lv_block_exception[e].rdev_new);
752 + if (hardsectsize > max_hardsectsize)
753 + max_hardsectsize = hardsectsize;
758 + if (max_hardsectsize == 0)
759 + max_hardsectsize = SECTOR_SIZE;
760 + P_DEV("hardblocksize for LV %s is %d\n",
761 + kdevname(lv->lv_dev), max_hardsectsize);
762 lvm_hardsectsizes[MINOR(lv->lv_dev)] = max_hardsectsize;
765 @@ -1876,7 +1954,7 @@
766 lv_ptr->lv_snapshot_next = NULL;
767 lv_ptr->lv_block_exception = NULL;
768 lv_ptr->lv_iobuf = NULL;
769 - lv_ptr->lv_COW_table_iobuf = NULL;
770 + lv_ptr->lv_COW_table_iobuf = NULL;
771 lv_ptr->lv_snapshot_hash_table = NULL;
772 lv_ptr->lv_snapshot_hash_table_size = 0;
773 lv_ptr->lv_snapshot_hash_mask = 0;
774 @@ -1926,7 +2004,7 @@
775 if (lv_ptr->lv_snapshot_org != NULL) {
776 size = lv_ptr->lv_remap_end * sizeof(lv_block_exception_t);
781 "%s -- zero length exception table requested\n",
783 @@ -1956,12 +2034,11 @@
784 LVM_SNAPSHOT_DROPPED_SECTOR)
787 - "%s -- lvm_do_lv_create: snapshot has been dropped and will not be activated\n",
788 + "%s -- lvm_do_lv_create: snapshot has been dropped and will not be activated\n",
794 /* point to the original logical volume */
795 lv_ptr = lv_ptr->lv_snapshot_org;
797 @@ -1995,11 +2072,11 @@
798 lv_ptr->lv_block_exception[e].rsector_org, lv_ptr);
799 /* need to fill the COW exception table data
800 into the page for disk i/o */
801 - if(lvm_snapshot_fill_COW_page(vg_ptr, lv_ptr)) {
803 - vg_ptr->lv[l] = NULL;
806 + if(lvm_snapshot_fill_COW_page(vg_ptr, lv_ptr)) {
808 + vg_ptr->lv[l] = NULL;
811 init_waitqueue_head(&lv_ptr->lv_snapshot_wait);
814 @@ -2022,6 +2099,7 @@
815 LVM_CORRECT_READ_AHEAD(lv_ptr->lv_read_ahead);
817 lv_ptr->lv_status = lv_status_save;
818 + lv_ptr->vg = vg_ptr;
820 __update_hardsectsize(lv_ptr);
822 @@ -2040,6 +2118,7 @@
823 org->lv_access |= LV_SNAPSHOT_ORG;
824 lv_ptr->lv_access &= ~LV_SNAPSHOT_ORG; /* this can only hide an userspace bug */
827 /* Link in the list of snapshot volumes */
828 for (last = org; last->lv_snapshot_next; last = last->lv_snapshot_next);
829 lv_ptr->lv_snapshot_prev = last;
830 @@ -2064,11 +2143,8 @@
831 unlockfs(lv_ptr->lv_snapshot_org->lv_dev);
834 - lv_ptr->vg = vg_ptr;
836 lvm_gendisk.part[MINOR(lv_ptr->lv_dev)].de =
837 - lvm_fs_create_lv(vg_ptr, lv_ptr);
839 + lvm_fs_create_lv(vg_ptr, lv_ptr);
841 } /* lvm_do_lv_create() */
843 @@ -2184,214 +2260,213 @@
844 * logical volume extend / reduce
846 static int __extend_reduce_snapshot(vg_t *vg_ptr, lv_t *old_lv, lv_t *new_lv) {
848 - lv_block_exception_t *lvbe;
850 + lv_block_exception_t *lvbe;
852 - if (!new_lv->lv_block_exception)
854 + if (!new_lv->lv_block_exception)
857 + size = new_lv->lv_remap_end * sizeof(lv_block_exception_t);
858 + if ((lvbe = vmalloc(size)) == NULL) {
860 + "%s -- lvm_do_lv_extend_reduce: vmalloc "
861 + "error LV_BLOCK_EXCEPTION of %lu Byte at line %d\n",
862 + lvm_name, size, __LINE__);
866 + if ((new_lv->lv_remap_end > old_lv->lv_remap_end) &&
867 + (copy_from_user(lvbe, new_lv->lv_block_exception, size))) {
871 + new_lv->lv_block_exception = lvbe;
873 - size = new_lv->lv_remap_end * sizeof(lv_block_exception_t);
874 - if ((lvbe = vmalloc(size)) == NULL) {
876 - "%s -- lvm_do_lv_extend_reduce: vmalloc "
877 - "error LV_BLOCK_EXCEPTION of %lu Byte at line %d\n",
878 - lvm_name, size, __LINE__);
882 - if ((new_lv->lv_remap_end > old_lv->lv_remap_end) &&
883 - (copy_from_user(lvbe, new_lv->lv_block_exception, size))) {
887 - new_lv->lv_block_exception = lvbe;
889 - if (lvm_snapshot_alloc_hash_table(new_lv)) {
890 - vfree(new_lv->lv_block_exception);
893 + if (lvm_snapshot_alloc_hash_table(new_lv)) {
894 + vfree(new_lv->lv_block_exception);
902 static int __extend_reduce(vg_t *vg_ptr, lv_t *old_lv, lv_t *new_lv) {
903 - ulong size, l, p, end;
905 + ulong size, l, p, end;
908 + /* allocate space for new pe structures */
909 + size = new_lv->lv_current_le * sizeof(pe_t);
910 + if ((pe = vmalloc(size)) == NULL) {
912 + "%s -- lvm_do_lv_extend_reduce: "
913 + "vmalloc error LV_CURRENT_PE of %lu Byte at line %d\n",
914 + lvm_name, size, __LINE__);
918 + /* get the PE structures from user space */
919 + if (copy_from_user(pe, new_lv->lv_current_pe, size)) {
920 + if(old_lv->lv_access & LV_SNAPSHOT)
921 + vfree(new_lv->lv_snapshot_hash_table);
926 + new_lv->lv_current_pe = pe;
928 + /* reduce allocation counters on PV(s) */
929 + for (l = 0; l < old_lv->lv_allocated_le; l++) {
930 + vg_ptr->pe_allocated--;
931 + for (p = 0; p < vg_ptr->pv_cur; p++) {
932 + if (vg_ptr->pv[p]->pv_dev ==
933 + old_lv->lv_current_pe[l].dev) {
934 + vg_ptr->pv[p]->pe_allocated--;
940 - /* allocate space for new pe structures */
941 - size = new_lv->lv_current_le * sizeof(pe_t);
942 - if ((pe = vmalloc(size)) == NULL) {
944 - "%s -- lvm_do_lv_extend_reduce: "
945 - "vmalloc error LV_CURRENT_PE of %lu Byte at line %d\n",
946 - lvm_name, size, __LINE__);
950 - /* get the PE structures from user space */
951 - if (copy_from_user(pe, new_lv->lv_current_pe, size)) {
952 - if(old_lv->lv_access & LV_SNAPSHOT)
953 - vfree(new_lv->lv_snapshot_hash_table);
958 - new_lv->lv_current_pe = pe;
960 - /* reduce allocation counters on PV(s) */
961 - for (l = 0; l < old_lv->lv_allocated_le; l++) {
962 - vg_ptr->pe_allocated--;
963 - for (p = 0; p < vg_ptr->pv_cur; p++) {
964 - if (vg_ptr->pv[p]->pv_dev ==
965 - old_lv->lv_current_pe[l].dev) {
966 - vg_ptr->pv[p]->pe_allocated--;
972 - /* extend the PE count in PVs */
973 - for (l = 0; l < new_lv->lv_allocated_le; l++) {
974 - vg_ptr->pe_allocated++;
975 - for (p = 0; p < vg_ptr->pv_cur; p++) {
976 - if (vg_ptr->pv[p]->pv_dev ==
977 + /* extend the PE count in PVs */
978 + for (l = 0; l < new_lv->lv_allocated_le; l++) {
979 + vg_ptr->pe_allocated++;
980 + for (p = 0; p < vg_ptr->pv_cur; p++) {
981 + if (vg_ptr->pv[p]->pv_dev ==
982 new_lv->lv_current_pe[l].dev) {
983 - vg_ptr->pv[p]->pe_allocated++;
989 - /* save availiable i/o statistic data */
990 - if (old_lv->lv_stripes < 2) { /* linear logical volume */
991 - end = min(old_lv->lv_current_le, new_lv->lv_current_le);
992 - for (l = 0; l < end; l++) {
993 - new_lv->lv_current_pe[l].reads +=
994 - old_lv->lv_current_pe[l].reads;
996 - new_lv->lv_current_pe[l].writes +=
997 - old_lv->lv_current_pe[l].writes;
1000 - } else { /* striped logical volume */
1001 - uint i, j, source, dest, end, old_stripe_size, new_stripe_size;
1003 - old_stripe_size = old_lv->lv_allocated_le / old_lv->lv_stripes;
1004 - new_stripe_size = new_lv->lv_allocated_le / new_lv->lv_stripes;
1005 - end = min(old_stripe_size, new_stripe_size);
1007 - for (i = source = dest = 0;
1008 - i < new_lv->lv_stripes; i++) {
1009 - for (j = 0; j < end; j++) {
1010 - new_lv->lv_current_pe[dest + j].reads +=
1011 - old_lv->lv_current_pe[source + j].reads;
1012 - new_lv->lv_current_pe[dest + j].writes +=
1013 - old_lv->lv_current_pe[source + j].writes;
1015 - source += old_stripe_size;
1016 - dest += new_stripe_size;
1019 + vg_ptr->pv[p]->pe_allocated++;
1026 + /* save availiable i/o statistic data */
1027 + if (old_lv->lv_stripes < 2) { /* linear logical volume */
1028 + end = min(old_lv->lv_current_le, new_lv->lv_current_le);
1029 + for (l = 0; l < end; l++) {
1030 + new_lv->lv_current_pe[l].reads +=
1031 + old_lv->lv_current_pe[l].reads;
1033 + new_lv->lv_current_pe[l].writes +=
1034 + old_lv->lv_current_pe[l].writes;
1037 + } else { /* striped logical volume */
1038 + uint i, j, source, dest, end, old_stripe_size, new_stripe_size;
1040 + old_stripe_size = old_lv->lv_allocated_le / old_lv->lv_stripes;
1041 + new_stripe_size = new_lv->lv_allocated_le / new_lv->lv_stripes;
1042 + end = min(old_stripe_size, new_stripe_size);
1044 + for (i = source = dest = 0; i < new_lv->lv_stripes; i++) {
1045 + for (j = 0; j < end; j++) {
1046 + new_lv->lv_current_pe[dest + j].reads +=
1047 + old_lv->lv_current_pe[source + j].reads;
1048 + new_lv->lv_current_pe[dest + j].writes +=
1049 + old_lv->lv_current_pe[source + j].writes;
1051 + source += old_stripe_size;
1052 + dest += new_stripe_size;
1059 static int lvm_do_lv_extend_reduce(int minor, char *lv_name, lv_t *new_lv)
1063 - vg_t *vg_ptr = vg[VG_CHR(minor)];
1067 - if ((pe = new_lv->lv_current_pe) == NULL)
1070 - for (l = 0; l < vg_ptr->lv_max; l++)
1071 - if (vg_ptr->lv[l] && !strcmp(vg_ptr->lv[l]->lv_name, lv_name))
1075 + vg_t *vg_ptr = vg[VG_CHR(minor)];
1079 - if (l == vg_ptr->lv_max)
1081 + if ((pe = new_lv->lv_current_pe) == NULL)
1084 - old_lv = vg_ptr->lv[l];
1085 + for (l = 0; l < vg_ptr->lv_max; l++)
1086 + if (vg_ptr->lv[l] && !strcmp(vg_ptr->lv[l]->lv_name, lv_name))
1089 + if (l == vg_ptr->lv_max)
1092 + old_lv = vg_ptr->lv[l];
1094 if (old_lv->lv_access & LV_SNAPSHOT) {
1095 /* only perform this operation on active snapshots */
1096 if (old_lv->lv_status & LV_ACTIVE)
1097 - r = __extend_reduce_snapshot(vg_ptr, old_lv, new_lv);
1099 + r = __extend_reduce_snapshot(vg_ptr, old_lv, new_lv);
1104 - r = __extend_reduce(vg_ptr, old_lv, new_lv);
1105 + r = __extend_reduce(vg_ptr, old_lv, new_lv);
1112 - /* copy relevent fields */
1113 + /* copy relevent fields */
1114 down_write(&old_lv->lv_lock);
1116 - if(new_lv->lv_access & LV_SNAPSHOT) {
1117 - size = (new_lv->lv_remap_end > old_lv->lv_remap_end) ?
1118 - old_lv->lv_remap_ptr : new_lv->lv_remap_end;
1119 - size *= sizeof(lv_block_exception_t);
1120 - memcpy(new_lv->lv_block_exception,
1121 - old_lv->lv_block_exception, size);
1123 - old_lv->lv_remap_end = new_lv->lv_remap_end;
1124 - old_lv->lv_block_exception = new_lv->lv_block_exception;
1125 - old_lv->lv_snapshot_hash_table =
1126 - new_lv->lv_snapshot_hash_table;
1127 - old_lv->lv_snapshot_hash_table_size =
1128 - new_lv->lv_snapshot_hash_table_size;
1129 - old_lv->lv_snapshot_hash_mask =
1130 - new_lv->lv_snapshot_hash_mask;
1132 - for (e = 0; e < new_lv->lv_remap_ptr; e++)
1133 - lvm_hash_link(new_lv->lv_block_exception + e,
1134 - new_lv->lv_block_exception[e].rdev_org,
1135 - new_lv->lv_block_exception[e].rsector_org,
1140 - vfree(old_lv->lv_current_pe);
1141 - vfree(old_lv->lv_snapshot_hash_table);
1143 - old_lv->lv_size = new_lv->lv_size;
1144 - old_lv->lv_allocated_le = new_lv->lv_allocated_le;
1145 - old_lv->lv_current_le = new_lv->lv_current_le;
1146 - old_lv->lv_current_pe = new_lv->lv_current_pe;
1147 - lvm_gendisk.part[MINOR(old_lv->lv_dev)].nr_sects =
1149 - lvm_size[MINOR(old_lv->lv_dev)] = old_lv->lv_size >> 1;
1151 - if (old_lv->lv_access & LV_SNAPSHOT_ORG) {
1153 - for(snap = old_lv->lv_snapshot_next; snap;
1154 - snap = snap->lv_snapshot_next) {
1155 + if(new_lv->lv_access & LV_SNAPSHOT) {
1156 + size = (new_lv->lv_remap_end > old_lv->lv_remap_end) ?
1157 + old_lv->lv_remap_ptr : new_lv->lv_remap_end;
1158 + size *= sizeof(lv_block_exception_t);
1159 + memcpy(new_lv->lv_block_exception,
1160 + old_lv->lv_block_exception, size);
1162 + old_lv->lv_remap_end = new_lv->lv_remap_end;
1163 + old_lv->lv_block_exception = new_lv->lv_block_exception;
1164 + old_lv->lv_snapshot_hash_table =
1165 + new_lv->lv_snapshot_hash_table;
1166 + old_lv->lv_snapshot_hash_table_size =
1167 + new_lv->lv_snapshot_hash_table_size;
1168 + old_lv->lv_snapshot_hash_mask =
1169 + new_lv->lv_snapshot_hash_mask;
1171 + for (e = 0; e < new_lv->lv_remap_ptr; e++)
1172 + lvm_hash_link(new_lv->lv_block_exception + e,
1173 + new_lv->lv_block_exception[e].rdev_org,
1174 + new_lv->lv_block_exception[e].rsector_org,
1179 + vfree(old_lv->lv_current_pe);
1180 + vfree(old_lv->lv_snapshot_hash_table);
1182 + old_lv->lv_size = new_lv->lv_size;
1183 + old_lv->lv_allocated_le = new_lv->lv_allocated_le;
1184 + old_lv->lv_current_le = new_lv->lv_current_le;
1185 + old_lv->lv_current_pe = new_lv->lv_current_pe;
1186 + lvm_gendisk.part[MINOR(old_lv->lv_dev)].nr_sects =
1188 + lvm_size[MINOR(old_lv->lv_dev)] = old_lv->lv_size >> 1;
1190 + if (old_lv->lv_access & LV_SNAPSHOT_ORG) {
1192 + for(snap = old_lv->lv_snapshot_next; snap;
1193 + snap = snap->lv_snapshot_next) {
1194 down_write(&snap->lv_lock);
1195 - snap->lv_current_pe = old_lv->lv_current_pe;
1196 - snap->lv_allocated_le =
1197 - old_lv->lv_allocated_le;
1198 - snap->lv_current_le = old_lv->lv_current_le;
1199 - snap->lv_size = old_lv->lv_size;
1201 - lvm_gendisk.part[MINOR(snap->lv_dev)].nr_sects
1202 - = old_lv->lv_size;
1203 - lvm_size[MINOR(snap->lv_dev)] =
1204 - old_lv->lv_size >> 1;
1205 - __update_hardsectsize(snap);
1206 + snap->lv_current_pe = old_lv->lv_current_pe;
1207 + snap->lv_allocated_le =
1208 + old_lv->lv_allocated_le;
1209 + snap->lv_current_le = old_lv->lv_current_le;
1210 + snap->lv_size = old_lv->lv_size;
1212 + lvm_gendisk.part[MINOR(snap->lv_dev)].nr_sects
1213 + = old_lv->lv_size;
1214 + lvm_size[MINOR(snap->lv_dev)] =
1215 + old_lv->lv_size >> 1;
1216 + __update_hardsectsize(snap);
1217 up_write(&snap->lv_lock);
1225 - __update_hardsectsize(old_lv);
1226 + __update_hardsectsize(old_lv);
1227 up_write(&old_lv->lv_lock);
1231 } /* lvm_do_lv_extend_reduce() */
1234 @@ -2426,7 +2501,6 @@
1239 if (saved_ptr1 != NULL) {
1240 if (copy_to_user(saved_ptr1,
1241 lv_ptr->lv_current_pe,
1242 @@ -2461,9 +2535,6 @@
1244 if (lv_status_byindex_req.lv == NULL)
1246 - if (lv_status_byindex_req.lv_index <0 ||
1247 - lv_status_byindex_req.lv_index >= MAX_LV)
1249 if ( ( lv_ptr = vg_ptr->lv[lv_status_byindex_req.lv_index]) == NULL)
1252 @@ -2552,9 +2623,7 @@
1253 if (lv_ptr->lv_dev == lv->lv_dev)
1255 lvm_fs_remove_lv(vg_ptr, lv_ptr);
1256 - strncpy(lv_ptr->lv_name,
1259 + strncpy(lv_ptr->lv_name, lv_req->lv_name, NAME_LEN);
1260 lvm_fs_create_lv(vg_ptr, lv_ptr);
1263 @@ -2629,23 +2698,24 @@
1265 } /* lvm_do_pv_status() */
1269 * character device support function flush and invalidate all buffers of a PV
1271 static int lvm_do_pv_flush(void *arg)
1273 - pv_flush_req_t pv_flush_req;
1274 + pv_flush_req_t pv_flush_req;
1276 - if (copy_from_user(&pv_flush_req, arg,
1277 - sizeof(pv_flush_req)) != 0)
1279 + if (copy_from_user(&pv_flush_req, arg, sizeof(pv_flush_req)) != 0)
1282 - fsync_dev(pv_flush_req.pv_dev);
1283 - invalidate_buffers(pv_flush_req.pv_dev);
1284 + fsync_dev(pv_flush_req.pv_dev);
1285 + invalidate_buffers(pv_flush_req.pv_dev);
1293 * support function initialize gendisk variables
1295 @@ -2708,6 +2778,7 @@
1301 * we must open the pv's before we use them
1303 @@ -2719,22 +2790,25 @@
1306 err = blkdev_get(bd, FMODE_READ|FMODE_WRITE, 0, BDEV_FILE);
1317 static void _close_pv(pv_t *pv) {
1319 - struct block_device *bdev = pv->bd;
1322 - blkdev_put(bdev, BDEV_FILE);
1324 + if(!pv || !pv->bd)
1327 + blkdev_put(pv->bd, BDEV_FILE);
1333 static unsigned long _sectors_to_k(unsigned long sect)
1335 if(SECTOR_SIZE > 1024) {
1336 @@ -2744,6 +2818,11 @@
1337 return sect / (1024 / SECTOR_SIZE);
1340 +MODULE_AUTHOR("Heinz Mauelshagen, Sistina Software");
1341 +MODULE_DESCRIPTION("Logical Volume Manager");
1342 +#ifdef MODULE_LICENSE
1343 +MODULE_LICENSE("GPL");
1346 module_init(lvm_init);
1347 module_exit(lvm_cleanup);
1348 -MODULE_LICENSE("GPL");
1349 --- linux/drivers/md/lvm-internal.h.orig Sun Nov 11 18:09:32 2001
1350 +++ linux/drivers/md/lvm-internal.h Thu Jan 10 12:24:08 2002
1354 - * kernel/lvm-internal.h
1355 + * kernel/lvm_internal.h
1357 * Copyright (C) 2001 Sistina Software
1363 - * 05/01/2001:Joe Thornber - Factored this file out of lvm.c
1364 + * 05/01/2001 - Factored this file out of lvm.c (Joe Thornber)
1365 + * 11/01/2001 - Renamed lvm_internal and added declarations
1366 + * for lvm_fs.c stuff
1372 #include <linux/lvm.h>
1374 -#define _LVM_INTERNAL_H_VERSION "LVM "LVM_RELEASE_NAME" ("LVM_RELEASE_DATE")"
1375 +#define _LVM_INTERNAL_H_VERSION "LVM "LVM_RELEASE_NAME" ("LVM_RELEASE_DATE")"
1377 /* global variables, defined in lvm.c */
1378 extern char *lvm_version;
1380 extern const char *const lvm_name;
1383 +extern uint vg_count;
1385 extern struct file_operations lvm_chr_fops;
1387 extern struct block_device_operations lvm_blk_dops;
1389 +#define lvm_sectsize(dev) get_hardsect_size(dev)
1391 +/* 2.4.8 had no global min/max macros, and 2.4.9's were flawed */
1395 --- linux/drivers/md/lvm-snap.c.orig Fri Dec 21 17:41:54 2001
1396 +++ linux/drivers/md/lvm-snap.c Thu Jan 10 12:24:08 2002
1400 * Copyright (C) 2000 Andrea Arcangeli <andrea@suse.de> SuSE
1401 - * Heinz Mauelshagen, Sistina Software (persistent snapshots)
1402 + * 2000 - 2001 Heinz Mauelshagen, Sistina Software
1404 * LVM snapshot driver is free software; you can redistribute it and/or modify
1405 * it under the terms of the GNU General Public License as published by
1406 * the Free Software Foundation; either version 2, or (at your option)
1407 * any later version.
1410 * LVM snapshot driver is distributed in the hope that it will be useful,
1411 * but WITHOUT ANY WARRANTY; without even the implied warranty of
1412 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1413 * GNU General Public License for more details.
1416 * You should have received a copy of the GNU General Public License
1417 * along with GNU CC; see the file COPYING. If not, write to
1418 * the Free Software Foundation, 59 Temple Place - Suite 330,
1419 - * Boston, MA 02111-1307, USA.
1420 + * Boston, MA 02111-1307, USA.
1425 * 23/11/2000 - used cpu_to_le64 rather than my own macro
1426 * 25/01/2001 - Put LockPage back in
1427 * 01/02/2001 - A dropped snapshot is now set as inactive
1428 + * 14/02/2001 - tidied debug statements
1429 + * 19/02/2001 - changed rawio calls to pass in preallocated buffer_heads
1430 + * 26/02/2001 - introduced __brw_kiovec to remove a lot of conditional
1432 + * 07/03/2001 - fixed COW exception table not persistent on 2.2 (HM)
1433 * 12/03/2001 - lvm_pv_get_number changes:
1435 * o renamed it to _pv_get_number
1436 * o pv number is returned in new uint * arg
1437 * o -1 returned on error
1438 * lvm_snapshot_fill_COW_table has a return value too.
1439 + * 15/10/2001 - fix snapshot alignment problem [CM]
1440 + * - fix snapshot full oops (always check lv_block_exception) [CM]
1444 #include <linux/kernel.h>
1445 -#include <linux/module.h>
1446 #include <linux/vmalloc.h>
1447 #include <linux/blkdev.h>
1448 #include <linux/smp_lock.h>
1449 #include <linux/types.h>
1450 #include <linux/iobuf.h>
1451 #include <linux/lvm.h>
1452 +#include <linux/devfs_fs_kernel.h>
1455 #include "lvm-internal.h"
1457 -static char *lvm_snap_version __attribute__ ((unused)) =
1458 - "LVM "LVM_RELEASE_NAME" snapshot code ("LVM_RELEASE_DATE")\n";
1459 +static char *lvm_snap_version __attribute__ ((unused)) = "LVM "LVM_RELEASE_NAME" snapshot code ("LVM_RELEASE_DATE")\n";
1462 extern const char *const lvm_name;
1463 extern int lvm_blocksizes[];
1465 void lvm_snapshot_release(lv_t *);
1467 static int _write_COW_table_block(vg_t *vg, lv_t *lv, int idx,
1468 - const char **reason);
1469 + const char **reason);
1470 static void _disable_snapshot(vg_t *vg, lv_t *lv);
1473 -static int _pv_get_number(vg_t * vg, kdev_t rdev, uint *pvn) {
1474 +static inline int __brw_kiovec(int rw, int nr, struct kiobuf *iovec[],
1475 + kdev_t dev, unsigned long b[], int size,
1477 + return brw_kiovec(rw, nr, iovec, dev, b, size);
1481 +static int _pv_get_number(vg_t * vg, kdev_t rdev, uint *pvn)
1484 - for(p = 0; p < vg->pv_max; p++) {
1485 - if(vg->pv[p] == NULL)
1486 + for (p = 0; p < vg->pv_max; p++) {
1487 + if (vg->pv[p] == NULL)
1490 - if(vg->pv[p]->pv_dev == rdev)
1491 + if (vg->pv[p]->pv_dev == rdev)
1496 - if(p >= vg->pv_max) {
1497 + if (p >= vg->pv_max) {
1498 /* bad news, the snapshot COW table is probably corrupt */
1500 "%s -- _pv_get_number failed for rdev = %u\n",
1506 #define hashfn(dev,block,mask,chunk_size) \
1507 ((HASHDEV(dev)^((block)/(chunk_size))) & (mask))
1509 @@ -129,10 +144,20 @@
1510 unsigned long mask = lv->lv_snapshot_hash_mask;
1511 int chunk_size = lv->lv_chunk_size;
1515 hash_table = &hash_table[hashfn(org_dev, org_start, mask, chunk_size)];
1516 list_add(&exception->hash, hash_table);
1520 + * Determine if we already have a snapshot chunk for this block.
1521 + * Return: 1 if it the chunk already exists
1522 + * 0 if we need to COW this block and allocate a new chunk
1523 + * -1 if the snapshot was disabled because it ran out of space
1525 + * We need to be holding at least a read lock on lv->lv_lock.
1527 int lvm_snapshot_remap_block(kdev_t * org_dev, unsigned long * org_sector,
1528 unsigned long pe_start, lv_t * lv)
1531 int chunk_size = lv->lv_chunk_size;
1532 lv_block_exception_t * exception;
1534 + if (!lv->lv_block_exception)
1537 pe_off = pe_start % chunk_size;
1538 pe_adjustment = (*org_sector-pe_off) % chunk_size;
1539 __org_start = *org_sector - pe_adjustment;
1541 or error on this snapshot --> release it */
1542 invalidate_buffers(lv_snap->lv_dev);
1544 - /* wipe the snapshot since it's inconsistent now */
1545 - _disable_snapshot(vg, lv_snap);
1546 + /* wipe the snapshot since it's inconsistent now */
1547 + _disable_snapshot(vg, lv_snap);
1549 for (i = last_dev = 0; i < lv_snap->lv_remap_ptr; i++) {
1550 if ( lv_snap->lv_block_exception[i].rdev_new != last_dev) {
1551 @@ -186,15 +214,15 @@
1554 static inline int lvm_snapshot_prepare_blocks(unsigned long *blocks,
1555 - unsigned long start,
1558 + unsigned long start,
1562 int i, sectors_per_block, nr_blocks;
1564 sectors_per_block = blocksize / SECTOR_SIZE;
1566 - if(start & (sectors_per_block - 1))
1567 + if (start & (sectors_per_block - 1))
1570 nr_blocks = nr_sectors / sectors_per_block;
1571 @@ -245,49 +273,51 @@
1573 int lvm_snapshot_fill_COW_page(vg_t * vg, lv_t * lv_snap)
1576 - int id = 0, is = lv_snap->lv_remap_ptr;
1577 - ulong blksize_snap;
1578 - lv_COW_table_disk_t * lv_COW_table = (lv_COW_table_disk_t *)
1579 - page_address(lv_snap->lv_COW_table_iobuf->maplist[0]);
1580 + int id = 0, is = lv_snap->lv_remap_ptr;
1581 + ulong blksize_snap;
1582 + lv_COW_table_disk_t * lv_COW_table = (lv_COW_table_disk_t *)
1583 + page_address(lv_snap->lv_COW_table_iobuf->maplist[0]);
1592 - lvm_get_blksize(lv_snap->lv_block_exception[is].rdev_new);
1593 - is -= is % (blksize_snap / sizeof(lv_COW_table_disk_t));
1595 + lvm_get_blksize(lv_snap->lv_block_exception[is].rdev_new);
1596 + is -= is % (blksize_snap / sizeof(lv_COW_table_disk_t));
1598 memset(lv_COW_table, 0, blksize_snap);
1599 for ( ; is < lv_snap->lv_remap_ptr; is++, id++) {
1600 /* store new COW_table entry */
1601 - lv_block_exception_t *be = lv_snap->lv_block_exception + is;
1602 - if(_pv_get_number(vg, be->rdev_org, &pvn))
1604 + lv_block_exception_t *be = lv_snap->lv_block_exception + is;
1607 - lv_COW_table[id].pv_org_number = cpu_to_le64(pvn);
1608 - lv_COW_table[id].pv_org_rsector = cpu_to_le64(be->rsector_org);
1609 - if(_pv_get_number(vg, be->rdev_new, &pvn))
1611 + if (_pv_get_number(vg, be->rdev_org, &pvn))
1614 - lv_COW_table[id].pv_snap_number = cpu_to_le64(pvn);
1615 - lv_COW_table[id].pv_snap_rsector =
1616 - cpu_to_le64(be->rsector_new);
1617 + lv_COW_table[id].pv_org_number = cpu_to_le64(pvn);
1618 + lv_COW_table[id].pv_org_rsector = cpu_to_le64(be->rsector_org);
1620 + if (_pv_get_number(vg, be->rdev_new, &pvn))
1623 + lv_COW_table[id].pv_snap_number = cpu_to_le64(pvn);
1624 + lv_COW_table[id].pv_snap_rsector = cpu_to_le64(be->rsector_new);
1631 - printk(KERN_ERR "%s -- lvm_snapshot_fill_COW_page failed", lvm_name);
1633 + printk(KERN_ERR "%s -- lvm_snapshot_fill_COW_page failed", lvm_name);
1639 * writes a COW exception table sector to disk (HM)
1641 + * We need to hold a write lock on lv_snap->lv_lock.
1644 int lvm_write_COW_table_block(vg_t * vg, lv_t *lv_snap)
1647 @@ -305,6 +335,10 @@
1648 * if there is no exception storage space free any longer --> release snapshot.
1650 * this routine gets called for each _first_ write to a physical chunk.
1652 + * We need to hold a write lock on lv_snap->lv_lock. It is assumed that
1653 + * lv->lv_block_exception is non-NULL (checked by lvm_snapshot_remap_block())
1654 + * when this function is called.
1656 int lvm_snapshot_COW(kdev_t org_phys_dev,
1657 unsigned long org_phys_sector,
1658 @@ -314,8 +348,10 @@
1660 const char * reason;
1661 unsigned long org_start, snap_start, snap_phys_dev, virt_start, pe_off;
1662 + unsigned long phys_start;
1663 int idx = lv_snap->lv_remap_ptr, chunk_size = lv_snap->lv_chunk_size;
1664 struct kiobuf * iobuf;
1665 + unsigned long blocks[KIO_MAX_SECTORS];
1666 int blksize_snap, blksize_org, min_blksize, max_blksize;
1667 int max_sectors, nr_sectors;
1671 iobuf = lv_snap->lv_iobuf;
1673 - blksize_org = lvm_get_blksize(org_phys_dev);
1674 - blksize_snap = lvm_get_blksize(snap_phys_dev);
1675 + blksize_org = lvm_sectsize(org_phys_dev);
1676 + blksize_snap = lvm_sectsize(snap_phys_dev);
1677 max_blksize = max(blksize_org, blksize_snap);
1678 min_blksize = min(blksize_org, blksize_snap);
1679 max_sectors = KIO_MAX_SECTORS * (min_blksize>>9);
1681 if (chunk_size % (max_blksize>>9))
1684 + /* Don't change org_start, we need it to fill in the exception table */
1685 + phys_start = org_start;
1689 nr_sectors = min(chunk_size, max_sectors);
1690 @@ -363,21 +402,24 @@
1692 iobuf->length = nr_sectors << 9;
1694 - if(!lvm_snapshot_prepare_blocks(iobuf->blocks, org_start,
1695 - nr_sectors, blksize_org))
1696 + if (!lvm_snapshot_prepare_blocks(blocks, phys_start,
1697 + nr_sectors, blksize_org))
1700 - if (brw_kiovec(READ, 1, &iobuf, org_phys_dev,
1701 - iobuf->blocks, blksize_org) != (nr_sectors<<9))
1702 + if (__brw_kiovec(READ, 1, &iobuf, org_phys_dev, blocks,
1703 + blksize_org, lv_snap) != (nr_sectors<<9))
1706 - if(!lvm_snapshot_prepare_blocks(iobuf->blocks, snap_start,
1707 - nr_sectors, blksize_snap))
1708 + if (!lvm_snapshot_prepare_blocks(blocks, snap_start,
1709 + nr_sectors, blksize_snap))
1712 - if (brw_kiovec(WRITE, 1, &iobuf, snap_phys_dev,
1713 - iobuf->blocks, blksize_snap) != (nr_sectors<<9))
1714 + if (__brw_kiovec(WRITE, 1, &iobuf, snap_phys_dev, blocks,
1715 + blksize_snap, lv_snap) != (nr_sectors<<9))
1716 goto fail_raw_write;
1718 + phys_start += nr_sectors;
1719 + snap_start += nr_sectors;
1722 #ifdef DEBUG_SNAPSHOT
1723 @@ -401,24 +443,24 @@
1729 lvm_drop_snapshot(vg, lv_snap, reason);
1732 - fail_out_of_space:
1734 reason = "out of space";
1738 reason = "read error";
1742 reason = "write error";
1746 reason = "blocksize error";
1751 reason = "couldn't prepare kiovec blocks "
1752 "(start probably isn't block aligned)";
1757 page = alloc_page(GFP_KERNEL);
1760 + if (!page) goto out;
1762 iobuf->maplist[i] = page;
1774 @@ -515,13 +557,12 @@
1775 if (ret) goto out_free_kiovec;
1777 ret = lvm_snapshot_alloc_iobuf_pages(lv_snap->lv_COW_table_iobuf,
1778 - PAGE_SIZE/SECTOR_SIZE);
1779 + PAGE_SIZE/SECTOR_SIZE);
1780 if (ret) goto out_free_both_kiovecs;
1782 ret = lvm_snapshot_alloc_hash_table(lv_snap);
1783 if (ret) goto out_free_both_kiovecs;
1790 unmap_kiobuf(lv_snap->lv_iobuf);
1791 free_kiovec(1, &lv_snap->lv_iobuf);
1792 lv_snap->lv_iobuf = NULL;
1793 - if (lv_snap->lv_snapshot_hash_table != NULL)
1794 - vfree(lv_snap->lv_snapshot_hash_table);
1795 + vfree(lv_snap->lv_snapshot_hash_table);
1796 lv_snap->lv_snapshot_hash_table = NULL;
1799 @@ -562,10 +602,10 @@
1801 if (lv->lv_COW_table_iobuf)
1803 - kiobuf_wait_for_io(lv->lv_COW_table_iobuf);
1804 - unmap_kiobuf(lv->lv_COW_table_iobuf);
1805 - free_kiovec(1, &lv->lv_COW_table_iobuf);
1806 - lv->lv_COW_table_iobuf = NULL;
1807 + kiobuf_wait_for_io(lv->lv_COW_table_iobuf);
1808 + unmap_kiobuf(lv->lv_COW_table_iobuf);
1809 + free_kiovec(1, &lv->lv_COW_table_iobuf);
1810 + lv->lv_COW_table_iobuf = NULL;
1814 @@ -577,11 +617,11 @@
1817 ulong snap_pe_start, COW_table_sector_offset,
1818 - COW_entries_per_pe, COW_chunks_per_pe, COW_entries_per_block;
1819 + COW_entries_per_pe, COW_chunks_per_pe, COW_entries_per_block;
1821 kdev_t snap_phys_dev;
1822 lv_block_exception_t *be;
1823 - struct kiobuf * COW_table_iobuf = lv_snap->lv_COW_table_iobuf;
1824 + struct kiobuf *COW_table_iobuf = lv_snap->lv_COW_table_iobuf;
1825 lv_COW_table_disk_t * lv_COW_table =
1826 ( lv_COW_table_disk_t *) page_address(lv_snap->lv_COW_table_iobuf->maplist[0]);
1828 @@ -592,46 +632,47 @@
1829 snap_phys_dev = lv_snap->lv_block_exception[idx].rdev_new;
1830 snap_pe_start = lv_snap->lv_block_exception[idx - (idx % COW_entries_per_pe)].rsector_new - lv_snap->lv_chunk_size;
1832 - blksize_snap = lvm_get_blksize(snap_phys_dev);
1833 + blksize_snap = lvm_sectsize(snap_phys_dev);
1835 COW_entries_per_block = blksize_snap / sizeof(lv_COW_table_disk_t);
1836 idx_COW_table = idx % COW_entries_per_pe % COW_entries_per_block;
1838 if ( idx_COW_table == 0) memset(lv_COW_table, 0, blksize_snap);
1840 - /* sector offset into the on disk COW table */
1841 + /* sector offset into the on disk COW table */
1842 COW_table_sector_offset = (idx % COW_entries_per_pe) / (SECTOR_SIZE / sizeof(lv_COW_table_disk_t));
1844 /* COW table block to write next */
1845 blocks[0] = (snap_pe_start + COW_table_sector_offset) >> (blksize_snap >> 10);
1847 /* store new COW_table entry */
1848 - be = lv_snap->lv_block_exception + idx;
1849 - if(_pv_get_number(vg, be->rdev_org, &pvn))
1850 - goto fail_pv_get_number;
1852 - lv_COW_table[idx_COW_table].pv_org_number = cpu_to_le64(pvn);
1853 - lv_COW_table[idx_COW_table].pv_org_rsector =
1854 - cpu_to_le64(be->rsector_org);
1855 - if(_pv_get_number(vg, snap_phys_dev, &pvn))
1856 - goto fail_pv_get_number;
1858 - lv_COW_table[idx_COW_table].pv_snap_number = cpu_to_le64(pvn);
1859 - lv_COW_table[idx_COW_table].pv_snap_rsector =
1860 - cpu_to_le64(be->rsector_new);
1861 + be = lv_snap->lv_block_exception + idx;
1862 + if(_pv_get_number(vg, be->rdev_org, &pvn))
1863 + goto fail_pv_get_number;
1865 + lv_COW_table[idx_COW_table].pv_org_number = cpu_to_le64(pvn);
1866 + lv_COW_table[idx_COW_table].pv_org_rsector =
1867 + cpu_to_le64(be->rsector_org);
1868 + if(_pv_get_number(vg, snap_phys_dev, &pvn))
1869 + goto fail_pv_get_number;
1871 + lv_COW_table[idx_COW_table].pv_snap_number = cpu_to_le64(pvn);
1872 + lv_COW_table[idx_COW_table].pv_snap_rsector =
1873 + cpu_to_le64(be->rsector_new);
1875 COW_table_iobuf->length = blksize_snap;
1876 + /* COW_table_iobuf->nr_pages = 1; */
1878 - if (brw_kiovec(WRITE, 1, &COW_table_iobuf, snap_phys_dev,
1879 - blocks, blksize_snap) != blksize_snap)
1880 + if (__brw_kiovec(WRITE, 1, &COW_table_iobuf, snap_phys_dev,
1881 + blocks, blksize_snap, lv_snap) != blksize_snap)
1882 goto fail_raw_write;
1884 - /* initialization of next COW exception table block with zeroes */
1885 + /* initialization of next COW exception table block with zeroes */
1886 end_of_table = idx % COW_entries_per_pe == COW_entries_per_pe - 1;
1887 if (idx_COW_table % COW_entries_per_block == COW_entries_per_block - 1 || end_of_table)
1889 /* don't go beyond the end */
1890 - if (idx + 1 >= lv_snap->lv_remap_end) goto out;
1891 + if (idx + 1 >= lv_snap->lv_remap_end) goto out;
1893 memset(lv_COW_table, 0, blksize_snap);
1895 @@ -640,24 +681,24 @@
1897 snap_phys_dev = lv_snap->lv_block_exception[idx].rdev_new;
1898 snap_pe_start = lv_snap->lv_block_exception[idx - (idx % COW_entries_per_pe)].rsector_new - lv_snap->lv_chunk_size;
1899 - blksize_snap = lvm_get_blksize(snap_phys_dev);
1900 + blksize_snap = lvm_sectsize(snap_phys_dev);
1901 blocks[0] = snap_pe_start >> (blksize_snap >> 10);
1904 - if (brw_kiovec(WRITE, 1, &COW_table_iobuf, snap_phys_dev,
1905 - blocks, blksize_snap) !=
1906 + if (__brw_kiovec(WRITE, 1, &COW_table_iobuf, snap_phys_dev,
1907 + blocks, blksize_snap, lv_snap) !=
1909 goto fail_raw_write;
1918 *reason = "write error";
1921 - fail_pv_get_number:
1922 +fail_pv_get_number:
1923 *reason = "_pv_get_number failed";
1931 -MODULE_LICENSE("GPL");
1932 --- linux/drivers/md/lvm-fs.c.orig Fri Dec 21 17:41:54 2001
1933 +++ linux/drivers/md/lvm-fs.c Thu Jan 10 12:24:08 2002
1936 * Copyright (C) 2001 Sistina Software
1938 - * January,February 2001
1939 + * January-April 2001
1941 * LVM driver is free software; you can redistribute it and/or modify
1942 * it under the terms of the GNU General Public License as published by
1944 * 04/10/2001 - corrected devfs_register() call in lvm_init_fs()
1945 * 11/04/2001 - don't devfs_register("lvm") as user-space always does it
1946 * 10/05/2001 - show more of PV name in /proc/lvm/global
1947 - * 16/12/2001 - fix devfs unregister order and prevent duplicate unreg (REG)
1951 #include <linux/config.h>
1952 #include <linux/version.h>
1953 -#include <linux/module.h>
1955 #include <linux/kernel.h>
1956 #include <linux/vmalloc.h>
1958 S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP,
1959 &lvm_chr_fops, NULL);
1962 lvm_proc_dir = create_proc_entry(LVM_DIR, S_IFDIR, &proc_root);
1964 lvm_proc_vg_subdir = create_proc_entry(LVM_VG_SUBDIR, S_IFDIR,
1967 devfs_unregister (lvm_devfs_handle);
1970 remove_proc_entry(LVM_GLOBAL, lvm_proc_dir);
1971 remove_proc_entry(LVM_VG_SUBDIR, lvm_proc_dir);
1972 remove_proc_entry(LVM_DIR, &proc_root);
1976 devfs_unregister(ch_devfs_handle[vg_ptr->vg_number]);
1977 - ch_devfs_handle[vg_ptr->vg_number] = NULL;
1978 + devfs_unregister(vg_devfs_handle[vg_ptr->vg_number]);
1981 for(i = 0; i < vg_ptr->lv_max; i++)
1982 @@ -149,10 +145,6 @@
1983 for(i = 0; i < vg_ptr->pv_max; i++)
1984 if(vg_ptr->pv[i]) lvm_fs_remove_pv(vg_ptr, vg_ptr->pv[i]);
1986 - /* must not remove directory before leaf nodes */
1987 - devfs_unregister(vg_devfs_handle[vg_ptr->vg_number]);
1988 - vg_devfs_handle[vg_ptr->vg_number] = NULL;
1990 if(vg_ptr->vg_dir_pde) {
1991 remove_proc_entry(LVM_LV_SUBDIR, vg_ptr->vg_dir_pde);
1992 vg_ptr->lv_subdir_pde = NULL;
1995 void lvm_fs_remove_lv(vg_t *vg_ptr, lv_t *lv) {
1996 devfs_unregister(lv_devfs_handle[MINOR(lv->lv_dev)]);
1997 - lv_devfs_handle[MINOR(lv->lv_dev)] = NULL;
1999 if(vg_ptr->lv_subdir_pde) {
2000 const char *name = _basename(lv->lv_name);
2001 @@ -282,12 +273,12 @@
2002 sz += sprintf(page + sz, "number: %u\n", lv->lv_number);
2003 sz += sprintf(page + sz, "open: %u\n", lv->lv_open);
2004 sz += sprintf(page + sz, "allocation: %u\n", lv->lv_allocation);
2005 - if(lv->lv_stripes > 1) {
2006 - sz += sprintf(page + sz, "stripes: %u\n",
2008 - sz += sprintf(page + sz, "stripesize: %u\n",
2009 - lv->lv_stripesize);
2011 + if(lv->lv_stripes > 1) {
2012 + sz += sprintf(page + sz, "stripes: %u\n",
2014 + sz += sprintf(page + sz, "stripesize: %u\n",
2015 + lv->lv_stripesize);
2017 sz += sprintf(page + sz, "device: %02u:%02u\n",
2018 MAJOR(lv->lv_dev), MINOR(lv->lv_dev));
2024 -MODULE_LICENSE("GPL");