Merge branch 'for-4.14' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux

Pull btrfs updates from David Sterba:
 "The changes range through all types: cleanups, core chagnes, sanity
  checks, fixes, other user visible changes, detailed list below:

   - deprecated: user transaction ioctl

   - mount option ssd does not change allocation alignments

   - degraded read-write mount is allowed if all the raid profile
     constraints are met, now based on more accurate check

   - defrag: do not reset compression afterwards; the NOCOMPRESS flag
     can be now overriden by defrag

   - prep work for better extent reference tracking (related to the
     qgroup slowness with balance)

   - prep work for compression heuristics

   - memory allocation reductions (may help latencies on a loaded
     system)

   - better accounting for io waiting states

   - error handling improvements (removed BUGs)

   - added more sanity checks for shared refs

   - fix readdir vs pagefault deadlock under some circumstances

   - fix for 'no-hole' mode, certain combination of compressed and
     inline extents

   - send: fix emission of invalid clone operations

   - fixup file mode if setting acls fail

   - more fixes from fuzzing

   - oher cleanups"

* 'for-4.14' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux: (104 commits)
  btrfs: submit superblock io with REQ_META and REQ_PRIO
  btrfs: remove unnecessary memory barrier in btrfs_direct_IO
  btrfs: remove superfluous chunk_tree argument from btrfs_alloc_dev_extent
  btrfs: Remove chunk_objectid parameter of btrfs_alloc_dev_extent
  btrfs: pass fs_info to btrfs_del_root instead of tree_root
  Btrfs: add one more sanity check for shared ref type
  Btrfs: remove BUG_ON in __add_tree_block
  Btrfs: remove BUG() in add_data_reference
  Btrfs: remove BUG() in print_extent_item
  Btrfs: remove BUG() in btrfs_extent_inline_ref_size
  Btrfs: convert to use btrfs_get_extent_inline_ref_type
  Btrfs: add a helper to retrive extent inline ref type
  btrfs: scrub: simplify scrub worker initialization
  btrfs: scrub: clean up division in scrub_find_csum
  btrfs: scrub: clean up division in __scrub_mark_bitmap
  btrfs: scrub: use bool for flush_all_writes
  btrfs: preserve i_mode if __btrfs_set_acl() fails
  btrfs: Remove extraneous chunk_objectid variable
  btrfs: Remove chunk_objectid argument from btrfs_make_block_group
  btrfs: Remove extra parentheses from condition in copy_items()
  ...
This commit is contained in:
Linus Torvalds 2017-09-09 13:27:51 -07:00
commit 66ba772ee3
40 changed files with 1706 additions and 1544 deletions

View File

