Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 28e8351a authored by Linus Torvalds's avatar Linus Torvalds
Browse files
* git://git.kernel.org/pub/scm/linux/kernel/git/steve/gfs2-2.6-fixes:
  [GFS2] Revert remounting w/o acl option leaves acls enabled
  [GFS2] Fix setting of inherit jdata attr
  [GFS2] Fix incorrect error path in prepare_write()
  [GFS2] Fix incorrect return code in rgrp.c
  [GFS2] soft lockup in rgblk_search
  [GFS2] soft lockup detected in databuf_lo_before_commit
  [DLM] fix basts for granted PR waiting CW
  [DLM] More othercon fixes
  [DLM] Fix memory leak in dlm_add_member() when dlm_node_weight() returns less than zero
  [DLM] zero unused parts of sockaddr_storage
  [DLM] fix NULL ls usage
  [DLM] Clear othercon pointers when a connection is closed
parents 3b993e8b d18c4d68
Loading
Loading
Loading
Loading
+55 −14
Original line number Diff line number Diff line
@@ -1670,9 +1670,10 @@ static int can_be_granted(struct dlm_rsb *r, struct dlm_lkb *lkb, int now,
   with a deadlk here, we'd have to generate something like grant_lock with
   the deadlk error.) */

/* returns the highest requested mode of all blocked conversions */
/* Returns the highest requested mode of all blocked conversions; sets
   cw if there's a blocked conversion to DLM_LOCK_CW. */

static int grant_pending_convert(struct dlm_rsb *r, int high)
static int grant_pending_convert(struct dlm_rsb *r, int high, int *cw)
{
	struct dlm_lkb *lkb, *s;
	int hi, demoted, quit, grant_restart, demote_restart;
@@ -1709,6 +1710,9 @@ static int grant_pending_convert(struct dlm_rsb *r, int high)
		}

		hi = max_t(int, lkb->lkb_rqmode, hi);

		if (cw && lkb->lkb_rqmode == DLM_LOCK_CW)
			*cw = 1;
	}

	if (grant_restart)
@@ -1721,29 +1725,52 @@ static int grant_pending_convert(struct dlm_rsb *r, int high)
	return max_t(int, high, hi);
}

static int grant_pending_wait(struct dlm_rsb *r, int high)
static int grant_pending_wait(struct dlm_rsb *r, int high, int *cw)
{
	struct dlm_lkb *lkb, *s;

	list_for_each_entry_safe(lkb, s, &r->res_waitqueue, lkb_statequeue) {
		if (can_be_granted(r, lkb, 0, NULL))
			grant_lock_pending(r, lkb);
                else
                else {
			high = max_t(int, lkb->lkb_rqmode, high);
			if (lkb->lkb_rqmode == DLM_LOCK_CW)
				*cw = 1;
		}
	}

	return high;
}

/* cw of 1 means there's a lock with a rqmode of DLM_LOCK_CW that's blocked
   on either the convert or waiting queue.
   high is the largest rqmode of all locks blocked on the convert or
   waiting queue. */

static int lock_requires_bast(struct dlm_lkb *gr, int high, int cw)
{
	if (gr->lkb_grmode == DLM_LOCK_PR && cw) {
		if (gr->lkb_highbast < DLM_LOCK_EX)
			return 1;
		return 0;
	}

	if (gr->lkb_highbast < high &&
	    !__dlm_compat_matrix[gr->lkb_grmode+1][high+1])
		return 1;
	return 0;
}

