From 24ff32fd63a19df0b2ea166fd4a6b439d778257a Mon Sep 17 00:00:00 2001 From: Mike Fleetwood Date: Wed, 28 Feb 2024 14:57:23 +0000 Subject: [PATCH 01/14] Move ZFS to a darker shade of Orange (!123) Bcachefs [1] has many of the same capabilities as Btrfs [2] and ZFS [3]: COW (Copy-on-Write), multi-device, multi-volume, snapshotting and many more. Therefore when adding bcachefs use the same range of Orange colours already used by Btrfs and ZFS [4]. As bcachefs is a native Linux file system and ZFS is not, move ZFS to a darker shade of Orange to allow bcachefs to be added in the middle: Btrfs - Orange Medium (#E58749) bcachefs - Orange Dark (#C26825) ZFS - Orange Shadow (#984F18) [1] bcachefs https://bcachefs.org/ [2] Welcome to BTRFS documentation! > Introduction https://btrfs.readthedocs.io/en/latest/Introduction.html [3] ZFS https://en.wikipedia.org/wiki/ZFS [4] 8a4f9ad205378f2738a2bde9fab42bf604856ef4 Adjust shades of aquamarine, cyan and orange Closes !123 - Add support for bcachefs, single device file systems only --- src/Utils.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Utils.cc b/src/Utils.cc index 534912cb..adf3aa1e 100644 --- a/src/Utils.cc +++ b/src/Utils.cc @@ -185,7 +185,7 @@ Glib::ustring Utils::get_color(FSType fstype) case FS_LINUX_SWSUSPEND: return "#884631"; // Red Dark case FS_REFS: return "#3EA281"; // Aquamarine Dark [*] case FS_UFS: return "#AA8F2C"; // Accent Yellow Shadow [+] - case FS_ZFS: return "#C26825"; // Orange Dark [*] + case FS_ZFS: return "#984F18"; // Orange Shadow [*] case FS_USED: return "#F8F8BA"; // Light Tan Yellow [*] case FS_UNUSED: return "#FFFFFF"; // White default: return "#000000"; // Black From 4b30efd29dcf20164ae312188c25b2bb32c9a6f2 Mon Sep 17 00:00:00 2001 From: Mike Fleetwood Date: Mon, 26 Feb 2024 21:47:15 +0000 Subject: [PATCH 02/14] Add bcachefs detection (!123) Uses blkid from util-linux >= 2.39 [1] for detection of bcachefs file systems. Use util-linux's FS images when testing GParted detection. # wget https://git.kernel.org/pub/scm/utils/util-linux/util-linux.git/plain/tests/ts/blkid/images-fs/bcachefs.img.xz # zxcat bcachefs.img.xz > /dev/sdb1 # wget https://git.kernel.org/pub/scm/utils/util-linux/util-linux.git/plain/tests/ts/blkid/images-fs/bcachefs-2.img.xz # zxcat bcachefs-2.img.xz > /dev/sdb2 # blkid /dev/sdb1 /dev/sdb2 /dev/sdb1: UUID="46bd306f-80ad-4cd0-af4f-147e7d85f393" LABEL="Label" BLOCK_SIZE="4096" UUID_SUB="72a60ede-4cb6-4374-aa70-cb38a50af5ef" TYPE="bcachefs" PARTUUID="bd47302a-b33b-47a5-83a1-ba89f52f2a45" /dev/sdb2: UUID="4fa11b1e-75e6-4210-9167-34e1769c0fe1" LABEL="Label" BLOCK_SIZE="512" UUID_SUB="525fa857-174a-4d3f-be33-6fe60441de7c" LABEL_SUB="Device Label" TYPE="bcachefs" PARTUUID="6a46a084-5d3b-408a-bba7-351daaea1c66" [1] Util-linux 2.39 Release Notes https://mirrors.edge.kernel.org/pub/linux/utils/util-linux/v2.39/v2.39-ReleaseNotes "blkid(8) and libblkid: * supports bcachefs " Closes !123 - Add support for bcachefs, single device file systems only --- include/Utils.h | 71 +++++++++++++++++++++++---------------------- src/GParted_Core.cc | 2 ++ src/Utils.cc | 2 ++ 3 files changed, 40 insertions(+), 35 deletions(-) diff --git a/include/Utils.h b/include/Utils.h index 5c6635b4..5aa566eb 100644 --- a/include/Utils.h +++ b/include/Utils.h @@ -71,45 +71,46 @@ enum FSType FS_EXTENDED = 6, // Fully supported file system types - FS_BTRFS = 7, - FS_EXFAT = 8, /* Also known as fat64 */ - FS_EXT2 = 9, - FS_EXT3 = 10, - FS_EXT4 = 11, - FS_F2FS = 12, - FS_FAT16 = 13, - FS_FAT32 = 14, - FS_HFS = 15, - FS_HFSPLUS = 16, - FS_JFS = 17, - FS_LINUX_SWAP = 18, - FS_LUKS = 19, - FS_LVM2_PV = 20, - FS_MINIX = 21, - FS_NILFS2 = 22, - FS_NTFS = 23, - FS_REISER4 = 24, - FS_REISERFS = 25, - FS_UDF = 26, - FS_XFS = 27, + FS_BCACHEFS = 7, + FS_BTRFS = 8, + FS_EXFAT = 9, /* Also known as fat64 */ + FS_EXT2 = 10, + FS_EXT3 = 11, + FS_EXT4 = 12, + FS_F2FS = 13, + FS_FAT16 = 14, + FS_FAT32 = 15, + FS_HFS = 16, + FS_HFSPLUS = 17, + FS_JFS = 18, + FS_LINUX_SWAP = 19, + FS_LUKS = 20, + FS_LVM2_PV = 21, + FS_MINIX = 22, + FS_NILFS2 = 23, + FS_NTFS = 24, + FS_REISER4 = 25, + FS_REISERFS = 26, + FS_UDF = 27, + FS_XFS = 28, // Other recognised file system types - FS_APFS = 28, - FS_ATARAID = 29, - FS_BCACHE = 30, - FS_BITLOCKER = 31, - FS_GRUB2_CORE_IMG = 32, - FS_ISO9660 = 33, - FS_JBD = 34, - FS_LINUX_SWRAID = 35, - FS_LINUX_SWSUSPEND = 36, - FS_REFS = 37, - FS_UFS = 38, - FS_ZFS = 39, + FS_APFS = 29, + FS_ATARAID = 30, + FS_BCACHE = 31, + FS_BITLOCKER = 32, + FS_GRUB2_CORE_IMG = 33, + FS_ISO9660 = 34, + FS_JBD = 35, + FS_LINUX_SWRAID = 36, + FS_LINUX_SWSUSPEND = 37, + FS_REFS = 38, + FS_UFS = 39, + FS_ZFS = 40, // Partition space usage colours - FS_USED = 40, - FS_UNUSED = 41 + FS_USED = 41, + FS_UNUSED = 42 } ; enum SIZE_UNIT diff --git a/src/GParted_Core.cc b/src/GParted_Core.cc index 1629f94f..4d955733 100644 --- a/src/GParted_Core.cc +++ b/src/GParted_Core.cc @@ -1270,6 +1270,8 @@ FSType GParted_Core::detect_filesystem(const PedDevice *lp_device, const PedPart { if ( fsname == "extended" ) return FS_EXTENDED; + else if (fsname == "bcachefs") + return FS_BCACHEFS; else if ( fsname == "btrfs" ) return FS_BTRFS; else if ( fsname == "exfat" ) diff --git a/src/Utils.cc b/src/Utils.cc index adf3aa1e..83aaa037 100644 --- a/src/Utils.cc +++ b/src/Utils.cc @@ -153,6 +153,7 @@ Glib::ustring Utils::get_color(FSType fstype) case FS_CLEARED: return "#000000"; // Black case FS_OTHER: return "#000000"; // Black (never displayed) case FS_EXTENDED: return "#95E3E5"; // Cyan Hilight [*] + case FS_BCACHEFS: return "#C26825"; // Orange Dark [*] case FS_BTRFS: return "#E58749"; // Orange Medium [*] case FS_EXFAT: return "#267726"; // Accent Green Dark case FS_EXT2: return "#7590AE"; // Blue Medium @@ -347,6 +348,7 @@ const Glib::ustring Utils::get_filesystem_string(FSType fstype) */ return _("cleared"); case FS_EXTENDED: return "extended"; + case FS_BCACHEFS: return "bcachefs"; case FS_BTRFS: return "btrfs"; case FS_EXFAT: return "exfat"; case FS_EXT2: return "ext2"; From 5b47fb5c6845df0d125ebcb7910b1bf61fad0841 Mon Sep 17 00:00:00 2001 From: Mike Fleetwood Date: Wed, 28 Feb 2024 16:35:22 +0000 Subject: [PATCH 03/14] Add bcachefs creation (!123) Set the minimum file system size to 16 MiB as creating a bcachefs that size succeeds: $ truncate -s $((16*1024*1024)) /tmp/disk.img $ bcachefs format /tmp/disk.img ... initializing new filesystem going read-write initializing freespace $ echo $? 0 Where as creating a smaller file system fails for most sizes below that: $ rm /tmp/disk.img $ truncate -s $((15*1024*1024)) /tmp/disk.img $ bcachefs format /tmp/disk.img ... mounting version 1.6: btree_subvolume_children initializing new filesystem going read-write bch2_trans_mark_dev_sb(): error ENOSPC_disk_reservation bch2_fs_initialize(): error marking superblocks ENOSPC_disk_reservation bch2_fs_initialize(): error ENOSPC_disk_reservation bch2_fs_start(): error starting filesystem ENOSPC_disk_reservation error opening /tmp/disk.img: ENOSPC_disk_reservation $ echo $? 1 Closes !123 - Add support for bcachefs, single device file systems only --- README | 1 + gparted.appdata.xml.in | 6 ++-- include/Makefile.am | 1 + include/bcachefs.h | 41 +++++++++++++++++++++++++ po/POTFILES.in | 1 + src/Makefile.am | 1 + src/SupportedFileSystems.cc | 2 ++ src/Utils.cc | 1 + src/bcachefs.cc | 61 +++++++++++++++++++++++++++++++++++++ tests/Makefile.am | 1 + 10 files changed, 113 insertions(+), 3 deletions(-) create mode 100644 include/bcachefs.h create mode 100644 src/bcachefs.cc diff --git a/README b/README index a501ae6b..89a56f80 100644 --- a/README +++ b/README @@ -265,6 +265,7 @@ devices and partitions. When available, it uses each file system's specific commands. The following optional file system specific packages provide this support: + bcachefs-tools btrfs-progs / btrfs-tools e2fsprogs exfatprogs diff --git a/gparted.appdata.xml.in b/gparted.appdata.xml.in index 2c180939..3536f6c9 100644 --- a/gparted.appdata.xml.in +++ b/gparted.appdata.xml.in @@ -18,9 +18,9 @@ data rescue from lost partitions.

- GParted works with many file systems including: btrfs, exfat, ext2, - ext3, ext4, fat16, fat32, hfs, hfs+, linux-swap, lvm2 pv, minix, - nilfs2, ntfs, reiserfs, reiser4, udf, ufs, and xfs. + GParted works with many file systems including: bcachefs, btrfs, + exfat, ext2, ext3, ext4, fat16, fat32, hfs, hfs+, linux-swap, + lvm2 pv, minix, nilfs2, ntfs, reiserfs, reiser4, udf, ufs, and xfs.

gparted.desktop diff --git a/include/Makefile.am b/include/Makefile.am index 836edacb..fbd30ab6 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -53,6 +53,7 @@ noinst_HEADERS = \ TreeView_Detail.h \ Utils.h \ Win_GParted.h \ + bcachefs.h \ btrfs.h \ exfat.h \ ext2.h \ diff --git a/include/bcachefs.h b/include/bcachefs.h new file mode 100644 index 00000000..1766277a --- /dev/null +++ b/include/bcachefs.h @@ -0,0 +1,41 @@ +/* Copyright (C) 2024 Mike Fleetwood + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + + +#ifndef GPARTED_BCACHEFS_H +#define GPARTED_BCACHEFS_H + + +#include "FileSystem.h" +#include "OperationDetail.h" +#include "Partition.h" + + +namespace GParted +{ + + +class bcachefs : public FileSystem +{ +public: + FS get_filesystem_support(); + bool create(const Partition& new_partition, OperationDetail& operationdetail); +}; + + +} //GParted + +#endif /* GPARTED_BCACHEFS_H */ diff --git a/po/POTFILES.in b/po/POTFILES.in index a1d85cc1..51c3dffd 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -48,6 +48,7 @@ src/SWRaid_Info.cc src/TreeView_Detail.cc src/Utils.cc src/Win_GParted.cc +src/bcachefs.cc src/btrfs.cc src/exfat.cc src/ext2.cc diff --git a/src/Makefile.am b/src/Makefile.am index 200176a8..e04c173a 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -63,6 +63,7 @@ gpartedbin_SOURCES = \ TreeView_Detail.cc \ Utils.cc \ Win_GParted.cc \ + bcachefs.cc \ btrfs.cc \ exfat.cc \ ext2.cc \ diff --git a/src/SupportedFileSystems.cc b/src/SupportedFileSystems.cc index ca7a471d..c78b7715 100644 --- a/src/SupportedFileSystems.cc +++ b/src/SupportedFileSystems.cc @@ -18,6 +18,7 @@ #include "SupportedFileSystems.h" #include "FileSystem.h" #include "Utils.h" +#include "bcachefs.h" #include "btrfs.h" #include "exfat.h" #include "ext2.h" @@ -59,6 +60,7 @@ SupportedFileSystems::SupportedFileSystems() // supported_filesystem() -> false m_fs_objects[FS_UNKNOWN] = nullptr; m_fs_objects[FS_OTHER] = nullptr; + m_fs_objects[FS_BCACHEFS] = new bcachefs(); m_fs_objects[FS_BTRFS] = new btrfs(); m_fs_objects[FS_EXFAT] = new exfat(); m_fs_objects[FS_EXT2] = new ext2(FS_EXT2); diff --git a/src/Utils.cc b/src/Utils.cc index 83aaa037..2bc92269 100644 --- a/src/Utils.cc +++ b/src/Utils.cc @@ -435,6 +435,7 @@ const Glib::ustring Utils::get_filesystem_software(FSType fstype) { switch (fstype) { + case FS_BCACHEFS: return "bcachefs-tools"; case FS_BTRFS: return "btrfs-progs / btrfs-tools"; case FS_EXFAT: return "exfatprogs"; case FS_EXT2: return "e2fsprogs"; diff --git a/src/bcachefs.cc b/src/bcachefs.cc new file mode 100644 index 00000000..6c173926 --- /dev/null +++ b/src/bcachefs.cc @@ -0,0 +1,61 @@ +/* Copyright (C) 2024 Mike Fleetwood + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + + +#include "bcachefs.h" +#include "FileSystem.h" +#include "OperationDetail.h" +#include "Partition.h" +#include "Utils.h" + +# include +# include + + +namespace GParted +{ + + +FS bcachefs::get_filesystem_support() +{ + FS fs(FS_BCACHEFS); + + fs.busy = FS::GPARTED; + fs.move = FS::GPARTED; + fs.copy = FS::GPARTED; + fs.online_read = FS::GPARTED; + + if (! Glib::find_program_in_path("bcachefs").empty()) + { + fs.create = FS::EXTERNAL; + fs.create_with_label = FS::EXTERNAL; + } + + fs_limits.min_size = 16 * MEBIBYTE; + + return fs; +} + + +bool bcachefs::create(const Partition& new_partition, OperationDetail& operationdetail) +{ + return ! execute_command("bcachefs format -L " + Glib::shell_quote(new_partition.get_filesystem_label()) + + " " + Glib::shell_quote(new_partition.get_path()), + operationdetail, EXEC_CHECK_STATUS); +} + + +} //GParted diff --git a/tests/Makefile.am b/tests/Makefile.am index ccb64ed6..98562512 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -50,6 +50,7 @@ gparted_core_OBJECTS = \ $(top_builddir)/src/SupportedFileSystems.$(OBJEXT) \ $(top_builddir)/src/SWRaid_Info.$(OBJEXT) \ $(top_builddir)/src/Utils.$(OBJEXT) \ + $(top_builddir)/src/bcachefs.$(OBJEXT) \ $(top_builddir)/src/btrfs.$(OBJEXT) \ $(top_builddir)/src/exfat.$(OBJEXT) \ $(top_builddir)/src/ext2.$(OBJEXT) \ From b891498d0a1c87b933354081f8757271fd8f4c32 Mon Sep 17 00:00:00 2001 From: Mike Fleetwood Date: Wed, 20 Mar 2024 08:06:15 +0000 Subject: [PATCH 04/14] Add reading of bcachefs usage when mounted (!123) Currently bcachefs-tools only provides a method to report the file system usage while it is mounted. We won't make GParted mount a bcachefs to read it's usage as we want to keep GParted's scanning as a read-only activity. Therefore GParted can't report the usage of an unmounted bcachefs. # bcachefs format /dev/sdb1 # bcachefs fs usage /dev/sdb1 error opening /dev/sdb1: not a bcachefs filesystem # echo $? 1 # bcachefs fs usage --help bcachefs fs usage - display detailed filesystem usage Usage: bcachefs fs usage [OPTION]... ... # mount /dev/sdb1 /mnt/1 # bcachefs fs usage /mnt/1 Filesystem: a61a8302-9a79-4c24-a9e6-486e7fcc78f5 Size: 987842560 Used: 12713984 Online reserved: 0 Data type Required/total Durability Devices btree: 1/1 1 [sdb1] 1048576 (no label) (device 0): sdb1 rw data buckets fragmented free: 1061027840 8095 sb: 3149824 25 126976 journal: 8388608 64 btree: 1048576 8 user: 0 0 cached: 0 0 parity: 0 0 stripe: 0 0 need_gc_gens: 0 0 need_discard: 0 0 capacity: 1073741824 8192 # echo $? 0 Closes !123 - Add support for bcachefs, single device file systems only --- include/bcachefs.h | 1 + src/bcachefs.cc | 37 +++++++++++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+) diff --git a/include/bcachefs.h b/include/bcachefs.h index 1766277a..77f90b81 100644 --- a/include/bcachefs.h +++ b/include/bcachefs.h @@ -32,6 +32,7 @@ class bcachefs : public FileSystem { public: FS get_filesystem_support(); + void set_used_sectors(Partition& partition); bool create(const Partition& new_partition, OperationDetail& operationdetail); }; diff --git a/src/bcachefs.cc b/src/bcachefs.cc index 6c173926..ae649e52 100644 --- a/src/bcachefs.cc +++ b/src/bcachefs.cc @@ -40,6 +40,7 @@ FS bcachefs::get_filesystem_support() if (! Glib::find_program_in_path("bcachefs").empty()) { + fs.online_read = FS::EXTERNAL; fs.create = FS::EXTERNAL; fs.create_with_label = FS::EXTERNAL; } @@ -50,6 +51,42 @@ FS bcachefs::get_filesystem_support() } +void bcachefs::set_used_sectors(Partition& partition) +{ + // 'bcachefs fs usage' only reports usage for mounted file systems. + exit_status = Utils::execute_command("bcachefs fs usage " + Glib::shell_quote(partition.get_mountpoint()), + output, error, true); + if (exit_status != 0) + { + if (! output.empty()) + partition.push_back_message(output); + if (! error.empty()) + partition.push_back_message(error); + return; + } + + // Device specific free space in bytes + long long dev_free_bytes = -1; + Glib::ustring::size_type index = output.find("free:"); + if (index < output.length()) + sscanf(output.substr(index).c_str(), "free: %lld", &dev_free_bytes); + + // Device specific size in bytes + long long dev_capacity_bytes = -1; + index = output.find("capacity:"); + if (index < output.length()) + sscanf(output.substr(index).c_str(), "capacity: %lld", &dev_capacity_bytes); + + if (dev_free_bytes > -1 && dev_capacity_bytes > -1) + { + Sector fs_size = dev_capacity_bytes / partition.sector_size; + Sector fs_free = dev_free_bytes / partition.sector_size; + partition.set_sector_usage(fs_size, fs_free); + // Block size is not available in 'bcachefs fs usage' output. + } +} + + bool bcachefs::create(const Partition& new_partition, OperationDetail& operationdetail) { return ! execute_command("bcachefs format -L " + Glib::shell_quote(new_partition.get_filesystem_label()) + From 0da4f5999a1128667ec98f7c8ed0eb31d3cc590f Mon Sep 17 00:00:00 2001 From: Mike Fleetwood Date: Thu, 21 Mar 2024 09:14:33 +0000 Subject: [PATCH 05/14] Increase minimum bcachefs size to 32 MiB (!123) For bcachefs file systems 19 MiB and smaller, the available space is reported as a very large value. The calculation went negative in a 64-bit signed value but then was interpreted as an unsiged value. Writing any significant amount of data to the file system hangs. # truncate -s $((19*1024*1024)) /tmp/test.img # losetup --find --show /tmp/test.img /dev/loop0 # bcachefs format /dev/loop0 # mkdir /mnt/0 # mount /dev/loop0 /mnt/0 # strace -e statfs df -k /mnt/0 statfs("/mnt/0", {f_type=0xca451a4e, f_bsize=4096, f_blocks=2305843009213693856, f_bfree=2305843009213693600, f_bavail=35474507834056483, f_files=18446744073709529090, f_ffree=18446744073709529088, f_fsid={val=[0xddb6645d, 0x8560584]}, f_namelen=512, f_frsize=4096, f_flags=ST_VALID|ST_RELATIME}) = 0 Filesystem 1K-blocks Used Available Use% Mounted on /dev/loop0 9223372036854775424 1024 141898031336225932 1% /mnt/0 For a 20 MiB bcachefs the available space is 0 so the file system overhead is 100%. # umount /mnt/0 # truncate -s $((20*1024*1024)) /tmp/disk.img # losetup --set-capacity /dev/loop0 # bcachefs format --force /dev/loop0 # mount /dev/loop0 /mnt/0 # strace -e statfs df -k /mnt/0 statfs("/mnt/0", {f_type=0xca451a4e, f_bsize=512, f_blocks=1280, f_bfree=0, f_bavail=0, f_files=2, f_ffree=0, f_fsid={val=[0x6b3e4926, 0x33f99a32]}, f_namelen=512, f_frsize=512, f_flags=ST_VALID|ST_RELATIME}) = 0 Filesystem 1K-blocks Used Available Use% Mounted on /dev/loop0 640 640 0 100% /mnt/0 For a 32 MiB bcachefs the file system overhead is a more reasonable 9% so use this as the minimum bcachefs file system size. ... # truncate -s $((32*1024*1024)) /tmp/disk.img ... # strace -e statfs df -k /mnt/0 statfs("/mnt/0", {f_type=0xca451a4e, f_bsize=512, f_blocks=24832, f_bfree=22784, f_bavail=22433, f_files=182274, f_ffree=182272, f_fsid={val=[0xfdddedd3, 0xe90be3cb]}, f_namelen=512, f_frsize=512, f_flags=ST_VALID|ST_RELATIME}) = 0 Filesystem 1K-blocks Used Available Use% Mounted on /dev/loop0 12416 1024 11217 9% /mnt/0 Closes !123 - Add support for bcachefs, single device file systems only --- src/bcachefs.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bcachefs.cc b/src/bcachefs.cc index ae649e52..3660ed95 100644 --- a/src/bcachefs.cc +++ b/src/bcachefs.cc @@ -45,7 +45,7 @@ FS bcachefs::get_filesystem_support() fs.create_with_label = FS::EXTERNAL; } - fs_limits.min_size = 16 * MEBIBYTE; + fs_limits.min_size = 32 * MEBIBYTE; return fs; } From 6534bfa28d5286abbce8d1523194b364212d1704 Mon Sep 17 00:00:00 2001 From: Mike Fleetwood Date: Sat, 9 Mar 2024 21:03:06 +0000 Subject: [PATCH 06/14] Add bcachefs label and UUID reading (!123) Add reading of the bcachefs file system label, not the per device label, and the external UUID. These match what blkid reports. Example without a label: # bcachefs format /dev/sdb1 # bcachefs show-super /dev/sdb1 | egrep -i 'Label:|UUID:|Device:' External UUID: 3316bc9a-d129-42b6-a80e-9649874bca73 Internal UUID: 656eebe5-10a9-4f12-94c8-aab2fdc54732 Label: Device: 0 Label: (none) UUID: cd436a8d-82eb-4993-a317-b39ea0d6bd2e # blkid /dev/sdb1 /dev/sdb1: UUID="3316bc9a-d129-42b6-a80e-9649874bca73" BLOCK_SIZE="512" UUID_SUB="cd436a8d-82eb-4993-a317-b39ea0d6bd2e" TYPE="bcachefs" PARTUUID="7962e584-34c9-4088-8a00-a651af517089" Example with a label: # bcachefs format --force -L 'test label' /dev/sdb1 # bcachefs show-super /dev/sdb1 | egrep -i 'Label:|UUID:|Device:' External UUID: 3d7bdabe-2616-4545-affc-1aba0f8fb4a7 Internal UUID: 9cc95d3e-7991-4f78-9dd0-850cb9749e34 Label: test label Device: 0 Label: (none) UUID: 784d1bd0-5769-4fbb-ad32-07894d381bba # blkid /dev/sdb1 /dev/sdb1: UUID="3d7bdabe-2616-4545-affc-1aba0f8fb4a7" LABEL="test label" BLOCK_SIZE="512" UUID_SUB="784d1bd0-5769-4fbb-ad32-07894d381bba" TYPE="bcachefs" PARTUUID="7962e584-34c9-4088-8a00-a651af517089" Closes !123 - Add support for bcachefs, single device file systems only --- include/bcachefs.h | 2 ++ src/bcachefs.cc | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+) diff --git a/include/bcachefs.h b/include/bcachefs.h index 77f90b81..94a4d80f 100644 --- a/include/bcachefs.h +++ b/include/bcachefs.h @@ -34,6 +34,8 @@ public: FS get_filesystem_support(); void set_used_sectors(Partition& partition); bool create(const Partition& new_partition, OperationDetail& operationdetail); + void read_label(Partition& partition); + void read_uuid(Partition& partition); }; diff --git a/src/bcachefs.cc b/src/bcachefs.cc index 3660ed95..f8c1f082 100644 --- a/src/bcachefs.cc +++ b/src/bcachefs.cc @@ -43,6 +43,8 @@ FS bcachefs::get_filesystem_support() fs.online_read = FS::EXTERNAL; fs.create = FS::EXTERNAL; fs.create_with_label = FS::EXTERNAL; + fs.read_label = FS::EXTERNAL; + fs.read_uuid = FS::EXTERNAL; } fs_limits.min_size = 32 * MEBIBYTE; @@ -95,4 +97,38 @@ bool bcachefs::create(const Partition& new_partition, OperationDetail& operation } +void bcachefs::read_label(Partition& partition) +{ + exit_status = Utils::execute_command("bcachefs show-super " + Glib::shell_quote(partition.get_path()), + output, error, true); + if (exit_status != 0) + { + if (! output.empty()) + partition.push_back_message(output); + if (! error.empty()) + partition.push_back_message(error); + return; + } + + partition.set_filesystem_label(Utils::regexp_label(output, "^Label:[[:blank:]]*(.*)$")); +} + + +void bcachefs::read_uuid(Partition& partition) +{ + exit_status = Utils::execute_command("bcachefs show-super " + Glib::shell_quote(partition.get_path()), + output, error, true); + if (exit_status != 0) + { + if (! output.empty()) + partition.push_back_message(output); + if (! error.empty()) + partition.push_back_message(error); + return; + } + + partition.uuid = Utils::regexp_label(output, "^External UUID: *(" RFC4122_NONE_NIL_UUID_REGEXP ")"); +} + + } //GParted From 6e5f84c6416458199553ec37e68cc0db02305631 Mon Sep 17 00:00:00 2001 From: Mike Fleetwood Date: Sat, 16 Mar 2024 08:57:42 +0000 Subject: [PATCH 07/14] Erase Bcachefs backup super block (!123) GParted doesn't clear all bcachefs file system signatures. # truncate -s $((1*1024*1024*1024)) /tmp/disk.img # losetup --find --show /tmp/disk.img /dev/loop0 # bcachefs format /tmp/disk.img # wipefs /dev/loop0 DEVICE OFFSET TYPE UUID LABEL loop0 0x1018 bcachefs 15304edb-6dc4-476c-989e-74eaea6660e8 loop0 0x3ff00018 bcachefs 15304edb-6dc4-476c-989e-74eaea6660e8 Use GParted to format to cleared /dev/loop0. # wipefs /dev/loop0 DEVICE OFFSET TYPE UUID LABEL loop0 0x3ff00018 bcachefs 15304edb-6dc4-476c-989e-74eaea6660e8 The backup super block is located at -1 MiB before the end of the device, rounded down to the file system's bucket size [1], where the bucket size is one of: 128 KiB, 256 KiB, 512 KiB, 1024 KiB [2]. location = device size - 1 MiB = hex(1*1024*1024*1024 - 1*1024*1024) = 0x3ff00000 Bcachefs magic is at byte offset 24 (0x18) into the super block [3]. The backup super block was not erased because GParted only writes zeros from -512 KiB to the end of the device. It is necessary to clear old signatures before formatting with a new file system to avoid confusion from detection of multiple incompatible signatures [4][5]. Fix this by writing zeros over all possible locations of the bcachefs backup super block. [1] bcachefs-tools v1.6.4: c_src/libbcachefs.c:bch2_format() https://evilpiepirate.org/git/bcachefs-tools.git/tree/c_src/libbcachefs.c?h=v1.6.4#n313 [This code locates the backup super block at device size - 1 MiB rounded down to the bucket size.] 321 struct bch_sb_layout *l = &sb.sb->layout; 322 u64 backup_sb = size_sectors - (1 << l->sb_max_size_bits); 323 324 backup_sb = rounddown(backup_sb, i->bucket_size >> 9); [2] bcachefs-tools v1.6.4: c_src/libbcachefs.c:bch2_pick_bucket_size() https://evilpiepirate.org/git/bcachefs-tools.git/tree/c_src/libbcachefs.c?h=v1.6.4#n85 85 /* Want a bucket size of at least 128k, if possible: */ 86 bucket_size = max(bucket_size, 128ULL << 10); ... 94 /* max bucket size 1 mb */ 95 bucket_size = min(bucket_size * scale, 1ULL << 20); [3] bcachefs-tools v1.6.4: libcachefs/bcachefs_format.h:struct bch_sb https://evilpiepirate.org/git/bcachefs-tools.git/tree/libbcachefs/bcachefs_format.h?h=v1.6.4#n907 [4] 743968ef68085f6043e8fd569384c0747c8fc9e2 Add clearing of SWRaid metadata 0.90 and 1.0 super blocks (#756829) [5] 3c75f3f5b103bc158b0f70ea63459aa362b0bab8 Use wipefs to clear old signatures before creating new file systems (#688882) Closes !123 - Add support for bcachefs, single device file systems only --- src/GParted_Core.cc | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/GParted_Core.cc b/src/GParted_Core.cc index 4d955733..6abfb98a 100644 --- a/src/GParted_Core.cc +++ b/src/GParted_Core.cc @@ -3789,6 +3789,7 @@ bool GParted_Core::erase_filesystem_signatures( const Partition & partition, Ope // Not covered by the above are: // * Btrfs super block mirror copies // * One possible location of Promise FastTrack RAID super block + // * Bcachefs super block backup // // Btrfs super blocks are located at: 64 KiB, 64 MiB, 256 GiB and 1 PiB. The // super block at 64 KiB will be erased by the zeroing from offset 0. The super @@ -3803,6 +3804,16 @@ bool GParted_Core::erase_filesystem_signatures( const Partition & partition, Ope // location -3087 must be explicitly cleared. // util-linux v2.38.1: libblkid/src/subperblocks/promise_raid.c:probe_pdcraid() // https://git.kernel.org/pub/scm/utils/util-linux/util-linux.git/tree/libblkid/src/superblocks/promise_raid.c?h=v2.38.1#n27 + // + // Bcachefs super block backup is located at -1 MiB before the end of the device, + // rounded down to the file system's bucket size, where the bucket size is one of: + // 128 KiB, 256 KiB, 512 KiB or 1024 KiB. + // * bcachefs-tools v1.6.4: c_src/libbcachefs.c:bch2_format() + // https://evilpiepirate.org/git/bcachefs-tools.git/tree/c_src/libbcachefs.c?h=v1.6.4#n313 + // * bcachefs-tools v1.6.4: c_src/libbcachefs.c:bch2_pick_bucket_size() + // https://evilpiepirate.org/git/bcachefs-tools.git/tree/c_src/libbcachefs.c?h=v1.6.4#n85 + // * bcachefs-tools v1.6.4: libcachefs/bcachefs_format.h:struct bch_sb + // https://evilpiepirate.org/git/bcachefs-tools.git/tree/libbcachefs/bcachefs_format.h?h=v1.6.4#n907 struct { Byte_Value offset; // Negative offsets work backwards from the end of the partition Byte_Value rounding; // Minimum desired rounding for offset @@ -3814,6 +3825,10 @@ bool GParted_Core::erase_filesystem_signatures( const Partition & partition, Ope { 256LL * GIBIBYTE, 1LL , 4LL * KIBIBYTE }, // Btrfs super block mirror copy { 1LL * PEBIBYTE, 1LL , 4LL * KIBIBYTE }, // Btrfs super block mirror copy { -3087LL * 512LL , 1LL , 512LL }, // Promise FastTrack RAID super block + { -1LL * MEBIBYTE, 128LL * KIBIBYTE, 4LL * KIBIBYTE }, // Bcachefs backup super block + { -1LL * MEBIBYTE, 256LL * KIBIBYTE, 4LL * KIBIBYTE }, // Bcachefs backup super block + { -1LL * MEBIBYTE, 512LL * KIBIBYTE, 4LL * KIBIBYTE }, // Bcachefs backup super block + { -1LL * MEBIBYTE, 1LL * MEBIBYTE, 4LL * KIBIBYTE }, // Bcachefs backup super block { -512LL * KIBIBYTE, 256LL * KIBIBYTE, 768LL * KIBIBYTE } // Super blocks at end } ; for ( unsigned int i = 0 ; overall_success && i < sizeof( ranges ) / sizeof( ranges[0] ) ; i ++ ) From f38bebf6f29bcc27290dac1b633cb97f5b057c3a Mon Sep 17 00:00:00 2001 From: Mike Fleetwood Date: Sat, 23 Mar 2024 08:01:20 +0000 Subject: [PATCH 08/14] Avoid erasing the same range multiple times (!123) When the size of the partition being cleared is an exact multiple of MiBs, likely given that GParted aligns partitions to whole MiBs by default, then the same range will be zeroed 4 times in a row. Example operation details from clearing a partition look like this: Format /dev/sdb1 as cleared + calibrate /dev/sdb1 path: /dev/sdb1 (partition) start: 2048 end: 2099199 size: 2097152 (1.00 GiB) + clear old file system signatures in /dev/sdb1 write 512.00 KiB of zeros at byte offset 0 write 4.00 KiB of zeros at byte offset 67108864 write 512.00 B of zeros at byte offset 1072161280 >> write 4.00 KiB of zeros at byte offset 1072693248 >> write 4.00 KiB of zeros at byte offset 1072693248 >> write 4.00 KiB of zeros at byte offset 1072693248 >> write 4.00 KiB of zeros at byte offset 1072693248 write 512.00 KiB of zeros at byte offset 1073217536 + set partition type on /dev/sdb1 This is because the bcachefs backup super block is located at -1 MiB from the end of the device, rounded down by the bcachefs bucket size. The bucket size can be any of 128 KiB, 256 KiB, 512 KiB or 1 MiB, depending on the size of the bcachefs file system. So when the partition size is an exact multiple of MiBs all 4 possible rounding sizes result in the same offset. Avoid writing the same range of zeros multiple times by skipping a range if it is identical to the previous range. Closes !123 - Add support for bcachefs, single device file systems only --- src/GParted_Core.cc | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/GParted_Core.cc b/src/GParted_Core.cc index 6abfb98a..5e4b8611 100644 --- a/src/GParted_Core.cc +++ b/src/GParted_Core.cc @@ -3831,6 +3831,8 @@ bool GParted_Core::erase_filesystem_signatures( const Partition & partition, Ope { -1LL * MEBIBYTE, 1LL * MEBIBYTE, 4LL * KIBIBYTE }, // Bcachefs backup super block { -512LL * KIBIBYTE, 256LL * KIBIBYTE, 768LL * KIBIBYTE } // Super blocks at end } ; + Byte_Value prev_byte_offset = -1; + Byte_Value prev_byte_len = -1; for ( unsigned int i = 0 ; overall_success && i < sizeof( ranges ) / sizeof( ranges[0] ) ; i ++ ) { //Rounding is performed in multiples of the sector size because writes are in whole sectors. @@ -3879,6 +3881,10 @@ bool GParted_Core::erase_filesystem_signatures( const Partition & partition, Ope byte_len = partition .get_byte_length() - byte_offset ; } + if (byte_offset == prev_byte_offset && byte_len == prev_byte_len) + // Byte range identical to previous. Skip. + continue; + OperationDetail & od = operationdetail .get_last_child() ; Byte_Value written = 0LL ; bool zero_success = false ; @@ -3904,6 +3910,10 @@ bool GParted_Core::erase_filesystem_signatures( const Partition & partition, Ope written += amount ; } + // Save byte range for detection of following identical range. + prev_byte_offset = byte_offset; + prev_byte_len = byte_len; + od.get_last_child().set_success_and_capture_errors( zero_success ); } overall_success &= zero_success ; From 53682c6aa1e89fea7da7b07baea15c2a72fbc160 Mon Sep 17 00:00:00 2001 From: Mike Fleetwood Date: Sun, 17 Mar 2024 08:03:50 +0000 Subject: [PATCH 09/14] Add bcachefs growing (!123) Shrinking a bcachefs file system is not supported. # truncate -s $((1*1024*1024*1024)) /tmp/disk.img # losetup --find --show /tmp/disk.img /dev/loop0 # bcachefs format /dev/loop0 ... # bcachefs device resize /dev/loop0 $((1*1024*1024*1024 - 512)) Doing offline resize of /dev/loop0 mounting version 1.4: member_seq initializing new filesystem going read-write initializing freespace Shrinking not supported yet # echo $? 1 Growing a bcachefs file system is supported when unmounted. # truncate -s $((2*1024*1024*1024)) /tmp/disk.img # losetup --set-capacity /dev/loop0 # bcachefs device resize /dev/loop0 Doing offline resize of /dev/loop0 mounting version 1.6: btree_subvolume_children recovering from unclean shutdown journal read done, replaying entries 1-1 alloc_read... done stripes_read... done snapshots_read... done going read-write journal_replay... done resume_logged_ops... done delete_dead_inodes... done resizing /dev/loop0 to 16384 buckets # echo $? 0 # bcachefs show-super /dev/loop0 | egrep 'Device:|Size:' Device: 0 Size: 2.00 GiB Growing is also supported when mounted. # mount /dev/loop0 /mnt/0 # truncate -s $((3*1024*1024*1024)) /tmp/disk.img # losetup --set-capacity /dev/loop0 # bcachefs device resize /dev/loop0 Doing online resize of /dev/loop0 resizing /dev/loop0 to 24576 buckets # echo $? 0 # bcachefs show-super /dev/loop0 | egrep 'Device:|Size:' Device: 0 Size: 3.00 GiB Closes !123 - Add support for bcachefs, single device file systems only --- include/bcachefs.h | 1 + src/bcachefs.cc | 12 ++++++++++++ 2 files changed, 13 insertions(+) diff --git a/include/bcachefs.h b/include/bcachefs.h index 94a4d80f..b04744b9 100644 --- a/include/bcachefs.h +++ b/include/bcachefs.h @@ -36,6 +36,7 @@ public: bool create(const Partition& new_partition, OperationDetail& operationdetail); void read_label(Partition& partition); void read_uuid(Partition& partition); + bool resize(const Partition& partition_new, OperationDetail& operationdetail, bool fill_partition); }; diff --git a/src/bcachefs.cc b/src/bcachefs.cc index f8c1f082..1a6514ae 100644 --- a/src/bcachefs.cc +++ b/src/bcachefs.cc @@ -45,6 +45,11 @@ FS bcachefs::get_filesystem_support() fs.create_with_label = FS::EXTERNAL; fs.read_label = FS::EXTERNAL; fs.read_uuid = FS::EXTERNAL; + fs.grow = FS::EXTERNAL; +#ifdef ENABLE_ONLINE_RESIZE + if (Utils::kernel_version_at_least(3, 6, 0)) + fs.online_grow = FS::EXTERNAL; +#endif } fs_limits.min_size = 32 * MEBIBYTE; @@ -131,4 +136,11 @@ void bcachefs::read_uuid(Partition& partition) } +bool bcachefs::resize(const Partition& partition_new, OperationDetail& operationdetail, bool fill_partition) +{ + return ! execute_command("bcachefs device resize " + Glib::shell_quote(partition_new.get_path()), + operationdetail, EXEC_CHECK_STATUS); +} + + } //GParted From 7a00482ab95f7a74dfcf3174812b5b06898964c2 Mon Sep 17 00:00:00 2001 From: Mike Fleetwood Date: Sat, 6 Apr 2024 20:42:00 +0100 Subject: [PATCH 10/14] Add bcachefs checking (!123) [Only the options being used by GParted are quoted here from the help output. More options are available.] $ bcachefs fsck --help bcachefs fsck - filesystem check and repair Usage: bcachefs fsck [OPTION]... Options: -y Assume "yes" to all questions -f Force checking even if filesystem is marked clean -v Be verbose Closes !123 - Add support for bcachefs, single device file systems only --- include/bcachefs.h | 1 + src/bcachefs.cc | 8 ++++++++ 2 files changed, 9 insertions(+) diff --git a/include/bcachefs.h b/include/bcachefs.h index b04744b9..815c495f 100644 --- a/include/bcachefs.h +++ b/include/bcachefs.h @@ -37,6 +37,7 @@ public: void read_label(Partition& partition); void read_uuid(Partition& partition); bool resize(const Partition& partition_new, OperationDetail& operationdetail, bool fill_partition); + bool check_repair(const Partition& partition, OperationDetail& operationdetail); }; diff --git a/src/bcachefs.cc b/src/bcachefs.cc index 1a6514ae..21958290 100644 --- a/src/bcachefs.cc +++ b/src/bcachefs.cc @@ -50,6 +50,7 @@ FS bcachefs::get_filesystem_support() if (Utils::kernel_version_at_least(3, 6, 0)) fs.online_grow = FS::EXTERNAL; #endif + fs.check = FS::EXTERNAL; } fs_limits.min_size = 32 * MEBIBYTE; @@ -143,4 +144,11 @@ bool bcachefs::resize(const Partition& partition_new, OperationDetail& operation } +bool bcachefs::check_repair(const Partition& partition, OperationDetail& operationdetail) +{ + return ! execute_command("bcachefs fsck -f -y -v " + Glib::shell_quote(partition.get_path()), + operationdetail, EXEC_CHECK_STATUS); +} + + } //GParted From 26a3140d4be5d1e6e4a95d3c950b7994f1a7d51d Mon Sep 17 00:00:00 2001 From: Mike Fleetwood Date: Mon, 25 Mar 2024 21:15:10 +0000 Subject: [PATCH 11/14] Query usage of multi-device bcachefs file systems correctly Create an uneven used space multi-device bcachefs file system like this, where sdb1 is about 1/2 used and sdb2 is almost empty: # bcachefs format /dev/sdb1 # mount /dev/sdb1 /mnt/1 # dd if=/dev/zero bs=1M count=512 of=/mnt/1/zeros.bin # bcachefs device add /mnt/1 /dev/sdb2 GParted reports both devices as having the same usage: Partition File System Mount Point Size Used Unused Flags /dev/sdb1 bcachefs /mnt/1 1.00 GiB 526.00 MiB 498.00 MiB /dev/sdb2 bcachefs /mnt/1 1.00 GiB 526.00 MiB 498.00 MiB When in fact the used space is significantly different for each device: # bcachefs fs usage /mnt/1 | egrep ' \(device |free:|capacity:' (no label) (device 0): sdb1 rw free: 522190848 3984 capacity: 1073741824 8192 (no label) (device 1): sdb2 rw free: 1061945344 8102 capacity: 1073741824 8192 This is because bcachefs::set_used_sectors() is always searching for the first "free:" and "capacity:" figures. Fix by reading the figures for the correct device. --- src/bcachefs.cc | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/src/bcachefs.cc b/src/bcachefs.cc index 21958290..ece6ac25 100644 --- a/src/bcachefs.cc +++ b/src/bcachefs.cc @@ -16,6 +16,7 @@ #include "bcachefs.h" +#include "BlockSpecial.h" #include "FileSystem.h" #include "OperationDetail.h" #include "Partition.h" @@ -73,6 +74,35 @@ void bcachefs::set_used_sectors(Partition& partition) return; } + // Example output: + // # bcachefs fs usage /mnt/1 | egrep ' \(device |free:|capacity:' + // (no label) (device 0): sdb1 rw + // free: 522190848 3984 + // capacity: 1073741824 8192 + // (no label) (device 1): sdb2 rw + // free: 1061945344 8102 + // capacity: 1073741824 8192 + // + // Substring the output down to just the device section for this partition. + BlockSpecial wanted = BlockSpecial(partition.get_path()); + bool found = false; + Glib::ustring::size_type start_offset = output.find(" (device "); + while (start_offset != Glib::ustring::npos) + { + Glib::ustring device_name = Utils::regexp_label(output.substr(start_offset), + " \\(device [[:digit:]]+\\):[[:blank:]]+([[:graph:]]+)"); + Glib::ustring::size_type end_offset = output.find(" (device ", start_offset + 9); + if (wanted == BlockSpecial("/dev/" + device_name)) + { + output = output.substr(start_offset, end_offset - start_offset); + found = true; + break; + } + start_offset = end_offset; + } + if (! found) + return; + // Device specific free space in bytes long long dev_free_bytes = -1; Glib::ustring::size_type index = output.find("free:"); From 7b047ec6e8e7d69b4e65da188ccc6f8236a86ec2 Mon Sep 17 00:00:00 2001 From: Mike Fleetwood Date: Sat, 16 Mar 2024 21:35:19 +0000 Subject: [PATCH 12/14] Drop the 2 decimal places when printing values in bytes When printing a number of bytes using Utils::format_size() it always formatted the value with 2 decimal digits and an IEC multiplier. This can be seen in the details of any operation which includes clearing old file system signatures. Fragment of operation details: Format /dev/sdb1 as cleared + calibrate /dev/sdb1 + clear old file system signatures in /dev/sdb1 write 512.00 KiB of zeros at byte offset 0 write 4.00 KiB of zeros at byte offset 67108864 >> write 512.00 B of zeros at byte offset 132537184 write 4.00 KiB of zeros at byte offset 1072693248 write 512.00 KiB of zeros at byte offset 133593440 flush operating system cache of /dev/sdb1 It doesn't make sense to be reporting 100ths of a byte. So when values are below 1 KiB report numbers of bytes without any decimal digits. --- src/Utils.cc | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/Utils.cc b/src/Utils.cc index 2bc92269..4715efff 100644 --- a/src/Utils.cc +++ b/src/Utils.cc @@ -535,14 +535,17 @@ bool Utils::kernel_version_at_least( int major_ver, int minor_ver, int patch_ver Glib::ustring Utils::format_size( Sector sectors, Byte_Value sector_size ) { std::stringstream ss ; - ss << std::setiosflags( std::ios::fixed ) << std::setprecision( 2 ) ; + ss << std::setiosflags(std::ios::fixed); if ( (sectors * sector_size) < KIBIBYTE ) { + ss << std::setprecision(0); ss << sector_to_unit( sectors, sector_size, UNIT_BYTE ) ; return Glib::ustring::compose( _("%1 B"), ss .str() ) ; } - else if ( (sectors * sector_size) < MEBIBYTE ) + + ss << std::setprecision(2); + if (sectors * sector_size < MEBIBYTE) { ss << sector_to_unit( sectors, sector_size, UNIT_KIB ) ; return Glib::ustring::compose( _("%1 KiB"), ss .str() ) ; From e03fb233596314217c786b82dd859a55153ff76f Mon Sep 17 00:00:00 2001 From: Mike Fleetwood Date: Sat, 6 Apr 2024 08:05:04 +0100 Subject: [PATCH 13/14] Stop assigning a zero length string when constructing them Most of the code doesn't assign a zero length string when constructing a string object. However there were a few places where it did. This is unnecessary because Glib::ustring [1] and std::string [2] objects are constructed as the the empty string by default. [1] Glib::ustring::ustring() https://developer-old.gnome.org/glibmm/stable/classGlib_1_1ustring.html#a71802782f4c2c408ef7ac69c6564b370 "Glib::ustring::ustring() Default constructor, which creates an empty string. " [2] std::string::string https://cplusplus.com/reference/string/string/string/ "(1) empty string constructor (default constructor) Constructs an empty string, with a length of zero characters. " --- src/DMRaid.cc | 13 ++++++------- src/Dialog_Partition_Info.cc | 2 +- src/GParted_Core.cc | 3 +-- src/Win_GParted.cc | 4 ++-- src/f2fs.cc | 2 +- src/fat16.cc | 2 +- src/hfs.cc | 2 +- src/hfsplus.cc | 2 +- src/luks.cc | 2 +- src/lvm2_pv.cc | 2 +- src/ntfs.cc | 2 +- src/reiserfs.cc | 2 +- 12 files changed, 18 insertions(+), 20 deletions(-) diff --git a/src/DMRaid.cc b/src/DMRaid.cc index 4c6a6911..40f06331 100644 --- a/src/DMRaid.cc +++ b/src/DMRaid.cc @@ -210,12 +210,11 @@ void DMRaid::get_devices( std::vector & device_list ) Glib::ustring DMRaid::get_dmraid_name( const Glib::ustring & dev_path ) { //Retrieve name of dmraid device - Glib::ustring dmraid_name = "" ; - Glib::ustring regexp = "" ; + Glib::ustring dmraid_name; for ( unsigned int k=0; k < dmraid_devices .size(); k++ ) { - regexp = ".*(" + dmraid_devices[k] + ").*" ; + Glib::ustring regexp = ".*(" + dmraid_devices[k] + ").*"; if ( Utils::regexp_label( dev_path, regexp ) == dmraid_devices[k] ) dmraid_name = dmraid_devices[k] ; } @@ -256,7 +255,7 @@ void DMRaid::get_dmraid_dir_entries( const Glib::ustring & dev_path, std::vector Glib::ustring dmraid_name = get_dmraid_name( dev_path ) ; //Loop through the entries in the directory - Glib::ustring filename = "" ; + Glib::ustring filename; Glib::Dir dir( DEV_MAPPER_PATH ); while ( ( filename = dir .read_name() ) != "" ) { @@ -277,9 +276,9 @@ int DMRaid::get_partition_number( const Glib::ustring & partition_name ) Glib::ustring DMRaid::get_udev_dm_name( const Glib::ustring & dev_path ) { //Retrieve DM_NAME of device using udev information - Glib::ustring output = "" ; - Glib::ustring error = "" ; - Glib::ustring dm_name = "" ; + Glib::ustring output; + Glib::ustring error; + Glib::ustring dm_name; if (udevadm_found) Utils::execute_command( "udevadm info --query=all --name=" + Glib::shell_quote( dev_path ), diff --git a/src/Dialog_Partition_Info.cc b/src/Dialog_Partition_Info.cc index 5d659843..26214164 100644 --- a/src/Dialog_Partition_Info.cc +++ b/src/Dialog_Partition_Info.cc @@ -228,7 +228,7 @@ void Dialog_Partition_Info::Display_Info() Sector ptn_sectors = partition .get_sector_length() ; - Glib::ustring vgname = "" ; //Also used in partition status message + Glib::ustring vgname; if (filesystem_ptn.fstype == FS_LVM2_PV) vgname = LVM2_PV_Info::get_vg_name( filesystem_ptn.get_path() ); diff --git a/src/GParted_Core.cc b/src/GParted_Core.cc index 5e4b8611..51677793 100644 --- a/src/GParted_Core.cc +++ b/src/GParted_Core.cc @@ -1235,7 +1235,6 @@ FSType GParted_Core::detect_filesystem(const PedDevice *lp_device, const PedPart { g_assert(lp_device != nullptr); // Bug: Not initialised by call to ped_device_get() or ped_device_get_next() - Glib::ustring fsname = ""; Glib::ustring path; DMRaid dmraid; @@ -1257,7 +1256,7 @@ FSType GParted_Core::detect_filesystem(const PedDevice *lp_device, const PedPart // (Q2) FS_Info (blkid) file system detection // Blkid detects more signatures and generally has less limitations so use before // libparted detection, but it doesn't report anything for extended partitions. - fsname = FS_Info::get_fs_type( path ); + Glib::ustring fsname = FS_Info::get_fs_type(path); // (Q3) Libparted file system detection // Only used when blkid didn't report anything and only on partitions, not whole diff --git a/src/Win_GParted.cc b/src/Win_GParted.cc index a020cc87..33f7ceb0 100644 --- a/src/Win_GParted.cc +++ b/src/Win_GParted.cc @@ -3322,7 +3322,7 @@ void Win_GParted::activate_change_uuid() Gtk::MESSAGE_WARNING, Gtk::BUTTONS_OK, true ); - Glib::ustring tmp_msg = "" ; + Glib::ustring tmp_msg; for ( i = 1 ; filesystem_object->get_custom_text( CTEXT_CHANGE_UUID_WARNING, i ) != "" ; i++ ) { if ( i > 1 ) @@ -3564,7 +3564,7 @@ bool Win_GParted::remove_non_empty_lvm2_pv_dialog( const OperationType optype ) true, false, false, Gtk::ALIGN_START); grid->attach(*label_members, 0, 1, 1, 1); - Glib::ustring members_str = "" ; + Glib::ustring members_str; if ( ! members .empty() ) { for ( unsigned int i = 0 ; i < members .size() ; i ++ ) diff --git a/src/f2fs.cc b/src/f2fs.cc index a3b70061..86be6896 100644 --- a/src/f2fs.cc +++ b/src/f2fs.cc @@ -128,7 +128,7 @@ bool f2fs::create( const Partition & new_partition, OperationDetail & operationd bool f2fs::resize(const Partition & partition_new, OperationDetail & operationdetail, bool fill_partition) { - Glib::ustring size = ""; + Glib::ustring size; if (! fill_partition) // resize.f2fs works in sector size units of whatever device the file // system is currently stored on. diff --git a/src/fat16.cc b/src/fat16.cc index 84b8dd1a..5ff0f894 100644 --- a/src/fat16.cc +++ b/src/fat16.cc @@ -209,7 +209,7 @@ void fat16::read_label(Partition& partition) bool fat16::write_label( const Partition & partition, OperationDetail & operationdetail ) { - Glib::ustring cmd = "" ; + Glib::ustring cmd; if ( partition.get_filesystem_label().empty() ) cmd = "mlabel -c -i " + Glib::shell_quote(partition.get_path()) + " ::"; else diff --git a/src/hfs.cc b/src/hfs.cc index ac835b7e..c4221b40 100644 --- a/src/hfs.cc +++ b/src/hfs.cc @@ -57,7 +57,7 @@ FS hfs::get_filesystem_support() bool hfs::create( const Partition & new_partition, OperationDetail & operationdetail ) { - Glib::ustring cmd = ""; + Glib::ustring cmd; if( new_partition.get_filesystem_label().empty() ) cmd = "hformat " + Glib::shell_quote( new_partition.get_path() ); else diff --git a/src/hfsplus.cc b/src/hfsplus.cc index 1320e6a4..cbe4fe1a 100644 --- a/src/hfsplus.cc +++ b/src/hfsplus.cc @@ -55,7 +55,7 @@ FS hfsplus::get_filesystem_support() bool hfsplus::create( const Partition & new_partition, OperationDetail & operationdetail ) { - Glib::ustring cmd = ""; + Glib::ustring cmd; if( new_partition.get_filesystem_label().empty() ) cmd = "mkfs.hfsplus " + Glib::shell_quote( new_partition.get_path() ); else diff --git a/src/luks.cc b/src/luks.cc index 73c6dd57..1dc61bfc 100644 --- a/src/luks.cc +++ b/src/luks.cc @@ -151,7 +151,7 @@ bool luks::resize( const Partition & partition_new, OperationDetail & operationd } } - Glib::ustring size = ""; + Glib::ustring size; if ( ! fill_partition ) // Cryptsetup resize takes the size of the encryption mapping, not the // size of the underlying block device. Both device-mapper and cryptsetup diff --git a/src/lvm2_pv.cc b/src/lvm2_pv.cc index 3fad9a64..d6811172 100644 --- a/src/lvm2_pv.cc +++ b/src/lvm2_pv.cc @@ -105,7 +105,7 @@ bool lvm2_pv::create( const Partition & new_partition, OperationDetail & operati bool lvm2_pv::resize( const Partition & partition_new, OperationDetail & operationdetail, bool fill_partition ) { - Glib::ustring size = "" ; + Glib::ustring size; if ( ! fill_partition ) size = " --yes --setphysicalvolumesize " + Utils::num_to_str(partition_new.get_byte_length() / KIBIBYTE) + "K "; diff --git a/src/ntfs.cc b/src/ntfs.cc index f73b09cb..d249b352 100644 --- a/src/ntfs.cc +++ b/src/ntfs.cc @@ -190,7 +190,7 @@ bool ntfs::create( const Partition & new_partition, OperationDetail & operationd bool ntfs::resize( const Partition & partition_new, OperationDetail & operationdetail, bool fill_partition ) { bool success; - Glib::ustring size = "" ; + Glib::ustring size; if ( ! fill_partition ) size = " -s " + Utils::num_to_str(partition_new.get_byte_length()); Glib::ustring cmd = "ntfsresize --force --force" + size ; diff --git a/src/reiserfs.cc b/src/reiserfs.cc index 50602547..43aa3a63 100644 --- a/src/reiserfs.cc +++ b/src/reiserfs.cc @@ -176,7 +176,7 @@ bool reiserfs::create( const Partition & new_partition, OperationDetail & operat bool reiserfs::resize( const Partition & partition_new, OperationDetail & operationdetail, bool fill_partition ) { - Glib::ustring size = "" ; + Glib::ustring size; if ( ! fill_partition ) size = " -s " + Utils::num_to_str(partition_new.get_byte_length()); const Glib::ustring resize_cmd = "echo y | resize_reiserfs" + size + From 69fa0beabab9d8184c0cbf5c79fed31dd55b1a7f Mon Sep 17 00:00:00 2001 From: Mike Fleetwood Date: Sat, 6 Apr 2024 08:17:40 +0100 Subject: [PATCH 14/14] Use Glib::build_path() to simplify remove_non_empty_lvm2_pv_dialog() Simplify code in Win_GParted::remove_non_empty_lvm2_pv_dialog() by replacing open coded concatenation of a vector of strings using a new line separator with a call to Glib::build_path(). --- src/Win_GParted.cc | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/src/Win_GParted.cc b/src/Win_GParted.cc index 33f7ceb0..cd72432c 100644 --- a/src/Win_GParted.cc +++ b/src/Win_GParted.cc @@ -3563,18 +3563,8 @@ bool Win_GParted::remove_non_empty_lvm2_pv_dialog( const OperationType optype ) Gtk::Label *label_members = Utils::mk_label("" + Glib::ustring(members_label) + "", true, false, false, Gtk::ALIGN_START); grid->attach(*label_members, 0, 1, 1, 1); - - Glib::ustring members_str; - if ( ! members .empty() ) - { - for ( unsigned int i = 0 ; i < members .size() ; i ++ ) - { - if ( i > 0 ) - members_str += "\n" ; - members_str += members[i] ; - } - } - Gtk::Label *value_members = Utils::mk_label(members_str, true, false, true, Gtk::ALIGN_START); + Gtk::Label *value_members = Utils::mk_label(Glib::build_path("\n", members), + true, false, true, Gtk::ALIGN_START); grid->attach(*value_members, 1, 1, 1, 1); value_members->get_accessible()->add_relationship(Atk::RELATION_LABELLED_BY, label_members->get_accessible());