From patchwork Thu Jun 30 13:47:04 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andreas Gruenbacher X-Patchwork-Id: 9207625 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 0231760752 for ; Thu, 30 Jun 2016 13:49:16 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id E842F2865F for ; Thu, 30 Jun 2016 13:49:15 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id DD20528673; Thu, 30 Jun 2016 13:49:15 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-4.2 required=2.0 tests=BAYES_00, RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 Received: from oss.sgi.com (oss.sgi.com [192.48.182.195]) (using TLSv1 with cipher DHE-RSA-CAMELLIA256-SHA (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 19D912865F for ; Thu, 30 Jun 2016 13:49:15 +0000 (UTC) Received: from oss.sgi.com (localhost [IPv6:::1]) by oss.sgi.com (Postfix) with ESMTP id D021E7CE7; Thu, 30 Jun 2016 08:49:00 -0500 (CDT) X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 544977CD9 for ; Thu, 30 Jun 2016 08:48:55 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay2.corp.sgi.com (Postfix) with ESMTP id 18B48304039 for ; Thu, 30 Jun 2016 06:48:55 -0700 (PDT) X-ASG-Debug-ID: 1467294533-04cb6c063e2c4560001-NocioJ Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by cuda.sgi.com with ESMTP id aAyNyNDaAjnE3mTh (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 30 Jun 2016 06:48:53 -0700 (PDT) X-Barracuda-Envelope-From: agruenba@redhat.com X-Barracuda-Effective-Source-IP: mx1.redhat.com[209.132.183.28] X-Barracuda-Apparent-Source-IP: 209.132.183.28 X-ASG-Whitelist: Client Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 200F2C049D67; Thu, 30 Jun 2016 13:48:53 +0000 (UTC) Received: from nux.redhat.com (vpn1-5-124.ams2.redhat.com [10.36.5.124]) by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u5UDlDso005273; Thu, 30 Jun 2016 09:48:46 -0400 From: Andreas Gruenbacher To: Alexander Viro Subject: [PATCH v23 13/22] vfs: Cache richacl in struct inode Date: Thu, 30 Jun 2016 15:47:04 +0200 X-ASG-Orig-Subj: [PATCH v23 13/22] vfs: Cache richacl in struct inode Message-Id: <1467294433-3222-14-git-send-email-agruenba@redhat.com> In-Reply-To: <1467294433-3222-1-git-send-email-agruenba@redhat.com> References: <1467294433-3222-1-git-send-email-agruenba@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.31]); Thu, 30 Jun 2016 13:48:53 +0000 (UTC) X-Barracuda-Connect: mx1.redhat.com[209.132.183.28] X-Barracuda-Start-Time: 1467294533 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 5815 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 Cc: "J. Bruce Fields" , linux-nfs@vger.kernel.org, Theodore Ts'o , Andreas Gruenbacher , linux-cifs@vger.kernel.org, linux-api@vger.kernel.org, Trond Myklebust , linux-kernel@vger.kernel.org, xfs@oss.sgi.com, Christoph Hellwig , Andreas Dilger , linux-fsdevel@vger.kernel.org, Jeff Layton , linux-ext4@vger.kernel.org, Anna Schumaker X-BeenThere: xfs@oss.sgi.com X-Mailman-Version: 2.1.14 Precedence: list List-Id: XFS Filesystem from SGI List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: xfs-bounces@oss.sgi.com Sender: xfs-bounces@oss.sgi.com 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 | 13 +++++--- fs/richacl.c | 81 +++++++++++++++++++++++++++++++++++++++++++++++++ include/linux/fs.h | 5 ++- include/linux/richacl.h | 11 +++++++ 4 files changed, 105 insertions(+), 5 deletions(-) diff --git a/fs/inode.c b/fs/inode.c index 40c03a7..7dbb09c 100644 --- a/fs/inode.c +++ b/fs/inode.c @@ -181,8 +181,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 @@ -238,17 +241,19 @@ 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 && !is_uncached_acl(inode->i_acl)) base_acl_put(inode->i_acl); +# if defined(CONFIG_FS_POSIX_ACL) if (inode->i_default_acl && !is_uncached_acl(inode->i_default_acl)) base_acl_put(inode->i_default_acl); +# endif #endif this_cpu_dec(nr_inodes); } EXPORT_SYMBOL(__destroy_inode); -#ifdef CONFIG_FS_POSIX_ACL +#if defined(CONFIG_FS_POSIX_ACL) || defined(CONFIG_FS_RICHACL) struct base_acl *__get_cached_acl(struct base_acl **p) { struct base_acl *base_acl; diff --git a/fs/richacl.c b/fs/richacl.c index 8971ead..b2a03c1 100644 --- a/fs/richacl.c +++ b/fs/richacl.c @@ -20,6 +20,87 @@ #include #include +void set_cached_richacl(struct inode *inode, struct richacl *acl) +{ + struct base_acl *old; + + old = xchg(&inode->i_acl, &richacl_get(acl)->a_base); + if (!is_uncached_acl(old)) + base_acl_put(old); +} +EXPORT_SYMBOL_GPL(set_cached_richacl); + +void forget_cached_richacl(struct inode *inode) +{ + __forget_cached_acl(&inode->i_acl); +} +EXPORT_SYMBOL_GPL(forget_cached_richacl); + +struct richacl *get_richacl(struct inode *inode) +{ + struct base_acl *sentinel, *base_acl; + struct richacl *acl; + + if (!IS_RICHACL(inode)) + return NULL; + + /* + * The sentinel is used to detect when another operation like + * set_cached_richacl() or forget_cached_richacl() races with + * get_richacl(). + * It is guaranteed that is_uncached_acl(sentinel) is true. + */ + + base_acl = __get_cached_acl(&inode->i_acl); + if (!is_uncached_acl(base_acl)) + return richacl(base_acl); + + sentinel = uncached_acl_sentinel(current); + + /* + * If the ACL isn't being read yet, set our sentinel. Otherwise, the + * current value of the ACL will not be ACL_NOT_CACHED and so our own + * sentinel will not be set; another task will update the cache. We + * could wait for that other task to complete its job, but it's easier + * to just call ->get_acl to fetch the ACL ourself. (This is going to + * be an unlikely race.) + */ + if (cmpxchg(&inode->i_acl, ACL_NOT_CACHED, sentinel) != ACL_NOT_CACHED) + /* fall through */ ; + + /* + * Normally, the ACL returned by ->get_richacl will be cached. + * A filesystem can prevent that by calling + * forget_cached_richacl(inode) in ->get_richacl. + * + * 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; + } + + acl = inode->i_op->get_richacl(inode); + if (IS_ERR(acl)) { + /* + * Remove our sentinel so that we don't block future attempts + * to cache the ACL. + */ + cmpxchg(&inode->i_acl, sentinel, ACL_NOT_CACHED); + return acl; + } + + /* + * Cache the result, but only if our sentinel is still in place. + */ + richacl_get(acl); + if (unlikely(cmpxchg(&inode->i_acl, sentinel, &acl->a_base) != sentinel)) + richacl_put(acl); + return acl; +} +EXPORT_SYMBOL_GPL(get_richacl); + /** * richacl_alloc - allocate a richacl * @count: number of entries diff --git a/include/linux/fs.h b/include/linux/fs.h index ac96bda..4d72a6d 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -589,6 +589,7 @@ struct base_acl { }; }; struct posix_acl; +struct richacl; #define ACL_NOT_CACHED ((void *)(-1)) static inline struct base_acl * @@ -619,9 +620,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 35a5bcb..3e05c94 100644 --- a/include/linux/richacl.h +++ b/include/linux/richacl.h @@ -70,6 +70,17 @@ richacl_put(struct richacl *acl) base_acl_put(&acl->a_base); } +static inline struct richacl * +richacl(struct base_acl *base_acl) +{ + BUILD_BUG_ON(offsetof(struct richacl, a_base) != 0); + return container_of(base_acl, struct richacl, a_base); +} + +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 */