Merge branch 'for-linus-4.2' of git://git.kernel.org/pub/scm/linux/kernel/git/mason/linux-btrfs
Pull btrfs fixes from Chris Mason: "This is an assortment of fixes. Most of the commits are from Filipe (fsync, the inode allocation cache and a few others). Mark kicked in a series fixing corners in the extent sharing ioctls, and everyone else fixed up on assorted other problems" * 'for-linus-4.2' of git://git.kernel.org/pub/scm/linux/kernel/git/mason/linux-btrfs: Btrfs: fix wrong check for btrfs_force_chunk_alloc() Btrfs: fix warning of bytes_may_use Btrfs: fix hang when failing to submit bio of directIO Btrfs: fix a comment in inode.c:evict_inode_truncate_pages() Btrfs: fix memory corruption on failure to submit bio for direct IO btrfs: don't update mtime/ctime on deduped inodes btrfs: allow dedupe of same inode btrfs: fix deadlock with extent-same and readpage btrfs: pass unaligned length to btrfs_cmp_data() Btrfs: fix fsync after truncate when no_holes feature is enabled Btrfs: fix fsync xattr loss in the fast fsync path Btrfs: fix fsync data loss after append write Btrfs: fix crash on close_ctree() if cleaner starts new transaction Btrfs: fix race between caching kthread and returning inode to inode cache Btrfs: use kmem_cache_free when freeing entry in inode cache Btrfs: fix race between balance and unused block group deletion btrfs: add error handling for scrub_workers_get() btrfs: cleanup noused initialization of dev in btrfs_end_bio() btrfs: qgroup: allow user to clear the limitation on qgroup
This commit is contained in:
@@ -2766,6 +2766,20 @@ static int btrfs_relocate_chunk(struct btrfs_root *root,
|
||||
root = root->fs_info->chunk_root;
|
||||
extent_root = root->fs_info->extent_root;
|
||||
|
||||
/*
|
||||
* Prevent races with automatic removal of unused block groups.
|
||||
* After we relocate and before we remove the chunk with offset
|
||||
* chunk_offset, automatic removal of the block group can kick in,
|
||||
* resulting in a failure when calling btrfs_remove_chunk() below.
|
||||
*
|
||||
* Make sure to acquire this mutex before doing a tree search (dev
|
||||
* or chunk trees) to find chunks. Otherwise the cleaner kthread might
|
||||
* call btrfs_remove_chunk() (through btrfs_delete_unused_bgs()) after
|
||||
* we release the path used to search the chunk/dev tree and before
|
||||
* the current task acquires this mutex and calls us.
|
||||
*/
|
||||
ASSERT(mutex_is_locked(&root->fs_info->delete_unused_bgs_mutex));
|
||||
|
||||
ret = btrfs_can_relocate(extent_root, chunk_offset);
|
||||
if (ret)
|
||||
return -ENOSPC;
|
||||
@@ -2814,13 +2828,18 @@ again:
|
||||
key.type = BTRFS_CHUNK_ITEM_KEY;
|
||||
|
||||
while (1) {
|
||||
mutex_lock(&root->fs_info->delete_unused_bgs_mutex);
|
||||
ret = btrfs_search_slot(NULL, chunk_root, &key, path, 0, 0);
|
||||
if (ret < 0)
|
||||
if (ret < 0) {
|
||||
mutex_unlock(&root->fs_info->delete_unused_bgs_mutex);
|
||||
goto error;
|
||||
}
|
||||
BUG_ON(ret == 0); /* Corruption */
|
||||
|
||||
ret = btrfs_previous_item(chunk_root, path, key.objectid,
|
||||
key.type);
|
||||
if (ret)
|
||||
mutex_unlock(&root->fs_info->delete_unused_bgs_mutex);
|
||||
if (ret < 0)
|
||||
goto error;
|
||||
if (ret > 0)
|
||||
@@ -2843,6 +2862,7 @@ again:
|
||||
else
|
||||
BUG_ON(ret);
|
||||
}
|
||||
mutex_unlock(&root->fs_info->delete_unused_bgs_mutex);
|
||||
|
||||
if (found_key.offset == 0)
|
||||
break;
|
||||
@@ -3299,9 +3319,12 @@ again:
|
||||
goto error;
|
||||
}
|
||||
|
||||
mutex_lock(&fs_info->delete_unused_bgs_mutex);
|
||||
ret = btrfs_search_slot(NULL, chunk_root, &key, path, 0, 0);
|
||||
if (ret < 0)
|
||||
if (ret < 0) {
|
||||
mutex_unlock(&fs_info->delete_unused_bgs_mutex);
|
||||
goto error;
|
||||
}
|
||||
|
||||
/*
|
||||
* this shouldn't happen, it means the last relocate
|
||||
@@ -3313,6 +3336,7 @@ again:
|
||||
ret = btrfs_previous_item(chunk_root, path, 0,
|
||||
BTRFS_CHUNK_ITEM_KEY);
|
||||
if (ret) {
|
||||
mutex_unlock(&fs_info->delete_unused_bgs_mutex);
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
@@ -3321,8 +3345,10 @@ again:
|
||||
slot = path->slots[0];
|
||||
btrfs_item_key_to_cpu(leaf, &found_key, slot);
|
||||
|
||||
if (found_key.objectid != key.objectid)
|
||||
if (found_key.objectid != key.objectid) {
|
||||
mutex_unlock(&fs_info->delete_unused_bgs_mutex);
|
||||
break;
|
||||
}
|
||||
|
||||
chunk = btrfs_item_ptr(leaf, slot, struct btrfs_chunk);
|
||||
|
||||
@@ -3335,10 +3361,13 @@ again:
|
||||
ret = should_balance_chunk(chunk_root, leaf, chunk,
|
||||
found_key.offset);
|
||||
btrfs_release_path(path);
|
||||
if (!ret)
|
||||
if (!ret) {
|
||||
mutex_unlock(&fs_info->delete_unused_bgs_mutex);
|
||||
goto loop;
|
||||
}
|
||||
|
||||
if (counting) {
|
||||
mutex_unlock(&fs_info->delete_unused_bgs_mutex);
|
||||
spin_lock(&fs_info->balance_lock);
|
||||
bctl->stat.expected++;
|
||||
spin_unlock(&fs_info->balance_lock);
|
||||
@@ -3348,6 +3377,7 @@ again:
|
||||
ret = btrfs_relocate_chunk(chunk_root,
|
||||
found_key.objectid,
|
||||
found_key.offset);
|
||||
mutex_unlock(&fs_info->delete_unused_bgs_mutex);
|
||||
if (ret && ret != -ENOSPC)
|
||||
goto error;
|
||||
if (ret == -ENOSPC) {
|
||||
@@ -4087,11 +4117,16 @@ again:
|
||||
key.type = BTRFS_DEV_EXTENT_KEY;
|
||||
|
||||
do {
|
||||
mutex_lock(&root->fs_info->delete_unused_bgs_mutex);
|
||||
ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
|
||||
if (ret < 0)
|
||||
if (ret < 0) {
|
||||
mutex_unlock(&root->fs_info->delete_unused_bgs_mutex);
|
||||
goto done;
|
||||
}
|
||||
|
||||
ret = btrfs_previous_item(root, path, 0, key.type);
|
||||
if (ret)
|
||||
mutex_unlock(&root->fs_info->delete_unused_bgs_mutex);
|
||||
if (ret < 0)
|
||||
goto done;
|
||||
if (ret) {
|
||||
@@ -4105,6 +4140,7 @@ again:
|
||||
btrfs_item_key_to_cpu(l, &key, path->slots[0]);
|
||||
|
||||
if (key.objectid != device->devid) {
|
||||
mutex_unlock(&root->fs_info->delete_unused_bgs_mutex);
|
||||
btrfs_release_path(path);
|
||||
break;
|
||||
}
|
||||
@@ -4113,6 +4149,7 @@ again:
|
||||
length = btrfs_dev_extent_length(l, dev_extent);
|
||||
|
||||
if (key.offset + length <= new_size) {
|
||||
mutex_unlock(&root->fs_info->delete_unused_bgs_mutex);
|
||||
btrfs_release_path(path);
|
||||
break;
|
||||
}
|
||||
@@ -4122,6 +4159,7 @@ again:
|
||||
btrfs_release_path(path);
|
||||
|
||||
ret = btrfs_relocate_chunk(root, chunk_objectid, chunk_offset);
|
||||
mutex_unlock(&root->fs_info->delete_unused_bgs_mutex);
|
||||
if (ret && ret != -ENOSPC)
|
||||
goto done;
|
||||
if (ret == -ENOSPC)
|
||||
@@ -5715,7 +5753,6 @@ static inline void btrfs_end_bbio(struct btrfs_bio *bbio, struct bio *bio, int e
|
||||
static void btrfs_end_bio(struct bio *bio, int err)
|
||||
{
|
||||
struct btrfs_bio *bbio = bio->bi_private;
|
||||
struct btrfs_device *dev = bbio->stripes[0].dev;
|
||||
int is_orig_bio = 0;
|
||||
|
||||
if (err) {
|
||||
@@ -5723,6 +5760,7 @@ static void btrfs_end_bio(struct bio *bio, int err)
|
||||
if (err == -EIO || err == -EREMOTEIO) {
|
||||
unsigned int stripe_index =
|
||||
btrfs_io_bio(bio)->stripe_index;
|
||||
struct btrfs_device *dev;
|
||||
|
||||
BUG_ON(stripe_index >= bbio->num_stripes);
|
||||
dev = bbio->stripes[stripe_index].dev;
|
||||
|
Reference in New Issue
Block a user