[v2,1/5] btrfs-progs: introduce framework to check kernel supported features
diff mbox

Message ID 1448283378-10579-2-git-send-email-anand.jain@oracle.com
State New
Headers show

Commit Message

Anand Jain Nov. 23, 2015, 12:56 p.m. UTC
In the newer kernel, supported kernel features can be known from
  /sys/fs/btrfs/features
however this interface was introduced only after 3.14, and most the
incompatible FS features were introduce before 3.14.

This patch proposes to maintain kernel version against the feature list,
and so that will be the minimum kernel version needed to use the feature.

Further, for features supported later than 3.14 this list can still be
updated, so it serves as a repository which can be displayed for easy
reference.

Signed-off-by: Anand Jain <anand.jain@oracle.com>
---
v2: Check for condition that what happens when we fail to read kernel
    version. Now the code will fail back to use the default as set by
    the progs.

 utils.c | 80 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----
 utils.h |  1 +
 2 files changed, 76 insertions(+), 5 deletions(-)

Comments

Mike Fleetwood Nov. 24, 2015, 2:39 p.m. UTC | #1
On 23 November 2015 at 12:56, Anand Jain <anand.jain@oracle.com> wrote:
> In the newer kernel, supported kernel features can be known from
>   /sys/fs/btrfs/features
> however this interface was introduced only after 3.14, and most the
> incompatible FS features were introduce before 3.14.
>
> This patch proposes to maintain kernel version against the feature list,
> and so that will be the minimum kernel version needed to use the feature.
>
> Further, for features supported later than 3.14 this list can still be
> updated, so it serves as a repository which can be displayed for easy
> reference.
>
> Signed-off-by: Anand Jain <anand.jain@oracle.com>
> ---
> v2: Check for condition that what happens when we fail to read kernel
>     version. Now the code will fail back to use the default as set by
>     the progs.
>
>  utils.c | 80 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----
>  utils.h |  1 +
>  2 files changed, 76 insertions(+), 5 deletions(-)
>
> diff --git a/utils.c b/utils.c
> index b754686..24042e5 100644
> --- a/utils.c
> +++ b/utils.c
> @@ -32,10 +32,12 @@
>  #include <linux/loop.h>
>  #include <linux/major.h>
>  #include <linux/kdev_t.h>
> +#include <linux/version.h>
>  #include <limits.h>
>  #include <blkid/blkid.h>
>  #include <sys/vfs.h>
>  #include <sys/statfs.h>
> +#include <sys/utsname.h>
>  #include <linux/magic.h>
>
>  #include "kerncompat.h"
> @@ -567,21 +569,28 @@ out:
>         return ret;
>  }
>
> +/*
> + * min_ker_ver: update with minimum kernel version at which the feature
> + * was integrated into the mainline. For the transit period, that is
> + * feature not yet in mainline but in mailing list and for testing,
> + * please use "0.0" to indicate the same.
> + */
>  static const struct btrfs_fs_feature {
>         const char *name;
>         u64 flag;
>         const char *desc;
> +       const char *min_ker_ver;
>  } mkfs_features[] = {
>         { "mixed-bg", BTRFS_FEATURE_INCOMPAT_MIXED_GROUPS,
> -               "mixed data and metadata block groups" },
> +               "mixed data and metadata block groups", "2.7.31"},
I think you mean 2.6.37 here.
67377734fd24c3 "Btrfs: add support for mixed data+metadata block groups"

Thanks,
Mike

