
From: From: Andreas Gruenbacher <agruen@suse.de>

* Various minor cleanups and simplifications in the extended attributes
  and acl code.

* Use a smarter shortcut rule in ext[23]_permission(): If the mask
  contains permissions that are not also contained in the group
  file mode permission bits, those permissions can never be granted by
  an acl. (The previous shortcut rule was more coarse.)



 fs/ext2/acl.c   |   85 ++++++++++++++++++++++++++++++++----------------------
 fs/ext2/xattr.c |   55 ++++++++++++++++-------------------
 fs/ext3/acl.c   |   88 +++++++++++++++++++++++++++++++++-----------------------
 fs/ext3/xattr.c |   49 ++++++++++++++-----------------
 4 files changed, 153 insertions(+), 124 deletions(-)

diff -puN fs/ext2/acl.c~xattr-cleanup fs/ext2/acl.c
--- 25/fs/ext2/acl.c~xattr-cleanup	2003-07-02 16:35:37.000000000 -0700
+++ 25-akpm/fs/ext2/acl.c	2003-07-02 16:35:37.000000000 -0700
@@ -1,7 +1,7 @@
 /*
  * linux/fs/ext2/acl.c
  *
- * Copyright (C) 2001 by Andreas Gruenbacher, <a.gruenbacher@computer.org>
+ * Copyright (C) 2001-2003 Andreas Gruenbacher, <agruen@suse.de>
  */
 
 #include <linux/init.h>
