131 lines · c
1// SPDX-License-Identifier: GPL-2.02/*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 18#include <linux/iversion.h>19 20/*21 * Add a locked inode to the transaction.22 *23 * The inode must be locked, and it cannot be associated with any transaction.24 * If lock_flags is non-zero the inode will be unlocked on transaction commit.25 */26void27xfs_trans_ijoin(28 struct xfs_trans *tp,29 struct xfs_inode *ip,30 uint lock_flags)31{32 struct xfs_inode_log_item *iip;33 34 xfs_assert_ilocked(ip, XFS_ILOCK_EXCL);35 if (ip->i_itemp == NULL)36 xfs_inode_item_init(ip, ip->i_mount);37 iip = ip->i_itemp;38 39 ASSERT(iip->ili_lock_flags == 0);40 iip->ili_lock_flags = lock_flags;41 ASSERT(!xfs_iflags_test(ip, XFS_ISTALE));42 43 /* Reset the per-tx dirty context and add the item to the tx. */44 iip->ili_dirty_flags = 0;45 xfs_trans_add_item(tp, &iip->ili_item);46}47 48/*49 * Transactional inode timestamp update. Requires the inode to be locked and50 * joined to the transaction supplied. Relies on the transaction subsystem to51 * track dirty state and update/writeback the inode accordingly.52 */53void54xfs_trans_ichgtime(55 struct xfs_trans *tp,56 struct xfs_inode *ip,57 int flags)58{59 struct inode *inode = VFS_I(ip);60 struct timespec64 tv;61 62 ASSERT(tp);63 xfs_assert_ilocked(ip, XFS_ILOCK_EXCL);64 65 tv = current_time(inode);66 67 if (flags & XFS_ICHGTIME_MOD)68 inode_set_mtime_to_ts(inode, tv);69 if (flags & XFS_ICHGTIME_CHG)70 inode_set_ctime_to_ts(inode, tv);71 if (flags & XFS_ICHGTIME_ACCESS)72 inode_set_atime_to_ts(inode, tv);73 if (flags & XFS_ICHGTIME_CREATE)74 ip->i_crtime = tv;75}76 77/*78 * This is called to mark the fields indicated in fieldmask as needing to be79 * logged when the transaction is committed. The inode must already be80 * associated with the given transaction. All we do here is record where the81 * inode was dirtied and mark the transaction and inode log item dirty;82 * everything else is done in the ->precommit log item operation after the83 * changes in the transaction have been completed.84 */85void86xfs_trans_log_inode(87 struct xfs_trans *tp,88 struct xfs_inode *ip,89 uint flags)90{91 struct xfs_inode_log_item *iip = ip->i_itemp;92 struct inode *inode = VFS_I(ip);93 94 ASSERT(iip);95 xfs_assert_ilocked(ip, XFS_ILOCK_EXCL);96 ASSERT(!xfs_iflags_test(ip, XFS_ISTALE));97 98 tp->t_flags |= XFS_TRANS_DIRTY;99 100 /*101 * First time we log the inode in a transaction, bump the inode change102 * counter if it is configured for this to occur. While we have the103 * inode locked exclusively for metadata modification, we can usually104 * avoid setting XFS_ILOG_CORE if no one has queried the value since105 * the last time it was incremented. If we have XFS_ILOG_CORE already106 * set however, then go ahead and bump the i_version counter107 * unconditionally.108 */109 if (!test_and_set_bit(XFS_LI_DIRTY, &iip->ili_item.li_flags)) {110 if (IS_I_VERSION(inode) &&111 inode_maybe_inc_iversion(inode, flags & XFS_ILOG_CORE))112 flags |= XFS_ILOG_IVERSION;113 }114 115 iip->ili_dirty_flags |= flags;116}117 118int119xfs_trans_roll_inode(120 struct xfs_trans **tpp,121 struct xfs_inode *ip)122{123 int error;124 125 xfs_trans_log_inode(*tpp, ip, XFS_ILOG_CORE);126 error = xfs_trans_roll(tpp);127 if (!error)128 xfs_trans_ijoin(*tpp, ip, 0);129 return error;130}131