Skip to content

Commit

Permalink
Merge branch 'for-linus-4.7-part2' of git://git.kernel.org/pub/scm/li…
Browse files Browse the repository at this point in the history
…nux/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
  • Loading branch information
Linus Torvalds committed Jun 25, 2016
2 parents b971712 + 02dbfc9 commit da2f6ab
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 13 deletions.
27 changes: 22 additions & 5 deletions fs/btrfs/delayed-inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -1606,15 +1606,23 @@ int btrfs_inode_delayed_dir_index_count(struct inode *inode)
return 0;
}

void btrfs_get_delayed_items(struct inode *inode, struct list_head *ins_list,
struct list_head *del_list)
bool btrfs_readdir_get_delayed_items(struct inode *inode,
struct list_head *ins_list,
struct list_head *del_list)
{
struct btrfs_delayed_node *delayed_node;
struct btrfs_delayed_item *item;

delayed_node = btrfs_get_delayed_node(inode);
if (!delayed_node)
return;
return false;

/*
* We can only do one readdir with delayed items at a time because of
* item->readdir_list.
*/
inode_unlock_shared(inode);
inode_lock(inode);

mutex_lock(&delayed_node->mutex);
item = __btrfs_first_delayed_insertion_item(delayed_node);
Expand All @@ -1641,10 +1649,13 @@ void btrfs_get_delayed_items(struct inode *inode, struct list_head *ins_list,
* requeue or dequeue this delayed node.
*/
atomic_dec(&delayed_node->refs);

return true;
}

void btrfs_put_delayed_items(struct list_head *ins_list,
struct list_head *del_list)
void btrfs_readdir_put_delayed_items(struct inode *inode,
struct list_head *ins_list,
struct list_head *del_list)
{
struct btrfs_delayed_item *curr, *next;

Expand All @@ -1659,6 +1670,12 @@ void btrfs_put_delayed_items(struct list_head *ins_list,
if (atomic_dec_and_test(&curr->refs))
kfree(curr);
}

/*
* The VFS is going to do up_read(), so we need to downgrade back to a
* read lock.
*/
downgrade_write(&inode->i_rwsem);
}

int btrfs_should_delete_dir_index(struct list_head *del_list,
Expand Down
10 changes: 6 additions & 4 deletions fs/btrfs/delayed-inode.h
Original file line number Diff line number Diff line change
Expand Up @@ -137,10 +137,12 @@ void btrfs_kill_all_delayed_nodes(struct btrfs_root *root);
void btrfs_destroy_delayed_inodes(struct btrfs_root *root);

/* Used for readdir() */
void btrfs_get_delayed_items(struct inode *inode, struct list_head *ins_list,
struct list_head *del_list);
void btrfs_put_delayed_items(struct list_head *ins_list,
struct list_head *del_list);
bool btrfs_readdir_get_delayed_items(struct inode *inode,
struct list_head *ins_list,
struct list_head *del_list);
void btrfs_readdir_put_delayed_items(struct inode *inode,
struct list_head *ins_list,
struct list_head *del_list);
int btrfs_should_delete_dir_index(struct list_head *del_list,
u64 index);
int btrfs_readdir_delayed_dir_index(struct dir_context *ctx,
Expand Down
10 changes: 6 additions & 4 deletions fs/btrfs/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -5758,6 +5758,7 @@ static int btrfs_real_readdir(struct file *file, struct dir_context *ctx)
int name_len;
int is_curr = 0; /* ctx->pos points to the current index? */
bool emitted;
bool put = false;

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

key.type = key_type;
Expand Down Expand Up @@ -5922,8 +5924,8 @@ static int btrfs_real_readdir(struct file *file, struct dir_context *ctx)
nopos:
ret = 0;
err:
if (key_type == BTRFS_DIR_INDEX_KEY)
btrfs_put_delayed_items(&ins_list, &del_list);
if (put)
btrfs_readdir_put_delayed_items(inode, &ins_list, &del_list);
btrfs_free_path(path);
return ret;
}
Expand Down Expand Up @@ -10535,7 +10537,7 @@ static const struct inode_operations btrfs_dir_ro_inode_operations = {
static const struct file_operations btrfs_dir_file_operations = {
.llseek = generic_file_llseek,
.read = generic_read_dir,
.iterate = btrfs_real_readdir,
.iterate_shared = btrfs_real_readdir,
.unlocked_ioctl = btrfs_ioctl,
#ifdef CONFIG_COMPAT
.compat_ioctl = btrfs_compat_ioctl,
Expand Down

0 comments on commit da2f6ab

Please sign in to comment.