Received: by 2002:a25:e7d8:0:0:0:0:0 with SMTP id e207csp1859777ybh; Fri, 13 Mar 2020 08:38:15 -0700 (PDT) X-Google-Smtp-Source: ADFU+vv7XhLffsk9Fx0BBumVmRZnzNtMVyNAC4t/qs4vAq8diRiqOn7OnhzLMSS32OV3HWCyMGKX X-Received: by 2002:a9d:64d4:: with SMTP id n20mr10957269otl.193.1584113895551; Fri, 13 Mar 2020 08:38:15 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1584113895; cv=none; d=google.com; s=arc-20160816; b=IZhT6xTJEw1rzIWVHMhCTMQvLxIBWXWC+MUc7P7RSu81WqTA8mB0wqTmr85s/NSX8A KdvUlfiO0ugfjTub9DTrakfu14m9pAuFk8wDRkUyNYo+3ASUgTx69VHwBAUGyuEFZ/Oq fVHOXw+vkDrmpsgndkGDMaRl86oSqp3xB60jRtaMT6TMfysjJ9CbdOb6BSUebwujAm0b g7cghNQ0GRnYNCNhqT6eqTDv8WTSywC5oahi+oGcEB8qj957np0kCkXpdQ4tK8cIGv1Y JYplFz9mUu4OPh4Bh/ecsg36rl5uTOFJgD9sG3lav836YZ8X3wB/Z5tu9LODiYsYA/b/ WqVA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:user-agent:in-reply-to :content-disposition:mime-version:references:message-id:subject:cc :to:from:date; bh=QTsT+WK51EEIOjwRF4+hcTOLTOnQwoERBW8MTuXfXuw=; b=Us3duv3IZMUxtuLXMSuN8pfUEylU3Do6BYCi635ZIjI3s5Bt69SnevgV2TZx/1N+Fu a09i5KgxG/FHxaxJ9yz/XYfvUw/QbUE0TWq8+RQv/1iAmDkK/33UfReXIbQ0RUP+zM5c Z2HG4A3OvhtjDa+o0pseIZuFjbaIaD9rCmytI6McH5mQ2AHX9M50PpSWez4IfBRLgpbI kC4YzkxgKiDyYMwdFntYPWwVycEgqklmKsaR72X7xPaAPc+QfvYQLj0Pv+65657ArjuV 848Wpc0+HzkKlf4xdqXVsZFFqXhPDJUUwQB6+EOPpF1zPb4UnOFkjl7OYWpmIZZaWmx8 ySWg== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-nfs-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-nfs-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id i19si4175966oik.272.2020.03.13.08.37.52; Fri, 13 Mar 2020 08:38:15 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-nfs-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-nfs-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-nfs-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726637AbgCMPfv (ORCPT + 99 others); Fri, 13 Mar 2020 11:35:51 -0400 Received: from fieldses.org ([173.255.197.46]:51172 "EHLO fieldses.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726591AbgCMPfu (ORCPT ); Fri, 13 Mar 2020 11:35:50 -0400 Received: by fieldses.org (Postfix, from userid 2815) id 9FC1D83B; Fri, 13 Mar 2020 11:35:49 -0400 (EDT) Date: Fri, 13 Mar 2020 11:35:49 -0400 From: "J. Bruce Fields" To: Frank van der Linden Cc: chuck.lever@oracle.com, linux-nfs@vger.kernel.org Subject: Re: [PATCH 02/14] xattr: modify vfs_{set,remove}xattr for NFS server use Message-ID: <20200313153549.GD12537@fieldses.org> References: <20200311195954.27117-1-fllinden@amazon.com> <20200311195954.27117-3-fllinden@amazon.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20200311195954.27117-3-fllinden@amazon.com> User-Agent: Mutt/1.5.21 (2010-09-15) Sender: linux-nfs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-nfs@vger.kernel.org On Wed, Mar 11, 2020 at 07:59:42PM +0000, Frank van der Linden wrote: > To be called from the upcoming NFS server xattr code, the vfs_removexattr > and vfs_setxattr need some modifications. > > First, they need to grow a _locked variant, since the NFS server code > will call this with i_rwsem held. It needs to do that in fh_lock to be > able to atomically provide the before and after change attributes. Unlike NFSv3, NFSv4+ doesn't support atomic before- and after- change attributes for setattr. Trying to take advantage of that assumption might result in worse code, though. > Second, RFC 8276 (NFSv4 extended attribute support) specifies that > delegations should be recalled (8.4.2.4, 8.4.4.4) when a SETXATTR > or REMOVEXATTR operation is performed. So, like with other fs > operations, try to break the delegation. The _locked version of > these operations will not wait for the delegation to be successfully > broken, instead returning an error if it wasn't, so that the NFS > server code can return NFS4ERR_DELAY to the client (similar to > what e.g. vfs_link does). Is there a preexisting bug here? Even without NFS support for xattrs, a local setxattr on the filesystem should still revoke any delegations held by remote NFS clients. I couldn't tell whether we're getting that right from a quick look at the current code. --b. > > Signed-off-by: Frank van der Linden > --- > fs/xattr.c | 63 +++++++++++++++++++++++++++++++++++++++++++++------ > include/linux/xattr.h | 2 ++ > 2 files changed, 58 insertions(+), 7 deletions(-) > > diff --git a/fs/xattr.c b/fs/xattr.c > index 90dd78f0eb27..58013bcbc333 100644 > --- a/fs/xattr.c > +++ b/fs/xattr.c > @@ -204,10 +204,10 @@ int __vfs_setxattr_noperm(struct dentry *dentry, const char *name, > return error; > } > > - > int > -vfs_setxattr(struct dentry *dentry, const char *name, const void *value, > - size_t size, int flags) > +__vfs_setxattr_locked(struct dentry *dentry, const char *name, > + const void *value, size_t size, int flags, > + struct inode **delegated_inode) > { > struct inode *inode = dentry->d_inode; > int error; > @@ -216,15 +216,40 @@ vfs_setxattr(struct dentry *dentry, const char *name, const void *value, > if (error) > return error; > > - inode_lock(inode); > error = security_inode_setxattr(dentry, name, value, size, flags); > if (error) > goto out; > > + error = try_break_deleg(inode, delegated_inode); > + if (error) > + goto out; > + > error = __vfs_setxattr_noperm(dentry, name, value, size, flags); > > out: > + return error; > +} > +EXPORT_SYMBOL_GPL(__vfs_setxattr_locked); > + > +int > +vfs_setxattr(struct dentry *dentry, const char *name, const void *value, > + size_t size, int flags) > +{ > + struct inode *inode = dentry->d_inode; > + struct inode *delegated_inode = NULL; > + int error; > + > +retry_deleg: > + inode_lock(inode); > + error = __vfs_setxattr_locked(dentry, name, value, size, flags, > + &delegated_inode); > inode_unlock(inode); > + > + if (delegated_inode) { > + error = break_deleg_wait(&delegated_inode); > + if (!error) > + goto retry_deleg; > + } > return error; > } > EXPORT_SYMBOL_GPL(vfs_setxattr); > @@ -379,7 +404,8 @@ __vfs_removexattr(struct dentry *dentry, const char *name) > EXPORT_SYMBOL(__vfs_removexattr); > > int > -vfs_removexattr(struct dentry *dentry, const char *name) > +__vfs_removexattr_locked(struct dentry *dentry, const char *name, > + struct inode **delegated_inode) > { > struct inode *inode = dentry->d_inode; > int error; > @@ -388,11 +414,14 @@ vfs_removexattr(struct dentry *dentry, const char *name) > if (error) > return error; > > - inode_lock(inode); > error = security_inode_removexattr(dentry, name); > if (error) > goto out; > > + error = try_break_deleg(inode, delegated_inode); > + if (error) > + goto out; > + > error = __vfs_removexattr(dentry, name); > > if (!error) { > @@ -401,12 +430,32 @@ vfs_removexattr(struct dentry *dentry, const char *name) > } > > out: > + return error; > +} > +EXPORT_SYMBOL_GPL(__vfs_removexattr_locked); > + > +int > +vfs_removexattr(struct dentry *dentry, const char *name) > +{ > + struct inode *inode = dentry->d_inode; > + struct inode *delegated_inode = NULL; > + int error; > + > +retry_deleg: > + inode_lock(inode); > + error = __vfs_removexattr_locked(dentry, name, &delegated_inode); > inode_unlock(inode); > + > + if (delegated_inode) { > + error = break_deleg_wait(&delegated_inode); > + if (!error) > + goto retry_deleg; > + } > + > return error; > } > EXPORT_SYMBOL_GPL(vfs_removexattr); > > - > /* > * Extended attribute SET operations > */ > diff --git a/include/linux/xattr.h b/include/linux/xattr.h > index 6dad031be3c2..3a71ad716da5 100644 > --- a/include/linux/xattr.h > +++ b/include/linux/xattr.h > @@ -51,8 +51,10 @@ ssize_t vfs_getxattr(struct dentry *, const char *, void *, size_t); > ssize_t vfs_listxattr(struct dentry *d, char *list, size_t size); > int __vfs_setxattr(struct dentry *, struct inode *, const char *, const void *, size_t, int); > int __vfs_setxattr_noperm(struct dentry *, const char *, const void *, size_t, int); > +int __vfs_setxattr_locked(struct dentry *, const char *, const void *, size_t, int, struct inode **); > int vfs_setxattr(struct dentry *, const char *, const void *, size_t, int); > int __vfs_removexattr(struct dentry *, const char *); > +int __vfs_removexattr_locked(struct dentry *, const char *, struct inode **); > int vfs_removexattr(struct dentry *, const char *); > > ssize_t generic_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size); > -- > 2.16.6