Skip to content

Commit 5c87d4b

Browse files
Dave ChinnerBen Myers
authored andcommitted
xfs: increase number of ACL entries for V5 superblocks
The limit of 25 ACL entries is arbitrary, but baked into the on-disk format. For version 5 superblocks, increase it to the maximum nuber of ACLs that can fit into a single xattr. Signed-off-by: Dave Chinner <[email protected]> Reviewed-by: Brian Foster <[email protected]> Reviewed-by: Mark Tinguely <[email protected]> Signed-off-by: Ben Myers <[email protected]>
1 parent d3eaace commit 5c87d4b

File tree

2 files changed

+42
-20
lines changed

2 files changed

+42
-20
lines changed

fs/xfs/xfs_acl.c

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@
2121
#include "xfs_bmap_btree.h"
2222
#include "xfs_inode.h"
2323
#include "xfs_vnodeops.h"
24+
#include "xfs_sb.h"
25+
#include "xfs_mount.h"
2426
#include "xfs_trace.h"
2527
#include <linux/slab.h>
2628
#include <linux/xattr.h>
@@ -34,15 +36,17 @@
3436
*/
3537

3638
STATIC struct posix_acl *
37-
xfs_acl_from_disk(struct xfs_acl *aclp)
39+
xfs_acl_from_disk(
40+
struct xfs_acl *aclp,
41+
int max_entries)
3842
{
3943
struct posix_acl_entry *acl_e;
4044
struct posix_acl *acl;
4145
struct xfs_acl_entry *ace;
4246
unsigned int count, i;
4347

4448
count = be32_to_cpu(aclp->acl_cnt);
45-
if (count > XFS_ACL_MAX_ENTRIES)
49+
if (count > max_entries)
4650
return ERR_PTR(-EFSCORRUPTED);
4751

4852
acl = posix_acl_alloc(count, GFP_KERNEL);
@@ -108,9 +112,9 @@ xfs_get_acl(struct inode *inode, int type)
108112
struct xfs_inode *ip = XFS_I(inode);
109113
struct posix_acl *acl;
110114
struct xfs_acl *xfs_acl;
111-
int len = sizeof(struct xfs_acl);
112115
unsigned char *ea_name;
113116
int error;
117+
int len;
114118

115119
acl = get_cached_acl(inode, type);
116120
if (acl != ACL_NOT_CACHED)
@@ -133,8 +137,8 @@ xfs_get_acl(struct inode *inode, int type)
133137
* If we have a cached ACLs value just return it, not need to
134138
* go out to the disk.
135139
*/
136-
137-
xfs_acl = kzalloc(sizeof(struct xfs_acl), GFP_KERNEL);
140+
len = XFS_ACL_MAX_SIZE(ip->i_mount);
141+
xfs_acl = kzalloc(len, GFP_KERNEL);
138142
if (!xfs_acl)
139143
return ERR_PTR(-ENOMEM);
140144

@@ -153,7 +157,7 @@ xfs_get_acl(struct inode *inode, int type)
153157
goto out;
154158
}
155159

156-
acl = xfs_acl_from_disk(xfs_acl);
160+
acl = xfs_acl_from_disk(xfs_acl, XFS_ACL_MAX_ENTRIES(ip->i_mount));
157161
if (IS_ERR(acl))
158162
goto out;
159163

@@ -189,16 +193,17 @@ xfs_set_acl(struct inode *inode, int type, struct posix_acl *acl)
189193

190194
if (acl) {
191195
struct xfs_acl *xfs_acl;
192-
int len;
196+
int len = XFS_ACL_MAX_SIZE(ip->i_mount);
193197

194-
xfs_acl = kzalloc(sizeof(struct xfs_acl), GFP_KERNEL);
198+
xfs_acl = kzalloc(len, GFP_KERNEL);
195199
if (!xfs_acl)
196200
return -ENOMEM;
197201

198202
xfs_acl_to_disk(xfs_acl, acl);
199-
len = sizeof(struct xfs_acl) -
200-
(sizeof(struct xfs_acl_entry) *
201-
(XFS_ACL_MAX_ENTRIES - acl->a_count));
203+
204+
/* subtract away the unused acl entries */
205+
len -= sizeof(struct xfs_acl_entry) *
206+
(XFS_ACL_MAX_ENTRIES(ip->i_mount) - acl->a_count);
202207

203208
error = -xfs_attr_set(ip, ea_name, (unsigned char *)xfs_acl,
204209
len, ATTR_ROOT);
@@ -243,7 +248,7 @@ xfs_set_mode(struct inode *inode, umode_t mode)
243248
static int
244249
xfs_acl_exists(struct inode *inode, unsigned char *name)
245250
{
246-
int len = sizeof(struct xfs_acl);
251+
int len = XFS_ACL_MAX_SIZE(XFS_M(inode->i_sb));
247252

248253
return (xfs_attr_get(XFS_I(inode), name, NULL, &len,
249254
ATTR_ROOT|ATTR_KERNOVAL) == 0);
@@ -379,7 +384,7 @@ xfs_xattr_acl_set(struct dentry *dentry, const char *name,
379384
goto out_release;
380385

381386
error = -EINVAL;
382-
if (acl->a_count > XFS_ACL_MAX_ENTRIES)
387+
if (acl->a_count > XFS_ACL_MAX_ENTRIES(XFS_M(inode->i_sb)))
383388
goto out_release;
384389

385390
if (type == ACL_TYPE_ACCESS) {

fs/xfs/xfs_acl.h

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,19 +22,36 @@ struct inode;
2222
struct posix_acl;
2323
struct xfs_inode;
2424

25-
#define XFS_ACL_MAX_ENTRIES 25
2625
#define XFS_ACL_NOT_PRESENT (-1)
2726

2827
/* On-disk XFS access control list structure */
28+
struct xfs_acl_entry {
29+
__be32 ae_tag;
30+
__be32 ae_id;
31+
__be16 ae_perm;
32+
__be16 ae_pad; /* fill the implicit hole in the structure */
33+
};
34+
2935
struct xfs_acl {
30-
__be32 acl_cnt;
31-
struct xfs_acl_entry {
32-
__be32 ae_tag;
33-
__be32 ae_id;
34-
__be16 ae_perm;
35-
} acl_entry[XFS_ACL_MAX_ENTRIES];
36+
__be32 acl_cnt;
37+
struct xfs_acl_entry acl_entry[0];
3638
};
3739

40+
/*
41+
* The number of ACL entries allowed is defined by the on-disk format.
42+
* For v4 superblocks, that is limited to 25 entries. For v5 superblocks, it is
43+
* limited only by the maximum size of the xattr that stores the information.
44+
*/
45+
#define XFS_ACL_MAX_ENTRIES(mp) \
46+
(xfs_sb_version_hascrc(&mp->m_sb) \
47+
? (XATTR_SIZE_MAX - sizeof(struct xfs_acl)) / \
48+
sizeof(struct xfs_acl_entry) \
49+
: 25)
50+
51+
#define XFS_ACL_MAX_SIZE(mp) \
52+
(sizeof(struct xfs_acl) + \
53+
sizeof(struct xfs_acl_entry) * XFS_ACL_MAX_ENTRIES((mp)))
54+
3855
/* On-disk XFS extended attribute names */
3956
#define SGI_ACL_FILE (unsigned char *)"SGI_ACL_FILE"
4057
#define SGI_ACL_DEFAULT (unsigned char *)"SGI_ACL_DEFAULT"

0 commit comments

Comments
 (0)