Skip to content

Commit

Permalink
Merge branch 'for-linus-4.5' of git://git.kernel.org/pub/scm/linux/ke…
Browse files Browse the repository at this point in the history
…rnel/git/mason/linux-btrfs

Pull more btrfs updates from Chris Mason:
 "These are mostly fixes that we've been testing, but also we grabbed
  and tested a few small cleanups that had been on the list for a while.

  Zhao Lei's patchset also fixes some early ENOSPC buglets"

* 'for-linus-4.5' of git://git.kernel.org/pub/scm/linux/kernel/git/mason/linux-btrfs: (21 commits)
  btrfs: raid56: Use raid_write_end_io for scrub
  btrfs: Remove unnecessary ClearPageUptodate for raid56
  btrfs: use rbio->nr_pages to reduce calculation
  btrfs: Use unified stripe_page's index calculation
  btrfs: Fix calculation of rbio->dbitmap's size calculation
  btrfs: Fix no_space in write and rm loop
  btrfs: merge functions for wait snapshot creation
  btrfs: delete unused argument in btrfs_copy_from_user
  btrfs: Use direct way to determine raid56 write/recover mode
  btrfs: Small cleanup for get index_srcdev loop
  btrfs: Enhance chunk validation check
  btrfs: Enhance super validation check
  Btrfs: fix deadlock running delayed iputs at transaction commit time
  Btrfs: fix typo in log message when starting a balance
  btrfs: remove duplicate const specifier
  btrfs: initialize the seq counter in struct btrfs_device
  Btrfs: clean up an error code in btrfs_init_space_info()
  btrfs: fix iterator with update error in backref.c
  Btrfs: fix output of compression message in btrfs_parse_options()
  Btrfs: Initialize btrfs_root->highest_objectid when loading tree root and subvolume roots
  ...
  • Loading branch information
