Commit 2b9fb532 authored by Linus Torvalds's avatar Linus Torvalds

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

Pull btrfs updates from Chris Mason:
 "This pull is mostly cleanups and fixes:

   - The raid5/6 cleanups from Zhao Lei fixup some long standing warts
     in the code and add improvements on top of the scrubbing support
     from 3.19.

   - Josef has round one of our ENOSPC fixes coming from large btrfs
     clusters here at FB.

   - Dave Sterba continues a long series of cleanups (thanks Dave), and
     Filipe continues hammering on corner cases in fsync and others

  This all was held up a little trying to track down a use-after-free in
  btrfs raid5/6.  It's not clear yet if this is just made easier to
  trigger with this pull or if its a new bug from the raid5/6 cleanups.
  Dave Sterba is the only one to trigger it so far, but he has a
  consistent way to reproduce, so we'll get it nailed shortly"

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mason/linux-btrfs: (68 commits)
  Btrfs: don't remove extents and xattrs when logging new names
  Btrfs: fix fsync data loss after adding hard link to inode
  Btrfs: fix BUG_ON in btrfs_orphan_add() when delete unused block group
  Btrfs: account for large extents with enospc
  Btrfs: don't set and clear delalloc for O_DIRECT writes
  Btrfs: only adjust outstanding_extents when we do a short write
  btrfs: Fix out-of-space bug
  Btrfs: scrub, fix sleep in atomic context
  Btrfs: fix scheduler warning when syncing log
  Btrfs: Remove unnecessary placeholder in btrfs_err_code
  btrfs: cleanup init for list in free-space-cache
  btrfs: delete chunk allocation attemp when setting block group ro
  btrfs: clear bio reference after submit_one_bio()
  Btrfs: fix scrub race leading to use-after-free
  Btrfs: add missing cleanup on sysfs init failure
  Btrfs: fix race between transaction commit and empty block group removal
  btrfs: add more checks to btrfs_read_sys_array
  btrfs: cleanup, rename a few variables in btrfs_read_sys_array
  btrfs: add checks for sys_chunk_array sizes
  btrfs: more superblock checks, lower bounds on devices and sectorsize/nodesize
  ...
