xfs_trans_inode.c 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Copyright (c) 2000,2005 Silicon Graphics, Inc.
  4. * All Rights Reserved.
  5. */
  6. #include "xfs.h"
  7. #include "xfs_fs.h"
  8. #include "xfs_shared.h"
  9. #include "xfs_format.h"
  10. #include "xfs_log_format.h"
  11. #include "xfs_trans_resv.h"
  12. #include "xfs_mount.h"
  13. #include "xfs_inode.h"
  14. #include "xfs_trans.h"
  15. #include "xfs_trans_priv.h"
  16. #include "xfs_inode_item.h"
  17. #include <linux/iversion.h>
  18. /*
  19. * Add a locked inode to the transaction.
  20. *
  21. * The inode must be locked, and it cannot be associated with any transaction.
  22. * If lock_flags is non-zero the inode will be unlocked on transaction commit.
  23. */
  24. void
  25. xfs_trans_ijoin(
  26. struct xfs_trans *tp,
  27. struct xfs_inode *ip,
  28. uint lock_flags)
  29. {
  30. struct xfs_inode_log_item *iip;
  31. xfs_assert_ilocked(ip, XFS_ILOCK_EXCL);
  32. if (ip->i_itemp == NULL)
  33. xfs_inode_item_init(ip, ip->i_mount);
  34. iip = ip->i_itemp;
  35. ASSERT(iip->ili_lock_flags == 0);
  36. iip->ili_lock_flags = lock_flags;
  37. ASSERT(!xfs_iflags_test(ip, XFS_ISTALE));
  38. /* Reset the per-tx dirty context and add the item to the tx. */
  39. iip->ili_dirty_flags = 0;
  40. xfs_trans_add_item(tp, &iip->ili_item);
  41. }
  42. /*
  43. * Transactional inode timestamp update. Requires the inode to be locked and
  44. * joined to the transaction supplied. Relies on the transaction subsystem to
  45. * track dirty state and update/writeback the inode accordingly.
  46. */
  47. void
  48. xfs_trans_ichgtime(
  49. struct xfs_trans *tp,
  50. struct xfs_inode *ip,
  51. int flags)
  52. {
  53. struct inode *inode = VFS_I(ip);
  54. struct timespec64 tv;
  55. ASSERT(tp);
  56. xfs_assert_ilocked(ip, XFS_ILOCK_EXCL);
  57. tv = current_time(inode);
  58. if (flags & XFS_ICHGTIME_MOD)
  59. inode_set_mtime_to_ts(inode, tv);
  60. if (flags & XFS_ICHGTIME_CHG)
  61. inode_set_ctime_to_ts(inode, tv);
  62. if (flags & XFS_ICHGTIME_ACCESS)
  63. inode_set_atime_to_ts(inode, tv);
  64. if (flags & XFS_ICHGTIME_CREATE)
  65. ip->i_crtime = tv;
  66. }
  67. /*
  68. * This is called to mark the fields indicated in fieldmask as needing to be
  69. * logged when the transaction is committed. The inode must already be
  70. * associated with the given transaction. All we do here is record where the
  71. * inode was dirtied and mark the transaction and inode log item dirty;
  72. * everything else is done in the ->precommit log item operation after the
  73. * changes in the transaction have been completed.
  74. */
  75. void
  76. xfs_trans_log_inode(
  77. struct xfs_trans *tp,
  78. struct xfs_inode *ip,
  79. uint flags)
  80. {
  81. struct xfs_inode_log_item *iip = ip->i_itemp;
  82. struct inode *inode = VFS_I(ip);
  83. ASSERT(iip);
  84. xfs_assert_ilocked(ip, XFS_ILOCK_EXCL);
  85. ASSERT(!xfs_iflags_test(ip, XFS_ISTALE));
  86. tp->t_flags |= XFS_TRANS_DIRTY;
  87. /*
  88. * First time we log the inode in a transaction, bump the inode change
  89. * counter if it is configured for this to occur. While we have the
  90. * inode locked exclusively for metadata modification, we can usually
  91. * avoid setting XFS_ILOG_CORE if no one has queried the value since
  92. * the last time it was incremented. If we have XFS_ILOG_CORE already
  93. * set however, then go ahead and bump the i_version counter
  94. * unconditionally.
  95. */
  96. if (!test_and_set_bit(XFS_LI_DIRTY, &iip->ili_item.li_flags)) {
  97. if (IS_I_VERSION(inode) &&
  98. inode_maybe_inc_iversion(inode, flags & XFS_ILOG_CORE))
  99. flags |= XFS_ILOG_IVERSION;
  100. }
  101. iip->ili_dirty_flags |= flags;
  102. }
  103. int
  104. xfs_trans_roll_inode(
  105. struct xfs_trans **tpp,
  106. struct xfs_inode *ip)
  107. {
  108. int error;
  109. xfs_trans_log_inode(*tpp, ip, XFS_ILOG_CORE);
  110. error = xfs_trans_roll(tpp);
  111. if (!error)
  112. xfs_trans_ijoin(*tpp, ip, 0);
  113. return error;
  114. }