]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
5.4-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 7 Feb 2020 10:28:45 +0000 (11:28 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 7 Feb 2020 10:28:45 +0000 (11:28 +0100)
added patches:
cpufreq-avoid-creating-excessively-large-stack-frames.patch
f2fs-choose-hardlimit-when-softlimit-is-larger-than-hardlimit-in-f2fs_statfs_project.patch
f2fs-code-cleanup-for-f2fs_statfs_project.patch
f2fs-fix-dcache-lookup-of-casefolded-directories.patch
f2fs-fix-miscounted-block-limit-in-f2fs_statfs_project.patch
f2fs-fix-race-conditions-in-d_compare-and-d_hash.patch
ovl-fix-lseek-overflow-on-32bit.patch
ovl-fix-wrong-warn_on-in-ovl_cache_update_ino.patch
pm-core-fix-handling-of-devices-deleted-during-system-wide-resume.patch

queue-5.4/cpufreq-avoid-creating-excessively-large-stack-frames.patch [new file with mode: 0644]
queue-5.4/f2fs-choose-hardlimit-when-softlimit-is-larger-than-hardlimit-in-f2fs_statfs_project.patch [new file with mode: 0644]
queue-5.4/f2fs-code-cleanup-for-f2fs_statfs_project.patch [new file with mode: 0644]
queue-5.4/f2fs-fix-dcache-lookup-of-casefolded-directories.patch [new file with mode: 0644]
queue-5.4/f2fs-fix-miscounted-block-limit-in-f2fs_statfs_project.patch [new file with mode: 0644]
queue-5.4/f2fs-fix-race-conditions-in-d_compare-and-d_hash.patch [new file with mode: 0644]
queue-5.4/ovl-fix-lseek-overflow-on-32bit.patch [new file with mode: 0644]
queue-5.4/ovl-fix-wrong-warn_on-in-ovl_cache_update_ino.patch [new file with mode: 0644]
queue-5.4/pm-core-fix-handling-of-devices-deleted-during-system-wide-resume.patch [new file with mode: 0644]
queue-5.4/series

diff --git a/queue-5.4/cpufreq-avoid-creating-excessively-large-stack-frames.patch b/queue-5.4/cpufreq-avoid-creating-excessively-large-stack-frames.patch
new file mode 100644 (file)
index 0000000..f1808b7
--- /dev/null
@@ -0,0 +1,659 @@
+From 1e4f63aecb53e48468661e922fc2fa3b83e55722 Mon Sep 17 00:00:00 2001
+From: "Rafael J. Wysocki" <rafael.j.wysocki@intel.com>
+Date: Sun, 26 Jan 2020 23:40:11 +0100
+Subject: cpufreq: Avoid creating excessively large stack frames
+
+From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+
+commit 1e4f63aecb53e48468661e922fc2fa3b83e55722 upstream.
+
+In the process of modifying a cpufreq policy, the cpufreq core makes
+a copy of it including all of the internals which is stored on the
+CPU stack.  Because struct cpufreq_policy is relatively large, this
+may cause the size of the stack frame to exceed the 2 KB limit and
+so the GCC complains when -Wframe-larger-than= is used.
+
+In fact, it is not necessary to copy the entire policy structure
+in order to modify it, however.
+
+First, because cpufreq_set_policy() obtains the min and max policy
+limits from frequency QoS now, it is not necessary to pass the limits
+to it from the callers.  The only things that need to be passed to it
+from there are the new governor pointer or (if there is a built-in
+governor in the driver) the "policy" value representing the governor
+choice.  They both can be passed as individual arguments, though, so
+make cpufreq_set_policy() take them this way and rework its callers
+accordingly.  This avoids making copies of cpufreq policies in the
+callers of cpufreq_set_policy().
+
+Second, cpufreq_set_policy() still needs to pass the new policy
+data to the ->verify() callback of the cpufreq driver whose task
+is to sanitize the min and max policy limits.  It still does not
+need to make a full copy of struct cpufreq_policy for this purpose,
+but it needs to pass a few items from it to the driver in case they
+are needed (different drivers have different needs in that respect
+and all of them have to be covered).  For this reason, introduce
+struct cpufreq_policy_data to hold copies of the members of
+struct cpufreq_policy used by the existing ->verify() driver
+callbacks and pass a pointer to a temporary structure of that
+type to ->verify() (instead of passing a pointer to full struct
+cpufreq_policy to it).
+
+While at it, notice that intel_pstate and longrun don't really need
+to verify the "policy" value in struct cpufreq_policy, so drop those
+check from them to avoid copying "policy" into struct
+cpufreq_policy_data (which allows it to be slightly smaller).
+
+Also while at it fix up white space in a couple of places and make
+cpufreq_set_policy() static (as it can be so).
+
+Fixes: 3000ce3c52f8 ("cpufreq: Use per-policy frequency QoS")
+Link: https://lore.kernel.org/linux-pm/CAMuHMdX6-jb1W8uC2_237m8ctCpsnGp=JCxqt8pCWVqNXHmkVg@mail.gmail.com
+Reported-by: kbuild test robot <lkp@intel.com>
+Reported-by: Geert Uytterhoeven <geert@linux-m68k.org>
+Cc: 5.4+ <stable@vger.kernel.org> # 5.4+
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Acked-by: Viresh Kumar <viresh.kumar@linaro.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/cpufreq/cppc_cpufreq.c     |    2 
+ drivers/cpufreq/cpufreq-nforce2.c  |    2 
+ drivers/cpufreq/cpufreq.c          |  147 +++++++++++++++++--------------------
+ drivers/cpufreq/freq_table.c       |    4 -
+ drivers/cpufreq/gx-suspmod.c       |    2 
+ drivers/cpufreq/intel_pstate.c     |   38 ++++-----
+ drivers/cpufreq/longrun.c          |    6 -
+ drivers/cpufreq/pcc-cpufreq.c      |    2 
+ drivers/cpufreq/sh-cpufreq.c       |    2 
+ drivers/cpufreq/unicore2-cpufreq.c |    2 
+ include/linux/cpufreq.h            |   32 +++++---
+ 11 files changed, 119 insertions(+), 120 deletions(-)
+
+--- a/drivers/cpufreq/cppc_cpufreq.c
++++ b/drivers/cpufreq/cppc_cpufreq.c
+@@ -217,7 +217,7 @@ static int cppc_cpufreq_set_target(struc
+       return ret;
+ }
+-static int cppc_verify_policy(struct cpufreq_policy *policy)
++static int cppc_verify_policy(struct cpufreq_policy_data *policy)
+ {
+       cpufreq_verify_within_cpu_limits(policy);
+       return 0;
+--- a/drivers/cpufreq/cpufreq-nforce2.c
++++ b/drivers/cpufreq/cpufreq-nforce2.c
+@@ -291,7 +291,7 @@ static int nforce2_target(struct cpufreq
+  * nforce2_verify - verifies a new CPUFreq policy
+  * @policy: new policy
+  */
+-static int nforce2_verify(struct cpufreq_policy *policy)
++static int nforce2_verify(struct cpufreq_policy_data *policy)
+ {
+       unsigned int fsb_pol_max;
+--- a/drivers/cpufreq/cpufreq.c
++++ b/drivers/cpufreq/cpufreq.c
+@@ -74,6 +74,9 @@ static void cpufreq_exit_governor(struct
+ static int cpufreq_start_governor(struct cpufreq_policy *policy);
+ static void cpufreq_stop_governor(struct cpufreq_policy *policy);
+ static void cpufreq_governor_limits(struct cpufreq_policy *policy);
++static int cpufreq_set_policy(struct cpufreq_policy *policy,
++                            struct cpufreq_governor *new_gov,
++                            unsigned int new_pol);
+ /**
+  * Two notifier lists: the "policy" list is involved in the
+@@ -613,25 +616,22 @@ static struct cpufreq_governor *find_gov
+       return NULL;
+ }
+-static int cpufreq_parse_policy(char *str_governor,
+-                              struct cpufreq_policy *policy)
++static unsigned int cpufreq_parse_policy(char *str_governor)
+ {
+-      if (!strncasecmp(str_governor, "performance", CPUFREQ_NAME_LEN)) {
+-              policy->policy = CPUFREQ_POLICY_PERFORMANCE;
+-              return 0;
+-      }
+-      if (!strncasecmp(str_governor, "powersave", CPUFREQ_NAME_LEN)) {
+-              policy->policy = CPUFREQ_POLICY_POWERSAVE;
+-              return 0;
+-      }
+-      return -EINVAL;
++      if (!strncasecmp(str_governor, "performance", CPUFREQ_NAME_LEN))
++              return CPUFREQ_POLICY_PERFORMANCE;
++
++      if (!strncasecmp(str_governor, "powersave", CPUFREQ_NAME_LEN))
++              return CPUFREQ_POLICY_POWERSAVE;
++
++      return CPUFREQ_POLICY_UNKNOWN;
+ }
+ /**
+  * cpufreq_parse_governor - parse a governor string only for has_target()
++ * @str_governor: Governor name.
+  */
+-static int cpufreq_parse_governor(char *str_governor,
+-                                struct cpufreq_policy *policy)
++static struct cpufreq_governor *cpufreq_parse_governor(char *str_governor)
+ {
+       struct cpufreq_governor *t;
+@@ -645,7 +645,7 @@ static int cpufreq_parse_governor(char *
+               ret = request_module("cpufreq_%s", str_governor);
+               if (ret)
+-                      return -EINVAL;
++                      return NULL;
+               mutex_lock(&cpufreq_governor_mutex);
+@@ -656,12 +656,7 @@ static int cpufreq_parse_governor(char *
+       mutex_unlock(&cpufreq_governor_mutex);
+-      if (t) {
+-              policy->governor = t;
+-              return 0;
+-      }
+-
+-      return -EINVAL;
++      return t;
+ }
+ /**
+@@ -762,28 +757,33 @@ static ssize_t show_scaling_governor(str
+ static ssize_t store_scaling_governor(struct cpufreq_policy *policy,
+                                       const char *buf, size_t count)
+ {
++      char str_governor[16];
+       int ret;
+-      char    str_governor[16];
+-      struct cpufreq_policy new_policy;
+-
+-      memcpy(&new_policy, policy, sizeof(*policy));
+       ret = sscanf(buf, "%15s", str_governor);
+       if (ret != 1)
+               return -EINVAL;
+       if (cpufreq_driver->setpolicy) {
+-              if (cpufreq_parse_policy(str_governor, &new_policy))
++              unsigned int new_pol;
++
++              new_pol = cpufreq_parse_policy(str_governor);
++              if (!new_pol)
+                       return -EINVAL;
++
++              ret = cpufreq_set_policy(policy, NULL, new_pol);
+       } else {
+-              if (cpufreq_parse_governor(str_governor, &new_policy))
++              struct cpufreq_governor *new_gov;
++
++              new_gov = cpufreq_parse_governor(str_governor);
++              if (!new_gov)
+                       return -EINVAL;
+-      }
+-      ret = cpufreq_set_policy(policy, &new_policy);
++              ret = cpufreq_set_policy(policy, new_gov,
++                                       CPUFREQ_POLICY_UNKNOWN);
+-      if (new_policy.governor)
+-              module_put(new_policy.governor->owner);
++              module_put(new_gov->owner);
++      }
+       return ret ? ret : count;
+ }
+@@ -1050,40 +1050,33 @@ __weak struct cpufreq_governor *cpufreq_
+ static int cpufreq_init_policy(struct cpufreq_policy *policy)
+ {
+-      struct cpufreq_governor *gov = NULL, *def_gov = NULL;
+-      struct cpufreq_policy new_policy;
+-
+-      memcpy(&new_policy, policy, sizeof(*policy));
+-
+-      def_gov = cpufreq_default_governor();
++      struct cpufreq_governor *def_gov = cpufreq_default_governor();
++      struct cpufreq_governor *gov = NULL;
++      unsigned int pol = CPUFREQ_POLICY_UNKNOWN;
+       if (has_target()) {
+-              /*
+-               * Update governor of new_policy to the governor used before
+-               * hotplug
+-               */
++              /* Update policy governor to the one used before hotplug. */
+               gov = find_governor(policy->last_governor);
+               if (gov) {
+                       pr_debug("Restoring governor %s for cpu %d\n",
+-                              policy->governor->name, policy->cpu);
+-              } else {
+-                      if (!def_gov)
+-                              return -ENODATA;
++                               policy->governor->name, policy->cpu);
++              } else if (def_gov) {
+                       gov = def_gov;
++              } else {
++                      return -ENODATA;
+               }
+-              new_policy.governor = gov;
+       } else {
+               /* Use the default policy if there is no last_policy. */
+               if (policy->last_policy) {
+-                      new_policy.policy = policy->last_policy;
++                      pol = policy->last_policy;
++              } else if (def_gov) {
++                      pol = cpufreq_parse_policy(def_gov->name);
+               } else {
+-                      if (!def_gov)
+-                              return -ENODATA;
+-                      cpufreq_parse_policy(def_gov->name, &new_policy);
++                      return -ENODATA;
+               }
+       }
+-      return cpufreq_set_policy(policy, &new_policy);
++      return cpufreq_set_policy(policy, gov, pol);
+ }
+ static int cpufreq_add_policy_cpu(struct cpufreq_policy *policy, unsigned int cpu)
+@@ -1111,13 +1104,10 @@ static int cpufreq_add_policy_cpu(struct
+ void refresh_frequency_limits(struct cpufreq_policy *policy)
+ {
+-      struct cpufreq_policy new_policy;
+-
+       if (!policy_is_inactive(policy)) {
+-              new_policy = *policy;
+               pr_debug("updating policy for CPU %u\n", policy->cpu);
+-              cpufreq_set_policy(policy, &new_policy);
++              cpufreq_set_policy(policy, policy->governor, policy->policy);
+       }
+ }
+ EXPORT_SYMBOL(refresh_frequency_limits);
+@@ -2361,43 +2351,46 @@ EXPORT_SYMBOL(cpufreq_get_policy);
+ /**
+  * cpufreq_set_policy - Modify cpufreq policy parameters.
+  * @policy: Policy object to modify.
+- * @new_policy: New policy data.
++ * @new_gov: Policy governor pointer.
++ * @new_pol: Policy value (for drivers with built-in governors).
+  *
+- * Pass @new_policy to the cpufreq driver's ->verify() callback. Next, copy the
+- * min and max parameters of @new_policy to @policy and either invoke the
+- * driver's ->setpolicy() callback (if present) or carry out a governor update
+- * for @policy.  That is, run the current governor's ->limits() callback (if the
+- * governor field in @new_policy points to the same object as the one in
+- * @policy) or replace the governor for @policy with the new one stored in
+- * @new_policy.
++ * Invoke the cpufreq driver's ->verify() callback to sanity-check the frequency
++ * limits to be set for the policy, update @policy with the verified limits
++ * values and either invoke the driver's ->setpolicy() callback (if present) or
++ * carry out a governor update for @policy.  That is, run the current governor's
++ * ->limits() callback (if @new_gov points to the same object as the one in
++ * @policy) or replace the governor for @policy with @new_gov.
+  *
+  * The cpuinfo part of @policy is not updated by this function.
+  */
+-int cpufreq_set_policy(struct cpufreq_policy *policy,
+-                     struct cpufreq_policy *new_policy)
++static int cpufreq_set_policy(struct cpufreq_policy *policy,
++                            struct cpufreq_governor *new_gov,
++                            unsigned int new_pol)
+ {
++      struct cpufreq_policy_data new_data;
+       struct cpufreq_governor *old_gov;
+       int ret;
+-      pr_debug("setting new policy for CPU %u: %u - %u kHz\n",
+-               new_policy->cpu, new_policy->min, new_policy->max);
+-
+-      memcpy(&new_policy->cpuinfo, &policy->cpuinfo, sizeof(policy->cpuinfo));
+-
++      memcpy(&new_data.cpuinfo, &policy->cpuinfo, sizeof(policy->cpuinfo));
++      new_data.freq_table = policy->freq_table;
++      new_data.cpu = policy->cpu;
+       /*
+        * PM QoS framework collects all the requests from users and provide us
+        * the final aggregated value here.
+        */
+-      new_policy->min = freq_qos_read_value(&policy->constraints, FREQ_QOS_MIN);
+-      new_policy->max = freq_qos_read_value(&policy->constraints, FREQ_QOS_MAX);
++      new_data.min = freq_qos_read_value(&policy->constraints, FREQ_QOS_MIN);
++      new_data.max = freq_qos_read_value(&policy->constraints, FREQ_QOS_MAX);
++
++      pr_debug("setting new policy for CPU %u: %u - %u kHz\n",
++               new_data.cpu, new_data.min, new_data.max);
+       /* verify the cpu speed can be set within this limit */
+-      ret = cpufreq_driver->verify(new_policy);
++      ret = cpufreq_driver->verify(&new_data);
+       if (ret)
+               return ret;
+-      policy->min = new_policy->min;
+-      policy->max = new_policy->max;
++      policy->min = new_data.min;
++      policy->max = new_data.max;
+       trace_cpu_frequency_limits(policy);
+       policy->cached_target_freq = UINT_MAX;
+@@ -2406,12 +2399,12 @@ int cpufreq_set_policy(struct cpufreq_po
+                policy->min, policy->max);
+       if (cpufreq_driver->setpolicy) {
+-              policy->policy = new_policy->policy;
++              policy->policy = new_pol;
+               pr_debug("setting range\n");
+               return cpufreq_driver->setpolicy(policy);
+       }
+-      if (new_policy->governor == policy->governor) {
++      if (new_gov == policy->governor) {
+               pr_debug("governor limits update\n");
+               cpufreq_governor_limits(policy);
+               return 0;
+@@ -2428,7 +2421,7 @@ int cpufreq_set_policy(struct cpufreq_po
+       }
+       /* start new governor */
+-      policy->governor = new_policy->governor;
++      policy->governor = new_gov;
+       ret = cpufreq_init_governor(policy);
+       if (!ret) {
+               ret = cpufreq_start_governor(policy);
+--- a/drivers/cpufreq/freq_table.c
++++ b/drivers/cpufreq/freq_table.c
+@@ -60,7 +60,7 @@ int cpufreq_frequency_table_cpuinfo(stru
+               return 0;
+ }
+-int cpufreq_frequency_table_verify(struct cpufreq_policy *policy,
++int cpufreq_frequency_table_verify(struct cpufreq_policy_data *policy,
+                                  struct cpufreq_frequency_table *table)
+ {
+       struct cpufreq_frequency_table *pos;
+@@ -100,7 +100,7 @@ EXPORT_SYMBOL_GPL(cpufreq_frequency_tabl
+  * Generic routine to verify policy & frequency table, requires driver to set
+  * policy->freq_table prior to it.
+  */
+-int cpufreq_generic_frequency_table_verify(struct cpufreq_policy *policy)
++int cpufreq_generic_frequency_table_verify(struct cpufreq_policy_data *policy)
+ {
+       if (!policy->freq_table)
+               return -ENODEV;
+--- a/drivers/cpufreq/gx-suspmod.c
++++ b/drivers/cpufreq/gx-suspmod.c
+@@ -328,7 +328,7 @@ static void gx_set_cpuspeed(struct cpufr
+  *      for the hardware supported by the driver.
+  */
+-static int cpufreq_gx_verify(struct cpufreq_policy *policy)
++static int cpufreq_gx_verify(struct cpufreq_policy_data *policy)
+ {
+       unsigned int tmp_freq = 0;
+       u8 tmp1, tmp2;
+--- a/drivers/cpufreq/intel_pstate.c
++++ b/drivers/cpufreq/intel_pstate.c
+@@ -2036,8 +2036,9 @@ static int intel_pstate_get_max_freq(str
+                       cpu->pstate.max_freq : cpu->pstate.turbo_freq;
+ }
+-static void intel_pstate_update_perf_limits(struct cpufreq_policy *policy,
+-                                          struct cpudata *cpu)
++static void intel_pstate_update_perf_limits(struct cpudata *cpu,
++                                          unsigned int policy_min,
++                                          unsigned int policy_max)
+ {
+       int max_freq = intel_pstate_get_max_freq(cpu);
+       int32_t max_policy_perf, min_policy_perf;
+@@ -2056,18 +2057,17 @@ static void intel_pstate_update_perf_lim
+               turbo_max = cpu->pstate.turbo_pstate;
+       }
+-      max_policy_perf = max_state * policy->max / max_freq;
+-      if (policy->max == policy->min) {
++      max_policy_perf = max_state * policy_max / max_freq;
++      if (policy_max == policy_min) {
+               min_policy_perf = max_policy_perf;
+       } else {
+-              min_policy_perf = max_state * policy->min / max_freq;
++              min_policy_perf = max_state * policy_min / max_freq;
+               min_policy_perf = clamp_t(int32_t, min_policy_perf,
+                                         0, max_policy_perf);
+       }
+       pr_debug("cpu:%d max_state %d min_policy_perf:%d max_policy_perf:%d\n",
+-               policy->cpu, max_state,
+-               min_policy_perf, max_policy_perf);
++               cpu->cpu, max_state, min_policy_perf, max_policy_perf);
+       /* Normalize user input to [min_perf, max_perf] */
+       if (per_cpu_limits) {
+@@ -2081,7 +2081,7 @@ static void intel_pstate_update_perf_lim
+               global_min = DIV_ROUND_UP(turbo_max * global.min_perf_pct, 100);
+               global_min = clamp_t(int32_t, global_min, 0, global_max);
+-              pr_debug("cpu:%d global_min:%d global_max:%d\n", policy->cpu,
++              pr_debug("cpu:%d global_min:%d global_max:%d\n", cpu->cpu,
+                        global_min, global_max);
+               cpu->min_perf_ratio = max(min_policy_perf, global_min);
+@@ -2094,7 +2094,7 @@ static void intel_pstate_update_perf_lim
+                                         cpu->max_perf_ratio);
+       }
+-      pr_debug("cpu:%d max_perf_ratio:%d min_perf_ratio:%d\n", policy->cpu,
++      pr_debug("cpu:%d max_perf_ratio:%d min_perf_ratio:%d\n", cpu->cpu,
+                cpu->max_perf_ratio,
+                cpu->min_perf_ratio);
+ }
+@@ -2114,7 +2114,7 @@ static int intel_pstate_set_policy(struc
+       mutex_lock(&intel_pstate_limits_lock);
+-      intel_pstate_update_perf_limits(policy, cpu);
++      intel_pstate_update_perf_limits(cpu, policy->min, policy->max);
+       if (cpu->policy == CPUFREQ_POLICY_PERFORMANCE) {
+               /*
+@@ -2143,8 +2143,8 @@ static int intel_pstate_set_policy(struc
+       return 0;
+ }
+-static void intel_pstate_adjust_policy_max(struct cpufreq_policy *policy,
+-                                       struct cpudata *cpu)
++static void intel_pstate_adjust_policy_max(struct cpudata *cpu,
++                                         struct cpufreq_policy_data *policy)
+ {
+       if (!hwp_active &&
+           cpu->pstate.max_pstate_physical > cpu->pstate.max_pstate &&
+@@ -2155,7 +2155,7 @@ static void intel_pstate_adjust_policy_m
+       }
+ }
+-static int intel_pstate_verify_policy(struct cpufreq_policy *policy)
++static int intel_pstate_verify_policy(struct cpufreq_policy_data *policy)
+ {
+       struct cpudata *cpu = all_cpu_data[policy->cpu];
+@@ -2163,11 +2163,7 @@ static int intel_pstate_verify_policy(st
+       cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq,
+                                    intel_pstate_get_max_freq(cpu));
+-      if (policy->policy != CPUFREQ_POLICY_POWERSAVE &&
+-          policy->policy != CPUFREQ_POLICY_PERFORMANCE)
+-              return -EINVAL;
+-
+-      intel_pstate_adjust_policy_max(policy, cpu);
++      intel_pstate_adjust_policy_max(cpu, policy);
+       return 0;
+ }
+@@ -2268,7 +2264,7 @@ static struct cpufreq_driver intel_pstat
+       .name           = "intel_pstate",
+ };
+-static int intel_cpufreq_verify_policy(struct cpufreq_policy *policy)
++static int intel_cpufreq_verify_policy(struct cpufreq_policy_data *policy)
+ {
+       struct cpudata *cpu = all_cpu_data[policy->cpu];
+@@ -2276,9 +2272,9 @@ static int intel_cpufreq_verify_policy(s
+       cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq,
+                                    intel_pstate_get_max_freq(cpu));
+-      intel_pstate_adjust_policy_max(policy, cpu);
++      intel_pstate_adjust_policy_max(cpu, policy);
+-      intel_pstate_update_perf_limits(policy, cpu);
++      intel_pstate_update_perf_limits(cpu, policy->min, policy->max);
+       return 0;
+ }
+--- a/drivers/cpufreq/longrun.c
++++ b/drivers/cpufreq/longrun.c
+@@ -122,7 +122,7 @@ static int longrun_set_policy(struct cpu
+  * Validates a new CPUFreq policy. This function has to be called with
+  * cpufreq_driver locked.
+  */
+-static int longrun_verify_policy(struct cpufreq_policy *policy)
++static int longrun_verify_policy(struct cpufreq_policy_data *policy)
+ {
+       if (!policy)
+               return -EINVAL;
+@@ -130,10 +130,6 @@ static int longrun_verify_policy(struct
+       policy->cpu = 0;
+       cpufreq_verify_within_cpu_limits(policy);
+-      if ((policy->policy != CPUFREQ_POLICY_POWERSAVE) &&
+-          (policy->policy != CPUFREQ_POLICY_PERFORMANCE))
+-              return -EINVAL;
+-
+       return 0;
+ }
+--- a/drivers/cpufreq/pcc-cpufreq.c
++++ b/drivers/cpufreq/pcc-cpufreq.c
+@@ -109,7 +109,7 @@ struct pcc_cpu {
+ static struct pcc_cpu __percpu *pcc_cpu_info;
+-static int pcc_cpufreq_verify(struct cpufreq_policy *policy)
++static int pcc_cpufreq_verify(struct cpufreq_policy_data *policy)
+ {
+       cpufreq_verify_within_cpu_limits(policy);
+       return 0;
+--- a/drivers/cpufreq/sh-cpufreq.c
++++ b/drivers/cpufreq/sh-cpufreq.c
+@@ -87,7 +87,7 @@ static int sh_cpufreq_target(struct cpuf
+       return work_on_cpu(policy->cpu, __sh_cpufreq_target, &data);
+ }
+-static int sh_cpufreq_verify(struct cpufreq_policy *policy)
++static int sh_cpufreq_verify(struct cpufreq_policy_data *policy)
+ {
+       struct clk *cpuclk = &per_cpu(sh_cpuclk, policy->cpu);
+       struct cpufreq_frequency_table *freq_table;
+--- a/drivers/cpufreq/unicore2-cpufreq.c
++++ b/drivers/cpufreq/unicore2-cpufreq.c
+@@ -22,7 +22,7 @@ static struct cpufreq_driver ucv2_driver
+ /* make sure that only the "userspace" governor is run
+  * -- anything else wouldn't make sense on this platform, anyway.
+  */
+-static int ucv2_verify_speed(struct cpufreq_policy *policy)
++static int ucv2_verify_speed(struct cpufreq_policy_data *policy)
+ {
+       if (policy->cpu)
+               return -EINVAL;
+--- a/include/linux/cpufreq.h
++++ b/include/linux/cpufreq.h
+@@ -148,6 +148,20 @@ struct cpufreq_policy {
+       struct notifier_block nb_max;
+ };
++/*
++ * Used for passing new cpufreq policy data to the cpufreq driver's ->verify()
++ * callback for sanitization.  That callback is only expected to modify the min
++ * and max values, if necessary, and specifically it must not update the
++ * frequency table.
++ */
++struct cpufreq_policy_data {
++      struct cpufreq_cpuinfo          cpuinfo;
++      struct cpufreq_frequency_table  *freq_table;
++      unsigned int                    cpu;
++      unsigned int                    min;    /* in kHz */
++      unsigned int                    max;    /* in kHz */
++};
++
+ struct cpufreq_freqs {
+       struct cpufreq_policy *policy;
+       unsigned int old;
+@@ -201,8 +215,6 @@ u64 get_cpu_idle_time(unsigned int cpu,
+ struct cpufreq_policy *cpufreq_cpu_acquire(unsigned int cpu);
+ void cpufreq_cpu_release(struct cpufreq_policy *policy);
+ int cpufreq_get_policy(struct cpufreq_policy *policy, unsigned int cpu);
+-int cpufreq_set_policy(struct cpufreq_policy *policy,
+-                     struct cpufreq_policy *new_policy);
+ void refresh_frequency_limits(struct cpufreq_policy *policy);
+ void cpufreq_update_policy(unsigned int cpu);
+ void cpufreq_update_limits(unsigned int cpu);
+@@ -284,7 +296,7 @@ struct cpufreq_driver {
+       /* needed by all drivers */
+       int             (*init)(struct cpufreq_policy *policy);
+-      int             (*verify)(struct cpufreq_policy *policy);
++      int             (*verify)(struct cpufreq_policy_data *policy);
+       /* define one out of two */
+       int             (*setpolicy)(struct cpufreq_policy *policy);
+@@ -415,8 +427,9 @@ static inline int cpufreq_thermal_contro
+               (drv->flags & CPUFREQ_IS_COOLING_DEV);
+ }
+-static inline void cpufreq_verify_within_limits(struct cpufreq_policy *policy,
+-              unsigned int min, unsigned int max)
++static inline void cpufreq_verify_within_limits(struct cpufreq_policy_data *policy,
++                                              unsigned int min,
++                                              unsigned int max)
+ {
+       if (policy->min < min)
+               policy->min = min;
+@@ -432,10 +445,10 @@ static inline void cpufreq_verify_within
+ }
+ static inline void
+-cpufreq_verify_within_cpu_limits(struct cpufreq_policy *policy)
++cpufreq_verify_within_cpu_limits(struct cpufreq_policy_data *policy)
+ {
+       cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq,
+-                      policy->cpuinfo.max_freq);
++                                   policy->cpuinfo.max_freq);
+ }
+ #ifdef CONFIG_CPU_FREQ
+@@ -513,6 +526,7 @@ static inline unsigned long cpufreq_scal
+  *                          CPUFREQ GOVERNORS                        *
+  *********************************************************************/
++#define CPUFREQ_POLICY_UNKNOWN                (0)
+ /*
+  * If (cpufreq_driver->target) exists, the ->governor decides what frequency
+  * within the limits is used. If (cpufreq_driver->setpolicy> exists, these
+@@ -684,9 +698,9 @@ static inline void dev_pm_opp_free_cpufr
+ int cpufreq_frequency_table_cpuinfo(struct cpufreq_policy *policy,
+                                   struct cpufreq_frequency_table *table);
+-int cpufreq_frequency_table_verify(struct cpufreq_policy *policy,
++int cpufreq_frequency_table_verify(struct cpufreq_policy_data *policy,
+                                  struct cpufreq_frequency_table *table);
+-int cpufreq_generic_frequency_table_verify(struct cpufreq_policy *policy);
++int cpufreq_generic_frequency_table_verify(struct cpufreq_policy_data *policy);
+ int cpufreq_table_index_unsorted(struct cpufreq_policy *policy,
+                                unsigned int target_freq,
diff --git a/queue-5.4/f2fs-choose-hardlimit-when-softlimit-is-larger-than-hardlimit-in-f2fs_statfs_project.patch b/queue-5.4/f2fs-choose-hardlimit-when-softlimit-is-larger-than-hardlimit-in-f2fs_statfs_project.patch
new file mode 100644 (file)
index 0000000..de4f587
--- /dev/null
@@ -0,0 +1,58 @@
+From 909110c060f22e65756659ec6fa957ae75777e00 Mon Sep 17 00:00:00 2001
+From: Chengguang Xu <cgxu519@mykernel.net>
+Date: Mon, 25 Nov 2019 11:20:36 +0800
+Subject: f2fs: choose hardlimit when softlimit is larger than hardlimit in f2fs_statfs_project()
+
+From: Chengguang Xu <cgxu519@mykernel.net>
+
+commit 909110c060f22e65756659ec6fa957ae75777e00 upstream.
+
+Setting softlimit larger than hardlimit seems meaningless
+for disk quota but currently it is allowed. In this case,
+there may be a bit of comfusion for users when they run
+df comamnd to directory which has project quota.
+
+For example, we set 20M softlimit and 10M hardlimit of
+block usage limit for project quota of test_dir(project id 123).
+
+[root@hades f2fs]# repquota -P -a
+---
+ fs/f2fs/super.c |   20 ++++++++++++++------
+ 1 file changed, 14 insertions(+), 6 deletions(-)
+
+--- a/fs/f2fs/super.c
++++ b/fs/f2fs/super.c
+@@ -1213,9 +1213,13 @@ static int f2fs_statfs_project(struct su
+               return PTR_ERR(dquot);
+       spin_lock(&dquot->dq_dqb_lock);
+-      limit = (dquot->dq_dqb.dqb_bsoftlimit ?
+-               dquot->dq_dqb.dqb_bsoftlimit :
+-               dquot->dq_dqb.dqb_bhardlimit) >> sb->s_blocksize_bits;
++      limit = 0;
++      if (dquot->dq_dqb.dqb_bsoftlimit)
++              limit = dquot->dq_dqb.dqb_bsoftlimit;
++      if (dquot->dq_dqb.dqb_bhardlimit &&
++                      (!limit || dquot->dq_dqb.dqb_bhardlimit < limit))
++              limit = dquot->dq_dqb.dqb_bhardlimit;
++
+       if (limit && buf->f_blocks > limit) {
+               curblock = dquot->dq_dqb.dqb_curspace >> sb->s_blocksize_bits;
+               buf->f_blocks = limit;
+@@ -1224,9 +1228,13 @@ static int f2fs_statfs_project(struct su
+                        (buf->f_blocks - curblock) : 0;
+       }
+-      limit = dquot->dq_dqb.dqb_isoftlimit ?
+-              dquot->dq_dqb.dqb_isoftlimit :
+-              dquot->dq_dqb.dqb_ihardlimit;
++      limit = 0;
++      if (dquot->dq_dqb.dqb_isoftlimit)
++              limit = dquot->dq_dqb.dqb_isoftlimit;
++      if (dquot->dq_dqb.dqb_ihardlimit &&
++                      (!limit || dquot->dq_dqb.dqb_ihardlimit < limit))
++              limit = dquot->dq_dqb.dqb_ihardlimit;
++
+       if (limit && buf->f_files > limit) {
+               buf->f_files = limit;
+               buf->f_ffree =
diff --git a/queue-5.4/f2fs-code-cleanup-for-f2fs_statfs_project.patch b/queue-5.4/f2fs-code-cleanup-for-f2fs_statfs_project.patch
new file mode 100644 (file)
index 0000000..fb0a36a
--- /dev/null
@@ -0,0 +1,53 @@
+From bf2cbd3c57159c2b639ee8797b52ab5af180bf83 Mon Sep 17 00:00:00 2001
+From: Chengguang Xu <cgxu519@mykernel.net>
+Date: Sat, 4 Jan 2020 22:20:04 +0800
+Subject: f2fs: code cleanup for f2fs_statfs_project()
+
+From: Chengguang Xu <cgxu519@mykernel.net>
+
+commit bf2cbd3c57159c2b639ee8797b52ab5af180bf83 upstream.
+
+Calling min_not_zero() to simplify complicated prjquota
+limit comparison in f2fs_statfs_project().
+
+Signed-off-by: Chengguang Xu <cgxu519@mykernel.net>
+Reviewed-by: Chao Yu <yuchao0@huawei.com>
+Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/f2fs/super.c |   16 ++++------------
+ 1 file changed, 4 insertions(+), 12 deletions(-)
+
+--- a/fs/f2fs/super.c
++++ b/fs/f2fs/super.c
+@@ -1213,12 +1213,8 @@ static int f2fs_statfs_project(struct su
+               return PTR_ERR(dquot);
+       spin_lock(&dquot->dq_dqb_lock);
+-      limit = 0;
+-      if (dquot->dq_dqb.dqb_bsoftlimit)
+-              limit = dquot->dq_dqb.dqb_bsoftlimit;
+-      if (dquot->dq_dqb.dqb_bhardlimit &&
+-                      (!limit || dquot->dq_dqb.dqb_bhardlimit < limit))
+-              limit = dquot->dq_dqb.dqb_bhardlimit;
++      limit = min_not_zero(dquot->dq_dqb.dqb_bsoftlimit,
++                                      dquot->dq_dqb.dqb_bhardlimit);
+       if (limit)
+               limit >>= sb->s_blocksize_bits;
+@@ -1230,12 +1226,8 @@ static int f2fs_statfs_project(struct su
+                        (buf->f_blocks - curblock) : 0;
+       }
+-      limit = 0;
+-      if (dquot->dq_dqb.dqb_isoftlimit)
+-              limit = dquot->dq_dqb.dqb_isoftlimit;
+-      if (dquot->dq_dqb.dqb_ihardlimit &&
+-                      (!limit || dquot->dq_dqb.dqb_ihardlimit < limit))
+-              limit = dquot->dq_dqb.dqb_ihardlimit;
++      limit = min_not_zero(dquot->dq_dqb.dqb_isoftlimit,
++                                      dquot->dq_dqb.dqb_ihardlimit);
+       if (limit && buf->f_files > limit) {
+               buf->f_files = limit;
diff --git a/queue-5.4/f2fs-fix-dcache-lookup-of-casefolded-directories.patch b/queue-5.4/f2fs-fix-dcache-lookup-of-casefolded-directories.patch
new file mode 100644 (file)
index 0000000..397fec5
--- /dev/null
@@ -0,0 +1,35 @@
+From 5515eae647426169e4b7969271fb207881eba7f6 Mon Sep 17 00:00:00 2001
+From: Eric Biggers <ebiggers@google.com>
+Date: Thu, 23 Jan 2020 20:15:48 -0800
+Subject: f2fs: fix dcache lookup of !casefolded directories
+
+From: Eric Biggers <ebiggers@google.com>
+
+commit 5515eae647426169e4b7969271fb207881eba7f6 upstream.
+
+Do the name comparison for non-casefolded directories correctly.
+
+This is analogous to ext4's commit 66883da1eee8 ("ext4: fix dcache
+lookup of !casefolded directories").
+
+Fixes: 2c2eb7a300cd ("f2fs: Support case-insensitive file name lookups")
+Cc: <stable@vger.kernel.org> # v5.4+
+Signed-off-by: Eric Biggers <ebiggers@google.com>
+Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/f2fs/dir.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/fs/f2fs/dir.c
++++ b/fs/f2fs/dir.c
+@@ -1072,7 +1072,7 @@ static int f2fs_d_compare(const struct d
+       if (!IS_CASEFOLDED(dentry->d_parent->d_inode)) {
+               if (len != name->len)
+                       return -1;
+-              return memcmp(str, name, len);
++              return memcmp(str, name->name, len);
+       }
+       return f2fs_ci_compare(dentry->d_parent->d_inode, name, &qstr, false);
diff --git a/queue-5.4/f2fs-fix-miscounted-block-limit-in-f2fs_statfs_project.patch b/queue-5.4/f2fs-fix-miscounted-block-limit-in-f2fs_statfs_project.patch
new file mode 100644 (file)
index 0000000..3062b21
--- /dev/null
@@ -0,0 +1,33 @@
+From acdf2172172a511f97fa21ed0ee7609a6d3b3a07 Mon Sep 17 00:00:00 2001
+From: Chengguang Xu <cgxu519@mykernel.net>
+Date: Sat, 4 Jan 2020 22:20:03 +0800
+Subject: f2fs: fix miscounted block limit in f2fs_statfs_project()
+
+From: Chengguang Xu <cgxu519@mykernel.net>
+
+commit acdf2172172a511f97fa21ed0ee7609a6d3b3a07 upstream.
+
+statfs calculates Total/Used/Avail disk space in block unit,
+so we should translate soft/hard prjquota limit to block unit
+as well.
+
+Below testing result shows the block/inode numbers of
+Total/Used/Avail from df command are all correct afer
+applying this patch.
+
+[root@localhost quota-tools]\# ./repquota -P /dev/sdb1
+---
+ fs/f2fs/super.c |    2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/fs/f2fs/super.c
++++ b/fs/f2fs/super.c
+@@ -1219,6 +1219,8 @@ static int f2fs_statfs_project(struct su
+       if (dquot->dq_dqb.dqb_bhardlimit &&
+                       (!limit || dquot->dq_dqb.dqb_bhardlimit < limit))
+               limit = dquot->dq_dqb.dqb_bhardlimit;
++      if (limit)
++              limit >>= sb->s_blocksize_bits;
+       if (limit && buf->f_blocks > limit) {
+               curblock = dquot->dq_dqb.dqb_curspace >> sb->s_blocksize_bits;
diff --git a/queue-5.4/f2fs-fix-race-conditions-in-d_compare-and-d_hash.patch b/queue-5.4/f2fs-fix-race-conditions-in-d_compare-and-d_hash.patch
new file mode 100644 (file)
index 0000000..711c3d0
--- /dev/null
@@ -0,0 +1,82 @@
+From 80f2388afa6ef985f9c5c228e36705c4d4db4756 Mon Sep 17 00:00:00 2001
+From: Eric Biggers <ebiggers@google.com>
+Date: Thu, 23 Jan 2020 20:15:49 -0800
+Subject: f2fs: fix race conditions in ->d_compare() and ->d_hash()
+
+From: Eric Biggers <ebiggers@google.com>
+
+commit 80f2388afa6ef985f9c5c228e36705c4d4db4756 upstream.
+
+Since ->d_compare() and ->d_hash() can be called in RCU-walk mode,
+->d_parent and ->d_inode can be concurrently modified, and in
+particular, ->d_inode may be changed to NULL.  For f2fs_d_hash() this
+resulted in a reproducible NULL dereference if a lookup is done in a
+directory being deleted, e.g. with:
+
+       int main()
+       {
+               if (fork()) {
+                       for (;;) {
+                               mkdir("subdir", 0700);
+                               rmdir("subdir");
+                       }
+               } else {
+                       for (;;)
+                               access("subdir/file", 0);
+               }
+       }
+
+... or by running the 't_encrypted_d_revalidate' program from xfstests.
+Both repros work in any directory on a filesystem with the encoding
+feature, even if the directory doesn't actually have the casefold flag.
+
+I couldn't reproduce a crash in f2fs_d_compare(), but it appears that a
+similar crash is possible there.
+
+Fix these bugs by reading ->d_parent and ->d_inode using READ_ONCE() and
+falling back to the case sensitive behavior if the inode is NULL.
+
+Reported-by: Al Viro <viro@zeniv.linux.org.uk>
+Fixes: 2c2eb7a300cd ("f2fs: Support case-insensitive file name lookups")
+Cc: <stable@vger.kernel.org> # v5.4+
+Signed-off-by: Eric Biggers <ebiggers@google.com>
+Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/f2fs/dir.c |    9 ++++++---
+ 1 file changed, 6 insertions(+), 3 deletions(-)
+
+--- a/fs/f2fs/dir.c
++++ b/fs/f2fs/dir.c
+@@ -1068,24 +1068,27 @@ static int f2fs_d_compare(const struct d
+                         const char *str, const struct qstr *name)
+ {
+       struct qstr qstr = {.name = str, .len = len };
++      const struct dentry *parent = READ_ONCE(dentry->d_parent);
++      const struct inode *inode = READ_ONCE(parent->d_inode);
+-      if (!IS_CASEFOLDED(dentry->d_parent->d_inode)) {
++      if (!inode || !IS_CASEFOLDED(inode)) {
+               if (len != name->len)
+                       return -1;
+               return memcmp(str, name->name, len);
+       }
+-      return f2fs_ci_compare(dentry->d_parent->d_inode, name, &qstr, false);
++      return f2fs_ci_compare(inode, name, &qstr, false);
+ }
+ static int f2fs_d_hash(const struct dentry *dentry, struct qstr *str)
+ {
+       struct f2fs_sb_info *sbi = F2FS_SB(dentry->d_sb);
+       const struct unicode_map *um = sbi->s_encoding;
++      const struct inode *inode = READ_ONCE(dentry->d_inode);
+       unsigned char *norm;
+       int len, ret = 0;
+-      if (!IS_CASEFOLDED(dentry->d_inode))
++      if (!inode || !IS_CASEFOLDED(inode))
+               return 0;
+       norm = f2fs_kmalloc(sbi, PATH_MAX, GFP_ATOMIC);
diff --git a/queue-5.4/ovl-fix-lseek-overflow-on-32bit.patch b/queue-5.4/ovl-fix-lseek-overflow-on-32bit.patch
new file mode 100644 (file)
index 0000000..9534242
--- /dev/null
@@ -0,0 +1,35 @@
+From a4ac9d45c0cd14a2adc872186431c79804b77dbf Mon Sep 17 00:00:00 2001
+From: Miklos Szeredi <mszeredi@redhat.com>
+Date: Mon, 3 Feb 2020 11:41:53 +0100
+Subject: ovl: fix lseek overflow on 32bit
+
+From: Miklos Szeredi <mszeredi@redhat.com>
+
+commit a4ac9d45c0cd14a2adc872186431c79804b77dbf upstream.
+
+ovl_lseek() is using ssize_t to return the value from vfs_llseek().  On a
+32-bit kernel ssize_t is a 32-bit signed int, which overflows above 2 GB.
+
+Assign the return value of vfs_llseek() to loff_t to fix this.
+
+Reported-by: Boris Gjenero <boris.gjenero@gmail.com>
+Fixes: 9e46b840c705 ("ovl: support stacked SEEK_HOLE/SEEK_DATA")
+Cc: <stable@vger.kernel.org> # v4.19
+Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/overlayfs/file.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/fs/overlayfs/file.c
++++ b/fs/overlayfs/file.c
+@@ -146,7 +146,7 @@ static loff_t ovl_llseek(struct file *fi
+       struct inode *inode = file_inode(file);
+       struct fd real;
+       const struct cred *old_cred;
+-      ssize_t ret;
++      loff_t ret;
+       /*
+        * The two special cases below do not need to involve real fs,
diff --git a/queue-5.4/ovl-fix-wrong-warn_on-in-ovl_cache_update_ino.patch b/queue-5.4/ovl-fix-wrong-warn_on-in-ovl_cache_update_ino.patch
new file mode 100644 (file)
index 0000000..bc4078f
--- /dev/null
@@ -0,0 +1,43 @@
+From 4c37e71b713ecffe81f8e6273c6835e54306d412 Mon Sep 17 00:00:00 2001
+From: Amir Goldstein <amir73il@gmail.com>
+Date: Sun, 22 Dec 2019 22:47:54 +0200
+Subject: ovl: fix wrong WARN_ON() in ovl_cache_update_ino()
+
+From: Amir Goldstein <amir73il@gmail.com>
+
+commit 4c37e71b713ecffe81f8e6273c6835e54306d412 upstream.
+
+The WARN_ON() that child entry is always on overlay st_dev became wrong
+when we allowed this function to update d_ino in non-samefs setup with xino
+enabled.
+
+It is not true in case of xino bits overflow on a non-dir inode.  Leave the
+WARN_ON() only for directories, where assertion is still true.
+
+Fixes: adbf4f7ea834 ("ovl: consistent d_ino for non-samefs with xino")
+Cc: <stable@vger.kernel.org> # v4.17+
+Signed-off-by: Amir Goldstein <amir73il@gmail.com>
+Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/overlayfs/readdir.c |    8 +++++++-
+ 1 file changed, 7 insertions(+), 1 deletion(-)
+
+--- a/fs/overlayfs/readdir.c
++++ b/fs/overlayfs/readdir.c
+@@ -504,7 +504,13 @@ get:
+               if (err)
+                       goto fail;
+-              WARN_ON_ONCE(dir->d_sb->s_dev != stat.dev);
++              /*
++               * Directory inode is always on overlay st_dev.
++               * Non-dir with ovl_same_dev() could be on pseudo st_dev in case
++               * of xino bits overflow.
++               */
++              WARN_ON_ONCE(S_ISDIR(stat.mode) &&
++                           dir->d_sb->s_dev != stat.dev);
+               ino = stat.ino;
+       } else if (xinobits && !OVL_TYPE_UPPER(type)) {
+               ino = ovl_remap_lower_ino(ino, xinobits,
diff --git a/queue-5.4/pm-core-fix-handling-of-devices-deleted-during-system-wide-resume.patch b/queue-5.4/pm-core-fix-handling-of-devices-deleted-during-system-wide-resume.patch
new file mode 100644 (file)
index 0000000..eee609c
--- /dev/null
@@ -0,0 +1,123 @@
+From 0552e05fdfea191a2cf3a0abd33574b5ef9ca818 Mon Sep 17 00:00:00 2001
+From: "Rafael J. Wysocki" <rafael.j.wysocki@intel.com>
+Date: Thu, 23 Jan 2020 00:11:24 +0100
+Subject: PM: core: Fix handling of devices deleted during system-wide resume
+
+From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+
+commit 0552e05fdfea191a2cf3a0abd33574b5ef9ca818 upstream.
+
+If a device is deleted by one of its system-wide resume callbacks
+(for example, because it does not appear to be present or accessible
+any more) along with its children, the resume of the children may
+continue leading to use-after-free errors and other issues
+(potentially).
+
+Namely, if the device's children are resumed asynchronously, their
+resume may have been scheduled already before the device's callback
+runs and so the device may be deleted while dpm_wait_for_superior()
+is being executed for them.  The memory taken up by the parent device
+object may be freed then while dpm_wait() is waiting for the parent's
+resume callback to complete, which leads to a use-after-free.
+Moreover, the resume of the children is really not expected to
+continue after they have been unregistered, so it must be terminated
+right away in that case.
+
+To address this problem, modify dpm_wait_for_superior() to check
+if the target device is still there in the system-wide PM list of
+devices and if so, to increment its parent's reference counter, both
+under dpm_list_mtx which prevents device_del() running for the child
+from dropping the parent's reference counter prematurely.
+
+If the device is not present in the system-wide PM list of devices
+any more, the resume of it cannot continue, so check that again after
+dpm_wait() returns, which means that the parent's callback has been
+completed, and pass the result of that check to the caller of
+dpm_wait_for_superior() to allow it to abort the device's resume
+if it is not there any more.
+
+Link: https://lore.kernel.org/linux-pm/1579568452-27253-1-git-send-email-chanho.min@lge.com
+Reported-by: Chanho Min <chanho.min@lge.com>
+Cc: All applicable <stable@vger.kernel.org>
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/base/power/main.c |   42 +++++++++++++++++++++++++++++++++++++-----
+ 1 file changed, 37 insertions(+), 5 deletions(-)
+
+--- a/drivers/base/power/main.c
++++ b/drivers/base/power/main.c
+@@ -273,10 +273,38 @@ static void dpm_wait_for_suppliers(struc
+       device_links_read_unlock(idx);
+ }
+-static void dpm_wait_for_superior(struct device *dev, bool async)
++static bool dpm_wait_for_superior(struct device *dev, bool async)
+ {
+-      dpm_wait(dev->parent, async);
++      struct device *parent;
++
++      /*
++       * If the device is resumed asynchronously and the parent's callback
++       * deletes both the device and the parent itself, the parent object may
++       * be freed while this function is running, so avoid that by reference
++       * counting the parent once more unless the device has been deleted
++       * already (in which case return right away).
++       */
++      mutex_lock(&dpm_list_mtx);
++
++      if (!device_pm_initialized(dev)) {
++              mutex_unlock(&dpm_list_mtx);
++              return false;
++      }
++
++      parent = get_device(dev->parent);
++
++      mutex_unlock(&dpm_list_mtx);
++
++      dpm_wait(parent, async);
++      put_device(parent);
++
+       dpm_wait_for_suppliers(dev, async);
++
++      /*
++       * If the parent's callback has deleted the device, attempting to resume
++       * it would be invalid, so avoid doing that then.
++       */
++      return device_pm_initialized(dev);
+ }
+ static void dpm_wait_for_consumers(struct device *dev, bool async)
+@@ -621,7 +649,8 @@ static int device_resume_noirq(struct de
+       if (!dev->power.is_noirq_suspended)
+               goto Out;
+-      dpm_wait_for_superior(dev, async);
++      if (!dpm_wait_for_superior(dev, async))
++              goto Out;
+       skip_resume = dev_pm_may_skip_resume(dev);
+@@ -829,7 +858,8 @@ static int device_resume_early(struct de
+       if (!dev->power.is_late_suspended)
+               goto Out;
+-      dpm_wait_for_superior(dev, async);
++      if (!dpm_wait_for_superior(dev, async))
++              goto Out;
+       callback = dpm_subsys_resume_early_cb(dev, state, &info);
+@@ -944,7 +974,9 @@ static int device_resume(struct device *
+               goto Complete;
+       }
+-      dpm_wait_for_superior(dev, async);
++      if (!dpm_wait_for_superior(dev, async))
++              goto Complete;
++
+       dpm_watchdog_set(&wd, dev);
+       device_lock(dev);
index a993d046d45590191f04e7134eaad6bcef1aa869..63b63aca88496f2ad77a98e43c8431b520537b51 100644 (file)
@@ -113,3 +113,12 @@ scsi-qla2xxx-fix-mtcp-dump-collection-failure.patch
 cpupower-revert-library-abi-changes-from-commit-ae2917093fb60bdc1ed3e.patch
 power-supply-axp20x_ac_power-fix-reporting-online-status.patch
 power-supply-ltc2941-battery-gauge-fix-use-after-free.patch
+ovl-fix-wrong-warn_on-in-ovl_cache_update_ino.patch
+ovl-fix-lseek-overflow-on-32bit.patch
+f2fs-choose-hardlimit-when-softlimit-is-larger-than-hardlimit-in-f2fs_statfs_project.patch
+f2fs-fix-miscounted-block-limit-in-f2fs_statfs_project.patch
+f2fs-code-cleanup-for-f2fs_statfs_project.patch
+f2fs-fix-dcache-lookup-of-casefolded-directories.patch
+f2fs-fix-race-conditions-in-d_compare-and-d_hash.patch
+pm-core-fix-handling-of-devices-deleted-during-system-wide-resume.patch
+cpufreq-avoid-creating-excessively-large-stack-frames.patch