Skip to content

Commit da2f6ab

Browse files
committed
Merge branch 'for-linus-4.7-part2' of git://git.kernel.org/pub/scm/linux/kernel/git/mason/linux-btrfs
Pull btrfs fixes part 2 from Chris Mason: "This has one patch from Omar to bring iterate_shared back to btrfs. We have a tree of work we queue up for directory items and it doesn't lend itself well to shared access. While we're cleaning it up, Omar has changed things to use an exclusive lock when there are delayed items" * 'for-linus-4.7-part2' of git://git.kernel.org/pub/scm/linux/kernel/git/mason/linux-btrfs: Btrfs: fix ->iterate_shared() by upgrading i_rwsem for delayed nodes
2 parents b971712 + 02dbfc9 commit da2f6ab

3 files changed

Lines changed: 34 additions & 13 deletions

File tree

fs/btrfs/delayed-inode.c

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1606,15 +1606,23 @@ int btrfs_inode_delayed_dir_index_count(struct inode *inode)
16061606
return 0;
16071607
}
16081608

1609-
void btrfs_get_delayed_items(struct inode *inode, struct list_head *ins_list,
1610-
struct list_head *del_list)
1609+
bool btrfs_readdir_get_delayed_items(struct inode *inode,
1610+
struct list_head *ins_list,
1611+
struct list_head *del_list)
16111612
{
16121613
struct btrfs_delayed_node *delayed_node;
16131614
struct btrfs_delayed_item *item;
16141615

16151616
delayed_node = btrfs_get_delayed_node(inode);
16161617
if (!delayed_node)
1617-
return;
1618+
return false;
1619+
1620+
/*
1621+
* We can only do one readdir with delayed items at a time because of
1622+
* item->readdir_list.
1623+
*/
1624+
inode_unlock_shared(inode);
1625+
inode_lock(inode);
16181626

16191627
mutex_lock(&delayed_node->mutex);
16201628
item = __btrfs_first_delayed_insertion_item(delayed_node);
@@ -1641,10 +1649,13 @@ void btrfs_get_delayed_items(struct inode *inode, struct list_head *ins_list,
16411649
* requeue or dequeue this delayed node.
16421650
*/
16431651
atomic_dec(&delayed_node->refs);
1652+
1653+
return true;
16441654
}
16451655

1646-
void btrfs_put_delayed_items(struct list_head *ins_list,
1647-
struct list_head *del_list)
1656+
void btrfs_readdir_put_delayed_items(struct inode *inode,
1657+
struct list_head *ins_list,
1658+
struct list_head *del_list)
16481659
{
16491660
struct btrfs_delayed_item *curr, *next;
16501661

@@ -1659,6 +1670,12 @@ void btrfs_put_delayed_items(struct list_head *ins_list,
16591670
if (atomic_dec_and_test(&curr->refs))
16601671
kfree(curr);
16611672
}
1673+
1674+
/*
1675+
* The VFS is going to do up_read(), so we need to downgrade back to a
1676+
* read lock.
1677+
*/
1678+
downgrade_write(&inode->i_rwsem);
16621679
}
16631680

16641681
int btrfs_should_delete_dir_index(struct list_head *del_list,

fs/btrfs/delayed-inode.h

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -137,10 +137,12 @@ void btrfs_kill_all_delayed_nodes(struct btrfs_root *root);
137137
void btrfs_destroy_delayed_inodes(struct btrfs_root *root);
138138

139139
/* Used for readdir() */
140-
void btrfs_get_delayed_items(struct inode *inode, struct list_head *ins_list,
141-
struct list_head *del_list);
142-
void btrfs_put_delayed_items(struct list_head *ins_list,
143-
struct list_head *del_list);
140+
bool btrfs_readdir_get_delayed_items(struct inode *inode,
141+
struct list_head *ins_list,
142+
struct list_head *del_list);
143+
void btrfs_readdir_put_delayed_items(struct inode *inode,
144+
struct list_head *ins_list,
145+
struct list_head *del_list);
144146
int btrfs_should_delete_dir_index(struct list_head *del_list,
145147
u64 index);
146148
int btrfs_readdir_delayed_dir_index(struct dir_context *ctx,

fs/btrfs/inode.c

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5758,6 +5758,7 @@ static int btrfs_real_readdir(struct file *file, struct dir_context *ctx)
57585758
int name_len;
57595759
int is_curr = 0; /* ctx->pos points to the current index? */
57605760
bool emitted;
5761+
bool put = false;
57615762

57625763
/* FIXME, use a real flag for deciding about the key type */
57635764
if (root->fs_info->tree_root == root)
@@ -5775,7 +5776,8 @@ static int btrfs_real_readdir(struct file *file, struct dir_context *ctx)
57755776
if (key_type == BTRFS_DIR_INDEX_KEY) {
57765777
INIT_LIST_HEAD(&ins_list);
57775778
INIT_LIST_HEAD(&del_list);
5778-
btrfs_get_delayed_items(inode, &ins_list, &del_list);
5779+
put = btrfs_readdir_get_delayed_items(inode, &ins_list,
5780+
&del_list);
57795781
}
57805782

57815783
key.type = key_type;
@@ -5922,8 +5924,8 @@ static int btrfs_real_readdir(struct file *file, struct dir_context *ctx)
59225924
nopos:
59235925
ret = 0;
59245926
err:
5925-
if (key_type == BTRFS_DIR_INDEX_KEY)
5926-
btrfs_put_delayed_items(&ins_list, &del_list);
5927+
if (put)
5928+
btrfs_readdir_put_delayed_items(inode, &ins_list, &del_list);
59275929
btrfs_free_path(path);
59285930
return ret;
59295931
}
@@ -10535,7 +10537,7 @@ static const struct inode_operations btrfs_dir_ro_inode_operations = {
1053510537
static const struct file_operations btrfs_dir_file_operations = {
1053610538
.llseek = generic_file_llseek,
1053710539
.read = generic_read_dir,
10538-
.iterate = btrfs_real_readdir,
10540+
.iterate_shared = btrfs_real_readdir,
1053910541
.unlocked_ioctl = btrfs_ioctl,
1054010542
#ifdef CONFIG_COMPAT
1054110543
.compat_ioctl = btrfs_compat_ioctl,

0 commit comments

Comments
 (0)