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

Commit cdf5f61e authored by Linus Torvalds's avatar Linus Torvalds
Browse files
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/sage/ceph-client:
  ceph: preserve seq # on requeued messages after transient transport errors
  ceph: fix cap removal races
  ceph: zero unused message header, footer fields
  ceph: fix locking for waking session requests after reconnect
  ceph: resubmit requests on pg mapping change (not just primary change)
  ceph: fix open file counting on snapped inodes when mds returns no caps
  ceph: unregister osd request on failure
  ceph: don't use writeback_control in writepages completion
  ceph: unregister bdi before kill_anon_super releases device name
parents 769d9968 e84346b7
Loading
Loading
Loading
Loading
+0 −6
Original line number Diff line number Diff line
@@ -504,7 +504,6 @@ static void writepages_finish(struct ceph_osd_request *req,
	int i;
	struct ceph_snap_context *snapc = req->r_snapc;
	struct address_space *mapping = inode->i_mapping;
	struct writeback_control *wbc = req->r_wbc;
	__s32 rc = -EIO;
	u64 bytes = 0;
	struct ceph_client *client = ceph_inode_to_client(inode);
@@ -546,10 +545,6 @@ static void writepages_finish(struct ceph_osd_request *req,
			clear_bdi_congested(&client->backing_dev_info,
					    BLK_RW_ASYNC);

		if (i >= wrote) {
			dout("inode %p skipping page %p\n", inode, page);
			wbc->pages_skipped++;
		}
		ceph_put_snap_context((void *)page->private);
		page->private = 0;
		ClearPagePrivate(page);
@@ -799,7 +794,6 @@ get_more_pages:
				alloc_page_vec(client, req);
				req->r_callback = writepages_finish;
				req->r_inode = inode;
				req->r_wbc = wbc;
			}

			/* note position of first page in pvec */
+12 −7
Original line number Diff line number Diff line
@@ -858,6 +858,8 @@ static int __ceph_is_any_caps(struct ceph_inode_info *ci)
}

/*
 * Remove a cap.  Take steps to deal with a racing iterate_session_caps.
 *
 * caller should hold i_lock.
 * caller will not hold session s_mutex if called from destroy_inode.
 */
@@ -866,15 +868,10 @@ void __ceph_remove_cap(struct ceph_cap *cap)
	struct ceph_mds_session *session = cap->session;
	struct ceph_inode_info *ci = cap->ci;
	struct ceph_mds_client *mdsc = &ceph_client(ci->vfs_inode.i_sb)->mdsc;
	int removed = 0;

	dout("__ceph_remove_cap %p from %p\n", cap, &ci->vfs_inode);

	/* remove from inode list */
	rb_erase(&cap->ci_node, &ci->i_caps);
	cap->ci = NULL;
	if (ci->i_auth_cap == cap)
		ci->i_auth_cap = NULL;

	/* remove from session list */
	spin_lock(&session->s_cap_lock);
	if (session->s_cap_iterator == cap) {
@@ -885,10 +882,18 @@ void __ceph_remove_cap(struct ceph_cap *cap)
		list_del_init(&cap->session_caps);
		session->s_nr_caps--;
		cap->session = NULL;
		removed = 1;
	}
	/* protect backpointer with s_cap_lock: see iterate_session_caps */
	cap->ci = NULL;
	spin_unlock(&session->s_cap_lock);

	if (cap->session == NULL)
	/* remove from inode list */
	rb_erase(&cap->ci_node, &ci->i_caps);
	if (ci->i_auth_cap == cap)
		ci->i_auth_cap = NULL;

	if (removed)
		ceph_put_cap(cap);

	if (!__ceph_is_any_caps(ci) && ci->i_snap_realm) {
+4 −0
Original line number Diff line number Diff line
@@ -733,6 +733,10 @@ no_change:
				__ceph_get_fmode(ci, cap_fmode);
			spin_unlock(&inode->i_lock);
		}
	} else if (cap_fmode >= 0) {
		pr_warning("mds issued no caps on %llx.%llx\n",
			   ceph_vinop(inode));
		__ceph_get_fmode(ci, cap_fmode);
	}

	/* update delegation info? */
+19 −15
Original line number Diff line number Diff line
@@ -736,9 +736,10 @@ static void cleanup_cap_releases(struct ceph_mds_session *session)
}