>         { "extref", BTRFS_FEATURE_INCOMPAT_EXTENDED_IREF,
> -               "increased hardlink limit per file to 65536" },
> +               "increased hardlink limit per file to 65536", "3.7"},
>         { "raid56", BTRFS_FEATURE_INCOMPAT_RAID56,
> -               "raid56 extended format" },
> +               "raid56 extended format", "3.9"},
>         { "skinny-metadata", BTRFS_FEATURE_INCOMPAT_SKINNY_METADATA,
> -               "reduced-size metadata extent refs" },
> +               "reduced-size metadata extent refs", "3.10"},
>         { "no-holes", BTRFS_FEATURE_INCOMPAT_NO_HOLES,
> -               "no explicit hole extents for files" },
> +               "no explicit hole extents for files", "3.14"},
>         /* Keep this one last */
>         { "list-all", BTRFS_FEATURE_LIST_ALL, NULL }
>  };
> @@ -3077,3 +3086,64 @@ unsigned int get_unit_mode_from_arg(int *argc, char *argv[], int df_mode)
>
>         return unit_mode;
>  }
> +
> +static int version_to_code(char *v)
> +{
> +       int i = 0;
> +       char *b[3] = {NULL};
> +       char *save_b = NULL;
> +
> +       for (b[i] = strtok_r(v, ".", &save_b);
> +               b[i] != NULL;
> +               b[i] = strtok_r(NULL, ".", &save_b))
> +               i++;
> +
> +       if (b[2] == NULL)
> +               return KERNEL_VERSION(atoi(b[0]), atoi(b[1]), 0);
> +       else
> +               return KERNEL_VERSION(atoi(b[0]), atoi(b[1]), atoi(b[2]));
> +
> +}
> +
> +static int get_kernel_code()
> +{
> +       int ret;
> +       struct utsname utsbuf;
> +       char *version;
> +
> +       ret = uname(&utsbuf);
> +       if (ret)
> +               return -ret;
> +
> +       if (!strlen(utsbuf.release))
> +               return -EINVAL;
> +
> +       version = strtok(utsbuf.release, "-");
> +
> +       return version_to_code(version);
> +}
> +
> +u64 btrfs_features_allowed_by_kernel(void)
> +{
> +       int i;
> +       int local_kernel_code = get_kernel_code();
> +       u64 features = 0;
> +
> +       /*
> +        * When system did not provide the kernel version then just
> +        * return 0, the caller has to depend on the intelligence as
> +        * per btrfs-progs version
> +        */
> +       if (local_kernel_code <= 0)
> +               return 0;
> +
> +       for (i = 0; i < ARRAY_SIZE(mkfs_features) - 1; i++) {
> +               char *ver = strdup(mkfs_features[i].min_ker_ver);
> +
> +               if (local_kernel_code >= version_to_code(ver))
> +                       features |= mkfs_features[i].flag;
> +
> +               free(ver);
> +       }
> +       return (features);
> +}
> diff --git a/utils.h b/utils.h
> index 192f3d1..9044643 100644
> --- a/utils.h
> +++ b/utils.h
> @@ -104,6 +104,7 @@ void btrfs_list_all_fs_features(u64 mask_disallowed);
>  char* btrfs_parse_fs_features(char *namelist, u64 *flags);
>  void btrfs_process_fs_features(u64 flags);
>  void btrfs_parse_features_to_string(char *buf, u64 flags);
> +u64 btrfs_features_allowed_by_kernel(void);
>
>  struct btrfs_mkfs_config {
>         char *label;
> --
> 2.6.2
--
To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Austin S. Hemmelgarn Nov. 24, 2015, 8:21 p.m. UTC | #2
On 2015-11-24 09:39, Mike Fleetwood wrote:
> On 23 November 2015 at 12:56, Anand Jain <anand.jain@oracle.com> wrote:
>> In the newer kernel, supported kernel features can be known from
>>    /sys/fs/btrfs/features
>> however this interface was introduced only after 3.14, and most the
>> incompatible FS features were introduce before 3.14.
>>
>> This patch proposes to maintain kernel version against the feature list,
>> and so that will be the minimum kernel version needed to use the feature.
>>
>> Further, for features supported later than 3.14 this list can still be
>> updated, so it serves as a repository which can be displayed for easy
>> reference.
>>
>> Signed-off-by: Anand Jain <anand.jain@oracle.com>
>> ---
>> v2: Check for condition that what happens when we fail to read kernel
>>      version. Now the code will fail back to use the default as set by
>>      the progs.
>>
>>   utils.c | 80 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----
>>   utils.h |  1 +
>>   2 files changed, 76 insertions(+), 5 deletions(-)
>>
>> diff --git a/utils.c b/utils.c
>> index b754686..24042e5 100644
>> --- a/utils.c
>> +++ b/utils.c
>> @@ -32,10 +32,12 @@
>>   #include <linux/loop.h>
>>   #include <linux/major.h>
>>   #include <linux/kdev_t.h>
>> +#include <linux/version.h>
>>   #include <limits.h>
>>   #include <blkid/blkid.h>
>>   #include <sys/vfs.h>
>>   #include <sys/statfs.h>
>> +#include <sys/utsname.h>
>>   #include <linux/magic.h>
>>
>>   #include "kerncompat.h"
>> @@ -567,21 +569,28 @@ out:
>>          return ret;
>>   }
>>
>> +/*
>> + * min_ker_ver: update with minimum kernel version at which the feature
>> + * was integrated into the mainline. For the transit period, that is
>> + * feature not yet in mainline but in mailing list and for testing,
>> + * please use "0.0" to indicate the same.
>> + */
>>   static const struct btrfs_fs_feature {
>>          const char *name;
>>          u64 flag;
>>          const char *desc;
>> +       const char *min_ker_ver;
>>   } mkfs_features[] = {
>>          { "mixed-bg", BTRFS_FEATURE_INCOMPAT_MIXED_GROUPS,
>> -               "mixed data and metadata block groups" },
>> +               "mixed data and metadata block groups", "2.7.31"},
> I think you mean 2.6.37 here.
> 67377734fd24c3 "Btrfs: add support for mixed data+metadata block groups"
This brings up a rather important question:
Should compat-X.Y mean features that were considered usable in that 
version, or everything that version offered?  I understand wanting 
consistency with the kernel versions, but we shouldn't be creating 
filesystems that we know will break on the specified kernel even if it 
is mountable on it.
David Sterba Nov. 26, 2015, 5:38 p.m. UTC | #3
On Tue, Nov 24, 2015 at 03:21:19PM -0500, Austin S Hemmelgarn wrote:
> > I think you mean 2.6.37 here.
> > 67377734fd24c3 "Btrfs: add support for mixed data+metadata block groups"
> This brings up a rather important question:
> Should compat-X.Y mean features that were considered usable in that 
> version, or everything that version offered?  I understand wanting 
> consistency with the kernel versions, but we shouldn't be creating 
> filesystems that we know will break on the specified kernel even if it 
> is mountable on it.

