All of lore.kernel.org
 help / color / mirror / Atom feed
* system crash at mounting of btrfs
@ 2010-10-07 14:12 Gerhard Kulzer
  2010-10-08  6:32 ` Gerhard Kulzer
  2010-10-08 17:16 ` Chris Mason
  0 siblings, 2 replies; 16+ messages in thread
From: Gerhard Kulzer @ 2010-10-07 14:12 UTC (permalink / raw)
  To: linux-btrfs

I have a weird problem concerning 5 btrfs partitions on 3 different disks:
My system became slow and started to hang and go, so I shut it down and it 
hang totally whilst shutting down. With the sysrq shortcut I could kill it 
and restart.

Booting didn't work any more throwing me into a shell at initramfs.

I booted from a CD and tried to mount the first btrfs partition, the system hung
up after about 1 sec, just throwing "killed" to the shell.
I tried (after reboot) to mount the 4 other partitions which are on different
disks: the failure is always the same. I also tried mount options as "degraded",
"read-only" w/o success. But btrfsck works flawless, also btrfsctl -A, no
crashes. Any other partition on the same disk like ext4 mount perfectly.
I tried it with 3 kernels from the 2.5.35 series.
My system is a AMD64, so I put one SSD disk as an external drive (USB) to a
laptop running a 32bit system, it crashed the same at my wanting to mount the
partition.

This is my config:
$uname -a
Linux ubuntu 2.6.35-22-generic #33-Ubuntu SMP Sun Sep 19 20:34:50 UTC 2010 i686
GNU/Linux

Here is a dmesg trace during booting from the CD, it not the crash yet.

[    7.782823] Btrfs loaded
[    7.786081] xor: automatically using best checksumming function: pIII_sse
[    7.804000]    pIII_sse  : 11626.000 MB/sec
[    7.804001] xor: using function: pIII_sse (11626.000 MB/sec)
[    7.805746] device-mapper: dm-raid45: initialized v0.2594b
[    7.851186] device fsid 3a4b4bc6c07de70b-2b32b3df70d2459f devid 1 transid
407064 /dev/sda2
[    7.881078] Btrfs detected SSD devices, enabling SSD mode
[    7.923553] ------------[ cut here ]------------
[    7.923556] kernel BUG at /build/buildd/linux-2.6.35/fs/btrfs/tree-log.c:813!
[    7.923558] invalid opcode: 0000 [#1] SMP 
[    7.923561] last sysfs file: /sys/devices/virtual/bdi/btrfs-1/uevent
[    7.923562] Modules linked in: dm_raid45 xor btrfs zlib_deflate crc32c
libcrc32c nouveau ttm drm_kms_helper usbhid hid usb_storage drm sky2
firewire_ohci firewire_core intel_agp crc_itu_t ahci pata_jmicron libahci
agpgart i2c_algo_bit
[    7.923577] 
[    7.923579] Pid: 453, comm: exe Not tainted 2.6.35-22-generic #33-Ubuntu
P5K-E/P5K-E
[    7.923582] EIP: 0060:[<f9c44024>] EFLAGS: 00010246 CPU: 0
[    7.923590] EIP is at add_inode_ref+0x3f4/0x410 [btrfs]
[    7.923592] EAX: 00000000 EBX: 00000097 ECX: 00000000 EDX: 00000274
[    7.923594] ESI: 00000002 EDI: f6fe8af0 EBP: c1257c30 ESP: c1257bd4
[    7.923596]  DS: 007b ES: 007b FS: 00d8 GS: 00e0 SS: 0068
[    7.923598] Process exe (pid: 453, ti=c1256000 task=f6a30000 task.ti=c1256000)
[    7.923599] Stack:
[    7.923600]  c1257be8 c1257be8 c0132ba6 f6fe8af0 00000011 c1257bf0 f9c2d2c1
c1257c30
[    7.923605] <0> f9c21d37 c1257c20 00000000 f6f9b000 f643887c 00000004
00000000 f6fe8af0
[    7.923610] <0> f68e6000 f7156000 fffb6000 fffb6000 00000097 00000002
f6fe8af0 c1257c94
[    7.923615] Call Trace:
[    7.923620]  [<c0132ba6>] ? kunmap_atomic+0x66/0x80
[    7.923628]  [<f9c2d2c1>] ? unmap_extent_buffer+0x11/0x20 [btrfs]
[    7.923637]  [<f9c21d37>] ? btrfs_item_size+0xc7/0xd0 [btrfs]
[    7.923644]  [<f9c45a46>] ? replay_one_buffer+0x246/0x320 [btrfs]
[    7.923651]  [<f9c423a9>] ? walk_down_log_tree+0x219/0x3b0 [btrfs]
[    7.923658]  [<f9c425e9>] ? walk_log_tree+0xa9/0x1d0 [btrfs]
[    7.923665]  [<f9c44d94>] ? btrfs_recover_log_trees+0x1d4/0x2b0 [btrfs]
[    7.923672]  [<f9c45800>] ? replay_one_buffer+0x0/0x320 [btrfs]
[    7.923680]  [<f9c0d07c>] ? open_ctree+0x101c/0x14c0 [btrfs]
[    7.923686]  [<f9bee672>] ? btrfs_fill_super+0x52/0x110 [btrfs]
[    7.923690]  [<c0356069>] ? strlcpy+0x39/0x50
[    7.923695]  [<f9beebbd>] ? btrfs_get_sb+0x24d/0x2d0 [btrfs]
[    7.923699]  [<c020f66f>] ? __alloc_percpu+0xf/0x20
[    7.923701]  [<c0231109>] ? alloc_vfsmnt+0xf9/0x130
[    7.923704]  [<c021aee4>] ? vfs_kern_mount+0x74/0x1c0
[    7.923707]  [<c022f493>] ? get_fs_type+0x33/0xb0
[    7.923709]  [<c021b08e>] ? do_kern_mount+0x3e/0xe0
[    7.923711]  [<c023260c>] ? do_mount+0x1dc/0x220
[    7.923714]  [<c02326bb>] ? sys_mount+0x6b/0xa0
[    7.923717]  [<c05c90a4>] ? syscall_call+0x7/0xb
[    7.923718] Code: e8 42 b3 fa ff 8b 45 d4 e8 5a 87 5e c6 8b 45 cc e8 52 87 5e
c6 31 c0 83 c4 50 5b 5e 5f 5d c3 0f 0b eb fe 0f 0b eb fe 0f 0b eb fe <0f> 0b eb
fe 0f 0b eb fe 0f 0b eb fe 0f 0b eb fe 8d b6 00 00 00 
[    7.923746] EIP: [<f9c44024>] add_inode_ref+0x3f4/0x410 [btrfs] SS:ESP
0068:c1257bd4
[    7.923755] ---[ end trace 2b634c981d89a441 ]---

Any help how to get my data off those disk is seriously appreciated.


^ permalink raw reply	[flat|nested] 16+ messages in thread
* Re: system crash at mounting of btrfs
@ 2010-10-08  6:43 Tomasz Chmielewski
  2010-10-08 16:49 ` Gerhard Kulzer
  0 siblings, 1 reply; 16+ messages in thread
From: Tomasz Chmielewski @ 2010-10-08  6:43 UTC (permalink / raw)
  To: linux-btrfs

> I tried it with 3 kernels from the 2.5.35 series.
> My system is a AMD64, so I put one SSD disk as an external drive (USB) to a
> laptop running a 32bit system, it crashed the same at my wanting to mount the
> partition.
>
> This is my config:
> $uname -a
> Linux ubuntu 2.6.35-22-generic #33-Ubuntu SMP Sun Sep 19 20:34:50 UTC 2010 i686
> GNU/Linux

You could try:

http://kernel.ubuntu.com/~kernel-ppa/mainline/v2.6.36-rc7-maverick/


-- 
Tomasz Chmielewski
http://wpkg.org


^ permalink raw reply	[flat|nested] 16+ messages in thread
* [PATCH] Btrfs: fix dentry->d_parent abuses
@ 2010-10-27 14:39 Josef Bacik
  2010-10-27 14:53 ` system crash at mounting of btrfs Erik Hoppe
  0 siblings, 1 reply; 16+ messages in thread
From: Josef Bacik @ 2010-10-27 14:39 UTC (permalink / raw)
  To: linux-btrfs

There are lots of places where we do dentry->d_parent->d_inode without holding
the dentry->d_lock.  This could cause problems with rename.  So instead use
dget_parent where we can, or in some cases we don't even need to use
dentry->d_parent->d_inode since we get the inode of the dir passed to us from
VFS.  I tested this with xfstests and my no space tests and everything turned
out fine.  Thanks,

Signed-off-by: Josef Bacik <josef@redhat.com>
---
 fs/btrfs/file.c        |    2 ++
 fs/btrfs/inode.c       |   48 ++++++++++++++++++++++++------------------------
 fs/btrfs/ioctl.c       |   11 +++++++++--
 fs/btrfs/transaction.c |    5 ++++-
 fs/btrfs/tree-log.c    |   22 ++++++++++++++++++----
 5 files changed, 57 insertions(+), 31 deletions(-)

diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c
index e354c33..6a4daa0 100644
--- a/fs/btrfs/file.c
+++ b/fs/btrfs/file.c
@@ -1047,8 +1047,10 @@ out:
 
 		if ((file->f_flags & O_DSYNC) || IS_SYNC(inode)) {
 			trans = btrfs_start_transaction(root, 0);
+			mutex_lock(&inode->i_mutex);
 			ret = btrfs_log_dentry_safe(trans, root,
 						    file->f_dentry);
+			mutex_unlock(&inode->i_mutex);
 			if (ret == 0) {
 				ret = btrfs_sync_log(trans, root);
 				if (ret == 0)
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index 7146971..e77ee56 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -4144,6 +4144,7 @@ static int btrfs_dentry_delete(struct dentry *dentry)
 		if (btrfs_root_refs(&root->root_item) == 0)
 			return 1;
 	}
+
 	return 0;
 }
 
@@ -4627,12 +4628,12 @@ int btrfs_add_link(struct btrfs_trans_handle *trans,
 }
 
 static int btrfs_add_nondir(struct btrfs_trans_handle *trans,
-			    struct dentry *dentry, struct inode *inode,
-			    int backref, u64 index)
+			    struct inode *dir, struct dentry *dentry,
+			    struct inode *inode, int backref, u64 index)
 {
-	int err = btrfs_add_link(trans, dentry->d_parent->d_inode,
-				 inode, dentry->d_name.name,
-				 dentry->d_name.len, backref, index);
+	int err = btrfs_add_link(trans, dir, inode,
+				 dentry->d_name.name, dentry->d_name.len,
+				 backref, index);
 	if (!err) {
 		d_instantiate(dentry, inode);
 		return 0;
@@ -4673,8 +4674,7 @@ static int btrfs_mknod(struct inode *dir, struct dentry *dentry,
 	btrfs_set_trans_block_group(trans, dir);
 
 	inode = btrfs_new_inode(trans, root, dir, dentry->d_name.name,
-				dentry->d_name.len,
-				dentry->d_parent->d_inode->i_ino, objectid,
+				dentry->d_name.len, dir->i_ino, objectid,
 				BTRFS_I(dir)->block_group, mode, &index);
 	err = PTR_ERR(inode);
 	if (IS_ERR(inode))
@@ -4687,7 +4687,7 @@ static int btrfs_mknod(struct inode *dir, struct dentry *dentry,
 	}
 
 	btrfs_set_trans_block_group(trans, inode);
-	err = btrfs_add_nondir(trans, dentry, inode, 0, index);
+	err = btrfs_add_nondir(trans, dir, dentry, inode, 0, index);
 	if (err)
 		drop_inode = 1;
 	else {
@@ -4735,10 +4735,8 @@ static int btrfs_create(struct inode *dir, struct dentry *dentry,
 	btrfs_set_trans_block_group(trans, dir);
 
 	inode = btrfs_new_inode(trans, root, dir, dentry->d_name.name,
-				dentry->d_name.len,
-				dentry->d_parent->d_inode->i_ino,
-				objectid, BTRFS_I(dir)->block_group, mode,
-				&index);
+				dentry->d_name.len, dir->i_ino, objectid,
+				BTRFS_I(dir)->block_group, mode, &index);
 	err = PTR_ERR(inode);
 	if (IS_ERR(inode))
 		goto out_unlock;
@@ -4750,7 +4748,7 @@ static int btrfs_create(struct inode *dir, struct dentry *dentry,
 	}
 
 	btrfs_set_trans_block_group(trans, inode);
-	err = btrfs_add_nondir(trans, dentry, inode, 0, index);
+	err = btrfs_add_nondir(trans, dir, dentry, inode, 0, index);
 	if (err)
 		drop_inode = 1;
 	else {
@@ -4810,15 +4808,17 @@ static int btrfs_link(struct dentry *old_dentry, struct inode *dir,
 	btrfs_set_trans_block_group(trans, dir);
 	atomic_inc(&inode->i_count);
 
-	err = btrfs_add_nondir(trans, dentry, inode, 1, index);
+	err = btrfs_add_nondir(trans, dir, dentry, inode, 1, index);
 
 	if (err) {
 		drop_inode = 1;
 	} else {
+		struct dentry *parent = dget_parent(dentry);
 		btrfs_update_inode_block_group(trans, dir);
 		err = btrfs_update_inode(trans, root, inode);
 		BUG_ON(err);
-		btrfs_log_new_name(trans, inode, NULL, dentry->d_parent);
+		btrfs_log_new_name(trans, inode, NULL, parent);
+		dput(parent);
 	}
 
 	nr = trans->blocks_used;
@@ -4858,8 +4858,7 @@ static int btrfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
 	btrfs_set_trans_block_group(trans, dir);
 
 	inode = btrfs_new_inode(trans, root, dir, dentry->d_name.name,
-				dentry->d_name.len,
-				dentry->d_parent->d_inode->i_ino, objectid,
+				dentry->d_name.len, dir->i_ino, objectid,
 				BTRFS_I(dir)->block_group, S_IFDIR | mode,
 				&index);
 	if (IS_ERR(inode)) {
@@ -4882,9 +4881,8 @@ static int btrfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
 	if (err)
 		goto out_fail;
 
-	err = btrfs_add_link(trans, dentry->d_parent->d_inode,
-				 inode, dentry->d_name.name,
-				 dentry->d_name.len, 0, index);
+	err = btrfs_add_link(trans, dir, inode, dentry->d_name.name,
+			     dentry->d_name.len, 0, index);
 	if (err)
 		goto out_fail;
 
@@ -6613,8 +6611,11 @@ static int btrfs_rename(struct inode *old_dir, struct dentry *old_dentry,
 	BUG_ON(ret);
 
 	if (old_inode->i_ino != BTRFS_FIRST_FREE_OBJECTID) {
+		struct dentry *parent = dget_parent(new_dentry);
+
 		btrfs_log_new_name(trans, old_inode, old_dir,
-				   new_dentry->d_parent);
+				   parent);
+		dput(parent);
 		btrfs_end_log_trans(root);
 	}
 out_fail:
@@ -6764,8 +6765,7 @@ static int btrfs_symlink(struct inode *dir, struct dentry *dentry,
 	btrfs_set_trans_block_group(trans, dir);
 
 	inode = btrfs_new_inode(trans, root, dir, dentry->d_name.name,
-				dentry->d_name.len,
-				dentry->d_parent->d_inode->i_ino, objectid,
+				dentry->d_name.len, dir->i_ino, objectid,
 				BTRFS_I(dir)->block_group, S_IFLNK|S_IRWXUGO,
 				&index);
 	err = PTR_ERR(inode);
@@ -6779,7 +6779,7 @@ static int btrfs_symlink(struct inode *dir, struct dentry *dentry,
 	}
 
 	btrfs_set_trans_block_group(trans, inode);
-	err = btrfs_add_nondir(trans, dentry, inode, 0, index);
+	err = btrfs_add_nondir(trans, dir, dentry, inode, 0, index);
 	if (err)
 		drop_inode = 1;
 	else {
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
index e264072..396ccd1 100644
--- a/fs/btrfs/ioctl.c
+++ b/fs/btrfs/ioctl.c
@@ -232,13 +232,17 @@ static noinline int create_subvol(struct btrfs_root *root,
 	struct btrfs_inode_item *inode_item;
 	struct extent_buffer *leaf;
 	struct btrfs_root *new_root;
-	struct inode *dir = dentry->d_parent->d_inode;
+	struct dentry *parent = dget_parent(dentry);
+	struct inode *dir;
 	int ret;
 	int err;
 	u64 objectid;
 	u64 new_dirid = BTRFS_FIRST_FREE_OBJECTID;
 	u64 index = 0;
 
+	dir = parent->d_inode;
+	dput(parent);
+
 	ret = btrfs_find_free_objectid(NULL, root->fs_info->tree_root,
 				       0, &objectid);
 	if (ret)
@@ -347,6 +351,7 @@ fail:
 static int create_snapshot(struct btrfs_root *root, struct dentry *dentry)
 {
 	struct inode *inode;
+	struct dentry *parent;
 	struct btrfs_pending_snapshot *pending_snapshot;
 	struct btrfs_trans_handle *trans;
 	int ret;
@@ -382,7 +387,9 @@ static int create_snapshot(struct btrfs_root *root, struct dentry *dentry)
 
 	btrfs_orphan_cleanup(pending_snapshot->snap);
 
-	inode = btrfs_lookup_dentry(dentry->d_parent->d_inode, dentry);
+	parent = dget_parent(dentry);
+	inode = btrfs_lookup_dentry(parent->d_inode, dentry);
+	dput(parent);
 	if (IS_ERR(inode)) {
 		ret = PTR_ERR(inode);
 		goto fail;
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c
index 0af647c..076729e 100644
--- a/fs/btrfs/transaction.c
+++ b/fs/btrfs/transaction.c
@@ -849,6 +849,7 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans,
 	struct btrfs_root *root = pending->root;
 	struct btrfs_root *parent_root;
 	struct inode *parent_inode;
+	struct dentry *parent_dentry;
 	struct dentry *dentry;
 	struct extent_buffer *tmp;
 	struct extent_buffer *old;
@@ -888,7 +889,9 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans,
 	trans->block_rsv = &pending->block_rsv;
 
 	dentry = pending->dentry;
-	parent_inode = dentry->d_parent->d_inode;
+	parent_dentry = dget_parent(dentry);
+	parent_inode = parent_dentry->d_inode;
+	dput(parent_dentry);
 	parent_root = BTRFS_I(parent_inode)->root;
 	record_root_in_trans(trans, parent_root);
 
diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c
index fb102a9..bf01bdb 100644
--- a/fs/btrfs/tree-log.c
+++ b/fs/btrfs/tree-log.c
@@ -2884,6 +2884,7 @@ static noinline int check_parent_dirs_for_sync(struct btrfs_trans_handle *trans,
 {
 	int ret = 0;
 	struct btrfs_root *root;
+	struct dentry *old_parent = NULL;
 
 	/*
 	 * for regular files, if its inode is already on disk, we don't
@@ -2925,10 +2926,13 @@ static noinline int check_parent_dirs_for_sync(struct btrfs_trans_handle *trans,
 		if (IS_ROOT(parent))
 			break;
 
-		parent = parent->d_parent;
+		parent = dget_parent(parent);
+		dput(old_parent);
+		old_parent = parent;
 		inode = parent->d_inode;
 
 	}
+	dput(old_parent);
 out:
 	return ret;
 }
@@ -2960,6 +2964,7 @@ int btrfs_log_inode_parent(struct btrfs_trans_handle *trans,
 {
 	int inode_only = exists_only ? LOG_INODE_EXISTS : LOG_INODE_ALL;
 	struct super_block *sb;
+	struct dentry *old_parent = NULL;
 	int ret = 0;
 	u64 last_committed = root->fs_info->last_trans_committed;
 
@@ -3031,10 +3036,13 @@ int btrfs_log_inode_parent(struct btrfs_trans_handle *trans,
 		if (IS_ROOT(parent))
 			break;
 
-		parent = parent->d_parent;
+		parent = dget_parent(parent);
+		dput(old_parent);
+		old_parent = parent;
 	}
 	ret = 0;
 end_trans:
+	dput(old_parent);
 	if (ret < 0) {
 		BUG_ON(ret != -ENOSPC);
 		root->fs_info->last_trans_log_full_commit = trans->transid;
@@ -3054,8 +3062,14 @@ end_no_trans:
 int btrfs_log_dentry_safe(struct btrfs_trans_handle *trans,
 			  struct btrfs_root *root, struct dentry *dentry)
 {
-	return btrfs_log_inode_parent(trans, root, dentry->d_inode,
-				      dentry->d_parent, 0);
+	struct dentry *parent = dget_parent(dentry);
+	int ret;
+
+	ret = btrfs_log_inode_parent(trans, root, dentry->d_inode, parent, 0);
+
+	dput(parent);
+
+	return ret;
 }
 
 /*
-- 
1.6.6.1


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

end of thread, other threads:[~2010-10-27 14:53 UTC | newest]

Thread overview: 16+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-10-07 14:12 system crash at mounting of btrfs Gerhard Kulzer
2010-10-08  6:32 ` Gerhard Kulzer
2010-10-08 17:16 ` Chris Mason
2010-10-09  5:37   ` Gerhard Kulzer
2010-10-09 13:08     ` Gerhard Kulzer
2010-10-11 23:55       ` Chris Mason
2010-10-12  6:44         ` Gerhard Kulzer
2010-10-13  0:49           ` Chris Mason
2010-10-13  6:00             ` Francis Galiegue
2010-10-13  6:42             ` Gerhard Kulzer
2010-10-13 12:33             ` Erik Hoppe
  -- strict thread matches above, loose matches on Subject: below --
2010-10-08  6:43 Tomasz Chmielewski
2010-10-08 16:49 ` Gerhard Kulzer
2010-10-08 16:53   ` Chris Mason
2010-10-08 17:04     ` Gerhard Kulzer
2010-10-27 14:39 [PATCH] Btrfs: fix dentry->d_parent abuses Josef Bacik
2010-10-27 14:53 ` system crash at mounting of btrfs Erik Hoppe

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.