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:
Родитель
73e39e4dba
Коммит
d3383a8e37
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
Загрузка…
Ссылка в новой задаче