Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit af8c0816 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull btrfs fixes from David Sterba:

 - when NR_CPUS is large, a SRCU structure can significantly inflate
   size of the main filesystem structure that would not be possible to
   allocate by kmalloc, so the kvalloc fallback is used

 - improved error handling

 - fix endiannes when printing some filesystem attributes via sysfs,
   this is could happen when a filesystem is moved between different
   endianity hosts

 - send fixes: the NO_HOLE mode should not send a write operation for a
   file hole

 - fix log replay for for special files followed by file hardlinks

 - fix log replay failure after unlink and link combination

 - fix max chunk size calculation for DUP allocation

* tag 'for-4.16-rc3-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux:
  Btrfs: fix log replay failure after unlink and link combination
  Btrfs: fix log replay failure after linking special file and fsync
  Btrfs: send, fix issuing write op when processing hole in no data mode
  btrfs: use proper endianness accessors for super_copy
  btrfs: alloc_chunk: fix DUP stripe size handling
  btrfs: Handle btrfs_set_extent_delalloc failure in relocate_file_extent_cluster
  btrfs: handle failure of add_pending_csums
  btrfs: use kvzalloc to allocate btrfs_fs_info
parents 58bdf601 1f250e92
Loading
Loading
Loading
Loading
+5 −2
Original line number Diff line number Diff line
@@ -2974,7 +2974,7 @@ static inline void free_fs_info(struct btrfs_fs_info *fs_info)
	kfree(fs_info->super_copy);
	kfree(fs_info->super_for_commit);
	security_free_mnt_opts(&fs_info->security_opts);
	kfree(fs_info);
	kvfree(fs_info);
}

/* tree mod log functions from ctree.c */
@@ -3095,7 +3095,10 @@ btrfs_lookup_inode_extref(struct btrfs_trans_handle *trans,
			  u64 inode_objectid, u64 ref_objectid, int ins_len,
			  int cow);

