1
0
mirror of https://gitlab.gnome.org/GNOME/gparted synced 2024-06-30 23:05:09 +00:00

Compare commits

...

13 Commits

Author SHA1 Message Date
Mike Fleetwood
3d36d7ed2b While space tidy-up of Utils::get_filesystem_maxlength()
Use smart tab alignment; indent with tabs and align with spaces.  Also
remove entries for lvm2 pv and minix which don't support labels, adding
a comment as to why.
2024-04-12 21:42:37 +01:00
Mike Fleetwood
3ebeadf050 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().
2024-04-12 08:02:41 +01:00
Mike Fleetwood
61ac1a416f 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.
        "
2024-04-12 08:02:35 +01:00
Mike Fleetwood
cc65eef59a 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.
2024-04-12 08:02:30 +01:00
Mike Fleetwood
a621623326 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.
2024-04-12 08:02:25 +01:00
Mike Fleetwood
3b5da02943 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]... <device>

    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
2024-04-12 08:02:20 +01:00
Mike Fleetwood
31df2f2b75 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
2024-04-12 08:02:16 +01:00
Mike Fleetwood
f027809e73 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
2024-04-12 08:02:06 +01:00
Mike Fleetwood
76b27b9f7a 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] 743968ef68
    Add clearing of SWRaid metadata 0.90 and 1.0 super blocks (#756829)
[5] 3c75f3f5b1
    Use wipefs to clear old signatures before creating new file systems (#688882)

Closes !123 - Add support for bcachefs, single device file systems only
2024-04-12 08:02:00 +01:00
Mike Fleetwood
b8304a141a 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
2024-04-12 08:01:55 +01:00
Mike Fleetwood
aabba99594 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
2024-04-12 08:01:50 +01:00
Mike Fleetwood
ccdf14ddb4 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]... <mountpoint>
    ...
    # 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
2024-04-12 08:01:45 +01:00
Mike Fleetwood
7ca99a1577 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
2024-04-12 07:54:10 +01:00
22 changed files with 334 additions and 78 deletions

1
README
View File

@ -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

View File

@ -18,9 +18,9 @@
data rescue from lost partitions.
</p>
<p>
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.
</p>
</description>
<launchable type="desktop-id">gparted.desktop</launchable>

View File

@ -53,6 +53,7 @@ noinst_HEADERS = \
TreeView_Detail.h \
Utils.h \
Win_GParted.h \
bcachefs.h \
btrfs.h \
exfat.h \
ext2.h \

46
include/bcachefs.h Normal file
View File

@ -0,0 +1,46 @@
/* 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 <http://www.gnu.org/licenses/>.
*/
#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();
void set_used_sectors(Partition& partition);
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);
bool check_repair(const Partition& partition, OperationDetail& operationdetail);
};
} //GParted
#endif /* GPARTED_BCACHEFS_H */

View File

@ -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

View File

@ -210,12 +210,11 @@ void DMRaid::get_devices( std::vector<Glib::ustring> & 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 ),

View File

@ -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() );

View File

@ -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
@ -3789,6 +3788,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 +3803,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,8 +3824,14 @@ 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
} ;
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.
@ -3864,6 +3880,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 ;
@ -3889,6 +3909,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 ;

View File

@ -63,6 +63,7 @@ gpartedbin_SOURCES = \
TreeView_Detail.cc \
Utils.cc \
Win_GParted.cc \
bcachefs.cc \
btrfs.cc \
exfat.cc \
ext2.cc \

View File

@ -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);

View File