/*
 * Helper to safely iterate over all caps associated with a session.
 * Helper to safely iterate over all caps associated with a session, with
 * special care taken to handle a racing __ceph_remove_cap().
 *
 * caller must hold session s_mutex
 * Caller must hold session s_mutex.
 */
static int iterate_session_caps(struct ceph_mds_session *session,
				 int (*cb)(struct inode *, struct ceph_cap *,
@@ -2136,7 +2137,7 @@ static void send_mds_reconnect(struct ceph_mds_client *mdsc, int mds)
	struct ceph_mds_session *session = NULL;
	struct ceph_msg *reply;
	struct rb_node *p;
	int err;
	int err = -ENOMEM;
	struct ceph_pagelist *pagelist;

	pr_info("reconnect to recovering mds%d\n", mds);
@@ -2185,7 +2186,7 @@ static void send_mds_reconnect(struct ceph_mds_client *mdsc, int mds)
		goto fail;
	err = iterate_session_caps(session, encode_caps_cb, pagelist);
	if (err < 0)
		goto out;
		goto fail;

	/*
	 * snaprealms.  we provide mds with the ino, seq (version), and
@@ -2213,28 +2214,31 @@ send:
	reply->nr_pages = calc_pages_for(0, pagelist->length);
	ceph_con_send(&session->s_con, reply);

	if (session) {
	session->s_state = CEPH_MDS_SESSION_OPEN;
	mutex_unlock(&session->s_mutex);

	mutex_lock(&mdsc->mutex);
	__wake_requests(mdsc, &session->s_waiting);
	}
	mutex_unlock(&mdsc->mutex);

out:
	up_read(&mdsc->snap_rwsem);
	if (session) {
		mutex_unlock(&session->s_mutex);
	ceph_put_mds_session(session);
	}

	up_read(&mdsc->snap_rwsem);
	mutex_lock(&mdsc->mutex);
	return;

fail:
	ceph_msg_put(reply);
	up_read(&mdsc->snap_rwsem);
	mutex_unlock(&session->s_mutex);
	ceph_put_mds_session(session);
fail_nomsg:
	ceph_pagelist_release(pagelist);
	kfree(pagelist);
fail_nopagelist:
	pr_err("ENOMEM preparing reconnect for mds%d\n", mds);
	goto out;
	pr_err("error %d preparing reconnect for mds%d\n", err, mds);
	mutex_lock(&mdsc->mutex);
	return;
}


+15 −2
Original line number Diff line number Diff line
@@ -492,7 +492,14 @@ static void prepare_write_message(struct ceph_connection *con)
		list_move_tail(&m->list_head, &con->out_sent);
	}

	/*
	 * only assign outgoing seq # if we haven't sent this message
	 * yet.  if it is requeued, resend with it's original seq.
	 */
	if (m->needs_out_seq) {
		m->hdr.seq = cpu_to_le64(++con->out_seq);
		m->needs_out_seq = false;
	}

	dout("prepare_write_message %p seq %lld type %d len %d+%d+%d %d pgs\n",
	     m, con->out_seq, le16_to_cpu(m->hdr.type),
@@ -1986,6 +1993,8 @@ void ceph_con_send(struct ceph_connection *con, struct ceph_msg *msg)

	BUG_ON(msg->front.iov_len != le32_to_cpu(msg->hdr.front_len));

	msg->needs_out_seq = true;

	/* queue */
	mutex_lock(&con->mutex);
	BUG_ON(!list_empty(&msg->list_head));
@@ -2085,15 +2094,19 @@ struct ceph_msg *ceph_msg_new(int type, int front_len,
	kref_init(&m->kref);
	INIT_LIST_HEAD(&m->list_head);

	m->hdr.tid = 0;
	m->hdr.type = cpu_to_le16(type);
	m->hdr.priority = cpu_to_le16(CEPH_MSG_PRIO_DEFAULT);
	m->hdr.version = 0;
	m->hdr.front_len = cpu_to_le32(front_len);
	m->hdr.middle_len = 0;
	m->hdr.data_len = cpu_to_le32(page_len);
	m->hdr.data_off = cpu_to_le16(page_off);
	m->hdr.priority = cpu_to_le16(CEPH_MSG_PRIO_DEFAULT);
	m->hdr.reserved = 0;
	m->footer.front_crc = 0;
	m->footer.middle_crc = 0;
	m->footer.data_crc = 0;
	m->footer.flags = 0;
	m->front_max = front_len;
	m->front_is_vmalloc = false;
	m->more_to_follow = false;
Loading