diff mbox series

[RFC,2/2] xfs: do not allow reflinking inodes with the dax flag set

Message ID 07c41ba8-ecb7-5042-fa6c-dd8c9754b824@redhat.com (mailing list archive)
State Superseded
Headers show
Series xfs: fix up some reflink+dax interactions | expand

Commit Message

Eric Sandeen Dec. 1, 2020, 7:20 p.m. UTC
Today, xfs_reflink_remap_prep() will reject inodes which are in the CPU
direct access state, i.e. IS_DAX() is true.  However, it is possible to
have inodes with the XFS_DIFLAG2_DAX set, but which are not activated as
dax, due to the dax=never mount option, or due to the flag being set after
the inode was loaded.

To avoid confusion and make the lack of dax+reflink crystal clear for the
user, reject reflink requests for both IS_DAX and XFS_DIFLAG2_DAX inodes.

Signed-off-by: Eric Sandeen <sandeen@redhat.com>
---

This is RFC because as Darrick says, it introduces a new failure mode for
reflink. On the flip side, today the user can reflink a chattr +x'd file,
but cannot chattr +x a reflinked file, which seems a best a bit asymmetrical
and confusing... see xfs_ioctl_setattr_xflags()

 fs/xfs/xfs_reflink.c | 5 +++++
 1 file changed, 5 insertions(+)

Comments

Christoph Hellwig Dec. 2, 2020, 10:22 a.m. UTC | #1
On Tue, Dec 01, 2020 at 01:20:55PM -0600, Eric Sandeen wrote:
> Today, xfs_reflink_remap_prep() will reject inodes which are in the CPU
> direct access state, i.e. IS_DAX() is true.  However, it is possible to
> have inodes with the XFS_DIFLAG2_DAX set, but which are not activated as
> dax, due to the dax=never mount option, or due to the flag being set after
> the inode was loaded.
> 
> To avoid confusion and make the lack of dax+reflink crystal clear for the
> user, reject reflink requests for both IS_DAX and XFS_DIFLAG2_DAX inodes.
> 
> Signed-off-by: Eric Sandeen <sandeen@redhat.com>
> ---
> 
> This is RFC because as Darrick says, it introduces a new failure mode for
> reflink. On the flip side, today the user can reflink a chattr +x'd file,
> but cannot chattr +x a reflinked file, which seems a best a bit asymmetrical
> and confusing... see xfs_ioctl_setattr_xflags()

This seems confusing.  IMHO for now we should just for non-dax access
to any reflink file even if XFS_DIFLAG2_DAX is set.  The only place
where we cannot do that is if a file has XFS_DIFLAG2_DAX set and is in
use and we want to reflink it.  Note that "in use" is kinda murky and
potentially racy.  So IMHO not allowing reflink when XFS_DIFLAG2_DAX
is set and dax=never is not set makes sense, but we should not go
further.
Eric Sandeen Dec. 2, 2020, 2:44 p.m. UTC | #2
On 12/2/20 4:22 AM, Christoph Hellwig wrote:
> On Tue, Dec 01, 2020 at 01:20:55PM -0600, Eric Sandeen wrote:
>> Today, xfs_reflink_remap_prep() will reject inodes which are in the CPU
>> direct access state, i.e. IS_DAX() is true.  However, it is possible to
>> have inodes with the XFS_DIFLAG2_DAX set, but which are not activated as
>> dax, due to the dax=never mount option, or due to the flag being set after
>> the inode was loaded.
>>
>> To avoid confusion and make the lack of dax+reflink crystal clear for the
>> user, reject reflink requests for both IS_DAX and XFS_DIFLAG2_DAX inodes.
>>
>> Signed-off-by: Eric Sandeen <sandeen@redhat.com>
>> ---
>>
>> This is RFC because as Darrick says, it introduces a new failure mode for
>> reflink. On the flip side, today the user can reflink a chattr +x'd file,
>> but cannot chattr +x a reflinked file, which seems a best a bit asymmetrical
>> and confusing... see xfs_ioctl_setattr_xflags()
> 
> This seems confusing.  IMHO for now we should just for non-dax access
> to any reflink file even if XFS_DIFLAG2_DAX is set.  The only place
> where we cannot do that is if a file has XFS_DIFLAG2_DAX set and is in
> use and we want to reflink it.  Note that "in use" is kinda murky and
> potentially racy.  So IMHO not allowing reflink when XFS_DIFLAG2_DAX
> is set and dax=never is not set makes sense, but we should not go
> further.

Hm, trying to parse that...

Would it be correct to restate your last sentence as "Disallowing reflink
when XFS_DIFLAG2_DAX is set and dax=inode is set makes sense?"

If so, then the only change you're suggesting to this patch is to /allow/
reflinking if dax=never is set?

I just figured a very clear statementa bout incompatible flags was simplest,
but I get it that it's overly restrictive, functionally.

Thanks,
-Eric
Christoph Hellwig Dec. 2, 2020, 5:15 p.m. UTC | #3
On Wed, Dec 02, 2020 at 08:44:24AM -0600, Eric Sandeen wrote:
> Would it be correct to restate your last sentence as "Disallowing reflink
> when XFS_DIFLAG2_DAX is set and dax=inode is set makes sense?"
> 
> If so, then the only change you're suggesting to this patch is to /allow/
> reflinking if dax=never is set?

Yes, I think we should.

> I just figured a very clear statementa bout incompatible flags was simplest,
> but I get it that it's overly restrictive, functionally.

The simplest in terms of semantics is to make sure reflink+DAX works,
and while we are on the way we'll still need a workaround until that
happen.
Christoph Hellwig Dec. 2, 2020, 5:15 p.m. UTC | #4
On Wed, Dec 02, 2020 at 05:15:30PM +0000, Christoph Hellwig wrote:
> On Wed, Dec 02, 2020 at 08:44:24AM -0600, Eric Sandeen wrote:
> > Would it be correct to restate your last sentence as "Disallowing reflink
> > when XFS_DIFLAG2_DAX is set and dax=inode is set makes sense?"
> > 
> > If so, then the only change you're suggesting to this patch is to /allow/
> > reflinking if dax=never is set?
> 
> Yes, I think we should.
> 
> > I just figured a very clear statementa bout incompatible flags was simplest,
> > but I get it that it's overly restrictive, functionally.
> 
> The simplest in terms of semantics is to make sure reflink+DAX works,
> and while we are on the way we'll still need a workaround until that
> happen.
happens.
diff mbox series

Patch

diff --git a/fs/xfs/xfs_reflink.c b/fs/xfs/xfs_reflink.c
index 6fa05fb78189..b69dbb992b0c 100644
--- a/fs/xfs/xfs_reflink.c
+++ b/fs/xfs/xfs_reflink.c
@@ -1308,6 +1308,11 @@  xfs_reflink_remap_prep(
 	if (IS_DAX(inode_in) || IS_DAX(inode_out))
 		goto out_unlock;
 
+	/* Until we have dax+reflink don't even allow the flags to co-exist */
+	if (src->i_d.di_flags2 & XFS_DIFLAG2_DAX ||
+	    dest->i_d.di_flags2 & XFS_DIFLAG2_DAX)
+		goto out_unlock;
+
 	ret = generic_remap_file_range_prep(file_in, pos_in, file_out, pos_out,
 			len, remap_flags);
 	if (ret || *len == 0)