Commit b7c09ad4 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 is against 3.11-rc7, but was pulled and tested against your tree
  as of yesterday.  We do have two small incrementals queued up, but I
  wanted to get this bunch out the door before I hop on an airplane.

  This is a fairly large batch of fixes, performance improvements, and
  cleanups from the usual Btrfs suspects.

  We've included Stefan Behren's work to index subvolume UUIDs, which is
  targeted at speeding up send/receive with many subvolumes or snapshots
  in place.  It closes a long standing performance issue that was built
  in to the disk format.

  Mark Fasheh's offline dedup work is also here.  In this case offline
  means the FS is mounted and active, but the dedup work is not done
  inline during file IO.  This is a building block where utilities are
  able to ask the FS to dedup a series of extents.  The kernel takes
  care of verifying the data involved really is the same.  Today this
  involves reading both extents, but we'll continue to evolve the
  patches"

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mason/linux-btrfs: (118 commits)
  Btrfs: optimize key searches in btrfs_search_slot
  Btrfs: don't use an async starter for most of our workers
  Btrfs: only update disk_i_size as we remove extents
  Btrfs: fix deadlock in uuid scan kthread
  Btrfs: stop refusing the relocation of chunk 0
  Btrfs: fix memory leak of uuid_root in free_fs_info
  btrfs: reuse kbasename helper
  btrfs: return btrfs error code for dev excl ops err
  Btrfs: allow partial ordered extent completion
  Btrfs: convert all bug_ons in free-space-cache.c
  Btrfs: add support for asserts
  Btrfs: adjust the fs_devices->missing count on unmount
  Btrf: cleanup: don't check for root_refs == 0 twice
  Btrfs: fix for patch "cleanup: don't check the same thing twice"
  Btrfs: get rid of one BUG() in write_all_supers()
  Btrfs: allocate prelim_ref with a slab allocater
  Btrfs: pass gfp_t to __add_prelim_ref() to avoid always using GFP_ATOMIC
  Btrfs: fix race conditions in BTRFS_IOC_FS_INFO ioctl
  Btrfs: fix race between removing a dev and writing sbs
  Btrfs: remove ourselves from the cluster list under lock
  ...
