diff options
author | Chris Mason <chris.mason@oracle.com> | 2007-04-24 12:44:26 -0400 |
---|---|---|
committer | David Woodhouse <dwmw2@hera.kernel.org> | 2007-04-24 12:44:26 -0400 |
commit | f68cad0f9eb3c3cc100635bd0ea191ee093cf887 (patch) | |
tree | 081f6eeaff6e03ca2d002d49822fdac10e517875 /fs/btrfs | |
parent | c62a1920ced752e86f57ab1d4ad0ec65012bce4d (diff) |
Btrfs: fixup dirty_inode related deadlocks
Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs')
-rw-r--r-- | fs/btrfs/super.c | 109 |
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: | |||
120 | make_bad_inode(inode); | 120 | make_bad_inode(inode); |
121 | } | 121 | } |
122 | 122 | ||
123 | static void fill_inode_item(struct btrfs_inode_item *item, | ||
124 | struct inode *inode) | ||
125 | { | ||
126 | btrfs_set_inode_uid(item, inode->i_uid); | ||
127 | btrfs_set_inode_gid(item, inode->i_gid); | ||
128 | btrfs_set_inode_size(item, inode->i_size); | ||
129 | btrfs_set_inode_mode(item, inode->i_mode); | ||
130 | btrfs_set_inode_nlink(item, inode->i_nlink); | ||
131 | btrfs_set_timespec_sec(&item->atime, inode->i_atime.tv_sec); | ||
132 | btrfs_set_timespec_nsec(&item->atime, inode->i_atime.tv_nsec); | ||
133 | btrfs_set_timespec_sec(&item->mtime, inode->i_mtime.tv_sec); | ||
134 | btrfs_set_timespec_nsec(&item->mtime, inode->i_mtime.tv_nsec); | ||
135 | btrfs_set_timespec_sec(&item->ctime, inode->i_ctime.tv_sec); | ||
136 | btrfs_set_timespec_nsec(&item->ctime, inode->i_ctime.tv_nsec); | ||
137 | btrfs_set_inode_nblocks(item, inode->i_blocks); | ||
138 | btrfs_set_inode_generation(item, inode->i_generation); | ||
139 | } | ||
140 | |||
141 | |||
142 | static int btrfs_update_inode(struct btrfs_trans_handle *trans, | ||
143 | struct btrfs_root *root, | ||
144 | struct inode *inode) | ||
145 | { | ||
146 | struct btrfs_inode_item *inode_item; | ||
147 | struct btrfs_path *path; | ||
148 | int ret; | ||
149 | |||
150 | path = btrfs_alloc_path(); | ||
151 | BUG_ON(!path); | ||
152 | btrfs_init_path(path); | ||
153 | ret = btrfs_lookup_inode(trans, root, path, | ||
154 | &BTRFS_I(inode)->location, 1); | ||
155 | if (ret) { | ||
156 | if (ret > 0) | ||
157 | ret = -ENOENT; | ||
158 | goto failed; | ||
159 | } | ||
160 | |||
161 | inode_item = btrfs_item_ptr(btrfs_buffer_leaf(path->nodes[0]), | ||
162 | path->slots[0], | ||
163 | struct btrfs_inode_item); | ||
164 | |||
165 | fill_inode_item(inode_item, inode); | ||
166 | btrfs_mark_buffer_dirty(path->nodes[0]); | ||
167 | ret = 0; | ||
168 | failed: | ||
169 | btrfs_release_path(root, path); | ||
170 | btrfs_free_path(path); | ||
171 | return ret; | ||
172 | } | ||
173 | |||
174 | |||
123 | static int btrfs_unlink_trans(struct btrfs_trans_handle *trans, | 175 | static int btrfs_unlink_trans(struct btrfs_trans_handle *trans, |
124 | struct btrfs_root *root, | 176 | struct btrfs_root *root, |
125 | struct inode *dir, | 177 | struct inode *dir, |
@@ -166,10 +218,11 @@ static int btrfs_unlink_trans(struct btrfs_trans_handle *trans, | |||
166 | dentry->d_inode->i_ctime = dir->i_ctime; | 218 | dentry->d_inode->i_ctime = dir->i_ctime; |
167 | err: | 219 | err: |
168 | btrfs_free_path(path); | 220 | btrfs_free_path(path); |
169 | if (ret == 0) { | 221 | if (!ret) { |
170 | inode_dec_link_count(dentry->d_inode); | ||
171 | dir->i_size -= name_len * 2; | 222 | dir->i_size -= name_len * 2; |
172 | mark_inode_dirty(dir); | 223 | btrfs_update_inode(trans, root, dir); |
224 | drop_nlink(dentry->d_inode); | ||
225 | btrfs_update_inode(trans, root, dentry->d_inode); | ||
173 | } | 226 | } |
174 | return ret; | 227 | return ret; |
175 | } | 228 | } |
@@ -668,56 +721,6 @@ static int btrfs_fill_super(struct super_block * sb, void * data, int silent) | |||
668 | return 0; | 721 | return 0; |
669 | } | 722 | } |
670 | 723 | ||
671 | static void fill_inode_item(struct btrfs_inode_item *item, | ||
672 | struct inode *inode) | ||
673 | { | ||
674 | btrfs_set_inode_uid(item, inode->i_uid); | ||
675 | btrfs_set_inode_gid(item, inode->i_gid); | ||
676 | btrfs_set_inode_size(item, inode->i_size); | ||
677 | btrfs_set_inode_mode(item, inode->i_mode); | ||
678 | btrfs_set_inode_nlink(item, inode->i_nlink); | ||
679 | btrfs_set_timespec_sec(&item->atime, inode->i_atime.tv_sec); | ||
680 | btrfs_set_timespec_nsec(&item->atime, inode->i_atime.tv_nsec); | ||
681 | btrfs_set_timespec_sec(&item->mtime, inode->i_mtime.tv_sec); | ||
682 | btrfs_set_timespec_nsec(&item->mtime, inode->i_mtime.tv_nsec); | ||
683 | btrfs_set_timespec_sec(&item->ctime, inode->i_ctime.tv_sec); | ||
684 | btrfs_set_timespec_nsec(&item->ctime, inode->i_ctime.tv_nsec); | ||
685 | btrfs_set_inode_nblocks(item, inode->i_blocks); | ||
686 | btrfs_set_inode_generation(item, inode->i_generation); | ||
687 | } | ||
688 | |||
689 | static int btrfs_update_inode(struct btrfs_trans_handle *trans, | ||
690 | struct btrfs_root *root, | ||
691 | struct inode *inode) | ||
692 | { | ||
693 | struct btrfs_inode_item *inode_item; | ||
694 | struct btrfs_path *path; | ||
695 | int ret; | ||
696 | |||
697 | path = btrfs_alloc_path(); | ||
698 | BUG_ON(!path); | ||
699 | btrfs_init_path(path); | ||
700 | ret = btrfs_lookup_inode(trans, root, path, | ||
701 | &BTRFS_I(inode)->location, 1); | ||
702 | if (ret) { | ||
703 | if (ret > 0) | ||
704 | ret = -ENOENT; | ||
705 | goto failed; | ||
706 | } | ||
707 | |||
708 | inode_item = btrfs_item_ptr(btrfs_buffer_leaf(path->nodes[0]), | ||
709 | path->slots[0], | ||
710 | struct btrfs_inode_item); | ||
711 | |||
712 | fill_inode_item(inode_item, inode); | ||
713 | btrfs_mark_buffer_dirty(path->nodes[0]); | ||
714 | ret = 0; | ||
715 | failed: | ||
716 | btrfs_release_path(root, path); | ||
717 | btrfs_free_path(path); | ||
718 | return ret; | ||
719 | } | ||
720 | |||
721 | static int btrfs_write_inode(struct inode *inode, int wait) | 724 | static int btrfs_write_inode(struct inode *inode, int wait) |
722 | { | 725 | { |
723 | struct btrfs_root *root = BTRFS_I(inode)->root; | 726 | struct btrfs_root *root = BTRFS_I(inode)->root; |