mirror of
https://github.com/torvalds/linux.git
synced 2024-11-23 04:31:50 +00:00
for-4.18-tag
-----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEE8rQSAMVO+zA4DBdWxWXV+ddtWDsFAlsVV6wACgkQxWXV+ddt WDsaOhAAnrG3o/Bkn4loifYjiWQoArswwVJ2m5MvG14oPcn/c6wCUlE6mHdEsT8l WgltSRSd/3hJ1BcuWjhcR8RSLBRSaPcw4FAHikAdOWMrLXSKfA+quT/upXD00iDS +bnHoknc5vvk+Ow0KyGODAeMYfJm8gGB43BeVDr/mgrVRrwYY9r14s+6LX897NOT qObdxBjtedua0uIYZX5673siFaSbvJNQyGn6iKO9Ww+7bkWjgKO8qY8/3/gEaJn1 q1303Oo65VOXQQKZed+NjPNakpqRmABaN79qTwWMnUI4qYBKi651a7sr5HljDpmc szY3uF/E7AOfJSDeTBdglFR1eQgv20ceeIx7FN0n6iUbuIVH9P85mBF6f76Hivpq fA39uPYxWwWq8RxmC09yqoTkuNS0zAQhov4n8XO0q/81Gfek0RpR+LMK15W02Ur8 +5Pazkgz+xRYRPhpExe75pbM5N31KFJdf+4wpXeZoXKGTeiiCl/SZV3NzyUtemGg eN7ltHD/Y9iNpx7sgHn+2veXwn6psDad8ORxIlRyKDeot2pNZ4lnekPbqMC/IwAz hF3ZpcEo8v2Q2kqwCqw5evq4NSOvfG0cEuIqAKir1AgTn2nPH99qRSR1He9kluap GBPTPXNgBrhhdsh5kltI6CJcGE46bHsLG4LI5WvRs+wOtyaG5Ww= =jIvf -----END PGP SIGNATURE----- Merge tag 'for-4.18-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux Pull btrfs updates from David Sterba: "User visible features: - added support for the ioctl FS_IOC_FSGETXATTR, per-inode flags, successor of GET/SETFLAGS; now supports only existing flags: append, immutable, noatime, nodump, sync - 3 new unprivileged ioctls to allow users to enumerate subvolumes - dedupe syscall implementation does not restrict the range to 16MiB, though it still splits the whole range to 16MiB chunks - on user demand, rmdir() is able to delete an empty subvolume, export the capability in sysfs - fix inode number types in tracepoints, other cleanups - send: improved speed when dealing with a large removed directory, measurements show decrease from 2000 minutes to 2 minutes on a directory with 2 million entries - pre-commit check of superblock to detect a mysterious in-memory corruption - log message updates Other changes: - orphan inode cleanup improved, does no keep long-standing reservations that could lead up to early ENOSPC in some cases - slight improvement of handling snapshotted NOCOW files by avoiding some unnecessary tree searches - avoid OOM when dealing with many unmergeable small extents at flush time - speedup conversion of free space tree representations from/to bitmap/tree - code refactoring, deletion, cleanups: + delayed refs + delayed iput + redundant argument removals + memory barrier cleanups + remove a redundant mutex supposedly excluding several ioctls to run in parallel - new tracepoints for blockgroup manipulation - more sanity checks of compressed headers" * tag 'for-4.18-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux: (183 commits) btrfs: Add unprivileged version of ino_lookup ioctl btrfs: Add unprivileged ioctl which returns subvolume's ROOT_REF btrfs: Add unprivileged ioctl which returns subvolume information Btrfs: clean up error handling in btrfs_truncate() btrfs: Factor out write portion of btrfs_get_blocks_direct btrfs: Factor out read portion of btrfs_get_blocks_direct btrfs: return ENOMEM if path allocation fails in btrfs_cross_ref_exist btrfs: raid56: Remove VLA usage btrfs: return error value if create_io_em failed in cow_file_range btrfs: drop useless member qgroup_reserved of btrfs_pending_snapshot btrfs: drop unused parameter qgroup_reserved btrfs: balance dirty metadata pages in btrfs_finish_ordered_io btrfs: lift some btrfs_cross_ref_exist checks in nocow path btrfs: Remove fs_info argument from btrfs_uuid_tree_rem btrfs: Remove fs_info argument from btrfs_uuid_tree_add Btrfs: remove unused check of skip_locking Btrfs: remove always true check in unlock_up Btrfs: grab write lock directly if write_lock_level is the max level Btrfs: move get root out of btrfs_search_slot to a helper Btrfs: use more straightforward extent_buffer_uptodate check ...
This commit is contained in:
commit
704996566f
@ -19,17 +19,17 @@
|
||||
* ordered operations list so that we make sure to flush out any
|
||||
* new data the application may have written before commit.
|
||||
*/
|
||||
#define BTRFS_INODE_ORDERED_DATA_CLOSE 0
|
||||
#define BTRFS_INODE_ORPHAN_META_RESERVED 1
|
||||
#define BTRFS_INODE_DUMMY 2
|
||||
#define BTRFS_INODE_IN_DEFRAG 3
|
||||
#define BTRFS_INODE_HAS_ORPHAN_ITEM 4
|
||||
#define BTRFS_INODE_HAS_ASYNC_EXTENT 5
|
||||
#define BTRFS_INODE_NEEDS_FULL_SYNC 6
|
||||
#define BTRFS_INODE_COPY_EVERYTHING 7
|
||||
#define BTRFS_INODE_IN_DELALLOC_LIST 8
|
||||
#define BTRFS_INODE_READDIO_NEED_LOCK 9
|
||||
#define BTRFS_INODE_HAS_PROPS 10
|
||||
enum {
|
||||
BTRFS_INODE_ORDERED_DATA_CLOSE = 0,
|
||||
BTRFS_INODE_DUMMY,
|
||||
BTRFS_INODE_IN_DEFRAG,
|
||||
BTRFS_INODE_HAS_ASYNC_EXTENT,
|
||||
BTRFS_INODE_NEEDS_FULL_SYNC,
|
||||
BTRFS_INODE_COPY_EVERYTHING,
|
||||
BTRFS_INODE_IN_DELALLOC_LIST,
|
||||
BTRFS_INODE_READDIO_NEED_LOCK,
|
||||
BTRFS_INODE_HAS_PROPS,
|
||||
};
|
||||
|
||||
/* in memory btrfs inode */
|
||||
struct btrfs_inode {
|
||||
|
@ -990,12 +990,7 @@ static void __free_workspace(int type, struct list_head *workspace,
|
||||
btrfs_compress_op[idx]->free_workspace(workspace);
|
||||
atomic_dec(total_ws);
|
||||
wake:
|
||||
/*
|
||||
* Make sure counter is updated before we wake up waiters.
|
||||
*/
|
||||
smp_mb();
|
||||
if (waitqueue_active(ws_wait))
|
||||
wake_up(ws_wait);
|
||||
cond_wake_up(ws_wait);
|
||||
}
|
||||
|
||||
static void free_workspace(int type, struct list_head *ws)
|
||||
|
@ -6,6 +6,8 @@
|
||||
#ifndef BTRFS_COMPRESSION_H
|
||||
#define BTRFS_COMPRESSION_H
|
||||
|
||||
#include <linux/sizes.h>
|
||||
|
||||
/*
|
||||
* We want to make sure that amount of RAM required to uncompress an extent is
|
||||
* reasonable, so we limit the total size in ram of a compressed extent to
|
||||
|
123
fs/btrfs/ctree.c
123
fs/btrfs/ctree.c
@ -2330,7 +2330,7 @@ static noinline void unlock_up(struct btrfs_path *path, int level,
|
||||
no_skips = 1;
|
||||
|
||||
t = path->nodes[i];
|
||||
if (i >= lowest_unlock && i > skip_level && path->locks[i]) {
|
||||
if (i >= lowest_unlock && i > skip_level) {
|
||||
btrfs_tree_unlock_rw(t, path->locks[i]);
|
||||
path->locks[i] = 0;
|
||||
if (write_lock_level &&
|
||||
@ -2432,7 +2432,6 @@ read_block_for_search(struct btrfs_root *root, struct btrfs_path *p,
|
||||
btrfs_unlock_up_safe(p, level + 1);
|
||||
btrfs_set_path_blocking(p);
|
||||
|
||||
free_extent_buffer(tmp);
|
||||
if (p->reada != READA_NONE)
|
||||
reada_for_search(fs_info, p, level, slot, key->objectid);
|
||||
|
||||
@ -2446,7 +2445,7 @@ read_block_for_search(struct btrfs_root *root, struct btrfs_path *p,
|
||||
* and give up so that our caller doesn't loop forever
|
||||
* on our EAGAINs.
|
||||
*/
|
||||
if (!btrfs_buffer_uptodate(tmp, 0, 0))
|
||||
if (!extent_buffer_uptodate(tmp))
|
||||
ret = -EIO;
|
||||
free_extent_buffer(tmp);
|
||||
} else {
|
||||
@ -2599,6 +2598,78 @@ int btrfs_find_item(struct btrfs_root *fs_root, struct btrfs_path *path,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct extent_buffer *btrfs_search_slot_get_root(struct btrfs_root *root,
|
||||
struct btrfs_path *p,
|
||||
int write_lock_level)
|
||||
{
|
||||
struct btrfs_fs_info *fs_info = root->fs_info;
|
||||
struct extent_buffer *b;
|
||||
int root_lock;
|
||||
int level = 0;
|
||||
|
||||
/* We try very hard to do read locks on the root */
|
||||
root_lock = BTRFS_READ_LOCK;
|
||||
|
||||
if (p->search_commit_root) {
|
||||
/* The commit roots are read only so we always do read locks */
|
||||
if (p->need_commit_sem)
|
||||
down_read(&fs_info->commit_root_sem);
|
||||
b = root->commit_root;
|
||||
extent_buffer_get(b);
|
||||
level = btrfs_header_level(b);
|
||||
if (p->need_commit_sem)
|
||||
up_read(&fs_info->commit_root_sem);
|
||||
/*
|
||||
* Ensure that all callers have set skip_locking when
|
||||
* p->search_commit_root = 1.
|
||||
*/
|
||||
ASSERT(p->skip_locking == 1);
|
||||
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (p->skip_locking) {
|
||||
b = btrfs_root_node(root);
|
||||
level = btrfs_header_level(b);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* If the level is set to maximum, we can skip trying to get the read
|
||||
* lock.
|
||||
*/
|
||||
if (write_lock_level < BTRFS_MAX_LEVEL) {
|
||||
/*
|
||||
* We don't know the level of the root node until we actually
|
||||
* have it read locked
|
||||
*/
|
||||
b = btrfs_read_lock_root_node(root);
|
||||
level = btrfs_header_level(b);
|
||||
if (level > write_lock_level)
|
||||
goto out;
|
||||
|
||||
/* Whoops, must trade for write lock */
|
||||
btrfs_tree_read_unlock(b);
|
||||
free_extent_buffer(b);
|
||||
}
|
||||
|
||||
b = btrfs_lock_root_node(root);
|
||||
root_lock = BTRFS_WRITE_LOCK;
|
||||
|
||||
/* The level might have changed, check again */
|
||||
level = btrfs_header_level(b);
|
||||
|
||||
out:
|
||||
p->nodes[level] = b;
|
||||
if (!p->skip_locking)
|
||||
p->locks[level] = root_lock;
|
||||
/*
|
||||
* Callers are responsible for dropping b's references.
|
||||
*/
|
||||
return b;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* btrfs_search_slot - look for a key in a tree and perform necessary
|
||||
* modifications to preserve tree invariants.
|
||||
@ -2635,7 +2706,6 @@ int btrfs_search_slot(struct btrfs_trans_handle *trans, struct btrfs_root *root,
|
||||
int err;
|
||||
int level;
|
||||
int lowest_unlock = 1;
|
||||
int root_lock;
|
||||
/* everything at write_lock_level or lower must be write locked */
|
||||
int write_lock_level = 0;
|
||||
u8 lowest_level = 0;
|
||||
@ -2673,50 +2743,7 @@ int btrfs_search_slot(struct btrfs_trans_handle *trans, struct btrfs_root *root,
|
||||
|
||||
again:
|
||||
prev_cmp = -1;
|
||||
/*
|
||||
* we try very hard to do read locks on the root
|
||||
*/
|
||||
root_lock = BTRFS_READ_LOCK;
|
||||
level = 0;
|
||||
if (p->search_commit_root) {
|
||||
/*
|
||||
* the commit roots are read only
|
||||
* so we always do read locks
|
||||
*/
|
||||
if (p->need_commit_sem)
|
||||
down_read(&fs_info->commit_root_sem);
|
||||
b = root->commit_root;
|
||||
extent_buffer_get(b);
|
||||
level = btrfs_header_level(b);
|
||||
if (p->need_commit_sem)
|
||||
up_read(&fs_info->commit_root_sem);
|
||||
if (!p->skip_locking)
|
||||
btrfs_tree_read_lock(b);
|
||||
} else {
|
||||
if (p->skip_locking) {
|
||||
b = btrfs_root_node(root);
|
||||
level = btrfs_header_level(b);
|
||||
} else {
|
||||
/* we don't know the level of the root node
|
||||
* until we actually have it read locked
|
||||
*/
|
||||
b = btrfs_read_lock_root_node(root);
|
||||
level = btrfs_header_level(b);
|
||||
if (level <= write_lock_level) {
|
||||
/* whoops, must trade for write lock */
|
||||
btrfs_tree_read_unlock(b);
|
||||
free_extent_buffer(b);
|
||||
b = btrfs_lock_root_node(root);
|
||||
root_lock = BTRFS_WRITE_LOCK;
|
||||
|
||||
/* the level might have changed, check again */
|
||||
level = btrfs_header_level(b);
|
||||
}
|
||||
}
|
||||
}
|
||||
p->nodes[level] = b;
|
||||
if (!p->skip_locking)
|
||||
p->locks[level] = root_lock;
|
||||
b = btrfs_search_slot_get_root(root, p, write_lock_level);
|
||||
|
||||
while (b) {
|
||||
level = btrfs_header_level(b);
|
||||
|
@ -739,6 +739,12 @@ struct btrfs_delayed_root;
|
||||
*/
|
||||
#define BTRFS_FS_NEED_ASYNC_COMMIT 17
|
||||
|
||||
/*
|
||||
* Indicate that balance has been set up from the ioctl and is in the main
|
||||
* phase. The fs_info::balance_ctl is initialized.
|
||||
*/
|
||||
#define BTRFS_FS_BALANCE_RUNNING 18
|
||||
|
||||
struct btrfs_fs_info {
|
||||
u8 fsid[BTRFS_FSID_SIZE];
|
||||
u8 chunk_tree_uuid[BTRFS_UUID_SIZE];
|
||||
@ -838,7 +844,6 @@ struct btrfs_fs_info {
|
||||
struct mutex transaction_kthread_mutex;
|
||||
struct mutex cleaner_mutex;
|
||||
struct mutex chunk_mutex;
|
||||
struct mutex volume_mutex;
|
||||
|
||||
/*
|
||||
* this is taken to make sure we don't set block groups ro after
|
||||
@ -1004,7 +1009,6 @@ struct btrfs_fs_info {
|
||||
/* restriper state */
|
||||
spinlock_t balance_lock;
|
||||
struct mutex balance_mutex;
|
||||
atomic_t balance_running;
|
||||
atomic_t balance_pause_req;
|
||||
atomic_t balance_cancel_req;
|
||||
struct btrfs_balance_control *balance_ctl;
|
||||
@ -1219,9 +1223,6 @@ struct btrfs_root {
|
||||
spinlock_t log_extents_lock[2];
|
||||
struct list_head logged_list[2];
|
||||
|
||||
spinlock_t orphan_lock;
|
||||
atomic_t orphan_inodes;
|
||||
struct btrfs_block_rsv *orphan_block_rsv;
|
||||
int orphan_cleanup_state;
|
||||
|
||||
spinlock_t inode_lock;
|
||||
@ -2764,13 +2765,9 @@ void btrfs_delalloc_release_space(struct inode *inode,
|
||||
void btrfs_free_reserved_data_space_noquota(struct inode *inode, u64 start,
|
||||
u64 len);
|
||||
void btrfs_trans_release_chunk_metadata(struct btrfs_trans_handle *trans);
|
||||
int btrfs_orphan_reserve_metadata(struct btrfs_trans_handle *trans,
|
||||
struct btrfs_inode *inode);
|
||||
void btrfs_orphan_release_metadata(struct btrfs_inode *inode);
|
||||
int btrfs_subvolume_reserve_metadata(struct btrfs_root *root,
|
||||
struct btrfs_block_rsv *rsv,
|
||||
int nitems,
|
||||
u64 *qgroup_reserved, bool use_global_rsv);
|
||||
int nitems, bool use_global_rsv);
|
||||
void btrfs_subvolume_release_metadata(struct btrfs_fs_info *fs_info,
|
||||
struct btrfs_block_rsv *rsv);
|
||||
void btrfs_delalloc_release_extents(struct btrfs_inode *inode, u64 num_bytes,
|
||||
@ -2828,7 +2825,7 @@ void btrfs_wait_for_snapshot_creation(struct btrfs_root *root);
|
||||
void check_system_chunk(struct btrfs_trans_handle *trans,
|
||||
struct btrfs_fs_info *fs_info, const u64 type);
|
||||
u64 add_new_free_space(struct btrfs_block_group_cache *block_group,
|
||||
struct btrfs_fs_info *info, u64 start, u64 end);
|
||||
u64 start, u64 end);
|
||||
|
||||
/* ctree.c */
|
||||
int btrfs_bin_search(struct extent_buffer *eb, const struct btrfs_key *key,
|
||||
@ -3042,11 +3039,9 @@ void btrfs_update_root_times(struct btrfs_trans_handle *trans,
|
||||
struct btrfs_root *root);
|
||||
|
||||
/* uuid-tree.c */
|
||||
int btrfs_uuid_tree_add(struct btrfs_trans_handle *trans,
|
||||
struct btrfs_fs_info *fs_info, u8 *uuid, u8 type,
|
||||
int btrfs_uuid_tree_add(struct btrfs_trans_handle *trans, u8 *uuid, u8 type,
|
||||
u64 subid);
|
||||
int btrfs_uuid_tree_rem(struct btrfs_trans_handle *trans,
|
||||
struct btrfs_fs_info *fs_info, u8 *uuid, u8 type,
|
||||
int btrfs_uuid_tree_remove(struct btrfs_trans_handle *trans, u8 *uuid, u8 type,
|
||||
u64 subid);
|
||||
int btrfs_uuid_tree_iterate(struct btrfs_fs_info *fs_info,
|
||||
int (*check_func)(struct btrfs_fs_info *, u8 *, u8,
|
||||
@ -3163,18 +3158,6 @@ void btrfs_extent_item_to_extent_map(struct btrfs_inode *inode,
|
||||
struct extent_map *em);
|
||||
|
||||
/* inode.c */
|
||||
struct btrfs_delalloc_work {
|
||||
struct inode *inode;
|
||||
int delay_iput;
|
||||
struct completion completion;
|
||||
struct list_head list;
|
||||
struct btrfs_work work;
|
||||
};
|
||||
|
||||
struct btrfs_delalloc_work *btrfs_alloc_delalloc_work(struct inode *inode,
|
||||
int delay_iput);
|
||||
void btrfs_wait_and_free_delalloc_work(struct btrfs_delalloc_work *work);
|
||||
|
||||
struct extent_map *btrfs_get_extent_fiemap(struct btrfs_inode *inode,
|
||||
struct page *page, size_t pg_offset, u64 start,
|
||||
u64 len, int create);
|
||||
@ -3193,10 +3176,7 @@ int btrfs_unlink_inode(struct btrfs_trans_handle *trans,
|
||||
int btrfs_add_link(struct btrfs_trans_handle *trans,
|
||||
struct btrfs_inode *parent_inode, struct btrfs_inode *inode,
|
||||
const char *name, int name_len, int add_backref, u64 index);
|
||||
int btrfs_unlink_subvol(struct btrfs_trans_handle *trans,
|
||||
struct btrfs_root *root,
|
||||
struct inode *dir, u64 objectid,
|
||||
const char *name, int name_len);
|
||||
int btrfs_delete_subvolume(struct inode *dir, struct dentry *dentry);
|
||||
int btrfs_truncate_block(struct inode *inode, loff_t from, loff_t len,
|
||||
int front);
|
||||
int btrfs_truncate_inode_items(struct btrfs_trans_handle *trans,
|
||||
@ -3204,9 +3184,8 @@ int btrfs_truncate_inode_items(struct btrfs_trans_handle *trans,
|
||||
struct inode *inode, u64 new_size,
|
||||
u32 min_type);
|
||||
|
||||
int btrfs_start_delalloc_inodes(struct btrfs_root *root, int delay_iput);
|
||||
int btrfs_start_delalloc_roots(struct btrfs_fs_info *fs_info, int delay_iput,
|
||||
int nr);
|
||||
int btrfs_start_delalloc_inodes(struct btrfs_root *root);
|
||||
int btrfs_start_delalloc_roots(struct btrfs_fs_info *fs_info, int nr);
|
||||
int btrfs_set_extent_delalloc(struct inode *inode, u64 start, u64 end,
|
||||
unsigned int extra_bits,
|
||||
struct extent_state **cached_state, int dedupe);
|
||||
@ -3240,10 +3219,7 @@ int btrfs_update_inode_fallback(struct btrfs_trans_handle *trans,
|
||||
int btrfs_orphan_add(struct btrfs_trans_handle *trans,
|
||||
struct btrfs_inode *inode);
|
||||
int btrfs_orphan_cleanup(struct btrfs_root *root);
|
||||
void btrfs_orphan_commit_root(struct btrfs_trans_handle *trans,
|
||||
struct btrfs_root *root);
|
||||
int btrfs_cont_expand(struct inode *inode, loff_t oldsize, loff_t size);
|
||||
void btrfs_invalidate_inodes(struct btrfs_root *root);
|
||||
void btrfs_add_delayed_iput(struct inode *inode);
|
||||
void btrfs_run_delayed_iputs(struct btrfs_fs_info *fs_info);
|
||||
int btrfs_prealloc_file_range(struct inode *inode, int mode,
|
||||
@ -3262,14 +3238,14 @@ void btrfs_test_inode_set_ops(struct inode *inode);
|
||||
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);
|
||||
int btrfs_ioctl_get_supported_features(void __user *arg);
|
||||
void btrfs_update_iflags(struct inode *inode);
|
||||
void btrfs_sync_inode_flags_to_i_flags(struct inode *inode);
|
||||
int btrfs_is_empty_uuid(u8 *uuid);
|
||||
int btrfs_defrag_file(struct inode *inode, struct file *file,
|
||||
struct btrfs_ioctl_defrag_range_args *range,
|
||||
u64 newer_than, unsigned long max_pages);
|
||||
void btrfs_get_block_group_info(struct list_head *groups_list,
|
||||
struct btrfs_ioctl_space_info *space);
|
||||
void update_ioctl_balance_args(struct btrfs_fs_info *fs_info, int lock,
|
||||
void btrfs_update_ioctl_balance_args(struct btrfs_fs_info *fs_info,
|
||||
struct btrfs_ioctl_balance_args *bargs);
|
||||
ssize_t btrfs_dedupe_file_range(struct file *src_file, u64 loff, u64 olen,
|
||||
struct file *dst_file, u64 dst_loff);
|
||||
@ -3767,4 +3743,26 @@ static inline int btrfs_is_testing(struct btrfs_fs_info *fs_info)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void cond_wake_up(struct wait_queue_head *wq)
|
||||
{
|
||||
/*
|
||||
* This implies a full smp_mb barrier, see comments for
|
||||
* waitqueue_active why.
|
||||
*/
|
||||
if (wq_has_sleeper(wq))
|
||||
wake_up(wq);
|
||||
}
|
||||
|
||||
static inline void cond_wake_up_nomb(struct wait_queue_head *wq)
|
||||
{
|
||||
/*
|
||||
* Special case for conditional wakeup where the barrier required for
|
||||
* waitqueue_active is implied by some of the preceding code. Eg. one
|
||||
* of such atomic operations (atomic_dec_and_return, ...), or a
|
||||
* unlock/lock sequence, etc.
|
||||
*/
|
||||
if (waitqueue_active(wq))
|
||||
wake_up(wq);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -460,13 +460,10 @@ static void finish_one_item(struct btrfs_delayed_root *delayed_root)
|
||||
{
|
||||
int seq = atomic_inc_return(&delayed_root->items_seq);
|
||||
|
||||
/*
|
||||
* atomic_dec_return implies a barrier for waitqueue_active
|
||||
*/
|
||||
/* atomic_dec_return implies a barrier */
|
||||
if ((atomic_dec_return(&delayed_root->items) <
|
||||
BTRFS_DELAYED_BACKGROUND || seq % BTRFS_DELAYED_BATCH == 0) &&
|
||||
waitqueue_active(&delayed_root->wait))
|
||||
wake_up(&delayed_root->wait);
|
||||
BTRFS_DELAYED_BACKGROUND || seq % BTRFS_DELAYED_BATCH == 0))
|
||||
cond_wake_up_nomb(&delayed_root->wait);
|
||||
}
|
||||
|
||||
static void __btrfs_remove_delayed_item(struct btrfs_delayed_item *delayed_item)
|
||||
|
@ -286,10 +286,10 @@ static bool merge_ref(struct btrfs_trans_handle *trans,
|
||||
}
|
||||
|
||||
void btrfs_merge_delayed_refs(struct btrfs_trans_handle *trans,
|
||||
struct btrfs_fs_info *fs_info,
|
||||
struct btrfs_delayed_ref_root *delayed_refs,
|
||||
struct btrfs_delayed_ref_head *head)
|
||||
{
|
||||
struct btrfs_fs_info *fs_info = trans->fs_info;
|
||||
struct btrfs_delayed_ref_node *ref;
|
||||
struct rb_node *node;
|
||||
u64 seq = 0;
|
||||
@ -323,9 +323,7 @@ again:
|
||||
}
|
||||
}
|
||||
|
||||
int btrfs_check_delayed_seq(struct btrfs_fs_info *fs_info,
|
||||
struct btrfs_delayed_ref_root *delayed_refs,
|
||||
u64 seq)
|
||||
int btrfs_check_delayed_seq(struct btrfs_fs_info *fs_info, u64 seq)
|
||||
{
|
||||
struct seq_list *elem;
|
||||
int ret = 0;
|
||||
@ -336,10 +334,9 @@ int btrfs_check_delayed_seq(struct btrfs_fs_info *fs_info,
|
||||
struct seq_list, list);
|
||||
if (seq >= elem->seq) {
|
||||
btrfs_debug(fs_info,
|
||||
"holding back delayed_ref %#x.%x, lowest is %#x.%x (%p)",
|
||||
"holding back delayed_ref %#x.%x, lowest is %#x.%x",
|
||||
(u32)(seq >> 32), (u32)seq,
|
||||
(u32)(elem->seq >> 32), (u32)elem->seq,
|
||||
delayed_refs);
|
||||
(u32)(elem->seq >> 32), (u32)elem->seq);
|
||||
ret = 1;
|
||||
}
|
||||
}
|
||||
@ -529,33 +526,20 @@ update_existing_head_ref(struct btrfs_delayed_ref_root *delayed_refs,
|
||||
spin_unlock(&existing->lock);
|
||||
}
|
||||
|
||||
/*
|
||||
* helper function to actually insert a head node into the rbtree.
|
||||
* this does all the dirty work in terms of maintaining the correct
|
||||
* overall modification count.
|
||||
*/
|
||||
static noinline struct btrfs_delayed_ref_head *
|
||||
add_delayed_ref_head(struct btrfs_fs_info *fs_info,
|
||||
struct btrfs_trans_handle *trans,
|
||||
struct btrfs_delayed_ref_head *head_ref,
|
||||
struct btrfs_qgroup_extent_record *qrecord,
|
||||
u64 bytenr, u64 num_bytes, u64 ref_root, u64 reserved,
|
||||
int action, int is_data, int is_system,
|
||||
int *qrecord_inserted_ret,
|
||||
int *old_ref_mod, int *new_ref_mod)
|
||||
|
||||
static void init_delayed_ref_head(struct btrfs_delayed_ref_head *head_ref,
|
||||
struct btrfs_qgroup_extent_record *qrecord,
|
||||
u64 bytenr, u64 num_bytes, u64 ref_root,
|
||||
u64 reserved, int action, bool is_data,
|
||||
bool is_system)
|
||||
{
|
||||
struct btrfs_delayed_ref_head *existing;
|
||||
struct btrfs_delayed_ref_root *delayed_refs;
|
||||
int count_mod = 1;
|
||||
int must_insert_reserved = 0;
|
||||
int qrecord_inserted = 0;
|
||||
|
||||
/* If reserved is provided, it must be a data extent. */
|
||||
BUG_ON(!is_data && reserved);
|
||||
|
||||
/*
|
||||
* the head node stores the sum of all the mods, so dropping a ref
|
||||
* The head node stores the sum of all the mods, so dropping a ref
|
||||
* should drop the sum in the head node by one.
|
||||
*/
|
||||
if (action == BTRFS_UPDATE_DELAYED_HEAD)
|
||||
@ -564,12 +548,11 @@ add_delayed_ref_head(struct btrfs_fs_info *fs_info,
|
||||
count_mod = -1;
|
||||
|
||||
/*
|
||||
* BTRFS_ADD_DELAYED_EXTENT means that we need to update
|
||||
* the reserved accounting when the extent is finally added, or
|
||||
* if a later modification deletes the delayed ref without ever
|
||||
* inserting the extent into the extent allocation tree.
|
||||
* ref->must_insert_reserved is the flag used to record
|
||||
* that accounting mods are required.
|
||||
* BTRFS_ADD_DELAYED_EXTENT means that we need to update the reserved
|
||||
* accounting when the extent is finally added, or if a later
|
||||
* modification deletes the delayed ref without ever inserting the
|
||||
* extent into the extent allocation tree. ref->must_insert_reserved
|
||||
* is the flag used to record that accounting mods are required.
|
||||
*
|
||||
* Once we record must_insert_reserved, switch the action to
|
||||
* BTRFS_ADD_DELAYED_REF because other special casing is not required.
|
||||
@ -579,8 +562,6 @@ add_delayed_ref_head(struct btrfs_fs_info *fs_info,
|
||||
else
|
||||
must_insert_reserved = 0;
|
||||
|
||||
delayed_refs = &trans->transaction->delayed_refs;
|
||||
|
||||
refcount_set(&head_ref->refs, 1);
|
||||
head_ref->bytenr = bytenr;
|
||||
head_ref->num_bytes = num_bytes;
|
||||
@ -598,7 +579,6 @@ add_delayed_ref_head(struct btrfs_fs_info *fs_info,
|
||||
spin_lock_init(&head_ref->lock);
|
||||
mutex_init(&head_ref->mutex);
|
||||
|
||||
/* Record qgroup extent info if provided */
|
||||
if (qrecord) {
|
||||
if (ref_root && reserved) {
|
||||
head_ref->qgroup_ref_root = ref_root;
|
||||
@ -608,20 +588,44 @@ add_delayed_ref_head(struct btrfs_fs_info *fs_info,
|
||||
qrecord->bytenr = bytenr;
|
||||
qrecord->num_bytes = num_bytes;
|
||||
qrecord->old_roots = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if(btrfs_qgroup_trace_extent_nolock(fs_info,
|
||||
/*
|
||||
* helper function to actually insert a head node into the rbtree.
|
||||
* this does all the dirty work in terms of maintaining the correct
|
||||
* overall modification count.
|
||||
*/
|
||||
static noinline struct btrfs_delayed_ref_head *
|
||||
add_delayed_ref_head(struct btrfs_trans_handle *trans,
|
||||
struct btrfs_delayed_ref_head *head_ref,
|
||||
struct btrfs_qgroup_extent_record *qrecord,
|
||||
int action, int *qrecord_inserted_ret,
|
||||
int *old_ref_mod, int *new_ref_mod)
|
||||
{
|
||||
struct btrfs_delayed_ref_head *existing;
|
||||
struct btrfs_delayed_ref_root *delayed_refs;
|
||||
int qrecord_inserted = 0;
|
||||
|
||||
delayed_refs = &trans->transaction->delayed_refs;
|
||||
|
||||
/* Record qgroup extent info if provided */
|
||||
if (qrecord) {
|
||||
if (btrfs_qgroup_trace_extent_nolock(trans->fs_info,
|
||||
delayed_refs, qrecord))
|
||||
kfree(qrecord);
|
||||
else
|
||||
qrecord_inserted = 1;
|
||||
}
|
||||
|
||||
trace_add_delayed_ref_head(fs_info, head_ref, action);
|
||||
trace_add_delayed_ref_head(trans->fs_info, head_ref, action);
|
||||
|
||||
existing = htree_insert(&delayed_refs->href_root,
|
||||
&head_ref->href_node);
|
||||
if (existing) {
|
||||
WARN_ON(ref_root && reserved && existing->qgroup_ref_root
|
||||
WARN_ON(qrecord && head_ref->qgroup_ref_root
|
||||
&& head_ref->qgroup_reserved
|
||||
&& existing->qgroup_ref_root
|
||||
&& existing->qgroup_reserved);
|
||||
update_existing_head_ref(delayed_refs, existing, head_ref,
|
||||
old_ref_mod);
|
||||
@ -634,8 +638,8 @@ add_delayed_ref_head(struct btrfs_fs_info *fs_info,
|
||||
} else {
|
||||
if (old_ref_mod)
|
||||
*old_ref_mod = 0;
|
||||
if (is_data && count_mod < 0)
|
||||
delayed_refs->pending_csums += num_bytes;
|
||||
if (head_ref->is_data && head_ref->ref_mod < 0)
|
||||
delayed_refs->pending_csums += head_ref->num_bytes;
|
||||
delayed_refs->num_heads++;
|
||||
delayed_refs->num_heads_ready++;
|
||||
atomic_inc(&delayed_refs->num_entries);
|
||||
@ -645,33 +649,48 @@ add_delayed_ref_head(struct btrfs_fs_info *fs_info,
|
||||
*qrecord_inserted_ret = qrecord_inserted;
|
||||
if (new_ref_mod)
|
||||
*new_ref_mod = head_ref->total_ref_mod;
|
||||
|
||||
return head_ref;
|
||||
}
|
||||
|
||||
/*
|
||||
* helper to insert a delayed tree ref into the rbtree.
|
||||
* init_delayed_ref_common - Initialize the structure which represents a
|
||||
* modification to a an extent.
|
||||
*
|
||||
* @fs_info: Internal to the mounted filesystem mount structure.
|
||||
*
|
||||
* @ref: The structure which is going to be initialized.
|
||||
*
|
||||
* @bytenr: The logical address of the extent for which a modification is
|
||||
* going to be recorded.
|
||||
*
|
||||
* @num_bytes: Size of the extent whose modification is being recorded.
|
||||
*
|
||||
* @ref_root: The id of the root where this modification has originated, this
|
||||
* can be either one of the well-known metadata trees or the
|
||||
* subvolume id which references this extent.
|
||||
*
|
||||
* @action: Can be one of BTRFS_ADD_DELAYED_REF/BTRFS_DROP_DELAYED_REF or
|
||||
* BTRFS_ADD_DELAYED_EXTENT
|
||||
*
|
||||
* @ref_type: Holds the type of the extent which is being recorded, can be
|
||||
* one of BTRFS_SHARED_BLOCK_REF_KEY/BTRFS_TREE_BLOCK_REF_KEY
|
||||
* when recording a metadata extent or BTRFS_SHARED_DATA_REF_KEY/
|
||||
* BTRFS_EXTENT_DATA_REF_KEY when recording data extent
|
||||
*/
|
||||
static noinline void
|
||||
add_delayed_tree_ref(struct btrfs_fs_info *fs_info,
|
||||
struct btrfs_trans_handle *trans,
|
||||
struct btrfs_delayed_ref_head *head_ref,
|
||||
struct btrfs_delayed_ref_node *ref, u64 bytenr,
|
||||
u64 num_bytes, u64 parent, u64 ref_root, int level,
|
||||
int action)
|
||||
static void init_delayed_ref_common(struct btrfs_fs_info *fs_info,
|
||||
struct btrfs_delayed_ref_node *ref,
|
||||
u64 bytenr, u64 num_bytes, u64 ref_root,
|
||||
int action, u8 ref_type)
|
||||
{
|
||||
struct btrfs_delayed_tree_ref *full_ref;
|
||||
struct btrfs_delayed_ref_root *delayed_refs;
|
||||
u64 seq = 0;
|
||||
int ret;
|
||||
|
||||
if (action == BTRFS_ADD_DELAYED_EXTENT)
|
||||
action = BTRFS_ADD_DELAYED_REF;
|
||||
|
||||
if (is_fstree(ref_root))
|
||||
seq = atomic64_read(&fs_info->tree_mod_seq);
|
||||
delayed_refs = &trans->transaction->delayed_refs;
|
||||
|
||||
/* first set the basic ref node struct up */
|
||||
refcount_set(&ref->refs, 1);
|
||||
ref->bytenr = bytenr;
|
||||
ref->num_bytes = num_bytes;
|
||||
@ -680,82 +699,9 @@ add_delayed_tree_ref(struct btrfs_fs_info *fs_info,
|
||||
ref->is_head = 0;
|
||||
ref->in_tree = 1;
|
||||
ref->seq = seq;
|
||||
ref->type = ref_type;
|
||||
RB_CLEAR_NODE(&ref->ref_node);
|
||||
INIT_LIST_HEAD(&ref->add_list);
|
||||
|
||||
full_ref = btrfs_delayed_node_to_tree_ref(ref);
|
||||
full_ref->parent = parent;
|
||||
full_ref->root = ref_root;
|
||||
if (parent)
|
||||
ref->type = BTRFS_SHARED_BLOCK_REF_KEY;
|
||||
else
|
||||
ref->type = BTRFS_TREE_BLOCK_REF_KEY;
|
||||
full_ref->level = level;
|
||||
|
||||
trace_add_delayed_tree_ref(fs_info, ref, full_ref, action);
|
||||
|
||||
ret = insert_delayed_ref(trans, delayed_refs, head_ref, ref);
|
||||
|
||||
/*
|
||||
* XXX: memory should be freed at the same level allocated.
|
||||
* But bad practice is anywhere... Follow it now. Need cleanup.
|
||||
*/
|
||||
if (ret > 0)
|
||||
kmem_cache_free(btrfs_delayed_tree_ref_cachep, full_ref);
|
||||
}
|
||||
|
||||
/*
|
||||
* helper to insert a delayed data ref into the rbtree.
|
||||
*/
|
||||
static noinline void
|
||||
add_delayed_data_ref(struct btrfs_fs_info *fs_info,
|
||||
struct btrfs_trans_handle *trans,
|
||||
struct btrfs_delayed_ref_head *head_ref,
|
||||
struct btrfs_delayed_ref_node *ref, u64 bytenr,
|
||||
u64 num_bytes, u64 parent, u64 ref_root, u64 owner,
|
||||
u64 offset, int action)
|
||||
{
|
||||
struct btrfs_delayed_data_ref *full_ref;
|
||||
struct btrfs_delayed_ref_root *delayed_refs;
|
||||
u64 seq = 0;
|
||||
int ret;
|
||||
|
||||
if (action == BTRFS_ADD_DELAYED_EXTENT)
|
||||
action = BTRFS_ADD_DELAYED_REF;
|
||||
|
||||
delayed_refs = &trans->transaction->delayed_refs;
|
||||
|
||||
if (is_fstree(ref_root))
|
||||
seq = atomic64_read(&fs_info->tree_mod_seq);
|
||||
|
||||
/* first set the basic ref node struct up */
|
||||
refcount_set(&ref->refs, 1);
|
||||
ref->bytenr = bytenr;
|
||||
ref->num_bytes = num_bytes;
|
||||
ref->ref_mod = 1;
|
||||
ref->action = action;
|
||||
ref->is_head = 0;
|
||||
ref->in_tree = 1;
|
||||
ref->seq = seq;
|
||||
RB_CLEAR_NODE(&ref->ref_node);
|
||||
INIT_LIST_HEAD(&ref->add_list);
|
||||
|
||||
full_ref = btrfs_delayed_node_to_data_ref(ref);
|
||||
full_ref->parent = parent;
|
||||
full_ref->root = ref_root;
|
||||
if (parent)
|
||||
ref->type = BTRFS_SHARED_DATA_REF_KEY;
|
||||
else
|
||||
ref->type = BTRFS_EXTENT_DATA_REF_KEY;
|
||||
|
||||
full_ref->objectid = owner;
|
||||
full_ref->offset = offset;
|
||||
|
||||
trace_add_delayed_data_ref(fs_info, ref, full_ref, action);
|
||||
|
||||
ret = insert_delayed_ref(trans, delayed_refs, head_ref, ref);
|
||||
if (ret > 0)
|
||||
kmem_cache_free(btrfs_delayed_data_ref_cachep, full_ref);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -775,13 +721,25 @@ int btrfs_add_delayed_tree_ref(struct btrfs_fs_info *fs_info,
|
||||
struct btrfs_delayed_ref_root *delayed_refs;
|
||||
struct btrfs_qgroup_extent_record *record = NULL;
|
||||
int qrecord_inserted;
|
||||
int is_system = (ref_root == BTRFS_CHUNK_TREE_OBJECTID);
|
||||
bool is_system = (ref_root == BTRFS_CHUNK_TREE_OBJECTID);
|
||||
int ret;
|
||||
u8 ref_type;
|
||||
|
||||
BUG_ON(extent_op && extent_op->is_data);
|
||||
ref = kmem_cache_alloc(btrfs_delayed_tree_ref_cachep, GFP_NOFS);
|
||||
if (!ref)
|
||||
return -ENOMEM;
|
||||
|
||||
if (parent)
|
||||
ref_type = BTRFS_SHARED_BLOCK_REF_KEY;
|
||||
else
|
||||
ref_type = BTRFS_TREE_BLOCK_REF_KEY;
|
||||
init_delayed_ref_common(fs_info, &ref->node, bytenr, num_bytes,
|
||||
ref_root, action, ref_type);
|
||||
ref->root = ref_root;
|
||||
ref->parent = parent;
|
||||
ref->level = level;
|
||||
|
||||
head_ref = kmem_cache_alloc(btrfs_delayed_ref_head_cachep, GFP_NOFS);
|
||||
if (!head_ref)
|
||||
goto free_ref;
|
||||
@ -793,6 +751,8 @@ int btrfs_add_delayed_tree_ref(struct btrfs_fs_info *fs_info,
|
||||
goto free_head_ref;
|
||||
}
|
||||
|
||||
init_delayed_ref_head(head_ref, record, bytenr, num_bytes,
|
||||
ref_root, 0, action, false, is_system);
|
||||
head_ref->extent_op = extent_op;
|
||||
|
||||
delayed_refs = &trans->transaction->delayed_refs;
|
||||
@ -802,15 +762,19 @@ int btrfs_add_delayed_tree_ref(struct btrfs_fs_info *fs_info,
|
||||
* insert both the head node and the new ref without dropping
|
||||
* the spin lock
|
||||
*/
|
||||
head_ref = add_delayed_ref_head(fs_info, trans, head_ref, record,
|
||||
bytenr, num_bytes, 0, 0, action, 0,
|
||||
is_system, &qrecord_inserted,
|
||||
head_ref = add_delayed_ref_head(trans, head_ref, record,
|
||||
action, &qrecord_inserted,
|
||||
old_ref_mod, new_ref_mod);
|
||||
|
||||
add_delayed_tree_ref(fs_info, trans, head_ref, &ref->node, bytenr,
|
||||
num_bytes, parent, ref_root, level, action);
|
||||
ret = insert_delayed_ref(trans, delayed_refs, head_ref, &ref->node);
|
||||
spin_unlock(&delayed_refs->lock);
|
||||
|
||||
trace_add_delayed_tree_ref(fs_info, &ref->node, ref,
|
||||
action == BTRFS_ADD_DELAYED_EXTENT ?
|
||||
BTRFS_ADD_DELAYED_REF : action);
|
||||
if (ret > 0)
|
||||
kmem_cache_free(btrfs_delayed_tree_ref_cachep, ref);
|
||||
|
||||
if (qrecord_inserted)
|
||||
btrfs_qgroup_trace_extent_post(fs_info, record);
|
||||
|
||||
@ -839,11 +803,25 @@ int btrfs_add_delayed_data_ref(struct btrfs_fs_info *fs_info,
|
||||
struct btrfs_delayed_ref_root *delayed_refs;
|
||||
struct btrfs_qgroup_extent_record *record = NULL;
|
||||
int qrecord_inserted;
|
||||
int ret;
|
||||
u8 ref_type;
|
||||
|
||||
ref = kmem_cache_alloc(btrfs_delayed_data_ref_cachep, GFP_NOFS);
|
||||
if (!ref)
|
||||
return -ENOMEM;
|
||||
|
||||
if (parent)
|
||||
ref_type = BTRFS_SHARED_DATA_REF_KEY;
|
||||
else
|
||||
ref_type = BTRFS_EXTENT_DATA_REF_KEY;
|
||||
init_delayed_ref_common(fs_info, &ref->node, bytenr, num_bytes,
|
||||
ref_root, action, ref_type);
|
||||
ref->root = ref_root;
|
||||
ref->parent = parent;
|
||||
ref->objectid = owner;
|
||||
ref->offset = offset;
|
||||
|
||||
|
||||
head_ref = kmem_cache_alloc(btrfs_delayed_ref_head_cachep, GFP_NOFS);
|
||||
if (!head_ref) {
|
||||
kmem_cache_free(btrfs_delayed_data_ref_cachep, ref);
|
||||
@ -861,6 +839,8 @@ int btrfs_add_delayed_data_ref(struct btrfs_fs_info *fs_info,
|
||||
}
|
||||
}
|
||||
|
||||
init_delayed_ref_head(head_ref, record, bytenr, num_bytes, ref_root,
|
||||
reserved, action, true, false);
|
||||
head_ref->extent_op = NULL;
|
||||
|
||||
delayed_refs = &trans->transaction->delayed_refs;
|
||||
@ -870,16 +850,20 @@ int btrfs_add_delayed_data_ref(struct btrfs_fs_info *fs_info,
|
||||
* insert both the head node and the new ref without dropping
|
||||
* the spin lock
|
||||
*/
|
||||
head_ref = add_delayed_ref_head(fs_info, trans, head_ref, record,
|
||||
bytenr, num_bytes, ref_root, reserved,
|
||||
action, 1, 0, &qrecord_inserted,
|
||||
head_ref = add_delayed_ref_head(trans, head_ref, record,
|
||||
action, &qrecord_inserted,
|
||||
old_ref_mod, new_ref_mod);
|
||||
|
||||
add_delayed_data_ref(fs_info, trans, head_ref, &ref->node, bytenr,
|
||||
num_bytes, parent, ref_root, owner, offset,
|
||||
action);
|
||||
ret = insert_delayed_ref(trans, delayed_refs, head_ref, &ref->node);
|
||||
spin_unlock(&delayed_refs->lock);
|
||||
|
||||
trace_add_delayed_data_ref(trans->fs_info, &ref->node, ref,
|
||||
action == BTRFS_ADD_DELAYED_EXTENT ?
|
||||
BTRFS_ADD_DELAYED_REF : action);
|
||||
if (ret > 0)
|
||||
kmem_cache_free(btrfs_delayed_data_ref_cachep, ref);
|
||||
|
||||
|
||||
if (qrecord_inserted)
|
||||
return btrfs_qgroup_trace_extent_post(fs_info, record);
|
||||
return 0;
|
||||
@ -897,19 +881,16 @@ int btrfs_add_delayed_extent_op(struct btrfs_fs_info *fs_info,
|
||||
if (!head_ref)
|
||||
return -ENOMEM;
|
||||
|
||||
init_delayed_ref_head(head_ref, NULL, bytenr, num_bytes, 0, 0,
|
||||
BTRFS_UPDATE_DELAYED_HEAD, extent_op->is_data,
|
||||
false);
|
||||
head_ref->extent_op = extent_op;
|
||||
|
||||
delayed_refs = &trans->transaction->delayed_refs;
|
||||
spin_lock(&delayed_refs->lock);
|
||||
|
||||
/*
|
||||
* extent_ops just modify the flags of an extent and they don't result
|
||||
* in ref count changes, hence it's safe to pass false/0 for is_system
|
||||
* argument
|
||||
*/
|
||||
add_delayed_ref_head(fs_info, trans, head_ref, NULL, bytenr,
|
||||
num_bytes, 0, 0, BTRFS_UPDATE_DELAYED_HEAD,
|
||||
extent_op->is_data, 0, NULL, NULL, NULL);
|
||||
add_delayed_ref_head(trans, head_ref, NULL, BTRFS_UPDATE_DELAYED_HEAD,
|
||||
NULL, NULL, NULL);
|
||||
|
||||
spin_unlock(&delayed_refs->lock);
|
||||
return 0;
|
||||
|
@ -251,7 +251,6 @@ int btrfs_add_delayed_extent_op(struct btrfs_fs_info *fs_info,
|
||||
u64 bytenr, u64 num_bytes,
|
||||
struct btrfs_delayed_extent_op *extent_op);
|
||||
void btrfs_merge_delayed_refs(struct btrfs_trans_handle *trans,
|
||||
struct btrfs_fs_info *fs_info,
|
||||
struct btrfs_delayed_ref_root *delayed_refs,
|
||||
struct btrfs_delayed_ref_head *head);
|
||||
|
||||
@ -269,9 +268,7 @@ static inline void btrfs_delayed_ref_unlock(struct btrfs_delayed_ref_head *head)
|
||||
struct btrfs_delayed_ref_head *
|
||||
btrfs_select_ref_head(struct btrfs_trans_handle *trans);
|
||||
|
||||
int btrfs_check_delayed_seq(struct btrfs_fs_info *fs_info,
|
||||
struct btrfs_delayed_ref_root *delayed_refs,
|
||||
u64 seq);
|
||||
int btrfs_check_delayed_seq(struct btrfs_fs_info *fs_info, u64 seq);
|
||||
|
||||
/*
|
||||
* helper functions to cast a node into its container
|
||||
|
@ -33,8 +33,6 @@ static void btrfs_dev_replace_update_device_in_mapping_tree(
|
||||
struct btrfs_device *srcdev,
|
||||
struct btrfs_device *tgtdev);
|
||||
static int btrfs_dev_replace_kthread(void *data);
|
||||
static int btrfs_dev_replace_continue_on_mount(struct btrfs_fs_info *fs_info);
|
||||
|
||||
|
||||
int btrfs_init_dev_replace(struct btrfs_fs_info *fs_info)
|
||||
{
|
||||
@ -178,6 +176,105 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize a new device for device replace target from a given source dev
|
||||
* and path.
|
||||
*
|
||||
* Return 0 and new device in @device_out, otherwise return < 0
|
||||
*/
|
||||
static int btrfs_init_dev_replace_tgtdev(struct btrfs_fs_info *fs_info,
|
||||
const char *device_path,
|
||||
struct btrfs_device *srcdev,
|
||||
struct btrfs_device **device_out)
|
||||
{
|
||||
struct btrfs_device *device;
|
||||
struct block_device *bdev;
|
||||
struct list_head *devices;
|
||||
struct rcu_string *name;
|
||||
u64 devid = BTRFS_DEV_REPLACE_DEVID;
|
||||
int ret = 0;
|
||||
|
||||
*device_out = NULL;
|
||||
if (fs_info->fs_devices->seeding) {
|
||||
btrfs_err(fs_info, "the filesystem is a seed filesystem!");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
bdev = blkdev_get_by_path(device_path, FMODE_WRITE | FMODE_EXCL,
|
||||
fs_info->bdev_holder);
|
||||
if (IS_ERR(bdev)) {
|
||||
btrfs_err(fs_info, "target device %s is invalid!", device_path);
|
||||
return PTR_ERR(bdev);
|
||||
}
|
||||
|
||||
filemap_write_and_wait(bdev->bd_inode->i_mapping);
|
||||
|
||||
devices = &fs_info->fs_devices->devices;
|
||||
list_for_each_entry(device, devices, dev_list) {
|
||||
if (device->bdev == bdev) {
|
||||
btrfs_err(fs_info,
|
||||
"target device is in the filesystem!");
|
||||
ret = -EEXIST;
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (i_size_read(bdev->bd_inode) <
|
||||
btrfs_device_get_total_bytes(srcdev)) {
|
||||
btrfs_err(fs_info,
|
||||
"target device is smaller than source device!");
|
||||
ret = -EINVAL;
|
||||
goto error;
|
||||
}
|
||||
|
||||
|
||||
device = btrfs_alloc_device(NULL, &devid, NULL);
|
||||
if (IS_ERR(device)) {
|
||||
ret = PTR_ERR(device);
|
||||
goto error;
|
||||
}
|
||||
|
||||
name = rcu_string_strdup(device_path, GFP_KERNEL);
|
||||
if (!name) {
|
||||
btrfs_free_device(device);
|
||||
ret = -ENOMEM;
|
||||
goto error;
|
||||
}
|
||||
rcu_assign_pointer(device->name, name);
|
||||
|
||||
mutex_lock(&fs_info->fs_devices->device_list_mutex);
|
||||
set_bit(BTRFS_DEV_STATE_WRITEABLE, &device->dev_state);
|
||||
device->generation = 0;
|
||||
device->io_width = fs_info->sectorsize;
|
||||
device->io_align = fs_info->sectorsize;
|
||||
device->sector_size = fs_info->sectorsize;
|
||||
device->total_bytes = btrfs_device_get_total_bytes(srcdev);
|
||||
device->disk_total_bytes = btrfs_device_get_disk_total_bytes(srcdev);
|
||||
device->bytes_used = btrfs_device_get_bytes_used(srcdev);
|
||||
device->commit_total_bytes = srcdev->commit_total_bytes;
|
||||
device->commit_bytes_used = device->bytes_used;
|
||||
device->fs_info = fs_info;
|
||||
device->bdev = bdev;
|
||||
set_bit(BTRFS_DEV_STATE_IN_FS_METADATA, &device->dev_state);
|
||||
set_bit(BTRFS_DEV_STATE_REPLACE_TGT, &device->dev_state);
|
||||
device->mode = FMODE_EXCL;
|
||||
device->dev_stats_valid = 1;
|
||||
set_blocksize(device->bdev, BTRFS_BDEV_BLOCKSIZE);
|
||||
device->fs_devices = fs_info->fs_devices;
|
||||
list_add(&device->dev_list, &fs_info->fs_devices->devices);
|
||||
fs_info->fs_devices->num_devices++;
|
||||
fs_info->fs_devices->open_devices++;
|
||||
mutex_unlock(&fs_info->fs_devices->device_list_mutex);
|
||||
|
||||
*device_out = device;
|
||||
return 0;
|
||||
|
||||
error:
|
||||
blkdev_put(bdev, FMODE_EXCL);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* called from commit_transaction. Writes changed device replace state to
|
||||
* disk.
|
||||
@ -317,18 +414,13 @@ int btrfs_dev_replace_start(struct btrfs_fs_info *fs_info,
|
||||
struct btrfs_device *tgt_device = NULL;
|
||||
struct btrfs_device *src_device = NULL;
|
||||
|
||||
/* the disk copy procedure reuses the scrub code */
|
||||
mutex_lock(&fs_info->volume_mutex);
|
||||
ret = btrfs_find_device_by_devspec(fs_info, srcdevid,
|
||||
srcdev_name, &src_device);
|
||||
if (ret) {
|
||||
mutex_unlock(&fs_info->volume_mutex);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = btrfs_init_dev_replace_tgtdev(fs_info, tgtdev_name,
|
||||
src_device, &tgt_device);
|
||||
mutex_unlock(&fs_info->volume_mutex);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
@ -360,7 +452,6 @@ int btrfs_dev_replace_start(struct btrfs_fs_info *fs_info,
|
||||
dev_replace->cont_reading_from_srcdev_mode = read_src;
|
||||
WARN_ON(!src_device);
|
||||
dev_replace->srcdev = src_device;
|
||||
WARN_ON(!tgt_device);
|
||||
dev_replace->tgtdev = tgt_device;
|
||||
|
||||
btrfs_info_in_rcu(fs_info,
|
||||
@ -503,7 +594,7 @@ static int btrfs_dev_replace_finishing(struct btrfs_fs_info *fs_info,
|
||||
* flush all outstanding I/O and inode extent mappings before the
|
||||
* copy operation is declared as being finished
|
||||
*/
|
||||
ret = btrfs_start_delalloc_roots(fs_info, 0, -1);
|
||||
ret = btrfs_start_delalloc_roots(fs_info, -1);
|
||||
if (ret) {
|
||||
mutex_unlock(&dev_replace->lock_finishing_cancel_unmount);
|
||||
return ret;
|
||||
@ -518,7 +609,6 @@ static int btrfs_dev_replace_finishing(struct btrfs_fs_info *fs_info,
|
||||
ret = btrfs_commit_transaction(trans);
|
||||
WARN_ON(ret);
|
||||
|
||||
mutex_lock(&uuid_mutex);
|
||||
/* keep away write_all_supers() during the finishing procedure */
|
||||
mutex_lock(&fs_info->fs_devices->device_list_mutex);
|
||||
mutex_lock(&fs_info->chunk_mutex);
|
||||
@ -545,7 +635,6 @@ static int btrfs_dev_replace_finishing(struct btrfs_fs_info *fs_info,
|
||||
btrfs_dev_replace_write_unlock(dev_replace);
|
||||
mutex_unlock(&fs_info->chunk_mutex);
|
||||
mutex_unlock(&fs_info->fs_devices->device_list_mutex);
|
||||
mutex_unlock(&uuid_mutex);
|
||||
btrfs_rm_dev_replace_blocked(fs_info);
|
||||
if (tgt_device)
|
||||
btrfs_destroy_dev_replace_tgtdev(fs_info, tgt_device);
|
||||
@ -596,7 +685,6 @@ static int btrfs_dev_replace_finishing(struct btrfs_fs_info *fs_info,
|
||||
*/
|
||||
mutex_unlock(&fs_info->chunk_mutex);
|
||||
mutex_unlock(&fs_info->fs_devices->device_list_mutex);
|
||||
mutex_unlock(&uuid_mutex);
|
||||
|
||||
/* replace the sysfs entry */
|
||||
btrfs_sysfs_rm_device_link(fs_info->fs_devices, src_device);
|
||||
@ -800,7 +888,17 @@ int btrfs_resume_dev_replace_async(struct btrfs_fs_info *fs_info)
|
||||
}
|
||||
btrfs_dev_replace_write_unlock(dev_replace);
|
||||
|
||||
WARN_ON(test_and_set_bit(BTRFS_FS_EXCL_OP, &fs_info->flags));
|
||||
/*
|
||||
* This could collide with a paused balance, but the exclusive op logic
|
||||
* should never allow both to start and pause. We don't want to allow
|
||||
* dev-replace to start anyway.
|
||||
*/
|
||||
if (test_and_set_bit(BTRFS_FS_EXCL_OP, &fs_info->flags)) {
|
||||
btrfs_info(fs_info,
|
||||
"cannot resume dev-replace, other exclusive operation running");
|
||||
return 0;
|
||||
}
|
||||
|
||||
task = kthread_run(btrfs_dev_replace_kthread, fs_info, "btrfs-devrepl");
|
||||
return PTR_ERR_OR_ZERO(task);
|
||||
}
|
||||
@ -810,6 +908,7 @@ static int btrfs_dev_replace_kthread(void *data)
|
||||
struct btrfs_fs_info *fs_info = data;
|
||||
struct btrfs_dev_replace *dev_replace = &fs_info->dev_replace;
|
||||
u64 progress;
|
||||
int ret;
|
||||
|
||||
progress = btrfs_dev_replace_progress(fs_info);
|
||||
progress = div_u64(progress, 10);
|
||||
@ -820,23 +919,14 @@ static int btrfs_dev_replace_kthread(void *data)
|
||||
btrfs_dev_name(dev_replace->tgtdev),
|
||||
(unsigned int)progress);
|
||||
|
||||
btrfs_dev_replace_continue_on_mount(fs_info);
|
||||
clear_bit(BTRFS_FS_EXCL_OP, &fs_info->flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int btrfs_dev_replace_continue_on_mount(struct btrfs_fs_info *fs_info)
|
||||
{
|
||||
struct btrfs_dev_replace *dev_replace = &fs_info->dev_replace;
|
||||
int ret;
|
||||
|
||||
ret = btrfs_scrub_dev(fs_info, dev_replace->srcdev->devid,
|
||||
dev_replace->committed_cursor_left,
|
||||
btrfs_device_get_total_bytes(dev_replace->srcdev),
|
||||
&dev_replace->scrub_progress, 0, 1);
|
||||
ret = btrfs_dev_replace_finishing(fs_info, ret);
|
||||
WARN_ON(ret);
|
||||
|
||||
clear_bit(BTRFS_FS_EXCL_OP, &fs_info->flags);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -916,9 +1006,9 @@ void btrfs_dev_replace_clear_lock_blocking(
|
||||
ASSERT(atomic_read(&dev_replace->read_locks) > 0);
|
||||
ASSERT(atomic_read(&dev_replace->blocking_readers) > 0);
|
||||
read_lock(&dev_replace->lock);
|
||||
if (atomic_dec_and_test(&dev_replace->blocking_readers) &&
|
||||
waitqueue_active(&dev_replace->read_lock_wq))
|
||||
wake_up(&dev_replace->read_lock_wq);
|
||||
/* Barrier implied by atomic_dec_and_test */
|
||||
if (atomic_dec_and_test(&dev_replace->blocking_readers))
|
||||
cond_wake_up_nomb(&dev_replace->read_lock_wq);
|
||||
}
|
||||
|
||||
void btrfs_bio_counter_inc_noblocked(struct btrfs_fs_info *fs_info)
|
||||
@ -929,9 +1019,7 @@ void btrfs_bio_counter_inc_noblocked(struct btrfs_fs_info *fs_info)
|
||||
void btrfs_bio_counter_sub(struct btrfs_fs_info *fs_info, s64 amount)
|
||||
{
|
||||
percpu_counter_sub(&fs_info->bio_counter, amount);
|
||||
|
||||
if (waitqueue_active(&fs_info->replace_wait))
|
||||
wake_up(&fs_info->replace_wait);
|
||||
cond_wake_up_nomb(&fs_info->replace_wait);
|
||||
}
|
||||
|
||||
void btrfs_bio_counter_inc_blocked(struct btrfs_fs_info *fs_info)
|
||||
|
@ -55,7 +55,6 @@
|
||||
static const struct extent_io_ops btree_extent_io_ops;
|
||||
static void end_workqueue_fn(struct btrfs_work *work);
|
||||
static void free_fs_root(struct btrfs_root *root);
|
||||
static int btrfs_check_super_valid(struct btrfs_fs_info *fs_info);
|
||||
static void btrfs_destroy_ordered_extents(struct btrfs_root *root);
|
||||
static int btrfs_destroy_delayed_refs(struct btrfs_transaction *trans,
|
||||
struct btrfs_fs_info *fs_info);
|
||||
@ -416,7 +415,7 @@ static int btrfs_check_super_csum(struct btrfs_fs_info *fs_info,
|
||||
|
||||
static int verify_level_key(struct btrfs_fs_info *fs_info,
|
||||
struct extent_buffer *eb, int level,
|
||||
struct btrfs_key *first_key)
|
||||
struct btrfs_key *first_key, u64 parent_transid)
|
||||
{
|
||||
int found_level;
|
||||
struct btrfs_key found_key;
|
||||
@ -454,10 +453,11 @@ static int verify_level_key(struct btrfs_fs_info *fs_info,
|
||||
if (ret) {
|
||||
WARN_ON(1);
|
||||
btrfs_err(fs_info,
|
||||
"tree first key mismatch detected, bytenr=%llu key expected=(%llu, %u, %llu) has=(%llu, %u, %llu)",
|
||||
eb->start, first_key->objectid, first_key->type,
|
||||
first_key->offset, found_key.objectid,
|
||||
found_key.type, found_key.offset);
|
||||
"tree first key mismatch detected, bytenr=%llu parent_transid=%llu key expected=(%llu,%u,%llu) has=(%llu,%u,%llu)",
|
||||
eb->start, parent_transid, first_key->objectid,
|
||||
first_key->type, first_key->offset,
|
||||
found_key.objectid, found_key.type,
|
||||
found_key.offset);
|
||||
}
|
||||
#endif
|
||||
return ret;
|
||||
@ -493,7 +493,7 @@ static int btree_read_extent_buffer_pages(struct btrfs_fs_info *fs_info,
|
||||
parent_transid, 0))
|
||||
ret = -EIO;
|
||||
else if (verify_level_key(fs_info, eb, level,
|
||||
first_key))
|
||||
first_key, parent_transid))
|
||||
ret = -EUCLEAN;
|
||||
else
|
||||
break;
|
||||
@ -1185,7 +1185,6 @@ static void __setup_root(struct btrfs_root *root, struct btrfs_fs_info *fs_info,
|
||||
root->inode_tree = RB_ROOT;
|
||||
INIT_RADIX_TREE(&root->delayed_nodes_tree, GFP_ATOMIC);
|
||||
root->block_rsv = NULL;
|
||||
root->orphan_block_rsv = NULL;
|
||||
|
||||
INIT_LIST_HEAD(&root->dirty_list);
|
||||
INIT_LIST_HEAD(&root->root_list);
|
||||
@ -1195,7 +1194,6 @@ static void __setup_root(struct btrfs_root *root, struct btrfs_fs_info *fs_info,
|
||||
INIT_LIST_HEAD(&root->ordered_root);
|
||||
INIT_LIST_HEAD(&root->logged_list[0]);
|
||||
INIT_LIST_HEAD(&root->logged_list[1]);
|
||||
spin_lock_init(&root->orphan_lock);
|
||||
spin_lock_init(&root->inode_lock);
|
||||
spin_lock_init(&root->delalloc_lock);
|
||||
spin_lock_init(&root->ordered_extent_lock);
|
||||
@ -1216,7 +1214,6 @@ static void __setup_root(struct btrfs_root *root, struct btrfs_fs_info *fs_info,
|
||||
atomic_set(&root->log_commit[1], 0);
|
||||
atomic_set(&root->log_writers, 0);
|
||||
atomic_set(&root->log_batch, 0);
|
||||
atomic_set(&root->orphan_inodes, 0);
|
||||
refcount_set(&root->refs, 1);
|
||||
atomic_set(&root->will_be_snapshotted, 0);
|
||||
root->log_transid = 0;
|
||||
@ -2164,7 +2161,6 @@ static void btrfs_init_balance(struct btrfs_fs_info *fs_info)
|
||||
{
|
||||
spin_lock_init(&fs_info->balance_lock);
|
||||
mutex_init(&fs_info->balance_mutex);
|
||||
atomic_set(&fs_info->balance_running, 0);
|
||||
atomic_set(&fs_info->balance_pause_req, 0);
|
||||
atomic_set(&fs_info->balance_cancel_req, 0);
|
||||
fs_info->balance_ctl = NULL;
|
||||
@ -2442,6 +2438,211 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Real super block validation
|
||||
* NOTE: super csum type and incompat features will not be checked here.
|
||||
*
|
||||
* @sb: super block to check
|
||||
* @mirror_num: the super block number to check its bytenr:
|
||||
* 0 the primary (1st) sb
|
||||
* 1, 2 2nd and 3rd backup copy
|
||||
* -1 skip bytenr check
|
||||
*/
|
||||
static int validate_super(struct btrfs_fs_info *fs_info,
|
||||
struct btrfs_super_block *sb, int mirror_num)
|
||||
{
|
||||
u64 nodesize = btrfs_super_nodesize(sb);
|
||||
u64 sectorsize = btrfs_super_sectorsize(sb);
|
||||
int ret = 0;
|
||||
|
||||
if (btrfs_super_magic(sb) != BTRFS_MAGIC) {
|
||||
btrfs_err(fs_info, "no valid FS found");
|
||||
ret = -EINVAL;
|
||||
}
|
||||
if (btrfs_super_flags(sb) & ~BTRFS_SUPER_FLAG_SUPP) {
|
||||
btrfs_err(fs_info, "unrecognized or unsupported super flag: %llu",
|
||||
btrfs_super_flags(sb) & ~BTRFS_SUPER_FLAG_SUPP);
|
||||
ret = -EINVAL;
|
||||
}
|
||||
if (btrfs_super_root_level(sb) >= BTRFS_MAX_LEVEL) {
|
||||
btrfs_err(fs_info, "tree_root level too big: %d >= %d",
|
||||
btrfs_super_root_level(sb), BTRFS_MAX_LEVEL);
|
||||
ret = -EINVAL;
|
||||
}
|
||||
if (btrfs_super_chunk_root_level(sb) >= BTRFS_MAX_LEVEL) {
|
||||
btrfs_err(fs_info, "chunk_root level too big: %d >= %d",
|
||||
btrfs_super_chunk_root_level(sb), BTRFS_MAX_LEVEL);
|
||||
ret = -EINVAL;
|
||||
}
|
||||
if (btrfs_super_log_root_level(sb) >= BTRFS_MAX_LEVEL) {
|
||||
btrfs_err(fs_info, "log_root level too big: %d >= %d",
|
||||
btrfs_super_log_root_level(sb), BTRFS_MAX_LEVEL);
|
||||
ret = -EINVAL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check sectorsize and nodesize first, other check will need it.
|
||||
* Check all possible sectorsize(4K, 8K, 16K, 32K, 64K) here.
|
||||
*/
|
||||
if (!is_power_of_2(sectorsize) || sectorsize < 4096 ||
|
||||
sectorsize > BTRFS_MAX_METADATA_BLOCKSIZE) {
|
||||
btrfs_err(fs_info, "invalid sectorsize %llu", sectorsize);
|
||||
ret = -EINVAL;
|
||||
}
|
||||
/* Only PAGE SIZE is supported yet */
|
||||
if (sectorsize != PAGE_SIZE) {
|
||||
btrfs_err(fs_info,
|
||||
"sectorsize %llu not supported yet, only support %lu",
|
||||
sectorsize, PAGE_SIZE);
|
||||
ret = -EINVAL;
|
||||
}
|
||||
if (!is_power_of_2(nodesize) || nodesize < sectorsize ||
|
||||
nodesize > BTRFS_MAX_METADATA_BLOCKSIZE) {
|
||||
btrfs_err(fs_info, "invalid nodesize %llu", nodesize);
|
||||
ret = -EINVAL;
|
||||
}
|
||||
if (nodesize != le32_to_cpu(sb->__unused_leafsize)) {
|
||||
btrfs_err(fs_info, "invalid leafsize %u, should be %llu",
|
||||
le32_to_cpu(sb->__unused_leafsize), nodesize);
|
||||
ret = -EINVAL;
|
||||
}
|
||||
|
||||
/* Root alignment check */
|
||||
if (!IS_ALIGNED(btrfs_super_root(sb), sectorsize)) {
|
||||
btrfs_warn(fs_info, "tree_root block unaligned: %llu",
|
||||
btrfs_super_root(sb));
|
||||
ret = -EINVAL;
|
||||
}
|
||||
if (!IS_ALIGNED(btrfs_super_chunk_root(sb), sectorsize)) {
|
||||
btrfs_warn(fs_info, "chunk_root block unaligned: %llu",
|
||||
btrfs_super_chunk_root(sb));
|
||||
ret = -EINVAL;
|
||||
}
|
||||
if (!IS_ALIGNED(btrfs_super_log_root(sb), sectorsize)) {
|
||||
btrfs_warn(fs_info, "log_root block unaligned: %llu",
|
||||
btrfs_super_log_root(sb));
|
||||
ret = -EINVAL;
|
||||
}
|
||||
|
||||
if (memcmp(fs_info->fsid, sb->dev_item.fsid, BTRFS_FSID_SIZE) != 0) {
|
||||
btrfs_err(fs_info,
|
||||
"dev_item UUID does not match fsid: %pU != %pU",
|
||||
fs_info->fsid, sb->dev_item.fsid);
|
||||
ret = -EINVAL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Hint to catch really bogus numbers, bitflips or so, more exact checks are
|
||||
* done later
|
||||
*/
|
||||
if (btrfs_super_bytes_used(sb) < 6 * btrfs_super_nodesize(sb)) {
|
||||
btrfs_err(fs_info, "bytes_used is too small %llu",
|
||||
btrfs_super_bytes_used(sb));
|
||||
ret = -EINVAL;
|
||||
}
|
||||
if (!is_power_of_2(btrfs_super_stripesize(sb))) {
|
||||
btrfs_err(fs_info, "invalid stripesize %u",
|
||||
btrfs_super_stripesize(sb));
|
||||
ret = -EINVAL;
|
||||
}
|
||||
if (btrfs_super_num_devices(sb) > (1UL << 31))
|
||||
btrfs_warn(fs_info, "suspicious number of devices: %llu",
|
||||
btrfs_super_num_devices(sb));
|
||||
if (btrfs_super_num_devices(sb) == 0) {
|
||||
btrfs_err(fs_info, "number of devices is 0");
|
||||
ret = -EINVAL;
|
||||
}
|
||||
|
||||
if (mirror_num >= 0 &&
|
||||
btrfs_super_bytenr(sb) != btrfs_sb_offset(mirror_num)) {
|
||||
btrfs_err(fs_info, "super offset mismatch %llu != %u",
|
||||
btrfs_super_bytenr(sb), BTRFS_SUPER_INFO_OFFSET);
|
||||
ret = -EINVAL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Obvious sys_chunk_array corruptions, it must hold at least one key
|
||||
* and one chunk
|
||||
*/
|
||||
if (btrfs_super_sys_array_size(sb) > BTRFS_SYSTEM_CHUNK_ARRAY_SIZE) {
|
||||
btrfs_err(fs_info, "system chunk array too big %u > %u",
|
||||
btrfs_super_sys_array_size(sb),
|
||||
BTRFS_SYSTEM_CHUNK_ARRAY_SIZE);
|
||||
ret = -EINVAL;
|
||||
}
|
||||
if (btrfs_super_sys_array_size(sb) < sizeof(struct btrfs_disk_key)
|
||||
+ sizeof(struct btrfs_chunk)) {
|
||||
btrfs_err(fs_info, "system chunk array too small %u < %zu",
|
||||
btrfs_super_sys_array_size(sb),
|
||||
sizeof(struct btrfs_disk_key)
|
||||
+ sizeof(struct btrfs_chunk));
|
||||
ret = -EINVAL;
|
||||
}
|
||||
|
||||
/*
|
||||
* The generation is a global counter, we'll trust it more than the others
|
||||
* but it's still possible that it's the one that's wrong.
|
||||
*/
|
||||
if (btrfs_super_generation(sb) < btrfs_super_chunk_root_generation(sb))
|
||||
btrfs_warn(fs_info,
|
||||
"suspicious: generation < chunk_root_generation: %llu < %llu",
|
||||
btrfs_super_generation(sb),
|
||||
btrfs_super_chunk_root_generation(sb));
|
||||
if (btrfs_super_generation(sb) < btrfs_super_cache_generation(sb)
|
||||
&& btrfs_super_cache_generation(sb) != (u64)-1)
|
||||
btrfs_warn(fs_info,
|
||||
"suspicious: generation < cache_generation: %llu < %llu",
|
||||
btrfs_super_generation(sb),
|
||||
btrfs_super_cache_generation(sb));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Validation of super block at mount time.
|
||||
* Some checks already done early at mount time, like csum type and incompat
|
||||
* flags will be skipped.
|
||||
*/
|
||||
static int btrfs_validate_mount_super(struct btrfs_fs_info *fs_info)
|
||||
{
|
||||
return validate_super(fs_info, fs_info->super_copy, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Validation of super block at write time.
|
||||
* Some checks like bytenr check will be skipped as their values will be
|
||||
* overwritten soon.
|
||||
* Extra checks like csum type and incompat flags will be done here.
|
||||
*/
|
||||
static int btrfs_validate_write_super(struct btrfs_fs_info *fs_info,
|
||||
struct btrfs_super_block *sb)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = validate_super(fs_info, sb, -1);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
if (btrfs_super_csum_type(sb) != BTRFS_CSUM_TYPE_CRC32) {
|
||||
ret = -EUCLEAN;
|
||||
btrfs_err(fs_info, "invalid csum type, has %u want %u",
|
||||
btrfs_super_csum_type(sb), BTRFS_CSUM_TYPE_CRC32);
|
||||
goto out;
|
||||
}
|
||||
if (btrfs_super_incompat_flags(sb) & ~BTRFS_FEATURE_INCOMPAT_SUPP) {
|
||||
ret = -EUCLEAN;
|
||||
btrfs_err(fs_info,
|
||||
"invalid incompat flags, has 0x%llx valid mask 0x%llx",
|
||||
btrfs_super_incompat_flags(sb),
|
||||
(unsigned long long)BTRFS_FEATURE_INCOMPAT_SUPP);
|
||||
goto out;
|
||||
}
|
||||
out:
|
||||
if (ret < 0)
|
||||
btrfs_err(fs_info,
|
||||
"super block corruption detected before writing it to disk");
|
||||
return ret;
|
||||
}
|
||||
|
||||
int open_ctree(struct super_block *sb,
|
||||
struct btrfs_fs_devices *fs_devices,
|
||||
char *options)
|
||||
@ -2601,7 +2802,6 @@ int open_ctree(struct super_block *sb,
|
||||
mutex_init(&fs_info->chunk_mutex);
|
||||
mutex_init(&fs_info->transaction_kthread_mutex);
|
||||
mutex_init(&fs_info->cleaner_mutex);
|
||||
mutex_init(&fs_info->volume_mutex);
|
||||
mutex_init(&fs_info->ro_block_group_mutex);
|
||||
init_rwsem(&fs_info->commit_root_sem);
|
||||
init_rwsem(&fs_info->cleanup_work_sem);
|
||||
@ -2668,7 +2868,7 @@ int open_ctree(struct super_block *sb,
|
||||
|
||||
memcpy(fs_info->fsid, fs_info->super_copy->fsid, BTRFS_FSID_SIZE);
|
||||
|
||||
ret = btrfs_check_super_valid(fs_info);
|
||||
ret = btrfs_validate_mount_super(fs_info);
|
||||
if (ret) {
|
||||
btrfs_err(fs_info, "superblock contains fatal errors");
|
||||
err = -EINVAL;
|
||||
@ -3523,7 +3723,7 @@ int btrfs_get_num_tolerated_disk_barrier_failures(u64 flags)
|
||||
for (raid_type = 0; raid_type < BTRFS_NR_RAID_TYPES; raid_type++) {
|
||||
if (raid_type == BTRFS_RAID_SINGLE)
|
||||
continue;
|
||||
if (!(flags & btrfs_raid_group[raid_type]))
|
||||
if (!(flags & btrfs_raid_array[raid_type].bg_flag))
|
||||
continue;
|
||||
min_tolerated = min(min_tolerated,
|
||||
btrfs_raid_array[raid_type].
|
||||
@ -3603,6 +3803,14 @@ int write_all_supers(struct btrfs_fs_info *fs_info, int max_mirrors)
|
||||
flags = btrfs_super_flags(sb);
|
||||
btrfs_set_super_flags(sb, flags | BTRFS_HEADER_FLAG_WRITTEN);
|
||||
|
||||
ret = btrfs_validate_write_super(fs_info, sb);
|
||||
if (ret < 0) {
|
||||
mutex_unlock(&fs_info->fs_devices->device_list_mutex);
|
||||
btrfs_handle_fs_error(fs_info, -EUCLEAN,
|
||||
"unexpected superblock corruption detected");
|
||||
return -EUCLEAN;
|
||||
}
|
||||
|
||||
ret = write_dev_supers(dev, sb, max_mirrors);
|
||||
if (ret)
|
||||
total_errors++;
|
||||
@ -3674,8 +3882,6 @@ static void free_fs_root(struct btrfs_root *root)
|
||||
{
|
||||
iput(root->ino_cache_inode);
|
||||
WARN_ON(!RB_EMPTY_ROOT(&root->inode_tree));
|
||||
btrfs_free_block_rsv(root->fs_info, root->orphan_block_rsv);
|
||||
root->orphan_block_rsv = NULL;
|
||||
if (root->anon_dev)
|
||||
free_anon_bdev(root->anon_dev);
|
||||
if (root->subv_writers)
|
||||
@ -3766,7 +3972,6 @@ int btrfs_commit_super(struct btrfs_fs_info *fs_info)
|
||||
|
||||
void close_ctree(struct btrfs_fs_info *fs_info)
|
||||
{
|
||||
struct btrfs_root *root = fs_info->tree_root;
|
||||
int ret;
|
||||
|
||||
set_bit(BTRFS_FS_CLOSING_START, &fs_info->flags);
|
||||
@ -3862,9 +4067,6 @@ void close_ctree(struct btrfs_fs_info *fs_info)
|
||||
btrfs_free_stripe_hash_table(fs_info);
|
||||
btrfs_free_ref_cache(fs_info);
|
||||
|
||||
__btrfs_free_block_rsv(root->orphan_block_rsv);
|
||||
root->orphan_block_rsv = NULL;
|
||||
|
||||
while (!list_empty(&fs_info->pinned_chunks)) {
|
||||
struct extent_map *em;
|
||||
|
||||
@ -3975,155 +4177,6 @@ int btrfs_read_buffer(struct extent_buffer *buf, u64 parent_transid, int level,
|
||||
level, first_key);
|
||||
}
|
||||
|
||||
static int btrfs_check_super_valid(struct btrfs_fs_info *fs_info)
|
||||
{
|
||||
struct btrfs_super_block *sb = fs_info->super_copy;
|
||||
u64 nodesize = btrfs_super_nodesize(sb);
|
||||
u64 sectorsize = btrfs_super_sectorsize(sb);
|
||||
int ret = 0;
|
||||
|
||||
if (btrfs_super_magic(sb) != BTRFS_MAGIC) {
|
||||
btrfs_err(fs_info, "no valid FS found");
|
||||
ret = -EINVAL;
|
||||
}
|
||||
if (btrfs_super_flags(sb) & ~BTRFS_SUPER_FLAG_SUPP) {
|
||||
btrfs_err(fs_info, "unrecognized or unsupported super flag: %llu",
|
||||
btrfs_super_flags(sb) & ~BTRFS_SUPER_FLAG_SUPP);
|
||||
ret = -EINVAL;
|
||||
}
|
||||
if (btrfs_super_root_level(sb) >= BTRFS_MAX_LEVEL) {
|
||||
btrfs_err(fs_info, "tree_root level too big: %d >= %d",
|
||||
btrfs_super_root_level(sb), BTRFS_MAX_LEVEL);
|
||||
ret = -EINVAL;
|
||||
}
|
||||
if (btrfs_super_chunk_root_level(sb) >= BTRFS_MAX_LEVEL) {
|
||||
btrfs_err(fs_info, "chunk_root level too big: %d >= %d",
|
||||
btrfs_super_chunk_root_level(sb), BTRFS_MAX_LEVEL);
|
||||
ret = -EINVAL;
|
||||
}
|
||||
if (btrfs_super_log_root_level(sb) >= BTRFS_MAX_LEVEL) {
|
||||
btrfs_err(fs_info, "log_root level too big: %d >= %d",
|
||||
btrfs_super_log_root_level(sb), BTRFS_MAX_LEVEL);
|
||||
ret = -EINVAL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check sectorsize and nodesize first, other check will need it.
|
||||
* Check all possible sectorsize(4K, 8K, 16K, 32K, 64K) here.
|
||||
*/
|
||||
if (!is_power_of_2(sectorsize) || sectorsize < 4096 ||
|
||||
sectorsize > BTRFS_MAX_METADATA_BLOCKSIZE) {
|
||||
btrfs_err(fs_info, "invalid sectorsize %llu", sectorsize);
|
||||
ret = -EINVAL;
|
||||
}
|
||||
/* Only PAGE SIZE is supported yet */
|
||||
if (sectorsize != PAGE_SIZE) {
|
||||
btrfs_err(fs_info,
|
||||
"sectorsize %llu not supported yet, only support %lu",
|
||||
sectorsize, PAGE_SIZE);
|
||||
ret = -EINVAL;
|
||||
}
|
||||
if (!is_power_of_2(nodesize) || nodesize < sectorsize ||
|
||||
nodesize > BTRFS_MAX_METADATA_BLOCKSIZE) {
|
||||
btrfs_err(fs_info, "invalid nodesize %llu", nodesize);
|
||||
ret = -EINVAL;
|
||||
}
|
||||
if (nodesize != le32_to_cpu(sb->__unused_leafsize)) {
|
||||
btrfs_err(fs_info, "invalid leafsize %u, should be %llu",
|
||||
le32_to_cpu(sb->__unused_leafsize), nodesize);
|
||||
ret = -EINVAL;
|
||||
}
|
||||
|
||||
/* Root alignment check */
|
||||
if (!IS_ALIGNED(btrfs_super_root(sb), sectorsize)) {
|
||||
btrfs_warn(fs_info, "tree_root block unaligned: %llu",
|
||||
btrfs_super_root(sb));
|
||||
ret = -EINVAL;
|
||||
}
|
||||
if (!IS_ALIGNED(btrfs_super_chunk_root(sb), sectorsize)) {
|
||||
btrfs_warn(fs_info, "chunk_root block unaligned: %llu",
|
||||
btrfs_super_chunk_root(sb));
|
||||
ret = -EINVAL;
|
||||
}
|
||||
if (!IS_ALIGNED(btrfs_super_log_root(sb), sectorsize)) {
|
||||
btrfs_warn(fs_info, "log_root block unaligned: %llu",
|
||||
btrfs_super_log_root(sb));
|
||||
ret = -EINVAL;
|
||||
}
|
||||
|
||||
if (memcmp(fs_info->fsid, sb->dev_item.fsid, BTRFS_FSID_SIZE) != 0) {
|
||||
btrfs_err(fs_info,
|
||||
"dev_item UUID does not match fsid: %pU != %pU",
|
||||
fs_info->fsid, sb->dev_item.fsid);
|
||||
ret = -EINVAL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Hint to catch really bogus numbers, bitflips or so, more exact checks are
|
||||
* done later
|
||||
*/
|
||||
if (btrfs_super_bytes_used(sb) < 6 * btrfs_super_nodesize(sb)) {
|
||||
btrfs_err(fs_info, "bytes_used is too small %llu",
|
||||
btrfs_super_bytes_used(sb));
|
||||
ret = -EINVAL;
|
||||
}
|
||||
if (!is_power_of_2(btrfs_super_stripesize(sb))) {
|
||||
btrfs_err(fs_info, "invalid stripesize %u",
|
||||
btrfs_super_stripesize(sb));
|
||||
ret = -EINVAL;
|
||||
}
|
||||
if (btrfs_super_num_devices(sb) > (1UL << 31))
|
||||
btrfs_warn(fs_info, "suspicious number of devices: %llu",
|
||||
btrfs_super_num_devices(sb));
|
||||
if (btrfs_super_num_devices(sb) == 0) {
|
||||
btrfs_err(fs_info, "number of devices is 0");
|
||||
ret = -EINVAL;
|
||||
}
|
||||
|
||||
if (btrfs_super_bytenr(sb) != BTRFS_SUPER_INFO_OFFSET) {
|
||||
btrfs_err(fs_info, "super offset mismatch %llu != %u",
|
||||
btrfs_super_bytenr(sb), BTRFS_SUPER_INFO_OFFSET);
|
||||
ret = -EINVAL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Obvious sys_chunk_array corruptions, it must hold at least one key
|
||||
* and one chunk
|
||||
*/
|
||||
if (btrfs_super_sys_array_size(sb) > BTRFS_SYSTEM_CHUNK_ARRAY_SIZE) {
|
||||
btrfs_err(fs_info, "system chunk array too big %u > %u",
|
||||
btrfs_super_sys_array_size(sb),
|
||||
BTRFS_SYSTEM_CHUNK_ARRAY_SIZE);
|
||||
ret = -EINVAL;
|
||||
}
|
||||
if (btrfs_super_sys_array_size(sb) < sizeof(struct btrfs_disk_key)
|
||||
+ sizeof(struct btrfs_chunk)) {
|
||||
btrfs_err(fs_info, "system chunk array too small %u < %zu",
|
||||
btrfs_super_sys_array_size(sb),
|
||||
sizeof(struct btrfs_disk_key)
|
||||
+ sizeof(struct btrfs_chunk));
|
||||
ret = -EINVAL;
|
||||
}
|
||||
|
||||
/*
|
||||
* The generation is a global counter, we'll trust it more than the others
|
||||
* but it's still possible that it's the one that's wrong.
|
||||
*/
|
||||
if (btrfs_super_generation(sb) < btrfs_super_chunk_root_generation(sb))
|
||||
btrfs_warn(fs_info,
|
||||
"suspicious: generation < chunk_root_generation: %llu < %llu",
|
||||
btrfs_super_generation(sb),
|
||||
btrfs_super_chunk_root_generation(sb));
|
||||
if (btrfs_super_generation(sb) < btrfs_super_cache_generation(sb)
|
||||
&& btrfs_super_cache_generation(sb) != (u64)-1)
|
||||
btrfs_warn(fs_info,
|
||||
"suspicious: generation < cache_generation: %llu < %llu",
|
||||
btrfs_super_generation(sb),
|
||||
btrfs_super_cache_generation(sb));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void btrfs_error_commit_super(struct btrfs_fs_info *fs_info)
|
||||
{
|
||||
/* cleanup FS via transaction */
|
||||
|
@ -66,10 +66,8 @@ static int alloc_reserved_file_extent(struct btrfs_trans_handle *trans,
|
||||
u64 flags, u64 owner, u64 offset,
|
||||
struct btrfs_key *ins, int ref_mod);
|
||||
static int alloc_reserved_tree_block(struct btrfs_trans_handle *trans,
|
||||
struct btrfs_fs_info *fs_info,
|
||||
u64 parent, u64 root_objectid,
|
||||
u64 flags, struct btrfs_disk_key *key,
|
||||
int level, struct btrfs_key *ins);
|
||||
struct btrfs_delayed_ref_node *node,
|
||||
struct btrfs_delayed_extent_op *extent_op);
|
||||
static int do_chunk_alloc(struct btrfs_trans_handle *trans,
|
||||
struct btrfs_fs_info *fs_info, u64 flags,
|
||||
int force);
|
||||
@ -256,7 +254,7 @@ static int exclude_super_stripes(struct btrfs_fs_info *fs_info,
|
||||
for (i = 0; i < BTRFS_SUPER_MIRROR_MAX; i++) {
|
||||
bytenr = btrfs_sb_offset(i);
|
||||
ret = btrfs_rmap_block(fs_info, cache->key.objectid,
|
||||
bytenr, 0, &logical, &nr, &stripe_len);
|
||||
bytenr, &logical, &nr, &stripe_len);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
@ -343,8 +341,9 @@ static void fragment_free_space(struct btrfs_block_group_cache *block_group)
|
||||
* since their free space will be released as soon as the transaction commits.
|
||||
*/
|
||||
u64 add_new_free_space(struct btrfs_block_group_cache *block_group,
|
||||
struct btrfs_fs_info *info, u64 start, u64 end)
|
||||
u64 start, u64 end)
|
||||
{
|
||||
struct btrfs_fs_info *info = block_group->fs_info;
|
||||
u64 extent_start, extent_end, size, total_added = 0;
|
||||
int ret;
|
||||
|
||||
@ -489,8 +488,7 @@ next:
|
||||
|
||||
if (key.type == BTRFS_EXTENT_ITEM_KEY ||
|
||||
key.type == BTRFS_METADATA_ITEM_KEY) {
|
||||
total_found += add_new_free_space(block_group,
|
||||
fs_info, last,
|
||||
total_found += add_new_free_space(block_group, last,
|
||||
key.objectid);
|
||||
if (key.type == BTRFS_METADATA_ITEM_KEY)
|
||||
last = key.objectid +
|
||||
@ -508,7 +506,7 @@ next:
|
||||
}
|
||||
ret = 0;
|
||||
|
||||
total_found += add_new_free_space(block_group, fs_info, last,
|
||||
total_found += add_new_free_space(block_group, last,
|
||||
block_group->key.objectid +
|
||||
block_group->key.offset);
|
||||
caching_ctl->progress = (u64)-1;
|
||||
@ -744,12 +742,12 @@ static struct btrfs_space_info *__find_space_info(struct btrfs_fs_info *info,
|
||||
}
|
||||
|
||||
static void add_pinned_bytes(struct btrfs_fs_info *fs_info, s64 num_bytes,
|
||||
u64 owner, u64 root_objectid)
|
||||
bool metadata, u64 root_objectid)
|
||||
{
|
||||
struct btrfs_space_info *space_info;
|
||||
u64 flags;
|
||||
|
||||
if (owner < BTRFS_FIRST_FREE_OBJECTID) {
|
||||
if (metadata) {
|
||||
if (root_objectid == BTRFS_CHUNK_TREE_OBJECTID)
|
||||
flags = BTRFS_BLOCK_GROUP_SYSTEM;
|
||||
else
|
||||
@ -2200,8 +2198,11 @@ int btrfs_inc_extent_ref(struct btrfs_trans_handle *trans,
|
||||
&old_ref_mod, &new_ref_mod);
|
||||
}
|
||||
|
||||
if (ret == 0 && old_ref_mod < 0 && new_ref_mod >= 0)
|
||||
add_pinned_bytes(fs_info, -num_bytes, owner, root_objectid);
|
||||
if (ret == 0 && old_ref_mod < 0 && new_ref_mod >= 0) {
|
||||
bool metadata = owner < BTRFS_FIRST_FREE_OBJECTID;
|
||||
|
||||
add_pinned_bytes(fs_info, -num_bytes, metadata, root_objectid);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
@ -2428,10 +2429,8 @@ static int run_delayed_tree_ref(struct btrfs_trans_handle *trans,
|
||||
{
|
||||
int ret = 0;
|
||||
struct btrfs_delayed_tree_ref *ref;
|
||||
struct btrfs_key ins;
|
||||
u64 parent = 0;
|
||||
u64 ref_root = 0;
|
||||
bool skinny_metadata = btrfs_fs_incompat(fs_info, SKINNY_METADATA);
|
||||
|
||||
ref = btrfs_delayed_node_to_tree_ref(node);
|
||||
trace_run_delayed_tree_ref(fs_info, node, ref, node->action);
|
||||
@ -2440,15 +2439,6 @@ static int run_delayed_tree_ref(struct btrfs_trans_handle *trans,
|
||||
parent = ref->parent;
|
||||
ref_root = ref->root;
|
||||
|
||||
ins.objectid = node->bytenr;
|
||||
if (skinny_metadata) {
|
||||
ins.offset = ref->level;
|
||||
ins.type = BTRFS_METADATA_ITEM_KEY;
|
||||
} else {
|
||||
ins.offset = node->num_bytes;
|
||||
ins.type = BTRFS_EXTENT_ITEM_KEY;
|
||||
}
|
||||
|
||||
if (node->ref_mod != 1) {
|
||||
btrfs_err(fs_info,
|
||||
"btree block(%llu) has %d references rather than 1: action %d ref_root %llu parent %llu",
|
||||
@ -2458,11 +2448,7 @@ static int run_delayed_tree_ref(struct btrfs_trans_handle *trans,
|
||||
}
|
||||
if (node->action == BTRFS_ADD_DELAYED_REF && insert_reserved) {
|
||||
BUG_ON(!extent_op || !extent_op->update_flags);
|
||||
ret = alloc_reserved_tree_block(trans, fs_info,
|
||||
parent, ref_root,
|
||||
extent_op->flags_to_set,
|
||||
&extent_op->key,
|
||||
ref->level, &ins);
|
||||
ret = alloc_reserved_tree_block(trans, node, extent_op);
|
||||
} else if (node->action == BTRFS_ADD_DELAYED_REF) {
|
||||
ret = __btrfs_inc_extent_ref(trans, fs_info, node,
|
||||
parent, ref_root,
|
||||
@ -2594,8 +2580,8 @@ static int cleanup_ref_head(struct btrfs_trans_handle *trans,
|
||||
delayed_refs->num_heads--;
|
||||
rb_erase(&head->href_node, &delayed_refs->href_root);
|
||||
RB_CLEAR_NODE(&head->href_node);
|
||||
spin_unlock(&delayed_refs->lock);
|
||||
spin_unlock(&head->lock);
|
||||
spin_unlock(&delayed_refs->lock);
|
||||
atomic_dec(&delayed_refs->num_entries);
|
||||
|
||||
trace_run_delayed_ref_head(fs_info, head, 0);
|
||||
@ -2700,17 +2686,12 @@ static noinline int __btrfs_run_delayed_refs(struct btrfs_trans_handle *trans,
|
||||
* insert_inline_extent_backref()).
|
||||
*/
|
||||
spin_lock(&locked_ref->lock);
|
||||
btrfs_merge_delayed_refs(trans, fs_info, delayed_refs,
|
||||
locked_ref);
|
||||
btrfs_merge_delayed_refs(trans, delayed_refs, locked_ref);
|
||||
|
||||
/*
|
||||
* locked_ref is the head node, so we have to go one
|
||||
* node back for any delayed ref updates
|
||||
*/
|
||||
ref = select_delayed_ref(locked_ref);
|
||||
|
||||
if (ref && ref->seq &&
|
||||
btrfs_check_delayed_seq(fs_info, delayed_refs, ref->seq)) {
|
||||
btrfs_check_delayed_seq(fs_info, ref->seq)) {
|
||||
spin_unlock(&locked_ref->lock);
|
||||
unselect_delayed_ref_head(delayed_refs, locked_ref);
|
||||
locked_ref = NULL;
|
||||
@ -3291,7 +3272,7 @@ int btrfs_cross_ref_exist(struct btrfs_root *root, u64 objectid, u64 offset,
|
||||
|
||||
path = btrfs_alloc_path();
|
||||
if (!path)
|
||||
return -ENOENT;
|
||||
return -ENOMEM;
|
||||
|
||||
do {
|
||||
ret = check_committed_ref(root, path, objectid,
|
||||
@ -4026,8 +4007,7 @@ static const char *alloc_name(u64 flags)
|
||||
};
|
||||
}
|
||||
|
||||
static int create_space_info(struct btrfs_fs_info *info, u64 flags,
|
||||
struct btrfs_space_info **new)
|
||||
static int create_space_info(struct btrfs_fs_info *info, u64 flags)
|
||||
{
|
||||
|
||||
struct btrfs_space_info *space_info;
|
||||
@ -4065,7 +4045,6 @@ static int create_space_info(struct btrfs_fs_info *info, u64 flags,
|
||||
return ret;
|
||||
}
|
||||
|
||||
*new = space_info;
|
||||
list_add_rcu(&space_info->list, &info->space_info);
|
||||
if (flags & BTRFS_BLOCK_GROUP_DATA)
|
||||
info->data_sinfo = space_info;
|
||||
@ -4122,7 +4101,7 @@ static void set_avail_alloc_bits(struct btrfs_fs_info *fs_info, u64 flags)
|
||||
* returns target flags in extended format or 0 if restripe for this
|
||||
* chunk_type is not in progress
|
||||
*
|
||||
* should be called with either volume_mutex or balance_lock held
|
||||
* should be called with balance_lock held
|
||||
*/
|
||||
static u64 get_restripe_target(struct btrfs_fs_info *fs_info, u64 flags)
|
||||
{
|
||||
@ -4178,7 +4157,7 @@ static u64 btrfs_reduce_alloc_profile(struct btrfs_fs_info *fs_info, u64 flags)
|
||||
/* First, mask out the RAID levels which aren't possible */
|
||||
for (raid_type = 0; raid_type < BTRFS_NR_RAID_TYPES; raid_type++) {
|
||||
if (num_devices >= btrfs_raid_array[raid_type].devs_min)
|
||||
allowed |= btrfs_raid_group[raid_type];
|
||||
allowed |= btrfs_raid_array[raid_type].bg_flag;
|
||||
}
|
||||
allowed &= flags;
|
||||
|
||||
@ -4341,7 +4320,7 @@ commit_trans:
|
||||
need_commit--;
|
||||
|
||||
if (need_commit > 0) {
|
||||
btrfs_start_delalloc_roots(fs_info, 0, -1);
|
||||
btrfs_start_delalloc_roots(fs_info, -1);
|
||||
btrfs_wait_ordered_roots(fs_info, U64_MAX, 0,
|
||||
(u64)-1);
|
||||
}
|
||||
@ -4678,12 +4657,14 @@ again:
|
||||
trans->allocating_chunk = false;
|
||||
|
||||
spin_lock(&space_info->lock);
|
||||
if (ret < 0 && ret != -ENOSPC)
|
||||
goto out;
|
||||
if (ret)
|
||||
space_info->full = 1;
|
||||
else
|
||||
if (ret < 0) {
|
||||
if (ret == -ENOSPC)
|
||||
space_info->full = 1;
|
||||
else
|
||||
goto out;
|
||||
} else {
|
||||
ret = 1;
|
||||
}
|
||||
|
||||
space_info->force_alloc = CHUNK_ALLOC_NO_FORCE;
|
||||
out:
|
||||
@ -4792,7 +4773,7 @@ static void btrfs_writeback_inodes_sb_nr(struct btrfs_fs_info *fs_info,
|
||||
* the filesystem is readonly(all dirty pages are written to
|
||||
* the disk).
|
||||
*/
|
||||
btrfs_start_delalloc_roots(fs_info, 0, nr_items);
|
||||
btrfs_start_delalloc_roots(fs_info, nr_items);
|
||||
if (!current->journal_info)
|
||||
btrfs_wait_ordered_roots(fs_info, nr_items, 0, (u64)-1);
|
||||
}
|
||||
@ -5949,44 +5930,6 @@ void btrfs_trans_release_chunk_metadata(struct btrfs_trans_handle *trans)
|
||||
trans->chunk_bytes_reserved = 0;
|
||||
}
|
||||
|
||||
/* Can only return 0 or -ENOSPC */
|
||||
int btrfs_orphan_reserve_metadata(struct btrfs_trans_handle *trans,
|
||||
struct btrfs_inode *inode)
|
||||
{
|
||||
struct btrfs_fs_info *fs_info = btrfs_sb(inode->vfs_inode.i_sb);
|
||||
struct btrfs_root *root = inode->root;
|
||||
/*
|
||||
* We always use trans->block_rsv here as we will have reserved space
|
||||
* for our orphan when starting the transaction, using get_block_rsv()
|
||||
* here will sometimes make us choose the wrong block rsv as we could be
|
||||
* doing a reloc inode for a non refcounted root.
|
||||
*/
|
||||
struct btrfs_block_rsv *src_rsv = trans->block_rsv;
|
||||
struct btrfs_block_rsv *dst_rsv = root->orphan_block_rsv;
|
||||
|
||||
/*
|
||||
* We need to hold space in order to delete our orphan item once we've
|
||||
* added it, so this takes the reservation so we can release it later
|
||||
* when we are truly done with the orphan item.
|
||||
*/
|
||||
u64 num_bytes = btrfs_calc_trans_metadata_size(fs_info, 1);
|
||||
|
||||
trace_btrfs_space_reservation(fs_info, "orphan", btrfs_ino(inode),
|
||||
num_bytes, 1);
|
||||
return btrfs_block_rsv_migrate(src_rsv, dst_rsv, num_bytes, 1);
|
||||
}
|
||||
|
||||
void btrfs_orphan_release_metadata(struct btrfs_inode *inode)
|
||||
{
|
||||
struct btrfs_fs_info *fs_info = btrfs_sb(inode->vfs_inode.i_sb);
|
||||
struct btrfs_root *root = inode->root;
|
||||
u64 num_bytes = btrfs_calc_trans_metadata_size(fs_info, 1);
|
||||
|
||||
trace_btrfs_space_reservation(fs_info, "orphan", btrfs_ino(inode),
|
||||
num_bytes, 0);
|
||||
btrfs_block_rsv_release(fs_info, root->orphan_block_rsv, num_bytes);
|
||||
}
|
||||
|
||||
/*
|
||||
* btrfs_subvolume_reserve_metadata() - reserve space for subvolume operation
|
||||
* root: the root of the parent directory
|
||||
@ -6004,7 +5947,6 @@ void btrfs_orphan_release_metadata(struct btrfs_inode *inode)
|
||||
int btrfs_subvolume_reserve_metadata(struct btrfs_root *root,
|
||||
struct btrfs_block_rsv *rsv,
|
||||
int items,
|
||||
u64 *qgroup_reserved,
|
||||
bool use_global_rsv)
|
||||
{
|
||||
u64 num_bytes;
|
||||
@ -6022,8 +5964,6 @@ int btrfs_subvolume_reserve_metadata(struct btrfs_root *root,
|
||||
num_bytes = 0;
|
||||
}
|
||||
|
||||
*qgroup_reserved = num_bytes;
|
||||
|
||||
num_bytes = btrfs_calc_trans_metadata_size(fs_info, items);
|
||||
rsv->space_info = __find_space_info(fs_info,
|
||||
BTRFS_BLOCK_GROUP_METADATA);
|
||||
@ -6033,8 +5973,8 @@ int btrfs_subvolume_reserve_metadata(struct btrfs_root *root,
|
||||
if (ret == -ENOSPC && use_global_rsv)
|
||||
ret = btrfs_block_rsv_migrate(global_rsv, rsv, num_bytes, 1);
|
||||
|
||||
if (ret && *qgroup_reserved)
|
||||
btrfs_qgroup_free_meta_prealloc(root, *qgroup_reserved);
|
||||
if (ret && num_bytes)
|
||||
btrfs_qgroup_free_meta_prealloc(root, num_bytes);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@ -6354,6 +6294,7 @@ static int update_block_group(struct btrfs_trans_handle *trans,
|
||||
spin_lock(&info->unused_bgs_lock);
|
||||
if (list_empty(&cache->bg_list)) {
|
||||
btrfs_get_block_group(cache);
|
||||
trace_btrfs_add_unused_block_group(cache);
|
||||
list_add_tail(&cache->bg_list,
|
||||
&info->unused_bgs);
|
||||
}
|
||||
@ -6511,6 +6452,7 @@ int btrfs_exclude_logged_extents(struct btrfs_fs_info *fs_info,
|
||||
struct btrfs_key key;
|
||||
int found_type;
|
||||
int i;
|
||||
int ret = 0;
|
||||
|
||||
if (!btrfs_fs_incompat(fs_info, MIXED_GROUPS))
|
||||
return 0;
|
||||
@ -6527,10 +6469,12 @@ int btrfs_exclude_logged_extents(struct btrfs_fs_info *fs_info,
|
||||
continue;
|
||||
key.objectid = btrfs_file_extent_disk_bytenr(eb, item);
|
||||
key.offset = btrfs_file_extent_disk_num_bytes(eb, item);
|
||||
__exclude_logged_extent(fs_info, key.objectid, key.offset);
|
||||
ret = __exclude_logged_extent(fs_info, key.objectid, key.offset);
|
||||
if (ret)
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
@ -7122,7 +7066,7 @@ static int __btrfs_free_extent(struct btrfs_trans_handle *trans,
|
||||
}
|
||||
}
|
||||
|
||||
ret = add_to_free_space_tree(trans, info, bytenr, num_bytes);
|
||||
ret = add_to_free_space_tree(trans, bytenr, num_bytes);
|
||||
if (ret) {
|
||||
btrfs_abort_transaction(trans, ret);
|
||||
goto out;
|
||||
@ -7266,7 +7210,7 @@ void btrfs_free_tree_block(struct btrfs_trans_handle *trans,
|
||||
}
|
||||
out:
|
||||
if (pin)
|
||||
add_pinned_bytes(fs_info, buf->len, btrfs_header_level(buf),
|
||||
add_pinned_bytes(fs_info, buf->len, true,
|
||||
root->root_key.objectid);
|
||||
|
||||
if (last_ref) {
|
||||
@ -7320,8 +7264,11 @@ int btrfs_free_extent(struct btrfs_trans_handle *trans,
|
||||
&old_ref_mod, &new_ref_mod);
|
||||
}
|
||||
|
||||
if (ret == 0 && old_ref_mod >= 0 && new_ref_mod < 0)
|
||||
add_pinned_bytes(fs_info, num_bytes, owner, root_objectid);
|
||||
if (ret == 0 && old_ref_mod >= 0 && new_ref_mod < 0) {
|
||||
bool metadata = owner < BTRFS_FIRST_FREE_OBJECTID;
|
||||
|
||||
add_pinned_bytes(fs_info, num_bytes, metadata, root_objectid);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
@ -7373,24 +7320,6 @@ wait_block_group_cache_done(struct btrfs_block_group_cache *cache)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const char *btrfs_raid_type_names[BTRFS_NR_RAID_TYPES] = {
|
||||
[BTRFS_RAID_RAID10] = "raid10",
|
||||
[BTRFS_RAID_RAID1] = "raid1",
|
||||
[BTRFS_RAID_DUP] = "dup",
|
||||
[BTRFS_RAID_RAID0] = "raid0",
|
||||
[BTRFS_RAID_SINGLE] = "single",
|
||||
[BTRFS_RAID_RAID5] = "raid5",
|
||||
[BTRFS_RAID_RAID6] = "raid6",
|
||||
};
|
||||
|
||||
static const char *get_raid_name(enum btrfs_raid_types type)
|
||||
{
|
||||
if (type >= BTRFS_NR_RAID_TYPES)
|
||||
return NULL;
|
||||
|
||||
return btrfs_raid_type_names[type];
|
||||
}
|
||||
|
||||
enum btrfs_loop_type {
|
||||
LOOP_CACHING_NOWAIT = 0,
|
||||
LOOP_CACHING_WAIT = 1,
|
||||
@ -7662,7 +7591,7 @@ have_block_group:
|
||||
if (offset) {
|
||||
/* we have a block, we're done */
|
||||
spin_unlock(&last_ptr->refill_lock);
|
||||
trace_btrfs_reserve_extent_cluster(fs_info,
|
||||
trace_btrfs_reserve_extent_cluster(
|
||||
used_block_group,
|
||||
search_start, num_bytes);
|
||||
if (used_block_group != block_group) {
|
||||
@ -7735,7 +7664,7 @@ refill_cluster:
|
||||
if (offset) {
|
||||
/* we found one, proceed */
|
||||
spin_unlock(&last_ptr->refill_lock);
|
||||
trace_btrfs_reserve_extent_cluster(fs_info,
|
||||
trace_btrfs_reserve_extent_cluster(
|
||||
block_group, search_start,
|
||||
num_bytes);
|
||||
goto checks;
|
||||
@ -7835,8 +7764,7 @@ checks:
|
||||
ins->objectid = search_start;
|
||||
ins->offset = num_bytes;
|
||||
|
||||
trace_btrfs_reserve_extent(fs_info, block_group,
|
||||
search_start, num_bytes);
|
||||
trace_btrfs_reserve_extent(block_group, search_start, num_bytes);
|
||||
btrfs_release_block_group(block_group, delalloc);
|
||||
break;
|
||||
loop:
|
||||
@ -8184,8 +8112,7 @@ static int alloc_reserved_file_extent(struct btrfs_trans_handle *trans,
|
||||
btrfs_mark_buffer_dirty(path->nodes[0]);
|
||||
btrfs_free_path(path);
|
||||
|
||||
ret = remove_from_free_space_tree(trans, fs_info, ins->objectid,
|
||||
ins->offset);
|
||||
ret = remove_from_free_space_tree(trans, ins->objectid, ins->offset);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
@ -8200,37 +8127,52 @@ static int alloc_reserved_file_extent(struct btrfs_trans_handle *trans,
|
||||
}
|
||||
|
||||
static int alloc_reserved_tree_block(struct btrfs_trans_handle *trans,
|
||||
struct btrfs_fs_info *fs_info,
|
||||
u64 parent, u64 root_objectid,
|
||||
u64 flags, struct btrfs_disk_key *key,
|
||||
int level, struct btrfs_key *ins)
|
||||
struct btrfs_delayed_ref_node *node,
|
||||
struct btrfs_delayed_extent_op *extent_op)
|
||||
{
|
||||
struct btrfs_fs_info *fs_info = trans->fs_info;
|
||||
int ret;
|
||||
struct btrfs_extent_item *extent_item;
|
||||
struct btrfs_key extent_key;
|
||||
struct btrfs_tree_block_info *block_info;
|
||||
struct btrfs_extent_inline_ref *iref;
|
||||
struct btrfs_path *path;
|
||||
struct extent_buffer *leaf;
|
||||
struct btrfs_delayed_tree_ref *ref;
|
||||
u32 size = sizeof(*extent_item) + sizeof(*iref);
|
||||
u64 num_bytes = ins->offset;
|
||||
u64 num_bytes;
|
||||
u64 flags = extent_op->flags_to_set;
|
||||
bool skinny_metadata = btrfs_fs_incompat(fs_info, SKINNY_METADATA);
|
||||
|
||||
if (!skinny_metadata)
|
||||
ref = btrfs_delayed_node_to_tree_ref(node);
|
||||
|
||||
extent_key.objectid = node->bytenr;
|
||||
if (skinny_metadata) {
|
||||
extent_key.offset = ref->level;
|
||||
extent_key.type = BTRFS_METADATA_ITEM_KEY;
|
||||
num_bytes = fs_info->nodesize;
|
||||
} else {
|
||||
extent_key.offset = node->num_bytes;
|
||||
extent_key.type = BTRFS_EXTENT_ITEM_KEY;
|
||||
size += sizeof(*block_info);
|
||||
num_bytes = node->num_bytes;
|
||||
}
|
||||
|
||||
path = btrfs_alloc_path();
|
||||
if (!path) {
|
||||
btrfs_free_and_pin_reserved_extent(fs_info, ins->objectid,
|
||||
btrfs_free_and_pin_reserved_extent(fs_info,
|
||||
extent_key.objectid,
|
||||
fs_info->nodesize);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
path->leave_spinning = 1;
|
||||
ret = btrfs_insert_empty_item(trans, fs_info->extent_root, path,
|
||||
ins, size);
|
||||
&extent_key, size);
|
||||
if (ret) {
|
||||
btrfs_free_path(path);
|
||||
btrfs_free_and_pin_reserved_extent(fs_info, ins->objectid,
|
||||
btrfs_free_and_pin_reserved_extent(fs_info,
|
||||
extent_key.objectid,
|
||||
fs_info->nodesize);
|
||||
return ret;
|
||||
}
|
||||
@ -8245,42 +8187,41 @@ static int alloc_reserved_tree_block(struct btrfs_trans_handle *trans,
|
||||
|
||||
if (skinny_metadata) {
|
||||
iref = (struct btrfs_extent_inline_ref *)(extent_item + 1);
|
||||
num_bytes = fs_info->nodesize;
|
||||
} else {
|
||||
block_info = (struct btrfs_tree_block_info *)(extent_item + 1);
|
||||
btrfs_set_tree_block_key(leaf, block_info, key);
|
||||
btrfs_set_tree_block_level(leaf, block_info, level);
|
||||
btrfs_set_tree_block_key(leaf, block_info, &extent_op->key);
|
||||
btrfs_set_tree_block_level(leaf, block_info, ref->level);
|
||||
iref = (struct btrfs_extent_inline_ref *)(block_info + 1);
|
||||
}
|
||||
|
||||
if (parent > 0) {
|
||||
if (node->type == BTRFS_SHARED_BLOCK_REF_KEY) {
|
||||
BUG_ON(!(flags & BTRFS_BLOCK_FLAG_FULL_BACKREF));
|
||||
btrfs_set_extent_inline_ref_type(leaf, iref,
|
||||
BTRFS_SHARED_BLOCK_REF_KEY);
|
||||
btrfs_set_extent_inline_ref_offset(leaf, iref, parent);
|
||||
btrfs_set_extent_inline_ref_offset(leaf, iref, ref->parent);
|
||||
} else {
|
||||
btrfs_set_extent_inline_ref_type(leaf, iref,
|
||||
BTRFS_TREE_BLOCK_REF_KEY);
|
||||
btrfs_set_extent_inline_ref_offset(leaf, iref, root_objectid);
|
||||
btrfs_set_extent_inline_ref_offset(leaf, iref, ref->root);
|
||||
}
|
||||
|
||||
btrfs_mark_buffer_dirty(leaf);
|
||||
btrfs_free_path(path);
|
||||
|
||||
ret = remove_from_free_space_tree(trans, fs_info, ins->objectid,
|
||||
ret = remove_from_free_space_tree(trans, extent_key.objectid,
|
||||
num_bytes);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = update_block_group(trans, fs_info, ins->objectid,
|
||||
ret = update_block_group(trans, fs_info, extent_key.objectid,
|
||||
fs_info->nodesize, 1);
|
||||
if (ret) { /* -ENOENT, logic error */
|
||||
btrfs_err(fs_info, "update block group failed for %llu %llu",
|
||||
ins->objectid, ins->offset);
|
||||
extent_key.objectid, extent_key.offset);
|
||||
BUG();
|
||||
}
|
||||
|
||||
trace_btrfs_reserved_extent_alloc(fs_info, ins->objectid,
|
||||
trace_btrfs_reserved_extent_alloc(fs_info, extent_key.objectid,
|
||||
fs_info->nodesize);
|
||||
return ret;
|
||||
}
|
||||
@ -10173,8 +10114,7 @@ int btrfs_read_block_groups(struct btrfs_fs_info *info)
|
||||
} else if (btrfs_block_group_used(&cache->item) == 0) {
|
||||
cache->last_byte_to_unpin = (u64)-1;
|
||||
cache->cached = BTRFS_CACHE_FINISHED;
|
||||
add_new_free_space(cache, info,
|
||||
found_key.objectid,
|
||||
add_new_free_space(cache, found_key.objectid,
|
||||
found_key.objectid +
|
||||
found_key.offset);
|
||||
free_excluded_extents(info, cache);
|
||||
@ -10204,6 +10144,7 @@ int btrfs_read_block_groups(struct btrfs_fs_info *info)
|
||||
/* Should always be true but just in case. */
|
||||
if (list_empty(&cache->bg_list)) {
|
||||
btrfs_get_block_group(cache);
|
||||
trace_btrfs_add_unused_block_group(cache);
|
||||
list_add_tail(&cache->bg_list,
|
||||
&info->unused_bgs);
|
||||
}
|
||||
@ -10269,7 +10210,7 @@ void btrfs_create_pending_block_groups(struct btrfs_trans_handle *trans)
|
||||
key.offset);
|
||||
if (ret)
|
||||
btrfs_abort_transaction(trans, ret);
|
||||
add_block_group_free_space(trans, fs_info, block_group);
|
||||
add_block_group_free_space(trans, block_group);
|
||||
/* already aborted the transaction if it failed. */
|
||||
next:
|
||||
list_del_init(&block_group->bg_list);
|
||||
@ -10310,7 +10251,7 @@ int btrfs_make_block_group(struct btrfs_trans_handle *trans,
|
||||
return ret;
|
||||
}
|
||||
|
||||
add_new_free_space(cache, fs_info, chunk_offset, chunk_offset + size);
|
||||
add_new_free_space(cache, chunk_offset, chunk_offset + size);
|
||||
|
||||
free_excluded_extents(fs_info, cache);
|
||||
|
||||
@ -10391,6 +10332,7 @@ int btrfs_remove_block_group(struct btrfs_trans_handle *trans,
|
||||
BUG_ON(!block_group);
|
||||
BUG_ON(!block_group->ro);
|
||||
|
||||
trace_btrfs_remove_block_group(block_group);
|
||||
/*
|
||||
* Free the reserved super bytes from this block group before
|
||||
* remove it.
|
||||
@ -10648,7 +10590,7 @@ int btrfs_remove_block_group(struct btrfs_trans_handle *trans,
|
||||
|
||||
mutex_unlock(&fs_info->chunk_mutex);
|
||||
|
||||
ret = remove_block_group_free_space(trans, fs_info, block_group);
|
||||
ret = remove_block_group_free_space(trans, block_group);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
@ -10755,6 +10697,7 @@ void btrfs_delete_unused_bgs(struct btrfs_fs_info *fs_info)
|
||||
* the ro check in case balance is currently acting on
|
||||
* this block group.
|
||||
*/
|
||||
trace_btrfs_skip_unused_block_group(block_group);
|
||||
spin_unlock(&block_group->lock);
|
||||
up_write(&space_info->groups_sem);
|
||||
goto next;
|
||||
@ -10877,7 +10820,6 @@ next:
|
||||
|
||||
int btrfs_init_space_info(struct btrfs_fs_info *fs_info)
|
||||
{
|
||||
struct btrfs_space_info *space_info;
|
||||
struct btrfs_super_block *disk_super;
|
||||
u64 features;
|
||||
u64 flags;
|
||||
@ -10893,21 +10835,21 @@ int btrfs_init_space_info(struct btrfs_fs_info *fs_info)
|
||||
mixed = 1;
|
||||
|
||||
flags = BTRFS_BLOCK_GROUP_SYSTEM;
|
||||
ret = create_space_info(fs_info, flags, &space_info);
|
||||
ret = create_space_info(fs_info, flags);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
if (mixed) {
|
||||
flags = BTRFS_BLOCK_GROUP_METADATA | BTRFS_BLOCK_GROUP_DATA;
|
||||
ret = create_space_info(fs_info, flags, &space_info);
|
||||
ret = create_space_info(fs_info, flags);
|
||||
} else {
|
||||
flags = BTRFS_BLOCK_GROUP_METADATA;
|
||||
ret = create_space_info(fs_info, flags, &space_info);
|
||||
ret = create_space_info(fs_info, flags);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
flags = BTRFS_BLOCK_GROUP_DATA;
|
||||
ret = create_space_info(fs_info, flags, &space_info);
|
||||
ret = create_space_info(fs_info, flags);
|
||||
}
|
||||
out:
|
||||
return ret;
|
||||
@ -11092,12 +11034,7 @@ int btrfs_trim_fs(struct btrfs_fs_info *fs_info, struct fstrim_range *range)
|
||||
void btrfs_end_write_no_snapshotting(struct btrfs_root *root)
|
||||
{
|
||||
percpu_counter_dec(&root->subv_writers->counter);
|
||||
/*
|
||||
* Make sure counter is updated before we wake up waiters.
|
||||
*/
|
||||
smp_mb();
|
||||
if (waitqueue_active(&root->subv_writers->wait))
|
||||
wake_up(&root->subv_writers->wait);
|
||||
cond_wake_up(&root->subv_writers->wait);
|
||||
}
|
||||
|
||||
int btrfs_start_write_no_snapshotting(struct btrfs_root *root)
|
||||
|
@ -4106,14 +4106,13 @@ int extent_write_locked_range(struct inode *inode, u64 start, u64 end,
|
||||
return ret;
|
||||
}
|
||||
|
||||
int extent_writepages(struct extent_io_tree *tree,
|
||||
struct address_space *mapping,
|
||||
int extent_writepages(struct address_space *mapping,
|
||||
struct writeback_control *wbc)
|
||||
{
|
||||
int ret = 0;
|
||||
struct extent_page_data epd = {
|
||||
.bio = NULL,
|
||||
.tree = tree,
|
||||
.tree = &BTRFS_I(mapping->host)->io_tree,
|
||||
.extent_locked = 0,
|
||||
.sync_io = wbc->sync_mode == WB_SYNC_ALL,
|
||||
};
|
||||
@ -4123,9 +4122,8 @@ int extent_writepages(struct extent_io_tree *tree,
|
||||
return ret;
|
||||
}
|
||||
|
||||
int extent_readpages(struct extent_io_tree *tree,
|
||||
struct address_space *mapping,
|
||||
struct list_head *pages, unsigned nr_pages)
|
||||
int extent_readpages(struct address_space *mapping, struct list_head *pages,
|
||||
unsigned nr_pages)
|
||||
{
|
||||
struct bio *bio = NULL;
|
||||
unsigned page_idx;
|
||||
@ -4133,6 +4131,7 @@ int extent_readpages(struct extent_io_tree *tree,
|
||||
struct page *pagepool[16];
|
||||
struct page *page;
|
||||
struct extent_map *em_cached = NULL;
|
||||
struct extent_io_tree *tree = &BTRFS_I(mapping->host)->io_tree;
|
||||
int nr = 0;
|
||||
u64 prev_em_start = (u64)-1;
|
||||
|
||||
@ -4199,8 +4198,7 @@ int extent_invalidatepage(struct extent_io_tree *tree,
|
||||
* are locked or under IO and drops the related state bits if it is safe
|
||||
* to drop the page.
|
||||
*/
|
||||
static int try_release_extent_state(struct extent_map_tree *map,
|
||||
struct extent_io_tree *tree,
|
||||
static int try_release_extent_state(struct extent_io_tree *tree,
|
||||
struct page *page, gfp_t mask)
|
||||
{
|
||||
u64 start = page_offset(page);
|
||||
@ -4235,13 +4233,13 @@ static int try_release_extent_state(struct extent_map_tree *map,
|
||||
* in the range corresponding to the page, both state records and extent
|
||||
* map records are removed
|
||||
*/
|
||||
int try_release_extent_mapping(struct extent_map_tree *map,
|
||||
struct extent_io_tree *tree, struct page *page,
|
||||
gfp_t mask)
|
||||
int try_release_extent_mapping(struct page *page, gfp_t mask)
|
||||
{
|
||||
struct extent_map *em;
|
||||
u64 start = page_offset(page);
|
||||
u64 end = start + PAGE_SIZE - 1;
|
||||
struct extent_io_tree *tree = &BTRFS_I(page->mapping->host)->io_tree;
|
||||
struct extent_map_tree *map = &BTRFS_I(page->mapping->host)->extent_tree;
|
||||
|
||||
if (gfpflags_allow_blocking(mask) &&
|
||||
page->mapping->host->i_size > SZ_16M) {
|
||||
@ -4275,7 +4273,7 @@ int try_release_extent_mapping(struct extent_map_tree *map,
|
||||
free_extent_map(em);
|
||||
}
|
||||
}
|
||||
return try_release_extent_state(map, tree, page, mask);
|
||||
return try_release_extent_state(tree, page, mask);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -5617,46 +5615,6 @@ void copy_extent_buffer(struct extent_buffer *dst, struct extent_buffer *src,
|
||||
}
|
||||
}
|
||||
|
||||
void le_bitmap_set(u8 *map, unsigned int start, int len)
|
||||
{
|
||||
u8 *p = map + BIT_BYTE(start);
|
||||
const unsigned int size = start + len;
|
||||
int bits_to_set = BITS_PER_BYTE - (start % BITS_PER_BYTE);
|
||||
u8 mask_to_set = BITMAP_FIRST_BYTE_MASK(start);
|
||||
|
||||
while (len - bits_to_set >= 0) {
|
||||
*p |= mask_to_set;
|
||||
len -= bits_to_set;
|
||||
bits_to_set = BITS_PER_BYTE;
|
||||
mask_to_set = ~0;
|
||||
p++;
|
||||
}
|
||||
if (len) {
|
||||
mask_to_set &= BITMAP_LAST_BYTE_MASK(size);
|
||||
*p |= mask_to_set;
|
||||
}
|
||||
}
|
||||
|
||||
void le_bitmap_clear(u8 *map, unsigned int start, int len)
|
||||
{
|
||||
u8 *p = map + BIT_BYTE(start);
|
||||
const unsigned int size = start + len;
|
||||
int bits_to_clear = BITS_PER_BYTE - (start % BITS_PER_BYTE);
|
||||
u8 mask_to_clear = BITMAP_FIRST_BYTE_MASK(start);
|
||||
|
||||
while (len - bits_to_clear >= 0) {
|
||||
*p &= ~mask_to_clear;
|
||||
len -= bits_to_clear;
|
||||
bits_to_clear = BITS_PER_BYTE;
|
||||
mask_to_clear = ~0;
|
||||
p++;
|
||||
}
|
||||
if (len) {
|
||||
mask_to_clear &= BITMAP_LAST_BYTE_MASK(size);
|
||||
*p &= ~mask_to_clear;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* eb_bitmap_offset() - calculate the page and offset of the byte containing the
|
||||
* given bit number
|
||||
|
@ -79,14 +79,6 @@
|
||||
#define BITMAP_LAST_BYTE_MASK(nbits) \
|
||||
(BYTE_MASK >> (-(nbits) & (BITS_PER_BYTE - 1)))
|
||||
|
||||
static inline int le_test_bit(int nr, const u8 *addr)
|
||||
{
|
||||
return 1U & (addr[BIT_BYTE(nr)] >> (nr & (BITS_PER_BYTE-1)));
|
||||
}
|
||||
|
||||
void le_bitmap_set(u8 *map, unsigned int start, int len);
|
||||
void le_bitmap_clear(u8 *map, unsigned int start, int len);
|
||||
|
||||
struct extent_state;
|
||||
struct btrfs_root;
|
||||
struct btrfs_inode;
|
||||
@ -278,9 +270,7 @@ typedef struct extent_map *(get_extent_t)(struct btrfs_inode *inode,
|
||||
int create);
|
||||
|
||||
void extent_io_tree_init(struct extent_io_tree *tree, void *private_data);
|
||||
int try_release_extent_mapping(struct extent_map_tree *map,
|
||||
struct extent_io_tree *tree, struct page *page,
|
||||
gfp_t mask);
|
||||
int try_release_extent_mapping(struct page *page, gfp_t mask);
|
||||
int try_release_extent_buffer(struct page *page);
|
||||
int lock_extent_bits(struct extent_io_tree *tree, u64 start, u64 end,
|
||||
struct extent_state **cached);
|
||||
@ -421,14 +411,12 @@ int extent_invalidatepage(struct extent_io_tree *tree,
|
||||
int extent_write_full_page(struct page *page, struct writeback_control *wbc);
|
||||
int extent_write_locked_range(struct inode *inode, u64 start, u64 end,
|
||||
int mode);
|
||||
int extent_writepages(struct extent_io_tree *tree,
|
||||
struct address_space *mapping,
|
||||
int extent_writepages(struct address_space *mapping,
|
||||
struct writeback_control *wbc);
|
||||
int btree_write_cache_pages(struct address_space *mapping,
|
||||
struct writeback_control *wbc);
|
||||
int extent_readpages(struct extent_io_tree *tree,
|
||||
struct address_space *mapping,
|
||||
struct list_head *pages, unsigned nr_pages);
|
||||
int extent_readpages(struct address_space *mapping, struct list_head *pages,
|
||||
unsigned nr_pages);
|
||||
int extent_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
|
||||
__u64 start, __u64 len);
|
||||
void set_page_extent_mapped(struct page *page);
|
||||
|
@ -518,6 +518,7 @@ static noinline int merge_extent_mapping(struct extent_map_tree *em_tree,
|
||||
|
||||
/**
|
||||
* btrfs_add_extent_mapping - add extent mapping into em_tree
|
||||
* @fs_info - used for tracepoint
|
||||
* @em_tree - the extent tree into which we want to insert the extent mapping
|
||||
* @em_in - extent we are inserting
|
||||
* @start - start of the logical range btrfs_get_extent() is requesting
|
||||
@ -535,7 +536,8 @@ static noinline int merge_extent_mapping(struct extent_map_tree *em_tree,
|
||||
* Return 0 on success, otherwise -EEXIST.
|
||||
*
|
||||
*/
|
||||
int btrfs_add_extent_mapping(struct extent_map_tree *em_tree,
|
||||
int btrfs_add_extent_mapping(struct btrfs_fs_info *fs_info,
|
||||
struct extent_map_tree *em_tree,
|
||||
struct extent_map **em_in, u64 start, u64 len)
|
||||
{
|
||||
int ret;
|
||||
@ -553,7 +555,7 @@ int btrfs_add_extent_mapping(struct extent_map_tree *em_tree,
|
||||
|
||||
existing = search_extent_mapping(em_tree, start, len);
|
||||
|
||||
trace_btrfs_handle_em_exist(existing, em, start, len);
|
||||
trace_btrfs_handle_em_exist(fs_info, existing, em, start, len);
|
||||
|
||||
/*
|
||||
* existing will always be non-NULL, since there must be
|
||||
|
@ -92,7 +92,8 @@ int unpin_extent_cache(struct extent_map_tree *tree, u64 start, u64 len, u64 gen
|
||||
void clear_em_logging(struct extent_map_tree *tree, struct extent_map *em);
|
||||
struct extent_map *search_extent_mapping(struct extent_map_tree *tree,
|
||||
u64 start, u64 len);
|
||||
int btrfs_add_extent_mapping(struct extent_map_tree *em_tree,
|
||||
int btrfs_add_extent_mapping(struct btrfs_fs_info *fs_info,
|
||||
struct extent_map_tree *em_tree,
|
||||
struct extent_map **em_in, u64 start, u64 len);
|
||||
|
||||
#endif
|
||||
|
@ -253,10 +253,8 @@ int btrfs_truncate_free_space_cache(struct btrfs_trans_handle *trans,
|
||||
truncate_pagecache(inode, 0);
|
||||
|
||||
/*
|
||||
* We don't need an orphan item because truncating the free space cache
|
||||
* will never be split across transactions.
|
||||
* We don't need to check for -EAGAIN because we're a free space
|
||||
* cache inode
|
||||
* We skip the throttling logic for free space cache inodes, so we don't
|
||||
* need to check for -EAGAIN.
|
||||
*/
|
||||
ret = btrfs_truncate_inode_items(trans, root, inode,
|
||||
0, BTRFS_EXTENT_DATA_KEY);
|
||||
|
@ -12,7 +12,6 @@
|
||||
#include "transaction.h"
|
||||
|
||||
static int __add_block_group_free_space(struct btrfs_trans_handle *trans,
|
||||
struct btrfs_fs_info *fs_info,
|
||||
struct btrfs_block_group_cache *block_group,
|
||||
struct btrfs_path *path);
|
||||
|
||||
@ -45,11 +44,10 @@ void set_free_space_tree_thresholds(struct btrfs_block_group_cache *cache)
|
||||
}
|
||||
|
||||
static int add_new_free_space_info(struct btrfs_trans_handle *trans,
|
||||
struct btrfs_fs_info *fs_info,
|
||||
struct btrfs_block_group_cache *block_group,
|
||||
struct btrfs_path *path)
|
||||
{
|
||||
struct btrfs_root *root = fs_info->free_space_root;
|
||||
struct btrfs_root *root = trans->fs_info->free_space_root;
|
||||
struct btrfs_free_space_info *info;
|
||||
struct btrfs_key key;
|
||||
struct extent_buffer *leaf;
|
||||
@ -138,10 +136,11 @@ static inline u32 free_space_bitmap_size(u64 size, u32 sectorsize)
|
||||
return DIV_ROUND_UP((u32)div_u64(size, sectorsize), BITS_PER_BYTE);
|
||||
}
|
||||
|
||||
static u8 *alloc_bitmap(u32 bitmap_size)
|
||||
static unsigned long *alloc_bitmap(u32 bitmap_size)
|
||||
{
|
||||
u8 *ret;
|
||||
unsigned long *ret;
|
||||
unsigned int nofs_flag;
|
||||
u32 bitmap_rounded_size = round_up(bitmap_size, sizeof(unsigned long));
|
||||
|
||||
/*
|
||||
* GFP_NOFS doesn't work with kvmalloc(), but we really can't recurse
|
||||
@ -152,21 +151,42 @@ static u8 *alloc_bitmap(u32 bitmap_size)
|
||||
* know that recursion is unsafe.
|
||||
*/
|
||||
nofs_flag = memalloc_nofs_save();
|
||||
ret = kvzalloc(bitmap_size, GFP_KERNEL);
|
||||
ret = kvzalloc(bitmap_rounded_size, GFP_KERNEL);
|
||||
memalloc_nofs_restore(nofs_flag);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void le_bitmap_set(unsigned long *map, unsigned int start, int len)
|
||||
{
|
||||
u8 *p = ((u8 *)map) + BIT_BYTE(start);
|
||||
const unsigned int size = start + len;
|
||||
int bits_to_set = BITS_PER_BYTE - (start % BITS_PER_BYTE);
|
||||
u8 mask_to_set = BITMAP_FIRST_BYTE_MASK(start);
|
||||
|
||||
while (len - bits_to_set >= 0) {
|
||||
*p |= mask_to_set;
|
||||
len -= bits_to_set;
|
||||
bits_to_set = BITS_PER_BYTE;
|
||||
mask_to_set = ~0;
|
||||
p++;
|
||||
}
|
||||
if (len) {
|
||||
mask_to_set &= BITMAP_LAST_BYTE_MASK(size);
|
||||
*p |= mask_to_set;
|
||||
}
|
||||
}
|
||||
|
||||
int convert_free_space_to_bitmaps(struct btrfs_trans_handle *trans,
|
||||
struct btrfs_fs_info *fs_info,
|
||||
struct btrfs_block_group_cache *block_group,
|
||||
struct btrfs_path *path)
|
||||
{
|
||||
struct btrfs_fs_info *fs_info = trans->fs_info;
|
||||
struct btrfs_root *root = fs_info->free_space_root;
|
||||
struct btrfs_free_space_info *info;
|
||||
struct btrfs_key key, found_key;
|
||||
struct extent_buffer *leaf;
|
||||
u8 *bitmap, *bitmap_cursor;
|
||||
unsigned long *bitmap;
|
||||
char *bitmap_cursor;
|
||||
u64 start, end;
|
||||
u64 bitmap_range, i;
|
||||
u32 bitmap_size, flags, expected_extent_count;
|
||||
@ -255,7 +275,7 @@ int convert_free_space_to_bitmaps(struct btrfs_trans_handle *trans,
|
||||
goto out;
|
||||
}
|
||||
|
||||
bitmap_cursor = bitmap;
|
||||
bitmap_cursor = (char *)bitmap;
|
||||
bitmap_range = fs_info->sectorsize * BTRFS_FREE_SPACE_BITMAP_BITS;
|
||||
i = start;
|
||||
while (i < end) {
|
||||
@ -296,21 +316,18 @@ out:
|
||||
}
|
||||
|
||||
int convert_free_space_to_extents(struct btrfs_trans_handle *trans,
|
||||
struct btrfs_fs_info *fs_info,
|
||||
struct btrfs_block_group_cache *block_group,
|
||||
struct btrfs_path *path)
|
||||
{
|
||||
struct btrfs_fs_info *fs_info = trans->fs_info;
|
||||
struct btrfs_root *root = fs_info->free_space_root;
|
||||
struct btrfs_free_space_info *info;
|
||||
struct btrfs_key key, found_key;
|
||||
struct extent_buffer *leaf;
|
||||
u8 *bitmap;
|
||||
unsigned long *bitmap;
|
||||
u64 start, end;
|
||||
/* Initialize to silence GCC. */
|
||||
u64 extent_start = 0;
|
||||
u64 offset;
|
||||
u32 bitmap_size, flags, expected_extent_count;
|
||||
int prev_bit = 0, bit, bitnr;
|
||||
unsigned long nrbits, start_bit, end_bit;
|
||||
u32 extent_count = 0;
|
||||
int done = 0, nr;
|
||||
int ret;
|
||||
@ -348,7 +365,7 @@ int convert_free_space_to_extents(struct btrfs_trans_handle *trans,
|
||||
break;
|
||||
} else if (found_key.type == BTRFS_FREE_SPACE_BITMAP_KEY) {
|
||||
unsigned long ptr;
|
||||
u8 *bitmap_cursor;
|
||||
char *bitmap_cursor;
|
||||
u32 bitmap_pos, data_size;
|
||||
|
||||
ASSERT(found_key.objectid >= start);
|
||||
@ -358,7 +375,7 @@ int convert_free_space_to_extents(struct btrfs_trans_handle *trans,
|
||||
bitmap_pos = div_u64(found_key.objectid - start,
|
||||
fs_info->sectorsize *
|
||||
BITS_PER_BYTE);
|
||||
bitmap_cursor = bitmap + bitmap_pos;
|
||||
bitmap_cursor = ((char *)bitmap) + bitmap_pos;
|
||||
data_size = free_space_bitmap_size(found_key.offset,
|
||||
fs_info->sectorsize);
|
||||
|
||||
@ -392,32 +409,16 @@ int convert_free_space_to_extents(struct btrfs_trans_handle *trans,
|
||||
btrfs_mark_buffer_dirty(leaf);
|
||||
btrfs_release_path(path);
|
||||
|
||||
offset = start;
|
||||
bitnr = 0;
|
||||
while (offset < end) {
|
||||
bit = !!le_test_bit(bitnr, bitmap);
|
||||
if (prev_bit == 0 && bit == 1) {
|
||||
extent_start = offset;
|
||||
} else if (prev_bit == 1 && bit == 0) {
|
||||
key.objectid = extent_start;
|
||||
key.type = BTRFS_FREE_SPACE_EXTENT_KEY;
|
||||
key.offset = offset - extent_start;
|
||||
nrbits = div_u64(block_group->key.offset, block_group->fs_info->sectorsize);
|
||||
start_bit = find_next_bit_le(bitmap, nrbits, 0);
|
||||
|
||||
ret = btrfs_insert_empty_item(trans, root, path, &key, 0);
|
||||
if (ret)
|
||||
goto out;
|
||||
btrfs_release_path(path);
|
||||
while (start_bit < nrbits) {
|
||||
end_bit = find_next_zero_bit_le(bitmap, nrbits, start_bit);
|
||||
ASSERT(start_bit < end_bit);
|
||||
|
||||
extent_count++;
|
||||
}
|
||||
prev_bit = bit;
|
||||
offset += fs_info->sectorsize;
|
||||
bitnr++;
|
||||
}
|
||||
if (prev_bit == 1) {
|
||||
key.objectid = extent_start;
|
||||
key.objectid = start + start_bit * block_group->fs_info->sectorsize;
|
||||
key.type = BTRFS_FREE_SPACE_EXTENT_KEY;
|
||||
key.offset = end - extent_start;
|
||||
key.offset = (end_bit - start_bit) * block_group->fs_info->sectorsize;
|
||||
|
||||
ret = btrfs_insert_empty_item(trans, root, path, &key, 0);
|
||||
if (ret)
|
||||
@ -425,6 +426,8 @@ int convert_free_space_to_extents(struct btrfs_trans_handle *trans,
|
||||
btrfs_release_path(path);
|
||||
|
||||
extent_count++;
|
||||
|
||||
start_bit = find_next_bit_le(bitmap, nrbits, end_bit);
|
||||
}
|
||||
|
||||
if (extent_count != expected_extent_count) {
|
||||
@ -446,7 +449,6 @@ out:
|
||||
}
|
||||
|
||||
static int update_free_space_extent_count(struct btrfs_trans_handle *trans,
|
||||
struct btrfs_fs_info *fs_info,
|
||||
struct btrfs_block_group_cache *block_group,
|
||||
struct btrfs_path *path,
|
||||
int new_extents)
|
||||
@ -459,7 +461,8 @@ static int update_free_space_extent_count(struct btrfs_trans_handle *trans,
|
||||
if (new_extents == 0)
|
||||
return 0;
|
||||
|
||||
info = search_free_space_info(trans, fs_info, block_group, path, 1);
|
||||
info = search_free_space_info(trans, trans->fs_info, block_group, path,
|
||||
1);
|
||||
if (IS_ERR(info)) {
|
||||
ret = PTR_ERR(info);
|
||||
goto out;
|
||||
@ -474,12 +477,10 @@ static int update_free_space_extent_count(struct btrfs_trans_handle *trans,
|
||||
|
||||
if (!(flags & BTRFS_FREE_SPACE_USING_BITMAPS) &&
|
||||
extent_count > block_group->bitmap_high_thresh) {
|
||||
ret = convert_free_space_to_bitmaps(trans, fs_info, block_group,
|
||||
path);
|
||||
ret = convert_free_space_to_bitmaps(trans, block_group, path);
|
||||
} else if ((flags & BTRFS_FREE_SPACE_USING_BITMAPS) &&
|
||||
extent_count < block_group->bitmap_low_thresh) {
|
||||
ret = convert_free_space_to_extents(trans, fs_info, block_group,
|
||||
path);
|
||||
ret = convert_free_space_to_extents(trans, block_group, path);
|
||||
}
|
||||
|
||||
out:
|
||||
@ -576,12 +577,11 @@ static int free_space_next_bitmap(struct btrfs_trans_handle *trans,
|
||||
* the bitmap.
|
||||
*/
|
||||
static int modify_free_space_bitmap(struct btrfs_trans_handle *trans,
|
||||
struct btrfs_fs_info *fs_info,
|
||||
struct btrfs_block_group_cache *block_group,
|
||||
struct btrfs_path *path,
|
||||
u64 start, u64 size, int remove)
|
||||
{
|
||||
struct btrfs_root *root = fs_info->free_space_root;
|
||||
struct btrfs_root *root = block_group->fs_info->free_space_root;
|
||||
struct btrfs_key key;
|
||||
u64 end = start + size;
|
||||
u64 cur_start, cur_size;
|
||||
@ -682,7 +682,7 @@ static int modify_free_space_bitmap(struct btrfs_trans_handle *trans,
|
||||
}
|
||||
|
||||
btrfs_release_path(path);
|
||||
ret = update_free_space_extent_count(trans, fs_info, block_group, path,
|
||||
ret = update_free_space_extent_count(trans, block_group, path,
|
||||
new_extents);
|
||||
|
||||
out:
|
||||
@ -690,12 +690,11 @@ out:
|
||||
}
|
||||
|
||||
static int remove_free_space_extent(struct btrfs_trans_handle *trans,
|
||||
struct btrfs_fs_info *fs_info,
|
||||
struct btrfs_block_group_cache *block_group,
|
||||
struct btrfs_path *path,
|
||||
u64 start, u64 size)
|
||||
{
|
||||
struct btrfs_root *root = fs_info->free_space_root;
|
||||
struct btrfs_root *root = trans->fs_info->free_space_root;
|
||||
struct btrfs_key key;
|
||||
u64 found_start, found_end;
|
||||
u64 end = start + size;
|
||||
@ -769,7 +768,7 @@ static int remove_free_space_extent(struct btrfs_trans_handle *trans,
|
||||
}
|
||||
|
||||
btrfs_release_path(path);
|
||||
ret = update_free_space_extent_count(trans, fs_info, block_group, path,
|
||||
ret = update_free_space_extent_count(trans, block_group, path,
|
||||
new_extents);
|
||||
|
||||
out:
|
||||
@ -777,7 +776,6 @@ out:
|
||||
}
|
||||
|
||||
int __remove_from_free_space_tree(struct btrfs_trans_handle *trans,
|
||||
struct btrfs_fs_info *fs_info,
|
||||
struct btrfs_block_group_cache *block_group,
|
||||
struct btrfs_path *path, u64 start, u64 size)
|
||||
{
|
||||
@ -786,36 +784,35 @@ int __remove_from_free_space_tree(struct btrfs_trans_handle *trans,
|
||||
int ret;
|
||||
|
||||
if (block_group->needs_free_space) {
|
||||
ret = __add_block_group_free_space(trans, fs_info, block_group,
|
||||
path);
|
||||
ret = __add_block_group_free_space(trans, block_group, path);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
info = search_free_space_info(NULL, fs_info, block_group, path, 0);
|
||||
info = search_free_space_info(NULL, trans->fs_info, block_group, path,
|
||||
0);
|
||||
if (IS_ERR(info))
|
||||
return PTR_ERR(info);
|
||||
flags = btrfs_free_space_flags(path->nodes[0], info);
|
||||
btrfs_release_path(path);
|
||||
|
||||
if (flags & BTRFS_FREE_SPACE_USING_BITMAPS) {
|
||||
return modify_free_space_bitmap(trans, fs_info, block_group,
|
||||
path, start, size, 1);
|
||||
return modify_free_space_bitmap(trans, block_group, path,
|
||||
start, size, 1);
|
||||
} else {
|
||||
return remove_free_space_extent(trans, fs_info, block_group,
|
||||
path, start, size);
|
||||
return remove_free_space_extent(trans, block_group, path,
|
||||
start, size);
|
||||
}
|
||||
}
|
||||
|
||||
int remove_from_free_space_tree(struct btrfs_trans_handle *trans,
|
||||
struct btrfs_fs_info *fs_info,
|
||||
u64 start, u64 size)
|
||||
{
|
||||
struct btrfs_block_group_cache *block_group;
|
||||
struct btrfs_path *path;
|
||||
int ret;
|
||||
|
||||
if (!btrfs_fs_compat_ro(fs_info, FREE_SPACE_TREE))
|
||||
if (!btrfs_fs_compat_ro(trans->fs_info, FREE_SPACE_TREE))
|
||||
return 0;
|
||||
|
||||
path = btrfs_alloc_path();
|
||||
@ -824,7 +821,7 @@ int remove_from_free_space_tree(struct btrfs_trans_handle *trans,
|
||||
goto out;
|
||||
}
|
||||
|
||||
block_group = btrfs_lookup_block_group(fs_info, start);
|
||||
block_group = btrfs_lookup_block_group(trans->fs_info, start);
|
||||
if (!block_group) {
|
||||
ASSERT(0);
|
||||
ret = -ENOENT;
|
||||
@ -832,8 +829,8 @@ int remove_from_free_space_tree(struct btrfs_trans_handle *trans,
|
||||
}
|
||||
|
||||
mutex_lock(&block_group->free_space_lock);
|
||||
ret = __remove_from_free_space_tree(trans, fs_info, block_group, path,
|
||||
start, size);
|
||||
ret = __remove_from_free_space_tree(trans, block_group, path, start,
|
||||
size);
|
||||
mutex_unlock(&block_group->free_space_lock);
|
||||
|
||||
btrfs_put_block_group(block_group);
|
||||
@ -845,12 +842,11 @@ out:
|
||||
}
|
||||
|
||||
static int add_free_space_extent(struct btrfs_trans_handle *trans,
|
||||
struct btrfs_fs_info *fs_info,
|
||||
struct btrfs_block_group_cache *block_group,
|
||||
struct btrfs_path *path,
|
||||
u64 start, u64 size)
|
||||
{
|
||||
struct btrfs_root *root = fs_info->free_space_root;
|
||||
struct btrfs_root *root = trans->fs_info->free_space_root;
|
||||
struct btrfs_key key, new_key;
|
||||
u64 found_start, found_end;
|
||||
u64 end = start + size;
|
||||
@ -965,7 +961,7 @@ insert:
|
||||
goto out;
|
||||
|
||||
btrfs_release_path(path);
|
||||
ret = update_free_space_extent_count(trans, fs_info, block_group, path,
|
||||
ret = update_free_space_extent_count(trans, block_group, path,
|
||||
new_extents);
|
||||
|
||||
out:
|
||||
@ -973,17 +969,16 @@ out:
|
||||
}
|
||||
|
||||
int __add_to_free_space_tree(struct btrfs_trans_handle *trans,
|
||||
struct btrfs_fs_info *fs_info,
|
||||
struct btrfs_block_group_cache *block_group,
|
||||
struct btrfs_path *path, u64 start, u64 size)
|
||||
{
|
||||
struct btrfs_fs_info *fs_info = trans->fs_info;
|
||||
struct btrfs_free_space_info *info;
|
||||
u32 flags;
|
||||
int ret;
|
||||
|
||||
if (block_group->needs_free_space) {
|
||||
ret = __add_block_group_free_space(trans, fs_info, block_group,
|
||||
path);
|
||||
ret = __add_block_group_free_space(trans, block_group, path);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
@ -995,23 +990,22 @@ int __add_to_free_space_tree(struct btrfs_trans_handle *trans,
|
||||
btrfs_release_path(path);
|
||||
|
||||
if (flags & BTRFS_FREE_SPACE_USING_BITMAPS) {
|
||||
return modify_free_space_bitmap(trans, fs_info, block_group,
|
||||
path, start, size, 0);
|
||||
return modify_free_space_bitmap(trans, block_group, path,
|
||||
start, size, 0);
|
||||
} else {
|
||||
return add_free_space_extent(trans, fs_info, block_group, path,
|
||||
start, size);
|
||||
return add_free_space_extent(trans, block_group, path, start,
|
||||
size);
|
||||
}
|
||||
}
|
||||
|
||||
int add_to_free_space_tree(struct btrfs_trans_handle *trans,
|
||||
struct btrfs_fs_info *fs_info,
|
||||
u64 start, u64 size)
|
||||
{
|
||||
struct btrfs_block_group_cache *block_group;
|
||||
struct btrfs_path *path;
|
||||
int ret;
|
||||
|
||||
if (!btrfs_fs_compat_ro(fs_info, FREE_SPACE_TREE))
|
||||
if (!btrfs_fs_compat_ro(trans->fs_info, FREE_SPACE_TREE))
|
||||
return 0;
|
||||
|
||||
path = btrfs_alloc_path();
|
||||
@ -1020,7 +1014,7 @@ int add_to_free_space_tree(struct btrfs_trans_handle *trans,
|
||||
goto out;
|
||||
}
|
||||
|
||||
block_group = btrfs_lookup_block_group(fs_info, start);
|
||||
block_group = btrfs_lookup_block_group(trans->fs_info, start);
|
||||
if (!block_group) {
|
||||
ASSERT(0);
|
||||
ret = -ENOENT;
|
||||
@ -1028,8 +1022,7 @@ int add_to_free_space_tree(struct btrfs_trans_handle *trans,
|
||||
}
|
||||
|
||||
mutex_lock(&block_group->free_space_lock);
|
||||
ret = __add_to_free_space_tree(trans, fs_info, block_group, path, start,
|
||||
size);
|
||||
ret = __add_to_free_space_tree(trans, block_group, path, start, size);
|
||||
mutex_unlock(&block_group->free_space_lock);
|
||||
|
||||
btrfs_put_block_group(block_group);
|
||||
@ -1046,10 +1039,9 @@ out:
|
||||
* through the normal add/remove hooks.
|
||||
*/
|
||||
static int populate_free_space_tree(struct btrfs_trans_handle *trans,
|
||||
struct btrfs_fs_info *fs_info,
|
||||
struct btrfs_block_group_cache *block_group)
|
||||
{
|
||||
struct btrfs_root *extent_root = fs_info->extent_root;
|
||||
struct btrfs_root *extent_root = trans->fs_info->extent_root;
|
||||
struct btrfs_path *path, *path2;
|
||||
struct btrfs_key key;
|
||||
u64 start, end;
|
||||
@ -1066,7 +1058,7 @@ static int populate_free_space_tree(struct btrfs_trans_handle *trans,
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
ret = add_new_free_space_info(trans, fs_info, block_group, path2);
|
||||
ret = add_new_free_space_info(trans, block_group, path2);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
@ -1099,7 +1091,7 @@ static int populate_free_space_tree(struct btrfs_trans_handle *trans,
|
||||
break;
|
||||
|
||||
if (start < key.objectid) {
|
||||
ret = __add_to_free_space_tree(trans, fs_info,
|
||||
ret = __add_to_free_space_tree(trans,
|
||||
block_group,
|
||||
path2, start,
|
||||
key.objectid -
|
||||
@ -1109,7 +1101,7 @@ static int populate_free_space_tree(struct btrfs_trans_handle *trans,
|
||||
}
|
||||
start = key.objectid;
|
||||
if (key.type == BTRFS_METADATA_ITEM_KEY)
|
||||
start += fs_info->nodesize;
|
||||
start += trans->fs_info->nodesize;
|
||||
else
|
||||
start += key.offset;
|
||||
} else if (key.type == BTRFS_BLOCK_GROUP_ITEM_KEY) {
|
||||
@ -1124,8 +1116,8 @@ static int populate_free_space_tree(struct btrfs_trans_handle *trans,
|
||||
break;
|
||||
}
|
||||
if (start < end) {
|
||||
ret = __add_to_free_space_tree(trans, fs_info, block_group,
|
||||
path2, start, end - start);
|
||||
ret = __add_to_free_space_tree(trans, block_group, path2,
|
||||
start, end - start);
|
||||
if (ret)
|
||||
goto out_locked;
|
||||
}
|
||||
@ -1165,7 +1157,7 @@ int btrfs_create_free_space_tree(struct btrfs_fs_info *fs_info)
|
||||
while (node) {
|
||||
block_group = rb_entry(node, struct btrfs_block_group_cache,
|
||||
cache_node);
|
||||
ret = populate_free_space_tree(trans, fs_info, block_group);
|
||||
ret = populate_free_space_tree(trans, block_group);
|
||||
if (ret)
|
||||
goto abort;
|
||||
node = rb_next(node);
|
||||
@ -1269,7 +1261,6 @@ abort:
|
||||
}
|
||||
|
||||
static int __add_block_group_free_space(struct btrfs_trans_handle *trans,
|
||||
struct btrfs_fs_info *fs_info,
|
||||
struct btrfs_block_group_cache *block_group,
|
||||
struct btrfs_path *path)
|
||||
{
|
||||
@ -1277,19 +1268,19 @@ static int __add_block_group_free_space(struct btrfs_trans_handle *trans,
|
||||
|
||||
block_group->needs_free_space = 0;
|
||||
|
||||
ret = add_new_free_space_info(trans, fs_info, block_group, path);
|
||||
ret = add_new_free_space_info(trans, block_group, path);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return __add_to_free_space_tree(trans, fs_info, block_group, path,
|
||||
return __add_to_free_space_tree(trans, block_group, path,
|
||||
block_group->key.objectid,
|
||||
block_group->key.offset);
|
||||
}
|
||||
|
||||
int add_block_group_free_space(struct btrfs_trans_handle *trans,
|
||||
struct btrfs_fs_info *fs_info,
|
||||
struct btrfs_block_group_cache *block_group)
|
||||
{
|
||||
struct btrfs_fs_info *fs_info = trans->fs_info;
|
||||
struct btrfs_path *path = NULL;
|
||||
int ret = 0;
|
||||
|
||||
@ -1306,7 +1297,7 @@ int add_block_group_free_space(struct btrfs_trans_handle *trans,
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = __add_block_group_free_space(trans, fs_info, block_group, path);
|
||||
ret = __add_block_group_free_space(trans, block_group, path);
|
||||
|
||||
out:
|
||||
btrfs_free_path(path);
|
||||
@ -1317,10 +1308,9 @@ out:
|
||||
}
|
||||
|
||||
int remove_block_group_free_space(struct btrfs_trans_handle *trans,
|
||||
struct btrfs_fs_info *fs_info,
|
||||
struct btrfs_block_group_cache *block_group)
|
||||
{
|
||||
struct btrfs_root *root = fs_info->free_space_root;
|
||||
struct btrfs_root *root = trans->fs_info->free_space_root;
|
||||
struct btrfs_path *path;
|
||||
struct btrfs_key key, found_key;
|
||||
struct extent_buffer *leaf;
|
||||
@ -1328,7 +1318,7 @@ int remove_block_group_free_space(struct btrfs_trans_handle *trans,
|
||||
int done = 0, nr;
|
||||
int ret;
|
||||
|
||||
if (!btrfs_fs_compat_ro(fs_info, FREE_SPACE_TREE))
|
||||
if (!btrfs_fs_compat_ro(trans->fs_info, FREE_SPACE_TREE))
|
||||
return 0;
|
||||
|
||||
if (block_group->needs_free_space) {
|
||||
@ -1439,7 +1429,6 @@ static int load_free_space_bitmaps(struct btrfs_caching_control *caching_ctl,
|
||||
extent_start = offset;
|
||||
} else if (prev_bit == 1 && bit == 0) {
|
||||
total_found += add_new_free_space(block_group,
|
||||
fs_info,
|
||||
extent_start,
|
||||
offset);
|
||||
if (total_found > CACHING_CTL_WAKE_UP) {
|
||||
@ -1453,8 +1442,8 @@ static int load_free_space_bitmaps(struct btrfs_caching_control *caching_ctl,
|
||||
}
|
||||
}
|
||||
if (prev_bit == 1) {
|
||||
total_found += add_new_free_space(block_group, fs_info,
|
||||
extent_start, end);
|
||||
total_found += add_new_free_space(block_group, extent_start,
|
||||
end);
|
||||
extent_count++;
|
||||
}
|
||||
|
||||
@ -1511,8 +1500,7 @@ static int load_free_space_extents(struct btrfs_caching_control *caching_ctl,
|
||||
|
||||
caching_ctl->progress = key.objectid;
|
||||
|
||||
total_found += add_new_free_space(block_group, fs_info,
|
||||
key.objectid,
|
||||
total_found += add_new_free_space(block_group, key.objectid,
|
||||
key.objectid + key.offset);
|
||||
if (total_found > CACHING_CTL_WAKE_UP) {
|
||||
total_found = 0;
|
||||
|
@ -19,16 +19,12 @@ int btrfs_create_free_space_tree(struct btrfs_fs_info *fs_info);
|
||||
int btrfs_clear_free_space_tree(struct btrfs_fs_info *fs_info);
|
||||
int load_free_space_tree(struct btrfs_caching_control *caching_ctl);
|
||||
int add_block_group_free_space(struct btrfs_trans_handle *trans,
|
||||
struct btrfs_fs_info *fs_info,
|
||||
struct btrfs_block_group_cache *block_group);
|
||||
int remove_block_group_free_space(struct btrfs_trans_handle *trans,
|
||||
struct btrfs_fs_info *fs_info,
|
||||
struct btrfs_block_group_cache *block_group);
|
||||
int add_to_free_space_tree(struct btrfs_trans_handle *trans,
|
||||
struct btrfs_fs_info *fs_info,
|
||||
u64 start, u64 size);
|
||||
int remove_from_free_space_tree(struct btrfs_trans_handle *trans,
|
||||
struct btrfs_fs_info *fs_info,
|
||||
u64 start, u64 size);
|
||||
|
||||
#ifdef CONFIG_BTRFS_FS_RUN_SANITY_TESTS
|
||||
@ -38,19 +34,15 @@ search_free_space_info(struct btrfs_trans_handle *trans,
|
||||
struct btrfs_block_group_cache *block_group,
|
||||
struct btrfs_path *path, int cow);
|
||||
int __add_to_free_space_tree(struct btrfs_trans_handle *trans,
|
||||
struct btrfs_fs_info *fs_info,
|
||||
struct btrfs_block_group_cache *block_group,
|
||||
struct btrfs_path *path, u64 start, u64 size);
|
||||
int __remove_from_free_space_tree(struct btrfs_trans_handle *trans,
|
||||
struct btrfs_fs_info *fs_info,
|
||||
struct btrfs_block_group_cache *block_group,
|
||||
struct btrfs_path *path, u64 start, u64 size);
|
||||
int convert_free_space_to_bitmaps(struct btrfs_trans_handle *trans,
|
||||
struct btrfs_fs_info *fs_info,
|
||||
struct btrfs_block_group_cache *block_group,
|
||||
struct btrfs_path *path);
|
||||
int convert_free_space_to_extents(struct btrfs_trans_handle *trans,
|
||||
struct btrfs_fs_info *fs_info,
|
||||
struct btrfs_block_group_cache *block_group,
|
||||
struct btrfs_path *path);
|
||||
int free_space_test_bit(struct btrfs_block_group_cache *block_group,
|
||||
|
1359
fs/btrfs/inode.c
1359
fs/btrfs/inode.c
File diff suppressed because it is too large
Load Diff
1132
fs/btrfs/ioctl.c
1132
fs/btrfs/ioctl.c
File diff suppressed because it is too large
Load Diff
@ -66,22 +66,16 @@ void btrfs_clear_lock_blocking_rw(struct extent_buffer *eb, int rw)
|
||||
write_lock(&eb->lock);
|
||||
WARN_ON(atomic_read(&eb->spinning_writers));
|
||||
atomic_inc(&eb->spinning_writers);
|
||||
/*
|
||||
* atomic_dec_and_test implies a barrier for waitqueue_active
|
||||
*/
|
||||
if (atomic_dec_and_test(&eb->blocking_writers) &&
|
||||
waitqueue_active(&eb->write_lock_wq))
|
||||
wake_up(&eb->write_lock_wq);
|
||||
/* atomic_dec_and_test implies a barrier */
|
||||
if (atomic_dec_and_test(&eb->blocking_writers))
|
||||
cond_wake_up_nomb(&eb->write_lock_wq);
|
||||
} else if (rw == BTRFS_READ_LOCK_BLOCKING) {
|
||||
BUG_ON(atomic_read(&eb->blocking_readers) == 0);
|
||||
read_lock(&eb->lock);
|
||||
atomic_inc(&eb->spinning_readers);
|
||||
/*
|
||||
* atomic_dec_and_test implies a barrier for waitqueue_active
|
||||
*/
|
||||
if (atomic_dec_and_test(&eb->blocking_readers) &&
|
||||
waitqueue_active(&eb->read_lock_wq))
|
||||
wake_up(&eb->read_lock_wq);
|
||||
/* atomic_dec_and_test implies a barrier */
|
||||
if (atomic_dec_and_test(&eb->blocking_readers))
|
||||
cond_wake_up_nomb(&eb->read_lock_wq);
|
||||
}
|
||||
}
|
||||
|
||||
@ -221,12 +215,9 @@ void btrfs_tree_read_unlock_blocking(struct extent_buffer *eb)
|
||||
}
|
||||
btrfs_assert_tree_read_locked(eb);
|
||||
WARN_ON(atomic_read(&eb->blocking_readers) == 0);
|
||||
/*
|
||||
* atomic_dec_and_test implies a barrier for waitqueue_active
|
||||
*/
|
||||
if (atomic_dec_and_test(&eb->blocking_readers) &&
|
||||
waitqueue_active(&eb->read_lock_wq))
|
||||
wake_up(&eb->read_lock_wq);
|
||||
/* atomic_dec_and_test implies a barrier */
|
||||
if (atomic_dec_and_test(&eb->blocking_readers))
|
||||
cond_wake_up_nomb(&eb->read_lock_wq);
|
||||
atomic_dec(&eb->read_locks);
|
||||
}
|
||||
|
||||
@ -275,12 +266,9 @@ void btrfs_tree_unlock(struct extent_buffer *eb)
|
||||
if (blockers) {
|
||||
WARN_ON(atomic_read(&eb->spinning_writers));
|
||||
atomic_dec(&eb->blocking_writers);
|
||||
/*
|
||||
* Make sure counter is updated before we wake up waiters.
|
||||
*/
|
||||
/* Use the lighter barrier after atomic */
|
||||
smp_mb__after_atomic();
|
||||
if (waitqueue_active(&eb->write_lock_wq))
|
||||
wake_up(&eb->write_lock_wq);
|
||||
cond_wake_up_nomb(&eb->write_lock_wq);
|
||||
} else {
|
||||
WARN_ON(atomic_read(&eb->spinning_writers) != 1);
|
||||
atomic_dec(&eb->spinning_writers);
|
||||
|
@ -17,6 +17,43 @@
|
||||
|
||||
#define LZO_LEN 4
|
||||
|
||||
/*
|
||||
* Btrfs LZO compression format
|
||||
*
|
||||
* Regular and inlined LZO compressed data extents consist of:
|
||||
*
|
||||
* 1. Header
|
||||
* Fixed size. LZO_LEN (4) bytes long, LE32.
|
||||
* Records the total size (including the header) of compressed data.
|
||||
*
|
||||
* 2. Segment(s)
|
||||
* Variable size. Each segment includes one segment header, followd by data
|
||||
* payload.
|
||||
* One regular LZO compressed extent can have one or more segments.
|
||||
* For inlined LZO compressed extent, only one segment is allowed.
|
||||
* One segment represents at most one page of uncompressed data.
|
||||
*
|
||||
* 2.1 Segment header
|
||||
* Fixed size. LZO_LEN (4) bytes long, LE32.
|
||||
* Records the total size of the segment (not including the header).
|
||||
* Segment header never crosses page boundary, thus it's possible to
|
||||
* have at most 3 padding zeros at the end of the page.
|
||||
*
|
||||
* 2.2 Data Payload
|
||||
* Variable size. Size up limit should be lzo1x_worst_compress(PAGE_SIZE)
|
||||
* which is 4419 for a 4KiB page.
|
||||
*
|
||||
* Example:
|
||||
* Page 1:
|
||||
* 0 0x2 0x4 0x6 0x8 0xa 0xc 0xe 0x10
|
||||
* 0x0000 | Header | SegHdr 01 | Data payload 01 ... |
|
||||
* ...
|
||||
* 0x0ff0 | SegHdr N | Data payload N ... |00|
|
||||
* ^^ padding zeros
|
||||
* Page 2:
|
||||
* 0x1000 | SegHdr N+1| Data payload N+1 ... |
|
||||
*/
|
||||
|
||||
struct workspace {
|
||||
void *mem;
|
||||
void *buf; /* where decompressed data goes */
|
||||
@ -258,6 +295,7 @@ static int lzo_decompress_bio(struct list_head *ws, struct compressed_bio *cb)
|
||||
unsigned long working_bytes;
|
||||
size_t in_len;
|
||||
size_t out_len;
|
||||
const size_t max_segment_len = lzo1x_worst_compress(PAGE_SIZE);
|
||||
unsigned long in_offset;
|
||||
unsigned long in_page_bytes_left;
|
||||
unsigned long tot_in;
|
||||
@ -271,10 +309,22 @@ static int lzo_decompress_bio(struct list_head *ws, struct compressed_bio *cb)
|
||||
|
||||
data_in = kmap(pages_in[0]);
|
||||
tot_len = read_compress_length(data_in);
|
||||
/*
|
||||
* Compressed data header check.
|
||||
*
|
||||
* The real compressed size can't exceed the maximum extent length, and
|
||||
* all pages should be used (whole unused page with just the segment
|
||||
* header is not possible). If this happens it means the compressed
|
||||
* extent is corrupted.
|
||||
*/
|
||||
if (tot_len > min_t(size_t, BTRFS_MAX_COMPRESSED, srclen) ||
|
||||
tot_len < srclen - PAGE_SIZE) {
|
||||
ret = -EUCLEAN;
|
||||
goto done;
|
||||
}
|
||||
|
||||
tot_in = LZO_LEN;
|
||||
in_offset = LZO_LEN;
|
||||
tot_len = min_t(size_t, srclen, tot_len);
|
||||
in_page_bytes_left = PAGE_SIZE - LZO_LEN;
|
||||
|
||||
tot_out = 0;
|
||||
@ -285,6 +335,17 @@ static int lzo_decompress_bio(struct list_head *ws, struct compressed_bio *cb)
|
||||
in_offset += LZO_LEN;
|
||||
tot_in += LZO_LEN;
|
||||
|
||||
/*
|
||||
* Segment header check.
|
||||
*
|
||||
* The segment length must not exceed the maximum LZO
|
||||
* compression size, nor the total compressed size.
|
||||
*/
|
||||
if (in_len > max_segment_len || tot_in + in_len > tot_len) {
|
||||
ret = -EUCLEAN;
|
||||
goto done;
|
||||
}
|
||||
|
||||
tot_in += in_len;
|
||||
working_bytes = in_len;
|
||||
may_late_unmap = need_unmap = false;
|
||||
@ -335,7 +396,7 @@ cont:
|
||||
}
|
||||
}
|
||||
|
||||
out_len = lzo1x_worst_compress(PAGE_SIZE);
|
||||
out_len = max_segment_len;
|
||||
ret = lzo1x_decompress_safe(buf, in_len, workspace->buf,
|
||||
&out_len);
|
||||
if (need_unmap)
|
||||
@ -369,15 +430,24 @@ static int lzo_decompress(struct list_head *ws, unsigned char *data_in,
|
||||
struct workspace *workspace = list_entry(ws, struct workspace, list);
|
||||
size_t in_len;
|
||||
size_t out_len;
|
||||
size_t max_segment_len = lzo1x_worst_compress(PAGE_SIZE);
|
||||
int ret = 0;
|
||||
char *kaddr;
|
||||
unsigned long bytes;
|
||||
|
||||
BUG_ON(srclen < LZO_LEN);
|
||||
if (srclen < LZO_LEN || srclen > max_segment_len + LZO_LEN * 2)
|
||||
return -EUCLEAN;
|
||||
|
||||
in_len = read_compress_length(data_in);
|
||||
if (in_len != srclen)
|
||||
return -EUCLEAN;
|
||||
data_in += LZO_LEN;
|
||||
|
||||
in_len = read_compress_length(data_in);
|
||||
if (in_len != srclen - LZO_LEN * 2) {
|
||||
ret = -EUCLEAN;
|
||||
goto out;
|
||||
}
|
||||
data_in += LZO_LEN;
|
||||
|
||||
out_len = PAGE_SIZE;
|
||||
|
@ -343,11 +343,8 @@ int btrfs_dec_test_first_ordered_pending(struct inode *inode,
|
||||
|
||||
if (entry->bytes_left == 0) {
|
||||
ret = test_and_set_bit(BTRFS_ORDERED_IO_DONE, &entry->flags);
|
||||
/*
|
||||
* Implicit memory barrier after test_and_set_bit
|
||||
*/
|
||||
if (waitqueue_active(&entry->wait))
|
||||
wake_up(&entry->wait);
|
||||
/* test_and_set_bit implies a barrier */
|
||||
cond_wake_up_nomb(&entry->wait);
|
||||
} else {
|
||||
ret = 1;
|
||||
}
|
||||
@ -410,11 +407,8 @@ have_entry:
|
||||
|
||||
if (entry->bytes_left == 0) {
|
||||
ret = test_and_set_bit(BTRFS_ORDERED_IO_DONE, &entry->flags);
|
||||
/*
|
||||
* Implicit memory barrier after test_and_set_bit
|
||||
*/
|
||||
if (waitqueue_active(&entry->wait))
|
||||
wake_up(&entry->wait);
|
||||
/* test_and_set_bit implies a barrier */
|
||||
cond_wake_up_nomb(&entry->wait);
|
||||
} else {
|
||||
ret = 1;
|
||||
}
|
||||
|
@ -166,6 +166,25 @@ static void print_uuid_item(struct extent_buffer *l, unsigned long offset,
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Helper to output refs and locking status of extent buffer. Useful to debug
|
||||
* race condition related problems.
|
||||
*/
|
||||
static void print_eb_refs_lock(struct extent_buffer *eb)
|
||||
{
|
||||
#ifdef CONFIG_BTRFS_DEBUG
|
||||
btrfs_info(eb->fs_info,
|
||||
"refs %u lock (w:%d r:%d bw:%d br:%d sw:%d sr:%d) lock_owner %u current %u",
|
||||
atomic_read(&eb->refs), atomic_read(&eb->write_locks),
|
||||
atomic_read(&eb->read_locks),
|
||||
atomic_read(&eb->blocking_writers),
|
||||
atomic_read(&eb->blocking_readers),
|
||||
atomic_read(&eb->spinning_writers),
|
||||
atomic_read(&eb->spinning_readers),
|
||||
eb->lock_owner, current->pid);
|
||||
#endif
|
||||
}
|
||||
|
||||
void btrfs_print_leaf(struct extent_buffer *l)
|
||||
{
|
||||
struct btrfs_fs_info *fs_info;
|
||||
@ -193,6 +212,7 @@ void btrfs_print_leaf(struct extent_buffer *l)
|
||||
"leaf %llu gen %llu total ptrs %d free space %d owner %llu",
|
||||
btrfs_header_bytenr(l), btrfs_header_generation(l), nr,
|
||||
btrfs_leaf_free_space(fs_info, l), btrfs_header_owner(l));
|
||||
print_eb_refs_lock(l);
|
||||
for (i = 0 ; i < nr ; i++) {
|
||||
item = btrfs_item_nr(i);
|
||||
btrfs_item_key_to_cpu(l, &key, i);
|
||||
@ -347,6 +367,7 @@ void btrfs_print_tree(struct extent_buffer *c, bool follow)
|
||||
btrfs_header_bytenr(c), level, btrfs_header_generation(c),
|
||||
nr, (u32)BTRFS_NODEPTRS_PER_BLOCK(fs_info) - nr,
|
||||
btrfs_header_owner(c));
|
||||
print_eb_refs_lock(c);
|
||||
for (i = 0; i < nr; i++) {
|
||||
btrfs_node_key_to_cpu(c, &key, i);
|
||||
pr_info("\tkey %d (%llu %u %llu) block %llu gen %llu\n",
|
||||
|
@ -1882,8 +1882,8 @@ static int qgroup_update_counters(struct btrfs_fs_info *fs_info,
|
||||
cur_old_count = btrfs_qgroup_get_old_refcnt(qg, seq);
|
||||
cur_new_count = btrfs_qgroup_get_new_refcnt(qg, seq);
|
||||
|
||||
trace_qgroup_update_counters(fs_info, qg->qgroupid,
|
||||
cur_old_count, cur_new_count);
|
||||
trace_qgroup_update_counters(fs_info, qg, cur_old_count,
|
||||
cur_new_count);
|
||||
|
||||
/* Rfer update part */
|
||||
if (cur_old_count == 0 && cur_new_count > 0) {
|
||||
@ -2014,8 +2014,8 @@ btrfs_qgroup_account_extent(struct btrfs_trans_handle *trans,
|
||||
|
||||
BUG_ON(!fs_info->quota_root);
|
||||
|
||||
trace_btrfs_qgroup_account_extent(fs_info, bytenr, num_bytes,
|
||||
nr_old_roots, nr_new_roots);
|
||||
trace_btrfs_qgroup_account_extent(fs_info, trans->transid, bytenr,
|
||||
num_bytes, nr_old_roots, nr_new_roots);
|
||||
|
||||
qgroups = ulist_alloc(GFP_NOFS);
|
||||
if (!qgroups) {
|
||||
@ -2579,6 +2579,21 @@ out:
|
||||
spin_unlock(&fs_info->qgroup_lock);
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if the leaf is the last leaf. Which means all node pointers
|
||||
* are at their last position.
|
||||
*/
|
||||
static bool is_last_leaf(struct btrfs_path *path)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 1; i < BTRFS_MAX_LEVEL && path->nodes[i]; i++) {
|
||||
if (path->slots[i] != btrfs_header_nritems(path->nodes[i]) - 1)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* returns < 0 on error, 0 when more leafs are to be scanned.
|
||||
* returns 1 when done.
|
||||
@ -2590,8 +2605,8 @@ qgroup_rescan_leaf(struct btrfs_fs_info *fs_info, struct btrfs_path *path,
|
||||
struct btrfs_key found;
|
||||
struct extent_buffer *scratch_leaf = NULL;
|
||||
struct ulist *roots = NULL;
|
||||
struct seq_list tree_mod_seq_elem = SEQ_LIST_INIT(tree_mod_seq_elem);
|
||||
u64 num_bytes;
|
||||
bool done;
|
||||
int slot;
|
||||
int ret;
|
||||
|
||||
@ -2620,12 +2635,12 @@ qgroup_rescan_leaf(struct btrfs_fs_info *fs_info, struct btrfs_path *path,
|
||||
mutex_unlock(&fs_info->qgroup_rescan_lock);
|
||||
return ret;
|
||||
}
|
||||
done = is_last_leaf(path);
|
||||
|
||||
btrfs_item_key_to_cpu(path->nodes[0], &found,
|
||||
btrfs_header_nritems(path->nodes[0]) - 1);
|
||||
fs_info->qgroup_rescan_progress.objectid = found.objectid + 1;
|
||||
|
||||
btrfs_get_tree_mod_seq(fs_info, &tree_mod_seq_elem);
|
||||
scratch_leaf = btrfs_clone_extent_buffer(path->nodes[0]);
|
||||
if (!scratch_leaf) {
|
||||
ret = -ENOMEM;
|
||||
@ -2664,8 +2679,9 @@ out:
|
||||
btrfs_tree_read_unlock_blocking(scratch_leaf);
|
||||
free_extent_buffer(scratch_leaf);
|
||||
}
|
||||
btrfs_put_tree_mod_seq(fs_info, &tree_mod_seq_elem);
|
||||
|
||||
if (done && !ret)
|
||||
ret = 1;
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -2681,6 +2697,12 @@ static void btrfs_qgroup_rescan_worker(struct btrfs_work *work)
|
||||
path = btrfs_alloc_path();
|
||||
if (!path)
|
||||
goto out;
|
||||
/*
|
||||
* Rescan should only search for commit root, and any later difference
|
||||
* should be recorded by qgroup
|
||||
*/
|
||||
path->search_commit_root = 1;
|
||||
path->skip_locking = 1;
|
||||
|
||||
err = 0;
|
||||
while (!err && !btrfs_fs_closing(fs_info)) {
|
||||
@ -2760,26 +2782,36 @@ qgroup_rescan_init(struct btrfs_fs_info *fs_info, u64 progress_objectid,
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (!init_flags &&
|
||||
(!(fs_info->qgroup_flags & BTRFS_QGROUP_STATUS_FLAG_RESCAN) ||
|
||||
!(fs_info->qgroup_flags & BTRFS_QGROUP_STATUS_FLAG_ON))) {
|
||||
ret = -EINVAL;
|
||||
goto err;
|
||||
if (!init_flags) {
|
||||
/* we're resuming qgroup rescan at mount time */
|
||||
if (!(fs_info->qgroup_flags & BTRFS_QGROUP_STATUS_FLAG_RESCAN))
|
||||
btrfs_warn(fs_info,
|
||||
"qgroup rescan init failed, qgroup is not enabled");
|
||||
else if (!(fs_info->qgroup_flags & BTRFS_QGROUP_STATUS_FLAG_ON))
|
||||
btrfs_warn(fs_info,
|
||||
"qgroup rescan init failed, qgroup rescan is not queued");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
mutex_lock(&fs_info->qgroup_rescan_lock);
|
||||
spin_lock(&fs_info->qgroup_lock);
|
||||
|
||||
if (init_flags) {
|
||||
if (fs_info->qgroup_flags & BTRFS_QGROUP_STATUS_FLAG_RESCAN)
|
||||
if (fs_info->qgroup_flags & BTRFS_QGROUP_STATUS_FLAG_RESCAN) {
|
||||
btrfs_warn(fs_info,
|
||||
"qgroup rescan is already in progress");
|
||||
ret = -EINPROGRESS;
|
||||
else if (!(fs_info->qgroup_flags & BTRFS_QGROUP_STATUS_FLAG_ON))
|
||||
} else if (!(fs_info->qgroup_flags &
|
||||
BTRFS_QGROUP_STATUS_FLAG_ON)) {
|
||||
btrfs_warn(fs_info,
|
||||
"qgroup rescan init failed, qgroup is not enabled");
|
||||
ret = -EINVAL;
|
||||
}
|
||||
|
||||
if (ret) {
|
||||
spin_unlock(&fs_info->qgroup_lock);
|
||||
mutex_unlock(&fs_info->qgroup_rescan_lock);
|
||||
goto err;
|
||||
return ret;
|
||||
}
|
||||
fs_info->qgroup_flags |= BTRFS_QGROUP_STATUS_FLAG_RESCAN;
|
||||
}
|
||||
@ -2798,13 +2830,6 @@ qgroup_rescan_init(struct btrfs_fs_info *fs_info, u64 progress_objectid,
|
||||
btrfs_init_work(&fs_info->qgroup_rescan_work,
|
||||
btrfs_qgroup_rescan_helper,
|
||||
btrfs_qgroup_rescan_worker, NULL, NULL);
|
||||
|
||||
if (ret) {
|
||||
err:
|
||||
btrfs_info(fs_info, "qgroup_rescan_init failed with %d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -163,6 +163,12 @@ struct btrfs_raid_bio {
|
||||
* bitmap to record which horizontal stripe has data
|
||||
*/
|
||||
unsigned long *dbitmap;
|
||||
|
||||
/* allocated with real_stripes-many pointers for finish_*() calls */
|
||||
void **finish_pointers;
|
||||
|
||||
/* allocated with stripe_npages-many bits for finish_*() calls */
|
||||
unsigned long *finish_pbitmap;
|
||||
};
|
||||
|
||||
static int __raid56_parity_recover(struct btrfs_raid_bio *rbio);
|
||||
@ -981,9 +987,14 @@ static struct btrfs_raid_bio *alloc_rbio(struct btrfs_fs_info *fs_info,
|
||||
int stripe_npages = DIV_ROUND_UP(stripe_len, PAGE_SIZE);
|
||||
void *p;
|
||||
|
||||
rbio = kzalloc(sizeof(*rbio) + num_pages * sizeof(struct page *) * 2 +
|
||||
DIV_ROUND_UP(stripe_npages, BITS_PER_LONG) *
|
||||
sizeof(long), GFP_NOFS);
|
||||
rbio = kzalloc(sizeof(*rbio) +
|
||||
sizeof(*rbio->stripe_pages) * num_pages +
|
||||
sizeof(*rbio->bio_pages) * num_pages +
|
||||
sizeof(*rbio->finish_pointers) * real_stripes +
|
||||
sizeof(*rbio->dbitmap) * BITS_TO_LONGS(stripe_npages) +
|
||||
sizeof(*rbio->finish_pbitmap) *
|
||||
BITS_TO_LONGS(stripe_npages),
|
||||
GFP_NOFS);
|
||||
if (!rbio)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
@ -1005,13 +1016,20 @@ static struct btrfs_raid_bio *alloc_rbio(struct btrfs_fs_info *fs_info,
|
||||
atomic_set(&rbio->stripes_pending, 0);
|
||||
|
||||
/*
|
||||
* the stripe_pages and bio_pages array point to the extra
|
||||
* the stripe_pages, bio_pages, etc arrays point to the extra
|
||||
* memory we allocated past the end of the rbio
|
||||
*/
|
||||
p = rbio + 1;
|
||||
rbio->stripe_pages = p;
|
||||
rbio->bio_pages = p + sizeof(struct page *) * num_pages;
|
||||
rbio->dbitmap = p + sizeof(struct page *) * num_pages * 2;
|
||||
#define CONSUME_ALLOC(ptr, count) do { \
|
||||
ptr = p; \
|
||||
p = (unsigned char *)p + sizeof(*(ptr)) * (count); \
|
||||
} while (0)
|
||||
CONSUME_ALLOC(rbio->stripe_pages, num_pages);
|
||||
CONSUME_ALLOC(rbio->bio_pages, num_pages);
|
||||
CONSUME_ALLOC(rbio->finish_pointers, real_stripes);
|
||||
CONSUME_ALLOC(rbio->dbitmap, BITS_TO_LONGS(stripe_npages));
|
||||
CONSUME_ALLOC(rbio->finish_pbitmap, BITS_TO_LONGS(stripe_npages));
|
||||
#undef CONSUME_ALLOC
|
||||
|
||||
if (bbio->map_type & BTRFS_BLOCK_GROUP_RAID5)
|
||||
nr_data = real_stripes - 1;
|
||||
@ -1180,7 +1198,7 @@ static void index_rbio_pages(struct btrfs_raid_bio *rbio)
|
||||
static noinline void finish_rmw(struct btrfs_raid_bio *rbio)
|
||||
{
|
||||
struct btrfs_bio *bbio = rbio->bbio;
|
||||
void *pointers[rbio->real_stripes];
|
||||
void **pointers = rbio->finish_pointers;
|
||||
int nr_data = rbio->nr_data;
|
||||
int stripe;
|
||||
int pagenr;
|
||||
@ -2350,8 +2368,8 @@ static noinline void finish_parity_scrub(struct btrfs_raid_bio *rbio,
|
||||
int need_check)
|
||||
{
|
||||
struct btrfs_bio *bbio = rbio->bbio;
|
||||
void *pointers[rbio->real_stripes];
|
||||
DECLARE_BITMAP(pbitmap, rbio->stripe_npages);
|
||||
void **pointers = rbio->finish_pointers;
|
||||
unsigned long *pbitmap = rbio->finish_pbitmap;
|
||||
int nr_data = rbio->nr_data;
|
||||
int stripe;
|
||||
int pagenr;
|
||||
|
@ -4299,7 +4299,7 @@ out:
|
||||
return inode;
|
||||
}
|
||||
|
||||
static struct reloc_control *alloc_reloc_control(struct btrfs_fs_info *fs_info)
|
||||
static struct reloc_control *alloc_reloc_control(void)
|
||||
{
|
||||
struct reloc_control *rc;
|
||||
|
||||
@ -4344,7 +4344,7 @@ static void describe_relocation(struct btrfs_fs_info *fs_info,
|
||||
DESCRIBE_FLAG(RAID5, "raid5");
|
||||
DESCRIBE_FLAG(RAID6, "raid6");
|
||||
if (flags)
|
||||
snprintf(buf, buf - bp + sizeof(buf), "|0x%llx", flags);
|
||||
snprintf(bp, buf - bp + sizeof(buf), "|0x%llx", flags);
|
||||
#undef DESCRIBE_FLAG
|
||||
}
|
||||
|
||||
@ -4366,7 +4366,7 @@ int btrfs_relocate_block_group(struct btrfs_fs_info *fs_info, u64 group_start)
|
||||
int rw = 0;
|
||||
int err = 0;
|
||||
|
||||
rc = alloc_reloc_control(fs_info);
|
||||
rc = alloc_reloc_control();
|
||||
if (!rc)
|
||||
return -ENOMEM;
|
||||
|
||||
@ -4562,7 +4562,7 @@ int btrfs_recover_relocation(struct btrfs_root *root)
|
||||
if (list_empty(&reloc_roots))
|
||||
goto out;
|
||||
|
||||
rc = alloc_reloc_control(fs_info);
|
||||
rc = alloc_reloc_control();
|
||||
if (!rc) {
|
||||
err = -ENOMEM;
|
||||
goto out;
|
||||
|
@ -3984,6 +3984,7 @@ int scrub_enumerate_chunks(struct scrub_ctx *sctx,
|
||||
spin_lock(&fs_info->unused_bgs_lock);
|
||||
if (list_empty(&cache->bg_list)) {
|
||||
btrfs_get_block_group(cache);
|
||||
trace_btrfs_add_unused_block_group(cache);
|
||||
list_add_tail(&cache->bg_list,
|
||||
&fs_info->unused_bgs);
|
||||
}
|
||||
|
@ -235,6 +235,7 @@ struct orphan_dir_info {
|
||||
struct rb_node node;
|
||||
u64 ino;
|
||||
u64 gen;
|
||||
u64 last_dir_index_offset;
|
||||
};
|
||||
|
||||
struct name_cache_entry {
|
||||
@ -2844,12 +2845,6 @@ add_orphan_dir_info(struct send_ctx *sctx, u64 dir_ino)
|
||||
struct rb_node *parent = NULL;
|
||||
struct orphan_dir_info *entry, *odi;
|
||||
|
||||
odi = kmalloc(sizeof(*odi), GFP_KERNEL);
|
||||
if (!odi)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
odi->ino = dir_ino;
|
||||
odi->gen = 0;
|
||||
|
||||
while (*p) {
|
||||
parent = *p;
|
||||
entry = rb_entry(parent, struct orphan_dir_info, node);
|
||||
@ -2858,11 +2853,17 @@ add_orphan_dir_info(struct send_ctx *sctx, u64 dir_ino)
|
||||
} else if (dir_ino > entry->ino) {
|
||||
p = &(*p)->rb_right;
|
||||
} else {
|
||||
kfree(odi);
|
||||
return entry;
|
||||
}
|
||||
}
|
||||
|
||||
odi = kmalloc(sizeof(*odi), GFP_KERNEL);
|
||||
if (!odi)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
odi->ino = dir_ino;
|
||||
odi->gen = 0;
|
||||
odi->last_dir_index_offset = 0;
|
||||
|
||||
rb_link_node(&odi->node, parent, p);
|
||||
rb_insert_color(&odi->node, &sctx->orphan_dirs);
|
||||
return odi;
|
||||
@ -2917,6 +2918,7 @@ static int can_rmdir(struct send_ctx *sctx, u64 dir, u64 dir_gen,
|
||||
struct btrfs_key found_key;
|
||||
struct btrfs_key loc;
|
||||
struct btrfs_dir_item *di;
|
||||
struct orphan_dir_info *odi = NULL;
|
||||
|
||||
/*
|
||||
* Don't try to rmdir the top/root subvolume dir.
|
||||
@ -2931,6 +2933,11 @@ static int can_rmdir(struct send_ctx *sctx, u64 dir, u64 dir_gen,
|
||||
key.objectid = dir;
|
||||
key.type = BTRFS_DIR_INDEX_KEY;
|
||||
key.offset = 0;
|
||||
|
||||
odi = get_orphan_dir_info(sctx, dir);
|
||||
if (odi)
|
||||
key.offset = odi->last_dir_index_offset;
|
||||
|
||||
ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
@ -2958,30 +2965,33 @@ static int can_rmdir(struct send_ctx *sctx, u64 dir, u64 dir_gen,
|
||||
|
||||
dm = get_waiting_dir_move(sctx, loc.objectid);
|
||||
if (dm) {
|
||||
struct orphan_dir_info *odi;
|
||||
|
||||
odi = add_orphan_dir_info(sctx, dir);
|
||||
if (IS_ERR(odi)) {
|
||||
ret = PTR_ERR(odi);
|
||||
goto out;
|
||||
}
|
||||
odi->gen = dir_gen;
|
||||
odi->last_dir_index_offset = found_key.offset;
|
||||
dm->rmdir_ino = dir;
|
||||
ret = 0;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (loc.objectid > send_progress) {
|
||||
struct orphan_dir_info *odi;
|
||||
|
||||
odi = get_orphan_dir_info(sctx, dir);
|
||||
free_orphan_dir_info(sctx, odi);
|
||||
odi = add_orphan_dir_info(sctx, dir);
|
||||
if (IS_ERR(odi)) {
|
||||
ret = PTR_ERR(odi);
|
||||
goto out;
|
||||
}
|
||||
odi->gen = dir_gen;
|
||||
odi->last_dir_index_offset = found_key.offset;
|
||||
ret = 0;
|
||||
goto out;
|
||||
}
|
||||
|
||||
path->slots[0]++;
|
||||
}
|
||||
free_orphan_dir_info(sctx, odi);
|
||||
|
||||
ret = 1;
|
||||
|
||||
@ -3259,13 +3269,16 @@ static int apply_dir_move(struct send_ctx *sctx, struct pending_dir_move *pm)
|
||||
|
||||
if (rmdir_ino) {
|
||||
struct orphan_dir_info *odi;
|
||||
u64 gen;
|
||||
|
||||
odi = get_orphan_dir_info(sctx, rmdir_ino);
|
||||
if (!odi) {
|
||||
/* already deleted */
|
||||
goto finish;
|
||||
}
|
||||
ret = can_rmdir(sctx, rmdir_ino, odi->gen, sctx->cur_ino);
|
||||
gen = odi->gen;
|
||||
|
||||
ret = can_rmdir(sctx, rmdir_ino, gen, sctx->cur_ino);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
if (!ret)
|
||||
@ -3276,13 +3289,12 @@ static int apply_dir_move(struct send_ctx *sctx, struct pending_dir_move *pm)
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
ret = get_cur_path(sctx, rmdir_ino, odi->gen, name);
|
||||
ret = get_cur_path(sctx, rmdir_ino, gen, name);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
ret = send_rmdir(sctx, name);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
free_orphan_dir_info(sctx, odi);
|
||||
}
|
||||
|
||||
finish:
|
||||
@ -6454,7 +6466,7 @@ static void btrfs_root_dec_send_in_progress(struct btrfs_root* root)
|
||||
*/
|
||||
if (root->send_in_progress < 0)
|
||||
btrfs_err(root->fs_info,
|
||||
"send_in_progres unbalanced %d root %llu",
|
||||
"send_in_progress unbalanced %d root %llu",
|
||||
root->send_in_progress, root->root_key.objectid);
|
||||
spin_unlock(&root->root_item_lock);
|
||||
}
|
||||
|
@ -323,6 +323,7 @@ enum {
|
||||
Opt_ssd, Opt_nossd,
|
||||
Opt_ssd_spread, Opt_nossd_spread,
|
||||
Opt_subvol,
|
||||
Opt_subvol_empty,
|
||||
Opt_subvolid,
|
||||
Opt_thread_pool,
|
||||
Opt_treelog, Opt_notreelog,
|
||||
@ -388,6 +389,7 @@ static const match_table_t tokens = {
|
||||
{Opt_ssd_spread, "ssd_spread"},
|
||||
{Opt_nossd_spread, "nossd_spread"},
|
||||
{Opt_subvol, "subvol=%s"},
|
||||
{Opt_subvol_empty, "subvol="},
|
||||
{Opt_subvolid, "subvolid=%s"},
|
||||
{Opt_thread_pool, "thread_pool=%u"},
|
||||
{Opt_treelog, "treelog"},
|
||||
@ -461,6 +463,7 @@ int btrfs_parse_options(struct btrfs_fs_info *info, char *options,
|
||||
btrfs_set_opt(info->mount_opt, DEGRADED);
|
||||
break;
|
||||
case Opt_subvol:
|
||||
case Opt_subvol_empty:
|
||||
case Opt_subvolid:
|
||||
case Opt_subvolrootid:
|
||||
case Opt_device:
|
||||
@ -1782,10 +1785,8 @@ static int btrfs_remount(struct super_block *sb, int *flags, char *data)
|
||||
}
|
||||
|
||||
ret = btrfs_parse_options(fs_info, data, *flags);
|
||||
if (ret) {
|
||||
ret = -EINVAL;
|
||||
if (ret)
|
||||
goto restore;
|
||||
}
|
||||
|
||||
btrfs_remount_begin(fs_info, old_opts, *flags);
|
||||
btrfs_resize_thread_pool(fs_info,
|
||||
|
@ -210,12 +210,42 @@ static struct attribute *btrfs_supported_feature_attrs[] = {
|
||||
NULL
|
||||
};
|
||||
|
||||
/*
|
||||
* Features which depend on feature bits and may differ between each fs.
|
||||
*
|
||||
* /sys/fs/btrfs/features lists all available features of this kernel while
|
||||
* /sys/fs/btrfs/UUID/features shows features of the fs which are enabled or
|
||||
* can be changed online.
|
||||
*/
|
||||
static const struct attribute_group btrfs_feature_attr_group = {
|
||||
.name = "features",
|
||||
.is_visible = btrfs_feature_visible,
|
||||
.attrs = btrfs_supported_feature_attrs,
|
||||
};
|
||||
|
||||
static ssize_t rmdir_subvol_show(struct kobject *kobj,
|
||||
struct kobj_attribute *ka, char *buf)
|
||||
{
|
||||
return snprintf(buf, PAGE_SIZE, "0\n");
|
||||
}
|
||||
BTRFS_ATTR(static_feature, rmdir_subvol, rmdir_subvol_show);
|
||||
|
||||
static struct attribute *btrfs_supported_static_feature_attrs[] = {
|
||||
BTRFS_ATTR_PTR(static_feature, rmdir_subvol),
|
||||
NULL
|
||||
};
|
||||
|
||||
/*
|
||||
* Features which only depend on kernel version.
|
||||
*
|
||||
* These are listed in /sys/fs/btrfs/features along with
|
||||
* btrfs_feature_attr_group
|
||||
*/
|
||||
static const struct attribute_group btrfs_static_feature_attr_group = {
|
||||
.name = "features",
|
||||
.attrs = btrfs_supported_static_feature_attrs,
|
||||
};
|
||||
|
||||
static ssize_t btrfs_show_u64(u64 *value_ptr, spinlock_t *lock, char *buf)
|
||||
{
|
||||
u64 val;
|
||||
@ -514,10 +544,11 @@ static inline struct btrfs_fs_info *to_fs_info(struct kobject *kobj)
|
||||
}
|
||||
|
||||
#define NUM_FEATURE_BITS 64
|
||||
static char btrfs_unknown_feature_names[3][NUM_FEATURE_BITS][13];
|
||||
static struct btrfs_feature_attr btrfs_feature_attrs[3][NUM_FEATURE_BITS];
|
||||
#define BTRFS_FEATURE_NAME_MAX 13
|
||||
static char btrfs_unknown_feature_names[FEAT_MAX][NUM_FEATURE_BITS][BTRFS_FEATURE_NAME_MAX];
|
||||
static struct btrfs_feature_attr btrfs_feature_attrs[FEAT_MAX][NUM_FEATURE_BITS];
|
||||
|
||||
static const u64 supported_feature_masks[3] = {
|
||||
static const u64 supported_feature_masks[FEAT_MAX] = {
|
||||
[FEAT_COMPAT] = BTRFS_FEATURE_COMPAT_SUPP,
|
||||
[FEAT_COMPAT_RO] = BTRFS_FEATURE_COMPAT_RO_SUPP,
|
||||
[FEAT_INCOMPAT] = BTRFS_FEATURE_INCOMPAT_SUPP,
|
||||
@ -589,7 +620,7 @@ void btrfs_sysfs_remove_fsid(struct btrfs_fs_devices *fs_devs)
|
||||
return;
|
||||
}
|
||||
|
||||
list_for_each_entry(fs_devs, fs_uuids, list) {
|
||||
list_for_each_entry(fs_devs, fs_uuids, fs_list) {
|
||||
__btrfs_sysfs_remove_fsid(fs_devs);
|
||||
}
|
||||
}
|
||||
@ -609,7 +640,7 @@ void btrfs_sysfs_remove_mounted(struct btrfs_fs_info *fs_info)
|
||||
btrfs_sysfs_rm_device_link(fs_info->fs_devices, NULL);
|
||||
}
|
||||
|
||||
const char * const btrfs_feature_set_names[3] = {
|
||||
const char * const btrfs_feature_set_names[FEAT_MAX] = {
|
||||
[FEAT_COMPAT] = "compat",
|
||||
[FEAT_COMPAT_RO] = "compat_ro",
|
||||
[FEAT_INCOMPAT] = "incompat",
|
||||
@ -673,7 +704,7 @@ static void init_feature_attrs(void)
|
||||
if (fa->kobj_attr.attr.name)
|
||||
continue;
|
||||
|
||||
snprintf(name, 13, "%s:%u",
|
||||
snprintf(name, BTRFS_FEATURE_NAME_MAX, "%s:%u",
|
||||
btrfs_feature_set_names[set], i);
|
||||
|
||||
fa->kobj_attr.attr.name = name;
|
||||
@ -900,8 +931,15 @@ int __init btrfs_init_sysfs(void)
|
||||
ret = sysfs_create_group(&btrfs_kset->kobj, &btrfs_feature_attr_group);
|
||||
if (ret)
|
||||
goto out2;
|
||||
ret = sysfs_merge_group(&btrfs_kset->kobj,
|
||||
&btrfs_static_feature_attr_group);
|
||||
if (ret)
|
||||
goto out_remove_group;
|
||||
|
||||
return 0;
|
||||
|
||||
out_remove_group:
|
||||
sysfs_remove_group(&btrfs_kset->kobj, &btrfs_feature_attr_group);
|
||||
out2:
|
||||
debugfs_remove_recursive(btrfs_debugfs_root_dentry);
|
||||
out1:
|
||||
@ -912,6 +950,8 @@ out1:
|
||||
|
||||
void __cold btrfs_exit_sysfs(void)
|
||||
{
|
||||
sysfs_unmerge_group(&btrfs_kset->kobj,
|
||||
&btrfs_static_feature_attr_group);
|
||||
sysfs_remove_group(&btrfs_kset->kobj, &btrfs_feature_attr_group);
|
||||
kset_unregister(btrfs_kset);
|
||||
debugfs_remove_recursive(btrfs_debugfs_root_dentry);
|
||||
|
@ -9,7 +9,7 @@
|
||||
extern u64 btrfs_debugfs_test;
|
||||
|
||||
enum btrfs_feature_set {
|
||||
FEAT_COMPAT,
|
||||
FEAT_COMPAT = 0,
|
||||
FEAT_COMPAT_RO,
|
||||
FEAT_INCOMPAT,
|
||||
FEAT_MAX
|
||||
@ -77,7 +77,7 @@ attr_to_btrfs_feature_attr(struct attribute *attr)
|
||||
}
|
||||
|
||||
char *btrfs_printable_features(enum btrfs_feature_set set, u64 flags);
|
||||
extern const char * const btrfs_feature_set_names[3];
|
||||
extern const char * const btrfs_feature_set_names[FEAT_MAX];
|
||||
extern struct kobj_type space_info_ktype;
|
||||
extern struct kobj_type btrfs_raid_ktype;
|
||||
int btrfs_sysfs_add_device_link(struct btrfs_fs_devices *fs_devices,
|
||||
|
@ -219,11 +219,13 @@ void btrfs_free_dummy_block_group(struct btrfs_block_group_cache *cache)
|
||||
kfree(cache);
|
||||
}
|
||||
|
||||
void btrfs_init_dummy_trans(struct btrfs_trans_handle *trans)
|
||||
void btrfs_init_dummy_trans(struct btrfs_trans_handle *trans,
|
||||
struct btrfs_fs_info *fs_info)
|
||||
{
|
||||
memset(trans, 0, sizeof(*trans));
|
||||
trans->transid = 1;
|
||||
trans->type = __TRANS_DUMMY;
|
||||
trans->fs_info = fs_info;
|
||||
}
|
||||
|
||||
int btrfs_run_sanity_tests(void)
|
||||
|
@ -9,7 +9,8 @@
|
||||
#ifdef CONFIG_BTRFS_FS_RUN_SANITY_TESTS
|
||||
int btrfs_run_sanity_tests(void);
|
||||
|
||||
#define test_msg(fmt, ...) pr_info("BTRFS: selftest: " fmt, ##__VA_ARGS__)
|
||||
#define test_msg(fmt, ...) pr_info("BTRFS: selftest: " fmt "\n", ##__VA_ARGS__)
|
||||
#define test_err(fmt, ...) pr_err("BTRFS: selftest: " fmt "\n", ##__VA_ARGS__)
|
||||
|
||||
struct btrfs_root;
|
||||
struct btrfs_trans_handle;
|
||||
@ -28,7 +29,8 @@ void btrfs_free_dummy_root(struct btrfs_root *root);
|
||||
struct btrfs_block_group_cache *
|
||||
btrfs_alloc_dummy_block_group(struct btrfs_fs_info *fs_info, unsigned long length);
|
||||
void btrfs_free_dummy_block_group(struct btrfs_block_group_cache *cache);
|
||||
void btrfs_init_dummy_trans(struct btrfs_trans_handle *trans);
|
||||
void btrfs_init_dummy_trans(struct btrfs_trans_handle *trans,
|
||||
struct btrfs_fs_info *fs_info);
|
||||
#else
|
||||
static inline int btrfs_run_sanity_tests(void)
|
||||
{
|
||||
|
@ -26,31 +26,31 @@ static int test_btrfs_split_item(u32 sectorsize, u32 nodesize)
|
||||
u32 value_len = strlen(value);
|
||||
int ret = 0;
|
||||
|
||||
test_msg("Running btrfs_split_item tests\n");
|
||||
test_msg("running btrfs_split_item tests");
|
||||
|
||||
fs_info = btrfs_alloc_dummy_fs_info(nodesize, sectorsize);
|
||||
if (!fs_info) {
|
||||
test_msg("Could not allocate fs_info\n");
|
||||
test_err("could not allocate fs_info");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
root = btrfs_alloc_dummy_root(fs_info);
|
||||
if (IS_ERR(root)) {
|
||||
test_msg("Could not allocate root\n");
|
||||
test_err("could not allocate root");
|
||||
ret = PTR_ERR(root);
|
||||
goto out;
|
||||
}
|
||||
|
||||
path = btrfs_alloc_path();
|
||||
if (!path) {
|
||||
test_msg("Could not allocate path\n");
|
||||
test_err("could not allocate path");
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
path->nodes[0] = eb = alloc_dummy_extent_buffer(fs_info, nodesize);
|
||||
if (!eb) {
|
||||
test_msg("Could not allocate dummy buffer\n");
|
||||
test_err("could not allocate dummy buffer");
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
@ -75,7 +75,7 @@ static int test_btrfs_split_item(u32 sectorsize, u32 nodesize)
|
||||
*/
|
||||
ret = btrfs_split_item(NULL, root, path, &key, 17);
|
||||
if (ret) {
|
||||
test_msg("Split item failed %d\n", ret);
|
||||
test_err("split item failed %d", ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
@ -86,14 +86,14 @@ static int test_btrfs_split_item(u32 sectorsize, u32 nodesize)
|
||||
btrfs_item_key_to_cpu(eb, &key, 0);
|
||||
if (key.objectid != 0 || key.type != BTRFS_EXTENT_CSUM_KEY ||
|
||||
key.offset != 0) {
|
||||
test_msg("Invalid key at slot 0\n");
|
||||
test_err("invalid key at slot 0");
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
item = btrfs_item_nr(0);
|
||||
if (btrfs_item_size(eb, item) != strlen(split1)) {
|
||||
test_msg("Invalid len in the first split\n");
|
||||
test_err("invalid len in the first split");
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
@ -101,8 +101,8 @@ static int test_btrfs_split_item(u32 sectorsize, u32 nodesize)
|
||||
read_extent_buffer(eb, buf, btrfs_item_ptr_offset(eb, 0),
|
||||
strlen(split1));
|
||||
if (memcmp(buf, split1, strlen(split1))) {
|
||||
test_msg("Data in the buffer doesn't match what it should "
|
||||
"in the first split have='%.*s' want '%s'\n",
|
||||
test_err(
|
||||
"data in the buffer doesn't match what it should in the first split have='%.*s' want '%s'",
|
||||
(int)strlen(split1), buf, split1);
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
@ -111,14 +111,14 @@ static int test_btrfs_split_item(u32 sectorsize, u32 nodesize)
|
||||
btrfs_item_key_to_cpu(eb, &key, 1);
|
||||
if (key.objectid != 0 || key.type != BTRFS_EXTENT_CSUM_KEY ||
|
||||
key.offset != 3) {
|
||||
test_msg("Invalid key at slot 1\n");
|
||||
test_err("invalid key at slot 1");
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
item = btrfs_item_nr(1);
|
||||
if (btrfs_item_size(eb, item) != strlen(split2)) {
|
||||
test_msg("Invalid len in the second split\n");
|
||||
test_err("invalid len in the second split");
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
@ -126,8 +126,8 @@ static int test_btrfs_split_item(u32 sectorsize, u32 nodesize)
|
||||
read_extent_buffer(eb, buf, btrfs_item_ptr_offset(eb, 1),
|
||||
strlen(split2));
|
||||
if (memcmp(buf, split2, strlen(split2))) {
|
||||
test_msg("Data in the buffer doesn't match what it should "
|
||||
"in the second split\n");
|
||||
test_err(
|
||||
"data in the buffer doesn't match what it should in the second split");
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
@ -136,21 +136,21 @@ static int test_btrfs_split_item(u32 sectorsize, u32 nodesize)
|
||||
/* Do it again so we test memmoving the other items in the leaf */
|
||||
ret = btrfs_split_item(NULL, root, path, &key, 4);
|
||||
if (ret) {
|
||||
test_msg("Second split item failed %d\n", ret);
|
||||
test_err("second split item failed %d", ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
btrfs_item_key_to_cpu(eb, &key, 0);
|
||||
if (key.objectid != 0 || key.type != BTRFS_EXTENT_CSUM_KEY ||
|
||||
key.offset != 0) {
|
||||
test_msg("Invalid key at slot 0\n");
|
||||
test_err("invalid key at slot 0");
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
item = btrfs_item_nr(0);
|
||||
if (btrfs_item_size(eb, item) != strlen(split3)) {
|
||||
test_msg("Invalid len in the first split\n");
|
||||
test_err("invalid len in the first split");
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
@ -158,8 +158,8 @@ static int test_btrfs_split_item(u32 sectorsize, u32 nodesize)
|
||||
read_extent_buffer(eb, buf, btrfs_item_ptr_offset(eb, 0),
|
||||
strlen(split3));
|
||||
if (memcmp(buf, split3, strlen(split3))) {
|
||||
test_msg("Data in the buffer doesn't match what it should "
|
||||
"in the third split");
|
||||
test_err(
|
||||
"data in the buffer doesn't match what it should in the third split");
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
@ -167,14 +167,14 @@ static int test_btrfs_split_item(u32 sectorsize, u32 nodesize)
|
||||
btrfs_item_key_to_cpu(eb, &key, 1);
|
||||
if (key.objectid != 0 || key.type != BTRFS_EXTENT_CSUM_KEY ||
|
||||
key.offset != 1) {
|
||||
test_msg("Invalid key at slot 1\n");
|
||||
test_err("invalid key at slot 1");
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
item = btrfs_item_nr(1);
|
||||
if (btrfs_item_size(eb, item) != strlen(split4)) {
|
||||
test_msg("Invalid len in the second split\n");
|
||||
test_err("invalid len in the second split");
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
@ -182,8 +182,8 @@ static int test_btrfs_split_item(u32 sectorsize, u32 nodesize)
|
||||
read_extent_buffer(eb, buf, btrfs_item_ptr_offset(eb, 1),
|
||||
strlen(split4));
|
||||
if (memcmp(buf, split4, strlen(split4))) {
|
||||
test_msg("Data in the buffer doesn't match what it should "
|
||||
"in the fourth split\n");
|
||||
test_err(
|
||||
"data in the buffer doesn't match what it should in the fourth split");
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
@ -191,14 +191,14 @@ static int test_btrfs_split_item(u32 sectorsize, u32 nodesize)
|
||||
btrfs_item_key_to_cpu(eb, &key, 2);
|
||||
if (key.objectid != 0 || key.type != BTRFS_EXTENT_CSUM_KEY ||
|
||||
key.offset != 3) {
|
||||
test_msg("Invalid key at slot 2\n");
|
||||
test_err("invalid key at slot 2");
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
item = btrfs_item_nr(2);
|
||||
if (btrfs_item_size(eb, item) != strlen(split2)) {
|
||||
test_msg("Invalid len in the second split\n");
|
||||
test_err("invalid len in the second split");
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
@ -206,8 +206,8 @@ static int test_btrfs_split_item(u32 sectorsize, u32 nodesize)
|
||||
read_extent_buffer(eb, buf, btrfs_item_ptr_offset(eb, 2),
|
||||
strlen(split2));
|
||||
if (memcmp(buf, split2, strlen(split2))) {
|
||||
test_msg("Data in the buffer doesn't match what it should "
|
||||
"in the last chunk\n");
|
||||
test_err(
|
||||
"data in the buffer doesn't match what it should in the last chunk");
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
@ -220,6 +220,6 @@ out:
|
||||
|
||||
int btrfs_test_extent_buffer_operations(u32 sectorsize, u32 nodesize)
|
||||
{
|
||||
test_msg("Running extent buffer operation tests\n");
|
||||
test_msg("running extent buffer operation tests");
|
||||
return test_btrfs_split_item(sectorsize, nodesize);
|
||||
}
|
||||
|
@ -46,7 +46,9 @@ static noinline int process_page_range(struct inode *inode, u64 start, u64 end,
|
||||
cond_resched();
|
||||
loops++;
|
||||
if (loops > 100000) {
|
||||
printk(KERN_ERR "stuck in a loop, start %Lu, end %Lu, nr_pages %lu, ret %d\n", start, end, nr_pages, ret);
|
||||
printk(KERN_ERR
|
||||
"stuck in a loop, start %llu, end %llu, nr_pages %lu, ret %d\n",
|
||||
start, end, nr_pages, ret);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -66,11 +68,11 @@ static int test_find_delalloc(u32 sectorsize)
|
||||
u64 found;
|
||||
int ret = -EINVAL;
|
||||
|
||||
test_msg("Running find delalloc tests\n");
|
||||
test_msg("running find delalloc tests");
|
||||
|
||||
inode = btrfs_new_test_inode();
|
||||
if (!inode) {
|
||||
test_msg("Failed to allocate test inode\n");
|
||||
test_err("failed to allocate test inode");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
@ -84,7 +86,7 @@ static int test_find_delalloc(u32 sectorsize)
|
||||
for (index = 0; index < (total_dirty >> PAGE_SHIFT); index++) {
|
||||
page = find_or_create_page(inode->i_mapping, index, GFP_KERNEL);
|
||||
if (!page) {
|
||||
test_msg("Failed to allocate test page\n");
|
||||
test_err("failed to allocate test page");
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
@ -107,11 +109,11 @@ static int test_find_delalloc(u32 sectorsize)
|
||||
found = find_lock_delalloc_range(inode, &tmp, locked_page, &start,
|
||||
&end, max_bytes);
|
||||
if (!found) {
|
||||
test_msg("Should have found at least one delalloc\n");
|
||||
test_err("should have found at least one delalloc");
|
||||
goto out_bits;
|
||||
}
|
||||
if (start != 0 || end != (sectorsize - 1)) {
|
||||
test_msg("Expected start 0 end %u, got start %llu end %llu\n",
|
||||
test_err("expected start 0 end %u, got start %llu end %llu",
|
||||
sectorsize - 1, start, end);
|
||||
goto out_bits;
|
||||
}
|
||||
@ -129,7 +131,7 @@ static int test_find_delalloc(u32 sectorsize)
|
||||
locked_page = find_lock_page(inode->i_mapping,
|
||||
test_start >> PAGE_SHIFT);
|
||||
if (!locked_page) {
|
||||
test_msg("Couldn't find the locked page\n");
|
||||
test_err("couldn't find the locked page");
|
||||
goto out_bits;
|
||||
}
|
||||
set_extent_delalloc(&tmp, sectorsize, max_bytes - 1, 0, NULL);
|
||||
@ -138,17 +140,17 @@ static int test_find_delalloc(u32 sectorsize)
|
||||
found = find_lock_delalloc_range(inode, &tmp, locked_page, &start,
|
||||
&end, max_bytes);
|
||||
if (!found) {
|
||||
test_msg("Couldn't find delalloc in our range\n");
|
||||
test_err("couldn't find delalloc in our range");
|
||||
goto out_bits;
|
||||
}
|
||||
if (start != test_start || end != max_bytes - 1) {
|
||||
test_msg("Expected start %Lu end %Lu, got start %Lu, end "
|
||||
"%Lu\n", test_start, max_bytes - 1, start, end);
|
||||
test_err("expected start %llu end %llu, got start %llu, end %llu",
|
||||
test_start, max_bytes - 1, start, end);
|
||||
goto out_bits;
|
||||
}
|
||||
if (process_page_range(inode, start, end,
|
||||
PROCESS_TEST_LOCKED | PROCESS_UNLOCK)) {
|
||||
test_msg("There were unlocked pages in the range\n");
|
||||
test_err("there were unlocked pages in the range");
|
||||
goto out_bits;
|
||||
}
|
||||
unlock_extent(&tmp, start, end);
|
||||
@ -164,7 +166,7 @@ static int test_find_delalloc(u32 sectorsize)
|
||||
locked_page = find_lock_page(inode->i_mapping, test_start >>
|
||||
PAGE_SHIFT);
|
||||
if (!locked_page) {
|
||||
test_msg("Couldn't find the locked page\n");
|
||||
test_err("couldn't find the locked page");
|
||||
goto out_bits;
|
||||
}
|
||||
start = test_start;
|
||||
@ -172,11 +174,11 @@ static int test_find_delalloc(u32 sectorsize)
|
||||
found = find_lock_delalloc_range(inode, &tmp, locked_page, &start,
|
||||
&end, max_bytes);
|
||||
if (found) {
|
||||
test_msg("Found range when we shouldn't have\n");
|
||||
test_err("found range when we shouldn't have");
|
||||
goto out_bits;
|
||||
}
|
||||
if (end != (u64)-1) {
|
||||
test_msg("Did not return the proper end offset\n");
|
||||
test_err("did not return the proper end offset");
|
||||
goto out_bits;
|
||||
}
|
||||
|
||||
@ -193,17 +195,17 @@ static int test_find_delalloc(u32 sectorsize)
|
||||
found = find_lock_delalloc_range(inode, &tmp, locked_page, &start,
|
||||
&end, max_bytes);
|
||||
if (!found) {
|
||||
test_msg("Didn't find our range\n");
|
||||
test_err("didn't find our range");
|
||||
goto out_bits;
|
||||
}
|
||||
if (start != test_start || end != total_dirty - 1) {
|
||||
test_msg("Expected start %Lu end %Lu, got start %Lu end %Lu\n",
|
||||
test_err("expected start %llu end %llu, got start %llu end %llu",
|
||||
test_start, total_dirty - 1, start, end);
|
||||
goto out_bits;
|
||||
}
|
||||
if (process_page_range(inode, start, end,
|
||||
PROCESS_TEST_LOCKED | PROCESS_UNLOCK)) {
|
||||
test_msg("Pages in range were not all locked\n");
|
||||
test_err("pages in range were not all locked");
|
||||
goto out_bits;
|
||||
}
|
||||
unlock_extent(&tmp, start, end);
|
||||
@ -215,7 +217,7 @@ static int test_find_delalloc(u32 sectorsize)
|
||||
page = find_get_page(inode->i_mapping,
|
||||
(max_bytes + SZ_1M) >> PAGE_SHIFT);
|
||||
if (!page) {
|
||||
test_msg("Couldn't find our page\n");
|
||||
test_err("couldn't find our page");
|
||||
goto out_bits;
|
||||
}
|
||||
ClearPageDirty(page);
|
||||
@ -234,18 +236,17 @@ static int test_find_delalloc(u32 sectorsize)
|
||||
found = find_lock_delalloc_range(inode, &tmp, locked_page, &start,
|
||||
&end, max_bytes);
|
||||
if (!found) {
|
||||
test_msg("Didn't find our range\n");
|
||||
test_err("didn't find our range");
|
||||
goto out_bits;
|
||||
}
|
||||
if (start != test_start && end != test_start + PAGE_SIZE - 1) {
|
||||
test_msg("Expected start %Lu end %Lu, got start %Lu end %Lu\n",
|
||||
test_start, test_start + PAGE_SIZE - 1, start,
|
||||
end);
|
||||
test_err("expected start %llu end %llu, got start %llu end %llu",
|
||||
test_start, test_start + PAGE_SIZE - 1, start, end);
|
||||
goto out_bits;
|
||||
}
|
||||
if (process_page_range(inode, start, end, PROCESS_TEST_LOCKED |
|
||||
PROCESS_UNLOCK)) {
|
||||
test_msg("Pages in range were not all locked\n");
|
||||
test_err("pages in range were not all locked");
|
||||
goto out_bits;
|
||||
}
|
||||
ret = 0;
|
||||
@ -271,14 +272,14 @@ static int check_eb_bitmap(unsigned long *bitmap, struct extent_buffer *eb,
|
||||
bit = !!test_bit(i, bitmap);
|
||||
bit1 = !!extent_buffer_test_bit(eb, 0, i);
|
||||
if (bit1 != bit) {
|
||||
test_msg("Bits do not match\n");
|
||||
test_err("bits do not match");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
bit1 = !!extent_buffer_test_bit(eb, i / BITS_PER_BYTE,
|
||||
i % BITS_PER_BYTE);
|
||||
if (bit1 != bit) {
|
||||
test_msg("Offset bits do not match\n");
|
||||
test_err("offset bits do not match");
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
@ -295,7 +296,7 @@ static int __test_eb_bitmaps(unsigned long *bitmap, struct extent_buffer *eb,
|
||||
memset(bitmap, 0, len);
|
||||
memzero_extent_buffer(eb, 0, len);
|
||||
if (memcmp_extent_buffer(eb, bitmap, 0, len) != 0) {
|
||||
test_msg("Bitmap was not zeroed\n");
|
||||
test_err("bitmap was not zeroed");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@ -303,7 +304,7 @@ static int __test_eb_bitmaps(unsigned long *bitmap, struct extent_buffer *eb,
|
||||
extent_buffer_bitmap_set(eb, 0, 0, len * BITS_PER_BYTE);
|
||||
ret = check_eb_bitmap(bitmap, eb, len);
|
||||
if (ret) {
|
||||
test_msg("Setting all bits failed\n");
|
||||
test_err("setting all bits failed");
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -311,7 +312,7 @@ static int __test_eb_bitmaps(unsigned long *bitmap, struct extent_buffer *eb,
|
||||
extent_buffer_bitmap_clear(eb, 0, 0, len * BITS_PER_BYTE);
|
||||
ret = check_eb_bitmap(bitmap, eb, len);
|
||||
if (ret) {
|
||||
test_msg("Clearing all bits failed\n");
|
||||
test_err("clearing all bits failed");
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -324,7 +325,7 @@ static int __test_eb_bitmaps(unsigned long *bitmap, struct extent_buffer *eb,
|
||||
sizeof(long) * BITS_PER_BYTE);
|
||||
ret = check_eb_bitmap(bitmap, eb, len);
|
||||
if (ret) {
|
||||
test_msg("Setting straddling pages failed\n");
|
||||
test_err("setting straddling pages failed");
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -337,7 +338,7 @@ static int __test_eb_bitmaps(unsigned long *bitmap, struct extent_buffer *eb,
|
||||
sizeof(long) * BITS_PER_BYTE);
|
||||
ret = check_eb_bitmap(bitmap, eb, len);
|
||||
if (ret) {
|
||||
test_msg("Clearing straddling pages failed\n");
|
||||
test_err("clearing straddling pages failed");
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
@ -361,7 +362,7 @@ static int __test_eb_bitmaps(unsigned long *bitmap, struct extent_buffer *eb,
|
||||
|
||||
ret = check_eb_bitmap(bitmap, eb, len);
|
||||
if (ret) {
|
||||
test_msg("Random bit pattern failed\n");
|
||||
test_err("random bit pattern failed");
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -376,7 +377,7 @@ static int test_eb_bitmaps(u32 sectorsize, u32 nodesize)
|
||||
struct extent_buffer *eb;
|
||||
int ret;
|
||||
|
||||
test_msg("Running extent buffer bitmap tests\n");
|
||||
test_msg("running extent buffer bitmap tests");
|
||||
|
||||
/*
|
||||
* In ppc64, sectorsize can be 64K, thus 4 * 64K will be larger than
|
||||
@ -389,13 +390,13 @@ static int test_eb_bitmaps(u32 sectorsize, u32 nodesize)
|
||||
|
||||
bitmap = kmalloc(len, GFP_KERNEL);
|
||||
if (!bitmap) {
|
||||
test_msg("Couldn't allocate test bitmap\n");
|
||||
test_err("couldn't allocate test bitmap");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
eb = __alloc_dummy_extent_buffer(fs_info, 0, len);
|
||||
if (!eb) {
|
||||
test_msg("Couldn't allocate test extent buffer\n");
|
||||
test_err("couldn't allocate test extent buffer");
|
||||
kfree(bitmap);
|
||||
return -ENOMEM;
|
||||
}
|
||||
@ -408,7 +409,7 @@ static int test_eb_bitmaps(u32 sectorsize, u32 nodesize)
|
||||
free_extent_buffer(eb);
|
||||
eb = __alloc_dummy_extent_buffer(NULL, nodesize / 2, len);
|
||||
if (!eb) {
|
||||
test_msg("Couldn't allocate test extent buffer\n");
|
||||
test_err("couldn't allocate test extent buffer");
|
||||
kfree(bitmap);
|
||||
return -ENOMEM;
|
||||
}
|
||||
@ -424,7 +425,7 @@ int btrfs_test_extent_io(u32 sectorsize, u32 nodesize)
|
||||
{
|
||||
int ret;
|
||||
|
||||
test_msg("Running extent I/O tests\n");
|
||||
test_msg("running extent I/O tests");
|
||||
|
||||
ret = test_find_delalloc(sectorsize);
|
||||
if (ret)
|
||||
@ -432,6 +433,6 @@ int btrfs_test_extent_io(u32 sectorsize, u32 nodesize)
|
||||
|
||||
ret = test_eb_bitmaps(sectorsize, nodesize);
|
||||
out:
|
||||
test_msg("Extent I/O tests finished\n");
|
||||
test_msg("extent I/O tests finished");
|
||||
return ret;
|
||||
}
|
||||
|
@ -19,8 +19,8 @@ static void free_extent_map_tree(struct extent_map_tree *em_tree)
|
||||
|
||||
#ifdef CONFIG_BTRFS_DEBUG
|
||||
if (refcount_read(&em->refs) != 1) {
|
||||
test_msg(
|
||||
"em leak: em (start 0x%llx len 0x%llx block_start 0x%llx block_len 0x%llx) refs %d\n",
|
||||
test_err(
|
||||
"em leak: em (start 0x%llx len 0x%llx block_start 0x%llx block_len 0x%llx) refs %d",
|
||||
em->start, em->len, em->block_start,
|
||||
em->block_len, refcount_read(&em->refs));
|
||||
|
||||
@ -47,7 +47,8 @@ static void free_extent_map_tree(struct extent_map_tree *em_tree)
|
||||
* ->add_extent_mapping(0, 16K)
|
||||
* -> #handle -EEXIST
|
||||
*/
|
||||
static void test_case_1(struct extent_map_tree *em_tree)
|
||||
static void test_case_1(struct btrfs_fs_info *fs_info,
|
||||
struct extent_map_tree *em_tree)
|
||||
{
|
||||
struct extent_map *em;
|
||||
u64 start = 0;
|
||||
@ -90,14 +91,14 @@ static void test_case_1(struct extent_map_tree *em_tree)
|
||||
em->len = len;
|
||||
em->block_start = start;
|
||||
em->block_len = len;
|
||||
ret = btrfs_add_extent_mapping(em_tree, &em, em->start, em->len);
|
||||
ret = btrfs_add_extent_mapping(fs_info, em_tree, &em, em->start, em->len);
|
||||
if (ret)
|
||||
test_msg("case1 [%llu %llu]: ret %d\n", start, start + len, ret);
|
||||
test_err("case1 [%llu %llu]: ret %d", start, start + len, ret);
|
||||
if (em &&
|
||||
(em->start != 0 || extent_map_end(em) != SZ_16K ||
|
||||
em->block_start != 0 || em->block_len != SZ_16K))
|
||||
test_msg(
|
||||
"case1 [%llu %llu]: ret %d return a wrong em (start %llu len %llu block_start %llu block_len %llu\n",
|
||||
test_err(
|
||||
"case1 [%llu %llu]: ret %d return a wrong em (start %llu len %llu block_start %llu block_len %llu",
|
||||
start, start + len, ret, em->start, em->len,
|
||||
em->block_start, em->block_len);
|
||||
free_extent_map(em);
|
||||
@ -112,7 +113,8 @@ out:
|
||||
* Reading the inline ending up with EEXIST, ie. read an inline
|
||||
* extent and discard page cache and read it again.
|
||||
*/
|
||||
static void test_case_2(struct extent_map_tree *em_tree)
|
||||
static void test_case_2(struct btrfs_fs_info *fs_info,
|
||||
struct extent_map_tree *em_tree)
|
||||
{
|
||||
struct extent_map *em;
|
||||
int ret;
|
||||
@ -153,14 +155,14 @@ static void test_case_2(struct extent_map_tree *em_tree)
|
||||
em->len = SZ_1K;
|
||||
em->block_start = EXTENT_MAP_INLINE;
|
||||
em->block_len = (u64)-1;
|
||||
ret = btrfs_add_extent_mapping(em_tree, &em, em->start, em->len);
|
||||
ret = btrfs_add_extent_mapping(fs_info, em_tree, &em, em->start, em->len);
|
||||
if (ret)
|
||||
test_msg("case2 [0 1K]: ret %d\n", ret);
|
||||
test_err("case2 [0 1K]: ret %d", ret);
|
||||
if (em &&
|
||||
(em->start != 0 || extent_map_end(em) != SZ_1K ||
|
||||
em->block_start != EXTENT_MAP_INLINE || em->block_len != (u64)-1))
|
||||
test_msg(
|
||||
"case2 [0 1K]: ret %d return a wrong em (start %llu len %llu block_start %llu block_len %llu\n",
|
||||
test_err(
|
||||
"case2 [0 1K]: ret %d return a wrong em (start %llu len %llu block_start %llu block_len %llu",
|
||||
ret, em->start, em->len, em->block_start,
|
||||
em->block_len);
|
||||
free_extent_map(em);
|
||||
@ -169,7 +171,8 @@ out:
|
||||
free_extent_map_tree(em_tree);
|
||||
}
|
||||
|
||||
static void __test_case_3(struct extent_map_tree *em_tree, u64 start)
|
||||
static void __test_case_3(struct btrfs_fs_info *fs_info,
|
||||
struct extent_map_tree *em_tree, u64 start)
|
||||
{
|
||||
struct extent_map *em;
|
||||
u64 len = SZ_4K;
|
||||
@ -198,9 +201,9 @@ static void __test_case_3(struct extent_map_tree *em_tree, u64 start)
|
||||
em->len = SZ_16K;
|
||||
em->block_start = 0;
|
||||
em->block_len = SZ_16K;
|
||||
ret = btrfs_add_extent_mapping(em_tree, &em, start, len);
|
||||
ret = btrfs_add_extent_mapping(fs_info, em_tree, &em, start, len);
|
||||
if (ret)
|
||||
test_msg("case3 [0x%llx 0x%llx): ret %d\n",
|
||||
test_err("case3 [0x%llx 0x%llx): ret %d",
|
||||
start, start + len, ret);
|
||||
/*
|
||||
* Since bytes within em are contiguous, em->block_start is identical to
|
||||
@ -209,8 +212,8 @@ static void __test_case_3(struct extent_map_tree *em_tree, u64 start)
|
||||
if (em &&
|
||||
(start < em->start || start + len > extent_map_end(em) ||
|
||||
em->start != em->block_start || em->len != em->block_len))
|
||||
test_msg(
|
||||
"case3 [0x%llx 0x%llx): ret %d em (start 0x%llx len 0x%llx block_start 0x%llx block_len 0x%llx)\n",
|
||||
test_err(
|
||||
"case3 [0x%llx 0x%llx): ret %d em (start 0x%llx len 0x%llx block_start 0x%llx block_len 0x%llx)",
|
||||
start, start + len, ret, em->start, em->len,
|
||||
em->block_start, em->block_len);
|
||||
free_extent_map(em);
|
||||
@ -235,14 +238,16 @@ out:
|
||||
* -> add_extent_mapping()
|
||||
* -> add_extent_mapping()
|
||||
*/
|
||||
static void test_case_3(struct extent_map_tree *em_tree)
|
||||
static void test_case_3(struct btrfs_fs_info *fs_info,
|
||||
struct extent_map_tree *em_tree)
|
||||
{
|
||||
__test_case_3(em_tree, 0);
|
||||
__test_case_3(em_tree, SZ_8K);
|
||||
__test_case_3(em_tree, (12 * 1024ULL));
|
||||
__test_case_3(fs_info, em_tree, 0);
|
||||
__test_case_3(fs_info, em_tree, SZ_8K);
|
||||
__test_case_3(fs_info, em_tree, (12 * 1024ULL));
|
||||
}
|
||||
|
||||
static void __test_case_4(struct extent_map_tree *em_tree, u64 start)
|
||||
static void __test_case_4(struct btrfs_fs_info *fs_info,
|
||||
struct extent_map_tree *em_tree, u64 start)
|
||||
{
|
||||
struct extent_map *em;
|
||||
u64 len = SZ_4K;
|
||||
@ -283,14 +288,14 @@ static void __test_case_4(struct extent_map_tree *em_tree, u64 start)
|
||||
em->len = SZ_32K;
|
||||
em->block_start = 0;
|
||||
em->block_len = SZ_32K;
|
||||
ret = btrfs_add_extent_mapping(em_tree, &em, start, len);
|
||||
ret = btrfs_add_extent_mapping(fs_info, em_tree, &em, start, len);
|
||||
if (ret)
|
||||
test_msg("case4 [0x%llx 0x%llx): ret %d\n",
|
||||
test_err("case4 [0x%llx 0x%llx): ret %d",
|
||||
start, len, ret);
|
||||
if (em &&
|
||||
(start < em->start || start + len > extent_map_end(em)))
|
||||
test_msg(
|
||||
"case4 [0x%llx 0x%llx): ret %d, added wrong em (start 0x%llx len 0x%llx block_start 0x%llx block_len 0x%llx)\n",
|
||||
test_err(
|
||||
"case4 [0x%llx 0x%llx): ret %d, added wrong em (start 0x%llx len 0x%llx block_start 0x%llx block_len 0x%llx)",
|
||||
start, len, ret, em->start, em->len, em->block_start,
|
||||
em->block_len);
|
||||
free_extent_map(em);
|
||||
@ -324,30 +329,45 @@ out:
|
||||
* # handle -EEXIST when adding
|
||||
* # [0, 32K)
|
||||
*/
|
||||
static void test_case_4(struct extent_map_tree *em_tree)
|
||||
static void test_case_4(struct btrfs_fs_info *fs_info,
|
||||
struct extent_map_tree *em_tree)
|
||||
{
|
||||
__test_case_4(em_tree, 0);
|
||||
__test_case_4(em_tree, SZ_4K);
|
||||
__test_case_4(fs_info, em_tree, 0);
|
||||
__test_case_4(fs_info, em_tree, SZ_4K);
|
||||
}
|
||||
|
||||
int btrfs_test_extent_map(void)
|
||||
{
|
||||
struct btrfs_fs_info *fs_info = NULL;
|
||||
struct extent_map_tree *em_tree;
|
||||
|
||||
test_msg("Running extent_map tests\n");
|
||||
test_msg("running extent_map tests");
|
||||
|
||||
/*
|
||||
* Note: the fs_info is not set up completely, we only need
|
||||
* fs_info::fsid for the tracepoint.
|
||||
*/
|
||||
fs_info = btrfs_alloc_dummy_fs_info(PAGE_SIZE, PAGE_SIZE);
|
||||
if (!fs_info) {
|
||||
test_msg("Couldn't allocate dummy fs info");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
em_tree = kzalloc(sizeof(*em_tree), GFP_KERNEL);
|
||||
if (!em_tree)
|
||||
/* Skip the test on error. */
|
||||
return 0;
|
||||
goto out;
|
||||
|
||||
extent_map_tree_init(em_tree);
|
||||
|
||||
test_case_1(em_tree);
|
||||
test_case_2(em_tree);
|
||||
test_case_3(em_tree);
|
||||
test_case_4(em_tree);
|
||||
test_case_1(fs_info, em_tree);
|
||||
test_case_2(fs_info, em_tree);
|
||||
test_case_3(fs_info, em_tree);
|
||||
test_case_4(fs_info, em_tree);
|
||||
|
||||
kfree(em_tree);
|
||||
out:
|
||||
btrfs_free_dummy_fs_info(fs_info);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -20,63 +20,63 @@ static int test_extents(struct btrfs_block_group_cache *cache)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
test_msg("Running extent only tests\n");
|
||||
test_msg("running extent only tests");
|
||||
|
||||
/* First just make sure we can remove an entire entry */
|
||||
ret = btrfs_add_free_space(cache, 0, SZ_4M);
|
||||
if (ret) {
|
||||
test_msg("Error adding initial extents %d\n", ret);
|
||||
test_err("error adding initial extents %d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = btrfs_remove_free_space(cache, 0, SZ_4M);
|
||||
if (ret) {
|
||||
test_msg("Error removing extent %d\n", ret);
|
||||
test_err("error removing extent %d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (test_check_exists(cache, 0, SZ_4M)) {
|
||||
test_msg("Full remove left some lingering space\n");
|
||||
test_err("full remove left some lingering space");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Ok edge and middle cases now */
|
||||
ret = btrfs_add_free_space(cache, 0, SZ_4M);
|
||||
if (ret) {
|
||||
test_msg("Error adding half extent %d\n", ret);
|
||||
test_err("error adding half extent %d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = btrfs_remove_free_space(cache, 3 * SZ_1M, SZ_1M);
|
||||
if (ret) {
|
||||
test_msg("Error removing tail end %d\n", ret);
|
||||
test_err("error removing tail end %d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = btrfs_remove_free_space(cache, 0, SZ_1M);
|
||||
if (ret) {
|
||||
test_msg("Error removing front end %d\n", ret);
|
||||
test_err("error removing front end %d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = btrfs_remove_free_space(cache, SZ_2M, 4096);
|
||||
if (ret) {
|
||||
test_msg("Error removing middle piece %d\n", ret);
|
||||
test_err("error removing middle piece %d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (test_check_exists(cache, 0, SZ_1M)) {
|
||||
test_msg("Still have space at the front\n");
|
||||
test_err("still have space at the front");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (test_check_exists(cache, SZ_2M, 4096)) {
|
||||
test_msg("Still have space in the middle\n");
|
||||
test_err("still have space in the middle");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (test_check_exists(cache, 3 * SZ_1M, SZ_1M)) {
|
||||
test_msg("Still have space at the end\n");
|
||||
test_err("still have space at the end");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -92,34 +92,34 @@ static int test_bitmaps(struct btrfs_block_group_cache *cache,
|
||||
u64 next_bitmap_offset;
|
||||
int ret;
|
||||
|
||||
test_msg("Running bitmap only tests\n");
|
||||
test_msg("running bitmap only tests");
|
||||
|
||||
ret = test_add_free_space_entry(cache, 0, SZ_4M, 1);
|
||||
if (ret) {
|
||||
test_msg("Couldn't create a bitmap entry %d\n", ret);
|
||||
test_err("couldn't create a bitmap entry %d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = btrfs_remove_free_space(cache, 0, SZ_4M);
|
||||
if (ret) {
|
||||
test_msg("Error removing bitmap full range %d\n", ret);
|
||||
test_err("error removing bitmap full range %d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (test_check_exists(cache, 0, SZ_4M)) {
|
||||
test_msg("Left some space in bitmap\n");
|
||||
test_err("left some space in bitmap");
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = test_add_free_space_entry(cache, 0, SZ_4M, 1);
|
||||
if (ret) {
|
||||
test_msg("Couldn't add to our bitmap entry %d\n", ret);
|
||||
test_err("couldn't add to our bitmap entry %d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = btrfs_remove_free_space(cache, SZ_1M, SZ_2M);
|
||||
if (ret) {
|
||||
test_msg("Couldn't remove middle chunk %d\n", ret);
|
||||
test_err("couldn't remove middle chunk %d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -133,19 +133,19 @@ static int test_bitmaps(struct btrfs_block_group_cache *cache,
|
||||
ret = test_add_free_space_entry(cache, next_bitmap_offset - SZ_2M,
|
||||
SZ_4M, 1);
|
||||
if (ret) {
|
||||
test_msg("Couldn't add space that straddles two bitmaps %d\n",
|
||||
test_err("couldn't add space that straddles two bitmaps %d",
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = btrfs_remove_free_space(cache, next_bitmap_offset - SZ_1M, SZ_2M);
|
||||
if (ret) {
|
||||
test_msg("Couldn't remove overlapping space %d\n", ret);
|
||||
test_err("couldn't remove overlapping space %d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (test_check_exists(cache, next_bitmap_offset - SZ_1M, SZ_2M)) {
|
||||
test_msg("Left some space when removing overlapping\n");
|
||||
test_err("left some space when removing overlapping");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -161,7 +161,7 @@ static int test_bitmaps_and_extents(struct btrfs_block_group_cache *cache,
|
||||
u64 bitmap_offset = (u64)(BITS_PER_BITMAP * sectorsize);
|
||||
int ret;
|
||||
|
||||
test_msg("Running bitmap and extent tests\n");
|
||||
test_msg("running bitmap and extent tests");
|
||||
|
||||
/*
|
||||
* First let's do something simple, an extent at the same offset as the
|
||||
@ -170,42 +170,42 @@ static int test_bitmaps_and_extents(struct btrfs_block_group_cache *cache,
|
||||
*/
|
||||
ret = test_add_free_space_entry(cache, SZ_4M, SZ_1M, 1);
|
||||
if (ret) {
|
||||
test_msg("Couldn't create bitmap entry %d\n", ret);
|
||||
test_err("couldn't create bitmap entry %d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = test_add_free_space_entry(cache, 0, SZ_1M, 0);
|
||||
if (ret) {
|
||||
test_msg("Couldn't add extent entry %d\n", ret);
|
||||
test_err("couldn't add extent entry %d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = btrfs_remove_free_space(cache, 0, SZ_1M);
|
||||
if (ret) {
|
||||
test_msg("Couldn't remove extent entry %d\n", ret);
|
||||
test_err("couldn't remove extent entry %d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (test_check_exists(cache, 0, SZ_1M)) {
|
||||
test_msg("Left remnants after our remove\n");
|
||||
test_err("left remnants after our remove");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Now to add back the extent entry and remove from the bitmap */
|
||||
ret = test_add_free_space_entry(cache, 0, SZ_1M, 0);
|
||||
if (ret) {
|
||||
test_msg("Couldn't re-add extent entry %d\n", ret);
|
||||
test_err("couldn't re-add extent entry %d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = btrfs_remove_free_space(cache, SZ_4M, SZ_1M);
|
||||
if (ret) {
|
||||
test_msg("Couldn't remove from bitmap %d\n", ret);
|
||||
test_err("couldn't remove from bitmap %d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (test_check_exists(cache, SZ_4M, SZ_1M)) {
|
||||
test_msg("Left remnants in the bitmap\n");
|
||||
test_err("left remnants in the bitmap");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -215,18 +215,18 @@ static int test_bitmaps_and_extents(struct btrfs_block_group_cache *cache,
|
||||
*/
|
||||
ret = test_add_free_space_entry(cache, SZ_1M, SZ_4M, 1);
|
||||
if (ret) {
|
||||
test_msg("Couldn't add to a bitmap %d\n", ret);
|
||||
test_err("couldn't add to a bitmap %d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = btrfs_remove_free_space(cache, SZ_512K, 3 * SZ_1M);
|
||||
if (ret) {
|
||||
test_msg("Couldn't remove overlapping space %d\n", ret);
|
||||
test_err("couldn't remove overlapping space %d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (test_check_exists(cache, SZ_512K, 3 * SZ_1M)) {
|
||||
test_msg("Left over pieces after removing overlapping\n");
|
||||
test_err("left over pieces after removing overlapping");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -235,24 +235,24 @@ static int test_bitmaps_and_extents(struct btrfs_block_group_cache *cache,
|
||||
/* Now with the extent entry offset into the bitmap */
|
||||
ret = test_add_free_space_entry(cache, SZ_4M, SZ_4M, 1);
|
||||
if (ret) {
|
||||
test_msg("Couldn't add space to the bitmap %d\n", ret);
|
||||
test_err("couldn't add space to the bitmap %d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = test_add_free_space_entry(cache, SZ_2M, SZ_2M, 0);
|
||||
if (ret) {
|
||||
test_msg("Couldn't add extent to the cache %d\n", ret);
|
||||
test_err("couldn't add extent to the cache %d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = btrfs_remove_free_space(cache, 3 * SZ_1M, SZ_4M);
|
||||
if (ret) {
|
||||
test_msg("Problem removing overlapping space %d\n", ret);
|
||||
test_err("problem removing overlapping space %d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (test_check_exists(cache, 3 * SZ_1M, SZ_4M)) {
|
||||
test_msg("Left something behind when removing space");
|
||||
test_err("left something behind when removing space");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -269,25 +269,25 @@ static int test_bitmaps_and_extents(struct btrfs_block_group_cache *cache,
|
||||
__btrfs_remove_free_space_cache(cache->free_space_ctl);
|
||||
ret = test_add_free_space_entry(cache, bitmap_offset + SZ_4M, SZ_4M, 1);
|
||||
if (ret) {
|
||||
test_msg("Couldn't add bitmap %d\n", ret);
|
||||
test_err("couldn't add bitmap %d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = test_add_free_space_entry(cache, bitmap_offset - SZ_1M,
|
||||
5 * SZ_1M, 0);
|
||||
if (ret) {
|
||||
test_msg("Couldn't add extent entry %d\n", ret);
|
||||
test_err("couldn't add extent entry %d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = btrfs_remove_free_space(cache, bitmap_offset + SZ_1M, 5 * SZ_1M);
|
||||
if (ret) {
|
||||
test_msg("Failed to free our space %d\n", ret);
|
||||
test_err("failed to free our space %d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (test_check_exists(cache, bitmap_offset + SZ_1M, 5 * SZ_1M)) {
|
||||
test_msg("Left stuff over\n");
|
||||
test_err("left stuff over");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -301,19 +301,19 @@ static int test_bitmaps_and_extents(struct btrfs_block_group_cache *cache,
|
||||
*/
|
||||
ret = test_add_free_space_entry(cache, SZ_1M, SZ_2M, 1);
|
||||
if (ret) {
|
||||
test_msg("Couldn't add bitmap entry %d\n", ret);
|
||||
test_err("couldn't add bitmap entry %d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = test_add_free_space_entry(cache, 3 * SZ_1M, SZ_1M, 0);
|
||||
if (ret) {
|
||||
test_msg("Couldn't add extent entry %d\n", ret);
|
||||
test_err("couldn't add extent entry %d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = btrfs_remove_free_space(cache, SZ_1M, 3 * SZ_1M);
|
||||
if (ret) {
|
||||
test_msg("Error removing bitmap and extent overlapping %d\n", ret);
|
||||
test_err("error removing bitmap and extent overlapping %d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -335,12 +335,14 @@ check_num_extents_and_bitmaps(const struct btrfs_block_group_cache *cache,
|
||||
const int num_bitmaps)
|
||||
{
|
||||
if (cache->free_space_ctl->free_extents != num_extents) {
|
||||
test_msg("Incorrect # of extent entries in the cache: %d, expected %d\n",
|
||||
test_err(
|
||||
"incorrect # of extent entries in the cache: %d, expected %d",
|
||||
cache->free_space_ctl->free_extents, num_extents);
|
||||
return -EINVAL;
|
||||
}
|
||||
if (cache->free_space_ctl->total_bitmaps != num_bitmaps) {
|
||||
test_msg("Incorrect # of extent entries in the cache: %d, expected %d\n",
|
||||
test_err(
|
||||
"incorrect # of extent entries in the cache: %d, expected %d",
|
||||
cache->free_space_ctl->total_bitmaps, num_bitmaps);
|
||||
return -EINVAL;
|
||||
}
|
||||
@ -358,7 +360,7 @@ static int check_cache_empty(struct btrfs_block_group_cache *cache)
|
||||
* allocate.
|
||||
*/
|
||||
if (cache->free_space_ctl->free_space != 0) {
|
||||
test_msg("Cache free space is not 0\n");
|
||||
test_err("cache free space is not 0");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@ -366,7 +368,7 @@ static int check_cache_empty(struct btrfs_block_group_cache *cache)
|
||||
offset = btrfs_find_space_for_alloc(cache, 0, 4096, 0,
|
||||
&max_extent_size);
|
||||
if (offset != 0) {
|
||||
test_msg("Space allocation did not fail, returned offset: %llu",
|
||||
test_err("space allocation did not fail, returned offset: %llu",
|
||||
offset);
|
||||
return -EINVAL;
|
||||
}
|
||||
@ -402,7 +404,7 @@ test_steal_space_from_bitmap_to_extent(struct btrfs_block_group_cache *cache,
|
||||
};
|
||||
const struct btrfs_free_space_op *orig_free_space_ops;
|
||||
|
||||
test_msg("Running space stealing from bitmap to extent\n");
|
||||
test_msg("running space stealing from bitmap to extent");
|
||||
|
||||
/*
|
||||
* For this test, we want to ensure we end up with an extent entry
|
||||
@ -430,7 +432,7 @@ test_steal_space_from_bitmap_to_extent(struct btrfs_block_group_cache *cache,
|
||||
*/
|
||||
ret = test_add_free_space_entry(cache, SZ_128M - SZ_256K, SZ_128K, 0);
|
||||
if (ret) {
|
||||
test_msg("Couldn't add extent entry %d\n", ret);
|
||||
test_err("couldn't add extent entry %d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -438,7 +440,7 @@ test_steal_space_from_bitmap_to_extent(struct btrfs_block_group_cache *cache,
|
||||
ret = test_add_free_space_entry(cache, SZ_128M + SZ_512K,
|
||||
SZ_128M - SZ_512K, 1);
|
||||
if (ret) {
|
||||
test_msg("Couldn't add bitmap entry %d\n", ret);
|
||||
test_err("couldn't add bitmap entry %d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -457,17 +459,17 @@ test_steal_space_from_bitmap_to_extent(struct btrfs_block_group_cache *cache,
|
||||
SZ_128M + 768 * SZ_1K,
|
||||
SZ_128M - 768 * SZ_1K);
|
||||
if (ret) {
|
||||
test_msg("Failed to free part of bitmap space %d\n", ret);
|
||||
test_err("failed to free part of bitmap space %d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Confirm that only those 2 ranges are marked as free. */
|
||||
if (!test_check_exists(cache, SZ_128M - SZ_256K, SZ_128K)) {
|
||||
test_msg("Free space range missing\n");
|
||||
test_err("free space range missing");
|
||||
return -ENOENT;
|
||||
}
|
||||
if (!test_check_exists(cache, SZ_128M + SZ_512K, SZ_256K)) {
|
||||
test_msg("Free space range missing\n");
|
||||
test_err("free space range missing");
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
@ -477,7 +479,7 @@ test_steal_space_from_bitmap_to_extent(struct btrfs_block_group_cache *cache,
|
||||
*/
|
||||
if (test_check_exists(cache, SZ_128M + 768 * SZ_1K,
|
||||
SZ_128M - 768 * SZ_1K)) {
|
||||
test_msg("Bitmap region not removed from space cache\n");
|
||||
test_err("bitmap region not removed from space cache");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@ -486,7 +488,7 @@ test_steal_space_from_bitmap_to_extent(struct btrfs_block_group_cache *cache,
|
||||
* covered by the bitmap, isn't marked as free.
|
||||
*/
|
||||
if (test_check_exists(cache, SZ_128M + SZ_256K, SZ_256K)) {
|
||||
test_msg("Invalid bitmap region marked as free\n");
|
||||
test_err("invalid bitmap region marked as free");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@ -495,7 +497,7 @@ test_steal_space_from_bitmap_to_extent(struct btrfs_block_group_cache *cache,
|
||||
* by the bitmap too, isn't marked as free either.
|
||||
*/
|
||||
if (test_check_exists(cache, SZ_128M, SZ_256K)) {
|
||||
test_msg("Invalid bitmap region marked as free\n");
|
||||
test_err("invalid bitmap region marked as free");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@ -506,12 +508,12 @@ test_steal_space_from_bitmap_to_extent(struct btrfs_block_group_cache *cache,
|
||||
*/
|
||||
ret = btrfs_add_free_space(cache, SZ_128M, SZ_512K);
|
||||
if (ret) {
|
||||
test_msg("Error adding free space: %d\n", ret);
|
||||
test_err("error adding free space: %d", ret);
|
||||
return ret;
|
||||
}
|
||||
/* Confirm the region is marked as free. */
|
||||
if (!test_check_exists(cache, SZ_128M, SZ_512K)) {
|
||||
test_msg("Bitmap region not marked as free\n");
|
||||
test_err("bitmap region not marked as free");
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
@ -531,7 +533,7 @@ test_steal_space_from_bitmap_to_extent(struct btrfs_block_group_cache *cache,
|
||||
*/
|
||||
ret = btrfs_add_free_space(cache, SZ_128M + SZ_16M, sectorsize);
|
||||
if (ret) {
|
||||
test_msg("Error adding free space: %d\n", ret);
|
||||
test_err("error adding free space: %d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -550,12 +552,12 @@ test_steal_space_from_bitmap_to_extent(struct btrfs_block_group_cache *cache,
|
||||
*/
|
||||
ret = btrfs_add_free_space(cache, SZ_128M - SZ_128K, SZ_128K);
|
||||
if (ret) {
|
||||
test_msg("Error adding free space: %d\n", ret);
|
||||
test_err("error adding free space: %d", ret);
|
||||
return ret;
|
||||
}
|
||||
/* Confirm the region is marked as free. */
|
||||
if (!test_check_exists(cache, SZ_128M - SZ_128K, SZ_128K)) {
|
||||
test_msg("Extent region not marked as free\n");
|
||||
test_err("extent region not marked as free");
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
@ -583,12 +585,12 @@ test_steal_space_from_bitmap_to_extent(struct btrfs_block_group_cache *cache,
|
||||
* allocate the whole free space at once.
|
||||
*/
|
||||
if (!test_check_exists(cache, SZ_128M - SZ_256K, SZ_1M)) {
|
||||
test_msg("Expected region not marked as free\n");
|
||||
test_err("expected region not marked as free");
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
if (cache->free_space_ctl->free_space != (SZ_1M + sectorsize)) {
|
||||
test_msg("Cache free space is not 1Mb + %u\n", sectorsize);
|
||||
test_err("cache free space is not 1Mb + %u", sectorsize);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@ -596,7 +598,8 @@ test_steal_space_from_bitmap_to_extent(struct btrfs_block_group_cache *cache,
|
||||
0, SZ_1M, 0,
|
||||
&max_extent_size);
|
||||
if (offset != (SZ_128M - SZ_256K)) {
|
||||
test_msg("Failed to allocate 1Mb from space cache, returned offset is: %llu\n",
|
||||
test_err(
|
||||
"failed to allocate 1Mb from space cache, returned offset is: %llu",
|
||||
offset);
|
||||
return -EINVAL;
|
||||
}
|
||||
@ -610,7 +613,7 @@ test_steal_space_from_bitmap_to_extent(struct btrfs_block_group_cache *cache,
|
||||
return ret;
|
||||
|
||||
if (cache->free_space_ctl->free_space != sectorsize) {
|
||||
test_msg("Cache free space is not %u\n", sectorsize);
|
||||
test_err("cache free space is not %u", sectorsize);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@ -618,7 +621,7 @@ test_steal_space_from_bitmap_to_extent(struct btrfs_block_group_cache *cache,
|
||||
0, sectorsize, 0,
|
||||
&max_extent_size);
|
||||
if (offset != (SZ_128M + SZ_16M)) {
|
||||
test_msg("Failed to allocate %u, returned offset : %llu\n",
|
||||
test_err("failed to allocate %u, returned offset : %llu",
|
||||
sectorsize, offset);
|
||||
return -EINVAL;
|
||||
}
|
||||
@ -640,14 +643,14 @@ test_steal_space_from_bitmap_to_extent(struct btrfs_block_group_cache *cache,
|
||||
*/
|
||||
ret = test_add_free_space_entry(cache, SZ_128M + SZ_128K, SZ_128K, 0);
|
||||
if (ret) {
|
||||
test_msg("Couldn't add extent entry %d\n", ret);
|
||||
test_err("couldn't add extent entry %d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Bitmap entry covering free space range [0, 128Mb - 512Kb[ */
|
||||
ret = test_add_free_space_entry(cache, 0, SZ_128M - SZ_512K, 1);
|
||||
if (ret) {
|
||||
test_msg("Couldn't add bitmap entry %d\n", ret);
|
||||
test_err("couldn't add bitmap entry %d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -664,17 +667,17 @@ test_steal_space_from_bitmap_to_extent(struct btrfs_block_group_cache *cache,
|
||||
*/
|
||||
ret = btrfs_remove_free_space(cache, 0, SZ_128M - 768 * SZ_1K);
|
||||
if (ret) {
|
||||
test_msg("Failed to free part of bitmap space %d\n", ret);
|
||||
test_err("failed to free part of bitmap space %d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Confirm that only those 2 ranges are marked as free. */
|
||||
if (!test_check_exists(cache, SZ_128M + SZ_128K, SZ_128K)) {
|
||||
test_msg("Free space range missing\n");
|
||||
test_err("free space range missing");
|
||||
return -ENOENT;
|
||||
}
|
||||
if (!test_check_exists(cache, SZ_128M - 768 * SZ_1K, SZ_256K)) {
|
||||
test_msg("Free space range missing\n");
|
||||
test_err("free space range missing");
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
@ -683,7 +686,7 @@ test_steal_space_from_bitmap_to_extent(struct btrfs_block_group_cache *cache,
|
||||
* as free anymore.
|
||||
*/
|
||||
if (test_check_exists(cache, 0, SZ_128M - 768 * SZ_1K)) {
|
||||
test_msg("Bitmap region not removed from space cache\n");
|
||||
test_err("bitmap region not removed from space cache");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@ -692,7 +695,7 @@ test_steal_space_from_bitmap_to_extent(struct btrfs_block_group_cache *cache,
|
||||
* covered by the bitmap, isn't marked as free.
|
||||
*/
|
||||
if (test_check_exists(cache, SZ_128M - SZ_512K, SZ_512K)) {
|
||||
test_msg("Invalid bitmap region marked as free\n");
|
||||
test_err("invalid bitmap region marked as free");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@ -703,12 +706,12 @@ test_steal_space_from_bitmap_to_extent(struct btrfs_block_group_cache *cache,
|
||||
*/
|
||||
ret = btrfs_add_free_space(cache, SZ_128M - SZ_512K, SZ_512K);
|
||||
if (ret) {
|
||||
test_msg("Error adding free space: %d\n", ret);
|
||||
test_err("error adding free space: %d", ret);
|
||||
return ret;
|
||||
}
|
||||
/* Confirm the region is marked as free. */
|
||||
if (!test_check_exists(cache, SZ_128M - SZ_512K, SZ_512K)) {
|
||||
test_msg("Bitmap region not marked as free\n");
|
||||
test_err("bitmap region not marked as free");
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
@ -728,7 +731,7 @@ test_steal_space_from_bitmap_to_extent(struct btrfs_block_group_cache *cache,
|
||||
*/
|
||||
ret = btrfs_add_free_space(cache, SZ_32M, 2 * sectorsize);
|
||||
if (ret) {
|
||||
test_msg("Error adding free space: %d\n", ret);
|
||||
test_err("error adding free space: %d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -739,12 +742,12 @@ test_steal_space_from_bitmap_to_extent(struct btrfs_block_group_cache *cache,
|
||||
*/
|
||||
ret = btrfs_add_free_space(cache, SZ_128M, SZ_128K);
|
||||
if (ret) {
|
||||
test_msg("Error adding free space: %d\n", ret);
|
||||
test_err("error adding free space: %d", ret);
|
||||
return ret;
|
||||
}
|
||||
/* Confirm the region is marked as free. */
|
||||
if (!test_check_exists(cache, SZ_128M, SZ_128K)) {
|
||||
test_msg("Extent region not marked as free\n");
|
||||
test_err("extent region not marked as free");
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
@ -772,19 +775,20 @@ test_steal_space_from_bitmap_to_extent(struct btrfs_block_group_cache *cache,
|
||||
* allocate the whole free space at once.
|
||||
*/
|
||||
if (!test_check_exists(cache, SZ_128M - 768 * SZ_1K, SZ_1M)) {
|
||||
test_msg("Expected region not marked as free\n");
|
||||
test_err("expected region not marked as free");
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
if (cache->free_space_ctl->free_space != (SZ_1M + 2 * sectorsize)) {
|
||||
test_msg("Cache free space is not 1Mb + %u\n", 2 * sectorsize);
|
||||
test_err("cache free space is not 1Mb + %u", 2 * sectorsize);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
offset = btrfs_find_space_for_alloc(cache, 0, SZ_1M, 0,
|
||||
&max_extent_size);
|
||||
if (offset != (SZ_128M - 768 * SZ_1K)) {
|
||||
test_msg("Failed to allocate 1Mb from space cache, returned offset is: %llu\n",
|
||||
test_err(
|
||||
"failed to allocate 1Mb from space cache, returned offset is: %llu",
|
||||
offset);
|
||||
return -EINVAL;
|
||||
}
|
||||
@ -798,7 +802,7 @@ test_steal_space_from_bitmap_to_extent(struct btrfs_block_group_cache *cache,
|
||||
return ret;
|
||||
|
||||
if (cache->free_space_ctl->free_space != 2 * sectorsize) {
|
||||
test_msg("Cache free space is not %u\n", 2 * sectorsize);
|
||||
test_err("cache free space is not %u", 2 * sectorsize);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@ -806,9 +810,8 @@ test_steal_space_from_bitmap_to_extent(struct btrfs_block_group_cache *cache,
|
||||
0, 2 * sectorsize, 0,
|
||||
&max_extent_size);
|
||||
if (offset != SZ_32M) {
|
||||
test_msg("Failed to allocate %u, offset: %llu\n",
|
||||
2 * sectorsize,
|
||||
offset);
|
||||
test_err("failed to allocate %u, offset: %llu",
|
||||
2 * sectorsize, offset);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@ -829,7 +832,7 @@ int btrfs_test_free_space_cache(u32 sectorsize, u32 nodesize)
|
||||
struct btrfs_root *root = NULL;
|
||||
int ret = -ENOMEM;
|
||||
|
||||
test_msg("Running btrfs free space cache tests\n");
|
||||
test_msg("running btrfs free space cache tests");
|
||||
fs_info = btrfs_alloc_dummy_fs_info(nodesize, sectorsize);
|
||||
if (!fs_info)
|
||||
return -ENOMEM;
|
||||
@ -843,7 +846,7 @@ int btrfs_test_free_space_cache(u32 sectorsize, u32 nodesize)
|
||||
cache = btrfs_alloc_dummy_block_group(fs_info,
|
||||
BITS_PER_BITMAP * sectorsize + PAGE_SIZE);
|
||||
if (!cache) {
|
||||
test_msg("Couldn't run the tests\n");
|
||||
test_err("couldn't run the tests");
|
||||
btrfs_free_dummy_fs_info(fs_info);
|
||||
return 0;
|
||||
}
|
||||
@ -871,6 +874,6 @@ out:
|
||||
btrfs_free_dummy_block_group(cache);
|
||||
btrfs_free_dummy_root(root);
|
||||
btrfs_free_dummy_fs_info(fs_info);
|
||||
test_msg("Free space cache tests finished\n");
|
||||
test_msg("free space cache tests finished");
|
||||
return ret;
|
||||
}
|
||||
|
@ -32,7 +32,7 @@ static int __check_free_space_extents(struct btrfs_trans_handle *trans,
|
||||
|
||||
info = search_free_space_info(trans, fs_info, cache, path, 0);
|
||||
if (IS_ERR(info)) {
|
||||
test_msg("Could not find free space info\n");
|
||||
test_err("could not find free space info");
|
||||
ret = PTR_ERR(info);
|
||||
goto out;
|
||||
}
|
||||
@ -40,7 +40,7 @@ static int __check_free_space_extents(struct btrfs_trans_handle *trans,
|
||||
extent_count = btrfs_free_space_extent_count(path->nodes[0], info);
|
||||
|
||||
if (extent_count != num_extents) {
|
||||
test_msg("Extent count is wrong\n");
|
||||
test_err("extent count is wrong");
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
@ -99,7 +99,7 @@ out:
|
||||
btrfs_release_path(path);
|
||||
return ret;
|
||||
invalid:
|
||||
test_msg("Free space tree is invalid\n");
|
||||
test_err("free space tree is invalid");
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
@ -117,7 +117,7 @@ static int check_free_space_extents(struct btrfs_trans_handle *trans,
|
||||
|
||||
info = search_free_space_info(trans, fs_info, cache, path, 0);
|
||||
if (IS_ERR(info)) {
|
||||
test_msg("Could not find free space info\n");
|
||||
test_err("could not find free space info");
|
||||
btrfs_release_path(path);
|
||||
return PTR_ERR(info);
|
||||
}
|
||||
@ -131,15 +131,15 @@ static int check_free_space_extents(struct btrfs_trans_handle *trans,
|
||||
|
||||
/* Flip it to the other format and check that for good measure. */
|
||||
if (flags & BTRFS_FREE_SPACE_USING_BITMAPS) {
|
||||
ret = convert_free_space_to_extents(trans, fs_info, cache, path);
|
||||
ret = convert_free_space_to_extents(trans, cache, path);
|
||||
if (ret) {
|
||||
test_msg("Could not convert to extents\n");
|
||||
test_err("could not convert to extents");
|
||||
return ret;
|
||||
}
|
||||
} else {
|
||||
ret = convert_free_space_to_bitmaps(trans, fs_info, cache, path);
|
||||
ret = convert_free_space_to_bitmaps(trans, cache, path);
|
||||
if (ret) {
|
||||
test_msg("Could not convert to bitmaps\n");
|
||||
test_err("could not convert to bitmaps");
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
@ -170,11 +170,11 @@ static int test_remove_all(struct btrfs_trans_handle *trans,
|
||||
const struct free_space_extent extents[] = {};
|
||||
int ret;
|
||||
|
||||
ret = __remove_from_free_space_tree(trans, fs_info, cache, path,
|
||||
ret = __remove_from_free_space_tree(trans, cache, path,
|
||||
cache->key.objectid,
|
||||
cache->key.offset);
|
||||
if (ret) {
|
||||
test_msg("Could not remove free space\n");
|
||||
test_err("could not remove free space");
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -194,10 +194,10 @@ static int test_remove_beginning(struct btrfs_trans_handle *trans,
|
||||
};
|
||||
int ret;
|
||||
|
||||
ret = __remove_from_free_space_tree(trans, fs_info, cache, path,
|
||||
ret = __remove_from_free_space_tree(trans, cache, path,
|
||||
cache->key.objectid, alignment);
|
||||
if (ret) {
|
||||
test_msg("Could not remove free space\n");
|
||||
test_err("could not remove free space");
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -217,12 +217,12 @@ static int test_remove_end(struct btrfs_trans_handle *trans,
|
||||
};
|
||||
int ret;
|
||||
|
||||
ret = __remove_from_free_space_tree(trans, fs_info, cache, path,
|
||||
ret = __remove_from_free_space_tree(trans, cache, path,
|
||||
cache->key.objectid +
|
||||
cache->key.offset - alignment,
|
||||
alignment);
|
||||
if (ret) {
|
||||
test_msg("Could not remove free space\n");
|
||||
test_err("could not remove free space");
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -243,11 +243,11 @@ static int test_remove_middle(struct btrfs_trans_handle *trans,
|
||||
};
|
||||
int ret;
|
||||
|
||||
ret = __remove_from_free_space_tree(trans, fs_info, cache, path,
|
||||
ret = __remove_from_free_space_tree(trans, cache, path,
|
||||
cache->key.objectid + alignment,
|
||||
alignment);
|
||||
if (ret) {
|
||||
test_msg("Could not remove free space\n");
|
||||
test_err("could not remove free space");
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -266,26 +266,26 @@ static int test_merge_left(struct btrfs_trans_handle *trans,
|
||||
};
|
||||
int ret;
|
||||
|
||||
ret = __remove_from_free_space_tree(trans, fs_info, cache, path,
|
||||
ret = __remove_from_free_space_tree(trans, cache, path,
|
||||
cache->key.objectid,
|
||||
cache->key.offset);
|
||||
if (ret) {
|
||||
test_msg("Could not remove free space\n");
|
||||
test_err("could not remove free space");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = __add_to_free_space_tree(trans, fs_info, cache, path,
|
||||
cache->key.objectid, alignment);
|
||||
ret = __add_to_free_space_tree(trans, cache, path, cache->key.objectid,
|
||||
alignment);
|
||||
if (ret) {
|
||||
test_msg("Could not add free space\n");
|
||||
test_err("could not add free space");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = __add_to_free_space_tree(trans, fs_info, cache, path,
|
||||
ret = __add_to_free_space_tree(trans, cache, path,
|
||||
cache->key.objectid + alignment,
|
||||
alignment);
|
||||
if (ret) {
|
||||
test_msg("Could not add free space\n");
|
||||
test_err("could not add free space");
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -304,27 +304,27 @@ static int test_merge_right(struct btrfs_trans_handle *trans,
|
||||
};
|
||||
int ret;
|
||||
|
||||
ret = __remove_from_free_space_tree(trans, fs_info, cache, path,
|
||||
ret = __remove_from_free_space_tree(trans, cache, path,
|
||||
cache->key.objectid,
|
||||
cache->key.offset);
|
||||
if (ret) {
|
||||
test_msg("Could not remove free space\n");
|
||||
test_err("could not remove free space");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = __add_to_free_space_tree(trans, fs_info, cache, path,
|
||||
ret = __add_to_free_space_tree(trans, cache, path,
|
||||
cache->key.objectid + 2 * alignment,
|
||||
alignment);
|
||||
if (ret) {
|
||||
test_msg("Could not add free space\n");
|
||||
test_err("could not add free space");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = __add_to_free_space_tree(trans, fs_info, cache, path,
|
||||
ret = __add_to_free_space_tree(trans, cache, path,
|
||||
cache->key.objectid + alignment,
|
||||
alignment);
|
||||
if (ret) {
|
||||
test_msg("Could not add free space\n");
|
||||
test_err("could not add free space");
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -343,34 +343,34 @@ static int test_merge_both(struct btrfs_trans_handle *trans,
|
||||
};
|
||||
int ret;
|
||||
|
||||
ret = __remove_from_free_space_tree(trans, fs_info, cache, path,
|
||||
ret = __remove_from_free_space_tree(trans, cache, path,
|
||||
cache->key.objectid,
|
||||
cache->key.offset);
|
||||
if (ret) {
|
||||
test_msg("Could not remove free space\n");
|
||||
test_err("could not remove free space");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = __add_to_free_space_tree(trans, fs_info, cache, path,
|
||||
cache->key.objectid, alignment);
|
||||
ret = __add_to_free_space_tree(trans, cache, path, cache->key.objectid,
|
||||
alignment);
|
||||
if (ret) {
|
||||
test_msg("Could not add free space\n");
|
||||
test_err("could not add free space");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = __add_to_free_space_tree(trans, fs_info, cache, path,
|
||||
ret = __add_to_free_space_tree(trans, cache, path,
|
||||
cache->key.objectid + 2 * alignment,
|
||||
alignment);
|
||||
if (ret) {
|
||||
test_msg("Could not add free space\n");
|
||||
test_err("could not add free space");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = __add_to_free_space_tree(trans, fs_info, cache, path,
|
||||
ret = __add_to_free_space_tree(trans, cache, path,
|
||||
cache->key.objectid + alignment,
|
||||
alignment);
|
||||
if (ret) {
|
||||
test_msg("Could not add free space\n");
|
||||
test_err("could not add free space");
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -391,34 +391,34 @@ static int test_merge_none(struct btrfs_trans_handle *trans,
|
||||
};
|
||||
int ret;
|
||||
|
||||
ret = __remove_from_free_space_tree(trans, fs_info, cache, path,
|
||||
ret = __remove_from_free_space_tree(trans, cache, path,
|
||||
cache->key.objectid,
|
||||
cache->key.offset);
|
||||
if (ret) {
|
||||
test_msg("Could not remove free space\n");
|
||||
test_err("could not remove free space");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = __add_to_free_space_tree(trans, fs_info, cache, path,
|
||||
cache->key.objectid, alignment);
|
||||
ret = __add_to_free_space_tree(trans, cache, path, cache->key.objectid,
|
||||
alignment);
|
||||
if (ret) {
|
||||
test_msg("Could not add free space\n");
|
||||
test_err("could not add free space");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = __add_to_free_space_tree(trans, fs_info, cache, path,
|
||||
ret = __add_to_free_space_tree(trans, cache, path,
|
||||
cache->key.objectid + 4 * alignment,
|
||||
alignment);
|
||||
if (ret) {
|
||||
test_msg("Could not add free space\n");
|
||||
test_err("could not add free space");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = __add_to_free_space_tree(trans, fs_info, cache, path,
|
||||
ret = __add_to_free_space_tree(trans, cache, path,
|
||||
cache->key.objectid + 2 * alignment,
|
||||
alignment);
|
||||
if (ret) {
|
||||
test_msg("Could not add free space\n");
|
||||
test_err("could not add free space");
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -444,14 +444,14 @@ static int run_test(test_func_t test_func, int bitmaps, u32 sectorsize,
|
||||
|
||||
fs_info = btrfs_alloc_dummy_fs_info(nodesize, sectorsize);
|
||||
if (!fs_info) {
|
||||
test_msg("Couldn't allocate dummy fs info\n");
|
||||
test_err("couldn't allocate dummy fs info");
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
root = btrfs_alloc_dummy_root(fs_info);
|
||||
if (IS_ERR(root)) {
|
||||
test_msg("Couldn't allocate dummy root\n");
|
||||
test_err("couldn't allocate dummy root");
|
||||
ret = PTR_ERR(root);
|
||||
goto out;
|
||||
}
|
||||
@ -463,7 +463,7 @@ static int run_test(test_func_t test_func, int bitmaps, u32 sectorsize,
|
||||
|
||||
root->node = alloc_test_extent_buffer(root->fs_info, nodesize);
|
||||
if (!root->node) {
|
||||
test_msg("Couldn't allocate dummy buffer\n");
|
||||
test_err("couldn't allocate dummy buffer");
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
@ -473,7 +473,7 @@ static int run_test(test_func_t test_func, int bitmaps, u32 sectorsize,
|
||||
|
||||
cache = btrfs_alloc_dummy_block_group(fs_info, 8 * alignment);
|
||||
if (!cache) {
|
||||
test_msg("Couldn't allocate dummy block group cache\n");
|
||||
test_err("couldn't allocate dummy block group cache");
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
@ -482,26 +482,25 @@ static int run_test(test_func_t test_func, int bitmaps, u32 sectorsize,
|
||||
cache->needs_free_space = 1;
|
||||
cache->fs_info = root->fs_info;
|
||||
|
||||
btrfs_init_dummy_trans(&trans);
|
||||
btrfs_init_dummy_trans(&trans, root->fs_info);
|
||||
|
||||
path = btrfs_alloc_path();
|
||||
if (!path) {
|
||||
test_msg("Couldn't allocate path\n");
|
||||
test_err("couldn't allocate path");
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = add_block_group_free_space(&trans, root->fs_info, cache);
|
||||
ret = add_block_group_free_space(&trans, cache);
|
||||
if (ret) {
|
||||
test_msg("Could not add block group free space\n");
|
||||
test_err("could not add block group free space");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (bitmaps) {
|
||||
ret = convert_free_space_to_bitmaps(&trans, root->fs_info,
|
||||
cache, path);
|
||||
ret = convert_free_space_to_bitmaps(&trans, cache, path);
|
||||
if (ret) {
|
||||
test_msg("Could not convert block group to bitmaps\n");
|
||||
test_err("could not convert block group to bitmaps");
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
@ -510,14 +509,14 @@ static int run_test(test_func_t test_func, int bitmaps, u32 sectorsize,
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
ret = remove_block_group_free_space(&trans, root->fs_info, cache);
|
||||
ret = remove_block_group_free_space(&trans, cache);
|
||||
if (ret) {
|
||||
test_msg("Could not remove block group free space\n");
|
||||
test_err("could not remove block group free space");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (btrfs_header_nritems(root->node) != 0) {
|
||||
test_msg("Free space tree has leftover items\n");
|
||||
test_err("free space tree has leftover items");
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
@ -539,14 +538,16 @@ static int run_test_both_formats(test_func_t test_func, u32 sectorsize,
|
||||
|
||||
ret = run_test(test_func, 0, sectorsize, nodesize, alignment);
|
||||
if (ret) {
|
||||
test_msg("%pf failed with extents, sectorsize=%u, nodesize=%u, alignment=%u\n",
|
||||
test_err(
|
||||
"%pf failed with extents, sectorsize=%u, nodesize=%u, alignment=%u",
|
||||
test_func, sectorsize, nodesize, alignment);
|
||||
test_ret = ret;
|
||||
}
|
||||
|
||||
ret = run_test(test_func, 1, sectorsize, nodesize, alignment);
|
||||
if (ret) {
|
||||
test_msg("%pf failed with bitmaps, sectorsize=%u, nodesize=%u, alignment=%u\n",
|
||||
test_err(
|
||||
"%pf failed with bitmaps, sectorsize=%u, nodesize=%u, alignment=%u",
|
||||
test_func, sectorsize, nodesize, alignment);
|
||||
test_ret = ret;
|
||||
}
|
||||
@ -577,7 +578,7 @@ int btrfs_test_free_space_tree(u32 sectorsize, u32 nodesize)
|
||||
*/
|
||||
bitmap_alignment = BTRFS_FREE_SPACE_BITMAP_BITS * PAGE_SIZE;
|
||||
|
||||
test_msg("Running free space tree tests\n");
|
||||
test_msg("running free space tree tests");
|
||||
for (i = 0; i < ARRAY_SIZE(tests); i++) {
|
||||
int ret;
|
||||
|
||||
|
@ -228,7 +228,7 @@ static noinline int test_btrfs_get_extent(u32 sectorsize, u32 nodesize)
|
||||
|
||||
inode = btrfs_new_test_inode();
|
||||
if (!inode) {
|
||||
test_msg("Couldn't allocate inode\n");
|
||||
test_err("couldn't allocate inode");
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -238,19 +238,19 @@ static noinline int test_btrfs_get_extent(u32 sectorsize, u32 nodesize)
|
||||
|
||||
fs_info = btrfs_alloc_dummy_fs_info(nodesize, sectorsize);
|
||||
if (!fs_info) {
|
||||
test_msg("Couldn't allocate dummy fs info\n");
|
||||
test_err("couldn't allocate dummy fs info");
|
||||
goto out;
|
||||
}
|
||||
|
||||
root = btrfs_alloc_dummy_root(fs_info);
|
||||
if (IS_ERR(root)) {
|
||||
test_msg("Couldn't allocate root\n");
|
||||
test_err("couldn't allocate root");
|
||||
goto out;
|
||||
}
|
||||
|
||||
root->node = alloc_dummy_extent_buffer(fs_info, nodesize);
|
||||
if (!root->node) {
|
||||
test_msg("Couldn't allocate dummy buffer\n");
|
||||
test_err("couldn't allocate dummy buffer");
|
||||
goto out;
|
||||
}
|
||||
|
||||
@ -268,11 +268,11 @@ static noinline int test_btrfs_get_extent(u32 sectorsize, u32 nodesize)
|
||||
em = btrfs_get_extent(BTRFS_I(inode), NULL, 0, 0, sectorsize, 0);
|
||||
if (IS_ERR(em)) {
|
||||
em = NULL;
|
||||
test_msg("Got an error when we shouldn't have\n");
|
||||
test_err("got an error when we shouldn't have");
|
||||
goto out;
|
||||
}
|
||||
if (em->block_start != EXTENT_MAP_HOLE) {
|
||||
test_msg("Expected a hole, got %llu\n", em->block_start);
|
||||
test_err("expected a hole, got %llu", em->block_start);
|
||||
goto out;
|
||||
}
|
||||
free_extent_map(em);
|
||||
@ -287,20 +287,21 @@ static noinline int test_btrfs_get_extent(u32 sectorsize, u32 nodesize)
|
||||
|
||||
em = btrfs_get_extent(BTRFS_I(inode), NULL, 0, 0, (u64)-1, 0);
|
||||
if (IS_ERR(em)) {
|
||||
test_msg("Got an error when we shouldn't have\n");
|
||||
test_err("got an error when we shouldn't have");
|
||||
goto out;
|
||||
}
|
||||
if (em->block_start != EXTENT_MAP_HOLE) {
|
||||
test_msg("Expected a hole, got %llu\n", em->block_start);
|
||||
test_err("expected a hole, got %llu", em->block_start);
|
||||
goto out;
|
||||
}
|
||||
if (em->start != 0 || em->len != 5) {
|
||||
test_msg("Unexpected extent wanted start 0 len 5, got start "
|
||||
"%llu len %llu\n", em->start, em->len);
|
||||
test_err(
|
||||
"unexpected extent wanted start 0 len 5, got start %llu len %llu",
|
||||
em->start, em->len);
|
||||
goto out;
|
||||
}
|
||||
if (em->flags != 0) {
|
||||
test_msg("Unexpected flags set, want 0 have %lu\n", em->flags);
|
||||
test_err("unexpected flags set, want 0 have %lu", em->flags);
|
||||
goto out;
|
||||
}
|
||||
offset = em->start + em->len;
|
||||
@ -308,21 +309,22 @@ static noinline int test_btrfs_get_extent(u32 sectorsize, u32 nodesize)
|
||||
|
||||
em = btrfs_get_extent(BTRFS_I(inode), NULL, 0, offset, sectorsize, 0);
|
||||
if (IS_ERR(em)) {
|
||||
test_msg("Got an error when we shouldn't have\n");
|
||||
test_err("got an error when we shouldn't have");
|
||||
goto out;
|
||||
}
|
||||
if (em->block_start != EXTENT_MAP_INLINE) {
|
||||
test_msg("Expected an inline, got %llu\n", em->block_start);
|
||||
test_err("expected an inline, got %llu", em->block_start);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (em->start != offset || em->len != (sectorsize - 5)) {
|
||||
test_msg("Unexpected extent wanted start %llu len 1, got start "
|
||||
"%llu len %llu\n", offset, em->start, em->len);
|
||||
test_err(
|
||||
"unexpected extent wanted start %llu len 1, got start %llu len %llu",
|
||||
offset, em->start, em->len);
|
||||
goto out;
|
||||
}
|
||||
if (em->flags != 0) {
|
||||
test_msg("Unexpected flags set, want 0 have %lu\n", em->flags);
|
||||
test_err("unexpected flags set, want 0 have %lu", em->flags);
|
||||
goto out;
|
||||
}
|
||||
/*
|
||||
@ -335,20 +337,21 @@ static noinline int test_btrfs_get_extent(u32 sectorsize, u32 nodesize)
|
||||
|
||||
em = btrfs_get_extent(BTRFS_I(inode), NULL, 0, offset, sectorsize, 0);
|
||||
if (IS_ERR(em)) {
|
||||
test_msg("Got an error when we shouldn't have\n");
|
||||
test_err("got an error when we shouldn't have");
|
||||
goto out;
|
||||
}
|
||||
if (em->block_start != EXTENT_MAP_HOLE) {
|
||||
test_msg("Expected a hole, got %llu\n", em->block_start);
|
||||
test_err("expected a hole, got %llu", em->block_start);
|
||||
goto out;
|
||||
}
|
||||
if (em->start != offset || em->len != 4) {
|
||||
test_msg("Unexpected extent wanted start %llu len 4, got start "
|
||||
"%llu len %llu\n", offset, em->start, em->len);
|
||||
test_err(
|
||||
"unexpected extent wanted start %llu len 4, got start %llu len %llu",
|
||||
offset, em->start, em->len);
|
||||
goto out;
|
||||
}
|
||||
if (em->flags != 0) {
|
||||
test_msg("Unexpected flags set, want 0 have %lu\n", em->flags);
|
||||
test_err("unexpected flags set, want 0 have %lu", em->flags);
|
||||
goto out;
|
||||
}
|
||||
offset = em->start + em->len;
|
||||
@ -357,24 +360,25 @@ static noinline int test_btrfs_get_extent(u32 sectorsize, u32 nodesize)
|
||||
/* Regular extent */
|
||||
em = btrfs_get_extent(BTRFS_I(inode), NULL, 0, offset, sectorsize, 0);
|
||||
if (IS_ERR(em)) {
|
||||
test_msg("Got an error when we shouldn't have\n");
|
||||
test_err("got an error when we shouldn't have");
|
||||
goto out;
|
||||
}
|
||||
if (em->block_start >= EXTENT_MAP_LAST_BYTE) {
|
||||
test_msg("Expected a real extent, got %llu\n", em->block_start);
|
||||
test_err("expected a real extent, got %llu", em->block_start);
|
||||
goto out;
|
||||
}
|
||||
if (em->start != offset || em->len != sectorsize - 1) {
|
||||
test_msg("Unexpected extent wanted start %llu len 4095, got "
|
||||
"start %llu len %llu\n", offset, em->start, em->len);
|
||||
test_err(
|
||||
"unexpected extent wanted start %llu len 4095, got start %llu len %llu",
|
||||
offset, em->start, em->len);
|
||||
goto out;
|
||||
}
|
||||
if (em->flags != 0) {
|
||||
test_msg("Unexpected flags set, want 0 have %lu\n", em->flags);
|
||||
test_err("unexpected flags set, want 0 have %lu", em->flags);
|
||||
goto out;
|
||||
}
|
||||
if (em->orig_start != em->start) {
|
||||
test_msg("Wrong orig offset, want %llu, have %llu\n", em->start,
|
||||
test_err("wrong orig offset, want %llu, have %llu", em->start,
|
||||
em->orig_start);
|
||||
goto out;
|
||||
}
|
||||
@ -384,25 +388,25 @@ static noinline int test_btrfs_get_extent(u32 sectorsize, u32 nodesize)
|
||||
/* The next 3 are split extents */
|
||||
em = btrfs_get_extent(BTRFS_I(inode), NULL, 0, offset, sectorsize, 0);
|
||||
if (IS_ERR(em)) {
|
||||
test_msg("Got an error when we shouldn't have\n");
|
||||
test_err("got an error when we shouldn't have");
|
||||
goto out;
|
||||
}
|
||||
if (em->block_start >= EXTENT_MAP_LAST_BYTE) {
|
||||
test_msg("Expected a real extent, got %llu\n", em->block_start);
|
||||
test_err("expected a real extent, got %llu", em->block_start);
|
||||
goto out;
|
||||
}
|
||||
if (em->start != offset || em->len != sectorsize) {
|
||||
test_msg("Unexpected extent start %llu len %u, "
|
||||
"got start %llu len %llu\n",
|
||||
test_err(
|
||||
"unexpected extent start %llu len %u, got start %llu len %llu",
|
||||
offset, sectorsize, em->start, em->len);
|
||||
goto out;
|
||||
}
|
||||
if (em->flags != 0) {
|
||||
test_msg("Unexpected flags set, want 0 have %lu\n", em->flags);
|
||||
test_err("unexpected flags set, want 0 have %lu", em->flags);
|
||||
goto out;
|
||||
}
|
||||
if (em->orig_start != em->start) {
|
||||
test_msg("Wrong orig offset, want %llu, have %llu\n", em->start,
|
||||
test_err("wrong orig offset, want %llu, have %llu", em->start,
|
||||
em->orig_start);
|
||||
goto out;
|
||||
}
|
||||
@ -413,21 +417,21 @@ static noinline int test_btrfs_get_extent(u32 sectorsize, u32 nodesize)
|
||||
|
||||
em = btrfs_get_extent(BTRFS_I(inode), NULL, 0, offset, sectorsize, 0);
|
||||
if (IS_ERR(em)) {
|
||||
test_msg("Got an error when we shouldn't have\n");
|
||||
test_err("got an error when we shouldn't have");
|
||||
goto out;
|
||||
}
|
||||
if (em->block_start != EXTENT_MAP_HOLE) {
|
||||
test_msg("Expected a hole, got %llu\n", em->block_start);
|
||||
test_err("expected a hole, got %llu", em->block_start);
|
||||
goto out;
|
||||
}
|
||||
if (em->start != offset || em->len != sectorsize) {
|
||||
test_msg("Unexpected extent wanted start %llu len %u, "
|
||||
"got start %llu len %llu\n",
|
||||
test_err(
|
||||
"unexpected extent wanted start %llu len %u, got start %llu len %llu",
|
||||
offset, sectorsize, em->start, em->len);
|
||||
goto out;
|
||||
}
|
||||
if (em->flags != 0) {
|
||||
test_msg("Unexpected flags set, want 0 have %lu\n", em->flags);
|
||||
test_err("unexpected flags set, want 0 have %lu", em->flags);
|
||||
goto out;
|
||||
}
|
||||
offset = em->start + em->len;
|
||||
@ -435,31 +439,31 @@ static noinline int test_btrfs_get_extent(u32 sectorsize, u32 nodesize)
|
||||
|
||||
em = btrfs_get_extent(BTRFS_I(inode), NULL, 0, offset, sectorsize, 0);
|
||||
if (IS_ERR(em)) {
|
||||
test_msg("Got an error when we shouldn't have\n");
|
||||
test_err("got an error when we shouldn't have");
|
||||
goto out;
|
||||
}
|
||||
if (em->block_start >= EXTENT_MAP_LAST_BYTE) {
|
||||
test_msg("Expected a real extent, got %llu\n", em->block_start);
|
||||
test_err("expected a real extent, got %llu", em->block_start);
|
||||
goto out;
|
||||
}
|
||||
if (em->start != offset || em->len != 2 * sectorsize) {
|
||||
test_msg("Unexpected extent wanted start %llu len %u, "
|
||||
"got start %llu len %llu\n",
|
||||
test_err(
|
||||
"unexpected extent wanted start %llu len %u, got start %llu len %llu",
|
||||
offset, 2 * sectorsize, em->start, em->len);
|
||||
goto out;
|
||||
}
|
||||
if (em->flags != 0) {
|
||||
test_msg("Unexpected flags set, want 0 have %lu\n", em->flags);
|
||||
test_err("unexpected flags set, want 0 have %lu", em->flags);
|
||||
goto out;
|
||||
}
|
||||
if (em->orig_start != orig_start) {
|
||||
test_msg("Wrong orig offset, want %llu, have %llu\n",
|
||||
test_err("wrong orig offset, want %llu, have %llu",
|
||||
orig_start, em->orig_start);
|
||||
goto out;
|
||||
}
|
||||
disk_bytenr += (em->start - orig_start);
|
||||
if (em->block_start != disk_bytenr) {
|
||||
test_msg("Wrong block start, want %llu, have %llu\n",
|
||||
test_err("wrong block start, want %llu, have %llu",
|
||||
disk_bytenr, em->block_start);
|
||||
goto out;
|
||||
}
|
||||
@ -469,26 +473,26 @@ static noinline int test_btrfs_get_extent(u32 sectorsize, u32 nodesize)
|
||||
/* Prealloc extent */
|
||||
em = btrfs_get_extent(BTRFS_I(inode), NULL, 0, offset, sectorsize, 0);
|
||||
if (IS_ERR(em)) {
|
||||
test_msg("Got an error when we shouldn't have\n");
|
||||
test_err("got an error when we shouldn't have");
|
||||
goto out;
|
||||
}
|
||||
if (em->block_start >= EXTENT_MAP_LAST_BYTE) {
|
||||
test_msg("Expected a real extent, got %llu\n", em->block_start);
|
||||
test_err("expected a real extent, got %llu", em->block_start);
|
||||
goto out;
|
||||
}
|
||||
if (em->start != offset || em->len != sectorsize) {
|
||||
test_msg("Unexpected extent wanted start %llu len %u, "
|
||||
"got start %llu len %llu\n",
|
||||
test_err(
|
||||
"unexpected extent wanted start %llu len %u, got start %llu len %llu",
|
||||
offset, sectorsize, em->start, em->len);
|
||||
goto out;
|
||||
}
|
||||
if (em->flags != prealloc_only) {
|
||||
test_msg("Unexpected flags set, want %lu have %lu\n",
|
||||
test_err("unexpected flags set, want %lu have %lu",
|
||||
prealloc_only, em->flags);
|
||||
goto out;
|
||||
}
|
||||
if (em->orig_start != em->start) {
|
||||
test_msg("Wrong orig offset, want %llu, have %llu\n", em->start,
|
||||
test_err("wrong orig offset, want %llu, have %llu", em->start,
|
||||
em->orig_start);
|
||||
goto out;
|
||||
}
|
||||
@ -498,26 +502,26 @@ static noinline int test_btrfs_get_extent(u32 sectorsize, u32 nodesize)
|
||||
/* The next 3 are a half written prealloc extent */
|
||||
em = btrfs_get_extent(BTRFS_I(inode), NULL, 0, offset, sectorsize, 0);
|
||||
if (IS_ERR(em)) {
|
||||
test_msg("Got an error when we shouldn't have\n");
|
||||
test_err("got an error when we shouldn't have");
|
||||
goto out;
|
||||
}
|
||||
if (em->block_start >= EXTENT_MAP_LAST_BYTE) {
|
||||
test_msg("Expected a real extent, got %llu\n", em->block_start);
|
||||
test_err("expected a real extent, got %llu", em->block_start);
|
||||
goto out;
|
||||
}
|
||||
if (em->start != offset || em->len != sectorsize) {
|
||||
test_msg("Unexpected extent wanted start %llu len %u, "
|
||||
"got start %llu len %llu\n",
|
||||
test_err(
|
||||
"unexpected extent wanted start %llu len %u, got start %llu len %llu",
|
||||
offset, sectorsize, em->start, em->len);
|
||||
goto out;
|
||||
}
|
||||
if (em->flags != prealloc_only) {
|
||||
test_msg("Unexpected flags set, want %lu have %lu\n",
|
||||
test_err("unexpected flags set, want %lu have %lu",
|
||||
prealloc_only, em->flags);
|
||||
goto out;
|
||||
}
|
||||
if (em->orig_start != em->start) {
|
||||
test_msg("Wrong orig offset, want %llu, have %llu\n", em->start,
|
||||
test_err("wrong orig offset, want %llu, have %llu", em->start,
|
||||
em->orig_start);
|
||||
goto out;
|
||||
}
|
||||
@ -528,30 +532,30 @@ static noinline int test_btrfs_get_extent(u32 sectorsize, u32 nodesize)
|
||||
|
||||
em = btrfs_get_extent(BTRFS_I(inode), NULL, 0, offset, sectorsize, 0);
|
||||
if (IS_ERR(em)) {
|
||||
test_msg("Got an error when we shouldn't have\n");
|
||||
test_err("got an error when we shouldn't have");
|
||||
goto out;
|
||||
}
|
||||
if (em->block_start >= EXTENT_MAP_HOLE) {
|
||||
test_msg("Expected a real extent, got %llu\n", em->block_start);
|
||||
test_err("expected a real extent, got %llu", em->block_start);
|
||||
goto out;
|
||||
}
|
||||
if (em->start != offset || em->len != sectorsize) {
|
||||
test_msg("Unexpected extent wanted start %llu len %u, "
|
||||
"got start %llu len %llu\n",
|
||||
test_err(
|
||||
"unexpected extent wanted start %llu len %u, got start %llu len %llu",
|
||||
offset, sectorsize, em->start, em->len);
|
||||
goto out;
|
||||
}
|
||||
if (em->flags != 0) {
|
||||
test_msg("Unexpected flags set, want 0 have %lu\n", em->flags);
|
||||
test_err("unexpected flags set, want 0 have %lu", em->flags);
|
||||
goto out;
|
||||
}
|
||||
if (em->orig_start != orig_start) {
|
||||
test_msg("Unexpected orig offset, wanted %llu, have %llu\n",
|
||||
test_err("unexpected orig offset, wanted %llu, have %llu",
|
||||
orig_start, em->orig_start);
|
||||
goto out;
|
||||
}
|
||||
if (em->block_start != (disk_bytenr + (em->start - em->orig_start))) {
|
||||
test_msg("Unexpected block start, wanted %llu, have %llu\n",
|
||||
test_err("unexpected block start, wanted %llu, have %llu",
|
||||
disk_bytenr + (em->start - em->orig_start),
|
||||
em->block_start);
|
||||
goto out;
|
||||
@ -561,31 +565,31 @@ static noinline int test_btrfs_get_extent(u32 sectorsize, u32 nodesize)
|
||||
|
||||
em = btrfs_get_extent(BTRFS_I(inode), NULL, 0, offset, sectorsize, 0);
|
||||
if (IS_ERR(em)) {
|
||||
test_msg("Got an error when we shouldn't have\n");
|
||||
test_err("got an error when we shouldn't have");
|
||||
goto out;
|
||||
}
|
||||
if (em->block_start >= EXTENT_MAP_LAST_BYTE) {
|
||||
test_msg("Expected a real extent, got %llu\n", em->block_start);
|
||||
test_err("expected a real extent, got %llu", em->block_start);
|
||||
goto out;
|
||||
}
|
||||
if (em->start != offset || em->len != 2 * sectorsize) {
|
||||
test_msg("Unexpected extent wanted start %llu len %u, "
|
||||
"got start %llu len %llu\n",
|
||||
test_err(
|
||||
"unexpected extent wanted start %llu len %u, got start %llu len %llu",
|
||||
offset, 2 * sectorsize, em->start, em->len);
|
||||
goto out;
|
||||
}
|
||||
if (em->flags != prealloc_only) {
|
||||
test_msg("Unexpected flags set, want %lu have %lu\n",
|
||||
test_err("unexpected flags set, want %lu have %lu",
|
||||
prealloc_only, em->flags);
|
||||
goto out;
|
||||
}
|
||||
if (em->orig_start != orig_start) {
|
||||
test_msg("Wrong orig offset, want %llu, have %llu\n", orig_start,
|
||||
test_err("wrong orig offset, want %llu, have %llu", orig_start,
|
||||
em->orig_start);
|
||||
goto out;
|
||||
}
|
||||
if (em->block_start != (disk_bytenr + (em->start - em->orig_start))) {
|
||||
test_msg("Unexpected block start, wanted %llu, have %llu\n",
|
||||
test_err("unexpected block start, wanted %llu, have %llu",
|
||||
disk_bytenr + (em->start - em->orig_start),
|
||||
em->block_start);
|
||||
goto out;
|
||||
@ -596,31 +600,31 @@ static noinline int test_btrfs_get_extent(u32 sectorsize, u32 nodesize)
|
||||
/* Now for the compressed extent */
|
||||
em = btrfs_get_extent(BTRFS_I(inode), NULL, 0, offset, sectorsize, 0);
|
||||
if (IS_ERR(em)) {
|
||||
test_msg("Got an error when we shouldn't have\n");
|
||||
test_err("got an error when we shouldn't have");
|
||||
goto out;
|
||||
}
|
||||
if (em->block_start >= EXTENT_MAP_LAST_BYTE) {
|
||||
test_msg("Expected a real extent, got %llu\n", em->block_start);
|
||||
test_err("expected a real extent, got %llu", em->block_start);
|
||||
goto out;
|
||||
}
|
||||
if (em->start != offset || em->len != 2 * sectorsize) {
|
||||
test_msg("Unexpected extent wanted start %llu len %u,"
|
||||
"got start %llu len %llu\n",
|
||||
test_err(
|
||||
"unexpected extent wanted start %llu len %u, got start %llu len %llu",
|
||||
offset, 2 * sectorsize, em->start, em->len);
|
||||
goto out;
|
||||
}
|
||||
if (em->flags != compressed_only) {
|
||||
test_msg("Unexpected flags set, want %lu have %lu\n",
|
||||
test_err("unexpected flags set, want %lu have %lu",
|
||||
compressed_only, em->flags);
|
||||
goto out;
|
||||
}
|
||||
if (em->orig_start != em->start) {
|
||||
test_msg("Wrong orig offset, want %llu, have %llu\n",
|
||||
test_err("wrong orig offset, want %llu, have %llu",
|
||||
em->start, em->orig_start);
|
||||
goto out;
|
||||
}
|
||||
if (em->compress_type != BTRFS_COMPRESS_ZLIB) {
|
||||
test_msg("Unexpected compress type, wanted %d, got %d\n",
|
||||
test_err("unexpected compress type, wanted %d, got %d",
|
||||
BTRFS_COMPRESS_ZLIB, em->compress_type);
|
||||
goto out;
|
||||
}
|
||||
@ -630,31 +634,31 @@ static noinline int test_btrfs_get_extent(u32 sectorsize, u32 nodesize)
|
||||
/* Split compressed extent */
|
||||
em = btrfs_get_extent(BTRFS_I(inode), NULL, 0, offset, sectorsize, 0);
|
||||
if (IS_ERR(em)) {
|
||||
test_msg("Got an error when we shouldn't have\n");
|
||||
test_err("got an error when we shouldn't have");
|
||||
goto out;
|
||||
}
|
||||
if (em->block_start >= EXTENT_MAP_LAST_BYTE) {
|
||||
test_msg("Expected a real extent, got %llu\n", em->block_start);
|
||||
test_err("expected a real extent, got %llu", em->block_start);
|
||||
goto out;
|
||||
}
|
||||
if (em->start != offset || em->len != sectorsize) {
|
||||
test_msg("Unexpected extent wanted start %llu len %u,"
|
||||
"got start %llu len %llu\n",
|
||||
test_err(
|
||||
"unexpected extent wanted start %llu len %u, got start %llu len %llu",
|
||||
offset, sectorsize, em->start, em->len);
|
||||
goto out;
|
||||
}
|
||||
if (em->flags != compressed_only) {
|
||||
test_msg("Unexpected flags set, want %lu have %lu\n",
|
||||
test_err("unexpected flags set, want %lu have %lu",
|
||||
compressed_only, em->flags);
|
||||
goto out;
|
||||
}
|
||||
if (em->orig_start != em->start) {
|
||||
test_msg("Wrong orig offset, want %llu, have %llu\n",
|
||||
test_err("wrong orig offset, want %llu, have %llu",
|
||||
em->start, em->orig_start);
|
||||
goto out;
|
||||
}
|
||||
if (em->compress_type != BTRFS_COMPRESS_ZLIB) {
|
||||
test_msg("Unexpected compress type, wanted %d, got %d\n",
|
||||
test_err("unexpected compress type, wanted %d, got %d",
|
||||
BTRFS_COMPRESS_ZLIB, em->compress_type);
|
||||
goto out;
|
||||
}
|
||||
@ -665,25 +669,25 @@ static noinline int test_btrfs_get_extent(u32 sectorsize, u32 nodesize)
|
||||
|
||||
em = btrfs_get_extent(BTRFS_I(inode), NULL, 0, offset, sectorsize, 0);
|
||||
if (IS_ERR(em)) {
|
||||
test_msg("Got an error when we shouldn't have\n");
|
||||
test_err("got an error when we shouldn't have");
|
||||
goto out;
|
||||
}
|
||||
if (em->block_start >= EXTENT_MAP_LAST_BYTE) {
|
||||
test_msg("Expected a real extent, got %llu\n", em->block_start);
|
||||
test_err("expected a real extent, got %llu", em->block_start);
|
||||
goto out;
|
||||
}
|
||||
if (em->start != offset || em->len != sectorsize) {
|
||||
test_msg("Unexpected extent wanted start %llu len %u, "
|
||||
"got start %llu len %llu\n",
|
||||
test_err(
|
||||
"unexpected extent wanted start %llu len %u, got start %llu len %llu",
|
||||
offset, sectorsize, em->start, em->len);
|
||||
goto out;
|
||||
}
|
||||
if (em->flags != 0) {
|
||||
test_msg("Unexpected flags set, want 0 have %lu\n", em->flags);
|
||||
test_err("unexpected flags set, want 0 have %lu", em->flags);
|
||||
goto out;
|
||||
}
|
||||
if (em->orig_start != em->start) {
|
||||
test_msg("Wrong orig offset, want %llu, have %llu\n", em->start,
|
||||
test_err("wrong orig offset, want %llu, have %llu", em->start,
|
||||
em->orig_start);
|
||||
goto out;
|
||||
}
|
||||
@ -692,32 +696,32 @@ static noinline int test_btrfs_get_extent(u32 sectorsize, u32 nodesize)
|
||||
|
||||
em = btrfs_get_extent(BTRFS_I(inode), NULL, 0, offset, sectorsize, 0);
|
||||
if (IS_ERR(em)) {
|
||||
test_msg("Got an error when we shouldn't have\n");
|
||||
test_err("got an error when we shouldn't have");
|
||||
goto out;
|
||||
}
|
||||
if (em->block_start != disk_bytenr) {
|
||||
test_msg("Block start does not match, want %llu got %llu\n",
|
||||
test_err("block start does not match, want %llu got %llu",
|
||||
disk_bytenr, em->block_start);
|
||||
goto out;
|
||||
}
|
||||
if (em->start != offset || em->len != 2 * sectorsize) {
|
||||
test_msg("Unexpected extent wanted start %llu len %u, "
|
||||
"got start %llu len %llu\n",
|
||||
test_err(
|
||||
"unexpected extent wanted start %llu len %u, got start %llu len %llu",
|
||||
offset, 2 * sectorsize, em->start, em->len);
|
||||
goto out;
|
||||
}
|
||||
if (em->flags != compressed_only) {
|
||||
test_msg("Unexpected flags set, want %lu have %lu\n",
|
||||
test_err("unexpected flags set, want %lu have %lu",
|
||||
compressed_only, em->flags);
|
||||
goto out;
|
||||
}
|
||||
if (em->orig_start != orig_start) {
|
||||
test_msg("Wrong orig offset, want %llu, have %llu\n",
|
||||
test_err("wrong orig offset, want %llu, have %llu",
|
||||
em->start, orig_start);
|
||||
goto out;
|
||||
}
|
||||
if (em->compress_type != BTRFS_COMPRESS_ZLIB) {
|
||||
test_msg("Unexpected compress type, wanted %d, got %d\n",
|
||||
test_err("unexpected compress type, wanted %d, got %d",
|
||||
BTRFS_COMPRESS_ZLIB, em->compress_type);
|
||||
goto out;
|
||||
}
|
||||
@ -728,25 +732,25 @@ static noinline int test_btrfs_get_extent(u32 sectorsize, u32 nodesize)
|
||||
em = btrfs_get_extent(BTRFS_I(inode), NULL, 0, offset + 6,
|
||||
sectorsize, 0);
|
||||
if (IS_ERR(em)) {
|
||||
test_msg("Got an error when we shouldn't have\n");
|
||||
test_err("got an error when we shouldn't have");
|
||||
goto out;
|
||||
}
|
||||
if (em->block_start >= EXTENT_MAP_LAST_BYTE) {
|
||||
test_msg("Expected a real extent, got %llu\n", em->block_start);
|
||||
test_err("expected a real extent, got %llu", em->block_start);
|
||||
goto out;
|
||||
}
|
||||
if (em->start != offset || em->len != sectorsize) {
|
||||
test_msg("Unexpected extent wanted start %llu len %u, "
|
||||
"got start %llu len %llu\n",
|
||||
test_err(
|
||||
"unexpected extent wanted start %llu len %u, got start %llu len %llu",
|
||||
offset, sectorsize, em->start, em->len);
|
||||
goto out;
|
||||
}
|
||||
if (em->flags != 0) {
|
||||
test_msg("Unexpected flags set, want 0 have %lu\n", em->flags);
|
||||
test_err("unexpected flags set, want 0 have %lu", em->flags);
|
||||
goto out;
|
||||
}
|
||||
if (em->orig_start != em->start) {
|
||||
test_msg("Wrong orig offset, want %llu, have %llu\n", em->start,
|
||||
test_err("wrong orig offset, want %llu, have %llu", em->start,
|
||||
em->orig_start);
|
||||
goto out;
|
||||
}
|
||||
@ -755,11 +759,11 @@ static noinline int test_btrfs_get_extent(u32 sectorsize, u32 nodesize)
|
||||
|
||||
em = btrfs_get_extent(BTRFS_I(inode), NULL, 0, offset, SZ_4M, 0);
|
||||
if (IS_ERR(em)) {
|
||||
test_msg("Got an error when we shouldn't have\n");
|
||||
test_err("got an error when we shouldn't have");
|
||||
goto out;
|
||||
}
|
||||
if (em->block_start != EXTENT_MAP_HOLE) {
|
||||
test_msg("Expected a hole extent, got %llu\n", em->block_start);
|
||||
test_err("expected a hole extent, got %llu", em->block_start);
|
||||
goto out;
|
||||
}
|
||||
/*
|
||||
@ -768,18 +772,18 @@ static noinline int test_btrfs_get_extent(u32 sectorsize, u32 nodesize)
|
||||
* test.
|
||||
*/
|
||||
if (em->start != offset || em->len != 3 * sectorsize) {
|
||||
test_msg("Unexpected extent wanted start %llu len %u, "
|
||||
"got start %llu len %llu\n",
|
||||
test_err(
|
||||
"unexpected extent wanted start %llu len %u, got start %llu len %llu",
|
||||
offset, 3 * sectorsize, em->start, em->len);
|
||||
goto out;
|
||||
}
|
||||
if (em->flags != vacancy_only) {
|
||||
test_msg("Unexpected flags set, want %lu have %lu\n",
|
||||
test_err("unexpected flags set, want %lu have %lu",
|
||||
vacancy_only, em->flags);
|
||||
goto out;
|
||||
}
|
||||
if (em->orig_start != em->start) {
|
||||
test_msg("Wrong orig offset, want %llu, have %llu\n", em->start,
|
||||
test_err("wrong orig offset, want %llu, have %llu", em->start,
|
||||
em->orig_start);
|
||||
goto out;
|
||||
}
|
||||
@ -788,25 +792,25 @@ static noinline int test_btrfs_get_extent(u32 sectorsize, u32 nodesize)
|
||||
|
||||
em = btrfs_get_extent(BTRFS_I(inode), NULL, 0, offset, sectorsize, 0);
|
||||
if (IS_ERR(em)) {
|
||||
test_msg("Got an error when we shouldn't have\n");
|
||||
test_err("got an error when we shouldn't have");
|
||||
goto out;
|
||||
}
|
||||
if (em->block_start >= EXTENT_MAP_LAST_BYTE) {
|
||||
test_msg("Expected a real extent, got %llu\n", em->block_start);
|
||||
test_err("expected a real extent, got %llu", em->block_start);
|
||||
goto out;
|
||||
}
|
||||
if (em->start != offset || em->len != sectorsize) {
|
||||
test_msg("Unexpected extent wanted start %llu len %u,"
|
||||
"got start %llu len %llu\n",
|
||||
test_err(
|
||||
"unexpected extent wanted start %llu len %u, got start %llu len %llu",
|
||||
offset, sectorsize, em->start, em->len);
|
||||
goto out;
|
||||
}
|
||||
if (em->flags != 0) {
|
||||
test_msg("Unexpected flags set, want 0 have %lu\n", em->flags);
|
||||
test_err("unexpected flags set, want 0 have %lu", em->flags);
|
||||
goto out;
|
||||
}
|
||||
if (em->orig_start != em->start) {
|
||||
test_msg("Wrong orig offset, want %llu, have %llu\n", em->start,
|
||||
test_err("wrong orig offset, want %llu, have %llu", em->start,
|
||||
em->orig_start);
|
||||
goto out;
|
||||
}
|
||||
@ -830,7 +834,7 @@ static int test_hole_first(u32 sectorsize, u32 nodesize)
|
||||
|
||||
inode = btrfs_new_test_inode();
|
||||
if (!inode) {
|
||||
test_msg("Couldn't allocate inode\n");
|
||||
test_err("couldn't allocate inode");
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -840,19 +844,19 @@ static int test_hole_first(u32 sectorsize, u32 nodesize)
|
||||
|
||||
fs_info = btrfs_alloc_dummy_fs_info(nodesize, sectorsize);
|
||||
if (!fs_info) {
|
||||
test_msg("Couldn't allocate dummy fs info\n");
|
||||
test_err("couldn't allocate dummy fs info");
|
||||
goto out;
|
||||
}
|
||||
|
||||
root = btrfs_alloc_dummy_root(fs_info);
|
||||
if (IS_ERR(root)) {
|
||||
test_msg("Couldn't allocate root\n");
|
||||
test_err("couldn't allocate root");
|
||||
goto out;
|
||||
}
|
||||
|
||||
root->node = alloc_dummy_extent_buffer(fs_info, nodesize);
|
||||
if (!root->node) {
|
||||
test_msg("Couldn't allocate dummy buffer\n");
|
||||
test_err("couldn't allocate dummy buffer");
|
||||
goto out;
|
||||
}
|
||||
|
||||
@ -871,21 +875,21 @@ static int test_hole_first(u32 sectorsize, u32 nodesize)
|
||||
sectorsize, BTRFS_FILE_EXTENT_REG, 0, 1);
|
||||
em = btrfs_get_extent(BTRFS_I(inode), NULL, 0, 0, 2 * sectorsize, 0);
|
||||
if (IS_ERR(em)) {
|
||||
test_msg("Got an error when we shouldn't have\n");
|
||||
test_err("got an error when we shouldn't have");
|
||||
goto out;
|
||||
}
|
||||
if (em->block_start != EXTENT_MAP_HOLE) {
|
||||
test_msg("Expected a hole, got %llu\n", em->block_start);
|
||||
test_err("expected a hole, got %llu", em->block_start);
|
||||
goto out;
|
||||
}
|
||||
if (em->start != 0 || em->len != sectorsize) {
|
||||
test_msg("Unexpected extent wanted start 0 len %u, "
|
||||
"got start %llu len %llu\n",
|
||||
test_err(
|
||||
"unexpected extent wanted start 0 len %u, got start %llu len %llu",
|
||||
sectorsize, em->start, em->len);
|
||||
goto out;
|
||||
}
|
||||
if (em->flags != vacancy_only) {
|
||||
test_msg("Wrong flags, wanted %lu, have %lu\n", vacancy_only,
|
||||
test_err("wrong flags, wanted %lu, have %lu", vacancy_only,
|
||||
em->flags);
|
||||
goto out;
|
||||
}
|
||||
@ -894,21 +898,21 @@ static int test_hole_first(u32 sectorsize, u32 nodesize)
|
||||
em = btrfs_get_extent(BTRFS_I(inode), NULL, 0, sectorsize,
|
||||
2 * sectorsize, 0);
|
||||
if (IS_ERR(em)) {
|
||||
test_msg("Got an error when we shouldn't have\n");
|
||||
test_err("got an error when we shouldn't have");
|
||||
goto out;
|
||||
}
|
||||
if (em->block_start != sectorsize) {
|
||||
test_msg("Expected a real extent, got %llu\n", em->block_start);
|
||||
test_err("expected a real extent, got %llu", em->block_start);
|
||||
goto out;
|
||||
}
|
||||
if (em->start != sectorsize || em->len != sectorsize) {
|
||||
test_msg("Unexpected extent wanted start %u len %u, "
|
||||
"got start %llu len %llu\n",
|
||||
test_err(
|
||||
"unexpected extent wanted start %u len %u, got start %llu len %llu",
|
||||
sectorsize, sectorsize, em->start, em->len);
|
||||
goto out;
|
||||
}
|
||||
if (em->flags != 0) {
|
||||
test_msg("Unexpected flags set, wanted 0 got %lu\n",
|
||||
test_err("unexpected flags set, wanted 0 got %lu",
|
||||
em->flags);
|
||||
goto out;
|
||||
}
|
||||
@ -931,19 +935,19 @@ static int test_extent_accounting(u32 sectorsize, u32 nodesize)
|
||||
|
||||
inode = btrfs_new_test_inode();
|
||||
if (!inode) {
|
||||
test_msg("Couldn't allocate inode\n");
|
||||
test_err("couldn't allocate inode");
|
||||
return ret;
|
||||
}
|
||||
|
||||
fs_info = btrfs_alloc_dummy_fs_info(nodesize, sectorsize);
|
||||
if (!fs_info) {
|
||||
test_msg("Couldn't allocate dummy fs info\n");
|
||||
test_err("couldn't allocate dummy fs info");
|
||||
goto out;
|
||||
}
|
||||
|
||||
root = btrfs_alloc_dummy_root(fs_info);
|
||||
if (IS_ERR(root)) {
|
||||
test_msg("Couldn't allocate root\n");
|
||||
test_err("couldn't allocate root");
|
||||
goto out;
|
||||
}
|
||||
|
||||
@ -954,12 +958,12 @@ static int test_extent_accounting(u32 sectorsize, u32 nodesize)
|
||||
ret = btrfs_set_extent_delalloc(inode, 0, BTRFS_MAX_EXTENT_SIZE - 1, 0,
|
||||
NULL, 0);
|
||||
if (ret) {
|
||||
test_msg("btrfs_set_extent_delalloc returned %d\n", ret);
|
||||
test_err("btrfs_set_extent_delalloc returned %d", ret);
|
||||
goto out;
|
||||
}
|
||||
if (BTRFS_I(inode)->outstanding_extents != 1) {
|
||||
ret = -EINVAL;
|
||||
test_msg("Miscount, wanted 1, got %u\n",
|
||||
test_err("miscount, wanted 1, got %u",
|
||||
BTRFS_I(inode)->outstanding_extents);
|
||||
goto out;
|
||||
}
|
||||
@ -969,12 +973,12 @@ static int test_extent_accounting(u32 sectorsize, u32 nodesize)
|
||||
BTRFS_MAX_EXTENT_SIZE + sectorsize - 1,
|
||||
0, NULL, 0);
|
||||
if (ret) {
|
||||
test_msg("btrfs_set_extent_delalloc returned %d\n", ret);
|
||||
test_err("btrfs_set_extent_delalloc returned %d", ret);
|
||||
goto out;
|
||||
}
|
||||
if (BTRFS_I(inode)->outstanding_extents != 2) {
|
||||
ret = -EINVAL;
|
||||
test_msg("Miscount, wanted 2, got %u\n",
|
||||
test_err("miscount, wanted 2, got %u",
|
||||
BTRFS_I(inode)->outstanding_extents);
|
||||
goto out;
|
||||
}
|
||||
@ -986,12 +990,12 @@ static int test_extent_accounting(u32 sectorsize, u32 nodesize)
|
||||
EXTENT_DELALLOC | EXTENT_DIRTY |
|
||||
EXTENT_UPTODATE, 0, 0, NULL);
|
||||
if (ret) {
|
||||
test_msg("clear_extent_bit returned %d\n", ret);
|
||||
test_err("clear_extent_bit returned %d", ret);
|
||||
goto out;
|
||||
}
|
||||
if (BTRFS_I(inode)->outstanding_extents != 2) {
|
||||
ret = -EINVAL;
|
||||
test_msg("Miscount, wanted 2, got %u\n",
|
||||
test_err("miscount, wanted 2, got %u",
|
||||
BTRFS_I(inode)->outstanding_extents);
|
||||
goto out;
|
||||
}
|
||||
@ -1002,12 +1006,12 @@ static int test_extent_accounting(u32 sectorsize, u32 nodesize)
|
||||
+ sectorsize - 1,
|
||||
0, NULL, 0);
|
||||
if (ret) {
|
||||
test_msg("btrfs_set_extent_delalloc returned %d\n", ret);
|
||||
test_err("btrfs_set_extent_delalloc returned %d", ret);
|
||||
goto out;
|
||||
}
|
||||
if (BTRFS_I(inode)->outstanding_extents != 2) {
|
||||
ret = -EINVAL;
|
||||
test_msg("Miscount, wanted 2, got %u\n",
|
||||
test_err("miscount, wanted 2, got %u",
|
||||
BTRFS_I(inode)->outstanding_extents);
|
||||
goto out;
|
||||
}
|
||||
@ -1020,12 +1024,12 @@ static int test_extent_accounting(u32 sectorsize, u32 nodesize)
|
||||
(BTRFS_MAX_EXTENT_SIZE << 1) + 3 * sectorsize - 1,
|
||||
0, NULL, 0);
|
||||
if (ret) {
|
||||
test_msg("btrfs_set_extent_delalloc returned %d\n", ret);
|
||||
test_err("btrfs_set_extent_delalloc returned %d", ret);
|
||||
goto out;
|
||||
}
|
||||
if (BTRFS_I(inode)->outstanding_extents != 4) {
|
||||
ret = -EINVAL;
|
||||
test_msg("Miscount, wanted 4, got %u\n",
|
||||
test_err("miscount, wanted 4, got %u",
|
||||
BTRFS_I(inode)->outstanding_extents);
|
||||
goto out;
|
||||
}
|
||||
@ -1037,12 +1041,12 @@ static int test_extent_accounting(u32 sectorsize, u32 nodesize)
|
||||
BTRFS_MAX_EXTENT_SIZE + sectorsize,
|
||||
BTRFS_MAX_EXTENT_SIZE + 2 * sectorsize - 1, 0, NULL, 0);
|
||||
if (ret) {
|
||||
test_msg("btrfs_set_extent_delalloc returned %d\n", ret);
|
||||
test_err("btrfs_set_extent_delalloc returned %d", ret);
|
||||
goto out;
|
||||
}
|
||||
if (BTRFS_I(inode)->outstanding_extents != 3) {
|
||||
ret = -EINVAL;
|
||||
test_msg("Miscount, wanted 3, got %u\n",
|
||||
test_err("miscount, wanted 3, got %u",
|
||||
BTRFS_I(inode)->outstanding_extents);
|
||||
goto out;
|
||||
}
|
||||
@ -1054,12 +1058,12 @@ static int test_extent_accounting(u32 sectorsize, u32 nodesize)
|
||||
EXTENT_DIRTY | EXTENT_DELALLOC |
|
||||
EXTENT_UPTODATE, 0, 0, NULL);
|
||||
if (ret) {
|
||||
test_msg("clear_extent_bit returned %d\n", ret);
|
||||
test_err("clear_extent_bit returned %d", ret);
|
||||
goto out;
|
||||
}
|
||||
if (BTRFS_I(inode)->outstanding_extents != 4) {
|
||||
ret = -EINVAL;
|
||||
test_msg("Miscount, wanted 4, got %u\n",
|
||||
test_err("miscount, wanted 4, got %u",
|
||||
BTRFS_I(inode)->outstanding_extents);
|
||||
goto out;
|
||||
}
|
||||
@ -1072,12 +1076,12 @@ static int test_extent_accounting(u32 sectorsize, u32 nodesize)
|
||||
BTRFS_MAX_EXTENT_SIZE + sectorsize,
|
||||
BTRFS_MAX_EXTENT_SIZE + 2 * sectorsize - 1, 0, NULL, 0);
|
||||
if (ret) {
|
||||
test_msg("btrfs_set_extent_delalloc returned %d\n", ret);
|
||||
test_err("btrfs_set_extent_delalloc returned %d", ret);
|
||||
goto out;
|
||||
}
|
||||
if (BTRFS_I(inode)->outstanding_extents != 3) {
|
||||
ret = -EINVAL;
|
||||
test_msg("Miscount, wanted 3, got %u\n",
|
||||
test_err("miscount, wanted 3, got %u",
|
||||
BTRFS_I(inode)->outstanding_extents);
|
||||
goto out;
|
||||
}
|
||||
@ -1087,12 +1091,12 @@ static int test_extent_accounting(u32 sectorsize, u32 nodesize)
|
||||
EXTENT_DIRTY | EXTENT_DELALLOC |
|
||||
EXTENT_UPTODATE, 0, 0, NULL);
|
||||
if (ret) {
|
||||
test_msg("clear_extent_bit returned %d\n", ret);
|
||||
test_err("clear_extent_bit returned %d", ret);
|
||||
goto out;
|
||||
}
|
||||
if (BTRFS_I(inode)->outstanding_extents) {
|
||||
ret = -EINVAL;
|
||||
test_msg("Miscount, wanted 0, got %u\n",
|
||||
test_err("miscount, wanted 0, got %u",
|
||||
BTRFS_I(inode)->outstanding_extents);
|
||||
goto out;
|
||||
}
|
||||
@ -1115,14 +1119,14 @@ int btrfs_test_inodes(u32 sectorsize, u32 nodesize)
|
||||
set_bit(EXTENT_FLAG_COMPRESSED, &compressed_only);
|
||||
set_bit(EXTENT_FLAG_PREALLOC, &prealloc_only);
|
||||
|
||||
test_msg("Running btrfs_get_extent tests\n");
|
||||
test_msg("running btrfs_get_extent tests");
|
||||
ret = test_btrfs_get_extent(sectorsize, nodesize);
|
||||
if (ret)
|
||||
return ret;
|
||||
test_msg("Running hole first btrfs_get_extent test\n");
|
||||
test_msg("running hole first btrfs_get_extent test");
|
||||
ret = test_hole_first(sectorsize, nodesize);
|
||||
if (ret)
|
||||
return ret;
|
||||
test_msg("Running outstanding_extents tests\n");
|
||||
test_msg("running outstanding_extents tests");
|
||||
return test_extent_accounting(sectorsize, nodesize);
|
||||
}
|
||||
|
@ -24,7 +24,7 @@ static int insert_normal_tree_ref(struct btrfs_root *root, u64 bytenr,
|
||||
u32 size = sizeof(*item) + sizeof(*iref) + sizeof(*block_info);
|
||||
int ret;
|
||||
|
||||
btrfs_init_dummy_trans(&trans);
|
||||
btrfs_init_dummy_trans(&trans, NULL);
|
||||
|
||||
ins.objectid = bytenr;
|
||||
ins.type = BTRFS_EXTENT_ITEM_KEY;
|
||||
@ -32,14 +32,14 @@ static int insert_normal_tree_ref(struct btrfs_root *root, u64 bytenr,
|
||||
|
||||
path = btrfs_alloc_path();
|
||||
if (!path) {
|
||||
test_msg("Couldn't allocate path\n");
|
||||
test_err("couldn't allocate path");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
path->leave_spinning = 1;
|
||||
ret = btrfs_insert_empty_item(&trans, root, path, &ins, size);
|
||||
if (ret) {
|
||||
test_msg("Couldn't insert ref %d\n", ret);
|
||||
test_err("couldn't insert ref %d", ret);
|
||||
btrfs_free_path(path);
|
||||
return ret;
|
||||
}
|
||||
@ -74,7 +74,7 @@ static int add_tree_ref(struct btrfs_root *root, u64 bytenr, u64 num_bytes,
|
||||
u64 refs;
|
||||
int ret;
|
||||
|
||||
btrfs_init_dummy_trans(&trans);
|
||||
btrfs_init_dummy_trans(&trans, NULL);
|
||||
|
||||
key.objectid = bytenr;
|
||||
key.type = BTRFS_EXTENT_ITEM_KEY;
|
||||
@ -82,14 +82,14 @@ static int add_tree_ref(struct btrfs_root *root, u64 bytenr, u64 num_bytes,
|
||||
|
||||
path = btrfs_alloc_path();
|
||||
if (!path) {
|
||||
test_msg("Couldn't allocate path\n");
|
||||
test_err("couldn't allocate path");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
path->leave_spinning = 1;
|
||||
ret = btrfs_search_slot(&trans, root, &key, path, 0, 1);
|
||||
if (ret) {
|
||||
test_msg("Couldn't find extent ref\n");
|
||||
test_err("couldn't find extent ref");
|
||||
btrfs_free_path(path);
|
||||
return ret;
|
||||
}
|
||||
@ -111,7 +111,7 @@ static int add_tree_ref(struct btrfs_root *root, u64 bytenr, u64 num_bytes,
|
||||
|
||||
ret = btrfs_insert_empty_item(&trans, root, path, &key, 0);
|
||||
if (ret)
|
||||
test_msg("Failed to insert backref\n");
|
||||
test_err("failed to insert backref");
|
||||
btrfs_free_path(path);
|
||||
return ret;
|
||||
}
|
||||
@ -124,7 +124,7 @@ static int remove_extent_item(struct btrfs_root *root, u64 bytenr,
|
||||
struct btrfs_path *path;
|
||||
int ret;
|
||||
|
||||
btrfs_init_dummy_trans(&trans);
|
||||
btrfs_init_dummy_trans(&trans, NULL);
|
||||
|
||||
key.objectid = bytenr;
|
||||
key.type = BTRFS_EXTENT_ITEM_KEY;
|
||||
@ -132,14 +132,14 @@ static int remove_extent_item(struct btrfs_root *root, u64 bytenr,
|
||||
|
||||
path = btrfs_alloc_path();
|
||||
if (!path) {
|
||||
test_msg("Couldn't allocate path\n");
|
||||
test_err("couldn't allocate path");
|
||||
return -ENOMEM;
|
||||
}
|
||||
path->leave_spinning = 1;
|
||||
|
||||
ret = btrfs_search_slot(&trans, root, &key, path, -1, 1);
|
||||
if (ret) {
|
||||
test_msg("Didn't find our key %d\n", ret);
|
||||
test_err("didn't find our key %d", ret);
|
||||
btrfs_free_path(path);
|
||||
return ret;
|
||||
}
|
||||
@ -158,7 +158,7 @@ static int remove_extent_ref(struct btrfs_root *root, u64 bytenr,
|
||||
u64 refs;
|
||||
int ret;
|
||||
|
||||
btrfs_init_dummy_trans(&trans);
|
||||
btrfs_init_dummy_trans(&trans, NULL);
|
||||
|
||||
key.objectid = bytenr;
|
||||
key.type = BTRFS_EXTENT_ITEM_KEY;
|
||||
@ -166,14 +166,14 @@ static int remove_extent_ref(struct btrfs_root *root, u64 bytenr,
|
||||
|
||||
path = btrfs_alloc_path();
|
||||
if (!path) {
|
||||
test_msg("Couldn't allocate path\n");
|
||||
test_err("couldn't allocate path");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
path->leave_spinning = 1;
|
||||
ret = btrfs_search_slot(&trans, root, &key, path, 0, 1);
|
||||
if (ret) {
|
||||
test_msg("Couldn't find extent ref\n");
|
||||
test_err("couldn't find extent ref");
|
||||
btrfs_free_path(path);
|
||||
return ret;
|
||||
}
|
||||
@ -195,7 +195,7 @@ static int remove_extent_ref(struct btrfs_root *root, u64 bytenr,
|
||||
|
||||
ret = btrfs_search_slot(&trans, root, &key, path, -1, 1);
|
||||
if (ret) {
|
||||
test_msg("Couldn't find backref %d\n", ret);
|
||||
test_err("couldn't find backref %d", ret);
|
||||
btrfs_free_path(path);
|
||||
return ret;
|
||||
}
|
||||
@ -213,12 +213,12 @@ static int test_no_shared_qgroup(struct btrfs_root *root,
|
||||
struct ulist *new_roots = NULL;
|
||||
int ret;
|
||||
|
||||
btrfs_init_dummy_trans(&trans);
|
||||
btrfs_init_dummy_trans(&trans, fs_info);
|
||||
|
||||
test_msg("Qgroup basic add\n");
|
||||
test_msg("qgroup basic add");
|
||||
ret = btrfs_create_qgroup(NULL, fs_info, BTRFS_FS_TREE_OBJECTID);
|
||||
if (ret) {
|
||||
test_msg("Couldn't create a qgroup %d\n", ret);
|
||||
test_err("couldn't create a qgroup %d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -231,7 +231,7 @@ static int test_no_shared_qgroup(struct btrfs_root *root,
|
||||
false);
|
||||
if (ret) {
|
||||
ulist_free(old_roots);
|
||||
test_msg("Couldn't find old roots: %d\n", ret);
|
||||
test_err("couldn't find old roots: %d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -245,20 +245,20 @@ static int test_no_shared_qgroup(struct btrfs_root *root,
|
||||
if (ret) {
|
||||
ulist_free(old_roots);
|
||||
ulist_free(new_roots);
|
||||
test_msg("Couldn't find old roots: %d\n", ret);
|
||||
test_err("couldn't find old roots: %d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = btrfs_qgroup_account_extent(&trans, fs_info, nodesize,
|
||||
nodesize, old_roots, new_roots);
|
||||
if (ret) {
|
||||
test_msg("Couldn't account space for a qgroup %d\n", ret);
|
||||
test_err("couldn't account space for a qgroup %d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (btrfs_verify_qgroup_counts(fs_info, BTRFS_FS_TREE_OBJECTID,
|
||||
nodesize, nodesize)) {
|
||||
test_msg("Qgroup counts didn't match expected values\n");
|
||||
test_err("qgroup counts didn't match expected values");
|
||||
return -EINVAL;
|
||||
}
|
||||
old_roots = NULL;
|
||||
@ -268,7 +268,7 @@ static int test_no_shared_qgroup(struct btrfs_root *root,
|
||||
false);
|
||||
if (ret) {
|
||||
ulist_free(old_roots);
|
||||
test_msg("Couldn't find old roots: %d\n", ret);
|
||||
test_err("couldn't find old roots: %d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -281,19 +281,19 @@ static int test_no_shared_qgroup(struct btrfs_root *root,
|
||||
if (ret) {
|
||||
ulist_free(old_roots);
|
||||
ulist_free(new_roots);
|
||||
test_msg("Couldn't find old roots: %d\n", ret);
|
||||
test_err("couldn't find old roots: %d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = btrfs_qgroup_account_extent(&trans, fs_info, nodesize,
|
||||
nodesize, old_roots, new_roots);
|
||||
if (ret) {
|
||||
test_msg("Couldn't account space for a qgroup %d\n", ret);
|
||||
test_err("couldn't account space for a qgroup %d", ret);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (btrfs_verify_qgroup_counts(fs_info, BTRFS_FS_TREE_OBJECTID, 0, 0)) {
|
||||
test_msg("Qgroup counts didn't match expected values\n");
|
||||
test_err("qgroup counts didn't match expected values");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@ -314,9 +314,9 @@ static int test_multiple_refs(struct btrfs_root *root,
|
||||
struct ulist *new_roots = NULL;
|
||||
int ret;
|
||||
|
||||
btrfs_init_dummy_trans(&trans);
|
||||
btrfs_init_dummy_trans(&trans, fs_info);
|
||||
|
||||
test_msg("Qgroup multiple refs test\n");
|
||||
test_msg("qgroup multiple refs test");
|
||||
|
||||
/*
|
||||
* We have BTRFS_FS_TREE_OBJECTID created already from the
|
||||
@ -324,7 +324,7 @@ static int test_multiple_refs(struct btrfs_root *root,
|
||||
*/
|
||||
ret = btrfs_create_qgroup(NULL, fs_info, BTRFS_FIRST_FREE_OBJECTID);
|
||||
if (ret) {
|
||||
test_msg("Couldn't create a qgroup %d\n", ret);
|
||||
test_err("couldn't create a qgroup %d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -332,7 +332,7 @@ static int test_multiple_refs(struct btrfs_root *root,
|
||||
false);
|
||||
if (ret) {
|
||||
ulist_free(old_roots);
|
||||
test_msg("Couldn't find old roots: %d\n", ret);
|
||||
test_err("couldn't find old roots: %d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -346,20 +346,20 @@ static int test_multiple_refs(struct btrfs_root *root,
|
||||
if (ret) {
|
||||
ulist_free(old_roots);
|
||||
ulist_free(new_roots);
|
||||
test_msg("Couldn't find old roots: %d\n", ret);
|
||||
test_err("couldn't find old roots: %d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = btrfs_qgroup_account_extent(&trans, fs_info, nodesize,
|
||||
nodesize, old_roots, new_roots);
|
||||
if (ret) {
|
||||
test_msg("Couldn't account space for a qgroup %d\n", ret);
|
||||
test_err("couldn't account space for a qgroup %d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (btrfs_verify_qgroup_counts(fs_info, BTRFS_FS_TREE_OBJECTID,
|
||||
nodesize, nodesize)) {
|
||||
test_msg("Qgroup counts didn't match expected values\n");
|
||||
test_err("qgroup counts didn't match expected values");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@ -367,7 +367,7 @@ static int test_multiple_refs(struct btrfs_root *root,
|
||||
false);
|
||||
if (ret) {
|
||||
ulist_free(old_roots);
|
||||
test_msg("Couldn't find old roots: %d\n", ret);
|
||||
test_err("couldn't find old roots: %d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -381,26 +381,26 @@ static int test_multiple_refs(struct btrfs_root *root,
|
||||
if (ret) {
|
||||
ulist_free(old_roots);
|
||||
ulist_free(new_roots);
|
||||
test_msg("Couldn't find old roots: %d\n", ret);
|
||||
test_err("couldn't find old roots: %d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = btrfs_qgroup_account_extent(&trans, fs_info, nodesize,
|
||||
nodesize, old_roots, new_roots);
|
||||
if (ret) {
|
||||
test_msg("Couldn't account space for a qgroup %d\n", ret);
|
||||
test_err("couldn't account space for a qgroup %d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (btrfs_verify_qgroup_counts(fs_info, BTRFS_FS_TREE_OBJECTID,
|
||||
nodesize, 0)) {
|
||||
test_msg("Qgroup counts didn't match expected values\n");
|
||||
test_err("qgroup counts didn't match expected values");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (btrfs_verify_qgroup_counts(fs_info, BTRFS_FIRST_FREE_OBJECTID,
|
||||
nodesize, 0)) {
|
||||
test_msg("Qgroup counts didn't match expected values\n");
|
||||
test_err("qgroup counts didn't match expected values");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@ -408,7 +408,7 @@ static int test_multiple_refs(struct btrfs_root *root,
|
||||
false);
|
||||
if (ret) {
|
||||
ulist_free(old_roots);
|
||||
test_msg("Couldn't find old roots: %d\n", ret);
|
||||
test_err("couldn't find old roots: %d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -422,26 +422,26 @@ static int test_multiple_refs(struct btrfs_root *root,
|
||||
if (ret) {
|
||||
ulist_free(old_roots);
|
||||
ulist_free(new_roots);
|
||||
test_msg("Couldn't find old roots: %d\n", ret);
|
||||
test_err("couldn't find old roots: %d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = btrfs_qgroup_account_extent(&trans, fs_info, nodesize,
|
||||
nodesize, old_roots, new_roots);
|
||||
if (ret) {
|
||||
test_msg("Couldn't account space for a qgroup %d\n", ret);
|
||||
test_err("couldn't account space for a qgroup %d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (btrfs_verify_qgroup_counts(fs_info, BTRFS_FIRST_FREE_OBJECTID,
|
||||
0, 0)) {
|
||||
test_msg("Qgroup counts didn't match expected values\n");
|
||||
test_err("qgroup counts didn't match expected values");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (btrfs_verify_qgroup_counts(fs_info, BTRFS_FS_TREE_OBJECTID,
|
||||
nodesize, nodesize)) {
|
||||
test_msg("Qgroup counts didn't match expected values\n");
|
||||
test_err("qgroup counts didn't match expected values");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@ -457,13 +457,13 @@ int btrfs_test_qgroups(u32 sectorsize, u32 nodesize)
|
||||
|
||||
fs_info = btrfs_alloc_dummy_fs_info(nodesize, sectorsize);
|
||||
if (!fs_info) {
|
||||
test_msg("Couldn't allocate dummy fs info\n");
|
||||
test_err("couldn't allocate dummy fs info");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
root = btrfs_alloc_dummy_root(fs_info);
|
||||
if (IS_ERR(root)) {
|
||||
test_msg("Couldn't allocate root\n");
|
||||
test_err("couldn't allocate root");
|
||||
ret = PTR_ERR(root);
|
||||
goto out;
|
||||
}
|
||||
@ -485,7 +485,7 @@ int btrfs_test_qgroups(u32 sectorsize, u32 nodesize)
|
||||
*/
|
||||
root->node = alloc_test_extent_buffer(root->fs_info, nodesize);
|
||||
if (!root->node) {
|
||||
test_msg("Couldn't allocate dummy buffer\n");
|
||||
test_err("couldn't allocate dummy buffer");
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
@ -495,7 +495,7 @@ int btrfs_test_qgroups(u32 sectorsize, u32 nodesize)
|
||||
|
||||
tmp_root = btrfs_alloc_dummy_root(fs_info);
|
||||
if (IS_ERR(tmp_root)) {
|
||||
test_msg("Couldn't allocate a fs root\n");
|
||||
test_err("couldn't allocate a fs root");
|
||||
ret = PTR_ERR(tmp_root);
|
||||
goto out;
|
||||
}
|
||||
@ -504,13 +504,13 @@ int btrfs_test_qgroups(u32 sectorsize, u32 nodesize)
|
||||
root->fs_info->fs_root = tmp_root;
|
||||
ret = btrfs_insert_fs_root(root->fs_info, tmp_root);
|
||||
if (ret) {
|
||||
test_msg("Couldn't insert fs root %d\n", ret);
|
||||
test_err("couldn't insert fs root %d", ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
tmp_root = btrfs_alloc_dummy_root(fs_info);
|
||||
if (IS_ERR(tmp_root)) {
|
||||
test_msg("Couldn't allocate a fs root\n");
|
||||
test_err("couldn't allocate a fs root");
|
||||
ret = PTR_ERR(tmp_root);
|
||||
goto out;
|
||||
}
|
||||
@ -518,11 +518,11 @@ int btrfs_test_qgroups(u32 sectorsize, u32 nodesize)
|
||||
tmp_root->root_key.objectid = BTRFS_FIRST_FREE_OBJECTID;
|
||||
ret = btrfs_insert_fs_root(root->fs_info, tmp_root);
|
||||
if (ret) {
|
||||
test_msg("Couldn't insert fs root %d\n", ret);
|
||||
test_err("couldn't insert fs root %d", ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
test_msg("Running qgroup tests\n");
|
||||
test_msg("running qgroup tests");
|
||||
ret = test_no_shared_qgroup(root, sectorsize, nodesize);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
@ -877,12 +877,7 @@ static int __btrfs_end_transaction(struct btrfs_trans_handle *trans,
|
||||
atomic_dec(&cur_trans->num_writers);
|
||||
extwriter_counter_dec(cur_trans, trans->type);
|
||||
|
||||
/*
|
||||
* Make sure counter is updated before we wake up waiters.
|
||||
*/
|
||||
smp_mb();
|
||||
if (waitqueue_active(&cur_trans->writer_wait))
|
||||
wake_up(&cur_trans->writer_wait);
|
||||
cond_wake_up(&cur_trans->writer_wait);
|
||||
btrfs_put_transaction(cur_trans);
|
||||
|
||||
if (current->journal_info == trans)
|
||||
@ -1250,7 +1245,6 @@ static noinline int commit_fs_roots(struct btrfs_trans_handle *trans)
|
||||
|
||||
btrfs_free_log(trans, root);
|
||||
btrfs_update_reloc_root(trans, root);
|
||||
btrfs_orphan_commit_root(trans, root);
|
||||
|
||||
btrfs_save_ino_cache(root, trans);
|
||||
|
||||
@ -1640,15 +1634,14 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans,
|
||||
btrfs_abort_transaction(trans, ret);
|
||||
goto fail;
|
||||
}
|
||||
ret = btrfs_uuid_tree_add(trans, fs_info, new_uuid.b,
|
||||
BTRFS_UUID_KEY_SUBVOL, objectid);
|
||||
ret = btrfs_uuid_tree_add(trans, new_uuid.b, BTRFS_UUID_KEY_SUBVOL,
|
||||
objectid);
|
||||
if (ret) {
|
||||
btrfs_abort_transaction(trans, ret);
|
||||
goto fail;
|
||||
}
|
||||
if (!btrfs_is_empty_uuid(new_root_item->received_uuid)) {
|
||||
ret = btrfs_uuid_tree_add(trans, fs_info,
|
||||
new_root_item->received_uuid,
|
||||
ret = btrfs_uuid_tree_add(trans, new_root_item->received_uuid,
|
||||
BTRFS_UUID_KEY_RECEIVED_SUBVOL,
|
||||
objectid);
|
||||
if (ret && ret != -EEXIST) {
|
||||
|
@ -139,7 +139,6 @@ struct btrfs_pending_snapshot {
|
||||
struct btrfs_path *path;
|
||||
/* block reservation for the operation */
|
||||
struct btrfs_block_rsv block_rsv;
|
||||
u64 qgroup_reserved;
|
||||
/* extra metadata reservation for relocation */
|
||||
int error;
|
||||
bool readonly;
|
||||
|
@ -222,11 +222,8 @@ int btrfs_pin_log_trans(struct btrfs_root *root)
|
||||
void btrfs_end_log_trans(struct btrfs_root *root)
|
||||
{
|
||||
if (atomic_dec_and_test(&root->log_writers)) {
|
||||
/*
|
||||
* Implicit memory barrier after atomic_dec_and_test
|
||||
*/
|
||||
if (waitqueue_active(&root->log_writer_wait))
|
||||
wake_up(&root->log_writer_wait);
|
||||
/* atomic_dec_and_test implies a barrier */
|
||||
cond_wake_up_nomb(&root->log_writer_wait);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2988,11 +2985,8 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans,
|
||||
|
||||
mutex_lock(&log_root_tree->log_mutex);
|
||||
if (atomic_dec_and_test(&log_root_tree->log_writers)) {
|
||||
/*
|
||||
* Implicit memory barrier after atomic_dec_and_test
|
||||
*/
|
||||
if (waitqueue_active(&log_root_tree->log_writer_wait))
|
||||
wake_up(&log_root_tree->log_writer_wait);
|
||||
/* atomic_dec_and_test implies a barrier */
|
||||
cond_wake_up_nomb(&log_root_tree->log_writer_wait);
|
||||
}
|
||||
|
||||
if (ret) {
|
||||
@ -3116,10 +3110,11 @@ out_wake_log_root:
|
||||
mutex_unlock(&log_root_tree->log_mutex);
|
||||
|
||||
/*
|
||||
* The barrier before waitqueue_active is implied by mutex_unlock
|
||||
* The barrier before waitqueue_active (in cond_wake_up) is needed so
|
||||
* all the updates above are seen by the woken threads. It might not be
|
||||
* necessary, but proving that seems to be hard.
|
||||
*/
|
||||
if (waitqueue_active(&log_root_tree->log_commit_wait[index2]))
|
||||
wake_up(&log_root_tree->log_commit_wait[index2]);
|
||||
cond_wake_up(&log_root_tree->log_commit_wait[index2]);
|
||||
out:
|
||||
mutex_lock(&root->log_mutex);
|
||||
btrfs_remove_all_log_ctxs(root, index1, ret);
|
||||
@ -3128,10 +3123,11 @@ out:
|
||||
mutex_unlock(&root->log_mutex);
|
||||
|
||||
/*
|
||||
* The barrier before waitqueue_active is implied by mutex_unlock
|
||||
* The barrier before waitqueue_active (in cond_wake_up) is needed so
|
||||
* all the updates above are seen by the woken threads. It might not be
|
||||
* necessary, but proving that seems to be hard.
|
||||
*/
|
||||
if (waitqueue_active(&root->log_commit_wait[index1]))
|
||||
wake_up(&root->log_commit_wait[index1]);
|
||||
cond_wake_up(&root->log_commit_wait[index1]);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -79,10 +79,10 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int btrfs_uuid_tree_add(struct btrfs_trans_handle *trans,
|
||||
struct btrfs_fs_info *fs_info, u8 *uuid, u8 type,
|
||||
int btrfs_uuid_tree_add(struct btrfs_trans_handle *trans, u8 *uuid, u8 type,
|
||||
u64 subid_cpu)
|
||||
{
|
||||
struct btrfs_fs_info *fs_info = trans->fs_info;
|
||||
struct btrfs_root *uuid_root = fs_info->uuid_root;
|
||||
int ret;
|
||||
struct btrfs_path *path = NULL;
|
||||
@ -144,10 +144,10 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int btrfs_uuid_tree_rem(struct btrfs_trans_handle *trans,
|
||||
struct btrfs_fs_info *fs_info, u8 *uuid, u8 type,
|
||||
int btrfs_uuid_tree_remove(struct btrfs_trans_handle *trans, u8 *uuid, u8 type,
|
||||
u64 subid)
|
||||
{
|
||||
struct btrfs_fs_info *fs_info = trans->fs_info;
|
||||
struct btrfs_root *uuid_root = fs_info->uuid_root;
|
||||
int ret;
|
||||
struct btrfs_path *path = NULL;
|
||||
@ -239,7 +239,7 @@ static int btrfs_uuid_iter_rem(struct btrfs_root *uuid_root, u8 *uuid, u8 type,
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = btrfs_uuid_tree_rem(trans, uuid_root->fs_info, uuid, type, subid);
|
||||
ret = btrfs_uuid_tree_remove(trans, uuid, type, subid);
|
||||
btrfs_end_transaction(trans);
|
||||
|
||||
out:
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -208,6 +208,7 @@ BTRFS_DEVICE_GETSET_FUNCS(bytes_used);
|
||||
|
||||
struct btrfs_fs_devices {
|
||||
u8 fsid[BTRFS_FSID_SIZE]; /* FS specific uuid */
|
||||
struct list_head fs_list;
|
||||
|
||||
u64 num_devices;
|
||||
u64 open_devices;
|
||||
@ -229,7 +230,6 @@ struct btrfs_fs_devices {
|
||||
struct list_head resized_devices;
|
||||
/* devices not currently being allocated */
|
||||
struct list_head alloc_list;
|
||||
struct list_head list;
|
||||
|
||||
struct btrfs_fs_devices *seed;
|
||||
int seeding;
|
||||
@ -329,11 +329,12 @@ struct btrfs_raid_attr {
|
||||
int tolerated_failures; /* max tolerated fail devs */
|
||||
int devs_increment; /* ndevs has to be a multiple of this */
|
||||
int ncopies; /* how many copies to data has */
|
||||
int mindev_error; /* error code if min devs requisite is unmet */
|
||||
const char raid_name[8]; /* name of the raid */
|
||||
u64 bg_flag; /* block group flag of the raid */
|
||||
};
|
||||
|
||||
extern const struct btrfs_raid_attr btrfs_raid_array[BTRFS_NR_RAID_TYPES];
|
||||
extern const int btrfs_raid_mindev_error[BTRFS_NR_RAID_TYPES];
|
||||
extern const u64 btrfs_raid_group[BTRFS_NR_RAID_TYPES];
|
||||
|
||||
struct map_lookup {
|
||||
u64 type;
|
||||
@ -351,8 +352,6 @@ struct map_lookup {
|
||||
struct btrfs_balance_args;
|
||||
struct btrfs_balance_progress;
|
||||
struct btrfs_balance_control {
|
||||
struct btrfs_fs_info *fs_info;
|
||||
|
||||
struct btrfs_balance_args data;
|
||||
struct btrfs_balance_args meta;
|
||||
struct btrfs_balance_args sys;
|
||||
@ -393,9 +392,8 @@ int btrfs_map_block(struct btrfs_fs_info *fs_info, enum btrfs_map_op op,
|
||||
int btrfs_map_sblock(struct btrfs_fs_info *fs_info, enum btrfs_map_op op,
|
||||
u64 logical, u64 *length,
|
||||
struct btrfs_bio **bbio_ret);
|
||||
int btrfs_rmap_block(struct btrfs_fs_info *fs_info,
|
||||
u64 chunk_start, u64 physical, u64 devid,
|
||||
u64 **logical, int *naddrs, int *stripe_len);
|
||||
int btrfs_rmap_block(struct btrfs_fs_info *fs_info, u64 chunk_start,
|
||||
u64 physical, u64 **logical, int *naddrs, int *stripe_len);
|
||||
int btrfs_read_sys_array(struct btrfs_fs_info *fs_info);
|
||||
int btrfs_read_chunk_tree(struct btrfs_fs_info *fs_info);
|
||||
int btrfs_alloc_chunk(struct btrfs_trans_handle *trans,
|
||||
@ -421,6 +419,7 @@ int btrfs_find_device_by_devspec(struct btrfs_fs_info *fs_info, u64 devid,
|
||||
struct btrfs_device *btrfs_alloc_device(struct btrfs_fs_info *fs_info,
|
||||
const u64 *devid,
|
||||
const u8 *uuid);
|
||||
void btrfs_free_device(struct btrfs_device *device);
|
||||
int btrfs_rm_device(struct btrfs_fs_info *fs_info,
|
||||
const char *device_path, u64 devid);
|
||||
void __exit btrfs_cleanup_fs_uuids(void);
|
||||
@ -431,11 +430,8 @@ struct btrfs_device *btrfs_find_device(struct btrfs_fs_info *fs_info, u64 devid,
|
||||
u8 *uuid, u8 *fsid);
|
||||
int btrfs_shrink_device(struct btrfs_device *device, u64 new_size);
|
||||
int btrfs_init_new_device(struct btrfs_fs_info *fs_info, const char *path);
|
||||
int btrfs_init_dev_replace_tgtdev(struct btrfs_fs_info *fs_info,
|
||||
const char *device_path,
|
||||
struct btrfs_device *srcdev,
|
||||
struct btrfs_device **device_out);
|
||||
int btrfs_balance(struct btrfs_balance_control *bctl,
|
||||
int btrfs_balance(struct btrfs_fs_info *fs_info,
|
||||
struct btrfs_balance_control *bctl,
|
||||
struct btrfs_ioctl_balance_args *bargs);
|
||||
int btrfs_resume_balance_async(struct btrfs_fs_info *fs_info);
|
||||
int btrfs_recover_balance(struct btrfs_fs_info *fs_info);
|
||||
@ -553,6 +549,8 @@ static inline enum btrfs_raid_types btrfs_bg_flags_to_raid_index(u64 flags)
|
||||
return BTRFS_RAID_SINGLE; /* BTRFS_BLOCK_GROUP_SINGLE */
|
||||
}
|
||||
|
||||
const char *get_raid_name(enum btrfs_raid_types type);
|
||||
|
||||
void btrfs_update_commit_device_size(struct btrfs_fs_info *fs_info);
|
||||
void btrfs_update_commit_device_bytes_used(struct btrfs_transaction *trans);
|
||||
|
||||
|
@ -121,9 +121,9 @@ TRACE_EVENT(btrfs_transaction_commit,
|
||||
__entry->root_objectid = root->root_key.objectid;
|
||||
),
|
||||
|
||||
TP_printk_btrfs("root = %llu(%s), gen = %llu",
|
||||
TP_printk_btrfs("root=%llu(%s) gen=%llu",
|
||||
show_root_type(__entry->root_objectid),
|
||||
(unsigned long long)__entry->generation)
|
||||
__entry->generation)
|
||||
);
|
||||
|
||||
DECLARE_EVENT_CLASS(btrfs__inode,
|
||||
@ -133,7 +133,7 @@ DECLARE_EVENT_CLASS(btrfs__inode,
|
||||
TP_ARGS(inode),
|
||||
|
||||
TP_STRUCT__entry_btrfs(
|
||||
__field( ino_t, ino )
|
||||
__field( u64, ino )
|
||||
__field( blkcnt_t, blocks )
|
||||
__field( u64, disk_i_size )
|
||||
__field( u64, generation )
|
||||
@ -143,7 +143,7 @@ DECLARE_EVENT_CLASS(btrfs__inode,
|
||||
),
|
||||
|
||||
TP_fast_assign_btrfs(btrfs_sb(inode->i_sb),
|
||||
__entry->ino = inode->i_ino;
|
||||
__entry->ino = btrfs_ino(BTRFS_I(inode));
|
||||
__entry->blocks = inode->i_blocks;
|
||||
__entry->disk_i_size = BTRFS_I(inode)->disk_i_size;
|
||||
__entry->generation = BTRFS_I(inode)->generation;
|
||||
@ -153,15 +153,15 @@ DECLARE_EVENT_CLASS(btrfs__inode,
|
||||
BTRFS_I(inode)->root->root_key.objectid;
|
||||
),
|
||||
|
||||
TP_printk_btrfs("root=%llu(%s) gen=%llu ino=%lu blocks=%llu "
|
||||
TP_printk_btrfs("root=%llu(%s) gen=%llu ino=%llu blocks=%llu "
|
||||
"disk_i_size=%llu last_trans=%llu logged_trans=%llu",
|
||||
show_root_type(__entry->root_objectid),
|
||||
(unsigned long long)__entry->generation,
|
||||
(unsigned long)__entry->ino,
|
||||
__entry->generation,
|
||||
__entry->ino,
|
||||
(unsigned long long)__entry->blocks,
|
||||
(unsigned long long)__entry->disk_i_size,
|
||||
(unsigned long long)__entry->last_trans,
|
||||
(unsigned long long)__entry->logged_trans)
|
||||
__entry->disk_i_size,
|
||||
__entry->last_trans,
|
||||
__entry->logged_trans)
|
||||
);
|
||||
|
||||
DEFINE_EVENT(btrfs__inode, btrfs_inode_new,
|
||||
@ -244,23 +244,25 @@ TRACE_EVENT_CONDITION(btrfs_get_extent,
|
||||
"block_len=%llu flags=%s refs=%u "
|
||||
"compress_type=%u",
|
||||
show_root_type(__entry->root_objectid),
|
||||
(unsigned long long)__entry->ino,
|
||||
(unsigned long long)__entry->start,
|
||||
(unsigned long long)__entry->len,
|
||||
(unsigned long long)__entry->orig_start,
|
||||
__entry->ino,
|
||||
__entry->start,
|
||||
__entry->len,
|
||||
__entry->orig_start,
|
||||
show_map_type(__entry->block_start),
|
||||
(unsigned long long)__entry->block_len,
|
||||
__entry->block_len,
|
||||
show_map_flags(__entry->flags),
|
||||
__entry->refs, __entry->compress_type)
|
||||
);
|
||||
|
||||
TRACE_EVENT(btrfs_handle_em_exist,
|
||||
|
||||
TP_PROTO(const struct extent_map *existing, const struct extent_map *map, u64 start, u64 len),
|
||||
TP_PROTO(struct btrfs_fs_info *fs_info,
|
||||
const struct extent_map *existing, const struct extent_map *map,
|
||||
u64 start, u64 len),
|
||||
|
||||
TP_ARGS(existing, map, start, len),
|
||||
TP_ARGS(fs_info, existing, map, start, len),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
TP_STRUCT__entry_btrfs(
|
||||
__field( u64, e_start )
|
||||
__field( u64, e_len )
|
||||
__field( u64, map_start )
|
||||
@ -269,7 +271,7 @@ TRACE_EVENT(btrfs_handle_em_exist,
|
||||
__field( u64, len )
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
TP_fast_assign_btrfs(fs_info,
|
||||
__entry->e_start = existing->start;
|
||||
__entry->e_len = existing->len;
|
||||
__entry->map_start = map->start;
|
||||
@ -278,15 +280,15 @@ TRACE_EVENT(btrfs_handle_em_exist,
|
||||
__entry->len = len;
|
||||
),
|
||||
|
||||
TP_printk("start=%llu len=%llu "
|
||||
TP_printk_btrfs("start=%llu len=%llu "
|
||||
"existing(start=%llu len=%llu) "
|
||||
"em(start=%llu len=%llu)",
|
||||
(unsigned long long)__entry->start,
|
||||
(unsigned long long)__entry->len,
|
||||
(unsigned long long)__entry->e_start,
|
||||
(unsigned long long)__entry->e_len,
|
||||
(unsigned long long)__entry->map_start,
|
||||
(unsigned long long)__entry->map_len)
|
||||
__entry->start,
|
||||
__entry->len,
|
||||
__entry->e_start,
|
||||
__entry->e_len,
|
||||
__entry->map_start,
|
||||
__entry->map_len)
|
||||
);
|
||||
|
||||
/* file extent item */
|
||||
@ -443,7 +445,7 @@ DECLARE_EVENT_CLASS(btrfs__ordered_extent,
|
||||
TP_ARGS(inode, ordered),
|
||||
|
||||
TP_STRUCT__entry_btrfs(
|
||||
__field( ino_t, ino )
|
||||
__field( u64, ino )
|
||||
__field( u64, file_offset )
|
||||
__field( u64, start )
|
||||
__field( u64, len )
|
||||
@ -457,7 +459,7 @@ DECLARE_EVENT_CLASS(btrfs__ordered_extent,
|
||||
),
|
||||
|
||||
TP_fast_assign_btrfs(btrfs_sb(inode->i_sb),
|
||||
__entry->ino = inode->i_ino;
|
||||
__entry->ino = btrfs_ino(BTRFS_I(inode));
|
||||
__entry->file_offset = ordered->file_offset;
|
||||
__entry->start = ordered->start;
|
||||
__entry->len = ordered->len;
|
||||
@ -477,13 +479,13 @@ DECLARE_EVENT_CLASS(btrfs__ordered_extent,
|
||||
"bytes_left=%llu flags=%s compress_type=%d "
|
||||
"refs=%d",
|
||||
show_root_type(__entry->root_objectid),
|
||||
(unsigned long long)__entry->ino,
|
||||
(unsigned long long)__entry->file_offset,
|
||||
(unsigned long long)__entry->start,
|
||||
(unsigned long long)__entry->len,
|
||||
(unsigned long long)__entry->disk_len,
|
||||
(unsigned long long)__entry->truncated_len,
|
||||
(unsigned long long)__entry->bytes_left,
|
||||
__entry->ino,
|
||||
__entry->file_offset,
|
||||
__entry->start,
|
||||
__entry->len,
|
||||
__entry->disk_len,
|
||||
__entry->truncated_len,
|
||||
__entry->bytes_left,
|
||||
show_ordered_flags(__entry->flags),
|
||||
__entry->compress_type, __entry->refs)
|
||||
);
|
||||
@ -528,7 +530,7 @@ DECLARE_EVENT_CLASS(btrfs__writepage,
|
||||
TP_ARGS(page, inode, wbc),
|
||||
|
||||
TP_STRUCT__entry_btrfs(
|
||||
__field( ino_t, ino )
|
||||
__field( u64, ino )
|
||||
__field( pgoff_t, index )
|
||||
__field( long, nr_to_write )
|
||||
__field( long, pages_skipped )
|
||||
@ -542,7 +544,7 @@ DECLARE_EVENT_CLASS(btrfs__writepage,
|
||||
),
|
||||
|
||||
TP_fast_assign_btrfs(btrfs_sb(inode->i_sb),
|
||||
__entry->ino = inode->i_ino;
|
||||
__entry->ino = btrfs_ino(BTRFS_I(inode));
|
||||
__entry->index = page->index;
|
||||
__entry->nr_to_write = wbc->nr_to_write;
|
||||
__entry->pages_skipped = wbc->pages_skipped;
|
||||
@ -556,12 +558,12 @@ DECLARE_EVENT_CLASS(btrfs__writepage,
|
||||
BTRFS_I(inode)->root->root_key.objectid;
|
||||
),
|
||||
|
||||
TP_printk_btrfs("root=%llu(%s) ino=%lu page_index=%lu "
|
||||
TP_printk_btrfs("root=%llu(%s) ino=%llu page_index=%lu "
|
||||
"nr_to_write=%ld pages_skipped=%ld range_start=%llu "
|
||||
"range_end=%llu for_kupdate=%d "
|
||||
"for_reclaim=%d range_cyclic=%d writeback_index=%lu",
|
||||
show_root_type(__entry->root_objectid),
|
||||
(unsigned long)__entry->ino, __entry->index,
|
||||
__entry->ino, __entry->index,
|
||||
__entry->nr_to_write, __entry->pages_skipped,
|
||||
__entry->range_start, __entry->range_end,
|
||||
__entry->for_kupdate,
|
||||
@ -584,7 +586,7 @@ TRACE_EVENT(btrfs_writepage_end_io_hook,
|
||||
TP_ARGS(page, start, end, uptodate),
|
||||
|
||||
TP_STRUCT__entry_btrfs(
|
||||
__field( ino_t, ino )
|
||||
__field( u64, ino )
|
||||
__field( pgoff_t, index )
|
||||
__field( u64, start )
|
||||
__field( u64, end )
|
||||
@ -593,7 +595,7 @@ TRACE_EVENT(btrfs_writepage_end_io_hook,
|
||||
),
|
||||
|
||||
TP_fast_assign_btrfs(btrfs_sb(page->mapping->host->i_sb),
|
||||
__entry->ino = page->mapping->host->i_ino;
|
||||
__entry->ino = btrfs_ino(BTRFS_I(page->mapping->host));
|
||||
__entry->index = page->index;
|
||||
__entry->start = start;
|
||||
__entry->end = end;
|
||||
@ -602,12 +604,12 @@ TRACE_EVENT(btrfs_writepage_end_io_hook,
|
||||
BTRFS_I(page->mapping->host)->root->root_key.objectid;
|
||||
),
|
||||
|
||||
TP_printk_btrfs("root=%llu(%s) ino=%lu page_index=%lu start=%llu "
|
||||
TP_printk_btrfs("root=%llu(%s) ino=%llu page_index=%lu start=%llu "
|
||||
"end=%llu uptodate=%d",
|
||||
show_root_type(__entry->root_objectid),
|
||||
(unsigned long)__entry->ino, (unsigned long)__entry->index,
|
||||
(unsigned long long)__entry->start,
|
||||
(unsigned long long)__entry->end, __entry->uptodate)
|
||||
__entry->ino, (unsigned long)__entry->index,
|
||||
__entry->start,
|
||||
__entry->end, __entry->uptodate)
|
||||
);
|
||||
|
||||
TRACE_EVENT(btrfs_sync_file,
|
||||
@ -617,8 +619,8 @@ TRACE_EVENT(btrfs_sync_file,
|
||||
TP_ARGS(file, datasync),
|
||||
|
||||
TP_STRUCT__entry_btrfs(
|
||||
__field( ino_t, ino )
|
||||
__field( ino_t, parent )
|
||||
__field( u64, ino )
|
||||
__field( u64, parent )
|
||||
__field( int, datasync )
|
||||
__field( u64, root_objectid )
|
||||
),
|
||||
@ -628,16 +630,17 @@ TRACE_EVENT(btrfs_sync_file,
|
||||
const struct inode *inode = d_inode(dentry);
|
||||
|
||||
TP_fast_assign_fsid(btrfs_sb(file->f_path.dentry->d_sb));
|
||||
__entry->ino = inode->i_ino;
|
||||
__entry->parent = d_inode(dentry->d_parent)->i_ino;
|
||||
__entry->ino = btrfs_ino(BTRFS_I(inode));
|
||||
__entry->parent = btrfs_ino(BTRFS_I(d_inode(dentry->d_parent)));
|
||||
__entry->datasync = datasync;
|
||||
__entry->root_objectid =
|
||||
BTRFS_I(inode)->root->root_key.objectid;
|
||||
),
|
||||
|
||||
TP_printk_btrfs("root=%llu(%s) ino=%ld parent=%ld datasync=%d",
|
||||
TP_printk_btrfs("root=%llu(%s) ino=%llu parent=%llu datasync=%d",
|
||||
show_root_type(__entry->root_objectid),
|
||||
(unsigned long)__entry->ino, (unsigned long)__entry->parent,
|
||||
__entry->ino,
|
||||
__entry->parent,
|
||||
__entry->datasync)
|
||||
);
|
||||
|
||||
@ -655,7 +658,7 @@ TRACE_EVENT(btrfs_sync_fs,
|
||||
__entry->wait = wait;
|
||||
),
|
||||
|
||||
TP_printk_btrfs("wait = %d", __entry->wait)
|
||||
TP_printk_btrfs("wait=%d", __entry->wait)
|
||||
);
|
||||
|
||||
TRACE_EVENT(btrfs_add_block_group,
|
||||
@ -665,8 +668,7 @@ TRACE_EVENT(btrfs_add_block_group,
|
||||
|
||||
TP_ARGS(fs_info, block_group, create),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__array( u8, fsid, BTRFS_FSID_SIZE )
|
||||
TP_STRUCT__entry_btrfs(
|
||||
__field( u64, offset )
|
||||
__field( u64, size )
|
||||
__field( u64, flags )
|
||||
@ -675,8 +677,7 @@ TRACE_EVENT(btrfs_add_block_group,
|
||||
__field( int, create )
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
memcpy(__entry->fsid, fs_info->fsid, BTRFS_FSID_SIZE);
|
||||
TP_fast_assign_btrfs(fs_info,
|
||||
__entry->offset = block_group->key.objectid;
|
||||
__entry->size = block_group->key.offset;
|
||||
__entry->flags = block_group->flags;
|
||||
@ -686,16 +687,16 @@ TRACE_EVENT(btrfs_add_block_group,
|
||||
__entry->create = create;
|
||||
),
|
||||
|
||||
TP_printk("%pU: block_group offset=%llu size=%llu "
|
||||
TP_printk_btrfs("block_group offset=%llu size=%llu "
|
||||
"flags=%llu(%s) bytes_used=%llu bytes_super=%llu "
|
||||
"create=%d", __entry->fsid,
|
||||
(unsigned long long)__entry->offset,
|
||||
(unsigned long long)__entry->size,
|
||||
(unsigned long long)__entry->flags,
|
||||
"create=%d",
|
||||
__entry->offset,
|
||||
__entry->size,
|
||||
__entry->flags,
|
||||
__print_flags((unsigned long)__entry->flags, "|",
|
||||
BTRFS_GROUP_FLAGS),
|
||||
(unsigned long long)__entry->bytes_used,
|
||||
(unsigned long long)__entry->bytes_super, __entry->create)
|
||||
__entry->bytes_used,
|
||||
__entry->bytes_super, __entry->create)
|
||||
);
|
||||
|
||||
#define show_ref_action(action) \
|
||||
@ -740,13 +741,13 @@ DECLARE_EVENT_CLASS(btrfs_delayed_tree_ref,
|
||||
TP_printk_btrfs("bytenr=%llu num_bytes=%llu action=%s "
|
||||
"parent=%llu(%s) ref_root=%llu(%s) level=%d "
|
||||
"type=%s seq=%llu",
|
||||
(unsigned long long)__entry->bytenr,
|
||||
(unsigned long long)__entry->num_bytes,
|
||||
__entry->bytenr,
|
||||
__entry->num_bytes,
|
||||
show_ref_action(__entry->action),
|
||||
show_root_type(__entry->parent),
|
||||
show_root_type(__entry->ref_root),
|
||||
__entry->level, show_ref_type(__entry->type),
|
||||
(unsigned long long)__entry->seq)
|
||||
__entry->seq)
|
||||
);
|
||||
|
||||
DEFINE_EVENT(btrfs_delayed_tree_ref, add_delayed_tree_ref,
|
||||
@ -805,15 +806,15 @@ DECLARE_EVENT_CLASS(btrfs_delayed_data_ref,
|
||||
TP_printk_btrfs("bytenr=%llu num_bytes=%llu action=%s "
|
||||
"parent=%llu(%s) ref_root=%llu(%s) owner=%llu "
|
||||
"offset=%llu type=%s seq=%llu",
|
||||
(unsigned long long)__entry->bytenr,
|
||||
(unsigned long long)__entry->num_bytes,
|
||||
__entry->bytenr,
|
||||
__entry->num_bytes,
|
||||
show_ref_action(__entry->action),
|
||||
show_root_type(__entry->parent),
|
||||
show_root_type(__entry->ref_root),
|
||||
(unsigned long long)__entry->owner,
|
||||
(unsigned long long)__entry->offset,
|
||||
__entry->owner,
|
||||
__entry->offset,
|
||||
show_ref_type(__entry->type),
|
||||
(unsigned long long)__entry->seq)
|
||||
__entry->seq)
|
||||
);
|
||||
|
||||
DEFINE_EVENT(btrfs_delayed_data_ref, add_delayed_data_ref,
|
||||
@ -859,8 +860,8 @@ DECLARE_EVENT_CLASS(btrfs_delayed_ref_head,
|
||||
),
|
||||
|
||||
TP_printk_btrfs("bytenr=%llu num_bytes=%llu action=%s is_data=%d",
|
||||
(unsigned long long)__entry->bytenr,
|
||||
(unsigned long long)__entry->num_bytes,
|
||||
__entry->bytenr,
|
||||
__entry->num_bytes,
|
||||
show_ref_action(__entry->action),
|
||||
__entry->is_data)
|
||||
);
|
||||
@ -923,8 +924,8 @@ DECLARE_EVENT_CLASS(btrfs__chunk,
|
||||
TP_printk_btrfs("root=%llu(%s) offset=%llu size=%llu "
|
||||
"num_stripes=%d sub_stripes=%d type=%s",
|
||||
show_root_type(__entry->root_objectid),
|
||||
(unsigned long long)__entry->offset,
|
||||
(unsigned long long)__entry->size,
|
||||
__entry->offset,
|
||||
__entry->size,
|
||||
__entry->num_stripes, __entry->sub_stripes,
|
||||
show_chunk_type(__entry->type))
|
||||
);
|
||||
@ -974,9 +975,9 @@ TRACE_EVENT(btrfs_cow_block,
|
||||
"(orig_level=%d) cow_buf=%llu (cow_level=%d)",
|
||||
show_root_type(__entry->root_objectid),
|
||||
__entry->refs,
|
||||
(unsigned long long)__entry->buf_start,
|
||||
__entry->buf_start,
|
||||
__entry->buf_level,
|
||||
(unsigned long long)__entry->cow_start,
|
||||
__entry->cow_start,
|
||||
__entry->cow_level)
|
||||
);
|
||||
|
||||
@ -1001,7 +1002,7 @@ TRACE_EVENT(btrfs_space_reservation,
|
||||
__entry->reserve = reserve;
|
||||
),
|
||||
|
||||
TP_printk_btrfs("%s: %Lu %s %Lu", __get_str(type), __entry->val,
|
||||
TP_printk_btrfs("%s: %llu %s %llu", __get_str(type), __entry->val,
|
||||
__entry->reserve ? "reserve" : "release",
|
||||
__entry->bytes)
|
||||
);
|
||||
@ -1019,29 +1020,27 @@ TRACE_EVENT(btrfs_trigger_flush,
|
||||
|
||||
TP_ARGS(fs_info, flags, bytes, flush, reason),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__array( u8, fsid, BTRFS_FSID_SIZE )
|
||||
TP_STRUCT__entry_btrfs(
|
||||
__field( u64, flags )
|
||||
__field( u64, bytes )
|
||||
__field( int, flush )
|
||||
__string( reason, reason )
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
memcpy(__entry->fsid, fs_info->fsid, BTRFS_FSID_SIZE);
|
||||
TP_fast_assign_btrfs(fs_info,
|
||||
__entry->flags = flags;
|
||||
__entry->bytes = bytes;
|
||||
__entry->flush = flush;
|
||||
__assign_str(reason, reason)
|
||||
),
|
||||
|
||||
TP_printk("%pU: %s: flush=%d(%s) flags=%llu(%s) bytes=%llu",
|
||||
__entry->fsid, __get_str(reason), __entry->flush,
|
||||
TP_printk_btrfs("%s: flush=%d(%s) flags=%llu(%s) bytes=%llu",
|
||||
__get_str(reason), __entry->flush,
|
||||
show_flush_action(__entry->flush),
|
||||
(unsigned long long)__entry->flags,
|
||||
__entry->flags,
|
||||
__print_flags((unsigned long)__entry->flags, "|",
|
||||
BTRFS_GROUP_FLAGS),
|
||||
(unsigned long long)__entry->bytes)
|
||||
__entry->bytes)
|
||||
);
|
||||
|
||||
#define show_flush_state(state) \
|
||||
@ -1060,29 +1059,27 @@ TRACE_EVENT(btrfs_flush_space,
|
||||
|
||||
TP_ARGS(fs_info, flags, num_bytes, state, ret),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__array( u8, fsid, BTRFS_FSID_SIZE )
|
||||
TP_STRUCT__entry_btrfs(
|
||||
__field( u64, flags )
|
||||
__field( u64, num_bytes )
|
||||
__field( int, state )
|
||||
__field( int, ret )
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
memcpy(__entry->fsid, fs_info->fsid, BTRFS_FSID_SIZE);
|
||||
TP_fast_assign_btrfs(fs_info,
|
||||
__entry->flags = flags;
|
||||
__entry->num_bytes = num_bytes;
|
||||
__entry->state = state;
|
||||
__entry->ret = ret;
|
||||
),
|
||||
|
||||
TP_printk("%pU: state=%d(%s) flags=%llu(%s) num_bytes=%llu ret=%d",
|
||||
__entry->fsid, __entry->state,
|
||||
TP_printk_btrfs("state=%d(%s) flags=%llu(%s) num_bytes=%llu ret=%d",
|
||||
__entry->state,
|
||||
show_flush_state(__entry->state),
|
||||
(unsigned long long)__entry->flags,
|
||||
__entry->flags,
|
||||
__print_flags((unsigned long)__entry->flags, "|",
|
||||
BTRFS_GROUP_FLAGS),
|
||||
(unsigned long long)__entry->num_bytes, __entry->ret)
|
||||
__entry->num_bytes, __entry->ret)
|
||||
);
|
||||
|
||||
DECLARE_EVENT_CLASS(btrfs__reserved_extent,
|
||||
@ -1103,8 +1100,8 @@ DECLARE_EVENT_CLASS(btrfs__reserved_extent,
|
||||
|
||||
TP_printk_btrfs("root=%llu(%s) start=%llu len=%llu",
|
||||
show_root_type(BTRFS_EXTENT_TREE_OBJECTID),
|
||||
(unsigned long long)__entry->start,
|
||||
(unsigned long long)__entry->len)
|
||||
__entry->start,
|
||||
__entry->len)
|
||||
);
|
||||
|
||||
DEFINE_EVENT(btrfs__reserved_extent, btrfs_reserved_extent_alloc,
|
||||
@ -1140,7 +1137,7 @@ TRACE_EVENT(find_free_extent,
|
||||
__entry->data = data;
|
||||
),
|
||||
|
||||
TP_printk_btrfs("root=%Lu(%s) len=%Lu empty_size=%Lu flags=%Lu(%s)",
|
||||
TP_printk_btrfs("root=%llu(%s) len=%llu empty_size=%llu flags=%llu(%s)",
|
||||
show_root_type(BTRFS_EXTENT_TREE_OBJECTID),
|
||||
__entry->num_bytes, __entry->empty_size, __entry->data,
|
||||
__print_flags((unsigned long)__entry->data, "|",
|
||||
@ -1149,11 +1146,10 @@ TRACE_EVENT(find_free_extent,
|
||||
|
||||
DECLARE_EVENT_CLASS(btrfs__reserve_extent,
|
||||
|
||||
TP_PROTO(const struct btrfs_fs_info *fs_info,
|
||||
const struct btrfs_block_group_cache *block_group, u64 start,
|
||||
TP_PROTO(const struct btrfs_block_group_cache *block_group, u64 start,
|
||||
u64 len),
|
||||
|
||||
TP_ARGS(fs_info, block_group, start, len),
|
||||
TP_ARGS(block_group, start, len),
|
||||
|
||||
TP_STRUCT__entry_btrfs(
|
||||
__field( u64, bg_objectid )
|
||||
@ -1162,15 +1158,15 @@ DECLARE_EVENT_CLASS(btrfs__reserve_extent,
|
||||
__field( u64, len )
|
||||
),
|
||||
|
||||
TP_fast_assign_btrfs(fs_info,
|
||||
TP_fast_assign_btrfs(block_group->fs_info,
|
||||
__entry->bg_objectid = block_group->key.objectid;
|
||||
__entry->flags = block_group->flags;
|
||||
__entry->start = start;
|
||||
__entry->len = len;
|
||||
),
|
||||
|
||||
TP_printk_btrfs("root=%Lu(%s) block_group=%Lu flags=%Lu(%s) "
|
||||
"start=%Lu len=%Lu",
|
||||
TP_printk_btrfs("root=%llu(%s) block_group=%llu flags=%llu(%s) "
|
||||
"start=%llu len=%llu",
|
||||
show_root_type(BTRFS_EXTENT_TREE_OBJECTID),
|
||||
__entry->bg_objectid,
|
||||
__entry->flags, __print_flags((unsigned long)__entry->flags,
|
||||
@ -1180,20 +1176,18 @@ DECLARE_EVENT_CLASS(btrfs__reserve_extent,
|
||||
|
||||
DEFINE_EVENT(btrfs__reserve_extent, btrfs_reserve_extent,
|
||||
|
||||
TP_PROTO(const struct btrfs_fs_info *fs_info,
|
||||
const struct btrfs_block_group_cache *block_group, u64 start,
|
||||
TP_PROTO(const struct btrfs_block_group_cache *block_group, u64 start,
|
||||
u64 len),
|
||||
|
||||
TP_ARGS(fs_info, block_group, start, len)
|
||||
TP_ARGS(block_group, start, len)
|
||||
);
|
||||
|
||||
DEFINE_EVENT(btrfs__reserve_extent, btrfs_reserve_extent_cluster,
|
||||
|
||||
TP_PROTO(const struct btrfs_fs_info *fs_info,
|
||||
const struct btrfs_block_group_cache *block_group, u64 start,
|
||||
TP_PROTO(const struct btrfs_block_group_cache *block_group, u64 start,
|
||||
u64 len),
|
||||
|
||||
TP_ARGS(fs_info, block_group, start, len)
|
||||
TP_ARGS(block_group, start, len)
|
||||
);
|
||||
|
||||
TRACE_EVENT(btrfs_find_cluster,
|
||||
@ -1221,8 +1215,8 @@ TRACE_EVENT(btrfs_find_cluster,
|
||||
__entry->min_bytes = min_bytes;
|
||||
),
|
||||
|
||||
TP_printk_btrfs("block_group=%Lu flags=%Lu(%s) start=%Lu len=%Lu "
|
||||
"empty_size=%Lu min_bytes=%Lu", __entry->bg_objectid,
|
||||
TP_printk_btrfs("block_group=%llu flags=%llu(%s) start=%llu len=%llu "
|
||||
"empty_size=%llu min_bytes=%llu", __entry->bg_objectid,
|
||||
__entry->flags,
|
||||
__print_flags((unsigned long)__entry->flags, "|",
|
||||
BTRFS_GROUP_FLAGS), __entry->start,
|
||||
@ -1243,7 +1237,7 @@ TRACE_EVENT(btrfs_failed_cluster_setup,
|
||||
__entry->bg_objectid = block_group->key.objectid;
|
||||
),
|
||||
|
||||
TP_printk_btrfs("block_group=%Lu", __entry->bg_objectid)
|
||||
TP_printk_btrfs("block_group=%llu", __entry->bg_objectid)
|
||||
);
|
||||
|
||||
TRACE_EVENT(btrfs_setup_cluster,
|
||||
@ -1272,8 +1266,8 @@ TRACE_EVENT(btrfs_setup_cluster,
|
||||
__entry->bitmap = bitmap;
|
||||
),
|
||||
|
||||
TP_printk_btrfs("block_group=%Lu flags=%Lu(%s) window_start=%Lu "
|
||||
"size=%Lu max_size=%Lu bitmap=%d",
|
||||
TP_printk_btrfs("block_group=%llu flags=%llu(%s) window_start=%llu "
|
||||
"size=%llu max_size=%llu bitmap=%d",
|
||||
__entry->bg_objectid,
|
||||
__entry->flags,
|
||||
__print_flags((unsigned long)__entry->flags, "|",
|
||||
@ -1476,7 +1470,7 @@ DECLARE_EVENT_CLASS(btrfs__qgroup_rsv_data,
|
||||
|
||||
TP_STRUCT__entry_btrfs(
|
||||
__field( u64, rootid )
|
||||
__field( unsigned long, ino )
|
||||
__field( u64, ino )
|
||||
__field( u64, start )
|
||||
__field( u64, len )
|
||||
__field( u64, reserved )
|
||||
@ -1485,14 +1479,14 @@ DECLARE_EVENT_CLASS(btrfs__qgroup_rsv_data,
|
||||
|
||||
TP_fast_assign_btrfs(btrfs_sb(inode->i_sb),
|
||||
__entry->rootid = BTRFS_I(inode)->root->objectid;
|
||||
__entry->ino = inode->i_ino;
|
||||
__entry->ino = btrfs_ino(BTRFS_I(inode));
|
||||
__entry->start = start;
|
||||
__entry->len = len;
|
||||
__entry->reserved = reserved;
|
||||
__entry->op = op;
|
||||
),
|
||||
|
||||
TP_printk_btrfs("root=%llu ino=%lu start=%llu len=%llu reserved=%llu op=%s",
|
||||
TP_printk_btrfs("root=%llu ino=%llu start=%llu len=%llu reserved=%llu op=%s",
|
||||
__entry->rootid, __entry->ino, __entry->start, __entry->len,
|
||||
__entry->reserved,
|
||||
__print_flags((unsigned long)__entry->op, "",
|
||||
@ -1584,12 +1578,14 @@ DEFINE_EVENT(btrfs_qgroup_extent, btrfs_qgroup_trace_extent,
|
||||
|
||||
TRACE_EVENT(btrfs_qgroup_account_extent,
|
||||
|
||||
TP_PROTO(const struct btrfs_fs_info *fs_info, u64 bytenr,
|
||||
TP_PROTO(const struct btrfs_fs_info *fs_info, u64 transid, u64 bytenr,
|
||||
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, transid, bytenr, num_bytes, nr_old_roots,
|
||||
nr_new_roots),
|
||||
|
||||
TP_STRUCT__entry_btrfs(
|
||||
__field( u64, transid )
|
||||
__field( u64, bytenr )
|
||||
__field( u64, num_bytes )
|
||||
__field( u64, nr_old_roots )
|
||||
@ -1597,43 +1593,49 @@ TRACE_EVENT(btrfs_qgroup_account_extent,
|
||||
),
|
||||
|
||||
TP_fast_assign_btrfs(fs_info,
|
||||
__entry->transid = transid;
|
||||
__entry->bytenr = bytenr;
|
||||
__entry->num_bytes = num_bytes;
|
||||
__entry->nr_old_roots = nr_old_roots;
|
||||
__entry->nr_new_roots = nr_new_roots;
|
||||
),
|
||||
|
||||
TP_printk_btrfs("bytenr=%llu num_bytes=%llu nr_old_roots=%llu "
|
||||
"nr_new_roots=%llu",
|
||||
__entry->bytenr,
|
||||
__entry->num_bytes,
|
||||
__entry->nr_old_roots,
|
||||
__entry->nr_new_roots)
|
||||
TP_printk_btrfs(
|
||||
"transid=%llu bytenr=%llu num_bytes=%llu nr_old_roots=%llu nr_new_roots=%llu",
|
||||
__entry->transid,
|
||||
__entry->bytenr,
|
||||
__entry->num_bytes,
|
||||
__entry->nr_old_roots,
|
||||
__entry->nr_new_roots)
|
||||
);
|
||||
|
||||
TRACE_EVENT(qgroup_update_counters,
|
||||
|
||||
TP_PROTO(const struct btrfs_fs_info *fs_info, u64 qgid,
|
||||
TP_PROTO(const struct btrfs_fs_info *fs_info,
|
||||
struct btrfs_qgroup *qgroup,
|
||||
u64 cur_old_count, u64 cur_new_count),
|
||||
|
||||
TP_ARGS(fs_info, qgid, cur_old_count, cur_new_count),
|
||||
TP_ARGS(fs_info, qgroup, cur_old_count, cur_new_count),
|
||||
|
||||
TP_STRUCT__entry_btrfs(
|
||||
__field( u64, qgid )
|
||||
__field( u64, old_rfer )
|
||||
__field( u64, old_excl )
|
||||
__field( u64, cur_old_count )
|
||||
__field( u64, cur_new_count )
|
||||
),
|
||||
|
||||
TP_fast_assign_btrfs(fs_info,
|
||||
__entry->qgid = qgid;
|
||||
__entry->qgid = qgroup->qgroupid;
|
||||
__entry->old_rfer = qgroup->rfer;
|
||||
__entry->old_excl = qgroup->excl;
|
||||
__entry->cur_old_count = cur_old_count;
|
||||
__entry->cur_new_count = cur_new_count;
|
||||
),
|
||||
|
||||
TP_printk_btrfs("qgid=%llu cur_old_count=%llu cur_new_count=%llu",
|
||||
__entry->qgid,
|
||||
__entry->cur_old_count,
|
||||
__entry->cur_new_count)
|
||||
TP_printk_btrfs("qgid=%llu old_rfer=%llu old_excl=%llu cur_old_count=%llu cur_new_count=%llu",
|
||||
__entry->qgid, __entry->old_rfer, __entry->old_excl,
|
||||
__entry->cur_old_count, __entry->cur_new_count)
|
||||
);
|
||||
|
||||
TRACE_EVENT(qgroup_update_reserve,
|
||||
@ -1765,14 +1767,14 @@ DECLARE_EVENT_CLASS(btrfs__prelim_ref,
|
||||
),
|
||||
|
||||
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->root_id,
|
||||
__entry->objectid, __entry->type,
|
||||
__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)
|
||||
__entry->parent,
|
||||
__entry->bytenr,
|
||||
__entry->tree_size)
|
||||
);
|
||||
|
||||
DEFINE_EVENT(btrfs__prelim_ref, btrfs_prelim_ref_merge,
|
||||
@ -1808,8 +1810,51 @@ TRACE_EVENT(btrfs_inode_mod_outstanding_extents,
|
||||
|
||||
TP_printk_btrfs("root=%llu(%s) ino=%llu mod=%d",
|
||||
show_root_type(__entry->root_objectid),
|
||||
(unsigned long long)__entry->ino, __entry->mod)
|
||||
__entry->ino, __entry->mod)
|
||||
);
|
||||
|
||||
DECLARE_EVENT_CLASS(btrfs__block_group,
|
||||
TP_PROTO(const struct btrfs_block_group_cache *bg_cache),
|
||||
|
||||
TP_ARGS(bg_cache),
|
||||
|
||||
TP_STRUCT__entry_btrfs(
|
||||
__field( u64, bytenr )
|
||||
__field( u64, len )
|
||||
__field( u64, used )
|
||||
__field( u64, flags )
|
||||
),
|
||||
|
||||
TP_fast_assign_btrfs(bg_cache->fs_info,
|
||||
__entry->bytenr = bg_cache->key.objectid,
|
||||
__entry->len = bg_cache->key.offset,
|
||||
__entry->used = btrfs_block_group_used(&bg_cache->item);
|
||||
__entry->flags = bg_cache->flags;
|
||||
),
|
||||
|
||||
TP_printk_btrfs("bg bytenr=%llu len=%llu used=%llu flags=%llu(%s)",
|
||||
__entry->bytenr, __entry->len, __entry->used, __entry->flags,
|
||||
__print_flags(__entry->flags, "|", BTRFS_GROUP_FLAGS))
|
||||
);
|
||||
|
||||
DEFINE_EVENT(btrfs__block_group, btrfs_remove_block_group,
|
||||
TP_PROTO(const struct btrfs_block_group_cache *bg_cache),
|
||||
|
||||
TP_ARGS(bg_cache)
|
||||
);
|
||||
|
||||
DEFINE_EVENT(btrfs__block_group, btrfs_add_unused_block_group,
|
||||
TP_PROTO(const struct btrfs_block_group_cache *bg_cache),
|
||||
|
||||
TP_ARGS(bg_cache)
|
||||
);
|
||||
|
||||
DEFINE_EVENT(btrfs__block_group, btrfs_skip_unused_block_group,
|
||||
TP_PROTO(const struct btrfs_block_group_cache *bg_cache),
|
||||
|
||||
TP_ARGS(bg_cache)
|
||||
);
|
||||
|
||||
#endif /* _TRACE_BTRFS_H */
|
||||
|
||||
/* This part must be outside protection */
|
||||
|
@ -422,6 +422,21 @@ struct btrfs_ioctl_ino_lookup_args {
|
||||
char name[BTRFS_INO_LOOKUP_PATH_MAX];
|
||||
};
|
||||
|
||||
#define BTRFS_INO_LOOKUP_USER_PATH_MAX (4080 - BTRFS_VOL_NAME_MAX - 1)
|
||||
struct btrfs_ioctl_ino_lookup_user_args {
|
||||
/* in, inode number containing the subvolume of 'subvolid' */
|
||||
__u64 dirid;
|
||||
/* in */
|
||||
__u64 treeid;
|
||||
/* out, name of the subvolume of 'treeid' */
|
||||
char name[BTRFS_VOL_NAME_MAX + 1];
|
||||
/*
|
||||
* out, constructed path from the directory with which the ioctl is
|
||||
* called to dirid
|
||||
*/
|
||||
char path[BTRFS_INO_LOOKUP_USER_PATH_MAX];
|
||||
};
|
||||
|
||||
/* Search criteria for the btrfs SEARCH ioctl family. */
|
||||
struct btrfs_ioctl_search_key {
|
||||
/*
|
||||
@ -725,6 +740,82 @@ struct btrfs_ioctl_send_args {
|
||||
__u64 reserved[4]; /* in */
|
||||
};
|
||||
|
||||
/*
|
||||
* Information about a fs tree root.
|
||||
*
|
||||
* All items are filled by the ioctl
|
||||
*/
|
||||
struct btrfs_ioctl_get_subvol_info_args {
|
||||
/* Id of this subvolume */
|
||||
__u64 treeid;
|
||||
|
||||
/* Name of this subvolume, used to get the real name at mount point */
|
||||
char name[BTRFS_VOL_NAME_MAX + 1];
|
||||
|
||||
/*
|
||||
* Id of the subvolume which contains this subvolume.
|
||||
* Zero for top-level subvolume or a deleted subvolume.
|
||||
*/
|
||||
__u64 parent_id;
|
||||
|
||||
/*
|
||||
* Inode number of the directory which contains this subvolume.
|
||||
* Zero for top-level subvolume or a deleted subvolume
|
||||
*/
|
||||
__u64 dirid;
|
||||
|
||||
/* Latest transaction id of this subvolume */
|
||||
__u64 generation;
|
||||
|
||||
/* Flags of this subvolume */
|
||||
__u64 flags;
|
||||
|
||||
/* UUID of this subvolume */
|
||||
__u8 uuid[BTRFS_UUID_SIZE];
|
||||
|
||||
/*
|
||||
* UUID of the subvolume of which this subvolume is a snapshot.
|
||||
* All zero for a non-snapshot subvolume.
|
||||
*/
|
||||
__u8 parent_uuid[BTRFS_UUID_SIZE];
|
||||
|
||||
/*
|
||||
* UUID of the subvolume from which this subvolume was received.
|
||||
* All zero for non-received subvolume.
|
||||
*/
|
||||
__u8 received_uuid[BTRFS_UUID_SIZE];
|
||||
|
||||
/* Transaction id indicating when change/create/send/receive happened */
|
||||
__u64 ctransid;
|
||||
__u64 otransid;
|
||||
__u64 stransid;
|
||||
__u64 rtransid;
|
||||
/* Time corresponding to c/o/s/rtransid */
|
||||
struct btrfs_ioctl_timespec ctime;
|
||||
struct btrfs_ioctl_timespec otime;
|
||||
struct btrfs_ioctl_timespec stime;
|
||||
struct btrfs_ioctl_timespec rtime;
|
||||
|
||||
/* Must be zero */
|
||||
__u64 reserved[8];
|
||||
};
|
||||
|
||||
#define BTRFS_MAX_ROOTREF_BUFFER_NUM 255
|
||||
struct btrfs_ioctl_get_subvol_rootref_args {
|
||||
/* in/out, minimum id of rootref's treeid to be searched */
|
||||
__u64 min_treeid;
|
||||
|
||||
/* out */
|
||||
struct {
|
||||
__u64 treeid;
|
||||
__u64 dirid;
|
||||
} rootref[BTRFS_MAX_ROOTREF_BUFFER_NUM];
|
||||
|
||||
/* out, number of found items */
|
||||
__u8 num_items;
|
||||
__u8 align[7];
|
||||
};
|
||||
|
||||
/* Error codes as returned by the kernel */
|
||||
enum btrfs_err_code {
|
||||
BTRFS_ERROR_DEV_RAID1_MIN_NOT_MET = 1,
|
||||
@ -843,5 +934,11 @@ enum btrfs_err_code {
|
||||
struct btrfs_ioctl_vol_args_v2)
|
||||
#define BTRFS_IOC_LOGICAL_INO_V2 _IOWR(BTRFS_IOCTL_MAGIC, 59, \
|
||||
struct btrfs_ioctl_logical_ino_args)
|
||||
#define BTRFS_IOC_GET_SUBVOL_INFO _IOR(BTRFS_IOCTL_MAGIC, 60, \
|
||||
struct btrfs_ioctl_get_subvol_info_args)
|
||||
#define BTRFS_IOC_GET_SUBVOL_ROOTREF _IOWR(BTRFS_IOCTL_MAGIC, 61, \
|
||||
struct btrfs_ioctl_get_subvol_rootref_args)
|
||||
#define BTRFS_IOC_INO_LOOKUP_USER _IOWR(BTRFS_IOCTL_MAGIC, 62, \
|
||||
struct btrfs_ioctl_ino_lookup_user_args)
|
||||
|
||||
#endif /* _UAPI_LINUX_BTRFS_H */
|
||||
|
Loading…
Reference in New Issue
Block a user