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/module.h>
16 #include <linux/moduleparam.h>
17 #include <linux/file.h>
18 #include <linux/major.h>
19 #include <linux/blkdev.h>
20 #include <linux/devfs_fs_kernel.h>
22 #include <linux/vroot.h>
23 #include <linux/vserver/debug.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 vxdprintk(VXD_CBIT(misc, 0),
64 "vroot[%d]_set_dev: dev=" VXF_DEV,
65 vr->vr_number, VXD_DEV(real_bdev));
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 vxdprintk(VXD_CBIT(misc, 0),
91 "vroot[%d]_clr_dev: dev=" VXF_DEV,
92 vr->vr_number, VXD_DEV(real_bdev));
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 vxdprintk(VXD_CBIT(misc, 0),
161 "vroot[%d]_get_real_bdev: dev=" VXF_DEV,
162 vr->vr_number, VXD_DEV(real_bdev));
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"))
200 vroot_dev = kmalloc(max_vroot * sizeof(struct vroot_device), GFP_KERNEL);
203 memset(vroot_dev, 0, max_vroot * sizeof(struct vroot_device));
205 disks = kmalloc(max_vroot * sizeof(struct gendisk *), GFP_KERNEL);
209 for (i = 0; i < max_vroot; i++) {
210 disks[i] = alloc_disk(1);
215 devfs_mk_dir("vroot");
217 for (i = 0; i < max_vroot; i++) {
218 struct vroot_device *vr = &vroot_dev[i];
219 struct gendisk *disk = disks[i];
221 memset(vr, 0, sizeof(*vr));
222 init_MUTEX(&vr->vr_ctl_mutex);
224 disk->major = VROOT_MAJOR;
225 disk->first_minor = i;
226 disk->fops = &vr_fops;
227 sprintf(disk->disk_name, "vroot%d", i);
228 sprintf(disk->devfs_name, "vroot/%d", i);
229 disk->private_data = vr;
232 err = register_vroot_grb(&__vroot_get_real_bdev);
236 for (i = 0; i < max_vroot; i++)
238 printk(KERN_INFO "vroot: loaded (max %d devices)\n", max_vroot);
242 devfs_remove("vroot");
250 unregister_blkdev(VROOT_MAJOR, "vroot");
251 printk(KERN_ERR "vroot: ran out of memory\n");
255 void vroot_exit(void)
259 if (unregister_vroot_grb(&__vroot_get_real_bdev))
260 printk(KERN_WARNING "vroot: cannot unregister grb\n");
262 for (i = 0; i < max_vroot; i++) {
263 del_gendisk(disks[i]);
266 devfs_remove("vroot");
267 if (unregister_blkdev(VROOT_MAJOR, "vroot"))
268 printk(KERN_WARNING "vroot: cannot unregister blkdev\n");
274 module_init(vroot_init);
275 module_exit(vroot_exit);
279 static int __init max_vroot_setup(char *str)
281 max_vroot = simple_strtol(str, NULL, 0);
285 __setup("max_vroot=", max_vroot_setup);