int btrfs_find_name_in_ext_backref(struct btrfs_path *path,
int btrfs_find_name_in_backref(struct extent_buffer *leaf, int slot,
			       const char *name,
			       int name_len, struct btrfs_inode_ref **ref_ret);
int btrfs_find_name_in_ext_backref(struct extent_buffer *leaf, int slot,
				   u64 ref_objectid, const char *name,
				   int name_len,
				   struct btrfs_inode_extref **extref_ret);
+26 −18
Original line number Diff line number Diff line
@@ -22,10 +22,10 @@
#include "transaction.h"
#include "print-tree.h"

static int find_name_in_backref(struct btrfs_path *path, const char *name,
int btrfs_find_name_in_backref(struct extent_buffer *leaf, int slot,
			       const char *name,
			       int name_len, struct btrfs_inode_ref **ref_ret)
{
	struct extent_buffer *leaf;
	struct btrfs_inode_ref *ref;
	unsigned long ptr;
	unsigned long name_ptr;
@@ -33,9 +33,8 @@ static int find_name_in_backref(struct btrfs_path *path, const char *name,
	u32 cur_offset = 0;
	int len;

	leaf = path->nodes[0];
	item_size = btrfs_item_size_nr(leaf, path->slots[0]);
	ptr = btrfs_item_ptr_offset(leaf, path->slots[0]);
	item_size = btrfs_item_size_nr(leaf, slot);
	ptr = btrfs_item_ptr_offset(leaf, slot);
	while (cur_offset < item_size) {
		ref = (struct btrfs_inode_ref *)(ptr + cur_offset);
		len = btrfs_inode_ref_name_len(leaf, ref);
@@ -44,6 +43,7 @@ static int find_name_in_backref(struct btrfs_path *path, const char *name,
		if (len != name_len)
			continue;
		if (memcmp_extent_buffer(leaf, name, name_ptr, name_len) == 0) {
			if (ref_ret)
				*ref_ret = ref;
			return 1;
		}
@@ -51,11 +51,11 @@ static int find_name_in_backref(struct btrfs_path *path, const char *name,
	return 0;
}

int btrfs_find_name_in_ext_backref(struct btrfs_path *path, u64 ref_objectid,
int btrfs_find_name_in_ext_backref(struct extent_buffer *leaf, int slot,
				   u64 ref_objectid,
				   const char *name, int name_len,
				   struct btrfs_inode_extref **extref_ret)
{
	struct extent_buffer *leaf;
	struct btrfs_inode_extref *extref;
	unsigned long ptr;
	unsigned long name_ptr;
@@ -63,9 +63,8 @@ int btrfs_find_name_in_ext_backref(struct btrfs_path *path, u64 ref_objectid,
	u32 cur_offset = 0;
	int ref_name_len;

	leaf = path->nodes[0];
	item_size = btrfs_item_size_nr(leaf, path->slots[0]);
	ptr = btrfs_item_ptr_offset(leaf, path->slots[0]);
	item_size = btrfs_item_size_nr(leaf, slot);
	ptr = btrfs_item_ptr_offset(leaf, slot);

	/*
	 * Search all extended backrefs in this item. We're only
@@ -113,7 +112,9 @@ btrfs_lookup_inode_extref(struct btrfs_trans_handle *trans,
		return ERR_PTR(ret);
	if (ret > 0)
		return NULL;
	if (!btrfs_find_name_in_ext_backref(path, ref_objectid, name, name_len, &extref))
	if (!btrfs_find_name_in_ext_backref(path->nodes[0], path->slots[0],
					    ref_objectid, name, name_len,
					    &extref))
		return NULL;
	return extref;
}
@@ -155,7 +156,8 @@ static int btrfs_del_inode_extref(struct btrfs_trans_handle *trans,
	 * This should always succeed so error here will make the FS
	 * readonly.
	 */
	if (!btrfs_find_name_in_ext_backref(path, ref_objectid,
	if (!btrfs_find_name_in_ext_backref(path->nodes[0], path->slots[0],
					    ref_objectid,
					    name, name_len, &extref)) {
		btrfs_handle_fs_error(root->fs_info, -ENOENT, NULL);
		ret = -EROFS;
@@ -225,7 +227,8 @@ int btrfs_del_inode_ref(struct btrfs_trans_handle *trans,
	} else if (ret < 0) {
		goto out;
	}
	if (!find_name_in_backref(path, name, name_len, &ref)) {
	if (!btrfs_find_name_in_backref(path->nodes[0], path->slots[0],
					name, name_len, &ref)) {
		ret = -ENOENT;
		search_ext_refs = 1;
		goto out;
@@ -293,7 +296,9 @@ static int btrfs_insert_inode_extref(struct btrfs_trans_handle *trans,
	ret = btrfs_insert_empty_item(trans, root, path, &key,
				      ins_len);
	if (ret == -EEXIST) {
		if (btrfs_find_name_in_ext_backref(path, ref_objectid,
		if (btrfs_find_name_in_ext_backref(path->nodes[0],
						   path->slots[0],
						   ref_objectid,
						   name, name_len, NULL))
			goto out;

@@ -351,7 +356,8 @@ int btrfs_insert_inode_ref(struct btrfs_trans_handle *trans,
	if (ret == -EEXIST) {
		u32 old_size;

		if (find_name_in_backref(path, name, name_len, &ref))
		if (btrfs_find_name_in_backref(path->nodes[0], path->slots[0],
					       name, name_len, &ref))
			goto out;

		old_size = btrfs_item_size_nr(path->nodes[0], path->slots[0]);
@@ -365,7 +371,9 @@ int btrfs_insert_inode_ref(struct btrfs_trans_handle *trans,
		ret = 0;
	} else if (ret < 0) {
		if (ret == -EOVERFLOW) {
			if (find_name_in_backref(path, name, name_len, &ref))
			if (btrfs_find_name_in_backref(path->nodes[0],
						       path->slots[0],
						       name, name_len, &ref))
				ret = -EEXIST;
			else
				ret = -EMLINK;
+9 −2
Original line number Diff line number Diff line
@@ -2043,12 +2043,15 @@ static noinline int add_pending_csums(struct btrfs_trans_handle *trans,
			     struct inode *inode, struct list_head *list)
{
	struct btrfs_ordered_sum *sum;
	int ret;

	list_for_each_entry(sum, list, list) {
		trans->adding_csums = true;
		btrfs_csum_file_blocks(trans,
		ret = btrfs_csum_file_blocks(trans,
		       BTRFS_I(inode)->root->fs_info->csum_root, sum);
		trans->adding_csums = false;
		if (ret)
			return ret;
	}
	return 0;
}
@@ -3062,7 +3065,11 @@ static int btrfs_finish_ordered_io(struct btrfs_ordered_extent *ordered_extent)
		goto out;
	}

	add_pending_csums(trans, inode, &ordered_extent->list);
	ret = add_pending_csums(trans, inode, &ordered_extent->list);
	if (ret) {
		btrfs_abort_transaction(trans, ret);
		goto out;
	}

	btrfs_ordered_update_i_size(inode, 0, ordered_extent);
	ret = btrfs_update_inode_fallback(trans, root, inode);
+16 −2
Original line number Diff line number Diff line
@@ -3268,8 +3268,22 @@ static int relocate_file_extent_cluster(struct inode *inode,
			nr++;
		}

		btrfs_set_extent_delalloc(inode, page_start, page_end, 0, NULL,
					  0);
		ret = btrfs_set_extent_delalloc(inode, page_start, page_end, 0,
						NULL, 0);
		if (ret) {
			unlock_page(page);
			put_page(page);
			btrfs_delalloc_release_metadata(BTRFS_I(inode),
							 PAGE_SIZE);
			btrfs_delalloc_release_extents(BTRFS_I(inode),
			                               PAGE_SIZE);

			clear_extent_bits(&BTRFS_I(inode)->io_tree,
					  page_start, page_end,
					  EXTENT_LOCKED | EXTENT_BOUNDARY);
			goto out;

		}
		set_page_dirty(page);

		unlock_extent(&BTRFS_I(inode)->io_tree,
+3 −0
Original line number Diff line number Diff line
@@ -5005,6 +5005,9 @@ static int send_hole(struct send_ctx *sctx, u64 end)
	u64 len;
	int ret = 0;

	if (sctx->flags & BTRFS_SEND_FLAG_NO_FILE_DATA)
		return send_update_extent(sctx, offset, end - offset);

	p = fs_path_alloc();
	if (!p)
		return -ENOMEM;
Loading