Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Laurent Vivier and committed by
Linus Torvalds
d71a6d73 48cf6061

+21 -4
+21 -4
drivers/block/nbd.c
··· 56 56 57 57 static unsigned int nbds_max = 16; 58 58 static struct nbd_device *nbd_dev; 59 + static int max_part; 59 60 60 61 /* 61 62 * Use just one lock (or at most 1 per NIC). Two arguments for this: ··· 611 610 error = -EINVAL; 612 611 file = fget(arg); 613 612 if (file) { 613 + struct block_device *bdev = inode->i_bdev; 614 614 inode = file->f_path.dentry->d_inode; 615 615 if (S_ISSOCK(inode->i_mode)) { 616 616 lo->file = file; 617 617 lo->sock = SOCKET_I(inode); 618 + if (max_part > 0) 619 + bdev->bd_invalidated = 1; 618 620 error = 0; 619 621 } else { 620 622 fput(file); ··· 667 663 lo->bytesize = 0; 668 664 inode->i_bdev->bd_inode->i_size = 0; 669 665 set_capacity(lo->disk, 0); 666 + if (max_part > 0) 667 + ioctl_by_bdev(inode->i_bdev, BLKRRPART, 0); 670 668 return lo->harderror; 671 669 case NBD_CLEAR_QUE: 672 670 /* ··· 702 696 { 703 697 int err = -ENOMEM; 704 698 int i; 699 + int part_shift; 705 700 706 701 BUILD_BUG_ON(sizeof(struct nbd_request) != 28); 707 702 ··· 710 703 if (!nbd_dev) 711 704 return -ENOMEM; 712 705 706 + if (max_part < 0) { 707 + printk(KERN_CRIT "nbd: max_part must be >= 0\n"); 708 + return -EINVAL; 709 + } 710 + 711 + part_shift = 0; 712 + if (max_part > 0) 713 + part_shift = fls(max_part); 714 + 713 715 for (i = 0; i < nbds_max; i++) { 714 - struct gendisk *disk = alloc_disk(1); 716 + struct gendisk *disk = alloc_disk(1 << part_shift); 715 717 elevator_t *old_e; 716 718 if (!disk) 717 719 goto out; ··· 764 748 nbd_dev[i].blksize = 1024; 765 749 nbd_dev[i].bytesize = 0; 766 750 disk->major = NBD_MAJOR; 767 - disk->first_minor = i; 751 + disk->first_minor = i << part_shift; 768 752 disk->fops = &nbd_fops; 769 753 disk->private_data = &nbd_dev[i]; 770 - disk->flags |= GENHD_FL_SUPPRESS_PARTITION_INFO; 771 754 sprintf(disk->disk_name, "nbd%d", i); 772 755 set_capacity(disk, 0); 773 756 add_disk(disk); ··· 804 789 MODULE_LICENSE("GPL"); 805 790 806 791 module_param(nbds_max, int, 0444); 807 - MODULE_PARM_DESC(nbds_max, "How many network block devices to initialize."); 792 + MODULE_PARM_DESC(nbds_max, "number of network block devices to initialize (default: 16)"); 793 + module_param(max_part, int, 0444); 794 + MODULE_PARM_DESC(max_part, "number of partitions per device (default: 0)"); 808 795 #ifndef NDEBUG 809 796 module_param(debugflags, int, 0644); 810 797 MODULE_PARM_DESC(debugflags, "flags for controlling debug output");