ceph: skip updating 'wanted' caps if caps are already issued
authorYan, Zheng <zyan@redhat.com>
Thu, 22 Nov 2018 07:26:01 +0000 (15:26 +0800)
committerIlya Dryomov <idryomov@gmail.com>
Wed, 26 Dec 2018 15:08:36 +0000 (16:08 +0100)
When reading cached inode that already has Fscr caps, this can avoid
two cap messages (one updats 'wanted' caps, one clears 'wanted' caps).

Signed-off-by: "Yan, Zheng" <zyan@redhat.com>
Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
fs/ceph/caps.c

index e7af647..92643b8 100644 (file)
@@ -1973,8 +1973,7 @@ retry_locked:
                        goto ack;
 
                /* things we might delay */
-               if ((cap->issued & ~retain) == 0 &&
-                   cap->mds_wanted == want)
+               if ((cap->issued & ~retain) == 0)
                        continue;     /* nope, all good */
 
                if (no_delay)
@@ -3051,7 +3050,8 @@ static void handle_cap_grant(struct inode *inode,
        int used, wanted, dirty;
        u64 size = le64_to_cpu(grant->size);
        u64 max_size = le64_to_cpu(grant->max_size);
-       int check_caps = 0;
+       unsigned char check_caps = 0;
+       bool was_stale = cap->cap_gen < session->s_cap_gen;
        bool wake = false;
        bool writeback = false;
        bool queue_trunc = false;
@@ -3203,13 +3203,20 @@ static void handle_cap_grant(struct inode *inode,
             ceph_cap_string(wanted),
             ceph_cap_string(used),
             ceph_cap_string(dirty));
-       if (wanted != le32_to_cpu(grant->wanted)) {
-               dout("mds wanted %s -> %s\n",
-                    ceph_cap_string(le32_to_cpu(grant->wanted)),
-                    ceph_cap_string(wanted));
-               /* imported cap may not have correct mds_wanted */
-               if (le32_to_cpu(grant->op) == CEPH_CAP_OP_IMPORT)
-                       check_caps = 1;
+
+       if ((was_stale || le32_to_cpu(grant->op) == CEPH_CAP_OP_IMPORT) &&
+           (wanted & ~(cap->mds_wanted | newcaps))) {
+               /*
+                * If mds is importing cap, prior cap messages that update
+                * 'wanted' may get dropped by mds (migrate seq mismatch).
+                *
+                * We don't send cap message to update 'wanted' if what we
+                * want are already issued. If mds revokes caps, cap message
+                * that releases caps also tells mds what we want. But if
+                * caps got revoked by mds forcedly (session stale). We may
+                * haven't told mds what we want.
+                */
+               check_caps = 1;
        }
 
        /* revocation, grant, or no-op? */