ceph: fix infinite loop in get_quota_realm()
authorYan, Zheng <zyan@redhat.com>
Fri, 31 May 2019 12:19:18 +0000 (20:19 +0800)
committerIlya Dryomov <idryomov@gmail.com>
Mon, 8 Jul 2019 12:01:42 +0000 (14:01 +0200)
get_quota_realm() enters infinite loop if quota inode has no caps.
This can happen after client gets evicted.

Signed-off-by: "Yan, Zheng" <zyan@redhat.com>
Reviewed-by: Luis Henriques <lhenriques@suse.com>
Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
fs/ceph/quota.c

index d629fc857450afcd54a71b72b5275419adb740f0..de56dee60540bae9aad7bf45c995a529d43dfd0b 100644 (file)
@@ -135,7 +135,7 @@ static struct inode *lookup_quotarealm_inode(struct ceph_mds_client *mdsc,
                return NULL;
 
        mutex_lock(&qri->mutex);
-       if (qri->inode) {
+       if (qri->inode && ceph_is_any_caps(qri->inode)) {
                /* A request has already returned the inode */
                mutex_unlock(&qri->mutex);
                return qri->inode;
@@ -146,7 +146,18 @@ static struct inode *lookup_quotarealm_inode(struct ceph_mds_client *mdsc,
                mutex_unlock(&qri->mutex);
                return NULL;
        }
-       in = ceph_lookup_inode(sb, realm->ino);
+       if (qri->inode) {
+               /* get caps */
+               int ret = __ceph_do_getattr(qri->inode, NULL,
+                                           CEPH_STAT_CAP_INODE, true);
+               if (ret >= 0)
+                       in = qri->inode;
+               else
+                       in = ERR_PTR(ret);
+       }  else {
+               in = ceph_lookup_inode(sb, realm->ino);
+       }
+
        if (IS_ERR(in)) {
                pr_warn("Can't lookup inode %llx (err: %ld)\n",
                        realm->ino, PTR_ERR(in));