@@ -19,7 +19,7 @@ static struct posix_acl *
 ext2_acl_from_disk(const void *value, size_t size)
 {
 	const char *end = (char *)value + size;
-	int n, count;
+	size_t n, count;
 	struct posix_acl *acl;
 
 	if (!value)
@@ -85,7 +85,7 @@ ext2_acl_to_disk(const struct posix_acl 
 {
 	ext2_acl_header *ext_acl;
 	char *e;
-	int n;
+	size_t n;
 
 	*size = ext2_acl_size(acl->a_count);
 	ext_acl = (ext2_acl_header *)kmalloc(sizeof(ext2_acl_header) +
@@ -130,10 +130,11 @@ fail:
 static struct posix_acl *
 ext2_get_acl(struct inode *inode, int type)
 {
+	const size_t max_size = ext2_acl_size(EXT2_ACL_MAX_ENTRIES);
+	struct ext2_inode_inode *ei = EXT2_I(inode);
 	int name_index;
 	char *value;
-	struct posix_acl *acl, **p_acl;
-	const size_t size = ext2_acl_size(EXT2_ACL_MAX_ENTRIES);
+	struct posix_acl *acl;
 	int retval;
 
 	if (!test_opt(inode->i_sb, POSIX_ACL))
@@ -141,36 +142,43 @@ ext2_get_acl(struct inode *inode, int ty
 
 	switch(type) {
 		case ACL_TYPE_ACCESS:
-			p_acl = &EXT2_I(inode)->i_acl;
+			if (ei->i_acl != EXT2_ACL_NOT_CACHED)
+				return posix_acl_dup(ei->i_acl);
 			name_index = EXT2_XATTR_INDEX_POSIX_ACL_ACCESS;
 			break;
 
 		case ACL_TYPE_DEFAULT:
-			p_acl = &EXT2_I(inode)->i_default_acl;
+			if (ei->i_default_acl != EXT2_ACL_NOT_CACHED)
+				return posix_acl_dup(ei->i_default_acl);
 			name_index = EXT2_XATTR_INDEX_POSIX_ACL_DEFAULT;
 			break;
 
 		default:
 			return ERR_PTR(-EINVAL);
 	}
-	if (*p_acl != EXT2_ACL_NOT_CACHED)
-		return posix_acl_dup(*p_acl);
-	value = kmalloc(size, GFP_KERNEL);
+	value = kmalloc(max_size, GFP_KERNEL);
 	if (!value)
 		return ERR_PTR(-ENOMEM);
 
-	retval = ext2_xattr_get(inode, name_index, "", value, size);
-
-	if (retval == -ENODATA || retval == -ENOSYS)
-		*p_acl = acl = NULL;
-	else if (retval < 0)
-		acl = ERR_PTR(retval);
-	else {
+	retval = ext2_xattr_get(inode, name_index, "", value, max_size);
+	acl = ERR_PTR(retval);
+	if (retval >= 0)
 		acl = ext2_acl_from_disk(value, retval);
-		if (!IS_ERR(acl))
-			*p_acl = posix_acl_dup(acl);
-	}
+	else if (retval == -ENODATA || retval == -ENOSYS)
+		acl = NULL;
 	kfree(value);
+
+	if (!IS_ERR(acl)) {
+		switch(type) {
+			case ACL_TYPE_ACCESS:
+				ei->i_acl = posix_acl_dup(acl);
+				break;
+
+			case ACL_TYPE_DEFAULT:
+				ei->i_default_acl = posix_acl_dup(acl);
+				break;
+		}
+	}
 	return acl;
 }
 
@@ -180,9 +188,9 @@ ext2_get_acl(struct inode *inode, int ty
 static int
 ext2_set_acl(struct inode *inode, int type, struct posix_acl *acl)
 {
+	struct ext2_inode_info *ei = EXT2_I(inode);
 	int name_index;
 	void *value = NULL;
-	struct posix_acl **p_acl;
 	size_t size;
 	int error;
 
@@ -194,7 +202,6 @@ ext2_set_acl(struct inode *inode, int ty
 	switch(type) {
 		case ACL_TYPE_ACCESS:
 			name_index = EXT2_XATTR_INDEX_POSIX_ACL_ACCESS;
-			p_acl = &EXT2_I(inode)->i_acl;
 			if (acl) {
 				mode_t mode = inode->i_mode;
 				error = posix_acl_equiv_mode(acl, &mode);
@@ -211,7 +218,6 @@ ext2_set_acl(struct inode *inode, int ty
 
 		case ACL_TYPE_DEFAULT:
 			name_index = EXT2_XATTR_INDEX_POSIX_ACL_DEFAULT;
-			p_acl = &EXT2_I(inode)->i_default_acl;
 			if (!S_ISDIR(inode->i_mode))
 				return acl ? -EACCES : 0;
 			break;
@@ -232,9 +238,19 @@ ext2_set_acl(struct inode *inode, int ty
 	if (value)
 		kfree(value);
 	if (!error) {
-		if (*p_acl && *p_acl != EXT2_ACL_NOT_CACHED)
-			posix_acl_release(*p_acl);
-		*p_acl = posix_acl_dup(acl);
+		switch(type) {
+			case ACL_TYPE_ACCESS:
+				if (ei->i_acl != EXT2_ACL_NOT_CACHED)
+					posix_acl_release(ei->i_acl);
+				ei->i_acl = posix_acl_dup(acl);
+				break;
+
+			case ACL_TYPE_DEFAULT:
+				if (ei->i_default_acl != EXT2_ACL_NOT_CACHED)
+					posix_acl_release(ei->i_default_acl);
+				ei->i_default_acl = posix_acl_dup(acl);
+				break;
+		}
 	}
 	return error;
 }
@@ -254,11 +270,13 @@ __ext2_permission(struct inode *inode, i
 	if (current->fsuid == inode->i_uid) {
 		mode >>= 6;
 	} else if (test_opt(inode->i_sb, POSIX_ACL)) {
-		/* ACL can't contain additional permissions if
-		   the ACL_MASK entry is 0 */
-		if (!(mode & S_IRWXG))
+		struct ext2_inode_info *ei = EXT2_I(inode);
+
+		/* The access ACL cannot grant access if the group class
+		   permission bits don't contain all requested permissions. */
+		if (((mode >> 3) & mask & S_IRWXO) != mask)
 			goto check_groups;
-		if (EXT2_I(inode)->i_acl == EXT2_ACL_NOT_CACHED) {
+		if (ei->i_acl == EXT2_ACL_NOT_CACHED) {
 			struct posix_acl *acl;
 
 			if (lock) {
@@ -271,12 +289,11 @@ __ext2_permission(struct inode *inode, i
 			if (IS_ERR(acl))
 				return PTR_ERR(acl);
 			posix_acl_release(acl);
-			if (EXT2_I(inode)->i_acl == EXT2_ACL_NOT_CACHED)
+			if (ei->i_acl == EXT2_ACL_NOT_CACHED)
 				return -EIO;
 		}
-		if (EXT2_I(inode)->i_acl) {
-			int error = posix_acl_permission(inode,
-				EXT2_I(inode)->i_acl, mask);
+		if (ei->i_acl) {
+			int error = posix_acl_permission(inode, ei->i_acl,mask);
 			if (error == -EACCES)
 				goto check_capabilities;
 			return error;
diff -puN fs/ext2/xattr.c~xattr-cleanup fs/ext2/xattr.c
--- 25/fs/ext2/xattr.c~xattr-cleanup	2003-07-02 16:35:37.000000000 -0700
+++ 25-akpm/fs/ext2/xattr.c	2003-07-02 16:35:37.000000000 -0700
@@ -1,7 +1,7 @@
 /*
  * linux/fs/ext2/xattr.c
  *
- * Copyright (C) 2001 by Andreas Gruenbacher, <a.gruenbacher@computer.org>
+ * Copyright (C) 2001-2003 Andreas Gruenbacher <agruen@suse.de>
  *
  * Fix by Harrison Xing <harrison@mountainviewdata.com>.
  * Extended attributes for symlinks and special files added per
@@ -83,8 +83,9 @@ EXPORT_SYMBOL(ext2_xattr_set);
 	} while (0)
 # define ea_bdebug(bh, f...) do { \
 		char b[BDEVNAME_SIZE]; \
-		printk(KERN_DEBUG "block %s:%ld: ", \
-			bdevname(bh->b_bdev, b), bh->b_blocknr); \
+		printk(KERN_DEBUG "block %s:%lu: ", \
+			bdevname(bh->b_bdev, b), \
+			(unsigned long) bh->b_blocknr); \
 		printk(f); \
 		printk("\n"); \
 	} while (0)
@@ -196,7 +197,6 @@ ext2_xattr_handler(int name_index)
  * Inode operation getxattr()
  *
  * dentry->d_inode->i_sem down
- * BKL held [before 2.5.x]
  */
 ssize_t
 ext2_getxattr(struct dentry *dentry, const char *name,
@@ -215,7 +215,6 @@ ext2_getxattr(struct dentry *dentry, con
  * Inode operation listxattr()
  *
  * dentry->d_inode->i_sem down
- * BKL held [before 2.5.x]
  */
 ssize_t
 ext2_listxattr(struct dentry *dentry, char *buffer, size_t size)
@@ -227,7 +226,6 @@ ext2_listxattr(struct dentry *dentry, ch
  * Inode operation setxattr()
  *
  * dentry->d_inode->i_sem down
- * BKL held [before 2.5.x]
  */
 int
 ext2_setxattr(struct dentry *dentry, const char *name,
@@ -248,7 +246,6 @@ ext2_setxattr(struct dentry *dentry, con
  * Inode operation removexattr()
  *
  * dentry->d_inode->i_sem down
- * BKL held [before 2.5.x]
  */
 int
 ext2_removexattr(struct dentry *dentry, const char *name)
@@ -278,9 +275,9 @@ ext2_xattr_get(struct inode *inode, int 
 {
 	struct buffer_head *bh = NULL;
 	struct ext2_xattr_entry *entry;
-	unsigned int size;
+	size_t name_len, size;
 	char *end;
-	int name_len, error;
+	int error;
 
 	ea_idebug(inode, "name=%d.%s, buffer=%p, buffer_size=%ld",
 		  name_index, name, buffer, (long)buffer_size);
@@ -376,7 +373,7 @@ ext2_xattr_list(struct inode *inode, cha
 {
 	struct buffer_head *bh = NULL;
 	struct ext2_xattr_entry *entry;
-	unsigned int size = 0;
+	size_t size = 0;
 	char *buf, *end;
 	int error;
 
@@ -482,8 +479,8 @@ ext2_xattr_set(struct inode *inode, int 
 	struct buffer_head *bh = NULL;
 	struct ext2_xattr_header *header = NULL;
 	struct ext2_xattr_entry *here, *last;
-	unsigned int name_len;
-	int min_offs = sb->s_blocksize, not_found = 1, free, error;
+	size_t name_len, free, min_offs = sb->s_blocksize;
+	int not_found = 1, error;
 	char *end;
 	
 	/*
@@ -540,7 +537,7 @@ bad_block:		ext2_error(sb, "ext2_xattr_s
 			if ((char *)next >= end)
 				goto bad_block;
 			if (!here->e_value_block && here->e_value_size) {
-				int offs = le16_to_cpu(here->e_value_offs);
+				size_t offs = le16_to_cpu(here->e_value_offs);
 				if (offs < min_offs)
 					min_offs = offs;
 			}
@@ -560,7 +557,7 @@ bad_block:		ext2_error(sb, "ext2_xattr_s
 			if ((char *)next >= end)
 				goto bad_block;
 			if (!last->e_value_block && last->e_value_size) {
-				int offs = le16_to_cpu(last->e_value_offs);
+				size_t offs = le16_to_cpu(last->e_value_offs);
 				if (offs < min_offs)
 					min_offs = offs;
 			}
@@ -584,25 +581,23 @@ bad_block:		ext2_error(sb, "ext2_xattr_s
 		error = 0;
 		if (value == NULL)
 			goto cleanup;
-		else
-			free -= EXT2_XATTR_LEN(name_len);
 	} else {
 		/* Request to create an existing attribute? */
 		error = -EEXIST;
 		if (flags & XATTR_CREATE)
 			goto cleanup;
 		if (!here->e_value_block && here->e_value_size) {
-			unsigned int size = le32_to_cpu(here->e_value_size);
+			size_t size = le32_to_cpu(here->e_value_size);
 
 			if (le16_to_cpu(here->e_value_offs) + size > 
 			    sb->s_blocksize || size > sb->s_blocksize)
 				goto bad_block;
 			free += EXT2_XATTR_SIZE(size);
 		}
+		free += EXT2_XATTR_LEN(name_len);
 	}
-	free -= EXT2_XATTR_SIZE(value_len);
 	error = -ENOSPC;
-	if (free < 0)
+	if (free < EXT2_XATTR_LEN(name_len) + EXT2_XATTR_SIZE(value_len))
 		goto cleanup;
 
 	/* Here we know that we can set the new attribute. */
@@ -640,8 +635,8 @@ bad_block:		ext2_error(sb, "ext2_xattr_s
 
 	if (not_found) {
 		/* Insert the new name. */
-		int size = EXT2_XATTR_LEN(name_len);
-		int rest = (char *)last - (char *)here;
+		size_t size = EXT2_XATTR_LEN(name_len);
+		size_t rest = (char *)last - (char *)here;
 		memmove((char *)here + size, here, rest);
 		memset(here, 0, size);
 		here->e_name_index = name_index;
@@ -651,7 +646,7 @@ bad_block:		ext2_error(sb, "ext2_xattr_s
 		/* Remove the old value. */
 		if (!here->e_value_block && here->e_value_size) {
 			char *first_val = (char *)header + min_offs;
-			int offs = le16_to_cpu(here->e_value_offs);
+			size_t offs = le16_to_cpu(here->e_value_offs);
 			char *val = (char *)header + offs;
 			size_t size = EXT2_XATTR_SIZE(
 				le32_to_cpu(here->e_value_size));
@@ -663,7 +658,7 @@ bad_block:		ext2_error(sb, "ext2_xattr_s
 			/* Adjust all value offsets. */
 			last = ENTRY(header+1);
 			while (!IS_LAST_ENTRY(last)) {
-				int o = le16_to_cpu(last->e_value_offs);
+				size_t o = le16_to_cpu(last->e_value_offs);
 				if (!last->e_value_block && o < offs)
 					last->e_value_offs =
 						cpu_to_le16(o + size);
@@ -678,7 +673,7 @@ bad_block:		ext2_error(sb, "ext2_xattr_s
 				goto cleanup;
 			} else {
 				/* Remove the old name. */
-				int size = EXT2_XATTR_LEN(name_len);
+				size_t size = EXT2_XATTR_LEN(name_len);
 				last = ENTRY((char *)last - size);
 				memmove(here, (char*)here + size,
 					(char*)last - (char*)here);
@@ -732,9 +727,9 @@ ext2_xattr_set2(struct inode *inode, str
 			 * The old block will be released after updating
 			 * the inode.
 			 */
-			ea_bdebug(new_bh, "%s block %ld",
+			ea_bdebug(new_bh, "%s block %lu",
 				(old_bh == new_bh) ? "keeping" : "reusing",
-				new_bh->b_blocknr);
+				(unsigned long) new_bh->b_blocknr);
 			
 			error = -EDQUOT;
 			if (DQUOT_ALLOC_BLOCK(inode, 1))
@@ -751,8 +746,10 @@ ext2_xattr_set2(struct inode *inode, str
 			ext2_xattr_cache_insert(new_bh);
 		} else {
 			/* We need to allocate a new block */
-			int goal = le32_to_cpu(EXT2_SB(sb)->s_es->s_first_data_block) +
-				EXT2_I(inode)->i_block_group * EXT2_BLOCKS_PER_GROUP(sb);
+			int goal = le32_to_cpu(EXT2_SB(sb)->s_es->
+						           s_first_data_block) +
+				   EXT2_I(inode)->i_block_group *
+				   EXT2_BLOCKS_PER_GROUP(sb);
 			int block = ext2_new_block(inode, goal, 0, 0, &error);
 			if (error)
 				goto cleanup;
@@ -857,8 +854,8 @@ ext2_xattr_delete_inode(struct inode *in
 	if (HDR(bh)->h_refcount == cpu_to_le32(1)) {
 		ext2_xattr_cache_remove(bh);
 		ext2_free_blocks(inode, EXT2_I(inode)->i_file_acl, 1);
+		get_bh(bh);
 		bforget(bh);
-		bh = NULL;
 	} else {
 		HDR(bh)->h_refcount = cpu_to_le32(
 			le32_to_cpu(HDR(bh)->h_refcount) - 1);
diff -puN fs/ext3/acl.c~xattr-cleanup fs/ext3/acl.c
--- 25/fs/ext3/acl.c~xattr-cleanup	2003-07-02 16:35:37.000000000 -0700
+++ 25-akpm/fs/ext3/acl.c	2003-07-02 16:35:37.000000000 -0700
@@ -1,7 +1,7 @@
 /*
  * linux/fs/ext3/acl.c
  *
- * Copyright (C) 2001 by Andreas Gruenbacher, <a.gruenbacher@computer.org>
+ * Copyright (C) 2001-2003 Andreas Gruenbacher, <agruen@suse.de>
  */
 
 #include <linux/init.h>
@@ -20,7 +20,7 @@ static struct posix_acl *
 ext3_acl_from_disk(const void *value, size_t size)
 {
 	const char *end = (char *)value + size;
-	int n, count;
+	size_t n, count;
 	struct posix_acl *acl;
 
 	if (!value)
@@ -86,7 +86,7 @@ ext3_acl_to_disk(const struct posix_acl 
 {
 	ext3_acl_header *ext_acl;
 	char *e;
-	int n;
+	size_t n;
 
 	*size = ext3_acl_size(acl->a_count);
 	ext_acl = (ext3_acl_header *)kmalloc(sizeof(ext3_acl_header) +
@@ -133,10 +133,11 @@ fail:
 static struct posix_acl *
 ext3_get_acl(struct inode *inode, int type)
 {
+	const size_t max_size = ext3_acl_size(EXT3_ACL_MAX_ENTRIES);
+	struct ext3_inode_info *ei = EXT3_I(inode);
 	int name_index;
 	char *value;
-	struct posix_acl *acl, **p_acl;
-	const size_t size = ext3_acl_size(EXT3_ACL_MAX_ENTRIES);
+	struct posix_acl *acl;
 	int retval;
 
 	if (!test_opt(inode->i_sb, POSIX_ACL))
@@ -144,36 +145,43 @@ ext3_get_acl(struct inode *inode, int ty
 
 	switch(type) {
 		case ACL_TYPE_ACCESS:
-			p_acl = &EXT3_I(inode)->i_acl;
+			if (ei->i_acl != EXT3_ACL_NOT_CACHED)
+				return posix_acl_dup(ei->i_acl);
 			name_index = EXT3_XATTR_INDEX_POSIX_ACL_ACCESS;
 			break;
 
 		case ACL_TYPE_DEFAULT:
-			p_acl = &EXT3_I(inode)->i_default_acl;
+			if (ei->i_default_acl != EXT3_ACL_NOT_CACHED)
+				return posix_acl_dup(ei->i_default_acl);
 			name_index = EXT3_XATTR_INDEX_POSIX_ACL_DEFAULT;
 			break;
 
 		default:
 			return ERR_PTR(-EINVAL);
 	}
-	if (*p_acl != EXT3_ACL_NOT_CACHED)
-		return posix_acl_dup(*p_acl);
-	value = kmalloc(size, GFP_KERNEL);
+	value = kmalloc(max_size, GFP_KERNEL);
 	if (!value)
 		return ERR_PTR(-ENOMEM);
 
-	retval = ext3_xattr_get(inode, name_index, "", value, size);
-
-	if (retval == -ENODATA || retval == -ENOSYS)
-		*p_acl = acl = NULL;
-	else if (retval < 0)
-		acl = ERR_PTR(retval);
-	else {
+	retval = ext3_xattr_get(inode, name_index, "", value, max_size);
+	acl = ERR_PTR(retval);
+	if (retval > 0)
 		acl = ext3_acl_from_disk(value, retval);
-		if (!IS_ERR(acl))
-			*p_acl = posix_acl_dup(acl);
-	}
+	else if (retval == -ENODATA || retval == -ENOSYS)
+		acl = NULL;
 	kfree(value);
+
+	if (!IS_ERR(acl)) {
+		switch(type) {
+			case ACL_TYPE_ACCESS:
+				ei->i_acl = posix_acl_dup(acl);
+				break;
+
+			case ACL_TYPE_DEFAULT:
+				ei->i_default_acl = posix_acl_dup(acl);
+				break;
+		}
+	}
 	return acl;
 }
 
@@ -186,9 +194,9 @@ static int
 ext3_set_acl(handle_t *handle, struct inode *inode, int type,
 	     struct posix_acl *acl)
 {
+	struct ext3_inode_info *ei = EXT3_I(inode);
 	int name_index;
 	void *value = NULL;
-	struct posix_acl **p_acl;
 	size_t size;
 	int error;
 
@@ -198,7 +206,6 @@ ext3_set_acl(handle_t *handle, struct in
 	switch(type) {
 		case ACL_TYPE_ACCESS:
 			name_index = EXT3_XATTR_INDEX_POSIX_ACL_ACCESS;
-			p_acl = &EXT3_I(inode)->i_acl;
 			if (acl) {
 				mode_t mode = inode->i_mode;
 				error = posix_acl_equiv_mode(acl, &mode);
@@ -215,7 +222,6 @@ ext3_set_acl(handle_t *handle, struct in
 
 		case ACL_TYPE_DEFAULT:
 			name_index = EXT3_XATTR_INDEX_POSIX_ACL_DEFAULT;
-			p_acl = &EXT3_I(inode)->i_default_acl;
 			if (!S_ISDIR(inode->i_mode))
 				return acl ? -EACCES : 0;
 			break;
@@ -231,14 +237,25 @@ ext3_set_acl(handle_t *handle, struct in
 			return (int)PTR_ERR(value);
 	}
 
-	error = ext3_xattr_set_handle(handle, inode, name_index, "", value, size, 0);
+	error = ext3_xattr_set_handle(handle, inode, name_index, "",
+				      value, size, 0);
 
 	if (value)
 		kfree(value);
 	if (!error) {
-		if (*p_acl && *p_acl != EXT3_ACL_NOT_CACHED)
-			posix_acl_release(*p_acl);
-		*p_acl = posix_acl_dup(acl);
+		switch(type) {
+			case ACL_TYPE_ACCESS:
+				if (ei->i_acl != EXT3_ACL_NOT_CACHED)
+					posix_acl_release(ei->i_acl);
+				ei->i_acl = posix_acl_dup(acl);
+				break;
+
+			case ACL_TYPE_DEFAULT:
+				if (ei->i_default_acl != EXT3_ACL_NOT_CACHED)
+					posix_acl_release(ei->i_default_acl);
+				ei->i_default_acl = posix_acl_dup(acl);
+				break;
+		}
 	}
 	return error;
 }
@@ -258,11 +275,13 @@ __ext3_permission(struct inode *inode, i
 	if (current->fsuid == inode->i_uid) {
 		mode >>= 6;
 	} else if (test_opt(inode->i_sb, POSIX_ACL)) {
-		/* ACL can't contain additional permissions if
-		   the ACL_MASK entry is 0 */
-		if (!(mode & S_IRWXG))
+		struct ext3_inode_info *ei = EXT3_I(inode);
+
+		/* The access ACL cannot grant access if the group class
+		   permission bits don't contain all requested permissions. */
+		if (((mode >> 3) & mask & S_IRWXO) != mask)
 			goto check_groups;
-		if (EXT3_I(inode)->i_acl == EXT3_ACL_NOT_CACHED) {
+		if (ei->i_acl == EXT3_ACL_NOT_CACHED) {
 			struct posix_acl *acl;
 
 			if (lock) {
@@ -275,12 +294,11 @@ __ext3_permission(struct inode *inode, i
 			if (IS_ERR(acl))
 				return PTR_ERR(acl);
 			posix_acl_release(acl);
-			if (EXT3_I(inode)->i_acl == EXT3_ACL_NOT_CACHED)
+			if (ei->i_acl == EXT3_ACL_NOT_CACHED)
 				return -EIO;
 		}
-		if (EXT3_I(inode)->i_acl) {
-			int error = posix_acl_permission(inode,
-				EXT3_I(inode)->i_acl, mask);
+		if (ei->i_acl) {
+			int error = posix_acl_permission(inode, ei->i_acl,mask);
 			if (error == -EACCES)
 				goto check_capabilities;
 			return error;
diff -puN fs/ext3/xattr.c~xattr-cleanup fs/ext3/xattr.c
--- 25/fs/ext3/xattr.c~xattr-cleanup	2003-07-02 16:35:37.000000000 -0700
+++ 25-akpm/fs/ext3/xattr.c	2003-07-02 16:35:37.000000000 -0700
@@ -1,7 +1,7 @@
 /*
  * linux/fs/ext3/xattr.c
  *
- * Copyright (C) 2001 by Andreas Gruenbacher, <a.gruenbacher@computer.org>
+ * Copyright (C) 2001-2003 Andreas Gruenbacher, <agruen@suse.de>
  *
  * Fix by Harrison Xing <harrison@mountainviewdata.com>.
  * Ext3 code with a lot of help from Eric Jarman <ejarman@acm.org>.
@@ -63,8 +63,6 @@
 #include "xattr.h"
 #include "acl.h"
 
-#define EXT3_EA_USER "user."
-
 #define HDR(bh) ((struct ext3_xattr_header *)((bh)->b_data))
 #define ENTRY(ptr) ((struct ext3_xattr_entry *)(ptr))
 #define FIRST_ENTRY(bh) ENTRY(HDR(bh)+1)
@@ -79,8 +77,9 @@
 	} while (0)
 # define ea_bdebug(bh, f...) do { \
 		char b[BDEVNAME_SIZE]; \
-		printk(KERN_DEBUG "block %s:%ld: ", \
-			bdevname(bh->b_bdev, b), bh->b_blocknr); \
+		printk(KERN_DEBUG "block %s:%lu: ", \
+			bdevname(bh->b_bdev, b), \
+			(unsigned long) bh->b_blocknr); \
 		printk(f); \
 		printk("\n"); \
 	} while (0)
@@ -271,9 +270,9 @@ ext3_xattr_get(struct inode *inode, int 
 {
 	struct buffer_head *bh = NULL;
 	struct ext3_xattr_entry *entry;
-	unsigned int size;
+	size_t name_len, size;
 	char *end;
-	int name_len, error;
+	int error;
 
 	ea_idebug(inode, "name=%d.%s, buffer=%p, buffer_size=%ld",
 		  name_index, name, buffer, (long)buffer_size);
@@ -369,7 +368,7 @@ ext3_xattr_list(struct inode *inode, cha
 {
 	struct buffer_head *bh = NULL;
 	struct ext3_xattr_entry *entry;
-	unsigned int size = 0;
+	size_t size = 0;
 	char *buf, *end;
 	int error;
 
@@ -478,8 +477,8 @@ ext3_xattr_set_handle(handle_t *handle, 
 	struct buffer_head *bh = NULL;
 	struct ext3_xattr_header *header = NULL;
 	struct ext3_xattr_entry *here, *last;
-	unsigned int name_len;
-	int min_offs = sb->s_blocksize, not_found = 1, free, error;
+	size_t name_len, free, min_offs = sb->s_blocksize;
+	int not_found = 1, error;
 	char *end;
 
 	/*
@@ -536,7 +535,7 @@ bad_block:		ext3_error(sb, "ext3_xattr_s
 			if ((char *)next >= end)
 				goto bad_block;
 			if (!here->e_value_block && here->e_value_size) {
-				int offs = le16_to_cpu(here->e_value_offs);
+				size_t offs = le16_to_cpu(here->e_value_offs);
 				if (offs < min_offs)
 					min_offs = offs;
 			}
@@ -556,7 +555,7 @@ bad_block:		ext3_error(sb, "ext3_xattr_s
 			if ((char *)next >= end)
 				goto bad_block;
 			if (!last->e_value_block && last->e_value_size) {
-				int offs = le16_to_cpu(last->e_value_offs);
+				size_t offs = le16_to_cpu(last->e_value_offs);
 				if (offs < min_offs)
 					min_offs = offs;
 			}
@@ -580,25 +579,23 @@ bad_block:		ext3_error(sb, "ext3_xattr_s
 		error = 0;
 		if (value == NULL)
 			goto cleanup;
-		else
-			free -= EXT3_XATTR_LEN(name_len);
 	} else {
 		/* Request to create an existing attribute? */
 		error = -EEXIST;
 		if (flags & XATTR_CREATE)
 			goto cleanup;
 		if (!here->e_value_block && here->e_value_size) {
-			unsigned int size = le32_to_cpu(here->e_value_size);
+			size_t size = le32_to_cpu(here->e_value_size);
 
 			if (le16_to_cpu(here->e_value_offs) + size > 
 			    sb->s_blocksize || size > sb->s_blocksize)
 				goto bad_block;
 			free += EXT3_XATTR_SIZE(size);
 		}
+		free += EXT3_XATTR_LEN(name_len);
 	}
-	free -= EXT3_XATTR_SIZE(value_len);
 	error = -ENOSPC;
-	if (free < 0)
+	if (free < EXT3_XATTR_LEN(name_len) + EXT3_XATTR_SIZE(value_len))
 		goto cleanup;
 
 	/* Here we know that we can set the new attribute. */
@@ -639,8 +636,8 @@ bad_block:		ext3_error(sb, "ext3_xattr_s
 
 	if (not_found) {
 		/* Insert the new name. */
-		int size = EXT3_XATTR_LEN(name_len);
-		int rest = (char *)last - (char *)here;
+		size_t size = EXT3_XATTR_LEN(name_len);
+		size_t rest = (char *)last - (char *)here;
 		memmove((char *)here + size, here, rest);
 		memset(here, 0, size);
 		here->e_name_index = name_index;
@@ -650,7 +647,7 @@ bad_block:		ext3_error(sb, "ext3_xattr_s
 		/* Remove the old value. */
 		if (!here->e_value_block && here->e_value_size) {
 			char *first_val = (char *)header + min_offs;
-			int offs = le16_to_cpu(here->e_value_offs);
+			size_t offs = le16_to_cpu(here->e_value_offs);
 			char *val = (char *)header + offs;
 			size_t size = EXT3_XATTR_SIZE(
 				le32_to_cpu(here->e_value_size));
@@ -662,7 +659,7 @@ bad_block:		ext3_error(sb, "ext3_xattr_s
 			/* Adjust all value offsets. */
 			last = ENTRY(header+1);
 			while (!IS_LAST_ENTRY(last)) {
-				int o = le16_to_cpu(last->e_value_offs);
+				size_t o = le16_to_cpu(last->e_value_offs);
 				if (!last->e_value_block && o < offs)
 					last->e_value_offs =
 						cpu_to_le16(o + size);
@@ -678,7 +675,7 @@ bad_block:		ext3_error(sb, "ext3_xattr_s
 				goto cleanup;
 			} else {
 				/* Remove the old name. */
-				int size = EXT3_XATTR_LEN(name_len);
+				size_t size = EXT3_XATTR_LEN(name_len);
 				last = ENTRY((char *)last - size);
 				memmove(here, (char*)here + size,
 					(char*)last - (char*)here);
@@ -733,9 +730,9 @@ ext3_xattr_set_handle2(handle_t *handle,
 			 * The old block will be released after updating
 			 * the inode.
 			 */
-			ea_bdebug(new_bh, "%s block %ld",
+			ea_bdebug(new_bh, "%s block %lu",
 				(old_bh == new_bh) ? "keeping" : "reusing",
-				new_bh->b_blocknr);
+				(unsigned long) new_bh->b_blocknr);
 
 			error = -EDQUOT;
 			if (DQUOT_ALLOC_BLOCK(inode, 1))
@@ -759,7 +756,7 @@ ext3_xattr_set_handle2(handle_t *handle,
 					EXT3_SB(sb)->s_es->s_first_data_block) +
 				EXT3_I(inode)->i_block_group *
 				EXT3_BLOCKS_PER_GROUP(sb);
-			int block  = ext3_new_block(handle,
+			int block = ext3_new_block(handle,
 				inode, goal, 0, 0, &error);
 			if (error)
 				goto cleanup;
@@ -895,8 +892,8 @@ ext3_xattr_delete_inode(handle_t *handle
 	if (HDR(bh)->h_refcount == cpu_to_le32(1)) {
 		ext3_xattr_cache_remove(bh);
 		ext3_free_blocks(handle, inode, EXT3_I(inode)->i_file_acl, 1);
+		get_bh(bh);
 		ext3_forget(handle, 1, inode, bh, EXT3_I(inode)->i_file_acl);
-		bh = NULL;
 	} else {
 		HDR(bh)->h_refcount = cpu_to_le32(
 			le32_to_cpu(HDR(bh)->h_refcount) - 1);

_
