ceph: fix infinite loop in get_quota_realm()

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>
This commit is contained in:
Yan, Zheng 2019-05-31 20:19:18 +08:00 коммит произвёл Ilya Dryomov
Родитель ac6713ccb5
Коммит 2ef5df1abe
1 изменённых файлов: 13 добавлений и 2 удалений

Просмотреть файл

@ -135,7 +135,7 @@ static struct inode *lookup_quotarealm_inode(struct ceph_mds_client *mdsc,
return NULL; return NULL;
mutex_lock(&qri->mutex); mutex_lock(&qri->mutex);
if (qri->inode) { if (qri->inode && ceph_is_any_caps(qri->inode)) {
/* A request has already returned the inode */ /* A request has already returned the inode */
mutex_unlock(&qri->mutex); mutex_unlock(&qri->mutex);
return qri->inode; return qri->inode;
@ -146,7 +146,18 @@ static struct inode *lookup_quotarealm_inode(struct ceph_mds_client *mdsc,
mutex_unlock(&qri->mutex); mutex_unlock(&qri->mutex);
return NULL; 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)) { if (IS_ERR(in)) {
pr_warn("Can't lookup inode %llx (err: %ld)\n", pr_warn("Can't lookup inode %llx (err: %ld)\n",
realm->ino, PTR_ERR(in)); realm->ino, PTR_ERR(in));