From patchwork Fri May 27 16:17:18 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Josef Bacik X-Patchwork-Id: 824782 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter1.kernel.org (8.14.4/8.14.3) with ESMTP id p4RGHhsg009027 for ; Fri, 27 May 2011 16:17:44 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753845Ab1E0QRk (ORCPT ); Fri, 27 May 2011 12:17:40 -0400 Received: from mx1.redhat.com ([209.132.183.28]:23999 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751316Ab1E0QRk (ORCPT ); Fri, 27 May 2011 12:17:40 -0400 Received: from int-mx12.intmail.prod.int.phx2.redhat.com (int-mx12.intmail.prod.int.phx2.redhat.com [10.5.11.25]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id p4RGHdXi021854 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Fri, 27 May 2011 12:17:40 -0400 Received: from test1244.test.redhat.com (dhcp231-135.rdu.redhat.com [10.11.231.135]) by int-mx12.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id p4RGHdO1030046 for ; Fri, 27 May 2011 12:17:39 -0400 From: Josef Bacik To: linux-btrfs@vger.kernel.org Subject: [PATCH] Btrfs: try to only do one btrfs_search_slot in do_setxattr Date: Fri, 27 May 2011 12:17:18 -0400 Message-Id: <1306513038-3133-1-git-send-email-josef@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.25 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.6 (demeter1.kernel.org [140.211.167.41]); Fri, 27 May 2011 16:17:44 +0000 (UTC) I've been watching how many btrfs_search_slot()'s we do and I noticed that when we create a file with selinux enabled we were doing 2 each time we initialize the security context. That's because we lookup the xattr first so we can delete it if we're setting a new value to an existing xattr. But in the create case we don't have any xattrs, so it is completely useless to have the extra lookup. So re-arrange things so that we only lookup first if we specifically have XATTR_REPLACE. That way in the basic case we only do 1 search, and in the more complicated case we do the normal 2 lookups. Thanks, Signed-off-by: Josef Bacik --- fs/btrfs/xattr.c | 54 ++++++++++++++++++++++++++---------------------------- 1 files changed, 26 insertions(+), 28 deletions(-) diff --git a/fs/btrfs/xattr.c b/fs/btrfs/xattr.c index 72ab029..4857a87 100644 --- a/fs/btrfs/xattr.c +++ b/fs/btrfs/xattr.c @@ -102,43 +102,41 @@ static int do_setxattr(struct btrfs_trans_handle *trans, if (!path) return -ENOMEM; - /* first lets see if we already have this xattr */ - di = btrfs_lookup_xattr(trans, root, path, inode->i_ino, name, - strlen(name), -1); - if (IS_ERR(di)) { - ret = PTR_ERR(di); - goto out; - } - - /* ok we already have this xattr, lets remove it */ - if (di) { - /* if we want create only exit */ - if (flags & XATTR_CREATE) { - ret = -EEXIST; + if (flags & XATTR_REPLACE) { + di = btrfs_lookup_xattr(trans, root, path, inode->i_ino, name, + strlen(name), -1); + if (IS_ERR(di)) { + ret = PTR_ERR(di); + goto out; + } else if (!di) { + ret = -ENODATA; goto out; } - ret = btrfs_delete_one_dir_name(trans, root, path, di); - BUG_ON(ret); - btrfs_release_path(root, path); - - /* if we don't have a value then we are removing the xattr */ - if (!value) + if (ret) goto out; - } else { btrfs_release_path(root, path); - - if (flags & XATTR_REPLACE) { - /* we couldn't find the attr to replace */ - ret = -ENODATA; - goto out; - } } - /* ok we have to create a completely new xattr */ +again: ret = btrfs_insert_xattr_item(trans, root, path, inode->i_ino, name, name_len, value, size); - BUG_ON(ret); + if (ret == -EEXIST) { + if (flags & XATTR_CREATE) + goto out; + di = btrfs_match_dir_item_name(root, path, name, name_len); + ret = btrfs_delete_one_dir_name(trans, root, path, di); + if (ret) + goto out; + + /* + * We have a value to set, so go back and try to insert it now. + */ + if (value) { + btrfs_release_path(root, path); + goto again; + } + } out: btrfs_free_path(path); return ret;