Add extended attributes to ext2/3
PATCH 3/4 Add extended attributes to ext2/3
This patch adds extended attribute support to the ext3 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.
- Ted
# This is a BitKeeper generated patch for the following project:
# Project Name: Linux kernel tree
#
# fs/Config.help | 7 # fs/Config.in | 1 # fs/ext3/Makefile | 6 # fs/ext3/file.c | 5 # fs/ext3/ialloc.c | 2 # fs/ext3/inode.c | 35 - # fs/ext3/namei.c | 22 # fs/ext3/super.c | 23 # fs/ext3/symlink.c | 16 # fs/ext3/xattr.c | 1191 ++++++++++++++++++++++++++++++++++++++++ # fs/ext3/xattr_user.c | 99 +++ # include/linux/ext3_fs.h | 31 - # include/linux/ext3_jbd.h | 8 # include/linux/ext3_xattr.h | 137 +++++
# 14 files changed, 1535 insertions(+), 48 deletions(-) #
# The following is the BitKeeper ChangeSet Log # --------------------------------------------
# 02/10/14 [email protected] 1.785
# Port of (bugfixed) 0.8.50 xattr-ext3 to 2.5. #
# -------------------------------------------- #
fs/Config.help +7 -0
@@ -154,6 +154,13 @@ of your root partition (the one containing the directory /) cannot be compiled as a module, and so this may be dangerous. +CONFIG_EXT3_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_JBD This is a generic journaling layer for block devices. It is currently used by the ext3 file system, but it could also be used to
fs/Config.in +1 -0
@@ -27,6 +27,7 @@ dep_tristate 'BFS file system support (EXPERIMENTAL)' CONFIG_BFS_FS $CONFIG_EXPERIMENTAL tristate 'Ext3 journalling file system support' CONFIG_EXT3_FS +dep_bool ' Ext3 extended attributes' CONFIG_EXT3_FS_XATTR $CONFIG_EXT3_FS # CONFIG_JBD could be its own option (even modular), but until there are # other users than ext3, we will simply make it be the same as CONFIG_EXT3_FS # dep_tristate ' Journal Block Device support (JBD for ext3)' CONFIG_JBD $CONFIG_EXT3_FS
fs/ext3/Makefile +6 -0
@@ -7,4 +7,10 @@ ext3-objs := balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o \ ioctl.o namei.o super.o symlink.o hash.o +export-objs += xattr.o + +ifeq ($(CONFIG_EXT3_FS_XATTR),y) +ext3-objs += xattr.o xattr_user.o +endif + include $(TOPDIR)/Rules.make
fs/ext3/file.c +5 -0
@@ -22,6 +22,7 @@#include <linux/fs.h> #include <linux/jbd.h> #include <linux/ext3_fs.h> +#include <linux/ext3_xattr.h> #include <linux/ext3_jbd.h> #include <linux/smp_lock.h>
@@ -98,5 +99,9 @@struct inode_operations ext3_file_inode_operations = { .truncate = ext3_truncate, .setattr = ext3_setattr, + .setxattr = ext3_setxattr, + .getxattr = ext3_getxattr, + .listxattr = ext3_listxattr, + .removexattr = ext3_removexattr, };
fs/ext3/ialloc.c +2 -0
@@ -17,6 +17,7 @@#include <linux/jbd.h> #include <linux/ext3_fs.h> #include <linux/ext3_jbd.h> +#include <linux/ext3_xattr.h> #include <linux/stat.h> #include <linux/string.h> #include <linux/quotaops.h>
@@ -118,6 +119,7 @@* as writing the quota to disk may need the lock as well. */ DQUOT_INIT (inode); +ext3_xattr_delete_inode (handle, inode);DQUOT_FREE_INODE (inode);DQUOT_DROP (inode);
fs/ext3/inode.c +22 -13
@@ -42,6 +42,18 @@*/ #undef SEARCH_FROM_ZERO +/* +* Test whether an inode is a fast symlink. +*/ +static inline int ext3_inode_is_fast_symlink (struct inode *inode) +{ +int ea_blocks =EXT3_I (inode)->i_file_acl ? + (inode->i_sb->s_blocksize >>9 ) :0 ; + +return (S_ISLNK (inode->i_mode) && + inode->i_blocks - ea_blocks ==0 ); +} +/* The ext3 forget function must perform a revoke if we are freeing data * which has been journaled. Metadata (eg. indirect blocks) must be * revoked in all cases.
@@ -51,7 +63,7 @@* still needs to be revoked. */ -static int ext3_forget (handle_t *handle,int is_metadata, +int ext3_forget (handle_t *handle,int is_metadata,struct inode *inode,struct buffer_head *bh,int blocknr) {
@@ -167,9 +179,7 @@ {handle_t *handle; -if (is_bad_inode (inode) || - inode->i_ino ==EXT3_ACL_IDX_INO || - inode->i_ino ==EXT3_ACL_DATA_INO ) +if (is_bad_inode (inode)) goto no_delete;lock_kernel ();
@@ -1979,6 +1989,8 @@if (!(S_ISREG (inode->i_mode) ||S_ISDIR (inode->i_mode) ||S_ISLNK (inode->i_mode)))return ; +if (ext3_inode_is_fast_symlink (inode)) +return ;if (IS_APPEND (inode) ||IS_IMMUTABLE (inode))return ;
@@ -2130,8 +2142,6 @@struct ext3_group_desc * gdp;if ((inode->i_ino !=EXT3_ROOT_INO && - inode->i_ino !=EXT3_ACL_IDX_INO && - inode->i_ino !=EXT3_ACL_DATA_INO && inode->i_ino !=EXT3_JOURNAL_INO && inode->i_ino <EXT3_FIRST_INO (inode->i_sb)) || inode->i_ino > le32_to_cpu(
@@ -2263,10 +2273,7 @@brelse (iloc.bh); -if (inode->i_ino ==EXT3_ACL_IDX_INO || - inode->i_ino ==EXT3_ACL_DATA_INO ) -/* Nothing to do */ ; -else if (S_ISREG (inode->i_mode)) { +if (S_ISREG (inode->i_mode)) { inode->i_op = &ext3_file_inode_operations; inode->i_fop = &ext3_file_operations;if (ext3_should_writeback_data (inode))
@@ -2277,18 +2284,20 @@ inode->i_op = &ext3_dir_inode_operations; inode->i_fop = &ext3_dir_operations; }else if (S_ISLNK (inode->i_mode)) { -if (!inode->i_blocks) +if (ext3_inode_is_fast_symlink (inode)) inode->i_op = &ext3_fast_symlink_inode_operations;else { - inode->i_op = &page_symlink_inode_operations; + inode->i_op = &ext3_symlink_inode_operations;if (ext3_should_writeback_data (inode)) inode->i_mapping->a_ops = &ext3_writeback_aops;else inode->i_mapping->a_ops = &ext3_aops; } - }else + }else { + inode->i_op = &ext3_special_inode_operations;init_special_inode (inode, inode->i_mode,le32_to_cpu (iloc.raw_inode->i_block[0 ])); + }if (ei->i_flags &EXT3_SYNC_FL ) inode->i_flags |=S_SYNC ;if (ei->i_flags &EXT3_APPEND_FL )
fs/ext3/namei.c +16 -6
@@ -30,6 +30,7 @@#include <linux/time.h> #include <linux/ext3_fs.h> #include <linux/ext3_jbd.h> +#include <linux/ext3_xattr.h> #include <linux/fcntl.h> #include <linux/stat.h> #include <linux/string.h>
@@ -1654,7 +1655,7 @@if (IS_DIRSYNC (dir)) handle->h_sync =1 ; - inode =ext3_new_inode (handle, dir,S_IFDIR ); + inode =ext3_new_inode (handle, dir,S_IFDIR | mode); err =PTR_ERR (inode);if (IS_ERR (inode)) goto out_stop;
@@ -1662,7 +1663,6 @@ inode->i_op = &ext3_dir_inode_operations; inode->i_fop = &ext3_dir_operations; inode->i_size =EXT3_I (inode)->i_disksize = inode->i_sb->s_blocksize; - inode->i_blocks =0 ; dir_block =ext3_bread (handle, inode,0 ,1 , &err);if (!dir_block) { inode->i_nlink--;/* is this nlink == 0? */
@@ -1689,9 +1689,6 @@BUFFER_TRACE (dir_block,"call ext3_journal_dirty_metadata" );ext3_journal_dirty_metadata (handle, dir_block);brelse (dir_block); - inode->i_mode =S_IFDIR | mode; -if (dir->i_mode &S_ISGID ) - inode->i_mode |=S_ISGID ;ext3_mark_inode_dirty (handle, inode); err =ext3_add_entry (handle, dentry, inode);if (err) {
@@ -2068,7 +2065,7 @@ goto out_stop;if (l >sizeof (EXT3_I (inode)->i_data)) { - inode->i_op = &page_symlink_inode_operations; + inode->i_op = &ext3_symlink_inode_operations;if (ext3_should_writeback_data (inode)) inode->i_mapping->a_ops = &ext3_writeback_aops;else
@@ -2284,4 +2281,17 @@ .rmdir = ext3_rmdir, .mknod = ext3_mknod, .rename = ext3_rename, + .setxattr = ext3_setxattr, + .getxattr = ext3_getxattr, + .listxattr = ext3_listxattr, + .removexattr = ext3_removexattr, }; + +struct inode_operations ext3_special_inode_operations = { + .setxattr = ext3_setxattr, + .getxattr = ext3_getxattr, + .listxattr = ext3_listxattr, + .removexattr = ext3_removexattr, +}; + +
fs/ext3/super.c +22 -1
@@ -24,6 +24,7 @@#include <linux/jbd.h> #include <linux/ext3_fs.h> #include <linux/ext3_jbd.h> +#include <linux/ext3_xattr.h> #include <linux/slab.h> #include <linux/init.h> #include <linux/blkdev.h>
@@ -405,6 +406,7 @@struct ext3_super_block *es = sbi->s_es;int i; +ext3_xattr_put_super (sb);journal_destroy (sbi->s_journal);if (!(sb->s_flags &MS_RDONLY )) {EXT3_CLEAR_INCOMPAT_FEATURE (sb,EXT3_FEATURE_INCOMPAT_RECOVER );
@@ -554,6 +556,7 @@ int is_remount) {unsigned long *mount_options = &sbi->s_mount_opt; +uid_t *resuid = &sbi->s_resuid;gid_t *resgid = &sbi->s_resgid;char * this_char;
@@ -566,6 +569,13 @@continue ;if ((value =strchr (this_char,'=' )) !=NULL ) *value++ =0 ; +#ifdef CONFIG_EXT3_FS_XATTR +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" )) {
@@ -982,6 +992,12 @@ sbi->s_mount_opt =0 ; sbi->s_resuid =EXT3_DEF_RESUID ; sbi->s_resgid =EXT3_DEF_RESGID ; + +/* Default extended attribute flags */ +#ifdef CONFIG_EXT3_FS_XATTR +set_opt (sbi->s_mount_opt,XATTR_USER ); +#endif +if (!parse_options ((char *) data, &sb_block, sbi, &journal_inum,0 )) goto out_fail;
@@ -1820,7 +1836,10 @@static int __init init_ext3_fs (void ) { -int err =init_inodecache (); +int err =init_ext3_xattr (); +if (err) +return err; + err =init_inodecache ();if (err) goto out1; err =register_filesystem (&ext3_fs_type);
@@ -1830,6 +1849,7 @@ out:destroy_inodecache (); out1: +exit_ext3_xattr ();return err; }
@@ -1837,6 +1857,7 @@ {unregister_filesystem (&ext3_fs_type);destroy_inodecache (); +exit_ext3_xattr (); }MODULE_AUTHOR ("Remy Card, Stephen Tweedie, Andrew Morton, Andreas Dilger, Theodore Ts'o and others" );
fs/ext3/symlink.c +15 -1
@@ -20,6 +20,7 @@#include <linux/fs.h> #include <linux/jbd.h> #include <linux/ext3_fs.h> +#include <linux/ext3_xattr.h> static int ext3_readlink (struct dentry *dentry,char *buffer,int buflen) {
@@ -33,7 +34,20 @@return vfs_follow_link (nd, (char *)ei->i_data); } +struct inode_operations ext3_symlink_inode_operations = { + .readlink = page_readlink, + .follow_link = page_follow_link, + .setxattr = ext3_setxattr, + .getxattr = ext3_getxattr, + .listxattr = ext3_listxattr, + .removexattr = ext3_removexattr, +}; +struct inode_operations ext3_fast_symlink_inode_operations = { - .readlink = ext3_readlink,/* BKL not held. Don't need */ + .readlink = ext3_readlink,/* BKL not held. Don't need */ .follow_link = ext3_follow_link,/* BKL not held. Don't need */ + .setxattr = ext3_setxattr, + .getxattr = ext3_getxattr, + .listxattr = ext3_listxattr, + .removexattr = ext3_removexattr, };
fs/ext3/xattr.c new file +1191 -0
1,191 lines not on this page · raw message
fs/ext3/xattr_user.c new file +99 -0
99 lines not on this page · raw message
include/linux/ext3_fs.h +5 -26
@@ -64,8 +64,6 @@*/ #define EXT3_BAD_INO 1/* Bad blocks inode */ #define EXT3_ROOT_INO 2/* Root inode */ -#define EXT3_ACL_IDX_INO 3/* ACL inode */ -#define EXT3_ACL_DATA_INO 4/* ACL inode */ #define EXT3_BOOT_LOADER_INO 5/* Boot loader inode */ #define EXT3_UNDEL_DIR_INO 6/* Undelete directory inode */ #define EXT3_RESIZE_INO 7/* Reserved group descriptors inode */
@@ -95,7 +93,6 @@#else # define EXT3_BLOCK_SIZE (s) (EXT3_MIN_BLOCK_SIZE << (s)->s_log_block_size)#endif -#define EXT3_ACLE_PER_BLOCK (s) (EXT3_BLOCK_SIZE(s) / sizeof (struct ext3_acl_entry))#define EXT3_ADDR_PER_BLOCK (s) (EXT3_BLOCK_SIZE(s) / sizeof (__u32))#ifdef __KERNEL__# define EXT3_BLOCK_SIZE_BITS (s) ((s)->s_blocksize_bits)
@@ -130,28 +127,6 @@#endif /* -* ACL structures -*/ -struct ext3_acl_header /* Header of Access Control Lists */ -{ -__u32 aclh_size; -__u32 aclh_file_count; -__u32 aclh_acle_count; -__u32 aclh_first_acle; -}; - -struct ext3_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 ext3_group_desc
@@ -347,6 +322,7 @@#define EXT3_MOUNT_WRITEBACK_DATA 0x0C00/* No data ordering */ #define EXT3_MOUNT_UPDATE_JOURNAL 0x1000/* Update the journal format */ #define EXT3_MOUNT_NO_UID32 0x2000/* Disable 32-bit UIDs */ +#define EXT3_MOUNT_XATTR_USER 0x4000/* Extended user attributes */ /* Compatibility, for having both ext2_fs.h and ext3_fs.h included at once */ #ifndef _LINUX_EXT2_FS_H
@@ -529,7 +505,7 @@#define EXT3_FEATURE_INCOMPAT_RECOVER 0x0004/* Needs recovery */ #define EXT3_FEATURE_INCOMPAT_JOURNAL_DEV 0x0008/* Journal device */ -#define EXT3_FEATURE_COMPAT_SUPP 0 +#define EXT3_FEATURE_COMPAT_SUPP EXT2_FEATURE_COMPAT_EXT_ATTR#define EXT3_FEATURE_INCOMPAT_SUPP (EXT3_FEATURE_INCOMPAT_FILETYPE| \ EXT3_FEATURE_INCOMPAT_RECOVER)#define EXT3_FEATURE_RO_COMPAT_SUPP (EXT3_FEATURE_RO_COMPAT_SPARSE_SUPER| \
@@ -713,6 +689,7 @@/* inode.c */ +extern int ext3_forget (handle_t *,int ,struct inode *,struct buffer_head *,int );extern struct buffer_head *ext3_getblk (handle_t *,struct inode *,long ,int ,int *);extern struct buffer_head *ext3_bread (handle_t *,struct inode *,int ,int ,int *);
@@ -781,8 +758,10 @@/* namei.c */ extern struct inode_operations ext3_dir_inode_operations; +extern struct inode_operations ext3_special_inode_operations;/* symlink.c */ +extern struct inode_operations ext3_symlink_inode_operations;extern struct inode_operations ext3_fast_symlink_inode_operations;
include/linux/ext3_jbd.h +7 -1
@@ -30,13 +30,19 @@#define EXT3_SINGLEDATA_TRANS_BLOCKS 8 +/* Extended attributes may touch two data buffers, two bitmap buffers, +* and two group and summaries. */ + +#define EXT3_XATTR_TRANS_BLOCKS 8 +/* Define the minimum size for a transaction which modifies data. This * needs to take into account the fact that we may end up modifying two * quota files too (one for the group, one for the user quota). The * superblock only gets updated once, of course, so don't bother * counting that again for the quota updates. */ -#define EXT3_DATA_TRANS_BLOCKS (3 * EXT3_SINGLEDATA_TRANS_BLOCKS - 2) +#define EXT3_DATA_TRANS_BLOCKS (3 * EXT3_SINGLEDATA_TRANS_BLOCKS + \ + EXT3_XATTR_TRANS_BLOCKS - 2)extern int ext3_writepage_trans_blocks (struct inode *inode);
include/linux/ext3_xattr.h new file +137 -0
137 lines not on this page · raw message