Posix ACL support for ext 2/3 filesystems
PATCH 4/5 Posix ACL support for ext 2/3 filesystems
This patch adds ACL support to the ext3 filesystem.
- Ted
# This is a BitKeeper generated patch for the following project:
# Project Name: Linux kernel tree
# This patch format is intended for GNU patch command version 2.5 or higher. # This patch includes the following deltas:
# ChangeSet 1.800 -> 1.801
# include/linux/ext3_fs_i.h 1.3 -> 1.4
# fs/ext3/Makefile 1.5 -> 1.6 # fs/ext3/xattr_user.c 1.1 -> 1.2 # fs/ext3/ialloc.c 1.18 -> 1.19 # fs/ext3/xattr.c 1.1 -> 1.2 # fs/ext3/namei.c 1.23 -> 1.24 # include/linux/ext3_fs.h 1.12 -> 1.13 # fs/Config.in 1.43 -> 1.44 # fs/ext3/inode.c 1.43 -> 1.44 # fs/Config.help 1.23 -> 1.24 # fs/ext3/super.c 1.34 -> 1.35 # fs/ext3/file.c 1.10 -> 1.11 # (new) -> 1.1 fs/ext3/acl.c # (new) -> 1.1 fs/ext3/acl.h
#
# The following is the BitKeeper ChangeSet Log # --------------------------------------------
# 02/10/16 [email protected] 1.801
# Port of (bugfixed) 0.8.50 acl-ext3 to 2.5. #
# This patch adds ACL support to the ext3 filesystem. # -------------------------------------------- #
fs/Config.help +11 -0
@@ -166,7 +166,18 @@ the kernel or by users (see the attr(5) manual page, or visit <http://acl.bestbits.at/> for details). + You need this for POSIX ACL support on ext3. + If unsure, say N. + +CONFIG_EXT3_FS_POSIX_ACL + Posix Access Control Lists (ACLs) support permissions for users and + groups beyond the owner/group/world scheme. + + To learn more about Access Control Lists, visit the Posix ACLs for + Linux website <http://acl.bestbits.at/>. + + If you don't know what Access Control Lists are, say N. CONFIG_JBD This is a generic journaling layer for block devices. It is
fs/Config.in +1 -0
@@ -28,6 +28,7 @@ tristate 'Ext3 journalling file system support' CONFIG_EXT3_FS dep_mbool ' Ext3 extended attributes' CONFIG_EXT3_FS_XATTR $CONFIG_EXT3_FS +dep_mbool ' Ext3 POSIX Access Control Lists' CONFIG_EXT3_FS_POSIX_ACL $CONFIG_EXT3_FS_XATTR $CONFIG_FS_POSIX_ACL # 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 +4 -0
@@ -13,4 +13,8 @@ ext3-objs += xattr.o xattr_user.o endif +ifeq ($(CONFIG_EXT3_FS_POSIX_ACL),y) +ext3-objs += acl.o +endif + include $(TOPDIR)/Rules.make
fs/ext3/acl.c new file +584 -0
584 lines not on this page · raw message
fs/ext3/acl.h new file +91 -0
91 lines not on this page · raw message
fs/ext3/file.c +2 -0
@@ -24,6 +24,7 @@#include <linux/ext3_fs.h> #include <linux/ext3_jbd.h> #include "xattr.h" +#include "acl.h" /* * Called when an inode is released. Note that this is different
@@ -102,5 +103,6 @@ .getxattr = ext3_getxattr, .listxattr = ext3_listxattr, .removexattr = ext3_removexattr, + .permission = ext3_permission, };
fs/ext3/ialloc.c +23 -9
@@ -26,6 +26,7 @@#include <asm/byteorder.h> #include "xattr.h" +#include "acl.h" /* * ialloc.c contains the inodes allocation and deallocation routines
@@ -423,20 +424,27 @@ inode->i_generation =EXT3_SB (sb)->s_next_generation++; ei->i_state =EXT3_STATE_NEW ; - err =ext3_mark_inode_dirty (handle, inode); -if (err) goto fail; - +unlock_super (sb); ret = inode;if (DQUOT_ALLOC_INODE (inode)) {DQUOT_DROP (inode); - inode->i_flags |=S_NOQUOTA ; - inode->i_nlink =0 ; -iput (inode); - ret =ERR_PTR (-EDQUOT ); - }else { -ext3_debug ("allocating inode %lu\n" , inode->i_ino); + err = -EDQUOT ; + goto fail2; } + err =ext3_init_acl (handle, inode, dir); +if (err) { +DQUOT_FREE_INODE (inode); + goto fail2; + } + err =ext3_mark_inode_dirty (handle, inode); +if (err) { +ext3_std_error (sb, err); +DQUOT_FREE_INODE (inode); + goto fail2; + } + +ext3_debug ("allocating inode %lu\n" , inode->i_ino); goto really_out; fail:ext3_std_error (sb, err);
@@ -447,6 +455,12 @@ really_out:brelse (bitmap_bh);return ret; + +fail2: + inode->i_flags |=S_NOQUOTA ; + inode->i_nlink =0 ; +iput (inode); +return ERR_PTR (err); }/* Verify that we are loading a valid orphan from disk */
fs/ext3/inode.c +24 -8
@@ -34,6 +34,8 @@#include <linux/string.h> #include <linux/buffer_head.h> #include <linux/mpage.h> +#include "xattr.h" +#include "acl.h" /* * SEARCH_FROM_ZERO forces each block allocation to search from the start
@@ -2199,7 +2201,11 @@struct buffer_head *bh;int block; -if (ext3_get_inode_loc (inode, &iloc)) +#ifdef CONFIG_EXT3_FS_POSIX_ACL + ei->i_acl =EXT3_ACL_NOT_CACHED ; + ei->i_default_acl =EXT3_ACL_NOT_CACHED ; +#endif +if (ext3_get_inode_loc (inode, &iloc)) goto bad_inode; bh = iloc.bh; raw_inode = iloc.raw_inode;
@@ -2495,13 +2501,8 @@* be freed, so we have a strong guarantee that no future commit will * leave these blocks visible to the user.) * -* This is only needed for regular files. rmdir() has its own path, and -* we can never truncate a direcory except on final unlink (at which -* point i_nlink is zero so recovery is easy.) -* -* Called with the BKL. +* Called with inode->sem down. */ -int ext3_setattr (struct dentry *dentry,struct iattr *attr) {struct inode *inode = dentry->d_inode;
@@ -2521,7 +2522,8 @@lock_kernel (); -if (attr->ia_valid &ATTR_SIZE && attr->ia_size < inode->i_size) { +if (S_ISREG (inode->i_mode) && + attr->ia_valid &ATTR_SIZE && attr->ia_size < inode->i_size) {handle_t *handle; handle =ext3_journal_start (inode,3 );
@@ -2545,6 +2547,20 @@* orphan list manually. */ if (inode->i_nlink)ext3_orphan_del (NULL , inode); + +#ifdef CONFIG_EXT3_FS_POSIX_ACL +if (!rc &&test_opt (inode->i_sb,POSIX_ACL ) && (ia_valid &ATTR_MODE )) { +handle_t *handle; + + handle =ext3_journal_start (inode,EXT3_XATTR_TRANS_BLOCKS ); +if (IS_ERR (handle)) { + error =PTR_ERR (handle); + goto err_out; + } + rc =ext3_acl_chmod (handle, inode); + error =ext3_journal_stop (handle, inode); + } +#endif err_out:ext3_std_error (inode->i_sb, error);
fs/ext3/namei.c +9 -2
@@ -37,7 +37,7 @@#include <linux/buffer_head.h> #include <linux/smp_lock.h> #include "xattr.h" - +#include "acl.h" /* * define how far ahead to read directories while searching them.
@@ -1624,7 +1624,10 @@ inode =ext3_new_inode (handle, dir, mode); err =PTR_ERR (inode);if (!IS_ERR (inode)) { -init_special_inode (inode, mode, rdev); +init_special_inode (inode, inode->i_mode, rdev); +#ifdef CONFIG_EXT3_FS_XATTR + inode->i_op = &ext3_special_inode_operations; +#endif err =ext3_add_nondir (handle, dentry, inode);ext3_mark_inode_dirty (handle, inode); }
@@ -2281,17 +2284,21 @@ .rmdir = ext3_rmdir, .mknod = ext3_mknod, .rename = ext3_rename, + .setattr = ext3_setattr, .setxattr = ext3_setxattr, .getxattr = ext3_getxattr, .listxattr = ext3_listxattr, .removexattr = ext3_removexattr, + .permission = ext3_permission, };struct inode_operations ext3_special_inode_operations = { + .setattr = ext3_setattr, .setxattr = ext3_setxattr, .getxattr = ext3_getxattr, .listxattr = ext3_listxattr, .removexattr = ext3_removexattr, + .permission = ext3_permission, };
fs/ext3/super.c +39 -0
@@ -31,6 +31,7 @@#include <linux/buffer_head.h> #include <asm/uaccess.h> #include "xattr.h" +#include "acl.h" #ifdef CONFIG_JBD_DEBUG static int ext3_ro_after;/* Make fs read-only after this many jiffies */
@@ -458,6 +459,10 @@ ei =kmem_cache_alloc (ext3_inode_cachep,SLAB_NOFS );if (!ei)return NULL ; +#ifdef CONFIG_EXT3_FS_POSIX_ACL + ei->i_acl =EXT3_ACL_NOT_CACHED ; + ei->i_default_acl =EXT3_ACL_NOT_CACHED ; +#endif return &ei->vfs_inode; }
@@ -495,6 +500,26 @@printk (KERN_INFO "ext3_inode_cache: not all structures were freed\n" ); } +#ifdef CONFIG_EXT3_FS_POSIX_ACL + +static void ext3_clear_inode (struct inode *inode) +{ +if (EXT3_I (inode)->i_acl && +EXT3_I (inode)->i_acl !=EXT3_ACL_NOT_CACHED ) { +posix_acl_release (EXT3_I (inode)->i_acl); +EXT3_I (inode)->i_acl =EXT3_ACL_NOT_CACHED ; + } +if (EXT3_I (inode)->i_default_acl && +EXT3_I (inode)->i_default_acl !=EXT3_ACL_NOT_CACHED ) { +posix_acl_release (EXT3_I (inode)->i_default_acl); +EXT3_I (inode)->i_default_acl =EXT3_ACL_NOT_CACHED ; + } +} + +#else +# define ext3_clear_inode NULL +#endif +static struct super_operations ext3_sops = { .alloc_inode = ext3_alloc_inode, .destroy_inode = ext3_destroy_inode,
@@ -509,6 +534,7 @@ .unlockfs = ext3_unlockfs, /* BKL not held. We take it */ .statfs = ext3_statfs, /* BKL not held. */ .remount_fs = ext3_remount, /* BKL held */ + .clear_inode = ext3_clear_inode, /* BKL not needed. */ };struct dentry *ext3_get_parent (struct dentry *child);
@@ -576,6 +602,13 @@clear_opt (*mount_options,XATTR_USER ); else#endif +#ifdef CONFIG_EXT3_FS_POSIX_ACL +if (!strcmp (this_char,"acl" )) +set_opt (*mount_options,POSIX_ACL ); +else if (!strcmp (this_char,"noacl" )) +clear_opt (*mount_options,POSIX_ACL ); + else +#endif if (!strcmp (this_char,"bsddf" ))clear_opt (*mount_options,MINIX_DF );else if (!strcmp (this_char,"nouid32" )) {
@@ -1001,6 +1034,9 @@if (!parse_options ((char *) data, &sb_block, sbi, &journal_inum,0 )) goto out_fail; + sb->s_flags = (sb->s_flags & ~MS_POSIXACL ) | + ((sbi->s_mount_opt &EXT3_MOUNT_POSIX_ACL ) ?MS_POSIXACL :0 ); + blocksize =sb_min_blocksize (sb,EXT3_MIN_BLOCK_SIZE );/*
@@ -1719,6 +1755,9 @@if (sbi->s_mount_opt &EXT3_MOUNT_ABORT )ext3_abort (sb, __FUNCTION__,"Abort forced by user" ); + + sb->s_flags = (sb->s_flags & ~MS_POSIXACL ) | + ((sbi->s_mount_opt &EXT3_MOUNT_POSIX_ACL ) ?MS_POSIXACL :0 ); es = sbi->s_es;
fs/ext3/xattr.c +19 -4
@@ -61,6 +61,7 @@#include <linux/quotaops.h> #include <asm/semaphore.h> #include "xattr.h" +#include "acl.h" #define EXT3_EA_USER "user."
@@ -1105,15 +1106,27 @@ err =ext3_xattr_register (EXT3_XATTR_INDEX_USER , &ext3_xattr_user_handler);if (err)return err; +#ifdef CONFIG_EXT3_FS_POSIX_ACL + err =init_ext3_acl (); +if (err) + goto out; +#endif ext3_xattr_cache =mb_cache_create ("ext3_xattr" ,NULL ,sizeof (struct mb_cache_entry ) +sizeof (struct mb_cache_entry_index ),1 ,6 );if (!ext3_xattr_cache) { -ext3_xattr_unregister (EXT3_XATTR_INDEX_USER , &ext3_xattr_user_handler); -return -ENOMEM ; + err = -ENOMEM ; + goto out1; } -return 0 ; +out1: +#ifdef CONFIG_EXT3_FS_POSIX_ACL +exit_ext3_acl (); +out: +#endif +ext3_xattr_unregister (EXT3_XATTR_INDEX_USER , + &ext3_xattr_user_handler); +return err; }void
@@ -1122,6 +1135,8 @@if (ext3_xattr_cache)mb_cache_destroy (ext3_xattr_cache); ext3_xattr_cache =NULL ; +#ifdef CONFIG_EXT3_FS_POSIX_ACL +exit_ext3_acl (); +#endif ext3_xattr_unregister (EXT3_XATTR_INDEX_USER , &ext3_xattr_user_handler); } -
fs/ext3/xattr_user.c +1 -4
@@ -12,10 +12,7 @@#include <linux/ext3_jbd.h> #include <linux/ext3_fs.h> #include "xattr.h" - -#ifdef CONFIG_EXT3_FS_POSIX_ACL -# include <linux/ext3_acl.h> -#endif +#include "acl.h" #define XATTR_USER_PREFIX "user."
include/linux/ext3_fs.h +1 -0
@@ -323,6 +323,7 @@#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 */ +#define EXT3_MOUNT_POSIX_ACL 0x8000/* POSIX Access Control Lists */ /* Compatibility, for having both ext2_fs.h and ext3_fs.h included at once */ #ifndef _LINUX_EXT2_FS_H
include/linux/ext3_fs_i.h +4 -0
@@ -41,6 +41,10 @@__u32 i_prealloc_count;#endif __u32 i_dir_start_lookup; +#ifdef CONFIG_EXT3_FS_POSIX_ACL +struct posix_acl *i_acl; +struct posix_acl *i_default_acl; +#endif struct list_head i_orphan;/* unlinked but open inodes */