[PATCH] switch nbd
[safe/jmp/linux-2.6] / drivers / block / nbd.c
index 8e33de6..d3a91ca 100644 (file)
@@ -56,6 +56,7 @@ static unsigned int debugflags;
 
 static unsigned int nbds_max = 16;
 static struct nbd_device *nbd_dev;
+static int max_part;
 
 /*
  * Use just one lock (or at most 1 per NIC). Two arguments for this:
@@ -338,7 +339,7 @@ static struct request *nbd_read_stat(struct nbd_device *lo)
        }
 
        req = nbd_find_request(lo, *(struct request **)reply.handle);
-       if (unlikely(IS_ERR(req))) {
+       if (IS_ERR(req)) {
                result = PTR_ERR(req);
                if (result != -ENOENT)
                        goto harderror;
@@ -390,7 +391,7 @@ static ssize_t pid_show(struct device *dev,
 }
 
 static struct device_attribute pid_attr = {
-       .attr = { .name = "pid", .mode = S_IRUGO, .owner = THIS_MODULE },
+       .attr = { .name = "pid", .mode = S_IRUGO},
        .show = pid_show,
 };
 
@@ -402,7 +403,7 @@ static int nbd_do_it(struct nbd_device *lo)
        BUG_ON(lo->magic != LO_MAGIC);
 
        lo->pid = current->pid;
-       ret = sysfs_create_file(&lo->disk->dev.kobj, &pid_attr.attr);
+       ret = sysfs_create_file(&disk_to_dev(lo->disk)->kobj, &pid_attr.attr);
        if (ret) {
                printk(KERN_ERR "nbd: sysfs_create_file failed!");
                return ret;
@@ -411,7 +412,7 @@ static int nbd_do_it(struct nbd_device *lo)
        while ((req = nbd_read_stat(lo)) != NULL)
                nbd_end_request(req);
 
-       sysfs_remove_file(&lo->disk->dev.kobj, &pid_attr.attr);
+       sysfs_remove_file(&disk_to_dev(lo->disk)->kobj, &pid_attr.attr);
        return 0;
 }
 
@@ -556,10 +557,11 @@ static void do_nbd_request(struct request_queue * q)
        }
 }
 
-static int nbd_ioctl(struct inode *inode, struct file *file,
+static int nbd_ioctl(struct block_device *bdev, fmode_t mode,
                     unsigned int cmd, unsigned long arg)
 {
-       struct nbd_device *lo = inode->i_bdev->bd_disk->private_data;
+       struct nbd_device *lo = bdev->bd_disk->private_data;
+       struct file *file;
        int error;
        struct request sreq ;
        struct task_struct *thread;
@@ -576,6 +578,7 @@ static int nbd_ioctl(struct inode *inode, struct file *file,
        switch (cmd) {
        case NBD_DISCONNECT:
                printk(KERN_INFO "%s: NBD_DISCONNECT\n", lo->disk->disk_name);
+               blk_rq_init(NULL, &sreq);
                sreq.cmd_type = REQ_TYPE_SPECIAL;
                nbd_cmd(&sreq) = NBD_CMD_DISC;
                /*
@@ -610,10 +613,12 @@ static int nbd_ioctl(struct inode *inode, struct file *file,
                error = -EINVAL;
                file = fget(arg);
                if (file) {
-                       inode = file->f_path.dentry->d_inode;
+                       struct inode *inode = file->f_path.dentry->d_inode;
                        if (S_ISSOCK(inode->i_mode)) {
                                lo->file = file;
                                lo->sock = SOCKET_I(inode);
+                               if (max_part > 0)
+                                       bdev->bd_invalidated = 1;
                                error = 0;
                        } else {
                                fput(file);
@@ -623,14 +628,14 @@ static int nbd_ioctl(struct inode *inode, struct file *file,
        case NBD_SET_BLKSIZE:
                lo->blksize = arg;
                lo->bytesize &= ~(lo->blksize-1);
-               inode->i_bdev->bd_inode->i_size = lo->bytesize;
-               set_blocksize(inode->i_bdev, lo->blksize);
+               bdev->bd_inode->i_size = lo->bytesize;
+               set_blocksize(bdev, lo->blksize);
                set_capacity(lo->disk, lo->bytesize >> 9);
                return 0;
        case NBD_SET_SIZE:
                lo->bytesize = arg & ~(lo->blksize-1);
-               inode->i_bdev->bd_inode->i_size = lo->bytesize;
-               set_blocksize(inode->i_bdev, lo->blksize);
+               bdev->bd_inode->i_size = lo->bytesize;
+               set_blocksize(bdev, lo->blksize);
                set_capacity(lo->disk, lo->bytesize >> 9);
                return 0;
        case NBD_SET_TIMEOUT:
@@ -638,8 +643,8 @@ static int nbd_ioctl(struct inode *inode, struct file *file,
                return 0;
        case NBD_SET_SIZE_BLOCKS:
                lo->bytesize = ((u64) arg) * lo->blksize;
-               inode->i_bdev->bd_inode->i_size = lo->bytesize;
-               set_blocksize(inode->i_bdev, lo->blksize);
+               bdev->bd_inode->i_size = lo->bytesize;
+               set_blocksize(bdev, lo->blksize);
                set_capacity(lo->disk, lo->bytesize >> 9);
                return 0;
        case NBD_DO_IT:
@@ -661,8 +666,10 @@ static int nbd_ioctl(struct inode *inode, struct file *file,
                if (file)
                        fput(file);
                lo->bytesize = 0;
-               inode->i_bdev->bd_inode->i_size = 0;
+               bdev->bd_inode->i_size = 0;
                set_capacity(lo->disk, 0);
+               if (max_part > 0)
+                       ioctl_by_bdev(bdev, BLKRRPART, 0);
                return lo->harderror;
        case NBD_CLEAR_QUE:
                /*
@@ -673,7 +680,7 @@ static int nbd_ioctl(struct inode *inode, struct file *file,
                return 0;
        case NBD_PRINT_DEBUG:
                printk(KERN_INFO "%s: next = %p, prev = %p, head = %p\n",
-                       inode->i_bdev->bd_disk->disk_name,
+                       bdev->bd_disk->disk_name,
                        lo->queue_head.next, lo->queue_head.prev,
                        &lo->queue_head);
                return 0;
@@ -684,7 +691,7 @@ static int nbd_ioctl(struct inode *inode, struct file *file,
 static struct block_device_operations nbd_fops =
 {
        .owner =        THIS_MODULE,
-       .ioctl =        nbd_ioctl,
+       .locked_ioctl = nbd_ioctl,
 };
 
 /*
@@ -696,15 +703,25 @@ static int __init nbd_init(void)
 {
        int err = -ENOMEM;
        int i;
+       int part_shift;
 
        BUILD_BUG_ON(sizeof(struct nbd_request) != 28);
 
+       if (max_part < 0) {
+               printk(KERN_CRIT "nbd: max_part must be >= 0\n");
+               return -EINVAL;
+       }
+
        nbd_dev = kcalloc(nbds_max, sizeof(*nbd_dev), GFP_KERNEL);
        if (!nbd_dev)
                return -ENOMEM;
 
+       part_shift = 0;
+       if (max_part > 0)
+               part_shift = fls(max_part);
+
        for (i = 0; i < nbds_max; i++) {
-               struct gendisk *disk = alloc_disk(1);
+               struct gendisk *disk = alloc_disk(1 << part_shift);
                elevator_t *old_e;
                if (!disk)
                        goto out;
@@ -748,10 +765,9 @@ static int __init nbd_init(void)
                nbd_dev[i].blksize = 1024;
                nbd_dev[i].bytesize = 0;
                disk->major = NBD_MAJOR;
-               disk->first_minor = i;
+               disk->first_minor = i << part_shift;
                disk->fops = &nbd_fops;
                disk->private_data = &nbd_dev[i];
-               disk->flags |= GENHD_FL_SUPPRESS_PARTITION_INFO;
                sprintf(disk->disk_name, "nbd%d", i);
                set_capacity(disk, 0);
                add_disk(disk);
@@ -763,6 +779,7 @@ out:
                blk_cleanup_queue(nbd_dev[i].disk->queue);
                put_disk(nbd_dev[i].disk);
        }
+       kfree(nbd_dev);
        return err;
 }
 
@@ -779,6 +796,7 @@ static void __exit nbd_cleanup(void)
                }
        }
        unregister_blkdev(NBD_MAJOR, "nbd");
+       kfree(nbd_dev);
        printk(KERN_INFO "nbd: unregistered device at major %d\n", NBD_MAJOR);
 }
 
@@ -789,7 +807,9 @@ MODULE_DESCRIPTION("Network Block Device");
 MODULE_LICENSE("GPL");
 
 module_param(nbds_max, int, 0444);
-MODULE_PARM_DESC(nbds_max, "How many network block devices to initialize.");
+MODULE_PARM_DESC(nbds_max, "number of network block devices to initialize (default: 16)");
+module_param(max_part, int, 0444);
+MODULE_PARM_DESC(max_part, "number of partitions per device (default: 0)");
 #ifndef NDEBUG
 module_param(debugflags, int, 0644);
 MODULE_PARM_DESC(debugflags, "flags for controlling debug output");