@ -114,13 +114,17 @@ out:
int btrfs_set_acl(struct inode *inode, struct posix_acl *acl, int type) int btrfs_set_acl(struct inode *inode, struct posix_acl *acl, int type)
{ {
int ret; int ret;
umode_t old_mode = inode->i_mode;
if (type == ACL_TYPE_ACCESS && acl) { if (type == ACL_TYPE_ACCESS && acl) {
ret = posix_acl_update_mode(inode, &inode->i_mode, &acl); ret = posix_acl_update_mode(inode, &inode->i_mode, &acl);
if (ret) if (ret)
return ret; return ret;
} }
return __btrfs_set_acl(NULL, inode, acl, type); ret = __btrfs_set_acl(NULL, inode, acl, type);
if (ret)
inode->i_mode = old_mode;
return ret;
} }
/* /*

View File

@ -75,18 +75,18 @@ void btrfs_##name(struct work_struct *arg) \
} }
struct btrfs_fs_info * struct btrfs_fs_info *
btrfs_workqueue_owner(struct __btrfs_workqueue *wq) btrfs_workqueue_owner(const struct __btrfs_workqueue *wq)
{ {
return wq->fs_info; return wq->fs_info;
} }
struct btrfs_fs_info * struct btrfs_fs_info *
btrfs_work_owner(struct btrfs_work *work) btrfs_work_owner(const struct btrfs_work *work)
{ {
return work->wq->fs_info; return work->wq->fs_info;
} }
bool btrfs_workqueue_normal_congested(struct btrfs_workqueue *wq) bool btrfs_workqueue_normal_congested(const struct btrfs_workqueue *wq)
{ {
/* /*
* We could compare wq->normal->pending with num_online_cpus() * We could compare wq->normal->pending with num_online_cpus()

View File

@ -82,7 +82,7 @@ void btrfs_queue_work(struct btrfs_workqueue *wq,
void btrfs_destroy_workqueue(struct btrfs_workqueue *wq); void btrfs_destroy_workqueue(struct btrfs_workqueue *wq);
void btrfs_workqueue_set_max(struct btrfs_workqueue *wq, int max); void btrfs_workqueue_set_max(struct btrfs_workqueue *wq, int max);
void btrfs_set_work_high_priority(struct btrfs_work *work); void btrfs_set_work_high_priority(struct btrfs_work *work);
struct btrfs_fs_info *btrfs_work_owner(struct btrfs_work *work); struct btrfs_fs_info *btrfs_work_owner(const struct btrfs_work *work);
struct btrfs_fs_info *btrfs_workqueue_owner(struct __btrfs_workqueue *wq); struct btrfs_fs_info *btrfs_workqueue_owner(const struct __btrfs_workqueue *wq);
bool btrfs_workqueue_normal_congested(struct btrfs_workqueue *wq); bool btrfs_workqueue_normal_congested(const struct btrfs_workqueue *wq);
#endif #endif

File diff suppressed because it is too large Load Diff

View File

@ -68,10 +68,20 @@ int btrfs_find_one_extref(struct btrfs_root *root, u64 inode_objectid,
u64 start_off, struct btrfs_path *path, u64 start_off, struct btrfs_path *path,
struct btrfs_inode_extref **ret_extref, struct btrfs_inode_extref **ret_extref,
u64 *found_off); u64 *found_off);
int btrfs_check_shared(struct btrfs_trans_handle *trans, int btrfs_check_shared(struct btrfs_root *root, u64 inum, u64 bytenr);
struct btrfs_fs_info *fs_info, u64 root_objectid,
u64 inum, u64 bytenr);
int __init btrfs_prelim_ref_init(void); int __init btrfs_prelim_ref_init(void);
void btrfs_prelim_ref_exit(void); void btrfs_prelim_ref_exit(void);
struct prelim_ref {
struct rb_node rbnode;
u64 root_id;
struct btrfs_key key_for_search;
int level;
int count;
struct extent_inode_elem *inode_list;
u64 parent;
u64 wanted_disk_byte;
};
#endif #endif

View File

@ -179,9 +179,14 @@ struct btrfs_inode {
unsigned reserved_extents; unsigned reserved_extents;
/* /*
* always compress this one file * Cached values of inode properties
*/ */
unsigned force_compress; unsigned prop_compress; /* per-file compression algorithm */
/*
* Force compression on the file using the defrag ioctl, could be
* different from prop_compress and takes precedence if set
*/
unsigned defrag_compress;
struct btrfs_delayed_node *delayed_node; struct btrfs_delayed_node *delayed_node;
@ -207,7 +212,7 @@ struct btrfs_inode {
extern unsigned char btrfs_filetype_table[]; extern unsigned char btrfs_filetype_table[];
static inline struct btrfs_inode *BTRFS_I(struct inode *inode) static inline struct btrfs_inode *BTRFS_I(const struct inode *inode)
{ {
return container_of(inode, struct btrfs_inode, vfs_inode); return container_of(inode, struct btrfs_inode, vfs_inode);
} }
@ -231,7 +236,7 @@ static inline void btrfs_insert_inode_hash(struct inode *inode)
__insert_inode_hash(inode, h); __insert_inode_hash(inode, h);
} }
static inline u64 btrfs_ino(struct btrfs_inode *inode) static inline u64 btrfs_ino(const struct btrfs_inode *inode)
{ {
u64 ino = inode->location.objectid; u64 ino = inode->location.objectid;

View File

@ -791,12 +791,12 @@ static int btrfsic_process_superblock_dev_mirror(
dev_bytenr = btrfs_sb_offset(superblock_mirror_num); dev_bytenr = btrfs_sb_offset(superblock_mirror_num);
if (dev_bytenr + BTRFS_SUPER_INFO_SIZE > device->commit_total_bytes) if (dev_bytenr + BTRFS_SUPER_INFO_SIZE > device->commit_total_bytes)
return -1; return -1;
bh = __bread(superblock_bdev, dev_bytenr / 4096, bh = __bread(superblock_bdev, dev_bytenr / BTRFS_BDEV_BLOCKSIZE,
BTRFS_SUPER_INFO_SIZE); BTRFS_SUPER_INFO_SIZE);
if (NULL == bh) if (NULL == bh)
return -1; return -1;
super_tmp = (struct btrfs_super_block *) super_tmp = (struct btrfs_super_block *)
(bh->b_data + (dev_bytenr & 4095)); (bh->b_data + (dev_bytenr & (BTRFS_BDEV_BLOCKSIZE - 1)));
if (btrfs_super_bytenr(super_tmp) != dev_bytenr || if (btrfs_super_bytenr(super_tmp) != dev_bytenr ||
btrfs_super_magic(super_tmp) != BTRFS_MAGIC || btrfs_super_magic(super_tmp) != BTRFS_MAGIC ||
@ -1728,7 +1728,7 @@ static int btrfsic_test_for_metadata(struct btrfsic_state *state,
num_pages = state->metablock_size >> PAGE_SHIFT; num_pages = state->metablock_size >> PAGE_SHIFT;
h = (struct btrfs_header *)datav[0]; h = (struct btrfs_header *)datav[0];
if (memcmp(h->fsid, fs_info->fsid, BTRFS_UUID_SIZE)) if (memcmp(h->fsid, fs_info->fsid, BTRFS_FSID_SIZE))
return 1; return 1;
for (i = 0; i < num_pages; i++) { for (i = 0; i < num_pages; i++) {
@ -2753,7 +2753,7 @@ int btrfsic_submit_bh(int op, int op_flags, struct buffer_head *bh)
(op == REQ_OP_WRITE) && bh->b_size > 0) { (op == REQ_OP_WRITE) && bh->b_size > 0) {
u64 dev_bytenr; u64 dev_bytenr;
dev_bytenr = 4096 * bh->b_blocknr; dev_bytenr = BTRFS_BDEV_BLOCKSIZE * bh->b_blocknr;
if (dev_state->state->print_mask & if (dev_state->state->print_mask &
BTRFSIC_PRINT_MASK_SUBMIT_BIO_BH) BTRFSIC_PRINT_MASK_SUBMIT_BIO_BH)
pr_info("submit_bh(op=0x%x,0x%x, blocknr=%llu (bytenr %llu), size=%zu, data=%p, bdev=%p)\n", pr_info("submit_bh(op=0x%x,0x%x, blocknr=%llu (bytenr %llu), size=%zu, data=%p, bdev=%p)\n",

View File

@ -825,7 +825,7 @@ static void free_workspace(int type, struct list_head *workspace)
int *free_ws = &btrfs_comp_ws[idx].free_ws; int *free_ws = &btrfs_comp_ws[idx].free_ws;
spin_lock(ws_lock); spin_lock(ws_lock);
if (*free_ws < num_online_cpus()) { if (*free_ws <= num_online_cpus()) {
list_add(workspace, idle_ws); list_add(workspace, idle_ws);
(*free_ws)++; (*free_ws)++;
spin_unlock(ws_lock); spin_unlock(ws_lock);
@ -1047,3 +1047,36 @@ int btrfs_decompress_buf2page(const char *buf, unsigned long buf_start,
return 1; return 1;
} }
/*
* Compression heuristic.
*
* For now is's a naive and optimistic 'return true', we'll extend the logic to
* quickly (compared to direct compression) detect data characteristics
* (compressible/uncompressible) to avoid wasting CPU time on uncompressible
* data.
*
* The following types of analysis can be performed:
* - detect mostly zero data
* - detect data with low "byte set" size (text, etc)
* - detect data with low/high "core byte" set
*
* Return non-zero if the compression should be done, 0 otherwise.
*/
int btrfs_compress_heuristic(struct inode *inode, u64 start, u64 end)
{
u64 index = start >> PAGE_SHIFT;
u64 end_index = end >> PAGE_SHIFT;
struct page *page;
int ret = 1;
while (index <= end_index) {
page = find_get_page(inode->i_mapping, index);
kmap(page);
kunmap(page);
put_page(page);
index++;
}
return ret;
}

View File

@ -100,7 +100,6 @@ enum btrfs_compression_type {
BTRFS_COMPRESS_ZLIB = 1, BTRFS_COMPRESS_ZLIB = 1,
BTRFS_COMPRESS_LZO = 2, BTRFS_COMPRESS_LZO = 2,
BTRFS_COMPRESS_TYPES = 2, BTRFS_COMPRESS_TYPES = 2,
BTRFS_COMPRESS_LAST = 3,
}; };
struct btrfs_compress_op { struct btrfs_compress_op {
@ -129,4 +128,6 @@ struct btrfs_compress_op {
extern const struct btrfs_compress_op btrfs_zlib_compress; extern const struct btrfs_compress_op btrfs_zlib_compress;
extern const struct btrfs_compress_op btrfs_lzo_compress; extern const struct btrfs_compress_op btrfs_lzo_compress;
int btrfs_compress_heuristic(struct inode *inode, u64 start, u64 end);
#endif #endif

View File

@ -4650,7 +4650,7 @@ void btrfs_truncate_item(struct btrfs_fs_info *fs_info,
btrfs_mark_buffer_dirty(leaf); btrfs_mark_buffer_dirty(leaf);
if (btrfs_leaf_free_space(fs_info, leaf) < 0) { if (btrfs_leaf_free_space(fs_info, leaf) < 0) {
btrfs_print_leaf(fs_info, leaf); btrfs_print_leaf(leaf);
BUG(); BUG();
} }
} }
@ -4679,7 +4679,7 @@ void btrfs_extend_item(struct btrfs_fs_info *fs_info, struct btrfs_path *path,
data_end = leaf_data_end(fs_info, leaf); data_end = leaf_data_end(fs_info, leaf);
if (btrfs_leaf_free_space(fs_info, leaf) < data_size) { if (btrfs_leaf_free_space(fs_info, leaf) < data_size) {
btrfs_print_leaf(fs_info, leaf); btrfs_print_leaf(leaf);
BUG(); BUG();
} }
slot = path->slots[0]; slot = path->slots[0];
@ -4687,7 +4687,7 @@ void btrfs_extend_item(struct btrfs_fs_info *fs_info, struct btrfs_path *path,
BUG_ON(slot < 0); BUG_ON(slot < 0);
if (slot >= nritems) { if (slot >= nritems) {
btrfs_print_leaf(fs_info, leaf); btrfs_print_leaf(leaf);
btrfs_crit(fs_info, "slot %d too large, nritems %d", btrfs_crit(fs_info, "slot %d too large, nritems %d",
slot, nritems); slot, nritems);
BUG_ON(1); BUG_ON(1);
@ -4718,7 +4718,7 @@ void btrfs_extend_item(struct btrfs_fs_info *fs_info, struct btrfs_path *path,
btrfs_mark_buffer_dirty(leaf); btrfs_mark_buffer_dirty(leaf);
if (btrfs_leaf_free_space(fs_info, leaf) < 0) { if (btrfs_leaf_free_space(fs_info, leaf) < 0) {
btrfs_print_leaf(fs_info, leaf); btrfs_print_leaf(leaf);
BUG(); BUG();
} }
} }
@ -4757,7 +4757,7 @@ void setup_items_for_insert(struct btrfs_root *root, struct btrfs_path *path,
data_end = leaf_data_end(fs_info, leaf); data_end = leaf_data_end(fs_info, leaf);
if (btrfs_leaf_free_space(fs_info, leaf) < total_size) { if (btrfs_leaf_free_space(fs_info, leaf) < total_size) {
btrfs_print_leaf(fs_info, leaf); btrfs_print_leaf(leaf);
btrfs_crit(fs_info, "not enough freespace need %u have %d", btrfs_crit(fs_info, "not enough freespace need %u have %d",
total_size, btrfs_leaf_free_space(fs_info, leaf)); total_size, btrfs_leaf_free_space(fs_info, leaf));
BUG(); BUG();
@ -4767,7 +4767,7 @@ void setup_items_for_insert(struct btrfs_root *root, struct btrfs_path *path,
unsigned int old_data = btrfs_item_end_nr(leaf, slot); unsigned int old_data = btrfs_item_end_nr(leaf, slot);
if (old_data < data_end) { if (old_data < data_end) {
btrfs_print_leaf(fs_info, leaf); btrfs_print_leaf(leaf);
btrfs_crit(fs_info, "slot %d old_data %d data_end %d", btrfs_crit(fs_info, "slot %d old_data %d data_end %d",
slot, old_data, data_end); slot, old_data, data_end);
BUG_ON(1); BUG_ON(1);
@ -4811,7 +4811,7 @@ void setup_items_for_insert(struct btrfs_root *root, struct btrfs_path *path,
btrfs_mark_buffer_dirty(leaf); btrfs_mark_buffer_dirty(leaf);
if (btrfs_leaf_free_space(fs_info, leaf) < 0) { if (btrfs_leaf_free_space(fs_info, leaf) < 0) {
btrfs_print_leaf(fs_info, leaf); btrfs_print_leaf(leaf);
BUG(); BUG();
} }
} }

View File

@ -470,8 +470,8 @@ struct btrfs_block_rsv {
/* /*
* free clusters are used to claim free space in relatively large chunks, * free clusters are used to claim free space in relatively large chunks,
* allowing us to do less seeky writes. They are used for all metadata * allowing us to do less seeky writes. They are used for all metadata
* allocations and data allocations in ssd mode. * allocations. In ssd_spread mode they are also used for data allocations.
*/ */
struct btrfs_free_cluster { struct btrfs_free_cluster {
spinlock_t lock; spinlock_t lock;
@ -558,7 +558,6 @@ struct btrfs_block_group_cache {
u64 bytes_super; u64 bytes_super;
u64 flags; u64 flags;
u64 cache_generation; u64 cache_generation;
u32 sectorsize;
/* /*
* If the free space extent count exceeds this number, convert the block * If the free space extent count exceeds this number, convert the block
@ -968,7 +967,7 @@ struct btrfs_fs_info {
struct reloc_control *reloc_ctl; struct reloc_control *reloc_ctl;
/* data_alloc_cluster is only used in ssd mode */ /* data_alloc_cluster is only used in ssd_spread mode */
struct btrfs_free_cluster data_alloc_cluster; struct btrfs_free_cluster data_alloc_cluster;
/* all metadata allocations go through this cluster */ /* all metadata allocations go through this cluster */
@ -1072,8 +1071,6 @@ struct btrfs_fs_info {
/* next backup root to be overwritten */ /* next backup root to be overwritten */
int backup_root_index; int backup_root_index;
int num_tolerated_disk_barrier_failures;
/* device replace state */ /* device replace state */
struct btrfs_dev_replace dev_replace; struct btrfs_dev_replace dev_replace;
@ -1261,12 +1258,17 @@ struct btrfs_root {
*/ */
int send_in_progress; int send_in_progress;
struct btrfs_subvolume_writers *subv_writers; struct btrfs_subvolume_writers *subv_writers;
atomic_t will_be_snapshoted; atomic_t will_be_snapshotted;
/* For qgroup metadata space reserve */ /* For qgroup metadata space reserve */
atomic64_t qgroup_meta_rsv; atomic64_t qgroup_meta_rsv;
}; };
struct btrfs_file_private {
struct btrfs_trans_handle *trans;
void *filldir_buf;
};
static inline u32 btrfs_inode_sectorsize(const struct inode *inode) static inline u32 btrfs_inode_sectorsize(const struct inode *inode)
{ {
return btrfs_sb(inode->i_sb)->sectorsize; return btrfs_sb(inode->i_sb)->sectorsize;
@ -1435,7 +1437,7 @@ do { \
#define BTRFS_INODE_ROOT_ITEM_INIT (1 << 31) #define BTRFS_INODE_ROOT_ITEM_INIT (1 << 31)
struct btrfs_map_token { struct btrfs_map_token {
struct extent_buffer *eb; const struct extent_buffer *eb;
char *kaddr; char *kaddr;
unsigned long offset; unsigned long offset;
}; };
@ -1469,18 +1471,19 @@ static inline void btrfs_init_map_token (struct btrfs_map_token *token)
sizeof(((type *)0)->member))) sizeof(((type *)0)->member)))
#define DECLARE_BTRFS_SETGET_BITS(bits) \ #define DECLARE_BTRFS_SETGET_BITS(bits) \
u##bits btrfs_get_token_##bits(struct extent_buffer *eb, void *ptr, \ u##bits btrfs_get_token_##bits(const struct extent_buffer *eb, \
unsigned long off, \ const void *ptr, unsigned long off, \
struct btrfs_map_token *token); \ struct btrfs_map_token *token); \
void btrfs_set_token_##bits(struct extent_buffer *eb, void *ptr, \ void btrfs_set_token_##bits(struct extent_buffer *eb, const void *ptr, \
unsigned long off, u##bits val, \ unsigned long off, u##bits val, \
struct btrfs_map_token *token); \ struct btrfs_map_token *token); \
static inline u##bits btrfs_get_##bits(struct extent_buffer *eb, void *ptr, \ static inline u##bits btrfs_get_##bits(const struct extent_buffer *eb, \
const void *ptr, \
unsigned long off) \ unsigned long off) \
{ \ { \
return btrfs_get_token_##bits(eb, ptr, off, NULL); \ return btrfs_get_token_##bits(eb, ptr, off, NULL); \
} \ } \
static inline void btrfs_set_##bits(struct extent_buffer *eb, void *ptr, \ static inline void btrfs_set_##bits(struct extent_buffer *eb, void *ptr,\
unsigned long off, u##bits val) \ unsigned long off, u##bits val) \
{ \ { \
btrfs_set_token_##bits(eb, ptr, off, val, NULL); \ btrfs_set_token_##bits(eb, ptr, off, val, NULL); \
@ -1492,7 +1495,8 @@ DECLARE_BTRFS_SETGET_BITS(32)
DECLARE_BTRFS_SETGET_BITS(64) DECLARE_BTRFS_SETGET_BITS(64)
#define BTRFS_SETGET_FUNCS(name, type, member, bits) \ #define BTRFS_SETGET_FUNCS(name, type, member, bits) \
static inline u##bits btrfs_##name(struct extent_buffer *eb, type *s) \ static inline u##bits btrfs_##name(const struct extent_buffer *eb, \
const type *s) \
{ \ { \
BUILD_BUG_ON(sizeof(u##bits) != sizeof(((type *)0))->member); \ BUILD_BUG_ON(sizeof(u##bits) != sizeof(((type *)0))->member); \
return btrfs_get_##bits(eb, s, offsetof(type, member)); \ return btrfs_get_##bits(eb, s, offsetof(type, member)); \
@ -1503,7 +1507,8 @@ static inline void btrfs_set_##name(struct extent_buffer *eb, type *s, \
BUILD_BUG_ON(sizeof(u##bits) != sizeof(((type *)0))->member); \ BUILD_BUG_ON(sizeof(u##bits) != sizeof(((type *)0))->member); \
btrfs_set_##bits(eb, s, offsetof(type, member), val); \ btrfs_set_##bits(eb, s, offsetof(type, member), val); \
} \ } \
static inline u##bits btrfs_token_##name(struct extent_buffer *eb, type *s, \ static inline u##bits btrfs_token_##name(const struct extent_buffer *eb,\
const type *s, \
struct btrfs_map_token *token) \ struct btrfs_map_token *token) \
{ \ { \
BUILD_BUG_ON(sizeof(u##bits) != sizeof(((type *)0))->member); \ BUILD_BUG_ON(sizeof(u##bits) != sizeof(((type *)0))->member); \
@ -1518,9 +1523,9 @@ static inline void btrfs_set_token_##name(struct extent_buffer *eb, \
} }
#define BTRFS_SETGET_HEADER_FUNCS(name, type, member, bits) \ #define BTRFS_SETGET_HEADER_FUNCS(name, type, member, bits) \
static inline u##bits btrfs_##name(struct extent_buffer *eb) \ static inline u##bits btrfs_##name(const struct extent_buffer *eb) \
{ \ { \
type *p = page_address(eb->pages[0]); \ const type *p = page_address(eb->pages[0]); \
u##bits res = le##bits##_to_cpu(p->member); \ u##bits res = le##bits##_to_cpu(p->member); \
return res; \ return res; \
} \ } \
@ -1532,7 +1537,7 @@ static inline void btrfs_set_##name(struct extent_buffer *eb, \
} }
#define BTRFS_SETGET_STACK_FUNCS(name, type, member, bits) \ #define BTRFS_SETGET_STACK_FUNCS(name, type, member, bits) \
static inline u##bits btrfs_##name(type *s) \ static inline u##bits btrfs_##name(const type *s) \
{ \ { \
return le##bits##_to_cpu(s->member); \ return le##bits##_to_cpu(s->member); \
} \ } \
@ -1799,7 +1804,6 @@ static inline u32 btrfs_extent_inline_ref_size(int type)
if (type == BTRFS_EXTENT_DATA_REF_KEY) if (type == BTRFS_EXTENT_DATA_REF_KEY)
return sizeof(struct btrfs_extent_data_ref) + return sizeof(struct btrfs_extent_data_ref) +
offsetof(struct btrfs_extent_inline_ref, offset); offsetof(struct btrfs_extent_inline_ref, offset);
BUG();
return 0; return 0;
} }
@ -1857,7 +1861,7 @@ static inline unsigned long btrfs_node_key_ptr_offset(int nr)
sizeof(struct btrfs_key_ptr) * nr; sizeof(struct btrfs_key_ptr) * nr;
} }
void btrfs_node_key(struct extent_buffer *eb, void btrfs_node_key(const struct extent_buffer *eb,
struct btrfs_disk_key *disk_key, int nr); struct btrfs_disk_key *disk_key, int nr);
static inline void btrfs_set_node_key(struct extent_buffer *eb, static inline void btrfs_set_node_key(struct extent_buffer *eb,
@ -1886,28 +1890,28 @@ static inline struct btrfs_item *btrfs_item_nr(int nr)
return (struct btrfs_item *)btrfs_item_nr_offset(nr); return (struct btrfs_item *)btrfs_item_nr_offset(nr);
} }
static inline u32 btrfs_item_end(struct extent_buffer *eb, static inline u32 btrfs_item_end(const struct extent_buffer *eb,
struct btrfs_item *item) struct btrfs_item *item)
{ {
return btrfs_item_offset(eb, item) + btrfs_item_size(eb, item); return btrfs_item_offset(eb, item) + btrfs_item_size(eb, item);
} }
static inline u32 btrfs_item_end_nr(struct extent_buffer *eb, int nr) static inline u32 btrfs_item_end_nr(const struct extent_buffer *eb, int nr)
{ {
return btrfs_item_end(eb, btrfs_item_nr(nr)); return btrfs_item_end(eb, btrfs_item_nr(nr));
} }
static inline u32 btrfs_item_offset_nr(struct extent_buffer *eb, int nr) static inline u32 btrfs_item_offset_nr(const struct extent_buffer *eb, int nr)
{ {
return btrfs_item_offset(eb, btrfs_item_nr(nr)); return btrfs_item_offset(eb, btrfs_item_nr(nr));
} }
static inline u32 btrfs_item_size_nr(struct extent_buffer *eb, int nr) static inline u32 btrfs_item_size_nr(const struct extent_buffer *eb, int nr)
{ {
return btrfs_item_size(eb, btrfs_item_nr(nr)); return btrfs_item_size(eb, btrfs_item_nr(nr));
} }
static inline void btrfs_item_key(struct extent_buffer *eb, static inline void btrfs_item_key(const struct extent_buffer *eb,
struct btrfs_disk_key *disk_key, int nr) struct btrfs_disk_key *disk_key, int nr)
{ {
struct btrfs_item *item = btrfs_item_nr(nr); struct btrfs_item *item = btrfs_item_nr(nr);
@ -1943,8 +1947,8 @@ BTRFS_SETGET_STACK_FUNCS(stack_dir_name_len, struct btrfs_dir_item,
BTRFS_SETGET_STACK_FUNCS(stack_dir_transid, struct btrfs_dir_item, BTRFS_SETGET_STACK_FUNCS(stack_dir_transid, struct btrfs_dir_item,
transid, 64); transid, 64);
static inline void btrfs_dir_item_key(struct extent_buffer *eb, static inline void btrfs_dir_item_key(const struct extent_buffer *eb,
struct btrfs_dir_item *item, const struct btrfs_dir_item *item,
struct btrfs_disk_key *key) struct btrfs_disk_key *key)
{ {
read_eb_member(eb, item, struct btrfs_dir_item, location, key); read_eb_member(eb, item, struct btrfs_dir_item, location, key);
@ -1952,7 +1956,7 @@ static inline void btrfs_dir_item_key(struct extent_buffer *eb,
static inline void btrfs_set_dir_item_key(struct extent_buffer *eb, static inline void btrfs_set_dir_item_key(struct extent_buffer *eb,
struct btrfs_dir_item *item, struct btrfs_dir_item *item,
struct btrfs_disk_key *key) const struct btrfs_disk_key *key)
{ {
write_eb_member(eb, item, struct btrfs_dir_item, location, key); write_eb_member(eb, item, struct btrfs_dir_item, location, key);
} }
@ -1964,8 +1968,8 @@ BTRFS_SETGET_FUNCS(free_space_bitmaps, struct btrfs_free_space_header,
BTRFS_SETGET_FUNCS(free_space_generation, struct btrfs_free_space_header, BTRFS_SETGET_FUNCS(free_space_generation, struct btrfs_free_space_header,
generation, 64); generation, 64);
static inline void btrfs_free_space_key(struct extent_buffer *eb, static inline void btrfs_free_space_key(const struct extent_buffer *eb,
struct btrfs_free_space_header *h, const struct btrfs_free_space_header *h,
struct btrfs_disk_key *key) struct btrfs_disk_key *key)
{ {
read_eb_member(eb, h, struct btrfs_free_space_header, location, key); read_eb_member(eb, h, struct btrfs_free_space_header, location, key);
@ -1973,7 +1977,7 @@ static inline void btrfs_free_space_key(struct extent_buffer *eb,
static inline void btrfs_set_free_space_key(struct extent_buffer *eb, static inline void btrfs_set_free_space_key(struct extent_buffer *eb,
struct btrfs_free_space_header *h, struct btrfs_free_space_header *h,
struct btrfs_disk_key *key) const struct btrfs_disk_key *key)
{ {
write_eb_member(eb, h, struct btrfs_free_space_header, location, key); write_eb_member(eb, h, struct btrfs_free_space_header, location, key);
} }
@ -2000,25 +2004,25 @@ static inline void btrfs_cpu_key_to_disk(struct btrfs_disk_key *disk,
disk->objectid = cpu_to_le64(cpu->objectid); disk->objectid = cpu_to_le64(cpu->objectid);
} }
static inline void btrfs_node_key_to_cpu(struct extent_buffer *eb, static inline void btrfs_node_key_to_cpu(const struct extent_buffer *eb,
struct btrfs_key *key, int nr) struct btrfs_key *key, int nr)
{ {
struct btrfs_disk_key disk_key; struct btrfs_disk_key disk_key;
btrfs_node_key(eb, &disk_key, nr); btrfs_node_key(eb, &disk_key, nr);
btrfs_disk_key_to_cpu(key, &disk_key); btrfs_disk_key_to_cpu(key, &disk_key);
} }
static inline void btrfs_item_key_to_cpu(struct extent_buffer *eb, static inline void btrfs_item_key_to_cpu(const struct extent_buffer *eb,
struct btrfs_key *key, int nr) struct btrfs_key *key, int nr)
{ {
struct btrfs_disk_key disk_key; struct btrfs_disk_key disk_key;
btrfs_item_key(eb, &disk_key, nr); btrfs_item_key(eb, &disk_key, nr);
btrfs_disk_key_to_cpu(key, &disk_key); btrfs_disk_key_to_cpu(key, &disk_key);
} }
static inline void btrfs_dir_item_key_to_cpu(struct extent_buffer *eb, static inline void btrfs_dir_item_key_to_cpu(const struct extent_buffer *eb,
struct btrfs_dir_item *item, const struct btrfs_dir_item *item,
struct btrfs_key *key) struct btrfs_key *key)
{ {
struct btrfs_disk_key disk_key; struct btrfs_disk_key disk_key;
btrfs_dir_item_key(eb, item, &disk_key); btrfs_dir_item_key(eb, item, &disk_key);
@ -2050,7 +2054,7 @@ BTRFS_SETGET_STACK_FUNCS(stack_header_nritems, struct btrfs_header,
nritems, 32); nritems, 32);
BTRFS_SETGET_STACK_FUNCS(stack_header_bytenr, struct btrfs_header, bytenr, 64); BTRFS_SETGET_STACK_FUNCS(stack_header_bytenr, struct btrfs_header, bytenr, 64);
static inline int btrfs_header_flag(struct extent_buffer *eb, u64 flag) static inline int btrfs_header_flag(const struct extent_buffer *eb, u64 flag)
{ {
return (btrfs_header_flags(eb) & flag) == flag; return (btrfs_header_flags(eb) & flag) == flag;
} }
@ -2069,7 +2073,7 @@ static inline int btrfs_clear_header_flag(struct extent_buffer *eb, u64 flag)
return (flags & flag) == flag; return (flags & flag) == flag;
} }
static inline int btrfs_header_backref_rev(struct extent_buffer *eb) static inline int btrfs_header_backref_rev(const struct extent_buffer *eb)
{ {
u64 flags = btrfs_header_flags(eb); u64 flags = btrfs_header_flags(eb);
return flags >> BTRFS_BACKREF_REV_SHIFT; return flags >> BTRFS_BACKREF_REV_SHIFT;
@ -2089,12 +2093,12 @@ static inline unsigned long btrfs_header_fsid(void)
return offsetof(struct btrfs_header, fsid); return offsetof(struct btrfs_header, fsid);
} }
static inline unsigned long btrfs_header_chunk_tree_uuid(struct extent_buffer *eb) static inline unsigned long btrfs_header_chunk_tree_uuid(const struct extent_buffer *eb)
{ {
return offsetof(struct btrfs_header, chunk_tree_uuid); return offsetof(struct btrfs_header, chunk_tree_uuid);
} }
static inline int btrfs_is_leaf(struct extent_buffer *eb) static inline int btrfs_is_leaf(const struct extent_buffer *eb)
{ {
return btrfs_header_level(eb) == 0; return btrfs_header_level(eb) == 0;
} }
@ -2128,12 +2132,12 @@ BTRFS_SETGET_STACK_FUNCS(root_stransid, struct btrfs_root_item,
BTRFS_SETGET_STACK_FUNCS(root_rtransid, struct btrfs_root_item, BTRFS_SETGET_STACK_FUNCS(root_rtransid, struct btrfs_root_item,
rtransid, 64); rtransid, 64);
static inline bool btrfs_root_readonly(struct btrfs_root *root) static inline bool btrfs_root_readonly(const struct btrfs_root *root)
{ {
return (root->root_item.flags & cpu_to_le64(BTRFS_ROOT_SUBVOL_RDONLY)) != 0; return (root->root_item.flags & cpu_to_le64(BTRFS_ROOT_SUBVOL_RDONLY)) != 0;
} }
static inline bool btrfs_root_dead(struct btrfs_root *root) static inline bool btrfs_root_dead(const struct btrfs_root *root)
{ {
return (root->root_item.flags & cpu_to_le64(BTRFS_ROOT_SUBVOL_DEAD)) != 0; return (root->root_item.flags & cpu_to_le64(BTRFS_ROOT_SUBVOL_DEAD)) != 0;
} }
@ -2190,51 +2194,51 @@ BTRFS_SETGET_STACK_FUNCS(backup_num_devices, struct btrfs_root_backup,
/* struct btrfs_balance_item */ /* struct btrfs_balance_item */
BTRFS_SETGET_FUNCS(balance_flags, struct btrfs_balance_item, flags, 64); BTRFS_SETGET_FUNCS(balance_flags, struct btrfs_balance_item, flags, 64);
static inline void btrfs_balance_data(struct extent_buffer *eb, static inline void btrfs_balance_data(const struct extent_buffer *eb,
struct btrfs_balance_item *bi, const struct btrfs_balance_item *bi,
struct btrfs_disk_balance_args *ba) struct btrfs_disk_balance_args *ba)
{ {
read_eb_member(eb, bi, struct btrfs_balance_item, data, ba); read_eb_member(eb, bi, struct btrfs_balance_item, data, ba);
} }
static inline void btrfs_set_balance_data(struct extent_buffer *eb, static inline void btrfs_set_balance_data(struct extent_buffer *eb,
struct btrfs_balance_item *bi, struct btrfs_balance_item *bi,
struct btrfs_disk_balance_args *ba) const struct btrfs_disk_balance_args *ba)
{ {
write_eb_member(eb, bi, struct btrfs_balance_item, data, ba); write_eb_member(eb, bi, struct btrfs_balance_item, data, ba);
} }
static inline void btrfs_balance_meta(struct extent_buffer *eb, static inline void btrfs_balance_meta(const struct extent_buffer *eb,
struct btrfs_balance_item *bi, const struct btrfs_balance_item *bi,
struct btrfs_disk_balance_args *ba) struct btrfs_disk_balance_args *ba)
{ {
read_eb_member(eb, bi, struct btrfs_balance_item, meta, ba); read_eb_member(eb, bi, struct btrfs_balance_item, meta, ba);
} }
static inline void btrfs_set_balance_meta(struct extent_buffer *eb, static inline void btrfs_set_balance_meta(struct extent_buffer *eb,
struct btrfs_balance_item *bi, struct btrfs_balance_item *bi,
struct btrfs_disk_balance_args *ba) const struct btrfs_disk_balance_args *ba)
{ {
write_eb_member(eb, bi, struct btrfs_balance_item, meta, ba); write_eb_member(eb, bi, struct btrfs_balance_item, meta, ba);
} }
static inline void btrfs_balance_sys(struct extent_buffer *eb, static inline void btrfs_balance_sys(const struct extent_buffer *eb,
struct btrfs_balance_item *bi, const struct btrfs_balance_item *bi,
struct btrfs_disk_balance_args *ba) struct btrfs_disk_balance_args *ba)
{ {
read_eb_member(eb, bi, struct btrfs_balance_item, sys, ba); read_eb_member(eb, bi, struct btrfs_balance_item, sys, ba);
} }
static inline void btrfs_set_balance_sys(struct extent_buffer *eb, static inline void btrfs_set_balance_sys(struct extent_buffer *eb,
struct btrfs_balance_item *bi, struct btrfs_balance_item *bi,
struct btrfs_disk_balance_args *ba) const struct btrfs_disk_balance_args *ba)
{ {
write_eb_member(eb, bi, struct btrfs_balance_item, sys, ba); write_eb_member(eb, bi, struct btrfs_balance_item, sys, ba);
} }
static inline void static inline void
btrfs_disk_balance_args_to_cpu(struct btrfs_balance_args *cpu, btrfs_disk_balance_args_to_cpu(struct btrfs_balance_args *cpu,
struct btrfs_disk_balance_args *disk) const struct btrfs_disk_balance_args *disk)
{ {
memset(cpu, 0, sizeof(*cpu)); memset(cpu, 0, sizeof(*cpu));
@ -2254,7 +2258,7 @@ btrfs_disk_balance_args_to_cpu(struct btrfs_balance_args *cpu,
static inline void static inline void
btrfs_cpu_balance_args_to_disk(struct btrfs_disk_balance_args *disk, btrfs_cpu_balance_args_to_disk(struct btrfs_disk_balance_args *disk,
struct btrfs_balance_args *cpu) const struct btrfs_balance_args *cpu)
{ {
memset(disk, 0, sizeof(*disk)); memset(disk, 0, sizeof(*disk));
@ -2322,7 +2326,7 @@ BTRFS_SETGET_STACK_FUNCS(super_magic, struct btrfs_super_block, magic, 64);
BTRFS_SETGET_STACK_FUNCS(super_uuid_tree_generation, struct btrfs_super_block, BTRFS_SETGET_STACK_FUNCS(super_uuid_tree_generation, struct btrfs_super_block,
uuid_tree_generation, 64); uuid_tree_generation, 64);
static inline int btrfs_super_csum_size(struct btrfs_super_block *s) static inline int btrfs_super_csum_size(const struct btrfs_super_block *s)
{ {
u16 t = btrfs_super_csum_type(s); u16 t = btrfs_super_csum_type(s);
/* /*
@ -2337,8 +2341,8 @@ static inline int btrfs_super_csum_size(struct btrfs_super_block *s)
* this returns the address of the start of the last item, * this returns the address of the start of the last item,
* which is the stop of the leaf data stack * which is the stop of the leaf data stack
*/ */
static inline unsigned int leaf_data_end(struct btrfs_fs_info *fs_info, static inline unsigned int leaf_data_end(const struct btrfs_fs_info *fs_info,
struct extent_buffer *leaf) const struct extent_buffer *leaf)
{ {
u32 nr = btrfs_header_nritems(leaf); u32 nr = btrfs_header_nritems(leaf);
@ -2363,7 +2367,7 @@ BTRFS_SETGET_STACK_FUNCS(stack_file_extent_compression,
struct btrfs_file_extent_item, compression, 8); struct btrfs_file_extent_item, compression, 8);
static inline unsigned long static inline unsigned long
btrfs_file_extent_inline_start(struct btrfs_file_extent_item *e) btrfs_file_extent_inline_start(const struct btrfs_file_extent_item *e)
{ {
return (unsigned long)e + BTRFS_FILE_EXTENT_INLINE_DATA_START; return (unsigned long)e + BTRFS_FILE_EXTENT_INLINE_DATA_START;
} }
@ -2397,8 +2401,9 @@ BTRFS_SETGET_FUNCS(file_extent_other_encoding, struct btrfs_file_extent_item,
* size of any extent headers. If a file is compressed on disk, this is * size of any extent headers. If a file is compressed on disk, this is
* the compressed size * the compressed size
*/ */
static inline u32 btrfs_file_extent_inline_item_len(struct extent_buffer *eb, static inline u32 btrfs_file_extent_inline_item_len(
struct btrfs_item *e) const struct extent_buffer *eb,
struct btrfs_item *e)
{ {
return btrfs_item_size(eb, e) - BTRFS_FILE_EXTENT_INLINE_DATA_START; return btrfs_item_size(eb, e) - BTRFS_FILE_EXTENT_INLINE_DATA_START;
} }
@ -2406,9 +2411,9 @@ static inline u32 btrfs_file_extent_inline_item_len(struct extent_buffer *eb,
/* this returns the number of file bytes represented by the inline item. /* this returns the number of file bytes represented by the inline item.
* If an item is compressed, this is the uncompressed size * If an item is compressed, this is the uncompressed size
*/ */
static inline u32 btrfs_file_extent_inline_len(struct extent_buffer *eb, static inline u32 btrfs_file_extent_inline_len(const struct extent_buffer *eb,
int slot, int slot,
struct btrfs_file_extent_item *fi) const struct btrfs_file_extent_item *fi)
{ {
struct btrfs_map_token token; struct btrfs_map_token token;
@ -2430,8 +2435,8 @@ static inline u32 btrfs_file_extent_inline_len(struct extent_buffer *eb,
/* btrfs_dev_stats_item */ /* btrfs_dev_stats_item */
static inline u64 btrfs_dev_stats_value(struct extent_buffer *eb, static inline u64 btrfs_dev_stats_value(const struct extent_buffer *eb,
struct btrfs_dev_stats_item *ptr, const struct btrfs_dev_stats_item *ptr,
int index) int index)
{ {
u64 val; u64 val;
@ -2561,6 +2566,17 @@ static inline gfp_t btrfs_alloc_write_mask(struct address_space *mapping)
/* extent-tree.c */ /* extent-tree.c */
enum btrfs_inline_ref_type {
BTRFS_REF_TYPE_INVALID = 0,
BTRFS_REF_TYPE_BLOCK = 1,
BTRFS_REF_TYPE_DATA = 2,
BTRFS_REF_TYPE_ANY = 3,
};
int btrfs_get_extent_inline_ref_type(const struct extent_buffer *eb,
struct btrfs_extent_inline_ref *iref,
enum btrfs_inline_ref_type is_data);
u64 btrfs_csum_bytes_to_leaves(struct btrfs_fs_info *fs_info, u64 csum_bytes); u64 btrfs_csum_bytes_to_leaves(struct btrfs_fs_info *fs_info, u64 csum_bytes);
static inline u64 btrfs_calc_trans_metadata_size(struct btrfs_fs_info *fs_info, static inline u64 btrfs_calc_trans_metadata_size(struct btrfs_fs_info *fs_info,
@ -2670,8 +2686,7 @@ int btrfs_read_block_groups(struct btrfs_fs_info *info);
int btrfs_can_relocate(struct btrfs_fs_info *fs_info, u64 bytenr); int btrfs_can_relocate(struct btrfs_fs_info *fs_info, u64 bytenr);
int btrfs_make_block_group(struct btrfs_trans_handle *trans, int btrfs_make_block_group(struct btrfs_trans_handle *trans,
struct btrfs_fs_info *fs_info, u64 bytes_used, struct btrfs_fs_info *fs_info, u64 bytes_used,
u64 type, u64 chunk_objectid, u64 chunk_offset, u64 type, u64 chunk_offset, u64 size);
u64 size);
struct btrfs_trans_handle *btrfs_start_trans_remove_block_group( struct btrfs_trans_handle *btrfs_start_trans_remove_block_group(
struct btrfs_fs_info *fs_info, struct btrfs_fs_info *fs_info,
const u64 chunk_offset); const u64 chunk_offset);
@ -2772,8 +2787,8 @@ int btrfs_init_space_info(struct btrfs_fs_info *fs_info);
int btrfs_delayed_refs_qgroup_accounting(struct btrfs_trans_handle *trans, int btrfs_delayed_refs_qgroup_accounting(struct btrfs_trans_handle *trans,
struct btrfs_fs_info *fs_info); struct btrfs_fs_info *fs_info);
int __get_raid_index(u64 flags); int __get_raid_index(u64 flags);
int btrfs_start_write_no_snapshoting(struct btrfs_root *root); int btrfs_start_write_no_snapshotting(struct btrfs_root *root);
void btrfs_end_write_no_snapshoting(struct btrfs_root *root); void btrfs_end_write_no_snapshotting(struct btrfs_root *root);
void btrfs_wait_for_snapshot_creation(struct btrfs_root *root); void btrfs_wait_for_snapshot_creation(struct btrfs_root *root);
void check_system_chunk(struct btrfs_trans_handle *trans, void check_system_chunk(struct btrfs_trans_handle *trans,
struct btrfs_fs_info *fs_info, const u64 type); struct btrfs_fs_info *fs_info, const u64 type);
@ -2973,8 +2988,8 @@ int btrfs_del_root_ref(struct btrfs_trans_handle *trans,
struct btrfs_fs_info *fs_info, struct btrfs_fs_info *fs_info,
u64 root_id, u64 ref_id, u64 dirid, u64 *sequence, u64 root_id, u64 ref_id, u64 dirid, u64 *sequence,
const char *name, int name_len); const char *name, int name_len);
int btrfs_del_root(struct btrfs_trans_handle *trans, struct btrfs_root *root, int btrfs_del_root(struct btrfs_trans_handle *trans,
const struct btrfs_key *key); struct btrfs_fs_info *fs_info, const struct btrfs_key *key);
int btrfs_insert_root(struct btrfs_trans_handle *trans, struct btrfs_root *root, int btrfs_insert_root(struct btrfs_trans_handle *trans, struct btrfs_root *root,
const struct btrfs_key *key, const struct btrfs_key *key,
struct btrfs_root_item *item); struct btrfs_root_item *item);
@ -3135,21 +3150,6 @@ noinline int can_nocow_extent(struct inode *inode, u64 offset, u64 *len,
u64 *orig_start, u64 *orig_block_len, u64 *orig_start, u64 *orig_block_len,
u64 *ram_bytes); u64 *ram_bytes);
/* RHEL and EL kernels have a patch that renames PG_checked to FsMisc */
#if defined(ClearPageFsMisc) && !defined(ClearPageChecked)
#define ClearPageChecked ClearPageFsMisc
#define SetPageChecked SetPageFsMisc
#define PageChecked PageFsMisc
#endif
/* This forces readahead on a given range of bytes in an inode */
static inline void btrfs_force_ra(struct address_space *mapping,
struct file_ra_state *ra, struct file *file,
pgoff_t offset, unsigned long req_size)
{
page_cache_sync_readahead(mapping, ra, file, offset, req_size);
}
struct inode *btrfs_lookup_dentry(struct inode *dir, struct dentry *dentry); struct inode *btrfs_lookup_dentry(struct inode *dir, struct dentry *dentry);
int btrfs_set_inode_index(struct btrfs_inode *dir, u64 *index); int btrfs_set_inode_index(struct btrfs_inode *dir, u64 *index);
int btrfs_unlink_inode(struct btrfs_trans_handle *trans, int btrfs_unlink_inode(struct btrfs_trans_handle *trans,
@ -3229,7 +3229,6 @@ long btrfs_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
long btrfs_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg); long btrfs_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
int btrfs_ioctl_get_supported_features(void __user *arg); int btrfs_ioctl_get_supported_features(void __user *arg);
void btrfs_update_iflags(struct inode *inode); void btrfs_update_iflags(struct inode *inode);
void btrfs_inherit_iflags(struct inode *inode, struct inode *dir);
int btrfs_is_empty_uuid(u8 *uuid); int btrfs_is_empty_uuid(u8 *uuid);
int btrfs_defrag_file(struct inode *inode, struct file *file, int btrfs_defrag_file(struct inode *inode, struct file *file,
struct btrfs_ioctl_defrag_range_args *range, struct btrfs_ioctl_defrag_range_args *range,

View File

@ -1727,6 +1727,7 @@ int btrfs_readdir_delayed_dir_index(struct dir_context *ctx,
if (over) if (over)
return 1; return 1;
ctx->pos++;
} }
return 0; return 0;
} }

View File

@ -639,11 +639,39 @@ static void btrfs_dev_replace_update_device_in_mapping_tree(
write_unlock(&em_tree->lock); write_unlock(&em_tree->lock);
} }
/*
* Read progress of device replace status according to the state and last
* stored position. The value format is the same as for
* btrfs_dev_replace::progress_1000
*/
static u64 btrfs_dev_replace_progress(struct btrfs_fs_info *fs_info)
{
struct btrfs_dev_replace *dev_replace = &fs_info->dev_replace;
u64 ret = 0;
switch (dev_replace->replace_state) {
case BTRFS_IOCTL_DEV_REPLACE_STATE_NEVER_STARTED:
case BTRFS_IOCTL_DEV_REPLACE_STATE_CANCELED:
ret = 0;
break;
case BTRFS_IOCTL_DEV_REPLACE_STATE_FINISHED:
ret = 1000;
break;
case BTRFS_IOCTL_DEV_REPLACE_STATE_STARTED:
case BTRFS_IOCTL_DEV_REPLACE_STATE_SUSPENDED:
ret = div64_u64(dev_replace->cursor_left,
div_u64(btrfs_device_get_total_bytes(
dev_replace->srcdev), 1000));
break;
}
return ret;
}
void btrfs_dev_replace_status(struct btrfs_fs_info *fs_info, void btrfs_dev_replace_status(struct btrfs_fs_info *fs_info,
struct btrfs_ioctl_dev_replace_args *args) struct btrfs_ioctl_dev_replace_args *args)
{ {
struct btrfs_dev_replace *dev_replace = &fs_info->dev_replace; struct btrfs_dev_replace *dev_replace = &fs_info->dev_replace;
struct btrfs_device *srcdev;
btrfs_dev_replace_lock(dev_replace, 0); btrfs_dev_replace_lock(dev_replace, 0);
/* even if !dev_replace_is_valid, the values are good enough for /* even if !dev_replace_is_valid, the values are good enough for
@ -656,21 +684,7 @@ void btrfs_dev_replace_status(struct btrfs_fs_info *fs_info,
atomic64_read(&dev_replace->num_write_errors); atomic64_read(&dev_replace->num_write_errors);
args->status.num_uncorrectable_read_errors = args->status.num_uncorrectable_read_errors =
atomic64_read(&dev_replace->num_uncorrectable_read_errors); atomic64_read(&dev_replace->num_uncorrectable_read_errors);
switch (dev_replace->replace_state) { args->status.progress_1000 = btrfs_dev_replace_progress(fs_info);
case BTRFS_IOCTL_DEV_REPLACE_STATE_NEVER_STARTED:
case BTRFS_IOCTL_DEV_REPLACE_STATE_CANCELED:
args->status.progress_1000 = 0;
break;
case BTRFS_IOCTL_DEV_REPLACE_STATE_FINISHED:
args->status.progress_1000 = 1000;
break;
case BTRFS_IOCTL_DEV_REPLACE_STATE_STARTED:
case BTRFS_IOCTL_DEV_REPLACE_STATE_SUSPENDED:
srcdev = dev_replace->srcdev;
args->status.progress_1000 = div64_u64(dev_replace->cursor_left,
div_u64(btrfs_device_get_total_bytes(srcdev), 1000));
break;
}
btrfs_dev_replace_unlock(dev_replace, 0); btrfs_dev_replace_unlock(dev_replace, 0);
} }
@ -795,25 +809,19 @@ static int btrfs_dev_replace_kthread(void *data)
{ {
struct btrfs_fs_info *fs_info = data; struct btrfs_fs_info *fs_info = data;
struct btrfs_dev_replace *dev_replace = &fs_info->dev_replace; struct btrfs_dev_replace *dev_replace = &fs_info->dev_replace;
struct btrfs_ioctl_dev_replace_args *status_args;
u64 progress; u64 progress;
status_args = kzalloc(sizeof(*status_args), GFP_KERNEL); progress = btrfs_dev_replace_progress(fs_info);
if (status_args) { progress = div_u64(progress, 10);
btrfs_dev_replace_status(fs_info, status_args); btrfs_info_in_rcu(fs_info,
progress = status_args->status.progress_1000; "continuing dev_replace from %s (devid %llu) to %s @%u%%",
kfree(status_args); dev_replace->srcdev->missing ? "<missing disk>"
progress = div_u64(progress, 10); : rcu_str_deref(dev_replace->srcdev->name),
btrfs_info_in_rcu(fs_info, dev_replace->srcdev->devid,
"continuing dev_replace from %s (devid %llu) to %s @%u%%", dev_replace->tgtdev ? rcu_str_deref(dev_replace->tgtdev->name)
dev_replace->srcdev->missing ? "<missing disk>" : : "<missing target disk>",
rcu_str_deref(dev_replace->srcdev->name), (unsigned int)progress);
dev_replace->srcdev->devid,
dev_replace->tgtdev ?
rcu_str_deref(dev_replace->tgtdev->name) :
"<missing target disk>",
(unsigned int)progress);
}
btrfs_dev_replace_continue_on_mount(fs_info); btrfs_dev_replace_continue_on_mount(fs_info);
clear_bit(BTRFS_FS_EXCL_OP, &fs_info->flags); clear_bit(BTRFS_FS_EXCL_OP, &fs_info->flags);

View File

@ -529,7 +529,7 @@ static int check_tree_block_fsid(struct btrfs_fs_info *fs_info,
struct extent_buffer *eb) struct extent_buffer *eb)
{ {
struct btrfs_fs_devices *fs_devices = fs_info->fs_devices; struct btrfs_fs_devices *fs_devices = fs_info->fs_devices;
u8 fsid[BTRFS_UUID_SIZE]; u8 fsid[BTRFS_FSID_SIZE];
int ret = 1; int ret = 1;
read_extent_buffer(eb, fsid, btrfs_header_fsid(), BTRFS_FSID_SIZE); read_extent_buffer(eb, fsid, btrfs_header_fsid(), BTRFS_FSID_SIZE);
@ -1343,7 +1343,7 @@ static void __setup_root(struct btrfs_root *root, struct btrfs_fs_info *fs_info,
atomic_set(&root->log_batch, 0); atomic_set(&root->log_batch, 0);
atomic_set(&root->orphan_inodes, 0); atomic_set(&root->orphan_inodes, 0);
refcount_set(&root->refs, 1); refcount_set(&root->refs, 1);
atomic_set(&root->will_be_snapshoted, 0); atomic_set(&root->will_be_snapshotted, 0);
atomic64_set(&root->qgroup_meta_rsv, 0); atomic64_set(&root->qgroup_meta_rsv, 0);
root->log_transid = 0; root->log_transid = 0;
root->log_transid_committed = -1; root->log_transid_committed = -1;
@ -2694,8 +2694,8 @@ int open_ctree(struct super_block *sb,
btrfs_init_balance(fs_info); btrfs_init_balance(fs_info);
btrfs_init_async_reclaim_work(&fs_info->async_reclaim_work); btrfs_init_async_reclaim_work(&fs_info->async_reclaim_work);
sb->s_blocksize = 4096; sb->s_blocksize = BTRFS_BDEV_BLOCKSIZE;
sb->s_blocksize_bits = blksize_bits(4096); sb->s_blocksize_bits = blksize_bits(BTRFS_BDEV_BLOCKSIZE);
btrfs_init_btree_inode(fs_info); btrfs_init_btree_inode(fs_info);
@ -3035,15 +3035,10 @@ retry_root_backup:
btrfs_err(fs_info, "failed to read block groups: %d", ret); btrfs_err(fs_info, "failed to read block groups: %d", ret);
goto fail_sysfs; goto fail_sysfs;
} }
fs_info->num_tolerated_disk_barrier_failures =
btrfs_calc_num_tolerated_disk_barrier_failures(fs_info); if (!(sb->s_flags & MS_RDONLY) && !btrfs_check_rw_degradable(fs_info)) {
if (fs_info->fs_devices->missing_devices >
fs_info->num_tolerated_disk_barrier_failures &&
!(sb->s_flags & MS_RDONLY)) {
btrfs_warn(fs_info, btrfs_warn(fs_info,
"missing devices (%llu) exceeds the limit (%d), writeable mount is not allowed", "writeable mount is not allowed due to too many missing devices");
fs_info->fs_devices->missing_devices,
fs_info->num_tolerated_disk_barrier_failures);
goto fail_sysfs; goto fail_sysfs;
} }
@ -3058,11 +3053,9 @@ retry_root_backup:
if (IS_ERR(fs_info->transaction_kthread)) if (IS_ERR(fs_info->transaction_kthread))
goto fail_cleaner; goto fail_cleaner;
if (!btrfs_test_opt(fs_info, SSD) && if (!btrfs_test_opt(fs_info, NOSSD) &&
!btrfs_test_opt(fs_info, NOSSD) &&
!fs_info->fs_devices->rotating) { !fs_info->fs_devices->rotating) {
btrfs_info(fs_info, "detected SSD devices, enabling SSD mode"); btrfs_set_and_info(fs_info, SSD, "enabling ssd optimizations");
btrfs_set_opt(fs_info->mount_opt, SSD);
} }
/* /*
@ -3321,7 +3314,7 @@ int btrfs_read_dev_one_super(struct block_device *bdev, int copy_num,
if (bytenr + BTRFS_SUPER_INFO_SIZE >= i_size_read(bdev->bd_inode)) if (bytenr + BTRFS_SUPER_INFO_SIZE >= i_size_read(bdev->bd_inode))
return -EINVAL; return -EINVAL;
bh = __bread(bdev, bytenr / 4096, BTRFS_SUPER_INFO_SIZE); bh = __bread(bdev, bytenr / BTRFS_BDEV_BLOCKSIZE, BTRFS_SUPER_INFO_SIZE);
/* /*
* If we fail to read from the underlying devices, as of now * If we fail to read from the underlying devices, as of now
* the best option we have is to mark it EIO. * the best option we have is to mark it EIO.
@ -3378,19 +3371,17 @@ struct buffer_head *btrfs_read_dev_super(struct block_device *bdev)
} }
/* /*
* this should be called twice, once with wait == 0 and * Write superblock @sb to the @device. Do not wait for completion, all the
* once with wait == 1. When wait == 0 is done, all the buffer heads * buffer heads we write are pinned.
* we write are pinned.
* *
* They are released when wait == 1 is done. * Write @max_mirrors copies of the superblock, where 0 means default that fit
* max_mirrors must be the same for both runs, and it indicates how * the expected device size at commit time. Note that max_mirrors must be
* many supers on this one device should be written. * same for write and wait phases.
* *
* max_mirrors == 0 means to write them all. * Return number of errors when buffer head is not found or submission fails.
*/ */
static int write_dev_supers(struct btrfs_device *device, static int write_dev_supers(struct btrfs_device *device,
struct btrfs_super_block *sb, struct btrfs_super_block *sb, int max_mirrors)
int wait, int max_mirrors)
{ {
struct buffer_head *bh; struct buffer_head *bh;
int i; int i;
@ -3408,67 +3399,44 @@ static int write_dev_supers(struct btrfs_device *device,
device->commit_total_bytes) device->commit_total_bytes)
break; break;
if (wait) { btrfs_set_super_bytenr(sb, bytenr);
bh = __find_get_block(device->bdev, bytenr / 4096,
BTRFS_SUPER_INFO_SIZE);
if (!bh) {
errors++;
continue;
}
wait_on_buffer(bh);
if (!buffer_uptodate(bh))
errors++;
/* drop our reference */ crc = ~(u32)0;
brelse(bh); crc = btrfs_csum_data((const char *)sb + BTRFS_CSUM_SIZE, crc,
BTRFS_SUPER_INFO_SIZE - BTRFS_CSUM_SIZE);
btrfs_csum_final(crc, sb->csum);
/* drop the reference from the wait == 0 run */ /* One reference for us, and we leave it for the caller */
brelse(bh); bh = __getblk(device->bdev, bytenr / BTRFS_BDEV_BLOCKSIZE,
BTRFS_SUPER_INFO_SIZE);
if (!bh) {
btrfs_err(device->fs_info,
"couldn't get super buffer head for bytenr %llu",
bytenr);
errors++;
continue; continue;
} else {
btrfs_set_super_bytenr(sb, bytenr);
crc = ~(u32)0;
crc = btrfs_csum_data((const char *)sb +
BTRFS_CSUM_SIZE, crc,
BTRFS_SUPER_INFO_SIZE -
BTRFS_CSUM_SIZE);
btrfs_csum_final(crc, sb->csum);
/*
* one reference for us, and we leave it for the
* caller
*/
bh = __getblk(device->bdev, bytenr / 4096,
BTRFS_SUPER_INFO_SIZE);
if (!bh) {
btrfs_err(device->fs_info,
"couldn't get super buffer head for bytenr %llu",
bytenr);
errors++;
continue;
}
memcpy(bh->b_data, sb, BTRFS_SUPER_INFO_SIZE);
/* one reference for submit_bh */
get_bh(bh);
set_buffer_uptodate(bh);
lock_buffer(bh);
bh->b_end_io = btrfs_end_buffer_write_sync;
bh->b_private = device;
} }
memcpy(bh->b_data, sb, BTRFS_SUPER_INFO_SIZE);
/* one reference for submit_bh */
get_bh(bh);
set_buffer_uptodate(bh);
lock_buffer(bh);
bh->b_end_io = btrfs_end_buffer_write_sync;
bh->b_private = device;
/* /*
* we fua the first super. The others we allow * we fua the first super. The others we allow
* to go down lazy. * to go down lazy.
*/ */
if (i == 0) { if (i == 0) {
ret = btrfsic_submit_bh(REQ_OP_WRITE, ret = btrfsic_submit_bh(REQ_OP_WRITE,
REQ_SYNC | REQ_FUA, bh); REQ_SYNC | REQ_FUA | REQ_META | REQ_PRIO, bh);
} else { } else {
ret = btrfsic_submit_bh(REQ_OP_WRITE, REQ_SYNC, bh); ret = btrfsic_submit_bh(REQ_OP_WRITE,
REQ_SYNC | REQ_META | REQ_PRIO, bh);
} }
if (ret) if (ret)
errors++; errors++;
@ -3476,6 +3444,50 @@ static int write_dev_supers(struct btrfs_device *device,
return errors < i ? 0 : -1; return errors < i ? 0 : -1;
} }
/*
* Wait for write completion of superblocks done by write_dev_supers,
* @max_mirrors same for write and wait phases.
*
* Return number of errors when buffer head is not found or not marked up to
* date.
*/
static int wait_dev_supers(struct btrfs_device *device, int max_mirrors)
{
struct buffer_head *bh;
int i;
int errors = 0;
u64 bytenr;
if (max_mirrors == 0)
max_mirrors = BTRFS_SUPER_MIRROR_MAX;
for (i = 0; i < max_mirrors; i++) {
bytenr = btrfs_sb_offset(i);
if (bytenr + BTRFS_SUPER_INFO_SIZE >=
device->commit_total_bytes)
break;
bh = __find_get_block(device->bdev,
bytenr / BTRFS_BDEV_BLOCKSIZE,
BTRFS_SUPER_INFO_SIZE);
if (!bh) {
errors++;
continue;
}
wait_on_buffer(bh);
if (!buffer_uptodate(bh))
errors++;
/* drop our reference */
brelse(bh);
/* drop the reference from the writing run */
brelse(bh);
}
return errors < i ? 0 : -1;
}
/* /*
* endio for the write_dev_flush, this will wake anyone waiting * endio for the write_dev_flush, this will wake anyone waiting
* for the barrier when it is done * for the barrier when it is done
@ -3504,7 +3516,7 @@ static void write_dev_flush(struct btrfs_device *device)
init_completion(&device->flush_wait); init_completion(&device->flush_wait);
bio->bi_private = &device->flush_wait; bio->bi_private = &device->flush_wait;
submit_bio(bio); btrfsic_submit_bio(bio);
device->flush_bio_sent = 1; device->flush_bio_sent = 1;
} }
@ -3524,20 +3536,10 @@ static blk_status_t wait_dev_flush(struct btrfs_device *device)
return bio->bi_status; return bio->bi_status;
} }
static int check_barrier_error(struct btrfs_fs_devices *fsdevs) static int check_barrier_error(struct btrfs_fs_info *fs_info)
{ {
int dev_flush_error = 0; if (!btrfs_check_rw_degradable(fs_info))
struct btrfs_device *dev;
list_for_each_entry_rcu(dev, &fsdevs->devices, dev_list) {
if (!dev->bdev || dev->last_flush_error)
dev_flush_error++;
}
if (dev_flush_error >
fsdevs->fs_info->num_tolerated_disk_barrier_failures)
return -EIO; return -EIO;
return 0; return 0;
} }
@ -3592,7 +3594,7 @@ static int barrier_all_devices(struct btrfs_fs_info *info)
* to arrive at the volume status. So error checking * to arrive at the volume status. So error checking
* is being pushed to a separate loop. * is being pushed to a separate loop.
*/ */
return check_barrier_error(info->fs_devices); return check_barrier_error(info);
} }
return 0; return 0;
} }
@ -3626,60 +3628,6 @@ int btrfs_get_num_tolerated_disk_barrier_failures(u64 flags)
return min_tolerated; return min_tolerated;
} }
int btrfs_calc_num_tolerated_disk_barrier_failures(
struct btrfs_fs_info *fs_info)
{
struct btrfs_ioctl_space_info space;
struct btrfs_space_info *sinfo;
u64 types[] = {BTRFS_BLOCK_GROUP_DATA,
BTRFS_BLOCK_GROUP_SYSTEM,
BTRFS_BLOCK_GROUP_METADATA,
BTRFS_BLOCK_GROUP_DATA | BTRFS_BLOCK_GROUP_METADATA};
int i;
int c;
int num_tolerated_disk_barrier_failures =
(int)fs_info->fs_devices->num_devices;
for (i = 0; i < ARRAY_SIZE(types); i++) {
struct btrfs_space_info *tmp;
sinfo = NULL;
rcu_read_lock();
list_for_each_entry_rcu(tmp, &fs_info->space_info, list) {
if (tmp->flags == types[i]) {
sinfo = tmp;
break;
}
}
rcu_read_unlock();
if (!sinfo)
continue;
down_read(&sinfo->groups_sem);
for (c = 0; c < BTRFS_NR_RAID_TYPES; c++) {
u64 flags;
if (list_empty(&sinfo->block_groups[c]))
continue;
btrfs_get_block_group_info(&sinfo->block_groups[c],
&space);
if (space.total_bytes == 0 || space.used_bytes == 0)
continue;
flags = space.flags;
num_tolerated_disk_barrier_failures = min(
num_tolerated_disk_barrier_failures,
btrfs_get_num_tolerated_disk_barrier_failures(
flags));
}
up_read(&sinfo->groups_sem);
}
return num_tolerated_disk_barrier_failures;
}
int write_all_supers(struct btrfs_fs_info *fs_info, int max_mirrors) int write_all_supers(struct btrfs_fs_info *fs_info, int max_mirrors)
{ {
struct list_head *head; struct list_head *head;
@ -3732,12 +3680,12 @@ int write_all_supers(struct btrfs_fs_info *fs_info, int max_mirrors)
btrfs_set_stack_device_io_width(dev_item, dev->io_width); btrfs_set_stack_device_io_width(dev_item, dev->io_width);
btrfs_set_stack_device_sector_size(dev_item, dev->sector_size); btrfs_set_stack_device_sector_size(dev_item, dev->sector_size);
memcpy(dev_item->uuid, dev->uuid, BTRFS_UUID_SIZE); memcpy(dev_item->uuid, dev->uuid, BTRFS_UUID_SIZE);
memcpy(dev_item->fsid, dev->fs_devices->fsid, BTRFS_UUID_SIZE); memcpy(dev_item->fsid, dev->fs_devices->fsid, BTRFS_FSID_SIZE);
flags = btrfs_super_flags(sb); flags = btrfs_super_flags(sb);
btrfs_set_super_flags(sb, flags | BTRFS_HEADER_FLAG_WRITTEN); btrfs_set_super_flags(sb, flags | BTRFS_HEADER_FLAG_WRITTEN);
ret = write_dev_supers(dev, sb, 0, max_mirrors); ret = write_dev_supers(dev, sb, max_mirrors);
if (ret) if (ret)
total_errors++; total_errors++;
} }
@ -3760,7 +3708,7 @@ int write_all_supers(struct btrfs_fs_info *fs_info, int max_mirrors)
if (!dev->in_fs_metadata || !dev->writeable) if (!dev->in_fs_metadata || !dev->writeable)
continue; continue;
ret = write_dev_supers(dev, sb, 1, max_mirrors); ret = wait_dev_supers(dev, max_mirrors);
if (ret) if (ret)
total_errors++; total_errors++;
} }
@ -3995,7 +3943,6 @@ void close_ctree(struct btrfs_fs_info *fs_info)
__btrfs_free_block_rsv(root->orphan_block_rsv); __btrfs_free_block_rsv(root->orphan_block_rsv);
root->orphan_block_rsv = NULL; root->orphan_block_rsv = NULL;
mutex_lock(&fs_info->chunk_mutex);
while (!list_empty(&fs_info->pinned_chunks)) { while (!list_empty(&fs_info->pinned_chunks)) {
struct extent_map *em; struct extent_map *em;
@ -4004,7 +3951,6 @@ void close_ctree(struct btrfs_fs_info *fs_info)
list_del_init(&em->list); list_del_init(&em->list);
free_extent_map(em); free_extent_map(em);
} }
mutex_unlock(&fs_info->chunk_mutex);
} }
int btrfs_buffer_uptodate(struct extent_buffer *buf, u64 parent_transid, int btrfs_buffer_uptodate(struct extent_buffer *buf, u64 parent_transid,
@ -4053,7 +3999,7 @@ void btrfs_mark_buffer_dirty(struct extent_buffer *buf)
fs_info->dirty_metadata_batch); fs_info->dirty_metadata_batch);
#ifdef CONFIG_BTRFS_FS_CHECK_INTEGRITY #ifdef CONFIG_BTRFS_FS_CHECK_INTEGRITY
if (btrfs_header_level(buf) == 0 && check_leaf(root, buf)) { if (btrfs_header_level(buf) == 0 && check_leaf(root, buf)) {
btrfs_print_leaf(fs_info, buf); btrfs_print_leaf(buf);
ASSERT(0); ASSERT(0);
} }
#endif #endif
@ -4173,7 +4119,7 @@ static int btrfs_check_super_valid(struct btrfs_fs_info *fs_info)
ret = -EINVAL; ret = -EINVAL;
} }
if (memcmp(fs_info->fsid, sb->dev_item.fsid, BTRFS_UUID_SIZE) != 0) { if (memcmp(fs_info->fsid, sb->dev_item.fsid, BTRFS_FSID_SIZE) != 0) {
btrfs_err(fs_info, btrfs_err(fs_info,
"dev_item UUID does not match fsid: %pU != %pU", "dev_item UUID does not match fsid: %pU != %pU",
fs_info->fsid, sb->dev_item.fsid); fs_info->fsid, sb->dev_item.fsid);

View File

@ -25,6 +25,14 @@
#define BTRFS_SUPER_MIRROR_MAX 3 #define BTRFS_SUPER_MIRROR_MAX 3
#define BTRFS_SUPER_MIRROR_SHIFT 12 #define BTRFS_SUPER_MIRROR_SHIFT 12
/*
* Fixed blocksize for all devices, applies to specific ways of reading
* metadata like superblock. Must meet the set_blocksize requirements.
*
* Do not change.
*/
#define BTRFS_BDEV_BLOCKSIZE (4096)
enum btrfs_wq_endio_type { enum btrfs_wq_endio_type {
BTRFS_WQ_ENDIO_DATA = 0, BTRFS_WQ_ENDIO_DATA = 0,
BTRFS_WQ_ENDIO_METADATA = 1, BTRFS_WQ_ENDIO_METADATA = 1,
@ -142,8 +150,6 @@ struct btrfs_root *btrfs_create_tree(struct btrfs_trans_handle *trans,
int btree_lock_page_hook(struct page *page, void *data, int btree_lock_page_hook(struct page *page, void *data,
void (*flush_fn)(void *)); void (*flush_fn)(void *));
int btrfs_get_num_tolerated_disk_barrier_failures(u64 flags); int btrfs_get_num_tolerated_disk_barrier_failures(u64 flags);
int btrfs_calc_num_tolerated_disk_barrier_failures(
struct btrfs_fs_info *fs_info);
int __init btrfs_end_io_wq_init(void); int __init btrfs_end_io_wq_init(void);
void btrfs_end_io_wq_exit(void); void btrfs_end_io_wq_exit(void);

View File

@ -1148,6 +1148,64 @@ static int convert_extent_item_v0(struct btrfs_trans_handle *trans,
} }
#endif #endif
/*
* is_data == BTRFS_REF_TYPE_BLOCK, tree block type is required,
* is_data == BTRFS_REF_TYPE_DATA, data type is requried,
* is_data == BTRFS_REF_TYPE_ANY, either type is OK.
*/
int btrfs_get_extent_inline_ref_type(const struct extent_buffer *eb,
struct btrfs_extent_inline_ref *iref,
enum btrfs_inline_ref_type is_data)
{
int type = btrfs_extent_inline_ref_type(eb, iref);
u64 offset = btrfs_extent_inline_ref_offset(eb, iref);
if (type == BTRFS_TREE_BLOCK_REF_KEY ||
type == BTRFS_SHARED_BLOCK_REF_KEY ||
type == BTRFS_SHARED_DATA_REF_KEY ||
type == BTRFS_EXTENT_DATA_REF_KEY) {
if (is_data == BTRFS_REF_TYPE_BLOCK) {
if (type == BTRFS_TREE_BLOCK_REF_KEY)
return type;
if (type == BTRFS_SHARED_BLOCK_REF_KEY) {
ASSERT(eb->fs_info);
/*
* Every shared one has parent tree
* block, which must be aligned to
* nodesize.
*/
if (offset &&
IS_ALIGNED(offset, eb->fs_info->nodesize))
return type;
}
} else if (is_data == BTRFS_REF_TYPE_DATA) {
if (type == BTRFS_EXTENT_DATA_REF_KEY)
return type;
if (type == BTRFS_SHARED_DATA_REF_KEY) {
ASSERT(eb->fs_info);
/*
* Every shared one has parent tree
* block, which must be aligned to
* nodesize.
*/
if (offset &&
IS_ALIGNED(offset, eb->fs_info->nodesize))
return type;
}
} else {
ASSERT(is_data == BTRFS_REF_TYPE_ANY);
return type;
}
}
btrfs_print_leaf((struct extent_buffer *)eb);
btrfs_err(eb->fs_info, "eb %llu invalid extent inline ref type %d",
eb->start, type);
WARN_ON(1);
return BTRFS_REF_TYPE_INVALID;
}
static u64 hash_extent_data_ref(u64 root_objectid, u64 owner, u64 offset) static u64 hash_extent_data_ref(u64 root_objectid, u64 owner, u64 offset)
{ {
u32 high_crc = ~(u32)0; u32 high_crc = ~(u32)0;
@ -1417,12 +1475,18 @@ static noinline u32 extent_data_ref_count(struct btrfs_path *path,
struct btrfs_extent_data_ref *ref1; struct btrfs_extent_data_ref *ref1;
struct btrfs_shared_data_ref *ref2; struct btrfs_shared_data_ref *ref2;
u32 num_refs = 0; u32 num_refs = 0;
int type;
leaf = path->nodes[0]; leaf = path->nodes[0];
btrfs_item_key_to_cpu(leaf, &key, path->slots[0]); btrfs_item_key_to_cpu(leaf, &key, path->slots[0]);
if (iref) { if (iref) {
if (btrfs_extent_inline_ref_type(leaf, iref) == /*
BTRFS_EXTENT_DATA_REF_KEY) { * If type is invalid, we should have bailed out earlier than
* this call.
*/
type = btrfs_get_extent_inline_ref_type(leaf, iref, BTRFS_REF_TYPE_DATA);
ASSERT(type != BTRFS_REF_TYPE_INVALID);
if (type == BTRFS_EXTENT_DATA_REF_KEY) {
ref1 = (struct btrfs_extent_data_ref *)(&iref->offset); ref1 = (struct btrfs_extent_data_ref *)(&iref->offset);
num_refs = btrfs_extent_data_ref_count(leaf, ref1); num_refs = btrfs_extent_data_ref_count(leaf, ref1);
} else { } else {
@ -1583,6 +1647,7 @@ int lookup_inline_extent_backref(struct btrfs_trans_handle *trans,
int ret; int ret;
int err = 0; int err = 0;
bool skinny_metadata = btrfs_fs_incompat(fs_info, SKINNY_METADATA); bool skinny_metadata = btrfs_fs_incompat(fs_info, SKINNY_METADATA);
int needed;
key.objectid = bytenr; key.objectid = bytenr;
key.type = BTRFS_EXTENT_ITEM_KEY; key.type = BTRFS_EXTENT_ITEM_KEY;
@ -1674,6 +1739,11 @@ again:
BUG_ON(ptr > end); BUG_ON(ptr > end);
} }
if (owner >= BTRFS_FIRST_FREE_OBJECTID)
needed = BTRFS_REF_TYPE_DATA;
else
needed = BTRFS_REF_TYPE_BLOCK;
err = -ENOENT; err = -ENOENT;
while (1) { while (1) {
if (ptr >= end) { if (ptr >= end) {
@ -1681,7 +1751,12 @@ again:
break; break;
} }
iref = (struct btrfs_extent_inline_ref *)ptr; iref = (struct btrfs_extent_inline_ref *)ptr;
type = btrfs_extent_inline_ref_type(leaf, iref); type = btrfs_get_extent_inline_ref_type(leaf, iref, needed);
if (type == BTRFS_REF_TYPE_INVALID) {
err = -EINVAL;
goto out;
}
if (want < type) if (want < type)
break; break;
if (want > type) { if (want > type) {
@ -1873,7 +1948,12 @@ void update_inline_extent_backref(struct btrfs_fs_info *fs_info,
if (extent_op) if (extent_op)
__run_delayed_extent_op(extent_op, leaf, ei); __run_delayed_extent_op(extent_op, leaf, ei);
type = btrfs_extent_inline_ref_type(leaf, iref); /*
* If type is invalid, we should have bailed out after
* lookup_inline_extent_backref().
*/
type = btrfs_get_extent_inline_ref_type(leaf, iref, BTRFS_REF_TYPE_ANY);
ASSERT(type != BTRFS_REF_TYPE_INVALID);
if (type == BTRFS_EXTENT_DATA_REF_KEY) { if (type == BTRFS_EXTENT_DATA_REF_KEY) {
dref = (struct btrfs_extent_data_ref *)(&iref->offset); dref = (struct btrfs_extent_data_ref *)(&iref->offset);
@ -3158,6 +3238,7 @@ static noinline int check_committed_ref(struct btrfs_root *root,
struct btrfs_extent_item *ei; struct btrfs_extent_item *ei;
struct btrfs_key key; struct btrfs_key key;
u32 item_size; u32 item_size;
int type;
int ret; int ret;
key.objectid = bytenr; key.objectid = bytenr;
@ -3199,8 +3280,9 @@ static noinline int check_committed_ref(struct btrfs_root *root,
goto out; goto out;
iref = (struct btrfs_extent_inline_ref *)(ei + 1); iref = (struct btrfs_extent_inline_ref *)(ei + 1);
if (btrfs_extent_inline_ref_type(leaf, iref) !=
BTRFS_EXTENT_DATA_REF_KEY) type = btrfs_get_extent_inline_ref_type(leaf, iref, BTRFS_REF_TYPE_DATA);
if (type != BTRFS_EXTENT_DATA_REF_KEY)
goto out; goto out;
ref = (struct btrfs_extent_data_ref *)(&iref->offset); ref = (struct btrfs_extent_data_ref *)(&iref->offset);
@ -4199,9 +4281,9 @@ static u64 btrfs_space_info_used(struct btrfs_space_info *s_info,
int btrfs_alloc_data_chunk_ondemand(struct btrfs_inode *inode, u64 bytes) int btrfs_alloc_data_chunk_ondemand(struct btrfs_inode *inode, u64 bytes)
{ {
struct btrfs_space_info *data_sinfo;
struct btrfs_root *root = inode->root; struct btrfs_root *root = inode->root;
struct btrfs_fs_info *fs_info = root->fs_info; struct btrfs_fs_info *fs_info = root->fs_info;
struct btrfs_space_info *data_sinfo = fs_info->data_sinfo;
u64 used; u64 used;
int ret = 0; int ret = 0;
int need_commit = 2; int need_commit = 2;
@ -4215,10 +4297,6 @@ int btrfs_alloc_data_chunk_ondemand(struct btrfs_inode *inode, u64 bytes)
ASSERT(current->journal_info); ASSERT(current->journal_info);
} }
data_sinfo = fs_info->data_sinfo;
if (!data_sinfo)
goto alloc;
again: again:
/* make sure we have enough space to handle the data first */ /* make sure we have enough space to handle the data first */
spin_lock(&data_sinfo->lock); spin_lock(&data_sinfo->lock);
@ -4236,7 +4314,7 @@ again:
data_sinfo->force_alloc = CHUNK_ALLOC_FORCE; data_sinfo->force_alloc = CHUNK_ALLOC_FORCE;
spin_unlock(&data_sinfo->lock); spin_unlock(&data_sinfo->lock);
alloc:
alloc_target = btrfs_data_alloc_profile(fs_info); alloc_target = btrfs_data_alloc_profile(fs_info);
/* /*
* It is ugly that we don't call nolock join * It is ugly that we don't call nolock join
@ -4264,9 +4342,6 @@ alloc:
} }
} }
if (!data_sinfo)
data_sinfo = fs_info->data_sinfo;
goto again; goto again;
} }
@ -4425,8 +4500,7 @@ static int should_alloc_chunk(struct btrfs_fs_info *fs_info,
struct btrfs_space_info *sinfo, int force) struct btrfs_space_info *sinfo, int force)
{ {
struct btrfs_block_rsv *global_rsv = &fs_info->global_block_rsv; struct btrfs_block_rsv *global_rsv = &fs_info->global_block_rsv;
u64 num_bytes = sinfo->total_bytes - sinfo->bytes_readonly; u64 bytes_used = btrfs_space_info_used(sinfo, false);
u64 num_allocated = sinfo->bytes_used + sinfo->bytes_reserved;
u64 thresh; u64 thresh;
if (force == CHUNK_ALLOC_FORCE) if (force == CHUNK_ALLOC_FORCE)
@ -4438,7 +4512,7 @@ static int should_alloc_chunk(struct btrfs_fs_info *fs_info,
* global_rsv, it doesn't change except when the transaction commits. * global_rsv, it doesn't change except when the transaction commits.
*/ */
if (sinfo->flags & BTRFS_BLOCK_GROUP_METADATA) if (sinfo->flags & BTRFS_BLOCK_GROUP_METADATA)
num_allocated += calc_global_rsv_need_space(global_rsv); bytes_used += calc_global_rsv_need_space(global_rsv);
/* /*
* in limited mode, we want to have some free space up to * in limited mode, we want to have some free space up to
@ -4448,11 +4522,11 @@ static int should_alloc_chunk(struct btrfs_fs_info *fs_info,
thresh = btrfs_super_total_bytes(fs_info->super_copy); thresh = btrfs_super_total_bytes(fs_info->super_copy);
thresh = max_t(u64, SZ_64M, div_factor_fine(thresh, 1)); thresh = max_t(u64, SZ_64M, div_factor_fine(thresh, 1));
if (num_bytes - num_allocated < thresh) if (sinfo->total_bytes - bytes_used < thresh)
return 1; return 1;
} }
if (num_allocated + SZ_2M < div_factor(num_bytes, 8)) if (bytes_used + SZ_2M < div_factor(sinfo->total_bytes, 8))
return 0; return 0;
return 1; return 1;
} }
@ -4904,9 +4978,14 @@ struct reserve_ticket {
wait_queue_head_t wait; wait_queue_head_t wait;
}; };
static int flush_space(struct btrfs_fs_info *fs_info, /*
* Try to flush some data based on policy set by @state. This is only advisory
* and may fail for various reasons. The caller is supposed to examine the
* state of @space_info to detect the outcome.
*/
static void flush_space(struct btrfs_fs_info *fs_info,
struct btrfs_space_info *space_info, u64 num_bytes, struct btrfs_space_info *space_info, u64 num_bytes,
u64 orig_bytes, int state) int state)
{ {
struct btrfs_root *root = fs_info->extent_root; struct btrfs_root *root = fs_info->extent_root;
struct btrfs_trans_handle *trans; struct btrfs_trans_handle *trans;
@ -4931,7 +5010,7 @@ static int flush_space(struct btrfs_fs_info *fs_info,
break; break;
case FLUSH_DELALLOC: case FLUSH_DELALLOC:
case FLUSH_DELALLOC_WAIT: case FLUSH_DELALLOC_WAIT:
shrink_delalloc(fs_info, num_bytes * 2, orig_bytes, shrink_delalloc(fs_info, num_bytes * 2, num_bytes,
state == FLUSH_DELALLOC_WAIT); state == FLUSH_DELALLOC_WAIT);
break; break;
case ALLOC_CHUNK: case ALLOC_CHUNK:
@ -4949,16 +5028,16 @@ static int flush_space(struct btrfs_fs_info *fs_info,
break; break;
case COMMIT_TRANS: case COMMIT_TRANS:
ret = may_commit_transaction(fs_info, space_info, ret = may_commit_transaction(fs_info, space_info,
orig_bytes, 0); num_bytes, 0);
break; break;
default: default:
ret = -ENOSPC; ret = -ENOSPC;
break; break;
} }
trace_btrfs_flush_space(fs_info, space_info->flags, num_bytes, trace_btrfs_flush_space(fs_info, space_info->flags, num_bytes, state,
orig_bytes, state, ret); ret);
return ret; return;
} }
static inline u64 static inline u64
@ -5060,11 +5139,7 @@ static void btrfs_async_reclaim_metadata_space(struct work_struct *work)
flush_state = FLUSH_DELAYED_ITEMS_NR; flush_state = FLUSH_DELAYED_ITEMS_NR;
do { do {
struct reserve_ticket *ticket; flush_space(fs_info, space_info, to_reclaim, flush_state);
int ret;
ret = flush_space(fs_info, space_info, to_reclaim, to_reclaim,
flush_state);
spin_lock(&space_info->lock); spin_lock(&space_info->lock);
if (list_empty(&space_info->tickets)) { if (list_empty(&space_info->tickets)) {
space_info->flush = 0; space_info->flush = 0;
@ -5074,8 +5149,6 @@ static void btrfs_async_reclaim_metadata_space(struct work_struct *work)
to_reclaim = btrfs_calc_reclaim_metadata_size(fs_info, to_reclaim = btrfs_calc_reclaim_metadata_size(fs_info,
space_info, space_info,
false); false);
ticket = list_first_entry(&space_info->tickets,
struct reserve_ticket, list);
if (last_tickets_id == space_info->tickets_id) { if (last_tickets_id == space_info->tickets_id) {
flush_state++; flush_state++;
} else { } else {
@ -5120,8 +5193,7 @@ static void priority_reclaim_metadata_space(struct btrfs_fs_info *fs_info,
spin_unlock(&space_info->lock); spin_unlock(&space_info->lock);
do { do {
flush_space(fs_info, space_info, to_reclaim, to_reclaim, flush_space(fs_info, space_info, to_reclaim, flush_state);
flush_state);
flush_state++; flush_state++;
spin_lock(&space_info->lock); spin_lock(&space_info->lock);
if (ticket->bytes == 0) { if (ticket->bytes == 0) {
@ -6664,19 +6736,20 @@ fetch_cluster_info(struct btrfs_fs_info *fs_info,
struct btrfs_space_info *space_info, u64 *empty_cluster) struct btrfs_space_info *space_info, u64 *empty_cluster)
{ {
struct btrfs_free_cluster *ret = NULL; struct btrfs_free_cluster *ret = NULL;
bool ssd = btrfs_test_opt(fs_info, SSD);
*empty_cluster = 0; *empty_cluster = 0;
if (btrfs_mixed_space_info(space_info)) if (btrfs_mixed_space_info(space_info))
return ret; return ret;
if (ssd)
*empty_cluster = SZ_2M;
if (space_info->flags & BTRFS_BLOCK_GROUP_METADATA) { if (space_info->flags & BTRFS_BLOCK_GROUP_METADATA) {
ret = &fs_info->meta_alloc_cluster; ret = &fs_info->meta_alloc_cluster;
if (!ssd) if (btrfs_test_opt(fs_info, SSD))
*empty_cluster = SZ_2M;
else
*empty_cluster = SZ_64K; *empty_cluster = SZ_64K;
} else if ((space_info->flags & BTRFS_BLOCK_GROUP_DATA) && ssd) { } else if ((space_info->flags & BTRFS_BLOCK_GROUP_DATA) &&
btrfs_test_opt(fs_info, SSD_SPREAD)) {
*empty_cluster = SZ_2M;
ret = &fs_info->data_alloc_cluster; ret = &fs_info->data_alloc_cluster;
} }
@ -6755,7 +6828,7 @@ static int unpin_extent_range(struct btrfs_fs_info *fs_info,
if (!readonly && return_free_space && if (!readonly && return_free_space &&
global_rsv->space_info == space_info) { global_rsv->space_info == space_info) {
u64 to_add = len; u64 to_add = len;
WARN_ON(!return_free_space);
spin_lock(&global_rsv->lock); spin_lock(&global_rsv->lock);
if (!global_rsv->full) { if (!global_rsv->full) {
to_add = min(len, global_rsv->size - to_add = min(len, global_rsv->size -
@ -6841,7 +6914,7 @@ int btrfs_finish_extent_commit(struct btrfs_trans_handle *trans,
if (ret) { if (ret) {
const char *errstr = btrfs_decode_error(ret); const char *errstr = btrfs_decode_error(ret);
btrfs_warn(fs_info, btrfs_warn(fs_info,
"Discard failed while removing blockgroup: errno=%d %s\n", "discard failed while removing blockgroup: errno=%d %s",
ret, errstr); ret, errstr);
} }
} }
@ -6969,7 +7042,7 @@ static int __btrfs_free_extent(struct btrfs_trans_handle *trans,
"umm, got %d back from search, was looking for %llu", "umm, got %d back from search, was looking for %llu",
ret, bytenr); ret, bytenr);
if (ret > 0) if (ret > 0)
btrfs_print_leaf(info, path->nodes[0]); btrfs_print_leaf(path->nodes[0]);
} }
if (ret < 0) { if (ret < 0) {
btrfs_abort_transaction(trans, ret); btrfs_abort_transaction(trans, ret);
@ -6978,7 +7051,7 @@ static int __btrfs_free_extent(struct btrfs_trans_handle *trans,
extent_slot = path->slots[0]; extent_slot = path->slots[0];
} }
} else if (WARN_ON(ret == -ENOENT)) { } else if (WARN_ON(ret == -ENOENT)) {
btrfs_print_leaf(info, path->nodes[0]); btrfs_print_leaf(path->nodes[0]);
btrfs_err(info, btrfs_err(info,
"unable to find ref byte nr %llu parent %llu root %llu owner %llu offset %llu", "unable to find ref byte nr %llu parent %llu root %llu owner %llu offset %llu",
bytenr, parent, root_objectid, owner_objectid, bytenr, parent, root_objectid, owner_objectid,
@ -7015,7 +7088,7 @@ static int __btrfs_free_extent(struct btrfs_trans_handle *trans,
btrfs_err(info, btrfs_err(info,
"umm, got %d back from search, was looking for %llu", "umm, got %d back from search, was looking for %llu",
ret, bytenr); ret, bytenr);
btrfs_print_leaf(info, path->nodes[0]); btrfs_print_leaf(path->nodes[0]);
} }
if (ret < 0) { if (ret < 0) {
btrfs_abort_transaction(trans, ret); btrfs_abort_transaction(trans, ret);
@ -9193,7 +9266,7 @@ int btrfs_drop_snapshot(struct btrfs_root *root,
if (err) if (err)
goto out_end_trans; goto out_end_trans;
ret = btrfs_del_root(trans, tree_root, &root->root_key); ret = btrfs_del_root(trans, fs_info, &root->root_key);
if (ret) { if (ret) {
btrfs_abort_transaction(trans, ret); btrfs_abort_transaction(trans, ret);
goto out_end_trans; goto out_end_trans;
@ -9952,11 +10025,8 @@ btrfs_create_block_group_cache(struct btrfs_fs_info *fs_info,
cache->key.offset = size; cache->key.offset = size;
cache->key.type = BTRFS_BLOCK_GROUP_ITEM_KEY; cache->key.type = BTRFS_BLOCK_GROUP_ITEM_KEY;
cache->sectorsize = fs_info->sectorsize;
cache->fs_info = fs_info; cache->fs_info = fs_info;
cache->full_stripe_len = btrfs_full_stripe_len(fs_info, cache->full_stripe_len = btrfs_full_stripe_len(fs_info, start);
&fs_info->mapping_tree,
start);
set_free_space_tree_thresholds(cache); set_free_space_tree_thresholds(cache);
atomic_set(&cache->count, 1); atomic_set(&cache->count, 1);
@ -10192,8 +10262,7 @@ next:
int btrfs_make_block_group(struct btrfs_trans_handle *trans, int btrfs_make_block_group(struct btrfs_trans_handle *trans,
struct btrfs_fs_info *fs_info, u64 bytes_used, struct btrfs_fs_info *fs_info, u64 bytes_used,
u64 type, u64 chunk_objectid, u64 chunk_offset, u64 type, u64 chunk_offset, u64 size)
u64 size)
{ {
struct btrfs_block_group_cache *cache; struct btrfs_block_group_cache *cache;
int ret; int ret;
@ -10205,7 +10274,8 @@ int btrfs_make_block_group(struct btrfs_trans_handle *trans,
return -ENOMEM; return -ENOMEM;
btrfs_set_block_group_used(&cache->item, bytes_used); btrfs_set_block_group_used(&cache->item, bytes_used);
btrfs_set_block_group_chunk_objectid(&cache->item, chunk_objectid); btrfs_set_block_group_chunk_objectid(&cache->item,
BTRFS_FIRST_CHUNK_TREE_OBJECTID);
btrfs_set_block_group_flags(&cache->item, type); btrfs_set_block_group_flags(&cache->item, type);
cache->flags = type; cache->flags = type;
@ -11001,14 +11071,14 @@ int btrfs_trim_fs(struct btrfs_fs_info *fs_info, struct fstrim_range *range)
} }
/* /*
* btrfs_{start,end}_write_no_snapshoting() are similar to * btrfs_{start,end}_write_no_snapshotting() are similar to
* mnt_{want,drop}_write(), they are used to prevent some tasks from writing * mnt_{want,drop}_write(), they are used to prevent some tasks from writing
* data into the page cache through nocow before the subvolume is snapshoted, * data into the page cache through nocow before the subvolume is snapshoted,
* but flush the data into disk after the snapshot creation, or to prevent * but flush the data into disk after the snapshot creation, or to prevent
* operations while snapshoting is ongoing and that cause the snapshot to be * operations while snapshotting is ongoing and that cause the snapshot to be
* inconsistent (writes followed by expanding truncates for example). * inconsistent (writes followed by expanding truncates for example).
*/ */
void btrfs_end_write_no_snapshoting(struct btrfs_root *root) void btrfs_end_write_no_snapshotting(struct btrfs_root *root)
{ {
percpu_counter_dec(&root->subv_writers->counter); percpu_counter_dec(&root->subv_writers->counter);
/* /*
@ -11019,9 +11089,9 @@ void btrfs_end_write_no_snapshoting(struct btrfs_root *root)
wake_up(&root->subv_writers->wait); wake_up(&root->subv_writers->wait);
} }
int btrfs_start_write_no_snapshoting(struct btrfs_root *root) int btrfs_start_write_no_snapshotting(struct btrfs_root *root)
{ {
if (atomic_read(&root->will_be_snapshoted)) if (atomic_read(&root->will_be_snapshotted))
return 0; return 0;
percpu_counter_inc(&root->subv_writers->counter); percpu_counter_inc(&root->subv_writers->counter);
@ -11029,14 +11099,14 @@ int btrfs_start_write_no_snapshoting(struct btrfs_root *root)
* Make sure counter is updated before we check for snapshot creation. * Make sure counter is updated before we check for snapshot creation.
*/ */
smp_mb(); smp_mb();
if (atomic_read(&root->will_be_snapshoted)) { if (atomic_read(&root->will_be_snapshotted)) {
btrfs_end_write_no_snapshoting(root); btrfs_end_write_no_snapshotting(root);
return 0; return 0;
} }
return 1; return 1;
} }
static int wait_snapshoting_atomic_t(atomic_t *a) static int wait_snapshotting_atomic_t(atomic_t *a)
{ {
schedule(); schedule();
return 0; return 0;
@ -11047,11 +11117,11 @@ void btrfs_wait_for_snapshot_creation(struct btrfs_root *root)
while (true) { while (true) {
int ret; int ret;
ret = btrfs_start_write_no_snapshoting(root); ret = btrfs_start_write_no_snapshotting(root);
if (ret) if (ret)
break; break;
wait_on_atomic_t(&root->will_be_snapshoted, wait_on_atomic_t(&root->will_be_snapshotted,
wait_snapshoting_atomic_t, wait_snapshotting_atomic_t,
TASK_UNINTERRUPTIBLE); TASK_UNINTERRUPTIBLE);
} }
} }

View File

@ -20,7 +20,6 @@
#include "locking.h" #include "locking.h"
#include "rcu-string.h" #include "rcu-string.h"
#include "backref.h" #include "backref.h"
#include "transaction.h"
static struct kmem_cache *extent_state_cache; static struct kmem_cache *extent_state_cache;
static struct kmem_cache *extent_buffer_cache; static struct kmem_cache *extent_buffer_cache;
@ -1998,7 +1997,7 @@ int repair_io_failure(struct btrfs_fs_info *fs_info, u64 ino, u64 start,
* read repair operation. * read repair operation.
*/ */
btrfs_bio_counter_inc_blocked(fs_info); btrfs_bio_counter_inc_blocked(fs_info);
if (btrfs_is_parity_mirror(fs_info, logical, length, mirror_num)) { if (btrfs_is_parity_mirror(fs_info, logical, length)) {
/* /*
* Note that we don't use BTRFS_MAP_WRITE because it's supposed * Note that we don't use BTRFS_MAP_WRITE because it's supposed
* to update all raid stripes, but here we just want to correct * to update all raid stripes, but here we just want to correct
@ -2757,7 +2756,10 @@ static int merge_bio(struct extent_io_tree *tree, struct page *page,
} }
static int submit_extent_page(int op, int op_flags, struct extent_io_tree *tree, /*
* @opf: bio REQ_OP_* and REQ_* flags as one value
*/
static int submit_extent_page(unsigned int opf, struct extent_io_tree *tree,
struct writeback_control *wbc, struct writeback_control *wbc,
struct page *page, sector_t sector, struct page *page, sector_t sector,
size_t size, unsigned long offset, size_t size, unsigned long offset,
@ -2804,7 +2806,7 @@ static int submit_extent_page(int op, int op_flags, struct extent_io_tree *tree,
bio->bi_end_io = end_io_func; bio->bi_end_io = end_io_func;
bio->bi_private = tree; bio->bi_private = tree;
bio->bi_write_hint = page->mapping->host->i_write_hint; bio->bi_write_hint = page->mapping->host->i_write_hint;
bio_set_op_attrs(bio, op, op_flags); bio->bi_opf = opf;
if (wbc) { if (wbc) {
wbc_init_bio(wbc, bio); wbc_init_bio(wbc, bio);
wbc_account_io(wbc, page, page_size); wbc_account_io(wbc, page, page_size);
@ -2878,7 +2880,7 @@ static int __do_readpage(struct extent_io_tree *tree,
get_extent_t *get_extent, get_extent_t *get_extent,
struct extent_map **em_cached, struct extent_map **em_cached,
struct bio **bio, int mirror_num, struct bio **bio, int mirror_num,
unsigned long *bio_flags, int read_flags, unsigned long *bio_flags, unsigned int read_flags,
u64 *prev_em_start) u64 *prev_em_start)
{ {
struct inode *inode = page->mapping->host; struct inode *inode = page->mapping->host;
@ -3059,7 +3061,7 @@ static int __do_readpage(struct extent_io_tree *tree,
continue; continue;
} }
ret = submit_extent_page(REQ_OP_READ, read_flags, tree, NULL, ret = submit_extent_page(REQ_OP_READ | read_flags, tree, NULL,
page, sector, disk_io_size, pg_offset, page, sector, disk_io_size, pg_offset,
bdev, bio, bdev, bio,
end_bio_extent_readpage, mirror_num, end_bio_extent_readpage, mirror_num,
@ -3164,7 +3166,8 @@ static int __extent_read_full_page(struct extent_io_tree *tree,
struct page *page, struct page *page,
get_extent_t *get_extent, get_extent_t *get_extent,
struct bio **bio, int mirror_num, struct bio **bio, int mirror_num,
unsigned long *bio_flags, int read_flags) unsigned long *bio_flags,
unsigned int read_flags)
{ {
struct inode *inode = page->mapping->host; struct inode *inode = page->mapping->host;
struct btrfs_ordered_extent *ordered; struct btrfs_ordered_extent *ordered;
@ -3311,7 +3314,7 @@ static noinline_for_stack int __extent_writepage_io(struct inode *inode,
struct extent_page_data *epd, struct extent_page_data *epd,
loff_t i_size, loff_t i_size,
unsigned long nr_written, unsigned long nr_written,
int write_flags, int *nr_ret) unsigned int write_flags, int *nr_ret)
{ {
struct extent_io_tree *tree = epd->tree; struct extent_io_tree *tree = epd->tree;
u64 start = page_offset(page); u64 start = page_offset(page);
@ -3427,7 +3430,7 @@ static noinline_for_stack int __extent_writepage_io(struct inode *inode,
page->index, cur, end); page->index, cur, end);
} }
ret = submit_extent_page(REQ_OP_WRITE, write_flags, tree, wbc, ret = submit_extent_page(REQ_OP_WRITE | write_flags, tree, wbc,
page, sector, iosize, pg_offset, page, sector, iosize, pg_offset,
bdev, &epd->bio, bdev, &epd->bio,
end_bio_extent_writepage, end_bio_extent_writepage,
@ -3465,7 +3468,7 @@ static int __extent_writepage(struct page *page, struct writeback_control *wbc,
size_t pg_offset = 0; size_t pg_offset = 0;
loff_t i_size = i_size_read(inode); loff_t i_size = i_size_read(inode);
unsigned long end_index = i_size >> PAGE_SHIFT; unsigned long end_index = i_size >> PAGE_SHIFT;
int write_flags = 0; unsigned int write_flags = 0;
unsigned long nr_written = 0; unsigned long nr_written = 0;
if (wbc->sync_mode == WB_SYNC_ALL) if (wbc->sync_mode == WB_SYNC_ALL)
@ -3715,7 +3718,7 @@ static noinline_for_stack int write_one_eb(struct extent_buffer *eb,
unsigned long i, num_pages; unsigned long i, num_pages;
unsigned long bio_flags = 0; unsigned long bio_flags = 0;
unsigned long start, end; unsigned long start, end;
int write_flags = (epd->sync_io ? REQ_SYNC : 0) | REQ_META; unsigned int write_flags = (epd->sync_io ? REQ_SYNC : 0) | REQ_META;
int ret = 0; int ret = 0;
clear_bit(EXTENT_BUFFER_WRITE_ERR, &eb->bflags); clear_bit(EXTENT_BUFFER_WRITE_ERR, &eb->bflags);
@ -3745,7 +3748,7 @@ static noinline_for_stack int write_one_eb(struct extent_buffer *eb,
clear_page_dirty_for_io(p); clear_page_dirty_for_io(p);
set_page_writeback(p); set_page_writeback(p);
ret = submit_extent_page(REQ_OP_WRITE, write_flags, tree, wbc, ret = submit_extent_page(REQ_OP_WRITE | write_flags, tree, wbc,
p, offset >> 9, PAGE_SIZE, 0, bdev, p, offset >> 9, PAGE_SIZE, 0, bdev,
&epd->bio, &epd->bio,
end_bio_extent_buffer_writepage, end_bio_extent_buffer_writepage,
@ -4606,24 +4609,11 @@ int extent_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
flags |= (FIEMAP_EXTENT_DELALLOC | flags |= (FIEMAP_EXTENT_DELALLOC |
FIEMAP_EXTENT_UNKNOWN); FIEMAP_EXTENT_UNKNOWN);
} else if (fieinfo->fi_extents_max) { } else if (fieinfo->fi_extents_max) {
struct btrfs_trans_handle *trans;
u64 bytenr = em->block_start - u64 bytenr = em->block_start -
(em->start - em->orig_start); (em->start - em->orig_start);
disko = em->block_start + offset_in_extent; disko = em->block_start + offset_in_extent;
/*
* We need a trans handle to get delayed refs
*/
trans = btrfs_join_transaction(root);
/*
* It's OK if we can't start a trans we can still check
* from commit_root
*/
if (IS_ERR(trans))
trans = NULL;
/* /*
* As btrfs supports shared space, this information * As btrfs supports shared space, this information
* can be exported to userspace tools via * can be exported to userspace tools via
@ -4631,11 +4621,9 @@ int extent_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
* then we're just getting a count and we can skip the * then we're just getting a count and we can skip the
* lookup stuff. * lookup stuff.
*/ */
ret = btrfs_check_shared(trans, root->fs_info, ret = btrfs_check_shared(root,
root->objectid, btrfs_ino(BTRFS_I(inode)),
btrfs_ino(BTRFS_I(inode)), bytenr); bytenr);
if (trans)
btrfs_end_transaction(trans);
if (ret < 0) if (ret < 0)
goto out_free; goto out_free;
if (ret) if (ret)
@ -5405,9 +5393,8 @@ unlock_exit:
return ret; return ret;
} }
void read_extent_buffer(struct extent_buffer *eb, void *dstv, void read_extent_buffer(const struct extent_buffer *eb, void *dstv,
unsigned long start, unsigned long start, unsigned long len)
unsigned long len)
{ {
size_t cur; size_t cur;
size_t offset; size_t offset;
@ -5417,8 +5404,12 @@ void read_extent_buffer(struct extent_buffer *eb, void *dstv,
size_t start_offset = eb->start & ((u64)PAGE_SIZE - 1); size_t start_offset = eb->start & ((u64)PAGE_SIZE - 1);
unsigned long i = (start_offset + start) >> PAGE_SHIFT; unsigned long i = (start_offset + start) >> PAGE_SHIFT;
WARN_ON(start > eb->len); if (start + len > eb->len) {
WARN_ON(start + len > eb->start + eb->len); WARN(1, KERN_ERR "btrfs bad mapping eb start %llu len %lu, wanted %lu %lu\n",
eb->start, eb->len, start, len);
memset(dst, 0, len);
return;
}
offset = (start_offset + start) & (PAGE_SIZE - 1); offset = (start_offset + start) & (PAGE_SIZE - 1);
@ -5436,9 +5427,9 @@ void read_extent_buffer(struct extent_buffer *eb, void *dstv,
} }
} }
int read_extent_buffer_to_user(struct extent_buffer *eb, void __user *dstv, int read_extent_buffer_to_user(const struct extent_buffer *eb,
unsigned long start, void __user *dstv,
unsigned long len) unsigned long start, unsigned long len)
{ {
size_t cur; size_t cur;
size_t offset; size_t offset;
@ -5478,10 +5469,10 @@ int read_extent_buffer_to_user(struct extent_buffer *eb, void __user *dstv,
* return 1 if the item spans two pages. * return 1 if the item spans two pages.
* return -EINVAL otherwise. * return -EINVAL otherwise.
*/ */
int map_private_extent_buffer(struct extent_buffer *eb, unsigned long start, int map_private_extent_buffer(const struct extent_buffer *eb,
unsigned long min_len, char **map, unsigned long start, unsigned long min_len,
unsigned long *map_start, char **map, unsigned long *map_start,
unsigned long *map_len) unsigned long *map_len)
{ {
size_t offset = start & (PAGE_SIZE - 1); size_t offset = start & (PAGE_SIZE - 1);
char *kaddr; char *kaddr;
@ -5491,6 +5482,12 @@ int map_private_extent_buffer(struct extent_buffer *eb, unsigned long start,
unsigned long end_i = (start_offset + start + min_len - 1) >> unsigned long end_i = (start_offset + start + min_len - 1) >>
PAGE_SHIFT; PAGE_SHIFT;
if (start + min_len > eb->len) {
WARN(1, KERN_ERR "btrfs bad mapping eb start %llu len %lu, wanted %lu %lu\n",
eb->start, eb->len, start, min_len);
return -EINVAL;
}
if (i != end_i) if (i != end_i)
return 1; return 1;
@ -5502,12 +5499,6 @@ int map_private_extent_buffer(struct extent_buffer *eb, unsigned long start,
*map_start = ((u64)i << PAGE_SHIFT) - start_offset; *map_start = ((u64)i << PAGE_SHIFT) - start_offset;
} }
if (start + min_len > eb->len) {
WARN(1, KERN_ERR "btrfs bad mapping eb start %llu len %lu, wanted %lu %lu\n",
eb->start, eb->len, start, min_len);
return -EINVAL;
}
p = eb->pages[i]; p = eb->pages[i];
kaddr = page_address(p); kaddr = page_address(p);
*map = kaddr + offset; *map = kaddr + offset;
@ -5515,9 +5506,8 @@ int map_private_extent_buffer(struct extent_buffer *eb, unsigned long start,
return 0; return 0;
} }
int memcmp_extent_buffer(struct extent_buffer *eb, const void *ptrv, int memcmp_extent_buffer(const struct extent_buffer *eb, const void *ptrv,
unsigned long start, unsigned long start, unsigned long len)
unsigned long len)
{ {
size_t cur; size_t cur;
size_t offset; size_t offset;

View File

@ -449,14 +449,13 @@ static inline void extent_buffer_get(struct extent_buffer *eb)
atomic_inc(&eb->refs); atomic_inc(&eb->refs);
} }
int memcmp_extent_buffer(struct extent_buffer *eb, const void *ptrv, int memcmp_extent_buffer(const struct extent_buffer *eb, const void *ptrv,
unsigned long start, unsigned long start, unsigned long len);
unsigned long len); void read_extent_buffer(const struct extent_buffer *eb, void *dst,
void read_extent_buffer(struct extent_buffer *eb, void *dst,
unsigned long start, unsigned long start,
unsigned long len); unsigned long len);
int read_extent_buffer_to_user(struct extent_buffer *eb, void __user *dst, int read_extent_buffer_to_user(const struct extent_buffer *eb,
unsigned long start, void __user *dst, unsigned long start,
unsigned long len); unsigned long len);
void write_extent_buffer_fsid(struct extent_buffer *eb, const void *src); void write_extent_buffer_fsid(struct extent_buffer *eb, const void *src);
void write_extent_buffer_chunk_tree_uuid(struct extent_buffer *eb, void write_extent_buffer_chunk_tree_uuid(struct extent_buffer *eb,
@ -486,10 +485,10 @@ void set_extent_buffer_uptodate(struct extent_buffer *eb);
void clear_extent_buffer_uptodate(struct extent_buffer *eb); void clear_extent_buffer_uptodate(struct extent_buffer *eb);
int extent_buffer_uptodate(struct extent_buffer *eb); int extent_buffer_uptodate(struct extent_buffer *eb);
int extent_buffer_under_io(struct extent_buffer *eb); int extent_buffer_under_io(struct extent_buffer *eb);
int map_private_extent_buffer(struct extent_buffer *eb, unsigned long offset, int map_private_extent_buffer(const struct extent_buffer *eb,
unsigned long min_len, char **map, unsigned long offset, unsigned long min_len,
unsigned long *map_start, char **map, unsigned long *map_start,
unsigned long *map_len); unsigned long *map_len);
void extent_range_clear_dirty_for_io(struct inode *inode, u64 start, u64 end); void extent_range_clear_dirty_for_io(struct inode *inode, u64 start, u64 end);
void extent_range_redirty_for_io(struct inode *inode, u64 start, u64 end); void extent_range_redirty_for_io(struct inode *inode, u64 start, u64 end);
void extent_clear_unlock_delalloc(struct inode *inode, u64 start, u64 end, void extent_clear_unlock_delalloc(struct inode *inode, u64 start, u64 end,

View File

@ -1536,7 +1536,7 @@ static noinline int check_can_nocow(struct btrfs_inode *inode, loff_t pos,
u64 num_bytes; u64 num_bytes;
int ret; int ret;
ret = btrfs_start_write_no_snapshoting(root); ret = btrfs_start_write_no_snapshotting(root);
if (!ret) if (!ret)
return -ENOSPC; return -ENOSPC;
@ -1561,7 +1561,7 @@ static noinline int check_can_nocow(struct btrfs_inode *inode, loff_t pos,
NULL, NULL, NULL); NULL, NULL, NULL);
if (ret <= 0) { if (ret <= 0) {
ret = 0; ret = 0;
btrfs_end_write_no_snapshoting(root); btrfs_end_write_no_snapshotting(root);
} else { } else {
*write_bytes = min_t(size_t, *write_bytes , *write_bytes = min_t(size_t, *write_bytes ,
num_bytes - pos + lockstart); num_bytes - pos + lockstart);
@ -1664,7 +1664,7 @@ static noinline ssize_t __btrfs_buffered_write(struct file *file,
data_reserved, pos, data_reserved, pos,
write_bytes); write_bytes);
else else
btrfs_end_write_no_snapshoting(root); btrfs_end_write_no_snapshotting(root);
break; break;
} }
@ -1767,7 +1767,7 @@ again:
release_bytes = 0; release_bytes = 0;
if (only_release_metadata) if (only_release_metadata)
btrfs_end_write_no_snapshoting(root); btrfs_end_write_no_snapshotting(root);
if (only_release_metadata && copied > 0) { if (only_release_metadata && copied > 0) {
lockstart = round_down(pos, lockstart = round_down(pos,
@ -1797,7 +1797,7 @@ again:
if (release_bytes) { if (release_bytes) {
if (only_release_metadata) { if (only_release_metadata) {
btrfs_end_write_no_snapshoting(root); btrfs_end_write_no_snapshotting(root);
btrfs_delalloc_release_metadata(BTRFS_I(inode), btrfs_delalloc_release_metadata(BTRFS_I(inode),
release_bytes); release_bytes);
} else { } else {
@ -1990,8 +1990,15 @@ out:
int btrfs_release_file(struct inode *inode, struct file *filp) int btrfs_release_file(struct inode *inode, struct file *filp)
{ {
if (filp->private_data) struct btrfs_file_private *private = filp->private_data;
if (private && private->trans)
btrfs_ioctl_trans_end(filp); btrfs_ioctl_trans_end(filp);
if (private && private->filldir_buf)
kfree(private->filldir_buf);
kfree(private);
filp->private_data = NULL;
/* /*
* ordered_data_close is set by settattr when we are about to truncate * ordered_data_close is set by settattr when we are about to truncate
* a file from a non-zero size to a zero size. This tries to * a file from a non-zero size to a zero size. This tries to

View File

@ -709,7 +709,7 @@ static int __load_free_space_cache(struct btrfs_root *root, struct inode *inode,
if (!BTRFS_I(inode)->generation) { if (!BTRFS_I(inode)->generation) {
btrfs_info(fs_info, btrfs_info(fs_info,
"The free space cache file (%llu) is invalid. skip it\n", "the free space cache file (%llu) is invalid, skip it",
offset); offset);
return 0; return 0;
} }

View File

@ -1257,7 +1257,7 @@ int btrfs_clear_free_space_tree(struct btrfs_fs_info *fs_info)
if (ret) if (ret)
goto abort; goto abort;
ret = btrfs_del_root(trans, tree_root, &free_space_root->root_key); ret = btrfs_del_root(trans, fs_info, &free_space_root->root_key);
if (ret) if (ret)
goto abort; goto abort;

View File

@ -44,7 +44,7 @@ int remove_from_free_space_tree(struct btrfs_trans_handle *trans,
struct btrfs_fs_info *fs_info, struct btrfs_fs_info *fs_info,
u64 start, u64 size); u64 start, u64 size);
/* Exposed for testing. */ #ifdef CONFIG_BTRFS_FS_RUN_SANITY_TESTS
struct btrfs_free_space_info * struct btrfs_free_space_info *
search_free_space_info(struct btrfs_trans_handle *trans, search_free_space_info(struct btrfs_trans_handle *trans,
struct btrfs_fs_info *fs_info, struct btrfs_fs_info *fs_info,
@ -68,5 +68,6 @@ int convert_free_space_to_extents(struct btrfs_trans_handle *trans,
struct btrfs_path *path); struct btrfs_path *path);
int free_space_test_bit(struct btrfs_block_group_cache *block_group, int free_space_test_bit(struct btrfs_block_group_cache *block_group,
struct btrfs_path *path, u64 offset); struct btrfs_path *path, u64 offset);
#endif
#endif #endif

View File

@ -392,20 +392,23 @@ static noinline int add_async_extent(struct async_cow *cow,
return 0; return 0;
} }
static inline int inode_need_compress(struct inode *inode) static inline int inode_need_compress(struct inode *inode, u64 start, u64 end)
{ {
struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb); struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
/* force compress */ /* force compress */
if (btrfs_test_opt(fs_info, FORCE_COMPRESS)) if (btrfs_test_opt(fs_info, FORCE_COMPRESS))
return 1; return 1;
/* defrag ioctl */
if (BTRFS_I(inode)->defrag_compress)
return 1;
/* bad compression ratios */ /* bad compression ratios */
if (BTRFS_I(inode)->flags & BTRFS_INODE_NOCOMPRESS) if (BTRFS_I(inode)->flags & BTRFS_INODE_NOCOMPRESS)
return 0; return 0;
if (btrfs_test_opt(fs_info, COMPRESS) || if (btrfs_test_opt(fs_info, COMPRESS) ||
BTRFS_I(inode)->flags & BTRFS_INODE_COMPRESS || BTRFS_I(inode)->flags & BTRFS_INODE_COMPRESS ||
BTRFS_I(inode)->force_compress) BTRFS_I(inode)->prop_compress)
return 1; return btrfs_compress_heuristic(inode, start, end);
return 0; return 0;
} }
@ -503,7 +506,7 @@ again:
* inode has not been flagged as nocompress. This flag can * inode has not been flagged as nocompress. This flag can
* change at any time if we discover bad compression ratios. * change at any time if we discover bad compression ratios.
*/ */
if (inode_need_compress(inode)) { if (inode_need_compress(inode, start, end)) {
WARN_ON(pages); WARN_ON(pages);
pages = kcalloc(nr_pages, sizeof(struct page *), GFP_NOFS); pages = kcalloc(nr_pages, sizeof(struct page *), GFP_NOFS);
if (!pages) { if (!pages) {
@ -511,8 +514,10 @@ again:
goto cont; goto cont;
} }
if (BTRFS_I(inode)->force_compress) if (BTRFS_I(inode)->defrag_compress)
compress_type = BTRFS_I(inode)->force_compress; compress_type = BTRFS_I(inode)->defrag_compress;
else if (BTRFS_I(inode)->prop_compress)
compress_type = BTRFS_I(inode)->prop_compress;
/* /*
* we need to call clear_page_dirty_for_io on each * we need to call clear_page_dirty_for_io on each
@ -645,7 +650,7 @@ cont:
/* flag the file so we don't compress in the future */ /* flag the file so we don't compress in the future */
if (!btrfs_test_opt(fs_info, FORCE_COMPRESS) && if (!btrfs_test_opt(fs_info, FORCE_COMPRESS) &&
!(BTRFS_I(inode)->force_compress)) { !(BTRFS_I(inode)->prop_compress)) {
BTRFS_I(inode)->flags |= BTRFS_INODE_NOCOMPRESS; BTRFS_I(inode)->flags |= BTRFS_INODE_NOCOMPRESS;
} }
} }
@ -1381,7 +1386,7 @@ next_slot:
* we fall into common COW way. * we fall into common COW way.
*/ */
if (!nolock) { if (!nolock) {
err = btrfs_start_write_no_snapshoting(root); err = btrfs_start_write_no_snapshotting(root);
if (!err) if (!err)
goto out_check; goto out_check;
} }
@ -1393,12 +1398,12 @@ next_slot:
if (csum_exist_in_range(fs_info, disk_bytenr, if (csum_exist_in_range(fs_info, disk_bytenr,
num_bytes)) { num_bytes)) {
if (!nolock) if (!nolock)
btrfs_end_write_no_snapshoting(root); btrfs_end_write_no_snapshotting(root);
goto out_check; goto out_check;
} }
if (!btrfs_inc_nocow_writers(fs_info, disk_bytenr)) { if (!btrfs_inc_nocow_writers(fs_info, disk_bytenr)) {
if (!nolock) if (!nolock)
btrfs_end_write_no_snapshoting(root); btrfs_end_write_no_snapshotting(root);
goto out_check; goto out_check;
} }
nocow = 1; nocow = 1;
@ -1415,7 +1420,7 @@ out_check:
if (extent_end <= start) { if (extent_end <= start) {
path->slots[0]++; path->slots[0]++;
if (!nolock && nocow) if (!nolock && nocow)
btrfs_end_write_no_snapshoting(root); btrfs_end_write_no_snapshotting(root);
if (nocow) if (nocow)
btrfs_dec_nocow_writers(fs_info, disk_bytenr); btrfs_dec_nocow_writers(fs_info, disk_bytenr);
goto next_slot; goto next_slot;
@ -1438,7 +1443,7 @@ out_check:
NULL); NULL);
if (ret) { if (ret) {
if (!nolock && nocow) if (!nolock && nocow)
btrfs_end_write_no_snapshoting(root); btrfs_end_write_no_snapshotting(root);
if (nocow) if (nocow)
btrfs_dec_nocow_writers(fs_info, btrfs_dec_nocow_writers(fs_info,
disk_bytenr); disk_bytenr);
@ -1459,7 +1464,7 @@ out_check:
BTRFS_ORDERED_PREALLOC); BTRFS_ORDERED_PREALLOC);
if (IS_ERR(em)) { if (IS_ERR(em)) {
if (!nolock && nocow) if (!nolock && nocow)
btrfs_end_write_no_snapshoting(root); btrfs_end_write_no_snapshotting(root);
if (nocow) if (nocow)
btrfs_dec_nocow_writers(fs_info, btrfs_dec_nocow_writers(fs_info,
disk_bytenr); disk_bytenr);
@ -1499,7 +1504,7 @@ out_check:
PAGE_UNLOCK | PAGE_SET_PRIVATE2); PAGE_UNLOCK | PAGE_SET_PRIVATE2);
if (!nolock && nocow) if (!nolock && nocow)
btrfs_end_write_no_snapshoting(root); btrfs_end_write_no_snapshotting(root);
cur_offset = extent_end; cur_offset = extent_end;
/* /*
@ -1576,7 +1581,7 @@ static int run_delalloc_range(void *private_data, struct page *locked_page,
} else if (BTRFS_I(inode)->flags & BTRFS_INODE_PREALLOC && !force_cow) { } else if (BTRFS_I(inode)->flags & BTRFS_INODE_PREALLOC && !force_cow) {
ret = run_delalloc_nocow(inode, locked_page, start, end, ret = run_delalloc_nocow(inode, locked_page, start, end,
page_started, 0, nr_written); page_started, 0, nr_written);
} else if (!inode_need_compress(inode)) { } else if (!inode_need_compress(inode, start, end)) {
ret = cow_file_range(inode, locked_page, start, end, end, ret = cow_file_range(inode, locked_page, start, end, end,
page_started, nr_written, 1, NULL); page_started, nr_written, 1, NULL);
} else { } else {
@ -1796,10 +1801,11 @@ static void btrfs_clear_bit_hook(void *private_data,
u64 len = state->end + 1 - state->start; u64 len = state->end + 1 - state->start;
u32 num_extents = count_max_extents(len); u32 num_extents = count_max_extents(len);
spin_lock(&inode->lock); if ((state->state & EXTENT_DEFRAG) && (*bits & EXTENT_DEFRAG)) {
if ((state->state & EXTENT_DEFRAG) && (*bits & EXTENT_DEFRAG)) spin_lock(&inode->lock);
inode->defrag_bytes -= len; inode->defrag_bytes -= len;
spin_unlock(&inode->lock); spin_unlock(&inode->lock);
}
/* /*
* set_bit and clear bit hooks normally require _irqsave/restore * set_bit and clear bit hooks normally require _irqsave/restore
@ -3159,8 +3165,6 @@ zeroit:
memset(kaddr + pgoff, 1, len); memset(kaddr + pgoff, 1, len);
flush_dcache_page(page); flush_dcache_page(page);
kunmap_atomic(kaddr); kunmap_atomic(kaddr);
if (csum_expected == 0)
return 0;
return -EIO; return -EIO;
} }
@ -5055,7 +5059,7 @@ static int btrfs_setsize(struct inode *inode, struct iattr *attr)
if (newsize > oldsize) { if (newsize > oldsize) {
/* /*
* Don't do an expanding truncate while snapshoting is ongoing. * Don't do an expanding truncate while snapshotting is ongoing.
* This is to ensure the snapshot captures a fully consistent * This is to ensure the snapshot captures a fully consistent
* state of this file - if the snapshot captures this expanding * state of this file - if the snapshot captures this expanding
* truncation, it must capture all writes that happened before * truncation, it must capture all writes that happened before
@ -5064,13 +5068,13 @@ static int btrfs_setsize(struct inode *inode, struct iattr *attr)
btrfs_wait_for_snapshot_creation(root); btrfs_wait_for_snapshot_creation(root);
ret = btrfs_cont_expand(inode, oldsize, newsize); ret = btrfs_cont_expand(inode, oldsize, newsize);
if (ret) { if (ret) {
btrfs_end_write_no_snapshoting(root); btrfs_end_write_no_snapshotting(root);
return ret; return ret;
} }
trans = btrfs_start_transaction(root, 1); trans = btrfs_start_transaction(root, 1);
if (IS_ERR(trans)) { if (IS_ERR(trans)) {
btrfs_end_write_no_snapshoting(root); btrfs_end_write_no_snapshotting(root);
return PTR_ERR(trans); return PTR_ERR(trans);
} }
@ -5078,7 +5082,7 @@ static int btrfs_setsize(struct inode *inode, struct iattr *attr)
btrfs_ordered_update_i_size(inode, i_size_read(inode), NULL); btrfs_ordered_update_i_size(inode, i_size_read(inode), NULL);
pagecache_isize_extended(inode, oldsize, newsize); pagecache_isize_extended(inode, oldsize, newsize);
ret = btrfs_update_inode(trans, root, inode); ret = btrfs_update_inode(trans, root, inode);
btrfs_end_write_no_snapshoting(root); btrfs_end_write_no_snapshotting(root);
btrfs_end_transaction(trans); btrfs_end_transaction(trans);
} else { } else {
@ -5873,25 +5877,74 @@ unsigned char btrfs_filetype_table[] = {
DT_UNKNOWN, DT_REG, DT_DIR, DT_CHR, DT_BLK, DT_FIFO, DT_SOCK, DT_LNK DT_UNKNOWN, DT_REG, DT_DIR, DT_CHR, DT_BLK, DT_FIFO, DT_SOCK, DT_LNK
}; };
/*
* All this infrastructure exists because dir_emit can fault, and we are holding
* the tree lock when doing readdir. For now just allocate a buffer and copy
* our information into that, and then dir_emit from the buffer. This is
* similar to what NFS does, only we don't keep the buffer around in pagecache
* because I'm afraid I'll mess that up. Long term we need to make filldir do
* copy_to_user_inatomic so we don't have to worry about page faulting under the
* tree lock.
*/
static int btrfs_opendir(struct inode *inode, struct file *file)
{
struct btrfs_file_private *private;
private = kzalloc(sizeof(struct btrfs_file_private), GFP_KERNEL);
if (!private)
return -ENOMEM;
private->filldir_buf = kzalloc(PAGE_SIZE, GFP_KERNEL);
if (!private->filldir_buf) {
kfree(private);
return -ENOMEM;
}
file->private_data = private;
return 0;
}
struct dir_entry {
u64 ino;
u64 offset;
unsigned type;
int name_len;
};
static int btrfs_filldir(void *addr, int entries, struct dir_context *ctx)
{
while (entries--) {
struct dir_entry *entry = addr;
char *name = (char *)(entry + 1);
ctx->pos = entry->offset;
if (!dir_emit(ctx, name, entry->name_len, entry->ino,
entry->type))
return 1;
addr += sizeof(struct dir_entry) + entry->name_len;
ctx->pos++;
}
return 0;
}
static int btrfs_real_readdir(struct file *file, struct dir_context *ctx) static int btrfs_real_readdir(struct file *file, struct dir_context *ctx)
{ {
struct inode *inode = file_inode(file); struct inode *inode = file_inode(file);
struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb); struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
struct btrfs_root *root = BTRFS_I(inode)->root; struct btrfs_root *root = BTRFS_I(inode)->root;
struct btrfs_file_private *private = file->private_data;
struct btrfs_dir_item *di; struct btrfs_dir_item *di;
struct btrfs_key key; struct btrfs_key key;
struct btrfs_key found_key; struct btrfs_key found_key;
struct btrfs_path *path; struct btrfs_path *path;
void *addr;
struct list_head ins_list; struct list_head ins_list;
struct list_head del_list; struct list_head del_list;
int ret; int ret;
struct extent_buffer *leaf; struct extent_buffer *leaf;
int slot; int slot;
unsigned char d_type;
int over = 0;
char tmp_name[32];
char *name_ptr; char *name_ptr;
int name_len; int name_len;
int entries = 0;
int total_len = 0;
bool put = false; bool put = false;
struct btrfs_key location; struct btrfs_key location;
@ -5902,12 +5955,14 @@ static int btrfs_real_readdir(struct file *file, struct dir_context *ctx)
if (!path) if (!path)
return -ENOMEM; return -ENOMEM;
addr = private->filldir_buf;
path->reada = READA_FORWARD; path->reada = READA_FORWARD;
INIT_LIST_HEAD(&ins_list); INIT_LIST_HEAD(&ins_list);
INIT_LIST_HEAD(&del_list); INIT_LIST_HEAD(&del_list);
put = btrfs_readdir_get_delayed_items(inode, &ins_list, &del_list); put = btrfs_readdir_get_delayed_items(inode, &ins_list, &del_list);
again:
key.type = BTRFS_DIR_INDEX_KEY; key.type = BTRFS_DIR_INDEX_KEY;
key.offset = ctx->pos; key.offset = ctx->pos;
key.objectid = btrfs_ino(BTRFS_I(inode)); key.objectid = btrfs_ino(BTRFS_I(inode));
@ -5917,6 +5972,8 @@ static int btrfs_real_readdir(struct file *file, struct dir_context *ctx)
goto err; goto err;
while (1) { while (1) {
struct dir_entry *entry;
leaf = path->nodes[0]; leaf = path->nodes[0];
slot = path->slots[0]; slot = path->slots[0];
if (slot >= btrfs_header_nritems(leaf)) { if (slot >= btrfs_header_nritems(leaf)) {
@ -5938,41 +5995,43 @@ static int btrfs_real_readdir(struct file *file, struct dir_context *ctx)
goto next; goto next;
if (btrfs_should_delete_dir_index(&del_list, found_key.offset)) if (btrfs_should_delete_dir_index(&del_list, found_key.offset))
goto next; goto next;
ctx->pos = found_key.offset;
di = btrfs_item_ptr(leaf, slot, struct btrfs_dir_item); di = btrfs_item_ptr(leaf, slot, struct btrfs_dir_item);
if (verify_dir_item(fs_info, leaf, slot, di)) if (verify_dir_item(fs_info, leaf, slot, di))
goto next; goto next;
name_len = btrfs_dir_name_len(leaf, di); name_len = btrfs_dir_name_len(leaf, di);
if (name_len <= sizeof(tmp_name)) { if ((total_len + sizeof(struct dir_entry) + name_len) >=
name_ptr = tmp_name; PAGE_SIZE) {
} else { btrfs_release_path(path);
name_ptr = kmalloc(name_len, GFP_KERNEL); ret = btrfs_filldir(private->filldir_buf, entries, ctx);
if (!name_ptr) { if (ret)
ret = -ENOMEM; goto nopos;
goto err; addr = private->filldir_buf;
} entries = 0;
total_len = 0;
goto again;
} }
entry = addr;
entry->name_len = name_len;
name_ptr = (char *)(entry + 1);
read_extent_buffer(leaf, name_ptr, (unsigned long)(di + 1), read_extent_buffer(leaf, name_ptr, (unsigned long)(di + 1),
name_len); name_len);
entry->type = btrfs_filetype_table[btrfs_dir_type(leaf, di)];
d_type = btrfs_filetype_table[btrfs_dir_type(leaf, di)];
btrfs_dir_item_key_to_cpu(leaf, di, &location); btrfs_dir_item_key_to_cpu(leaf, di, &location);
entry->ino = location.objectid;
over = !dir_emit(ctx, name_ptr, name_len, location.objectid, entry->offset = found_key.offset;
d_type); entries++;
addr += sizeof(struct dir_entry) + name_len;
if (name_ptr != tmp_name) total_len += sizeof(struct dir_entry) + name_len;
kfree(name_ptr);
if (over)
goto nopos;
ctx->pos++;
next: next:
path->slots[0]++; path->slots[0]++;
} }
btrfs_release_path(path);
ret = btrfs_filldir(private->filldir_buf, entries, ctx);
if (ret)
goto nopos;
ret = btrfs_readdir_delayed_dir_index(ctx, &ins_list); ret = btrfs_readdir_delayed_dir_index(ctx, &ins_list);
if (ret) if (ret)
@ -6185,6 +6244,37 @@ static int btrfs_insert_inode_locked(struct inode *inode)
btrfs_find_actor, &args); btrfs_find_actor, &args);
} }
/*
* Inherit flags from the parent inode.
*
* Currently only the compression flags and the cow flags are inherited.
*/
static void btrfs_inherit_iflags(struct inode *inode, struct inode *dir)
{
unsigned int flags;
if (!dir)
return;
flags = BTRFS_I(dir)->flags;
if (flags & BTRFS_INODE_NOCOMPRESS) {
BTRFS_I(inode)->flags &= ~BTRFS_INODE_COMPRESS;
BTRFS_I(inode)->flags |= BTRFS_INODE_NOCOMPRESS;
} else if (flags & BTRFS_INODE_COMPRESS) {
BTRFS_I(inode)->flags &= ~BTRFS_INODE_NOCOMPRESS;
BTRFS_I(inode)->flags |= BTRFS_INODE_COMPRESS;
}
if (flags & BTRFS_INODE_NODATACOW) {
BTRFS_I(inode)->flags |= BTRFS_INODE_NODATACOW;
if (S_ISREG(inode->i_mode))
BTRFS_I(inode)->flags |= BTRFS_INODE_NODATASUM;
}
btrfs_update_iflags(inode);
}
static struct inode *btrfs_new_inode(struct btrfs_trans_handle *trans, static struct inode *btrfs_new_inode(struct btrfs_trans_handle *trans,
struct btrfs_root *root, struct btrfs_root *root,
struct inode *dir, struct inode *dir,
@ -7991,7 +8081,7 @@ static blk_status_t dio_read_error(struct inode *inode, struct bio *failed_bio,
struct extent_io_tree *failure_tree = &BTRFS_I(inode)->io_failure_tree; struct extent_io_tree *failure_tree = &BTRFS_I(inode)->io_failure_tree;
struct bio *bio; struct bio *bio;
int isector; int isector;
int read_mode = 0; unsigned int read_mode = 0;
int segs; int segs;
int ret; int ret;
blk_status_t status; blk_status_t status;
@ -8021,7 +8111,7 @@ static blk_status_t dio_read_error(struct inode *inode, struct bio *failed_bio,
bio_set_op_attrs(bio, REQ_OP_READ, read_mode); bio_set_op_attrs(bio, REQ_OP_READ, read_mode);
btrfs_debug(BTRFS_I(inode)->root->fs_info, btrfs_debug(BTRFS_I(inode)->root->fs_info,
"Repair DIO Read Error: submitting new dio read[%#x] to this_mirror=%d, in_validation=%d\n", "repair DIO read error: submitting new dio read[%#x] to this_mirror=%d, in_validation=%d",
read_mode, failrec->this_mirror, failrec->in_validation); read_mode, failrec->this_mirror, failrec->in_validation);
status = submit_dio_repair_bio(inode, bio, failrec->this_mirror); status = submit_dio_repair_bio(inode, bio, failrec->this_mirror);
@ -8106,7 +8196,7 @@ next_block_or_try_again:
goto next; goto next;
} }
wait_for_completion(&done.done); wait_for_completion_io(&done.done);
if (!done.uptodate) { if (!done.uptodate) {
/* We might have another mirror, so try again */ /* We might have another mirror, so try again */
@ -8221,7 +8311,7 @@ try_again:
goto next; goto next;
} }
wait_for_completion(&done.done); wait_for_completion_io(&done.done);
if (!done.uptodate) { if (!done.uptodate) {
/* We might have another mirror, so try again */ /* We might have another mirror, so try again */
@ -8428,7 +8518,7 @@ static inline blk_status_t btrfs_lookup_and_bind_dio_csum(struct inode *inode,
static inline blk_status_t static inline blk_status_t
__btrfs_submit_dio_bio(struct bio *bio, struct inode *inode, u64 file_offset, __btrfs_submit_dio_bio(struct bio *bio, struct inode *inode, u64 file_offset,
int skip_sum, int async_submit) int async_submit)
{ {
struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb); struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
struct btrfs_dio_private *dip = bio->bi_private; struct btrfs_dio_private *dip = bio->bi_private;
@ -8446,7 +8536,7 @@ __btrfs_submit_dio_bio(struct bio *bio, struct inode *inode, u64 file_offset,
goto err; goto err;
} }
if (skip_sum) if (BTRFS_I(inode)->flags & BTRFS_INODE_NODATASUM)
goto map; goto map;
if (write && async_submit) { if (write && async_submit) {
@ -8476,8 +8566,7 @@ err:
return ret; return ret;
} }
static int btrfs_submit_direct_hook(struct btrfs_dio_private *dip, static int btrfs_submit_direct_hook(struct btrfs_dio_private *dip)
int skip_sum)
{ {
struct inode *inode = dip->inode; struct inode *inode = dip->inode;
struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb); struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
@ -8541,7 +8630,7 @@ static int btrfs_submit_direct_hook(struct btrfs_dio_private *dip,
*/ */
atomic_inc(&dip->pending_bios); atomic_inc(&dip->pending_bios);
status = __btrfs_submit_dio_bio(bio, inode, file_offset, skip_sum, status = __btrfs_submit_dio_bio(bio, inode, file_offset,
async_submit); async_submit);
if (status) { if (status) {
bio_put(bio); bio_put(bio);
@ -8561,8 +8650,7 @@ static int btrfs_submit_direct_hook(struct btrfs_dio_private *dip,
} while (submit_len > 0); } while (submit_len > 0);
submit: submit:
status = __btrfs_submit_dio_bio(bio, inode, file_offset, skip_sum, status = __btrfs_submit_dio_bio(bio, inode, file_offset, async_submit);
async_submit);
if (!status) if (!status)
return 0; return 0;
@ -8587,12 +8675,9 @@ static void btrfs_submit_direct(struct bio *dio_bio, struct inode *inode,
struct btrfs_dio_private *dip = NULL; struct btrfs_dio_private *dip = NULL;
struct bio *bio = NULL; struct bio *bio = NULL;
struct btrfs_io_bio *io_bio; struct btrfs_io_bio *io_bio;
int skip_sum;
bool write = (bio_op(dio_bio) == REQ_OP_WRITE); bool write = (bio_op(dio_bio) == REQ_OP_WRITE);
int ret = 0; int ret = 0;
skip_sum = BTRFS_I(inode)->flags & BTRFS_INODE_NODATASUM;
bio = btrfs_bio_clone(dio_bio); bio = btrfs_bio_clone(dio_bio);
dip = kzalloc(sizeof(*dip), GFP_NOFS); dip = kzalloc(sizeof(*dip), GFP_NOFS);
@ -8635,7 +8720,7 @@ static void btrfs_submit_direct(struct bio *dio_bio, struct inode *inode,
dio_data->unsubmitted_oe_range_end; dio_data->unsubmitted_oe_range_end;
} }
ret = btrfs_submit_direct_hook(dip, skip_sum); ret = btrfs_submit_direct_hook(dip);
if (!ret) if (!ret)
return; return;
@ -8735,7 +8820,6 @@ static ssize_t btrfs_direct_IO(struct kiocb *iocb, struct iov_iter *iter)
return 0; return 0;
inode_dio_begin(inode); inode_dio_begin(inode);
smp_mb__after_atomic();
/* /*
* The generic stuff only does filemap_write_and_wait_range, which * The generic stuff only does filemap_write_and_wait_range, which
@ -9408,7 +9492,8 @@ struct inode *btrfs_alloc_inode(struct super_block *sb)
ei->reserved_extents = 0; ei->reserved_extents = 0;
ei->runtime_flags = 0; ei->runtime_flags = 0;
ei->force_compress = BTRFS_COMPRESS_NONE; ei->prop_compress = BTRFS_COMPRESS_NONE;
ei->defrag_compress = BTRFS_COMPRESS_NONE;
ei->delayed_node = NULL; ei->delayed_node = NULL;
@ -10748,6 +10833,7 @@ static const struct file_operations btrfs_dir_file_operations = {
.llseek = generic_file_llseek, .llseek = generic_file_llseek,
.read = generic_read_dir, .read = generic_read_dir,
.iterate_shared = btrfs_real_readdir, .iterate_shared = btrfs_real_readdir,
.open = btrfs_opendir,
.unlocked_ioctl = btrfs_ioctl, .unlocked_ioctl = btrfs_ioctl,
#ifdef CONFIG_COMPAT #ifdef CONFIG_COMPAT
.compat_ioctl = btrfs_compat_ioctl, .compat_ioctl = btrfs_compat_ioctl,

View File

@ -156,37 +156,6 @@ void btrfs_update_iflags(struct inode *inode)
new_fl); new_fl);
} }
/*
* Inherit flags from the parent inode.
*
* Currently only the compression flags and the cow flags are inherited.
*/
void btrfs_inherit_iflags(struct inode *inode, struct inode *dir)
{
unsigned int flags;
if (!dir)
return;
flags = BTRFS_I(dir)->flags;
if (flags & BTRFS_INODE_NOCOMPRESS) {
BTRFS_I(inode)->flags &= ~BTRFS_INODE_COMPRESS;
BTRFS_I(inode)->flags |= BTRFS_INODE_NOCOMPRESS;
} else if (flags & BTRFS_INODE_COMPRESS) {
BTRFS_I(inode)->flags &= ~BTRFS_INODE_NOCOMPRESS;
BTRFS_I(inode)->flags |= BTRFS_INODE_COMPRESS;
}
if (flags & BTRFS_INODE_NODATACOW) {
BTRFS_I(inode)->flags |= BTRFS_INODE_NODATACOW;
if (S_ISREG(inode->i_mode))
BTRFS_I(inode)->flags |= BTRFS_INODE_NODATASUM;
}
btrfs_update_iflags(inode);
}
static int btrfs_ioctl_getflags(struct file *file, void __user *arg) static int btrfs_ioctl_getflags(struct file *file, void __user *arg)
{ {
struct btrfs_inode *ip = BTRFS_I(file_inode(file)); struct btrfs_inode *ip = BTRFS_I(file_inode(file));
@ -638,7 +607,7 @@ fail_free:
return ret; return ret;
} }
static void btrfs_wait_for_no_snapshoting_writes(struct btrfs_root *root) static void btrfs_wait_for_no_snapshotting_writes(struct btrfs_root *root)
{ {
s64 writers; s64 writers;
DEFINE_WAIT(wait); DEFINE_WAIT(wait);
@ -681,9 +650,9 @@ static int create_snapshot(struct btrfs_root *root, struct inode *dir,
goto free_pending; goto free_pending;
} }
atomic_inc(&root->will_be_snapshoted); atomic_inc(&root->will_be_snapshotted);
smp_mb__after_atomic(); smp_mb__after_atomic();
btrfs_wait_for_no_snapshoting_writes(root); btrfs_wait_for_no_snapshotting_writes(root);
ret = btrfs_start_delalloc_inodes(root, 0); ret = btrfs_start_delalloc_inodes(root, 0);
if (ret) if (ret)
@ -754,8 +723,8 @@ static int create_snapshot(struct btrfs_root *root, struct inode *dir,
fail: fail:
btrfs_subvolume_release_metadata(fs_info, &pending_snapshot->block_rsv); btrfs_subvolume_release_metadata(fs_info, &pending_snapshot->block_rsv);
dec_and_free: dec_and_free:
if (atomic_dec_and_test(&root->will_be_snapshoted)) if (atomic_dec_and_test(&root->will_be_snapshotted))
wake_up_atomic_t(&root->will_be_snapshoted); wake_up_atomic_t(&root->will_be_snapshotted);
free_pending: free_pending:
kfree(pending_snapshot->root_item); kfree(pending_snapshot->root_item);
btrfs_free_path(pending_snapshot->path); btrfs_free_path(pending_snapshot->path);
@ -1286,6 +1255,7 @@ int btrfs_defrag_file(struct inode *inode, struct file *file,
unsigned long cluster = max_cluster; unsigned long cluster = max_cluster;
u64 new_align = ~((u64)SZ_128K - 1); u64 new_align = ~((u64)SZ_128K - 1);
struct page **pages = NULL; struct page **pages = NULL;
bool do_compress = range->flags & BTRFS_DEFRAG_RANGE_COMPRESS;
if (isize == 0) if (isize == 0)
return 0; return 0;
@ -1293,7 +1263,7 @@ int btrfs_defrag_file(struct inode *inode, struct file *file,
if (range->start >= isize) if (range->start >= isize)
return -EINVAL; return -EINVAL;
if (range->flags & BTRFS_DEFRAG_RANGE_COMPRESS) { if (do_compress) {
if (range->compress_type > BTRFS_COMPRESS_TYPES) if (range->compress_type > BTRFS_COMPRESS_TYPES)
return -EINVAL; return -EINVAL;
if (range->compress_type) if (range->compress_type)
@ -1304,20 +1274,19 @@ int btrfs_defrag_file(struct inode *inode, struct file *file,
extent_thresh = SZ_256K; extent_thresh = SZ_256K;
/* /*
* if we were not given a file, allocate a readahead * If we were not given a file, allocate a readahead context. As
* context * readahead is just an optimization, defrag will work without it so
* we don't error out.
*/ */
if (!file) { if (!file) {
ra = kzalloc(sizeof(*ra), GFP_NOFS); ra = kzalloc(sizeof(*ra), GFP_KERNEL);
if (!ra) if (ra)
return -ENOMEM; file_ra_state_init(ra, inode->i_mapping);
file_ra_state_init(ra, inode->i_mapping);
} else { } else {
ra = &file->f_ra; ra = &file->f_ra;
} }
pages = kmalloc_array(max_cluster, sizeof(struct page *), pages = kmalloc_array(max_cluster, sizeof(struct page *), GFP_KERNEL);
GFP_NOFS);
if (!pages) { if (!pages) {
ret = -ENOMEM; ret = -ENOMEM;
goto out_ra; goto out_ra;
@ -1373,8 +1342,7 @@ int btrfs_defrag_file(struct inode *inode, struct file *file,
if (!should_defrag_range(inode, (u64)i << PAGE_SHIFT, if (!should_defrag_range(inode, (u64)i << PAGE_SHIFT,
extent_thresh, &last_len, &skip, extent_thresh, &last_len, &skip,
&defrag_end, range->flags & &defrag_end, do_compress)){
BTRFS_DEFRAG_RANGE_COMPRESS)) {
unsigned long next; unsigned long next;
/* /*
* the should_defrag function tells us how much to skip * the should_defrag function tells us how much to skip
@ -1395,14 +1363,15 @@ int btrfs_defrag_file(struct inode *inode, struct file *file,
if (i + cluster > ra_index) { if (i + cluster > ra_index) {
ra_index = max(i, ra_index); ra_index = max(i, ra_index);
btrfs_force_ra(inode->i_mapping, ra, file, ra_index, if (ra)
cluster); page_cache_sync_readahead(inode->i_mapping, ra,
file, ra_index, cluster);
ra_index += cluster; ra_index += cluster;
} }
inode_lock(inode); inode_lock(inode);
if (range->flags & BTRFS_DEFRAG_RANGE_COMPRESS) if (do_compress)
BTRFS_I(inode)->force_compress = compress_type; BTRFS_I(inode)->defrag_compress = compress_type;
ret = cluster_pages_for_defrag(inode, pages, i, cluster); ret = cluster_pages_for_defrag(inode, pages, i, cluster);
if (ret < 0) { if (ret < 0) {
inode_unlock(inode); inode_unlock(inode);
@ -1449,7 +1418,7 @@ int btrfs_defrag_file(struct inode *inode, struct file *file,
filemap_flush(inode->i_mapping); filemap_flush(inode->i_mapping);
} }
if ((range->flags & BTRFS_DEFRAG_RANGE_COMPRESS)) { if (do_compress) {
/* the filemap_flush will queue IO into the worker threads, but /* the filemap_flush will queue IO into the worker threads, but
* we have to make sure the IO is actually started and that * we have to make sure the IO is actually started and that
* ordered extents get created before we return * ordered extents get created before we return
@ -1471,9 +1440,9 @@ int btrfs_defrag_file(struct inode *inode, struct file *file,
ret = defrag_count; ret = defrag_count;
out_ra: out_ra:
if (range->flags & BTRFS_DEFRAG_RANGE_COMPRESS) { if (do_compress) {
inode_lock(inode); inode_lock(inode);
BTRFS_I(inode)->force_compress = BTRFS_COMPRESS_NONE; BTRFS_I(inode)->defrag_compress = BTRFS_COMPRESS_NONE;
inode_unlock(inode); inode_unlock(inode);
} }
if (!file) if (!file)
@ -1600,8 +1569,7 @@ static noinline int btrfs_ioctl_resize(struct file *file,
goto out_free; goto out_free;
} }
new_size = div_u64(new_size, fs_info->sectorsize); new_size = round_down(new_size, fs_info->sectorsize);
new_size *= fs_info->sectorsize;
btrfs_info_in_rcu(fs_info, "new size for %s is %llu", btrfs_info_in_rcu(fs_info, "new size for %s is %llu",
rcu_str_deref(device->name), new_size); rcu_str_deref(device->name), new_size);
@ -2201,9 +2169,6 @@ static noinline int btrfs_ioctl_tree_search_v2(struct file *file,
buf_size = args.buf_size; buf_size = args.buf_size;
if (buf_size < sizeof(struct btrfs_ioctl_search_header))
return -EOVERFLOW;
/* limit result size to 16MB */ /* limit result size to 16MB */
if (buf_size > buf_limit) if (buf_size > buf_limit)
buf_size = buf_limit; buf_size = buf_limit;
@ -3998,15 +3963,35 @@ static long btrfs_ioctl_trans_start(struct file *file)
struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb); struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
struct btrfs_root *root = BTRFS_I(inode)->root; struct btrfs_root *root = BTRFS_I(inode)->root;
struct btrfs_trans_handle *trans; struct btrfs_trans_handle *trans;
struct btrfs_file_private *private;
int ret; int ret;
static bool warned = false;
ret = -EPERM; ret = -EPERM;
if (!capable(CAP_SYS_ADMIN)) if (!capable(CAP_SYS_ADMIN))
goto out; goto out;
if (!warned) {
btrfs_warn(fs_info,
"Userspace transaction mechanism is considered "
"deprecated and slated to be removed in 4.17. "
"If you have a valid use case please "
"speak up on the mailing list");
WARN_ON(1);
warned = true;
}
ret = -EINPROGRESS; ret = -EINPROGRESS;
if (file->private_data) private = file->private_data;
if (private && private->trans)
goto out; goto out;
if (!private) {
private = kzalloc(sizeof(struct btrfs_file_private),
GFP_KERNEL);
if (!private)
return -ENOMEM;
file->private_data = private;
}
ret = -EROFS; ret = -EROFS;
if (btrfs_root_readonly(root)) if (btrfs_root_readonly(root))
@ -4023,7 +4008,7 @@ static long btrfs_ioctl_trans_start(struct file *file)
if (IS_ERR(trans)) if (IS_ERR(trans))
goto out_drop; goto out_drop;
file->private_data = trans; private->trans = trans;
return 0; return 0;
out_drop: out_drop:
@ -4278,14 +4263,13 @@ long btrfs_ioctl_trans_end(struct file *file)
{ {
struct inode *inode = file_inode(file); struct inode *inode = file_inode(file);
struct btrfs_root *root = BTRFS_I(inode)->root; struct btrfs_root *root = BTRFS_I(inode)->root;
struct btrfs_trans_handle *trans; struct btrfs_file_private *private = file->private_data;
trans = file->private_data; if (!private || !private->trans)
if (!trans)
return -EINVAL; return -EINVAL;
file->private_data = NULL;
btrfs_end_transaction(trans); btrfs_end_transaction(private->trans);
private->trans = NULL;
atomic_dec(&root->fs_info->open_ioctl_trans); atomic_dec(&root->fs_info->open_ioctl_trans);

View File

@ -44,7 +44,7 @@ static void print_dev_item(struct extent_buffer *eb,
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)
{ {
pr_info("\t\textent data backref root %llu objectid %llu offset %llu count %u\n", pr_cont("extent data backref root %llu objectid %llu offset %llu count %u\n",
btrfs_extent_data_ref_root(eb, ref), btrfs_extent_data_ref_root(eb, ref),
btrfs_extent_data_ref_objectid(eb, ref), btrfs_extent_data_ref_objectid(eb, ref),
btrfs_extent_data_ref_offset(eb, ref), btrfs_extent_data_ref_offset(eb, ref),
@ -63,6 +63,7 @@ static void print_extent_item(struct extent_buffer *eb, int slot, int type)
u32 item_size = btrfs_item_size_nr(eb, slot); u32 item_size = btrfs_item_size_nr(eb, slot);
u64 flags; u64 flags;
u64 offset; u64 offset;
int ref_index = 0;
if (item_size < sizeof(*ei)) { if (item_size < sizeof(*ei)) {
#ifdef BTRFS_COMPAT_EXTENT_TREE_V0 #ifdef BTRFS_COMPAT_EXTENT_TREE_V0
@ -104,12 +105,20 @@ static void print_extent_item(struct extent_buffer *eb, int slot, int type)
iref = (struct btrfs_extent_inline_ref *)ptr; iref = (struct btrfs_extent_inline_ref *)ptr;
type = btrfs_extent_inline_ref_type(eb, iref); type = btrfs_extent_inline_ref_type(eb, iref);
offset = btrfs_extent_inline_ref_offset(eb, iref); offset = btrfs_extent_inline_ref_offset(eb, iref);
pr_info("\t\tref#%d: ", ref_index++);
switch (type) { switch (type) {
case BTRFS_TREE_BLOCK_REF_KEY: case BTRFS_TREE_BLOCK_REF_KEY:
pr_info("\t\ttree block backref root %llu\n", offset); pr_cont("tree block backref root %llu\n", offset);
break; break;
case BTRFS_SHARED_BLOCK_REF_KEY: case BTRFS_SHARED_BLOCK_REF_KEY:
pr_info("\t\tshared block backref parent %llu\n", offset); pr_cont("shared block backref parent %llu\n", offset);
/*
* offset is supposed to be a tree block which
* must be aligned to nodesize.
*/
if (!IS_ALIGNED(offset, eb->fs_info->nodesize))
pr_info("\t\t\t(parent %llu is NOT ALIGNED to nodesize %llu)\n",
offset, (unsigned long long)eb->fs_info->nodesize);
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);
@ -117,11 +126,20 @@ static void print_extent_item(struct extent_buffer *eb, int slot, int type)
break; break;
case BTRFS_SHARED_DATA_REF_KEY: case BTRFS_SHARED_DATA_REF_KEY:
sref = (struct btrfs_shared_data_ref *)(iref + 1); sref = (struct btrfs_shared_data_ref *)(iref + 1);
pr_info("\t\tshared data backref parent %llu count %u\n", pr_cont("shared data backref parent %llu count %u\n",
offset, btrfs_shared_data_ref_count(eb, sref)); offset, btrfs_shared_data_ref_count(eb, sref));
/*
* offset is supposed to be a tree block which
* must be aligned to nodesize.
*/
if (!IS_ALIGNED(offset, eb->fs_info->nodesize))
pr_info("\t\t\t(parent %llu is NOT ALIGNED to nodesize %llu)\n",
offset, (unsigned long long)eb->fs_info->nodesize);
break; break;
default: default:
BUG(); pr_cont("(extent %llu has INVALID ref type %d)\n",
eb->start, type);
return;
} }
ptr += btrfs_extent_inline_ref_size(type); ptr += btrfs_extent_inline_ref_size(type);
} }
@ -161,8 +179,9 @@ static void print_uuid_item(struct extent_buffer *l, unsigned long offset,
} }
} }
void btrfs_print_leaf(struct btrfs_fs_info *fs_info, struct extent_buffer *l) void btrfs_print_leaf(struct extent_buffer *l)
{ {
struct btrfs_fs_info *fs_info;
int i; int i;
u32 type, nr; u32 type, nr;
struct btrfs_item *item; struct btrfs_item *item;
@ -180,6 +199,7 @@ void btrfs_print_leaf(struct btrfs_fs_info *fs_info, struct extent_buffer *l)
if (!l) if (!l)
return; return;
fs_info = l->fs_info;
nr = btrfs_header_nritems(l); nr = btrfs_header_nritems(l);
btrfs_info(fs_info, "leaf %llu total ptrs %d free space %d", btrfs_info(fs_info, "leaf %llu total ptrs %d free space %d",
@ -318,18 +338,20 @@ void btrfs_print_leaf(struct btrfs_fs_info *fs_info, struct extent_buffer *l)
} }
} }
void btrfs_print_tree(struct btrfs_fs_info *fs_info, struct extent_buffer *c) void btrfs_print_tree(struct extent_buffer *c)
{ {
struct btrfs_fs_info *fs_info;
int i; u32 nr; int i; u32 nr;
struct btrfs_key key; struct btrfs_key key;
int level; int level;
if (!c) if (!c)
return; return;
fs_info = c->fs_info;
nr = btrfs_header_nritems(c); nr = btrfs_header_nritems(c);
level = btrfs_header_level(c); level = btrfs_header_level(c);
if (level == 0) { if (level == 0) {
btrfs_print_leaf(fs_info, c); btrfs_print_leaf(c);
return; return;
} }
btrfs_info(fs_info, btrfs_info(fs_info,
@ -359,7 +381,7 @@ void btrfs_print_tree(struct btrfs_fs_info *fs_info, struct extent_buffer *c)
if (btrfs_header_level(next) != if (btrfs_header_level(next) !=
level - 1) level - 1)
BUG(); BUG();
btrfs_print_tree(fs_info, next); btrfs_print_tree(next);
free_extent_buffer(next); free_extent_buffer(next);
} }
} }

View File

@ -18,6 +18,6 @@
#ifndef __PRINT_TREE_ #ifndef __PRINT_TREE_
#define __PRINT_TREE_ #define __PRINT_TREE_
void btrfs_print_leaf(struct btrfs_fs_info *fs_info, struct extent_buffer *l); void btrfs_print_leaf(struct extent_buffer *l);
void btrfs_print_tree(struct btrfs_fs_info *fs_info, struct extent_buffer *c); void btrfs_print_tree(struct extent_buffer *c);
#endif #endif

View File

@ -403,28 +403,28 @@ static int prop_compression_apply(struct inode *inode,
if (len == 0) { if (len == 0) {
BTRFS_I(inode)->flags |= BTRFS_INODE_NOCOMPRESS; BTRFS_I(inode)->flags |= BTRFS_INODE_NOCOMPRESS;
BTRFS_I(inode)->flags &= ~BTRFS_INODE_COMPRESS; BTRFS_I(inode)->flags &= ~BTRFS_INODE_COMPRESS;
BTRFS_I(inode)->force_compress = BTRFS_COMPRESS_NONE; BTRFS_I(inode)->prop_compress = BTRFS_COMPRESS_NONE;
return 0; return 0;
} }
if (!strncmp("lzo", value, len)) if (!strncmp("lzo", value, 3))
type = BTRFS_COMPRESS_LZO; type = BTRFS_COMPRESS_LZO;
else if (!strncmp("zlib", value, len)) else if (!strncmp("zlib", value, 4))
type = BTRFS_COMPRESS_ZLIB; type = BTRFS_COMPRESS_ZLIB;
else else
return -EINVAL; return -EINVAL;
BTRFS_I(inode)->flags &= ~BTRFS_INODE_NOCOMPRESS; BTRFS_I(inode)->flags &= ~BTRFS_INODE_NOCOMPRESS;
BTRFS_I(inode)->flags |= BTRFS_INODE_COMPRESS; BTRFS_I(inode)->flags |= BTRFS_INODE_COMPRESS;
BTRFS_I(inode)->force_compress = type; BTRFS_I(inode)->prop_compress = type;
return 0; return 0;
} }
static const char *prop_compression_extract(struct inode *inode) static const char *prop_compression_extract(struct inode *inode)
{ {
switch (BTRFS_I(inode)->force_compress) { switch (BTRFS_I(inode)->prop_compress) {
case BTRFS_COMPRESS_ZLIB: case BTRFS_COMPRESS_ZLIB:
return "zlib"; return "zlib";
case BTRFS_COMPRESS_LZO: case BTRFS_COMPRESS_LZO:

View File

@ -946,7 +946,6 @@ out:
int btrfs_quota_disable(struct btrfs_trans_handle *trans, int btrfs_quota_disable(struct btrfs_trans_handle *trans,
struct btrfs_fs_info *fs_info) struct btrfs_fs_info *fs_info)
{ {
struct btrfs_root *tree_root = fs_info->tree_root;
struct btrfs_root *quota_root; struct btrfs_root *quota_root;
int ret = 0; int ret = 0;
@ -968,7 +967,7 @@ int btrfs_quota_disable(struct btrfs_trans_handle *trans,
if (ret) if (ret)
goto out; goto out;
ret = btrfs_del_root(trans, tree_root, &quota_root->root_key); ret = btrfs_del_root(trans, fs_info, &quota_root->root_key);
if (ret) if (ret)
goto out; goto out;
@ -1603,7 +1602,7 @@ int btrfs_qgroup_trace_subtree(struct btrfs_trans_handle *trans,
struct extent_buffer *eb = root_eb; struct extent_buffer *eb = root_eb;
struct btrfs_path *path = NULL; struct btrfs_path *path = NULL;
BUG_ON(root_level < 0 || root_level > BTRFS_MAX_LEVEL); BUG_ON(root_level < 0 || root_level >= BTRFS_MAX_LEVEL);
BUG_ON(root_eb == NULL); BUG_ON(root_eb == NULL);
if (!test_bit(BTRFS_FS_QUOTA_ENABLED, &fs_info->flags)) if (!test_bit(BTRFS_FS_QUOTA_ENABLED, &fs_info->flags))
@ -2646,7 +2645,7 @@ out:
if (IS_ERR(trans)) { if (IS_ERR(trans)) {
err = PTR_ERR(trans); err = PTR_ERR(trans);
btrfs_err(fs_info, btrfs_err(fs_info,
"fail to start transaction for status update: %d\n", "fail to start transaction for status update: %d",
err); err);
goto done; goto done;
} }

View File

@ -32,6 +32,7 @@
#include "free-space-cache.h" #include "free-space-cache.h"
#include "inode-map.h" #include "inode-map.h"
#include "qgroup.h" #include "qgroup.h"
#include "print-tree.h"
/* /*
* backref_node, mapping_node and tree_block start with this * backref_node, mapping_node and tree_block start with this
@ -799,9 +800,17 @@ again:
if (ptr < end) { if (ptr < end) {
/* update key for inline back ref */ /* update key for inline back ref */
struct btrfs_extent_inline_ref *iref; struct btrfs_extent_inline_ref *iref;
int type;
iref = (struct btrfs_extent_inline_ref *)ptr; iref = (struct btrfs_extent_inline_ref *)ptr;
key.type = btrfs_extent_inline_ref_type(eb, iref); type = btrfs_get_extent_inline_ref_type(eb, iref,
BTRFS_REF_TYPE_BLOCK);
if (type == BTRFS_REF_TYPE_INVALID) {
err = -EINVAL;
goto out;
}
key.type = type;
key.offset = btrfs_extent_inline_ref_offset(eb, iref); key.offset = btrfs_extent_inline_ref_offset(eb, iref);
WARN_ON(key.type != BTRFS_TREE_BLOCK_REF_KEY && WARN_ON(key.type != BTRFS_TREE_BLOCK_REF_KEY &&
key.type != BTRFS_SHARED_BLOCK_REF_KEY); key.type != BTRFS_SHARED_BLOCK_REF_KEY);
} }
@ -1308,8 +1317,6 @@ static int __must_check __add_reloc_root(struct btrfs_root *root)
btrfs_panic(fs_info, -EEXIST, btrfs_panic(fs_info, -EEXIST,
"Duplicate root found for start=%llu while inserting into relocation tree", "Duplicate root found for start=%llu while inserting into relocation tree",
node->bytenr); node->bytenr);
kfree(node);
return -EEXIST;
} }
list_add_tail(&root->root_list, &rc->reloc_roots); list_add_tail(&root->root_list, &rc->reloc_roots);
@ -3477,7 +3484,16 @@ again:
goto again; goto again;
} }
} }
BUG_ON(ret); if (ret) {
ASSERT(ret == 1);
btrfs_print_leaf(path->nodes[0]);
btrfs_err(fs_info,
"tree block extent item (%llu) is not found in extent tree",
bytenr);
WARN_ON(1);
ret = -EINVAL;
goto out;
}
ret = add_tree_block(rc, &key, path, blocks); ret = add_tree_block(rc, &key, path, blocks);
out: out:
@ -3755,7 +3771,8 @@ int add_data_references(struct reloc_control *rc,
while (ptr < end) { while (ptr < end) {
iref = (struct btrfs_extent_inline_ref *)ptr; iref = (struct btrfs_extent_inline_ref *)ptr;
key.type = btrfs_extent_inline_ref_type(eb, iref); key.type = btrfs_get_extent_inline_ref_type(eb, iref,
BTRFS_REF_TYPE_DATA);
if (key.type == BTRFS_SHARED_DATA_REF_KEY) { if (key.type == BTRFS_SHARED_DATA_REF_KEY) {
key.offset = btrfs_extent_inline_ref_offset(eb, iref); key.offset = btrfs_extent_inline_ref_offset(eb, iref);
ret = __add_tree_block(rc, key.offset, blocksize, ret = __add_tree_block(rc, key.offset, blocksize,
@ -3765,7 +3782,10 @@ int add_data_references(struct reloc_control *rc,
ret = find_data_references(rc, extent_key, ret = find_data_references(rc, extent_key,
eb, dref, blocks); eb, dref, blocks);
} else { } else {
BUG(); ret = -EINVAL;
btrfs_err(rc->extent_root->fs_info,
"extent %llu slot %d has an invalid inline ref type",
eb->start, path->slots[0]);
} }
if (ret) { if (ret) {
err = ret; err = ret;

View File

@ -151,7 +151,7 @@ int btrfs_update_root(struct btrfs_trans_handle *trans, struct btrfs_root
} }
if (ret != 0) { if (ret != 0) {
btrfs_print_leaf(fs_info, path->nodes[0]); btrfs_print_leaf(path->nodes[0]);
btrfs_crit(fs_info, "unable to update root key %llu %u %llu", btrfs_crit(fs_info, "unable to update root key %llu %u %llu",
key->objectid, key->type, key->offset); key->objectid, key->type, key->offset);
BUG_ON(1); BUG_ON(1);
@ -335,10 +335,11 @@ int btrfs_find_orphan_roots(struct btrfs_fs_info *fs_info)
return err; return err;
} }
/* drop the root item for 'key' from 'root' */ /* drop the root item for 'key' from the tree root */
int btrfs_del_root(struct btrfs_trans_handle *trans, struct btrfs_root *root, int btrfs_del_root(struct btrfs_trans_handle *trans,
const struct btrfs_key *key) struct btrfs_fs_info *fs_info, const struct btrfs_key *key)
{ {
struct btrfs_root *root = fs_info->tree_root;
struct btrfs_path *path; struct btrfs_path *path;
int ret; int ret;

View File

@ -182,8 +182,8 @@ struct scrub_ctx {
struct scrub_bio *wr_curr_bio; struct scrub_bio *wr_curr_bio;
struct mutex wr_lock; struct mutex wr_lock;
int pages_per_wr_bio; /* <= SCRUB_PAGES_PER_WR_BIO */ int pages_per_wr_bio; /* <= SCRUB_PAGES_PER_WR_BIO */
atomic_t flush_all_writes;
struct btrfs_device *wr_tgtdev; struct btrfs_device *wr_tgtdev;
bool flush_all_writes;
/* /*
* statistics * statistics
@ -717,7 +717,7 @@ struct scrub_ctx *scrub_setup_ctx(struct btrfs_device *dev, int is_dev_replace)
WARN_ON(!fs_info->dev_replace.tgtdev); WARN_ON(!fs_info->dev_replace.tgtdev);
sctx->pages_per_wr_bio = SCRUB_PAGES_PER_WR_BIO; sctx->pages_per_wr_bio = SCRUB_PAGES_PER_WR_BIO;
sctx->wr_tgtdev = fs_info->dev_replace.tgtdev; sctx->wr_tgtdev = fs_info->dev_replace.tgtdev;
atomic_set(&sctx->flush_all_writes, 0); sctx->flush_all_writes = false;
} }
return sctx; return sctx;
@ -1704,7 +1704,7 @@ static int scrub_submit_raid56_bio_wait(struct btrfs_fs_info *fs_info,
if (ret) if (ret)
return ret; return ret;
wait_for_completion(&done.event); wait_for_completion_io(&done.event);
if (done.status) if (done.status)
return -EIO; return -EIO;
@ -1769,7 +1769,7 @@ static inline int scrub_check_fsid(u8 fsid[],
struct btrfs_fs_devices *fs_devices = spage->dev->fs_devices; struct btrfs_fs_devices *fs_devices = spage->dev->fs_devices;
int ret; int ret;
ret = memcmp(fsid, fs_devices->fsid, BTRFS_UUID_SIZE); ret = memcmp(fsid, fs_devices->fsid, BTRFS_FSID_SIZE);
return !ret; return !ret;
} }
@ -2402,8 +2402,7 @@ static void scrub_missing_raid56_worker(struct btrfs_work *work)
scrub_block_put(sblock); scrub_block_put(sblock);
if (sctx->is_dev_replace && if (sctx->is_dev_replace && sctx->flush_all_writes) {
atomic_read(&sctx->flush_all_writes)) {
mutex_lock(&sctx->wr_lock); mutex_lock(&sctx->wr_lock);
scrub_wr_submit(sctx); scrub_wr_submit(sctx);
mutex_unlock(&sctx->wr_lock); mutex_unlock(&sctx->wr_lock);
@ -2607,8 +2606,7 @@ static void scrub_bio_end_io_worker(struct btrfs_work *work)
sctx->first_free = sbio->index; sctx->first_free = sbio->index;
spin_unlock(&sctx->list_lock); spin_unlock(&sctx->list_lock);
if (sctx->is_dev_replace && if (sctx->is_dev_replace && sctx->flush_all_writes) {
atomic_read(&sctx->flush_all_writes)) {
mutex_lock(&sctx->wr_lock); mutex_lock(&sctx->wr_lock);
scrub_wr_submit(sctx); scrub_wr_submit(sctx);
mutex_unlock(&sctx->wr_lock); mutex_unlock(&sctx->wr_lock);
@ -2622,7 +2620,8 @@ static inline void __scrub_mark_bitmap(struct scrub_parity *sparity,
u64 start, u64 len) u64 start, u64 len)
{ {
u64 offset; u64 offset;
int nsectors; u64 nsectors64;
u32 nsectors;
int sectorsize = sparity->sctx->fs_info->sectorsize; int sectorsize = sparity->sctx->fs_info->sectorsize;
if (len >= sparity->stripe_len) { if (len >= sparity->stripe_len) {
@ -2633,7 +2632,10 @@ static inline void __scrub_mark_bitmap(struct scrub_parity *sparity,
start -= sparity->logic_start; start -= sparity->logic_start;
start = div64_u64_rem(start, sparity->stripe_len, &offset); start = div64_u64_rem(start, sparity->stripe_len, &offset);
offset = div_u64(offset, sectorsize); offset = div_u64(offset, sectorsize);
nsectors = (int)len / sectorsize; nsectors64 = div_u64(len, sectorsize);
ASSERT(nsectors64 < UINT_MAX);
nsectors = (u32)nsectors64;
if (offset + nsectors <= sparity->nsectors) { if (offset + nsectors <= sparity->nsectors) {
bitmap_set(bitmap, offset, nsectors); bitmap_set(bitmap, offset, nsectors);
@ -2706,7 +2708,9 @@ static int scrub_find_csum(struct scrub_ctx *sctx, u64 logical, u8 *csum)
if (!sum) if (!sum)
return 0; return 0;
index = ((u32)(logical - sum->bytenr)) / sctx->fs_info->sectorsize; index = div_u64(logical - sum->bytenr, sctx->fs_info->sectorsize);
ASSERT(index < UINT_MAX);
num_sectors = sum->len / sctx->fs_info->sectorsize; num_sectors = sum->len / sctx->fs_info->sectorsize;
memcpy(csum, sum->sums + index, sctx->csum_size); memcpy(csum, sum->sums + index, sctx->csum_size);
if (index == num_sectors - 1) { if (index == num_sectors - 1) {
@ -3440,14 +3444,14 @@ static noinline_for_stack int scrub_stripe(struct scrub_ctx *sctx,
*/ */
if (atomic_read(&fs_info->scrub_pause_req)) { if (atomic_read(&fs_info->scrub_pause_req)) {
/* push queued extents */ /* push queued extents */
atomic_set(&sctx->flush_all_writes, 1); sctx->flush_all_writes = true;
scrub_submit(sctx); scrub_submit(sctx);
mutex_lock(&sctx->wr_lock); mutex_lock(&sctx->wr_lock);
scrub_wr_submit(sctx); scrub_wr_submit(sctx);
mutex_unlock(&sctx->wr_lock); mutex_unlock(&sctx->wr_lock);
wait_event(sctx->list_wait, wait_event(sctx->list_wait,
atomic_read(&sctx->bios_in_flight) == 0); atomic_read(&sctx->bios_in_flight) == 0);
atomic_set(&sctx->flush_all_writes, 0); sctx->flush_all_writes = false;
scrub_blocked_if_needed(fs_info); scrub_blocked_if_needed(fs_info);
} }
@ -3869,8 +3873,7 @@ int scrub_enumerate_chunks(struct scrub_ctx *sctx,
ro_set = 0; ro_set = 0;
} else { } else {
btrfs_warn(fs_info, btrfs_warn(fs_info,
"failed setting block group ro, ret=%d\n", "failed setting block group ro: %d", ret);
ret);
btrfs_put_block_group(cache); btrfs_put_block_group(cache);
break; break;
} }
@ -3893,7 +3896,7 @@ int scrub_enumerate_chunks(struct scrub_ctx *sctx,
* write requests are really completed when bios_in_flight * write requests are really completed when bios_in_flight
* changes to 0. * changes to 0.
*/ */
atomic_set(&sctx->flush_all_writes, 1); sctx->flush_all_writes = true;
scrub_submit(sctx); scrub_submit(sctx);
mutex_lock(&sctx->wr_lock); mutex_lock(&sctx->wr_lock);
scrub_wr_submit(sctx); scrub_wr_submit(sctx);
@ -3911,7 +3914,7 @@ int scrub_enumerate_chunks(struct scrub_ctx *sctx,
*/ */
wait_event(sctx->list_wait, wait_event(sctx->list_wait,
atomic_read(&sctx->workers_pending) == 0); atomic_read(&sctx->workers_pending) == 0);
atomic_set(&sctx->flush_all_writes, 0); sctx->flush_all_writes = false;
scrub_pause_off(fs_info); scrub_pause_off(fs_info);
@ -4012,14 +4015,8 @@ static noinline_for_stack int scrub_workers_get(struct btrfs_fs_info *fs_info,
int max_active = fs_info->thread_pool_size; int max_active = fs_info->thread_pool_size;
if (fs_info->scrub_workers_refcnt == 0) { if (fs_info->scrub_workers_refcnt == 0) {
if (is_dev_replace) fs_info->scrub_workers = btrfs_alloc_workqueue(fs_info, "scrub",
fs_info->scrub_workers = flags, is_dev_replace ? 1 : max_active, 4);
btrfs_alloc_workqueue(fs_info, "scrub", flags,
1, 4);
else
fs_info->scrub_workers =
btrfs_alloc_workqueue(fs_info, "scrub", flags,
max_active, 4);
if (!fs_info->scrub_workers) if (!fs_info->scrub_workers)
goto fail_scrub_workers; goto fail_scrub_workers;

View File

@ -4733,7 +4733,7 @@ static ssize_t fill_read_buf(struct send_ctx *sctx, u64 offset, u32 len)
/* initial readahead */ /* initial readahead */
memset(&sctx->ra, 0, sizeof(struct file_ra_state)); memset(&sctx->ra, 0, sizeof(struct file_ra_state));
file_ra_state_init(&sctx->ra, inode->i_mapping); file_ra_state_init(&sctx->ra, inode->i_mapping);
btrfs_force_ra(inode->i_mapping, &sctx->ra, NULL, index, page_cache_sync_readahead(inode->i_mapping, &sctx->ra, NULL, index,
last_index - index + 1); last_index - index + 1);
while (index <= last_index) { while (index <= last_index) {
@ -4992,6 +4992,25 @@ static int clone_range(struct send_ctx *sctx,
struct btrfs_key key; struct btrfs_key key;
int ret; int ret;
/*
* Prevent cloning from a zero offset with a length matching the sector
* size because in some scenarios this will make the receiver fail.
*
* For example, if in the source filesystem the extent at offset 0
* has a length of sectorsize and it was written using direct IO, then
* it can never be an inline extent (even if compression is enabled).
* Then this extent can be cloned in the original filesystem to a non
* zero file offset, but it may not be possible to clone in the
* destination filesystem because it can be inlined due to compression
* on the destination filesystem (as the receiver's write operations are
* always done using buffered IO). The same happens when the original
* filesystem does not have compression enabled but the destination
* filesystem has.
*/
if (clone_root->offset == 0 &&
len == sctx->send_root->fs_info->sectorsize)
return send_extent_data(sctx, offset, len);
path = alloc_path_for_send(); path = alloc_path_for_send();
if (!path) if (!path)
return -ENOMEM; return -ENOMEM;

View File

@ -50,8 +50,8 @@ static inline void put_unaligned_le8(u8 val, void *p)
*/ */
#define DEFINE_BTRFS_SETGET_BITS(bits) \ #define DEFINE_BTRFS_SETGET_BITS(bits) \
u##bits btrfs_get_token_##bits(struct extent_buffer *eb, void *ptr, \ u##bits btrfs_get_token_##bits(const struct extent_buffer *eb, \
unsigned long off, \ const void *ptr, unsigned long off, \
struct btrfs_map_token *token) \ struct btrfs_map_token *token) \
{ \ { \
unsigned long part_offset = (unsigned long)ptr; \ unsigned long part_offset = (unsigned long)ptr; \
@ -90,7 +90,8 @@ u##bits btrfs_get_token_##bits(struct extent_buffer *eb, void *ptr, \
return res; \ return res; \
} \ } \
void btrfs_set_token_##bits(struct extent_buffer *eb, \ void btrfs_set_token_##bits(struct extent_buffer *eb, \
void *ptr, unsigned long off, u##bits val, \ const void *ptr, unsigned long off, \
u##bits val, \
struct btrfs_map_token *token) \ struct btrfs_map_token *token) \
{ \ { \
unsigned long part_offset = (unsigned long)ptr; \ unsigned long part_offset = (unsigned long)ptr; \
@ -133,7 +134,7 @@ DEFINE_BTRFS_SETGET_BITS(16)
DEFINE_BTRFS_SETGET_BITS(32) DEFINE_BTRFS_SETGET_BITS(32)
DEFINE_BTRFS_SETGET_BITS(64) DEFINE_BTRFS_SETGET_BITS(64)
void btrfs_node_key(struct extent_buffer *eb, void btrfs_node_key(const struct extent_buffer *eb,
struct btrfs_disk_key *disk_key, int nr) struct btrfs_disk_key *disk_key, int nr)
{ {
unsigned long ptr = btrfs_node_key_ptr_offset(nr); unsigned long ptr = btrfs_node_key_ptr_offset(nr);

View File

@ -61,6 +61,7 @@
#include "tests/btrfs-tests.h" #include "tests/btrfs-tests.h"
#include "qgroup.h" #include "qgroup.h"
#include "backref.h"
#define CREATE_TRACE_POINTS #define CREATE_TRACE_POINTS
#include <trace/events/btrfs.h> #include <trace/events/btrfs.h>
@ -425,7 +426,7 @@ int btrfs_parse_options(struct btrfs_fs_info *info, char *options,
* strsep changes the string, duplicate it because parse_options * strsep changes the string, duplicate it because parse_options
* gets called twice * gets called twice
*/ */
options = kstrdup(options, GFP_NOFS); options = kstrdup(options, GFP_KERNEL);
if (!options) if (!options)
return -ENOMEM; return -ENOMEM;
@ -498,14 +499,14 @@ int btrfs_parse_options(struct btrfs_fs_info *info, char *options,
btrfs_test_opt(info, FORCE_COMPRESS); btrfs_test_opt(info, FORCE_COMPRESS);
if (token == Opt_compress || if (token == Opt_compress ||
token == Opt_compress_force || token == Opt_compress_force ||
strcmp(args[0].from, "zlib") == 0) { strncmp(args[0].from, "zlib", 4) == 0) {
compress_type = "zlib"; compress_type = "zlib";
info->compress_type = BTRFS_COMPRESS_ZLIB; info->compress_type = BTRFS_COMPRESS_ZLIB;
btrfs_set_opt(info->mount_opt, COMPRESS); btrfs_set_opt(info->mount_opt, COMPRESS);
btrfs_clear_opt(info->mount_opt, NODATACOW); btrfs_clear_opt(info->mount_opt, NODATACOW);
btrfs_clear_opt(info->mount_opt, NODATASUM); btrfs_clear_opt(info->mount_opt, NODATASUM);
no_compress = 0; no_compress = 0;
} else if (strcmp(args[0].from, "lzo") == 0) { } else if (strncmp(args[0].from, "lzo", 3) == 0) {
compress_type = "lzo"; compress_type = "lzo";
info->compress_type = BTRFS_COMPRESS_LZO; info->compress_type = BTRFS_COMPRESS_LZO;
btrfs_set_opt(info->mount_opt, COMPRESS); btrfs_set_opt(info->mount_opt, COMPRESS);
@ -548,20 +549,22 @@ int btrfs_parse_options(struct btrfs_fs_info *info, char *options,
break; break;
case Opt_ssd: case Opt_ssd:
btrfs_set_and_info(info, SSD, btrfs_set_and_info(info, SSD,
"use ssd allocation scheme"); "enabling ssd optimizations");
btrfs_clear_opt(info->mount_opt, NOSSD); btrfs_clear_opt(info->mount_opt, NOSSD);
break; break;
case Opt_ssd_spread: case Opt_ssd_spread:
btrfs_set_and_info(info, SSD,
"enabling ssd optimizations");
btrfs_set_and_info(info, SSD_SPREAD, btrfs_set_and_info(info, SSD_SPREAD,
"use spread ssd allocation scheme"); "using spread ssd allocation scheme");
btrfs_set_opt(info->mount_opt, SSD);
btrfs_clear_opt(info->mount_opt, NOSSD); btrfs_clear_opt(info->mount_opt, NOSSD);
break; break;
case Opt_nossd: case Opt_nossd:
btrfs_set_and_info(info, NOSSD, btrfs_set_opt(info->mount_opt, NOSSD);
"not using ssd allocation scheme"); btrfs_clear_and_info(info, SSD,
btrfs_clear_opt(info->mount_opt, SSD); "not using ssd optimizations");
btrfs_clear_opt(info->mount_opt, SSD_SPREAD); btrfs_clear_and_info(info, SSD_SPREAD,
"not using spread ssd allocation scheme");
break; break;
case Opt_barrier: case Opt_barrier:
btrfs_clear_and_info(info, NOBARRIER, btrfs_clear_and_info(info, NOBARRIER,
@ -949,7 +952,7 @@ static char *get_subvol_name_from_objectid(struct btrfs_fs_info *fs_info,
} }
path->leave_spinning = 1; path->leave_spinning = 1;
name = kmalloc(PATH_MAX, GFP_NOFS); name = kmalloc(PATH_MAX, GFP_KERNEL);
if (!name) { if (!name) {
ret = -ENOMEM; ret = -ENOMEM;
goto err; goto err;
@ -1335,10 +1338,11 @@ static char *setup_root_args(char *args)
char *buf, *dst, *sep; char *buf, *dst, *sep;
if (!args) if (!args)
return kstrdup("subvolid=0", GFP_NOFS); return kstrdup("subvolid=0", GFP_KERNEL);
/* The worst case is that we add ",subvolid=0" to the end. */ /* The worst case is that we add ",subvolid=0" to the end. */
buf = dst = kmalloc(strlen(args) + strlen(",subvolid=0") + 1, GFP_NOFS); buf = dst = kmalloc(strlen(args) + strlen(",subvolid=0") + 1,
GFP_KERNEL);
if (!buf) if (!buf)
return NULL; return NULL;
@ -1567,7 +1571,7 @@ static struct dentry *btrfs_mount(struct file_system_type *fs_type, int flags,
* it for searching for existing supers, so this lets us do that and * it for searching for existing supers, so this lets us do that and
* then open_ctree will properly initialize everything later. * then open_ctree will properly initialize everything later.
*/ */
fs_info = kzalloc(sizeof(struct btrfs_fs_info), GFP_NOFS); fs_info = kzalloc(sizeof(struct btrfs_fs_info), GFP_KERNEL);
if (!fs_info) { if (!fs_info) {
error = -ENOMEM; error = -ENOMEM;
goto error_sec_opts; goto error_sec_opts;
@ -1575,8 +1579,8 @@ static struct dentry *btrfs_mount(struct file_system_type *fs_type, int flags,
fs_info->fs_devices = fs_devices; fs_info->fs_devices = fs_devices;
fs_info->super_copy = kzalloc(BTRFS_SUPER_INFO_SIZE, GFP_NOFS); fs_info->super_copy = kzalloc(BTRFS_SUPER_INFO_SIZE, GFP_KERNEL);
fs_info->super_for_commit = kzalloc(BTRFS_SUPER_INFO_SIZE, GFP_NOFS); fs_info->super_for_commit = kzalloc(BTRFS_SUPER_INFO_SIZE, GFP_KERNEL);
security_init_mnt_opts(&fs_info->security_opts); security_init_mnt_opts(&fs_info->security_opts);
if (!fs_info->super_copy || !fs_info->super_for_commit) { if (!fs_info->super_copy || !fs_info->super_for_commit) {
error = -ENOMEM; error = -ENOMEM;
@ -1780,8 +1784,7 @@ static int btrfs_remount(struct super_block *sb, int *flags, char *data)
goto restore; goto restore;
} }
if (fs_info->fs_devices->missing_devices > if (!btrfs_check_rw_degradable(fs_info)) {
fs_info->num_tolerated_disk_barrier_failures) {
btrfs_warn(fs_info, btrfs_warn(fs_info,
"too many missing devices, writeable remount is not allowed"); "too many missing devices, writeable remount is not allowed");
ret = -EACCES; ret = -EACCES;
@ -1814,6 +1817,8 @@ static int btrfs_remount(struct super_block *sb, int *flags, char *data)
goto restore; goto restore;
} }
btrfs_qgroup_rescan_resume(fs_info);
if (!fs_info->uuid_root) { if (!fs_info->uuid_root) {
btrfs_info(fs_info, "creating UUID tree"); btrfs_info(fs_info, "creating UUID tree");
ret = btrfs_create_uuid_tree(fs_info); ret = btrfs_create_uuid_tree(fs_info);

View File

@ -211,7 +211,6 @@ btrfs_alloc_dummy_block_group(struct btrfs_fs_info *fs_info,
cache->key.objectid = 0; cache->key.objectid = 0;
cache->key.offset = length; cache->key.offset = length;
cache->key.type = BTRFS_BLOCK_GROUP_ITEM_KEY; cache->key.type = BTRFS_BLOCK_GROUP_ITEM_KEY;
cache->sectorsize = fs_info->sectorsize;
cache->full_stripe_len = fs_info->sectorsize; cache->full_stripe_len = fs_info->sectorsize;
cache->fs_info = fs_info; cache->fs_info = fs_info;

View File

@ -81,7 +81,7 @@ static int __check_free_space_extents(struct btrfs_trans_handle *trans,
i++; i++;
} }
prev_bit = bit; prev_bit = bit;
offset += cache->sectorsize; offset += fs_info->sectorsize;
} }
} }
if (prev_bit == 1) { if (prev_bit == 1) {

View File

@ -1143,8 +1143,6 @@ again:
goto again; goto again;
} }
kfree(victim_name); kfree(victim_name);
if (ret)
return ret;
next: next:
cur_offset += victim_name_len + sizeof(*extref); cur_offset += victim_name_len + sizeof(*extref);
} }
@ -3690,7 +3688,7 @@ static noinline int copy_items(struct btrfs_trans_handle *trans,
src_offset = btrfs_item_ptr_offset(src, start_slot + i); src_offset = btrfs_item_ptr_offset(src, start_slot + i);
if ((i == (nr - 1))) if (i == nr - 1)
last_key = ins_keys[i]; last_key = ins_keys[i];
if (ins_keys[i].type == BTRFS_INODE_ITEM_KEY) { if (ins_keys[i].type == BTRFS_INODE_ITEM_KEY) {
@ -4450,7 +4448,10 @@ static int btrfs_log_trailing_hole(struct btrfs_trans_handle *trans,
len = btrfs_file_extent_inline_len(leaf, len = btrfs_file_extent_inline_len(leaf,
path->slots[0], path->slots[0],
extent); extent);
ASSERT(len == i_size); ASSERT(len == i_size ||
(len == fs_info->sectorsize &&
btrfs_file_extent_compression(leaf, extent) !=
BTRFS_COMPRESS_NONE));
return 0; return 0;
} }

View File

@ -152,7 +152,15 @@ struct list_head *btrfs_get_fs_uuids(void)
return &fs_uuids; return &fs_uuids;
} }
static struct btrfs_fs_devices *__alloc_fs_devices(void) /*
* alloc_fs_devices - allocate struct btrfs_fs_devices
* @fsid: if not NULL, copy the uuid to fs_devices::fsid
*
* Return a pointer to a new struct btrfs_fs_devices on success, or ERR_PTR().
* The returned struct is not linked onto any lists and can be destroyed with
* kfree() right away.
*/
static struct btrfs_fs_devices *alloc_fs_devices(const u8 *fsid)
{ {
struct btrfs_fs_devices *fs_devs; struct btrfs_fs_devices *fs_devs;
@ -166,31 +174,8 @@ static struct btrfs_fs_devices *__alloc_fs_devices(void)
INIT_LIST_HEAD(&fs_devs->resized_devices); INIT_LIST_HEAD(&fs_devs->resized_devices);
INIT_LIST_HEAD(&fs_devs->alloc_list); INIT_LIST_HEAD(&fs_devs->alloc_list);
INIT_LIST_HEAD(&fs_devs->list); INIT_LIST_HEAD(&fs_devs->list);
return fs_devs;
}
/**
* alloc_fs_devices - allocate struct btrfs_fs_devices
* @fsid: a pointer to UUID for this FS. If NULL a new UUID is
* generated.
*
* Return: a pointer to a new &struct btrfs_fs_devices on success;
* ERR_PTR() on error. Returned struct is not linked onto any lists and
* can be destroyed with kfree() right away.
*/
static struct btrfs_fs_devices *alloc_fs_devices(const u8 *fsid)
{
struct btrfs_fs_devices *fs_devs;
fs_devs = __alloc_fs_devices();
if (IS_ERR(fs_devs))
return fs_devs;
if (fsid) if (fsid)
memcpy(fs_devs->fsid, fsid, BTRFS_FSID_SIZE); memcpy(fs_devs->fsid, fsid, BTRFS_FSID_SIZE);
else
generate_random_uuid(fs_devs->fsid);
return fs_devs; return fs_devs;
} }
@ -269,9 +254,17 @@ static struct btrfs_device *__alloc_device(void)
return dev; return dev;
} }
static noinline struct btrfs_device *__find_device(struct list_head *head, /*
u64 devid, u8 *uuid) * Find a device specified by @devid or @uuid in the list of @fs_devices, or
* return NULL.
*
* If devid and uuid are both specified, the match must be exact, otherwise
* only devid is used.
*/
static struct btrfs_device *find_device(struct btrfs_fs_devices *fs_devices,
u64 devid, const u8 *uuid)
{ {
struct list_head *head = &fs_devices->devices;
struct btrfs_device *dev; struct btrfs_device *dev;
list_for_each_entry(dev, head, dev_list) { list_for_each_entry(dev, head, dev_list) {
@ -310,7 +303,7 @@ btrfs_get_bdev_and_sb(const char *device_path, fmode_t flags, void *holder,
if (flush) if (flush)
filemap_write_and_wait((*bdev)->bd_inode->i_mapping); filemap_write_and_wait((*bdev)->bd_inode->i_mapping);
ret = set_blocksize(*bdev, 4096); ret = set_blocksize(*bdev, BTRFS_BDEV_BLOCKSIZE);
if (ret) { if (ret) {
blkdev_put(*bdev, flags); blkdev_put(*bdev, flags);
goto error; goto error;
@ -636,8 +629,8 @@ static noinline int device_list_add(const char *path,
device = NULL; device = NULL;
} else { } else {
device = __find_device(&fs_devices->devices, devid, device = find_device(fs_devices, devid,
disk_super->dev_item.uuid); disk_super->dev_item.uuid);
} }
if (!device) { if (!device) {
@ -1578,7 +1571,6 @@ out:
static int btrfs_alloc_dev_extent(struct btrfs_trans_handle *trans, static int btrfs_alloc_dev_extent(struct btrfs_trans_handle *trans,
struct btrfs_device *device, struct btrfs_device *device,
u64 chunk_tree, u64 chunk_objectid,
u64 chunk_offset, u64 start, u64 num_bytes) u64 chunk_offset, u64 start, u64 num_bytes)
{ {
int ret; int ret;
@ -1606,12 +1598,12 @@ static int btrfs_alloc_dev_extent(struct btrfs_trans_handle *trans,
leaf = path->nodes[0]; leaf = path->nodes[0];
extent = btrfs_item_ptr(leaf, path->slots[0], extent = btrfs_item_ptr(leaf, path->slots[0],
struct btrfs_dev_extent); struct btrfs_dev_extent);
btrfs_set_dev_extent_chunk_tree(leaf, extent, chunk_tree); btrfs_set_dev_extent_chunk_tree(leaf, extent,
btrfs_set_dev_extent_chunk_objectid(leaf, extent, chunk_objectid); BTRFS_CHUNK_TREE_OBJECTID);
btrfs_set_dev_extent_chunk_objectid(leaf, extent,
BTRFS_FIRST_CHUNK_TREE_OBJECTID);
btrfs_set_dev_extent_chunk_offset(leaf, extent, chunk_offset); btrfs_set_dev_extent_chunk_offset(leaf, extent, chunk_offset);
write_extent_buffer_chunk_tree_uuid(leaf, fs_info->chunk_tree_uuid);
btrfs_set_dev_extent_length(leaf, extent, num_bytes); btrfs_set_dev_extent_length(leaf, extent, num_bytes);
btrfs_mark_buffer_dirty(leaf); btrfs_mark_buffer_dirty(leaf);
out: out:
@ -1726,7 +1718,7 @@ static int btrfs_add_device(struct btrfs_trans_handle *trans,
ptr = btrfs_device_uuid(dev_item); ptr = btrfs_device_uuid(dev_item);
write_extent_buffer(leaf, device->uuid, ptr, BTRFS_UUID_SIZE); write_extent_buffer(leaf, device->uuid, ptr, BTRFS_UUID_SIZE);
ptr = btrfs_device_fsid(dev_item); ptr = btrfs_device_fsid(dev_item);
write_extent_buffer(leaf, fs_info->fsid, ptr, BTRFS_UUID_SIZE); write_extent_buffer(leaf, fs_info->fsid, ptr, BTRFS_FSID_SIZE);
btrfs_mark_buffer_dirty(leaf); btrfs_mark_buffer_dirty(leaf);
ret = 0; ret = 0;
@ -1872,7 +1864,6 @@ int btrfs_rm_device(struct btrfs_fs_info *fs_info, const char *device_path,
struct btrfs_fs_devices *cur_devices; struct btrfs_fs_devices *cur_devices;
u64 num_devices; u64 num_devices;
int ret = 0; int ret = 0;
bool clear_super = false;
mutex_lock(&uuid_mutex); mutex_lock(&uuid_mutex);
@ -1908,7 +1899,6 @@ int btrfs_rm_device(struct btrfs_fs_info *fs_info, const char *device_path,
list_del_init(&device->dev_alloc_list); list_del_init(&device->dev_alloc_list);
device->fs_devices->rw_devices--; device->fs_devices->rw_devices--;
mutex_unlock(&fs_info->chunk_mutex); mutex_unlock(&fs_info->chunk_mutex);
clear_super = true;
} }
mutex_unlock(&uuid_mutex); mutex_unlock(&uuid_mutex);
@ -1987,9 +1977,6 @@ int btrfs_rm_device(struct btrfs_fs_info *fs_info, const char *device_path,
free_fs_devices(cur_devices); free_fs_devices(cur_devices);
} }
fs_info->num_tolerated_disk_barrier_failures =
btrfs_calc_num_tolerated_disk_barrier_failures(fs_info);
out: out:
mutex_unlock(&uuid_mutex); mutex_unlock(&uuid_mutex);
return ret; return ret;
@ -2202,7 +2189,7 @@ static int btrfs_prepare_sprout(struct btrfs_fs_info *fs_info)
if (!fs_devices->seeding) if (!fs_devices->seeding)
return -EINVAL; return -EINVAL;
seed_devices = __alloc_fs_devices(); seed_devices = alloc_fs_devices(NULL);
if (IS_ERR(seed_devices)) if (IS_ERR(seed_devices))
return PTR_ERR(seed_devices); return PTR_ERR(seed_devices);
@ -2261,7 +2248,7 @@ static int btrfs_finish_sprout(struct btrfs_trans_handle *trans,
struct btrfs_dev_item *dev_item; struct btrfs_dev_item *dev_item;
struct btrfs_device *device; struct btrfs_device *device;
struct btrfs_key key; struct btrfs_key key;
u8 fs_uuid[BTRFS_UUID_SIZE]; u8 fs_uuid[BTRFS_FSID_SIZE];
u8 dev_uuid[BTRFS_UUID_SIZE]; u8 dev_uuid[BTRFS_UUID_SIZE];
u64 devid; u64 devid;
int ret; int ret;
@ -2304,7 +2291,7 @@ next_slot:
read_extent_buffer(leaf, dev_uuid, btrfs_device_uuid(dev_item), read_extent_buffer(leaf, dev_uuid, btrfs_device_uuid(dev_item),
BTRFS_UUID_SIZE); BTRFS_UUID_SIZE);
read_extent_buffer(leaf, fs_uuid, btrfs_device_fsid(dev_item), read_extent_buffer(leaf, fs_uuid, btrfs_device_fsid(dev_item),
BTRFS_UUID_SIZE); BTRFS_FSID_SIZE);
device = btrfs_find_device(fs_info, devid, dev_uuid, fs_uuid); device = btrfs_find_device(fs_info, devid, dev_uuid, fs_uuid);
BUG_ON(!device); /* Logic error */ BUG_ON(!device); /* Logic error */
@ -2407,7 +2394,7 @@ int btrfs_init_new_device(struct btrfs_fs_info *fs_info, const char *device_path
device->is_tgtdev_for_dev_replace = 0; device->is_tgtdev_for_dev_replace = 0;
device->mode = FMODE_EXCL; device->mode = FMODE_EXCL;
device->dev_stats_valid = 1; device->dev_stats_valid = 1;
set_blocksize(device->bdev, 4096); set_blocksize(device->bdev, BTRFS_BDEV_BLOCKSIZE);
if (seeding_dev) { if (seeding_dev) {
sb->s_flags &= ~MS_RDONLY; sb->s_flags &= ~MS_RDONLY;
@ -2487,8 +2474,6 @@ int btrfs_init_new_device(struct btrfs_fs_info *fs_info, const char *device_path
"sysfs: failed to create fsid for sprout"); "sysfs: failed to create fsid for sprout");
} }
fs_info->num_tolerated_disk_barrier_failures =
btrfs_calc_num_tolerated_disk_barrier_failures(fs_info);
ret = btrfs_commit_transaction(trans); ret = btrfs_commit_transaction(trans);
if (seeding_dev) { if (seeding_dev) {
@ -2612,7 +2597,7 @@ int btrfs_init_dev_replace_tgtdev(struct btrfs_fs_info *fs_info,
device->is_tgtdev_for_dev_replace = 1; device->is_tgtdev_for_dev_replace = 1;
device->mode = FMODE_EXCL; device->mode = FMODE_EXCL;
device->dev_stats_valid = 1; device->dev_stats_valid = 1;
set_blocksize(device->bdev, 4096); set_blocksize(device->bdev, BTRFS_BDEV_BLOCKSIZE);
device->fs_devices = fs_info->fs_devices; device->fs_devices = fs_info->fs_devices;
list_add(&device->dev_list, &fs_info->fs_devices->devices); list_add(&device->dev_list, &fs_info->fs_devices->devices);
fs_info->fs_devices->num_devices++; fs_info->fs_devices->num_devices++;
@ -2728,8 +2713,7 @@ int btrfs_grow_device(struct btrfs_trans_handle *trans,
} }
static int btrfs_free_chunk(struct btrfs_trans_handle *trans, static int btrfs_free_chunk(struct btrfs_trans_handle *trans,
struct btrfs_fs_info *fs_info, u64 chunk_objectid, struct btrfs_fs_info *fs_info, u64 chunk_offset)
u64 chunk_offset)
{ {
struct btrfs_root *root = fs_info->chunk_root; struct btrfs_root *root = fs_info->chunk_root;
int ret; int ret;
@ -2740,7 +2724,7 @@ static int btrfs_free_chunk(struct btrfs_trans_handle *trans,
if (!path) if (!path)
return -ENOMEM; return -ENOMEM;
key.objectid = chunk_objectid; key.objectid = BTRFS_FIRST_CHUNK_TREE_OBJECTID;
key.offset = chunk_offset; key.offset = chunk_offset;
key.type = BTRFS_CHUNK_ITEM_KEY; key.type = BTRFS_CHUNK_ITEM_KEY;
@ -2763,8 +2747,7 @@ out:
return ret; return ret;
} }
static int btrfs_del_sys_chunk(struct btrfs_fs_info *fs_info, static int btrfs_del_sys_chunk(struct btrfs_fs_info *fs_info, u64 chunk_offset)
u64 chunk_objectid, u64 chunk_offset)
{ {
struct btrfs_super_block *super_copy = fs_info->super_copy; struct btrfs_super_block *super_copy = fs_info->super_copy;
struct btrfs_disk_key *disk_key; struct btrfs_disk_key *disk_key;
@ -2797,7 +2780,7 @@ static int btrfs_del_sys_chunk(struct btrfs_fs_info *fs_info,
ret = -EIO; ret = -EIO;
break; break;
} }
if (key.objectid == chunk_objectid && if (key.objectid == BTRFS_FIRST_CHUNK_TREE_OBJECTID &&
key.offset == chunk_offset) { key.offset == chunk_offset) {
memmove(ptr, ptr + len, array_size - (cur + len)); memmove(ptr, ptr + len, array_size - (cur + len));
array_size -= len; array_size -= len;
@ -2846,7 +2829,6 @@ int btrfs_remove_chunk(struct btrfs_trans_handle *trans,
struct extent_map *em; struct extent_map *em;
struct map_lookup *map; struct map_lookup *map;
u64 dev_extent_len = 0; u64 dev_extent_len = 0;
u64 chunk_objectid = BTRFS_FIRST_CHUNK_TREE_OBJECTID;
int i, ret = 0; int i, ret = 0;
struct btrfs_fs_devices *fs_devices = fs_info->fs_devices; struct btrfs_fs_devices *fs_devices = fs_info->fs_devices;
@ -2902,7 +2884,7 @@ int btrfs_remove_chunk(struct btrfs_trans_handle *trans,
} }
mutex_unlock(&fs_devices->device_list_mutex); mutex_unlock(&fs_devices->device_list_mutex);
ret = btrfs_free_chunk(trans, fs_info, chunk_objectid, chunk_offset); ret = btrfs_free_chunk(trans, fs_info, chunk_offset);
if (ret) { if (ret) {
btrfs_abort_transaction(trans, ret); btrfs_abort_transaction(trans, ret);
goto out; goto out;
@ -2911,8 +2893,7 @@ int btrfs_remove_chunk(struct btrfs_trans_handle *trans,
trace_btrfs_chunk_free(fs_info, map, chunk_offset, em->len); trace_btrfs_chunk_free(fs_info, map, chunk_offset, em->len);
if (map->type & BTRFS_BLOCK_GROUP_SYSTEM) { if (map->type & BTRFS_BLOCK_GROUP_SYSTEM) {
ret = btrfs_del_sys_chunk(fs_info, chunk_objectid, ret = btrfs_del_sys_chunk(fs_info, chunk_offset);
chunk_offset);
if (ret) { if (ret) {
btrfs_abort_transaction(trans, ret); btrfs_abort_transaction(trans, ret);
goto out; goto out;
@ -3312,7 +3293,6 @@ static int chunk_devid_filter(struct extent_buffer *leaf,
/* [pstart, pend) */ /* [pstart, pend) */
static int chunk_drange_filter(struct extent_buffer *leaf, static int chunk_drange_filter(struct extent_buffer *leaf,
struct btrfs_chunk *chunk, struct btrfs_chunk *chunk,
u64 chunk_offset,
struct btrfs_balance_args *bargs) struct btrfs_balance_args *bargs)
{ {
struct btrfs_stripe *stripe; struct btrfs_stripe *stripe;
@ -3439,7 +3419,7 @@ static int should_balance_chunk(struct btrfs_fs_info *fs_info,
/* drange filter, makes sense only with devid filter */ /* drange filter, makes sense only with devid filter */
if ((bargs->flags & BTRFS_BALANCE_ARGS_DRANGE) && if ((bargs->flags & BTRFS_BALANCE_ARGS_DRANGE) &&
chunk_drange_filter(leaf, chunk, chunk_offset, bargs)) { chunk_drange_filter(leaf, chunk, bargs)) {
return 0; return 0;
} }
@ -3898,13 +3878,6 @@ int btrfs_balance(struct btrfs_balance_control *bctl,
meta_target, data_target); meta_target, data_target);
} }
if (bctl->sys.flags & BTRFS_BALANCE_ARGS_CONVERT) {
fs_info->num_tolerated_disk_barrier_failures = min(
btrfs_calc_num_tolerated_disk_barrier_failures(fs_info),
btrfs_get_num_tolerated_disk_barrier_failures(
bctl->sys.target));
}
ret = insert_balance_item(fs_info, bctl); ret = insert_balance_item(fs_info, bctl);
if (ret && ret != -EEXIST) if (ret && ret != -EEXIST)
goto out; goto out;
@ -3927,11 +3900,6 @@ int btrfs_balance(struct btrfs_balance_control *bctl,
mutex_lock(&fs_info->balance_mutex); mutex_lock(&fs_info->balance_mutex);
atomic_dec(&fs_info->balance_running); atomic_dec(&fs_info->balance_running);
if (bctl->sys.flags & BTRFS_BALANCE_ARGS_CONVERT) {
fs_info->num_tolerated_disk_barrier_failures =
btrfs_calc_num_tolerated_disk_barrier_failures(fs_info);
}
if (bargs) { if (bargs) {
memset(bargs, 0, sizeof(*bargs)); memset(bargs, 0, sizeof(*bargs));
update_ioctl_balance_args(fs_info, 0, bargs); update_ioctl_balance_args(fs_info, 0, bargs);
@ -4127,7 +4095,6 @@ static int btrfs_uuid_scan_kthread(void *data)
struct btrfs_fs_info *fs_info = data; struct btrfs_fs_info *fs_info = data;
struct btrfs_root *root = fs_info->tree_root; struct btrfs_root *root = fs_info->tree_root;
struct btrfs_key key; struct btrfs_key key;
struct btrfs_key max_key;
struct btrfs_path *path = NULL; struct btrfs_path *path = NULL;
int ret = 0; int ret = 0;
struct extent_buffer *eb; struct extent_buffer *eb;
@ -4146,10 +4113,6 @@ static int btrfs_uuid_scan_kthread(void *data)
key.type = BTRFS_ROOT_ITEM_KEY; key.type = BTRFS_ROOT_ITEM_KEY;
key.offset = 0; key.offset = 0;
max_key.objectid = (u64)-1;
max_key.type = BTRFS_ROOT_ITEM_KEY;
max_key.offset = (u64)-1;
while (1) { while (1) {
ret = btrfs_search_forward(root, &key, path, 0); ret = btrfs_search_forward(root, &key, path, 0);
if (ret) { if (ret) {
@ -4601,12 +4564,6 @@ static int btrfs_cmp_device_info(const void *a, const void *b)
return 0; return 0;
} }
static u32 find_raid56_stripe_len(u32 data_devices, u32 dev_stripe_target)
{
/* TODO allow them to set a preferred stripe size */
return SZ_64K;
}
static void check_raid56_incompat_flag(struct btrfs_fs_info *info, u64 type) static void check_raid56_incompat_flag(struct btrfs_fs_info *info, u64 type)
{ {
if (!(type & BTRFS_BLOCK_GROUP_RAID56_MASK)) if (!(type & BTRFS_BLOCK_GROUP_RAID56_MASK))
@ -4629,7 +4586,7 @@ static int __btrfs_alloc_chunk(struct btrfs_trans_handle *trans,
{ {
struct btrfs_fs_info *info = trans->fs_info; struct btrfs_fs_info *info = trans->fs_info;
struct btrfs_fs_devices *fs_devices = info->fs_devices; struct btrfs_fs_devices *fs_devices = info->fs_devices;
struct list_head *cur; struct btrfs_device *device;
struct map_lookup *map = NULL; struct map_lookup *map = NULL;
struct extent_map_tree *em_tree; struct extent_map_tree *em_tree;
struct extent_map *em; struct extent_map *em;
@ -4649,7 +4606,6 @@ static int __btrfs_alloc_chunk(struct btrfs_trans_handle *trans,
u64 max_chunk_size; u64 max_chunk_size;
u64 stripe_size; u64 stripe_size;
u64 num_bytes; u64 num_bytes;
u64 raid_stripe_len = BTRFS_STRIPE_LEN;
int ndevs; int ndevs;
int i; int i;
int j; int j;
@ -4703,22 +4659,15 @@ static int __btrfs_alloc_chunk(struct btrfs_trans_handle *trans,
if (!devices_info) if (!devices_info)
return -ENOMEM; return -ENOMEM;
cur = fs_devices->alloc_list.next;
/* /*
* in the first pass through the devices list, we gather information * in the first pass through the devices list, we gather information
* about the available holes on each device. * about the available holes on each device.
*/ */
ndevs = 0; ndevs = 0;
while (cur != &fs_devices->alloc_list) { list_for_each_entry(device, &fs_devices->alloc_list, dev_alloc_list) {
struct btrfs_device *device;
u64 max_avail; u64 max_avail;
u64 dev_offset; u64 dev_offset;
device = list_entry(cur, struct btrfs_device, dev_alloc_list);
cur = cur->next;
if (!device->writeable) { if (!device->writeable) {
WARN(1, KERN_ERR WARN(1, KERN_ERR
"BTRFS: read-only device in alloc_list\n"); "BTRFS: read-only device in alloc_list\n");
@ -4769,15 +4718,15 @@ static int __btrfs_alloc_chunk(struct btrfs_trans_handle *trans,
btrfs_cmp_device_info, NULL); btrfs_cmp_device_info, NULL);
/* round down to number of usable stripes */ /* round down to number of usable stripes */
ndevs -= ndevs % devs_increment; ndevs = round_down(ndevs, devs_increment);
if (ndevs < devs_increment * sub_stripes || ndevs < devs_min) { if (ndevs < devs_increment * sub_stripes || ndevs < devs_min) {
ret = -ENOSPC; ret = -ENOSPC;
goto error; goto error;
} }
if (devs_max && ndevs > devs_max) ndevs = min(ndevs, devs_max);
ndevs = devs_max;
/* /*
* the primary goal is to maximize the number of stripes, so use as many * the primary goal is to maximize the number of stripes, so use as many
* devices as possible, even if the stripes are not maximum sized. * devices as possible, even if the stripes are not maximum sized.
@ -4791,16 +4740,11 @@ static int __btrfs_alloc_chunk(struct btrfs_trans_handle *trans,
*/ */
data_stripes = num_stripes / ncopies; data_stripes = num_stripes / ncopies;
if (type & BTRFS_BLOCK_GROUP_RAID5) { if (type & BTRFS_BLOCK_GROUP_RAID5)
raid_stripe_len = find_raid56_stripe_len(ndevs - 1,
info->stripesize);
data_stripes = num_stripes - 1; data_stripes = num_stripes - 1;
}
if (type & BTRFS_BLOCK_GROUP_RAID6) { if (type & BTRFS_BLOCK_GROUP_RAID6)
raid_stripe_len = find_raid56_stripe_len(ndevs - 2,
info->stripesize);
data_stripes = num_stripes - 2; data_stripes = num_stripes - 2;
}
/* /*
* Use the number of data stripes to figure out how big this chunk * Use the number of data stripes to figure out how big this chunk
@ -4825,8 +4769,7 @@ static int __btrfs_alloc_chunk(struct btrfs_trans_handle *trans,
stripe_size = div_u64(stripe_size, dev_stripes); stripe_size = div_u64(stripe_size, dev_stripes);
/* align to BTRFS_STRIPE_LEN */ /* align to BTRFS_STRIPE_LEN */
stripe_size = div64_u64(stripe_size, raid_stripe_len); stripe_size = round_down(stripe_size, BTRFS_STRIPE_LEN);
stripe_size *= raid_stripe_len;
map = kmalloc(map_lookup_size(num_stripes), GFP_NOFS); map = kmalloc(map_lookup_size(num_stripes), GFP_NOFS);
if (!map) { if (!map) {
@ -4843,10 +4786,9 @@ static int __btrfs_alloc_chunk(struct btrfs_trans_handle *trans,
j * stripe_size; j * stripe_size;
} }
} }
map->sector_size = info->sectorsize; map->stripe_len = BTRFS_STRIPE_LEN;
map->stripe_len = raid_stripe_len; map->io_align = BTRFS_STRIPE_LEN;
map->io_align = raid_stripe_len; map->io_width = BTRFS_STRIPE_LEN;
map->io_width = raid_stripe_len;
map->type = type; map->type = type;
map->sub_stripes = sub_stripes; map->sub_stripes = sub_stripes;
@ -4881,9 +4823,7 @@ static int __btrfs_alloc_chunk(struct btrfs_trans_handle *trans,
goto error; goto error;
} }
ret = btrfs_make_block_group(trans, info, 0, type, ret = btrfs_make_block_group(trans, info, 0, type, start, num_bytes);
BTRFS_FIRST_CHUNK_TREE_OBJECTID,
start, num_bytes);
if (ret) if (ret)
goto error_del_extent; goto error_del_extent;
@ -4963,11 +4903,8 @@ int btrfs_finish_chunk_alloc(struct btrfs_trans_handle *trans,
ret = btrfs_update_device(trans, device); ret = btrfs_update_device(trans, device);
if (ret) if (ret)
break; break;
ret = btrfs_alloc_dev_extent(trans, device, ret = btrfs_alloc_dev_extent(trans, device, chunk_offset,
chunk_root->root_key.objectid, dev_offset, stripe_size);
BTRFS_FIRST_CHUNK_TREE_OBJECTID,
chunk_offset, dev_offset,
stripe_size);
if (ret) if (ret)
break; break;
} }
@ -5172,7 +5109,6 @@ int btrfs_num_copies(struct btrfs_fs_info *fs_info, u64 logical, u64 len)
} }
unsigned long btrfs_full_stripe_len(struct btrfs_fs_info *fs_info, unsigned long btrfs_full_stripe_len(struct btrfs_fs_info *fs_info,
struct btrfs_mapping_tree *map_tree,
u64 logical) u64 logical)
{ {
struct extent_map *em; struct extent_map *em;
@ -5180,29 +5116,30 @@ unsigned long btrfs_full_stripe_len(struct btrfs_fs_info *fs_info,
unsigned long len = fs_info->sectorsize; unsigned long len = fs_info->sectorsize;
em = get_chunk_map(fs_info, logical, len); em = get_chunk_map(fs_info, logical, len);
WARN_ON(IS_ERR(em));
map = em->map_lookup; if (!WARN_ON(IS_ERR(em))) {
if (map->type & BTRFS_BLOCK_GROUP_RAID56_MASK) map = em->map_lookup;
len = map->stripe_len * nr_data_stripes(map); if (map->type & BTRFS_BLOCK_GROUP_RAID56_MASK)
free_extent_map(em); len = map->stripe_len * nr_data_stripes(map);
free_extent_map(em);
}
return len; return len;
} }
int btrfs_is_parity_mirror(struct btrfs_fs_info *fs_info, int btrfs_is_parity_mirror(struct btrfs_fs_info *fs_info, u64 logical, u64 len)
u64 logical, u64 len, int mirror_num)
{ {
struct extent_map *em; struct extent_map *em;
struct map_lookup *map; struct map_lookup *map;
int ret = 0; int ret = 0;
em = get_chunk_map(fs_info, logical, len); em = get_chunk_map(fs_info, logical, len);
WARN_ON(IS_ERR(em));
map = em->map_lookup; if(!WARN_ON(IS_ERR(em))) {
if (map->type & BTRFS_BLOCK_GROUP_RAID56_MASK) map = em->map_lookup;
ret = 1; if (map->type & BTRFS_BLOCK_GROUP_RAID56_MASK)
free_extent_map(em); ret = 1;
free_extent_map(em);
}
return ret; return ret;
} }
@ -6295,9 +6232,8 @@ struct btrfs_device *btrfs_find_device(struct btrfs_fs_info *fs_info, u64 devid,
cur_devices = fs_info->fs_devices; cur_devices = fs_info->fs_devices;
while (cur_devices) { while (cur_devices) {
if (!fsid || if (!fsid ||
!memcmp(cur_devices->fsid, fsid, BTRFS_UUID_SIZE)) { !memcmp(cur_devices->fsid, fsid, BTRFS_FSID_SIZE)) {
device = __find_device(&cur_devices->devices, device = find_device(cur_devices, devid, uuid);
devid, uuid);
if (device) if (device)
return device; return device;
} }
@ -6450,7 +6386,6 @@ static int read_one_chunk(struct btrfs_fs_info *fs_info, struct btrfs_key *key,
struct extent_map *em; struct extent_map *em;
u64 logical; u64 logical;
u64 length; u64 length;
u64 stripe_len;
u64 devid; u64 devid;
u8 uuid[BTRFS_UUID_SIZE]; u8 uuid[BTRFS_UUID_SIZE];
int num_stripes; int num_stripes;
@ -6459,7 +6394,6 @@ static int read_one_chunk(struct btrfs_fs_info *fs_info, struct btrfs_key *key,
logical = key->offset; logical = key->offset;
length = btrfs_chunk_length(leaf, chunk); length = btrfs_chunk_length(leaf, chunk);
stripe_len = btrfs_chunk_stripe_len(leaf, chunk);
num_stripes = btrfs_chunk_num_stripes(leaf, chunk); num_stripes = btrfs_chunk_num_stripes(leaf, chunk);
ret = btrfs_check_chunk_valid(fs_info, leaf, chunk, logical); ret = btrfs_check_chunk_valid(fs_info, leaf, chunk, logical);
@ -6498,7 +6432,6 @@ static int read_one_chunk(struct btrfs_fs_info *fs_info, struct btrfs_key *key,
map->num_stripes = num_stripes; map->num_stripes = num_stripes;
map->io_width = btrfs_chunk_io_width(leaf, chunk); map->io_width = btrfs_chunk_io_width(leaf, chunk);
map->io_align = btrfs_chunk_io_align(leaf, chunk); map->io_align = btrfs_chunk_io_align(leaf, chunk);
map->sector_size = btrfs_chunk_sector_size(leaf, chunk);
map->stripe_len = btrfs_chunk_stripe_len(leaf, chunk); map->stripe_len = btrfs_chunk_stripe_len(leaf, chunk);
map->type = btrfs_chunk_type(leaf, chunk); map->type = btrfs_chunk_type(leaf, chunk);
map->sub_stripes = btrfs_chunk_sub_stripes(leaf, chunk); map->sub_stripes = btrfs_chunk_sub_stripes(leaf, chunk);
@ -6514,6 +6447,7 @@ static int read_one_chunk(struct btrfs_fs_info *fs_info, struct btrfs_key *key,
if (!map->stripes[i].dev && if (!map->stripes[i].dev &&
!btrfs_test_opt(fs_info, DEGRADED)) { !btrfs_test_opt(fs_info, DEGRADED)) {
free_extent_map(em); free_extent_map(em);
btrfs_report_missing_device(fs_info, devid, uuid);
return -EIO; return -EIO;
} }
if (!map->stripes[i].dev) { if (!map->stripes[i].dev) {
@ -6524,8 +6458,7 @@ static int read_one_chunk(struct btrfs_fs_info *fs_info, struct btrfs_key *key,
free_extent_map(em); free_extent_map(em);
return -EIO; return -EIO;
} }
btrfs_warn(fs_info, "devid %llu uuid %pU is missing", btrfs_report_missing_device(fs_info, devid, uuid);
devid, uuid);
} }
map->stripes[i].dev->in_fs_metadata = 1; map->stripes[i].dev->in_fs_metadata = 1;
} }
@ -6569,10 +6502,11 @@ static struct btrfs_fs_devices *open_seed_devices(struct btrfs_fs_info *fs_info,
int ret; int ret;
BUG_ON(!mutex_is_locked(&uuid_mutex)); BUG_ON(!mutex_is_locked(&uuid_mutex));
ASSERT(fsid);
fs_devices = fs_info->fs_devices->seed; fs_devices = fs_info->fs_devices->seed;
while (fs_devices) { while (fs_devices) {
if (!memcmp(fs_devices->fsid, fsid, BTRFS_UUID_SIZE)) if (!memcmp(fs_devices->fsid, fsid, BTRFS_FSID_SIZE))
return fs_devices; return fs_devices;
fs_devices = fs_devices->seed; fs_devices = fs_devices->seed;
@ -6625,16 +6559,16 @@ static int read_one_dev(struct btrfs_fs_info *fs_info,
struct btrfs_device *device; struct btrfs_device *device;
u64 devid; u64 devid;
int ret; int ret;
u8 fs_uuid[BTRFS_UUID_SIZE]; u8 fs_uuid[BTRFS_FSID_SIZE];
u8 dev_uuid[BTRFS_UUID_SIZE]; u8 dev_uuid[BTRFS_UUID_SIZE];
devid = btrfs_device_id(leaf, dev_item); devid = btrfs_device_id(leaf, dev_item);
read_extent_buffer(leaf, dev_uuid, btrfs_device_uuid(dev_item), read_extent_buffer(leaf, dev_uuid, btrfs_device_uuid(dev_item),
BTRFS_UUID_SIZE); BTRFS_UUID_SIZE);
read_extent_buffer(leaf, fs_uuid, btrfs_device_fsid(dev_item), read_extent_buffer(leaf, fs_uuid, btrfs_device_fsid(dev_item),
BTRFS_UUID_SIZE); BTRFS_FSID_SIZE);
if (memcmp(fs_uuid, fs_info->fsid, BTRFS_UUID_SIZE)) { if (memcmp(fs_uuid, fs_info->fsid, BTRFS_FSID_SIZE)) {
fs_devices = open_seed_devices(fs_info, fs_uuid); fs_devices = open_seed_devices(fs_info, fs_uuid);
if (IS_ERR(fs_devices)) if (IS_ERR(fs_devices))
return PTR_ERR(fs_devices); return PTR_ERR(fs_devices);
@ -6642,17 +6576,21 @@ static int read_one_dev(struct btrfs_fs_info *fs_info,
device = btrfs_find_device(fs_info, devid, dev_uuid, fs_uuid); device = btrfs_find_device(fs_info, devid, dev_uuid, fs_uuid);
if (!device) { if (!device) {
if (!btrfs_test_opt(fs_info, DEGRADED)) if (!btrfs_test_opt(fs_info, DEGRADED)) {
btrfs_report_missing_device(fs_info, devid, dev_uuid);
return -EIO; return -EIO;
}
device = add_missing_dev(fs_devices, devid, dev_uuid); device = add_missing_dev(fs_devices, devid, dev_uuid);
if (!device) if (!device)
return -ENOMEM; return -ENOMEM;
btrfs_warn(fs_info, "devid %llu uuid %pU missing", btrfs_report_missing_device(fs_info, devid, dev_uuid);
devid, dev_uuid);
} else { } else {
if (!device->bdev && !btrfs_test_opt(fs_info, DEGRADED)) if (!device->bdev) {
return -EIO; btrfs_report_missing_device(fs_info, devid, dev_uuid);
if (!btrfs_test_opt(fs_info, DEGRADED))
return -EIO;
}
if(!device->bdev && !device->missing) { if(!device->bdev && !device->missing) {
/* /*
@ -6818,6 +6756,70 @@ out_short_read:
return -EIO; return -EIO;
} }
void btrfs_report_missing_device(struct btrfs_fs_info *fs_info, u64 devid,
u8 *uuid)
{
btrfs_warn_rl(fs_info, "devid %llu uuid %pU is missing", devid, uuid);
}
/*
* Check if all chunks in the fs are OK for read-write degraded mount
*
* Return true if all chunks meet the minimal RW mount requirements.
* Return false if any chunk doesn't meet the minimal RW mount requirements.
*/
bool btrfs_check_rw_degradable(struct btrfs_fs_info *fs_info)
{
struct btrfs_mapping_tree *map_tree = &fs_info->mapping_tree;
struct extent_map *em;
u64 next_start = 0;
bool ret = true;
read_lock(&map_tree->map_tree.lock);
em = lookup_extent_mapping(&map_tree->map_tree, 0, (u64)-1);
read_unlock(&map_tree->map_tree.lock);
/* No chunk at all? Return false anyway */
if (!em) {
ret = false;
goto out;
}
while (em) {
struct map_lookup *map;
int missing = 0;
int max_tolerated;
int i;
map = em->map_lookup;
max_tolerated =
btrfs_get_num_tolerated_disk_barrier_failures(
map->type);
for (i = 0; i < map->num_stripes; i++) {
struct btrfs_device *dev = map->stripes[i].dev;
if (!dev || !dev->bdev || dev->missing ||
dev->last_flush_error)
missing++;
}
if (missing > max_tolerated) {
btrfs_warn(fs_info,
"chunk %llu missing %d devices, max tolerance is %d for writeable mount",
em->start, missing, max_tolerated);
free_extent_map(em);
ret = false;
goto out;
}
next_start = extent_map_end(em);
free_extent_map(em);
read_lock(&map_tree->map_tree.lock);
em = lookup_extent_mapping(&map_tree->map_tree, next_start,
(u64)(-1) - next_start);
read_unlock(&map_tree->map_tree.lock);
}
out:
return ret;
}
int btrfs_read_chunk_tree(struct btrfs_fs_info *fs_info) int btrfs_read_chunk_tree(struct btrfs_fs_info *fs_info)
{ {
struct btrfs_root *root = fs_info->chunk_root; struct btrfs_root *root = fs_info->chunk_root;

View File

@ -353,7 +353,6 @@ struct map_lookup {
int io_align; int io_align;
int io_width; int io_width;
u64 stripe_len; u64 stripe_len;
int sector_size;
int num_stripes; int num_stripes;
int sub_stripes; int sub_stripes;
struct btrfs_bio_stripe stripes[]; struct btrfs_bio_stripe stripes[];
@ -481,9 +480,8 @@ void btrfs_init_dev_replace_tgtdev_for_resume(struct btrfs_fs_info *fs_info,
struct btrfs_device *tgtdev); struct btrfs_device *tgtdev);
void btrfs_scratch_superblocks(struct block_device *bdev, const char *device_path); void btrfs_scratch_superblocks(struct block_device *bdev, const char *device_path);
int btrfs_is_parity_mirror(struct btrfs_fs_info *fs_info, int btrfs_is_parity_mirror(struct btrfs_fs_info *fs_info,
u64 logical, u64 len, int mirror_num); u64 logical, u64 len);
unsigned long btrfs_full_stripe_len(struct btrfs_fs_info *fs_info, unsigned long btrfs_full_stripe_len(struct btrfs_fs_info *fs_info,
struct btrfs_mapping_tree *map_tree,
u64 logical); u64 logical);
int btrfs_finish_chunk_alloc(struct btrfs_trans_handle *trans, int btrfs_finish_chunk_alloc(struct btrfs_trans_handle *trans,
struct btrfs_fs_info *fs_info, struct btrfs_fs_info *fs_info,
@ -543,4 +541,8 @@ struct list_head *btrfs_get_fs_uuids(void);
void btrfs_set_fs_info_ptr(struct btrfs_fs_info *fs_info); void btrfs_set_fs_info_ptr(struct btrfs_fs_info *fs_info);
void btrfs_reset_fs_info_ptr(struct btrfs_fs_info *fs_info); void btrfs_reset_fs_info_ptr(struct btrfs_fs_info *fs_info);
bool btrfs_check_rw_degradable(struct btrfs_fs_info *fs_info);
void btrfs_report_missing_device(struct btrfs_fs_info *fs_info, u64 devid,
u8 *uuid);
#endif #endif

View File

@ -26,6 +26,7 @@ struct btrfs_work;
struct __btrfs_workqueue; struct __btrfs_workqueue;
struct btrfs_qgroup_extent_record; struct btrfs_qgroup_extent_record;
struct btrfs_qgroup; struct btrfs_qgroup;
struct prelim_ref;
#define show_ref_type(type) \ #define show_ref_type(type) \
__print_symbolic(type, \ __print_symbolic(type, \
@ -73,11 +74,11 @@ struct btrfs_qgroup;
{ BTRFS_BLOCK_GROUP_RAID5, "RAID5"}, \ { BTRFS_BLOCK_GROUP_RAID5, "RAID5"}, \
{ BTRFS_BLOCK_GROUP_RAID6, "RAID6"} { BTRFS_BLOCK_GROUP_RAID6, "RAID6"}
#define BTRFS_UUID_SIZE 16 #define BTRFS_FSID_SIZE 16
#define TP_STRUCT__entry_fsid __array(u8, fsid, BTRFS_UUID_SIZE) #define TP_STRUCT__entry_fsid __array(u8, fsid, BTRFS_FSID_SIZE)
#define TP_fast_assign_fsid(fs_info) \ #define TP_fast_assign_fsid(fs_info) \
memcpy(__entry->fsid, fs_info->fsid, BTRFS_UUID_SIZE) memcpy(__entry->fsid, fs_info->fsid, BTRFS_FSID_SIZE)
#define TP_STRUCT__entry_btrfs(args...) \ #define TP_STRUCT__entry_btrfs(args...) \
TP_STRUCT__entry( \ TP_STRUCT__entry( \
@ -92,7 +93,7 @@ struct btrfs_qgroup;
TRACE_EVENT(btrfs_transaction_commit, TRACE_EVENT(btrfs_transaction_commit,
TP_PROTO(struct btrfs_root *root), TP_PROTO(const struct btrfs_root *root),
TP_ARGS(root), TP_ARGS(root),
@ -113,7 +114,7 @@ TRACE_EVENT(btrfs_transaction_commit,
DECLARE_EVENT_CLASS(btrfs__inode, DECLARE_EVENT_CLASS(btrfs__inode,
TP_PROTO(struct inode *inode), TP_PROTO(const struct inode *inode),
TP_ARGS(inode), TP_ARGS(inode),
@ -151,21 +152,21 @@ DECLARE_EVENT_CLASS(btrfs__inode,
DEFINE_EVENT(btrfs__inode, btrfs_inode_new, DEFINE_EVENT(btrfs__inode, btrfs_inode_new,
TP_PROTO(struct inode *inode), TP_PROTO(const struct inode *inode),
TP_ARGS(inode) TP_ARGS(inode)
); );
DEFINE_EVENT(btrfs__inode, btrfs_inode_request, DEFINE_EVENT(btrfs__inode, btrfs_inode_request,
TP_PROTO(struct inode *inode), TP_PROTO(const struct inode *inode),
TP_ARGS(inode) TP_ARGS(inode)
); );
DEFINE_EVENT(btrfs__inode, btrfs_inode_evict, DEFINE_EVENT(btrfs__inode, btrfs_inode_evict,
TP_PROTO(struct inode *inode), TP_PROTO(const struct inode *inode),
TP_ARGS(inode) TP_ARGS(inode)
); );
@ -192,8 +193,8 @@ DEFINE_EVENT(btrfs__inode, btrfs_inode_evict,
TRACE_EVENT_CONDITION(btrfs_get_extent, TRACE_EVENT_CONDITION(btrfs_get_extent,
TP_PROTO(struct btrfs_root *root, struct btrfs_inode *inode, TP_PROTO(const struct btrfs_root *root, const struct btrfs_inode *inode,
struct extent_map *map), const struct extent_map *map),
TP_ARGS(root, inode, map), TP_ARGS(root, inode, map),
@ -388,7 +389,8 @@ DEFINE_EVENT(
DECLARE_EVENT_CLASS(btrfs__ordered_extent, DECLARE_EVENT_CLASS(btrfs__ordered_extent,
TP_PROTO(struct inode *inode, struct btrfs_ordered_extent *ordered), TP_PROTO(const struct inode *inode,
const struct btrfs_ordered_extent *ordered),
TP_ARGS(inode, ordered), TP_ARGS(inode, ordered),
@ -440,36 +442,40 @@ DECLARE_EVENT_CLASS(btrfs__ordered_extent,
DEFINE_EVENT(btrfs__ordered_extent, btrfs_ordered_extent_add, DEFINE_EVENT(btrfs__ordered_extent, btrfs_ordered_extent_add,
TP_PROTO(struct inode *inode, struct btrfs_ordered_extent *ordered), TP_PROTO(const struct inode *inode,
const struct btrfs_ordered_extent *ordered),
TP_ARGS(inode, ordered) TP_ARGS(inode, ordered)
); );
DEFINE_EVENT(btrfs__ordered_extent, btrfs_ordered_extent_remove, DEFINE_EVENT(btrfs__ordered_extent, btrfs_ordered_extent_remove,
TP_PROTO(struct inode *inode, struct btrfs_ordered_extent *ordered), TP_PROTO(const struct inode *inode,
const struct btrfs_ordered_extent *ordered),
TP_ARGS(inode, ordered) TP_ARGS(inode, ordered)
); );
DEFINE_EVENT(btrfs__ordered_extent, btrfs_ordered_extent_start, DEFINE_EVENT(btrfs__ordered_extent, btrfs_ordered_extent_start,
TP_PROTO(struct inode *inode, struct btrfs_ordered_extent *ordered), TP_PROTO(const struct inode *inode,
const struct btrfs_ordered_extent *ordered),
TP_ARGS(inode, ordered) TP_ARGS(inode, ordered)
); );
DEFINE_EVENT(btrfs__ordered_extent, btrfs_ordered_extent_put, DEFINE_EVENT(btrfs__ordered_extent, btrfs_ordered_extent_put,
TP_PROTO(struct inode *inode, struct btrfs_ordered_extent *ordered), TP_PROTO(const struct inode *inode,
const struct btrfs_ordered_extent *ordered),
TP_ARGS(inode, ordered) TP_ARGS(inode, ordered)
); );
DECLARE_EVENT_CLASS(btrfs__writepage, DECLARE_EVENT_CLASS(btrfs__writepage,
TP_PROTO(struct page *page, struct inode *inode, TP_PROTO(const struct page *page, const struct inode *inode,
struct writeback_control *wbc), const struct writeback_control *wbc),
TP_ARGS(page, inode, wbc), TP_ARGS(page, inode, wbc),
@ -517,15 +523,15 @@ DECLARE_EVENT_CLASS(btrfs__writepage,
DEFINE_EVENT(btrfs__writepage, __extent_writepage, DEFINE_EVENT(btrfs__writepage, __extent_writepage,
TP_PROTO(struct page *page, struct inode *inode, TP_PROTO(const struct page *page, const struct inode *inode,
struct writeback_control *wbc), const struct writeback_control *wbc),
TP_ARGS(page, inode, wbc) TP_ARGS(page, inode, wbc)
); );
TRACE_EVENT(btrfs_writepage_end_io_hook, TRACE_EVENT(btrfs_writepage_end_io_hook,
TP_PROTO(struct page *page, u64 start, u64 end, int uptodate), TP_PROTO(const struct page *page, u64 start, u64 end, int uptodate),
TP_ARGS(page, start, end, uptodate), TP_ARGS(page, start, end, uptodate),
@ -558,7 +564,7 @@ TRACE_EVENT(btrfs_writepage_end_io_hook,
TRACE_EVENT(btrfs_sync_file, TRACE_EVENT(btrfs_sync_file,
TP_PROTO(struct file *file, int datasync), TP_PROTO(const struct file *file, int datasync),
TP_ARGS(file, datasync), TP_ARGS(file, datasync),
@ -570,8 +576,8 @@ TRACE_EVENT(btrfs_sync_file,
), ),
TP_fast_assign( TP_fast_assign(
struct dentry *dentry = file->f_path.dentry; const struct dentry *dentry = file->f_path.dentry;
struct inode *inode = d_inode(dentry); const struct inode *inode = d_inode(dentry);
TP_fast_assign_fsid(btrfs_sb(file->f_path.dentry->d_sb)); TP_fast_assign_fsid(btrfs_sb(file->f_path.dentry->d_sb));
__entry->ino = inode->i_ino; __entry->ino = inode->i_ino;
@ -589,7 +595,7 @@ TRACE_EVENT(btrfs_sync_file,
TRACE_EVENT(btrfs_sync_fs, TRACE_EVENT(btrfs_sync_fs,
TP_PROTO(struct btrfs_fs_info *fs_info, int wait), TP_PROTO(const struct btrfs_fs_info *fs_info, int wait),
TP_ARGS(fs_info, wait), TP_ARGS(fs_info, wait),
@ -606,13 +612,13 @@ TRACE_EVENT(btrfs_sync_fs,
TRACE_EVENT(btrfs_add_block_group, TRACE_EVENT(btrfs_add_block_group,
TP_PROTO(struct btrfs_fs_info *fs_info, TP_PROTO(const struct btrfs_fs_info *fs_info,
struct btrfs_block_group_cache *block_group, int create), const struct btrfs_block_group_cache *block_group, int create),
TP_ARGS(fs_info, block_group, create), TP_ARGS(fs_info, block_group, create),
TP_STRUCT__entry( TP_STRUCT__entry(
__array( u8, fsid, BTRFS_UUID_SIZE ) __array( u8, fsid, BTRFS_FSID_SIZE )
__field( u64, offset ) __field( u64, offset )
__field( u64, size ) __field( u64, size )
__field( u64, flags ) __field( u64, flags )
@ -622,7 +628,7 @@ TRACE_EVENT(btrfs_add_block_group,
), ),
TP_fast_assign( TP_fast_assign(
memcpy(__entry->fsid, fs_info->fsid, BTRFS_UUID_SIZE); memcpy(__entry->fsid, fs_info->fsid, BTRFS_FSID_SIZE);
__entry->offset = block_group->key.objectid; __entry->offset = block_group->key.objectid;
__entry->size = block_group->key.offset; __entry->size = block_group->key.offset;
__entry->flags = block_group->flags; __entry->flags = block_group->flags;
@ -654,9 +660,9 @@ TRACE_EVENT(btrfs_add_block_group,
DECLARE_EVENT_CLASS(btrfs_delayed_tree_ref, DECLARE_EVENT_CLASS(btrfs_delayed_tree_ref,
TP_PROTO(struct btrfs_fs_info *fs_info, TP_PROTO(const struct btrfs_fs_info *fs_info,
struct btrfs_delayed_ref_node *ref, const struct btrfs_delayed_ref_node *ref,
struct btrfs_delayed_tree_ref *full_ref, const struct btrfs_delayed_tree_ref *full_ref,
int action), int action),
TP_ARGS(fs_info, ref, full_ref, action), TP_ARGS(fs_info, ref, full_ref, action),
@ -697,9 +703,9 @@ DECLARE_EVENT_CLASS(btrfs_delayed_tree_ref,
DEFINE_EVENT(btrfs_delayed_tree_ref, add_delayed_tree_ref, DEFINE_EVENT(btrfs_delayed_tree_ref, add_delayed_tree_ref,
TP_PROTO(struct btrfs_fs_info *fs_info, TP_PROTO(const struct btrfs_fs_info *fs_info,
struct btrfs_delayed_ref_node *ref, const struct btrfs_delayed_ref_node *ref,
struct btrfs_delayed_tree_ref *full_ref, const struct btrfs_delayed_tree_ref *full_ref,
int action), int action),
TP_ARGS(fs_info, ref, full_ref, action) TP_ARGS(fs_info, ref, full_ref, action)
@ -707,9 +713,9 @@ DEFINE_EVENT(btrfs_delayed_tree_ref, add_delayed_tree_ref,
DEFINE_EVENT(btrfs_delayed_tree_ref, run_delayed_tree_ref, DEFINE_EVENT(btrfs_delayed_tree_ref, run_delayed_tree_ref,
TP_PROTO(struct btrfs_fs_info *fs_info, TP_PROTO(const struct btrfs_fs_info *fs_info,
struct btrfs_delayed_ref_node *ref, const struct btrfs_delayed_ref_node *ref,
struct btrfs_delayed_tree_ref *full_ref, const struct btrfs_delayed_tree_ref *full_ref,
int action), int action),
TP_ARGS(fs_info, ref, full_ref, action) TP_ARGS(fs_info, ref, full_ref, action)
@ -717,9 +723,9 @@ DEFINE_EVENT(btrfs_delayed_tree_ref, run_delayed_tree_ref,
DECLARE_EVENT_CLASS(btrfs_delayed_data_ref, DECLARE_EVENT_CLASS(btrfs_delayed_data_ref,
TP_PROTO(struct btrfs_fs_info *fs_info, TP_PROTO(const struct btrfs_fs_info *fs_info,
struct btrfs_delayed_ref_node *ref, const struct btrfs_delayed_ref_node *ref,
struct btrfs_delayed_data_ref *full_ref, const struct btrfs_delayed_data_ref *full_ref,
int action), int action),
TP_ARGS(fs_info, ref, full_ref, action), TP_ARGS(fs_info, ref, full_ref, action),
@ -764,9 +770,9 @@ DECLARE_EVENT_CLASS(btrfs_delayed_data_ref,
DEFINE_EVENT(btrfs_delayed_data_ref, add_delayed_data_ref, DEFINE_EVENT(btrfs_delayed_data_ref, add_delayed_data_ref,
TP_PROTO(struct btrfs_fs_info *fs_info, TP_PROTO(const struct btrfs_fs_info *fs_info,
struct btrfs_delayed_ref_node *ref, const struct btrfs_delayed_ref_node *ref,
struct btrfs_delayed_data_ref *full_ref, const struct btrfs_delayed_data_ref *full_ref,
int action), int action),
TP_ARGS(fs_info, ref, full_ref, action) TP_ARGS(fs_info, ref, full_ref, action)
@ -774,9 +780,9 @@ DEFINE_EVENT(btrfs_delayed_data_ref, add_delayed_data_ref,
DEFINE_EVENT(btrfs_delayed_data_ref, run_delayed_data_ref, DEFINE_EVENT(btrfs_delayed_data_ref, run_delayed_data_ref,
TP_PROTO(struct btrfs_fs_info *fs_info, TP_PROTO(const struct btrfs_fs_info *fs_info,
struct btrfs_delayed_ref_node *ref, const struct btrfs_delayed_ref_node *ref,
struct btrfs_delayed_data_ref *full_ref, const struct btrfs_delayed_data_ref *full_ref,
int action), int action),
TP_ARGS(fs_info, ref, full_ref, action) TP_ARGS(fs_info, ref, full_ref, action)
@ -784,9 +790,9 @@ DEFINE_EVENT(btrfs_delayed_data_ref, run_delayed_data_ref,
DECLARE_EVENT_CLASS(btrfs_delayed_ref_head, DECLARE_EVENT_CLASS(btrfs_delayed_ref_head,
TP_PROTO(struct btrfs_fs_info *fs_info, TP_PROTO(const struct btrfs_fs_info *fs_info,
struct btrfs_delayed_ref_node *ref, const struct btrfs_delayed_ref_node *ref,
struct btrfs_delayed_ref_head *head_ref, const struct btrfs_delayed_ref_head *head_ref,
int action), int action),
TP_ARGS(fs_info, ref, head_ref, action), TP_ARGS(fs_info, ref, head_ref, action),
@ -814,9 +820,9 @@ DECLARE_EVENT_CLASS(btrfs_delayed_ref_head,
DEFINE_EVENT(btrfs_delayed_ref_head, add_delayed_ref_head, DEFINE_EVENT(btrfs_delayed_ref_head, add_delayed_ref_head,
TP_PROTO(struct btrfs_fs_info *fs_info, TP_PROTO(const struct btrfs_fs_info *fs_info,
struct btrfs_delayed_ref_node *ref, const struct btrfs_delayed_ref_node *ref,
struct btrfs_delayed_ref_head *head_ref, const struct btrfs_delayed_ref_head *head_ref,
int action), int action),
TP_ARGS(fs_info, ref, head_ref, action) TP_ARGS(fs_info, ref, head_ref, action)
@ -824,9 +830,9 @@ DEFINE_EVENT(btrfs_delayed_ref_head, add_delayed_ref_head,
DEFINE_EVENT(btrfs_delayed_ref_head, run_delayed_ref_head, DEFINE_EVENT(btrfs_delayed_ref_head, run_delayed_ref_head,
TP_PROTO(struct btrfs_fs_info *fs_info, TP_PROTO(const struct btrfs_fs_info *fs_info,
struct btrfs_delayed_ref_node *ref, const struct btrfs_delayed_ref_node *ref,
struct btrfs_delayed_ref_head *head_ref, const struct btrfs_delayed_ref_head *head_ref,
int action), int action),
TP_ARGS(fs_info, ref, head_ref, action) TP_ARGS(fs_info, ref, head_ref, action)
@ -846,8 +852,8 @@ DEFINE_EVENT(btrfs_delayed_ref_head, run_delayed_ref_head,
DECLARE_EVENT_CLASS(btrfs__chunk, DECLARE_EVENT_CLASS(btrfs__chunk,
TP_PROTO(struct btrfs_fs_info *fs_info, struct map_lookup *map, TP_PROTO(const struct btrfs_fs_info *fs_info,
u64 offset, u64 size), const struct map_lookup *map, u64 offset, u64 size),
TP_ARGS(fs_info, map, offset, size), TP_ARGS(fs_info, map, offset, size),
@ -880,24 +886,24 @@ DECLARE_EVENT_CLASS(btrfs__chunk,
DEFINE_EVENT(btrfs__chunk, btrfs_chunk_alloc, DEFINE_EVENT(btrfs__chunk, btrfs_chunk_alloc,
TP_PROTO(struct btrfs_fs_info *fs_info, struct map_lookup *map, TP_PROTO(const struct btrfs_fs_info *fs_info,
u64 offset, u64 size), const struct map_lookup *map, u64 offset, u64 size),
TP_ARGS(fs_info, map, offset, size) TP_ARGS(fs_info, map, offset, size)
); );
DEFINE_EVENT(btrfs__chunk, btrfs_chunk_free, DEFINE_EVENT(btrfs__chunk, btrfs_chunk_free,
TP_PROTO(struct btrfs_fs_info *fs_info, struct map_lookup *map, TP_PROTO(const struct btrfs_fs_info *fs_info,
u64 offset, u64 size), const struct map_lookup *map, u64 offset, u64 size),
TP_ARGS(fs_info, map, offset, size) TP_ARGS(fs_info, map, offset, size)
); );
TRACE_EVENT(btrfs_cow_block, TRACE_EVENT(btrfs_cow_block,
TP_PROTO(struct btrfs_root *root, struct extent_buffer *buf, TP_PROTO(const struct btrfs_root *root, const struct extent_buffer *buf,
struct extent_buffer *cow), const struct extent_buffer *cow),
TP_ARGS(root, buf, cow), TP_ARGS(root, buf, cow),
@ -931,7 +937,7 @@ TRACE_EVENT(btrfs_cow_block,
TRACE_EVENT(btrfs_space_reservation, TRACE_EVENT(btrfs_space_reservation,
TP_PROTO(struct btrfs_fs_info *fs_info, char *type, u64 val, TP_PROTO(const struct btrfs_fs_info *fs_info, char *type, u64 val,
u64 bytes, int reserve), u64 bytes, int reserve),
TP_ARGS(fs_info, type, val, bytes, reserve), TP_ARGS(fs_info, type, val, bytes, reserve),
@ -963,13 +969,13 @@ TRACE_EVENT(btrfs_space_reservation,
TRACE_EVENT(btrfs_trigger_flush, TRACE_EVENT(btrfs_trigger_flush,
TP_PROTO(struct btrfs_fs_info *fs_info, u64 flags, u64 bytes, TP_PROTO(const struct btrfs_fs_info *fs_info, u64 flags, u64 bytes,
int flush, char *reason), int flush, char *reason),
TP_ARGS(fs_info, flags, bytes, flush, reason), TP_ARGS(fs_info, flags, bytes, flush, reason),
TP_STRUCT__entry( TP_STRUCT__entry(
__array( u8, fsid, BTRFS_UUID_SIZE ) __array( u8, fsid, BTRFS_FSID_SIZE )
__field( u64, flags ) __field( u64, flags )
__field( u64, bytes ) __field( u64, bytes )
__field( int, flush ) __field( int, flush )
@ -977,7 +983,7 @@ TRACE_EVENT(btrfs_trigger_flush,
), ),
TP_fast_assign( TP_fast_assign(
memcpy(__entry->fsid, fs_info->fsid, BTRFS_UUID_SIZE); memcpy(__entry->fsid, fs_info->fsid, BTRFS_FSID_SIZE);
__entry->flags = flags; __entry->flags = flags;
__entry->bytes = bytes; __entry->bytes = bytes;
__entry->flush = flush; __entry->flush = flush;
@ -1004,42 +1010,39 @@ TRACE_EVENT(btrfs_trigger_flush,
TRACE_EVENT(btrfs_flush_space, TRACE_EVENT(btrfs_flush_space,
TP_PROTO(struct btrfs_fs_info *fs_info, u64 flags, u64 num_bytes, TP_PROTO(const struct btrfs_fs_info *fs_info, u64 flags, u64 num_bytes,
u64 orig_bytes, int state, int ret), int state, int ret),
TP_ARGS(fs_info, flags, num_bytes, orig_bytes, state, ret), TP_ARGS(fs_info, flags, num_bytes, state, ret),
TP_STRUCT__entry( TP_STRUCT__entry(
__array( u8, fsid, BTRFS_UUID_SIZE ) __array( u8, fsid, BTRFS_FSID_SIZE )
__field( u64, flags ) __field( u64, flags )
__field( u64, num_bytes ) __field( u64, num_bytes )
__field( u64, orig_bytes )
__field( int, state ) __field( int, state )
__field( int, ret ) __field( int, ret )
), ),
TP_fast_assign( TP_fast_assign(
memcpy(__entry->fsid, fs_info->fsid, BTRFS_UUID_SIZE); memcpy(__entry->fsid, fs_info->fsid, BTRFS_FSID_SIZE);
__entry->flags = flags; __entry->flags = flags;
__entry->num_bytes = num_bytes; __entry->num_bytes = num_bytes;
__entry->orig_bytes = orig_bytes;
__entry->state = state; __entry->state = state;
__entry->ret = ret; __entry->ret = ret;
), ),
TP_printk("%pU: state=%d(%s) flags=%llu(%s) num_bytes=%llu " TP_printk("%pU: state=%d(%s) flags=%llu(%s) num_bytes=%llu ret=%d",
"orig_bytes=%llu ret=%d", __entry->fsid, __entry->state, __entry->fsid, __entry->state,
show_flush_state(__entry->state), show_flush_state(__entry->state),
(unsigned long long)__entry->flags, (unsigned long long)__entry->flags,
__print_flags((unsigned long)__entry->flags, "|", __print_flags((unsigned long)__entry->flags, "|",
BTRFS_GROUP_FLAGS), BTRFS_GROUP_FLAGS),
(unsigned long long)__entry->num_bytes, (unsigned long long)__entry->num_bytes, __entry->ret)
(unsigned long long)__entry->orig_bytes, __entry->ret)
); );
DECLARE_EVENT_CLASS(btrfs__reserved_extent, DECLARE_EVENT_CLASS(btrfs__reserved_extent,
TP_PROTO(struct btrfs_fs_info *fs_info, u64 start, u64 len), TP_PROTO(const struct btrfs_fs_info *fs_info, u64 start, u64 len),
TP_ARGS(fs_info, start, len), TP_ARGS(fs_info, start, len),
@ -1061,22 +1064,22 @@ DECLARE_EVENT_CLASS(btrfs__reserved_extent,
DEFINE_EVENT(btrfs__reserved_extent, btrfs_reserved_extent_alloc, DEFINE_EVENT(btrfs__reserved_extent, btrfs_reserved_extent_alloc,
TP_PROTO(struct btrfs_fs_info *fs_info, u64 start, u64 len), TP_PROTO(const struct btrfs_fs_info *fs_info, u64 start, u64 len),
TP_ARGS(fs_info, start, len) TP_ARGS(fs_info, start, len)
); );
DEFINE_EVENT(btrfs__reserved_extent, btrfs_reserved_extent_free, DEFINE_EVENT(btrfs__reserved_extent, btrfs_reserved_extent_free,
TP_PROTO(struct btrfs_fs_info *fs_info, u64 start, u64 len), TP_PROTO(const struct btrfs_fs_info *fs_info, u64 start, u64 len),
TP_ARGS(fs_info, start, len) TP_ARGS(fs_info, start, len)
); );
TRACE_EVENT(find_free_extent, TRACE_EVENT(find_free_extent,
TP_PROTO(struct btrfs_fs_info *fs_info, u64 num_bytes, u64 empty_size, TP_PROTO(const struct btrfs_fs_info *fs_info, u64 num_bytes,
u64 data), u64 empty_size, u64 data),
TP_ARGS(fs_info, num_bytes, empty_size, data), TP_ARGS(fs_info, num_bytes, empty_size, data),
@ -1101,8 +1104,8 @@ TRACE_EVENT(find_free_extent,
DECLARE_EVENT_CLASS(btrfs__reserve_extent, DECLARE_EVENT_CLASS(btrfs__reserve_extent,
TP_PROTO(struct btrfs_fs_info *fs_info, TP_PROTO(const struct btrfs_fs_info *fs_info,
struct btrfs_block_group_cache *block_group, u64 start, const struct btrfs_block_group_cache *block_group, u64 start,
u64 len), u64 len),
TP_ARGS(fs_info, block_group, start, len), TP_ARGS(fs_info, block_group, start, len),
@ -1132,8 +1135,8 @@ DECLARE_EVENT_CLASS(btrfs__reserve_extent,
DEFINE_EVENT(btrfs__reserve_extent, btrfs_reserve_extent, DEFINE_EVENT(btrfs__reserve_extent, btrfs_reserve_extent,
TP_PROTO(struct btrfs_fs_info *fs_info, TP_PROTO(const struct btrfs_fs_info *fs_info,
struct btrfs_block_group_cache *block_group, u64 start, const struct btrfs_block_group_cache *block_group, u64 start,
u64 len), u64 len),
TP_ARGS(fs_info, block_group, start, len) TP_ARGS(fs_info, block_group, start, len)
@ -1141,8 +1144,8 @@ DEFINE_EVENT(btrfs__reserve_extent, btrfs_reserve_extent,
DEFINE_EVENT(btrfs__reserve_extent, btrfs_reserve_extent_cluster, DEFINE_EVENT(btrfs__reserve_extent, btrfs_reserve_extent_cluster,
TP_PROTO(struct btrfs_fs_info *fs_info, TP_PROTO(const struct btrfs_fs_info *fs_info,
struct btrfs_block_group_cache *block_group, u64 start, const struct btrfs_block_group_cache *block_group, u64 start,
u64 len), u64 len),
TP_ARGS(fs_info, block_group, start, len) TP_ARGS(fs_info, block_group, start, len)
@ -1150,7 +1153,7 @@ DEFINE_EVENT(btrfs__reserve_extent, btrfs_reserve_extent_cluster,
TRACE_EVENT(btrfs_find_cluster, TRACE_EVENT(btrfs_find_cluster,
TP_PROTO(struct btrfs_block_group_cache *block_group, u64 start, TP_PROTO(const struct btrfs_block_group_cache *block_group, u64 start,
u64 bytes, u64 empty_size, u64 min_bytes), u64 bytes, u64 empty_size, u64 min_bytes),
TP_ARGS(block_group, start, bytes, empty_size, min_bytes), TP_ARGS(block_group, start, bytes, empty_size, min_bytes),
@ -1183,7 +1186,7 @@ TRACE_EVENT(btrfs_find_cluster,
TRACE_EVENT(btrfs_failed_cluster_setup, TRACE_EVENT(btrfs_failed_cluster_setup,
TP_PROTO(struct btrfs_block_group_cache *block_group), TP_PROTO(const struct btrfs_block_group_cache *block_group),
TP_ARGS(block_group), TP_ARGS(block_group),
@ -1200,8 +1203,9 @@ TRACE_EVENT(btrfs_failed_cluster_setup,
TRACE_EVENT(btrfs_setup_cluster, TRACE_EVENT(btrfs_setup_cluster,
TP_PROTO(struct btrfs_block_group_cache *block_group, TP_PROTO(const struct btrfs_block_group_cache *block_group,
struct btrfs_free_cluster *cluster, u64 size, int bitmap), const struct btrfs_free_cluster *cluster,
u64 size, int bitmap),
TP_ARGS(block_group, cluster, size, bitmap), TP_ARGS(block_group, cluster, size, bitmap),
@ -1235,12 +1239,13 @@ TRACE_EVENT(btrfs_setup_cluster,
struct extent_state; struct extent_state;
TRACE_EVENT(alloc_extent_state, TRACE_EVENT(alloc_extent_state,
TP_PROTO(struct extent_state *state, gfp_t mask, unsigned long IP), TP_PROTO(const struct extent_state *state,
gfp_t mask, unsigned long IP),
TP_ARGS(state, mask, IP), TP_ARGS(state, mask, IP),
TP_STRUCT__entry( TP_STRUCT__entry(
__field(struct extent_state *, state) __field(const struct extent_state *, state)
__field(gfp_t, mask) __field(gfp_t, mask)
__field(unsigned long, ip) __field(unsigned long, ip)
), ),
@ -1252,17 +1257,17 @@ TRACE_EVENT(alloc_extent_state,
), ),
TP_printk("state=%p mask=%s caller=%pS", __entry->state, TP_printk("state=%p mask=%s caller=%pS", __entry->state,
show_gfp_flags(__entry->mask), (void *)__entry->ip) show_gfp_flags(__entry->mask), (const void *)__entry->ip)
); );
TRACE_EVENT(free_extent_state, TRACE_EVENT(free_extent_state,
TP_PROTO(struct extent_state *state, unsigned long IP), TP_PROTO(const struct extent_state *state, unsigned long IP),
TP_ARGS(state, IP), TP_ARGS(state, IP),
TP_STRUCT__entry( TP_STRUCT__entry(
__field(struct extent_state *, state) __field(const struct extent_state *, state)
__field(unsigned long, ip) __field(unsigned long, ip)
), ),
@ -1272,22 +1277,22 @@ TRACE_EVENT(free_extent_state,
), ),
TP_printk("state=%p caller=%pS", __entry->state, TP_printk("state=%p caller=%pS", __entry->state,
(void *)__entry->ip) (const void *)__entry->ip)
); );
DECLARE_EVENT_CLASS(btrfs__work, DECLARE_EVENT_CLASS(btrfs__work,
TP_PROTO(struct btrfs_work *work), TP_PROTO(const struct btrfs_work *work),
TP_ARGS(work), TP_ARGS(work),
TP_STRUCT__entry_btrfs( TP_STRUCT__entry_btrfs(
__field( void *, work ) __field( const void *, work )
__field( void *, wq ) __field( const void *, wq )
__field( void *, func ) __field( const void *, func )
__field( void *, ordered_func ) __field( const void *, ordered_func )
__field( void *, ordered_free ) __field( const void *, ordered_free )
__field( void *, normal_work ) __field( const void *, normal_work )
), ),
TP_fast_assign_btrfs(btrfs_work_owner(work), TP_fast_assign_btrfs(btrfs_work_owner(work),
@ -1312,12 +1317,12 @@ DECLARE_EVENT_CLASS(btrfs__work,
*/ */
DECLARE_EVENT_CLASS(btrfs__work__done, DECLARE_EVENT_CLASS(btrfs__work__done,
TP_PROTO(struct btrfs_fs_info *fs_info, void *wtag), TP_PROTO(const struct btrfs_fs_info *fs_info, const void *wtag),
TP_ARGS(fs_info, wtag), TP_ARGS(fs_info, wtag),
TP_STRUCT__entry_btrfs( TP_STRUCT__entry_btrfs(
__field( void *, wtag ) __field( const void *, wtag )
), ),
TP_fast_assign_btrfs(fs_info, TP_fast_assign_btrfs(fs_info,
@ -1329,40 +1334,41 @@ DECLARE_EVENT_CLASS(btrfs__work__done,
DEFINE_EVENT(btrfs__work, btrfs_work_queued, DEFINE_EVENT(btrfs__work, btrfs_work_queued,
TP_PROTO(struct btrfs_work *work), TP_PROTO(const struct btrfs_work *work),
TP_ARGS(work) TP_ARGS(work)
); );
DEFINE_EVENT(btrfs__work, btrfs_work_sched, DEFINE_EVENT(btrfs__work, btrfs_work_sched,
TP_PROTO(struct btrfs_work *work), TP_PROTO(const struct btrfs_work *work),
TP_ARGS(work) TP_ARGS(work)
); );
DEFINE_EVENT(btrfs__work__done, btrfs_all_work_done, DEFINE_EVENT(btrfs__work__done, btrfs_all_work_done,
TP_PROTO(struct btrfs_fs_info *fs_info, void *wtag), TP_PROTO(const struct btrfs_fs_info *fs_info, const void *wtag),
TP_ARGS(fs_info, wtag) TP_ARGS(fs_info, wtag)
); );
DEFINE_EVENT(btrfs__work, btrfs_ordered_sched, DEFINE_EVENT(btrfs__work, btrfs_ordered_sched,
TP_PROTO(struct btrfs_work *work), TP_PROTO(const struct btrfs_work *work),
TP_ARGS(work) TP_ARGS(work)
); );
DECLARE_EVENT_CLASS(btrfs__workqueue, DECLARE_EVENT_CLASS(btrfs__workqueue,
TP_PROTO(struct __btrfs_workqueue *wq, const char *name, int high), TP_PROTO(const struct __btrfs_workqueue *wq,
const char *name, int high),
TP_ARGS(wq, name, high), TP_ARGS(wq, name, high),
TP_STRUCT__entry_btrfs( TP_STRUCT__entry_btrfs(
__field( void *, wq ) __field( const void *, wq )
__string( name, name ) __string( name, name )
__field( int , high ) __field( int , high )
), ),
@ -1381,19 +1387,20 @@ DECLARE_EVENT_CLASS(btrfs__workqueue,
DEFINE_EVENT(btrfs__workqueue, btrfs_workqueue_alloc, DEFINE_EVENT(btrfs__workqueue, btrfs_workqueue_alloc,
TP_PROTO(struct __btrfs_workqueue *wq, const char *name, int high), TP_PROTO(const struct __btrfs_workqueue *wq,
const char *name, int high),
TP_ARGS(wq, name, high) TP_ARGS(wq, name, high)
); );
DECLARE_EVENT_CLASS(btrfs__workqueue_done, DECLARE_EVENT_CLASS(btrfs__workqueue_done,
TP_PROTO(struct __btrfs_workqueue *wq), TP_PROTO(const struct __btrfs_workqueue *wq),
TP_ARGS(wq), TP_ARGS(wq),
TP_STRUCT__entry_btrfs( TP_STRUCT__entry_btrfs(
__field( void *, wq ) __field( const void *, wq )
), ),
TP_fast_assign_btrfs(btrfs_workqueue_owner(wq), TP_fast_assign_btrfs(btrfs_workqueue_owner(wq),
@ -1405,7 +1412,7 @@ DECLARE_EVENT_CLASS(btrfs__workqueue_done,
DEFINE_EVENT(btrfs__workqueue_done, btrfs_workqueue_destroy, DEFINE_EVENT(btrfs__workqueue_done, btrfs_workqueue_destroy,
TP_PROTO(struct __btrfs_workqueue *wq), TP_PROTO(const struct __btrfs_workqueue *wq),
TP_ARGS(wq) TP_ARGS(wq)
); );
@ -1417,7 +1424,8 @@ DEFINE_EVENT(btrfs__workqueue_done, btrfs_workqueue_destroy,
DECLARE_EVENT_CLASS(btrfs__qgroup_rsv_data, DECLARE_EVENT_CLASS(btrfs__qgroup_rsv_data,
TP_PROTO(struct inode *inode, u64 start, u64 len, u64 reserved, int op), TP_PROTO(const struct inode *inode, u64 start, u64 len,
u64 reserved, int op),
TP_ARGS(inode, start, len, reserved, op), TP_ARGS(inode, start, len, reserved, op),
@ -1449,21 +1457,24 @@ DECLARE_EVENT_CLASS(btrfs__qgroup_rsv_data,
DEFINE_EVENT(btrfs__qgroup_rsv_data, btrfs_qgroup_reserve_data, DEFINE_EVENT(btrfs__qgroup_rsv_data, btrfs_qgroup_reserve_data,
TP_PROTO(struct inode *inode, u64 start, u64 len, u64 reserved, int op), TP_PROTO(const struct inode *inode, u64 start, u64 len,
u64 reserved, int op),
TP_ARGS(inode, start, len, reserved, op) TP_ARGS(inode, start, len, reserved, op)
); );
DEFINE_EVENT(btrfs__qgroup_rsv_data, btrfs_qgroup_release_data, DEFINE_EVENT(btrfs__qgroup_rsv_data, btrfs_qgroup_release_data,
TP_PROTO(struct inode *inode, u64 start, u64 len, u64 reserved, int op), TP_PROTO(const struct inode *inode, u64 start, u64 len,
u64 reserved, int op),
TP_ARGS(inode, start, len, reserved, op) TP_ARGS(inode, start, len, reserved, op)
); );
DECLARE_EVENT_CLASS(btrfs__qgroup_delayed_ref, DECLARE_EVENT_CLASS(btrfs__qgroup_delayed_ref,
TP_PROTO(struct btrfs_fs_info *fs_info, u64 ref_root, u64 reserved), TP_PROTO(const struct btrfs_fs_info *fs_info,
u64 ref_root, u64 reserved),
TP_ARGS(fs_info, ref_root, reserved), TP_ARGS(fs_info, ref_root, reserved),
@ -1483,14 +1494,15 @@ DECLARE_EVENT_CLASS(btrfs__qgroup_delayed_ref,
DEFINE_EVENT(btrfs__qgroup_delayed_ref, btrfs_qgroup_free_delayed_ref, DEFINE_EVENT(btrfs__qgroup_delayed_ref, btrfs_qgroup_free_delayed_ref,
TP_PROTO(struct btrfs_fs_info *fs_info, u64 ref_root, u64 reserved), TP_PROTO(const struct btrfs_fs_info *fs_info,
u64 ref_root, u64 reserved),
TP_ARGS(fs_info, ref_root, reserved) TP_ARGS(fs_info, ref_root, reserved)
); );
DECLARE_EVENT_CLASS(btrfs_qgroup_extent, DECLARE_EVENT_CLASS(btrfs_qgroup_extent,
TP_PROTO(struct btrfs_fs_info *fs_info, TP_PROTO(const struct btrfs_fs_info *fs_info,
struct btrfs_qgroup_extent_record *rec), const struct btrfs_qgroup_extent_record *rec),
TP_ARGS(fs_info, rec), TP_ARGS(fs_info, rec),
@ -1511,23 +1523,23 @@ DECLARE_EVENT_CLASS(btrfs_qgroup_extent,
DEFINE_EVENT(btrfs_qgroup_extent, btrfs_qgroup_account_extents, DEFINE_EVENT(btrfs_qgroup_extent, btrfs_qgroup_account_extents,
TP_PROTO(struct btrfs_fs_info *fs_info, TP_PROTO(const struct btrfs_fs_info *fs_info,
struct btrfs_qgroup_extent_record *rec), const struct btrfs_qgroup_extent_record *rec),
TP_ARGS(fs_info, rec) TP_ARGS(fs_info, rec)
); );
DEFINE_EVENT(btrfs_qgroup_extent, btrfs_qgroup_trace_extent, DEFINE_EVENT(btrfs_qgroup_extent, btrfs_qgroup_trace_extent,
TP_PROTO(struct btrfs_fs_info *fs_info, TP_PROTO(const struct btrfs_fs_info *fs_info,
struct btrfs_qgroup_extent_record *rec), const struct btrfs_qgroup_extent_record *rec),
TP_ARGS(fs_info, rec) TP_ARGS(fs_info, rec)
); );
TRACE_EVENT(btrfs_qgroup_account_extent, TRACE_EVENT(btrfs_qgroup_account_extent,
TP_PROTO(struct btrfs_fs_info *fs_info, u64 bytenr, TP_PROTO(const struct btrfs_fs_info *fs_info, u64 bytenr,
u64 num_bytes, u64 nr_old_roots, u64 nr_new_roots), u64 num_bytes, u64 nr_old_roots, u64 nr_new_roots),
TP_ARGS(fs_info, bytenr, num_bytes, nr_old_roots, nr_new_roots), TP_ARGS(fs_info, bytenr, num_bytes, nr_old_roots, nr_new_roots),
@ -1556,7 +1568,7 @@ TRACE_EVENT(btrfs_qgroup_account_extent,
TRACE_EVENT(qgroup_update_counters, TRACE_EVENT(qgroup_update_counters,
TP_PROTO(struct btrfs_fs_info *fs_info, u64 qgid, TP_PROTO(const struct btrfs_fs_info *fs_info, u64 qgid,
u64 cur_old_count, u64 cur_new_count), u64 cur_old_count, u64 cur_new_count),
TP_ARGS(fs_info, qgid, cur_old_count, cur_new_count), TP_ARGS(fs_info, qgid, cur_old_count, cur_new_count),
@ -1622,6 +1634,63 @@ TRACE_EVENT(qgroup_meta_reserve,
show_root_type(__entry->refroot), __entry->diff) show_root_type(__entry->refroot), __entry->diff)
); );
DECLARE_EVENT_CLASS(btrfs__prelim_ref,
TP_PROTO(const struct btrfs_fs_info *fs_info,
const struct prelim_ref *oldref,
const struct prelim_ref *newref, u64 tree_size),
TP_ARGS(fs_info, newref, oldref, tree_size),
TP_STRUCT__entry_btrfs(
__field( u64, root_id )
__field( u64, objectid )
__field( u8, type )
__field( u64, offset )
__field( int, level )
__field( int, old_count )
__field( u64, parent )
__field( u64, bytenr )
__field( int, mod_count )
__field( u64, tree_size )
),
TP_fast_assign_btrfs(fs_info,
__entry->root_id = oldref->root_id;
__entry->objectid = oldref->key_for_search.objectid;
__entry->type = oldref->key_for_search.type;
__entry->offset = oldref->key_for_search.offset;
__entry->level = oldref->level;
__entry->old_count = oldref->count;
__entry->parent = oldref->parent;
__entry->bytenr = oldref->wanted_disk_byte;
__entry->mod_count = newref ? newref->count : 0;
__entry->tree_size = tree_size;
),
TP_printk_btrfs("root_id=%llu key=[%llu,%u,%llu] level=%d count=[%d+%d=%d] parent=%llu wanted_disk_byte=%llu nodes=%llu",
(unsigned long long)__entry->root_id,
(unsigned long long)__entry->objectid, __entry->type,
(unsigned long long)__entry->offset, __entry->level,
__entry->old_count, __entry->mod_count,
__entry->old_count + __entry->mod_count,
(unsigned long long)__entry->parent,
(unsigned long long)__entry->bytenr,
(unsigned long long)__entry->tree_size)
);
DEFINE_EVENT(btrfs__prelim_ref, btrfs_prelim_ref_merge,
TP_PROTO(const struct btrfs_fs_info *fs_info,
const struct prelim_ref *oldref,
const struct prelim_ref *newref, u64 tree_size),
TP_ARGS(fs_info, oldref, newref, tree_size)
);
DEFINE_EVENT(btrfs__prelim_ref, btrfs_prelim_ref_insert,
TP_PROTO(const struct btrfs_fs_info *fs_info,
const struct prelim_ref *oldref,
const struct prelim_ref *newref, u64 tree_size),
TP_ARGS(fs_info, oldref, newref, tree_size)
);
#endif /* _TRACE_BTRFS_H */ #endif /* _TRACE_BTRFS_H */
/* This part must be outside protection */ /* This part must be outside protection */