From mboxrd@z Thu Jan 1 00:00:00 1970 From: Jeff Layton Subject: Re: [PATCH v23 11/22] vfs: Cache base_acl objects in inodes Date: Tue, 05 Jul 2016 11:56:03 -0400 Message-ID: <1467734163.3800.43.camel@redhat.com> References: <1467294433-3222-1-git-send-email-agruenba@redhat.com> <1467294433-3222-12-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, Andreas Dilger To: Andreas Gruenbacher , Alexander Viro Return-path: In-Reply-To: <1467294433-3222-12-git-send-email-agruenba-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org> Sender: linux-cifs-owner-u79uwXL29TY76Z2rM5mHXA@public.gmane.org List-ID: On Thu, 2016-06-30 at 15:47 +0200, Andreas Gruenbacher wrote: > POSIX ACLs and richacls are both objects allocated by kmalloc() with = a > reference count which are freed by kfree_rcu().=C2=A0=C2=A0An inode c= an either > cache an access and a default POSIX ACL, or a richacl (richacls do no= t > have default acls).=C2=A0=C2=A0To allow an inode to cache either of t= he two kinds > of acls, introduce a new base_acl type and convert i_acl and > i_default_acl to that type. In most cases, the vfs then doesn't care = which > kind of acl an inode caches (if any). >=20 > Signed-off-by: Andreas Gruenbacher > Cc: Andreas Dilger > --- > =C2=A0drivers/staging/lustre/lustre/llite/llite_lib.c |=C2=A0=C2=A02 = +- > =C2=A0fs/9p/acl.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=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=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0=C2=A0|=C2=A0=C2=A08 +-- > =C2=A0fs/f2fs/acl.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=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=C2=A0=C2=A0=C2=A0=C2=A0=C2= =A0=C2=A0=C2=A0|=C2=A0=C2=A04 +- > =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=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=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0| 32 +++++++++++- > =C2=A0fs/jffs2/acl.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=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=C2=A0=C2=A0=C2=A0=C2=A0=C2= =A0=C2=A0|=C2=A0=C2=A06 ++- > =C2=A0fs/namei.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=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=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0| 33 ++++++------ > =C2=A0fs/nfs/nfs3acl.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=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=C2=A0=C2=A0=C2=A0=C2=A0= | 14 ++--- > =C2=A0fs/posix_acl.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=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=C2=A0=C2=A0=C2=A0=C2=A0=C2= =A0=C2=A0| 69 +++++++------------------ > =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=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=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2= =A0=C2=A0=C2=A0=C2=A0|=C2=A0=C2=A04 +- > =C2=A0include/linux/fs.h=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=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=C2=A0=C2=A0| 41 +++= ++++++++++-- > =C2=A0include/linux/posix_acl.h=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=C2=A0=C2=A0=C2=A0=C2=A0=C2= =A0=C2=A0=C2=A0=C2=A0=C2=A0| 21 ++++---- > =C2=A0include/linux/richacl.h=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=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=A09 ++-- > =C2=A012 files changed, 139 insertions(+), 104 deletions(-) >=20 > diff --git a/drivers/staging/lustre/lustre/llite/llite_lib.c b/driver= s/staging/lustre/lustre/llite/llite_lib.c > index 96c7e9f..7819a7c 100644 > --- a/drivers/staging/lustre/lustre/llite/llite_lib.c > +++ b/drivers/staging/lustre/lustre/llite/llite_lib.c > @@ -1087,7 +1087,7 @@ void ll_clear_inode(struct inode *inode) > =C2=A0 } > =C2=A0#ifdef CONFIG_FS_POSIX_ACL > =C2=A0 else if (lli->lli_posix_acl) { > - LASSERT(atomic_read(&lli->lli_posix_acl->a_refcount) =3D=3D 1); > + LASSERT(base_acl_refcount(&lli->lli_posix_acl->a_base) =3D=3D 1); > =C2=A0 LASSERT(!lli->lli_remote_perms); > =C2=A0 posix_acl_release(lli->lli_posix_acl); > =C2=A0 lli->lli_posix_acl =3D NULL; > diff --git a/fs/9p/acl.c b/fs/9p/acl.c > index 0576eae..1ce572f 100644 > --- a/fs/9p/acl.c > +++ b/fs/9p/acl.c > @@ -87,14 +87,14 @@ int v9fs_get_acl(struct inode *inode, struct p9_f= id *fid) > =C2=A0 > =C2=A0static struct posix_acl *v9fs_get_cached_acl(struct inode *inod= e, int type) > =C2=A0{ > - struct posix_acl *acl; > + struct base_acl *base_acl; > =C2=A0 /* > =C2=A0 =C2=A0* 9p Always cache the acl value when > =C2=A0 =C2=A0* instantiating the inode (v9fs_inode_from_fid) > =C2=A0 =C2=A0*/ > - acl =3D get_cached_acl(inode, type); > - BUG_ON(is_uncached_acl(acl)); > - return acl; > + base_acl =3D get_cached_acl(inode, type); > + BUG_ON(is_uncached_acl(base_acl)); > + return posix_acl(base_acl); > =C2=A0} > =C2=A0 > =C2=A0struct posix_acl *v9fs_iop_get_acl(struct inode *inode, int typ= e) > diff --git a/fs/f2fs/acl.c b/fs/f2fs/acl.c > index a31c7e8..6079017 100644 > --- a/fs/f2fs/acl.c > +++ b/fs/f2fs/acl.c > @@ -267,7 +267,7 @@ static struct posix_acl *f2fs_acl_clone(const str= uct posix_acl *acl, > =C2=A0 sizeof(struct posix_acl_entry); > =C2=A0 clone =3D kmemdup(acl, size, flags); > =C2=A0 if (clone) > - atomic_set(&clone->a_refcount, 1); > + base_acl_init(&clone->a_base); > =C2=A0 } > =C2=A0 return clone; > =C2=A0} > @@ -279,7 +279,7 @@ static int f2fs_acl_create_masq(struct posix_acl = *acl, umode_t *mode_p) > =C2=A0 umode_t mode =3D *mode_p; > =C2=A0 int not_equiv =3D 0; > =C2=A0 > - /* assert(atomic_read(acl->a_refcount) =3D=3D 1); */ > + /* assert(base_acl_refcount(&acl->a_base) =3D=3D 1); */ > =C2=A0 > =C2=A0 FOREACH_ACL_ENTRY(pa, acl, pe) { > =C2=A0 switch(pa->e_tag) { > diff --git a/fs/inode.c b/fs/inode.c > index 4ccbc21..40c03a7 100644 > --- a/fs/inode.c > +++ b/fs/inode.c > @@ -240,14 +240,42 @@ void __destroy_inode(struct inode *inode) > =C2=A0 > =C2=A0#ifdef CONFIG_FS_POSIX_ACL > =C2=A0 if (inode->i_acl && !is_uncached_acl(inode->i_acl)) > - posix_acl_release(inode->i_acl); > + base_acl_put(inode->i_acl); > =C2=A0 if (inode->i_default_acl && !is_uncached_acl(inode->i_default_= acl)) > - posix_acl_release(inode->i_default_acl); > + base_acl_put(inode->i_default_acl); > =C2=A0#endif > =C2=A0 this_cpu_dec(nr_inodes); > =C2=A0} > =C2=A0EXPORT_SYMBOL(__destroy_inode); > =C2=A0 > +#ifdef CONFIG_FS_POSIX_ACL > +struct base_acl *__get_cached_acl(struct base_acl **p) > +{ > + struct base_acl *base_acl; > + > + for (;;) { > + rcu_read_lock(); > + base_acl =3D rcu_dereference(*p); > + if (!base_acl || is_uncached_acl(base_acl) || > + =C2=A0=C2=A0=C2=A0=C2=A0atomic_inc_not_zero(&base_acl->ba_refcount= )) > + break; > + rcu_read_unlock(); > + cpu_relax(); > + } > + rcu_read_unlock(); > + return base_acl; > +} > + I know this is basically copied from the existing get_cached_acl function, but I'm a little uneasy with the above (and also with the existing code that does the same thing). The ba_refcount and ba_rcu are unioned. Once you've done the final base_acl_put on the object, the you'll end up calling kfree_rcu which is going to clobber the ba_refcount. How is it then safe to rely on it still being zero for the atomic_inc_not_zero? ISTM that it would be safer to make those separate fields and not union them. =2E..or am I missing something that prevents that? > +void __forget_cached_acl(struct base_acl **p) > +{ > + struct base_acl *old; > + > + old =3D xchg(p, ACL_NOT_CACHED); > + if (!is_uncached_acl(old)) > + base_acl_put(old); > +} > +#endif > + > =C2=A0static void i_callback(struct rcu_head *head) > =C2=A0{ > =C2=A0 struct inode *inode =3D container_of(head, struct inode, i_rcu= ); > diff --git a/fs/jffs2/acl.c b/fs/jffs2/acl.c > index bc2693d..6c11909 100644 > --- a/fs/jffs2/acl.c > +++ b/fs/jffs2/acl.c > @@ -292,13 +292,15 @@ int jffs2_init_acl_post(struct inode *inode) > =C2=A0 int rc; > =C2=A0 > =C2=A0 if (inode->i_default_acl) { > - rc =3D __jffs2_set_acl(inode, JFFS2_XPREFIX_ACL_DEFAULT, inode->i_= default_acl); > + rc =3D __jffs2_set_acl(inode, JFFS2_XPREFIX_ACL_DEFAULT, > + =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0posix_acl(inode->i_default_acl)); > =C2=A0 if (rc) > =C2=A0 return rc; > =C2=A0 } > =C2=A0 > =C2=A0 if (inode->i_acl) { > - rc =3D __jffs2_set_acl(inode, JFFS2_XPREFIX_ACL_ACCESS, inode->i_a= cl); > + rc =3D __jffs2_set_acl(inode, JFFS2_XPREFIX_ACL_ACCESS, > + =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0posix_acl(inode->i_acl)); > =C2=A0 if (rc) > =C2=A0 return rc; > =C2=A0 } > diff --git a/fs/namei.c b/fs/namei.c > index 663933e..7a822d0 100644 > --- a/fs/namei.c > +++ b/fs/namei.c > @@ -259,25 +259,28 @@ void putname(struct filename *name) > =C2=A0static int check_acl(struct inode *inode, int mask) > =C2=A0{ > =C2=A0#ifdef CONFIG_FS_POSIX_ACL > - struct posix_acl *acl; > - > =C2=A0 if (mask & MAY_NOT_BLOCK) { > - acl =3D get_cached_acl_rcu(inode, ACL_TYPE_ACCESS); > - =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (!acl) > + struct base_acl *base_acl; > + > + base_acl =3D rcu_dereference(inode->i_acl); > + =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (!base_acl) > =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=C2=A0=C2=A0=C2=A0return -EAGAIN; > =C2=A0 /* no ->get_acl() calls in RCU mode... */ > - if (is_uncached_acl(acl)) > + if (is_uncached_acl(base_acl)) > =C2=A0 return -ECHILD; > - =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0return posix_acl_pe= rmission(inode, acl, mask & ~MAY_NOT_BLOCK); > - } > - > - acl =3D get_acl(inode, ACL_TYPE_ACCESS); > - if (IS_ERR(acl)) > - return PTR_ERR(acl); > - if (acl) { > - =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0int error =3D posix= _acl_permission(inode, acl, mask); > - =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0posix_acl_release(a= cl); > - =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0return error; > + =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0return posix_acl_pe= rmission(inode, posix_acl(base_acl), > + =C2=A0=C2=A0=C2=A0=C2=A0mask & ~MAY_NOT_BLOCK); > + } else { > + struct posix_acl *acl; > + > + acl =3D get_acl(inode, ACL_TYPE_ACCESS); > + if (IS_ERR(acl)) > + return PTR_ERR(acl); > + if (acl) { > + int error =3D posix_acl_permission(inode, acl, mask); > + posix_acl_release(acl); > + return error; > + } > =C2=A0 } > =C2=A0#endif > =C2=A0 > diff --git a/fs/nfs/nfs3acl.c b/fs/nfs/nfs3acl.c > index 720d92f5..2b70944 100644 > --- a/fs/nfs/nfs3acl.c > +++ b/fs/nfs/nfs3acl.c > @@ -16,28 +16,28 @@ > =C2=A0 * caching get_acl results in a race-free way.=C2=A0=C2=A0See f= s/posix_acl.c:get_acl() > =C2=A0 * for explanations. > =C2=A0 */ > -static void nfs3_prepare_get_acl(struct posix_acl **p) > +static void nfs3_prepare_get_acl(struct base_acl **p) > =C2=A0{ > - struct posix_acl *sentinel =3D uncached_acl_sentinel(current); > + struct base_acl *sentinel =3D uncached_acl_sentinel(current); > =C2=A0 > =C2=A0 if (cmpxchg(p, ACL_NOT_CACHED, sentinel) !=3D ACL_NOT_CACHED) = { > =C2=A0 /* Not the first reader or sentinel already in place. */ > =C2=A0 } > =C2=A0} > =C2=A0 > -static void nfs3_complete_get_acl(struct posix_acl **p, struct posix= _acl *acl) > +static void nfs3_complete_get_acl(struct base_acl **p, struct posix_= acl *acl) > =C2=A0{ > - struct posix_acl *sentinel =3D uncached_acl_sentinel(current); > + struct base_acl *sentinel =3D uncached_acl_sentinel(current); > =C2=A0 > =C2=A0 /* Only cache the ACL if our sentinel is still in place. */ > =C2=A0 posix_acl_dup(acl); > - if (cmpxchg(p, sentinel, acl) !=3D sentinel) > + if (cmpxchg(p, sentinel, &acl->a_base) !=3D sentinel) > =C2=A0 posix_acl_release(acl); > =C2=A0} > =C2=A0 > -static void nfs3_abort_get_acl(struct posix_acl **p) > +static void nfs3_abort_get_acl(struct base_acl **p) > =C2=A0{ > - struct posix_acl *sentinel =3D uncached_acl_sentinel(current); > + struct base_acl *sentinel =3D uncached_acl_sentinel(current); > =C2=A0 > =C2=A0 /* Remove our sentinel upon failure. */ > =C2=A0 cmpxchg(p, sentinel, ACL_NOT_CACHED); > diff --git a/fs/posix_acl.c b/fs/posix_acl.c > index edc452c..1b685a1 100644 > --- a/fs/posix_acl.c > +++ b/fs/posix_acl.c > @@ -21,7 +21,7 @@ > =C2=A0#include=20 > =C2=A0#include=20 > =C2=A0 > -static struct posix_acl **acl_by_type(struct inode *inode, int type) > +static inline struct base_acl **acl_by_type(struct inode *inode, int= type) > =C2=A0{ > =C2=A0 switch (type) { > =C2=A0 case ACL_TYPE_ACCESS: > @@ -33,51 +33,23 @@ static struct posix_acl **acl_by_type(struct inod= e *inode, int type) > =C2=A0 } > =C2=A0} > =C2=A0 > -struct posix_acl *get_cached_acl(struct inode *inode, int type) > +struct base_acl *get_cached_acl(struct inode *inode, int type) > =C2=A0{ > - struct posix_acl **p =3D acl_by_type(inode, type); > - struct posix_acl *acl; > - > - for (;;) { > - rcu_read_lock(); > - acl =3D rcu_dereference(*p); > - if (!acl || is_uncached_acl(acl) || > - =C2=A0=C2=A0=C2=A0=C2=A0atomic_inc_not_zero(&acl->a_refcount)) > - break; > - rcu_read_unlock(); > - cpu_relax(); > - } > - rcu_read_unlock(); > - return acl; > + return __get_cached_acl(acl_by_type(inode, type)); > =C2=A0} > =C2=A0EXPORT_SYMBOL(get_cached_acl); > =C2=A0 > -struct posix_acl *get_cached_acl_rcu(struct inode *inode, int type) > -{ > - return rcu_dereference(*acl_by_type(inode, type)); > -} > -EXPORT_SYMBOL(get_cached_acl_rcu); > - > =C2=A0void set_cached_acl(struct inode *inode, int type, struct posix= _acl *acl) > =C2=A0{ > - struct posix_acl **p =3D acl_by_type(inode, type); > - struct posix_acl *old; > + struct base_acl **p =3D acl_by_type(inode, type); > + struct base_acl *old; > =C2=A0 > - old =3D xchg(p, posix_acl_dup(acl)); > + old =3D xchg(p, &posix_acl_dup(acl)->a_base); > =C2=A0 if (!is_uncached_acl(old)) > - posix_acl_release(old); > + base_acl_put(old); > =C2=A0} > =C2=A0EXPORT_SYMBOL(set_cached_acl); > =C2=A0 > -static void __forget_cached_acl(struct posix_acl **p) > -{ > - struct posix_acl *old; > - > - old =3D xchg(p, ACL_NOT_CACHED); > - if (!is_uncached_acl(old)) > - posix_acl_release(old); > -} > - > =C2=A0void forget_cached_acl(struct inode *inode, int type) > =C2=A0{ > =C2=A0 __forget_cached_acl(acl_by_type(inode, type)); > @@ -93,25 +65,24 @@ EXPORT_SYMBOL(forget_all_cached_acls); > =C2=A0 > =C2=A0struct posix_acl *get_acl(struct inode *inode, int type) > =C2=A0{ > - void *sentinel; > - struct posix_acl **p; > + struct base_acl **p =3D acl_by_type(inode, type); > + struct base_acl *sentinel, *base_acl; > =C2=A0 struct posix_acl *acl; > =C2=A0 > + if (!IS_POSIXACL(inode)) > + return NULL; > + > =C2=A0 /* > =C2=A0 =C2=A0* The sentinel is used to detect when another operation = like > =C2=A0 =C2=A0* set_cached_acl() or forget_cached_acl() races with get= _acl(). > =C2=A0 =C2=A0* It is guaranteed that is_uncached_acl(sentinel) is tru= e. > =C2=A0 =C2=A0*/ > =C2=A0 > - acl =3D get_cached_acl(inode, type); > - if (!is_uncached_acl(acl)) > - return acl; > - > - if (!IS_POSIXACL(inode)) > - return NULL; > + base_acl =3D __get_cached_acl(p); > + if (!is_uncached_acl(base_acl)) > + return posix_acl(base_acl); > =C2=A0 > =C2=A0 sentinel =3D uncached_acl_sentinel(current); > - p =3D acl_by_type(inode, type); > =C2=A0 > =C2=A0 /* > =C2=A0 =C2=A0* If the ACL isn't being read yet, set our sentinel.=C2=A0= =C2=A0Otherwise, the > @@ -151,7 +122,7 @@ struct posix_acl *get_acl(struct inode *inode, in= t type) > =C2=A0 =C2=A0* Cache the result, but only if our sentinel is still in= place. > =C2=A0 =C2=A0*/ > =C2=A0 posix_acl_dup(acl); > - if (unlikely(cmpxchg(p, sentinel, acl) !=3D sentinel)) > + if (unlikely(cmpxchg(p, sentinel, &acl->a_base) !=3D sentinel)) > =C2=A0 posix_acl_release(acl); > =C2=A0 return acl; > =C2=A0} > @@ -163,7 +134,7 @@ EXPORT_SYMBOL(get_acl); > =C2=A0void > =C2=A0posix_acl_init(struct posix_acl *acl, int count) > =C2=A0{ > - atomic_set(&acl->a_refcount, 1); > + base_acl_init(&acl->a_base); > =C2=A0 acl->a_count =3D count; > =C2=A0} > =C2=A0EXPORT_SYMBOL(posix_acl_init); > @@ -196,7 +167,7 @@ posix_acl_clone(const struct posix_acl *acl, gfp_= t flags) > =C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2= =A0sizeof(struct posix_acl_entry); > =C2=A0 clone =3D kmemdup(acl, size, flags); > =C2=A0 if (clone) > - atomic_set(&clone->a_refcount, 1); > + base_acl_init(&clone->a_base); > =C2=A0 } > =C2=A0 return clone; > =C2=A0} > @@ -418,7 +389,7 @@ static int posix_acl_create_masq(struct posix_acl= *acl, umode_t *mode_p) > =C2=A0 umode_t mode =3D *mode_p; > =C2=A0 int not_equiv =3D 0; > =C2=A0 > - /* assert(atomic_read(acl->a_refcount) =3D=3D 1); */ > + /* assert(base_acl_refcount(&acl->a_base) =3D=3D 1); */ > =C2=A0 > =C2=A0 FOREACH_ACL_ENTRY(pa, acl, pe) { > =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=C2=A0=C2=A0=C2=A0switch(pa->e_tag) { > @@ -473,7 +444,7 @@ static int __posix_acl_chmod_masq(struct posix_ac= l *acl, umode_t mode) > =C2=A0 struct posix_acl_entry *group_obj =3D NULL, *mask_obj =3D NULL= ; > =C2=A0 struct posix_acl_entry *pa, *pe; > =C2=A0 > - /* assert(atomic_read(acl->a_refcount) =3D=3D 1); */ > + /* assert(base_acl_refcount(&acl->a_base) =3D=3D 1); */ > =C2=A0 > =C2=A0 FOREACH_ACL_ENTRY(pa, acl, pe) { > =C2=A0 switch(pa->e_tag) { > diff --git a/fs/richacl.c b/fs/richacl.c > index cb0ef3f..8971ead 100644 > --- a/fs/richacl.c > +++ b/fs/richacl.c > @@ -31,7 +31,7 @@ richacl_alloc(int count, gfp_t gfp) > =C2=A0 struct richacl *acl =3D kzalloc(size, gfp); > =C2=A0 > =C2=A0 if (acl) { > - atomic_set(&acl->a_refcount, 1); > + base_acl_init(&acl->a_base); > =C2=A0 acl->a_count =3D count; > =C2=A0 } > =C2=A0 return acl; > @@ -50,7 +50,7 @@ richacl_clone(const struct richacl *acl, gfp_t gfp) > =C2=A0 > =C2=A0 if (dup) { > =C2=A0 memcpy(dup, acl, size); > - atomic_set(&dup->a_refcount, 1); > + base_acl_init(&dup->a_base); > =C2=A0 } > =C2=A0 return dup; > =C2=A0} > diff --git a/include/linux/fs.h b/include/linux/fs.h > index bb36561..06a30b0 100644 > --- a/include/linux/fs.h > +++ b/include/linux/fs.h > @@ -582,17 +582,23 @@ static inline void mapping_allow_writable(struc= t address_space *mapping) > =C2=A0#define i_size_ordered_init(inode) do { } while (0) > =C2=A0#endif > =C2=A0 > +struct base_acl { > + union { > + atomic_t ba_refcount; > + struct rcu_head ba_rcu; > + }; > +}; > =C2=A0struct posix_acl; > =C2=A0#define ACL_NOT_CACHED ((void *)(-1)) > =C2=A0 > -static inline struct posix_acl * > +static inline struct base_acl * > =C2=A0uncached_acl_sentinel(struct task_struct *task) > =C2=A0{ > =C2=A0 return (void *)task + 1; > =C2=A0} > =C2=A0 > =C2=A0static inline bool > -is_uncached_acl(struct posix_acl *acl) > +is_uncached_acl(struct base_acl *acl) > =C2=A0{ > =C2=A0 return (long)acl & 1; > =C2=A0} > @@ -613,9 +619,9 @@ struct inode { > =C2=A0 kgid_t i_gid; > =C2=A0 unsigned int i_flags; > =C2=A0 > -#ifdef CONFIG_FS_POSIX_ACL > - struct posix_acl *i_acl; > - struct posix_acl *i_default_acl; > +#if defined(CONFIG_FS_POSIX_ACL) > + struct base_acl *i_acl; > + struct base_acl *i_default_acl; > =C2=A0#endif > =C2=A0 > =C2=A0 const struct inode_operations *i_op; > @@ -3193,4 +3199,29 @@ static inline bool dir_relax_shared(struct ino= de *inode) > =C2=A0extern bool path_noexec(const struct path *path); > =C2=A0extern void inode_nohighmem(struct inode *inode); > =C2=A0 > +static inline void base_acl_get(struct base_acl *acl) > +{ > + if (acl) > + atomic_inc(&acl->ba_refcount); > +} > + > +static inline void base_acl_put(struct base_acl *acl) > +{ > + if (acl && atomic_dec_and_test(&acl->ba_refcount)) > + kfree_rcu(acl, ba_rcu); > +} > + > +static inline void base_acl_init(struct base_acl *acl) > +{ > + atomic_set(&acl->ba_refcount, 1); > +} > + > +static inline int base_acl_refcount(struct base_acl *acl) > +{ > + return atomic_read(&acl->ba_refcount); > +} > + > +extern struct base_acl *__get_cached_acl(struct base_acl **); > +extern void __forget_cached_acl(struct base_acl **); > + > =C2=A0#endif /* _LINUX_FS_H */ > diff --git a/include/linux/posix_acl.h b/include/linux/posix_acl.h > index 5b5a80c..daf84fa 100644 > --- a/include/linux/posix_acl.h > +++ b/include/linux/posix_acl.h > @@ -43,10 +43,7 @@ struct posix_acl_entry { > =C2=A0}; > =C2=A0 > =C2=A0struct posix_acl { > - union { > - atomic_t a_refcount; > - struct rcu_head a_rcu; > - }; > + struct base_acl a_base;=C2=A0=C2=A0/* must be first, see posix_acl= _release() */ > =C2=A0 unsigned int a_count; > =C2=A0 struct posix_acl_entry a_entries[0]; > =C2=A0}; > @@ -61,8 +58,7 @@ struct posix_acl { > =C2=A0static inline struct posix_acl * > =C2=A0posix_acl_dup(struct posix_acl *acl) > =C2=A0{ > - if (acl) > - atomic_inc(&acl->a_refcount); > + base_acl_get(&acl->a_base); > =C2=A0 return acl; > =C2=A0} > =C2=A0 > @@ -72,10 +68,16 @@ posix_acl_dup(struct posix_acl *acl) > =C2=A0static inline void > =C2=A0posix_acl_release(struct posix_acl *acl) > =C2=A0{ > - if (acl && atomic_dec_and_test(&acl->a_refcount)) > - kfree_rcu(acl, a_rcu); > + BUILD_BUG_ON(offsetof(struct posix_acl, a_base) !=3D 0); > + base_acl_put(&acl->a_base); > =C2=A0} > =C2=A0 > +static inline struct posix_acl * > +posix_acl(struct base_acl *base_acl) > +{ > + BUILD_BUG_ON(offsetof(struct posix_acl, a_base) !=3D 0); > + return container_of(base_acl, struct posix_acl, a_base); > +} > =C2=A0 > =C2=A0/* posix_acl.c */ > =C2=A0 > @@ -99,8 +101,7 @@ extern int posix_acl_create(struct inode *, umode_= t *, struct posix_acl **, > =C2=A0extern int simple_set_acl(struct inode *, struct posix_acl *, i= nt); > =C2=A0extern int simple_acl_create(struct inode *, struct inode *); > =C2=A0 > -struct posix_acl *get_cached_acl(struct inode *inode, int type); > -struct posix_acl *get_cached_acl_rcu(struct inode *inode, int type); > +struct base_acl *get_cached_acl(struct inode *inode, int type); > =C2=A0void set_cached_acl(struct inode *inode, int type, struct posix= _acl *acl); > =C2=A0void forget_cached_acl(struct inode *inode, int type); > =C2=A0void forget_all_cached_acls(struct inode *inode); > diff --git a/include/linux/richacl.h b/include/linux/richacl.h > index be9fb65..35a5bcb 100644 > --- a/include/linux/richacl.h > +++ b/include/linux/richacl.h > @@ -31,7 +31,7 @@ struct richace { > =C2=A0}; > =C2=A0 > =C2=A0struct richacl { > - atomic_t a_refcount; > + struct base_acl a_base;=C2=A0=C2=A0/* must be first, see richacl_pu= t() */ > =C2=A0 unsigned int a_owner_mask; > =C2=A0 unsigned int a_group_mask; > =C2=A0 unsigned int a_other_mask; > @@ -56,8 +56,7 @@ struct richacl { > =C2=A0static inline struct richacl * > =C2=A0richacl_get(struct richacl *acl) > =C2=A0{ > - if (acl) > - atomic_inc(&acl->a_refcount); > + base_acl_get(&acl->a_base); > =C2=A0 return acl; > =C2=A0} > =C2=A0 > @@ -67,8 +66,8 @@ richacl_get(struct richacl *acl) > =C2=A0static inline void > =C2=A0richacl_put(struct richacl *acl) > =C2=A0{ > - if (acl && atomic_dec_and_test(&acl->a_refcount)) > - kfree(acl); > + BUILD_BUG_ON(offsetof(struct richacl, a_base) !=3D 0); > + base_acl_put(&acl->a_base); > =C2=A0} > =C2=A0 > =C2=A0/** -- Jeff Layton From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755393AbcGEP4N (ORCPT ); Tue, 5 Jul 2016 11:56:13 -0400 Received: from mail-qk0-f176.google.com ([209.85.220.176]:35797 "EHLO mail-qk0-f176.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754770AbcGEP4I (ORCPT ); Tue, 5 Jul 2016 11:56:08 -0400 Message-ID: <1467734163.3800.43.camel@redhat.com> Subject: Re: [PATCH v23 11/22] vfs: Cache base_acl objects in inodes 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, Andreas Dilger Date: Tue, 05 Jul 2016 11:56:03 -0400 In-Reply-To: <1467294433-3222-12-git-send-email-agruenba@redhat.com> References: <1467294433-3222-1-git-send-email-agruenba@redhat.com> <1467294433-3222-12-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: > POSIX ACLs and richacls are both objects allocated by kmalloc() with a > reference count which are freed by kfree_rcu().  An inode can either > cache an access and a default POSIX ACL, or a richacl (richacls do not > have default acls).  To allow an inode to cache either of the two kinds > of acls, introduce a new base_acl type and convert i_acl and > i_default_acl to that type. In most cases, the vfs then doesn't care which > kind of acl an inode caches (if any). > > Signed-off-by: Andreas Gruenbacher > Cc: Andreas Dilger > --- >  drivers/staging/lustre/lustre/llite/llite_lib.c |  2 +- >  fs/9p/acl.c                                     |  8 +-- >  fs/f2fs/acl.c                                   |  4 +- >  fs/inode.c                                      | 32 +++++++++++- >  fs/jffs2/acl.c                                  |  6 ++- >  fs/namei.c                                      | 33 ++++++------ >  fs/nfs/nfs3acl.c                                | 14 ++--- >  fs/posix_acl.c                                  | 69 +++++++------------------ >  fs/richacl.c                                    |  4 +- >  include/linux/fs.h                              | 41 +++++++++++++-- >  include/linux/posix_acl.h                       | 21 ++++---- >  include/linux/richacl.h                         |  9 ++-- >  12 files changed, 139 insertions(+), 104 deletions(-) > > diff --git a/drivers/staging/lustre/lustre/llite/llite_lib.c b/drivers/staging/lustre/lustre/llite/llite_lib.c > index 96c7e9f..7819a7c 100644 > --- a/drivers/staging/lustre/lustre/llite/llite_lib.c > +++ b/drivers/staging/lustre/lustre/llite/llite_lib.c > @@ -1087,7 +1087,7 @@ void ll_clear_inode(struct inode *inode) >   } >  #ifdef CONFIG_FS_POSIX_ACL >   else if (lli->lli_posix_acl) { > - LASSERT(atomic_read(&lli->lli_posix_acl->a_refcount) == 1); > + LASSERT(base_acl_refcount(&lli->lli_posix_acl->a_base) == 1); >   LASSERT(!lli->lli_remote_perms); >   posix_acl_release(lli->lli_posix_acl); >   lli->lli_posix_acl = NULL; > diff --git a/fs/9p/acl.c b/fs/9p/acl.c > index 0576eae..1ce572f 100644 > --- a/fs/9p/acl.c > +++ b/fs/9p/acl.c > @@ -87,14 +87,14 @@ int v9fs_get_acl(struct inode *inode, struct p9_fid *fid) >   >  static struct posix_acl *v9fs_get_cached_acl(struct inode *inode, int type) >  { > - struct posix_acl *acl; > + struct base_acl *base_acl; >   /* >    * 9p Always cache the acl value when >    * instantiating the inode (v9fs_inode_from_fid) >    */ > - acl = get_cached_acl(inode, type); > - BUG_ON(is_uncached_acl(acl)); > - return acl; > + base_acl = get_cached_acl(inode, type); > + BUG_ON(is_uncached_acl(base_acl)); > + return posix_acl(base_acl); >  } >   >  struct posix_acl *v9fs_iop_get_acl(struct inode *inode, int type) > diff --git a/fs/f2fs/acl.c b/fs/f2fs/acl.c > index a31c7e8..6079017 100644 > --- a/fs/f2fs/acl.c > +++ b/fs/f2fs/acl.c > @@ -267,7 +267,7 @@ static struct posix_acl *f2fs_acl_clone(const struct posix_acl *acl, >   sizeof(struct posix_acl_entry); >   clone = kmemdup(acl, size, flags); >   if (clone) > - atomic_set(&clone->a_refcount, 1); > + base_acl_init(&clone->a_base); >   } >   return clone; >  } > @@ -279,7 +279,7 @@ static int f2fs_acl_create_masq(struct posix_acl *acl, umode_t *mode_p) >   umode_t mode = *mode_p; >   int not_equiv = 0; >   > - /* assert(atomic_read(acl->a_refcount) == 1); */ > + /* assert(base_acl_refcount(&acl->a_base) == 1); */ >   >   FOREACH_ACL_ENTRY(pa, acl, pe) { >   switch(pa->e_tag) { > diff --git a/fs/inode.c b/fs/inode.c > index 4ccbc21..40c03a7 100644 > --- a/fs/inode.c > +++ b/fs/inode.c > @@ -240,14 +240,42 @@ void __destroy_inode(struct inode *inode) >   >  #ifdef CONFIG_FS_POSIX_ACL >   if (inode->i_acl && !is_uncached_acl(inode->i_acl)) > - posix_acl_release(inode->i_acl); > + base_acl_put(inode->i_acl); >   if (inode->i_default_acl && !is_uncached_acl(inode->i_default_acl)) > - posix_acl_release(inode->i_default_acl); > + base_acl_put(inode->i_default_acl); >  #endif >   this_cpu_dec(nr_inodes); >  } >  EXPORT_SYMBOL(__destroy_inode); >   > +#ifdef CONFIG_FS_POSIX_ACL > +struct base_acl *__get_cached_acl(struct base_acl **p) > +{ > + struct base_acl *base_acl; > + > + for (;;) { > + rcu_read_lock(); > + base_acl = rcu_dereference(*p); > + if (!base_acl || is_uncached_acl(base_acl) || > +     atomic_inc_not_zero(&base_acl->ba_refcount)) > + break; > + rcu_read_unlock(); > + cpu_relax(); > + } > + rcu_read_unlock(); > + return base_acl; > +} > + I know this is basically copied from the existing get_cached_acl function, but I'm a little uneasy with the above (and also with the existing code that does the same thing). The ba_refcount and ba_rcu are unioned. Once you've done the final base_acl_put on the object, the you'll end up calling kfree_rcu which is going to clobber the ba_refcount. How is it then safe to rely on it still being zero for the atomic_inc_not_zero? ISTM that it would be safer to make those separate fields and not union them. ...or am I missing something that prevents that? > +void __forget_cached_acl(struct base_acl **p) > +{ > + struct base_acl *old; > + > + old = xchg(p, ACL_NOT_CACHED); > + if (!is_uncached_acl(old)) > + base_acl_put(old); > +} > +#endif > + >  static void i_callback(struct rcu_head *head) >  { >   struct inode *inode = container_of(head, struct inode, i_rcu); > diff --git a/fs/jffs2/acl.c b/fs/jffs2/acl.c > index bc2693d..6c11909 100644 > --- a/fs/jffs2/acl.c > +++ b/fs/jffs2/acl.c > @@ -292,13 +292,15 @@ int jffs2_init_acl_post(struct inode *inode) >   int rc; >   >   if (inode->i_default_acl) { > - rc = __jffs2_set_acl(inode, JFFS2_XPREFIX_ACL_DEFAULT, inode->i_default_acl); > + rc = __jffs2_set_acl(inode, JFFS2_XPREFIX_ACL_DEFAULT, > +      posix_acl(inode->i_default_acl)); >   if (rc) >   return rc; >   } >   >   if (inode->i_acl) { > - rc = __jffs2_set_acl(inode, JFFS2_XPREFIX_ACL_ACCESS, inode->i_acl); > + rc = __jffs2_set_acl(inode, JFFS2_XPREFIX_ACL_ACCESS, > +      posix_acl(inode->i_acl)); >   if (rc) >   return rc; >   } > diff --git a/fs/namei.c b/fs/namei.c > index 663933e..7a822d0 100644 > --- a/fs/namei.c > +++ b/fs/namei.c > @@ -259,25 +259,28 @@ void putname(struct filename *name) >  static int check_acl(struct inode *inode, int mask) >  { >  #ifdef CONFIG_FS_POSIX_ACL > - struct posix_acl *acl; > - >   if (mask & MAY_NOT_BLOCK) { > - acl = get_cached_acl_rcu(inode, ACL_TYPE_ACCESS); > -         if (!acl) > + struct base_acl *base_acl; > + > + base_acl = rcu_dereference(inode->i_acl); > +         if (!base_acl) >                   return -EAGAIN; >   /* no ->get_acl() calls in RCU mode... */ > - if (is_uncached_acl(acl)) > + if (is_uncached_acl(base_acl)) >   return -ECHILD; > -         return posix_acl_permission(inode, acl, mask & ~MAY_NOT_BLOCK); > - } > - > - acl = get_acl(inode, ACL_TYPE_ACCESS); > - if (IS_ERR(acl)) > - return PTR_ERR(acl); > - if (acl) { > -         int error = posix_acl_permission(inode, acl, mask); > -         posix_acl_release(acl); > -         return error; > +         return posix_acl_permission(inode, posix_acl(base_acl), > +     mask & ~MAY_NOT_BLOCK); > + } else { > + struct posix_acl *acl; > + > + acl = get_acl(inode, ACL_TYPE_ACCESS); > + if (IS_ERR(acl)) > + return PTR_ERR(acl); > + if (acl) { > + int error = posix_acl_permission(inode, acl, mask); > + posix_acl_release(acl); > + return error; > + } >   } >  #endif >   > diff --git a/fs/nfs/nfs3acl.c b/fs/nfs/nfs3acl.c > index 720d92f5..2b70944 100644 > --- a/fs/nfs/nfs3acl.c > +++ b/fs/nfs/nfs3acl.c > @@ -16,28 +16,28 @@ >   * caching get_acl results in a race-free way.  See fs/posix_acl.c:get_acl() >   * for explanations. >   */ > -static void nfs3_prepare_get_acl(struct posix_acl **p) > +static void nfs3_prepare_get_acl(struct base_acl **p) >  { > - struct posix_acl *sentinel = uncached_acl_sentinel(current); > + struct base_acl *sentinel = uncached_acl_sentinel(current); >   >   if (cmpxchg(p, ACL_NOT_CACHED, sentinel) != ACL_NOT_CACHED) { >   /* Not the first reader or sentinel already in place. */ >   } >  } >   > -static void nfs3_complete_get_acl(struct posix_acl **p, struct posix_acl *acl) > +static void nfs3_complete_get_acl(struct base_acl **p, struct posix_acl *acl) >  { > - struct posix_acl *sentinel = uncached_acl_sentinel(current); > + struct base_acl *sentinel = uncached_acl_sentinel(current); >   >   /* Only cache the ACL if our sentinel is still in place. */ >   posix_acl_dup(acl); > - if (cmpxchg(p, sentinel, acl) != sentinel) > + if (cmpxchg(p, sentinel, &acl->a_base) != sentinel) >   posix_acl_release(acl); >  } >   > -static void nfs3_abort_get_acl(struct posix_acl **p) > +static void nfs3_abort_get_acl(struct base_acl **p) >  { > - struct posix_acl *sentinel = uncached_acl_sentinel(current); > + struct base_acl *sentinel = uncached_acl_sentinel(current); >   >   /* Remove our sentinel upon failure. */ >   cmpxchg(p, sentinel, ACL_NOT_CACHED); > diff --git a/fs/posix_acl.c b/fs/posix_acl.c > index edc452c..1b685a1 100644 > --- a/fs/posix_acl.c > +++ b/fs/posix_acl.c > @@ -21,7 +21,7 @@ >  #include >  #include >   > -static struct posix_acl **acl_by_type(struct inode *inode, int type) > +static inline struct base_acl **acl_by_type(struct inode *inode, int type) >  { >   switch (type) { >   case ACL_TYPE_ACCESS: > @@ -33,51 +33,23 @@ static struct posix_acl **acl_by_type(struct inode *inode, int type) >   } >  } >   > -struct posix_acl *get_cached_acl(struct inode *inode, int type) > +struct base_acl *get_cached_acl(struct inode *inode, int type) >  { > - struct posix_acl **p = acl_by_type(inode, type); > - struct posix_acl *acl; > - > - for (;;) { > - rcu_read_lock(); > - acl = rcu_dereference(*p); > - if (!acl || is_uncached_acl(acl) || > -     atomic_inc_not_zero(&acl->a_refcount)) > - break; > - rcu_read_unlock(); > - cpu_relax(); > - } > - rcu_read_unlock(); > - return acl; > + return __get_cached_acl(acl_by_type(inode, type)); >  } >  EXPORT_SYMBOL(get_cached_acl); >   > -struct posix_acl *get_cached_acl_rcu(struct inode *inode, int type) > -{ > - return rcu_dereference(*acl_by_type(inode, type)); > -} > -EXPORT_SYMBOL(get_cached_acl_rcu); > - >  void set_cached_acl(struct inode *inode, int type, struct posix_acl *acl) >  { > - struct posix_acl **p = acl_by_type(inode, type); > - struct posix_acl *old; > + struct base_acl **p = acl_by_type(inode, type); > + struct base_acl *old; >   > - old = xchg(p, posix_acl_dup(acl)); > + old = xchg(p, &posix_acl_dup(acl)->a_base); >   if (!is_uncached_acl(old)) > - posix_acl_release(old); > + base_acl_put(old); >  } >  EXPORT_SYMBOL(set_cached_acl); >   > -static void __forget_cached_acl(struct posix_acl **p) > -{ > - struct posix_acl *old; > - > - old = xchg(p, ACL_NOT_CACHED); > - if (!is_uncached_acl(old)) > - posix_acl_release(old); > -} > - >  void forget_cached_acl(struct inode *inode, int type) >  { >   __forget_cached_acl(acl_by_type(inode, type)); > @@ -93,25 +65,24 @@ EXPORT_SYMBOL(forget_all_cached_acls); >   >  struct posix_acl *get_acl(struct inode *inode, int type) >  { > - void *sentinel; > - struct posix_acl **p; > + struct base_acl **p = acl_by_type(inode, type); > + struct base_acl *sentinel, *base_acl; >   struct posix_acl *acl; >   > + if (!IS_POSIXACL(inode)) > + return NULL; > + >   /* >    * The sentinel is used to detect when another operation like >    * set_cached_acl() or forget_cached_acl() races with get_acl(). >    * It is guaranteed that is_uncached_acl(sentinel) is true. >    */ >   > - acl = get_cached_acl(inode, type); > - if (!is_uncached_acl(acl)) > - return acl; > - > - if (!IS_POSIXACL(inode)) > - return NULL; > + base_acl = __get_cached_acl(p); > + if (!is_uncached_acl(base_acl)) > + return posix_acl(base_acl); >   >   sentinel = uncached_acl_sentinel(current); > - p = acl_by_type(inode, type); >   >   /* >    * If the ACL isn't being read yet, set our sentinel.  Otherwise, the > @@ -151,7 +122,7 @@ struct posix_acl *get_acl(struct inode *inode, int type) >    * Cache the result, but only if our sentinel is still in place. >    */ >   posix_acl_dup(acl); > - if (unlikely(cmpxchg(p, sentinel, acl) != sentinel)) > + if (unlikely(cmpxchg(p, sentinel, &acl->a_base) != sentinel)) >   posix_acl_release(acl); >   return acl; >  } > @@ -163,7 +134,7 @@ EXPORT_SYMBOL(get_acl); >  void >  posix_acl_init(struct posix_acl *acl, int count) >  { > - atomic_set(&acl->a_refcount, 1); > + base_acl_init(&acl->a_base); >   acl->a_count = count; >  } >  EXPORT_SYMBOL(posix_acl_init); > @@ -196,7 +167,7 @@ posix_acl_clone(const struct posix_acl *acl, gfp_t flags) >              sizeof(struct posix_acl_entry); >   clone = kmemdup(acl, size, flags); >   if (clone) > - atomic_set(&clone->a_refcount, 1); > + base_acl_init(&clone->a_base); >   } >   return clone; >  } > @@ -418,7 +389,7 @@ static int posix_acl_create_masq(struct posix_acl *acl, umode_t *mode_p) >   umode_t mode = *mode_p; >   int not_equiv = 0; >   > - /* assert(atomic_read(acl->a_refcount) == 1); */ > + /* assert(base_acl_refcount(&acl->a_base) == 1); */ >   >   FOREACH_ACL_ENTRY(pa, acl, pe) { >                  switch(pa->e_tag) { > @@ -473,7 +444,7 @@ static int __posix_acl_chmod_masq(struct posix_acl *acl, umode_t mode) >   struct posix_acl_entry *group_obj = NULL, *mask_obj = NULL; >   struct posix_acl_entry *pa, *pe; >   > - /* assert(atomic_read(acl->a_refcount) == 1); */ > + /* assert(base_acl_refcount(&acl->a_base) == 1); */ >   >   FOREACH_ACL_ENTRY(pa, acl, pe) { >   switch(pa->e_tag) { > diff --git a/fs/richacl.c b/fs/richacl.c > index cb0ef3f..8971ead 100644 > --- a/fs/richacl.c > +++ b/fs/richacl.c > @@ -31,7 +31,7 @@ richacl_alloc(int count, gfp_t gfp) >   struct richacl *acl = kzalloc(size, gfp); >   >   if (acl) { > - atomic_set(&acl->a_refcount, 1); > + base_acl_init(&acl->a_base); >   acl->a_count = count; >   } >   return acl; > @@ -50,7 +50,7 @@ richacl_clone(const struct richacl *acl, gfp_t gfp) >   >   if (dup) { >   memcpy(dup, acl, size); > - atomic_set(&dup->a_refcount, 1); > + base_acl_init(&dup->a_base); >   } >   return dup; >  } > diff --git a/include/linux/fs.h b/include/linux/fs.h > index bb36561..06a30b0 100644 > --- a/include/linux/fs.h > +++ b/include/linux/fs.h > @@ -582,17 +582,23 @@ static inline void mapping_allow_writable(struct address_space *mapping) >  #define i_size_ordered_init(inode) do { } while (0) >  #endif >   > +struct base_acl { > + union { > + atomic_t ba_refcount; > + struct rcu_head ba_rcu; > + }; > +}; >  struct posix_acl; >  #define ACL_NOT_CACHED ((void *)(-1)) >   > -static inline struct posix_acl * > +static inline struct base_acl * >  uncached_acl_sentinel(struct task_struct *task) >  { >   return (void *)task + 1; >  } >   >  static inline bool > -is_uncached_acl(struct posix_acl *acl) > +is_uncached_acl(struct base_acl *acl) >  { >   return (long)acl & 1; >  } > @@ -613,9 +619,9 @@ struct inode { >   kgid_t i_gid; >   unsigned int i_flags; >   > -#ifdef CONFIG_FS_POSIX_ACL > - struct posix_acl *i_acl; > - struct posix_acl *i_default_acl; > +#if defined(CONFIG_FS_POSIX_ACL) > + struct base_acl *i_acl; > + struct base_acl *i_default_acl; >  #endif >   >   const struct inode_operations *i_op; > @@ -3193,4 +3199,29 @@ static inline bool dir_relax_shared(struct inode *inode) >  extern bool path_noexec(const struct path *path); >  extern void inode_nohighmem(struct inode *inode); >   > +static inline void base_acl_get(struct base_acl *acl) > +{ > + if (acl) > + atomic_inc(&acl->ba_refcount); > +} > + > +static inline void base_acl_put(struct base_acl *acl) > +{ > + if (acl && atomic_dec_and_test(&acl->ba_refcount)) > + kfree_rcu(acl, ba_rcu); > +} > + > +static inline void base_acl_init(struct base_acl *acl) > +{ > + atomic_set(&acl->ba_refcount, 1); > +} > + > +static inline int base_acl_refcount(struct base_acl *acl) > +{ > + return atomic_read(&acl->ba_refcount); > +} > + > +extern struct base_acl *__get_cached_acl(struct base_acl **); > +extern void __forget_cached_acl(struct base_acl **); > + >  #endif /* _LINUX_FS_H */ > diff --git a/include/linux/posix_acl.h b/include/linux/posix_acl.h > index 5b5a80c..daf84fa 100644 > --- a/include/linux/posix_acl.h > +++ b/include/linux/posix_acl.h > @@ -43,10 +43,7 @@ struct posix_acl_entry { >  }; >   >  struct posix_acl { > - union { > - atomic_t a_refcount; > - struct rcu_head a_rcu; > - }; > + struct base_acl a_base;  /* must be first, see posix_acl_release() */ >   unsigned int a_count; >   struct posix_acl_entry a_entries[0]; >  }; > @@ -61,8 +58,7 @@ struct posix_acl { >  static inline struct posix_acl * >  posix_acl_dup(struct posix_acl *acl) >  { > - if (acl) > - atomic_inc(&acl->a_refcount); > + base_acl_get(&acl->a_base); >   return acl; >  } >   > @@ -72,10 +68,16 @@ posix_acl_dup(struct posix_acl *acl) >  static inline void >  posix_acl_release(struct posix_acl *acl) >  { > - if (acl && atomic_dec_and_test(&acl->a_refcount)) > - kfree_rcu(acl, a_rcu); > + BUILD_BUG_ON(offsetof(struct posix_acl, a_base) != 0); > + base_acl_put(&acl->a_base); >  } >   > +static inline struct posix_acl * > +posix_acl(struct base_acl *base_acl) > +{ > + BUILD_BUG_ON(offsetof(struct posix_acl, a_base) != 0); > + return container_of(base_acl, struct posix_acl, a_base); > +} >   >  /* posix_acl.c */ >   > @@ -99,8 +101,7 @@ extern int posix_acl_create(struct inode *, umode_t *, struct posix_acl **, >  extern int simple_set_acl(struct inode *, struct posix_acl *, int); >  extern int simple_acl_create(struct inode *, struct inode *); >   > -struct posix_acl *get_cached_acl(struct inode *inode, int type); > -struct posix_acl *get_cached_acl_rcu(struct inode *inode, int type); > +struct base_acl *get_cached_acl(struct inode *inode, int type); >  void set_cached_acl(struct inode *inode, int type, struct posix_acl *acl); >  void forget_cached_acl(struct inode *inode, int type); >  void forget_all_cached_acls(struct inode *inode); > diff --git a/include/linux/richacl.h b/include/linux/richacl.h > index be9fb65..35a5bcb 100644 > --- a/include/linux/richacl.h > +++ b/include/linux/richacl.h > @@ -31,7 +31,7 @@ struct richace { >  }; >   >  struct richacl { > - atomic_t a_refcount; > + struct base_acl a_base;  /* must be first, see richacl_put() */ >   unsigned int a_owner_mask; >   unsigned int a_group_mask; >   unsigned int a_other_mask; > @@ -56,8 +56,7 @@ struct richacl { >  static inline struct richacl * >  richacl_get(struct richacl *acl) >  { > - if (acl) > - atomic_inc(&acl->a_refcount); > + base_acl_get(&acl->a_base); >   return acl; >  } >   > @@ -67,8 +66,8 @@ richacl_get(struct richacl *acl) >  static inline void >  richacl_put(struct richacl *acl) >  { > - if (acl && atomic_dec_and_test(&acl->a_refcount)) > - kfree(acl); > + BUILD_BUG_ON(offsetof(struct richacl, a_base) != 0); > + base_acl_put(&acl->a_base); >  } >   >  /** -- 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 BE2097CCD for ; Tue, 5 Jul 2016 10:56:10 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay2.corp.sgi.com (Postfix) with ESMTP id 8FA3830405F for ; Tue, 5 Jul 2016 08:56:10 -0700 (PDT) Received: from mail-qk0-f177.google.com (mail-qk0-f177.google.com [209.85.220.177]) by cuda.sgi.com with ESMTP id D3zDX9Ws1WPx0bw1 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NO) for ; Tue, 05 Jul 2016 08:56:06 -0700 (PDT) Received: by mail-qk0-f177.google.com with SMTP id u68so15660144qkc.3 for ; Tue, 05 Jul 2016 08:56:06 -0700 (PDT) Message-ID: <1467734163.3800.43.camel@redhat.com> Subject: Re: [PATCH v23 11/22] vfs: Cache base_acl objects in inodes From: Jeff Layton Date: Tue, 05 Jul 2016 11:56:03 -0400 In-Reply-To: <1467294433-3222-12-git-send-email-agruenba@redhat.com> References: <1467294433-3222-1-git-send-email-agruenba@redhat.com> <1467294433-3222-12-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: Andreas Dilger , "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+IFBPU0lYIEFDTHMgYW5kIHJpY2hhY2xzIGFyZSBib3RoIG9iamVjdHMgYWxsb2NhdGVk IGJ5IGttYWxsb2MoKSB3aXRoIGEKPiByZWZlcmVuY2UgY291bnQgd2hpY2ggYXJlIGZyZWVkIGJ5 IGtmcmVlX3JjdSgpLsKgwqBBbiBpbm9kZSBjYW4gZWl0aGVyCj4gY2FjaGUgYW4gYWNjZXNzIGFu ZCBhIGRlZmF1bHQgUE9TSVggQUNMLCBvciBhIHJpY2hhY2wgKHJpY2hhY2xzIGRvIG5vdAo+IGhh dmUgZGVmYXVsdCBhY2xzKS7CoMKgVG8gYWxsb3cgYW4gaW5vZGUgdG8gY2FjaGUgZWl0aGVyIG9m IHRoZSB0d28ga2luZHMKPiBvZiBhY2xzLCBpbnRyb2R1Y2UgYSBuZXcgYmFzZV9hY2wgdHlwZSBh bmQgY29udmVydCBpX2FjbCBhbmQKPiBpX2RlZmF1bHRfYWNsIHRvIHRoYXQgdHlwZS4gSW4gbW9z dCBjYXNlcywgdGhlIHZmcyB0aGVuIGRvZXNuJ3QgY2FyZSB3aGljaAo+IGtpbmQgb2YgYWNsIGFu IGlub2RlIGNhY2hlcyAoaWYgYW55KS4KPiAKPiBTaWduZWQtb2ZmLWJ5OiBBbmRyZWFzIEdydWVu YmFjaGVyIDxhZ3J1ZW5iYUByZWRoYXQuY29tPgo+IENjOiBBbmRyZWFzIERpbGdlciA8YWRpbGdl ckBkaWxnZXIuY2E+Cj4gLS0tCj4gwqBkcml2ZXJzL3N0YWdpbmcvbHVzdHJlL2x1c3RyZS9sbGl0 ZS9sbGl0ZV9saWIuYyB8wqDCoDIgKy0KPiDCoGZzLzlwL2FjbC5jwqDCoMKgwqDCoMKgwqDCoMKg wqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqB8 wqDCoDggKy0tCj4gwqBmcy9mMmZzL2FjbC5jwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKg wqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoHzCoMKgNCArLQo+IMKgZnMv aW5vZGUuY8KgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKg wqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqB8IDMyICsrKysrKysrKysrLQo+IMKgZnMvamZmczIv YWNsLmPCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKg wqDCoMKgwqDCoMKgwqDCoHzCoMKgNiArKy0KPiDCoGZzL25hbWVpLmPCoMKgwqDCoMKgwqDCoMKg wqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDC oMKgfCAzMyArKysrKystLS0tLS0KPiDCoGZzL25mcy9uZnMzYWNsLmPCoMKgwqDCoMKgwqDCoMKg wqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgfCAxNCArKy0t LQo+IMKgZnMvcG9zaXhfYWNsLmPCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDC oMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoHwgNjkgKysrKysrKy0tLS0tLS0tLS0tLS0t LS0tLQo+IMKgZnMvcmljaGFjbC5jwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKg wqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgfMKgwqA0ICstCj4gwqBpbmNsdWRl L2xpbnV4L2ZzLmjCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKg wqDCoMKgwqDCoMKgwqB8IDQxICsrKysrKysrKysrKystLQo+IMKgaW5jbHVkZS9saW51eC9wb3Np eF9hY2wuaMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqB8IDIx ICsrKystLS0tCj4gwqBpbmNsdWRlL2xpbnV4L3JpY2hhY2wuaMKgwqDCoMKgwqDCoMKgwqDCoMKg wqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgfMKgwqA5ICsrLS0KPiDCoDEyIGZpbGVzIGNo YW5nZWQsIDEzOSBpbnNlcnRpb25zKCspLCAxMDQgZGVsZXRpb25zKC0pCj4gCj4gZGlmZiAtLWdp dCBhL2RyaXZlcnMvc3RhZ2luZy9sdXN0cmUvbHVzdHJlL2xsaXRlL2xsaXRlX2xpYi5jIGIvZHJp dmVycy9zdGFnaW5nL2x1c3RyZS9sdXN0cmUvbGxpdGUvbGxpdGVfbGliLmMKPiBpbmRleCA5NmM3 ZTlmLi43ODE5YTdjIDEwMDY0NAo+IC0tLSBhL2RyaXZlcnMvc3RhZ2luZy9sdXN0cmUvbHVzdHJl L2xsaXRlL2xsaXRlX2xpYi5jCj4gKysrIGIvZHJpdmVycy9zdGFnaW5nL2x1c3RyZS9sdXN0cmUv bGxpdGUvbGxpdGVfbGliLmMKPiBAQCAtMTA4Nyw3ICsxMDg3LDcgQEAgdm9pZCBsbF9jbGVhcl9p bm9kZShzdHJ1Y3QgaW5vZGUgKmlub2RlKQo+IMKgCX0KPiDCoCNpZmRlZiBDT05GSUdfRlNfUE9T SVhfQUNMCj4gwqAJZWxzZSBpZiAobGxpLT5sbGlfcG9zaXhfYWNsKSB7Cj4gLQkJTEFTU0VSVChh dG9taWNfcmVhZCgmbGxpLT5sbGlfcG9zaXhfYWNsLT5hX3JlZmNvdW50KSA9PSAxKTsKPiArCQlM QVNTRVJUKGJhc2VfYWNsX3JlZmNvdW50KCZsbGktPmxsaV9wb3NpeF9hY2wtPmFfYmFzZSkgPT0g MSk7Cj4gwqAJCUxBU1NFUlQoIWxsaS0+bGxpX3JlbW90ZV9wZXJtcyk7Cj4gwqAJCXBvc2l4X2Fj bF9yZWxlYXNlKGxsaS0+bGxpX3Bvc2l4X2FjbCk7Cj4gwqAJCWxsaS0+bGxpX3Bvc2l4X2FjbCA9 IE5VTEw7Cj4gZGlmZiAtLWdpdCBhL2ZzLzlwL2FjbC5jIGIvZnMvOXAvYWNsLmMKPiBpbmRleCAw NTc2ZWFlLi4xY2U1NzJmIDEwMDY0NAo+IC0tLSBhL2ZzLzlwL2FjbC5jCj4gKysrIGIvZnMvOXAv YWNsLmMKPiBAQCAtODcsMTQgKzg3LDE0IEBAIGludCB2OWZzX2dldF9hY2woc3RydWN0IGlub2Rl ICppbm9kZSwgc3RydWN0IHA5X2ZpZCAqZmlkKQo+IMKgCj4gwqBzdGF0aWMgc3RydWN0IHBvc2l4 X2FjbCAqdjlmc19nZXRfY2FjaGVkX2FjbChzdHJ1Y3QgaW5vZGUgKmlub2RlLCBpbnQgdHlwZSkK PiDCoHsKPiAtCXN0cnVjdCBwb3NpeF9hY2wgKmFjbDsKPiArCXN0cnVjdCBiYXNlX2FjbCAqYmFz ZV9hY2w7Cj4gwqAJLyoKPiDCoAnCoCogOXAgQWx3YXlzIGNhY2hlIHRoZSBhY2wgdmFsdWUgd2hl bgo+IMKgCcKgKiBpbnN0YW50aWF0aW5nIHRoZSBpbm9kZSAodjlmc19pbm9kZV9mcm9tX2ZpZCkK PiDCoAnCoCovCj4gLQlhY2wgPSBnZXRfY2FjaGVkX2FjbChpbm9kZSwgdHlwZSk7Cj4gLQlCVUdf T04oaXNfdW5jYWNoZWRfYWNsKGFjbCkpOwo+IC0JcmV0dXJuIGFjbDsKPiArCWJhc2VfYWNsID0g Z2V0X2NhY2hlZF9hY2woaW5vZGUsIHR5cGUpOwo+ICsJQlVHX09OKGlzX3VuY2FjaGVkX2FjbChi YXNlX2FjbCkpOwo+ICsJcmV0dXJuIHBvc2l4X2FjbChiYXNlX2FjbCk7Cj4gwqB9Cj4gwqAKPiDC oHN0cnVjdCBwb3NpeF9hY2wgKnY5ZnNfaW9wX2dldF9hY2woc3RydWN0IGlub2RlICppbm9kZSwg aW50IHR5cGUpCj4gZGlmZiAtLWdpdCBhL2ZzL2YyZnMvYWNsLmMgYi9mcy9mMmZzL2FjbC5jCj4g aW5kZXggYTMxYzdlOC4uNjA3OTAxNyAxMDA2NDQKPiAtLS0gYS9mcy9mMmZzL2FjbC5jCj4gKysr IGIvZnMvZjJmcy9hY2wuYwo+IEBAIC0yNjcsNyArMjY3LDcgQEAgc3RhdGljIHN0cnVjdCBwb3Np eF9hY2wgKmYyZnNfYWNsX2Nsb25lKGNvbnN0IHN0cnVjdCBwb3NpeF9hY2wgKmFjbCwKPiDCoAkJ CQlzaXplb2Yoc3RydWN0IHBvc2l4X2FjbF9lbnRyeSk7Cj4gwqAJCWNsb25lID0ga21lbWR1cChh Y2wsIHNpemUsIGZsYWdzKTsKPiDCoAkJaWYgKGNsb25lKQo+IC0JCQlhdG9taWNfc2V0KCZjbG9u ZS0+YV9yZWZjb3VudCwgMSk7Cj4gKwkJCWJhc2VfYWNsX2luaXQoJmNsb25lLT5hX2Jhc2UpOwo+ IMKgCX0KPiDCoAlyZXR1cm4gY2xvbmU7Cj4gwqB9Cj4gQEAgLTI3OSw3ICsyNzksNyBAQCBzdGF0 aWMgaW50IGYyZnNfYWNsX2NyZWF0ZV9tYXNxKHN0cnVjdCBwb3NpeF9hY2wgKmFjbCwgdW1vZGVf dCAqbW9kZV9wKQo+IMKgCXVtb2RlX3QgbW9kZSA9ICptb2RlX3A7Cj4gwqAJaW50IG5vdF9lcXVp diA9IDA7Cj4gwqAKPiAtCS8qIGFzc2VydChhdG9taWNfcmVhZChhY2wtPmFfcmVmY291bnQpID09 IDEpOyAqLwo+ICsJLyogYXNzZXJ0KGJhc2VfYWNsX3JlZmNvdW50KCZhY2wtPmFfYmFzZSkgPT0g MSk7ICovCj4gwqAKPiDCoAlGT1JFQUNIX0FDTF9FTlRSWShwYSwgYWNsLCBwZSkgewo+IMKgCQlz d2l0Y2gocGEtPmVfdGFnKSB7Cj4gZGlmZiAtLWdpdCBhL2ZzL2lub2RlLmMgYi9mcy9pbm9kZS5j Cj4gaW5kZXggNGNjYmMyMS4uNDBjMDNhNyAxMDA2NDQKPiAtLS0gYS9mcy9pbm9kZS5jCj4gKysr IGIvZnMvaW5vZGUuYwo+IEBAIC0yNDAsMTQgKzI0MCw0MiBAQCB2b2lkIF9fZGVzdHJveV9pbm9k ZShzdHJ1Y3QgaW5vZGUgKmlub2RlKQo+IMKgCj4gwqAjaWZkZWYgQ09ORklHX0ZTX1BPU0lYX0FD TAo+IMKgCWlmIChpbm9kZS0+aV9hY2wgJiYgIWlzX3VuY2FjaGVkX2FjbChpbm9kZS0+aV9hY2wp KQo+IC0JCXBvc2l4X2FjbF9yZWxlYXNlKGlub2RlLT5pX2FjbCk7Cj4gKwkJYmFzZV9hY2xfcHV0 KGlub2RlLT5pX2FjbCk7Cj4gwqAJaWYgKGlub2RlLT5pX2RlZmF1bHRfYWNsICYmICFpc191bmNh Y2hlZF9hY2woaW5vZGUtPmlfZGVmYXVsdF9hY2wpKQo+IC0JCXBvc2l4X2FjbF9yZWxlYXNlKGlu b2RlLT5pX2RlZmF1bHRfYWNsKTsKPiArCQliYXNlX2FjbF9wdXQoaW5vZGUtPmlfZGVmYXVsdF9h Y2wpOwo+IMKgI2VuZGlmCj4gwqAJdGhpc19jcHVfZGVjKG5yX2lub2Rlcyk7Cj4gwqB9Cj4gwqBF WFBPUlRfU1lNQk9MKF9fZGVzdHJveV9pbm9kZSk7Cj4gwqAKPiArI2lmZGVmIENPTkZJR19GU19Q T1NJWF9BQ0wKPiArc3RydWN0IGJhc2VfYWNsICpfX2dldF9jYWNoZWRfYWNsKHN0cnVjdCBiYXNl X2FjbCAqKnApCj4gK3sKPiArCXN0cnVjdCBiYXNlX2FjbCAqYmFzZV9hY2w7Cj4gKwo+ICsJZm9y ICg7Oykgewo+ICsJCXJjdV9yZWFkX2xvY2soKTsKPiArCQliYXNlX2FjbCA9IHJjdV9kZXJlZmVy ZW5jZSgqcCk7Cj4gKwkJaWYgKCFiYXNlX2FjbCB8fCBpc191bmNhY2hlZF9hY2woYmFzZV9hY2wp IHx8Cj4gKwkJwqDCoMKgwqBhdG9taWNfaW5jX25vdF96ZXJvKCZiYXNlX2FjbC0+YmFfcmVmY291 bnQpKQo+ICsJCQlicmVhazsKPiArCQlyY3VfcmVhZF91bmxvY2soKTsKPiArCQljcHVfcmVsYXgo KTsKPiArCX0KPiArCXJjdV9yZWFkX3VubG9jaygpOwo+ICsJcmV0dXJuIGJhc2VfYWNsOwo+ICt9 Cj4gKwoKSSBrbm93IHRoaXMgaXMgYmFzaWNhbGx5IGNvcGllZCBmcm9tIHRoZSBleGlzdGluZyBn ZXRfY2FjaGVkX2FjbApmdW5jdGlvbiwgYnV0IEknbSBhIGxpdHRsZSB1bmVhc3kgd2l0aCB0aGUg YWJvdmUgKGFuZCBhbHNvIHdpdGggdGhlCmV4aXN0aW5nIGNvZGUgdGhhdCBkb2VzIHRoZSBzYW1l IHRoaW5nKS4KClRoZSBiYV9yZWZjb3VudCBhbmQgYmFfcmN1IGFyZSB1bmlvbmVkLiBPbmNlIHlv dSd2ZSBkb25lIHRoZSBmaW5hbApiYXNlX2FjbF9wdXQgb24gdGhlIG9iamVjdCwgdGhlIHlvdSds bCBlbmQgdXAgY2FsbGluZyBrZnJlZV9yY3Ugd2hpY2gKaXMgZ29pbmcgdG8gY2xvYmJlciB0aGUg YmFfcmVmY291bnQuIEhvdyBpcyBpdCB0aGVuIHNhZmUgdG8gcmVseSBvbiBpdApzdGlsbCBiZWlu ZyB6ZXJvIGZvciB0aGUgYXRvbWljX2luY19ub3RfemVybz8gSVNUTSB0aGF0IGl0IHdvdWxkIGJl CnNhZmVyIHRvIG1ha2UgdGhvc2Ugc2VwYXJhdGUgZmllbGRzIGFuZCBub3QgdW5pb24gdGhlbS4K Ci4uLm9yIGFtIEkgbWlzc2luZyBzb21ldGhpbmcgdGhhdCBwcmV2ZW50cyB0aGF0PwoKPiArdm9p ZCBfX2ZvcmdldF9jYWNoZWRfYWNsKHN0cnVjdCBiYXNlX2FjbCAqKnApCj4gK3sKPiArCXN0cnVj dCBiYXNlX2FjbCAqb2xkOwo+ICsKPiArCW9sZCA9IHhjaGcocCwgQUNMX05PVF9DQUNIRUQpOwo+ ICsJaWYgKCFpc191bmNhY2hlZF9hY2wob2xkKSkKPiArCQliYXNlX2FjbF9wdXQob2xkKTsKPiAr fQo+ICsjZW5kaWYKPiArCj4gwqBzdGF0aWMgdm9pZCBpX2NhbGxiYWNrKHN0cnVjdCByY3VfaGVh ZCAqaGVhZCkKPiDCoHsKPiDCoAlzdHJ1Y3QgaW5vZGUgKmlub2RlID0gY29udGFpbmVyX29mKGhl YWQsIHN0cnVjdCBpbm9kZSwgaV9yY3UpOwo+IGRpZmYgLS1naXQgYS9mcy9qZmZzMi9hY2wuYyBi L2ZzL2pmZnMyL2FjbC5jCj4gaW5kZXggYmMyNjkzZC4uNmMxMTkwOSAxMDA2NDQKPiAtLS0gYS9m cy9qZmZzMi9hY2wuYwo+ICsrKyBiL2ZzL2pmZnMyL2FjbC5jCj4gQEAgLTI5MiwxMyArMjkyLDE1 IEBAIGludCBqZmZzMl9pbml0X2FjbF9wb3N0KHN0cnVjdCBpbm9kZSAqaW5vZGUpCj4gwqAJaW50 IHJjOwo+IMKgCj4gwqAJaWYgKGlub2RlLT5pX2RlZmF1bHRfYWNsKSB7Cj4gLQkJcmMgPSBfX2pm ZnMyX3NldF9hY2woaW5vZGUsIEpGRlMyX1hQUkVGSVhfQUNMX0RFRkFVTFQsIGlub2RlLT5pX2Rl ZmF1bHRfYWNsKTsKPiArCQlyYyA9IF9famZmczJfc2V0X2FjbChpbm9kZSwgSkZGUzJfWFBSRUZJ WF9BQ0xfREVGQVVMVCwKPiArCQkJCcKgwqDCoMKgwqBwb3NpeF9hY2woaW5vZGUtPmlfZGVmYXVs dF9hY2wpKTsKPiDCoAkJaWYgKHJjKQo+IMKgCQkJcmV0dXJuIHJjOwo+IMKgCX0KPiDCoAo+IMKg CWlmIChpbm9kZS0+aV9hY2wpIHsKPiAtCQlyYyA9IF9famZmczJfc2V0X2FjbChpbm9kZSwgSkZG UzJfWFBSRUZJWF9BQ0xfQUNDRVNTLCBpbm9kZS0+aV9hY2wpOwo+ICsJCXJjID0gX19qZmZzMl9z ZXRfYWNsKGlub2RlLCBKRkZTMl9YUFJFRklYX0FDTF9BQ0NFU1MsCj4gKwkJCQnCoMKgwqDCoMKg cG9zaXhfYWNsKGlub2RlLT5pX2FjbCkpOwo+IMKgCQlpZiAocmMpCj4gwqAJCQlyZXR1cm4gcmM7 Cj4gwqAJfQo+IGRpZmYgLS1naXQgYS9mcy9uYW1laS5jIGIvZnMvbmFtZWkuYwo+IGluZGV4IDY2 MzkzM2UuLjdhODIyZDAgMTAwNjQ0Cj4gLS0tIGEvZnMvbmFtZWkuYwo+ICsrKyBiL2ZzL25hbWVp LmMKPiBAQCAtMjU5LDI1ICsyNTksMjggQEAgdm9pZCBwdXRuYW1lKHN0cnVjdCBmaWxlbmFtZSAq bmFtZSkKPiDCoHN0YXRpYyBpbnQgY2hlY2tfYWNsKHN0cnVjdCBpbm9kZSAqaW5vZGUsIGludCBt YXNrKQo+IMKgewo+IMKgI2lmZGVmIENPTkZJR19GU19QT1NJWF9BQ0wKPiAtCXN0cnVjdCBwb3Np eF9hY2wgKmFjbDsKPiAtCj4gwqAJaWYgKG1hc2sgJiBNQVlfTk9UX0JMT0NLKSB7Cj4gLQkJYWNs ID0gZ2V0X2NhY2hlZF9hY2xfcmN1KGlub2RlLCBBQ0xfVFlQRV9BQ0NFU1MpOwo+IC0JwqDCoMKg wqDCoMKgwqDCoGlmICghYWNsKQo+ICsJCXN0cnVjdCBiYXNlX2FjbCAqYmFzZV9hY2w7Cj4gKwo+ ICsJCWJhc2VfYWNsID0gcmN1X2RlcmVmZXJlbmNlKGlub2RlLT5pX2FjbCk7Cj4gKwnCoMKgwqDC oMKgwqDCoMKgaWYgKCFiYXNlX2FjbCkKPiDCoAnCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKg wqDCoHJldHVybiAtRUFHQUlOOwo+IMKgCQkvKiBubyAtPmdldF9hY2woKSBjYWxscyBpbiBSQ1Ug bW9kZS4uLiAqLwo+IC0JCWlmIChpc191bmNhY2hlZF9hY2woYWNsKSkKPiArCQlpZiAoaXNfdW5j YWNoZWRfYWNsKGJhc2VfYWNsKSkKPiDCoAkJCXJldHVybiAtRUNISUxEOwo+IC0JwqDCoMKgwqDC oMKgwqDCoHJldHVybiBwb3NpeF9hY2xfcGVybWlzc2lvbihpbm9kZSwgYWNsLCBtYXNrICYgfk1B WV9OT1RfQkxPQ0spOwo+IC0JfQo+IC0KPiAtCWFjbCA9IGdldF9hY2woaW5vZGUsIEFDTF9UWVBF X0FDQ0VTUyk7Cj4gLQlpZiAoSVNfRVJSKGFjbCkpCj4gLQkJcmV0dXJuIFBUUl9FUlIoYWNsKTsK PiAtCWlmIChhY2wpIHsKPiAtCcKgwqDCoMKgwqDCoMKgwqBpbnQgZXJyb3IgPSBwb3NpeF9hY2xf cGVybWlzc2lvbihpbm9kZSwgYWNsLCBtYXNrKTsKPiAtCcKgwqDCoMKgwqDCoMKgwqBwb3NpeF9h Y2xfcmVsZWFzZShhY2wpOwo+IC0JwqDCoMKgwqDCoMKgwqDCoHJldHVybiBlcnJvcjsKPiArCcKg wqDCoMKgwqDCoMKgwqByZXR1cm4gcG9zaXhfYWNsX3Blcm1pc3Npb24oaW5vZGUsIHBvc2l4X2Fj bChiYXNlX2FjbCksCj4gKwkJCQkJwqDCoMKgwqBtYXNrICYgfk1BWV9OT1RfQkxPQ0spOwo+ICsJ fSBlbHNlIHsKPiArCQlzdHJ1Y3QgcG9zaXhfYWNsICphY2w7Cj4gKwo+ICsJCWFjbCA9IGdldF9h Y2woaW5vZGUsIEFDTF9UWVBFX0FDQ0VTUyk7Cj4gKwkJaWYgKElTX0VSUihhY2wpKQo+ICsJCQly ZXR1cm4gUFRSX0VSUihhY2wpOwo+ICsJCWlmIChhY2wpIHsKPiArCQkJaW50IGVycm9yID0gcG9z aXhfYWNsX3Blcm1pc3Npb24oaW5vZGUsIGFjbCwgbWFzayk7Cj4gKwkJCXBvc2l4X2FjbF9yZWxl YXNlKGFjbCk7Cj4gKwkJCXJldHVybiBlcnJvcjsKPiArCQl9Cj4gwqAJfQo+IMKgI2VuZGlmCj4g wqAKPiBkaWZmIC0tZ2l0IGEvZnMvbmZzL25mczNhY2wuYyBiL2ZzL25mcy9uZnMzYWNsLmMKPiBp bmRleCA3MjBkOTJmNS4uMmI3MDk0NCAxMDA2NDQKPiAtLS0gYS9mcy9uZnMvbmZzM2FjbC5jCj4g KysrIGIvZnMvbmZzL25mczNhY2wuYwo+IEBAIC0xNiwyOCArMTYsMjggQEAKPiDCoCAqIGNhY2hp bmcgZ2V0X2FjbCByZXN1bHRzIGluIGEgcmFjZS1mcmVlIHdheS7CoMKgU2VlIGZzL3Bvc2l4X2Fj bC5jOmdldF9hY2woKQo+IMKgICogZm9yIGV4cGxhbmF0aW9ucy4KPiDCoCAqLwo+IC1zdGF0aWMg dm9pZCBuZnMzX3ByZXBhcmVfZ2V0X2FjbChzdHJ1Y3QgcG9zaXhfYWNsICoqcCkKPiArc3RhdGlj IHZvaWQgbmZzM19wcmVwYXJlX2dldF9hY2woc3RydWN0IGJhc2VfYWNsICoqcCkKPiDCoHsKPiAt CXN0cnVjdCBwb3NpeF9hY2wgKnNlbnRpbmVsID0gdW5jYWNoZWRfYWNsX3NlbnRpbmVsKGN1cnJl bnQpOwo+ICsJc3RydWN0IGJhc2VfYWNsICpzZW50aW5lbCA9IHVuY2FjaGVkX2FjbF9zZW50aW5l bChjdXJyZW50KTsKPiDCoAo+IMKgCWlmIChjbXB4Y2hnKHAsIEFDTF9OT1RfQ0FDSEVELCBzZW50 aW5lbCkgIT0gQUNMX05PVF9DQUNIRUQpIHsKPiDCoAkJLyogTm90IHRoZSBmaXJzdCByZWFkZXIg b3Igc2VudGluZWwgYWxyZWFkeSBpbiBwbGFjZS4gKi8KPiDCoAl9Cj4gwqB9Cj4gwqAKPiAtc3Rh dGljIHZvaWQgbmZzM19jb21wbGV0ZV9nZXRfYWNsKHN0cnVjdCBwb3NpeF9hY2wgKipwLCBzdHJ1 Y3QgcG9zaXhfYWNsICphY2wpCj4gK3N0YXRpYyB2b2lkIG5mczNfY29tcGxldGVfZ2V0X2FjbChz dHJ1Y3QgYmFzZV9hY2wgKipwLCBzdHJ1Y3QgcG9zaXhfYWNsICphY2wpCj4gwqB7Cj4gLQlzdHJ1 Y3QgcG9zaXhfYWNsICpzZW50aW5lbCA9IHVuY2FjaGVkX2FjbF9zZW50aW5lbChjdXJyZW50KTsK PiArCXN0cnVjdCBiYXNlX2FjbCAqc2VudGluZWwgPSB1bmNhY2hlZF9hY2xfc2VudGluZWwoY3Vy cmVudCk7Cj4gwqAKPiDCoAkvKiBPbmx5IGNhY2hlIHRoZSBBQ0wgaWYgb3VyIHNlbnRpbmVsIGlz IHN0aWxsIGluIHBsYWNlLiAqLwo+IMKgCXBvc2l4X2FjbF9kdXAoYWNsKTsKPiAtCWlmIChjbXB4 Y2hnKHAsIHNlbnRpbmVsLCBhY2wpICE9IHNlbnRpbmVsKQo+ICsJaWYgKGNtcHhjaGcocCwgc2Vu dGluZWwsICZhY2wtPmFfYmFzZSkgIT0gc2VudGluZWwpCj4gwqAJCXBvc2l4X2FjbF9yZWxlYXNl KGFjbCk7Cj4gwqB9Cj4gwqAKPiAtc3RhdGljIHZvaWQgbmZzM19hYm9ydF9nZXRfYWNsKHN0cnVj dCBwb3NpeF9hY2wgKipwKQo+ICtzdGF0aWMgdm9pZCBuZnMzX2Fib3J0X2dldF9hY2woc3RydWN0 IGJhc2VfYWNsICoqcCkKPiDCoHsKPiAtCXN0cnVjdCBwb3NpeF9hY2wgKnNlbnRpbmVsID0gdW5j YWNoZWRfYWNsX3NlbnRpbmVsKGN1cnJlbnQpOwo+ICsJc3RydWN0IGJhc2VfYWNsICpzZW50aW5l bCA9IHVuY2FjaGVkX2FjbF9zZW50aW5lbChjdXJyZW50KTsKPiDCoAo+IMKgCS8qIFJlbW92ZSBv dXIgc2VudGluZWwgdXBvbiBmYWlsdXJlLiAqLwo+IMKgCWNtcHhjaGcocCwgc2VudGluZWwsIEFD TF9OT1RfQ0FDSEVEKTsKPiBkaWZmIC0tZ2l0IGEvZnMvcG9zaXhfYWNsLmMgYi9mcy9wb3NpeF9h Y2wuYwo+IGluZGV4IGVkYzQ1MmMuLjFiNjg1YTEgMTAwNjQ0Cj4gLS0tIGEvZnMvcG9zaXhfYWNs LmMKPiArKysgYi9mcy9wb3NpeF9hY2wuYwo+IEBAIC0yMSw3ICsyMSw3IEBACj4gwqAjaW5jbHVk ZSAKPiDCoCNpbmNsdWRlIAo+IMKgCj4gLXN0YXRpYyBzdHJ1Y3QgcG9zaXhfYWNsICoqYWNsX2J5 X3R5cGUoc3RydWN0IGlub2RlICppbm9kZSwgaW50IHR5cGUpCj4gK3N0YXRpYyBpbmxpbmUgc3Ry dWN0IGJhc2VfYWNsICoqYWNsX2J5X3R5cGUoc3RydWN0IGlub2RlICppbm9kZSwgaW50IHR5cGUp Cj4gwqB7Cj4gwqAJc3dpdGNoICh0eXBlKSB7Cj4gwqAJY2FzZSBBQ0xfVFlQRV9BQ0NFU1M6Cj4g QEAgLTMzLDUxICszMywyMyBAQCBzdGF0aWMgc3RydWN0IHBvc2l4X2FjbCAqKmFjbF9ieV90eXBl KHN0cnVjdCBpbm9kZSAqaW5vZGUsIGludCB0eXBlKQo+IMKgCX0KPiDCoH0KPiDCoAo+IC1zdHJ1 Y3QgcG9zaXhfYWNsICpnZXRfY2FjaGVkX2FjbChzdHJ1Y3QgaW5vZGUgKmlub2RlLCBpbnQgdHlw ZSkKPiArc3RydWN0IGJhc2VfYWNsICpnZXRfY2FjaGVkX2FjbChzdHJ1Y3QgaW5vZGUgKmlub2Rl LCBpbnQgdHlwZSkKPiDCoHsKPiAtCXN0cnVjdCBwb3NpeF9hY2wgKipwID0gYWNsX2J5X3R5cGUo aW5vZGUsIHR5cGUpOwo+IC0Jc3RydWN0IHBvc2l4X2FjbCAqYWNsOwo+IC0KPiAtCWZvciAoOzsp IHsKPiAtCQlyY3VfcmVhZF9sb2NrKCk7Cj4gLQkJYWNsID0gcmN1X2RlcmVmZXJlbmNlKCpwKTsK PiAtCQlpZiAoIWFjbCB8fCBpc191bmNhY2hlZF9hY2woYWNsKSB8fAo+IC0JCcKgwqDCoMKgYXRv bWljX2luY19ub3RfemVybygmYWNsLT5hX3JlZmNvdW50KSkKPiAtCQkJYnJlYWs7Cj4gLQkJcmN1 X3JlYWRfdW5sb2NrKCk7Cj4gLQkJY3B1X3JlbGF4KCk7Cj4gLQl9Cj4gLQlyY3VfcmVhZF91bmxv Y2soKTsKPiAtCXJldHVybiBhY2w7Cj4gKwlyZXR1cm4gX19nZXRfY2FjaGVkX2FjbChhY2xfYnlf dHlwZShpbm9kZSwgdHlwZSkpOwo+IMKgfQo+IMKgRVhQT1JUX1NZTUJPTChnZXRfY2FjaGVkX2Fj bCk7Cj4gwqAKPiAtc3RydWN0IHBvc2l4X2FjbCAqZ2V0X2NhY2hlZF9hY2xfcmN1KHN0cnVjdCBp bm9kZSAqaW5vZGUsIGludCB0eXBlKQo+IC17Cj4gLQlyZXR1cm4gcmN1X2RlcmVmZXJlbmNlKCph Y2xfYnlfdHlwZShpbm9kZSwgdHlwZSkpOwo+IC19Cj4gLUVYUE9SVF9TWU1CT0woZ2V0X2NhY2hl ZF9hY2xfcmN1KTsKPiAtCj4gwqB2b2lkIHNldF9jYWNoZWRfYWNsKHN0cnVjdCBpbm9kZSAqaW5v ZGUsIGludCB0eXBlLCBzdHJ1Y3QgcG9zaXhfYWNsICphY2wpCj4gwqB7Cj4gLQlzdHJ1Y3QgcG9z aXhfYWNsICoqcCA9IGFjbF9ieV90eXBlKGlub2RlLCB0eXBlKTsKPiAtCXN0cnVjdCBwb3NpeF9h Y2wgKm9sZDsKPiArCXN0cnVjdCBiYXNlX2FjbCAqKnAgPSBhY2xfYnlfdHlwZShpbm9kZSwgdHlw ZSk7Cj4gKwlzdHJ1Y3QgYmFzZV9hY2wgKm9sZDsKPiDCoAo+IC0Jb2xkID0geGNoZyhwLCBwb3Np eF9hY2xfZHVwKGFjbCkpOwo+ICsJb2xkID0geGNoZyhwLCAmcG9zaXhfYWNsX2R1cChhY2wpLT5h X2Jhc2UpOwo+IMKgCWlmICghaXNfdW5jYWNoZWRfYWNsKG9sZCkpCj4gLQkJcG9zaXhfYWNsX3Jl bGVhc2Uob2xkKTsKPiArCQliYXNlX2FjbF9wdXQob2xkKTsKPiDCoH0KPiDCoEVYUE9SVF9TWU1C T0woc2V0X2NhY2hlZF9hY2wpOwo+IMKgCj4gLXN0YXRpYyB2b2lkIF9fZm9yZ2V0X2NhY2hlZF9h Y2woc3RydWN0IHBvc2l4X2FjbCAqKnApCj4gLXsKPiAtCXN0cnVjdCBwb3NpeF9hY2wgKm9sZDsK PiAtCj4gLQlvbGQgPSB4Y2hnKHAsIEFDTF9OT1RfQ0FDSEVEKTsKPiAtCWlmICghaXNfdW5jYWNo ZWRfYWNsKG9sZCkpCj4gLQkJcG9zaXhfYWNsX3JlbGVhc2Uob2xkKTsKPiAtfQo+IC0KPiDCoHZv aWQgZm9yZ2V0X2NhY2hlZF9hY2woc3RydWN0IGlub2RlICppbm9kZSwgaW50IHR5cGUpCj4gwqB7 Cj4gwqAJX19mb3JnZXRfY2FjaGVkX2FjbChhY2xfYnlfdHlwZShpbm9kZSwgdHlwZSkpOwo+IEBA IC05MywyNSArNjUsMjQgQEAgRVhQT1JUX1NZTUJPTChmb3JnZXRfYWxsX2NhY2hlZF9hY2xzKTsK PiDCoAo+IMKgc3RydWN0IHBvc2l4X2FjbCAqZ2V0X2FjbChzdHJ1Y3QgaW5vZGUgKmlub2RlLCBp bnQgdHlwZSkKPiDCoHsKPiAtCXZvaWQgKnNlbnRpbmVsOwo+IC0Jc3RydWN0IHBvc2l4X2FjbCAq KnA7Cj4gKwlzdHJ1Y3QgYmFzZV9hY2wgKipwID0gYWNsX2J5X3R5cGUoaW5vZGUsIHR5cGUpOwo+ ICsJc3RydWN0IGJhc2VfYWNsICpzZW50aW5lbCwgKmJhc2VfYWNsOwo+IMKgCXN0cnVjdCBwb3Np eF9hY2wgKmFjbDsKPiDCoAo+ICsJaWYgKCFJU19QT1NJWEFDTChpbm9kZSkpCj4gKwkJcmV0dXJu IE5VTEw7Cj4gKwo+IMKgCS8qCj4gwqAJwqAqIFRoZSBzZW50aW5lbCBpcyB1c2VkIHRvIGRldGVj dCB3aGVuIGFub3RoZXIgb3BlcmF0aW9uIGxpa2UKPiDCoAnCoCogc2V0X2NhY2hlZF9hY2woKSBv ciBmb3JnZXRfY2FjaGVkX2FjbCgpIHJhY2VzIHdpdGggZ2V0X2FjbCgpLgo+IMKgCcKgKiBJdCBp cyBndWFyYW50ZWVkIHRoYXQgaXNfdW5jYWNoZWRfYWNsKHNlbnRpbmVsKSBpcyB0cnVlLgo+IMKg CcKgKi8KPiDCoAo+IC0JYWNsID0gZ2V0X2NhY2hlZF9hY2woaW5vZGUsIHR5cGUpOwo+IC0JaWYg KCFpc191bmNhY2hlZF9hY2woYWNsKSkKPiAtCQlyZXR1cm4gYWNsOwo+IC0KPiAtCWlmICghSVNf UE9TSVhBQ0woaW5vZGUpKQo+IC0JCXJldHVybiBOVUxMOwo+ICsJYmFzZV9hY2wgPSBfX2dldF9j YWNoZWRfYWNsKHApOwo+ICsJaWYgKCFpc191bmNhY2hlZF9hY2woYmFzZV9hY2wpKQo+ICsJCXJl dHVybiBwb3NpeF9hY2woYmFzZV9hY2wpOwo+IMKgCj4gwqAJc2VudGluZWwgPSB1bmNhY2hlZF9h Y2xfc2VudGluZWwoY3VycmVudCk7Cj4gLQlwID0gYWNsX2J5X3R5cGUoaW5vZGUsIHR5cGUpOwo+ IMKgCj4gwqAJLyoKPiDCoAnCoCogSWYgdGhlIEFDTCBpc24ndCBiZWluZyByZWFkIHlldCwgc2V0 IG91ciBzZW50aW5lbC7CoMKgT3RoZXJ3aXNlLCB0aGUKPiBAQCAtMTUxLDcgKzEyMiw3IEBAIHN0 cnVjdCBwb3NpeF9hY2wgKmdldF9hY2woc3RydWN0IGlub2RlICppbm9kZSwgaW50IHR5cGUpCj4g wqAJwqAqIENhY2hlIHRoZSByZXN1bHQsIGJ1dCBvbmx5IGlmIG91ciBzZW50aW5lbCBpcyBzdGls bCBpbiBwbGFjZS4KPiDCoAnCoCovCj4gwqAJcG9zaXhfYWNsX2R1cChhY2wpOwo+IC0JaWYgKHVu bGlrZWx5KGNtcHhjaGcocCwgc2VudGluZWwsIGFjbCkgIT0gc2VudGluZWwpKQo+ICsJaWYgKHVu bGlrZWx5KGNtcHhjaGcocCwgc2VudGluZWwsICZhY2wtPmFfYmFzZSkgIT0gc2VudGluZWwpKQo+ IMKgCQlwb3NpeF9hY2xfcmVsZWFzZShhY2wpOwo+IMKgCXJldHVybiBhY2w7Cj4gwqB9Cj4gQEAg LTE2Myw3ICsxMzQsNyBAQCBFWFBPUlRfU1lNQk9MKGdldF9hY2wpOwo+IMKgdm9pZAo+IMKgcG9z aXhfYWNsX2luaXQoc3RydWN0IHBvc2l4X2FjbCAqYWNsLCBpbnQgY291bnQpCj4gwqB7Cj4gLQlh dG9taWNfc2V0KCZhY2wtPmFfcmVmY291bnQsIDEpOwo+ICsJYmFzZV9hY2xfaW5pdCgmYWNsLT5h X2Jhc2UpOwo+IMKgCWFjbC0+YV9jb3VudCA9IGNvdW50Owo+IMKgfQo+IMKgRVhQT1JUX1NZTUJP TChwb3NpeF9hY2xfaW5pdCk7Cj4gQEAgLTE5Niw3ICsxNjcsNyBAQCBwb3NpeF9hY2xfY2xvbmUo Y29uc3Qgc3RydWN0IHBvc2l4X2FjbCAqYWNsLCBnZnBfdCBmbGFncykKPiDCoAkJwqDCoMKgwqDC oMKgwqDCoMKgwqDCoHNpemVvZihzdHJ1Y3QgcG9zaXhfYWNsX2VudHJ5KTsKPiDCoAkJY2xvbmUg PSBrbWVtZHVwKGFjbCwgc2l6ZSwgZmxhZ3MpOwo+IMKgCQlpZiAoY2xvbmUpCj4gLQkJCWF0b21p Y19zZXQoJmNsb25lLT5hX3JlZmNvdW50LCAxKTsKPiArCQkJYmFzZV9hY2xfaW5pdCgmY2xvbmUt PmFfYmFzZSk7Cj4gwqAJfQo+IMKgCXJldHVybiBjbG9uZTsKPiDCoH0KPiBAQCAtNDE4LDcgKzM4 OSw3IEBAIHN0YXRpYyBpbnQgcG9zaXhfYWNsX2NyZWF0ZV9tYXNxKHN0cnVjdCBwb3NpeF9hY2wg KmFjbCwgdW1vZGVfdCAqbW9kZV9wKQo+IMKgCXVtb2RlX3QgbW9kZSA9ICptb2RlX3A7Cj4gwqAJ aW50IG5vdF9lcXVpdiA9IDA7Cj4gwqAKPiAtCS8qIGFzc2VydChhdG9taWNfcmVhZChhY2wtPmFf cmVmY291bnQpID09IDEpOyAqLwo+ICsJLyogYXNzZXJ0KGJhc2VfYWNsX3JlZmNvdW50KCZhY2wt PmFfYmFzZSkgPT0gMSk7ICovCj4gwqAKPiDCoAlGT1JFQUNIX0FDTF9FTlRSWShwYSwgYWNsLCBw ZSkgewo+IMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqBzd2l0Y2gocGEtPmVfdGFn KSB7Cj4gQEAgLTQ3Myw3ICs0NDQsNyBAQCBzdGF0aWMgaW50IF9fcG9zaXhfYWNsX2NobW9kX21h c3Eoc3RydWN0IHBvc2l4X2FjbCAqYWNsLCB1bW9kZV90IG1vZGUpCj4gwqAJc3RydWN0IHBvc2l4 X2FjbF9lbnRyeSAqZ3JvdXBfb2JqID0gTlVMTCwgKm1hc2tfb2JqID0gTlVMTDsKPiDCoAlzdHJ1 Y3QgcG9zaXhfYWNsX2VudHJ5ICpwYSwgKnBlOwo+IMKgCj4gLQkvKiBhc3NlcnQoYXRvbWljX3Jl YWQoYWNsLT5hX3JlZmNvdW50KSA9PSAxKTsgKi8KPiArCS8qIGFzc2VydChiYXNlX2FjbF9yZWZj b3VudCgmYWNsLT5hX2Jhc2UpID09IDEpOyAqLwo+IMKgCj4gwqAJRk9SRUFDSF9BQ0xfRU5UUlko cGEsIGFjbCwgcGUpIHsKPiDCoAkJc3dpdGNoKHBhLT5lX3RhZykgewo+IGRpZmYgLS1naXQgYS9m cy9yaWNoYWNsLmMgYi9mcy9yaWNoYWNsLmMKPiBpbmRleCBjYjBlZjNmLi44OTcxZWFkIDEwMDY0 NAo+IC0tLSBhL2ZzL3JpY2hhY2wuYwo+ICsrKyBiL2ZzL3JpY2hhY2wuYwo+IEBAIC0zMSw3ICsz MSw3IEBAIHJpY2hhY2xfYWxsb2MoaW50IGNvdW50LCBnZnBfdCBnZnApCj4gwqAJc3RydWN0IHJp Y2hhY2wgKmFjbCA9IGt6YWxsb2Moc2l6ZSwgZ2ZwKTsKPiDCoAo+IMKgCWlmIChhY2wpIHsKPiAt CQlhdG9taWNfc2V0KCZhY2wtPmFfcmVmY291bnQsIDEpOwo+ICsJCWJhc2VfYWNsX2luaXQoJmFj bC0+YV9iYXNlKTsKPiDCoAkJYWNsLT5hX2NvdW50ID0gY291bnQ7Cj4gwqAJfQo+IMKgCXJldHVy biBhY2w7Cj4gQEAgLTUwLDcgKzUwLDcgQEAgcmljaGFjbF9jbG9uZShjb25zdCBzdHJ1Y3Qgcmlj aGFjbCAqYWNsLCBnZnBfdCBnZnApCj4gwqAKPiDCoAlpZiAoZHVwKSB7Cj4gwqAJCW1lbWNweShk dXAsIGFjbCwgc2l6ZSk7Cj4gLQkJYXRvbWljX3NldCgmZHVwLT5hX3JlZmNvdW50LCAxKTsKPiAr CQliYXNlX2FjbF9pbml0KCZkdXAtPmFfYmFzZSk7Cj4gwqAJfQo+IMKgCXJldHVybiBkdXA7Cj4g wqB9Cj4gZGlmZiAtLWdpdCBhL2luY2x1ZGUvbGludXgvZnMuaCBiL2luY2x1ZGUvbGludXgvZnMu aAo+IGluZGV4IGJiMzY1NjEuLjA2YTMwYjAgMTAwNjQ0Cj4gLS0tIGEvaW5jbHVkZS9saW51eC9m cy5oCj4gKysrIGIvaW5jbHVkZS9saW51eC9mcy5oCj4gQEAgLTU4MiwxNyArNTgyLDIzIEBAIHN0 YXRpYyBpbmxpbmUgdm9pZCBtYXBwaW5nX2FsbG93X3dyaXRhYmxlKHN0cnVjdCBhZGRyZXNzX3Nw YWNlICptYXBwaW5nKQo+IMKgI2RlZmluZSBpX3NpemVfb3JkZXJlZF9pbml0KGlub2RlKSBkbyB7 IH0gd2hpbGUgKDApCj4gwqAjZW5kaWYKPiDCoAo+ICtzdHJ1Y3QgYmFzZV9hY2wgewo+ICsJdW5p b24gewo+ICsJCWF0b21pY190IGJhX3JlZmNvdW50Owo+ICsJCXN0cnVjdCByY3VfaGVhZCBiYV9y Y3U7Cj4gKwl9Owo+ICt9Owo+IMKgc3RydWN0IHBvc2l4X2FjbDsKPiDCoCNkZWZpbmUgQUNMX05P VF9DQUNIRUQgKCh2b2lkICopKC0xKSkKPiDCoAo+IC1zdGF0aWMgaW5saW5lIHN0cnVjdCBwb3Np eF9hY2wgKgo+ICtzdGF0aWMgaW5saW5lIHN0cnVjdCBiYXNlX2FjbCAqCj4gwqB1bmNhY2hlZF9h Y2xfc2VudGluZWwoc3RydWN0IHRhc2tfc3RydWN0ICp0YXNrKQo+IMKgewo+IMKgCXJldHVybiAo dm9pZCAqKXRhc2sgKyAxOwo+IMKgfQo+IMKgCj4gwqBzdGF0aWMgaW5saW5lIGJvb2wKPiAtaXNf dW5jYWNoZWRfYWNsKHN0cnVjdCBwb3NpeF9hY2wgKmFjbCkKPiAraXNfdW5jYWNoZWRfYWNsKHN0 cnVjdCBiYXNlX2FjbCAqYWNsKQo+IMKgewo+IMKgCXJldHVybiAobG9uZylhY2wgJiAxOwo+IMKg fQo+IEBAIC02MTMsOSArNjE5LDkgQEAgc3RydWN0IGlub2RlIHsKPiDCoAlrZ2lkX3QJCQlpX2dp ZDsKPiDCoAl1bnNpZ25lZCBpbnQJCWlfZmxhZ3M7Cj4gwqAKPiAtI2lmZGVmIENPTkZJR19GU19Q T1NJWF9BQ0wKPiAtCXN0cnVjdCBwb3NpeF9hY2wJKmlfYWNsOwo+IC0Jc3RydWN0IHBvc2l4X2Fj bAkqaV9kZWZhdWx0X2FjbDsKPiArI2lmIGRlZmluZWQoQ09ORklHX0ZTX1BPU0lYX0FDTCkKPiAr CXN0cnVjdCBiYXNlX2FjbAkJKmlfYWNsOwo+ICsJc3RydWN0IGJhc2VfYWNsCQkqaV9kZWZhdWx0 X2FjbDsKPiDCoCNlbmRpZgo+IMKgCj4gwqAJY29uc3Qgc3RydWN0IGlub2RlX29wZXJhdGlvbnMJ Kmlfb3A7Cj4gQEAgLTMxOTMsNCArMzE5OSwyOSBAQCBzdGF0aWMgaW5saW5lIGJvb2wgZGlyX3Jl bGF4X3NoYXJlZChzdHJ1Y3QgaW5vZGUgKmlub2RlKQo+IMKgZXh0ZXJuIGJvb2wgcGF0aF9ub2V4 ZWMoY29uc3Qgc3RydWN0IHBhdGggKnBhdGgpOwo+IMKgZXh0ZXJuIHZvaWQgaW5vZGVfbm9oaWdo bWVtKHN0cnVjdCBpbm9kZSAqaW5vZGUpOwo+IMKgCj4gK3N0YXRpYyBpbmxpbmUgdm9pZCBiYXNl X2FjbF9nZXQoc3RydWN0IGJhc2VfYWNsICphY2wpCj4gK3sKPiArCWlmIChhY2wpCj4gKwkJYXRv bWljX2luYygmYWNsLT5iYV9yZWZjb3VudCk7Cj4gK30KPiArCj4gK3N0YXRpYyBpbmxpbmUgdm9p ZCBiYXNlX2FjbF9wdXQoc3RydWN0IGJhc2VfYWNsICphY2wpCj4gK3sKPiArCWlmIChhY2wgJiYg YXRvbWljX2RlY19hbmRfdGVzdCgmYWNsLT5iYV9yZWZjb3VudCkpCj4gKwkJa2ZyZWVfcmN1KGFj bCwgYmFfcmN1KTsKPiArfQo+ICsKPiArc3RhdGljIGlubGluZSB2b2lkIGJhc2VfYWNsX2luaXQo c3RydWN0IGJhc2VfYWNsICphY2wpCj4gK3sKPiArCWF0b21pY19zZXQoJmFjbC0+YmFfcmVmY291 bnQsIDEpOwo+ICt9Cj4gKwo+ICtzdGF0aWMgaW5saW5lIGludCBiYXNlX2FjbF9yZWZjb3VudChz dHJ1Y3QgYmFzZV9hY2wgKmFjbCkKPiArewo+ICsJcmV0dXJuIGF0b21pY19yZWFkKCZhY2wtPmJh X3JlZmNvdW50KTsKPiArfQo+ICsKPiArZXh0ZXJuIHN0cnVjdCBiYXNlX2FjbCAqX19nZXRfY2Fj aGVkX2FjbChzdHJ1Y3QgYmFzZV9hY2wgKiopOwo+ICtleHRlcm4gdm9pZCBfX2ZvcmdldF9jYWNo ZWRfYWNsKHN0cnVjdCBiYXNlX2FjbCAqKik7Cj4gKwo+IMKgI2VuZGlmIC8qIF9MSU5VWF9GU19I ICovCj4gZGlmZiAtLWdpdCBhL2luY2x1ZGUvbGludXgvcG9zaXhfYWNsLmggYi9pbmNsdWRlL2xp bnV4L3Bvc2l4X2FjbC5oCj4gaW5kZXggNWI1YTgwYy4uZGFmODRmYSAxMDA2NDQKPiAtLS0gYS9p bmNsdWRlL2xpbnV4L3Bvc2l4X2FjbC5oCj4gKysrIGIvaW5jbHVkZS9saW51eC9wb3NpeF9hY2wu aAo+IEBAIC00MywxMCArNDMsNyBAQCBzdHJ1Y3QgcG9zaXhfYWNsX2VudHJ5IHsKPiDCoH07Cj4g wqAKPiDCoHN0cnVjdCBwb3NpeF9hY2wgewo+IC0JdW5pb24gewo+IC0JCWF0b21pY190CQlhX3Jl ZmNvdW50Owo+IC0JCXN0cnVjdCByY3VfaGVhZAkJYV9yY3U7Cj4gLQl9Owo+ICsJc3RydWN0IGJh c2VfYWNsCQlhX2Jhc2U7wqDCoC8qIG11c3QgYmUgZmlyc3QsIHNlZSBwb3NpeF9hY2xfcmVsZWFz ZSgpICovCj4gwqAJdW5zaWduZWQgaW50CQlhX2NvdW50Owo+IMKgCXN0cnVjdCBwb3NpeF9hY2xf ZW50cnkJYV9lbnRyaWVzWzBdOwo+IMKgfTsKPiBAQCAtNjEsOCArNTgsNyBAQCBzdHJ1Y3QgcG9z aXhfYWNsIHsKPiDCoHN0YXRpYyBpbmxpbmUgc3RydWN0IHBvc2l4X2FjbCAqCj4gwqBwb3NpeF9h Y2xfZHVwKHN0cnVjdCBwb3NpeF9hY2wgKmFjbCkKPiDCoHsKPiAtCWlmIChhY2wpCj4gLQkJYXRv bWljX2luYygmYWNsLT5hX3JlZmNvdW50KTsKPiArCWJhc2VfYWNsX2dldCgmYWNsLT5hX2Jhc2Up Owo+IMKgCXJldHVybiBhY2w7Cj4gwqB9Cj4gwqAKPiBAQCAtNzIsMTAgKzY4LDE2IEBAIHBvc2l4 X2FjbF9kdXAoc3RydWN0IHBvc2l4X2FjbCAqYWNsKQo+IMKgc3RhdGljIGlubGluZSB2b2lkCj4g wqBwb3NpeF9hY2xfcmVsZWFzZShzdHJ1Y3QgcG9zaXhfYWNsICphY2wpCj4gwqB7Cj4gLQlpZiAo YWNsICYmIGF0b21pY19kZWNfYW5kX3Rlc3QoJmFjbC0+YV9yZWZjb3VudCkpCj4gLQkJa2ZyZWVf cmN1KGFjbCwgYV9yY3UpOwo+ICsJQlVJTERfQlVHX09OKG9mZnNldG9mKHN0cnVjdCBwb3NpeF9h Y2wsIGFfYmFzZSkgIT0gMCk7Cj4gKwliYXNlX2FjbF9wdXQoJmFjbC0+YV9iYXNlKTsKPiDCoH0K PiDCoAo+ICtzdGF0aWMgaW5saW5lIHN0cnVjdCBwb3NpeF9hY2wgKgo+ICtwb3NpeF9hY2woc3Ry dWN0IGJhc2VfYWNsICpiYXNlX2FjbCkKPiArewo+ICsJQlVJTERfQlVHX09OKG9mZnNldG9mKHN0 cnVjdCBwb3NpeF9hY2wsIGFfYmFzZSkgIT0gMCk7Cj4gKwlyZXR1cm4gY29udGFpbmVyX29mKGJh c2VfYWNsLCBzdHJ1Y3QgcG9zaXhfYWNsLCBhX2Jhc2UpOwo+ICt9Cj4gwqAKPiDCoC8qIHBvc2l4 X2FjbC5jICovCj4gwqAKPiBAQCAtOTksOCArMTAxLDcgQEAgZXh0ZXJuIGludCBwb3NpeF9hY2xf Y3JlYXRlKHN0cnVjdCBpbm9kZSAqLCB1bW9kZV90ICosIHN0cnVjdCBwb3NpeF9hY2wgKiosCj4g wqBleHRlcm4gaW50IHNpbXBsZV9zZXRfYWNsKHN0cnVjdCBpbm9kZSAqLCBzdHJ1Y3QgcG9zaXhf YWNsICosIGludCk7Cj4gwqBleHRlcm4gaW50IHNpbXBsZV9hY2xfY3JlYXRlKHN0cnVjdCBpbm9k ZSAqLCBzdHJ1Y3QgaW5vZGUgKik7Cj4gwqAKPiAtc3RydWN0IHBvc2l4X2FjbCAqZ2V0X2NhY2hl ZF9hY2woc3RydWN0IGlub2RlICppbm9kZSwgaW50IHR5cGUpOwo+IC1zdHJ1Y3QgcG9zaXhfYWNs ICpnZXRfY2FjaGVkX2FjbF9yY3Uoc3RydWN0IGlub2RlICppbm9kZSwgaW50IHR5cGUpOwo+ICtz dHJ1Y3QgYmFzZV9hY2wgKmdldF9jYWNoZWRfYWNsKHN0cnVjdCBpbm9kZSAqaW5vZGUsIGludCB0 eXBlKTsKPiDCoHZvaWQgc2V0X2NhY2hlZF9hY2woc3RydWN0IGlub2RlICppbm9kZSwgaW50IHR5 cGUsIHN0cnVjdCBwb3NpeF9hY2wgKmFjbCk7Cj4gwqB2b2lkIGZvcmdldF9jYWNoZWRfYWNsKHN0 cnVjdCBpbm9kZSAqaW5vZGUsIGludCB0eXBlKTsKPiDCoHZvaWQgZm9yZ2V0X2FsbF9jYWNoZWRf YWNscyhzdHJ1Y3QgaW5vZGUgKmlub2RlKTsKPiBkaWZmIC0tZ2l0IGEvaW5jbHVkZS9saW51eC9y aWNoYWNsLmggYi9pbmNsdWRlL2xpbnV4L3JpY2hhY2wuaAo+IGluZGV4IGJlOWZiNjUuLjM1YTVi Y2IgMTAwNjQ0Cj4gLS0tIGEvaW5jbHVkZS9saW51eC9yaWNoYWNsLmgKPiArKysgYi9pbmNsdWRl L2xpbnV4L3JpY2hhY2wuaAo+IEBAIC0zMSw3ICszMSw3IEBAIHN0cnVjdCByaWNoYWNlIHsKPiDC oH07Cj4gwqAKPiDCoHN0cnVjdCByaWNoYWNsIHsKPiAtCWF0b21pY190CWFfcmVmY291bnQ7Cj4g KwlzdHJ1Y3QgYmFzZV9hY2wJYV9iYXNlO8KgwqAvKiBtdXN0IGJlIGZpcnN0LCBzZWUgcmljaGFj bF9wdXQoKSAqLwo+IMKgCXVuc2lnbmVkIGludAlhX293bmVyX21hc2s7Cj4gwqAJdW5zaWduZWQg aW50CWFfZ3JvdXBfbWFzazsKPiDCoAl1bnNpZ25lZCBpbnQJYV9vdGhlcl9tYXNrOwo+IEBAIC01 Niw4ICs1Niw3IEBAIHN0cnVjdCByaWNoYWNsIHsKPiDCoHN0YXRpYyBpbmxpbmUgc3RydWN0IHJp Y2hhY2wgKgo+IMKgcmljaGFjbF9nZXQoc3RydWN0IHJpY2hhY2wgKmFjbCkKPiDCoHsKPiAtCWlm IChhY2wpCj4gLQkJYXRvbWljX2luYygmYWNsLT5hX3JlZmNvdW50KTsKPiArCWJhc2VfYWNsX2dl dCgmYWNsLT5hX2Jhc2UpOwo+IMKgCXJldHVybiBhY2w7Cj4gwqB9Cj4gwqAKPiBAQCAtNjcsOCAr NjYsOCBAQCByaWNoYWNsX2dldChzdHJ1Y3QgcmljaGFjbCAqYWNsKQo+IMKgc3RhdGljIGlubGlu ZSB2b2lkCj4gwqByaWNoYWNsX3B1dChzdHJ1Y3QgcmljaGFjbCAqYWNsKQo+IMKgewo+IC0JaWYg KGFjbCAmJiBhdG9taWNfZGVjX2FuZF90ZXN0KCZhY2wtPmFfcmVmY291bnQpKQo+IC0JCWtmcmVl KGFjbCk7Cj4gKwlCVUlMRF9CVUdfT04ob2Zmc2V0b2Yoc3RydWN0IHJpY2hhY2wsIGFfYmFzZSkg IT0gMCk7Cj4gKwliYXNlX2FjbF9wdXQoJmFjbC0+YV9iYXNlKTsKPiDCoH0KPiDCoAo+IMKgLyoq CgotLQpKZWZmIExheXRvbiA8amxheXRvbkByZWRoYXQuY29tPgoKX19fX19fX19fX19fX19fX19f X19fX19fX19fX19fX19fX19fX19fX19fX19fX18KeGZzIG1haWxpbmcgbGlzdAp4ZnNAb3NzLnNn aS5jb20KaHR0cDovL29zcy5zZ2kuY29tL21haWxtYW4vbGlzdGluZm8veGZzCg==