From: Karel Zak Date: Mon, 16 Sep 2024 12:50:43 +0000 (+0200) Subject: sfdisk: add --discard-free X-Git-Tag: v2.42-start~206^2 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=8f6f35aeb63341ce90122259196501467e44734b;p=thirdparty%2Futil-linux.git sfdisk: add --discard-free Why do we need this? It can be difficult for end-users to discard unpartitioned areas using blkdiscard, as it requires using fdisk to obtain a list of free areas and then using blkdiscard with the correct --offset and --length options. It is less risky for end-users to use (s)fdisk, as they have a better understanding of the disk layout. Addresses: https://github.com/util-linux/util-linux/issues/2804 Signed-off-by: Karel Zak --- diff --git a/bash-completion/sfdisk b/bash-completion/sfdisk index b075ccc91..4dc57c4ea 100644 --- a/bash-completion/sfdisk +++ b/bash-completion/sfdisk @@ -58,6 +58,7 @@ _sfdisk_module() --show-geometry --list --list-free + --discard-free --disk-id --reorder --show-size diff --git a/disk-utils/sfdisk.8.adoc b/disk-utils/sfdisk.8.adoc index b2e5279d2..26ccad5a3 100644 --- a/disk-utils/sfdisk.8.adoc +++ b/disk-utils/sfdisk.8.adoc @@ -116,6 +116,13 @@ Change the GPT partition UUID. If _uuid_ is not specified, then print the curren *--disk-id* _device_ [__id__]:: Change the disk identifier. If _id_ is not specified, then print the current identifier. The identifier is UUID for GPT or unsigned integer for MBR. +*--discard-free* _device_ :: +Discard any unused (unpartitioned) sectors on the device. Use the *--list-free* option to get a list of the free regions. See also *blkdiscard*(8). ++ +WARNING: All data in the discarded regions on the device will be lost! Do not use this option if you are unsure. ++ +Note that the 'T' command in *fdisk* provides a dialog to specify which unused area should be discarded. However, *sfdisk* always discards all unpartitioned regions (except for the areas where it is not possible to create partitions, such as the beginning of the device). + *-r*, *--reorder* _device_:: Renumber the partitions, ordering them by their start offset. diff --git a/disk-utils/sfdisk.c b/disk-utils/sfdisk.c index 71b0191d2..cf402007b 100644 --- a/disk-utils/sfdisk.c +++ b/disk-utils/sfdisk.c @@ -87,6 +87,7 @@ enum { ACT_PARTUUID, ACT_PARTLABEL, ACT_PARTATTRS, + ACT_DISCARD_FREE, ACT_DISKID, ACT_DELETE, ACT_BACKUP_SECTORS, @@ -1369,6 +1370,69 @@ static int command_partattrs(struct sfdisk *sf, int argc, char **argv) return write_changes(sf); } +/* + * sfdisk --discard-free + */ +static int command_discard_free(struct sfdisk *sf, int argc, char **argv) +{ + struct fdisk_table *tb = NULL; + struct fdisk_iter *itr = NULL; + struct fdisk_partition *pa = NULL; + const char *devname = NULL; + uint64_t ss; + int rc; + + if (!argc) + errx(EXIT_FAILURE, _("no disk device specified")); + devname = argv[0]; + if (argc > 1) + errx(EXIT_FAILURE, _("unexpected arguments")); + + itr = fdisk_new_iter(FDISK_ITER_FORWARD); + if (!itr) + err(EXIT_FAILURE, _("failed to allocate iterator")); + + assign_device(sf, devname, 0); + + ss = fdisk_get_sector_size(sf->cxt); + + rc = fdisk_get_freespaces(sf->cxt, &tb); + if (rc) { + fdisk_warn(sf->cxt, _("failed to gather unpartitioned space")); + goto done; + } + + while (fdisk_table_next_partition(tb, itr, &pa) == 0) { + uint64_t range[2]; + + if (!fdisk_partition_has_size(pa) || + !fdisk_partition_has_start(pa)) + continue; + + range[0] = (uint64_t) fdisk_partition_get_start(pa); + range[1] = (uint64_t) fdisk_partition_get_size(pa); + + fdisk_info(sf->cxt, _("Discarding region %"PRIu64 + "-%"PRIu64""), + range[0], range[0] + range[1] - 1); + + range[0] *= ss; + range[1] *= ss; + + errno = 0; + if (ioctl(fdisk_get_devfd(sf->cxt), BLKDISCARD, &range)) { + rc = -errno; + fdisk_warn(sf->cxt, _("BLKDISCARD ioctl failed")); + break; + } + } + +done: + fdisk_free_iter(itr); + fdisk_unref_table(tb); + return rc; +} + /* * sfdisk --disk-id [] */ @@ -2070,6 +2134,7 @@ static void __attribute__((__noreturn__)) usage(void) fputs(_(" --part-attrs [] print or change partition attributes\n"), out); fputs(USAGE_SEPARATOR, out); + fputs(_(" --discard-free discard (trim) unpartitioned areas\n"), out); fputs(_(" --disk-id [] print or change disk label ID (UUID)\n"), out); fputs(_(" --relocate move partition header\n"), out); @@ -2142,6 +2207,7 @@ int main(int argc, char *argv[]) OPT_PARTLABEL, OPT_PARTTYPE, OPT_PARTATTRS, + OPT_DISCARDFREE, OPT_DISKID, OPT_BYTES, OPT_COLOR, @@ -2194,6 +2260,8 @@ int main(int argc, char *argv[]) { "part-type", no_argument, NULL, OPT_PARTTYPE }, { "part-attrs", no_argument, NULL, OPT_PARTATTRS }, + { "discard-free", no_argument, NULL, OPT_DISCARDFREE }, + { "disk-id", no_argument, NULL, OPT_DISKID }, { "show-pt-geometry", no_argument, NULL, 'G' }, /* deprecated */ @@ -2340,6 +2408,9 @@ int main(int argc, char *argv[]) case OPT_PARTATTRS: sf->act = ACT_PARTATTRS; break; + case OPT_DISCARDFREE: + sf->act = ACT_DISCARD_FREE; + break; case OPT_DISKID: sf->act = ACT_DISKID; break; @@ -2462,6 +2533,10 @@ int main(int argc, char *argv[]) rc = command_partattrs(sf, argc - optind, argv + optind); break; + case ACT_DISCARD_FREE: + rc = command_discard_free(sf, argc - optind, argv + optind); + break; + case ACT_DISKID: rc = command_diskid(sf, argc - optind, argv + optind); break; diff --git a/sys-utils/blkdiscard.8.adoc b/sys-utils/blkdiscard.8.adoc index cf661acd9..3be78b49d 100644 --- a/sys-utils/blkdiscard.8.adoc +++ b/sys-utils/blkdiscard.8.adoc @@ -24,7 +24,7 @@ The _device_ argument is the pathname of the block device. *WARNING: All data in the discarded region on the device will be lost!* -Since util-linux v2.41, fdisk has the ability to discard sectors on both partitions and unpartitioned areas using the 'T' command. +Since util-linux v2.41, *fdisk* has the ability to discard sectors on both partitions and unpartitioned areas using the 'T' command. Additionally, *sfdisk* has the option --discard-free to discard unpartitioned areas. == OPTIONS