Re: [PATCH 2/3] of: Make of_find_node_by_path() handle /aliases

From: Frank Rowand
Date: Tue May 20 2014 - 22:41:31 EST


On 5/18/2014 2:27 AM, Grant Likely wrote:

> On Fri, 16 May 2014 11:54:44 +0100, Grant Likely <grant.likely@xxxxxxxxxx> wrote:

>> On Thu, 15 May 2014 19:51:17 -0700, Frank Rowand <frowand.list@xxxxxxxxx> wrote:

>>> On 5/13/2014 7:58 AM, Grant Likely wrote:

>>>> Make of_find_node_by_path() handle aliases as prefixes. To make this

>>>> work the name search is refactored to search by path component instead

>>>> of by full string. This should be a more efficient search, and it makes

>>>> it possible to start a search at a subnode of a tree.

>>>>

>>>> Signed-off-by: David Daney <david.daney@xxxxxxxxxx>

>>>> Signed-off-by: Pantelis Antoniou <pantelis.antoniou@xxxxxxxxxxxx>

>>>> [grant.likely: Rework to not require allocating at runtime]

>>>> Acked-by: Rob Herring <robh@xxxxxxxxxx>

>>>> Signed-off-by: Grant Likely <grant.likely@xxxxxxxxxx>

>>>> ---

>>>> drivers/of/base.c | 60 +++++++++++++++++++++++++++++++++++++++++++++++++++----

>>>> 1 file changed, 56 insertions(+), 4 deletions(-)

>>>>

>>>> diff --git a/drivers/of/base.c b/drivers/of/base.c

>>>> index 6e240698353b..60089b9a3014 100644

>>>> --- a/drivers/of/base.c

>>>> +++ b/drivers/of/base.c

>>>> @@ -771,9 +771,38 @@ struct device_node *of_get_child_by_name(const struct device_node *node,

>>>> }

>>>> EXPORT_SYMBOL(of_get_child_by_name);

>>>>

>>>> +static struct device_node *__of_find_node_by_path(struct device_node *parent,

>>>> + const char *path)

>>>> +{

>>>> + struct device_node *child;

>>>> + int len = strchrnul(path, '/') - path;

>>>> +

>>>> + if (!len)

>>>> + return parent;

>>>

>>> (!len) is true if the the final character of the path passed into of_find_node_by_path()

>>> was "/". Strictly speaking, ->full_name will never end with "/", so the return value

>>> should be NULL, indicating that the match fails.

>>

>> Ah, good catch. I should add a test case for that.

>

> In my testing this looks okay. The while loop that calls into

> __of_find_node_by_path() looks like this:

>

> while (np && *path == '/') {

> path++; /* Increment past '/' delimiter */

> np = __of_find_node_by_path(np, path);

> path = strchrnul(path, '/');

> }

>

> If the path ends with a '/', then the loop will go around one more time.

> The pointer will be incremented to point at the null character and len

> will be null because strchrnul() will point at the last item.



Yes, that was my point. The old version of of_find_node_by_path() would not

find a match if the path ended with a "/" (unless the full path was "/").

This patch series changes the behavior to be a match.


I will reply to this email with an additional patch that restores the

original behavior.


If you move the additional test cases you provide below and the test cases

in patch 3 to the beginning of the series, you can see the before and after

behavior of adding patch 1 and patch 2.


>

> I've added a couple of test cases to make sure it works correctly:

>

> diff --git a/drivers/of/selftest.c b/drivers/of/selftest.c

> index a9d00e8c17ea..10900b18fc06 100644

> --- a/drivers/of/selftest.c

> +++ b/drivers/of/selftest.c

> @@ -40,6 +40,12 @@ static void __init of_selftest_find_node_by_name(void)

> "find /testcase-data failed\n");

> of_node_put(np);

>

> + /* Test if trailing '/' works */

> + np = of_find_node_by_path("/testcase-data/");

> + selftest(np && !strcmp("/testcase-data", np->full_name),

> + "find /testcase-data/ failed\n");

> + of_node_put(np);

> +

> np = of_find_node_by_path("/testcase-data/phandle-tests/consumer-a");

> selftest(np && !strcmp("/testcase-data/phandle-tests/consumer-a", np->full_name),

> "find /testcase-data/phandle-tests/consumer-a failed\n");

> @@ -50,6 +56,12 @@ static void __init of_selftest_find_node_by_name(void)

> "find testcase-alias failed\n");

> of_node_put(np);

>

> + /* Test if trailing '/' works on aliases */

> + np = of_find_node_by_path("testcase-alias/");

> + selftest(np && !strcmp("/testcase-data", np->full_name),

> + "find testcase-alias/ failed\n");

> + of_node_put(np);

> +

> np = of_find_node_by_path("testcase-alias/phandle-tests/consumer-a");

> selftest(np && !strcmp("/testcase-data/phandle-tests/consumer-a", np->full_name),

> "find testcase-alias/phandle-tests/consumer-a failed\n");

>

> g.

>

>

>>

>>>

>>>> +

>>>> + for_each_child_of_node(parent, child) {

>>>> + const char *name = strrchr(child->full_name, '/');

>>>> + if (WARN(!name, "malformed device_node %s\n", child->full_name))

>>>> + continue;

>>>> + name++;


< snip >

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/