diff options
author | Laurent Vivier <Laurent.Vivier@bull.net> | 2008-04-29 04:02:51 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-04-29 11:06:23 -0400 |
commit | d71a6d7332e5881a65249f4fb97b0db3c61dd5ec (patch) | |
tree | ff38d51dc1de5651e87ad33ec3a02648297237da /drivers/block | |
parent | 48cf6061b30205b29b306bf9bc22dd6f0b091461 (diff) |
NBD: add partition support
Permit the use of partitions with network block devices (NBD).
A new parameter is introduced to define how many partition we want to be able
to manage per network block device. This parameter is "max_part".
For instance, to manage 63 partitions / loop device, we will do:
[on the server side]
# nbd-server 1234 /dev/sdb
[on the client side]
# modprobe nbd max_part=63
# ls -l /dev/nbd*
brw-rw---- 1 root disk 43, 0 2008-03-25 11:14 /dev/nbd0
brw-rw---- 1 root disk 43, 64 2008-03-25 11:11 /dev/nbd1
brw-rw---- 1 root disk 43, 640 2008-03-25 11:11 /dev/nbd10
brw-rw---- 1 root disk 43, 704 2008-03-25 11:11 /dev/nbd11
brw-rw---- 1 root disk 43, 768 2008-03-25 11:11 /dev/nbd12
brw-rw---- 1 root disk 43, 832 2008-03-25 11:11 /dev/nbd13
brw-rw---- 1 root disk 43, 896 2008-03-25 11:11 /dev/nbd14
brw-rw---- 1 root disk 43, 960 2008-03-25 11:11 /dev/nbd15
brw-rw---- 1 root disk 43, 128 2008-03-25 11:11 /dev/nbd2
brw-rw---- 1 root disk 43, 192 2008-03-25 11:11 /dev/nbd3
brw-rw---- 1 root disk 43, 256 2008-03-25 11:11 /dev/nbd4
brw-rw---- 1 root disk 43, 320 2008-03-25 11:11 /dev/nbd5
brw-rw---- 1 root disk 43, 384 2008-03-25 11:11 /dev/nbd6
brw-rw---- 1 root disk 43, 448 2008-03-25 11:11 /dev/nbd7
brw-rw---- 1 root disk 43, 512 2008-03-25 11:11 /dev/nbd8
brw-rw---- 1 root disk 43, 576 2008-03-25 11:11 /dev/nbd9
# nbd-client localhost 1234 /dev/nbd0
Negotiation: ..size = 80418240KB
bs=1024, sz=80418240
-------NOTE, RFC: partition table is not automatically read.
The driver sets bdev->bd_invalidated to 1 to force the read of the partition
table of the device, but this is done only on an open of the device.
So we have to do a "touch /dev/nbdX" or something like that.
It can't be done from the nbd-client or nbd driver because at this
level we can't ask to read the partition table and to serve the request
at the same time (-> deadlock)
If someone has a better idea, I'm open to any suggestion.
-------NOTE, RFC
# fdisk -l /dev/nbd0
Disk /dev/nbd0: 82.3 GB, 82348277760 bytes
255 heads, 63 sectors/track, 10011 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes
Device Boot Start End Blocks Id System
/dev/nbd0p1 * 1 9965 80043831 83 Linux
/dev/nbd0p2 9966 10011 369495 5 Extended
/dev/nbd0p5 9966 10011 369463+ 82 Linux swap / Solaris
# ls -l /dev/nbd0*
brw-rw---- 1 root disk 43, 0 2008-03-25 11:16 /dev/nbd0
brw-rw---- 1 root disk 43, 1 2008-03-25 11:16 /dev/nbd0p1
brw-rw---- 1 root disk 43, 2 2008-03-25 11:16 /dev/nbd0p2
brw-rw---- 1 root disk 43, 5 2008-03-25 11:16 /dev/nbd0p5
# mount /dev/nbd0p1 /mnt
# ls /mnt
bin dev initrd lost+found opt sbin sys var
boot etc initrd.img media proc selinux tmp vmlinuz
cdrom home lib mnt root srv usr
# umount /mnt
# nbd-client -d /dev/nbd0
# ls -l /dev/nbd0*
brw-rw---- 1 root disk 43, 0 2008-03-25 11:16 /dev/nbd0
-------NOTE
On "nbd-client -d", we can do an iocl(BLKRRPART) to update partition table:
as the size of the device is 0, we don't have to serve the partition manager
request (-> no deadlock).
-------NOTE
Signed-off-by: Paul Clements <paul.clements@steeleye.com>
Cc: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/block')
-rw-r--r-- | drivers/block/nbd.c | 25 |
1 files changed, 21 insertions, 4 deletions
diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c index 8e33de6bea3..a3da198ca42 100644 --- a/drivers/block/nbd.c +++ b/drivers/block/nbd.c | |||
@@ -56,6 +56,7 @@ static unsigned int debugflags; | |||
56 | 56 | ||
57 | static unsigned int nbds_max = 16; | 57 | static unsigned int nbds_max = 16; |
58 | static struct nbd_device *nbd_dev; | 58 | static struct nbd_device *nbd_dev; |
59 | static int max_part; | ||
59 | 60 | ||
60 | /* | 61 | /* |
61 | * Use just one lock (or at most 1 per NIC). Two arguments for this: | 62 | * Use just one lock (or at most 1 per NIC). Two arguments for this: |
@@ -610,10 +611,13 @@ static int nbd_ioctl(struct inode *inode, struct file *file, | |||
610 | error = -EINVAL; | 611 | error = -EINVAL; |
611 | file = fget(arg); | 612 | file = fget(arg); |
612 | if (file) { | 613 | if (file) { |
614 | struct block_device *bdev = inode->i_bdev; | ||
613 | inode = file->f_path.dentry->d_inode; | 615 | inode = file->f_path.dentry->d_inode; |
614 | if (S_ISSOCK(inode->i_mode)) { | 616 | if (S_ISSOCK(inode->i_mode)) { |
615 | lo->file = file; | 617 | lo->file = file; |
616 | lo->sock = SOCKET_I(inode); | 618 | lo->sock = SOCKET_I(inode); |
619 | if (max_part > 0) | ||
620 | bdev->bd_invalidated = 1; | ||
617 | error = 0; | 621 | error = 0; |
618 | } else { | 622 | } else { |
619 | fput(file); | 623 | fput(file); |
@@ -663,6 +667,8 @@ static int nbd_ioctl(struct inode *inode, struct file *file, | |||
663 | lo->bytesize = 0; | 667 | lo->bytesize = 0; |
664 | inode->i_bdev->bd_inode->i_size = 0; | 668 | inode->i_bdev->bd_inode->i_size = 0; |
665 | set_capacity(lo->disk, 0); | 669 | set_capacity(lo->disk, 0); |
670 | if (max_part > 0) | ||
671 | ioctl_by_bdev(inode->i_bdev, BLKRRPART, 0); | ||
666 | return lo->harderror; | 672 | return lo->harderror; |
667 | case NBD_CLEAR_QUE: | 673 | case NBD_CLEAR_QUE: |
668 | /* | 674 | /* |
@@ -696,6 +702,7 @@ static int __init nbd_init(void) | |||
696 | { | 702 | { |
697 | int err = -ENOMEM; | 703 | int err = -ENOMEM; |
698 | int i; | 704 | int i; |
705 | int part_shift; | ||
699 | 706 | ||
700 | BUILD_BUG_ON(sizeof(struct nbd_request) != 28); | 707 | BUILD_BUG_ON(sizeof(struct nbd_request) != 28); |
701 | 708 | ||
@@ -703,8 +710,17 @@ static int __init nbd_init(void) | |||
703 | if (!nbd_dev) | 710 | if (!nbd_dev) |
704 | return -ENOMEM; | 711 | return -ENOMEM; |
705 | 712 | ||
713 | if (max_part < 0) { | ||
714 | printk(KERN_CRIT "nbd: max_part must be >= 0\n"); | ||
715 | return -EINVAL; | ||
716 | } | ||
717 | |||
718 | part_shift = 0; | ||
719 | if (max_part > 0) | ||
720 | part_shift = fls(max_part); | ||
721 | |||
706 | for (i = 0; i < nbds_max; i++) { | 722 | for (i = 0; i < nbds_max; i++) { |
707 | struct gendisk *disk = alloc_disk(1); | 723 | struct gendisk *disk = alloc_disk(1 << part_shift); |
708 | elevator_t *old_e; | 724 | elevator_t *old_e; |
709 | if (!disk) | 725 | if (!disk) |
710 | goto out; | 726 | goto out; |
@@ -748,10 +764,9 @@ static int __init nbd_init(void) | |||
748 | nbd_dev[i].blksize = 1024; | 764 | nbd_dev[i].blksize = 1024; |
749 | nbd_dev[i].bytesize = 0; | 765 | nbd_dev[i].bytesize = 0; |
750 | disk->major = NBD_MAJOR; | 766 | disk->major = NBD_MAJOR; |
751 | disk->first_minor = i; | 767 | disk->first_minor = i << part_shift; |
752 | disk->fops = &nbd_fops; | 768 | disk->fops = &nbd_fops; |
753 | disk->private_data = &nbd_dev[i]; | 769 | disk->private_data = &nbd_dev[i]; |
754 | disk->flags |= GENHD_FL_SUPPRESS_PARTITION_INFO; | ||
755 | sprintf(disk->disk_name, "nbd%d", i); | 770 | sprintf(disk->disk_name, "nbd%d", i); |
756 | set_capacity(disk, 0); | 771 | set_capacity(disk, 0); |
757 | add_disk(disk); | 772 | add_disk(disk); |
@@ -789,7 +804,9 @@ MODULE_DESCRIPTION("Network Block Device"); | |||
789 | MODULE_LICENSE("GPL"); | 804 | MODULE_LICENSE("GPL"); |
790 | 805 | ||
791 | module_param(nbds_max, int, 0444); | 806 | module_param(nbds_max, int, 0444); |
792 | MODULE_PARM_DESC(nbds_max, "How many network block devices to initialize."); | 807 | MODULE_PARM_DESC(nbds_max, "number of network block devices to initialize (default: 16)"); |
808 | module_param(max_part, int, 0444); | ||
809 | MODULE_PARM_DESC(max_part, "number of partitions per device (default: 0)"); | ||
793 | #ifndef NDEBUG | 810 | #ifndef NDEBUG |
794 | module_param(debugflags, int, 0644); | 811 | module_param(debugflags, int, 0644); |
795 | MODULE_PARM_DESC(debugflags, "flags for controlling debug output"); | 812 | MODULE_PARM_DESC(debugflags, "flags for controlling debug output"); |