提交 f017754d 编写于 作者: C Chengguang Xu 提交者: Ilya Dryomov

ceph: add retry logic for error -ERANGE in ceph_get_acl()

When the size of acl extended attribution is larger than pre-allocated
value buffer size, we will hit error '-ERANGE' and it's probabaly caused
by concurrent get/set acl from different clients. In this case, current
logic just sets acl to NULL so that we cannot get proper information but
the operation looks successful.

This patch adds retry logic for error -ERANGE and return -EIO if fail
from the retry. Additionally, print real errno when failing from
__ceph_getxattr().
Signed-off-by: NChengguang Xu <cgxu519@gmx.com>
Reviewed-by: N"Yan, Zheng" <zyan@redhat.com>
Signed-off-by: NIlya Dryomov <idryomov@gmail.com>
上级 acb18725
...@@ -45,6 +45,7 @@ static inline void ceph_set_cached_acl(struct inode *inode, ...@@ -45,6 +45,7 @@ static inline void ceph_set_cached_acl(struct inode *inode,
struct posix_acl *ceph_get_acl(struct inode *inode, int type) struct posix_acl *ceph_get_acl(struct inode *inode, int type)
{ {
int size; int size;
unsigned int retry_cnt = 0;
const char *name; const char *name;
char *value = NULL; char *value = NULL;
struct posix_acl *acl; struct posix_acl *acl;
...@@ -60,6 +61,7 @@ struct posix_acl *ceph_get_acl(struct inode *inode, int type) ...@@ -60,6 +61,7 @@ struct posix_acl *ceph_get_acl(struct inode *inode, int type)
BUG(); BUG();
} }
retry:
size = __ceph_getxattr(inode, name, "", 0); size = __ceph_getxattr(inode, name, "", 0);
if (size > 0) { if (size > 0) {
value = kzalloc(size, GFP_NOFS); value = kzalloc(size, GFP_NOFS);
...@@ -68,12 +70,22 @@ struct posix_acl *ceph_get_acl(struct inode *inode, int type) ...@@ -68,12 +70,22 @@ struct posix_acl *ceph_get_acl(struct inode *inode, int type)
size = __ceph_getxattr(inode, name, value, size); size = __ceph_getxattr(inode, name, value, size);
} }
if (size > 0) if (size == -ERANGE && retry_cnt < 10) {
retry_cnt++;
kfree(value);
value = NULL;
goto retry;
}
if (size > 0) {
acl = posix_acl_from_xattr(&init_user_ns, value, size); acl = posix_acl_from_xattr(&init_user_ns, value, size);
else if (size == -ERANGE || size == -ENODATA || size == 0) } else if (size == -ENODATA || size == 0) {
acl = NULL; acl = NULL;
else } else {
pr_err_ratelimited("get acl %llx.%llx failed, err=%d\n",
ceph_vinop(inode), size);
acl = ERR_PTR(-EIO); acl = ERR_PTR(-EIO);
}
kfree(value); kfree(value);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册