diff options
author | Frank Rowand <frank.rowand@sony.com> | 2017-10-18 01:36:29 +0200 |
---|---|---|
committer | Rob Herring <robh@kernel.org> | 2017-10-18 03:47:27 +0200 |
commit | f948d6d8b792bb90041edc12eac35faf83030994 (patch) | |
tree | f98bad2bb9e0701c3fc198e72575216e442006b5 /drivers/of/unittest.c | |
parent | of: overlay: loosen overly strict phandle clash check (diff) | |
download | linux-f948d6d8b792bb90041edc12eac35faf83030994.tar.xz linux-f948d6d8b792bb90041edc12eac35faf83030994.zip |
of: overlay: avoid race condition between applying multiple overlays
The process of applying an overlay consists of:
- unflatten an overlay FDT (flattened device tree) into an
EDT (expanded device tree)
- fixup the phandle values in the overlay EDT to fit in a
range above the phandle values in the live device tree
- create the overlay changeset to reflect the contents of
the overlay EDT
- apply the overlay changeset, to modify the live device tree,
potentially changing the maximum phandle value in the live
device tree
There is currently no protection against two overlay applies
concurrently determining what range of phandle values are in use
in the live device tree, and subsequently changing that range.
Add a mutex to prevent multiple overlay applies from occurring
simultaneously.
Move of_resolve_phandles() into of_overlay_apply() so that it does not
have to be duplicated by each caller of of_overlay_apply().
The test in of_resolve_phandles() that the overlay tree is detached is
temporarily disabled so that old style overlay unittests do not fail.
Signed-off-by: Frank Rowand <frank.rowand@sony.com>
Signed-off-by: Rob Herring <robh@kernel.org>
Diffstat (limited to 'drivers/of/unittest.c')
-rw-r--r-- | drivers/of/unittest.c | 22 |
1 files changed, 16 insertions, 6 deletions
diff --git a/drivers/of/unittest.c b/drivers/of/unittest.c index 3640dae4b9b2..273d78c1520b 100644 --- a/drivers/of/unittest.c +++ b/drivers/of/unittest.c @@ -993,9 +993,17 @@ static int __init unittest_data_add(void) pr_warn("%s: No tree to attach; not running tests\n", __func__); return -ENODATA; } + + /* + * This lock normally encloses of_overlay_apply() as well as + * of_resolve_phandles(). + */ + of_overlay_mutex_lock(); + rc = of_resolve_phandles(unittest_data_node); if (rc) { pr_err("%s: Failed to resolve phandles (rc=%i)\n", __func__, rc); + of_overlay_mutex_unlock(); return -EINVAL; } @@ -1005,6 +1013,7 @@ static int __init unittest_data_add(void) __of_attach_node_sysfs(np); of_aliases = of_find_node_by_path("/aliases"); of_chosen = of_find_node_by_path("/chosen"); + of_overlay_mutex_unlock(); return 0; } @@ -1017,6 +1026,9 @@ static int __init unittest_data_add(void) attach_node_and_children(np); np = next; } + + of_overlay_mutex_unlock(); + return 0; } @@ -2148,16 +2160,11 @@ static int __init overlay_data_add(int onum) goto out_free_data; } - ret = of_resolve_phandles(info->np_overlay); - if (ret) { - pr_err("resolve ot phandles (ret=%d), %d\n", ret, onum); - goto out_free_np_overlay; - } - info->overlay_id = 0; ret = of_overlay_apply(info->np_overlay, &info->overlay_id); if (ret < 0) { pr_err("of_overlay_apply() (ret=%d), %d\n", ret, onum); + of_overlay_mutex_unlock(); goto out_free_np_overlay; } @@ -2207,7 +2214,10 @@ static __init void of_unittest_overlay_high_level(void) * Could not fixup phandles in unittest_unflatten_overlay_base() * because kmalloc() was not yet available. */ + of_overlay_mutex_lock(); of_resolve_phandles(overlay_base_root); + of_overlay_mutex_unlock(); + /* * do not allow overlay_base to duplicate any node already in |