4 * Copyright (C) 1997 - 2000 Heinz Mauelshagen, Sistina Software
6 * February-November 1997
7 * April-May,July-August,November 1998
8 * January-March,May,July,September,October 1999
9 * January,February,July,September-November 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_global_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 Arcagneli's snapshot code
126 * 25/06/2000 - james (chip) , IKKHAYD! roffl
127 * 26/06/2000 - enhanced lv_extend_reduce for snapshot logical volume support
128 * 06/09/2000 - added devfs support
129 * 07/09/2000 - changed IOP version to 9
130 * - started to add new char ioctl LV_STATUS_BYDEV_T to support
131 * getting an lv_t based on the dev_t of the Logical Volume
132 * 14/09/2000 - enhanced lvm_do_lv_create to upcall VFS functions
133 * to sync and lock, activate snapshot and unlock the FS
134 * (to support journaled filesystems)
135 * 18/09/2000 - hardsector size support
136 * 27/09/2000 - implemented lvm_do_lv_rename() and lvm_do_vg_rename()
137 * 30/10/2000 - added Andi Kleen's LV_BMAP ioctl to support LILO
138 * 01/11/2000 - added memory information on hash tables to
139 * lvm_proc_get_global_info()
140 * 02/11/2000 - implemented /proc/lvm/ hierarchy
141 * 07/12/2000 - make sure lvm_make_request_fn returns correct value - 0 or 1 - NeilBrown
146 static char *lvm_version
= "LVM version 0.9 by Heinz Mauelshagen (13/11/2000)\n";
147 static char *lvm_short_version
= "version 0.9 (13/11/2000)";
149 #define MAJOR_NR LVM_BLK_MAJOR
150 #define DEVICE_OFF(device)
152 /* lvm_do_lv_create calls fsync_dev_lockfs()/unlockfs() */
153 /* #define LVM_VFS_ENHANCEMENT */
155 #include <linux/config.h>
156 #include <linux/version.h>
161 #include <linux/modversions.h>
164 #include <linux/module.h>
166 #include <linux/kernel.h>
167 #include <linux/vmalloc.h>
168 #include <linux/slab.h>
169 #include <linux/init.h>
171 #include <linux/hdreg.h>
172 #include <linux/stat.h>
173 #include <linux/fs.h>
174 #include <linux/proc_fs.h>
175 #include <linux/blkdev.h>
176 #include <linux/genhd.h>
177 #include <linux/locks.h>
178 #include <linux/smp_lock.h>
179 #include <asm/ioctl.h>
180 #include <asm/segment.h>
181 #include <asm/uaccess.h>
183 #ifdef CONFIG_KERNELD
184 #include <linux/kerneld.h>
187 #include <linux/blk.h>
188 #include <linux/blkpg.h>
190 #include <linux/errno.h>
191 #include <linux/lvm.h>
193 #define LVM_CORRECT_READ_AHEAD( a) \
194 if ( a < LVM_MIN_READ_AHEAD || \
195 a > LVM_MAX_READ_AHEAD) a = LVM_MAX_READ_AHEAD;
198 # define WRITEA WRITE
202 * External function prototypes
205 int init_module(void);
206 void cleanup_module(void);
208 extern int lvm_init(void);
211 static void lvm_dummy_device_request(request_queue_t
*);
212 #define DEVICE_REQUEST lvm_dummy_device_request
214 static int lvm_make_request_fn(request_queue_t
*, int, struct buffer_head
*);
216 static int lvm_blk_ioctl(struct inode
*, struct file
*, uint
, ulong
);
217 static int lvm_blk_open(struct inode
*, struct file
*);
219 static int lvm_chr_open(struct inode
*, struct file
*);
221 static int lvm_chr_close(struct inode
*, struct file
*);
222 static int lvm_blk_close(struct inode
*, struct file
*);
223 static int lvm_user_bmap(struct inode
*, struct lv_bmap
*);
225 static int lvm_chr_ioctl(struct inode
*, struct file
*, uint
, ulong
);
227 #if defined CONFIG_LVM_PROC_FS && defined CONFIG_PROC_FS
228 int lvm_proc_read_vg_info(char *, char **, off_t
, int, int *, void *);
229 int lvm_proc_read_lv_info(char *, char **, off_t
, int, int *, void *);
230 int lvm_proc_read_pv_info(char *, char **, off_t
, int, int *, void *);
231 static int lvm_proc_get_global_info(char *, char **, off_t
, int, int *, void *);
232 void lvm_do_create_proc_entry_of_vg ( vg_t
*);
233 inline void lvm_do_remove_proc_entry_of_vg ( vg_t
*);
234 inline void lvm_do_create_proc_entry_of_lv ( vg_t
*, lv_t
*);
235 inline void lvm_do_remove_proc_entry_of_lv ( vg_t
*, lv_t
*);
236 inline void lvm_do_create_proc_entry_of_pv ( vg_t
*, pv_t
*);
237 inline void lvm_do_remove_proc_entry_of_pv ( vg_t
*, pv_t
*);
241 void lvm_hd_name(char *, int);
243 /* End external function prototypes */
247 * Internal function prototypes
249 static void lvm_init_vars(void);
251 /* external snapshot calls */
252 extern inline int lvm_get_blksize(kdev_t
);
253 extern int lvm_snapshot_alloc(lv_t
*);
254 extern void lvm_snapshot_fill_COW_page(vg_t
*, lv_t
*);
255 extern int lvm_snapshot_COW(kdev_t
, ulong
, ulong
, ulong
, lv_t
*);
256 extern int lvm_snapshot_remap_block(kdev_t
*, ulong
*, ulong
, lv_t
*);
257 extern void lvm_snapshot_release(lv_t
*);
258 extern int lvm_write_COW_table_block(vg_t
*, lv_t
*);
259 extern inline void lvm_hash_link(lv_block_exception_t
*, kdev_t
, ulong
, lv_t
*);
260 extern int lvm_snapshot_alloc_hash_table(lv_t
*);
261 extern void lvm_drop_snapshot(lv_t
*, char *);
264 extern void (*lvm_hd_name_ptr
) (char *, int);
266 static int lvm_map(struct buffer_head
*, int);
267 static int lvm_do_lock_lvm(void);
268 static int lvm_do_le_remap(vg_t
*, void *);
270 static int lvm_do_pv_create(pv_t
*, vg_t
*, ulong
);
271 static int lvm_do_pv_remove(vg_t
*, ulong
);
272 static int lvm_do_lv_create(int, char *, lv_t
*);
273 static int lvm_do_lv_extend_reduce(int, char *, lv_t
*);
274 static int lvm_do_lv_remove(int, char *, int);
275 static int lvm_do_lv_rename(vg_t
*, lv_req_t
*, lv_t
*);
276 static int lvm_do_lv_status_byname(vg_t
*r
, void *);
277 static int lvm_do_lv_status_byindex(vg_t
*, void *);
278 static int lvm_do_lv_status_bydev(vg_t
*, void *);
280 static int lvm_do_pe_lock_unlock(vg_t
*r
, void *);
282 static int lvm_do_pv_change(vg_t
*, void*);
283 static int lvm_do_pv_status(vg_t
*, void *);
285 static int lvm_do_vg_create(int, void *);
286 static int lvm_do_vg_extend(vg_t
*, void *);
287 static int lvm_do_vg_reduce(vg_t
*, void *);
288 static int lvm_do_vg_rename(vg_t
*, void *);
289 static int lvm_do_vg_remove(int);
290 static void lvm_geninit(struct gendisk
*);
292 static struct inode
*lvm_get_inode(int);
293 void lvm_clear_inode(struct inode
*);
295 /* END Internal function prototypes */
298 /* volume group descriptor area pointers */
299 static vg_t
*vg
[ABS_MAX_VG
];
301 #ifdef CONFIG_DEVFS_FS
302 static devfs_handle_t lvm_devfs_handle
;
303 static devfs_handle_t vg_devfs_handle
[MAX_VG
];
304 static devfs_handle_t ch_devfs_handle
[MAX_VG
];
305 static devfs_handle_t lv_devfs_handle
[MAX_LV
];
308 static pv_t
*pvp
= NULL
;
309 static lv_t
*lvp
= NULL
;
310 static pe_t
*pep
= NULL
;
311 static pe_t
*pep1
= NULL
;
312 static char *basename
= NULL
;
315 /* map from block minor number to VG and LV numbers */
320 static vg_lv_map_t vg_lv_map
[ABS_MAX_LV
];
323 /* Request structures (lvm_chr_ioctl()) */
324 static pv_change_req_t pv_change_req
;
325 static pv_flush_req_t pv_flush_req
;
326 static pv_status_req_t pv_status_req
;
327 static pe_lock_req_t pe_lock_req
;
328 static le_remap_req_t le_remap_req
;
329 static lv_req_t lv_req
;
331 #ifdef LVM_TOTAL_RESET
332 static int lvm_reset_spindown
= 0;
335 static char pv_name
[NAME_LEN
];
336 /* static char rootvg[NAME_LEN] = { 0, }; */
337 const char *const lvm_name
= LVM_NAME
;
339 static int loadtime
= 0;
340 static uint vg_count
= 0;
341 static long lvm_chr_open_count
= 0;
342 static ushort lvm_iop_version
= LVM_DRIVER_IOP_VERSION
;
343 static DECLARE_WAIT_QUEUE_HEAD(lvm_snapshot_wait
);
344 static DECLARE_WAIT_QUEUE_HEAD(lvm_wait
);
345 static DECLARE_WAIT_QUEUE_HEAD(lvm_map_wait
);
347 static spinlock_t lvm_lock
= SPIN_LOCK_UNLOCKED
;
348 static spinlock_t lvm_snapshot_lock
= SPIN_LOCK_UNLOCKED
;
350 #if defined CONFIG_LVM_PROC_FS && defined CONFIG_PROC_FS
351 static struct proc_dir_entry
*lvm_proc_dir
= NULL
;
352 static struct proc_dir_entry
*lvm_proc_vg_subdir
= NULL
;
353 struct proc_dir_entry
*pde
= NULL
;
356 static struct file_operations lvm_chr_fops
=
359 release
: lvm_chr_close
,
360 ioctl
: lvm_chr_ioctl
,
363 #define BLOCK_DEVICE_OPERATIONS
364 /* block device operations structure needed for 2.3.38? and above */
365 static struct block_device_operations lvm_blk_dops
=
368 release
: lvm_blk_close
,
369 ioctl
: lvm_blk_ioctl
,
373 /* gendisk structures */
374 static struct hd_struct lvm_hd_struct
[MAX_LV
];
375 static int lvm_blocksizes
[MAX_LV
] =
377 static int lvm_size
[MAX_LV
] =
379 static struct gendisk lvm_gendisk
=
381 MAJOR_NR
, /* major # */
382 LVM_NAME
, /* name of major */
383 0, /* number of times minor is shifted
385 1, /* maximum partitions per device */
386 lvm_hd_struct
, /* partition table */
387 lvm_size
, /* device size in blocks, copied
389 MAX_LV
, /* number or real devices */
391 NULL
, /* pointer to next gendisk struct (internal) */
397 * Module initialization...
399 int init_module(void)
402 * Driver initialization...
405 __initfunc(int lvm_init(void))
407 int __init
lvm_init(void)
409 #endif /* #ifdef MODULE */
411 struct gendisk
*gendisk_ptr
= NULL
;
413 if (register_chrdev(LVM_CHAR_MAJOR
, lvm_name
, &lvm_chr_fops
) < 0) {
414 printk(KERN_ERR
"%s -- register_chrdev failed\n", lvm_name
);
417 #ifdef BLOCK_DEVICE_OPERATIONS
418 if (register_blkdev(MAJOR_NR
, lvm_name
, &lvm_blk_dops
) < 0)
420 if (register_blkdev(MAJOR_NR
, lvm_name
, &lvm_blk_fops
) < 0)
423 printk("%s -- register_blkdev failed\n", lvm_name
);
424 if (unregister_chrdev(LVM_CHAR_MAJOR
, lvm_name
) < 0)
425 printk(KERN_ERR
"%s -- unregister_chrdev failed\n", lvm_name
);
429 #ifdef CONFIG_DEVFS_FS
430 lvm_devfs_handle
= devfs_register(
431 0 , "lvm", 0, 0, LVM_CHAR_MAJOR
,
432 S_IFCHR
| S_IRUSR
| S_IWUSR
| S_IRGRP
,
433 &lvm_chr_fops
, NULL
);
436 #if defined CONFIG_LVM_PROC_FS && defined CONFIG_PROC_FS
437 lvm_proc_dir
= create_proc_entry (LVM_DIR
, S_IFDIR
, &proc_root
);
438 if (lvm_proc_dir
!= NULL
) {
439 lvm_proc_vg_subdir
= create_proc_entry (LVM_VG_SUBDIR
, S_IFDIR
, lvm_proc_dir
);
440 pde
= create_proc_entry(LVM_GLOBAL
, S_IFREG
, lvm_proc_dir
);
441 if ( pde
!= NULL
) pde
->read_proc
= &lvm_proc_get_global_info
;
446 lvm_geninit(&lvm_gendisk
);
448 /* insert our gendisk at the corresponding major */
449 if (gendisk_head
!= NULL
) {
450 gendisk_ptr
= gendisk_head
;
451 while (gendisk_ptr
->next
!= NULL
&&
452 gendisk_ptr
->major
> lvm_gendisk
.major
) {
453 gendisk_ptr
= gendisk_ptr
->next
;
455 lvm_gendisk
.next
= gendisk_ptr
->next
;
456 gendisk_ptr
->next
= &lvm_gendisk
;
458 gendisk_head
= &lvm_gendisk
;
459 lvm_gendisk
.next
= NULL
;
463 /* reference from drivers/block/genhd.c */
464 lvm_hd_name_ptr
= lvm_hd_name
;
467 blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR
), DEVICE_REQUEST
);
468 blk_queue_make_request(BLK_DEFAULT_QUEUE(MAJOR_NR
), lvm_make_request_fn
);
470 /* optional read root VGDA */
472 if ( *rootvg != 0) vg_read_with_pv_and_lv ( rootvg, &vg);
482 " successfully initialized\n",
483 lvm_version
, lvm_name
);
486 } /* init_module() / lvm_init() */
493 void cleanup_module(void)
495 struct gendisk
*gendisk_ptr
= NULL
, *gendisk_ptr_prev
= NULL
;
497 #ifdef CONFIG_DEVFS_FS
498 devfs_unregister (lvm_devfs_handle
);
501 if (unregister_chrdev(LVM_CHAR_MAJOR
, lvm_name
) < 0) {
502 printk(KERN_ERR
"%s -- unregister_chrdev failed\n", lvm_name
);
504 if (unregister_blkdev(MAJOR_NR
, lvm_name
) < 0) {
505 printk(KERN_ERR
"%s -- unregister_blkdev failed\n", lvm_name
);
507 blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR
));
509 gendisk_ptr
= gendisk_ptr_prev
= gendisk_head
;
510 while (gendisk_ptr
!= NULL
) {
511 if (gendisk_ptr
== &lvm_gendisk
)
513 gendisk_ptr_prev
= gendisk_ptr
;
514 gendisk_ptr
= gendisk_ptr
->next
;
516 /* delete our gendisk from chain */
517 if (gendisk_ptr
== &lvm_gendisk
)
518 gendisk_ptr_prev
->next
= gendisk_ptr
->next
;
520 blk_size
[MAJOR_NR
] = NULL
;
521 blksize_size
[MAJOR_NR
] = NULL
;
522 hardsect_size
[MAJOR_NR
] = NULL
;
524 #if defined CONFIG_LVM_PROC_FS && defined CONFIG_PROC_FS
525 remove_proc_entry(LVM_GLOBAL
, lvm_proc_dir
);
526 remove_proc_entry(LVM_VG_SUBDIR
, lvm_proc_dir
);
527 remove_proc_entry(LVM_DIR
, &proc_root
);
531 /* reference from linux/drivers/block/genhd.c */
532 lvm_hd_name_ptr
= NULL
;
535 printk(KERN_INFO
"%s -- Module successfully deactivated\n", lvm_name
);
538 } /* void cleanup_module() */
539 #endif /* #ifdef MODULE */
543 * support function to initialize lvm variables
546 __initfunc(void lvm_init_vars(void))
548 void __init
lvm_init_vars(void)
553 loadtime
= CURRENT_TIME
;
555 lvm_lock
= lvm_snapshot_lock
= SPIN_LOCK_UNLOCKED
;
557 pe_lock_req
.lock
= UNLOCK_PE
;
558 pe_lock_req
.data
.lv_dev
= \
559 pe_lock_req
.data
.pv_dev
= \
560 pe_lock_req
.data
.pv_offset
= 0;
562 /* Initialize VG pointers */
563 for (v
= 0; v
< ABS_MAX_VG
; v
++) vg
[v
] = NULL
;
565 /* Initialize LV -> VG association */
566 for (v
= 0; v
< ABS_MAX_LV
; v
++) {
567 /* index ABS_MAX_VG never used for real VG */
568 vg_lv_map
[v
].vg_number
= ABS_MAX_VG
;
569 vg_lv_map
[v
].lv_number
= -1;
573 } /* lvm_init_vars() */
576 /********************************************************************
578 * Character device functions
580 ********************************************************************/
583 * character device open routine
585 static int lvm_chr_open(struct inode
*inode
,
588 int minor
= MINOR(inode
->i_rdev
);
592 "%s -- lvm_chr_open MINOR: %d VG#: %d mode: 0x%X lock: %d\n",
593 lvm_name
, minor
, VG_CHR(minor
), file
->f_mode
, lock
);
596 /* super user validation */
597 if (!capable(CAP_SYS_ADMIN
)) return -EACCES
;
599 /* Group special file open */
600 if (VG_CHR(minor
) > MAX_VG
) return -ENXIO
;
602 lvm_chr_open_count
++;
607 } /* lvm_chr_open() */
611 * character device i/o-control routine
613 * Only one changing process can do changing ioctl at one time,
617 static int lvm_chr_ioctl(struct inode
*inode
, struct file
*file
,
618 uint command
, ulong a
)
620 int minor
= MINOR(inode
->i_rdev
);
621 uint extendable
, l
, v
;
622 void *arg
= (void *) a
;
624 vg_t
* vg_ptr
= vg
[VG_CHR(minor
)];
626 /* otherwise cc will complain about unused variables */
632 "%s -- lvm_chr_ioctl: command: 0x%X MINOR: %d "
633 "VG#: %d mode: 0x%X\n",
634 lvm_name
, command
, minor
, VG_CHR(minor
), file
->f_mode
);
637 #ifdef LVM_TOTAL_RESET
638 if (lvm_reset_spindown
> 0) return -EACCES
;
641 /* Main command switch */
645 return lvm_do_lock_lvm();
647 case LVM_GET_IOP_VERSION
:
648 /* check lvm version to ensure driver/tools+lib
650 if (copy_to_user(arg
, &lvm_iop_version
, sizeof(ushort
)) != 0)
654 #ifdef LVM_TOTAL_RESET
656 /* lock reset function */
657 lvm_reset_spindown
= 1;
658 for (v
= 0; v
< ABS_MAX_VG
; v
++) {
659 if (vg
[v
] != NULL
) lvm_do_vg_remove(v
);
663 while (GET_USE_COUNT(&__this_module
) < 1)
665 while (GET_USE_COUNT(&__this_module
) > 1)
668 lock
= 0; /* release lock */
669 wake_up_interruptible(&lvm_wait
);
671 #endif /* LVM_TOTAL_RESET */
675 /* remap a logical extent (after moving the physical extent) */
676 return lvm_do_le_remap(vg_ptr
,arg
);
679 /* lock/unlock i/o to a physical extent to move it to another
680 physical volume (move's done in user space's pvmove) */
681 return lvm_do_pe_lock_unlock(vg_ptr
,arg
);
685 return lvm_do_vg_create(minor
, arg
);
688 /* extend a volume group */
689 return lvm_do_vg_extend(vg_ptr
, arg
);
692 /* reduce a volume group */
693 return lvm_do_vg_reduce(vg_ptr
, arg
);
696 /* rename a volume group */
697 return lvm_do_vg_rename(vg_ptr
, arg
);
700 /* remove an inactive VGDA */
701 return lvm_do_vg_remove(minor
);
704 case VG_SET_EXTENDABLE
:
705 /* set/clear extendability flag of volume group */
706 if (vg_ptr
== NULL
) return -ENXIO
;
707 if (copy_from_user(&extendable
, arg
, sizeof(extendable
)) != 0)
710 if (extendable
== VG_EXTENDABLE
||
711 extendable
== ~VG_EXTENDABLE
) {
712 if (extendable
== VG_EXTENDABLE
)
713 vg_ptr
->vg_status
|= VG_EXTENDABLE
;
715 vg_ptr
->vg_status
&= ~VG_EXTENDABLE
;
716 } else return -EINVAL
;
721 /* get volume group data (only the vg_t struct) */
722 if (vg_ptr
== NULL
) return -ENXIO
;
723 if (copy_to_user(arg
, vg_ptr
, sizeof(vg_t
)) != 0)
728 case VG_STATUS_GET_COUNT
:
729 /* get volume group count */
730 if (copy_to_user(arg
, &vg_count
, sizeof(vg_count
)) != 0)
735 case VG_STATUS_GET_NAMELIST
:
736 /* get volume group count */
737 for (l
= v
= 0; v
< ABS_MAX_VG
; v
++) {
739 if (copy_to_user(arg
+ l
* NAME_LEN
,
754 /* create, extend, reduce, remove or rename a logical volume */
755 if (vg_ptr
== NULL
) return -ENXIO
;
756 if (copy_from_user(&lv_req
, arg
, sizeof(lv_req
)) != 0)
759 if (command
!= LV_REMOVE
) {
760 if (copy_from_user(&lv
, lv_req
.lv
, sizeof(lv_t
)) != 0)
765 return lvm_do_lv_create(minor
, lv_req
.lv_name
, &lv
);
769 return lvm_do_lv_extend_reduce(minor
, lv_req
.lv_name
, &lv
);
771 return lvm_do_lv_remove(minor
, lv_req
.lv_name
, -1);
774 return lvm_do_lv_rename(vg_ptr
, &lv_req
, &lv
);
780 case LV_STATUS_BYNAME
:
781 /* get status of a logical volume by name */
782 return lvm_do_lv_status_byname(vg_ptr
, arg
);
785 case LV_STATUS_BYINDEX
:
786 /* get status of a logical volume by index */
787 return lvm_do_lv_status_byindex(vg_ptr
, arg
);
790 case LV_STATUS_BYDEV
:
791 return lvm_do_lv_status_bydev(vg_ptr
, arg
);
795 /* change a physical volume */
796 return lvm_do_pv_change(vg_ptr
,arg
);
800 /* get physical volume data (pv_t structure only) */
801 return lvm_do_pv_status(vg_ptr
,arg
);
805 /* physical volume buffer flush/invalidate */
806 if (copy_from_user(&pv_flush_req
, arg
,
807 sizeof(pv_flush_req
)) != 0)
810 fsync_dev(pv_flush_req
.pv_dev
);
811 invalidate_buffers(pv_flush_req
.pv_dev
);
817 "%s -- lvm_chr_ioctl: unknown command %x\n",
823 } /* lvm_chr_ioctl */
827 * character device close routine
829 static int lvm_chr_close(struct inode
*inode
, struct file
*file
)
832 int minor
= MINOR(inode
->i_rdev
);
834 "%s -- lvm_chr_close VG#: %d\n", lvm_name
, VG_CHR(minor
));
837 #ifdef LVM_TOTAL_RESET
838 if (lvm_reset_spindown
> 0) {
839 lvm_reset_spindown
= 0;
840 lvm_chr_open_count
= 0;
844 if (lvm_chr_open_count
> 0) lvm_chr_open_count
--;
845 if (lock
== current
->pid
) {
846 lock
= 0; /* release lock */
847 wake_up_interruptible(&lvm_wait
);
853 } /* lvm_chr_close() */
857 /********************************************************************
859 * Block device functions
861 ********************************************************************/
864 * block device open routine
866 static int lvm_blk_open(struct inode
*inode
, struct file
*file
)
868 int minor
= MINOR(inode
->i_rdev
);
870 vg_t
*vg_ptr
= vg
[VG_BLK(minor
)];
872 #ifdef DEBUG_LVM_BLK_OPEN
874 "%s -- lvm_blk_open MINOR: %d VG#: %d LV#: %d mode: 0x%X\n",
875 lvm_name
, minor
, VG_BLK(minor
), LV_BLK(minor
), file
->f_mode
);
878 #ifdef LVM_TOTAL_RESET
879 if (lvm_reset_spindown
> 0)
883 if (vg_ptr
!= NULL
&&
884 (vg_ptr
->vg_status
& VG_ACTIVE
) &&
885 (lv_ptr
= vg_ptr
->lv
[LV_BLK(minor
)]) != NULL
&&
886 LV_BLK(minor
) >= 0 &&
887 LV_BLK(minor
) < vg_ptr
->lv_max
) {
889 /* Check parallel LV spindown (LV remove) */
890 if (lv_ptr
->lv_status
& LV_SPINDOWN
) return -EPERM
;
892 /* Check inactive LV and open for read/write */
893 if (file
->f_mode
& O_RDWR
) {
894 if (!(lv_ptr
->lv_status
& LV_ACTIVE
)) return -EPERM
;
895 if (!(lv_ptr
->lv_access
& LV_WRITE
)) return -EACCES
;
898 #ifndef BLOCK_DEVICE_OPERATIONS
899 file
->f_op
= &lvm_blk_fops
;
902 /* be sure to increment VG counter */
903 if (lv_ptr
->lv_open
== 0) vg_ptr
->lv_open
++;
908 #ifdef DEBUG_LVM_BLK_OPEN
910 "%s -- lvm_blk_open MINOR: %d VG#: %d LV#: %d size: %d\n",
911 lvm_name
, minor
, VG_BLK(minor
), LV_BLK(minor
),
918 } /* lvm_blk_open() */
922 * block device i/o-control routine
924 static int lvm_blk_ioctl(struct inode
*inode
, struct file
*file
,
925 uint command
, ulong a
)
927 int minor
= MINOR(inode
->i_rdev
);
928 vg_t
*vg_ptr
= vg
[VG_BLK(minor
)];
929 lv_t
*lv_ptr
= vg_ptr
->lv
[LV_BLK(minor
)];
930 void *arg
= (void *) a
;
931 struct hd_geometry
*hd
= (struct hd_geometry
*) a
;
935 "%s -- lvm_blk_ioctl MINOR: %d command: 0x%X arg: %X "
936 "VG#: %dl LV#: %d\n",
937 lvm_name
, minor
, command
, (ulong
) arg
,
938 VG_BLK(minor
), LV_BLK(minor
));
943 /* return device size */
946 "%s -- lvm_blk_ioctl -- BLKGETSIZE: %u\n",
947 lvm_name
, lv_ptr
->lv_size
);
949 if (put_user(lv_ptr
->lv_size
, (long *)arg
))
955 /* flush buffer cache */
956 if (!capable(CAP_SYS_ADMIN
)) return -EACCES
;
960 "%s -- lvm_blk_ioctl -- BLKFLSBUF\n", lvm_name
);
962 fsync_dev(inode
->i_rdev
);
963 invalidate_buffers(inode
->i_rdev
);
968 /* set read ahead for block device */
969 if (!capable(CAP_SYS_ADMIN
)) return -EACCES
;
973 "%s -- lvm_blk_ioctl -- BLKRASET: %d sectors for %02X:%02X\n",
974 lvm_name
, (long) arg
, MAJOR(inode
->i_rdev
), minor
);
976 if ((long) arg
< LVM_MIN_READ_AHEAD
||
977 (long) arg
> LVM_MAX_READ_AHEAD
)
979 lv_ptr
->lv_read_ahead
= (long) arg
;
984 /* get current read ahead setting */
987 "%s -- lvm_blk_ioctl -- BLKRAGET\n", lvm_name
);
989 if (put_user(lv_ptr
->lv_read_ahead
, (long *)arg
))
995 /* get disk geometry */
998 "%s -- lvm_blk_ioctl -- HDIO_GETGEO\n", lvm_name
);
1003 unsigned char heads
= 64;
1004 unsigned char sectors
= 32;
1006 short cylinders
= lv_ptr
->lv_size
/ heads
/ sectors
;
1008 if (copy_to_user((char *) &hd
->heads
, &heads
,
1009 sizeof(heads
)) != 0 ||
1010 copy_to_user((char *) &hd
->sectors
, §ors
,
1011 sizeof(sectors
)) != 0 ||
1012 copy_to_user((short *) &hd
->cylinders
,
1013 &cylinders
, sizeof(cylinders
)) != 0 ||
1014 copy_to_user((long *) &hd
->start
, &start
,
1015 sizeof(start
)) != 0)
1021 "%s -- lvm_blk_ioctl -- cylinders: %d\n",
1022 lvm_name
, lv_ptr
->lv_size
/ heads
/ sectors
);
1028 /* set access flags of a logical volume */
1029 if (!capable(CAP_SYS_ADMIN
)) return -EACCES
;
1030 lv_ptr
->lv_access
= (ulong
) arg
;
1031 if ( lv_ptr
->lv_access
& LV_WRITE
)
1032 set_device_ro(lv_ptr
->lv_dev
, 0);
1034 set_device_ro(lv_ptr
->lv_dev
, 1);
1039 /* set status flags of a logical volume */
1040 if (!capable(CAP_SYS_ADMIN
)) return -EACCES
;
1041 if (!((ulong
) arg
& LV_ACTIVE
) && lv_ptr
->lv_open
> 1)
1043 lv_ptr
->lv_status
= (ulong
) arg
;
1047 /* turn logical block into (dev_t, block). non privileged. */
1048 return lvm_user_bmap(inode
, (struct lv_bmap
*) arg
);
1051 case LV_SET_ALLOCATION
:
1052 /* set allocation flags of a logical volume */
1053 if (!capable(CAP_SYS_ADMIN
)) return -EACCES
;
1054 lv_ptr
->lv_allocation
= (ulong
) arg
;
1057 case LV_SNAPSHOT_USE_RATE
:
1058 if (!(lv_ptr
->lv_access
& LV_SNAPSHOT
)) return -EPERM
;
1060 lv_snapshot_use_rate_req_t lv_snapshot_use_rate_req
;
1062 if (copy_from_user(&lv_snapshot_use_rate_req
, arg
,
1063 sizeof(lv_snapshot_use_rate_req_t
)))
1065 if (lv_snapshot_use_rate_req
.rate
< 0 ||
1066 lv_snapshot_use_rate_req
.rate
> 100) return -EFAULT
;
1068 switch (lv_snapshot_use_rate_req
.block
)
1071 lv_ptr
->lv_snapshot_use_rate
= lv_snapshot_use_rate_req
.rate
;
1072 if (lv_ptr
->lv_remap_ptr
* 100 / lv_ptr
->lv_remap_end
< lv_ptr
->lv_snapshot_use_rate
)
1073 interruptible_sleep_on (&lv_ptr
->lv_snapshot_wait
);
1082 lv_snapshot_use_rate_req
.rate
= lv_ptr
->lv_remap_ptr
* 100 / lv_ptr
->lv_remap_end
;
1083 if (copy_to_user(arg
, &lv_snapshot_use_rate_req
,
1084 sizeof(lv_snapshot_use_rate_req_t
)))
1091 "%s -- lvm_blk_ioctl: unknown command %d\n",
1097 } /* lvm_blk_ioctl() */
1101 * block device close routine
1103 static int lvm_blk_close(struct inode
*inode
, struct file
*file
)
1105 int minor
= MINOR(inode
->i_rdev
);
1106 vg_t
*vg_ptr
= vg
[VG_BLK(minor
)];
1107 lv_t
*lv_ptr
= vg_ptr
->lv
[LV_BLK(minor
)];
1111 "%s -- lvm_blk_close MINOR: %d VG#: %d LV#: %d\n",
1112 lvm_name
, minor
, VG_BLK(minor
), LV_BLK(minor
));
1115 sync_dev(inode
->i_rdev
);
1116 if (lv_ptr
->lv_open
== 1) vg_ptr
->lv_open
--;
1122 } /* lvm_blk_close() */
1125 static int lvm_user_bmap(struct inode
*inode
, struct lv_bmap
*user_result
)
1127 struct buffer_head bh
;
1128 unsigned long block
;
1131 if (get_user(block
, &user_result
->lv_block
))
1134 memset(&bh
,0,sizeof bh
);
1135 bh
.b_rsector
= block
;
1136 bh
.b_dev
= bh
.b_rdev
= inode
->i_dev
;
1137 bh
.b_size
= lvm_get_blksize(bh
.b_dev
);
1138 if ((err
=lvm_map(&bh
, READ
)) < 0) {
1139 printk("lvm map failed: %d\n", err
);
1143 return put_user( kdev_t_to_nr(bh
.b_rdev
), &user_result
->lv_dev
) ||
1144 put_user(bh
.b_rsector
, &user_result
->lv_block
) ? -EFAULT
: 0;
1149 * provide VG info for proc filesystem use (global)
1151 int lvm_vg_info(vg_t
*vg_ptr
, char *buf
) {
1153 char inactive_flag
= ' ';
1155 if (!(vg_ptr
->vg_status
& VG_ACTIVE
)) inactive_flag
= 'I';
1157 "\nVG: %c%s [%d PV, %d LV/%d open] "
1159 " Usage [KB/PE]: %d /%d total "
1160 "%d /%d used %d /%d free",
1166 vg_ptr
->pe_size
>> 1,
1167 vg_ptr
->pe_size
* vg_ptr
->pe_total
>> 1,
1169 vg_ptr
->pe_allocated
* vg_ptr
->pe_size
>> 1,
1170 vg_ptr
->pe_allocated
,
1171 (vg_ptr
->pe_total
- vg_ptr
->pe_allocated
) *
1172 vg_ptr
->pe_size
>> 1,
1173 vg_ptr
->pe_total
- vg_ptr
->pe_allocated
);
1179 * provide LV info for proc filesystem use (global)
1181 int lvm_lv_info(vg_t
*vg_ptr
, lv_t
*lv_ptr
, char *buf
) {
1183 char inactive_flag
= 'A', allocation_flag
= ' ',
1184 stripes_flag
= ' ', rw_flag
= ' ';
1186 if (!(lv_ptr
->lv_status
& LV_ACTIVE
))
1187 inactive_flag
= 'I';
1189 if (lv_ptr
->lv_access
& LV_WRITE
)
1191 allocation_flag
= 'D';
1192 if (lv_ptr
->lv_allocation
& LV_CONTIGUOUS
)
1193 allocation_flag
= 'C';
1195 if (lv_ptr
->lv_stripes
> 1)
1197 sz
+= sprintf(buf
+sz
,
1203 if (lv_ptr
->lv_stripes
> 1)
1204 sz
+= sprintf(buf
+sz
, "%-2d",
1205 lv_ptr
->lv_stripes
);
1207 sz
+= sprintf(buf
+sz
, " ");
1208 basename
= strrchr(lv_ptr
->lv_name
, '/');
1209 if ( basename
== 0) basename
= lv_ptr
->lv_name
;
1211 sz
+= sprintf(buf
+sz
, "] %-25s", basename
);
1212 if (strlen(basename
) > 25)
1213 sz
+= sprintf(buf
+sz
,
1215 sz
+= sprintf(buf
+sz
, "%9d /%-6d ",
1216 lv_ptr
->lv_size
>> 1,
1217 lv_ptr
->lv_size
/ vg_ptr
->pe_size
);
1219 if (lv_ptr
->lv_open
== 0)
1220 sz
+= sprintf(buf
+sz
, "close");
1222 sz
+= sprintf(buf
+sz
, "%dx open",
1230 * provide PV info for proc filesystem use (global)
1232 int lvm_pv_info(pv_t
*pv_ptr
, char *buf
) {
1234 char inactive_flag
= 'A', allocation_flag
= ' ';
1235 char *pv_name
= NULL
;
1237 if (!(pv_ptr
->pv_status
& PV_ACTIVE
))
1238 inactive_flag
= 'I';
1239 allocation_flag
= 'A';
1240 if (!(pv_ptr
->pv_allocatable
& PV_ALLOCATABLE
))
1241 allocation_flag
= 'N';
1242 pv_name
= strrchr(pv_ptr
->pv_name
+1,'/');
1243 if ( pv_name
== 0) pv_name
= pv_ptr
->pv_name
;
1246 "[%c%c] %-21s %8d /%-6d "
1247 "%8d /%-6d %8d /%-6d",
1252 pv_ptr
->pe_size
>> 1,
1254 pv_ptr
->pe_allocated
*
1255 pv_ptr
->pe_size
>> 1,
1256 pv_ptr
->pe_allocated
,
1258 pv_ptr
->pe_allocated
) *
1259 pv_ptr
->pe_size
>> 1,
1261 pv_ptr
->pe_allocated
);
1266 #if defined CONFIG_LVM_PROC_FS && defined CONFIG_PROC_FS
1268 * Support functions /proc-Filesystem
1271 #define LVM_PROC_BUF ( i == 0 ? dummy_buf : &buf[sz])
1274 * provide global LVM information
1276 static int lvm_proc_get_global_info(char *page
, char **start
, off_t pos
, int count
, int *eof
, void *data
)
1278 int c
, i
, l
, p
, v
, vg_counter
, pv_counter
, lv_counter
, lv_open_counter
,
1279 lv_open_total
, pe_t_bytes
, hash_table_bytes
, lv_block_exception_t_bytes
, seconds
;
1282 static char *buf
= NULL
;
1283 static char dummy_buf
[160]; /* sized for 2 lines */
1289 #ifdef DEBUG_LVM_PROC_GET_INFO
1291 "%s - lvm_proc_get_global_info CALLED pos: %lu count: %d whence: %d\n",
1292 lvm_name
, pos
, count
, whence
);
1297 if (pos
== 0 || buf
== NULL
) {
1298 sz_last
= vg_counter
= pv_counter
= lv_counter
= lv_open_counter
= \
1299 lv_open_total
= pe_t_bytes
= hash_table_bytes
= \
1300 lv_block_exception_t_bytes
= 0;
1302 /* search for activity */
1303 for (v
= 0; v
< ABS_MAX_VG
; v
++) {
1304 if ((vg_ptr
= vg
[v
]) != NULL
) {
1306 pv_counter
+= vg_ptr
->pv_cur
;
1307 lv_counter
+= vg_ptr
->lv_cur
;
1308 if (vg_ptr
->lv_cur
> 0) {
1309 for (l
= 0; l
< vg
[v
]->lv_max
; l
++) {
1310 if ((lv_ptr
= vg_ptr
->lv
[l
]) != NULL
) {
1311 pe_t_bytes
+= lv_ptr
->lv_allocated_le
;
1312 hash_table_bytes
+= lv_ptr
->lv_snapshot_hash_table_size
;
1313 if (lv_ptr
->lv_block_exception
!= NULL
)
1314 lv_block_exception_t_bytes
+= lv_ptr
->lv_remap_end
;
1315 if (lv_ptr
->lv_open
> 0) {
1317 lv_open_total
+= lv_ptr
->lv_open
;
1324 pe_t_bytes
*= sizeof(pe_t
);
1325 lv_block_exception_t_bytes
*= sizeof(lv_block_exception_t
);
1330 "%s -- vfree %d\n", lvm_name
, __LINE__
);
1337 /* 2 times: first to get size to allocate buffer,
1338 2nd to fill the malloced buffer */
1339 for (i
= 0; i
< 2; i
++) {
1341 sz
+= sprintf(LVM_PROC_BUF
,
1349 "Total: %d VG%s %d PV%s %d LV%s ",
1351 vg_counter
, vg_counter
== 1 ? "" : "s",
1352 pv_counter
, pv_counter
== 1 ? "" : "s",
1353 lv_counter
, lv_counter
== 1 ? "" : "s");
1354 sz
+= sprintf(LVM_PROC_BUF
,
1357 lv_open_counter
== 1 ? "" : "s");
1358 if (lv_open_total
> 0)
1359 sz
+= sprintf(LVM_PROC_BUF
,
1363 sz
+= sprintf(LVM_PROC_BUF
, ")");
1364 sz
+= sprintf(LVM_PROC_BUF
,
1365 "\nGlobal: %lu bytes malloced IOP version: %d ",
1366 vg_counter
* sizeof(vg_t
) +
1367 pv_counter
* sizeof(pv_t
) +
1368 lv_counter
* sizeof(lv_t
) +
1369 pe_t_bytes
+ hash_table_bytes
+ lv_block_exception_t_bytes
+ sz_last
,
1372 seconds
= CURRENT_TIME
- loadtime
;
1374 loadtime
= CURRENT_TIME
+ seconds
;
1375 if (seconds
/ 86400 > 0) {
1376 sz
+= sprintf(LVM_PROC_BUF
, "%d day%s ",
1378 seconds
/ 86400 == 0 ||
1379 seconds
/ 86400 > 1 ? "s" : "");
1381 sz
+= sprintf(LVM_PROC_BUF
, "%d:%02d:%02d active\n",
1382 (seconds
% 86400) / 3600,
1383 (seconds
% 3600) / 60,
1386 if (vg_counter
> 0) {
1387 for (v
= 0; v
< ABS_MAX_VG
; v
++) {
1389 if ((vg_ptr
= vg
[v
]) != NULL
) {
1390 sz
+= lvm_vg_info(vg_ptr
, LVM_PROC_BUF
);
1392 /* physical volumes */
1393 sz
+= sprintf(LVM_PROC_BUF
,
1395 vg_ptr
->pv_cur
== 1 ? ": " : "s:");
1397 for (p
= 0; p
< vg_ptr
->pv_max
; p
++) {
1398 if ((pv_ptr
= vg_ptr
->pv
[p
]) != NULL
) {
1399 sz
+= lvm_pv_info(pv_ptr
, LVM_PROC_BUF
);
1402 if (c
< vg_ptr
->pv_cur
)
1403 sz
+= sprintf(LVM_PROC_BUF
,
1408 /* logical volumes */
1409 sz
+= sprintf(LVM_PROC_BUF
,
1411 vg_ptr
->lv_cur
== 1 ? ": " : "s:");
1413 for (l
= 0; l
< vg_ptr
->lv_max
; l
++) {
1414 if ((lv_ptr
= vg_ptr
->lv
[l
]) != NULL
) {
1415 sz
+= lvm_lv_info(vg_ptr
, lv_ptr
, LVM_PROC_BUF
);
1417 if (c
< vg_ptr
->lv_cur
)
1418 sz
+= sprintf(LVM_PROC_BUF
,
1422 if (vg_ptr
->lv_cur
== 0) sz
+= sprintf(LVM_PROC_BUF
, "none");
1423 sz
+= sprintf(LVM_PROC_BUF
, "\n");
1434 return sprintf(page
, "%s - vmalloc error at line %d\n",
1435 lvm_name
, __LINE__
);
1450 if (sz
- pos
< count
)
1454 } /* lvm_proc_get_global_info() */
1455 #endif /* #if defined CONFIG_LVM_PROC_FS && defined CONFIG_PROC_FS */
1459 * provide VG information
1461 int lvm_proc_read_vg_info(char *page
, char **start
, off_t off
,
1462 int count
, int *eof
, void *data
) {
1466 sz
+= sprintf ( page
+sz
, "name: %s\n", vg
->vg_name
);
1467 sz
+= sprintf ( page
+sz
, "size: %u\n",
1468 vg
->pe_total
* vg
->pe_size
/ 2);
1469 sz
+= sprintf ( page
+sz
, "access: %u\n", vg
->vg_access
);
1470 sz
+= sprintf ( page
+sz
, "status: %u\n", vg
->vg_status
);
1471 sz
+= sprintf ( page
+sz
, "number: %u\n", vg
->vg_number
);
1472 sz
+= sprintf ( page
+sz
, "LV max: %u\n", vg
->lv_max
);
1473 sz
+= sprintf ( page
+sz
, "LV current: %u\n", vg
->lv_cur
);
1474 sz
+= sprintf ( page
+sz
, "LV open: %u\n", vg
->lv_open
);
1475 sz
+= sprintf ( page
+sz
, "PV max: %u\n", vg
->pv_max
);
1476 sz
+= sprintf ( page
+sz
, "PV current: %u\n", vg
->pv_cur
);
1477 sz
+= sprintf ( page
+sz
, "PV active: %u\n", vg
->pv_act
);
1478 sz
+= sprintf ( page
+sz
, "PE size: %u\n", vg
->pe_size
/ 2);
1479 sz
+= sprintf ( page
+sz
, "PE total: %u\n", vg
->pe_total
);
1480 sz
+= sprintf ( page
+sz
, "PE allocated: %u\n", vg
->pe_allocated
);
1481 sz
+= sprintf ( page
+sz
, "uuid: %s\n", vg
->vg_uuid
);
1488 * provide LV information
1490 int lvm_proc_read_lv_info(char *page
, char **start
, off_t off
,
1491 int count
, int *eof
, void *data
) {
1495 sz
+= sprintf ( page
+sz
, "name: %s\n", lv
->lv_name
);
1496 sz
+= sprintf ( page
+sz
, "size: %u\n", lv
->lv_size
);
1497 sz
+= sprintf ( page
+sz
, "access: %u\n", lv
->lv_access
);
1498 sz
+= sprintf ( page
+sz
, "status: %u\n", lv
->lv_status
);
1499 sz
+= sprintf ( page
+sz
, "number: %u\n", lv
->lv_number
);
1500 sz
+= sprintf ( page
+sz
, "open: %u\n", lv
->lv_open
);
1501 sz
+= sprintf ( page
+sz
, "allocation: %u\n", lv
->lv_allocation
);
1502 sz
+= sprintf ( page
+sz
, "device: %02u:%02u\n",
1503 MAJOR(lv
->lv_dev
), MINOR(lv
->lv_dev
));
1510 * provide PV information
1512 int lvm_proc_read_pv_info(char *page
, char **start
, off_t off
,
1513 int count
, int *eof
, void *data
) {
1517 sz
+= sprintf ( page
+sz
, "name: %s\n", pv
->pv_name
);
1518 sz
+= sprintf ( page
+sz
, "size: %u\n", pv
->pv_size
);
1519 sz
+= sprintf ( page
+sz
, "status: %u\n", pv
->pv_status
);
1520 sz
+= sprintf ( page
+sz
, "number: %u\n", pv
->pv_number
);
1521 sz
+= sprintf ( page
+sz
, "allocatable: %u\n", pv
->pv_allocatable
);
1522 sz
+= sprintf ( page
+sz
, "LV current: %u\n", pv
->lv_cur
);
1523 sz
+= sprintf ( page
+sz
, "PE size: %u\n", pv
->pe_size
/ 2);
1524 sz
+= sprintf ( page
+sz
, "PE total: %u\n", pv
->pe_total
);
1525 sz
+= sprintf ( page
+sz
, "PE allocated: %u\n", pv
->pe_allocated
);
1526 sz
+= sprintf ( page
+sz
, "device: %02u:%02u\n",
1527 MAJOR(pv
->pv_dev
), MINOR(pv
->pv_dev
));
1528 sz
+= sprintf ( page
+sz
, "uuid: %s\n", pv
->pv_uuid
);
1536 * block device support function for /usr/src/linux/drivers/block/ll_rw_blk.c
1537 * (see init_module/lvm_init)
1539 static int lvm_map(struct buffer_head
*bh
, int rw
)
1541 int minor
= MINOR(bh
->b_dev
);
1545 ulong size
= bh
->b_size
>> 9;
1546 ulong rsector_tmp
= bh
->b_blocknr
* size
;
1548 kdev_t rdev_tmp
= bh
->b_dev
;
1550 vg_t
*vg_this
= vg
[VG_BLK(minor
)];
1551 lv_t
*lv
= vg_this
->lv
[LV_BLK(minor
)];
1554 if (!(lv
->lv_status
& LV_ACTIVE
)) {
1556 "%s - lvm_map: ll_rw_blk for inactive LV %s\n",
1557 lvm_name
, lv
->lv_name
);
1561 if ((rw
== WRITE
|| rw
== WRITEA
) &&
1562 !(lv
->lv_access
& LV_WRITE
)) {
1564 "%s - lvm_map: ll_rw_blk write for readonly LV %s\n",
1565 lvm_name
, lv
->lv_name
);
1570 "%s - lvm_map minor:%d *rdev: %02d:%02d *rsector: %lu "
1578 if (rsector_tmp
+ size
> lv
->lv_size
) {
1580 "%s - lvm_map access beyond end of device; *rsector: "
1581 "%lu or size: %lu wrong for minor: %2d\n",
1582 lvm_name
, rsector_tmp
, size
, minor
);
1585 rsector_sav
= rsector_tmp
;
1586 rdev_sav
= rdev_tmp
;
1589 /* linear mapping */
1590 if (lv
->lv_stripes
< 2) {
1592 index
= rsector_tmp
/ vg_this
->pe_size
;
1593 pe_start
= lv
->lv_current_pe
[index
].pe
;
1594 rsector_tmp
= lv
->lv_current_pe
[index
].pe
+
1595 (rsector_tmp
% vg_this
->pe_size
);
1596 rdev_tmp
= lv
->lv_current_pe
[index
].dev
;
1600 "lv_current_pe[%ld].pe: %ld rdev: %02d:%02d rsector:%ld\n",
1602 lv
->lv_current_pe
[index
].pe
,
1608 /* striped mapping */
1611 ulong stripe_length
;
1613 stripe_length
= vg_this
->pe_size
* lv
->lv_stripes
;
1614 stripe_index
= (rsector_tmp
% stripe_length
) / lv
->lv_stripesize
;
1615 index
= rsector_tmp
/ stripe_length
+
1616 (stripe_index
% lv
->lv_stripes
) *
1617 (lv
->lv_allocated_le
/ lv
->lv_stripes
);
1618 pe_start
= lv
->lv_current_pe
[index
].pe
;
1619 rsector_tmp
= lv
->lv_current_pe
[index
].pe
+
1620 (rsector_tmp
% stripe_length
) -
1621 (stripe_index
% lv
->lv_stripes
) * lv
->lv_stripesize
-
1622 stripe_index
/ lv
->lv_stripes
*
1623 (lv
->lv_stripes
- 1) * lv
->lv_stripesize
;
1624 rdev_tmp
= lv
->lv_current_pe
[index
].dev
;
1629 "lv_current_pe[%ld].pe: %ld rdev: %02d:%02d rsector:%ld\n"
1630 "stripe_length: %ld stripe_index: %ld\n",
1632 lv
->lv_current_pe
[index
].pe
,
1640 /* handle physical extents on the move */
1641 if (pe_lock_req
.lock
== LOCK_PE
) {
1642 if (rdev_tmp
== pe_lock_req
.data
.pv_dev
&&
1643 rsector_tmp
>= pe_lock_req
.data
.pv_offset
&&
1644 rsector_tmp
< (pe_lock_req
.data
.pv_offset
+
1645 vg_this
->pe_size
)) {
1646 sleep_on(&lvm_map_wait
);
1647 rsector_tmp
= rsector_sav
;
1648 rdev_tmp
= rdev_sav
;
1649 goto lvm_second_remap
;
1653 if (rw
== WRITE
|| rw
== WRITEA
)
1654 lv
->lv_current_pe
[index
].writes
++;
1656 lv
->lv_current_pe
[index
].reads
++;
1658 /* snapshot volume exception handling on physical device address base */
1659 if (lv
->lv_access
& (LV_SNAPSHOT
|LV_SNAPSHOT_ORG
)) {
1660 /* original logical volume */
1661 if (lv
->lv_access
& LV_SNAPSHOT_ORG
) {
1662 if (rw
== WRITE
|| rw
== WRITEA
)
1666 /* start with first snapshot and loop thrugh all of them */
1667 for (lv_ptr
= lv
->lv_snapshot_next
;
1669 lv_ptr
= lv_ptr
->lv_snapshot_next
) {
1670 /* Check for inactive snapshot */
1671 if (!(lv_ptr
->lv_status
& LV_ACTIVE
)) continue;
1672 down(&lv
->lv_snapshot_org
->lv_snapshot_sem
);
1673 /* do we still have exception storage for this snapshot free? */
1674 if (lv_ptr
->lv_block_exception
!= NULL
) {
1675 rdev_sav
= rdev_tmp
;
1676 rsector_sav
= rsector_tmp
;
1677 if (!lvm_snapshot_remap_block(&rdev_tmp
,
1681 /* create a new mapping */
1682 if (!(ret
= lvm_snapshot_COW(rdev_tmp
,
1687 ret
= lvm_write_COW_table_block(vg_this
,
1690 rdev_tmp
= rdev_sav
;
1691 rsector_tmp
= rsector_sav
;
1693 up(&lv
->lv_snapshot_org
->lv_snapshot_sem
);
1697 /* remap snapshot logical volume */
1698 down(&lv
->lv_snapshot_sem
);
1699 if (lv
->lv_block_exception
!= NULL
)
1700 lvm_snapshot_remap_block(&rdev_tmp
, &rsector_tmp
, pe_start
, lv
);
1701 up(&lv
->lv_snapshot_sem
);
1704 bh
->b_rdev
= rdev_tmp
;
1705 bh
->b_rsector
= rsector_tmp
;
1712 * internal support functions
1717 * generate "hard disk" name
1719 void lvm_hd_name(char *buf
, int minor
)
1724 if (vg
[VG_BLK(minor
)] == NULL
||
1725 (lv_ptr
= vg
[VG_BLK(minor
)]->lv
[LV_BLK(minor
)]) == NULL
)
1727 len
= strlen(lv_ptr
->lv_name
) - 5;
1728 memcpy(buf
, &lv_ptr
->lv_name
[5], len
);
1736 * this one never should be called...
1738 static void lvm_dummy_device_request(request_queue_t
* t
)
1741 "%s -- oops, got lvm request for %02d:%02d [sector: %lu]\n",
1743 MAJOR(CURRENT
->rq_dev
),
1744 MINOR(CURRENT
->rq_dev
),
1751 * make request function
1753 static int lvm_make_request_fn(request_queue_t
*q
,
1755 struct buffer_head
*bh
)
1757 if (lvm_map(bh
, rw
)<0)
1758 return 0; /* failure, buffer_IO_error has been called, don't recurse */
1760 return 1; /* all ok, mapping done, call lower level driver */
1764 /********************************************************************
1766 * Character device support functions
1768 ********************************************************************/
1770 * character device support function logical volume manager lock
1772 static int lvm_do_lock_lvm(void)
1775 spin_lock(&lvm_lock
);
1776 if (lock
!= 0 && lock
!= current
->pid
) {
1778 printk(KERN_INFO
"lvm_do_lock_lvm: %s is locked by pid %d ...\n",
1781 spin_unlock(&lvm_lock
);
1782 interruptible_sleep_on(&lvm_wait
);
1783 if (current
->sigpending
!= 0)
1785 #ifdef LVM_TOTAL_RESET
1786 if (lvm_reset_spindown
> 0)
1789 goto lock_try_again
;
1791 lock
= current
->pid
;
1792 spin_unlock(&lvm_lock
);
1794 } /* lvm_do_lock_lvm */
1798 * character device support function lock/unlock physical extend
1800 static int lvm_do_pe_lock_unlock(vg_t
*vg_ptr
, void *arg
)
1804 if (vg_ptr
== NULL
) return -ENXIO
;
1805 if (copy_from_user(&pe_lock_req
, arg
,
1806 sizeof(pe_lock_req_t
)) != 0) return -EFAULT
;
1808 switch (pe_lock_req
.lock
) {
1810 for (p
= 0; p
< vg_ptr
->pv_max
; p
++) {
1811 if (vg_ptr
->pv
[p
] != NULL
&&
1812 pe_lock_req
.data
.pv_dev
==
1813 vg_ptr
->pv
[p
]->pv_dev
)
1816 if (p
== vg_ptr
->pv_max
) return -ENXIO
;
1818 pe_lock_req
.lock
= UNLOCK_PE
;
1819 fsync_dev(pe_lock_req
.data
.lv_dev
);
1820 pe_lock_req
.lock
= LOCK_PE
;
1824 pe_lock_req
.lock
= UNLOCK_PE
;
1825 pe_lock_req
.data
.lv_dev
= \
1826 pe_lock_req
.data
.pv_dev
= \
1827 pe_lock_req
.data
.pv_offset
= 0;
1828 wake_up(&lvm_map_wait
);
1839 * character device support function logical extend remap
1841 static int lvm_do_le_remap(vg_t
*vg_ptr
, void *arg
)
1846 if (vg_ptr
== NULL
) return -ENXIO
;
1847 if (copy_from_user(&le_remap_req
, arg
,
1848 sizeof(le_remap_req_t
)) != 0)
1851 for (l
= 0; l
< vg_ptr
->lv_max
; l
++) {
1852 lv_ptr
= vg_ptr
->lv
[l
];
1853 if (lv_ptr
!= NULL
&&
1854 strcmp(lv_ptr
->lv_name
,
1855 le_remap_req
.lv_name
) == 0) {
1856 for (le
= 0; le
< lv_ptr
->lv_allocated_le
; le
++) {
1857 if (lv_ptr
->lv_current_pe
[le
].dev
==
1858 le_remap_req
.old_dev
&&
1859 lv_ptr
->lv_current_pe
[le
].pe
==
1860 le_remap_req
.old_pe
) {
1861 lv_ptr
->lv_current_pe
[le
].dev
=
1862 le_remap_req
.new_dev
;
1863 lv_ptr
->lv_current_pe
[le
].pe
=
1864 le_remap_req
.new_pe
;
1872 } /* lvm_do_le_remap() */
1876 * character device support function VGDA create
1878 int lvm_do_vg_create(int minor
, void *arg
)
1881 ulong l
, ls
= 0, p
, size
;
1886 if (vg
[VG_CHR(minor
)] != NULL
) return -EPERM
;
1888 if ((vg_ptr
= kmalloc(sizeof(vg_t
),GFP_KERNEL
)) == NULL
) {
1890 "%s -- VG_CREATE: kmalloc error VG at line %d\n",
1891 lvm_name
, __LINE__
);
1894 /* get the volume group structure */
1895 if (copy_from_user(vg_ptr
, arg
, sizeof(vg_t
)) != 0) {
1900 /* we are not that active so far... */
1901 vg_ptr
->vg_status
&= ~VG_ACTIVE
;
1902 vg
[VG_CHR(minor
)] = vg_ptr
;
1903 vg
[VG_CHR(minor
)]->pe_allocated
= 0;
1905 if (vg_ptr
->pv_max
> ABS_MAX_PV
) {
1907 "%s -- Can't activate VG: ABS_MAX_PV too small\n",
1910 vg
[VG_CHR(minor
)] = NULL
;
1913 if (vg_ptr
->lv_max
> ABS_MAX_LV
) {
1915 "%s -- Can't activate VG: ABS_MAX_LV too small for %u\n",
1916 lvm_name
, vg_ptr
->lv_max
);
1922 /* get the physical volume structures */
1923 vg_ptr
->pv_act
= vg_ptr
->pv_cur
= 0;
1924 for (p
= 0; p
< vg_ptr
->pv_max
; p
++) {
1925 /* user space address */
1926 if ((pvp
= vg_ptr
->pv
[p
]) != NULL
) {
1927 ret
= lvm_do_pv_create(pvp
, vg_ptr
, p
);
1929 lvm_do_vg_remove(minor
);
1935 size
= vg_ptr
->lv_max
* sizeof(lv_t
*);
1936 if ((snap_lv_ptr
= vmalloc ( size
)) == NULL
) {
1938 "%s -- VG_CREATE: vmalloc error snapshot LVs at line %d\n",
1939 lvm_name
, __LINE__
);
1940 lvm_do_vg_remove(minor
);
1943 memset(snap_lv_ptr
, 0, size
);
1945 /* get the logical volume structures */
1947 for (l
= 0; l
< vg_ptr
->lv_max
; l
++) {
1948 /* user space address */
1949 if ((lvp
= vg_ptr
->lv
[l
]) != NULL
) {
1950 if (copy_from_user(&lv
, lvp
, sizeof(lv_t
)) != 0) {
1951 lvm_do_vg_remove(minor
);
1954 if ( lv
.lv_access
& LV_SNAPSHOT
) {
1955 snap_lv_ptr
[ls
] = lvp
;
1956 vg_ptr
->lv
[l
] = NULL
;
1960 vg_ptr
->lv
[l
] = NULL
;
1961 /* only create original logical volumes for now */
1962 if (lvm_do_lv_create(minor
, lv
.lv_name
, &lv
) != 0) {
1963 lvm_do_vg_remove(minor
);
1969 /* Second path to correct snapshot logical volumes which are not
1970 in place during first path above */
1971 for (l
= 0; l
< ls
; l
++) {
1972 lvp
= snap_lv_ptr
[l
];
1973 if (copy_from_user(&lv
, lvp
, sizeof(lv_t
)) != 0) {
1974 lvm_do_vg_remove(minor
);
1977 if (lvm_do_lv_create(minor
, lv
.lv_name
, &lv
) != 0) {
1978 lvm_do_vg_remove(minor
);
1983 #ifdef CONFIG_DEVFS_FS
1984 vg_devfs_handle
[vg_ptr
->vg_number
] = devfs_mk_dir(0, vg_ptr
->vg_name
, NULL
);
1985 ch_devfs_handle
[vg_ptr
->vg_number
] = devfs_register(
1986 vg_devfs_handle
[vg_ptr
->vg_number
] , "group",
1987 DEVFS_FL_DEFAULT
, LVM_CHAR_MAJOR
, vg_ptr
->vg_number
,
1988 S_IFCHR
| S_IRUSR
| S_IWUSR
| S_IRGRP
,
1989 &lvm_chr_fops
, NULL
);
1992 #if defined CONFIG_LVM_PROC_FS && defined CONFIG_PROC_FS
1993 lvm_do_create_proc_entry_of_vg ( vg_ptr
);
2003 /* let's go active */
2004 vg_ptr
->vg_status
|= VG_ACTIVE
;
2007 } /* lvm_do_vg_create() */
2011 * character device support function VGDA extend
2013 static int lvm_do_vg_extend(vg_t
*vg_ptr
, void *arg
)
2019 if (vg_ptr
== NULL
) return -ENXIO
;
2020 if (vg_ptr
->pv_cur
< vg_ptr
->pv_max
) {
2021 for (p
= 0; p
< vg_ptr
->pv_max
; p
++) {
2022 if ( ( pv_ptr
= vg_ptr
->pv
[p
]) == NULL
) {
2023 ret
= lvm_do_pv_create(arg
, vg_ptr
, p
);
2024 lvm_do_create_proc_entry_of_pv ( vg_ptr
, pv_ptr
);
2025 if ( ret
!= 0) return ret
;
2027 /* We don't need the PE list
2028 in kernel space like LVs pe_t list */
2034 #ifdef LVM_GET_INODE
2035 /* insert a dummy inode for fs_may_mount */
2036 pv_ptr
->inode
= lvm_get_inode(pv_ptr
->pv_dev
);
2043 } /* lvm_do_vg_extend() */
2047 * character device support function VGDA reduce
2049 static int lvm_do_vg_reduce(vg_t
*vg_ptr
, void *arg
) {
2053 if (vg_ptr
== NULL
) return -ENXIO
;
2054 if (copy_from_user(pv_name
, arg
, sizeof(pv_name
)) != 0)
2057 for (p
= 0; p
< vg_ptr
->pv_max
; p
++) {
2058 pv_ptr
= vg_ptr
->pv
[p
];
2059 if (pv_ptr
!= NULL
&&
2060 strcmp(pv_ptr
->pv_name
,
2062 if (pv_ptr
->lv_cur
> 0) return -EPERM
;
2067 lvm_do_pv_remove(vg_ptr
, p
);
2068 /* Make PV pointer array contiguous */
2069 for (; p
< vg_ptr
->pv_max
- 1; p
++)
2070 vg_ptr
->pv
[p
] = vg_ptr
->pv
[p
+ 1];
2071 vg_ptr
->pv
[p
+ 1] = NULL
;
2076 } /* lvm_do_vg_reduce */
2080 * character device support function VG rename
2082 static int lvm_do_vg_rename(vg_t
*vg_ptr
, void *arg
)
2084 int l
= 0, p
= 0, len
= 0;
2085 char vg_name
[NAME_LEN
] = { 0,};
2086 char lv_name
[NAME_LEN
] = { 0,};
2088 lv_t
*lv_ptr
= NULL
;
2089 pv_t
*pv_ptr
= NULL
;
2091 if (copy_from_user(vg_name
, arg
, sizeof(vg_name
)) != 0)
2094 #if defined CONFIG_LVM_PROC_FS && defined CONFIG_PROC_FS
2095 lvm_do_remove_proc_entry_of_vg ( vg_ptr
);
2098 strncpy ( vg_ptr
->vg_name
, vg_name
, sizeof ( vg_name
)-1);
2099 for ( l
= 0; l
< vg_ptr
->lv_max
; l
++)
2101 if ((lv_ptr
= vg_ptr
->lv
[l
]) == NULL
) continue;
2102 strncpy(lv_ptr
->vg_name
, vg_name
, sizeof ( vg_name
));
2103 ptr
= strrchr(lv_ptr
->lv_name
, '/');
2104 if (ptr
== NULL
) ptr
= lv_ptr
->lv_name
;
2105 strncpy(lv_name
, ptr
, sizeof ( lv_name
));
2106 len
= sizeof(LVM_DIR_PREFIX
);
2107 strcpy(lv_ptr
->lv_name
, LVM_DIR_PREFIX
);
2108 strncat(lv_ptr
->lv_name
, vg_name
, NAME_LEN
- len
);
2109 len
+= strlen ( vg_name
);
2110 strncat(lv_ptr
->lv_name
, lv_name
, NAME_LEN
- len
);
2112 for ( p
= 0; p
< vg_ptr
->pv_max
; p
++)
2114 if ( (pv_ptr
= vg_ptr
->pv
[p
]) == NULL
) continue;
2115 strncpy(pv_ptr
->vg_name
, vg_name
, NAME_LEN
);
2118 #if defined CONFIG_LVM_PROC_FS && defined CONFIG_PROC_FS
2119 lvm_do_create_proc_entry_of_vg ( vg_ptr
);
2123 } /* lvm_do_vg_rename */
2127 * character device support function VGDA remove
2129 static int lvm_do_vg_remove(int minor
)
2132 vg_t
*vg_ptr
= vg
[VG_CHR(minor
)];
2135 if (vg_ptr
== NULL
) return -ENXIO
;
2137 #ifdef LVM_TOTAL_RESET
2138 if (vg_ptr
->lv_open
> 0 && lvm_reset_spindown
== 0)
2140 if (vg_ptr
->lv_open
> 0)
2144 /* let's go inactive */
2145 vg_ptr
->vg_status
&= ~VG_ACTIVE
;
2148 /* first free snapshot logical volumes */
2149 for (i
= 0; i
< vg_ptr
->lv_max
; i
++) {
2150 if (vg_ptr
->lv
[i
] != NULL
&&
2151 vg_ptr
->lv
[i
]->lv_access
& LV_SNAPSHOT
) {
2152 lvm_do_lv_remove(minor
, NULL
, i
);
2153 current
->state
= TASK_UNINTERRUPTIBLE
;
2154 schedule_timeout(1);
2157 /* then free the rest of the LVs */
2158 for (i
= 0; i
< vg_ptr
->lv_max
; i
++) {
2159 if (vg_ptr
->lv
[i
] != NULL
) {
2160 lvm_do_lv_remove(minor
, NULL
, i
);
2161 current
->state
= TASK_UNINTERRUPTIBLE
;
2162 schedule_timeout(1);
2167 for (i
= 0; i
< vg_ptr
->pv_max
; i
++) {
2168 if ((pv_ptr
= vg_ptr
->pv
[i
]) != NULL
) {
2171 "%s -- kfree %d\n", lvm_name
, __LINE__
);
2173 lvm_do_pv_remove(vg_ptr
, i
);
2177 #ifdef CONFIG_DEVFS_FS
2178 devfs_unregister (ch_devfs_handle
[vg_ptr
->vg_number
]);
2179 devfs_unregister (vg_devfs_handle
[vg_ptr
->vg_number
]);
2182 #if defined CONFIG_LVM_PROC_FS && defined CONFIG_PROC_FS
2183 lvm_do_remove_proc_entry_of_vg ( vg_ptr
);
2187 printk(KERN_DEBUG
"%s -- kfree %d\n", lvm_name
, __LINE__
);
2191 vg
[VG_CHR(minor
)] = NULL
;
2198 } /* lvm_do_vg_remove() */
2202 * character device support function physical volume create
2204 static int lvm_do_pv_create(pv_t
*pvp
, vg_t
*vg_ptr
, ulong p
) {
2205 pv_t
*pv_ptr
= NULL
;
2207 pv_ptr
= vg_ptr
->pv
[p
] = kmalloc(sizeof(pv_t
),GFP_KERNEL
);
2208 if (pv_ptr
== NULL
) {
2210 "%s -- VG_CREATE: kmalloc error PV at line %d\n",
2211 lvm_name
, __LINE__
);
2214 if (copy_from_user(pv_ptr
, pvp
, sizeof(pv_t
)) != 0) {
2217 /* We don't need the PE list
2218 in kernel space as with LVs pe_t list (see below) */
2220 pv_ptr
->pe_allocated
= 0;
2221 pv_ptr
->pv_status
= PV_ACTIVE
;
2225 #ifdef LVM_GET_INODE
2226 /* insert a dummy inode for fs_may_mount */
2227 pv_ptr
->inode
= lvm_get_inode(pv_ptr
->pv_dev
);
2231 } /* lvm_do_pv_create() */
2235 * character device support function physical volume create
2237 static int lvm_do_pv_remove(vg_t
*vg_ptr
, ulong p
) {
2238 pv_t
*pv_ptr
= vg_ptr
->pv
[p
];
2240 #if defined CONFIG_LVM_PROC_FS && defined CONFIG_PROC_FS
2241 lvm_do_remove_proc_entry_of_pv ( vg_ptr
, pv_ptr
);
2247 #ifdef LVM_GET_INODE
2248 lvm_clear_inode(pv_ptr
->inode
);
2251 vg_ptr
->pv
[p
] = NULL
;
2258 * character device support function logical volume create
2260 static int lvm_do_lv_create(int minor
, char *lv_name
, lv_t
*lv
)
2262 int e
, ret
, l
, le
, l_new
, p
, size
;
2263 ulong lv_status_save
;
2264 lv_block_exception_t
*lvbe
= lv
->lv_block_exception
;
2265 vg_t
*vg_ptr
= vg
[VG_CHR(minor
)];
2266 lv_t
*lv_ptr
= NULL
;
2268 if ((pep
= lv
->lv_current_pe
) == NULL
) return -EINVAL
;
2269 if (lv
->lv_chunk_size
> LVM_SNAPSHOT_MAX_CHUNK
)
2272 for (l
= 0; l
< vg_ptr
->lv_max
; l
++) {
2273 if (vg_ptr
->lv
[l
] != NULL
&&
2274 strcmp(vg_ptr
->lv
[l
]->lv_name
, lv_name
) == 0)
2278 /* in case of lv_remove(), lv_create() pair */
2280 if (vg_ptr
->lv
[lv
->lv_number
] == NULL
)
2281 l_new
= lv
->lv_number
;
2283 for (l
= 0; l
< vg_ptr
->lv_max
; l
++) {
2284 if (vg_ptr
->lv
[l
] == NULL
)
2285 if (l_new
== -1) l_new
= l
;
2288 if (l_new
== -1) return -EPERM
;
2291 if ((lv_ptr
= kmalloc(sizeof(lv_t
),GFP_KERNEL
)) == NULL
) {;
2292 printk(KERN_CRIT
"%s -- LV_CREATE: kmalloc error LV at line %d\n",
2293 lvm_name
, __LINE__
);
2296 /* copy preloaded LV */
2297 memcpy((char *) lv_ptr
, (char *) lv
, sizeof(lv_t
));
2299 lv_status_save
= lv_ptr
->lv_status
;
2300 lv_ptr
->lv_status
&= ~LV_ACTIVE
;
2301 lv_ptr
->lv_snapshot_org
= \
2302 lv_ptr
->lv_snapshot_prev
= \
2303 lv_ptr
->lv_snapshot_next
= NULL
;
2304 lv_ptr
->lv_block_exception
= NULL
;
2305 lv_ptr
->lv_iobuf
= NULL
;
2306 lv_ptr
->lv_snapshot_hash_table
= NULL
;
2307 lv_ptr
->lv_snapshot_hash_table_size
= 0;
2308 lv_ptr
->lv_snapshot_hash_mask
= 0;
2309 lv_ptr
->lv_COW_table_page
= NULL
;
2310 init_MUTEX(&lv_ptr
->lv_snapshot_sem
);
2311 lv_ptr
->lv_snapshot_use_rate
= 0;
2312 vg_ptr
->lv
[l
] = lv_ptr
;
2314 /* get the PE structures from user space if this
2315 is no snapshot logical volume */
2316 if (!(lv_ptr
->lv_access
& LV_SNAPSHOT
)) {
2317 size
= lv_ptr
->lv_allocated_le
* sizeof(pe_t
);
2318 if ((lv_ptr
->lv_current_pe
= vmalloc(size
)) == NULL
) {
2320 "%s -- LV_CREATE: vmalloc error LV_CURRENT_PE of %d Byte "
2322 lvm_name
, size
, __LINE__
);
2324 printk(KERN_DEBUG
"%s -- kfree %d\n", lvm_name
, __LINE__
);
2327 vg
[VG_CHR(minor
)]->lv
[l
] = NULL
;
2330 if (copy_from_user(lv_ptr
->lv_current_pe
, pep
, size
)) {
2331 vfree(lv_ptr
->lv_current_pe
);
2333 vg_ptr
->lv
[l
] = NULL
;
2336 /* correct the PE count in PVs */
2337 for (le
= 0; le
< lv_ptr
->lv_allocated_le
; le
++) {
2338 vg_ptr
->pe_allocated
++;
2339 for (p
= 0; p
< vg_ptr
->pv_cur
; p
++) {
2340 if (vg_ptr
->pv
[p
]->pv_dev
==
2341 lv_ptr
->lv_current_pe
[le
].dev
)
2342 vg_ptr
->pv
[p
]->pe_allocated
++;
2346 /* Get snapshot exception data and block list */
2348 lv_ptr
->lv_snapshot_org
=
2349 vg_ptr
->lv
[LV_BLK(lv_ptr
->lv_snapshot_minor
)];
2350 if (lv_ptr
->lv_snapshot_org
!= NULL
) {
2351 size
= lv_ptr
->lv_remap_end
* sizeof(lv_block_exception_t
);
2352 if ((lv_ptr
->lv_block_exception
= vmalloc(size
)) == NULL
) {
2354 "%s -- lvm_do_lv_create: vmalloc error LV_BLOCK_EXCEPTION "
2355 "of %d byte at line %d\n",
2356 lvm_name
, size
, __LINE__
);
2358 printk(KERN_DEBUG
"%s -- kfree %d\n", lvm_name
, __LINE__
);
2361 vg_ptr
->lv
[l
] = NULL
;
2364 if (copy_from_user(lv_ptr
->lv_block_exception
, lvbe
, size
)) {
2365 vfree(lv_ptr
->lv_block_exception
);
2367 vg
[VG_CHR(minor
)]->lv
[l
] = NULL
;
2370 /* point to the original logical volume */
2371 lv_ptr
= lv_ptr
->lv_snapshot_org
;
2373 lv_ptr
->lv_snapshot_minor
= 0;
2374 lv_ptr
->lv_snapshot_org
= lv_ptr
;
2375 lv_ptr
->lv_snapshot_prev
= NULL
;
2376 /* walk thrugh the snapshot list */
2377 while (lv_ptr
->lv_snapshot_next
!= NULL
)
2378 lv_ptr
= lv_ptr
->lv_snapshot_next
;
2379 /* now lv_ptr points to the last existing snapshot in the chain */
2380 vg_ptr
->lv
[l
]->lv_snapshot_prev
= lv_ptr
;
2381 /* our new one now back points to the previous last in the chain
2382 which can be the original logical volume */
2383 lv_ptr
= vg_ptr
->lv
[l
];
2384 /* now lv_ptr points to our new last snapshot logical volume */
2385 lv_ptr
->lv_snapshot_org
= lv_ptr
->lv_snapshot_prev
->lv_snapshot_org
;
2386 lv_ptr
->lv_snapshot_next
= NULL
;
2387 lv_ptr
->lv_current_pe
= lv_ptr
->lv_snapshot_org
->lv_current_pe
;
2388 lv_ptr
->lv_allocated_le
= lv_ptr
->lv_snapshot_org
->lv_allocated_le
;
2389 lv_ptr
->lv_current_le
= lv_ptr
->lv_snapshot_org
->lv_current_le
;
2390 lv_ptr
->lv_size
= lv_ptr
->lv_snapshot_org
->lv_size
;
2391 lv_ptr
->lv_stripes
= lv_ptr
->lv_snapshot_org
->lv_stripes
;
2392 lv_ptr
->lv_stripesize
= lv_ptr
->lv_snapshot_org
->lv_stripesize
;
2393 if ((ret
= lvm_snapshot_alloc(lv_ptr
)) != 0)
2395 vfree(lv_ptr
->lv_block_exception
);
2397 vg
[VG_CHR(minor
)]->lv
[l
] = NULL
;
2400 for ( e
= 0; e
< lv_ptr
->lv_remap_ptr
; e
++)
2401 lvm_hash_link (lv_ptr
->lv_block_exception
+ e
, lv_ptr
->lv_block_exception
[e
].rdev_org
, lv_ptr
->lv_block_exception
[e
].rsector_org
, lv_ptr
);
2402 /* need to fill the COW exception table data
2403 into the page for disk i/o */
2404 lvm_snapshot_fill_COW_page(vg_ptr
, lv_ptr
);
2405 init_waitqueue_head(&lv_ptr
->lv_snapshot_wait
);
2407 vfree(lv_ptr
->lv_block_exception
);
2409 vg_ptr
->lv
[l
] = NULL
;
2413 kfree(vg_ptr
->lv
[l
]);
2414 vg_ptr
->lv
[l
] = NULL
;
2417 } /* if ( vg[VG_CHR(minor)]->lv[l]->lv_access & LV_SNAPSHOT) */
2419 lv_ptr
= vg_ptr
->lv
[l
];
2420 lvm_gendisk
.part
[MINOR(lv_ptr
->lv_dev
)].start_sect
= 0;
2421 lvm_gendisk
.part
[MINOR(lv_ptr
->lv_dev
)].nr_sects
= lv_ptr
->lv_size
;
2422 lvm_size
[MINOR(lv_ptr
->lv_dev
)] = lv_ptr
->lv_size
>> 1;
2423 vg_lv_map
[MINOR(lv_ptr
->lv_dev
)].vg_number
= vg_ptr
->vg_number
;
2424 vg_lv_map
[MINOR(lv_ptr
->lv_dev
)].lv_number
= lv_ptr
->lv_number
;
2425 LVM_CORRECT_READ_AHEAD(lv_ptr
->lv_read_ahead
);
2427 lv_ptr
->lv_status
= lv_status_save
;
2429 #ifdef CONFIG_DEVFS_FS
2431 char *lv_tmp
, *lv_buf
= NULL
;
2433 strtok(lv
->lv_name
, "/"); /* /dev */
2434 while((lv_tmp
= strtok(NULL
, "/")) != NULL
)
2437 lv_devfs_handle
[lv
->lv_number
] = devfs_register(
2438 vg_devfs_handle
[vg_ptr
->vg_number
], lv_buf
,
2439 DEVFS_FL_DEFAULT
, LVM_BLK_MAJOR
, lv
->lv_number
,
2440 S_IFBLK
| S_IRUSR
| S_IWUSR
| S_IRGRP
,
2441 &lvm_blk_dops
, NULL
);
2445 #if defined CONFIG_LVM_PROC_FS && defined CONFIG_PROC_FS
2446 lvm_do_create_proc_entry_of_lv ( vg_ptr
, lv_ptr
);
2449 /* optionally add our new snapshot LV */
2450 if (lv_ptr
->lv_access
& LV_SNAPSHOT
) {
2451 /* sync the original logical volume */
2452 fsync_dev(lv_ptr
->lv_snapshot_org
->lv_dev
);
2453 #ifdef LVM_VFS_ENHANCEMENT
2454 /* VFS function call to sync and lock the filesystem */
2455 fsync_dev_lockfs(lv_ptr
->lv_snapshot_org
->lv_dev
);
2457 lv_ptr
->lv_snapshot_org
->lv_access
|= LV_SNAPSHOT_ORG
;
2458 lv_ptr
->lv_access
&= ~LV_SNAPSHOT_ORG
;
2459 /* put ourselve into the chain */
2460 lv_ptr
->lv_snapshot_prev
->lv_snapshot_next
= lv_ptr
;
2463 /* activate the logical volume */
2464 lv_ptr
->lv_status
|= LV_ACTIVE
;
2465 if ( lv_ptr
->lv_access
& LV_WRITE
)
2466 set_device_ro(lv_ptr
->lv_dev
, 0);
2468 set_device_ro(lv_ptr
->lv_dev
, 1);
2470 #ifdef LVM_VFS_ENHANCEMENT
2471 /* VFS function call to unlock the filesystem */
2472 if (lv_ptr
->lv_access
& LV_SNAPSHOT
) {
2473 unlockfs(lv_ptr
->lv_snapshot_org
->lv_dev
);
2477 lv_ptr
->vg
= vg_ptr
;
2480 } /* lvm_do_lv_create() */
2484 * character device support function logical volume remove
2486 static int lvm_do_lv_remove(int minor
, char *lv_name
, int l
)
2489 vg_t
*vg_ptr
= vg
[VG_CHR(minor
)];
2493 for (l
= 0; l
< vg_ptr
->lv_max
; l
++) {
2494 if (vg_ptr
->lv
[l
] != NULL
&&
2495 strcmp(vg_ptr
->lv
[l
]->lv_name
, lv_name
) == 0) {
2500 if (l
== vg_ptr
->lv_max
) return -ENXIO
;
2502 lv_ptr
= vg_ptr
->lv
[l
];
2503 #ifdef LVM_TOTAL_RESET
2504 if (lv_ptr
->lv_open
> 0 && lvm_reset_spindown
== 0)
2506 if (lv_ptr
->lv_open
> 0)
2510 /* check for deletion of snapshot source while
2511 snapshot volume still exists */
2512 if ((lv_ptr
->lv_access
& LV_SNAPSHOT_ORG
) &&
2513 lv_ptr
->lv_snapshot_next
!= NULL
)
2516 lv_ptr
->lv_status
|= LV_SPINDOWN
;
2518 /* sync the buffers */
2519 fsync_dev(lv_ptr
->lv_dev
);
2521 lv_ptr
->lv_status
&= ~LV_ACTIVE
;
2523 /* invalidate the buffers */
2524 invalidate_buffers(lv_ptr
->lv_dev
);
2526 /* reset generic hd */
2527 lvm_gendisk
.part
[MINOR(lv_ptr
->lv_dev
)].start_sect
= -1;
2528 lvm_gendisk
.part
[MINOR(lv_ptr
->lv_dev
)].nr_sects
= 0;
2529 lvm_size
[MINOR(lv_ptr
->lv_dev
)] = 0;
2531 /* reset VG/LV mapping */
2532 vg_lv_map
[MINOR(lv_ptr
->lv_dev
)].vg_number
= ABS_MAX_VG
;
2533 vg_lv_map
[MINOR(lv_ptr
->lv_dev
)].lv_number
= -1;
2535 /* correct the PE count in PVs if this is no snapshot logical volume */
2536 if (!(lv_ptr
->lv_access
& LV_SNAPSHOT
)) {
2537 /* only if this is no snapshot logical volume because
2538 we share the lv_current_pe[] structs with the
2539 original logical volume */
2540 for (le
= 0; le
< lv_ptr
->lv_allocated_le
; le
++) {
2541 vg_ptr
->pe_allocated
--;
2542 for (p
= 0; p
< vg_ptr
->pv_cur
; p
++) {
2543 if (vg_ptr
->pv
[p
]->pv_dev
==
2544 lv_ptr
->lv_current_pe
[le
].dev
)
2545 vg_ptr
->pv
[p
]->pe_allocated
--;
2548 vfree(lv_ptr
->lv_current_pe
);
2551 /* remove this snapshot logical volume from the chain */
2552 lv_ptr
->lv_snapshot_prev
->lv_snapshot_next
= lv_ptr
->lv_snapshot_next
;
2553 if (lv_ptr
->lv_snapshot_next
!= NULL
) {
2554 lv_ptr
->lv_snapshot_next
->lv_snapshot_prev
=
2555 lv_ptr
->lv_snapshot_prev
;
2557 /* no more snapshots? */
2558 if (lv_ptr
->lv_snapshot_org
->lv_snapshot_next
== NULL
)
2559 lv_ptr
->lv_snapshot_org
->lv_access
&= ~LV_SNAPSHOT_ORG
;
2560 lvm_snapshot_release(lv_ptr
);
2563 #ifdef CONFIG_DEVFS_FS
2564 devfs_unregister(lv_devfs_handle
[lv_ptr
->lv_number
]);
2567 #if defined CONFIG_LVM_PROC_FS && defined CONFIG_PROC_FS
2568 lvm_do_remove_proc_entry_of_lv ( vg_ptr
, lv_ptr
);
2572 printk(KERN_DEBUG
"%s -- kfree %d\n", lvm_name
, __LINE__
);
2575 vg_ptr
->lv
[l
] = NULL
;
2578 } /* lvm_do_lv_remove() */
2582 * character device support function logical volume extend / reduce
2584 static int lvm_do_lv_extend_reduce(int minor
, char *lv_name
, lv_t
*lv
)
2586 ulong end
, l
, le
, p
, size
, old_allocated_le
;
2587 vg_t
*vg_ptr
= vg
[VG_CHR(minor
)];
2591 if ((pep
= lv
->lv_current_pe
) == NULL
) return -EINVAL
;
2593 for (l
= 0; l
< vg_ptr
->lv_max
; l
++) {
2594 if (vg_ptr
->lv
[l
] != NULL
&&
2595 strcmp(vg_ptr
->lv
[l
]->lv_name
, lv_name
) == 0)
2598 if (l
== vg_ptr
->lv_max
) return -ENXIO
;
2599 lv_ptr
= vg_ptr
->lv
[l
];
2601 /* check for active snapshot */
2602 if (lv
->lv_access
& LV_SNAPSHOT
)
2605 lv_block_exception_t
*lvbe
, *lvbe_old
;
2606 struct list_head
* lvs_hash_table_old
;
2608 if (lv
->lv_block_exception
== NULL
) return -ENXIO
;
2609 size
= lv
->lv_remap_end
* sizeof ( lv_block_exception_t
);
2610 if ((lvbe
= vmalloc(size
)) == NULL
)
2613 "%s -- lvm_do_lv_extend_reduce: vmalloc error LV_BLOCK_EXCEPTION "
2614 "of %lu Byte at line %d\n",
2615 lvm_name
, size
, __LINE__
);
2618 if (lv
->lv_remap_end
> lv_ptr
->lv_remap_end
)
2620 if (copy_from_user(lvbe
, lv
->lv_block_exception
, size
))
2627 lvbe_old
= lv_ptr
->lv_block_exception
;
2628 lvs_hash_table_old
= lv_ptr
->lv_snapshot_hash_table
;
2630 /* we need to play on the safe side here... */
2631 down(&lv_ptr
->lv_snapshot_org
->lv_snapshot_sem
);
2632 if (lv_ptr
->lv_block_exception
== NULL
||
2633 lv_ptr
->lv_remap_ptr
> lv_ptr
->lv_remap_end
)
2635 up(&lv_ptr
->lv_snapshot_org
->lv_snapshot_sem
);
2640 lv_ptr
->lv_block_exception
,
2641 (lv
->lv_remap_end
> lv_ptr
->lv_remap_end
? lv_ptr
->lv_remap_ptr
: lv
->lv_remap_end
) * sizeof(lv_block_exception_t
));
2643 lv_ptr
->lv_block_exception
= lvbe
;
2644 lv_ptr
->lv_remap_end
= lv
->lv_remap_end
;
2645 if (lvm_snapshot_alloc_hash_table(lv_ptr
) != 0)
2647 lvm_drop_snapshot(lv_ptr
, "hash_alloc");
2648 up(&lv_ptr
->lv_snapshot_org
->lv_snapshot_sem
);
2650 vfree(lvs_hash_table_old
);
2654 for (e
= 0; e
< lv_ptr
->lv_remap_ptr
; e
++)
2655 lvm_hash_link (lv_ptr
->lv_block_exception
+ e
, lv_ptr
->lv_block_exception
[e
].rdev_org
, lv_ptr
->lv_block_exception
[e
].rsector_org
, lv_ptr
);
2657 up(&lv_ptr
->lv_snapshot_org
->lv_snapshot_sem
);
2660 vfree(lvs_hash_table_old
);
2666 /* we drop in here in case it is an original logical volume */
2667 if ((pe
= vmalloc(size
= lv
->lv_current_le
* sizeof(pe_t
))) == NULL
) {
2669 "%s -- lvm_do_lv_extend_reduce: vmalloc error LV_CURRENT_PE "
2670 "of %lu Byte at line %d\n",
2671 lvm_name
, size
, __LINE__
);
2674 /* get the PE structures from user space */
2675 if (copy_from_user(pe
, pep
, size
)) {
2682 "%s -- fsync_dev and "
2683 "invalidate_buffers for %s [%s] in %s\n",
2684 lvm_name
, lv_ptr
->lv_name
,
2685 kdevname(lv_ptr
->lv_dev
),
2689 /* reduce allocation counters on PV(s) */
2690 for (le
= 0; le
< lv_ptr
->lv_allocated_le
; le
++) {
2691 vg_ptr
->pe_allocated
--;
2692 for (p
= 0; p
< vg_ptr
->pv_cur
; p
++) {
2693 if (vg_ptr
->pv
[p
]->pv_dev
==
2694 lv_ptr
->lv_current_pe
[le
].dev
) {
2695 vg_ptr
->pv
[p
]->pe_allocated
--;
2702 /* save pointer to "old" lv/pe pointer array */
2703 pep1
= lv_ptr
->lv_current_pe
;
2704 end
= lv_ptr
->lv_current_le
;
2706 /* save open counter... */
2707 lv
->lv_open
= lv_ptr
->lv_open
;
2708 lv
->lv_snapshot_prev
= lv_ptr
->lv_snapshot_prev
;
2709 lv
->lv_snapshot_next
= lv_ptr
->lv_snapshot_next
;
2710 lv
->lv_snapshot_org
= lv_ptr
->lv_snapshot_org
;
2712 lv
->lv_current_pe
= pe
;
2714 /* save # of old allocated logical extents */
2715 old_allocated_le
= lv_ptr
->lv_allocated_le
;
2717 /* in case of shrinking -> let's flush */
2718 if ( end
> lv
->lv_current_le
) fsync_dev(lv_ptr
->lv_dev
);
2720 /* copy preloaded LV */
2721 memcpy((char *) lv_ptr
, (char *) lv
, sizeof(lv_t
));
2723 lvm_gendisk
.part
[MINOR(lv_ptr
->lv_dev
)].start_sect
= 0;
2724 lvm_gendisk
.part
[MINOR(lv_ptr
->lv_dev
)].nr_sects
= lv_ptr
->lv_size
;
2725 lvm_size
[MINOR(lv_ptr
->lv_dev
)] = lv_ptr
->lv_size
>> 1;
2726 /* vg_lv_map array doesn't have to be changed here */
2728 LVM_CORRECT_READ_AHEAD(lv_ptr
->lv_read_ahead
);
2730 /* save availiable i/o statistic data */
2731 /* linear logical volume */
2732 if (lv_ptr
->lv_stripes
< 2) {
2733 /* Check what last LE shall be used */
2734 if (end
> lv_ptr
->lv_current_le
) end
= lv_ptr
->lv_current_le
;
2735 for (le
= 0; le
< end
; le
++) {
2736 lv_ptr
->lv_current_pe
[le
].reads
+= pep1
[le
].reads
;
2737 lv_ptr
->lv_current_pe
[le
].writes
+= pep1
[le
].writes
;
2739 /* striped logical volume */
2741 uint i
, j
, source
, dest
, end
, old_stripe_size
, new_stripe_size
;
2743 old_stripe_size
= old_allocated_le
/ lv_ptr
->lv_stripes
;
2744 new_stripe_size
= lv_ptr
->lv_allocated_le
/ lv_ptr
->lv_stripes
;
2745 end
= old_stripe_size
;
2746 if (end
> new_stripe_size
) end
= new_stripe_size
;
2747 for (i
= source
= dest
= 0;
2748 i
< lv_ptr
->lv_stripes
; i
++) {
2749 for (j
= 0; j
< end
; j
++) {
2750 lv_ptr
->lv_current_pe
[dest
+ j
].reads
+=
2751 pep1
[source
+ j
].reads
;
2752 lv_ptr
->lv_current_pe
[dest
+ j
].writes
+=
2753 pep1
[source
+ j
].writes
;
2755 source
+= old_stripe_size
;
2756 dest
+= new_stripe_size
;
2760 /* extend the PE count in PVs */
2761 for (le
= 0; le
< lv_ptr
->lv_allocated_le
; le
++) {
2762 vg_ptr
->pe_allocated
++;
2763 for (p
= 0; p
< vg_ptr
->pv_cur
; p
++) {
2764 if (vg_ptr
->pv
[p
]->pv_dev
==
2765 lv_ptr
->lv_current_pe
[le
].dev
) {
2766 vg_ptr
->pv
[p
]->pe_allocated
++;
2775 if (lv
->lv_access
& LV_SNAPSHOT_ORG
)
2777 /* Correct the snapshot size information */
2778 while ((lv_ptr
= lv_ptr
->lv_snapshot_next
) != NULL
)
2780 lv_ptr
->lv_current_pe
= lv_ptr
->lv_snapshot_org
->lv_current_pe
;
2781 lv_ptr
->lv_allocated_le
= lv_ptr
->lv_snapshot_org
->lv_allocated_le
;
2782 lv_ptr
->lv_current_le
= lv_ptr
->lv_snapshot_org
->lv_current_le
;
2783 lv_ptr
->lv_size
= lv_ptr
->lv_snapshot_org
->lv_size
;
2784 lvm_gendisk
.part
[MINOR(lv_ptr
->lv_dev
)].nr_sects
= lv_ptr
->lv_size
;
2785 lvm_size
[MINOR(lv_ptr
->lv_dev
)] = lv_ptr
->lv_size
>> 1;
2790 } /* lvm_do_lv_extend_reduce() */
2794 * character device support function logical volume status by name
2796 static int lvm_do_lv_status_byname(vg_t
*vg_ptr
, void *arg
)
2802 lv_status_byname_req_t lv_status_byname_req
;
2804 if (vg_ptr
== NULL
) return -ENXIO
;
2805 if (copy_from_user(&lv_status_byname_req
, arg
,
2806 sizeof(lv_status_byname_req_t
)) != 0)
2809 if (lv_status_byname_req
.lv
== NULL
) return -EINVAL
;
2810 if (copy_from_user(&lv
, lv_status_byname_req
.lv
,
2814 for (l
= 0; l
< vg_ptr
->lv_max
; l
++) {
2815 lv_ptr
= vg_ptr
->lv
[l
];
2816 if (lv_ptr
!= NULL
&&
2817 strcmp(lv_ptr
->lv_name
,
2818 lv_status_byname_req
.lv_name
) == 0) {
2819 if (copy_to_user(lv_status_byname_req
.lv
,
2824 if (lv
.lv_current_pe
!= NULL
) {
2825 size
= lv_ptr
->lv_allocated_le
*
2827 if (copy_to_user(lv
.lv_current_pe
,
2828 lv_ptr
->lv_current_pe
,
2836 } /* lvm_do_lv_status_byname() */
2840 * character device support function logical volume status by index
2842 static int lvm_do_lv_status_byindex(vg_t
*vg_ptr
,void *arg
)
2847 lv_status_byindex_req_t lv_status_byindex_req
;
2849 if (vg_ptr
== NULL
) return -ENXIO
;
2850 if (copy_from_user(&lv_status_byindex_req
, arg
,
2851 sizeof(lv_status_byindex_req
)) != 0)
2854 if ((lvp
= lv_status_byindex_req
.lv
) == NULL
)
2856 if ( ( lv_ptr
= vg_ptr
->lv
[lv_status_byindex_req
.lv_index
]) == NULL
)
2859 if (copy_from_user(&lv
, lvp
, sizeof(lv_t
)) != 0)
2862 if (copy_to_user(lvp
, lv_ptr
, sizeof(lv_t
)) != 0)
2865 if (lv
.lv_current_pe
!= NULL
) {
2866 size
= lv_ptr
->lv_allocated_le
* sizeof(pe_t
);
2867 if (copy_to_user(lv
.lv_current_pe
,
2868 lv_ptr
->lv_current_pe
,
2873 } /* lvm_do_lv_status_byindex() */
2877 * character device support function logical volume status by device number
2879 static int lvm_do_lv_status_bydev(vg_t
* vg_ptr
, void * arg
) {
2881 lv_status_bydev_req_t lv_status_bydev_req
;
2883 if (vg_ptr
== NULL
) return -ENXIO
;
2884 if (copy_from_user(&lv_status_bydev_req
, arg
,
2885 sizeof(lv_status_bydev_req
)) != 0)
2888 for ( l
= 0; l
< vg_ptr
->lv_max
; l
++) {
2889 if ( vg_ptr
->lv
[l
] == NULL
) continue;
2890 if ( vg_ptr
->lv
[l
]->lv_dev
== lv_status_bydev_req
.dev
) break;
2893 if ( l
== vg_ptr
->lv_max
) return -ENXIO
;
2895 if (copy_to_user(lv_status_bydev_req
.lv
,
2896 vg_ptr
->lv
[l
], sizeof(lv_t
)) != 0)
2900 } /* lvm_do_lv_status_bydev() */
2904 * character device support function rename a logical volume
2906 static int lvm_do_lv_rename(vg_t
*vg_ptr
, lv_req_t
*lv_req
, lv_t
*lv
)
2910 lv_t
*lv_ptr
= NULL
;
2912 for (l
= 0; l
< vg_ptr
->lv_max
; l
++)
2914 if ( (lv_ptr
= vg_ptr
->lv
[l
]) == NULL
) continue;
2915 if (lv_ptr
->lv_dev
== lv
->lv_dev
)
2917 #if defined CONFIG_LVM_PROC_FS && defined CONFIG_PROC_FS
2918 lvm_do_remove_proc_entry_of_lv ( vg_ptr
, lv_ptr
);
2920 strncpy(lv_ptr
->lv_name
,
2923 #if defined CONFIG_LVM_PROC_FS && defined CONFIG_PROC_FS
2924 lvm_do_create_proc_entry_of_lv ( vg_ptr
, lv_ptr
);
2929 if (l
== vg_ptr
->lv_max
) ret
= -ENODEV
;
2932 } /* lvm_do_lv_rename */
2936 * character device support function physical volume change
2938 static int lvm_do_pv_change(vg_t
*vg_ptr
, void *arg
)
2942 #ifdef LVM_GET_INODE
2943 struct inode
*inode_sav
;
2946 if (vg_ptr
== NULL
) return -ENXIO
;
2947 if (copy_from_user(&pv_change_req
, arg
,
2948 sizeof(pv_change_req
)) != 0)
2951 for (p
= 0; p
< vg_ptr
->pv_max
; p
++) {
2952 pv_ptr
= vg_ptr
->pv
[p
];
2953 if (pv_ptr
!= NULL
&&
2954 strcmp(pv_ptr
->pv_name
,
2955 pv_change_req
.pv_name
) == 0) {
2956 #ifdef LVM_GET_INODE
2957 inode_sav
= pv_ptr
->inode
;
2959 if (copy_from_user(pv_ptr
,
2964 /* We don't need the PE list
2965 in kernel space as with LVs pe_t list */
2967 #ifdef LVM_GET_INODE
2968 pv_ptr
->inode
= inode_sav
;
2974 } /* lvm_do_pv_change() */
2977 * character device support function get physical volume status
2979 static int lvm_do_pv_status(vg_t
*vg_ptr
, void *arg
)
2984 if (vg_ptr
== NULL
) return -ENXIO
;
2985 if (copy_from_user(&pv_status_req
, arg
,
2986 sizeof(pv_status_req
)) != 0)
2989 for (p
= 0; p
< vg_ptr
->pv_max
; p
++) {
2990 pv_ptr
= vg_ptr
->pv
[p
];
2991 if (pv_ptr
!= NULL
&&
2992 strcmp(pv_ptr
->pv_name
,
2993 pv_status_req
.pv_name
) == 0) {
2994 if (copy_to_user(pv_status_req
.pv
,
3002 } /* lvm_do_pv_status() */
3007 * create a /proc entry for a logical volume
3009 inline void lvm_do_create_proc_entry_of_lv ( vg_t
*vg_ptr
, lv_t
*lv_ptr
) {
3012 if ( vg_ptr
->lv_subdir_pde
!= NULL
) {
3013 basename
= strrchr(lv_ptr
->lv_name
, '/');
3014 if (basename
== NULL
) basename
= lv_ptr
->lv_name
;
3016 pde
= create_proc_entry(basename
, S_IFREG
,
3017 vg_ptr
->lv_subdir_pde
);
3019 pde
->read_proc
= lvm_proc_read_lv_info
;
3027 * remove a /proc entry for a logical volume
3029 inline void lvm_do_remove_proc_entry_of_lv ( vg_t
*vg_ptr
, lv_t
*lv_ptr
) {
3032 if ( vg_ptr
->lv_subdir_pde
!= NULL
) {
3033 basename
= strrchr(lv_ptr
->lv_name
, '/');
3034 if (basename
== NULL
) basename
= lv_ptr
->lv_name
;
3036 remove_proc_entry(basename
, vg_ptr
->lv_subdir_pde
);
3042 * create a /proc entry for a physical volume
3044 inline void lvm_do_create_proc_entry_of_pv ( vg_t
*vg_ptr
, pv_t
*pv_ptr
) {
3047 basename
= strrchr(pv_ptr
->pv_name
, '/');
3048 if (basename
== NULL
) basename
= pv_ptr
->pv_name
;
3050 pde
= create_proc_entry(basename
, S_IFREG
, vg_ptr
->pv_subdir_pde
);
3052 pde
->read_proc
= lvm_proc_read_pv_info
;
3059 * remove a /proc entry for a physical volume
3061 inline void lvm_do_remove_proc_entry_of_pv ( vg_t
*vg_ptr
, pv_t
*pv_ptr
) {
3064 basename
= strrchr(pv_ptr
->pv_name
, '/');
3065 if ( vg_ptr
->pv_subdir_pde
!= NULL
) {
3066 basename
= strrchr(pv_ptr
->pv_name
, '/');
3067 if (basename
== NULL
) basename
= pv_ptr
->pv_name
;
3069 remove_proc_entry(basename
, vg_ptr
->pv_subdir_pde
);
3075 * create a /proc entry for a volume group
3077 #if defined CONFIG_LVM_PROC_FS && defined CONFIG_PROC_FS
3078 void lvm_do_create_proc_entry_of_vg ( vg_t
*vg_ptr
) {
3083 pde
= create_proc_entry(vg_ptr
->vg_name
, S_IFDIR
,
3084 lvm_proc_vg_subdir
);
3086 vg_ptr
->vg_dir_pde
= pde
;
3087 pde
= create_proc_entry("group", S_IFREG
,
3088 vg_ptr
->vg_dir_pde
);
3090 pde
->read_proc
= lvm_proc_read_vg_info
;
3093 vg_ptr
->lv_subdir_pde
=
3094 create_proc_entry(LVM_LV_SUBDIR
, S_IFDIR
,
3095 vg_ptr
->vg_dir_pde
);
3096 vg_ptr
->pv_subdir_pde
=
3097 create_proc_entry(LVM_PV_SUBDIR
, S_IFDIR
,
3098 vg_ptr
->vg_dir_pde
);
3101 if ( vg_ptr
->pv_subdir_pde
!= NULL
) {
3102 for ( l
= 0; l
< vg_ptr
->lv_max
; l
++) {
3103 if ( ( lv_ptr
= vg_ptr
->lv
[l
]) == NULL
) continue;
3104 lvm_do_create_proc_entry_of_lv ( vg_ptr
, lv_ptr
);
3106 for ( p
= 0; p
< vg_ptr
->pv_max
; p
++) {
3107 if ( ( pv_ptr
= vg_ptr
->pv
[p
]) == NULL
) continue;
3108 lvm_do_create_proc_entry_of_pv ( vg_ptr
, pv_ptr
);
3114 * remove a /proc entry for a volume group
3116 void lvm_do_remove_proc_entry_of_vg ( vg_t
*vg_ptr
) {
3121 for ( l
= 0; l
< vg_ptr
->lv_max
; l
++) {
3122 if ( ( lv_ptr
= vg_ptr
->lv
[l
]) == NULL
) continue;
3123 lvm_do_remove_proc_entry_of_lv ( vg_ptr
, vg_ptr
->lv
[l
]);
3125 for ( p
= 0; p
< vg_ptr
->pv_max
; p
++) {
3126 if ( ( pv_ptr
= vg_ptr
->pv
[p
]) == NULL
) continue;
3127 lvm_do_remove_proc_entry_of_pv ( vg_ptr
, vg_ptr
->pv
[p
]);
3129 if ( vg_ptr
->vg_dir_pde
!= NULL
) {
3130 remove_proc_entry(LVM_LV_SUBDIR
, vg_ptr
->vg_dir_pde
);
3131 remove_proc_entry(LVM_PV_SUBDIR
, vg_ptr
->vg_dir_pde
);
3132 remove_proc_entry("group", vg_ptr
->vg_dir_pde
);
3133 remove_proc_entry(vg_ptr
->vg_name
, lvm_proc_vg_subdir
);
3140 * support function initialize gendisk variables
3143 __initfunc(void lvm_geninit(struct gendisk
*lvm_gdisk
))
3146 lvm_geninit(struct gendisk
*lvm_gdisk
)
3151 #ifdef DEBUG_GENDISK
3152 printk(KERN_DEBUG
"%s -- lvm_gendisk\n", lvm_name
);
3155 for (i
= 0; i
< MAX_LV
; i
++) {
3156 lvm_gendisk
.part
[i
].start_sect
= -1; /* avoid partition check */
3157 lvm_size
[i
] = lvm_gendisk
.part
[i
].nr_sects
= 0;
3158 lvm_blocksizes
[i
] = BLOCK_SIZE
;
3161 blk_size
[MAJOR_NR
] = lvm_size
;
3162 blksize_size
[MAJOR_NR
] = lvm_blocksizes
;
3163 hardsect_size
[MAJOR_NR
] = lvm_blocksizes
;
3166 } /* lvm_gen_init() */
3169 #ifdef LVM_GET_INODE
3171 * support function to get an empty inode
3173 * Gets an empty inode to be inserted into the inode hash,
3174 * so that a physical volume can't be mounted.
3175 * This is analog to drivers/block/md.c
3177 * Is this the real thing?
3180 struct inode
*lvm_get_inode(int dev
)
3182 struct inode
*inode_this
= NULL
;
3184 /* Lock the device by inserting a dummy inode. */
3185 inode_this
= get_empty_inode();
3186 inode_this
->i_dev
= dev
;
3187 insert_inode_hash(inode_this
);
3193 * support function to clear an inode
3196 void lvm_clear_inode(struct inode
*inode
)
3199 inode
->i_state
|= I_FREEING
;
3204 #endif /* #ifdef LVM_GET_INODE */