aboutsummaryrefslogtreecommitdiffstats
path: root/fs/dlm/lock.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/dlm/lock.c')
-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);