2009-06-25 11:36:24

by Steinar H. Gunderson

[permalink] [raw]
Subject: Segmentation fault in e4defrag -c

Hi,

I tested e4defrag -c (granted, on a 2.6.30-rc kernel, so it doesn't actually
have the defrag patches, but checking should still work, right?) and it
segfaults with a null pointer deference on certain filesystems. Could you
please take a look?

pannekake:/home/sesse# gdb ./e4defrag
GNU gdb 6.8-debian
Copyright (C) 2008 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu"...
(gdb) r -c /dev/mapper/pannekake-home
Starting program: /home/sesse/e4defrag -c /dev/mapper/pannekake-home

Program received signal SIGSEGV, Segmentation fault.
0x00000000004027b9 in get_physical_count (physical_list_head=0x0) at e4defrag.c:1055
1055 if ((ext_list_tmp->data.physical + ext_list_tmp->data.len)
(gdb) bt full
#0 0x00000000004027b9 in get_physical_count (physical_list_head=0x0) at e4defrag.c:1055
ret = 0
ext_list_tmp = (struct fiemap_extent_list *) 0x0
#1 0x0000000000402f6c in file_statistic (file=0x60e260 "/home/sesse/Mika - Life In Cartoon Motion/11 - Ring Ring (Bonus Track).mp3",
buf=0x7fff33662fd0, flag=0, ftwbuf=0x7fff33667378) at e4defrag.c:1326
fd = 8
ret = 0
now_ext_count = 862335568
best_ext_count = 32767
physical_ext_count = 862352208
i = 32767
j = 32
ratio = 0
blk_count = 0
msg_buffer = "(", '\0' <repeats 15 times>, "\030!f3ÿ\177\000\000\000\000\000\000f\000\000\000À\022a\000\000\000\000\000/home/se/home/lo\a\000\000\000\000\000\000\000\2200f3ÿ\177\000\000\035\000\000\000\000\000\000\000P2f3ÿ\177\000\000\004\000\000\000\000\000\000\000à0f3ÿ\177\000\000Ñ,@\000\000\000\000\000P2f3ÿ\177\000\000VêÜæb\177\000\000Psf3ÿ\177\000\000C'@\000\000\000\000\000\020Ð`\000\000\000\000\000ày\nçb\177\000\000xsf3ÿ\177\000\000\f\000\000\000\001\000\000\000@1f3ÿ\177\000\000`â`", '\0' <repeats 21 times>, "Psf3ÿ\177\000\000"...
physical_list_head = (struct fiemap_extent_list *) 0x0
logical_list_head = (struct fiemap_extent_list *) 0x0
#2 0x00007f62e6e1d73a in ?? () from /lib/libc.so.6
No symbol table info available.
#3 0x00007f62e6e1da85 in ?? () from /lib/libc.so.6
No symbol table info available.
#4 0x00007f62e6e1d67e in ?? () from /lib/libc.so.6
No symbol table info available.
#5 0x00007f62e6e1da85 in ?? () from /lib/libc.so.6
No symbol table info available.
#6 0x00007f62e6e1d67e in ?? () from /lib/libc.so.6
No symbol table info available.
#7 0x00007f62e6e1da85 in ?? () from /lib/libc.so.6
No symbol table info available.
#8 0x00007f62e6e1e2cb in ?? () from /lib/libc.so.6
No symbol table info available.
#9 0x0000000000404a67 in main (argc=3, argv=0x7fff336689e8) at e4defrag.c:2022
mount_dir_len = 32767
opt = -1
i = 2
j = 0
flags = 3
arg_type = 0
success_flag = 0
dir_name = "/home", '\0' <repeats 4091 times>
buf = {st_dev = 64787, st_ino = 2, st_nlink = 33, st_mode = 16877, st_uid = 0, st_gid = 0, pad0 = 0, st_rdev = 0, st_size = 4096,
st_blksize = 4096, st_blocks = 8, st_atim = {tv_sec = 1245891895, tv_nsec = 968453897}, st_mtim = {tv_sec = 1245401183,
tv_nsec = 304453887}, st_ctim = {tv_sec = 1245401183, tv_nsec = 304453887}, __unused = {0, 0, 0}}
sb = {s_inodes_count = 2621440, s_blocks_count_lo = 10485760, s_r_blocks_count_lo = 524224, s_free_blocks_count_lo = 3310667,
s_free_inodes_count = 2377762, s_first_data_block = 0, s_log_block_size = 2, s_obso_log_frag_size = 2, s_blocks_per_group = 32768,
s_obso_frags_per_group = 32768, s_inodes_per_group = 8192, s_mtime = 1243121832, s_wtime = 1243121832, s_mnt_count = 11,
s_max_mnt_count = 38, s_magic = 61267, s_state = 1, s_errors = 1, s_minor_rev_level = 0, s_lastcheck = 1239019329,
s_checkinterval = 15552000, s_creator_os = 0, s_rev_level = 1, s_def_resuid = 0, s_def_resgid = 0, s_first_ino = 11,
s_inode_size = 256, s_block_group_nr = 0, s_feature_compat = 60, s_feature_incompat = 582, s_feature_ro_compat = 123,
s_uuid = "À{Ó;{rM*\227±Ã\22742\v2", s_volume_name = '\0' <repeats 15 times>, s_last_mounted = '\0' <repeats 63 times>,
s_algorithm_usage_bitmap = 0, s_prealloc_blocks = 0 '\0', s_prealloc_dir_blocks = 0 '\0', s_reserved_gdt_blocks = 1021,
s_journal_uuid = '\0' <repeats 15 times>, s_journal_inum = 8, s_journal_dev = 0, s_last_orphan = 655808, s_hash_seed = {3246912957,
3041674718, 1885689521, 1976377087}, s_def_hash_version = 2 '\002', s_reserved_char_pad = 1 '\001', s_desc_size = 0,
s_default_mount_opts = 0, s_first_meta_bg = 0, s_mkfs_time = 1219499056, s_jnl_blocks = {9255, 9256, 9257, 9258, 9259, 9260, 9261,
9262, 9263, 9264, 9265, 9266, 9267, 10292, 0, 0, 134217728}, s_blocks_count_hi = 0, s_r_blocks_count_hi = 0,
s_free_blocks_count_hi = 0, s_min_extra_isize = 28, s_want_extra_isize = 28, s_flags = 1, s_raid_stride = 0, s_mmp_interval = 0,
s_mmp_block = 0, s_raid_stripe_width = 0, s_log_groups_per_flex = 4 '\004', s_reserved_char_pad2 = 0 '\0', s_reserved_pad = 0,
s_reserved = {15648, 0 <repeats 161 times>}}

/* Steinar */
--
Homepage: http://www.sesse.net/


2009-06-26 08:35:27

by Kazuya Mio

[permalink] [raw]
Subject: Re: Segmentation fault in e4defrag -c

Hi Steinar,

Thanks for testing defrag.

e4defrag -c works fine in the case without defrag patch.
I cannot reproduce this problem, so I think this problem occurred in unusual
cases (e.g. i_size is not zeroed but it has no extent)


To solve this problem, could you send me the following information?
1. mount option of /home/sesse
2. filefrag -v "/home/sesse/Mika - Life In Cartoon Motion/11 - Ring Ring (Bonus
Track).mp3"
3. stat "/home/sesse/Mika - Life In Cartoon Motion/11 - Ring Ring (Bonus Track).mp3"

Does this problem occur at all times?

Regards,

Kazuya Mio

2009-06-26 09:38:17

by Steinar H. Gunderson

[permalink] [raw]
Subject: Re: Segmentation fault in e4defrag -c

On Fri, Jun 26, 2009 at 05:32:48PM +0900, Kazuya Mio wrote:
> e4defrag -c works fine in the case without defrag patch.

I tried 2.6.31-rc1 now (which should have the defrag patch, right?).
There's no change -- and it still cannot actually defrag for some reason.

> To solve this problem, could you send me the following information?
> 1. mount option of /home/sesse

/dev/mapper/pannekake-home on /home type ext4 (rw,errors=remount-ro)

> 2. filefrag -v "/home/sesse/Mika - Life In Cartoon Motion/11 - Ring
> Ring (Bonus Track).mp3"

pannekake:~# filefrag -v "/home/sesse/Mika - Life In Cartoon Motion/11 - Ring Ring (Bonus Track).mp3"
Checking /home/sesse/Mika - Life In Cartoon Motion/11 - Ring Ring (Bonus Track).mp3
Filesystem type is: ef53
Filesystem cylinder groups is approximately 315
File is stored in extents format
Blocksize of file /home/sesse/Mika - Life In Cartoon Motion/11 - Ring Ring (Bonus Track).mp3 is 4096
File size of /home/sesse/Mika - Life In Cartoon Motion/11 - Ring Ring (Bonus Track).mp3 is 4050385 (989 blocks)
First block: 0
Last block: 0
/home/sesse/Mika - Life In Cartoon Motion/11 - Ring Ring (Bonus Track).mp3: 1 extent found

> 3. stat "/home/sesse/Mika - Life In Cartoon Motion/11 - Ring Ring (Bonus Track).mp3"

pannekake:~# stat "/home/sesse/Mika - Life In Cartoon Motion/11 - Ring Ring (Bonus Track).mp3"
File: `/home/sesse/Mika - Life In Cartoon Motion/11 - Ring Ring (Bonus Track).mp3'
Size: 4050385 Blocks: 0 IO Block: 4096 regular file
Device: fd12h/64786d Inode: 688755 Links: 1
Access: (0644/-rw-r--r--) Uid: ( 1000/ sesse) Gid: ( 1000/ sesse)
Access: 2009-05-30 03:08:38.724454316 +0200
Modify: 2008-09-01 20:38:26.135589449 +0200
Change: 2008-09-01 20:38:26.135589449 +0200

> Does this problem occur at all times?

Yes, it's 100% consistent on that file.

/* Steinar */
--
Homepage: http://www.sesse.net/

2009-06-29 06:03:52

by Akira Fujita

[permalink] [raw]
Subject: Re: Segmentation fault in e4defrag -c

Hi,

Steinar H. Gunderson wrote:
>> 3. stat "/home/sesse/Mika - Life In Cartoon Motion/11 - Ring Ring (Bonus Track).mp3"
>
> pannekake:~# stat "/home/sesse/Mika - Life In Cartoon Motion/11 - Ring Ring (Bonus Track).mp3"
> File: `/home/sesse/Mika - Life In Cartoon Motion/11 - Ring Ring (Bonus Track).mp3'
> Size: 4050385 Blocks: 0 IO Block: 4096 regular file
> Device: fd12h/64786d Inode: 688755 Links: 1
> Access: (0644/-rw-r--r--) Uid: ( 1000/ sesse) Gid: ( 1000/ sesse)
> Access: 2009-05-30 03:08:38.724454316 +0200
> Modify: 2008-09-01 20:38:26.135589449 +0200
> Change: 2008-09-01 20:38:26.135589449 +0200

Thank you for information.

File size is "4050385" but Blocks is "0"
probably means blocks are not allocated yet or file is *corrupted*.
Is your mp3 file available?

Anyway, with this patch, 0 blocks file is skipped,
therefore the segmentation fault you had will not happen.

Thanks and Regards,
Akira Fujita

Signed-off-by Akira Fujita <[email protected]>
---
online-defrag-cmd | 18 ++++++++++++++++++
1 file changed, 18 insertions(+)
--- online-defrag-cmd 2009-06-29 13:07:16.000000000 +0900
+++ online-defrag-cmd-20090629 2009-06-29 13:07:41.000000000 +0900
@@ -1303,6 +1303,15 @@ int file_statistic(const char *file, con
return 0;
}

