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

Commit d3383a8e authored by Yan, Zheng's avatar Yan, Zheng Committed by Ilya Dryomov
Browse files

ceph: avoid block operation when !TASK_RUNNING (ceph_mdsc_sync)



check_cap_flush() calls mutex_lock(), which may block. So we can't
use it as condition check function for wait_event();

Signed-off-by: default avatarYan, Zheng <zyan@redhat.com>
parent 73e39e4d
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -1450,8 +1450,8 @@ static int __mark_caps_flushing(struct inode *inode,
	spin_lock(&mdsc->cap_dirty_lock);
	list_del_init(&ci->i_dirty_item);

	ci->i_cap_flush_seq = ++mdsc->cap_flush_seq;
	if (list_empty(&ci->i_flushing_item)) {
		ci->i_cap_flush_seq = ++mdsc->cap_flush_seq;
		list_add_tail(&ci->i_flushing_item, &session->s_cap_flushing);
		mdsc->num_cap_flushing++;
		dout(" inode %p now flushing seq %lld\n", inode,
+34 −17
Original line number Diff line number Diff line
@@ -1464,19 +1464,33 @@ int ceph_add_cap_releases(struct ceph_mds_client *mdsc,
	return err;
}

static int check_cap_flush(struct inode *inode, u64 want_flush_seq)
{
	struct ceph_inode_info *ci = ceph_inode(inode);
	int ret;
	spin_lock(&ci->i_ceph_lock);
	if (ci->i_flushing_caps)
		ret = ci->i_cap_flush_seq >= want_flush_seq;
	else
		ret = 1;
	spin_unlock(&ci->i_ceph_lock);
	return ret;
}

/*
 * flush all dirty inode data to disk.
 *
 * returns true if we've flushed through want_flush_seq
 */
static int check_cap_flush(struct ceph_mds_client *mdsc, u64 want_flush_seq)
static void wait_caps_flush(struct ceph_mds_client *mdsc, u64 want_flush_seq)
{
	int mds, ret = 1;
	int mds;

	dout("check_cap_flush want %lld\n", want_flush_seq);
	mutex_lock(&mdsc->mutex);
	for (mds = 0; ret && mds < mdsc->max_sessions; mds++) {
	for (mds = 0; mds < mdsc->max_sessions; mds++) {
		struct ceph_mds_session *session = mdsc->sessions[mds];
		struct inode *inode = NULL;

		if (!session)
			continue;
@@ -1489,29 +1503,29 @@ static int check_cap_flush(struct ceph_mds_client *mdsc, u64 want_flush_seq)
				list_entry(session->s_cap_flushing.next,
					   struct ceph_inode_info,
					   i_flushing_item);
			struct inode *inode = &ci->vfs_inode;

			spin_lock(&ci->i_ceph_lock);
			if (ci->i_cap_flush_seq <= want_flush_seq) {
			if (!check_cap_flush(&ci->vfs_inode, want_flush_seq)) {
				dout("check_cap_flush still flushing %p "
				     "seq %lld <= %lld to mds%d\n", inode,
				     ci->i_cap_flush_seq, want_flush_seq,
				     session->s_mds);
				ret = 0;
				     "seq %lld <= %lld to mds%d\n",
				     &ci->vfs_inode, ci->i_cap_flush_seq,
				     want_flush_seq, session->s_mds);
				inode = igrab(&ci->vfs_inode);
			}
			spin_unlock(&ci->i_ceph_lock);
		}
		mutex_unlock(&session->s_mutex);
		ceph_put_mds_session(session);

		if (!ret)
			return ret;
		if (inode) {
			wait_event(mdsc->cap_flushing_wq,
				   check_cap_flush(inode, want_flush_seq));
			iput(inode);
		}

		mutex_lock(&mdsc->mutex);
	}

	mutex_unlock(&mdsc->mutex);
	dout("check_cap_flush ok, flushed thru %lld\n", want_flush_seq);
	return ret;
}

/*
@@ -3447,14 +3461,17 @@ void ceph_mdsc_sync(struct ceph_mds_client *mdsc)
	dout("sync\n");
	mutex_lock(&mdsc->mutex);
	want_tid = mdsc->last_tid;
	want_flush = mdsc->cap_flush_seq;
	mutex_unlock(&mdsc->mutex);
	dout("sync want tid %lld flush_seq %lld\n", want_tid, want_flush);

	ceph_flush_dirty_caps(mdsc);
	spin_lock(&mdsc->cap_dirty_lock);
	want_flush = mdsc->cap_flush_seq;
	spin_unlock(&mdsc->cap_dirty_lock);

	dout("sync want tid %lld flush_seq %lld\n", want_tid, want_flush);

	wait_unsafe_requests(mdsc, want_tid);
	wait_event(mdsc->cap_flushing_wq, check_cap_flush(mdsc, want_flush));
	wait_caps_flush(mdsc, want_flush);
}

/*