include cleanup: Update gfp.h and slab.h includes to prepare for breaking implicit...
[safe/jmp/linux-2.6] / fs / ceph / snap.c
index dcf18d9..e6f9bc5 100644 (file)
@@ -1,7 +1,7 @@
 #include "ceph_debug.h"
 
-#include <linux/radix-tree.h>
 #include <linux/sort.h>
+#include <linux/slab.h>
 
 #include "super.h"
 #include "decode.h"
@@ -77,6 +77,28 @@ void ceph_get_snap_realm(struct ceph_mds_client *mdsc,
        atomic_inc(&realm->nref);
 }
 
+static void __insert_snap_realm(struct rb_root *root,
+                               struct ceph_snap_realm *new)
+{
+       struct rb_node **p = &root->rb_node;
+       struct rb_node *parent = NULL;
+       struct ceph_snap_realm *r = NULL;
+
+       while (*p) {
+               parent = *p;
+               r = rb_entry(parent, struct ceph_snap_realm, node);
+               if (new->ino < r->ino)
+                       p = &(*p)->rb_left;
+               else if (new->ino > r->ino)
+                       p = &(*p)->rb_right;
+               else
+                       BUG();
+       }
+
+       rb_link_node(&new->node, parent, p);
+       rb_insert_color(&new->node, root);
+}
+
 /*
  * create and get the realm rooted at @ino and bump its ref count.
  *
@@ -92,8 +114,6 @@ static struct ceph_snap_realm *ceph_create_snap_realm(
        if (!realm)
                return ERR_PTR(-ENOMEM);
 
-       radix_tree_insert(&mdsc->snap_realms, ino, realm);
-
        atomic_set(&realm->nref, 0);    /* tree does not take a ref */
        realm->ino = ino;
        INIT_LIST_HEAD(&realm->children);
@@ -101,24 +121,34 @@ static struct ceph_snap_realm *ceph_create_snap_realm(
        INIT_LIST_HEAD(&realm->empty_item);
        INIT_LIST_HEAD(&realm->inodes_with_caps);
        spin_lock_init(&realm->inodes_with_caps_lock);
+       __insert_snap_realm(&mdsc->snap_realms, realm);
        dout("create_snap_realm %llx %p\n", realm->ino, realm);
        return realm;
 }
 
 /*
- * find and get (if found) the realm rooted at @ino and bump its ref count.
+ * lookup the realm rooted at @ino.
  *
  * caller must hold snap_rwsem for write.
  */
 struct ceph_snap_realm *ceph_lookup_snap_realm(struct ceph_mds_client *mdsc,
                                               u64 ino)
 {
-       struct ceph_snap_realm *realm;
-
-       realm = radix_tree_lookup(&mdsc->snap_realms, ino);
-       if (realm)
-               dout("lookup_snap_realm %llx %p\n", realm->ino, realm);
-       return realm;
+       struct rb_node *n = mdsc->snap_realms.rb_node;
+       struct ceph_snap_realm *r;
+
+       while (n) {
+               r = rb_entry(n, struct ceph_snap_realm, node);
+               if (ino < r->ino)
+                       n = n->rb_left;
+               else if (ino > r->ino)
+                       n = n->rb_right;
+               else {
+                       dout("lookup_snap_realm %llx %p\n", r->ino, r);
+                       return r;
+               }
+       }
+       return NULL;
 }
 
 static void __put_snap_realm(struct ceph_mds_client *mdsc,
@@ -132,7 +162,7 @@ static void __destroy_snap_realm(struct ceph_mds_client *mdsc,
 {
        dout("__destroy_snap_realm %p %llx\n", realm, realm->ino);
 
-       radix_tree_delete(&mdsc->snap_realms, realm->ino);
+       rb_erase(&realm->node, &mdsc->snap_realms);
 
        if (realm->parent) {
                list_del_init(&realm->child_item);
@@ -285,9 +315,9 @@ static int build_snap_context(struct ceph_snap_realm *realm)
           because we rebuild_snap_realms() works _downward_ in
           hierarchy after each update.) */
        if (realm->cached_context &&
-           realm->cached_context->seq <= realm->seq &&
+           realm->cached_context->seq == realm->seq &&
            (!parent ||
-            realm->cached_context->seq <= parent->cached_context->seq)) {
+            realm->cached_context->seq >= parent->cached_context->seq)) {
                dout("build_snap_context %llx %p: %p seq %lld (%d snaps)"
                     " (unchanged)\n",
                     realm->ino, realm, realm->cached_context,
@@ -684,11 +714,11 @@ static void flush_snaps(struct ceph_mds_client *mdsc)
  * directory into another realm.
  */
 void ceph_handle_snap(struct ceph_mds_client *mdsc,
+                     struct ceph_mds_session *session,
                      struct ceph_msg *msg)
 {
        struct super_block *sb = mdsc->client->sb;
-       struct ceph_mds_session *session;
-       int mds;
+       int mds = session->s_mds;
        u64 split;
        int op;
        int trace_len;
@@ -701,10 +731,6 @@ void ceph_handle_snap(struct ceph_mds_client *mdsc,
        int i;
        int locked_rwsem = 0;
 
-       if (msg->hdr.src.name.type != CEPH_ENTITY_TYPE_MDS)
-               return;
-       mds = le64_to_cpu(msg->hdr.src.name.num);
-
        /* decode */
        if (msg->front.iov_len < sizeof(*h))
                goto bad;
@@ -720,15 +746,6 @@ void ceph_handle_snap(struct ceph_mds_client *mdsc,
        dout("handle_snap from mds%d op %s split %llx tracelen %d\n", mds,
             ceph_snap_op_name(op), split, trace_len);
 
-       /* find session */
-       mutex_lock(&mdsc->mutex);
-       session = __ceph_lookup_mds_session(mdsc, mds);
-       mutex_unlock(&mdsc->mutex);
-       if (!session) {
-               dout("WTF, got snap but no session for mds%d\n", mds);
-               return;
-       }
-
        mutex_lock(&session->s_mutex);
        session->s_seq++;
        mutex_unlock(&session->s_mutex);
@@ -802,7 +819,9 @@ void ceph_handle_snap(struct ceph_mds_client *mdsc,
                         * queued (again) by ceph_update_snap_trace()
                         * below.  Queue it _now_, under the old context.
                         */
+                       spin_lock(&realm->inodes_with_caps_lock);
                        list_del_init(&ci->i_snap_realm_item);
+                       spin_unlock(&realm->inodes_with_caps_lock);
                        spin_unlock(&inode->i_lock);
 
                        ceph_queue_cap_snap(ci,