From: Greg Kroah-Hartman Date: Mon, 4 Feb 2019 08:54:38 +0000 (+0100) Subject: 4.20-stable patches X-Git-Tag: v4.20.7~16 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=1ace62962a74121b5b0442a7b07c51a863e9c0b1;p=thirdparty%2Fkernel%2Fstable-queue.git 4.20-stable patches added patches: cifs-always-resolve-hostname-before-reconnecting.patch md-raid5-fix-out-of-memory-during-raid-cache-recovery.patch of-overlay-add-missing-of_node_get-in-__of_attach_node_sysfs.patch of-overlay-add-tests-to-validate-kfrees-from-overlay-removal.patch of-overlay-do-not-duplicate-properties-from-overlay-for-new-nodes.patch of-overlay-use-prop-add-changeset-entry-for-property-in-new-nodes.patch --- diff --git a/queue-4.20/cifs-always-resolve-hostname-before-reconnecting.patch b/queue-4.20/cifs-always-resolve-hostname-before-reconnecting.patch new file mode 100644 index 00000000000..5de6c8e1d2b --- /dev/null +++ b/queue-4.20/cifs-always-resolve-hostname-before-reconnecting.patch @@ -0,0 +1,99 @@ +From 28eb24ff75c5ac130eb326b3b4d0dcecfc0f427d Mon Sep 17 00:00:00 2001 +From: Paulo Alcantara +Date: Tue, 20 Nov 2018 15:16:36 -0200 +Subject: cifs: Always resolve hostname before reconnecting + +From: Paulo Alcantara + +commit 28eb24ff75c5ac130eb326b3b4d0dcecfc0f427d upstream. + +In case a hostname resolves to a different IP address (e.g. long +running mounts), make sure to resolve it every time prior to calling +generic_ip_connect() in reconnect. + +Suggested-by: Steve French +Signed-off-by: Paulo Alcantara +Signed-off-by: Steve French +Signed-off-by: Pavel Shilovsky +Signed-off-by: Greg Kroah-Hartman + +--- + fs/cifs/connect.c | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 53 insertions(+) + +--- a/fs/cifs/connect.c ++++ b/fs/cifs/connect.c +@@ -50,6 +50,7 @@ + #include "cifs_unicode.h" + #include "cifs_debug.h" + #include "cifs_fs_sb.h" ++#include "dns_resolve.h" + #include "ntlmssp.h" + #include "nterr.h" + #include "rfc1002pdu.h" +@@ -319,6 +320,53 @@ static int cifs_setup_volume_info(struct + const char *devname, bool is_smb3); + + /* ++ * Resolve hostname and set ip addr in tcp ses. Useful for hostnames that may ++ * get their ip addresses changed at some point. ++ * ++ * This should be called with server->srv_mutex held. ++ */ ++#ifdef CONFIG_CIFS_DFS_UPCALL ++static int reconn_set_ipaddr(struct TCP_Server_Info *server) ++{ ++ int rc; ++ int len; ++ char *unc, *ipaddr = NULL; ++ ++ if (!server->hostname) ++ return -EINVAL; ++ ++ len = strlen(server->hostname) + 3; ++ ++ unc = kmalloc(len, GFP_KERNEL); ++ if (!unc) { ++ cifs_dbg(FYI, "%s: failed to create UNC path\n", __func__); ++ return -ENOMEM; ++ } ++ snprintf(unc, len, "\\\\%s", server->hostname); ++ ++ rc = dns_resolve_server_name_to_ip(unc, &ipaddr); ++ kfree(unc); ++ ++ if (rc < 0) { ++ cifs_dbg(FYI, "%s: failed to resolve server part of %s to IP: %d\n", ++ __func__, server->hostname, rc); ++ return rc; ++ } ++ ++ rc = cifs_convert_address((struct sockaddr *)&server->dstaddr, ipaddr, ++ strlen(ipaddr)); ++ kfree(ipaddr); ++ ++ return !rc ? -1 : 0; ++} ++#else ++static inline int reconn_set_ipaddr(struct TCP_Server_Info *server) ++{ ++ return 0; ++} ++#endif ++ ++/* + * cifs tcp session reconnection + * + * mark tcp session as reconnecting so temporarily locked +@@ -418,6 +466,11 @@ cifs_reconnect(struct TCP_Server_Info *s + rc = generic_ip_connect(server); + if (rc) { + cifs_dbg(FYI, "reconnect error %d\n", rc); ++ rc = reconn_set_ipaddr(server); ++ if (rc) { ++ cifs_dbg(FYI, "%s: failed to resolve hostname: %d\n", ++ __func__, rc); ++ } + mutex_unlock(&server->srv_mutex); + msleep(3000); + } else { diff --git a/queue-4.20/md-raid5-fix-out-of-memory-during-raid-cache-recovery.patch b/queue-4.20/md-raid5-fix-out-of-memory-during-raid-cache-recovery.patch new file mode 100644 index 00000000000..e8c9997ae27 --- /dev/null +++ b/queue-4.20/md-raid5-fix-out-of-memory-during-raid-cache-recovery.patch @@ -0,0 +1,125 @@ +From 483cbbeddd5fe2c80fd4141ff0748fa06c4ff146 Mon Sep 17 00:00:00 2001 +From: Alexei Naberezhnov +Date: Tue, 27 Mar 2018 16:54:16 -0700 +Subject: md/raid5: fix 'out of memory' during raid cache recovery + +From: Alexei Naberezhnov + +commit 483cbbeddd5fe2c80fd4141ff0748fa06c4ff146 upstream. + +This fixes the case when md array assembly fails because of raid cache recovery +unable to allocate a stripe, despite attempts to replay stripes and increase +cache size. This happens because stripes released by r5c_recovery_replay_stripes +and raid5_set_cache_size don't become available for allocation immediately. +Released stripes first are placed on conf->released_stripes list and require +md thread to merge them on conf->inactive_list before they can be allocated. + +Patch allows final allocation attempt during cache recovery to wait for +new stripes to become availabe for allocation. + +Cc: linux-raid@vger.kernel.org +Cc: Shaohua Li +Cc: linux-stable # 4.10+ +Fixes: b4c625c67362 ("md/r5cache: r5cache recovery: part 1") +Signed-off-by: Alexei Naberezhnov +Signed-off-by: Song Liu +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/md/raid5-cache.c | 33 ++++++++++++++++++++++----------- + drivers/md/raid5.c | 8 ++++++-- + 2 files changed, 28 insertions(+), 13 deletions(-) + +--- a/drivers/md/raid5-cache.c ++++ b/drivers/md/raid5-cache.c +@@ -1935,12 +1935,14 @@ out: + } + + static struct stripe_head * +-r5c_recovery_alloc_stripe(struct r5conf *conf, +- sector_t stripe_sect) ++r5c_recovery_alloc_stripe( ++ struct r5conf *conf, ++ sector_t stripe_sect, ++ int noblock) + { + struct stripe_head *sh; + +- sh = raid5_get_active_stripe(conf, stripe_sect, 0, 1, 0); ++ sh = raid5_get_active_stripe(conf, stripe_sect, 0, noblock, 0); + if (!sh) + return NULL; /* no more stripe available */ + +@@ -2150,7 +2152,7 @@ r5c_recovery_analyze_meta_block(struct r + stripe_sect); + + if (!sh) { +- sh = r5c_recovery_alloc_stripe(conf, stripe_sect); ++ sh = r5c_recovery_alloc_stripe(conf, stripe_sect, 1); + /* + * cannot get stripe from raid5_get_active_stripe + * try replay some stripes +@@ -2159,20 +2161,29 @@ r5c_recovery_analyze_meta_block(struct r + r5c_recovery_replay_stripes( + cached_stripe_list, ctx); + sh = r5c_recovery_alloc_stripe( +- conf, stripe_sect); ++ conf, stripe_sect, 1); + } + if (!sh) { ++ int new_size = conf->min_nr_stripes * 2; + pr_debug("md/raid:%s: Increasing stripe cache size to %d to recovery data on journal.\n", + mdname(mddev), +- conf->min_nr_stripes * 2); +- raid5_set_cache_size(mddev, +- conf->min_nr_stripes * 2); +- sh = r5c_recovery_alloc_stripe(conf, +- stripe_sect); ++ new_size); ++ ret = raid5_set_cache_size(mddev, new_size); ++ if (conf->min_nr_stripes <= new_size / 2) { ++ pr_err("md/raid:%s: Cannot increase cache size, ret=%d, new_size=%d, min_nr_stripes=%d, max_nr_stripes=%d\n", ++ mdname(mddev), ++ ret, ++ new_size, ++ conf->min_nr_stripes, ++ conf->max_nr_stripes); ++ return -ENOMEM; ++ } ++ sh = r5c_recovery_alloc_stripe( ++ conf, stripe_sect, 0); + } + if (!sh) { + pr_err("md/raid:%s: Cannot get enough stripes due to memory pressure. Recovery failed.\n", +- mdname(mddev)); ++ mdname(mddev)); + return -ENOMEM; + } + list_add_tail(&sh->lru, cached_stripe_list); +--- a/drivers/md/raid5.c ++++ b/drivers/md/raid5.c +@@ -6369,6 +6369,7 @@ raid5_show_stripe_cache_size(struct mdde + int + raid5_set_cache_size(struct mddev *mddev, int size) + { ++ int result = 0; + struct r5conf *conf = mddev->private; + + if (size <= 16 || size > 32768) +@@ -6385,11 +6386,14 @@ raid5_set_cache_size(struct mddev *mddev + + mutex_lock(&conf->cache_size_mutex); + while (size > conf->max_nr_stripes) +- if (!grow_one_stripe(conf, GFP_KERNEL)) ++ if (!grow_one_stripe(conf, GFP_KERNEL)) { ++ conf->min_nr_stripes = conf->max_nr_stripes; ++ result = -ENOMEM; + break; ++ } + mutex_unlock(&conf->cache_size_mutex); + +- return 0; ++ return result; + } + EXPORT_SYMBOL(raid5_set_cache_size); + diff --git a/queue-4.20/of-overlay-add-missing-of_node_get-in-__of_attach_node_sysfs.patch b/queue-4.20/of-overlay-add-missing-of_node_get-in-__of_attach_node_sysfs.patch new file mode 100644 index 00000000000..29f29149178 --- /dev/null +++ b/queue-4.20/of-overlay-add-missing-of_node_get-in-__of_attach_node_sysfs.patch @@ -0,0 +1,66 @@ +From 5b2c2f5a0ea3a43e0dee78059e34c7cb54136dcc Mon Sep 17 00:00:00 2001 +From: Frank Rowand +Date: Thu, 4 Oct 2018 20:26:05 -0700 +Subject: of: overlay: add missing of_node_get() in __of_attach_node_sysfs + +From: Frank Rowand + +commit 5b2c2f5a0ea3a43e0dee78059e34c7cb54136dcc upstream. + +There is a matching of_node_put() in __of_detach_node_sysfs() + +Remove misleading comment from function header comment for +of_detach_node(). + +This patch may result in memory leaks from code that directly calls +the dynamic node add and delete functions directly instead of +using changesets. + +This commit should result in powerpc systems that dynamically +allocate a node, then later deallocate the node to have a +memory leak when the node is deallocated. + +The next commit will fix the leak. + +Tested-by: Alan Tull +Acked-by: Michael Ellerman (powerpc) +Signed-off-by: Frank Rowand +Cc: Guenter Roeck +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/of/dynamic.c | 3 --- + drivers/of/kobj.c | 4 +++- + 2 files changed, 3 insertions(+), 4 deletions(-) + +--- a/drivers/of/dynamic.c ++++ b/drivers/of/dynamic.c +@@ -275,9 +275,6 @@ void __of_detach_node(struct device_node + + /** + * of_detach_node() - "Unplug" a node from the device tree. +- * +- * The caller must hold a reference to the node. The memory associated with +- * the node is not freed until its refcount goes to zero. + */ + int of_detach_node(struct device_node *np) + { +--- a/drivers/of/kobj.c ++++ b/drivers/of/kobj.c +@@ -133,6 +133,9 @@ int __of_attach_node_sysfs(struct device + } + if (!name) + return -ENOMEM; ++ ++ of_node_get(np); ++ + rc = kobject_add(&np->kobj, parent, "%s", name); + kfree(name); + if (rc) +@@ -159,6 +162,5 @@ void __of_detach_node_sysfs(struct devic + kobject_del(&np->kobj); + } + +- /* finally remove the kobj_init ref */ + of_node_put(np); + } diff --git a/queue-4.20/of-overlay-add-tests-to-validate-kfrees-from-overlay-removal.patch b/queue-4.20/of-overlay-add-tests-to-validate-kfrees-from-overlay-removal.patch new file mode 100644 index 00000000000..da40f43574d --- /dev/null +++ b/queue-4.20/of-overlay-add-tests-to-validate-kfrees-from-overlay-removal.patch @@ -0,0 +1,114 @@ +From 144552c786925314c1e7cb8f91a71dae1aca8798 Mon Sep 17 00:00:00 2001 +From: Frank Rowand +Date: Thu, 4 Oct 2018 20:24:17 -0700 +Subject: of: overlay: add tests to validate kfrees from overlay removal + +From: Frank Rowand + +commit 144552c786925314c1e7cb8f91a71dae1aca8798 upstream. + +Add checks: + - attempted kfree due to refcount reaching zero before overlay + is removed + - properties linked to an overlay node when the node is removed + - node refcount > one during node removal in a changeset destroy, + if the node was created by the changeset + +After applying this patch, several validation warnings will be +reported from the devicetree unittest during boot due to +pre-existing devicetree bugs. The warnings will be similar to: + + OF: ERROR: of_node_release(), unexpected properties in /testcase-data/overlay-node/test-bus/test-unittest11 + OF: ERROR: memory leak, expected refcount 1 instead of 2, of_node_get()/of_node_put() unbalanced - destroy cset entry: attach overlay node /testcase-data-2/substation@100/ + hvac-medium-2 + +Tested-by: Alan Tull +Signed-off-by: Frank Rowand +Cc: Guenter Roeck +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/of/dynamic.c | 29 +++++++++++++++++++++++++++++ + drivers/of/overlay.c | 1 + + include/linux/of.h | 15 ++++++++++----- + 3 files changed, 40 insertions(+), 5 deletions(-) + +--- a/drivers/of/dynamic.c ++++ b/drivers/of/dynamic.c +@@ -333,6 +333,25 @@ void of_node_release(struct kobject *kob + if (!of_node_check_flag(node, OF_DYNAMIC)) + return; + ++ if (of_node_check_flag(node, OF_OVERLAY)) { ++ ++ if (!of_node_check_flag(node, OF_OVERLAY_FREE_CSET)) { ++ /* premature refcount of zero, do not free memory */ ++ pr_err("ERROR: memory leak before free overlay changeset, %pOF\n", ++ node); ++ return; ++ } ++ ++ /* ++ * If node->properties non-empty then properties were added ++ * to this node either by different overlay that has not ++ * yet been removed, or by a non-overlay mechanism. ++ */ ++ if (node->properties) ++ pr_err("ERROR: %s(), unexpected properties in %pOF\n", ++ __func__, node); ++ } ++ + property_list_free(node->properties); + property_list_free(node->deadprops); + +@@ -437,6 +456,16 @@ struct device_node *__of_node_dup(const + + static void __of_changeset_entry_destroy(struct of_changeset_entry *ce) + { ++ if (ce->action == OF_RECONFIG_ATTACH_NODE && ++ of_node_check_flag(ce->np, OF_OVERLAY)) { ++ if (kref_read(&ce->np->kobj.kref) > 1) { ++ pr_err("ERROR: memory leak, expected refcount 1 instead of %d, of_node_get()/of_node_put() unbalanced - destroy cset entry: attach overlay node %pOF\n", ++ kref_read(&ce->np->kobj.kref), ce->np); ++ } else { ++ of_node_set_flag(ce->np, OF_OVERLAY_FREE_CSET); ++ } ++ } ++ + of_node_put(ce->np); + list_del(&ce->node); + kfree(ce); +--- a/drivers/of/overlay.c ++++ b/drivers/of/overlay.c +@@ -373,6 +373,7 @@ static int add_changeset_node(struct ove + return -ENOMEM; + + tchild->parent = target_node; ++ of_node_set_flag(tchild, OF_OVERLAY); + + ret = of_changeset_attach_node(&ovcs->cset, tchild); + if (ret) +--- a/include/linux/of.h ++++ b/include/linux/of.h +@@ -138,11 +138,16 @@ extern struct device_node *of_aliases; + extern struct device_node *of_stdout; + extern raw_spinlock_t devtree_lock; + +-/* flag descriptions (need to be visible even when !CONFIG_OF) */ +-#define OF_DYNAMIC 1 /* node and properties were allocated via kmalloc */ +-#define OF_DETACHED 2 /* node has been detached from the device tree */ +-#define OF_POPULATED 3 /* device already created for the node */ +-#define OF_POPULATED_BUS 4 /* of_platform_populate recursed to children of this node */ ++/* ++ * struct device_node flag descriptions ++ * (need to be visible even when !CONFIG_OF) ++ */ ++#define OF_DYNAMIC 1 /* (and properties) allocated via kmalloc */ ++#define OF_DETACHED 2 /* detached from the device tree */ ++#define OF_POPULATED 3 /* device already created */ ++#define OF_POPULATED_BUS 4 /* platform bus created for children */ ++#define OF_OVERLAY 5 /* allocated for an overlay */ ++#define OF_OVERLAY_FREE_CSET 6 /* in overlay cset being freed */ + + #define OF_BAD_ADDR ((u64)-1) + diff --git a/queue-4.20/of-overlay-do-not-duplicate-properties-from-overlay-for-new-nodes.patch b/queue-4.20/of-overlay-do-not-duplicate-properties-from-overlay-for-new-nodes.patch new file mode 100644 index 00000000000..4a24631136a --- /dev/null +++ b/queue-4.20/of-overlay-do-not-duplicate-properties-from-overlay-for-new-nodes.patch @@ -0,0 +1,48 @@ +From 8814dc46bd9e347d4de55ec5bf8f16ea54470499 Mon Sep 17 00:00:00 2001 +From: Frank Rowand +Date: Thu, 4 Oct 2018 20:29:01 -0700 +Subject: of: overlay: do not duplicate properties from overlay for new nodes + +From: Frank Rowand + +commit 8814dc46bd9e347d4de55ec5bf8f16ea54470499 upstream. + +When allocating a new node, add_changeset_node() was duplicating the +properties from the respective node in the overlay instead of +allocating a node with no properties. + +When this patch is applied the errors reported by the devictree +unittest from patch "of: overlay: add tests to validate kfrees from +overlay removal" will no longer occur. These error messages are of +the form: + + "OF: ERROR: ..." + +and the unittest results will change from: + + ### dt-test ### end of unittest - 203 passed, 7 failed + +to + + ### dt-test ### end of unittest - 210 passed, 0 failed + +Tested-by: Alan Tull +Signed-off-by: Frank Rowand +Cc: Guenter Roeck +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/of/overlay.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/of/overlay.c ++++ b/drivers/of/overlay.c +@@ -393,7 +393,7 @@ static int add_changeset_node(struct ove + break; + + if (!tchild) { +- tchild = __of_node_dup(node, node_kbasename); ++ tchild = __of_node_dup(NULL, node_kbasename); + if (!tchild) + return -ENOMEM; + diff --git a/queue-4.20/of-overlay-use-prop-add-changeset-entry-for-property-in-new-nodes.patch b/queue-4.20/of-overlay-use-prop-add-changeset-entry-for-property-in-new-nodes.patch new file mode 100644 index 00000000000..0de3dc65f06 --- /dev/null +++ b/queue-4.20/of-overlay-use-prop-add-changeset-entry-for-property-in-new-nodes.patch @@ -0,0 +1,329 @@ +From 6b4955ba7bc05e40c8c41071cc121bc26ca65277 Mon Sep 17 00:00:00 2001 +From: Frank Rowand +Date: Thu, 4 Oct 2018 20:28:08 -0700 +Subject: of: overlay: use prop add changeset entry for property in new nodes + +From: Frank Rowand + +commit 6b4955ba7bc05e40c8c41071cc121bc26ca65277 upstream. + +The changeset entry 'update property' was used for new properties in +an overlay instead of 'add property'. + +The decision of whether to use 'update property' was based on whether +the property already exists in the subtree where the node is being +spliced into. At the top level of creating a changeset describing the +overlay, the target node is in the live devicetree, so checking whether +the property exists in the target node returns the correct result. +As soon as the changeset creation algorithm recurses into a new node, +the target is no longer in the live devicetree, but is instead in the +detached overlay tree, thus all properties are incorrectly found to +already exist in the target. + +This fix will expose another devicetree bug that will be fixed +in the following patch in the series. + +When this patch is applied the errors reported by the devictree +unittest will change, and the unittest results will change from: + + ### dt-test ### end of unittest - 210 passed, 0 failed + +to + + ### dt-test ### end of unittest - 203 passed, 7 failed + +Tested-by: Alan Tull +Signed-off-by: Frank Rowand +Cc: Guenter Roeck +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/of/overlay.c | 112 +++++++++++++++++++++++++++++++++------------------ + 1 file changed, 74 insertions(+), 38 deletions(-) + +--- a/drivers/of/overlay.c ++++ b/drivers/of/overlay.c +@@ -24,6 +24,26 @@ + #include "of_private.h" + + /** ++ * struct target - info about current target node as recursing through overlay ++ * @np: node where current level of overlay will be applied ++ * @in_livetree: @np is a node in the live devicetree ++ * ++ * Used in the algorithm to create the portion of a changeset that describes ++ * an overlay fragment, which is a devicetree subtree. Initially @np is a node ++ * in the live devicetree where the overlay subtree is targeted to be grafted ++ * into. When recursing to the next level of the overlay subtree, the target ++ * also recurses to the next level of the live devicetree, as long as overlay ++ * subtree node also exists in the live devicetree. When a node in the overlay ++ * subtree does not exist at the same level in the live devicetree, target->np ++ * points to a newly allocated node, and all subsequent targets in the subtree ++ * will be newly allocated nodes. ++ */ ++struct target { ++ struct device_node *np; ++ bool in_livetree; ++}; ++ ++/** + * struct fragment - info about fragment nodes in overlay expanded device tree + * @target: target of the overlay operation + * @overlay: pointer to the __overlay__ node +@@ -72,8 +92,7 @@ static int devicetree_corrupt(void) + } + + static int build_changeset_next_level(struct overlay_changeset *ovcs, +- struct device_node *target_node, +- const struct device_node *overlay_node); ++ struct target *target, const struct device_node *overlay_node); + + /* + * of_resolve_phandles() finds the largest phandle in the live tree. +@@ -257,14 +276,17 @@ err_free_target_path: + /** + * add_changeset_property() - add @overlay_prop to overlay changeset + * @ovcs: overlay changeset +- * @target_node: where to place @overlay_prop in live tree ++ * @target: where @overlay_prop will be placed + * @overlay_prop: property to add or update, from overlay tree + * @is_symbols_prop: 1 if @overlay_prop is from node "/__symbols__" + * +- * If @overlay_prop does not already exist in @target_node, add changeset entry +- * to add @overlay_prop in @target_node, else add changeset entry to update ++ * If @overlay_prop does not already exist in live devicetree, add changeset ++ * entry to add @overlay_prop in @target, else add changeset entry to update + * value of @overlay_prop. + * ++ * @target may be either in the live devicetree or in a new subtree that ++ * is contained in the changeset. ++ * + * Some special properties are not updated (no error returned). + * + * Update of property in symbols node is not allowed. +@@ -273,20 +295,22 @@ err_free_target_path: + * invalid @overlay. + */ + static int add_changeset_property(struct overlay_changeset *ovcs, +- struct device_node *target_node, +- struct property *overlay_prop, ++ struct target *target, struct property *overlay_prop, + bool is_symbols_prop) + { + struct property *new_prop = NULL, *prop; + int ret = 0; + +- prop = of_find_property(target_node, overlay_prop->name, NULL); +- + if (!of_prop_cmp(overlay_prop->name, "name") || + !of_prop_cmp(overlay_prop->name, "phandle") || + !of_prop_cmp(overlay_prop->name, "linux,phandle")) + return 0; + ++ if (target->in_livetree) ++ prop = of_find_property(target->np, overlay_prop->name, NULL); ++ else ++ prop = NULL; ++ + if (is_symbols_prop) { + if (prop) + return -EINVAL; +@@ -299,10 +323,10 @@ static int add_changeset_property(struct + return -ENOMEM; + + if (!prop) +- ret = of_changeset_add_property(&ovcs->cset, target_node, ++ ret = of_changeset_add_property(&ovcs->cset, target->np, + new_prop); + else +- ret = of_changeset_update_property(&ovcs->cset, target_node, ++ ret = of_changeset_update_property(&ovcs->cset, target->np, + new_prop); + + if (ret) { +@@ -315,14 +339,14 @@ static int add_changeset_property(struct + + /** + * add_changeset_node() - add @node (and children) to overlay changeset +- * @ovcs: overlay changeset +- * @target_node: where to place @node in live tree +- * @node: node from within overlay device tree fragment ++ * @ovcs: overlay changeset ++ * @target: where @node will be placed in live tree or changeset ++ * @node: node from within overlay device tree fragment + * +- * If @node does not already exist in @target_node, add changeset entry +- * to add @node in @target_node. ++ * If @node does not already exist in @target, add changeset entry ++ * to add @node in @target. + * +- * If @node already exists in @target_node, and the existing node has ++ * If @node already exists in @target, and the existing node has + * a phandle, the overlay node is not allowed to have a phandle. + * + * If @node has child nodes, add the children recursively via +@@ -355,15 +379,16 @@ static int add_changeset_property(struct + * invalid @overlay. + */ + static int add_changeset_node(struct overlay_changeset *ovcs, +- struct device_node *target_node, struct device_node *node) ++ struct target *target, struct device_node *node) + { + const char *node_kbasename; + struct device_node *tchild; ++ struct target target_child; + int ret = 0; + + node_kbasename = kbasename(node->full_name); + +- for_each_child_of_node(target_node, tchild) ++ for_each_child_of_node(target->np, tchild) + if (!of_node_cmp(node_kbasename, kbasename(tchild->full_name))) + break; + +@@ -372,22 +397,28 @@ static int add_changeset_node(struct ove + if (!tchild) + return -ENOMEM; + +- tchild->parent = target_node; ++ tchild->parent = target->np; + of_node_set_flag(tchild, OF_OVERLAY); + + ret = of_changeset_attach_node(&ovcs->cset, tchild); + if (ret) + return ret; + +- ret = build_changeset_next_level(ovcs, tchild, node); ++ target_child.np = tchild; ++ target_child.in_livetree = false; ++ ++ ret = build_changeset_next_level(ovcs, &target_child, node); + of_node_put(tchild); + return ret; + } + +- if (node->phandle && tchild->phandle) ++ if (node->phandle && tchild->phandle) { + ret = -EINVAL; +- else +- ret = build_changeset_next_level(ovcs, tchild, node); ++ } else { ++ target_child.np = tchild; ++ target_child.in_livetree = target->in_livetree; ++ ret = build_changeset_next_level(ovcs, &target_child, node); ++ } + of_node_put(tchild); + + return ret; +@@ -396,7 +427,7 @@ static int add_changeset_node(struct ove + /** + * build_changeset_next_level() - add level of overlay changeset + * @ovcs: overlay changeset +- * @target_node: where to place @overlay_node in live tree ++ * @target: where to place @overlay_node in live tree + * @overlay_node: node from within an overlay device tree fragment + * + * Add the properties (if any) and nodes (if any) from @overlay_node to the +@@ -409,27 +440,26 @@ static int add_changeset_node(struct ove + * invalid @overlay_node. + */ + static int build_changeset_next_level(struct overlay_changeset *ovcs, +- struct device_node *target_node, +- const struct device_node *overlay_node) ++ struct target *target, const struct device_node *overlay_node) + { + struct device_node *child; + struct property *prop; + int ret; + + for_each_property_of_node(overlay_node, prop) { +- ret = add_changeset_property(ovcs, target_node, prop, 0); ++ ret = add_changeset_property(ovcs, target, prop, 0); + if (ret) { + pr_debug("Failed to apply prop @%pOF/%s, err=%d\n", +- target_node, prop->name, ret); ++ target->np, prop->name, ret); + return ret; + } + } + + for_each_child_of_node(overlay_node, child) { +- ret = add_changeset_node(ovcs, target_node, child); ++ ret = add_changeset_node(ovcs, target, child); + if (ret) { + pr_debug("Failed to apply node @%pOF/%pOFn, err=%d\n", +- target_node, child, ret); ++ target->np, child, ret); + of_node_put(child); + return ret; + } +@@ -442,17 +472,17 @@ static int build_changeset_next_level(st + * Add the properties from __overlay__ node to the @ovcs->cset changeset. + */ + static int build_changeset_symbols_node(struct overlay_changeset *ovcs, +- struct device_node *target_node, ++ struct target *target, + const struct device_node *overlay_symbols_node) + { + struct property *prop; + int ret; + + for_each_property_of_node(overlay_symbols_node, prop) { +- ret = add_changeset_property(ovcs, target_node, prop, 1); ++ ret = add_changeset_property(ovcs, target, prop, 1); + if (ret) { + pr_debug("Failed to apply prop @%pOF/%s, err=%d\n", +- target_node, prop->name, ret); ++ target->np, prop->name, ret); + return ret; + } + } +@@ -475,6 +505,7 @@ static int build_changeset_symbols_node( + static int build_changeset(struct overlay_changeset *ovcs) + { + struct fragment *fragment; ++ struct target target; + int fragments_count, i, ret; + + /* +@@ -489,7 +520,9 @@ static int build_changeset(struct overla + for (i = 0; i < fragments_count; i++) { + fragment = &ovcs->fragments[i]; + +- ret = build_changeset_next_level(ovcs, fragment->target, ++ target.np = fragment->target; ++ target.in_livetree = true; ++ ret = build_changeset_next_level(ovcs, &target, + fragment->overlay); + if (ret) { + pr_debug("apply failed '%pOF'\n", fragment->target); +@@ -499,7 +532,10 @@ static int build_changeset(struct overla + + if (ovcs->symbols_fragment) { + fragment = &ovcs->fragments[ovcs->count - 1]; +- ret = build_changeset_symbols_node(ovcs, fragment->target, ++ ++ target.np = fragment->target; ++ target.in_livetree = true; ++ ret = build_changeset_symbols_node(ovcs, &target, + fragment->overlay); + if (ret) { + pr_debug("apply failed '%pOF'\n", fragment->target); +@@ -517,7 +553,7 @@ static int build_changeset(struct overla + * 1) "target" property containing the phandle of the target + * 2) "target-path" property containing the path of the target + */ +-static struct device_node *find_target_node(struct device_node *info_node) ++static struct device_node *find_target(struct device_node *info_node) + { + struct device_node *node; + const char *path; +@@ -623,7 +659,7 @@ static int init_overlay_changeset(struct + + fragment = &fragments[cnt]; + fragment->overlay = overlay_node; +- fragment->target = find_target_node(node); ++ fragment->target = find_target(node); + if (!fragment->target) { + of_node_put(fragment->overlay); + ret = -EINVAL; diff --git a/queue-4.20/series b/queue-4.20/series index cae0d685c56..bf3ccc03dda 100644 --- a/queue-4.20/series +++ b/queue-4.20/series @@ -72,3 +72,9 @@ mm-memory_hotplug-fix-scan_movable_pages-for-gigantic-hugepages.patch mm-oom-fix-use-after-free-in-oom_kill_process.patch mm-hwpoison-use-do_send_sig_info-instead-of-force_sig.patch mm-migrate-don-t-rely-on-__pagemovable-of-newpage-after-unlocking-it.patch +of-overlay-add-tests-to-validate-kfrees-from-overlay-removal.patch +of-overlay-add-missing-of_node_get-in-__of_attach_node_sysfs.patch +of-overlay-use-prop-add-changeset-entry-for-property-in-new-nodes.patch +of-overlay-do-not-duplicate-properties-from-overlay-for-new-nodes.patch +md-raid5-fix-out-of-memory-during-raid-cache-recovery.patch +cifs-always-resolve-hostname-before-reconnecting.patch