summaryrefslogtreecommitdiff
path: root/libfdisk/src/alignment.c
diff options
context:
space:
mode:
Diffstat (limited to 'libfdisk/src/alignment.c')
-rw-r--r--libfdisk/src/alignment.c241
1 files changed, 198 insertions, 43 deletions
diff --git a/libfdisk/src/alignment.c b/libfdisk/src/alignment.c
index ac44e73c1..f661c5cce 100644
--- a/libfdisk/src/alignment.c
+++ b/libfdisk/src/alignment.c
@@ -74,6 +74,10 @@ sector_t fdisk_align_lba(struct fdisk_context *cxt, sector_t lba, int direction)
}
}
+ if (lba != res)
+ DBG(TOPOLOGY, dbgprint("LBA %ju -aligned-to-> %ju",
+ (uintmax_t) lba,
+ (uintmax_t) res));
return res;
}
@@ -114,32 +118,13 @@ static unsigned long get_sector_size(int fd)
return DEFAULT_SECTOR_SIZE;
}
-/**
- * fdisk_override_sector_size:
- * @cxt: fdisk context
- * @s: required sector size
- *
- * Overwrites logical and physical sector size. Note that the default sector
- * size is discovered by fdisk_new_context_from_device() from device topology.
- *
- * Don't use this function, rely on the default behavioer is more safe.
- *
- * Returns: 0 on success, < 0 on error.
- */
-int fdisk_override_sector_size(struct fdisk_context *cxt, sector_t s)
-{
- if (!cxt)
- return -EINVAL;
-
- cxt->phy_sector_size = cxt->sector_size = s;
- cxt->min_io_size = cxt->io_size = s;
-
- fdisk_reset_alignment(cxt);
- return 0;
-}
-
static void recount_geometry(struct fdisk_context *cxt)
{
+ if (!cxt->geom.heads)
+ cxt->geom.heads = 255;
+ if (!cxt->geom.sectors)
+ cxt->geom.sectors = 63;
+
cxt->geom.cylinders = cxt->total_sectors /
(cxt->geom.heads * cxt->geom.sectors);
}
@@ -151,7 +136,8 @@ static void recount_geometry(struct fdisk_context *cxt)
* @heads: user specified heads
* @sectors: user specified sectors
*
- * Overrides autodiscovery and apply user specified geometry.
+ * Overrides autodiscovery and apply user specified geometry. The function
+ * fdisk_reset_device_properties() restores the original setting.
*
* Returns: 0 on success, < 0 on error.
*/
@@ -173,6 +159,133 @@ int fdisk_override_geometry(struct fdisk_context *cxt,
recount_geometry(cxt);
fdisk_reset_alignment(cxt);
+
+ DBG(GEOMETRY, dbgprint("override C/H/S: %u/%u/%u",
+ (unsigned) cxt->geom.cylinders,
+ (unsigned) cxt->geom.heads,
+ (unsigned) cxt->geom.sectors));
+
+ return 0;
+}
+
+int fdisk_save_user_geometry(struct fdisk_context *cxt,
+ unsigned int cylinders,
+ unsigned int heads,
+ unsigned int sectors)
+{
+ if (!cxt)
+ return -EINVAL;
+
+ if (heads)
+ cxt->user_geom.heads = heads > 256 ? 0 : heads;
+ if (sectors)
+ cxt->user_geom.sectors = sectors >= 64 ? 0 : sectors;
+ if (cylinders)
+ cxt->user_geom.cylinders = cylinders;
+
+ DBG(GEOMETRY, dbgprint("user C/H/S: %u/%u/%u",
+ (unsigned) cxt->user_geom.cylinders,
+ (unsigned) cxt->user_geom.heads,
+ (unsigned) cxt->user_geom.sectors));
+
+ return 0;
+}
+
+int fdisk_save_user_sector_size(struct fdisk_context *cxt,
+ unsigned int phy,
+ unsigned int log)
+{
+ if (!cxt)
+ return -EINVAL;
+
+ DBG(TOPOLOGY, dbgprint("user phy/log sector size: %u/%u", phy, log));
+
+ cxt->user_pyh_sector = phy;
+ cxt->user_log_sector = log;
+
+ return 0;
+}
+
+int fdisk_has_user_device_properties(struct fdisk_context *cxt)
+{
+ return (cxt->user_pyh_sector
+ || cxt->user_log_sector
+ || cxt->user_geom.heads
+ || cxt->user_geom.sectors
+ || cxt->user_geom.cylinders);
+}
+
+int fdisk_apply_user_device_properties(struct fdisk_context *cxt)
+{
+ if (!cxt)
+ return -EINVAL;
+
+ DBG(TOPOLOGY, dbgprint("appling user device properties"));
+
+ if (cxt->user_pyh_sector)
+ cxt->phy_sector_size = cxt->user_pyh_sector;
+ if (cxt->user_log_sector)
+ cxt->sector_size = cxt->min_io_size =
+ cxt->io_size = cxt->user_log_sector;
+
+ if (cxt->user_geom.heads)
+ cxt->geom.heads = cxt->user_geom.heads;
+ if (cxt->user_geom.sectors)
+ cxt->geom.sectors = cxt->user_geom.sectors;
+
+ if (cxt->user_geom.cylinders)
+ cxt->geom.cylinders = cxt->user_geom.cylinders;
+ else if (cxt->user_geom.heads || cxt->user_geom.sectors)
+ recount_geometry(cxt);
+
+ fdisk_reset_alignment(cxt);
+
+ DBG(GEOMETRY, dbgprint("new C/H/S: %u/%u/%u",
+ (unsigned) cxt->geom.cylinders,
+ (unsigned) cxt->geom.heads,
+ (unsigned) cxt->geom.sectors));
+ DBG(TOPOLOGY, dbgprint("new log/phy sector size: %u/%u",
+ (unsigned) cxt->sector_size,
+ (unsigned) cxt->phy_sector_size));
+
+ return 0;
+}
+
+void fdisk_zeroize_device_properties(struct fdisk_context *cxt)
+{
+ assert(cxt);
+
+ cxt->io_size = 0;
+ cxt->optimal_io_size = 0;
+ cxt->min_io_size = 0;
+ cxt->phy_sector_size = 0;
+ cxt->sector_size = 0;
+ cxt->alignment_offset = 0;
+ cxt->grain = 0;
+ cxt->first_lba = 0;
+ cxt->total_sectors = 0;
+
+ memset(&cxt->geom, 0, sizeof(struct fdisk_geometry));
+}
+
+int fdisk_reset_device_properties(struct fdisk_context *cxt)
+{
+ int rc;
+
+ if (!cxt)
+ return -EINVAL;
+
+ DBG(TOPOLOGY, dbgprint("*** reseting device properties"));
+
+ fdisk_zeroize_device_properties(cxt);
+ fdisk_discover_topology(cxt);
+ fdisk_discover_geometry(cxt);
+
+ rc = fdisk_read_firstsector(cxt);
+ if (rc)
+ return rc;
+
+ fdisk_apply_user_device_properties(cxt);
return 0;
}
@@ -182,31 +295,26 @@ int fdisk_override_geometry(struct fdisk_context *cxt,
int fdisk_discover_geometry(struct fdisk_context *cxt)
{
sector_t nsects;
- unsigned int h = 0, s = 0;
assert(cxt);
assert(cxt->geom.heads == 0);
+ DBG(GEOMETRY, dbgprint("%s: discovering geometry...", cxt->dev_path));
+
/* get number of 512-byte sectors, and convert it the real sectors */
if (!blkdev_get_sectors(cxt->dev_fd, &nsects))
cxt->total_sectors = (nsects / (cxt->sector_size >> 9));
/* what the kernel/bios thinks the geometry is */
- blkdev_get_geometry(cxt->dev_fd, &h, &s);
- if (!h && !s) {
- /* unable to discover geometry, use default values */
- s = 63;
- h = 255;
- }
+ blkdev_get_geometry(cxt->dev_fd, &cxt->geom.heads, (unsigned int *) &cxt->geom.sectors);
/* obtained heads and sectors */
- cxt->geom.heads = h;
- cxt->geom.sectors = s;
recount_geometry(cxt);
- DBG(GEOMETRY, dbgprint("geometry discovered for %s: C/H/S: %lld/%d/%lld",
- cxt->dev_path, cxt->geom.cylinders,
- cxt->geom.heads, cxt->geom.sectors));
+ DBG(GEOMETRY, dbgprint("result: C/H/S: %u/%u/%u",
+ (unsigned) cxt->geom.cylinders,
+ (unsigned) cxt->geom.heads,
+ (unsigned) cxt->geom.sectors));
return 0;
}
@@ -218,6 +326,7 @@ int fdisk_discover_topology(struct fdisk_context *cxt)
assert(cxt);
assert(cxt->sector_size == 0);
+ DBG(TOPOLOGY, dbgprint("%s: discovering topology...", cxt->dev_path));
#ifdef HAVE_LIBBLKID
DBG(TOPOLOGY, dbgprint("initialize libblkid prober"));
@@ -251,11 +360,10 @@ int fdisk_discover_topology(struct fdisk_context *cxt)
if (!cxt->io_size)
cxt->io_size = cxt->sector_size;
- DBG(TOPOLOGY, dbgprint("topology discovered for %s:\n"
- "\tlogical/physical sector sizes: %ld/%ld\n"
- "\tfdisk/minimal/optimal io sizes: %ld/%ld/%ld\n",
- cxt->dev_path, cxt->sector_size, cxt->phy_sector_size,
- cxt->io_size, cxt->optimal_io_size, cxt->min_io_size));
+ DBG(TOPOLOGY, dbgprint("result: log/phy sector size: %ld/%ld",
+ cxt->sector_size, cxt->phy_sector_size));
+ DBG(TOPOLOGY, dbgprint("result: fdisk/min/optimal io: %ld/%ld/%ld",
+ cxt->io_size, cxt->optimal_io_size, cxt->min_io_size));
return 0;
}
@@ -364,6 +472,8 @@ int fdisk_reset_alignment(struct fdisk_context *cxt)
if (!cxt)
return -EINVAL;
+ DBG(TOPOLOGY, dbgprint("reseting alignment..."));
+
/* default */
cxt->grain = fdisk_topology_get_grain(cxt);
cxt->first_lba = fdisk_topology_get_first_lba(cxt);
@@ -372,10 +482,55 @@ int fdisk_reset_alignment(struct fdisk_context *cxt)
if (cxt->label && cxt->label->op->reset_alignment)
rc = cxt->label->op->reset_alignment(cxt);
- DBG(LABEL, dbgprint("%s alignment reseted to: "
+ DBG(TOPOLOGY, dbgprint("%s alignment reseted to: "
"first LBA=%ju, grain=%lu [rc=%d]",
cxt->label ? cxt->label->name : NULL,
(uintmax_t) cxt->first_lba,
cxt->grain, rc));
return rc;
}
+
+
+sector_t fdisk_scround(struct fdisk_context *cxt, sector_t num)
+{
+ sector_t un = fdisk_context_get_units_per_sector(cxt);
+ return (num + un - 1) / un;
+}
+
+sector_t fdisk_cround(struct fdisk_context *cxt, sector_t num)
+{
+ return fdisk_context_use_cylinders(cxt) ?
+ (num / fdisk_context_get_units_per_sector(cxt)) + 1 : num;
+}
+
+int fdisk_reread_partition_table(struct fdisk_context *cxt)
+{
+ int i;
+ struct stat statbuf;
+
+ assert(cxt);
+ assert(cxt->dev_fd >= 0);
+
+ i = fstat(cxt->dev_fd, &statbuf);
+ if (i == 0 && S_ISBLK(statbuf.st_mode)) {
+ sync();
+#ifdef BLKRRPART
+ fdisk_info(cxt, _("Calling ioctl() to re-read partition table."));
+ i = ioctl(cxt->dev_fd, BLKRRPART);
+#else
+ errno = ENOSYS;
+ i = 1;
+#endif
+ }
+
+ if (i) {
+ fdisk_warn(cxt, _("Re-reading the partition table failed."));
+ fdisk_info(cxt, _(
+ "The kernel still uses the old table. The "
+ "new table will be used at the next reboot "
+ "or after you run partprobe(8) or kpartx(8)."));
+ return -errno;
+ }
+
+ return 0;
+}