Add extended attributes to ext2/3
Subsystems (2)
RFC PATCH 4/4 Add extended attributes to ext2/3
This is the fourth of four patches which add extended attribute support to the ext2 and ext3 filesystems. Please comment and bleed.
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.
# This is a BitKeeper generated patch for the following project:
# Project Name: Linux kernel tree
#
# fs/Config.help | 24 # fs/Config.in | 5 # fs/ext2/Makefile | 4 # fs/ext2/ext2.h | 3 # fs/ext2/file.c | 4 # fs/ext2/ialloc.c | 1 # fs/ext2/inode.c | 38 - # fs/ext2/namei.c | 13 # fs/ext2/super.c | 24 # fs/ext2/symlink.c | 13 # fs/ext2/xattr.c | 1228 +++++++++++++++++++++++++++++++++++++++++++++ # fs/ext2/xattr_user.c | 100 +++ # include/linux/ext2_fs.h | 28 - # include/linux/ext2_xattr.h | 157 +++++
#
# The following is the BitKeeper ChangeSet Log
# --------------------------------------------
# 02/10/05 [email protected] 1.668
# Port of 0.8.50 xattr-ext2 to 2.5.
#
# Enable EA's by default.
# --------------------------------------------
#
fs/Config.help +24 -0
@@ -123,6 +123,30 @@ be compiled as a module, and so this could be dangerous. Most everyone wants to say Y here. +Ext2 extended attributes +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. + +Ext2 extended attribute block sharing +CONFIG_EXT2_FS_XATTR_SHARING + This options enables code for sharing identical extended attribute + blocks among multiple inodes. + + Usually, say Y. + +Ext2 extended user attributes +CONFIG_EXT2_FS_XATTR_USER + This option enables extended user attributes on ext2. Processes can + associate extended user attributes with inodes to store additional + information such as the character encoding of files, etc. (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 +5 -0
@@ -97,6 +97,11 @@ tristate 'ROM file system support' CONFIG_ROMFS_FS tristate 'Second extended fs support' CONFIG_EXT2_FS +if [ "$CONFIG_EXT2_FS" != "n" ] ; then + define_tristate CONFIG_EXT2_FS_XATTR $CONFIG_EXT2_FS + define_bool CONFIG_EXT2_FS_XATTR_SHARING y + define_bool CONFIG_EXT2_FS_XATTR_USER y +fi tristate 'System V/Xenix/V7/Coherent file system support' CONFIG_SYSV_FS
fs/ext2/Makefile +4 -0
@@ -7,4 +7,8 @@ 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 +obj-$(CONFIG_EXT2_FS_XATTR) += xattr.o +obj-$(CONFIG_EXT2_FS_XATTR_USER) += xattr_user.o + include $(TOPDIR)/Rules.make
fs/ext2/ext2.h +3 -0
@@ -1,5 +1,6 @@#include <linux/fs.h> #include <linux/ext2_fs.h> +#include <linux/ext2_xattr.h> /* * second extended file system inode data in memory
@@ -110,6 +111,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 +4 -0
@@ -53,4 +53,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 +1 -0
@@ -97,6 +97,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 -16
@@ -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);
@@ -848,6 +858,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 ;
@@ -934,8 +946,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;
@@ -1029,9 +1040,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;
@@ -1040,15 +1049,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 ;
@@ -1080,11 +1091,6 @@if (IS_ERR (raw_inode))return -EIO ; -if (ino ==EXT2_ACL_IDX_INO || ino ==EXT2_ACL_DATA_INO ) { -ext2_error (sb,"ext2_write_inode" ,"bad inode number: %lu" , 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 +12 -1
@@ -162,7 +162,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 +368,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 +23 -1
@@ -131,6 +131,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;
@@ -233,6 +234,13 @@continue ;if ((value =strchr (this_char,'=' )) !=NULL ) *value++ =0 ; +#ifdef CONFIG_EXT2_FS_XATTR_USER +if (!strcmp (this_char,"user_xattr" )) +set_opt (*mount_options,XATTR_USER ); +else if (!strcmp (this_char,"nouser_xattr" )) +clear_opt (*mount_options,XATTR_USER ); + else +#endif if (!strcmp (this_char,"bsddf" ))clear_opt (*mount_options,MINIX_DF );else if (!strcmp (this_char,"nouid32" )) {
@@ -487,6 +495,9 @@*/ sbi->s_mount_opt =0 ; +#ifdef CONFIG_EXT2_FS_XATTR_USER +set_opt (EXT2_SB (sb)->s_mount_opt,XATTR_USER ); +#endif if (!parse_options ((char *) data, &sb_block, &resuid, &resgid, &sbi->s_mount_opt)) goto failed_sbi;
@@ -883,7 +894,13 @@static int __init init_ext2_fs (void ) { -int err =init_inodecache (); +int err =init_ext2_xattr (); +if (err) +return err; + err =init_ext2_xattr_user (); +if (err) + goto out2; + err =init_inodecache ();if (err) goto out1; err =register_filesystem (&ext2_fs_type);
@@ -893,6 +910,9 @@ out:destroy_inodecache (); out1: +exit_ext2_xattr_user (); +out2: +exit_ext2_xattr ();return err; }
@@ -900,6 +920,8 @@ {unregister_filesystem (&ext2_fs_type);destroy_inodecache (); +exit_ext2_xattr_user (); +exit_ext2_xattr (); }module_init (init_ext2_fs)
fs/ext2/symlink.c +13 -0
@@ -31,7 +31,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 +1228 -0
1,228 lines not on this page · raw message
fs/ext2/xattr_user.c new file +100 -0
100 lines not on this page · raw message
include/linux/ext2_fs.h +2 -26
@@ -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
@@ -475,7 +451,7 @@#define EXT3_FEATURE_INCOMPAT_JOURNAL_DEV 0x0008#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#define EXT2_FEATURE_RO_COMPAT_SUPP (EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER| \ EXT2_FEATURE_RO_COMPAT_LARGE_FILE| \
include/linux/ext2_xattr.h new file +157 -0
157 lines not on this page · raw message