diff options
author | Yan, Zheng <zyan@redhat.com> | 2015-05-05 09:22:13 -0400 |
---|---|---|
committer | Ilya Dryomov <idryomov@gmail.com> | 2015-06-25 04:49:29 -0400 |
commit | affbc19a68f9966ad65a773db405f78e2bafc07b (patch) | |
tree | 63c34c40700e8b1fe1a73f1df244f3143b7aa99f /fs/ceph/mds_client.c | |
parent | 622f3e250f498976ad4cbae6f2be5cb359ded4f5 (diff) |
ceph: make sure syncfs flushes all cap snaps
Signed-off-by: Yan, Zheng <zyan@redhat.com>
Diffstat (limited to 'fs/ceph/mds_client.c')
-rw-r--r-- | fs/ceph/mds_client.c | 86 |
1 files changed, 62 insertions, 24 deletions
diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c index 88010f9a254d..2bb9264b9225 100644 --- a/fs/ceph/mds_client.c +++ b/fs/ceph/mds_client.c | |||
@@ -1488,17 +1488,22 @@ out_unlocked: | |||
1488 | return err; | 1488 | return err; |
1489 | } | 1489 | } |
1490 | 1490 | ||
1491 | static int check_cap_flush(struct inode *inode, u64 want_flush_seq) | 1491 | static int check_cap_flush(struct ceph_inode_info *ci, |
1492 | u64 want_flush_seq, u64 want_snap_seq) | ||
1492 | { | 1493 | { |
1493 | struct ceph_inode_info *ci = ceph_inode(inode); | 1494 | int ret1 = 1, ret2 = 1; |
1494 | int ret; | ||
1495 | spin_lock(&ci->i_ceph_lock); | 1495 | spin_lock(&ci->i_ceph_lock); |
1496 | if (ci->i_flushing_caps) | 1496 | if (want_flush_seq > 0 && ci->i_flushing_caps) |
1497 | ret = ci->i_cap_flush_seq >= want_flush_seq; | 1497 | ret1 = ci->i_cap_flush_seq >= want_flush_seq; |
1498 | else | 1498 | |
1499 | ret = 1; | 1499 | if (want_snap_seq > 0 && !list_empty(&ci->i_cap_snaps)) { |
1500 | struct ceph_cap_snap *capsnap = | ||
1501 | list_first_entry(&ci->i_cap_snaps, | ||
1502 | struct ceph_cap_snap, ci_item); | ||
1503 | ret2 = capsnap->follows >= want_snap_seq; | ||
1504 | } | ||
1500 | spin_unlock(&ci->i_ceph_lock); | 1505 | spin_unlock(&ci->i_ceph_lock); |
1501 | return ret; | 1506 | return ret1 && ret2; |
1502 | } | 1507 | } |
1503 | 1508 | ||
1504 | /* | 1509 | /* |
@@ -1506,45 +1511,72 @@ static int check_cap_flush(struct inode *inode, u64 want_flush_seq) | |||
1506 | * | 1511 | * |
1507 | * returns true if we've flushed through want_flush_seq | 1512 | * returns true if we've flushed through want_flush_seq |
1508 | */ | 1513 | */ |
1509 | static void wait_caps_flush(struct ceph_mds_client *mdsc, u64 want_flush_seq) | 1514 | static void wait_caps_flush(struct ceph_mds_client *mdsc, |
1515 | u64 want_flush_seq, u64 want_snap_seq) | ||
1510 | { | 1516 | { |
1511 | int mds; | 1517 | int mds; |
1512 | 1518 | ||
1513 | dout("check_cap_flush want %lld\n", want_flush_seq); | 1519 | dout("check_cap_flush want %lld\n", want_flush_seq); |
1514 | mutex_lock(&mdsc->mutex); | 1520 | mutex_lock(&mdsc->mutex); |
1515 | for (mds = 0; mds < mdsc->max_sessions; mds++) { | 1521 | for (mds = 0; mds < mdsc->max_sessions; ) { |
1516 | struct ceph_mds_session *session = mdsc->sessions[mds]; | 1522 | struct ceph_mds_session *session = mdsc->sessions[mds]; |
1517 | struct inode *inode = NULL; | 1523 | struct inode *inode1 = NULL, *inode2 = NULL; |
1518 | 1524 | ||
1519 | if (!session) | 1525 | if (!session) { |
1526 | mds++; | ||
1520 | continue; | 1527 | continue; |
1528 | } | ||
1521 | get_session(session); | 1529 | get_session(session); |
1522 | mutex_unlock(&mdsc->mutex); | 1530 | mutex_unlock(&mdsc->mutex); |
1523 | 1531 | ||
1524 | mutex_lock(&session->s_mutex); | 1532 | mutex_lock(&session->s_mutex); |
1525 | if (!list_empty(&session->s_cap_flushing)) { | 1533 | if (!list_empty(&session->s_cap_flushing)) { |
1526 | struct ceph_inode_info *ci = | 1534 | struct ceph_inode_info *ci = |
1527 | list_entry(session->s_cap_flushing.next, | 1535 | list_first_entry(&session->s_cap_flushing, |
1528 | struct ceph_inode_info, | 1536 | struct ceph_inode_info, |
1529 | i_flushing_item); | 1537 | i_flushing_item); |
1530 | 1538 | ||
1531 | if (!check_cap_flush(&ci->vfs_inode, want_flush_seq)) { | 1539 | if (!check_cap_flush(ci, want_flush_seq, 0)) { |
1532 | dout("check_cap_flush still flushing %p " | 1540 | dout("check_cap_flush still flushing %p " |
1533 | "seq %lld <= %lld to mds%d\n", | 1541 | "seq %lld <= %lld to mds%d\n", |
1534 | &ci->vfs_inode, ci->i_cap_flush_seq, | 1542 | &ci->vfs_inode, ci->i_cap_flush_seq, |
1535 | want_flush_seq, session->s_mds); | 1543 | want_flush_seq, mds); |
1536 | inode = igrab(&ci->vfs_inode); | 1544 | inode1 = igrab(&ci->vfs_inode); |
1545 | } | ||
1546 | } | ||
1547 | if (!list_empty(&session->s_cap_snaps_flushing)) { | ||
1548 | struct ceph_cap_snap *capsnap = | ||
1549 | list_first_entry(&session->s_cap_snaps_flushing, | ||
1550 | struct ceph_cap_snap, | ||
1551 | flushing_item); | ||
1552 | struct ceph_inode_info *ci = capsnap->ci; | ||
1553 | if (!check_cap_flush(ci, 0, want_snap_seq)) { | ||
1554 | dout("check_cap_flush still flushing snap %p " | ||
1555 | "follows %lld <= %lld to mds%d\n", | ||
1556 | &ci->vfs_inode, capsnap->follows, | ||
1557 | want_snap_seq, mds); | ||
1558 | inode2 = igrab(&ci->vfs_inode); | ||
1537 | } | 1559 | } |
1538 | } | 1560 | } |
1539 | mutex_unlock(&session->s_mutex); | 1561 | mutex_unlock(&session->s_mutex); |
1540 | ceph_put_mds_session(session); | 1562 | ceph_put_mds_session(session); |
1541 | 1563 | ||
1542 | if (inode) { | 1564 | if (inode1) { |
1543 | wait_event(mdsc->cap_flushing_wq, | 1565 | wait_event(mdsc->cap_flushing_wq, |
1544 | check_cap_flush(inode, want_flush_seq)); | 1566 | check_cap_flush(ceph_inode(inode1), |
1545 | iput(inode); | 1567 | want_flush_seq, 0)); |
1568 | iput(inode1); | ||
1569 | } | ||
1570 | if (inode2) { | ||
1571 | wait_event(mdsc->cap_flushing_wq, | ||
1572 | check_cap_flush(ceph_inode(inode2), | ||
1573 | 0, want_snap_seq)); | ||
1574 | iput(inode2); | ||
1546 | } | 1575 | } |
1547 | 1576 | ||
1577 | if (!inode1 && !inode2) | ||
1578 | mds++; | ||
1579 | |||
1548 | mutex_lock(&mdsc->mutex); | 1580 | mutex_lock(&mdsc->mutex); |
1549 | } | 1581 | } |
1550 | 1582 | ||
@@ -3391,6 +3423,7 @@ int ceph_mdsc_init(struct ceph_fs_client *fsc) | |||
3391 | atomic_set(&mdsc->num_sessions, 0); | 3423 | atomic_set(&mdsc->num_sessions, 0); |
3392 | mdsc->max_sessions = 0; | 3424 | mdsc->max_sessions = 0; |
3393 | mdsc->stopping = 0; | 3425 | mdsc->stopping = 0; |
3426 | mdsc->last_snap_seq = 0; | ||
3394 | init_rwsem(&mdsc->snap_rwsem); | 3427 | init_rwsem(&mdsc->snap_rwsem); |
3395 | mdsc->snap_realms = RB_ROOT; | 3428 | mdsc->snap_realms = RB_ROOT; |
3396 | INIT_LIST_HEAD(&mdsc->snap_empty); | 3429 | INIT_LIST_HEAD(&mdsc->snap_empty); |
@@ -3517,7 +3550,7 @@ restart: | |||
3517 | 3550 | ||
3518 | void ceph_mdsc_sync(struct ceph_mds_client *mdsc) | 3551 | void ceph_mdsc_sync(struct ceph_mds_client *mdsc) |
3519 | { | 3552 | { |
3520 | u64 want_tid, want_flush; | 3553 | u64 want_tid, want_flush, want_snap; |
3521 | 3554 | ||
3522 | if (mdsc->fsc->mount_state == CEPH_MOUNT_SHUTDOWN) | 3555 | if (mdsc->fsc->mount_state == CEPH_MOUNT_SHUTDOWN) |
3523 | return; | 3556 | return; |
@@ -3532,10 +3565,15 @@ void ceph_mdsc_sync(struct ceph_mds_client *mdsc) | |||
3532 | want_flush = mdsc->cap_flush_seq; | 3565 | want_flush = mdsc->cap_flush_seq; |
3533 | spin_unlock(&mdsc->cap_dirty_lock); | 3566 | spin_unlock(&mdsc->cap_dirty_lock); |
3534 | 3567 | ||
3535 | dout("sync want tid %lld flush_seq %lld\n", want_tid, want_flush); | 3568 | down_read(&mdsc->snap_rwsem); |
3569 | want_snap = mdsc->last_snap_seq; | ||
3570 | up_read(&mdsc->snap_rwsem); | ||
3571 | |||
3572 | dout("sync want tid %lld flush_seq %lld snap_seq %lld\n", | ||
3573 | want_tid, want_flush, want_snap); | ||
3536 | 3574 | ||
3537 | wait_unsafe_requests(mdsc, want_tid); | 3575 | wait_unsafe_requests(mdsc, want_tid); |
3538 | wait_caps_flush(mdsc, want_flush); | 3576 | wait_caps_flush(mdsc, want_flush, want_snap); |
3539 | } | 3577 | } |
3540 | 3578 | ||
3541 | /* | 3579 | /* |