parents 18129977 d7396f07
...@@ -72,3 +72,12 @@ config BTRFS_DEBUG ...@@ -72,3 +72,12 @@ config BTRFS_DEBUG
performance, or export extra information via sysfs. performance, or export extra information via sysfs.
If unsure, say N. If unsure, say N.
config BTRFS_ASSERT
bool "Btrfs assert support"
depends on BTRFS_FS
help
Enable run-time assertion checking. This will result in panics if
any of the assertions trip. This is meant for btrfs developers only.
If unsure, say N.
...@@ -8,7 +8,10 @@ btrfs-y += super.o ctree.o extent-tree.o print-tree.o root-tree.o dir-item.o \ ...@@ -8,7 +8,10 @@ btrfs-y += super.o ctree.o extent-tree.o print-tree.o root-tree.o dir-item.o \
extent_io.o volumes.o async-thread.o ioctl.o locking.o orphan.o \ extent_io.o volumes.o async-thread.o ioctl.o locking.o orphan.o \
export.o tree-log.o free-space-cache.o zlib.o lzo.o \ export.o tree-log.o free-space-cache.o zlib.o lzo.o \
compression.o delayed-ref.o relocation.o delayed-inode.o scrub.o \ compression.o delayed-ref.o relocation.o delayed-inode.o scrub.o \
reada.o backref.o ulist.o qgroup.o send.o dev-replace.o raid56.o reada.o backref.o ulist.o qgroup.o send.o dev-replace.o raid56.o \
uuid-tree.o
btrfs-$(CONFIG_BTRFS_FS_POSIX_ACL) += acl.o btrfs-$(CONFIG_BTRFS_FS_POSIX_ACL) += acl.o
btrfs-$(CONFIG_BTRFS_FS_CHECK_INTEGRITY) += check-integrity.o btrfs-$(CONFIG_BTRFS_FS_CHECK_INTEGRITY) += check-integrity.o
btrfs-$(CONFIG_BTRFS_FS_RUN_SANITY_TESTS) += tests/free-space-tests.o
...@@ -119,6 +119,26 @@ struct __prelim_ref { ...@@ -119,6 +119,26 @@ struct __prelim_ref {
u64 wanted_disk_byte; u64 wanted_disk_byte;
}; };
static struct kmem_cache *btrfs_prelim_ref_cache;
int __init btrfs_prelim_ref_init(void)
{
btrfs_prelim_ref_cache = kmem_cache_create("btrfs_prelim_ref",
sizeof(struct __prelim_ref),
0,
SLAB_RECLAIM_ACCOUNT | SLAB_MEM_SPREAD,
NULL);
if (!btrfs_prelim_ref_cache)
return -ENOMEM;
return 0;
}
void btrfs_prelim_ref_exit(void)
{
if (btrfs_prelim_ref_cache)
kmem_cache_destroy(btrfs_prelim_ref_cache);
}
/* /*
* the rules for all callers of this function are: * the rules for all callers of this function are:
* - obtaining the parent is the goal * - obtaining the parent is the goal
...@@ -160,12 +180,12 @@ struct __prelim_ref { ...@@ -160,12 +180,12 @@ struct __prelim_ref {
static int __add_prelim_ref(struct list_head *head, u64 root_id, static int __add_prelim_ref(struct list_head *head, u64 root_id,
struct btrfs_key *key, int level, struct btrfs_key *key, int level,
u64 parent, u64 wanted_disk_byte, int count) u64 parent, u64 wanted_disk_byte, int count,
gfp_t gfp_mask)
{ {
struct __prelim_ref *ref; struct __prelim_ref *ref;
/* in case we're adding delayed refs, we're holding the refs spinlock */ ref = kmem_cache_alloc(btrfs_prelim_ref_cache, gfp_mask);
ref = kmalloc(sizeof(*ref), GFP_ATOMIC);
if (!ref) if (!ref)
return -ENOMEM; return -ENOMEM;
...@@ -295,10 +315,9 @@ static int __resolve_indirect_ref(struct btrfs_fs_info *fs_info, ...@@ -295,10 +315,9 @@ static int __resolve_indirect_ref(struct btrfs_fs_info *fs_info,
ret = btrfs_search_old_slot(root, &ref->key_for_search, path, time_seq); ret = btrfs_search_old_slot(root, &ref->key_for_search, path, time_seq);
pr_debug("search slot in root %llu (level %d, ref count %d) returned " pr_debug("search slot in root %llu (level %d, ref count %d) returned "
"%d for key (%llu %u %llu)\n", "%d for key (%llu %u %llu)\n",
(unsigned long long)ref->root_id, level, ref->count, ret, ref->root_id, level, ref->count, ret,
(unsigned long long)ref->key_for_search.objectid, ref->key_for_search.objectid, ref->key_for_search.type,
ref->key_for_search.type, ref->key_for_search.offset);
(unsigned long long)ref->key_for_search.offset);
if (ret < 0) if (ret < 0)
goto out; goto out;
...@@ -365,11 +384,12 @@ static int __resolve_indirect_refs(struct btrfs_fs_info *fs_info, ...@@ -365,11 +384,12 @@ static int __resolve_indirect_refs(struct btrfs_fs_info *fs_info,
node = ulist_next(parents, &uiter); node = ulist_next(parents, &uiter);
ref->parent = node ? node->val : 0; ref->parent = node ? node->val : 0;
ref->inode_list = node ? ref->inode_list = node ?
(struct extent_inode_elem *)(uintptr_t)node->aux : 0; (struct extent_inode_elem *)(uintptr_t)node->aux : NULL;
/* additional parents require new refs being added here */ /* additional parents require new refs being added here */
while ((node = ulist_next(parents, &uiter))) { while ((node = ulist_next(parents, &uiter))) {
new_ref = kmalloc(sizeof(*new_ref), GFP_NOFS); new_ref = kmem_cache_alloc(btrfs_prelim_ref_cache,
GFP_NOFS);
if (!new_ref) { if (!new_ref) {
ret = -ENOMEM; ret = -ENOMEM;
goto out; goto out;
...@@ -493,7 +513,7 @@ static void __merge_refs(struct list_head *head, int mode) ...@@ -493,7 +513,7 @@ static void __merge_refs(struct list_head *head, int mode)
ref1->count += ref2->count; ref1->count += ref2->count;
list_del(&ref2->list); list_del(&ref2->list);
kfree(ref2); kmem_cache_free(btrfs_prelim_ref_cache, ref2);
} }
} }
...@@ -548,7 +568,7 @@ static int __add_delayed_refs(struct btrfs_delayed_ref_head *head, u64 seq, ...@@ -548,7 +568,7 @@ static int __add_delayed_refs(struct btrfs_delayed_ref_head *head, u64 seq,
ref = btrfs_delayed_node_to_tree_ref(node); ref = btrfs_delayed_node_to_tree_ref(node);
ret = __add_prelim_ref(prefs, ref->root, &op_key, ret = __add_prelim_ref(prefs, ref->root, &op_key,
ref->level + 1, 0, node->bytenr, ref->level + 1, 0, node->bytenr,
node->ref_mod * sgn); node->ref_mod * sgn, GFP_ATOMIC);
break; break;
} }
case BTRFS_SHARED_BLOCK_REF_KEY: { case BTRFS_SHARED_BLOCK_REF_KEY: {
...@@ -558,7 +578,7 @@ static int __add_delayed_refs(struct btrfs_delayed_ref_head *head, u64 seq, ...@@ -558,7 +578,7 @@ static int __add_delayed_refs(struct btrfs_delayed_ref_head *head, u64 seq,
ret = __add_prelim_ref(prefs, ref->root, NULL, ret = __add_prelim_ref(prefs, ref->root, NULL,
ref->level + 1, ref->parent, ref->level + 1, ref->parent,
node->bytenr, node->bytenr,
node->ref_mod * sgn); node->ref_mod * sgn, GFP_ATOMIC);
break; break;
} }
case BTRFS_EXTENT_DATA_REF_KEY: { case BTRFS_EXTENT_DATA_REF_KEY: {
...@@ -570,7 +590,7 @@ static int __add_delayed_refs(struct btrfs_delayed_ref_head *head, u64 seq, ...@@ -570,7 +590,7 @@ static int __add_delayed_refs(struct btrfs_delayed_ref_head *head, u64 seq,
key.offset = ref->offset; key.offset = ref->offset;
ret = __add_prelim_ref(prefs, ref->root, &key, 0, 0, ret = __add_prelim_ref(prefs, ref->root, &key, 0, 0,
node->bytenr, node->bytenr,
node->ref_mod * sgn); node->ref_mod * sgn, GFP_ATOMIC);
break; break;
} }
case BTRFS_SHARED_DATA_REF_KEY: { case BTRFS_SHARED_DATA_REF_KEY: {
...@@ -583,7 +603,7 @@ static int __add_delayed_refs(struct btrfs_delayed_ref_head *head, u64 seq, ...@@ -583,7 +603,7 @@ static int __add_delayed_refs(struct btrfs_delayed_ref_head *head, u64 seq,
key.offset = ref->offset; key.offset = ref->offset;
ret = __add_prelim_ref(prefs, ref->root, &key, 0, ret = __add_prelim_ref(prefs, ref->root, &key, 0,
ref->parent, node->bytenr, ref->parent, node->bytenr,
node->ref_mod * sgn); node->ref_mod * sgn, GFP_ATOMIC);
break; break;
} }
default: default:
...@@ -657,7 +677,7 @@ static int __add_inline_refs(struct btrfs_fs_info *fs_info, ...@@ -657,7 +677,7 @@ static int __add_inline_refs(struct btrfs_fs_info *fs_info,
case BTRFS_SHARED_BLOCK_REF_KEY: case BTRFS_SHARED_BLOCK_REF_KEY:
ret = __add_prelim_ref(prefs, 0, NULL, ret = __add_prelim_ref(prefs, 0, NULL,
*info_level + 1, offset, *info_level + 1, offset,
bytenr, 1); bytenr, 1, GFP_NOFS);
break; break;
case BTRFS_SHARED_DATA_REF_KEY: { case BTRFS_SHARED_DATA_REF_KEY: {
struct btrfs_shared_data_ref *sdref; struct btrfs_shared_data_ref *sdref;
...@@ -666,13 +686,13 @@ static int __add_inline_refs(struct btrfs_fs_info *fs_info, ...@@ -666,13 +686,13 @@ static int __add_inline_refs(struct btrfs_fs_info *fs_info,
sdref = (struct btrfs_shared_data_ref *)(iref + 1); sdref = (struct btrfs_shared_data_ref *)(iref + 1);
count = btrfs_shared_data_ref_count(leaf, sdref); count = btrfs_shared_data_ref_count(leaf, sdref);
ret = __add_prelim_ref(prefs, 0, NULL, 0, offset, ret = __add_prelim_ref(prefs, 0, NULL, 0, offset,
bytenr, count); bytenr, count, GFP_NOFS);
break; break;
} }
case BTRFS_TREE_BLOCK_REF_KEY: case BTRFS_TREE_BLOCK_REF_KEY:
ret = __add_prelim_ref(prefs, offset, NULL, ret = __add_prelim_ref(prefs, offset, NULL,
*info_level + 1, 0, *info_level + 1, 0,
bytenr, 1); bytenr, 1, GFP_NOFS);
break; break;
case BTRFS_EXTENT_DATA_REF_KEY: { case BTRFS_EXTENT_DATA_REF_KEY: {
struct btrfs_extent_data_ref *dref; struct btrfs_extent_data_ref *dref;
...@@ -687,7 +707,7 @@ static int __add_inline_refs(struct btrfs_fs_info *fs_info, ...@@ -687,7 +707,7 @@ static int __add_inline_refs(struct btrfs_fs_info *fs_info,
key.offset = btrfs_extent_data_ref_offset(leaf, dref); key.offset = btrfs_extent_data_ref_offset(leaf, dref);
root = btrfs_extent_data_ref_root(leaf, dref); root = btrfs_extent_data_ref_root(leaf, dref);
ret = __add_prelim_ref(prefs, root, &key, 0, 0, ret = __add_prelim_ref(prefs, root, &key, 0, 0,
bytenr, count); bytenr, count, GFP_NOFS);
break; break;
} }
default: default:
...@@ -738,7 +758,7 @@ static int __add_keyed_refs(struct btrfs_fs_info *fs_info, ...@@ -738,7 +758,7 @@ static int __add_keyed_refs(struct btrfs_fs_info *fs_info,
case BTRFS_SHARED_BLOCK_REF_KEY: case BTRFS_SHARED_BLOCK_REF_KEY:
ret = __add_prelim_ref(prefs, 0, NULL, ret = __add_prelim_ref(prefs, 0, NULL,
info_level + 1, key.offset, info_level + 1, key.offset,
bytenr, 1); bytenr, 1, GFP_NOFS);
break; break;
case BTRFS_SHARED_DATA_REF_KEY: { case BTRFS_SHARED_DATA_REF_KEY: {
struct btrfs_shared_data_ref *sdref; struct btrfs_shared_data_ref *sdref;
...@@ -748,13 +768,13 @@ static int __add_keyed_refs(struct btrfs_fs_info *fs_info, ...@@ -748,13 +768,13 @@ static int __add_keyed_refs(struct btrfs_fs_info *fs_info,
struct btrfs_shared_data_ref); struct btrfs_shared_data_ref);
count = btrfs_shared_data_ref_count(leaf, sdref); count = btrfs_shared_data_ref_count(leaf, sdref);
ret = __add_prelim_ref(prefs, 0, NULL, 0, key.offset, ret = __add_prelim_ref(prefs, 0, NULL, 0, key.offset,
bytenr, count); bytenr, count, GFP_NOFS);
break; break;
} }
case BTRFS_TREE_BLOCK_REF_KEY: case BTRFS_TREE_BLOCK_REF_KEY:
ret = __add_prelim_ref(prefs, key.offset, NULL, ret = __add_prelim_ref(prefs, key.offset, NULL,
info_level + 1, 0, info_level + 1, 0,
bytenr, 1); bytenr, 1, GFP_NOFS);
break; break;
case BTRFS_EXTENT_DATA_REF_KEY: { case BTRFS_EXTENT_DATA_REF_KEY: {
struct btrfs_extent_data_ref *dref; struct btrfs_extent_data_ref *dref;
...@@ -770,7 +790,7 @@ static int __add_keyed_refs(struct btrfs_fs_info *fs_info, ...@@ -770,7 +790,7 @@ static int __add_keyed_refs(struct btrfs_fs_info *fs_info,
key.offset = btrfs_extent_data_ref_offset(leaf, dref); key.offset = btrfs_extent_data_ref_offset(leaf, dref);
root = btrfs_extent_data_ref_root(leaf, dref); root = btrfs_extent_data_ref_root(leaf, dref);
ret = __add_prelim_ref(prefs, root, &key, 0, 0, ret = __add_prelim_ref(prefs, root, &key, 0, 0,
bytenr, count); bytenr, count, GFP_NOFS);
break; break;
} }
default: default:
...@@ -911,7 +931,6 @@ static int find_parent_nodes(struct btrfs_trans_handle *trans, ...@@ -911,7 +931,6 @@ static int find_parent_nodes(struct btrfs_trans_handle *trans,
while (!list_empty(&prefs)) { while (!list_empty(&prefs)) {
ref = list_first_entry(&prefs, struct __prelim_ref, list); ref = list_first_entry(&prefs, struct __prelim_ref, list);
list_del(&ref->list);
WARN_ON(ref->count < 0); WARN_ON(ref->count < 0);
if (ref->count && ref->root_id && ref->parent == 0) { if (ref->count && ref->root_id && ref->parent == 0) {
/* no parent == root of tree */ /* no parent == root of tree */
...@@ -935,8 +954,10 @@ static int find_parent_nodes(struct btrfs_trans_handle *trans, ...@@ -935,8 +954,10 @@ static int find_parent_nodes(struct btrfs_trans_handle *trans,
} }
ret = find_extent_in_eb(eb, bytenr, ret = find_extent_in_eb(eb, bytenr,
*extent_item_pos, &eie); *extent_item_pos, &eie);
ref->inode_list = eie;
free_extent_buffer(eb); free_extent_buffer(eb);
if (ret < 0)
goto out;
ref->inode_list = eie;
} }
ret = ulist_add_merge(refs, ref->parent, ret = ulist_add_merge(refs, ref->parent,
(uintptr_t)ref->inode_list, (uintptr_t)ref->inode_list,
...@@ -954,7 +975,8 @@ static int find_parent_nodes(struct btrfs_trans_handle *trans, ...@@ -954,7 +975,8 @@ static int find_parent_nodes(struct btrfs_trans_handle *trans,
eie->next = ref->inode_list; eie->next = ref->inode_list;
} }
} }
kfree(ref); list_del(&ref->list);
kmem_cache_free(btrfs_prelim_ref_cache, ref);
} }
out: out:
...@@ -962,13 +984,13 @@ static int find_parent_nodes(struct btrfs_trans_handle *trans, ...@@ -962,13 +984,13 @@ static int find_parent_nodes(struct btrfs_trans_handle *trans,
while (!list_empty(&prefs)) { while (!list_empty(&prefs)) {
ref = list_first_entry(&prefs, struct __prelim_ref, list); ref = list_first_entry(&prefs, struct __prelim_ref, list);
list_del(&ref->list); list_del(&ref->list);
kfree(ref); kmem_cache_free(btrfs_prelim_ref_cache, ref);
} }
while (!list_empty(&prefs_delayed)) { while (!list_empty(&prefs_delayed)) {
ref = list_first_entry(&prefs_delayed, struct __prelim_ref, ref = list_first_entry(&prefs_delayed, struct __prelim_ref,
list); list);
list_del(&ref->list); list_del(&ref->list);
kfree(ref); kmem_cache_free(btrfs_prelim_ref_cache, ref);
} }
return ret; return ret;
...@@ -1326,8 +1348,7 @@ int extent_from_logical(struct btrfs_fs_info *fs_info, u64 logical, ...@@ -1326,8 +1348,7 @@ int extent_from_logical(struct btrfs_fs_info *fs_info, u64 logical,
found_key->type != BTRFS_METADATA_ITEM_KEY) || found_key->type != BTRFS_METADATA_ITEM_KEY) ||
found_key->objectid > logical || found_key->objectid > logical ||
found_key->objectid + size <= logical) { found_key->objectid + size <= logical) {
pr_debug("logical %llu is not within any extent\n", pr_debug("logical %llu is not within any extent\n", logical);
(unsigned long long)logical);
return -ENOENT; return -ENOENT;
} }
...@@ -1340,11 +1361,8 @@ int extent_from_logical(struct btrfs_fs_info *fs_info, u64 logical, ...@@ -1340,11 +1361,8 @@ int extent_from_logical(struct btrfs_fs_info *fs_info, u64 logical,
pr_debug("logical %llu is at position %llu within the extent (%llu " pr_debug("logical %llu is at position %llu within the extent (%llu "
"EXTENT_ITEM %llu) flags %#llx size %u\n", "EXTENT_ITEM %llu) flags %#llx size %u\n",
(unsigned long long)logical, logical, logical - found_key->objectid, found_key->objectid,
(unsigned long long)(logical - found_key->objectid), found_key->offset, flags, item_size);
(unsigned long long)found_key->objectid,
(unsigned long long)found_key->offset,
(unsigned long long)flags, item_size);
WARN_ON(!flags_ret); WARN_ON(!flags_ret);
if (flags_ret) { if (flags_ret) {
...@@ -1516,7 +1534,7 @@ int iterate_extent_inodes(struct btrfs_fs_info *fs_info, ...@@ -1516,7 +1534,7 @@ int iterate_extent_inodes(struct btrfs_fs_info *fs_info,
while (!ret && (root_node = ulist_next(roots, &root_uiter))) { while (!ret && (root_node = ulist_next(roots, &root_uiter))) {
pr_debug("root %llu references leaf %llu, data list " pr_debug("root %llu references leaf %llu, data list "
"%#llx\n", root_node->val, ref_node->val, "%#llx\n", root_node->val, ref_node->val,
(long long)ref_node->aux); ref_node->aux);
ret = iterate_leaf_refs((struct extent_inode_elem *) ret = iterate_leaf_refs((struct extent_inode_elem *)
(uintptr_t)ref_node->aux, (uintptr_t)ref_node->aux,
root_node->val, root_node->val,
...@@ -1608,9 +1626,8 @@ static int iterate_inode_refs(u64 inum, struct btrfs_root *fs_root, ...@@ -1608,9 +1626,8 @@ static int iterate_inode_refs(u64 inum, struct btrfs_root *fs_root,
name_len = btrfs_inode_ref_name_len(eb, iref); name_len = btrfs_inode_ref_name_len(eb, iref);
/* path must be released before calling iterate()! */ /* path must be released before calling iterate()! */
pr_debug("following ref at offset %u for inode %llu in " pr_debug("following ref at offset %u for inode %llu in "
"tree %llu\n", cur, "tree %llu\n", cur, found_key.objectid,
(unsigned long long)found_key.objectid, fs_root->objectid);
(unsigned long long)fs_root->objectid);
ret = iterate(parent, name_len, ret = iterate(parent, name_len,
(unsigned long)(iref + 1), eb, ctx); (unsigned long)(iref + 1), eb, ctx);
if (ret) if (ret)
......
...@@ -72,4 +72,6 @@ int btrfs_find_one_extref(struct btrfs_root *root, u64 inode_objectid, ...@@ -72,4 +72,6 @@ int btrfs_find_one_extref(struct btrfs_root *root, u64 inode_objectid,
struct btrfs_inode_extref **ret_extref, struct btrfs_inode_extref **ret_extref,
u64 *found_off); u64 *found_off);
int __init btrfs_prelim_ref_init(void);
void btrfs_prelim_ref_exit(void);
#endif #endif
...@@ -218,6 +218,27 @@ static inline int btrfs_inode_in_log(struct inode *inode, u64 generation) ...@@ -218,6 +218,27 @@ static inline int btrfs_inode_in_log(struct inode *inode, u64 generation)
return 0; return 0;
} }
struct btrfs_dio_private {
struct inode *inode;
u64 logical_offset;
u64 disk_bytenr;
u64 bytes;
void *private;
/* number of bios pending for this dio */
atomic_t pending_bios;
/* IO errors */
int errors;
/* orig_bio is our btrfs_io_bio */
struct bio *orig_bio;
/* dio_bio came from fs/direct-io.c */
struct bio *dio_bio;
u8 csum[0];
};
/* /*
* Disable DIO read nolock optimization, so new dio readers will be forced * Disable DIO read nolock optimization, so new dio readers will be forced
* to grab i_mutex. It is used to avoid the endless truncate due to * to grab i_mutex. It is used to avoid the endless truncate due to
......
This diff is collapsed.
...@@ -132,9 +132,8 @@ static int check_compressed_csum(struct inode *inode, ...@@ -132,9 +132,8 @@ static int check_compressed_csum(struct inode *inode,
printk(KERN_INFO "btrfs csum failed ino %llu " printk(KERN_INFO "btrfs csum failed ino %llu "
"extent %llu csum %u " "extent %llu csum %u "
"wanted %u mirror %d\n", "wanted %u mirror %d\n",
(unsigned long long)btrfs_ino(inode), btrfs_ino(inode), disk_start, csum, *cb_sum,
(unsigned long long)disk_start, cb->mirror_num);
csum, *cb_sum, cb->mirror_num);
ret = -EIO; ret = -EIO;
goto fail; goto fail;
} }
...@@ -639,6 +638,10 @@ int btrfs_submit_compressed_read(struct inode *inode, struct bio *bio, ...@@ -639,6 +638,10 @@ int btrfs_submit_compressed_read(struct inode *inode, struct bio *bio,
faili = nr_pages - 1; faili = nr_pages - 1;
cb->nr_pages = nr_pages; cb->nr_pages = nr_pages;
/* In the parent-locked case, we only locked the range we are
* interested in. In all other cases, we can opportunistically
* cache decompressed data that goes beyond the requested range. */
if (!(bio_flags & EXTENT_BIO_PARENT_LOCKED))
add_ra_bio_pages(inode, em_start + em_len, cb); add_ra_bio_pages(inode, em_start + em_len, cb);
/* include any pages we added in add_ra-bio_pages */ /* include any pages we added in add_ra-bio_pages */
......
This diff is collapsed.
This diff is collapsed.
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#include "delayed-inode.h" #include "delayed-inode.h"
#include "disk-io.h" #include "disk-io.h"
#include "transaction.h" #include "transaction.h"
#include "ctree.h"
#define BTRFS_DELAYED_WRITEBACK 512 #define BTRFS_DELAYED_WRITEBACK 512
#define BTRFS_DELAYED_BACKGROUND 128 #define BTRFS_DELAYED_BACKGROUND 128
...@@ -1453,10 +1454,10 @@ int btrfs_insert_delayed_dir_index(struct btrfs_trans_handle *trans, ...@@ -1453,10 +1454,10 @@ int btrfs_insert_delayed_dir_index(struct btrfs_trans_handle *trans,
dir_item = (struct btrfs_dir_item *)delayed_item->data; dir_item = (struct btrfs_dir_item *)delayed_item->data;
dir_item->location = *disk_key; dir_item->location = *disk_key;
dir_item->transid = cpu_to_le64(trans->transid); btrfs_set_stack_dir_transid(dir_item, trans->transid);
dir_item->data_len = 0; btrfs_set_stack_dir_data_len(dir_item, 0);
dir_item->name_len = cpu_to_le16(name_len); btrfs_set_stack_dir_name_len(dir_item, name_len);
dir_item->type = type; btrfs_set_stack_dir_type(dir_item, type);
memcpy((char *)(dir_item + 1), name, name_len); memcpy((char *)(dir_item + 1), name, name_len);
ret = btrfs_delayed_item_reserve_metadata(trans, root, delayed_item); ret = btrfs_delayed_item_reserve_metadata(trans, root, delayed_item);
...@@ -1470,13 +1471,11 @@ int btrfs_insert_delayed_dir_index(struct btrfs_trans_handle *trans, ...@@ -1470,13 +1471,11 @@ int btrfs_insert_delayed_dir_index(struct btrfs_trans_handle *trans,
mutex_lock(&delayed_node->mutex); mutex_lock(&delayed_node->mutex);
ret = __btrfs_add_delayed_insertion_item(delayed_node, delayed_item); ret = __btrfs_add_delayed_insertion_item(delayed_node, delayed_item);
if (unlikely(ret)) { if (unlikely(ret)) {
printk(KERN_ERR "err add delayed dir index item(name: %s) into " printk(KERN_ERR "err add delayed dir index item(name: %.*s) "
"the insertion tree of the delayed node" "into the insertion tree of the delayed node"
"(root id: %llu, inode id: %llu, errno: %d)\n", "(root id: %llu, inode id: %llu, errno: %d)\n",
name, name_len, name, delayed_node->root->objectid,
(unsigned long long)delayed_node->root->objectid, delayed_node->inode_id, ret);
(unsigned long long)delayed_node->inode_id,
ret);
BUG(); BUG();
} }
mutex_unlock(&delayed_node->mutex); mutex_unlock(&delayed_node->mutex);
...@@ -1547,9 +1546,7 @@ int btrfs_delete_delayed_dir_index(struct btrfs_trans_handle *trans, ...@@ -1547,9 +1546,7 @@ int btrfs_delete_delayed_dir_index(struct btrfs_trans_handle *trans,
printk(KERN_ERR "err add delayed dir index item(index: %llu) " printk(KERN_ERR "err add delayed dir index item(index: %llu) "
"into the deletion tree of the delayed node" "into the deletion tree of the delayed node"
"(root id: %llu, inode id: %llu, errno: %d)\n", "(root id: %llu, inode id: %llu, errno: %d)\n",
(unsigned long long)index, index, node->root->objectid, node->inode_id,
(unsigned long long)node->root->objectid,
(unsigned long long)node->inode_id,
ret); ret);
BUG(); BUG();
} }
...@@ -1699,7 +1696,7 @@ int btrfs_readdir_delayed_dir_index(struct dir_context *ctx, ...@@ -1699,7 +1696,7 @@ int btrfs_readdir_delayed_dir_index(struct dir_context *ctx,
di = (struct btrfs_dir_item *)curr->data; di = (struct btrfs_dir_item *)curr->data;
name = (char *)(di + 1); name = (char *)(di + 1);
name_len = le16_to_cpu(di->name_len); name_len = btrfs_stack_dir_name_len(di);
d_type = btrfs_filetype_table[di->type]; d_type = btrfs_filetype_table[di->type];
btrfs_disk_key_to_cpu(&location, &di->location); btrfs_disk_key_to_cpu(&location, &di->location);
...@@ -1716,27 +1713,6 @@ int btrfs_readdir_delayed_dir_index(struct dir_context *ctx, ...@@ -1716,27 +1713,6 @@ int btrfs_readdir_delayed_dir_index(struct dir_context *ctx,
return 0; return 0;
} }
BTRFS_SETGET_STACK_FUNCS(stack_inode_generation, struct btrfs_inode_item,
generation, 64);
BTRFS_SETGET_STACK_FUNCS(stack_inode_sequence, struct btrfs_inode_item,
sequence, 64);
BTRFS_SETGET_STACK_FUNCS(stack_inode_transid, struct btrfs_inode_item,
transid, 64);
BTRFS_SETGET_STACK_FUNCS(stack_inode_size, struct btrfs_inode_item, size, 64);
BTRFS_SETGET_STACK_FUNCS(stack_inode_nbytes, struct btrfs_inode_item,
nbytes, 64);
BTRFS_SETGET_STACK_FUNCS(stack_inode_block_group, struct btrfs_inode_item,
block_group, 64);
BTRFS_SETGET_STACK_FUNCS(stack_inode_nlink, struct btrfs_inode_item, nlink, 32);
BTRFS_SETGET_STACK_FUNCS(stack_inode_uid, struct btrfs_inode_item, uid, 32);
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_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_timespec_sec, struct btrfs_timespec, sec, 64);
BTRFS_SETGET_STACK_FUNCS(stack_timespec_nsec, struct btrfs_timespec, nsec, 32);
static void fill_stack_inode_item(struct btrfs_trans_handle *trans, static void fill_stack_inode_item(struct btrfs_trans_handle *trans,
struct btrfs_inode_item *inode_item, struct btrfs_inode_item *inode_item,
struct inode *inode) struct inode *inode)
......
...@@ -241,7 +241,7 @@ int btrfs_delayed_ref_lock(struct btrfs_trans_handle *trans, ...@@ -241,7 +241,7 @@ int btrfs_delayed_ref_lock(struct btrfs_trans_handle *trans,
return 0; return 0;
} }
static void inline drop_delayed_ref(struct btrfs_trans_handle *trans, static inline void drop_delayed_ref(struct btrfs_trans_handle *trans,
struct btrfs_delayed_ref_root *delayed_refs, struct btrfs_delayed_ref_root *delayed_refs,
struct btrfs_delayed_ref_node *ref) struct btrfs_delayed_ref_node *ref)
{ {
...@@ -600,7 +600,7 @@ static noinline void add_delayed_ref_head(struct btrfs_fs_info *fs_info, ...@@ -600,7 +600,7 @@ static noinline void add_delayed_ref_head(struct btrfs_fs_info *fs_info,
INIT_LIST_HEAD(&head_ref->cluster); INIT_LIST_HEAD(&head_ref->cluster);
mutex_init(&head_ref->mutex); mutex_init(&head_ref->mutex);
trace_btrfs_delayed_ref_head(ref, head_ref, action); trace_add_delayed_ref_head(ref, head_ref, action);
existing = tree_insert(&delayed_refs->root, &ref->rb_node); existing = tree_insert(&delayed_refs->root, &ref->rb_node);
...@@ -661,7 +661,7 @@ static noinline void add_delayed_tree_ref(struct btrfs_fs_info *fs_info, ...@@ -661,7 +661,7 @@ static noinline void add_delayed_tree_ref(struct btrfs_fs_info *fs_info,
ref->type = BTRFS_TREE_BLOCK_REF_KEY; ref->type = BTRFS_TREE_BLOCK_REF_KEY;
full_ref->level = level; full_ref->level = level;
trace_btrfs_delayed_tree_ref(ref, full_ref, action); trace_add_delayed_tree_ref(ref, full_ref, action);
existing = tree_insert(&delayed_refs->root, &ref->rb_node); existing = tree_insert(&delayed_refs->root, &ref->rb_node);
...@@ -722,7 +722,7 @@ static noinline void add_delayed_data_ref(struct btrfs_fs_info *fs_info, ...@@ -722,7 +722,7 @@ static noinline void add_delayed_data_ref(struct btrfs_fs_info *fs_info,
full_ref->objectid = owner; full_ref->objectid = owner;
full_ref->offset = offset; full_ref->offset = offset;
trace_btrfs_delayed_data_ref(ref, full_ref, action); trace_add_delayed_data_ref(ref, full_ref, action);
existing = tree_insert(&delayed_refs->root, &ref->rb_node); existing = tree_insert(&delayed_refs->root, &ref->rb_node);
......
...@@ -148,13 +148,13 @@ int btrfs_init_dev_replace(struct btrfs_fs_info *fs_info) ...@@ -148,13 +148,13 @@ int btrfs_init_dev_replace(struct btrfs_fs_info *fs_info)
!btrfs_test_opt(dev_root, DEGRADED)) { !btrfs_test_opt(dev_root, DEGRADED)) {
ret = -EIO; ret = -EIO;
pr_warn("btrfs: cannot mount because device replace operation is ongoing and\n" "srcdev (devid %llu) is missing, need to run 'btrfs dev scan'?\n", pr_warn("btrfs: cannot mount because device replace operation is ongoing and\n" "srcdev (devid %llu) is missing, need to run 'btrfs dev scan'?\n",
(unsigned long long)src_devid); src_devid);
} }
if (!dev_replace->tgtdev && if (!dev_replace->tgtdev &&
!btrfs_test_opt(dev_root, DEGRADED)) { !btrfs_test_opt(dev_root, DEGRADED)) {
ret = -EIO; ret = -EIO;
pr_warn("btrfs: cannot mount because device replace operation is ongoing and\n" "tgtdev (devid %llu) is missing, need to run btrfs dev scan?\n", pr_warn("btrfs: cannot mount because device replace operation is ongoing and\n" "tgtdev (devid %llu) is missing, need to run btrfs dev scan?\n",
(unsigned long long)BTRFS_DEV_REPLACE_DEVID); BTRFS_DEV_REPLACE_DEVID);
} }
if (dev_replace->tgtdev) { if (dev_replace->tgtdev) {
if (dev_replace->srcdev) { if (dev_replace->srcdev) {
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
...@@ -29,6 +29,7 @@ ...@@ -29,6 +29,7 @@
*/ */
#define EXTENT_BIO_COMPRESSED 1 #define EXTENT_BIO_COMPRESSED 1
#define EXTENT_BIO_TREE_LOG 2 #define EXTENT_BIO_TREE_LOG 2
#define EXTENT_BIO_PARENT_LOCKED 4
#define EXTENT_BIO_FLAG_SHIFT 16 #define EXTENT_BIO_FLAG_SHIFT 16
/* these are bit numbers for test/set bit */ /* these are bit numbers for test/set bit */
...@@ -44,14 +45,11 @@ ...@@ -44,14 +45,11 @@
#define EXTENT_BUFFER_DUMMY 9 #define EXTENT_BUFFER_DUMMY 9
/* these are flags for extent_clear_unlock_delalloc */ /* these are flags for extent_clear_unlock_delalloc */
#define EXTENT_CLEAR_UNLOCK_PAGE 0x1 #define PAGE_UNLOCK (1 << 0)
#define EXTENT_CLEAR_UNLOCK 0x2 #define PAGE_CLEAR_DIRTY (1 << 1)
#define EXTENT_CLEAR_DELALLOC 0x4 #define PAGE_SET_WRITEBACK (1 << 2)
#define EXTENT_CLEAR_DIRTY 0x8 #define PAGE_END_WRITEBACK (1 << 3)
#define EXTENT_SET_WRITEBACK 0x10 #define PAGE_SET_PRIVATE2 (1 << 4)
#define EXTENT_END_WRITEBACK 0x20
#define EXTENT_SET_PRIVATE2 0x40
#define EXTENT_CLEAR_ACCOUNTING 0x80
/* /*
* page->private values. Every page that is controlled by the extent * page->private values. Every page that is controlled by the extent
...@@ -62,6 +60,7 @@ ...@@ -62,6 +60,7 @@
struct extent_state; struct extent_state;
struct btrfs_root; struct btrfs_root;
struct btrfs_io_bio;
typedef int (extent_submit_bio_hook_t)(struct inode *inode, int rw, typedef int (extent_submit_bio_hook_t)(struct inode *inode, int rw,
struct bio *bio, int mirror_num, struct bio *bio, int mirror_num,
...@@ -77,8 +76,9 @@ struct extent_io_ops { ...@@ -77,8 +76,9 @@ struct extent_io_ops {
size_t size, struct bio *bio, size_t size, struct bio *bio,
unsigned long bio_flags); unsigned long bio_flags);
int (*readpage_io_failed_hook)(struct page *page, int failed_mirror); int (*readpage_io_failed_hook)(struct page *page, int failed_mirror);
int (*readpage_end_io_hook)(struct page *page, u64 start, u64 end, int (*readpage_end_io_hook)(struct btrfs_io_bio *io_bio, u64 phy_offset,
struct extent_state *state, int mirror); struct page *page, u64 start, u64 end,
int mirror);
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,
...@@ -200,6 +200,8 @@ int unlock_extent_cached(struct extent_io_tree *tree, u64 start, u64 end, ...@@ -200,6 +200,8 @@ int unlock_extent_cached(struct extent_io_tree *tree, u64 start, u64 end,
int try_lock_extent(struct extent_io_tree *tree, u64 start, u64 end); int try_lock_extent(struct extent_io_tree *tree, u64 start, u64 end);
int extent_read_full_page(struct extent_io_tree *tree, struct page *page, int extent_read_full_page(struct extent_io_tree *tree, struct page *page,
get_extent_t *get_extent, int mirror_num); get_extent_t *get_extent, int mirror_num);
int extent_read_full_page_nolock(struct extent_io_tree *tree, struct page *page,
get_extent_t *get_extent, int mirror_num);
int __init extent_io_init(void); int __init extent_io_init(void);
void extent_io_exit(void); void extent_io_exit(void);
...@@ -261,11 +263,6 @@ int extent_readpages(struct extent_io_tree *tree, ...@@ -261,11 +263,6 @@ int extent_readpages(struct extent_io_tree *tree,
get_extent_t get_extent); get_extent_t get_extent);
int extent_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, int extent_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
__u64 start, __u64 len, get_extent_t *get_extent); __u64 start, __u64 len, get_extent_t *get_extent);
int set_state_private(struct extent_io_tree *tree, u64 start, u64 private);
void extent_cache_csums_dio(struct extent_io_tree *tree, u64 start, u32 csums[],
int count);
void extent_cache_csums(struct extent_io_tree *tree, struct bio *bio,
int bvec_index, u32 csums[], int count);
int get_state_private(struct extent_io_tree *tree, u64 start, u64 *private); 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);
...@@ -330,10 +327,10 @@ int map_private_extent_buffer(struct extent_buffer *eb, unsigned long offset, ...@@ -330,10 +327,10 @@ int map_private_extent_buffer(struct extent_buffer *eb, unsigned long offset,
unsigned long *map_len); unsigned long *map_len);
int extent_range_clear_dirty_for_io(struct inode *inode, u64 start, u64 end); 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, int extent_clear_unlock_delalloc(struct inode *inode, u64 start, u64 end,
struct extent_io_tree *tree, struct page *locked_page,
u64 start, u64 end, struct page *locked_page, unsigned long bits_to_clear,
unsigned long op); 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,
gfp_t gfp_flags); gfp_t gfp_flags);
......
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
#include "ctree.h" #include "ctree.h"
#include "disk-io.h" #include "disk-io.h"
#include "transaction.h" #include "transaction.h"
#include "volumes.h"
#include "print-tree.h" #include "print-tree.h"
#define __MAX_CSUM_ITEMS(r, size) ((unsigned long)(((BTRFS_LEAF_DATA_SIZE(r) - \ #define __MAX_CSUM_ITEMS(r, size) ((unsigned long)(((BTRFS_LEAF_DATA_SIZE(r) - \
...@@ -152,28 +153,54 @@ int btrfs_lookup_file_extent(struct btrfs_trans_handle *trans, ...@@ -152,28 +153,54 @@ int btrfs_lookup_file_extent(struct btrfs_trans_handle *trans,
return ret; return ret;
} }
static void btrfs_io_bio_endio_readpage(struct btrfs_io_bio *bio, int err)
{
kfree(bio->csum_allocated);
}
static int __btrfs_lookup_bio_sums(struct btrfs_root *root, static int __btrfs_lookup_bio_sums(struct btrfs_root *root,
struct inode *inode, struct bio *bio, struct inode *inode, struct bio *bio,
u64 logical_offset, u32 *dst, int dio) u64 logical_offset, u32 *dst, int dio)
{ {
u32 sum[16];
int len;
struct bio_vec *bvec = bio->bi_io_vec; struct bio_vec *bvec = bio->bi_io_vec;
int bio_index = 0; struct btrfs_io_bio *btrfs_bio = btrfs_io_bio(bio);
struct btrfs_csum_item *item = NULL;
struct extent_io_tree *io_tree = &BTRFS_I(inode)->io_tree;
struct btrfs_path *path;
u8 *csum;
u64 offset = 0; u64 offset = 0;
u64 item_start_offset = 0; u64 item_start_offset = 0;
u64 item_last_offset = 0; u64 item_last_offset = 0;
u64 disk_bytenr; u64 disk_bytenr;
u32 diff; u32 diff;
u16 csum_size = btrfs_super_csum_size(root->fs_info->super_copy); int nblocks;
int bio_index = 0;
int count; int count;
struct btrfs_path *path; u16 csum_size = btrfs_super_csum_size(root->fs_info->super_copy);
struct btrfs_csum_item *item = NULL;
struct extent_io_tree *io_tree = &BTRFS_I(inode)->io_tree;
path = btrfs_alloc_path(); path = btrfs_alloc_path();
if (!path) if (!path)
return -ENOMEM; return -ENOMEM;
nblocks = bio->bi_size >> inode->i_sb->s_blocksize_bits;
if (!dst) {
if (nblocks * csum_size > BTRFS_BIO_INLINE_CSUM_SIZE) {
btrfs_bio->csum_allocated = kmalloc(nblocks * csum_size,
GFP_NOFS);
if (!btrfs_bio->csum_allocated) {
btrfs_free_path(path);
return -ENOMEM;
}
btrfs_bio->csum = btrfs_bio->csum_allocated;
btrfs_bio->end_io = btrfs_io_bio_endio_readpage;
} else {
btrfs_bio->csum = btrfs_bio->csum_inline;
}
csum = btrfs_bio->csum;
} else {
csum = (u8 *)dst;
}
if (bio->bi_size > PAGE_CACHE_SIZE * 8) if (bio->bi_size > PAGE_CACHE_SIZE * 8)
path->reada = 2; path->reada = 2;
...@@ -194,11 +221,10 @@ static int __btrfs_lookup_bio_sums(struct btrfs_root *root, ...@@ -194,11 +221,10 @@ static int __btrfs_lookup_bio_sums(struct btrfs_root *root,
if (dio) if (dio)
offset = logical_offset; offset = logical_offset;
while (bio_index < bio->bi_vcnt) { while (bio_index < bio->bi_vcnt) {
len = min_t(int, ARRAY_SIZE(sum), bio->bi_vcnt - bio_index);
if (!dio) if (!dio)
offset = page_offset(bvec->bv_page) + bvec->bv_offset; offset = page_offset(bvec->bv_page) + bvec->bv_offset;
count = btrfs_find_ordered_sum(inode, offset, disk_bytenr, sum, count = btrfs_find_ordered_sum(inode, offset, disk_bytenr,
len); (u32 *)csum, nblocks);
if (count) if (count)
goto found; goto found;
...@@ -213,7 +239,7 @@ static int __btrfs_lookup_bio_sums(struct btrfs_root *root, ...@@ -213,7 +239,7 @@ static int __btrfs_lookup_bio_sums(struct btrfs_root *root,
path, disk_bytenr, 0); path, disk_bytenr, 0);
if (IS_ERR(item)) { if (IS_ERR(item)) {
count = 1; count = 1;
sum[0] = 0; memset(csum, 0, csum_size);
if (BTRFS_I(inode)->root->root_key.objectid == if (BTRFS_I(inode)->root->root_key.objectid ==
BTRFS_DATA_RELOC_TREE_OBJECTID) { BTRFS_DATA_RELOC_TREE_OBJECTID) {
set_extent_bits(io_tree, offset, set_extent_bits(io_tree, offset,
...@@ -222,9 +248,7 @@ static int __btrfs_lookup_bio_sums(struct btrfs_root *root, ...@@ -222,9 +248,7 @@ static int __btrfs_lookup_bio_sums(struct btrfs_root *root,
} else { } else {
printk(KERN_INFO "btrfs no csum found " printk(KERN_INFO "btrfs no csum found "
"for inode %llu start %llu\n", "for inode %llu start %llu\n",
(unsigned long long) btrfs_ino(inode), offset);
btrfs_ino(inode),
(unsigned long long)offset);
} }
item = NULL; item = NULL;
btrfs_release_path(path); btrfs_release_path(path);
...@@ -249,23 +273,14 @@ static int __btrfs_lookup_bio_sums(struct btrfs_root *root, ...@@ -249,23 +273,14 @@ static int __btrfs_lookup_bio_sums(struct btrfs_root *root,
diff = disk_bytenr - item_start_offset; diff = disk_bytenr - item_start_offset;
diff = diff / root->sectorsize; diff = diff / root->sectorsize;
diff = diff * csum_size; diff = diff * csum_size;
count = min_t(int, len, (item_last_offset - disk_bytenr) >> count = min_t(int, nblocks, (item_last_offset - disk_bytenr) >>
inode->i_sb->s_blocksize_bits); inode->i_sb->s_blocksize_bits);
read_extent_buffer(path->nodes[0], sum, read_extent_buffer(path->nodes[0], csum,
((unsigned long)item) + diff, ((unsigned long)item) + diff,
csum_size * count); csum_size * count);
found: found:
if (dst) { csum += count * csum_size;
memcpy(dst, sum, count * csum_size); nblocks -= count;
dst += count;
} else {
if (dio)
extent_cache_csums_dio(io_tree, offset, sum,
count);
else
extent_cache_csums(io_tree, bio, bio_index, sum,
count);
}
while (count--) { while (count--) {
disk_bytenr += bvec->bv_len; disk_bytenr += bvec->bv_len;
offset += bvec->bv_len; offset += bvec->bv_len;
...@@ -284,9 +299,19 @@ int btrfs_lookup_bio_sums(struct btrfs_root *root, struct inode *inode, ...@@ -284,9 +299,19 @@ int btrfs_lookup_bio_sums(struct btrfs_root *root, struct inode *inode,
} }
int btrfs_lookup_bio_sums_dio(struct btrfs_root *root, struct inode *inode, int btrfs_lookup_bio_sums_dio(struct btrfs_root *root, struct inode *inode,
struct bio *bio, u64 offset) struct btrfs_dio_private *dip, struct bio *bio,
u64 offset)
{ {
return __btrfs_lookup_bio_sums(root, inode, bio, offset, NULL, 1); int len = (bio->bi_sector << 9) - dip->disk_bytenr;
u16 csum_size = btrfs_super_csum_size(root->fs_info->super_copy);
int ret;
len >>= inode->i_sb->s_blocksize_bits;
len *= csum_size;
ret = __btrfs_lookup_bio_sums(root, inode, bio, offset,
(u32 *)(dip->csum + len), 1);
return ret;
} }
int btrfs_lookup_csums_range(struct btrfs_root *root, u64 start, u64 end, int btrfs_lookup_csums_range(struct btrfs_root *root, u64 start, u64 end,
......
...@@ -1334,7 +1334,6 @@ static noinline int prepare_pages(struct btrfs_root *root, struct file *file, ...@@ -1334,7 +1334,6 @@ static noinline int prepare_pages(struct btrfs_root *root, struct file *file,
static noinline int check_can_nocow(struct inode *inode, loff_t pos, static noinline int check_can_nocow(struct inode *inode, loff_t pos,
size_t *write_bytes) size_t *write_bytes)
{ {
struct btrfs_trans_handle *trans;
struct btrfs_root *root = BTRFS_I(inode)->root; struct btrfs_root *root = BTRFS_I(inode)->root;
struct btrfs_ordered_extent *ordered; struct btrfs_ordered_extent *ordered;
u64 lockstart, lockend; u64 lockstart, lockend;
...@@ -1356,16 +1355,8 @@ static noinline int check_can_nocow(struct inode *inode, loff_t pos, ...@@ -1356,16 +1355,8 @@ static noinline int check_can_nocow(struct inode *inode, loff_t pos,
btrfs_put_ordered_extent(ordered); btrfs_put_ordered_extent(ordered);
} }
trans = btrfs_join_transaction(root);
if (IS_ERR(trans)) {
unlock_extent(&BTRFS_I(inode)->io_tree, lockstart, lockend);
return PTR_ERR(trans);
}
num_bytes = lockend - lockstart + 1; num_bytes = lockend - lockstart + 1;
ret = can_nocow_extent(trans, inode, lockstart, &num_bytes, NULL, NULL, ret = can_nocow_extent(inode, lockstart, &num_bytes, NULL, NULL, NULL);
NULL);
btrfs_end_transaction(trans, root);
if (ret <= 0) { if (ret <= 0) {
ret = 0; ret = 0;
} else { } else {
......
This diff is collapsed.
...@@ -98,8 +98,7 @@ u64 btrfs_find_space_for_alloc(struct btrfs_block_group_cache *block_group, ...@@ -98,8 +98,7 @@ u64 btrfs_find_space_for_alloc(struct btrfs_block_group_cache *block_group,
u64 btrfs_find_ino_for_alloc(struct btrfs_root *fs_root); u64 btrfs_find_ino_for_alloc(struct btrfs_root *fs_root);
void btrfs_dump_free_space(struct btrfs_block_group_cache *block_group, void btrfs_dump_free_space(struct btrfs_block_group_cache *block_group,
u64 bytes); u64 bytes);
int btrfs_find_space_cluster(struct btrfs_trans_handle *trans, int btrfs_find_space_cluster(struct btrfs_root *root,
struct btrfs_root *root,
struct btrfs_block_group_cache *block_group, struct btrfs_block_group_cache *block_group,
struct btrfs_free_cluster *cluster, struct btrfs_free_cluster *cluster,
u64 offset, u64 bytes, u64 empty_size); u64 offset, u64 bytes, u64 empty_size);
...@@ -113,6 +112,12 @@ int btrfs_return_cluster_to_free_space( ...@@ -113,6 +112,12 @@ int btrfs_return_cluster_to_free_space(
int btrfs_trim_block_group(struct btrfs_block_group_cache *block_group, int btrfs_trim_block_group(struct btrfs_block_group_cache *block_group,
u64 *trimmed, u64 start, u64 end, u64 minlen); u64 *trimmed, u64 start, u64 end, u64 minlen);
void btrfs_test_free_space_cache(void); /* Support functions for runnint our sanity tests */
#ifdef CONFIG_BTRFS_FS_RUN_SANITY_TESTS
int test_add_free_space_entry(struct btrfs_block_group_cache *cache,
u64 offset, u64 bytes, bool bitmap);
int test_check_exists(struct btrfs_block_group_cache *cache,
u64 offset, u64 bytes);
#endif
#endif #endif
This diff is collapsed.
This diff is collapsed.
...@@ -207,8 +207,10 @@ static int lzo_compress_pages(struct list_head *ws, ...@@ -207,8 +207,10 @@ static int lzo_compress_pages(struct list_head *ws,
} }
/* we're making it bigger, give up */ /* we're making it bigger, give up */
if (tot_in > 8192 && tot_in < tot_out) if (tot_in > 8192 && tot_in < tot_out) {
ret = -1;
goto out; goto out;
}
/* we're all done */ /* we're all done */
if (tot_in >= len) if (tot_in >= len)
......
...@@ -67,7 +67,7 @@ static void ordered_data_tree_panic(struct inode *inode, int errno, ...@@ -67,7 +67,7 @@ static void ordered_data_tree_panic(struct inode *inode, int errno,
{ {
struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb); struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
btrfs_panic(fs_info, errno, "Inconsistency in ordered tree at offset " btrfs_panic(fs_info, errno, "Inconsistency in ordered tree at offset "
"%llu\n", (unsigned long long)offset); "%llu\n", offset);
} }
/* /*
...@@ -205,6 +205,7 @@ static int __btrfs_add_ordered_extent(struct inode *inode, u64 file_offset, ...@@ -205,6 +205,7 @@ static int __btrfs_add_ordered_extent(struct inode *inode, u64 file_offset,
entry->bytes_left = len; entry->bytes_left = len;
entry->inode = igrab(inode); entry->inode = igrab(inode);
entry->compress_type = compress_type; entry->compress_type = compress_type;
entry->truncated_len = (u64)-1;
if (type != BTRFS_ORDERED_IO_DONE && type != BTRFS_ORDERED_COMPLETE) if (type != BTRFS_ORDERED_IO_DONE && type != BTRFS_ORDERED_COMPLETE)
set_bit(type, &entry->flags); set_bit(type, &entry->flags);
...@@ -336,14 +337,12 @@ int btrfs_dec_test_first_ordered_pending(struct inode *inode, ...@@ -336,14 +337,12 @@ int btrfs_dec_test_first_ordered_pending(struct inode *inode,
*file_offset = dec_end; *file_offset = dec_end;
if (dec_start > dec_end) { if (dec_start > dec_end) {
printk(KERN_CRIT "bad ordering dec_start %llu end %llu\n", printk(KERN_CRIT "bad ordering dec_start %llu end %llu\n",
(unsigned long long)dec_start, dec_start, dec_end);
(unsigned long long)dec_end);
} }
to_dec = dec_end - dec_start; to_dec = dec_end - dec_start;
if (to_dec > entry->bytes_left) { if (to_dec > entry->bytes_left) {
printk(KERN_CRIT "bad ordered accounting left %llu size %llu\n", printk(KERN_CRIT "bad ordered accounting left %llu size %llu\n",
(unsigned long long)entry->bytes_left, entry->bytes_left, to_dec);
(unsigned long long)to_dec);
} }
entry->bytes_left -= to_dec; entry->bytes_left -= to_dec;
if (!uptodate) if (!uptodate)
...@@ -403,8 +402,7 @@ int btrfs_dec_test_ordered_pending(struct inode *inode, ...@@ -403,8 +402,7 @@ int btrfs_dec_test_ordered_pending(struct inode *inode,
if (io_size > entry->bytes_left) { if (io_size > entry->bytes_left) {
printk(KERN_CRIT "bad ordered accounting left %llu size %llu\n", printk(KERN_CRIT "bad ordered accounting left %llu size %llu\n",
(unsigned long long)entry->bytes_left, entry->bytes_left, io_size);
(unsigned long long)io_size);
} }
entry->bytes_left -= io_size; entry->bytes_left -= io_size;
if (!uptodate) if (!uptodate)
...@@ -671,7 +669,7 @@ int btrfs_run_ordered_operations(struct btrfs_trans_handle *trans, ...@@ -671,7 +669,7 @@ int btrfs_run_ordered_operations(struct btrfs_trans_handle *trans,
INIT_LIST_HEAD(&splice); INIT_LIST_HEAD(&splice);
INIT_LIST_HEAD(&works); INIT_LIST_HEAD(&works);
mutex_lock(&root->fs_info->ordered_operations_mutex); mutex_lock(&root->fs_info->ordered_extent_flush_mutex);
spin_lock(&root->fs_info->ordered_root_lock); spin_lock(&root->fs_info->ordered_root_lock);
list_splice_init(&cur_trans->ordered_operations, &splice); list_splice_init(&cur_trans->ordered_operations, &splice);
while (!list_empty(&splice)) { while (!list_empty(&splice)) {
...@@ -718,7 +716,7 @@ int btrfs_run_ordered_operations(struct btrfs_trans_handle *trans, ...@@ -718,7 +716,7 @@ int btrfs_run_ordered_operations(struct btrfs_trans_handle *trans,
list_del_init(&work->list); list_del_init(&work->list);
btrfs_wait_and_free_delalloc_work(work); btrfs_wait_and_free_delalloc_work(work);
} }
mutex_unlock(&root->fs_info->ordered_operations_mutex); mutex_unlock(&root->fs_info->ordered_extent_flush_mutex);
return ret; return ret;
} }
...@@ -923,12 +921,16 @@ int btrfs_ordered_update_i_size(struct inode *inode, u64 offset, ...@@ -923,12 +921,16 @@ int btrfs_ordered_update_i_size(struct inode *inode, u64 offset,
struct btrfs_ordered_extent *test; struct btrfs_ordered_extent *test;
int ret = 1; int ret = 1;
if (ordered) spin_lock_irq(&tree->lock);
if (ordered) {
offset = entry_end(ordered); offset = entry_end(ordered);
else if (test_bit(BTRFS_ORDERED_TRUNCATED, &ordered->flags))
offset = min(offset,
ordered->file_offset +
ordered->truncated_len);
} else {
offset = ALIGN(offset, BTRFS_I(inode)->root->sectorsize); offset = ALIGN(offset, BTRFS_I(inode)->root->sectorsize);
}
spin_lock_irq(&tree->lock);
disk_i_size = BTRFS_I(inode)->disk_i_size; disk_i_size = BTRFS_I(inode)->disk_i_size;
/* truncate file */ /* truncate file */
......
...@@ -69,6 +69,7 @@ struct btrfs_ordered_sum { ...@@ -69,6 +69,7 @@ struct btrfs_ordered_sum {
* the isize. */ * the isize. */
#define BTRFS_ORDERED_LOGGED_CSUM 8 /* We've logged the csums on this ordered #define BTRFS_ORDERED_LOGGED_CSUM 8 /* We've logged the csums on this ordered
ordered extent */ ordered extent */
#define BTRFS_ORDERED_TRUNCATED 9 /* Set when we have to truncate an extent */
struct btrfs_ordered_extent { struct btrfs_ordered_extent {
/* logical offset in the file */ /* logical offset in the file */
...@@ -96,6 +97,12 @@ struct btrfs_ordered_extent { ...@@ -96,6 +97,12 @@ struct btrfs_ordered_extent {
*/ */
u64 outstanding_isize; u64 outstanding_isize;
/*
* If we get truncated we need to adjust the file extent we enter for
* this ordered extent so that we do not expose stale data.
*/
u64 truncated_len;
/* flags (described above) */ /* flags (described above) */
unsigned long flags; unsigned long flags;
......
...@@ -26,14 +26,12 @@ static void print_chunk(struct extent_buffer *eb, struct btrfs_chunk *chunk) ...@@ -26,14 +26,12 @@ static void print_chunk(struct extent_buffer *eb, struct btrfs_chunk *chunk)
int i; int i;
printk(KERN_INFO "\t\tchunk length %llu owner %llu type %llu " printk(KERN_INFO "\t\tchunk length %llu owner %llu type %llu "
"num_stripes %d\n", "num_stripes %d\n",
(unsigned long long)btrfs_chunk_length(eb, chunk), btrfs_chunk_length(eb, chunk), btrfs_chunk_owner(eb, chunk),
(unsigned long long)btrfs_chunk_owner(eb, chunk), btrfs_chunk_type(eb, chunk), num_stripes);
(unsigned long long)btrfs_chunk_type(eb, chunk),
num_stripes);
for (i = 0 ; i < num_stripes ; i++) { for (i = 0 ; i < num_stripes ; i++) {
printk(KERN_INFO "\t\t\tstripe %d devid %llu offset %llu\n", i, printk(KERN_INFO "\t\t\tstripe %d devid %llu offset %llu\n", i,
(unsigned long long)btrfs_stripe_devid_nr(eb, chunk, i), btrfs_stripe_devid_nr(eb, chunk, i),
(unsigned long long)btrfs_stripe_offset_nr(eb, chunk, i)); btrfs_stripe_offset_nr(eb, chunk, i));
} }
} }
static void print_dev_item(struct extent_buffer *eb, static void print_dev_item(struct extent_buffer *eb,
...@@ -41,18 +39,18 @@ static void print_dev_item(struct extent_buffer *eb, ...@@ -41,18 +39,18 @@ static void print_dev_item(struct extent_buffer *eb,
{ {
printk(KERN_INFO "\t\tdev item devid %llu " printk(KERN_INFO "\t\tdev item devid %llu "
"total_bytes %llu bytes used %llu\n", "total_bytes %llu bytes used %llu\n",
(unsigned long long)btrfs_device_id(eb, dev_item), btrfs_device_id(eb, dev_item),
(unsigned long long)btrfs_device_total_bytes(eb, dev_item), btrfs_device_total_bytes(eb, dev_item),
(unsigned long long)btrfs_device_bytes_used(eb, dev_item)); btrfs_device_bytes_used(eb, dev_item));
} }
static void print_extent_data_ref(struct extent_buffer *eb, static void print_extent_data_ref(struct extent_buffer *eb,
struct btrfs_extent_data_ref *ref) struct btrfs_extent_data_ref *ref)
{ {
printk(KERN_INFO "\t\textent data backref root %llu " printk(KERN_INFO "\t\textent data backref root %llu "
"objectid %llu offset %llu count %u\n", "objectid %llu offset %llu count %u\n",
(unsigned long long)btrfs_extent_data_ref_root(eb, ref), btrfs_extent_data_ref_root(eb, ref),
(unsigned long long)btrfs_extent_data_ref_objectid(eb, ref), btrfs_extent_data_ref_objectid(eb, ref),
(unsigned long long)btrfs_extent_data_ref_offset(eb, ref), btrfs_extent_data_ref_offset(eb, ref),
btrfs_extent_data_ref_count(eb, ref)); btrfs_extent_data_ref_count(eb, ref));
} }
...@@ -87,19 +85,17 @@ static void print_extent_item(struct extent_buffer *eb, int slot) ...@@ -87,19 +85,17 @@ static void print_extent_item(struct extent_buffer *eb, int slot)
flags = btrfs_extent_flags(eb, ei); flags = btrfs_extent_flags(eb, ei);
printk(KERN_INFO "\t\textent refs %llu gen %llu flags %llu\n", printk(KERN_INFO "\t\textent refs %llu gen %llu flags %llu\n",
(unsigned long long)btrfs_extent_refs(eb, ei), btrfs_extent_refs(eb, ei), btrfs_extent_generation(eb, ei),
(unsigned long long)btrfs_extent_generation(eb, ei), flags);
(unsigned long long)flags);
if (flags & BTRFS_EXTENT_FLAG_TREE_BLOCK) { if (flags & BTRFS_EXTENT_FLAG_TREE_BLOCK) {
struct btrfs_tree_block_info *info; struct btrfs_tree_block_info *info;
info = (struct btrfs_tree_block_info *)(ei + 1); info = (struct btrfs_tree_block_info *)(ei + 1);
btrfs_tree_block_key(eb, info, &key); btrfs_tree_block_key(eb, info, &key);
printk(KERN_INFO "\t\ttree block key (%llu %x %llu) " printk(KERN_INFO "\t\ttree block key (%llu %u %llu) "
"level %d\n", "level %d\n",
(unsigned long long)btrfs_disk_key_objectid(&key), btrfs_disk_key_objectid(&key), key.type,
key.type, btrfs_disk_key_offset(&key),
(unsigned long long)btrfs_disk_key_offset(&key),
btrfs_tree_block_level(eb, info)); btrfs_tree_block_level(eb, info));
iref = (struct btrfs_extent_inline_ref *)(info + 1); iref = (struct btrfs_extent_inline_ref *)(info + 1);
} else { } else {
...@@ -115,11 +111,11 @@ static void print_extent_item(struct extent_buffer *eb, int slot) ...@@ -115,11 +111,11 @@ static void print_extent_item(struct extent_buffer *eb, int slot)
switch (type) { switch (type) {
case BTRFS_TREE_BLOCK_REF_KEY: case BTRFS_TREE_BLOCK_REF_KEY:
printk(KERN_INFO "\t\ttree block backref " printk(KERN_INFO "\t\ttree block backref "
"root %llu\n", (unsigned long long)offset); "root %llu\n", offset);
break; break;
case BTRFS_SHARED_BLOCK_REF_KEY: case BTRFS_SHARED_BLOCK_REF_KEY:
printk(KERN_INFO "\t\tshared block backref " printk(KERN_INFO "\t\tshared block backref "
"parent %llu\n", (unsigned long long)offset); "parent %llu\n", offset);
break; break;
case BTRFS_EXTENT_DATA_REF_KEY: case BTRFS_EXTENT_DATA_REF_KEY:
dref = (struct btrfs_extent_data_ref *)(&iref->offset); dref = (struct btrfs_extent_data_ref *)(&iref->offset);
...@@ -129,8 +125,7 @@ static void print_extent_item(struct extent_buffer *eb, int slot) ...@@ -129,8 +125,7 @@ static void print_extent_item(struct extent_buffer *eb, int slot)
sref = (struct btrfs_shared_data_ref *)(iref + 1); sref = (struct btrfs_shared_data_ref *)(iref + 1);
printk(KERN_INFO "\t\tshared data backref " printk(KERN_INFO "\t\tshared data backref "
"parent %llu count %u\n", "parent %llu count %u\n",
(unsigned long long)offset, offset, btrfs_shared_data_ref_count(eb, sref));
btrfs_shared_data_ref_count(eb, sref));
break; break;
default: default:
BUG(); BUG();
...@@ -148,13 +143,32 @@ static void print_extent_ref_v0(struct extent_buffer *eb, int slot) ...@@ -148,13 +143,32 @@ static void print_extent_ref_v0(struct extent_buffer *eb, int slot)
ref0 = btrfs_item_ptr(eb, slot, struct btrfs_extent_ref_v0); ref0 = btrfs_item_ptr(eb, slot, struct btrfs_extent_ref_v0);
printk("\t\textent back ref root %llu gen %llu " printk("\t\textent back ref root %llu gen %llu "
"owner %llu num_refs %lu\n", "owner %llu num_refs %lu\n",
(unsigned long long)btrfs_ref_root_v0(eb, ref0), btrfs_ref_root_v0(eb, ref0),
(unsigned long long)btrfs_ref_generation_v0(eb, ref0), btrfs_ref_generation_v0(eb, ref0),
(unsigned long long)btrfs_ref_objectid_v0(eb, ref0), btrfs_ref_objectid_v0(eb, ref0),
(unsigned long)btrfs_ref_count_v0(eb, ref0)); (unsigned long)btrfs_ref_count_v0(eb, ref0));
} }
#endif #endif
static void print_uuid_item(struct extent_buffer *l, unsigned long offset,
u32 item_size)
{
if (!IS_ALIGNED(item_size, sizeof(u64))) {
pr_warn("btrfs: uuid item with illegal size %lu!\n",
(unsigned long)item_size);
return;
}
while (item_size) {
__le64 subvol_id;
read_extent_buffer(l, &subvol_id, offset, sizeof(subvol_id));
printk(KERN_INFO "\t\tsubvol_id %llu\n",
(unsigned long long)le64_to_cpu(subvol_id));
item_size -= sizeof(u64);
offset += sizeof(u64);
}
}
void btrfs_print_leaf(struct btrfs_root *root, struct extent_buffer *l) void btrfs_print_leaf(struct btrfs_root *root, struct extent_buffer *l)
{ {
int i; int i;
...@@ -177,39 +191,34 @@ void btrfs_print_leaf(struct btrfs_root *root, struct extent_buffer *l) ...@@ -177,39 +191,34 @@ void btrfs_print_leaf(struct btrfs_root *root, struct extent_buffer *l)
nr = btrfs_header_nritems(l); nr = btrfs_header_nritems(l);
btrfs_info(root->fs_info, "leaf %llu total ptrs %d free space %d", btrfs_info(root->fs_info, "leaf %llu total ptrs %d free space %d",
(unsigned long long)btrfs_header_bytenr(l), nr, btrfs_header_bytenr(l), nr, btrfs_leaf_free_space(root, l));
btrfs_leaf_free_space(root, l));
for (i = 0 ; i < nr ; i++) { for (i = 0 ; i < nr ; i++) {
item = btrfs_item_nr(l, i); item = btrfs_item_nr(l, i);
btrfs_item_key_to_cpu(l, &key, i); btrfs_item_key_to_cpu(l, &key, i);
type = btrfs_key_type(&key); type = btrfs_key_type(&key);
printk(KERN_INFO "\titem %d key (%llu %x %llu) itemoff %d " printk(KERN_INFO "\titem %d key (%llu %u %llu) itemoff %d "
"itemsize %d\n", "itemsize %d\n",
i, i, key.objectid, type, key.offset,
(unsigned long long)key.objectid, type,
(unsigned long long)key.offset,
btrfs_item_offset(l, item), btrfs_item_size(l, item)); btrfs_item_offset(l, item), btrfs_item_size(l, item));
switch (type) { switch (type) {
case BTRFS_INODE_ITEM_KEY: case BTRFS_INODE_ITEM_KEY:
ii = btrfs_item_ptr(l, i, struct btrfs_inode_item); ii = btrfs_item_ptr(l, i, struct btrfs_inode_item);
printk(KERN_INFO "\t\tinode generation %llu size %llu " printk(KERN_INFO "\t\tinode generation %llu size %llu "
"mode %o\n", "mode %o\n",
(unsigned long long)
btrfs_inode_generation(l, ii), btrfs_inode_generation(l, ii),
(unsigned long long)btrfs_inode_size(l, ii), btrfs_inode_size(l, ii),
btrfs_inode_mode(l, ii)); btrfs_inode_mode(l, ii));
break; break;
case BTRFS_DIR_ITEM_KEY: case BTRFS_DIR_ITEM_KEY:
di = btrfs_item_ptr(l, i, struct btrfs_dir_item); di = btrfs_item_ptr(l, i, struct btrfs_dir_item);
btrfs_dir_item_key_to_cpu(l, di, &found_key); btrfs_dir_item_key_to_cpu(l, di, &found_key);
printk(KERN_INFO "\t\tdir oid %llu type %u\n", printk(KERN_INFO "\t\tdir oid %llu type %u\n",
(unsigned long long)found_key.objectid, found_key.objectid,
btrfs_dir_type(l, di)); btrfs_dir_type(l, di));
break; break;
case BTRFS_ROOT_ITEM_KEY: case BTRFS_ROOT_ITEM_KEY:
ri = btrfs_item_ptr(l, i, struct btrfs_root_item); ri = btrfs_item_ptr(l, i, struct btrfs_root_item);
printk(KERN_INFO "\t\troot data bytenr %llu refs %u\n", printk(KERN_INFO "\t\troot data bytenr %llu refs %u\n",
(unsigned long long)
btrfs_disk_root_bytenr(l, ri), btrfs_disk_root_bytenr(l, ri),
btrfs_disk_root_refs(l, ri)); btrfs_disk_root_refs(l, ri));
break; break;
...@@ -245,17 +254,12 @@ void btrfs_print_leaf(struct btrfs_root *root, struct extent_buffer *l) ...@@ -245,17 +254,12 @@ void btrfs_print_leaf(struct btrfs_root *root, struct extent_buffer *l)
} }
printk(KERN_INFO "\t\textent data disk bytenr %llu " printk(KERN_INFO "\t\textent data disk bytenr %llu "
"nr %llu\n", "nr %llu\n",
(unsigned long long)
btrfs_file_extent_disk_bytenr(l, fi), btrfs_file_extent_disk_bytenr(l, fi),
(unsigned long long)
btrfs_file_extent_disk_num_bytes(l, fi)); btrfs_file_extent_disk_num_bytes(l, fi));
printk(KERN_INFO "\t\textent data offset %llu " printk(KERN_INFO "\t\textent data offset %llu "
"nr %llu ram %llu\n", "nr %llu ram %llu\n",
(unsigned long long)
btrfs_file_extent_offset(l, fi), btrfs_file_extent_offset(l, fi),
(unsigned long long)
btrfs_file_extent_num_bytes(l, fi), btrfs_file_extent_num_bytes(l, fi),
(unsigned long long)
btrfs_file_extent_ram_bytes(l, fi)); btrfs_file_extent_ram_bytes(l, fi));
break; break;
case BTRFS_EXTENT_REF_V0_KEY: case BTRFS_EXTENT_REF_V0_KEY:
...@@ -269,7 +273,6 @@ void btrfs_print_leaf(struct btrfs_root *root, struct extent_buffer *l) ...@@ -269,7 +273,6 @@ void btrfs_print_leaf(struct btrfs_root *root, struct extent_buffer *l)
bi = btrfs_item_ptr(l, i, bi = btrfs_item_ptr(l, i,
struct btrfs_block_group_item); struct btrfs_block_group_item);
printk(KERN_INFO "\t\tblock group used %llu\n", printk(KERN_INFO "\t\tblock group used %llu\n",
(unsigned long long)
btrfs_disk_block_group_used(l, bi)); btrfs_disk_block_group_used(l, bi));
break; break;
case BTRFS_CHUNK_ITEM_KEY: case BTRFS_CHUNK_ITEM_KEY:
...@@ -286,13 +289,9 @@ void btrfs_print_leaf(struct btrfs_root *root, struct extent_buffer *l) ...@@ -286,13 +289,9 @@ void btrfs_print_leaf(struct btrfs_root *root, struct extent_buffer *l)
printk(KERN_INFO "\t\tdev extent chunk_tree %llu\n" printk(KERN_INFO "\t\tdev extent chunk_tree %llu\n"
"\t\tchunk objectid %llu chunk offset %llu " "\t\tchunk objectid %llu chunk offset %llu "
"length %llu\n", "length %llu\n",
(unsigned long long)
btrfs_dev_extent_chunk_tree(l, dev_extent), btrfs_dev_extent_chunk_tree(l, dev_extent),
(unsigned long long)
btrfs_dev_extent_chunk_objectid(l, dev_extent), btrfs_dev_extent_chunk_objectid(l, dev_extent),
(unsigned long long)
btrfs_dev_extent_chunk_offset(l, dev_extent), btrfs_dev_extent_chunk_offset(l, dev_extent),
(unsigned long long)
btrfs_dev_extent_length(l, dev_extent)); btrfs_dev_extent_length(l, dev_extent));
break; break;
case BTRFS_DEV_STATS_KEY: case BTRFS_DEV_STATS_KEY:
...@@ -301,6 +300,11 @@ void btrfs_print_leaf(struct btrfs_root *root, struct extent_buffer *l) ...@@ -301,6 +300,11 @@ void btrfs_print_leaf(struct btrfs_root *root, struct extent_buffer *l)
case BTRFS_DEV_REPLACE_KEY: case BTRFS_DEV_REPLACE_KEY:
printk(KERN_INFO "\t\tdev replace\n"); printk(KERN_INFO "\t\tdev replace\n");
break; break;
case BTRFS_UUID_KEY_SUBVOL:
case BTRFS_UUID_KEY_RECEIVED_SUBVOL:
print_uuid_item(l, btrfs_item_ptr_offset(l, i),
btrfs_item_size_nr(l, i));
break;
}; };
} }
} }
...@@ -320,16 +324,13 @@ void btrfs_print_tree(struct btrfs_root *root, struct extent_buffer *c) ...@@ -320,16 +324,13 @@ void btrfs_print_tree(struct btrfs_root *root, struct extent_buffer *c)
return; return;
} }
btrfs_info(root->fs_info, "node %llu level %d total ptrs %d free spc %u", btrfs_info(root->fs_info, "node %llu level %d total ptrs %d free spc %u",
(unsigned long long)btrfs_header_bytenr(c), btrfs_header_bytenr(c), level, nr,
level, nr, (u32)BTRFS_NODEPTRS_PER_BLOCK(root) - nr); (u32)BTRFS_NODEPTRS_PER_BLOCK(root) - nr);
for (i = 0; i < nr; i++) { for (i = 0; i < nr; i++) {
btrfs_node_key_to_cpu(c, &key, i); btrfs_node_key_to_cpu(c, &key, i);
printk(KERN_INFO "\tkey %d (%llu %u %llu) block %llu\n", printk(KERN_INFO "\tkey %d (%llu %u %llu) block %llu\n",
i, i, key.objectid, key.type, key.offset,
(unsigned long long)key.objectid, btrfs_node_blockptr(c, i));
key.type,
(unsigned long long)key.offset,
(unsigned long long)btrfs_node_blockptr(c, i));
} }
for (i = 0; i < nr; i++) { for (i = 0; i < nr; i++) {
struct extent_buffer *next = read_tree_block(root, struct extent_buffer *next = read_tree_block(root,
......
...@@ -157,18 +157,11 @@ static struct btrfs_qgroup *add_qgroup_rb(struct btrfs_fs_info *fs_info, ...@@ -157,18 +157,11 @@ static struct btrfs_qgroup *add_qgroup_rb(struct btrfs_fs_info *fs_info,
return qgroup; return qgroup;
} }
/* must be called with qgroup_lock held */ static void __del_qgroup_rb(struct btrfs_qgroup *qgroup)
static int del_qgroup_rb(struct btrfs_fs_info *fs_info, u64 qgroupid)
{ {
struct btrfs_qgroup *qgroup = find_qgroup_rb(fs_info, qgroupid);
struct btrfs_qgroup_list *list; struct btrfs_qgroup_list *list;
if (!qgroup)
return -ENOENT;
rb_erase(&qgroup->node, &fs_info->qgroup_tree);
list_del(&qgroup->dirty); list_del(&qgroup->dirty);
while (!list_empty(&qgroup->groups)) { while (!list_empty(&qgroup->groups)) {
list = list_first_entry(&qgroup->groups, list = list_first_entry(&qgroup->groups,
struct btrfs_qgroup_list, next_group); struct btrfs_qgroup_list, next_group);
...@@ -185,7 +178,18 @@ static int del_qgroup_rb(struct btrfs_fs_info *fs_info, u64 qgroupid) ...@@ -185,7 +178,18 @@ static int del_qgroup_rb(struct btrfs_fs_info *fs_info, u64 qgroupid)
kfree(list); kfree(list);
} }
kfree(qgroup); kfree(qgroup);
}
/* must be called with qgroup_lock held */
static int del_qgroup_rb(struct btrfs_fs_info *fs_info, u64 qgroupid)
{
struct btrfs_qgroup *qgroup = find_qgroup_rb(fs_info, qgroupid);
if (!qgroup)
return -ENOENT;
rb_erase(&qgroup->node, &fs_info->qgroup_tree);
__del_qgroup_rb(qgroup);
return 0; return 0;
} }
...@@ -394,8 +398,7 @@ int btrfs_read_qgroup_config(struct btrfs_fs_info *fs_info) ...@@ -394,8 +398,7 @@ int btrfs_read_qgroup_config(struct btrfs_fs_info *fs_info)
if (ret == -ENOENT) { if (ret == -ENOENT) {
printk(KERN_WARNING printk(KERN_WARNING
"btrfs: orphan qgroup relation 0x%llx->0x%llx\n", "btrfs: orphan qgroup relation 0x%llx->0x%llx\n",
(unsigned long long)found_key.objectid, found_key.objectid, found_key.offset);
(unsigned long long)found_key.offset);
ret = 0; /* ignore the error */ ret = 0; /* ignore the error */
} }
if (ret) if (ret)
...@@ -428,39 +431,28 @@ int btrfs_read_qgroup_config(struct btrfs_fs_info *fs_info) ...@@ -428,39 +431,28 @@ int btrfs_read_qgroup_config(struct btrfs_fs_info *fs_info)
} }
/* /*
* This is only called from close_ctree() or open_ctree(), both in single- * This is called from close_ctree() or open_ctree() or btrfs_quota_disable(),
* treaded paths. Clean up the in-memory structures. No locking needed. * first two are in single-threaded paths.And for the third one, we have set
* quota_root to be null with qgroup_lock held before, so it is safe to clean
* up the in-memory structures without qgroup_lock held.
*/ */
void btrfs_free_qgroup_config(struct btrfs_fs_info *fs_info) void btrfs_free_qgroup_config(struct btrfs_fs_info *fs_info)
{ {
struct rb_node *n; struct rb_node *n;
struct btrfs_qgroup *qgroup; struct btrfs_qgroup *qgroup;
struct btrfs_qgroup_list *list;
while ((n = rb_first(&fs_info->qgroup_tree))) { while ((n = rb_first(&fs_info->qgroup_tree))) {
qgroup = rb_entry(n, struct btrfs_qgroup, node); qgroup = rb_entry(n, struct btrfs_qgroup, node);
rb_erase(n, &fs_info->qgroup_tree); rb_erase(n, &fs_info->qgroup_tree);
__del_qgroup_rb(qgroup);
while (!list_empty(&qgroup->groups)) {
list = list_first_entry(&qgroup->groups,
struct btrfs_qgroup_list,
next_group);
list_del(&list->next_group);
list_del(&list->next_member);
kfree(list);
}
while (!list_empty(&qgroup->members)) {
list = list_first_entry(&qgroup->members,
struct btrfs_qgroup_list,
next_member);
list_del(&list->next_group);
list_del(&list->next_member);
kfree(list);
}
kfree(qgroup);
} }
/*
* we call btrfs_free_qgroup_config() when umounting
* filesystem and disabling quota, so we set qgroup_ulit
* to be null here to avoid double free.
*/
ulist_free(fs_info->qgroup_ulist); ulist_free(fs_info->qgroup_ulist);
fs_info->qgroup_ulist = NULL;
} }
static int add_qgroup_relation_item(struct btrfs_trans_handle *trans, static int add_qgroup_relation_item(struct btrfs_trans_handle *trans,
...@@ -946,13 +938,9 @@ int btrfs_quota_disable(struct btrfs_trans_handle *trans, ...@@ -946,13 +938,9 @@ int btrfs_quota_disable(struct btrfs_trans_handle *trans,
fs_info->pending_quota_state = 0; fs_info->pending_quota_state = 0;
quota_root = fs_info->quota_root; quota_root = fs_info->quota_root;
fs_info->quota_root = NULL; fs_info->quota_root = NULL;
btrfs_free_qgroup_config(fs_info);
spin_unlock(&fs_info->qgroup_lock); spin_unlock(&fs_info->qgroup_lock);
if (!quota_root) { btrfs_free_qgroup_config(fs_info);
ret = -EINVAL;
goto out;
}
ret = btrfs_clean_quota_tree(trans, quota_root); ret = btrfs_clean_quota_tree(trans, quota_root);
if (ret) if (ret)
...@@ -1174,7 +1162,7 @@ int btrfs_limit_qgroup(struct btrfs_trans_handle *trans, ...@@ -1174,7 +1162,7 @@ int btrfs_limit_qgroup(struct btrfs_trans_handle *trans,
if (ret) { if (ret) {
fs_info->qgroup_flags |= BTRFS_QGROUP_STATUS_FLAG_INCONSISTENT; fs_info->qgroup_flags |= BTRFS_QGROUP_STATUS_FLAG_INCONSISTENT;
printk(KERN_INFO "unable to update quota limit for %llu\n", printk(KERN_INFO "unable to update quota limit for %llu\n",
(unsigned long long)qgroupid); qgroupid);
} }
spin_lock(&fs_info->qgroup_lock); spin_lock(&fs_info->qgroup_lock);
...@@ -1884,10 +1872,9 @@ qgroup_rescan_leaf(struct btrfs_fs_info *fs_info, struct btrfs_path *path, ...@@ -1884,10 +1872,9 @@ qgroup_rescan_leaf(struct btrfs_fs_info *fs_info, struct btrfs_path *path,
path, 1, 0); path, 1, 0);
pr_debug("current progress key (%llu %u %llu), search_slot ret %d\n", pr_debug("current progress key (%llu %u %llu), search_slot ret %d\n",
(unsigned long long)fs_info->qgroup_rescan_progress.objectid, fs_info->qgroup_rescan_progress.objectid,
fs_info->qgroup_rescan_progress.type, fs_info->qgroup_rescan_progress.type,
(unsigned long long)fs_info->qgroup_rescan_progress.offset, fs_info->qgroup_rescan_progress.offset, ret);
ret);
if (ret) { if (ret) {
/* /*
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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