diff options
author | Yan, Zheng <zyan@redhat.com> | 2015-01-08 08:30:12 -0500 |
---|---|---|
committer | Ilya Dryomov <idryomov@gmail.com> | 2015-02-19 05:31:38 -0500 |
commit | d3383a8e37f802818cde4cb489bb0735db637cf0 (patch) | |
tree | d4c662fa1a495440c7e6f5e9c851e2562287f930 /fs/ceph | |
parent | 73e39e4dba828fe1affefe6290456623319707bd (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.c | 2 | ||||
-rw-r--r-- | fs/ceph/mds_client.c | 51 |
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 | ||
1467 | static 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 | */ |
1472 | static int check_cap_flush(struct ceph_mds_client *mdsc, u64 want_flush_seq) | 1485 | static 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 | /* |