diff mbox series

[2/4] xfs: allow renames of project-less inodes

Message ID 20240509151459.3622910-4-aalbersh@redhat.com (mailing list archive)
State Superseded, archived
Headers show
Series Introduce XFS_IOC_SETFSXATTRAT/XFS_IOC_GETFSXATTRAT ioctls | expand

Commit Message

Andrey Albershteyn May 9, 2024, 3:14 p.m. UTC
Identical problem as worked around in commit e23d7e82b707 ("xfs:
allow cross-linking special files without project quota") exists
with renames. Renaming special file without project ID is not
possible inside PROJINHERIT directory.

Special files inodes can not have project ID set from userspace and
are skipped during initial project setup. Those inodes are left
project-less in the project directory. New inodes created after
project initialization do have an ID. Creating hard links or
renaming those project-less inodes then fails on different ID check.

Add workaround to allow renames of special files without project ID.

Signed-off-by: Andrey Albershteyn <aalbersh@redhat.com>
---
 fs/xfs/xfs_inode.c | 15 +++++++++++++--
 1 file changed, 13 insertions(+), 2 deletions(-)

Comments

Darrick J. Wong May 9, 2024, 11:28 p.m. UTC | #1
On Thu, May 09, 2024 at 05:14:58PM +0200, Andrey Albershteyn wrote:
> Identical problem as worked around in commit e23d7e82b707 ("xfs:
> allow cross-linking special files without project quota") exists
> with renames. Renaming special file without project ID is not
> possible inside PROJINHERIT directory.
> 
> Special files inodes can not have project ID set from userspace and
> are skipped during initial project setup. Those inodes are left
> project-less in the project directory. New inodes created after
> project initialization do have an ID. Creating hard links or
> renaming those project-less inodes then fails on different ID check.
> 
> Add workaround to allow renames of special files without project ID.
> 
> Signed-off-by: Andrey Albershteyn <aalbersh@redhat.com>
> ---
>  fs/xfs/xfs_inode.c | 15 +++++++++++++--
>  1 file changed, 13 insertions(+), 2 deletions(-)
> 
> diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c
> index 58fb7a5062e1..508113515eec 100644
> --- a/fs/xfs/xfs_inode.c
> +++ b/fs/xfs/xfs_inode.c
> @@ -3275,8 +3275,19 @@ xfs_rename(
>  	 */
>  	if (unlikely((target_dp->i_diflags & XFS_DIFLAG_PROJINHERIT) &&
>  		     target_dp->i_projid != src_ip->i_projid)) {
> -		error = -EXDEV;
> -		goto out_trans_cancel;
> +		/*
> +		 * Project quota setup skips special files which can
> +		 * leave inodes in a PROJINHERIT directory without a
> +		 * project ID set. We need to allow renames to be made
> +		 * to these "project-less" inodes because userspace
> +		 * expects them to succeed after project ID setup,
> +		 * but everything else should be rejected.
> +		 */
> +		if (!special_file(VFS_I(src_ip)->i_mode) ||
> +		    src_ip->i_projid != 0) {
> +			error = -EXDEV;
> +			goto out_trans_cancel;
> +		}
>  	}

Should this be a shared helper called by xfs_rename and xfs_link?

--D

>  
>  	/* RENAME_EXCHANGE is unique from here on. */
> -- 
> 2.42.0
> 
>
Andrey Albershteyn May 10, 2024, 9:41 a.m. UTC | #2
On 2024-05-09 16:28:05, Darrick J. Wong wrote:
> On Thu, May 09, 2024 at 05:14:58PM +0200, Andrey Albershteyn wrote:
> > Identical problem as worked around in commit e23d7e82b707 ("xfs:
> > allow cross-linking special files without project quota") exists
> > with renames. Renaming special file without project ID is not
> > possible inside PROJINHERIT directory.
> > 
> > Special files inodes can not have project ID set from userspace and
> > are skipped during initial project setup. Those inodes are left
> > project-less in the project directory. New inodes created after
> > project initialization do have an ID. Creating hard links or
> > renaming those project-less inodes then fails on different ID check.
> > 
> > Add workaround to allow renames of special files without project ID.
> > 
> > Signed-off-by: Andrey Albershteyn <aalbersh@redhat.com>
> > ---
> >  fs/xfs/xfs_inode.c | 15 +++++++++++++--
> >  1 file changed, 13 insertions(+), 2 deletions(-)
> > 
> > diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c
> > index 58fb7a5062e1..508113515eec 100644
> > --- a/fs/xfs/xfs_inode.c
> > +++ b/fs/xfs/xfs_inode.c
> > @@ -3275,8 +3275,19 @@ xfs_rename(
> >  	 */
> >  	if (unlikely((target_dp->i_diflags & XFS_DIFLAG_PROJINHERIT) &&
> >  		     target_dp->i_projid != src_ip->i_projid)) {
> > -		error = -EXDEV;
> > -		goto out_trans_cancel;
> > +		/*
> > +		 * Project quota setup skips special files which can
> > +		 * leave inodes in a PROJINHERIT directory without a
> > +		 * project ID set. We need to allow renames to be made
> > +		 * to these "project-less" inodes because userspace
> > +		 * expects them to succeed after project ID setup,
> > +		 * but everything else should be rejected.
> > +		 */
> > +		if (!special_file(VFS_I(src_ip)->i_mode) ||
> > +		    src_ip->i_projid != 0) {
> > +			error = -EXDEV;
> > +			goto out_trans_cancel;
> > +		}
> >  	}
> 
> Should this be a shared helper called by xfs_rename and xfs_link?

yeah, it can be

> 
> --D
> 
> >  
> >  	/* RENAME_EXCHANGE is unique from here on. */
> > -- 
> > 2.42.0
> > 
> > 
>
diff mbox series

Patch

diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c
index 58fb7a5062e1..508113515eec 100644
--- a/fs/xfs/xfs_inode.c
+++ b/fs/xfs/xfs_inode.c
@@ -3275,8 +3275,19 @@  xfs_rename(
 	 */
 	if (unlikely((target_dp->i_diflags & XFS_DIFLAG_PROJINHERIT) &&
 		     target_dp->i_projid != src_ip->i_projid)) {
-		error = -EXDEV;
-		goto out_trans_cancel;
+		/*
+		 * Project quota setup skips special files which can
+		 * leave inodes in a PROJINHERIT directory without a
+		 * project ID set. We need to allow renames to be made
+		 * to these "project-less" inodes because userspace
+		 * expects them to succeed after project ID setup,
+		 * but everything else should be rejected.
+		 */
+		if (!special_file(VFS_I(src_ip)->i_mode) ||
+		    src_ip->i_projid != 0) {
+			error = -EXDEV;
+			goto out_trans_cancel;
+		}
 	}
 
 	/* RENAME_EXCHANGE is unique from here on. */