static void grant_pending_locks(struct dlm_rsb *r)
{
	struct dlm_lkb *lkb, *s;
	int high = DLM_LOCK_IV;
	int cw = 0;

	DLM_ASSERT(is_master(r), dlm_dump_rsb(r););

	high = grant_pending_convert(r, high);
	high = grant_pending_wait(r, high);
	high = grant_pending_convert(r, high, &cw);
	high = grant_pending_wait(r, high, &cw);

	if (high == DLM_LOCK_IV)
		return;
@@ -1751,27 +1778,41 @@ static void grant_pending_locks(struct dlm_rsb *r)
	/*
	 * If there are locks left on the wait/convert queue then send blocking
	 * ASTs to granted locks based on the largest requested mode (high)
	 * found above. FIXME: highbast < high comparison not valid for PR/CW.
	 * found above.
	 */

	list_for_each_entry_safe(lkb, s, &r->res_grantqueue, lkb_statequeue) {
		if (lkb->lkb_bastaddr && (lkb->lkb_highbast < high) &&
		    !__dlm_compat_matrix[lkb->lkb_grmode+1][high+1]) {
		if (lkb->lkb_bastaddr && lock_requires_bast(lkb, high, cw)) {
			if (cw && high == DLM_LOCK_PR)
				queue_bast(r, lkb, DLM_LOCK_CW);
			else
				queue_bast(r, lkb, high);
			lkb->lkb_highbast = high;
		}
	}
}

static int modes_require_bast(struct dlm_lkb *gr, struct dlm_lkb *rq)
{
	if ((gr->lkb_grmode == DLM_LOCK_PR && rq->lkb_rqmode == DLM_LOCK_CW) ||
	    (gr->lkb_grmode == DLM_LOCK_CW && rq->lkb_rqmode == DLM_LOCK_PR)) {
		if (gr->lkb_highbast < DLM_LOCK_EX)
			return 1;
		return 0;
	}

	if (gr->lkb_highbast < rq->lkb_rqmode && !modes_compat(gr, rq))
		return 1;
	return 0;
}

static void send_bast_queue(struct dlm_rsb *r, struct list_head *head,
			    struct dlm_lkb *lkb)
{
	struct dlm_lkb *gr;

	list_for_each_entry(gr, head, lkb_statequeue) {
		if (gr->lkb_bastaddr &&
		    gr->lkb_highbast < lkb->lkb_rqmode &&
		    !modes_compat(gr, lkb)) {
		if (gr->lkb_bastaddr && modes_require_bast(gr, lkb)) {
			queue_bast(r, gr, lkb->lkb_rqmode);
			gr->lkb_highbast = lkb->lkb_rqmode;
		}
@@ -2235,7 +2276,7 @@ static int do_convert(struct dlm_rsb *r, struct dlm_lkb *lkb)
	   before we try again to grant this one. */

	if (is_demoted(lkb)) {
		grant_pending_convert(r, DLM_LOCK_IV);
		grant_pending_convert(r, DLM_LOCK_IV, NULL);
		if (_can_be_granted(r, lkb, 1)) {
			grant_lock(r, lkb);
			queue_cast(r, lkb, 0);
+16 −8
Original line number Diff line number Diff line
@@ -313,6 +313,7 @@ static void make_sockaddr(struct sockaddr_storage *saddr, uint16_t port,
		in6_addr->sin6_port = cpu_to_be16(port);
		*addr_len = sizeof(struct sockaddr_in6);
	}
	memset((char *)saddr + *addr_len, 0, sizeof(struct sockaddr_storage) - *addr_len);
}

/* Close a remote connection and tidy up */
@@ -332,9 +333,20 @@ static void close_connection(struct connection *con, bool and_other)
		__free_page(con->rx_page);
		con->rx_page = NULL;
	}

	/* If we are an 'othercon' then NULL the pointer to us
	   from the parent and tidy ourself up */
	if (test_bit(CF_IS_OTHERCON, &con->flags)) {
		struct connection *parent = __nodeid2con(con->nodeid, 0);
		parent->othercon = NULL;
		kmem_cache_free(con_cache, con);
	}
	else {
		/* Parent connections get reused */
		con->retries = 0;
		mutex_unlock(&con->sock_mutex);
	}
}

/* We only send shutdown messages to nodes that are not part of the cluster */
static void sctp_send_shutdown(sctp_assoc_t associd)
@@ -631,7 +643,7 @@ out_resched:

out_close:
	mutex_unlock(&con->sock_mutex);
	if (ret != -EAGAIN && !test_bit(CF_IS_OTHERCON, &con->flags)) {
	if (ret != -EAGAIN) {
		close_connection(con, false);
		/* Reconnect when there is something to send */
	}
@@ -1122,8 +1134,6 @@ static int tcp_listen_for_all(void)

	log_print("Using TCP for communications");

	set_bit(CF_IS_OTHERCON, &con->flags);

	sock = tcp_create_listen_sock(con, dlm_local_addr[0]);
	if (sock) {
		add_sock(sock, con);
@@ -1407,7 +1417,7 @@ void dlm_lowcomms_stop(void)
	for (i = 0; i <= max_nodeid; i++) {
		con = __nodeid2con(i, 0);
		if (con) {
			con->flags |= 0xFF;
			con->flags |= 0x0F;
			if (con->sock)
				con->sock->sk->sk_user_data = NULL;
		}
@@ -1423,8 +1433,6 @@ void dlm_lowcomms_stop(void)
		con = __nodeid2con(i, 0);
		if (con) {
			close_connection(con, true);
			if (con->othercon)
				kmem_cache_free(con_cache, con->othercon);
			kmem_cache_free(con_cache, con);
		}
	}
+3 −1
Original line number Diff line number Diff line
@@ -56,8 +56,10 @@ static int dlm_add_member(struct dlm_ls *ls, int nodeid)
		return -ENOMEM;

	w = dlm_node_weight(ls->ls_name, nodeid);
	if (w < 0)
	if (w < 0) {
		kfree(memb);
		return w;
	}

	memb->nodeid = nodeid;
	memb->weight = w;
+3 −4
Original line number Diff line number Diff line
@@ -386,8 +386,7 @@ static void receive_rcom_lock_reply(struct dlm_ls *ls, struct dlm_rcom *rc_in)
	dlm_recover_process_copy(ls, rc_in);
}

static int send_ls_not_ready(struct dlm_ls *ls, int nodeid,
			     struct dlm_rcom *rc_in)
static int send_ls_not_ready(int nodeid, struct dlm_rcom *rc_in)
{
	struct dlm_rcom *rc;
	struct rcom_config *rf;
@@ -395,7 +394,7 @@ static int send_ls_not_ready(struct dlm_ls *ls, int nodeid,
	char *mb;
	int mb_len = sizeof(struct dlm_rcom) + sizeof(struct rcom_config);

	mh = dlm_lowcomms_get_buffer(nodeid, mb_len, ls->ls_allocation, &mb);
	mh = dlm_lowcomms_get_buffer(nodeid, mb_len, GFP_NOFS, &mb);
	if (!mh)
		return -ENOBUFS;
	memset(mb, 0, mb_len);
@@ -465,7 +464,7 @@ void dlm_receive_rcom(struct dlm_header *hd, int nodeid)
		log_print("lockspace %x from %d type %x not found",
			  hd->h_lockspace, nodeid, rc->rc_type);
		if (rc->rc_type == DLM_RCOM_STATUS)
			send_ls_not_ready(ls, nodeid, rc);
			send_ls_not_ready(nodeid, rc);
		return;
	}

+4 −2
Original line number Diff line number Diff line
@@ -486,8 +486,8 @@ static void databuf_lo_add(struct gfs2_sbd *sdp, struct gfs2_log_element *le)
		gfs2_pin(sdp, bd->bd_bh);
		tr->tr_num_databuf_new++;
	}
	sdp->sd_log_num_databuf++;
	gfs2_log_lock(sdp);
	sdp->sd_log_num_databuf++;
	list_add(&le->le_list, &sdp->sd_log_le_databuf);
	gfs2_log_unlock(sdp);
}
@@ -523,7 +523,7 @@ static void databuf_lo_before_commit(struct gfs2_sbd *sdp)
	struct buffer_head *bh = NULL,*bh1 = NULL;
	struct gfs2_log_descriptor *ld;
	unsigned int limit;
	unsigned int total_dbuf = sdp->sd_log_num_databuf;
	unsigned int total_dbuf;
	unsigned int total_jdata = sdp->sd_log_num_jdata;
	unsigned int num, n;
	__be64 *ptr = NULL;
@@ -535,6 +535,7 @@ static void databuf_lo_before_commit(struct gfs2_sbd *sdp)
	 * into the log along with a header
	 */
	gfs2_log_lock(sdp);
	total_dbuf = sdp->sd_log_num_databuf;
	bd2 = bd1 = list_prepare_entry(bd1, &sdp->sd_log_le_databuf,
				       bd_le.le_list);
	while(total_dbuf) {
@@ -653,6 +654,7 @@ static void databuf_lo_before_commit(struct gfs2_sbd *sdp)
				break;
		}
		bh = NULL;
		BUG_ON(total_dbuf < num);
		total_dbuf -= num;
		total_jdata -= num;
	}
Loading