2 * linux/drivers/block/vroot.c
4 * written by Herbert Pötzl, 9/11/2002
5 * ported to 2.6.10 by Herbert Pötzl, 30/12/2004
7 * based on the loop.c code by Theodore Ts'o.
9 * Copyright (C) 2002-2007 by Herbert Pötzl.
10 * Redistribution of this file is permitted under the
11 * GNU General Public License.
15 #include <linux/module.h>
16 #include <linux/moduleparam.h>
17 #include <linux/file.h>
18 #include <linux/major.h>
19 #include <linux/blkdev.h>
21 #include <linux/vroot.h>
22 #include <linux/vs_context.h>
25 static int max_vroot = 8;
27 static struct vroot_device *vroot_dev;
28 static struct gendisk **disks;
31 static int vroot_set_dev(
32 struct vroot_device *vr,
34 struct block_device *bdev,
37 struct block_device *real_bdev;
43 if (vr->vr_state != Vr_unbound)
52 inode = file->f_dentry->d_inode;
55 if (S_ISBLK(inode->i_mode)) {
56 real_bdev = inode->i_bdev;
57 vr->vr_device = real_bdev;
58 __iget(real_bdev->bd_inode);
62 vxdprintk(VXD_CBIT(misc, 0),
63 "vroot[%d]_set_dev: dev=" VXF_DEV,
64 vr->vr_number, VXD_DEV(real_bdev));
66 vr->vr_state = Vr_bound;
75 static int vroot_clr_dev(
76 struct vroot_device *vr,
78 struct block_device *bdev)
80 struct block_device *real_bdev;
82 if (vr->vr_state != Vr_bound)
84 if (vr->vr_refcnt > 1) /* we needed one fd for the ioctl */
87 real_bdev = vr->vr_device;
89 vxdprintk(VXD_CBIT(misc, 0),
90 "vroot[%d]_clr_dev: dev=" VXF_DEV,
91 vr->vr_number, VXD_DEV(real_bdev));
94 vr->vr_state = Vr_unbound;
100 static int vr_ioctl(struct inode * inode, struct file * file,
101 unsigned int cmd, unsigned long arg)
103 struct vroot_device *vr = inode->i_bdev->bd_disk->private_data;
106 down(&vr->vr_ctl_mutex);
109 err = vroot_set_dev(vr, file, inode->i_bdev, arg);
112 err = vroot_clr_dev(vr, file, inode->i_bdev);
118 up(&vr->vr_ctl_mutex);
122 static int vr_open(struct inode *inode, struct file *file)
124 struct vroot_device *vr = inode->i_bdev->bd_disk->private_data;
126 down(&vr->vr_ctl_mutex);
128 up(&vr->vr_ctl_mutex);
132 static int vr_release(struct inode *inode, struct file *file)
134 struct vroot_device *vr = inode->i_bdev->bd_disk->private_data;
136 down(&vr->vr_ctl_mutex);
138 up(&vr->vr_ctl_mutex);
142 static struct block_device_operations vr_fops = {
143 .owner = THIS_MODULE,
145 .release = vr_release,
149 struct block_device *__vroot_get_real_bdev(struct block_device *bdev)
151 struct inode *inode = bdev->bd_inode;
152 struct vroot_device *vr;
153 struct block_device *real_bdev;
154 int minor = iminor(inode);
156 vr = &vroot_dev[minor];
157 real_bdev = vr->vr_device;
159 vxdprintk(VXD_CBIT(misc, 0),
160 "vroot[%d]_get_real_bdev: dev=" VXF_DEV,
161 vr->vr_number, VXD_DEV(real_bdev));
163 if (vr->vr_state != Vr_bound)
164 return ERR_PTR(-ENXIO);
166 __iget(real_bdev->bd_inode);
171 * And now the modules code and kernel interface.
174 module_param(max_vroot, int, 0);
176 MODULE_PARM_DESC(max_vroot, "Maximum number of vroot devices (1-256)");
177 MODULE_LICENSE("GPL");
178 MODULE_ALIAS_BLOCKDEV_MAJOR(VROOT_MAJOR);
180 MODULE_AUTHOR ("Herbert Pötzl");
181 MODULE_DESCRIPTION ("Virtual Root Device Mapper");
184 int __init vroot_init(void)
188 if (max_vroot < 1 || max_vroot > 256) {
189 max_vroot = MAX_VROOT_DEFAULT;
190 printk(KERN_WARNING "vroot: invalid max_vroot "
191 "(must be between 1 and 256), "
192 "using default (%d)\n", max_vroot);
195 if (register_blkdev(VROOT_MAJOR, "vroot"))
199 vroot_dev = kmalloc(max_vroot * sizeof(struct vroot_device), GFP_KERNEL);
202 memset(vroot_dev, 0, max_vroot * sizeof(struct vroot_device));
204 disks = kmalloc(max_vroot * sizeof(struct gendisk *), GFP_KERNEL);
208 for (i = 0; i < max_vroot; i++) {
209 disks[i] = alloc_disk(1);
214 for (i = 0; i < max_vroot; i++) {
215 struct vroot_device *vr = &vroot_dev[i];
216 struct gendisk *disk = disks[i];
218 memset(vr, 0, sizeof(*vr));
219 init_MUTEX(&vr->vr_ctl_mutex);
221 disk->major = VROOT_MAJOR;
222 disk->first_minor = i;
223 disk->fops = &vr_fops;
224 sprintf(disk->disk_name, "vroot%d", i);
225 disk->private_data = vr;
228 err = register_vroot_grb(&__vroot_get_real_bdev);
232 for (i = 0; i < max_vroot; i++)
234 printk(KERN_INFO "vroot: loaded (max %d devices)\n", max_vroot);
244 unregister_blkdev(VROOT_MAJOR, "vroot");
245 printk(KERN_ERR "vroot: ran out of memory\n");
249 void vroot_exit(void)
253 if (unregister_vroot_grb(&__vroot_get_real_bdev))
254 printk(KERN_WARNING "vroot: cannot unregister grb\n");
256 for (i = 0; i < max_vroot; i++) {
257 del_gendisk(disks[i]);
260 if (unregister_blkdev(VROOT_MAJOR, "vroot"))
261 printk(KERN_WARNING "vroot: cannot unregister blkdev\n");
267 module_init(vroot_init);
268 module_exit(vroot_exit);
272 static int __init max_vroot_setup(char *str)
274 max_vroot = simple_strtol(str, NULL, 0);
278 __setup("max_vroot=", max_vroot_setup);