On 2024-03-14 19:48:26, Darrick J. Wong wrote: > On Thu, Mar 14, 2024 at 06:07:02PM +0100, Andrey Albershteyn wrote: > > There's an issue that if special files is created before quota > > project is enabled, then it's not possible to link this file. This > > works fine for normal files. This happens because xfs_quota skips > > special files (no ioctls to set necessary flags). The check for > > having the same project ID for source and destination then fails as > > source file doesn't have any ID. > > > > mkfs.xfs -f /dev/sda > > mount -o prjquota /dev/sda /mnt/test > > > > mkdir /mnt/test/foo > > mkfifo /mnt/test/foo/fifo1 > > > > xfs_quota -xc "project -sp /mnt/test/foo 9" /mnt/test > > > Setting up project 9 (path /mnt/test/foo)... > > > xfs_quota: skipping special file /mnt/test/foo/fifo1 > > > Processed 1 (/etc/projects and cmdline) paths for project 9 with recursion depth infinite (-1). > > > > ln /mnt/test/foo/fifo1 /mnt/test/foo/fifo1_link > > > ln: failed to create hard link '/mnt/test/testdir/fifo1_link' => '/mnt/test/testdir/fifo1': Invalid cross-device link > > Aha. So hardlinking special files within a directory subtree that all > have the same nonzero project quota ID fails if that special file > happened to have been created before the subtree was assigned that pqid. > And there's nothing we can do about that, because there's no way to call > XFS_IOC_SETFSXATTR on a special file because opening those gets you a > different inode from the special block/fifo/chardev filesystem... > > > mkfifo /mnt/test/foo/fifo2 > > ln /mnt/test/foo/fifo2 /mnt/test/foo/fifo2_link > > > > Fix this by allowing linking of special files to the project quota > > if special files doesn't have any ID set (ID = 0). > > ...and that's the workaround for this situation. The project quota > accounting here will be weird because there will be (more) files in a > directory subtree than is reported by xfs_quota, but the subtree was > already messed up in that manner. > > Question: Should we have a XFS_IOC_SETFSXATTRAT where we can pass in > relative directory paths and actually query/update special files? After some more thinking/looking into the code this is probably the only way to make it work the same for special files. Also, I've noticed that this workaround can be applied to xfs_rename then. So, I will start with implementing XFS_IOC_SETFSXATTRAT -- - Andrey > > Signed-off-by: Andrey Albershteyn <aalbersh@xxxxxxxxxx> > > Reviewed-by: Darrick J. Wong <djwong@xxxxxxxxxx> > > --D > > > --- > > 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 1fd94958aa97..b7be19be0132 100644 > > --- a/fs/xfs/xfs_inode.c > > +++ b/fs/xfs/xfs_inode.c > > @@ -1240,8 +1240,19 @@ xfs_link( > > */ > > if (unlikely((tdp->i_diflags & XFS_DIFLAG_PROJINHERIT) && > > tdp->i_projid != sip->i_projid)) { > > - error = -EXDEV; > > - goto error_return; > > + /* > > + * Project quota setup skips special files which can > > + * leave inodes in a PROJINHERIT directory without a > > + * project ID set. We need to allow links 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(sip)->i_mode) || > > + sip->i_projid != 0) { > > + error = -EXDEV; > > + goto error_return; > > + } > > } > > > > if (!resblks) { > > -- > > 2.42.0 > > > > >