Skip to content

Commit

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

Pull btrfs update from Chris Mason:
 "The dates look like I had to rebase this morning because there was a
  compiler warning for a printk arg that I had missed earlier.

  These are all fixes, including one to prevent using stale pointers for
  device names, and lots of fixes around transaction abort cleanups
  (Josef, Liu Bo).

  Jan Schmidt also sent in a number of fixes for the new reference
  number tracking code.

  Liu Bo beat me to updating the MAINTAINERS file.  Since he thought to
  also fix the git url, I kept his commit."

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mason/linux-btrfs: (24 commits)
  Btrfs: update MAINTAINERS info for BTRFS FILE SYSTEM
  Btrfs: destroy the items of the delayed inodes in error handling routine
  Btrfs: make sure that we've made everything in pinned tree clean
  Btrfs: avoid memory leak of extent state in error handling routine
  Btrfs: do not resize a seeding device
  Btrfs: fix missing inherited flag in rename
  Btrfs: fix incompat flags setting
  Btrfs: fix defrag regression
  Btrfs: call filemap_fdatawrite twice for compression
  Btrfs: keep inode pinned when compressing writes
  Btrfs: implement ->show_devname
  Btrfs: use rcu to protect device->name
  Btrfs: unlock everything properly in the error case for nocow
  Btrfs: fix btrfs_destroy_marked_extents
  Btrfs: abort the transaction if the commit fails
  Btrfs: wake up transaction waiters when aborting a transaction
  Btrfs: fix locking in btrfs_destroy_delayed_refs
  Btrfs: pass locked_page into extent_clear_unlock_delalloc if theres an error
  Btrfs: fix race in tree mod log addition
  Btrfs: add btrfs_next_old_leaf
  ...
  • Loading branch information
torvalds committed Jun 15, 2012
2 parents 424d54d + 9c10640 commit 718f58a
Show file tree
Hide file tree
Showing 19 changed files with 478 additions and 191 deletions.
4 changes: 2 additions & 2 deletions MAINTAINERS
Original file line number Diff line number Diff line change
Expand Up @@ -1646,11 +1646,11 @@ S: Maintained
F: drivers/gpio/gpio-bt8xx.c

BTRFS FILE SYSTEM
M: Chris Mason <chris.mason@oracle.com>
M: Chris Mason <chris.mason@fusionio.com>
L: [email protected]
W: http://btrfs.wiki.kernel.org/
Q: http://patchwork.kernel.org/project/linux-btrfs/list/
T: git git://git.kernel.org/pub/scm/linux/kernel/git/mason/btrfs-unstable.git
T: git git://git.kernel.org/pub/scm/linux/kernel/git/mason/linux-btrfs.git
S: Maintained
F: Documentation/filesystems/btrfs.txt
F: fs/btrfs/
Expand Down
17 changes: 5 additions & 12 deletions fs/btrfs/backref.c
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,8 @@ static int __add_prelim_ref(struct list_head *head, u64 root_id,

static int add_all_parents(struct btrfs_root *root, struct btrfs_path *path,
struct ulist *parents, int level,
struct btrfs_key *key, u64 wanted_disk_byte,
struct btrfs_key *key, u64 time_seq,
u64 wanted_disk_byte,
const u64 *extent_item_pos)
{
int ret;
Expand Down Expand Up @@ -212,7 +213,7 @@ static int add_all_parents(struct btrfs_root *root, struct btrfs_path *path,
*/
while (1) {
eie = NULL;
ret = btrfs_next_leaf(root, path);
ret = btrfs_next_old_leaf(root, path, time_seq);
if (ret < 0)
return ret;
if (ret)
Expand Down Expand Up @@ -294,18 +295,10 @@ static int __resolve_indirect_ref(struct btrfs_fs_info *fs_info,
goto out;
}

if (level == 0) {
if (ret == 1 && path->slots[0] >= btrfs_header_nritems(eb)) {
ret = btrfs_next_leaf(root, path);
if (ret)
goto out;
eb = path->nodes[0];
}

if (level == 0)
btrfs_item_key_to_cpu(eb, &key, path->slots[0]);
}

ret = add_all_parents(root, path, parents, level, &key,
ret = add_all_parents(root, path, parents, level, &key, time_seq,
ref->wanted_disk_byte, extent_item_pos);
out:
btrfs_free_path(path);
Expand Down
1 change: 1 addition & 0 deletions fs/btrfs/btrfs_inode.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
#define BTRFS_INODE_IN_DEFRAG 3
#define BTRFS_INODE_DELALLOC_META_RESERVED 4
#define BTRFS_INODE_HAS_ORPHAN_ITEM 5
#define BTRFS_INODE_HAS_ASYNC_EXTENT 6

/* in memory btrfs inode */
struct btrfs_inode {
Expand Down
16 changes: 9 additions & 7 deletions fs/btrfs/check-integrity.c
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@
#include "print-tree.h"
#include "locking.h"
#include "check-integrity.h"
#include "rcu-string.h"

#define BTRFSIC_BLOCK_HASHTABLE_SIZE 0x10000
#define BTRFSIC_BLOCK_LINK_HASHTABLE_SIZE 0x10000
Expand Down Expand Up @@ -843,13 +844,14 @@ static int btrfsic_process_superblock_dev_mirror(
superblock_tmp->never_written = 0;
superblock_tmp->mirror_num = 1 + superblock_mirror_num;
if (state->print_mask & BTRFSIC_PRINT_MASK_SUPERBLOCK_WRITE)
printk(KERN_INFO "New initial S-block (bdev %p, %s)"
" @%llu (%s/%llu/%d)\n",
superblock_bdev, device->name,
(unsigned long long)dev_bytenr,
dev_state->name,
(unsigned long long)dev_bytenr,
superblock_mirror_num);
printk_in_rcu(KERN_INFO "New initial S-block (bdev %p, %s)"
" @%llu (%s/%llu/%d)\n",
superblock_bdev,
rcu_str_deref(device->name),
(unsigned long long)dev_bytenr,
dev_state->name,
(unsigned long long)dev_bytenr,
superblock_mirror_num);
list_add(&superblock_tmp->all_blocks_node,
&state->all_blocks_list);
btrfsic_block_hashtable_add(superblock_tmp,
Expand Down
86 changes: 63 additions & 23 deletions fs/btrfs/ctree.c
Original file line number Diff line number Diff line change
Expand Up @@ -467,6 +467,15 @@ static inline int tree_mod_dont_log(struct btrfs_fs_info *fs_info,
return 0;
}

/*
* This allocates memory and gets a tree modification sequence number when
* needed.
*
* Returns 0 when no sequence number is needed, < 0 on error.
* Returns 1 when a sequence number was added. In this case,
* fs_info->tree_mod_seq_lock was acquired and must be released by the caller
* after inserting into the rb tree.
*/
static inline int tree_mod_alloc(struct btrfs_fs_info *fs_info, gfp_t flags,
struct tree_mod_elem **tm_ret)
{
Expand All @@ -491,11 +500,11 @@ static inline int tree_mod_alloc(struct btrfs_fs_info *fs_info, gfp_t flags,
*/
kfree(tm);
seq = 0;
spin_unlock(&fs_info->tree_mod_seq_lock);
} else {
__get_tree_mod_seq(fs_info, &tm->elem);
seq = tm->elem.seq;
}
spin_unlock(&fs_info->tree_mod_seq_lock);

return seq;
}
Expand All @@ -521,7 +530,9 @@ tree_mod_log_insert_key_mask(struct btrfs_fs_info *fs_info,
tm->slot = slot;
tm->generation = btrfs_node_ptr_generation(eb, slot);

return __tree_mod_log_insert(fs_info, tm);
ret = __tree_mod_log_insert(fs_info, tm);
spin_unlock(&fs_info->tree_mod_seq_lock);
return ret;
}

static noinline int
Expand Down Expand Up @@ -559,7 +570,9 @@ tree_mod_log_insert_move(struct btrfs_fs_info *fs_info,
tm->move.nr_items = nr_items;
tm->op = MOD_LOG_MOVE_KEYS;

return __tree_mod_log_insert(fs_info, tm);
ret = __tree_mod_log_insert(fs_info, tm);
spin_unlock(&fs_info->tree_mod_seq_lock);
return ret;
}

static noinline int
Expand All @@ -580,7 +593,9 @@ tree_mod_log_insert_root(struct btrfs_fs_info *fs_info,
tm->generation = btrfs_header_generation(old_root);
tm->op = MOD_LOG_ROOT_REPLACE;

return __tree_mod_log_insert(fs_info, tm);
ret = __tree_mod_log_insert(fs_info, tm);
spin_unlock(&fs_info->tree_mod_seq_lock);
return ret;
}

static struct tree_mod_elem *
Expand Down Expand Up @@ -1023,6 +1038,10 @@ __tree_mod_log_oldest_root(struct btrfs_fs_info *fs_info,
looped = 1;
}

/* if there's no old root to return, return what we found instead */
if (!found)
found = tm;

return found;
}

Expand Down Expand Up @@ -1143,45 +1162,62 @@ tree_mod_log_rewind(struct btrfs_fs_info *fs_info, struct extent_buffer *eb,
return eb_rewin;
}

/*
* get_old_root() rewinds the state of @root's root node to the given @time_seq
* value. If there are no changes, the current root->root_node is returned. If
* anything changed in between, there's a fresh buffer allocated on which the
* rewind operations are done. In any case, the returned buffer is read locked.
* Returns NULL on error (with no locks held).
*/
static inline struct extent_buffer *
get_old_root(struct btrfs_root *root, u64 time_seq)
{
struct tree_mod_elem *tm;
struct extent_buffer *eb;
struct tree_mod_root *old_root;
struct tree_mod_root *old_root = NULL;
u64 old_generation;
u64 logical;

eb = btrfs_read_lock_root_node(root);
tm = __tree_mod_log_oldest_root(root->fs_info, root, time_seq);
if (!tm)
return root->node;

old_root = &tm->old_root;
old_generation = tm->generation;
if (tm->op == MOD_LOG_ROOT_REPLACE) {
old_root = &tm->old_root;
old_generation = tm->generation;
logical = old_root->logical;
} else {
logical = root->node->start;
}

tm = tree_mod_log_search(root->fs_info, old_root->logical, time_seq);
tm = tree_mod_log_search(root->fs_info, logical, time_seq);
/*
* there was an item in the log when __tree_mod_log_oldest_root
* returned. this one must not go away, because the time_seq passed to
* us must be blocking its removal.
*/
BUG_ON(!tm);

if (old_root->logical == root->node->start) {
/* there are logged operations for the current root */
eb = btrfs_clone_extent_buffer(root->node);
} else {
/* there's a root replace operation for the current root */
if (old_root)
eb = alloc_dummy_extent_buffer(tm->index << PAGE_CACHE_SHIFT,
root->nodesize);
else
eb = btrfs_clone_extent_buffer(root->node);
btrfs_tree_read_unlock(root->node);
free_extent_buffer(root->node);
if (!eb)
return NULL;
btrfs_tree_read_lock(eb);
if (old_root) {
btrfs_set_header_bytenr(eb, eb->start);
btrfs_set_header_backref_rev(eb, BTRFS_MIXED_BACKREF_REV);
btrfs_set_header_owner(eb, root->root_key.objectid);
btrfs_set_header_level(eb, old_root->level);
btrfs_set_header_generation(eb, old_generation);
}
if (!eb)
return NULL;
btrfs_set_header_level(eb, old_root->level);
btrfs_set_header_generation(eb, old_generation);
__tree_mod_log_rewind(eb, time_seq, tm);
extent_buffer_get(eb);

return eb;
}
Expand Down Expand Up @@ -1650,8 +1686,6 @@ static noinline int balance_level(struct btrfs_trans_handle *trans,
BTRFS_NODEPTRS_PER_BLOCK(root) / 4)
return 0;

btrfs_header_nritems(mid);

left = read_node_slot(root, parent, pslot - 1);
if (left) {
btrfs_tree_lock(left);
Expand Down Expand Up @@ -1681,7 +1715,6 @@ static noinline int balance_level(struct btrfs_trans_handle *trans,
wret = push_node_left(trans, root, left, mid, 1);
if (wret < 0)
ret = wret;
btrfs_header_nritems(mid);
}

/*
Expand Down Expand Up @@ -2615,9 +2648,7 @@ int btrfs_search_old_slot(struct btrfs_root *root, struct btrfs_key *key,

again:
b = get_old_root(root, time_seq);
extent_buffer_get(b);
level = btrfs_header_level(b);
btrfs_tree_read_lock(b);
p->locks[level] = BTRFS_READ_LOCK;

while (b) {
Expand Down Expand Up @@ -5000,6 +5031,12 @@ int btrfs_find_next_key(struct btrfs_root *root, struct btrfs_path *path,
* returns < 0 on io errors.
*/
int btrfs_next_leaf(struct btrfs_root *root, struct btrfs_path *path)
{
return btrfs_next_old_leaf(root, path, 0);
}

int btrfs_next_old_leaf(struct btrfs_root *root, struct btrfs_path *path,
u64 time_seq)
{
int slot;
int level;
Expand All @@ -5025,7 +5062,10 @@ int btrfs_next_leaf(struct btrfs_root *root, struct btrfs_path *path)
path->keep_locks = 1;
path->leave_spinning = 1;

ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
if (time_seq)
ret = btrfs_search_old_slot(root, &key, path, time_seq);
else
ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
path->keep_locks = 0;

if (ret < 0)
Expand Down
2 changes: 2 additions & 0 deletions fs/btrfs/ctree.h
Original file line number Diff line number Diff line change
Expand Up @@ -2753,6 +2753,8 @@ static inline int btrfs_insert_empty_item(struct btrfs_trans_handle *trans,
}

int btrfs_next_leaf(struct btrfs_root *root, struct btrfs_path *path);
int btrfs_next_old_leaf(struct btrfs_root *root, struct btrfs_path *path,
u64 time_seq);
static inline int btrfs_next_item(struct btrfs_root *root, struct btrfs_path *p)
{
++p->slots[0];
Expand Down
18 changes: 18 additions & 0 deletions fs/btrfs/delayed-inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -1879,3 +1879,21 @@ void btrfs_kill_all_delayed_nodes(struct btrfs_root *root)
}
}
}

void btrfs_destroy_delayed_inodes(struct btrfs_root *root)
{
struct btrfs_delayed_root *delayed_root;
struct btrfs_delayed_node *curr_node, *prev_node;

delayed_root = btrfs_get_delayed_root(root);

curr_node = btrfs_first_delayed_node(delayed_root);
while (curr_node) {
__btrfs_kill_delayed_node(curr_node);

prev_node = curr_node;
curr_node = btrfs_next_delayed_node(curr_node);
btrfs_release_delayed_node(prev_node);
}
}

3 changes: 3 additions & 0 deletions fs/btrfs/delayed-inode.h
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,9 @@ int btrfs_fill_inode(struct inode *inode, u32 *rdev);
/* Used for drop dead root */
void btrfs_kill_all_delayed_nodes(struct btrfs_root *root);

/* Used for clean the transaction */
void btrfs_destroy_delayed_inodes(struct btrfs_root *root);

/* Used for readdir() */
void btrfs_get_delayed_items(struct inode *inode, struct list_head *ins_list,
struct list_head *del_list);
Expand Down
Loading

0 comments on commit 718f58a

Please sign in to comment.