[gparted] Calculate unmounted JFS size accurately (!50)



commit e55d10b91973e8b73c9a55c6c488d2c79c5718ac
Author: Mike Fleetwood <mike fleetwood googlemail com>
Date:   Tue Nov 5 11:32:05 2019 +0000

    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() ),


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]