[PARTITION]: Add whole_disk attribute.
authorFabio Massimo Di Nitto <fabbione@ubuntu.com>
Sun, 11 Feb 2007 07:50:00 +0000 (23:50 -0800)
committerDavid S. Miller <davem@davemloft.net>
Sun, 11 Feb 2007 07:50:00 +0000 (23:50 -0800)
Some partitioning systems create special partitions that
span the entire disk.  One example are Sun partitions, and
this whole-disk partition exists to tell the firmware the
extent of the entire device so it can load the boot block
and do other things.

Such partitions should not be treated as normal partitions,
because all the other partitions overlap this whole-disk one.
So we'd see multiple instances of the same UUID etc. which
we do not want.  udev and friends can thus search for this
'whole_disk' attribute and use it to decide to ignore the
partition.

Signed-off-by: Fabio Massimo Di Nitto <fabbione@ubuntu.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
block/ioctl.c
fs/partitions/check.c
fs/partitions/msdos.c
fs/partitions/sgi.c
fs/partitions/sun.c
include/linux/genhd.h

index f6962b64660ea67c6092c6303d7d52cd69bffbeb..e3f5eb9882cf4dfb403f6ca64f7262180b9db0fa 100644 (file)
@@ -61,7 +61,7 @@ static int blkpg_ioctl(struct block_device *bdev, struct blkpg_ioctl_arg __user
                                }
                        }
                        /* all seems OK */
-                       add_partition(disk, part, start, length);
+                       add_partition(disk, part, start, length, ADDPART_FLAG_NONE);
                        mutex_unlock(&bdev->bd_mutex);
                        return 0;
                case BLKPG_DEL_PARTITION:
index 3d73d94d93a7dd9321cdfe5d9750fcf25a836df5..ac32a2e8540c4fb2ac34c1c27286f1a0d624fbd1 100644 (file)
@@ -365,7 +365,7 @@ void delete_partition(struct gendisk *disk, int part)
        kobject_put(&p->kobj);
 }
 
-void add_partition(struct gendisk *disk, int part, sector_t start, sector_t len)
+void add_partition(struct gendisk *disk, int part, sector_t start, sector_t len, int flags)
 {
        struct hd_struct *p;
 
@@ -390,6 +390,15 @@ void add_partition(struct gendisk *disk, int part, sector_t start, sector_t len)
        if (!disk->part_uevent_suppress)
                kobject_uevent(&p->kobj, KOBJ_ADD);
        sysfs_create_link(&p->kobj, &block_subsys.kset.kobj, "subsystem");
+       if (flags & ADDPART_FLAG_WHOLEDISK) {
+               static struct attribute addpartattr = {
+                       .name = "whole_disk",
+                       .mode = S_IRUSR | S_IRGRP | S_IROTH,
+                       .owner = THIS_MODULE,
+               };
+
+               sysfs_create_file(&p->kobj, &addpartattr);
+       }
        partition_sysfs_add_subdir(p);
        disk->part[part-1] = p;
 }
@@ -543,9 +552,9 @@ int rescan_partitions(struct gendisk *disk, struct block_device *bdev)
                        printk(" %s: p%d exceeds device capacity\n",
                                disk->disk_name, p);
                }
-               add_partition(disk, p, from, size);
+               add_partition(disk, p, from, size, state->parts[p].flags);
 #ifdef CONFIG_BLK_DEV_MD
-               if (state->parts[p].flags)
+               if (state->parts[p].flags & ADDPART_FLAG_RAID)
                        md_autodetect_dev(bdev->bd_dev+p);
 #endif
        }
index 8c7af1777819e2b2d5cdeabc49ef87298ca89c19..d964d1f90decff0855c8f1ddedd96c40512b3668 100644 (file)
@@ -155,7 +155,7 @@ parse_extended(struct parsed_partitions *state, struct block_device *bdev,
 
                        put_partition(state, state->next, next, size);
                        if (SYS_IND(p) == LINUX_RAID_PARTITION)
-                               state->parts[state->next].flags = 1;
+                               state->parts[state->next].flags = ADDPART_FLAG_RAID;
                        loopct = 0;
                        if (++state->next == state->limit)
                                goto done;
index 6fa4ff8951042f8f0becd6318b5991668933de5b..ed5ac83fe83ab0f5ec0333b986b693e2ce70743f 100644 (file)
@@ -72,7 +72,7 @@ int sgi_partition(struct parsed_partitions *state, struct block_device *bdev)
                if (blocks) {
                        put_partition(state, slot, start, blocks);
                        if (be32_to_cpu(p->type) == LINUX_RAID_PARTITION)
-                               state->parts[slot].flags = 1;
+                               state->parts[slot].flags = ADDPART_FLAG_RAID;
                }
                slot++;
        }
index 0a5927c806ca7dbf2aaa244b577159b779a602d6..123f8b46c8ba7cfbfd3676b37b00a8fa07070e38 100644 (file)
@@ -80,8 +80,11 @@ int sun_partition(struct parsed_partitions *state, struct block_device *bdev)
                num_sectors = be32_to_cpu(p->num_sectors);
                if (num_sectors) {
                        put_partition(state, slot, st_sector, num_sectors);
+                       state->parts[slot].flags = 0;
                        if (label->infos[i].id == LINUX_RAID_PARTITION)
-                               state->parts[slot].flags = 1;
+                               state->parts[slot].flags |= ADDPART_FLAG_RAID;
+                       if (label->infos[i].id == SUN_WHOLE_DISK)
+                               state->parts[slot].flags |= ADDPART_FLAG_WHOLEDISK;
                }
                slot++;
        }
index 0a022b2f63fc0fa95fa35df16784e2fcaef225b3..247734f7881fdd98d5b84ed3fb8415445a97b8fe 100644 (file)
@@ -20,6 +20,8 @@ enum {
        LINUX_EXTENDED_PARTITION = 0x85,
        WIN98_EXTENDED_PARTITION = 0x0f,
 
+       SUN_WHOLE_DISK = DOS_EXTENDED_PARTITION,
+
        LINUX_SWAP_PARTITION = 0x82,
        LINUX_RAID_PARTITION = 0xfd,    /* autodetect RAID partition */
 
@@ -400,10 +402,14 @@ struct unixware_disklabel {
 
 #ifdef __KERNEL__
 
+#define ADDPART_FLAG_NONE      0
+#define ADDPART_FLAG_RAID      1
+#define ADDPART_FLAG_WHOLEDISK 2
+
 char *disk_name (struct gendisk *hd, int part, char *buf);
 
 extern int rescan_partitions(struct gendisk *disk, struct block_device *bdev);
-extern void add_partition(struct gendisk *, int, sector_t, sector_t);
+extern void add_partition(struct gendisk *, int, sector_t, sector_t, int);
 extern void delete_partition(struct gendisk *, int);
 
 extern struct gendisk *alloc_disk_node(int minors, int node_id);