diff options
Diffstat (limited to 'fs/dlm')
-rw-r--r-- | fs/dlm/lock.c | 69 | ||||
-rw-r--r-- | fs/dlm/lowcomms.c | 24 | ||||
-rw-r--r-- | fs/dlm/member.c | 4 | ||||
-rw-r--r-- | fs/dlm/rcom.c | 7 |
4 files changed, 77 insertions, 27 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 | ||
1675 | static int grant_pending_convert(struct dlm_rsb *r, int high) | 1676 | static 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 | ||
1724 | static int grant_pending_wait(struct dlm_rsb *r, int high) | 1728 | static 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 | |||
1750 | static 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 | |||
1738 | static void grant_pending_locks(struct dlm_rsb *r) | 1764 | static 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 | ||
1795 | static 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 | |||
1766 | static void send_bast_queue(struct dlm_rsb *r, struct list_head *head, | 1809 | static 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); |
diff --git a/fs/dlm/lowcomms.c b/fs/dlm/lowcomms.c index dd362739d291..9e9d2e82f40f 100644 --- a/fs/dlm/lowcomms.c +++ b/fs/dlm/lowcomms.c | |||
@@ -313,6 +313,7 @@ static void make_sockaddr(struct sockaddr_storage *saddr, uint16_t port, | |||
313 | in6_addr->sin6_port = cpu_to_be16(port); | 313 | in6_addr->sin6_port = cpu_to_be16(port); |
314 | *addr_len = sizeof(struct sockaddr_in6); | 314 | *addr_len = sizeof(struct sockaddr_in6); |
315 | } | 315 | } |
316 | memset((char *)saddr + *addr_len, 0, sizeof(struct sockaddr_storage) - *addr_len); | ||
316 | } | 317 | } |
317 | 318 | ||
318 | /* Close a remote connection and tidy up */ | 319 | /* Close a remote connection and tidy up */ |
@@ -332,8 +333,19 @@ static void close_connection(struct connection *con, bool and_other) | |||
332 | __free_page(con->rx_page); | 333 | __free_page(con->rx_page); |
333 | con->rx_page = NULL; | 334 | con->rx_page = NULL; |
334 | } | 335 | } |
335 | con->retries = 0; | 336 | |
336 | mutex_unlock(&con->sock_mutex); | 337 | /* If we are an 'othercon' then NULL the pointer to us |
338 | from the parent and tidy ourself up */ | ||
339 | if (test_bit(CF_IS_OTHERCON, &con->flags)) { | ||
340 | struct connection *parent = __nodeid2con(con->nodeid, 0); | ||
341 | parent->othercon = NULL; | ||
342 | kmem_cache_free(con_cache, con); | ||
343 | } | ||
344 | else { | ||
345 | /* Parent connections get reused */ | ||
346 | con->retries = 0; | ||
347 | mutex_unlock(&con->sock_mutex); | ||
348 | } | ||
337 | } | 349 | } |
338 | 350 | ||
339 | /* We only send shutdown messages to nodes that are not part of the cluster */ | 351 | /* We only send shutdown messages to nodes that are not part of the cluster */ |
@@ -631,7 +643,7 @@ out_resched: | |||
631 | 643 | ||
632 | out_close: | 644 | out_close: |
633 | mutex_unlock(&con->sock_mutex); | 645 | mutex_unlock(&con->sock_mutex); |
634 | if (ret != -EAGAIN && !test_bit(CF_IS_OTHERCON, &con->flags)) { | 646 | if (ret != -EAGAIN) { |
635 | close_connection(con, false); | 647 | close_connection(con, false); |
636 | /* Reconnect when there is something to send */ | 648 | /* Reconnect when there is something to send */ |
637 | } | 649 | } |
@@ -1122,8 +1134,6 @@ static int tcp_listen_for_all(void) | |||
1122 | 1134 | ||
1123 | log_print("Using TCP for communications"); | 1135 | log_print("Using TCP for communications"); |
1124 | 1136 | ||
1125 | set_bit(CF_IS_OTHERCON, &con->flags); | ||
1126 | |||
1127 | sock = tcp_create_listen_sock(con, dlm_local_addr[0]); | 1137 | sock = tcp_create_listen_sock(con, dlm_local_addr[0]); |
1128 | if (sock) { | 1138 | if (sock) { |
1129 | add_sock(sock, con); | 1139 | add_sock(sock, con); |
@@ -1407,7 +1417,7 @@ void dlm_lowcomms_stop(void) | |||
1407 | for (i = 0; i <= max_nodeid; i++) { | 1417 | for (i = 0; i <= max_nodeid; i++) { |
1408 | con = __nodeid2con(i, 0); | 1418 | con = __nodeid2con(i, 0); |
1409 | if (con) { | 1419 | if (con) { |
1410 | con->flags |= 0xFF; | 1420 | con->flags |= 0x0F; |
1411 | if (con->sock) | 1421 | if (con->sock) |
1412 | con->sock->sk->sk_user_data = NULL; | 1422 | con->sock->sk->sk_user_data = NULL; |
1413 | } | 1423 | } |
@@ -1423,8 +1433,6 @@ void dlm_lowcomms_stop(void) | |||
1423 | con = __nodeid2con(i, 0); | 1433 | con = __nodeid2con(i, 0); |
1424 | if (con) { | 1434 | if (con) { |
1425 | close_connection(con, true); | 1435 | close_connection(con, true); |
1426 | if (con->othercon) | ||
1427 | kmem_cache_free(con_cache, con->othercon); | ||
1428 | kmem_cache_free(con_cache, con); | 1436 | kmem_cache_free(con_cache, con); |
1429 | } | 1437 | } |
1430 | } | 1438 | } |
diff --git a/fs/dlm/member.c b/fs/dlm/member.c index 073599dced2a..d09977528f69 100644 --- a/fs/dlm/member.c +++ b/fs/dlm/member.c | |||
@@ -56,8 +56,10 @@ static int dlm_add_member(struct dlm_ls *ls, int nodeid) | |||
56 | return -ENOMEM; | 56 | return -ENOMEM; |
57 | 57 | ||
58 | w = dlm_node_weight(ls->ls_name, nodeid); | 58 | w = dlm_node_weight(ls->ls_name, nodeid); |
59 | if (w < 0) | 59 | if (w < 0) { |
60 | kfree(memb); | ||
60 | return w; | 61 | return w; |
62 | } | ||
61 | 63 | ||
62 | memb->nodeid = nodeid; | 64 | memb->nodeid = nodeid; |
63 | memb->weight = w; | 65 | memb->weight = w; |
diff --git a/fs/dlm/rcom.c b/fs/dlm/rcom.c index e3a1527cbdbe..188b91c027e4 100644 --- a/fs/dlm/rcom.c +++ b/fs/dlm/rcom.c | |||
@@ -386,8 +386,7 @@ static void receive_rcom_lock_reply(struct dlm_ls *ls, struct dlm_rcom *rc_in) | |||
386 | dlm_recover_process_copy(ls, rc_in); | 386 | dlm_recover_process_copy(ls, rc_in); |
387 | } | 387 | } |
388 | 388 | ||
389 | static int send_ls_not_ready(struct dlm_ls *ls, int nodeid, | 389 | static int send_ls_not_ready(int nodeid, struct dlm_rcom *rc_in) |
390 | struct dlm_rcom *rc_in) | ||
391 | { | 390 | { |
392 | struct dlm_rcom *rc; | 391 | struct dlm_rcom *rc; |
393 | struct rcom_config *rf; | 392 | struct rcom_config *rf; |
@@ -395,7 +394,7 @@ static int send_ls_not_ready(struct dlm_ls *ls, int nodeid, | |||
395 | char *mb; | 394 | char *mb; |
396 | int mb_len = sizeof(struct dlm_rcom) + sizeof(struct rcom_config); | 395 | int mb_len = sizeof(struct dlm_rcom) + sizeof(struct rcom_config); |
397 | 396 | ||
398 | mh = dlm_lowcomms_get_buffer(nodeid, mb_len, ls->ls_allocation, &mb); | 397 | mh = dlm_lowcomms_get_buffer(nodeid, mb_len, GFP_NOFS, &mb); |
399 | if (!mh) | 398 | if (!mh) |
400 | return -ENOBUFS; | 399 | return -ENOBUFS; |
401 | memset(mb, 0, mb_len); | 400 | memset(mb, 0, mb_len); |
@@ -465,7 +464,7 @@ void dlm_receive_rcom(struct dlm_header *hd, int nodeid) | |||
465 | log_print("lockspace %x from %d type %x not found", | 464 | log_print("lockspace %x from %d type %x not found", |
466 | hd->h_lockspace, nodeid, rc->rc_type); | 465 | hd->h_lockspace, nodeid, rc->rc_type); |
467 | if (rc->rc_type == DLM_RCOM_STATUS) | 466 | if (rc->rc_type == DLM_RCOM_STATUS) |
468 | send_ls_not_ready(ls, nodeid, rc); | 467 | send_ls_not_ready(nodeid, rc); |
469 | return; | 468 | return; |
470 | } | 469 | } |
471 | 470 | ||