+ /* Has no blocks */
+ if (buf->st_blocks == 0) {
+ if (mode_flag & DETAIL) {
+ PRINT_FILE_NAME(file);
+ STATISTIC_ERR_MSG("File has no blocks");
+ }
+ return 0;
+ }
+
fd = open64(file, O_RDONLY);
if (fd < 0) {
if (mode_flag & DETAIL) {
@@ -1624,6 +1633,15 @@ int file_defrag(const char *file, const
return 0;
}

+ /* Has no blocks */
+ if (buf->st_blocks == 0) {
+ if (mode_flag & DETAIL) {
+ PRINT_FILE_NAME(file);
+ STATISTIC_ERR_MSG("File has no blocks");
+ }
+ return 0;
+ }
+
fd = open64(file, O_RDONLY);
if (fd < 0) {
if (mode_flag & DETAIL) {

2009-06-29 21:50:17

by Andreas Dilger

[permalink] [raw]
Subject: Re: Segmentation fault in e4defrag -c

On Jun 29, 2009 15:03 +0900, Akira Fujita wrote:
> > Size: 4050385 Blocks: 0 IO Block: 4096 regular file
> > Device: fd12h/64786d Inode: 688755 Links: 1
> > Access: (0644/-rw-r--r--) Uid: ( 1000/ sesse) Gid: ( 1000/ sesse)
> > Access: 2009-05-30 03:08:38.724454316 +0200
> > Modify: 2008-09-01 20:38:26.135589449 +0200
> > Change: 2008-09-01 20:38:26.135589449 +0200
>
> File size is "4050385" but Blocks is "0"
> probably means blocks are not allocated yet or file is *corrupted*.
> Is your mp3 file available?

Well, this is a sparse file for some reason (e.g. failed mp3 p2p download).

> Anyway, with this patch, 0 blocks file is skipped,
> therefore the segmentation fault you had will not happen.

Is it possible that the code has not been tested with sparse files?
In that case, the check for size == 0 is only going to catch a single
case of problem, and not handle general sparse files.

Cheers, Andreas
--
Andreas Dilger
Sr. Staff Engineer, Lustre Group
Sun Microsystems of Canada, Inc.


2009-06-30 23:43:58

by Akira Fujita

[permalink] [raw]
Subject: Re: Segmentation fault in e4defrag -c

Hi,
Andreas Dilger wrote:
> On Jun 29, 2009 15:03 +0900, Akira Fujita wrote:
>>> Size: 4050385 Blocks: 0 IO Block: 4096 regular file
>>> Device: fd12h/64786d Inode: 688755 Links: 1
>>> Access: (0644/-rw-r--r--) Uid: ( 1000/ sesse) Gid: ( 1000/ sesse)
>>> Access: 2009-05-30 03:08:38.724454316 +0200
>>> Modify: 2008-09-01 20:38:26.135589449 +0200
>>> Change: 2008-09-01 20:38:26.135589449 +0200
>> File size is "4050385" but Blocks is "0"
>> probably means blocks are not allocated yet or file is *corrupted*.
>> Is your mp3 file available?
>
> Well, this is a sparse file for some reason (e.g. failed mp3 p2p download).
>

Ah, may be so.

>> Anyway, with this patch, 0 blocks file is skipped,
>> therefore the segmentation fault you had will not happen.
>
> Is it possible that the code has not been tested with sparse files?
> In that case, the check for size == 0 is only going to catch a single
> case of problem, and not handle general sparse files.
>

I have tested files that have sparse blocks
(e.g. files that have sparse blocks in its beginning,
middle and those combinations) and got fine results.
Unfortunately, like this case, only 0 blocks file (all sparse blocks)
has not been tested yet.

But the kernel space (EXT4_IOC_MOVE_EXTENT) does not have this kind of issue.
Because there is a check of whether the extents of orig_inode
that ext4_ext_find_extent() gets is NULL.
If extents is NULL or ext4_ext_find_extent() fails,
ext4_move_extents() returns an error value (e.g. EINVAL) to the user space.

Regards,
Akira Fujita