@ -256,53 +256,54 @@ int Utils::get_max_partition_name_length( Glib::ustring & tabletype )
int Utils::get_filesystem_label_maxlength(FSType fstype)
{
// Only file systems which can have labels, either set when created or changed
// afterwards, need a maximum length defining.
switch (fstype)
{
//All file systems commented out are not supported for labelling
// by either the new partition or label partition operations.
case FS_BTRFS : return 255 ;
case FS_EXFAT : return 11;
case FS_EXT2 : return 16 ;
case FS_EXT3 : return 16 ;
case FS_EXT4 : return 16 ;
case FS_BCACHEFS: return 32;
case FS_BTRFS: return 255;
case FS_EXFAT: return 11;
case FS_EXT2: return 16;
case FS_EXT3: return 16;
case FS_EXT4: return 16;
// mkfs.f2fs supports labels up to 512 characters, however only blkid is
// used to read the label and that only displays the first 127 characters.
case FS_F2FS : return 127;
case FS_FAT16 : return 11 ;
case FS_FAT32 : return 11 ;
//mkfs.hfsplus can create hfs and hfs+ file systems with labels up to 255
// characters. However there is no specific tool to read the labels and
// blkid, the only tool currently available, only display the first 27
// and 63 character respectively.
// Reference:
// util-linux-2.20.1/libblkid/src/superblocks/hfs.c:struct hfs_mdb
case FS_HFS : return 27 ;
case FS_HFSPLUS : return 63 ;
//mkfs.jfs and jfs_tune can create and update labels to 16 characters but
// only displays the first 11 characters. This is because version 1 jfs
// file systems only have an 11 character field for the label but version
// 2 jfs has extra fields containing a 16 character label. mkfs.jfs
// writes the extra fields containing the 16 character label, but then
// sets it to version 1 jfs. It does this to be backwardly compatible
// with jfs before 1.0.18, released May 2002. Blkid does display the
// full 16 character label by just ignoring the file system version.
// As using jfs_tune to get the label stick with an 11 character limit.
// References:
// jfsutils-1.1.15/tune/tune.c:main()
// jfsutils-1.1.15/mkfs/mkfs.c:create_aggregate()
// http://jfs.cvs.sourceforge.net/viewvc/jfs/jfsutils/NEWS?revision=HEAD
case FS_JFS : return 11 ;
case FS_LINUX_SWAP : return 15 ;
//case FS_LVM2_PV : return ;
case FS_MINIX : return 0; // MINIX doesn't support labelling.
case FS_NILFS2 : return 80 ;
case FS_NTFS : return 128 ;
case FS_REISER4 : return 16 ;
case FS_REISERFS : return 16 ;
case FS_UDF : return 126; // and only 63 if label contains character above U+FF
case FS_XFS : return 12 ;
case FS_F2FS: return 127;
case FS_FAT16: return 11;
case FS_FAT32: return 11;
default : return 30 ;
// mkfs.hfsplus can create hfs and hfs+ file systems with labels up to 255
// characters. However there is no specific tool to read the labels and
// blkid, the only tool currently available, only display the first 27 and
// 63 character respectively.
// Reference:
// util-linux-2.20.1/libblkid/src/superblocks/hfs.c:struct hfs_mdb
case FS_HFS: return 27;
case FS_HFSPLUS: return 63;
// mkfs.jfs and jfs_tune can create and update labels to 16 characters but
// only displays the first 11 characters. This is because version 1 jfs
// file systems only have an 11 character field for the label but version
// 2 jfs has extra fields containing a 16 character label. mkfs.jfs
// writes the extra fields containing the 16 character label, but then
// sets it to version 1 jfs. It does this to be backwardly compatible
// with jfs before 1.0.18, released May 2002. Blkid does display the full
// 16 character label by just ignoring the file system version. As using
// jfs_tune to read the label stick with an 11 character limit.
// References:
// jfsutils-1.1.15/tune/tune.c:main()
// jfsutils-1.1.15/mkfs/mkfs.c:create_aggregate()
// http://jfs.cvs.sourceforge.net/viewvc/jfs/jfsutils/NEWS?revision=HEAD
case FS_JFS: return 11;
case FS_LINUX_SWAP: return 15;
case FS_NILFS2: return 80;
case FS_NTFS: return 128;
case FS_REISER4: return 16;
case FS_REISERFS: return 16;
case FS_UDF: return 126; // and only 63 if label contains character above U+FF
case FS_XFS: return 12;
default: return 30;
}
}
@ -408,6 +409,7 @@ const Glib::ustring Utils::get_filesystem_kernel_name( FSType fstype )
{
switch ( fstype )
{
case FS_BCACHEFS : return "bcachefs";
case FS_BTRFS : return "btrfs";
case FS_EXFAT : return "exfat";
case FS_EXT2 : return "ext2";
@ -435,6 +437,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";
@ -534,14 +537,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() ) ;

View File

@ -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 )
@ -3563,18 +3563,8 @@ bool Win_GParted::remove_non_empty_lvm2_pv_dialog( const OperationType optype )
Gtk::Label *label_members = Utils::mk_label("<b>" + Glib::ustring(members_label) + "</b>",
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());

184
src/bcachefs.cc Normal file
View File

@ -0,0 +1,184 @@
/* 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 <http://www.gnu.org/licenses/>.
*/
#include "bcachefs.h"
#include "BlockSpecial.h"
#include "FileSystem.h"
#include "OperationDetail.h"
#include "Partition.h"
#include "Utils.h"
# include <glibmm/miscutils.h>
# include <glibmm/shell.h>
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.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.grow = FS::EXTERNAL;
#ifdef ENABLE_ONLINE_RESIZE
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;
return fs;
}
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;
}
// 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:");
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()) +
" " + Glib::shell_quote(new_partition.get_path()),
operationdetail, EXEC_CHECK_STATUS);
}
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 ")");
}
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);
}
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

View File

@ -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.

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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 ";

View File

@ -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 ;

View File

@ -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 +

View File

@ -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) \