Skip to content

Commit

Permalink
Merge tag 'for-4.16-rc3-tag' of git://git.kernel.org/pub/scm/linux/ke…
Browse files Browse the repository at this point in the history
…rnel/git/kdave/linux

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
  • Loading branch information
Linus Torvalds committed Mar 4, 2018
2 parents 58bdf60 + 1f250e9 commit af8c081
Show file tree
Hide file tree
Showing 10 changed files with 191 additions and 47 deletions.
7 changes: 5 additions & 2 deletions fs/btrfs/ctree.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down Expand Up @@ -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);
Expand Down
44 changes: 26 additions & 18 deletions fs/btrfs/inode-item.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,20 +22,19 @@
#include "transaction.h"
#include "print-tree.h"

static int find_name_in_backref(struct btrfs_path *path, const char *name,
int name_len, struct btrfs_inode_ref **ref_ret)
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;
u32 item_size;
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);
Expand All @@ -44,28 +43,28 @@ 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) {
*ref_ret = ref;
if (ref_ret)
*ref_ret = ref;
return 1;
}
}
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;
u32 item_size;
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
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -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]);
Expand All @@ -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;
Expand Down
11 changes: 9 additions & 2 deletions fs/btrfs/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down Expand Up @@ -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);
Expand Down
18 changes: 16 additions & 2 deletions fs/btrfs/relocation.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
3 changes: 3 additions & 0 deletions fs/btrfs/send.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
2 changes: 1 addition & 1 deletion fs/btrfs/super.c
Original file line number Diff line number Diff line change
Expand Up @@ -1545,7 +1545,7 @@ static struct dentry *btrfs_mount_root(struct file_system_type *fs_type,
* it for searching for existing supers, so this lets us do that and
* then open_ctree will properly initialize everything later.
*/
fs_info = kzalloc(sizeof(struct btrfs_fs_info), GFP_KERNEL);
fs_info = kvzalloc(sizeof(struct btrfs_fs_info), GFP_KERNEL);
if (!fs_info) {
error = -ENOMEM;
goto error_sec_opts;
Expand Down
8 changes: 3 additions & 5 deletions fs/btrfs/sysfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -423,7 +423,7 @@ static ssize_t btrfs_nodesize_show(struct kobject *kobj,
{
struct btrfs_fs_info *fs_info = to_fs_info(kobj);

return snprintf(buf, PAGE_SIZE, "%u\n", fs_info->super_copy->nodesize);
return snprintf(buf, PAGE_SIZE, "%u\n", fs_info->nodesize);
}

BTRFS_ATTR(, nodesize, btrfs_nodesize_show);
Expand All @@ -433,8 +433,7 @@ static ssize_t btrfs_sectorsize_show(struct kobject *kobj,
{
struct btrfs_fs_info *fs_info = to_fs_info(kobj);

return snprintf(buf, PAGE_SIZE, "%u\n",
fs_info->super_copy->sectorsize);
return snprintf(buf, PAGE_SIZE, "%u\n", fs_info->sectorsize);
}

BTRFS_ATTR(, sectorsize, btrfs_sectorsize_show);
Expand All @@ -444,8 +443,7 @@ static ssize_t btrfs_clone_alignment_show(struct kobject *kobj,
{
struct btrfs_fs_info *fs_info = to_fs_info(kobj);

return snprintf(buf, PAGE_SIZE, "%u\n",
fs_info->super_copy->sectorsize);
return snprintf(buf, PAGE_SIZE, "%u\n", fs_info->sectorsize);
}

BTRFS_ATTR(, clone_alignment, btrfs_clone_alignment_show);
Expand Down
20 changes: 12 additions & 8 deletions fs/btrfs/transaction.c
Original file line number Diff line number Diff line change
Expand Up @@ -1722,19 +1722,23 @@ static void update_super_roots(struct btrfs_fs_info *fs_info)

super = fs_info->super_copy;

/* update latest btrfs_super_block::chunk_root refs */
root_item = &fs_info->chunk_root->root_item;
super->chunk_root = root_item->bytenr;
super->chunk_root_generation = root_item->generation;
super->chunk_root_level = root_item->level;
btrfs_set_super_chunk_root(super, root_item->bytenr);
btrfs_set_super_chunk_root_generation(super, root_item->generation);
btrfs_set_super_chunk_root_level(super, root_item->level);

/* update latest btrfs_super_block::root refs */
root_item = &fs_info->tree_root->root_item;
super->root = root_item->bytenr;
super->generation = root_item->generation;
super->root_level = root_item->level;
btrfs_set_super_root(super, root_item->bytenr);
btrfs_set_super_generation(super, root_item->generation);
btrfs_set_super_root_level(super, root_item->level);

if (btrfs_test_opt(fs_info, SPACE_CACHE))
super->cache_generation = root_item->generation;
btrfs_set_super_cache_generation(super, root_item->generation);
if (test_bit(BTRFS_FS_UPDATE_UUID_TREE_GEN, &fs_info->flags))
super->uuid_tree_generation = root_item->generation;
btrfs_set_super_uuid_tree_generation(super,
root_item->generation);
}

int btrfs_transaction_in_commit(struct btrfs_fs_info *info)
Expand Down
Loading

0 comments on commit af8c081

Please sign in to comment.