]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
kclient: queue inode for cap check if mds_wanted mismatch
authorSage Weil <sage@newdream.net>
Fri, 3 Apr 2009 22:45:59 +0000 (15:45 -0700)
committerSage Weil <sage@newdream.net>
Fri, 3 Apr 2009 22:46:11 +0000 (15:46 -0700)
If mds_wanted in add_cap is more than we actually want (for
example, on a getattr that races with a cap wanted release),
requeue a cap check.  We don't want to release immediately if we
can help it because something like readdir would prematurely (?)
release caps we're holding on to for good measure...

src/TODO
src/kernel/caps.c

index 579d6c5b3902e8232790a946774763aa1d4ba982..5aa5f37e6ce3670125cff34f8806c0651ada2ab6 100644 (file)
--- a/src/TODO
+++ b/src/TODO
@@ -50,6 +50,11 @@ kclient caps
 /- revisit unmount
 /- make request paths relative to a non-snapshotted inode.
 /- fix nfs exporting
+- fix mds_wanted tracking
+  - racing lookup + open           - do not reduce wanted on mds
+  - wanted expansion on ceph_open  - do no lose it on mds, even if racing with lookup + open
+  - racing wanted release + getattr --- we need to keep the client's notion of mds_wanted accurate!  ****
+
 
 - ENOSPC
 - flock
index f6b5b4cbb77888f455ee01b16fcec76f6122bbe8..9f8006186b45e417ce14057f66db90c24c3e8def 100644 (file)
@@ -391,9 +391,10 @@ int ceph_add_cap(struct inode *inode,
 {
        struct ceph_mds_client *mdsc = &ceph_inode_to_client(inode)->mdsc;
        struct ceph_inode_info *ci = ceph_inode(inode);
+       struct ceph_cap *new_cap = NULL;
        struct ceph_cap *cap;
        int mds = session->s_mds;
-       struct ceph_cap *new_cap = NULL;
+       int actual_wanted;
 
        dout(10, "add_cap %p mds%d cap %llx %s seq %d\n", inode,
             session->s_mds, cap_id, ceph_cap_string(issued), seq);
@@ -471,6 +472,17 @@ retry:
                ci->i_ceph_flags &= ~CEPH_I_COMPLETE;
        }
 
+       /*
+        * If we are issued caps we don't want, queue a check so we'll
+        * update the mds wanted value.
+        */
+       actual_wanted = __ceph_caps_wanted(ci);
+       if (wanted & ~actual_wanted) {
+               dout(10, " mds wanted %s, actual wanted %s, queueing\n",
+                    ceph_cap_string(wanted), ceph_cap_string(actual_wanted));
+               __cap_delay_requeue(mdsc, ci);
+       }
+
        if (flags & CEPH_CAP_FLAG_AUTH)
                ci->i_auth_cap = cap;
        else if (ci->i_auth_cap == cap)