diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c index 49db1611de96f249a02ea9ba828425e9616719fb..75928200d7e9f5913052821b425e42a0ba0fc212 100644 --- a/fs/xfs/xfs_file.c +++ b/fs/xfs/xfs_file.c @@ -814,6 +814,10 @@ xfs_file_write_iter( return xfs_file_dax_write(iocb, from); if (iocb->ki_flags & IOCB_DIRECT) { + + if (xfs_inode_atomicwrites(ip) && + xfs_has_atomicalways(ip->i_mount)) + iocb->ki_flags |= IOCB_ATOMIC; /* * Allow a directio write to fall back to a buffered * write *only* in the case that we're doing a reflink diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h index 888d6bf9bea7adf2dd30ba73b74e7b2238ce7ed8..6b952ff031b6dea9aa62448419a2a046b69e9194 100644 --- a/fs/xfs/xfs_mount.h +++ b/fs/xfs/xfs_mount.h @@ -279,6 +279,7 @@ typedef struct xfs_mount { /* Mount features */ +#define XFS_FEAT_ATOMICALWAYS (1ULL << 47) /* convert dio to atomic writes always */ #define XFS_FEAT_NOATTR2 (1ULL << 48) /* disable attr2 creation */ #define XFS_FEAT_NOALIGN (1ULL << 49) /* ignore alignment */ #define XFS_FEAT_ALLOCSIZE (1ULL << 50) /* user specified allocation size */ @@ -365,6 +366,7 @@ __XFS_HAS_FEAT(dax_always, DAX_ALWAYS) __XFS_HAS_FEAT(dax_never, DAX_NEVER) __XFS_HAS_FEAT(norecovery, NORECOVERY) __XFS_HAS_FEAT(nouuid, NOUUID) +__XFS_HAS_FEAT(atomicalways, ATOMICALWAYS) /* * Operational mount state flags diff --git a/fs/xfs/xfs_super.c b/fs/xfs/xfs_super.c index d43f76a4b99a433f17697cf44ed2507cef076d35..0359713fefd872620fa9a3d7676905797f2c4866 100644 --- a/fs/xfs/xfs_super.c +++ b/fs/xfs/xfs_super.c @@ -116,7 +116,7 @@ enum { Opt_filestreams, Opt_quota, Opt_noquota, Opt_usrquota, Opt_grpquota, Opt_prjquota, Opt_uquota, Opt_gquota, Opt_pquota, Opt_uqnoenforce, Opt_gqnoenforce, Opt_pqnoenforce, Opt_qnoenforce, - Opt_discard, Opt_nodiscard, Opt_dax, Opt_dax_enum, + Opt_discard, Opt_nodiscard, Opt_dax, Opt_dax_enum, Opt_atomicalways, }; static const struct fs_parameter_spec xfs_fs_parameters[] = { @@ -161,6 +161,7 @@ static const struct fs_parameter_spec xfs_fs_parameters[] = { fsparam_flag("nodiscard", Opt_nodiscard), fsparam_flag("dax", Opt_dax), fsparam_enum("dax", Opt_dax_enum, dax_param_enums), + fsparam_flag("atomicalways", Opt_atomicalways), {} }; @@ -1361,6 +1362,9 @@ xfs_fc_parse_param( xfs_fs_warn_deprecated(fc, param, XFS_FEAT_NOATTR2, true); parsing_mp->m_features |= XFS_FEAT_NOATTR2; return 0; + case Opt_atomicalways: + parsing_mp->m_features |= XFS_FEAT_ATOMICALWAYS; + return 0; default: xfs_warn(parsing_mp, "unknown mount option [%s].", param->key); return -EINVAL;