/*
  * build the snap context for a given realm.
  */
-static int build_snap_context(struct ceph_snap_realm *realm)
+static int build_snap_context(struct ceph_snap_realm *realm,
+                             struct list_head* dirty_realms)
 {
        struct ceph_snap_realm *parent = realm->parent;
        struct ceph_snap_context *snapc;
         */
        if (parent) {
                if (!parent->cached_context) {
-                       err = build_snap_context(parent);
+                       err = build_snap_context(parent, dirty_realms);
                        if (err)
                                goto fail;
                }
                     " (unchanged)\n",
                     realm->ino, realm, realm->cached_context,
                     realm->cached_context->seq,
-                    (unsigned int) realm->cached_context->num_snaps);
+                    (unsigned int)realm->cached_context->num_snaps);
                return 0;
        }
 
             realm->ino, realm, snapc, snapc->seq,
             (unsigned int) snapc->num_snaps);
 
-       ceph_put_snap_context(realm->cached_context);
+       if (realm->cached_context) {
+               ceph_put_snap_context(realm->cached_context);
+               /* queue realm for cap_snap creation */
+               list_add_tail(&realm->dirty_item, dirty_realms);
+       }
        realm->cached_context = snapc;
        return 0;
 
 /*
  * rebuild snap context for the given realm and all of its children.
  */
-static void rebuild_snap_realms(struct ceph_snap_realm *realm)
+static void rebuild_snap_realms(struct ceph_snap_realm *realm,
+                               struct list_head *dirty_realms)
 {
        struct ceph_snap_realm *child;
 
        dout("rebuild_snap_realms %llx %p\n", realm->ino, realm);
-       build_snap_context(realm);
+       build_snap_context(realm, dirty_realms);
 
        list_for_each_entry(child, &realm->children, child_item)
-               rebuild_snap_realms(child);
+               rebuild_snap_realms(child, dirty_realms);
 }
 
 
 {
        struct ceph_inode_info *ci;
        struct inode *lastinode = NULL;
-       struct ceph_snap_realm *child;
 
        dout("queue_realm_cap_snaps %p %llx inodes\n", realm, realm->ino);
 
        spin_lock(&realm->inodes_with_caps_lock);
-       list_for_each_entry(ci, &realm->inodes_with_caps,
-                           i_snap_realm_item) {
+       list_for_each_entry(ci, &realm->inodes_with_caps, i_snap_realm_item) {
                struct inode *inode = igrab(&ci->vfs_inode);
                if (!inode)
                        continue;
        spin_unlock(&realm->inodes_with_caps_lock);
        iput(lastinode);
 
-       list_for_each_entry(child, &realm->children, child_item) {
-               dout("queue_realm_cap_snaps %p %llx queue child %p %llx\n",
-                    realm, realm->ino, child, child->ino);
-               list_del_init(&child->dirty_item);
-               list_add(&child->dirty_item, &realm->dirty_item);
-       }
-
-       list_del_init(&realm->dirty_item);
        dout("queue_realm_cap_snaps %p %llx done\n", realm, realm->ino);
 }
 
                if (err < 0)
                        goto fail;
 
-               /* queue realm for cap_snap creation */
-               list_add(&realm->dirty_item, &dirty_realms);
                if (realm->seq > mdsc->last_snap_seq)
                        mdsc->last_snap_seq = realm->seq;
 
 
        /* invalidate when we reach the _end_ (root) of the trace */
        if (invalidate && p >= e)
-               rebuild_snap_realms(realm);
+               rebuild_snap_realms(realm, &dirty_realms);
 
        if (!first_realm)
                first_realm = realm;
        while (!list_empty(&dirty_realms)) {
                realm = list_first_entry(&dirty_realms, struct ceph_snap_realm,
                                         dirty_item);
+               list_del_init(&realm->dirty_item);
                queue_realm_cap_snaps(realm);
        }