aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ceph
diff options
context:
space:
mode:
Diffstat (limited to 'fs/ceph')
-rw-r--r--fs/ceph/acl.c18
1 files changed, 15 insertions, 3 deletions
diff --git a/fs/ceph/acl.c b/fs/ceph/acl.c
index 59cb307b15fb..eb9d567c9ef8 100644
--- a/fs/ceph/acl.c
+++ b/fs/ceph/acl.c
@@ -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)
{
int size;
+ unsigned int retry_cnt = 0;
const char *name;
char *value = NULL;
struct posix_acl *acl;
@@ -60,6 +61,7 @@ struct posix_acl *ceph_get_acl(struct inode *inode, int type)
BUG();
}
+retry:
size = __ceph_getxattr(inode, name, "", 0);
if (size > 0) {
value = kzalloc(size, GFP_NOFS);
@@ -68,12 +70,22 @@ struct posix_acl *ceph_get_acl(struct inode *inode, int type)
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);
- else if (size == -ERANGE || size == -ENODATA || size == 0)
+ } else if (size == -ENODATA || size == 0) {
acl = NULL;
- else
+ } else {
+ pr_err_ratelimited("get acl %llx.%llx failed, err=%d\n",
+ ceph_vinop(inode), size);
acl = ERR_PTR(-EIO);
+ }
kfree(value);