aboutsummaryrefslogtreecommitdiffstats
path: root/fs/dlm
diff options
context:
space:
mode:
authorDavid Teigland <teigland@redhat.com>2007-08-07 10:44:48 -0400
committerSteven Whitehouse <swhiteho@redhat.com>2007-08-14 05:31:02 -0400
commit3650925893469ccb03dbcc6a440c5d363350f591 (patch)
tree8f0b9d6ce880547723cb6590c27799821b9c2f96 /fs/dlm
parent9e5f2825a8b721360b291f14f42cd7a25781156b (diff)
[DLM] fix basts for granted PR waiting CW
Fix a long standing bug where a blocking callback would be missed when there's a granted lock in PR mode and waiting locks in both PR and CW modes (and the PR lock was added to the waiting queue before the CW lock). The logic simply compared the numerical values of the modes to determine if a blocking callback was required, but in the one case of PR and CW, the lower valued CW mode blocks the higher valued PR mode. We just need to add a special check for this PR/CW case in the tests that decide when a blocking callback is needed. Signed-off-by: David Teigland <teigland@redhat.com> Signed-off-by: Steven Whitehouse <swhiteho@redhat.com>
Diffstat (limited to 'fs/dlm')
-rw-r--r--fs/dlm/lock.c69
1 files changed, 55 insertions, 14 deletions
diff --git a/fs/dlm/lock.c b/fs/dlm/lock.c
index b455919c1998..2082daf083d8 100644
--- a/fs/dlm/lock.c
+++ b/fs/dlm/lock.c
@@ -1670,9 +1670,10 @@ static int can_be_granted(struct dlm_rsb *r, struct dlm_lkb *lkb, int now,
1670 with a deadlk here, we'd have to generate something like grant_lock with 1670 with a deadlk here, we'd have to generate something like grant_lock with
1671 the deadlk error.) */ 1671 the deadlk error.) */
1672 1672
1673/* returns the highest requested mode of all blocked conversions */ 1673/* Returns the highest requested mode of all blocked conversions; sets
1674 cw if there's a blocked conversion to DLM_LOCK_CW. */
1674 1675
1675static int grant_pending_convert(struct dlm_rsb *r, int high) 1676static int grant_pending_convert(struct dlm_rsb *r, int high, int *cw)
1676{ 1677{
1677 struct dlm_lkb *lkb, *s; 1678 struct dlm_lkb *lkb, *s;
1678 int hi, demoted, quit, grant_restart, demote_restart; 1679 int hi, demoted, quit, grant_restart, demote_restart;
@@ -1709,6 +1710,9 @@ static int grant_pending_convert(struct dlm_rsb *r, int high)
1709 } 1710 }
1710 1711
1711 hi = max_t(int, lkb->lkb_rqmode, hi); 1712 hi = max_t(int, lkb->lkb_rqmode, hi);
1713
1714 if (cw && lkb->lkb_rqmode == DLM_LOCK_CW)
1715 *cw = 1;
1712 } 1716 }
1713 1717
1714 if (grant_restart) 1718 if (grant_restart)
@@ -1721,29 +1725,52 @@ static int grant_pending_convert(struct dlm_rsb *r, int high)
1721 return max_t(int, high, hi); 1725 return max_t(int, high, hi);
1722} 1726}
1723 1727
1724static int grant_pending_wait(struct dlm_rsb *r, int high) 1728static int grant_pending_wait(struct dlm_rsb *r, int high, int *cw)
1725{ 1729{
1726 struct dlm_lkb *lkb, *s; 1730 struct dlm_lkb *lkb, *s;
1727 1731
1728 list_for_each_entry_safe(lkb, s, &r->res_waitqueue, lkb_statequeue) { 1732 list_for_each_entry_safe(lkb, s, &r->res_waitqueue, lkb_statequeue) {
1729 if (can_be_granted(r, lkb, 0, NULL)) 1733 if (can_be_granted(r, lkb, 0, NULL))
1730 grant_lock_pending(r, lkb); 1734 grant_lock_pending(r, lkb);
1731 else 1735 else {
1732 high = max_t(int, lkb->lkb_rqmode, high); 1736 high = max_t(int, lkb->lkb_rqmode, high);
1737 if (lkb->lkb_rqmode == DLM_LOCK_CW)
1738 *cw = 1;
1739 }
1733 } 1740 }
1734 1741
1735 return high; 1742 return high;
1736} 1743}
1737 1744
1745/* cw of 1 means there's a lock with a rqmode of DLM_LOCK_CW that's blocked
1746 on either the convert or waiting queue.
1747 high is the largest rqmode of all locks blocked on the convert or
1748 waiting queue. */
1749
1750static int lock_requires_bast(struct dlm_lkb *gr, int high, int cw)
1751{
1752 if (gr->lkb_grmode == DLM_LOCK_PR && cw) {
1753 if (gr->lkb_highbast < DLM_LOCK_EX)
1754 return 1;
1755 return 0;
1756 }
1757
1758 if (gr->lkb_highbast < high &&
1759 !__dlm_compat_matrix[gr->lkb_grmode+1][high+1])
1760 return 1;
1761 return 0;
1762}
1763
1738static void grant_pending_locks(struct dlm_rsb *r) 1764static void grant_pending_locks(struct dlm_rsb *r)
1739{ 1765{
1740 struct dlm_lkb *lkb, *s; 1766 struct dlm_lkb *lkb, *s;
1741 int high = DLM_LOCK_IV; 1767 int high = DLM_LOCK_IV;
1768 int cw = 0;
1742 1769
1743 DLM_ASSERT(is_master(r), dlm_dump_rsb(r);); 1770 DLM_ASSERT(is_master(r), dlm_dump_rsb(r););
1744 1771
1745 high = grant_pending_convert(r, high); 1772 high = grant_pending_convert(r, high, &cw);
1746 high = grant_pending_wait(r, high); 1773 high = grant_pending_wait(r, high, &cw);
1747 1774
1748 if (high == DLM_LOCK_IV) 1775 if (high == DLM_LOCK_IV)
1749 return; 1776 return;
@@ -1751,27 +1778,41 @@ static void grant_pending_locks(struct dlm_rsb *r)
1751 /* 1778 /*
1752 * If there are locks left on the wait/convert queue then send blocking 1779 * If there are locks left on the wait/convert queue then send blocking
1753 * ASTs to granted locks based on the largest requested mode (high) 1780 * ASTs to granted locks based on the largest requested mode (high)
1754 * found above. FIXME: highbast < high comparison not valid for PR/CW. 1781 * found above.
1755 */ 1782 */
1756 1783
1757 list_for_each_entry_safe(lkb, s, &r->res_grantqueue, lkb_statequeue) { 1784 list_for_each_entry_safe(lkb, s, &r->res_grantqueue, lkb_statequeue) {
1758 if (lkb->lkb_bastaddr && (lkb->lkb_highbast < high) && 1785 if (lkb->lkb_bastaddr && lock_requires_bast(lkb, high, cw)) {
1759 !__dlm_compat_matrix[lkb->lkb_grmode+1][high+1]) { 1786 if (cw && high == DLM_LOCK_PR)
1760 queue_bast(r, lkb, high); 1787 queue_bast(r, lkb, DLM_LOCK_CW);
1788 else
1789 queue_bast(r, lkb, high);
1761 lkb->lkb_highbast = high; 1790 lkb->lkb_highbast = high;
1762 } 1791 }
1763 } 1792 }
1764} 1793}
1765 1794
1795static int modes_require_bast(struct dlm_lkb *gr, struct dlm_lkb *rq)
1796{
1797 if ((gr->lkb_grmode == DLM_LOCK_PR && rq->lkb_rqmode == DLM_LOCK_CW) ||
1798 (gr->lkb_grmode == DLM_LOCK_CW && rq->lkb_rqmode == DLM_LOCK_PR)) {
1799 if (gr->lkb_highbast < DLM_LOCK_EX)
1800 return 1;
1801 return 0;
1802 }
1803
1804 if (gr->lkb_highbast < rq->lkb_rqmode && !modes_compat(gr, rq))
1805 return 1;
1806 return 0;
1807}
1808
1766static void send_bast_queue(struct dlm_rsb *r, struct list_head *head, 1809static void send_bast_queue(struct dlm_rsb *r, struct list_head *head,
1767 struct dlm_lkb *lkb) 1810 struct dlm_lkb *lkb)
1768{ 1811{
1769 struct dlm_lkb *gr; 1812 struct dlm_lkb *gr;
1770 1813
1771 list_for_each_entry(gr, head, lkb_statequeue) { 1814 list_for_each_entry(gr, head, lkb_statequeue) {
1772 if (gr->lkb_bastaddr && 1815 if (gr->lkb_bastaddr && modes_require_bast(gr, lkb)) {
1773 gr->lkb_highbast < lkb->lkb_rqmode &&
1774 !modes_compat(gr, lkb)) {
1775 queue_bast(r, gr, lkb->lkb_rqmode); 1816 queue_bast(r, gr, lkb->lkb_rqmode);
1776 gr->lkb_highbast = lkb->lkb_rqmode; 1817 gr->lkb_highbast = lkb->lkb_rqmode;
1777 } 1818 }
@@ -2235,7 +2276,7 @@ static int do_convert(struct dlm_rsb *r, struct dlm_lkb *lkb)
2235 before we try again to grant this one. */ 2276 before we try again to grant this one. */
2236 2277
2237 if (is_demoted(lkb)) { 2278 if (is_demoted(lkb)) {
2238 grant_pending_convert(r, DLM_LOCK_IV); 2279 grant_pending_convert(r, DLM_LOCK_IV, NULL);
2239 if (_can_be_granted(r, lkb, 1)) { 2280 if (_can_be_granted(r, lkb, 1)) {
2240 grant_lock(r, lkb); 2281 grant_lock(r, lkb);
2241 queue_cast(r, lkb, 0); 2282 queue_cast(r, lkb, 0);