* m68k boot failure in -next bisected to 'xarray: Replace exceptional entries'
@ 2018-06-22 18:42 Guenter Roeck
2018-06-22 21:05 ` Matthew Wilcox
0 siblings, 1 reply; 13+ messages in thread
From: Guenter Roeck @ 2018-06-22 18:42 UTC (permalink / raw)
To: Matthew Wilcox; +Cc: Josef Bacik, Geert Uytterhoeven, linux-m68k, linux-kernel
Hi,
a few days ago, m68k boot tests in linux-next started to crash.
I bisected the problem to commit 'xarray: Replace exceptional entries'.
Bisect and crash logs are attached below.
My apologies for the noise if this has already been reported and/or
addressed.
Guenter
---
# bad: [2e6381681ec48ed6dd455473a657d8a393518aa6] Add linux-next specific files for 20180622
# good: [ce397d215ccd07b8ae3f71db689aedb85d56ab40] Linux 4.18-rc1
git bisect start 'HEAD' 'v4.18-rc1'
# good: [07b762f7baf30aaa93d35f36ff367d4b36632059] Merge remote-tracking branch 'spi-nor/spi-nor/next'
git bisect good 07b762f7baf30aaa93d35f36ff367d4b36632059
# good: [c61d3dfe9381fc4b72541fd7698951b290d2a776] Merge remote-tracking branch 'tip/auto-latest'
git bisect good c61d3dfe9381fc4b72541fd7698951b290d2a776
# good: [a92ae111eb9e0f6f05f1173cf91c20fccda1a833] Merge remote-tracking branch 'scsi-mkp/for-next'
git bisect good a92ae111eb9e0f6f05f1173cf91c20fccda1a833
# bad: [1aa90eab1a14860f0d128ad67edf7b0381fa44e8] Merge remote-tracking branch 'xarray/xarray'
git bisect bad 1aa90eab1a14860f0d128ad67edf7b0381fa44e8
# good: [22ca6bc3dfd805a53f303fa5362fcc19e9c52565] Merge remote-tracking branch 'nvdimm/libnvdimm-for-next'
git bisect good 22ca6bc3dfd805a53f303fa5362fcc19e9c52565
# bad: [932116ce98f3d2ddf3e9eb243eebd62ebddebee9] mm: Convert page migration to XArray
git bisect bad 932116ce98f3d2ddf3e9eb243eebd62ebddebee9
# bad: [68fd9dcd423f49c4c916c0f222f12193f0c1655d] page cache: Rearrange address_space
git bisect bad 68fd9dcd423f49c4c916c0f222f12193f0c1655d
# bad: [8c0feb14b49670ea363ccef3f42165df64a5852e] xarray: Add XArray tags
git bisect bad 8c0feb14b49670ea363ccef3f42165df64a5852e
# bad: [88f2e731264b03319b9d0475ceadd0cc1d1dcefb] xarray: Change definition of sibling entries
git bisect bad 88f2e731264b03319b9d0475ceadd0cc1d1dcefb
# good: [0826cef09f48e767ad7416d1047fe4726addc49d] radix tree test suite: Enable ubsan
git bisect good 0826cef09f48e767ad7416d1047fe4726addc49d
# bad: [087ba81049d32c762831ae58de0b00fd6467ee8e] xarray: Replace exceptional entries
git bisect bad 087ba81049d32c762831ae58de0b00fd6467ee8e
# good: [8255ddef2101b02a1dc63461121903e25ed82873] dax: Fix use of zero page
git bisect good 8255ddef2101b02a1dc63461121903e25ed82873
# first bad commit: [087ba81049d32c762831ae58de0b00fd6467ee8e] xarray: Replace exceptional entries
---
...
SCSI subsystem initialized
------------[ cut here ]------------
WARNING: CPU: 0 PID: 1 at lib/idr.c:42 idr_alloc_u32+0x44/0xe8
Modules linked in:
CPU: 0 PID: 1 Comm: swapper Not tainted 4.18.0-rc1-next-20180622-mac #1
Stack from 0781fe3c:
0781fe3c 0036d51c 000180d6 ffffffea 00000000 0036dfe6 00000020 000020e8
003abf1c 0036dfe6 0001816a 0036d51f 0000002a 002b50e4 00000009 00000000
00000000 00340ae9 002b50e4 0036d51f 0000002a 00000010 0036dfee 00000000
00000010 0036dfe6 003f7518 0781feb8 00000000 00000078 002f7f6a 002b51e4
003abf1c 0036dfe6 0781fed4 00000010 006000c0 07800100 00000010 0781ff8c
00247160 003abf1c 0036dfe6 00000010 00000011 006000c0 00000078 00000005
Call Trace: [<000180d6>] __warn+0xc0/0xc2
[<000020e8>] do_one_initcall+0x0/0x140
[<0001816a>] warn_slowpath_null+0x26/0x2c
[<002b50e4>] idr_alloc_u32+0x44/0xe8
[<002b50e4>] idr_alloc_u32+0x44/0xe8
[<002b51e4>] idr_alloc+0x5c/0x76
[<00247160>] genl_register_family+0x14c/0x54c
[<000020e8>] do_one_initcall+0x0/0x140
[<003f0f02>] genl_init+0x0/0x34
[<003f0ce6>] bpf_lwt_init+0x10/0x14
[<003f0f0e>] genl_init+0xc/0x34
[<00002142>] do_one_initcall+0x5a/0x140
[<00029828>] parse_args+0x0/0x202
[<000020e8>] do_one_initcall+0x0/0x140
[<002bf6c4>] strcpy+0x0/0x1c
[<00040004>] timekeeping_resume+0x280/0x2cc
[<003df1e6>] kernel_init_freeable+0x176/0x190
[<002bf6c4>] strcpy+0x0/0x1c
[<003df1fc>] kernel_init_freeable+0x18c/0x190
[<003f0f02>] genl_init+0x0/0x34
[<002c4b66>] kernel_init+0x0/0xd2
[<002c4b6e>] kernel_init+0x8/0xd2
[<002c4b66>] kernel_init+0x0/0xd2
[<000028e0>] ret_from_kernel_thread+0xc/0x14
---[ end trace 62c263e59debfdfe ]---
Kernel panic - not syncing: GENL: Cannot register controller: -22
CPU: 0 PID: 1 Comm: swapper Tainted: G W 4.18.0-rc1-next-20180622-mac #1
Stack from 0781fef0:
0781fef0 0036d51c 00018216 00000078 00000005 0055a040 00000000 003f0f02
003ff868 003f7518 0781ff8c 003f0f34 0036849f ffffffea 00002142 00000078
00000005 0055a040 00029828 000020e8 00000000 003f7538 003ff868 00000000
003f7534 00000004 003f7518 002bf6c4 00040004 0055a052 0055a05a 003df1e6
0033e814 0055a040 0038fd64 00000078 00000004 00000004 00000000 002bf6c4
003df1fc 003f0f02 00000000 0781774c 0000000f 00000000 00000000 002c4b66
Call Trace: [<00018216>] panic+0xa6/0x230
[<003f0f02>] genl_init+0x0/0x34
[<003f0f34>] genl_init+0x32/0x34
[<00002142>] do_one_initcall+0x5a/0x140
[<00029828>] parse_args+0x0/0x202
[<000020e8>] do_one_initcall+0x0/0x140
[<002bf6c4>] strcpy+0x0/0x1c
[<00040004>] timekeeping_resume+0x280/0x2cc
[<003df1e6>] kernel_init_freeable+0x176/0x190
[<002bf6c4>] strcpy+0x0/0x1c
[<003df1fc>] kernel_init_freeable+0x18c/0x190
[<003f0f02>] genl_init+0x0/0x34
[<002c4b66>] kernel_init+0x0/0xd2
[<002c4b6e>] kernel_init+0x8/0xd2
[<002c4b66>] kernel_init+0x0/0xd2
[<000028e0>] ret_from_kernel_thread+0xc/0x14
---[ end Kernel panic - not syncing: GENL: Cannot register controller: -22
^ permalink raw reply [flat|nested] 13+ messages in thread* Re: m68k boot failure in -next bisected to 'xarray: Replace exceptional entries' 2018-06-22 18:42 m68k boot failure in -next bisected to 'xarray: Replace exceptional entries' Guenter Roeck @ 2018-06-22 21:05 ` Matthew Wilcox 2018-06-22 22:33 ` Guenter Roeck 0 siblings, 1 reply; 13+ messages in thread From: Matthew Wilcox @ 2018-06-22 21:05 UTC (permalink / raw) To: Guenter Roeck; +Cc: Josef Bacik, Geert Uytterhoeven, linux-m68k, linux-kernel On Fri, Jun 22, 2018 at 11:42:46AM -0700, Guenter Roeck wrote: > Hi, > > a few days ago, m68k boot tests in linux-next started to crash. > I bisected the problem to commit 'xarray: Replace exceptional entries'. > Bisect and crash logs are attached below. Thank you! I was afraid something like this might happen. > ------------[ cut here ]------------ > WARNING: CPU: 0 PID: 1 at lib/idr.c:42 idr_alloc_u32+0x44/0xe8 Line 42 is: if (WARN_ON_ONCE(radix_tree_is_internal_node(ptr))) return -EINVAL; The pointer passed in to idr_alloc() is not 4-byte aligned; it's aligned to a 2 byte boundary. I'm having a little trouble seeing who it is that's passing in what pointer ... > Call Trace: [<000180d6>] __warn+0xc0/0xc2 > [<000020e8>] do_one_initcall+0x0/0x140 > [<0001816a>] warn_slowpath_null+0x26/0x2c > [<002b50e4>] idr_alloc_u32+0x44/0xe8 > [<002b50e4>] idr_alloc_u32+0x44/0xe8 > [<002b51e4>] idr_alloc+0x5c/0x76 > [<00247160>] genl_register_family+0x14c/0x54c It makes sense to here (other than idr_alloc being listed twice) > [<000020e8>] do_one_initcall+0x0/0x140 > [<003f0f02>] genl_init+0x0/0x34 Assuming this is right, that would imply that genl_ctrl is not 4-byte aligned. Is that true? I'm not familiar with the m68k alignment rules, but it has a lot of 4-byte sized quantities in the struct, so I would assume it's 4-byte aligned. > [<003f0ce6>] bpf_lwt_init+0x10/0x14 I don't think this is the caller. > [<003f0f0e>] genl_init+0xc/0x34 > [<00002142>] do_one_initcall+0x5a/0x140 > [<00029828>] parse_args+0x0/0x202 > [<000020e8>] do_one_initcall+0x0/0x140 > [<002bf6c4>] strcpy+0x0/0x1c > [<00040004>] timekeeping_resume+0x280/0x2cc > [<003df1e6>] kernel_init_freeable+0x176/0x190 > [<002bf6c4>] strcpy+0x0/0x1c > [<003df1fc>] kernel_init_freeable+0x18c/0x190 > [<003f0f02>] genl_init+0x0/0x34 > [<002c4b66>] kernel_init+0x0/0xd2 > [<002c4b6e>] kernel_init+0x8/0xd2 > [<002c4b66>] kernel_init+0x0/0xd2 > [<000028e0>] ret_from_kernel_thread+0xc/0x14 > ---[ end trace 62c263e59debfdfe ]--- > Kernel panic - not syncing: GENL: Cannot register controller: -22 ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: m68k boot failure in -next bisected to 'xarray: Replace exceptional entries' 2018-06-22 21:05 ` Matthew Wilcox @ 2018-06-22 22:33 ` Guenter Roeck 2018-06-23 7:46 ` Matthew Wilcox ` (2 more replies) 0 siblings, 3 replies; 13+ messages in thread From: Guenter Roeck @ 2018-06-22 22:33 UTC (permalink / raw) To: Matthew Wilcox; +Cc: Josef Bacik, Geert Uytterhoeven, linux-m68k, linux-kernel On Fri, Jun 22, 2018 at 02:05:19PM -0700, Matthew Wilcox wrote: > On Fri, Jun 22, 2018 at 11:42:46AM -0700, Guenter Roeck wrote: > > Hi, > > > > a few days ago, m68k boot tests in linux-next started to crash. > > I bisected the problem to commit 'xarray: Replace exceptional entries'. > > Bisect and crash logs are attached below. > > Thank you! I was afraid something like this might happen. > > > ------------[ cut here ]------------ > > WARNING: CPU: 0 PID: 1 at lib/idr.c:42 idr_alloc_u32+0x44/0xe8 > > Line 42 is: > > if (WARN_ON_ONCE(radix_tree_is_internal_node(ptr))) > return -EINVAL; > > The pointer passed in to idr_alloc() is not 4-byte aligned; it's aligned > to a 2 byte boundary. I'm having a little trouble seeing who it is that's > passing in what pointer ... > > > Call Trace: [<000180d6>] __warn+0xc0/0xc2 > > [<000020e8>] do_one_initcall+0x0/0x140 > > [<0001816a>] warn_slowpath_null+0x26/0x2c > > [<002b50e4>] idr_alloc_u32+0x44/0xe8 > > [<002b50e4>] idr_alloc_u32+0x44/0xe8 > > [<002b51e4>] idr_alloc+0x5c/0x76 > > [<00247160>] genl_register_family+0x14c/0x54c > > It makes sense to here (other than idr_alloc being listed twice) > > > [<000020e8>] do_one_initcall+0x0/0x140 > > [<003f0f02>] genl_init+0x0/0x34 > > Assuming this is right, that would imply that genl_ctrl is not 4-byte > aligned. Is that true? I'm not familiar with the m68k alignment rules, > but it has a lot of 4-byte sized quantities in the struct, so I would > assume it's 4-byte aligned. > > > [<003f0ce6>] bpf_lwt_init+0x10/0x14 > > I don't think this is the caller. > Here is the culprit: genl_register_family(0x36dd7a) registering VFS_DQUOT ------------[ cut here ]------------ WARNING: CPU: 0 PID: 1 at lib/idr.c:42 idr_alloc_u32+0x44/0xe8 It may be odd that fs/quota/netlink.c:quota_genl_family is not word aligned, but on the other side I don't think there is a rule that the function parameter to genl_register_family() - or the second parameter of idr_alloc() - must be word aligned. Am I missing something ? After all, it could be a pointer to the nth element of a string, or the caller could on purpose allocate IDRs for (ptr), (ptr + 1), and so on. Thanks, Guenter ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: m68k boot failure in -next bisected to 'xarray: Replace exceptional entries' 2018-06-22 22:33 ` Guenter Roeck @ 2018-06-23 7:46 ` Matthew Wilcox 2018-06-23 16:43 ` Guenter Roeck 2018-06-23 20:51 ` Geert Uytterhoeven 2018-06-24 1:17 ` Matthew Wilcox 2 siblings, 1 reply; 13+ messages in thread From: Matthew Wilcox @ 2018-06-23 7:46 UTC (permalink / raw) To: Guenter Roeck; +Cc: Josef Bacik, Geert Uytterhoeven, linux-m68k, linux-kernel On Fri, Jun 22, 2018 at 03:33:35PM -0700, Guenter Roeck wrote: > On Fri, Jun 22, 2018 at 02:05:19PM -0700, Matthew Wilcox wrote: > > On Fri, Jun 22, 2018 at 11:42:46AM -0700, Guenter Roeck wrote: > > > Hi, > > > > > > a few days ago, m68k boot tests in linux-next started to crash. > > > I bisected the problem to commit 'xarray: Replace exceptional entries'. > > > Bisect and crash logs are attached below. > > > > Thank you! I was afraid something like this might happen. > > > > > ------------[ cut here ]------------ > > > WARNING: CPU: 0 PID: 1 at lib/idr.c:42 idr_alloc_u32+0x44/0xe8 > > > > Line 42 is: > > > > if (WARN_ON_ONCE(radix_tree_is_internal_node(ptr))) > > return -EINVAL; > > > > The pointer passed in to idr_alloc() is not 4-byte aligned; it's aligned > > to a 2 byte boundary. I'm having a little trouble seeing who it is that's > > passing in what pointer ... > > > > > Call Trace: [<000180d6>] __warn+0xc0/0xc2 > > > [<000020e8>] do_one_initcall+0x0/0x140 > > > [<0001816a>] warn_slowpath_null+0x26/0x2c > > > [<002b50e4>] idr_alloc_u32+0x44/0xe8 > > > [<002b50e4>] idr_alloc_u32+0x44/0xe8 > > > [<002b51e4>] idr_alloc+0x5c/0x76 > > > [<00247160>] genl_register_family+0x14c/0x54c > > > > It makes sense to here (other than idr_alloc being listed twice) > > > > > [<000020e8>] do_one_initcall+0x0/0x140 > > > [<003f0f02>] genl_init+0x0/0x34 > > > > Assuming this is right, that would imply that genl_ctrl is not 4-byte > > aligned. Is that true? I'm not familiar with the m68k alignment rules, > > but it has a lot of 4-byte sized quantities in the struct, so I would > > assume it's 4-byte aligned. > > > > > [<003f0ce6>] bpf_lwt_init+0x10/0x14 > > > > I don't think this is the caller. > > > > Here is the culprit: > > genl_register_family(0x36dd7a) registering VFS_DQUOT > ------------[ cut here ]------------ > WARNING: CPU: 0 PID: 1 at lib/idr.c:42 idr_alloc_u32+0x44/0xe8 > > It may be odd that fs/quota/netlink.c:quota_genl_family is not word > aligned, but on the other side I don't think there is a rule that > the function parameter to genl_register_family() - or the second > parameter of idr_alloc() - must be word aligned. Am I missing > something ? After all, it could be a pointer to the nth element > of a string, or the caller could on purpose allocate IDRs for > (ptr), (ptr + 1), and so on. There actually is a rule that pointers passed to the IDR be aligned. It might not be written down anywhere ;-) And I'm quite happy to lift that restriction; after all I don't want to force everybody to decorate definitions with __aligned(4). I'll see what I can do to fix it. I'm actually on holiday this week, so a fix may be delayed. ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: m68k boot failure in -next bisected to 'xarray: Replace exceptional entries' 2018-06-23 7:46 ` Matthew Wilcox @ 2018-06-23 16:43 ` Guenter Roeck 2018-06-23 23:20 ` Matthew Wilcox 0 siblings, 1 reply; 13+ messages in thread From: Guenter Roeck @ 2018-06-23 16:43 UTC (permalink / raw) To: Matthew Wilcox; +Cc: Josef Bacik, Geert Uytterhoeven, linux-m68k, linux-kernel On 06/23/2018 12:46 AM, Matthew Wilcox wrote: >> >> Here is the culprit: >> >> genl_register_family(0x36dd7a) registering VFS_DQUOT >> ------------[ cut here ]------------ >> WARNING: CPU: 0 PID: 1 at lib/idr.c:42 idr_alloc_u32+0x44/0xe8 >> >> It may be odd that fs/quota/netlink.c:quota_genl_family is not word >> aligned, but on the other side I don't think there is a rule that >> the function parameter to genl_register_family() - or the second >> parameter of idr_alloc() - must be word aligned. Am I missing >> something ? After all, it could be a pointer to the nth element >> of a string, or the caller could on purpose allocate IDRs for >> (ptr), (ptr + 1), and so on. > > There actually is a rule that pointers passed to the IDR be aligned. > It might not be written down anywhere ;-) And I'm quite happy to lift > that restriction; after all I don't want to force everybody to decorate > definitions with __aligned(4). > I am not sure if that is really correct, or at least I was unable to find such a restriction documented or even mentioned anywhere. It is true for radix trees, but even there the restriction used to be "even". This was changed to "word aligned" with commit 3bcadd6fa6c4f, and the offending commit here moves the "INTERNAL" bit from position 0 to 1. This is quite a subtle change that was introduced over time. I'd be not surprised if there are other more severe problems lurking in the radix tree code and/or its users because of that. Either case, I think the check for radix_tree_is_internal_node() in idr_alloc_u32() is wrong. If anything, it should be radix_tree_exception(). If that was the case, the problem (and maybe other similar problems) would have been found with commit 3bcadd6fa6c4f, not only now. Guenter ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: m68k boot failure in -next bisected to 'xarray: Replace exceptional entries' 2018-06-23 16:43 ` Guenter Roeck @ 2018-06-23 23:20 ` Matthew Wilcox 0 siblings, 0 replies; 13+ messages in thread From: Matthew Wilcox @ 2018-06-23 23:20 UTC (permalink / raw) To: Guenter Roeck; +Cc: Josef Bacik, Geert Uytterhoeven, linux-m68k, linux-kernel On Sat, Jun 23, 2018 at 09:43:41AM -0700, Guenter Roeck wrote: > On 06/23/2018 12:46 AM, Matthew Wilcox wrote: > > There actually is a rule that pointers passed to the IDR be aligned. > > It might not be written down anywhere ;-) And I'm quite happy to lift > > that restriction; after all I don't want to force everybody to decorate > > definitions with __aligned(4). > > I am not sure if that is really correct, or at least I was unable to > find such a restriction documented or even mentioned anywhere. It is > true for radix trees, but even there the restriction used to be "even". > This was changed to "word aligned" with commit 3bcadd6fa6c4f, and the > offending commit here moves the "INTERNAL" bit from position 0 to 1. > This is quite a subtle change that was introduced over time. I'd be > not surprised if there are other more severe problems lurking in > the radix tree code and/or its users because of that. > > Either case, I think the check for radix_tree_is_internal_node() in > idr_alloc_u32() is wrong. If anything, it should be radix_tree_exception(). > If that was the case, the problem (and maybe other similar problems) > would have been found with commit 3bcadd6fa6c4f, not only now. Oh, but we want people to be able to store exceptional entries as well as pointers. So this was the right solution at the time. Now that I'm trying to expand the range of exceptional entries, it's time to make all (*) values storable in the IDR. (*) Still not all. The radix tree/IDR/XArray reserve some values for its own use. Various values below 4096 and above -4095, for example. Here's the test-case I'm currently working on: +static void idr_align_test(struct idr *idr) +{ + char name[] = "Motorola 68000"; + int i; + + for (i = 0; i < 9; i++) + BUG_ON(idr_alloc(idr, &name[i], 0, 0, GFP_KERNEL) != i); + idr_destroy(idr); + + for (i = 1; i < 10; i++) + BUG_ON(idr_alloc(idr, &name[i], 0, 0, GFP_KERNEL) != i - 1); + idr_destroy(idr); + + for (i = 2; i < 11; i++) + BUG_ON(idr_alloc(idr, &name[i], 0, 0, GFP_KERNEL) != i - 2); + idr_destroy(idr); + + for (i = 3; i < 12; i++) + BUG_ON(idr_alloc(idr, &name[i], 0, 0, GFP_KERNEL) != i - 3); + idr_destroy(idr); + + for (i = 0; i < 8; i++) { + BUG_ON(idr_alloc(idr, &name[i], 0, 0, GFP_KERNEL) != 0); + BUG_ON(idr_alloc(idr, &name[i + 1], 0, 0, GFP_KERNEL) != 1); + idr_remove(idr, 1); + idr_remove(idr, 0); + BUG_ON(!idr_is_empty(idr)); + } +} ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: m68k boot failure in -next bisected to 'xarray: Replace exceptional entries' 2018-06-22 22:33 ` Guenter Roeck 2018-06-23 7:46 ` Matthew Wilcox @ 2018-06-23 20:51 ` Geert Uytterhoeven 2018-06-24 1:17 ` Matthew Wilcox 2 siblings, 0 replies; 13+ messages in thread From: Geert Uytterhoeven @ 2018-06-23 20:51 UTC (permalink / raw) To: Guenter Roeck Cc: Matthew Wilcox, Josef Bacik, linux-m68k, Linux Kernel Mailing List Hi all, On Sat, Jun 23, 2018 at 12:33 AM Guenter Roeck <linux@roeck-us.net> wrote: > On Fri, Jun 22, 2018 at 02:05:19PM -0700, Matthew Wilcox wrote: > > On Fri, Jun 22, 2018 at 11:42:46AM -0700, Guenter Roeck wrote: > > > a few days ago, m68k boot tests in linux-next started to crash. > > > I bisected the problem to commit 'xarray: Replace exceptional entries'. > > > Bisect and crash logs are attached below. > > > > Thank you! I was afraid something like this might happen. > > > > > ------------[ cut here ]------------ > > > WARNING: CPU: 0 PID: 1 at lib/idr.c:42 idr_alloc_u32+0x44/0xe8 > > > > Line 42 is: > > > > if (WARN_ON_ONCE(radix_tree_is_internal_node(ptr))) > > return -EINVAL; > > > > The pointer passed in to idr_alloc() is not 4-byte aligned; it's aligned > > to a 2 byte boundary. I'm having a little trouble seeing who it is that's > > passing in what pointer ... > > > > > Call Trace: [<000180d6>] __warn+0xc0/0xc2 > > > [<000020e8>] do_one_initcall+0x0/0x140 > > > [<0001816a>] warn_slowpath_null+0x26/0x2c > > > [<002b50e4>] idr_alloc_u32+0x44/0xe8 > > > [<002b50e4>] idr_alloc_u32+0x44/0xe8 > > > [<002b51e4>] idr_alloc+0x5c/0x76 > > > [<00247160>] genl_register_family+0x14c/0x54c > > > > It makes sense to here (other than idr_alloc being listed twice) > > > > > [<000020e8>] do_one_initcall+0x0/0x140 > > > [<003f0f02>] genl_init+0x0/0x34 > > > > Assuming this is right, that would imply that genl_ctrl is not 4-byte > > aligned. Is that true? I'm not familiar with the m68k alignment rules, > > but it has a lot of 4-byte sized quantities in the struct, so I would > > assume it's 4-byte aligned. > > > > > [<003f0ce6>] bpf_lwt_init+0x10/0x14 > > > > I don't think this is the caller. > > > > Here is the culprit: > > genl_register_family(0x36dd7a) registering VFS_DQUOT > ------------[ cut here ]------------ > WARNING: CPU: 0 PID: 1 at lib/idr.c:42 idr_alloc_u32+0x44/0xe8 > > It may be odd that fs/quota/netlink.c:quota_genl_family is not word > aligned, but on the other side I don't think there is a rule that On m68k (and a few other architectures), the alignment of int and larger integral types is 2 bytes. > the function parameter to genl_register_family() - or the second > parameter of idr_alloc() - must be word aligned. Am I missing > something ? After all, it could be a pointer to the nth element > of a string, or the caller could on purpose allocate IDRs for > (ptr), (ptr + 1), and so on. Good point. Gr{oetje,eeting}s, Geert -- Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org In personal conversations with technical people, I call myself a hacker. But when I'm talking to journalists I just say "programmer" or something like that. -- Linus Torvalds ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: m68k boot failure in -next bisected to 'xarray: Replace exceptional entries' 2018-06-22 22:33 ` Guenter Roeck 2018-06-23 7:46 ` Matthew Wilcox 2018-06-23 20:51 ` Geert Uytterhoeven @ 2018-06-24 1:17 ` Matthew Wilcox 2018-06-24 2:52 ` Guenter Roeck 2 siblings, 1 reply; 13+ messages in thread From: Matthew Wilcox @ 2018-06-24 1:17 UTC (permalink / raw) To: Guenter Roeck; +Cc: Josef Bacik, Geert Uytterhoeven, linux-m68k, linux-kernel On Fri, Jun 22, 2018 at 03:33:35PM -0700, Guenter Roeck wrote: > It may be odd that fs/quota/netlink.c:quota_genl_family is not word > aligned, but on the other side I don't think there is a rule that > the function parameter to genl_register_family() - or the second > parameter of idr_alloc() - must be word aligned. Am I missing > something ? After all, it could be a pointer to the nth element > of a string, or the caller could on purpose allocate IDRs for > (ptr), (ptr + 1), and so on. This is probably going to cure the problem for you (apply on top of the existing radix tree / IDR changes). I realised when I was reviewing the patch that it's no good; if you call idr_replace() with a radix_tree_is_internal_node(), then you'll still get a crash. I'm going to have to disable the optimisation of shrinking the tree all the way into the head for the IDR. But this will probably get m68k working again. diff --git a/lib/idr.c b/lib/idr.c index 58b88f5eb672..51ee0c6170d1 100644 --- a/lib/idr.c +++ b/lib/idr.c @@ -38,17 +38,24 @@ int idr_alloc_u32(struct idr *idr, void *ptr, u32 *nextid, void __rcu **slot; unsigned int base = idr->idr_base; unsigned int id = *nextid; + bool advanced = false; - if (WARN_ON_ONCE(radix_tree_is_internal_node(ptr))) - return -EINVAL; if (WARN_ON_ONCE(!(idr->idr_rt.xa_flags & ROOT_IS_IDR))) idr->idr_rt.xa_flags |= IDR_RT_MARKER; id = (id < base) ? 0 : id - base; + if (id == 0 && radix_tree_is_internal_node(ptr) && idr_is_empty(idr)) { + advanced = true; + id = 1; + } radix_tree_iter_init(&iter, id); slot = idr_get_free(&idr->idr_rt, &iter, gfp, max - base); if (IS_ERR(slot)) return PTR_ERR(slot); + if (advanced) { + iter.index = 0; + slot--; + } *nextid = iter.index + base; /* there is a memory barrier inside radix_tree_iter_replace() */ @@ -295,8 +302,6 @@ void *idr_replace(struct idr *idr, void *ptr, unsigned long id) void __rcu **slot = NULL; void *entry; - if (WARN_ON_ONCE(radix_tree_is_internal_node(ptr))) - return ERR_PTR(-EINVAL); id -= idr->idr_base; entry = __radix_tree_lookup(&idr->idr_rt, id, &node, &slot); diff --git a/lib/radix-tree.c b/lib/radix-tree.c index 101f1c28e1b6..b0bd105a365d 100644 --- a/lib/radix-tree.c +++ b/lib/radix-tree.c @@ -562,11 +562,14 @@ static inline bool radix_tree_shrink(struct radix_tree_root *root) child = rcu_dereference_raw(node->slots[0]); if (!child) break; - if (!radix_tree_is_internal_node(child) && node->shift) + if (!radix_tree_is_internal_node(child)) break; - if (radix_tree_is_internal_node(child)) + if (radix_tree_is_internal_node(child)) { + if (!node->shift) + break; entry_to_node(child)->parent = NULL; + } /* * We don't need rcu_assign_pointer(), since we are simply @@ -733,7 +736,7 @@ static void radix_tree_free_nodes(struct radix_tree_node *node) for (;;) { void *entry = rcu_dereference_raw(child->slots[offset]); - if (xa_is_node(entry)) { + if (xa_is_node(entry) && child->shift) { child = entry_to_node(entry); offset = 0; continue; @@ -904,6 +907,8 @@ void *__radix_tree_lookup(const struct radix_tree_root *root, parent = entry_to_node(node); offset = radix_tree_descend(parent, &node, index); slot = parent->slots + offset; + if (parent->shift == 0) + break; } if (nodep) @@ -977,9 +982,6 @@ static inline void replace_sibling_entries(struct radix_tree_node *node, static void replace_slot(void __rcu **slot, void *item, struct radix_tree_node *node, int count, int values) { - if (WARN_ON_ONCE(radix_tree_is_internal_node(item))) - return; - if (node && (count || values)) { node->count += count; node->nr_values += values; diff --git a/tools/testing/radix-tree/idr-test.c b/tools/testing/radix-tree/idr-test.c index 46fc2f1142c3..e494f1d24687 100644 --- a/tools/testing/radix-tree/idr-test.c +++ b/tools/testing/radix-tree/idr-test.c @@ -227,6 +227,43 @@ void idr_u32_test(int base) idr_u32_test1(&idr, 0xffffffff); } +static void idr_align_test(struct idr *idr) +{ + char name[] = "Motorola 68000"; + int i; + + for (i = 0; i < 9; i++) + BUG_ON(idr_alloc(idr, &name[i], 0, 0, GFP_KERNEL) != i); + idr_destroy(idr); + + for (i = 1; i < 10; i++) + BUG_ON(idr_alloc(idr, &name[i], 0, 0, GFP_KERNEL) != i - 1); + idr_destroy(idr); + + for (i = 2; i < 11; i++) + BUG_ON(idr_alloc(idr, &name[i], 0, 0, GFP_KERNEL) != i - 2); + idr_destroy(idr); + + for (i = 3; i < 12; i++) + BUG_ON(idr_alloc(idr, &name[i], 0, 0, GFP_KERNEL) != i - 3); + idr_destroy(idr); + + for (i = 0; i < 8; i++) { + BUG_ON(idr_alloc(idr, &name[i], 0, 0, GFP_KERNEL) != 0); + BUG_ON(idr_alloc(idr, &name[i + 1], 0, 0, GFP_KERNEL) != 1); + idr_remove(idr, 1); + idr_remove(idr, 0); + BUG_ON(!idr_is_empty(idr)); + } + + for (i = 0; i < 8; i++) { + BUG_ON(idr_alloc(idr, NULL, 0, 0, GFP_KERNEL) != 0); + idr_replace(idr, &name[i], 0); + BUG_ON(idr_find(idr, 0) != &name[i]); + idr_remove(idr, 0); + } +} + void idr_checks(void) { unsigned long i; @@ -307,6 +344,7 @@ void idr_checks(void) idr_u32_test(4); idr_u32_test(1); idr_u32_test(0); + idr_align_test(&idr); } /* ^ permalink raw reply related [flat|nested] 13+ messages in thread
* Re: m68k boot failure in -next bisected to 'xarray: Replace exceptional entries' 2018-06-24 1:17 ` Matthew Wilcox @ 2018-06-24 2:52 ` Guenter Roeck 2018-06-24 3:26 ` Matthew Wilcox 0 siblings, 1 reply; 13+ messages in thread From: Guenter Roeck @ 2018-06-24 2:52 UTC (permalink / raw) To: Matthew Wilcox; +Cc: Josef Bacik, Geert Uytterhoeven, linux-m68k, linux-kernel On 06/23/2018 06:17 PM, Matthew Wilcox wrote: > On Fri, Jun 22, 2018 at 03:33:35PM -0700, Guenter Roeck wrote: >> It may be odd that fs/quota/netlink.c:quota_genl_family is not word >> aligned, but on the other side I don't think there is a rule that >> the function parameter to genl_register_family() - or the second >> parameter of idr_alloc() - must be word aligned. Am I missing >> something ? After all, it could be a pointer to the nth element >> of a string, or the caller could on purpose allocate IDRs for >> (ptr), (ptr + 1), and so on. > > This is probably going to cure the problem for you (apply on top > of the existing radix tree / IDR changes). > > I realised when I was reviewing the patch that it's no good; if you > call idr_replace() with a radix_tree_is_internal_node(), then you'll > still get a crash. I'm going to have to disable the optimisation of > shrinking the tree all the way into the head for the IDR. But this > will probably get m68k working again. > It doesn't crash anymore, but there is still a backtrace. ------------[ cut here ]------------ WARNING: CPU: 0 PID: 1 at lib/idr.c:250 idr_get_next+0x62/0x82 Modules linked in: CPU: 0 PID: 1 Comm: swapper Not tainted 4.18.0-rc1-next-20180622-mac-00001-g6731a81057be-dirty #1 Stack from 07c19e28: 07c19e28 0036d5b2 000180d6 00000000 0036e0d6 0055a040 00000000 000020e8 07c19eb0 002b5326 0001816a 0036d5b5 000000fa 002b5388 00000009 00000000 00000000 00340b1d 002b5388 0036d5b5 000000fa 00000401 0036e0d6 80000000 00000000 00036fa0 0036ddc0 07c19eb0 00246164 003abf1c 07c19eb0 00036fa0 0036e0ce 07c19f8c 00000011 00246f04 0036e0d6 003abf34 00000400 00000006 0055a040 00000000 000020e8 00000000 00036fa0 003ff8e0 003f751c 07c19f8c Call Trace: [<000180d6>] __warn+0xc0/0xc2 [<000020e8>] do_one_initcall+0x0/0x140 [<002b5326>] idr_get_next+0x0/0x82 [<0001816a>] warn_slowpath_null+0x26/0x2c [<002b5388>] idr_get_next+0x62/0x82 [<002b5388>] idr_get_next+0x62/0x82 [<00036fa0>] printk+0x0/0x18 [<00246164>] genl_family_find_byname+0x1c/0x4c [<00036fa0>] printk+0x0/0x18 [<00246f04>] genl_register_family+0x74/0x55c [<000020e8>] do_one_initcall+0x0/0x140 Guenter ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: m68k boot failure in -next bisected to 'xarray: Replace exceptional entries' 2018-06-24 2:52 ` Guenter Roeck @ 2018-06-24 3:26 ` Matthew Wilcox 2018-06-24 4:01 ` Guenter Roeck 0 siblings, 1 reply; 13+ messages in thread From: Matthew Wilcox @ 2018-06-24 3:26 UTC (permalink / raw) To: Guenter Roeck; +Cc: Josef Bacik, Geert Uytterhoeven, linux-m68k, linux-kernel On Sat, Jun 23, 2018 at 07:52:35PM -0700, Guenter Roeck wrote: > On 06/23/2018 06:17 PM, Matthew Wilcox wrote: > > On Fri, Jun 22, 2018 at 03:33:35PM -0700, Guenter Roeck wrote: > > > It may be odd that fs/quota/netlink.c:quota_genl_family is not word > > > aligned, but on the other side I don't think there is a rule that > > > the function parameter to genl_register_family() - or the second > > > parameter of idr_alloc() - must be word aligned. Am I missing > > > something ? After all, it could be a pointer to the nth element > > > of a string, or the caller could on purpose allocate IDRs for > > > (ptr), (ptr + 1), and so on. > > > > This is probably going to cure the problem for you (apply on top > > of the existing radix tree / IDR changes). > > > > I realised when I was reviewing the patch that it's no good; if you > > call idr_replace() with a radix_tree_is_internal_node(), then you'll > > still get a crash. I'm going to have to disable the optimisation of > > shrinking the tree all the way into the head for the IDR. But this > > will probably get m68k working again. > > > > It doesn't crash anymore, but there is still a backtrace. Oof. Thank you! Updated patch (still doesn't fix idr_replace, but does fix the idr_for_each() problem, at least according to the tests I added to the test-suite. diff --git a/lib/idr.c b/lib/idr.c index 58b88f5eb672..51ee0c6170d1 100644 --- a/lib/idr.c +++ b/lib/idr.c @@ -38,17 +38,24 @@ int idr_alloc_u32(struct idr *idr, void *ptr, u32 *nextid, void __rcu **slot; unsigned int base = idr->idr_base; unsigned int id = *nextid; + bool advanced = false; - if (WARN_ON_ONCE(radix_tree_is_internal_node(ptr))) - return -EINVAL; if (WARN_ON_ONCE(!(idr->idr_rt.xa_flags & ROOT_IS_IDR))) idr->idr_rt.xa_flags |= IDR_RT_MARKER; id = (id < base) ? 0 : id - base; + if (id == 0 && radix_tree_is_internal_node(ptr) && idr_is_empty(idr)) { + advanced = true; + id = 1; + } radix_tree_iter_init(&iter, id); slot = idr_get_free(&idr->idr_rt, &iter, gfp, max - base); if (IS_ERR(slot)) return PTR_ERR(slot); + if (advanced) { + iter.index = 0; + slot--; + } *nextid = iter.index + base; /* there is a memory barrier inside radix_tree_iter_replace() */ @@ -295,8 +302,6 @@ void *idr_replace(struct idr *idr, void *ptr, unsigned long id) void __rcu **slot = NULL; void *entry; - if (WARN_ON_ONCE(radix_tree_is_internal_node(ptr))) - return ERR_PTR(-EINVAL); id -= idr->idr_base; entry = __radix_tree_lookup(&idr->idr_rt, id, &node, &slot); diff --git a/lib/radix-tree.c b/lib/radix-tree.c index 101f1c28e1b6..15f34de929f5 100644 --- a/lib/radix-tree.c +++ b/lib/radix-tree.c @@ -562,11 +562,14 @@ static inline bool radix_tree_shrink(struct radix_tree_root *root) child = rcu_dereference_raw(node->slots[0]); if (!child) break; - if (!radix_tree_is_internal_node(child) && node->shift) + if (!radix_tree_is_internal_node(child)) break; - if (radix_tree_is_internal_node(child)) + if (radix_tree_is_internal_node(child)) { + if (!node->shift) + break; entry_to_node(child)->parent = NULL; + } /* * We don't need rcu_assign_pointer(), since we are simply @@ -733,7 +736,7 @@ static void radix_tree_free_nodes(struct radix_tree_node *node) for (;;) { void *entry = rcu_dereference_raw(child->slots[offset]); - if (xa_is_node(entry)) { + if (xa_is_node(entry) && child->shift) { child = entry_to_node(entry); offset = 0; continue; @@ -904,6 +907,8 @@ void *__radix_tree_lookup(const struct radix_tree_root *root, parent = entry_to_node(node); offset = radix_tree_descend(parent, &node, index); slot = parent->slots + offset; + if (parent->shift == 0) + break; } if (nodep) @@ -977,9 +982,6 @@ static inline void replace_sibling_entries(struct radix_tree_node *node, static void replace_slot(void __rcu **slot, void *item, struct radix_tree_node *node, int count, int values) { - if (WARN_ON_ONCE(radix_tree_is_internal_node(item))) - return; - if (node && (count || values)) { node->count += count; node->nr_values += values; @@ -1486,7 +1488,7 @@ void __rcu **radix_tree_next_chunk(const struct radix_tree_root *root, goto restart; if (child == RADIX_TREE_RETRY) break; - } while (radix_tree_is_internal_node(child)); + } while (node->shift && radix_tree_is_internal_node(child)); /* Update the iterator state */ iter->index = (index &~ node_maxindex(node)) | (offset << node->shift); diff --git a/tools/testing/radix-tree/idr-test.c b/tools/testing/radix-tree/idr-test.c index 46fc2f1142c3..ec7e8f2fb0ec 100644 --- a/tools/testing/radix-tree/idr-test.c +++ b/tools/testing/radix-tree/idr-test.c @@ -227,6 +227,56 @@ void idr_u32_test(int base) idr_u32_test1(&idr, 0xffffffff); } +static void idr_align_test(struct idr *idr) +{ + char name[] = "Motorola 68000"; + int i, id; + void *entry; + + for (i = 0; i < 9; i++) { + BUG_ON(idr_alloc(idr, &name[i], 0, 0, GFP_KERNEL) != i); + idr_for_each_entry(idr, entry, id); + } + idr_destroy(idr); + + for (i = 1; i < 10; i++) { + BUG_ON(idr_alloc(idr, &name[i], 0, 0, GFP_KERNEL) != i - 1); + idr_for_each_entry(idr, entry, id); + } + idr_destroy(idr); + + for (i = 2; i < 11; i++) { + BUG_ON(idr_alloc(idr, &name[i], 0, 0, GFP_KERNEL) != i - 2); + idr_for_each_entry(idr, entry, id); + } + idr_destroy(idr); + + for (i = 3; i < 12; i++) { + BUG_ON(idr_alloc(idr, &name[i], 0, 0, GFP_KERNEL) != i - 3); + idr_for_each_entry(idr, entry, id); + } + idr_destroy(idr); + + for (i = 0; i < 8; i++) { + BUG_ON(idr_alloc(idr, &name[i], 0, 0, GFP_KERNEL) != 0); + BUG_ON(idr_alloc(idr, &name[i + 1], 0, 0, GFP_KERNEL) != 1); + idr_for_each_entry(idr, entry, id); + idr_remove(idr, 1); + idr_for_each_entry(idr, entry, id); + idr_remove(idr, 0); + BUG_ON(!idr_is_empty(idr)); + } + + for (i = 0; i < 8; i++) { + BUG_ON(idr_alloc(idr, NULL, 0, 0, GFP_KERNEL) != 0); + idr_for_each_entry(idr, entry, id); + idr_replace(idr, &name[i], 0); + idr_for_each_entry(idr, entry, id); + BUG_ON(idr_find(idr, 0) != &name[i]); + idr_remove(idr, 0); + } +} + void idr_checks(void) { unsigned long i; @@ -307,6 +357,7 @@ void idr_checks(void) idr_u32_test(4); idr_u32_test(1); idr_u32_test(0); + idr_align_test(&idr); } /* ^ permalink raw reply related [flat|nested] 13+ messages in thread
* Re: m68k boot failure in -next bisected to 'xarray: Replace exceptional entries' 2018-06-24 3:26 ` Matthew Wilcox @ 2018-06-24 4:01 ` Guenter Roeck 2018-06-24 23:39 ` Matthew Wilcox 0 siblings, 1 reply; 13+ messages in thread From: Guenter Roeck @ 2018-06-24 4:01 UTC (permalink / raw) To: Matthew Wilcox; +Cc: Josef Bacik, Geert Uytterhoeven, linux-m68k, linux-kernel On 06/23/2018 08:26 PM, Matthew Wilcox wrote: > On Sat, Jun 23, 2018 at 07:52:35PM -0700, Guenter Roeck wrote: >> On 06/23/2018 06:17 PM, Matthew Wilcox wrote: >>> On Fri, Jun 22, 2018 at 03:33:35PM -0700, Guenter Roeck wrote: >>>> It may be odd that fs/quota/netlink.c:quota_genl_family is not word >>>> aligned, but on the other side I don't think there is a rule that >>>> the function parameter to genl_register_family() - or the second >>>> parameter of idr_alloc() - must be word aligned. Am I missing >>>> something ? After all, it could be a pointer to the nth element >>>> of a string, or the caller could on purpose allocate IDRs for >>>> (ptr), (ptr + 1), and so on. >>> >>> This is probably going to cure the problem for you (apply on top >>> of the existing radix tree / IDR changes). >>> >>> I realised when I was reviewing the patch that it's no good; if you >>> call idr_replace() with a radix_tree_is_internal_node(), then you'll >>> still get a crash. I'm going to have to disable the optimisation of >>> shrinking the tree all the way into the head for the IDR. But this >>> will probably get m68k working again. >>> >> >> It doesn't crash anymore, but there is still a backtrace. > > Oof. Thank you! Updated patch (still doesn't fix idr_replace, but does > fix the idr_for_each() problem, at least according to the tests I added > to the test-suite. > Yes, that is much better: Build reference: next-20180622-1-g023ad92e94da Building mcf5208evb:m5208:m5208evb_defconfig:initrd ... running .... passed Building q800:m68040:mac_defconfig:initrd ... running .... passed Building q800:m68040:mac_defconfig:rootfs ... running .... passed Guenter ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: m68k boot failure in -next bisected to 'xarray: Replace exceptional entries' 2018-06-24 4:01 ` Guenter Roeck @ 2018-06-24 23:39 ` Matthew Wilcox 2018-06-25 1:36 ` Guenter Roeck 0 siblings, 1 reply; 13+ messages in thread From: Matthew Wilcox @ 2018-06-24 23:39 UTC (permalink / raw) To: Guenter Roeck; +Cc: Josef Bacik, Geert Uytterhoeven, linux-m68k, linux-kernel On Sat, Jun 23, 2018 at 09:01:37PM -0700, Guenter Roeck wrote: > Yes, that is much better: > > Build reference: next-20180622-1-g023ad92e94da > > Building mcf5208evb:m5208:m5208evb_defconfig:initrd ... running .... passed > Building q800:m68040:mac_defconfig:initrd ... running .... passed > Building q800:m68040:mac_defconfig:rootfs ... running .... passed great! Here's a version which fixes idr_replace() too. diff --git a/lib/idr.c b/lib/idr.c index 58b88f5eb672..f16a95cbc527 100644 --- a/lib/idr.c +++ b/lib/idr.c @@ -39,8 +39,6 @@ int idr_alloc_u32(struct idr *idr, void *ptr, u32 *nextid, unsigned int base = idr->idr_base; unsigned int id = *nextid; - if (WARN_ON_ONCE(radix_tree_is_internal_node(ptr))) - return -EINVAL; if (WARN_ON_ONCE(!(idr->idr_rt.xa_flags & ROOT_IS_IDR))) idr->idr_rt.xa_flags |= IDR_RT_MARKER; @@ -295,8 +293,6 @@ void *idr_replace(struct idr *idr, void *ptr, unsigned long id) void __rcu **slot = NULL; void *entry; - if (WARN_ON_ONCE(radix_tree_is_internal_node(ptr))) - return ERR_PTR(-EINVAL); id -= idr->idr_base; entry = __radix_tree_lookup(&idr->idr_rt, id, &node, &slot); diff --git a/lib/radix-tree.c b/lib/radix-tree.c index 101f1c28e1b6..22fecea283d8 100644 --- a/lib/radix-tree.c +++ b/lib/radix-tree.c @@ -564,6 +564,8 @@ static inline bool radix_tree_shrink(struct radix_tree_root *root) break; if (!radix_tree_is_internal_node(child) && node->shift) break; + if (!node->shift && is_idr(root)) + break; if (radix_tree_is_internal_node(child)) entry_to_node(child)->parent = NULL; @@ -733,7 +735,7 @@ static void radix_tree_free_nodes(struct radix_tree_node *node) for (;;) { void *entry = rcu_dereference_raw(child->slots[offset]); - if (xa_is_node(entry)) { + if (xa_is_node(entry) && child->shift) { child = entry_to_node(entry); offset = 0; continue; @@ -904,6 +906,8 @@ void *__radix_tree_lookup(const struct radix_tree_root *root, parent = entry_to_node(node); offset = radix_tree_descend(parent, &node, index); slot = parent->slots + offset; + if (parent->shift == 0) + break; } if (nodep) @@ -977,9 +981,6 @@ static inline void replace_sibling_entries(struct radix_tree_node *node, static void replace_slot(void __rcu **slot, void *item, struct radix_tree_node *node, int count, int values) { - if (WARN_ON_ONCE(radix_tree_is_internal_node(item))) - return; - if (node && (count || values)) { node->count += count; node->nr_values += values; @@ -1486,7 +1487,7 @@ void __rcu **radix_tree_next_chunk(const struct radix_tree_root *root, goto restart; if (child == RADIX_TREE_RETRY) break; - } while (radix_tree_is_internal_node(child)); + } while (node->shift && radix_tree_is_internal_node(child)); /* Update the iterator state */ iter->index = (index &~ node_maxindex(node)) | (offset << node->shift); @@ -1789,6 +1790,8 @@ void __rcu **idr_get_free(struct radix_tree_root *root, shift = error; child = rcu_dereference_raw(root->xa_head); } + if (start == 0 && shift == 0) + shift = RADIX_TREE_MAP_SHIFT; while (shift) { shift -= RADIX_TREE_MAP_SHIFT; diff --git a/lib/xarray.c b/lib/xarray.c index 8dddad5b237c..f549ee744cc6 100644 --- a/lib/xarray.c +++ b/lib/xarray.c @@ -1719,15 +1719,19 @@ void xa_dump_entry(const void *entry, unsigned long index, unsigned long shift) xa_dump_index(index, shift); if (xa_is_node(entry)) { - unsigned long i; - struct xa_node *node = xa_to_node(entry); - xa_dump_node(node); - for (i = 0; i < XA_CHUNK_SIZE; i++) - xa_dump_entry(node->slots[i], + if (shift == 0) { + pr_cont("%px\n", entry); + } else { + unsigned long i; + struct xa_node *node = xa_to_node(entry); + xa_dump_node(node); + for (i = 0; i < XA_CHUNK_SIZE; i++) + xa_dump_entry(node->slots[i], index + (i << node->shift), node->shift); + } } else if (xa_is_value(entry)) - pr_cont("value %ld (0x%lx)\n", xa_to_value(entry), - xa_to_value(entry)); + pr_cont("value %ld (0x%lx) [%px]\n", xa_to_value(entry), + xa_to_value(entry), entry); else if (!xa_is_internal(entry)) pr_cont("%px\n", entry); else if (xa_is_retry(entry)) diff --git a/tools/testing/radix-tree/idr-test.c b/tools/testing/radix-tree/idr-test.c index 46fc2f1142c3..67d851d31e26 100644 --- a/tools/testing/radix-tree/idr-test.c +++ b/tools/testing/radix-tree/idr-test.c @@ -227,6 +227,66 @@ void idr_u32_test(int base) idr_u32_test1(&idr, 0xffffffff); } +static void idr_align_test(struct idr *idr) +{ + char name[] = "Motorola 68000"; + int i, id; + void *entry; + + for (i = 0; i < 9; i++) { + BUG_ON(idr_alloc(idr, &name[i], 0, 0, GFP_KERNEL) != i); + idr_for_each_entry(idr, entry, id); + } + idr_destroy(idr); + + for (i = 1; i < 10; i++) { + BUG_ON(idr_alloc(idr, &name[i], 0, 0, GFP_KERNEL) != i - 1); + idr_for_each_entry(idr, entry, id); + } + idr_destroy(idr); + + for (i = 2; i < 11; i++) { + BUG_ON(idr_alloc(idr, &name[i], 0, 0, GFP_KERNEL) != i - 2); + idr_for_each_entry(idr, entry, id); + } + idr_destroy(idr); + + for (i = 3; i < 12; i++) { + BUG_ON(idr_alloc(idr, &name[i], 0, 0, GFP_KERNEL) != i - 3); + idr_for_each_entry(idr, entry, id); + } + idr_destroy(idr); + + for (i = 0; i < 8; i++) { + BUG_ON(idr_alloc(idr, &name[i], 0, 0, GFP_KERNEL) != 0); + BUG_ON(idr_alloc(idr, &name[i + 1], 0, 0, GFP_KERNEL) != 1); + idr_for_each_entry(idr, entry, id); + idr_remove(idr, 1); + idr_for_each_entry(idr, entry, id); + idr_remove(idr, 0); + BUG_ON(!idr_is_empty(idr)); + } + + for (i = 0; i < 8; i++) { + BUG_ON(idr_alloc(idr, NULL, 0, 0, GFP_KERNEL) != 0); + idr_for_each_entry(idr, entry, id); + idr_replace(idr, &name[i], 0); + idr_for_each_entry(idr, entry, id); + BUG_ON(idr_find(idr, 0) != &name[i]); + idr_remove(idr, 0); + } + + for (i = 0; i < 8; i++) { + BUG_ON(idr_alloc(idr, &name[i], 0, 0, GFP_KERNEL) != 0); + BUG_ON(idr_alloc(idr, NULL, 0, 0, GFP_KERNEL) != 1); + idr_remove(idr, 1); + idr_for_each_entry(idr, entry, id); + idr_replace(idr, &name[i + 1], 0); + idr_for_each_entry(idr, entry, id); + idr_remove(idr, 0); + } +} + void idr_checks(void) { unsigned long i; @@ -307,6 +367,7 @@ void idr_checks(void) idr_u32_test(4); idr_u32_test(1); idr_u32_test(0); + idr_align_test(&idr); } /* @@ -396,6 +457,7 @@ void ida_check_conv(void) } assert(ida_is_empty(&ida)); +#if 0 radix_tree_cpu_dead(1); for (i = 0; i < 1000000; i++) { int err = ida_get_new(&ida, &id); @@ -410,6 +472,7 @@ void ida_check_conv(void) assert(id == i); } ida_destroy(&ida); +#endif } /* ^ permalink raw reply related [flat|nested] 13+ messages in thread
* Re: m68k boot failure in -next bisected to 'xarray: Replace exceptional entries' 2018-06-24 23:39 ` Matthew Wilcox @ 2018-06-25 1:36 ` Guenter Roeck 0 siblings, 0 replies; 13+ messages in thread From: Guenter Roeck @ 2018-06-25 1:36 UTC (permalink / raw) To: Matthew Wilcox; +Cc: Josef Bacik, Geert Uytterhoeven, linux-m68k, linux-kernel On 06/24/2018 04:39 PM, Matthew Wilcox wrote: > On Sat, Jun 23, 2018 at 09:01:37PM -0700, Guenter Roeck wrote: >> Yes, that is much better: >> >> Build reference: next-20180622-1-g023ad92e94da >> >> Building mcf5208evb:m5208:m5208evb_defconfig:initrd ... running .... passed >> Building q800:m68040:mac_defconfig:initrd ... running .... passed >> Building q800:m68040:mac_defconfig:rootfs ... running .... passed > > great! Here's a version which fixes idr_replace() too. > Still passes: Build reference: next-20180622-1-g374388bcb967 Building mcf5208evb:m5208:m5208evb_defconfig:initrd ... running .... passed Building q800:m68040:mac_defconfig:initrd ... running .... passed Building q800:m68040:mac_defconfig:rootfs ... running .... passed Guenter ^ permalink raw reply [flat|nested] 13+ messages in thread
end of thread, other threads:[~2018-06-25 1:36 UTC | newest] Thread overview: 13+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2018-06-22 18:42 m68k boot failure in -next bisected to 'xarray: Replace exceptional entries' Guenter Roeck 2018-06-22 21:05 ` Matthew Wilcox 2018-06-22 22:33 ` Guenter Roeck 2018-06-23 7:46 ` Matthew Wilcox 2018-06-23 16:43 ` Guenter Roeck 2018-06-23 23:20 ` Matthew Wilcox 2018-06-23 20:51 ` Geert Uytterhoeven 2018-06-24 1:17 ` Matthew Wilcox 2018-06-24 2:52 ` Guenter Roeck 2018-06-24 3:26 ` Matthew Wilcox 2018-06-24 4:01 ` Guenter Roeck 2018-06-24 23:39 ` Matthew Wilcox 2018-06-25 1:36 ` Guenter Roeck
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox