From patchwork Wed Dec 2 21:01:19 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andreas Gruenbacher X-Patchwork-Id: 7752011 Return-Path: X-Original-To: patchwork-linux-nfs@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 88187BEEE1 for ; Wed, 2 Dec 2015 21:03:59 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 860212053E for ; Wed, 2 Dec 2015 21:03:58 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 7DE752053F for ; Wed, 2 Dec 2015 21:03:56 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932450AbbLBVDu (ORCPT ); Wed, 2 Dec 2015 16:03:50 -0500 Received: from mx1.redhat.com ([209.132.183.28]:49075 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1757309AbbLBVDr (ORCPT ); Wed, 2 Dec 2015 16:03:47 -0500 Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) by mx1.redhat.com (Postfix) with ESMTPS id 0DBC868E18; Wed, 2 Dec 2015 21:03:47 +0000 (UTC) Received: from nux.redhat.com (vpn1-7-96.ams2.redhat.com [10.36.7.96]) by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id tB2L1T2g016990; Wed, 2 Dec 2015 16:03:38 -0500 From: Andreas Gruenbacher To: Alexander Viro , "Theodore Ts'o" , Andreas Dilger , "J. Bruce Fields" , Jeff Layton , Trond Myklebust , Anna Schumaker , Dave Chinner , linux-ext4@vger.kernel.org, xfs@oss.sgi.com, linux-kernel@vger.kernel.org, linux-fsdevel@vger.kernel.org, linux-nfs@vger.kernel.org, linux-cifs@vger.kernel.org, linux-api@vger.kernel.org Cc: Andreas Gruenbacher Subject: [PATCH v16 13/22] vfs: Cache richacl in struct inode Date: Wed, 2 Dec 2015 22:01:19 +0100 Message-Id: <1449090088-9281-14-git-send-email-agruenba@redhat.com> In-Reply-To: <1449090088-9281-1-git-send-email-agruenba@redhat.com> References: <1449090088-9281-1-git-send-email-agruenba@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.23 Sender: linux-nfs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-nfs@vger.kernel.org X-Spam-Status: No, score=-6.9 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Cache richacls in struct inode so that this doesn't have to be done individually in each filesystem. This is similar to POSIX ACLs. Signed-off-by: Andreas Gruenbacher --- fs/inode.c | 11 +++++-- fs/posix_acl.c | 2 +- fs/richacl_inode.c | 77 +++++++++++++++++++++++++++++++++++++++++++++++++ include/linux/fs.h | 5 +++- include/linux/richacl.h | 6 ++++ 5 files changed, 96 insertions(+), 5 deletions(-) diff --git a/fs/inode.c b/fs/inode.c index 1d6d035..3459bc9 100644 --- a/fs/inode.c +++ b/fs/inode.c @@ -174,8 +174,11 @@ int inode_init_always(struct super_block *sb, struct inode *inode) inode->i_private = NULL; inode->i_mapping = mapping; INIT_HLIST_HEAD(&inode->i_dentry); /* buggered by rcu freeing */ -#ifdef CONFIG_FS_POSIX_ACL - inode->i_acl = inode->i_default_acl = ACL_NOT_CACHED; +#if defined(CONFIG_FS_POSIX_ACL) || defined(CONFIG_FS_RICHACL) + inode->i_acl = ACL_NOT_CACHED; +# if defined(CONFIG_FS_POSIX_ACL) + inode->i_default_acl = ACL_NOT_CACHED; +# endif #endif #ifdef CONFIG_FSNOTIFY @@ -231,11 +234,13 @@ void __destroy_inode(struct inode *inode) atomic_long_dec(&inode->i_sb->s_remove_count); } -#ifdef CONFIG_FS_POSIX_ACL +#if defined(CONFIG_FS_POSIX_ACL) || defined(CONFIG_FS_RICHACL) if (inode->i_acl && inode->i_acl != ACL_NOT_CACHED) base_acl_put(inode->i_acl); +# if defined(CONFIG_FS_POSIX_ACL) if (inode->i_default_acl && inode->i_default_acl != ACL_NOT_CACHED) base_acl_put(inode->i_default_acl); +# endif #endif this_cpu_dec(nr_inodes); } diff --git a/fs/posix_acl.c b/fs/posix_acl.c index df2673f..9e2195a 100644 --- a/fs/posix_acl.c +++ b/fs/posix_acl.c @@ -37,7 +37,7 @@ struct posix_acl *get_cached_acl(struct inode *inode, int type) { struct base_acl **p = acl_by_type(inode, type); struct base_acl *acl = ACCESS_ONCE(*p); - if (acl) { + if (acl && IS_POSIXACL(inode)) { spin_lock(&inode->i_lock); acl = *p; if (acl != ACL_NOT_CACHED) diff --git a/fs/richacl_inode.c b/fs/richacl_inode.c index 99b3c93..52c1595 100644 --- a/fs/richacl_inode.c +++ b/fs/richacl_inode.c @@ -20,6 +20,83 @@ #include #include +struct richacl *get_cached_richacl(struct inode *inode) +{ + struct base_acl *acl; + + acl = ACCESS_ONCE(inode->i_acl); + if (acl && IS_RICHACL(inode)) { + spin_lock(&inode->i_lock); + acl = inode->i_acl; + if (acl != ACL_NOT_CACHED) + base_acl_get(acl); + spin_unlock(&inode->i_lock); + } + return container_of(acl, struct richacl, a_base); +} +EXPORT_SYMBOL_GPL(get_cached_richacl); + +struct richacl *get_cached_richacl_rcu(struct inode *inode) +{ + struct base_acl *acl = rcu_dereference(inode->i_acl); + + return container_of(acl, struct richacl, a_base); +} +EXPORT_SYMBOL_GPL(get_cached_richacl_rcu); + +void set_cached_richacl(struct inode *inode, struct richacl *acl) +{ + struct base_acl *old = NULL; + + spin_lock(&inode->i_lock); + old = inode->i_acl; + rcu_assign_pointer(inode->i_acl, &richacl_get(acl)->a_base); + spin_unlock(&inode->i_lock); + if (old != ACL_NOT_CACHED) + base_acl_put(old); +} +EXPORT_SYMBOL_GPL(set_cached_richacl); + +void forget_cached_richacl(struct inode *inode) +{ + struct base_acl *old = NULL; + + spin_lock(&inode->i_lock); + old = inode->i_acl; + inode->i_acl = ACL_NOT_CACHED; + spin_unlock(&inode->i_lock); + if (old != ACL_NOT_CACHED) + base_acl_put(old); +} +EXPORT_SYMBOL_GPL(forget_cached_richacl); + +struct richacl *get_richacl(struct inode *inode) +{ + struct richacl *acl; + + acl = get_cached_richacl(inode); + if (acl != ACL_NOT_CACHED) + return acl; + + if (!IS_RICHACL(inode)) + return NULL; + + /* + * A filesystem can force a ACL callback by just never filling the + * ACL cache. But normally you'd fill the cache either at inode + * instantiation time, or on the first ->get_richacl call. + * + * If the filesystem doesn't have a get_richacl() function at all, + * we'll just create the negative cache entry. + */ + if (!inode->i_op->get_richacl) { + set_cached_richacl(inode, NULL); + return NULL; + } + return inode->i_op->get_richacl(inode); +} +EXPORT_SYMBOL_GPL(get_richacl); + /** * richacl_permission - richacl permission check algorithm * @inode: inode to check diff --git a/include/linux/fs.h b/include/linux/fs.h index 4847417..76d71b2 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -583,6 +583,7 @@ struct base_acl { }; }; struct posix_acl; +struct richacl; #define ACL_NOT_CACHED ((void *)(-1)) #define IOP_FASTPERM 0x0001 @@ -601,9 +602,11 @@ struct inode { kgid_t i_gid; unsigned int i_flags; -#if defined(CONFIG_FS_POSIX_ACL) +#if defined(CONFIG_FS_POSIX_ACL) || defined(CONFIG_FS_RICHACL) struct base_acl *i_acl; +# if defined(CONFIG_FS_POSIX_ACL) struct base_acl *i_default_acl; +# endif #endif const struct inode_operations *i_op; diff --git a/include/linux/richacl.h b/include/linux/richacl.h index 7628fad..7bf912b6 100644 --- a/include/linux/richacl.h +++ b/include/linux/richacl.h @@ -70,6 +70,12 @@ richacl_put(struct richacl *acl) base_acl_put(&acl->a_base); } +extern struct richacl *get_cached_richacl(struct inode *); +extern struct richacl *get_cached_richacl_rcu(struct inode *); +extern void set_cached_richacl(struct inode *, struct richacl *); +extern void forget_cached_richacl(struct inode *); +extern struct richacl *get_richacl(struct inode *); + /** * richace_is_owner - check if @ace is an OWNER@ entry */