aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ceph
diff options
context:
space:
mode:
authorYan, Zheng <zyan@redhat.com>2015-01-08 08:30:12 -0500
committerIlya Dryomov <idryomov@gmail.com>2015-02-19 05:31:38 -0500
commitd3383a8e37f802818cde4cb489bb0735db637cf0 (patch)
treed4c662fa1a495440c7e6f5e9c851e2562287f930 /fs/ceph
parent73e39e4dba828fe1affefe6290456623319707bd (diff)
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>
Diffstat (limited to 'fs/ceph')
-rw-r--r--fs/ceph/caps.c2
-rw-r--r--fs/ceph/mds_client.c51
2 files changed, 35 insertions, 18 deletions
diff --git a/fs/ceph/caps.c b/fs/ceph/caps.c
index 8ed1192606d9..844b57cb52bd 100644
--- a/fs/ceph/caps.c
+++ b/fs/ceph/caps.c
@@ -1450,8 +1450,8 @@ static int __mark_caps_flushing(struct inode *inode,
1450 spin_lock(&mdsc->cap_dirty_lock); 1450 spin_lock(&mdsc->cap_dirty_lock);
1451 list_del_init(&ci->i_dirty_item); 1451 list_del_init(&ci->i_dirty_item);
1452 1452
1453 ci->i_cap_flush_seq = ++mdsc->cap_flush_seq;
1454 if (list_empty(&ci->i_flushing_item)) { 1453 if (list_empty(&ci->i_flushing_item)) {
1454 ci->i_cap_flush_seq = ++mdsc->cap_flush_seq;
1455 list_add_tail(&ci->i_flushing_item, &session->s_cap_flushing); 1455 list_add_tail(&ci->i_flushing_item, &session->s_cap_flushing);
1456 mdsc->num_cap_flushing++; 1456 mdsc->num_cap_flushing++;
1457 dout(" inode %p now flushing seq %lld\n", inode, 1457 dout(" inode %p now flushing seq %lld\n", inode,
diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c
index 85c67ae03e46..fdf5cc8737ee 100644
--- a/fs/ceph/mds_client.c
+++ b/fs/ceph/mds_client.c
@@ -1464,19 +1464,33 @@ out_unlocked:
1464 return err; 1464 return err;
1465} 1465}
1466 1466
1467static int check_cap_flush(struct inode *inode, u64 want_flush_seq)
1468{
1469 struct ceph_inode_info *ci = ceph_inode(inode);
1470 int ret;
1471 spin_lock(&ci->i_ceph_lock);
1472 if (ci->i_flushing_caps)
1473 ret = ci->i_cap_flush_seq >= want_flush_seq;
1474 else
1475 ret = 1;
1476 spin_unlock(&ci->i_ceph_lock);
1477 return ret;
1478}
1479
1467/* 1480/*
1468 * flush all dirty inode data to disk. 1481 * flush all dirty inode data to disk.
1469 * 1482 *
1470 * returns true if we've flushed through want_flush_seq 1483 * returns true if we've flushed through want_flush_seq
1471 */ 1484 */
1472static int check_cap_flush(struct ceph_mds_client *mdsc, u64 want_flush_seq) 1485static void wait_caps_flush(struct ceph_mds_client *mdsc, u64 want_flush_seq)
1473{ 1486{
1474 int mds, ret = 1; 1487 int mds;
1475 1488
1476 dout("check_cap_flush want %lld\n", want_flush_seq); 1489 dout("check_cap_flush want %lld\n", want_flush_seq);
1477 mutex_lock(&mdsc->mutex); 1490 mutex_lock(&mdsc->mutex);
1478 for (mds = 0; ret && mds < mdsc->max_sessions; mds++) { 1491 for (mds = 0; mds < mdsc->max_sessions; mds++) {
1479 struct ceph_mds_session *session = mdsc->sessions[mds]; 1492 struct ceph_mds_session *session = mdsc->sessions[mds];
1493 struct inode *inode = NULL;
1480 1494
1481 if (!session) 1495 if (!session)
1482 continue; 1496 continue;
@@ -1489,29 +1503,29 @@ static int check_cap_flush(struct ceph_mds_client *mdsc, u64 want_flush_seq)
1489 list_entry(session->s_cap_flushing.next, 1503 list_entry(session->s_cap_flushing.next,
1490 struct ceph_inode_info, 1504 struct ceph_inode_info,
1491 i_flushing_item); 1505 i_flushing_item);
1492 struct inode *inode = &ci->vfs_inode;
1493 1506
1494 spin_lock(&ci->i_ceph_lock); 1507 if (!check_cap_flush(&ci->vfs_inode, want_flush_seq)) {
1495 if (ci->i_cap_flush_seq <= want_flush_seq) {
1496 dout("check_cap_flush still flushing %p " 1508 dout("check_cap_flush still flushing %p "
1497 "seq %lld <= %lld to mds%d\n", inode, 1509 "seq %lld <= %lld to mds%d\n",
1498 ci->i_cap_flush_seq, want_flush_seq, 1510 &ci->vfs_inode, ci->i_cap_flush_seq,
1499 session->s_mds); 1511 want_flush_seq, session->s_mds);
1500 ret = 0; 1512 inode = igrab(&ci->vfs_inode);
1501 } 1513 }
1502 spin_unlock(&ci->i_ceph_lock);
1503 } 1514 }
1504 mutex_unlock(&session->s_mutex); 1515 mutex_unlock(&session->s_mutex);
1505 ceph_put_mds_session(session); 1516 ceph_put_mds_session(session);
1506 1517
1507 if (!ret) 1518 if (inode) {
1508 return ret; 1519 wait_event(mdsc->cap_flushing_wq,
1520 check_cap_flush(inode, want_flush_seq));
1521 iput(inode);
1522 }
1523
1509 mutex_lock(&mdsc->mutex); 1524 mutex_lock(&mdsc->mutex);
1510 } 1525 }
1511 1526
1512 mutex_unlock(&mdsc->mutex); 1527 mutex_unlock(&mdsc->mutex);
1513 dout("check_cap_flush ok, flushed thru %lld\n", want_flush_seq); 1528 dout("check_cap_flush ok, flushed thru %lld\n", want_flush_seq);
1514 return ret;
1515} 1529}
1516 1530
1517/* 1531/*
@@ -3447,14 +3461,17 @@ void ceph_mdsc_sync(struct ceph_mds_client *mdsc)
3447 dout("sync\n"); 3461 dout("sync\n");
3448 mutex_lock(&mdsc->mutex); 3462 mutex_lock(&mdsc->mutex);
3449 want_tid = mdsc->last_tid; 3463 want_tid = mdsc->last_tid;
3450 want_flush = mdsc->cap_flush_seq;
3451 mutex_unlock(&mdsc->mutex); 3464 mutex_unlock(&mdsc->mutex);
3452 dout("sync want tid %lld flush_seq %lld\n", want_tid, want_flush);
3453 3465
3454 ceph_flush_dirty_caps(mdsc); 3466 ceph_flush_dirty_caps(mdsc);
3467 spin_lock(&mdsc->cap_dirty_lock);
3468 want_flush = mdsc->cap_flush_seq;
3469 spin_unlock(&mdsc->cap_dirty_lock);
3470
3471 dout("sync want tid %lld flush_seq %lld\n", want_tid, want_flush);
3455 3472
3456 wait_unsafe_requests(mdsc, want_tid); 3473 wait_unsafe_requests(mdsc, want_tid);
3457 wait_event(mdsc->cap_flushing_wq, check_cap_flush(mdsc, want_flush)); 3474 wait_caps_flush(mdsc, want_flush);
3458} 3475}
3459 3476
3460/* 3477/*