[Btrfs-devel] [PATCH] Add btrfs acl checking
Chris mason
chris.mason at oracle.com
Mon Jan 21 05:59:10 PST 2008
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 at oss.oracle.com
> http://oss.oracle.com/mailman/listinfo/btrfs-devel
More information about the Btrfs-devel
mailing list