Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v4.18 155 lines 4.3 kB view raw
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 "xfs_trace.h" 18 19#include <linux/iversion.h> 20 21/* 22 * Add a locked inode to the transaction. 23 * 24 * The inode must be locked, and it cannot be associated with any transaction. 25 * If lock_flags is non-zero the inode will be unlocked on transaction commit. 26 */ 27void 28xfs_trans_ijoin( 29 struct xfs_trans *tp, 30 struct xfs_inode *ip, 31 uint lock_flags) 32{ 33 xfs_inode_log_item_t *iip; 34 35 ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL)); 36 if (ip->i_itemp == NULL) 37 xfs_inode_item_init(ip, ip->i_mount); 38 iip = ip->i_itemp; 39 40 ASSERT(iip->ili_lock_flags == 0); 41 iip->ili_lock_flags = lock_flags; 42 43 /* 44 * Get a log_item_desc to point at the new item. 45 */ 46 xfs_trans_add_item(tp, &iip->ili_item); 47} 48 49/* 50 * Transactional inode timestamp update. Requires the inode to be locked and 51 * joined to the transaction supplied. Relies on the transaction subsystem to 52 * track dirty state and update/writeback the inode accordingly. 53 */ 54void 55xfs_trans_ichgtime( 56 struct xfs_trans *tp, 57 struct xfs_inode *ip, 58 int flags) 59{ 60 struct inode *inode = VFS_I(ip); 61 struct timespec64 tv; 62 63 ASSERT(tp); 64 ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL)); 65 66 tv = current_time(inode); 67 68 if (flags & XFS_ICHGTIME_MOD) 69 inode->i_mtime = tv; 70 if (flags & XFS_ICHGTIME_CHG) 71 inode->i_ctime = tv; 72} 73 74/* 75 * This is called to mark the fields indicated in fieldmask as needing 76 * to be logged when the transaction is committed. The inode must 77 * already be associated with the given transaction. 78 * 79 * The values for fieldmask are defined in xfs_inode_item.h. We always 80 * log all of the core inode if any of it has changed, and we always log 81 * all of the inline data/extents/b-tree root if any of them has changed. 82 */ 83void 84xfs_trans_log_inode( 85 xfs_trans_t *tp, 86 xfs_inode_t *ip, 87 uint flags) 88{ 89 struct inode *inode = VFS_I(ip); 90 91 ASSERT(ip->i_itemp != NULL); 92 ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL)); 93 94 /* 95 * Don't bother with i_lock for the I_DIRTY_TIME check here, as races 96 * don't matter - we either will need an extra transaction in 24 hours 97 * to log the timestamps, or will clear already cleared fields in the 98 * worst case. 99 */ 100 if (inode->i_state & (I_DIRTY_TIME | I_DIRTY_TIME_EXPIRED)) { 101 spin_lock(&inode->i_lock); 102 inode->i_state &= ~(I_DIRTY_TIME | I_DIRTY_TIME_EXPIRED); 103 spin_unlock(&inode->i_lock); 104 } 105 106 /* 107 * Record the specific change for fdatasync optimisation. This 108 * allows fdatasync to skip log forces for inodes that are only 109 * timestamp dirty. We do this before the change count so that 110 * the core being logged in this case does not impact on fdatasync 111 * behaviour. 112 */ 113 ip->i_itemp->ili_fsync_fields |= flags; 114 115 /* 116 * First time we log the inode in a transaction, bump the inode change 117 * counter if it is configured for this to occur. While we have the 118 * inode locked exclusively for metadata modification, we can usually 119 * avoid setting XFS_ILOG_CORE if no one has queried the value since 120 * the last time it was incremented. If we have XFS_ILOG_CORE already 121 * set however, then go ahead and bump the i_version counter 122 * unconditionally. 123 */ 124 if (!test_and_set_bit(XFS_LI_DIRTY, &ip->i_itemp->ili_item.li_flags) && 125 IS_I_VERSION(VFS_I(ip))) { 126 if (inode_maybe_inc_iversion(VFS_I(ip), flags & XFS_ILOG_CORE)) 127 flags |= XFS_ILOG_CORE; 128 } 129 130 tp->t_flags |= XFS_TRANS_DIRTY; 131 132 /* 133 * Always OR in the bits from the ili_last_fields field. 134 * This is to coordinate with the xfs_iflush() and xfs_iflush_done() 135 * routines in the eventual clearing of the ili_fields bits. 136 * See the big comment in xfs_iflush() for an explanation of 137 * this coordination mechanism. 138 */ 139 flags |= ip->i_itemp->ili_last_fields; 140 ip->i_itemp->ili_fields |= flags; 141} 142 143int 144xfs_trans_roll_inode( 145 struct xfs_trans **tpp, 146 struct xfs_inode *ip) 147{ 148 int error; 149 150 xfs_trans_log_inode(*tpp, ip, XFS_ILOG_CORE); 151 error = xfs_trans_roll(tpp); 152 if (!error) 153 xfs_trans_ijoin(*tpp, ip, 0); 154 return error; 155}