4 * Copyright (C) 1997 - 2000 Heinz Mauelshagen, Germany
6 * February-November 1997
7 * April-May,July-August,November 1998
8 * January-March,May,July,September,October 1999
9 * January,February 2000
12 * LVM driver is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2, or (at your option)
17 * LVM driver is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with GNU CC; see the file COPYING. If not, write to
24 * the Free Software Foundation, 59 Temple Place - Suite 330,
25 * Boston, MA 02111-1307, USA.
32 * 09/11/1997 - added chr ioctls VG_STATUS_GET_COUNT
33 * and VG_STATUS_GET_NAMELIST
34 * 18/01/1998 - change lvm_chr_open/close lock handling
35 * 30/04/1998 - changed LV_STATUS ioctl to LV_STATUS_BYNAME and
36 * - added LV_STATUS_BYINDEX ioctl
37 * - used lvm_status_byname_req_t and
38 * lvm_status_byindex_req_t vars
39 * 04/05/1998 - added multiple device support
40 * 08/05/1998 - added support to set/clear extendable flag in volume group
41 * 09/05/1998 - changed output of lvm_proc_get_info() because of
42 * support for free (eg. longer) logical volume names
43 * 12/05/1998 - added spin_locks (thanks to Pascal van Dam
44 * <pascal@ramoth.xs4all.nl>)
45 * 25/05/1998 - fixed handling of locked PEs in lvm_map() and lvm_chr_ioctl()
46 * 26/05/1998 - reactivated verify_area by access_ok
47 * 07/06/1998 - used vmalloc/vfree instead of kmalloc/kfree to go
48 * beyond 128/256 KB max allocation limit per call
49 * - #ifdef blocked spin_lock calls to avoid compile errors
51 * 11/06/1998 - another enhancement to spinlock code in lvm_chr_open()
52 * and use of LVM_VERSION_CODE instead of my own macros
53 * (thanks to Michael Marxmeier <mike@msede.com>)
54 * 07/07/1998 - added statistics in lvm_map()
55 * 08/07/1998 - saved statistics in lvm_do_lv_extend_reduce()
56 * 25/07/1998 - used __initfunc macro
57 * 02/08/1998 - changes for official char/block major numbers
58 * 07/08/1998 - avoided init_module() and cleanup_module() to be static
59 * 30/08/1998 - changed VG lv_open counter from sum of LV lv_open counters
60 * to sum of LVs open (no matter how often each is)
61 * 01/09/1998 - fixed lvm_gendisk.part[] index error
62 * 07/09/1998 - added copying of lv_current_pe-array
63 * in LV_STATUS_BYINDEX ioctl
64 * 17/11/1998 - added KERN_* levels to printk
65 * 13/01/1999 - fixed LV index bug in lvm_do_lv_create() which hit lvrename
66 * 07/02/1999 - fixed spinlock handling bug in case of LVM_RESET
67 * by moving spinlock code from lvm_chr_open()
69 * - added LVM_LOCK_LVM ioctl to lvm_chr_ioctl()
70 * - allowed LVM_RESET and retrieval commands to go ahead;
71 * only other update ioctls are blocked now
72 * - fixed pv->pe to NULL for pv_status
73 * - using lv_req structure in lvm_chr_ioctl() now
74 * - fixed NULL ptr reference bug in lvm_do_lv_extend_reduce()
75 * caused by uncontiguous PV array in lvm_chr_ioctl(VG_REDUCE)
76 * 09/02/1999 - changed BLKRASET and BLKRAGET in lvm_chr_ioctl() to
77 * handle lgoical volume private read ahead sector
78 * - implemented LV read_ahead handling with lvm_blk_read()
80 * 10/02/1999 - implemented 2.[12].* support function lvm_hd_name()
81 * to be used in drivers/block/genhd.c by disk_name()
82 * 12/02/1999 - fixed index bug in lvm_blk_ioctl(), HDIO_GETGEO
83 * - enhanced gendisk insert/remove handling
84 * 16/02/1999 - changed to dynamic block minor number allocation to
85 * have as much as 99 volume groups with 256 logical volumes
86 * as the grand total; this allows having 1 volume group with
87 * up to 256 logical volumes in it
88 * 21/02/1999 - added LV open count information to proc filesystem
89 * - substituted redundant LVM_RESET code by calls
90 * to lvm_do_vg_remove()
91 * 22/02/1999 - used schedule_timeout() to be more responsive
92 * in case of lvm_do_vg_remove() with lots of logical volumes
93 * 19/03/1999 - fixed NULL pointer bug in module_init/lvm_init
94 * 17/05/1999 - used DECLARE_WAIT_QUEUE_HEAD macro (>2.3.0)
95 * - enhanced lvm_hd_name support
96 * 03/07/1999 - avoided use of KERNEL_VERSION macro based ifdefs and
97 * memcpy_tofs/memcpy_fromfs macro redefinitions
98 * 06/07/1999 - corrected reads/writes statistic counter copy in case
99 * of striped logical volume
100 * 28/07/1999 - implemented snapshot logical volumes
102 * - LV_STATUS_BYINDEX
107 * - new lvm_snapshot_remap_block
108 * - new lvm_snapshot_remap_new_block
109 * 08/10/1999 - implemented support for multiple snapshots per
110 * original logical volume
111 * 12/10/1999 - support for 2.3.19
112 * 11/11/1999 - support for 2.3.28
113 * 21/11/1999 - changed lvm_map() interface to buffer_head based
114 * 19/12/1999 - support for 2.3.33
115 * 01/01/2000 - changed locking concept in lvm_map(),
116 * lvm_do_vg_create() and lvm_do_lv_remove()
117 * 15/01/2000 - fixed PV_FLUSH bug in lvm_chr_ioctl()
118 * 24/01/2000 - ported to 2.3.40 including Alan Cox's pointer changes etc.
119 * 29/01/2000 - used kmalloc/kfree again for all small structures
120 * 20/01/2000 - cleaned up lvm_chr_ioctl by moving code
121 * to seperated functions
122 * - avoided "/dev/" in proc filesystem output
123 * - avoided inline strings functions lvm_strlen etc.
124 * 14/02/2000 - support for 2.3.43
125 * - integrated Andrea Arcangeli's snapshot code
126 * 07/12/2000 - make sure lvm_make_request_fn returns correct value - 0 or 1 - NeilBrown
131 static char *lvm_version
= "LVM version 0.8final by Heinz Mauelshagen (15/02/2000)\n";
132 static char *lvm_short_version
= "version 0.8final (15/02/2000)";
134 #define MAJOR_NR LVM_BLK_MAJOR
135 #define DEVICE_OFF(device)
137 #include <linux/config.h>
138 #include <linux/version.h>
143 #include <linux/modversions.h>
146 #include <linux/module.h>
148 #include <linux/kernel.h>
149 #include <linux/vmalloc.h>
150 #include <linux/slab.h>
151 #include <linux/init.h>
153 #include <linux/hdreg.h>
154 #include <linux/stat.h>
155 #include <linux/fs.h>
156 #include <linux/proc_fs.h>
157 #include <linux/blkdev.h>
158 #include <linux/genhd.h>
159 #include <linux/locks.h>
160 #include <linux/smp_lock.h>
161 #include <asm/ioctl.h>
162 #include <asm/segment.h>
163 #include <asm/uaccess.h>
165 #ifdef CONFIG_KERNELD
166 #include <linux/kerneld.h>
169 #define LOCAL_END_REQUEST
171 #include <linux/blk.h>
172 #include <linux/blkpg.h>
174 #include <linux/errno.h>
175 #include <linux/lvm.h>
177 #define LVM_CORRECT_READ_AHEAD(a) \
178 (((a) < LVM_MIN_READ_AHEAD || (a) > LVM_MAX_READ_AHEAD) \
179 ? LVM_MAX_READ_AHEAD : (a))
182 # define WRITEA WRITE
186 * External function prototypes
189 int init_module(void);
190 void cleanup_module(void);
192 extern int lvm_init(void);
195 static void lvm_dummy_device_request(request_queue_t
*);
196 #define DEVICE_REQUEST lvm_dummy_device_request
198 static int lvm_make_request_fn(request_queue_t
*, int, struct buffer_head
*);
199 static void lvm_plug_device_noop(request_queue_t
*, kdev_t
);
201 static int lvm_blk_ioctl(struct inode
*, struct file
*, uint
, ulong
);
202 static int lvm_blk_open(struct inode
*, struct file
*);
204 static int lvm_chr_open(struct inode
*, struct file
*);
206 static int lvm_chr_close(struct inode
*, struct file
*);
207 static int lvm_blk_close(struct inode
*, struct file
*);
209 static int lvm_chr_ioctl(struct inode
*, struct file
*, uint
, ulong
);
211 #if defined CONFIG_LVM_PROC_FS && defined CONFIG_PROC_FS
212 static int lvm_proc_get_info(char *, char **, off_t
, int);
213 static int (*lvm_proc_get_info_ptr
) (char *, char **, off_t
, int) =
218 void lvm_hd_name(char *, int);
220 /* End external function prototypes */
224 * Internal function prototypes
226 static void lvm_init_vars(void);
228 /* external snapshot calls */
229 int lvm_snapshot_remap_block(kdev_t
*, ulong
*, ulong
, lv_t
*);
230 int lvm_snapshot_COW(kdev_t
, ulong
, ulong
, ulong
, lv_t
*);
231 int lvm_snapshot_alloc(lv_t
*);
232 void lvm_snapshot_release(lv_t
*);
235 extern void (*lvm_hd_name_ptr
) (char *, int);
237 static int lvm_map(struct buffer_head
*, int);
238 static int lvm_do_lock_lvm(void);
239 static int lvm_do_le_remap(vg_t
*, void *);
240 static int lvm_do_pe_lock_unlock(vg_t
*r
, void *);
241 static int lvm_do_vg_create(int, void *);
242 static int lvm_do_vg_extend(vg_t
*, void *);
243 static int lvm_do_vg_reduce(vg_t
*, void *);
244 static int lvm_do_vg_remove(int);
245 static int lvm_do_lv_create(int, char *, lv_t
*);
246 static int lvm_do_lv_remove(int, char *, int);
247 static int lvm_do_lv_extend_reduce(int, char *, lv_t
*);
248 static int lvm_do_lv_status_byname(vg_t
*r
, void *);
249 static int lvm_do_lv_status_byindex(vg_t
*, void *arg
);
250 static int lvm_do_pv_change(vg_t
*, void*);
251 static int lvm_do_pv_status(vg_t
*, void *);
252 static void lvm_geninit(struct gendisk
*);
254 static struct inode
*lvm_get_inode(kdev_t
);
255 void lvm_clear_inode(struct inode
*);
257 /* END Internal function prototypes */
260 /* volume group descriptor area pointers */
261 static vg_t
*vg
[ABS_MAX_VG
];
262 static pv_t
*pvp
= NULL
;
263 static lv_t
*lvp
= NULL
;
264 static pe_t
*pep
= NULL
;
265 static pe_t
*pep1
= NULL
;
268 /* map from block minor number to VG and LV numbers */
273 static vg_lv_map_t vg_lv_map
[ABS_MAX_LV
];
276 /* Request structures (lvm_chr_ioctl()) */
277 static pv_change_req_t pv_change_req
;
278 static pv_flush_req_t pv_flush_req
;
279 static pv_status_req_t pv_status_req
;
280 static pe_lock_req_t pe_lock_req
;
281 static le_remap_req_t le_remap_req
;
282 static lv_req_t lv_req
;
284 #ifdef LVM_TOTAL_RESET
285 static int lvm_reset_spindown
= 0;
288 static char pv_name
[NAME_LEN
];
289 /* static char rootvg[NAME_LEN] = { 0, }; */
290 static uint lv_open
= 0;
291 const char *const lvm_name
= LVM_NAME
;
293 static int loadtime
= 0;
294 static uint vg_count
= 0;
295 static long lvm_chr_open_count
= 0;
296 static ushort lvm_iop_version
= LVM_DRIVER_IOP_VERSION
;
297 static DECLARE_WAIT_QUEUE_HEAD(lvm_snapshot_wait
);
298 static DECLARE_WAIT_QUEUE_HEAD(lvm_wait
);
299 static DECLARE_WAIT_QUEUE_HEAD(lvm_map_wait
);
301 static spinlock_t lvm_lock
= SPIN_LOCK_UNLOCKED
;
303 static devfs_handle_t lvm_devfs_handle
;
304 static devfs_handle_t vg_devfs_handle
[MAX_VG
];
305 static devfs_handle_t ch_devfs_handle
[MAX_VG
];
306 static devfs_handle_t lv_devfs_handle
[MAX_LV
];
308 static struct file_operations lvm_chr_fops
=
312 release
: lvm_chr_close
,
313 ioctl
: lvm_chr_ioctl
,
316 static struct block_device_operations lvm_blk_dops
=
319 release
: lvm_blk_close
,
323 /* gendisk structures */
324 static struct hd_struct lvm_hd_struct
[MAX_LV
];
325 static int lvm_blocksizes
[MAX_LV
] =
327 static int lvm_size
[MAX_LV
] =
329 static struct gendisk lvm_gendisk
=
331 MAJOR_NR
, /* major # */
332 LVM_NAME
, /* name of major */
333 0, /* number of times minor is shifted
335 1, /* maximum partitions per device */
336 lvm_hd_struct
, /* partition table */
337 lvm_size
, /* device size in blocks, copied
339 MAX_LV
, /* number or real devices */
341 NULL
, /* pointer to next gendisk struct (internal) */
347 * Module initialization...
349 int init_module(void)
352 * Driver initialization...
355 __initfunc(int lvm_init(void))
357 int __init
lvm_init(void)
359 #endif /* #ifdef MODULE */
361 struct gendisk
*gendisk_ptr
= NULL
;
363 if (register_chrdev(LVM_CHAR_MAJOR
, lvm_name
, &lvm_chr_fops
) < 0) {
364 printk(KERN_ERR
"%s -- register_chrdev failed\n", lvm_name
);
367 if (register_blkdev(MAJOR_NR
, lvm_name
, &lvm_blk_dops
) < 0) {
368 printk("%s -- register_blkdev failed\n", lvm_name
);
369 if (unregister_chrdev(LVM_CHAR_MAJOR
, lvm_name
) < 0)
370 printk(KERN_ERR
"%s -- unregister_chrdev failed\n", lvm_name
);
374 lvm_devfs_handle
= devfs_register(
375 0 , "lvm", 0, 0, LVM_CHAR_MAJOR
,
376 S_IFCHR
| S_IRUSR
| S_IWUSR
| S_IRGRP
,
377 &lvm_chr_fops
, NULL
);
379 #if defined CONFIG_LVM_PROC_FS && defined CONFIG_PROC_FS
380 create_proc_info_entry(LVM_NAME
, S_IFREG
| S_IRUGO
,
381 &proc_root
, lvm_proc_get_info_ptr
);
385 lvm_geninit(&lvm_gendisk
);
387 /* insert our gendisk at the corresponding major */
388 if (gendisk_head
!= NULL
) {
389 gendisk_ptr
= gendisk_head
;
390 while (gendisk_ptr
->next
!= NULL
&&
391 gendisk_ptr
->major
> lvm_gendisk
.major
) {
392 gendisk_ptr
= gendisk_ptr
->next
;
394 lvm_gendisk
.next
= gendisk_ptr
->next
;
395 gendisk_ptr
->next
= &lvm_gendisk
;
397 gendisk_head
= &lvm_gendisk
;
398 lvm_gendisk
.next
= NULL
;
402 /* reference from drivers/block/genhd.c */
403 lvm_hd_name_ptr
= lvm_hd_name
;
406 blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR
), DEVICE_REQUEST
);
407 blk_queue_make_request(BLK_DEFAULT_QUEUE(MAJOR_NR
), lvm_make_request_fn
);
408 blk_queue_pluggable(BLK_DEFAULT_QUEUE(MAJOR_NR
), lvm_plug_device_noop
);
409 /* optional read root VGDA */
411 if ( *rootvg != 0) vg_read_with_pv_and_lv ( rootvg, &vg);
421 " successfully initialized\n",
422 lvm_version
, lvm_name
);
425 } /* init_module() / lvm_init() */
432 void cleanup_module(void)
434 struct gendisk
*gendisk_ptr
= NULL
, *gendisk_ptr_prev
= NULL
;
436 devfs_unregister (lvm_devfs_handle
);
438 if (unregister_chrdev(LVM_CHAR_MAJOR
, lvm_name
) < 0) {
439 printk(KERN_ERR
"%s -- unregister_chrdev failed\n", lvm_name
);
441 if (unregister_blkdev(MAJOR_NR
, lvm_name
) < 0) {
442 printk(KERN_ERR
"%s -- unregister_blkdev failed\n", lvm_name
);
444 blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR
));
446 gendisk_ptr
= gendisk_ptr_prev
= gendisk_head
;
447 while (gendisk_ptr
!= NULL
) {
448 if (gendisk_ptr
== &lvm_gendisk
)
450 gendisk_ptr_prev
= gendisk_ptr
;
451 gendisk_ptr
= gendisk_ptr
->next
;
453 /* delete our gendisk from chain */
454 if (gendisk_ptr
== &lvm_gendisk
)
455 gendisk_ptr_prev
->next
= gendisk_ptr
->next
;
457 blk_size
[MAJOR_NR
] = NULL
;
458 blksize_size
[MAJOR_NR
] = NULL
;
460 #if defined CONFIG_LVM_PROC_FS && defined CONFIG_PROC_FS
461 remove_proc_entry(LVM_NAME
, &proc_root
);
465 /* reference from linux/drivers/block/genhd.c */
466 lvm_hd_name_ptr
= NULL
;
469 printk(KERN_INFO
"%s -- Module successfully deactivated\n", lvm_name
);
472 } /* void cleanup_module() */
473 #endif /* #ifdef MODULE */
477 * support function to initialize lvm variables
480 __initfunc(void lvm_init_vars(void))
482 void __init
lvm_init_vars(void)
487 loadtime
= CURRENT_TIME
;
489 pe_lock_req
.lock
= UNLOCK_PE
;
490 pe_lock_req
.data
.lv_dev
= pe_lock_req
.data
.pv_dev
= 0;
491 pe_lock_req
.data
.pv_offset
= 0;
493 /* Initialize VG pointers */
494 for (v
= 0; v
< ABS_MAX_VG
; v
++) vg
[v
] = NULL
;
496 /* Initialize LV -> VG association */
497 for (v
= 0; v
< ABS_MAX_LV
; v
++) {
498 /* index ABS_MAX_VG never used for real VG */
499 vg_lv_map
[v
].vg_number
= ABS_MAX_VG
;
500 vg_lv_map
[v
].lv_number
= -1;
504 } /* lvm_init_vars() */
507 /********************************************************************
509 * Character device functions
511 ********************************************************************/
514 * character device open routine
516 static int lvm_chr_open(struct inode
*inode
,
519 int minor
= MINOR(inode
->i_rdev
);
523 "%s -- lvm_chr_open MINOR: %d VG#: %d mode: 0x%X lock: %d\n",
524 lvm_name
, minor
, VG_CHR(minor
), file
->f_mode
, lock
);
527 /* super user validation */
528 if (!capable(CAP_SYS_ADMIN
)) return -EACCES
;
530 /* Group special file open */
531 if (VG_CHR(minor
) > MAX_VG
) return -ENXIO
;
533 lvm_chr_open_count
++;
535 } /* lvm_chr_open() */
539 * character device i/o-control routine
541 * Only one changing process can do changing ioctl at one time,
545 static int lvm_chr_ioctl(struct inode
*inode
, struct file
*file
,
546 uint command
, ulong a
)
548 int minor
= MINOR(inode
->i_rdev
);
549 uint extendable
, l
, v
;
550 void *arg
= (void *) a
;
552 vg_t
* vg_ptr
= vg
[VG_CHR(minor
)];
554 /* otherwise cc will complain about unused variables */
560 "%s -- lvm_chr_ioctl: command: 0x%X MINOR: %d "
561 "VG#: %d mode: 0x%X\n",
562 lvm_name
, command
, minor
, VG_CHR(minor
), file
->f_mode
);
565 #ifdef LVM_TOTAL_RESET
566 if (lvm_reset_spindown
> 0) return -EACCES
;
569 /* Main command switch */
573 return lvm_do_lock_lvm();
575 case LVM_GET_IOP_VERSION
:
576 /* check lvm version to ensure driver/tools+lib
578 if (copy_to_user(arg
, &lvm_iop_version
, sizeof(ushort
)) != 0)
582 #ifdef LVM_TOTAL_RESET
584 /* lock reset function */
585 lvm_reset_spindown
= 1;
586 for (v
= 0; v
< ABS_MAX_VG
; v
++) {
587 if (vg
[v
] != NULL
) lvm_do_vg_remove(v
);
591 while (GET_USE_COUNT(&__this_module
) < 1)
593 while (GET_USE_COUNT(&__this_module
) > 1)
596 lock
= 0; /* release lock */
597 wake_up_interruptible(&lvm_wait
);
599 #endif /* LVM_TOTAL_RESET */
603 /* remap a logical extent (after moving the physical extent) */
604 return lvm_do_le_remap(vg_ptr
,arg
);
607 /* lock/unlock i/o to a physical extent to move it to another
608 physical volume (move's done in user space's pvmove) */
609 return lvm_do_pe_lock_unlock(vg_ptr
,arg
);
613 return lvm_do_vg_create(minor
, arg
);
616 /* remove an inactive VGDA */
617 return lvm_do_vg_remove(minor
);
620 /* extend a volume group */
621 return lvm_do_vg_extend(vg_ptr
,arg
);
624 /* reduce a volume group */
625 return lvm_do_vg_reduce(vg_ptr
,arg
);
628 case VG_SET_EXTENDABLE
:
629 /* set/clear extendability flag of volume group */
630 if (vg_ptr
== NULL
) return -ENXIO
;
631 if (copy_from_user(&extendable
, arg
, sizeof(extendable
)) != 0)
634 if (extendable
== VG_EXTENDABLE
||
635 extendable
== ~VG_EXTENDABLE
) {
636 if (extendable
== VG_EXTENDABLE
)
637 vg_ptr
->vg_status
|= VG_EXTENDABLE
;
639 vg_ptr
->vg_status
&= ~VG_EXTENDABLE
;
640 } else return -EINVAL
;
645 /* get volume group data (only the vg_t struct) */
646 if (vg_ptr
== NULL
) return -ENXIO
;
647 if (copy_to_user(arg
, vg_ptr
, sizeof(vg_t
)) != 0)
652 case VG_STATUS_GET_COUNT
:
653 /* get volume group count */
654 if (copy_to_user(arg
, &vg_count
, sizeof(vg_count
)) != 0)
659 case VG_STATUS_GET_NAMELIST
:
660 /* get volume group count */
661 for (l
= v
= 0; v
< ABS_MAX_VG
; v
++) {
663 if (copy_to_user(arg
+ l
++ * NAME_LEN
,
676 /* create, remove, extend or reduce a logical volume */
677 if (vg_ptr
== NULL
) return -ENXIO
;
678 if (copy_from_user(&lv_req
, arg
, sizeof(lv_req
)) != 0)
681 if (command
!= LV_REMOVE
) {
682 if (copy_from_user(&lv
, lv_req
.lv
, sizeof(lv_t
)) != 0)
687 return lvm_do_lv_create(minor
, lv_req
.lv_name
, &lv
);
690 return lvm_do_lv_remove(minor
, lv_req
.lv_name
, -1);
694 return lvm_do_lv_extend_reduce(minor
, lv_req
.lv_name
, &lv
);
698 case LV_STATUS_BYNAME
:
699 /* get status of a logical volume by name */
700 return lvm_do_lv_status_byname(vg_ptr
,arg
);
702 case LV_STATUS_BYINDEX
:
703 /* get status of a logical volume by index */
704 return lvm_do_lv_status_byindex(vg_ptr
,arg
);
707 /* change a physical volume */
708 return lvm_do_pv_change(vg_ptr
,arg
);
711 /* get physical volume data (pv_t structure only) */
712 return lvm_do_pv_status(vg_ptr
,arg
);
715 /* physical volume buffer flush/invalidate */
716 if (copy_from_user(&pv_flush_req
, arg
,
717 sizeof(pv_flush_req
)) != 0)
720 for ( v
= 0; v
< ABS_MAX_VG
; v
++) {
722 if ( vg
[v
] == NULL
) continue;
723 for ( p
= 0; p
< vg
[v
]->pv_max
; p
++) {
724 if ( vg
[v
]->pv
[p
] != NULL
&&
725 strcmp ( vg
[v
]->pv
[p
]->pv_name
,
726 pv_flush_req
.pv_name
) == 0) {
727 fsync_dev ( vg
[v
]->pv
[p
]->pv_dev
);
728 invalidate_buffers ( vg
[v
]->pv
[p
]->pv_dev
);
737 "%s -- lvm_chr_ioctl: unknown command %x\n",
743 } /* lvm_chr_ioctl */
747 * character device close routine
749 static int lvm_chr_close(struct inode
*inode
, struct file
*file
)
752 int minor
= MINOR(inode
->i_rdev
);
754 "%s -- lvm_chr_close VG#: %d\n", lvm_name
, VG_CHR(minor
));
758 #ifdef LVM_TOTAL_RESET
759 if (lvm_reset_spindown
> 0) {
760 lvm_reset_spindown
= 0;
761 lvm_chr_open_count
= 1;
765 if (lvm_chr_open_count
> 0) lvm_chr_open_count
--;
766 if (lock
== current
->pid
) {
767 lock
= 0; /* release lock */
768 wake_up_interruptible(&lvm_wait
);
773 } /* lvm_chr_close() */
777 /********************************************************************
779 * Block device functions
781 ********************************************************************/
784 * block device open routine
786 static int lvm_blk_open(struct inode
*inode
, struct file
*file
)
788 int minor
= MINOR(inode
->i_rdev
);
790 vg_t
*vg_ptr
= vg
[VG_BLK(minor
)];
792 #ifdef DEBUG_LVM_BLK_OPEN
794 "%s -- lvm_blk_open MINOR: %d VG#: %d LV#: %d mode: 0x%X\n",
795 lvm_name
, minor
, VG_BLK(minor
), LV_BLK(minor
), file
->f_mode
);
798 #ifdef LVM_TOTAL_RESET
799 if (lvm_reset_spindown
> 0)
803 if (vg_ptr
!= NULL
&&
804 (vg_ptr
->vg_status
& VG_ACTIVE
) &&
805 (lv_ptr
= vg_ptr
->lv
[LV_BLK(minor
)]) != NULL
&&
806 LV_BLK(minor
) >= 0 &&
807 LV_BLK(minor
) < vg_ptr
->lv_max
) {
809 /* Check parallel LV spindown (LV remove) */
810 if (lv_ptr
->lv_status
& LV_SPINDOWN
) return -EPERM
;
812 /* Check inactive LV and open for read/write */
813 if (file
->f_mode
& O_RDWR
) {
814 if (!(lv_ptr
->lv_status
& LV_ACTIVE
)) return -EPERM
;
815 if (!(lv_ptr
->lv_access
& LV_WRITE
)) return -EACCES
;
818 /* be sure to increment VG counter */
819 if (lv_ptr
->lv_open
== 0) vg_ptr
->lv_open
++;
824 #ifdef DEBUG_LVM_BLK_OPEN
826 "%s -- lvm_blk_open MINOR: %d VG#: %d LV#: %d size: %d\n",
827 lvm_name
, minor
, VG_BLK(minor
), LV_BLK(minor
),
834 } /* lvm_blk_open() */
838 * block device i/o-control routine
840 static int lvm_blk_ioctl(struct inode
*inode
, struct file
*file
,
841 uint command
, ulong a
)
843 int minor
= MINOR(inode
->i_rdev
);
844 vg_t
*vg_ptr
= vg
[VG_BLK(minor
)];
845 lv_t
*lv_ptr
= vg_ptr
->lv
[LV_BLK(minor
)];
846 void *arg
= (void *) a
;
847 struct hd_geometry
*hd
= (struct hd_geometry
*) a
;
851 "%s -- lvm_blk_ioctl MINOR: %d command: 0x%X arg: %X "
852 "VG#: %dl LV#: %d\n",
853 lvm_name
, minor
, command
, (ulong
) arg
,
854 VG_BLK(minor
), LV_BLK(minor
));
859 /* return device size */
862 "%s -- lvm_blk_ioctl -- BLKGETSIZE: %u\n",
863 lvm_name
, lv_ptr
->lv_size
);
865 if (put_user(lv_ptr
->lv_size
, (long *)arg
))
871 /* flush buffer cache */
872 if (!capable(CAP_SYS_ADMIN
)) return -EACCES
;
876 "%s -- lvm_blk_ioctl -- BLKFLSBUF\n", lvm_name
);
878 fsync_dev(inode
->i_rdev
);
879 invalidate_buffers(inode
->i_rdev
);
884 /* set read ahead for block device */
885 if (!capable(CAP_SYS_ADMIN
)) return -EACCES
;
889 "%s -- lvm_blk_ioctl -- BLKRASET: %d sectors for %02X:%02X\n",
890 lvm_name
, (long) arg
, MAJOR(inode
->i_rdev
), minor
);
892 if ((long) arg
< LVM_MIN_READ_AHEAD
||
893 (long) arg
> LVM_MAX_READ_AHEAD
)
895 read_ahead
[MAJOR_NR
] = lv_ptr
->lv_read_ahead
= (long) arg
;
900 /* get current read ahead setting */
903 "%s -- lvm_blk_ioctl -- BLKRAGET\n", lvm_name
);
905 if (put_user(lv_ptr
->lv_read_ahead
, (long *)arg
))
911 /* get disk geometry */
914 "%s -- lvm_blk_ioctl -- HDIO_GETGEO\n", lvm_name
);
919 unsigned char heads
= 64;
920 unsigned char sectors
= 32;
922 short cylinders
= lv_ptr
->lv_size
/ heads
/ sectors
;
924 if (copy_to_user((char *) &hd
->heads
, &heads
,
925 sizeof(heads
)) != 0 ||
926 copy_to_user((char *) &hd
->sectors
, §ors
,
927 sizeof(sectors
)) != 0 ||
928 copy_to_user((short *) &hd
->cylinders
,
929 &cylinders
, sizeof(cylinders
)) != 0 ||
930 copy_to_user((long *) &hd
->start
, &start
,
937 "%s -- lvm_blk_ioctl -- cylinders: %d\n",
938 lvm_name
, lv_ptr
->lv_size
/ heads
/ sectors
);
944 /* set access flags of a logical volume */
945 if (!capable(CAP_SYS_ADMIN
)) return -EACCES
;
946 lv_ptr
->lv_access
= (ulong
) arg
;
951 /* set status flags of a logical volume */
952 if (!capable(CAP_SYS_ADMIN
)) return -EACCES
;
953 if (!((ulong
) arg
& LV_ACTIVE
) && lv_ptr
->lv_open
> 1)
955 lv_ptr
->lv_status
= (ulong
) arg
;
959 case LV_SET_ALLOCATION
:
960 /* set allocation flags of a logical volume */
961 if (!capable(CAP_SYS_ADMIN
)) return -EACCES
;
962 lv_ptr
->lv_allocation
= (ulong
) arg
;
968 "%s -- lvm_blk_ioctl: unknown command %d\n",
974 } /* lvm_blk_ioctl() */
978 * block device close routine
980 static int lvm_blk_close(struct inode
*inode
, struct file
*file
)
982 int minor
= MINOR(inode
->i_rdev
);
983 vg_t
*vg_ptr
= vg
[VG_BLK(minor
)];
984 lv_t
*lv_ptr
= vg_ptr
->lv
[LV_BLK(minor
)];
988 "%s -- lvm_blk_close MINOR: %d VG#: %d LV#: %d\n",
989 lvm_name
, minor
, VG_BLK(minor
), LV_BLK(minor
));
992 sync_dev(inode
->i_rdev
);
993 if (lv_ptr
->lv_open
== 1) vg_ptr
->lv_open
--;
999 } /* lvm_blk_close() */
1002 #if defined CONFIG_LVM_PROC_FS && defined CONFIG_PROC_FS
1004 * Support function /proc-Filesystem
1006 #define LVM_PROC_BUF ( i == 0 ? dummy_buf : &buf[sz])
1008 static int lvm_proc_get_info(char *page
, char **start
, off_t pos
, int count
)
1010 int c
, i
, l
, p
, v
, vg_counter
, pv_counter
, lv_counter
, lv_open_counter
,
1011 lv_open_total
, pe_t_bytes
, lv_block_exception_t_bytes
, seconds
;
1014 char allocation_flag
, inactive_flag
, rw_flag
, stripes_flag
;
1015 char *lv_name
, *pv_name
;
1016 static char *buf
= NULL
;
1017 static char dummy_buf
[160]; /* sized for 2 lines */
1023 #ifdef DEBUG_LVM_PROC_GET_INFO
1025 "%s - lvm_proc_get_info CALLED pos: %lu count: %d whence: %d\n",
1026 lvm_name
, pos
, count
, whence
);
1029 if (pos
== 0 || buf
== NULL
) {
1030 sz_last
= vg_counter
= pv_counter
= lv_counter
= lv_open_counter
= \
1031 lv_open_total
= pe_t_bytes
= lv_block_exception_t_bytes
= 0;
1033 /* search for activity */
1034 for (v
= 0; v
< ABS_MAX_VG
; v
++) {
1035 if ((vg_ptr
= vg
[v
]) != NULL
) {
1037 pv_counter
+= vg_ptr
->pv_cur
;
1038 lv_counter
+= vg_ptr
->lv_cur
;
1039 if (vg_ptr
->lv_cur
> 0) {
1040 for (l
= 0; l
< vg
[v
]->lv_max
; l
++) {
1041 if ((lv_ptr
= vg_ptr
->lv
[l
]) != NULL
) {
1042 pe_t_bytes
+= lv_ptr
->lv_allocated_le
;
1043 if (lv_ptr
->lv_block_exception
!= NULL
)
1044 lv_block_exception_t_bytes
+= lv_ptr
->lv_remap_end
;
1045 if (lv_ptr
->lv_open
> 0) {
1047 lv_open_total
+= lv_ptr
->lv_open
;
1054 pe_t_bytes
*= sizeof(pe_t
);
1055 lv_block_exception_t_bytes
*= sizeof(lv_block_exception_t
);
1060 "%s -- kfree %d\n", lvm_name
, __LINE__
);
1065 /* 2 times: first to get size to allocate buffer,
1066 2nd to fill the malloced buffer */
1067 for (i
= 0; i
< 2; i
++) {
1069 sz
+= sprintf(LVM_PROC_BUF
,
1077 "Total: %d VG%s %d PV%s %d LV%s ",
1079 vg_counter
, vg_counter
== 1 ? "" : "s",
1080 pv_counter
, pv_counter
== 1 ? "" : "s",
1081 lv_counter
, lv_counter
== 1 ? "" : "s");
1082 sz
+= sprintf(LVM_PROC_BUF
,
1085 lv_open_counter
== 1 ? "" : "s");
1086 if (lv_open_total
> 0)
1087 sz
+= sprintf(LVM_PROC_BUF
,
1091 sz
+= sprintf(LVM_PROC_BUF
, ")");
1092 sz
+= sprintf(LVM_PROC_BUF
,
1093 "\nGlobal: %lu bytes malloced IOP version: %d ",
1094 vg_counter
* sizeof(vg_t
) +
1095 pv_counter
* sizeof(pv_t
) +
1096 lv_counter
* sizeof(lv_t
) +
1097 pe_t_bytes
+ lv_block_exception_t_bytes
+ sz_last
,
1100 seconds
= CURRENT_TIME
- loadtime
;
1102 loadtime
= CURRENT_TIME
+ seconds
;
1103 if (seconds
/ 86400 > 0) {
1104 sz
+= sprintf(LVM_PROC_BUF
, "%d day%s ",
1106 seconds
/ 86400 == 0 ||
1107 seconds
/ 86400 > 1 ? "s" : "");
1109 sz
+= sprintf(LVM_PROC_BUF
, "%d:%02d:%02d active\n",
1110 (seconds
% 86400) / 3600,
1111 (seconds
% 3600) / 60,
1114 if (vg_counter
> 0) {
1115 for (v
= 0; v
< ABS_MAX_VG
; v
++) {
1117 if ((vg_ptr
= vg
[v
]) != NULL
) {
1118 inactive_flag
= ' ';
1119 if (!(vg_ptr
->vg_status
& VG_ACTIVE
)) inactive_flag
= 'I';
1120 sz
+= sprintf(LVM_PROC_BUF
,
1121 "\nVG: %c%s [%d PV, %d LV/%d open] "
1123 " Usage [KB/PE]: %d /%d total "
1124 "%d /%d used %d /%d free",
1130 vg_ptr
->pe_size
>> 1,
1131 vg_ptr
->pe_size
* vg_ptr
->pe_total
>> 1,
1133 vg_ptr
->pe_allocated
* vg_ptr
->pe_size
>> 1,
1134 vg_ptr
->pe_allocated
,
1135 (vg_ptr
->pe_total
- vg_ptr
->pe_allocated
) *
1136 vg_ptr
->pe_size
>> 1,
1137 vg_ptr
->pe_total
- vg_ptr
->pe_allocated
);
1139 /* physical volumes */
1140 sz
+= sprintf(LVM_PROC_BUF
,
1142 vg_ptr
->pv_cur
== 1 ? ": " : "s:");
1144 for (p
= 0; p
< vg_ptr
->pv_max
; p
++) {
1145 if ((pv_ptr
= vg_ptr
->pv
[p
]) != NULL
) {
1146 inactive_flag
= 'A';
1147 if (!(pv_ptr
->pv_status
& PV_ACTIVE
))
1148 inactive_flag
= 'I';
1149 allocation_flag
= 'A';
1150 if (!(pv_ptr
->pv_allocatable
& PV_ALLOCATABLE
))
1151 allocation_flag
= 'N';
1152 pv_name
= strchr(pv_ptr
->pv_name
+1,'/');
1153 if ( pv_name
== 0) pv_name
= pv_ptr
->pv_name
;
1155 sz
+= sprintf(LVM_PROC_BUF
,
1156 "[%c%c] %-21s %8d /%-6d "
1157 "%8d /%-6d %8d /%-6d",
1162 pv_ptr
->pe_size
>> 1,
1164 pv_ptr
->pe_allocated
*
1165 pv_ptr
->pe_size
>> 1,
1166 pv_ptr
->pe_allocated
,
1168 pv_ptr
->pe_allocated
) *
1169 pv_ptr
->pe_size
>> 1,
1171 pv_ptr
->pe_allocated
);
1173 if (c
< vg_ptr
->pv_cur
)
1174 sz
+= sprintf(LVM_PROC_BUF
,
1179 /* logical volumes */
1180 sz
+= sprintf(LVM_PROC_BUF
,
1182 vg_ptr
->lv_cur
== 1 ? ": " : "s:");
1184 for (l
= 0; l
< vg
[v
]->lv_max
; l
++) {
1185 if ((lv_ptr
= vg_ptr
->lv
[l
]) != NULL
) {
1186 inactive_flag
= 'A';
1187 if (!(lv_ptr
->lv_status
& LV_ACTIVE
))
1188 inactive_flag
= 'I';
1190 if (lv_ptr
->lv_access
& LV_WRITE
)
1192 allocation_flag
= 'D';
1193 if (lv_ptr
->lv_allocation
& LV_CONTIGUOUS
)
1194 allocation_flag
= 'C';
1196 if (lv_ptr
->lv_stripes
> 1)
1198 sz
+= sprintf(LVM_PROC_BUF
,
1204 if (lv_ptr
->lv_stripes
> 1)
1205 sz
+= sprintf(LVM_PROC_BUF
, "%-2d",
1206 lv_ptr
->lv_stripes
);
1208 sz
+= sprintf(LVM_PROC_BUF
, " ");
1209 lv_name
= strrchr(lv_ptr
->lv_name
, '/');
1210 if ( lv_name
== 0) lv_name
= lv_ptr
->lv_name
;
1212 sz
+= sprintf(LVM_PROC_BUF
, "] %-25s", lv_name
);
1213 if (strlen(lv_name
) > 25)
1214 sz
+= sprintf(LVM_PROC_BUF
,
1216 sz
+= sprintf(LVM_PROC_BUF
, "%9d /%-6d ",
1217 lv_ptr
->lv_size
>> 1,
1218 lv_ptr
->lv_size
/ vg
[v
]->pe_size
);
1220 if (lv_ptr
->lv_open
== 0)
1221 sz
+= sprintf(LVM_PROC_BUF
, "close");
1223 sz
+= sprintf(LVM_PROC_BUF
, "%dx open",
1226 if (c
< vg_ptr
->lv_cur
)
1227 sz
+= sprintf(LVM_PROC_BUF
,
1231 if (vg_ptr
->lv_cur
== 0) sz
+= sprintf(LVM_PROC_BUF
, "none");
1232 sz
+= sprintf(LVM_PROC_BUF
, "\n");
1237 if ((buf
= vmalloc(sz
)) == NULL
) {
1239 return sprintf(page
, "%s - vmalloc error at line %d\n",
1240 lvm_name
, __LINE__
);
1252 if (sz
- pos
< count
)
1256 } /* lvm_proc_get_info() */
1257 #endif /* #if defined CONFIG_LVM_PROC_FS && defined CONFIG_PROC_FS */
1261 * block device support function for /usr/src/linux/drivers/block/ll_rw_blk.c
1262 * (see init_module/lvm_init)
1264 static int lvm_map(struct buffer_head
*bh
, int rw
)
1266 int minor
= MINOR(bh
->b_rdev
);
1269 ulong size
= bh
->b_size
>> 9;
1270 ulong rsector_tmp
= bh
->b_rsector
;
1272 kdev_t rdev_tmp
= bh
->b_rdev
;
1274 lv_t
*lv
= vg
[VG_BLK(minor
)]->lv
[LV_BLK(minor
)];
1277 if (!(lv
->lv_status
& LV_ACTIVE
)) {
1279 "%s - lvm_map: ll_rw_blk for inactive LV %s\n",
1280 lvm_name
, lv
->lv_name
);
1284 if ( lv->lv_access & LV_SNAPSHOT)
1285 printk ( "%s -- %02d:%02d block: %lu rw: %d\n", lvm_name, MAJOR ( bh->b_dev), MINOR ( bh->b_dev), bh->b_blocknr, rw);
1288 /* take care of snapshot chunk writes before
1289 check for writable logical volume */
1290 if ((lv
->lv_access
& LV_SNAPSHOT
) &&
1291 MAJOR(bh
->b_rdev
) != 0 &&
1292 MAJOR(bh
->b_rdev
) != MAJOR_NR
&&
1293 (rw
== WRITEA
|| rw
== WRITE
))
1295 printk ( "%s -- doing snapshot write for %02d:%02d[%02d:%02d] b_blocknr: %lu b_rsector: %lu\n", lvm_name
, MAJOR ( bh
->b_dev
), MINOR ( bh
->b_dev
), MAJOR ( bh
->b_rdev
), MINOR ( bh
->b_rdev
), bh
->b_blocknr
, bh
->b_rsector
);
1299 if ((rw
== WRITE
|| rw
== WRITEA
) &&
1300 !(lv
->lv_access
& LV_WRITE
)) {
1302 "%s - lvm_map: ll_rw_blk write for readonly LV %s\n",
1303 lvm_name
, lv
->lv_name
);
1308 "%s - lvm_map minor:%d *rdev: %02d:%02d *rsector: %lu "
1316 if (rsector_tmp
+ size
> lv
->lv_size
) {
1318 "%s - lvm_map *rsector: %lu or size: %lu wrong for"
1319 " minor: %2d\n", lvm_name
, rsector_tmp
, size
, minor
);
1322 rsector_sav
= rsector_tmp
;
1323 rdev_sav
= rdev_tmp
;
1326 /* linear mapping */
1327 if (lv
->lv_stripes
< 2) {
1329 index
= rsector_tmp
/ vg
[VG_BLK(minor
)]->pe_size
;
1330 pe_start
= lv
->lv_current_pe
[index
].pe
;
1331 rsector_tmp
= lv
->lv_current_pe
[index
].pe
+
1332 (rsector_tmp
% vg
[VG_BLK(minor
)]->pe_size
);
1333 rdev_tmp
= lv
->lv_current_pe
[index
].dev
;
1337 "lv_current_pe[%ld].pe: %ld rdev: %02d:%02d rsector:%ld\n",
1339 lv
->lv_current_pe
[index
].pe
,
1345 /* striped mapping */
1348 ulong stripe_length
;
1350 stripe_length
= vg
[VG_BLK(minor
)]->pe_size
* lv
->lv_stripes
;
1351 stripe_index
= (rsector_tmp
% stripe_length
) / lv
->lv_stripesize
;
1352 index
= rsector_tmp
/ stripe_length
+
1353 (stripe_index
% lv
->lv_stripes
) *
1354 (lv
->lv_allocated_le
/ lv
->lv_stripes
);
1355 pe_start
= lv
->lv_current_pe
[index
].pe
;
1356 rsector_tmp
= lv
->lv_current_pe
[index
].pe
+
1357 (rsector_tmp
% stripe_length
) -
1358 (stripe_index
% lv
->lv_stripes
) * lv
->lv_stripesize
-
1359 stripe_index
/ lv
->lv_stripes
*
1360 (lv
->lv_stripes
- 1) * lv
->lv_stripesize
;
1361 rdev_tmp
= lv
->lv_current_pe
[index
].dev
;
1366 "lv_current_pe[%ld].pe: %ld rdev: %02d:%02d rsector:%ld\n"
1367 "stripe_length: %ld stripe_index: %ld\n",
1369 lv
->lv_current_pe
[index
].pe
,
1377 /* handle physical extents on the move */
1378 if (pe_lock_req
.lock
== LOCK_PE
) {
1379 if (rdev_tmp
== pe_lock_req
.data
.pv_dev
&&
1380 rsector_tmp
>= pe_lock_req
.data
.pv_offset
&&
1381 rsector_tmp
< (pe_lock_req
.data
.pv_offset
+
1382 vg
[VG_BLK(minor
)]->pe_size
)) {
1383 sleep_on(&lvm_map_wait
);
1384 rsector_tmp
= rsector_sav
;
1385 rdev_tmp
= rdev_sav
;
1386 goto lvm_second_remap
;
1390 if (rw
== WRITE
|| rw
== WRITEA
)
1391 lv
->lv_current_pe
[index
].writes
++;
1393 lv
->lv_current_pe
[index
].reads
++;
1395 /* snapshot volume exception handling on physical device address base */
1396 if (lv
->lv_access
& (LV_SNAPSHOT
| LV_SNAPSHOT_ORG
)) {
1397 /* original logical volume */
1398 if (lv
->lv_access
& LV_SNAPSHOT_ORG
) {
1399 if (rw
== WRITE
|| rw
== WRITEA
)
1403 /* start with first snapshot and loop thrugh all of them */
1404 for (lv_ptr
= lv
->lv_snapshot_next
;
1406 lv_ptr
= lv_ptr
->lv_snapshot_next
) {
1407 down(&lv
->lv_snapshot_org
->lv_snapshot_sem
);
1408 /* do we still have exception storage for this snapshot free? */
1409 if (lv_ptr
->lv_block_exception
!= NULL
) {
1410 rdev_sav
= rdev_tmp
;
1411 rsector_sav
= rsector_tmp
;
1412 if (!lvm_snapshot_remap_block(&rdev_tmp
,
1416 /* create a new mapping */
1417 lvm_snapshot_COW(rdev_tmp
,
1423 rdev_tmp
= rdev_sav
;
1424 rsector_tmp
= rsector_sav
;
1426 up(&lv
->lv_snapshot_org
->lv_snapshot_sem
);
1430 /* remap snapshot logical volume */
1431 down(&lv
->lv_snapshot_sem
);
1432 if (lv
->lv_block_exception
!= NULL
)
1433 lvm_snapshot_remap_block(&rdev_tmp
, &rsector_tmp
, pe_start
, lv
);
1434 up(&lv
->lv_snapshot_sem
);
1437 bh
->b_rdev
= rdev_tmp
;
1438 bh
->b_rsector
= rsector_tmp
;
1443 buffer_IO_error(bh
);
1449 * internal support functions
1454 * generate "hard disk" name
1456 void lvm_hd_name(char *buf
, int minor
)
1461 if (vg
[VG_BLK(minor
)] == NULL
||
1462 (lv_ptr
= vg
[VG_BLK(minor
)]->lv
[LV_BLK(minor
)]) == NULL
)
1464 len
= strlen(lv_ptr
->lv_name
) - 5;
1465 memcpy(buf
, &lv_ptr
->lv_name
[5], len
);
1473 * this one never should be called...
1475 static void lvm_dummy_device_request(request_queue_t
* t
)
1478 "%s -- oops, got lvm request for %02d:%02d [sector: %lu]\n",
1480 MAJOR(CURRENT
->rq_dev
),
1481 MINOR(CURRENT
->rq_dev
),
1488 * make request function
1490 static int lvm_make_request_fn(request_queue_t
*q
, int rw
, struct buffer_head
*bh
)
1492 if (lvm_map(bh
, rw
)<0)
1493 return 0; /* failure, buffer_IO_error has been called, don't recurse */
1495 return 1; /* all ok, mapping done, call lower level driver */
1499 * plug device function is a noop because plugging has to happen
1500 * in the queue of the physical blockdevice to allow the
1501 * elevator to do a better job.
1503 static void lvm_plug_device_noop(request_queue_t
*q
, kdev_t dev
) { }
1505 /********************************************************************
1507 * Character device support functions
1509 ********************************************************************/
1511 * character device support function logical volume manager lock
1513 static int lvm_do_lock_lvm(void)
1516 spin_lock(&lvm_lock
);
1517 if (lock
!= 0 && lock
!= current
->pid
) {
1519 printk(KERN_INFO
"lvm_do_lock_lvm: %s is locked by pid %d ...\n",
1522 spin_unlock(&lvm_lock
);
1523 interruptible_sleep_on(&lvm_wait
);
1524 if (current
->sigpending
!= 0)
1526 #ifdef LVM_TOTAL_RESET
1527 if (lvm_reset_spindown
> 0)
1530 goto lock_try_again
;
1532 lock
= current
->pid
;
1533 spin_unlock(&lvm_lock
);
1535 } /* lvm_do_lock_lvm */
1539 * character device support function lock/unlock physical extend
1541 static int lvm_do_pe_lock_unlock(vg_t
*vg_ptr
, void *arg
)
1545 if (vg_ptr
== NULL
) return -ENXIO
;
1546 if (copy_from_user(&pe_lock_req
, arg
,
1547 sizeof(pe_lock_req_t
)) != 0) return -EFAULT
;
1549 switch (pe_lock_req
.lock
) {
1551 for (p
= 0; p
< vg_ptr
->pv_max
; p
++) {
1552 if (vg_ptr
->pv
[p
] != NULL
&&
1553 pe_lock_req
.data
.pv_dev
==
1554 vg_ptr
->pv
[p
]->pv_dev
)
1557 if (p
== vg_ptr
->pv_max
) return -ENXIO
;
1559 pe_lock_req
.lock
= UNLOCK_PE
;
1560 fsync_dev(pe_lock_req
.data
.lv_dev
);
1561 pe_lock_req
.lock
= LOCK_PE
;
1565 pe_lock_req
.lock
= UNLOCK_PE
;
1566 pe_lock_req
.data
.lv_dev
= pe_lock_req
.data
.pv_dev
= 0;
1567 pe_lock_req
.data
.pv_offset
= 0;
1568 wake_up(&lvm_map_wait
);
1579 * character device support function logical extend remap
1581 static int lvm_do_le_remap(vg_t
*vg_ptr
, void *arg
)
1586 if (vg_ptr
== NULL
) return -ENXIO
;
1587 if (copy_from_user(&le_remap_req
, arg
,
1588 sizeof(le_remap_req_t
)) != 0)
1591 for (l
= 0; l
< vg_ptr
->lv_max
; l
++) {
1592 lv_ptr
= vg_ptr
->lv
[l
];
1593 if (lv_ptr
!= NULL
&&
1594 strcmp(lv_ptr
->lv_name
,
1595 le_remap_req
.lv_name
) == 0) {
1596 for (le
= 0; le
< lv_ptr
->lv_allocated_le
;
1598 if (lv_ptr
->lv_current_pe
[le
].dev
==
1599 le_remap_req
.old_dev
&&
1600 lv_ptr
->lv_current_pe
[le
].pe
==
1601 le_remap_req
.old_pe
) {
1602 lv_ptr
->lv_current_pe
[le
].dev
=
1603 le_remap_req
.new_dev
;
1604 lv_ptr
->lv_current_pe
[le
].pe
=
1605 le_remap_req
.new_pe
;
1613 } /* lvm_do_le_remap() */
1617 * character device support function VGDA create
1619 int lvm_do_vg_create(int minor
, void *arg
)
1621 int snaporg_minor
= 0;
1628 if (vg
[VG_CHR(minor
)] != NULL
) return -EPERM
;
1630 if ((vg_ptr
= kmalloc(sizeof(vg_t
),GFP_KERNEL
)) == NULL
) {
1632 "%s -- VG_CREATE: kmalloc error VG at line %d\n",
1633 lvm_name
, __LINE__
);
1636 /* get the volume group structure */
1637 if (copy_from_user(vg_ptr
, arg
, sizeof(vg_t
)) != 0) {
1642 vg_devfs_handle
[vg_ptr
->vg_number
] = devfs_mk_dir(0, vg_ptr
->vg_name
, NULL
);
1643 ch_devfs_handle
[vg_ptr
->vg_number
] = devfs_register(
1644 vg_devfs_handle
[vg_ptr
->vg_number
] , "group",
1645 DEVFS_FL_DEFAULT
, LVM_CHAR_MAJOR
, vg_ptr
->vg_number
,
1646 S_IFCHR
| S_IRUSR
| S_IWUSR
| S_IRGRP
,
1647 &lvm_chr_fops
, NULL
);
1649 /* we are not that active so far... */
1650 vg_ptr
->vg_status
&= ~VG_ACTIVE
;
1651 vg
[VG_CHR(minor
)] = vg_ptr
;
1653 vg
[VG_CHR(minor
)]->pe_allocated
= 0;
1654 if (vg_ptr
->pv_max
> ABS_MAX_PV
) {
1656 "%s -- Can't activate VG: ABS_MAX_PV too small\n",
1659 vg
[VG_CHR(minor
)] = NULL
;
1662 if (vg_ptr
->lv_max
> ABS_MAX_LV
) {
1664 "%s -- Can't activate VG: ABS_MAX_LV too small for %u\n",
1665 lvm_name
, vg_ptr
->lv_max
);
1670 /* get the physical volume structures */
1671 vg_ptr
->pv_act
= vg_ptr
->pv_cur
= 0;
1672 for (p
= 0; p
< vg_ptr
->pv_max
; p
++) {
1673 /* user space address */
1674 if ((pvp
= vg_ptr
->pv
[p
]) != NULL
) {
1675 pv_ptr
= vg_ptr
->pv
[p
] = kmalloc(sizeof(pv_t
),GFP_KERNEL
);
1676 if (pv_ptr
== NULL
) {
1678 "%s -- VG_CREATE: kmalloc error PV at line %d\n",
1679 lvm_name
, __LINE__
);
1680 lvm_do_vg_remove(minor
);
1683 if (copy_from_user(pv_ptr
, pvp
, sizeof(pv_t
)) != 0) {
1684 lvm_do_vg_remove(minor
);
1687 /* We don't need the PE list
1688 in kernel space as with LVs pe_t list (see below) */
1690 pv_ptr
->pe_allocated
= 0;
1691 pv_ptr
->pv_status
= PV_ACTIVE
;
1695 #ifdef LVM_GET_INODE
1696 /* insert a dummy inode for fs_may_mount */
1697 pv_ptr
->inode
= lvm_get_inode(pv_ptr
->pv_dev
);
1702 /* get the logical volume structures */
1704 for (l
= 0; l
< vg_ptr
->lv_max
; l
++) {
1705 /* user space address */
1706 if ((lvp
= vg_ptr
->lv
[l
]) != NULL
) {
1707 if (copy_from_user(&lv
, lvp
, sizeof(lv_t
)) != 0) {
1708 lvm_do_vg_remove(minor
);
1711 vg_ptr
->lv
[l
] = NULL
;
1712 if (lvm_do_lv_create(minor
, lv
.lv_name
, &lv
) != 0) {
1713 lvm_do_vg_remove(minor
);
1719 /* Second path to correct snapshot logical volumes which are not
1720 in place during first path above */
1721 for (l
= 0; l
< vg_ptr
->lv_max
; l
++) {
1722 if ((lv_ptr
= vg_ptr
->lv
[l
]) != NULL
&&
1723 vg_ptr
->lv
[l
]->lv_access
& LV_SNAPSHOT
) {
1724 snaporg_minor
= lv_ptr
->lv_snapshot_minor
;
1725 if (vg_ptr
->lv
[LV_BLK(snaporg_minor
)] != NULL
) {
1726 /* get pointer to original logical volume */
1727 lv_ptr
= vg_ptr
->lv
[l
]->lv_snapshot_org
=
1728 vg_ptr
->lv
[LV_BLK(snaporg_minor
)];
1730 /* set necessary fields of original logical volume */
1731 lv_ptr
->lv_access
|= LV_SNAPSHOT_ORG
;
1732 lv_ptr
->lv_snapshot_minor
= 0;
1733 lv_ptr
->lv_snapshot_org
= lv_ptr
;
1734 lv_ptr
->lv_snapshot_prev
= NULL
;
1736 /* find last snapshot logical volume in the chain */
1737 while (lv_ptr
->lv_snapshot_next
!= NULL
)
1738 lv_ptr
= lv_ptr
->lv_snapshot_next
;
1740 /* set back pointer to this last one in our new logical volume */
1741 vg_ptr
->lv
[l
]->lv_snapshot_prev
= lv_ptr
;
1743 /* last logical volume now points to our new snapshot volume */
1744 lv_ptr
->lv_snapshot_next
= vg_ptr
->lv
[l
];
1746 /* now point to the new one */
1747 lv_ptr
= lv_ptr
->lv_snapshot_next
;
1749 /* set necessary fields of new snapshot logical volume */
1750 lv_ptr
->lv_snapshot_next
= NULL
;
1751 lv_ptr
->lv_current_pe
=
1752 vg_ptr
->lv
[LV_BLK(snaporg_minor
)]->lv_current_pe
;
1753 lv_ptr
->lv_allocated_le
=
1754 vg_ptr
->lv
[LV_BLK(snaporg_minor
)]->lv_allocated_le
;
1755 lv_ptr
->lv_current_le
=
1756 vg_ptr
->lv
[LV_BLK(snaporg_minor
)]->lv_current_le
;
1758 vg_ptr
->lv
[LV_BLK(snaporg_minor
)]->lv_size
;
1765 /* let's go active */
1766 vg_ptr
->vg_status
|= VG_ACTIVE
;
1771 } /* lvm_do_vg_create() */
1775 * character device support function VGDA extend
1777 static int lvm_do_vg_extend(vg_t
*vg_ptr
, void *arg
)
1782 if (vg_ptr
== NULL
) return -ENXIO
;
1783 if (vg_ptr
->pv_cur
< vg_ptr
->pv_max
) {
1784 for (p
= 0; p
< vg_ptr
->pv_max
; p
++) {
1785 if (vg_ptr
->pv
[p
] == NULL
) {
1786 if ((pv_ptr
= vg_ptr
->pv
[p
] = kmalloc(sizeof(pv_t
),GFP_KERNEL
)) == NULL
) {
1788 "%s -- VG_EXTEND: kmalloc error PV at line %d\n",
1789 lvm_name
, __LINE__
);
1792 if (copy_from_user(pv_ptr
, arg
, sizeof(pv_t
)) != 0) {
1794 vg_ptr
->pv
[p
] = NULL
;
1798 pv_ptr
->pv_status
= PV_ACTIVE
;
1799 /* We don't need the PE list
1800 in kernel space like LVs pe_t list */
1806 #ifdef LVM_GET_INODE
1807 /* insert a dummy inode for fs_may_mount */
1808 pv_ptr
->inode
= lvm_get_inode(pv_ptr
->pv_dev
);
1815 } /* lvm_do_vg_extend() */
1819 * character device support function VGDA reduce
1821 static int lvm_do_vg_reduce(vg_t
*vg_ptr
, void *arg
)
1826 if (vg_ptr
== NULL
) return -ENXIO
;
1827 if (copy_from_user(pv_name
, arg
, sizeof(pv_name
)) != 0)
1830 for (p
= 0; p
< vg_ptr
->pv_max
; p
++) {
1831 pv_ptr
= vg_ptr
->pv
[p
];
1832 if (pv_ptr
!= NULL
&&
1833 strcmp(pv_ptr
->pv_name
,
1835 if (pv_ptr
->lv_cur
> 0) return -EPERM
;
1840 #ifdef LVM_GET_INODE
1841 lvm_clear_inode(pv_ptr
->inode
);
1844 /* Make PV pointer array contiguous */
1845 for (; p
< vg_ptr
->pv_max
- 1; p
++)
1846 vg_ptr
->pv
[p
] = vg_ptr
->pv
[p
+ 1];
1847 vg_ptr
->pv
[p
+ 1] = NULL
;
1852 } /* lvm_do_vg_reduce */
1856 * character device support function VGDA remove
1858 static int lvm_do_vg_remove(int minor
)
1861 vg_t
*vg_ptr
= vg
[VG_CHR(minor
)];
1864 if (vg_ptr
== NULL
) return -ENXIO
;
1866 #ifdef LVM_TOTAL_RESET
1867 if (vg_ptr
->lv_open
> 0 && lvm_reset_spindown
== 0)
1869 if (vg_ptr
->lv_open
> 0)
1873 /* let's go inactive */
1874 vg_ptr
->vg_status
&= ~VG_ACTIVE
;
1876 devfs_unregister (ch_devfs_handle
[vg_ptr
->vg_number
]);
1877 devfs_unregister (vg_devfs_handle
[vg_ptr
->vg_number
]);
1880 /* first free snapshot logical volumes */
1881 for (i
= 0; i
< vg_ptr
->lv_max
; i
++) {
1882 if (vg_ptr
->lv
[i
] != NULL
&&
1883 vg_ptr
->lv
[i
]->lv_access
& LV_SNAPSHOT
) {
1884 lvm_do_lv_remove(minor
, NULL
, i
);
1885 current
->state
= TASK_UNINTERRUPTIBLE
;
1886 schedule_timeout(1);
1889 /* then free the rest of the LVs */
1890 for (i
= 0; i
< vg_ptr
->lv_max
; i
++) {
1891 if (vg_ptr
->lv
[i
] != NULL
) {
1892 lvm_do_lv_remove(minor
, NULL
, i
);
1893 current
->state
= TASK_UNINTERRUPTIBLE
;
1894 schedule_timeout(1);
1899 for (i
= 0; i
< vg_ptr
->pv_max
; i
++) {
1900 if ((pv_ptr
= vg_ptr
->pv
[i
]) != NULL
) {
1903 "%s -- kfree %d\n", lvm_name
, __LINE__
);
1905 #ifdef LVM_GET_INODE
1906 lvm_clear_inode(pv_ptr
->inode
);
1909 vg
[VG_CHR(minor
)]->pv
[i
] = NULL
;
1914 printk(KERN_DEBUG
"%s -- kfree %d\n", lvm_name
, __LINE__
);
1917 vg
[VG_CHR(minor
)] = NULL
;
1924 } /* lvm_do_vg_remove() */
1928 * character device support function logical volume create
1930 static int lvm_do_lv_create(int minor
, char *lv_name
, lv_t
*lv
)
1932 int l
, le
, l_new
, p
, size
;
1933 ulong lv_status_save
;
1934 char *lv_tmp
, *lv_buf
= NULL
;
1935 lv_block_exception_t
*lvbe
= lv
->lv_block_exception
;
1936 vg_t
*vg_ptr
= vg
[VG_CHR(minor
)];
1937 lv_t
*lv_ptr
= NULL
;
1939 if ((pep
= lv
->lv_current_pe
) == NULL
) return -EINVAL
;
1940 if (lv
->lv_chunk_size
> LVM_SNAPSHOT_MAX_CHUNK
)
1943 for (l
= 0; l
< vg_ptr
->lv_max
; l
++) {
1944 if (vg_ptr
->lv
[l
] != NULL
&&
1945 strcmp(vg_ptr
->lv
[l
]->lv_name
, lv_name
) == 0)
1949 /* in case of lv_remove(), lv_create() pair; for eg. lvrename does this */
1951 if (vg_ptr
->lv
[lv
->lv_number
] == NULL
)
1952 l_new
= lv
->lv_number
;
1954 for (l
= 0; l
< vg_ptr
->lv_max
; l
++) {
1955 if (vg_ptr
->lv
[l
] == NULL
)
1956 if (l_new
== -1) l_new
= l
;
1959 if (l_new
== -1) return -EPERM
;
1962 if ((lv_ptr
= kmalloc(sizeof(lv_t
),GFP_KERNEL
)) == NULL
) {;
1963 printk(KERN_CRIT
"%s -- LV_CREATE: kmalloc error LV at line %d\n",
1964 lvm_name
, __LINE__
);
1967 /* copy preloaded LV */
1968 memcpy((char *) lv_ptr
, (char *) lv
, sizeof(lv_t
));
1970 lv_status_save
= lv_ptr
->lv_status
;
1971 lv_ptr
->lv_status
&= ~LV_ACTIVE
;
1972 lv_ptr
->lv_snapshot_org
= \
1973 lv_ptr
->lv_snapshot_prev
= \
1974 lv_ptr
->lv_snapshot_next
= NULL
;
1975 lv_ptr
->lv_block_exception
= NULL
;
1976 init_MUTEX(&lv_ptr
->lv_snapshot_sem
);
1977 vg_ptr
->lv
[l
] = lv_ptr
;
1979 /* get the PE structures from user space if this
1980 is no snapshot logical volume */
1981 if (!(lv_ptr
->lv_access
& LV_SNAPSHOT
)) {
1982 size
= lv_ptr
->lv_allocated_le
* sizeof(pe_t
);
1983 if ((lv_ptr
->lv_current_pe
= vmalloc(size
)) == NULL
) {
1985 "%s -- LV_CREATE: vmalloc error LV_CURRENT_PE of %d Byte "
1987 lvm_name
, size
, __LINE__
);
1989 printk(KERN_DEBUG
"%s -- kfree %d\n", lvm_name
, __LINE__
);
1992 vg
[VG_CHR(minor
)]->lv
[l
] = NULL
;
1995 if (copy_from_user(lv_ptr
->lv_current_pe
, pep
, size
)) {
1996 vfree(lv_ptr
->lv_current_pe
);
1998 vg_ptr
->lv
[l
] = NULL
;
2001 /* correct the PE count in PVs */
2002 for (le
= 0; le
< lv_ptr
->lv_allocated_le
; le
++) {
2003 vg_ptr
->pe_allocated
++;
2004 for (p
= 0; p
< vg_ptr
->pv_cur
; p
++) {
2005 if (vg_ptr
->pv
[p
]->pv_dev
==
2006 lv_ptr
->lv_current_pe
[le
].dev
)
2007 vg_ptr
->pv
[p
]->pe_allocated
++;
2011 /* Get snapshot exception data and block list */
2013 lv_ptr
->lv_snapshot_org
=
2014 vg_ptr
->lv
[LV_BLK(lv_ptr
->lv_snapshot_minor
)];
2015 if (lv_ptr
->lv_snapshot_org
!= NULL
) {
2016 size
= lv_ptr
->lv_remap_end
* sizeof(lv_block_exception_t
);
2017 if ((lv_ptr
->lv_block_exception
= vmalloc(size
)) == NULL
) {
2019 "%s -- lvm_do_lv_create: vmalloc error LV_BLOCK_EXCEPTION "
2020 "of %d byte at line %d\n",
2021 lvm_name
, size
, __LINE__
);
2023 printk(KERN_DEBUG
"%s -- kfree %d\n", lvm_name
, __LINE__
);
2026 vg_ptr
->lv
[l
] = NULL
;
2029 if (copy_from_user(lv_ptr
->lv_block_exception
, lvbe
, size
)) {
2030 vfree(lv_ptr
->lv_block_exception
);
2032 vg
[VG_CHR(minor
)]->lv
[l
] = NULL
;
2035 /* get pointer to original logical volume */
2036 lv_ptr
= lv_ptr
->lv_snapshot_org
;
2038 lv_ptr
->lv_snapshot_minor
= 0;
2039 lv_ptr
->lv_snapshot_org
= lv_ptr
;
2040 lv_ptr
->lv_snapshot_prev
= NULL
;
2041 /* walk thrugh the snapshot list */
2042 while (lv_ptr
->lv_snapshot_next
!= NULL
)
2043 lv_ptr
= lv_ptr
->lv_snapshot_next
;
2044 /* now lv_ptr points to the last existing snapshot in the chain */
2045 vg_ptr
->lv
[l
]->lv_snapshot_prev
= lv_ptr
;
2046 /* our new one now back points to the previous last in the chain */
2047 lv_ptr
= vg_ptr
->lv
[l
];
2048 /* now lv_ptr points to our new last snapshot logical volume */
2049 lv_ptr
->lv_snapshot_org
= lv_ptr
->lv_snapshot_prev
->lv_snapshot_org
;
2050 lv_ptr
->lv_snapshot_next
= NULL
;
2051 lv_ptr
->lv_current_pe
= lv_ptr
->lv_snapshot_org
->lv_current_pe
;
2052 lv_ptr
->lv_allocated_le
= lv_ptr
->lv_snapshot_org
->lv_allocated_le
;
2053 lv_ptr
->lv_current_le
= lv_ptr
->lv_snapshot_org
->lv_current_le
;
2054 lv_ptr
->lv_size
= lv_ptr
->lv_snapshot_org
->lv_size
;
2055 lv_ptr
->lv_stripes
= lv_ptr
->lv_snapshot_org
->lv_stripes
;
2056 lv_ptr
->lv_stripesize
= lv_ptr
->lv_snapshot_org
->lv_stripesize
;
2058 int err
= lvm_snapshot_alloc(lv_ptr
);
2061 vfree(lv_ptr
->lv_block_exception
);
2063 vg
[VG_CHR(minor
)]->lv
[l
] = NULL
;
2068 vfree(lv_ptr
->lv_block_exception
);
2070 vg_ptr
->lv
[l
] = NULL
;
2074 kfree(vg_ptr
->lv
[l
]);
2075 vg_ptr
->lv
[l
] = NULL
;
2078 } /* if ( vg[VG_CHR(minor)]->lv[l]->lv_access & LV_SNAPSHOT) */
2080 lv_ptr
= vg_ptr
->lv
[l
];
2081 lvm_gendisk
.part
[MINOR(lv_ptr
->lv_dev
)].start_sect
= 0;
2082 lvm_gendisk
.part
[MINOR(lv_ptr
->lv_dev
)].nr_sects
= lv_ptr
->lv_size
;
2083 lvm_size
[MINOR(lv_ptr
->lv_dev
)] = lv_ptr
->lv_size
>> 1;
2084 vg_lv_map
[MINOR(lv_ptr
->lv_dev
)].vg_number
= vg_ptr
->vg_number
;
2085 vg_lv_map
[MINOR(lv_ptr
->lv_dev
)].lv_number
= lv_ptr
->lv_number
;
2086 read_ahead
[MAJOR_NR
] = lv_ptr
->lv_read_ahead
= LVM_CORRECT_READ_AHEAD(lv_ptr
->lv_read_ahead
);
2088 lv_ptr
->lv_status
= lv_status_save
;
2090 strtok(lv
->lv_name
, "/"); /* /dev */
2092 while((lv_tmp
= strtok(NULL
, "/")) != NULL
)
2095 lv_devfs_handle
[lv
->lv_number
] = devfs_register(
2096 vg_devfs_handle
[vg_ptr
->vg_number
], lv_buf
,
2097 DEVFS_FL_DEFAULT
, LVM_BLK_MAJOR
, lv
->lv_number
,
2098 S_IFBLK
| S_IRUSR
| S_IWUSR
| S_IRGRP
,
2099 &lvm_blk_dops
, NULL
);
2101 /* optionally add our new snapshot LV */
2102 if (lv_ptr
->lv_access
& LV_SNAPSHOT
) {
2103 /* sync the original logical volume */
2104 fsync_dev(lv_ptr
->lv_snapshot_org
->lv_dev
);
2105 /* put ourselve into the chain */
2106 lv_ptr
->lv_snapshot_prev
->lv_snapshot_next
= lv_ptr
;
2107 lv_ptr
->lv_snapshot_org
->lv_access
|= LV_SNAPSHOT_ORG
;
2110 } /* lvm_do_lv_create() */
2114 * character device support function logical volume remove
2116 static int lvm_do_lv_remove(int minor
, char *lv_name
, int l
)
2119 vg_t
*vg_ptr
= vg
[VG_CHR(minor
)];
2123 for (l
= 0; l
< vg_ptr
->lv_max
; l
++) {
2124 if (vg_ptr
->lv
[l
] != NULL
&&
2125 strcmp(vg_ptr
->lv
[l
]->lv_name
, lv_name
) == 0) {
2130 if (l
== vg_ptr
->lv_max
) return -ENXIO
;
2132 lv_ptr
= vg_ptr
->lv
[l
];
2133 #ifdef LVM_TOTAL_RESET
2134 if (lv_ptr
->lv_open
> 0 && lvm_reset_spindown
== 0)
2136 if (lv_ptr
->lv_open
> 0)
2140 /* check for deletion of snapshot source while
2141 snapshot volume still exists */
2142 if ((lv_ptr
->lv_access
& LV_SNAPSHOT_ORG
) &&
2143 lv_ptr
->lv_snapshot_next
!= NULL
)
2146 lv_ptr
->lv_status
|= LV_SPINDOWN
;
2148 /* sync the buffers */
2149 fsync_dev(lv_ptr
->lv_dev
);
2151 lv_ptr
->lv_status
&= ~LV_ACTIVE
;
2153 /* invalidate the buffers */
2154 invalidate_buffers(lv_ptr
->lv_dev
);
2156 /* reset generic hd */
2157 lvm_gendisk
.part
[MINOR(lv_ptr
->lv_dev
)].start_sect
= -1;
2158 lvm_gendisk
.part
[MINOR(lv_ptr
->lv_dev
)].nr_sects
= 0;
2159 lvm_size
[MINOR(lv_ptr
->lv_dev
)] = 0;
2161 /* reset VG/LV mapping */
2162 vg_lv_map
[MINOR(lv_ptr
->lv_dev
)].vg_number
= ABS_MAX_VG
;
2163 vg_lv_map
[MINOR(lv_ptr
->lv_dev
)].lv_number
= -1;
2165 /* correct the PE count in PVs if this is no snapshot logical volume */
2166 if (!(lv_ptr
->lv_access
& LV_SNAPSHOT
)) {
2167 /* only if this is no snapshot logical volume because
2168 we share the lv_current_pe[] structs with the
2169 original logical volume */
2170 for (le
= 0; le
< lv_ptr
->lv_allocated_le
; le
++) {
2171 vg_ptr
->pe_allocated
--;
2172 for (p
= 0; p
< vg_ptr
->pv_cur
; p
++) {
2173 if (vg_ptr
->pv
[p
]->pv_dev
==
2174 lv_ptr
->lv_current_pe
[le
].dev
)
2175 vg_ptr
->pv
[p
]->pe_allocated
--;
2178 vfree(lv_ptr
->lv_current_pe
);
2181 /* remove this snapshot logical volume from the chain */
2182 lv_ptr
->lv_snapshot_prev
->lv_snapshot_next
= lv_ptr
->lv_snapshot_next
;
2183 if (lv_ptr
->lv_snapshot_next
!= NULL
) {
2184 lv_ptr
->lv_snapshot_next
->lv_snapshot_prev
=
2185 lv_ptr
->lv_snapshot_prev
;
2187 /* no more snapshots? */
2188 if (lv_ptr
->lv_snapshot_org
->lv_snapshot_next
== NULL
)
2189 lv_ptr
->lv_snapshot_org
->lv_access
&= ~LV_SNAPSHOT_ORG
;
2190 lvm_snapshot_release(lv_ptr
);
2193 devfs_unregister(lv_devfs_handle
[lv_ptr
->lv_number
]);
2196 printk(KERN_DEBUG
"%s -- kfree %d\n", lvm_name
, __LINE__
);
2199 vg_ptr
->lv
[l
] = NULL
;
2202 } /* lvm_do_lv_remove() */
2206 * character device support function logical volume extend / reduce
2208 static int lvm_do_lv_extend_reduce(int minor
, char *lv_name
, lv_t
*lv
)
2210 int l
, le
, p
, size
, old_allocated_le
;
2211 uint32_t end
, lv_status_save
;
2212 vg_t
*vg_ptr
= vg
[VG_CHR(minor
)];
2216 if ((pep
= lv
->lv_current_pe
) == NULL
) return -EINVAL
;
2218 for (l
= 0; l
< vg_ptr
->lv_max
; l
++) {
2219 if (vg_ptr
->lv
[l
] != NULL
&&
2220 strcmp(vg_ptr
->lv
[l
]->lv_name
, lv_name
) == 0)
2223 if (l
== vg_ptr
->lv_max
) return -ENXIO
;
2224 lv_ptr
= vg_ptr
->lv
[l
];
2226 /* check for active snapshot */
2227 if (lv
->lv_access
& (LV_SNAPSHOT
| LV_SNAPSHOT_ORG
)) return -EPERM
;
2229 if ((pe
= vmalloc(size
= lv
->lv_current_le
* sizeof(pe_t
))) == NULL
) {
2231 "%s -- lvm_do_lv_extend_reduce: vmalloc error LV_CURRENT_PE "
2232 "of %d Byte at line %d\n",
2233 lvm_name
, size
, __LINE__
);
2236 /* get the PE structures from user space */
2237 if (copy_from_user(pe
, pep
, size
)) {
2244 "%s -- fsync_dev and "
2245 "invalidate_buffers for %s [%s] in %s\n",
2246 lvm_name
, lv_ptr
->lv_name
,
2247 kdevname(lv_ptr
->lv_dev
),
2251 lv_ptr
->lv_status
|= LV_SPINDOWN
;
2252 fsync_dev(lv_ptr
->lv_dev
);
2253 lv_ptr
->lv_status
&= ~LV_ACTIVE
;
2254 invalidate_buffers(lv_ptr
->lv_dev
);
2256 /* reduce allocation counters on PV(s) */
2257 for (le
= 0; le
< lv_ptr
->lv_allocated_le
; le
++) {
2258 vg_ptr
->pe_allocated
--;
2259 for (p
= 0; p
< vg_ptr
->pv_cur
; p
++) {
2260 if (vg_ptr
->pv
[p
]->pv_dev
==
2261 lv_ptr
->lv_current_pe
[le
].dev
) {
2262 vg_ptr
->pv
[p
]->pe_allocated
--;
2269 /* save pointer to "old" lv/pe pointer array */
2270 pep1
= lv_ptr
->lv_current_pe
;
2271 end
= lv_ptr
->lv_current_le
;
2273 /* save open counter */
2274 lv_open
= lv_ptr
->lv_open
;
2276 /* save # of old allocated logical extents */
2277 old_allocated_le
= lv_ptr
->lv_allocated_le
;
2279 /* copy preloaded LV */
2280 lv_status_save
= lv
->lv_status
;
2281 lv
->lv_status
|= LV_SPINDOWN
;
2282 lv
->lv_status
&= ~LV_ACTIVE
;
2283 memcpy((char *) lv_ptr
, (char *) lv
, sizeof(lv_t
));
2284 lv_ptr
->lv_current_pe
= pe
;
2285 lv_ptr
->lv_open
= lv_open
;
2287 /* save availiable i/o statistic data */
2288 /* linear logical volume */
2289 if (lv_ptr
->lv_stripes
< 2) {
2290 /* Check what last LE shall be used */
2291 if (end
> lv_ptr
->lv_current_le
) end
= lv_ptr
->lv_current_le
;
2292 for (le
= 0; le
< end
; le
++) {
2293 lv_ptr
->lv_current_pe
[le
].reads
= pep1
[le
].reads
;
2294 lv_ptr
->lv_current_pe
[le
].writes
= pep1
[le
].writes
;
2296 /* striped logical volume */
2298 uint i
, j
, source
, dest
, end
, old_stripe_size
, new_stripe_size
;
2300 old_stripe_size
= old_allocated_le
/ lv_ptr
->lv_stripes
;
2301 new_stripe_size
= lv_ptr
->lv_allocated_le
/ lv_ptr
->lv_stripes
;
2302 end
= old_stripe_size
;
2303 if (end
> new_stripe_size
) end
= new_stripe_size
;
2304 for (i
= source
= dest
= 0;
2305 i
< lv_ptr
->lv_stripes
; i
++) {
2306 for (j
= 0; j
< end
; j
++) {
2307 lv_ptr
->lv_current_pe
[dest
+ j
].reads
=
2308 pep1
[source
+ j
].reads
;
2309 lv_ptr
->lv_current_pe
[dest
+ j
].writes
=
2310 pep1
[source
+ j
].writes
;
2312 source
+= old_stripe_size
;
2313 dest
+= new_stripe_size
;
2320 /* extend the PE count in PVs */
2321 for (le
= 0; le
< lv_ptr
->lv_allocated_le
; le
++) {
2322 vg_ptr
->pe_allocated
++;
2323 for (p
= 0; p
< vg_ptr
->pv_cur
; p
++) {
2324 if (vg_ptr
->pv
[p
]->pv_dev
==
2325 vg_ptr
->lv
[l
]->lv_current_pe
[le
].dev
) {
2326 vg_ptr
->pv
[p
]->pe_allocated
++;
2332 lvm_gendisk
.part
[MINOR(lv_ptr
->lv_dev
)].start_sect
= 0;
2333 lvm_gendisk
.part
[MINOR(lv_ptr
->lv_dev
)].nr_sects
= lv_ptr
->lv_size
;
2334 lvm_size
[MINOR(lv_ptr
->lv_dev
)] = lv_ptr
->lv_size
>> 1;
2335 /* vg_lv_map array doesn't have to be changed here */
2337 read_ahead
[MAJOR_NR
] = lv_ptr
->lv_read_ahead
= LVM_CORRECT_READ_AHEAD(lv_ptr
->lv_read_ahead
);
2338 lv_ptr
->lv_status
= lv_status_save
;
2341 } /* lvm_do_lv_extend_reduce() */
2345 * character device support function logical volume status by name
2347 static int lvm_do_lv_status_byname(vg_t
*vg_ptr
, void *arg
)
2353 lv_status_byname_req_t lv_status_byname_req
;
2355 if (vg_ptr
== NULL
) return -ENXIO
;
2356 if (copy_from_user(&lv_status_byname_req
, arg
,
2357 sizeof(lv_status_byname_req_t
)) != 0)
2360 if (lv_status_byname_req
.lv
== NULL
) return -EINVAL
;
2361 if (copy_from_user(&lv
, lv_status_byname_req
.lv
,
2365 for (l
= 0; l
< vg_ptr
->lv_max
; l
++) {
2366 lv_ptr
= vg_ptr
->lv
[l
];
2367 if (lv_ptr
!= NULL
&&
2368 strcmp(lv_ptr
->lv_name
,
2369 lv_status_byname_req
.lv_name
) == 0) {
2370 if (copy_to_user(lv_status_byname_req
.lv
,
2375 if (lv
.lv_current_pe
!= NULL
) {
2376 size
= lv_ptr
->lv_allocated_le
*
2378 if (copy_to_user(lv
.lv_current_pe
,
2379 lv_ptr
->lv_current_pe
,
2387 } /* lvm_do_lv_status_byname() */
2391 * character device support function logical volume status by index
2393 static int lvm_do_lv_status_byindex(vg_t
*vg_ptr
,void *arg
)
2398 lv_status_byindex_req_t lv_status_byindex_req
;
2400 if (vg_ptr
== NULL
) return -ENXIO
;
2401 if (copy_from_user(&lv_status_byindex_req
, arg
,
2402 sizeof(lv_status_byindex_req
)) != 0)
2405 if ((lvp
= lv_status_byindex_req
.lv
) == NULL
)
2407 if ( ( lv_ptr
= vg_ptr
->lv
[lv_status_byindex_req
.lv_index
]) == NULL
)
2410 if (copy_from_user(&lv
, lvp
, sizeof(lv_t
)) != 0)
2413 if (copy_to_user(lvp
, lv_ptr
, sizeof(lv_t
)) != 0)
2416 if (lv
.lv_current_pe
!= NULL
) {
2417 size
= lv_ptr
->lv_allocated_le
* sizeof(pe_t
);
2418 if (copy_to_user(lv
.lv_current_pe
,
2419 lv_ptr
->lv_current_pe
,
2424 } /* lvm_do_lv_status_byindex() */
2428 * character device support function physical volume change
2430 static int lvm_do_pv_change(vg_t
*vg_ptr
, void *arg
)
2434 #ifdef LVM_GET_INODE
2435 struct inode
*inode_sav
;
2438 if (vg_ptr
== NULL
) return -ENXIO
;
2439 if (copy_from_user(&pv_change_req
, arg
,
2440 sizeof(pv_change_req
)) != 0)
2443 for (p
= 0; p
< vg_ptr
->pv_max
; p
++) {
2444 pv_ptr
= vg_ptr
->pv
[p
];
2445 if (pv_ptr
!= NULL
&&
2446 strcmp(pv_ptr
->pv_name
,
2447 pv_change_req
.pv_name
) == 0) {
2448 #ifdef LVM_GET_INODE
2449 inode_sav
= pv_ptr
->inode
;
2451 if (copy_from_user(pv_ptr
,
2456 /* We don't need the PE list
2457 in kernel space as with LVs pe_t list */
2459 #ifdef LVM_GET_INODE
2460 pv_ptr
->inode
= inode_sav
;
2466 } /* lvm_do_pv_change() */
2469 * character device support function get physical volume status
2471 static int lvm_do_pv_status(vg_t
*vg_ptr
, void *arg
)
2476 if (vg_ptr
== NULL
) return -ENXIO
;
2477 if (copy_from_user(&pv_status_req
, arg
,
2478 sizeof(pv_status_req
)) != 0)
2481 for (p
= 0; p
< vg_ptr
->pv_max
; p
++) {
2482 pv_ptr
= vg_ptr
->pv
[p
];
2483 if (pv_ptr
!= NULL
&&
2484 strcmp(pv_ptr
->pv_name
,
2485 pv_status_req
.pv_name
) == 0) {
2486 if (copy_to_user(pv_status_req
.pv
,
2494 } /* lvm_do_pv_status() */
2498 * support function initialize gendisk variables
2501 __initfunc(void lvm_geninit(struct gendisk
*lvm_gdisk
))
2504 lvm_geninit(struct gendisk
*lvm_gdisk
)
2509 #ifdef DEBUG_GENDISK
2510 printk(KERN_DEBUG
"%s -- lvm_gendisk\n", lvm_name
);
2513 for (i
= 0; i
< MAX_LV
; i
++) {
2514 lvm_gendisk
.part
[i
].start_sect
= -1; /* avoid partition check */
2515 lvm_size
[i
] = lvm_gendisk
.part
[i
].nr_sects
= 0;
2516 lvm_blocksizes
[i
] = BLOCK_SIZE
;
2519 blksize_size
[MAJOR_NR
] = lvm_blocksizes
;
2520 blk_size
[MAJOR_NR
] = lvm_size
;
2523 } /* lvm_gen_init() */
2526 #ifdef LVM_GET_INODE
2528 * support function to get an empty inode
2530 * Gets an empty inode to be inserted into the inode hash,
2531 * so that a physical volume can't be mounted.
2532 * This is analog to drivers/block/md.c
2534 * Is this the real thing?
2536 * No, it's bollocks. md.c tries to do a bit different thing that might
2537 * _somewhat_ work eons ago. Neither does any good these days. mount() couldn't
2538 * care less for icache (it cares only for ->s_root->d_count and if we want
2539 * loopback mounts even that will stop). BTW, with the form used here mount()
2540 * would have to scan the _whole_ icache to detect the attempt - how on the
2541 * Earth could it guess the i_ino of your dummy inode? Official line on the
2542 * exclusion between mount()/swapon()/open()/etc. is Just Don't Do It(tm).
2543 * If you can convince Linus that it's worth changing - fine, then you'll need
2544 * to do blkdev_get()/blkdev_put(). Until then...
2546 struct inode
*lvm_get_inode(kdev_t dev
)
2548 struct inode
*inode_this
= NULL
;
2550 /* Lock the device by inserting a dummy inode. */
2551 inode_this
= get_empty_inode();
2552 inode_this
->i_dev
= dev
;
2553 insert_inode_hash(inode_this
);
2559 * support function to clear an inode
2562 void lvm_clear_inode(struct inode
*inode
)
2565 inode
->i_state
|= I_FREEING
;
2570 #endif /* #ifdef LVM_GET_INODE */