ceph: introduce global empty snap context
[pandora-kernel.git] / fs / ceph / snap.c
index a559c80..d5df940 100644 (file)
@@ -288,6 +288,9 @@ static int cmpu64_rev(const void *a, const void *b)
        return 0;
 }
 
+
+static struct ceph_snap_context *empty_snapc;
+
 /*
  * build the snap context for a given realm.
  */
@@ -329,9 +332,15 @@ static int build_snap_context(struct ceph_snap_realm *realm)
                return 0;
        }
 
+       if (num == 0 && realm->seq == empty_snapc->seq) {
+               ceph_get_snap_context(empty_snapc);
+               snapc = empty_snapc;
+               goto done;
+       }
+
        /* alloc new snap context */
        err = -ENOMEM;
-       if (num > ULONG_MAX / sizeof(u64) - sizeof(*snapc))
+       if (num > (SIZE_MAX - sizeof(*snapc)) / sizeof(u64))
                goto fail;
        snapc = kzalloc(sizeof(*snapc) + num*sizeof(u64), GFP_NOFS);
        if (!snapc)
@@ -364,6 +373,7 @@ static int build_snap_context(struct ceph_snap_realm *realm)
        dout("build_snap_context %llx %p: %p seq %lld (%d snaps)\n",
             realm->ino, realm, snapc, snapc->seq, snapc->num_snaps);
 
+done:
        if (realm->cached_context)
                ceph_put_snap_context(realm->cached_context);
        realm->cached_context = snapc;
@@ -465,6 +475,9 @@ void ceph_queue_cap_snap(struct ceph_inode_info *ci)
                   cap_snap.  lucky us. */
                dout("queue_cap_snap %p already pending\n", inode);
                kfree(capsnap);
+       } else if (ci->i_snap_realm->cached_context == empty_snapc) {
+               dout("queue_cap_snap %p empty snapc\n", inode);
+               kfree(capsnap);
        } else if (dirty & (CEPH_CAP_AUTH_EXCL|CEPH_CAP_XATTR_EXCL|
                            CEPH_CAP_FILE_EXCL|CEPH_CAP_FILE_WR)) {
                struct ceph_snap_context *snapc = ci->i_head_snapc;
@@ -927,5 +940,17 @@ out:
        return;
 }
 
+int __init ceph_snap_init(void)
+{
+       empty_snapc = kzalloc(sizeof(struct ceph_snap_context), GFP_NOFS);
+       if (!empty_snapc)
+               return -ENOMEM;
+       atomic_set(&empty_snapc->nref, 1);
+       empty_snapc->seq = 1;
+       return 0;
+}
 
-
+void ceph_snap_exit(void)
+{
+       ceph_put_snap_context(empty_snapc);
+}