* Automatic SSD trim script
@ 2013-12-05 19:20 Sten Heinze
2013-12-06 10:49 ` Karel Zak
0 siblings, 1 reply; 11+ messages in thread
From: Sten Heinze @ 2013-12-05 19:20 UTC (permalink / raw)
To: util-linux
[-- Attachment #1: Type: text/plain, Size: 356 bytes --]
Having experienced the drop in speed when using a SSD with online discard, I wrote a small perl script to run fstrim using batched discard on partitions located on a SSD through cron. Do you think util-linux would be a good place for such a script, given that it is a helper to fstrim? What would be the best way to include one in util-linux?
Thanks,
Sten
[-- Attachment #2: autotrim.pl --]
[-- Type: text/plain, Size: 4151 bytes --]
#!/usr/bin/perl
# This script tries to detect all mounted file systems, which of them are on SSD drives, and run fstrim on them.
# For details see http://wiki.ubuntuusers.de/SSD/TRIM or https://wiki.debian.org/SSDOptimization
# Use cron to run regularly, logger to redirect the output to syslog (essentially the output of fstrim).
# Written by Sten Heinze, 2013.
use strict;
use warnings;
use Cwd qw(realpath);
my $hdparm = '/sbin/hdparm';
my $grep = '/bin/grep';
my $block_dev_path = '/sys/block/';
my $rotational_file = '/queue/rotational';
my $mount = '/bin/mount';
my $discard_option = 'discard';
my $fstrim = '/sbin/fstrim -v'; # verbose needed?
# remove leading and trailing whitespace
sub trim {
my $str = shift;
$str =~ s/^\s+|\s+$//g;
return $str;
}
# read file content
sub read_file {
my $filename = shift;
open( my $file_handle, "<", $filename ) || die "$filename: $!";
my $content = trim( join( '', <$file_handle> ) );
close( $file_handle );
return $content;
}
# print and execute the given command
sub e {
my $cmd = shift;
print( "$cmd\n" );
system( "$cmd" );
}
# list all mounted drives; blkid doesn't provide mount points; fstab does ans is another possible source.
# maybe only include fixed/internal drives? /sys/block/sdX/removable doesn't help for deciding if a dev is fixed.
sub get_devs_from_mount {
my %devs = (); # empty hash
my $output = `$mount`;
my @lines = split( '\n', $output); # split the output into lines
foreach my $line ( @lines ) {
if( $line =~ m$(\S+) on (/\S*) type \S+ (.*)$) { # eg. /dev/sda8 on /home type ext4 (rw,relatime,data=ordered)
my $path = $1;
my $mount_point = $2;
my $mount_options = $3;
next if( index( $mount_options, $discard_option ) != -1 ); # not -1 means found discard, i.e. skip this line
next if( ! -e $path ); # skip lines that are virtual fs
$path = realpath( $path ); # get absolute path for those mount points that are uuid symlinks
$devs{ $path } = $mount_point; # add to hash
}
}
return %devs;
}
# check if device is ssd using hdparm
sub is_ssd_hdparm {
my $dev = shift;
$dev = substr( $dev, 5, 3 ); # short to 3 chars: /dev/xxxN to xxx
return 0 if( ! -X $hdparm || ! -X $grep ); # return no ssd if no hdparm or no grep command available
`$hdparm -I /dev/$dev 2>&1 | $grep 'TRIM supported' 2>/dev/null`; # perl calls bash, use bash redirect
if( $? == -1 ) {
#print "failed to execute: $!\n";
}
elsif( $? & 127 ) {
#printf "child died with signal %d, %s coredump\n", ($? & 127), ($? & 128) ? 'with' : 'without';
}
else {
my $exit_code = $? >> 8;
#printf "child exited with value %d\n", $exit_code;
return 1 if( $exit_code == 0 ); # only if grep found something, TRIM is supported
}
return 0;
}
# check if device is ssd using /sys/block/sdX/queue/rotational: 0=SSD, 1=likely HDD, but could be USB memory etc.
# if any error occurs, assume dev is not rotational and return 0.
sub is_ssd_sysfs {
my $dev = shift;
$dev = substr( $dev, 5, 3 ); # short to 3 chars: /dev/xxxN to xxx
my $dev_substr = substr( $dev, 0, 2 );
return 0 if( $dev_substr ne "sd" ); # if device name is not sdX, assume it is not a ssd
return 0 if( ! -R $block_dev_path.$dev.$rotational_file ); # return false if file is not readable
return 0 if( read_file( $block_dev_path.$dev.$rotational_file ) eq "1" ); # if rotational, it's likely not a SSD
return 1;
}
# check if $block_dev_dir/dev/queue/rotational is 0 -> not reliable, use only as fallback
sub filter_ssd {
my %devs = @_;
while( my ( $dev, $mount_point ) = each( %devs ) ) { # loop over hash and remove all non-ssd devs
delete $devs{ $dev } if( ! is_ssd_hdparm( $dev ) && ! is_ssd_sysfs( $dev ) ); # remove dev if no ssd
}
return %devs;
}
# trim the mount points
sub trim_mount_points {
my %devs = @_;
while( my ( $dev, $mount_point ) = each( %devs ) ) { # loop over hash and call trim on mount points
e( "$fstrim $mount_point" );
#return; # for testing: use only the first
}
}
# main
my %devs = get_devs_from_mount();
%devs = filter_ssd( %devs );
trim_mount_points( %devs );
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: Automatic SSD trim script
2013-12-05 19:20 Automatic SSD trim script Sten Heinze
@ 2013-12-06 10:49 ` Karel Zak
2013-12-09 13:43 ` Lukáš Czerner
0 siblings, 1 reply; 11+ messages in thread
From: Karel Zak @ 2013-12-06 10:49 UTC (permalink / raw)
To: Sten Heinze; +Cc: util-linux, Lukas Czerner
Hi Sten,
On Thu, Dec 05, 2013 at 08:20:07PM +0100, Sten Heinze wrote:
> Having experienced the drop in speed when using a SSD with online
> discard, I wrote a small perl script to run fstrim using batched
> discard on partitions located on a SSD through cron. Do you think
> util-linux would be a good place for such a script, given that it is
> a helper to fstrim? What would be the best way to include one in
> util-linux?
I have doubts we want to add a perl script to the package as a regular
util, util-linux is very basic package and dependence on Perl is
unexpected here. Maybe it would be possible to write a simple shell
script for this task and add it to the Documentation/example.files/
directory.
IMHO the best solution would be to improve fstrim to trim all
filesystems where it makes sense.
All we need is to link fstrim with libmount and lib/sysfs.c, add a new
option --all and check non-zero /sys/block/<name>/queue/discard_granularity
(or so).
I guess that implement something like this will be ~30 lines in C :-)
[CC: to Lukas who is fstrim author]
Karel
Anyway, a few comments to your script:
> # list all mounted drives; blkid doesn't provide mount points; fstab does ans is another possible source.
don't use mount(8) to list info about mountpoints, findmnt(8) is better, for example:
findmnt -clo TARGET -O nodiscard
> # maybe only include fixed/internal drives? /sys/block/sdX/removable doesn't help for deciding if a dev is fixed.
> sub get_devs_from_mount {
> my %devs = (); # empty hash
>
> my $output = `$mount`;
> my @lines = split( '\n', $output); # split the output into lines
> foreach my $line ( @lines ) {
> if( $line =~ m$(\S+) on (/\S*) type \S+ (.*)$) { # eg. /dev/sda8 on /home type ext4 (rw,relatime,data=ordered)
> my $path = $1;
> my $mount_point = $2;
> my $mount_options = $3;
> next if( index( $mount_options, $discard_option ) != -1 ); # not -1 means found discard, i.e. skip this line
> next if( ! -e $path ); # skip lines that are virtual fs
> $path = realpath( $path ); # get absolute path for those mount points that are uuid symlinks
> $devs{ $path } = $mount_point; # add to hash
> }
> }
> return %devs;
> }
>
> # check if device is ssd using hdparm
> sub is_ssd_hdparm {
> my $dev = shift;
> $dev = substr( $dev, 5, 3 ); # short to 3 chars: /dev/xxxN to xxx
>
> return 0 if( ! -X $hdparm || ! -X $grep ); # return no ssd if no hdparm or no grep command available
>
> `$hdparm -I /dev/$dev 2>&1 | $grep 'TRIM supported' 2>/dev/null`; # perl calls bash, use bash redirect
it would be possible to use lsblk to list devices with non-zero DISC-GRAN column,
the util also provides mounpoints.
> # check if device is ssd using /sys/block/sdX/queue/rotational: 0=SSD, 1=likely HDD, but could be USB memory etc.
again, use lsblk
--
Karel Zak <kzak@redhat.com>
http://karelzak.blogspot.com
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: Automatic SSD trim script
2013-12-06 10:49 ` Karel Zak
@ 2013-12-09 13:43 ` Lukáš Czerner
2013-12-10 15:44 ` Karel Zak
0 siblings, 1 reply; 11+ messages in thread
From: Lukáš Czerner @ 2013-12-09 13:43 UTC (permalink / raw)
To: Karel Zak; +Cc: Sten Heinze, util-linux
On Fri, 6 Dec 2013, Karel Zak wrote:
> Date: Fri, 6 Dec 2013 11:49:44 +0100
> From: Karel Zak <kzak@redhat.com>
> To: Sten Heinze <shze@gmx.de>
> Cc: util-linux@vger.kernel.org, Lukas Czerner <lczerner@redhat.com>
> Subject: Re: Automatic SSD trim script
>
>
> Hi Sten,
>
> On Thu, Dec 05, 2013 at 08:20:07PM +0100, Sten Heinze wrote:
> > Having experienced the drop in speed when using a SSD with online
> > discard, I wrote a small perl script to run fstrim using batched
> > discard on partitions located on a SSD through cron. Do you think
> > util-linux would be a good place for such a script, given that it is
> > a helper to fstrim? What would be the best way to include one in
> > util-linux?
>
> I have doubts we want to add a perl script to the package as a regular
> util, util-linux is very basic package and dependence on Perl is
> unexpected here. Maybe it would be possible to write a simple shell
> script for this task and add it to the Documentation/example.files/
> directory.
I very much like the idea of having a simple script to add to cron
to be able to keep SSD's at top of its performance.
>
>
> IMHO the best solution would be to improve fstrim to trim all
> filesystems where it makes sense.
>
> All we need is to link fstrim with libmount and lib/sysfs.c, add a new
> option --all and check non-zero /sys/block/<name>/queue/discard_granularity
> (or so).
Yes and yes. This is the ultimate solution. Simply being able to run
fstrim --all to discard free space on all the mounted supported file
systems is great idea. In that case we do not need any scripts at
all.
Thanks!
-Lukas
>
> I guess that implement something like this will be ~30 lines in C :-)
>
> [CC: to Lukas who is fstrim author]
>
> Karel
>
>
> Anyway, a few comments to your script:
>
> > # list all mounted drives; blkid doesn't provide mount points; fstab does ans is another possible source.
>
> don't use mount(8) to list info about mountpoints, findmnt(8) is better, for example:
>
> findmnt -clo TARGET -O nodiscard
>
> > # maybe only include fixed/internal drives? /sys/block/sdX/removable doesn't help for deciding if a dev is fixed.
> > sub get_devs_from_mount {
> > my %devs = (); # empty hash
> >
> > my $output = `$mount`;
> > my @lines = split( '\n', $output); # split the output into lines
> > foreach my $line ( @lines ) {
> > if( $line =~ m$(\S+) on (/\S*) type \S+ (.*)$) { # eg. /dev/sda8 on /home type ext4 (rw,relatime,data=ordered)
> > my $path = $1;
> > my $mount_point = $2;
> > my $mount_options = $3;
> > next if( index( $mount_options, $discard_option ) != -1 ); # not -1 means found discard, i.e. skip this line
> > next if( ! -e $path ); # skip lines that are virtual fs
> > $path = realpath( $path ); # get absolute path for those mount points that are uuid symlinks
> > $devs{ $path } = $mount_point; # add to hash
> > }
> > }
> > return %devs;
> > }
> >
> > # check if device is ssd using hdparm
> > sub is_ssd_hdparm {
> > my $dev = shift;
> > $dev = substr( $dev, 5, 3 ); # short to 3 chars: /dev/xxxN to xxx
> >
> > return 0 if( ! -X $hdparm || ! -X $grep ); # return no ssd if no hdparm or no grep command available
> >
> > `$hdparm -I /dev/$dev 2>&1 | $grep 'TRIM supported' 2>/dev/null`; # perl calls bash, use bash redirect
>
>
> it would be possible to use lsblk to list devices with non-zero DISC-GRAN column,
> the util also provides mounpoints.
>
> > # check if device is ssd using /sys/block/sdX/queue/rotational: 0=SSD, 1=likely HDD, but could be USB memory etc.
>
> again, use lsblk
>
>
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: Automatic SSD trim script
2013-12-09 13:43 ` Lukáš Czerner
@ 2013-12-10 15:44 ` Karel Zak
2013-12-11 2:07 ` Sten Heinze
` (2 more replies)
0 siblings, 3 replies; 11+ messages in thread
From: Karel Zak @ 2013-12-10 15:44 UTC (permalink / raw)
To: Lukáš Czerner; +Cc: Sten Heinze, util-linux
On Mon, Dec 09, 2013 at 02:43:32PM +0100, Lukáš Czerner wrote:
> > All we need is to link fstrim with libmount and lib/sysfs.c, add a new
> > option --all and check non-zero /sys/block/<name>/queue/discard_granularity
> > (or so).
>
> Yes and yes. This is the ultimate solution. Simply being able to run
> fstrim --all to discard free space on all the mounted supported file
> systems is great idea. In that case we do not need any scripts at
> all.
Implemented. Sten, maybe you can try fstrim --all from git tree
in your crontab.
Karel
--
Karel Zak <kzak@redhat.com>
http://karelzak.blogspot.com
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: Automatic SSD trim script
2013-12-10 15:44 ` Karel Zak
@ 2013-12-11 2:07 ` Sten Heinze
2013-12-11 10:54 ` Pádraig Brady
2013-12-17 19:46 ` Marcos Mello
2 siblings, 0 replies; 11+ messages in thread
From: Sten Heinze @ 2013-12-11 2:07 UTC (permalink / raw)
To: Karel Zak, Lukáš Czerner; +Cc: util-linux
On 12/10/2013 9:44 AM, Karel Zak wrote:
> On Mon, Dec 09, 2013 at 02:43:32PM +0100, Lukáš Czerner wrote:
>>> All we need is to link fstrim with libmount and lib/sysfs.c, add a new
>>> option --all and check non-zero /sys/block/<name>/queue/discard_granularity
>>> (or so).
>>
>> Yes and yes. This is the ultimate solution. Simply being able to run
>> fstrim --all to discard free space on all the mounted supported file
>> systems is great idea. In that case we do not need any scripts at
>> all.
>
> Implemented. Sten, maybe you can try fstrim --all from git tree
> in your crontab.
>
> Karel
>
This was fantastic fast! I will try it out as soon as I have cloned the
git repo and built it.
Thanks a lot!
Sten
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: Automatic SSD trim script
2013-12-10 15:44 ` Karel Zak
2013-12-11 2:07 ` Sten Heinze
@ 2013-12-11 10:54 ` Pádraig Brady
2013-12-11 11:36 ` Karel Zak
2013-12-11 16:03 ` Karel Zak
2013-12-17 19:46 ` Marcos Mello
2 siblings, 2 replies; 11+ messages in thread
From: Pádraig Brady @ 2013-12-11 10:54 UTC (permalink / raw)
To: Karel Zak; +Cc: Lukáš Czerner, Sten Heinze, util-linux
On 12/10/2013 03:44 PM, Karel Zak wrote:
> On Mon, Dec 09, 2013 at 02:43:32PM +0100, Lukáš Czerner wrote:
>>> All we need is to link fstrim with libmount and lib/sysfs.c, add a new
>>> option --all and check non-zero /sys/block/<name>/queue/discard_granularity
>>> (or so).
>>
>> Yes and yes. This is the ultimate solution. Simply being able to run
>> fstrim --all to discard free space on all the mounted supported file
>> systems is great idea. In that case we do not need any scripts at
>> all.
>
> Implemented. Sten, maybe you can try fstrim --all from git tree
> in your crontab.
Very nice:
https://git.kernel.org/cgit/utils/util-linux/util-linux.git/commit/?id=36c370c
One foible was it was called multiple times for my /home
Now my /home is mounted a couple of times on my system (why I don't know):
├─/home /dev/sdb1 ext4 rw,relatime,seclabel,user_xattr,barrier=1,data=ordered
│ └─/home /dev/sdb1 ext4 rw,relatime,seclabel,user_xattr,barrier=1,data=ordered
If this was common it might be worth avoiding processing the same entry multiple times.
thanks!
Pádraig
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: Automatic SSD trim script
2013-12-11 10:54 ` Pádraig Brady
@ 2013-12-11 11:36 ` Karel Zak
2013-12-11 16:03 ` Karel Zak
1 sibling, 0 replies; 11+ messages in thread
From: Karel Zak @ 2013-12-11 11:36 UTC (permalink / raw)
To: Pádraig Brady; +Cc: Lukáš Czerner, Sten Heinze, util-linux
On Wed, Dec 11, 2013 at 10:54:07AM +0000, Pádraig Brady wrote:
> Very nice:
> https://git.kernel.org/cgit/utils/util-linux/util-linux.git/commit/?id=36c370c
>
> One foible was it was called multiple times for my /home
> Now my /home is mounted a couple of times on my system (why I don't know):
>
> ├─/home /dev/sdb1 ext4 rw,relatime,seclabel,user_xattr,barrier=1,data=ordered
> │ └─/home /dev/sdb1 ext4 rw,relatime,seclabel,user_xattr,barrier=1,data=ordered
>
> If this was common it might be worth avoiding processing the same entry multiple times.
The common things is something like:
├─/boot systemd-1 autofs rw,relatime,fd=41,pgrp=1,timeout=300,minproto=5,maxpr
│ └─/boot /dev/sda1 vfat rw,relatime,fmask=0077,dmask=0077,codepage=437,iochar
but "autofs" is ignored.
My old plan is to add some de-duplication function to libmount... now
I have a real motivation :-)
Karel
--
Karel Zak <kzak@redhat.com>
http://karelzak.blogspot.com
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: Automatic SSD trim script
2013-12-11 10:54 ` Pádraig Brady
2013-12-11 11:36 ` Karel Zak
@ 2013-12-11 16:03 ` Karel Zak
1 sibling, 0 replies; 11+ messages in thread
From: Karel Zak @ 2013-12-11 16:03 UTC (permalink / raw)
To: Pádraig Brady; +Cc: Lukáš Czerner, Sten Heinze, util-linux
On Wed, Dec 11, 2013 at 10:54:07AM +0000, Pádraig Brady wrote:
> If this was common it might be worth avoiding processing the same entry multiple times.
Implemented. I have also added --uniq to findmnt, so you will see your
/home only once :-)
Karel
--
Karel Zak <kzak@redhat.com>
http://karelzak.blogspot.com
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: Automatic SSD trim script
2013-12-10 15:44 ` Karel Zak
2013-12-11 2:07 ` Sten Heinze
2013-12-11 10:54 ` Pádraig Brady
@ 2013-12-17 19:46 ` Marcos Mello
2013-12-17 19:58 ` Marcos Mello
2014-01-13 12:12 ` Karel Zak
2 siblings, 2 replies; 11+ messages in thread
From: Marcos Mello @ 2013-12-17 19:46 UTC (permalink / raw)
To: util-linux
Karel Zak <kzak@...> writes:
>
> On Mon, Dec 09, 2013 at 02:43:32PM +0100, Lukáš Czerner wrote:
> > > All we need is to link fstrim with libmount and lib/sysfs.c, add a new
> > > option --all and check non-zero
/sys/block/≤name>/queue/discard_granularity
> > > (or so).
> >
> > Yes and yes. This is the ultimate solution. Simply being able to run
> > fstrim --all to discard free space on all the mounted supported file
> > systems is great idea. In that case we do not need any scripts at
> > all.
>
> Implemented. Sten, maybe you can try fstrim --all from git tree
> in your crontab.
>
Thanks, Karel!
Would it be possible add an option for the "--all" mode to tell fstrim skip
mountpoints witch have "discard" option in fstab?
--
Marcos
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: Automatic SSD trim script
2013-12-17 19:46 ` Marcos Mello
@ 2013-12-17 19:58 ` Marcos Mello
2014-01-13 12:12 ` Karel Zak
1 sibling, 0 replies; 11+ messages in thread
From: Marcos Mello @ 2013-12-17 19:58 UTC (permalink / raw)
To: util-linux
Marcos Mello <marcosfrm@...> writes:
>
[snip]
>
> Thanks, Karel!
>
> Would it be possible add an option for the "--all" mode to tell fstrim skip
> mountpoints witch have "discard" option in fstab?
>
s/witch/which/
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: Automatic SSD trim script
2013-12-17 19:46 ` Marcos Mello
2013-12-17 19:58 ` Marcos Mello
@ 2014-01-13 12:12 ` Karel Zak
1 sibling, 0 replies; 11+ messages in thread
From: Karel Zak @ 2014-01-13 12:12 UTC (permalink / raw)
To: Marcos Mello; +Cc: util-linux
On Tue, Dec 17, 2013 at 07:46:35PM +0000, Marcos Mello wrote:
> Karel Zak <kzak@...> writes:
>
> >
> > On Mon, Dec 09, 2013 at 02:43:32PM +0100, Lukáš Czerner wrote:
> > > > All we need is to link fstrim with libmount and lib/sysfs.c, add a new
> > > > option --all and check non-zero
> /sys/block/≤name>/queue/discard_granularity
> > > > (or so).
> > >
> > > Yes and yes. This is the ultimate solution. Simply being able to run
> > > fstrim --all to discard free space on all the mounted supported file
> > > systems is great idea. In that case we do not need any scripts at
> > > all.
> >
> > Implemented. Sten, maybe you can try fstrim --all from git tree
> > in your crontab.
> >
>
> Thanks, Karel!
>
> Would it be possible add an option for the "--all" mode to tell fstrim skip
> mountpoints witch have "discard" option in fstab?
It seems like unnecessary optimization -- the overhead on filesystem with
active discard is minimal.
(And according to Lukas in some cases FSTRIM ioctl can help you
with deleted files smaller than than discard_granularity.)
Karel
--
Karel Zak <kzak@redhat.com>
http://karelzak.blogspot.com
^ permalink raw reply [flat|nested] 11+ messages in thread
end of thread, other threads:[~2014-01-13 12:12 UTC | newest]
Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-12-05 19:20 Automatic SSD trim script Sten Heinze
2013-12-06 10:49 ` Karel Zak
2013-12-09 13:43 ` Lukáš Czerner
2013-12-10 15:44 ` Karel Zak
2013-12-11 2:07 ` Sten Heinze
2013-12-11 10:54 ` Pádraig Brady
2013-12-11 11:36 ` Karel Zak
2013-12-11 16:03 ` Karel Zak
2013-12-17 19:46 ` Marcos Mello
2013-12-17 19:58 ` Marcos Mello
2014-01-13 12:12 ` Karel Zak
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox