summaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorChris Mason <chris.mason@oracle.com>2007-04-24 18:44:26 +0200
committerDavid Woodhouse <dwmw2@hera.kernel.org>2007-04-24 18:44:26 +0200
commitf68cad0f9eb3c3cc100635bd0ea191ee093cf887 (patch)
tree081f6eeaff6e03ca2d002d49822fdac10e517875 /fs
parentBtrfs: get rid of the extent_item type field (diff)
downloadlinux-f68cad0f9eb3c3cc100635bd0ea191ee093cf887.tar.xz
linux-f68cad0f9eb3c3cc100635bd0ea191ee093cf887.zip
Btrfs: fixup dirty_inode related deadlocks
Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs')
-rw-r--r--fs/btrfs/super.c109
1 files changed, 56 insertions, 53 deletions
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c
index c076474c8bff..5bbccbc7e3cc 100644
--- a/fs/btrfs/super.c
+++ b/fs/btrfs/super.c
@@ -120,6 +120,58 @@ make_bad:
make_bad_inode(inode);
}
+static void fill_inode_item(struct btrfs_inode_item *item,
+ struct inode *inode)
+{
+ btrfs_set_inode_uid(item, inode->i_uid);
+ btrfs_set_inode_gid(item, inode->i_gid);
+ btrfs_set_inode_size(item, inode->i_size);
+ btrfs_set_inode_mode(item, inode->i_mode);
+ btrfs_set_inode_nlink(item, inode->i_nlink);
+ btrfs_set_timespec_sec(&item->atime, inode->i_atime.tv_sec);
+ btrfs_set_timespec_nsec(&item->atime, inode->i_atime.tv_nsec);
+ btrfs_set_timespec_sec(&item->mtime, inode->i_mtime.tv_sec);
+ btrfs_set_timespec_nsec(&item->mtime, inode->i_mtime.tv_nsec);
+ btrfs_set_timespec_sec(&item->ctime, inode->i_ctime.tv_sec);
+ btrfs_set_timespec_nsec(&item->ctime, inode->i_ctime.tv_nsec);
+ btrfs_set_inode_nblocks(item, inode->i_blocks);
+ btrfs_set_inode_generation(item, inode->i_generation);
+}
+
+
+static int btrfs_update_inode(struct btrfs_trans_handle *trans,
+ struct btrfs_root *root,
+ struct inode *inode)
+{
+ struct btrfs_inode_item *inode_item;
+ struct btrfs_path *path;
+ int ret;
+
+ path = btrfs_alloc_path();
+ BUG_ON(!path);
+ btrfs_init_path(path);
+ ret = btrfs_lookup_inode(trans, root, path,
+ &BTRFS_I(inode)->location, 1);
+ if (ret) {
+ if (ret > 0)
+ ret = -ENOENT;
+ goto failed;
+ }
+
+ inode_item = btrfs_item_ptr(btrfs_buffer_leaf(path->nodes[0]),
+ path->slots[0],
+ struct btrfs_inode_item);
+
+ fill_inode_item(inode_item, inode);
+ btrfs_mark_buffer_dirty(path->nodes[0]);
+ ret = 0;
+failed:
+ btrfs_release_path(root, path);
+ btrfs_free_path(path);
+ return ret;
+}
+
+
static int btrfs_unlink_trans(struct btrfs_trans_handle *trans,
struct btrfs_root *root,
struct inode *dir,
@@ -166,10 +218,11 @@ static int btrfs_unlink_trans(struct btrfs_trans_handle *trans,
dentry->d_inode->i_ctime = dir->i_ctime;
err:
btrfs_free_path(path);
- if (ret == 0) {
- inode_dec_link_count(dentry->d_inode);
+ if (!ret) {
dir->i_size -= name_len * 2;
- mark_inode_dirty(dir);
+ btrfs_update_inode(trans, root, dir);
+ drop_nlink(dentry->d_inode);
+ btrfs_update_inode(trans, root, dentry->d_inode);
}
return ret;
}
@@ -668,56 +721,6 @@ static int btrfs_fill_super(struct super_block * sb, void * data, int silent)
return 0;
}
-static void fill_inode_item(struct btrfs_inode_item *item,
- struct inode *inode)
-{
- btrfs_set_inode_uid(item, inode->i_uid);
- btrfs_set_inode_gid(item, inode->i_gid);
- btrfs_set_inode_size(item, inode->i_size);
- btrfs_set_inode_mode(item, inode->i_mode);
- btrfs_set_inode_nlink(item, inode->i_nlink);
- btrfs_set_timespec_sec(&item->atime, inode->i_atime.tv_sec);
- btrfs_set_timespec_nsec(&item->atime, inode->i_atime.tv_nsec);
- btrfs_set_timespec_sec(&item->mtime, inode->i_mtime.tv_sec);
- btrfs_set_timespec_nsec(&item->mtime, inode->i_mtime.tv_nsec);
- btrfs_set_timespec_sec(&item->ctime, inode->i_ctime.tv_sec);
- btrfs_set_timespec_nsec(&item->ctime, inode->i_ctime.tv_nsec);
- btrfs_set_inode_nblocks(item, inode->i_blocks);
- btrfs_set_inode_generation(item, inode->i_generation);
-}
-
-static int btrfs_update_inode(struct btrfs_trans_handle *trans,
- struct btrfs_root *root,
- struct inode *inode)
-{
- struct btrfs_inode_item *inode_item;
- struct btrfs_path *path;
- int ret;
-
- path = btrfs_alloc_path();
- BUG_ON(!path);
- btrfs_init_path(path);
- ret = btrfs_lookup_inode(trans, root, path,
- &BTRFS_I(inode)->location, 1);
- if (ret) {
- if (ret > 0)
- ret = -ENOENT;
- goto failed;
- }
-
- inode_item = btrfs_item_ptr(btrfs_buffer_leaf(path->nodes[0]),
- path->slots[0],
- struct btrfs_inode_item);
-
- fill_inode_item(inode_item, inode);
- btrfs_mark_buffer_dirty(path->nodes[0]);
- ret = 0;
-failed:
- btrfs_release_path(root, path);
- btrfs_free_path(path);
- return ret;
-}
-
static int btrfs_write_inode(struct inode *inode, int wait)
{
struct btrfs_root *root = BTRFS_I(inode)->root;