Skip to contentSkip to conversation

ext2/3 updates for 2.5.44 (6/11): ext2 xattr support

PATCH New [email protected] 1 participant 1 message Oct 20, 2002

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

PATCH 1/1 ext2/3 updates for 2.5.44 (6/11): ext2 xattr support

# The following is the BitKeeper ChangeSet Log
# --------------------------------------------
# 02/10/20 [email protected] 1.815
# Port of (bugfixed) 0.8.50 xattr-ext2 to 2.5 (w/ hch cleanups. mbcache API) #
# This patch adds extended attribute support to the ext2 filesystem. This

# uses the generic extended attribute patch which was developed by Andreas
# Gruenbacher and the XFS team.  As a result, the user space utilities
# which work for XFS will also work with these patches.
# --------------------------------------------
#
# fs/Config.help          |    7 
# fs/Config.in            |    1 
# fs/ext2/Makefile        |    6 
# fs/ext2/ext2.h          |    2 
# fs/ext2/file.c          |    7 
# fs/ext2/ialloc.c        |    4 
# fs/ext2/inode.c         |   39 -
# fs/ext2/namei.c         |   16 
# fs/ext2/super.c         |   20 
# fs/ext2/symlink.c       |   14 
# fs/ext2/xattr.c         | 1118 ++++++++++++++++++++++++++++++++++++++++++++++++
# fs/ext2/xattr.h         |  135 +++++
# fs/ext2/xattr_user.c    |   98 ++++
# include/linux/ext2_fs.h |   28 -
# 14 files changed, 1446 insertions(+), 49 deletions(-)
#
diff -Nru a/fs/Config.help b/fs/Config.help
--- a/fs/Config.help	Sun Oct 20 04:41:19 2002
+++ b/fs/Config.help	Sun Oct 20 04:41:19 2002
@@ -123,6 +123,13 @@
   be compiled as a module, and so this could be dangerous.  Most
   everyone wants to say Y here.

+CONFIG_EXT2_FS_XATTR

+  Extended attributes are name:value pairs associated with inodes by
+  the kernel or by users (see the attr(5) manual page, or visit
+  <http://acl.bestbits.at/> for details).

+
+ If unsure, say N.
+
CONFIG_EXT3_FS
This is the journaling version of the Second extended file system (often called ext3), the de facto standard Linux file system

fs/Config.in +1 -0
diff -Nru a/fs/Config.in b/fs/Config.in
@@ -93,6 +93,7 @@
 tristate 'ROM file system support' CONFIG_ROMFS_FS
 
 tristate 'Second extended fs support' CONFIG_EXT2_FS
+dep_mbool '  Ext2 extended attributes' CONFIG_EXT2_FS_XATTR $CONFIG_EXT2_FS
 
 tristate 'System V/Xenix/V7/Coherent file system support' CONFIG_SYSV_FS
 
fs/ext2/Makefile +6 -0
diff -Nru a/fs/ext2/Makefile b/fs/ext2/Makefile
@@ -7,4 +7,10 @@
 ext2-objs := balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o \
 	     ioctl.o namei.o super.o symlink.o
 
+export-objs += xattr.o
+
+ifeq ($(CONFIG_EXT2_FS_XATTR),y)
+ext2-objs += xattr.o xattr_user.o
+endif
+
 include $(TOPDIR)/Rules.make
fs/ext2/ext2.h +2 -0
diff -Nru a/fs/ext2/ext2.h b/fs/ext2/ext2.h
@@ -117,6 +117,8 @@
 
 /* namei.c */
 extern struct inode_operations ext2_dir_inode_operations;
+extern struct inode_operations ext2_special_inode_operations;
 
 /* symlink.c */
 extern struct inode_operations ext2_fast_symlink_inode_operations;
+extern struct inode_operations ext2_symlink_inode_operations;
fs/ext2/file.c +6 -1
diff -Nru a/fs/ext2/file.c b/fs/ext2/file.c
@@ -18,8 +18,9 @@
  * 	([email protected])
  */
 
-#include "ext2.h"
 #include <linux/time.h>
+#include "ext2.h"
+#include "xattr.h"
 
 /*
  * Called when an inode is released. Note that this is different
@@ -55,4 +56,8 @@
 
 struct inode_operations ext2_file_inode_operations = {
 	.truncate	= ext2_truncate,
+	.setxattr	= ext2_setxattr,
+	.getxattr	= ext2_getxattr,
+	.listxattr	= ext2_listxattr,
+	.removexattr	= ext2_removexattr,
 };
fs/ext2/ialloc.c +3 -1
diff -Nru a/fs/ext2/ialloc.c b/fs/ext2/ialloc.c
@@ -13,11 +13,12 @@
  */
 
 #include <linux/config.h>
-#include "ext2.h"
 #include <linux/quotaops.h>
 #include <linux/sched.h>
 #include <linux/backing-dev.h>
 #include <linux/buffer_head.h>
+#include "ext2.h"
+#include "xattr.h"
 
 /*
  * ialloc.c contains the inodes allocation and deallocation routines
@@ -97,6 +98,7 @@
 	 */
 	if (!is_bad_inode(inode)) {
 		/* Quota is already initialized in iput() */
+		ext2_xattr_delete_inode(inode);
 	    	DQUOT_FREE_INODE(inode);
 		DQUOT_DROP(inode);
 	}
fs/ext2/inode.c +22 -17
diff -Nru a/fs/ext2/inode.c b/fs/ext2/inode.c
@@ -39,6 +39,18 @@
 static int ext2_update_inode(struct inode * inode, int do_sync);
 
 /*
+ * Test whether an inode is a fast symlink.
+ */
+static inline int ext2_inode_is_fast_symlink(struct inode *inode)
+{
+	int ea_blocks = EXT2_I(inode)->i_file_acl ?
+		(inode->i_sb->s_blocksize >> 9) : 0;
+
+	return (S_ISLNK(inode->i_mode) &&
+		inode->i_blocks - ea_blocks == 0);
+}
+
+/*
  * Called at each iput()
  */
 void ext2_put_inode (struct inode * inode)
@@ -51,9 +63,7 @@
  */
 void ext2_delete_inode (struct inode * inode)
 {
-	if (is_bad_inode(inode) ||
-	    inode->i_ino == EXT2_ACL_IDX_INO ||
-	    inode->i_ino == EXT2_ACL_DATA_INO)
+	if (is_bad_inode(inode))
 		goto no_delete;
 	EXT2_I(inode)->i_dtime	= CURRENT_TIME;
 	mark_inode_dirty(inode);
@@ -843,6 +853,8 @@
 	if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
 	    S_ISLNK(inode->i_mode)))
 		return;
