Commit e6ece707 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mason/btrfs-unstable

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mason/btrfs-unstable: (25 commits)
  btrfs: fix uninitialized variable warning
  btrfs: add helper for fs_info->closing
  Btrfs: add mount -o inode_cache
  btrfs: scrub: add explicit plugging
  btrfs: use btrfs_ino to access inode number
  Btrfs: don't save the inode cache if we are deleting this root
  btrfs: false BUG_ON when degraded
  Btrfs: don't save the inode cache in non-FS roots
  Btrfs: make sure we don't overflow the free space cache crc page
  Btrfs: fix uninit variable in the delayed inode code
  btrfs: scrub: don't reuse bios and pages
  Btrfs: leave spinning on lookup and map the leaf
  Btrfs: check for duplicate entries in the free space cache
  Btrfs: don't try to allocate from a block group that doesn't have enough space
  Btrfs: don't always do readahead
  Btrfs: try not to sleep as much when doing slow caching
  Btrfs: kill BTRFS_I(inode)->block_group
  Btrfs: don't look at the extent buffer level 3 times in a row
  Btrfs: map the node block when looking for readahead targets
  Btrfs: set range_start to the right start in count_range_bits
  ...
parents 23c79d31 aa0467d8
...@@ -121,9 +121,6 @@ struct btrfs_inode { ...@@ -121,9 +121,6 @@ struct btrfs_inode {
*/ */
u64 index_cnt; u64 index_cnt;
/* the start of block group preferred for allocations. */
u64 block_group;
/* the fsync log has some corner cases that mean we have to check /* the fsync log has some corner cases that mean we have to check
* directories to see if any unlinks have been done before * directories to see if any unlinks have been done before
* the directory was logged. See tree-log.c for all the * the directory was logged. See tree-log.c for all the
......
...@@ -43,8 +43,6 @@ struct btrfs_path *btrfs_alloc_path(void) ...@@ -43,8 +43,6 @@ struct btrfs_path *btrfs_alloc_path(void)
{ {
struct btrfs_path *path; struct btrfs_path *path;
path = kmem_cache_zalloc(btrfs_path_cachep, GFP_NOFS); path = kmem_cache_zalloc(btrfs_path_cachep, GFP_NOFS);
if (path)
path->reada = 1;
return path; return path;
} }
...@@ -1224,6 +1222,7 @@ static void reada_for_search(struct btrfs_root *root, ...@@ -1224,6 +1222,7 @@ static void reada_for_search(struct btrfs_root *root,
u64 search; u64 search;
u64 target; u64 target;
u64 nread = 0; u64 nread = 0;
u64 gen;
int direction = path->reada; int direction = path->reada;
struct extent_buffer *eb; struct extent_buffer *eb;
u32 nr; u32 nr;
...@@ -1251,6 +1250,15 @@ static void reada_for_search(struct btrfs_root *root, ...@@ -1251,6 +1250,15 @@ static void reada_for_search(struct btrfs_root *root,
nritems = btrfs_header_nritems(node); nritems = btrfs_header_nritems(node);
nr = slot; nr = slot;
while (1) { while (1) {
if (!node->map_token) {
unsigned long offset = btrfs_node_key_ptr_offset(nr);
map_private_extent_buffer(node, offset,
sizeof(struct btrfs_key_ptr),
&node->map_token,
&node->kaddr,
&node->map_start,
&node->map_len, KM_USER1);
}
if (direction < 0) { if (direction < 0) {
if (nr == 0) if (nr == 0)
break; break;
...@@ -1268,14 +1276,23 @@ static void reada_for_search(struct btrfs_root *root, ...@@ -1268,14 +1276,23 @@ static void reada_for_search(struct btrfs_root *root,
search = btrfs_node_blockptr(node, nr); search = btrfs_node_blockptr(node, nr);
if ((search <= target && target - search <= 65536) || if ((search <= target && target - search <= 65536) ||
(search > target && search - target <= 65536)) { (search > target && search - target <= 65536)) {
readahead_tree_block(root, search, blocksize, gen = btrfs_node_ptr_generation(node, nr);
btrfs_node_ptr_generation(node, nr)); if (node->map_token) {
unmap_extent_buffer(node, node->map_token,
KM_USER1);
node->map_token = NULL;
}
readahead_tree_block(root, search, blocksize, gen);
nread += blocksize; nread += blocksize;
} }
nscan++; nscan++;
if ((nread > 65536 || nscan > 32)) if ((nread > 65536 || nscan > 32))
break; break;
} }
if (node->map_token) {
unmap_extent_buffer(node, node->map_token, KM_USER1);
node->map_token = NULL;
}
} }
/* /*
...@@ -1648,9 +1665,6 @@ int btrfs_search_slot(struct btrfs_trans_handle *trans, struct btrfs_root ...@@ -1648,9 +1665,6 @@ int btrfs_search_slot(struct btrfs_trans_handle *trans, struct btrfs_root
} }
cow_done: cow_done:
BUG_ON(!cow && ins_len); BUG_ON(!cow && ins_len);
if (level != btrfs_header_level(b))
WARN_ON(1);
level = btrfs_header_level(b);
p->nodes[level] = b; p->nodes[level] = b;
if (!p->skip_locking) if (!p->skip_locking)
......
...@@ -930,7 +930,6 @@ struct btrfs_fs_info { ...@@ -930,7 +930,6 @@ struct btrfs_fs_info {
* is required instead of the faster short fsync log commits * is required instead of the faster short fsync log commits
*/ */
u64 last_trans_log_full_commit; u64 last_trans_log_full_commit;
u64 open_ioctl_trans;
unsigned long mount_opt:20; unsigned long mount_opt:20;
unsigned long compress_type:4; unsigned long compress_type:4;
u64 max_inline; u64 max_inline;
...@@ -947,7 +946,6 @@ struct btrfs_fs_info { ...@@ -947,7 +946,6 @@ struct btrfs_fs_info {
struct super_block *sb; struct super_block *sb;
struct inode *btree_inode; struct inode *btree_inode;
struct backing_dev_info bdi; struct backing_dev_info bdi;
struct mutex trans_mutex;
struct mutex tree_log_mutex; struct mutex tree_log_mutex;
struct mutex transaction_kthread_mutex; struct mutex transaction_kthread_mutex;
struct mutex cleaner_mutex; struct mutex cleaner_mutex;
...@@ -968,6 +966,7 @@ struct btrfs_fs_info { ...@@ -968,6 +966,7 @@ struct btrfs_fs_info {
struct rw_semaphore subvol_sem; struct rw_semaphore subvol_sem;
struct srcu_struct subvol_srcu; struct srcu_struct subvol_srcu;
spinlock_t trans_lock;
struct list_head trans_list; struct list_head trans_list;
struct list_head hashers; struct list_head hashers;
struct list_head dead_roots; struct list_head dead_roots;
...@@ -980,6 +979,7 @@ struct btrfs_fs_info { ...@@ -980,6 +979,7 @@ struct btrfs_fs_info {
atomic_t async_submit_draining; atomic_t async_submit_draining;
atomic_t nr_async_bios; atomic_t nr_async_bios;
atomic_t async_delalloc_pages; atomic_t async_delalloc_pages;
atomic_t open_ioctl_trans;
/* /*
* this is used by the balancing code to wait for all the pending * this is used by the balancing code to wait for all the pending
...@@ -1044,6 +1044,7 @@ struct btrfs_fs_info { ...@@ -1044,6 +1044,7 @@ struct btrfs_fs_info {
int closing; int closing;
int log_root_recovering; int log_root_recovering;
int enospc_unlink; int enospc_unlink;
int trans_no_join;
u64 total_pinned; u64 total_pinned;
...@@ -1065,7 +1066,6 @@ struct btrfs_fs_info { ...@@ -1065,7 +1066,6 @@ struct btrfs_fs_info {
struct reloc_control *reloc_ctl; struct reloc_control *reloc_ctl;
spinlock_t delalloc_lock; spinlock_t delalloc_lock;
spinlock_t new_trans_lock;
u64 delalloc_bytes; u64 delalloc_bytes;
/* data_alloc_cluster is only used in ssd mode */ /* data_alloc_cluster is only used in ssd mode */
...@@ -1340,6 +1340,7 @@ struct btrfs_ioctl_defrag_range_args { ...@@ -1340,6 +1340,7 @@ struct btrfs_ioctl_defrag_range_args {
#define BTRFS_MOUNT_USER_SUBVOL_RM_ALLOWED (1 << 14) #define BTRFS_MOUNT_USER_SUBVOL_RM_ALLOWED (1 << 14)
#define BTRFS_MOUNT_ENOSPC_DEBUG (1 << 15) #define BTRFS_MOUNT_ENOSPC_DEBUG (1 << 15)
#define BTRFS_MOUNT_AUTO_DEFRAG (1 << 16) #define BTRFS_MOUNT_AUTO_DEFRAG (1 << 16)
#define BTRFS_MOUNT_INODE_MAP_CACHE (1 << 17)
#define btrfs_clear_opt(o, opt) ((o) &= ~BTRFS_MOUNT_##opt) #define btrfs_clear_opt(o, opt) ((o) &= ~BTRFS_MOUNT_##opt)
#define btrfs_set_opt(o, opt) ((o) |= BTRFS_MOUNT_##opt) #define btrfs_set_opt(o, opt) ((o) |= BTRFS_MOUNT_##opt)
...@@ -2238,6 +2239,9 @@ int btrfs_block_rsv_migrate(struct btrfs_block_rsv *src_rsv, ...@@ -2238,6 +2239,9 @@ int btrfs_block_rsv_migrate(struct btrfs_block_rsv *src_rsv,
void btrfs_block_rsv_release(struct btrfs_root *root, void btrfs_block_rsv_release(struct btrfs_root *root,
struct btrfs_block_rsv *block_rsv, struct btrfs_block_rsv *block_rsv,
u64 num_bytes); u64 num_bytes);
int btrfs_truncate_reserve_metadata(struct btrfs_trans_handle *trans,
struct btrfs_root *root,
struct btrfs_block_rsv *rsv);
int btrfs_set_block_group_ro(struct btrfs_root *root, int btrfs_set_block_group_ro(struct btrfs_root *root,
struct btrfs_block_group_cache *cache); struct btrfs_block_group_cache *cache);
int btrfs_set_block_group_rw(struct btrfs_root *root, int btrfs_set_block_group_rw(struct btrfs_root *root,
...@@ -2350,6 +2354,15 @@ int btrfs_drop_subtree(struct btrfs_trans_handle *trans, ...@@ -2350,6 +2354,15 @@ int btrfs_drop_subtree(struct btrfs_trans_handle *trans,
struct btrfs_root *root, struct btrfs_root *root,
struct extent_buffer *node, struct extent_buffer *node,
struct extent_buffer *parent); struct extent_buffer *parent);
static inline int btrfs_fs_closing(struct btrfs_fs_info *fs_info)
{
/*
* Get synced with close_ctree()
*/
smp_mb();
return fs_info->closing;
}
/* root-item.c */ /* root-item.c */
int btrfs_find_root_ref(struct btrfs_root *tree_root, int btrfs_find_root_ref(struct btrfs_root *tree_root,
struct btrfs_path *path, struct btrfs_path *path,
...@@ -2512,8 +2525,7 @@ int btrfs_set_extent_delalloc(struct inode *inode, u64 start, u64 end, ...@@ -2512,8 +2525,7 @@ int btrfs_set_extent_delalloc(struct inode *inode, u64 start, u64 end,
int btrfs_writepages(struct address_space *mapping, int btrfs_writepages(struct address_space *mapping,
struct writeback_control *wbc); struct writeback_control *wbc);
int btrfs_create_subvol_root(struct btrfs_trans_handle *trans, int btrfs_create_subvol_root(struct btrfs_trans_handle *trans,
struct btrfs_root *new_root, struct btrfs_root *new_root, u64 new_dirid);
u64 new_dirid, u64 alloc_hint);
int btrfs_merge_bio_hook(struct page *page, unsigned long offset, int btrfs_merge_bio_hook(struct page *page, unsigned long offset,
size_t size, struct bio *bio, unsigned long bio_flags); size_t size, struct bio *bio, unsigned long bio_flags);
......
...@@ -678,6 +678,7 @@ static int btrfs_batch_insert_items(struct btrfs_trans_handle *trans, ...@@ -678,6 +678,7 @@ static int btrfs_batch_insert_items(struct btrfs_trans_handle *trans,
INIT_LIST_HEAD(&head); INIT_LIST_HEAD(&head);
next = item; next = item;
nitems = 0;
/* /*
* count the number of the continuous items that we can insert in batch * count the number of the continuous items that we can insert in batch
...@@ -1129,7 +1130,7 @@ static void btrfs_async_run_delayed_node_done(struct btrfs_work *work) ...@@ -1129,7 +1130,7 @@ static void btrfs_async_run_delayed_node_done(struct btrfs_work *work)
delayed_node = async_node->delayed_node; delayed_node = async_node->delayed_node;
root = delayed_node->root; root = delayed_node->root;
trans = btrfs_join_transaction(root, 0); trans = btrfs_join_transaction(root);
if (IS_ERR(trans)) if (IS_ERR(trans))
goto free_path; goto free_path;
...@@ -1572,8 +1573,7 @@ static void fill_stack_inode_item(struct btrfs_trans_handle *trans, ...@@ -1572,8 +1573,7 @@ static void fill_stack_inode_item(struct btrfs_trans_handle *trans,
btrfs_set_stack_inode_transid(inode_item, trans->transid); btrfs_set_stack_inode_transid(inode_item, trans->transid);
btrfs_set_stack_inode_rdev(inode_item, inode->i_rdev); btrfs_set_stack_inode_rdev(inode_item, inode->i_rdev);
btrfs_set_stack_inode_flags(inode_item, BTRFS_I(inode)->flags); btrfs_set_stack_inode_flags(inode_item, BTRFS_I(inode)->flags);
btrfs_set_stack_inode_block_group(inode_item, btrfs_set_stack_inode_block_group(inode_item, 0);
BTRFS_I(inode)->block_group);
btrfs_set_stack_timespec_sec(btrfs_inode_atime(inode_item), btrfs_set_stack_timespec_sec(btrfs_inode_atime(inode_item),
inode->i_atime.tv_sec); inode->i_atime.tv_sec);
...@@ -1595,7 +1595,7 @@ int btrfs_delayed_update_inode(struct btrfs_trans_handle *trans, ...@@ -1595,7 +1595,7 @@ int btrfs_delayed_update_inode(struct btrfs_trans_handle *trans,
struct btrfs_root *root, struct inode *inode) struct btrfs_root *root, struct inode *inode)
{ {
struct btrfs_delayed_node *delayed_node; struct btrfs_delayed_node *delayed_node;
int ret; int ret = 0;
delayed_node = btrfs_get_or_create_delayed_node(inode); delayed_node = btrfs_get_or_create_delayed_node(inode);
if (IS_ERR(delayed_node)) if (IS_ERR(delayed_node))
......
...@@ -1505,24 +1505,24 @@ static int transaction_kthread(void *arg) ...@@ -1505,24 +1505,24 @@ static int transaction_kthread(void *arg)
vfs_check_frozen(root->fs_info->sb, SB_FREEZE_WRITE); vfs_check_frozen(root->fs_info->sb, SB_FREEZE_WRITE);
mutex_lock(&root->fs_info->transaction_kthread_mutex); mutex_lock(&root->fs_info->transaction_kthread_mutex);
spin_lock(&root->fs_info->new_trans_lock); spin_lock(&root->fs_info->trans_lock);
cur = root->fs_info->running_transaction; cur = root->fs_info->running_transaction;
if (!cur) { if (!cur) {
spin_unlock(&root->fs_info->new_trans_lock); spin_unlock(&root->fs_info->trans_lock);
goto sleep; goto sleep;
} }
now = get_seconds(); now = get_seconds();
if (!cur->blocked && if (!cur->blocked &&
(now < cur->start_time || now - cur->start_time < 30)) { (now < cur->start_time || now - cur->start_time < 30)) {
spin_unlock(&root->fs_info->new_trans_lock); spin_unlock(&root->fs_info->trans_lock);
delay = HZ * 5; delay = HZ * 5;
goto sleep; goto sleep;
} }
transid = cur->transid; transid = cur->transid;
spin_unlock(&root->fs_info->new_trans_lock); spin_unlock(&root->fs_info->trans_lock);
trans = btrfs_join_transaction(root, 1); trans = btrfs_join_transaction(root);
BUG_ON(IS_ERR(trans)); BUG_ON(IS_ERR(trans));
if (transid == trans->transid) { if (transid == trans->transid) {
ret = btrfs_commit_transaction(trans, root); ret = btrfs_commit_transaction(trans, root);
...@@ -1613,7 +1613,7 @@ struct btrfs_root *open_ctree(struct super_block *sb, ...@@ -1613,7 +1613,7 @@ struct btrfs_root *open_ctree(struct super_block *sb,
INIT_LIST_HEAD(&fs_info->ordered_operations); INIT_LIST_HEAD(&fs_info->ordered_operations);
INIT_LIST_HEAD(&fs_info->caching_block_groups); INIT_LIST_HEAD(&fs_info->caching_block_groups);
spin_lock_init(&fs_info->delalloc_lock); spin_lock_init(&fs_info->delalloc_lock);
spin_lock_init(&fs_info->new_trans_lock); spin_lock_init(&fs_info->trans_lock);
spin_lock_init(&fs_info->ref_cache_lock); spin_lock_init(&fs_info->ref_cache_lock);
spin_lock_init(&fs_info->fs_roots_radix_lock); spin_lock_init(&fs_info->fs_roots_radix_lock);
spin_lock_init(&fs_info->delayed_iput_lock); spin_lock_init(&fs_info->delayed_iput_lock);
...@@ -1645,6 +1645,7 @@ struct btrfs_root *open_ctree(struct super_block *sb, ...@@ -1645,6 +1645,7 @@ struct btrfs_root *open_ctree(struct super_block *sb,
fs_info->max_inline = 8192 * 1024; fs_info->max_inline = 8192 * 1024;
fs_info->metadata_ratio = 0; fs_info->metadata_ratio = 0;
fs_info->defrag_inodes = RB_ROOT; fs_info->defrag_inodes = RB_ROOT;
fs_info->trans_no_join = 0;
fs_info->thread_pool_size = min_t(unsigned long, fs_info->thread_pool_size = min_t(unsigned long,
num_online_cpus() + 2, 8); num_online_cpus() + 2, 8);
...@@ -1709,7 +1710,6 @@ struct btrfs_root *open_ctree(struct super_block *sb, ...@@ -1709,7 +1710,6 @@ struct btrfs_root *open_ctree(struct super_block *sb,
fs_info->do_barriers = 1; fs_info->do_barriers = 1;
mutex_init(&fs_info->trans_mutex);
mutex_init(&fs_info->ordered_operations_mutex); mutex_init(&fs_info->ordered_operations_mutex);
mutex_init(&fs_info->tree_log_mutex); mutex_init(&fs_info->tree_log_mutex);
mutex_init(&fs_info->chunk_mutex); mutex_init(&fs_info->chunk_mutex);
...@@ -2479,13 +2479,13 @@ int btrfs_commit_super(struct btrfs_root *root) ...@@ -2479,13 +2479,13 @@ int btrfs_commit_super(struct btrfs_root *root)
down_write(&root->fs_info->cleanup_work_sem); down_write(&root->fs_info->cleanup_work_sem);
up_write(&root->fs_info->cleanup_work_sem); up_write(&root->fs_info->cleanup_work_sem);
trans = btrfs_join_transaction(root, 1); trans = btrfs_join_transaction(root);
if (IS_ERR(trans)) if (IS_ERR(trans))
return PTR_ERR(trans); return PTR_ERR(trans);
ret = btrfs_commit_transaction(trans, root); ret = btrfs_commit_transaction(trans, root);
BUG_ON(ret); BUG_ON(ret);
/* run commit again to drop the original snapshot */ /* run commit again to drop the original snapshot */
trans = btrfs_join_transaction(root, 1); trans = btrfs_join_transaction(root);
if (IS_ERR(trans)) if (IS_ERR(trans))
return PTR_ERR(trans); return PTR_ERR(trans);
btrfs_commit_transaction(trans, root); btrfs_commit_transaction(trans, root);
...@@ -3024,10 +3024,13 @@ static int btrfs_cleanup_transaction(struct btrfs_root *root) ...@@ -3024,10 +3024,13 @@ static int btrfs_cleanup_transaction(struct btrfs_root *root)
WARN_ON(1); WARN_ON(1);
mutex_lock(&root->fs_info->trans_mutex);
mutex_lock(&root->fs_info->transaction_kthread_mutex); mutex_lock(&root->fs_info->transaction_kthread_mutex);
spin_lock(&root->fs_info->trans_lock);
list_splice_init(&root->fs_info->trans_list, &list); list_splice_init(&root->fs_info->trans_list, &list);
root->fs_info->trans_no_join = 1;
spin_unlock(&root->fs_info->trans_lock);
while (!list_empty(&list)) { while (!list_empty(&list)) {
t = list_entry(list.next, struct btrfs_transaction, list); t = list_entry(list.next, struct btrfs_transaction, list);
if (!t) if (!t)
...@@ -3052,23 +3055,18 @@ static int btrfs_cleanup_transaction(struct btrfs_root *root) ...@@ -3052,23 +3055,18 @@ static int btrfs_cleanup_transaction(struct btrfs_root *root)
t->blocked = 0; t->blocked = 0;
if (waitqueue_active(&root->fs_info->transaction_wait)) if (waitqueue_active(&root->fs_info->transaction_wait))
wake_up(&root->fs_info->transaction_wait); wake_up(&root->fs_info->transaction_wait);
mutex_unlock(&root->fs_info->trans_mutex);
mutex_lock(&root->fs_info->trans_mutex);
t->commit_done = 1; t->commit_done = 1;
if (waitqueue_active(&t->commit_wait)) if (waitqueue_active(&t->commit_wait))
wake_up(&t->commit_wait); wake_up(&t->commit_wait);
mutex_unlock(&root->fs_info->trans_mutex);
mutex_lock(&root->fs_info->trans_mutex);
btrfs_destroy_pending_snapshots(t); btrfs_destroy_pending_snapshots(t);
btrfs_destroy_delalloc_inodes(root); btrfs_destroy_delalloc_inodes(root);
spin_lock(&root->fs_info->new_trans_lock); spin_lock(&root->fs_info->trans_lock);
root->fs_info->running_transaction = NULL; root->fs_info->running_transaction = NULL;
spin_unlock(&root->fs_info->new_trans_lock); spin_unlock(&root->fs_info->trans_lock);
btrfs_destroy_marked_extents(root, &t->dirty_pages, btrfs_destroy_marked_extents(root, &t->dirty_pages,
EXTENT_DIRTY); EXTENT_DIRTY);
...@@ -3082,8 +3080,10 @@ static int btrfs_cleanup_transaction(struct btrfs_root *root) ...@@ -3082,8 +3080,10 @@ static int btrfs_cleanup_transaction(struct btrfs_root *root)
kmem_cache_free(btrfs_transaction_cachep, t); kmem_cache_free(btrfs_transaction_cachep, t);
} }
spin_lock(&root->fs_info->trans_lock);
root->fs_info->trans_no_join = 0;
spin_unlock(&root->fs_info->trans_lock);
mutex_unlock(&root->fs_info->transaction_kthread_mutex); mutex_unlock(&root->fs_info->transaction_kthread_mutex);
mutex_unlock(&root->fs_info->trans_mutex);
return 0; return 0;
} }
......
...@@ -348,7 +348,7 @@ static int caching_kthread(void *data) ...@@ -348,7 +348,7 @@ static int caching_kthread(void *data)
*/ */
path->skip_locking = 1; path->skip_locking = 1;
path->search_commit_root = 1; path->search_commit_root = 1;
path->reada = 2; path->reada = 1;
key.objectid = last; key.objectid = last;
key.offset = 0; key.offset = 0;
...@@ -366,8 +366,7 @@ static int caching_kthread(void *data) ...@@ -366,8 +366,7 @@ static int caching_kthread(void *data)
nritems = btrfs_header_nritems(leaf); nritems = btrfs_header_nritems(leaf);
while (1) { while (1) {
smp_mb(); if (btrfs_fs_closing(fs_info) > 1) {
if (fs_info->closing > 1) {
last = (u64)-1; last = (u64)-1;
break; break;
} }
...@@ -379,15 +378,18 @@ static int caching_kthread(void *data) ...@@ -379,15 +378,18 @@ static int caching_kthread(void *data)
if (ret) if (ret)
break; break;
caching_ctl->progress = last; if (need_resched() ||
btrfs_release_path(path); btrfs_next_leaf(extent_root, path)) {
up_read(&fs_info->extent_commit_sem); caching_ctl->progress = last;
mutex_unlock(&caching_ctl->mutex); btrfs_release_path(path);
if (btrfs_transaction_in_commit(fs_info)) up_read(&fs_info->extent_commit_sem);
schedule_timeout(1); mutex_unlock(&caching_ctl->mutex);
else
cond_resched(); cond_resched();
goto again; goto again;
}
leaf = path->nodes[0];
nritems = btrfs_header_nritems(leaf);
continue;
} }
if (key.objectid < block_group->key.objectid) { if (key.objectid < block_group->key.objectid) {
...@@ -3065,7 +3067,7 @@ int btrfs_check_data_free_space(struct inode *inode, u64 bytes) ...@@ -3065,7 +3067,7 @@ int btrfs_check_data_free_space(struct inode *inode, u64 bytes)
spin_unlock(&data_sinfo->lock); spin_unlock(&data_sinfo->lock);
alloc: alloc:
alloc_target = btrfs_get_alloc_profile(root, 1); alloc_target = btrfs_get_alloc_profile(root, 1);
trans = btrfs_join_transaction(root, 1); trans = btrfs_join_transaction(root);
if (IS_ERR(trans)) if (IS_ERR(trans))
return PTR_ERR(trans); return PTR_ERR(trans);
...@@ -3091,9 +3093,10 @@ int btrfs_check_data_free_space(struct inode *inode, u64 bytes) ...@@ -3091,9 +3093,10 @@ int btrfs_check_data_free_space(struct inode *inode, u64 bytes)
/* commit the current transaction and try again */ /* commit the current transaction and try again */
commit_trans: commit_trans:
if (!committed && !root->fs_info->open_ioctl_trans) { if (!committed &&
!atomic_read(&root->fs_info->open_ioctl_trans)) {
committed = 1; committed = 1;
trans = btrfs_join_transaction(root, 1); trans = btrfs_join_transaction(root);
if (IS_ERR(trans)) if (IS_ERR(trans))
return PTR_ERR(trans); return PTR_ERR(trans);
ret = btrfs_commit_transaction(trans, root); ret = btrfs_commit_transaction(trans, root);
...@@ -3472,7 +3475,7 @@ static int reserve_metadata_bytes(struct btrfs_trans_handle *trans, ...@@ -3472,7 +3475,7 @@ static int reserve_metadata_bytes(struct btrfs_trans_handle *trans,
goto out; goto out;
ret = -ENOSPC; ret = -ENOSPC;
trans = btrfs_join_transaction(root, 1); trans = btrfs_join_transaction(root);
if (IS_ERR(trans)) if (IS_ERR(trans))
goto out; goto out;
ret = btrfs_commit_transaction(trans, root); ret = btrfs_commit_transaction(trans, root);
...@@ -3699,7 +3702,7 @@ int btrfs_block_rsv_check(struct btrfs_trans_handle *trans, ...@@ -3699,7 +3702,7 @@ int btrfs_block_rsv_check(struct btrfs_trans_handle *trans,
if (trans) if (trans)
return -EAGAIN; return -EAGAIN;
trans = btrfs_join_transaction(root, 1); trans = btrfs_join_transaction(root);
BUG_ON(IS_ERR(trans)); BUG_ON(IS_ERR(trans));
ret = btrfs_commit_transaction(trans, root); ret = btrfs_commit_transaction(trans, root);
return 0; return 0;
...@@ -3837,6 +3840,37 @@ static void release_global_block_rsv(struct btrfs_fs_info *fs_info) ...@@ -3837,6 +3840,37 @@ static void release_global_block_rsv(struct btrfs_fs_info *fs_info)
WARN_ON(fs_info->chunk_block_rsv.reserved > 0); WARN_ON(fs_info->chunk_block_rsv.reserved > 0);
} }
int btrfs_truncate_reserve_metadata(struct btrfs_trans_handle *trans,
struct btrfs_root *root,
struct btrfs_block_rsv *rsv)
{
struct btrfs_block_rsv *trans_rsv = &root->fs_info->trans_block_rsv;
u64 num_bytes;
int ret;
/*
* Truncate should be freeing data, but give us 2 items just in case it
* needs to use some space. We may want to be smarter about this in the
* future.
*/
num_bytes = btrfs_calc_trans_metadata_size(root, 2);
/* We already have enough bytes, just return */
if (rsv->reserved >= num_bytes)
return 0;
num_bytes -= rsv->reserved;
/*
* You should have reserved enough space before hand to do this, so this
* should not fail.
*/
ret = block_rsv_migrate_bytes(trans_rsv, rsv, num_bytes);
BUG_ON(ret);
return 0;
}
int btrfs_trans_reserve_metadata(struct btrfs_trans_handle *trans, int btrfs_trans_reserve_metadata(struct btrfs_trans_handle *trans,
struct btrfs_root *root, struct btrfs_root *root,
int num_items) int num_items)
...@@ -3877,23 +3911,18 @@ int btrfs_orphan_reserve_metadata(struct btrfs_trans_handle *trans, ...@@ -3877,23 +3911,18 @@ int btrfs_orphan_reserve_metadata(struct btrfs_trans_handle *trans,
struct btrfs_block_rsv *dst_rsv = root->orphan_block_rsv; struct btrfs_block_rsv *dst_rsv = root->orphan_block_rsv;
/* /*
* one for deleting orphan item, one for updating inode and * We need to hold space in order to delete our orphan item once we've
* two for calling btrfs_truncate_inode_items. * added it, so this takes the reservation so we can release it later
* * when we are truly done with the orphan item.
* btrfs_truncate_inode_items is a delete operation, it frees
* more space than it uses in most cases. So two units of
* metadata space should be enough for calling it many times.
* If all of the metadata space is used, we can commit
* transaction and use space it freed.
*/ */
u64 num_bytes = btrfs_calc_trans_metadata_size(root, 4); u64 num_bytes = btrfs_calc_trans_metadata_size(root, 1);
return block_rsv_migrate_bytes(src_rsv, dst_rsv, num_bytes); return block_rsv_migrate_bytes(src_rsv, dst_rsv, num_bytes);
} }
void btrfs_orphan_release_metadata(struct inode *inode) void btrfs_orphan_release_metadata(struct inode *inode)
{ {
struct btrfs_root *root = BTRFS_I(inode)->root; struct btrfs_root *root = BTRFS_I(inode)->root;
u64 num_bytes = btrfs_calc_trans_metadata_size(root, 4); u64 num_bytes = btrfs_calc_trans_metadata_size(root, 1);
btrfs_block_rsv_release(root, root->orphan_block_rsv, num_bytes); btrfs_block_rsv_release(root, root->orphan_block_rsv, num_bytes);
} }
...@@ -4987,6 +5016,15 @@ static noinline int find_free_extent(struct btrfs_trans_handle *trans, ...@@ -4987,6 +5016,15 @@ static noinline int find_free_extent(struct btrfs_trans_handle *trans,
if (unlikely(block_group->ro)) if (unlikely(block_group->ro))
goto loop; goto loop;
spin_lock(&block_group->free_space_ctl->tree_lock);
if (cached &&
block_group->free_space_ctl->free_space <
num_bytes + empty_size) {
spin_unlock(&block_group->free_space_ctl->tree_lock);
goto loop;
}
spin_unlock(&block_group->free_space_ctl->tree_lock);
/* /*
* Ok we want to try and use the cluster allocator, so lets look * Ok we want to try and use the cluster allocator, so lets look
* there, unless we are on LOOP_NO_EMPTY_SIZE, since we will * there, unless we are on LOOP_NO_EMPTY_SIZE, since we will
...@@ -5150,6 +5188,7 @@ static noinline int find_free_extent(struct btrfs_trans_handle *trans, ...@@ -5150,6 +5188,7 @@ static noinline int find_free_extent(struct btrfs_trans_handle *trans,
btrfs_add_free_space(block_group, offset, btrfs_add_free_space(block_group, offset,
search_start - offset); search_start - offset);
BUG_ON(offset > search_start); BUG_ON(offset > search_start);
btrfs_put_block_group(block_group);
break; break;
loop: loop:
failed_cluster_refill = false; failed_cluster_refill = false;
...@@ -5242,14 +5281,7 @@ static noinline int find_free_extent(struct btrfs_trans_handle *trans, ...@@ -5242,14 +5281,7 @@ static noinline int find_free_extent(struct btrfs_trans_handle *trans,
ret = -ENOSPC; ret = -ENOSPC;
} else if (!ins->objectid) { } else if (!ins->objectid) {
ret = -ENOSPC; ret = -ENOSPC;
} } else if (ins->objectid) {
/* we found what we needed */
if (ins->objectid) {
if (!(data & BTRFS_BLOCK_GROUP_DATA))
trans->block_group = block_group->key.objectid;
btrfs_put_block_group(block_group);
ret = 0; ret = 0;
} }
...@@ -6526,7 +6558,7 @@ int btrfs_set_block_group_ro(struct btrfs_root *root, ...@@ -6526,7 +6558,7 @@ int btrfs_set_block_group_ro(struct btrfs_root *root,
BUG_ON(cache->ro); BUG_ON(cache->ro);
trans = btrfs_join_transaction(root, 1); trans = btrfs_join_transaction(root);
BUG_ON(IS_ERR(trans)); BUG_ON(IS_ERR(trans));
alloc_flags = update_block_group_flags(root, cache->flags); alloc_flags = update_block_group_flags(root, cache->flags);
...@@ -6882,6 +6914,7 @@ int btrfs_read_block_groups(struct btrfs_root *root) ...@@ -6882,6 +6914,7 @@ int btrfs_read_block_groups(struct btrfs_root *root)
path = btrfs_alloc_path(); path = btrfs_alloc_path();
if (!path) if (!path)
return -ENOMEM; return -ENOMEM;
path->reada = 1;
cache_gen = btrfs_super_cache_generation(&root->fs_info->super_copy); cache_gen = btrfs_super_cache_generation(&root->fs_info->super_copy);
if (cache_gen != 0 && if (cache_gen != 0 &&
......
...@@ -1476,7 +1476,7 @@ u64 count_range_bits(struct extent_io_tree *tree, ...@@ -1476,7 +1476,7 @@ u64 count_range_bits(struct extent_io_tree *tree,
if (total_bytes >= max_bytes) if (total_bytes >= max_bytes)
break; break;
if (!found) { if (!found) {
*start = state->start; *start = max(cur_start, state->start);
found = 1; found = 1;
} }
last = state->end; last = state->end;
......
...@@ -129,7 +129,7 @@ int btrfs_add_inode_defrag(struct btrfs_trans_handle *trans, ...@@ -129,7 +129,7 @@ int btrfs_add_inode_defrag(struct btrfs_trans_handle *trans,
if (!btrfs_test_opt(root, AUTO_DEFRAG)) if (!btrfs_test_opt(root, AUTO_DEFRAG))
return 0; return 0;
if (root->fs_info->closing) if (btrfs_fs_closing(root->fs_info))
return 0; return 0;
if (BTRFS_I(inode)->in_defrag) if (BTRFS_I(inode)->in_defrag)
...@@ -144,7 +144,7 @@ int btrfs_add_inode_defrag(struct btrfs_trans_handle *trans, ...@@ -144,7 +144,7 @@ int btrfs_add_inode_defrag(struct btrfs_trans_handle *trans,
if (!defrag) if (!defrag)
return -ENOMEM; return -ENOMEM;
defrag->ino = inode->i_ino; defrag->ino = btrfs_ino(inode);
defrag->transid = transid; defrag->transid = transid;
defrag->root = root->root_key.objectid; defrag->root = root->root_key.objectid;
...@@ -229,7 +229,7 @@ int btrfs_run_defrag_inodes(struct btrfs_fs_info *fs_info) ...@@ -229,7 +229,7 @@ int btrfs_run_defrag_inodes(struct btrfs_fs_info *fs_info)
first_ino = defrag->ino + 1; first_ino = defrag->ino + 1;
rb_erase(&defrag->rb_node, &fs_info->defrag_inodes); rb_erase(&defrag->rb_node, &fs_info->defrag_inodes);
if (fs_info->closing) if (btrfs_fs_closing(fs_info))
goto next_free; goto next_free;
spin_unlock(&fs_info->defrag_inodes_lock); spin_unlock(&fs_info->defrag_inodes_lock);
...@@ -1480,14 +1480,12 @@ int btrfs_sync_file(struct file *file, int datasync) ...@@ -1480,14 +1480,12 @@ int btrfs_sync_file(struct file *file, int datasync)
* the current transaction, we can bail out now without any * the current transaction, we can bail out now without any
* syncing * syncing
*/ */
mutex_lock(&root->fs_info->trans_mutex); smp_mb();
if (BTRFS_I(inode)->last_trans <= if (BTRFS_I(inode)->last_trans <=
root->fs_info->last_trans_committed) { root->fs_info->last_trans_committed) {
BTRFS_I(inode)->last_trans = 0; BTRFS_I(inode)->last_trans = 0;
mutex_unlock(&root->fs_info->trans_mutex);
goto out; goto out;
} }
mutex_unlock(&root->fs_info->trans_mutex);
/* /*
* ok we haven't committed the transaction yet, lets do a commit * ok we haven't committed the transaction yet, lets do a commit
......
...@@ -98,7 +98,7 @@ struct inode *lookup_free_space_inode(struct btrfs_root *root, ...@@ -98,7 +98,7 @@ struct inode *lookup_free_space_inode(struct btrfs_root *root,
return inode; return inode;
spin_lock(&block_group->lock); spin_lock(&block_group->lock);
if (!root->fs_info->closing) { if (!btrfs_fs_closing(root->fs_info)) {
block_group->inode = igrab(inode); block_group->inode = igrab(inode);
block_group->iref = 1; block_group->iref = 1;
} }
...@@ -402,7 +402,14 @@ int __load_free_space_cache(struct btrfs_root *root, struct inode *inode, ...@@ -402,7 +402,14 @@ int __load_free_space_cache(struct btrfs_root *root, struct inode *inode,
spin_lock(&ctl->tree_lock); spin_lock(&ctl->tree_lock);
ret = link_free_space(ctl, e); ret = link_free_space(ctl, e);
spin_unlock(&ctl->tree_lock); spin_unlock(&ctl->tree_lock);
BUG_ON(ret); if (ret) {
printk(KERN_ERR "Duplicate entries in "
"free space cache, dumping\n");
kunmap(page);
unlock_page(page);
page_cache_release(page);
goto free_cache;
}
} else { } else {
e->bitmap = kzalloc(PAGE_CACHE_SIZE, GFP_NOFS); e->bitmap = kzalloc(PAGE_CACHE_SIZE, GFP_NOFS);
if (!e->bitmap) { if (!e->bitmap) {
...@@ -419,6 +426,14 @@ int __load_free_space_cache(struct btrfs_root *root, struct inode *inode, ...@@ -419,6 +426,14 @@ int __load_free_space_cache(struct btrfs_root *root, struct inode *inode,
ctl->op->recalc_thresholds(ctl); ctl->op->recalc_thresholds(ctl);
spin_unlock(&ctl->tree_lock); spin_unlock(&ctl->tree_lock);
list_add_tail(&e->list, &bitmaps); list_add_tail(&e->list, &bitmaps);
if (ret) {
printk(KERN_ERR "Duplicate entries in "
"free space cache, dumping\n");
kunmap(page);
unlock_page(page);
page_cache_release(page);
goto free_cache;
}
} }
num_entries--; num_entries--;
...@@ -478,8 +493,7 @@ int load_free_space_cache(struct btrfs_fs_info *fs_info, ...@@ -478,8 +493,7 @@ int load_free_space_cache(struct btrfs_fs_info *fs_info,
* If we're unmounting then just return, since this does a search on the * If we're unmounting then just return, since this does a search on the
* normal root and not the commit root and we could deadlock. * normal root and not the commit root and we could deadlock.
*/ */
smp_mb(); if (btrfs_fs_closing(fs_info))
if (fs_info->closing)
return 0; return 0;
/* /*
...@@ -575,10 +589,25 @@ int __btrfs_write_out_cache(struct btrfs_root *root, struct inode *inode, ...@@ -575,10 +589,25 @@ int __btrfs_write_out_cache(struct btrfs_root *root, struct inode *inode,
num_pages = (i_size_read(inode) + PAGE_CACHE_SIZE - 1) >> num_pages = (i_size_read(inode) + PAGE_CACHE_SIZE - 1) >>
PAGE_CACHE_SHIFT; PAGE_CACHE_SHIFT;
/* Since the first page has all of our checksums and our generation we
* need to calculate the offset into the page that we can start writing
* our entries.
*/
first_page_offset = (sizeof(u32) * num_pages) + sizeof(u64);
filemap_write_and_wait(inode->i_mapping); filemap_write_and_wait(inode->i_mapping);
btrfs_wait_ordered_range(inode, inode->i_size & btrfs_wait_ordered_range(inode, inode->i_size &
~(root->sectorsize - 1), (u64)-1); ~(root->sectorsize - 1), (u64)-1);
/* make sure we don't overflow that first page */
if (first_page_offset + sizeof(struct btrfs_free_space_entry) >= PAGE_CACHE_SIZE) {
/* this is really the same as running out of space, where we also return 0 */
printk(KERN_CRIT "Btrfs: free space cache was too big for the crc page\n");
ret = 0;
goto out_update;
}
/* We need a checksum per page. */ /* We need a checksum per page. */
crc = checksums = kzalloc(sizeof(u32) * num_pages, GFP_NOFS); crc = checksums = kzalloc(sizeof(u32) * num_pages, GFP_NOFS);
if (!crc) if (!crc)
...@@ -590,12 +619,6 @@ int __btrfs_write_out_cache(struct btrfs_root *root, struct inode *inode, ...@@ -590,12 +619,6 @@ int __btrfs_write_out_cache(struct btrfs_root *root, struct inode *inode,
return -1; return -1;
} }
/* Since the first page has all of our checksums and our generation we
* need to calculate the offset into the page that we can start writing
* our entries.
*/
first_page_offset = (sizeof(u32) * num_pages) + sizeof(u64);
/* Get the cluster for this block_group if it exists */ /* Get the cluster for this block_group if it exists */
if (block_group && !list_empty(&block_group->cluster_list)) if (block_group && !list_empty(&block_group->cluster_list))
cluster = list_entry(block_group->cluster_list.next, cluster = list_entry(block_group->cluster_list.next,
...@@ -857,12 +880,14 @@ int __btrfs_write_out_cache(struct btrfs_root *root, struct inode *inode, ...@@ -857,12 +880,14 @@ int __btrfs_write_out_cache(struct btrfs_root *root, struct inode *inode,
ret = 1; ret = 1;
out_free: out_free:
kfree(checksums);
kfree(pages);
out_update:
if (ret != 1) { if (ret != 1) {
invalidate_inode_pages2_range(inode->i_mapping, 0, index); invalidate_inode_pages2_range(inode->i_mapping, 0, index);
BTRFS_I(inode)->generation = 0; BTRFS_I(inode)->generation = 0;
} }
kfree(checksums);
kfree(pages);
btrfs_update_inode(trans, root, inode); btrfs_update_inode(trans, root, inode);
return ret; return ret;
} }
...@@ -963,10 +988,16 @@ static int tree_insert_offset(struct rb_root *root, u64 offset, ...@@ -963,10 +988,16 @@ static int tree_insert_offset(struct rb_root *root, u64 offset,
* logically. * logically.
*/ */
if (bitmap) { if (bitmap) {
WARN_ON(info->bitmap); if (info->bitmap) {
WARN_ON_ONCE(1);
return -EEXIST;
}
p = &(*p)->rb_right; p = &(*p)->rb_right;
} else { } else {
WARN_ON(!info->bitmap); if (!info->bitmap) {
WARN_ON_ONCE(1);
return -EEXIST;
}
p = &(*p)->rb_left; p = &(*p)->rb_left;
} }
} }
...@@ -2481,7 +2512,7 @@ struct inode *lookup_free_ino_inode(struct btrfs_root *root, ...@@ -2481,7 +2512,7 @@ struct inode *lookup_free_ino_inode(struct btrfs_root *root,
return inode; return inode;
spin_lock(&root->cache_lock); spin_lock(&root->cache_lock);
if (!root->fs_info->closing) if (!btrfs_fs_closing(root->fs_info))
root->cache_inode = igrab(inode); root->cache_inode = igrab(inode);
spin_unlock(&root->cache_lock); spin_unlock(&root->cache_lock);
...@@ -2504,12 +2535,14 @@ int load_free_ino_cache(struct btrfs_fs_info *fs_info, struct btrfs_root *root) ...@@ -2504,12 +2535,14 @@ int load_free_ino_cache(struct btrfs_fs_info *fs_info, struct btrfs_root *root)
int ret = 0; int ret = 0;
u64 root_gen = btrfs_root_generation(&root->root_item); u64 root_gen = btrfs_root_generation(&root->root_item);
if (!btrfs_test_opt(root, INODE_MAP_CACHE))
return 0;
/* /*
* If we're unmounting then just return, since this does a search on the * If we're unmounting then just return, since this does a search on the
* normal root and not the commit root and we could deadlock. * normal root and not the commit root and we could deadlock.
*/ */
smp_mb(); if (btrfs_fs_closing(fs_info))
if (fs_info->closing)
return 0; return 0;
path = btrfs_alloc_path(); path = btrfs_alloc_path();
...@@ -2543,6 +2576,9 @@ int btrfs_write_out_ino_cache(struct btrfs_root *root, ...@@ -2543,6 +2576,9 @@ int btrfs_write_out_ino_cache(struct btrfs_root *root,
struct inode *inode; struct inode *inode;
int ret; int ret;
if (!btrfs_test_opt(root, INODE_MAP_CACHE))
return 0;
inode = lookup_free_ino_inode(root, path); inode = lookup_free_ino_inode(root, path);
if (IS_ERR(inode)) if (IS_ERR(inode))
return 0; return 0;
......
...@@ -38,6 +38,9 @@ static int caching_kthread(void *data) ...@@ -38,6 +38,9 @@ static int caching_kthread(void *data)
int slot; int slot;
int ret; int ret;
if (!btrfs_test_opt(root, INODE_MAP_CACHE))
return 0;
path = btrfs_alloc_path(); path = btrfs_alloc_path();
if (!path) if (!path)
return -ENOMEM; return -ENOMEM;
...@@ -59,8 +62,7 @@ static int caching_kthread(void *data) ...@@ -59,8 +62,7 @@ static int caching_kthread(void *data)
goto out; goto out;
while (1) { while (1) {
smp_mb(); if (btrfs_fs_closing(fs_info))
if (fs_info->closing)
goto out; goto out;
leaf = path->nodes[0]; leaf = path->nodes[0];
...@@ -141,6 +143,9 @@ static void start_caching(struct btrfs_root *root) ...@@ -141,6 +143,9 @@ static void start_caching(struct btrfs_root *root)
int ret; int ret;
u64 objectid; u64 objectid;
if (!btrfs_test_opt(root, INODE_MAP_CACHE))
return;
spin_lock(&root->cache_lock); spin_lock(&root->cache_lock);
if (root->cached != BTRFS_CACHE_NO) { if (root->cached != BTRFS_CACHE_NO) {
spin_unlock(&root->cache_lock); spin_unlock(&root->cache_lock);
...@@ -178,6 +183,9 @@ static void start_caching(struct btrfs_root *root) ...@@ -178,6 +183,9 @@ static void start_caching(struct btrfs_root *root)
int btrfs_find_free_ino(struct btrfs_root *root, u64 *objectid) int btrfs_find_free_ino(struct btrfs_root *root, u64 *objectid)
{ {
if (!btrfs_test_opt(root, INODE_MAP_CACHE))
return btrfs_find_free_objectid(root, objectid);
again: again:
*objectid = btrfs_find_ino_for_alloc(root); *objectid = btrfs_find_ino_for_alloc(root);
...@@ -201,6 +209,10 @@ void btrfs_return_ino(struct btrfs_root *root, u64 objectid) ...@@ -201,6 +209,10 @@ void btrfs_return_ino(struct btrfs_root *root, u64 objectid)
{ {
struct btrfs_free_space_ctl *ctl = root->free_ino_ctl; struct btrfs_free_space_ctl *ctl = root->free_ino_ctl;
struct btrfs_free_space_ctl *pinned = root->free_ino_pinned; struct btrfs_free_space_ctl *pinned = root->free_ino_pinned;
if (!btrfs_test_opt(root, INODE_MAP_CACHE))
return;
again: again:
if (root->cached == BTRFS_CACHE_FINISHED) { if (root->cached == BTRFS_CACHE_FINISHED) {
__btrfs_add_free_space(ctl, objectid, 1); __btrfs_add_free_space(ctl, objectid, 1);
...@@ -250,6 +262,9 @@ void btrfs_unpin_free_ino(struct btrfs_root *root) ...@@ -250,6 +262,9 @@ void btrfs_unpin_free_ino(struct btrfs_root *root)
struct rb_node *n; struct rb_node *n;
u64 count; u64 count;
if (!btrfs_test_opt(root, INODE_MAP_CACHE))
return;
while (1) { while (1) {
n = rb_first(rbroot); n = rb_first(rbroot);
if (!n) if (!n)
...@@ -388,9 +403,24 @@ int btrfs_save_ino_cache(struct btrfs_root *root, ...@@ -388,9 +403,24 @@ int btrfs_save_ino_cache(struct btrfs_root *root,
int prealloc; int prealloc;
bool retry = false; bool retry = false;
/* only fs tree and subvol/snap needs ino cache */
if (root->root_key.objectid != BTRFS_FS_TREE_OBJECTID &&
(root->root_key.objectid < BTRFS_FIRST_FREE_OBJECTID ||
root->root_key.objectid > BTRFS_LAST_FREE_OBJECTID))
return 0;
/* Don't save inode cache if we are deleting this root */
if (btrfs_root_refs(&root->root_item) == 0 &&
root != root->fs_info->tree_root)
return 0;
if (!btrfs_test_opt(root, INODE_MAP_CACHE))
return 0;
path = btrfs_alloc_path(); path = btrfs_alloc_path();
if (!path) if (!path)
return -ENOMEM; return -ENOMEM;
again: again:
inode = lookup_free_ino_inode(root, path); inode = lookup_free_ino_inode(root, path);
if (IS_ERR(inode) && PTR_ERR(inode) != -ENOENT) { if (IS_ERR(inode) && PTR_ERR(inode) != -ENOENT) {
......
This diff is collapsed.
...@@ -243,7 +243,7 @@ static int btrfs_ioctl_setflags(struct file *file, void __user *arg) ...@@ -243,7 +243,7 @@ static int btrfs_ioctl_setflags(struct file *file, void __user *arg)
ip->flags &= ~(BTRFS_INODE_COMPRESS | BTRFS_INODE_NOCOMPRESS); ip->flags &= ~(BTRFS_INODE_COMPRESS | BTRFS_INODE_NOCOMPRESS);
} }
trans = btrfs_join_transaction(root, 1); trans = btrfs_join_transaction(root);
BUG_ON(IS_ERR(trans)); BUG_ON(IS_ERR(trans));
ret = btrfs_update_inode(trans, root, inode); ret = btrfs_update_inode(trans, root, inode);
...@@ -414,8 +414,7 @@ static noinline int create_subvol(struct btrfs_root *root, ...@@ -414,8 +414,7 @@ static noinline int create_subvol(struct btrfs_root *root,
btrfs_record_root_in_trans(trans, new_root); btrfs_record_root_in_trans(trans, new_root);
ret = btrfs_create_subvol_root(trans, new_root, new_dirid, ret = btrfs_create_subvol_root(trans, new_root, new_dirid);
BTRFS_I(dir)->block_group);
/* /*
* insert the directory item * insert the directory item
*/ */
...@@ -707,16 +706,17 @@ static int find_new_extents(struct btrfs_root *root, ...@@ -707,16 +706,17 @@ static int find_new_extents(struct btrfs_root *root,
struct btrfs_file_extent_item *extent; struct btrfs_file_extent_item *extent;
int type; int type;
int ret; int ret;
u64 ino = btrfs_ino(inode);
path = btrfs_alloc_path(); path = btrfs_alloc_path();
if (!path) if (!path)
return -ENOMEM; return -ENOMEM;
min_key.objectid = inode->i_ino; min_key.objectid = ino;
min_key.type = BTRFS_EXTENT_DATA_KEY; min_key.type = BTRFS_EXTENT_DATA_KEY;
min_key.offset = *off; min_key.offset = *off;
max_key.objectid = inode->i_ino; max_key.objectid = ino;
max_key.type = (u8)-1; max_key.type = (u8)-1;
max_key.offset = (u64)-1; max_key.offset = (u64)-1;
...@@ -727,7 +727,7 @@ static int find_new_extents(struct btrfs_root *root, ...@@ -727,7 +727,7 @@ static int find_new_extents(struct btrfs_root *root,
path, 0, newer_than); path, 0, newer_than);
if (ret != 0) if (ret != 0)
goto none; goto none;
if (min_key.objectid != inode->i_ino) if (min_key.objectid != ino)
goto none; goto none;
if (min_key.type != BTRFS_EXTENT_DATA_KEY) if (min_key.type != BTRFS_EXTENT_DATA_KEY)
goto none; goto none;
...@@ -2489,12 +2489,10 @@ static long btrfs_ioctl_trans_start(struct file *file) ...@@ -2489,12 +2489,10 @@ static long btrfs_ioctl_trans_start(struct file *file)
if (ret) if (ret)
goto out; goto out;
mutex_lock(&root->fs_info->trans_mutex); atomic_inc(&root->fs_info->open_ioctl_trans);
root->fs_info->open_ioctl_trans++;
mutex_unlock(&root->fs_info->trans_mutex);
ret = -ENOMEM; ret = -ENOMEM;
trans = btrfs_start_ioctl_transaction(root, 0); trans = btrfs_start_ioctl_transaction(root);
if (IS_ERR(trans)) if (IS_ERR(trans))
goto out_drop; goto out_drop;
...@@ -2502,9 +2500,7 @@ static long btrfs_ioctl_trans_start(struct file *file) ...@@ -2502,9 +2500,7 @@ static long btrfs_ioctl_trans_start(struct file *file)
return 0; return 0;
out_drop: out_drop:
mutex_lock(&root->fs_info->trans_mutex); atomic_dec(&root->fs_info->open_ioctl_trans);
root->fs_info->open_ioctl_trans--;
mutex_unlock(&root->fs_info->trans_mutex);
mnt_drop_write(file->f_path.mnt); mnt_drop_write(file->f_path.mnt);
out: out:
return ret; return ret;
...@@ -2738,9 +2734,7 @@ long btrfs_ioctl_trans_end(struct file *file) ...@@ -2738,9 +2734,7 @@ long btrfs_ioctl_trans_end(struct file *file)
btrfs_end_transaction(trans, root); btrfs_end_transaction(trans, root);
mutex_lock(&root->fs_info->trans_mutex); atomic_dec(&root->fs_info->open_ioctl_trans);
root->fs_info->open_ioctl_trans--;
mutex_unlock(&root->fs_info->trans_mutex);
mnt_drop_write(file->f_path.mnt); mnt_drop_write(file->f_path.mnt);
return 0; return 0;
......
...@@ -677,6 +677,8 @@ struct backref_node *build_backref_tree(struct reloc_control *rc, ...@@ -677,6 +677,8 @@ struct backref_node *build_backref_tree(struct reloc_control *rc,
err = -ENOMEM; err = -ENOMEM;
goto out; goto out;
} }
path1->reada = 1;
path2->reada = 2;
node = alloc_backref_node(cache); node = alloc_backref_node(cache);
if (!node) { if (!node) {
...@@ -1999,6 +2001,7 @@ static noinline_for_stack int merge_reloc_root(struct reloc_control *rc, ...@@ -1999,6 +2001,7 @@ static noinline_for_stack int merge_reloc_root(struct reloc_control *rc,
path = btrfs_alloc_path(); path = btrfs_alloc_path();
if (!path) if (!path)
return -ENOMEM; return -ENOMEM;
path->reada = 1;
reloc_root = root->reloc_root; reloc_root = root->reloc_root;
root_item = &reloc_root->root_item; root_item = &reloc_root->root_item;
...@@ -2139,10 +2142,10 @@ int prepare_to_merge(struct reloc_control *rc, int err) ...@@ -2139,10 +2142,10 @@ int prepare_to_merge(struct reloc_control *rc, int err)
u64 num_bytes = 0; u64 num_bytes = 0;
int ret; int ret;
mutex_lock(&root->fs_info->trans_mutex); spin_lock(&root->fs_info->trans_lock);
rc->merging_rsv_size += root->nodesize * (BTRFS_MAX_LEVEL - 1) * 2; rc->merging_rsv_size += root->nodesize * (BTRFS_MAX_LEVEL - 1) * 2;
rc->merging_rsv_size += rc->nodes_relocated * 2; rc->merging_rsv_size += rc->nodes_relocated * 2;
mutex_unlock(&root->fs_info->trans_mutex); spin_unlock(&root->fs_info->trans_lock);
again: again:
if (!err) { if (!err) {
num_bytes = rc->merging_rsv_size; num_bytes = rc->merging_rsv_size;
...@@ -2152,7 +2155,7 @@ int prepare_to_merge(struct reloc_control *rc, int err) ...@@ -2152,7 +2155,7 @@ int prepare_to_merge(struct reloc_control *rc, int err)
err = ret; err = ret;
} }
trans = btrfs_join_transaction(rc->extent_root, 1); trans = btrfs_join_transaction(rc->extent_root);
if (IS_ERR(trans)) { if (IS_ERR(trans)) {
if (!err) if (!err)
btrfs_block_rsv_release(rc->extent_root, btrfs_block_rsv_release(rc->extent_root,
...@@ -2211,9 +2214,9 @@ int merge_reloc_roots(struct reloc_control *rc) ...@@ -2211,9 +2214,9 @@ int merge_reloc_roots(struct reloc_control *rc)
int ret; int ret;
again: again:
root = rc->extent_root; root = rc->extent_root;
mutex_lock(&root->fs_info->trans_mutex); spin_lock(&root->fs_info->trans_lock);
list_splice_init(&rc->reloc_roots, &reloc_roots); list_splice_init(&rc->reloc_roots, &reloc_roots);
mutex_unlock(&root->fs_info->trans_mutex); spin_unlock(&root->fs_info->trans_lock);
while (!list_empty(&reloc_roots)) { while (!list_empty(&reloc_roots)) {
found = 1; found = 1;
...@@ -3236,7 +3239,7 @@ static int delete_block_group_cache(struct btrfs_fs_info *fs_info, ...@@ -3236,7 +3239,7 @@ static int delete_block_group_cache(struct btrfs_fs_info *fs_info,
goto out; goto out;
} }
trans = btrfs_join_transaction(root, 0); trans = btrfs_join_transaction(root);
if (IS_ERR(trans)) { if (IS_ERR(trans)) {
btrfs_free_path(path); btrfs_free_path(path);
ret = PTR_ERR(trans); ret = PTR_ERR(trans);
...@@ -3300,6 +3303,7 @@ static int find_data_references(struct reloc_control *rc, ...@@ -3300,6 +3303,7 @@ static int find_data_references(struct reloc_control *rc,
path = btrfs_alloc_path(); path = btrfs_alloc_path();
if (!path) if (!path)
return -ENOMEM; return -ENOMEM;
path->reada = 1;
root = read_fs_root(rc->extent_root->fs_info, ref_root); root = read_fs_root(rc->extent_root->fs_info, ref_root);
if (IS_ERR(root)) { if (IS_ERR(root)) {
...@@ -3586,17 +3590,17 @@ int find_next_extent(struct btrfs_trans_handle *trans, ...@@ -3586,17 +3590,17 @@ int find_next_extent(struct btrfs_trans_handle *trans,
static void set_reloc_control(struct reloc_control *rc) static void set_reloc_control(struct reloc_control *rc)
{ {
struct btrfs_fs_info *fs_info = rc->extent_root->fs_info; struct btrfs_fs_info *fs_info = rc->extent_root->fs_info;
mutex_lock(&fs_info->trans_mutex); spin_lock(&fs_info->trans_lock);
fs_info->reloc_ctl = rc; fs_info->reloc_ctl = rc;
mutex_unlock(&fs_info->trans_mutex); spin_unlock(&fs_info->trans_lock);
} }
static void unset_reloc_control(struct reloc_control *rc) static void unset_reloc_control(struct reloc_control *rc)
{ {
struct btrfs_fs_info *fs_info = rc->extent_root->fs_info; struct btrfs_fs_info *fs_info = rc->extent_root->fs_info;
mutex_lock(&fs_info->trans_mutex); spin_lock(&fs_info->trans_lock);
fs_info->reloc_ctl = NULL; fs_info->reloc_ctl = NULL;
mutex_unlock(&fs_info->trans_mutex); spin_unlock(&fs_info->trans_lock);
} }
static int check_extent_flags(u64 flags) static int check_extent_flags(u64 flags)
...@@ -3645,7 +3649,7 @@ int prepare_to_relocate(struct reloc_control *rc) ...@@ -3645,7 +3649,7 @@ int prepare_to_relocate(struct reloc_control *rc)
rc->create_reloc_tree = 1; rc->create_reloc_tree = 1;
set_reloc_control(rc); set_reloc_control(rc);
trans = btrfs_join_transaction(rc->extent_root, 1); trans = btrfs_join_transaction(rc->extent_root);
BUG_ON(IS_ERR(trans)); BUG_ON(IS_ERR(trans));
btrfs_commit_transaction(trans, rc->extent_root); btrfs_commit_transaction(trans, rc->extent_root);
return 0; return 0;
...@@ -3668,6 +3672,7 @@ static noinline_for_stack int relocate_block_group(struct reloc_control *rc) ...@@ -3668,6 +3672,7 @@ static noinline_for_stack int relocate_block_group(struct reloc_control *rc)
path = btrfs_alloc_path(); path = btrfs_alloc_path();
if (!path) if (!path)
return -ENOMEM; return -ENOMEM;
path->reada = 1;
ret = prepare_to_relocate(rc); ret = prepare_to_relocate(rc);
if (ret) { if (ret) {
...@@ -3834,7 +3839,7 @@ static noinline_for_stack int relocate_block_group(struct reloc_control *rc) ...@@ -3834,7 +3839,7 @@ static noinline_for_stack int relocate_block_group(struct reloc_control *rc)
btrfs_block_rsv_release(rc->extent_root, rc->block_rsv, (u64)-1); btrfs_block_rsv_release(rc->extent_root, rc->block_rsv, (u64)-1);
/* get rid of pinned extents */ /* get rid of pinned extents */
trans = btrfs_join_transaction(rc->extent_root, 1); trans = btrfs_join_transaction(rc->extent_root);
if (IS_ERR(trans)) if (IS_ERR(trans))
err = PTR_ERR(trans); err = PTR_ERR(trans);
else else
...@@ -4093,6 +4098,7 @@ int btrfs_recover_relocation(struct btrfs_root *root) ...@@ -4093,6 +4098,7 @@ int btrfs_recover_relocation(struct btrfs_root *root)
path = btrfs_alloc_path(); path = btrfs_alloc_path();
if (!path) if (!path)
return -ENOMEM; return -ENOMEM;
path->reada = -1;
key.objectid = BTRFS_TREE_RELOC_OBJECTID; key.objectid = BTRFS_TREE_RELOC_OBJECTID;
key.type = BTRFS_ROOT_ITEM_KEY; key.type = BTRFS_ROOT_ITEM_KEY;
...@@ -4159,7 +4165,7 @@ int btrfs_recover_relocation(struct btrfs_root *root) ...@@ -4159,7 +4165,7 @@ int btrfs_recover_relocation(struct btrfs_root *root)
set_reloc_control(rc); set_reloc_control(rc);
trans = btrfs_join_transaction(rc->extent_root, 1); trans = btrfs_join_transaction(rc->extent_root);
if (IS_ERR(trans)) { if (IS_ERR(trans)) {
unset_reloc_control(rc); unset_reloc_control(rc);
err = PTR_ERR(trans); err = PTR_ERR(trans);
...@@ -4193,7 +4199,7 @@ int btrfs_recover_relocation(struct btrfs_root *root) ...@@ -4193,7 +4199,7 @@ int btrfs_recover_relocation(struct btrfs_root *root)
unset_reloc_control(rc); unset_reloc_control(rc);
trans = btrfs_join_transaction(rc->extent_root, 1); trans = btrfs_join_transaction(rc->extent_root);
if (IS_ERR(trans)) if (IS_ERR(trans))
err = PTR_ERR(trans); err = PTR_ERR(trans);
else else
......
...@@ -117,33 +117,37 @@ static void scrub_free_csums(struct scrub_dev *sdev) ...@@ -117,33 +117,37 @@ static void scrub_free_csums(struct scrub_dev *sdev)
} }
} }
static void scrub_free_bio(struct bio *bio)
{
int i;
struct page *last_page = NULL;
if (!bio)
return;
for (i = 0; i < bio->bi_vcnt; ++i) {
if (bio->bi_io_vec[i].bv_page == last_page)
continue;
last_page = bio->bi_io_vec[i].bv_page;
__free_page(last_page);
}
bio_put(bio);
}
static noinline_for_stack void scrub_free_dev(struct scrub_dev *sdev) static noinline_for_stack void scrub_free_dev(struct scrub_dev *sdev)
{ {
int i; int i;
int j;
struct page *last_page;
if (!sdev) if (!sdev)
return; return;
for (i = 0; i < SCRUB_BIOS_PER_DEV; ++i) { for (i = 0; i < SCRUB_BIOS_PER_DEV; ++i) {
struct scrub_bio *sbio = sdev->bios[i]; struct scrub_bio *sbio = sdev->bios[i];
struct bio *bio;
if (!sbio) if (!sbio)
break; break;
bio = sbio->bio; scrub_free_bio(sbio->bio);
if (bio) {
last_page = NULL;
for (j = 0; j < bio->bi_vcnt; ++j) {
if (bio->bi_io_vec[j].bv_page == last_page)
continue;
last_page = bio->bi_io_vec[j].bv_page;
__free_page(last_page);
}
bio_put(bio);
}
kfree(sbio); kfree(sbio);
} }
...@@ -156,8 +160,6 @@ struct scrub_dev *scrub_setup_dev(struct btrfs_device *dev) ...@@ -156,8 +160,6 @@ struct scrub_dev *scrub_setup_dev(struct btrfs_device *dev)
{ {
struct scrub_dev *sdev; struct scrub_dev *sdev;
int i; int i;
int j;
int ret;
struct btrfs_fs_info *fs_info = dev->dev_root->fs_info; struct btrfs_fs_info *fs_info = dev->dev_root->fs_info;
sdev = kzalloc(sizeof(*sdev), GFP_NOFS); sdev = kzalloc(sizeof(*sdev), GFP_NOFS);
...@@ -165,7 +167,6 @@ struct scrub_dev *scrub_setup_dev(struct btrfs_device *dev) ...@@ -165,7 +167,6 @@ struct scrub_dev *scrub_setup_dev(struct btrfs_device *dev)
goto nomem; goto nomem;
sdev->dev = dev; sdev->dev = dev;
for (i = 0; i < SCRUB_BIOS_PER_DEV; ++i) { for (i = 0; i < SCRUB_BIOS_PER_DEV; ++i) {
struct bio *bio;
struct scrub_bio *sbio; struct scrub_bio *sbio;
sbio = kzalloc(sizeof(*sbio), GFP_NOFS); sbio = kzalloc(sizeof(*sbio), GFP_NOFS);
...@@ -173,32 +174,10 @@ struct scrub_dev *scrub_setup_dev(struct btrfs_device *dev) ...@@ -173,32 +174,10 @@ struct scrub_dev *scrub_setup_dev(struct btrfs_device *dev)
goto nomem; goto nomem;
sdev->bios[i] = sbio; sdev->bios[i] = sbio;
bio = bio_kmalloc(GFP_NOFS, SCRUB_PAGES_PER_BIO);
if (!bio)
goto nomem;
sbio->index = i; sbio->index = i;
sbio->sdev = sdev; sbio->sdev = sdev;
sbio->bio = bio;
sbio->count = 0; sbio->count = 0;
sbio->work.func = scrub_checksum; sbio->work.func = scrub_checksum;
bio->bi_private = sdev->bios[i];
bio->bi_end_io = scrub_bio_end_io;
bio->bi_sector = 0;
bio->bi_bdev = dev->bdev;
bio->bi_size = 0;
for (j = 0; j < SCRUB_PAGES_PER_BIO; ++j) {
struct page *page;
page = alloc_page(GFP_NOFS);
if (!page)
goto nomem;
ret = bio_add_page(bio, page, PAGE_SIZE, 0);
if (!ret)
goto nomem;
}
WARN_ON(bio->bi_vcnt != SCRUB_PAGES_PER_BIO);
if (i != SCRUB_BIOS_PER_DEV-1) if (i != SCRUB_BIOS_PER_DEV-1)
sdev->bios[i]->next_free = i + 1; sdev->bios[i]->next_free = i + 1;
...@@ -369,9 +348,6 @@ static int scrub_fixup_io(int rw, struct block_device *bdev, sector_t sector, ...@@ -369,9 +348,6 @@ static int scrub_fixup_io(int rw, struct block_device *bdev, sector_t sector,
int ret; int ret;
DECLARE_COMPLETION_ONSTACK(complete); DECLARE_COMPLETION_ONSTACK(complete);
/* we are going to wait on this IO */
rw |= REQ_SYNC;
bio = bio_alloc(GFP_NOFS, 1); bio = bio_alloc(GFP_NOFS, 1);
bio->bi_bdev = bdev; bio->bi_bdev = bdev;
bio->bi_sector = sector; bio->bi_sector = sector;
...@@ -380,6 +356,7 @@ static int scrub_fixup_io(int rw, struct block_device *bdev, sector_t sector, ...@@ -380,6 +356,7 @@ static int scrub_fixup_io(int rw, struct block_device *bdev, sector_t sector,
bio->bi_private = &complete; bio->bi_private = &complete;
submit_bio(rw, bio); submit_bio(rw, bio);
/* this will also unplug the queue */
wait_for_completion(&complete); wait_for_completion(&complete);
ret = !test_bit(BIO_UPTODATE, &bio->bi_flags); ret = !test_bit(BIO_UPTODATE, &bio->bi_flags);
...@@ -394,6 +371,7 @@ static void scrub_bio_end_io(struct bio *bio, int err) ...@@ -394,6 +371,7 @@ static void scrub_bio_end_io(struct bio *bio, int err)
struct btrfs_fs_info *fs_info = sdev->dev->dev_root->fs_info; struct btrfs_fs_info *fs_info = sdev->dev->dev_root->fs_info;
sbio->err = err; sbio->err = err;
sbio->bio = bio;
btrfs_queue_worker(&fs_info->scrub_workers, &sbio->work); btrfs_queue_worker(&fs_info->scrub_workers, &sbio->work);
} }
...@@ -453,6 +431,8 @@ static void scrub_checksum(struct btrfs_work *work) ...@@ -453,6 +431,8 @@ static void scrub_checksum(struct btrfs_work *work)
} }
out: out:
scrub_free_bio(sbio->bio);
sbio->bio = NULL;
spin_lock(&sdev->list_lock); spin_lock(&sdev->list_lock);
sbio->next_free = sdev->first_free; sbio->next_free = sdev->first_free;
sdev->first_free = sbio->index; sdev->first_free = sbio->index;
...@@ -583,25 +563,50 @@ static int scrub_checksum_super(struct scrub_bio *sbio, void *buffer) ...@@ -583,25 +563,50 @@ static int scrub_checksum_super(struct scrub_bio *sbio, void *buffer)
static int scrub_submit(struct scrub_dev *sdev) static int scrub_submit(struct scrub_dev *sdev)
{ {
struct scrub_bio *sbio; struct scrub_bio *sbio;
struct bio *bio;
int i;
if (sdev->curr == -1) if (sdev->curr == -1)
return 0; return 0;
sbio = sdev->bios[sdev->curr]; sbio = sdev->bios[sdev->curr];
sbio->bio->bi_sector = sbio->physical >> 9; bio = bio_alloc(GFP_NOFS, sbio->count);
sbio->bio->bi_size = sbio->count * PAGE_SIZE; if (!bio)
sbio->bio->bi_next = NULL; goto nomem;
sbio->bio->bi_flags |= 1 << BIO_UPTODATE;
sbio->bio->bi_comp_cpu = -1; bio->bi_private = sbio;
sbio->bio->bi_bdev = sdev->dev->bdev; bio->bi_end_io = scrub_bio_end_io;
bio->bi_bdev = sdev->dev->bdev;
bio->bi_sector = sbio->physical >> 9;
for (i = 0; i < sbio->count; ++i) {
struct page *page;
int ret;
page = alloc_page(GFP_NOFS);
if (!page)
goto nomem;
ret = bio_add_page(bio, page, PAGE_SIZE, 0);
if (!ret) {
__free_page(page);
goto nomem;
}
}
sbio->err = 0; sbio->err = 0;
sdev->curr = -1; sdev->curr = -1;
atomic_inc(&sdev->in_flight); atomic_inc(&sdev->in_flight);
submit_bio(0, sbio->bio); submit_bio(READ, bio);
return 0; return 0;
nomem:
scrub_free_bio(bio);
return -ENOMEM;
} }
static int scrub_page(struct scrub_dev *sdev, u64 logical, u64 len, static int scrub_page(struct scrub_dev *sdev, u64 logical, u64 len,
...@@ -633,7 +638,11 @@ static int scrub_page(struct scrub_dev *sdev, u64 logical, u64 len, ...@@ -633,7 +638,11 @@ static int scrub_page(struct scrub_dev *sdev, u64 logical, u64 len,
sbio->logical = logical; sbio->logical = logical;
} else if (sbio->physical + sbio->count * PAGE_SIZE != physical || } else if (sbio->physical + sbio->count * PAGE_SIZE != physical ||
sbio->logical + sbio->count * PAGE_SIZE != logical) { sbio->logical + sbio->count * PAGE_SIZE != logical) {
scrub_submit(sdev); int ret;
ret = scrub_submit(sdev);
if (ret)
return ret;
goto again; goto again;
} }
sbio->spag[sbio->count].flags = flags; sbio->spag[sbio->count].flags = flags;
...@@ -645,8 +654,13 @@ static int scrub_page(struct scrub_dev *sdev, u64 logical, u64 len, ...@@ -645,8 +654,13 @@ static int scrub_page(struct scrub_dev *sdev, u64 logical, u64 len,
memcpy(sbio->spag[sbio->count].csum, csum, sdev->csum_size); memcpy(sbio->spag[sbio->count].csum, csum, sdev->csum_size);
} }
++sbio->count; ++sbio->count;
if (sbio->count == SCRUB_PAGES_PER_BIO || force) if (sbio->count == SCRUB_PAGES_PER_BIO || force) {
scrub_submit(sdev); int ret;
ret = scrub_submit(sdev);
if (ret)
return ret;
}
return 0; return 0;
} }
...@@ -727,6 +741,7 @@ static noinline_for_stack int scrub_stripe(struct scrub_dev *sdev, ...@@ -727,6 +741,7 @@ static noinline_for_stack int scrub_stripe(struct scrub_dev *sdev,
struct btrfs_root *root = fs_info->extent_root; struct btrfs_root *root = fs_info->extent_root;
struct btrfs_root *csum_root = fs_info->csum_root; struct btrfs_root *csum_root = fs_info->csum_root;
struct btrfs_extent_item *extent; struct btrfs_extent_item *extent;
struct blk_plug plug;
u64 flags; u64 flags;
int ret; int ret;
int slot; int slot;
...@@ -831,6 +846,7 @@ static noinline_for_stack int scrub_stripe(struct scrub_dev *sdev, ...@@ -831,6 +846,7 @@ static noinline_for_stack int scrub_stripe(struct scrub_dev *sdev,
* the scrub. This might currently (crc32) end up to be about 1MB * the scrub. This might currently (crc32) end up to be about 1MB
*/ */
start_stripe = 0; start_stripe = 0;
blk_start_plug(&plug);
again: again:
logical = base + offset + start_stripe * increment; logical = base + offset + start_stripe * increment;
for (i = start_stripe; i < nstripes; ++i) { for (i = start_stripe; i < nstripes; ++i) {
...@@ -972,6 +988,7 @@ static noinline_for_stack int scrub_stripe(struct scrub_dev *sdev, ...@@ -972,6 +988,7 @@ static noinline_for_stack int scrub_stripe(struct scrub_dev *sdev,
scrub_submit(sdev); scrub_submit(sdev);
out: out:
blk_finish_plug(&plug);
btrfs_free_path(path); btrfs_free_path(path);
return ret < 0 ? ret : 0; return ret < 0 ? ret : 0;
} }
...@@ -1166,7 +1183,7 @@ int btrfs_scrub_dev(struct btrfs_root *root, u64 devid, u64 start, u64 end, ...@@ -1166,7 +1183,7 @@ int btrfs_scrub_dev(struct btrfs_root *root, u64 devid, u64 start, u64 end,
int ret; int ret;
struct btrfs_device *dev; struct btrfs_device *dev;
if (root->fs_info->closing) if (btrfs_fs_closing(root->fs_info))
return -EINVAL; return -EINVAL;
/* /*
......
...@@ -161,7 +161,8 @@ enum { ...@@ -161,7 +161,8 @@ enum {
Opt_compress_type, Opt_compress_force, Opt_compress_force_type, Opt_compress_type, Opt_compress_force, Opt_compress_force_type,
Opt_notreelog, Opt_ratio, Opt_flushoncommit, Opt_discard, Opt_notreelog, Opt_ratio, Opt_flushoncommit, Opt_discard,
Opt_space_cache, Opt_clear_cache, Opt_user_subvol_rm_allowed, Opt_space_cache, Opt_clear_cache, Opt_user_subvol_rm_allowed,
Opt_enospc_debug, Opt_subvolrootid, Opt_defrag, Opt_err, Opt_enospc_debug, Opt_subvolrootid, Opt_defrag,
Opt_inode_cache, Opt_err,
}; };
static match_table_t tokens = { static match_table_t tokens = {
...@@ -193,6 +194,7 @@ static match_table_t tokens = { ...@@ -193,6 +194,7 @@ static match_table_t tokens = {
{Opt_enospc_debug, "enospc_debug"}, {Opt_enospc_debug, "enospc_debug"},
{Opt_subvolrootid, "subvolrootid=%d"}, {Opt_subvolrootid, "subvolrootid=%d"},
{Opt_defrag, "autodefrag"}, {Opt_defrag, "autodefrag"},
{Opt_inode_cache, "inode_cache"},
{Opt_err, NULL}, {Opt_err, NULL},
}; };
...@@ -361,6 +363,10 @@ int btrfs_parse_options(struct btrfs_root *root, char *options) ...@@ -361,6 +363,10 @@ int btrfs_parse_options(struct btrfs_root *root, char *options)
printk(KERN_INFO "btrfs: enabling disk space caching\n"); printk(KERN_INFO "btrfs: enabling disk space caching\n");
btrfs_set_opt(info->mount_opt, SPACE_CACHE); btrfs_set_opt(info->mount_opt, SPACE_CACHE);
break; break;
case Opt_inode_cache:
printk(KERN_INFO "btrfs: enabling inode map caching\n");
btrfs_set_opt(info->mount_opt, INODE_MAP_CACHE);
break;
case Opt_clear_cache: case Opt_clear_cache:
printk(KERN_INFO "btrfs: force clearing of disk cache\n"); printk(KERN_INFO "btrfs: force clearing of disk cache\n");
btrfs_set_opt(info->mount_opt, CLEAR_CACHE); btrfs_set_opt(info->mount_opt, CLEAR_CACHE);
......
This diff is collapsed.
...@@ -28,10 +28,12 @@ struct btrfs_transaction { ...@@ -28,10 +28,12 @@ struct btrfs_transaction {
* transaction can end * transaction can end
*/ */
atomic_t num_writers; atomic_t num_writers;
atomic_t use_count;
unsigned long num_joined; unsigned long num_joined;
spinlock_t commit_lock;
int in_commit; int in_commit;
atomic_t use_count;
int commit_done; int commit_done;
int blocked; int blocked;
struct list_head list; struct list_head list;
...@@ -45,13 +47,14 @@ struct btrfs_transaction { ...@@ -45,13 +47,14 @@ struct btrfs_transaction {
struct btrfs_trans_handle { struct btrfs_trans_handle {
u64 transid; u64 transid;
u64 block_group;
u64 bytes_reserved; u64 bytes_reserved;
unsigned long use_count;
unsigned long blocks_reserved; unsigned long blocks_reserved;
unsigned long blocks_used; unsigned long blocks_used;
unsigned long delayed_ref_updates; unsigned long delayed_ref_updates;
struct btrfs_transaction *transaction; struct btrfs_transaction *transaction;
struct btrfs_block_rsv *block_rsv; struct btrfs_block_rsv *block_rsv;
struct btrfs_block_rsv *orig_rsv;
}; };
struct btrfs_pending_snapshot { struct btrfs_pending_snapshot {
...@@ -66,19 +69,6 @@ struct btrfs_pending_snapshot { ...@@ -66,19 +69,6 @@ struct btrfs_pending_snapshot {
struct list_head list; struct list_head list;
}; };
static inline void btrfs_set_trans_block_group(struct btrfs_trans_handle *trans,
struct inode *inode)
{
trans->block_group = BTRFS_I(inode)->block_group;
}
static inline void btrfs_update_inode_block_group(
struct btrfs_trans_handle *trans,
struct inode *inode)
{
BTRFS_I(inode)->block_group = trans->block_group;
}
static inline void btrfs_set_inode_last_trans(struct btrfs_trans_handle *trans, static inline void btrfs_set_inode_last_trans(struct btrfs_trans_handle *trans,
struct inode *inode) struct inode *inode)
{ {
...@@ -92,12 +82,9 @@ int btrfs_end_transaction_nolock(struct btrfs_trans_handle *trans, ...@@ -92,12 +82,9 @@ int btrfs_end_transaction_nolock(struct btrfs_trans_handle *trans,
struct btrfs_root *root); struct btrfs_root *root);
struct btrfs_trans_handle *btrfs_start_transaction(struct btrfs_root *root, struct btrfs_trans_handle *btrfs_start_transaction(struct btrfs_root *root,
int num_items); int num_items);
struct btrfs_trans_handle *btrfs_join_transaction(struct btrfs_root *root, struct btrfs_trans_handle *btrfs_join_transaction(struct btrfs_root *root);
int num_blocks); struct btrfs_trans_handle *btrfs_join_transaction_nolock(struct btrfs_root *root);
struct btrfs_trans_handle *btrfs_join_transaction_nolock(struct btrfs_root *root, struct btrfs_trans_handle *btrfs_start_ioctl_transaction(struct btrfs_root *root);
int num_blocks);
struct btrfs_trans_handle *btrfs_start_ioctl_transaction(struct btrfs_root *r,
int num_blocks);
int btrfs_wait_for_commit(struct btrfs_root *root, u64 transid); int btrfs_wait_for_commit(struct btrfs_root *root, u64 transid);
int btrfs_write_and_wait_transaction(struct btrfs_trans_handle *trans, int btrfs_write_and_wait_transaction(struct btrfs_trans_handle *trans,
struct btrfs_root *root); struct btrfs_root *root);
......
...@@ -504,7 +504,7 @@ static int __btrfs_close_devices(struct btrfs_fs_devices *fs_devices) ...@@ -504,7 +504,7 @@ static int __btrfs_close_devices(struct btrfs_fs_devices *fs_devices)
BUG_ON(!new_device); BUG_ON(!new_device);
memcpy(new_device, device, sizeof(*new_device)); memcpy(new_device, device, sizeof(*new_device));
new_device->name = kstrdup(device->name, GFP_NOFS); new_device->name = kstrdup(device->name, GFP_NOFS);
BUG_ON(!new_device->name); BUG_ON(device->name && !new_device->name);
new_device->bdev = NULL; new_device->bdev = NULL;
new_device->writeable = 0; new_device->writeable = 0;
new_device->in_fs_metadata = 0; new_device->in_fs_metadata = 0;
......
...@@ -158,8 +158,6 @@ int __btrfs_setxattr(struct btrfs_trans_handle *trans, ...@@ -158,8 +158,6 @@ int __btrfs_setxattr(struct btrfs_trans_handle *trans,
if (IS_ERR(trans)) if (IS_ERR(trans))
return PTR_ERR(trans); return PTR_ERR(trans);
btrfs_set_trans_block_group(trans, inode);
ret = do_setxattr(trans, inode, name, value, size, flags); ret = do_setxattr(trans, inode, name, value, size, flags);
if (ret) if (ret)
goto out; goto out;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment