Commit ef4d4cb1 authored by Mike Fleetwood's avatar Mike Fleetwood Committed by Curtis Gedak

Switch to faster ntfsinfo to read NTFS usage (#47)

A user reported GParted was slow to refresh and timing ntfsresize to
query his file systems found that it was taking 4.7 seconds and 9.2
seconds for sizes 31.7 GiB and 49 GiB NTFS file systems respectively.
Almost 14 seconds just to read the usage.

Created a 4 GiB NTFS and filled it with as many 4 KiB files as possible,
just over 800,000 files.

    # df -k /mnt/2
    Filesystem     1K-blocks    Used Available Use% Mounted on
    /dev/sdb2        4194300 4193860       440 100% /mnt/2
    # df -i /mnt/2
    Filesystem     Inodes  IUsed IFree IUse% Mounted on
    /dev/sdb2      819640 808591 11049   99% /mnt/2

Testing perform of ntfsresize:

    # time ntfsresize --info --force --no-progress-bar /dev/sdb2 | \
    > egrep 'Current volume size|resize at|Cluster size'
    Cluster size       : 4096 bytes
    Current volume size: 4294963712 bytes (4295 MB)
    You might resize at 4294516736 bytes (freeing 450560 bytes).

    real    0m5.231s
    user    0m2.072s
    sys     0m3.014s

Computation of figures:
    Clusters per volume = 4294963712 / 4096 = 1048575.125
    Free clusters = (4294963712 - 4294516736) / 4096 = 109.125

Testing performance of ntfscluster, as used before this commit [1] from
GParted 0.3 in 2006:

    # time ntfscluster --force /dev/sdb2 | \
    > egrep 'bytes per cluster|bytes per volume|clusters per volume|clusters of free space'
    ...
    bytes per cluster       : 4096
    bytes per volume        : 4294963200
    clusters per volume     : 131071
    clusters of free space  : 110

    real    0m4.243s
    user    0m1.629s
    sys     0m2.587s

Note that the clusters per volume figure reported by ntfscluster is
wrong.  4294963200 / 4096 = 1048575, not 131071.

Testing performance using ntfsinfo:

    # time ntfsinfo --mft /dev/sdb2 | \
    egrep 'Cluster Size|Volume Size in Clusters|Free Clusters'
            Cluster Size: 4096
            Volume Size in Clusters: 1048575
            Free Clusters: 110 (0.0%)

    real    0m0.022s
    user    0m0.012s
    sys     0m0.018s

Repeating the above tests while also using 'btrace /dev/sdb2' and Ctrl-C
around each test via a separate terminal, reports these numbers of I/Os
being performed:
  Command      Read requests   Read bytes
- ntfsresize           2,695     1116 MiB
- ntfscluster          2,685     1116 MiB
- ntfsinfo                13     2208 KiB
No wonder that ntfsresize and ntfscluster take a long time, they read
just over 1 GiB of data from the 4 GiB file system, where as ntfsinfo
only reads just over 2 MiB.

Switch to using ntfsinfo to report file system usage.

[1] 9d956594
    replaced ntfscluster with ntfsresize (see #350789)

Closes #47 - GParted is slow refreshing NTFS file systems
parent 8a7d7fbc
......@@ -62,11 +62,11 @@ FS ntfs::get_filesystem_support()
fs .busy = FS::GPARTED ;
if ( ! Glib::find_program_in_path( "ntfsresize" ) .empty() )
{
if (! Glib::find_program_in_path("ntfsinfo").empty())
fs.read = FS::EXTERNAL;
if (! Glib::find_program_in_path("ntfsresize").empty())
fs.check = FS::EXTERNAL;
}
if ( ! Glib::find_program_in_path( "ntfslabel" ) .empty() ) {
Glib::ustring version ;
......@@ -93,7 +93,7 @@ FS ntfs::get_filesystem_support()
}
//resizing is a delicate process ...
if ( fs .read && fs .check )
if (fs.check)
{
fs.grow = FS::EXTERNAL;
......@@ -101,7 +101,6 @@ FS ntfs::get_filesystem_support()
fs.shrink = FS::EXTERNAL;
}
//we need ntfsresize to set correct used/unused after cloning
if ( ! Glib::find_program_in_path( "ntfsclone" ) .empty() )
fs.copy = FS::EXTERNAL;
......@@ -120,47 +119,38 @@ FS ntfs::get_filesystem_support()
void ntfs::set_used_sectors( Partition & partition )
{
exit_status = Utils::execute_command( "ntfsresize --info --force --no-progress-bar " +
Glib::shell_quote( partition.get_path() ),
output, error, true );
if ( exit_status == 0 || exit_status == 1 )
exit_status = Utils::execute_command("ntfsinfo --mft " + Glib::shell_quote(partition.get_path()),
output, error, true);
if (exit_status != 0)
{
Glib::ustring::size_type index = output.find( "Current volume size:" );
if ( index >= output .length() ||
sscanf( output.substr( index ).c_str(), "Current volume size: %lld", &T ) != 1 )
T = -1 ;
index = output .find( "resize at" ) ;
if ( index >= output .length() ||
sscanf( output.substr( index ).c_str(), "resize at %lld", &N ) != 1 )
N = -1 ;
//For an absolutely full NTFS, "ntfsresize --info" exits
// with status 1 and reports this message instead
index = output .find( "ERROR: Volume is full" ) ;
if ( index < output .length() )
N = T ;
index = output.find( "Cluster size" );
if ( index >= output.length() ||
sscanf( output.substr( index ).c_str(), "Cluster size : %lld", &S ) != 1 )
S = -1;
if ( T > -1 && N > -1 )
{
T = Utils::round( T / double(partition .sector_size) ) ;
N = Utils::round( N / double(partition .sector_size) ) ;
partition .set_sector_usage( T, T - N );
}
if ( S > -1 )
partition.fs_block_size = S;
if (! output.empty())
partition.push_back_message(output);
if (! error.empty())
partition.push_back_message(output);
return;
}
else
long long cluster_size = -1;
Glib::ustring::size_type index = output.find("Cluster Size:");
if (index < output.length())
sscanf(output.substr(index).c_str(), "Cluster Size: %lld", &cluster_size);
long long volume_size = -1;
index = output.find("Volume Size in Clusters:");
if (index < output.length())
sscanf(output.substr(index).c_str(), "Volume Size in Clusters: %lld", &volume_size);
long long free_clusters = -1;
index = output.find("Free Clusters:");
if (index < output.length())
sscanf(output.substr(index).c_str(), "Free Clusters: %lld", &free_clusters);
if (cluster_size > -1 && volume_size > -1 && free_clusters > -1)
{
if ( ! output .empty() )
partition.push_back_message( output );
if ( ! error .empty() )
partition.push_back_message( error );
Sector fs_size = volume_size * cluster_size / partition.sector_size;
Sector fs_free = free_clusters * cluster_size / partition.sector_size;
partition.set_sector_usage(fs_size, fs_free);
partition.fs_block_size = cluster_size;
}
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment