Re: btrfs zero divide
tl;dr: we got the faulty code pinned down, it's m68k specific, except the m68k specific part didn’t change from 3.2… Joe Perches dixit: Something like this maybe. (uncompiled/untested) I tried this: --- div64.h.orig2013-08-08 19:34:32.663540965 + +++ - 2013-08-08 19:47:30.309776791 + @@ -6,6 +6,8 @@ #else #include linux/types.h +#include linux/bug.h +#include linux/printk.h /* n = n / base; return rem; */ @@ -16,6 +18,11 @@ } __n; \ unsigned long __rem, __upper; \ \ +if (base == 0) { \ +WARN(1, Attempted division by 0\n); \ +dump_stack(); \ +__rem = 0; \ +} else { \ __n.n64 = (n); \ if ((__upper = __n.n32[0])) { \ asm (divul.l %2,%1:%0 \ @@ -26,6 +33,7 @@ : =d (__n.n32[1]), =d (__rem) \ : d (base), 1 (__upper), 0 (__n.n32[1])); \ (n) = __n.n64; \ +} \ __rem; \ }) It didn’t trigger, apparently: [817508.37] bio: create slab bio-1 at 1 [817508.51] Btrfs loaded [817524.11] loop: module loaded [817534.86] device fsid 01cfa645-5cde-4e4c-9b0b-df7b37bdc495 devid 1 transid 4 /dev/loop0 [817534.86] btrfs: disk space caching is enabled [817534.86] *** ZERO DIVIDE *** FORMAT=2 [817534.86] Current process id is 32312 [817534.86] BAD KERNEL TRAP: [817534.86] Modules linked in: loop btrfs lzo_compress zlib_deflate raid6_pq crc32c libcrc32c xor ipv6 evdev mac_hid ext3 mbcache jbd [last unloaded: btrfs] [817534.86] PC: [31c46612] __btrfs_map_block+0x134/0x147a [btrfs] [817534.86] SR: 2000 SP: 0249fab0 a2: 3010f660 [817534.86] d0: d1: 00022000d2: d3: [817534.86] d4: 0001d5: 0001a0: 021777a4a1: 021777a4 [817534.86] Process mount (pid: 32312, task=3010f660) [817534.86] Frame format=2 instr addr=31c4660e [817534.86] Stack from 0249fae8: 0020 1000 00022000 0766a928 07621800 00415d84 0070 077a97c0 0070 0249fb68 0009e250 00d106c0 00011220 0070 0020 00022000 00ff 0009 1000 021777a4 0020 0249fd14 0009e26c 0020 0003 0009dd8a 3007c02c 0766a928 00415d84 1000 0110 31c417ae 0766a928 00415d84 1000 [817534.86] Call Trace: [1000] kernel_pg_dir+0x0/0x1000 [817534.86] [00022000] _060_fpsp_effadd+0xb2c0/0xd518 [817534.86] [0009e250] bvec_alloc+0xa2/0xbe [817534.86] [00011220] sasin+0x87c/0x944 [817534.86] [00022000] _060_fpsp_effadd+0xb2c0/0xd518 [817534.86] [1000] kernel_pg_dir+0x0/0x1000 [817534.86] [0009e26c] bio_alloc_bioset+0x0/0x12e [817534.86] [0009dd8a] bio_add_page+0x4a/0x58 [817534.86] [1000] kernel_pg_dir+0x0/0x1000 [817534.86] [31c417ae] submit_extent_page.isra.44+0x170/0x1bc [btrfs] [817534.86] [1000] kernel_pg_dir+0x0/0x1000 [817534.86] [1000] kernel_pg_dir+0x0/0x1000 [817534.86] [31c4cbfe] btrfs_map_bio+0x60/0x48c [btrfs] [817534.86] [00022000] _060_fpsp_effadd+0xb2c0/0xd518 [817534.86] [00022000] _060_fpsp_effadd+0xb2c0/0xd518 [817534.86] [31c24bb2] btree_submit_bio_hook+0x0/0xae [btrfs] [817534.86] [31c41ae4] end_bio_extent_readpage+0x0/0x69c [btrfs] [817534.86] [1000] kernel_pg_dir+0x0/0x1000 [817534.86] [31c24984] btrfs_bio_wq_end_io+0x16/0x50 [btrfs] [817534.86] [31c24c0e] btree_submit_bio_hook+0x5c/0xae [btrfs] [817534.87] [00022000] _060_fpsp_effadd+0xb2c0/0xd518 [817534.87] [31c3ed7a] submit_one_bio+0x7c/0xb2 [btrfs] [817534.87] [00022000] _060_fpsp_effadd+0xb2c0/0xd518 [817534.87] [31c421b8] __extent_read_full_page+0x0/0x70a [btrfs] [817534.87] [00058828] unlock_page+0x0/0x26 [817534.87] [31c44780] read_extent_buffer_pages+0x1a8/0x218 [btrfs] [817534.88] [31c4c3b2] btrfs_num_copies+0x0/0x142 [btrfs] [817534.88] [31c23aa6] btree_read_extent_buffer_pages.constprop.52+0x42/0xca [btrfs] [817534.88] [31c22802] btree_get_extent+0x0/0x102 [btrfs] [817534.88] [00022000] _060_fpsp_effadd+0xb2c0/0xd518 [817534.88] [1000] kernel_pg_dir+0x0/0x1000 [817534.88] [31c2525e] read_tree_block+0x38/0x48 [btrfs] [817534.88] [31c25226] read_tree_block+0x0/0x48 [btrfs] [817534.89] [31c26d40] open_ctree+0xe80/0x15e6 [btrfs] [817534.89] [00022000] _060_fpsp_effadd+0xb2c0/0xd518 [817534.89] [1000] kernel_pg_dir+0x0/0x1000 [817534.89] [1000] kernel_pg_dir+0x0/0x1000 [817534.89] [1000] kernel_pg_dir+0x0/0x1000
Re: btrfs zero divide
Geert Uytterhoeven dixit: 0: 222e ff74 movel %fp@(-140),%d1 4: 2a2e ff5c movel %fp@(-164),%d5 8: 2c2e ff60 movel %fp@(-160),%d6 c: 4c45 1402 divul %d5,%d2,%d1 10: 2d40 ff64 movel %d0,%fp@(-156) 14: 2d41 ff68 movel %d1,%fp@(-152) 18: 2205movel %d5,%d1 1a: 4c2e 1800 ff68 mulsl %fp@(-152),%d1 20: 4c04 0800 mulsl %d4,%d0 24: 2041moveal %d1,%a0 26: d1c0addal %d0,%a0 28: 2206movel %d6,%d1 2a: 4c2e 1400 ff68 mulul %fp@(-152),%d0,%d1 This is gcc-4.8 compiled, btw… in case that’s a known issue. bye, //mirabilos -- “It is inappropriate to require that a time represented as seconds since the Epoch precisely represent the number of seconds between the referenced time and the Epoch.” -- IEEE Std 1003.1b-1993 (POSIX) Section B.2.2.2 -- To unsubscribe from this list: send the line unsubscribe linux-btrfs in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: btrfs zero divide
Josef Bacik dixit: Can you gdb btrfs.ko and do list *(__btrfs_map_block+0x11c) Not easily (the kernel image is from a .deb package), and even in a compile tree gdb just says: No symbol table is loaded. Use the file command. With a bit of cheating and a cross-compiler, this is: (gdb) list *0x106e 0x106e is in __btrfs_map_block (/var/lib/gforge/chroot/home/users/tg/Xl/linux-3.10.1/fs/btrfs/volumes.c:4447). 4442stripe_nr = offset; 4443/* * stripe_nr counts the total number of stripes we have to stride 4445 * to get to this block 4446 */ 4447do_div(stripe_nr, stripe_len); 4448 4449stripe_offset = stripe_nr * stripe_len; 4450BUG_ON(offset stripe_offset); 4451 The code is somewhat matching: 0x1062 +268: movel %fp@(-140),%d1 0x1066 +272: movel %fp@(-164),%d5 0x106a +276: movel %fp@(-160),%d6 0x106e +280: divul %d5,%d2,%d1 0x1072 +284: movel %d0,%fp@(-156) 0x1076 +288: movel %d1,%fp@(-152) 0x107a +292: movel %d5,%d1 0x107c +294: mulsl %fp@(-152),%d1 0x1082 +300: mulsl %d4,%d0 0x1086 +304: moveal %d1,%a0 0x1088 +306: addal %d0,%a0 0x108a +308: movel %d6,%d1 0x108c +310: mulul %fp@(-152),%d0,%d1 According to the registers… [ 38.80] d0: d1: 1000d2: d3: [ 38.83] d4: 0001d5: a0: 3085c72ca1: 3085c72c … this is (if I parse this right) 1000 / (64-bit D2:D1 divided by 32-bit D5 store into D1, remainder into D2). Joe Perches dixit quod… do_div seems a likely suspect... I do admit I don’t understand arch/m68k/include/asm/div64.h being not a real m68k coder, but “it works elsewhere”… (And I loathe GCC inline asm with a passion!) From the code expansion, I assume (__upper = __n.n32[0]) is always zero (as we get only one divul instruction). This looks a bit weird because the numbers in question are all 64 bit (stripe_nr, offset, logical). Hm, actually… from a test program… #include stdio.h typedef unsigned long long u64; int main(void) { u64 stripe_nr; u64 stripe_len; stripe_nr = 1234; stripe_len = 2; printf(in : %llu / %llu\n, stripe_nr, stripe_len); ({ union { unsigned long n32[2]; unsigned long long n64; } __n; unsigned long __rem, __upper; __n.n64 = (stripe_nr); if ((__upper = __n.n32[0])) { asm (divul.l %2,%1:%0 : =d (__n.n32[0]), =d (__upper) : d (stripe_len), 0 (__n.n32[0])); } asm (divu.l %2,%1:%0 : =d (__n.n32[1]), =d (__rem) : d (stripe_len), 1 (__upper), 0 (__n.n32[1])); (stripe_nr) = __n.n64; __rem; }); printf(out: %llu R %llu\n, stripe_nr, stripe_len); return (0); } … I think we get two divul instructions, just with a lot of moves between them. Hmpf. The frame pointer would be useful to know, to know the proper values used for these operations… … Aaaah okay. Some reading *(gdb.info):: later, indeed: (gdb) info line 4446 Line 4446 of /var/lib/gforge/chroot/home/users/tg/Xl/linux-3.10.1/fs/btrfs/volumes.c is at address 0x104a __btrfs_map_block+244 but contains no code. (gdb) info line 4448 Line 4448 of /var/lib/gforge/chroot/home/users/tg/Xl/linux-3.10.1/fs/btrfs/volumes.c is at address 0x107a __btrfs_map_block+292 but contains no code. (gdb) disas /r 0x104a,0x107a Dump of assembler code from 0x104a to 0x107a: 0x104a __btrfs_map_block+244: 20 02 movel %d2,%d0 0x104c __btrfs_map_block+246: 24 2e ff 70 movel %fp@(-144),%d2 0x1050 __btrfs_map_block+250: 4a 80 tstl %d0 0x1052 __btrfs_map_block+252: 67 0e beqs 0x1062 __btrfs_map_block+268 0x1054 __btrfs_map_block+254: 20 02 movel %d2,%d0 0x1056 __btrfs_map_block+256: 2c 2e ff 5c movel %fp@(-164),%d6 0x105a __btrfs_map_block+260: 2e 2e ff 60 movel %fp@(-160),%d7 0x105e __btrfs_map_block+264: 4c 46 00 02 divull %d6,%d2,%d0 0x1062 __btrfs_map_block+268: 22 2e ff 74 movel %fp@(-140),%d1 0x1066 __btrfs_map_block+272: 2a 2e ff 5c movel %fp@(-164),%d5 0x106a __btrfs_map_block+276: 2c 2e ff 60 movel %fp@(-160),%d6 0x106e __btrfs_map_block+280: 4c 45 14 02 divul %d5,%d2,%d1 0x1072 __btrfs_map_block+284: 2d 40 ff 64 movel %d0,%fp@(-156) 0x1076 __btrfs_map_block+288: 2d 41 ff 68 movel %d1,%fp@(-152) End of assembler dump. Now, can anyone more fluent in m68k asm make out a problem with it? bye, //mirabilos -- I believe no one can invent an algorithm. One just happens to hit upon it when God enlightens him. Or only God invents algorithms, we merely copy them. If you don't believe in God, just consider God as Nature if you won't deny existence. -- Coywolf Qi Hunt -- To unsubscribe from this list: send the line unsubscribe linux-btrfs in the body of a message to majord...@vger.kernel.org More majordomo info at
Re: btrfs zero divide
Josef Bacik dixit: So stripe_len shouldn't be 0, if it is you have bigger problems :). ☺ Is this a corrupt fs or something? If there was some sort of I don’t think so, I can access and use that filesystem under 3.2 just fine (it’s what I created it under, too, so it’s possible that it’s indeed corrupt and Linux 3.2 is just the same corrupt to happen to make it work, e.g. wrong endianness used for stripe_len which makes the upper 32 bit of that 64-bit value (usually 0) become the lower 32 bit, or something like that). I have access to that system, and it’s currently running as a Debian/m68k buildd using said filesystem, but I can run commands you tell me to diagnose/analyse it if it won’t get corrupted by those. Joe Perches dixit: Maybe use a temporary check in do_div Mh. If nobody finds anything I’ll try that. (Doing things like compiling a kernel and testing it takes about two days timeboxed and some hours of active human effort, though, so I’d like to avoid guessing. Plus it’ll disrupt running the Debian buildd…) On second thoughts, this sort of check sounds like a good idea to add to that file in general, depending on some debugging CPPFLAG or Kconfig option. But I’m not the authority on that. bye, //mirabilos -- ch you introduced a merge commit│mika % g rebase -i HEAD^^ mika sorry, no idea and rebasing just fscked │mika Segmentation ch should have cloned into a clean repo │ fault (core dumped) ch if I rebase that now, it's really ugh │mika:#grml wuahh -- To unsubscribe from this list: send the line unsubscribe linux-btrfs in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html