2007-06-12 21:07:11 +08:00
|
|
|
/*
|
|
|
|
* Copyright (C) 2007 Oracle. All rights reserved.
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU General Public
|
|
|
|
* License v2 as published by the Free Software Foundation.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public
|
|
|
|
* License along with this program; if not, write to the
|
|
|
|
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
|
|
|
* Boston, MA 021110-1307, USA.
|
|
|
|
*/
|
|
|
|
|
2012-09-21 05:26:28 +08:00
|
|
|
#include "kerncompat.h"
|
2015-09-01 00:15:27 +08:00
|
|
|
#include "androidcompat.h"
|
2012-09-21 05:26:28 +08:00
|
|
|
|
2008-04-29 04:44:22 +08:00
|
|
|
#include <sys/ioctl.h>
|
|
|
|
#include <sys/mount.h>
|
|
|
|
#include "ioctl.h"
|
2007-02-21 05:41:09 +08:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/stat.h>
|
2015-09-01 00:15:27 +08:00
|
|
|
/* #include <sys/dir.h> included via androidcompat.h */
|
2007-02-21 05:41:09 +08:00
|
|
|
#include <fcntl.h>
|
|
|
|
#include <unistd.h>
|
2008-04-01 23:08:13 +08:00
|
|
|
#include <getopt.h>
|
2007-04-06 02:29:12 +08:00
|
|
|
#include <uuid/uuid.h>
|
2007-12-22 05:25:35 +08:00
|
|
|
#include <ctype.h>
|
2014-02-02 21:01:20 +08:00
|
|
|
#include <sys/xattr.h>
|
2014-12-13 22:07:25 +08:00
|
|
|
#include <limits.h>
|
|
|
|
#include <linux/limits.h>
|
2013-01-20 02:06:21 +08:00
|
|
|
#include <blkid/blkid.h>
|
2013-01-18 07:23:10 +08:00
|
|
|
#include <ftw.h>
|
2007-02-21 05:41:09 +08:00
|
|
|
#include "ctree.h"
|
|
|
|
#include "disk-io.h"
|
2008-03-25 03:03:18 +08:00
|
|
|
#include "volumes.h"
|
2007-03-21 23:13:29 +08:00
|
|
|
#include "transaction.h"
|
2008-01-04 23:38:22 +08:00
|
|
|
#include "utils.h"
|
2015-11-03 19:03:00 +08:00
|
|
|
#include "list_sort.h"
|
2007-02-21 05:41:09 +08:00
|
|
|
|
2010-07-08 17:17:59 +08:00
|
|
|
static u64 index_cnt = 2;
|
2014-12-18 04:14:05 +08:00
|
|
|
static int verbose = 1;
|
2010-07-08 17:17:59 +08:00
|
|
|
|
|
|
|
struct directory_name_entry {
|
|
|
|
char *dir_name;
|
|
|
|
char *path;
|
|
|
|
ino_t inum;
|
|
|
|
struct list_head list;
|
|
|
|
};
|
|
|
|
|
2015-06-08 18:54:54 +08:00
|
|
|
struct mkfs_allocation {
|
|
|
|
u64 data;
|
|
|
|
u64 metadata;
|
|
|
|
u64 mixed;
|
|
|
|
u64 system;
|
|
|
|
};
|
|
|
|
|
Revert "btrfs-progs: mkfs: create only desired block groups for single device"
This reverts commit 5f8232e5c8f0b0de0ef426274911385b0e877392.
This commit causes a regression:
$ mkfs.btrfs -f /dev/sda6
$ btrfsck /dev/sda6
Checking filesystem on /dev/sda6
UUID: 2ebb483c-1986-4610-802a-c6f3e6ab4b76
checking extents
Chunk[256, 228, 0]: length(4194304), offset(0), type(2) mismatch with
block group[0, 192, 4194304]: offset(4194304), objectid(0), flags(34)
Chunk[256, 228, 4194304]: length(8388608), offset(4194304), type(4)
mismatch with block group[4194304, 192, 8388608]: offset(8388608),
objectid(4194304), flags(36)
Block group[0, 4194304] (flags = 34) didn't find the relative chunk.
Block group[4194304, 8388608] (flags = 36) didn't find the relative
chunk.
......
The commit has the following bug causing the problem.
1) Typo forgets to add meta/data_profile for alloc_chunk.
Only meta/data_profile is added to allocate a block group, but not
chunk.
2) Type for the first system chunk is impossible to modify yet.
The type for the first chunk and its stripe is hard coded into
make_btrfs() function.
So even we try to modify the type of the block group, we are unable to
change the type of the first chunk.
Causing the chunk type mismatch problem.
The 1st bug can be fixed quite easily but the second is not.
The good news is, the last patch "btrfs-progs: mkfs: Cleanup temporary
chunk to avoid strange balance behavior." from my patchset can handle it
quite well alone.
So just revert the patch.
New bug fix for btrfsck(err is 0 even chunk/extent tree is corrupted) and
new test cases for mkfs will follow soon.
Signed-off-by: Qu Wenruo <quwenruo@cn.fujitsu.com>
Signed-off-by: David Sterba <dsterba@suse.com>
2015-07-14 10:13:01 +08:00
|
|
|
static int create_metadata_block_groups(struct btrfs_root *root, int mixed,
|
|
|
|
struct mkfs_allocation *allocation)
|
2008-09-24 00:29:10 +08:00
|
|
|
{
|
2007-04-07 03:39:12 +08:00
|
|
|
struct btrfs_trans_handle *trans;
|
2008-03-25 03:03:18 +08:00
|
|
|
u64 bytes_used;
|
|
|
|
u64 chunk_start = 0;
|
|
|
|
u64 chunk_size = 0;
|
2008-01-04 23:38:22 +08:00
|
|
|
int ret;
|
2007-04-07 03:39:12 +08:00
|
|
|
|
|
|
|
trans = btrfs_start_transaction(root, 1);
|
2013-03-07 00:32:51 +08:00
|
|
|
bytes_used = btrfs_super_bytes_used(root->fs_info->super_copy);
|
2008-03-25 03:03:18 +08:00
|
|
|
|
2008-04-23 02:06:56 +08:00
|
|
|
root->fs_info->system_allocs = 1;
|
2008-03-25 03:03:18 +08:00
|
|
|
ret = btrfs_make_block_group(trans, root, bytes_used,
|
|
|
|
BTRFS_BLOCK_GROUP_SYSTEM,
|
2008-04-16 03:42:08 +08:00
|
|
|
BTRFS_FIRST_CHUNK_TREE_OBJECTID,
|
2008-03-25 03:03:18 +08:00
|
|
|
0, BTRFS_MKFS_SYSTEM_GROUP_SIZE);
|
2015-06-08 18:54:54 +08:00
|
|
|
allocation->system += BTRFS_MKFS_SYSTEM_GROUP_SIZE;
|
2016-08-22 22:57:15 +08:00
|
|
|
if (ret)
|
|
|
|
return ret;
|
2008-04-16 03:42:08 +08:00
|
|
|
|
2010-12-10 02:31:08 +08:00
|
|
|
if (mixed) {
|
|
|
|
ret = btrfs_alloc_chunk(trans, root->fs_info->extent_root,
|
|
|
|
&chunk_start, &chunk_size,
|
|
|
|
BTRFS_BLOCK_GROUP_METADATA |
|
|
|
|
BTRFS_BLOCK_GROUP_DATA);
|
2013-09-05 14:55:08 +08:00
|
|
|
if (ret == -ENOSPC) {
|
2016-08-19 00:38:34 +08:00
|
|
|
error("no space to allocate data/metadata chunk");
|
2013-09-05 14:55:08 +08:00
|
|
|
goto err;
|
|
|
|
}
|
2016-08-22 22:57:15 +08:00
|
|
|
if (ret)
|
|
|
|
return ret;
|
2010-12-10 02:31:08 +08:00
|
|
|
ret = btrfs_make_block_group(trans, root, 0,
|
|
|
|
BTRFS_BLOCK_GROUP_METADATA |
|
|
|
|
BTRFS_BLOCK_GROUP_DATA,
|
|
|
|
BTRFS_FIRST_CHUNK_TREE_OBJECTID,
|
|
|
|
chunk_start, chunk_size);
|
2016-08-22 22:57:15 +08:00
|
|
|
if (ret)
|
|
|
|
return ret;
|
2015-06-08 18:54:54 +08:00
|
|
|
allocation->mixed += chunk_size;
|
2010-12-10 02:31:08 +08:00
|
|
|
} else {
|
|
|
|
ret = btrfs_alloc_chunk(trans, root->fs_info->extent_root,
|
|
|
|
&chunk_start, &chunk_size,
|
|
|
|
BTRFS_BLOCK_GROUP_METADATA);
|
2013-09-05 14:55:08 +08:00
|
|
|
if (ret == -ENOSPC) {
|
2016-08-19 00:38:34 +08:00
|
|
|
error("no space to allocate metadata chunk");
|
2013-09-05 14:55:08 +08:00
|
|
|
goto err;
|
|
|
|
}
|
2016-08-22 22:57:15 +08:00
|
|
|
if (ret)
|
|
|
|
return ret;
|
2010-12-10 02:31:08 +08:00
|
|
|
ret = btrfs_make_block_group(trans, root, 0,
|
|
|
|
BTRFS_BLOCK_GROUP_METADATA,
|
|
|
|
BTRFS_FIRST_CHUNK_TREE_OBJECTID,
|
|
|
|
chunk_start, chunk_size);
|
2015-06-08 18:54:54 +08:00
|
|
|
allocation->metadata += chunk_size;
|
2016-08-22 22:57:15 +08:00
|
|
|
if (ret)
|
|
|
|
return ret;
|
2010-12-10 02:31:08 +08:00
|
|
|
}
|
2008-03-25 03:03:18 +08:00
|
|
|
|
2008-04-23 02:06:56 +08:00
|
|
|
root->fs_info->system_allocs = 0;
|
2016-08-22 22:57:15 +08:00
|
|
|
ret = btrfs_commit_transaction(trans, root);
|
2015-07-02 01:12:38 +08:00
|
|
|
|
|
|
|
err:
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2015-07-02 01:19:05 +08:00
|
|
|
static int create_data_block_groups(struct btrfs_trans_handle *trans,
|
Revert "btrfs-progs: mkfs: create only desired block groups for single device"
This reverts commit 5f8232e5c8f0b0de0ef426274911385b0e877392.
This commit causes a regression:
$ mkfs.btrfs -f /dev/sda6
$ btrfsck /dev/sda6
Checking filesystem on /dev/sda6
UUID: 2ebb483c-1986-4610-802a-c6f3e6ab4b76
checking extents
Chunk[256, 228, 0]: length(4194304), offset(0), type(2) mismatch with
block group[0, 192, 4194304]: offset(4194304), objectid(0), flags(34)
Chunk[256, 228, 4194304]: length(8388608), offset(4194304), type(4)
mismatch with block group[4194304, 192, 8388608]: offset(8388608),
objectid(4194304), flags(36)
Block group[0, 4194304] (flags = 34) didn't find the relative chunk.
Block group[4194304, 8388608] (flags = 36) didn't find the relative
chunk.
......
The commit has the following bug causing the problem.
1) Typo forgets to add meta/data_profile for alloc_chunk.
Only meta/data_profile is added to allocate a block group, but not
chunk.
2) Type for the first system chunk is impossible to modify yet.
The type for the first chunk and its stripe is hard coded into
make_btrfs() function.
So even we try to modify the type of the block group, we are unable to
change the type of the first chunk.
Causing the chunk type mismatch problem.
The 1st bug can be fixed quite easily but the second is not.
The good news is, the last patch "btrfs-progs: mkfs: Cleanup temporary
chunk to avoid strange balance behavior." from my patchset can handle it
quite well alone.
So just revert the patch.
New bug fix for btrfsck(err is 0 even chunk/extent tree is corrupted) and
new test cases for mkfs will follow soon.
Signed-off-by: Qu Wenruo <quwenruo@cn.fujitsu.com>
Signed-off-by: David Sterba <dsterba@suse.com>
2015-07-14 10:13:01 +08:00
|
|
|
struct btrfs_root *root, int mixed,
|
2015-07-02 01:19:05 +08:00
|
|
|
struct mkfs_allocation *allocation)
|
2015-07-02 01:12:38 +08:00
|
|
|
{
|
|
|
|
u64 chunk_start = 0;
|
|
|
|
u64 chunk_size = 0;
|
2015-07-02 01:19:05 +08:00
|
|
|
int ret = 0;
|
2015-07-02 01:12:38 +08:00
|
|
|
|
2010-12-10 02:31:08 +08:00
|
|
|
if (!mixed) {
|
|
|
|
ret = btrfs_alloc_chunk(trans, root->fs_info->extent_root,
|
|
|
|
&chunk_start, &chunk_size,
|
|
|
|
BTRFS_BLOCK_GROUP_DATA);
|
2013-09-05 14:55:08 +08:00
|
|
|
if (ret == -ENOSPC) {
|
2016-08-19 00:38:34 +08:00
|
|
|
error("no space to allocate data chunk");
|
2013-09-05 14:55:08 +08:00
|
|
|
goto err;
|
|
|
|
}
|
2016-08-22 22:57:15 +08:00
|
|
|
if (ret)
|
|
|
|
return ret;
|
2010-12-10 02:31:08 +08:00
|
|
|
ret = btrfs_make_block_group(trans, root, 0,
|
|
|
|
BTRFS_BLOCK_GROUP_DATA,
|
|
|
|
BTRFS_FIRST_CHUNK_TREE_OBJECTID,
|
|
|
|
chunk_start, chunk_size);
|
2015-06-08 18:54:54 +08:00
|
|
|
allocation->data += chunk_size;
|
2016-08-22 22:57:15 +08:00
|
|
|
if (ret)
|
|
|
|
return ret;
|
2010-12-10 02:31:08 +08:00
|
|
|
}
|
2008-03-25 03:03:18 +08:00
|
|
|
|
2015-07-02 01:19:05 +08:00
|
|
|
err:
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int make_root_dir(struct btrfs_trans_handle *trans, struct btrfs_root *root,
|
2015-10-15 01:39:37 +08:00
|
|
|
struct mkfs_allocation *allocation)
|
2015-07-02 01:19:05 +08:00
|
|
|
{
|
|
|
|
struct btrfs_key location;
|
|
|
|
int ret;
|
|
|
|
|
2008-01-04 23:38:22 +08:00
|
|
|
ret = btrfs_make_root_dir(trans, root->fs_info->tree_root,
|
2007-04-11 20:58:53 +08:00
|
|
|
BTRFS_ROOT_TREE_DIR_OBJECTID);
|
2007-03-21 23:13:29 +08:00
|
|
|
if (ret)
|
2007-04-07 03:39:12 +08:00
|
|
|
goto err;
|
2008-01-04 23:38:22 +08:00
|
|
|
ret = btrfs_make_root_dir(trans, root, BTRFS_FIRST_FREE_OBJECTID);
|
2007-04-07 03:39:12 +08:00
|
|
|
if (ret)
|
|
|
|
goto err;
|
|
|
|
memcpy(&location, &root->fs_info->fs_root->root_key, sizeof(location));
|
|
|
|
location.offset = (u64)-1;
|
|
|
|
ret = btrfs_insert_dir_item(trans, root->fs_info->tree_root,
|
2007-08-30 03:56:44 +08:00
|
|
|
"default", 7,
|
2013-03-07 00:32:51 +08:00
|
|
|
btrfs_super_root_dir(root->fs_info->super_copy),
|
2008-12-18 05:10:07 +08:00
|
|
|
&location, BTRFS_FT_DIR, 0);
|
2007-04-07 03:39:12 +08:00
|
|
|
if (ret)
|
|
|
|
goto err;
|
2007-12-13 03:39:46 +08:00
|
|
|
|
|
|
|
ret = btrfs_insert_inode_ref(trans, root->fs_info->tree_root,
|
|
|
|
"default", 7, location.objectid,
|
2008-07-25 00:13:32 +08:00
|
|
|
BTRFS_ROOT_TREE_DIR_OBJECTID, 0);
|
2007-12-13 03:39:46 +08:00
|
|
|
if (ret)
|
|
|
|
goto err;
|
|
|
|
|
2007-04-07 03:39:12 +08:00
|
|
|
err:
|
2007-03-21 23:13:29 +08:00
|
|
|
return ret;
|
|
|
|
}
|
2007-03-21 08:35:03 +08:00
|
|
|
|
2016-08-22 23:55:16 +08:00
|
|
|
static int __recow_root(struct btrfs_trans_handle *trans,
|
2013-07-03 21:25:09 +08:00
|
|
|
struct btrfs_root *root)
|
2008-04-05 03:42:17 +08:00
|
|
|
{
|
|
|
|
struct extent_buffer *tmp;
|
2016-08-22 23:55:16 +08:00
|
|
|
int ret;
|
2008-04-05 03:42:17 +08:00
|
|
|
|
2013-07-03 21:25:09 +08:00
|
|
|
if (trans->transid != btrfs_root_generation(&root->root_item)) {
|
2013-11-28 00:08:24 +08:00
|
|
|
extent_buffer_get(root->node);
|
2013-07-03 21:25:09 +08:00
|
|
|
ret = __btrfs_cow_block(trans, root, root->node,
|
|
|
|
NULL, 0, &tmp, 0, 0);
|
2016-08-22 23:55:16 +08:00
|
|
|
if (ret)
|
|
|
|
return ret;
|
2013-07-03 21:25:09 +08:00
|
|
|
free_extent_buffer(tmp);
|
|
|
|
}
|
2016-08-22 23:55:16 +08:00
|
|
|
|
|
|
|
return 0;
|
2013-07-03 21:25:09 +08:00
|
|
|
}
|
2008-04-05 03:42:17 +08:00
|
|
|
|
2016-08-22 23:55:16 +08:00
|
|
|
static int recow_roots(struct btrfs_trans_handle *trans,
|
2013-07-03 21:25:09 +08:00
|
|
|
struct btrfs_root *root)
|
|
|
|
{
|
|
|
|
struct btrfs_fs_info *info = root->fs_info;
|
2016-08-22 23:55:16 +08:00
|
|
|
int ret;
|
2009-05-30 04:35:30 +08:00
|
|
|
|
2016-08-22 23:55:16 +08:00
|
|
|
ret = __recow_root(trans, info->fs_root);
|
|
|
|
if (ret)
|
|
|
|
return ret;
|
|
|
|
ret = __recow_root(trans, info->tree_root);
|
|
|
|
if (ret)
|
|
|
|
return ret;
|
|
|
|
ret = __recow_root(trans, info->extent_root);
|
|
|
|
if (ret)
|
|
|
|
return ret;
|
|
|
|
ret = __recow_root(trans, info->chunk_root);
|
|
|
|
if (ret)
|
|
|
|
return ret;
|
|
|
|
ret = __recow_root(trans, info->dev_root);
|
|
|
|
if (ret)
|
|
|
|
return ret;
|
|
|
|
ret = __recow_root(trans, info->csum_root);
|
|
|
|
if (ret)
|
|
|
|
return ret;
|
|
|
|
|
|
|
|
return 0;
|
2008-04-05 03:42:17 +08:00
|
|
|
}
|
|
|
|
|
2008-04-04 04:35:48 +08:00
|
|
|
static int create_one_raid_group(struct btrfs_trans_handle *trans,
|
2015-06-08 18:54:54 +08:00
|
|
|
struct btrfs_root *root, u64 type,
|
|
|
|
struct mkfs_allocation *allocation)
|
|
|
|
|
2008-04-04 04:35:48 +08:00
|
|
|
{
|
|
|
|
u64 chunk_start;
|
|
|
|
u64 chunk_size;
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
ret = btrfs_alloc_chunk(trans, root->fs_info->extent_root,
|
|
|
|
&chunk_start, &chunk_size, type);
|
2013-09-05 14:55:08 +08:00
|
|
|
if (ret == -ENOSPC) {
|
2016-08-19 00:38:34 +08:00
|
|
|
error("not enough free space to allocate chunk");
|
2013-09-05 14:55:08 +08:00
|
|
|
exit(1);
|
|
|
|
}
|
2016-08-22 22:57:15 +08:00
|
|
|
if (ret)
|
|
|
|
return ret;
|
|
|
|
|
2008-04-04 04:35:48 +08:00
|
|
|
ret = btrfs_make_block_group(trans, root->fs_info->extent_root, 0,
|
2008-04-16 03:42:08 +08:00
|
|
|
type, BTRFS_FIRST_CHUNK_TREE_OBJECTID,
|
2008-04-04 04:35:48 +08:00
|
|
|
chunk_start, chunk_size);
|
2016-08-22 22:57:15 +08:00
|
|
|
|
|
|
|
type &= BTRFS_BLOCK_GROUP_TYPE_MASK;
|
|
|
|
if (type == BTRFS_BLOCK_GROUP_DATA) {
|
2015-06-08 18:54:54 +08:00
|
|
|
allocation->data += chunk_size;
|
2016-08-22 22:57:15 +08:00
|
|
|
} else if (type == BTRFS_BLOCK_GROUP_METADATA) {
|
2015-06-08 18:54:54 +08:00
|
|
|
allocation->metadata += chunk_size;
|
2016-08-22 22:57:15 +08:00
|
|
|
} else if (type == BTRFS_BLOCK_GROUP_SYSTEM) {
|
2015-06-08 18:54:54 +08:00
|
|
|
allocation->system += chunk_size;
|
2016-08-22 22:57:15 +08:00
|
|
|
} else if (type ==
|
|
|
|
(BTRFS_BLOCK_GROUP_METADATA | BTRFS_BLOCK_GROUP_DATA)) {
|
2015-06-08 18:54:54 +08:00
|
|
|
allocation->mixed += chunk_size;
|
2016-08-22 22:57:15 +08:00
|
|
|
} else {
|
|
|
|
error("unrecognized profile type: 0x%llx",
|
|
|
|
(unsigned long long)type);
|
|
|
|
ret = -EINVAL;
|
|
|
|
}
|
2015-06-08 18:54:54 +08:00
|
|
|
|
2008-04-04 04:35:48 +08:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int create_raid_groups(struct btrfs_trans_handle *trans,
|
|
|
|
struct btrfs_root *root, u64 data_profile,
|
2015-07-03 01:23:27 +08:00
|
|
|
u64 metadata_profile, int mixed,
|
2015-06-08 18:54:54 +08:00
|
|
|
struct mkfs_allocation *allocation)
|
2008-04-04 04:35:48 +08:00
|
|
|
{
|
|
|
|
int ret;
|
|
|
|
|
2013-08-07 20:11:25 +08:00
|
|
|
if (metadata_profile) {
|
2010-12-10 02:31:08 +08:00
|
|
|
u64 meta_flags = BTRFS_BLOCK_GROUP_METADATA;
|
|
|
|
|
2008-04-05 03:42:17 +08:00
|
|
|
ret = create_one_raid_group(trans, root,
|
|
|
|
BTRFS_BLOCK_GROUP_SYSTEM |
|
2015-06-08 18:54:54 +08:00
|
|
|
metadata_profile, allocation);
|
2016-08-22 22:57:15 +08:00
|
|
|
if (ret)
|
|
|
|
return ret;
|
2008-04-05 03:42:17 +08:00
|
|
|
|
2010-12-10 02:31:08 +08:00
|
|
|
if (mixed)
|
|
|
|
meta_flags |= BTRFS_BLOCK_GROUP_DATA;
|
|
|
|
|
|
|
|
ret = create_one_raid_group(trans, root, meta_flags |
|
2015-06-08 18:54:54 +08:00
|
|
|
metadata_profile, allocation);
|
2016-08-22 22:57:15 +08:00
|
|
|
if (ret)
|
|
|
|
return ret;
|
2008-04-05 03:42:17 +08:00
|
|
|
|
2008-04-04 04:35:48 +08:00
|
|
|
}
|
btrfs-progs: mkfs: allow --data DUP for single device
Current code don't support DUP profile on single device, except it
is in mixed mode, because of following reasons:
1: Some SSD do deduplication internally, so the duplication on
the filesystem side has no effect.
2: On a physical device, if the entire disk broken, --data DUP does not
help.
3: Half performance compared to single profile.
4: We have a workaround: create multi-partition on a single device,
and btffs will treat them as multi device.
Instead of refusing --data DUP, we give the user a choice and print
a wrning.
Test:
1: Tested by xfstests
Run with modified xfstests, I add test items of -d dup in single
device into btrfs/* and common/rc, run tests of btrfs/*,
with all mount option, no regression diffed with v4.3.
2: Tested by btrfs-progs
Checked following commands in "-m dup -d dup" fs with memleck
checking, all passed:
mkfs.btrfs -f --data dup --metadata dup /dev/sda6
btrfs filesystem show /dev/sda6
btrfs filesystem label /dev/sda6 btrfs_label_test
btrfs filesystem label /dev/sda6
btrfs device scan --all-devices
btrfs device scan /dev/sda6
btrfs device scan /dev/sda6
btrfs device ready /dev/sda6
btrfs check /dev/sda6
btrfs check -s 1 /dev/sda6
btrfs check --repair /dev/sda6
btrfs check --init-csum-tree /dev/sda6
btrfs check --init-extent-tree /dev/sda6
btrfs check --check-data-csum /dev/sda6
btrfs check --qgroup-report /dev/sda6
btrfs rescue super-recover -y /dev/sda6
btrfs rescue zero-log /dev/sda6
btrfs restore -l /dev/sda6
btrfs restore /dev/sda6 /
btrfs restore -s /dev/sda6 /
btrfs restore -x /dev/sda6 /
btrfs restore -m /dev/sda6 /
btrfs restore -S /dev/sda6 /
btrfs restore -v /dev/sda6 /
btrfs restore -i /dev/sda6 /
btrfs restore -o /dev/sda6 /
btrfs restore -u0 /dev/sda6 /
btrfs restore -u1 /dev/sda6 /
btrfs restore -D /dev/sda6 /
btrfs property list /dev/sda6
btrfs property get /dev/sda6 label
btrfs property set /dev/sda6 label test
btrfs property set /dev/sda6 label btrfs_label_test
btrfs help
btrfs help --full
btrfs version
btrfsck /dev/sda6
btrfs-find-root /dev/sda6
btrfs-find-root -a /dev/sda6
btrfs-map-logical -l1 /dev/sda6
btrfs-map-logical -l1 -c1 /dev/sda6
btrfs-map-logical -l1 -o /tmp/btrfs-map-logic-out /dev/sda6
btrfs-map-logical -l1 -b1 /dev/sda6
btrfs-select-super -s 0 /dev/sda6
btrfs-select-super -s 1 /dev/sda6
btrfstune -S 1 /dev/sda6
btrfstune -f -S 0 /dev/sda6
btrfstune -r /dev/sda6
btrfstune -x /dev/sda6
btrfstune -n /dev/sda6
btrfstune -f -U 00000000-0000-0000-0000-000000000000 /dev/sda6
btrfstune -f -u /dev/sda6
btrfs-calc-size /dev/sda6
btrfs-calc-size -v /dev/sda6
btrfs-calc-size -b /dev/sda6
btrfs-debug-tree /dev/sda6
btrfs-debug-tree -e /dev/sda6
btrfs-debug-tree -d /dev/sda6
btrfs-debug-tree -r /dev/sda6
btrfs-debug-tree -R /dev/sda6
btrfs-debug-tree -u /dev/sda6
btrfs-debug-tree -b 0 /dev/sda6
btrfs-debug-tree -t 0 /dev/sda6
btrfs-debug-tree -t 2 /dev/sda6
btrfs-show-super /dev/sda6
btrfs-show-super -i 0 /dev/sda6
btrfs-show-super -i 1 /dev/sda6
btrfs-show-super -i 2 /dev/sda6
btrfs-show-super -a /dev/sda6
btrfs-show-super -f /dev/sda6
btrfs-show-super -F /dev/sda6
btrfs subvolume list /mnt/btrfs-progs-tests
btrfs subvolume create /mnt/btrfs-progs-tests/mysubvol
btrfs subvolume list /mnt/btrfs-progs-tests
btrfs subvolume get-default /mnt/btrfs-progs-tests
btrfs subvolume set-default 258 /mnt/btrfs-progs-tests
btrfs subvolume get-default /mnt/btrfs-progs-tests
btrfs subvolume set-default /mnt/btrfs-progs-tests
btrfs subvolume snapshot /mnt/btrfs-progs-tests/mysubvol /mnt/btrfs-progs-tests/mysubvol_snap
btrfs subvolume list /mnt/btrfs-progs-tests
btrfs subvolume find-new /mnt/btrfs-progs-tests 0
btrfs subvolume find-new /mnt/btrfs-progs-tests 0
btrfs subvolume find-new /mnt/btrfs-progs-tests/mysubvol 0
btrfs subvolume find-new /mnt/btrfs-progs-tests/mysubvol 0
btrfs subvolume show /mnt/btrfs-progs-tests
btrfs subvolume show /mnt/btrfs-progs-tests/mysubvol
btrfs subvolume show /mnt/btrfs-progs-tests/mysubvol_snap
btrfs subvolume sync /mnt/btrfs-progs-tests
btrfs subvolume delete /mnt/btrfs-progs-tests/mysubvol_snap
btrfs subvolume delete /mnt/btrfs-progs-tests/mysubvol
btrfs subvolume sync /mnt/btrfs-progs-tests
btrfs filesystem df /mnt/btrfs-progs-tests
btrfs filesystem show /mnt/btrfs-progs-tests
btrfs filesystem sync /mnt/btrfs-progs-tests
btrfs filesystem label /mnt/btrfs-progs-tests btrfs_label_test
btrfs filesystem label /mnt/btrfs-progs-tests
btrfs filesystem usage /mnt/btrfs-progs-tests
btrfs filesystem defragment -s 1024 -l 2048 /mnt/btrfs-progs-tests/filesystem_test_dir/test_dir_0/test_file_0
btrfs filesystem defragment /mnt/btrfs-progs-tests/filesystem_test_dir/test_dir_0/test_file_1
btrfs filesystem defragment -f /mnt/btrfs-progs-tests/filesystem_test_dir/test_dir_0/test_file_2
btrfs filesystem defragment -czlib /mnt/btrfs-progs-tests/filesystem_test_dir/test_dir_0/test_file_3
btrfs filesystem defragment -clzo /mnt/btrfs-progs-tests/filesystem_test_dir/test_dir_0/test_file_4
btrfs filesystem defragment /mnt/btrfs-progs-tests/filesystem_test_dir
btrfs filesystem defragment -r /mnt/btrfs-progs-tests/filesystem_test_dir
btrfs filesystem defragment /mnt/btrfs-progs-tests
btrfs filesystem resize 1:-10M /mnt/btrfs-progs-tests
btrfs filesystem resize 1:max /mnt/btrfs-progs-tests
btrfs balance start /mnt/btrfs-progs-tests
btrfs balance start -v /mnt/btrfs-progs-tests
btrfs balance start -f /mnt/btrfs-progs-tests
btrfs balance status -v /mnt/btrfs-progs-tests
btrfs balance pause /mnt/btrfs-progs-tests
btrfs balance status /mnt/btrfs-progs-tests
btrfs balance resume /mnt/btrfs-progs-tests
btrfs balance status -v /mnt/btrfs-progs-tests
btrfs balance cancel /mnt/btrfs-progs-tests
btrfs balance start -dprofiles=single /mnt/btrfs-progs-tests
btrfs balance start -dconvert=single /mnt/btrfs-progs-tests
btrfs balance start -ddevid=1 /mnt/btrfs-progs-tests
btrfs balance start -f -mprofiles=single /mnt/btrfs-progs-tests
btrfs balance start -f -mconvert=single /mnt/btrfs-progs-tests
btrfs balance start -f -mdevid=1 /mnt/btrfs-progs-tests
btrfs balance start -f -sprofiles=single /mnt/btrfs-progs-tests
btrfs balance start -f -sconvert=single /mnt/btrfs-progs-tests
btrfs balance start -f -sdevid=1 /mnt/btrfs-progs-tests
btrfs device add -f /dev/sda10 /mnt/btrfs-progs-tests
btrfs device del /dev/sda10 /mnt/btrfs-progs-tests
btrfs device stats /dev/sda6
btrfs device stats -z /dev/sda6
btrfs device stats /mnt/btrfs-progs-tests
btrfs device stats -z /mnt/btrfs-progs-tests
btrfs device usage /mnt/btrfs-progs-tests
btrfs scrub status /mnt/btrfs-progs-tests
btrfs scrub start -B /mnt/btrfs-progs-tests
btrfs scrub start -B -d /mnt/btrfs-progs-tests
btrfs scrub start -B -r /mnt/btrfs-progs-tests
btrfs scrub status /mnt/btrfs-progs-tests
btrfs scrub start /mnt/btrfs-progs-tests
btrfs scrub status /mnt/btrfs-progs-tests
btrfs scrub status /mnt/btrfs-progs-tests
btrfs scrub status -d /mnt/btrfs-progs-tests
btrfs scrub status -R /mnt/btrfs-progs-tests
btrfs scrub status /mnt/btrfs-progs-tests
btrfs scrub start /dev/sda6
btrfs scrub status /dev/sda6
btrfs scrub status /dev/sda6
btrfs scrub status -d /dev/sda6
btrfs scrub status -R /dev/sda6
btrfs scrub status /dev/sda6
btrfs subvolume snapshot -r /mnt/btrfs-progs-tests /mnt/btrfs-progs-tests/snap1
btrfs send -f /tmp/btrfs_snapshot_test /mnt/btrfs-progs-tests/snap1
btrfs send -e -f /tmp/btrfs_snapshot_test /mnt/btrfs-progs-tests/snap1
btrfs send --no-data -f /tmp/btrfs_snapshot_test /mnt/btrfs-progs-tests/snap1
btrfs quota enable /mnt/btrfs-progs-tests
btrfs quota rescan /mnt/btrfs-progs-tests
btrfs quota rescan -s /mnt/btrfs-progs-tests
btrfs quota rescan -w /mnt/btrfs-progs-tests
btrfs quota disable /mnt/btrfs-progs-tests
btrfs quota enable /mnt/btrfs-progs-tests
btrfs qgroup create 1/5 /mnt/btrfs-progs-tests
btrfs qgroup create 2/5 /mnt/btrfs-progs-tests
btrfs qgroup assign 1/5 2/5 /mnt/btrfs-progs-tests
btrfs qgroup limit 1G 1/5 /mnt/btrfs-progs-tests
btrfs qgroup show /mnt/btrfs-progs-tests
btrfs qgroup show -p -c -r -e -F -f /mnt/btrfs-progs-tests
btrfs qgroup remove 1/5 2/5 /mnt/btrfs-progs-tests
btrfs qgroup destroy 2/5 /mnt/btrfs-progs-tests
btrfs qgroup destroy 1/5 /mnt/btrfs-progs-tests
btrfs quota disable /mnt/btrfs-progs-tests
btrfs replace start -f -B /dev/sda6 /dev/sda10 /mnt/btrfs-progs-tests
btrfs replace status /mnt/btrfs-progs-tests
btrfs replace start -f -B /dev/sda10 /dev/sda6 /mnt/btrfs-progs-tests
btrfs-convert /dev/sda6
btrfs-convert -r /dev/sda6
btrfs-convert -d /dev/sda6
btrfs-convert -i /dev/sda6
btrfs-convert -n /dev/sda6
btrfs-convert -N 4096 /dev/sda6
btrfs-convert -l test /dev/sda6
btrfs-convert -L /dev/sda6
btrfs-convert --no-progress /dev/sda6
mkfs.btrfs -f /dev/sda6
btrfs-image /dev/sda6 /tmp/btrfs_image.img
btrfs-image -r /tmp/btrfs_image.img /dev/sda6
mkfs.btrfs -f /dev/sda6
btrfs-image -c 0 /dev/sda6 /tmp/btrfs_image.img
btrfs-image -r /tmp/btrfs_image.img /dev/sda6
mkfs.btrfs -f /dev/sda6
btrfs-image -c 9 /dev/sda6 /tmp/btrfs_image.img
btrfs-image -r /tmp/btrfs_image.img /dev/sda6
mkfs.btrfs -f /dev/sda6
btrfs-image -t 0 /dev/sda6 /tmp/btrfs_image.img
btrfs-image -r /tmp/btrfs_image.img /dev/sda6
mkfs.btrfs -f /dev/sda6
btrfs-image -t 1 /dev/sda6 /tmp/btrfs_image.img
btrfs-image -r /tmp/btrfs_image.img /dev/sda6
mkfs.btrfs -f /dev/sda6
btrfs-image -t 32 /dev/sda6 /tmp/btrfs_image.img
btrfs-image -r /tmp/btrfs_image.img /dev/sda6
mkfs.btrfs -f /dev/sda6
btrfs-image -w /dev/sda6 /tmp/btrfs_image.img
btrfs-image -r /tmp/btrfs_image.img /dev/sda6
mkfs.btrfs -f /dev/sda6
btrfs-image -w /dev/sda6 /tmp/btrfs_image.img
btrfs-image -r /tmp/btrfs_image.img /dev/sda6
btrfs-image -r -t 0 /tmp/btrfs_image.img /dev/sda6
btrfs-image -r -t 1 /tmp/btrfs_image.img /dev/sda6
btrfs-image -r -t 32 /tmp/btrfs_image.img /dev/sda6
btrfs-image -r -o /tmp/btrfs_image.img /dev/sda6
3: Manual check relation source by:
grep DUP *.c
Confirmed that all source are modified.
4: Use this raid type manually, do some operations in fs,
no error found in command and dmesg.
5: Combination of dup conversion with fsck
Confirmed OK with relative kernel patch titled:
[PATCH] btrfs: Support convert to -d dup for btrfs-convert
export TEST_DEV='/dev/vdc'
export TEST_DIR='/var/ltf/tester/mnt'
do_dup_test()
{
local m_from="$1"
local d_from="$2"
local m_to="$3"
local d_to="$4"
echo "Convert from -m $m_from -d $d_from to -m $m_to -d $d_to"
umount "$TEST_DIR" &>/dev/null
./mkfs.btrfs -f -m "$m_from" -d "$d_from" "$TEST_DEV" >/dev/null || return 1
mount "$TEST_DEV" "$TEST_DIR" || return 1
cp -a /sbin/* "$TEST_DIR"
[[ "$m_from" != "$m_to" ]] && {
./btrfs balance start -f -mconvert="$m_to" "$TEST_DIR" || return 1
}
[[ "$d_from" != "$d_to" ]] && {
local opt=()
[[ "$d_to" == single ]] && opt+=("-f")
./btrfs balance start "${opt[@]}" -dconvert="$d_to" "$TEST_DIR" || return 1
}
umount "$TEST_DIR" || return 1
./btrfsck "$TEST_DEV" || return 1
echo
return 0
}
test_all()
{
for m_from in single dup; do
for d_from in single dup; do
for m_to in single dup; do
for d_to in single dup; do
do_dup_test "$m_from" "$d_from" "$m_to" "$d_to" || return 1
done
done
done
done
}
test_all
Signed-off-by: Zhao Lei <zhaolei@cn.fujitsu.com>
Tested-by: Austin S. Hemmelgarn <ahferroin7@gmail.com>
[ minor updates in the changelog ]
Signed-off-by: David Sterba <dsterba@suse.com>
2015-11-19 17:36:24 +08:00
|
|
|
if (!mixed && data_profile) {
|
2008-04-04 04:35:48 +08:00
|
|
|
ret = create_one_raid_group(trans, root,
|
|
|
|
BTRFS_BLOCK_GROUP_DATA |
|
2015-06-08 18:54:54 +08:00
|
|
|
data_profile, allocation);
|
2016-08-22 22:57:15 +08:00
|
|
|
if (ret)
|
|
|
|
return ret;
|
2008-04-04 04:35:48 +08:00
|
|
|
}
|
2016-08-22 23:55:16 +08:00
|
|
|
ret = recow_roots(trans, root);
|
2013-07-03 21:25:09 +08:00
|
|
|
|
2016-08-22 23:55:16 +08:00
|
|
|
return ret;
|
2008-04-04 04:35:48 +08:00
|
|
|
}
|
|
|
|
|
2008-09-26 22:26:53 +08:00
|
|
|
static int create_data_reloc_tree(struct btrfs_trans_handle *trans,
|
|
|
|
struct btrfs_root *root)
|
|
|
|
{
|
|
|
|
struct btrfs_key location;
|
|
|
|
struct btrfs_root_item root_item;
|
|
|
|
struct extent_buffer *tmp;
|
|
|
|
u64 objectid = BTRFS_DATA_RELOC_TREE_OBJECTID;
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
ret = btrfs_copy_root(trans, root, root->node, &tmp, objectid);
|
2016-08-22 22:57:15 +08:00
|
|
|
if (ret)
|
|
|
|
return ret;
|
2008-09-26 22:26:53 +08:00
|
|
|
|
|
|
|
memcpy(&root_item, &root->root_item, sizeof(root_item));
|
|
|
|
btrfs_set_root_bytenr(&root_item, tmp->start);
|
|
|
|
btrfs_set_root_level(&root_item, btrfs_header_level(tmp));
|
2008-10-30 02:07:47 +08:00
|
|
|
btrfs_set_root_generation(&root_item, trans->transid);
|
2008-09-26 22:26:53 +08:00
|
|
|
free_extent_buffer(tmp);
|
|
|
|
|
|
|
|
location.objectid = objectid;
|
|
|
|
location.type = BTRFS_ROOT_ITEM_KEY;
|
2009-05-30 04:35:30 +08:00
|
|
|
location.offset = 0;
|
2008-09-26 22:26:53 +08:00
|
|
|
ret = btrfs_insert_root(trans, root->fs_info->tree_root,
|
|
|
|
&location, &root_item);
|
2016-08-22 22:57:15 +08:00
|
|
|
|
|
|
|
return ret;
|
2008-09-26 22:26:53 +08:00
|
|
|
}
|
|
|
|
|
2015-06-11 06:04:19 +08:00
|
|
|
static void print_usage(int ret)
|
2007-10-16 04:25:14 +08:00
|
|
|
{
|
2016-08-23 00:18:54 +08:00
|
|
|
printf("usage: mkfs.btrfs [options] dev [ dev ... ]\n");
|
|
|
|
printf("options:\n");
|
|
|
|
printf("\t-A|--alloc-start START the offset to start the FS\n");
|
|
|
|
printf("\t-b|--byte-count SIZE total number of bytes in the FS\n");
|
|
|
|
printf("\t-d|--data PROFILE data profile, raid0, raid1, raid5, raid6, raid10, dup or single\n");
|
|
|
|
printf("\t-f|--force force overwrite of existing filesystem\n");
|
|
|
|
printf("\t-l|--leafsize SIZE deprecated, alias for nodesize\n");
|
|
|
|
printf("\t-L|--label LABEL set a label\n");
|
|
|
|
printf("\t-m|--metadata PROFILE metadata profile, values like data profile\n");
|
|
|
|
printf("\t-M|--mixed mix metadata and data together\n");
|
|
|
|
printf("\t-n|--nodesize SIZE size of btree nodes\n");
|
|
|
|
printf("\t-s|--sectorsize SIZE min block allocation (may not mountable by current kernel)\n");
|
|
|
|
printf("\t-r|--rootdir DIR the source directory\n");
|
|
|
|
printf("\t-K|--nodiscard do not perform whole device TRIM\n");
|
|
|
|
printf("\t-O|--features LIST comma separated list of filesystem features, use '-O list-all' to list features\n");
|
|
|
|
printf("\t-U|--uuid UUID specify the filesystem UUID\n");
|
|
|
|
printf("\t-q|--quiet no messages except errors\n");
|
|
|
|
printf("\t-V|--version print the mkfs.btrfs version and exit\n");
|
2015-06-11 06:04:19 +08:00
|
|
|
exit(ret);
|
2007-10-16 04:25:14 +08:00
|
|
|
}
|
2007-03-21 08:35:03 +08:00
|
|
|
|
2013-09-10 06:06:38 +08:00
|
|
|
static void print_version(void) __attribute__((noreturn));
|
2009-06-04 00:00:20 +08:00
|
|
|
static void print_version(void)
|
|
|
|
{
|
2016-08-23 00:18:54 +08:00
|
|
|
printf("mkfs.btrfs, part of %s\n", PACKAGE_STRING);
|
2009-06-04 00:00:20 +08:00
|
|
|
exit(0);
|
|
|
|
}
|
|
|
|
|
2008-04-04 04:35:48 +08:00
|
|
|
static u64 parse_profile(char *s)
|
|
|
|
{
|
2016-03-17 00:41:16 +08:00
|
|
|
if (strcasecmp(s, "raid0") == 0) {
|
2008-04-04 04:35:48 +08:00
|
|
|
return BTRFS_BLOCK_GROUP_RAID0;
|
2015-06-06 07:03:48 +08:00
|
|
|
} else if (strcasecmp(s, "raid1") == 0) {
|
2011-12-13 02:00:25 +08:00
|
|
|
return BTRFS_BLOCK_GROUP_RAID1;
|
2015-06-06 07:03:48 +08:00
|
|
|
} else if (strcasecmp(s, "raid5") == 0) {
|
2009-07-12 01:12:37 +08:00
|
|
|
return BTRFS_BLOCK_GROUP_RAID5;
|
2015-06-06 07:03:48 +08:00
|
|
|
} else if (strcasecmp(s, "raid6") == 0) {
|
2009-07-12 01:12:37 +08:00
|
|
|
return BTRFS_BLOCK_GROUP_RAID6;
|
2015-06-06 07:03:48 +08:00
|
|
|
} else if (strcasecmp(s, "raid10") == 0) {
|
2011-12-13 02:00:25 +08:00
|
|
|
return BTRFS_BLOCK_GROUP_RAID10;
|
2015-06-06 07:03:48 +08:00
|
|
|
} else if (strcasecmp(s, "dup") == 0) {
|
2012-03-14 04:15:07 +08:00
|
|
|
return BTRFS_BLOCK_GROUP_DUP;
|
2015-06-06 07:03:48 +08:00
|
|
|
} else if (strcasecmp(s, "single") == 0) {
|
2008-04-04 04:35:48 +08:00
|
|
|
return 0;
|
|
|
|
} else {
|
2016-08-19 00:38:34 +08:00
|
|
|
error("unknown profile %s", s);
|
2015-07-29 10:28:17 +08:00
|
|
|
exit(1);
|
2008-04-04 04:35:48 +08:00
|
|
|
}
|
2011-12-13 02:00:25 +08:00
|
|
|
/* not reached */
|
2008-04-04 04:35:48 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2008-04-18 22:31:42 +08:00
|
|
|
static char *parse_label(char *input)
|
|
|
|
{
|
|
|
|
int len = strlen(input);
|
|
|
|
|
2011-08-31 12:35:51 +08:00
|
|
|
if (len >= BTRFS_LABEL_SIZE) {
|
2016-08-19 00:38:34 +08:00
|
|
|
error("label %s is too long (max %d)", input,
|
2011-08-31 12:35:51 +08:00
|
|
|
BTRFS_LABEL_SIZE - 1);
|
2008-04-18 22:31:42 +08:00
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
return strdup(input);
|
|
|
|
}
|
|
|
|
|
2010-07-08 17:17:59 +08:00
|
|
|
static int add_directory_items(struct btrfs_trans_handle *trans,
|
|
|
|
struct btrfs_root *root, u64 objectid,
|
|
|
|
ino_t parent_inum, const char *name,
|
|
|
|
struct stat *st, int *dir_index_cnt)
|
|
|
|
{
|
|
|
|
int ret;
|
|
|
|
int name_len;
|
|
|
|
struct btrfs_key location;
|
|
|
|
u8 filetype = 0;
|
|
|
|
|
|
|
|
name_len = strlen(name);
|
|
|
|
|
|
|
|
location.objectid = objectid;
|
|
|
|
location.offset = 0;
|
|
|
|
btrfs_set_key_type(&location, BTRFS_INODE_ITEM_KEY);
|
|
|
|
|
|
|
|
if (S_ISDIR(st->st_mode))
|
|
|
|
filetype = BTRFS_FT_DIR;
|
|
|
|
if (S_ISREG(st->st_mode))
|
|
|
|
filetype = BTRFS_FT_REG_FILE;
|
|
|
|
if (S_ISLNK(st->st_mode))
|
|
|
|
filetype = BTRFS_FT_SYMLINK;
|
|
|
|
|
|
|
|
ret = btrfs_insert_dir_item(trans, root, name, name_len,
|
|
|
|
parent_inum, &location,
|
|
|
|
filetype, index_cnt);
|
2014-03-11 18:29:09 +08:00
|
|
|
if (ret)
|
|
|
|
return ret;
|
|
|
|
ret = btrfs_insert_inode_ref(trans, root, name, name_len,
|
|
|
|
objectid, parent_inum, index_cnt);
|
2010-07-08 17:17:59 +08:00
|
|
|
*dir_index_cnt = index_cnt;
|
|
|
|
index_cnt++;
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int fill_inode_item(struct btrfs_trans_handle *trans,
|
|
|
|
struct btrfs_root *root,
|
|
|
|
struct btrfs_inode_item *dst, struct stat *src)
|
|
|
|
{
|
|
|
|
u64 blocks = 0;
|
|
|
|
u64 sectorsize = root->sectorsize;
|
|
|
|
|
2011-06-04 16:19:21 +08:00
|
|
|
/*
|
|
|
|
* btrfs_inode_item has some reserved fields
|
|
|
|
* and represents on-disk inode entry, so
|
|
|
|
* zero everything to prevent information leak
|
|
|
|
*/
|
|
|
|
memset(dst, 0, sizeof (*dst));
|
|
|
|
|
2010-07-08 17:17:59 +08:00
|
|
|
btrfs_set_stack_inode_generation(dst, trans->transid);
|
|
|
|
btrfs_set_stack_inode_size(dst, src->st_size);
|
|
|
|
btrfs_set_stack_inode_nbytes(dst, 0);
|
|
|
|
btrfs_set_stack_inode_block_group(dst, 0);
|
|
|
|
btrfs_set_stack_inode_nlink(dst, src->st_nlink);
|
|
|
|
btrfs_set_stack_inode_uid(dst, src->st_uid);
|
|
|
|
btrfs_set_stack_inode_gid(dst, src->st_gid);
|
|
|
|
btrfs_set_stack_inode_mode(dst, src->st_mode);
|
|
|
|
btrfs_set_stack_inode_rdev(dst, 0);
|
|
|
|
btrfs_set_stack_inode_flags(dst, 0);
|
|
|
|
btrfs_set_stack_timespec_sec(&dst->atime, src->st_atime);
|
|
|
|
btrfs_set_stack_timespec_nsec(&dst->atime, 0);
|
|
|
|
btrfs_set_stack_timespec_sec(&dst->ctime, src->st_ctime);
|
|
|
|
btrfs_set_stack_timespec_nsec(&dst->ctime, 0);
|
|
|
|
btrfs_set_stack_timespec_sec(&dst->mtime, src->st_mtime);
|
|
|
|
btrfs_set_stack_timespec_nsec(&dst->mtime, 0);
|
|
|
|
btrfs_set_stack_timespec_sec(&dst->otime, 0);
|
|
|
|
btrfs_set_stack_timespec_nsec(&dst->otime, 0);
|
|
|
|
|
|
|
|
if (S_ISDIR(src->st_mode)) {
|
|
|
|
btrfs_set_stack_inode_size(dst, 0);
|
|
|
|
btrfs_set_stack_inode_nlink(dst, 1);
|
|
|
|
}
|
|
|
|
if (S_ISREG(src->st_mode)) {
|
|
|
|
btrfs_set_stack_inode_size(dst, (u64)src->st_size);
|
|
|
|
if (src->st_size <= BTRFS_MAX_INLINE_DATA_SIZE(root))
|
|
|
|
btrfs_set_stack_inode_nbytes(dst, src->st_size);
|
|
|
|
else {
|
|
|
|
blocks = src->st_size / sectorsize;
|
|
|
|
if (src->st_size % sectorsize)
|
|
|
|
blocks += 1;
|
|
|
|
blocks *= sectorsize;
|
|
|
|
btrfs_set_stack_inode_nbytes(dst, blocks);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (S_ISLNK(src->st_mode))
|
|
|
|
btrfs_set_stack_inode_nbytes(dst, src->st_size + 1);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int directory_select(const struct direct *entry)
|
|
|
|
{
|
|
|
|
if ((strncmp(entry->d_name, ".", entry->d_reclen) == 0) ||
|
|
|
|
(strncmp(entry->d_name, "..", entry->d_reclen) == 0))
|
|
|
|
return 0;
|
|
|
|
else
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2011-06-04 16:19:23 +08:00
|
|
|
static void free_namelist(struct direct **files, int count)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
if (count < 0)
|
|
|
|
return;
|
|
|
|
|
|
|
|
for (i = 0; i < count; ++i)
|
|
|
|
free(files[i]);
|
|
|
|
free(files);
|
|
|
|
}
|
|
|
|
|
2010-07-08 17:17:59 +08:00
|
|
|
static u64 calculate_dir_inode_size(char *dirname)
|
|
|
|
{
|
|
|
|
int count, i;
|
|
|
|
struct direct **files, *cur_file;
|
|
|
|
u64 dir_inode_size = 0;
|
|
|
|
|
|
|
|
count = scandir(dirname, &files, directory_select, NULL);
|
|
|
|
|
|
|
|
for (i = 0; i < count; i++) {
|
|
|
|
cur_file = files[i];
|
|
|
|
dir_inode_size += strlen(cur_file->d_name);
|
|
|
|
}
|
|
|
|
|
2011-06-04 16:19:23 +08:00
|
|
|
free_namelist(files, count);
|
|
|
|
|
2010-07-08 17:17:59 +08:00
|
|
|
dir_inode_size *= 2;
|
|
|
|
return dir_inode_size;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int add_inode_items(struct btrfs_trans_handle *trans,
|
|
|
|
struct btrfs_root *root,
|
|
|
|
struct stat *st, char *name,
|
|
|
|
u64 self_objectid, ino_t parent_inum,
|
|
|
|
int dir_index_cnt, struct btrfs_inode_item *inode_ret)
|
|
|
|
{
|
|
|
|
int ret;
|
|
|
|
struct btrfs_key inode_key;
|
|
|
|
struct btrfs_inode_item btrfs_inode;
|
|
|
|
u64 objectid;
|
|
|
|
u64 inode_size = 0;
|
|
|
|
|
|
|
|
fill_inode_item(trans, root, &btrfs_inode, st);
|
|
|
|
objectid = self_objectid;
|
|
|
|
|
|
|
|
if (S_ISDIR(st->st_mode)) {
|
|
|
|
inode_size = calculate_dir_inode_size(name);
|
|
|
|
btrfs_set_stack_inode_size(&btrfs_inode, inode_size);
|
|
|
|
}
|
|
|
|
|
|
|
|
inode_key.objectid = objectid;
|
|
|
|
inode_key.offset = 0;
|
|
|
|
btrfs_set_key_type(&inode_key, BTRFS_INODE_ITEM_KEY);
|
|
|
|
|
|
|
|
ret = btrfs_insert_inode(trans, root, objectid, &btrfs_inode);
|
|
|
|
|
|
|
|
*inode_ret = btrfs_inode;
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int add_xattr_item(struct btrfs_trans_handle *trans,
|
|
|
|
struct btrfs_root *root, u64 objectid,
|
|
|
|
const char *file_name)
|
|
|
|
{
|
|
|
|
int ret;
|
|
|
|
int cur_name_len;
|
|
|
|
char xattr_list[XATTR_LIST_MAX];
|
|
|
|
char *cur_name;
|
|
|
|
char cur_value[XATTR_SIZE_MAX];
|
|
|
|
char delimiter = '\0';
|
|
|
|
char *next_location = xattr_list;
|
|
|
|
|
|
|
|
ret = llistxattr(file_name, xattr_list, XATTR_LIST_MAX);
|
|
|
|
if (ret < 0) {
|
2011-06-21 09:45:59 +08:00
|
|
|
if(errno == ENOTSUP)
|
|
|
|
return 0;
|
2016-08-19 00:38:34 +08:00
|
|
|
error("getting a list of xattr failed for %s: %s", file_name,
|
|
|
|
strerror(errno));
|
2010-07-08 17:17:59 +08:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
if (ret == 0)
|
|
|
|
return ret;
|
|
|
|
|
|
|
|
cur_name = strtok(xattr_list, &delimiter);
|
|
|
|
while (cur_name != NULL) {
|
|
|
|
cur_name_len = strlen(cur_name);
|
|
|
|
next_location += cur_name_len + 1;
|
|
|
|
|
|
|
|
ret = getxattr(file_name, cur_name, cur_value, XATTR_SIZE_MAX);
|
|
|
|
if (ret < 0) {
|
2011-06-21 09:45:59 +08:00
|
|
|
if(errno == ENOTSUP)
|
|
|
|
return 0;
|
2016-08-19 00:38:34 +08:00
|
|
|
error("gettig a xattr value failed for %s attr %s: %s",
|
|
|
|
file_name, cur_name, strerror(errno));
|
2011-06-21 09:45:59 +08:00
|
|
|
return ret;
|
2010-07-08 17:17:59 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
ret = btrfs_insert_xattr_item(trans, root, cur_name,
|
|
|
|
cur_name_len, cur_value,
|
|
|
|
ret, objectid);
|
|
|
|
if (ret) {
|
2016-08-19 00:38:34 +08:00
|
|
|
error("inserting a xattr item failed for %s: %s",
|
|
|
|
file_name, strerror(-ret));
|
2010-07-08 17:17:59 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
cur_name = strtok(next_location, &delimiter);
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int add_symbolic_link(struct btrfs_trans_handle *trans,
|
|
|
|
struct btrfs_root *root,
|
|
|
|
u64 objectid, const char *path_name)
|
|
|
|
{
|
|
|
|
int ret;
|
2016-01-06 21:22:34 +08:00
|
|
|
char buf[PATH_MAX];
|
2010-07-08 17:17:59 +08:00
|
|
|
|
2016-01-06 21:22:34 +08:00
|
|
|
ret = readlink(path_name, buf, sizeof(buf));
|
2010-07-08 17:17:59 +08:00
|
|
|
if (ret <= 0) {
|
2016-08-19 00:38:34 +08:00
|
|
|
error("readlink failed for %s: %s", path_name, strerror(errno));
|
2010-07-08 17:17:59 +08:00
|
|
|
goto fail;
|
|
|
|
}
|
2016-01-06 21:22:34 +08:00
|
|
|
if (ret >= sizeof(buf)) {
|
2016-08-19 00:38:34 +08:00
|
|
|
error("symlink too long for %s", path_name);
|
2010-07-08 17:17:59 +08:00
|
|
|
ret = -1;
|
|
|
|
goto fail;
|
|
|
|
}
|
2011-06-04 16:19:20 +08:00
|
|
|
|
|
|
|
buf[ret] = '\0'; /* readlink does not do it for us */
|
2010-07-08 17:17:59 +08:00
|
|
|
ret = btrfs_insert_inline_extent(trans, root, objectid, 0,
|
|
|
|
buf, ret + 1);
|
|
|
|
fail:
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int add_file_items(struct btrfs_trans_handle *trans,
|
|
|
|
struct btrfs_root *root,
|
|
|
|
struct btrfs_inode_item *btrfs_inode, u64 objectid,
|
|
|
|
ino_t parent_inum, struct stat *st,
|
|
|
|
const char *path_name, int out_fd)
|
|
|
|
{
|
2011-06-27 02:41:18 +08:00
|
|
|
int ret = -1;
|
2010-07-08 17:17:59 +08:00
|
|
|
ssize_t ret_read;
|
|
|
|
u64 bytes_read = 0;
|
|
|
|
struct btrfs_key key;
|
|
|
|
int blocks;
|
|
|
|
u32 sectorsize = root->sectorsize;
|
|
|
|
u64 first_block = 0;
|
2013-10-16 22:36:55 +08:00
|
|
|
u64 file_pos = 0;
|
|
|
|
u64 cur_bytes;
|
|
|
|
u64 total_bytes;
|
|
|
|
struct extent_buffer *eb = NULL;
|
2010-07-08 17:17:59 +08:00
|
|
|
int fd;
|
|
|
|
|
2014-03-11 18:29:08 +08:00
|
|
|
if (st->st_size == 0)
|
|
|
|
return 0;
|
|
|
|
|
2010-07-08 17:17:59 +08:00
|
|
|
fd = open(path_name, O_RDONLY);
|
|
|
|
if (fd == -1) {
|
2016-08-19 00:38:34 +08:00
|
|
|
error("cannot open %s: %s", path_name, strerror(errno));
|
2013-01-22 09:11:28 +08:00
|
|
|
return ret;
|
2010-07-08 17:17:59 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
blocks = st->st_size / sectorsize;
|
|
|
|
if (st->st_size % sectorsize)
|
|
|
|
blocks += 1;
|
|
|
|
|
|
|
|
if (st->st_size <= BTRFS_MAX_INLINE_DATA_SIZE(root)) {
|
2013-10-16 22:36:55 +08:00
|
|
|
char *buffer = malloc(st->st_size);
|
2015-11-07 00:57:41 +08:00
|
|
|
|
|
|
|
if (!buffer) {
|
|
|
|
ret = -ENOMEM;
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
2010-07-08 17:17:59 +08:00
|
|
|
ret_read = pread64(fd, buffer, st->st_size, bytes_read);
|
|
|
|
if (ret_read == -1) {
|
2016-08-19 00:38:34 +08:00
|
|
|
error("cannot read %s at offset %llu length %llu: %s",
|
|
|
|
path_name, (unsigned long long)bytes_read,
|
|
|
|
(unsigned long long)st->st_size,
|
|
|
|
strerror(errno));
|
2013-11-07 07:15:46 +08:00
|
|
|
free(buffer);
|
2010-07-08 17:17:59 +08:00
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = btrfs_insert_inline_extent(trans, root, objectid, 0,
|
|
|
|
buffer, st->st_size);
|
2013-10-16 22:36:55 +08:00
|
|
|
free(buffer);
|
2010-07-08 17:17:59 +08:00
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
2013-10-16 22:36:55 +08:00
|
|
|
/* round up our st_size to the FS blocksize */
|
|
|
|
total_bytes = (u64)blocks * sectorsize;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* do our IO in extent buffers so it can work
|
|
|
|
* against any raid type
|
|
|
|
*/
|
2015-09-30 01:10:36 +08:00
|
|
|
eb = calloc(1, sizeof(*eb) + sectorsize);
|
2013-10-16 22:36:55 +08:00
|
|
|
if (!eb) {
|
|
|
|
ret = -ENOMEM;
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
|
|
|
again:
|
|
|
|
|
|
|
|
/*
|
|
|
|
* keep our extent size at 1MB max, this makes it easier to work inside
|
|
|
|
* the tiny block groups created during mkfs
|
|
|
|
*/
|
|
|
|
cur_bytes = min(total_bytes, 1024ULL * 1024);
|
|
|
|
ret = btrfs_reserve_extent(trans, root, cur_bytes, 0, 0, (u64)-1,
|
|
|
|
&key, 1);
|
2010-07-08 17:17:59 +08:00
|
|
|
if (ret)
|
|
|
|
goto end;
|
|
|
|
|
|
|
|
first_block = key.objectid;
|
|
|
|
bytes_read = 0;
|
|
|
|
|
2013-10-16 22:36:55 +08:00
|
|
|
while (bytes_read < cur_bytes) {
|
|
|
|
|
|
|
|
memset(eb->data, 0, sectorsize);
|
|
|
|
|
|
|
|
ret_read = pread64(fd, eb->data, sectorsize, file_pos + bytes_read);
|
2010-07-08 17:17:59 +08:00
|
|
|
if (ret_read == -1) {
|
2016-08-19 00:38:34 +08:00
|
|
|
error("cannot read %s at offset %llu length %llu: %s",
|
|
|
|
path_name,
|
|
|
|
(unsigned long long)file_pos + bytes_read,
|
|
|
|
(unsigned long long)sectorsize,
|
|
|
|
strerror(errno));
|
2010-07-08 17:17:59 +08:00
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
2013-10-16 22:36:55 +08:00
|
|
|
eb->start = first_block + bytes_read;
|
|
|
|
eb->len = sectorsize;
|
2010-07-08 17:17:59 +08:00
|
|
|
|
2013-10-16 22:36:55 +08:00
|
|
|
/*
|
|
|
|
* we're doing the csum before we record the extent, but
|
|
|
|
* that's ok
|
|
|
|
*/
|
2010-07-08 17:17:59 +08:00
|
|
|
ret = btrfs_csum_file_block(trans, root->fs_info->csum_root,
|
2013-10-16 22:36:55 +08:00
|
|
|
first_block + bytes_read + sectorsize,
|
|
|
|
first_block + bytes_read,
|
|
|
|
eb->data, sectorsize);
|
|
|
|
if (ret)
|
|
|
|
goto end;
|
|
|
|
|
|
|
|
ret = write_and_map_eb(trans, root, eb);
|
2010-07-08 17:17:59 +08:00
|
|
|
if (ret) {
|
2016-08-19 00:38:34 +08:00
|
|
|
error("failed to write %s", path_name);
|
2010-07-08 17:17:59 +08:00
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
2013-10-16 22:36:55 +08:00
|
|
|
bytes_read += sectorsize;
|
|
|
|
}
|
2010-07-08 17:17:59 +08:00
|
|
|
|
2013-10-16 22:36:55 +08:00
|
|
|
if (bytes_read) {
|
|
|
|
ret = btrfs_record_file_extent(trans, root, objectid, btrfs_inode,
|
|
|
|
file_pos, first_block, cur_bytes);
|
2010-07-08 17:17:59 +08:00
|
|
|
if (ret)
|
|
|
|
goto end;
|
2013-10-16 22:36:55 +08:00
|
|
|
|
2010-07-08 17:17:59 +08:00
|
|
|
}
|
|
|
|
|
2013-10-16 22:36:55 +08:00
|
|
|
file_pos += cur_bytes;
|
|
|
|
total_bytes -= cur_bytes;
|
|
|
|
|
|
|
|
if (total_bytes)
|
|
|
|
goto again;
|
|
|
|
|
2010-07-08 17:17:59 +08:00
|
|
|
end:
|
2013-12-12 18:41:07 +08:00
|
|
|
free(eb);
|
2010-07-08 17:17:59 +08:00
|
|
|
close(fd);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static char *make_path(char *dir, char *name)
|
|
|
|
{
|
|
|
|
char *path;
|
|
|
|
|
|
|
|
path = malloc(strlen(dir) + strlen(name) + 2);
|
|
|
|
if (!path)
|
|
|
|
return NULL;
|
|
|
|
strcpy(path, dir);
|
|
|
|
if (dir[strlen(dir) - 1] != '/')
|
|
|
|
strcat(path, "/");
|
|
|
|
strcat(path, name);
|
|
|
|
return path;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int traverse_directory(struct btrfs_trans_handle *trans,
|
|
|
|
struct btrfs_root *root, char *dir_name,
|
|
|
|
struct directory_name_entry *dir_head, int out_fd)
|
|
|
|
{
|
|
|
|
int ret = 0;
|
|
|
|
|
|
|
|
struct btrfs_inode_item cur_inode;
|
|
|
|
struct btrfs_inode_item *inode_item;
|
|
|
|
int count, i, dir_index_cnt;
|
|
|
|
struct direct **files;
|
|
|
|
struct stat st;
|
|
|
|
struct directory_name_entry *dir_entry, *parent_dir_entry;
|
|
|
|
struct direct *cur_file;
|
|
|
|
ino_t parent_inum, cur_inum;
|
|
|
|
ino_t highest_inum = 0;
|
|
|
|
char *parent_dir_name;
|
2014-03-13 13:01:30 +08:00
|
|
|
char real_path[PATH_MAX];
|
2010-07-08 17:17:59 +08:00
|
|
|
struct btrfs_path path;
|
|
|
|
struct extent_buffer *leaf;
|
|
|
|
struct btrfs_key root_dir_key;
|
|
|
|
u64 root_dir_inode_size = 0;
|
|
|
|
|
|
|
|
/* Add list for source directory */
|
|
|
|
dir_entry = malloc(sizeof(struct directory_name_entry));
|
2015-11-07 01:03:24 +08:00
|
|
|
if (!dir_entry)
|
|
|
|
return -ENOMEM;
|
2010-07-08 17:17:59 +08:00
|
|
|
dir_entry->dir_name = dir_name;
|
2014-03-13 13:01:30 +08:00
|
|
|
dir_entry->path = realpath(dir_name, real_path);
|
|
|
|
if (!dir_entry->path) {
|
2016-08-19 00:38:34 +08:00
|
|
|
error("realpath failed for %s: %s", dir_name, strerror(errno));
|
2014-03-13 13:01:30 +08:00
|
|
|
ret = -1;
|
|
|
|
goto fail_no_dir;
|
|
|
|
}
|
2010-07-08 17:17:59 +08:00
|
|
|
|
|
|
|
parent_inum = highest_inum + BTRFS_FIRST_FREE_OBJECTID;
|
|
|
|
dir_entry->inum = parent_inum;
|
|
|
|
list_add_tail(&dir_entry->list, &dir_head->list);
|
|
|
|
|
|
|
|
btrfs_init_path(&path);
|
|
|
|
|
|
|
|
root_dir_key.objectid = btrfs_root_dirid(&root->root_item);
|
|
|
|
root_dir_key.offset = 0;
|
|
|
|
btrfs_set_key_type(&root_dir_key, BTRFS_INODE_ITEM_KEY);
|
|
|
|
ret = btrfs_lookup_inode(trans, root, &path, &root_dir_key, 1);
|
|
|
|
if (ret) {
|
2016-08-19 00:38:34 +08:00
|
|
|
error("failed to lookup root dir: %d", ret);
|
2014-03-13 13:01:30 +08:00
|
|
|
goto fail_no_dir;
|
2010-07-08 17:17:59 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
leaf = path.nodes[0];
|
|
|
|
inode_item = btrfs_item_ptr(leaf, path.slots[0],
|
|
|
|
struct btrfs_inode_item);
|
|
|
|
|
|
|
|
root_dir_inode_size = calculate_dir_inode_size(dir_name);
|
|
|
|
btrfs_set_inode_size(leaf, inode_item, root_dir_inode_size);
|
|
|
|
btrfs_mark_buffer_dirty(leaf);
|
|
|
|
|
2013-08-03 08:52:43 +08:00
|
|
|
btrfs_release_path(&path);
|
2010-07-08 17:17:59 +08:00
|
|
|
|
|
|
|
do {
|
|
|
|
parent_dir_entry = list_entry(dir_head->list.next,
|
|
|
|
struct directory_name_entry,
|
|
|
|
list);
|
|
|
|
list_del(&parent_dir_entry->list);
|
|
|
|
|
|
|
|
parent_inum = parent_dir_entry->inum;
|
|
|
|
parent_dir_name = parent_dir_entry->dir_name;
|
|
|
|
if (chdir(parent_dir_entry->path)) {
|
2016-08-19 00:38:34 +08:00
|
|
|
error("chdir failed for %s: %s",
|
|
|
|
parent_dir_name, strerror(errno));
|
2014-03-13 13:01:30 +08:00
|
|
|
ret = -1;
|
2011-06-27 02:41:18 +08:00
|
|
|
goto fail_no_files;
|
2010-07-08 17:17:59 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
count = scandir(parent_dir_entry->path, &files,
|
|
|
|
directory_select, NULL);
|
2011-06-04 16:19:18 +08:00
|
|
|
if (count == -1)
|
|
|
|
{
|
2016-08-19 00:38:34 +08:00
|
|
|
error("scandir failed for %s: %s",
|
2011-06-04 16:19:18 +08:00
|
|
|
parent_dir_name, strerror (errno));
|
2014-03-13 13:01:30 +08:00
|
|
|
ret = -1;
|
2011-06-04 16:19:18 +08:00
|
|
|
goto fail;
|
|
|
|
}
|
2010-07-08 17:17:59 +08:00
|
|
|
|
|
|
|
for (i = 0; i < count; i++) {
|
|
|
|
cur_file = files[i];
|
|
|
|
|
|
|
|
if (lstat(cur_file->d_name, &st) == -1) {
|
2016-08-19 00:38:34 +08:00
|
|
|
error("lstat failed for %s: %s",
|
|
|
|
cur_file->d_name, strerror(errno));
|
2014-03-13 13:01:30 +08:00
|
|
|
ret = -1;
|
2010-07-08 17:17:59 +08:00
|
|
|
goto fail;
|
|
|
|
}
|
|
|
|
|
2014-03-11 18:29:09 +08:00
|
|
|
cur_inum = st.st_ino;
|
2010-07-08 17:17:59 +08:00
|
|
|
ret = add_directory_items(trans, root,
|
|
|
|
cur_inum, parent_inum,
|
|
|
|
cur_file->d_name,
|
|
|
|
&st, &dir_index_cnt);
|
|
|
|
if (ret) {
|
2016-08-19 00:38:34 +08:00
|
|
|
error("unable to add directory items for %s: %d",
|
|
|
|
cur_file->d_name, ret);
|
2010-07-08 17:17:59 +08:00
|
|
|
goto fail;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = add_inode_items(trans, root, &st,
|
|
|
|
cur_file->d_name, cur_inum,
|
|
|
|
parent_inum, dir_index_cnt,
|
|
|
|
&cur_inode);
|
2014-03-11 18:29:09 +08:00
|
|
|
if (ret == -EEXIST) {
|
2016-08-23 00:10:43 +08:00
|
|
|
if (st.st_nlink <= 1) {
|
|
|
|
error(
|
|
|
|
"item %s already exists but has wrong st_nlink %ld <= 1",
|
|
|
|
cur_file->d_name, st.st_nlink);
|
|
|
|
goto fail;
|
|
|
|
}
|
2014-03-11 18:29:09 +08:00
|
|
|
continue;
|
|
|
|
}
|
2010-07-08 17:17:59 +08:00
|
|
|
if (ret) {
|
2016-08-19 00:38:34 +08:00
|
|
|
error("unable to add inode items for %s: %d",
|
|
|
|
cur_file->d_name, ret);
|
2010-07-08 17:17:59 +08:00
|
|
|
goto fail;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = add_xattr_item(trans, root,
|
|
|
|
cur_inum, cur_file->d_name);
|
|
|
|
if (ret) {
|
2016-08-19 00:38:34 +08:00
|
|
|
error("unable to add xattr items for %s: %d",
|
|
|
|
cur_file->d_name, ret);
|
2011-06-21 09:45:59 +08:00
|
|
|
if(ret != -ENOTSUP)
|
|
|
|
goto fail;
|
2010-07-08 17:17:59 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (S_ISDIR(st.st_mode)) {
|
|
|
|
dir_entry = malloc(sizeof(struct directory_name_entry));
|
2015-11-07 01:03:24 +08:00
|
|
|
if (!dir_entry) {
|
|
|
|
ret = -ENOMEM;
|
|
|
|
goto fail;
|
|
|
|
}
|
2010-07-08 17:17:59 +08:00
|
|
|
dir_entry->dir_name = cur_file->d_name;
|
|
|
|
dir_entry->path = make_path(parent_dir_entry->path,
|
|
|
|
cur_file->d_name);
|
|
|
|
dir_entry->inum = cur_inum;
|
|
|
|
list_add_tail(&dir_entry->list, &dir_head->list);
|
|
|
|
} else if (S_ISREG(st.st_mode)) {
|
|
|
|
ret = add_file_items(trans, root, &cur_inode,
|
|
|
|
cur_inum, parent_inum, &st,
|
|
|
|
cur_file->d_name, out_fd);
|
|
|
|
if (ret) {
|
2016-08-19 00:38:34 +08:00
|
|
|
error("unable to add file items for %s: %d",
|
|
|
|
cur_file->d_name, ret);
|
2010-07-08 17:17:59 +08:00
|
|
|
goto fail;
|
|
|
|
}
|
|
|
|
} else if (S_ISLNK(st.st_mode)) {
|
|
|
|
ret = add_symbolic_link(trans, root,
|
|
|
|
cur_inum, cur_file->d_name);
|
|
|
|
if (ret) {
|
2016-08-19 00:38:34 +08:00
|
|
|
error("unable to add symlink for %s: %d",
|
|
|
|
cur_file->d_name, ret);
|
2010-07-08 17:17:59 +08:00
|
|
|
goto fail;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-06-04 16:19:23 +08:00
|
|
|
free_namelist(files, count);
|
2010-07-08 17:17:59 +08:00
|
|
|
free(parent_dir_entry);
|
|
|
|
|
|
|
|
index_cnt = 2;
|
|
|
|
|
|
|
|
} while (!list_empty(&dir_head->list));
|
|
|
|
|
2014-03-13 13:01:30 +08:00
|
|
|
out:
|
|
|
|
return !!ret;
|
2010-07-08 17:17:59 +08:00
|
|
|
fail:
|
2011-06-04 16:19:23 +08:00
|
|
|
free_namelist(files, count);
|
2011-06-27 02:41:18 +08:00
|
|
|
fail_no_files:
|
2010-07-08 17:17:59 +08:00
|
|
|
free(parent_dir_entry);
|
2014-03-13 13:01:30 +08:00
|
|
|
goto out;
|
|
|
|
fail_no_dir:
|
|
|
|
free(dir_entry);
|
|
|
|
goto out;
|
2010-07-08 17:17:59 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static int open_target(char *output_name)
|
|
|
|
{
|
|
|
|
int output_fd;
|
2015-11-05 21:22:10 +08:00
|
|
|
output_fd = open(output_name, O_CREAT | O_RDWR,
|
2010-07-08 17:17:59 +08:00
|
|
|
S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH);
|
|
|
|
|
|
|
|
return output_fd;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int create_chunks(struct btrfs_trans_handle *trans,
|
|
|
|
struct btrfs_root *root, u64 num_of_meta_chunks,
|
2015-06-08 18:54:54 +08:00
|
|
|
u64 size_of_data,
|
|
|
|
struct mkfs_allocation *allocation)
|
2010-07-08 17:17:59 +08:00
|
|
|
{
|
|
|
|
u64 chunk_start;
|
|
|
|
u64 chunk_size;
|
|
|
|
u64 meta_type = BTRFS_BLOCK_GROUP_METADATA;
|
|
|
|
u64 data_type = BTRFS_BLOCK_GROUP_DATA;
|
2011-06-21 09:45:59 +08:00
|
|
|
u64 minimum_data_chunk_size = 8 * 1024 * 1024;
|
2010-07-08 17:17:59 +08:00
|
|
|
u64 i;
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
for (i = 0; i < num_of_meta_chunks; i++) {
|
|
|
|
ret = btrfs_alloc_chunk(trans, root->fs_info->extent_root,
|
|
|
|
&chunk_start, &chunk_size, meta_type);
|
2016-08-22 22:57:15 +08:00
|
|
|
if (ret)
|
|
|
|
return ret;
|
2010-07-08 17:17:59 +08:00
|
|
|
ret = btrfs_make_block_group(trans, root->fs_info->extent_root, 0,
|
|
|
|
meta_type, BTRFS_FIRST_CHUNK_TREE_OBJECTID,
|
|
|
|
chunk_start, chunk_size);
|
2015-06-08 18:54:54 +08:00
|
|
|
allocation->metadata += chunk_size;
|
2016-08-22 22:57:15 +08:00
|
|
|
if (ret)
|
|
|
|
return ret;
|
2010-07-08 17:17:59 +08:00
|
|
|
set_extent_dirty(&root->fs_info->free_space_cache,
|
|
|
|
chunk_start, chunk_start + chunk_size - 1, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (size_of_data < minimum_data_chunk_size)
|
|
|
|
size_of_data = minimum_data_chunk_size;
|
2013-10-16 22:36:55 +08:00
|
|
|
|
2010-07-08 17:17:59 +08:00
|
|
|
ret = btrfs_alloc_data_chunk(trans, root->fs_info->extent_root,
|
2016-01-29 13:03:22 +08:00
|
|
|
&chunk_start, size_of_data, data_type, 0);
|
2016-08-22 22:57:15 +08:00
|
|
|
if (ret)
|
|
|
|
return ret;
|
2010-07-08 17:17:59 +08:00
|
|
|
ret = btrfs_make_block_group(trans, root->fs_info->extent_root, 0,
|
|
|
|
data_type, BTRFS_FIRST_CHUNK_TREE_OBJECTID,
|
|
|
|
chunk_start, size_of_data);
|
2015-06-08 18:54:54 +08:00
|
|
|
allocation->data += size_of_data;
|
2016-08-22 22:57:15 +08:00
|
|
|
if (ret)
|
|
|
|
return ret;
|
2010-07-08 17:17:59 +08:00
|
|
|
set_extent_dirty(&root->fs_info->free_space_cache,
|
|
|
|
chunk_start, chunk_start + size_of_data - 1, 0);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int make_image(char *source_dir, struct btrfs_root *root, int out_fd)
|
|
|
|
{
|
|
|
|
int ret;
|
|
|
|
struct btrfs_trans_handle *trans;
|
|
|
|
|
|
|
|
struct stat root_st;
|
|
|
|
|
|
|
|
struct directory_name_entry dir_head;
|
|
|
|
|
2013-09-05 10:38:55 +08:00
|
|
|
struct directory_name_entry *dir_entry = NULL;
|
|
|
|
|
2010-07-08 17:17:59 +08:00
|
|
|
ret = lstat(source_dir, &root_st);
|
|
|
|
if (ret) {
|
2016-08-19 00:38:34 +08:00
|
|
|
error("unable to lstat %s: %s", source_dir, strerror(errno));
|
2014-03-13 13:01:31 +08:00
|
|
|
goto out;
|
2010-07-08 17:17:59 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
INIT_LIST_HEAD(&dir_head.list);
|
|
|
|
|
|
|
|
trans = btrfs_start_transaction(root, 1);
|
|
|
|
ret = traverse_directory(trans, root, source_dir, &dir_head, out_fd);
|
|
|
|
if (ret) {
|
2016-08-19 00:38:34 +08:00
|
|
|
error("unable to traverse directory %s: %d", source_dir, ret);
|
2010-07-08 17:17:59 +08:00
|
|
|
goto fail;
|
|
|
|
}
|
2016-08-23 00:18:14 +08:00
|
|
|
ret = btrfs_commit_transaction(trans, root);
|
|
|
|
if (ret) {
|
|
|
|
error("transaction commit failed: %d", ret);
|
|
|
|
goto out;
|
|
|
|
}
|
2010-07-08 17:17:59 +08:00
|
|
|
|
2014-12-18 04:14:05 +08:00
|
|
|
if (verbose)
|
|
|
|
printf("Making image is completed.\n");
|
2010-07-08 17:17:59 +08:00
|
|
|
return 0;
|
|
|
|
fail:
|
2013-09-05 10:38:55 +08:00
|
|
|
while (!list_empty(&dir_head.list)) {
|
|
|
|
dir_entry = list_entry(dir_head.list.next,
|
|
|
|
struct directory_name_entry, list);
|
|
|
|
list_del(&dir_entry->list);
|
|
|
|
free(dir_entry);
|
|
|
|
}
|
2014-03-13 13:01:31 +08:00
|
|
|
out:
|
2010-07-08 17:17:59 +08:00
|
|
|
fprintf(stderr, "Making image is aborted.\n");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2013-01-18 07:23:10 +08:00
|
|
|
/*
|
|
|
|
* This ignores symlinks with unreadable targets and subdirs that can't
|
|
|
|
* be read. It's a best-effort to give a rough estimate of the size of
|
|
|
|
* a subdir. It doesn't guarantee that prepopulating btrfs from this
|
2015-12-15 18:02:00 +08:00
|
|
|
* tree won't still run out of space.
|
2013-01-18 07:23:10 +08:00
|
|
|
*/
|
|
|
|
static u64 global_total_size;
|
2015-12-15 18:02:00 +08:00
|
|
|
static u64 fs_block_size;
|
2013-01-18 07:23:10 +08:00
|
|
|
static int ftw_add_entry_size(const char *fpath, const struct stat *st,
|
|
|
|
int type)
|
|
|
|
{
|
|
|
|
if (type == FTW_F || type == FTW_D)
|
2015-12-15 18:02:00 +08:00
|
|
|
global_total_size += round_up(st->st_size, fs_block_size);
|
2013-01-18 07:23:10 +08:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2010-07-08 17:17:59 +08:00
|
|
|
static u64 size_sourcedir(char *dir_name, u64 sectorsize,
|
|
|
|
u64 *num_of_meta_chunks_ret, u64 *size_of_data_ret)
|
|
|
|
{
|
|
|
|
u64 dir_size = 0;
|
|
|
|
u64 total_size = 0;
|
|
|
|
int ret;
|
|
|
|
u64 default_chunk_size = 8 * 1024 * 1024; /* 8MB */
|
|
|
|
u64 allocated_meta_size = 8 * 1024 * 1024; /* 8MB */
|
|
|
|
u64 allocated_total_size = 20 * 1024 * 1024; /* 20MB */
|
|
|
|
u64 num_of_meta_chunks = 0;
|
2013-10-16 22:36:55 +08:00
|
|
|
u64 num_of_data_chunks = 0;
|
2010-07-08 17:17:59 +08:00
|
|
|
u64 num_of_allocated_meta_chunks =
|
|
|
|
allocated_meta_size / default_chunk_size;
|
|
|
|
|
2013-01-18 07:23:10 +08:00
|
|
|
global_total_size = 0;
|
2015-12-15 18:02:00 +08:00
|
|
|
fs_block_size = sectorsize;
|
2013-01-18 07:23:10 +08:00
|
|
|
ret = ftw(dir_name, ftw_add_entry_size, 10);
|
|
|
|
dir_size = global_total_size;
|
2010-07-08 17:17:59 +08:00
|
|
|
if (ret < 0) {
|
2016-08-19 00:38:34 +08:00
|
|
|
error("ftw subdir walk of %s failed: %s", dir_name,
|
|
|
|
strerror(errno));
|
2013-01-18 07:23:10 +08:00
|
|
|
exit(1);
|
2010-07-08 17:17:59 +08:00
|
|
|
}
|
|
|
|
|
2013-10-16 22:36:55 +08:00
|
|
|
num_of_data_chunks = (dir_size + default_chunk_size - 1) /
|
|
|
|
default_chunk_size;
|
|
|
|
|
2010-07-08 17:17:59 +08:00
|
|
|
num_of_meta_chunks = (dir_size / 2) / default_chunk_size;
|
|
|
|
if (((dir_size / 2) % default_chunk_size) != 0)
|
|
|
|
num_of_meta_chunks++;
|
|
|
|
if (num_of_meta_chunks <= num_of_allocated_meta_chunks)
|
|
|
|
num_of_meta_chunks = 0;
|
|
|
|
else
|
|
|
|
num_of_meta_chunks -= num_of_allocated_meta_chunks;
|
|
|
|
|
2013-10-16 22:36:55 +08:00
|
|
|
total_size = allocated_total_size +
|
|
|
|
(num_of_data_chunks * default_chunk_size) +
|
2010-07-08 17:17:59 +08:00
|
|
|
(num_of_meta_chunks * default_chunk_size);
|
|
|
|
|
|
|
|
*num_of_meta_chunks_ret = num_of_meta_chunks;
|
2013-10-16 22:36:55 +08:00
|
|
|
*size_of_data_ret = num_of_data_chunks * default_chunk_size;
|
2010-07-08 17:17:59 +08:00
|
|
|
return total_size;
|
|
|
|
}
|
|
|
|
|
2015-11-07 01:12:44 +08:00
|
|
|
static int zero_output_file(int out_fd, u64 size)
|
2010-07-08 17:17:59 +08:00
|
|
|
{
|
2015-11-07 01:10:29 +08:00
|
|
|
int loop_num;
|
2010-07-08 17:17:59 +08:00
|
|
|
u64 location = 0;
|
2015-11-07 01:10:29 +08:00
|
|
|
char buf[4096];
|
2010-07-08 17:17:59 +08:00
|
|
|
int ret = 0, i;
|
|
|
|
ssize_t written;
|
|
|
|
|
2015-11-07 01:10:29 +08:00
|
|
|
memset(buf, 0, 4096);
|
|
|
|
loop_num = size / 4096;
|
2010-07-08 17:17:59 +08:00
|
|
|
for (i = 0; i < loop_num; i++) {
|
2015-11-07 01:10:29 +08:00
|
|
|
written = pwrite64(out_fd, buf, 4096, location);
|
|
|
|
if (written != 4096)
|
2010-07-08 17:17:59 +08:00
|
|
|
ret = -EIO;
|
2015-11-07 01:10:29 +08:00
|
|
|
location += 4096;
|
2010-07-08 17:17:59 +08:00
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2013-01-20 02:06:21 +08:00
|
|
|
static int is_ssd(const char *file)
|
|
|
|
{
|
|
|
|
blkid_probe probe;
|
2015-11-08 23:33:03 +08:00
|
|
|
char wholedisk[PATH_MAX];
|
2013-04-11 23:44:18 +08:00
|
|
|
char sysfs_path[PATH_MAX];
|
|
|
|
dev_t devno;
|
2013-01-20 02:06:21 +08:00
|
|
|
int fd;
|
|
|
|
char rotational;
|
2013-09-04 19:43:20 +08:00
|
|
|
int ret;
|
2013-01-20 02:06:21 +08:00
|
|
|
|
|
|
|
probe = blkid_new_probe_from_filename(file);
|
|
|
|
if (!probe)
|
|
|
|
return 0;
|
|
|
|
|
2013-04-11 23:39:30 +08:00
|
|
|
/* Device number of this disk (possibly a partition) */
|
2013-04-11 23:44:18 +08:00
|
|
|
devno = blkid_probe_get_devno(probe);
|
2013-09-05 10:38:55 +08:00
|
|
|
if (!devno) {
|
|
|
|
blkid_free_probe(probe);
|
2013-01-20 02:06:21 +08:00
|
|
|
return 0;
|
2013-09-05 10:38:55 +08:00
|
|
|
}
|
2013-01-20 02:06:21 +08:00
|
|
|
|
2013-04-11 23:39:30 +08:00
|
|
|
/* Get whole disk name (not full path) for this devno */
|
2013-09-04 19:43:20 +08:00
|
|
|
ret = blkid_devno_to_wholedisk(devno,
|
|
|
|
wholedisk, sizeof(wholedisk), NULL);
|
|
|
|
if (ret) {
|
|
|
|
blkid_free_probe(probe);
|
|
|
|
return 0;
|
|
|
|
}
|
2013-01-20 02:06:21 +08:00
|
|
|
|
2013-04-11 23:44:18 +08:00
|
|
|
snprintf(sysfs_path, PATH_MAX, "/sys/block/%s/queue/rotational",
|
|
|
|
wholedisk);
|
2013-01-20 02:06:21 +08:00
|
|
|
|
|
|
|
blkid_free_probe(probe);
|
|
|
|
|
2013-04-11 23:44:18 +08:00
|
|
|
fd = open(sysfs_path, O_RDONLY);
|
2013-01-20 02:06:21 +08:00
|
|
|
if (fd < 0) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (read(fd, &rotational, sizeof(char)) < sizeof(char)) {
|
|
|
|
close(fd);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
close(fd);
|
|
|
|
|
|
|
|
return !atoi((const char *)&rotational);
|
|
|
|
}
|
|
|
|
|
2015-11-03 19:03:00 +08:00
|
|
|
static int _cmp_device_by_id(void *priv, struct list_head *a,
|
|
|
|
struct list_head *b)
|
|
|
|
{
|
|
|
|
return list_entry(a, struct btrfs_device, dev_list)->devid -
|
|
|
|
list_entry(b, struct btrfs_device, dev_list)->devid;
|
|
|
|
}
|
|
|
|
|
btrfs-progs: mkfs: print the summary
This patch prints the summary of the filesystem after the creation.
The main fileds printed are:
- devices list with their uuid, devid, path and size
- raid profile (dup,single,raid0...)
- leafsize/nodesize/sectorsize
- filesystem features (raid56, extref, mixed-bg)
- chunk size and type
If the '-v' switched is passed, the output is more verbose; if the '-q'
switched is passed, only the errors are printed.
Below an example:
BTRFS filesystem summary:
Label: btrfs-test
UUID: 14ae8a88-98ac-4f22-8441-79f76ec622f7
Node size: 4096
Leaf size: 4096
Sector size: 4096
Initial chunks:
Data+Metadata: 9.01GiB
System: 18.06MiB
Metadata profile: RAID5
Data profile: RAID5
Mixed mode: YES
SSD detected: NO
Incompat features: mixed-bg, extref, raid56
Number of devices: 10
UUID ID SIZE PATH
------------------------------------ -- --------- -----------
df1c7f50-1980-4da2-8bc9-7ee6ffb0b554 1 50.00GiB /dev/vdb
32c808a0-cd7b-4497-a2c0-1d77a9854af9 2 50.00GiB /dev/vdc
3159782e-d108-40bc-9e15-090ecac160b4 3 50.00GiB /dev/vdd
db7eaf0c-beb8-4093-a9d0-b9c25c146305 4 50.00GiB /dev/vde
c367ca04-1f71-49c0-a331-11fc0b87e9fc 5 50.00GiB /dev/vdf
e9b73c86-4058-4b3a-90ac-18741a276e70 6 50.00GiB /dev/vdg
c4298b7a-ad41-4690-bf10-bf748b319413 7 50.00GiB /dev/vdh
1cf048c8-af8a-4225-b09a-5d12e9b217fa 8 2.00GiB /dev/vdi
7e157869-768a-4725-bad5-82e6bd05fd17 9 2.00GiB /dev/vdj
2c9431ac-c7f0-45a5-8529-cef8cf6e4033 10 2.00GiB /dev/vdk
Total devices size: 356.01GiB
Signed-off-by: Goffredo Baroncelli <kreijack@inwind.it>
Signed-off-by: David Sterba <dsterba@suse.cz>
2015-06-08 19:00:50 +08:00
|
|
|
static void list_all_devices(struct btrfs_root *root)
|
|
|
|
{
|
|
|
|
struct btrfs_fs_devices *fs_devices;
|
|
|
|
struct btrfs_device *device;
|
|
|
|
int number_of_devices = 0;
|
|
|
|
u64 total_block_count = 0;
|
|
|
|
|
|
|
|
fs_devices = root->fs_info->fs_devices;
|
|
|
|
|
|
|
|
list_for_each_entry(device, &fs_devices->devices, dev_list)
|
|
|
|
number_of_devices++;
|
|
|
|
|
2015-11-03 19:03:00 +08:00
|
|
|
list_sort(NULL, &fs_devices->devices, _cmp_device_by_id);
|
|
|
|
|
2015-06-08 22:26:54 +08:00
|
|
|
printf("Number of devices: %d\n", number_of_devices);
|
|
|
|
/* printf("Total devices size: %10s\n", */
|
|
|
|
/* pretty_size(total_block_count)); */
|
|
|
|
printf("Devices:\n");
|
|
|
|
printf(" ID SIZE PATH\n");
|
2015-11-03 19:03:00 +08:00
|
|
|
list_for_each_entry(device, &fs_devices->devices, dev_list) {
|
2015-06-08 22:26:54 +08:00
|
|
|
printf(" %3llu %10s %s\n",
|
2015-02-02 23:10:10 +08:00
|
|
|
device->devid,
|
btrfs-progs: mkfs: print the summary
This patch prints the summary of the filesystem after the creation.
The main fileds printed are:
- devices list with their uuid, devid, path and size
- raid profile (dup,single,raid0...)
- leafsize/nodesize/sectorsize
- filesystem features (raid56, extref, mixed-bg)
- chunk size and type
If the '-v' switched is passed, the output is more verbose; if the '-q'
switched is passed, only the errors are printed.
Below an example:
BTRFS filesystem summary:
Label: btrfs-test
UUID: 14ae8a88-98ac-4f22-8441-79f76ec622f7
Node size: 4096
Leaf size: 4096
Sector size: 4096
Initial chunks:
Data+Metadata: 9.01GiB
System: 18.06MiB
Metadata profile: RAID5
Data profile: RAID5
Mixed mode: YES
SSD detected: NO
Incompat features: mixed-bg, extref, raid56
Number of devices: 10
UUID ID SIZE PATH
------------------------------------ -- --------- -----------
df1c7f50-1980-4da2-8bc9-7ee6ffb0b554 1 50.00GiB /dev/vdb
32c808a0-cd7b-4497-a2c0-1d77a9854af9 2 50.00GiB /dev/vdc
3159782e-d108-40bc-9e15-090ecac160b4 3 50.00GiB /dev/vdd
db7eaf0c-beb8-4093-a9d0-b9c25c146305 4 50.00GiB /dev/vde
c367ca04-1f71-49c0-a331-11fc0b87e9fc 5 50.00GiB /dev/vdf
e9b73c86-4058-4b3a-90ac-18741a276e70 6 50.00GiB /dev/vdg
c4298b7a-ad41-4690-bf10-bf748b319413 7 50.00GiB /dev/vdh
1cf048c8-af8a-4225-b09a-5d12e9b217fa 8 2.00GiB /dev/vdi
7e157869-768a-4725-bad5-82e6bd05fd17 9 2.00GiB /dev/vdj
2c9431ac-c7f0-45a5-8529-cef8cf6e4033 10 2.00GiB /dev/vdk
Total devices size: 356.01GiB
Signed-off-by: Goffredo Baroncelli <kreijack@inwind.it>
Signed-off-by: David Sterba <dsterba@suse.cz>
2015-06-08 19:00:50 +08:00
|
|
|
pretty_size(device->total_bytes),
|
2015-02-02 23:11:23 +08:00
|
|
|
device->name);
|
btrfs-progs: mkfs: print the summary
This patch prints the summary of the filesystem after the creation.
The main fileds printed are:
- devices list with their uuid, devid, path and size
- raid profile (dup,single,raid0...)
- leafsize/nodesize/sectorsize
- filesystem features (raid56, extref, mixed-bg)
- chunk size and type
If the '-v' switched is passed, the output is more verbose; if the '-q'
switched is passed, only the errors are printed.
Below an example:
BTRFS filesystem summary:
Label: btrfs-test
UUID: 14ae8a88-98ac-4f22-8441-79f76ec622f7
Node size: 4096
Leaf size: 4096
Sector size: 4096
Initial chunks:
Data+Metadata: 9.01GiB
System: 18.06MiB
Metadata profile: RAID5
Data profile: RAID5
Mixed mode: YES
SSD detected: NO
Incompat features: mixed-bg, extref, raid56
Number of devices: 10
UUID ID SIZE PATH
------------------------------------ -- --------- -----------
df1c7f50-1980-4da2-8bc9-7ee6ffb0b554 1 50.00GiB /dev/vdb
32c808a0-cd7b-4497-a2c0-1d77a9854af9 2 50.00GiB /dev/vdc
3159782e-d108-40bc-9e15-090ecac160b4 3 50.00GiB /dev/vdd
db7eaf0c-beb8-4093-a9d0-b9c25c146305 4 50.00GiB /dev/vde
c367ca04-1f71-49c0-a331-11fc0b87e9fc 5 50.00GiB /dev/vdf
e9b73c86-4058-4b3a-90ac-18741a276e70 6 50.00GiB /dev/vdg
c4298b7a-ad41-4690-bf10-bf748b319413 7 50.00GiB /dev/vdh
1cf048c8-af8a-4225-b09a-5d12e9b217fa 8 2.00GiB /dev/vdi
7e157869-768a-4725-bad5-82e6bd05fd17 9 2.00GiB /dev/vdj
2c9431ac-c7f0-45a5-8529-cef8cf6e4033 10 2.00GiB /dev/vdk
Total devices size: 356.01GiB
Signed-off-by: Goffredo Baroncelli <kreijack@inwind.it>
Signed-off-by: David Sterba <dsterba@suse.cz>
2015-06-08 19:00:50 +08:00
|
|
|
total_block_count += device->total_bytes;
|
|
|
|
}
|
|
|
|
|
|
|
|
printf("\n");
|
|
|
|
}
|
|
|
|
|
btrfs-progs: mkfs: Cleanup temporary chunk to avoid strange balance behavior.
[BUG]
# mkfs.btrfs /dev/sdb /dev/sdd -m raid0 -d raid0
# mount /dev/sdb /mnt/btrfs
# btrfs balance start /mnt/btrfs
# btrfs fi df /mnt/btrfs
Data, single: total=1.00GiB, used=320.00KiB
System, single: total=32.00MiB, used=16.00KiB
Metadata, RAID0: total=256.00MiB, used=112.00KiB
GlobalReserve, single: total=16.00MiB, used=0.00B
Only metadata stay RAID0. Data and system goes from RAID0 to single.
[REASON]
The problem is caused by the temporary single chunk.
In mkfs, it will always create single data/metadata/sys chunk and them
add device into the temporary btrfs.
When doing all chunk balance, for data and syschunk, they are almost
empty, so balance will move them into the single chunk and remove the
old RAID0 chunk.
For metadata, it has more data and will kick the metadata chunk pre
alloc, so new RAID0 chunk is allocated and the old metadata is move
there. Old RAID0 and single chunks are removed.
[FIX]
Now we add a new function to cleanup the temporary chunks at the end of
mkfs routine.
It will cleanup the chunks which is empty and its profile differs from
the mkfs profile.
So in balance, btrfs will always alloc a new chunk to keep the profile,
other than moving data into the single chunk.
Signed-off-by: Qu Wenruo <quwenruo@cn.fujitsu.com>
Signed-off-by: David Sterba <dsterba@suse.com>
2015-07-07 16:15:28 +08:00
|
|
|
static int is_temp_block_group(struct extent_buffer *node,
|
|
|
|
struct btrfs_block_group_item *bgi,
|
|
|
|
u64 data_profile, u64 meta_profile,
|
|
|
|
u64 sys_profile)
|
|
|
|
{
|
|
|
|
u64 flag = btrfs_disk_block_group_flags(node, bgi);
|
|
|
|
u64 flag_type = flag & BTRFS_BLOCK_GROUP_TYPE_MASK;
|
|
|
|
u64 flag_profile = flag & BTRFS_BLOCK_GROUP_PROFILE_MASK;
|
|
|
|
u64 used = btrfs_disk_block_group_used(node, bgi);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Chunks meets all the following conditions is a temp chunk
|
|
|
|
* 1) Empty chunk
|
|
|
|
* Temp chunk is always empty.
|
|
|
|
*
|
2016-05-12 07:50:36 +08:00
|
|
|
* 2) profile mismatch with mkfs profile.
|
btrfs-progs: mkfs: Cleanup temporary chunk to avoid strange balance behavior.
[BUG]
# mkfs.btrfs /dev/sdb /dev/sdd -m raid0 -d raid0
# mount /dev/sdb /mnt/btrfs
# btrfs balance start /mnt/btrfs
# btrfs fi df /mnt/btrfs
Data, single: total=1.00GiB, used=320.00KiB
System, single: total=32.00MiB, used=16.00KiB
Metadata, RAID0: total=256.00MiB, used=112.00KiB
GlobalReserve, single: total=16.00MiB, used=0.00B
Only metadata stay RAID0. Data and system goes from RAID0 to single.
[REASON]
The problem is caused by the temporary single chunk.
In mkfs, it will always create single data/metadata/sys chunk and them
add device into the temporary btrfs.
When doing all chunk balance, for data and syschunk, they are almost
empty, so balance will move them into the single chunk and remove the
old RAID0 chunk.
For metadata, it has more data and will kick the metadata chunk pre
alloc, so new RAID0 chunk is allocated and the old metadata is move
there. Old RAID0 and single chunks are removed.
[FIX]
Now we add a new function to cleanup the temporary chunks at the end of
mkfs routine.
It will cleanup the chunks which is empty and its profile differs from
the mkfs profile.
So in balance, btrfs will always alloc a new chunk to keep the profile,
other than moving data into the single chunk.
Signed-off-by: Qu Wenruo <quwenruo@cn.fujitsu.com>
Signed-off-by: David Sterba <dsterba@suse.com>
2015-07-07 16:15:28 +08:00
|
|
|
* Temp chunk is always in SINGLE
|
|
|
|
*
|
|
|
|
* 3) Size differs with mkfs_alloc
|
|
|
|
* Special case for SINGLE/SINGLE btrfs.
|
|
|
|
* In that case, temp data chunk and real data chunk are always empty.
|
|
|
|
* So we need to use mkfs_alloc to be sure which chunk is the newly
|
|
|
|
* allocated.
|
|
|
|
*
|
|
|
|
* Normally, new chunk size is equal to mkfs one (One chunk)
|
|
|
|
* If it has multiple chunks, we just refuse to delete any one.
|
|
|
|
* As they are all single, so no real problem will happen.
|
|
|
|
* So only use condition 1) and 2) to judge them.
|
|
|
|
*/
|
|
|
|
if (used != 0)
|
|
|
|
return 0;
|
|
|
|
switch (flag_type) {
|
|
|
|
case BTRFS_BLOCK_GROUP_DATA:
|
|
|
|
case BTRFS_BLOCK_GROUP_DATA | BTRFS_BLOCK_GROUP_METADATA:
|
|
|
|
data_profile &= BTRFS_BLOCK_GROUP_PROFILE_MASK;
|
|
|
|
if (flag_profile != data_profile)
|
|
|
|
return 1;
|
|
|
|
break;
|
|
|
|
case BTRFS_BLOCK_GROUP_METADATA:
|
|
|
|
meta_profile &= BTRFS_BLOCK_GROUP_PROFILE_MASK;
|
|
|
|
if (flag_profile != meta_profile)
|
|
|
|
return 1;
|
|
|
|
break;
|
|
|
|
case BTRFS_BLOCK_GROUP_SYSTEM:
|
|
|
|
sys_profile &= BTRFS_BLOCK_GROUP_PROFILE_MASK;
|
|
|
|
if (flag_profile != sys_profile)
|
|
|
|
return 1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Note: if current is a block group, it will skip it anyway */
|
|
|
|
static int next_block_group(struct btrfs_root *root,
|
|
|
|
struct btrfs_path *path)
|
|
|
|
{
|
|
|
|
struct btrfs_key key;
|
|
|
|
int ret = 0;
|
|
|
|
|
|
|
|
while (1) {
|
|
|
|
ret = btrfs_next_item(root, path);
|
|
|
|
if (ret)
|
|
|
|
goto out;
|
|
|
|
|
|
|
|
btrfs_item_key_to_cpu(path->nodes[0], &key, path->slots[0]);
|
|
|
|
if (key.type == BTRFS_BLOCK_GROUP_ITEM_KEY)
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
out:
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* This function will cleanup */
|
|
|
|
static int cleanup_temp_chunks(struct btrfs_fs_info *fs_info,
|
|
|
|
struct mkfs_allocation *alloc,
|
|
|
|
u64 data_profile, u64 meta_profile,
|
|
|
|
u64 sys_profile)
|
|
|
|
{
|
|
|
|
struct btrfs_trans_handle *trans = NULL;
|
|
|
|
struct btrfs_block_group_item *bgi;
|
|
|
|
struct btrfs_root *root = fs_info->extent_root;
|
|
|
|
struct btrfs_key key;
|
|
|
|
struct btrfs_key found_key;
|
|
|
|
struct btrfs_path *path;
|
|
|
|
int ret = 0;
|
|
|
|
|
|
|
|
path = btrfs_alloc_path();
|
|
|
|
if (!path) {
|
|
|
|
ret = -ENOMEM;
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
trans = btrfs_start_transaction(root, 1);
|
|
|
|
|
|
|
|
key.objectid = 0;
|
|
|
|
key.type = BTRFS_BLOCK_GROUP_ITEM_KEY;
|
|
|
|
key.offset = 0;
|
|
|
|
|
|
|
|
while (1) {
|
|
|
|
/*
|
|
|
|
* as the rest of the loop may modify the tree, we need to
|
|
|
|
* start a new search each time.
|
|
|
|
*/
|
|
|
|
ret = btrfs_search_slot(trans, root, &key, path, 0, 0);
|
|
|
|
if (ret < 0)
|
|
|
|
goto out;
|
|
|
|
|
|
|
|
btrfs_item_key_to_cpu(path->nodes[0], &found_key,
|
|
|
|
path->slots[0]);
|
|
|
|
if (found_key.objectid < key.objectid)
|
|
|
|
goto out;
|
|
|
|
if (found_key.type != BTRFS_BLOCK_GROUP_ITEM_KEY) {
|
|
|
|
ret = next_block_group(root, path);
|
|
|
|
if (ret < 0)
|
|
|
|
goto out;
|
|
|
|
if (ret > 0) {
|
|
|
|
ret = 0;
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
btrfs_item_key_to_cpu(path->nodes[0], &found_key,
|
|
|
|
path->slots[0]);
|
|
|
|
}
|
|
|
|
|
|
|
|
bgi = btrfs_item_ptr(path->nodes[0], path->slots[0],
|
|
|
|
struct btrfs_block_group_item);
|
|
|
|
if (is_temp_block_group(path->nodes[0], bgi,
|
|
|
|
data_profile, meta_profile,
|
|
|
|
sys_profile)) {
|
2016-07-01 13:26:25 +08:00
|
|
|
u64 flags = btrfs_disk_block_group_flags(path->nodes[0],
|
|
|
|
bgi);
|
|
|
|
|
btrfs-progs: mkfs: Cleanup temporary chunk to avoid strange balance behavior.
[BUG]
# mkfs.btrfs /dev/sdb /dev/sdd -m raid0 -d raid0
# mount /dev/sdb /mnt/btrfs
# btrfs balance start /mnt/btrfs
# btrfs fi df /mnt/btrfs
Data, single: total=1.00GiB, used=320.00KiB
System, single: total=32.00MiB, used=16.00KiB
Metadata, RAID0: total=256.00MiB, used=112.00KiB
GlobalReserve, single: total=16.00MiB, used=0.00B
Only metadata stay RAID0. Data and system goes from RAID0 to single.
[REASON]
The problem is caused by the temporary single chunk.
In mkfs, it will always create single data/metadata/sys chunk and them
add device into the temporary btrfs.
When doing all chunk balance, for data and syschunk, they are almost
empty, so balance will move them into the single chunk and remove the
old RAID0 chunk.
For metadata, it has more data and will kick the metadata chunk pre
alloc, so new RAID0 chunk is allocated and the old metadata is move
there. Old RAID0 and single chunks are removed.
[FIX]
Now we add a new function to cleanup the temporary chunks at the end of
mkfs routine.
It will cleanup the chunks which is empty and its profile differs from
the mkfs profile.
So in balance, btrfs will always alloc a new chunk to keep the profile,
other than moving data into the single chunk.
Signed-off-by: Qu Wenruo <quwenruo@cn.fujitsu.com>
Signed-off-by: David Sterba <dsterba@suse.com>
2015-07-07 16:15:28 +08:00
|
|
|
ret = btrfs_free_block_group(trans, fs_info,
|
|
|
|
found_key.objectid, found_key.offset);
|
|
|
|
if (ret < 0)
|
|
|
|
goto out;
|
2016-07-01 13:26:25 +08:00
|
|
|
|
|
|
|
if ((flags & BTRFS_BLOCK_GROUP_TYPE_MASK) ==
|
|
|
|
BTRFS_BLOCK_GROUP_DATA)
|
|
|
|
alloc->data -= found_key.offset;
|
|
|
|
else if ((flags & BTRFS_BLOCK_GROUP_TYPE_MASK) ==
|
|
|
|
BTRFS_BLOCK_GROUP_METADATA)
|
|
|
|
alloc->metadata -= found_key.offset;
|
|
|
|
else if ((flags & BTRFS_BLOCK_GROUP_TYPE_MASK) ==
|
|
|
|
BTRFS_BLOCK_GROUP_SYSTEM)
|
|
|
|
alloc->system -= found_key.offset;
|
|
|
|
else if ((flags & BTRFS_BLOCK_GROUP_TYPE_MASK) ==
|
|
|
|
(BTRFS_BLOCK_GROUP_METADATA |
|
|
|
|
BTRFS_BLOCK_GROUP_DATA))
|
|
|
|
alloc->mixed -= found_key.offset;
|
btrfs-progs: mkfs: Cleanup temporary chunk to avoid strange balance behavior.
[BUG]
# mkfs.btrfs /dev/sdb /dev/sdd -m raid0 -d raid0
# mount /dev/sdb /mnt/btrfs
# btrfs balance start /mnt/btrfs
# btrfs fi df /mnt/btrfs
Data, single: total=1.00GiB, used=320.00KiB
System, single: total=32.00MiB, used=16.00KiB
Metadata, RAID0: total=256.00MiB, used=112.00KiB
GlobalReserve, single: total=16.00MiB, used=0.00B
Only metadata stay RAID0. Data and system goes from RAID0 to single.
[REASON]
The problem is caused by the temporary single chunk.
In mkfs, it will always create single data/metadata/sys chunk and them
add device into the temporary btrfs.
When doing all chunk balance, for data and syschunk, they are almost
empty, so balance will move them into the single chunk and remove the
old RAID0 chunk.
For metadata, it has more data and will kick the metadata chunk pre
alloc, so new RAID0 chunk is allocated and the old metadata is move
there. Old RAID0 and single chunks are removed.
[FIX]
Now we add a new function to cleanup the temporary chunks at the end of
mkfs routine.
It will cleanup the chunks which is empty and its profile differs from
the mkfs profile.
So in balance, btrfs will always alloc a new chunk to keep the profile,
other than moving data into the single chunk.
Signed-off-by: Qu Wenruo <quwenruo@cn.fujitsu.com>
Signed-off-by: David Sterba <dsterba@suse.com>
2015-07-07 16:15:28 +08:00
|
|
|
}
|
|
|
|
btrfs_release_path(path);
|
|
|
|
key.objectid = found_key.objectid + found_key.offset;
|
|
|
|
}
|
|
|
|
out:
|
|
|
|
if (trans)
|
|
|
|
btrfs_commit_transaction(trans, root);
|
|
|
|
btrfs_free_path(path);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2016-03-01 23:28:11 +08:00
|
|
|
int main(int argc, char **argv)
|
2007-03-21 08:35:03 +08:00
|
|
|
{
|
|
|
|
char *file;
|
2008-04-18 22:31:42 +08:00
|
|
|
struct btrfs_root *root;
|
|
|
|
struct btrfs_trans_handle *trans;
|
|
|
|
char *label = NULL;
|
2007-03-21 08:35:03 +08:00
|
|
|
u64 block_count = 0;
|
2008-03-25 03:04:49 +08:00
|
|
|
u64 dev_block_count = 0;
|
Btrfs: move data checksumming into a dedicated tree
Btrfs stores checksums for each data block. Until now, they have
been stored in the subvolume trees, indexed by the inode that is
referencing the data block. This means that when we read the inode,
we've probably read in at least some checksums as well.
But, this has a few problems:
* The checksums are indexed by logical offset in the file. When
compression is on, this means we have to do the expensive checksumming
on the uncompressed data. It would be faster if we could checksum
the compressed data instead.
* If we implement encryption, we'll be checksumming the plain text and
storing that on disk. This is significantly less secure.
* For either compression or encryption, we have to get the plain text
back before we can verify the checksum as correct. This makes the raid
layer balancing and extent moving much more expensive.
* It makes the front end caching code more complex, as we have touch
the subvolume and inodes as we cache extents.
* There is potentitally one copy of the checksum in each subvolume
referencing an extent.
The solution used here is to store the extent checksums in a dedicated
tree. This allows us to index the checksums by phyiscal extent
start and length. It means:
* The checksum is against the data stored on disk, after any compression
or encryption is done.
* The checksum is stored in a central location, and can be verified without
following back references, or reading inodes.
This makes compression significantly faster by reducing the amount of
data that needs to be checksummed. It will also allow much faster
raid management code in general.
The checksums are indexed by a key with a fixed objectid (a magic value
in ctree.h) and offset set to the starting byte of the extent. This
allows us to copy the checksum items into the fsync log tree directly (or
any other tree), without having to invent a second format for them.
Signed-off-by: Chris Mason <chris.mason@oracle.com>
2008-12-09 06:00:31 +08:00
|
|
|
u64 blocks[7];
|
2008-05-01 22:22:47 +08:00
|
|
|
u64 alloc_start = 0;
|
2011-12-13 02:00:25 +08:00
|
|
|
u64 metadata_profile = 0;
|
|
|
|
u64 data_profile = 0;
|
2015-02-02 22:51:15 +08:00
|
|
|
u32 nodesize = max_t(u32, sysconf(_SC_PAGESIZE),
|
2015-03-20 09:10:15 +08:00
|
|
|
BTRFS_MKFS_DEFAULT_NODE_SIZE);
|
2007-10-16 04:25:14 +08:00
|
|
|
u32 sectorsize = 4096;
|
2007-12-01 00:30:24 +08:00
|
|
|
u32 stripesize = 4096;
|
2008-03-25 03:04:49 +08:00
|
|
|
int zero_end = 1;
|
2008-04-18 22:31:42 +08:00
|
|
|
int fd;
|
|
|
|
int ret;
|
|
|
|
int i;
|
2010-12-10 02:31:08 +08:00
|
|
|
int mixed = 0;
|
2015-02-02 22:51:15 +08:00
|
|
|
int nodesize_forced = 0;
|
2010-12-10 02:31:08 +08:00
|
|
|
int data_profile_opt = 0;
|
|
|
|
int metadata_profile_opt = 0;
|
2013-09-17 22:54:00 +08:00
|
|
|
int discard = 1;
|
2013-01-20 02:06:21 +08:00
|
|
|
int ssd = 0;
|
2013-02-15 02:30:03 +08:00
|
|
|
int force_overwrite = 0;
|
2010-07-08 17:17:59 +08:00
|
|
|
char *source_dir = NULL;
|
|
|
|
int source_dir_set = 0;
|
|
|
|
u64 num_of_meta_chunks = 0;
|
|
|
|
u64 size_of_data = 0;
|
2011-06-21 09:45:59 +08:00
|
|
|
u64 source_dir_size = 0;
|
2013-04-15 14:38:09 +08:00
|
|
|
int dev_cnt = 0;
|
|
|
|
int saved_optind;
|
2014-12-18 04:14:09 +08:00
|
|
|
char fs_uuid[BTRFS_UUID_UNPARSED_SIZE] = { 0 };
|
2015-03-24 02:20:37 +08:00
|
|
|
u64 features = BTRFS_MKFS_DEFAULT_FEATURES;
|
2015-06-08 18:54:54 +08:00
|
|
|
struct mkfs_allocation allocation = { 0 };
|
2015-07-01 23:49:21 +08:00
|
|
|
struct btrfs_mkfs_config mkfs_cfg;
|
2010-07-08 17:17:59 +08:00
|
|
|
|
2007-10-16 04:25:14 +08:00
|
|
|
while(1) {
|
|
|
|
int c;
|
2015-01-19 20:44:49 +08:00
|
|
|
static const struct option long_options[] = {
|
2015-04-08 23:39:51 +08:00
|
|
|
{ "alloc-start", required_argument, NULL, 'A'},
|
|
|
|
{ "byte-count", required_argument, NULL, 'b' },
|
|
|
|
{ "force", no_argument, NULL, 'f' },
|
|
|
|
{ "leafsize", required_argument, NULL, 'l' },
|
|
|
|
{ "label", required_argument, NULL, 'L'},
|
|
|
|
{ "metadata", required_argument, NULL, 'm' },
|
|
|
|
{ "mixed", no_argument, NULL, 'M' },
|
|
|
|
{ "nodesize", required_argument, NULL, 'n' },
|
|
|
|
{ "sectorsize", required_argument, NULL, 's' },
|
|
|
|
{ "data", required_argument, NULL, 'd' },
|
|
|
|
{ "version", no_argument, NULL, 'V' },
|
|
|
|
{ "rootdir", required_argument, NULL, 'r' },
|
|
|
|
{ "nodiscard", no_argument, NULL, 'K' },
|
|
|
|
{ "features", required_argument, NULL, 'O' },
|
2015-01-19 20:30:06 +08:00
|
|
|
{ "uuid", required_argument, NULL, 'U' },
|
2014-12-18 04:14:05 +08:00
|
|
|
{ "quiet", 0, NULL, 'q' },
|
2015-06-11 06:04:19 +08:00
|
|
|
{ "help", no_argument, NULL, GETOPT_VAL_HELP },
|
2015-01-19 20:30:06 +08:00
|
|
|
{ NULL, 0, NULL, 0}
|
|
|
|
};
|
|
|
|
|
2016-03-01 23:28:11 +08:00
|
|
|
c = getopt_long(argc, argv, "A:b:fl:n:s:m:d:L:O:r:U:VMKq",
|
2015-04-08 23:33:55 +08:00
|
|
|
long_options, NULL);
|
2007-10-16 04:25:14 +08:00
|
|
|
if (c < 0)
|
|
|
|
break;
|
|
|
|
switch(c) {
|
2008-04-26 04:55:21 +08:00
|
|
|
case 'A':
|
|
|
|
alloc_start = parse_size(optarg);
|
|
|
|
break;
|
2013-02-15 02:30:03 +08:00
|
|
|
case 'f':
|
|
|
|
force_overwrite = 1;
|
|
|
|
break;
|
2008-04-04 04:35:48 +08:00
|
|
|
case 'd':
|
|
|
|
data_profile = parse_profile(optarg);
|
2010-12-10 02:31:08 +08:00
|
|
|
data_profile_opt = 1;
|
2008-04-04 04:35:48 +08:00
|
|
|
break;
|
2007-10-16 04:25:14 +08:00
|
|
|
case 'l':
|
2016-08-19 00:38:34 +08:00
|
|
|
warning("--leafsize is deprecated, use --nodesize");
|
2012-03-27 04:17:08 +08:00
|
|
|
case 'n':
|
|
|
|
nodesize = parse_size(optarg);
|
2015-02-02 22:51:15 +08:00
|
|
|
nodesize_forced = 1;
|
2007-10-16 04:25:14 +08:00
|
|
|
break;
|
2008-04-18 22:31:42 +08:00
|
|
|
case 'L':
|
|
|
|
label = parse_label(optarg);
|
|
|
|
break;
|
|
|
|
case 'm':
|
|
|
|
metadata_profile = parse_profile(optarg);
|
2010-12-10 02:31:08 +08:00
|
|
|
metadata_profile_opt = 1;
|
|
|
|
break;
|
|
|
|
case 'M':
|
|
|
|
mixed = 1;
|
2008-04-18 22:31:42 +08:00
|
|
|
break;
|
2013-05-16 23:04:04 +08:00
|
|
|
case 'O': {
|
|
|
|
char *orig = strdup(optarg);
|
|
|
|
char *tmp = orig;
|
|
|
|
|
2015-03-24 02:20:37 +08:00
|
|
|
tmp = btrfs_parse_fs_features(tmp, &features);
|
2013-05-16 23:04:04 +08:00
|
|
|
if (tmp) {
|
2016-08-19 00:38:34 +08:00
|
|
|
error("unrecognized filesystem feature '%s'",
|
2013-05-16 23:04:04 +08:00
|
|
|
tmp);
|
|
|
|
free(orig);
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
free(orig);
|
|
|
|
if (features & BTRFS_FEATURE_LIST_ALL) {
|
2015-03-24 02:49:51 +08:00
|
|
|
btrfs_list_all_fs_features(0);
|
2013-05-16 23:04:04 +08:00
|
|
|
exit(0);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2007-12-01 00:30:24 +08:00
|
|
|
case 's':
|
2008-04-01 23:08:13 +08:00
|
|
|
sectorsize = parse_size(optarg);
|
2007-12-01 00:30:24 +08:00
|
|
|
break;
|
2008-03-25 03:04:49 +08:00
|
|
|
case 'b':
|
|
|
|
block_count = parse_size(optarg);
|
|
|
|
zero_end = 0;
|
|
|
|
break;
|
2009-06-04 00:00:20 +08:00
|
|
|
case 'V':
|
|
|
|
print_version();
|
|
|
|
break;
|
2010-07-08 17:17:59 +08:00
|
|
|
case 'r':
|
|
|
|
source_dir = optarg;
|
|
|
|
source_dir_set = 1;
|
|
|
|
break;
|
2014-05-15 01:39:07 +08:00
|
|
|
case 'U':
|
2014-12-18 04:14:09 +08:00
|
|
|
strncpy(fs_uuid, optarg,
|
|
|
|
BTRFS_UUID_UNPARSED_SIZE - 1);
|
2014-05-15 01:39:07 +08:00
|
|
|
break;
|
2012-07-17 18:30:16 +08:00
|
|
|
case 'K':
|
2013-09-17 22:54:00 +08:00
|
|
|
discard = 0;
|
2012-07-06 22:11:10 +08:00
|
|
|
break;
|
2014-12-18 04:14:05 +08:00
|
|
|
case 'q':
|
|
|
|
verbose = 0;
|
|
|
|
break;
|
2015-06-11 06:04:19 +08:00
|
|
|
case GETOPT_VAL_HELP:
|
2007-10-16 04:25:14 +08:00
|
|
|
default:
|
2015-06-11 06:04:19 +08:00
|
|
|
print_usage(c != GETOPT_VAL_HELP);
|
2007-10-16 04:25:14 +08:00
|
|
|
}
|
|
|
|
}
|
2015-09-26 00:15:44 +08:00
|
|
|
|
2015-10-30 23:58:52 +08:00
|
|
|
if (verbose) {
|
|
|
|
printf("%s\n", PACKAGE_STRING);
|
|
|
|
printf("See %s for more information.\n\n", PACKAGE_URL);
|
|
|
|
}
|
|
|
|
|
2013-01-20 02:06:17 +08:00
|
|
|
sectorsize = max(sectorsize, (u32)sysconf(_SC_PAGESIZE));
|
2016-06-17 13:37:54 +08:00
|
|
|
stripesize = sectorsize;
|
2013-04-15 14:38:09 +08:00
|
|
|
saved_optind = optind;
|
2016-03-01 23:28:11 +08:00
|
|
|
dev_cnt = argc - optind;
|
2013-04-15 14:38:09 +08:00
|
|
|
if (dev_cnt == 0)
|
2015-06-11 06:04:19 +08:00
|
|
|
print_usage(1);
|
2008-03-25 03:04:49 +08:00
|
|
|
|
2013-04-15 14:38:09 +08:00
|
|
|
if (source_dir_set && dev_cnt > 1) {
|
2016-08-19 00:38:34 +08:00
|
|
|
error("the option -r is limited to a single device");
|
2013-04-15 14:38:09 +08:00
|
|
|
exit(1);
|
|
|
|
}
|
2014-05-15 01:39:07 +08:00
|
|
|
|
2014-12-18 04:14:09 +08:00
|
|
|
if (*fs_uuid) {
|
2014-05-15 01:39:07 +08:00
|
|
|
uuid_t dummy_uuid;
|
|
|
|
|
|
|
|
if (uuid_parse(fs_uuid, dummy_uuid) != 0) {
|
2016-08-19 00:38:34 +08:00
|
|
|
error("could not parse UUID: %s", fs_uuid);
|
2014-05-15 01:39:07 +08:00
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
if (!test_uuid_unique(fs_uuid)) {
|
2016-08-19 00:38:34 +08:00
|
|
|
error("non-unique UUID: %s", fs_uuid);
|
2014-05-15 01:39:07 +08:00
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
}
|
2015-10-15 01:39:37 +08:00
|
|
|
|
2013-04-15 14:38:09 +08:00
|
|
|
while (dev_cnt-- > 0) {
|
2016-03-01 23:28:11 +08:00
|
|
|
file = argv[optind++];
|
2015-08-28 22:11:30 +08:00
|
|
|
if (is_block_device(file) == 1)
|
2015-06-11 06:46:30 +08:00
|
|
|
if (test_dev_for_mkfs(file, force_overwrite))
|
2013-02-15 02:30:03 +08:00
|
|
|
exit(1);
|
2013-04-15 14:38:09 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
optind = saved_optind;
|
2016-03-01 23:28:11 +08:00
|
|
|
dev_cnt = argc - optind;
|
2013-04-15 14:38:09 +08:00
|
|
|
|
2016-03-01 23:28:11 +08:00
|
|
|
file = argv[optind++];
|
2013-08-07 20:11:25 +08:00
|
|
|
ssd = is_ssd(file);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Set default profiles according to number of added devices.
|
|
|
|
* For mixed groups defaults are single/single.
|
|
|
|
*/
|
|
|
|
if (!mixed) {
|
|
|
|
if (!metadata_profile_opt) {
|
2014-12-18 04:14:05 +08:00
|
|
|
if (dev_cnt == 1 && ssd && verbose)
|
2013-08-07 20:11:25 +08:00
|
|
|
printf("Detected a SSD, turning off metadata "
|
|
|
|
"duplication. Mkfs with -m dup if you want to "
|
|
|
|
"force metadata duplication.\n");
|
|
|
|
|
|
|
|
metadata_profile = (dev_cnt > 1) ?
|
|
|
|
BTRFS_BLOCK_GROUP_RAID1 : (ssd) ?
|
|
|
|
0: BTRFS_BLOCK_GROUP_DUP;
|
|
|
|
}
|
|
|
|
if (!data_profile_opt) {
|
|
|
|
data_profile = (dev_cnt > 1) ?
|
|
|
|
BTRFS_BLOCK_GROUP_RAID0 : 0; /* raid0 or single */
|
|
|
|
}
|
|
|
|
} else {
|
2015-02-02 22:51:15 +08:00
|
|
|
u32 best_nodesize = max_t(u32, sysconf(_SC_PAGESIZE), sectorsize);
|
2013-11-15 19:11:09 +08:00
|
|
|
|
|
|
|
if (metadata_profile_opt || data_profile_opt) {
|
|
|
|
if (metadata_profile != data_profile) {
|
2016-08-19 00:38:34 +08:00
|
|
|
error(
|
|
|
|
"with mixed block groups data and metadata profiles must be the same");
|
2013-11-15 19:11:09 +08:00
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
}
|
2013-11-09 02:51:52 +08:00
|
|
|
|
2015-09-26 00:15:44 +08:00
|
|
|
if (!nodesize_forced)
|
2015-02-02 22:51:15 +08:00
|
|
|
nodesize = best_nodesize;
|
2013-08-07 20:11:25 +08:00
|
|
|
}
|
2015-10-15 01:40:38 +08:00
|
|
|
|
|
|
|
/*
|
|
|
|
* FS features that can be set by other means than -O
|
|
|
|
* just set the bit here
|
|
|
|
*/
|
|
|
|
if (mixed)
|
|
|
|
features |= BTRFS_FEATURE_INCOMPAT_MIXED_GROUPS;
|
|
|
|
|
|
|
|
if ((data_profile | metadata_profile) &
|
|
|
|
(BTRFS_BLOCK_GROUP_RAID5 | BTRFS_BLOCK_GROUP_RAID6)) {
|
|
|
|
features |= BTRFS_FEATURE_INCOMPAT_RAID56;
|
|
|
|
}
|
|
|
|
|
2015-09-26 00:15:44 +08:00
|
|
|
if (btrfs_check_nodesize(nodesize, sectorsize,
|
|
|
|
features))
|
|
|
|
exit(1);
|
2013-08-07 20:11:25 +08:00
|
|
|
|
2015-02-02 22:51:15 +08:00
|
|
|
/* Check device/block_count after the nodesize is determined */
|
|
|
|
if (block_count && block_count < btrfs_min_dev_size(nodesize)) {
|
2016-08-19 00:38:34 +08:00
|
|
|
error("size %llu is too small to make a usable filesystem",
|
2014-07-04 15:29:17 +08:00
|
|
|
block_count);
|
2016-08-19 00:38:34 +08:00
|
|
|
error("minimum size for btrfs filesystem is %llu",
|
2015-02-02 22:51:15 +08:00
|
|
|
btrfs_min_dev_size(nodesize));
|
2014-07-04 15:29:17 +08:00
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
for (i = saved_optind; i < saved_optind + dev_cnt; i++) {
|
|
|
|
char *path;
|
|
|
|
|
2016-03-01 23:28:11 +08:00
|
|
|
path = argv[i];
|
2015-02-02 22:51:15 +08:00
|
|
|
ret = test_minimum_size(path, nodesize);
|
2014-07-04 15:29:17 +08:00
|
|
|
if (ret < 0) {
|
2016-08-19 00:38:34 +08:00
|
|
|
error("failed to check size for %s: %s",
|
2014-07-04 15:29:17 +08:00
|
|
|
path, strerror(-ret));
|
|
|
|
exit (1);
|
|
|
|
}
|
|
|
|
if (ret > 0) {
|
2016-08-19 00:38:34 +08:00
|
|
|
error("'%s' is too small to make a usable filesystem",
|
2014-07-04 15:29:17 +08:00
|
|
|
path);
|
2016-08-19 00:38:34 +08:00
|
|
|
error("minimum size for each btrfs device is %llu",
|
2015-02-02 22:51:15 +08:00
|
|
|
btrfs_min_dev_size(nodesize));
|
2014-07-04 15:29:17 +08:00
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
}
|
2013-08-07 20:11:25 +08:00
|
|
|
ret = test_num_disk_vs_raid(metadata_profile, data_profile,
|
btrfs-progs: mkfs: allow --data DUP for single device
Current code don't support DUP profile on single device, except it
is in mixed mode, because of following reasons:
1: Some SSD do deduplication internally, so the duplication on
the filesystem side has no effect.
2: On a physical device, if the entire disk broken, --data DUP does not
help.
3: Half performance compared to single profile.
4: We have a workaround: create multi-partition on a single device,
and btffs will treat them as multi device.
Instead of refusing --data DUP, we give the user a choice and print
a wrning.
Test:
1: Tested by xfstests
Run with modified xfstests, I add test items of -d dup in single
device into btrfs/* and common/rc, run tests of btrfs/*,
with all mount option, no regression diffed with v4.3.
2: Tested by btrfs-progs
Checked following commands in "-m dup -d dup" fs with memleck
checking, all passed:
mkfs.btrfs -f --data dup --metadata dup /dev/sda6
btrfs filesystem show /dev/sda6
btrfs filesystem label /dev/sda6 btrfs_label_test
btrfs filesystem label /dev/sda6
btrfs device scan --all-devices
btrfs device scan /dev/sda6
btrfs device scan /dev/sda6
btrfs device ready /dev/sda6
btrfs check /dev/sda6
btrfs check -s 1 /dev/sda6
btrfs check --repair /dev/sda6
btrfs check --init-csum-tree /dev/sda6
btrfs check --init-extent-tree /dev/sda6
btrfs check --check-data-csum /dev/sda6
btrfs check --qgroup-report /dev/sda6
btrfs rescue super-recover -y /dev/sda6
btrfs rescue zero-log /dev/sda6
btrfs restore -l /dev/sda6
btrfs restore /dev/sda6 /
btrfs restore -s /dev/sda6 /
btrfs restore -x /dev/sda6 /
btrfs restore -m /dev/sda6 /
btrfs restore -S /dev/sda6 /
btrfs restore -v /dev/sda6 /
btrfs restore -i /dev/sda6 /
btrfs restore -o /dev/sda6 /
btrfs restore -u0 /dev/sda6 /
btrfs restore -u1 /dev/sda6 /
btrfs restore -D /dev/sda6 /
btrfs property list /dev/sda6
btrfs property get /dev/sda6 label
btrfs property set /dev/sda6 label test
btrfs property set /dev/sda6 label btrfs_label_test
btrfs help
btrfs help --full
btrfs version
btrfsck /dev/sda6
btrfs-find-root /dev/sda6
btrfs-find-root -a /dev/sda6
btrfs-map-logical -l1 /dev/sda6
btrfs-map-logical -l1 -c1 /dev/sda6
btrfs-map-logical -l1 -o /tmp/btrfs-map-logic-out /dev/sda6
btrfs-map-logical -l1 -b1 /dev/sda6
btrfs-select-super -s 0 /dev/sda6
btrfs-select-super -s 1 /dev/sda6
btrfstune -S 1 /dev/sda6
btrfstune -f -S 0 /dev/sda6
btrfstune -r /dev/sda6
btrfstune -x /dev/sda6
btrfstune -n /dev/sda6
btrfstune -f -U 00000000-0000-0000-0000-000000000000 /dev/sda6
btrfstune -f -u /dev/sda6
btrfs-calc-size /dev/sda6
btrfs-calc-size -v /dev/sda6
btrfs-calc-size -b /dev/sda6
btrfs-debug-tree /dev/sda6
btrfs-debug-tree -e /dev/sda6
btrfs-debug-tree -d /dev/sda6
btrfs-debug-tree -r /dev/sda6
btrfs-debug-tree -R /dev/sda6
btrfs-debug-tree -u /dev/sda6
btrfs-debug-tree -b 0 /dev/sda6
btrfs-debug-tree -t 0 /dev/sda6
btrfs-debug-tree -t 2 /dev/sda6
btrfs-show-super /dev/sda6
btrfs-show-super -i 0 /dev/sda6
btrfs-show-super -i 1 /dev/sda6
btrfs-show-super -i 2 /dev/sda6
btrfs-show-super -a /dev/sda6
btrfs-show-super -f /dev/sda6
btrfs-show-super -F /dev/sda6
btrfs subvolume list /mnt/btrfs-progs-tests
btrfs subvolume create /mnt/btrfs-progs-tests/mysubvol
btrfs subvolume list /mnt/btrfs-progs-tests
btrfs subvolume get-default /mnt/btrfs-progs-tests
btrfs subvolume set-default 258 /mnt/btrfs-progs-tests
btrfs subvolume get-default /mnt/btrfs-progs-tests
btrfs subvolume set-default /mnt/btrfs-progs-tests
btrfs subvolume snapshot /mnt/btrfs-progs-tests/mysubvol /mnt/btrfs-progs-tests/mysubvol_snap
btrfs subvolume list /mnt/btrfs-progs-tests
btrfs subvolume find-new /mnt/btrfs-progs-tests 0
btrfs subvolume find-new /mnt/btrfs-progs-tests 0
btrfs subvolume find-new /mnt/btrfs-progs-tests/mysubvol 0
btrfs subvolume find-new /mnt/btrfs-progs-tests/mysubvol 0
btrfs subvolume show /mnt/btrfs-progs-tests
btrfs subvolume show /mnt/btrfs-progs-tests/mysubvol
btrfs subvolume show /mnt/btrfs-progs-tests/mysubvol_snap
btrfs subvolume sync /mnt/btrfs-progs-tests
btrfs subvolume delete /mnt/btrfs-progs-tests/mysubvol_snap
btrfs subvolume delete /mnt/btrfs-progs-tests/mysubvol
btrfs subvolume sync /mnt/btrfs-progs-tests
btrfs filesystem df /mnt/btrfs-progs-tests
btrfs filesystem show /mnt/btrfs-progs-tests
btrfs filesystem sync /mnt/btrfs-progs-tests
btrfs filesystem label /mnt/btrfs-progs-tests btrfs_label_test
btrfs filesystem label /mnt/btrfs-progs-tests
btrfs filesystem usage /mnt/btrfs-progs-tests
btrfs filesystem defragment -s 1024 -l 2048 /mnt/btrfs-progs-tests/filesystem_test_dir/test_dir_0/test_file_0
btrfs filesystem defragment /mnt/btrfs-progs-tests/filesystem_test_dir/test_dir_0/test_file_1
btrfs filesystem defragment -f /mnt/btrfs-progs-tests/filesystem_test_dir/test_dir_0/test_file_2
btrfs filesystem defragment -czlib /mnt/btrfs-progs-tests/filesystem_test_dir/test_dir_0/test_file_3
btrfs filesystem defragment -clzo /mnt/btrfs-progs-tests/filesystem_test_dir/test_dir_0/test_file_4
btrfs filesystem defragment /mnt/btrfs-progs-tests/filesystem_test_dir
btrfs filesystem defragment -r /mnt/btrfs-progs-tests/filesystem_test_dir
btrfs filesystem defragment /mnt/btrfs-progs-tests
btrfs filesystem resize 1:-10M /mnt/btrfs-progs-tests
btrfs filesystem resize 1:max /mnt/btrfs-progs-tests
btrfs balance start /mnt/btrfs-progs-tests
btrfs balance start -v /mnt/btrfs-progs-tests
btrfs balance start -f /mnt/btrfs-progs-tests
btrfs balance status -v /mnt/btrfs-progs-tests
btrfs balance pause /mnt/btrfs-progs-tests
btrfs balance status /mnt/btrfs-progs-tests
btrfs balance resume /mnt/btrfs-progs-tests
btrfs balance status -v /mnt/btrfs-progs-tests
btrfs balance cancel /mnt/btrfs-progs-tests
btrfs balance start -dprofiles=single /mnt/btrfs-progs-tests
btrfs balance start -dconvert=single /mnt/btrfs-progs-tests
btrfs balance start -ddevid=1 /mnt/btrfs-progs-tests
btrfs balance start -f -mprofiles=single /mnt/btrfs-progs-tests
btrfs balance start -f -mconvert=single /mnt/btrfs-progs-tests
btrfs balance start -f -mdevid=1 /mnt/btrfs-progs-tests
btrfs balance start -f -sprofiles=single /mnt/btrfs-progs-tests
btrfs balance start -f -sconvert=single /mnt/btrfs-progs-tests
btrfs balance start -f -sdevid=1 /mnt/btrfs-progs-tests
btrfs device add -f /dev/sda10 /mnt/btrfs-progs-tests
btrfs device del /dev/sda10 /mnt/btrfs-progs-tests
btrfs device stats /dev/sda6
btrfs device stats -z /dev/sda6
btrfs device stats /mnt/btrfs-progs-tests
btrfs device stats -z /mnt/btrfs-progs-tests
btrfs device usage /mnt/btrfs-progs-tests
btrfs scrub status /mnt/btrfs-progs-tests
btrfs scrub start -B /mnt/btrfs-progs-tests
btrfs scrub start -B -d /mnt/btrfs-progs-tests
btrfs scrub start -B -r /mnt/btrfs-progs-tests
btrfs scrub status /mnt/btrfs-progs-tests
btrfs scrub start /mnt/btrfs-progs-tests
btrfs scrub status /mnt/btrfs-progs-tests
btrfs scrub status /mnt/btrfs-progs-tests
btrfs scrub status -d /mnt/btrfs-progs-tests
btrfs scrub status -R /mnt/btrfs-progs-tests
btrfs scrub status /mnt/btrfs-progs-tests
btrfs scrub start /dev/sda6
btrfs scrub status /dev/sda6
btrfs scrub status /dev/sda6
btrfs scrub status -d /dev/sda6
btrfs scrub status -R /dev/sda6
btrfs scrub status /dev/sda6
btrfs subvolume snapshot -r /mnt/btrfs-progs-tests /mnt/btrfs-progs-tests/snap1
btrfs send -f /tmp/btrfs_snapshot_test /mnt/btrfs-progs-tests/snap1
btrfs send -e -f /tmp/btrfs_snapshot_test /mnt/btrfs-progs-tests/snap1
btrfs send --no-data -f /tmp/btrfs_snapshot_test /mnt/btrfs-progs-tests/snap1
btrfs quota enable /mnt/btrfs-progs-tests
btrfs quota rescan /mnt/btrfs-progs-tests
btrfs quota rescan -s /mnt/btrfs-progs-tests
btrfs quota rescan -w /mnt/btrfs-progs-tests
btrfs quota disable /mnt/btrfs-progs-tests
btrfs quota enable /mnt/btrfs-progs-tests
btrfs qgroup create 1/5 /mnt/btrfs-progs-tests
btrfs qgroup create 2/5 /mnt/btrfs-progs-tests
btrfs qgroup assign 1/5 2/5 /mnt/btrfs-progs-tests
btrfs qgroup limit 1G 1/5 /mnt/btrfs-progs-tests
btrfs qgroup show /mnt/btrfs-progs-tests
btrfs qgroup show -p -c -r -e -F -f /mnt/btrfs-progs-tests
btrfs qgroup remove 1/5 2/5 /mnt/btrfs-progs-tests
btrfs qgroup destroy 2/5 /mnt/btrfs-progs-tests
btrfs qgroup destroy 1/5 /mnt/btrfs-progs-tests
btrfs quota disable /mnt/btrfs-progs-tests
btrfs replace start -f -B /dev/sda6 /dev/sda10 /mnt/btrfs-progs-tests
btrfs replace status /mnt/btrfs-progs-tests
btrfs replace start -f -B /dev/sda10 /dev/sda6 /mnt/btrfs-progs-tests
btrfs-convert /dev/sda6
btrfs-convert -r /dev/sda6
btrfs-convert -d /dev/sda6
btrfs-convert -i /dev/sda6
btrfs-convert -n /dev/sda6
btrfs-convert -N 4096 /dev/sda6
btrfs-convert -l test /dev/sda6
btrfs-convert -L /dev/sda6
btrfs-convert --no-progress /dev/sda6
mkfs.btrfs -f /dev/sda6
btrfs-image /dev/sda6 /tmp/btrfs_image.img
btrfs-image -r /tmp/btrfs_image.img /dev/sda6
mkfs.btrfs -f /dev/sda6
btrfs-image -c 0 /dev/sda6 /tmp/btrfs_image.img
btrfs-image -r /tmp/btrfs_image.img /dev/sda6
mkfs.btrfs -f /dev/sda6
btrfs-image -c 9 /dev/sda6 /tmp/btrfs_image.img
btrfs-image -r /tmp/btrfs_image.img /dev/sda6
mkfs.btrfs -f /dev/sda6
btrfs-image -t 0 /dev/sda6 /tmp/btrfs_image.img
btrfs-image -r /tmp/btrfs_image.img /dev/sda6
mkfs.btrfs -f /dev/sda6
btrfs-image -t 1 /dev/sda6 /tmp/btrfs_image.img
btrfs-image -r /tmp/btrfs_image.img /dev/sda6
mkfs.btrfs -f /dev/sda6
btrfs-image -t 32 /dev/sda6 /tmp/btrfs_image.img
btrfs-image -r /tmp/btrfs_image.img /dev/sda6
mkfs.btrfs -f /dev/sda6
btrfs-image -w /dev/sda6 /tmp/btrfs_image.img
btrfs-image -r /tmp/btrfs_image.img /dev/sda6
mkfs.btrfs -f /dev/sda6
btrfs-image -w /dev/sda6 /tmp/btrfs_image.img
btrfs-image -r /tmp/btrfs_image.img /dev/sda6
btrfs-image -r -t 0 /tmp/btrfs_image.img /dev/sda6
btrfs-image -r -t 1 /tmp/btrfs_image.img /dev/sda6
btrfs-image -r -t 32 /tmp/btrfs_image.img /dev/sda6
btrfs-image -r -o /tmp/btrfs_image.img /dev/sda6
3: Manual check relation source by:
grep DUP *.c
Confirmed that all source are modified.
4: Use this raid type manually, do some operations in fs,
no error found in command and dmesg.
5: Combination of dup conversion with fsck
Confirmed OK with relative kernel patch titled:
[PATCH] btrfs: Support convert to -d dup for btrfs-convert
export TEST_DEV='/dev/vdc'
export TEST_DIR='/var/ltf/tester/mnt'
do_dup_test()
{
local m_from="$1"
local d_from="$2"
local m_to="$3"
local d_to="$4"
echo "Convert from -m $m_from -d $d_from to -m $m_to -d $d_to"
umount "$TEST_DIR" &>/dev/null
./mkfs.btrfs -f -m "$m_from" -d "$d_from" "$TEST_DEV" >/dev/null || return 1
mount "$TEST_DEV" "$TEST_DIR" || return 1
cp -a /sbin/* "$TEST_DIR"
[[ "$m_from" != "$m_to" ]] && {
./btrfs balance start -f -mconvert="$m_to" "$TEST_DIR" || return 1
}
[[ "$d_from" != "$d_to" ]] && {
local opt=()
[[ "$d_to" == single ]] && opt+=("-f")
./btrfs balance start "${opt[@]}" -dconvert="$d_to" "$TEST_DIR" || return 1
}
umount "$TEST_DIR" || return 1
./btrfsck "$TEST_DEV" || return 1
echo
return 0
}
test_all()
{
for m_from in single dup; do
for d_from in single dup; do
for m_to in single dup; do
for d_to in single dup; do
do_dup_test "$m_from" "$d_from" "$m_to" "$d_to" || return 1
done
done
done
done
}
test_all
Signed-off-by: Zhao Lei <zhaolei@cn.fujitsu.com>
Tested-by: Austin S. Hemmelgarn <ahferroin7@gmail.com>
[ minor updates in the changelog ]
Signed-off-by: David Sterba <dsterba@suse.com>
2015-11-19 17:36:24 +08:00
|
|
|
dev_cnt, mixed, ssd);
|
2015-06-11 06:51:15 +08:00
|
|
|
if (ret)
|
2013-08-07 20:11:25 +08:00
|
|
|
exit(1);
|
|
|
|
|
2013-04-15 14:38:09 +08:00
|
|
|
dev_cnt--;
|
|
|
|
|
|
|
|
if (!source_dir_set) {
|
2013-02-14 15:53:04 +08:00
|
|
|
/*
|
2013-04-15 14:38:09 +08:00
|
|
|
* open without O_EXCL so that the problem should not
|
2013-02-14 15:53:04 +08:00
|
|
|
* occur by the following processing.
|
|
|
|
* (btrfs_register_one_device() fails if O_EXCL is on)
|
|
|
|
*/
|
2010-07-08 17:17:59 +08:00
|
|
|
fd = open(file, O_RDWR);
|
|
|
|
if (fd < 0) {
|
2016-08-19 00:38:34 +08:00
|
|
|
error("unable to open %s: %s", file, strerror(errno));
|
2010-07-08 17:17:59 +08:00
|
|
|
exit(1);
|
|
|
|
}
|
2016-07-28 07:47:40 +08:00
|
|
|
ret = btrfs_prepare_device(fd, file, &dev_block_count,
|
|
|
|
block_count,
|
|
|
|
(zero_end ? PREP_DEVICE_ZERO_END : 0) |
|
|
|
|
(discard ? PREP_DEVICE_DISCARD : 0) |
|
|
|
|
(verbose ? PREP_DEVICE_VERBOSE : 0));
|
2013-12-18 12:07:55 +08:00
|
|
|
if (ret) {
|
|
|
|
close(fd);
|
|
|
|
exit(1);
|
|
|
|
}
|
2012-07-27 20:37:55 +08:00
|
|
|
if (block_count && block_count > dev_block_count) {
|
2016-08-19 00:38:34 +08:00
|
|
|
error("%s is smaller than requested size, expected %llu, found %llu",
|
|
|
|
file,
|
|
|
|
(unsigned long long)block_count,
|
|
|
|
(unsigned long long)dev_block_count);
|
mkfs: Handle creation of filesystem larger than the first device
On Wed 08-02-12 22:05:26, Phillip Susi wrote:
> -----BEGIN PGP SIGNED MESSAGE-----
> Hash: SHA1
>
> On 02/08/2012 06:20 PM, Jan Kara wrote:
> > Thanks for your reply. I admit I was not sure what exactly size argument
> > should be. So after looking into the code for a while I figured it should
> > be a total size of the filesystem - or differently it should be size of
> > virtual block address space in the filesystem. Thus when filesystem has
> > more devices (or admin wants to add more devices later), it can be larger
> > than the first device. But I'm not really a btrfs developper so I might be
> > wrong and of course feel free to fix the issue as you deem fit.
>
> The size of the fs is the total size of the individual disks. When you
> limit the size, you limit the size of a disk, not the whole fs. IIRC,
> mkfs initializes the fs on the first disk, which is why it was using that
> size as the size of the whole fs, and then adds the other disks after (
> which then add their size to the total fs size ).
OK, I missed that btrfs_add_to_fsid() increases total size of the
filesystem. So now I agree with you. New patch is attached. Thanks for your
review.
> It might be nice if
> mkfs could take sizes for each disk, but it only seems to take one size
> for the initial disk.
Yes, but I don't see a realistic usecase so I don't think it's really
worth the work.
Honza
--
Jan Kara <jack@suse.cz>
SUSE Labs, CR
>From e5f46872232520310c56327593c02ef6a7f5ea33 Mon Sep 17 00:00:00 2001
From: Jan Kara <jack@suse.cz>
Date: Fri, 10 Feb 2012 11:44:44 +0100
Subject: [PATCH] mkfs: Handle creation of filesystem larger than the first device
mkfs does not properly check requested size of the filesystem. Thus if the
requested size is larger than the first device, it happily creates larger
filesystem than a device it resides on which results in 'attemp to access
beyond end of device' messages from the kernel. So verify specified filesystem
size against the size of the first device.
CC: David Sterba <dsterba@suse.cz>
Signed-off-by: Jan Kara <jack@suse.cz>
2012-02-10 18:49:19 +08:00
|
|
|
exit(1);
|
|
|
|
}
|
2010-07-08 17:17:59 +08:00
|
|
|
} else {
|
2011-06-21 09:45:59 +08:00
|
|
|
fd = open_target(file);
|
2010-07-08 17:17:59 +08:00
|
|
|
if (fd < 0) {
|
2016-08-19 00:38:34 +08:00
|
|
|
error("unable to open %s: %s", file, strerror(errno));
|
2010-07-08 17:17:59 +08:00
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
|
2011-06-21 09:45:59 +08:00
|
|
|
source_dir_size = size_sourcedir(source_dir, sectorsize,
|
2010-07-08 17:17:59 +08:00
|
|
|
&num_of_meta_chunks, &size_of_data);
|
2011-06-21 09:45:59 +08:00
|
|
|
if(block_count < source_dir_size)
|
|
|
|
block_count = source_dir_size;
|
2015-11-07 01:12:44 +08:00
|
|
|
ret = zero_output_file(fd, block_count);
|
2010-07-08 17:17:59 +08:00
|
|
|
if (ret) {
|
2016-08-19 00:38:34 +08:00
|
|
|
error("unable to zero the output file");
|
2010-07-08 17:17:59 +08:00
|
|
|
exit(1);
|
|
|
|
}
|
2013-01-30 04:32:28 +08:00
|
|
|
/* our "device" is the new image file */
|
|
|
|
dev_block_count = block_count;
|
2007-03-21 08:35:03 +08:00
|
|
|
}
|
2013-01-20 02:06:21 +08:00
|
|
|
|
2013-09-05 14:53:34 +08:00
|
|
|
/* To create the first block group and chunk 0 in make_btrfs */
|
|
|
|
if (dev_block_count < BTRFS_MKFS_SYSTEM_GROUP_SIZE) {
|
2016-08-19 00:38:34 +08:00
|
|
|
error("device is too small to make filesystem, must be at least %llu",
|
|
|
|
(unsigned long long)BTRFS_MKFS_SYSTEM_GROUP_SIZE);
|
2013-09-05 14:53:34 +08:00
|
|
|
exit(1);
|
|
|
|
}
|
2013-01-20 02:06:21 +08:00
|
|
|
|
2008-12-06 01:21:31 +08:00
|
|
|
blocks[0] = BTRFS_SUPER_INFO_OFFSET;
|
|
|
|
for (i = 1; i < 7; i++) {
|
|
|
|
blocks[i] = BTRFS_SUPER_INFO_OFFSET + 1024 * 1024 +
|
2015-02-02 22:51:15 +08:00
|
|
|
nodesize * i;
|
2008-12-06 01:21:31 +08:00
|
|
|
}
|
2008-02-16 00:19:26 +08:00
|
|
|
|
2015-05-30 22:54:48 +08:00
|
|
|
if (group_profile_max_safe_loss(metadata_profile) <
|
|
|
|
group_profile_max_safe_loss(data_profile)){
|
2016-08-19 00:38:34 +08:00
|
|
|
warning("metadata has lower redundancy than data!\n");
|
2015-05-30 22:54:48 +08:00
|
|
|
}
|
|
|
|
|
2015-07-01 23:49:21 +08:00
|
|
|
mkfs_cfg.label = label;
|
|
|
|
mkfs_cfg.fs_uuid = fs_uuid;
|
|
|
|
memcpy(mkfs_cfg.blocks, blocks, sizeof(blocks));
|
|
|
|
mkfs_cfg.num_bytes = dev_block_count;
|
|
|
|
mkfs_cfg.nodesize = nodesize;
|
|
|
|
mkfs_cfg.sectorsize = sectorsize;
|
|
|
|
mkfs_cfg.stripesize = stripesize;
|
|
|
|
mkfs_cfg.features = features;
|
|
|
|
|
2016-01-29 13:03:14 +08:00
|
|
|
ret = make_btrfs(fd, &mkfs_cfg, NULL);
|
2007-03-21 08:35:03 +08:00
|
|
|
if (ret) {
|
2016-08-19 00:38:34 +08:00
|
|
|
error("error during mkfs: %s", strerror(-ret));
|
2007-03-21 08:35:03 +08:00
|
|
|
exit(1);
|
|
|
|
}
|
2011-12-13 02:00:25 +08:00
|
|
|
|
2016-08-22 22:32:24 +08:00
|
|
|
root = open_ctree(file, 0, OPEN_CTREE_WRITES | OPEN_CTREE_FS_PARTIAL);
|
2011-12-13 02:00:25 +08:00
|
|
|
if (!root) {
|
2016-08-19 00:38:34 +08:00
|
|
|
error("open ctree failed");
|
2013-01-21 23:57:25 +08:00
|
|
|
close(fd);
|
2011-12-13 02:00:25 +08:00
|
|
|
exit(1);
|
|
|
|
}
|
2008-09-24 00:29:10 +08:00
|
|
|
root->fs_info->alloc_start = alloc_start;
|
|
|
|
|
Revert "btrfs-progs: mkfs: create only desired block groups for single device"
This reverts commit 5f8232e5c8f0b0de0ef426274911385b0e877392.
This commit causes a regression:
$ mkfs.btrfs -f /dev/sda6
$ btrfsck /dev/sda6
Checking filesystem on /dev/sda6
UUID: 2ebb483c-1986-4610-802a-c6f3e6ab4b76
checking extents
Chunk[256, 228, 0]: length(4194304), offset(0), type(2) mismatch with
block group[0, 192, 4194304]: offset(4194304), objectid(0), flags(34)
Chunk[256, 228, 4194304]: length(8388608), offset(4194304), type(4)
mismatch with block group[4194304, 192, 8388608]: offset(8388608),
objectid(4194304), flags(36)
Block group[0, 4194304] (flags = 34) didn't find the relative chunk.
Block group[4194304, 8388608] (flags = 36) didn't find the relative
chunk.
......
The commit has the following bug causing the problem.
1) Typo forgets to add meta/data_profile for alloc_chunk.
Only meta/data_profile is added to allocate a block group, but not
chunk.
2) Type for the first system chunk is impossible to modify yet.
The type for the first chunk and its stripe is hard coded into
make_btrfs() function.
So even we try to modify the type of the block group, we are unable to
change the type of the first chunk.
Causing the chunk type mismatch problem.
The 1st bug can be fixed quite easily but the second is not.
The good news is, the last patch "btrfs-progs: mkfs: Cleanup temporary
chunk to avoid strange balance behavior." from my patchset can handle it
quite well alone.
So just revert the patch.
New bug fix for btrfsck(err is 0 even chunk/extent tree is corrupted) and
new test cases for mkfs will follow soon.
Signed-off-by: Qu Wenruo <quwenruo@cn.fujitsu.com>
Signed-off-by: David Sterba <dsterba@suse.com>
2015-07-14 10:13:01 +08:00
|
|
|
ret = create_metadata_block_groups(root, mixed, &allocation);
|
2015-07-02 01:12:38 +08:00
|
|
|
if (ret) {
|
2016-08-19 00:38:34 +08:00
|
|
|
error("failed to create default block groups: %d", ret);
|
2015-07-02 01:12:38 +08:00
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
|
2015-07-02 01:15:35 +08:00
|
|
|
trans = btrfs_start_transaction(root, 1);
|
2015-07-11 06:18:21 +08:00
|
|
|
if (!trans) {
|
2016-08-19 00:38:34 +08:00
|
|
|
error("failed to start transaction");
|
2015-07-11 06:18:21 +08:00
|
|
|
exit(1);
|
|
|
|
}
|
2015-07-02 01:15:35 +08:00
|
|
|
|
Revert "btrfs-progs: mkfs: create only desired block groups for single device"
This reverts commit 5f8232e5c8f0b0de0ef426274911385b0e877392.
This commit causes a regression:
$ mkfs.btrfs -f /dev/sda6
$ btrfsck /dev/sda6
Checking filesystem on /dev/sda6
UUID: 2ebb483c-1986-4610-802a-c6f3e6ab4b76
checking extents
Chunk[256, 228, 0]: length(4194304), offset(0), type(2) mismatch with
block group[0, 192, 4194304]: offset(4194304), objectid(0), flags(34)
Chunk[256, 228, 4194304]: length(8388608), offset(4194304), type(4)
mismatch with block group[4194304, 192, 8388608]: offset(8388608),
objectid(4194304), flags(36)
Block group[0, 4194304] (flags = 34) didn't find the relative chunk.
Block group[4194304, 8388608] (flags = 36) didn't find the relative
chunk.
......
The commit has the following bug causing the problem.
1) Typo forgets to add meta/data_profile for alloc_chunk.
Only meta/data_profile is added to allocate a block group, but not
chunk.
2) Type for the first system chunk is impossible to modify yet.
The type for the first chunk and its stripe is hard coded into
make_btrfs() function.
So even we try to modify the type of the block group, we are unable to
change the type of the first chunk.
Causing the chunk type mismatch problem.
The 1st bug can be fixed quite easily but the second is not.
The good news is, the last patch "btrfs-progs: mkfs: Cleanup temporary
chunk to avoid strange balance behavior." from my patchset can handle it
quite well alone.
So just revert the patch.
New bug fix for btrfsck(err is 0 even chunk/extent tree is corrupted) and
new test cases for mkfs will follow soon.
Signed-off-by: Qu Wenruo <quwenruo@cn.fujitsu.com>
Signed-off-by: David Sterba <dsterba@suse.com>
2015-07-14 10:13:01 +08:00
|
|
|
ret = create_data_block_groups(trans, root, mixed, &allocation);
|
2015-07-02 01:19:05 +08:00
|
|
|
if (ret) {
|
2016-08-19 00:38:34 +08:00
|
|
|
error("failed to create default data block groups: %d", ret);
|
2015-07-02 01:19:05 +08:00
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
|
2015-10-15 01:39:37 +08:00
|
|
|
ret = make_root_dir(trans, root, &allocation);
|
2007-03-21 23:13:29 +08:00
|
|
|
if (ret) {
|
2016-08-19 00:38:34 +08:00
|
|
|
error("failed to setup the root directory: %d", ret);
|
2007-03-21 23:13:29 +08:00
|
|
|
exit(1);
|
|
|
|
}
|
2008-09-24 00:29:10 +08:00
|
|
|
|
2016-08-23 00:18:14 +08:00
|
|
|
ret = btrfs_commit_transaction(trans, root);
|
|
|
|
if (ret) {
|
|
|
|
error("unable to commit transaction: %d", ret);
|
|
|
|
goto out;
|
|
|
|
}
|
2015-07-02 01:15:35 +08:00
|
|
|
|
2008-04-04 04:35:48 +08:00
|
|
|
trans = btrfs_start_transaction(root, 1);
|
2015-07-11 06:18:21 +08:00
|
|
|
if (!trans) {
|
2016-08-19 00:38:34 +08:00
|
|
|
error("failed to start transaction");
|
2015-07-11 06:18:21 +08:00
|
|
|
exit(1);
|
|
|
|
}
|
2008-04-04 04:35:48 +08:00
|
|
|
|
2013-04-15 14:38:09 +08:00
|
|
|
if (dev_cnt == 0)
|
Revert "btrfs-progs: mkfs: create only desired block groups for single device"
This reverts commit 5f8232e5c8f0b0de0ef426274911385b0e877392.
This commit causes a regression:
$ mkfs.btrfs -f /dev/sda6
$ btrfsck /dev/sda6
Checking filesystem on /dev/sda6
UUID: 2ebb483c-1986-4610-802a-c6f3e6ab4b76
checking extents
Chunk[256, 228, 0]: length(4194304), offset(0), type(2) mismatch with
block group[0, 192, 4194304]: offset(4194304), objectid(0), flags(34)
Chunk[256, 228, 4194304]: length(8388608), offset(4194304), type(4)
mismatch with block group[4194304, 192, 8388608]: offset(8388608),
objectid(4194304), flags(36)
Block group[0, 4194304] (flags = 34) didn't find the relative chunk.
Block group[4194304, 8388608] (flags = 36) didn't find the relative
chunk.
......
The commit has the following bug causing the problem.
1) Typo forgets to add meta/data_profile for alloc_chunk.
Only meta/data_profile is added to allocate a block group, but not
chunk.
2) Type for the first system chunk is impossible to modify yet.
The type for the first chunk and its stripe is hard coded into
make_btrfs() function.
So even we try to modify the type of the block group, we are unable to
change the type of the first chunk.
Causing the chunk type mismatch problem.
The 1st bug can be fixed quite easily but the second is not.
The good news is, the last patch "btrfs-progs: mkfs: Cleanup temporary
chunk to avoid strange balance behavior." from my patchset can handle it
quite well alone.
So just revert the patch.
New bug fix for btrfsck(err is 0 even chunk/extent tree is corrupted) and
new test cases for mkfs will follow soon.
Signed-off-by: Qu Wenruo <quwenruo@cn.fujitsu.com>
Signed-off-by: David Sterba <dsterba@suse.com>
2015-07-14 10:13:01 +08:00
|
|
|
goto raid_groups;
|
2008-03-25 03:04:49 +08:00
|
|
|
|
2013-04-15 14:38:09 +08:00
|
|
|
while (dev_cnt-- > 0) {
|
2016-03-01 23:28:11 +08:00
|
|
|
file = argv[optind++];
|
2013-02-15 02:30:03 +08:00
|
|
|
|
2013-02-14 15:53:04 +08:00
|
|
|
/*
|
2013-04-15 14:38:09 +08:00
|
|
|
* open without O_EXCL so that the problem should not
|
2013-02-14 15:53:04 +08:00
|
|
|
* occur by the following processing.
|
|
|
|
* (btrfs_register_one_device() fails if O_EXCL is on)
|
|
|
|
*/
|
2008-03-25 03:04:49 +08:00
|
|
|
fd = open(file, O_RDWR);
|
|
|
|
if (fd < 0) {
|
2016-08-19 00:38:34 +08:00
|
|
|
error("unable to open %s: %s", file, strerror(errno));
|
2008-03-25 03:04:49 +08:00
|
|
|
exit(1);
|
|
|
|
}
|
2008-04-18 22:45:17 +08:00
|
|
|
ret = btrfs_device_already_in_root(root, fd,
|
|
|
|
BTRFS_SUPER_INFO_OFFSET);
|
|
|
|
if (ret) {
|
2016-08-19 00:38:34 +08:00
|
|
|
error("skipping duplicate device %s in the filesystem",
|
2008-04-18 22:45:17 +08:00
|
|
|
file);
|
|
|
|
close(fd);
|
|
|
|
continue;
|
|
|
|
}
|
2016-07-28 07:47:40 +08:00
|
|
|
ret = btrfs_prepare_device(fd, file, &dev_block_count,
|
|
|
|
block_count,
|
|
|
|
(verbose ? PREP_DEVICE_VERBOSE : 0) |
|
|
|
|
(zero_end ? PREP_DEVICE_ZERO_END : 0) |
|
|
|
|
(discard ? PREP_DEVICE_DISCARD : 0));
|
2013-12-18 12:07:55 +08:00
|
|
|
if (ret) {
|
|
|
|
close(fd);
|
|
|
|
exit(1);
|
|
|
|
}
|
2008-03-25 03:04:49 +08:00
|
|
|
|
2008-04-18 22:31:42 +08:00
|
|
|
ret = btrfs_add_to_fsid(trans, root, fd, file, dev_block_count,
|
2008-03-25 03:04:49 +08:00
|
|
|
sectorsize, sectorsize, sectorsize);
|
2016-08-22 23:50:49 +08:00
|
|
|
if (ret) {
|
|
|
|
error("unable to add %s to filesystem: %d", file, ret);
|
|
|
|
goto out;
|
|
|
|
}
|
2015-06-06 07:39:26 +08:00
|
|
|
if (verbose >= 2) {
|
|
|
|
struct btrfs_device *device;
|
|
|
|
|
|
|
|
device = container_of(root->fs_info->fs_devices->devices.next,
|
|
|
|
struct btrfs_device, dev_list);
|
|
|
|
printf("adding device %s id %llu\n", file,
|
|
|
|
(unsigned long long)device->devid);
|
|
|
|
}
|
2008-03-25 03:04:49 +08:00
|
|
|
}
|
2008-04-04 04:35:48 +08:00
|
|
|
|
Revert "btrfs-progs: mkfs: create only desired block groups for single device"
This reverts commit 5f8232e5c8f0b0de0ef426274911385b0e877392.
This commit causes a regression:
$ mkfs.btrfs -f /dev/sda6
$ btrfsck /dev/sda6
Checking filesystem on /dev/sda6
UUID: 2ebb483c-1986-4610-802a-c6f3e6ab4b76
checking extents
Chunk[256, 228, 0]: length(4194304), offset(0), type(2) mismatch with
block group[0, 192, 4194304]: offset(4194304), objectid(0), flags(34)
Chunk[256, 228, 4194304]: length(8388608), offset(4194304), type(4)
mismatch with block group[4194304, 192, 8388608]: offset(8388608),
objectid(4194304), flags(36)
Block group[0, 4194304] (flags = 34) didn't find the relative chunk.
Block group[4194304, 8388608] (flags = 36) didn't find the relative
chunk.
......
The commit has the following bug causing the problem.
1) Typo forgets to add meta/data_profile for alloc_chunk.
Only meta/data_profile is added to allocate a block group, but not
chunk.
2) Type for the first system chunk is impossible to modify yet.
The type for the first chunk and its stripe is hard coded into
make_btrfs() function.
So even we try to modify the type of the block group, we are unable to
change the type of the first chunk.
Causing the chunk type mismatch problem.
The 1st bug can be fixed quite easily but the second is not.
The good news is, the last patch "btrfs-progs: mkfs: Cleanup temporary
chunk to avoid strange balance behavior." from my patchset can handle it
quite well alone.
So just revert the patch.
New bug fix for btrfsck(err is 0 even chunk/extent tree is corrupted) and
new test cases for mkfs will follow soon.
Signed-off-by: Qu Wenruo <quwenruo@cn.fujitsu.com>
Signed-off-by: David Sterba <dsterba@suse.com>
2015-07-14 10:13:01 +08:00
|
|
|
raid_groups:
|
2010-07-08 17:17:59 +08:00
|
|
|
if (!source_dir_set) {
|
|
|
|
ret = create_raid_groups(trans, root, data_profile,
|
2015-07-03 01:23:27 +08:00
|
|
|
metadata_profile, mixed, &allocation);
|
2016-08-22 23:50:49 +08:00
|
|
|
if (ret) {
|
|
|
|
error("unable to create raid groups: %d", ret);
|
|
|
|
goto out;
|
|
|
|
}
|
2010-07-08 17:17:59 +08:00
|
|
|
}
|
2008-04-23 02:06:31 +08:00
|
|
|
|
2008-09-26 22:26:53 +08:00
|
|
|
ret = create_data_reloc_tree(trans, root);
|
2016-08-22 23:50:49 +08:00
|
|
|
if (ret) {
|
|
|
|
error("unable to create data reloc tree: %d", ret);
|
|
|
|
goto out;
|
|
|
|
}
|
2008-09-26 22:26:53 +08:00
|
|
|
|
2016-08-23 00:18:14 +08:00
|
|
|
ret = btrfs_commit_transaction(trans, root);
|
|
|
|
if (ret) {
|
|
|
|
error("unable to commit transaction: %d", ret);
|
|
|
|
goto out;
|
|
|
|
}
|
2010-07-08 17:17:59 +08:00
|
|
|
|
|
|
|
if (source_dir_set) {
|
|
|
|
trans = btrfs_start_transaction(root, 1);
|
|
|
|
ret = create_chunks(trans, root,
|
2015-06-08 18:54:54 +08:00
|
|
|
num_of_meta_chunks, size_of_data,
|
|
|
|
&allocation);
|
2016-08-22 23:50:49 +08:00
|
|
|
if (ret) {
|
|
|
|
error("unable to create chunks: %d", ret);
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
ret = btrfs_commit_transaction(trans, root);
|
|
|
|
if (ret) {
|
|
|
|
error("transaction commit failed: %d", ret);
|
|
|
|
goto out;
|
|
|
|
}
|
2010-07-08 17:17:59 +08:00
|
|
|
|
|
|
|
ret = make_image(source_dir, root, fd);
|
2016-08-22 23:50:49 +08:00
|
|
|
if (ret) {
|
|
|
|
error("error wihle filling filesystem: %d", ret);
|
|
|
|
goto out;
|
|
|
|
}
|
2010-07-08 17:17:59 +08:00
|
|
|
}
|
btrfs-progs: mkfs: Cleanup temporary chunk to avoid strange balance behavior.
[BUG]
# mkfs.btrfs /dev/sdb /dev/sdd -m raid0 -d raid0
# mount /dev/sdb /mnt/btrfs
# btrfs balance start /mnt/btrfs
# btrfs fi df /mnt/btrfs
Data, single: total=1.00GiB, used=320.00KiB
System, single: total=32.00MiB, used=16.00KiB
Metadata, RAID0: total=256.00MiB, used=112.00KiB
GlobalReserve, single: total=16.00MiB, used=0.00B
Only metadata stay RAID0. Data and system goes from RAID0 to single.
[REASON]
The problem is caused by the temporary single chunk.
In mkfs, it will always create single data/metadata/sys chunk and them
add device into the temporary btrfs.
When doing all chunk balance, for data and syschunk, they are almost
empty, so balance will move them into the single chunk and remove the
old RAID0 chunk.
For metadata, it has more data and will kick the metadata chunk pre
alloc, so new RAID0 chunk is allocated and the old metadata is move
there. Old RAID0 and single chunks are removed.
[FIX]
Now we add a new function to cleanup the temporary chunks at the end of
mkfs routine.
It will cleanup the chunks which is empty and its profile differs from
the mkfs profile.
So in balance, btrfs will always alloc a new chunk to keep the profile,
other than moving data into the single chunk.
Signed-off-by: Qu Wenruo <quwenruo@cn.fujitsu.com>
Signed-off-by: David Sterba <dsterba@suse.com>
2015-07-07 16:15:28 +08:00
|
|
|
ret = cleanup_temp_chunks(root->fs_info, &allocation, data_profile,
|
|
|
|
metadata_profile, metadata_profile);
|
|
|
|
if (ret < 0) {
|
2016-08-19 00:38:34 +08:00
|
|
|
error("failed to cleanup temporary chunks: %d", ret);
|
btrfs-progs: mkfs: Cleanup temporary chunk to avoid strange balance behavior.
[BUG]
# mkfs.btrfs /dev/sdb /dev/sdd -m raid0 -d raid0
# mount /dev/sdb /mnt/btrfs
# btrfs balance start /mnt/btrfs
# btrfs fi df /mnt/btrfs
Data, single: total=1.00GiB, used=320.00KiB
System, single: total=32.00MiB, used=16.00KiB
Metadata, RAID0: total=256.00MiB, used=112.00KiB
GlobalReserve, single: total=16.00MiB, used=0.00B
Only metadata stay RAID0. Data and system goes from RAID0 to single.
[REASON]
The problem is caused by the temporary single chunk.
In mkfs, it will always create single data/metadata/sys chunk and them
add device into the temporary btrfs.
When doing all chunk balance, for data and syschunk, they are almost
empty, so balance will move them into the single chunk and remove the
old RAID0 chunk.
For metadata, it has more data and will kick the metadata chunk pre
alloc, so new RAID0 chunk is allocated and the old metadata is move
there. Old RAID0 and single chunks are removed.
[FIX]
Now we add a new function to cleanup the temporary chunks at the end of
mkfs routine.
It will cleanup the chunks which is empty and its profile differs from
the mkfs profile.
So in balance, btrfs will always alloc a new chunk to keep the profile,
other than moving data into the single chunk.
Signed-off-by: Qu Wenruo <quwenruo@cn.fujitsu.com>
Signed-off-by: David Sterba <dsterba@suse.com>
2015-07-07 16:15:28 +08:00
|
|
|
goto out;
|
|
|
|
}
|
2010-07-08 17:17:59 +08:00
|
|
|
|
btrfs-progs: mkfs: print the summary
This patch prints the summary of the filesystem after the creation.
The main fileds printed are:
- devices list with their uuid, devid, path and size
- raid profile (dup,single,raid0...)
- leafsize/nodesize/sectorsize
- filesystem features (raid56, extref, mixed-bg)
- chunk size and type
If the '-v' switched is passed, the output is more verbose; if the '-q'
switched is passed, only the errors are printed.
Below an example:
BTRFS filesystem summary:
Label: btrfs-test
UUID: 14ae8a88-98ac-4f22-8441-79f76ec622f7
Node size: 4096
Leaf size: 4096
Sector size: 4096
Initial chunks:
Data+Metadata: 9.01GiB
System: 18.06MiB
Metadata profile: RAID5
Data profile: RAID5
Mixed mode: YES
SSD detected: NO
Incompat features: mixed-bg, extref, raid56
Number of devices: 10
UUID ID SIZE PATH
------------------------------------ -- --------- -----------
df1c7f50-1980-4da2-8bc9-7ee6ffb0b554 1 50.00GiB /dev/vdb
32c808a0-cd7b-4497-a2c0-1d77a9854af9 2 50.00GiB /dev/vdc
3159782e-d108-40bc-9e15-090ecac160b4 3 50.00GiB /dev/vdd
db7eaf0c-beb8-4093-a9d0-b9c25c146305 4 50.00GiB /dev/vde
c367ca04-1f71-49c0-a331-11fc0b87e9fc 5 50.00GiB /dev/vdf
e9b73c86-4058-4b3a-90ac-18741a276e70 6 50.00GiB /dev/vdg
c4298b7a-ad41-4690-bf10-bf748b319413 7 50.00GiB /dev/vdh
1cf048c8-af8a-4225-b09a-5d12e9b217fa 8 2.00GiB /dev/vdi
7e157869-768a-4725-bad5-82e6bd05fd17 9 2.00GiB /dev/vdj
2c9431ac-c7f0-45a5-8529-cef8cf6e4033 10 2.00GiB /dev/vdk
Total devices size: 356.01GiB
Signed-off-by: Goffredo Baroncelli <kreijack@inwind.it>
Signed-off-by: David Sterba <dsterba@suse.cz>
2015-06-08 19:00:50 +08:00
|
|
|
if (verbose) {
|
|
|
|
char features_buf[64];
|
|
|
|
|
2015-06-08 22:26:54 +08:00
|
|
|
printf("Label: %s\n", label);
|
|
|
|
printf("UUID: %s\n", fs_uuid);
|
|
|
|
printf("Node size: %u\n", nodesize);
|
|
|
|
printf("Sector size: %u\n", sectorsize);
|
|
|
|
printf("Filesystem size: %s\n",
|
|
|
|
pretty_size(btrfs_super_total_bytes(root->fs_info->super_copy)));
|
|
|
|
printf("Block group profiles:\n");
|
btrfs-progs: mkfs: print the summary
This patch prints the summary of the filesystem after the creation.
The main fileds printed are:
- devices list with their uuid, devid, path and size
- raid profile (dup,single,raid0...)
- leafsize/nodesize/sectorsize
- filesystem features (raid56, extref, mixed-bg)
- chunk size and type
If the '-v' switched is passed, the output is more verbose; if the '-q'
switched is passed, only the errors are printed.
Below an example:
BTRFS filesystem summary:
Label: btrfs-test
UUID: 14ae8a88-98ac-4f22-8441-79f76ec622f7
Node size: 4096
Leaf size: 4096
Sector size: 4096
Initial chunks:
Data+Metadata: 9.01GiB
System: 18.06MiB
Metadata profile: RAID5
Data profile: RAID5
Mixed mode: YES
SSD detected: NO
Incompat features: mixed-bg, extref, raid56
Number of devices: 10
UUID ID SIZE PATH
------------------------------------ -- --------- -----------
df1c7f50-1980-4da2-8bc9-7ee6ffb0b554 1 50.00GiB /dev/vdb
32c808a0-cd7b-4497-a2c0-1d77a9854af9 2 50.00GiB /dev/vdc
3159782e-d108-40bc-9e15-090ecac160b4 3 50.00GiB /dev/vdd
db7eaf0c-beb8-4093-a9d0-b9c25c146305 4 50.00GiB /dev/vde
c367ca04-1f71-49c0-a331-11fc0b87e9fc 5 50.00GiB /dev/vdf
e9b73c86-4058-4b3a-90ac-18741a276e70 6 50.00GiB /dev/vdg
c4298b7a-ad41-4690-bf10-bf748b319413 7 50.00GiB /dev/vdh
1cf048c8-af8a-4225-b09a-5d12e9b217fa 8 2.00GiB /dev/vdi
7e157869-768a-4725-bad5-82e6bd05fd17 9 2.00GiB /dev/vdj
2c9431ac-c7f0-45a5-8529-cef8cf6e4033 10 2.00GiB /dev/vdk
Total devices size: 356.01GiB
Signed-off-by: Goffredo Baroncelli <kreijack@inwind.it>
Signed-off-by: David Sterba <dsterba@suse.cz>
2015-06-08 19:00:50 +08:00
|
|
|
if (allocation.data)
|
2015-06-08 22:26:54 +08:00
|
|
|
printf(" Data: %-8s %16s\n",
|
|
|
|
btrfs_group_profile_str(data_profile),
|
btrfs-progs: mkfs: print the summary
This patch prints the summary of the filesystem after the creation.
The main fileds printed are:
- devices list with their uuid, devid, path and size
- raid profile (dup,single,raid0...)
- leafsize/nodesize/sectorsize
- filesystem features (raid56, extref, mixed-bg)
- chunk size and type
If the '-v' switched is passed, the output is more verbose; if the '-q'
switched is passed, only the errors are printed.
Below an example:
BTRFS filesystem summary:
Label: btrfs-test
UUID: 14ae8a88-98ac-4f22-8441-79f76ec622f7
Node size: 4096
Leaf size: 4096
Sector size: 4096
Initial chunks:
Data+Metadata: 9.01GiB
System: 18.06MiB
Metadata profile: RAID5
Data profile: RAID5
Mixed mode: YES
SSD detected: NO
Incompat features: mixed-bg, extref, raid56
Number of devices: 10
UUID ID SIZE PATH
------------------------------------ -- --------- -----------
df1c7f50-1980-4da2-8bc9-7ee6ffb0b554 1 50.00GiB /dev/vdb
32c808a0-cd7b-4497-a2c0-1d77a9854af9 2 50.00GiB /dev/vdc
3159782e-d108-40bc-9e15-090ecac160b4 3 50.00GiB /dev/vdd
db7eaf0c-beb8-4093-a9d0-b9c25c146305 4 50.00GiB /dev/vde
c367ca04-1f71-49c0-a331-11fc0b87e9fc 5 50.00GiB /dev/vdf
e9b73c86-4058-4b3a-90ac-18741a276e70 6 50.00GiB /dev/vdg
c4298b7a-ad41-4690-bf10-bf748b319413 7 50.00GiB /dev/vdh
1cf048c8-af8a-4225-b09a-5d12e9b217fa 8 2.00GiB /dev/vdi
7e157869-768a-4725-bad5-82e6bd05fd17 9 2.00GiB /dev/vdj
2c9431ac-c7f0-45a5-8529-cef8cf6e4033 10 2.00GiB /dev/vdk
Total devices size: 356.01GiB
Signed-off-by: Goffredo Baroncelli <kreijack@inwind.it>
Signed-off-by: David Sterba <dsterba@suse.cz>
2015-06-08 19:00:50 +08:00
|
|
|
pretty_size(allocation.data));
|
|
|
|
if (allocation.metadata)
|
2015-06-08 22:26:54 +08:00
|
|
|
printf(" Metadata: %-8s %16s\n",
|
|
|
|
btrfs_group_profile_str(metadata_profile),
|
btrfs-progs: mkfs: print the summary
This patch prints the summary of the filesystem after the creation.
The main fileds printed are:
- devices list with their uuid, devid, path and size
- raid profile (dup,single,raid0...)
- leafsize/nodesize/sectorsize
- filesystem features (raid56, extref, mixed-bg)
- chunk size and type
If the '-v' switched is passed, the output is more verbose; if the '-q'
switched is passed, only the errors are printed.
Below an example:
BTRFS filesystem summary:
Label: btrfs-test
UUID: 14ae8a88-98ac-4f22-8441-79f76ec622f7
Node size: 4096
Leaf size: 4096
Sector size: 4096
Initial chunks:
Data+Metadata: 9.01GiB
System: 18.06MiB
Metadata profile: RAID5
Data profile: RAID5
Mixed mode: YES
SSD detected: NO
Incompat features: mixed-bg, extref, raid56
Number of devices: 10
UUID ID SIZE PATH
------------------------------------ -- --------- -----------
df1c7f50-1980-4da2-8bc9-7ee6ffb0b554 1 50.00GiB /dev/vdb
32c808a0-cd7b-4497-a2c0-1d77a9854af9 2 50.00GiB /dev/vdc
3159782e-d108-40bc-9e15-090ecac160b4 3 50.00GiB /dev/vdd
db7eaf0c-beb8-4093-a9d0-b9c25c146305 4 50.00GiB /dev/vde
c367ca04-1f71-49c0-a331-11fc0b87e9fc 5 50.00GiB /dev/vdf
e9b73c86-4058-4b3a-90ac-18741a276e70 6 50.00GiB /dev/vdg
c4298b7a-ad41-4690-bf10-bf748b319413 7 50.00GiB /dev/vdh
1cf048c8-af8a-4225-b09a-5d12e9b217fa 8 2.00GiB /dev/vdi
7e157869-768a-4725-bad5-82e6bd05fd17 9 2.00GiB /dev/vdj
2c9431ac-c7f0-45a5-8529-cef8cf6e4033 10 2.00GiB /dev/vdk
Total devices size: 356.01GiB
Signed-off-by: Goffredo Baroncelli <kreijack@inwind.it>
Signed-off-by: David Sterba <dsterba@suse.cz>
2015-06-08 19:00:50 +08:00
|
|
|
pretty_size(allocation.metadata));
|
|
|
|
if (allocation.mixed)
|
2015-06-08 22:26:54 +08:00
|
|
|
printf(" Data+Metadata: %-8s %16s\n",
|
|
|
|
btrfs_group_profile_str(data_profile),
|
btrfs-progs: mkfs: print the summary
This patch prints the summary of the filesystem after the creation.
The main fileds printed are:
- devices list with their uuid, devid, path and size
- raid profile (dup,single,raid0...)
- leafsize/nodesize/sectorsize
- filesystem features (raid56, extref, mixed-bg)
- chunk size and type
If the '-v' switched is passed, the output is more verbose; if the '-q'
switched is passed, only the errors are printed.
Below an example:
BTRFS filesystem summary:
Label: btrfs-test
UUID: 14ae8a88-98ac-4f22-8441-79f76ec622f7
Node size: 4096
Leaf size: 4096
Sector size: 4096
Initial chunks:
Data+Metadata: 9.01GiB
System: 18.06MiB
Metadata profile: RAID5
Data profile: RAID5
Mixed mode: YES
SSD detected: NO
Incompat features: mixed-bg, extref, raid56
Number of devices: 10
UUID ID SIZE PATH
------------------------------------ -- --------- -----------
df1c7f50-1980-4da2-8bc9-7ee6ffb0b554 1 50.00GiB /dev/vdb
32c808a0-cd7b-4497-a2c0-1d77a9854af9 2 50.00GiB /dev/vdc
3159782e-d108-40bc-9e15-090ecac160b4 3 50.00GiB /dev/vdd
db7eaf0c-beb8-4093-a9d0-b9c25c146305 4 50.00GiB /dev/vde
c367ca04-1f71-49c0-a331-11fc0b87e9fc 5 50.00GiB /dev/vdf
e9b73c86-4058-4b3a-90ac-18741a276e70 6 50.00GiB /dev/vdg
c4298b7a-ad41-4690-bf10-bf748b319413 7 50.00GiB /dev/vdh
1cf048c8-af8a-4225-b09a-5d12e9b217fa 8 2.00GiB /dev/vdi
7e157869-768a-4725-bad5-82e6bd05fd17 9 2.00GiB /dev/vdj
2c9431ac-c7f0-45a5-8529-cef8cf6e4033 10 2.00GiB /dev/vdk
Total devices size: 356.01GiB
Signed-off-by: Goffredo Baroncelli <kreijack@inwind.it>
Signed-off-by: David Sterba <dsterba@suse.cz>
2015-06-08 19:00:50 +08:00
|
|
|
pretty_size(allocation.mixed));
|
2015-06-08 22:26:54 +08:00
|
|
|
printf(" System: %-8s %16s\n",
|
|
|
|
btrfs_group_profile_str(metadata_profile),
|
btrfs-progs: mkfs: print the summary
This patch prints the summary of the filesystem after the creation.
The main fileds printed are:
- devices list with their uuid, devid, path and size
- raid profile (dup,single,raid0...)
- leafsize/nodesize/sectorsize
- filesystem features (raid56, extref, mixed-bg)
- chunk size and type
If the '-v' switched is passed, the output is more verbose; if the '-q'
switched is passed, only the errors are printed.
Below an example:
BTRFS filesystem summary:
Label: btrfs-test
UUID: 14ae8a88-98ac-4f22-8441-79f76ec622f7
Node size: 4096
Leaf size: 4096
Sector size: 4096
Initial chunks:
Data+Metadata: 9.01GiB
System: 18.06MiB
Metadata profile: RAID5
Data profile: RAID5
Mixed mode: YES
SSD detected: NO
Incompat features: mixed-bg, extref, raid56
Number of devices: 10
UUID ID SIZE PATH
------------------------------------ -- --------- -----------
df1c7f50-1980-4da2-8bc9-7ee6ffb0b554 1 50.00GiB /dev/vdb
32c808a0-cd7b-4497-a2c0-1d77a9854af9 2 50.00GiB /dev/vdc
3159782e-d108-40bc-9e15-090ecac160b4 3 50.00GiB /dev/vdd
db7eaf0c-beb8-4093-a9d0-b9c25c146305 4 50.00GiB /dev/vde
c367ca04-1f71-49c0-a331-11fc0b87e9fc 5 50.00GiB /dev/vdf
e9b73c86-4058-4b3a-90ac-18741a276e70 6 50.00GiB /dev/vdg
c4298b7a-ad41-4690-bf10-bf748b319413 7 50.00GiB /dev/vdh
1cf048c8-af8a-4225-b09a-5d12e9b217fa 8 2.00GiB /dev/vdi
7e157869-768a-4725-bad5-82e6bd05fd17 9 2.00GiB /dev/vdj
2c9431ac-c7f0-45a5-8529-cef8cf6e4033 10 2.00GiB /dev/vdk
Total devices size: 356.01GiB
Signed-off-by: Goffredo Baroncelli <kreijack@inwind.it>
Signed-off-by: David Sterba <dsterba@suse.cz>
2015-06-08 19:00:50 +08:00
|
|
|
pretty_size(allocation.system));
|
2015-06-08 22:26:54 +08:00
|
|
|
printf("SSD detected: %s\n", ssd ? "yes" : "no");
|
btrfs-progs: mkfs: print the summary
This patch prints the summary of the filesystem after the creation.
The main fileds printed are:
- devices list with their uuid, devid, path and size
- raid profile (dup,single,raid0...)
- leafsize/nodesize/sectorsize
- filesystem features (raid56, extref, mixed-bg)
- chunk size and type
If the '-v' switched is passed, the output is more verbose; if the '-q'
switched is passed, only the errors are printed.
Below an example:
BTRFS filesystem summary:
Label: btrfs-test
UUID: 14ae8a88-98ac-4f22-8441-79f76ec622f7
Node size: 4096
Leaf size: 4096
Sector size: 4096
Initial chunks:
Data+Metadata: 9.01GiB
System: 18.06MiB
Metadata profile: RAID5
Data profile: RAID5
Mixed mode: YES
SSD detected: NO
Incompat features: mixed-bg, extref, raid56
Number of devices: 10
UUID ID SIZE PATH
------------------------------------ -- --------- -----------
df1c7f50-1980-4da2-8bc9-7ee6ffb0b554 1 50.00GiB /dev/vdb
32c808a0-cd7b-4497-a2c0-1d77a9854af9 2 50.00GiB /dev/vdc
3159782e-d108-40bc-9e15-090ecac160b4 3 50.00GiB /dev/vdd
db7eaf0c-beb8-4093-a9d0-b9c25c146305 4 50.00GiB /dev/vde
c367ca04-1f71-49c0-a331-11fc0b87e9fc 5 50.00GiB /dev/vdf
e9b73c86-4058-4b3a-90ac-18741a276e70 6 50.00GiB /dev/vdg
c4298b7a-ad41-4690-bf10-bf748b319413 7 50.00GiB /dev/vdh
1cf048c8-af8a-4225-b09a-5d12e9b217fa 8 2.00GiB /dev/vdi
7e157869-768a-4725-bad5-82e6bd05fd17 9 2.00GiB /dev/vdj
2c9431ac-c7f0-45a5-8529-cef8cf6e4033 10 2.00GiB /dev/vdk
Total devices size: 356.01GiB
Signed-off-by: Goffredo Baroncelli <kreijack@inwind.it>
Signed-off-by: David Sterba <dsterba@suse.cz>
2015-06-08 19:00:50 +08:00
|
|
|
btrfs_parse_features_to_string(features_buf, features);
|
2015-06-08 22:26:54 +08:00
|
|
|
printf("Incompat features: %s", features_buf);
|
btrfs-progs: mkfs: print the summary
This patch prints the summary of the filesystem after the creation.
The main fileds printed are:
- devices list with their uuid, devid, path and size
- raid profile (dup,single,raid0...)
- leafsize/nodesize/sectorsize
- filesystem features (raid56, extref, mixed-bg)
- chunk size and type
If the '-v' switched is passed, the output is more verbose; if the '-q'
switched is passed, only the errors are printed.
Below an example:
BTRFS filesystem summary:
Label: btrfs-test
UUID: 14ae8a88-98ac-4f22-8441-79f76ec622f7
Node size: 4096
Leaf size: 4096
Sector size: 4096
Initial chunks:
Data+Metadata: 9.01GiB
System: 18.06MiB
Metadata profile: RAID5
Data profile: RAID5
Mixed mode: YES
SSD detected: NO
Incompat features: mixed-bg, extref, raid56
Number of devices: 10
UUID ID SIZE PATH
------------------------------------ -- --------- -----------
df1c7f50-1980-4da2-8bc9-7ee6ffb0b554 1 50.00GiB /dev/vdb
32c808a0-cd7b-4497-a2c0-1d77a9854af9 2 50.00GiB /dev/vdc
3159782e-d108-40bc-9e15-090ecac160b4 3 50.00GiB /dev/vdd
db7eaf0c-beb8-4093-a9d0-b9c25c146305 4 50.00GiB /dev/vde
c367ca04-1f71-49c0-a331-11fc0b87e9fc 5 50.00GiB /dev/vdf
e9b73c86-4058-4b3a-90ac-18741a276e70 6 50.00GiB /dev/vdg
c4298b7a-ad41-4690-bf10-bf748b319413 7 50.00GiB /dev/vdh
1cf048c8-af8a-4225-b09a-5d12e9b217fa 8 2.00GiB /dev/vdi
7e157869-768a-4725-bad5-82e6bd05fd17 9 2.00GiB /dev/vdj
2c9431ac-c7f0-45a5-8529-cef8cf6e4033 10 2.00GiB /dev/vdk
Total devices size: 356.01GiB
Signed-off-by: Goffredo Baroncelli <kreijack@inwind.it>
Signed-off-by: David Sterba <dsterba@suse.cz>
2015-06-08 19:00:50 +08:00
|
|
|
printf("\n");
|
|
|
|
|
|
|
|
list_all_devices(root);
|
|
|
|
}
|
|
|
|
|
2016-08-22 22:32:24 +08:00
|
|
|
/*
|
|
|
|
* The filesystem is now fully set up, commit the remaining changes and
|
|
|
|
* fix the signature as the last step before closing the devices.
|
|
|
|
*/
|
|
|
|
root->fs_info->finalize_on_close = 1;
|
btrfs-progs: mkfs: Cleanup temporary chunk to avoid strange balance behavior.
[BUG]
# mkfs.btrfs /dev/sdb /dev/sdd -m raid0 -d raid0
# mount /dev/sdb /mnt/btrfs
# btrfs balance start /mnt/btrfs
# btrfs fi df /mnt/btrfs
Data, single: total=1.00GiB, used=320.00KiB
System, single: total=32.00MiB, used=16.00KiB
Metadata, RAID0: total=256.00MiB, used=112.00KiB
GlobalReserve, single: total=16.00MiB, used=0.00B
Only metadata stay RAID0. Data and system goes from RAID0 to single.
[REASON]
The problem is caused by the temporary single chunk.
In mkfs, it will always create single data/metadata/sys chunk and them
add device into the temporary btrfs.
When doing all chunk balance, for data and syschunk, they are almost
empty, so balance will move them into the single chunk and remove the
old RAID0 chunk.
For metadata, it has more data and will kick the metadata chunk pre
alloc, so new RAID0 chunk is allocated and the old metadata is move
there. Old RAID0 and single chunks are removed.
[FIX]
Now we add a new function to cleanup the temporary chunks at the end of
mkfs routine.
It will cleanup the chunks which is empty and its profile differs from
the mkfs profile.
So in balance, btrfs will always alloc a new chunk to keep the profile,
other than moving data into the single chunk.
Signed-off-by: Qu Wenruo <quwenruo@cn.fujitsu.com>
Signed-off-by: David Sterba <dsterba@suse.com>
2015-07-07 16:15:28 +08:00
|
|
|
out:
|
2008-03-25 03:04:49 +08:00
|
|
|
ret = close_ctree(root);
|
2016-08-22 22:31:11 +08:00
|
|
|
|
2016-08-22 23:50:49 +08:00
|
|
|
if (!ret) {
|
|
|
|
optind = saved_optind;
|
|
|
|
dev_cnt = argc - optind;
|
|
|
|
while (dev_cnt-- > 0) {
|
|
|
|
file = argv[optind++];
|
|
|
|
if (is_block_device(file) == 1)
|
|
|
|
btrfs_register_one_device(file);
|
|
|
|
}
|
2016-08-22 22:31:11 +08:00
|
|
|
}
|
|
|
|
|
2015-08-24 16:45:03 +08:00
|
|
|
btrfs_close_all_devices();
|
2008-04-23 02:06:31 +08:00
|
|
|
free(label);
|
2016-08-22 23:50:49 +08:00
|
|
|
|
|
|
|
return !!ret;
|
2007-03-21 08:35:03 +08:00
|
|
|
}
|