diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2018-04-04 13:03:38 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2018-04-04 13:03:38 -0700 |
commit | 94514bbe9e5c402c4232af158a295a8fdfd72a2c (patch) | |
tree | c990c722cbac5abe8a3b28e0564effa722b7c80e /fs | |
parent | 547c43d777968228b1060b6f1b152b96215eb7b2 (diff) | |
parent | 57599c7e7722daf5f8c2dba4b0e4628f5c500771 (diff) |
Merge tag 'for-4.17-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux
Pull btrfs updates from David Sterba:
"There are a several user visible changes, the rest is mostly invisible
and continues to clean up the whole code base.
User visible changes:
- new mount option nossd_spread (pair for ssd_spread)
- mount option subvolid will detect junk after the number and fail
the mount
- add message after cancelled device replace
- direct module dependency on libcrc32, removed own crc wrappers
- removed user space transaction ioctls
- use lighter locking when reading /proc/self/mounts, RCU instead of
mutex to avoid unnecessary contention
Enhancements:
- skip writeback of last page when truncating file to same size
- send: do not issue unnecessary truncate operations
- mount option token specifiers: use %u for unsigned values, more
validation
- selftests: more tree block validations
qgroups:
- preparatory work for splitting reservation types for data and
metadata, this should allow for more accurate tracking and fix some
issues with underflows or do further enhancements
- split metadata reservations for started and joined transaction so
they do not get mixed up and are accounted correctly at commit time
- with the above, it's possible to revert patch that potentially
deadlocks when trying to make more space by explicitly committing
when the quota limit is hit
- fix root item corruption when multiple same source snapshots are
created with quota enabled
RAID56:
- make sure target is identical to source when raid56 rebuild fails
after dev-replace
- faster rebuild during scrub, batch by stripes and not
block-by-block
- make more use of cached data when rebuilding from a missing device
Fixes:
- null pointer deref when device replace target is missing
- fix fsync after hole punching when using no-holes feature
- fix lockdep splat when allocating percpu data with wrong GFP flags
Cleanups, refactoring, core changes:
- drop redunant parameters from various functions
- kill and opencode trivial helpers
- __cold/__exit function annotations
- dead code removal
- continued audit and documentation of memory barriers
- error handling: handle removal from uuid tree
- error handling: remove handling of impossible condtitons
- more debugging or error messages
- updated tracepoints
- one VLA use removal (and one still left)"
* tag 'for-4.17-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux: (164 commits)
btrfs: lift errors from add_extent_changeset to the callers
Btrfs: print error messages when failing to read trees
btrfs: user proper type for btrfs_mask_flags flags
btrfs: split dev-replace locking helpers for read and write
btrfs: remove stale comments about fs_mutex
btrfs: use RCU in btrfs_show_devname for device list traversal
btrfs: update barrier in should_cow_block
btrfs: use lockdep_assert_held for mutexes
btrfs: use lockdep_assert_held for spinlocks
btrfs: Validate child tree block's level and first key
btrfs: tests/qgroup: Fix wrong tree backref level
Btrfs: fix copy_items() return value when logging an inode
Btrfs: fix fsync after hole punching when using no-holes feature
btrfs: use helper to set ulist aux from a qgroup
Revert "btrfs: qgroups: Retry after commit on getting EDQUOT"
btrfs: qgroup: Update trace events for metadata reservation
btrfs: qgroup: Use root::qgroup_meta_rsv_* to record qgroup meta reserved space
btrfs: delayed-inode: Use new qgroup meta rsv for delayed inode and item
btrfs: qgroup: Use separate meta reservation type for delalloc
btrfs: qgroup: Introduce function to convert META_PREALLOC into META_PERTRANS
...
Diffstat (limited to 'fs')
65 files changed, 1967 insertions, 1691 deletions
diff --git a/fs/btrfs/Kconfig b/fs/btrfs/Kconfig index 273351ee4c46..167e5dc7eadd 100644 --- a/fs/btrfs/Kconfig +++ b/fs/btrfs/Kconfig @@ -1,7 +1,6 @@ config BTRFS_FS tristate "Btrfs filesystem support" - select CRYPTO - select CRYPTO_CRC32C + select LIBCRC32C select ZLIB_INFLATE select ZLIB_DEFLATE select LZO_COMPRESS diff --git a/fs/btrfs/Makefile b/fs/btrfs/Makefile index 0c4373628eb4..ca693dd554e9 100644 --- a/fs/btrfs/Makefile +++ b/fs/btrfs/Makefile @@ -10,7 +10,7 @@ btrfs-y += super.o ctree.o extent-tree.o print-tree.o root-tree.o dir-item.o \ export.o tree-log.o free-space-cache.o zlib.o lzo.o zstd.o \ compression.o delayed-ref.o relocation.o delayed-inode.o scrub.o \ reada.o backref.o ulist.o qgroup.o send.o dev-replace.o raid56.o \ - uuid-tree.o props.o hash.o free-space-tree.o tree-checker.o + uuid-tree.o props.o free-space-tree.o tree-checker.o btrfs-$(CONFIG_BTRFS_FS_POSIX_ACL) += acl.o btrfs-$(CONFIG_BTRFS_FS_CHECK_INTEGRITY) += check-integrity.o diff --git a/fs/btrfs/acl.c b/fs/btrfs/acl.c index 1ba49ebe67da..0066d95b133f 100644 --- a/fs/btrfs/acl.c +++ b/fs/btrfs/acl.c @@ -46,12 +46,12 @@ struct posix_acl *btrfs_get_acl(struct inode *inode, int type) BUG(); } - size = __btrfs_getxattr(inode, name, "", 0); + size = btrfs_getxattr(inode, name, "", 0); if (size > 0) { value = kzalloc(size, GFP_KERNEL); if (!value) return ERR_PTR(-ENOMEM); - size = __btrfs_getxattr(inode, name, value, size); + size = btrfs_getxattr(inode, name, value, size); } if (size > 0) { acl = posix_acl_from_xattr(&init_user_ns, value, size); @@ -65,9 +65,6 @@ struct posix_acl *btrfs_get_acl(struct inode *inode, int type) return acl; } -/* - * Needs to be called with fs_mutex held - */ static int __btrfs_set_acl(struct btrfs_trans_handle *trans, struct inode *inode, struct posix_acl *acl, int type) { @@ -101,7 +98,7 @@ static int __btrfs_set_acl(struct btrfs_trans_handle *trans, goto out; } - ret = __btrfs_setxattr(trans, inode, name, value, size, 0); + ret = btrfs_setxattr(trans, inode, name, value, size, 0); out: kfree(value); @@ -127,11 +124,6 @@ int btrfs_set_acl(struct inode *inode, struct posix_acl *acl, int type) return ret; } -/* - * btrfs_init_acl is already generally called under fs_mutex, so the locking - * stuff has been fixed to work with that. If the locking stuff changes, we - * need to re-evaluate the acl locking stuff. - */ int btrfs_init_acl(struct btrfs_trans_handle *trans, struct inode *inode, struct inode *dir) { diff --git a/fs/btrfs/backref.c b/fs/btrfs/backref.c index 26484648d090..571024bc632e 100644 --- a/fs/btrfs/backref.c +++ b/fs/btrfs/backref.c @@ -170,7 +170,7 @@ int __init btrfs_prelim_ref_init(void) return 0; } -void btrfs_prelim_ref_exit(void) +void __cold btrfs_prelim_ref_exit(void) { kmem_cache_destroy(btrfs_prelim_ref_cache); } @@ -738,7 +738,8 @@ static int add_missing_keys(struct btrfs_fs_info *fs_info, BUG_ON(ref->key_for_search.type); BUG_ON(!ref->wanted_disk_byte); - eb = read_tree_block(fs_info, ref->wanted_disk_byte, 0); + eb = read_tree_block(fs_info, ref->wanted_disk_byte, 0, + ref->level - 1, NULL); if (IS_ERR(eb)) { free_pref(ref); return PTR_ERR(eb); @@ -773,15 +774,12 @@ static int add_delayed_refs(const struct btrfs_fs_info *fs_info, struct btrfs_delayed_extent_op *extent_op = head->extent_op; struct btrfs_key key; struct btrfs_key tmp_op_key; - struct btrfs_key *op_key = NULL; struct rb_node *n; int count; int ret = 0; - if (extent_op && extent_op->update_key) { + if (extent_op && extent_op->update_key) btrfs_disk_key_to_cpu(&tmp_op_key, &extent_op->key); - op_key = &tmp_op_key; - } spin_lock(&head->lock); for (n = rb_first(&head->ref_tree); n; n = rb_next(n)) { @@ -1291,7 +1289,8 @@ again: ref->level == 0) { struct extent_buffer *eb; - eb = read_tree_block(fs_info, ref->parent, 0); + eb = read_tree_block(fs_info, ref->parent, 0, + ref->level, NULL); if (IS_ERR(eb)) { ret = PTR_ERR(eb); goto out; diff --git a/fs/btrfs/backref.h b/fs/btrfs/backref.h index 0c2fab8514ff..0a30028d5196 100644 --- a/fs/btrfs/backref.h +++ b/fs/btrfs/backref.h @@ -73,7 +73,7 @@ int btrfs_find_one_extref(struct btrfs_root *root, u64 inode_objectid, int btrfs_check_shared(struct btrfs_root *root, u64 inum, u64 bytenr); int __init btrfs_prelim_ref_init(void); -void btrfs_prelim_ref_exit(void); +void __cold btrfs_prelim_ref_exit(void); struct prelim_ref { struct rb_node rbnode; diff --git a/fs/btrfs/btrfs_inode.h b/fs/btrfs/btrfs_inode.h index 63f0ccc92a71..ca15be569d69 100644 --- a/fs/btrfs/btrfs_inode.h +++ b/fs/btrfs/btrfs_inode.h @@ -195,7 +195,6 @@ struct btrfs_inode { /* Hook into fs_info->delayed_iputs */ struct list_head delayed_iput; - long delayed_iput_count; /* * To avoid races between lockless (i_mutex not held) direct IO writes @@ -365,6 +364,4 @@ static inline void btrfs_print_data_csum_error(struct btrfs_inode *inode, logical_start, csum, csum_expected, mirror_num); } -bool btrfs_page_exists_in_range(struct inode *inode, loff_t start, loff_t end); - #endif diff --git a/fs/btrfs/check-integrity.c b/fs/btrfs/check-integrity.c index 7d51b5a5b505..3baebbc021c5 100644 --- a/fs/btrfs/check-integrity.c +++ b/fs/btrfs/check-integrity.c @@ -96,9 +96,9 @@ #include <linux/blkdev.h> #include <linux/mm.h> #include <linux/string.h> +#include <linux/crc32c.h> #include "ctree.h" #include "disk-io.h" -#include "hash.h" #include "transaction.h" #include "extent_io.h" #include "volumes.h" @@ -1736,7 +1736,7 @@ static int btrfsic_test_for_metadata(struct btrfsic_state *state, size_t sublen = i ? PAGE_SIZE : (PAGE_SIZE - BTRFS_CSUM_SIZE); - crc = btrfs_crc32c(crc, data, sublen); + crc = crc32c(crc, data, sublen); } btrfs_csum_final(crc, csum); if (memcmp(csum, h->csum, state->csum_size)) diff --git a/fs/btrfs/compression.c b/fs/btrfs/compression.c index 07d049c0c20f..562c3e633403 100644 --- a/fs/btrfs/compression.c +++ b/fs/btrfs/compression.c @@ -1133,7 +1133,7 @@ int btrfs_decompress(int type, unsigned char *data_in, struct page *dest_page, return ret; } -void btrfs_exit_compress(void) +void __cold btrfs_exit_compress(void) { free_workspaces(); } diff --git a/fs/btrfs/compression.h b/fs/btrfs/compression.h index 677fa4aa0bd7..ce796557a918 100644 --- a/fs/btrfs/compression.h +++ b/fs/btrfs/compression.h @@ -76,7 +76,7 @@ struct compressed_bio { }; void __init btrfs_init_compress(void); -void btrfs_exit_compress(void); +void __cold btrfs_exit_compress(void); int btrfs_compress_pages(unsigned int type_level, struct address_space *mapping, u64 start, struct page **pages, diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c index b88a79e69ddf..a2c9d21176e2 100644 --- a/fs/btrfs/ctree.c +++ b/fs/btrfs/ctree.c @@ -41,8 +41,6 @@ static int balance_node_right(struct btrfs_trans_handle *trans, struct extent_buffer *src_buf); static void del_ptr(struct btrfs_root *root, struct btrfs_path *path, int level, int slot); -static int tree_mod_log_free_eb(struct btrfs_fs_info *fs_info, - struct extent_buffer *eb); struct btrfs_path *btrfs_alloc_path(void) { @@ -301,11 +299,6 @@ enum mod_log_op { MOD_LOG_ROOT_REPLACE, }; -struct tree_mod_move { - int dst_slot; - int nr_items; -}; - struct tree_mod_root { u64 logical; u8 level; @@ -328,32 +321,15 @@ struct tree_mod_elem { u64 blockptr; /* this is used for op == MOD_LOG_MOVE_KEYS */ - struct tree_mod_move move; + struct { + int dst_slot; + int nr_items; + } move; /* this is used for op == MOD_LOG_ROOT_REPLACE */ struct tree_mod_root old_root; }; -static inline void tree_mod_log_read_lock(struct btrfs_fs_info *fs_info) -{ - read_lock(&fs_info->tree_mod_log_lock); -} - -static inline void tree_mod_log_read_unlock(struct btrfs_fs_info *fs_info) -{ - read_unlock(&fs_info->tree_mod_log_lock); -} - -static inline void tree_mod_log_write_lock(struct btrfs_fs_info *fs_info) -{ - write_lock(&fs_info->tree_mod_log_lock); -} - -static inline void tree_mod_log_write_unlock(struct btrfs_fs_info *fs_info) -{ - write_unlock(&fs_info->tree_mod_log_lock); -} - /* * Pull a new tree mod seq number for our operation. */ @@ -373,14 +349,14 @@ static inline u64 btrfs_inc_tree_mod_seq(struct btrfs_fs_info *fs_info) u64 btrfs_get_tree_mod_seq(struct btrfs_fs_info *fs_info, struct seq_list *elem) { - tree_mod_log_write_lock(fs_info); + write_lock(&fs_info->tree_mod_log_lock); spin_lock(&fs_info->tree_mod_seq_lock); if (!elem->seq) { elem->seq = btrfs_inc_tree_mod_seq(fs_info); list_add_tail(&elem->list, &fs_info->tree_mod_seq_list); } spin_unlock(&fs_info->tree_mod_seq_lock); - tree_mod_log_write_unlock(fs_info); + write_unlock(&fs_info->tree_mod_log_lock); return elem->seq; } @@ -422,7 +398,7 @@ void btrfs_put_tree_mod_seq(struct btrfs_fs_info *fs_info, * anything that's lower than the lowest existing (read: blocked) * sequence number can be removed from the tree. */ - tree_mod_log_write_lock(fs_info); + write_lock(&fs_info->tree_mod_log_lock); tm_root = &fs_info->tree_mod_log; for (node = rb_first(tm_root); node; node = next) { next = rb_next(node); @@ -432,7 +408,7 @@ void btrfs_put_tree_mod_seq(struct btrfs_fs_info *fs_info, rb_erase(node, tm_root); kfree(tm); } - tree_mod_log_write_unlock(fs_info); + write_unlock(&fs_info->tree_mod_log_lock); } /* @@ -443,7 +419,7 @@ void btrfs_put_tree_mod_seq(struct btrfs_fs_info *fs_info, * for root replace operations, or the logical address of the affected * block for all other operations. * - * Note: must be called with write lock (tree_mod_log_write_lock). + * Note: must be called with write lock for fs_info::tree_mod_log_lock. */ static noinline int __tree_mod_log_insert(struct btrfs_fs_info *fs_info, struct tree_mod_elem *tm) @@ -481,7 +457,7 @@ __tree_mod_log_insert(struct btrfs_fs_info *fs_info, struct tree_mod_elem *tm) * Determines if logging can be omitted. Returns 1 if it can. Otherwise, it * returns zero with the tree_mod_log_lock acquired. The caller must hold * this until all tree mod log insertions are recorded in the rb tree and then - * call tree_mod_log_write_unlock() to release. + * write unlock fs_info::tree_mod_log_lock. */ static inline int tree_mod_dont_log(struct btrfs_fs_info *fs_info, struct extent_buffer *eb) { @@ -491,9 +467,9 @@ static inline int tree_mod_dont_log(struct btrfs_fs_info *fs_info, if (eb && btrfs_header_level(eb) == 0) return 1; - tree_mod_log_write_lock(fs_info); + write_lock(&fs_info->tree_mod_log_lock); if (list_empty(&(fs_info)->tree_mod_seq_list)) { - tree_mod_log_write_unlock(fs_info); + write_unlock(&fs_info->tree_mod_log_lock); return 1; } @@ -536,38 +512,34 @@ alloc_tree_mod_elem(struct extent_buffer *eb, int slot, return tm; } -static noinline int -tree_mod_log_insert_key(struct btrfs_fs_info *fs_info, - struct extent_buffer *eb, int slot, - enum mod_log_op op, gfp_t flags) +static noinline int tree_mod_log_insert_key(struct extent_buffer *eb, int slot, + enum mod_log_op op, gfp_t flags) { struct tree_mod_elem *tm; int ret; - if (!tree_mod_need_log(fs_info, eb)) + if (!tree_mod_need_log(eb->fs_info, eb)) return 0; tm = alloc_tree_mod_elem(eb, slot, op, flags); if (!tm) return -ENOMEM; - if (tree_mod_dont_log(fs_info, eb)) { + if (tree_mod_dont_log(eb->fs_info, eb)) { kfree(tm); return 0; } - ret = __tree_mod_log_insert(fs_info, tm); - tree_mod_log_write_unlock(fs_info); + ret = __tree_mod_log_insert(eb->fs_info, tm); + write_unlock(&eb->fs_info->tree_mod_log_lock); if (ret) kfree(tm); return ret; } -static noinline int -tree_mod_log_insert_move(struct btrfs_fs_info *fs_info, - struct extent_buffer *eb, int dst_slot, int src_slot, - int nr_items) +static noinline int tree_mod_log_insert_move(struct extent_buffer *eb, + int dst_slot, int src_slot, int nr_items) { struct tree_mod_elem *tm = NULL; struct tree_mod_elem **tm_list = NULL; @@ -575,7 +547,7 @@ tree_mod_log_insert_move(struct btrfs_fs_info *fs_info, int i; int locked = 0; - if (!tree_mod_need_log(fs_info, eb)) + if (!tree_mod_need_log(eb->fs_info, eb)) return 0; tm_list = kcalloc(nr_items, sizeof(struct tree_mod_elem *), GFP_NOFS); @@ -603,7 +575,7 @@ tree_mod_log_insert_move(struct btrfs_fs_info *fs_info, } } - if (tree_mod_dont_log(fs_info, eb)) + if (tree_mod_dont_log(eb->fs_info, eb)) goto free_tms; locked = 1; @@ -613,26 +585,26 @@ tree_mod_log_insert_move(struct btrfs_fs_info *fs_info, * buffer, i.e. dst_slot < src_slot. */ for (i = 0; i + dst_slot < src_slot && i < nr_items; i++) { - ret = __tree_mod_log_insert(fs_info, tm_list[i]); + ret = __tree_mod_log_insert(eb->fs_info, tm_list[i]); if (ret) goto free_tms; } - ret = __tree_mod_log_insert(fs_info, tm); + ret = __tree_mod_log_insert(eb->fs_info, tm); if (ret) goto free_tms; - tree_mod_log_write_unlock(fs_info); + write_unlock(&eb->fs_info->tree_mod_log_lock); kfree(tm_list); return 0; free_tms: for (i = 0; i < nr_items; i++) { if (tm_list[i] && !RB_EMPTY_NODE(&tm_list[i]->node)) - rb_erase(&tm_list[i]->node, &fs_info->tree_mod_log); + rb_erase(&tm_list[i]->node, &eb->fs_info->tree_mod_log); kfree(tm_list[i]); } if (locked) - tree_mod_log_write_unlock(fs_info); + write_unlock(&eb->fs_info->tree_mod_log_lock); kfree(tm_list); kfree(tm); @@ -660,12 +632,10 @@ __tree_mod_log_free_eb(struct btrfs_fs_info *fs_info, return 0; } -static noinline int -tree_mod_log_insert_root(struct btrfs_fs_info *fs_info, - struct extent_buffer *old_root, - struct extent_buffer *new_root, - int log_removal) +static noinline int tree_mod_log_insert_root(struct extent_buffer *old_root, + struct extent_buffer *new_root, int log_removal) { + struct btrfs_fs_info *fs_info = old_root->fs_info; struct tree_mod_elem *tm = NULL; struct tree_mod_elem **tm_list = NULL; int nritems = 0; @@ -713,7 +683,7 @@ tree_mod_log_insert_root(struct btrfs_fs_info *fs_info, if (!ret) ret = __tree_mod_log_insert(fs_info, tm); - tree_mod_log_write_unlock(fs_info); + write_unlock(&fs_info->tree_mod_log_lock); if (ret) goto free_tms; kfree(tm_list); @@ -740,7 +710,7 @@ __tree_mod_log_search(struct btrfs_fs_info *fs_info, u64 start, u64 min_seq, struct tree_mod_elem *cur = NULL; struct tree_mod_elem *found = NULL; - tree_mod_log_read_lock(fs_info); + read_lock(&fs_info->tree_mod_log_lock); tm_root = &fs_info->tree_mod_log; node = tm_root->rb_node; while (node) { @@ -768,7 +738,7 @@ __tree_mod_log_search(struct btrfs_fs_info *fs_info, u64 start, u64 min_seq, break; } } - tree_mod_log_read_unlock(fs_info); + read_unlock(&fs_info->tree_mod_log_lock); return found; } @@ -849,7 +819,7 @@ tree_mod_log_eb_copy(struct btrfs_fs_info *fs_info, struct extent_buffer *dst, goto free_tms; } - tree_mod_log_write_unlock(fs_info); + write_unlock(&fs_info->tree_mod_log_lock); kfree(tm_list); return 0; @@ -861,36 +831,13 @@ free_tms: kfree(tm_list[i]); } if (locked) - tree_mod_log_write_unlock(fs_info); + write_unlock(&fs_info->tree_mod_log_lock); kfree(tm_list); return ret; } -static inline void -tree_mod_log_eb_move(struct btrfs_fs_info *fs_info, struct extent_buffer *dst, - int dst_offset, int src_offset, int nr_items) -{ - int ret; - ret = tree_mod_log_insert_move(fs_info, dst, dst_offset, src_offset, - nr_items); - BUG_ON(ret < 0); -} - -static noinline void -tree_mod_log_set_node_key(struct btrfs_fs_info *fs_info, - struct extent_buffer *eb, int slot, int atomic) -{ - int ret; - - ret = tree_mod_log_insert_key(fs_info, eb, slot, - MOD_LOG_KEY_REPLACE, - atomic ? GFP_ATOMIC : GFP_NOFS); - BUG_ON(ret < 0); -} - -static noinline int -tree_mod_log_free_eb(struct btrfs_fs_info *fs_info, struct extent_buffer *eb) +static noinline int tree_mod_log_free_eb(struct extent_buffer *eb) { struct tree_mod_elem **tm_list = NULL; int nritems = 0; @@ -900,7 +847,7 @@ tree_mod_log_free_eb(struct btrfs_fs_info *fs_info, struct extent_buffer *eb) if (btrfs_header_level(eb) == 0) return 0; - if (!tree_mod_need_log(fs_info, NULL)) + if (!tree_mod_need_log(eb->fs_info, NULL)) return 0; |