Skip to contentSkip to conversation

mm/thp: Use conventional format for boolean attributes

PATCH In review Ben Hutchings 5 participants 11 messages Mar 22, 2011 – Apr 14, 2011

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

PATCH 1/1 mm/thp: Use conventional format for boolean attributes

The conventional format for boolean attributes in sysfs is numeric ("0" or "1" followed by new-line). Any boolean attribute can then be read and written using a generic function. Using the strings "yes [no]", "[yes] no" (read), "yes" and "no" (write) will frustrate this.

Cc'd to stable in order to change this before many scripts depend on the current strings.

---
 mm/huge_memory.c |   21 +++++++++++----------
 1 files changed, 11 insertions(+), 10 deletions(-)
mm/huge_memory.c +11 -10
index 113e35c..dc0b3f0 100644
@@ -244,24 +244,25 @@ static ssize_t single_flag_show(struct kobject *kobj,
 				struct kobj_attribute *attr, char *buf,
 				enum transparent_hugepage_flag flag)
 {
-	if (test_bit(flag, &transparent_hugepage_flags))
-		return sprintf(buf, "[yes] no\n");
-	else
-		return sprintf(buf, "yes [no]\n");
+	return sprintf(buf, "%d\n",
+		       test_bit(flag, &transparent_hugepage_flags));
 }
 static ssize_t single_flag_store(struct kobject *kobj,
 				 struct kobj_attribute *attr,
 				 const char *buf, size_t count,
 				 enum transparent_hugepage_flag flag)
 {
-	if (!memcmp("yes", buf,
-		    min(sizeof("yes")-1, count))) {
+	unsigned long value;
+	char *endp;
+
+	value = simple_strtoul(buf, &endp, 0);
+	if (endp == buf || value > 1)
+		return -EINVAL;
+
+	if (value)
 		set_bit(flag, &transparent_hugepage_flags);
-	} else if (!memcmp("no", buf,
-			   min(sizeof("no")-1, count))) {
+	else
 		clear_bit(flag, &transparent_hugepage_flags);
-	} else
-		return -EINVAL;
 
 	return count;
 }
Signature · 9 lines
1.7.4.1


--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to [email protected].  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Fight unfair telecom internet charges in Canada: sign http://stopthemeter.ca/
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
#1 lore raw
Quoted 9 lines · Ben Hutchings

The conventional format for boolean attributes in sysfs is numeric ("0" or "1" followed by new-line). Any boolean attribute can then be read and written using a generic function. Using the strings "yes [no]", "[yes] no" (read), "yes" and "no" (write) will frustrate this.

Cc'd to stable in order to change this before many scripts depend on the current strings.

I agree with this in general, it's certainly the standard way of altering a boolean tunable throughout the kernel so it would be nice to use the same userspace libraries with THP.

Let's cc Andrew on this since it will go through the -mm tree if it's merged.

Quoted 36 lines
---
 mm/huge_memory.c |   21 +++++++++++----------
 1 files changed, 11 insertions(+), 10 deletions(-)
