From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by smtp.lore.kernel.org (Postfix) with ESMTP id 5A65AEB64DD for ; Wed, 9 Aug 2023 09:50:59 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id B4E9E6B0071; Wed, 9 Aug 2023 05:50:58 -0400 (EDT) Received: by kanga.kvack.org (Postfix, from userid 40) id AFE4E900002; Wed, 9 Aug 2023 05:50:58 -0400 (EDT) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 9C6648E0001; Wed, 9 Aug 2023 05:50:58 -0400 (EDT) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0016.hostedemail.com [216.40.44.16]) by kanga.kvack.org (Postfix) with ESMTP id 8AF8C6B0071 for ; Wed, 9 Aug 2023 05:50:58 -0400 (EDT) Received: from smtpin15.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay10.hostedemail.com (Postfix) with ESMTP id 418FAC06A0 for ; Wed, 9 Aug 2023 09:50:58 +0000 (UTC) X-FDA: 81104097396.15.DF55A7B Received: from smtp-out2.suse.de (smtp-out2.suse.de [195.135.220.29]) by imf25.hostedemail.com (Postfix) with ESMTP id 11631A0011 for ; Wed, 9 Aug 2023 09:50:55 +0000 (UTC) Authentication-Results: imf25.hostedemail.com; dkim=pass header.d=suse.cz header.s=susede2_rsa header.b=WEII2Dpk; dkim=pass header.d=suse.cz header.s=susede2_ed25519 header.b=7CUVerWn; dmarc=none; spf=pass (imf25.hostedemail.com: domain of jack@suse.cz designates 195.135.220.29 as permitted sender) smtp.mailfrom=jack@suse.cz ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1691574656; h=from:from:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-type:content-transfer-encoding: in-reply-to:in-reply-to:references:references:dkim-signature; bh=pzno/UZcEN9Q2ua/jIDTbweLbHF86WOzEmwLdWml3rQ=; b=eK7VcsJapeL/Yko1sHlEWitzL3drWhPDzzLKdi/ZXU+J1tHad5tkO9he+HSq6fFuBR2PN9 AhKwvB44gHvUY0IYybT5LOfFmDk+uZtpb4Sjmqh15wQDnjr/NPawDXhoIhx9zw1hhFc/C7 FxxKP4XChcjr3R+W0WLIx+SVz3ewtts= ARC-Authentication-Results: i=1; imf25.hostedemail.com; dkim=pass header.d=suse.cz header.s=susede2_rsa header.b=WEII2Dpk; dkim=pass header.d=suse.cz header.s=susede2_ed25519 header.b=7CUVerWn; dmarc=none; spf=pass (imf25.hostedemail.com: domain of jack@suse.cz designates 195.135.220.29 as permitted sender) smtp.mailfrom=jack@suse.cz ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1691574656; a=rsa-sha256; cv=none; b=2GdEc7GAbyW/3ESwjJ+JVdOelm/ag5EbKm5NP5c9OTzzQuy9sCZ+n1WcAOPClek4UpIbLy 5gKbdccaxTZF3PunNNJfSjHQCbpQtyoyKDkgsV9Mc7x34wHpxP+a0nxUg2ptsQBLJkTLM4 7Wm5BHZTC369tSSP1T+wx7TjZgc+AuU= Received: from imap2.suse-dmz.suse.de (imap2.suse-dmz.suse.de [192.168.254.74]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-521) server-digest SHA512) (No client certificate requested) by smtp-out2.suse.de (Postfix) with ESMTPS id A7BF21F38C; Wed, 9 Aug 2023 09:50:54 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.cz; s=susede2_rsa; t=1691574654; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version:content-type:content-type: in-reply-to:in-reply-to:references:references; bh=pzno/UZcEN9Q2ua/jIDTbweLbHF86WOzEmwLdWml3rQ=; b=WEII2DpkGJENjFEaNuFeGVWCvv2AXFm9MfgUkQmElVILmP2iA60hmg8Kc9z3OuQEXnyX0I 5Ruy76VyZ/GC0Gj2vB/H48LZiJAsedGHaqys3UDB9UIwC9k5V2unFFiJG1ucVa3toGyAqE gz2/bnvsf/PZrfp7+N+FYKowrrW3qsw= DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=suse.cz; s=susede2_ed25519; t=1691574654; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version:content-type:content-type: in-reply-to:in-reply-to:references:references; bh=pzno/UZcEN9Q2ua/jIDTbweLbHF86WOzEmwLdWml3rQ=; b=7CUVerWnwSEVWDVGXFquMd0VKNTmv0uCEtj5dDRtvG5kT6jkDhEdwtD4Esg+Rh3VVCmLAY OLHroF2XzUlePUCg== Received: from imap2.suse-dmz.suse.de (imap2.suse-dmz.suse.de [192.168.254.74]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-521) server-digest SHA512) (No client certificate requested) by imap2.suse-dmz.suse.de (Postfix) with ESMTPS id 92633133B5; Wed, 9 Aug 2023 09:50:54 +0000 (UTC) Received: from dovecot-director2.suse.de ([192.168.254.65]) by imap2.suse-dmz.suse.de with ESMTPSA id CTa5I35h02SKHQAAMHmgww (envelope-from ); Wed, 09 Aug 2023 09:50:54 +0000 Received: by quack3.suse.cz (Postfix, from userid 1000) id 1D0AAA0769; Wed, 9 Aug 2023 11:50:54 +0200 (CEST) Date: Wed, 9 Aug 2023 11:50:54 +0200 From: Jan Kara To: Hugh Dickins Cc: Christian Brauner , Andrew Morton , Oleksandr Tymoshenko , Carlos Maiolino , Jeff Layton , Chuck Lever , Jan Kara , Miklos Szeredi , Daniel Xu , Chris Down , Tejun Heo , Greg Kroah-Hartman , Matthew Wilcox , Christoph Hellwig , Pete Zaitcev , Helge Deller , Topi Miettinen , Yu Kuai , linux-fsdevel@vger.kernel.org, linux-mm@kvack.org Subject: Re: [PATCH vfs.tmpfs 3/5] tmpfs,xattr: enable limited user extended attributes Message-ID: <20230809095054.w3cjtggejv3nph5e@quack3> References: <2e63b26e-df46-5baa-c7d6-f9a8dd3282c5@google.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <2e63b26e-df46-5baa-c7d6-f9a8dd3282c5@google.com> X-Rspam-User: X-Stat-Signature: giw1mhhtn4t9xnitbqse564j5gepisr6 X-Rspamd-Server: rspam07 X-Rspamd-Queue-Id: 11631A0011 X-HE-Tag: 1691574655-103699 X-HE-Meta: U2FsdGVkX1/OfiN65EReGU55P5bIYyDg6JsZanBzxtRy8SNKTxAfMWd9K6QG9rVuf3SrGujdgq2hy1Y5DxHVTX3TYep9/9iAtVt+xBD7qVKcdAH1slmmT1d+D+oBJQXacO7hxU6TjvINNnnFekxYLjdNujYJteEhbj0CAgJaseJ7MWKaba/0pZegxoKB3FP+GwSVqny87BNC5YKBPfq2W2eaD/Y+xKkuaYze489icXbnXmPh3yhAmq7ehHLojVRX2Pmq9DK//tVPVOshOdy9ySVp2goeJ2nAcoqxuOCNy/0fxBBweCPo64QcqVxVt5nRPC8GVjYZzz+ofHpV+pI7Cs59mh0m4heSBuY0YdkYsIYcU2U1S9+0jbvDoO57ZgAWNh8Orj/zyrL4x8SS3XDFfnXusPdY0Ac0r3qAb/HrFaMRhSLEVEBoUf9jpQZmfMvJohVT2QOZ+FAgnsWRW0po1k80hlZwADofcOGQcnr+N7oc0UJqbKHZSSv1xAv6xwygIVVwUdAhfcljch3Q1np0gZUPoC0J0eLubleF/9pnEcfjcNDiKA32bZgDraiQgnA3nJ5i5aLnublzgPbTcu8svOdVdskNDCehAun5iri94J1+pa1OZQNTniXmeZ6oB03L3T7rKB/HxMl4feHnrZ0IJaeQ1LTbfAJVH0n0uAjyl4h+jloWgN4ZlYleSfN3a3vyKfpZJ5UEGf3Na5Jjm38SJOJBtQal/WDdSYazuogfHGCesZkz47Oi58hkQkqR5pOcDwCuRQ2HPL2J0cUYRt+PbohkqC8pX5OfBjdD+gYhN7mvSpwCZEsd+612bEcmAG+XW0ZDwtNq3g3mi3HuLoMYOU5AMcKu3hvAfWat26s93zLaGEg+NfbTCIeDo5QxuYb9MqYTiQ1FrVKHRvTt8njvQYkSNDkAABpUlxg9HowTAu6I5cI53njpNEcchvcoeuzCA0m1INQyXyXQW3ZXgdI ttZOQ8WV LXuxDQFCBaMb9xlJzZEpHq+myST+5cjdpn3xA09QDWVYPJN1rbaNlFtM2GyrDK6djFYlY+mzrd18CtPW7PvzA+iEzlM0CS16O7TD/MXYZ9KpNX5Nsh+bDWX2XmLvD9OhLQDC+uatDZ+cF1ejUBxffbhIZEfHwCM0Y2/NIBiPO4E5keNKqCi2jU+ONU/PNzwe9ejMKYeCaMfrZiEY0jM4Gl5KQfibTW601Q6t46Ot+ZtwjSJHoh+dPF+dT1r8sn5YplL4A+P8/44nvOgcHtqn/n7ydlvwiyfyuE+sSVdWOS7vHMJQwmTv+x6AL6A== X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: On Tue 08-08-23 21:33:56, Hugh Dickins wrote: > Enable "user." extended attributes on tmpfs, limiting them by tracking > the space they occupy, and deducting that space from the limited ispace > (unless tmpfs mounted with nr_inodes=0 to leave that ispace unlimited). > > tmpfs inodes and simple xattrs are both unswappable, and have to be in > lowmem on a 32-bit highmem kernel: so the ispace limit is appropriate > for xattrs, without any need for a further mount option. > > Add simple_xattr_space() to give approximate but deterministic estimate > of the space taken up by each xattr: with simple_xattrs_free() outputting > the space freed if required (but kernfs and even some tmpfs usages do not > require that, so don't waste time on strlen'ing if not needed). > > Security and trusted xattrs were already supported: for consistency and > simplicity, account them from the same pool; though there's a small risk > that a tmpfs with enough space before would now be considered too small. > > When extended attributes are used, "df -i" does show more IUsed and less > IFree than can be explained by the inodes: document that (manpage later). > > xfstests tests/generic which were not run on tmpfs before but now pass: > 020 037 062 070 077 097 103 117 337 377 454 486 523 533 611 618 728 > with no new failures. > > Signed-off-by: Hugh Dickins Looks good to me. Feel free to add: Reviewed-by: Jan Kara Honza > --- > Documentation/filesystems/tmpfs.rst | 7 ++- > fs/Kconfig | 4 +- > fs/kernfs/dir.c | 2 +- > fs/xattr.c | 28 ++++++++++- > include/linux/xattr.h | 3 +- > mm/shmem.c | 78 +++++++++++++++++++++++++++---- > 6 files changed, 106 insertions(+), 16 deletions(-) > > diff --git a/Documentation/filesystems/tmpfs.rst b/Documentation/filesystems/tmpfs.rst > index 67422ee10e03..56a26c843dbe 100644 > --- a/Documentation/filesystems/tmpfs.rst > +++ b/Documentation/filesystems/tmpfs.rst > @@ -21,8 +21,8 @@ explained further below, some of which can be reconfigured dynamically on the > fly using a remount ('mount -o remount ...') of the filesystem. A tmpfs > filesystem can be resized but it cannot be resized to a size below its current > usage. tmpfs also supports POSIX ACLs, and extended attributes for the > -trusted.* and security.* namespaces. ramfs does not use swap and you cannot > -modify any parameter for a ramfs filesystem. The size limit of a ramfs > +trusted.*, security.* and user.* namespaces. ramfs does not use swap and you > +cannot modify any parameter for a ramfs filesystem. The size limit of a ramfs > filesystem is how much memory you have available, and so care must be taken if > used so to not run out of memory. > > @@ -97,6 +97,9 @@ mount with such options, since it allows any user with write access to > use up all the memory on the machine; but enhances the scalability of > that instance in a system with many CPUs making intensive use of it. > > +If nr_inodes is not 0, that limited space for inodes is also used up by > +extended attributes: "df -i"'s IUsed and IUse% increase, IFree decreases. > + > tmpfs blocks may be swapped out, when there is a shortage of memory. > tmpfs has a mount option to disable its use of swap: > > diff --git a/fs/Kconfig b/fs/Kconfig > index 8218a71933f9..7da21f563192 100644 > --- a/fs/Kconfig > +++ b/fs/Kconfig > @@ -205,8 +205,8 @@ config TMPFS_XATTR > Extended attributes are name:value pairs associated with inodes by > the kernel or by users (see the attr(5) manual page for details). > > - Currently this enables support for the trusted.* and > - security.* namespaces. > + This enables support for the trusted.*, security.* and user.* > + namespaces. > > You need this for POSIX ACL support on tmpfs. > > diff --git a/fs/kernfs/dir.c b/fs/kernfs/dir.c > index 5a1a4af9d3d2..660995856a04 100644 > --- a/fs/kernfs/dir.c > +++ b/fs/kernfs/dir.c > @@ -556,7 +556,7 @@ void kernfs_put(struct kernfs_node *kn) > kfree_const(kn->name); > > if (kn->iattr) { > - simple_xattrs_free(&kn->iattr->xattrs); > + simple_xattrs_free(&kn->iattr->xattrs, NULL); > kmem_cache_free(kernfs_iattrs_cache, kn->iattr); > } > spin_lock(&kernfs_idr_lock); > diff --git a/fs/xattr.c b/fs/xattr.c > index ba37a8f5cfd1..2d607542281b 100644 > --- a/fs/xattr.c > +++ b/fs/xattr.c > @@ -1039,6 +1039,26 @@ const char *xattr_full_name(const struct xattr_handler *handler, > } > EXPORT_SYMBOL(xattr_full_name); > > +/** > + * simple_xattr_space - estimate the memory used by a simple xattr > + * @name: the full name of the xattr > + * @size: the size of its value > + * > + * This takes no account of how much larger the two slab objects actually are: > + * that would depend on the slab implementation, when what is required is a > + * deterministic number, which grows with name length and size and quantity. > + * > + * Return: The approximate number of bytes of memory used by such an xattr. > + */ > +size_t simple_xattr_space(const char *name, size_t size) > +{ > + /* > + * Use "40" instead of sizeof(struct simple_xattr), to return the > + * same result on 32-bit and 64-bit, and even if simple_xattr grows. > + */ > + return 40 + size + strlen(name); > +} > + > /** > * simple_xattr_free - free an xattr object > * @xattr: the xattr object > @@ -1363,14 +1383,17 @@ void simple_xattrs_init(struct simple_xattrs *xattrs) > /** > * simple_xattrs_free - free xattrs > * @xattrs: xattr header whose xattrs to destroy > + * @freed_space: approximate number of bytes of memory freed from @xattrs > * > * Destroy all xattrs in @xattr. When this is called no one can hold a > * reference to any of the xattrs anymore. > */ > -void simple_xattrs_free(struct simple_xattrs *xattrs) > +void simple_xattrs_free(struct simple_xattrs *xattrs, size_t *freed_space) > { > struct rb_node *rbp; > > + if (freed_space) > + *freed_space = 0; > rbp = rb_first(&xattrs->rb_root); > while (rbp) { > struct simple_xattr *xattr; > @@ -1379,6 +1402,9 @@ void simple_xattrs_free(struct simple_xattrs *xattrs) > rbp_next = rb_next(rbp); > xattr = rb_entry(rbp, struct simple_xattr, rb_node); > rb_erase(&xattr->rb_node, &xattrs->rb_root); > + if (freed_space) > + *freed_space += simple_xattr_space(xattr->name, > + xattr->size); > simple_xattr_free(xattr); > rbp = rbp_next; > } > diff --git a/include/linux/xattr.h b/include/linux/xattr.h > index e37fe667ae04..d20051865800 100644 > --- a/include/linux/xattr.h > +++ b/include/linux/xattr.h > @@ -114,7 +114,8 @@ struct simple_xattr { > }; > > void simple_xattrs_init(struct simple_xattrs *xattrs); > -void simple_xattrs_free(struct simple_xattrs *xattrs); > +void simple_xattrs_free(struct simple_xattrs *xattrs, size_t *freed_space); > +size_t simple_xattr_space(const char *name, size_t size); > struct simple_xattr *simple_xattr_alloc(const void *value, size_t size); > void simple_xattr_free(struct simple_xattr *xattr); > int simple_xattr_get(struct simple_xattrs *xattrs, const char *name, > diff --git a/mm/shmem.c b/mm/shmem.c > index c39471384168..7420b510a9f3 100644 > --- a/mm/shmem.c > +++ b/mm/shmem.c > @@ -393,12 +393,12 @@ static int shmem_reserve_inode(struct super_block *sb, ino_t *inop) > return 0; > } > > -static void shmem_free_inode(struct super_block *sb) > +static void shmem_free_inode(struct super_block *sb, size_t freed_ispace) > { > struct shmem_sb_info *sbinfo = SHMEM_SB(sb); > if (sbinfo->max_inodes) { > raw_spin_lock(&sbinfo->stat_lock); > - sbinfo->free_ispace += BOGO_INODE_SIZE; > + sbinfo->free_ispace += BOGO_INODE_SIZE + freed_ispace; > raw_spin_unlock(&sbinfo->stat_lock); > } > } > @@ -1232,6 +1232,7 @@ static void shmem_evict_inode(struct inode *inode) > { > struct shmem_inode_info *info = SHMEM_I(inode); > struct shmem_sb_info *sbinfo = SHMEM_SB(inode->i_sb); > + size_t freed; > > if (shmem_mapping(inode->i_mapping)) { > shmem_unacct_size(info->flags, inode->i_size); > @@ -1258,9 +1259,9 @@ static void shmem_evict_inode(struct inode *inode) > } > } > > - simple_xattrs_free(&info->xattrs); > + simple_xattrs_free(&info->xattrs, sbinfo->max_inodes ? &freed : NULL); > + shmem_free_inode(inode->i_sb, freed); > WARN_ON(inode->i_blocks); > - shmem_free_inode(inode->i_sb); > clear_inode(inode); > #ifdef CONFIG_TMPFS_QUOTA > dquot_free_inode(inode); > @@ -2440,7 +2441,7 @@ static struct inode *__shmem_get_inode(struct mnt_idmap *idmap, > inode = new_inode(sb); > > if (!inode) { > - shmem_free_inode(sb); > + shmem_free_inode(sb, 0); > return ERR_PTR(-ENOSPC); > } > > @@ -3281,7 +3282,7 @@ static int shmem_link(struct dentry *old_dentry, struct inode *dir, struct dentr > ret = simple_offset_add(shmem_get_offset_ctx(dir), dentry); > if (ret) { > if (inode->i_nlink) > - shmem_free_inode(inode->i_sb); > + shmem_free_inode(inode->i_sb, 0); > goto out; > } > > @@ -3301,7 +3302,7 @@ static int shmem_unlink(struct inode *dir, struct dentry *dentry) > struct inode *inode = d_inode(dentry); > > if (inode->i_nlink > 1 && !S_ISDIR(inode->i_mode)) > - shmem_free_inode(inode->i_sb); > + shmem_free_inode(inode->i_sb, 0); > > simple_offset_remove(shmem_get_offset_ctx(dir), dentry); > > @@ -3554,21 +3555,40 @@ static int shmem_initxattrs(struct inode *inode, > void *fs_info) > { > struct shmem_inode_info *info = SHMEM_I(inode); > + struct shmem_sb_info *sbinfo = SHMEM_SB(inode->i_sb); > const struct xattr *xattr; > struct simple_xattr *new_xattr; > + size_t ispace = 0; > size_t len; > > + if (sbinfo->max_inodes) { > + for (xattr = xattr_array; xattr->name != NULL; xattr++) { > + ispace += simple_xattr_space(xattr->name, > + xattr->value_len + XATTR_SECURITY_PREFIX_LEN); > + } > + if (ispace) { > + raw_spin_lock(&sbinfo->stat_lock); > + if (sbinfo->free_ispace < ispace) > + ispace = 0; > + else > + sbinfo->free_ispace -= ispace; > + raw_spin_unlock(&sbinfo->stat_lock); > + if (!ispace) > + return -ENOSPC; > + } > + } > + > for (xattr = xattr_array; xattr->name != NULL; xattr++) { > new_xattr = simple_xattr_alloc(xattr->value, xattr->value_len); > if (!new_xattr) > - return -ENOMEM; > + break; > > len = strlen(xattr->name) + 1; > new_xattr->name = kmalloc(XATTR_SECURITY_PREFIX_LEN + len, > GFP_KERNEL); > if (!new_xattr->name) { > kvfree(new_xattr); > - return -ENOMEM; > + break; > } > > memcpy(new_xattr->name, XATTR_SECURITY_PREFIX, > @@ -3579,6 +3599,16 @@ static int shmem_initxattrs(struct inode *inode, > simple_xattr_add(&info->xattrs, new_xattr); > } > > + if (xattr->name != NULL) { > + if (ispace) { > + raw_spin_lock(&sbinfo->stat_lock); > + sbinfo->free_ispace += ispace; > + raw_spin_unlock(&sbinfo->stat_lock); > + } > + simple_xattrs_free(&info->xattrs, NULL); > + return -ENOMEM; > + } > + > return 0; > } > > @@ -3599,16 +3629,39 @@ static int shmem_xattr_handler_set(const struct xattr_handler *handler, > size_t size, int flags) > { > struct shmem_inode_info *info = SHMEM_I(inode); > + struct shmem_sb_info *sbinfo = SHMEM_SB(inode->i_sb); > struct simple_xattr *old_xattr; > + size_t ispace = 0; > > name = xattr_full_name(handler, name); > + if (value && sbinfo->max_inodes) { > + ispace = simple_xattr_space(name, size); > + raw_spin_lock(&sbinfo->stat_lock); > + if (sbinfo->free_ispace < ispace) > + ispace = 0; > + else > + sbinfo->free_ispace -= ispace; > + raw_spin_unlock(&sbinfo->stat_lock); > + if (!ispace) > + return -ENOSPC; > + } > + > old_xattr = simple_xattr_set(&info->xattrs, name, value, size, flags); > if (!IS_ERR(old_xattr)) { > + ispace = 0; > + if (old_xattr && sbinfo->max_inodes) > + ispace = simple_xattr_space(old_xattr->name, > + old_xattr->size); > simple_xattr_free(old_xattr); > old_xattr = NULL; > inode->i_ctime = current_time(inode); > inode_inc_iversion(inode); > } > + if (ispace) { > + raw_spin_lock(&sbinfo->stat_lock); > + sbinfo->free_ispace += ispace; > + raw_spin_unlock(&sbinfo->stat_lock); > + } > return PTR_ERR(old_xattr); > } > > @@ -3624,9 +3677,16 @@ static const struct xattr_handler shmem_trusted_xattr_handler = { > .set = shmem_xattr_handler_set, > }; > > +static const struct xattr_handler shmem_user_xattr_handler = { > + .prefix = XATTR_USER_PREFIX, > + .get = shmem_xattr_handler_get, > + .set = shmem_xattr_handler_set, > +}; > + > static const struct xattr_handler *shmem_xattr_handlers[] = { > &shmem_security_xattr_handler, > &shmem_trusted_xattr_handler, > + &shmem_user_xattr_handler, > NULL > }; > > -- > 2.35.3 > -- Jan Kara SUSE Labs, CR