]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
4.0-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 15 May 2015 01:42:04 +0000 (18:42 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 15 May 2015 01:42:04 +0000 (18:42 -0700)
added patches:
ocfs2-dlm-fix-race-between-purge-and-get-lock-resource.patch
rtc-armada38x-fix-concurrency-access-in-armada38x_rtc_set_time.patch

queue-4.0/ocfs2-dlm-fix-race-between-purge-and-get-lock-resource.patch [new file with mode: 0644]
queue-4.0/rtc-armada38x-fix-concurrency-access-in-armada38x_rtc_set_time.patch [new file with mode: 0644]

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 (file)
index 0000000..f77c083
--- /dev/null
@@ -0,0 +1,62 @@
+From b1432a2a35565f538586774a03bf277c27fc267d Mon Sep 17 00:00:00 2001
+From: Junxiao Bi <junxiao.bi@oracle.com>
+Date: Tue, 5 May 2015 16:24:02 -0700
+Subject: ocfs2: dlm: fix race between purge and get lock resource
+
+From: Junxiao Bi <junxiao.bi@oracle.com>
+
+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 <junxiao.bi@oracle.com>
+Cc: Joseph Qi <joseph.qi@huawei.com>
+Cc: Mark Fasheh <mfasheh@suse.com>
+Cc: Joel Becker <jlbec@evilplan.org>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ 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 (file)
index 0000000..c66badc
--- /dev/null
@@ -0,0 +1,95 @@
+From 489405fe5ed38e65f6f82f131a39c67f3bae6045 Mon Sep 17 00:00:00 2001
+From: Gregory CLEMENT <gregory.clement@free-electrons.com>
+Date: Tue, 5 May 2015 16:24:05 -0700
+Subject: rtc: armada38x: fix concurrency access in armada38x_rtc_set_time
+
+From: Gregory CLEMENT <gregory.clement@free-electrons.com>
+
+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 <gregory.clement@free-electrons.com>
+Acked-by: Alexandre Belloni <alexandre.belloni@free-electrons.com>
+Acked-by: Andrew Lunn <andrew@lunn.ch>
+Cc: Alessandro Zummo <a.zummo@towertech.it>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+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);