Skip to content

Commit f68cad0

Browse files
chrismason-xxDavid Woodhouse
authored andcommitted
Btrfs: fixup dirty_inode related deadlocks
Signed-off-by: Chris Mason <[email protected]>
1 parent c62a192 commit f68cad0

File tree

1 file changed

+56
-53
lines changed

1 file changed

+56
-53
lines changed

fs/btrfs/super.c

Lines changed: 56 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,58 @@ static void btrfs_read_locked_inode(struct inode *inode)
120120
make_bad_inode(inode);
121121
}
122122

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+
123175
static int btrfs_unlink_trans(struct btrfs_trans_handle *trans,
124176
struct btrfs_root *root,
125177
struct inode *dir,
@@ -166,10 +218,11 @@ static int btrfs_unlink_trans(struct btrfs_trans_handle *trans,
166218
dentry->d_inode->i_ctime = dir->i_ctime;
167219
err:
168220
btrfs_free_path(path);
169-
if (ret == 0) {
170-
inode_dec_link_count(dentry->d_inode);
221+
if (!ret) {
171222
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);
173226
}
174227
return ret;
175228
}
@@ -668,56 +721,6 @@ static int btrfs_fill_super(struct super_block * sb, void * data, int silent)
668721
return 0;
669722
}
670723

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-
721724
static int btrfs_write_inode(struct inode *inode, int wait)
722725
{
723726
struct btrfs_root *root = BTRFS_I(inode)->root;

0 commit comments

Comments
 (0)