diff options
Diffstat (limited to 'fs/btrfs/delayed-inode.c')
| -rw-r--r-- | fs/btrfs/delayed-inode.c | 29 | 
1 files changed, 23 insertions, 6 deletions
diff --git a/fs/btrfs/delayed-inode.c b/fs/btrfs/delayed-inode.c index 6cef0062f929..d3aaabbfada0 100644 --- a/fs/btrfs/delayed-inode.c +++ b/fs/btrfs/delayed-inode.c @@ -134,7 +134,7 @@ again:  	/* cached in the btrfs inode and can be accessed */  	atomic_add(2, &node->refs); -	ret = radix_tree_preload(GFP_NOFS & ~__GFP_HIGHMEM); +	ret = radix_tree_preload(GFP_NOFS);  	if (ret) {  		kmem_cache_free(delayed_node_cache, node);  		return ERR_PTR(ret); @@ -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); @@ -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; @@ -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,  |