ext4: only load buddy bitmap in ext4_trim_fs() when it is needed

Currently we are loading buddy ext4_mb_load_buddy() for every block
group we are going through in ext4_trim_fs() in many cases just to find
out that there is not enough space to be bothered with. As Amir Goldstein
suggested we can use bb_free information directly from ext4_group_info.

This commit removes ext4_mb_load_buddy() from ext4_trim_fs() and rather
get the ext4_group_info via ext4_get_group_info() and use the bb_free
information directly from that. This avoids unnecessary call to load
buddy in the case the group does not have enough free space to trim.
Loading buddy is now moved to ext4_trim_all_free().

Tested by me with xfstests 251.

Signed-off-by: Lukas Czerner <lczerner@redhat.com>
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
Signed-off-by: Blechd0se <alex.christ@hotmail.de>

Conflicts:
	fs/ext4/mballoc.c
ext4: protect bb_first_free in ext4_trim_all_free() with group lock

We should protect reading bd_info->bb_first_free with the group lock
because otherwise we might miss some free blocks. This is not a big deal
at all, but the change to do right thing is really simple, so lets do
that.

Signed-off-by: Lukas Czerner <lczerner@redhat.com>
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
ext4: fix trim length underflow with small trim length

In 0f0a25b, we adjust 'len' with s_first_data_block - start, but
it could underflow in case blocksize=1K, fstrim_range.len=512 and
fstrim_range.start = 0. In this case, when we run the code:
len -= first_data_blk - start; len will be underflow to -1ULL.
In the end, although we are safe that last_group check later will limit
the trim to the whole volume, but that isn't what the user really want.

So this patch fix it. It also adds the check for 'start' like ext3 so that
we can break immediately if the start is invalid.

Cc: Lukas Czerner <lczerner@redhat.com>
Signed-off-by: Tao Ma <boyu.mt@taobao.com>
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
ext4: speed up group trim with the right free block count

When we trim some free blocks in a group of ext4, we need to
calculate the free blocks properly and check whether there are
enough freed blocks left for us to trim. Current solution will
only calculate free spaces if they are large for a trim which
isn't appropriate.

Let us see a small example:
a group has 1.5M free which are 300k, 300k, 300k, 300k, 300k.
And minblocks is 1M.  With current solution, we have to iterate
the whole group since these 300k will never be subtracted from
1.5M.  But actually we should exit after we find the first 2
free spaces since the left 3 chunks only sum up to 900K if we
subtract the first 600K although they can't be trimed.

Reviewed-by: Andreas Dilger <adilger@dilger.ca>
Signed-off-by: Tao Ma <boyu.mt@taobao.com>
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
ext4: Add new ext4 trim tracepoints

Add ext4_trim_extent and ext4_trim_all_free.

Reviewed-by: Lukas Czerner <lczerner@redhat.com>
Signed-off-by: Tao Ma <boyu.mt@taobao.com>
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
ext4: Speed up FITRIM by recording flags in ext4_group_info

In ext4, when FITRIM is called every time, we iterate all the
groups and do trim one by one. It is a bit time wasting if the
group has been trimmed and there is no change since the last
trim.

So this patch adds a new flag in ext4_group_info->bb_state to
indicate that the group has been trimmed, and it will be cleared
if some blocks is freed(in release_blocks_on_commit). Another
trim_minlen is added in ext4_sb_info to record the last minlen
we use to trim the volume, so that if the caller provide a small
one, we will go on the trim regardless of the bb_state.

A simple test with my intel x25m ssd:
df -h shows:
/dev/sdb1              40G   21G   17G  56% /mnt/ext4
Block size:               4096

run the FITRIM with the following parameter:
range.start = 0;
range.len = UINT64_MAX;
range.minlen = 1048576;

