]> git.pld-linux.org Git - packages/kernel.git/blame - linux-2.4.7-lvm-1.0.1rc4cvs.patch
- obsolete
[packages/kernel.git] / linux-2.4.7-lvm-1.0.1rc4cvs.patch
CommitLineData
8419f150
AM
1--- linux/include/linux/lvm.h.orig Sat Oct 20 20:50:33 2001
2+++ linux/include/linux/lvm.h Sat Oct 20 20:55:23 2001
3@@ -9,7 +9,7 @@
4 * May-July 1998
5 * January-March,July,September,October,Dezember 1999
6 * January,February,July,November 2000
7- * January-March 2001
8+ * January-March,June,July 2001
9 *
10 * lvm is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12@@ -67,6 +67,10 @@
13 * 01/03/2001 - Revert to IOP10 and add VG_CREATE_OLD call for compatibility
14 * 08/03/2001 - new lv_t (in core) version number 5: changed page member
15 * to (struct kiobuf *) to use for COW exception table io
16+ * 26/03/2001 - changed lv_v4 to lv_v5 in structure definition (HM)
17+ * 21/06/2001 - changed BLOCK_SIZE back to 1024 for non S/390
18+ * 22/06/2001 - added Andreas Dilger's PE on 4k boundary alignment enhancements
19+ * 19/07/2001 - added rwsem compatibility macros for 2.2 kernels
20 *
21 */
22
23@@ -74,8 +78,8 @@
24 #ifndef _LVM_H_INCLUDE
25 #define _LVM_H_INCLUDE
26
27-#define LVM_RELEASE_NAME "0.9.1_beta6"
28-#define LVM_RELEASE_DATE "12/03/2001"
29+#define LVM_RELEASE_NAME "1.0.1-rc4"
30+#define LVM_RELEASE_DATE "03/10/2001"
31
32 #define _LVM_KERNEL_H_VERSION "LVM "LVM_RELEASE_NAME" ("LVM_RELEASE_DATE")"
33
34@@ -102,16 +106,14 @@
35 #define DEBUG_DEVICE
36 #define DEBUG_KFREE
37 */
38-#endif /* #ifdef __KERNEL__ */
39
40-#ifndef __KERNEL__
41-#define __KERNEL__
42 #include <linux/kdev_t.h>
43 #include <linux/list.h>
44-#undef __KERNEL__
45 #else
46+#define __KERNEL__
47 #include <linux/kdev_t.h>
48 #include <linux/list.h>
49+#undef __KERNEL__
50 #endif /* #ifndef __KERNEL__ */
51
52 #include <asm/types.h>
53@@ -123,6 +125,7 @@
54 #include <asm/semaphore.h>
55 #endif /* #ifdef __KERNEL__ */
56
57+
58 #include <asm/page.h>
59
60 #if !defined ( LVM_BLK_MAJOR) || !defined ( LVM_CHAR_MAJOR)
61@@ -136,38 +139,18 @@
62 #ifdef CONFIG_ARCH_S390
63 #define BLOCK_SIZE 4096
64 #else
65-#define BLOCK_SIZE 512
66+#define BLOCK_SIZE 1024
67 #endif
68
69 #ifndef SECTOR_SIZE
70 #define SECTOR_SIZE 512
71 #endif
72
73-#define LVM_STRUCT_VERSION 1 /* structure version */
74+/* structure version */
75+#define LVM_STRUCT_VERSION 1
76
77 #define LVM_DIR_PREFIX "/dev/"
78
79-#ifndef min
80-#define min(a,b) (((a)<(b))?(a):(b))
81-#endif
82-#ifndef max
83-#define max(a,b) (((a)>(b))?(a):(b))
84-#endif
85-
86-/* set the default structure version */
87-#if ( LVM_STRUCT_VERSION == 1)
88-#define pv_t pv_v2_t
89-#define lv_t lv_v5_t
90-#define vg_t vg_v3_t
91-#define pv_disk_t pv_disk_v2_t
92-#define lv_disk_t lv_disk_v3_t
93-#define vg_disk_t vg_disk_v2_t
94-#define lv_block_exception_t lv_block_exception_v1_t
95-#define lv_COW_table_disk_t lv_COW_table_disk_v1_t
96-#endif
97-
98-
99-
100 /*
101 * i/o protocol version
102 *
103@@ -241,40 +224,11 @@
104 */
105
106 /* DONT TOUCH THESE !!! */
107-/* base of PV structure in disk partition */
108-#define LVM_PV_DISK_BASE 0L
109
110-/* size reserved for PV structure on disk */
111-#define LVM_PV_DISK_SIZE 1024L
112
113-/* base of VG structure in disk partition */
114-#define LVM_VG_DISK_BASE LVM_PV_DISK_SIZE
115
116-/* size reserved for VG structure */
117-#define LVM_VG_DISK_SIZE ( 9 * 512L)
118-
119-/* size reserved for timekeeping */
120-#define LVM_TIMESTAMP_DISK_BASE ( LVM_VG_DISK_BASE + LVM_VG_DISK_SIZE)
121-#define LVM_TIMESTAMP_DISK_SIZE 512L /* reserved for timekeeping */
122-
123-/* name list of physical volumes on disk */
124-#define LVM_PV_UUIDLIST_DISK_BASE ( LVM_TIMESTAMP_DISK_BASE + \
125- LVM_TIMESTAMP_DISK_SIZE)
126-
127-/* now for the dynamically calculated parts of the VGDA */
128-#define LVM_LV_DISK_OFFSET(a, b) ( (a)->lv_on_disk.base + \
129- sizeof ( lv_disk_t) * b)
130-#define LVM_DISK_SIZE(pv) ( (pv)->pe_on_disk.base + \
131- (pv)->pe_on_disk.size)
132-#define LVM_PE_DISK_OFFSET(pe, pv) ( pe * pv->pe_size + \
133- ( LVM_DISK_SIZE ( pv) / SECTOR_SIZE))
134-#define LVM_PE_ON_DISK_BASE(pv) \
135- { int rest; \
136- pv->pe_on_disk.base = pv->lv_on_disk.base + pv->lv_on_disk.size; \
137- if ( ( rest = pv->pe_on_disk.base % SECTOR_SIZE) != 0) \
138- pv->pe_on_disk.base += ( SECTOR_SIZE - rest); \
139- }
140-/* END default disk spaces and offsets for PVs */
141+
142+
143
144
145 /*
146@@ -318,25 +272,12 @@
147 #define LVM_SNAPSHOT_MIN_CHUNK (PAGE_SIZE/1024) /* 4 or 8 KB */
148
149 #define UNDEF -1
150-#define FALSE 0
151-#define TRUE 1
152-
153-
154-#define LVM_GET_COW_TABLE_CHUNKS_PER_PE(vg, lv) ( \
155- vg->pe_size / lv->lv_chunk_size)
156-
157-#define LVM_GET_COW_TABLE_ENTRIES_PER_PE(vg, lv) ( \
158-{ \
159- int COW_table_entries_per_PE; \
160- int COW_table_chunks_per_PE; \
161-\
162- COW_table_entries_per_PE = LVM_GET_COW_TABLE_CHUNKS_PER_PE(vg, lv); \
163- COW_table_chunks_per_PE = ( COW_table_entries_per_PE * sizeof(lv_COW_table_disk_t) / SECTOR_SIZE + lv->lv_chunk_size - 1) / lv->lv_chunk_size; \
164- COW_table_entries_per_PE - COW_table_chunks_per_PE;})
165-
166
167 /*
168 * ioctls
169+ * FIXME: the last parameter to _IO{W,R,WR} is a data type. The macro will
170+ * expand this using sizeof(), so putting "1" there is misleading
171+ * because sizeof(1) = sizeof(int) = sizeof(2) = 4 on a 32-bit machine!
172 */
173 /* volume group */
174 #define VG_CREATE_OLD _IOW ( 0xfe, 0x00, 1)
175@@ -400,7 +341,12 @@
176 #endif
177
178 /* lock the logical volume manager */
179+#if LVM_DRIVER_IOP_VERSION > 11
180+#define LVM_LOCK_LVM _IO ( 0xfe, 0x9A)
181+#else
182+/* This is actually the same as _IO ( 0xff, 0x00), oops. Remove for IOP 12+ */
183 #define LVM_LOCK_LVM _IO ( 0xfe, 0x100)
184+#endif
185 /* END ioctls */
186
187
188@@ -451,21 +397,21 @@
189 #define UUID_LEN 32 /* don't change!!! */
190
191 /* copy on write tables in disk format */
192-typedef struct {
193+typedef struct lv_COW_table_disk_v1 {
194 uint64_t pv_org_number;
195 uint64_t pv_org_rsector;
196 uint64_t pv_snap_number;
197 uint64_t pv_snap_rsector;
198-} lv_COW_table_disk_v1_t;
199+} lv_COW_table_disk_t;
200
201 /* remap physical sector/rdev pairs including hash */
202-typedef struct {
203+typedef struct lv_block_exception_v1 {
204 struct list_head hash;
205 uint32_t rsector_org;
206 kdev_t rdev_org;
207 uint32_t rsector_new;
208 kdev_t rdev_new;
209-} lv_block_exception_v1_t;
210+} lv_block_exception_t;
211
212 /* disk stored pe information */
213 typedef struct {
214@@ -481,37 +427,11 @@
215
216
217 /*
218- * Structure Physical Volume (PV) Version 1
219+ * physical volume structures
220 */
221
222 /* core */
223-typedef struct {
224- char id[2]; /* Identifier */
225- unsigned short version; /* HM lvm version */
226- lvm_disk_data_t pv_on_disk;
227- lvm_disk_data_t vg_on_disk;
228- lvm_disk_data_t pv_namelist_on_disk;
229- lvm_disk_data_t lv_on_disk;
230- lvm_disk_data_t pe_on_disk;
231- char pv_name[NAME_LEN];
232- char vg_name[NAME_LEN];
233- char system_id[NAME_LEN]; /* for vgexport/vgimport */
234- kdev_t pv_dev;
235- uint pv_number;
236- uint pv_status;
237- uint pv_allocatable;
238- uint pv_size; /* HM */
239- uint lv_cur;
240- uint pe_size;
241- uint pe_total;
242- uint pe_allocated;
243- uint pe_stale; /* for future use */
244- pe_disk_t *pe; /* HM */
245- struct inode *inode; /* HM */
246-} pv_v1_t;
247-
248-/* core */
249-typedef struct {
250+typedef struct pv_v2 {
251 char id[2]; /* Identifier */
252 unsigned short version; /* HM lvm version */
253 lvm_disk_data_t pv_on_disk;
254@@ -533,36 +453,17 @@
255 uint pe_allocated;
256 uint pe_stale; /* for future use */
257 pe_disk_t *pe; /* HM */
258- struct inode *inode; /* HM */
259+ struct block_device *bd;
260 char pv_uuid[UUID_LEN+1];
261-} pv_v2_t;
262
263+#ifndef __KERNEL__
264+ uint32_t pe_start; /* in sectors */
265+#endif
266+} pv_t;
267
268-/* disk */
269-typedef struct {
270- uint8_t id[2]; /* Identifier */
271- uint16_t version; /* HM lvm version */
272- lvm_disk_data_t pv_on_disk;
273- lvm_disk_data_t vg_on_disk;
274- lvm_disk_data_t pv_namelist_on_disk;
275- lvm_disk_data_t lv_on_disk;
276- lvm_disk_data_t pe_on_disk;
277- uint8_t pv_name[NAME_LEN];
278- uint8_t vg_name[NAME_LEN];
279- uint8_t system_id[NAME_LEN]; /* for vgexport/vgimport */
280- uint32_t pv_major;
281- uint32_t pv_number;
282- uint32_t pv_status;
283- uint32_t pv_allocatable;
284- uint32_t pv_size; /* HM */
285- uint32_t lv_cur;
286- uint32_t pe_size;
287- uint32_t pe_total;
288- uint32_t pe_allocated;
289-} pv_disk_v1_t;
290
291 /* disk */
292-typedef struct {
293+typedef struct pv_disk_v2 {
294 uint8_t id[2]; /* Identifier */
295 uint16_t version; /* HM lvm version */
296 lvm_disk_data_t pv_on_disk;
297@@ -582,7 +483,11 @@
298 uint32_t pe_size;
299 uint32_t pe_total;
300 uint32_t pe_allocated;
301-} pv_disk_v2_t;
302+
303+ /* new in struct version 2 */
304+ uint32_t pe_start; /* in sectors */
305+
306+} pv_disk_t;
307
308
309 /*
310@@ -606,7 +511,7 @@
311 } le_remap_req_t;
312
313 typedef struct lv_bmap {
314- ulong lv_block;
315+ uint32_t lv_block;
316 dev_t lv_dev;
317 } lv_bmap_t;
318
319@@ -615,7 +520,7 @@
320 */
321
322 /* core */
323-typedef struct lv_v4 {
324+typedef struct lv_v5 {
325 char lv_name[NAME_LEN];
326 char vg_name[NAME_LEN];
327 uint lv_access;
328@@ -638,9 +543,9 @@
329 uint lv_read_ahead;
330
331 /* delta to version 1 starts here */
332- struct lv_v4 *lv_snapshot_org;
333- struct lv_v4 *lv_snapshot_prev;
334- struct lv_v4 *lv_snapshot_next;
335+ struct lv_v5 *lv_snapshot_org;
336+ struct lv_v5 *lv_snapshot_prev;
337+ struct lv_v5 *lv_snapshot_next;
338 lv_block_exception_t *lv_block_exception;
339 uint lv_remap_ptr;
340 uint lv_remap_end;
341@@ -649,22 +554,22 @@
342 #ifdef __KERNEL__
343 struct kiobuf *lv_iobuf;
344 struct kiobuf *lv_COW_table_iobuf;
345- struct semaphore lv_snapshot_sem;
346+ struct rw_semaphore lv_lock;
347 struct list_head *lv_snapshot_hash_table;
348 uint32_t lv_snapshot_hash_table_size;
349 uint32_t lv_snapshot_hash_mask;
350 wait_queue_head_t lv_snapshot_wait;
351 int lv_snapshot_use_rate;
352- void *vg;
353+ struct vg_v3 *vg;
354
355 uint lv_allocated_snapshot_le;
356 #else
357 char dummy[200];
358 #endif
359-} lv_v5_t;
360+} lv_t;
361
362 /* disk */
363-typedef struct {
364+typedef struct lv_disk_v3 {
365 uint8_t lv_name[NAME_LEN];
366 uint8_t vg_name[NAME_LEN];
367 uint32_t lv_access;
368@@ -686,36 +591,14 @@
369 uint32_t lv_allocation;
370 uint32_t lv_io_timeout; /* for future use */
371 uint32_t lv_read_ahead; /* HM */
372-} lv_disk_v3_t;
373+} lv_disk_t;
374
375 /*
376 * Structure Volume Group (VG) Version 1
377 */
378
379 /* core */
380-typedef struct {
381- char vg_name[NAME_LEN]; /* volume group name */
382- uint vg_number; /* volume group number */
383- uint vg_access; /* read/write */
384- uint vg_status; /* active or not */
385- uint lv_max; /* maximum logical volumes */
386- uint lv_cur; /* current logical volumes */
387- uint lv_open; /* open logical volumes */
388- uint pv_max; /* maximum physical volumes */
389- uint pv_cur; /* current physical volumes FU */
390- uint pv_act; /* active physical volumes */
391- uint dummy; /* was obsolete max_pe_per_pv */
392- uint vgda; /* volume group descriptor arrays FU */
393- uint pe_size; /* physical extent size in sectors */
394- uint pe_total; /* total of physical extents */
395- uint pe_allocated; /* allocated physical extents */
396- uint pvg_total; /* physical volume groups FU */
397- struct proc_dir_entry *proc;
398- pv_t *pv[ABS_MAX_PV + 1]; /* physical volume struct pointers */
399- lv_t *lv[ABS_MAX_LV + 1]; /* logical volume struct pointers */
400-} vg_v1_t;
401-
402-typedef struct {
403+typedef struct vg_v3 {
404 char vg_name[NAME_LEN]; /* volume group name */
405 uint vg_number; /* volume group number */
406 uint vg_access; /* read/write */
407@@ -743,30 +626,11 @@
408 #else
409 char dummy1[200];
410 #endif
411-} vg_v3_t;
412+} vg_t;
413
414
415 /* disk */
416-typedef struct {
417- uint8_t vg_name[NAME_LEN]; /* volume group name */
418- uint32_t vg_number; /* volume group number */
419- uint32_t vg_access; /* read/write */
420- uint32_t vg_status; /* active or not */
421- uint32_t lv_max; /* maximum logical volumes */
422- uint32_t lv_cur; /* current logical volumes */
423- uint32_t lv_open; /* open logical volumes */
424- uint32_t pv_max; /* maximum physical volumes */
425- uint32_t pv_cur; /* current physical volumes FU */
426- uint32_t pv_act; /* active physical volumes */
427- uint32_t dummy;
428- uint32_t vgda; /* volume group descriptor arrays FU */
429- uint32_t pe_size; /* physical extent size in sectors */
430- uint32_t pe_total; /* total of physical extents */
431- uint32_t pe_allocated; /* allocated physical extents */
432- uint32_t pvg_total; /* physical volume groups FU */
433-} vg_disk_v1_t;
434-
435-typedef struct {
436+typedef struct vg_disk_v2 {
437 uint8_t vg_uuid[UUID_LEN]; /* volume group UUID */
438 uint8_t vg_name_dummy[NAME_LEN-UUID_LEN]; /* rest of v1 VG name */
439 uint32_t vg_number; /* volume group number */
440@@ -784,7 +648,7 @@
441 uint32_t pe_total; /* total of physical extents */
442 uint32_t pe_allocated; /* allocated physical extents */
443 uint32_t pvg_total; /* physical volume groups FU */
444-} vg_disk_v2_t;
445+} vg_disk_t;
446
447
448 /*
449@@ -844,4 +708,41 @@
450 int rate;
451 } lv_snapshot_use_rate_req_t;
452
453+
454+
455+/* useful inlines */
456+static inline ulong round_up(ulong n, ulong size) {
457+ size--;
458+ return (n + size) & ~size;
459+}
460+
461+static inline ulong div_up(ulong n, ulong size) {
462+ return round_up(n, size) / size;
463+}
464+
465+/* FIXME: nasty capital letters */
466+static int inline LVM_GET_COW_TABLE_CHUNKS_PER_PE(vg_t *vg, lv_t *lv) {
467+ return vg->pe_size / lv->lv_chunk_size;
468+}
469+
470+static int inline LVM_GET_COW_TABLE_ENTRIES_PER_PE(vg_t *vg, lv_t *lv) {
471+ ulong chunks = vg->pe_size / lv->lv_chunk_size;
472+ ulong entry_size = sizeof(lv_COW_table_disk_t);
473+ ulong chunk_size = lv->lv_chunk_size * SECTOR_SIZE;
474+ ulong entries = (vg->pe_size * SECTOR_SIZE) /
475+ (entry_size + chunk_size);
476+
477+ if(chunks < 2)
478+ return 0;
479+
480+ for(; entries; entries--)
481+ if((div_up(entries * entry_size, chunk_size) + entries) <=
482+ chunks)
483+ break;
484+
485+ return entries;
486+}
487+
488+
489 #endif /* #ifndef _LVM_H_INCLUDE */
490+
491--- linux/drivers/md/lvm.c.orig Sat Oct 20 20:50:29 2001
492+++ linux/drivers/md/lvm.c Sat Oct 20 20:36:55 2001
493@@ -7,7 +7,7 @@
494 * April-May,July-August,November 1998
495 * January-March,May,July,September,October 1999
496 * January,February,July,September-November 2000
497- * January,February,March 2001
498+ * January-April 2001
499 *
500 *
501 * LVM driver is free software; you can redistribute it and/or modify
502@@ -73,7 +73,7 @@
503 * only other update ioctls are blocked now
504 * - fixed pv->pe to NULL for pv_status
505 * - using lv_req structure in lvm_chr_ioctl() now
506- * - fixed NULL ptr reference bug in lvm_do_lv_extendreduce()
507+ * - fixed NULL ptr reference bug in lvm_do_lv_extend_reduce()
508 * caused by uncontiguous PV array in lvm_chr_ioctl(VG_REDUCE)
509 * 09/02/1999 - changed BLKRASET and BLKRAGET in lvm_chr_ioctl() to
510 * handle lgoical volume private read ahead sector
511@@ -194,11 +194,25 @@
512 * - factored lvm_do_pv_flush out of lvm_chr_ioctl (HM)
513 * 09/03/2001 - Added _lock_open_count to ensure we only drop the lock
514 * when the locking process closes.
515- * 05/04/2001 - lvm_map bugs: don't use b_blocknr/b_dev in lvm_map, it
516- * destroys stacking devices. call b_end_io on failed maps.
517- * (Jens Axboe)
518- * 30/04/2001 - replace get_hardblock_size() with get_hardsect_size() for
519- * 2.4.4 kernel.
520+ * 05/04/2001 - Defer writes to an extent that is being moved [JT]
521+ * 05/04/2001 - use b_rdev and b_rsector rather than b_dev and b_blocknr in
522+ * lvm_map() in order to make stacking devices more happy (HM)
523+ * 11/04/2001 - cleaned up the pvmove queue code. I no longer retain the
524+ * rw flag, instead WRITEA's are just dropped [JT]
525+ * 30/04/2001 - added KERNEL_VERSION > 2.4.3 get_hardsect_size() rather
526+ * than get_hardblocksize() call
527+ * 03/05/2001 - Use copy_to/from_user to preserve pointers in
528+ * lvm_do_status_by*
529+ * 11/05/2001 - avoid accesses to inactive snapshot data in
530+ * __update_hardsectsize() and lvm_do_lv_extend_reduce() (JW)
531+ * 28/05/2001 - implemented missing BLKSSZGET ioctl
532+ * 05/06/2001 - Move _pe_lock out of fast path for lvm_map when no PEs
533+ * locked. Make buffer queue flush not need locking.
534+ * Fix lvm_user_bmap() to set b_rsector for new lvm_map(). [AED]
535+ * 30/06/2001 - Speed up __update_hardsectsize() by checking if PVs have
536+ * the same hardsectsize (very likely) before scanning all LEs
537+ * in the LV each time. [AED]
538+ * 12/10/2001 - Use add/del_gendisk() routines in 2.4.10+
539 *
540 */
541
542@@ -228,6 +242,7 @@
543 #include <linux/locks.h>
544
545
546+#include <linux/devfs_fs_kernel.h>
547 #include <linux/smp_lock.h>
548 #include <asm/ioctl.h>
549 #include <asm/segment.h>
550@@ -312,6 +327,15 @@
551 static void __update_hardsectsize(lv_t *lv);
552
553
554+static void _queue_io(struct buffer_head *bh, int rw);
555+static struct buffer_head *_dequeue_io(void);
556+static void _flush_io(struct buffer_head *bh);
557+
558+static int _open_pv(pv_t *pv);
559+static void _close_pv(pv_t *pv);
560+
561+static unsigned long _sectors_to_k(unsigned long sect);
562+
563 #ifdef LVM_HD_NAME
564 void lvm_hd_name(char *, int);
565 #endif
566@@ -319,9 +343,7 @@
567
568
569 /* variables */
570-char *lvm_version = "LVM version "LVM_RELEASE_NAME" by Heinz Mauelshagen "
571- "("LVM_RELEASE_DATE")\n";
572-char *lvm_short_version = "version "LVM_RELEASE_NAME" ("LVM_RELEASE_DATE")";
573+char *lvm_version = "LVM version "LVM_RELEASE_NAME"("LVM_RELEASE_DATE")";
574 ushort lvm_iop_version = LVM_DRIVER_IOP_VERSION;
575 int loadtime = 0;
576 const char *const lvm_name = LVM_NAME;
577@@ -330,11 +352,6 @@
578 /* volume group descriptor area pointers */
579 vg_t *vg[ABS_MAX_VG];
580
581-static pv_t *pvp = NULL;
582-static lv_t *lvp = NULL;
583-static pe_t *pep = NULL;
584-
585-
586 /* map from block minor number to VG and LV numbers */
587 typedef struct {
588 int vg_number;
589@@ -346,7 +363,7 @@
590 /* Request structures (lvm_chr_ioctl()) */
591 static pv_change_req_t pv_change_req;
592 static pv_status_req_t pv_status_req;
593-static pe_lock_req_t pe_lock_req;
594+volatile static pe_lock_req_t pe_lock_req;
595 static le_remap_req_t le_remap_req;
596 static lv_req_t lv_req;
597
598@@ -361,11 +378,14 @@
599 static uint vg_count = 0;
600 static long lvm_chr_open_count = 0;
601 static DECLARE_WAIT_QUEUE_HEAD(lvm_wait);
602-static DECLARE_WAIT_QUEUE_HEAD(lvm_map_wait);
603
604 static spinlock_t lvm_lock = SPIN_LOCK_UNLOCKED;
605 static spinlock_t lvm_snapshot_lock = SPIN_LOCK_UNLOCKED;
606
607+static struct buffer_head *_pe_requests;
608+static DECLARE_RWSEM(_pe_lock);
609+
610+
611 struct file_operations lvm_chr_fops = {
612 open: lvm_chr_open,
613 release: lvm_chr_close,
614@@ -375,7 +395,7 @@
615 /* block device operations structure needed for 2.3.38? and above */
616 struct block_device_operations lvm_blk_dops =
617 {
618- open: lvm_blk_open,
619+ open: lvm_blk_open,
620 release: lvm_blk_close,
621 ioctl: lvm_blk_ioctl,
622 };
623@@ -402,22 +422,58 @@
624 NULL, /* pointer to next gendisk struct (internal) */
625 };
626
627+static void add_gendisk(struct gendisk *gp)
628+{
629+ struct gendisk *gendisk_ptr = NULL;
630+
631+ if (gendisk_head != NULL) {
632+ gendisk_ptr = gendisk_head;
633+ while (gendisk_ptr->next != NULL &&
634+ gendisk_ptr->major > lvm_gendisk.major) {
635+ gendisk_ptr = gendisk_ptr->next;
636+ }
637+ lvm_gendisk.next = gendisk_ptr->next;
638+ gendisk_ptr->next = &lvm_gendisk;
639+ } else {
640+ gendisk_head = &lvm_gendisk;
641+ lvm_gendisk.next = NULL;
642+ }
643+}
644+
645+static void del_gendisk(struct gendisk *gp)
646+{
647+ struct gendisk *gendisk_ptr = NULL, *gendisk_ptr_prev = NULL;
648+
649+ gendisk_ptr = gendisk_ptr_prev = gendisk_head;
650+ while (gendisk_ptr != NULL) {
651+ if (gendisk_ptr == &lvm_gendisk)
652+ break;
653+ gendisk_ptr_prev = gendisk_ptr;
654+ gendisk_ptr = gendisk_ptr->next;
655+ }
656+
657+ if (gendisk_ptr == &lvm_gendisk)
658+ gendisk_ptr_prev->next = gendisk_ptr->next;
659+}
660+
661 /*
662 * Driver initialization...
663 */
664 int lvm_init(void)
665 {
666- struct gendisk *gendisk_ptr = NULL;
667-
668- if (register_chrdev(LVM_CHAR_MAJOR, lvm_name, &lvm_chr_fops) < 0) {
669- printk(KERN_ERR "%s -- register_chrdev failed\n", lvm_name);
670+ if (devfs_register_chrdev(LVM_CHAR_MAJOR,
671+ lvm_name, &lvm_chr_fops) < 0) {
672+ printk(KERN_ERR "%s -- devfs_register_chrdev failed\n",
673+ lvm_name);
674 return -EIO;
675 }
676- if (register_blkdev(MAJOR_NR, lvm_name, &lvm_blk_dops) < 0)
677+ if (devfs_register_blkdev(MAJOR_NR, lvm_name, &lvm_blk_dops) < 0)
678 {
679- printk("%s -- register_blkdev failed\n", lvm_name);
680- if (unregister_chrdev(LVM_CHAR_MAJOR, lvm_name) < 0)
681- printk(KERN_ERR "%s -- unregister_chrdev failed\n", lvm_name);
682+ printk("%s -- devfs_register_blkdev failed\n", lvm_name);
683+ if (devfs_unregister_chrdev(LVM_CHAR_MAJOR, lvm_name) < 0)
684+ printk(KERN_ERR
685+ "%s -- devfs_unregister_chrdev failed\n",
686+ lvm_name);
687 return -EIO;
688 }
689
690@@ -426,18 +482,7 @@
691 lvm_geninit(&lvm_gendisk);
692
693 /* insert our gendisk at the corresponding major */
694- if (gendisk_head != NULL) {
695- gendisk_ptr = gendisk_head;
696- while (gendisk_ptr->next != NULL &&
697- gendisk_ptr->major > lvm_gendisk.major) {
698- gendisk_ptr = gendisk_ptr->next;
699- }
700- lvm_gendisk.next = gendisk_ptr->next;
701- gendisk_ptr->next = &lvm_gendisk;
702- } else {
703- gendisk_head = &lvm_gendisk;
704- lvm_gendisk.next = NULL;
705- }
706+ add_gendisk(&lvm_gendisk);
707
708 #ifdef LVM_HD_NAME
709 /* reference from drivers/block/genhd.c */
710@@ -447,20 +492,19 @@
711 blk_queue_make_request(BLK_DEFAULT_QUEUE(MAJOR_NR), lvm_make_request_fn);
712
713
714+ /* initialise the pe lock */
715+ pe_lock_req.lock = UNLOCK_PE;
716+
717 /* optional read root VGDA */
718 /*
719 if ( *rootvg != 0) vg_read_with_pv_and_lv ( rootvg, &vg);
720 */
721
722- printk(KERN_INFO
723- "%s%s -- "
724 #ifdef MODULE
725- "Module"
726+ printk(KERN_INFO "%s module loaded\n", lvm_version);
727 #else
728- "Driver"
729+ printk(KERN_INFO "%s\n", lvm_version);
730 #endif
731- " successfully initialized\n",
732- lvm_version, lvm_name);
733
734 return 0;
735 } /* lvm_init() */
736@@ -471,27 +515,17 @@
737
738 static void lvm_cleanup(void)
739 {
740- struct gendisk *gendisk_ptr = NULL, *gendisk_ptr_prev = NULL;
741-
742- if (unregister_chrdev(LVM_CHAR_MAJOR, lvm_name) < 0) {
743- printk(KERN_ERR "%s -- unregister_chrdev failed\n", lvm_name);
744- }
745- if (unregister_blkdev(MAJOR_NR, lvm_name) < 0) {
746- printk(KERN_ERR "%s -- unregister_blkdev failed\n", lvm_name);
747- }
748+ if (devfs_unregister_chrdev(LVM_CHAR_MAJOR, lvm_name) < 0)
749+ printk(KERN_ERR "%s -- devfs_unregister_chrdev failed\n",
750+ lvm_name);
751+ if (devfs_unregister_blkdev(MAJOR_NR, lvm_name) < 0)
752+ printk(KERN_ERR "%s -- devfs_unregister_blkdev failed\n",
753+ lvm_name);
754
755
756
757- gendisk_ptr = gendisk_ptr_prev = gendisk_head;
758- while (gendisk_ptr != NULL) {
759- if (gendisk_ptr == &lvm_gendisk)
760- break;
761- gendisk_ptr_prev = gendisk_ptr;
762- gendisk_ptr = gendisk_ptr->next;
763- }
764 /* delete our gendisk from chain */
765- if (gendisk_ptr == &lvm_gendisk)
766- gendisk_ptr_prev->next = gendisk_ptr->next;
767+ del_gendisk(&lvm_gendisk);
768
769 blk_size[MAJOR_NR] = NULL;
770 blksize_size[MAJOR_NR] = NULL;
771@@ -505,7 +539,9 @@
772 /* unregister with procfs and devfs */
773 lvm_fin_fs();
774
775+#ifdef MODULE
776 printk(KERN_INFO "%s -- Module successfully deactivated\n", lvm_name);
777+#endif
778
779 return;
780 } /* lvm_cleanup() */
781@@ -522,8 +558,8 @@
782 lvm_lock = lvm_snapshot_lock = SPIN_LOCK_UNLOCKED;
783
784 pe_lock_req.lock = UNLOCK_PE;
785- pe_lock_req.data.lv_dev = \
786- pe_lock_req.data.pv_dev = \
787+ pe_lock_req.data.lv_dev = 0;
788+ pe_lock_req.data.pv_dev = 0;
789 pe_lock_req.data.pv_offset = 0;
790
791 /* Initialize VG pointers */
792@@ -546,6 +582,9 @@
793 *
794 ********************************************************************/
795
796+#define MODE_TO_STR(mode) (mode) & FMODE_READ ? "READ" : "", \
797+ (mode) & FMODE_WRITE ? "WRITE" : ""
798+
799 /*
800 * character device open routine
801 */
802@@ -553,8 +592,8 @@
803 {
804 int minor = MINOR(inode->i_rdev);
805
806- P_DEV("%s -- lvm_chr_open MINOR: %d VG#: %d mode: 0x%X lock: %d\n",
807- lvm_name, minor, VG_CHR(minor), file->f_mode, lock);
808+ P_DEV("chr_open MINOR: %d VG#: %d mode: %s%s lock: %d\n",
809+ minor, VG_CHR(minor), MODE_TO_STR(file->f_mode), lock);
810
811 /* super user validation */
812 if (!capable(CAP_SYS_ADMIN)) return -EACCES;
813@@ -594,9 +633,8 @@
814 /* otherwise cc will complain about unused variables */
815 (void) lvm_lock;
816
817- P_IOCTL("%s -- lvm_chr_ioctl: command: 0x%X MINOR: %d "
818- "VG#: %d mode: 0x%X\n",
819- lvm_name, command, minor, VG_CHR(minor), file->f_mode);
820+ P_IOCTL("chr MINOR: %d command: 0x%X arg: %p VG#: %d mode: %s%s\n",
821+ minor, command, arg, VG_CHR(minor), MODE_TO_STR(file->f_mode));
822
823 #ifdef LVM_TOTAL_RESET
824 if (lvm_reset_spindown > 0) return -EACCES;
825@@ -789,13 +827,10 @@
826 /*
827 * character device close routine
828 */
829-int lvm_chr_close(struct inode *inode, struct file *file)
830+static int lvm_chr_close(struct inode *inode, struct file *file)
831 {
832-#ifdef DEBUG
833- int minor = MINOR(inode->i_rdev);
834- printk(KERN_DEBUG
835- "%s -- lvm_chr_close VG#: %d\n", lvm_name, VG_CHR(minor));
836-#endif
837+ P_DEV("chr_close MINOR: %d VG#: %d\n",
838+ MINOR(inode->i_rdev), VG_CHR(MINOR(inode->i_rdev)));
839
840 #ifdef LVM_TOTAL_RESET
841 if (lvm_reset_spindown > 0) {
842@@ -809,6 +844,7 @@
843 spin_lock(&lvm_lock);
844 if(lock == current->pid) {
845 if(!_lock_open_count) {
846+ P_DEV("chr_close: unlocking LVM for pid %d\n", lock);
847 lock = 0;
848 wake_up_interruptible(&lvm_wait);
849 } else
850@@ -838,8 +874,8 @@
851 lv_t *lv_ptr;
852 vg_t *vg_ptr = vg[VG_BLK(minor)];
853
854- P_DEV("%s -- lvm_blk_open MINOR: %d VG#: %d LV#: %d mode: 0x%X\n",
855- lvm_name, minor, VG_BLK(minor), LV_BLK(minor), file->f_mode);
856+ P_DEV("blk_open MINOR: %d VG#: %d LV#: %d mode: %s%s\n",
857+ minor, VG_BLK(minor), LV_BLK(minor), MODE_TO_STR(file->f_mode));
858
859 #ifdef LVM_TOTAL_RESET
860 if (lvm_reset_spindown > 0)
861@@ -873,7 +909,7 @@
862
863 MOD_INC_USE_COUNT;
864
865- P_DEV("%s -- OPEN OK, LV size %d\n", lvm_name, lv_ptr->lv_size);
866+ P_DEV("blk_open OK, LV size %d\n", lv_ptr->lv_size);
867
868 return 0;
869 }
870@@ -893,16 +929,18 @@
871 void *arg = (void *) a;
872 struct hd_geometry *hd = (struct hd_geometry *) a;
873
874- P_IOCTL("%s -- lvm_blk_ioctl MINOR: %d command: 0x%X arg: %lX "
875- "VG#: %dl LV#: %d\n",
876- lvm_name, minor, command, (ulong) arg,
877- VG_BLK(minor), LV_BLK(minor));
878+ P_IOCTL("blk MINOR: %d command: 0x%X arg: %p VG#: %d LV#: %d "
879+ "mode: %s%s\n", minor, command, arg, VG_BLK(minor),
880+ LV_BLK(minor), MODE_TO_STR(file->f_mode));
881
882 switch (command) {
883+ case BLKSSZGET:
884+ /* get block device sector size as needed e.g. by fdisk */
885+ return put_user(lvm_sectsize(inode->i_rdev), (int *) arg);
886+
887 case BLKGETSIZE:
888 /* return device size */
889- P_IOCTL("%s -- lvm_blk_ioctl -- BLKGETSIZE: %u\n",
890- lvm_name, lv_ptr->lv_size);
891+ P_IOCTL("BLKGETSIZE: %u\n", lv_ptr->lv_size);
892 if (put_user(lv_ptr->lv_size, (long *)arg))
893 return -EFAULT;
894 break;
895@@ -912,7 +950,7 @@
896 /* flush buffer cache */
897 if (!capable(CAP_SYS_ADMIN)) return -EACCES;
898
899- P_IOCTL("%s -- lvm_blk_ioctl -- BLKFLSBUF\n", lvm_name);
900+ P_IOCTL("BLKFLSBUF\n");
901
902 fsync_dev(inode->i_rdev);
903 invalidate_buffers(inode->i_rdev);
904@@ -923,8 +961,8 @@
905 /* set read ahead for block device */
906 if (!capable(CAP_SYS_ADMIN)) return -EACCES;
907
908- P_IOCTL("%s -- lvm_blk_ioctl -- BLKRASET: %ld sectors for %s\n",
909- lvm_name, (long) arg, kdevname(inode->i_rdev));
910+ P_IOCTL("BLKRASET: %ld sectors for %s\n",
911+ (long) arg, kdevname(inode->i_rdev));
912
913 if ((long) arg < LVM_MIN_READ_AHEAD ||
914 (long) arg > LVM_MAX_READ_AHEAD)
915@@ -935,14 +973,11 @@
916
917 case BLKRAGET:
918 /* get current read ahead setting */
919- P_IOCTL("%s -- lvm_blk_ioctl -- BLKRAGET\n", lvm_name);
920+ P_IOCTL("BLKRAGET %d\n", lv_ptr->lv_read_ahead);
921 if (put_user(lv_ptr->lv_read_ahead, (long *)arg))
922 return -EFAULT;
923 break;
924
925- case BLKBSZGET:
926- case BLKBSZSET:
927- return blk_ioctl (inode->i_rdev, command, a);
928
929 case HDIO_GETGEO:
930 /* get disk geometry */
931@@ -991,13 +1026,12 @@
932 break;
933
934 case LV_BMAP:
935- /* turn logical block into (dev_t, block). non privileged. */
936+ /* turn logical block into (dev_t, block). non privileged. */
937 /* don't bmap a snapshot, since the mapping can change */
938- if (lv_ptr->lv_access & LV_SNAPSHOT)
939+ if(lv_ptr->lv_access & LV_SNAPSHOT)
940 return -EPERM;
941
942 return lvm_user_bmap(inode, (struct lv_bmap *) arg);
943- break;
944
945 case LV_SET_ALLOCATION:
946 /* set allocation flags of a logical volume */
947@@ -1028,13 +1062,9 @@
948 vg_t *vg_ptr = vg[VG_BLK(minor)];
949 lv_t *lv_ptr = vg_ptr->lv[LV_BLK(minor)];
950
951-#ifdef DEBUG
952- printk(KERN_DEBUG
953- "%s -- lvm_blk_close MINOR: %d VG#: %d LV#: %d\n",
954- lvm_name, minor, VG_BLK(minor), LV_BLK(minor));
955-#endif
956+ P_DEV("blk_close MINOR: %d VG#: %d LV#: %d\n",
957+ minor, VG_BLK(minor), LV_BLK(minor));
958
959- sync_dev(inode->i_rdev);
960 if (lv_ptr->lv_open == 1) vg_ptr->lv_open--;
961 lv_ptr->lv_open--;
962
963@@ -1086,17 +1116,17 @@
964 return -EFAULT;
965
966 memset(&bh,0,sizeof bh);
967- bh.b_rsector = block;
968- bh.b_dev = bh.b_rdev = inode->i_dev;
969+ bh.b_blocknr = block;
970+ bh.b_dev = bh.b_rdev = inode->i_rdev;
971 bh.b_size = lvm_get_blksize(bh.b_dev);
972+ bh.b_rsector = block * (bh.b_size >> 9);
973 if ((err=lvm_map(&bh, READ)) < 0) {
974 printk("lvm map failed: %d\n", err);
975 return -EINVAL;
976 }
977
978- return put_user(kdev_t_to_nr(bh.b_rdev), &user_result->lv_dev) ||
979- put_user(bh.b_rsector/(bh.b_size>>9), &user_result->lv_block) ?
980- -EFAULT : 0;
981+ return (put_user(kdev_t_to_nr(bh.b_rdev), &user_result->lv_dev) ||
982+ put_user(bh.b_rsector/(bh.b_size>>9), &user_result->lv_block));
983 }
984
985
986@@ -1104,16 +1134,68 @@
987 * block device support function for /usr/src/linux/drivers/block/ll_rw_blk.c
988 * (see init_module/lvm_init)
989 */
990-static inline void __remap_snapshot(kdev_t rdev, ulong rsector,
991+static void __remap_snapshot(kdev_t rdev, ulong rsector,
992 ulong pe_start, lv_t *lv, vg_t *vg) {
993+
994+ /* copy a chunk from the origin to a snapshot device */
995+ down_write(&lv->lv_lock);
996+
997+ /* we must redo lvm_snapshot_remap_block in order to avoid a
998+ race condition in the gap where no lock was held */
999 if (!lvm_snapshot_remap_block(&rdev, &rsector, pe_start, lv) &&
1000 !lvm_snapshot_COW(rdev, rsector, pe_start, rsector, vg, lv))
1001 lvm_write_COW_table_block(vg, lv);
1002+
1003+ up_write(&lv->lv_lock);
1004+}
1005+
1006+static inline void _remap_snapshot(kdev_t rdev, ulong rsector,
1007+ ulong pe_start, lv_t *lv, vg_t *vg) {
1008+ int r;
1009+
1010+ /* check to see if this chunk is already in the snapshot */
1011+ down_read(&lv->lv_lock);
1012+ r = lvm_snapshot_remap_block(&rdev, &rsector, pe_start, lv);
1013+ up_read(&lv->lv_lock);
1014+
1015+ if (!r)
1016+ /* we haven't yet copied this block to the snapshot */
1017+ __remap_snapshot(rdev, rsector, pe_start, lv, vg);
1018 }
1019
1020+
1021+/*
1022+ * extents destined for a pe that is on the move should be deferred
1023+ */
1024+static inline int _should_defer(kdev_t pv, ulong sector, uint32_t pe_size) {
1025+ return ((pe_lock_req.lock == LOCK_PE) &&
1026+ (pv == pe_lock_req.data.pv_dev) &&
1027+ (sector >= pe_lock_req.data.pv_offset) &&
1028+ (sector < (pe_lock_req.data.pv_offset + pe_size)));
1029+}
1030+
1031+static inline int _defer_extent(struct buffer_head *bh, int rw,
1032+ kdev_t pv, ulong sector, uint32_t pe_size)
1033+{
1034+ if (pe_lock_req.lock == LOCK_PE) {
1035+ down_read(&_pe_lock);
1036+ if (_should_defer(pv, sector, pe_size)) {
1037+ up_read(&_pe_lock);
1038+ down_write(&_pe_lock);
1039+ if (_should_defer(pv, sector, pe_size))
1040+ _queue_io(bh, rw);
1041+ up_write(&_pe_lock);
1042+ return 1;
1043+ }
1044+ up_read(&_pe_lock);
1045+ }
1046+ return 0;
1047+}
1048+
1049+
1050 static int lvm_map(struct buffer_head *bh, int rw)
1051 {
1052- int minor = MINOR(bh->b_dev);
1053+ int minor = MINOR(bh->b_rdev);
1054 ulong index;
1055 ulong pe_start;
1056 ulong size = bh->b_size >> 9;
1057@@ -1124,7 +1206,7 @@
1058 lv_t *lv = vg_this->lv[LV_BLK(minor)];
1059
1060
1061- down(&lv->lv_snapshot_sem);
1062+ down_read(&lv->lv_lock);
1063 if (!(lv->lv_status & LV_ACTIVE)) {
1064 printk(KERN_ALERT
1065 "%s - lvm_map: ll_rw_blk for inactive LV %s\n",
1066@@ -1142,7 +1224,7 @@
1067
1068 P_MAP("%s - lvm_map minor: %d *rdev: %s *rsector: %lu size:%lu\n",
1069 lvm_name, minor,
1070- kdevname(bh->b_dev),
1071+ kdevname(bh->b_rdev),
1072 rsector_org, size);
1073
1074 if (rsector_org + size > lv->lv_size) {
1075@@ -1153,7 +1235,7 @@
1076 goto bad;
1077 }
1078
1079-remap:
1080+
1081 if (lv->lv_stripes < 2) { /* linear mapping */
1082 /* get the index */
1083 index = rsector_org / vg_this->pe_size;
1084@@ -1190,36 +1272,33 @@
1085 rsector_map, stripe_length, stripe_index);
1086 }
1087
1088- /* handle physical extents on the move */
1089- if (pe_lock_req.lock == LOCK_PE) {
1090- if (rdev_map == pe_lock_req.data.pv_dev &&
1091- rsector_map >= pe_lock_req.data.pv_offset &&
1092- rsector_map < (pe_lock_req.data.pv_offset +
1093- vg_this->pe_size)) {
1094- sleep_on(&lvm_map_wait);
1095- goto remap;
1096+ /*
1097+ * Queue writes to physical extents on the move until move completes.
1098+ * Don't get _pe_lock until there is a reasonable expectation that
1099+ * we need to queue this request, because this is in the fast path.
1100+ */
1101+ if (rw == WRITE || rw == WRITEA) {
1102+ if(_defer_extent(bh, rw, rdev_map,
1103+ rsector_map, vg_this->pe_size)) {
1104+
1105+ up_read(&lv->lv_lock);
1106+ return 0;
1107 }
1108- }
1109
1110- /* statistic */
1111- if (rw == WRITE || rw == WRITEA)
1112- lv->lv_current_pe[index].writes++;
1113- else
1114- lv->lv_current_pe[index].reads++;
1115+ lv->lv_current_pe[index].writes++; /* statistic */
1116+ } else
1117+ lv->lv_current_pe[index].reads++; /* statistic */
1118
1119- /* snapshot volume exception handling on physical device
1120- address base */
1121+ /* snapshot volume exception handling on physical device address base */
1122 if (!(lv->lv_access & (LV_SNAPSHOT|LV_SNAPSHOT_ORG)))
1123 goto out;
1124
1125 if (lv->lv_access & LV_SNAPSHOT) { /* remap snapshot */
1126- if (lv->lv_block_exception)
1127- lvm_snapshot_remap_block(&rdev_map, &rsector_map,
1128- pe_start, lv);
1129- else
1130+ if (lvm_snapshot_remap_block(&rdev_map, &rsector_map,
1131+ pe_start, lv) < 0)
1132 goto bad;
1133
1134- } else if(rw == WRITE || rw == WRITEA) { /* snapshot origin */
1135+ } else if (rw == WRITE || rw == WRITEA) { /* snapshot origin */
1136 lv_t *snap;
1137
1138 /* start with first snapshot and loop through all of
1139@@ -1232,22 +1311,20 @@
1140
1141 /* Serializes the COW with the accesses to the
1142 snapshot device */
1143- down(&snap->lv_snapshot_sem);
1144- __remap_snapshot(rdev_map, rsector_map,
1145+ _remap_snapshot(rdev_map, rsector_map,
1146 pe_start, snap, vg_this);
1147- up(&snap->lv_snapshot_sem);
1148 }
1149 }
1150
1151 out:
1152 bh->b_rdev = rdev_map;
1153 bh->b_rsector = rsector_map;
1154- up(&lv->lv_snapshot_sem);
1155+ up_read(&lv->lv_lock);
1156 return 1;
1157
1158 bad:
1159 buffer_IO_error(bh);
1160- up(&lv->lv_snapshot_sem);
1161+ up_read(&lv->lv_lock);
1162 return -1;
1163 } /* lvm_map() */
1164
1165@@ -1281,15 +1358,10 @@
1166 /*
1167 * make request function
1168 */
1169-static int lvm_make_request_fn(request_queue_t *q,
1170- int rw,
1171- struct buffer_head *bh)
1172-{
1173- if (lvm_map(bh, rw) >= 0)
1174- return 1;
1175-
1176- buffer_IO_error(bh);
1177- return 0;
1178+static int lvm_make_request_fn(request_queue_t *q,
1179+ int rw,
1180+ struct buffer_head *bh) {
1181+ return (lvm_map(bh, rw) <= 0) ? 0 : 1;
1182 }
1183
1184
1185@@ -1306,8 +1378,7 @@
1186 lock_try_again:
1187 spin_lock(&lvm_lock);
1188 if (lock != 0 && lock != current->pid) {
1189- P_IOCTL("lvm_do_lock_lvm: %s is locked by pid %d ...\n",
1190- lvm_name, lock);
1191+ P_DEV("lvm_do_lock_lvm: locked by pid %d ...\n", lock);
1192 spin_unlock(&lvm_lock);
1193 interruptible_sleep_on(&lvm_wait);
1194 if (current->sigpending != 0)
1195@@ -1319,6 +1390,7 @@
1196 goto lock_try_again;
1197 }
1198 lock = current->pid;
1199+ P_DEV("lvm_do_lock_lvm: locking LVM for pid %d\n", lock);
1200 spin_unlock(&lvm_lock);
1201 return 0;
1202 } /* lvm_do_lock_lvm */
1203@@ -1329,33 +1401,60 @@
1204 */
1205 static int lvm_do_pe_lock_unlock(vg_t *vg_ptr, void *arg)
1206 {
1207+ pe_lock_req_t new_lock;
1208+ struct buffer_head *bh;
1209 uint p;
1210
1211 if (vg_ptr == NULL) return -ENXIO;
1212- if (copy_from_user(&pe_lock_req, arg,
1213- sizeof(pe_lock_req_t)) != 0) return -EFAULT;
1214+ if (copy_from_user(&new_lock, arg, sizeof(new_lock)) != 0)
1215+ return -EFAULT;
1216
1217- switch (pe_lock_req.lock) {
1218+ switch (new_lock.lock) {
1219 case LOCK_PE:
1220 for (p = 0; p < vg_ptr->pv_max; p++) {
1221 if (vg_ptr->pv[p] != NULL &&
1222- pe_lock_req.data.pv_dev ==
1223- vg_ptr->pv[p]->pv_dev)
1224+ new_lock.data.pv_dev == vg_ptr->pv[p]->pv_dev)
1225 break;
1226 }
1227 if (p == vg_ptr->pv_max) return -ENXIO;
1228
1229- pe_lock_req.lock = UNLOCK_PE;
1230+ /*
1231+ * this sync releaves memory pressure to lessen the
1232+ * likelyhood of pvmove being paged out - resulting in
1233+ * deadlock.
1234+ *
1235+ * This method of doing a pvmove is broken
1236+ */
1237 fsync_dev(pe_lock_req.data.lv_dev);
1238+
1239+ down_write(&_pe_lock);
1240+ if (pe_lock_req.lock == LOCK_PE) {
1241+ up_write(&_pe_lock);
1242+ return -EBUSY;
1243+ }
1244+
1245+ /* Should we do to_kdev_t() on the pv_dev and lv_dev??? */
1246 pe_lock_req.lock = LOCK_PE;
1247+ pe_lock_req.data.lv_dev = new_lock.data.lv_dev;
1248+ pe_lock_req.data.pv_dev = new_lock.data.pv_dev;
1249+ pe_lock_req.data.pv_offset = new_lock.data.pv_offset;
1250+ up_write(&_pe_lock);
1251+
1252+ /* some requests may have got through since the fsync */
1253+ fsync_dev(pe_lock_req.data.pv_dev);
1254 break;
1255
1256 case UNLOCK_PE:
1257+ down_write(&_pe_lock);
1258 pe_lock_req.lock = UNLOCK_PE;
1259- pe_lock_req.data.lv_dev = \
1260- pe_lock_req.data.pv_dev = \
1261+ pe_lock_req.data.lv_dev = 0;
1262+ pe_lock_req.data.pv_dev = 0;
1263 pe_lock_req.data.pv_offset = 0;
1264- wake_up(&lvm_map_wait);
1265+ bh = _dequeue_io();
1266+ up_write(&_pe_lock);
1267+
1268+ /* handle all deferred io for this PE */
1269+ _flush_io(bh);
1270 break;
1271
1272 default:
1273@@ -1423,6 +1522,8 @@
1274 }
1275 /* get the volume group structure */
1276 if (copy_from_user(vg_ptr, arg, sizeof(vg_t)) != 0) {
1277+ P_IOCTL("lvm_do_vg_create ERROR: copy VG ptr %p (%d bytes)\n",
1278+ arg, sizeof(vg_t));
1279 kfree(vg_ptr);
1280 return -EFAULT;
1281 }
1282@@ -1432,8 +1533,9 @@
1283
1284 /* Validate it */
1285 if (vg[VG_CHR(minor)] != NULL) {
1286- kfree(vg_ptr);
1287- return -EPERM;
1288+ P_IOCTL("lvm_do_vg_create ERROR: VG %d in use\n", minor);
1289+ kfree(vg_ptr);
1290+ return -EPERM;
1291 }
1292
1293 /* we are not that active so far... */
1294@@ -1464,6 +1566,7 @@
1295 /* get the physical volume structures */
1296 vg_ptr->pv_act = vg_ptr->pv_cur = 0;
1297 for (p = 0; p < vg_ptr->pv_max; p++) {
1298+ pv_t *pvp;
1299 /* user space address */
1300 if ((pvp = vg_ptr->pv[p]) != NULL) {
1301 ret = lvm_do_pv_create(pvp, vg_ptr, p);
1302@@ -1487,9 +1590,12 @@
1303 /* get the logical volume structures */
1304 vg_ptr->lv_cur = 0;
1305 for (l = 0; l < vg_ptr->lv_max; l++) {
1306+ lv_t *lvp;
1307 /* user space address */
1308 if ((lvp = vg_ptr->lv[l]) != NULL) {
1309 if (copy_from_user(&lv, lvp, sizeof(lv_t)) != 0) {
1310+ P_IOCTL("ERROR: copying LV ptr %p (%d bytes)\n",
1311+ lvp, sizeof(lv_t));
1312 lvm_do_vg_remove(minor);
1313 return -EFAULT;
1314 }
1315@@ -1511,7 +1617,7 @@
1316 /* Second path to correct snapshot logical volumes which are not
1317 in place during first path above */
1318 for (l = 0; l < ls; l++) {
1319- lvp = snap_lv_ptr[l];
1320+ lv_t *lvp = snap_lv_ptr[l];
1321 if (copy_from_user(&lv, lvp, sizeof(lv_t)) != 0) {
1322 lvm_do_vg_remove(minor);
1323 return -EFAULT;
1324@@ -1703,27 +1809,41 @@
1325 * character device support function physical volume create
1326 */
1327 static int lvm_do_pv_create(pv_t *pvp, vg_t *vg_ptr, ulong p) {
1328- pv_t *pv_ptr = NULL;
1329+ pv_t *pv;
1330+ int err;
1331
1332- pv_ptr = vg_ptr->pv[p] = kmalloc(sizeof(pv_t),GFP_KERNEL);
1333- if (pv_ptr == NULL) {
1334+ pv = kmalloc(sizeof(pv_t),GFP_KERNEL);
1335+ if (pv == NULL) {
1336 printk(KERN_CRIT
1337 "%s -- PV_CREATE: kmalloc error PV at line %d\n",
1338 lvm_name, __LINE__);
1339 return -ENOMEM;
1340 }
1341- if (copy_from_user(pv_ptr, pvp, sizeof(pv_t)) != 0) {
1342+
1343+ memset(pv, 0, sizeof(*pv));
1344+
1345+ if (copy_from_user(pv, pvp, sizeof(pv_t)) != 0) {
1346+ P_IOCTL("lvm_do_pv_create ERROR: copy PV ptr %p (%d bytes)\n",
1347+ pvp, sizeof(pv_t));
1348+ kfree(pv);
1349 return -EFAULT;
1350 }
1351+
1352+ if ((err = _open_pv(pv))) {
1353+ kfree(pv);
1354+ return err;
1355+ }
1356+
1357 /* We don't need the PE list
1358 in kernel space as with LVs pe_t list (see below) */
1359- pv_ptr->pe = NULL;
1360- pv_ptr->pe_allocated = 0;
1361- pv_ptr->pv_status = PV_ACTIVE;
1362+ pv->pe = NULL;
1363+ pv->pe_allocated = 0;
1364+ pv->pv_status = PV_ACTIVE;
1365 vg_ptr->pv_act++;
1366 vg_ptr->pv_cur++;
1367- lvm_fs_create_pv(vg_ptr, pv_ptr);
1368+ lvm_fs_create_pv(vg_ptr, pv);
1369
1370+ vg_ptr->pv[p] = pv;
1371 return 0;
1372 } /* lvm_do_pv_create() */
1373
1374@@ -1732,47 +1852,73 @@
1375 * character device support function physical volume remove
1376 */
1377 static int lvm_do_pv_remove(vg_t *vg_ptr, ulong p) {
1378- pv_t *pv_ptr = vg_ptr->pv[p];
1379+ pv_t *pv = vg_ptr->pv[p];
1380
1381- lvm_fs_remove_pv(vg_ptr, pv_ptr);
1382+ lvm_fs_remove_pv(vg_ptr, pv);
1383
1384- vg_ptr->pe_total -= pv_ptr->pe_total;
1385+ vg_ptr->pe_total -= pv->pe_total;
1386 vg_ptr->pv_cur--;
1387 vg_ptr->pv_act--;
1388-#ifdef LVM_GET_INODE
1389- lvm_clear_inode(pv_ptr->inode);
1390-#endif
1391- kfree(pv_ptr);
1392+
1393+ _close_pv(pv);
1394+ kfree(pv);
1395+
1396 vg_ptr->pv[p] = NULL;
1397
1398 return 0;
1399 }
1400
1401
1402-static void __update_hardsectsize(lv_t *lv) {
1403- int le, e;
1404- int max_hardsectsize = 0, hardsectsize;
1405-
1406- for (le = 0; le < lv->lv_allocated_le; le++) {
1407- hardsectsize = get_hardsect_size(lv->lv_current_pe[le].dev);
1408- if (hardsectsize == 0)
1409- hardsectsize = 512;
1410- if (hardsectsize > max_hardsectsize)
1411- max_hardsectsize = hardsectsize;
1412- }
1413-
1414- if (lv->lv_access & LV_SNAPSHOT) {
1415- for (e = 0; e < lv->lv_remap_end; e++) {
1416- hardsectsize =
1417- get_hardsect_size(
1418- lv->lv_block_exception[e].rdev_new);
1419- if (hardsectsize == 0)
1420- hardsectsize = 512;
1421- if (hardsectsize > max_hardsectsize)
1422+static void __update_hardsectsize(lv_t *lv)
1423+{
1424+ int max_hardsectsize = 0, hardsectsize = 0;
1425+ int p;
1426+
1427+ /* Check PVs first to see if they all have same sector size */
1428+ for (p = 0; p < lv->vg->pv_cur; p++) {
1429+ pv_t *pv = lv->vg->pv[p];
1430+ if (pv && (hardsectsize = lvm_sectsize(pv->pv_dev))) {
1431+ if (max_hardsectsize == 0)
1432 max_hardsectsize = hardsectsize;
1433+ else if (hardsectsize != max_hardsectsize) {
1434+ P_DEV("%s PV[%d] (%s) sector size %d, not %d\n",
1435+ lv->lv_name, p, kdevname(pv->pv_dev),
1436+ hardsectsize, max_hardsectsize);
1437+ break;
1438+ }
1439+ }
1440+ }
1441+
1442+ /* PVs have different block size, need to check each LE sector size */
1443+ if (hardsectsize != max_hardsectsize) {
1444+ int le;
1445+ for (le = 0; le < lv->lv_allocated_le; le++) {
1446+ hardsectsize = lvm_sectsize(lv->lv_current_pe[le].dev);
1447+ if (hardsectsize > max_hardsectsize) {
1448+ P_DEV("%s LE[%d] (%s) blocksize %d not %d\n",
1449+ lv->lv_name, le,
1450+ kdevname(lv->lv_current_pe[le].dev),
1451+ hardsectsize, max_hardsectsize);
1452+ max_hardsectsize = hardsectsize;
1453+ }
1454+ }
1455+
1456+ /* only perform this operation on active snapshots */
1457+ if ((lv->lv_access & LV_SNAPSHOT) &&
1458+ (lv->lv_status & LV_ACTIVE)) {
1459+ int e;
1460+ for (e = 0; e < lv->lv_remap_end; e++) {
1461+ hardsectsize = lvm_sectsize(lv->lv_block_exception[e].rdev_new);
1462+ if (hardsectsize > max_hardsectsize)
1463+ max_hardsectsize = hardsectsize;
1464+ }
1465 }
1466 }
1467
1468+ if (max_hardsectsize == 0)
1469+ max_hardsectsize = SECTOR_SIZE;
1470+ P_DEV("hardblocksize for LV %s is %d\n",
1471+ kdevname(lv->lv_dev), max_hardsectsize);
1472 lvm_hardsectsizes[MINOR(lv->lv_dev)] = max_hardsectsize;
1473 }
1474
1475@@ -1786,9 +1932,12 @@
1476 lv_block_exception_t *lvbe = lv->lv_block_exception;
1477 vg_t *vg_ptr = vg[VG_CHR(minor)];
1478 lv_t *lv_ptr = NULL;
1479+ pe_t *pep;
1480
1481- if ((pep = lv->lv_current_pe) == NULL) return -EINVAL;
1482- if (lv->lv_chunk_size > LVM_SNAPSHOT_MAX_CHUNK)
1483+ if (!(pep = lv->lv_current_pe))
1484+ return -EINVAL;
1485+
1486+ if (_sectors_to_k(lv->lv_chunk_size) > LVM_SNAPSHOT_MAX_CHUNK)
1487 return -EINVAL;
1488
1489 for (l = 0; l < vg_ptr->lv_cur; l++) {
1490@@ -1820,8 +1969,8 @@
1491
1492 lv_status_save = lv_ptr->lv_status;
1493 lv_ptr->lv_status &= ~LV_ACTIVE;
1494- lv_ptr->lv_snapshot_org = \
1495- lv_ptr->lv_snapshot_prev = \
1496+ lv_ptr->lv_snapshot_org = NULL;
1497+ lv_ptr->lv_snapshot_prev = NULL;
1498 lv_ptr->lv_snapshot_next = NULL;
1499 lv_ptr->lv_block_exception = NULL;
1500 lv_ptr->lv_iobuf = NULL;
1501@@ -1829,7 +1978,8 @@
1502 lv_ptr->lv_snapshot_hash_table = NULL;
1503 lv_ptr->lv_snapshot_hash_table_size = 0;
1504 lv_ptr->lv_snapshot_hash_mask = 0;
1505- init_MUTEX(&lv_ptr->lv_snapshot_sem);
1506+ init_rwsem(&lv_ptr->lv_lock);
1507+
1508 lv_ptr->lv_snapshot_use_rate = 0;
1509
1510 vg_ptr->lv[l] = lv_ptr;
1511@@ -1838,6 +1988,7 @@
1512 is not a snapshot logical volume */
1513 if (!(lv_ptr->lv_access & LV_SNAPSHOT)) {
1514 size = lv_ptr->lv_allocated_le * sizeof(pe_t);
1515+
1516 if ((lv_ptr->lv_current_pe = vmalloc(size)) == NULL) {
1517 printk(KERN_CRIT
1518 "%s -- LV_CREATE: vmalloc error LV_CURRENT_PE of %d Byte "
1519@@ -1849,6 +2000,8 @@
1520 return -ENOMEM;
1521 }
1522 if (copy_from_user(lv_ptr->lv_current_pe, pep, size)) {
1523+ P_IOCTL("ERROR: copying PE ptr %p (%d bytes)\n",
1524+ pep, sizeof(size));
1525 vfree(lv_ptr->lv_current_pe);
1526 kfree(lv_ptr);
1527 vg_ptr->lv[l] = NULL;
1528@@ -1870,6 +2023,15 @@
1529 vg_ptr->lv[LV_BLK(lv_ptr->lv_snapshot_minor)];
1530 if (lv_ptr->lv_snapshot_org != NULL) {
1531 size = lv_ptr->lv_remap_end * sizeof(lv_block_exception_t);
1532+
1533+ if(!size) {
1534+ printk(KERN_WARNING
1535+ "%s -- zero length exception table requested\n",
1536+ lvm_name);
1537+ kfree(lv_ptr);
1538+ return -EINVAL;
1539+ }
1540+
1541 if ((lv_ptr->lv_block_exception = vmalloc(size)) == NULL) {
1542 printk(KERN_CRIT
1543 "%s -- lvm_do_lv_create: vmalloc error LV_BLOCK_EXCEPTION "
1544@@ -1957,6 +2119,7 @@
1545 LVM_CORRECT_READ_AHEAD(lv_ptr->lv_read_ahead);
1546 vg_ptr->lv_cur++;
1547 lv_ptr->lv_status = lv_status_save;
1548+ lv_ptr->vg = vg_ptr;
1549
1550 __update_hardsectsize(lv_ptr);
1551
1552@@ -1971,7 +2134,7 @@
1553 fsync_dev_lockfs(org->lv_dev);
1554 #endif
1555
1556- down(&org->lv_snapshot_sem);
1557+ down_write(&org->lv_lock);
1558 org->lv_access |= LV_SNAPSHOT_ORG;
1559 lv_ptr->lv_access &= ~LV_SNAPSHOT_ORG; /* this can only hide an userspace bug */
1560
1561@@ -1980,7 +2143,7 @@
1562 for (last = org; last->lv_snapshot_next; last = last->lv_snapshot_next);
1563 lv_ptr->lv_snapshot_prev = last;
1564 last->lv_snapshot_next = lv_ptr;
1565- up(&org->lv_snapshot_sem);
1566+ up_write(&org->lv_lock);
1567 }
1568
1569 /* activate the logical volume */
1570@@ -1996,14 +2159,12 @@
1571
1572 #ifdef LVM_VFS_ENHANCEMENT
1573 /* VFS function call to unlock the filesystem */
1574- if (lv_ptr->lv_access & LV_SNAPSHOT) {
1575+ if (lv_ptr->lv_access & LV_SNAPSHOT)
1576 unlockfs(lv_ptr->lv_snapshot_org->lv_dev);
1577- }
1578 #endif
1579
1580- lv_ptr->vg = vg_ptr;
1581-
1582- lvm_fs_create_lv(vg_ptr, lv_ptr);
1583+ lvm_gendisk.part[MINOR(lv_ptr->lv_dev)].de =
1584+ lvm_fs_create_lv(vg_ptr, lv_ptr);
1585 return 0;
1586 } /* lvm_do_lv_create() */
1587
1588@@ -2049,7 +2210,7 @@
1589 * to the original lv before playing with it.
1590 */
1591 lv_t * org = lv_ptr->lv_snapshot_org;
1592- down(&org->lv_snapshot_sem);
1593+ down_write(&org->lv_lock);
1594
1595 /* remove this snapshot logical volume from the chain */
1596 lv_ptr->lv_snapshot_prev->lv_snapshot_next = lv_ptr->lv_snapshot_next;
1597@@ -2062,7 +2223,7 @@
1598 if (!org->lv_snapshot_next) {
1599 org->lv_access &= ~LV_SNAPSHOT_ORG;
1600 }
1601- up(&org->lv_snapshot_sem);
1602+ up_write(&org->lv_lock);
1603
1604 lvm_snapshot_release(lv_ptr);
1605
1606@@ -2083,6 +2244,7 @@
1607 /* reset generic hd */
1608 lvm_gendisk.part[MINOR(lv_ptr->lv_dev)].start_sect = -1;
1609 lvm_gendisk.part[MINOR(lv_ptr->lv_dev)].nr_sects = 0;
1610+ lvm_gendisk.part[MINOR(lv_ptr->lv_dev)].de = 0;
1611 lvm_size[MINOR(lv_ptr->lv_dev)] = 0;
1612
1613 /* reset VG/LV mapping */
1614@@ -2214,8 +2376,7 @@
1615 new_stripe_size = new_lv->lv_allocated_le / new_lv->lv_stripes;
1616 end = min(old_stripe_size, new_stripe_size);
1617
1618- for (i = source = dest = 0;
1619- i < new_lv->lv_stripes; i++) {
1620+ for (i = source = dest = 0; i < new_lv->lv_stripes; i++) {
1621 for (j = 0; j < end; j++) {
1622 new_lv->lv_current_pe[dest + j].reads +=
1623 old_lv->lv_current_pe[source + j].reads;
1624@@ -2250,23 +2411,27 @@
1625
1626 old_lv = vg_ptr->lv[l];
1627
1628- if (old_lv->lv_access & LV_SNAPSHOT)
1629- r = __extend_reduce_snapshot(vg_ptr, old_lv, new_lv);
1630- else
1631+ if (old_lv->lv_access & LV_SNAPSHOT) {
1632+ /* only perform this operation on active snapshots */
1633+ if (old_lv->lv_status & LV_ACTIVE)
1634+ r = __extend_reduce_snapshot(vg_ptr, old_lv, new_lv);
1635+ else
1636+ r = -EPERM;
1637+
1638+ } else
1639 r = __extend_reduce(vg_ptr, old_lv, new_lv);
1640
1641 if(r)
1642 return r;
1643
1644 /* copy relevent fields */
1645- down(&old_lv->lv_snapshot_sem);
1646+ down_write(&old_lv->lv_lock);
1647
1648 if(new_lv->lv_access & LV_SNAPSHOT) {
1649-
1650 size = (new_lv->lv_remap_end > old_lv->lv_remap_end) ?
1651 old_lv->lv_remap_ptr : new_lv->lv_remap_end;
1652 size *= sizeof(lv_block_exception_t);
1653- memcpy(new_lv->lv_block_exception,
1654+ memcpy(new_lv->lv_block_exception,
1655 old_lv->lv_block_exception, size);
1656
1657 old_lv->lv_remap_end = new_lv->lv_remap_end;
1658@@ -2281,7 +2446,7 @@
1659 for (e = 0; e < new_lv->lv_remap_ptr; e++)
1660 lvm_hash_link(new_lv->lv_block_exception + e,
1661 new_lv->lv_block_exception[e].rdev_org,
1662- new_lv->lv_block_exception[e].rsector_org,
1663+ new_lv->lv_block_exception[e].rsector_org,
1664 new_lv);
1665
1666 } else {
1667@@ -2301,7 +2466,7 @@
1668 lv_t *snap;
1669 for(snap = old_lv->lv_snapshot_next; snap;
1670 snap = snap->lv_snapshot_next) {
1671- down(&snap->lv_snapshot_sem);
1672+ down_write(&snap->lv_lock);
1673 snap->lv_current_pe = old_lv->lv_current_pe;
1674 snap->lv_allocated_le =
1675 old_lv->lv_allocated_le;
1676@@ -2313,13 +2478,13 @@
1677 lvm_size[MINOR(snap->lv_dev)] =
1678 old_lv->lv_size >> 1;
1679 __update_hardsectsize(snap);
1680- up(&snap->lv_snapshot_sem);
1681+ up_write(&snap->lv_lock);
1682 }
1683 }
1684 }
1685
1686 __update_hardsectsize(old_lv);
1687- up(&old_lv->lv_snapshot_sem);
1688+ up_write(&old_lv->lv_lock);
1689
1690 return 0;
1691 } /* lvm_do_lv_extend_reduce() */
1692@@ -2348,8 +2513,10 @@
1693 strcmp(lv_ptr->lv_name,
1694 lv_status_byname_req.lv_name) == 0) {
1695 /* Save usermode pointers */
1696- saved_ptr1 = lv_status_byname_req.lv->lv_current_pe;
1697- saved_ptr2 = lv_status_byname_req.lv->lv_block_exception;
1698+ if (copy_from_user(&saved_ptr1, &lv_status_byname_req.lv->lv_current_pe, sizeof(void*)) != 0)
1699+ return -EFAULT;
1700+ if (copy_from_user(&saved_ptr2, &lv_status_byname_req.lv->lv_block_exception, sizeof(void*)) != 0)
1701+ return -EFAULT;
1702 if (copy_to_user(lv_status_byname_req.lv,
1703 lv_ptr,
1704 sizeof(lv_t)) != 0)
1705@@ -2362,7 +2529,8 @@
1706 return -EFAULT;
1707 }
1708 /* Restore usermode pointers */
1709- lv_status_byname_req.lv->lv_current_pe = saved_ptr1;
1710+ if (copy_to_user(&lv_status_byname_req.lv->lv_current_pe, &saved_ptr1, sizeof(void*)) != 0)
1711+ return -EFAULT;
1712 return 0;
1713 }
1714 }
1715@@ -2391,8 +2559,11 @@
1716 return -ENXIO;
1717
1718 /* Save usermode pointers */
1719- saved_ptr1 = lv_status_byindex_req.lv->lv_current_pe;
1720- saved_ptr2 = lv_status_byindex_req.lv->lv_block_exception;
1721+ if (copy_from_user(&saved_ptr1, &lv_status_byindex_req.lv->lv_current_pe, sizeof(void*)) != 0)
1722+ return -EFAULT;
1723+ if (copy_from_user(&saved_ptr2, &lv_status_byindex_req.lv->lv_block_exception, sizeof(void*)) != 0)
1724+ return -EFAULT;
1725+
1726 if (copy_to_user(lv_status_byindex_req.lv, lv_ptr, sizeof(lv_t)) != 0)
1727 return -EFAULT;
1728 if (saved_ptr1 != NULL) {
1729@@ -2404,7 +2575,8 @@
1730 }
1731
1732 /* Restore usermode pointers */
1733- lv_status_byindex_req.lv->lv_current_pe = saved_ptr1;
1734+ if (copy_to_user(&lv_status_byindex_req.lv->lv_current_pe, &saved_ptr1, sizeof(void *)) != 0)
1735+ return -EFAULT;
1736
1737 return 0;
1738 } /* lvm_do_lv_status_byindex() */
1739@@ -2434,8 +2606,10 @@
1740 lv_ptr = vg_ptr->lv[l];
1741
1742 /* Save usermode pointers */
1743- saved_ptr1 = lv_status_bydev_req.lv->lv_current_pe;
1744- saved_ptr2 = lv_status_bydev_req.lv->lv_block_exception;
1745+ if (copy_from_user(&saved_ptr1, &lv_status_bydev_req.lv->lv_current_pe, sizeof(void*)) != 0)
1746+ return -EFAULT;
1747+ if (copy_from_user(&saved_ptr2, &lv_status_bydev_req.lv->lv_block_exception, sizeof(void*)) != 0)
1748+ return -EFAULT;
1749
1750 if (copy_to_user(lv_status_bydev_req.lv, lv_ptr, sizeof(lv_t)) != 0)
1751 return -EFAULT;
1752@@ -2447,7 +2621,8 @@
1753 return -EFAULT;
1754 }
1755 /* Restore usermode pointers */
1756- lv_status_bydev_req.lv->lv_current_pe = saved_ptr1;
1757+ if (copy_to_user(&lv_status_bydev_req.lv->lv_current_pe, &saved_ptr1, sizeof(void *)) != 0)
1758+ return -EFAULT;
1759
1760 return 0;
1761 } /* lvm_do_lv_status_bydev() */
1762@@ -2468,9 +2643,7 @@
1763 if (lv_ptr->lv_dev == lv->lv_dev)
1764 {
1765 lvm_fs_remove_lv(vg_ptr, lv_ptr);
1766- strncpy(lv_ptr->lv_name,
1767- lv_req->lv_name,
1768- NAME_LEN);
1769+ strncpy(lv_ptr->lv_name, lv_req->lv_name, NAME_LEN);
1770 lvm_fs_create_lv(vg_ptr, lv_ptr);
1771 break;
1772 }
1773@@ -2488,9 +2661,7 @@
1774 {
1775 uint p;
1776 pv_t *pv_ptr;
1777-#ifdef LVM_GET_INODE
1778- struct inode *inode_sav;
1779-#endif
1780+ struct block_device *bd;
1781
1782 if (vg_ptr == NULL) return -ENXIO;
1783 if (copy_from_user(&pv_change_req, arg,
1784@@ -2502,20 +2673,17 @@
1785 if (pv_ptr != NULL &&
1786 strcmp(pv_ptr->pv_name,
1787 pv_change_req.pv_name) == 0) {
1788-#ifdef LVM_GET_INODE
1789- inode_sav = pv_ptr->inode;
1790-#endif
1791+
1792+ bd = pv_ptr->bd;
1793 if (copy_from_user(pv_ptr,
1794 pv_change_req.pv,
1795 sizeof(pv_t)) != 0)
1796 return -EFAULT;
1797+ pv_ptr->bd = bd;
1798
1799 /* We don't need the PE list
1800 in kernel space as with LVs pe_t list */
1801 pv_ptr->pe = NULL;
1802-#ifdef LVM_GET_INODE
1803- pv_ptr->inode = inode_sav;
1804-#endif
1805 return 0;
1806 }
1807 }
1808@@ -2558,8 +2726,7 @@
1809 {
1810 pv_flush_req_t pv_flush_req;
1811
1812- if (copy_from_user(&pv_flush_req, arg,
1813- sizeof(pv_flush_req)) != 0)
1814+ if (copy_from_user(&pv_flush_req, arg, sizeof(pv_flush_req)) != 0)
1815 return -EFAULT;
1816
1817 fsync_dev(pv_flush_req.pv_dev);
1818@@ -2594,5 +2761,82 @@
1819 } /* lvm_gen_init() */
1820
1821
1822+
1823+/* Must have down_write(_pe_lock) when we enqueue buffers */
1824+static void _queue_io(struct buffer_head *bh, int rw) {
1825+ if (bh->b_reqnext) BUG();
1826+ bh->b_reqnext = _pe_requests;
1827+ _pe_requests = bh;
1828+}
1829+
1830+/* Must have down_write(_pe_lock) when we dequeue buffers */
1831+static struct buffer_head *_dequeue_io(void)
1832+{
1833+ struct buffer_head *bh = _pe_requests;
1834+ _pe_requests = NULL;
1835+ return bh;
1836+}
1837+
1838+/*
1839+ * We do not need to hold _pe_lock to flush buffers. bh should be taken from
1840+ * _pe_requests under down_write(_pe_lock), and then _pe_requests can be set
1841+ * NULL and we drop _pe_lock. Any new buffers defered at this time will be
1842+ * added to a new list, and the old buffers can have their I/O restarted
1843+ * asynchronously.
1844+ *
1845+ * If, for some reason, the same PE is locked again before all of these writes
1846+ * have finished, then these buffers will just be re-queued (i.e. no danger).
1847+ */
1848+static void _flush_io(struct buffer_head *bh)
1849+{
1850+ while (bh) {
1851+ struct buffer_head *next = bh->b_reqnext;
1852+ bh->b_reqnext = NULL;
1853+ /* resubmit this buffer head */
1854+ generic_make_request(WRITE, bh);
1855+ bh = next;
1856+ }
1857+}
1858+
1859+
1860+/*
1861+ * we must open the pv's before we use them
1862+ */
1863+static int _open_pv(pv_t *pv) {
1864+ int err;
1865+ struct block_device *bd;
1866+
1867+ if (!(bd = bdget(kdev_t_to_nr(pv->pv_dev))))
1868+ return -ENOMEM;
1869+
1870+ err = blkdev_get(bd, FMODE_READ|FMODE_WRITE, 0, BDEV_FILE);
1871+ if (err) {
1872+ bdput(bd);
1873+ return err;
1874+ }
1875+
1876+ pv->bd = bd;
1877+ return 0;
1878+}
1879+
1880+static void _close_pv(pv_t *pv) {
1881+ if(!pv || !pv->bd)
1882+ return;
1883+
1884+ blkdev_put(pv->bd, BDEV_FILE);
1885+ bdput(pv->bd);
1886+ pv->bd = 0;
1887+}
1888+
1889+
1890+static unsigned long _sectors_to_k(unsigned long sect)
1891+{
1892+ if(SECTOR_SIZE > 1024) {
1893+ return sect * (SECTOR_SIZE / 1024);
1894+ }
1895+
1896+ return sect / (1024 / SECTOR_SIZE);
1897+}
1898+
1899 module_init(lvm_init);
1900 module_exit(lvm_cleanup);
1901--- linux/drivers/md/lvm-internal.h.orig Sat Oct 20 20:50:29 2001
1902+++ linux/drivers/md/lvm-internal.h Sat Oct 20 20:36:55 2001
1903@@ -1,3 +1,4 @@
1904+
1905 /*
1906 * kernel/lvm_internal.h
1907 *
1908@@ -39,17 +40,35 @@
1909
1910 /* global variables, defined in lvm.c */
1911 extern char *lvm_version;
1912-extern char *lvm_short_version;
1913 extern ushort lvm_iop_version;
1914 extern int loadtime;
1915 extern const char *const lvm_name;
1916
1917
1918+extern uint vg_count;
1919 extern vg_t *vg[];
1920 extern struct file_operations lvm_chr_fops;
1921
1922 extern struct block_device_operations lvm_blk_dops;
1923
1924+#define lvm_sectsize(dev) get_hardsect_size(dev)
1925+
1926+/* 2.4.8 had no global min/max macros, and 2.4.9's were flawed */
1927+
1928+#undef min
1929+#define min(x,y) ({ \
1930+ const typeof(x) _x = (x); \
1931+ const typeof(y) _y = (y); \
1932+ (void) (&_x == &_y); \
1933+ _x < _y ? _x : _y; })
1934+
1935+#undef max
1936+#define max(x,y) ({ \
1937+ const typeof(x) _x = (x); \
1938+ const typeof(y) _y = (y); \
1939+ (void) (&_x == &_y); \
1940+ _x > _y ? _x : _y; })
1941+
1942
1943 /* debug macros */
1944 #ifdef DEBUG_IOCTL
1945@@ -96,7 +115,7 @@
1946
1947 void lvm_fs_create_vg(vg_t *vg_ptr);
1948 void lvm_fs_remove_vg(vg_t *vg_ptr);
1949-void lvm_fs_create_lv(vg_t *vg_ptr, lv_t *lv);
1950+devfs_handle_t lvm_fs_create_lv(vg_t *vg_ptr, lv_t *lv);
1951 void lvm_fs_remove_lv(vg_t *vg_ptr, lv_t *lv);
1952 void lvm_fs_create_pv(vg_t *vg_ptr, pv_t *pv);
1953 void lvm_fs_remove_pv(vg_t *vg_ptr, pv_t *pv);
1954--- linux/drivers/md/lvm-snap.c.orig Sat Oct 20 20:50:29 2001
1955+++ linux/drivers/md/lvm-snap.c Sat Oct 20 20:36:55 2001
1956@@ -39,6 +39,8 @@
1957 * o pv number is returned in new uint * arg
1958 * o -1 returned on error
1959 * lvm_snapshot_fill_COW_table has a return value too.
1960+ * 15/10/2001 - fix snapshot alignment problem [CM]
1961+ * - fix snapshot full oops (always check lv_block_exception) [CM]
1962 *
1963 */
1964
1965@@ -49,6 +51,7 @@
1966 #include <linux/types.h>
1967 #include <linux/iobuf.h>
1968 #include <linux/lvm.h>
1969+#include <linux/devfs_fs_kernel.h>
1970
1971
1972 #include "lvm-internal.h"
1973@@ -140,10 +143,20 @@
1974 unsigned long mask = lv->lv_snapshot_hash_mask;
1975 int chunk_size = lv->lv_chunk_size;
1976
1977+ if (!hash_table)
1978+ BUG();
1979 hash_table = &hash_table[hashfn(org_dev, org_start, mask, chunk_size)];
1980 list_add(&exception->hash, hash_table);
1981 }
1982
1983+/*
1984+ * Determine if we already have a snapshot chunk for this block.
1985+ * Return: 1 if it the chunk already exists
1986+ * 0 if we need to COW this block and allocate a new chunk
1987+ * -1 if the snapshot was disabled because it ran out of space
1988+ *
1989+ * We need to be holding at least a read lock on lv->lv_lock.
1990+ */
1991 int lvm_snapshot_remap_block(kdev_t * org_dev, unsigned long * org_sector,
1992 unsigned long pe_start, lv_t * lv)
1993 {
1994@@ -153,6 +166,9 @@
1995 int chunk_size = lv->lv_chunk_size;
1996 lv_block_exception_t * exception;
1997
1998+ if (!lv->lv_block_exception)
1999+ return -1;
2000+
2001 pe_off = pe_start % chunk_size;
2002 pe_adjustment = (*org_sector-pe_off) % chunk_size;
2003 __org_start = *org_sector - pe_adjustment;
2004@@ -196,19 +212,25 @@
2005 reason);
2006 }
2007
2008-static inline void lvm_snapshot_prepare_blocks(unsigned long * blocks,
2009+static inline int lvm_snapshot_prepare_blocks(unsigned long *blocks,
2010 unsigned long start,
2011 int nr_sectors,
2012 int blocksize)
2013 {
2014 int i, sectors_per_block, nr_blocks;
2015
2016- sectors_per_block = blocksize >> 9;
2017+ sectors_per_block = blocksize / SECTOR_SIZE;
2018+
2019+ if(start & (sectors_per_block - 1))
2020+ return 0;
2021+
2022 nr_blocks = nr_sectors / sectors_per_block;
2023 start /= sectors_per_block;
2024
2025 for (i = 0; i < nr_blocks; i++)
2026 blocks[i] = start++;
2027+
2028+ return 1;
2029 }
2030
2031 inline int lvm_get_blksize(kdev_t dev)
2032@@ -291,6 +313,8 @@
2033
2034 /*
2035 * writes a COW exception table sector to disk (HM)
2036+ *
2037+ * We need to hold a write lock on lv_snap->lv_lock.
2038 */
2039 int lvm_write_COW_table_block(vg_t * vg, lv_t *lv_snap)
2040 {
2041@@ -309,6 +333,10 @@
2042 * if there is no exception storage space free any longer --> release snapshot.
2043 *
2044 * this routine gets called for each _first_ write to a physical chunk.
2045+ *
2046+ * We need to hold a write lock on lv_snap->lv_lock. It is assumed that
2047+ * lv->lv_block_exception is non-NULL (checked by lvm_snapshot_remap_block())
2048+ * when this function is called.
2049 */
2050 int lvm_snapshot_COW(kdev_t org_phys_dev,
2051 unsigned long org_phys_sector,
2052@@ -318,6 +346,7 @@
2053 {
2054 const char * reason;
2055 unsigned long org_start, snap_start, snap_phys_dev, virt_start, pe_off;
2056+ unsigned long phys_start;
2057 int idx = lv_snap->lv_remap_ptr, chunk_size = lv_snap->lv_chunk_size;
2058 struct kiobuf * iobuf;
2059 unsigned long blocks[KIO_MAX_SECTORS];
2060@@ -352,8 +381,8 @@
2061
2062 iobuf = lv_snap->lv_iobuf;
2063
2064- blksize_org = lvm_get_blksize(org_phys_dev);
2065- blksize_snap = lvm_get_blksize(snap_phys_dev);
2066+ blksize_org = lvm_sectsize(org_phys_dev);
2067+ blksize_snap = lvm_sectsize(snap_phys_dev);
2068 max_blksize = max(blksize_org, blksize_snap);
2069 min_blksize = min(blksize_org, blksize_snap);
2070 max_sectors = KIO_MAX_SECTORS * (min_blksize>>9);
2071@@ -361,6 +390,9 @@
2072 if (chunk_size % (max_blksize>>9))
2073 goto fail_blksize;
2074
2075+ /* Don't change org_start, we need it to fill in the exception table */
2076+ phys_start = org_start;
2077+
2078 while (chunk_size)
2079 {
2080 nr_sectors = min(chunk_size, max_sectors);
2081@@ -368,17 +400,24 @@
2082
2083 iobuf->length = nr_sectors << 9;
2084
2085- lvm_snapshot_prepare_blocks(blocks, org_start,
2086- nr_sectors, blksize_org);
2087+ if (!lvm_snapshot_prepare_blocks(blocks, phys_start,
2088+ nr_sectors, blksize_org))
2089+ goto fail_prepare;
2090+
2091 if (__brw_kiovec(READ, 1, &iobuf, org_phys_dev, blocks,
2092 blksize_org, lv_snap) != (nr_sectors<<9))
2093 goto fail_raw_read;
2094
2095- lvm_snapshot_prepare_blocks(blocks, snap_start,
2096- nr_sectors, blksize_snap);
2097+ if (!lvm_snapshot_prepare_blocks(blocks, snap_start,
2098+ nr_sectors, blksize_snap))
2099+ goto fail_prepare;
2100+
2101 if (__brw_kiovec(WRITE, 1, &iobuf, snap_phys_dev, blocks,
2102 blksize_snap, lv_snap) != (nr_sectors<<9))
2103 goto fail_raw_write;
2104+
2105+ phys_start += nr_sectors;
2106+ snap_start += nr_sectors;
2107 }
2108
2109 #ifdef DEBUG_SNAPSHOT
2110@@ -418,6 +457,11 @@
2111 fail_blksize:
2112 reason = "blocksize error";
2113 goto out;
2114+
2115+fail_prepare:
2116+ reason = "couldn't prepare kiovec blocks "
2117+ "(start probably isn't block aligned)";
2118+ goto out;
2119 }
2120
2121 int lvm_snapshot_alloc_iobuf_pages(struct kiobuf * iobuf, int sectors)
2122@@ -588,7 +632,7 @@
2123 snap_phys_dev = lv_snap->lv_block_exception[idx].rdev_new;
2124 snap_pe_start = lv_snap->lv_block_exception[idx - (idx % COW_entries_per_pe)].rsector_new - lv_snap->lv_chunk_size;
2125
2126- blksize_snap = lvm_get_blksize(snap_phys_dev);
2127+ blksize_snap = lvm_sectsize(snap_phys_dev);
2128
2129 COW_entries_per_block = blksize_snap / sizeof(lv_COW_table_disk_t);
2130 idx_COW_table = idx % COW_entries_per_pe % COW_entries_per_block;
2131@@ -637,7 +681,7 @@
2132 idx++;
2133 snap_phys_dev = lv_snap->lv_block_exception[idx].rdev_new;
2134 snap_pe_start = lv_snap->lv_block_exception[idx - (idx % COW_entries_per_pe)].rsector_new - lv_snap->lv_chunk_size;
2135- blksize_snap = lvm_get_blksize(snap_phys_dev);
2136+ blksize_snap = lvm_sectsize(snap_phys_dev);
2137 blocks[0] = snap_pe_start >> (blksize_snap >> 10);
2138 } else blocks[0]++;
2139
2140--- linux/drivers/md/lvm-fs.c.orig Sat Oct 20 20:50:29 2001
2141+++ linux/drivers/md/lvm-fs.c Sat Oct 20 20:36:55 2001
2142@@ -3,7 +3,7 @@
2143 *
2144 * Copyright (C) 2001 Sistina Software
2145 *
2146- * January,February 2001
2147+ * January-April 2001
2148 *
2149 * LVM driver is free software; you can redistribute it and/or modify
2150 * it under the terms of the GNU General Public License as published by
2151@@ -26,6 +26,10 @@
2152 * Changelog
2153 *
2154 * 11/01/2001 - First version (Joe Thornber)
2155+ * 21/03/2001 - added display of stripes and stripe size (HM)
2156+ * 04/10/2001 - corrected devfs_register() call in lvm_init_fs()
2157+ * 11/04/2001 - don't devfs_register("lvm") as user-space always does it
2158+ * 10/05/2001 - show more of PV name in /proc/lvm/global
2159 *
2160 */
2161
2162@@ -38,6 +42,7 @@
2163
2164 #include <linux/devfs_fs_kernel.h>
2165 #include <linux/proc_fs.h>
2166+#include <linux/init.h>
2167 #include <linux/lvm.h>
2168
2169 #include "lvm-internal.h"
2170@@ -58,7 +63,9 @@
2171
2172 static void _show_uuid(const char *src, char *b, char *e);
2173
2174+#if 0
2175 static devfs_handle_t lvm_devfs_handle;
2176+#endif
2177 static devfs_handle_t vg_devfs_handle[MAX_VG];
2178 static devfs_handle_t ch_devfs_handle[MAX_VG];
2179 static devfs_handle_t lv_devfs_handle[MAX_LV];
2180@@ -69,14 +76,16 @@
2181 /* inline functions */
2182
2183 /* public interface */
2184-void lvm_init_fs() {
2185+void __init lvm_init_fs() {
2186 struct proc_dir_entry *pde;
2187
2188+/* User-space has already registered this */
2189+#if 0
2190 lvm_devfs_handle = devfs_register(
2191- 0 , "lvm", 0, 0, LVM_CHAR_MAJOR,
2192+ 0 , "lvm", 0, LVM_CHAR_MAJOR, 0,
2193 S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP,
2194 &lvm_chr_fops, NULL);
2195-
2196+#endif
2197 lvm_proc_dir = create_proc_entry(LVM_DIR, S_IFDIR, &proc_root);
2198 if (lvm_proc_dir) {
2199 lvm_proc_vg_subdir = create_proc_entry(LVM_VG_SUBDIR, S_IFDIR,
2200@@ -87,8 +96,9 @@
2201 }
2202
2203 void lvm_fin_fs() {
2204+#if 0
2205 devfs_unregister (lvm_devfs_handle);
2206-
2207+#endif
2208 remove_proc_entry(LVM_GLOBAL, lvm_proc_dir);
2209 remove_proc_entry(LVM_VG_SUBDIR, lvm_proc_dir);
2210 remove_proc_entry(LVM_DIR, &proc_root);
2211@@ -137,8 +147,14 @@
2212
2213 if(vg_ptr->vg_dir_pde) {
2214 remove_proc_entry(LVM_LV_SUBDIR, vg_ptr->vg_dir_pde);
2215+ vg_ptr->lv_subdir_pde = NULL;
2216+
2217 remove_proc_entry(LVM_PV_SUBDIR, vg_ptr->vg_dir_pde);
2218+ vg_ptr->pv_subdir_pde = NULL;
2219+
2220 remove_proc_entry("group", vg_ptr->vg_dir_pde);
2221+ vg_ptr->vg_dir_pde = NULL;
2222+
2223 remove_proc_entry(vg_ptr->vg_name, lvm_proc_vg_subdir);
2224 }
2225 }
2226@@ -150,7 +166,7 @@
2227 return name;
2228 }
2229
2230-void lvm_fs_create_lv(vg_t *vg_ptr, lv_t *lv) {
2231+devfs_handle_t lvm_fs_create_lv(vg_t *vg_ptr, lv_t *lv) {
2232 struct proc_dir_entry *pde;
2233 const char *name = _basename(lv->lv_name);
2234
2235@@ -165,6 +181,7 @@
2236 pde->read_proc = _proc_read_lv;
2237 pde->data = lv;
2238 }
2239+ return lv_devfs_handle[MINOR(lv->lv_dev)];
2240 }
2241
2242 void lvm_fs_remove_lv(vg_t *vg_ptr, lv_t *lv) {
2243@@ -256,6 +273,12 @@
2244 sz += sprintf(page + sz, "number: %u\n", lv->lv_number);
2245 sz += sprintf(page + sz, "open: %u\n", lv->lv_open);
2246 sz += sprintf(page + sz, "allocation: %u\n", lv->lv_allocation);
2247+ if(lv->lv_stripes > 1) {
2248+ sz += sprintf(page + sz, "stripes: %u\n",
2249+ lv->lv_stripes);
2250+ sz += sprintf(page + sz, "stripesize: %u\n",
2251+ lv->lv_stripesize);
2252+ }
2253 sz += sprintf(page + sz, "device: %02u:%02u\n",
2254 MAJOR(lv->lv_dev), MINOR(lv->lv_dev));
2255
2256@@ -304,8 +327,8 @@
2257
2258 #ifdef DEBUG_LVM_PROC_GET_INFO
2259 printk(KERN_DEBUG
2260- "%s - lvm_proc_get_global_info CALLED pos: %lu count: %d whence: %d\n",
2261- lvm_name, pos, count, whence);
2262+ "%s - lvm_proc_get_global_info CALLED pos: %lu count: %d\n",
2263+ lvm_name, pos, count);
2264 #endif
2265
2266 if(pos != 0 && buf != NULL)
2267@@ -361,7 +384,7 @@
2268 #endif
2269 " %s\n\n"
2270 "Total: %d VG%s %d PV%s %d LV%s ",
2271- lvm_short_version,
2272+ lvm_version,
2273 vg_counter, vg_counter == 1 ? "" : "s",
2274 pv_counter, pv_counter == 1 ? "" : "s",
2275 lv_counter, lv_counter == 1 ? "" : "s");
2276@@ -564,7 +587,7 @@
2277 allocation_flag = 'A';
2278 if (!(pv->pv_allocatable & PV_ALLOCATABLE))
2279 allocation_flag = 'N';
2280- pv_name = strrchr(pv->pv_name+1,'/');
2281+ pv_name = strchr(pv->pv_name+1,'/');
2282 if ( pv_name == 0) pv_name = pv->pv_name;
2283 else pv_name++;
2284 sz = sprintf(buf,
2285diff -ruN -X /home/joe/packages/dontdiff linux_2.4.1/drivers/md/lvm-snap.h linux/drivers/md/lvm-snap.h
2286--- linux_2.4.1/drivers/md/lvm-snap.h Fri Feb 16 14:51:26 2001
2287+++ linux/drivers/md/lvm-snap.h Thu Jan 1 01:00:00 1970
2288@@ -1,47 +0,0 @@
2289-/*
2290- * kernel/lvm-snap.h
2291- *
2292- * Copyright (C) 2001 Sistina Software
2293- *
2294- *
2295- * LVM driver is free software; you can redistribute it and/or modify
2296- * it under the terms of the GNU General Public License as published by
2297- * the Free Software Foundation; either version 2, or (at your option)
2298- * any later version.
2299- *
2300- * LVM driver is distributed in the hope that it will be useful,
2301- * but WITHOUT ANY WARRANTY; without even the implied warranty of
2302- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2303- * GNU General Public License for more details.
2304- *
2305- * You should have received a copy of the GNU General Public License
2306- * along with GNU CC; see the file COPYING. If not, write to
2307- * the Free Software Foundation, 59 Temple Place - Suite 330,
2308- * Boston, MA 02111-1307, USA.
2309- *
2310- */
2311-
2312-/*
2313- * Changelog
2314- *
2315- * 05/01/2001:Joe Thornber - Factored this file out of lvm.c
2316- *
2317- */
2318-
2319-#ifndef LVM_SNAP_H
2320-#define LVM_SNAP_H
2321-
2322-/* external snapshot calls */
2323-extern inline int lvm_get_blksize(kdev_t);
2324-extern int lvm_snapshot_alloc(lv_t *);
2325-extern void lvm_snapshot_fill_COW_page(vg_t *, lv_t *);
2326-extern int lvm_snapshot_COW(kdev_t, ulong, ulong, ulong, lv_t *);
2327-extern int lvm_snapshot_remap_block(kdev_t *, ulong *, ulong, lv_t *);
2328-extern void lvm_snapshot_release(lv_t *);
2329-extern int lvm_write_COW_table_block(vg_t *, lv_t *);
2330-extern inline void lvm_hash_link(lv_block_exception_t *,
2331- kdev_t, ulong, lv_t *);
2332-extern int lvm_snapshot_alloc_hash_table(lv_t *);
2333-extern void lvm_drop_snapshot(lv_t *, const char *);
2334-
2335-#endif
This page took 0.476978 seconds and 4 git commands to generate.