Skip to content
Permalink
Browse files
xfs: extent transaction reservations for parent attributes
We need to add, remove or modify parent pointer attributes during
create/link/unlink/rename operations atomically with the dirents in the
parent directories being modified. This means they need to be modified
in the same transaction as the parent directories, and so we need to add
the required space for the attribute modifications to the transaction
reservations.

[achender: rebased, added xfs_sb_version_hasparent stub]

Signed-off-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Allison Henderson <allison.henderson@oracle.com>
  • Loading branch information
allisonhenderson committed Jul 7, 2021
1 parent ec37e58 commit 4801b661f577ce8fa4a27b26493a7b4c5bf327b4
Show file tree
Hide file tree
Showing 3 changed files with 94 additions and 23 deletions.
@@ -609,6 +609,11 @@ static inline bool xfs_sb_version_needsrepair(struct xfs_sb *sbp)
(sbp->sb_features_incompat & XFS_SB_FEAT_INCOMPAT_NEEDSREPAIR);
}

static inline bool xfs_sb_version_hasparent(struct xfs_sb *sbp)
{
return false; /* We'll enable this at the end of the set */
}

/*
* end of superblock version macros
*/
@@ -832,29 +832,30 @@ xfs_calc_sb_reservation(
return xfs_calc_buf_res(1, mp->m_sb.sb_sectsize);
}