without the patch:
[root@boyu-tm linux-2.6]# time ./ftrim /mnt/ext4/a
real	0m5.505s
user	0m0.000s
sys	0m1.224s
[root@boyu-tm linux-2.6]# time ./ftrim /mnt/ext4/a
real	0m5.359s
user	0m0.000s
sys	0m1.178s
[root@boyu-tm linux-2.6]# time ./ftrim /mnt/ext4/a
real	0m5.228s
user	0m0.000s
sys	0m1.151s

with the patch:
[root@boyu-tm linux-2.6]# time ./ftrim /mnt/ext4/a
real	0m5.625s
user	0m0.000s
sys	0m1.269s
[root@boyu-tm linux-2.6]# time ./ftrim /mnt/ext4/a
real	0m0.002s
user	0m0.000s
sys	0m0.001s
[root@boyu-tm linux-2.6]# time ./ftrim /mnt/ext4/a
real	0m0.002s
user	0m0.000s
sys	0m0.001s

A big improvement for the 2nd and 3rd run.

Even after I delete some big image files, it is still much
faster than iterating the whole disk.

[root@boyu-tm test]# time ./ftrim /mnt/ext4/a
real	0m1.217s
user	0m0.000s
sys	0m0.196s

Cc: Lukas Czerner <lczerner@redhat.com>
Reviewed-by: Andreas Dilger <adilger.kernel@dilger.ca>
Signed-off-by: Tao Ma <boyu.mt@taobao.com>
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
Signed-off-by: Blechd0se <alex.christ@hotmail.de>

Conflicts:
	fs/ext4/ext4.h
ext4: fix trim with spinlock around ext4_mb_load_buddy()

On a omap3630 like device trim causes problems
on the first bootup. This produces following oops;

<4>[  226.061492] [<c01dbd3c>] (vsnprintf+0x324/0x364) from [<c01dbdec>] (vscnprintf+0xc/0x24)
<4>[  226.061492] [<c01dbdec>] (vscnprintf+0xc/0x24) from [<c0063cb4>] (vprintk+0x144/0x3bc)
<4>[  226.061523] [<c0063cb4>] (vprintk+0x144/0x3bc) from [<c0130108>] (ext4_error+0x30/0x54)
<4>[  226.061553] [<c0130108>] (ext4_error+0x30/0x54) from [<c013cd1c>] (ext4_trim_fs+0x188/0x27c)
<4>[  226.061553] [<c013cd1c>] (ext4_trim_fs+0x188/0x27c) from [<c0128348>] (ext4_ioctl+0x7f8/0x89c)
<4>[  226.061584] [<c0128348>] (ext4_ioctl+0x7f8/0x89c) from [<c00dd0cc>] (vfs_ioctl+0x2c/0x8c)
<4>[  226.061614] [<c00dd0cc>] (vfs_ioctl+0x2c/0x8c) from [<c00dd778>] (do_vfs_ioctl+0x558/0x5c4)
<4>[  226.061614] [<c00dd778>] (do_vfs_ioctl+0x558/0x5c4) from [<c00dd818>] (sys_ioctl+0x34/0x54)
<4>[  226.061645] [<c00dd818>] (sys_ioctl+0x34/0x54) from [<c0032f40>] (ret_fast_syscall+0x0/0x2c)

ext4_mb_load_buddy() won't be called in a secure context
and therefore kernel crashes while trim gets executed
when the CPU is under heavy pressure. Ideally this shouldn't
happen at all, but since ext4 partition is mounted with discard
option this is a serious problem.

In my test scenario the problem wasn't reproducable with this patch.
This needs confirmation.

Signed-off-by: Blechd0se <alex.christ@hotmail.de>
ext4: switch from spin_lock to mutex_lock

A spinlock is probably not the right thing to use
on our singlecore processor. This has a nice sideeffect;
The scheduler won't get confused if a process
tries to sleep in this critical section.

This should fix every kernel crash while trimming and
using the device.

Change-Id: I96bb3462875143d963eacb301aca89194340aaaa
Signe-off-by: Blechd0se <alex.christ@hotmail.de>
Merge branch 'AeroKernel' of https://github.com/Quarx2k/jordan-kernel into AeroKernel