From e55d10b91973e8b73c9a55c6c488d2c79c5718ac Mon Sep 17 00:00:00 2001 From: Mike Fleetwood Date: Tue, 5 Nov 2019 11:32:05 +0000 Subject: [PATCH] Calculate unmounted JFS size accurately (!50) Create the smallest possible JFS (16 MiB) and GParted will report 1.2 MiB of unallocated space. This is because the size of the Aggregate Disk Map (dmap) was used as the size of the file system. However after reading the source code to mkfs.jfs, it separately accounts for the size of the Log (Journal) and the FSCK Working Space. The size of a JFS is the sum of these 3 components added together. Using the minimum 16 MiB JFS as an example: # jfs_debugfs /dev/sdb1 jfs_debugfs version 1.1.15, 04-Mar-2011 Aggregate Block Size: 4096 > superblock [1] s_magic: 'JFS1' [15] s_ait2.addr1: 0x00 [2] s_version: 1 [16] s_ait2.addr2: 0x00000018 [3] s_size: 0x0000000000007660 s_ait2.address: 24 [4] s_bsize: 4096 [17] s_logdev: 0x00000000 [5] s_l2bsize: 12 [18] s_logserial: 0x00000000 [6] s_l2bfactor: 3 [19] s_logpxd.len: 256 [7] s_pbsize: 512 [20] s_logpxd.addr1: 0x00 [8] s_l2pbsize: 9 [21] s_logpxd.addr2: 0x00000f00 [9] pad: Not Displayed s_logpxd.address: 3840 [10] s_agsize: 0x00002000 [22] s_fsckpxd.len: 52 [11] s_flag: 0x10200900 [23] s_fsckpxd.addr1: 0x00 JFS_LINUX [24] s_fsckpxd.addr2: 0x00000ecc JFS_COMMIT JFS_GROUPCOMMIT s_fsckpxd.address: 3788 JFS_INLINELOG [25] s_time.tv_sec: 0x5dbbdfa0 [26] s_time.tv_nsec: 0x00000000 [27] s_fpack: 'small_jfs' [12] s_state: 0x00000000 FM_CLEAN [13] s_compress: 0 [14] s_ait2.len: 4 display_super: [m]odify or e[x]it: x > dmap Block allocation map control page at block 16 [1] dn_mapsize: 0x00000000ecc [9] dn_agheigth: 0 [2] dn_nfree: 0x00000000eaa [10] dn_agwidth: 1 [3] dn_l2nbperpage: 0 [11] dn_agstart: 341 [4] dn_numag: 1 [12] dn_agl2size: 13 [5] dn_maxlevel: 0 [13] dn_agfree: type 'f' [6] dn_maxag: 0 [14] dn_agsize: 8192 [7] dn_agpref: 0 [15] pad: Not Displayed [8] dn_aglevel: 0 display_dbmap: [m]odify, [f]ree count, [t]ree, e[x]it > x > quit Values of interest: s_size - Aggregate size in device (s_pbsize) blocks s_bsize - Aggregate block (aka file system allocation) size in bytes s_pbsize - Physical (device) block size in bytes s_logpxd.len - Log (Journal) size in Aggregate (s_bsize) blocks s_fsckpxd.len - FSCK Working Space in Aggregate (s_bsize) blocks dn_nfree - Number of free (s_bsize) blocks in Aggregate Calculation: file system size = s_size * s_pbsize + s_logpxd.len * s_bsize + s_fsckpxd.len * s_bsize = 30304 * 512 + 256 * 4096 + 52 * 4096 = 16777216 (Exactly 16 MiB. The size of the partition.) free space = dn_nfree * s_bsize = 3754 * 4096 = 15376384 Rewrite JFS usage querying code to use this updated calculation. [1] JFS Overview / How the Journaled File System cuts system restart times to the quick http://jfs.sourceforge.net/project/pub/jfs.pdf [2] JFS Layout / How the Journaled File systems handles the on-disk layout http://jfs.sourceforge.net/project/pub/jfslayout.pdf [3] mkfs.jfs source code http://jfs.sourceforge.net/project/pub/jfsutils-1.1.15.tar.gz mkfs/mkfs.c Selected lines from mkfs/mkfs.c create_aggregate(..., number_of_blocks, ..., logsize, ...) number_of_blocks -= fsck_wspace_length; aggr_superblock.s_size = number_of_blocks * (aggr_block_size / phys_block_size); aggr_superblock.s_bsize = aggr_block_size; aggr_superblock.s_pbsize = phys_block_size; PXDlength(&aggr_superblock.s_logpxd, logsize); PXDlength(&aggr_superblock.s_fsckpxd, fsck_wspace_length); main() number_of_bytes = bytes_on_device; number_of_blocks = number_of_bytes / agg_block_size; logsize = logsize_in_bytes / aggr_block_size; number_of_blocks -= logsize; create_aggregate(..., number_of_blocks, ..., logsize, ...); Closes !50 - Calculate JFS size accurately --- src/jfs.cc | 89 ++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 56 insertions(+), 33 deletions(-) diff --git a/src/jfs.cc b/src/jfs.cc index 64643d87..309832be 100644 --- a/src/jfs.cc +++ b/src/jfs.cc @@ -78,47 +78,70 @@ FS jfs::get_filesystem_support() return fs ; } + void jfs::set_used_sectors( Partition & partition ) { - const Glib::ustring jfs_debug_cmd = "jfs_debugfs " + Glib::shell_quote( partition.get_path() ); - if (! Utils::execute_command(jfs_debug_cmd, "dmap\nx\nquit\n", output, error, true)) + 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) { - //blocksize - Glib::ustring::size_type index = output.find( "Block Size:" ); - if ( index >= output .length() || - sscanf( output.substr( index ).c_str(), "Block Size: %lld", &S ) != 1 ) - S = -1 ; - - //total blocks - index = output .find( "dn_mapsize:" ) ; - if ( index >= output .length() || - sscanf( output.substr( index ).c_str(), "dn_mapsize: %llx", &T ) != 1 ) - T = -1 ; - - //free blocks - index = output .find( "dn_nfree:" ) ; - if ( index >= output .length() || - sscanf( output.substr( index ).c_str(), "dn_nfree: %llx", &N ) != 1 ) - N = -1 ; - - if ( T > -1 && N > -1 && S > -1 ) - { - T = Utils::round( T * ( S / double(partition .sector_size) ) ) ; - N = Utils::round( N * ( S / double(partition .sector_size) ) ) ; - partition .set_sector_usage( T, N ) ; - partition.fs_block_size = S; - } + if (! output.empty()) + partition.push_back_message(output); + if (! error.empty()) + partition.push_back_message(error); + return; } - else + + // s_size - Aggregate size in device (s_pbsize) blocks + long long agg_size = -1; + Glib::ustring::size_type index = output.find("s_size:"); + if (index < output.length()) + sscanf(output.substr(index).c_str(), "s_size: %llx", &agg_size); + + // s_bsize - Aggregate block (aka file system allocation) size in bytes + long long agg_block_size = -1; + index = output.find("s_bsize:"); + if (index < output.length()) + sscanf(output.substr(index).c_str(), "s_bsize: %lld", &agg_block_size); + + // s_pbsize - Physical (device) block size in bytes + long long phys_block_size = -1; + index = output.find("s_pbsize:"); + if (index < output.length()) + sscanf(output.substr(index).c_str(), "s_pbsize: %lld", &phys_block_size); + + // s_logpxd.len - Log (Journal) size in Aggregate (s_bsize) blocks + long long log_len = -1; + index = output.find("s_logpxd.len:"); + if (index < output.length()) + sscanf(output.substr(index).c_str(), "s_logpxd.len: %lld", &log_len); + + // s_fsckpxd.len - FSCK Working Space in Aggregate (s_bsize) blocks + long long fsck_len = -1; + index = output.find("s_fsckpxd.len:"); + 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); + + if (agg_size > -1 && agg_block_size > -1 && phys_block_size > -1 && + log_len > -1 && fsck_len > -1 && free_blocks > -1 ) { - if ( ! output .empty() ) - partition.push_back_message( output ); - - if ( ! error .empty() ) - partition.push_back_message( error ); + 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; + + partition.set_sector_usage(fs_size_sectors, fs_free_sectors); + partition.fs_block_size = agg_block_size; } } + void jfs::read_label( Partition & partition ) { if ( ! Utils::execute_command( "jfs_tune -l " + Glib::shell_quote( partition.get_path() ),