~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
Linux/drivers/md/lvm.c

Version: ~ [ 2.4.0 ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /*
  2  * kernel/lvm.c
  3  *
  4  * Copyright (C) 1997 - 2000  Heinz Mauelshagen, Sistina Software
  5  *
  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
 10  *
 11  *
 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)
 15  * any later version.
 16  * 
 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.
 21  * 
 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. 
 26  *
 27  */
 28 
 29 /*
 30  * Changelog
 31  *
 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
 50  *                 with 2.0.x
 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()
 68  *                 to lvm_chr_ioctl()
 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()
 79  *                 and lvm_blk_write()
 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
101  *                 - lvm_chr_ioctl
102  *                   - LV_STATUS_BYINDEX
103  *                   - LV_STATUS_BYNAME
104  *                 - lvm_do_lv_create
105  *                 - lvm_do_lv_remove
106  *                 - lvm_map
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
142  *
143  */
144 
145 
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)";
148 
149 #define MAJOR_NR        LVM_BLK_MAJOR
150 #define DEVICE_OFF(device)
151 
152 /* lvm_do_lv_create calls fsync_dev_lockfs()/unlockfs() */
153 /* #define      LVM_VFS_ENHANCEMENT */
154 
155 #include <linux/config.h>
156 #include <linux/version.h>
157 
158 #ifdef MODVERSIONS
159 #undef MODULE
160 #define MODULE
161 #include <linux/modversions.h>
162 #endif
163 
164 #include <linux/module.h>
165 
166 #include <linux/kernel.h>
167 #include <linux/vmalloc.h>
168 #include <linux/slab.h>
169 #include <linux/init.h>
170 
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>
182 
183 #ifdef CONFIG_KERNELD
184 #include <linux/kerneld.h>
185 #endif
186 
187 #include <linux/blk.h>
188 #include <linux/blkpg.h>
189 
190 #include <linux/errno.h>
191 #include <linux/lvm.h>
192 
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;
196 
197 #ifndef WRITEA
198 #  define WRITEA WRITE
199 #endif
200 
201 /*
202  * External function prototypes
203  */
204 #ifdef MODULE
205 int init_module(void);
206 void cleanup_module(void);
207 #else
208 extern int lvm_init(void);
209 #endif
210 
211 static void lvm_dummy_device_request(request_queue_t *);
212 #define DEVICE_REQUEST  lvm_dummy_device_request
213 
214 static int lvm_make_request_fn(request_queue_t*, int, struct buffer_head*);
215 
216 static int lvm_blk_ioctl(struct inode *, struct file *, uint, ulong);
217 static int lvm_blk_open(struct inode *, struct file *);
218 
219 static int lvm_chr_open(struct inode *, struct file *);
220 
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 *);
224 
225 static int lvm_chr_ioctl(struct inode *, struct file *, uint, ulong);
226 
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 *);
238 #endif
239 
240 #ifdef LVM_HD_NAME
241 void lvm_hd_name(char *, int);
242 #endif
243 /* End external function prototypes */
244 
245 
246 /*
247  * Internal function prototypes
248  */
249 static void lvm_init_vars(void);
250 
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 *);
262 
263 #ifdef LVM_HD_NAME
264 extern void (*lvm_hd_name_ptr) (char *, int);
265 #endif
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 *);
269 
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 *);
279 
280 static int lvm_do_pe_lock_unlock(vg_t *r, void *);
281 
282 static int lvm_do_pv_change(vg_t*, void*);
283 static int lvm_do_pv_status(vg_t *, void *);
284 
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 *);
291 #ifdef LVM_GET_INODE
292 static struct inode *lvm_get_inode(int);
293 void lvm_clear_inode(struct inode *);
294 #endif
295 /* END Internal function prototypes */
296 
297 
298 /* volume group descriptor area pointers */
299 static vg_t *vg[ABS_MAX_VG];
300 
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];
306 #endif
307 
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;
313 
314 
315 /* map from block minor number to VG and LV numbers */
316 typedef struct {
317         int vg_number;
318         int lv_number;
319 } vg_lv_map_t;
320 static vg_lv_map_t vg_lv_map[ABS_MAX_LV];
321 
322 
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;
330 
331 #ifdef LVM_TOTAL_RESET
332 static int lvm_reset_spindown = 0;
333 #endif
334 
335 static char pv_name[NAME_LEN];
336 /* static char rootvg[NAME_LEN] = { 0, }; */
337 const char *const lvm_name = LVM_NAME;
338 static int lock = 0;
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);
346 
347 static spinlock_t lvm_lock = SPIN_LOCK_UNLOCKED;
348 static spinlock_t lvm_snapshot_lock = SPIN_LOCK_UNLOCKED;
349 
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;
354 #endif
355 
356 static struct file_operations lvm_chr_fops =
357 {
358         open:           lvm_chr_open,
359         release:        lvm_chr_close,
360         ioctl:          lvm_chr_ioctl,
361 };
362 
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 =
366 {
367         open:           lvm_blk_open,
368         release:        lvm_blk_close,
369         ioctl:          lvm_blk_ioctl,
370 };
371 
372 
373 /* gendisk structures */
374 static struct hd_struct lvm_hd_struct[MAX_LV];
375 static int lvm_blocksizes[MAX_LV] =
376 {0,};
377 static int lvm_size[MAX_LV] =
378 {0,};
379 static struct gendisk lvm_gendisk =
380 {
381         MAJOR_NR,               /* major # */
382         LVM_NAME,               /* name of major */
383         0,                      /* number of times minor is shifted
384                                    to get real minor */
385         1,                      /* maximum partitions per device */
386         lvm_hd_struct,          /* partition table */
387         lvm_size,               /* device size in blocks, copied
388                                    to block_size[] */
389         MAX_LV,                 /* number or real devices */
390         NULL,                   /* internal */
391         NULL,                   /* pointer to next gendisk struct (internal) */
392 };
393 
394 
395 #ifdef MODULE
396 /*
397  * Module initialization...
398  */
399 int init_module(void)
400 #else
401 /*
402  * Driver initialization...
403  */
404 #ifdef __initfunc
405 __initfunc(int lvm_init(void))
406 #else
407 int __init lvm_init(void)
408 #endif
409 #endif                          /* #ifdef MODULE */
410 {
411         struct gendisk *gendisk_ptr = NULL;
412 
413         if (register_chrdev(LVM_CHAR_MAJOR, lvm_name, &lvm_chr_fops) < 0) {
414                 printk(KERN_ERR "%s -- register_chrdev failed\n", lvm_name);
415                 return -EIO;
416         }
417 #ifdef BLOCK_DEVICE_OPERATIONS
418         if (register_blkdev(MAJOR_NR, lvm_name, &lvm_blk_dops) < 0)
419 #else
420         if (register_blkdev(MAJOR_NR, lvm_name, &lvm_blk_fops) < 0)
421 #endif
422         {
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);
426                 return -EIO;
427         }
428 
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);
434 #endif
435 
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;
442         }
443 #endif
444 
445         lvm_init_vars();
446         lvm_geninit(&lvm_gendisk);
447 
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;
454                 }
455                 lvm_gendisk.next = gendisk_ptr->next;
456                 gendisk_ptr->next = &lvm_gendisk;
457         } else {
458                 gendisk_head = &lvm_gendisk;
459                 lvm_gendisk.next = NULL;
460         }
461 
462 #ifdef LVM_HD_NAME
463         /* reference from drivers/block/genhd.c */
464         lvm_hd_name_ptr = lvm_hd_name;
465 #endif
466 
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);
469 
470         /* optional read root VGDA */
471 /*
472    if ( *rootvg != 0) vg_read_with_pv_and_lv ( rootvg, &vg);
473 */
474 
475         printk(KERN_INFO
476                "%s%s -- "
477 #ifdef MODULE
478                "Module"
479 #else
480                "Driver"
481 #endif
482                " successfully initialized\n",
483                lvm_version, lvm_name);
484 
485         return 0;
486 } /* init_module() / lvm_init() */
487 
488 
489 #ifdef MODULE
490 /*
491  * Module cleanup...
492  */
493 void cleanup_module(void)
494 {
495         struct gendisk *gendisk_ptr = NULL, *gendisk_ptr_prev = NULL;
496 
497 #ifdef  CONFIG_DEVFS_FS
498         devfs_unregister (lvm_devfs_handle);
499 #endif
500 
501         if (unregister_chrdev(LVM_CHAR_MAJOR, lvm_name) < 0) {
502                 printk(KERN_ERR "%s -- unregister_chrdev failed\n", lvm_name);
503         }
504         if (unregister_blkdev(MAJOR_NR, lvm_name) < 0) {
505                 printk(KERN_ERR "%s -- unregister_blkdev failed\n", lvm_name);
506         }
507         blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
508 
509         gendisk_ptr = gendisk_ptr_prev = gendisk_head;
510         while (gendisk_ptr != NULL) {
511                 if (gendisk_ptr == &lvm_gendisk)
512                         break;
513                 gendisk_ptr_prev = gendisk_ptr;
514                 gendisk_ptr = gendisk_ptr->next;
515         }
516         /* delete our gendisk from chain */
517         if (gendisk_ptr == &lvm_gendisk)
518                 gendisk_ptr_prev->next = gendisk_ptr->next;
519 
520         blk_size[MAJOR_NR] = NULL;
521         blksize_size[MAJOR_NR] = NULL;
522         hardsect_size[MAJOR_NR] = NULL;
523 
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);
528 #endif
529 
530 #ifdef LVM_HD_NAME
531         /* reference from linux/drivers/block/genhd.c */
532         lvm_hd_name_ptr = NULL;
533 #endif
534 
535         printk(KERN_INFO "%s -- Module successfully deactivated\n", lvm_name);
536 
537         return;
538 }       /* void cleanup_module() */
539 #endif  /* #ifdef MODULE */
540 
541 
542 /*
543  * support function to initialize lvm variables
544  */
545 #ifdef __initfunc
546 __initfunc(void lvm_init_vars(void))
547 #else
548 void __init lvm_init_vars(void)
549 #endif
550 {
551         int v;
552 
553         loadtime = CURRENT_TIME;
554 
555         lvm_lock = lvm_snapshot_lock = SPIN_LOCK_UNLOCKED;
556 
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;
561 
562         /* Initialize VG pointers */
563         for (v = 0; v < ABS_MAX_VG; v++) vg[v] = NULL;
564 
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;
570         }
571 
572         return;
573 } /* lvm_init_vars() */
574 
575 
576 /********************************************************************
577  *
578  * Character device functions
579  *
580  ********************************************************************/
581 
582 /*
583  * character device open routine
584  */
585 static int lvm_chr_open(struct inode *inode,
586                         struct file *file)
587 {
588         int minor = MINOR(inode->i_rdev);
589 
590 #ifdef DEBUG
591         printk(KERN_DEBUG
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);
594 #endif
595 
596         /* super user validation */
597         if (!capable(CAP_SYS_ADMIN)) return -EACCES;
598 
599         /* Group special file open */
600         if (VG_CHR(minor) > MAX_VG) return -ENXIO;
601 
602         lvm_chr_open_count++;
603 
604         MOD_INC_USE_COUNT;
605 
606         return 0;
607 } /* lvm_chr_open() */
608 
609 
610 /*
611  * character device i/o-control routine
612  *
613  * Only one changing process can do changing ioctl at one time,
614  * others will block.
615  *
616  */
617 static int lvm_chr_ioctl(struct inode *inode, struct file *file,
618                          uint command, ulong a)
619 {
620         int minor = MINOR(inode->i_rdev);
621         uint extendable, l, v;
622         void *arg = (void *) a;
623         lv_t lv;
624         vg_t* vg_ptr = vg[VG_CHR(minor)];
625 
626         /* otherwise cc will complain about unused variables */
627         (void) lvm_lock;
628 
629 
630 #ifdef DEBUG_IOCTL
631         printk(KERN_DEBUG
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);
635 #endif
636 
637 #ifdef LVM_TOTAL_RESET
638         if (lvm_reset_spindown > 0) return -EACCES;
639 #endif
640 
641         /* Main command switch */
642         switch (command) {
643         case LVM_LOCK_LVM:
644                 /* lock the LVM */
645                 return lvm_do_lock_lvm();
646 
647         case LVM_GET_IOP_VERSION:
648                 /* check lvm version to ensure driver/tools+lib
649                    interoperability */
650                 if (copy_to_user(arg, &lvm_iop_version, sizeof(ushort)) != 0)
651                         return -EFAULT;
652                 return 0;
653 
654 #ifdef LVM_TOTAL_RESET
655         case LVM_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);
660                 }
661 
662 #ifdef MODULE
663                 while (GET_USE_COUNT(&__this_module) < 1)
664                         MOD_INC_USE_COUNT;
665                 while (GET_USE_COUNT(&__this_module) > 1)
666                         MOD_DEC_USE_COUNT;
667 #endif /* MODULE */
668                 lock = 0;       /* release lock */
669                 wake_up_interruptible(&lvm_wait);
670                 return 0;
671 #endif /* LVM_TOTAL_RESET */
672 
673 
674         case LE_REMAP:
675                 /* remap a logical extent (after moving the physical extent) */
676                 return lvm_do_le_remap(vg_ptr,arg);
677 
678         case PE_LOCK_UNLOCK:
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);
682 
683         case VG_CREATE:
684                 /* create a VGDA */
685                 return lvm_do_vg_create(minor, arg);
686 
687         case VG_EXTEND:
688                 /* extend a volume group */
689                 return lvm_do_vg_extend(vg_ptr, arg);
690 
691         case VG_REDUCE:
692                 /* reduce a volume group */
693                 return lvm_do_vg_reduce(vg_ptr, arg);
694 
695         case VG_RENAME:
696                 /* rename a volume group */
697                 return lvm_do_vg_rename(vg_ptr, arg);
698 
699         case VG_REMOVE:
700                 /* remove an inactive VGDA */
701                 return lvm_do_vg_remove(minor);
702 
703 
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)
708                         return -EFAULT;
709 
710                 if (extendable == VG_EXTENDABLE ||
711                     extendable == ~VG_EXTENDABLE) {
712                         if (extendable == VG_EXTENDABLE)
713                                 vg_ptr->vg_status |= VG_EXTENDABLE;
714                         else
715                                 vg_ptr->vg_status &= ~VG_EXTENDABLE;
716                 } else return -EINVAL;
717                 return 0;
718 
719 
720         case VG_STATUS:
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)
724                         return -EFAULT;
725                 return 0;
726 
727 
728         case VG_STATUS_GET_COUNT:
729                 /* get volume group count */
730                 if (copy_to_user(arg, &vg_count, sizeof(vg_count)) != 0)
731                         return -EFAULT;
732                 return 0;
733 
734 
735         case VG_STATUS_GET_NAMELIST:
736                 /* get volume group count */
737                 for (l = v = 0; v < ABS_MAX_VG; v++) {
738                         if (vg[v] != NULL) {
739                                 if (copy_to_user(arg + l * NAME_LEN,
740                                                  vg[v]->vg_name,
741                                                  NAME_LEN) != 0)
742                                         return -EFAULT;
743                                 l++;
744                         }
745                 }
746                 return 0;
747 
748 
749         case LV_CREATE:
750         case LV_EXTEND:
751         case LV_REDUCE:
752         case LV_REMOVE:
753         case LV_RENAME:
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)
757                         return -EFAULT;
758 
759                 if (command != LV_REMOVE) {
760                         if (copy_from_user(&lv, lv_req.lv, sizeof(lv_t)) != 0)
761                                 return -EFAULT;
762                 }
763                 switch (command) {
764                 case LV_CREATE:
765                         return lvm_do_lv_create(minor, lv_req.lv_name, &lv);
766 
767                 case LV_EXTEND:
768                 case LV_REDUCE:
769                         return lvm_do_lv_extend_reduce(minor, lv_req.lv_name, &lv);
770                 case LV_REMOVE:
771                         return lvm_do_lv_remove(minor, lv_req.lv_name, -1);
772 
773                 case LV_RENAME:
774                         return lvm_do_lv_rename(vg_ptr, &lv_req, &lv);
775                 }
776 
777 
778 
779 
780         case LV_STATUS_BYNAME:
781                 /* get status of a logical volume by name */
782                 return lvm_do_lv_status_byname(vg_ptr, arg);
783 
784 
785         case LV_STATUS_BYINDEX:
786                 /* get status of a logical volume by index */
787                 return lvm_do_lv_status_byindex(vg_ptr, arg);
788 
789 
790         case LV_STATUS_BYDEV:
791                 return lvm_do_lv_status_bydev(vg_ptr, arg);
792 
793 
794         case PV_CHANGE:
795                 /* change a physical volume */
796                 return lvm_do_pv_change(vg_ptr,arg);
797 
798 
799         case PV_STATUS:
800                 /* get physical volume data (pv_t structure only) */
801                 return lvm_do_pv_status(vg_ptr,arg);
802 
803 
804         case PV_FLUSH:
805                 /* physical volume buffer flush/invalidate */
806                 if (copy_from_user(&pv_flush_req, arg,
807                                    sizeof(pv_flush_req)) != 0)
808                         return -EFAULT;
809 
810                 fsync_dev(pv_flush_req.pv_dev);
811                 invalidate_buffers(pv_flush_req.pv_dev);
812                 return 0;
813 
814 
815         default:
816                 printk(KERN_WARNING
817                        "%s -- lvm_chr_ioctl: unknown command %x\n",
818                        lvm_name, command);
819                 return -EINVAL;
820         }
821 
822         return 0;
823 } /* lvm_chr_ioctl */
824 
825 
826 /*
827  * character device close routine
828  */
829 static int lvm_chr_close(struct inode *inode, struct file *file)
830 {
831 #ifdef DEBUG
832         int minor = MINOR(inode->i_rdev);
833         printk(KERN_DEBUG
834              "%s -- lvm_chr_close   VG#: %d\n", lvm_name, VG_CHR(minor));
835 #endif
836 
837 #ifdef LVM_TOTAL_RESET
838         if (lvm_reset_spindown > 0) {
839                 lvm_reset_spindown = 0;
840                 lvm_chr_open_count = 0;
841         }
842 #endif
843 
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);
848         }
849 
850         MOD_DEC_USE_COUNT;
851 
852         return 0;
853 } /* lvm_chr_close() */
854 
855 
856 
857 /********************************************************************
858  *
859  * Block device functions
860  *
861  ********************************************************************/
862 
863 /*
864  * block device open routine
865  */
866 static int lvm_blk_open(struct inode *inode, struct file *file)
867 {
868         int minor = MINOR(inode->i_rdev);
869         lv_t *lv_ptr;
870         vg_t *vg_ptr = vg[VG_BLK(minor)];
871 
872 #ifdef DEBUG_LVM_BLK_OPEN
873         printk(KERN_DEBUG
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);
876 #endif
877 
878 #ifdef LVM_TOTAL_RESET
879         if (lvm_reset_spindown > 0)
880                 return -EPERM;
881 #endif
882 
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) {
888 
889                 /* Check parallel LV spindown (LV remove) */
890                 if (lv_ptr->lv_status & LV_SPINDOWN) return -EPERM;
891 
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;
896                 }
897 
898 #ifndef BLOCK_DEVICE_OPERATIONS
899                 file->f_op = &lvm_blk_fops;
900 #endif
901 
902                 /* be sure to increment VG counter */
903                 if (lv_ptr->lv_open == 0) vg_ptr->lv_open++;
904                 lv_ptr->lv_open++;
905 
906                 MOD_INC_USE_COUNT;
907 
908 #ifdef DEBUG_LVM_BLK_OPEN
909                 printk(KERN_DEBUG
910                        "%s -- lvm_blk_open MINOR: %d  VG#: %d  LV#: %d  size: %d\n",
911                        lvm_name, minor, VG_BLK(minor), LV_BLK(minor),
912                        lv_ptr->lv_size);
913 #endif
914 
915                 return 0;
916         }
917         return -ENXIO;
918 } /* lvm_blk_open() */
919 
920 
921 /*
922  * block device i/o-control routine
923  */
924 static int lvm_blk_ioctl(struct inode *inode, struct file *file,
925                          uint command, ulong a)
926 {
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;
932 
933 #ifdef DEBUG_IOCTL
934         printk(KERN_DEBUG
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));
939 #endif
940 
941         switch (command) {
942         case BLKGETSIZE:
943                 /* return device size */
944 #ifdef DEBUG_IOCTL
945                 printk(KERN_DEBUG
946                        "%s -- lvm_blk_ioctl -- BLKGETSIZE: %u\n",
947                        lvm_name, lv_ptr->lv_size);
948 #endif
949                 if (put_user(lv_ptr->lv_size, (long *)arg))
950                         return -EFAULT; 
951                 break;
952 
953 
954         case BLKFLSBUF:
955                 /* flush buffer cache */
956                 if (!capable(CAP_SYS_ADMIN)) return -EACCES;
957 
958 #ifdef DEBUG_IOCTL
959                 printk(KERN_DEBUG
960                        "%s -- lvm_blk_ioctl -- BLKFLSBUF\n", lvm_name);
961 #endif
962                 fsync_dev(inode->i_rdev);
963                 invalidate_buffers(inode->i_rdev);
964                 break;
965 
966 
967         case BLKRASET:
968                 /* set read ahead for block device */
969                 if (!capable(CAP_SYS_ADMIN)) return -EACCES;
970 
971 #ifdef DEBUG_IOCTL
972                 printk(KERN_DEBUG
973                        "%s -- lvm_blk_ioctl -- BLKRASET: %d sectors for %02X:%02X\n",
974                        lvm_name, (long) arg, MAJOR(inode->i_rdev), minor);
975 #endif
976                 if ((long) arg < LVM_MIN_READ_AHEAD ||
977                     (long) arg > LVM_MAX_READ_AHEAD)
978                         return -EINVAL;
979                 lv_ptr->lv_read_ahead = (long) arg;
980                 break;
981 
982 
983         case BLKRAGET:
984                 /* get current read ahead setting */
985 #ifdef DEBUG_IOCTL
986                 printk(KERN_DEBUG
987                        "%s -- lvm_blk_ioctl -- BLKRAGET\n", lvm_name);
988 #endif
989                 if (put_user(lv_ptr->lv_read_ahead, (long *)arg))
990                         return -EFAULT;
991                 break;
992 
993 
994         case HDIO_GETGEO:
995                 /* get disk geometry */
996 #ifdef DEBUG_IOCTL
997                 printk(KERN_DEBUG
998                        "%s -- lvm_blk_ioctl -- HDIO_GETGEO\n", lvm_name);
999 #endif
1000                 if (hd == NULL)
1001                         return -EINVAL;
1002                 {
1003                         unsigned char heads = 64;
1004                         unsigned char sectors = 32;
1005                         long start = 0;
1006                         short cylinders = lv_ptr->lv_size / heads / sectors;
1007 
1008                         if (copy_to_user((char *) &hd->heads, &heads,
1009                                          sizeof(heads)) != 0 ||
1010                             copy_to_user((char *) &hd->sectors, &sectors,
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)
1016                                 return -EFAULT;
1017                 }
1018 
1019 #ifdef DEBUG_IOCTL
1020                 printk(KERN_DEBUG
1021                        "%s -- lvm_blk_ioctl -- cylinders: %d\n",
1022                        lvm_name, lv_ptr->lv_size / heads / sectors);
1023 #endif
1024                 break;
1025 
1026 
1027         case LV_SET_ACCESS:
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);
1033                 else
1034                         set_device_ro(lv_ptr->lv_dev, 1);
1035                 break;
1036 
1037 
1038         case LV_SET_STATUS:
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)
1042                         return -EPERM;
1043                 lv_ptr->lv_status = (ulong) arg;
1044                 break;
1045 
1046         case LV_BMAP:
1047                 /* turn logical block into (dev_t, block). non privileged. */
1048                 return lvm_user_bmap(inode, (struct lv_bmap *) arg);
1049                 break;
1050 
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;
1055                 break;
1056 
1057         case LV_SNAPSHOT_USE_RATE:
1058                 if (!(lv_ptr->lv_access & LV_SNAPSHOT)) return -EPERM;
1059                 {
1060                         lv_snapshot_use_rate_req_t      lv_snapshot_use_rate_req;
1061 
1062                         if (copy_from_user(&lv_snapshot_use_rate_req, arg,
1063                                            sizeof(lv_snapshot_use_rate_req_t)))
1064                                 return -EFAULT;
1065                         if (lv_snapshot_use_rate_req.rate < 0 ||
1066                             lv_snapshot_use_rate_req.rate  > 100) return -EFAULT;
1067 
1068                         switch (lv_snapshot_use_rate_req.block)
1069                         {
1070                         case 0:
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);
1074                                 break;
1075 
1076                         case O_NONBLOCK:
1077                                 break;
1078 
1079                         default:
1080                                 return -EFAULT;
1081                         }
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)))
1085                                 return -EFAULT;
1086                 }
1087                 break;
1088 
1089         default:
1090                 printk(KERN_WARNING
1091                        "%s -- lvm_blk_ioctl: unknown command %d\n",
1092                        lvm_name, command);
1093                 return -EINVAL;
1094         }
1095 
1096         return 0;
1097 } /* lvm_blk_ioctl() */
1098 
1099 
1100 /*
1101  * block device close routine
1102  */
1103 static int lvm_blk_close(struct inode *inode, struct file *file)
1104 {
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)];
1108 
1109 #ifdef DEBUG
1110         printk(KERN_DEBUG
1111                "%s -- lvm_blk_close MINOR: %d  VG#: %d  LV#: %d\n",
1112                lvm_name, minor, VG_BLK(minor), LV_BLK(minor));
1113 #endif
1114 
1115         sync_dev(inode->i_rdev);
1116         if (lv_ptr->lv_open == 1) vg_ptr->lv_open--;
1117         lv_ptr->lv_open--;
1118 
1119         MOD_DEC_USE_COUNT;
1120 
1121         return 0;
1122 } /* lvm_blk_close() */
1123 
1124 
1125 static int lvm_user_bmap(struct inode *inode, struct lv_bmap *user_result)
1126 {
1127         struct buffer_head bh;
1128         unsigned long block;
1129         int err;
1130         
1131         if (get_user(block, &user_result->lv_block))
1132         return -EFAULT;
1133         
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);
1140         return -EINVAL;
1141         }
1142         
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;
1145 }     
1146 
1147 
1148 /*
1149  * provide VG info for proc filesystem use (global)
1150  */
1151 int lvm_vg_info(vg_t *vg_ptr, char *buf) {
1152         int sz = 0;
1153         char inactive_flag = ' ';
1154 
1155         if (!(vg_ptr->vg_status & VG_ACTIVE)) inactive_flag = 'I';
1156         sz = sprintf(buf,
1157                      "\nVG: %c%s  [%d PV, %d LV/%d open] "
1158                      " PE Size: %d KB\n"
1159                      "  Usage [KB/PE]: %d /%d total  "
1160                      "%d /%d used  %d /%d free",
1161                      inactive_flag,
1162                      vg_ptr->vg_name,
1163                      vg_ptr->pv_cur,
1164                      vg_ptr->lv_cur,
1165                      vg_ptr->lv_open,
1166                      vg_ptr->pe_size >> 1,
1167                      vg_ptr->pe_size * vg_ptr->pe_total >> 1,
1168                      vg_ptr->pe_total,
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);
1174         return sz;
1175 }
1176 
1177 
1178 /*
1179  * provide LV info for proc filesystem use (global)
1180  */
1181 int lvm_lv_info(vg_t *vg_ptr, lv_t *lv_ptr, char *buf) {
1182         int sz = 0;
1183         char inactive_flag = 'A', allocation_flag = ' ',
1184              stripes_flag = ' ', rw_flag = ' ';
1185 
1186         if (!(lv_ptr->lv_status & LV_ACTIVE))
1187                 inactive_flag = 'I';
1188         rw_flag = 'R';
1189         if (lv_ptr->lv_access & LV_WRITE)
1190                 rw_flag = 'W';
1191         allocation_flag = 'D';
1192         if (lv_ptr->lv_allocation & LV_CONTIGUOUS)
1193                 allocation_flag = 'C';
1194         stripes_flag = 'L';
1195         if (lv_ptr->lv_stripes > 1)
1196                 stripes_flag = 'S';
1197         sz += sprintf(buf+sz,
1198                       "[%c%c%c%c",
1199                       inactive_flag,
1200          rw_flag,
1201                       allocation_flag,
1202                       stripes_flag);
1203         if (lv_ptr->lv_stripes > 1)
1204                 sz += sprintf(buf+sz, "%-2d",
1205                               lv_ptr->lv_stripes);
1206         else
1207                 sz += sprintf(buf+sz, "  ");
1208         basename = strrchr(lv_ptr->lv_name, '/');
1209         if ( basename == 0) basename = lv_ptr->lv_name;
1210         else                basename++;
1211         sz += sprintf(buf+sz, "] %-25s", basename);
1212         if (strlen(basename) > 25)
1213                 sz += sprintf(buf+sz,
1214                               "\n                              ");
1215         sz += sprintf(buf+sz, "%9d /%-6d   ",
1216                       lv_ptr->lv_size >> 1,
1217                       lv_ptr->lv_size / vg_ptr->pe_size);
1218 
1219         if (lv_ptr->lv_open == 0)
1220                 sz += sprintf(buf+sz, "close");
1221         else
1222                 sz += sprintf(buf+sz, "%dx open",
1223                               lv_ptr->lv_open);
1224 
1225         return sz;
1226 }
1227 
1228 
1229 /*
1230  * provide PV info for proc filesystem use (global)
1231  */
1232 int lvm_pv_info(pv_t *pv_ptr, char *buf) {
1233         int sz = 0;
1234         char inactive_flag = 'A', allocation_flag = ' ';
1235         char *pv_name = NULL;
1236 
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;
1244         else               pv_name++;
1245         sz = sprintf(buf,
1246                      "[%c%c] %-21s %8d /%-6d  "
1247                      "%8d /%-6d  %8d /%-6d",
1248                      inactive_flag,
1249                      allocation_flag,
1250                      pv_name,
1251                      pv_ptr->pe_total *
1252                      pv_ptr->pe_size >> 1,
1253                      pv_ptr->pe_total,
1254                      pv_ptr->pe_allocated *
1255                      pv_ptr->pe_size >> 1,
1256                      pv_ptr->pe_allocated,
1257                      (pv_ptr->pe_total -
1258                       pv_ptr->pe_allocated) *
1259                      pv_ptr->pe_size >> 1,
1260                      pv_ptr->pe_total -
1261                      pv_ptr->pe_allocated);
1262         return sz;
1263 }
1264 
1265 
1266 #if defined CONFIG_LVM_PROC_FS && defined CONFIG_PROC_FS
1267 /*
1268  * Support functions /proc-Filesystem
1269  */
1270 
1271 #define  LVM_PROC_BUF   ( i == 0 ? dummy_buf : &buf[sz])
1272 
1273 /*
1274  * provide global LVM information
1275  */
1276 static int lvm_proc_get_global_info(char *page, char **start, off_t pos, int count, int *eof, void *data)
1277 {
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;
1280         static off_t sz;
1281         off_t sz_last;
1282         static char *buf = NULL;
1283         static char dummy_buf[160];     /* sized for 2 lines */
1284         vg_t *vg_ptr;
1285         lv_t *lv_ptr;
1286         pv_t *pv_ptr;
1287 
1288 
1289 #ifdef DEBUG_LVM_PROC_GET_INFO
1290         printk(KERN_DEBUG
1291                "%s - lvm_proc_get_global_info CALLED  pos: %lu  count: %d  whence: %d\n",
1292                lvm_name, pos, count, whence);
1293 #endif
1294 
1295         MOD_INC_USE_COUNT;
1296 
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;
1301 
1302                 /* search for activity */
1303                 for (v = 0; v < ABS_MAX_VG; v++) {
1304                         if ((vg_ptr = vg[v]) != NULL) {
1305                                 vg_counter++;
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) {
1316                                                                 lv_open_counter++;
1317                                                                 lv_open_total += lv_ptr->lv_open;
1318                                                         }
1319                                                 }
1320                                         }
1321                                 }
1322                         }
1323                 }
1324                 pe_t_bytes *= sizeof(pe_t);
1325                 lv_block_exception_t_bytes *= sizeof(lv_block_exception_t);
1326 
1327                 if (buf != NULL) {
1328 #ifdef DEBUG_KFREE
1329                         printk(KERN_DEBUG
1330                                "%s -- vfree %d\n", lvm_name, __LINE__);
1331 #endif
1332                         lock_kernel();
1333                         vfree(buf);
1334                         unlock_kernel();
1335                         buf = NULL;
1336                 }
1337                 /* 2 times: first to get size to allocate buffer,
1338                    2nd to fill the malloced buffer */
1339                 for (i = 0; i < 2; i++) {
1340                         sz = 0;
1341                         sz += sprintf(LVM_PROC_BUF,
1342                                       "LVM "
1343 #ifdef MODULE
1344                                       "module"
1345 #else
1346                                       "driver"
1347 #endif
1348                                       " %s\n\n"
1349                                     "Total:  %d VG%s  %d PV%s  %d LV%s ",
1350                                       lvm_short_version,
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,
1355                                       "(%d LV%s open",
1356                                       lv_open_counter,
1357                                       lv_open_counter == 1 ? "" : "s");
1358                         if (lv_open_total > 0)
1359                                 sz += sprintf(LVM_PROC_BUF,
1360                                               " %d times)\n",
1361                                               lv_open_total);
1362                         else
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,
1370                                       lvm_iop_version);
1371 
1372                         seconds = CURRENT_TIME - loadtime;
1373                         if (seconds < 0)
1374                                 loadtime = CURRENT_TIME + seconds;
1375                         if (seconds / 86400 > 0) {
1376                                 sz += sprintf(LVM_PROC_BUF, "%d day%s ",
1377                                               seconds / 86400,
1378                                               seconds / 86400 == 0 ||
1379                                          seconds / 86400 > 1 ? "s" : "");
1380                         }
1381                         sz += sprintf(LVM_PROC_BUF, "%d:%02d:%02d active\n",
1382                                       (seconds % 86400) / 3600,
1383                                       (seconds % 3600) / 60,
1384                                       seconds % 60);
1385 
1386                         if (vg_counter > 0) {
1387                                 for (v = 0; v < ABS_MAX_VG; v++) {
1388                                         /* volume group */
1389                                         if ((vg_ptr = vg[v]) != NULL) {
1390                                                 sz += lvm_vg_info(vg_ptr, LVM_PROC_BUF);
1391 
1392                                                 /* physical volumes */
1393                                                 sz += sprintf(LVM_PROC_BUF,
1394                                                               "\n  PV%s ",
1395                                                               vg_ptr->pv_cur == 1 ? ": " : "s:");
1396                                                 c = 0;
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);
1400 
1401                                                                 c++;
1402                                                                 if (c < vg_ptr->pv_cur)
1403                                                                         sz += sprintf(LVM_PROC_BUF,
1404                                                                                       "\n       ");
1405                                                         }
1406                                                 }
1407 
1408                                                 /* logical volumes */
1409                                                 sz += sprintf(LVM_PROC_BUF,
1410                                                            "\n    LV%s ",
1411                                                               vg_ptr->lv_cur == 1 ? ": " : "s:");
1412                                                 c = 0;
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);
1416                                                                 c++;
1417                                                                 if (c < vg_ptr->lv_cur)
1418                                                                         sz += sprintf(LVM_PROC_BUF,
1419                                                                                       "\n         ");
1420                                                         }
1421                                                 }
1422                                                 if (vg_ptr->lv_cur == 0) sz += sprintf(LVM_PROC_BUF, "none");
1423                                                 sz += sprintf(LVM_PROC_BUF, "\n");
1424                                         }
1425                                 }
1426                         }
1427                         if (buf == NULL) {
1428                                 lock_kernel();
1429                                 buf = vmalloc(sz);
1430                                 unlock_kernel();
1431                                 if (buf == NULL) {
1432                                         sz = 0;
1433                                         MOD_DEC_USE_COUNT;
1434                                         return sprintf(page, "%s - vmalloc error at line %d\n",
1435                                                      lvm_name, __LINE__);
1436                                 }
1437                         }
1438                         sz_last = sz;
1439                 }
1440         }
1441         MOD_DEC_USE_COUNT;
1442         if (pos > sz - 1) {
1443                 lock_kernel();
1444                 vfree(buf);
1445                 unlock_kernel();
1446                 buf = NULL;
1447                 return 0;
1448         }
1449         *start = &buf[pos];
1450         if (sz - pos < count)
1451                 return sz - pos;
1452         else
1453                 return count;
1454 } /* lvm_proc_get_global_info() */
1455 #endif /* #if defined CONFIG_LVM_PROC_FS && defined CONFIG_PROC_FS */
1456 
1457 
1458 /*
1459  * provide VG information
1460  */
1461 int lvm_proc_read_vg_info(char *page, char **start, off_t off,
1462                           int count, int *eof, void *data) {
1463         int sz = 0;
1464         vg_t *vg = data;
1465 
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);
1482 
1483         return sz;
1484 }
1485 
1486 
1487 /*
1488  * provide LV information
1489  */
1490 int lvm_proc_read_lv_info(char *page, char **start, off_t off,
1491                           int count, int *eof, void *data) {
1492         int sz = 0;
1493         lv_t *lv = data;
1494 
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));
1504 
1505         return sz;
1506 }
1507 
1508 
1509 /*
1510  * provide PV information
1511  */
1512 int lvm_proc_read_pv_info(char *page, char **start, off_t off,
1513                           int count, int *eof, void *data) {
1514         int sz = 0;
1515         pv_t *pv = data;
1516 
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);
1529 
1530 
1531         return sz;
1532 }
1533 
1534 
1535 /*
1536  * block device support function for /usr/src/linux/drivers/block/ll_rw_blk.c
1537  * (see init_module/lvm_init)
1538  */
1539 static int lvm_map(struct buffer_head *bh, int rw)
1540 {
1541         int minor = MINOR(bh->b_dev);
1542         int ret = 0;
1543         ulong index;
1544         ulong pe_start;
1545         ulong size = bh->b_size >> 9;
1546         ulong rsector_tmp = bh->b_blocknr * size;
1547         ulong rsector_sav;
1548         kdev_t rdev_tmp = bh->b_dev;
1549         kdev_t rdev_sav;
1550         vg_t *vg_this = vg[VG_BLK(minor)];
1551         lv_t *lv = vg_this->lv[LV_BLK(minor)];
1552 
1553 
1554         if (!(lv->lv_status & LV_ACTIVE)) {
1555                 printk(KERN_ALERT
1556                        "%s - lvm_map: ll_rw_blk for inactive LV %s\n",
1557                        lvm_name, lv->lv_name);
1558                 return -1;
1559         }
1560 
1561         if ((rw == WRITE || rw == WRITEA) &&
1562             !(lv->lv_access & LV_WRITE)) {
1563                 printk(KERN_CRIT
1564                     "%s - lvm_map: ll_rw_blk write for readonly LV %s\n",
1565                        lvm_name, lv->lv_name);
1566                 return -1;
1567         }
1568 #ifdef DEBUG_MAP
1569         printk(KERN_DEBUG
1570                "%s - lvm_map minor:%d  *rdev: %02d:%02d  *rsector: %lu  "
1571                "size:%lu\n",
1572                lvm_name, minor,
1573                MAJOR(rdev_tmp),
1574                MINOR(rdev_tmp),
1575                rsector_tmp, size);
1576 #endif
1577 
1578         if (rsector_tmp + size > lv->lv_size) {
1579                 printk(KERN_ALERT
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);
1583                 return -1;
1584         }
1585         rsector_sav = rsector_tmp;
1586         rdev_sav = rdev_tmp;
1587 
1588 lvm_second_remap:
1589         /* linear mapping */
1590         if (lv->lv_stripes < 2) {
1591                 /* get the index */
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;
1597 
1598 #ifdef DEBUG_MAP
1599                 printk(KERN_DEBUG
1600                        "lv_current_pe[%ld].pe: %ld  rdev: %02d:%02d  rsector:%ld\n",
1601                        index,
1602                        lv->lv_current_pe[index].pe,
1603                        MAJOR(rdev_tmp),
1604                        MINOR(rdev_tmp),
1605                        rsector_tmp);
1606 #endif
1607 
1608                 /* striped mapping */
1609         } else {
1610                 ulong stripe_index;
1611                 ulong stripe_length;
1612 
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;
1625         }
1626 
1627 #ifdef DEBUG_MAP
1628         printk(KERN_DEBUG
1629              "lv_current_pe[%ld].pe: %ld  rdev: %02d:%02d  rsector:%ld\n"
1630                "stripe_length: %ld  stripe_index: %ld\n",
1631                index,
1632                lv->lv_current_pe[index].pe,
1633                MAJOR(rdev_tmp),
1634                MINOR(rdev_tmp),
1635                rsector_tmp,
1636                stripe_length,
1637                stripe_index);
1638 #endif
1639 
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;
1650                 }
1651         }
1652         /* statistic */
1653         if (rw == WRITE || rw == WRITEA)
1654                 lv->lv_current_pe[index].writes++;
1655         else
1656                 lv->lv_current_pe[index].reads++;
1657 
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)
1663                         {
1664                                 lv_t *lv_ptr;
1665 
1666                                 /* start with first snapshot and loop thrugh all of them */
1667                                 for (lv_ptr = lv->lv_snapshot_next;
1668                                      lv_ptr != NULL;
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,
1678                                                                               &rsector_tmp,
1679                                                                               pe_start,
1680                                                                               lv_ptr)) {
1681                                                         /* create a new mapping */
1682                                                         if (!(ret = lvm_snapshot_COW(rdev_tmp,
1683                                                                                      rsector_tmp,
1684                                                                                      pe_start,
1685                                                                                      rsector_sav,
1686                                                                                      lv_ptr)))
1687                                                                 ret = lvm_write_COW_table_block(vg_this,
1688                                                                                                 lv_ptr);
1689                                                 }
1690                                                 rdev_tmp = rdev_sav;
1691                                                 rsector_tmp = rsector_sav;
1692                                         }
1693                                         up(&lv->lv_snapshot_org->lv_snapshot_sem);
1694                                 }
1695                         }
1696                 } else {
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);
1702                 }
1703         }
1704         bh->b_rdev = rdev_tmp;
1705         bh->b_rsector = rsector_tmp;
1706 
1707         return ret;
1708 } /* lvm_map() */
1709 
1710 
1711 /*
1712  * internal support functions
1713  */
1714 
1715 #ifdef LVM_HD_NAME
1716 /*
1717  * generate "hard disk" name
1718  */
1719 void lvm_hd_name(char *buf, int minor)
1720 {
1721         int len = 0;
1722         lv_t *lv_ptr;
1723 
1724         if (vg[VG_BLK(minor)] == NULL ||
1725             (lv_ptr = vg[VG_BLK(minor)]->lv[LV_BLK(minor)]) == NULL)
1726                 return;
1727         len = strlen(lv_ptr->lv_name) - 5;
1728         memcpy(buf, &lv_ptr->lv_name[5], len);
1729         buf[len] = 0;
1730         return;
1731 }
1732 #endif
1733 
1734 
1735 /*
1736  * this one never should be called...
1737  */
1738 static void lvm_dummy_device_request(request_queue_t * t)
1739 {
1740         printk(KERN_EMERG
1741              "%s -- oops, got lvm request for %02d:%02d [sector: %lu]\n",
1742                lvm_name,
1743                MAJOR(CURRENT->rq_dev),
1744                MINOR(CURRENT->rq_dev),
1745                CURRENT->sector);
1746         return;
1747 }
1748 
1749 
1750 /*
1751  * make request function
1752  */
1753 static int lvm_make_request_fn(request_queue_t *q,
1754                                int rw,
1755                                struct buffer_head *bh)
1756 {
1757         if (lvm_map(bh, rw)<0)
1758                 return 0; /* failure, buffer_IO_error has been called, don't recurse */
1759         else
1760                 return 1; /* all ok, mapping done, call lower level driver */
1761 }
1762 
1763 
1764 /********************************************************************
1765  *
1766  * Character device support functions
1767  *
1768  ********************************************************************/
1769 /*
1770  * character device support function logical volume manager lock
1771  */
1772 static int lvm_do_lock_lvm(void)
1773 {
1774 lock_try_again:
1775         spin_lock(&lvm_lock);
1776         if (lock != 0 && lock != current->pid) {
1777 #ifdef DEBUG_IOCTL
1778                 printk(KERN_INFO "lvm_do_lock_lvm: %s is locked by pid %d ...\n",
1779                        lvm_name, lock);
1780 #endif
1781                 spin_unlock(&lvm_lock);
1782                 interruptible_sleep_on(&lvm_wait);
1783                 if (current->sigpending != 0)
1784                         return -EINTR;
1785 #ifdef LVM_TOTAL_RESET
1786                 if (lvm_reset_spindown > 0)
1787                         return -EACCES;
1788 #endif
1789                 goto lock_try_again;
1790         }
1791         lock = current->pid;
1792         spin_unlock(&lvm_lock);
1793         return 0;
1794 } /* lvm_do_lock_lvm */
1795 
1796 
1797 /*
1798  * character device support function lock/unlock physical extend
1799  */
1800 static int lvm_do_pe_lock_unlock(vg_t *vg_ptr, void *arg)
1801 {
1802         uint p;
1803 
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;
1807 
1808         switch (pe_lock_req.lock) {
1809         case LOCK_PE:
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)
1814                                 break;
1815                 }
1816                 if (p == vg_ptr->pv_max) return -ENXIO;
1817 
1818                 pe_lock_req.lock = UNLOCK_PE;
1819                 fsync_dev(pe_lock_req.data.lv_dev);
1820                 pe_lock_req.lock = LOCK_PE;
1821                 break;
1822 
1823         case UNLOCK_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);
1829                 break;
1830 
1831         default:
1832                 return -EINVAL;
1833         }
1834         return 0;
1835 }
1836 
1837 
1838 /*
1839  * character device support function logical extend remap
1840  */
1841 static int lvm_do_le_remap(vg_t *vg_ptr, void *arg)
1842 {
1843         uint l, le;
1844         lv_t *lv_ptr;
1845 
1846         if (vg_ptr == NULL) return -ENXIO;
1847         if (copy_from_user(&le_remap_req, arg,
1848                            sizeof(le_remap_req_t)) != 0)
1849                 return -EFAULT;
1850 
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;
1865                                         return 0;
1866                                 }
1867                         }
1868                         return -EINVAL;
1869                 }
1870         }
1871         return -ENXIO;
1872 } /* lvm_do_le_remap() */
1873 
1874 
1875 /*
1876  * character device support function VGDA create
1877  */
1878 int lvm_do_vg_create(int minor, void *arg)
1879 {
1880         int ret = 0;
1881         ulong l, ls = 0, p, size;
1882         lv_t lv;
1883         vg_t *vg_ptr;
1884         lv_t **snap_lv_ptr;
1885 
1886         if (vg[VG_CHR(minor)] != NULL) return -EPERM;
1887 
1888         if ((vg_ptr = kmalloc(sizeof(vg_t),GFP_KERNEL)) == NULL) {
1889                 printk(KERN_CRIT
1890                        "%s -- VG_CREATE: kmalloc error VG at line %d\n",
1891                        lvm_name, __LINE__);
1892                 return -ENOMEM;
1893         }
1894         /* get the volume group structure */
1895         if (copy_from_user(vg_ptr, arg, sizeof(vg_t)) != 0) {
1896                 kfree(vg_ptr);
1897                 return -EFAULT;
1898         }
1899 
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;
1904 
1905         if (vg_ptr->pv_max > ABS_MAX_PV) {
1906                 printk(KERN_WARNING
1907                        "%s -- Can't activate VG: ABS_MAX_PV too small\n",
1908                        lvm_name);
1909                 kfree(vg_ptr);
1910                 vg[VG_CHR(minor)] = NULL;
1911                 return -EPERM;
1912         }
1913         if (vg_ptr->lv_max > ABS_MAX_LV) {
1914                 printk(KERN_WARNING
1915                 "%s -- Can't activate VG: ABS_MAX_LV too small for %u\n",
1916                        lvm_name, vg_ptr->lv_max);
1917                 kfree(vg_ptr);
1918                 vg_ptr = NULL;
1919                 return -EPERM;
1920         }
1921 
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);
1928                         if ( ret != 0) {
1929                                 lvm_do_vg_remove(minor);
1930                                 return ret;
1931                         }
1932                 }
1933         }
1934 
1935         size = vg_ptr->lv_max * sizeof(lv_t *);
1936         if ((snap_lv_ptr = vmalloc ( size)) == NULL) {
1937                 printk(KERN_CRIT
1938                        "%s -- VG_CREATE: vmalloc error snapshot LVs at line %d\n",
1939                        lvm_name, __LINE__);
1940                 lvm_do_vg_remove(minor);
1941                 return -EFAULT;
1942         }
1943         memset(snap_lv_ptr, 0, size);
1944 
1945         /* get the logical volume structures */
1946         vg_ptr->lv_cur = 0;
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);
1952                                 return -EFAULT;
1953                         }
1954                         if ( lv.lv_access & LV_SNAPSHOT) {
1955                                 snap_lv_ptr[ls] = lvp;
1956                                 vg_ptr->lv[l] = NULL;
1957                                 ls++;
1958                                 continue;
1959                         }
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);
1964                                 return -EFAULT;
1965                         }
1966                 }
1967         }
1968 
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);
1975                         return -EFAULT;
1976                 }
1977                 if (lvm_do_lv_create(minor, lv.lv_name, &lv) != 0) {
1978                         lvm_do_vg_remove(minor);
1979                         return -EFAULT;
1980                 }
1981         }
1982 
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);
1990 #endif
1991 
1992 #if defined CONFIG_LVM_PROC_FS && defined CONFIG_PROC_FS
1993         lvm_do_create_proc_entry_of_vg ( vg_ptr);
1994 #endif
1995 
1996         vfree(snap_lv_ptr);
1997 
1998         vg_count++;
1999 
2000 
2001         MOD_INC_USE_COUNT;
2002 
2003         /* let's go active */
2004         vg_ptr->vg_status |= VG_ACTIVE;
2005 
2006         return 0;
2007 } /* lvm_do_vg_create() */
2008 
2009 
2010 /*
2011  * character device support function VGDA extend
2012  */
2013 static int lvm_do_vg_extend(vg_t *vg_ptr, void *arg)
2014 {
2015         int ret = 0;
2016         uint p;
2017         pv_t *pv_ptr;
2018 
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;
2026         
2027                                 /* We don't need the PE list
2028                                    in kernel space like LVs pe_t list */
2029                                 pv_ptr->pe = NULL;
2030                                 vg_ptr->pv_cur++;
2031                                 vg_ptr->pv_act++;
2032                                 vg_ptr->pe_total +=
2033                                     pv_ptr->pe_total;
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);
2037 #endif
2038                                 return 0;
2039                         }
2040                 }
2041         }
2042 return -EPERM;
2043 } /* lvm_do_vg_extend() */
2044 
2045 
2046 /*
2047  * character device support function VGDA reduce
2048  */
2049 static int lvm_do_vg_reduce(vg_t *vg_ptr, void *arg) {
2050         uint p;
2051         pv_t *pv_ptr;
2052 
2053         if (vg_ptr == NULL) return -ENXIO;
2054         if (copy_from_user(pv_name, arg, sizeof(pv_name)) != 0)
2055                 return -EFAULT;
2056 
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,
2061                                pv_name) == 0) {
2062                         if (pv_ptr->lv_cur > 0) return -EPERM;
2063                         vg_ptr->pe_total -=
2064                             pv_ptr->pe_total;
2065                         vg_ptr->pv_cur--;
2066                         vg_ptr->pv_act--;
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;
2072                         return 0;
2073                 }
2074         }
2075         return -ENXIO;
2076 } /* lvm_do_vg_reduce */
2077 
2078 
2079 /*
2080  * character device support function VG rename
2081  */
2082 static int lvm_do_vg_rename(vg_t *vg_ptr, void *arg)
2083 {
2084         int l = 0, p = 0, len = 0;
2085         char vg_name[NAME_LEN] = { 0,};
2086         char lv_name[NAME_LEN] = { 0,};
2087         char *ptr = NULL;
2088         lv_t *lv_ptr = NULL;
2089         pv_t *pv_ptr = NULL;
2090 
2091         if (copy_from_user(vg_name, arg, sizeof(vg_name)) != 0)
2092                 return -EFAULT;
2093 
2094 #if defined CONFIG_LVM_PROC_FS && defined CONFIG_PROC_FS
2095         lvm_do_remove_proc_entry_of_vg ( vg_ptr);
2096 #endif
2097 
2098         strncpy ( vg_ptr->vg_name, vg_name, sizeof ( vg_name)-1);
2099         for ( l = 0; l < vg_ptr->lv_max; l++)
2100         {
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);
2111         }
2112         for ( p = 0; p < vg_ptr->pv_max; p++)
2113         {
2114                 if ( (pv_ptr = vg_ptr->pv[p]) == NULL) continue;
2115                 strncpy(pv_ptr->vg_name, vg_name, NAME_LEN);
2116         }
2117 
2118 #if defined CONFIG_LVM_PROC_FS && defined CONFIG_PROC_FS
2119         lvm_do_create_proc_entry_of_vg ( vg_ptr);
2120 #endif
2121 
2122         return 0;
2123 } /* lvm_do_vg_rename */
2124 
2125 
2126 /*
2127  * character device support function VGDA remove
2128  */
2129 static int lvm_do_vg_remove(int minor)
2130 {
2131         int i;
2132         vg_t *vg_ptr = vg[VG_CHR(minor)];
2133         pv_t *pv_ptr;
2134 
2135         if (vg_ptr == NULL) return -ENXIO;
2136 
2137 #ifdef LVM_TOTAL_RESET
2138         if (vg_ptr->lv_open > 0 && lvm_reset_spindown == 0)
2139 #else
2140         if (vg_ptr->lv_open > 0)
2141 #endif
2142                 return -EPERM;
2143 
2144         /* let's go inactive */
2145         vg_ptr->vg_status &= ~VG_ACTIVE;
2146 
2147         /* free LVs */
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);
2155                 }
2156         }
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);
2163                 }
2164         }
2165 
2166         /* free PVs */
2167         for (i = 0; i < vg_ptr->pv_max; i++) {
2168                 if ((pv_ptr = vg_ptr->pv[i]) != NULL) {
2169 #ifdef DEBUG_KFREE
2170                         printk(KERN_DEBUG
2171                                "%s -- kfree %d\n", lvm_name, __LINE__);
2172 #endif
2173                         lvm_do_pv_remove(vg_ptr, i);
2174                 }
2175         }
2176 
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]);
2180 #endif
2181 
2182 #if defined CONFIG_LVM_PROC_FS && defined CONFIG_PROC_FS
2183         lvm_do_remove_proc_entry_of_vg ( vg_ptr);
2184 #endif
2185 
2186 #ifdef DEBUG_KFREE
2187         printk(KERN_DEBUG "%s -- kfree %d\n", lvm_name, __LINE__);
2188 #endif
2189 
2190         kfree(vg_ptr);
2191         vg[VG_CHR(minor)] = NULL;
2192 
2193         vg_count--;
2194 
2195         MOD_DEC_USE_COUNT;
2196 
2197         return 0;
2198 } /* lvm_do_vg_remove() */
2199 
2200 
2201 /*
2202  * character device support function physical volume create
2203  */
2204 static int lvm_do_pv_create(pv_t *pvp, vg_t *vg_ptr, ulong p) {
2205         pv_t *pv_ptr = NULL;
2206 
2207         pv_ptr = vg_ptr->pv[p] = kmalloc(sizeof(pv_t),GFP_KERNEL);
2208         if (pv_ptr == NULL) {
2209                 printk(KERN_CRIT
2210                        "%s -- VG_CREATE: kmalloc error PV at line %d\n",
2211                        lvm_name, __LINE__);
2212                 return -ENOMEM;
2213         }
2214         if (copy_from_user(pv_ptr, pvp, sizeof(pv_t)) != 0) {
2215                 return -EFAULT;
2216         }
2217         /* We don't need the PE list
2218            in kernel space as with LVs pe_t list (see below) */
2219         pv_ptr->pe = NULL;
2220         pv_ptr->pe_allocated = 0;
2221         pv_ptr->pv_status = PV_ACTIVE;
2222         vg_ptr->pv_act++;
2223         vg_ptr->pv_cur++;
2224 
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);
2228 #endif
2229 
2230         return 0;
2231 } /* lvm_do_pv_create() */
2232 
2233 
2234 /*
2235  * character device support function physical volume create
2236  */
2237 static int lvm_do_pv_remove(vg_t *vg_ptr, ulong p) {
2238         pv_t *pv_ptr = vg_ptr->pv[p];
2239 
2240 #if defined CONFIG_LVM_PROC_FS && defined CONFIG_PROC_FS
2241         lvm_do_remove_proc_entry_of_pv ( vg_ptr, pv_ptr);
2242 #endif
2243         vg_ptr->pe_total -=
2244             pv_ptr->pe_total;
2245         vg_ptr->pv_cur--;
2246         vg_ptr->pv_act--;
2247 #ifdef LVM_GET_INODE
2248         lvm_clear_inode(pv_ptr->inode);
2249 #endif
2250         kfree(pv_ptr);
2251         vg_ptr->pv[p] = NULL;
2252 
2253         return 0;
2254 }
2255 
2256 
2257 /*
2258  * character device support function logical volume create
2259  */
2260 static int lvm_do_lv_create(int minor, char *lv_name, lv_t *lv)
2261 {
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;
2267 
2268         if ((pep = lv->lv_current_pe) == NULL) return -EINVAL;
2269         if (lv->lv_chunk_size > LVM_SNAPSHOT_MAX_CHUNK)
2270                 return -EINVAL;
2271 
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)
2275                         return -EEXIST;
2276         }
2277 
2278         /* in case of lv_remove(), lv_create() pair */
2279         l_new = -1;
2280         if (vg_ptr->lv[lv->lv_number] == NULL)
2281                 l_new = lv->lv_number;
2282         else {
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;
2286                 }
2287         }
2288         if (l_new == -1) return -EPERM;
2289         else             l = l_new;
2290 
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__);
2294                 return -ENOMEM;
2295         }
2296         /* copy preloaded LV */
2297         memcpy((char *) lv_ptr, (char *) lv, sizeof(lv_t));
2298 
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;
2313 
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) {
2319                         printk(KERN_CRIT
2320                                "%s -- LV_CREATE: vmalloc error LV_CURRENT_PE of %d Byte "
2321                                "at line %d\n",
2322                                lvm_name, size, __LINE__);
2323 #ifdef DEBUG_KFREE
2324                         printk(KERN_DEBUG "%s -- kfree %d\n", lvm_name, __LINE__);
2325 #endif
2326                         kfree(lv_ptr);
2327                         vg[VG_CHR(minor)]->lv[l] = NULL;
2328                         return -ENOMEM;
2329                 }
2330                 if (copy_from_user(lv_ptr->lv_current_pe, pep, size)) {
2331                         vfree(lv_ptr->lv_current_pe);
2332                         kfree(lv_ptr);
2333                         vg_ptr->lv[l] = NULL;
2334                         return -EFAULT;
2335                 }
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++;
2343                         }
2344                 }
2345         } else {
2346                 /* Get snapshot exception data and block list */
2347                 if (lvbe != NULL) {
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) {
2353                                         printk(KERN_CRIT
2354                                                "%s -- lvm_do_lv_create: vmalloc error LV_BLOCK_EXCEPTION "
2355                                                "of %d byte at line %d\n",
2356                                                lvm_name, size, __LINE__);
2357 #ifdef DEBUG_KFREE
2358                                         printk(KERN_DEBUG "%s -- kfree %d\n", lvm_name, __LINE__);
2359 #endif
2360                                         kfree(lv_ptr);
2361                                         vg_ptr->lv[l] = NULL;
2362                                         return -ENOMEM;
2363                                 }
2364                                 if (copy_from_user(lv_ptr->lv_block_exception, lvbe, size)) {
2365                                         vfree(lv_ptr->lv_block_exception);
2366                                         kfree(lv_ptr);
2367                                         vg[VG_CHR(minor)]->lv[l] = NULL;
2368                                         return -EFAULT;
2369                                 }
2370                                 /* point to the original logical volume */
2371                                 lv_ptr = lv_ptr->lv_snapshot_org;
2372 
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)
2394                                 {
2395                                         vfree(lv_ptr->lv_block_exception);
2396                                         kfree(lv_ptr);
2397                                         vg[VG_CHR(minor)]->lv[l] = NULL;
2398                                         return ret;
2399                                 }
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);
2406                         } else {
2407                                 vfree(lv_ptr->lv_block_exception);
2408                                 kfree(lv_ptr);
2409                                 vg_ptr->lv[l] = NULL;
2410                                 return -EFAULT;
2411                         }
2412                 } else {
2413                         kfree(vg_ptr->lv[l]);
2414                         vg_ptr->lv[l] = NULL;
2415                         return -EINVAL;
2416                 }
2417         } /* if ( vg[VG_CHR(minor)]->lv[l]->lv_access & LV_SNAPSHOT) */
2418 
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);
2426         vg_ptr->lv_cur++;
2427         lv_ptr->lv_status = lv_status_save;
2428 
2429 #ifdef  CONFIG_DEVFS_FS
2430         {
2431         char *lv_tmp, *lv_buf = NULL;
2432 
2433         strtok(lv->lv_name, "/");       /* /dev */
2434         while((lv_tmp = strtok(NULL, "/")) != NULL)
2435                 lv_buf = lv_tmp;
2436 
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);
2442         }
2443 #endif
2444 
2445 #if defined CONFIG_LVM_PROC_FS && defined CONFIG_PROC_FS
2446         lvm_do_create_proc_entry_of_lv ( vg_ptr, lv_ptr);
2447 #endif
2448 
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);
2456 #endif
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;
2461         }
2462 
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);
2467         else
2468                 set_device_ro(lv_ptr->lv_dev, 1);
2469 
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);
2474         }
2475 #endif
2476 
2477         lv_ptr->vg = vg_ptr;
2478 
2479         return 0;
2480 } /* lvm_do_lv_create() */
2481 
2482 
2483 /*
2484  * character device support function logical volume remove
2485  */
2486 static int lvm_do_lv_remove(int minor, char *lv_name, int l)
2487 {
2488         uint le, p;
2489         vg_t *vg_ptr = vg[VG_CHR(minor)];
2490         lv_t *lv_ptr;
2491 
2492         if (l == -1) {
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) {
2496                                 break;
2497                         }
2498                 }
2499         }
2500         if (l == vg_ptr->lv_max) return -ENXIO;
2501 
2502         lv_ptr = vg_ptr->lv[l];
2503 #ifdef LVM_TOTAL_RESET
2504         if (lv_ptr->lv_open > 0 && lvm_reset_spindown == 0)
2505 #else
2506         if (lv_ptr->lv_open > 0)
2507 #endif
2508                 return -EBUSY;
2509 
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)
2514                 return -EPERM;
2515 
2516         lv_ptr->lv_status |= LV_SPINDOWN;
2517 
2518         /* sync the buffers */
2519         fsync_dev(lv_ptr->lv_dev);
2520 
2521         lv_ptr->lv_status &= ~LV_ACTIVE;
2522 
2523         /* invalidate the buffers */
2524         invalidate_buffers(lv_ptr->lv_dev);
2525 
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;
2530 
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;
2534 
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--;
2546                         }
2547                 }
2548                 vfree(lv_ptr->lv_current_pe);
2549         /* LV_SNAPSHOT */
2550         } else {
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;
2556                 }
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);
2561         }
2562 
2563 #ifdef  CONFIG_DEVFS_FS
2564         devfs_unregister(lv_devfs_handle[lv_ptr->lv_number]);
2565 #endif
2566 
2567 #if defined CONFIG_LVM_PROC_FS && defined CONFIG_PROC_FS
2568         lvm_do_remove_proc_entry_of_lv ( vg_ptr, lv_ptr);
2569 #endif
2570 
2571 #ifdef DEBUG_KFREE
2572         printk(KERN_DEBUG "%s -- kfree %d\n", lvm_name, __LINE__);
2573 #endif
2574         kfree(lv_ptr);
2575         vg_ptr->lv[l] = NULL;
2576         vg_ptr->lv_cur--;
2577         return 0;
2578 } /* lvm_do_lv_remove() */
2579 
2580 
2581 /*
2582  * character device support function logical volume extend / reduce
2583  */
2584 static int lvm_do_lv_extend_reduce(int minor, char *lv_name, lv_t *lv)
2585 {
2586         ulong end, l, le, p, size, old_allocated_le;
2587         vg_t *vg_ptr = vg[VG_CHR(minor)];
2588         lv_t *lv_ptr;
2589         pe_t *pe;
2590 
2591         if ((pep = lv->lv_current_pe) == NULL) return -EINVAL;
2592 
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)
2596                         break;
2597         }
2598         if (l == vg_ptr->lv_max) return -ENXIO;
2599         lv_ptr = vg_ptr->lv[l];
2600 
2601         /* check for active snapshot */
2602         if (lv->lv_access & LV_SNAPSHOT)
2603         {
2604                 ulong e;
2605                 lv_block_exception_t *lvbe, *lvbe_old;
2606                 struct list_head * lvs_hash_table_old;
2607 
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)
2611                 {
2612                         printk(KERN_CRIT
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__);
2616                         return -ENOMEM;
2617                 }
2618                 if (lv->lv_remap_end > lv_ptr->lv_remap_end)
2619                 {
2620                         if (copy_from_user(lvbe, lv->lv_block_exception, size))
2621                         {
2622                                 vfree(lvbe);
2623                                 return -EFAULT;
2624                         }
2625                 }
2626 
2627                 lvbe_old = lv_ptr->lv_block_exception;
2628                 lvs_hash_table_old = lv_ptr->lv_snapshot_hash_table;
2629 
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)
2634                 {
2635                         up(&lv_ptr->lv_snapshot_org->lv_snapshot_sem);
2636                         vfree(lvbe);
2637                         return -EPERM;
2638                 }
2639                 memcpy(lvbe,
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));
2642 
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)
2646                 {
2647                         lvm_drop_snapshot(lv_ptr, "hash_alloc");
2648                         up(&lv_ptr->lv_snapshot_org->lv_snapshot_sem);
2649                         vfree(lvbe_old);
2650                         vfree(lvs_hash_table_old);
2651                         return 1;
2652                 }
2653 
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);
2656 
2657                 up(&lv_ptr->lv_snapshot_org->lv_snapshot_sem);
2658 
2659                 vfree(lvbe_old);
2660                 vfree(lvs_hash_table_old);
2661 
2662                 return 0;
2663         }
2664 
2665 
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) {
2668                 printk(KERN_CRIT
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__);
2672                 return -ENOMEM;
2673         }
2674         /* get the PE structures from user space */
2675         if (copy_from_user(pe, pep, size)) {
2676                 vfree(pe);
2677                 return -EFAULT;
2678         }
2679 
2680 #ifdef DEBUG
2681         printk(KERN_DEBUG
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),
2686                vg_ptr->vg_name);
2687 #endif
2688 
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--;
2696                                 break;
2697                         }
2698                 }
2699         }
2700 
2701 
2702         /* save pointer to "old" lv/pe pointer array */
2703         pep1 = lv_ptr->lv_current_pe;
2704         end = lv_ptr->lv_current_le;
2705 
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;
2711 
2712         lv->lv_current_pe = pe;
2713 
2714         /* save # of old allocated logical extents */
2715         old_allocated_le = lv_ptr->lv_allocated_le;
2716 
2717         /* in case of shrinking -> let's flush */
2718         if ( end > lv->lv_current_le) fsync_dev(lv_ptr->lv_dev);
2719 
2720         /* copy preloaded LV */
2721         memcpy((char *) lv_ptr, (char *) lv, sizeof(lv_t));
2722 
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 */
2727 
2728         LVM_CORRECT_READ_AHEAD(lv_ptr->lv_read_ahead);
2729 
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;
2738                 }
2739                 /* striped logical volume */
2740         } else {
2741                 uint i, j, source, dest, end, old_stripe_size, new_stripe_size;
2742 
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;
2754                         }
2755                         source += old_stripe_size;
2756                         dest += new_stripe_size;
2757                 }
2758         }
2759 
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++;
2767                                 break;
2768                         }
2769                 }
2770         }
2771 
2772         vfree ( pep1);
2773         pep1 = NULL;
2774 
2775         if (lv->lv_access & LV_SNAPSHOT_ORG)
2776         {
2777                 /* Correct the snapshot size information */
2778                 while ((lv_ptr = lv_ptr->lv_snapshot_next) != NULL)
2779                 {
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;
2786                 }
2787         }
2788 
2789         return 0;
2790 } /* lvm_do_lv_extend_reduce() */
2791 
2792 
2793 /*
2794  * character device support function logical volume status by name
2795  */
2796 static int lvm_do_lv_status_byname(vg_t *vg_ptr, void *arg)
2797 {
2798         uint l;
2799         ulong size;
2800         lv_t lv;
2801         lv_t *lv_ptr;
2802         lv_status_byname_req_t lv_status_byname_req;
2803 
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)
2807                 return -EFAULT;
2808 
2809         if (lv_status_byname_req.lv == NULL) return -EINVAL;
2810         if (copy_from_user(&lv, lv_status_byname_req.lv,
2811                            sizeof(lv_t)) != 0)
2812                 return -EFAULT;
2813 
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,
2820                                          lv_ptr,
2821                                          sizeof(lv_t)) != 0)
2822                                 return -EFAULT;
2823 
2824                         if (lv.lv_current_pe != NULL) {
2825                                 size = lv_ptr->lv_allocated_le *
2826                                        sizeof(pe_t);
2827                                 if (copy_to_user(lv.lv_current_pe,
2828                                                  lv_ptr->lv_current_pe,
2829                                                  size) != 0)
2830                                         return -EFAULT;
2831                         }
2832                         return 0;
2833                 }
2834         }
2835         return -ENXIO;
2836 } /* lvm_do_lv_status_byname() */
2837 
2838 
2839 /*
2840  * character device support function logical volume status by index
2841  */
2842 static int lvm_do_lv_status_byindex(vg_t *vg_ptr,void *arg)
2843 {
2844         ulong size;
2845         lv_t lv;
2846         lv_t *lv_ptr;
2847         lv_status_byindex_req_t lv_status_byindex_req;
2848 
2849         if (vg_ptr == NULL) return -ENXIO;
2850         if (copy_from_user(&lv_status_byindex_req, arg,
2851                            sizeof(lv_status_byindex_req)) != 0)
2852                 return -EFAULT;
2853 
2854         if ((lvp = lv_status_byindex_req.lv) == NULL)
2855                 return -EINVAL;
2856         if ( ( lv_ptr = vg_ptr->lv[lv_status_byindex_req.lv_index]) == NULL)
2857                 return -ENXIO;
2858 
2859         if (copy_from_user(&lv, lvp, sizeof(lv_t)) != 0)
2860                 return -EFAULT;
2861 
2862         if (copy_to_user(lvp, lv_ptr, sizeof(lv_t)) != 0)
2863                 return -EFAULT;
2864 
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,
2869                                  size) != 0)
2870                         return -EFAULT;
2871         }
2872         return 0;
2873 } /* lvm_do_lv_status_byindex() */
2874 
2875 
2876 /*
2877  * character device support function logical volume status by device number
2878  */
2879 static int lvm_do_lv_status_bydev(vg_t * vg_ptr, void * arg) {
2880         int l;
2881         lv_status_bydev_req_t lv_status_bydev_req;
2882 
2883         if (vg_ptr == NULL) return -ENXIO;
2884         if (copy_from_user(&lv_status_bydev_req, arg,
2885                            sizeof(lv_status_bydev_req)) != 0)
2886                 return -EFAULT;
2887 
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;
2891         }
2892 
2893         if ( l == vg_ptr->lv_max) return -ENXIO;
2894 
2895         if (copy_to_user(lv_status_bydev_req.lv,
2896                          vg_ptr->lv[l], sizeof(lv_t)) != 0)
2897                 return -EFAULT;
2898 
2899         return 0;
2900 } /* lvm_do_lv_status_bydev() */
2901 
2902 
2903 /*
2904  * character device support function rename a logical volume
2905  */
2906 static int lvm_do_lv_rename(vg_t *vg_ptr, lv_req_t *lv_req, lv_t *lv)
2907 {
2908         int l = 0;
2909         int ret = 0;
2910         lv_t *lv_ptr = NULL;
2911 
2912         for (l = 0; l < vg_ptr->lv_max; l++)
2913         {
2914                 if ( (lv_ptr = vg_ptr->lv[l]) == NULL) continue;
2915                 if (lv_ptr->lv_dev == lv->lv_dev)
2916                 {
2917 #if defined CONFIG_LVM_PROC_FS && defined CONFIG_PROC_FS
2918                         lvm_do_remove_proc_entry_of_lv ( vg_ptr, lv_ptr);
2919 #endif
2920                         strncpy(lv_ptr->lv_name,
2921                                 lv_req->lv_name,
2922                                 NAME_LEN);
2923 #if defined CONFIG_LVM_PROC_FS && defined CONFIG_PROC_FS
2924                         lvm_do_create_proc_entry_of_lv ( vg_ptr, lv_ptr);
2925 #endif
2926                         break;
2927                 }
2928         }
2929         if (l == vg_ptr->lv_max) ret = -ENODEV;
2930 
2931         return ret;
2932 } /* lvm_do_lv_rename */
2933 
2934 
2935 /*
2936  * character device support function physical volume change
2937  */
2938 static int lvm_do_pv_change(vg_t *vg_ptr, void *arg)
2939 {
2940         uint p;
2941         pv_t *pv_ptr;
2942 #ifdef LVM_GET_INODE
2943         struct inode *inode_sav;
2944 #endif
2945 
2946         if (vg_ptr == NULL) return -ENXIO;
2947         if (copy_from_user(&pv_change_req, arg,
2948                            sizeof(pv_change_req)) != 0)
2949                 return -EFAULT;
2950 
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;
2958 #endif
2959                         if (copy_from_user(pv_ptr,
2960                                            pv_change_req.pv,
2961                                            sizeof(pv_t)) != 0)
2962                                 return -EFAULT;
2963 
2964                         /* We don't need the PE list
2965                            in kernel space as with LVs pe_t list */
2966                         pv_ptr->pe = NULL;
2967 #ifdef LVM_GET_INODE
2968                         pv_ptr->inode = inode_sav;
2969 #endif
2970                         return 0;
2971                 }
2972         }
2973         return -ENXIO;
2974 } /* lvm_do_pv_change() */
2975 
2976 /*
2977  * character device support function get physical volume status
2978  */
2979 static int lvm_do_pv_status(vg_t *vg_ptr, void *arg)
2980 {
2981         uint p;
2982         pv_t *pv_ptr;
2983 
2984         if (vg_ptr == NULL) return -ENXIO;
2985         if (copy_from_user(&pv_status_req, arg,
2986                            sizeof(pv_status_req)) != 0)
2987                 return -EFAULT;
2988 
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,
2995                                          pv_ptr,
2996                                          sizeof(pv_t)) != 0)
2997                                 return -EFAULT;
2998                         return 0;
2999                 }
3000         }
3001         return -ENXIO;
3002 } /* lvm_do_pv_status() */
3003 
3004 
3005 
3006 /*
3007  * create a /proc entry for a logical volume
3008  */
3009 inline void lvm_do_create_proc_entry_of_lv ( vg_t *vg_ptr, lv_t *lv_ptr) {
3010         char *basename;
3011 
3012         if ( vg_ptr->lv_subdir_pde != NULL) {
3013                 basename = strrchr(lv_ptr->lv_name, '/');
3014                 if (basename == NULL) basename = lv_ptr->lv_name;
3015                 else                  basename++;
3016                 pde = create_proc_entry(basename, S_IFREG,
3017                                         vg_ptr->lv_subdir_pde);
3018                 if ( pde != NULL) {
3019                         pde->read_proc = lvm_proc_read_lv_info;
3020                         pde->data = lv_ptr;
3021                 }
3022         }
3023 }
3024 
3025 
3026 /*
3027  * remove a /proc entry for a logical volume
3028  */
3029 inline void lvm_do_remove_proc_entry_of_lv ( vg_t *vg_ptr, lv_t *lv_ptr) {
3030         char *basename;
3031 
3032         if ( vg_ptr->lv_subdir_pde != NULL) {
3033                 basename = strrchr(lv_ptr->lv_name, '/');
3034                 if (basename == NULL) basename = lv_ptr->lv_name;
3035                 else                  basename++;
3036                 remove_proc_entry(basename, vg_ptr->lv_subdir_pde);
3037         }
3038 }
3039 
3040 
3041 /*
3042  * create a /proc entry for a physical volume
3043  */
3044 inline void lvm_do_create_proc_entry_of_pv ( vg_t *vg_ptr, pv_t *pv_ptr) {
3045         char *basename;
3046 
3047         basename = strrchr(pv_ptr->pv_name, '/');
3048         if (basename == NULL) basename = pv_ptr->pv_name;
3049         else                  basename++;
3050         pde = create_proc_entry(basename, S_IFREG, vg_ptr->pv_subdir_pde);
3051         if ( pde != NULL) {
3052                 pde->read_proc = lvm_proc_read_pv_info;
3053                 pde->data = pv_ptr;
3054         }
3055 }
3056 
3057 
3058 /*
3059  * remove a /proc entry for a physical volume
3060  */
3061 inline void lvm_do_remove_proc_entry_of_pv ( vg_t *vg_ptr, pv_t *pv_ptr) {
3062         char *basename;
3063 
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;
3068                 else                  basename++;
3069                 remove_proc_entry(basename, vg_ptr->pv_subdir_pde);
3070         }
3071 }
3072 
3073 
3074 /*
3075  * create a /proc entry for a volume group
3076  */
3077 #if defined CONFIG_LVM_PROC_FS && defined CONFIG_PROC_FS
3078 void lvm_do_create_proc_entry_of_vg ( vg_t *vg_ptr) {
3079         int l, p;
3080         pv_t *pv_ptr;
3081         lv_t *lv_ptr;
3082 
3083         pde = create_proc_entry(vg_ptr->vg_name, S_IFDIR,
3084                                 lvm_proc_vg_subdir);
3085         if ( pde != NULL) {
3086                 vg_ptr->vg_dir_pde = pde;
3087                 pde = create_proc_entry("group", S_IFREG,
3088                                         vg_ptr->vg_dir_pde);
3089                 if ( pde != NULL) {
3090                         pde->read_proc = lvm_proc_read_vg_info;
3091                         pde->data = vg_ptr;
3092                 }
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);
3099         }
3100 
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);
3105                 }
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);
3109                 }
3110         }
3111 }
3112 
3113 /*
3114  * remove a /proc entry for a volume group
3115  */
3116 void lvm_do_remove_proc_entry_of_vg ( vg_t *vg_ptr) {
3117         int l, p;
3118         lv_t *lv_ptr;
3119         pv_t *pv_ptr;
3120 
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]);
3124         }
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]);
3128         }
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);
3134         }
3135 }
3136 #endif
3137 
3138 
3139 /*
3140  * support function initialize gendisk variables
3141  */
3142 #ifdef __initfunc
3143 __initfunc(void lvm_geninit(struct gendisk *lvm_gdisk))
3144 #else
3145 void __init
3146  lvm_geninit(struct gendisk *lvm_gdisk)
3147 #endif
3148 {
3149         int i = 0;
3150 
3151 #ifdef DEBUG_GENDISK
3152         printk(KERN_DEBUG "%s -- lvm_gendisk\n", lvm_name);
3153 #endif
3154 
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;
3159         }
3160 
3161         blk_size[MAJOR_NR] = lvm_size;
3162         blksize_size[MAJOR_NR] = lvm_blocksizes;
3163         hardsect_size[MAJOR_NR] = lvm_blocksizes;
3164 
3165         return;
3166 } /* lvm_gen_init() */
3167 
3168 
3169 #ifdef LVM_GET_INODE
3170 /*
3171  * support function to get an empty inode
3172  *
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
3176  *
3177  * Is this the real thing?
3178  *
3179  */
3180 struct inode *lvm_get_inode(int dev)
3181 {
3182         struct inode *inode_this = NULL;
3183 
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);
3188         return inode_this;
3189 }
3190 
3191 
3192 /*
3193  * support function to clear an inode
3194  *
3195  */
3196 void lvm_clear_inode(struct inode *inode)
3197 {
3198 #ifdef I_FREEING
3199         inode->i_state |= I_FREEING;
3200 #endif
3201         clear_inode(inode);
3202         return;
3203 }
3204 #endif /* #ifdef LVM_GET_INODE */
3205 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.