[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
More ACL item support
Hi,
Right now XFS can only support 21 ACLs. I've changed some code to make it
support more ACL items. Basically I change all the "acl" structure in the
ACL handling function to dynamically allocated pointers.
But it seems that if the maximum ACL number is increased to a large number,
say 1000, very strange problems will happen. Kernel becomes unstable, oops with
ACL related function. If the number is set to 25(default), everything is fine.
No problems. I don't see obvious errors in the XFS ACL code. Are there any
ideas why this happens? Thanks.
The attachment is a patch which is based on XFS 1.0.1 release.
--
Best Regards,
Harrison
--- 2.4-xfs/fs/xfs/linux/xfs_iops.c.acl Mon Oct 15 20:03:22 2001
+++ 2.4-xfs/fs/xfs/linux/xfs_iops.c Mon May 27 11:28:46 2002
@@ -74,10 +74,14 @@
struct inode *ip;
vattr_t va;
#ifdef CONFIG_FS_POSIX_ACL
- struct acl pdacl; /* parent default ACL */
+ struct acl *pdacl; /* parent default ACL */
#endif
int have_default_acl;
+ ACL_ALLOC(pdacl);
+ if(!pdacl)
+ return -ENOMEM;
+
dvp = LINVFS_GET_VN_ADDRESS(dir);
ASSERT(dvp);
@@ -87,7 +91,7 @@
bzero(&va, sizeof(va));
va.va_mask = AT_TYPE|AT_MODE;
va.va_type = tp;
- have_default_acl = _ACL_GET_DEFAULT(dvp, &pdacl);
+ have_default_acl = _ACL_GET_DEFAULT(dvp, pdacl);
if (!have_default_acl) {
mode &= ~current->fs->umask;
}
@@ -107,6 +111,7 @@
va.va_type = IFTOVT(mode);
if (va.va_type == VNON) {
+ ACL_FREE(pdacl);
return -EINVAL;
}
VOP_CREATE(dvp, (char *)dentry->d_name.name, &va, 0, 0, &vp,
@@ -123,6 +128,7 @@
ip = LINVFS_GET_IP(vp);
if (!ip) {
VN_RELE(vp);
+ ACL_FREE(pdacl);
return -ENOMEM;
}
if (ISVDEV(tp))
@@ -135,10 +141,12 @@
}
if (!error && have_default_acl) {
- error = _ACL_INHERIT(vp, &va, &pdacl);
+ error = _ACL_INHERIT(vp, &va, pdacl);
VMODIFY(vp);
}
+ ACL_FREE(pdacl);
+
return -error;
}
--- 2.4-xfs/fs/xfs/linux/acl.h.acl Mon May 27 11:29:14 2002
+++ 2.4-xfs/fs/xfs/linux/acl.h Mon May 27 15:30:03 2002
@@ -59,7 +59,7 @@
* (USER_OBJ, GROUP_OBJ, MASK, & OTHER_OBJ)
*/
#define NACLBASE 4
-#define ACL_MAX_ENTRIES 25 /* Arbitrarily chosen number */
+#define ACL_MAX_ENTRIES 105 /* Arbitrarily chosen number */
/*
* Data types required by POSIX P1003.1eD15
@@ -83,6 +83,42 @@
struct acl_entry acl_entry[ACL_MAX_ENTRIES];
};
+#ifdef XFS_ACL_DEBUG
+static long acl_kmem = 0;
+ #define ACL_ALLOC(ptr) \
+ do { \
+ ptr = (struct acl *)kmalloc((size_t)sizeof(struct acl), GFP_KERNEL); \
+ if (ptr == 0) { \
+ printk(KERN_ERR "kmalloc returns 0 at %s:%d\n", \
+ __FILE__, __LINE__); \
+ } else { \
+ acl_kmem += sizeof(struct acl); \
+ printk(KERN_INFO "acl_alloc %d, kmem %ld\n", \
+ (size_t)sizeof(struct acl), acl_kmem); \
+ } \
+ } while (0)
+
+ #define ACL_FREE(ptr) \
+ do { \
+ kfree((ptr)); \
+ acl_kmem -= sizeof(struct acl); \
+ printk(KERN_INFO "acl_free %d, kmem %ld\n", \
+ (size_t)sizeof(struct acl), acl_kmem); \
+ } while (0)
+
+#else
+ #define ACL_ALLOC(ptr) \
+ do { \
+ ptr = (struct acl *)kmalloc((size_t) sizeof(struct acl), GFP_KERNEL); \
+ } while (0)
+
+ #define ACL_FREE(ptr) \
+ do { \
+ kfree((ptr)); \
+ } while (0)
+
+#endif /* XFS_ACL_DEBUG */
+
/*
* Values for acl_get_entry
*/
--- 2.4-xfs/fs/xfs/xfs_acl.c.acl Mon Jul 9 14:16:12 2001
+++ 2.4-xfs/fs/xfs/xfs_acl.c Mon May 27 11:28:46 2002
@@ -45,27 +45,40 @@
int
xfs_acl_iaccess( xfs_inode_t *ip, mode_t mode, cred_t *cr )
{
- struct acl acl;
+ struct acl *pacl;
+ int rc = 0;
+
+ ACL_ALLOC(pacl);
+ if(!pacl)
+ return ENOMEM; /* XFS return positive errors */
/*
* If the file has no ACL return -1.
*/
- if (xfs_attr_fetch(ip, SGI_ACL_FILE, (char *)&acl, sizeof(struct acl)))
- return -1;
- xfs_acl_get_endian(&acl);
+ if (xfs_attr_fetch(ip, SGI_ACL_FILE, (char *)pacl, sizeof(struct acl))) {
+ rc = -1;
+ goto exit;
+ }
+ xfs_acl_get_endian(pacl);
/*
* If the file has an empty ACL return -1.
*/
- if (acl.acl_cnt == ACL_NOT_PRESENT)
- return -1;
+ if (pacl->acl_cnt == ACL_NOT_PRESENT) {
+ rc = -1;
+ goto exit;
+ }
/*
* Synchronize ACL with mode bits
*/
- xfs_acl_sync_mode(ip->i_d.di_mode, &acl);
+ xfs_acl_sync_mode(ip->i_d.di_mode, pacl);
- return xfs_acl_access(ip->i_d.di_uid, ip->i_d.di_gid, &acl, mode, cr);
+ rc = xfs_acl_access(ip->i_d.di_uid, ip->i_d.di_gid, pacl, mode, cr);
+
+exit:
+ ACL_FREE(pacl);
+ return rc;
}
/*
@@ -315,23 +328,31 @@
xfs_acl_set_attr(vnode_t *vp, struct acl *aclp, int kind, int *error)
{
struct acl_entry *ace, *newace, *end;
- struct acl newacl;
+ struct acl *pnewacl;
int len = sizeof(struct acl);
+ ACL_ALLOC(pnewacl);
+ if(!pnewacl) {
+ printk("Not enough memory!\n");
+ return;
+ }
+
/* do the endian conversion */
/* loop thru ACEs of ACL */
end = &aclp->acl_entry[0]+aclp->acl_cnt;
- for (ace=&aclp->acl_entry[0],newace=&newacl.acl_entry[0]; ace < end;
+ for (ace=&aclp->acl_entry[0],newace=&(pnewacl->acl_entry[0]); ace < end;
ace++,newace++) {
INT_SET(newace->ae_tag, ARCH_CONVERT, ace->ae_tag);
INT_SET(newace->ae_id, ARCH_CONVERT, ace->ae_id);
INT_SET(newace->ae_perm, ARCH_CONVERT, ace->ae_perm);
}
- INT_SET(newacl.acl_cnt, ARCH_CONVERT, aclp->acl_cnt);
+ INT_SET(pnewacl->acl_cnt, ARCH_CONVERT, aclp->acl_cnt);
VOP_ATTR_SET(vp, kind==ACL_ACCESS ? SGI_ACL_FILE: SGI_ACL_DEFAULT,
- (char *)&newacl, len, ATTR_ROOT, sys_cred, *error);
+ (char *)pnewacl, len, ATTR_ROOT, sys_cred, *error);
+
+ ACL_FREE(pnewacl);
}
STATIC int
@@ -383,7 +404,7 @@
int
xfs_acl_inherit(vnode_t *vp, vattr_t *vap, struct acl *pdaclp)
{
- struct acl cacl;
+ struct acl *pcacl;
int error = 0;
/*
@@ -395,6 +416,11 @@
if (pdaclp == NULL || xfs_acl_invalid(pdaclp))
return (0);
+ ACL_ALLOC(pcacl);
+ if(!pcacl) {
+ return ENOMEM;
+ }
+
/*
* Copy the default ACL of the containing directory to
* the access ACL of the new file and use the mode that
@@ -402,11 +428,11 @@
* the u::,g::[m::], and o:: entries. This is what makes
* umask() "work" with ACL's.
*/
- memcpy(&cacl, pdaclp, sizeof(cacl));
- xfs_acl_filter_mode(vap->va_mode, &cacl);
+ memcpy(pcacl, pdaclp, sizeof(struct acl));
+ xfs_acl_filter_mode(vap->va_mode, pcacl);
/* set the mode to the acl */
- xfs_acl_setmode(vp, &cacl);
+ xfs_acl_setmode(vp, pcacl);
/*
* Set the default and access acl on the file. The mode is already
@@ -420,9 +446,11 @@
xfs_acl_set_attr(vp, pdaclp, ACL_DEFAULT, &error);
}
if (!error) {
- xfs_acl_set_attr(vp, &cacl, ACL_ACCESS, &error);
+ xfs_acl_set_attr(vp, pcacl, ACL_ACCESS, &error);
}
+ ACL_FREE(pcacl);
+
return (error);
}
@@ -430,11 +458,16 @@
STATIC int
xfs_acl_vget(vnode_t *vp, int kind, struct acl *acl)
{
- struct acl kacl;
- int size = sizeof(kacl);
+ struct acl *pkacl;
+ int size = sizeof(struct acl);
int error = 0;
vattr_t va;
+ ACL_ALLOC(pkacl);
+ if(!pkacl) {
+ return ENOMEM;
+ }
+
#ifdef SERIOUS_DEBUG
cmn_err(CE_NOTE, "xfs_acl_vget 0x%x %s 0x%x", vp, (kind == ACL_ACCESS) ? "ACCESS_ACL" : "DEFAULT_ACL", acl);
#endif /* SERIOUS_DEBUG */
@@ -442,10 +475,10 @@
/*
* Get the ACL if there is one...
*/
- memset(&kacl, 0, size); /* Make sure we don't copyout random stack */
- xfs_acl_get_attr(vp, &kacl, kind, &error);
+ memset(pkacl, 0, size); /* Make sure we don't copyout random stack */
+ xfs_acl_get_attr(vp, pkacl, kind, &error);
- if (!error && xfs_acl_invalid(&kacl)) {
+ if (!error && xfs_acl_invalid(pkacl)) {
#ifdef SERIOUS_DEBUG
cmn_err(CE_WARN, "Invalid acl fetched");
#endif /* SERIOUS_DEBUG */
@@ -466,13 +499,13 @@
* ACL, then the ACL is deemed NOT PRESENT.
*/
if (error) {
- kacl.acl_cnt = ACL_NOT_PRESENT;
+ pkacl->acl_cnt = ACL_NOT_PRESENT;
} else if (kind == ACL_ACCESS) {
/*
* Synchronize an Access ACL with the mode before
* copying it out.
*/
- xfs_acl_sync_mode(va.va_mode, &kacl);
+ xfs_acl_sync_mode(va.va_mode, pkacl);
}
@@ -485,10 +518,13 @@
if (error == ENOATTR)
error = 0;
- if (!error && copyout((caddr_t)&kacl, (caddr_t)acl,
+ if (!error && copyout((caddr_t)pkacl, (caddr_t)acl,
sizeof(struct acl))) {
error = EFAULT;
}
+
+ ACL_FREE(pkacl);
+
return (error);
}
@@ -593,19 +629,33 @@
int
xfs_acl_set(vnode_t *vp, struct acl *acl, struct acl *dacl)
{
- struct acl kacl;
- struct acl kdacl;
+ struct acl *pkacl;
+ struct acl *pkdacl;
vattr_t va;
int error;
if (!acl && !dacl)
return (EINVAL);
- if (acl && copy_from_user((caddr_t)&kacl, (caddr_t)acl,
- sizeof (struct acl)))
- return (EFAULT);
- if (dacl && copy_from_user((caddr_t)&kdacl, (caddr_t)dacl,
- sizeof (struct acl)))
- return (EFAULT);
+ ACL_ALLOC(pkacl);
+ if(!pkacl) {
+ return ENOMEM;
+ }
+ ACL_ALLOC(pkdacl);
+ if(!pkdacl) {
+ ACL_FREE(pkacl);
+ return ENOMEM;
+ }
+
+ if (acl && copy_from_user((caddr_t)pkacl, (caddr_t)acl,
+ sizeof (struct acl))) {
+ error = (EFAULT);
+ goto exit;
+ }
+ if (dacl && copy_from_user((caddr_t)pkdacl, (caddr_t)dacl,
+ sizeof (struct acl))) {
+ error = (EFAULT);
+ goto exit;
+ }
VN_HOLD(vp);
@@ -630,15 +680,20 @@
/*
* Set the access ACL.
*/
- error = xfs_acl_vset(vp, &kacl);
+ error = xfs_acl_vset(vp, pkacl);
if (!error && dacl)
/*
* Set the default ACL.
*/
- error = xfs_dacl_vset(vp, &kdacl);
+ error = xfs_dacl_vset(vp, pkdacl);
}
VN_RELE(vp);
+
+exit:
+ ACL_FREE(pkacl);
+ ACL_FREE(pkdacl);
+
return (error);
}