diff options
Diffstat (limited to 'fs/ceph/mds_client.c')
-rw-r--r-- | fs/ceph/mds_client.c | 44 |
1 files changed, 33 insertions, 11 deletions
diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c index a2600101ec22..60a9a4ae47be 100644 --- a/fs/ceph/mds_client.c +++ b/fs/ceph/mds_client.c | |||
@@ -1,6 +1,7 @@ | |||
1 | #include "ceph_debug.h" | 1 | #include "ceph_debug.h" |
2 | 2 | ||
3 | #include <linux/wait.h> | 3 | #include <linux/wait.h> |
4 | #include <linux/slab.h> | ||
4 | #include <linux/sched.h> | 5 | #include <linux/sched.h> |
5 | 6 | ||
6 | #include "mds_client.h" | 7 | #include "mds_client.h" |
@@ -328,6 +329,8 @@ static struct ceph_mds_session *register_session(struct ceph_mds_client *mdsc, | |||
328 | struct ceph_mds_session *s; | 329 | struct ceph_mds_session *s; |
329 | 330 | ||
330 | s = kzalloc(sizeof(*s), GFP_NOFS); | 331 | s = kzalloc(sizeof(*s), GFP_NOFS); |
332 | if (!s) | ||
333 | return ERR_PTR(-ENOMEM); | ||
331 | s->s_mdsc = mdsc; | 334 | s->s_mdsc = mdsc; |
332 | s->s_mds = mds; | 335 | s->s_mds = mds; |
333 | s->s_state = CEPH_MDS_SESSION_NEW; | 336 | s->s_state = CEPH_MDS_SESSION_NEW; |
@@ -529,7 +532,7 @@ static void __unregister_request(struct ceph_mds_client *mdsc, | |||
529 | { | 532 | { |
530 | dout("__unregister_request %p tid %lld\n", req, req->r_tid); | 533 | dout("__unregister_request %p tid %lld\n", req, req->r_tid); |
531 | rb_erase(&req->r_node, &mdsc->request_tree); | 534 | rb_erase(&req->r_node, &mdsc->request_tree); |
532 | ceph_mdsc_put_request(req); | 535 | RB_CLEAR_NODE(&req->r_node); |
533 | 536 | ||
534 | if (req->r_unsafe_dir) { | 537 | if (req->r_unsafe_dir) { |
535 | struct ceph_inode_info *ci = ceph_inode(req->r_unsafe_dir); | 538 | struct ceph_inode_info *ci = ceph_inode(req->r_unsafe_dir); |
@@ -538,6 +541,8 @@ static void __unregister_request(struct ceph_mds_client *mdsc, | |||
538 | list_del_init(&req->r_unsafe_dir_item); | 541 | list_del_init(&req->r_unsafe_dir_item); |
539 | spin_unlock(&ci->i_unsafe_lock); | 542 | spin_unlock(&ci->i_unsafe_lock); |
540 | } | 543 | } |
544 | |||
545 | ceph_mdsc_put_request(req); | ||
541 | } | 546 | } |
542 | 547 | ||
543 | /* | 548 | /* |
@@ -862,6 +867,7 @@ static int send_renew_caps(struct ceph_mds_client *mdsc, | |||
862 | if (time_after_eq(jiffies, session->s_cap_ttl) && | 867 | if (time_after_eq(jiffies, session->s_cap_ttl) && |
863 | time_after_eq(session->s_cap_ttl, session->s_renew_requested)) | 868 | time_after_eq(session->s_cap_ttl, session->s_renew_requested)) |
864 | pr_info("mds%d caps stale\n", session->s_mds); | 869 | pr_info("mds%d caps stale\n", session->s_mds); |
870 | session->s_renew_requested = jiffies; | ||
865 | 871 | ||
866 | /* do not try to renew caps until a recovering mds has reconnected | 872 | /* do not try to renew caps until a recovering mds has reconnected |
867 | * with its clients. */ | 873 | * with its clients. */ |
@@ -874,7 +880,6 @@ static int send_renew_caps(struct ceph_mds_client *mdsc, | |||
874 | 880 | ||
875 | dout("send_renew_caps to mds%d (%s)\n", session->s_mds, | 881 | dout("send_renew_caps to mds%d (%s)\n", session->s_mds, |
876 | ceph_mds_state_name(state)); | 882 | ceph_mds_state_name(state)); |
877 | session->s_renew_requested = jiffies; | ||
878 | msg = create_session_msg(CEPH_SESSION_REQUEST_RENEWCAPS, | 883 | msg = create_session_msg(CEPH_SESSION_REQUEST_RENEWCAPS, |
879 | ++session->s_renew_seq); | 884 | ++session->s_renew_seq); |
880 | if (IS_ERR(msg)) | 885 | if (IS_ERR(msg)) |
@@ -1566,8 +1571,13 @@ static int __do_request(struct ceph_mds_client *mdsc, | |||
1566 | 1571 | ||
1567 | /* get, open session */ | 1572 | /* get, open session */ |
1568 | session = __ceph_lookup_mds_session(mdsc, mds); | 1573 | session = __ceph_lookup_mds_session(mdsc, mds); |
1569 | if (!session) | 1574 | if (!session) { |
1570 | session = register_session(mdsc, mds); | 1575 | session = register_session(mdsc, mds); |
1576 | if (IS_ERR(session)) { | ||
1577 | err = PTR_ERR(session); | ||
1578 | goto finish; | ||
1579 | } | ||
1580 | } | ||
1571 | dout("do_request mds%d session %p state %s\n", mds, session, | 1581 | dout("do_request mds%d session %p state %s\n", mds, session, |
1572 | session_state_name(session->s_state)); | 1582 | session_state_name(session->s_state)); |
1573 | if (session->s_state != CEPH_MDS_SESSION_OPEN && | 1583 | if (session->s_state != CEPH_MDS_SESSION_OPEN && |
@@ -1770,7 +1780,7 @@ static void handle_reply(struct ceph_mds_session *session, struct ceph_msg *msg) | |||
1770 | dout("handle_reply %p\n", req); | 1780 | dout("handle_reply %p\n", req); |
1771 | 1781 | ||
1772 | /* correct session? */ | 1782 | /* correct session? */ |
1773 | if (!req->r_session && req->r_session != session) { | 1783 | if (req->r_session != session) { |
1774 | pr_err("mdsc_handle_reply got %llu on session mds%d" | 1784 | pr_err("mdsc_handle_reply got %llu on session mds%d" |
1775 | " not mds%d\n", tid, session->s_mds, | 1785 | " not mds%d\n", tid, session->s_mds, |
1776 | req->r_session ? req->r_session->s_mds : -1); | 1786 | req->r_session ? req->r_session->s_mds : -1); |
@@ -2682,29 +2692,41 @@ void ceph_mdsc_pre_umount(struct ceph_mds_client *mdsc) | |||
2682 | */ | 2692 | */ |
2683 | static void wait_unsafe_requests(struct ceph_mds_client *mdsc, u64 want_tid) | 2693 | static void wait_unsafe_requests(struct ceph_mds_client *mdsc, u64 want_tid) |
2684 | { | 2694 | { |
2685 | struct ceph_mds_request *req = NULL; | 2695 | struct ceph_mds_request *req = NULL, *nextreq; |
2686 | struct rb_node *n; | 2696 | struct rb_node *n; |
2687 | 2697 | ||
2688 | mutex_lock(&mdsc->mutex); | 2698 | mutex_lock(&mdsc->mutex); |
2689 | dout("wait_unsafe_requests want %lld\n", want_tid); | 2699 | dout("wait_unsafe_requests want %lld\n", want_tid); |
2700 | restart: | ||
2690 | req = __get_oldest_req(mdsc); | 2701 | req = __get_oldest_req(mdsc); |
2691 | while (req && req->r_tid <= want_tid) { | 2702 | while (req && req->r_tid <= want_tid) { |
2703 | /* find next request */ | ||
2704 | n = rb_next(&req->r_node); | ||
2705 | if (n) | ||
2706 | nextreq = rb_entry(n, struct ceph_mds_request, r_node); | ||
2707 | else | ||
2708 | nextreq = NULL; | ||
2692 | if ((req->r_op & CEPH_MDS_OP_WRITE)) { | 2709 | if ((req->r_op & CEPH_MDS_OP_WRITE)) { |
2693 | /* write op */ | 2710 | /* write op */ |
2694 | ceph_mdsc_get_request(req); | 2711 | ceph_mdsc_get_request(req); |
2712 | if (nextreq) | ||
2713 | ceph_mdsc_get_request(nextreq); | ||
2695 | mutex_unlock(&mdsc->mutex); | 2714 | mutex_unlock(&mdsc->mutex); |
2696 | dout("wait_unsafe_requests wait on %llu (want %llu)\n", | 2715 | dout("wait_unsafe_requests wait on %llu (want %llu)\n", |
2697 | req->r_tid, want_tid); | 2716 | req->r_tid, want_tid); |
2698 | wait_for_completion(&req->r_safe_completion); | 2717 | wait_for_completion(&req->r_safe_completion); |
2699 | mutex_lock(&mdsc->mutex); | 2718 | mutex_lock(&mdsc->mutex); |
2700 | n = rb_next(&req->r_node); | ||
2701 | ceph_mdsc_put_request(req); | 2719 | ceph_mdsc_put_request(req); |
2702 | } else { | 2720 | if (!nextreq) |
2703 | n = rb_next(&req->r_node); | 2721 | break; /* next dne before, so we're done! */ |
2722 | if (RB_EMPTY_NODE(&nextreq->r_node)) { | ||
2723 | /* next request was removed from tree */ | ||
2724 | ceph_mdsc_put_request(nextreq); | ||
2725 | goto restart; | ||
2726 | } | ||
2727 | ceph_mdsc_put_request(nextreq); /* won't go away */ | ||
2704 | } | 2728 | } |
2705 | if (!n) | 2729 | req = nextreq; |
2706 | break; | ||
2707 | req = rb_entry(n, struct ceph_mds_request, r_node); | ||
2708 | } | 2730 | } |
2709 | mutex_unlock(&mdsc->mutex); | 2731 | mutex_unlock(&mdsc->mutex); |
2710 | dout("wait_unsafe_requests done\n"); | 2732 | dout("wait_unsafe_requests done\n"); |