Commit af8c0816 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'for-4.16-rc3-tag' of git://git.kernel.org/pub/scm/linux/kernel/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
parents 58bdf601 1f250e92
...@@ -2974,7 +2974,7 @@ static inline void free_fs_info(struct btrfs_fs_info *fs_info) ...@@ -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_copy);
kfree(fs_info->super_for_commit); kfree(fs_info->super_for_commit);
security_free_mnt_opts(&fs_info->security_opts); security_free_mnt_opts(&fs_info->security_opts);
kfree(fs_info); kvfree(fs_info);
} }
/* tree mod log functions from ctree.c */ /* tree mod log functions from ctree.c */
...@@ -3095,7 +3095,10 @@ btrfs_lookup_inode_extref(struct btrfs_trans_handle *trans, ...@@ -3095,7 +3095,10 @@ btrfs_lookup_inode_extref(struct btrfs_trans_handle *trans,
u64 inode_objectid, u64 ref_objectid, int ins_len, u64 inode_objectid, u64 ref_objectid, int ins_len,
int cow); 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, u64 ref_objectid, const char *name,
int name_len, int name_len,
struct btrfs_inode_extref **extref_ret); struct btrfs_inode_extref **extref_ret);
......
...@@ -22,10 +22,10 @@ ...@@ -22,10 +22,10 @@
#include "transaction.h" #include "transaction.h"
#include "print-tree.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,
int name_len, struct btrfs_inode_ref **ref_ret) const char *name,
int name_len, struct btrfs_inode_ref **ref_ret)
{ {
struct extent_buffer *leaf;
struct btrfs_inode_ref *ref; struct btrfs_inode_ref *ref;
unsigned long ptr; unsigned long ptr;
unsigned long name_ptr; unsigned long name_ptr;
...@@ -33,9 +33,8 @@ static int find_name_in_backref(struct btrfs_path *path, const char *name, ...@@ -33,9 +33,8 @@ static int find_name_in_backref(struct btrfs_path *path, const char *name,
u32 cur_offset = 0; u32 cur_offset = 0;
int len; int len;
leaf = path->nodes[0]; item_size = btrfs_item_size_nr(leaf, slot);
item_size = btrfs_item_size_nr(leaf, path->slots[0]); ptr = btrfs_item_ptr_offset(leaf, slot);
ptr = btrfs_item_ptr_offset(leaf, path->slots[0]);
while (cur_offset < item_size) { while (cur_offset < item_size) {
ref = (struct btrfs_inode_ref *)(ptr + cur_offset); ref = (struct btrfs_inode_ref *)(ptr + cur_offset);
len = btrfs_inode_ref_name_len(leaf, ref); len = btrfs_inode_ref_name_len(leaf, ref);
...@@ -44,18 +43,19 @@ static int find_name_in_backref(struct btrfs_path *path, const char *name, ...@@ -44,18 +43,19 @@ static int find_name_in_backref(struct btrfs_path *path, const char *name,
if (len != name_len) if (len != name_len)
continue; continue;
if (memcmp_extent_buffer(leaf, name, name_ptr, name_len) == 0) { if (memcmp_extent_buffer(leaf, name, name_ptr, name_len) == 0) {
*ref_ret = ref; if (ref_ret)
*ref_ret = ref;
return 1; return 1;
} }
} }
return 0; 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, const char *name, int name_len,
struct btrfs_inode_extref **extref_ret) struct btrfs_inode_extref **extref_ret)
{ {
struct extent_buffer *leaf;
struct btrfs_inode_extref *extref; struct btrfs_inode_extref *extref;
unsigned long ptr; unsigned long ptr;
unsigned long name_ptr; unsigned long name_ptr;
...@@ -63,9 +63,8 @@ int btrfs_find_name_in_ext_backref(struct btrfs_path *path, u64 ref_objectid, ...@@ -63,9 +63,8 @@ int btrfs_find_name_in_ext_backref(struct btrfs_path *path, u64 ref_objectid,
u32 cur_offset = 0; u32 cur_offset = 0;
int ref_name_len; int ref_name_len;
leaf = path->nodes[0]; item_size = btrfs_item_size_nr(leaf, slot);
item_size = btrfs_item_size_nr(leaf, path->slots[0]); ptr = btrfs_item_ptr_offset(leaf, slot);
ptr = btrfs_item_ptr_offset(leaf, path->slots[0]);
/* /*
* Search all extended backrefs in this item. We're only * Search all extended backrefs in this item. We're only
...@@ -113,7 +112,9 @@ btrfs_lookup_inode_extref(struct btrfs_trans_handle *trans, ...@@ -113,7 +112,9 @@ btrfs_lookup_inode_extref(struct btrfs_trans_handle *trans,
return ERR_PTR(ret); return ERR_PTR(ret);
if (ret > 0) if (ret > 0)
return NULL; 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 NULL;
return extref; return extref;
} }
...@@ -155,7 +156,8 @@ static int btrfs_del_inode_extref(struct btrfs_trans_handle *trans, ...@@ -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 * This should always succeed so error here will make the FS
* readonly. * 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)) { name, name_len, &extref)) {
btrfs_handle_fs_error(root->fs_info, -ENOENT, NULL); btrfs_handle_fs_error(root->fs_info, -ENOENT, NULL);
ret = -EROFS; ret = -EROFS;
...@@ -225,7 +227,8 @@ int btrfs_del_inode_ref(struct btrfs_trans_handle *trans, ...@@ -225,7 +227,8 @@ int btrfs_del_inode_ref(struct btrfs_trans_handle *trans,
} else if (ret < 0) { } else if (ret < 0) {
goto out; 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; ret = -ENOENT;
search_ext_refs = 1; search_ext_refs = 1;
goto out; goto out;
...@@ -293,7 +296,9 @@ static int btrfs_insert_inode_extref(struct btrfs_trans_handle *trans, ...@@ -293,7 +296,9 @@ static int btrfs_insert_inode_extref(struct btrfs_trans_handle *trans,
ret = btrfs_insert_empty_item(trans, root, path, &key, ret = btrfs_insert_empty_item(trans, root, path, &key,
ins_len); ins_len);
if (ret == -EEXIST) { 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)) name, name_len, NULL))
goto out; goto out;
...@@ -351,7 +356,8 @@ int btrfs_insert_inode_ref(struct btrfs_trans_handle *trans, ...@@ -351,7 +356,8 @@ int btrfs_insert_inode_ref(struct btrfs_trans_handle *trans,
if (ret == -EEXIST) { if (ret == -EEXIST) {
u32 old_size; 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; goto out;
old_size = btrfs_item_size_nr(path->nodes[0], path->slots[0]); 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, ...@@ -365,7 +371,9 @@ int btrfs_insert_inode_ref(struct btrfs_trans_handle *trans,
ret = 0; ret = 0;
} else if (ret < 0) { } else if (ret < 0) {
if (ret == -EOVERFLOW) { 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; ret = -EEXIST;
else else
ret = -EMLINK; ret = -EMLINK;
......
...@@ -2043,12 +2043,15 @@ static noinline int add_pending_csums(struct btrfs_trans_handle *trans, ...@@ -2043,12 +2043,15 @@ static noinline int add_pending_csums(struct btrfs_trans_handle *trans,
struct inode *inode, struct list_head *list) struct inode *inode, struct list_head *list)
{ {
struct btrfs_ordered_sum *sum; struct btrfs_ordered_sum *sum;
int ret;
list_for_each_entry(sum, list, list) { list_for_each_entry(sum, list, list) {
trans->adding_csums = true; trans->adding_csums = true;
btrfs_csum_file_blocks(trans, ret = btrfs_csum_file_blocks(trans,
BTRFS_I(inode)->root->fs_info->csum_root, sum); BTRFS_I(inode)->root->fs_info->csum_root, sum);
trans->adding_csums = false; trans->adding_csums = false;
if (ret)
return ret;
} }
return 0; return 0;
} }
...@@ -3062,7 +3065,11 @@ static int btrfs_finish_ordered_io(struct btrfs_ordered_extent *ordered_extent) ...@@ -3062,7 +3065,11 @@ static int btrfs_finish_ordered_io(struct btrfs_ordered_extent *ordered_extent)
goto out; 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); btrfs_ordered_update_i_size(inode, 0, ordered_extent);
ret = btrfs_update_inode_fallback(trans, root, inode); ret = btrfs_update_inode_fallback(trans, root, inode);
......
...@@ -3268,8 +3268,22 @@ static int relocate_file_extent_cluster(struct inode *inode, ...@@ -3268,8 +3268,22 @@ static int relocate_file_extent_cluster(struct inode *inode,
nr++; nr++;
} }
btrfs_set_extent_delalloc(inode, page_start, page_end, 0, NULL, ret = btrfs_set_extent_delalloc(inode, page_start, page_end, 0,
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); set_page_dirty(page);
unlock_extent(&BTRFS_I(inode)->io_tree, unlock_extent(&BTRFS_I(inode)->io_tree,
......
...@@ -5005,6 +5005,9 @@ static int send_hole(struct send_ctx *sctx, u64 end) ...@@ -5005,6 +5005,9 @@ static int send_hole(struct send_ctx *sctx, u64 end)
u64 len; u64 len;
int ret = 0; int ret = 0;
if (sctx->flags & BTRFS_SEND_FLAG_NO_FILE_DATA)
return send_update_extent(sctx, offset, end - offset);
p = fs_path_alloc(); p = fs_path_alloc();
if (!p) if (!p)
return -ENOMEM; return -ENOMEM;
......
...@@ -1545,7 +1545,7 @@ static struct dentry *btrfs_mount_root(struct file_system_type *fs_type, ...@@ -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 * it for searching for existing supers, so this lets us do that and
* then open_ctree will properly initialize everything later. * then open_ctree will properly initialize everything later.
*/ */
fs_info = kzalloc(sizeof(struct btrfs_fs_info), GFP_KERNEL); fs_info = kvzalloc(sizeof(struct btrfs_fs_info), GFP_KERNEL);
if (!fs_info) { if (!fs_info) {
error = -ENOMEM; error = -ENOMEM;
goto error_sec_opts; goto error_sec_opts;
......
...@@ -423,7 +423,7 @@ static ssize_t btrfs_nodesize_show(struct kobject *kobj, ...@@ -423,7 +423,7 @@ static ssize_t btrfs_nodesize_show(struct kobject *kobj,
{ {
struct btrfs_fs_info *fs_info = to_fs_info(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); BTRFS_ATTR(, nodesize, btrfs_nodesize_show);
...@@ -433,8 +433,7 @@ static ssize_t btrfs_sectorsize_show(struct kobject *kobj, ...@@ -433,8 +433,7 @@ static ssize_t btrfs_sectorsize_show(struct kobject *kobj,
{ {
struct btrfs_fs_info *fs_info = to_fs_info(kobj); struct btrfs_fs_info *fs_info = to_fs_info(kobj);
return snprintf(buf, PAGE_SIZE, "%u\n", return snprintf(buf, PAGE_SIZE, "%u\n", fs_info->sectorsize);
fs_info->super_copy->sectorsize);
} }
BTRFS_ATTR(, sectorsize, btrfs_sectorsize_show); BTRFS_ATTR(, sectorsize, btrfs_sectorsize_show);
...@@ -444,8 +443,7 @@ static ssize_t btrfs_clone_alignment_show(struct kobject *kobj, ...@@ -444,8 +443,7 @@ static ssize_t btrfs_clone_alignment_show(struct kobject *kobj,
{ {
struct btrfs_fs_info *fs_info = to_fs_info(kobj); struct btrfs_fs_info *fs_info = to_fs_info(kobj);
return snprintf(buf, PAGE_SIZE, "%u\n", return snprintf(buf, PAGE_SIZE, "%u\n", fs_info->sectorsize);
fs_info->super_copy->sectorsize);
} }
BTRFS_ATTR(, clone_alignment, btrfs_clone_alignment_show); BTRFS_ATTR(, clone_alignment, btrfs_clone_alignment_show);
......
...@@ -1722,19 +1722,23 @@ static void update_super_roots(struct btrfs_fs_info *fs_info) ...@@ -1722,19 +1722,23 @@ static void update_super_roots(struct btrfs_fs_info *fs_info)
super = fs_info->super_copy; super = fs_info->super_copy;
/* update latest btrfs_super_block::chunk_root refs */
root_item = &fs_info->chunk_root->root_item; root_item = &fs_info->chunk_root->root_item;
super->chunk_root = root_item->bytenr; btrfs_set_super_chunk_root(super, root_item->bytenr);
super->chunk_root_generation = root_item->generation; btrfs_set_super_chunk_root_generation(super, root_item->generation);
super->chunk_root_level = root_item->level; 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; root_item = &fs_info->tree_root->root_item;
super->root = root_item->bytenr; btrfs_set_super_root(super, root_item->bytenr);
super->generation = root_item->generation; btrfs_set_super_generation(super, root_item->generation);
super->root_level = root_item->level; btrfs_set_super_root_level(super, root_item->level);
if (btrfs_test_opt(fs_info, SPACE_CACHE)) 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)) 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) int btrfs_transaction_in_commit(struct btrfs_fs_info *info)
......
...@@ -967,7 +967,9 @@ static noinline int backref_in_log(struct btrfs_root *log, ...@@ -967,7 +967,9 @@ static noinline int backref_in_log(struct btrfs_root *log,
ptr = btrfs_item_ptr_offset(path->nodes[0], path->slots[0]); ptr = btrfs_item_ptr_offset(path->nodes[0], path->slots[0]);
if (key->type == BTRFS_INODE_EXTREF_KEY) { if (key->type == BTRFS_INODE_EXTREF_KEY) {
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, namelen, NULL)) name, namelen, NULL))
match = 1; match = 1;
...@@ -1191,7 +1193,8 @@ static int extref_get_fields(struct extent_buffer *eb, unsigned long ref_ptr, ...@@ -1191,7 +1193,8 @@ static int extref_get_fields(struct extent_buffer *eb, unsigned long ref_ptr,
read_extent_buffer(eb, *name, (unsigned long)&extref->name, read_extent_buffer(eb, *name, (unsigned long)&extref->name,
*namelen); *namelen);
*index = btrfs_inode_extref_index(eb, extref); if (index)
*index = btrfs_inode_extref_index(eb, extref);
if (parent_objectid) if (parent_objectid)
*parent_objectid = btrfs_inode_extref_parent(eb, extref); *parent_objectid = btrfs_inode_extref_parent(eb, extref);
...@@ -1212,11 +1215,101 @@ static int ref_get_fields(struct extent_buffer *eb, unsigned long ref_ptr, ...@@ -1212,11 +1215,101 @@ static int ref_get_fields(struct extent_buffer *eb, unsigned long ref_ptr,
read_extent_buffer(eb, *name, (unsigned long)(ref + 1), *namelen); read_extent_buffer(eb, *name, (unsigned long)(ref + 1), *namelen);
*index = btrfs_inode_ref_index(eb, ref); if (index)
*index = btrfs_inode_ref_index(eb, ref);
return 0; return 0;
} }
/*
* Take an inode reference item from the log tree and iterate all names from the
* inode reference item in the subvolume tree with the same key (if it exists).
* For any name that is not in the inode reference item from the log tree, do a
* proper unlink of that name (that is, remove its entry from the inode
* reference item and both dir index keys).
*/
static int unlink_old_inode_refs(struct btrfs_trans_handle *trans,
struct btrfs_root *root,
struct btrfs_path *path,
struct btrfs_inode *inode,
struct extent_buffer *log_eb,
int log_slot,
struct btrfs_key *key)
{
int ret;
unsigned long ref_ptr;
unsigned long ref_end;
struct extent_buffer *eb;
again:
btrfs_release_path(path);
ret = btrfs_search_slot(NULL, root, key, path, 0, 0);
if (ret > 0) {
ret = 0;
goto out;
}
if (ret < 0)
goto out;
eb = path->nodes[0];
ref_ptr = btrfs_item_ptr_offset(eb, path->slots[0]);
ref_end = ref_ptr + btrfs_item_size_nr(eb, path->slots[0]);
while (ref_ptr < ref_end) {
char *name = NULL;
int namelen;
u64 parent_id;
if (key->type == BTRFS_INODE_EXTREF_KEY) {
ret = extref_get_fields(eb, ref_ptr, &namelen, &name,
NULL, &parent_id);
} else {
parent_id = key->offset;
ret = ref_get_fields(eb, ref_ptr, &namelen, &name,
NULL);
}
if (ret)
goto out;
if (key->type == BTRFS_INODE_EXTREF_KEY)
ret = btrfs_find_name_in_ext_backref(log_eb, log_slot,
parent_id, name,
namelen, NULL);
else
ret = btrfs_find_name_in_backref(log_eb, log_slot, name,
namelen, NULL);
if (!ret) {
struct inode *dir;
btrfs_release_path(path);
dir = read_one_inode(root, parent_id);
if (!dir) {
ret = -ENOENT;
kfree(name);
goto out;
}
ret = btrfs_unlink_inode(trans, root, BTRFS_I(dir),
inode, name, namelen);
kfree(name);
iput(dir);
if (ret)
goto out;
goto again;
}
kfree(name);
ref_ptr += namelen;
if (key->type == BTRFS_INODE_EXTREF_KEY)
ref_ptr += sizeof(struct btrfs_inode_extref);
else
ref_ptr += sizeof(struct btrfs_inode_ref);
}
ret = 0;
out:
btrfs_release_path(path);
return ret;
}
/* /*
* replay one inode back reference item found in the log tree. * replay one inode back reference item found in the log tree.
* eb, slot and key refer to the buffer and key found in the log tree. * eb, slot and key refer to the buffer and key found in the log tree.
...@@ -1345,6 +1438,19 @@ static noinline int add_inode_ref(struct btrfs_trans_handle *trans, ...@@ -1345,6 +1438,19 @@ static noinline int add_inode_ref(struct btrfs_trans_handle *trans,
} }
} }
/*
* Before we overwrite the inode reference item in the subvolume tree
* with the item from the log tree, we must unlink all names from the
* parent directory that are in the subvolume's tree inode reference
* item, otherwise we end up with an inconsistent subvolume tree where
* dir index entries exist for a name but there is no inode reference
* item with the same name.
*/
ret = unlink_old_inode_refs(trans, root, path, BTRFS_I(inode), eb, slot,
key);
if (ret)
goto out;
/* finally write the back reference in the inode */ /* finally write the back reference in the inode */
ret = overwrite_item(trans, root, path, eb, slot, key); ret = overwrite_item(trans, root, path, eb, slot, key);
out: out:
...@@ -5853,7 +5959,7 @@ int btrfs_log_new_name(struct btrfs_trans_handle *trans, ...@@ -5853,7 +5959,7 @@ int btrfs_log_new_name(struct btrfs_trans_handle *trans,
* this will force the logging code to walk the dentry chain * this will force the logging code to walk the dentry chain
* up for the file * up for the file
*/ */
if (S_ISREG(inode->vfs_inode.i_mode)) if (!S_ISDIR(inode->vfs_inode.i_mode))
inode->last_unlink_trans = trans->transid; inode->last_unlink_trans = trans->transid;
/* /*
......
...@@ -4829,10 +4829,13 @@ static int __btrfs_alloc_chunk(struct btrfs_trans_handle *trans, ...@@ -4829,10 +4829,13 @@ static int __btrfs_alloc_chunk(struct btrfs_trans_handle *trans,
ndevs = min(ndevs, devs_max); ndevs = min(ndevs, devs_max);
/* /*
* the primary goal is to maximize the number of stripes, so use as many * The primary goal is to maximize the number of stripes, so use as
* devices as possible, even if the stripes are not maximum sized. * many devices as possible, even if the stripes are not maximum sized.
*
* The DUP profile stores more than one stripe per device, the
* max_avail is the total size so we have to adjust.
*/ */
stripe_size = devices_info[ndevs-1].max_avail; stripe_size = div_u64(devices_info[ndevs - 1].max_avail, dev_stripes);
num_stripes = ndevs * dev_stripes; num_stripes = ndevs * dev_stripes;
/* /*
...@@ -4867,8 +4870,6 @@ static int __btrfs_alloc_chunk(struct btrfs_trans_handle *trans, ...@@ -4867,8 +4870,6 @@ static int __btrfs_alloc_chunk(struct btrfs_trans_handle *trans,
stripe_size = devices_info[ndevs-1].max_avail; stripe_size = devices_info[ndevs-1].max_avail;
} }
stripe_size = div_u64(stripe_size, dev_stripes);
/* align to BTRFS_STRIPE_LEN */ /* align to BTRFS_STRIPE_LEN */
stripe_size = round_down(stripe_size, BTRFS_STRIPE_LEN); stripe_size = round_down(stripe_size, BTRFS_STRIPE_LEN);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment