Hi: This patch add btrfs acl checking. It makes btrfs's acl checking really work if you mount btrfs by using "acl" option, e.g. mount -t btrfs -o acl /dev/hda1 /mnt/ Thanks LiuHui diff -r 6c243ad8dddf acl.c --- a/acl.c Fri Jan 18 10:54:22 2008 -0500 +++ b/acl.c Sat Jan 19 21:38:02 2008 +0800 @@ -26,6 +26,35 @@ #define is_owner_or_cap(inode) \ ((current->fsuid == (inode)->i_uid) || capable(CAP_FOWNER)) #endif + +struct posix_acl *btrfs_get_posix_acl(struct inode *inode, int type) +{ + int ret, len; + char *value = NULL; + struct posix_acl *acl; + + len = btrfs_xattr_get(inode, type, "", NULL, 0); + if (len > 0) { + value = kmalloc(len, GFP_KERNEL); + if (!value) { + return ERR_PTR(-ENOMEM); + } + + } else { + return NULL; + } + ret = btrfs_xattr_get(inode, type, "", value, len); + if (ret > 0) { + acl = posix_acl_from_xattr(value, len); + } else if (-ENODATA == ret) { + acl = NULL; + } else { + acl = ERR_PTR(ret); + } + + kfree(value); + return acl; +} static int btrfs_xattr_set_acl(struct inode *inode, int type, const void *value, size_t size) diff -r 6c243ad8dddf ctree.h --- a/ctree.h Fri Jan 18 10:54:22 2008 -0500 +++ b/ctree.h Sat Jan 19 21:38:02 2008 +0800 @@ -446,6 +446,7 @@ struct btrfs_root { #define BTRFS_MOUNT_NODATACOW (1 << 1) #define BTRFS_MOUNT_NOBARRIER (1 << 2) #define BTRFS_MOUNT_SSD (1 << 3) +#define BTRFS_MOUNT_POSIX_ACL (1 << 4) #define btrfs_clear_opt(o, opt) ((o) &= ~BTRFS_MOUNT_##opt) #define btrfs_set_opt(o, opt) ((o) |= BTRFS_MOUNT_##opt) diff -r 6c243ad8dddf inode.c --- a/inode.c Fri Jan 18 10:54:22 2008 -0500 +++ b/inode.c Sat Jan 19 21:38:02 2008 +0800 @@ -33,12 +33,16 @@ #include <linux/bit_spinlock.h> #include <linux/version.h> #include <linux/xattr.h> +#include <linux/posix_acl.h> #include "ctree.h" #include "disk-io.h" #include "transaction.h" #include "btrfs_inode.h" #include "ioctl.h" #include "print-tree.h" +#include "xattr.h" + +extern struct posix_acl *btrfs_get_posix_acl(struct inode *inode, int type); struct btrfs_iget_args { u64 ino; @@ -2886,12 +2890,29 @@ out_fail: btrfs_throttle(root); return err; } + +static int btrfs_check_acl(struct inode *inode, int mask) +{ + struct posix_acl *acl; + acl = btrfs_get_posix_acl(inode, BTRFS_XATTR_INDEX_POSIX_ACL_ACCESS); + + if (IS_ERR(acl)) + return PTR_ERR(acl); + if (acl) { + int error = posix_acl_permission(inode, acl, mask); + posix_acl_release(acl); + return error; + } + + return -EAGAIN; +} + static int btrfs_permission(struct inode *inode, int mask, struct nameidata *nd) { if (btrfs_test_flag(inode, READONLY) && (mask & MAY_WRITE)) return -EACCES; - return generic_permission(inode, mask, NULL); + return generic_permission(inode, mask, btrfs_check_acl); } static struct inode_operations btrfs_dir_inode_operations = { diff -r 6c243ad8dddf super.c --- a/super.c Fri Jan 18 10:54:22 2008 -0500 +++ b/super.c Sat Jan 19 21:38:02 2008 +0800 @@ -64,7 +64,7 @@ static void btrfs_put_super (struct supe enum { Opt_subvol, Opt_nodatasum, Opt_nodatacow, Opt_max_extent, - Opt_alloc_start, Opt_nobarrier, Opt_ssd, Opt_err, + Opt_alloc_start, Opt_nobarrier, Opt_ssd, Opt_posix_acl, Opt_err, }; static match_table_t tokens = { @@ -75,6 +75,7 @@ static match_table_t tokens = { {Opt_max_extent, "max_extent=%s"}, {Opt_alloc_start, "alloc_start=%s"}, {Opt_ssd, "ssd"}, + {Opt_posix_acl, "acl"}, {Opt_err, NULL} }; @@ -162,6 +163,14 @@ static int parse_options (char * options btrfs_set_opt(info->mount_opt, NOBARRIER); } break; + + case Opt_posix_acl: + if (info) { + printk("btrfs: enabling posix acl\n"); + btrfs_set_opt(info->mount_opt, POSIX_ACL); + } + break; + case Opt_max_extent: if (info) { char *num = match_strdup(&args[0]); @@ -247,6 +256,12 @@ static int btrfs_fill_super(struct super } parse_options((char *)data, tree_root, NULL); + + if (tree_root->fs_info->mount_opt & BTRFS_MOUNT_POSIX_ACL) { + sb->s_flags |= MS_POSIXACL; + } else { + sb->s_flags = sb->s_flags & ~MS_POSIXACL; + } /* this does the super kobj at the same time */ err = btrfs_sysfs_add_super(tree_root->fs_info);
2008/1/19, only flyer <onlyflyer@gmail.com>:> Hi: > This patch add btrfs acl checking. It makes btrfs's acl checking > really work if you mount btrfs by using "acl" option, e.g. mount -t > btrfs -o acl /dev/hda1 /mnt/ > > Thanks > LiuHui > > diff -r 6c243ad8dddf acl.c > --- a/acl.c Fri Jan 18 10:54:22 2008 -0500 > +++ b/acl.c Sat Jan 19 21:38:02 2008 +0800 > @@ -26,6 +26,35 @@ > #define is_owner_or_cap(inode) \ > ((current->fsuid == (inode)->i_uid) || capable(CAP_FOWNER)) > #endif > + > +struct posix_acl *btrfs_get_posix_acl(struct inode *inode, int type) > +{ > + int ret, len; > + char *value = NULL; > + struct posix_acl *acl; > + > + len = btrfs_xattr_get(inode, type, "", NULL, 0); > + if (len > 0) { > + value = kmalloc(len, GFP_KERNEL); > + if (!value) { > + return ERR_PTR(-ENOMEM); > + } > + > + } else { > + return NULL; > + } > + ret = btrfs_xattr_get(inode, type, "", value, len); > + if (ret > 0) { > + acl = posix_acl_from_xattr(value, len); > + } else if (-ENODATA == ret) { > + acl = NULL; > + } else { > + acl = ERR_PTR(ret); > + } > + > + kfree(value); > + return acl; > +} > > static int btrfs_xattr_set_acl(struct inode *inode, int type, > const void *value, size_t size) > diff -r 6c243ad8dddf ctree.h > --- a/ctree.h Fri Jan 18 10:54:22 2008 -0500 > +++ b/ctree.h Sat Jan 19 21:38:02 2008 +0800 > @@ -446,6 +446,7 @@ struct btrfs_root { > #define BTRFS_MOUNT_NODATACOW (1 << 1) > #define BTRFS_MOUNT_NOBARRIER (1 << 2) > #define BTRFS_MOUNT_SSD (1 << 3) > +#define BTRFS_MOUNT_POSIX_ACL (1 << 4) > > #define btrfs_clear_opt(o, opt) ((o) &= ~BTRFS_MOUNT_##opt) > #define btrfs_set_opt(o, opt) ((o) |= BTRFS_MOUNT_##opt) > diff -r 6c243ad8dddf inode.c > --- a/inode.c Fri Jan 18 10:54:22 2008 -0500 > +++ b/inode.c Sat Jan 19 21:38:02 2008 +0800 > @@ -33,12 +33,16 @@ > #include <linux/bit_spinlock.h> > #include <linux/version.h> > #include <linux/xattr.h> > +#include <linux/posix_acl.h> > #include "ctree.h" > #include "disk-io.h" > #include "transaction.h" > #include "btrfs_inode.h" > #include "ioctl.h" > #include "print-tree.h" > +#include "xattr.h" > + > +extern struct posix_acl *btrfs_get_posix_acl(struct inode *inode, int type); > > struct btrfs_iget_args { > u64 ino; > @@ -2886,12 +2890,29 @@ out_fail: > btrfs_throttle(root); > return err; > } > + > +static int btrfs_check_acl(struct inode *inode, int mask) > +{ > + struct posix_acl *acl; > + acl = btrfs_get_posix_acl(inode, BTRFS_XATTR_INDEX_POSIX_ACL_ACCESS); > + > + if (IS_ERR(acl)) > + return PTR_ERR(acl); > + if (acl) { > + int error = posix_acl_permission(inode, acl, mask); > + posix_acl_release(acl); > + return error; > + } > + > + return -EAGAIN; > +} > +I feel this function should be moved into acl.c, so that btrfs can be compiled on kernel without acl support.> static int btrfs_permission(struct inode *inode, int mask, > struct nameidata *nd) > { > if (btrfs_test_flag(inode, READONLY) && (mask & MAY_WRITE)) > return -EACCES; > - return generic_permission(inode, mask, NULL); > + return generic_permission(inode, mask, btrfs_check_acl); > } > > static struct inode_operations btrfs_dir_inode_operations = { > diff -r 6c243ad8dddf super.c > --- a/super.c Fri Jan 18 10:54:22 2008 -0500 > +++ b/super.c Sat Jan 19 21:38:02 2008 +0800 > @@ -64,7 +64,7 @@ static void btrfs_put_super (struct supe > > enum { > Opt_subvol, Opt_nodatasum, Opt_nodatacow, Opt_max_extent, > - Opt_alloc_start, Opt_nobarrier, Opt_ssd, Opt_err, > + Opt_alloc_start, Opt_nobarrier, Opt_ssd, Opt_posix_acl, Opt_err, > }; > > static match_table_t tokens = { > @@ -75,6 +75,7 @@ static match_table_t tokens = { > {Opt_max_extent, "max_extent=%s"}, > {Opt_alloc_start, "alloc_start=%s"}, > {Opt_ssd, "ssd"}, > + {Opt_posix_acl, "acl"}, > {Opt_err, NULL} > }; > > @@ -162,6 +163,14 @@ static int parse_options (char * options > btrfs_set_opt(info->mount_opt, NOBARRIER); > } > break; > + > + case Opt_posix_acl: > + if (info) { > + printk("btrfs: enabling posix acl\n"); > + btrfs_set_opt(info->mount_opt, POSIX_ACL); > + } > + break; > + > case Opt_max_extent: > if (info) { > char *num = match_strdup(&args[0]); > @@ -247,6 +256,12 @@ static int btrfs_fill_super(struct super > } > > parse_options((char *)data, tree_root, NULL); > + > + if (tree_root->fs_info->mount_opt & BTRFS_MOUNT_POSIX_ACL) {You can use 'btrfs_test_opt' to do this test.> + sb->s_flags |= MS_POSIXACL; > + } else { > + sb->s_flags = sb->s_flags & ~MS_POSIXACL; > + } > > /* this does the super kobj at the same time */ > err = btrfs_sysfs_add_super(tree_root->fs_info); >Regards YZ
On Saturday 19 January 2008, only flyer wrote:> Hi: > This patch add btrfs acl checking. It makes btrfs's acl checking > really work if you mount btrfs by using "acl" option, e.g. mount -t > btrfs -o acl /dev/hda1 /mnt/ >Great, thank you for doing this. In addition to Yan's comments, I would like to make acls on by default, unless someone mounts with -o noacl. So, to avoid a performance hit related to always checking acls, please set an inode flag whenever acls are set on an inode, and only do the tree search for the acls when the flag is set. (For an example on inode flags, see BTRFS_INODE_NODATACOW) -chris> Thanks > LiuHui > > diff -r 6c243ad8dddf acl.c > --- a/acl.c Fri Jan 18 10:54:22 2008 -0500 > +++ b/acl.c Sat Jan 19 21:38:02 2008 +0800 > @@ -26,6 +26,35 @@ > #define is_owner_or_cap(inode) \ > ((current->fsuid == (inode)->i_uid) || capable(CAP_FOWNER)) > #endif > + > +struct posix_acl *btrfs_get_posix_acl(struct inode *inode, int type) > +{ > + int ret, len; > + char *value = NULL; > + struct posix_acl *acl; > + > + len = btrfs_xattr_get(inode, type, "", NULL, 0); > + if (len > 0) { > + value = kmalloc(len, GFP_KERNEL); > + if (!value) { > + return ERR_PTR(-ENOMEM); > + } > + > + } else { > + return NULL; > + } > + ret = btrfs_xattr_get(inode, type, "", value, len); > + if (ret > 0) { > + acl = posix_acl_from_xattr(value, len); > + } else if (-ENODATA == ret) { > + acl = NULL; > + } else { > + acl = ERR_PTR(ret); > + } > + > + kfree(value); > + return acl; > +} > > static int btrfs_xattr_set_acl(struct inode *inode, int type, > const void *value, size_t size) > diff -r 6c243ad8dddf ctree.h > --- a/ctree.h Fri Jan 18 10:54:22 2008 -0500 > +++ b/ctree.h Sat Jan 19 21:38:02 2008 +0800 > @@ -446,6 +446,7 @@ struct btrfs_root { > #define BTRFS_MOUNT_NODATACOW (1 << 1) > #define BTRFS_MOUNT_NOBARRIER (1 << 2) > #define BTRFS_MOUNT_SSD (1 << 3) > +#define BTRFS_MOUNT_POSIX_ACL (1 << 4) > > #define btrfs_clear_opt(o, opt) ((o) &= ~BTRFS_MOUNT_##opt) > #define btrfs_set_opt(o, opt) ((o) |= BTRFS_MOUNT_##opt) > diff -r 6c243ad8dddf inode.c > --- a/inode.c Fri Jan 18 10:54:22 2008 -0500 > +++ b/inode.c Sat Jan 19 21:38:02 2008 +0800 > @@ -33,12 +33,16 @@ > #include <linux/bit_spinlock.h> > #include <linux/version.h> > #include <linux/xattr.h> > +#include <linux/posix_acl.h> > #include "ctree.h" > #include "disk-io.h" > #include "transaction.h" > #include "btrfs_inode.h" > #include "ioctl.h" > #include "print-tree.h" > +#include "xattr.h" > + > +extern struct posix_acl *btrfs_get_posix_acl(struct inode *inode, int > type); > > struct btrfs_iget_args { > u64 ino; > @@ -2886,12 +2890,29 @@ out_fail: > btrfs_throttle(root); > return err; > } > + > +static int btrfs_check_acl(struct inode *inode, int mask) > +{ > + struct posix_acl *acl; > + acl = btrfs_get_posix_acl(inode, > BTRFS_XATTR_INDEX_POSIX_ACL_ACCESS); + > + if (IS_ERR(acl)) > + return PTR_ERR(acl); > + if (acl) { > + int error = posix_acl_permission(inode, acl, mask); > + posix_acl_release(acl); > + return error; > + } > + > + return -EAGAIN; > +} > + > static int btrfs_permission(struct inode *inode, int mask, > struct nameidata *nd) > { > if (btrfs_test_flag(inode, READONLY) && (mask & MAY_WRITE)) > return -EACCES; > - return generic_permission(inode, mask, NULL); > + return generic_permission(inode, mask, btrfs_check_acl); > } > > static struct inode_operations btrfs_dir_inode_operations = { > diff -r 6c243ad8dddf super.c > --- a/super.c Fri Jan 18 10:54:22 2008 -0500 > +++ b/super.c Sat Jan 19 21:38:02 2008 +0800 > @@ -64,7 +64,7 @@ static void btrfs_put_super (struct supe > > enum { > Opt_subvol, Opt_nodatasum, Opt_nodatacow, Opt_max_extent, > - Opt_alloc_start, Opt_nobarrier, Opt_ssd, Opt_err, > + Opt_alloc_start, Opt_nobarrier, Opt_ssd, Opt_posix_acl, Opt_err, > }; > > static match_table_t tokens = { > @@ -75,6 +75,7 @@ static match_table_t tokens = { > {Opt_max_extent, "max_extent=%s"}, > {Opt_alloc_start, "alloc_start=%s"}, > {Opt_ssd, "ssd"}, > + {Opt_posix_acl, "acl"}, > {Opt_err, NULL} > }; > > @@ -162,6 +163,14 @@ static int parse_options (char * options > btrfs_set_opt(info->mount_opt, NOBARRIER); > } > break; > + > + case Opt_posix_acl: > + if (info) { > + printk("btrfs: enabling posix acl\n"); > + btrfs_set_opt(info->mount_opt, POSIX_ACL); > + } > + break; > + > case Opt_max_extent: > if (info) { > char *num = match_strdup(&args[0]); > @@ -247,6 +256,12 @@ static int btrfs_fill_super(struct super > } > > parse_options((char *)data, tree_root, NULL); > + > + if (tree_root->fs_info->mount_opt & BTRFS_MOUNT_POSIX_ACL) { > + sb->s_flags |= MS_POSIXACL; > + } else { > + sb->s_flags = sb->s_flags & ~MS_POSIXACL; > + } > > /* this does the super kobj at the same time */ > err = btrfs_sysfs_add_super(tree_root->fs_info); > > _______________________________________________ > Btrfs-devel mailing list > Btrfs-devel@oss.oracle.com > http://oss.oracle.com/mailman/listinfo/btrfs-devel