mm/huge_memory.c +10 -6
index 113e35c..dc0b3f0 100644
@@ -244,24 +244,25 @@ static ssize_t single_flag_show(struct kobject *kobj,
 				struct kobj_attribute *attr, char *buf,
 				enum transparent_hugepage_flag flag)
 {
-	if (test_bit(flag, &transparent_hugepage_flags))
-		return sprintf(buf, "[yes] no\n");
-	else
-		return sprintf(buf, "yes [no]\n");
+	return sprintf(buf, "%d\n",
+		       test_bit(flag, &transparent_hugepage_flags));
 }
 static ssize_t single_flag_store(struct kobject *kobj,
 				 struct kobj_attribute *attr,
 				 const char *buf, size_t count,
 				 enum transparent_hugepage_flag flag)
 {
-	if (!memcmp("yes", buf,
-		    min(sizeof("yes")-1, count))) {
+	unsigned long value;
+	char *endp;
+
+	value = simple_strtoul(buf, &endp, 0);
+	if (endp == buf || value > 1)
+		return -EINVAL;
+
+	if (value)

mm/huge_memory.c static ssize_t single_flag_show(struct kobject *kobj, · line 268

Quoted 10 lines
mm/huge_memory.c +1 -4
 		set_bit(flag, &transparent_hugepage_flags);
-	} else if (!memcmp("no", buf,
-			   min(sizeof("no")-1, count))) {
+	else
 		clear_bit(flag, &transparent_hugepage_flags);
-	} else
-		return -EINVAL;
 
 	return count;
 }

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Fight unfair telecom internet charges in Canada: sign http://stopthemeter.ca/
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

maintainer
#2 lore raw
Quoted 8 lines · On Wed, 13 Apr 2011 12:04:59 -0700 (PDT) David Rientjes <[email protected]>…
Quoted 6 lines · Ben Hutchings

The conventional format for boolean attributes in sysfs is numeric ("0" or "1" followed by new-line). Any boolean attribute can then be read and written using a generic function. Using the strings "yes [no]", "[yes] no" (read), "yes" and "no" (write) will frustrate this.

Quoted 7 lines
Quoted 3 lines

Cc'd to stable in order to change this before many scripts depend on the current strings.

I agree with this in general, it's certainly the standard way of altering a boolean tunable throughout the kernel so it would be nice to use the same userspace libraries with THP.

yup.

It's a bit naughty to change the existing interface in 2.6.38.x but the time window is small and few people will be affected and they were nuts to be using 2.6.38.0 anyway ;)

I suppose we could support both the old and new formats for a while, then retire the old format but I doubt if it's worth it.

Isn't there some user documentation which needs to be updated to reflect this change? If not, why not? :)

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Fight unfair telecom internet charges in Canada: sign http://stopthemeter.ca/
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#3 lore raw
Quoted 10 lines · Andrew Morton

It's a bit naughty to change the existing interface in 2.6.38.x but the time window is small and few people will be affected and they were nuts to be using 2.6.38.0 anyway ;)

I suppose we could support both the old and new formats for a while, then retire the old format but I doubt if it's worth it.

Isn't there some user documentation which needs to be updated to reflect this change? If not, why not? :)

Indeed there is, in Documentation/vm/transhuge.txt -- only for /sys/kernel/mm/transparent_hugepage/khugepaged/defrag, though, we lack documentation of debug_cow.

Ben, do you have time to update the patch? It sounds like this is 2.6.39 material.

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Fight unfair telecom internet charges in Canada: sign http://stopthemeter.ca/
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#4 lore raw

Hi,

Quoted 9 lines · David Rientjes
Quoted 7 lines · Andrew Morton

It's a bit naughty to change the existing interface in 2.6.38.x but the time window is small and few people will be affected and they were nuts to be using 2.6.38.0 anyway ;)

I suppose we could support both the old and new formats for a while, then retire the old format but I doubt if it's worth it.

Quoted 7 lines
Quoted 3 lines

Isn't there some user documentation which needs to be updated to reflect this change? If not, why not? :)

Indeed there is, in Documentation/vm/transhuge.txt -- only for /sys/kernel/mm/transparent_hugepage/khugepaged/defrag, though, we lack documentation of debug_cow.

Well debug_cow only exists for CONFIG_DEBUG_VM so probably doesn't need to be documented unless CONFIG_DEBUG_VM is documented in the first place. It seems production kernels aren't using DEBUG_VM.

Quoted 2 lines

Ben, do you have time to update the patch? It sounds like this is 2.6.39 material.

I think it's fine for 2.6.39. Note that these tweaks are mostly for debugging too, unless something's bad in compaction one wouldn't need to tweak those. The only ones to tweak are the khugepaged parameters and those are integers not booleans.

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Fight unfair telecom internet charges in Canada: sign http://stopthemeter.ca/
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#5 lore raw
In reply to David Rientjes
Quoted 25 lines · On Wed, 13 Apr 2011 12:04:59 -0700 (PDT) David Rientjes <[email protected]>…
Quoted 9 lines · Ben Hutchings

The conventional format for boolean attributes in sysfs is numeric ("0" or "1" followed by new-line). Any boolean attribute can then be read and written using a generic function. Using the strings "yes [no]", "[yes] no" (read), "yes" and "no" (write) will frustrate this.

Cc'd to stable in order to change this before many scripts depend on the current strings.

I agree with this in general, it's certainly the standard way of altering a boolean tunable throughout the kernel so it would be nice to use the same userspace libraries with THP.

Let's cc Andrew on this since it will go through the -mm tree if it's merged.

Quoted 6 lines
---
 mm/huge_memory.c |   21 +++++++++++----------
 1 files changed, 11 insertions(+), 10 deletions(-)
Quoted 14 lines
Quoted 5 lines
mm/huge_memory.c +0 -0
index 113e35c..dc0b3f0 100644

mm/huge_memory.c static ssize_t single_flag_show(struct kobject *kobj, · line 248

Quoted 9 lines
mm/huge_memory.c +2 -4
@@ -244,24 +244,25 @@ static ssize_t single_flag_show(struct kobject *kobj,
 				struct kobj_attribute *attr, char *buf,
 				enum transparent_hugepage_flag flag)
 {
-	if (test_bit(flag, &transparent_hugepage_flags))
-		return sprintf(buf, "[yes] no\n");
-	else
-		return sprintf(buf, "yes [no]\n");
+	return sprintf(buf, "%d\n",
+		       test_bit(flag, &transparent_hugepage_flags));

It test bit guaranteed to return 0 or 1?

I think the x86 version returns 0 or -1 (that is from reading the code and using google to check what 'sbb' does).

Maybe make it "!!test_bit" or even

     strcpy(buf, test_bit(...) ? "1\n" : "0\n");
     return 2;

NeilBrown

Quoted 24 lines
Quoted 24 lines
mm/huge_memory.c +9 -6
 }
 static ssize_t single_flag_store(struct kobject *kobj,
 				 struct kobj_attribute *attr,
 				 const char *buf, size_t count,
 				 enum transparent_hugepage_flag flag)
 {
-	if (!memcmp("yes", buf,
-		    min(sizeof("yes")-1, count))) {
+	unsigned long value;
+	char *endp;
+
+	value = simple_strtoul(buf, &endp, 0);
+	if (endp == buf || value > 1)
+		return -EINVAL;
+
+	if (value)
 		set_bit(flag, &transparent_hugepage_flags);
-	} else if (!memcmp("no", buf,
-			   min(sizeof("no")-1, count))) {
+	else
 		clear_bit(flag, &transparent_hugepage_flags);
-	} else
-		return -EINVAL;
 
Quoted 9 lines

mm/huge_memory.c static ssize_t single_flag_show(struct kobject *kobj, · line 268

Quoted 2 lines
mm/huge_memory.c +0 -0
 	return count;
 }

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Fight unfair telecom internet charges in Canada: sign http://stopthemeter.ca/
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Fight unfair telecom internet charges in Canada: sign http://stopthemeter.ca/
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#6 lore raw
Quoted 2 lines · Neil Brown

I think the x86 version returns 0 or -1 (that is from reading the code and using google to check what 'sbb' does).

It really returns -1...

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Fight unfair telecom internet charges in Canada: sign http://stopthemeter.ca/
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#7 lore raw
Quoted 6 lines · Andrea Arcangeli
Quoted 2 lines · Neil Brown

I think the x86 version returns 0 or -1 (that is from reading the code and using google to check what 'sbb' does).

It really returns -1...

Sorry, thought I checked this before sending the patch.

Ben.

Signature · 10 lines
Ben Hutchings
We get into the habit of living before acquiring the habit of thinking.
                                                              - Albert Camus

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to [email protected].  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Fight unfair telecom internet charges in Canada: sign http://stopthemeter.ca/
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
maintainer
#8 lore raw
In reply to NeilBrown
Quoted 15 lines · On Thu, 14 Apr 2011 14:48:07 +1000 NeilBrown <[email protected]> wrote:
Quoted 4 lines
Quoted 4 lines
mm/huge_memory.c +0 -0
@@ -244,24 +244,25 @@ static ssize_t single_flag_show(struct kobject *kobj,
 				struct kobj_attribute *attr, char *buf,
Quoted 8 lines

mm/huge_memory.c static ssize_t single_flag_show(struct kobject *kobj, · line 248

Quoted 8 lines
mm/huge_memory.c +2 -4
 				enum transparent_hugepage_flag flag)
 {
-	if (test_bit(flag, &transparent_hugepage_flags))
-		return sprintf(buf, "[yes] no\n");
-	else
-		return sprintf(buf, "yes [no]\n");
+	return sprintf(buf, "%d\n",
+		       test_bit(flag, &transparent_hugepage_flags));

It test bit guaranteed to return 0 or 1?

Quoted 2 lines

I think the x86 version returns 0 or -1 (that is from reading the code and using google to check what 'sbb' does).

Thanks for catching that. One wonders how well-tested the patch was!

Speaking of which...

Here's the current status. Ben, can you please test this soon?

From: Ben Hutchings <[email protected]>

The conventional format for boolean attributes in sysfs is numeric ("0" or "1" followed by new-line). Any boolean attribute can then be read and written using a generic function. Using the strings "yes [no]", "[yes] no" (read), "yes" and "no" (write) will frustrate this.

[[email protected]: use kstrtoul()]
[[email protected]: test_bit() doesn't return 1/0, per Neil]
Cc Andrea Arcangeli <[email protected]>
Cc Mel Gorman <[email protected]>
Cc Johannes Weiner <[email protected]>
Cc Rik van Riel <[email protected]>
Cc Hugh Dickins <[email protected]>
Cc David Rientjes <[email protected]>
Cc NeilBrown <[email protected]>
Cc <[email protected]> [2.6.38.x]

---

 mm/huge_memory.c |   24 ++++++++++++++----------
 1 file changed, 14 insertions(+), 10 deletions(-)
mm/huge_memory.c renamed from mm/huge_memory.c~mm-thp-use-conventional-format-for-boolean-attributes +14 -10
diff -puN mm/huge_memory.c~mm-thp-use-conventional-format-for-boolean-attributes mm/huge_memory.c
@@ -244,24 +244,28 @@ static ssize_t single_flag_show(struct k
 				struct kobj_attribute *attr, char *buf,
 				enum transparent_hugepage_flag flag)
 {
-	if (test_bit(flag, &transparent_hugepage_flags))
-		return sprintf(buf, "[yes] no\n");
-	else
-		return sprintf(buf, "yes [no]\n");
+	return sprintf(buf, "%d\n",
+		       !!test_bit(flag, &transparent_hugepage_flags));
 }
+
 static ssize_t single_flag_store(struct kobject *kobj,
 				 struct kobj_attribute *attr,
 				 const char *buf, size_t count,
 				 enum transparent_hugepage_flag flag)
 {
-	if (!memcmp("yes", buf,
-		    min(sizeof("yes")-1, count))) {
+	unsigned long value;
+	int ret;
+
+	ret = kstrtoul(buf, 10, &value);
+	if (ret < 0)
+		return ret;
+	if (value > 1)
+		return -EINVAL;
+
+	if (value)
 		set_bit(flag, &transparent_hugepage_flags);
-	} else if (!memcmp("no", buf,
-			   min(sizeof("no")-1, count))) {
+	else
 		clear_bit(flag, &transparent_hugepage_flags);
-	} else
-		return -EINVAL;
 
 	return count;
 }

_

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Fight unfair telecom internet charges in Canada: sign http://stopthemeter.ca/
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

Tested-by
#9 lore raw
Quoted 7 lines · Andrew Morton

From: Ben Hutchings <[email protected]>

The conventional format for boolean attributes in sysfs is numeric ("0" or "1" followed by new-line). Any boolean attribute can then be read and written using a generic function. Using the strings "yes [no]", "[yes] no" (read), "yes" and "no" (write) will frustrate this.

Quoted 12 lines
[[email protected]: use kstrtoul()]
[[email protected]: test_bit() doesn't return 1/0, per Neil]
Cc Andrea Arcangeli <[email protected]>
Cc Mel Gorman <[email protected]>
Cc Johannes Weiner <[email protected]>
Cc Rik van Riel <[email protected]>
Cc Hugh Dickins <[email protected]>
Cc David Rientjes <[email protected]>
Cc NeilBrown <[email protected]>
Cc <[email protected]> [2.6.38.x]

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Fight unfair telecom internet charges in Canada: sign http://stopthemeter.ca/
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

maintainer
#10 lore raw
In reply to Ben Hutchings

Review

Quoted 11 lines · On Tue, 22 Mar 2011 05:45:11 +0000 Ben Hutchings <[email protected]> wrote:

static ssize_t single_flag_store(struct kobject *kobj,

(quoted diff) +4 -2
 				 struct kobj_attribute *attr,
 				 const char *buf, size_t count,
 				 enum transparent_hugepage_flag flag)
 {
-	if (!memcmp("yes", buf,
-		    min(sizeof("yes")-1, count))) {
+	unsigned long value;
+	char *endp;
+
+	value = simple_strtoul(buf, &endp, 0);

What the heck is this doing using simple_strtoul()? checkpatch has been telling us to use strict_strtoul() for ages, and lately it tells us to use kstrtoul().

Please review and test asap:

mm/huge_memory.c renamed from mm/huge_memory.c~mm-thp-use-conventional-format-for-boolean-attributes-fix +6 -3
@@ -247,16 +247,19 @@ static ssize_t single_flag_show(struct k
 	return sprintf(buf, "%d\n",
 		       test_bit(flag, &transparent_hugepage_flags));
 }
+
 static ssize_t single_flag_store(struct kobject *kobj,
 				 struct kobj_attribute *attr,
 				 const char *buf, size_t count,
 				 enum transparent_hugepage_flag flag)
 {
 	unsigned long value;
-	char *endp;
+	int ret;
 
-	value = simple_strtoul(buf, &endp, 0);
-	if (endp == buf || value > 1)
+	ret = kstrtoul(buf, 10, &value);
+	if (ret < 0)
+		return ret;
+	if (value > 1)
 		return -EINVAL;
 
 	if (value)

_

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Fight unfair telecom internet charges in Canada: sign http://stopthemeter.ca/
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>