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-2005 by Herbert Pötzl.
10 * Redistribution of this file is permitted under the
11 * GNU General Public License.
15 #include <linux/config.h>
16 #include <linux/module.h>
17 #include <linux/moduleparam.h>
18 #include <linux/file.h>
19 #include <linux/major.h>
20 #include <linux/blkdev.h>
21 #include <linux/devfs_fs_kernel.h>
23 #include <linux/vroot.h>
26 static int max_vroot = 8;
28 static struct vroot_device *vroot_dev;
29 static struct gendisk **disks;
32 static int vroot_set_dev(
33 struct vroot_device *vr,
35 struct block_device *bdev,
38 struct block_device *real_bdev;
44 if (vr->vr_state != Vr_unbound)
53 inode = file->f_dentry->d_inode;
56 if (S_ISBLK(inode->i_mode)) {
57 real_bdev = inode->i_bdev;
58 vr->vr_device = real_bdev;
59 __iget(real_bdev->bd_inode);
63 printk(KERN_INFO "vroot[%d]_set_dev: dev=%p[%d,%d]\n",
64 vr->vr_number, real_bdev,
65 imajor(real_bdev->bd_inode), iminor(real_bdev->bd_inode));
67 vr->vr_state = Vr_bound;
76 static int vroot_clr_dev(
77 struct vroot_device *vr,
79 struct block_device *bdev)
81 struct block_device *real_bdev;
83 if (vr->vr_state != Vr_bound)
85 if (vr->vr_refcnt > 1) /* we needed one fd for the ioctl */
88 real_bdev = vr->vr_device;
90 printk(KERN_INFO "vroot[%d]_clr_dev: dev=%p[%d,%d]\n",
91 vr->vr_number, real_bdev,
92 imajor(real_bdev->bd_inode), iminor(real_bdev->bd_inode));
95 vr->vr_state = Vr_unbound;
101 static int vr_ioctl(struct inode * inode, struct file * file,
102 unsigned int cmd, unsigned long arg)
104 struct vroot_device *vr = inode->i_bdev->bd_disk->private_data;
107 down(&vr->vr_ctl_mutex);
110 err = vroot_set_dev(vr, file, inode->i_bdev, arg);
113 err = vroot_clr_dev(vr, file, inode->i_bdev);
119 up(&vr->vr_ctl_mutex);
123 static int vr_open(struct inode *inode, struct file *file)
125 struct vroot_device *vr = inode->i_bdev->bd_disk->private_data;
127 down(&vr->vr_ctl_mutex);
129 up(&vr->vr_ctl_mutex);
133 static int vr_release(struct inode *inode, struct file *file)
135 struct vroot_device *vr = inode->i_bdev->bd_disk->private_data;
137 down(&vr->vr_ctl_mutex);
139 up(&vr->vr_ctl_mutex);
143 static struct block_device_operations vr_fops = {
144 .owner = THIS_MODULE,
146 .release = vr_release,
150 struct block_device *vroot_get_real_bdev(struct block_device *bdev)
152 struct inode *inode = bdev->bd_inode;
153 struct vroot_device *vr;
154 struct block_device *real_bdev;
155 int minor = iminor(inode);
157 vr = &vroot_dev[minor];
158 real_bdev = vr->vr_device;
160 printk(KERN_INFO "vroot[%d]_get_real_bdev: dev=%p[%p,%d,%d]\n",
161 vr->vr_number, real_bdev, real_bdev->bd_inode,
162 imajor(real_bdev->bd_inode), iminor(real_bdev->bd_inode));
164 if (vr->vr_state != Vr_bound)
165 return ERR_PTR(-ENXIO);
167 __iget(real_bdev->bd_inode);
172 * And now the modules code and kernel interface.
175 module_param(max_vroot, int, 0);
177 MODULE_PARM_DESC(max_vroot, "Maximum number of vroot devices (1-256)");
178 MODULE_LICENSE("GPL");
179 MODULE_ALIAS_BLOCKDEV_MAJOR(VROOT_MAJOR);
181 MODULE_AUTHOR ("Herbert Pötzl");
182 MODULE_DESCRIPTION ("Virtual Root Device Mapper");
185 int __init vroot_init(void)
189 if (max_vroot < 1 || max_vroot > 256) {
190 max_vroot = MAX_VROOT_DEFAULT;
191 printk(KERN_WARNING "vroot: invalid max_vroot "
192 "(must be between 1 and 256), "
193 "using default (%d)\n", max_vroot);
196 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 devfs_mk_dir("vroot");
216 for (i = 0; i < max_vroot; i++) {
217 struct vroot_device *vr = &vroot_dev[i];
218 struct gendisk *disk = disks[i];
220 memset(vr, 0, sizeof(*vr));
221 init_MUTEX(&vr->vr_ctl_mutex);
223 disk->major = VROOT_MAJOR;
224 disk->first_minor = i;
225 disk->fops = &vr_fops;
226 sprintf(disk->disk_name, "vroot%d", i);
227 sprintf(disk->devfs_name, "vroot/%d", i);
228 disk->private_data = vr;
231 for (i = 0; i < max_vroot; i++)
233 printk(KERN_INFO "vroot: loaded (max %d devices)\n", max_vroot);
243 unregister_blkdev(VROOT_MAJOR, "vroot");
244 printk(KERN_ERR "vroot: ran out of memory\n");
248 void vroot_exit(void)
252 for (i = 0; i < max_vroot; i++) {
253 del_gendisk(disks[i]);
256 devfs_remove("vroot");
257 if (unregister_blkdev(VROOT_MAJOR, "vroot"))
258 printk(KERN_WARNING "vroot: cannot unregister blkdev\n");
264 module_init(vroot_init);
265 module_exit(vroot_exit);