6/11 Ext2/3 Updates: Extended attributes, ACL, etc.
Subsystems (2)
PATCH 1/1 6/11 Ext2/3 Updates: Extended attributes, ACL, etc.
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 | 102 ++++ include/linux/ext2_fs.h | 28 - 14 files changed, 1450 insertions(+), 49 deletions(-)
fs/Config.help +7 -0
@@ -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
@@ -96,6 +96,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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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 +102 -0
102 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
@@ -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| \