提交 f9156c72 编写于 作者: L Linus Torvalds

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

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mason/linux-btrfs: (62 commits)
  Btrfs: use larger system chunks
  Btrfs: add a delalloc mutex to inodes for delalloc reservations
  Btrfs: space leak tracepoints
  Btrfs: protect orphan block rsv with spin_lock
  Btrfs: add allocator tracepoints
  Btrfs: don't call btrfs_throttle in file write
  Btrfs: release space on error in page_mkwrite
  Btrfs: fix btrfsck error 400 when truncating a compressed
  Btrfs: do not use btrfs_end_transaction_throttle everywhere
  Btrfs: add balance progress reporting
  Btrfs: allow for resuming restriper after it was paused
  Btrfs: allow for canceling restriper
  Btrfs: allow for pausing restriper
  Btrfs: add skip_balance mount option
  Btrfs: recover balance on mount
  Btrfs: save balance parameters to disk
  Btrfs: soft profile changing mode (aka soft convert)
  Btrfs: implement online profile changing
  Btrfs: do not reduce profile in do_chunk_alloc()
  Btrfs: virtual address space subset filter
  ...

Fix up trivial conflict in fs/btrfs/ioctl.c due to the use of the new
mnt_drop_write_file() helper.
...@@ -31,3 +31,22 @@ config BTRFS_FS_POSIX_ACL ...@@ -31,3 +31,22 @@ config BTRFS_FS_POSIX_ACL
Linux website <http://acl.bestbits.at/>. Linux website <http://acl.bestbits.at/>.
If you don't know what Access Control Lists are, say N If you don't know what Access Control Lists are, say N
config BTRFS_FS_CHECK_INTEGRITY
bool "Btrfs with integrity check tool compiled in (DANGEROUS)"
depends on BTRFS_FS
help
Adds code that examines all block write requests (including
writes of the super block). The goal is to verify that the
state of the filesystem on disk is always consistent, i.e.,
after a power-loss or kernel panic event the filesystem is
in a consistent state.
If the integrity check tool is included and activated in
the mount options, plenty of kernel memory is used, and
plenty of additional CPU cycles are spent. Enabling this
functionality is not intended for normal use.
In most cases, unless you are a btrfs developer who needs
to verify the integrity of (super)-block write requests
during the run of a regression test, say N
...@@ -8,6 +8,7 @@ btrfs-y += super.o ctree.o extent-tree.o print-tree.o root-tree.o dir-item.o \ ...@@ -8,6 +8,7 @@ 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 reada.o backref.o ulist.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
此差异已折叠。
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
#define __BTRFS_BACKREF__ #define __BTRFS_BACKREF__
#include "ioctl.h" #include "ioctl.h"
#include "ulist.h"
struct inode_fs_paths { struct inode_fs_paths {
struct btrfs_path *btrfs_path; struct btrfs_path *btrfs_path;
...@@ -54,6 +55,10 @@ int iterate_inodes_from_logical(u64 logical, struct btrfs_fs_info *fs_info, ...@@ -54,6 +55,10 @@ int iterate_inodes_from_logical(u64 logical, struct btrfs_fs_info *fs_info,
int paths_from_inode(u64 inum, struct inode_fs_paths *ipath); int paths_from_inode(u64 inum, struct inode_fs_paths *ipath);
int btrfs_find_all_roots(struct btrfs_trans_handle *trans,
struct btrfs_fs_info *fs_info, u64 bytenr,
u64 num_bytes, u64 seq, struct ulist **roots);
struct btrfs_data_container *init_data_container(u32 total_bytes); struct btrfs_data_container *init_data_container(u32 total_bytes);
struct inode_fs_paths *init_ipath(s32 total_bytes, struct btrfs_root *fs_root, struct inode_fs_paths *init_ipath(s32 total_bytes, struct btrfs_root *fs_root,
struct btrfs_path *path); struct btrfs_path *path);
......
...@@ -51,6 +51,9 @@ struct btrfs_inode { ...@@ -51,6 +51,9 @@ struct btrfs_inode {
/* held while logging the inode in tree-log.c */ /* held while logging the inode in tree-log.c */
struct mutex log_mutex; struct mutex log_mutex;
/* held while doing delalloc reservations */
struct mutex delalloc_mutex;
/* used to order data wrt metadata */ /* used to order data wrt metadata */
struct btrfs_ordered_inode_tree ordered_tree; struct btrfs_ordered_inode_tree ordered_tree;
......
此差异已折叠。
/*
* Copyright (C) STRATO AG 2011. All rights reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public
* License v2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this program; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 021110-1307, USA.
*/
#if !defined(__BTRFS_CHECK_INTEGRITY__)
#define __BTRFS_CHECK_INTEGRITY__
#ifdef CONFIG_BTRFS_FS_CHECK_INTEGRITY
int btrfsic_submit_bh(int rw, struct buffer_head *bh);
void btrfsic_submit_bio(int rw, struct bio *bio);
#else
#define btrfsic_submit_bh submit_bh
#define btrfsic_submit_bio submit_bio
#endif
int btrfsic_mount(struct btrfs_root *root,
struct btrfs_fs_devices *fs_devices,
int including_extent_data, u32 print_mask);
void btrfsic_unmount(struct btrfs_root *root,
struct btrfs_fs_devices *fs_devices);
#endif
...@@ -240,7 +240,7 @@ int btrfs_copy_root(struct btrfs_trans_handle *trans, ...@@ -240,7 +240,7 @@ int btrfs_copy_root(struct btrfs_trans_handle *trans,
cow = btrfs_alloc_free_block(trans, root, buf->len, 0, cow = btrfs_alloc_free_block(trans, root, buf->len, 0,
new_root_objectid, &disk_key, level, new_root_objectid, &disk_key, level,
buf->start, 0); buf->start, 0, 1);
if (IS_ERR(cow)) if (IS_ERR(cow))
return PTR_ERR(cow); return PTR_ERR(cow);
...@@ -261,9 +261,9 @@ int btrfs_copy_root(struct btrfs_trans_handle *trans, ...@@ -261,9 +261,9 @@ int btrfs_copy_root(struct btrfs_trans_handle *trans,
WARN_ON(btrfs_header_generation(buf) > trans->transid); WARN_ON(btrfs_header_generation(buf) > trans->transid);
if (new_root_objectid == BTRFS_TREE_RELOC_OBJECTID) if (new_root_objectid == BTRFS_TREE_RELOC_OBJECTID)
ret = btrfs_inc_ref(trans, root, cow, 1); ret = btrfs_inc_ref(trans, root, cow, 1, 1);
else else
ret = btrfs_inc_ref(trans, root, cow, 0); ret = btrfs_inc_ref(trans, root, cow, 0, 1);
if (ret) if (ret)
return ret; return ret;
...@@ -350,14 +350,14 @@ static noinline int update_ref_for_cow(struct btrfs_trans_handle *trans, ...@@ -350,14 +350,14 @@ static noinline int update_ref_for_cow(struct btrfs_trans_handle *trans,
if ((owner == root->root_key.objectid || if ((owner == root->root_key.objectid ||
root->root_key.objectid == BTRFS_TREE_RELOC_OBJECTID) && root->root_key.objectid == BTRFS_TREE_RELOC_OBJECTID) &&
!(flags & BTRFS_BLOCK_FLAG_FULL_BACKREF)) { !(flags & BTRFS_BLOCK_FLAG_FULL_BACKREF)) {
ret = btrfs_inc_ref(trans, root, buf, 1); ret = btrfs_inc_ref(trans, root, buf, 1, 1);
BUG_ON(ret); BUG_ON(ret);
if (root->root_key.objectid == if (root->root_key.objectid ==
BTRFS_TREE_RELOC_OBJECTID) { BTRFS_TREE_RELOC_OBJECTID) {
ret = btrfs_dec_ref(trans, root, buf, 0); ret = btrfs_dec_ref(trans, root, buf, 0, 1);
BUG_ON(ret); BUG_ON(ret);
ret = btrfs_inc_ref(trans, root, cow, 1); ret = btrfs_inc_ref(trans, root, cow, 1, 1);
BUG_ON(ret); BUG_ON(ret);
} }
new_flags |= BTRFS_BLOCK_FLAG_FULL_BACKREF; new_flags |= BTRFS_BLOCK_FLAG_FULL_BACKREF;
...@@ -365,9 +365,9 @@ static noinline int update_ref_for_cow(struct btrfs_trans_handle *trans, ...@@ -365,9 +365,9 @@ static noinline int update_ref_for_cow(struct btrfs_trans_handle *trans,
if (root->root_key.objectid == if (root->root_key.objectid ==
BTRFS_TREE_RELOC_OBJECTID) BTRFS_TREE_RELOC_OBJECTID)
ret = btrfs_inc_ref(trans, root, cow, 1); ret = btrfs_inc_ref(trans, root, cow, 1, 1);
else else
ret = btrfs_inc_ref(trans, root, cow, 0); ret = btrfs_inc_ref(trans, root, cow, 0, 1);
BUG_ON(ret); BUG_ON(ret);
} }
if (new_flags != 0) { if (new_flags != 0) {
...@@ -381,11 +381,11 @@ static noinline int update_ref_for_cow(struct btrfs_trans_handle *trans, ...@@ -381,11 +381,11 @@ static noinline int update_ref_for_cow(struct btrfs_trans_handle *trans,
if (flags & BTRFS_BLOCK_FLAG_FULL_BACKREF) { if (flags & BTRFS_BLOCK_FLAG_FULL_BACKREF) {
if (root->root_key.objectid == if (root->root_key.objectid ==
BTRFS_TREE_RELOC_OBJECTID) BTRFS_TREE_RELOC_OBJECTID)
ret = btrfs_inc_ref(trans, root, cow, 1); ret = btrfs_inc_ref(trans, root, cow, 1, 1);
else else
ret = btrfs_inc_ref(trans, root, cow, 0); ret = btrfs_inc_ref(trans, root, cow, 0, 1);
BUG_ON(ret); BUG_ON(ret);
ret = btrfs_dec_ref(trans, root, buf, 1); ret = btrfs_dec_ref(trans, root, buf, 1, 1);
BUG_ON(ret); BUG_ON(ret);
} }
clean_tree_block(trans, root, buf); clean_tree_block(trans, root, buf);
...@@ -446,7 +446,7 @@ static noinline int __btrfs_cow_block(struct btrfs_trans_handle *trans, ...@@ -446,7 +446,7 @@ static noinline int __btrfs_cow_block(struct btrfs_trans_handle *trans,
cow = btrfs_alloc_free_block(trans, root, buf->len, parent_start, cow = btrfs_alloc_free_block(trans, root, buf->len, parent_start,
root->root_key.objectid, &disk_key, root->root_key.objectid, &disk_key,
level, search_start, empty_size); level, search_start, empty_size, 1);
if (IS_ERR(cow)) if (IS_ERR(cow))
return PTR_ERR(cow); return PTR_ERR(cow);
...@@ -484,7 +484,7 @@ static noinline int __btrfs_cow_block(struct btrfs_trans_handle *trans, ...@@ -484,7 +484,7 @@ static noinline int __btrfs_cow_block(struct btrfs_trans_handle *trans,
rcu_assign_pointer(root->node, cow); rcu_assign_pointer(root->node, cow);
btrfs_free_tree_block(trans, root, buf, parent_start, btrfs_free_tree_block(trans, root, buf, parent_start,
last_ref); last_ref, 1);
free_extent_buffer(buf); free_extent_buffer(buf);
add_root_to_dirty_list(root); add_root_to_dirty_list(root);
} else { } else {
...@@ -500,7 +500,7 @@ static noinline int __btrfs_cow_block(struct btrfs_trans_handle *trans, ...@@ -500,7 +500,7 @@ static noinline int __btrfs_cow_block(struct btrfs_trans_handle *trans,
trans->transid); trans->transid);
btrfs_mark_buffer_dirty(parent); btrfs_mark_buffer_dirty(parent);
btrfs_free_tree_block(trans, root, buf, parent_start, btrfs_free_tree_block(trans, root, buf, parent_start,
last_ref); last_ref, 1);
} }
if (unlock_orig) if (unlock_orig)
btrfs_tree_unlock(buf); btrfs_tree_unlock(buf);
...@@ -957,7 +957,7 @@ static noinline int balance_level(struct btrfs_trans_handle *trans, ...@@ -957,7 +957,7 @@ static noinline int balance_level(struct btrfs_trans_handle *trans,
free_extent_buffer(mid); free_extent_buffer(mid);
root_sub_used(root, mid->len); root_sub_used(root, mid->len);
btrfs_free_tree_block(trans, root, mid, 0, 1); btrfs_free_tree_block(trans, root, mid, 0, 1, 0);
/* once for the root ptr */ /* once for the root ptr */
free_extent_buffer(mid); free_extent_buffer(mid);
return 0; return 0;
...@@ -1015,7 +1015,7 @@ static noinline int balance_level(struct btrfs_trans_handle *trans, ...@@ -1015,7 +1015,7 @@ static noinline int balance_level(struct btrfs_trans_handle *trans,
if (wret) if (wret)
ret = wret; ret = wret;
root_sub_used(root, right->len); root_sub_used(root, right->len);
btrfs_free_tree_block(trans, root, right, 0, 1); btrfs_free_tree_block(trans, root, right, 0, 1, 0);
free_extent_buffer(right); free_extent_buffer(right);
right = NULL; right = NULL;
} else { } else {
...@@ -1055,7 +1055,7 @@ static noinline int balance_level(struct btrfs_trans_handle *trans, ...@@ -1055,7 +1055,7 @@ static noinline int balance_level(struct btrfs_trans_handle *trans,
if (wret) if (wret)
ret = wret; ret = wret;
root_sub_used(root, mid->len); root_sub_used(root, mid->len);
btrfs_free_tree_block(trans, root, mid, 0, 1); btrfs_free_tree_block(trans, root, mid, 0, 1, 0);
free_extent_buffer(mid); free_extent_buffer(mid);
mid = NULL; mid = NULL;
} else { } else {
...@@ -2089,7 +2089,7 @@ static noinline int insert_new_root(struct btrfs_trans_handle *trans, ...@@ -2089,7 +2089,7 @@ static noinline int insert_new_root(struct btrfs_trans_handle *trans,
c = btrfs_alloc_free_block(trans, root, root->nodesize, 0, c = btrfs_alloc_free_block(trans, root, root->nodesize, 0,
root->root_key.objectid, &lower_key, root->root_key.objectid, &lower_key,
level, root->node->start, 0); level, root->node->start, 0, 0);
if (IS_ERR(c)) if (IS_ERR(c))
return PTR_ERR(c); return PTR_ERR(c);
...@@ -2216,7 +2216,7 @@ static noinline int split_node(struct btrfs_trans_handle *trans, ...@@ -2216,7 +2216,7 @@ static noinline int split_node(struct btrfs_trans_handle *trans,
split = btrfs_alloc_free_block(trans, root, root->nodesize, 0, split = btrfs_alloc_free_block(trans, root, root->nodesize, 0,
root->root_key.objectid, root->root_key.objectid,
&disk_key, level, c->start, 0); &disk_key, level, c->start, 0, 0);
if (IS_ERR(split)) if (IS_ERR(split))
return PTR_ERR(split); return PTR_ERR(split);
...@@ -2970,7 +2970,7 @@ static noinline int split_leaf(struct btrfs_trans_handle *trans, ...@@ -2970,7 +2970,7 @@ static noinline int split_leaf(struct btrfs_trans_handle *trans,
right = btrfs_alloc_free_block(trans, root, root->leafsize, 0, right = btrfs_alloc_free_block(trans, root, root->leafsize, 0,
root->root_key.objectid, root->root_key.objectid,
&disk_key, 0, l->start, 0); &disk_key, 0, l->start, 0, 0);
if (IS_ERR(right)) if (IS_ERR(right))
return PTR_ERR(right); return PTR_ERR(right);
...@@ -3781,7 +3781,7 @@ static noinline int btrfs_del_leaf(struct btrfs_trans_handle *trans, ...@@ -3781,7 +3781,7 @@ static noinline int btrfs_del_leaf(struct btrfs_trans_handle *trans,
root_sub_used(root, leaf->len); root_sub_used(root, leaf->len);
btrfs_free_tree_block(trans, root, leaf, 0, 1); btrfs_free_tree_block(trans, root, leaf, 0, 1, 0);
return 0; return 0;
} }
/* /*
......
...@@ -86,6 +86,9 @@ struct btrfs_ordered_sum; ...@@ -86,6 +86,9 @@ struct btrfs_ordered_sum;
/* holds checksums of all the data extents */ /* holds checksums of all the data extents */
#define BTRFS_CSUM_TREE_OBJECTID 7ULL #define BTRFS_CSUM_TREE_OBJECTID 7ULL
/* for storing balance parameters in the root tree */
#define BTRFS_BALANCE_OBJECTID -4ULL
/* orhpan objectid for tracking unlinked/truncated files */ /* orhpan objectid for tracking unlinked/truncated files */
#define BTRFS_ORPHAN_OBJECTID -5ULL #define BTRFS_ORPHAN_OBJECTID -5ULL
...@@ -692,6 +695,54 @@ struct btrfs_root_ref { ...@@ -692,6 +695,54 @@ struct btrfs_root_ref {
__le16 name_len; __le16 name_len;
} __attribute__ ((__packed__)); } __attribute__ ((__packed__));
struct btrfs_disk_balance_args {
/*
* profiles to operate on, single is denoted by
* BTRFS_AVAIL_ALLOC_BIT_SINGLE
*/
__le64 profiles;
/* usage filter */
__le64 usage;
/* devid filter */
__le64 devid;
/* devid subset filter [pstart..pend) */
__le64 pstart;
__le64 pend;
/* btrfs virtual address space subset filter [vstart..vend) */
__le64 vstart;
__le64 vend;
/*
* profile to convert to, single is denoted by
* BTRFS_AVAIL_ALLOC_BIT_SINGLE
*/
__le64 target;
/* BTRFS_BALANCE_ARGS_* */
__le64 flags;
__le64 unused[8];
} __attribute__ ((__packed__));
/*
* store balance parameters to disk so that balance can be properly
* resumed after crash or unmount
*/
struct btrfs_balance_item {
/* BTRFS_BALANCE_* */
__le64 flags;
struct btrfs_disk_balance_args data;
struct btrfs_disk_balance_args meta;
struct btrfs_disk_balance_args sys;
__le64 unused[4];
} __attribute__ ((__packed__));
#define BTRFS_FILE_EXTENT_INLINE 0 #define BTRFS_FILE_EXTENT_INLINE 0
#define BTRFS_FILE_EXTENT_REG 1 #define BTRFS_FILE_EXTENT_REG 1
#define BTRFS_FILE_EXTENT_PREALLOC 2 #define BTRFS_FILE_EXTENT_PREALLOC 2
...@@ -751,14 +802,32 @@ struct btrfs_csum_item { ...@@ -751,14 +802,32 @@ struct btrfs_csum_item {
} __attribute__ ((__packed__)); } __attribute__ ((__packed__));
/* different types of block groups (and chunks) */ /* different types of block groups (and chunks) */
#define BTRFS_BLOCK_GROUP_DATA (1 << 0) #define BTRFS_BLOCK_GROUP_DATA (1ULL << 0)
#define BTRFS_BLOCK_GROUP_SYSTEM (1 << 1) #define BTRFS_BLOCK_GROUP_SYSTEM (1ULL << 1)
#define BTRFS_BLOCK_GROUP_METADATA (1 << 2) #define BTRFS_BLOCK_GROUP_METADATA (1ULL << 2)
#define BTRFS_BLOCK_GROUP_RAID0 (1 << 3) #define BTRFS_BLOCK_GROUP_RAID0 (1ULL << 3)
#define BTRFS_BLOCK_GROUP_RAID1 (1 << 4) #define BTRFS_BLOCK_GROUP_RAID1 (1ULL << 4)
#define BTRFS_BLOCK_GROUP_DUP (1 << 5) #define BTRFS_BLOCK_GROUP_DUP (1ULL << 5)
#define BTRFS_BLOCK_GROUP_RAID10 (1 << 6) #define BTRFS_BLOCK_GROUP_RAID10 (1ULL << 6)
#define BTRFS_NR_RAID_TYPES 5 #define BTRFS_BLOCK_GROUP_RESERVED BTRFS_AVAIL_ALLOC_BIT_SINGLE
#define BTRFS_NR_RAID_TYPES 5
#define BTRFS_BLOCK_GROUP_TYPE_MASK (BTRFS_BLOCK_GROUP_DATA | \
BTRFS_BLOCK_GROUP_SYSTEM | \
BTRFS_BLOCK_GROUP_METADATA)
#define BTRFS_BLOCK_GROUP_PROFILE_MASK (BTRFS_BLOCK_GROUP_RAID0 | \
BTRFS_BLOCK_GROUP_RAID1 | \
BTRFS_BLOCK_GROUP_DUP | \
BTRFS_BLOCK_GROUP_RAID10)
/*
* 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
* fs_info->avail_*_alloc_bits (in-memory) and balance item fields
* (on-disk). The corresponding on-disk bit in chunk.type is reserved
* to avoid remappings between two formats in future.
*/
#define BTRFS_AVAIL_ALLOC_BIT_SINGLE (1ULL << 48)
struct btrfs_block_group_item { struct btrfs_block_group_item {
__le64 used; __le64 used;
...@@ -916,6 +985,7 @@ struct btrfs_block_group_cache { ...@@ -916,6 +985,7 @@ struct btrfs_block_group_cache {
struct reloc_control; struct reloc_control;
struct btrfs_device; struct btrfs_device;
struct btrfs_fs_devices; struct btrfs_fs_devices;
struct btrfs_balance_control;
struct btrfs_delayed_root; struct btrfs_delayed_root;
struct btrfs_fs_info { struct btrfs_fs_info {
u8 fsid[BTRFS_FSID_SIZE]; u8 fsid[BTRFS_FSID_SIZE];
...@@ -971,7 +1041,7 @@ struct btrfs_fs_info { ...@@ -971,7 +1041,7 @@ struct btrfs_fs_info {
* is required instead of the faster short fsync log commits * is required instead of the faster short fsync log commits
*/ */
u64 last_trans_log_full_commit; u64 last_trans_log_full_commit;
unsigned long mount_opt:20; unsigned long mount_opt:21;
unsigned long compress_type:4; unsigned long compress_type:4;
u64 max_inline; u64 max_inline;
u64 alloc_start; u64 alloc_start;
...@@ -1132,12 +1202,23 @@ struct btrfs_fs_info { ...@@ -1132,12 +1202,23 @@ struct btrfs_fs_info {
spinlock_t ref_cache_lock; spinlock_t ref_cache_lock;
u64 total_ref_cache_size; u64 total_ref_cache_size;
/*
* these three are in extended format (availability of single
* chunks is denoted by BTRFS_AVAIL_ALLOC_BIT_SINGLE bit, other
* types are denoted by corresponding BTRFS_BLOCK_GROUP_* bits)
*/
u64 avail_data_alloc_bits; u64 avail_data_alloc_bits;
u64 avail_metadata_alloc_bits; u64 avail_metadata_alloc_bits;
u64 avail_system_alloc_bits; u64 avail_system_alloc_bits;
u64 data_alloc_profile;
u64 metadata_alloc_profile; /* restriper state */
u64 system_alloc_profile; spinlock_t balance_lock;
struct mutex balance_mutex;
atomic_t balance_running;
atomic_t balance_pause_req;
atomic_t balance_cancel_req;
struct btrfs_balance_control *balance_ctl;
wait_queue_head_t balance_wait_q;
unsigned data_chunk_allocations; unsigned data_chunk_allocations;
unsigned metadata_ratio; unsigned metadata_ratio;
...@@ -1155,6 +1236,10 @@ struct btrfs_fs_info { ...@@ -1155,6 +1236,10 @@ struct btrfs_fs_info {
int scrub_workers_refcnt; int scrub_workers_refcnt;
struct btrfs_workers scrub_workers; struct btrfs_workers scrub_workers;
#ifdef CONFIG_BTRFS_FS_CHECK_INTEGRITY
u32 check_integrity_print_mask;
#endif
/* filesystem state */ /* filesystem state */
u64 fs_state; u64 fs_state;
...@@ -1383,6 +1468,8 @@ struct btrfs_ioctl_defrag_range_args { ...@@ -1383,6 +1468,8 @@ struct btrfs_ioctl_defrag_range_args {
#define BTRFS_DEV_ITEM_KEY 216 #define BTRFS_DEV_ITEM_KEY 216
#define BTRFS_CHUNK_ITEM_KEY 228 #define BTRFS_CHUNK_ITEM_KEY 228
#define BTRFS_BALANCE_ITEM_KEY 248
/* /*
* string items are for debugging. They just store a short string of * string items are for debugging. They just store a short string of
* data in the FS * data in the FS
...@@ -1413,6 +1500,9 @@ struct btrfs_ioctl_defrag_range_args { ...@@ -1413,6 +1500,9 @@ struct btrfs_ioctl_defrag_range_args {
#define BTRFS_MOUNT_AUTO_DEFRAG (1 << 16) #define BTRFS_MOUNT_AUTO_DEFRAG (1 << 16)
#define BTRFS_MOUNT_INODE_MAP_CACHE (1 << 17) #define BTRFS_MOUNT_INODE_MAP_CACHE (1 << 17)
#define BTRFS_MOUNT_RECOVERY (1 << 18) #define BTRFS_MOUNT_RECOVERY (1 << 18)
#define BTRFS_MOUNT_SKIP_BALANCE (1 << 19)
#define BTRFS_MOUNT_CHECK_INTEGRITY (1 << 20)
#define BTRFS_MOUNT_CHECK_INTEGRITY_INCLUDING_EXTENT_DATA (1 << 21)
#define btrfs_clear_opt(o, opt) ((o) &= ~BTRFS_MOUNT_##opt) #define btrfs_clear_opt(o, opt) ((o) &= ~BTRFS_MOUNT_##opt)
#define btrfs_set_opt(o, opt) ((o) |= BTRFS_MOUNT_##opt) #define btrfs_set_opt(o, opt) ((o) |= BTRFS_MOUNT_##opt)
...@@ -2077,8 +2167,86 @@ BTRFS_SETGET_STACK_FUNCS(backup_bytes_used, struct btrfs_root_backup, ...@@ -2077,8 +2167,86 @@ BTRFS_SETGET_STACK_FUNCS(backup_bytes_used, struct btrfs_root_backup,
BTRFS_SETGET_STACK_FUNCS(backup_num_devices, struct btrfs_root_backup, BTRFS_SETGET_STACK_FUNCS(backup_num_devices, struct btrfs_root_backup,
num_devices, 64); num_devices, 64);
/* struct btrfs_super_block */ /* struct btrfs_balance_item */
BTRFS_SETGET_FUNCS(balance_flags, struct btrfs_balance_item, flags, 64);
static inline void btrfs_balance_data(struct extent_buffer *eb,
struct btrfs_balance_item *bi,
struct btrfs_disk_balance_args *ba)
{
read_eb_member(eb, bi, struct btrfs_balance_item, data, ba);
}
static inline void btrfs_set_balance_data(struct extent_buffer *eb,
struct btrfs_balance_item *bi,
struct btrfs_disk_balance_args *ba)
{
write_eb_member(eb, bi, struct btrfs_balance_item, data, ba);
}
static inline void btrfs_balance_meta(struct extent_buffer *eb,
struct btrfs_balance_item *bi,
struct btrfs_disk_balance_args *ba)
{
read_eb_member(eb, bi, struct btrfs_balance_item, meta, ba);
}
static inline void btrfs_set_balance_meta(struct extent_buffer *eb,
struct btrfs_balance_item *bi,
struct btrfs_disk_balance_args *ba)
{
write_eb_member(eb, bi, struct btrfs_balance_item, meta, ba);
}
static inline void btrfs_balance_sys(struct extent_buffer *eb,
struct btrfs_balance_item *bi,
struct btrfs_disk_balance_args *ba)
{
read_eb_member(eb, bi, struct btrfs_balance_item, sys, ba);
}
static inline void btrfs_set_balance_sys(struct extent_buffer *eb,
struct btrfs_balance_item *bi,
struct btrfs_disk_balance_args *ba)
{
write_eb_member(eb, bi, struct btrfs_balance_item, sys, ba);
}
static inline void
btrfs_disk_balance_args_to_cpu(struct btrfs_balance_args *cpu,
struct btrfs_disk_balance_args *disk)
{
memset(cpu, 0, sizeof(*cpu));
cpu->profiles = le64_to_cpu(disk->profiles);
cpu->usage = le64_to_cpu(disk->usage);
cpu->devid = le64_to_cpu(disk->devid);
cpu->pstart = le64_to_cpu(disk->pstart);
cpu->pend = le64_to_cpu(disk->pend);
cpu->vstart = le64_to_cpu(disk->vstart);
cpu->vend = le64_to_cpu(disk->vend);
cpu->target = le64_to_cpu(disk->target);
cpu->flags = le64_to_cpu(disk->flags);
}
static inline void
btrfs_cpu_balance_args_to_disk(struct btrfs_disk_balance_args *disk,
struct btrfs_balance_args *cpu)
{
memset(disk, 0, sizeof(*disk));
disk->profiles = cpu_to_le64(cpu->profiles);
disk->usage = cpu_to_le64(cpu->usage);
disk->devid = cpu_to_le64(cpu->devid);
disk->pstart = cpu_to_le64(cpu->pstart);
disk->pend = cpu_to_le64(cpu->pend);
disk->vstart = cpu_to_le64(cpu->vstart);
disk->vend = cpu_to_le64(cpu->vend);
disk->target = cpu_to_le64(cpu->target);
disk->flags = cpu_to_le64(cpu->flags);
}
/* struct btrfs_super_block */
BTRFS_SETGET_STACK_FUNCS(super_bytenr, struct btrfs_super_block, bytenr, 64); BTRFS_SETGET_STACK_FUNCS(super_bytenr, struct btrfs_super_block, bytenr, 64);
BTRFS_SETGET_STACK_FUNCS(super_flags, struct btrfs_super_block, flags, 64); BTRFS_SETGET_STACK_FUNCS(super_flags, struct btrfs_super_block, flags, 64);
BTRFS_SETGET_STACK_FUNCS(super_generation, struct btrfs_super_block, BTRFS_SETGET_STACK_FUNCS(super_generation, struct btrfs_super_block,
...@@ -2277,11 +2445,11 @@ struct extent_buffer *btrfs_alloc_free_block(struct btrfs_trans_handle *trans, ...@@ -2277,11 +2445,11 @@ struct extent_buffer *btrfs_alloc_free_block(struct btrfs_trans_handle *trans,
struct btrfs_root *root, u32 blocksize, struct btrfs_root *root, u32 blocksize,
u64 parent, u64 root_objectid, u64 parent, u64 root_objectid,
struct btrfs_disk_key *key, int level, struct btrfs_disk_key *key, int level,
u64 hint, u64 empty_size); u64 hint, u64 empty_size, int for_cow);
void btrfs_free_tree_block(struct btrfs_trans_handle *trans, void btrfs_free_tree_block(struct btrfs_trans_handle *trans,
struct btrfs_root *root, struct btrfs_root *root,
struct extent_buffer *buf, struct extent_buffer *buf,
u64 parent, int last_ref); u64 parent, int last_ref, int for_cow);
struct extent_buffer *btrfs_init_new_buffer(struct btrfs_trans_handle *trans, struct extent_buffer *btrfs_init_new_buffer(struct btrfs_trans_handle *trans,
struct btrfs_root *root, struct btrfs_root *root,
u64 bytenr, u32 blocksize, u64 bytenr, u32 blocksize,
...@@ -2301,17 +2469,17 @@ int btrfs_reserve_extent(struct btrfs_trans_handle *trans, ...@@ -2301,17 +2469,17 @@ int btrfs_reserve_extent(struct btrfs_trans_handle *trans,
u64 search_end, struct btrfs_key *ins, u64 search_end, struct btrfs_key *ins,
u64 data); u64 data);
int btrfs_inc_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root, int btrfs_inc_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root,
struct extent_buffer *buf, int full_backref); struct extent_buffer *buf, int full_backref, int for_cow);
int btrfs_dec_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root, int btrfs_dec_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root,
struct extent_buffer *buf, int full_backref); struct extent_buffer *buf, int full_backref, int for_cow);
int btrfs_set_disk_extent_flags(struct btrfs_trans_handle *trans, int btrfs_set_disk_extent_flags(struct btrfs_trans_handle *trans,
struct btrfs_root *root, struct btrfs_root *root,
u64 bytenr, u64 num_bytes, u64 flags, u64 bytenr, u64 num_bytes, u64 flags,
int is_data); int is_data);
int btrfs_free_extent(struct btrfs_trans_handle *trans, int btrfs_free_extent(struct btrfs_trans_handle *trans,
struct btrfs_root *root, struct btrfs_root *root,
u64 bytenr, u64 num_bytes, u64 parent, u64 bytenr, u64 num_bytes, u64 parent, u64 root_objectid,
u64 root_objectid, u64 owner, u64 offset); u64 owner, u64 offset, int for_cow);
int btrfs_free_reserved_extent(struct btrfs_root *root, u64 start, u64 len); int btrfs_free_reserved_extent(struct btrfs_root *root, u64 start, u64 len);
int btrfs_free_and_pin_reserved_extent(struct btrfs_root *root, int btrfs_free_and_pin_reserved_extent(struct btrfs_root *root,
...@@ -2323,7 +2491,7 @@ int btrfs_finish_extent_commit(struct btrfs_trans_handle *trans, ...@@ -2323,7 +2491,7 @@ int btrfs_finish_extent_commit(struct btrfs_trans_handle *trans,
int btrfs_inc_extent_ref(struct btrfs_trans_handle *trans, int btrfs_inc_extent_ref(struct btrfs_trans_handle *trans,
struct btrfs_root *root, struct btrfs_root *root,
u64 bytenr, u64 num_bytes, u64 parent, u64 bytenr, u64 num_bytes, u64 parent,
u64 root_objectid, u64 owner, u64 offset); u64 root_objectid, u64 owner, u64 offset, int for_cow);
int btrfs_write_dirty_block_groups(struct btrfs_trans_handle *trans, int btrfs_write_dirty_block_groups(struct btrfs_trans_handle *trans,
struct btrfs_root *root); struct btrfs_root *root);
...@@ -2482,10 +2650,18 @@ static inline int btrfs_insert_empty_item(struct btrfs_trans_handle *trans, ...@@ -2482,10 +2650,18 @@ 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_leaf(struct btrfs_root *root, struct btrfs_path *path);
static inline int btrfs_next_item(struct btrfs_root *root, struct btrfs_path *p)
{
++p->slots[0];
if (p->slots[0] >= btrfs_header_nritems(p->nodes[0]))
return btrfs_next_leaf(root, p);
return 0;
}
int btrfs_prev_leaf(struct btrfs_root *root, struct btrfs_path *path); int btrfs_prev_leaf(struct btrfs_root *root, struct btrfs_path *path);
int btrfs_leaf_free_space(struct btrfs_root *root, struct extent_buffer *leaf); int btrfs_leaf_free_space(struct btrfs_root *root, struct extent_buffer *leaf);
void btrfs_drop_snapshot(struct btrfs_root *root, void btrfs_drop_snapshot(struct btrfs_root *root,
struct btrfs_block_rsv *block_rsv, int update_ref); struct btrfs_block_rsv *block_rsv, int update_ref,
int for_reloc);
int btrfs_drop_subtree(struct btrfs_trans_handle *trans, int btrfs_drop_subtree(struct btrfs_trans_handle *trans,
struct btrfs_root *root, struct btrfs_root *root,
struct extent_buffer *node, struct extent_buffer *node,
...@@ -2500,6 +2676,7 @@ static inline int btrfs_fs_closing(struct btrfs_fs_info *fs_info) ...@@ -2500,6 +2676,7 @@ static inline int btrfs_fs_closing(struct btrfs_fs_info *fs_info)
} }
static inline void free_fs_info(struct btrfs_fs_info *fs_info) static inline void free_fs_info(struct btrfs_fs_info *fs_info)
{ {
kfree(fs_info->balance_ctl);
kfree(fs_info->delayed_root); kfree(fs_info->delayed_root);
kfree(fs_info->extent_root); kfree(fs_info->extent_root);
kfree(fs_info->tree_root); kfree(fs_info->tree_root);
...@@ -2510,6 +2687,24 @@ static inline void free_fs_info(struct btrfs_fs_info *fs_info) ...@@ -2510,6 +2687,24 @@ static inline void free_fs_info(struct btrfs_fs_info *fs_info)
kfree(fs_info->super_for_commit); kfree(fs_info->super_for_commit);
kfree(fs_info); kfree(fs_info);
} }
/**
* profile_is_valid - tests whether a given profile is valid and reduced
* @flags: profile to validate
* @extended: if true @flags is treated as an extended profile
*/
static inline int profile_is_valid(u64 flags, int extended)
{
u64 mask = ~BTRFS_BLOCK_GROUP_PROFILE_MASK;
flags &= ~BTRFS_BLOCK_GROUP_TYPE_MASK;
if (extended)
mask &= ~BTRFS_AVAIL_ALLOC_BIT_SINGLE;
if (flags & mask)
return 0;
/* true if zero or exactly one bit set */
return (flags & (~flags + 1)) == flags;
}
/* root-item.c */ /* root-item.c */
int btrfs_find_root_ref(struct btrfs_root *tree_root, int btrfs_find_root_ref(struct btrfs_root *tree_root,
......
...@@ -595,8 +595,12 @@ static int btrfs_delayed_item_reserve_metadata(struct btrfs_trans_handle *trans, ...@@ -595,8 +595,12 @@ static int btrfs_delayed_item_reserve_metadata(struct btrfs_trans_handle *trans,
num_bytes = btrfs_calc_trans_metadata_size(root, 1); num_bytes = btrfs_calc_trans_metadata_size(root, 1);
ret = btrfs_block_rsv_migrate(src_rsv, dst_rsv, num_bytes); ret = btrfs_block_rsv_migrate(src_rsv, dst_rsv, num_bytes);
if (!ret) if (!ret) {
trace_btrfs_space_reservation(root->fs_info, "delayed_item",
item->key.objectid,
num_bytes, 1);
item->bytes_reserved = num_bytes; item->bytes_reserved = num_bytes;
}
return ret; return ret;
} }
...@@ -610,6 +614,9 @@ static void btrfs_delayed_item_release_metadata(struct btrfs_root *root, ...@@ -610,6 +614,9 @@ static void btrfs_delayed_item_release_metadata(struct btrfs_root *root,
return; return;
rsv = &root->fs_info->delayed_block_rsv; rsv = &root->fs_info->delayed_block_rsv;
trace_btrfs_space_reservation(root->fs_info, "delayed_item",
item->key.objectid, item->bytes_reserved,
0);
btrfs_block_rsv_release(root, rsv, btrfs_block_rsv_release(root, rsv,
item->bytes_reserved); item->bytes_reserved);
} }
...@@ -624,7 +631,7 @@ static int btrfs_delayed_inode_reserve_metadata( ...@@ -624,7 +631,7 @@ static int btrfs_delayed_inode_reserve_metadata(
struct btrfs_block_rsv *dst_rsv; struct btrfs_block_rsv *dst_rsv;
u64 num_bytes; u64 num_bytes;
int ret; int ret;
int release = false; bool release = false;
src_rsv = trans->block_rsv; src_rsv = trans->block_rsv;
dst_rsv = &root->fs_info->delayed_block_rsv; dst_rsv = &root->fs_info->delayed_block_rsv;
...@@ -651,8 +658,13 @@ static int btrfs_delayed_inode_reserve_metadata( ...@@ -651,8 +658,13 @@ static int btrfs_delayed_inode_reserve_metadata(
*/ */
if (ret == -EAGAIN) if (ret == -EAGAIN)
ret = -ENOSPC; ret = -ENOSPC;
if (!ret) if (!ret) {
node->bytes_reserved = num_bytes; node->bytes_reserved = num_bytes;
trace_btrfs_space_reservation(root->fs_info,
"delayed_inode",
btrfs_ino(inode),
num_bytes, 1);
}
return ret; return ret;
} else if (src_rsv == &root->fs_info->delalloc_block_rsv) { } else if (src_rsv == &root->fs_info->delalloc_block_rsv) {
spin_lock(&BTRFS_I(inode)->lock); spin_lock(&BTRFS_I(inode)->lock);
...@@ -707,11 +719,17 @@ static int btrfs_delayed_inode_reserve_metadata( ...@@ -707,11 +719,17 @@ static int btrfs_delayed_inode_reserve_metadata(
* reservation here. I think it may be time for a documentation page on * reservation here. I think it may be time for a documentation page on
* how block rsvs. work. * how block rsvs. work.
*/ */
if (!ret) if (!ret) {
trace_btrfs_space_reservation(root->fs_info, "delayed_inode",
btrfs_ino(inode), num_bytes, 1);
node->bytes_reserved = num_bytes; node->bytes_reserved = num_bytes;
}
if (release) if (release) {
trace_btrfs_space_reservation(root->fs_info, "delalloc",
btrfs_ino(inode), num_bytes, 0);
btrfs_block_rsv_release(root, src_rsv, num_bytes); btrfs_block_rsv_release(root, src_rsv, num_bytes);
}
return ret; return ret;
} }
...@@ -725,6 +743,8 @@ static void btrfs_delayed_inode_release_metadata(struct btrfs_root *root, ...@@ -725,6 +743,8 @@ static void btrfs_delayed_inode_release_metadata(struct btrfs_root *root,
return; return;
rsv = &root->fs_info->delayed_block_rsv; rsv = &root->fs_info->delayed_block_rsv;
trace_btrfs_space_reservation(root->fs_info, "delayed_inode",
node->inode_id, node->bytes_reserved, 0);
btrfs_block_rsv_release(root, rsv, btrfs_block_rsv_release(root, rsv,
node->bytes_reserved); node->bytes_reserved);
node->bytes_reserved = 0; node->bytes_reserved = 0;
...@@ -1372,13 +1392,6 @@ int btrfs_insert_delayed_dir_index(struct btrfs_trans_handle *trans, ...@@ -1372,13 +1392,6 @@ int btrfs_insert_delayed_dir_index(struct btrfs_trans_handle *trans,
goto release_node; goto release_node;
} }
ret = btrfs_delayed_item_reserve_metadata(trans, root, delayed_item);
/*
* we have reserved enough space when we start a new transaction,
* so reserving metadata failure is impossible
*/
BUG_ON(ret);
delayed_item->key.objectid = btrfs_ino(dir); delayed_item->key.objectid = btrfs_ino(dir);
btrfs_set_key_type(&delayed_item->key, BTRFS_DIR_INDEX_KEY); btrfs_set_key_type(&delayed_item->key, BTRFS_DIR_INDEX_KEY);
delayed_item->key.offset = index; delayed_item->key.offset = index;
...@@ -1391,6 +1404,14 @@ int btrfs_insert_delayed_dir_index(struct btrfs_trans_handle *trans, ...@@ -1391,6 +1404,14 @@ int btrfs_insert_delayed_dir_index(struct btrfs_trans_handle *trans,
dir_item->type = type; dir_item->type = 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);
/*
* we have reserved enough space when we start a new transaction,
* so reserving metadata failure is impossible
*/
BUG_ON(ret);
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)) {
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
...@@ -129,6 +129,7 @@ struct extent_buffer { ...@@ -129,6 +129,7 @@ struct extent_buffer {
struct list_head leak_list; struct list_head leak_list;
struct rcu_head rcu_head; struct rcu_head rcu_head;
atomic_t refs; atomic_t refs;
pid_t lock_owner;
/* count of read lock holders on the extent buffer */ /* count of read lock holders on the extent buffer */
atomic_t write_locks; atomic_t write_locks;
...@@ -137,6 +138,7 @@ struct extent_buffer { ...@@ -137,6 +138,7 @@ struct extent_buffer {
atomic_t blocking_readers; atomic_t blocking_readers;
atomic_t spinning_readers; atomic_t spinning_readers;
atomic_t spinning_writers; atomic_t spinning_writers;
int lock_nested;
/* protects write locks */ /* protects write locks */
rwlock_t lock; rwlock_t lock;
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册