@@ -3351,6 +3351,17 @@ xfs_bmap_btalloc_accounting(
args->len);
}
+static inline bool
+xfs_bmap_use_forcealign(
+ const struct xfs_bmalloca *ap)
+{
+ if (!xfs_inode_force_align(ap->ip))
+ return false;
+
+ return (ap->flags & XFS_BMAPI_COWFORK) ||
+ (ap->datatype & XFS_ALLOC_USERDATA);
+}
+
static int
xfs_bmap_compute_alignments(
struct xfs_bmalloca *ap,
@@ -3366,6 +3377,17 @@ xfs_bmap_compute_alignments(
else if (mp->m_dalign)
stripe_align = mp->m_dalign;
+ /*
+ * File data mappings with forced alignment can use the stripe
+ * alignment if it's a multiple of the forcealign value. Otherwise,
+ * use the regular forcealign value.
+ */
+ if (xfs_bmap_use_forcealign(ap)) {
+ if (!stripe_align || stripe_align % mp->m_sb.sb_rextsize)
+ stripe_align = mp->m_sb.sb_rextsize;
+ args->alignment = stripe_align;
+ }
+
if (ap->flags & XFS_BMAPI_COWFORK)
align = xfs_get_cowextsz_hint(ap->ip);
else if (ap->datatype & XFS_ALLOC_USERDATA)
@@ -3438,6 +3460,9 @@ xfs_bmap_exact_minlen_extent_alloc(
ASSERT(ap->length);
+ if (xfs_inode_force_align(ap->ip))
+ return -ENOSPC;
+
if (ap->minlen != 1) {
ap->blkno = NULLFSBLOCK;
ap->length = 0;
@@ -3511,6 +3536,7 @@ xfs_bmap_btalloc_at_eof(
{
struct xfs_mount *mp = args->mp;
struct xfs_perag *caller_pag = args->pag;
+ int orig_alignment = args->alignment;
int error;
/*
@@ -3585,10 +3611,10 @@ xfs_bmap_btalloc_at_eof(
/*
* Allocation failed, so turn return the allocation args to their
- * original non-aligned state so the caller can proceed on allocation
- * failure as if this function was never called.
+ * original state so the caller can proceed on allocation failure as
+ * if this function was never called.
*/
- args->alignment = 1;
+ args->alignment = orig_alignment;
return 0;
}
@@ -3611,6 +3637,10 @@ xfs_bmap_btalloc_low_space(
{
int error;
+ /* Don't try unaligned last-chance allocations with forcealign */
+ if (xfs_inode_force_align(ap->ip))
+ return -ENOSPC;
+
if (args->minlen > ap->minlen) {
args->minlen = ap->minlen;
error = xfs_alloc_vextent_start_ag(args, ap->blkno);
@@ -4115,7 +4145,9 @@ xfs_bmap_alloc_userdata(
if (bma->offset == 0)
bma->datatype |= XFS_ALLOC_INITIAL_USER_DATA;
- if (mp->m_dalign && bma->length >= mp->m_dalign) {
+ /* forcealign mode reuses the stripe unit alignment code */
+ if (xfs_inode_force_align(bma->ip) ||
+ (mp->m_dalign && bma->length >= mp->m_dalign)) {
error = xfs_bmap_isaeof(bma, whichfork);
if (error)
return error;
@@ -6381,6 +6413,10 @@ xfs_extlen_t
xfs_get_extsz_hint(
struct xfs_inode *ip)
{
+ /* forcealign means we align to rextsize */
+ if (xfs_inode_force_align(ip))
+ return ip->i_mount->m_sb.sb_rextsize;
+
/*
* No point in aligning allocations if we need to COW to actually
* write to them.
@@ -6405,6 +6441,10 @@ xfs_get_cowextsz_hint(
{
xfs_extlen_t a, b;
+ /* forcealign means we align to rextsize */
+ if (xfs_inode_force_align(ip))
+ return ip->i_mount->m_sb.sb_rextsize;
+
a = 0;
if (ip->i_diflags2 & XFS_DIFLAG2_COWEXTSIZE)
a = ip->i_cowextsize;
@@ -185,7 +185,9 @@ xfs_eof_alignment(
* If mounted with the "-o swalloc" option the alignment is
* increased from the strip unit size to the stripe width.
*/
- if (mp->m_swidth && xfs_has_swalloc(mp))
+ if (xfs_inode_force_align(ip))
+ align = xfs_get_extsz_hint(ip);
+ else if (mp->m_swidth && xfs_has_swalloc(mp))
align = mp->m_swidth;
else if (mp->m_dalign)
align = mp->m_dalign;
@@ -1803,6 +1803,10 @@ xfs_reflink_remap_prep(
if (IS_DAX(inode_in) != IS_DAX(inode_out))
goto out_unlock;
+ /* XXX Can't reflink forcealign files for now */
+ if (xfs_inode_force_align(src) || xfs_inode_force_align(dest))
+ goto out_unlock;
+
/* Check non-power of two alignment issues, if necessary. */
if (XFS_IS_REALTIME_INODE(dest) && !is_power_of_2(alloc_unit)) {
ret = xfs_reflink_remap_check_rtalign(src, pos_in, dest,