linux-btrfs.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* BUG: unable to handle kernel NULL pointer dereference at   (null)
@ 2011-04-05 17:38 Johannes Hirte
  2011-04-05 17:42 ` Josef Bacik
  0 siblings, 1 reply; 16+ messages in thread
From: Johannes Hirte @ 2011-04-05 17:38 UTC (permalink / raw)
  To: Josef Bacik; +Cc: linux-btrfs

With the latest btrfs changes, I got this Oops when doing rm on a large 
directory:

BUG: unable to handle kernel NULL pointer dereference at   (null)
IP: [<c101c838>] kunmap+0x46/0x46
*pdpt = 0000000034a85001 *pde = 0000000000000000 
Oops: 0000 [#1] PREEMPT SMP 
last sysfs file: /sys/devices/virtual/vtconsole/vtcon1/uevent
Modules linked in: snd_seq_oss snd_seq_midi_event snd_seq snd_seq_device 
snd_pcm_oss snd_mixer_oss fuse dm_crypt dm_mod usbhid snd_intel8x0 
snd_ac97_codec ac97_bus snd_pcm snd_timer sr_mod cdrom sg snd fschmd e1000 
uhci_hcd snd_page_alloc i2c_i801 [last unloaded: microcode]

Pid: 1156, comm: btrfs-transacti Tainted: G        W   2.6.39-rc1-00262-
gc53813f #20 FUJITSU SIEMENS SCENIC P / SCENICO P/D1561
EIP: 0060:[<c101c838>] EFLAGS: 00010296 CPU: 1
EIP is at kmap+0x0/0x38
EAX: 00000000 EBX: 00000000 ECX: 00000000 EDX: 00000010
ESI: f5bc6400 EDI: f3c75520 EBP: f3c755f0 ESP: f58f9e10
 DS: 007b ES: 007b FS: 00d8 GS: 0000 SS: 0068
Process btrfs-transacti (pid: 1156, ti=f58f8000 task=f6516f40 
task.ti=f58f8000)
Stack:
 c1186d15 ffc22000 f58f9ec0 00000010 f3c75610 00000000 f5885780 f52339e8
 00000009 f5bc6400 00010000 00000000 f6415800 f3c75638 000008bb f5bc63c0
 f58857b4 f60b68a0 00000040 f52338e8 ffc22000 00000000 00000008 00000010
Call Trace:
 [<c1186d15>] ? btrfs_write_out_cache+0x60c/0xa3c
 [<c114a815>] ? btrfs_write_dirty_block_groups+0x400/0x494
 [<c11566a7>] ? commit_cowonly_roots+0xa9/0x180
 [<c1157799>] ? btrfs_commit_transaction+0x2ee/0x59c
 [<c1037c85>] ? wake_up_bit+0x16/0x16
 [<c1152a83>] ? transaction_kthread+0x149/0x1d6
 [<c101d1b9>] ? complete+0x28/0x36
 [<c115293a>] ? btrfs_congested_fn+0x5d/0x5d
 [<c10379c4>] ? kthread+0x63/0x68
 [<c1037961>] ? kthread_worker_fn+0xeb/0xeb
 [<c13cba36>] ? kernel_thread_helper+0x6/0xd
Code: 8d 8a 00 e4 54 c1 2b 8a 8c e7 54 c1 81 f9 00 08 00 00 74 11 81 f9 00 0c 
00 00 75 0e 83 3d 10 2f 60 c1 02 75 05 e9 5e a3 04 00 c3 <8b> 10 c1 ea 1e c1 
e2 0a 8d 8a 00 e4 54 c1 2b 8a 8c e7 54 c1 81 
EIP: [<c101c838>] kmap+0x0/0x38 SS:ESP 0068:f58f9e10
CR2: 0000000000000000
---[ end trace c8511126ee91dfdf ]---

This is the second Oops. On the first one I wasn't able to catch the backtrace, 
but IIRC the bug happend on kmap not kunmap the first time.

regards,
  Johannes

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: BUG: unable to handle kernel NULL pointer dereference at (null)
  2011-04-05 17:38 BUG: unable to handle kernel NULL pointer dereference at (null) Johannes Hirte
@ 2011-04-05 17:42 ` Josef Bacik
  2011-04-05 18:52   ` Johannes Hirte
  0 siblings, 1 reply; 16+ messages in thread
From: Josef Bacik @ 2011-04-05 17:42 UTC (permalink / raw)
  To: Johannes Hirte; +Cc: Josef Bacik, linux-btrfs

On Tue, Apr 05, 2011 at 07:38:13PM +0200, Johannes Hirte wrote:
> With the latest btrfs changes, I got this Oops when doing rm on a large 
> directory:
> 
> BUG: unable to handle kernel NULL pointer dereference at   (null)
> IP: [<c101c838>] kunmap+0x46/0x46
> *pdpt = 0000000034a85001 *pde = 0000000000000000 
> Oops: 0000 [#1] PREEMPT SMP 
> last sysfs file: /sys/devices/virtual/vtconsole/vtcon1/uevent
> Modules linked in: snd_seq_oss snd_seq_midi_event snd_seq snd_seq_device 
> snd_pcm_oss snd_mixer_oss fuse dm_crypt dm_mod usbhid snd_intel8x0 
> snd_ac97_codec ac97_bus snd_pcm snd_timer sr_mod cdrom sg snd fschmd e1000 
> uhci_hcd snd_page_alloc i2c_i801 [last unloaded: microcode]
> 
> Pid: 1156, comm: btrfs-transacti Tainted: G        W   2.6.39-rc1-00262-
> gc53813f #20 FUJITSU SIEMENS SCENIC P / SCENICO P/D1561
> EIP: 0060:[<c101c838>] EFLAGS: 00010296 CPU: 1
> EIP is at kmap+0x0/0x38
> EAX: 00000000 EBX: 00000000 ECX: 00000000 EDX: 00000010
> ESI: f5bc6400 EDI: f3c75520 EBP: f3c755f0 ESP: f58f9e10
>  DS: 007b ES: 007b FS: 00d8 GS: 0000 SS: 0068
> Process btrfs-transacti (pid: 1156, ti=f58f8000 task=f6516f40 
> task.ti=f58f8000)
> Stack:
>  c1186d15 ffc22000 f58f9ec0 00000010 f3c75610 00000000 f5885780 f52339e8
>  00000009 f5bc6400 00010000 00000000 f6415800 f3c75638 000008bb f5bc63c0
>  f58857b4 f60b68a0 00000040 f52338e8 ffc22000 00000000 00000008 00000010
> Call Trace:
>  [<c1186d15>] ? btrfs_write_out_cache+0x60c/0xa3c
>  [<c114a815>] ? btrfs_write_dirty_block_groups+0x400/0x494
>  [<c11566a7>] ? commit_cowonly_roots+0xa9/0x180
>  [<c1157799>] ? btrfs_commit_transaction+0x2ee/0x59c
>  [<c1037c85>] ? wake_up_bit+0x16/0x16
>  [<c1152a83>] ? transaction_kthread+0x149/0x1d6
>  [<c101d1b9>] ? complete+0x28/0x36
>  [<c115293a>] ? btrfs_congested_fn+0x5d/0x5d
>  [<c10379c4>] ? kthread+0x63/0x68
>  [<c1037961>] ? kthread_worker_fn+0xeb/0xeb
>  [<c13cba36>] ? kernel_thread_helper+0x6/0xd
> Code: 8d 8a 00 e4 54 c1 2b 8a 8c e7 54 c1 81 f9 00 08 00 00 74 11 81 f9 00 0c 
> 00 00 75 0e 83 3d 10 2f 60 c1 02 75 05 e9 5e a3 04 00 c3 <8b> 10 c1 ea 1e c1 
> e2 0a 8d 8a 00 e4 54 c1 2b 8a 8c e7 54 c1 81 
> EIP: [<c101c838>] kmap+0x0/0x38 SS:ESP 0068:f58f9e10
> CR2: 0000000000000000
> ---[ end trace c8511126ee91dfdf ]---
> 
> This is the second Oops. On the first one I wasn't able to catch the backtrace, 
> but IIRC the bug happend on kmap not kunmap the first time.
>

Yeah I think I know what this is but I need somebody to verify it for me.  Can
you run with this patch and let me know what happens?  Thanks,

Josef

diff --git a/fs/btrfs/free-space-cache.c b/fs/btrfs/free-space-cache.c
index 74bc432..5e6f4b3 100644
--- a/fs/btrfs/free-space-cache.c
+++ b/fs/btrfs/free-space-cache.c
@@ -624,6 +624,7 @@ int btrfs_write_out_cache(struct btrfs_root *root,
 
 		next_page = false;
 
+		BUG_ON(index > last_index);
 		if (index == 0) {
 			start_offset = first_page_offset;
 			offset = start_offset;
@@ -732,6 +733,7 @@ int btrfs_write_out_cache(struct btrfs_root *root,
 		struct btrfs_free_space *entry =
 			list_entry(pos, struct btrfs_free_space, list);
 
+		BUG_ON(index > last_index);
 		page = find_get_page(inode->i_mapping, index);
 
 		addr = kmap(page);

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* Re: BUG: unable to handle kernel NULL pointer dereference at (null)
  2011-04-05 17:42 ` Josef Bacik
@ 2011-04-05 18:52   ` Johannes Hirte
  2011-04-05 18:53     ` Josef Bacik
  0 siblings, 1 reply; 16+ messages in thread
From: Johannes Hirte @ 2011-04-05 18:52 UTC (permalink / raw)
  To: Josef Bacik; +Cc: linux-btrfs

On Tuesday 05 April 2011 19:42:03 Josef Bacik wrote:
> On Tue, Apr 05, 2011 at 07:38:13PM +0200, Johannes Hirte wrote:
> > With the latest btrfs changes, I got this Oops when doing rm on a large
> > directory:
> > 
> > BUG: unable to handle kernel NULL pointer dereference at   (null)
> > IP: [<c101c838>] kunmap+0x46/0x46
> > *pdpt = 0000000034a85001 *pde = 0000000000000000
> > Oops: 0000 [#1] PREEMPT SMP
> > last sysfs file: /sys/devices/virtual/vtconsole/vtcon1/uevent
> > Modules linked in: snd_seq_oss snd_seq_midi_event snd_seq snd_seq_device
> > snd_pcm_oss snd_mixer_oss fuse dm_crypt dm_mod usbhid snd_intel8x0
> > snd_ac97_codec ac97_bus snd_pcm snd_timer sr_mod cdrom sg snd fschmd
> > e1000 uhci_hcd snd_page_alloc i2c_i801 [last unloaded: microcode]
> > 
> > Pid: 1156, comm: btrfs-transacti Tainted: G        W   2.6.39-rc1-00262-
> > gc53813f #20 FUJITSU SIEMENS SCENIC P / SCENICO P/D1561
> > EIP: 0060:[<c101c838>] EFLAGS: 00010296 CPU: 1
> > EIP is at kmap+0x0/0x38
> > EAX: 00000000 EBX: 00000000 ECX: 00000000 EDX: 00000010
> > ESI: f5bc6400 EDI: f3c75520 EBP: f3c755f0 ESP: f58f9e10
> > 
> >  DS: 007b ES: 007b FS: 00d8 GS: 0000 SS: 0068
> > 
> > Process btrfs-transacti (pid: 1156, ti=f58f8000 task=f6516f40
> > task.ti=f58f8000)
> > 
> > Stack:
> >  c1186d15 ffc22000 f58f9ec0 00000010 f3c75610 00000000 f5885780 f52339e8
> >  00000009 f5bc6400 00010000 00000000 f6415800 f3c75638 000008bb f5bc63c0
> >  f58857b4 f60b68a0 00000040 f52338e8 ffc22000 00000000 00000008 00000010
> > 
> > Call Trace:
> >  [<c1186d15>] ? btrfs_write_out_cache+0x60c/0xa3c
> >  [<c114a815>] ? btrfs_write_dirty_block_groups+0x400/0x494
> >  [<c11566a7>] ? commit_cowonly_roots+0xa9/0x180
> >  [<c1157799>] ? btrfs_commit_transaction+0x2ee/0x59c
> >  [<c1037c85>] ? wake_up_bit+0x16/0x16
> >  [<c1152a83>] ? transaction_kthread+0x149/0x1d6
> >  [<c101d1b9>] ? complete+0x28/0x36
> >  [<c115293a>] ? btrfs_congested_fn+0x5d/0x5d
> >  [<c10379c4>] ? kthread+0x63/0x68
> >  [<c1037961>] ? kthread_worker_fn+0xeb/0xeb
> >  [<c13cba36>] ? kernel_thread_helper+0x6/0xd
> > 
> > Code: 8d 8a 00 e4 54 c1 2b 8a 8c e7 54 c1 81 f9 00 08 00 00 74 11 81 f9
> > 00 0c 00 00 75 0e 83 3d 10 2f 60 c1 02 75 05 e9 5e a3 04 00 c3 <8b> 10
> > c1 ea 1e c1 e2 0a 8d 8a 00 e4 54 c1 2b 8a 8c e7 54 c1 81
> > EIP: [<c101c838>] kmap+0x0/0x38 SS:ESP 0068:f58f9e10
> > CR2: 0000000000000000
> > ---[ end trace c8511126ee91dfdf ]---
> > 
> > This is the second Oops. On the first one I wasn't able to catch the
> > backtrace, but IIRC the bug happend on kmap not kunmap the first time.
> 
> Yeah I think I know what this is but I need somebody to verify it for me. 
> Can you run with this patch and let me know what happens?  Thanks,
> 
> Josef
> 
> diff --git a/fs/btrfs/free-space-cache.c b/fs/btrfs/free-space-cache.c
> index 74bc432..5e6f4b3 100644
> --- a/fs/btrfs/free-space-cache.c
> +++ b/fs/btrfs/free-space-cache.c
> @@ -624,6 +624,7 @@ int btrfs_write_out_cache(struct btrfs_root *root,
> 
>  		next_page = false;
> 
> +		BUG_ON(index > last_index);
>  		if (index == 0) {
>  			start_offset = first_page_offset;
>  			offset = start_offset;
> @@ -732,6 +733,7 @@ int btrfs_write_out_cache(struct btrfs_root *root,
>  		struct btrfs_free_space *entry =
>  			list_entry(pos, struct btrfs_free_space, list);
> 
> +		BUG_ON(index > last_index);
>  		page = find_get_page(inode->i_mapping, index);
> 
>  		addr = kmap(page);

Hm, I tried but now I hit the 
BUG_ON(block_group->total_bitmaps >= max_bitmaps); in add_new_bitmap in
fs/btrfs/free-space-cache.c:1255 when booting the system.

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: BUG: unable to handle kernel NULL pointer dereference at (null)
  2011-04-05 18:52   ` Johannes Hirte
@ 2011-04-05 18:53     ` Josef Bacik
  2011-04-05 19:21       ` Johannes Hirte
  0 siblings, 1 reply; 16+ messages in thread
From: Josef Bacik @ 2011-04-05 18:53 UTC (permalink / raw)
  To: Johannes Hirte; +Cc: Josef Bacik, linux-btrfs

On Tue, Apr 05, 2011 at 08:52:21PM +0200, Johannes Hirte wrote:
> On Tuesday 05 April 2011 19:42:03 Josef Bacik wrote:
> > On Tue, Apr 05, 2011 at 07:38:13PM +0200, Johannes Hirte wrote:
> > > With the latest btrfs changes, I got this Oops when doing rm on a large
> > > directory:
> > > 
> > > BUG: unable to handle kernel NULL pointer dereference at   (null)
> > > IP: [<c101c838>] kunmap+0x46/0x46
> > > *pdpt = 0000000034a85001 *pde = 0000000000000000
> > > Oops: 0000 [#1] PREEMPT SMP
> > > last sysfs file: /sys/devices/virtual/vtconsole/vtcon1/uevent
> > > Modules linked in: snd_seq_oss snd_seq_midi_event snd_seq snd_seq_device
> > > snd_pcm_oss snd_mixer_oss fuse dm_crypt dm_mod usbhid snd_intel8x0
> > > snd_ac97_codec ac97_bus snd_pcm snd_timer sr_mod cdrom sg snd fschmd
> > > e1000 uhci_hcd snd_page_alloc i2c_i801 [last unloaded: microcode]
> > > 
> > > Pid: 1156, comm: btrfs-transacti Tainted: G        W   2.6.39-rc1-00262-
> > > gc53813f #20 FUJITSU SIEMENS SCENIC P / SCENICO P/D1561
> > > EIP: 0060:[<c101c838>] EFLAGS: 00010296 CPU: 1
> > > EIP is at kmap+0x0/0x38
> > > EAX: 00000000 EBX: 00000000 ECX: 00000000 EDX: 00000010
> > > ESI: f5bc6400 EDI: f3c75520 EBP: f3c755f0 ESP: f58f9e10
> > > 
> > >  DS: 007b ES: 007b FS: 00d8 GS: 0000 SS: 0068
> > > 
> > > Process btrfs-transacti (pid: 1156, ti=f58f8000 task=f6516f40
> > > task.ti=f58f8000)
> > > 
> > > Stack:
> > >  c1186d15 ffc22000 f58f9ec0 00000010 f3c75610 00000000 f5885780 f52339e8
> > >  00000009 f5bc6400 00010000 00000000 f6415800 f3c75638 000008bb f5bc63c0
> > >  f58857b4 f60b68a0 00000040 f52338e8 ffc22000 00000000 00000008 00000010
> > > 
> > > Call Trace:
> > >  [<c1186d15>] ? btrfs_write_out_cache+0x60c/0xa3c
> > >  [<c114a815>] ? btrfs_write_dirty_block_groups+0x400/0x494
> > >  [<c11566a7>] ? commit_cowonly_roots+0xa9/0x180
> > >  [<c1157799>] ? btrfs_commit_transaction+0x2ee/0x59c
> > >  [<c1037c85>] ? wake_up_bit+0x16/0x16
> > >  [<c1152a83>] ? transaction_kthread+0x149/0x1d6
> > >  [<c101d1b9>] ? complete+0x28/0x36
> > >  [<c115293a>] ? btrfs_congested_fn+0x5d/0x5d
> > >  [<c10379c4>] ? kthread+0x63/0x68
> > >  [<c1037961>] ? kthread_worker_fn+0xeb/0xeb
> > >  [<c13cba36>] ? kernel_thread_helper+0x6/0xd
> > > 
> > > Code: 8d 8a 00 e4 54 c1 2b 8a 8c e7 54 c1 81 f9 00 08 00 00 74 11 81 f9
> > > 00 0c 00 00 75 0e 83 3d 10 2f 60 c1 02 75 05 e9 5e a3 04 00 c3 <8b> 10
> > > c1 ea 1e c1 e2 0a 8d 8a 00 e4 54 c1 2b 8a 8c e7 54 c1 81
> > > EIP: [<c101c838>] kmap+0x0/0x38 SS:ESP 0068:f58f9e10
> > > CR2: 0000000000000000
> > > ---[ end trace c8511126ee91dfdf ]---
> > > 
> > > This is the second Oops. On the first one I wasn't able to catch the
> > > backtrace, but IIRC the bug happend on kmap not kunmap the first time.
> > 
> > Yeah I think I know what this is but I need somebody to verify it for me. 
> > Can you run with this patch and let me know what happens?  Thanks,
> > 
> > Josef
> > 
> > diff --git a/fs/btrfs/free-space-cache.c b/fs/btrfs/free-space-cache.c
> > index 74bc432..5e6f4b3 100644
> > --- a/fs/btrfs/free-space-cache.c
> > +++ b/fs/btrfs/free-space-cache.c
> > @@ -624,6 +624,7 @@ int btrfs_write_out_cache(struct btrfs_root *root,
> > 
> >  		next_page = false;
> > 
> > +		BUG_ON(index > last_index);
> >  		if (index == 0) {
> >  			start_offset = first_page_offset;
> >  			offset = start_offset;
> > @@ -732,6 +733,7 @@ int btrfs_write_out_cache(struct btrfs_root *root,
> >  		struct btrfs_free_space *entry =
> >  			list_entry(pos, struct btrfs_free_space, list);
> > 
> > +		BUG_ON(index > last_index);
> >  		page = find_get_page(inode->i_mapping, index);
> > 
> >  		addr = kmap(page);
> 
> Hm, I tried but now I hit the 
> BUG_ON(block_group->total_bitmaps >= max_bitmaps); in add_new_bitmap in
> fs/btrfs/free-space-cache.c:1255 when booting the system.

Can you mount -o clear_cache to make sure it's not the cache thats causing that?
Thanks,

Josef

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: BUG: unable to handle kernel NULL pointer dereference at (null)
  2011-04-05 18:53     ` Josef Bacik
@ 2011-04-05 19:21       ` Johannes Hirte
  2011-04-05 19:31         ` Josef Bacik
  0 siblings, 1 reply; 16+ messages in thread
From: Johannes Hirte @ 2011-04-05 19:21 UTC (permalink / raw)
  To: Josef Bacik; +Cc: linux-btrfs

On Tuesday 05 April 2011 20:53:24 Josef Bacik wrote:
> On Tue, Apr 05, 2011 at 08:52:21PM +0200, Johannes Hirte wrote:
> > On Tuesday 05 April 2011 19:42:03 Josef Bacik wrote:
> > > On Tue, Apr 05, 2011 at 07:38:13PM +0200, Johannes Hirte wrote:
> > > > With the latest btrfs changes, I got this Oops when doing rm on a
> > > > large directory:
> > > > 
> > > > BUG: unable to handle kernel NULL pointer dereference at   (null)
> > > > IP: [<c101c838>] kunmap+0x46/0x46
> > > > *pdpt = 0000000034a85001 *pde = 0000000000000000
> > > > Oops: 0000 [#1] PREEMPT SMP
> > > > last sysfs file: /sys/devices/virtual/vtconsole/vtcon1/uevent
> > > > Modules linked in: snd_seq_oss snd_seq_midi_event snd_seq
> > > > snd_seq_device snd_pcm_oss snd_mixer_oss fuse dm_crypt dm_mod usbhid
> > > > snd_intel8x0 snd_ac97_codec ac97_bus snd_pcm snd_timer sr_mod cdrom
> > > > sg snd fschmd e1000 uhci_hcd snd_page_alloc i2c_i801 [last unloaded:
> > > > microcode]
> > > > 
> > > > Pid: 1156, comm: btrfs-transacti Tainted: G        W  
> > > > 2.6.39-rc1-00262- gc53813f #20 FUJITSU SIEMENS SCENIC P / SCENICO
> > > > P/D1561
> > > > EIP: 0060:[<c101c838>] EFLAGS: 00010296 CPU: 1
> > > > EIP is at kmap+0x0/0x38
> > > > EAX: 00000000 EBX: 00000000 ECX: 00000000 EDX: 00000010
> > > > ESI: f5bc6400 EDI: f3c75520 EBP: f3c755f0 ESP: f58f9e10
> > > > 
> > > >  DS: 007b ES: 007b FS: 00d8 GS: 0000 SS: 0068
> > > > 
> > > > Process btrfs-transacti (pid: 1156, ti=f58f8000 task=f6516f40
> > > > task.ti=f58f8000)
> > > > 
> > > > Stack:
> > > >  c1186d15 ffc22000 f58f9ec0 00000010 f3c75610 00000000 f5885780
> > > >  f52339e8 00000009 f5bc6400 00010000 00000000 f6415800 f3c75638
> > > >  000008bb f5bc63c0 f58857b4 f60b68a0 00000040 f52338e8 ffc22000
> > > >  00000000 00000008 00000010
> > > > 
> > > > Call Trace:
> > > >  [<c1186d15>] ? btrfs_write_out_cache+0x60c/0xa3c
> > > >  [<c114a815>] ? btrfs_write_dirty_block_groups+0x400/0x494
> > > >  [<c11566a7>] ? commit_cowonly_roots+0xa9/0x180
> > > >  [<c1157799>] ? btrfs_commit_transaction+0x2ee/0x59c
> > > >  [<c1037c85>] ? wake_up_bit+0x16/0x16
> > > >  [<c1152a83>] ? transaction_kthread+0x149/0x1d6
> > > >  [<c101d1b9>] ? complete+0x28/0x36
> > > >  [<c115293a>] ? btrfs_congested_fn+0x5d/0x5d
> > > >  [<c10379c4>] ? kthread+0x63/0x68
> > > >  [<c1037961>] ? kthread_worker_fn+0xeb/0xeb
> > > >  [<c13cba36>] ? kernel_thread_helper+0x6/0xd
> > > > 
> > > > Code: 8d 8a 00 e4 54 c1 2b 8a 8c e7 54 c1 81 f9 00 08 00 00 74 11 81
> > > > f9 00 0c 00 00 75 0e 83 3d 10 2f 60 c1 02 75 05 e9 5e a3 04 00 c3
> > > > <8b> 10 c1 ea 1e c1 e2 0a 8d 8a 00 e4 54 c1 2b 8a 8c e7 54 c1 81
> > > > EIP: [<c101c838>] kmap+0x0/0x38 SS:ESP 0068:f58f9e10
> > > > CR2: 0000000000000000
> > > > ---[ end trace c8511126ee91dfdf ]---
> > > > 
> > > > This is the second Oops. On the first one I wasn't able to catch the
> > > > backtrace, but IIRC the bug happend on kmap not kunmap the first
> > > > time.
> > > 
> > > Yeah I think I know what this is but I need somebody to verify it for
> > > me. Can you run with this patch and let me know what happens?  Thanks,
> > > 
> > > Josef
> > > 
> > > diff --git a/fs/btrfs/free-space-cache.c b/fs/btrfs/free-space-cache.c
> > > index 74bc432..5e6f4b3 100644
> > > --- a/fs/btrfs/free-space-cache.c
> > > +++ b/fs/btrfs/free-space-cache.c
> > > @@ -624,6 +624,7 @@ int btrfs_write_out_cache(struct btrfs_root *root,
> > > 
> > >  		next_page = false;
> > > 
> > > +		BUG_ON(index > last_index);
> > > 
> > >  		if (index == 0) {
> > >  		
> > >  			start_offset = first_page_offset;
> > >  			offset = start_offset;
> > > 
> > > @@ -732,6 +733,7 @@ int btrfs_write_out_cache(struct btrfs_root *root,
> > > 
> > >  		struct btrfs_free_space *entry =
> > >  		
> > >  			list_entry(pos, struct btrfs_free_space, list);
> > > 
> > > +		BUG_ON(index > last_index);
> > > 
> > >  		page = find_get_page(inode->i_mapping, index);
> > >  		
> > >  		addr = kmap(page);
> > 
> > Hm, I tried but now I hit the
> > BUG_ON(block_group->total_bitmaps >= max_bitmaps); in add_new_bitmap in
> > fs/btrfs/free-space-cache.c:1255 when booting the system.
> 
> Can you mount -o clear_cache to make sure it's not the cache thats causing
> that? Thanks,
> 
> Josef

Mounting  with clear_cache under 2.6.38 helped. I was able to boot and test 
with your patch an hit the second BUG_ON on free-space-cache.c:738.

regards,
  Johannes

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: BUG: unable to handle kernel NULL pointer dereference at (null)
  2011-04-05 19:21       ` Johannes Hirte
@ 2011-04-05 19:31         ` Josef Bacik
       [not found]           ` <201104052308.53816.johannes.hirte@fem.tu-ilmenau.de>
  0 siblings, 1 reply; 16+ messages in thread
From: Josef Bacik @ 2011-04-05 19:31 UTC (permalink / raw)
  To: Johannes Hirte; +Cc: Josef Bacik, linux-btrfs

On Tue, Apr 05, 2011 at 09:21:55PM +0200, Johannes Hirte wrote:
> On Tuesday 05 April 2011 20:53:24 Josef Bacik wrote:
> > On Tue, Apr 05, 2011 at 08:52:21PM +0200, Johannes Hirte wrote:
> > > On Tuesday 05 April 2011 19:42:03 Josef Bacik wrote:
> > > > On Tue, Apr 05, 2011 at 07:38:13PM +0200, Johannes Hirte wrote:
> > > > > With the latest btrfs changes, I got this Oops when doing rm on a
> > > > > large directory:
> > > > > 
> > > > > BUG: unable to handle kernel NULL pointer dereference at   (null)
> > > > > IP: [<c101c838>] kunmap+0x46/0x46
> > > > > *pdpt = 0000000034a85001 *pde = 0000000000000000
> > > > > Oops: 0000 [#1] PREEMPT SMP
> > > > > last sysfs file: /sys/devices/virtual/vtconsole/vtcon1/uevent
> > > > > Modules linked in: snd_seq_oss snd_seq_midi_event snd_seq
> > > > > snd_seq_device snd_pcm_oss snd_mixer_oss fuse dm_crypt dm_mod usbhid
> > > > > snd_intel8x0 snd_ac97_codec ac97_bus snd_pcm snd_timer sr_mod cdrom
> > > > > sg snd fschmd e1000 uhci_hcd snd_page_alloc i2c_i801 [last unloaded:
> > > > > microcode]
> > > > > 
> > > > > Pid: 1156, comm: btrfs-transacti Tainted: G        W  
> > > > > 2.6.39-rc1-00262- gc53813f #20 FUJITSU SIEMENS SCENIC P / SCENICO
> > > > > P/D1561
> > > > > EIP: 0060:[<c101c838>] EFLAGS: 00010296 CPU: 1
> > > > > EIP is at kmap+0x0/0x38
> > > > > EAX: 00000000 EBX: 00000000 ECX: 00000000 EDX: 00000010
> > > > > ESI: f5bc6400 EDI: f3c75520 EBP: f3c755f0 ESP: f58f9e10
> > > > > 
> > > > >  DS: 007b ES: 007b FS: 00d8 GS: 0000 SS: 0068
> > > > > 
> > > > > Process btrfs-transacti (pid: 1156, ti=f58f8000 task=f6516f40
> > > > > task.ti=f58f8000)
> > > > > 
> > > > > Stack:
> > > > >  c1186d15 ffc22000 f58f9ec0 00000010 f3c75610 00000000 f5885780
> > > > >  f52339e8 00000009 f5bc6400 00010000 00000000 f6415800 f3c75638
> > > > >  000008bb f5bc63c0 f58857b4 f60b68a0 00000040 f52338e8 ffc22000
> > > > >  00000000 00000008 00000010
> > > > > 
> > > > > Call Trace:
> > > > >  [<c1186d15>] ? btrfs_write_out_cache+0x60c/0xa3c
> > > > >  [<c114a815>] ? btrfs_write_dirty_block_groups+0x400/0x494
> > > > >  [<c11566a7>] ? commit_cowonly_roots+0xa9/0x180
> > > > >  [<c1157799>] ? btrfs_commit_transaction+0x2ee/0x59c
> > > > >  [<c1037c85>] ? wake_up_bit+0x16/0x16
> > > > >  [<c1152a83>] ? transaction_kthread+0x149/0x1d6
> > > > >  [<c101d1b9>] ? complete+0x28/0x36
> > > > >  [<c115293a>] ? btrfs_congested_fn+0x5d/0x5d
> > > > >  [<c10379c4>] ? kthread+0x63/0x68
> > > > >  [<c1037961>] ? kthread_worker_fn+0xeb/0xeb
> > > > >  [<c13cba36>] ? kernel_thread_helper+0x6/0xd
> > > > > 
> > > > > Code: 8d 8a 00 e4 54 c1 2b 8a 8c e7 54 c1 81 f9 00 08 00 00 74 11 81
> > > > > f9 00 0c 00 00 75 0e 83 3d 10 2f 60 c1 02 75 05 e9 5e a3 04 00 c3
> > > > > <8b> 10 c1 ea 1e c1 e2 0a 8d 8a 00 e4 54 c1 2b 8a 8c e7 54 c1 81
> > > > > EIP: [<c101c838>] kmap+0x0/0x38 SS:ESP 0068:f58f9e10
> > > > > CR2: 0000000000000000
> > > > > ---[ end trace c8511126ee91dfdf ]---
> > > > > 
> > > > > This is the second Oops. On the first one I wasn't able to catch the
> > > > > backtrace, but IIRC the bug happend on kmap not kunmap the first
> > > > > time.
> > > > 
> > > > Yeah I think I know what this is but I need somebody to verify it for
> > > > me. Can you run with this patch and let me know what happens?  Thanks,
> > > > 
> > > > Josef
> > > > 
> > > > diff --git a/fs/btrfs/free-space-cache.c b/fs/btrfs/free-space-cache.c
> > > > index 74bc432..5e6f4b3 100644
> > > > --- a/fs/btrfs/free-space-cache.c
> > > > +++ b/fs/btrfs/free-space-cache.c
> > > > @@ -624,6 +624,7 @@ int btrfs_write_out_cache(struct btrfs_root *root,
> > > > 
> > > >  		next_page = false;
> > > > 
> > > > +		BUG_ON(index > last_index);
> > > > 
> > > >  		if (index == 0) {
> > > >  		
> > > >  			start_offset = first_page_offset;
> > > >  			offset = start_offset;
> > > > 
> > > > @@ -732,6 +733,7 @@ int btrfs_write_out_cache(struct btrfs_root *root,
> > > > 
> > > >  		struct btrfs_free_space *entry =
> > > >  		
> > > >  			list_entry(pos, struct btrfs_free_space, list);
> > > > 
> > > > +		BUG_ON(index > last_index);
> > > > 
> > > >  		page = find_get_page(inode->i_mapping, index);
> > > >  		
> > > >  		addr = kmap(page);
> > > 
> > > Hm, I tried but now I hit the
> > > BUG_ON(block_group->total_bitmaps >= max_bitmaps); in add_new_bitmap in
> > > fs/btrfs/free-space-cache.c:1255 when booting the system.
> > 
> > Can you mount -o clear_cache to make sure it's not the cache thats causing
> > that? Thanks,
> > 
> > Josef
> 
> Mounting  with clear_cache under 2.6.38 helped. I was able to boot and test 
> with your patch an hit the second BUG_ON on free-space-cache.c:738.
> 

Perfect can you try this and verify you don't panic anymore please?  Thanks,

Josef

---
 fs/btrfs/free-space-cache.c |   18 ++++++++++++++++++
 1 files changed, 18 insertions(+), 0 deletions(-)

diff --git a/fs/btrfs/free-space-cache.c b/fs/btrfs/free-space-cache.c
index 74bc432..33287e8 100644
--- a/fs/btrfs/free-space-cache.c
+++ b/fs/btrfs/free-space-cache.c
@@ -522,6 +522,7 @@ int btrfs_write_out_cache(struct btrfs_root *root,
 	int bitmaps = 0;
 	int ret = 0;
 	bool next_page = false;
+	bool out_of_space = false;
 
 	root = root->fs_info->tree_root;
 
@@ -629,6 +630,11 @@ int btrfs_write_out_cache(struct btrfs_root *root,
 			offset = start_offset;
 		}
 
+		if (index > last_index) {
+			out_of_space = true;
+			break;
+		}
+
 		page = find_get_page(inode->i_mapping, index);
 
 		addr = kmap(page);
@@ -732,6 +738,10 @@ int btrfs_write_out_cache(struct btrfs_root *root,
 		struct btrfs_free_space *entry =
 			list_entry(pos, struct btrfs_free_space, list);
 
+		if (index > last_index) {
+			out_of_space = true;
+			break;
+		}
 		page = find_get_page(inode->i_mapping, index);
 
 		addr = kmap(page);
@@ -754,6 +764,14 @@ int btrfs_write_out_cache(struct btrfs_root *root,
 		index++;
 	}
 
+	if (out_of_space) {
+		ret = 0;
+		unlock_extent_cached(&BTRFS_I(inode)->io_tree, 0,
+				     i_size_read(inode) - 1, &cached_state,
+				     GFP_NOFS);
+		goto out_free;
+	}
+
 	/* Zero out the rest of the pages just to make sure */
 	while (index <= last_index) {
 		void *addr;
-- 
1.7.2.3


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* Re: BUG: unable to handle kernel NULL pointer dereference at (null)
       [not found]           ` <201104052308.53816.johannes.hirte@fem.tu-ilmenau.de>
@ 2011-04-05 21:12             ` Josef Bacik
  2011-04-05 22:00               ` Johannes Hirte
  0 siblings, 1 reply; 16+ messages in thread
From: Josef Bacik @ 2011-04-05 21:12 UTC (permalink / raw)
  To: Johannes Hirte; +Cc: Josef Bacik, linux-btrfs

On Tue, Apr 05, 2011 at 11:08:52PM +0200, Johannes Hirte wrote:
> On Tuesday 05 April 2011 21:31:43 Josef Bacik wrote:
> > On Tue, Apr 05, 2011 at 09:21:55PM +0200, Johannes Hirte wrote:
> > > On Tuesday 05 April 2011 20:53:24 Josef Bacik wrote:
> > > > On Tue, Apr 05, 2011 at 08:52:21PM +0200, Johannes Hirte wrote:
> > > > > On Tuesday 05 April 2011 19:42:03 Josef Bacik wrote:
> > > > > > On Tue, Apr 05, 2011 at 07:38:13PM +0200, Johannes Hirte wrote:
> > > > > > > With the latest btrfs changes, I got this Oops when doing rm on a
> > > > > > > large directory:
> > > > > > > 
> > > > > > > BUG: unable to handle kernel NULL pointer dereference at   (null)
> > > > > > > IP: [<c101c838>] kunmap+0x46/0x46
> > > > > > > *pdpt = 0000000034a85001 *pde = 0000000000000000
> > > > > > > Oops: 0000 [#1] PREEMPT SMP
> > > > > > > last sysfs file: /sys/devices/virtual/vtconsole/vtcon1/uevent
> > > > > > > Modules linked in: snd_seq_oss snd_seq_midi_event snd_seq
> > > > > > > snd_seq_device snd_pcm_oss snd_mixer_oss fuse dm_crypt dm_mod
> > > > > > > usbhid snd_intel8x0 snd_ac97_codec ac97_bus snd_pcm snd_timer
> > > > > > > sr_mod cdrom sg snd fschmd e1000 uhci_hcd snd_page_alloc
> > > > > > > i2c_i801 [last unloaded: microcode]
> > > > > > > 
> > > > > > > Pid: 1156, comm: btrfs-transacti Tainted: G        W
> > > > > > > 2.6.39-rc1-00262- gc53813f #20 FUJITSU SIEMENS SCENIC P / SCENICO
> > > > > > > P/D1561
> > > > > > > EIP: 0060:[<c101c838>] EFLAGS: 00010296 CPU: 1
> > > > > > > EIP is at kmap+0x0/0x38
> > > > > > > EAX: 00000000 EBX: 00000000 ECX: 00000000 EDX: 00000010
> > > > > > > ESI: f5bc6400 EDI: f3c75520 EBP: f3c755f0 ESP: f58f9e10
> > > > > > > 
> > > > > > >  DS: 007b ES: 007b FS: 00d8 GS: 0000 SS: 0068
> > > > > > > 
> > > > > > > Process btrfs-transacti (pid: 1156, ti=f58f8000 task=f6516f40
> > > > > > > task.ti=f58f8000)
> > > > > > > 
> > > > > > > Stack:
> > > > > > >  c1186d15 ffc22000 f58f9ec0 00000010 f3c75610 00000000 f5885780
> > > > > > >  f52339e8 00000009 f5bc6400 00010000 00000000 f6415800 f3c75638
> > > > > > >  000008bb f5bc63c0 f58857b4 f60b68a0 00000040 f52338e8 ffc22000
> > > > > > >  00000000 00000008 00000010
> > > > > > > 
> > > > > > > Call Trace:
> > > > > > >  [<c1186d15>] ? btrfs_write_out_cache+0x60c/0xa3c
> > > > > > >  [<c114a815>] ? btrfs_write_dirty_block_groups+0x400/0x494
> > > > > > >  [<c11566a7>] ? commit_cowonly_roots+0xa9/0x180
> > > > > > >  [<c1157799>] ? btrfs_commit_transaction+0x2ee/0x59c
> > > > > > >  [<c1037c85>] ? wake_up_bit+0x16/0x16
> > > > > > >  [<c1152a83>] ? transaction_kthread+0x149/0x1d6
> > > > > > >  [<c101d1b9>] ? complete+0x28/0x36
> > > > > > >  [<c115293a>] ? btrfs_congested_fn+0x5d/0x5d
> > > > > > >  [<c10379c4>] ? kthread+0x63/0x68
> > > > > > >  [<c1037961>] ? kthread_worker_fn+0xeb/0xeb
> > > > > > >  [<c13cba36>] ? kernel_thread_helper+0x6/0xd
> > > > > > > 
> > > > > > > Code: 8d 8a 00 e4 54 c1 2b 8a 8c e7 54 c1 81 f9 00 08 00 00 74 11
> > > > > > > 81 f9 00 0c 00 00 75 0e 83 3d 10 2f 60 c1 02 75 05 e9 5e a3 04
> > > > > > > 00 c3 <8b> 10 c1 ea 1e c1 e2 0a 8d 8a 00 e4 54 c1 2b 8a 8c e7 54
> > > > > > > c1 81 EIP: [<c101c838>] kmap+0x0/0x38 SS:ESP 0068:f58f9e10
> > > > > > > CR2: 0000000000000000
> > > > > > > ---[ end trace c8511126ee91dfdf ]---
> > > > > > > 
> > > > > > > This is the second Oops. On the first one I wasn't able to catch
> > > > > > > the backtrace, but IIRC the bug happend on kmap not kunmap the
> > > > > > > first time.
> > > > > > 
> > > > > > Yeah I think I know what this is but I need somebody to verify it
> > > > > > for me. Can you run with this patch and let me know what happens? 
> > > > > > Thanks,
> > > > > > 
> > > > > > Josef
> > > > > > 
> > > > > > diff --git a/fs/btrfs/free-space-cache.c
> > > > > > b/fs/btrfs/free-space-cache.c index 74bc432..5e6f4b3 100644
> > > > > > --- a/fs/btrfs/free-space-cache.c
> > > > > > +++ b/fs/btrfs/free-space-cache.c
> > > > > > @@ -624,6 +624,7 @@ int btrfs_write_out_cache(struct btrfs_root
> > > > > > *root,
> > > > > > 
> > > > > >  		next_page = false;
> > > > > > 
> > > > > > +		BUG_ON(index > last_index);
> > > > > > 
> > > > > >  		if (index == 0) {
> > > > > >  		
> > > > > >  			start_offset = first_page_offset;
> > > > > >  			offset = start_offset;
> > > > > > 
> > > > > > @@ -732,6 +733,7 @@ int btrfs_write_out_cache(struct btrfs_root
> > > > > > *root,
> > > > > > 
> > > > > >  		struct btrfs_free_space *entry =
> > > > > >  		
> > > > > >  			list_entry(pos, struct btrfs_free_space, list);
> > > > > > 
> > > > > > +		BUG_ON(index > last_index);
> > > > > > 
> > > > > >  		page = find_get_page(inode->i_mapping, index);
> > > > > >  		
> > > > > >  		addr = kmap(page);
> > > > > 
> > > > > Hm, I tried but now I hit the
> > > > > BUG_ON(block_group->total_bitmaps >= max_bitmaps); in add_new_bitmap
> > > > > in fs/btrfs/free-space-cache.c:1255 when booting the system.
> > > > 
> > > > Can you mount -o clear_cache to make sure it's not the cache thats
> > > > causing that? Thanks,
> > > > 
> > > > Josef
> > > 
> > > Mounting  with clear_cache under 2.6.38 helped. I was able to boot and
> > > test with your patch an hit the second BUG_ON on free-space-cache.c:738.
> > 
> > Perfect can you try this and verify you don't panic anymore please? 
> > Thanks,
> > 
> > Josef
> > 
> > ---
> >  fs/btrfs/free-space-cache.c |   18 ++++++++++++++++++
> >  1 files changed, 18 insertions(+), 0 deletions(-)
> > 
> > diff --git a/fs/btrfs/free-space-cache.c b/fs/btrfs/free-space-cache.c
> > index 74bc432..33287e8 100644
> > --- a/fs/btrfs/free-space-cache.c
> > +++ b/fs/btrfs/free-space-cache.c
> > @@ -522,6 +522,7 @@ int btrfs_write_out_cache(struct btrfs_root *root,
> >  	int bitmaps = 0;
> >  	int ret = 0;
> >  	bool next_page = false;
> > +	bool out_of_space = false;
> > 
> >  	root = root->fs_info->tree_root;
> > 
> > @@ -629,6 +630,11 @@ int btrfs_write_out_cache(struct btrfs_root *root,
> >  			offset = start_offset;
> >  		}
> > 
> > +		if (index > last_index) {
> > +			out_of_space = true;
> > +			break;
> > +		}
> > +
> >  		page = find_get_page(inode->i_mapping, index);
> > 
> >  		addr = kmap(page);
> > @@ -732,6 +738,10 @@ int btrfs_write_out_cache(struct btrfs_root *root,
> >  		struct btrfs_free_space *entry =
> >  			list_entry(pos, struct btrfs_free_space, list);
> > 
> > +		if (index > last_index) {
> > +			out_of_space = true;
> > +			break;
> > +		}
> >  		page = find_get_page(inode->i_mapping, index);
> > 
> >  		addr = kmap(page);
> > @@ -754,6 +764,14 @@ int btrfs_write_out_cache(struct btrfs_root *root,
> >  		index++;
> >  	}
> > 
> > +	if (out_of_space) {
> > +		ret = 0;
> > +		unlock_extent_cached(&BTRFS_I(inode)->io_tree, 0,
> > +				     i_size_read(inode) - 1, &cached_state,
> > +				     GFP_NOFS);
> > +		goto out_free;
> > +	}
> > +
> >  	/* Zero out the rest of the pages just to make sure */
> >  	while (index <= last_index) {
> >  		void *addr;
> 
> With this patch the system doesn't panic anymore, it just hangs. The output 
> from sysrq-t after the hang is attached. I've got also several Oopses from 
> BUG_ON(block_group->total_bitmaps >= max_bitmaps) again when switching from 
> 2.6.38 to 2.6.39-rc.
> 

Balls, sorry about that, this should do the trick, thanks,

Josef

---
 fs/btrfs/free-space-cache.c |   23 +++++++++++++++++++++++
 1 files changed, 23 insertions(+), 0 deletions(-)

diff --git a/fs/btrfs/free-space-cache.c b/fs/btrfs/free-space-cache.c
index 74bc432..fc2bbbe 100644
--- a/fs/btrfs/free-space-cache.c
+++ b/fs/btrfs/free-space-cache.c
@@ -522,6 +522,7 @@ int btrfs_write_out_cache(struct btrfs_root *root,
 	int bitmaps = 0;
 	int ret = 0;
 	bool next_page = false;
+	bool out_of_space = false;
 
 	root = root->fs_info->tree_root;
 
@@ -629,6 +630,11 @@ int btrfs_write_out_cache(struct btrfs_root *root,
 			offset = start_offset;
 		}
 
+		if (index > last_index) {
+			out_of_space = true;
+			break;
+		}
+
 		page = find_get_page(inode->i_mapping, index);
 
 		addr = kmap(page);
@@ -732,6 +738,10 @@ int btrfs_write_out_cache(struct btrfs_root *root,
 		struct btrfs_free_space *entry =
 			list_entry(pos, struct btrfs_free_space, list);
 
+		if (index > last_index) {
+			out_of_space = true;
+			break;
+		}
 		page = find_get_page(inode->i_mapping, index);
 
 		addr = kmap(page);
@@ -754,6 +764,19 @@ int btrfs_write_out_cache(struct btrfs_root *root,
 		index++;
 	}
 
+	if (out_of_space) {
+		page = find_get_page(inode->i_mapping, 0);
+		unlock_page(page);
+		page_cache_release(page);
+		page_cache_release(page);
+
+		ret = 0;
+		unlock_extent_cached(&BTRFS_I(inode)->io_tree, 0,
+				     i_size_read(inode) - 1, &cached_state,
+				     GFP_NOFS);
+		goto out_free;
+	}
+
 	/* Zero out the rest of the pages just to make sure */
 	while (index <= last_index) {
 		void *addr;
-- 
1.7.2.3


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* Re: BUG: unable to handle kernel NULL pointer dereference at (null)
  2011-04-05 22:00               ` Johannes Hirte
@ 2011-04-05 21:57                 ` Josef Bacik
  2011-04-06 11:10                   ` Johannes Hirte
  0 siblings, 1 reply; 16+ messages in thread
From: Josef Bacik @ 2011-04-05 21:57 UTC (permalink / raw)
  To: Johannes Hirte; +Cc: Josef Bacik, linux-btrfs

> 
> Now it hit 

Man I cannot catch a break.  I hope this is the last one.  Thanks,

Josef

---
 fs/btrfs/free-space-cache.c |   32 ++++++++++++++++++++++++++++++++
 1 files changed, 32 insertions(+), 0 deletions(-)

diff --git a/fs/btrfs/free-space-cache.c b/fs/btrfs/free-space-cache.c
index 74bc432..b8052be 100644
--- a/fs/btrfs/free-space-cache.c
+++ b/fs/btrfs/free-space-cache.c
@@ -522,6 +522,7 @@ int btrfs_write_out_cache(struct btrfs_root *root,
 	int bitmaps = 0;
 	int ret = 0;
 	bool next_page = false;
+	bool out_of_space = false;
 
 	root = root->fs_info->tree_root;
 
@@ -629,6 +630,11 @@ int btrfs_write_out_cache(struct btrfs_root *root,
 			offset = start_offset;
 		}
 
+		if (index > last_index) {
+			out_of_space = true;
+			break;
+		}
+
 		page = find_get_page(inode->i_mapping, index);
 
 		addr = kmap(page);
@@ -732,6 +738,10 @@ int btrfs_write_out_cache(struct btrfs_root *root,
 		struct btrfs_free_space *entry =
 			list_entry(pos, struct btrfs_free_space, list);
 
+		if (index > last_index) {
+			out_of_space = true;
+			break;
+		}
 		page = find_get_page(inode->i_mapping, index);
 
 		addr = kmap(page);
@@ -754,6 +764,28 @@ int btrfs_write_out_cache(struct btrfs_root *root,
 		index++;
 	}
 
+	if (out_of_space) {
+		page = find_get_page(inode->i_mapping, 0);
+
+		/*
+		 * Have to do the normal stuff in case writeback gets started on
+		 * this page before we invalidate it.
+		 */
+		ClearPageChecked(page);
+		set_page_extent_mapped(page);
+		SetPageUptodate(page);
+		set_page_dirty(page);
+		unlock_page(page);
+		page_cache_release(page);
+		page_cache_release(page);
+
+		ret = 0;
+		unlock_extent_cached(&BTRFS_I(inode)->io_tree, 0,
+				     i_size_read(inode) - 1, &cached_state,
+				     GFP_NOFS);
+		goto out_free;
+	}
+
 	/* Zero out the rest of the pages just to make sure */
 	while (index <= last_index) {
 		void *addr;
-- 
1.7.2.3


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* Re: BUG: unable to handle kernel NULL pointer dereference at (null)
  2011-04-05 21:12             ` Josef Bacik
@ 2011-04-05 22:00               ` Johannes Hirte
  2011-04-05 21:57                 ` Josef Bacik
  0 siblings, 1 reply; 16+ messages in thread
From: Johannes Hirte @ 2011-04-05 22:00 UTC (permalink / raw)
  To: Josef Bacik; +Cc: linux-btrfs

On Tuesday 05 April 2011 23:12:27 Josef Bacik wrote:
> On Tue, Apr 05, 2011 at 11:08:52PM +0200, Johannes Hirte wrote:
> > On Tuesday 05 April 2011 21:31:43 Josef Bacik wrote:
> > > On Tue, Apr 05, 2011 at 09:21:55PM +0200, Johannes Hirte wrote:
> > > > On Tuesday 05 April 2011 20:53:24 Josef Bacik wrote:
> > > > > On Tue, Apr 05, 2011 at 08:52:21PM +0200, Johannes Hirte wrote:
> > > > > > On Tuesday 05 April 2011 19:42:03 Josef Bacik wrote:
> > > > > > > On Tue, Apr 05, 2011 at 07:38:13PM +0200, Johannes Hirte wrote:
> > > > > > > > With the latest btrfs changes, I got this Oops when doing rm
> > > > > > > > on a large directory:
> > > > > > > > 
> > > > > > > > BUG: unable to handle kernel NULL pointer dereference at  
> > > > > > > > (null) IP: [<c101c838>] kunmap+0x46/0x46
> > > > > > > > *pdpt = 0000000034a85001 *pde = 0000000000000000
> > > > > > > > Oops: 0000 [#1] PREEMPT SMP
> > > > > > > > last sysfs file: /sys/devices/virtual/vtconsole/vtcon1/uevent
> > > > > > > > Modules linked in: snd_seq_oss snd_seq_midi_event snd_seq
> > > > > > > > snd_seq_device snd_pcm_oss snd_mixer_oss fuse dm_crypt dm_mod
> > > > > > > > usbhid snd_intel8x0 snd_ac97_codec ac97_bus snd_pcm snd_timer
> > > > > > > > sr_mod cdrom sg snd fschmd e1000 uhci_hcd snd_page_alloc
> > > > > > > > i2c_i801 [last unloaded: microcode]
> > > > > > > > 
> > > > > > > > Pid: 1156, comm: btrfs-transacti Tainted: G        W
> > > > > > > > 2.6.39-rc1-00262- gc53813f #20 FUJITSU SIEMENS SCENIC P /
> > > > > > > > SCENICO P/D1561
> > > > > > > > EIP: 0060:[<c101c838>] EFLAGS: 00010296 CPU: 1
> > > > > > > > EIP is at kmap+0x0/0x38
> > > > > > > > EAX: 00000000 EBX: 00000000 ECX: 00000000 EDX: 00000010
> > > > > > > > ESI: f5bc6400 EDI: f3c75520 EBP: f3c755f0 ESP: f58f9e10
> > > > > > > > 
> > > > > > > >  DS: 007b ES: 007b FS: 00d8 GS: 0000 SS: 0068
> > > > > > > > 
> > > > > > > > Process btrfs-transacti (pid: 1156, ti=f58f8000 task=f6516f40
> > > > > > > > task.ti=f58f8000)
> > > > > > > > 
> > > > > > > > Stack:
> > > > > > > >  c1186d15 ffc22000 f58f9ec0 00000010 f3c75610 00000000
> > > > > > > >  f5885780 f52339e8 00000009 f5bc6400 00010000 00000000
> > > > > > > >  f6415800 f3c75638 000008bb f5bc63c0 f58857b4 f60b68a0
> > > > > > > >  00000040 f52338e8 ffc22000 00000000 00000008 00000010
> > > > > > > > 
> > > > > > > > Call Trace:
> > > > > > > >  [<c1186d15>] ? btrfs_write_out_cache+0x60c/0xa3c
> > > > > > > >  [<c114a815>] ? btrfs_write_dirty_block_groups+0x400/0x494
> > > > > > > >  [<c11566a7>] ? commit_cowonly_roots+0xa9/0x180
> > > > > > > >  [<c1157799>] ? btrfs_commit_transaction+0x2ee/0x59c
> > > > > > > >  [<c1037c85>] ? wake_up_bit+0x16/0x16
> > > > > > > >  [<c1152a83>] ? transaction_kthread+0x149/0x1d6
> > > > > > > >  [<c101d1b9>] ? complete+0x28/0x36
> > > > > > > >  [<c115293a>] ? btrfs_congested_fn+0x5d/0x5d
> > > > > > > >  [<c10379c4>] ? kthread+0x63/0x68
> > > > > > > >  [<c1037961>] ? kthread_worker_fn+0xeb/0xeb
> > > > > > > >  [<c13cba36>] ? kernel_thread_helper+0x6/0xd
> > > > > > > > 
> > > > > > > > Code: 8d 8a 00 e4 54 c1 2b 8a 8c e7 54 c1 81 f9 00 08 00 00
> > > > > > > > 74 11 81 f9 00 0c 00 00 75 0e 83 3d 10 2f 60 c1 02 75 05 e9
> > > > > > > > 5e a3 04 00 c3 <8b> 10 c1 ea 1e c1 e2 0a 8d 8a 00 e4 54 c1
> > > > > > > > 2b 8a 8c e7 54 c1 81 EIP: [<c101c838>] kmap+0x0/0x38 SS:ESP
> > > > > > > > 0068:f58f9e10 CR2: 0000000000000000
> > > > > > > > ---[ end trace c8511126ee91dfdf ]---
> > > > > > > > 
> > > > > > > > This is the second Oops. On the first one I wasn't able to
> > > > > > > > catch the backtrace, but IIRC the bug happend on kmap not
> > > > > > > > kunmap the first time.
> > > > > > > 
> > > > > > > Yeah I think I know what this is but I need somebody to verify
> > > > > > > it for me. Can you run with this patch and let me know what
> > > > > > > happens? Thanks,
> > > > > > > 
> > > > > > > Josef
> > > > > > > 
> > > > > > > diff --git a/fs/btrfs/free-space-cache.c
> > > > > > > b/fs/btrfs/free-space-cache.c index 74bc432..5e6f4b3 100644
> > > > > > > --- a/fs/btrfs/free-space-cache.c
> > > > > > > +++ b/fs/btrfs/free-space-cache.c
> > > > > > > @@ -624,6 +624,7 @@ int btrfs_write_out_cache(struct btrfs_root
> > > > > > > *root,
> > > > > > > 
> > > > > > >  		next_page = false;
> > > > > > > 
> > > > > > > +		BUG_ON(index > last_index);
> > > > > > > 
> > > > > > >  		if (index == 0) {
> > > > > > >  		
> > > > > > >  			start_offset = first_page_offset;
> > > > > > >  			offset = start_offset;
> > > > > > > 
> > > > > > > @@ -732,6 +733,7 @@ int btrfs_write_out_cache(struct btrfs_root
> > > > > > > *root,
> > > > > > > 
> > > > > > >  		struct btrfs_free_space *entry =
> > > > > > >  		
> > > > > > >  			list_entry(pos, struct btrfs_free_space, list);
> > > > > > > 
> > > > > > > +		BUG_ON(index > last_index);
> > > > > > > 
> > > > > > >  		page = find_get_page(inode->i_mapping, index);
> > > > > > >  		
> > > > > > >  		addr = kmap(page);
> > > > > > 
> > > > > > Hm, I tried but now I hit the
> > > > > > BUG_ON(block_group->total_bitmaps >= max_bitmaps); in
> > > > > > add_new_bitmap in fs/btrfs/free-space-cache.c:1255 when booting
> > > > > > the system.
> > > > > 
> > > > > Can you mount -o clear_cache to make sure it's not the cache thats
> > > > > causing that? Thanks,
> > > > > 
> > > > > Josef
> > > > 
> > > > Mounting  with clear_cache under 2.6.38 helped. I was able to boot
> > > > and test with your patch an hit the second BUG_ON on
> > > > free-space-cache.c:738.
> > > 
> > > Perfect can you try this and verify you don't panic anymore please?
> > > Thanks,
> > > 
> > > Josef
> > > 
> > > ---
> > > 
> > >  fs/btrfs/free-space-cache.c |   18 ++++++++++++++++++
> > >  1 files changed, 18 insertions(+), 0 deletions(-)
> > > 
> > > diff --git a/fs/btrfs/free-space-cache.c b/fs/btrfs/free-space-cache.c
> > > index 74bc432..33287e8 100644
> > > --- a/fs/btrfs/free-space-cache.c
> > > +++ b/fs/btrfs/free-space-cache.c
> > > @@ -522,6 +522,7 @@ int btrfs_write_out_cache(struct btrfs_root *root,
> > > 
> > >  	int bitmaps = 0;
> > >  	int ret = 0;
> > >  	bool next_page = false;
> > > 
> > > +	bool out_of_space = false;
> > > 
> > >  	root = root->fs_info->tree_root;
> > > 
> > > @@ -629,6 +630,11 @@ int btrfs_write_out_cache(struct btrfs_root *root,
> > > 
> > >  			offset = start_offset;
> > >  		
> > >  		}
> > > 
> > > +		if (index > last_index) {
> > > +			out_of_space = true;
> > > +			break;
> > > +		}
> > > +
> > > 
> > >  		page = find_get_page(inode->i_mapping, index);
> > >  		
> > >  		addr = kmap(page);
> > > 
> > > @@ -732,6 +738,10 @@ int btrfs_write_out_cache(struct btrfs_root *root,
> > > 
> > >  		struct btrfs_free_space *entry =
> > >  		
> > >  			list_entry(pos, struct btrfs_free_space, list);
> > > 
> > > +		if (index > last_index) {
> > > +			out_of_space = true;
> > > +			break;
> > > +		}
> > > 
> > >  		page = find_get_page(inode->i_mapping, index);
> > >  		
> > >  		addr = kmap(page);
> > > 
> > > @@ -754,6 +764,14 @@ int btrfs_write_out_cache(struct btrfs_root *root,
> > > 
> > >  		index++;
> > >  	
> > >  	}
> > > 
> > > +	if (out_of_space) {
> > > +		ret = 0;
> > > +		unlock_extent_cached(&BTRFS_I(inode)->io_tree, 0,
> > > +				     i_size_read(inode) - 1, &cached_state,
> > > +				     GFP_NOFS);
> > > +		goto out_free;
> > > +	}
> > > +
> > > 
> > >  	/* Zero out the rest of the pages just to make sure */
> > >  	while (index <= last_index) {
> > >  	
> > >  		void *addr;
> > 
> > With this patch the system doesn't panic anymore, it just hangs. The
> > output from sysrq-t after the hang is attached. I've got also several
> > Oopses from BUG_ON(block_group->total_bitmaps >= max_bitmaps) again when
> > switching from 2.6.38 to 2.6.39-rc.
> 
> Balls, sorry about that, this should do the trick, thanks,
> 
> Josef
> 
> ---
>  fs/btrfs/free-space-cache.c |   23 +++++++++++++++++++++++
>  1 files changed, 23 insertions(+), 0 deletions(-)
> 
> diff --git a/fs/btrfs/free-space-cache.c b/fs/btrfs/free-space-cache.c
> index 74bc432..fc2bbbe 100644
> --- a/fs/btrfs/free-space-cache.c
> +++ b/fs/btrfs/free-space-cache.c
> @@ -522,6 +522,7 @@ int btrfs_write_out_cache(struct btrfs_root *root,
>  	int bitmaps = 0;
>  	int ret = 0;
>  	bool next_page = false;
> +	bool out_of_space = false;
> 
>  	root = root->fs_info->tree_root;
> 
> @@ -629,6 +630,11 @@ int btrfs_write_out_cache(struct btrfs_root *root,
>  			offset = start_offset;
>  		}
> 
> +		if (index > last_index) {
> +			out_of_space = true;
> +			break;
> +		}
> +
>  		page = find_get_page(inode->i_mapping, index);
> 
>  		addr = kmap(page);
> @@ -732,6 +738,10 @@ int btrfs_write_out_cache(struct btrfs_root *root,
>  		struct btrfs_free_space *entry =
>  			list_entry(pos, struct btrfs_free_space, list);
> 
> +		if (index > last_index) {
> +			out_of_space = true;
> +			break;
> +		}
>  		page = find_get_page(inode->i_mapping, index);
> 
>  		addr = kmap(page);
> @@ -754,6 +764,19 @@ int btrfs_write_out_cache(struct btrfs_root *root,
>  		index++;
>  	}
> 
> +	if (out_of_space) {
> +		page = find_get_page(inode->i_mapping, 0);
> +		unlock_page(page);
> +		page_cache_release(page);
> +		page_cache_release(page);
> +
> +		ret = 0;
> +		unlock_extent_cached(&BTRFS_I(inode)->io_tree, 0,
> +				     i_size_read(inode) - 1, &cached_state,
> +				     GFP_NOFS);
> +		goto out_free;
> +	}
> +
>  	/* Zero out the rest of the pages just to make sure */
>  	while (index <= last_index) {
>  		void *addr;

Now it hit 
------------[ cut here ]------------
kernel BUG at fs/btrfs/inode.c:1565!
invalid opcode: 0000 [#1] PREEMPT SMP 
last sysfs file: /sys/devices/virtual/vtconsole/vtcon1/uevent
Modules linked in: snd_seq_oss snd_seq_midi_event snd_seq snd_seq_device 
snd_pcm_oss snd_mixer_oss fuse dm_crypt dm_mod usbhid snd_intel8x0 
snd_ac97_codec ac97_bus snd_pcm sr_mod snd_timer sg cdrom snd fschmd uhci_hcd 
e1000 snd_page_alloc i2c_i801 [last unloaded: microcode]

Pid: 1147, comm: btrfs-fixup-0 Tainted: G        W   2.6.39-rc1-00262-gc53813f-
dirty #24 FUJITSU SIEMENS SCENIC P / SCENICO P/D1561
EIP: 0060:[<c1158999>] EFLAGS: 00010246 CPU: 1
EIP is at btrfs_writepage_fixup_worker+0xf1/0x12d
EAX: 00000000 EBX: 00000000 ECX: 00000000 EDX: f58b1f3c
ESI: 00000000 EDI: f7aef080 EBP: f58b1f6c ESP: f58b1f54
 DS: 007b ES: 007b FS: 00d8 GS: 0000 SS: 0068
Process btrfs-fixup-0 (pid: 1147, ti=f58b0000 task=f65206c0 task.ti=f58b0000)
Stack:
 f4e354e0 00000fff 00000000 f4e353e0 00000000 f49d97c0 00000000 f6645c40
 f49d97d8 f49d97c4 f6645c4c c117c57f f58b1f9c f6645c6c f65206c0 f65206c0
 f65206c0 f6645c4c f58b1f9c f58b1f9c f49d9858 f49d9e98 00000000 f645fd6c
Call Trace:
 [<c117c57f>] ? worker_loop+0x117/0x3ac
 [<c117c468>] ? btrfs_queue_worker+0x1ee/0x1ee
 [<c10379c4>] ? kthread+0x63/0x68
 [<c1037961>] ? kthread_worker_fn+0xeb/0xeb
 [<c13cbab6>] ? kernel_thread_helper+0x6/0xd
Code: f1 8b 44 24 1c e8 83 92 01 00 89 f8 e8 38 e0 ef ff b9 01 00 00 00 8b 54 
24 20 8b 44 24 10 e8 61 6a 01 00 83 c4 10 e9 2c ff ff ff <0f> 0b 6a 50 55 ff 74 24 
10 ff 74 24 10 89 da 89 f1 8b 44 24 1c 
EIP: [<c1158999>] btrfs_writepage_fixup_worker+0xf1/0x12d SS:ESP 0068:f58b1f54
---[ end trace 60f7cf60a0edd44b ]---

And the code looks confusing to me here. btrfs_set_extent_delalloc and 
ClearPageChecked could never be reached. Why are they still there?

regards,
  Johannes

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: BUG: unable to handle kernel NULL pointer dereference at (null)
  2011-04-05 21:57                 ` Josef Bacik
@ 2011-04-06 11:10                   ` Johannes Hirte
  2011-04-06 17:15                     ` Josef Bacik
  0 siblings, 1 reply; 16+ messages in thread
From: Johannes Hirte @ 2011-04-06 11:10 UTC (permalink / raw)
  To: Josef Bacik; +Cc: linux-btrfs

On Tuesday 05 April 2011 23:57:53 Josef Bacik wrote:
> > Now it hit
> 
> Man I cannot catch a break.  I hope this is the last one.  Thanks,
> 
> Josef
> 
> ---
>  fs/btrfs/free-space-cache.c |   32 ++++++++++++++++++++++++++++++++
>  1 files changed, 32 insertions(+), 0 deletions(-)
> 
> diff --git a/fs/btrfs/free-space-cache.c b/fs/btrfs/free-space-cache.c
> index 74bc432..b8052be 100644
> --- a/fs/btrfs/free-space-cache.c
> +++ b/fs/btrfs/free-space-cache.c
> @@ -522,6 +522,7 @@ int btrfs_write_out_cache(struct btrfs_root *root,
>  	int bitmaps = 0;
>  	int ret = 0;
>  	bool next_page = false;
> +	bool out_of_space = false;
> 
>  	root = root->fs_info->tree_root;
> 
> @@ -629,6 +630,11 @@ int btrfs_write_out_cache(struct btrfs_root *root,
>  			offset = start_offset;
>  		}
> 
> +		if (index > last_index) {
> +			out_of_space = true;
> +			break;
> +		}
> +
>  		page = find_get_page(inode->i_mapping, index);
> 
>  		addr = kmap(page);
> @@ -732,6 +738,10 @@ int btrfs_write_out_cache(struct btrfs_root *root,
>  		struct btrfs_free_space *entry =
>  			list_entry(pos, struct btrfs_free_space, list);
> 
> +		if (index > last_index) {
> +			out_of_space = true;
> +			break;
> +		}
>  		page = find_get_page(inode->i_mapping, index);
> 
>  		addr = kmap(page);
> @@ -754,6 +764,28 @@ int btrfs_write_out_cache(struct btrfs_root *root,
>  		index++;
>  	}
> 
> +	if (out_of_space) {
> +		page = find_get_page(inode->i_mapping, 0);
> +
> +		/*
> +		 * Have to do the normal stuff in case writeback gets started on
> +		 * this page before we invalidate it.
> +		 */
> +		ClearPageChecked(page);
> +		set_page_extent_mapped(page);
> +		SetPageUptodate(page);
> +		set_page_dirty(page);
> +		unlock_page(page);
> +		page_cache_release(page);
> +		page_cache_release(page);
> +
> +		ret = 0;
> +		unlock_extent_cached(&BTRFS_I(inode)->io_tree, 0,
> +				     i_size_read(inode) - 1, &cached_state,
> +				     GFP_NOFS);
> +		goto out_free;
> +	}
> +
>  	/* Zero out the rest of the pages just to make sure */
>  	while (index <= last_index) {
>  		void *addr;

Sorry no, it still hits the BUG() in inode.c (line 1565). It takes longer to 
hit than before but is still reproducible.

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: BUG: unable to handle kernel NULL pointer dereference at (null)
  2011-04-06 11:10                   ` Johannes Hirte
@ 2011-04-06 17:15                     ` Josef Bacik
  2011-04-06 20:47                       ` Jordan Patterson
  2011-04-07  8:28                       ` Johannes Hirte
  0 siblings, 2 replies; 16+ messages in thread
From: Josef Bacik @ 2011-04-06 17:15 UTC (permalink / raw)
  To: Johannes Hirte; +Cc: Josef Bacik, linux-btrfs

On Wed, Apr 06, 2011 at 01:10:38PM +0200, Johannes Hirte wrote:
> On Tuesday 05 April 2011 23:57:53 Josef Bacik wrote:
> > > Now it hit
> > 
> > Man I cannot catch a break.  I hope this is the last one.  Thanks,
> > 

Ok I give up, I just cleaned it all up and don't mark the pages as dirty unless
we're actually going to succeed at writing them.  This should fix everything

---
 fs/btrfs/ctree.h            |    5 ++
 fs/btrfs/file.c             |   21 +++----
 fs/btrfs/free-space-cache.c |  117 ++++++++++++++++++++-----------------------
 3 files changed, 69 insertions(+), 74 deletions(-)

diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
index 3458b57..0d00a07 100644
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -2576,6 +2576,11 @@ int btrfs_drop_extents(struct btrfs_trans_handle *trans, struct inode *inode,
 int btrfs_mark_extent_written(struct btrfs_trans_handle *trans,
 			      struct inode *inode, u64 start, u64 end);
 int btrfs_release_file(struct inode *inode, struct file *file);
+void btrfs_drop_pages(struct page **pages, size_t num_pages);
+int btrfs_dirty_pages(struct btrfs_root *root, struct inode *inode,
+		      struct page **pages, size_t num_pages,
+		      loff_t pos, size_t write_bytes,
+		      struct extent_state **cached);
 
 /* tree-defrag.c */
 int btrfs_defrag_leaves(struct btrfs_trans_handle *trans,
diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c
index e621ea5..75899a0 100644
--- a/fs/btrfs/file.c
+++ b/fs/btrfs/file.c
@@ -104,7 +104,7 @@ static noinline int btrfs_copy_from_user(loff_t pos, int num_pages,
 /*
  * unlocks pages after btrfs_file_write is done with them
  */
-static noinline void btrfs_drop_pages(struct page **pages, size_t num_pages)
+void btrfs_drop_pages(struct page **pages, size_t num_pages)
 {
 	size_t i;
 	for (i = 0; i < num_pages; i++) {
@@ -127,16 +127,13 @@ static noinline void btrfs_drop_pages(struct page **pages, size_t num_pages)
  * this also makes the decision about creating an inline extent vs
  * doing real data extents, marking pages dirty and delalloc as required.
  */
-static noinline int dirty_and_release_pages(struct btrfs_root *root,
-					    struct file *file,
-					    struct page **pages,
-					    size_t num_pages,
-					    loff_t pos,
-					    size_t write_bytes)
+int btrfs_dirty_pages(struct btrfs_root *root, struct inode *inode,
+		      struct page **pages, size_t num_pages,
+		      loff_t pos, size_t write_bytes,
+		      struct extent_state **cached)
 {
 	int err = 0;
 	int i;
-	struct inode *inode = fdentry(file)->d_inode;
 	u64 num_bytes;
 	u64 start_pos;
 	u64 end_of_last_block;
@@ -149,7 +146,7 @@ static noinline int dirty_and_release_pages(struct btrfs_root *root,
 
 	end_of_last_block = start_pos + num_bytes - 1;
 	err = btrfs_set_extent_delalloc(inode, start_pos, end_of_last_block,
-					NULL);
+					cached);
 	if (err)
 		return err;
 
@@ -992,9 +989,9 @@ static noinline ssize_t __btrfs_buffered_write(struct file *file,
 		}
 
 		if (copied > 0) {
-			ret = dirty_and_release_pages(root, file, pages,
-						      dirty_pages, pos,
-						      copied);
+			ret = btrfs_dirty_pages(root, inode, pages,
+						dirty_pages, pos, copied,
+						NULL);
 			if (ret) {
 				btrfs_delalloc_release_space(inode,
 					dirty_pages << PAGE_CACHE_SHIFT);
diff --git a/fs/btrfs/free-space-cache.c b/fs/btrfs/free-space-cache.c
index f561c95..a3f420d 100644
--- a/fs/btrfs/free-space-cache.c
+++ b/fs/btrfs/free-space-cache.c
@@ -508,6 +508,7 @@ int btrfs_write_out_cache(struct btrfs_root *root,
 	struct inode *inode;
 	struct rb_node *node;
 	struct list_head *pos, *n;
+	struct page **pages;
 	struct page *page;
 	struct extent_state *cached_state = NULL;
 	struct btrfs_free_cluster *cluster = NULL;
@@ -517,13 +518,13 @@ int btrfs_write_out_cache(struct btrfs_root *root,
 	u64 start, end, len;
 	u64 bytes = 0;
 	u32 *crc, *checksums;
-	pgoff_t index = 0, last_index = 0;
 	unsigned long first_page_offset;
-	int num_checksums;
+	int index = 0, num_pages = 0;
 	int entries = 0;
 	int bitmaps = 0;
 	int ret = 0;
 	bool next_page = false;
+	bool out_of_space = false;
 
 	root = root->fs_info->tree_root;
 
@@ -551,24 +552,31 @@ int btrfs_write_out_cache(struct btrfs_root *root,
 		return 0;
 	}
 
-	last_index = (i_size_read(inode) - 1) >> PAGE_CACHE_SHIFT;
+	num_pages = (i_size_read(inode) + PAGE_CACHE_SIZE - 1) >>
+		PAGE_CACHE_SHIFT;
 	filemap_write_and_wait(inode->i_mapping);
 	btrfs_wait_ordered_range(inode, inode->i_size &
 				 ~(root->sectorsize - 1), (u64)-1);
 
 	/* We need a checksum per page. */
-	num_checksums = i_size_read(inode) / PAGE_CACHE_SIZE;
-	crc = checksums  = kzalloc(sizeof(u32) * num_checksums, GFP_NOFS);
+	crc = checksums = kzalloc(sizeof(u32) * num_pages, GFP_NOFS);
 	if (!crc) {
 		iput(inode);
 		return 0;
 	}
 
+	pages = kzalloc(sizeof(struct page *) * num_pages, GFP_NOFS);
+	if (!pages) {
+		kfree(crc);
+		iput(inode);
+		return 0;
+	}
+
 	/* Since the first page has all of our checksums and our generation we
 	 * need to calculate the offset into the page that we can start writing
 	 * our entries.
 	 */
-	first_page_offset = (sizeof(u32) * num_checksums) + sizeof(u64);
+	first_page_offset = (sizeof(u32) * num_pages) + sizeof(u64);
 
 	/* Get the cluster for this block_group if it exists */
 	if (!list_empty(&block_group->cluster_list))
@@ -590,20 +598,18 @@ int btrfs_write_out_cache(struct btrfs_root *root,
 	 * after find_get_page at this point.  Just putting this here so people
 	 * know and don't freak out.
 	 */
-	while (index <= last_index) {
+	while (index < num_pages) {
 		page = grab_cache_page(inode->i_mapping, index);
 		if (!page) {
-			pgoff_t i = 0;
+			int i;
 
-			while (i < index) {
-				page = find_get_page(inode->i_mapping, i);
-				unlock_page(page);
-				page_cache_release(page);
-				page_cache_release(page);
-				i++;
+			for (i = 0; i < num_pages; i++) {
+				unlock_page(pages[i]);
+				page_cache_release(pages[i]);
 			}
 			goto out_free;
 		}
+		pages[index] = page;
 		index++;
 	}
 
@@ -631,7 +637,12 @@ int btrfs_write_out_cache(struct btrfs_root *root,
 			offset = start_offset;
 		}
 
-		page = find_get_page(inode->i_mapping, index);
+		if (index >= num_pages) {
+			out_of_space = true;
+			break;
+		}
+
+		page = pages[index];
 
 		addr = kmap(page);
 		entry = addr + start_offset;
@@ -708,23 +719,6 @@ int btrfs_write_out_cache(struct btrfs_root *root,
 
 		bytes += PAGE_CACHE_SIZE;
 
-		ClearPageChecked(page);
-		set_page_extent_mapped(page);
-		SetPageUptodate(page);
-		set_page_dirty(page);
-
-		/*
-		 * We need to release our reference we got for grab_cache_page,
-		 * except for the first page which will hold our checksums, we
-		 * do that below.
-		 */
-		if (index != 0) {
-			unlock_page(page);
-			page_cache_release(page);
-		}
-
-		page_cache_release(page);
-
 		index++;
 	} while (node || next_page);
 
@@ -734,6 +728,10 @@ int btrfs_write_out_cache(struct btrfs_root *root,
 		struct btrfs_free_space *entry =
 			list_entry(pos, struct btrfs_free_space, list);
 
+		if (index >= num_pages) {
+			out_of_space = true;
+			break;
+		}
 		page = find_get_page(inode->i_mapping, index);
 
 		addr = kmap(page);
@@ -745,64 +743,58 @@ int btrfs_write_out_cache(struct btrfs_root *root,
 		crc++;
 		bytes += PAGE_CACHE_SIZE;
 
-		ClearPageChecked(page);
-		set_page_extent_mapped(page);
-		SetPageUptodate(page);
-		set_page_dirty(page);
-		unlock_page(page);
-		page_cache_release(page);
-		page_cache_release(page);
 		list_del_init(&entry->list);
 		index++;
 	}
 
+	if (out_of_space) {
+		btrfs_drop_pages(pages, num_pages);
+		unlock_extent_cached(&BTRFS_I(inode)->io_tree, 0,
+				     i_size_read(inode) - 1, &cached_state,
+				     GFP_NOFS);
+		ret = 0;
+		goto out_free;
+	}
+
 	/* Zero out the rest of the pages just to make sure */
-	while (index <= last_index) {
+	while (index < num_pages) {
 		void *addr;
 
-		page = find_get_page(inode->i_mapping, index);
-
+		page = pages[index];
 		addr = kmap(page);
 		memset(addr, 0, PAGE_CACHE_SIZE);
 		kunmap(page);
-		ClearPageChecked(page);
-		set_page_extent_mapped(page);
-		SetPageUptodate(page);
-		set_page_dirty(page);
-		unlock_page(page);
-		page_cache_release(page);
-		page_cache_release(page);
 		bytes += PAGE_CACHE_SIZE;
 		index++;
 	}
 
-	btrfs_set_extent_delalloc(inode, 0, bytes - 1, &cached_state);
-
 	/* Write the checksums and trans id to the first page */
 	{
 		void *addr;
 		u64 *gen;
 
-		page = find_get_page(inode->i_mapping, 0);
+		page = pages[0];
 
 		addr = kmap(page);
-		memcpy(addr, checksums, sizeof(u32) * num_checksums);
-		gen = addr + (sizeof(u32) * num_checksums);
+		memcpy(addr, checksums, sizeof(u32) * num_pages);
+		gen = addr + (sizeof(u32) * num_pages);
 		*gen = trans->transid;
 		kunmap(page);
-		ClearPageChecked(page);
-		set_page_extent_mapped(page);
-		SetPageUptodate(page);
-		set_page_dirty(page);
-		unlock_page(page);
-		page_cache_release(page);
-		page_cache_release(page);
 	}
-	BTRFS_I(inode)->generation = trans->transid;
 
+	ret = btrfs_dirty_pages(root, inode, pages, num_pages, 0,
+					    bytes, &cached_state);
+	btrfs_drop_pages(pages, num_pages);
 	unlock_extent_cached(&BTRFS_I(inode)->io_tree, 0,
 			     i_size_read(inode) - 1, &cached_state, GFP_NOFS);
 
+	if (ret) {
+		ret = 0;
+		goto out_free;
+	}
+
+	BTRFS_I(inode)->generation = trans->transid;
+
 	filemap_write_and_wait(inode->i_mapping);
 
 	key.objectid = BTRFS_FREE_SPACE_OBJECTID;
@@ -853,6 +845,7 @@ out_free:
 		BTRFS_I(inode)->generation = 0;
 	}
 	kfree(checksums);
+	kfree(pages);
 	btrfs_update_inode(trans, root, inode);
 	iput(inode);
 	return ret;
-- 
1.7.2.3


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* Re: BUG: unable to handle kernel NULL pointer dereference at (null)
  2011-04-06 17:15                     ` Josef Bacik
@ 2011-04-06 20:47                       ` Jordan Patterson
  2011-04-06 23:42                         ` Johannes Hirte
  2011-04-07 13:17                         ` Josef Bacik
  2011-04-07  8:28                       ` Johannes Hirte
  1 sibling, 2 replies; 16+ messages in thread
From: Jordan Patterson @ 2011-04-06 20:47 UTC (permalink / raw)
  To: Josef Bacik; +Cc: linux-btrfs

Hi Josef:

I tried your latest patch, since I had the same issue from the first
email.  With the patch applied, I am now hitting the
BUG_ON(block_group->total_bitmaps >=3D max_bitmaps); in add_new_bitmap
in
fs/btrfs/free-space-cache.c:1246 as soon as I mount the filesystem,
with or without -o clear_cache.

It works fine in 2.6.38.  I get the same error after mounting with
clear_cache under 2.6.38 and rebooting into the current kernel with
your patch.

Jordan

On Wed, Apr 6, 2011 at 11:15 AM, Josef Bacik <josef@redhat.com> wrote:
> On Wed, Apr 06, 2011 at 01:10:38PM +0200, Johannes Hirte wrote:
>> On Tuesday 05 April 2011 23:57:53 Josef Bacik wrote:
>> > > Now it hit
>> >
>> > Man I cannot catch a break. =A0I hope this is the last one. =A0Tha=
nks,
>> >
>
> Ok I give up, I just cleaned it all up and don't mark the pages as di=
rty unless
> we're actually going to succeed at writing them. =A0This should fix e=
verything
>
> ---
> =A0fs/btrfs/ctree.h =A0 =A0 =A0 =A0 =A0 =A0| =A0 =A05 ++
> =A0fs/btrfs/file.c =A0 =A0 =A0 =A0 =A0 =A0 | =A0 21 +++----
> =A0fs/btrfs/free-space-cache.c | =A0117 ++++++++++++++++++++---------=
--------------
> =A03 files changed, 69 insertions(+), 74 deletions(-)
>
> diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
> index 3458b57..0d00a07 100644
> --- a/fs/btrfs/ctree.h
> +++ b/fs/btrfs/ctree.h
> @@ -2576,6 +2576,11 @@ int btrfs_drop_extents(struct btrfs_trans_hand=
le *trans, struct inode *inode,
> =A0int btrfs_mark_extent_written(struct btrfs_trans_handle *trans,
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0struct ino=
de *inode, u64 start, u64 end);
> =A0int btrfs_release_file(struct inode *inode, struct file *file);
> +void btrfs_drop_pages(struct page **pages, size_t num_pages);
> +int btrfs_dirty_pages(struct btrfs_root *root, struct inode *inode,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 struct page **pages, size_t=
 num_pages,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 loff_t pos, size_t write_by=
tes,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 struct extent_state **cache=
d);
>
> =A0/* tree-defrag.c */
> =A0int btrfs_defrag_leaves(struct btrfs_trans_handle *trans,
> diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c
> index e621ea5..75899a0 100644
> --- a/fs/btrfs/file.c
> +++ b/fs/btrfs/file.c
> @@ -104,7 +104,7 @@ static noinline int btrfs_copy_from_user(loff_t p=
os, int num_pages,
> =A0/*
> =A0* unlocks pages after btrfs_file_write is done with them
> =A0*/
> -static noinline void btrfs_drop_pages(struct page **pages, size_t nu=
m_pages)
> +void btrfs_drop_pages(struct page **pages, size_t num_pages)
> =A0{
> =A0 =A0 =A0 =A0size_t i;
> =A0 =A0 =A0 =A0for (i =3D 0; i < num_pages; i++) {
> @@ -127,16 +127,13 @@ static noinline void btrfs_drop_pages(struct pa=
ge **pages, size_t num_pages)
> =A0* this also makes the decision about creating an inline extent vs
> =A0* doing real data extents, marking pages dirty and delalloc as req=
uired.
> =A0*/
> -static noinline int dirty_and_release_pages(struct btrfs_root *root,
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
 =A0 =A0 =A0 =A0 struct file *file,
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
 =A0 =A0 =A0 =A0 struct page **pages,
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
 =A0 =A0 =A0 =A0 size_t num_pages,
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
 =A0 =A0 =A0 =A0 loff_t pos,
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
 =A0 =A0 =A0 =A0 size_t write_bytes)
> +int btrfs_dirty_pages(struct btrfs_root *root, struct inode *inode,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 struct page **pages, size_t=
 num_pages,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 loff_t pos, size_t write_by=
tes,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 struct extent_state **cache=
d)
> =A0{
> =A0 =A0 =A0 =A0int err =3D 0;
> =A0 =A0 =A0 =A0int i;
> - =A0 =A0 =A0 struct inode *inode =3D fdentry(file)->d_inode;
> =A0 =A0 =A0 =A0u64 num_bytes;
> =A0 =A0 =A0 =A0u64 start_pos;
> =A0 =A0 =A0 =A0u64 end_of_last_block;
> @@ -149,7 +146,7 @@ static noinline int dirty_and_release_pages(struc=
t btrfs_root *root,
>
> =A0 =A0 =A0 =A0end_of_last_block =3D start_pos + num_bytes - 1;
> =A0 =A0 =A0 =A0err =3D btrfs_set_extent_delalloc(inode, start_pos, en=
d_of_last_block,
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
 =A0 =A0 NULL);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
 =A0 =A0 cached);
> =A0 =A0 =A0 =A0if (err)
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0return err;
>
> @@ -992,9 +989,9 @@ static noinline ssize_t __btrfs_buffered_write(st=
ruct file *file,
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0}
>
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0if (copied > 0) {
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 ret =3D dirty_and_relea=
se_pages(root, file, pages,
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 dirty_pages, pos,
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 copied);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 ret =3D btrfs_dirty_pag=
es(root, inode, pages,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
 =A0 =A0 =A0 =A0 =A0 =A0 dirty_pages, pos, copied,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
 =A0 =A0 =A0 =A0 =A0 =A0 NULL);
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0if (ret) {
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0btrfs_=
delalloc_release_space(inode,
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
 =A0 =A0dirty_pages << PAGE_CACHE_SHIFT);
> diff --git a/fs/btrfs/free-space-cache.c b/fs/btrfs/free-space-cache.=
c
> index f561c95..a3f420d 100644
> --- a/fs/btrfs/free-space-cache.c
> +++ b/fs/btrfs/free-space-cache.c
> @@ -508,6 +508,7 @@ int btrfs_write_out_cache(struct btrfs_root *root=
,
> =A0 =A0 =A0 =A0struct inode *inode;
> =A0 =A0 =A0 =A0struct rb_node *node;
> =A0 =A0 =A0 =A0struct list_head *pos, *n;
> + =A0 =A0 =A0 struct page **pages;
> =A0 =A0 =A0 =A0struct page *page;
> =A0 =A0 =A0 =A0struct extent_state *cached_state =3D NULL;
> =A0 =A0 =A0 =A0struct btrfs_free_cluster *cluster =3D NULL;
> @@ -517,13 +518,13 @@ int btrfs_write_out_cache(struct btrfs_root *ro=
ot,
> =A0 =A0 =A0 =A0u64 start, end, len;
> =A0 =A0 =A0 =A0u64 bytes =3D 0;
> =A0 =A0 =A0 =A0u32 *crc, *checksums;
> - =A0 =A0 =A0 pgoff_t index =3D 0, last_index =3D 0;
> =A0 =A0 =A0 =A0unsigned long first_page_offset;
> - =A0 =A0 =A0 int num_checksums;
> + =A0 =A0 =A0 int index =3D 0, num_pages =3D 0;
> =A0 =A0 =A0 =A0int entries =3D 0;
> =A0 =A0 =A0 =A0int bitmaps =3D 0;
> =A0 =A0 =A0 =A0int ret =3D 0;
> =A0 =A0 =A0 =A0bool next_page =3D false;
> + =A0 =A0 =A0 bool out_of_space =3D false;
>
> =A0 =A0 =A0 =A0root =3D root->fs_info->tree_root;
>
> @@ -551,24 +552,31 @@ int btrfs_write_out_cache(struct btrfs_root *ro=
ot,
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0return 0;
> =A0 =A0 =A0 =A0}
>
> - =A0 =A0 =A0 last_index =3D (i_size_read(inode) - 1) >> PAGE_CACHE_S=
HIFT;
> + =A0 =A0 =A0 num_pages =3D (i_size_read(inode) + PAGE_CACHE_SIZE - 1=
) >>
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 PAGE_CACHE_SHIFT;
> =A0 =A0 =A0 =A0filemap_write_and_wait(inode->i_mapping);
> =A0 =A0 =A0 =A0btrfs_wait_ordered_range(inode, inode->i_size &
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 ~(roo=
t->sectorsize - 1), (u64)-1);
>
> =A0 =A0 =A0 =A0/* We need a checksum per page. */
> - =A0 =A0 =A0 num_checksums =3D i_size_read(inode) / PAGE_CACHE_SIZE;
> - =A0 =A0 =A0 crc =3D checksums =A0=3D kzalloc(sizeof(u32) * num_chec=
ksums, GFP_NOFS);
> + =A0 =A0 =A0 crc =3D checksums =3D kzalloc(sizeof(u32) * num_pages, =
GFP_NOFS);
> =A0 =A0 =A0 =A0if (!crc) {
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0iput(inode);
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0return 0;
> =A0 =A0 =A0 =A0}
>
> + =A0 =A0 =A0 pages =3D kzalloc(sizeof(struct page *) * num_pages, GF=
P_NOFS);
> + =A0 =A0 =A0 if (!pages) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 kfree(crc);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 iput(inode);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 return 0;
> + =A0 =A0 =A0 }
> +
> =A0 =A0 =A0 =A0/* Since the first page has all of our checksums and o=
ur generation we
> =A0 =A0 =A0 =A0 * need to calculate the offset into the page that we =
can start writing
> =A0 =A0 =A0 =A0 * our entries.
> =A0 =A0 =A0 =A0 */
> - =A0 =A0 =A0 first_page_offset =3D (sizeof(u32) * num_checksums) + s=
izeof(u64);
> + =A0 =A0 =A0 first_page_offset =3D (sizeof(u32) * num_pages) + sizeo=
f(u64);
>
> =A0 =A0 =A0 =A0/* Get the cluster for this block_group if it exists *=
/
> =A0 =A0 =A0 =A0if (!list_empty(&block_group->cluster_list))
> @@ -590,20 +598,18 @@ int btrfs_write_out_cache(struct btrfs_root *ro=
ot,
> =A0 =A0 =A0 =A0 * after find_get_page at this point. =A0Just putting =
this here so people
> =A0 =A0 =A0 =A0 * know and don't freak out.
> =A0 =A0 =A0 =A0 */
> - =A0 =A0 =A0 while (index <=3D last_index) {
> + =A0 =A0 =A0 while (index < num_pages) {
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0page =3D grab_cache_page(inode->i_mapp=
ing, index);
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0if (!page) {
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 pgoff_t i =3D 0;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 int i;
>
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 while (i < index) {
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 page =3D=
 find_get_page(inode->i_mapping, i);
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 unlock_=
page(page);
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 page_ca=
che_release(page);
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 page_ca=
che_release(page);
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 i++;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 for (i =3D 0; i < num_p=
ages; i++) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 unlock_=
page(pages[i]);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 page_ca=
che_release(pages[i]);
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0}
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0goto out_free;
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0}
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 pages[index] =3D page;
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0index++;
> =A0 =A0 =A0 =A0}
>
> @@ -631,7 +637,12 @@ int btrfs_write_out_cache(struct btrfs_root *roo=
t,
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0offset =3D start_offse=
t;
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0}
>
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 page =3D find_get_page(inode->i_mapping=
, index);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (index >=3D num_pages) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 out_of_space =3D true;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 break;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 }
> +
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 page =3D pages[index];
>
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0addr =3D kmap(page);
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0entry =3D addr + start_offset;
> @@ -708,23 +719,6 @@ int btrfs_write_out_cache(struct btrfs_root *roo=
t,
>
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0bytes +=3D PAGE_CACHE_SIZE;
>
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 ClearPageChecked(page);
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 set_page_extent_mapped(page);
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 SetPageUptodate(page);
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 set_page_dirty(page);
> -
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 /*
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0* We need to release our reference w=
e got for grab_cache_page,
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0* except for the first page which wi=
ll hold our checksums, we
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0* do that below.
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0*/
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (index !=3D 0) {
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 unlock_page(page);
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 page_cache_release(page=
);
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 }
> -
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 page_cache_release(page);
> -
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0index++;
> =A0 =A0 =A0 =A0} while (node || next_page);
>
> @@ -734,6 +728,10 @@ int btrfs_write_out_cache(struct btrfs_root *roo=
t,
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0struct btrfs_free_space *entry =3D
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0list_entry(pos, struct=
 btrfs_free_space, list);
>
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (index >=3D num_pages) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 out_of_space =3D true;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 break;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 }
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0page =3D find_get_page(inode->i_mappin=
g, index);
>
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0addr =3D kmap(page);
> @@ -745,64 +743,58 @@ int btrfs_write_out_cache(struct btrfs_root *ro=
ot,
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0crc++;
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0bytes +=3D PAGE_CACHE_SIZE;
>
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 ClearPageChecked(page);
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 set_page_extent_mapped(page);
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 SetPageUptodate(page);
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 set_page_dirty(page);
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 unlock_page(page);
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 page_cache_release(page);
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 page_cache_release(page);
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0list_del_init(&entry->list);
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0index++;
> =A0 =A0 =A0 =A0}
>
> + =A0 =A0 =A0 if (out_of_space) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 btrfs_drop_pages(pages, num_pages);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 unlock_extent_cached(&BTRFS_I(inode)->i=
o_tree, 0,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
 =A0i_size_read(inode) - 1, &cached_state,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
 =A0GFP_NOFS);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 ret =3D 0;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 goto out_free;
> + =A0 =A0 =A0 }
> +
> =A0 =A0 =A0 =A0/* Zero out the rest of the pages just to make sure */
> - =A0 =A0 =A0 while (index <=3D last_index) {
> + =A0 =A0 =A0 while (index < num_pages) {
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0void *addr;
>
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 page =3D find_get_page(inode->i_mapping=
, index);
> -
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 page =3D pages[index];
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0addr =3D kmap(page);
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0memset(addr, 0, PAGE_CACHE_SIZE);
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0kunmap(page);
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 ClearPageChecked(page);
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 set_page_extent_mapped(page);
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 SetPageUptodate(page);
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 set_page_dirty(page);
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 unlock_page(page);
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 page_cache_release(page);
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 page_cache_release(page);
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0bytes +=3D PAGE_CACHE_SIZE;
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0index++;
> =A0 =A0 =A0 =A0}
>
> - =A0 =A0 =A0 btrfs_set_extent_delalloc(inode, 0, bytes - 1, &cached_=
state);
> -
> =A0 =A0 =A0 =A0/* Write the checksums and trans id to the first page =
*/
> =A0 =A0 =A0 =A0{
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0void *addr;
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0u64 *gen;
>
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 page =3D find_get_page(inode->i_mapping=
, 0);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 page =3D pages[0];
>
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0addr =3D kmap(page);
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 memcpy(addr, checksums, sizeof(u32) * n=
um_checksums);
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 gen =3D addr + (sizeof(u32) * num_check=
sums);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 memcpy(addr, checksums, sizeof(u32) * n=
um_pages);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 gen =3D addr + (sizeof(u32) * num_pages=
);
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0*gen =3D trans->transid;
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0kunmap(page);
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 ClearPageChecked(page);
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 set_page_extent_mapped(page);
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 SetPageUptodate(page);
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 set_page_dirty(page);
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 unlock_page(page);
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 page_cache_release(page);
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 page_cache_release(page);
> =A0 =A0 =A0 =A0}
> - =A0 =A0 =A0 BTRFS_I(inode)->generation =3D trans->transid;
>
> + =A0 =A0 =A0 ret =3D btrfs_dirty_pages(root, inode, pages, num_pages=
, 0,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
 =A0 =A0 =A0 =A0 bytes, &cached_state);
> + =A0 =A0 =A0 btrfs_drop_pages(pages, num_pages);
> =A0 =A0 =A0 =A0unlock_extent_cached(&BTRFS_I(inode)->io_tree, 0,
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 i_size_read(i=
node) - 1, &cached_state, GFP_NOFS);
>
> + =A0 =A0 =A0 if (ret) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 ret =3D 0;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 goto out_free;
> + =A0 =A0 =A0 }
> +
> + =A0 =A0 =A0 BTRFS_I(inode)->generation =3D trans->transid;
> +
> =A0 =A0 =A0 =A0filemap_write_and_wait(inode->i_mapping);
>
> =A0 =A0 =A0 =A0key.objectid =3D BTRFS_FREE_SPACE_OBJECTID;
> @@ -853,6 +845,7 @@ out_free:
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0BTRFS_I(inode)->generation =3D 0;
> =A0 =A0 =A0 =A0}
> =A0 =A0 =A0 =A0kfree(checksums);
> + =A0 =A0 =A0 kfree(pages);
> =A0 =A0 =A0 =A0btrfs_update_inode(trans, root, inode);
> =A0 =A0 =A0 =A0iput(inode);
> =A0 =A0 =A0 =A0return ret;
> --
> 1.7.2.3
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-btrfs=
" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at =A0http://vger.kernel.org/majordomo-info.html
>
--
To unsubscribe from this list: send the line "unsubscribe linux-btrfs" =
in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: BUG: unable to handle kernel NULL pointer dereference at (null)
  2011-04-06 20:47                       ` Jordan Patterson
@ 2011-04-06 23:42                         ` Johannes Hirte
  2011-04-07 13:17                         ` Josef Bacik
  1 sibling, 0 replies; 16+ messages in thread
From: Johannes Hirte @ 2011-04-06 23:42 UTC (permalink / raw)
  To: Jordan Patterson; +Cc: Josef Bacik, linux-btrfs

On Wednesday 06 April 2011 22:47:28 Jordan Patterson wrote:
> Hi Josef:
> 
> I tried your latest patch, since I had the same issue from the first
> email.  With the patch applied, I am now hitting the
> BUG_ON(block_group->total_bitmaps >= max_bitmaps); in add_new_bitmap
> in
> fs/btrfs/free-space-cache.c:1246 as soon as I mount the filesystem,
> with or without -o clear_cache.
> 
> It works fine in 2.6.38.  I get the same error after mounting with
> clear_cache under 2.6.38 and rebooting into the current kernel with
> your patch.
> 
> Jordan

What filesystem is it and how did you mount it with -o clear_cache? If it is 
your rootfs did you applied clear_cache to /etc/fstab or your bootloader? If 
it was the latter it won't work. For the rootfs you need to add it to the boot 
options. For me this worked every time.
Josef, is there any way to detect a wrong cache, saved by an pre-2.6.39 kernel 
and discard it?


regards,
  Johannes

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: BUG: unable to handle kernel NULL pointer dereference at (null)
  2011-04-06 17:15                     ` Josef Bacik
  2011-04-06 20:47                       ` Jordan Patterson
@ 2011-04-07  8:28                       ` Johannes Hirte
  1 sibling, 0 replies; 16+ messages in thread
From: Johannes Hirte @ 2011-04-07  8:28 UTC (permalink / raw)
  To: Josef Bacik; +Cc: linux-btrfs

On Wednesday 06 April 2011 19:15:41 Josef Bacik wrote:
> On Wed, Apr 06, 2011 at 01:10:38PM +0200, Johannes Hirte wrote:
> > On Tuesday 05 April 2011 23:57:53 Josef Bacik wrote:
> > > > Now it hit
> > > 
> > > Man I cannot catch a break.  I hope this is the last one.  Thanks,
> 
> Ok I give up, I just cleaned it all up and don't mark the pages as dirty
> unless we're actually going to succeed at writing them.  This should fix
> everything
> 
> ---
>  fs/btrfs/ctree.h            |    5 ++
>  fs/btrfs/file.c             |   21 +++----
>  fs/btrfs/free-space-cache.c |  117
> ++++++++++++++++++++----------------------- 3 files changed, 69
> insertions(+), 74 deletions(-)
> 
> diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
> index 3458b57..0d00a07 100644
> --- a/fs/btrfs/ctree.h
> +++ b/fs/btrfs/ctree.h
> @@ -2576,6 +2576,11 @@ int btrfs_drop_extents(struct btrfs_trans_handle
> *trans, struct inode *inode, int btrfs_mark_extent_written(struct
> btrfs_trans_handle *trans,
>  			      struct inode *inode, u64 start, u64 end);
>  int btrfs_release_file(struct inode *inode, struct file *file);
> +void btrfs_drop_pages(struct page **pages, size_t num_pages);
> +int btrfs_dirty_pages(struct btrfs_root *root, struct inode *inode,
> +		      struct page **pages, size_t num_pages,
> +		      loff_t pos, size_t write_bytes,
> +		      struct extent_state **cached);
> 
>  /* tree-defrag.c */
>  int btrfs_defrag_leaves(struct btrfs_trans_handle *trans,
> diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c
> index e621ea5..75899a0 100644
> --- a/fs/btrfs/file.c
> +++ b/fs/btrfs/file.c
> @@ -104,7 +104,7 @@ static noinline int btrfs_copy_from_user(loff_t pos,
> int num_pages, /*
>   * unlocks pages after btrfs_file_write is done with them
>   */
> -static noinline void btrfs_drop_pages(struct page **pages, size_t
> num_pages) +void btrfs_drop_pages(struct page **pages, size_t num_pages)
>  {
>  	size_t i;
>  	for (i = 0; i < num_pages; i++) {
> @@ -127,16 +127,13 @@ static noinline void btrfs_drop_pages(struct page
> **pages, size_t num_pages) * this also makes the decision about creating
> an inline extent vs * doing real data extents, marking pages dirty and
> delalloc as required. */
> -static noinline int dirty_and_release_pages(struct btrfs_root *root,
> -					    struct file *file,
> -					    struct page **pages,
> -					    size_t num_pages,
> -					    loff_t pos,
> -					    size_t write_bytes)
> +int btrfs_dirty_pages(struct btrfs_root *root, struct inode *inode,
> +		      struct page **pages, size_t num_pages,
> +		      loff_t pos, size_t write_bytes,
> +		      struct extent_state **cached)
>  {
>  	int err = 0;
>  	int i;
> -	struct inode *inode = fdentry(file)->d_inode;
>  	u64 num_bytes;
>  	u64 start_pos;
>  	u64 end_of_last_block;
> @@ -149,7 +146,7 @@ static noinline int dirty_and_release_pages(struct
> btrfs_root *root,
> 
>  	end_of_last_block = start_pos + num_bytes - 1;
>  	err = btrfs_set_extent_delalloc(inode, start_pos, end_of_last_block,
> -					NULL);
> +					cached);
>  	if (err)
>  		return err;
> 
> @@ -992,9 +989,9 @@ static noinline ssize_t __btrfs_buffered_write(struct
> file *file, }
> 
>  		if (copied > 0) {
> -			ret = dirty_and_release_pages(root, file, pages,
> -						      dirty_pages, pos,
> -						      copied);
> +			ret = btrfs_dirty_pages(root, inode, pages,
> +						dirty_pages, pos, copied,
> +						NULL);
>  			if (ret) {
>  				btrfs_delalloc_release_space(inode,
>  					dirty_pages << PAGE_CACHE_SHIFT);
> diff --git a/fs/btrfs/free-space-cache.c b/fs/btrfs/free-space-cache.c
> index f561c95..a3f420d 100644
> --- a/fs/btrfs/free-space-cache.c
> +++ b/fs/btrfs/free-space-cache.c
> @@ -508,6 +508,7 @@ int btrfs_write_out_cache(struct btrfs_root *root,
>  	struct inode *inode;
>  	struct rb_node *node;
>  	struct list_head *pos, *n;
> +	struct page **pages;
>  	struct page *page;
>  	struct extent_state *cached_state = NULL;
>  	struct btrfs_free_cluster *cluster = NULL;
> @@ -517,13 +518,13 @@ int btrfs_write_out_cache(struct btrfs_root *root,
>  	u64 start, end, len;
>  	u64 bytes = 0;
>  	u32 *crc, *checksums;
> -	pgoff_t index = 0, last_index = 0;
>  	unsigned long first_page_offset;
> -	int num_checksums;
> +	int index = 0, num_pages = 0;
>  	int entries = 0;
>  	int bitmaps = 0;
>  	int ret = 0;
>  	bool next_page = false;
> +	bool out_of_space = false;
> 
>  	root = root->fs_info->tree_root;
> 
> @@ -551,24 +552,31 @@ int btrfs_write_out_cache(struct btrfs_root *root,
>  		return 0;
>  	}
> 
> -	last_index = (i_size_read(inode) - 1) >> PAGE_CACHE_SHIFT;
> +	num_pages = (i_size_read(inode) + PAGE_CACHE_SIZE - 1) >>
> +		PAGE_CACHE_SHIFT;
>  	filemap_write_and_wait(inode->i_mapping);
>  	btrfs_wait_ordered_range(inode, inode->i_size &
>  				 ~(root->sectorsize - 1), (u64)-1);
> 
>  	/* We need a checksum per page. */
> -	num_checksums = i_size_read(inode) / PAGE_CACHE_SIZE;
> -	crc = checksums  = kzalloc(sizeof(u32) * num_checksums, GFP_NOFS);
> +	crc = checksums = kzalloc(sizeof(u32) * num_pages, GFP_NOFS);
>  	if (!crc) {
>  		iput(inode);
>  		return 0;
>  	}
> 
> +	pages = kzalloc(sizeof(struct page *) * num_pages, GFP_NOFS);
> +	if (!pages) {
> +		kfree(crc);
> +		iput(inode);
> +		return 0;
> +	}
> +
>  	/* Since the first page has all of our checksums and our generation we
>  	 * need to calculate the offset into the page that we can start writing
>  	 * our entries.
>  	 */
> -	first_page_offset = (sizeof(u32) * num_checksums) + sizeof(u64);
> +	first_page_offset = (sizeof(u32) * num_pages) + sizeof(u64);
> 
>  	/* Get the cluster for this block_group if it exists */
>  	if (!list_empty(&block_group->cluster_list))
> @@ -590,20 +598,18 @@ int btrfs_write_out_cache(struct btrfs_root *root,
>  	 * after find_get_page at this point.  Just putting this here so people
>  	 * know and don't freak out.
>  	 */
> -	while (index <= last_index) {
> +	while (index < num_pages) {
>  		page = grab_cache_page(inode->i_mapping, index);
>  		if (!page) {
> -			pgoff_t i = 0;
> +			int i;
> 
> -			while (i < index) {
> -				page = find_get_page(inode->i_mapping, i);
> -				unlock_page(page);
> -				page_cache_release(page);
> -				page_cache_release(page);
> -				i++;
> +			for (i = 0; i < num_pages; i++) {
> +				unlock_page(pages[i]);
> +				page_cache_release(pages[i]);
>  			}
>  			goto out_free;
>  		}
> +		pages[index] = page;
>  		index++;
>  	}
> 
> @@ -631,7 +637,12 @@ int btrfs_write_out_cache(struct btrfs_root *root,
>  			offset = start_offset;
>  		}
> 
> -		page = find_get_page(inode->i_mapping, index);
> +		if (index >= num_pages) {
> +			out_of_space = true;
> +			break;
> +		}
> +
> +		page = pages[index];
> 
>  		addr = kmap(page);
>  		entry = addr + start_offset;
> @@ -708,23 +719,6 @@ int btrfs_write_out_cache(struct btrfs_root *root,
> 
>  		bytes += PAGE_CACHE_SIZE;
> 
> -		ClearPageChecked(page);
> -		set_page_extent_mapped(page);
> -		SetPageUptodate(page);
> -		set_page_dirty(page);
> -
> -		/*
> -		 * We need to release our reference we got for grab_cache_page,
> -		 * except for the first page which will hold our checksums, we
> -		 * do that below.
> -		 */
> -		if (index != 0) {
> -			unlock_page(page);
> -			page_cache_release(page);
> -		}
> -
> -		page_cache_release(page);
> -
>  		index++;
>  	} while (node || next_page);
> 
> @@ -734,6 +728,10 @@ int btrfs_write_out_cache(struct btrfs_root *root,
>  		struct btrfs_free_space *entry =
>  			list_entry(pos, struct btrfs_free_space, list);
> 
> +		if (index >= num_pages) {
> +			out_of_space = true;
> +			break;
> +		}
>  		page = find_get_page(inode->i_mapping, index);
> 
>  		addr = kmap(page);
> @@ -745,64 +743,58 @@ int btrfs_write_out_cache(struct btrfs_root *root,
>  		crc++;
>  		bytes += PAGE_CACHE_SIZE;
> 
> -		ClearPageChecked(page);
> -		set_page_extent_mapped(page);
> -		SetPageUptodate(page);
> -		set_page_dirty(page);
> -		unlock_page(page);
> -		page_cache_release(page);
> -		page_cache_release(page);
>  		list_del_init(&entry->list);
>  		index++;
>  	}
> 
> +	if (out_of_space) {
> +		btrfs_drop_pages(pages, num_pages);
> +		unlock_extent_cached(&BTRFS_I(inode)->io_tree, 0,
> +				     i_size_read(inode) - 1, &cached_state,
> +				     GFP_NOFS);
> +		ret = 0;
> +		goto out_free;
> +	}
> +
>  	/* Zero out the rest of the pages just to make sure */
> -	while (index <= last_index) {
> +	while (index < num_pages) {
>  		void *addr;
> 
> -		page = find_get_page(inode->i_mapping, index);
> -
> +		page = pages[index];
>  		addr = kmap(page);
>  		memset(addr, 0, PAGE_CACHE_SIZE);
>  		kunmap(page);
> -		ClearPageChecked(page);
> -		set_page_extent_mapped(page);
> -		SetPageUptodate(page);
> -		set_page_dirty(page);
> -		unlock_page(page);
> -		page_cache_release(page);
> -		page_cache_release(page);
>  		bytes += PAGE_CACHE_SIZE;
>  		index++;
>  	}
> 
> -	btrfs_set_extent_delalloc(inode, 0, bytes - 1, &cached_state);
> -
>  	/* Write the checksums and trans id to the first page */
>  	{
>  		void *addr;
>  		u64 *gen;
> 
> -		page = find_get_page(inode->i_mapping, 0);
> +		page = pages[0];
> 
>  		addr = kmap(page);
> -		memcpy(addr, checksums, sizeof(u32) * num_checksums);
> -		gen = addr + (sizeof(u32) * num_checksums);
> +		memcpy(addr, checksums, sizeof(u32) * num_pages);
> +		gen = addr + (sizeof(u32) * num_pages);
>  		*gen = trans->transid;
>  		kunmap(page);
> -		ClearPageChecked(page);
> -		set_page_extent_mapped(page);
> -		SetPageUptodate(page);
> -		set_page_dirty(page);
> -		unlock_page(page);
> -		page_cache_release(page);
> -		page_cache_release(page);
>  	}
> -	BTRFS_I(inode)->generation = trans->transid;
> 
> +	ret = btrfs_dirty_pages(root, inode, pages, num_pages, 0,
> +					    bytes, &cached_state);
> +	btrfs_drop_pages(pages, num_pages);
>  	unlock_extent_cached(&BTRFS_I(inode)->io_tree, 0,
>  			     i_size_read(inode) - 1, &cached_state, GFP_NOFS);
> 
> +	if (ret) {
> +		ret = 0;
> +		goto out_free;
> +	}
> +
> +	BTRFS_I(inode)->generation = trans->transid;
> +
>  	filemap_write_and_wait(inode->i_mapping);
> 
>  	key.objectid = BTRFS_FREE_SPACE_OBJECTID;
> @@ -853,6 +845,7 @@ out_free:
>  		BTRFS_I(inode)->generation = 0;
>  	}
>  	kfree(checksums);
> +	kfree(pages);
>  	btrfs_update_inode(trans, root, inode);
>  	iput(inode);
>  	return ret;

After testing the last hours without any oops; i think it's really fixed now. 
It also seems to fix the ENOSPC-bug I've reported some time ago:
http://marc.info/?l=linux-btrfs&m=129120932813085&w=2
Feel free to add my:
Tested-by Johannes Hirte <johannes.hirte@fem.tu-ilmenau.de>

regards,
  Johannes

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: BUG: unable to handle kernel NULL pointer dereference at (null)
  2011-04-06 20:47                       ` Jordan Patterson
  2011-04-06 23:42                         ` Johannes Hirte
@ 2011-04-07 13:17                         ` Josef Bacik
       [not found]                           ` <BANLkTin1MN-QZWGvVE4o0T1_U9B1qtunig@mail.gmail.com>
  1 sibling, 1 reply; 16+ messages in thread
From: Josef Bacik @ 2011-04-07 13:17 UTC (permalink / raw)
  To: Jordan Patterson; +Cc: Josef Bacik, linux-btrfs

On Wed, Apr 06, 2011 at 02:47:28PM -0600, Jordan Patterson wrote:
> Hi Josef:
> 
> I tried your latest patch, since I had the same issue from the first
> email.  With the patch applied, I am now hitting the
> BUG_ON(block_group->total_bitmaps >= max_bitmaps); in add_new_bitmap
> in
> fs/btrfs/free-space-cache.c:1246 as soon as I mount the filesystem,
> with or without -o clear_cache.
> 
> It works fine in 2.6.38.  I get the same error after mounting with
> clear_cache under 2.6.38 and rebooting into the current kernel with
> your patch.
> 

Do you have a backtrace so I can see how we're getting here?  This is a seperate
issue from the one this patch tries to solve, but now that it seems that's fixed
I will work on this now :).  Thanks,

Josef

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: BUG: unable to handle kernel NULL pointer dereference at (null)
       [not found]                           ` <BANLkTin1MN-QZWGvVE4o0T1_U9B1qtunig@mail.gmail.com>
@ 2011-04-07 15:44                             ` Jordan Patterson
  0 siblings, 0 replies; 16+ messages in thread
From: Jordan Patterson @ 2011-04-07 15:44 UTC (permalink / raw)
  To: linux-btrfs

On Thu, Apr 7, 2011 at 9:44 AM, Jordan Patterson <jordanp@gmail.com> wr=
ote:
> On Thu, Apr 7, 2011 at 7:17 AM, Josef Bacik <josef@redhat.com> wrote:
>> On Wed, Apr 06, 2011 at 02:47:28PM -0600, Jordan Patterson wrote:
>>> Hi Josef:
>>>
>>> I tried your latest patch, since I had the same issue from the firs=
t
>>> email. =A0With the patch applied, I am now hitting the
>>> BUG_ON(block_group->total_bitmaps >=3D max_bitmaps); in add_new_bit=
map
>>> in
>>> fs/btrfs/free-space-cache.c:1246 as soon as I mount the filesystem,
>>> with or without -o clear_cache.
>>>
>>> It works fine in 2.6.38. =A0I get the same error after mounting wit=
h
>>> clear_cache under 2.6.38 and rebooting into the current kernel with
>>> your patch.
>>>
>>
>> Do you have a backtrace so I can see how we're getting here? =A0This=
 is a seperate
>> issue from the one this patch tries to solve, but now that it seems =
that's fixed
>> I will work on this now :). =A0Thanks,
>>
>> Josef
>>
>
> I wasn't able to test until now, but Johannes' suggestion may have
> fixed the issue for me. =A0I added clear_cache to my rootflags in gru=
b,
> and it is now mounted fine with the current btrfs code with your last
> patch. =A0I don't have the backtrace, but I'll send it to you it if I
> see it happen again.
>
> Thanks.
>
> Jordan
>
--
To unsubscribe from this list: send the line "unsubscribe linux-btrfs" =
in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 16+ messages in thread

end of thread, other threads:[~2011-04-07 15:44 UTC | newest]

Thread overview: 16+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-04-05 17:38 BUG: unable to handle kernel NULL pointer dereference at (null) Johannes Hirte
2011-04-05 17:42 ` Josef Bacik
2011-04-05 18:52   ` Johannes Hirte
2011-04-05 18:53     ` Josef Bacik
2011-04-05 19:21       ` Johannes Hirte
2011-04-05 19:31         ` Josef Bacik
     [not found]           ` <201104052308.53816.johannes.hirte@fem.tu-ilmenau.de>
2011-04-05 21:12             ` Josef Bacik
2011-04-05 22:00               ` Johannes Hirte
2011-04-05 21:57                 ` Josef Bacik
2011-04-06 11:10                   ` Johannes Hirte
2011-04-06 17:15                     ` Josef Bacik
2011-04-06 20:47                       ` Jordan Patterson
2011-04-06 23:42                         ` Johannes Hirte
2011-04-07 13:17                         ` Josef Bacik
     [not found]                           ` <BANLkTin1MN-QZWGvVE4o0T1_U9B1qtunig@mail.gmail.com>
2011-04-07 15:44                             ` Jordan Patterson
2011-04-07  8:28                       ` Johannes Hirte

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).