/*
* Namespace reservations.
*
* These get tricky when parent pointers are enabled as we have attribute
* modifications occurring from within these transactions. Rather than confuse
* each of these reservation calculations with the conditional attribute
* reservations, add them here in a clear and concise manner. This assumes that
* the attribute reservations have already been calculated.
*
* Note that we only include the static attribute reservation here; the runtime
* reservation will have to be modified by the size of the attributes being
* added/removed/modified. See the comments on the attribute reservation
* calculations for more details.
*
* Note for rename: rename will vastly overestimate requirements. This will be
* addressed later when modifications are made to ensure parent attribute
* modifications can be done atomically with the rename operation.
*/
void
xfs_trans_resv_calc(
xfs_calc_namespace_reservations(
struct xfs_mount *mp,
struct xfs_trans_resv *resp)
{
/*
* The following transactions are logged in physical format and
* require a permanent reservation on space.
*/
resp->tr_write.tr_logres = xfs_calc_write_reservation(mp);
if (xfs_sb_version_hasreflink(&mp->m_sb))
resp->tr_write.tr_logcount = XFS_WRITE_LOG_COUNT_REFLINK;
else
resp->tr_write.tr_logcount = XFS_WRITE_LOG_COUNT;
resp->tr_write.tr_logflags |= XFS_TRANS_PERM_LOG_RES;

resp->tr_itruncate.tr_logres = xfs_calc_itruncate_reservation(mp);
if (xfs_sb_version_hasreflink(&mp->m_sb))
resp->tr_itruncate.tr_logcount =
XFS_ITRUNCATE_LOG_COUNT_REFLINK;
else
resp->tr_itruncate.tr_logcount = XFS_ITRUNCATE_LOG_COUNT;
resp->tr_itruncate.tr_logflags |= XFS_TRANS_PERM_LOG_RES;
ASSERT(resp->tr_attrsetm.tr_logres > 0);

resp->tr_rename.tr_logres = xfs_calc_rename_reservation(mp);
resp->tr_rename.tr_logcount = XFS_RENAME_LOG_COUNT;
@@ -876,15 +877,77 @@ xfs_trans_resv_calc(
resp->tr_create.tr_logcount = XFS_CREATE_LOG_COUNT;
resp->tr_create.tr_logflags |= XFS_TRANS_PERM_LOG_RES;

resp->tr_mkdir.tr_logres = xfs_calc_mkdir_reservation(mp);
resp->tr_mkdir.tr_logcount = XFS_MKDIR_LOG_COUNT;
resp->tr_mkdir.tr_logflags |= XFS_TRANS_PERM_LOG_RES;

xfs_calc_parent_ptr_reservations(mp);
}

void xfs_calc_parent_ptr_reservations(struct xfs_mount *mp)
{
struct xfs_trans_resv *resp = M_RES(mp);

/* Calculate extra space needed for parent pointer attributes */
if (!xfs_sb_version_hasparent(&mp->m_sb))
return;

/* rename can add/remove/modify 4 parent attributes */
resp->tr_rename.tr_logres += 4 * max(resp->tr_attrsetm.tr_logres,
resp->tr_attrrm.tr_logres);
resp->tr_rename.tr_logcount += 4 * max(resp->tr_attrsetm.tr_logcount,
resp->tr_attrrm.tr_logcount);

/* create will add 1 parent attribute */
resp->tr_create.tr_logres += resp->tr_attrsetm.tr_logres;
resp->tr_create.tr_logcount += resp->tr_attrsetm.tr_logcount;

/* mkdir will add 1 parent attribute */
resp->tr_mkdir.tr_logres += resp->tr_attrsetm.tr_logres;
resp->tr_mkdir.tr_logcount += resp->tr_attrsetm.tr_logcount;

/* link will add 1 parent attribute */
resp->tr_link.tr_logres += resp->tr_attrsetm.tr_logres;
resp->tr_link.tr_logcount += resp->tr_attrsetm.tr_logcount;

/* symlink will add 1 parent attribute */
resp->tr_symlink.tr_logres += resp->tr_attrsetm.tr_logres;
resp->tr_symlink.tr_logcount += resp->tr_attrsetm.tr_logcount;

/* remove will remove 1 parent attribute */
resp->tr_remove.tr_logres += resp->tr_attrrm.tr_logres;
resp->tr_remove.tr_logcount += resp->tr_attrrm.tr_logcount;
}

void
xfs_trans_resv_calc(
struct xfs_mount *mp,
struct xfs_trans_resv *resp)
{
/*
* The following transactions are logged in physical format and
* require a permanent reservation on space.
*/
resp->tr_write.tr_logres = xfs_calc_write_reservation(mp);
if (xfs_sb_version_hasreflink(&mp->m_sb))
resp->tr_write.tr_logcount = XFS_WRITE_LOG_COUNT_REFLINK;
else
resp->tr_write.tr_logcount = XFS_WRITE_LOG_COUNT;
resp->tr_write.tr_logflags |= XFS_TRANS_PERM_LOG_RES;

resp->tr_itruncate.tr_logres = xfs_calc_itruncate_reservation(mp);
if (xfs_sb_version_hasreflink(&mp->m_sb))
resp->tr_itruncate.tr_logcount =
XFS_ITRUNCATE_LOG_COUNT_REFLINK;
else
resp->tr_itruncate.tr_logcount = XFS_ITRUNCATE_LOG_COUNT;
resp->tr_itruncate.tr_logflags |= XFS_TRANS_PERM_LOG_RES;

resp->tr_create_tmpfile.tr_logres =
xfs_calc_create_tmpfile_reservation(mp);
resp->tr_create_tmpfile.tr_logcount = XFS_CREATE_TMPFILE_LOG_COUNT;
resp->tr_create_tmpfile.tr_logflags |= XFS_TRANS_PERM_LOG_RES;

resp->tr_mkdir.tr_logres = xfs_calc_mkdir_reservation(mp);
resp->tr_mkdir.tr_logcount = XFS_MKDIR_LOG_COUNT;
resp->tr_mkdir.tr_logflags |= XFS_TRANS_PERM_LOG_RES;

resp->tr_ifree.tr_logres = xfs_calc_ifree_reservation(mp);
resp->tr_ifree.tr_logcount = XFS_INACTIVE_LOG_COUNT;
resp->tr_ifree.tr_logflags |= XFS_TRANS_PERM_LOG_RES;
@@ -916,6 +979,8 @@ xfs_trans_resv_calc(
resp->tr_qm_dqalloc.tr_logcount = XFS_WRITE_LOG_COUNT;
resp->tr_qm_dqalloc.tr_logflags |= XFS_TRANS_PERM_LOG_RES;

xfs_calc_namespace_reservations(mp, resp);

/*
* The following transactions are logged in logical format with
* a default log count.
@@ -93,5 +93,6 @@ struct xfs_trans_resv {

void xfs_trans_resv_calc(struct xfs_mount *mp, struct xfs_trans_resv *resp);
uint xfs_allocfree_log_count(struct xfs_mount *mp, uint num_ops);
void xfs_calc_parent_ptr_reservations(struct xfs_mount *mp);

#endif /* __XFS_TRANS_RESV_H__ */

0 comments on commit 4801b66

Please sign in to comment.