parents 4533f6e2 a742994a
...@@ -1246,25 +1246,6 @@ int btrfs_check_shared(struct btrfs_trans_handle *trans, ...@@ -1246,25 +1246,6 @@ int btrfs_check_shared(struct btrfs_trans_handle *trans,
return ret; return ret;
} }
/*
* this makes the path point to (inum INODE_ITEM ioff)
*/
int inode_item_info(u64 inum, u64 ioff, struct btrfs_root *fs_root,
struct btrfs_path *path)
{
struct btrfs_key key;
return btrfs_find_item(fs_root, path, inum, ioff,
BTRFS_INODE_ITEM_KEY, &key);
}
static int inode_ref_info(u64 inum, u64 ioff, struct btrfs_root *fs_root,
struct btrfs_path *path,
struct btrfs_key *found_key)
{
return btrfs_find_item(fs_root, path, inum, ioff,
BTRFS_INODE_REF_KEY, found_key);
}
int btrfs_find_one_extref(struct btrfs_root *root, u64 inode_objectid, int btrfs_find_one_extref(struct btrfs_root *root, u64 inode_objectid,
u64 start_off, struct btrfs_path *path, u64 start_off, struct btrfs_path *path,
struct btrfs_inode_extref **ret_extref, struct btrfs_inode_extref **ret_extref,
...@@ -1374,7 +1355,8 @@ char *btrfs_ref_to_path(struct btrfs_root *fs_root, struct btrfs_path *path, ...@@ -1374,7 +1355,8 @@ char *btrfs_ref_to_path(struct btrfs_root *fs_root, struct btrfs_path *path,
btrfs_tree_read_unlock_blocking(eb); btrfs_tree_read_unlock_blocking(eb);
free_extent_buffer(eb); free_extent_buffer(eb);
} }
ret = inode_ref_info(parent, 0, fs_root, path, &found_key); ret = btrfs_find_item(fs_root, path, parent, 0,
BTRFS_INODE_REF_KEY, &found_key);
if (ret > 0) if (ret > 0)
ret = -ENOENT; ret = -ENOENT;
if (ret) if (ret)
...@@ -1727,8 +1709,10 @@ static int iterate_inode_refs(u64 inum, struct btrfs_root *fs_root, ...@@ -1727,8 +1709,10 @@ static int iterate_inode_refs(u64 inum, struct btrfs_root *fs_root,
struct btrfs_key found_key; struct btrfs_key found_key;
while (!ret) { while (!ret) {
ret = inode_ref_info(inum, parent ? parent+1 : 0, fs_root, path, ret = btrfs_find_item(fs_root, path, inum,
&found_key); parent ? parent + 1 : 0, BTRFS_INODE_REF_KEY,
&found_key);
if (ret < 0) if (ret < 0)
break; break;
if (ret) { if (ret) {
......
...@@ -32,9 +32,6 @@ struct inode_fs_paths { ...@@ -32,9 +32,6 @@ struct inode_fs_paths {
typedef int (iterate_extent_inodes_t)(u64 inum, u64 offset, u64 root, typedef int (iterate_extent_inodes_t)(u64 inum, u64 offset, u64 root,
void *ctx); void *ctx);
int inode_item_info(u64 inum, u64 ioff, struct btrfs_root *fs_root,
struct btrfs_path *path);
int extent_from_logical(struct btrfs_fs_info *fs_info, u64 logical, int extent_from_logical(struct btrfs_fs_info *fs_info, u64 logical,
struct btrfs_path *path, struct btrfs_key *found_key, struct btrfs_path *path, struct btrfs_key *found_key,
u64 *flags); u64 *flags);
......
...@@ -185,6 +185,9 @@ struct btrfs_inode { ...@@ -185,6 +185,9 @@ struct btrfs_inode {
struct btrfs_delayed_node *delayed_node; struct btrfs_delayed_node *delayed_node;
/* File creation time. */
struct timespec i_otime;
struct inode vfs_inode; struct inode vfs_inode;
}; };
......
...@@ -213,11 +213,19 @@ static struct extent_buffer *btrfs_read_lock_root_node(struct btrfs_root *root) ...@@ -213,11 +213,19 @@ static struct extent_buffer *btrfs_read_lock_root_node(struct btrfs_root *root)
*/ */
static void add_root_to_dirty_list(struct btrfs_root *root) static void add_root_to_dirty_list(struct btrfs_root *root)
{ {
if (test_bit(BTRFS_ROOT_DIRTY, &root->state) ||
!test_bit(BTRFS_ROOT_TRACK_DIRTY, &root->state))
return;
spin_lock(&root->fs_info->trans_lock); spin_lock(&root->fs_info->trans_lock);
if (test_bit(BTRFS_ROOT_TRACK_DIRTY, &root->state) && if (!test_and_set_bit(BTRFS_ROOT_DIRTY, &root->state)) {
list_empty(&root->dirty_list)) { /* Want the extent tree to be the last on the list */
list_add(&root->dirty_list, if (root->objectid == BTRFS_EXTENT_TREE_OBJECTID)
&root->fs_info->dirty_cowonly_roots); list_move_tail(&root->dirty_list,
&root->fs_info->dirty_cowonly_roots);
else
list_move(&root->dirty_list,
&root->fs_info->dirty_cowonly_roots);
} }
spin_unlock(&root->fs_info->trans_lock); spin_unlock(&root->fs_info->trans_lock);
} }
...@@ -1363,8 +1371,7 @@ tree_mod_log_rewind(struct btrfs_fs_info *fs_info, struct btrfs_path *path, ...@@ -1363,8 +1371,7 @@ tree_mod_log_rewind(struct btrfs_fs_info *fs_info, struct btrfs_path *path,
if (tm->op == MOD_LOG_KEY_REMOVE_WHILE_FREEING) { if (tm->op == MOD_LOG_KEY_REMOVE_WHILE_FREEING) {
BUG_ON(tm->slot != 0); BUG_ON(tm->slot != 0);
eb_rewin = alloc_dummy_extent_buffer(eb->start, eb_rewin = alloc_dummy_extent_buffer(fs_info, eb->start);
fs_info->tree_root->nodesize);
if (!eb_rewin) { if (!eb_rewin) {
btrfs_tree_read_unlock_blocking(eb); btrfs_tree_read_unlock_blocking(eb);
free_extent_buffer(eb); free_extent_buffer(eb);
...@@ -1444,7 +1451,7 @@ get_old_root(struct btrfs_root *root, u64 time_seq) ...@@ -1444,7 +1451,7 @@ get_old_root(struct btrfs_root *root, u64 time_seq)
} else if (old_root) { } else if (old_root) {
btrfs_tree_read_unlock(eb_root); btrfs_tree_read_unlock(eb_root);
free_extent_buffer(eb_root); free_extent_buffer(eb_root);
eb = alloc_dummy_extent_buffer(logical, root->nodesize); eb = alloc_dummy_extent_buffer(root->fs_info, logical);
} else { } else {
btrfs_set_lock_blocking_rw(eb_root, BTRFS_READ_LOCK); btrfs_set_lock_blocking_rw(eb_root, BTRFS_READ_LOCK);
eb = btrfs_clone_extent_buffer(eb_root); eb = btrfs_clone_extent_buffer(eb_root);
...@@ -2282,7 +2289,7 @@ static void reada_for_search(struct btrfs_root *root, ...@@ -2282,7 +2289,7 @@ static void reada_for_search(struct btrfs_root *root,
if ((search <= target && target - search <= 65536) || if ((search <= target && target - search <= 65536) ||
(search > target && search - target <= 65536)) { (search > target && search - target <= 65536)) {
gen = btrfs_node_ptr_generation(node, nr); gen = btrfs_node_ptr_generation(node, nr);
readahead_tree_block(root, search, blocksize); readahead_tree_block(root, search);
nread += blocksize; nread += blocksize;
} }
nscan++; nscan++;
...@@ -2301,7 +2308,6 @@ static noinline void reada_for_balance(struct btrfs_root *root, ...@@ -2301,7 +2308,6 @@ static noinline void reada_for_balance(struct btrfs_root *root,
u64 gen; u64 gen;
u64 block1 = 0; u64 block1 = 0;
u64 block2 = 0; u64 block2 = 0;
int blocksize;
parent = path->nodes[level + 1]; parent = path->nodes[level + 1];
if (!parent) if (!parent)
...@@ -2309,7 +2315,6 @@ static noinline void reada_for_balance(struct btrfs_root *root, ...@@ -2309,7 +2315,6 @@ static noinline void reada_for_balance(struct btrfs_root *root,
nritems = btrfs_header_nritems(parent); nritems = btrfs_header_nritems(parent);
slot = path->slots[level + 1]; slot = path->slots[level + 1];
blocksize = root->nodesize;
if (slot > 0) { if (slot > 0) {
block1 = btrfs_node_blockptr(parent, slot - 1); block1 = btrfs_node_blockptr(parent, slot - 1);
...@@ -2334,9 +2339,9 @@ static noinline void reada_for_balance(struct btrfs_root *root, ...@@ -2334,9 +2339,9 @@ static noinline void reada_for_balance(struct btrfs_root *root,
} }
if (block1) if (block1)
readahead_tree_block(root, block1, blocksize); readahead_tree_block(root, block1);
if (block2) if (block2)
readahead_tree_block(root, block2, blocksize); readahead_tree_block(root, block2);
} }
...@@ -2609,32 +2614,24 @@ static int key_search(struct extent_buffer *b, struct btrfs_key *key, ...@@ -2609,32 +2614,24 @@ static int key_search(struct extent_buffer *b, struct btrfs_key *key,
return 0; return 0;
} }
int btrfs_find_item(struct btrfs_root *fs_root, struct btrfs_path *found_path, int btrfs_find_item(struct btrfs_root *fs_root, struct btrfs_path *path,
u64 iobjectid, u64 ioff, u8 key_type, u64 iobjectid, u64 ioff, u8 key_type,
struct btrfs_key *found_key) struct btrfs_key *found_key)
{ {
int ret; int ret;
struct btrfs_key key; struct btrfs_key key;
struct extent_buffer *eb; struct extent_buffer *eb;
struct btrfs_path *path;
ASSERT(path);
ASSERT(found_key);
key.type = key_type; key.type = key_type;
key.objectid = iobjectid; key.objectid = iobjectid;
key.offset = ioff; key.offset = ioff;
if (found_path == NULL) {
path = btrfs_alloc_path();
if (!path)
return -ENOMEM;
} else
path = found_path;
ret = btrfs_search_slot(NULL, fs_root, &key, path, 0, 0); ret = btrfs_search_slot(NULL, fs_root, &key, path, 0, 0);
if ((ret < 0) || (found_key == NULL)) { if (ret < 0)
if (path != found_path)
btrfs_free_path(path);
return ret; return ret;
}
eb = path->nodes[0]; eb = path->nodes[0];
if (ret && path->slots[0] >= btrfs_header_nritems(eb)) { if (ret && path->slots[0] >= btrfs_header_nritems(eb)) {
...@@ -3383,7 +3380,7 @@ static noinline int insert_new_root(struct btrfs_trans_handle *trans, ...@@ -3383,7 +3380,7 @@ static noinline int insert_new_root(struct btrfs_trans_handle *trans,
add_root_to_dirty_list(root); add_root_to_dirty_list(root);
extent_buffer_get(c); extent_buffer_get(c);
path->nodes[level] = c; path->nodes[level] = c;
path->locks[level] = BTRFS_WRITE_LOCK; path->locks[level] = BTRFS_WRITE_LOCK_BLOCKING;
path->slots[level] = 0; path->slots[level] = 0;
return 0; return 0;
} }
...@@ -4356,13 +4353,15 @@ static noinline int setup_leaf_for_split(struct btrfs_trans_handle *trans, ...@@ -4356,13 +4353,15 @@ static noinline int setup_leaf_for_split(struct btrfs_trans_handle *trans,
path->search_for_split = 1; path->search_for_split = 1;
ret = btrfs_search_slot(trans, root, &key, path, 0, 1); ret = btrfs_search_slot(trans, root, &key, path, 0, 1);
path->search_for_split = 0; path->search_for_split = 0;
if (ret > 0)
ret = -EAGAIN;
if (ret < 0) if (ret < 0)
goto err; goto err;
ret = -EAGAIN; ret = -EAGAIN;
leaf = path->nodes[0]; leaf = path->nodes[0];
/* if our item isn't there or got smaller, return now */ /* if our item isn't there, return now */
if (ret > 0 || item_size != btrfs_item_size_nr(leaf, path->slots[0])) if (item_size != btrfs_item_size_nr(leaf, path->slots[0]))
goto err; goto err;
/* the leaf has changed, it now has room. return now */ /* the leaf has changed, it now has room. return now */
......
...@@ -198,6 +198,8 @@ static int btrfs_csum_sizes[] = { 4, 0 }; ...@@ -198,6 +198,8 @@ static int btrfs_csum_sizes[] = { 4, 0 };
#define BTRFS_DIRTY_METADATA_THRESH (32 * 1024 * 1024) #define BTRFS_DIRTY_METADATA_THRESH (32 * 1024 * 1024)
#define BTRFS_MAX_EXTENT_SIZE (128 * 1024 * 1024)
/* /*
* The key defines the order in the tree, and so it also defines (optimal) * The key defines the order in the tree, and so it also defines (optimal)
* block layout. * block layout.
...@@ -1020,6 +1022,9 @@ enum btrfs_raid_types { ...@@ -1020,6 +1022,9 @@ enum btrfs_raid_types {
BTRFS_BLOCK_GROUP_RAID6 | \ BTRFS_BLOCK_GROUP_RAID6 | \
BTRFS_BLOCK_GROUP_DUP | \ BTRFS_BLOCK_GROUP_DUP | \
BTRFS_BLOCK_GROUP_RAID10) BTRFS_BLOCK_GROUP_RAID10)
#define BTRFS_BLOCK_GROUP_RAID56_MASK (BTRFS_BLOCK_GROUP_RAID5 | \
BTRFS_BLOCK_GROUP_RAID6)
/* /*
* We need a bit for restriper to be able to tell when chunks of type * We need a bit for restriper to be able to tell when chunks of type
* SINGLE are available. This "extended" profile format is used in * SINGLE are available. This "extended" profile format is used in
...@@ -1239,7 +1244,6 @@ enum btrfs_disk_cache_state { ...@@ -1239,7 +1244,6 @@ enum btrfs_disk_cache_state {
BTRFS_DC_ERROR = 1, BTRFS_DC_ERROR = 1,
BTRFS_DC_CLEAR = 2, BTRFS_DC_CLEAR = 2,
BTRFS_DC_SETUP = 3, BTRFS_DC_SETUP = 3,
BTRFS_DC_NEED_WRITE = 4,
}; };
struct btrfs_caching_control { struct btrfs_caching_control {
...@@ -1277,7 +1281,6 @@ struct btrfs_block_group_cache { ...@@ -1277,7 +1281,6 @@ struct btrfs_block_group_cache {
unsigned long full_stripe_len; unsigned long full_stripe_len;
unsigned int ro:1; unsigned int ro:1;
unsigned int dirty:1;
unsigned int iref:1; unsigned int iref:1;
unsigned int has_caching_ctl:1; unsigned int has_caching_ctl:1;
unsigned int removed:1; unsigned int removed:1;
...@@ -1315,6 +1318,9 @@ struct btrfs_block_group_cache { ...@@ -1315,6 +1318,9 @@ struct btrfs_block_group_cache {
struct list_head ro_list; struct list_head ro_list;
atomic_t trimming; atomic_t trimming;
/* For dirty block groups */
struct list_head dirty_list;
}; };
/* delayed seq elem */ /* delayed seq elem */
...@@ -1741,6 +1747,7 @@ struct btrfs_fs_info { ...@@ -1741,6 +1747,7 @@ struct btrfs_fs_info {
spinlock_t unused_bgs_lock; spinlock_t unused_bgs_lock;
struct list_head unused_bgs; struct list_head unused_bgs;
struct mutex unused_bg_unpin_mutex;
/* For btrfs to record security options */ /* For btrfs to record security options */
struct security_mnt_opts security_opts; struct security_mnt_opts security_opts;
...@@ -1776,6 +1783,7 @@ struct btrfs_subvolume_writers { ...@@ -1776,6 +1783,7 @@ struct btrfs_subvolume_writers {
#define BTRFS_ROOT_DEFRAG_RUNNING 6 #define BTRFS_ROOT_DEFRAG_RUNNING 6
#define BTRFS_ROOT_FORCE_COW 7 #define BTRFS_ROOT_FORCE_COW 7
#define BTRFS_ROOT_MULTI_LOG_TASKS 8 #define BTRFS_ROOT_MULTI_LOG_TASKS 8
#define BTRFS_ROOT_DIRTY 9
/* /*
* in ram representation of the tree. extent_root is used for all allocations * in ram representation of the tree. extent_root is used for all allocations
...@@ -1794,8 +1802,6 @@ struct btrfs_root { ...@@ -1794,8 +1802,6 @@ struct btrfs_root {
struct btrfs_fs_info *fs_info; struct btrfs_fs_info *fs_info;
struct extent_io_tree dirty_log_pages; struct extent_io_tree dirty_log_pages;
struct kobject root_kobj;
struct completion kobj_unregister;
struct mutex objectid_mutex; struct mutex objectid_mutex;
spinlock_t accounting_lock; spinlock_t accounting_lock;
...@@ -2465,31 +2471,6 @@ BTRFS_SETGET_STACK_FUNCS(stack_inode_gid, struct btrfs_inode_item, gid, 32); ...@@ -2465,31 +2471,6 @@ BTRFS_SETGET_STACK_FUNCS(stack_inode_gid, struct btrfs_inode_item, gid, 32);
BTRFS_SETGET_STACK_FUNCS(stack_inode_mode, struct btrfs_inode_item, mode, 32); BTRFS_SETGET_STACK_FUNCS(stack_inode_mode, struct btrfs_inode_item, mode, 32);
BTRFS_SETGET_STACK_FUNCS(stack_inode_rdev, struct btrfs_inode_item, rdev, 64); BTRFS_SETGET_STACK_FUNCS(stack_inode_rdev, struct btrfs_inode_item, rdev, 64);
BTRFS_SETGET_STACK_FUNCS(stack_inode_flags, struct btrfs_inode_item, flags, 64); BTRFS_SETGET_STACK_FUNCS(stack_inode_flags, struct btrfs_inode_item, flags, 64);
static inline struct btrfs_timespec *
btrfs_inode_atime(struct btrfs_inode_item *inode_item)
{
unsigned long ptr = (unsigned long)inode_item;
ptr += offsetof(struct btrfs_inode_item, atime);
return (struct btrfs_timespec *)ptr;
}
static inline struct btrfs_timespec *
btrfs_inode_mtime(struct btrfs_inode_item *inode_item)
{
unsigned long ptr = (unsigned long)inode_item;
ptr += offsetof(struct btrfs_inode_item, mtime);
return (struct btrfs_timespec *)ptr;
}
static inline struct btrfs_timespec *
btrfs_inode_ctime(struct btrfs_inode_item *inode_item)
{
unsigned long ptr = (unsigned long)inode_item;
ptr += offsetof(struct btrfs_inode_item, ctime);
return (struct btrfs_timespec *)ptr;
}
BTRFS_SETGET_FUNCS(timespec_sec, struct btrfs_timespec, sec, 64); BTRFS_SETGET_FUNCS(timespec_sec, struct btrfs_timespec, sec, 64);
BTRFS_SETGET_FUNCS(timespec_nsec, struct btrfs_timespec, nsec, 32); BTRFS_SETGET_FUNCS(timespec_nsec, struct btrfs_timespec, nsec, 32);
BTRFS_SETGET_STACK_FUNCS(stack_timespec_sec, struct btrfs_timespec, sec, 64); BTRFS_SETGET_STACK_FUNCS(stack_timespec_sec, struct btrfs_timespec, sec, 64);
......
...@@ -1755,27 +1755,31 @@ static void fill_stack_inode_item(struct btrfs_trans_handle *trans, ...@@ -1755,27 +1755,31 @@ static void fill_stack_inode_item(struct btrfs_trans_handle *trans,
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, 0); btrfs_set_stack_inode_block_group(inode_item, 0);
btrfs_set_stack_timespec_sec(btrfs_inode_atime(inode_item), btrfs_set_stack_timespec_sec(&inode_item->atime,
inode->i_atime.tv_sec); inode->i_atime.tv_sec);
btrfs_set_stack_timespec_nsec(btrfs_inode_atime(inode_item), btrfs_set_stack_timespec_nsec(&inode_item->atime,
inode->i_atime.tv_nsec); inode->i_atime.tv_nsec);
btrfs_set_stack_timespec_sec(btrfs_inode_mtime(inode_item), btrfs_set_stack_timespec_sec(&inode_item->mtime,
inode->i_mtime.tv_sec); inode->i_mtime.tv_sec);
btrfs_set_stack_timespec_nsec(btrfs_inode_mtime(inode_item), btrfs_set_stack_timespec_nsec(&inode_item->mtime,
inode->i_mtime.tv_nsec); inode->i_mtime.tv_nsec);
btrfs_set_stack_timespec_sec(btrfs_inode_ctime(inode_item), btrfs_set_stack_timespec_sec(&inode_item->ctime,
inode->i_ctime.tv_sec); inode->i_ctime.tv_sec);
btrfs_set_stack_timespec_nsec(btrfs_inode_ctime(inode_item), btrfs_set_stack_timespec_nsec(&inode_item->ctime,
inode->i_ctime.tv_nsec); inode->i_ctime.tv_nsec);
btrfs_set_stack_timespec_sec(&inode_item->otime,
BTRFS_I(inode)->i_otime.tv_sec);
btrfs_set_stack_timespec_nsec(&inode_item->otime,
BTRFS_I(inode)->i_otime.tv_nsec);
} }
int btrfs_fill_inode(struct inode *inode, u32 *rdev) int btrfs_fill_inode(struct inode *inode, u32 *rdev)
{ {
struct btrfs_delayed_node *delayed_node; struct btrfs_delayed_node *delayed_node;
struct btrfs_inode_item *inode_item; struct btrfs_inode_item *inode_item;
struct btrfs_timespec *tspec;
delayed_node = btrfs_get_delayed_node(inode); delayed_node = btrfs_get_delayed_node(inode);
if (!delayed_node) if (!delayed_node)
...@@ -1802,17 +1806,19 @@ int btrfs_fill_inode(struct inode *inode, u32 *rdev) ...@@ -1802,17 +1806,19 @@ int btrfs_fill_inode(struct inode *inode, u32 *rdev)
*rdev = btrfs_stack_inode_rdev(inode_item); *rdev = btrfs_stack_inode_rdev(inode_item);
BTRFS_I(inode)->flags = btrfs_stack_inode_flags(inode_item); BTRFS_I(inode)->flags = btrfs_stack_inode_flags(inode_item);
tspec = btrfs_inode_atime(inode_item); inode->i_atime.tv_sec = btrfs_stack_timespec_sec(&inode_item->atime);
inode->i_atime.tv_sec = btrfs_stack_timespec_sec(tspec); inode->i_atime.tv_nsec = btrfs_stack_timespec_nsec(&inode_item->atime);
inode->i_atime.tv_nsec = btrfs_stack_timespec_nsec(tspec);
inode->i_mtime.tv_sec = btrfs_stack_timespec_sec(&inode_item->mtime);
inode->i_mtime.tv_nsec = btrfs_stack_timespec_nsec(&inode_item->mtime);
tspec = btrfs_inode_mtime(inode_item); inode->i_ctime.tv_sec = btrfs_stack_timespec_sec(&inode_item->ctime);
inode->i_mtime.tv_sec = btrfs_stack_timespec_sec(tspec); inode->i_ctime.tv_nsec = btrfs_stack_timespec_nsec(&inode_item->ctime);
inode->i_mtime.tv_nsec = btrfs_stack_timespec_nsec(tspec);
tspec = btrfs_inode_ctime(inode_item); BTRFS_I(inode)->i_otime.tv_sec =
inode->i_ctime.tv_sec = btrfs_stack_timespec_sec(tspec); btrfs_stack_timespec_sec(&inode_item->otime);
inode->i_ctime.tv_nsec = btrfs_stack_timespec_nsec(tspec); BTRFS_I(inode)->i_otime.tv_nsec =
btrfs_stack_timespec_nsec(&inode_item->otime);
inode->i_generation = BTRFS_I(inode)->generation; inode->i_generation = BTRFS_I(inode)->generation;
BTRFS_I(inode)->index_cnt = (u64)-1; BTRFS_I(inode)->index_cnt = (u64)-1;
......
...@@ -440,18 +440,9 @@ int btrfs_dev_replace_start(struct btrfs_root *root, ...@@ -440,18 +440,9 @@ int btrfs_dev_replace_start(struct btrfs_root *root,
*/ */
static void btrfs_rm_dev_replace_blocked(struct btrfs_fs_info *fs_info) static void btrfs_rm_dev_replace_blocked(struct btrfs_fs_info *fs_info)
{ {
s64 writers;
DEFINE_WAIT(wait);
set_bit(BTRFS_FS_STATE_DEV_REPLACING, &fs_info->fs_state); set_bit(BTRFS_FS_STATE_DEV_REPLACING, &fs_info->fs_state);
do { wait_event(fs_info->replace_wait, !percpu_counter_sum(
prepare_to_wait(&fs_info->replace_wait, &wait, &fs_info->bio_counter));
TASK_UNINTERRUPTIBLE);
writers = percpu_counter_sum(&fs_info->bio_counter);
if (writers)
schedule();
finish_wait(&fs_info->replace_wait, &wait);
} while (writers);
} }
/* /*
...@@ -932,15 +923,15 @@ void btrfs_bio_counter_sub(struct btrfs_fs_info *fs_info, s64 amount) ...@@ -932,15 +923,15 @@ void btrfs_bio_counter_sub(struct btrfs_fs_info *fs_info, s64 amount)
void btrfs_bio_counter_inc_blocked(struct btrfs_fs_info *fs_info) void btrfs_bio_counter_inc_blocked(struct btrfs_fs_info *fs_info)
{ {
DEFINE_WAIT(wait); while (1) {
again: percpu_counter_inc(&fs_info->bio_counter);
percpu_counter_inc(&fs_info->bio_counter); if (likely(!test_bit(BTRFS_FS_STATE_DEV_REPLACING,
if (test_bit(BTRFS_FS_STATE_DEV_REPLACING, &fs_info->fs_state)) { &fs_info->fs_state)))
break;
btrfs_bio_counter_dec(fs_info); btrfs_bio_counter_dec(fs_info);
wait_event(fs_info->replace_wait, wait_event(fs_info->replace_wait,
!test_bit(BTRFS_FS_STATE_DEV_REPLACING, !test_bit(BTRFS_FS_STATE_DEV_REPLACING,
&fs_info->fs_state)); &fs_info->fs_state));
goto again;
} }
} }
This diff is collapsed.
...@@ -46,11 +46,11 @@ struct btrfs_fs_devices; ...@@ -46,11 +46,11 @@ struct btrfs_fs_devices;
struct extent_buffer *read_tree_block(struct btrfs_root *root, u64 bytenr, struct extent_buffer *read_tree_block(struct btrfs_root *root, u64 bytenr,
u64 parent_transid); u64 parent_transid);
void readahead_tree_block(struct btrfs_root *root, u64 bytenr, u32 blocksize); void readahead_tree_block(struct btrfs_root *root, u64 bytenr);
int reada_tree_block_flagged(struct btrfs_root *root, u64 bytenr, u32 blocksize, int reada_tree_block_flagged(struct btrfs_root *root, u64 bytenr,
int mirror_num, struct extent_buffer **eb); int mirror_num, struct extent_buffer **eb);
struct extent_buffer *btrfs_find_create_tree_block(struct btrfs_root *root, struct extent_buffer *btrfs_find_create_tree_block(struct btrfs_root *root,
u64 bytenr, u32 blocksize); u64 bytenr);
void clean_tree_block(struct btrfs_trans_handle *trans, void clean_tree_block(struct btrfs_trans_handle *trans,
struct btrfs_root *root, struct extent_buffer *buf); struct btrfs_root *root, struct extent_buffer *buf);
int open_ctree(struct super_block *sb, int open_ctree(struct super_block *sb,
......
This diff is collapsed.
This diff is collapsed.
...@@ -4,22 +4,22 @@ ...@@ -4,22 +4,22 @@
#include <linux/rbtree.h> #include <linux/rbtree.h>
/* bits for the extent state */ /* bits for the extent state */
#define EXTENT_DIRTY 1 #define EXTENT_DIRTY (1U << 0)
#define EXTENT_WRITEBACK (1 << 1) #define EXTENT_WRITEBACK (1U << 1)
#define EXTENT_UPTODATE (1 << 2) #define EXTENT_UPTODATE (1U << 2)
#define EXTENT_LOCKED (1 << 3) #define EXTENT_LOCKED (1U << 3)
#define EXTENT_NEW (1 << 4) #define EXTENT_NEW (1U << 4)
#define EXTENT_DELALLOC (1 << 5) #define EXTENT_DELALLOC (1U << 5)
#define EXTENT_DEFRAG (1 << 6) #define EXTENT_DEFRAG (1U << 6)
#define EXTENT_BOUNDARY (1 << 9) #define EXTENT_BOUNDARY (1U << 9)
#define EXTENT_NODATASUM (1 << 10) #define EXTENT_NODATASUM (1U << 10)
#define EXTENT_DO_ACCOUNTING (1 << 11) #define EXTENT_DO_ACCOUNTING (1U << 11)
#define EXTENT_FIRST_DELALLOC (1 << 12) #define EXTENT_FIRST_DELALLOC (1U << 12)
#define EXTENT_NEED_WAIT (1 << 13) #define EXTENT_NEED_WAIT (1U << 13)
#define EXTENT_DAMAGED (1 << 14) #define EXTENT_DAMAGED (1U << 14)
#define EXTENT_NORESERVE (1 << 15) #define EXTENT_NORESERVE (1U << 15)
#define EXTENT_IOBITS (EXTENT_LOCKED | EXTENT_WRITEBACK) #define EXTENT_IOBITS (EXTENT_LOCKED | EXTENT_WRITEBACK)
#define EXTENT_CTLBITS (EXTENT_DO_ACCOUNTING | EXTENT_FIRST_DELALLOC) #define EXTENT_CTLBITS (EXTENT_DO_ACCOUNTING | EXTENT_FIRST_DELALLOC)
/* /*
* flags for bio submission. The high bits indicate the compression * flags for bio submission. The high bits indicate the compression
...@@ -81,9 +81,9 @@ struct extent_io_ops { ...@@ -81,9 +81,9 @@ struct extent_io_ops {
int (*writepage_end_io_hook)(struct page *page, u64 start, u64 end, int (*writepage_end_io_hook)(struct page *page, u64 start, u64 end,
struct extent_state *state, int uptodate); struct extent_state *state, int uptodate);
void (*set_bit_hook)(struct inode *inode, struct extent_state *state, void (*set_bit_hook)(struct inode *inode, struct extent_state *state,
unsigned long *bits); unsigned *bits);
void (*clear_bit_hook)(struct inode *inode, struct extent_state *state, void (*clear_bit_hook)(struct inode *inode, struct extent_state *state,
unsigned long *bits); unsigned *bits);
void (*merge_extent_hook)(struct inode *inode, void (*merge_extent_hook)(struct inode *inode,
struct extent_state *new, struct extent_state *new,
struct extent_state *other); struct extent_state *other);
...@@ -108,7 +108,7 @@ struct extent_state { ...@@ -108,7 +108,7 @@ struct extent_state {
/* ADD NEW ELEMENTS AFTER THIS */ /* ADD NEW ELEMENTS AFTER THIS */
wait_queue_head_t wq; wait_queue_head_t wq;
atomic_t refs; atomic_t refs;
unsigned long state; unsigned state;
/* for use by the FS */ /* for use by the FS */
u64 private; u64 private;
...@@ -188,7 +188,7 @@ int try_release_extent_mapping(struct extent_map_tree *map, ...@@ -188,7 +188,7 @@ int try_release_extent_mapping(struct extent_map_tree *map,
int try_release_extent_buffer(struct page *page); int try_release_extent_buffer(struct page *page);
int lock_extent(struct extent_io_tree *tree, u64 start, u64 end); int lock_extent(struct extent_io_tree *tree, u64 start, u64 end);
int lock_extent_bits(struct extent_io_tree *tree, u64 start, u64 end, int lock_extent_bits(struct extent_io_tree *tree, u64 start, u64 end,
unsigned long bits, struct extent_state **cached); unsigned bits, struct extent_state **cached);
int unlock_extent(struct extent_io_tree *tree, u64 start, u64 end); int unlock_extent(struct extent_io_tree *tree, u64 start, u64 end);
int unlock_extent_cached(struct extent_io_tree *tree, u64 start, u64 end, int unlock_extent_cached(struct extent_io_tree *tree, u64 start, u64 end,
struct extent_state **cached, gfp_t mask); struct extent_state **cached, gfp_t mask);
...@@ -202,21 +202,21 @@ void extent_io_exit(void); ...@@ -202,21 +202,21 @@ void extent_io_exit(void);
u64 count_range_bits(struct extent_io_tree *tree, u64 count_range_bits(struct extent_io_tree *tree,
u64 *start, u64 search_end, u64 *start, u64 search_end,
u64 max_bytes, unsigned long bits, int contig); u64 max_bytes, unsigned bits, int contig);
void free_extent_state(struct extent_state *state); void free_extent_state(struct extent_state *state);
int test_range_bit(struct extent_io_tree *tree, u64 start, u64 end, int test_range_bit(struct extent_io_tree *tree, u64 start, u64 end,
unsigned long bits, int filled, unsigned bits, int filled,
struct extent_state *cached_state); struct extent_state *cached_state);
int clear_extent_bits(struct extent_io_tree *tree, u64 start, u64 end, int clear_extent_bits(struct extent_io_tree *tree, u64 start, u64 end,
unsigned long bits, gfp_t mask); unsigned bits, gfp_t mask);
int clear_extent_bit(struct extent_io_tree *tree, u64 start, u64 end, int clear_extent_bit(struct extent_io_tree *tree, u64 start, u64 end,
unsigned long bits, int wake, int delete, unsigned bits, int wake, int delete,
struct extent_state **cached, gfp_t mask); struct extent_state **cached, gfp_t mask);
int set_extent_bits(struct extent_io_tree *tree, u64 start, u64 end, int set_extent_bits(struct extent_io_tree *tree, u64 start, u64 end,
unsigned long bits, gfp_t mask); unsigned bits, gfp_t mask);
int set_extent_bit(struct extent_io_tree *tree, u64 start, u64 end, int set_extent_bit(struct extent_io_tree *tree, u64 start, u64 end,
unsigned long bits, u64 *failed_start, unsigned bits, u64 *failed_start,
struct extent_state **cached_state, gfp_t mask); struct extent_state **cached_state, gfp_t mask);
int set_extent_uptodate(struct extent_io_tree *tree, u64 start, u64 end, int set_extent_uptodate(struct extent_io_tree *tree, u64 start, u64 end,
struct extent_state **cached_state, gfp_t mask); struct extent_state **cached_state, gfp_t mask);
...@@ -229,14 +229,14 @@ int set_extent_dirty(struct extent_io_tree *tree, u64 start, u64 end, ...@@ -229,14 +229,14 @@ int set_extent_dirty(struct extent_io_tree *tree, u64 start, u64 end,
int clear_extent_dirty(struct extent_io_tree *tree, u64 start, u64 end, int clear_extent_dirty(struct extent_io_tree *tree, u64 start, u64 end,
gfp_t mask); gfp_t mask);
int convert_extent_bit(struct extent_io_tree *tree, u64 start, u64 end, int convert_extent_bit(struct extent_io_tree *tree, u64 start, u64 end,
unsigned long bits, unsigned long clear_bits, unsigned bits, unsigned clear_bits,
struct extent_state **cached_state, gfp_t mask); struct extent_state **cached_state, gfp_t mask);
int set_extent_delalloc(struct extent_io_tree *tree, u64 start, u64 end, int set_extent_delalloc(struct extent_io_tree *tree, u64 start, u64 end,
struct extent_state **cached_state, gfp_t mask); struct extent_state **cached_state, gfp_t mask);
int set_extent_defrag(struct extent_io_tree *tree, u64 start, u64 end, int set_extent_defrag(struct extent_io_tree *tree, u64 start, u64 end,
struct extent_state **cached_state, gfp_t mask); struct extent_state **cached_state, gfp_t mask);
int find_first_extent_bit(struct extent_io_tree *tree, u64 start, int find_first_extent_bit(struct extent_io_tree *tree, u64 start,
u64 *start_ret, u64 *end_ret, unsigned long bits, u64 *start_ret, u64 *end_ret, unsigned bits,
struct extent_state **cached_state); struct extent_state **cached_state);
int extent_invalidatepage(struct extent_io_tree *tree, int extent_invalidatepage(struct extent_io_tree *tree,
struct page *page, unsigned long offset); struct page *page, unsigned long offset);
...@@ -262,8 +262,9 @@ int get_state_private(struct extent_io_tree *tree, u64 start, u64 *private); ...@@ -262,8 +262,9 @@ int get_state_private(struct extent_io_tree *tree, u64 start, u64 *private);
void set_page_extent_mapped(struct page *page); void set_page_extent_mapped(struct page *page);
struct extent_buffer *alloc_extent_buffer(struct btrfs_fs_info *fs_info, struct extent_buffer *alloc_extent_buffer(struct btrfs_fs_info *fs_info,
u64 start, unsigned long len); u64 start);
struct extent_buffer *alloc_dummy_extent_buffer(u64 start, unsigned long len); struct extent_buffer *alloc_dummy_extent_buffer(struct btrfs_fs_info *fs_info,
u64 start);
struct extent_buffer *btrfs_clone_extent_buffer(struct extent_buffer *src); struct extent_buffer *btrfs_clone_extent_buffer(struct extent_buffer *src);
struct extent_buffer *find_extent_buffer(struct btrfs_fs_info *fs_info, struct extent_buffer *find_extent_buffer(struct btrfs_fs_info *fs_info,
u64 start); u64 start);
...@@ -322,7 +323,7 @@ int extent_range_clear_dirty_for_io(struct inode *inode, u64 start, u64 end); ...@@ -322,7 +323,7 @@ int extent_range_clear_dirty_for_io(struct inode *inode, u64 start, u64 end);
int extent_range_redirty_for_io(struct inode *inode, u64 start, u64 end); int extent_range_redirty_for_io(struct inode *inode, u64 start, u64 end);
int extent_clear_unlock_delalloc(struct inode *inode, u64 start, u64 end, int extent_clear_unlock_delalloc(struct inode *inode, u64 start, u64 end,
struct page *locked_page, struct page *locked_page,
unsigned long bits_to_clear, unsigned bits_to_clear,
unsigned long page_ops); unsigned long page_ops);
struct bio * struct bio *
btrfs_bio_alloc(struct block_device *bdev, u64 first_sector, int nr_vecs, btrfs_bio_alloc(struct block_device *bdev, u64 first_sector, int nr_vecs,
...@@ -377,5 +378,5 @@ noinline u64 find_lock_delalloc_range(struct inode *inode, ...@@ -377,5 +378,5 @@ noinline u64 find_lock_delalloc_range(struct inode *inode,
u64 *end, u64 max_bytes); u64 *end, u64 max_bytes);
#endif #endif
struct extent_buffer *alloc_test_extent_buffer(struct btrfs_fs_info *fs_info, struct extent_buffer *alloc_test_extent_buffer(struct btrfs_fs_info *fs_info,
u64 start, unsigned long len); u64 start);
#endif #endif
...@@ -651,15 +651,13 @@ static int __load_free_space_cache(struct btrfs_root *root, struct inode *inode, ...@@ -651,15 +651,13 @@ static int __load_free_space_cache(struct btrfs_root *root, struct inode *inode,
struct io_ctl io_ctl; struct io_ctl io_ctl;
struct btrfs_key key; struct btrfs_key key;
struct btrfs_free_space *e, *n; struct btrfs_free_space *e, *n;
struct list_head bitmaps; LIST_HEAD(bitmaps);
u64 num_entries; u64 num_entries;
u64 num_bitmaps; u64 num_bitmaps;
u64 generation; u64 generation;
u8 type; u8 type;
int ret = 0; int ret = 0;
INIT_LIST_HEAD(&bitmaps);
/* Nothing in the space cache, goodbye */ /* Nothing in the space cache, goodbye */
if (!i_size_read(inode)) if (!i_size_read(inode))
return 0; return 0;
...@@ -1243,6 +1241,7 @@ int btrfs_write_out_cache(struct btrfs_root *root, ...@@ -1243,6 +1241,7 @@ int btrfs_write_out_cache(struct btrfs_root *root,
struct btrfs_free_space_ctl *ctl = block_group->free_space_ctl; struct btrfs_free_space_ctl *ctl = block_group->free_space_ctl;
struct inode *inode; struct inode *inode;
int ret = 0; int ret = 0;
enum btrfs_disk_cache_state dcs = BTRFS_DC_WRITTEN;
root = root->fs_info->tree_root; root = root->fs_info->tree_root;
...@@ -1266,9 +1265,7 @@ int btrfs_write_out_cache(struct btrfs_root *root, ...@@ -1266,9 +1265,7 @@ int btrfs_write_out_cache(struct btrfs_root *root,
ret = __btrfs_write_out_cache(root, inode, ctl, block_group, trans, ret = __btrfs_write_out_cache(root, inode, ctl, block_group, trans,
path, block_group->key.objectid); path, block_group->key.objectid);
if (ret) { if (ret) {
spin_lock(&block_group->lock); dcs = BTRFS_DC_ERROR;
block_group->disk_cache_state = BTRFS_DC_ERROR;
spin_unlock(&block_group->lock);
ret = 0; ret = 0;
#ifdef DEBUG #ifdef DEBUG
btrfs_err(root->fs_info, btrfs_err(root->fs_info,
...@@ -1277,6 +1274,9 @@ int btrfs_write_out_cache(struct btrfs_root *root, ...@@ -1277,6 +1274,9 @@ int btrfs_write_out_cache(struct btrfs_root *root,
#endif #endif
} }
spin_lock(&block_group->lock);
block_group->disk_cache_state = dcs;
spin_unlock(&block_group->lock);
iput(inode); iput(inode);
return ret; return ret;
} }
...@@ -2903,7 +2903,6 @@ int btrfs_find_space_cluster(struct btrfs_root *root, ...@@ -2903,7 +2903,6 @@ int btrfs_find_space_cluster(struct btrfs_root *root,
trace_btrfs_find_cluster(block_group, offset, bytes, empty_size, trace_btrfs_find_cluster(block_group, offset, bytes, empty_size,
min_bytes); min_bytes);
INIT_LIST_HEAD(&bitmaps);
ret = setup_cluster_no_bitmap(block_group, cluster, &bitmaps, offset, ret = setup_cluster_no_bitmap(block_group, cluster, &bitmaps, offset,
bytes + empty_size, bytes + empty_size,
cont1_bytes, min_bytes); cont1_bytes, min_bytes);
......
...@@ -344,6 +344,7 @@ int btrfs_insert_inode_ref(struct btrfs_trans_handle *trans, ...@@ -344,6 +344,7 @@ int btrfs_insert_inode_ref(struct btrfs_trans_handle *trans,
return -ENOMEM; return -ENOMEM;
path->leave_spinning = 1; path->leave_spinning = 1;
path->skip_release_on_error = 1;
ret = btrfs_insert_empty_item(trans, root, path, &key, ret = btrfs_insert_empty_item(trans, root, path, &key,
ins_len); ins_len);
if (ret == -EEXIST) { if (ret == -EEXIST) {
...@@ -362,8 +363,12 @@ int btrfs_insert_inode_ref(struct btrfs_trans_handle *trans, ...@@ -362,8 +363,12 @@ int btrfs_insert_inode_ref(struct btrfs_trans_handle *trans,
ptr = (unsigned long)(ref + 1); ptr = (unsigned long)(ref + 1);
ret = 0; ret = 0;
} else if (ret < 0) { } else if (ret < 0) {
if (ret == -EOVERFLOW) if (ret == -EOVERFLOW) {
ret = -EMLINK; if (find_name_in_backref(path, name, name_len, &ref))
ret = -EEXIST;
else
ret = -EMLINK;
}
goto out; goto out;
} else { } else {
ref = btrfs_item_ptr(path->nodes[0], path->slots[0], ref = btrfs_item_ptr(path->nodes[0], path->slots[0],
......
This diff is collapsed.
...@@ -1431,9 +1431,8 @@ static int qgroup_excl_accounting(struct btrfs_fs_info *fs_info, ...@@ -1431,9 +1431,8 @@ static int qgroup_excl_accounting(struct btrfs_fs_info *fs_info,
qgroup = u64_to_ptr(unode->aux); qgroup = u64_to_ptr(unode->aux);
qgroup->rfer += sign * oper->num_bytes; qgroup->rfer += sign * oper->num_bytes;
qgroup->rfer_cmpr += sign * oper->num_bytes; qgroup->rfer_cmpr += sign * oper->num_bytes;
WARN_ON(sign < 0 && qgroup->excl < oper->num_bytes);
qgroup->excl += sign * oper->num_bytes; qgroup->excl += sign * oper->num_bytes;
if (sign < 0)
WARN_ON(qgroup->excl < oper->num_bytes);
qgroup->excl_cmpr += sign * oper->num_bytes; qgroup->excl_cmpr += sign * oper->num_bytes;
qgroup_dirty(fs_info, qgroup); qgroup_dirty(fs_info, qgroup);
......
...@@ -58,15 +58,6 @@ ...@@ -58,15 +58,6 @@
*/ */
#define RBIO_CACHE_READY_BIT 3 #define RBIO_CACHE_READY_BIT 3
/*
* bbio and raid_map is managed by the caller, so we shouldn't free
* them here. And besides that, all rbios with this flag should not
* be cached, because we need raid_map to check the rbios' stripe
* is the same or not, but it is very likely that the caller has
* free raid_map, so don't cache those rbios.
*/
#define RBIO_HOLD_BBIO_MAP_BIT 4
#define RBIO_CACHE_SIZE 1024 #define RBIO_CACHE_SIZE 1024
enum btrfs_rbio_ops { enum btrfs_rbio_ops {
...@@ -79,13 +70,6 @@ struct btrfs_raid_bio { ...@@ -79,13 +70,6 @@ struct btrfs_raid_bio {
struct btrfs_fs_info *fs_info; struct btrfs_fs_info *fs_info;
struct btrfs_bio *bbio; struct btrfs_bio *bbio;
/*
* logical block numbers for the start of each stripe
* The last one or two are p/q. These are sorted,
* so raid_map[0] is the start of our full stripe
*/
u64 *raid_map;
/* while we're doing rmw on a stripe /* while we're doing rmw on a stripe
* we put it into a hash table so we can * we put it into a hash table so we can
* lock the stripe and merge more rbios * lock the stripe and merge more rbios
...@@ -303,7 +287,7 @@ static void cache_rbio_pages(struct btrfs_raid_bio *rbio) ...@@ -303,7 +287,7 @@ static void cache_rbio_pages(struct btrfs_raid_bio *rbio)
*/ */
static int rbio_bucket(struct btrfs_raid_bio *rbio) static int rbio_bucket(struct btrfs_raid_bio *rbio)
{ {
u64 num = rbio->raid_map[0]; u64 num = rbio->bbio->raid_map[0];
/* /*
* we shift down quite a bit. We're using byte * we shift down quite a bit. We're using byte
...@@ -606,8 +590,8 @@ static int rbio_can_merge(struct btrfs_raid_bio *last, ...@@ -606,8 +590,8 @@ static int rbio_can_merge(struct btrfs_raid_bio *last,
test_bit(RBIO_CACHE_BIT, &cur->flags)) test_bit(RBIO_CACHE_BIT, &cur->flags))
return 0; return 0;
if (last->raid_map[0] != if (last->bbio->raid_map[0] !=
cur->raid_map[0]) cur->bbio->raid_map[0])
return 0; return 0;
/* we can't merge with different operations */ /* we can't merge with different operations */
...@@ -689,7 +673,7 @@ static noinline int lock_stripe_add(struct btrfs_raid_bio *rbio) ...@@ -689,7 +673,7 @@ static noinline int lock_stripe_add(struct btrfs_raid_bio *rbio)
spin_lock_irqsave(&h->lock, flags); spin_lock_irqsave(&h->lock, flags);
list_for_each_entry(cur, &h->hash_list, hash_list) { list_for_each_entry(cur, &h->hash_list, hash_list) {
walk++; walk++;
if (cur->raid_map[0] == rbio->raid_map[0]) { if (cur->bbio->raid_map[0] == rbio->bbio->raid_map[0]) {
spin_lock(&cur->bio_list_lock); spin_lock(&cur->bio_list_lock);
/* can we steal this cached rbio's pages? */ /* can we steal this cached rbio's pages? */
...@@ -841,21 +825,6 @@ static noinline void unlock_stripe(struct btrfs_raid_bio *rbio) ...@@ -841,21 +825,6 @@ static noinline void unlock_stripe(struct btrfs_raid_bio *rbio)
remove_rbio_from_cache(rbio); remove_rbio_from_cache(rbio);
} }
static inline void
__free_bbio_and_raid_map(struct btrfs_bio *bbio, u64 *raid_map, int need)
{
if (need) {
kfree(raid_map);
kfree(bbio);
}
}
static inline void free_bbio_and_raid_map(struct btrfs_raid_bio *rbio)
{
__free_bbio_and_raid_map(rbio->bbio, rbio->raid_map,
!test_bit(RBIO_HOLD_BBIO_MAP_BIT, &rbio->flags));
}
static void __free_raid_bio(struct btrfs_raid_bio *rbio) static void __free_raid_bio(struct btrfs_raid_bio *rbio)
{ {
int i; int i;
...@@ -875,8 +844,7 @@ static void __free_raid_bio(struct btrfs_raid_bio *rbio) ...@@ -875,8 +844,7 @@ static void __free_raid_bio(struct btrfs_raid_bio *rbio)
} }
} }
free_bbio_and_raid_map(rbio); btrfs_put_bbio(rbio->bbio);
kfree(rbio); kfree(rbio);
} }
...@@ -985,8 +953,7 @@ static unsigned long rbio_nr_pages(unsigned long stripe_len, int nr_stripes) ...@@ -985,8 +953,7 @@ static unsigned long rbio_nr_pages(unsigned long stripe_len, int nr_stripes)
* this does not allocate any pages for rbio->pages. * this does not allocate any pages for rbio->pages.
*/ */
static struct btrfs_raid_bio *alloc_rbio(struct btrfs_root *root, static struct btrfs_raid_bio *alloc_rbio(struct btrfs_root *root,
struct btrfs_bio *bbio, u64 *raid_map, struct btrfs_bio *bbio, u64 stripe_len)
u64 stripe_len)
{ {
struct btrfs_raid_bio *rbio; struct btrfs_raid_bio *rbio;
int nr_data = 0; int nr_data = 0;
...@@ -1007,7 +974,6 @@ static struct btrfs_raid_bio *alloc_rbio(struct btrfs_root *root, ...@@ -1007,7 +974,6 @@ static struct btrfs_raid_bio *alloc_rbio(struct btrfs_root *root,
INIT_LIST_HEAD(&rbio->stripe_cache); INIT_LIST_HEAD(&rbio->stripe_cache);
INIT_LIST_HEAD(&rbio->hash_list); INIT_LIST_HEAD(&rbio->hash_list);
rbio->bbio = bbio; rbio->bbio = bbio;
rbio->raid_map = raid_map;
rbio->fs_info = root->fs_info; rbio->fs_info = root->fs_info;
rbio->stripe_len = stripe_len; rbio->stripe_len = stripe_len;
rbio->nr_pages = num_pages; rbio->nr_pages = num_pages;
...@@ -1028,10 +994,12 @@ static struct btrfs_raid_bio *alloc_rbio(struct btrfs_root *root, ...@@ -1028,10 +994,12 @@ static struct btrfs_raid_bio *alloc_rbio(struct btrfs_root *root,
rbio->bio_pages = p + sizeof(struct page *) * num_pages; rbio->bio_pages = p + sizeof(struct page *) * num_pages;
rbio->dbitmap = p + sizeof(struct page *) * num_pages * 2; rbio->dbitmap = p + sizeof(struct page *) * num_pages * 2;
if (raid_map[real_stripes - 1] == RAID6_Q_STRIPE) if (bbio->map_type & BTRFS_BLOCK_GROUP_RAID5)
nr_data = real_stripes - 1;
else if (bbio->map_type & BTRFS_BLOCK_GROUP_RAID6)
nr_data = real_stripes - 2; nr_data = real_stripes - 2;
else else
nr_data = real_stripes - 1; BUG();
rbio->nr_data = nr_data; rbio->nr_data = nr_data;
return rbio; return rbio;
...@@ -1182,7 +1150,7 @@ static void index_rbio_pages(struct btrfs_raid_bio *rbio) ...@@ -1182,7 +1150,7 @@ static void index_rbio_pages(struct btrfs_raid_bio *rbio)
spin_lock_irq(&rbio->bio_list_lock); spin_lock_irq(&rbio->bio_list_lock);
bio_list_for_each(bio, &rbio->bio_list) { bio_list_for_each(bio, &rbio->bio_list) {
start = (u64)bio->bi_iter.bi_sector << 9; start = (u64)bio->bi_iter.bi_sector << 9;
stripe_offset = start - rbio->raid_map[0]; stripe_offset = start - rbio->bbio->raid_map[0];
page_index = stripe_offset >> PAGE_CACHE_SHIFT; page_index = stripe_offset >> PAGE_CACHE_SHIFT;
for (i = 0; i < bio->bi_vcnt; i++) { for (i = 0; i < bio->bi_vcnt; i++) {
...@@ -1402,7 +1370,7 @@ static int find_logical_bio_stripe(struct btrfs_raid_bio *rbio, ...@@ -1402,7 +1370,7 @@ static int find_logical_bio_stripe(struct btrfs_raid_bio *rbio,
logical <<= 9; logical <<= 9;
for (i = 0; i < rbio->nr_data; i++) { for (i = 0; i < rbio->nr_data; i++) {
stripe_start = rbio->raid_map[i]; stripe_start = rbio->bbio->raid_map[i];
if (logical >= stripe_start && if (logical >= stripe_start &&
logical < stripe_start + rbio->stripe_len) { logical < stripe_start + rbio->stripe_len) {
return i; return i;
...@@ -1776,17 +1744,16 @@ static void btrfs_raid_unplug(struct blk_plug_cb *cb, bool from_schedule) ...@@ -1776,17 +1744,16 @@ static void btrfs_raid_unplug(struct blk_plug_cb *cb, bool from_schedule)
* our main entry point for writes from the rest of the FS. * our main entry point for writes from the rest of the FS.
*/ */
int raid56_parity_write(struct btrfs_root *root, struct bio *bio, int raid56_parity_write(struct btrfs_root *root, struct bio *bio,
struct btrfs_bio *bbio, u64 *raid_map, struct btrfs_bio *bbio, u64 stripe_len)
u64 stripe_len)
{ {
struct btrfs_raid_bio *rbio; struct btrfs_raid_bio *rbio;
struct btrfs_plug_cb *plug = NULL; struct btrfs_plug_cb *plug = NULL;
struct blk_plug_cb *cb; struct blk_plug_cb *cb;
int ret; int ret;
rbio = alloc_rbio(root, bbio, raid_map, stripe_len); rbio = alloc_rbio(root, bbio, stripe_len);
if (IS_ERR(rbio)) { if (IS_ERR(rbio)) {
__free_bbio_and_raid_map(bbio, raid_map, 1); btrfs_put_bbio(bbio);
return PTR_ERR(rbio); return PTR_ERR(rbio);
} }
bio_list_add(&rbio->bio_list, bio); bio_list_add(&rbio->bio_list, bio);
...@@ -1885,9 +1852,7 @@ static void __raid_recover_end_io(struct btrfs_raid_bio *rbio) ...@@ -1885,9 +1852,7 @@ static void __raid_recover_end_io(struct btrfs_raid_bio *rbio)
} }
/* all raid6 handling here */ /* all raid6 handling here */
if (rbio->raid_map[rbio->real_stripes - 1] == if (rbio->bbio->map_type & BTRFS_BLOCK_GROUP_RAID6) {
RAID6_Q_STRIPE) {
/* /*
* single failure, rebuild from parity raid5 * single failure, rebuild from parity raid5
* style * style
...@@ -1922,8 +1887,9 @@ static void __raid_recover_end_io(struct btrfs_raid_bio *rbio) ...@@ -1922,8 +1887,9 @@ static void __raid_recover_end_io(struct btrfs_raid_bio *rbio)
* here due to a crc mismatch and we can't give them the * here due to a crc mismatch and we can't give them the
* data they want * data they want
*/ */
if (rbio->raid_map[failb] == RAID6_Q_STRIPE) { if (rbio->bbio->raid_map[failb] == RAID6_Q_STRIPE) {
if (rbio->raid_map[faila] == RAID5_P_STRIPE) { if (rbio->bbio->raid_map[faila] ==
RAID5_P_STRIPE) {
err = -EIO; err = -EIO;
goto cleanup; goto cleanup;
} }
...@@ -1934,7 +1900,7 @@ static void __raid_recover_end_io(struct btrfs_raid_bio *rbio) ...@@ -1934,7 +1900,7 @@ static void __raid_recover_end_io(struct btrfs_raid_bio *rbio)
goto pstripe; goto pstripe;
} }
if (rbio->raid_map[failb] == RAID5_P_STRIPE) { if (rbio->bbio->raid_map[failb] == RAID5_P_STRIPE) {
raid6_datap_recov(rbio->real_stripes, raid6_datap_recov(rbio->real_stripes,
PAGE_SIZE, faila, pointers); PAGE_SIZE, faila, pointers);
} else { } else {
...@@ -2001,8 +1967,7 @@ static void __raid_recover_end_io(struct btrfs_raid_bio *rbio) ...@@ -2001,8 +1967,7 @@ static void __raid_recover_end_io(struct btrfs_raid_bio *rbio)
cleanup_io: cleanup_io:
if (rbio->operation == BTRFS_RBIO_READ_REBUILD) { if (rbio->operation == BTRFS_RBIO_READ_REBUILD) {
if (err == 0 && if (err == 0)
!test_bit(RBIO_HOLD_BBIO_MAP_BIT, &rbio->flags))
cache_rbio_pages(rbio); cache_rbio_pages(rbio);
else else
clear_bit(RBIO_CACHE_READY_BIT, &rbio->flags); clear_bit(RBIO_CACHE_READY_BIT, &rbio->flags);
...@@ -2156,15 +2121,16 @@ static int __raid56_parity_recover(struct btrfs_raid_bio *rbio) ...@@ -2156,15 +2121,16 @@ static int __raid56_parity_recover(struct btrfs_raid_bio *rbio)
* of the drive. * of the drive.
*/ */
int raid56_parity_recover(struct btrfs_root *root, struct bio *bio, int raid56_parity_recover(struct btrfs_root *root, struct bio *bio,
struct btrfs_bio *bbio, u64 *raid_map, struct btrfs_bio *bbio, u64 stripe_len,
u64 stripe_len, int mirror_num, int generic_io) int mirror_num, int generic_io)
{ {
struct btrfs_raid_bio *rbio; struct btrfs_raid_bio *rbio;
int ret; int ret;
rbio = alloc_rbio(root, bbio, raid_map, stripe_len); rbio = alloc_rbio(root, bbio, stripe_len);
if (IS_ERR(rbio)) { if (IS_ERR(rbio)) {
__free_bbio_and_raid_map(bbio, raid_map, generic_io); if (generic_io)
btrfs_put_bbio(bbio);
return PTR_ERR(rbio); return PTR_ERR(rbio);
} }
...@@ -2175,7 +2141,8 @@ int raid56_parity_recover(struct btrfs_root *root, struct bio *bio, ...@@ -2175,7 +2141,8 @@ int raid56_parity_recover(struct btrfs_root *root, struct bio *bio,
rbio->faila = find_logical_bio_stripe(rbio, bio); rbio->faila = find_logical_bio_stripe(rbio, bio);
if (rbio->faila == -1) { if (rbio->faila == -1) {
BUG(); BUG();
__free_bbio_and_raid_map(bbio, raid_map, generic_io); if (generic_io)
btrfs_put_bbio(bbio);
kfree(rbio); kfree(rbio);
return -EIO; return -EIO;
} }
...@@ -2184,7 +2151,7 @@ int raid56_parity_recover(struct btrfs_root *root, struct bio *bio, ...@@ -2184,7 +2151,7 @@ int raid56_parity_recover(struct btrfs_root *root, struct bio *bio,
btrfs_bio_counter_inc_noblocked(root->fs_info); btrfs_bio_counter_inc_noblocked(root->fs_info);
rbio->generic_bio_cnt = 1; rbio->generic_bio_cnt = 1;
} else { } else {
set_bit(RBIO_HOLD_BBIO_MAP_BIT, &rbio->flags); btrfs_get_bbio(bbio);
} }
/* /*
...@@ -2240,14 +2207,14 @@ static void read_rebuild_work(struct btrfs_work *work) ...@@ -2240,14 +2207,14 @@ static void read_rebuild_work(struct btrfs_work *work)
struct btrfs_raid_bio * struct btrfs_raid_bio *
raid56_parity_alloc_scrub_rbio(struct btrfs_root *root, struct bio *bio, raid56_parity_alloc_scrub_rbio(struct btrfs_root *root, struct bio *bio,
struct btrfs_bio *bbio, u64 *raid_map, struct btrfs_bio *bbio, u64 stripe_len,
u64 stripe_len, struct btrfs_device *scrub_dev, struct btrfs_device *scrub_dev,
unsigned long *dbitmap, int stripe_nsectors) unsigned long *dbitmap, int stripe_nsectors)
{ {
struct btrfs_raid_bio *rbio; struct btrfs_raid_bio *rbio;
int i; int i;
rbio = alloc_rbio(root, bbio, raid_map, stripe_len); rbio = alloc_rbio(root, bbio, stripe_len);
if (IS_ERR(rbio)) if (IS_ERR(rbio))
return NULL; return NULL;
bio_list_add(&rbio->bio_list, bio); bio_list_add(&rbio->bio_list, bio);
...@@ -2279,10 +2246,10 @@ void raid56_parity_add_scrub_pages(struct btrfs_raid_bio *rbio, ...@@ -2279,10 +2246,10 @@ void raid56_parity_add_scrub_pages(struct btrfs_raid_bio *rbio,
int stripe_offset; int stripe_offset;
int index; int index;
ASSERT(logical >= rbio->raid_map[0]); ASSERT(logical >= rbio->bbio->raid_map[0]);
ASSERT(logical + PAGE_SIZE <= rbio->raid_map[0] + ASSERT(logical + PAGE_SIZE <= rbio->bbio->raid_map[0] +
rbio->stripe_len * rbio->nr_data); rbio->stripe_len * rbio->nr_data);
stripe_offset = (int)(logical - rbio->raid_map[0]); stripe_offset = (int)(logical - rbio->bbio->raid_map[0]);
index = stripe_offset >> PAGE_CACHE_SHIFT; index = stripe_offset >> PAGE_CACHE_SHIFT;
rbio->bio_pages[index] = page; rbio->bio_pages[index] = page;
} }
......
...@@ -43,16 +43,15 @@ struct btrfs_raid_bio; ...@@ -43,16 +43,15 @@ struct btrfs_raid_bio;
struct btrfs_device; struct btrfs_device;
int raid56_parity_recover(struct btrfs_root *root, struct bio *bio, int raid56_parity_recover(struct btrfs_root *root, struct bio *bio,
struct btrfs_bio *bbio, u64 *raid_map, struct btrfs_bio *bbio, u64 stripe_len,
u64 stripe_len, int mirror_num, int generic_io); int mirror_num, int generic_io);
int raid56_parity_write(struct btrfs_root *root, struct bio *bio, int raid56_parity_write(struct btrfs_root *root, struct bio *bio,
struct btrfs_bio *bbio, u64 *raid_map, struct btrfs_bio *bbio, u64 stripe_len);
u64 stripe_len);
struct btrfs_raid_bio * struct btrfs_raid_bio *
raid56_parity_alloc_scrub_rbio(struct btrfs_root *root, struct bio *bio, raid56_parity_alloc_scrub_rbio(struct btrfs_root *root, struct bio *bio,
struct btrfs_bio *bbio, u64 *raid_map, struct btrfs_bio *bbio, u64 stripe_len,
u64 stripe_len, struct btrfs_device *scrub_dev, struct btrfs_device *scrub_dev,
unsigned long *dbitmap, int stripe_nsectors); unsigned long *dbitmap, int stripe_nsectors);
void raid56_parity_add_scrub_pages(struct btrfs_raid_bio *rbio, void raid56_parity_add_scrub_pages(struct btrfs_raid_bio *rbio,
struct page *page, u64 logical); struct page *page, u64 logical);
......
...@@ -66,7 +66,6 @@ struct reada_extctl { ...@@ -66,7 +66,6 @@ struct reada_extctl {
struct reada_extent { struct reada_extent {
u64 logical; u64 logical;
struct btrfs_key top; struct btrfs_key top;
u32 blocksize;
int err; int err;
struct list_head extctl; struct list_head extctl;
int refcnt; int refcnt;
...@@ -349,7 +348,6 @@ static struct reada_extent *reada_find_extent(struct btrfs_root *root, ...@@ -349,7 +348,6 @@ static struct reada_extent *reada_find_extent(struct btrfs_root *root,
blocksize = root->nodesize; blocksize = root->nodesize;
re->logical = logical; re->logical = logical;
re->blocksize = blocksize;
re->top = *top; re->top = *top;
INIT_LIST_HEAD(&re->extctl); INIT_LIST_HEAD(&re->extctl);
spin_lock_init(&re->lock); spin_lock_init(&re->lock);
...@@ -463,7 +461,7 @@ static struct reada_extent *reada_find_extent(struct btrfs_root *root, ...@@ -463,7 +461,7 @@ static struct reada_extent *reada_find_extent(struct btrfs_root *root,
spin_unlock(&fs_info->reada_lock); spin_unlock(&fs_info->reada_lock);
btrfs_dev_replace_unlock(&fs_info->dev_replace); btrfs_dev_replace_unlock(&fs_info->dev_replace);
kfree(bbio); btrfs_put_bbio(bbio);
return re; return re;
error: error:
...@@ -488,7 +486,7 @@ static struct reada_extent *reada_find_extent(struct btrfs_root *root, ...@@ -488,7 +486,7 @@ static struct reada_extent *reada_find_extent(struct btrfs_root *root,
kref_put(&zone->refcnt, reada_zone_release); kref_put(&zone->refcnt, reada_zone_release);
spin_unlock(&fs_info->reada_lock); spin_unlock(&fs_info->reada_lock);
} }
kfree(bbio); btrfs_put_bbio(bbio);
kfree(re); kfree(re);
return re_exist; return re_exist;
} }
...@@ -660,7 +658,6 @@ static int reada_start_machine_dev(struct btrfs_fs_info *fs_info, ...@@ -660,7 +658,6 @@ static int reada_start_machine_dev(struct btrfs_fs_info *fs_info,
int mirror_num = 0; int mirror_num = 0;
struct extent_buffer *eb = NULL; struct extent_buffer *eb = NULL;
u64 logical; u64 logical;
u32 blocksize;
int ret; int ret;
int i; int i;
int need_kick = 0; int need_kick = 0;
...@@ -694,7 +691,7 @@ static int reada_start_machine_dev(struct btrfs_fs_info *fs_info, ...@@ -694,7 +691,7 @@ static int reada_start_machine_dev(struct btrfs_fs_info *fs_info,
spin_unlock(&fs_info->reada_lock); spin_unlock(&fs_info->reada_lock);
return 0; return 0;
} }
dev->reada_next = re->logical + re->blocksize; dev->reada_next = re->logical + fs_info->tree_root->nodesize;
re->refcnt++; re->refcnt++;
spin_unlock(&fs_info->reada_lock); spin_unlock(&fs_info->reada_lock);
...@@ -709,7 +706,6 @@ static int reada_start_machine_dev(struct btrfs_fs_info *fs_info, ...@@ -709,7 +706,6 @@ static int reada_start_machine_dev(struct btrfs_fs_info *fs_info,
} }
} }
logical = re->logical; logical = re->logical;
blocksize = re->blocksize;
spin_lock(&re->lock); spin_lock(&re->lock);
if (re->scheduled_for == NULL) { if (re->scheduled_for == NULL) {
...@@ -724,8 +720,8 @@ static int reada_start_machine_dev(struct btrfs_fs_info *fs_info, ...@@ -724,8 +720,8 @@ static int reada_start_machine_dev(struct btrfs_fs_info *fs_info,
return 0; return 0;
atomic_inc(&dev->reada_in_flight); atomic_inc(&dev->reada_in_flight);
ret = reada_tree_block_flagged(fs_info->extent_root, logical, blocksize, ret = reada_tree_block_flagged(fs_info->extent_root, logical,
mirror_num, &eb); mirror_num, &eb);
if (ret) if (ret)
__readahead_hook(fs_info->extent_root, NULL, logical, ret); __readahead_hook(fs_info->extent_root, NULL, logical, ret);
else if (eb) else if (eb)
...@@ -851,7 +847,7 @@ static void dump_devs(struct btrfs_fs_info *fs_info, int all) ...@@ -851,7 +847,7 @@ static void dump_devs(struct btrfs_fs_info *fs_info, int all)
break; break;
printk(KERN_DEBUG printk(KERN_DEBUG
" re: logical %llu size %u empty %d for %lld", " re: logical %llu size %u empty %d for %lld",
re->logical, re->blocksize, re->logical, fs_info->tree_root->nodesize,
list_empty(&re->extctl), re->scheduled_for ? list_empty(&re->extctl), re->scheduled_for ?
re->scheduled_for->devid : -1); re->scheduled_for->devid : -1);
...@@ -886,7 +882,8 @@ static void dump_devs(struct btrfs_fs_info *fs_info, int all) ...@@ -886,7 +882,8 @@ static void dump_devs(struct btrfs_fs_info *fs_info, int all)
} }
printk(KERN_DEBUG printk(KERN_DEBUG
"re: logical %llu size %u list empty %d for %lld", "re: logical %llu size %u list empty %d for %lld",
re->logical, re->blocksize, list_empty(&re->extctl), re->logical, fs_info->tree_root->nodesize,
list_empty(&re->extctl),
re->scheduled_for ? re->scheduled_for->devid : -1); re->scheduled_for ? re->scheduled_for->devid : -1);
for (i = 0; i < re->nzones; ++i) { for (i = 0; i < re->nzones; ++i) {
printk(KERN_CONT " zone %llu-%llu devs", printk(KERN_CONT " zone %llu-%llu devs",
......
...@@ -2855,9 +2855,10 @@ static void update_processed_blocks(struct reloc_control *rc, ...@@ -2855,9 +2855,10 @@ static void update_processed_blocks(struct reloc_control *rc,
} }
} }
static int tree_block_processed(u64 bytenr, u32 blocksize, static int tree_block_processed(u64 bytenr, struct reloc_control *rc)
struct reloc_control *rc)
{ {
u32 blocksize = rc->extent_root->nodesize;
if (test_range_bit(&rc->processed_blocks, bytenr, if (test_range_bit(&rc->processed_blocks, bytenr,
bytenr + blocksize - 1, EXTENT_DIRTY, 1, NULL)) bytenr + blocksize - 1, EXTENT_DIRTY, 1, NULL))
return 1; return 1;
...@@ -2965,8 +2966,7 @@ int relocate_tree_blocks(struct btrfs_trans_handle *trans, ...@@ -2965,8 +2966,7 @@ int relocate_tree_blocks(struct btrfs_trans_handle *trans,
while (rb_node) { while (rb_node) {
block = rb_entry(rb_node, struct tree_block, rb_node); block = rb_entry(rb_node, struct tree_block, rb_node);
if (!block->key_ready) if (!block->key_ready)
readahead_tree_block(rc->extent_root, block->bytenr, readahead_tree_block(rc->extent_root, block->bytenr);
block->key.objectid);
rb_node = rb_next(rb_node); rb_node = rb_next(rb_node);
} }
...@@ -3353,7 +3353,7 @@ static int __add_tree_block(struct reloc_control *rc, ...@@ -3353,7 +3353,7 @@ static int __add_tree_block(struct reloc_control *rc,
bool skinny = btrfs_fs_incompat(rc->extent_root->fs_info, bool skinny = btrfs_fs_incompat(rc->extent_root->fs_info,
SKINNY_METADATA); SKINNY_METADATA);
if (tree_block_processed(bytenr, blocksize, rc)) if (tree_block_processed(bytenr, rc))
return 0; return 0;
if (tree_search(blocks, bytenr)) if (tree_search(blocks, bytenr))
...@@ -3611,7 +3611,7 @@ static int find_data_references(struct reloc_control *rc, ...@@ -3611,7 +3611,7 @@ static int find_data_references(struct reloc_control *rc,
if (added) if (added)
goto next; goto next;
if (!tree_block_processed(leaf->start, leaf->len, rc)) { if (!tree_block_processed(leaf->start, rc)) {
block = kmalloc(sizeof(*block), GFP_NOFS); block = kmalloc(sizeof(*block), GFP_NOFS);
if (!block) { if (!block) {
err = -ENOMEM; err = -ENOMEM;
......
This diff is collapsed.
...@@ -2471,12 +2471,9 @@ verbose_printk("btrfs: send_utimes %llu\n", ino); ...@@ -2471,12 +2471,9 @@ verbose_printk("btrfs: send_utimes %llu\n", ino);
if (ret < 0) if (ret < 0)
goto out; goto out;
TLV_PUT_PATH(sctx, BTRFS_SEND_A_PATH, p); TLV_PUT_PATH(sctx, BTRFS_SEND_A_PATH, p);
TLV_PUT_BTRFS_TIMESPEC(sctx, BTRFS_SEND_A_ATIME, eb, TLV_PUT_BTRFS_TIMESPEC(sctx, BTRFS_SEND_A_ATIME, eb, &ii->atime);
btrfs_inode_atime(ii)); TLV_PUT_BTRFS_TIMESPEC(sctx, BTRFS_SEND_A_MTIME, eb, &ii->mtime);
TLV_PUT_BTRFS_TIMESPEC(sctx, BTRFS_SEND_A_MTIME, eb, TLV_PUT_BTRFS_TIMESPEC(sctx, BTRFS_SEND_A_CTIME, eb, &ii->ctime);
btrfs_inode_mtime(ii));
TLV_PUT_BTRFS_TIMESPEC(sctx, BTRFS_SEND_A_CTIME, eb,
btrfs_inode_ctime(ii));
/* TODO Add otime support when the otime patches get into upstream */ /* TODO Add otime support when the otime patches get into upstream */
ret = send_cmd(sctx); ret = send_cmd(sctx);
......
...@@ -1958,11 +1958,6 @@ static int btrfs_freeze(struct super_block *sb) ...@@ -1958,11 +1958,6 @@ static int btrfs_freeze(struct super_block *sb)
return btrfs_commit_transaction(trans, root); return btrfs_commit_transaction(trans, root);
} }
static int btrfs_unfreeze(struct super_block *sb)
{
return 0;
}
static int btrfs_show_devname(struct seq_file *m, struct dentry *root) static int btrfs_show_devname(struct seq_file *m, struct dentry *root)
{ {
struct btrfs_fs_info *fs_info = btrfs_sb(root->d_sb); struct btrfs_fs_info *fs_info = btrfs_sb(root->d_sb);
...@@ -2011,7 +2006,6 @@ static const struct super_operations btrfs_super_ops = { ...@@ -2011,7 +2006,6 @@ static const struct super_operations btrfs_super_ops = {
.statfs = btrfs_statfs, .statfs = btrfs_statfs,
.remount_fs = btrfs_remount, .remount_fs = btrfs_remount,
.freeze_fs = btrfs_freeze, .freeze_fs = btrfs_freeze,
.unfreeze_fs = btrfs_unfreeze,
}; };
static const struct file_operations btrfs_ctl_fops = { static const struct file_operations btrfs_ctl_fops = {
......
...@@ -733,10 +733,18 @@ int btrfs_init_sysfs(void) ...@@ -733,10 +733,18 @@ int btrfs_init_sysfs(void)
ret = btrfs_init_debugfs(); ret = btrfs_init_debugfs();
if (ret) if (ret)
return ret; goto out1;
init_feature_attrs(); init_feature_attrs();
ret = sysfs_create_group(&btrfs_kset->kobj, &btrfs_feature_attr_group); ret = sysfs_create_group(&btrfs_kset->kobj, &btrfs_feature_attr_group);
if (ret)
goto out2;
return 0;
out2:
debugfs_remove_recursive(btrfs_debugfs_root_dentry);
out1:
kset_unregister(btrfs_kset);
return ret; return ret;
} }
......
...@@ -53,7 +53,7 @@ static int test_btrfs_split_item(void) ...@@ -53,7 +53,7 @@ static int test_btrfs_split_item(void)
return -ENOMEM; return -ENOMEM;
} }
path->nodes[0] = eb = alloc_dummy_extent_buffer(0, 4096); path->nodes[0] = eb = alloc_dummy_extent_buffer(NULL, 4096);
if (!eb) { if (!eb) {
test_msg("Could not allocate dummy buffer\n"); test_msg("Could not allocate dummy buffer\n");
ret = -ENOMEM; ret = -ENOMEM;
......
...@@ -258,8 +258,7 @@ static int test_find_delalloc(void) ...@@ -258,8 +258,7 @@ static int test_find_delalloc(void)
} }
ret = 0; ret = 0;
out_bits: out_bits:
clear_extent_bits(&tmp, 0, total_dirty - 1, clear_extent_bits(&tmp, 0, total_dirty - 1, (unsigned)-1, GFP_NOFS);
(unsigned long)-1, GFP_NOFS);
out: out:
if (locked_page) if (locked_page)
page_cache_release(locked_page); page_cache_release(locked_page);
......
...@@ -255,7 +255,7 @@ static noinline int test_btrfs_get_extent(void) ...@@ -255,7 +255,7 @@ static noinline int test_btrfs_get_extent(void)
goto out; goto out;
} }
root->node = alloc_dummy_extent_buffer(0, 4096); root->node = alloc_dummy_extent_buffer(NULL, 4096);
if (!root->node) { if (!root->node) {
test_msg("Couldn't allocate dummy buffer\n"); test_msg("Couldn't allocate dummy buffer\n");
goto out; goto out;
...@@ -843,7 +843,7 @@ static int test_hole_first(void) ...@@ -843,7 +843,7 @@ static int test_hole_first(void)
goto out; goto out;
} }
root->node = alloc_dummy_extent_buffer(0, 4096); root->node = alloc_dummy_extent_buffer(NULL, 4096);
if (!root->node) { if (!root->node) {
test_msg("Couldn't allocate dummy buffer\n"); test_msg("Couldn't allocate dummy buffer\n");
goto out; goto out;
......
...@@ -404,12 +404,22 @@ int btrfs_test_qgroups(void) ...@@ -404,12 +404,22 @@ int btrfs_test_qgroups(void)
ret = -ENOMEM; ret = -ENOMEM;
goto out; goto out;
} }
/* We are using this root as our extent root */
root->fs_info->extent_root = root;
/*
* Some of the paths we test assume we have a filled out fs_info, so we
* just need to add the root in there so we don't panic.
*/
root->fs_info->tree_root = root;
root->fs_info->quota_root = root;
root->fs_info->quota_enabled = 1;
/* /*
* Can't use bytenr 0, some things freak out * Can't use bytenr 0, some things freak out
* *cough*backref walking code*cough* * *cough*backref walking code*cough*
*/ */
root->node = alloc_test_extent_buffer(root->fs_info, 4096, 4096); root->node = alloc_test_extent_buffer(root->fs_info, 4096);
if (!root->node) { if (!root->node) {
test_msg("Couldn't allocate dummy buffer\n"); test_msg("Couldn't allocate dummy buffer\n");
ret = -ENOMEM; ret = -ENOMEM;
...@@ -448,17 +458,6 @@ int btrfs_test_qgroups(void) ...@@ -448,17 +458,6 @@ int btrfs_test_qgroups(void)
goto out; goto out;
} }
/* We are using this root as our extent root */
root->fs_info->extent_root = root;
/*
* Some of the paths we test assume we have a filled out fs_info, so we
* just need to addt he root in there so we don't panic.
*/
root->fs_info->tree_root = root;
root->fs_info->quota_root = root;
root->fs_info->quota_enabled = 1;
test_msg("Running qgroup tests\n"); test_msg("Running qgroup tests\n");
ret = test_no_shared_qgroup(root); ret = test_no_shared_qgroup(root);
if (ret) if (ret)
......
...@@ -220,6 +220,7 @@ static noinline int join_transaction(struct btrfs_root *root, unsigned int type) ...@@ -220,6 +220,7 @@ static noinline int join_transaction(struct btrfs_root *root, unsigned int type)
* commit the transaction. * commit the transaction.
*/ */
atomic_set(&cur_trans->use_count, 2); atomic_set(&cur_trans->use_count, 2);
cur_trans->have_free_bgs = 0;
cur_trans->start_time = get_seconds(); cur_trans->start_time = get_seconds();
cur_trans->delayed_refs.href_root = RB_ROOT; cur_trans->delayed_refs.href_root = RB_ROOT;
...@@ -248,6 +249,8 @@ static noinline int join_transaction(struct btrfs_root *root, unsigned int type) ...@@ -248,6 +249,8 @@ static noinline int join_transaction(struct btrfs_root *root, unsigned int type)
INIT_LIST_HEAD(&cur_trans->pending_chunks); INIT_LIST_HEAD(&cur_trans->pending_chunks);
INIT_LIST_HEAD(&cur_trans->switch_commits); INIT_LIST_HEAD(&cur_trans->switch_commits);
INIT_LIST_HEAD(&cur_trans->pending_ordered); INIT_LIST_HEAD(&cur_trans->pending_ordered);
INIT_LIST_HEAD(&cur_trans->dirty_bgs);
spin_lock_init(&cur_trans->dirty_bgs_lock);
list_add_tail(&cur_trans->list, &fs_info->trans_list); list_add_tail(&cur_trans->list, &fs_info->trans_list);
extent_io_tree_init(&cur_trans->dirty_pages, extent_io_tree_init(&cur_trans->dirty_pages,
fs_info->btree_inode->i_mapping); fs_info->btree_inode->i_mapping);
...@@ -1020,6 +1023,7 @@ static int update_cowonly_root(struct btrfs_trans_handle *trans, ...@@ -1020,6 +1023,7 @@ static int update_cowonly_root(struct btrfs_trans_handle *trans,
u64 old_root_bytenr; u64 old_root_bytenr;
u64 old_root_used; u64 old_root_used;
struct btrfs_root *tree_root = root->fs_info->tree_root; struct btrfs_root *tree_root = root->fs_info->tree_root;
bool extent_root = (root->objectid == BTRFS_EXTENT_TREE_OBJECTID);
old_root_used = btrfs_root_used(&root->root_item); old_root_used = btrfs_root_used(&root->root_item);
btrfs_write_dirty_block_groups(trans, root); btrfs_write_dirty_block_groups(trans, root);
...@@ -1027,7 +1031,9 @@ static int update_cowonly_root(struct btrfs_trans_handle *trans, ...@@ -1027,7 +1031,9 @@ static int update_cowonly_root(struct btrfs_trans_handle *trans,
while (1) { while (1) {
old_root_bytenr = btrfs_root_bytenr(&root->root_item); old_root_bytenr = btrfs_root_bytenr(&root->root_item);
if (old_root_bytenr == root->node->start && if (old_root_bytenr == root->node->start &&
old_root_used == btrfs_root_used(&root->root_item)) old_root_used == btrfs_root_used(&root->root_item) &&
(!extent_root ||
list_empty(&trans->transaction->dirty_bgs)))
break; break;
btrfs_set_root_node(&root->root_item, root->node); btrfs_set_root_node(&root->root_item, root->node);
...@@ -1038,7 +1044,15 @@ static int update_cowonly_root(struct btrfs_trans_handle *trans, ...@@ -1038,7 +1044,15 @@ static int update_cowonly_root(struct btrfs_trans_handle *trans,
return ret; return ret;
old_root_used = btrfs_root_used(&root->root_item); old_root_used = btrfs_root_used(&root->root_item);
ret = btrfs_write_dirty_block_groups(trans, root); if (extent_root) {
ret = btrfs_write_dirty_block_groups(trans, root);
if (ret)
return ret;
}
ret = btrfs_run_delayed_refs(trans, root, (unsigned long)-1);
if (ret)
return ret;
ret = btrfs_run_delayed_refs(trans, root, (unsigned long)-1);
if (ret) if (ret)
return ret; return ret;
} }
...@@ -1061,10 +1075,6 @@ static noinline int commit_cowonly_roots(struct btrfs_trans_handle *trans, ...@@ -1061,10 +1075,6 @@ static noinline int commit_cowonly_roots(struct btrfs_trans_handle *trans,
struct extent_buffer *eb; struct extent_buffer *eb;
int ret; int ret;
ret = btrfs_run_delayed_refs(trans, root, (unsigned long)-1);
if (ret)
return ret;
eb = btrfs_lock_root_node(fs_info->tree_root); eb = btrfs_lock_root_node(fs_info->tree_root);
ret = btrfs_cow_block(trans, fs_info->tree_root, eb, NULL, ret = btrfs_cow_block(trans, fs_info->tree_root, eb, NULL,
0, &eb); 0, &eb);
...@@ -1097,6 +1107,7 @@ static noinline int commit_cowonly_roots(struct btrfs_trans_handle *trans, ...@@ -1097,6 +1107,7 @@ static noinline int commit_cowonly_roots(struct btrfs_trans_handle *trans,
next = fs_info->dirty_cowonly_roots.next; next = fs_info->dirty_cowonly_roots.next;
list_del_init(next); list_del_init(next);
root = list_entry(next, struct btrfs_root, dirty_list); root = list_entry(next, struct btrfs_root, dirty_list);
clear_bit(BTRFS_ROOT_DIRTY, &root->state);
if (root != fs_info->extent_root) if (root != fs_info->extent_root)
list_add_tail(&root->dirty_list, list_add_tail(&root->dirty_list,
...@@ -1983,6 +1994,7 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans, ...@@ -1983,6 +1994,7 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans,
switch_commit_roots(cur_trans, root->fs_info); switch_commit_roots(cur_trans, root->fs_info);
assert_qgroups_uptodate(trans); assert_qgroups_uptodate(trans);
ASSERT(list_empty(&cur_trans->dirty_bgs));
update_super_roots(root); update_super_roots(root);
btrfs_set_super_log_root(root->fs_info->super_copy, 0); btrfs_set_super_log_root(root->fs_info->super_copy, 0);
...@@ -2026,6 +2038,9 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans, ...@@ -2026,6 +2038,9 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans,
btrfs_finish_extent_commit(trans, root); btrfs_finish_extent_commit(trans, root);
if (cur_trans->have_free_bgs)
btrfs_clear_space_info_full(root->fs_info);
root->fs_info->last_trans_committed = cur_trans->transid; root->fs_info->last_trans_committed = cur_trans->transid;
/* /*
* We needn't acquire the lock here because there is no other task * We needn't acquire the lock here because there is no other task
......
...@@ -47,6 +47,11 @@ struct btrfs_transaction { ...@@ -47,6 +47,11 @@ struct btrfs_transaction {
atomic_t num_writers; atomic_t num_writers;
atomic_t use_count; atomic_t use_count;
/*
* true if there is free bgs operations in this transaction
*/
int have_free_bgs;
/* Be protected by fs_info->trans_lock when we want to change it. */ /* Be protected by fs_info->trans_lock when we want to change it. */
enum btrfs_trans_state state; enum btrfs_trans_state state;
struct list_head list; struct list_head list;
...@@ -58,6 +63,8 @@ struct btrfs_transaction { ...@@ -58,6 +63,8 @@ struct btrfs_transaction {
struct list_head pending_chunks; struct list_head pending_chunks;
struct list_head pending_ordered; struct list_head pending_ordered;
struct list_head switch_commits; struct list_head switch_commits;
struct list_head dirty_bgs;
spinlock_t dirty_bgs_lock;
struct btrfs_delayed_ref_root delayed_refs; struct btrfs_delayed_ref_root delayed_refs;
int aborted; int aborted;
}; };
......
This diff is collapsed.
This diff is collapsed.
...@@ -295,8 +295,10 @@ typedef void (btrfs_bio_end_io_t) (struct btrfs_bio *bio, int err); ...@@ -295,8 +295,10 @@ typedef void (btrfs_bio_end_io_t) (struct btrfs_bio *bio, int err);
#define BTRFS_BIO_ORIG_BIO_SUBMITTED (1 << 0) #define BTRFS_BIO_ORIG_BIO_SUBMITTED (1 << 0)
struct btrfs_bio { struct btrfs_bio {
atomic_t refs;
atomic_t stripes_pending; atomic_t stripes_pending;
struct btrfs_fs_info *fs_info; struct btrfs_fs_info *fs_info;
u64 map_type; /* get from map_lookup->type */
bio_end_io_t *end_io; bio_end_io_t *end_io;
struct bio *orig_bio; struct bio *orig_bio;
unsigned long flags; unsigned long flags;
...@@ -307,6 +309,12 @@ struct btrfs_bio { ...@@ -307,6 +309,12 @@ struct btrfs_bio {
int mirror_num; int mirror_num;
int num_tgtdevs; int num_tgtdevs;
int *tgtdev_map; int *tgtdev_map;
/*
* logical block numbers for the start of each stripe
* The last one or two are p/q. These are sorted,
* so raid_map[0] is the start of our full stripe
*/
u64 *raid_map;
struct btrfs_bio_stripe stripes[]; struct btrfs_bio_stripe stripes[];
}; };
...@@ -388,19 +396,15 @@ struct btrfs_balance_control { ...@@ -388,19 +396,15 @@ struct btrfs_balance_control {
int btrfs_account_dev_extents_size(struct btrfs_device *device, u64 start, int btrfs_account_dev_extents_size(struct btrfs_device *device, u64 start,
u64 end, u64 *length); u64 end, u64 *length);
void btrfs_get_bbio(struct btrfs_bio *bbio);
#define btrfs_bio_size(total_stripes, real_stripes) \ void btrfs_put_bbio(struct btrfs_bio *bbio);
(sizeof(struct btrfs_bio) + \
(sizeof(struct btrfs_bio_stripe) * (total_stripes)) + \
(sizeof(int) * (real_stripes)))
int btrfs_map_block(struct btrfs_fs_info *fs_info, int rw, int btrfs_map_block(struct btrfs_fs_info *fs_info, int rw,
u64 logical, u64 *length, u64 logical, u64 *length,
struct btrfs_bio **bbio_ret, int mirror_num); struct btrfs_bio **bbio_ret, int mirror_num);
int btrfs_map_sblock(struct btrfs_fs_info *fs_info, int rw, int btrfs_map_sblock(struct btrfs_fs_info *fs_info, int rw,
u64 logical, u64 *length, u64 logical, u64 *length,
struct btrfs_bio **bbio_ret, int mirror_num, struct btrfs_bio **bbio_ret, int mirror_num,
u64 **raid_map_ret); int need_raid_map);
int btrfs_rmap_block(struct btrfs_mapping_tree *map_tree, int btrfs_rmap_block(struct btrfs_mapping_tree *map_tree,
u64 chunk_start, u64 physical, u64 devid, u64 chunk_start, u64 physical, u64 devid,
u64 **logical, int *naddrs, int *stripe_len); u64 **logical, int *naddrs, int *stripe_len);
......
...@@ -495,8 +495,7 @@ struct btrfs_ioctl_send_args { ...@@ -495,8 +495,7 @@ struct btrfs_ioctl_send_args {
/* Error codes as returned by the kernel */ /* Error codes as returned by the kernel */
enum btrfs_err_code { enum btrfs_err_code {
notused, BTRFS_ERROR_DEV_RAID1_MIN_NOT_MET = 1,
BTRFS_ERROR_DEV_RAID1_MIN_NOT_MET,
BTRFS_ERROR_DEV_RAID10_MIN_NOT_MET, BTRFS_ERROR_DEV_RAID10_MIN_NOT_MET,
BTRFS_ERROR_DEV_RAID5_MIN_NOT_MET, BTRFS_ERROR_DEV_RAID5_MIN_NOT_MET,
BTRFS_ERROR_DEV_RAID6_MIN_NOT_MET, BTRFS_ERROR_DEV_RAID6_MIN_NOT_MET,
......
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