]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
kclient: do sync writepages if FILE_WRBUFFER is being revoked
authorSage Weil <sage@newdream.net>
Fri, 23 Jan 2009 22:50:13 +0000 (14:50 -0800)
committerSage Weil <sage@newdream.net>
Fri, 23 Jan 2009 22:50:13 +0000 (14:50 -0800)
This doesn't capture the case where we already started writeout
and _then_ the MDS tries to revoke, but that's probably not worth
the complexity.

src/kernel/addr.c
src/kernel/caps.c
src/kernel/super.h

index eeb3cbf07d5d9fba69f0ebc102405cb78f8cd8cf..5eb529b72e9314b938865d85f212e4db9a023fbc 100644 (file)
@@ -545,6 +545,9 @@ static int ceph_writepages_start(struct address_space *mapping,
        struct ceph_osd_request *req = NULL;
        int do_sync = atomic_read(&ci->i_want_sync_writeout);
 
+       if (ceph_caps_revoking(ci) & CEPH_CAP_FILE_WRBUFFER)
+               do_sync = 1;
+
        client = ceph_inode_to_client(inode);
        if (client->mount_state == CEPH_MOUNT_SHUTDOWN) {
                dout(1, "writepage on forced umount\n");
index da1ae54dcb91229f98cf4952499414d3b6d04387..e277b091aac4b010b1a57c5815d2748ede29207f 100644 (file)
@@ -276,6 +276,38 @@ retry:
        return 0;
 }
 
+/*
+ * Return true if cap has not timed out and belongs to the current
+ * generation of the MDS session.
+ */
+static int __cap_is_valid(struct ceph_cap *cap)
+{
+       unsigned long ttl;
+       u32 gen;
+
+       spin_lock(&cap->session->s_cap_lock);
+       gen = cap->session->s_cap_gen;
+       ttl = cap->session->s_cap_ttl;
+       spin_unlock(&cap->session->s_cap_lock);
+
+       if (cap->gen < gen || time_after_eq(jiffies, ttl)) {
+               dout(30, "__cap_is_valid %p cap %p issued %s "
+                    "but STALE (gen %u vs %u)\n", &cap->ci->vfs_inode,
+                    cap, ceph_cap_string(cap->issued), cap->gen, gen);
+               return 0;
+       }
+
+       if (time_after_eq(jiffies, cap->expires) &&
+           (cap->issued & ~CEPH_CAP_EXPIREABLE) == 0) {
+               dout(30, "__cap_is_valid %p cap %p issued %s "
+                    "but readonly and expired\n", &cap->ci->vfs_inode,
+                    cap, ceph_cap_string(cap->issued));
+               return 0;
+       }
+
+       return 1;
+}
+
 /*
  * Return set of valid cap bits issued to us.  Note that caps time
  * out, and may be invalidated in bulk if the client session times out
@@ -285,35 +317,14 @@ int __ceph_caps_issued(struct ceph_inode_info *ci, int *implemented)
 {
        int have = ci->i_snap_caps;
        struct ceph_cap *cap;
-       u32 gen;
-       unsigned long ttl;
        struct rb_node *p;
 
        if (implemented)
                *implemented = 0;
        for (p = rb_first(&ci->i_caps); p; p = rb_next(p)) {
                cap = rb_entry(p, struct ceph_cap, ci_node);
-
-               spin_lock(&cap->session->s_cap_lock);
-               gen = cap->session->s_cap_gen;
-               ttl = cap->session->s_cap_ttl;
-               spin_unlock(&cap->session->s_cap_lock);
-
-               if (cap->gen < gen || time_after_eq(jiffies, ttl)) {
-                       dout(30, "__ceph_caps_issued %p cap %p issued %s "
-                            "but STALE (gen %u vs %u)\n", &ci->vfs_inode,
-                            cap, ceph_cap_string(cap->issued), cap->gen, gen);
-                       continue;
-               }
-
-               if (time_after_eq(jiffies, cap->expires) &&
-                   (cap->issued & ~CEPH_CAP_EXPIREABLE) == 0) {
-                       dout(30, "__ceph_caps_issued %p cap %p issued %s "
-                            "but readonly and expired\n", &ci->vfs_inode,
-                            cap, ceph_cap_string(cap->issued));
+               if (!__cap_is_valid(cap))
                        continue;
-               }
-
                dout(30, "__ceph_caps_issued %p cap %p issued %s\n",
                     &ci->vfs_inode, cap, ceph_cap_string(cap->issued));
                have |= cap->issued;
@@ -336,6 +347,8 @@ int __ceph_caps_dirty(struct ceph_inode_info *ci)
 
        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;
                dout(30, "__ceph_caps_dirty %p cap %p flushing %s\n",
                     inode, cap, ceph_cap_string(cap->flushing));
                dirty |= cap->flushing;
@@ -345,6 +358,28 @@ int __ceph_caps_dirty(struct ceph_inode_info *ci)
        return dirty;
 }
 
+/*
+ * Return mask of caps currently being revoked by an MDS.
+ */
+int ceph_caps_revoking(struct ceph_inode_info *ci)
+{
+       struct inode *inode = &ci->vfs_inode;
+       struct ceph_cap *cap;
+       struct rb_node *p;
+       int revoking = 0;
+
+       spin_lock(&inode->i_lock);
+       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))
+                       revoking |= cap->implemented & ~cap->issued;
+       }
+       spin_unlock(&inode->i_lock);
+       dout(30, "ceph_caps_revoking %p revoking %s\n", inode,
+            ceph_cap_string(revoking));
+       return revoking;
+}
+
 /*
  * called under i_lock
  */
index b6087e99cc08886429484e86a5450b0570081f56..79946318c78a7ba0b77003f117f88a1a3783acdd 100644 (file)
@@ -435,6 +435,7 @@ static inline int ceph_caps_issued(struct ceph_inode_info *ci)
 }
 
 extern int __ceph_caps_dirty(struct ceph_inode_info *ci);
+extern int ceph_caps_revoking(struct ceph_inode_info *ci);
 
 static inline int __ceph_caps_used(struct ceph_inode_info *ci)
 {