Received: from mnm [127.0.0.1] by localhost with POP3 (fetchmail-5.9.0) for akpm@localhost (single-drop); Tue, 26 Aug 2003 18:11:32 -0700 (PDT) Received: from digeo-e2k04.digeo.com ([192.168.2.24]) by pao-ex01.pao.digeo.com with Microsoft SMTPSVC(5.0.2195.5329); Tue, 26 Aug 2003 18:07:20 -0700 Received: from digeo-nav01.digeo.com ([192.168.1.233]) by digeo-e2k04.digeo.com with Microsoft SMTPSVC(5.0.2195.5329); Tue, 26 Aug 2003 18:07:19 -0700 Received: from packet.digeo.com ([192.168.17.15]) by digeo-nav01.digeo.com (SAVSMTP 3.1.1.32) with SMTP id M2003082618094705354 for ; Tue, 26 Aug 2003 18:09:47 -0700 Received: from www.linux.org.uk (parcelfarce.linux.theplanet.co.uk [195.92.249.252]) by packet.digeo.com (8.12.8/8.12.8) with ESMTP id h7R16RGl017205 for ; Tue, 26 Aug 2003 18:06:29 -0700 (PDT) Received: from viro by www.linux.org.uk with local (Exim 4.22) id 19rolV-0002I4-WB for akpm@digeo.com; Wed, 27 Aug 2003 02:06:25 +0100 To: akpm@digeo.com Subject: [PATCH] large dev_t work - first series (12/12) Message-Id: From: viro@www.linux.org.uk Date: Wed, 27 Aug 2003 02:06:25 +0100 X-Scanned-By: MIMEDefang 2.30 (www . roaringpenguin . com / mimedefang) Return-Path: viro@www.linux.org.uk X-OriginalArrivalTime: 27 Aug 2003 01:07:19.0535 (UTC) FILETIME=[903BDFF0:01C36C37] X-Spam-Status: No, hits=-8.6 required=6.0 tests=BAYES_01,NO_REAL_NAME,PATCH_UNIFIED_DIFF autolearn=ham version=2.53 X-Spam-Level: X-Spam-Checker-Version: SpamAssassin 2.53 (1.174.2.15-2003-03-30-exp) added the exclusion between ADD_PARTITION/DELETE_PARTITION/open() (BLKPG ioctls didn't grab ->bd_sem when they should have). added bdev->bd_part; it is set at open() to point to the hd_struct of partition in question, reset on final close. blk_partition_remap() uses ->bd_part instead of the current mess ->bd_offset is gone, we use ->bd_part->start_sect instead added missing ->release() to hd_struct kobject, moved kfree() into it ->bd_part cotributes to refcount of hd_struct - we bump it when ->bd_part is set and drop when it's reset. diff -urN B4-imajor/drivers/block/genhd.c B4-bd_part/drivers/block/genhd.c --- B4-imajor/drivers/block/genhd.c Tue Aug 26 20:17:22 2003 +++ B4-bd_part/drivers/block/genhd.c Tue Aug 26 19:06:15 2003 @@ -576,13 +576,10 @@ void set_device_ro(struct block_device *bdev, int flag) { - struct gendisk *disk = bdev->bd_disk; - if (bdev->bd_contains != bdev) { - int part = bdev->bd_dev - MKDEV(disk->major, disk->first_minor); - struct hd_struct *p = disk->part[part-1]; - if (p) p->policy = flag; - } else - disk->policy = flag; + if (bdev->bd_contains != bdev) + bdev->bd_part->policy = flag; + else + bdev->bd_disk->policy = flag; } void set_disk_ro(struct gendisk *disk, int flag) @@ -595,17 +592,12 @@ int bdev_read_only(struct block_device *bdev) { - struct gendisk *disk; if (!bdev) return 0; - disk = bdev->bd_disk; - if (bdev->bd_contains != bdev) { - int part = bdev->bd_dev - MKDEV(disk->major, disk->first_minor); - struct hd_struct *p = disk->part[part-1]; - if (p) return p->policy; - return 0; - } else - return disk->policy; + else if (bdev->bd_contains != bdev) + return bdev->bd_part->policy; + else + return bdev->bd_disk->policy; } int invalidate_partition(struct gendisk *disk, int index) diff -urN B4-imajor/drivers/block/ioctl.c B4-bd_part/drivers/block/ioctl.c --- B4-imajor/drivers/block/ioctl.c Tue Aug 26 20:17:22 2003 +++ B4-bd_part/drivers/block/ioctl.c Tue Aug 26 19:06:15 2003 @@ -8,7 +8,6 @@ static int blkpg_ioctl(struct block_device *bdev, struct blkpg_ioctl_arg *arg) { struct block_device *bdevp; - int holder; struct gendisk *disk; struct blkpg_ioctl_arg a; struct blkpg_partition p; @@ -41,8 +40,11 @@ return -EINVAL; } /* partition number in use? */ - if (disk->part[part - 1]) + down(&bdev->bd_sem); + if (disk->part[part - 1]) { + up(&bdev->bd_sem); return -EBUSY; + } /* overlap? */ for (i = 0; i < disk->minors - 1; i++) { struct hd_struct *s = disk->part[i]; @@ -50,22 +52,26 @@ if (!s) continue; if (!(start+length <= s->start_sect || - start >= s->start_sect + s->nr_sects)) + start >= s->start_sect + s->nr_sects)) { + up(&bdev->bd_sem); return -EBUSY; + } } /* all seems OK */ add_partition(disk, part, start, length); + up(&bdev->bd_sem); return 0; case BLKPG_DEL_PARTITION: if (!disk->part[part-1]) return -ENXIO; if (disk->part[part - 1]->nr_sects == 0) return -ENXIO; - /* partition in use? Incomplete check for now. */ bdevp = bdget_disk(disk, part); if (!bdevp) return -ENOMEM; - if (bd_claim(bdevp, &holder) < 0) { + down(&bdevp->bd_sem); + if (bdevp->bd_openers) { + up(&bdevp->bd_sem); bdput(bdevp); return -EBUSY; } @@ -73,9 +79,12 @@ fsync_bdev(bdevp); invalidate_bdev(bdevp, 0); + down(&bdev->bd_sem); delete_partition(disk, part); - bd_release(bdevp); + up(&bdev->bd_sem); + up(&bdevp->bd_sem); bdput(bdevp); + return 0; default: return -EINVAL; diff -urN B4-imajor/drivers/block/ll_rw_blk.c B4-bd_part/drivers/block/ll_rw_blk.c --- B4-imajor/drivers/block/ll_rw_blk.c Tue Aug 26 20:17:22 2003 +++ B4-bd_part/drivers/block/ll_rw_blk.c Tue Aug 26 19:06:15 2003 @@ -2043,24 +2043,23 @@ static inline void blk_partition_remap(struct bio *bio) { struct block_device *bdev = bio->bi_bdev; - struct gendisk *disk = bdev->bd_disk; - struct hd_struct *p; - if (bdev == bdev->bd_contains) - return; - p = disk->part[bdev->bd_dev-MKDEV(disk->major,disk->first_minor)-1]; - switch (bio->bi_rw) { - case READ: - p->read_sectors += bio_sectors(bio); - p->reads++; - break; - case WRITE: - p->write_sectors += bio_sectors(bio); - p->writes++; - break; + if (bdev != bdev->bd_contains) { + struct hd_struct *p = bdev->bd_part; + + switch (bio->bi_rw) { + case READ: + p->read_sectors += bio_sectors(bio); + p->reads++; + break; + case WRITE: + p->write_sectors += bio_sectors(bio); + p->writes++; + break; + } + bio->bi_sector += p->start_sect; + bio->bi_bdev = bdev->bd_contains; } - bio->bi_sector += bdev->bd_offset; - bio->bi_bdev = bdev->bd_contains; } /** diff -urN B4-imajor/fs/block_dev.c B4-bd_part/fs/block_dev.c --- B4-imajor/fs/block_dev.c Tue Aug 26 20:17:22 2003 +++ B4-bd_part/fs/block_dev.c Tue Aug 26 19:06:15 2003 @@ -540,7 +540,6 @@ if (ret) goto out_first; } - bdev->bd_offset = 0; if (!bdev->bd_openers) { bd_set_size(bdev,(loff_t)get_capacity(disk)<<9); bdi = blk_get_backing_dev_info(bdev); @@ -572,7 +571,8 @@ ret = -ENXIO; goto out_first; } - bdev->bd_offset = p->start_sect; + kobject_get(&p->kobj); + bdev->bd_part = p; bd_set_size(bdev, (loff_t) p->nr_sects << 9); up(&whole->bd_sem); } @@ -693,6 +693,10 @@ put_disk(disk); module_put(owner); + if (bdev->bd_contains != bdev) { + kobject_put(&bdev->bd_part->kobj); + bdev->bd_part = NULL; + } bdev->bd_disk = NULL; bdev->bd_inode->i_data.backing_dev_info = &default_backing_dev_info; if (bdev != bdev->bd_contains) { diff -urN B4-imajor/fs/partitions/check.c B4-bd_part/fs/partitions/check.c --- B4-imajor/fs/partitions/check.c Tue Aug 26 20:17:22 2003 +++ B4-bd_part/fs/partitions/check.c Tue Aug 26 19:06:15 2003 @@ -267,7 +267,14 @@ extern struct subsystem block_subsys; +static void part_release(struct kobject *kobj) +{ + struct hd_struct * p = container_of(kobj,struct hd_struct,kobj); + kfree(p); +} + struct kobj_type ktype_part = { + .release = part_release, .default_attrs = default_attrs, .sysfs_ops = &part_sysfs_ops, }; @@ -279,13 +286,12 @@ return; if (!p->nr_sects) return; + disk->part[part-1] = NULL; p->start_sect = 0; p->nr_sects = 0; p->reads = p->writes = p->read_sectors = p->write_sectors = 0; devfs_remove("%s/part%d", disk->devfs_name, part); kobject_unregister(&p->kobj); - disk->part[part-1] = NULL; - kfree(p); } void add_partition(struct gendisk *disk, int part, sector_t start, sector_t len) @@ -300,7 +306,6 @@ p->start_sect = start; p->nr_sects = len; p->partno = part; - disk->part[part-1] = p; devfs_mk_bdev(MKDEV(disk->major, disk->first_minor + part), S_IFBLK|S_IRUSR|S_IWUSR, @@ -310,6 +315,7 @@ p->kobj.parent = &disk->kobj; p->kobj.ktype = &ktype_part; kobject_register(&p->kobj); + disk->part[part-1] = p; } static void disk_sysfs_symlinks(struct gendisk *disk) diff -urN B4-imajor/include/linux/fs.h B4-bd_part/include/linux/fs.h --- B4-imajor/include/linux/fs.h Tue Aug 26 20:17:22 2003 +++ B4-bd_part/include/linux/fs.h Tue Aug 26 19:06:15 2003 @@ -345,7 +345,7 @@ int bd_holders; struct block_device * bd_contains; unsigned bd_block_size; - sector_t bd_offset; + struct hd_struct * bd_part; unsigned bd_part_count; int bd_invalidated; struct gendisk * bd_disk; diff -urN B4-imajor/include/linux/genhd.h B4-bd_part/include/linux/genhd.h --- B4-imajor/include/linux/genhd.h Tue Aug 26 20:17:22 2003 +++ B4-bd_part/include/linux/genhd.h Tue Aug 26 19:06:15 2003 @@ -197,7 +197,7 @@ static inline sector_t get_start_sect(struct block_device *bdev) { - return bdev->bd_offset; + return bdev->bd_part->start_sect; } static inline sector_t get_capacity(struct gendisk *disk) {