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: Yan, Zheng <zyan@redhat.com>
This commit is contained in:
Yan, Zheng 2015-01-08 21:30:12 +08:00 коммит произвёл Ilya Dryomov
Родитель 73e39e4dba
Коммит d3383a8e37
2 изменённых файлов: 35 добавлений и 18 удалений

Просмотреть файл

@ -1450,8 +1450,8 @@ static int __mark_caps_flushing(struct inode *inode,
spin_lock(&mdsc->cap_dirty_lock); spin_lock(&mdsc->cap_dirty_lock);
list_del_init(&ci->i_dirty_item); list_del_init(&ci->i_dirty_item);
ci->i_cap_flush_seq = ++mdsc->cap_flush_seq;
if (list_empty(&ci->i_flushing_item)) { 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); list_add_tail(&ci->i_flushing_item, &session->s_cap_flushing);
mdsc->num_cap_flushing++; mdsc->num_cap_flushing++;
dout(" inode %p now flushing seq %lld\n", inode, dout(" inode %p now flushing seq %lld\n", inode,

Просмотреть файл

@ -1464,19 +1464,33 @@ out_unlocked:
return err; 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. * flush all dirty inode data to disk.
* *
* returns true if we've flushed through want_flush_seq * 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); dout("check_cap_flush want %lld\n", want_flush_seq);
mutex_lock(&mdsc->mutex); 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 ceph_mds_session *session = mdsc->sessions[mds];
struct inode *inode = NULL;
if (!session) if (!session)
continue; 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, list_entry(session->s_cap_flushing.next,
struct ceph_inode_info, struct ceph_inode_info,
i_flushing_item); i_flushing_item);
struct inode *inode = &ci->vfs_inode;
spin_lock(&ci->i_ceph_lock); if (!check_cap_flush(&ci->vfs_inode, want_flush_seq)) {
if (ci->i_cap_flush_seq <= want_flush_seq) {
dout("check_cap_flush still flushing %p " dout("check_cap_flush still flushing %p "
"seq %lld <= %lld to mds%d\n", inode, "seq %lld <= %lld to mds%d\n",
ci->i_cap_flush_seq, want_flush_seq, &ci->vfs_inode, ci->i_cap_flush_seq,
session->s_mds); want_flush_seq, session->s_mds);
ret = 0; inode = igrab(&ci->vfs_inode);
} }
spin_unlock(&ci->i_ceph_lock);
} }
mutex_unlock(&session->s_mutex); mutex_unlock(&session->s_mutex);
ceph_put_mds_session(session); ceph_put_mds_session(session);
if (!ret) if (inode) {
return ret; wait_event(mdsc->cap_flushing_wq,
check_cap_flush(inode, want_flush_seq));
iput(inode);
}
mutex_lock(&mdsc->mutex); mutex_lock(&mdsc->mutex);
} }
mutex_unlock(&mdsc->mutex); mutex_unlock(&mdsc->mutex);
dout("check_cap_flush ok, flushed thru %lld\n", want_flush_seq); 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"); dout("sync\n");
mutex_lock(&mdsc->mutex); mutex_lock(&mdsc->mutex);
want_tid = mdsc->last_tid; want_tid = mdsc->last_tid;
want_flush = mdsc->cap_flush_seq;
mutex_unlock(&mdsc->mutex); mutex_unlock(&mdsc->mutex);
dout("sync want tid %lld flush_seq %lld\n", want_tid, want_flush);
ceph_flush_dirty_caps(mdsc); 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_unsafe_requests(mdsc, want_tid);
wait_event(mdsc->cap_flushing_wq, check_cap_flush(mdsc, want_flush)); wait_caps_flush(mdsc, want_flush);
} }
/* /*