Linus Torvalds committed Jan 22, 2016
2 parents 391f2a1 + a6111d1 commit 2101ae4
Show file tree
Hide file tree
Showing 16 changed files with 264 additions and 213 deletions.
10 changes: 5 additions & 5 deletions fs/btrfs/backref.c
Original file line number Diff line number Diff line change
Expand Up @@ -560,13 +560,13 @@ static int __add_missing_keys(struct btrfs_fs_info *fs_info,
*/
static void __merge_refs(struct list_head *head, int mode)
{
struct __prelim_ref *ref1;
struct __prelim_ref *pos1;

list_for_each_entry(ref1, head, list) {
struct __prelim_ref *ref2 = ref1, *tmp;
list_for_each_entry(pos1, head, list) {
struct __prelim_ref *pos2 = pos1, *tmp;

list_for_each_entry_safe_continue(ref2, tmp, head, list) {
struct __prelim_ref *xchg;
list_for_each_entry_safe_continue(pos2, tmp, head, list) {
struct __prelim_ref *xchg, *ref1 = pos1, *ref2 = pos2;
struct extent_inode_elem *eie;

if (!ref_for_same_block(ref1, ref2))
Expand Down
3 changes: 2 additions & 1 deletion fs/btrfs/ctree.h
Original file line number Diff line number Diff line change
Expand Up @@ -1614,7 +1614,7 @@ struct btrfs_fs_info {

spinlock_t delayed_iput_lock;
struct list_head delayed_iputs;
struct rw_semaphore delayed_iput_sem;
struct mutex cleaner_delayed_iput_mutex;

/* this protects tree_mod_seq_list */
spinlock_t tree_mod_seq_lock;
Expand Down Expand Up @@ -3641,6 +3641,7 @@ int btrfs_delayed_refs_qgroup_accounting(struct btrfs_trans_handle *trans,
int __get_raid_index(u64 flags);
int btrfs_start_write_no_snapshoting(struct btrfs_root *root);
void btrfs_end_write_no_snapshoting(struct btrfs_root *root);
void btrfs_wait_for_snapshot_creation(struct btrfs_root *root);
void check_system_chunk(struct btrfs_trans_handle *trans,
struct btrfs_root *root,
const u64 type);
Expand Down
2 changes: 1 addition & 1 deletion fs/btrfs/dev-replace.c
Original file line number Diff line number Diff line change
Expand Up @@ -614,7 +614,7 @@ static void btrfs_dev_replace_update_device_in_mapping_tree(
em = lookup_extent_mapping(em_tree, start, (u64)-1);
if (!em)
break;
map = (struct map_lookup *)em->bdev;
map = em->map_lookup;
for (i = 0; i < map->num_stripes; i++)
if (srcdev == map->stripes[i].dev)
map->stripes[i].dev = tgtdev;
Expand Down
129 changes: 79 additions & 50 deletions fs/btrfs/disk-io.c
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,12 @@
#include <asm/cpufeature.h>
#endif

#define BTRFS_SUPER_FLAG_SUPP (BTRFS_HEADER_FLAG_WRITTEN |\
BTRFS_HEADER_FLAG_RELOC |\
BTRFS_SUPER_FLAG_ERROR |\
BTRFS_SUPER_FLAG_SEEDING |\
BTRFS_SUPER_FLAG_METADUMP)

static const struct extent_io_ops btree_extent_io_ops;
static void end_workqueue_fn(struct btrfs_work *work);
static void free_fs_root(struct btrfs_root *root);
Expand Down Expand Up @@ -1583,8 +1589,23 @@ int btrfs_init_fs_root(struct btrfs_root *root)
ret = get_anon_bdev(&root->anon_dev);
if (ret)
goto free_writers;

mutex_lock(&root->objectid_mutex);
ret = btrfs_find_highest_objectid(root,
&root->highest_objectid);
if (ret) {
mutex_unlock(&root->objectid_mutex);
goto free_root_dev;
}

ASSERT(root->highest_objectid <= BTRFS_LAST_FREE_OBJECTID);

mutex_unlock(&root->objectid_mutex);

return 0;

free_root_dev:
free_anon_bdev(root->anon_dev);
free_writers:
btrfs_free_subvolume_writers(root->subv_writers);
fail:
Expand Down Expand Up @@ -1786,7 +1807,10 @@ static int cleaner_kthread(void *arg)
goto sleep;
}

mutex_lock(&root->fs_info->cleaner_delayed_iput_mutex);
btrfs_run_delayed_iputs(root);
mutex_unlock(&root->fs_info->cleaner_delayed_iput_mutex);

again = btrfs_clean_one_deleted_snapshot(root);
mutex_unlock(&root->fs_info->cleaner_mutex);

Expand Down Expand Up @@ -2556,8 +2580,8 @@ int open_ctree(struct super_block *sb,
mutex_init(&fs_info->delete_unused_bgs_mutex);
mutex_init(&fs_info->reloc_mutex);
mutex_init(&fs_info->delalloc_root_mutex);
mutex_init(&fs_info->cleaner_delayed_iput_mutex);
seqlock_init(&fs_info->profiles_lock);
init_rwsem(&fs_info->delayed_iput_sem);

INIT_LIST_HEAD(&fs_info->dirty_cowonly_roots);
INIT_LIST_HEAD(&fs_info->space_info);
Expand Down Expand Up @@ -2742,26 +2766,6 @@ int open_ctree(struct super_block *sb,
goto fail_alloc;
}

/*
* Leafsize and nodesize were always equal, this is only a sanity check.
*/
if (le32_to_cpu(disk_super->__unused_leafsize) !=
btrfs_super_nodesize(disk_super)) {
printk(KERN_ERR "BTRFS: couldn't mount because metadata "
"blocksizes don't match. node %d leaf %d\n",
btrfs_super_nodesize(disk_super),
le32_to_cpu(disk_super->__unused_leafsize));
err = -EINVAL;
goto fail_alloc;
}
if (btrfs_super_nodesize(disk_super) > BTRFS_MAX_METADATA_BLOCKSIZE) {
printk(KERN_ERR "BTRFS: couldn't mount because metadata "
"blocksize (%d) was too large\n",
btrfs_super_nodesize(disk_super));
err = -EINVAL;
goto fail_alloc;
}

features = btrfs_super_incompat_flags(disk_super);
features |= BTRFS_FEATURE_INCOMPAT_MIXED_BACKREF;
if (tree_root->fs_info->compress_type == BTRFS_COMPRESS_LZO)
Expand Down Expand Up @@ -2833,17 +2837,6 @@ int open_ctree(struct super_block *sb,
sb->s_blocksize = sectorsize;
sb->s_blocksize_bits = blksize_bits(sectorsize);

if (btrfs_super_magic(disk_super) != BTRFS_MAGIC) {
printk(KERN_ERR "BTRFS: valid FS not found on %s\n", sb->s_id);
goto fail_sb_buffer;
}

if (sectorsize != PAGE_SIZE) {
printk(KERN_ERR "BTRFS: incompatible sector size (%lu) "
"found on %s\n", (unsigned long)sectorsize, sb->s_id);
goto fail_sb_buffer;
}

mutex_lock(&fs_info->chunk_mutex);
ret = btrfs_read_sys_array(tree_root);
mutex_unlock(&fs_info->chunk_mutex);
Expand Down Expand Up @@ -2915,6 +2908,18 @@ int open_ctree(struct super_block *sb,
tree_root->commit_root = btrfs_root_node(tree_root);
btrfs_set_root_refs(&tree_root->root_item, 1);

mutex_lock(&tree_root->objectid_mutex);
ret = btrfs_find_highest_objectid(tree_root,
&tree_root->highest_objectid);
if (ret) {
mutex_unlock(&tree_root->objectid_mutex);
goto recovery_tree_root;
}

ASSERT(tree_root->highest_objectid <= BTRFS_LAST_FREE_OBJECTID);

mutex_unlock(&tree_root->objectid_mutex);

ret = btrfs_read_roots(fs_info, tree_root);
if (ret)
goto recovery_tree_root;
Expand Down Expand Up @@ -4018,8 +4023,17 @@ static int btrfs_check_super_valid(struct btrfs_fs_info *fs_info,
int read_only)
{
struct btrfs_super_block *sb = fs_info->super_copy;
u64 nodesize = btrfs_super_nodesize(sb);
u64 sectorsize = btrfs_super_sectorsize(sb);
int ret = 0;

if (btrfs_super_magic(sb) != BTRFS_MAGIC) {
printk(KERN_ERR "BTRFS: no valid FS found\n");
ret = -EINVAL;
}
if (btrfs_super_flags(sb) & ~BTRFS_SUPER_FLAG_SUPP)
printk(KERN_WARNING "BTRFS: unrecognized super flag: %llu\n",
btrfs_super_flags(sb) & ~BTRFS_SUPER_FLAG_SUPP);
if (btrfs_super_root_level(sb) >= BTRFS_MAX_LEVEL) {
printk(KERN_ERR "BTRFS: tree_root level too big: %d >= %d\n",
btrfs_super_root_level(sb), BTRFS_MAX_LEVEL);
Expand All @@ -4037,31 +4051,46 @@ static int btrfs_check_super_valid(struct btrfs_fs_info *fs_info,
}

/*
* The common minimum, we don't know if we can trust the nodesize/sectorsize
* items yet, they'll be verified later. Issue just a warning.
* Check sectorsize and nodesize first, other check will need it.
* Check all possible sectorsize(4K, 8K, 16K, 32K, 64K) here.
*/
if (!IS_ALIGNED(btrfs_super_root(sb), 4096))
if (!is_power_of_2(sectorsize) || sectorsize < 4096 ||
sectorsize > BTRFS_MAX_METADATA_BLOCKSIZE) {
printk(KERN_ERR "BTRFS: invalid sectorsize %llu\n", sectorsize);
ret = -EINVAL;
}
/* Only PAGE SIZE is supported yet */
if (sectorsize != PAGE_CACHE_SIZE) {
printk(KERN_ERR "BTRFS: sectorsize %llu not supported yet, only support %lu\n",
sectorsize, PAGE_CACHE_SIZE);
ret = -EINVAL;
}
if (!is_power_of_2(nodesize) || nodesize < sectorsize ||
nodesize > BTRFS_MAX_METADATA_BLOCKSIZE) {
printk(KERN_ERR "BTRFS: invalid nodesize %llu\n", nodesize);
ret = -EINVAL;
}
if (nodesize != le32_to_cpu(sb->__unused_leafsize)) {
printk(KERN_ERR "BTRFS: invalid leafsize %u, should be %llu\n",
le32_to_cpu(sb->__unused_leafsize),
nodesize);
ret = -EINVAL;
}

/* Root alignment check */
if (!IS_ALIGNED(btrfs_super_root(sb), sectorsize)) {
printk(KERN_WARNING "BTRFS: tree_root block unaligned: %llu\n",
btrfs_super_root(sb));
if (!IS_ALIGNED(btrfs_super_chunk_root(sb), 4096))
ret = -EINVAL;
}
if (!IS_ALIGNED(btrfs_super_chunk_root(sb), sectorsize)) {
printk(KERN_WARNING "BTRFS: chunk_root block unaligned: %llu\n",
btrfs_super_chunk_root(sb));
if (!IS_ALIGNED(btrfs_super_log_root(sb), 4096))
printk(KERN_WARNING "BTRFS: log_root block unaligned: %llu\n",
btrfs_super_log_root(sb));

/*
* Check the lower bound, the alignment and other constraints are
* checked later.
*/
if (btrfs_super_nodesize(sb) < 4096) {
printk(KERN_ERR "BTRFS: nodesize too small: %u < 4096\n",
btrfs_super_nodesize(sb));
ret = -EINVAL;
}
if (btrfs_super_sectorsize(sb) < 4096) {
printk(KERN_ERR "BTRFS: sectorsize too small: %u < 4096\n",
btrfs_super_sectorsize(sb));
if (!IS_ALIGNED(btrfs_super_log_root(sb), sectorsize)) {
printk(KERN_WARNING "BTRFS: log_root block unaligned: %llu\n",
btrfs_super_log_root(sb));
ret = -EINVAL;
}

Expand Down
37 changes: 30 additions & 7 deletions fs/btrfs/extent-tree.c
Original file line number Diff line number Diff line change
Expand Up @@ -4139,8 +4139,10 @@ int btrfs_alloc_data_chunk_ondemand(struct inode *inode, u64 bytes)
!atomic_read(&root->fs_info->open_ioctl_trans)) {
need_commit--;

if (need_commit > 0)
if (need_commit > 0) {
btrfs_start_delalloc_roots(fs_info, 0, -1);
btrfs_wait_ordered_roots(fs_info, -1);
}

trans = btrfs_join_transaction(root);
if (IS_ERR(trans))
Expand All @@ -4153,11 +4155,12 @@ int btrfs_alloc_data_chunk_ondemand(struct inode *inode, u64 bytes)
if (ret)
return ret;
/*
* make sure that all running delayed iput are
* done
* The cleaner kthread might still be doing iput
* operations. Wait for it to finish so that
* more space is released.
*/
down_write(&root->fs_info->delayed_iput_sem);
up_write(&root->fs_info->delayed_iput_sem);
mutex_lock(&root->fs_info->cleaner_delayed_iput_mutex);
mutex_unlock(&root->fs_info->cleaner_delayed_iput_mutex);
goto again;
} else {
btrfs_end_transaction(trans, root);
Expand Down Expand Up @@ -10399,7 +10402,7 @@ btrfs_start_trans_remove_block_group(struct btrfs_fs_info *fs_info,
* more device items and remove one chunk item), but this is done at
* btrfs_remove_chunk() through a call to check_system_chunk().
*/
map = (struct map_lookup *)em->bdev;
map = em->map_lookup;
num_items = 3 + map->num_stripes;
free_extent_map(em);

Expand Down Expand Up @@ -10586,7 +10589,7 @@ int btrfs_init_space_info(struct btrfs_fs_info *fs_info)

disk_super = fs_info->super_copy;
if (!btrfs_super_root(disk_super))
return 1;
return -EINVAL;

features = btrfs_super_incompat_flags(disk_super);
if (features & BTRFS_FEATURE_INCOMPAT_MIXED_GROUPS)
Expand Down Expand Up @@ -10816,3 +10819,23 @@ int btrfs_start_write_no_snapshoting(struct btrfs_root *root)
}
return 1;
}

static int wait_snapshoting_atomic_t(atomic_t *a)
{
schedule();
return 0;
}

void btrfs_wait_for_snapshot_creation(struct btrfs_root *root)
{
while (true) {
int ret;

ret = btrfs_start_write_no_snapshoting(root);
if (ret)
break;
wait_on_atomic_t(&root->will_be_snapshoted,
wait_snapshoting_atomic_t,
TASK_UNINTERRUPTIBLE);
}
}
2 changes: 1 addition & 1 deletion fs/btrfs/extent_map.c
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ void free_extent_map(struct extent_map *em)
WARN_ON(extent_map_in_tree(em));
WARN_ON(!list_empty(&em->list));
if (test_bit(EXTENT_FLAG_FS_MAPPING, &em->flags))
kfree(em->bdev);
kfree(em->map_lookup);
kmem_cache_free(extent_map_cache, em);
}
}
Expand Down
10 changes: 9 additions & 1 deletion fs/btrfs/extent_map.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,15 @@ struct extent_map {
u64 block_len;
u64 generation;
unsigned long flags;
struct block_device *bdev;
union {
struct block_device *bdev;

/*
* used for chunk mappings
* flags & EXTENT_FLAG_FS_MAPPING must be set
*/
struct map_lookup *map_lookup;
};
atomic_t refs;
unsigned int compress_type;
struct list_head list;
Expand Down
6 changes: 2 additions & 4 deletions fs/btrfs/file.c
Original file line number Diff line number Diff line change
Expand Up @@ -406,8 +406,7 @@ int btrfs_run_defrag_inodes(struct btrfs_fs_info *fs_info)
/* simple helper to fault in pages and copy. This should go away
* and be replaced with calls into generic code.
*/
static noinline int btrfs_copy_from_user(loff_t pos, int num_pages,
size_t write_bytes,
static noinline int btrfs_copy_from_user(loff_t pos, size_t write_bytes,
struct page **prepared_pages,
struct iov_iter *i)
{
Expand Down Expand Up @@ -1588,8 +1587,7 @@ static noinline ssize_t __btrfs_buffered_write(struct file *file,
ret = 0;
}

copied = btrfs_copy_from_user(pos, num_pages,
write_bytes, pages, i);
copied = btrfs_copy_from_user(pos, write_bytes, pages, i);

/*
* if we have trouble faulting in the pages, fall
Expand Down
9 changes: 1 addition & 8 deletions fs/btrfs/inode-map.c
Original file line number Diff line number Diff line change
Expand Up @@ -515,7 +515,7 @@ int btrfs_save_ino_cache(struct btrfs_root *root,
return ret;
}

static int btrfs_find_highest_objectid(struct btrfs_root *root, u64 *objectid)
int btrfs_find_highest_objectid(struct btrfs_root *root, u64 *objectid)
{
struct btrfs_path *path;
int ret;
Expand Down Expand Up @@ -555,13 +555,6 @@ int btrfs_find_free_objectid(struct btrfs_root *root, u64 *objectid)
int ret;
mutex_lock(&root->objectid_mutex);

if (unlikely(root->highest_objectid < BTRFS_FIRST_FREE_OBJECTID)) {
ret = btrfs_find_highest_objectid(root,
&root->highest_objectid);
if (ret)
goto out;
}

if (unlikely(root->highest_objectid >= BTRFS_LAST_FREE_OBJECTID)) {
ret = -ENOSPC;
goto out;
Expand Down
1 change: 1 addition & 0 deletions fs/btrfs/inode-map.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,6 @@ int btrfs_save_ino_cache(struct btrfs_root *root,
struct btrfs_trans_handle *trans);

int btrfs_find_free_objectid(struct btrfs_root *root, u64 *objectid);
int btrfs_find_highest_objectid(struct btrfs_root *root, u64 *objectid);

#endif
Loading

0 comments on commit 2101ae4

Please sign in to comment.