From: Greg Kroah-Hartman Date: Fri, 15 May 2015 01:42:04 +0000 (-0700) Subject: 4.0-stable patches X-Git-Tag: v3.10.79~28 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=5e10d36af8dda644828d07e08d7b0338046e1172;p=thirdparty%2Fkernel%2Fstable-queue.git 4.0-stable patches added patches: ocfs2-dlm-fix-race-between-purge-and-get-lock-resource.patch rtc-armada38x-fix-concurrency-access-in-armada38x_rtc_set_time.patch --- diff --git a/queue-4.0/ocfs2-dlm-fix-race-between-purge-and-get-lock-resource.patch b/queue-4.0/ocfs2-dlm-fix-race-between-purge-and-get-lock-resource.patch new file mode 100644 index 00000000000..f77c0831c97 --- /dev/null +++ b/queue-4.0/ocfs2-dlm-fix-race-between-purge-and-get-lock-resource.patch @@ -0,0 +1,62 @@ +From b1432a2a35565f538586774a03bf277c27fc267d Mon Sep 17 00:00:00 2001 +From: Junxiao Bi +Date: Tue, 5 May 2015 16:24:02 -0700 +Subject: ocfs2: dlm: fix race between purge and get lock resource + +From: Junxiao Bi + +commit b1432a2a35565f538586774a03bf277c27fc267d upstream. + +There is a race window in dlm_get_lock_resource(), which may return a +lock resource which has been purged. This will cause the process to +hang forever in dlmlock() as the ast msg can't be handled due to its +lock resource not existing. + + dlm_get_lock_resource { + ... + spin_lock(&dlm->spinlock); + tmpres = __dlm_lookup_lockres_full(dlm, lockid, namelen, hash); + if (tmpres) { + spin_unlock(&dlm->spinlock); + >>>>>>>> race window, dlm_run_purge_list() may run and purge + the lock resource + spin_lock(&tmpres->spinlock); + ... + spin_unlock(&tmpres->spinlock); + } + } + +Signed-off-by: Junxiao Bi +Cc: Joseph Qi +Cc: Mark Fasheh +Cc: Joel Becker +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman + +--- + fs/ocfs2/dlm/dlmmaster.c | 13 +++++++++++++ + 1 file changed, 13 insertions(+) + +--- a/fs/ocfs2/dlm/dlmmaster.c ++++ b/fs/ocfs2/dlm/dlmmaster.c +@@ -757,6 +757,19 @@ lookup: + if (tmpres) { + spin_unlock(&dlm->spinlock); + spin_lock(&tmpres->spinlock); ++ ++ /* ++ * Right after dlm spinlock was released, dlm_thread could have ++ * purged the lockres. Check if lockres got unhashed. If so ++ * start over. ++ */ ++ if (hlist_unhashed(&tmpres->hash_node)) { ++ spin_unlock(&tmpres->spinlock); ++ dlm_lockres_put(tmpres); ++ tmpres = NULL; ++ goto lookup; ++ } ++ + /* Wait on the thread that is mastering the resource */ + if (tmpres->owner == DLM_LOCK_RES_OWNER_UNKNOWN) { + __dlm_wait_on_lockres(tmpres); diff --git a/queue-4.0/rtc-armada38x-fix-concurrency-access-in-armada38x_rtc_set_time.patch b/queue-4.0/rtc-armada38x-fix-concurrency-access-in-armada38x_rtc_set_time.patch new file mode 100644 index 00000000000..c66badca08e --- /dev/null +++ b/queue-4.0/rtc-armada38x-fix-concurrency-access-in-armada38x_rtc_set_time.patch @@ -0,0 +1,95 @@ +From 489405fe5ed38e65f6f82f131a39c67f3bae6045 Mon Sep 17 00:00:00 2001 +From: Gregory CLEMENT +Date: Tue, 5 May 2015 16:24:05 -0700 +Subject: rtc: armada38x: fix concurrency access in armada38x_rtc_set_time + +From: Gregory CLEMENT + +commit 489405fe5ed38e65f6f82f131a39c67f3bae6045 upstream. + +While setting the time, the RTC TIME register should not be accessed. +However due to hardware constraints, setting the RTC time involves +sleeping during 100ms. This sleep was done outside the critical section +protected by the spinlock, so it was possible to read the RTC TIME +register and get an incorrect value. This patch introduces a mutex for +protecting the RTC TIME access, unlike the spinlock it is allowed to +sleep in a critical section protected by a mutex. + +The RTC STATUS register can still be used from the interrupt handler but +it has no effect on setting the time. + +Signed-off-by: Gregory CLEMENT +Acked-by: Alexandre Belloni +Acked-by: Andrew Lunn +Cc: Alessandro Zummo +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman + +diff --git a/drivers/rtc/rtc-armada38x.c b/drivers/rtc/rtc-armada38x.c +index 43e04af39e09..cb70ced7e0db 100644 +--- a/drivers/rtc/rtc-armada38x.c ++++ b/drivers/rtc/rtc-armada38x.c +@@ -40,6 +40,13 @@ struct armada38x_rtc { + void __iomem *regs; + void __iomem *regs_soc; + spinlock_t lock; ++ /* ++ * While setting the time, the RTC TIME register should not be ++ * accessed. Setting the RTC time involves sleeping during ++ * 100ms, so a mutex instead of a spinlock is used to protect ++ * it ++ */ ++ struct mutex mutex_time; + int irq; + }; + +@@ -59,8 +66,7 @@ static int armada38x_rtc_read_time(struct device *dev, struct rtc_time *tm) + struct armada38x_rtc *rtc = dev_get_drvdata(dev); + unsigned long time, time_check, flags; + +- spin_lock_irqsave(&rtc->lock, flags); +- ++ mutex_lock(&rtc->mutex_time); + time = readl(rtc->regs + RTC_TIME); + /* + * WA for failing time set attempts. As stated in HW ERRATA if +@@ -71,7 +77,7 @@ static int armada38x_rtc_read_time(struct device *dev, struct rtc_time *tm) + if ((time_check - time) > 1) + time_check = readl(rtc->regs + RTC_TIME); + +- spin_unlock_irqrestore(&rtc->lock, flags); ++ mutex_unlock(&rtc->mutex_time); + + rtc_time_to_tm(time_check, tm); + +@@ -94,19 +100,12 @@ static int armada38x_rtc_set_time(struct device *dev, struct rtc_time *tm) + * then wait for 100ms before writing to the time register to be + * sure that the data will be taken into account. + */ +- spin_lock_irqsave(&rtc->lock, flags); +- ++ mutex_lock(&rtc->mutex_time); + rtc_delayed_write(0, rtc, RTC_STATUS); +- +- spin_unlock_irqrestore(&rtc->lock, flags); +- + msleep(100); +- +- spin_lock_irqsave(&rtc->lock, flags); +- + rtc_delayed_write(time, rtc, RTC_TIME); ++ mutex_unlock(&rtc->mutex_time); + +- spin_unlock_irqrestore(&rtc->lock, flags); + out: + return ret; + } +@@ -230,6 +229,7 @@ static __init int armada38x_rtc_probe(struct platform_device *pdev) + return -ENOMEM; + + spin_lock_init(&rtc->lock); ++ mutex_init(&rtc->mutex_time); + + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "rtc"); + rtc->regs = devm_ioremap_resource(&pdev->dev, res);