]> git.proxmox.com Git - mirror_ubuntu-zesty-kernel.git/blobdiff - fs/ceph/mon_client.c
include cleanup: Update gfp.h and slab.h includes to prepare for breaking implicit...
[mirror_ubuntu-zesty-kernel.git] / fs / ceph / mon_client.c
index 223e8bc207e39aeffb6983ec1b7ab94a51024b15..8fdc011ca956c64e5feb33285ff989fa8d792bdd 100644 (file)
@@ -1,6 +1,7 @@
 #include "ceph_debug.h"
 
 #include <linux/types.h>
+#include <linux/slab.h>
 #include <linux/random.h>
 #include <linux/sched.h>
 
@@ -29,6 +30,8 @@
 
 const static struct ceph_connection_operations mon_con_ops;
 
+static int __validate_auth(struct ceph_mon_client *monc);
+
 /*
  * Decode a monmap blob (e.g., during mount).
  */
@@ -93,6 +96,18 @@ int ceph_monmap_contains(struct ceph_monmap *m, struct ceph_entity_addr *addr)
        return 0;
 }
 
+/*
+ * Send an auth request.
+ */
+static void __send_prepared_auth_request(struct ceph_mon_client *monc, int len)
+{
+       monc->pending_auth = 1;
+       monc->m_auth->front.iov_len = len;
+       monc->m_auth->hdr.front_len = cpu_to_le32(len);
+       ceph_msg_get(monc->m_auth);  /* keep our ref */
+       ceph_con_send(monc->con, monc->m_auth);
+}
+
 /*
  * Close monitor session, if any.
  */
@@ -103,6 +118,7 @@ static void __close_session(struct ceph_mon_client *monc)
                ceph_con_revoke(monc->con, monc->m_auth);
                ceph_con_close(monc->con);
                monc->cur_mon = -1;
+               monc->pending_auth = 0;
                ceph_auth_reset(monc->auth);
        }
 }
@@ -134,10 +150,7 @@ static int __open_session(struct ceph_mon_client *monc)
                ret = ceph_auth_build_hello(monc->auth,
                                            monc->m_auth->front.iov_base,
                                            monc->m_auth->front_max);
-               monc->m_auth->front.iov_len = ret;
-               monc->m_auth->hdr.front_len = cpu_to_le32(ret);
-               ceph_msg_get(monc->m_auth);  /* keep our ref */
-               ceph_con_send(monc->con, monc->m_auth);
+               __send_prepared_auth_request(monc, ret);
        } else {
                dout("open_session mon%d already open\n", monc->cur_mon);
        }
@@ -334,12 +347,52 @@ static void ceph_monc_handle_map(struct ceph_mon_client *monc,
 
 out:
        mutex_unlock(&monc->mutex);
-       wake_up(&client->mount_wq);
+       wake_up(&client->auth_wq);
 }
 
 /*
  * statfs
  */
