]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
kclient: renew old rdcaps when we use them
authorSage Weil <sage@newdream.net>
Tue, 17 Mar 2009 23:47:40 +0000 (16:47 -0700)
committerSage Weil <sage@newdream.net>
Wed, 18 Mar 2009 17:45:56 +0000 (10:45 -0700)
src/kernel/caps.c
src/kernel/dir.c
src/kernel/inode.c
src/kernel/super.h

index 0d626b7136ec8361337947c7b8d171ce3d0a8828..7a6680ff69fa51f4dcddf47901fc6199f1c42490 100644 (file)
@@ -186,13 +186,13 @@ static void __adjust_cap_rdcaps_listing(struct ceph_inode_info *ci,
                if (!list_empty(&cap->session_rdcaps))
                        list_del_init(&cap->session_rdcaps);
                else
-                       dout(20, "adjust_cap_rdcaps_listing %p added %p\n",
-                            &ci->vfs_inode, cap);
+                       dout(20, "adjust_cap_rdcaps_listing %p added %p %s\n",
+                            &ci->vfs_inode, cap, ceph_cap_string(caps));
                list_add_tail(&cap->session_rdcaps, &cap->session->s_rdcaps);
        } else {
                if (!list_empty(&cap->session_rdcaps)) {
-                       dout(20, "adjust_cap_rdcaps_listing %p removed %p\n",
-                            &ci->vfs_inode, cap);
+                       dout(20, "adjust_cap_rdcaps_listing %p removed %p %s\n",
+                            &ci->vfs_inode, cap, ceph_cap_string(caps));
                        list_del_init(&cap->session_rdcaps);
                }
        }
@@ -221,6 +221,7 @@ int ceph_add_cap(struct inode *inode,
        struct ceph_cap *cap;
        int mds = session->s_mds;
        int is_first = 0;
+       unsigned long duration;
 
        dout(10, "add_cap %p mds%d cap %llx %s seq %d\n", inode,
             session->s_mds, cap_id, ceph_cap_string(issued), seq);
@@ -308,7 +309,13 @@ retry:
        cap->seq = seq;
        cap->mseq = mseq;
        cap->gen = session->s_cap_gen;
-       cap->expires = ttl_from + (ttl_ms * HZ / 1000);
+
+       duration = ttl_ms * HZ / 1000;
+       cap->expires = ttl_from + duration;
+       cap->renew_after = ttl_from + (duration >> 1);
+       dout(30, " expires %lu, renew_after %lu (duration %lu, %u ms)\n",
+            cap->expires, cap->renew_after, duration, ttl_ms);
+
        if (fmode >= 0)
                __ceph_get_fmode(ci, fmode);
        spin_unlock(&inode->i_lock);
@@ -995,6 +1002,54 @@ ack:
                up_read(&mdsc->snap_rwsem);
 }
 
+/*
+ * Check for cap mask.  If held via rdcaps, consider renewing.
+ *
+ * Called under i_lock.
+ */
+int __ceph_check_cap_maybe_renew(struct ceph_inode_info *ci, int mask)
+       __releases(ci->vfs_inode->i_lock)
+{
+       struct inode *inode = &ci->vfs_inode;
+       struct ceph_cap *cap;
+       struct rb_node *p;
+       int valid = 0;
+
+       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) || (cap->issued & mask) == 0)
+                       continue;
+               valid = 1;
+
+               if (list_empty(&cap->session_rdcaps)) {
+                       dout(30, "check_cap_maybe_renew %p %p %s has %s\n",
+                            inode, cap, ceph_cap_string(cap->issued),
+                            ceph_cap_string(mask));
+                       break;  /* not an rdcap, it doesn't expire */
+               }
+
+               /* should we renew the rdcap? */
+               if (cap->renew_after &&
+                   time_after(jiffies, cap->renew_after)) {
+                       dout(30, "check_cap_maybe_renew %p %p renewing"
+                            " (%lu <= %lu)\n", inode, cap,
+                            cap->renew_after, jiffies);
+                       cap->renew_after = 0;
+                       __send_cap(&ceph_client(inode->i_sb)->mdsc, cap,
+                                  CEPH_CAP_OP_RENEW, 0, 0, cap->issued);
+                       goto out;
+               }
+               dout(30, "check_cap_maybe_renew %p %p renew at %lu > %lu\n",
+                    inode, cap, cap->renew_after, jiffies);
+               break;
+       }       
+
+       spin_unlock(&inode->i_lock);
+out:
+       return valid;
+}
+
 /*
  * Take references to capabilities we hold, so that we don't release
  * them to the MDS prematurely.
index 42870dd9098d7a5bccc88d7504fa7fd9ea8adad3..445d824be81c5c6494de8644d910a1537254ed8e 100644 (file)
@@ -659,11 +659,10 @@ static int dir_lease_is_valid(struct inode *dir, struct dentry *dentry)
 
        spin_lock(&dir->i_lock);
        if (ceph_ino(dir) != CEPH_INO_ROOT &&
-           ci->i_version == dentry->d_time &&
-           (__ceph_caps_issued(ci, NULL) & CEPH_CAP_FILE_RDCACHE)) {
-               valid = 1;
-       }
-       spin_unlock(&dir->i_lock);
+           ci->i_version == dentry->d_time)
+               valid = __ceph_check_cap_maybe_renew(ci, CEPH_CAP_FILE_RDCACHE);
+       else
+               spin_unlock(&dir->i_lock);
        dout(20, "dir_lease_is_valid dir %p v%llu dentry %p v%lu = %d\n",
             dir, ci->i_version, dentry, dentry->d_time, valid);
        return valid;
index 5371f853d1da8f0eb8db9b528c35215d1f4b8c86..5ee469c93dfb50e2c5920111db20bcf16c6af52d 100644 (file)
@@ -1687,7 +1687,7 @@ int ceph_do_getattr(struct dentry *dentry, int mask)
 
        req = ceph_mdsc_create_request(mdsc, CEPH_MDS_OP_LSTAT,
                                       dentry, NULL, NULL, NULL,
-                                      USE_CAP_MDS);
+                                      USE_ANY_MDS);
        if (IS_ERR(req))
                return PTR_ERR(req);
        req->r_args.stat.mask = cpu_to_le32(mask);
index e6baf6cfb11054a0ff90f7bdb87a685107e37f1f..d4c9f2a15560f739e2fd3cadcd2231122583750e 100644 (file)
@@ -149,6 +149,7 @@ struct ceph_cap {
        int mds_wanted;
        u32 seq, mseq, gen;
        unsigned long expires;  /* if readonly and unwanted (jiffies) */
+       unsigned long renew_after;  /* if readonly and unwanted (jiffies) */
 };
 
 /*
@@ -732,6 +733,8 @@ extern void __ceph_flush_snaps(struct ceph_inode_info *ci,
 extern void ceph_check_caps(struct ceph_inode_info *ci, int delayed, int drop,
                            struct ceph_mds_session *session);
 extern void ceph_check_delayed_caps(struct ceph_mds_client *mdsc);
+extern int __ceph_check_cap_maybe_renew(struct ceph_inode_info *ci, int mask);
+
 void ceph_trim_session_rdcaps(struct ceph_mds_session *session);
 
 static inline void ceph_release_caps(struct inode *inode, int mask)