When creating small Btrfs filesystem instances (i.e. filesystem size <= 1GiB),
mkfs.btrfs fails if both sectorsize and nodesize are specified on the command
line and sectorsize != nodesize, since mixed block groups involves both data
and metadata blocks sharing the same block group. This is an incorrect behavior
when '-M' option isn't specified on the command line.

This commit makes optional the creation of mixed block groups i.e. Mixed block
groups are created only when -M option is specified on the command line.

While at it, this commit fixes a bug which allowed creation of filesystem
instances with "mixed block group" feature enabled and having differing block
sizes for data and metadata. For e.g.

[root@localhost btrfs-progs]# ./mkfs.btrfs -f -M  -s 4096 -n 16384 /dev/loop6
SMALL VOLUME: forcing mixed metadata/data groups
btrfs-progs v3.19-rc2-404-g71f7308
See http://btrfs.wiki.kernel.org for more information.

Performing full device TRIM (4.00GiB) ...
Label:              (null)
UUID:               c82b5720-6d88-4fa1-ac05-d0d4cb797fd5
Node size:          16384
Sector size:        4096
Filesystem size:    4.00GiB
Block group profiles:
  Data+Metadata:    single            8.00MiB
  System:           single            4.00MiB
SSD detected:       no
Incompat features:  mixed-bg, extref, skinny-metadata
Number of devices:  1
Devices:
  ID        SIZE  PATH
   1     4.00GiB  /dev/loop6

Signed-off-by: Chandan Rajendra <chan...@linux.vnet.ibm.com>
---
 cmds-device.c  |  3 +--
 cmds-replace.c |  3 +--
 mkfs.c         | 45 ++++++++++++++++++++-------------------------
 utils.c        |  5 +----
 utils.h        |  2 +-
 5 files changed, 24 insertions(+), 34 deletions(-)

diff --git a/cmds-device.c b/cmds-device.c
index 5f2b952..1b601cf 100644
--- a/cmds-device.c
+++ b/cmds-device.c
@@ -92,7 +92,6 @@ static int cmd_device_add(int argc, char **argv)
                struct btrfs_ioctl_vol_args ioctl_args;
                int     devfd, res;
                u64 dev_block_count = 0;
-               int mixed = 0;
                char *path;
 
                res = test_dev_for_mkfs(argv[i], force);
@@ -109,7 +108,7 @@ static int cmd_device_add(int argc, char **argv)
                }
 
                res = btrfs_prepare_device(devfd, argv[i], 1, &dev_block_count,
-                                          0, &mixed, discard);
+                                          0, discard);
                close(devfd);
                if (res) {
                        ret++;
diff --git a/cmds-replace.c b/cmds-replace.c
index 9ab8438..e944457 100644
--- a/cmds-replace.c
+++ b/cmds-replace.c
@@ -140,7 +140,6 @@ static int cmd_replace_start(int argc, char **argv)
        int force_using_targetdev = 0;
        u64 dstdev_block_count;
        int do_not_background = 0;
-       int mixed = 0;
        DIR *dirstream = NULL;
        u64 srcdev_size;
        u64 dstdev_size;
@@ -281,7 +280,7 @@ static int cmd_replace_start(int argc, char **argv)
        strncpy((char *)start_args.start.tgtdev_name, dstdev,
                BTRFS_DEVICE_PATH_NAME_MAX);
        ret = btrfs_prepare_device(fddstdev, dstdev, 1, &dstdev_block_count, 0,
-                                &mixed, 0);
+                               0);
        if (ret)
                goto leave_with_error;
 
diff --git a/mkfs.c b/mkfs.c
index a5802f7..10016b2 100644
--- a/mkfs.c
+++ b/mkfs.c
@@ -152,7 +152,7 @@ err:
 }
 
 static int make_root_dir(struct btrfs_trans_handle *trans, struct btrfs_root 
*root,
-               int mixed, struct mkfs_allocation *allocation)
+               struct mkfs_allocation *allocation)
 {
        struct btrfs_key location;
        int ret;
@@ -1440,8 +1440,6 @@ int main(int ac, char **av)
                                break;
                        case 'b':
                                block_count = parse_size(optarg);
-                               if (block_count <= BTRFS_MKFS_SMALL_VOLUME_SIZE)
-                                       mixed = 1;
                                zero_end = 0;
                                break;
                        case 'V':
@@ -1491,7 +1489,7 @@ int main(int ac, char **av)
                        exit(1);
                }
        }
