- David Miller: sparc and net updates. Fix merge_segments.
[davej-history.git] / drivers / md / lvm.c
blobf9433232eb9f92cf3dd498fb41693927a410748a
1 /*
2 * kernel/lvm.c
4 * Copyright (C) 1997 - 2000 Heinz Mauelshagen, Germany
6 * February-November 1997
7 * April-May,July-August,November 1998
8 * January-March,May,July,September,October 1999
9 * January,February 2000
12 * LVM driver is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2, or (at your option)
15 * any later version.
17 * LVM driver is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with GNU CC; see the file COPYING. If not, write to
24 * the Free Software Foundation, 59 Temple Place - Suite 330,
25 * Boston, MA 02111-1307, USA.
30 * Changelog
32 * 09/11/1997 - added chr ioctls VG_STATUS_GET_COUNT
33 * and VG_STATUS_GET_NAMELIST
34 * 18/01/1998 - change lvm_chr_open/close lock handling
35 * 30/04/1998 - changed LV_STATUS ioctl to LV_STATUS_BYNAME and
36 * - added LV_STATUS_BYINDEX ioctl
37 * - used lvm_status_byname_req_t and
38 * lvm_status_byindex_req_t vars
39 * 04/05/1998 - added multiple device support
40 * 08/05/1998 - added support to set/clear extendable flag in volume group
41 * 09/05/1998 - changed output of lvm_proc_get_info() because of
42 * support for free (eg. longer) logical volume names
43 * 12/05/1998 - added spin_locks (thanks to Pascal van Dam
44 * <pascal@ramoth.xs4all.nl>)
45 * 25/05/1998 - fixed handling of locked PEs in lvm_map() and lvm_chr_ioctl()
46 * 26/05/1998 - reactivated verify_area by access_ok
47 * 07/06/1998 - used vmalloc/vfree instead of kmalloc/kfree to go
48 * beyond 128/256 KB max allocation limit per call
49 * - #ifdef blocked spin_lock calls to avoid compile errors
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 Arcangeli's snapshot code
126 * 07/12/2000 - make sure lvm_make_request_fn returns correct value - 0 or 1 - NeilBrown
131 static char *lvm_version = "LVM version 0.8final by Heinz Mauelshagen (15/02/2000)\n";
132 static char *lvm_short_version = "version 0.8final (15/02/2000)";
134 #define MAJOR_NR LVM_BLK_MAJOR
135 #define DEVICE_OFF(device)
137 #include <linux/config.h>
138 #include <linux/version.h>
140 #ifdef MODVERSIONS
141 #undef MODULE
142 #define MODULE
143 #include <linux/modversions.h>
144 #endif
146 #include <linux/module.h>
148 #include <linux/kernel.h>
149 #include <linux/vmalloc.h>
150 #include <linux/slab.h>
151 #include <linux/init.h>
153 #include <linux/hdreg.h>
154 #include <linux/stat.h>
155 #include <linux/fs.h>
156 #include <linux/proc_fs.h>
157 #include <linux/blkdev.h>
158 #include <linux/genhd.h>
159 #include <linux/locks.h>
160 #include <linux/smp_lock.h>
161 #include <asm/ioctl.h>
162 #include <asm/segment.h>
163 #include <asm/uaccess.h>
165 #ifdef CONFIG_KERNELD
166 #include <linux/kerneld.h>
167 #endif
169 #define LOCAL_END_REQUEST
171 #include <linux/blk.h>
172 #include <linux/blkpg.h>
174 #include <linux/errno.h>
175 #include <linux/lvm.h>
177 #define LVM_CORRECT_READ_AHEAD(a) \
178 (((a) < LVM_MIN_READ_AHEAD || (a) > LVM_MAX_READ_AHEAD) \
179 ? LVM_MAX_READ_AHEAD : (a))
181 #ifndef WRITEA
182 # define WRITEA WRITE
183 #endif
186 * External function prototypes
188 #ifdef MODULE
189 int init_module(void);
190 void cleanup_module(void);
191 #else
192 extern int lvm_init(void);
193 #endif
195 static void lvm_dummy_device_request(request_queue_t *);
196 #define DEVICE_REQUEST lvm_dummy_device_request
198 static int lvm_make_request_fn(request_queue_t *, int, struct buffer_head*);
199 static void lvm_plug_device_noop(request_queue_t *, kdev_t);
201 static int lvm_blk_ioctl(struct inode *, struct file *, uint, ulong);
202 static int lvm_blk_open(struct inode *, struct file *);
204 static int lvm_chr_open(struct inode *, struct file *);
206 static int lvm_chr_close(struct inode *, struct file *);
207 static int lvm_blk_close(struct inode *, struct file *);
209 static int lvm_chr_ioctl(struct inode *, struct file *, uint, ulong);
211 #if defined CONFIG_LVM_PROC_FS && defined CONFIG_PROC_FS
212 static int lvm_proc_get_info(char *, char **, off_t, int);
213 static int (*lvm_proc_get_info_ptr) (char *, char **, off_t, int) =
214 &lvm_proc_get_info;
215 #endif
217 #ifdef LVM_HD_NAME
218 void lvm_hd_name(char *, int);
219 #endif
220 /* End external function prototypes */
224 * Internal function prototypes
226 static void lvm_init_vars(void);
228 /* external snapshot calls */
229 int lvm_snapshot_remap_block(kdev_t *, ulong *, ulong, lv_t *);
230 int lvm_snapshot_COW(kdev_t, ulong, ulong, ulong, lv_t *);
231 int lvm_snapshot_alloc(lv_t *);
232 void lvm_snapshot_release(lv_t *);
234 #ifdef LVM_HD_NAME
235 extern void (*lvm_hd_name_ptr) (char *, int);
236 #endif
237 static int lvm_map(struct buffer_head *, int);
238 static int lvm_do_lock_lvm(void);
239 static int lvm_do_le_remap(vg_t *, void *);
240 static int lvm_do_pe_lock_unlock(vg_t *r, void *);
241 static int lvm_do_vg_create(int, void *);
242 static int lvm_do_vg_extend(vg_t *, void *);
243 static int lvm_do_vg_reduce(vg_t *, void *);
244 static int lvm_do_vg_remove(int);
245 static int lvm_do_lv_create(int, char *, lv_t *);
246 static int lvm_do_lv_remove(int, char *, int);
247 static int lvm_do_lv_extend_reduce(int, char *, lv_t *);
248 static int lvm_do_lv_status_byname(vg_t *r, void *);
249 static int lvm_do_lv_status_byindex(vg_t *, void *arg);
250 static int lvm_do_pv_change(vg_t*, void*);
251 static int lvm_do_pv_status(vg_t *, void *);
252 static void lvm_geninit(struct gendisk *);
253 #ifdef LVM_GET_INODE
254 static struct inode *lvm_get_inode(kdev_t);
255 void lvm_clear_inode(struct inode *);
256 #endif
257 /* END Internal function prototypes */
260 /* volume group descriptor area pointers */
261 static vg_t *vg[ABS_MAX_VG];
262 static pv_t *pvp = NULL;
263 static lv_t *lvp = NULL;
264 static pe_t *pep = NULL;
265 static pe_t *pep1 = NULL;
268 /* map from block minor number to VG and LV numbers */
269 typedef struct {
270 int vg_number;
271 int lv_number;
272 } vg_lv_map_t;
273 static vg_lv_map_t vg_lv_map[ABS_MAX_LV];
276 /* Request structures (lvm_chr_ioctl()) */
277 static pv_change_req_t pv_change_req;
278 static pv_flush_req_t pv_flush_req;
279 static pv_status_req_t pv_status_req;
280 static pe_lock_req_t pe_lock_req;
281 static le_remap_req_t le_remap_req;
282 static lv_req_t lv_req;
284 #ifdef LVM_TOTAL_RESET
285 static int lvm_reset_spindown = 0;
286 #endif
288 static char pv_name[NAME_LEN];
289 /* static char rootvg[NAME_LEN] = { 0, }; */
290 static uint lv_open = 0;
291 const char *const lvm_name = LVM_NAME;
292 static int lock = 0;
293 static int loadtime = 0;
294 static uint vg_count = 0;
295 static long lvm_chr_open_count = 0;
296 static ushort lvm_iop_version = LVM_DRIVER_IOP_VERSION;
297 static DECLARE_WAIT_QUEUE_HEAD(lvm_snapshot_wait);
298 static DECLARE_WAIT_QUEUE_HEAD(lvm_wait);
299 static DECLARE_WAIT_QUEUE_HEAD(lvm_map_wait);
301 static spinlock_t lvm_lock = SPIN_LOCK_UNLOCKED;
303 static devfs_handle_t lvm_devfs_handle;
304 static devfs_handle_t vg_devfs_handle[MAX_VG];
305 static devfs_handle_t ch_devfs_handle[MAX_VG];
306 static devfs_handle_t lv_devfs_handle[MAX_LV];
308 static struct file_operations lvm_chr_fops =
310 owner: THIS_MODULE,
311 open: lvm_chr_open,
312 release: lvm_chr_close,
313 ioctl: lvm_chr_ioctl,
316 static struct block_device_operations lvm_blk_dops =
318 open: lvm_blk_open,
319 release: lvm_blk_close,
320 ioctl: lvm_blk_ioctl
323 /* gendisk structures */
324 static struct hd_struct lvm_hd_struct[MAX_LV];
325 static int lvm_blocksizes[MAX_LV] =
326 {0,};
327 static int lvm_size[MAX_LV] =
328 {0,};
329 static struct gendisk lvm_gendisk =
331 MAJOR_NR, /* major # */
332 LVM_NAME, /* name of major */
333 0, /* number of times minor is shifted
334 to get real minor */
335 1, /* maximum partitions per device */
336 lvm_hd_struct, /* partition table */
337 lvm_size, /* device size in blocks, copied
338 to block_size[] */
339 MAX_LV, /* number or real devices */
340 NULL, /* internal */
341 NULL, /* pointer to next gendisk struct (internal) */
345 #ifdef MODULE
347 * Module initialization...
349 int init_module(void)
350 #else
352 * Driver initialization...
354 #ifdef __initfunc
355 __initfunc(int lvm_init(void))
356 #else
357 int __init lvm_init(void)
358 #endif
359 #endif /* #ifdef MODULE */
361 struct gendisk *gendisk_ptr = NULL;
363 if (register_chrdev(LVM_CHAR_MAJOR, lvm_name, &lvm_chr_fops) < 0) {
364 printk(KERN_ERR "%s -- register_chrdev failed\n", lvm_name);
365 return -EIO;
367 if (register_blkdev(MAJOR_NR, lvm_name, &lvm_blk_dops) < 0) {
368 printk("%s -- register_blkdev failed\n", lvm_name);
369 if (unregister_chrdev(LVM_CHAR_MAJOR, lvm_name) < 0)
370 printk(KERN_ERR "%s -- unregister_chrdev failed\n", lvm_name);
371 return -EIO;
374 lvm_devfs_handle = devfs_register(
375 0 , "lvm", 0, 0, LVM_CHAR_MAJOR,
376 S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP,
377 &lvm_chr_fops, NULL);
379 #if defined CONFIG_LVM_PROC_FS && defined CONFIG_PROC_FS
380 create_proc_info_entry(LVM_NAME, S_IFREG | S_IRUGO,
381 &proc_root, lvm_proc_get_info_ptr);
382 #endif
384 lvm_init_vars();
385 lvm_geninit(&lvm_gendisk);
387 /* insert our gendisk at the corresponding major */
388 if (gendisk_head != NULL) {
389 gendisk_ptr = gendisk_head;
390 while (gendisk_ptr->next != NULL &&
391 gendisk_ptr->major > lvm_gendisk.major) {
392 gendisk_ptr = gendisk_ptr->next;
394 lvm_gendisk.next = gendisk_ptr->next;
395 gendisk_ptr->next = &lvm_gendisk;
396 } else {
397 gendisk_head = &lvm_gendisk;
398 lvm_gendisk.next = NULL;
401 #ifdef LVM_HD_NAME
402 /* reference from drivers/block/genhd.c */
403 lvm_hd_name_ptr = lvm_hd_name;
404 #endif
406 blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), DEVICE_REQUEST);
407 blk_queue_make_request(BLK_DEFAULT_QUEUE(MAJOR_NR), lvm_make_request_fn);
408 blk_queue_pluggable(BLK_DEFAULT_QUEUE(MAJOR_NR), lvm_plug_device_noop);
409 /* optional read root VGDA */
411 if ( *rootvg != 0) vg_read_with_pv_and_lv ( rootvg, &vg);
414 printk(KERN_INFO
415 "%s%s -- "
416 #ifdef MODULE
417 "Module"
418 #else
419 "Driver"
420 #endif
421 " successfully initialized\n",
422 lvm_version, lvm_name);
424 return 0;
425 } /* init_module() / lvm_init() */
428 #ifdef MODULE
430 * Module cleanup...
432 void cleanup_module(void)
434 struct gendisk *gendisk_ptr = NULL, *gendisk_ptr_prev = NULL;
436 devfs_unregister (lvm_devfs_handle);
438 if (unregister_chrdev(LVM_CHAR_MAJOR, lvm_name) < 0) {
439 printk(KERN_ERR "%s -- unregister_chrdev failed\n", lvm_name);
441 if (unregister_blkdev(MAJOR_NR, lvm_name) < 0) {
442 printk(KERN_ERR "%s -- unregister_blkdev failed\n", lvm_name);
444 blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
446 gendisk_ptr = gendisk_ptr_prev = gendisk_head;
447 while (gendisk_ptr != NULL) {
448 if (gendisk_ptr == &lvm_gendisk)
449 break;
450 gendisk_ptr_prev = gendisk_ptr;
451 gendisk_ptr = gendisk_ptr->next;
453 /* delete our gendisk from chain */
454 if (gendisk_ptr == &lvm_gendisk)
455 gendisk_ptr_prev->next = gendisk_ptr->next;
457 blk_size[MAJOR_NR] = NULL;
458 blksize_size[MAJOR_NR] = NULL;
460 #if defined CONFIG_LVM_PROC_FS && defined CONFIG_PROC_FS
461 remove_proc_entry(LVM_NAME, &proc_root);
462 #endif
464 #ifdef LVM_HD_NAME
465 /* reference from linux/drivers/block/genhd.c */
466 lvm_hd_name_ptr = NULL;
467 #endif
469 printk(KERN_INFO "%s -- Module successfully deactivated\n", lvm_name);
471 return;
472 } /* void cleanup_module() */
473 #endif /* #ifdef MODULE */
477 * support function to initialize lvm variables
479 #ifdef __initfunc
480 __initfunc(void lvm_init_vars(void))
481 #else
482 void __init lvm_init_vars(void)
483 #endif
485 int v;
487 loadtime = CURRENT_TIME;
489 pe_lock_req.lock = UNLOCK_PE;
490 pe_lock_req.data.lv_dev = pe_lock_req.data.pv_dev = 0;
491 pe_lock_req.data.pv_offset = 0;
493 /* Initialize VG pointers */
494 for (v = 0; v < ABS_MAX_VG; v++) vg[v] = NULL;
496 /* Initialize LV -> VG association */
497 for (v = 0; v < ABS_MAX_LV; v++) {
498 /* index ABS_MAX_VG never used for real VG */
499 vg_lv_map[v].vg_number = ABS_MAX_VG;
500 vg_lv_map[v].lv_number = -1;
503 return;
504 } /* lvm_init_vars() */
507 /********************************************************************
509 * Character device functions
511 ********************************************************************/
514 * character device open routine
516 static int lvm_chr_open(struct inode *inode,
517 struct file *file)
519 int minor = MINOR(inode->i_rdev);
521 #ifdef DEBUG
522 printk(KERN_DEBUG
523 "%s -- lvm_chr_open MINOR: %d VG#: %d mode: 0x%X lock: %d\n",
524 lvm_name, minor, VG_CHR(minor), file->f_mode, lock);
525 #endif
527 /* super user validation */
528 if (!capable(CAP_SYS_ADMIN)) return -EACCES;
530 /* Group special file open */
531 if (VG_CHR(minor) > MAX_VG) return -ENXIO;
533 lvm_chr_open_count++;
534 return 0;
535 } /* lvm_chr_open() */
539 * character device i/o-control routine
541 * Only one changing process can do changing ioctl at one time,
542 * others will block.
545 static int lvm_chr_ioctl(struct inode *inode, struct file *file,
546 uint command, ulong a)
548 int minor = MINOR(inode->i_rdev);
549 uint extendable, l, v;
550 void *arg = (void *) a;
551 lv_t lv;
552 vg_t* vg_ptr = vg[VG_CHR(minor)];
554 /* otherwise cc will complain about unused variables */
555 (void) lvm_lock;
558 #ifdef DEBUG_IOCTL
559 printk(KERN_DEBUG
560 "%s -- lvm_chr_ioctl: command: 0x%X MINOR: %d "
561 "VG#: %d mode: 0x%X\n",
562 lvm_name, command, minor, VG_CHR(minor), file->f_mode);
563 #endif
565 #ifdef LVM_TOTAL_RESET
566 if (lvm_reset_spindown > 0) return -EACCES;
567 #endif
569 /* Main command switch */
570 switch (command) {
571 case LVM_LOCK_LVM:
572 /* lock the LVM */
573 return lvm_do_lock_lvm();
575 case LVM_GET_IOP_VERSION:
576 /* check lvm version to ensure driver/tools+lib
577 interoperability */
578 if (copy_to_user(arg, &lvm_iop_version, sizeof(ushort)) != 0)
579 return -EFAULT;
580 return 0;
582 #ifdef LVM_TOTAL_RESET
583 case LVM_RESET:
584 /* lock reset function */
585 lvm_reset_spindown = 1;
586 for (v = 0; v < ABS_MAX_VG; v++) {
587 if (vg[v] != NULL) lvm_do_vg_remove(v);
590 #ifdef MODULE
591 while (GET_USE_COUNT(&__this_module) < 1)
592 MOD_INC_USE_COUNT;
593 while (GET_USE_COUNT(&__this_module) > 1)
594 MOD_DEC_USE_COUNT;
595 #endif /* MODULE */
596 lock = 0; /* release lock */
597 wake_up_interruptible(&lvm_wait);
598 return 0;
599 #endif /* LVM_TOTAL_RESET */
602 case LE_REMAP:
603 /* remap a logical extent (after moving the physical extent) */
604 return lvm_do_le_remap(vg_ptr,arg);
606 case PE_LOCK_UNLOCK:
607 /* lock/unlock i/o to a physical extent to move it to another
608 physical volume (move's done in user space's pvmove) */
609 return lvm_do_pe_lock_unlock(vg_ptr,arg);
611 case VG_CREATE:
612 /* create a VGDA */
613 return lvm_do_vg_create(minor, arg);
615 case VG_REMOVE:
616 /* remove an inactive VGDA */
617 return lvm_do_vg_remove(minor);
619 case VG_EXTEND:
620 /* extend a volume group */
621 return lvm_do_vg_extend(vg_ptr,arg);
623 case VG_REDUCE:
624 /* reduce a volume group */
625 return lvm_do_vg_reduce(vg_ptr,arg);
628 case VG_SET_EXTENDABLE:
629 /* set/clear extendability flag of volume group */
630 if (vg_ptr == NULL) return -ENXIO;
631 if (copy_from_user(&extendable, arg, sizeof(extendable)) != 0)
632 return -EFAULT;
634 if (extendable == VG_EXTENDABLE ||
635 extendable == ~VG_EXTENDABLE) {
636 if (extendable == VG_EXTENDABLE)
637 vg_ptr->vg_status |= VG_EXTENDABLE;
638 else
639 vg_ptr->vg_status &= ~VG_EXTENDABLE;
640 } else return -EINVAL;
641 return 0;
644 case VG_STATUS:
645 /* get volume group data (only the vg_t struct) */
646 if (vg_ptr == NULL) return -ENXIO;
647 if (copy_to_user(arg, vg_ptr, sizeof(vg_t)) != 0)
648 return -EFAULT;
649 return 0;
652 case VG_STATUS_GET_COUNT:
653 /* get volume group count */
654 if (copy_to_user(arg, &vg_count, sizeof(vg_count)) != 0)
655 return -EFAULT;
656 return 0;
659 case VG_STATUS_GET_NAMELIST:
660 /* get volume group count */
661 for (l = v = 0; v < ABS_MAX_VG; v++) {
662 if (vg[v] != NULL) {
663 if (copy_to_user(arg + l++ * NAME_LEN,
664 vg[v]->vg_name,
665 NAME_LEN) != 0)
666 return -EFAULT;
669 return 0;
672 case LV_CREATE:
673 case LV_REMOVE:
674 case LV_EXTEND:
675 case LV_REDUCE:
676 /* create, remove, extend or reduce a logical volume */
677 if (vg_ptr == NULL) return -ENXIO;
678 if (copy_from_user(&lv_req, arg, sizeof(lv_req)) != 0)
679 return -EFAULT;
681 if (command != LV_REMOVE) {
682 if (copy_from_user(&lv, lv_req.lv, sizeof(lv_t)) != 0)
683 return -EFAULT;
685 switch (command) {
686 case LV_CREATE:
687 return lvm_do_lv_create(minor, lv_req.lv_name, &lv);
689 case LV_REMOVE:
690 return lvm_do_lv_remove(minor, lv_req.lv_name, -1);
692 case LV_EXTEND:
693 case LV_REDUCE:
694 return lvm_do_lv_extend_reduce(minor, lv_req.lv_name, &lv);
698 case LV_STATUS_BYNAME:
699 /* get status of a logical volume by name */
700 return lvm_do_lv_status_byname(vg_ptr,arg);
702 case LV_STATUS_BYINDEX:
703 /* get status of a logical volume by index */
704 return lvm_do_lv_status_byindex(vg_ptr,arg);
706 case PV_CHANGE:
707 /* change a physical volume */
708 return lvm_do_pv_change(vg_ptr,arg);
710 case PV_STATUS:
711 /* get physical volume data (pv_t structure only) */
712 return lvm_do_pv_status(vg_ptr,arg);
714 case PV_FLUSH:
715 /* physical volume buffer flush/invalidate */
716 if (copy_from_user(&pv_flush_req, arg,
717 sizeof(pv_flush_req)) != 0)
718 return -EFAULT;
720 for ( v = 0; v < ABS_MAX_VG; v++) {
721 unsigned int p;
722 if ( vg[v] == NULL) continue;
723 for ( p = 0; p < vg[v]->pv_max; p++) {
724 if ( vg[v]->pv[p] != NULL &&
725 strcmp ( vg[v]->pv[p]->pv_name,
726 pv_flush_req.pv_name) == 0) {
727 fsync_dev ( vg[v]->pv[p]->pv_dev);
728 invalidate_buffers ( vg[v]->pv[p]->pv_dev);
729 return 0;
733 return 0;
735 default:
736 printk(KERN_WARNING
737 "%s -- lvm_chr_ioctl: unknown command %x\n",
738 lvm_name, command);
739 return -EINVAL;
742 return 0;
743 } /* lvm_chr_ioctl */
747 * character device close routine
749 static int lvm_chr_close(struct inode *inode, struct file *file)
751 #ifdef DEBUG
752 int minor = MINOR(inode->i_rdev);
753 printk(KERN_DEBUG
754 "%s -- lvm_chr_close VG#: %d\n", lvm_name, VG_CHR(minor));
755 #endif
757 lock_kernel();
758 #ifdef LVM_TOTAL_RESET
759 if (lvm_reset_spindown > 0) {
760 lvm_reset_spindown = 0;
761 lvm_chr_open_count = 1;
763 #endif
765 if (lvm_chr_open_count > 0) lvm_chr_open_count--;
766 if (lock == current->pid) {
767 lock = 0; /* release lock */
768 wake_up_interruptible(&lvm_wait);
770 unlock_kernel();
772 return 0;
773 } /* lvm_chr_close() */
777 /********************************************************************
779 * Block device functions
781 ********************************************************************/
784 * block device open routine
786 static int lvm_blk_open(struct inode *inode, struct file *file)
788 int minor = MINOR(inode->i_rdev);
789 lv_t *lv_ptr;
790 vg_t *vg_ptr = vg[VG_BLK(minor)];
792 #ifdef DEBUG_LVM_BLK_OPEN
793 printk(KERN_DEBUG
794 "%s -- lvm_blk_open MINOR: %d VG#: %d LV#: %d mode: 0x%X\n",
795 lvm_name, minor, VG_BLK(minor), LV_BLK(minor), file->f_mode);
796 #endif
798 #ifdef LVM_TOTAL_RESET
799 if (lvm_reset_spindown > 0)
800 return -EPERM;
801 #endif
803 if (vg_ptr != NULL &&
804 (vg_ptr->vg_status & VG_ACTIVE) &&
805 (lv_ptr = vg_ptr->lv[LV_BLK(minor)]) != NULL &&
806 LV_BLK(minor) >= 0 &&
807 LV_BLK(minor) < vg_ptr->lv_max) {
809 /* Check parallel LV spindown (LV remove) */
810 if (lv_ptr->lv_status & LV_SPINDOWN) return -EPERM;
812 /* Check inactive LV and open for read/write */
813 if (file->f_mode & O_RDWR) {
814 if (!(lv_ptr->lv_status & LV_ACTIVE)) return -EPERM;
815 if (!(lv_ptr->lv_access & LV_WRITE)) return -EACCES;
818 /* be sure to increment VG counter */
819 if (lv_ptr->lv_open == 0) vg_ptr->lv_open++;
820 lv_ptr->lv_open++;
822 MOD_INC_USE_COUNT;
824 #ifdef DEBUG_LVM_BLK_OPEN
825 printk(KERN_DEBUG
826 "%s -- lvm_blk_open MINOR: %d VG#: %d LV#: %d size: %d\n",
827 lvm_name, minor, VG_BLK(minor), LV_BLK(minor),
828 lv_ptr->lv_size);
829 #endif
831 return 0;
833 return -ENXIO;
834 } /* lvm_blk_open() */
838 * block device i/o-control routine
840 static int lvm_blk_ioctl(struct inode *inode, struct file *file,
841 uint command, ulong a)
843 int minor = MINOR(inode->i_rdev);
844 vg_t *vg_ptr = vg[VG_BLK(minor)];
845 lv_t *lv_ptr = vg_ptr->lv[LV_BLK(minor)];
846 void *arg = (void *) a;
847 struct hd_geometry *hd = (struct hd_geometry *) a;
849 #ifdef DEBUG_IOCTL
850 printk(KERN_DEBUG
851 "%s -- lvm_blk_ioctl MINOR: %d command: 0x%X arg: %X "
852 "VG#: %dl LV#: %d\n",
853 lvm_name, minor, command, (ulong) arg,
854 VG_BLK(minor), LV_BLK(minor));
855 #endif
857 switch (command) {
858 case BLKGETSIZE:
859 /* return device size */
860 #ifdef DEBUG_IOCTL
861 printk(KERN_DEBUG
862 "%s -- lvm_blk_ioctl -- BLKGETSIZE: %u\n",
863 lvm_name, lv_ptr->lv_size);
864 #endif
865 if (put_user(lv_ptr->lv_size, (long *)arg))
866 return -EFAULT;
867 break;
870 case BLKFLSBUF:
871 /* flush buffer cache */
872 if (!capable(CAP_SYS_ADMIN)) return -EACCES;
874 #ifdef DEBUG_IOCTL
875 printk(KERN_DEBUG
876 "%s -- lvm_blk_ioctl -- BLKFLSBUF\n", lvm_name);
877 #endif
878 fsync_dev(inode->i_rdev);
879 invalidate_buffers(inode->i_rdev);
880 break;
883 case BLKRASET:
884 /* set read ahead for block device */
885 if (!capable(CAP_SYS_ADMIN)) return -EACCES;
887 #ifdef DEBUG_IOCTL
888 printk(KERN_DEBUG
889 "%s -- lvm_blk_ioctl -- BLKRASET: %d sectors for %02X:%02X\n",
890 lvm_name, (long) arg, MAJOR(inode->i_rdev), minor);
891 #endif
892 if ((long) arg < LVM_MIN_READ_AHEAD ||
893 (long) arg > LVM_MAX_READ_AHEAD)
894 return -EINVAL;
895 read_ahead[MAJOR_NR] = lv_ptr->lv_read_ahead = (long) arg;
896 break;
899 case BLKRAGET:
900 /* get current read ahead setting */
901 #ifdef DEBUG_IOCTL
902 printk(KERN_DEBUG
903 "%s -- lvm_blk_ioctl -- BLKRAGET\n", lvm_name);
904 #endif
905 if (put_user(lv_ptr->lv_read_ahead, (long *)arg))
906 return -EFAULT;
907 break;
910 case HDIO_GETGEO:
911 /* get disk geometry */
912 #ifdef DEBUG_IOCTL
913 printk(KERN_DEBUG
914 "%s -- lvm_blk_ioctl -- HDIO_GETGEO\n", lvm_name);
915 #endif
916 if (hd == NULL)
917 return -EINVAL;
919 unsigned char heads = 64;
920 unsigned char sectors = 32;
921 long start = 0;
922 short cylinders = lv_ptr->lv_size / heads / sectors;
924 if (copy_to_user((char *) &hd->heads, &heads,
925 sizeof(heads)) != 0 ||
926 copy_to_user((char *) &hd->sectors, &sectors,
927 sizeof(sectors)) != 0 ||
928 copy_to_user((short *) &hd->cylinders,
929 &cylinders, sizeof(cylinders)) != 0 ||
930 copy_to_user((long *) &hd->start, &start,
931 sizeof(start)) != 0)
932 return -EFAULT;
935 #ifdef DEBUG_IOCTL
936 printk(KERN_DEBUG
937 "%s -- lvm_blk_ioctl -- cylinders: %d\n",
938 lvm_name, lv_ptr->lv_size / heads / sectors);
939 #endif
940 break;
943 case LV_SET_ACCESS:
944 /* set access flags of a logical volume */
945 if (!capable(CAP_SYS_ADMIN)) return -EACCES;
946 lv_ptr->lv_access = (ulong) arg;
947 break;
950 case LV_SET_STATUS:
951 /* set status flags of a logical volume */
952 if (!capable(CAP_SYS_ADMIN)) return -EACCES;
953 if (!((ulong) arg & LV_ACTIVE) && lv_ptr->lv_open > 1)
954 return -EPERM;
955 lv_ptr->lv_status = (ulong) arg;
956 break;
959 case LV_SET_ALLOCATION:
960 /* set allocation flags of a logical volume */
961 if (!capable(CAP_SYS_ADMIN)) return -EACCES;
962 lv_ptr->lv_allocation = (ulong) arg;
963 break;
966 default:
967 printk(KERN_WARNING
968 "%s -- lvm_blk_ioctl: unknown command %d\n",
969 lvm_name, command);
970 return -EINVAL;
973 return 0;
974 } /* lvm_blk_ioctl() */
978 * block device close routine
980 static int lvm_blk_close(struct inode *inode, struct file *file)
982 int minor = MINOR(inode->i_rdev);
983 vg_t *vg_ptr = vg[VG_BLK(minor)];
984 lv_t *lv_ptr = vg_ptr->lv[LV_BLK(minor)];
986 #ifdef DEBUG
987 printk(KERN_DEBUG
988 "%s -- lvm_blk_close MINOR: %d VG#: %d LV#: %d\n",
989 lvm_name, minor, VG_BLK(minor), LV_BLK(minor));
990 #endif
992 sync_dev(inode->i_rdev);
993 if (lv_ptr->lv_open == 1) vg_ptr->lv_open--;
994 lv_ptr->lv_open--;
996 MOD_DEC_USE_COUNT;
998 return 0;
999 } /* lvm_blk_close() */
1002 #if defined CONFIG_LVM_PROC_FS && defined CONFIG_PROC_FS
1004 * Support function /proc-Filesystem
1006 #define LVM_PROC_BUF ( i == 0 ? dummy_buf : &buf[sz])
1008 static int lvm_proc_get_info(char *page, char **start, off_t pos, int count)
1010 int c, i, l, p, v, vg_counter, pv_counter, lv_counter, lv_open_counter,
1011 lv_open_total, pe_t_bytes, lv_block_exception_t_bytes, seconds;
1012 static off_t sz;
1013 off_t sz_last;
1014 char allocation_flag, inactive_flag, rw_flag, stripes_flag;
1015 char *lv_name, *pv_name;
1016 static char *buf = NULL;
1017 static char dummy_buf[160]; /* sized for 2 lines */
1018 vg_t *vg_ptr;
1019 lv_t *lv_ptr;
1020 pv_t *pv_ptr;
1023 #ifdef DEBUG_LVM_PROC_GET_INFO
1024 printk(KERN_DEBUG
1025 "%s - lvm_proc_get_info CALLED pos: %lu count: %d whence: %d\n",
1026 lvm_name, pos, count, whence);
1027 #endif
1029 if (pos == 0 || buf == NULL) {
1030 sz_last = vg_counter = pv_counter = lv_counter = lv_open_counter = \
1031 lv_open_total = pe_t_bytes = lv_block_exception_t_bytes = 0;
1033 /* search for activity */
1034 for (v = 0; v < ABS_MAX_VG; v++) {
1035 if ((vg_ptr = vg[v]) != NULL) {
1036 vg_counter++;
1037 pv_counter += vg_ptr->pv_cur;
1038 lv_counter += vg_ptr->lv_cur;
1039 if (vg_ptr->lv_cur > 0) {
1040 for (l = 0; l < vg[v]->lv_max; l++) {
1041 if ((lv_ptr = vg_ptr->lv[l]) != NULL) {
1042 pe_t_bytes += lv_ptr->lv_allocated_le;
1043 if (lv_ptr->lv_block_exception != NULL)
1044 lv_block_exception_t_bytes += lv_ptr->lv_remap_end;
1045 if (lv_ptr->lv_open > 0) {
1046 lv_open_counter++;
1047 lv_open_total += lv_ptr->lv_open;
1054 pe_t_bytes *= sizeof(pe_t);
1055 lv_block_exception_t_bytes *= sizeof(lv_block_exception_t);
1057 if (buf != NULL) {
1058 #ifdef DEBUG_KFREE
1059 printk(KERN_DEBUG
1060 "%s -- kfree %d\n", lvm_name, __LINE__);
1061 #endif
1062 kfree(buf);
1063 buf = NULL;
1065 /* 2 times: first to get size to allocate buffer,
1066 2nd to fill the malloced buffer */
1067 for (i = 0; i < 2; i++) {
1068 sz = 0;
1069 sz += sprintf(LVM_PROC_BUF,
1070 "LVM "
1071 #ifdef MODULE
1072 "module"
1073 #else
1074 "driver"
1075 #endif
1076 " %s\n\n"
1077 "Total: %d VG%s %d PV%s %d LV%s ",
1078 lvm_short_version,
1079 vg_counter, vg_counter == 1 ? "" : "s",
1080 pv_counter, pv_counter == 1 ? "" : "s",
1081 lv_counter, lv_counter == 1 ? "" : "s");
1082 sz += sprintf(LVM_PROC_BUF,
1083 "(%d LV%s open",
1084 lv_open_counter,
1085 lv_open_counter == 1 ? "" : "s");
1086 if (lv_open_total > 0)
1087 sz += sprintf(LVM_PROC_BUF,
1088 " %d times)\n",
1089 lv_open_total);
1090 else
1091 sz += sprintf(LVM_PROC_BUF, ")");
1092 sz += sprintf(LVM_PROC_BUF,
1093 "\nGlobal: %lu bytes malloced IOP version: %d ",
1094 vg_counter * sizeof(vg_t) +
1095 pv_counter * sizeof(pv_t) +
1096 lv_counter * sizeof(lv_t) +
1097 pe_t_bytes + lv_block_exception_t_bytes + sz_last,
1098 lvm_iop_version);
1100 seconds = CURRENT_TIME - loadtime;
1101 if (seconds < 0)
1102 loadtime = CURRENT_TIME + seconds;
1103 if (seconds / 86400 > 0) {
1104 sz += sprintf(LVM_PROC_BUF, "%d day%s ",
1105 seconds / 86400,
1106 seconds / 86400 == 0 ||
1107 seconds / 86400 > 1 ? "s" : "");
1109 sz += sprintf(LVM_PROC_BUF, "%d:%02d:%02d active\n",
1110 (seconds % 86400) / 3600,
1111 (seconds % 3600) / 60,
1112 seconds % 60);
1114 if (vg_counter > 0) {
1115 for (v = 0; v < ABS_MAX_VG; v++) {
1116 /* volume group */
1117 if ((vg_ptr = vg[v]) != NULL) {
1118 inactive_flag = ' ';
1119 if (!(vg_ptr->vg_status & VG_ACTIVE)) inactive_flag = 'I';
1120 sz += sprintf(LVM_PROC_BUF,
1121 "\nVG: %c%s [%d PV, %d LV/%d open] "
1122 " PE Size: %d KB\n"
1123 " Usage [KB/PE]: %d /%d total "
1124 "%d /%d used %d /%d free",
1125 inactive_flag,
1126 vg_ptr->vg_name,
1127 vg_ptr->pv_cur,
1128 vg_ptr->lv_cur,
1129 vg_ptr->lv_open,
1130 vg_ptr->pe_size >> 1,
1131 vg_ptr->pe_size * vg_ptr->pe_total >> 1,
1132 vg_ptr->pe_total,
1133 vg_ptr->pe_allocated * vg_ptr->pe_size >> 1,
1134 vg_ptr->pe_allocated,
1135 (vg_ptr->pe_total - vg_ptr->pe_allocated) *
1136 vg_ptr->pe_size >> 1,
1137 vg_ptr->pe_total - vg_ptr->pe_allocated);
1139 /* physical volumes */
1140 sz += sprintf(LVM_PROC_BUF,
1141 "\n PV%s ",
1142 vg_ptr->pv_cur == 1 ? ": " : "s:");
1143 c = 0;
1144 for (p = 0; p < vg_ptr->pv_max; p++) {
1145 if ((pv_ptr = vg_ptr->pv[p]) != NULL) {
1146 inactive_flag = 'A';
1147 if (!(pv_ptr->pv_status & PV_ACTIVE))
1148 inactive_flag = 'I';
1149 allocation_flag = 'A';
1150 if (!(pv_ptr->pv_allocatable & PV_ALLOCATABLE))
1151 allocation_flag = 'N';
1152 pv_name = strchr(pv_ptr->pv_name+1,'/');
1153 if ( pv_name == 0) pv_name = pv_ptr->pv_name;
1154 else pv_name++;
1155 sz += sprintf(LVM_PROC_BUF,
1156 "[%c%c] %-21s %8d /%-6d "
1157 "%8d /%-6d %8d /%-6d",
1158 inactive_flag,
1159 allocation_flag,
1160 pv_name,
1161 pv_ptr->pe_total *
1162 pv_ptr->pe_size >> 1,
1163 pv_ptr->pe_total,
1164 pv_ptr->pe_allocated *
1165 pv_ptr->pe_size >> 1,
1166 pv_ptr->pe_allocated,
1167 (pv_ptr->pe_total -
1168 pv_ptr->pe_allocated) *
1169 pv_ptr->pe_size >> 1,
1170 pv_ptr->pe_total -
1171 pv_ptr->pe_allocated);
1172 c++;
1173 if (c < vg_ptr->pv_cur)
1174 sz += sprintf(LVM_PROC_BUF,
1175 "\n ");
1179 /* logical volumes */
1180 sz += sprintf(LVM_PROC_BUF,
1181 "\n LV%s ",
1182 vg_ptr->lv_cur == 1 ? ": " : "s:");
1183 c = 0;
1184 for (l = 0; l < vg[v]->lv_max; l++) {
1185 if ((lv_ptr = vg_ptr->lv[l]) != NULL) {
1186 inactive_flag = 'A';
1187 if (!(lv_ptr->lv_status & LV_ACTIVE))
1188 inactive_flag = 'I';
1189 rw_flag = 'R';
1190 if (lv_ptr->lv_access & LV_WRITE)
1191 rw_flag = 'W';
1192 allocation_flag = 'D';
1193 if (lv_ptr->lv_allocation & LV_CONTIGUOUS)
1194 allocation_flag = 'C';
1195 stripes_flag = 'L';
1196 if (lv_ptr->lv_stripes > 1)
1197 stripes_flag = 'S';
1198 sz += sprintf(LVM_PROC_BUF,
1199 "[%c%c%c%c",
1200 inactive_flag,
1201 rw_flag,
1202 allocation_flag,
1203 stripes_flag);
1204 if (lv_ptr->lv_stripes > 1)
1205 sz += sprintf(LVM_PROC_BUF, "%-2d",
1206 lv_ptr->lv_stripes);
1207 else
1208 sz += sprintf(LVM_PROC_BUF, " ");
1209 lv_name = strrchr(lv_ptr->lv_name, '/');
1210 if ( lv_name == 0) lv_name = lv_ptr->lv_name;
1211 else lv_name++;
1212 sz += sprintf(LVM_PROC_BUF, "] %-25s", lv_name);
1213 if (strlen(lv_name) > 25)
1214 sz += sprintf(LVM_PROC_BUF,
1215 "\n ");
1216 sz += sprintf(LVM_PROC_BUF, "%9d /%-6d ",
1217 lv_ptr->lv_size >> 1,
1218 lv_ptr->lv_size / vg[v]->pe_size);
1220 if (lv_ptr->lv_open == 0)
1221 sz += sprintf(LVM_PROC_BUF, "close");
1222 else
1223 sz += sprintf(LVM_PROC_BUF, "%dx open",
1224 lv_ptr->lv_open);
1225 c++;
1226 if (c < vg_ptr->lv_cur)
1227 sz += sprintf(LVM_PROC_BUF,
1228 "\n ");
1231 if (vg_ptr->lv_cur == 0) sz += sprintf(LVM_PROC_BUF, "none");
1232 sz += sprintf(LVM_PROC_BUF, "\n");
1236 if (buf == NULL) {
1237 if ((buf = vmalloc(sz)) == NULL) {
1238 sz = 0;
1239 return sprintf(page, "%s - vmalloc error at line %d\n",
1240 lvm_name, __LINE__);
1243 sz_last = sz;
1246 if (pos > sz - 1) {
1247 vfree(buf);
1248 buf = NULL;
1249 return 0;
1251 *start = &buf[pos];
1252 if (sz - pos < count)
1253 return sz - pos;
1254 else
1255 return count;
1256 } /* lvm_proc_get_info() */
1257 #endif /* #if defined CONFIG_LVM_PROC_FS && defined CONFIG_PROC_FS */
1261 * block device support function for /usr/src/linux/drivers/block/ll_rw_blk.c
1262 * (see init_module/lvm_init)
1264 static int lvm_map(struct buffer_head *bh, int rw)
1266 int minor = MINOR(bh->b_rdev);
1267 ulong index;
1268 ulong pe_start;
1269 ulong size = bh->b_size >> 9;
1270 ulong rsector_tmp = bh->b_rsector;
1271 ulong rsector_sav;
1272 kdev_t rdev_tmp = bh->b_rdev;
1273 kdev_t rdev_sav;
1274 lv_t *lv = vg[VG_BLK(minor)]->lv[LV_BLK(minor)];
1277 if (!(lv->lv_status & LV_ACTIVE)) {
1278 printk(KERN_ALERT
1279 "%s - lvm_map: ll_rw_blk for inactive LV %s\n",
1280 lvm_name, lv->lv_name);
1281 goto error;
1284 if ( lv->lv_access & LV_SNAPSHOT)
1285 printk ( "%s -- %02d:%02d block: %lu rw: %d\n", lvm_name, MAJOR ( bh->b_dev), MINOR ( bh->b_dev), bh->b_blocknr, rw);
1288 /* take care of snapshot chunk writes before
1289 check for writable logical volume */
1290 if ((lv->lv_access & LV_SNAPSHOT) &&
1291 MAJOR(bh->b_rdev) != 0 &&
1292 MAJOR(bh->b_rdev) != MAJOR_NR &&
1293 (rw == WRITEA || rw == WRITE))
1295 printk ( "%s -- doing snapshot write for %02d:%02d[%02d:%02d] b_blocknr: %lu b_rsector: %lu\n", lvm_name, MAJOR ( bh->b_dev), MINOR ( bh->b_dev), MAJOR ( bh->b_rdev), MINOR ( bh->b_rdev), bh->b_blocknr, bh->b_rsector);
1296 goto error;
1299 if ((rw == WRITE || rw == WRITEA) &&
1300 !(lv->lv_access & LV_WRITE)) {
1301 printk(KERN_CRIT
1302 "%s - lvm_map: ll_rw_blk write for readonly LV %s\n",
1303 lvm_name, lv->lv_name);
1304 goto error;
1306 #ifdef DEBUG_MAP
1307 printk(KERN_DEBUG
1308 "%s - lvm_map minor:%d *rdev: %02d:%02d *rsector: %lu "
1309 "size:%lu\n",
1310 lvm_name, minor,
1311 MAJOR(rdev_tmp),
1312 MINOR(rdev_tmp),
1313 rsector_tmp, size);
1314 #endif
1316 if (rsector_tmp + size > lv->lv_size) {
1317 printk(KERN_ALERT
1318 "%s - lvm_map *rsector: %lu or size: %lu wrong for"
1319 " minor: %2d\n", lvm_name, rsector_tmp, size, minor);
1320 goto error;
1322 rsector_sav = rsector_tmp;
1323 rdev_sav = rdev_tmp;
1325 lvm_second_remap:
1326 /* linear mapping */
1327 if (lv->lv_stripes < 2) {
1328 /* get the index */
1329 index = rsector_tmp / vg[VG_BLK(minor)]->pe_size;
1330 pe_start = lv->lv_current_pe[index].pe;
1331 rsector_tmp = lv->lv_current_pe[index].pe +
1332 (rsector_tmp % vg[VG_BLK(minor)]->pe_size);
1333 rdev_tmp = lv->lv_current_pe[index].dev;
1335 #ifdef DEBUG_MAP
1336 printk(KERN_DEBUG
1337 "lv_current_pe[%ld].pe: %ld rdev: %02d:%02d rsector:%ld\n",
1338 index,
1339 lv->lv_current_pe[index].pe,
1340 MAJOR(rdev_tmp),
1341 MINOR(rdev_tmp),
1342 rsector_tmp);
1343 #endif
1345 /* striped mapping */
1346 } else {
1347 ulong stripe_index;
1348 ulong stripe_length;
1350 stripe_length = vg[VG_BLK(minor)]->pe_size * lv->lv_stripes;
1351 stripe_index = (rsector_tmp % stripe_length) / lv->lv_stripesize;
1352 index = rsector_tmp / stripe_length +
1353 (stripe_index % lv->lv_stripes) *
1354 (lv->lv_allocated_le / lv->lv_stripes);
1355 pe_start = lv->lv_current_pe[index].pe;
1356 rsector_tmp = lv->lv_current_pe[index].pe +
1357 (rsector_tmp % stripe_length) -
1358 (stripe_index % lv->lv_stripes) * lv->lv_stripesize -
1359 stripe_index / lv->lv_stripes *
1360 (lv->lv_stripes - 1) * lv->lv_stripesize;
1361 rdev_tmp = lv->lv_current_pe[index].dev;
1364 #ifdef DEBUG_MAP
1365 printk(KERN_DEBUG
1366 "lv_current_pe[%ld].pe: %ld rdev: %02d:%02d rsector:%ld\n"
1367 "stripe_length: %ld stripe_index: %ld\n",
1368 index,
1369 lv->lv_current_pe[index].pe,
1370 MAJOR(rdev_tmp),
1371 MINOR(rdev_tmp),
1372 rsector_tmp,
1373 stripe_length,
1374 stripe_index);
1375 #endif
1377 /* handle physical extents on the move */
1378 if (pe_lock_req.lock == LOCK_PE) {
1379 if (rdev_tmp == pe_lock_req.data.pv_dev &&
1380 rsector_tmp >= pe_lock_req.data.pv_offset &&
1381 rsector_tmp < (pe_lock_req.data.pv_offset +
1382 vg[VG_BLK(minor)]->pe_size)) {
1383 sleep_on(&lvm_map_wait);
1384 rsector_tmp = rsector_sav;
1385 rdev_tmp = rdev_sav;
1386 goto lvm_second_remap;
1389 /* statistic */
1390 if (rw == WRITE || rw == WRITEA)
1391 lv->lv_current_pe[index].writes++;
1392 else
1393 lv->lv_current_pe[index].reads++;
1395 /* snapshot volume exception handling on physical device address base */
1396 if (lv->lv_access & (LV_SNAPSHOT | LV_SNAPSHOT_ORG)) {
1397 /* original logical volume */
1398 if (lv->lv_access & LV_SNAPSHOT_ORG) {
1399 if (rw == WRITE || rw == WRITEA)
1401 lv_t *lv_ptr;
1403 /* start with first snapshot and loop thrugh all of them */
1404 for (lv_ptr = lv->lv_snapshot_next;
1405 lv_ptr != NULL;
1406 lv_ptr = lv_ptr->lv_snapshot_next) {
1407 down(&lv->lv_snapshot_org->lv_snapshot_sem);
1408 /* do we still have exception storage for this snapshot free? */
1409 if (lv_ptr->lv_block_exception != NULL) {
1410 rdev_sav = rdev_tmp;
1411 rsector_sav = rsector_tmp;
1412 if (!lvm_snapshot_remap_block(&rdev_tmp,
1413 &rsector_tmp,
1414 pe_start,
1415 lv_ptr)) {
1416 /* create a new mapping */
1417 lvm_snapshot_COW(rdev_tmp,
1418 rsector_tmp,
1419 pe_start,
1420 rsector_sav,
1421 lv_ptr);
1423 rdev_tmp = rdev_sav;
1424 rsector_tmp = rsector_sav;
1426 up(&lv->lv_snapshot_org->lv_snapshot_sem);
1429 } else {
1430 /* remap snapshot logical volume */
1431 down(&lv->lv_snapshot_sem);
1432 if (lv->lv_block_exception != NULL)
1433 lvm_snapshot_remap_block(&rdev_tmp, &rsector_tmp, pe_start, lv);
1434 up(&lv->lv_snapshot_sem);
1437 bh->b_rdev = rdev_tmp;
1438 bh->b_rsector = rsector_tmp;
1440 return 1;
1442 error:
1443 buffer_IO_error(bh);
1444 return -1;
1445 } /* lvm_map() */
1449 * internal support functions
1452 #ifdef LVM_HD_NAME
1454 * generate "hard disk" name
1456 void lvm_hd_name(char *buf, int minor)
1458 int len = 0;
1459 lv_t *lv_ptr;
1461 if (vg[VG_BLK(minor)] == NULL ||
1462 (lv_ptr = vg[VG_BLK(minor)]->lv[LV_BLK(minor)]) == NULL)
1463 return;
1464 len = strlen(lv_ptr->lv_name) - 5;
1465 memcpy(buf, &lv_ptr->lv_name[5], len);
1466 buf[len] = 0;
1467 return;
1469 #endif
1473 * this one never should be called...
1475 static void lvm_dummy_device_request(request_queue_t * t)
1477 printk(KERN_EMERG
1478 "%s -- oops, got lvm request for %02d:%02d [sector: %lu]\n",
1479 lvm_name,
1480 MAJOR(CURRENT->rq_dev),
1481 MINOR(CURRENT->rq_dev),
1482 CURRENT->sector);
1483 return;
1488 * make request function
1490 static int lvm_make_request_fn(request_queue_t *q, int rw, struct buffer_head *bh)
1492 if (lvm_map(bh, rw)<0)
1493 return 0; /* failure, buffer_IO_error has been called, don't recurse */
1494 else
1495 return 1; /* all ok, mapping done, call lower level driver */
1499 * plug device function is a noop because plugging has to happen
1500 * in the queue of the physical blockdevice to allow the
1501 * elevator to do a better job.
1503 static void lvm_plug_device_noop(request_queue_t *q, kdev_t dev) { }
1505 /********************************************************************
1507 * Character device support functions
1509 ********************************************************************/
1511 * character device support function logical volume manager lock
1513 static int lvm_do_lock_lvm(void)
1515 lock_try_again:
1516 spin_lock(&lvm_lock);
1517 if (lock != 0 && lock != current->pid) {
1518 #ifdef DEBUG_IOCTL
1519 printk(KERN_INFO "lvm_do_lock_lvm: %s is locked by pid %d ...\n",
1520 lvm_name, lock);
1521 #endif
1522 spin_unlock(&lvm_lock);
1523 interruptible_sleep_on(&lvm_wait);
1524 if (current->sigpending != 0)
1525 return -EINTR;
1526 #ifdef LVM_TOTAL_RESET
1527 if (lvm_reset_spindown > 0)
1528 return -EACCES;
1529 #endif
1530 goto lock_try_again;
1532 lock = current->pid;
1533 spin_unlock(&lvm_lock);
1534 return 0;
1535 } /* lvm_do_lock_lvm */
1539 * character device support function lock/unlock physical extend
1541 static int lvm_do_pe_lock_unlock(vg_t *vg_ptr, void *arg)
1543 uint p;
1545 if (vg_ptr == NULL) return -ENXIO;
1546 if (copy_from_user(&pe_lock_req, arg,
1547 sizeof(pe_lock_req_t)) != 0) return -EFAULT;
1549 switch (pe_lock_req.lock) {
1550 case LOCK_PE:
1551 for (p = 0; p < vg_ptr->pv_max; p++) {
1552 if (vg_ptr->pv[p] != NULL &&
1553 pe_lock_req.data.pv_dev ==
1554 vg_ptr->pv[p]->pv_dev)
1555 break;
1557 if (p == vg_ptr->pv_max) return -ENXIO;
1559 pe_lock_req.lock = UNLOCK_PE;
1560 fsync_dev(pe_lock_req.data.lv_dev);
1561 pe_lock_req.lock = LOCK_PE;
1562 break;
1564 case UNLOCK_PE:
1565 pe_lock_req.lock = UNLOCK_PE;
1566 pe_lock_req.data.lv_dev = pe_lock_req.data.pv_dev = 0;
1567 pe_lock_req.data.pv_offset = 0;
1568 wake_up(&lvm_map_wait);
1569 break;
1571 default:
1572 return -EINVAL;
1574 return 0;
1579 * character device support function logical extend remap
1581 static int lvm_do_le_remap(vg_t *vg_ptr, void *arg)
1583 uint l, le;
1584 lv_t *lv_ptr;
1586 if (vg_ptr == NULL) return -ENXIO;
1587 if (copy_from_user(&le_remap_req, arg,
1588 sizeof(le_remap_req_t)) != 0)
1589 return -EFAULT;
1591 for (l = 0; l < vg_ptr->lv_max; l++) {
1592 lv_ptr = vg_ptr->lv[l];
1593 if (lv_ptr != NULL &&
1594 strcmp(lv_ptr->lv_name,
1595 le_remap_req.lv_name) == 0) {
1596 for (le = 0; le < lv_ptr->lv_allocated_le;
1597 le++) {
1598 if (lv_ptr->lv_current_pe[le].dev ==
1599 le_remap_req.old_dev &&
1600 lv_ptr->lv_current_pe[le].pe ==
1601 le_remap_req.old_pe) {
1602 lv_ptr->lv_current_pe[le].dev =
1603 le_remap_req.new_dev;
1604 lv_ptr->lv_current_pe[le].pe =
1605 le_remap_req.new_pe;
1606 return 0;
1609 return -EINVAL;
1612 return -ENXIO;
1613 } /* lvm_do_le_remap() */
1617 * character device support function VGDA create
1619 int lvm_do_vg_create(int minor, void *arg)
1621 int snaporg_minor = 0;
1622 ulong l, p;
1623 lv_t lv;
1624 vg_t *vg_ptr;
1625 pv_t *pv_ptr;
1626 lv_t *lv_ptr;
1628 if (vg[VG_CHR(minor)] != NULL) return -EPERM;
1630 if ((vg_ptr = kmalloc(sizeof(vg_t),GFP_KERNEL)) == NULL) {
1631 printk(KERN_CRIT
1632 "%s -- VG_CREATE: kmalloc error VG at line %d\n",
1633 lvm_name, __LINE__);
1634 return -ENOMEM;
1636 /* get the volume group structure */
1637 if (copy_from_user(vg_ptr, arg, sizeof(vg_t)) != 0) {
1638 kfree(vg_ptr);
1639 return -EFAULT;
1642 vg_devfs_handle[vg_ptr->vg_number] = devfs_mk_dir(0, vg_ptr->vg_name, NULL);
1643 ch_devfs_handle[vg_ptr->vg_number] = devfs_register(
1644 vg_devfs_handle[vg_ptr->vg_number] , "group",
1645 DEVFS_FL_DEFAULT, LVM_CHAR_MAJOR, vg_ptr->vg_number,
1646 S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP,
1647 &lvm_chr_fops, NULL);
1649 /* we are not that active so far... */
1650 vg_ptr->vg_status &= ~VG_ACTIVE;
1651 vg[VG_CHR(minor)] = vg_ptr;
1653 vg[VG_CHR(minor)]->pe_allocated = 0;
1654 if (vg_ptr->pv_max > ABS_MAX_PV) {
1655 printk(KERN_WARNING
1656 "%s -- Can't activate VG: ABS_MAX_PV too small\n",
1657 lvm_name);
1658 kfree(vg_ptr);
1659 vg[VG_CHR(minor)] = NULL;
1660 return -EPERM;
1662 if (vg_ptr->lv_max > ABS_MAX_LV) {
1663 printk(KERN_WARNING
1664 "%s -- Can't activate VG: ABS_MAX_LV too small for %u\n",
1665 lvm_name, vg_ptr->lv_max);
1666 kfree(vg_ptr);
1667 vg_ptr = NULL;
1668 return -EPERM;
1670 /* get the physical volume structures */
1671 vg_ptr->pv_act = vg_ptr->pv_cur = 0;
1672 for (p = 0; p < vg_ptr->pv_max; p++) {
1673 /* user space address */
1674 if ((pvp = vg_ptr->pv[p]) != NULL) {
1675 pv_ptr = vg_ptr->pv[p] = kmalloc(sizeof(pv_t),GFP_KERNEL);
1676 if (pv_ptr == NULL) {
1677 printk(KERN_CRIT
1678 "%s -- VG_CREATE: kmalloc error PV at line %d\n",
1679 lvm_name, __LINE__);
1680 lvm_do_vg_remove(minor);
1681 return -ENOMEM;
1683 if (copy_from_user(pv_ptr, pvp, sizeof(pv_t)) != 0) {
1684 lvm_do_vg_remove(minor);
1685 return -EFAULT;
1687 /* We don't need the PE list
1688 in kernel space as with LVs pe_t list (see below) */
1689 pv_ptr->pe = NULL;
1690 pv_ptr->pe_allocated = 0;
1691 pv_ptr->pv_status = PV_ACTIVE;
1692 vg_ptr->pv_act++;
1693 vg_ptr->pv_cur++;
1695 #ifdef LVM_GET_INODE
1696 /* insert a dummy inode for fs_may_mount */
1697 pv_ptr->inode = lvm_get_inode(pv_ptr->pv_dev);
1698 #endif
1702 /* get the logical volume structures */
1703 vg_ptr->lv_cur = 0;
1704 for (l = 0; l < vg_ptr->lv_max; l++) {
1705 /* user space address */
1706 if ((lvp = vg_ptr->lv[l]) != NULL) {
1707 if (copy_from_user(&lv, lvp, sizeof(lv_t)) != 0) {
1708 lvm_do_vg_remove(minor);
1709 return -EFAULT;
1711 vg_ptr->lv[l] = NULL;
1712 if (lvm_do_lv_create(minor, lv.lv_name, &lv) != 0) {
1713 lvm_do_vg_remove(minor);
1714 return -EFAULT;
1719 /* Second path to correct snapshot logical volumes which are not
1720 in place during first path above */
1721 for (l = 0; l < vg_ptr->lv_max; l++) {
1722 if ((lv_ptr = vg_ptr->lv[l]) != NULL &&
1723 vg_ptr->lv[l]->lv_access & LV_SNAPSHOT) {
1724 snaporg_minor = lv_ptr->lv_snapshot_minor;
1725 if (vg_ptr->lv[LV_BLK(snaporg_minor)] != NULL) {
1726 /* get pointer to original logical volume */
1727 lv_ptr = vg_ptr->lv[l]->lv_snapshot_org =
1728 vg_ptr->lv[LV_BLK(snaporg_minor)];
1730 /* set necessary fields of original logical volume */
1731 lv_ptr->lv_access |= LV_SNAPSHOT_ORG;
1732 lv_ptr->lv_snapshot_minor = 0;
1733 lv_ptr->lv_snapshot_org = lv_ptr;
1734 lv_ptr->lv_snapshot_prev = NULL;
1736 /* find last snapshot logical volume in the chain */
1737 while (lv_ptr->lv_snapshot_next != NULL)
1738 lv_ptr = lv_ptr->lv_snapshot_next;
1740 /* set back pointer to this last one in our new logical volume */
1741 vg_ptr->lv[l]->lv_snapshot_prev = lv_ptr;
1743 /* last logical volume now points to our new snapshot volume */
1744 lv_ptr->lv_snapshot_next = vg_ptr->lv[l];
1746 /* now point to the new one */
1747 lv_ptr = lv_ptr->lv_snapshot_next;
1749 /* set necessary fields of new snapshot logical volume */
1750 lv_ptr->lv_snapshot_next = NULL;
1751 lv_ptr->lv_current_pe =
1752 vg_ptr->lv[LV_BLK(snaporg_minor)]->lv_current_pe;
1753 lv_ptr->lv_allocated_le =
1754 vg_ptr->lv[LV_BLK(snaporg_minor)]->lv_allocated_le;
1755 lv_ptr->lv_current_le =
1756 vg_ptr->lv[LV_BLK(snaporg_minor)]->lv_current_le;
1757 lv_ptr->lv_size =
1758 vg_ptr->lv[LV_BLK(snaporg_minor)]->lv_size;
1763 vg_count++;
1765 /* let's go active */
1766 vg_ptr->vg_status |= VG_ACTIVE;
1768 MOD_INC_USE_COUNT;
1770 return 0;
1771 } /* lvm_do_vg_create() */
1775 * character device support function VGDA extend
1777 static int lvm_do_vg_extend(vg_t *vg_ptr, void *arg)
1779 uint p;
1780 pv_t *pv_ptr;
1782 if (vg_ptr == NULL) return -ENXIO;
1783 if (vg_ptr->pv_cur < vg_ptr->pv_max) {
1784 for (p = 0; p < vg_ptr->pv_max; p++) {
1785 if (vg_ptr->pv[p] == NULL) {
1786 if ((pv_ptr = vg_ptr->pv[p] = kmalloc(sizeof(pv_t),GFP_KERNEL)) == NULL) {
1787 printk(KERN_CRIT
1788 "%s -- VG_EXTEND: kmalloc error PV at line %d\n",
1789 lvm_name, __LINE__);
1790 return -ENOMEM;
1792 if (copy_from_user(pv_ptr, arg, sizeof(pv_t)) != 0) {
1793 kfree(pv_ptr);
1794 vg_ptr->pv[p] = NULL;
1795 return -EFAULT;
1798 pv_ptr->pv_status = PV_ACTIVE;
1799 /* We don't need the PE list
1800 in kernel space like LVs pe_t list */
1801 pv_ptr->pe = NULL;
1802 vg_ptr->pv_cur++;
1803 vg_ptr->pv_act++;
1804 vg_ptr->pe_total +=
1805 pv_ptr->pe_total;
1806 #ifdef LVM_GET_INODE
1807 /* insert a dummy inode for fs_may_mount */
1808 pv_ptr->inode = lvm_get_inode(pv_ptr->pv_dev);
1809 #endif
1810 return 0;
1814 return -EPERM;
1815 } /* lvm_do_vg_extend() */
1819 * character device support function VGDA reduce
1821 static int lvm_do_vg_reduce(vg_t *vg_ptr, void *arg)
1823 uint p;
1824 pv_t *pv_ptr;
1826 if (vg_ptr == NULL) return -ENXIO;
1827 if (copy_from_user(pv_name, arg, sizeof(pv_name)) != 0)
1828 return -EFAULT;
1830 for (p = 0; p < vg_ptr->pv_max; p++) {
1831 pv_ptr = vg_ptr->pv[p];
1832 if (pv_ptr != NULL &&
1833 strcmp(pv_ptr->pv_name,
1834 pv_name) == 0) {
1835 if (pv_ptr->lv_cur > 0) return -EPERM;
1836 vg_ptr->pe_total -=
1837 pv_ptr->pe_total;
1838 vg_ptr->pv_cur--;
1839 vg_ptr->pv_act--;
1840 #ifdef LVM_GET_INODE
1841 lvm_clear_inode(pv_ptr->inode);
1842 #endif
1843 kfree(pv_ptr);
1844 /* Make PV pointer array contiguous */
1845 for (; p < vg_ptr->pv_max - 1; p++)
1846 vg_ptr->pv[p] = vg_ptr->pv[p + 1];
1847 vg_ptr->pv[p + 1] = NULL;
1848 return 0;
1851 return -ENXIO;
1852 } /* lvm_do_vg_reduce */
1856 * character device support function VGDA remove
1858 static int lvm_do_vg_remove(int minor)
1860 int i;
1861 vg_t *vg_ptr = vg[VG_CHR(minor)];
1862 pv_t *pv_ptr;
1864 if (vg_ptr == NULL) return -ENXIO;
1866 #ifdef LVM_TOTAL_RESET
1867 if (vg_ptr->lv_open > 0 && lvm_reset_spindown == 0)
1868 #else
1869 if (vg_ptr->lv_open > 0)
1870 #endif
1871 return -EPERM;
1873 /* let's go inactive */
1874 vg_ptr->vg_status &= ~VG_ACTIVE;
1876 devfs_unregister (ch_devfs_handle[vg_ptr->vg_number]);
1877 devfs_unregister (vg_devfs_handle[vg_ptr->vg_number]);
1879 /* free LVs */
1880 /* first free snapshot logical volumes */
1881 for (i = 0; i < vg_ptr->lv_max; i++) {
1882 if (vg_ptr->lv[i] != NULL &&
1883 vg_ptr->lv[i]->lv_access & LV_SNAPSHOT) {
1884 lvm_do_lv_remove(minor, NULL, i);
1885 current->state = TASK_UNINTERRUPTIBLE;
1886 schedule_timeout(1);
1889 /* then free the rest of the LVs */
1890 for (i = 0; i < vg_ptr->lv_max; i++) {
1891 if (vg_ptr->lv[i] != NULL) {
1892 lvm_do_lv_remove(minor, NULL, i);
1893 current->state = TASK_UNINTERRUPTIBLE;
1894 schedule_timeout(1);
1898 /* free PVs */
1899 for (i = 0; i < vg_ptr->pv_max; i++) {
1900 if ((pv_ptr = vg_ptr->pv[i]) != NULL) {
1901 #ifdef DEBUG_KFREE
1902 printk(KERN_DEBUG
1903 "%s -- kfree %d\n", lvm_name, __LINE__);
1904 #endif
1905 #ifdef LVM_GET_INODE
1906 lvm_clear_inode(pv_ptr->inode);
1907 #endif
1908 kfree(pv_ptr);
1909 vg[VG_CHR(minor)]->pv[i] = NULL;
1913 #ifdef DEBUG_KFREE
1914 printk(KERN_DEBUG "%s -- kfree %d\n", lvm_name, __LINE__);
1915 #endif
1916 kfree(vg_ptr);
1917 vg[VG_CHR(minor)] = NULL;
1919 vg_count--;
1921 MOD_DEC_USE_COUNT;
1923 return 0;
1924 } /* lvm_do_vg_remove() */
1928 * character device support function logical volume create
1930 static int lvm_do_lv_create(int minor, char *lv_name, lv_t *lv)
1932 int l, le, l_new, p, size;
1933 ulong lv_status_save;
1934 char *lv_tmp, *lv_buf = NULL;
1935 lv_block_exception_t *lvbe = lv->lv_block_exception;
1936 vg_t *vg_ptr = vg[VG_CHR(minor)];
1937 lv_t *lv_ptr = NULL;
1939 if ((pep = lv->lv_current_pe) == NULL) return -EINVAL;
1940 if (lv->lv_chunk_size > LVM_SNAPSHOT_MAX_CHUNK)
1941 return -EINVAL;
1943 for (l = 0; l < vg_ptr->lv_max; l++) {
1944 if (vg_ptr->lv[l] != NULL &&
1945 strcmp(vg_ptr->lv[l]->lv_name, lv_name) == 0)
1946 return -EEXIST;
1949 /* in case of lv_remove(), lv_create() pair; for eg. lvrename does this */
1950 l_new = -1;
1951 if (vg_ptr->lv[lv->lv_number] == NULL)
1952 l_new = lv->lv_number;
1953 else {
1954 for (l = 0; l < vg_ptr->lv_max; l++) {
1955 if (vg_ptr->lv[l] == NULL)
1956 if (l_new == -1) l_new = l;
1959 if (l_new == -1) return -EPERM;
1960 else l = l_new;
1962 if ((lv_ptr = kmalloc(sizeof(lv_t),GFP_KERNEL)) == NULL) {;
1963 printk(KERN_CRIT "%s -- LV_CREATE: kmalloc error LV at line %d\n",
1964 lvm_name, __LINE__);
1965 return -ENOMEM;
1967 /* copy preloaded LV */
1968 memcpy((char *) lv_ptr, (char *) lv, sizeof(lv_t));
1970 lv_status_save = lv_ptr->lv_status;
1971 lv_ptr->lv_status &= ~LV_ACTIVE;
1972 lv_ptr->lv_snapshot_org = \
1973 lv_ptr->lv_snapshot_prev = \
1974 lv_ptr->lv_snapshot_next = NULL;
1975 lv_ptr->lv_block_exception = NULL;
1976 init_MUTEX(&lv_ptr->lv_snapshot_sem);
1977 vg_ptr->lv[l] = lv_ptr;
1979 /* get the PE structures from user space if this
1980 is no snapshot logical volume */
1981 if (!(lv_ptr->lv_access & LV_SNAPSHOT)) {
1982 size = lv_ptr->lv_allocated_le * sizeof(pe_t);
1983 if ((lv_ptr->lv_current_pe = vmalloc(size)) == NULL) {
1984 printk(KERN_CRIT
1985 "%s -- LV_CREATE: vmalloc error LV_CURRENT_PE of %d Byte "
1986 "at line %d\n",
1987 lvm_name, size, __LINE__);
1988 #ifdef DEBUG_KFREE
1989 printk(KERN_DEBUG "%s -- kfree %d\n", lvm_name, __LINE__);
1990 #endif
1991 kfree(lv_ptr);
1992 vg[VG_CHR(minor)]->lv[l] = NULL;
1993 return -ENOMEM;
1995 if (copy_from_user(lv_ptr->lv_current_pe, pep, size)) {
1996 vfree(lv_ptr->lv_current_pe);
1997 kfree(lv_ptr);
1998 vg_ptr->lv[l] = NULL;
1999 return -EFAULT;
2001 /* correct the PE count in PVs */
2002 for (le = 0; le < lv_ptr->lv_allocated_le; le++) {
2003 vg_ptr->pe_allocated++;
2004 for (p = 0; p < vg_ptr->pv_cur; p++) {
2005 if (vg_ptr->pv[p]->pv_dev ==
2006 lv_ptr->lv_current_pe[le].dev)
2007 vg_ptr->pv[p]->pe_allocated++;
2010 } else {
2011 /* Get snapshot exception data and block list */
2012 if (lvbe != NULL) {
2013 lv_ptr->lv_snapshot_org =
2014 vg_ptr->lv[LV_BLK(lv_ptr->lv_snapshot_minor)];
2015 if (lv_ptr->lv_snapshot_org != NULL) {
2016 size = lv_ptr->lv_remap_end * sizeof(lv_block_exception_t);
2017 if ((lv_ptr->lv_block_exception = vmalloc(size)) == NULL) {
2018 printk(KERN_CRIT
2019 "%s -- lvm_do_lv_create: vmalloc error LV_BLOCK_EXCEPTION "
2020 "of %d byte at line %d\n",
2021 lvm_name, size, __LINE__);
2022 #ifdef DEBUG_KFREE
2023 printk(KERN_DEBUG "%s -- kfree %d\n", lvm_name, __LINE__);
2024 #endif
2025 kfree(lv_ptr);
2026 vg_ptr->lv[l] = NULL;
2027 return -ENOMEM;
2029 if (copy_from_user(lv_ptr->lv_block_exception, lvbe, size)) {
2030 vfree(lv_ptr->lv_block_exception);
2031 kfree(lv_ptr);
2032 vg[VG_CHR(minor)]->lv[l] = NULL;
2033 return -EFAULT;
2035 /* get pointer to original logical volume */
2036 lv_ptr = lv_ptr->lv_snapshot_org;
2038 lv_ptr->lv_snapshot_minor = 0;
2039 lv_ptr->lv_snapshot_org = lv_ptr;
2040 lv_ptr->lv_snapshot_prev = NULL;
2041 /* walk thrugh the snapshot list */
2042 while (lv_ptr->lv_snapshot_next != NULL)
2043 lv_ptr = lv_ptr->lv_snapshot_next;
2044 /* now lv_ptr points to the last existing snapshot in the chain */
2045 vg_ptr->lv[l]->lv_snapshot_prev = lv_ptr;
2046 /* our new one now back points to the previous last in the chain */
2047 lv_ptr = vg_ptr->lv[l];
2048 /* now lv_ptr points to our new last snapshot logical volume */
2049 lv_ptr->lv_snapshot_org = lv_ptr->lv_snapshot_prev->lv_snapshot_org;
2050 lv_ptr->lv_snapshot_next = NULL;
2051 lv_ptr->lv_current_pe = lv_ptr->lv_snapshot_org->lv_current_pe;
2052 lv_ptr->lv_allocated_le = lv_ptr->lv_snapshot_org->lv_allocated_le;
2053 lv_ptr->lv_current_le = lv_ptr->lv_snapshot_org->lv_current_le;
2054 lv_ptr->lv_size = lv_ptr->lv_snapshot_org->lv_size;
2055 lv_ptr->lv_stripes = lv_ptr->lv_snapshot_org->lv_stripes;
2056 lv_ptr->lv_stripesize = lv_ptr->lv_snapshot_org->lv_stripesize;
2058 int err = lvm_snapshot_alloc(lv_ptr);
2059 if (err)
2061 vfree(lv_ptr->lv_block_exception);
2062 kfree(lv_ptr);
2063 vg[VG_CHR(minor)]->lv[l] = NULL;
2064 return err;
2067 } else {
2068 vfree(lv_ptr->lv_block_exception);
2069 kfree(lv_ptr);
2070 vg_ptr->lv[l] = NULL;
2071 return -EFAULT;
2073 } else {
2074 kfree(vg_ptr->lv[l]);
2075 vg_ptr->lv[l] = NULL;
2076 return -EINVAL;
2078 } /* if ( vg[VG_CHR(minor)]->lv[l]->lv_access & LV_SNAPSHOT) */
2080 lv_ptr = vg_ptr->lv[l];
2081 lvm_gendisk.part[MINOR(lv_ptr->lv_dev)].start_sect = 0;
2082 lvm_gendisk.part[MINOR(lv_ptr->lv_dev)].nr_sects = lv_ptr->lv_size;
2083 lvm_size[MINOR(lv_ptr->lv_dev)] = lv_ptr->lv_size >> 1;
2084 vg_lv_map[MINOR(lv_ptr->lv_dev)].vg_number = vg_ptr->vg_number;
2085 vg_lv_map[MINOR(lv_ptr->lv_dev)].lv_number = lv_ptr->lv_number;
2086 read_ahead[MAJOR_NR] = lv_ptr->lv_read_ahead = LVM_CORRECT_READ_AHEAD(lv_ptr->lv_read_ahead);
2087 vg_ptr->lv_cur++;
2088 lv_ptr->lv_status = lv_status_save;
2090 strtok(lv->lv_name, "/"); /* /dev */
2092 while((lv_tmp = strtok(NULL, "/")) != NULL)
2093 lv_buf = lv_tmp;
2095 lv_devfs_handle[lv->lv_number] = devfs_register(
2096 vg_devfs_handle[vg_ptr->vg_number], lv_buf,
2097 DEVFS_FL_DEFAULT, LVM_BLK_MAJOR, lv->lv_number,
2098 S_IFBLK | S_IRUSR | S_IWUSR | S_IRGRP,
2099 &lvm_blk_dops, NULL);
2101 /* optionally add our new snapshot LV */
2102 if (lv_ptr->lv_access & LV_SNAPSHOT) {
2103 /* sync the original logical volume */
2104 fsync_dev(lv_ptr->lv_snapshot_org->lv_dev);
2105 /* put ourselve into the chain */
2106 lv_ptr->lv_snapshot_prev->lv_snapshot_next = lv_ptr;
2107 lv_ptr->lv_snapshot_org->lv_access |= LV_SNAPSHOT_ORG;
2109 return 0;
2110 } /* lvm_do_lv_create() */
2114 * character device support function logical volume remove
2116 static int lvm_do_lv_remove(int minor, char *lv_name, int l)
2118 uint le, p;
2119 vg_t *vg_ptr = vg[VG_CHR(minor)];
2120 lv_t *lv_ptr;
2122 if (l == -1) {
2123 for (l = 0; l < vg_ptr->lv_max; l++) {
2124 if (vg_ptr->lv[l] != NULL &&
2125 strcmp(vg_ptr->lv[l]->lv_name, lv_name) == 0) {
2126 break;
2130 if (l == vg_ptr->lv_max) return -ENXIO;
2132 lv_ptr = vg_ptr->lv[l];
2133 #ifdef LVM_TOTAL_RESET
2134 if (lv_ptr->lv_open > 0 && lvm_reset_spindown == 0)
2135 #else
2136 if (lv_ptr->lv_open > 0)
2137 #endif
2138 return -EBUSY;
2140 /* check for deletion of snapshot source while
2141 snapshot volume still exists */
2142 if ((lv_ptr->lv_access & LV_SNAPSHOT_ORG) &&
2143 lv_ptr->lv_snapshot_next != NULL)
2144 return -EPERM;
2146 lv_ptr->lv_status |= LV_SPINDOWN;
2148 /* sync the buffers */
2149 fsync_dev(lv_ptr->lv_dev);
2151 lv_ptr->lv_status &= ~LV_ACTIVE;
2153 /* invalidate the buffers */
2154 invalidate_buffers(lv_ptr->lv_dev);
2156 /* reset generic hd */
2157 lvm_gendisk.part[MINOR(lv_ptr->lv_dev)].start_sect = -1;
2158 lvm_gendisk.part[MINOR(lv_ptr->lv_dev)].nr_sects = 0;
2159 lvm_size[MINOR(lv_ptr->lv_dev)] = 0;
2161 /* reset VG/LV mapping */
2162 vg_lv_map[MINOR(lv_ptr->lv_dev)].vg_number = ABS_MAX_VG;
2163 vg_lv_map[MINOR(lv_ptr->lv_dev)].lv_number = -1;
2165 /* correct the PE count in PVs if this is no snapshot logical volume */
2166 if (!(lv_ptr->lv_access & LV_SNAPSHOT)) {
2167 /* only if this is no snapshot logical volume because
2168 we share the lv_current_pe[] structs with the
2169 original logical volume */
2170 for (le = 0; le < lv_ptr->lv_allocated_le; le++) {
2171 vg_ptr->pe_allocated--;
2172 for (p = 0; p < vg_ptr->pv_cur; p++) {
2173 if (vg_ptr->pv[p]->pv_dev ==
2174 lv_ptr->lv_current_pe[le].dev)
2175 vg_ptr->pv[p]->pe_allocated--;
2178 vfree(lv_ptr->lv_current_pe);
2179 /* LV_SNAPSHOT */
2180 } else {
2181 /* remove this snapshot logical volume from the chain */
2182 lv_ptr->lv_snapshot_prev->lv_snapshot_next = lv_ptr->lv_snapshot_next;
2183 if (lv_ptr->lv_snapshot_next != NULL) {
2184 lv_ptr->lv_snapshot_next->lv_snapshot_prev =
2185 lv_ptr->lv_snapshot_prev;
2187 /* no more snapshots? */
2188 if (lv_ptr->lv_snapshot_org->lv_snapshot_next == NULL)
2189 lv_ptr->lv_snapshot_org->lv_access &= ~LV_SNAPSHOT_ORG;
2190 lvm_snapshot_release(lv_ptr);
2193 devfs_unregister(lv_devfs_handle[lv_ptr->lv_number]);
2195 #ifdef DEBUG_KFREE
2196 printk(KERN_DEBUG "%s -- kfree %d\n", lvm_name, __LINE__);
2197 #endif
2198 kfree(lv_ptr);
2199 vg_ptr->lv[l] = NULL;
2200 vg_ptr->lv_cur--;
2201 return 0;
2202 } /* lvm_do_lv_remove() */
2206 * character device support function logical volume extend / reduce
2208 static int lvm_do_lv_extend_reduce(int minor, char *lv_name, lv_t *lv)
2210 int l, le, p, size, old_allocated_le;
2211 uint32_t end, lv_status_save;
2212 vg_t *vg_ptr = vg[VG_CHR(minor)];
2213 lv_t *lv_ptr;
2214 pe_t *pe;
2216 if ((pep = lv->lv_current_pe) == NULL) return -EINVAL;
2218 for (l = 0; l < vg_ptr->lv_max; l++) {
2219 if (vg_ptr->lv[l] != NULL &&
2220 strcmp(vg_ptr->lv[l]->lv_name, lv_name) == 0)
2221 break;
2223 if (l == vg_ptr->lv_max) return -ENXIO;
2224 lv_ptr = vg_ptr->lv[l];
2226 /* check for active snapshot */
2227 if (lv->lv_access & (LV_SNAPSHOT | LV_SNAPSHOT_ORG)) return -EPERM;
2229 if ((pe = vmalloc(size = lv->lv_current_le * sizeof(pe_t))) == NULL) {
2230 printk(KERN_CRIT
2231 "%s -- lvm_do_lv_extend_reduce: vmalloc error LV_CURRENT_PE "
2232 "of %d Byte at line %d\n",
2233 lvm_name, size, __LINE__);
2234 return -ENOMEM;
2236 /* get the PE structures from user space */
2237 if (copy_from_user(pe, pep, size)) {
2238 vfree(pe);
2239 return -EFAULT;
2242 #ifdef DEBUG
2243 printk(KERN_DEBUG
2244 "%s -- fsync_dev and "
2245 "invalidate_buffers for %s [%s] in %s\n",
2246 lvm_name, lv_ptr->lv_name,
2247 kdevname(lv_ptr->lv_dev),
2248 vg_ptr->vg_name);
2249 #endif
2251 lv_ptr->lv_status |= LV_SPINDOWN;
2252 fsync_dev(lv_ptr->lv_dev);
2253 lv_ptr->lv_status &= ~LV_ACTIVE;
2254 invalidate_buffers(lv_ptr->lv_dev);
2256 /* reduce allocation counters on PV(s) */
2257 for (le = 0; le < lv_ptr->lv_allocated_le; le++) {
2258 vg_ptr->pe_allocated--;
2259 for (p = 0; p < vg_ptr->pv_cur; p++) {
2260 if (vg_ptr->pv[p]->pv_dev ==
2261 lv_ptr->lv_current_pe[le].dev) {
2262 vg_ptr->pv[p]->pe_allocated--;
2263 break;
2269 /* save pointer to "old" lv/pe pointer array */
2270 pep1 = lv_ptr->lv_current_pe;
2271 end = lv_ptr->lv_current_le;
2273 /* save open counter */
2274 lv_open = lv_ptr->lv_open;
2276 /* save # of old allocated logical extents */
2277 old_allocated_le = lv_ptr->lv_allocated_le;
2279 /* copy preloaded LV */
2280 lv_status_save = lv->lv_status;
2281 lv->lv_status |= LV_SPINDOWN;
2282 lv->lv_status &= ~LV_ACTIVE;
2283 memcpy((char *) lv_ptr, (char *) lv, sizeof(lv_t));
2284 lv_ptr->lv_current_pe = pe;
2285 lv_ptr->lv_open = lv_open;
2287 /* save availiable i/o statistic data */
2288 /* linear logical volume */
2289 if (lv_ptr->lv_stripes < 2) {
2290 /* Check what last LE shall be used */
2291 if (end > lv_ptr->lv_current_le) end = lv_ptr->lv_current_le;
2292 for (le = 0; le < end; le++) {
2293 lv_ptr->lv_current_pe[le].reads = pep1[le].reads;
2294 lv_ptr->lv_current_pe[le].writes = pep1[le].writes;
2296 /* striped logical volume */
2297 } else {
2298 uint i, j, source, dest, end, old_stripe_size, new_stripe_size;
2300 old_stripe_size = old_allocated_le / lv_ptr->lv_stripes;
2301 new_stripe_size = lv_ptr->lv_allocated_le / lv_ptr->lv_stripes;
2302 end = old_stripe_size;
2303 if (end > new_stripe_size) end = new_stripe_size;
2304 for (i = source = dest = 0;
2305 i < lv_ptr->lv_stripes; i++) {
2306 for (j = 0; j < end; j++) {
2307 lv_ptr->lv_current_pe[dest + j].reads =
2308 pep1[source + j].reads;
2309 lv_ptr->lv_current_pe[dest + j].writes =
2310 pep1[source + j].writes;
2312 source += old_stripe_size;
2313 dest += new_stripe_size;
2316 vfree(pep1);
2317 pep1 = NULL;
2320 /* extend the PE count in PVs */
2321 for (le = 0; le < lv_ptr->lv_allocated_le; le++) {
2322 vg_ptr->pe_allocated++;
2323 for (p = 0; p < vg_ptr->pv_cur; p++) {
2324 if (vg_ptr->pv[p]->pv_dev ==
2325 vg_ptr->lv[l]->lv_current_pe[le].dev) {
2326 vg_ptr->pv[p]->pe_allocated++;
2327 break;
2332 lvm_gendisk.part[MINOR(lv_ptr->lv_dev)].start_sect = 0;
2333 lvm_gendisk.part[MINOR(lv_ptr->lv_dev)].nr_sects = lv_ptr->lv_size;
2334 lvm_size[MINOR(lv_ptr->lv_dev)] = lv_ptr->lv_size >> 1;
2335 /* vg_lv_map array doesn't have to be changed here */
2337 read_ahead[MAJOR_NR] = lv_ptr->lv_read_ahead = LVM_CORRECT_READ_AHEAD(lv_ptr->lv_read_ahead);
2338 lv_ptr->lv_status = lv_status_save;
2340 return 0;
2341 } /* lvm_do_lv_extend_reduce() */
2345 * character device support function logical volume status by name
2347 static int lvm_do_lv_status_byname(vg_t *vg_ptr, void *arg)
2349 uint l;
2350 ulong size;
2351 lv_t lv;
2352 lv_t *lv_ptr;
2353 lv_status_byname_req_t lv_status_byname_req;
2355 if (vg_ptr == NULL) return -ENXIO;
2356 if (copy_from_user(&lv_status_byname_req, arg,
2357 sizeof(lv_status_byname_req_t)) != 0)
2358 return -EFAULT;
2360 if (lv_status_byname_req.lv == NULL) return -EINVAL;
2361 if (copy_from_user(&lv, lv_status_byname_req.lv,
2362 sizeof(lv_t)) != 0)
2363 return -EFAULT;
2365 for (l = 0; l < vg_ptr->lv_max; l++) {
2366 lv_ptr = vg_ptr->lv[l];
2367 if (lv_ptr != NULL &&
2368 strcmp(lv_ptr->lv_name,
2369 lv_status_byname_req.lv_name) == 0) {
2370 if (copy_to_user(lv_status_byname_req.lv,
2371 lv_ptr,
2372 sizeof(lv_t)) != 0)
2373 return -EFAULT;
2375 if (lv.lv_current_pe != NULL) {
2376 size = lv_ptr->lv_allocated_le *
2377 sizeof(pe_t);
2378 if (copy_to_user(lv.lv_current_pe,
2379 lv_ptr->lv_current_pe,
2380 size) != 0)
2381 return -EFAULT;
2383 return 0;
2386 return -ENXIO;
2387 } /* lvm_do_lv_status_byname() */
2391 * character device support function logical volume status by index
2393 static int lvm_do_lv_status_byindex(vg_t *vg_ptr,void *arg)
2395 ulong size;
2396 lv_t lv;
2397 lv_t *lv_ptr;
2398 lv_status_byindex_req_t lv_status_byindex_req;
2400 if (vg_ptr == NULL) return -ENXIO;
2401 if (copy_from_user(&lv_status_byindex_req, arg,
2402 sizeof(lv_status_byindex_req)) != 0)
2403 return -EFAULT;
2405 if ((lvp = lv_status_byindex_req.lv) == NULL)
2406 return -EINVAL;
2407 if ( ( lv_ptr = vg_ptr->lv[lv_status_byindex_req.lv_index]) == NULL)
2408 return -ENXIO;
2410 if (copy_from_user(&lv, lvp, sizeof(lv_t)) != 0)
2411 return -EFAULT;
2413 if (copy_to_user(lvp, lv_ptr, sizeof(lv_t)) != 0)
2414 return -EFAULT;
2416 if (lv.lv_current_pe != NULL) {
2417 size = lv_ptr->lv_allocated_le * sizeof(pe_t);
2418 if (copy_to_user(lv.lv_current_pe,
2419 lv_ptr->lv_current_pe,
2420 size) != 0)
2421 return -EFAULT;
2423 return 0;
2424 } /* lvm_do_lv_status_byindex() */
2428 * character device support function physical volume change
2430 static int lvm_do_pv_change(vg_t *vg_ptr, void *arg)
2432 uint p;
2433 pv_t *pv_ptr;
2434 #ifdef LVM_GET_INODE
2435 struct inode *inode_sav;
2436 #endif
2438 if (vg_ptr == NULL) return -ENXIO;
2439 if (copy_from_user(&pv_change_req, arg,
2440 sizeof(pv_change_req)) != 0)
2441 return -EFAULT;
2443 for (p = 0; p < vg_ptr->pv_max; p++) {
2444 pv_ptr = vg_ptr->pv[p];
2445 if (pv_ptr != NULL &&
2446 strcmp(pv_ptr->pv_name,
2447 pv_change_req.pv_name) == 0) {
2448 #ifdef LVM_GET_INODE
2449 inode_sav = pv_ptr->inode;
2450 #endif
2451 if (copy_from_user(pv_ptr,
2452 pv_change_req.pv,
2453 sizeof(pv_t)) != 0)
2454 return -EFAULT;
2456 /* We don't need the PE list
2457 in kernel space as with LVs pe_t list */
2458 pv_ptr->pe = NULL;
2459 #ifdef LVM_GET_INODE
2460 pv_ptr->inode = inode_sav;
2461 #endif
2462 return 0;
2465 return -ENXIO;
2466 } /* lvm_do_pv_change() */
2469 * character device support function get physical volume status
2471 static int lvm_do_pv_status(vg_t *vg_ptr, void *arg)
2473 uint p;
2474 pv_t *pv_ptr;
2476 if (vg_ptr == NULL) return -ENXIO;
2477 if (copy_from_user(&pv_status_req, arg,
2478 sizeof(pv_status_req)) != 0)
2479 return -EFAULT;
2481 for (p = 0; p < vg_ptr->pv_max; p++) {
2482 pv_ptr = vg_ptr->pv[p];
2483 if (pv_ptr != NULL &&
2484 strcmp(pv_ptr->pv_name,
2485 pv_status_req.pv_name) == 0) {
2486 if (copy_to_user(pv_status_req.pv,
2487 pv_ptr,
2488 sizeof(pv_t)) != 0)
2489 return -EFAULT;
2490 return 0;
2493 return -ENXIO;
2494 } /* lvm_do_pv_status() */
2498 * support function initialize gendisk variables
2500 #ifdef __initfunc
2501 __initfunc(void lvm_geninit(struct gendisk *lvm_gdisk))
2502 #else
2503 void __init
2504 lvm_geninit(struct gendisk *lvm_gdisk)
2505 #endif
2507 int i = 0;
2509 #ifdef DEBUG_GENDISK
2510 printk(KERN_DEBUG "%s -- lvm_gendisk\n", lvm_name);
2511 #endif
2513 for (i = 0; i < MAX_LV; i++) {
2514 lvm_gendisk.part[i].start_sect = -1; /* avoid partition check */
2515 lvm_size[i] = lvm_gendisk.part[i].nr_sects = 0;
2516 lvm_blocksizes[i] = BLOCK_SIZE;
2519 blksize_size[MAJOR_NR] = lvm_blocksizes;
2520 blk_size[MAJOR_NR] = lvm_size;
2522 return;
2523 } /* lvm_gen_init() */
2526 #ifdef LVM_GET_INODE
2528 * support function to get an empty inode
2530 * Gets an empty inode to be inserted into the inode hash,
2531 * so that a physical volume can't be mounted.
2532 * This is analog to drivers/block/md.c
2534 * Is this the real thing?
2536 * No, it's bollocks. md.c tries to do a bit different thing that might
2537 * _somewhat_ work eons ago. Neither does any good these days. mount() couldn't
2538 * care less for icache (it cares only for ->s_root->d_count and if we want
2539 * loopback mounts even that will stop). BTW, with the form used here mount()
2540 * would have to scan the _whole_ icache to detect the attempt - how on the
2541 * Earth could it guess the i_ino of your dummy inode? Official line on the
2542 * exclusion between mount()/swapon()/open()/etc. is Just Don't Do It(tm).
2543 * If you can convince Linus that it's worth changing - fine, then you'll need
2544 * to do blkdev_get()/blkdev_put(). Until then...
2546 struct inode *lvm_get_inode(kdev_t dev)
2548 struct inode *inode_this = NULL;
2550 /* Lock the device by inserting a dummy inode. */
2551 inode_this = get_empty_inode();
2552 inode_this->i_dev = dev;
2553 insert_inode_hash(inode_this);
2554 return inode_this;
2559 * support function to clear an inode
2562 void lvm_clear_inode(struct inode *inode)
2564 #ifdef I_FREEING
2565 inode->i_state |= I_FREEING;
2566 #endif
2567 clear_inode(inode);
2568 return;
2570 #endif /* #ifdef LVM_GET_INODE */