+static struct ceph_mon_statfs_request *__lookup_statfs(
+       struct ceph_mon_client *monc, u64 tid)
+{
+       struct ceph_mon_statfs_request *req;
+       struct rb_node *n = monc->statfs_request_tree.rb_node;
+
+       while (n) {
+               req = rb_entry(n, struct ceph_mon_statfs_request, node);
+               if (tid < req->tid)
+                       n = n->rb_left;
+               else if (tid > req->tid)
+                       n = n->rb_right;
+               else
+                       return req;
+       }
+       return NULL;
+}
+
+static void __insert_statfs(struct ceph_mon_client *monc,
+                           struct ceph_mon_statfs_request *new)
+{
+       struct rb_node **p = &monc->statfs_request_tree.rb_node;
+       struct rb_node *parent = NULL;
+       struct ceph_mon_statfs_request *req = NULL;
+
+       while (*p) {
+               parent = *p;
+               req = rb_entry(parent, struct ceph_mon_statfs_request, node);
+               if (new->tid < req->tid)
+                       p = &(*p)->rb_left;
+               else if (new->tid > req->tid)
+                       p = &(*p)->rb_right;
+               else
+                       BUG();
+       }
+
+       rb_link_node(&new->node, parent, p);
+       rb_insert_color(&new->node, &monc->statfs_request_tree);
+}
+
 static void handle_statfs_reply(struct ceph_mon_client *monc,
                                struct ceph_msg *msg)
 {
@@ -353,7 +406,7 @@ static void handle_statfs_reply(struct ceph_mon_client *monc,
        dout("handle_statfs_reply %p tid %llu\n", msg, tid);
 
        mutex_lock(&monc->mutex);
-       req = radix_tree_lookup(&monc->statfs_request_tree, tid);
+       req = __lookup_statfs(monc, tid);
        if (req) {
                *req->buf = reply->st;
                req->result = 0;
@@ -413,11 +466,7 @@ int ceph_monc_do_statfs(struct ceph_mon_client *monc, struct ceph_statfs *buf)
        req.tid = ++monc->last_tid;
        req.last_attempt = jiffies;
        req.delay = BASE_DELAY_INTERVAL;
-       if (radix_tree_insert(&monc->statfs_request_tree, req.tid, &req) < 0) {
-               mutex_unlock(&monc->mutex);
-               pr_err("ENOMEM in do_statfs\n");
-               return -ENOMEM;
-       }
+       __insert_statfs(monc, &req);
        monc->num_statfs_requests++;
        mutex_unlock(&monc->mutex);
 
@@ -427,7 +476,7 @@ int ceph_monc_do_statfs(struct ceph_mon_client *monc, struct ceph_statfs *buf)
                err = wait_for_completion_interruptible(&req.completion);
 
        mutex_lock(&monc->mutex);
-       radix_tree_delete(&monc->statfs_request_tree, req.tid);
+       rb_erase(&req.node, &monc->statfs_request_tree);
        monc->num_statfs_requests--;
        ceph_msgpool_resv(&monc->msgpool_statfs_reply, -1);
        mutex_unlock(&monc->mutex);
@@ -442,20 +491,11 @@ int ceph_monc_do_statfs(struct ceph_mon_client *monc, struct ceph_statfs *buf)
  */
 static void __resend_statfs(struct ceph_mon_client *monc)
 {
-       u64 next_tid = 0;
-       int got;
-       int did = 0;
        struct ceph_mon_statfs_request *req;
+       struct rb_node *p;
 
-       while (1) {
-               got = radix_tree_gang_lookup(&monc->statfs_request_tree,
-                                            (void **)&req,
-                                            next_tid, 1);
-               if (got == 0)
-                       break;
-               did++;
-               next_tid = req->tid + 1;
-
+       for (p = rb_first(&monc->statfs_request_tree); p; p = rb_next(p)) {
+               req = rb_entry(p, struct ceph_mon_statfs_request, node);
                send_statfs(monc, req);
        }
 }
@@ -477,6 +517,9 @@ static void delayed_work(struct work_struct *work)
                __open_session(monc);  /* continue hunting */
        } else {
                ceph_con_keepalive(monc->con);
+
+               __validate_auth(monc);
+
                if (monc->auth->ops->is_authenticated(monc->auth))
                        __send_subscribe(monc);
        }
@@ -557,6 +600,7 @@ int ceph_monc_init(struct ceph_mon_client *monc, struct ceph_client *cl)
                goto out_pool2;
 
        monc->m_auth = ceph_msg_new(CEPH_MSG_AUTH, 4096, 0, 0, NULL);
+       monc->pending_auth = 0;
        if (IS_ERR(monc->m_auth)) {
                err = PTR_ERR(monc->m_auth);
                monc->m_auth = NULL;
@@ -569,7 +613,7 @@ int ceph_monc_init(struct ceph_mon_client *monc, struct ceph_client *cl)
        monc->sub_sent = 0;
 
        INIT_DELAYED_WORK(&monc->delayed_work, delayed_work);
-       INIT_RADIX_TREE(&monc->statfs_request_tree, GFP_NOFS);
+       monc->statfs_request_tree = RB_ROOT;
        monc->num_statfs_requests = 0;
        monc->last_tid = 0;
 
@@ -614,25 +658,22 @@ void ceph_monc_stop(struct ceph_mon_client *monc)
        kfree(monc->monmap);
 }
 
-
 static void handle_auth_reply(struct ceph_mon_client *monc,
                              struct ceph_msg *msg)
 {
        int ret;
 
        mutex_lock(&monc->mutex);
+       monc->pending_auth = 0;
        ret = ceph_handle_auth_reply(monc->auth, msg->front.iov_base,
                                     msg->front.iov_len,
                                     monc->m_auth->front.iov_base,
                                     monc->m_auth->front_max);
        if (ret < 0) {
-               monc->client->mount_err = ret;
-               wake_up(&monc->client->mount_wq);
+               monc->client->auth_err = ret;
+               wake_up(&monc->client->auth_wq);
        } else if (ret > 0) {
-               monc->m_auth->front.iov_len = ret;
-               monc->m_auth->hdr.front_len = cpu_to_le32(ret);
-               ceph_msg_get(monc->m_auth);  /* keep our ref */
-               ceph_con_send(monc->con, monc->m_auth);
+               __send_prepared_auth_request(monc, ret);
        } else if (monc->auth->ops->is_authenticated(monc->auth)) {
                dout("authenticated, starting session\n");
 
@@ -645,6 +686,31 @@ static void handle_auth_reply(struct ceph_mon_client *monc,
        mutex_unlock(&monc->mutex);
 }
 
+static int __validate_auth(struct ceph_mon_client *monc)
+{
+       int ret;
+
+       if (monc->pending_auth)
+               return 0;
+
+       ret = ceph_build_auth(monc->auth, monc->m_auth->front.iov_base,
+                             monc->m_auth->front_max);
+       if (ret <= 0)
+               return ret; /* either an error, or no need to authenticate */
+       __send_prepared_auth_request(monc, ret);
+       return 0;
+}
+
+int ceph_monc_validate_auth(struct ceph_mon_client *monc)
+{
+       int ret;
+
+       mutex_lock(&monc->mutex);
+       ret = __validate_auth(monc);
+       mutex_unlock(&monc->mutex);
+       return ret;
+}
+
 /*
  * handle incoming message
  */
@@ -692,21 +758,38 @@ static void dispatch(struct ceph_connection *con, struct ceph_msg *msg)
  * Allocate memory for incoming message
  */
 static struct ceph_msg *mon_alloc_msg(struct ceph_connection *con,
-                                     struct ceph_msg_header *hdr)
+                                     struct ceph_msg_header *hdr,
+                                     int *skip)
 {
        struct ceph_mon_client *monc = con->private;
        int type = le16_to_cpu(hdr->type);
-       int front = le32_to_cpu(hdr->front_len);
+       int front_len = le32_to_cpu(hdr->front_len);
+       struct ceph_msg *m = NULL;
+
+       *skip = 0;
 
        switch (type) {
        case CEPH_MSG_MON_SUBSCRIBE_ACK:
-               return ceph_msgpool_get(&monc->msgpool_subscribe_ack, front);
+               m = ceph_msgpool_get(&monc->msgpool_subscribe_ack, front_len);
+               break;
        case CEPH_MSG_STATFS_REPLY:
-               return ceph_msgpool_get(&monc->msgpool_statfs_reply, front);
+               m = ceph_msgpool_get(&monc->msgpool_statfs_reply, front_len);
+               break;
        case CEPH_MSG_AUTH_REPLY:
-               return ceph_msgpool_get(&monc->msgpool_auth_reply, front);
+               m = ceph_msgpool_get(&monc->msgpool_auth_reply, front_len);
+               break;
+       case CEPH_MSG_MON_MAP:
+       case CEPH_MSG_MDS_MAP:
+       case CEPH_MSG_OSD_MAP:
+               m = ceph_msg_new(type, front_len, 0, 0, NULL);
+               break;
        }
-       return ceph_alloc_msg(con, hdr);
+
+       if (!m) {
+               pr_info("alloc_msg unknown type %d\n", type);
+               *skip = 1;
+       }
+       return m;
 }
 
 /*
@@ -749,5 +832,4 @@ const static struct ceph_connection_operations mon_con_ops = {
        .dispatch = dispatch,
        .fault = mon_fault,
        .alloc_msg = mon_alloc_msg,
-       .alloc_middle = ceph_alloc_middle,
 };