diff options
Diffstat (limited to 'fs/ceph/acl.c')
-rw-r--r-- | fs/ceph/acl.c | 18 |
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); |