diff options
-rw-r--r-- | libparted/arch/gnu.c | 84 |
1 files changed, 78 insertions, 6 deletions
diff --git a/libparted/arch/gnu.c b/libparted/arch/gnu.c index 0797115..b040c45 100644 --- a/libparted/arch/gnu.c +++ b/libparted/arch/gnu.c @@ -185,7 +185,7 @@ _init_device (const char *path) if (!dev->arch_specific) goto error_free_path; - dev->type = PED_DEVICE_FILE; /* FIXME? */ + dev->type = PED_DEVICE_UNKNOWN; /* It's deprecated anyway */ dev->open_count = 0; dev->read_only = 0; dev->external_mode = 0; @@ -204,11 +204,83 @@ error: return NULL; } +/* Ask the kernel and translators to reload the partition table. + XXX: Will probably be replaced by some RPC to partfs when it's finished. In + the meantime, gnumach's glue layer will pass BLKRRPART to the Linux drivers. + */ +#define BLKRRPART 0x125F static int -_kernel_reread_part_table (PedDevice* dev) +_reread_part_table (PedDevice* dev) { - /* XXX: We must wait for partfs to be finished. */ - return 1; + struct store *store = GNU_SPECIFIC (dev)->store; + int retry_count = 9; + int len = strlen (dev->path); + char path[len + 3 + 1]; + int i; + int done = 1; + + sync (); + + if(strcmp (store->class->name, "device") == 0) { + while (device_set_status (store->port, BLKRRPART, NULL, 0)) { + retry_count--; + sync (); + if (retry_count == 3) + sleep (1); /* Pause to allow system to settle */ + + if (!retry_count) { + ped_exception_throw ( + PED_EXCEPTION_WARNING, + PED_EXCEPTION_IGNORE, + _("WARNING: the kernel failed to re-read the " + "partition table on %s (%s). As a result, " + "it may not reflect all of your changes " + "until after reboot."), + dev->path, strerror (errno)); + return 0; + } + } + } + + i = 1; + while (1) { + file_t node; + error_t err; + + /* Throw away all active parted-based translators */ + snprintf (path, sizeof (path), "%ss%u", dev->path, i); + node = file_name_lookup (path, O_NOTRANS, 0666); + if (node == MACH_PORT_NULL) { + if (errno == ENOENT) + /* Finished looping over them */ + break; + + ped_exception_throw ( + PED_EXCEPTION_WARNING, + PED_EXCEPTION_IGNORE, + _("Warning: unable to open %s (%s). As a " + "result, it may not reflect all of your " + "changes until after reboot."), + path, strerror (errno)); + done = 0; + } + + err = file_set_translator (node, 0, FS_TRANS_SET, + 0, 0, 0, MACH_PORT_NULL, MACH_MSG_TYPE_COPY_SEND); + if (err) { + ped_exception_throw ( + PED_EXCEPTION_WARNING, + PED_EXCEPTION_IGNORE, + _("Warning: failed to make translator go away " + "on %s (%s). As a result, it may not reflect " + "all of your changes until after reboot."), + dev->path, strerror (errno)); + done = 0; + } + i++; + } + + return done; } /* Free the memory associated with a PedDevice structure. */ @@ -355,7 +427,7 @@ gnu_close (PedDevice* dev) _flush_cache (dev); if (dev->dirty && dev->type != PED_DEVICE_FILE) { - if (_kernel_reread_part_table (dev)) + if (_reread_part_table (dev)) dev->dirty = 0; } @@ -827,7 +899,7 @@ gnu_partition_is_busy (const PedPartition* part) static int gnu_disk_commit (PedDisk* disk) { - return 1; + return _reread_part_table (disk->dev); } static PedDeviceArchOps gnu_dev_ops = { |