+	if (ext2_inode_is_fast_symlink(inode))
+		return;
 	if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
 		return;
 
@@ -929,8 +941,7 @@
 	struct ext2_group_desc * gdp;
 
 	*p = NULL;
-	if ((ino != EXT2_ROOT_INO && ino != EXT2_ACL_IDX_INO &&
-	     ino != EXT2_ACL_DATA_INO && ino < EXT2_FIRST_INO(sb)) ||
+	if ((ino != EXT2_ROOT_INO && ino < EXT2_FIRST_INO(sb)) ||
 	    ino > le32_to_cpu(EXT2_SB(sb)->s_es->s_inodes_count))
 		goto Einval;
 
@@ -1026,9 +1037,7 @@
 	for (n = 0; n < EXT2_N_BLOCKS; n++)
 		ei->i_data[n] = raw_inode->i_block[n];
 
-	if (ino == EXT2_ACL_IDX_INO || ino == EXT2_ACL_DATA_INO)
-		/* Nothing to do */ ;
-	else if (S_ISREG(inode->i_mode)) {
+	if (S_ISREG(inode->i_mode)) {
 		inode->i_op = &ext2_file_inode_operations;
 		inode->i_fop = &ext2_file_operations;
 		inode->i_mapping->a_ops = &ext2_aops;
@@ -1037,15 +1046,17 @@
 		inode->i_fop = &ext2_dir_operations;
 		inode->i_mapping->a_ops = &ext2_aops;
 	} else if (S_ISLNK(inode->i_mode)) {
-		if (!inode->i_blocks)
+		if (ext2_inode_is_fast_symlink(inode))
 			inode->i_op = &ext2_fast_symlink_inode_operations;
 		else {
-			inode->i_op = &page_symlink_inode_operations;
+			inode->i_op = &ext2_symlink_inode_operations;
 			inode->i_mapping->a_ops = &ext2_aops;
 		}
-	} else 
+	} else {
+		inode->i_op = &ext2_special_inode_operations;
 		init_special_inode(inode, inode->i_mode,
 				   le32_to_cpu(raw_inode->i_block[0]));
+	}
 	brelse (bh);
 	if (ei->i_flags & EXT2_SYNC_FL)
 		inode->i_flags |= S_SYNC;
@@ -1082,12 +1093,6 @@
 	if (ei->i_state & EXT2_STATE_NEW)
 		memset(raw_inode, 0, EXT2_SB(sb)->s_inode_size);
 
-	if (ino == EXT2_ACL_IDX_INO || ino == EXT2_ACL_DATA_INO) {
-		ext2_error (sb, "ext2_write_inode", "bad inode number: %lu",
-			    (unsigned long) ino);
-		brelse(bh);
-		return -EIO;
-	}
 	raw_inode->i_mode = cpu_to_le16(inode->i_mode);
 	if (!(test_opt(sb, NO_UID32))) {
 		raw_inode->i_uid_low = cpu_to_le16(low_16_bits(uid));
fs/ext2/namei.c +14 -2
diff -Nru a/fs/ext2/namei.c b/fs/ext2/namei.c
@@ -29,8 +29,9 @@
  *        David S. Miller ([email protected]), 1995
  */
 
-#include "ext2.h"
 #include <linux/pagemap.h>
+#include "ext2.h"
+#include "xattr.h"
 
 /*
  * Couple of helper functions - make the code slightly cleaner.
@@ -162,7 +163,7 @@
 
 	if (l > sizeof (EXT2_I(inode)->i_data)) {
 		/* slow symlink */
-		inode->i_op = &page_symlink_inode_operations;
+		inode->i_op = &ext2_symlink_inode_operations;
 		inode->i_mapping->a_ops = &ext2_aops;
 		err = page_symlink(inode, symname, l);
 		if (err)
@@ -368,4 +369,15 @@
 	.rmdir		= ext2_rmdir,
 	.mknod		= ext2_mknod,
 	.rename		= ext2_rename,
+	.setxattr	= ext2_setxattr,
+	.getxattr	= ext2_getxattr,
+	.listxattr	= ext2_listxattr,
+	.removexattr	= ext2_removexattr,
+};
+
+struct inode_operations ext2_special_inode_operations = {
+	.setxattr	= ext2_setxattr,
+	.getxattr	= ext2_getxattr,
+	.listxattr	= ext2_listxattr,
+	.removexattr	= ext2_removexattr,
 };
fs/ext2/super.c +18 -2
diff -Nru a/fs/ext2/super.c b/fs/ext2/super.c
@@ -19,7 +19,6 @@
 #include <linux/config.h>
 #include <linux/module.h>
 #include <linux/string.h>
-#include "ext2.h"
 #include <linux/slab.h>
 #include <linux/init.h>
 #include <linux/blkdev.h>
@@ -27,6 +26,8 @@
 #include <linux/buffer_head.h>
 #include <linux/smp_lock.h>
 #include <asm/uaccess.h>
+#include "ext2.h"
+#include "xattr.h"
 
 
 static void ext2_sync_super(struct super_block *sb,
@@ -127,6 +128,7 @@
 	int i;
 	struct ext2_sb_info *sbi = EXT2_SB(sb);
 
+	ext2_xattr_put_super(sb);
 	if (!(sb->s_flags & MS_RDONLY)) {
 		struct ext2_super_block *es = sbi->s_es;
 
@@ -278,6 +280,13 @@
 			continue;
 		if ((value = strchr (this_char, '=')) != NULL)
 			*value++ = 0;
+#ifdef CONFIG_EXT2_FS_XATTR
+		if (!strcmp (this_char, "user_xattr"))
+			set_opt (sbi->s_mount_opt, XATTR_USER);
+		else if (!strcmp (this_char, "nouser_xattr"))
+			clear_opt (sbi->s_mount_opt, XATTR_USER);
+		else
+#endif
 		if (!strcmp (this_char, "bsddf"))
 			clear_opt (sbi->s_mount_opt, MINIX_DF);
 		else if (!strcmp (this_char, "nouid32")) {
@@ -560,6 +569,8 @@
 		set_opt(sbi->s_mount_opt, GRPID);
 	if (def_mount_opts & EXT2_DEFM_UID16)
 		set_opt(sbi->s_mount_opt, NO_UID32);
+	if (def_mount_opts & EXT2_DEFM_XATTR_USER)
+		set_opt(sbi->s_mount_opt, XATTR_USER);
 	
 	if (le16_to_cpu(sbi->s_es->s_errors) == EXT2_ERRORS_PANIC)
 		set_opt(sbi->s_mount_opt, ERRORS_PANIC);
@@ -917,7 +928,10 @@
 
 static int __init init_ext2_fs(void)
 {
-	int err = init_inodecache();
+	int err = init_ext2_xattr();
+	if (err)
+		return err;
+	err = init_inodecache();
 	if (err)
 		goto out1;
         err = register_filesystem(&ext2_fs_type);
@@ -927,6 +941,7 @@
 out:
 	destroy_inodecache();
 out1:
+	exit_ext2_xattr();
 	return err;
 }
 
@@ -934,6 +949,7 @@
 {
 	unregister_filesystem(&ext2_fs_type);
 	destroy_inodecache();
+	exit_ext2_xattr();
 }
 
 module_init(init_ext2_fs)
fs/ext2/symlink.c +14 -0
diff -Nru a/fs/ext2/symlink.c b/fs/ext2/symlink.c
@@ -18,6 +18,7 @@
  */
 
 #include "ext2.h"
+#include "xattr.h"
 
 static int ext2_readlink(struct dentry *dentry, char *buffer, int buflen)
 {
@@ -31,7 +32,20 @@
 	return vfs_follow_link(nd, (char *)ei->i_data);
 }
 
+struct inode_operations ext2_symlink_inode_operations = {
+	.readlink	= page_readlink,
+	.follow_link	= page_follow_link,
+	.setxattr	= ext2_setxattr,
+	.getxattr	= ext2_getxattr,
+	.listxattr	= ext2_listxattr,
+	.removexattr	= ext2_removexattr,
+};
+ 
 struct inode_operations ext2_fast_symlink_inode_operations = {
 	.readlink	= ext2_readlink,
 	.follow_link	= ext2_follow_link,
+	.setxattr	= ext2_setxattr,
+	.getxattr	= ext2_getxattr,
+	.listxattr	= ext2_listxattr,
+	.removexattr	= ext2_removexattr,
 };
fs/ext2/xattr.c new file +1118 -0

1,118 lines not on this page · raw message

fs/ext2/xattr.h new file +135 -0

135 lines not on this page · raw message

fs/ext2/xattr_user.c new file +98 -0

98 lines not on this page · raw message

include/linux/ext2_fs.h +2 -26
diff -Nru a/include/linux/ext2_fs.h b/include/linux/ext2_fs.h
@@ -58,8 +58,6 @@
  */
 #define	EXT2_BAD_INO		 1	/* Bad blocks inode */
 #define EXT2_ROOT_INO		 2	/* Root inode */
-#define EXT2_ACL_IDX_INO	 3	/* ACL inode */
-#define EXT2_ACL_DATA_INO	 4	/* ACL inode */
 #define EXT2_BOOT_LOADER_INO	 5	/* Boot loader inode */
 #define EXT2_UNDEL_DIR_INO	 6	/* Undelete directory inode */
 
@@ -99,7 +97,6 @@
 #else
 # define EXT2_BLOCK_SIZE(s)		(EXT2_MIN_BLOCK_SIZE << (s)->s_log_block_size)
 #endif
-#define EXT2_ACLE_PER_BLOCK(s)		(EXT2_BLOCK_SIZE(s) / sizeof (struct ext2_acl_entry))
 #define	EXT2_ADDR_PER_BLOCK(s)		(EXT2_BLOCK_SIZE(s) / sizeof (__u32))
 #ifdef __KERNEL__
 # define EXT2_BLOCK_SIZE_BITS(s)	((s)->s_blocksize_bits)
@@ -134,28 +131,6 @@
 #endif
 
 /*
- * ACL structures
- */
-struct ext2_acl_header	/* Header of Access Control Lists */
-{
-	__u32	aclh_size;
-	__u32	aclh_file_count;
-	__u32	aclh_acle_count;
-	__u32	aclh_first_acle;
-};
-
-struct ext2_acl_entry	/* Access Control List Entry */
-{
-	__u32	acle_size;
-	__u16	acle_perms;	/* Access permissions */
-	__u16	acle_type;	/* Type of entry */
-	__u16	acle_tag;	/* User or group identity */
-	__u16	acle_pad1;
-	__u32	acle_next;	/* Pointer on next entry for the */
-					/* same inode or on next free entry */
-};
-
-/*
  * Structure of a blocks group descriptor
  */
 struct ext2_group_desc
@@ -332,6 +307,7 @@
 #define EXT2_MOUNT_ERRORS_PANIC		0x0040	/* Panic on errors */
 #define EXT2_MOUNT_MINIX_DF		0x0080	/* Mimics the Minix statfs */
 #define EXT2_MOUNT_NO_UID32		0x0200  /* Disable 32-bit UIDs */
+#define EXT2_MOUNT_XATTR_USER		0x4000	/* Extended user attributes */
 
 #define clear_opt(o, opt)		o &= ~EXT2_MOUNT_##opt
 #define set_opt(o, opt)			o |= EXT2_MOUNT_##opt
@@ -489,7 +465,7 @@
 #define EXT2_FEATURE_INCOMPAT_META_BG		0x0010
 #define EXT2_FEATURE_INCOMPAT_ANY		0xffffffff
 
-#define EXT2_FEATURE_COMPAT_SUPP	0
+#define EXT2_FEATURE_COMPAT_SUPP	EXT2_FEATURE_COMPAT_EXT_ATTR
 #define EXT2_FEATURE_INCOMPAT_SUPP	(EXT2_FEATURE_INCOMPAT_FILETYPE| \
 					 EXT2_FEATURE_INCOMPAT_META_BG)
 #define EXT2_FEATURE_RO_COMPAT_SUPP	(EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER| \