From mboxrd@z Thu Jan 1 00:00:00 1970 From: Jeff Layton Subject: Re: [PATCH v23 13/22] vfs: Cache richacl in struct inode Date: Wed, 06 Jul 2016 14:57:05 -0400 Message-ID: <1467831425.2908.16.camel@redhat.com> References: <1467294433-3222-1-git-send-email-agruenba@redhat.com> <1467294433-3222-14-git-send-email-agruenba@redhat.com> Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: QUOTED-PRINTABLE Cc: Christoph Hellwig , Theodore Ts'o , Andreas Dilger , "J. Bruce Fields" , Trond Myklebust , Anna Schumaker , Dave Chinner , linux-ext4-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, xfs-VZNHf3L845pBDgjK7y7TUQ@public.gmane.org, linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, linux-fsdevel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, linux-nfs-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, linux-cifs-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, linux-api-u79uwXL29TY76Z2rM5mHXA@public.gmane.org To: Andreas Gruenbacher , Alexander Viro Return-path: In-Reply-To: <1467294433-3222-14-git-send-email-agruenba-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org> Sender: linux-nfs-owner-u79uwXL29TY76Z2rM5mHXA@public.gmane.org List-Id: linux-cifs.vger.kernel.org On Thu, 2016-06-30 at 15:47 +0200, Andreas Gruenbacher wrote: > Cache richacls in struct inode so that this doesn't have to be done > individually in each filesystem.=C2=A0=C2=A0This is similar to POSIX = ACLs. >=20 > Signed-off-by: Andreas Gruenbacher > --- > =C2=A0fs/inode.c=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0| 13 +++++--- > =C2=A0fs/richacl.c=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2= =A0=C2=A0=C2=A0=C2=A0| 81 +++++++++++++++++++++++++++++++++++++++++++++= ++++ > =C2=A0include/linux/fs.h=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0|=C2=A0=C2= =A05 ++- > =C2=A0include/linux/richacl.h | 11 +++++++ > =C2=A04 files changed, 105 insertions(+), 5 deletions(-) >=20 > 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, st= ruct inode *inode) > =C2=A0 inode->i_private =3D NULL; > =C2=A0 inode->i_mapping =3D mapping; > =C2=A0 INIT_HLIST_HEAD(&inode->i_dentry); /* buggered by rcu freeing = */ > -#ifdef CONFIG_FS_POSIX_ACL > - inode->i_acl =3D inode->i_default_acl =3D ACL_NOT_CACHED; > +#if defined(CONFIG_FS_POSIX_ACL) || defined(CONFIG_FS_RICHACL) > + inode->i_acl =3D ACL_NOT_CACHED; > +# if defined(CONFIG_FS_POSIX_ACL) > + inode->i_default_acl =3D ACL_NOT_CACHED; > +# endif > =C2=A0#endif > =C2=A0 > =C2=A0#ifdef CONFIG_FSNOTIFY > @@ -238,17 +241,19 @@ void __destroy_inode(struct inode *inode) > =C2=A0 atomic_long_dec(&inode->i_sb->s_remove_count); > =C2=A0 } > =C2=A0 > -#ifdef CONFIG_FS_POSIX_ACL > +#if defined(CONFIG_FS_POSIX_ACL) || defined(CONFIG_FS_RICHACL) > =C2=A0 if (inode->i_acl && !is_uncached_acl(inode->i_acl)) > =C2=A0 base_acl_put(inode->i_acl); > +# if defined(CONFIG_FS_POSIX_ACL) > =C2=A0 if (inode->i_default_acl && !is_uncached_acl(inode->i_default_= acl)) > =C2=A0 base_acl_put(inode->i_default_acl); > +# endif > =C2=A0#endif > =C2=A0 this_cpu_dec(nr_inodes); > =C2=A0} > =C2=A0EXPORT_SYMBOL(__destroy_inode); > =C2=A0 > -#ifdef CONFIG_FS_POSIX_ACL > +#if defined(CONFIG_FS_POSIX_ACL) || defined(CONFIG_FS_RICHACL) > =C2=A0struct base_acl *__get_cached_acl(struct base_acl **p) > =C2=A0{ > =C2=A0 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 @@ > =C2=A0#include=20 > =C2=A0#include=20 > =C2=A0 > +void set_cached_richacl(struct inode *inode, struct richacl *acl) > +{ > + struct base_acl *old; > + > + old =3D 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; > + > + /* > + =C2=A0* The sentinel is used to detect when another operation like > + =C2=A0* set_cached_richacl() or forget_cached_richacl() races with > + =C2=A0* get_richacl(). > + =C2=A0* It is guaranteed that is_uncached_acl(sentinel) is true. > + =C2=A0*/ > + > + base_acl =3D __get_cached_acl(&inode->i_acl); > + if (!is_uncached_acl(base_acl)) > + return richacl(base_acl); > + > + sentinel =3D uncached_acl_sentinel(current); > + > + /* > + =C2=A0* If the ACL isn't being read yet, set our sentinel.=C2=A0=C2= =A0Otherwise, the > + =C2=A0* current value of the ACL will not be ACL_NOT_CACHED and so = our own > + =C2=A0* sentinel will not be set; another task will update the cach= e.=C2=A0=C2=A0We > + =C2=A0* could wait for that other task to complete its job, but it'= s easier > + =C2=A0* to just call ->get_acl to fetch the ACL ourself.=C2=A0=C2=A0= (This is going to > + =C2=A0* be an unlikely race.) > + =C2=A0*/ > + if (cmpxchg(&inode->i_acl, ACL_NOT_CACHED, sentinel) !=3D ACL_NOT_C= ACHED) > + /* fall through */ ; > + So you do the same thing regardless of the outcome of the above? Why bother with the if at all here? Just do the cmpxchg and toss out the result. > + /* > + =C2=A0* Normally, the ACL returned by ->get_richacl will be cached. > + =C2=A0* A filesystem can prevent that by calling > + =C2=A0* forget_cached_richacl(inode) in ->get_richacl. > + =C2=A0* > + =C2=A0* If the filesystem doesn't have a ->get_richacl function at = all, > + =C2=A0* we'll just create the negative cache entry. > + =C2=A0*/ > + if (!inode->i_op->get_richacl) { > + set_cached_richacl(inode, NULL); > + return NULL; > + } > + > + acl =3D inode->i_op->get_richacl(inode); > + if (IS_ERR(acl)) { > + /* > + =C2=A0* Remove our sentinel so that we don't block future attempts > + =C2=A0* to cache the ACL. > + =C2=A0*/ > + cmpxchg(&inode->i_acl, sentinel, ACL_NOT_CACHED); > + return acl; > + } > + So this is sort of icky: only the task that sets the sentinel can set the cached acl. You could have one task set the sentinel, call get_richacl and fail, bu= t then a concurrent task also issues a get_richacl and succeeds. That t= ask will get its acl, but it doesn't end up getting cached and subseque= nt callers then have to reissue the request. It would be good if the fi= rst successful fetch of the acl sets it in the cache. That said, getting the acl could be pretty expensive with some filesyst= ems. NFS or CIFS are going to have to do an on the wire call to fetch t= hem, for instance. I think it would be better to have concurrent caller= s wait for the first caller's result instead of issuing parallel get_ri= chacl requests. > + /* > + =C2=A0* Cache the result, but only if our sentinel is still in plac= e. > + =C2=A0*/ > + richacl_get(acl); > + if (unlikely(cmpxchg(&inode->i_acl, sentinel, &acl->a_base) !=3D se= ntinel)) > + richacl_put(acl); > + return acl; > +} > +EXPORT_SYMBOL_GPL(get_richacl); > + > =C2=A0/** > =C2=A0 * richacl_alloc=C2=A0=C2=A0-=C2=A0=C2=A0allocate a richacl > =C2=A0 * @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 { > =C2=A0 }; > =C2=A0}; > =C2=A0struct posix_acl; > +struct richacl; > =C2=A0#define ACL_NOT_CACHED ((void *)(-1)) > =C2=A0 > =C2=A0static inline struct base_acl * > @@ -619,9 +620,11 @@ struct inode { > =C2=A0 kgid_t i_gid; > =C2=A0 unsigned int i_flags; > =C2=A0 > -#if defined(CONFIG_FS_POSIX_ACL) > +#if defined(CONFIG_FS_POSIX_ACL) || defined(CONFIG_FS_RICHACL) > =C2=A0 struct base_acl *i_acl; > +# if defined(CONFIG_FS_POSIX_ACL) > =C2=A0 struct base_acl *i_default_acl; > +# endif > =C2=A0#endif > =C2=A0 Oh, so if we compile in richacls and not posix acls, we shrink the inode by a pointer. Nice! > =C2=A0 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) > =C2=A0 base_acl_put(&acl->a_base); > =C2=A0} > =C2=A0 > +static inline struct richacl * > +richacl(struct base_acl *base_acl) > +{ > + BUILD_BUG_ON(offsetof(struct richacl, a_base) !=3D 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 *); > + > =C2=A0/** > =C2=A0 * richace_is_owner=C2=A0=C2=A0-=C2=A0=C2=A0check if @ace is an= OWNER@ entry > =C2=A0 */ --=20 Jeff Layton -- To unsubscribe from this list: send the line "unsubscribe linux-nfs" in the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org More majordomo info at http://vger.kernel.org/majordomo-info.html From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755573AbcGFS5N (ORCPT ); Wed, 6 Jul 2016 14:57:13 -0400 Received: from mail-qk0-f180.google.com ([209.85.220.180]:34660 "EHLO mail-qk0-f180.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1755470AbcGFS5I (ORCPT ); Wed, 6 Jul 2016 14:57:08 -0400 Message-ID: <1467831425.2908.16.camel@redhat.com> Subject: Re: [PATCH v23 13/22] vfs: Cache richacl in struct inode From: Jeff Layton To: Andreas Gruenbacher , Alexander Viro Cc: Christoph Hellwig , "Theodore Ts'o" , Andreas Dilger , "J. Bruce Fields" , 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 Date: Wed, 06 Jul 2016 14:57:05 -0400 In-Reply-To: <1467294433-3222-14-git-send-email-agruenba@redhat.com> References: <1467294433-3222-1-git-send-email-agruenba@redhat.com> <1467294433-3222-14-git-send-email-agruenba@redhat.com> Content-Type: text/plain; charset="UTF-8" X-Mailer: Evolution 3.18.5.2 (3.18.5.2-1.fc23) Mime-Version: 1.0 Content-Transfer-Encoding: 8bit Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On Thu, 2016-06-30 at 15:47 +0200, Andreas Gruenbacher wrote: > 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 */ ; > + So you do the same thing regardless of the outcome of the above? Why bother with the if at all here? Just do the cmpxchg and toss out the result. > + /* > +  * 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; > + } > + So this is sort of icky: only the task that sets the sentinel can set the cached acl. You could have one task set the sentinel, call get_richacl and fail, but then a concurrent task also issues a get_richacl and succeeds. That task will get its acl, but it doesn't end up getting cached and subsequent callers then have to reissue the request. It would be good if the first successful fetch of the acl sets it in the cache. That said, getting the acl could be pretty expensive with some filesystems. NFS or CIFS are going to have to do an on the wire call to fetch them, for instance. I think it would be better to have concurrent callers wait for the first caller's result instead of issuing parallel get_richacl requests. > + /* > +  * 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 >   Oh, so if we compile in richacls and not posix acls, we shrink the inode by a pointer. Nice! >   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 >   */ -- Jeff Layton From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 423937D0F for ; Wed, 6 Jul 2016 13:57:15 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay2.corp.sgi.com (Postfix) with ESMTP id E523A304064 for ; Wed, 6 Jul 2016 11:57:11 -0700 (PDT) Received: from mail-qk0-f179.google.com (mail-qk0-f179.google.com [209.85.220.179]) by cuda.sgi.com with ESMTP id 5SFXy4dCFzqGRmU7 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NO) for ; Wed, 06 Jul 2016 11:57:08 -0700 (PDT) Received: by mail-qk0-f179.google.com with SMTP id s126so39314960qkh.2 for ; Wed, 06 Jul 2016 11:57:08 -0700 (PDT) Message-ID: <1467831425.2908.16.camel@redhat.com> Subject: Re: [PATCH v23 13/22] vfs: Cache richacl in struct inode From: Jeff Layton Date: Wed, 06 Jul 2016 14:57:05 -0400 In-Reply-To: <1467294433-3222-14-git-send-email-agruenba@redhat.com> References: <1467294433-3222-1-git-send-email-agruenba@redhat.com> <1467294433-3222-14-git-send-email-agruenba@redhat.com> Mime-Version: 1.0 List-Id: XFS Filesystem from SGI List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: base64 Errors-To: xfs-bounces@oss.sgi.com Sender: xfs-bounces@oss.sgi.com To: Andreas Gruenbacher , Alexander Viro Cc: "J. Bruce Fields" , linux-nfs@vger.kernel.org, Theodore Ts'o , 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, linux-ext4@vger.kernel.org, Anna Schumaker T24gVGh1LCAyMDE2LTA2LTMwIGF0IDE1OjQ3ICswMjAwLCBBbmRyZWFzIEdydWVuYmFjaGVyIHdy b3RlOgo+IENhY2hlIHJpY2hhY2xzIGluIHN0cnVjdCBpbm9kZSBzbyB0aGF0IHRoaXMgZG9lc24n dCBoYXZlIHRvIGJlIGRvbmUKPiBpbmRpdmlkdWFsbHkgaW4gZWFjaCBmaWxlc3lzdGVtLsKgwqBU aGlzIGlzIHNpbWlsYXIgdG8gUE9TSVggQUNMcy4KPiAKPiBTaWduZWQtb2ZmLWJ5OiBBbmRyZWFz IEdydWVuYmFjaGVyIDxhZ3J1ZW5iYUByZWRoYXQuY29tPgo+IC0tLQo+IMKgZnMvaW5vZGUuY8Kg wqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqB8IDEzICsrKysrLS0tCj4gwqBmcy9yaWNoYWNsLmPC oMKgwqDCoMKgwqDCoMKgwqDCoMKgwqB8IDgxICsrKysrKysrKysrKysrKysrKysrKysrKysrKysr KysrKysrKysrKysrKysrKysrKysKPiDCoGluY2x1ZGUvbGludXgvZnMuaMKgwqDCoMKgwqDCoHzC oMKgNSArKy0KPiDCoGluY2x1ZGUvbGludXgvcmljaGFjbC5oIHwgMTEgKysrKysrKwo+IMKgNCBm aWxlcyBjaGFuZ2VkLCAxMDUgaW5zZXJ0aW9ucygrKSwgNSBkZWxldGlvbnMoLSkKPiAKPiBkaWZm IC0tZ2l0IGEvZnMvaW5vZGUuYyBiL2ZzL2lub2RlLmMKPiBpbmRleCA0MGMwM2E3Li43ZGJiMDlj IDEwMDY0NAo+IC0tLSBhL2ZzL2lub2RlLmMKPiArKysgYi9mcy9pbm9kZS5jCj4gQEAgLTE4MSw4 ICsxODEsMTEgQEAgaW50IGlub2RlX2luaXRfYWx3YXlzKHN0cnVjdCBzdXBlcl9ibG9jayAqc2Is IHN0cnVjdCBpbm9kZSAqaW5vZGUpCj4gwqAJaW5vZGUtPmlfcHJpdmF0ZSA9IE5VTEw7Cj4gwqAJ aW5vZGUtPmlfbWFwcGluZyA9IG1hcHBpbmc7Cj4gwqAJSU5JVF9ITElTVF9IRUFEKCZpbm9kZS0+ aV9kZW50cnkpOwkvKiBidWdnZXJlZCBieSByY3UgZnJlZWluZyAqLwo+IC0jaWZkZWYgQ09ORklH X0ZTX1BPU0lYX0FDTAo+IC0JaW5vZGUtPmlfYWNsID0gaW5vZGUtPmlfZGVmYXVsdF9hY2wgPSBB Q0xfTk9UX0NBQ0hFRDsKPiArI2lmIGRlZmluZWQoQ09ORklHX0ZTX1BPU0lYX0FDTCkgfHwgZGVm aW5lZChDT05GSUdfRlNfUklDSEFDTCkKPiArCWlub2RlLT5pX2FjbCA9IEFDTF9OT1RfQ0FDSEVE Owo+ICsjIGlmIGRlZmluZWQoQ09ORklHX0ZTX1BPU0lYX0FDTCkKPiArCWlub2RlLT5pX2RlZmF1 bHRfYWNsID0gQUNMX05PVF9DQUNIRUQ7Cj4gKyMgZW5kaWYKPiDCoCNlbmRpZgo+IMKgCj4gwqAj aWZkZWYgQ09ORklHX0ZTTk9USUZZCj4gQEAgLTIzOCwxNyArMjQxLDE5IEBAIHZvaWQgX19kZXN0 cm95X2lub2RlKHN0cnVjdCBpbm9kZSAqaW5vZGUpCj4gwqAJCWF0b21pY19sb25nX2RlYygmaW5v ZGUtPmlfc2ItPnNfcmVtb3ZlX2NvdW50KTsKPiDCoAl9Cj4gwqAKPiAtI2lmZGVmIENPTkZJR19G U19QT1NJWF9BQ0wKPiArI2lmIGRlZmluZWQoQ09ORklHX0ZTX1BPU0lYX0FDTCkgfHwgZGVmaW5l ZChDT05GSUdfRlNfUklDSEFDTCkKPiDCoAlpZiAoaW5vZGUtPmlfYWNsICYmICFpc191bmNhY2hl ZF9hY2woaW5vZGUtPmlfYWNsKSkKPiDCoAkJYmFzZV9hY2xfcHV0KGlub2RlLT5pX2FjbCk7Cj4g KyMgaWYgZGVmaW5lZChDT05GSUdfRlNfUE9TSVhfQUNMKQo+IMKgCWlmIChpbm9kZS0+aV9kZWZh dWx0X2FjbCAmJiAhaXNfdW5jYWNoZWRfYWNsKGlub2RlLT5pX2RlZmF1bHRfYWNsKSkKPiDCoAkJ YmFzZV9hY2xfcHV0KGlub2RlLT5pX2RlZmF1bHRfYWNsKTsKPiArIyBlbmRpZgo+IMKgI2VuZGlm Cj4gwqAJdGhpc19jcHVfZGVjKG5yX2lub2Rlcyk7Cj4gwqB9Cj4gwqBFWFBPUlRfU1lNQk9MKF9f ZGVzdHJveV9pbm9kZSk7Cj4gwqAKPiAtI2lmZGVmIENPTkZJR19GU19QT1NJWF9BQ0wKPiArI2lm IGRlZmluZWQoQ09ORklHX0ZTX1BPU0lYX0FDTCkgfHwgZGVmaW5lZChDT05GSUdfRlNfUklDSEFD TCkKPiDCoHN0cnVjdCBiYXNlX2FjbCAqX19nZXRfY2FjaGVkX2FjbChzdHJ1Y3QgYmFzZV9hY2wg KipwKQo+IMKgewo+IMKgCXN0cnVjdCBiYXNlX2FjbCAqYmFzZV9hY2w7Cj4gZGlmZiAtLWdpdCBh L2ZzL3JpY2hhY2wuYyBiL2ZzL3JpY2hhY2wuYwo+IGluZGV4IDg5NzFlYWQuLmIyYTAzYzEgMTAw NjQ0Cj4gLS0tIGEvZnMvcmljaGFjbC5jCj4gKysrIGIvZnMvcmljaGFjbC5jCj4gQEAgLTIwLDYg KzIwLDg3IEBACj4gwqAjaW5jbHVkZSAKPiDCoCNpbmNsdWRlIAo+IMKgCj4gK3ZvaWQgc2V0X2Nh Y2hlZF9yaWNoYWNsKHN0cnVjdCBpbm9kZSAqaW5vZGUsIHN0cnVjdCByaWNoYWNsICphY2wpCj4g K3sKPiArCXN0cnVjdCBiYXNlX2FjbCAqb2xkOwo+ICsKPiArCW9sZCA9IHhjaGcoJmlub2RlLT5p X2FjbCwgJnJpY2hhY2xfZ2V0KGFjbCktPmFfYmFzZSk7Cj4gKwlpZiAoIWlzX3VuY2FjaGVkX2Fj bChvbGQpKQo+ICsJCWJhc2VfYWNsX3B1dChvbGQpOwo+ICt9Cj4gK0VYUE9SVF9TWU1CT0xfR1BM KHNldF9jYWNoZWRfcmljaGFjbCk7Cj4gKwo+ICt2b2lkIGZvcmdldF9jYWNoZWRfcmljaGFjbChz dHJ1Y3QgaW5vZGUgKmlub2RlKQo+ICt7Cj4gKwlfX2ZvcmdldF9jYWNoZWRfYWNsKCZpbm9kZS0+ aV9hY2wpOwo+ICt9Cj4gK0VYUE9SVF9TWU1CT0xfR1BMKGZvcmdldF9jYWNoZWRfcmljaGFjbCk7 Cj4gKwo+ICtzdHJ1Y3QgcmljaGFjbCAqZ2V0X3JpY2hhY2woc3RydWN0IGlub2RlICppbm9kZSkK PiArewo+ICsJc3RydWN0IGJhc2VfYWNsICpzZW50aW5lbCwgKmJhc2VfYWNsOwo+ICsJc3RydWN0 IHJpY2hhY2wgKmFjbDsKPiArCj4gKwlpZiAoIUlTX1JJQ0hBQ0woaW5vZGUpKQo+ICsJCXJldHVy biBOVUxMOwo+ICsKPiArCS8qCj4gKwnCoCogVGhlIHNlbnRpbmVsIGlzIHVzZWQgdG8gZGV0ZWN0 IHdoZW4gYW5vdGhlciBvcGVyYXRpb24gbGlrZQo+ICsJwqAqIHNldF9jYWNoZWRfcmljaGFjbCgp IG9yIGZvcmdldF9jYWNoZWRfcmljaGFjbCgpIHJhY2VzIHdpdGgKPiArCcKgKiBnZXRfcmljaGFj bCgpLgo+ICsJwqAqIEl0IGlzIGd1YXJhbnRlZWQgdGhhdCBpc191bmNhY2hlZF9hY2woc2VudGlu ZWwpIGlzIHRydWUuCj4gKwnCoCovCj4gKwo+ICsJYmFzZV9hY2wgPSBfX2dldF9jYWNoZWRfYWNs KCZpbm9kZS0+aV9hY2wpOwo+ICsJaWYgKCFpc191bmNhY2hlZF9hY2woYmFzZV9hY2wpKQo+ICsJ CXJldHVybiByaWNoYWNsKGJhc2VfYWNsKTsKPiArCj4gKwlzZW50aW5lbCA9IHVuY2FjaGVkX2Fj bF9zZW50aW5lbChjdXJyZW50KTsKPiArCj4gKwkvKgo+ICsJwqAqIElmIHRoZSBBQ0wgaXNuJ3Qg YmVpbmcgcmVhZCB5ZXQsIHNldCBvdXIgc2VudGluZWwuwqDCoE90aGVyd2lzZSwgdGhlCj4gKwnC oCogY3VycmVudCB2YWx1ZSBvZiB0aGUgQUNMIHdpbGwgbm90IGJlIEFDTF9OT1RfQ0FDSEVEIGFu ZCBzbyBvdXIgb3duCj4gKwnCoCogc2VudGluZWwgd2lsbCBub3QgYmUgc2V0OyBhbm90aGVyIHRh c2sgd2lsbCB1cGRhdGUgdGhlIGNhY2hlLsKgwqBXZQo+ICsJwqAqIGNvdWxkIHdhaXQgZm9yIHRo YXQgb3RoZXIgdGFzayB0byBjb21wbGV0ZSBpdHMgam9iLCBidXQgaXQncyBlYXNpZXIKPiArCcKg KiB0byBqdXN0IGNhbGwgLT5nZXRfYWNsIHRvIGZldGNoIHRoZSBBQ0wgb3Vyc2VsZi7CoMKgKFRo aXMgaXMgZ29pbmcgdG8KPiArCcKgKiBiZSBhbiB1bmxpa2VseSByYWNlLikKPiArCcKgKi8KPiAr CWlmIChjbXB4Y2hnKCZpbm9kZS0+aV9hY2wsIEFDTF9OT1RfQ0FDSEVELCBzZW50aW5lbCkgIT0g QUNMX05PVF9DQUNIRUQpCj4gKwkJLyogZmFsbCB0aHJvdWdoICovIDsKPiArCgpTbyB5b3UgZG8g dGhlIHNhbWUgdGhpbmcgcmVnYXJkbGVzcyBvZiB0aGUgb3V0Y29tZSBvZiB0aGUgYWJvdmU/IFdo eQpib3RoZXIgd2l0aCB0aGUgaWYgYXQgYWxsIGhlcmU/IEp1c3QgZG8gdGhlIGNtcHhjaGcgYW5k IHRvc3Mgb3V0IHRoZQpyZXN1bHQuCgo+ICsJLyoKPiArCcKgKiBOb3JtYWxseSwgdGhlIEFDTCBy ZXR1cm5lZCBieSAtPmdldF9yaWNoYWNsIHdpbGwgYmUgY2FjaGVkLgo+ICsJwqAqIEEgZmlsZXN5 c3RlbSBjYW4gcHJldmVudCB0aGF0IGJ5IGNhbGxpbmcKPiArCcKgKiBmb3JnZXRfY2FjaGVkX3Jp Y2hhY2woaW5vZGUpIGluIC0+Z2V0X3JpY2hhY2wuCj4gKwnCoCoKPiArCcKgKiBJZiB0aGUgZmls ZXN5c3RlbSBkb2Vzbid0IGhhdmUgYSAtPmdldF9yaWNoYWNsIGZ1bmN0aW9uIGF0IGFsbCwKPiAr CcKgKiB3ZSdsbCBqdXN0IGNyZWF0ZSB0aGUgbmVnYXRpdmUgY2FjaGUgZW50cnkuCj4gKwnCoCov Cj4gKwlpZiAoIWlub2RlLT5pX29wLT5nZXRfcmljaGFjbCkgewo+ICsJCXNldF9jYWNoZWRfcmlj aGFjbChpbm9kZSwgTlVMTCk7Cj4gKwkJcmV0dXJuIE5VTEw7Cj4gKwl9Cj4gKwo+ICsJYWNsID0g aW5vZGUtPmlfb3AtPmdldF9yaWNoYWNsKGlub2RlKTsKPiArCWlmIChJU19FUlIoYWNsKSkgewo+ ICsJCS8qCj4gKwkJwqAqIFJlbW92ZSBvdXIgc2VudGluZWwgc28gdGhhdCB3ZSBkb24ndCBibG9j ayBmdXR1cmUgYXR0ZW1wdHMKPiArCQnCoCogdG8gY2FjaGUgdGhlIEFDTC4KPiArCQnCoCovCj4g KwkJY21weGNoZygmaW5vZGUtPmlfYWNsLCBzZW50aW5lbCwgQUNMX05PVF9DQUNIRUQpOwo+ICsJ CXJldHVybiBhY2w7Cj4gKwl9Cj4gKwoKU28gdGhpcyBpcyBzb3J0IG9mIGlja3k6IG9ubHkgdGhl IHRhc2sgdGhhdCBzZXRzIHRoZSBzZW50aW5lbCBjYW4gc2V0CnRoZSBjYWNoZWQgYWNsLgoKWW91 IGNvdWxkIGhhdmUgb25lIHRhc2sgc2V0IHRoZSBzZW50aW5lbCwgY2FsbCBnZXRfcmljaGFjbCBh bmQgZmFpbCwgYnV0IHRoZW4gYSBjb25jdXJyZW50IHRhc2sgYWxzbyBpc3N1ZXMgYSBnZXRfcmlj aGFjbCBhbmQgc3VjY2VlZHMuIFRoYXQgdGFzayB3aWxsIGdldCBpdHMgYWNsLCBidXQgaXQgZG9l c24ndCBlbmQgdXAgZ2V0dGluZyBjYWNoZWQgYW5kIHN1YnNlcXVlbnQgY2FsbGVycyB0aGVuIGhh dmUgdG8gcmVpc3N1ZSB0aGUgcmVxdWVzdC4gSXQgd291bGQgYmUgZ29vZCBpZiB0aGUgZmlyc3Qg c3VjY2Vzc2Z1bCBmZXRjaCBvZiB0aGUgYWNsIHNldHMgaXQgaW4gdGhlIGNhY2hlLgoKVGhhdCBz YWlkLCBnZXR0aW5nIHRoZSBhY2wgY291bGQgYmUgcHJldHR5IGV4cGVuc2l2ZSB3aXRoIHNvbWUg ZmlsZXN5c3RlbXMuIE5GUyBvciBDSUZTIGFyZSBnb2luZyB0byBoYXZlIHRvIGRvIGFuIG9uIHRo ZSB3aXJlIGNhbGwgdG8gZmV0Y2ggdGhlbSwgZm9yIGluc3RhbmNlLiBJIHRoaW5rIGl0IHdvdWxk IGJlIGJldHRlciB0byBoYXZlIGNvbmN1cnJlbnQgY2FsbGVycyB3YWl0IGZvciB0aGUgZmlyc3Qg Y2FsbGVyJ3MgcmVzdWx0IGluc3RlYWQgb2YgaXNzdWluZyBwYXJhbGxlbCBnZXRfcmljaGFjbCBy ZXF1ZXN0cy4KCj4gKwkvKgo+ICsJwqAqIENhY2hlIHRoZSByZXN1bHQsIGJ1dCBvbmx5IGlmIG91 ciBzZW50aW5lbCBpcyBzdGlsbCBpbiBwbGFjZS4KPiArCcKgKi8KPiArCXJpY2hhY2xfZ2V0KGFj bCk7Cj4gKwlpZiAodW5saWtlbHkoY21weGNoZygmaW5vZGUtPmlfYWNsLCBzZW50aW5lbCwgJmFj bC0+YV9iYXNlKSAhPSBzZW50aW5lbCkpCj4gKwkJcmljaGFjbF9wdXQoYWNsKTsKPiArCXJldHVy biBhY2w7Cj4gK30KPiArRVhQT1JUX1NZTUJPTF9HUEwoZ2V0X3JpY2hhY2wpOwo+ICsKPiDCoC8q Kgo+IMKgICogcmljaGFjbF9hbGxvY8KgwqAtwqDCoGFsbG9jYXRlIGEgcmljaGFjbAo+IMKgICog QGNvdW50OgludW1iZXIgb2YgZW50cmllcwo+IGRpZmYgLS1naXQgYS9pbmNsdWRlL2xpbnV4L2Zz LmggYi9pbmNsdWRlL2xpbnV4L2ZzLmgKPiBpbmRleCBhYzk2YmRhLi40ZDcyYTZkIDEwMDY0NAo+ IC0tLSBhL2luY2x1ZGUvbGludXgvZnMuaAo+ICsrKyBiL2luY2x1ZGUvbGludXgvZnMuaAo+IEBA IC01ODksNiArNTg5LDcgQEAgc3RydWN0IGJhc2VfYWNsIHsKPiDCoAl9Owo+IMKgfTsKPiDCoHN0 cnVjdCBwb3NpeF9hY2w7Cj4gK3N0cnVjdCByaWNoYWNsOwo+IMKgI2RlZmluZSBBQ0xfTk9UX0NB Q0hFRCAoKHZvaWQgKikoLTEpKQo+IMKgCj4gwqBzdGF0aWMgaW5saW5lIHN0cnVjdCBiYXNlX2Fj bCAqCj4gQEAgLTYxOSw5ICs2MjAsMTEgQEAgc3RydWN0IGlub2RlIHsKPiDCoAlrZ2lkX3QJCQlp X2dpZDsKPiDCoAl1bnNpZ25lZCBpbnQJCWlfZmxhZ3M7Cj4gwqAKPiAtI2lmIGRlZmluZWQoQ09O RklHX0ZTX1BPU0lYX0FDTCkKPiArI2lmIGRlZmluZWQoQ09ORklHX0ZTX1BPU0lYX0FDTCkgfHwg ZGVmaW5lZChDT05GSUdfRlNfUklDSEFDTCkKPiDCoAlzdHJ1Y3QgYmFzZV9hY2wJCSppX2FjbDsK PiArIyBpZiBkZWZpbmVkKENPTkZJR19GU19QT1NJWF9BQ0wpCj4gwqAJc3RydWN0IGJhc2VfYWNs CQkqaV9kZWZhdWx0X2FjbDsKPiArIyBlbmRpZgo+IMKgI2VuZGlmCj4gwqAKCk9oLCBzbyBpZiB3 ZSBjb21waWxlIGluIHJpY2hhY2xzIGFuZCBub3QgcG9zaXggYWNscywgd2Ugc2hyaW5rIHRoZQpp bm9kZSBieSBhIHBvaW50ZXIuIE5pY2UhCgo+IMKgCWNvbnN0IHN0cnVjdCBpbm9kZV9vcGVyYXRp b25zCSppX29wOwo+IGRpZmYgLS1naXQgYS9pbmNsdWRlL2xpbnV4L3JpY2hhY2wuaCBiL2luY2x1 ZGUvbGludXgvcmljaGFjbC5oCj4gaW5kZXggMzVhNWJjYi4uM2UwNWM5NCAxMDA2NDQKPiAtLS0g YS9pbmNsdWRlL2xpbnV4L3JpY2hhY2wuaAo+ICsrKyBiL2luY2x1ZGUvbGludXgvcmljaGFjbC5o Cj4gQEAgLTcwLDYgKzcwLDE3IEBAIHJpY2hhY2xfcHV0KHN0cnVjdCByaWNoYWNsICphY2wpCj4g wqAJYmFzZV9hY2xfcHV0KCZhY2wtPmFfYmFzZSk7Cj4gwqB9Cj4gwqAKPiArc3RhdGljIGlubGlu ZSBzdHJ1Y3QgcmljaGFjbCAqCj4gK3JpY2hhY2woc3RydWN0IGJhc2VfYWNsICpiYXNlX2FjbCkK PiArewo+ICsJQlVJTERfQlVHX09OKG9mZnNldG9mKHN0cnVjdCByaWNoYWNsLCBhX2Jhc2UpICE9 IDApOwo+ICsJcmV0dXJuIGNvbnRhaW5lcl9vZihiYXNlX2FjbCwgc3RydWN0IHJpY2hhY2wsIGFf YmFzZSk7Cj4gK30KPiArCj4gK2V4dGVybiB2b2lkIHNldF9jYWNoZWRfcmljaGFjbChzdHJ1Y3Qg aW5vZGUgKiwgc3RydWN0IHJpY2hhY2wgKik7Cj4gK2V4dGVybiB2b2lkIGZvcmdldF9jYWNoZWRf cmljaGFjbChzdHJ1Y3QgaW5vZGUgKik7Cj4gK2V4dGVybiBzdHJ1Y3QgcmljaGFjbCAqZ2V0X3Jp Y2hhY2woc3RydWN0IGlub2RlICopOwo+ICsKPiDCoC8qKgo+IMKgICogcmljaGFjZV9pc19vd25l csKgwqAtwqDCoGNoZWNrIGlmIEBhY2UgaXMgYW4gT1dORVJAIGVudHJ5Cj4gwqAgKi8KCi0tIApK ZWZmIExheXRvbiA8amxheXRvbkByZWRoYXQuY29tPgoKX19fX19fX19fX19fX19fX19fX19fX19f X19fX19fX19fX19fX19fX19fX19fX18KeGZzIG1haWxpbmcgbGlzdAp4ZnNAb3NzLnNnaS5jb20K aHR0cDovL29zcy5zZ2kuY29tL21haWxtYW4vbGlzdGluZm8veGZzCg==