From: Greg Kroah-Hartman Date: Mon, 4 Feb 2019 08:58:57 +0000 (+0100) Subject: 4.19-stable patches X-Git-Tag: v4.20.7~12 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=00d0566b024880999647defd01dc8e874b887f8c;p=thirdparty%2Fkernel%2Fstable-queue.git 4.19-stable patches added patches: cifs-always-resolve-hostname-before-reconnecting.patch md-raid5-fix-out-of-memory-during-raid-cache-recovery.patch --- diff --git a/queue-4.19/cifs-always-resolve-hostname-before-reconnecting.patch b/queue-4.19/cifs-always-resolve-hostname-before-reconnecting.patch new file mode 100644 index 00000000000..45205ca1b01 --- /dev/null +++ b/queue-4.19/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" +@@ -318,6 +319,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 +@@ -417,6 +465,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.19/md-raid5-fix-out-of-memory-during-raid-cache-recovery.patch b/queue-4.19/md-raid5-fix-out-of-memory-during-raid-cache-recovery.patch new file mode 100644 index 00000000000..419be3f21fb --- /dev/null +++ b/queue-4.19/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 +@@ -6357,6 +6357,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) +@@ -6373,11 +6374,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.19/series b/queue-4.19/series index 7b464820731..6f106a8f2e2 100644 --- a/queue-4.19/series +++ b/queue-4.19/series @@ -70,3 +70,5 @@ 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