diff options
author | Dave Chinner <dchinner@redhat.com> | 2013-06-04 22:09:10 -0400 |
---|---|---|
committer | Ben Myers <bpm@sgi.com> | 2013-06-06 11:52:15 -0400 |
commit | 0a8aa1939777dd114479677f0044652c1fd72398 (patch) | |
tree | 8ffde303c1bd382b421fc1d3a99b0be2f308caaf /fs/xfs | |
parent | f763fd440e094be37b38596ee14f1d64caa9bf9c (diff) |
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 <dchinner@redhat.com>
Reviewed-by: Brian Foster <bfoster@redhat.com>
Reviewed-by: Mark Tinguely <tinuguely@sgi.com>
Signed-off-by: Ben Myers <bpm@sgi.com>
(cherry picked from commit 5c87d4bc1a86bd6e6754ac3d6e111d776ddcfe57)
Diffstat (limited to 'fs/xfs')
-rw-r--r-- | fs/xfs/xfs_acl.c | 31 | ||||
-rw-r--r-- | fs/xfs/xfs_acl.h | 31 |
2 files changed, 42 insertions, 20 deletions
diff --git a/fs/xfs/xfs_acl.c b/fs/xfs/xfs_acl.c index 1d32f1d52763..306d883d89bc 100644 --- a/fs/xfs/xfs_acl.c +++ b/fs/xfs/xfs_acl.c | |||
@@ -21,6 +21,8 @@ | |||
21 | #include "xfs_bmap_btree.h" | 21 | #include "xfs_bmap_btree.h" |
22 | #include "xfs_inode.h" | 22 | #include "xfs_inode.h" |
23 | #include "xfs_vnodeops.h" | 23 | #include "xfs_vnodeops.h" |
24 | #include "xfs_sb.h" | ||
25 | #include "xfs_mount.h" | ||
24 | #include "xfs_trace.h" | 26 | #include "xfs_trace.h" |
25 | #include <linux/slab.h> | 27 | #include <linux/slab.h> |
26 | #include <linux/xattr.h> | 28 | #include <linux/xattr.h> |
@@ -34,7 +36,9 @@ | |||
34 | */ | 36 | */ |
35 | 37 | ||
36 | STATIC struct posix_acl * | 38 | 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) | ||
38 | { | 42 | { |
39 | struct posix_acl_entry *acl_e; | 43 | struct posix_acl_entry *acl_e; |
40 | struct posix_acl *acl; | 44 | struct posix_acl *acl; |
@@ -42,7 +46,7 @@ xfs_acl_from_disk(struct xfs_acl *aclp) | |||
42 | unsigned int count, i; | 46 | unsigned int count, i; |
43 | 47 | ||
44 | count = be32_to_cpu(aclp->acl_cnt); | 48 | count = be32_to_cpu(aclp->acl_cnt); |
45 | if (count > XFS_ACL_MAX_ENTRIES) | 49 | if (count > max_entries) |
46 | return ERR_PTR(-EFSCORRUPTED); | 50 | return ERR_PTR(-EFSCORRUPTED); |
47 | 51 | ||
48 | acl = posix_acl_alloc(count, GFP_KERNEL); | 52 | acl = posix_acl_alloc(count, GFP_KERNEL); |
@@ -108,9 +112,9 @@ xfs_get_acl(struct inode *inode, int type) | |||
108 | struct xfs_inode *ip = XFS_I(inode); | 112 | struct xfs_inode *ip = XFS_I(inode); |
109 | struct posix_acl *acl; | 113 | struct posix_acl *acl; |
110 | struct xfs_acl *xfs_acl; | 114 | struct xfs_acl *xfs_acl; |
111 | int len = sizeof(struct xfs_acl); | ||
112 | unsigned char *ea_name; | 115 | unsigned char *ea_name; |
113 | int error; | 116 | int error; |
117 | int len; | ||
114 | 118 | ||
115 | acl = get_cached_acl(inode, type); | 119 | acl = get_cached_acl(inode, type); |
116 | if (acl != ACL_NOT_CACHED) | 120 | if (acl != ACL_NOT_CACHED) |
@@ -133,8 +137,8 @@ xfs_get_acl(struct inode *inode, int type) | |||
133 | * If we have a cached ACLs value just return it, not need to | 137 | * If we have a cached ACLs value just return it, not need to |
134 | * go out to the disk. | 138 | * go out to the disk. |
135 | */ | 139 | */ |
136 | 140 | len = XFS_ACL_MAX_SIZE(ip->i_mount); | |
137 | xfs_acl = kzalloc(sizeof(struct xfs_acl), GFP_KERNEL); | 141 | xfs_acl = kzalloc(len, GFP_KERNEL); |
138 | if (!xfs_acl) | 142 | if (!xfs_acl) |
139 | return ERR_PTR(-ENOMEM); | 143 | return ERR_PTR(-ENOMEM); |
140 | 144 | ||
@@ -153,7 +157,7 @@ xfs_get_acl(struct inode *inode, int type) | |||
153 | goto out; | 157 | goto out; |
154 | } | 158 | } |
155 | 159 | ||
156 | acl = xfs_acl_from_disk(xfs_acl); | 160 | acl = xfs_acl_from_disk(xfs_acl, XFS_ACL_MAX_ENTRIES(ip->i_mount)); |
157 | if (IS_ERR(acl)) | 161 | if (IS_ERR(acl)) |
158 | goto out; | 162 | goto out; |
159 | 163 | ||
@@ -189,16 +193,17 @@ xfs_set_acl(struct inode *inode, int type, struct posix_acl *acl) | |||
189 | 193 | ||
190 | if (acl) { | 194 | if (acl) { |
191 | struct xfs_acl *xfs_acl; | 195 | struct xfs_acl *xfs_acl; |
192 | int len; | 196 | int len = XFS_ACL_MAX_SIZE(ip->i_mount); |
193 | 197 | ||
194 | xfs_acl = kzalloc(sizeof(struct xfs_acl), GFP_KERNEL); | 198 | xfs_acl = kzalloc(len, GFP_KERNEL); |
195 | if (!xfs_acl) | 199 | if (!xfs_acl) |
196 | return -ENOMEM; | 200 | return -ENOMEM; |
197 | 201 | ||
198 | xfs_acl_to_disk(xfs_acl, acl); | 202 | xfs_acl_to_disk(xfs_acl, acl); |
199 | len = sizeof(struct xfs_acl) - | 203 | |
200 | (sizeof(struct xfs_acl_entry) * | 204 | /* subtract away the unused acl entries */ |
201 | (XFS_ACL_MAX_ENTRIES - acl->a_count)); | 205 | len -= sizeof(struct xfs_acl_entry) * |
206 | (XFS_ACL_MAX_ENTRIES(ip->i_mount) - acl->a_count); | ||
202 | 207 | ||
203 | error = -xfs_attr_set(ip, ea_name, (unsigned char *)xfs_acl, | 208 | error = -xfs_attr_set(ip, ea_name, (unsigned char *)xfs_acl, |
204 | len, ATTR_ROOT); | 209 | len, ATTR_ROOT); |
@@ -243,7 +248,7 @@ xfs_set_mode(struct inode *inode, umode_t mode) | |||
243 | static int | 248 | static int |
244 | xfs_acl_exists(struct inode *inode, unsigned char *name) | 249 | xfs_acl_exists(struct inode *inode, unsigned char *name) |
245 | { | 250 | { |
246 | int len = sizeof(struct xfs_acl); | 251 | int len = XFS_ACL_MAX_SIZE(XFS_M(inode->i_sb)); |
247 | 252 | ||
248 | return (xfs_attr_get(XFS_I(inode), name, NULL, &len, | 253 | return (xfs_attr_get(XFS_I(inode), name, NULL, &len, |
249 | ATTR_ROOT|ATTR_KERNOVAL) == 0); | 254 | ATTR_ROOT|ATTR_KERNOVAL) == 0); |
@@ -379,7 +384,7 @@ xfs_xattr_acl_set(struct dentry *dentry, const char *name, | |||
379 | goto out_release; | 384 | goto out_release; |
380 | 385 | ||
381 | error = -EINVAL; | 386 | 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))) |
383 | goto out_release; | 388 | goto out_release; |
384 | 389 | ||
385 | if (type == ACL_TYPE_ACCESS) { | 390 | if (type == ACL_TYPE_ACCESS) { |
diff --git a/fs/xfs/xfs_acl.h b/fs/xfs/xfs_acl.h index 39632d941354..4016a567b83c 100644 --- a/fs/xfs/xfs_acl.h +++ b/fs/xfs/xfs_acl.h | |||
@@ -22,19 +22,36 @@ struct inode; | |||
22 | struct posix_acl; | 22 | struct posix_acl; |
23 | struct xfs_inode; | 23 | struct xfs_inode; |
24 | 24 | ||
25 | #define XFS_ACL_MAX_ENTRIES 25 | ||
26 | #define XFS_ACL_NOT_PRESENT (-1) | 25 | #define XFS_ACL_NOT_PRESENT (-1) |
27 | 26 | ||
28 | /* On-disk XFS access control list structure */ | 27 | /* 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 | |||
29 | struct xfs_acl { | 35 | struct xfs_acl { |
30 | __be32 acl_cnt; | 36 | __be32 acl_cnt; |
31 | struct xfs_acl_entry { | 37 | struct xfs_acl_entry acl_entry[0]; |
32 | __be32 ae_tag; | ||
33 | __be32 ae_id; | ||
34 | __be16 ae_perm; | ||
35 | } acl_entry[XFS_ACL_MAX_ENTRIES]; | ||
36 | }; | 38 | }; |
37 | 39 | ||
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 | |||
38 | /* On-disk XFS extended attribute names */ | 55 | /* On-disk XFS extended attribute names */ |
39 | #define SGI_ACL_FILE (unsigned char *)"SGI_ACL_FILE" | 56 | #define SGI_ACL_FILE (unsigned char *)"SGI_ACL_FILE" |
40 | #define SGI_ACL_DEFAULT (unsigned char *)"SGI_ACL_DEFAULT" | 57 | #define SGI_ACL_DEFAULT (unsigned char *)"SGI_ACL_DEFAULT" |