From 69de793cec64d120892e02b08e03ae1a34fa5bf3 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 7 Feb 2020 11:28:14 +0100 Subject: [PATCH] 4.14-stable patches added patches: f2fs-choose-hardlimit-when-softlimit-is-larger-than-hardlimit-in-f2fs_statfs_project.patch f2fs-code-cleanup-for-f2fs_statfs_project.patch f2fs-fix-miscounted-block-limit-in-f2fs_statfs_project.patch pm-core-fix-handling-of-devices-deleted-during-system-wide-resume.patch --- ...han-hardlimit-in-f2fs_statfs_project.patch | 58 +++++++++ ...code-cleanup-for-f2fs_statfs_project.patch | 53 ++++++++ ...d-block-limit-in-f2fs_statfs_project.patch | 33 +++++ ...es-deleted-during-system-wide-resume.patch | 123 ++++++++++++++++++ queue-4.14/series | 4 + 5 files changed, 271 insertions(+) create mode 100644 queue-4.14/f2fs-choose-hardlimit-when-softlimit-is-larger-than-hardlimit-in-f2fs_statfs_project.patch create mode 100644 queue-4.14/f2fs-code-cleanup-for-f2fs_statfs_project.patch create mode 100644 queue-4.14/f2fs-fix-miscounted-block-limit-in-f2fs_statfs_project.patch create mode 100644 queue-4.14/pm-core-fix-handling-of-devices-deleted-during-system-wide-resume.patch diff --git a/queue-4.14/f2fs-choose-hardlimit-when-softlimit-is-larger-than-hardlimit-in-f2fs_statfs_project.patch b/queue-4.14/f2fs-choose-hardlimit-when-softlimit-is-larger-than-hardlimit-in-f2fs_statfs_project.patch new file mode 100644 index 00000000000..5d539d1dcad --- /dev/null +++ b/queue-4.14/f2fs-choose-hardlimit-when-softlimit-is-larger-than-hardlimit-in-f2fs_statfs_project.patch @@ -0,0 +1,58 @@ +From 909110c060f22e65756659ec6fa957ae75777e00 Mon Sep 17 00:00:00 2001 +From: Chengguang Xu +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 + +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 +@@ -912,9 +912,13 @@ static int f2fs_statfs_project(struct su + return PTR_ERR(dquot); + spin_lock(&dq_data_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; +@@ -923,9 +927,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-4.14/f2fs-code-cleanup-for-f2fs_statfs_project.patch b/queue-4.14/f2fs-code-cleanup-for-f2fs_statfs_project.patch new file mode 100644 index 00000000000..5609b6c8db6 --- /dev/null +++ b/queue-4.14/f2fs-code-cleanup-for-f2fs_statfs_project.patch @@ -0,0 +1,53 @@ +From bf2cbd3c57159c2b639ee8797b52ab5af180bf83 Mon Sep 17 00:00:00 2001 +From: Chengguang Xu +Date: Sat, 4 Jan 2020 22:20:04 +0800 +Subject: f2fs: code cleanup for f2fs_statfs_project() + +From: Chengguang Xu + +commit bf2cbd3c57159c2b639ee8797b52ab5af180bf83 upstream. + +Calling min_not_zero() to simplify complicated prjquota +limit comparison in f2fs_statfs_project(). + +Signed-off-by: Chengguang Xu +Reviewed-by: Chao Yu +Signed-off-by: Jaegeuk Kim +Signed-off-by: Greg Kroah-Hartman + +--- + fs/f2fs/super.c | 16 ++++------------ + 1 file changed, 4 insertions(+), 12 deletions(-) + +--- a/fs/f2fs/super.c ++++ b/fs/f2fs/super.c +@@ -912,12 +912,8 @@ static int f2fs_statfs_project(struct su + return PTR_ERR(dquot); + spin_lock(&dq_data_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; + +@@ -929,12 +925,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-4.14/f2fs-fix-miscounted-block-limit-in-f2fs_statfs_project.patch b/queue-4.14/f2fs-fix-miscounted-block-limit-in-f2fs_statfs_project.patch new file mode 100644 index 00000000000..268952318c6 --- /dev/null +++ b/queue-4.14/f2fs-fix-miscounted-block-limit-in-f2fs_statfs_project.patch @@ -0,0 +1,33 @@ +From acdf2172172a511f97fa21ed0ee7609a6d3b3a07 Mon Sep 17 00:00:00 2001 +From: Chengguang Xu +Date: Sat, 4 Jan 2020 22:20:03 +0800 +Subject: f2fs: fix miscounted block limit in f2fs_statfs_project() + +From: Chengguang Xu + +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 +@@ -918,6 +918,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-4.14/pm-core-fix-handling-of-devices-deleted-during-system-wide-resume.patch b/queue-4.14/pm-core-fix-handling-of-devices-deleted-during-system-wide-resume.patch new file mode 100644 index 00000000000..04ef8535106 --- /dev/null +++ b/queue-4.14/pm-core-fix-handling-of-devices-deleted-during-system-wide-resume.patch @@ -0,0 +1,123 @@ +From 0552e05fdfea191a2cf3a0abd33574b5ef9ca818 Mon Sep 17 00:00:00 2001 +From: "Rafael J. Wysocki" +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 + +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 +Cc: All applicable +Signed-off-by: Rafael J. Wysocki +Acked-by: Greg Kroah-Hartman +Signed-off-by: Greg Kroah-Hartman + +--- + 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 +@@ -269,10 +269,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) +@@ -551,7 +579,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; + + if (dev->pm_domain) { + info = "noirq power domain "; +@@ -691,7 +720,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; + + if (dev->pm_domain) { + info = "early power domain "; +@@ -823,7 +853,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); + diff --git a/queue-4.14/series b/queue-4.14/series index 1417c3ebd33..0b6613e3fd9 100644 --- a/queue-4.14/series +++ b/queue-4.14/series @@ -46,3 +46,7 @@ hv_balloon-balloon-up-according-to-request-page-number.patch crypto-api-check-spawn-alg-under-lock-in-crypto_drop_spawn.patch scsi-qla2xxx-fix-mtcp-dump-collection-failure.patch power-supply-ltc2941-battery-gauge-fix-use-after-free.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 +pm-core-fix-handling-of-devices-deleted-during-system-wide-resume.patch -- 2.47.3