]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
ceph: don't skip updating wanted caps when cap is stale
authorYan, Zheng <zyan@redhat.com>
Tue, 10 Mar 2020 11:34:20 +0000 (19:34 +0800)
committerIlya Dryomov <idryomov@gmail.com>
Mon, 30 Mar 2020 10:42:43 +0000 (12:42 +0200)
1. try_get_cap_refs() fails to get caps and finds that mds_wanted
   does not include what it wants. It returns -ESTALE.
2. ceph_get_caps() calls ceph_renew_caps(). ceph_renew_caps() finds
   that inode has cap, so it calls ceph_check_caps().
3. ceph_check_caps() finds that issued caps (without checking if it's
   stale) already includes caps wanted by open file, so it skips
   updating wanted caps.

Above events can cause an infinite loop inside ceph_get_caps().

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

index 086bb3adc08a00152c73b301cbe296bfbce64d88..be1ae4b92cfd318e94f2ee8291a14f8c8223687c 100644 (file)
@@ -2008,8 +2008,12 @@ retry_locked:
                }
 
                /* want more caps from mds? */
-               if (want & ~(cap->mds_wanted | cap->issued))
-                       goto ack;
+               if (want & ~cap->mds_wanted) {
+                       if (want & ~(cap->mds_wanted | cap->issued))
+                               goto ack;
+                       if (!__cap_is_valid(cap))
+                               goto ack;
+               }
 
                /* things we might delay */
                if ((cap->issued & ~retain) == 0)