[gparted] Calculate mounted JFS size accurately (!50)
- From: Curtis Gedak <gedakc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gparted] Calculate mounted JFS size accurately (!50)
- Date: Thu, 14 Nov 2019 18:37:49 +0000 (UTC)
commit 2c0572e29668aae86ed1e7e7c96cf99b5d6eafca
Author: Mike Fleetwood <mike fleetwood googlemail com>
Date: Fri Nov 8 14:01:11 2019 +0000
Calculate mounted JFS size accurately (!50)
With the same minimum sized 16 MiB JFS used in the previous commit, now
mounted, GParted once again reports 1.20 MiB of unallocated space. This
is because the kernel JFS driver is also just reporting the size of the
Aggregate Disk Map (dmap) as the size of the file system [1].
Fix by reading the on disk JFS superblock to calculate the size of the
file system, but query the free space from the kernel using statvfs().
Need to query mounted JFS free space from the kernel because the on disk
dmap is not updated immediately so doesn't reflect recently used or
freed disk space.
For example, start with the 16 MiB JFS empty and mounted.
# echo -e 'dmap\nx\nquit' | jfs_debugfs /dev/sdb1 | fgrep dn_nfree
[2] dn_nfree: 0x00000000eaa [10] dn_agwidth: 1
# df -k /mnt/1
Filesystem 1K-blocks Used Available Use% Mounted on
/dev/sdb1 15152 136 15016 1% /mnt/1
Write 10 MiB of data to it:
# dd if=/dev/zero bs=1M count=10 of=/mnt/1/file_10M
10+0 records in
10+0 records out
1048760 bytes (10 MB, 10 MiB) copied, 0.0415676 s, 252 MB/s
Query the file system free space from the kernel and by reading the on
disk dmap figure:
# df -k /mnt/1
Filesystem 1K-blocks Used Available Use% Mounted on
/dev/sdb1 15152 10376 4776 69% /mnt/1
# echo -e 'dmap\nx\nquit' | jfs_debugfs /dev/sdb1 | fgrep dn_nfree
[2] dn_nfree: 0x00000000eaa [10] dn_agwidth: 1
# sync
# echo -e 'dmap\nx\nquit' | jfs_debugfs /dev/sdb1 | fgrep dn_nfree
[2] dn_nfree: 0x00000000eaa [10] dn_agwidth: 1
# umount /mnt/1
# echo -e 'dmap\nx\nquit' | jfs_debugfs /dev/sdb1 | fgrep dn_nfree
[2] dn_nfree: 0x000000004aa [10] dn_agwidth: 1
The kernel reports the updated usage straight away, but the on disk dmap
record doesn't get updated even by sync, only after unmounting.
This is the same fix as was previously done for EXT2/3/4 [2].
[1] Linux jfs_statfs() function
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/fs/jfs/super.c?h=v3.10#n142
[2] 3828019030f981cc5b3411badc40704f5525fdb3
Read file system size for mounted ext2/3/4 from superblock (#683255)
Closes !50 - Calculate JFS size accurately
src/jfs.cc | 52 ++++++++++++++++++++++++++++++++++++++++------------
1 file changed, 40 insertions(+), 12 deletions(-)
---
diff --git a/src/jfs.cc b/src/jfs.cc
index 309832be..fa773b9d 100644
--- a/src/jfs.cc
+++ b/src/jfs.cc
@@ -34,6 +34,7 @@ FS jfs::get_filesystem_support()
if ( ! Glib::find_program_in_path( "jfs_debugfs" ) .empty() ) {
fs.read = FS::EXTERNAL;
+ fs.online_read = FS::EXTERNAL;
}
if ( ! Glib::find_program_in_path( "jfs_tune" ) .empty() ) {
@@ -67,7 +68,6 @@ FS jfs::get_filesystem_support()
fs.copy = FS::GPARTED;
}
- fs .online_read = FS::GPARTED ;
#ifdef ENABLE_ONLINE_RESIZE
if ( Utils::kernel_version_at_least( 3, 6, 0 ) )
fs .online_grow = fs .grow ;
@@ -81,6 +81,11 @@ FS jfs::get_filesystem_support()
void jfs::set_used_sectors( Partition & partition )
{
+ // Called when the file system is unmounted *and* when mounted. Always reads the
+ // on disk superblock using jfs_debugfs to accurately calculate the overall size
+ // of the file system. Read free space from the kernel via statvfs() when mounted
+ // for the up to date figure, and from the on disk Aggregate Disk Map (dmap) when
+ // unmounted.
exit_status = Utils::execute_command("jfs_debugfs " + Glib::shell_quote(partition.get_path()),
"superblock\nx\ndmap\nx\nquit\n", output, error, true);
if (exit_status != 0)
@@ -122,20 +127,43 @@ void jfs::set_used_sectors( Partition & partition )
if (index < output.length())
sscanf(output.substr(index).c_str(), "s_fsckpxd.len: %lld", &fsck_len);
- // dn_nfree - Number of free (s_bsize) blocks in Aggregate
- long long free_blocks = -1;
- index = output.find("dn_nfree:");
- if (index < output.length())
- sscanf(output.substr(index).c_str(), "dn_nfree: %llx", &free_blocks);
+ Sector fs_size_sectors = -1;
+ if (agg_size > -1 && agg_block_size > -1 && phys_block_size > -1 && log_len > -1 && fsck_len > -1)
+ {
+ fs_size_sectors = ( agg_size * phys_block_size
+ + log_len * agg_block_size
+ + fsck_len * agg_block_size) / partition.sector_size;
+ }
- if (agg_size > -1 && agg_block_size > -1 && phys_block_size > -1 &&
- log_len > -1 && fsck_len > -1 && free_blocks > -1 )
+ Sector fs_free_sectors = -1;
+ if (partition.busy)
{
- Sector fs_size_sectors = ( agg_size * phys_block_size
- + log_len * agg_block_size
- + fsck_len * agg_block_size) / partition.sector_size;
- Sector fs_free_sectors = free_blocks * agg_block_size / partition.sector_size;
+ Byte_Value ignored;
+ Byte_Value fs_free_bytes;
+ if (Utils::get_mounted_filesystem_usage(partition.get_mountpoint(), ignored, fs_free_bytes,
error) != 0)
+ {
+ partition.push_back_message(error);
+ return;
+ }
+ fs_free_sectors = fs_free_bytes / partition.sector_size;
+ }
+ else // (! partition.busy)
+ {
+ // dn_nfree - Number of free (s_bsize) blocks in Aggregate
+ long long free_blocks = -1;
+ index = output.find("dn_nfree:");
+ if (index < output.length())
+ sscanf(output.substr(index).c_str(), "dn_nfree: %llx", &free_blocks);
+
+ if (agg_block_size && free_blocks > -1)
+ {
+ fs_free_sectors = free_blocks * agg_block_size / partition.sector_size;
+ }
+ }
+
+ if (fs_size_sectors > -1 && fs_free_sectors > -1 && agg_block_size > -1)
+ {
partition.set_sector_usage(fs_size_sectors, fs_free_sectors);
partition.fs_block_size = agg_block_size;
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]