summaryrefslogtreecommitdiff
path: root/mkfs.c
diff options
context:
space:
mode:
Diffstat (limited to 'mkfs.c')
-rw-r--r--mkfs.c92
1 files changed, 74 insertions, 18 deletions
diff --git a/mkfs.c b/mkfs.c
index 7cd0c23c..9dd10d68 100644
--- a/mkfs.c
+++ b/mkfs.c
@@ -39,6 +39,7 @@
#include <linux/fs.h>
#include <ctype.h>
#include <attr/xattr.h>
+#include <blkid/blkid.h>
#include "ctree.h"
#include "disk-io.h"
#include "volumes.h"
@@ -204,7 +205,7 @@ static int create_one_raid_group(struct btrfs_trans_handle *trans,
static int create_raid_groups(struct btrfs_trans_handle *trans,
struct btrfs_root *root, u64 data_profile,
int data_profile_opt, u64 metadata_profile,
- int metadata_profile_opt, int mixed)
+ int metadata_profile_opt, int mixed, int ssd)
{
u64 num_devices = btrfs_super_num_devices(&root->fs_info->super_copy);
u64 allowed = 0;
@@ -216,8 +217,12 @@ static int create_raid_groups(struct btrfs_trans_handle *trans,
* For mixed groups defaults are single/single.
*/
if (!metadata_profile_opt && !mixed) {
+ if (num_devices == 1 && ssd)
+ printf("Detected a SSD, turning off metadata "
+ "duplication. Mkfs with -m dup if you want to "
+ "force metadata duplication.\n");
metadata_profile = (num_devices > 1) ?
- BTRFS_BLOCK_GROUP_RAID1 : BTRFS_BLOCK_GROUP_DUP;
+ BTRFS_BLOCK_GROUP_RAID1 : (ssd) ? 0: BTRFS_BLOCK_GROUP_DUP;
}
if (!data_profile_opt && !mixed) {
data_profile = (num_devices > 1) ?
@@ -366,7 +371,6 @@ static u64 parse_profile(char *s)
static char *parse_label(char *input)
{
- int i;
int len = strlen(input);
if (len >= BTRFS_LABEL_SIZE) {
@@ -374,12 +378,6 @@ static char *parse_label(char *input)
BTRFS_LABEL_SIZE - 1);
exit(1);
}
- for (i = 0; i < len; i++) {
- if (input[i] == '/' || input[i] == '\\') {
- fprintf(stderr, "invalid label %s\n", input);
- exit(1);
- }
- }
return strdup(input);
}
@@ -1207,6 +1205,54 @@ static int check_leaf_or_node_size(u32 size, u32 sectorsize)
return 0;
}
+static int is_ssd(const char *file)
+{
+ char *devname;
+ blkid_probe probe;
+ char *dev;
+ char path[PATH_MAX];
+ dev_t disk;
+ int fd;
+ char rotational;
+
+ probe = blkid_new_probe_from_filename(file);
+ if (!probe)
+ return 0;
+
+ /*
+ * We want to use blkid_devno_to_wholedisk() but it's broken for some
+ * reason on F17 at least so we'll do this trickery
+ */
+ disk = blkid_probe_get_wholedisk_devno(probe);
+ if (!disk)
+ return 0;
+
+ devname = blkid_devno_to_devname(disk);
+ if (!devname)
+ return 0;
+
+ dev = strrchr(devname, '/');
+ dev++;
+
+ snprintf(path, PATH_MAX, "/sys/block/%s/queue/rotational", dev);
+
+ free(devname);
+ blkid_free_probe(probe);
+
+ fd = open(path, O_RDONLY);
+ if (fd < 0) {
+ return 0;
+ }
+
+ if (read(fd, &rotational, sizeof(char)) < sizeof(char)) {
+ close(fd);
+ return 0;
+ }
+ close(fd);
+
+ return !atoi((const char *)&rotational);
+}
+
int main(int ac, char **av)
{
char *file;
@@ -1220,7 +1266,7 @@ int main(int ac, char **av)
u64 alloc_start = 0;
u64 metadata_profile = 0;
u64 data_profile = 0;
- u32 leafsize = getpagesize();
+ u32 leafsize = sysconf(_SC_PAGESIZE);
u32 sectorsize = 4096;
u32 nodesize = leafsize;
u32 stripesize = 4096;
@@ -1233,6 +1279,7 @@ int main(int ac, char **av)
int data_profile_opt = 0;
int metadata_profile_opt = 0;
int nodiscard = 0;
+ int ssd = 0;
char *source_dir = NULL;
int source_dir_set = 0;
@@ -1240,6 +1287,8 @@ int main(int ac, char **av)
u64 size_of_data = 0;
u64 source_dir_size = 0;
char *pretty_buf;
+ struct btrfs_super_block *super;
+ u64 flags;
while(1) {
int c;
@@ -1296,7 +1345,7 @@ int main(int ac, char **av)
print_usage();
}
}
- sectorsize = max(sectorsize, (u32)getpagesize());
+ sectorsize = max(sectorsize, (u32)sysconf(_SC_PAGESIZE));
if (check_leaf_or_node_size(leafsize, sectorsize))
exit(1);
if (check_leaf_or_node_size(nodesize, sectorsize))
@@ -1351,7 +1400,12 @@ int main(int ac, char **av)
fprintf(stderr, "unable to zero the output file\n");
exit(1);
}
+ /* our "device" is the new image file */
+ dev_block_count = block_count;
}
+
+ ssd = is_ssd(file);
+
if (mixed) {
if (metadata_profile != data_profile) {
fprintf(stderr, "With mixed block groups data and metadata "
@@ -1376,7 +1430,8 @@ int main(int ac, char **av)
root = open_ctree(file, 0, O_RDWR);
if (!root) {
- fprintf(stderr, "ctree init failed\n");
+ fprintf(stderr, "Open ctree failed\n");
+ close(fd);
exit(1);
}
root->fs_info->alloc_start = alloc_start;
@@ -1437,20 +1492,21 @@ raid_groups:
if (!source_dir_set) {
ret = create_raid_groups(trans, root, data_profile,
data_profile_opt, metadata_profile,
- metadata_profile_opt, mixed);
+ metadata_profile_opt, mixed, ssd);
BUG_ON(ret);
}
ret = create_data_reloc_tree(trans, root);
BUG_ON(ret);
- if (mixed) {
- struct btrfs_super_block *super = &root->fs_info->super_copy;
- u64 flags = btrfs_super_incompat_flags(super);
+ super = &root->fs_info->super_copy;
+ flags = btrfs_super_incompat_flags(super);
+ flags |= BTRFS_FEATURE_INCOMPAT_EXTENDED_IREF;
+ if (mixed)
flags |= BTRFS_FEATURE_INCOMPAT_MIXED_GROUPS;
- btrfs_set_super_incompat_flags(super, flags);
- }
+
+ btrfs_set_super_incompat_flags(super, flags);
if ((data_profile | metadata_profile) &
(BTRFS_BLOCK_GROUP_RAID5 | BTRFS_BLOCK_GROUP_RAID6)) {