IMO compat refers to the compatibility feature bits so it's whether the
filesystem is mountable on a given version. Usability can be subjective.
I assume the kernel versions in wide use match some of the long term
branches. If it's k.org, we can submit the fixes and distros update
their long term branches.

A table of "is the feature usable" would be interesting but I think it's
for wiki.
--
To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Austin S. Hemmelgarn Nov. 30, 2015, 12:30 p.m. UTC | #4
On 2015-11-26 12:38, David Sterba wrote:
> On Tue, Nov 24, 2015 at 03:21:19PM -0500, Austin S Hemmelgarn wrote:
>>> I think you mean 2.6.37 here.
>>> 67377734fd24c3 "Btrfs: add support for mixed data+metadata block groups"
>> This brings up a rather important question:
>> Should compat-X.Y mean features that were considered usable in that
>> version, or everything that version offered?  I understand wanting
>> consistency with the kernel versions, but we shouldn't be creating
>> filesystems that we know will break on the specified kernel even if it
>> is mountable on it.
>
> IMO compat refers to the compatibility feature bits so it's whether the
> filesystem is mountable on a given version. Usability can be subjective.
> I assume the kernel versions in wide use match some of the long term
> branches. If it's k.org, we can submit the fixes and distros update
> their long term branches.
My point was that if we know that there's a significant chance of either 
data corruption or a kernel crash when using a given feature with a 
given kernel, we should not turn on that feature for that kernel.  For 
every other project I've ever seen, compatible means that you can be 
fairly certain that it won't crash, and won't destroy data.  There is no 
excuse for knowingly making filesystems that will break the system.

Also, expecting the distros to keep up with development given the pace 
at which BTRFS is moving is not all that realistic.  Secondarily, at 
least Ubuntu has a habit of picking kernel versions that aren't marked 
LTS by kernel.org.
>
> A table of "is the feature usable" would be interesting but I think it's
> for wiki.
I'd say it would be a lot more helpful in the manpage than in the wiki 
(if you're reprovisioning a system, you don't necessarily have access to 
the wiki).

Patch
diff mbox

diff --git a/utils.c b/utils.c
index b754686..24042e5 100644
--- a/utils.c
+++ b/utils.c
@@ -32,10 +32,12 @@ 
 #include <linux/loop.h>
 #include <linux/major.h>
 #include <linux/kdev_t.h>
+#include <linux/version.h>
 #include <limits.h>
 #include <blkid/blkid.h>
 #include <sys/vfs.h>
 #include <sys/statfs.h>
+#include <sys/utsname.h>
 #include <linux/magic.h>
 
 #include "kerncompat.h"
@@ -567,21 +569,28 @@  out:
 	return ret;
 }
 
+/*
+ * min_ker_ver: update with minimum kernel version at which the feature
+ * was integrated into the mainline. For the transit period, that is
+ * feature not yet in mainline but in mailing list and for testing,
+ * please use "0.0" to indicate the same.
+ */
 static const struct btrfs_fs_feature {
 	const char *name;
 	u64 flag;
 	const char *desc;
+	const char *min_ker_ver;
 } mkfs_features[] = {
 	{ "mixed-bg", BTRFS_FEATURE_INCOMPAT_MIXED_GROUPS,
-		"mixed data and metadata block groups" },
+		"mixed data and metadata block groups", "2.7.31"},
 	{ "extref", BTRFS_FEATURE_INCOMPAT_EXTENDED_IREF,
-		"increased hardlink limit per file to 65536" },
+		"increased hardlink limit per file to 65536", "3.7"},
 	{ "raid56", BTRFS_FEATURE_INCOMPAT_RAID56,
-		"raid56 extended format" },
+		"raid56 extended format", "3.9"},
 	{ "skinny-metadata", BTRFS_FEATURE_INCOMPAT_SKINNY_METADATA,
-		"reduced-size metadata extent refs" },
+		"reduced-size metadata extent refs", "3.10"},
 	{ "no-holes", BTRFS_FEATURE_INCOMPAT_NO_HOLES,
-		"no explicit hole extents for files" },
+		"no explicit hole extents for files", "3.14"},
 	/* Keep this one last */
 	{ "list-all", BTRFS_FEATURE_LIST_ALL, NULL }
 };
@@ -3077,3 +3086,64 @@  unsigned int get_unit_mode_from_arg(int *argc, char *argv[], int df_mode)
 
 	return unit_mode;
 }
+
+static int version_to_code(char *v)
+{
+	int i = 0;
+	char *b[3] = {NULL};
+	char *save_b = NULL;
+
+	for (b[i] = strtok_r(v, ".", &save_b);
+		b[i] != NULL;
+		b[i] = strtok_r(NULL, ".", &save_b))
+		i++;
+
+	if (b[2] == NULL)
+		return KERNEL_VERSION(atoi(b[0]), atoi(b[1]), 0);
+	else
+		return KERNEL_VERSION(atoi(b[0]), atoi(b[1]), atoi(b[2]));
+
+}
+
+static int get_kernel_code()
+{
+	int ret;
+	struct utsname utsbuf;
+	char *version;
+
+	ret = uname(&utsbuf);
+	if (ret)
+		return -ret;
+
+	if (!strlen(utsbuf.release))
+		return -EINVAL;
+
+	version = strtok(utsbuf.release, "-");
+
+	return version_to_code(version);
+}
+
+u64 btrfs_features_allowed_by_kernel(void)
+{
+	int i;
+	int local_kernel_code = get_kernel_code();
+	u64 features = 0;
+
+	/*
+	 * When system did not provide the kernel version then just
+	 * return 0, the caller has to depend on the intelligence as
+	 * per btrfs-progs version
+	 */
+	if (local_kernel_code <= 0)
+		return 0;
+
+	for (i = 0; i < ARRAY_SIZE(mkfs_features) - 1; i++) {
+		char *ver = strdup(mkfs_features[i].min_ker_ver);
+
+		if (local_kernel_code >= version_to_code(ver))
+			features |= mkfs_features[i].flag;
+
+		free(ver);
+	}
+	return (features);
+}
diff --git a/utils.h b/utils.h
index 192f3d1..9044643 100644
--- a/utils.h
+++ b/utils.h
@@ -104,6 +104,7 @@  void btrfs_list_all_fs_features(u64 mask_disallowed);
 char* btrfs_parse_fs_features(char *namelist, u64 *flags);
 void btrfs_process_fs_features(u64 flags);
 void btrfs_parse_features_to_string(char *buf, u64 flags);
+u64 btrfs_features_allowed_by_kernel(void);
 
 struct btrfs_mkfs_config {
 	char *label;