]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
kclient: make session cap list an LRU; combine touch with check for issued caps
authorSage Weil <sage@newdream.net>
Fri, 29 May 2009 17:43:31 +0000 (10:43 -0700)
committerSage Weil <sage@newdream.net>
Fri, 29 May 2009 21:30:20 +0000 (14:30 -0700)
This both makes the issued cap check better (only traverses caps until we
get what we want), and combines the touch_cap step to bump it to the front
of the LRU.

So far all callers do the touch, so the touch arg is of dubious value..

src/kernel/caps.c
src/kernel/dir.c
src/kernel/inode.c
src/kernel/super.h

index 7ef9548717047549d15a511b0dbcae1f6b7b6209..53f8faf9338f5b0cc6a4f7613fd60ac1db92d20b 100644 (file)
@@ -605,6 +605,76 @@ int __ceph_caps_issued(struct ceph_inode_info *ci, int *implemented)
        return have;
 }
 
+static void __touch_cap(struct ceph_cap *cap)
+{
+       struct ceph_mds_session *s = cap->session;
+
+       dout(20, "__touch_cap %p cap %p mds%d\n", &cap->ci->vfs_inode, cap,
+            s->s_mds);
+       spin_lock(&s->s_cap_lock);
+       list_move_tail(&cap->session_caps, &s->s_caps);
+       spin_unlock(&s->s_cap_lock);
+}
+
+/*
+ * Return true if we hold the given mask.  And move the cap(s) to the front
+ * of their respective LRUs.
+ */
+int __ceph_caps_issued_mask(struct ceph_inode_info *ci, int mask, int touch)
+{
+       struct ceph_cap *cap;
+       struct rb_node *p;
+       int have = ci->i_snap_caps;
+
+       if ((have & mask) == mask) {
+               dout(30, "__ceph_caps_issued_mask %p snap issued %s"
+                    " (mask %s)\n", &ci->vfs_inode,
+                    ceph_cap_string(have),
+                    ceph_cap_string(mask));
+               return 1;
+       }
+
+       for (p = rb_first(&ci->i_caps); p; p = rb_next(p)) {
+               cap = rb_entry(p, struct ceph_cap, ci_node);
+               if (!__cap_is_valid(cap))
+                       continue;
+               if ((cap->issued & mask) == mask) {
+                       dout(30, "__ceph_caps_issued_mask %p cap %p issued %s"
+                            " (mask %s)\n", &ci->vfs_inode, cap,
+                            ceph_cap_string(cap->issued),
+                            ceph_cap_string(mask));
+                       if (touch)
+                               __touch_cap(cap);
+                       return 1;
+               }
+
+               /* does a combination of caps satisfy mask? */
+               have |= cap->issued;
+               if ((have & mask) == mask) {
+                       dout(30, "__ceph_caps_issued_mask %p combo issued %s"
+                            " (mask %s)\n", &ci->vfs_inode,
+                            ceph_cap_string(cap->issued),
+                            ceph_cap_string(mask));
+                       if (touch) {
+                               struct rb_node *q;
+
+                               __touch_cap(cap);
+                               for (q = rb_first(&ci->i_caps); q != p;
+                                    q = rb_next(q)) {
+                                       cap = rb_entry(q, struct ceph_cap,
+                                                      ci_node);
+                                       if (!__cap_is_valid(cap))
+                                               continue;
+                                       __touch_cap(cap);
+                               }                               
+                       }
+                       return 1;
+               }
+       }
+
+       return 0;
+}
+
 /*
  * Return mask of caps currently being revoked by an MDS.
  */
index 8ec44a882b292898e4dc8e597b78082da9a04dc3..0c472e7ad39e3befc4861cc6791b91c5a9eae35d 100644 (file)
@@ -190,7 +190,7 @@ static int ceph_readdir(struct file *filp, void *dirent, filldir_t filldir)
        if ((filp->f_pos == 2 || fi->dentry) &&
            !ceph_test_opt(client, NOASYNCREADDIR) &&
            (ci->i_ceph_flags & CEPH_I_COMPLETE) &&
-           (__ceph_caps_issued(ci, NULL) & CEPH_CAP_FILE_SHARED)) {
+           __ceph_caps_issued_mask(ci, CEPH_CAP_FILE_SHARED, 1)) {
                err = __dcache_readdir(filp, dirent, filldir);
                if (err != -EAGAIN) {
                        spin_unlock(&inode->i_lock);
@@ -465,7 +465,7 @@ static struct dentry *ceph_lookup(struct inode *dir, struct dentry *dentry,
                            client->mount_args.snapdir_name,
                            dentry->d_name.len) &&
                    (ci->i_ceph_flags & CEPH_I_COMPLETE) &&
-                   (__ceph_caps_issued(ci, NULL) & CEPH_CAP_FILE_SHARED)) {
+                   (__ceph_caps_issued_mask(ci, CEPH_CAP_FILE_SHARED, 1))) {
                        di->offset = ci->i_max_offset++;
                        spin_unlock(&dir->i_lock);
                        dout(10, " dir %p complete, -ENOENT\n", dir);
@@ -846,7 +846,7 @@ static int dir_lease_is_valid(struct inode *dir, struct dentry *dentry)
 
        spin_lock(&dir->i_lock);
        if (ci->i_rdcache_gen == di->lease_rdcache_gen)
-               valid = __ceph_caps_issued(ci, NULL) & CEPH_CAP_FILE_SHARED;
+               valid = __ceph_caps_issued_mask(ci, CEPH_CAP_FILE_SHARED, 1);
        spin_unlock(&dir->i_lock);
        dout(20, "dir_lease_is_valid dir %p v%u dentry %p v%u = %d\n",
             dir, (unsigned)ci->i_rdcache_gen, dentry,
index debeadb404647569b1194431730cff8168bb0fe1..92f226fb8729fdb25ddf9fd2b04e6e63e4a170e7 100644 (file)
@@ -1493,7 +1493,7 @@ int ceph_do_getattr(struct inode *inode, int mask)
        }
 
        dout(30, "do_getattr inode %p mask %s\n", inode, ceph_cap_string(mask));
-       if (ceph_caps_issued_mask(ceph_inode(inode), mask))
+       if (ceph_caps_issued_mask(ceph_inode(inode), mask, 1))
                return 0;
 
        req = ceph_mdsc_create_request(mdsc, CEPH_MDS_OP_GETATTR, USE_ANY_MDS);
@@ -1992,7 +1992,6 @@ ssize_t ceph_getxattr(struct dentry *dentry, const char *name, void *value,
        int err;
        struct _ceph_vir_xattr_cb *vir_xattr;
        struct ceph_inode_xattr *xattr;
-       int issued;
 
        /* let's see if a virtual xattr was requested */
        vir_xattr = _ceph_match_vir_xattr(name);
@@ -2000,12 +1999,10 @@ ssize_t ceph_getxattr(struct dentry *dentry, const char *name, void *value,
                return (vir_xattr->getxattr_cb)(ci, value, size);
 
        spin_lock(&inode->i_lock);
-       issued = __ceph_caps_issued(ci, NULL);
-       dout(10, "getxattr %p issued %s ver=%lld index_ver=%lld\n", inode,
-                       ceph_cap_string(issued),
-                       ci->i_xattrs.version, ci->i_xattrs.index_version);
+       dout(10, "getxattr %p ver=%lld index_ver=%lld\n", inode,
+            ci->i_xattrs.version, ci->i_xattrs.index_version);
 
-       if ((issued & CEPH_CAP_XATTR_SHARED) &&
+       if (__ceph_caps_issued_mask(ci, CEPH_CAP_XATTR_SHARED, 1) &&
            (ci->i_xattrs.index_version >= ci->i_xattrs.version)) {
                goto get_xattr;
        } else {
@@ -2054,15 +2051,12 @@ ssize_t ceph_listxattr(struct dentry *dentry, char *names, size_t size)
        int err;
        u32 len;
        int i;
-       int issued;
 
        spin_lock(&inode->i_lock);
-       issued = __ceph_caps_issued(ci, NULL);
-       dout(10, "listxattr %p issued %s ver=%lld index_ver=%lld\n", inode,
-                       ceph_cap_string(issued),
-                       ci->i_xattrs.version, ci->i_xattrs.index_version);
+       dout(10, "listxattr %p ver=%lld index_ver=%lld\n", inode,
+            ci->i_xattrs.version, ci->i_xattrs.index_version);
 
-       if ((issued & CEPH_CAP_XATTR_SHARED) &&
+       if (__ceph_caps_issued_mask(ci, CEPH_CAP_XATTR_SHARED, 1) &&
            (ci->i_xattrs.index_version > ci->i_xattrs.version)) {
                goto list_xattr;
        } else {
@@ -2328,6 +2322,5 @@ do_sync:
        spin_unlock(&inode->i_lock);
        err = ceph_send_removexattr(dentry, name);
        return err;
-
 }
 
index 85ee7697bf1ae66166d9b3a4ef5e7475860db9c4..4c30fade0b1dfba62feefd1625bdc5414d2b6e18 100644 (file)
@@ -505,6 +505,7 @@ static inline bool __ceph_is_any_real_caps(struct ceph_inode_info *ci)
 }
 
 extern int __ceph_caps_issued(struct ceph_inode_info *ci, int *implemented);
+extern int __ceph_caps_issued_mask(struct ceph_inode_info *ci, int mask, int t);
 
 static inline int ceph_caps_issued(struct ceph_inode_info *ci)
 {
@@ -515,9 +516,14 @@ static inline int ceph_caps_issued(struct ceph_inode_info *ci)
        return issued;
 }
 
-static inline int ceph_caps_issued_mask(struct ceph_inode_info *ci, int mask)
+static inline int ceph_caps_issued_mask(struct ceph_inode_info *ci, int mask,
+                                       int touch)
 {
-       return (ceph_caps_issued(ci) & mask) == mask;
+       int r;
+       spin_lock(&ci->vfs_inode.i_lock);
+       r = __ceph_caps_issued_mask(ci, mask, touch);
+       spin_unlock(&ci->vfs_inode.i_lock);
+       return r;
 }
 
 static inline int __ceph_caps_dirty(struct ceph_inode_info *ci)