From patchwork Thu May 20 07:25:49 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Miao Xie X-Patchwork-Id: 101149 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter.kernel.org (8.14.3/8.14.3) with ESMTP id o4K7QLrH005587 for ; Thu, 20 May 2010 07:26:21 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754182Ab0ETH0Q (ORCPT ); Thu, 20 May 2010 03:26:16 -0400 Received: from cn.fujitsu.com ([222.73.24.84]:50083 "EHLO song.cn.fujitsu.com" rhost-flags-OK-FAIL-OK-OK) by vger.kernel.org with ESMTP id S1750877Ab0ETH0G (ORCPT ); Thu, 20 May 2010 03:26:06 -0400 Received: from tang.cn.fujitsu.com (tang.cn.fujitsu.com [10.167.250.3]) by song.cn.fujitsu.com (Postfix) with ESMTP id 044E617016C; Thu, 20 May 2010 15:26:04 +0800 (CST) Received: from fnst.cn.fujitsu.com (tang.cn.fujitsu.com [127.0.0.1]) by tang.cn.fujitsu.com (8.14.3/8.13.1) with ESMTP id o4K7NxsZ016210; Thu, 20 May 2010 15:24:01 +0800 Received: from [127.0.0.1] (unknown [10.167.141.211]) by fnst.cn.fujitsu.com (Postfix) with ESMTPA id 5900F10C0A1; Thu, 20 May 2010 15:29:39 +0800 (CST) Message-ID: <4BF4E3FD.5030402@cn.fujitsu.com> Date: Thu, 20 May 2010 15:25:49 +0800 From: Miao Xie Reply-To: miaox@cn.fujitsu.com User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9.1.9) Gecko/20100317 Thunderbird/3.0.4 MIME-Version: 1.0 To: Chris Mason CC: Linux Btrfs Subject: [PATCH 10/10] btrfs: fix the wrong handle of btrfs_set_acl() Sender: linux-btrfs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-btrfs@vger.kernel.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.3 (demeter.kernel.org [140.211.167.41]); Thu, 20 May 2010 07:26:21 +0000 (UTC) diff --git a/fs/btrfs/acl.c b/fs/btrfs/acl.c index da3133c..7f7c0e5 100644 --- a/fs/btrfs/acl.c +++ b/fs/btrfs/acl.c @@ -26,6 +26,7 @@ #include "ctree.h" #include "btrfs_inode.h" #include "xattr.h" +#include "transaction.h" #ifdef CONFIG_BTRFS_FS_POSIX_ACL @@ -97,6 +98,7 @@ static int btrfs_xattr_get_acl(struct inode *inode, int type, static int btrfs_set_acl(struct btrfs_trans_handle *trans, struct inode *inode, struct posix_acl *acl, int type) { + struct btrfs_root *root = BTRFS_I(inode)->root; int ret, size = 0; const char *name; char *value = NULL; @@ -111,15 +113,20 @@ static int btrfs_set_acl(struct btrfs_trans_handle *trans, switch (type) { case ACL_TYPE_ACCESS: - mode = inode->i_mode; name = POSIX_ACL_XATTR_ACCESS; if (acl) { + mode = inode->i_mode; ret = posix_acl_equiv_mode(acl, &mode); if (ret < 0) return ret; - inode->i_mode = mode; + else { + inode->i_mode = mode; + inode->i_ctime = CURRENT_TIME; + btrfs_update_inode(trans, root, inode); + if (ret == 0) + acl = NULL; + } } - ret = 0; break; case ACL_TYPE_DEFAULT: if (!S_ISDIR(inode->i_mode)) @@ -158,6 +165,8 @@ static int btrfs_xattr_set_acl(struct inode *inode, int type, { int ret; struct posix_acl *acl = NULL; + struct btrfs_root *root = BTRFS_I(inode)->root; + struct btrfs_trans_handle *trans; if (value) { acl = posix_acl_from_xattr(value, size); @@ -169,8 +178,23 @@ static int btrfs_xattr_set_acl(struct inode *inode, int type, } } - ret = btrfs_set_acl(NULL, inode, acl, type); + ret = btrfs_reserve_metadata_space(root, 2); + if (ret) + goto reserve_space_err; + + trans = btrfs_start_transaction(root, 1); + if (!trans) { + ret = -ENOMEM; + goto start_trans_err; + } + btrfs_set_trans_block_group(trans, inode); + + ret = btrfs_set_acl(trans, inode, acl, type); + btrfs_end_transaction_throttle(trans, root); +start_trans_err: + btrfs_unreserve_metadata_space(root, 2); +reserve_space_err: posix_acl_release(acl); return ret; @@ -279,6 +303,7 @@ failed: int btrfs_acl_chmod(struct inode *inode) { + struct btrfs_root *root = BTRFS_I(inode)->root; struct posix_acl *acl, *clone; int ret = 0; @@ -298,9 +323,28 @@ int btrfs_acl_chmod(struct inode *inode) return -ENOMEM; ret = posix_acl_chmod_masq(clone, inode->i_mode); - if (!ret) - ret = btrfs_set_acl(NULL, inode, clone, ACL_TYPE_ACCESS); + if (!ret) { + struct btrfs_trans_handle *trans; + + ret = btrfs_reserve_metadata_space(root, 2); + if (ret) + goto reserve_space_err; + + trans = btrfs_start_transaction(root, 1); + if (!trans) { + ret = -ENOMEM; + goto start_trans_err; + } + btrfs_set_trans_block_group(trans, inode); + + ret = btrfs_set_acl(trans, inode, clone, ACL_TYPE_ACCESS); + + btrfs_end_transaction_throttle(trans, root); + start_trans_err: + btrfs_unreserve_metadata_space(root, 2); + } +reserve_space_err: posix_acl_release(clone); return ret; diff --git a/fs/btrfs/xattr.c b/fs/btrfs/xattr.c index 193b58f..0b3a891 100644 --- a/fs/btrfs/xattr.c +++ b/fs/btrfs/xattr.c @@ -124,7 +124,7 @@ static int do_setxattr(struct btrfs_trans_handle *trans, /* if we don't have a value then we are removing the xattr */ if (!value) - goto out; + goto success_end; } else { btrfs_release_path(root, path); @@ -133,12 +133,20 @@ static int do_setxattr(struct btrfs_trans_handle *trans, ret = -ENODATA; goto out; } + + if (!value) + goto out; } /* ok we have to create a completely new xattr */ ret = btrfs_insert_xattr_item(trans, root, path, inode->i_ino, name, name_len, value, size); - BUG_ON(ret); + btrfs_release_path(root, path); +success_end: + if (!ret) { + inode->i_ctime = CURRENT_TIME; + btrfs_update_inode(trans, root, inode); + } out: btrfs_free_path(path); return ret; @@ -149,6 +157,7 @@ int __btrfs_setxattr(struct btrfs_trans_handle *trans, const void *value, size_t size, int flags) { struct btrfs_root *root = BTRFS_I(inode)->root; + int nr = 1; int ret; if (trans) @@ -166,15 +175,12 @@ int __btrfs_setxattr(struct btrfs_trans_handle *trans, btrfs_set_trans_block_group(trans, inode); ret = do_setxattr(trans, inode, name, value, size, flags); - if (ret) - goto out; - inode->i_ctime = CURRENT_TIME; - ret = btrfs_update_inode(trans, root, inode); - BUG_ON(ret); -out: + nr = trans->blocks_used; btrfs_end_transaction_throttle(trans, root); +out: btrfs_unreserve_metadata_space(root, 2); + btrfs_btree_balance_dirty(root, nr); return ret; }