-       
+
        while (dev_cnt-- > 0) {
                file = av[optind++];
                if (is_block_device(file) == 1)
@@ -1505,10 +1503,9 @@ int main(int ac, char **av)
        file = av[optind++];
        ssd = is_ssd(file);
 
-       if (is_vol_small(file) || mixed) {
+       if (mixed) {
                if (verbose)
-                       printf("SMALL VOLUME: forcing mixed metadata/data 
groups\n");
-               mixed = 1;
+                       printf("Forcing mixed metadata/data groups\n");
        }
 
        /*
@@ -1544,6 +1541,19 @@ int main(int ac, char **av)
                if (!nodesize_forced)
                        nodesize = best_nodesize;
        }
+
+       /*
+        * 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;
+       }
+
        if (btrfs_check_nodesize(nodesize, sectorsize,
                                 features))
                exit(1);
@@ -1604,7 +1614,7 @@ int main(int ac, char **av)
                        exit(1);
                }
                ret = btrfs_prepare_device(fd, file, zero_end, &dev_block_count,
-                                          block_count, &mixed, discard);
+                                          block_count, discard);
                if (ret) {
                        close(fd);
                        exit(1);
@@ -1651,18 +1661,6 @@ int main(int ac, char **av)
                        "WARNING: metatdata has lower redundancy than 
data!\n\n");
        }
 
-       /*
-        * 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;
-       }
-
        mkfs_cfg.label = label;
        mkfs_cfg.fs_uuid = fs_uuid;
        memcpy(mkfs_cfg.blocks, blocks, sizeof(blocks));
@@ -1704,7 +1702,7 @@ int main(int ac, char **av)
                exit(1);
        }
 
-       ret = make_root_dir(trans, root, mixed, &allocation);
+       ret = make_root_dir(trans, root, &allocation);
        if (ret) {
                fprintf(stderr, "failed to setup the root directory\n");
                exit(1);
@@ -1725,8 +1723,6 @@ int main(int ac, char **av)
                goto raid_groups;
 
        while (dev_cnt-- > 0) {
-               int old_mixed = mixed;
-
                file = av[optind++];
 
                /*
@@ -1749,12 +1745,11 @@ int main(int ac, char **av)
                        continue;
                }
                ret = btrfs_prepare_device(fd, file, zero_end, &dev_block_count,
-                                          block_count, &mixed, discard);
+                                          block_count, discard);
                if (ret) {
                        close(fd);
                        exit(1);
                }
-               mixed = old_mixed;
 
                ret = btrfs_add_to_fsid(trans, root, fd, file, dev_block_count,
                                        sectorsize, sectorsize, sectorsize);
diff --git a/utils.c b/utils.c
index f1e3248..269b510 100644
--- a/utils.c
+++ b/utils.c
@@ -847,7 +847,7 @@ out:
 }
 
 int btrfs_prepare_device(int fd, char *file, int zero_end, u64 
*block_count_ret,
-                          u64 max_block_count, int *mixed, int discard)
+                          u64 max_block_count, int discard)
 {
        u64 block_count;
        struct stat st;
@@ -867,9 +867,6 @@ int btrfs_prepare_device(int fd, char *file, int zero_end, 
u64 *block_count_ret,
        if (max_block_count)
                block_count = min(block_count, max_block_count);
 
-       if (block_count < BTRFS_MKFS_SMALL_VOLUME_SIZE && !(*mixed))
-               *mixed = 1;
-
        if (discard) {
                /*
                 * We intentionally ignore errors from the discard ioctl.  It
diff --git a/utils.h b/utils.h
index 192f3d1..2e8293d 100644
--- a/utils.h
+++ b/utils.h
@@ -120,7 +120,7 @@ int make_btrfs(int fd, struct btrfs_mkfs_config *cfg);
 int btrfs_make_root_dir(struct btrfs_trans_handle *trans,
                        struct btrfs_root *root, u64 objectid);
 int btrfs_prepare_device(int fd, char *file, int zero_end, u64 
*block_count_ret,
-                        u64 max_block_count, int *mixed, int discard);
+                        u64 max_block_count, int discard);
 int btrfs_add_to_fsid(struct btrfs_trans_handle *trans,
                      struct btrfs_root *root, int fd, char *path,
                      u64 block_count, u32 io_width, u32 io_align,
-- 
2.1.0

--
To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to