lkml.org 
[lkml]   [2004]   [Aug]   [22]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patches in this message
/
From
Subject[PATCH] Reread partition table when a partition is added
Date
  This small patch rereads the partition table even if the block device is 
beeing used. It only rereads it when there are no changes at the current
partitions and there are new partitions added at the end. Any existing
partition change will/should make it fail.

Is it OK and/or useful ?

(I'm quite inexperienced about kernel coding so be gentle :)

Signed-off-by: Stefanos Harhalakis <v13@priest.com>

RCS file: /usr/local/cvsroot/linux-2.6/fs/partitions/check.c,v
retrieving revision 1.1.1.1
diff -u -p -r1.1.1.1 check.c
--- check.c 22 Aug 2004 11:08:27 -0000 1.1.1.1
+++ check.c 22 Aug 2004 22:09:11 -0000
@@ -391,19 +391,44 @@ void register_disk(struct gendisk *disk)
blkdev_put(bdev);
}

+/*
+ * Determine the last partition.
+ * Return the partition number or 0 if there is no partition
+ */
+static int get_last_partition(struct gendisk *disk)
+{
+ int n, ret = 0;
+
+ for (n=0; n < disk->minors ; n++) {
+ if (disk->part[n])
+ ret=n+1;
+ }
+
+ return(ret);
+}
+
int rescan_partitions(struct gendisk *disk, struct block_device *bdev)
{
struct parsed_partitions *state;
+ struct hd_struct *phd;
int p, res;
+ int is_busy = 0, last_partition = 0;
+
+ if (bdev->bd_part_count) {
+ is_busy = 1;
+ last_partition=get_last_partition(disk);
+ }

- if (bdev->bd_part_count)
- return -EBUSY;
res = invalidate_partition(disk, 0);
if (res)
return res;
bdev->bd_invalidated = 0;
- for (p = 1; p < disk->minors; p++)
- delete_partition(disk, p);
+
+ if (!is_busy) {
+ for (p = 1; p < disk->minors; p++)
+ delete_partition(disk, p);
+ }
+
if (disk->fops->revalidate_disk)
disk->fops->revalidate_disk(disk);
if (!get_capacity(disk) || !(state = check_partition(disk, bdev)))
@@ -411,13 +436,29 @@ int rescan_partitions(struct gendisk *di
for (p = 1; p < state->limit; p++) {
sector_t size = state->parts[p].size;
sector_t from = state->parts[p].from;
+
+ if (is_busy && p<=last_partition) {
+ phd=disk->part[p-1];
+ if (phd != NULL && (phd->start_sect != from ||
+ phd->nr_sects != size)) {
+ printk(KERN_INFO
+ "Existing partition was changed. "
+ "Reboot is required.\n");
+ res=-EBUSY;
+ break;
+ }
+ }
+
if (!size)
continue;
- add_partition(disk, p, from, size);
+
+ if (!is_busy || p>last_partition) {
+ add_partition(disk, p, from, size);
#ifdef CONFIG_BLK_DEV_MD
- if (state->parts[p].flags)
- md_autodetect_dev(bdev->bd_dev+p);
+ if (state->parts[p].flags)
+ md_autodetect_dev(bdev->bd_dev+p);
#endif
+ }
}
kfree(state);
return res;RCS file: /usr/local/cvsroot/linux-2.6/fs/partitions/check.c,v
retrieving revision 1.1.1.1
diff -u -p -r1.1.1.1 check.c
--- check.c 22 Aug 2004 11:08:27 -0000 1.1.1.1
+++ check.c 22 Aug 2004 22:09:11 -0000
@@ -391,19 +391,44 @@ void register_disk(struct gendisk *disk)
blkdev_put(bdev);
}

+/*
+ * Determine the last partition.
+ * Return the partition number or 0 if there is no partition
+ */
+static int get_last_partition(struct gendisk *disk)
+{
+ int n, ret = 0;
+
+ for (n=0; n < disk->minors ; n++) {
+ if (disk->part[n])
+ ret=n+1;
+ }
+
+ return(ret);
+}
+
int rescan_partitions(struct gendisk *disk, struct block_device *bdev)
{
struct parsed_partitions *state;
+ struct hd_struct *phd;
int p, res;
+ int is_busy = 0, last_partition = 0;
+
+ if (bdev->bd_part_count) {
+ is_busy = 1;
+ last_partition=get_last_partition(disk);
+ }

- if (bdev->bd_part_count)
- return -EBUSY;
res = invalidate_partition(disk, 0);
if (res)
return res;
bdev->bd_invalidated = 0;
- for (p = 1; p < disk->minors; p++)
- delete_partition(disk, p);
+
+ if (!is_busy) {
+ for (p = 1; p < disk->minors; p++)
+ delete_partition(disk, p);
+ }
+
if (disk->fops->revalidate_disk)
disk->fops->revalidate_disk(disk);
if (!get_capacity(disk) || !(state = check_partition(disk, bdev)))
@@ -411,13 +436,29 @@ int rescan_partitions(struct gendisk *di
for (p = 1; p < state->limit; p++) {
sector_t size = state->parts[p].size;
sector_t from = state->parts[p].from;
+
+ if (is_busy && p<=last_partition) {
+ phd=disk->part[p-1];
+ if (phd != NULL && (phd->start_sect != from ||
+ phd->nr_sects != size)) {
+ printk(KERN_INFO
+ "Existing partition was changed. "
+ "Reboot is required.\n");
+ res=-EBUSY;
+ break;
+ }
+ }
+
if (!size)
continue;
- add_partition(disk, p, from, size);
+
+ if (!is_busy || p>last_partition) {
+ add_partition(disk, p, from, size);
#ifdef CONFIG_BLK_DEV_MD
- if (state->parts[p].flags)
- md_autodetect_dev(bdev->bd_dev+p);
+ if (state->parts[p].flags)
+ md_autodetect_dev(bdev->bd_dev+p);
#endif
+ }
}
kfree(state);
return res;[unhandled content-type:application/pgp-signature]
\
 
 \ /
  Last update: 2005-03-22 14:05    [W:0.038 / U:0.668 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site