Re: [PATCH V6 6/8] fs/xfs: Combine xfs_diflags_to_linux() and xfs_diflags_to_iflags()

From: Ira Weiny
Date: Wed Apr 08 2020 - 13:09:25 EST


On Wed, Apr 08, 2020 at 12:08:27PM +1000, Dave Chinner wrote:
> On Tue, Apr 07, 2020 at 11:29:56AM -0700, ira.weiny@xxxxxxxxx wrote:
> > From: Ira Weiny <ira.weiny@xxxxxxxxx>

[snip]

> >
> > -STATIC void
> > -xfs_diflags_to_linux(
> > - struct xfs_inode *ip)
> > -{
> > - struct inode *inode = VFS_I(ip);
> > - unsigned int xflags = xfs_ip2xflags(ip);
> > -
> > - if (xflags & FS_XFLAG_IMMUTABLE)
> > - inode->i_flags |= S_IMMUTABLE;
> > - else
> > - inode->i_flags &= ~S_IMMUTABLE;
> > - if (xflags & FS_XFLAG_APPEND)
> > - inode->i_flags |= S_APPEND;
> > - else
> > - inode->i_flags &= ~S_APPEND;
> > - if (xflags & FS_XFLAG_SYNC)
> > - inode->i_flags |= S_SYNC;
> > - else
> > - inode->i_flags &= ~S_SYNC;
> > - if (xflags & FS_XFLAG_NOATIME)
> > - inode->i_flags |= S_NOATIME;
> > - else
> > - inode->i_flags &= ~S_NOATIME;
> > -#if 0 /* disabled until the flag switching races are sorted out */
> > - if (xflags & FS_XFLAG_DAX)
> > - inode->i_flags |= S_DAX;
> > - else
> > - inode->i_flags &= ~S_DAX;
> > -#endif
>
> So this variant will set the flag in the inode if the disk inode
> flag is set, otherwise it will clear it. It does it with if/else
> branches.
>
>
> > diff --git a/fs/xfs/xfs_iops.c b/fs/xfs/xfs_iops.c
> > index e07f7b641226..a4ac8568c8c7 100644
> > --- a/fs/xfs/xfs_iops.c
> > +++ b/fs/xfs/xfs_iops.c
> > @@ -1259,7 +1259,7 @@ xfs_inode_supports_dax(
> > return xfs_inode_buftarg(ip)->bt_daxdev != NULL;
> > }
> >
> > -STATIC bool
> > +static bool
> > xfs_inode_enable_dax(
> > struct xfs_inode *ip)
> > {
>
> This belongs in the previous patch.

Ah yea... Sorry.

Fixed in V7

>
> > @@ -1272,26 +1272,38 @@ xfs_inode_enable_dax(
> > return false;
> > }
> >
> > -STATIC void
> > +void
> > xfs_diflags_to_iflags(
> > - struct inode *inode,
> > - struct xfs_inode *ip)
> > + struct xfs_inode *ip,
> > + bool init)
> > {
> > - uint16_t flags = ip->i_d.di_flags;
> > -
> > - inode->i_flags &= ~(S_IMMUTABLE | S_APPEND | S_SYNC |
> > - S_NOATIME | S_DAX);
>
> And this code cleared all the flags in the inode first, then
> set them if the disk inode flag is set. This does not require
> branches, resulting in more readable code and better code
> generation.
>
> > + struct inode *inode = VFS_I(ip);
> > + uint diflags = xfs_ip2xflags(ip);
> >
> > - if (flags & XFS_DIFLAG_IMMUTABLE)
> > + if (diflags & FS_XFLAG_IMMUTABLE)
> > inode->i_flags |= S_IMMUTABLE;
> > - if (flags & XFS_DIFLAG_APPEND)
> > + else
> > + inode->i_flags &= ~S_IMMUTABLE;
>
> > + if (diflags & FS_XFLAG_APPEND)
> > inode->i_flags |= S_APPEND;
> > - if (flags & XFS_DIFLAG_SYNC)
> > + else
> > + inode->i_flags &= ~S_APPEND;
> > + if (diflags & FS_XFLAG_SYNC)
> > inode->i_flags |= S_SYNC;
> > - if (flags & XFS_DIFLAG_NOATIME)
> > + else
> > + inode->i_flags &= ~S_SYNC;
> > + if (diflags & FS_XFLAG_NOATIME)
> > inode->i_flags |= S_NOATIME;
> > - if (xfs_inode_enable_dax(ip))
> > - inode->i_flags |= S_DAX;
> > + else
> > + inode->i_flags &= ~S_NOATIME;
> > +
> > + /* Only toggle the dax flag when initializing */
> > + if (init) {
> > + if (xfs_inode_enable_dax(ip))
> > + inode->i_flags |= S_DAX;
> > + else
> > + inode->i_flags &= ~S_DAX;
> > + }
> > }
>
> IOWs, this:
>
> struct inode *inode = VFS_I(ip);
> unsigned int xflags = xfs_ip2xflags(ip);
> unsigned int flags = 0;
>
> if (xflags & FS_XFLAG_IMMUTABLE)
> flags |= S_IMMUTABLE;
> if (xflags & FS_XFLAG_APPEND)
> flags |= S_APPEND;
> if (xflags & FS_XFLAG_SYNC)
> flags |= S_SYNC;
> if (xflags & FS_XFLAG_NOATIME)
> flags |= S_NOATIME;
> if ((xflags & FS_XFLAG_DAX) && init)
> flags |= S_DAX;
>
> inode->i_flags &= ~(S_IMMUTABLE | S_APPEND | S_SYNC | S_NOATIME);
> inode->i_flags |= flags;
>
> ends up being much easier to read and results in better code
> generation. And we don't need to clear the S_DAX flag when "init" is
> set, because we are starting from an inode that has no flags set
> (because init!)...

This sounds good but I think we need a slight modification to make the function equivalent in functionality.

void
xfs_diflags_to_iflags(
struct xfs_inode *ip,
bool init)
{
struct inode *inode = VFS_I(ip);
unsigned int xflags = xfs_ip2xflags(ip);
unsigned int flags = 0;

inode->i_flags &= ~(S_IMMUTABLE | S_APPEND | S_SYNC | S_NOATIME |
S_DAX);

if (xflags & FS_XFLAG_IMMUTABLE)
flags |= S_IMMUTABLE;
if (xflags & FS_XFLAG_APPEND)
flags |= S_APPEND;
if (xflags & FS_XFLAG_SYNC)
flags |= S_SYNC;
if (xflags & FS_XFLAG_NOATIME)
flags |= S_NOATIME;
if (init && xfs_inode_enable_dax(ip))
flags |= S_DAX;

inode->i_flags |= flags;
}

I've queued this for v7.

Thanks,
Ira

>
> Cheers,
>
> Dave.
> --
> Dave Chinner
> david@xxxxxxxxxxxxx