summaryrefslogtreecommitdiffstats
path: root/src/shared
diff options
context:
space:
mode:
authorDaan De Meyer <daan.j.demeyer@gmail.com>2022-07-29 12:19:09 +0200
committerDaan De Meyer <daan.j.demeyer@gmail.com>2022-08-03 20:55:32 +0200
commit35d40302af8ac1c8dfb7c970e621d2636a906851 (patch)
tree78ebcd09cdf845e634828991fc68b7858dd0ee0b /src/shared
parentloop-util: Add loop_device_unrelinquish() (diff)
downloadsystemd-35d40302af8ac1c8dfb7c970e621d2636a906851.tar.xz
systemd-35d40302af8ac1c8dfb7c970e621d2636a906851.zip
blockdev-util: Add block_device_remove_all_partitions()
This function takes a block device, uses sd-device to iterate all the partitions, and removes them one by one.
Diffstat (limited to 'src/shared')
-rw-r--r--src/shared/blockdev-util.c66
-rw-r--r--src/shared/blockdev-util.h1
2 files changed, 67 insertions, 0 deletions
diff --git a/src/shared/blockdev-util.c b/src/shared/blockdev-util.c
index b0ab5b440e..0d921cc045 100644
--- a/src/shared/blockdev-util.c
+++ b/src/shared/blockdev-util.c
@@ -5,9 +5,12 @@
#include <sys/ioctl.h>
#include <unistd.h>
+#include "sd-device.h"
+
#include "alloc-util.h"
#include "blockdev-util.h"
#include "btrfs-util.h"
+#include "device-util.h"
#include "devnum-util.h"
#include "dirent-util.h"
#include "errno-util.h"
@@ -476,3 +479,66 @@ int block_device_remove_partition(int fd, const char *name, int nr) {
return RET_NERRNO(ioctl(fd, BLKPG, &ba));
}
+
+int block_device_remove_all_partitions(int fd) {
+ struct stat stat;
+ _cleanup_(sd_device_unrefp) sd_device *dev = NULL;
+ _cleanup_(sd_device_enumerator_unrefp) sd_device_enumerator *e = NULL;
+ sd_device *part;
+ int r, k = 0;
+
+ if (fstat(fd, &stat) < 0)
+ return -errno;
+
+ r = sd_device_new_from_devnum(&dev, 'b', stat.st_rdev);
+ if (r < 0)
+ return r;
+
+ r = sd_device_enumerator_new(&e);
+ if (r < 0)
+ return r;
+
+ r = sd_device_enumerator_add_match_parent(e, dev);
+ if (r < 0)
+ return r;
+
+ r = sd_device_enumerator_add_match_subsystem(e, "block", true);
+ if (r < 0)
+ return r;
+
+ r = sd_device_enumerator_add_match_property(e, "DEVTYPE", "partition");
+ if (r < 0)
+ return r;
+
+ FOREACH_DEVICE(e, part) {
+ const char *v, *devname;
+ int nr;
+
+ r = sd_device_get_devname(part, &devname);
+ if (r < 0)
+ return r;
+
+ r = sd_device_get_property_value(part, "PARTN", &v);
+ if (r < 0)
+ return r;
+
+ r = safe_atoi(v, &nr);
+ if (r < 0)
+ return r;
+
+ r = block_device_remove_partition(fd, devname, nr);
+ if (r == -ENODEV) {
+ log_debug("Kernel removed partition %s before us, ignoring", devname);
+ continue;
+ }
+ if (r < 0) {
+ log_debug_errno(r, "Failed to remove partition %s: %m", devname);
+ k = k ?: r;
+ continue;
+ }
+
+ log_debug("Removed partition %s", devname);
+ }
+
+ return k;
+}
diff --git a/src/shared/blockdev-util.h b/src/shared/blockdev-util.h
index f7055625a3..8c9401b4a7 100644
--- a/src/shared/blockdev-util.h
+++ b/src/shared/blockdev-util.h
@@ -33,3 +33,4 @@ int path_get_whole_disk(const char *path, bool backing, dev_t *ret);
int block_device_add_partition(int fd, const char *name, int nr, uint64_t start, uint64_t size);
int block_device_remove_partition(int fd, const char *name, int nr);
+int block_device_remove_all_partitions(int fd);