xref: /linux/fs/xfs/xfs_trans.c (revision 501ab32387533924b211cacff36d19296414ec0b)
11da177e4SLinus Torvalds /*
27b718769SNathan Scott  * Copyright (c) 2000-2003,2005 Silicon Graphics, Inc.
3e98c414fSChristoph Hellwig  * Copyright (C) 2010 Red Hat, Inc.
47b718769SNathan Scott  * All Rights Reserved.
51da177e4SLinus Torvalds  *
67b718769SNathan Scott  * This program is free software; you can redistribute it and/or
77b718769SNathan Scott  * modify it under the terms of the GNU General Public License as
81da177e4SLinus Torvalds  * published by the Free Software Foundation.
91da177e4SLinus Torvalds  *
107b718769SNathan Scott  * This program is distributed in the hope that it would be useful,
117b718769SNathan Scott  * but WITHOUT ANY WARRANTY; without even the implied warranty of
127b718769SNathan Scott  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
137b718769SNathan Scott  * GNU General Public License for more details.
141da177e4SLinus Torvalds  *
157b718769SNathan Scott  * You should have received a copy of the GNU General Public License
167b718769SNathan Scott  * along with this program; if not, write the Free Software Foundation,
177b718769SNathan Scott  * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
181da177e4SLinus Torvalds  */
191da177e4SLinus Torvalds #include "xfs.h"
20a844f451SNathan Scott #include "xfs_fs.h"
2170a9883cSDave Chinner #include "xfs_shared.h"
22239880efSDave Chinner #include "xfs_format.h"
23239880efSDave Chinner #include "xfs_log_format.h"
24239880efSDave Chinner #include "xfs_trans_resv.h"
251da177e4SLinus Torvalds #include "xfs_mount.h"
26a844f451SNathan Scott #include "xfs_inode.h"
27efc27b52SDave Chinner #include "xfs_extent_busy.h"
281da177e4SLinus Torvalds #include "xfs_quota.h"
29239880efSDave Chinner #include "xfs_trans.h"
30a844f451SNathan Scott #include "xfs_trans_priv.h"
31239880efSDave Chinner #include "xfs_log.h"
32ed3b4d6cSDave Chinner #include "xfs_trace.h"
33a4fbe6abSDave Chinner #include "xfs_error.h"
341da177e4SLinus Torvalds 
351da177e4SLinus Torvalds kmem_zone_t	*xfs_trans_zone;
36e98c414fSChristoph Hellwig kmem_zone_t	*xfs_log_item_desc_zone;
371da177e4SLinus Torvalds 
384f3b5783SJeff Liu /*
391da177e4SLinus Torvalds  * Initialize the precomputed transaction reservation values
401da177e4SLinus Torvalds  * in the mount structure.
411da177e4SLinus Torvalds  */
421da177e4SLinus Torvalds void
431da177e4SLinus Torvalds xfs_trans_init(
44025101dcSChristoph Hellwig 	struct xfs_mount	*mp)
451da177e4SLinus Torvalds {
463d3c8b52SJie Liu 	xfs_trans_resv_calc(mp, M_RES(mp));
471da177e4SLinus Torvalds }
481da177e4SLinus Torvalds 
491da177e4SLinus Torvalds /*
501da177e4SLinus Torvalds  * This routine is called to allocate a transaction structure.
511da177e4SLinus Torvalds  * The type parameter indicates the type of the transaction.  These
521da177e4SLinus Torvalds  * are enumerated in xfs_trans.h.
53b2ce3974SAlex Elder  *
54b2ce3974SAlex Elder  * Dynamically allocate the transaction structure from the transaction
55b2ce3974SAlex Elder  * zone, initialize it, and return it to the caller.
561da177e4SLinus Torvalds  */
57b2ce3974SAlex Elder xfs_trans_t *
58b2ce3974SAlex Elder xfs_trans_alloc(
59b2ce3974SAlex Elder 	xfs_mount_t	*mp,
60b2ce3974SAlex Elder 	uint		type)
611da177e4SLinus Torvalds {
62d9457dc0SJan Kara 	xfs_trans_t     *tp;
63d9457dc0SJan Kara 
64d9457dc0SJan Kara 	sb_start_intwrite(mp->m_super);
65d9457dc0SJan Kara 	tp = _xfs_trans_alloc(mp, type, KM_SLEEP);
66d9457dc0SJan Kara 	tp->t_flags |= XFS_TRANS_FREEZE_PROT;
67d9457dc0SJan Kara 	return tp;
68b2ce3974SAlex Elder }
69b2ce3974SAlex Elder 
70b2ce3974SAlex Elder xfs_trans_t *
71b2ce3974SAlex Elder _xfs_trans_alloc(
72b2ce3974SAlex Elder 	xfs_mount_t	*mp,
73b2ce3974SAlex Elder 	uint		type,
7477ba7877SAl Viro 	xfs_km_flags_t	memflags)
75b2ce3974SAlex Elder {
76b2ce3974SAlex Elder 	xfs_trans_t	*tp;
771da177e4SLinus Torvalds 
78d9457dc0SJan Kara 	WARN_ON(mp->m_super->s_writers.frozen == SB_FREEZE_COMPLETE);
7934327e13SNathan Scott 	atomic_inc(&mp->m_active_trans);
801da177e4SLinus Torvalds 
8180641dc6SChristoph Hellwig 	tp = kmem_zone_zalloc(xfs_trans_zone, memflags);
822a3c0accSDave Chinner 	tp->t_magic = XFS_TRANS_HEADER_MAGIC;
831da177e4SLinus Torvalds 	tp->t_type = type;
841da177e4SLinus Torvalds 	tp->t_mountp = mp;
85e98c414fSChristoph Hellwig 	INIT_LIST_HEAD(&tp->t_items);
86ed3b4d6cSDave Chinner 	INIT_LIST_HEAD(&tp->t_busy);
8734327e13SNathan Scott 	return tp;
881da177e4SLinus Torvalds }
891da177e4SLinus Torvalds 
901da177e4SLinus Torvalds /*
91b1c1b5b6SDave Chinner  * Free the transaction structure.  If there is more clean up
92b1c1b5b6SDave Chinner  * to do when the structure is freed, add it here.
93b1c1b5b6SDave Chinner  */
94b1c1b5b6SDave Chinner STATIC void
95b1c1b5b6SDave Chinner xfs_trans_free(
96ed3b4d6cSDave Chinner 	struct xfs_trans	*tp)
97b1c1b5b6SDave Chinner {
984ecbfe63SDave Chinner 	xfs_extent_busy_sort(&tp->t_busy);
994ecbfe63SDave Chinner 	xfs_extent_busy_clear(tp->t_mountp, &tp->t_busy, false);
100ed3b4d6cSDave Chinner 
101b1c1b5b6SDave Chinner 	atomic_dec(&tp->t_mountp->m_active_trans);
102d9457dc0SJan Kara 	if (tp->t_flags & XFS_TRANS_FREEZE_PROT)
103d9457dc0SJan Kara 		sb_end_intwrite(tp->t_mountp->m_super);
104b1c1b5b6SDave Chinner 	xfs_trans_free_dqinfo(tp);
105b1c1b5b6SDave Chinner 	kmem_zone_free(xfs_trans_zone, tp);
106b1c1b5b6SDave Chinner }
107b1c1b5b6SDave Chinner 
108b1c1b5b6SDave Chinner /*
1091da177e4SLinus Torvalds  * This is called to create a new transaction which will share the
1101da177e4SLinus Torvalds  * permanent log reservation of the given transaction.  The remaining
1111da177e4SLinus Torvalds  * unused block and rt extent reservations are also inherited.  This
1121da177e4SLinus Torvalds  * implies that the original transaction is no longer allowed to allocate
1131da177e4SLinus Torvalds  * blocks.  Locks and log items, however, are no inherited.  They must
1141da177e4SLinus Torvalds  * be added to the new transaction explicitly.
1151da177e4SLinus Torvalds  */
1161da177e4SLinus Torvalds xfs_trans_t *
1171da177e4SLinus Torvalds xfs_trans_dup(
1181da177e4SLinus Torvalds 	xfs_trans_t	*tp)
1191da177e4SLinus Torvalds {
1201da177e4SLinus Torvalds 	xfs_trans_t	*ntp;
1211da177e4SLinus Torvalds 
1221da177e4SLinus Torvalds 	ntp = kmem_zone_zalloc(xfs_trans_zone, KM_SLEEP);
1231da177e4SLinus Torvalds 
1241da177e4SLinus Torvalds 	/*
1251da177e4SLinus Torvalds 	 * Initialize the new transaction structure.
1261da177e4SLinus Torvalds 	 */
1272a3c0accSDave Chinner 	ntp->t_magic = XFS_TRANS_HEADER_MAGIC;
1281da177e4SLinus Torvalds 	ntp->t_type = tp->t_type;
1291da177e4SLinus Torvalds 	ntp->t_mountp = tp->t_mountp;
130e98c414fSChristoph Hellwig 	INIT_LIST_HEAD(&ntp->t_items);
131ed3b4d6cSDave Chinner 	INIT_LIST_HEAD(&ntp->t_busy);
1321da177e4SLinus Torvalds 
1331da177e4SLinus Torvalds 	ASSERT(tp->t_flags & XFS_TRANS_PERM_LOG_RES);
1341da177e4SLinus Torvalds 	ASSERT(tp->t_ticket != NULL);
135cfcbbbd0SNathan Scott 
136d9457dc0SJan Kara 	ntp->t_flags = XFS_TRANS_PERM_LOG_RES |
137d9457dc0SJan Kara 		       (tp->t_flags & XFS_TRANS_RESERVE) |
138d9457dc0SJan Kara 		       (tp->t_flags & XFS_TRANS_FREEZE_PROT);
139d9457dc0SJan Kara 	/* We gave our writer reference to the new transaction */
140d9457dc0SJan Kara 	tp->t_flags &= ~XFS_TRANS_FREEZE_PROT;
141cc09c0dcSDave Chinner 	ntp->t_ticket = xfs_log_ticket_get(tp->t_ticket);
1421da177e4SLinus Torvalds 	ntp->t_blk_res = tp->t_blk_res - tp->t_blk_res_used;
1431da177e4SLinus Torvalds 	tp->t_blk_res = tp->t_blk_res_used;
1441da177e4SLinus Torvalds 	ntp->t_rtx_res = tp->t_rtx_res - tp->t_rtx_res_used;
1451da177e4SLinus Torvalds 	tp->t_rtx_res = tp->t_rtx_res_used;
14659c1b082SNathan Scott 	ntp->t_pflags = tp->t_pflags;
1471da177e4SLinus Torvalds 
1487d095257SChristoph Hellwig 	xfs_trans_dup_dqinfo(tp, ntp);
1491da177e4SLinus Torvalds 
1501da177e4SLinus Torvalds 	atomic_inc(&tp->t_mountp->m_active_trans);
1511da177e4SLinus Torvalds 	return ntp;
1521da177e4SLinus Torvalds }
1531da177e4SLinus Torvalds 
1541da177e4SLinus Torvalds /*
1551da177e4SLinus Torvalds  * This is called to reserve free disk blocks and log space for the
1561da177e4SLinus Torvalds  * given transaction.  This must be done before allocating any resources
1571da177e4SLinus Torvalds  * within the transaction.
1581da177e4SLinus Torvalds  *
1591da177e4SLinus Torvalds  * This will return ENOSPC if there are not enough blocks available.
1601da177e4SLinus Torvalds  * It will sleep waiting for available log space.
1611da177e4SLinus Torvalds  * The only valid value for the flags parameter is XFS_RES_LOG_PERM, which
1621da177e4SLinus Torvalds  * is used by long running transactions.  If any one of the reservations
1631da177e4SLinus Torvalds  * fails then they will all be backed out.
1641da177e4SLinus Torvalds  *
1651da177e4SLinus Torvalds  * This does not do quota reservations. That typically is done by the
1661da177e4SLinus Torvalds  * caller afterwards.
1671da177e4SLinus Torvalds  */
1681da177e4SLinus Torvalds int
1691da177e4SLinus Torvalds xfs_trans_reserve(
1703d3c8b52SJie Liu 	struct xfs_trans	*tp,
1713d3c8b52SJie Liu 	struct xfs_trans_res	*resp,
1721da177e4SLinus Torvalds 	uint			blocks,
1733d3c8b52SJie Liu 	uint			rtextents)
1741da177e4SLinus Torvalds {
17559c1b082SNathan Scott 	int		error = 0;
17659c1b082SNathan Scott 	int		rsvd = (tp->t_flags & XFS_TRANS_RESERVE) != 0;
1771da177e4SLinus Torvalds 
1781da177e4SLinus Torvalds 	/* Mark this thread as being in a transaction */
17959c1b082SNathan Scott 	current_set_flags_nested(&tp->t_pflags, PF_FSTRANS);
1801da177e4SLinus Torvalds 
1811da177e4SLinus Torvalds 	/*
1821da177e4SLinus Torvalds 	 * Attempt to reserve the needed disk blocks by decrementing
1831da177e4SLinus Torvalds 	 * the number needed from the number available.  This will
1841da177e4SLinus Torvalds 	 * fail if the count would go below zero.
1851da177e4SLinus Torvalds 	 */
1861da177e4SLinus Torvalds 	if (blocks > 0) {
18796540c78SChristoph Hellwig 		error = xfs_icsb_modify_counters(tp->t_mountp, XFS_SBS_FDBLOCKS,
18820f4ebf2SDavid Chinner 					  -((int64_t)blocks), rsvd);
1891da177e4SLinus Torvalds 		if (error != 0) {
19059c1b082SNathan Scott 			current_restore_flags_nested(&tp->t_pflags, PF_FSTRANS);
1912451337dSDave Chinner 			return -ENOSPC;
1921da177e4SLinus Torvalds 		}
1931da177e4SLinus Torvalds 		tp->t_blk_res += blocks;
1941da177e4SLinus Torvalds 	}
1951da177e4SLinus Torvalds 
1961da177e4SLinus Torvalds 	/*
1971da177e4SLinus Torvalds 	 * Reserve the log space needed for this transaction.
1981da177e4SLinus Torvalds 	 */
1993d3c8b52SJie Liu 	if (resp->tr_logres > 0) {
2009006fb91SChristoph Hellwig 		bool	permanent = false;
2019006fb91SChristoph Hellwig 
2023d3c8b52SJie Liu 		ASSERT(tp->t_log_res == 0 ||
2033d3c8b52SJie Liu 		       tp->t_log_res == resp->tr_logres);
2043d3c8b52SJie Liu 		ASSERT(tp->t_log_count == 0 ||
2053d3c8b52SJie Liu 		       tp->t_log_count == resp->tr_logcount);
2069006fb91SChristoph Hellwig 
2073d3c8b52SJie Liu 		if (resp->tr_logflags & XFS_TRANS_PERM_LOG_RES) {
2081da177e4SLinus Torvalds 			tp->t_flags |= XFS_TRANS_PERM_LOG_RES;
2099006fb91SChristoph Hellwig 			permanent = true;
2101da177e4SLinus Torvalds 		} else {
2111da177e4SLinus Torvalds 			ASSERT(tp->t_ticket == NULL);
2121da177e4SLinus Torvalds 			ASSERT(!(tp->t_flags & XFS_TRANS_PERM_LOG_RES));
2131da177e4SLinus Torvalds 		}
2141da177e4SLinus Torvalds 
2159006fb91SChristoph Hellwig 		if (tp->t_ticket != NULL) {
2163d3c8b52SJie Liu 			ASSERT(resp->tr_logflags & XFS_TRANS_PERM_LOG_RES);
2179006fb91SChristoph Hellwig 			error = xfs_log_regrant(tp->t_mountp, tp->t_ticket);
2189006fb91SChristoph Hellwig 		} else {
2193d3c8b52SJie Liu 			error = xfs_log_reserve(tp->t_mountp,
2203d3c8b52SJie Liu 						resp->tr_logres,
2213d3c8b52SJie Liu 						resp->tr_logcount,
2223d3c8b52SJie Liu 						&tp->t_ticket, XFS_TRANSACTION,
2233d3c8b52SJie Liu 						permanent, tp->t_type);
2241da177e4SLinus Torvalds 		}
2259006fb91SChristoph Hellwig 
2269006fb91SChristoph Hellwig 		if (error)
2279006fb91SChristoph Hellwig 			goto undo_blocks;
2289006fb91SChristoph Hellwig 
2293d3c8b52SJie Liu 		tp->t_log_res = resp->tr_logres;
2303d3c8b52SJie Liu 		tp->t_log_count = resp->tr_logcount;
2311da177e4SLinus Torvalds 	}
2321da177e4SLinus Torvalds 
2331da177e4SLinus Torvalds 	/*
2341da177e4SLinus Torvalds 	 * Attempt to reserve the needed realtime extents by decrementing
2351da177e4SLinus Torvalds 	 * the number needed from the number available.  This will
2361da177e4SLinus Torvalds 	 * fail if the count would go below zero.
2371da177e4SLinus Torvalds 	 */
2381da177e4SLinus Torvalds 	if (rtextents > 0) {
2391da177e4SLinus Torvalds 		error = xfs_mod_incore_sb(tp->t_mountp, XFS_SBS_FREXTENTS,
24020f4ebf2SDavid Chinner 					  -((int64_t)rtextents), rsvd);
2411da177e4SLinus Torvalds 		if (error) {
2422451337dSDave Chinner 			error = -ENOSPC;
2431da177e4SLinus Torvalds 			goto undo_log;
2441da177e4SLinus Torvalds 		}
2451da177e4SLinus Torvalds 		tp->t_rtx_res += rtextents;
2461da177e4SLinus Torvalds 	}
2471da177e4SLinus Torvalds 
2481da177e4SLinus Torvalds 	return 0;
2491da177e4SLinus Torvalds 
2501da177e4SLinus Torvalds 	/*
2511da177e4SLinus Torvalds 	 * Error cases jump to one of these labels to undo any
2521da177e4SLinus Torvalds 	 * reservations which have already been performed.
2531da177e4SLinus Torvalds 	 */
2541da177e4SLinus Torvalds undo_log:
2553d3c8b52SJie Liu 	if (resp->tr_logres > 0) {
2569006fb91SChristoph Hellwig 		int		log_flags;
2579006fb91SChristoph Hellwig 
2583d3c8b52SJie Liu 		if (resp->tr_logflags & XFS_TRANS_PERM_LOG_RES) {
2591da177e4SLinus Torvalds 			log_flags = XFS_LOG_REL_PERM_RESERV;
2601da177e4SLinus Torvalds 		} else {
2611da177e4SLinus Torvalds 			log_flags = 0;
2621da177e4SLinus Torvalds 		}
2631da177e4SLinus Torvalds 		xfs_log_done(tp->t_mountp, tp->t_ticket, NULL, log_flags);
2641da177e4SLinus Torvalds 		tp->t_ticket = NULL;
2651da177e4SLinus Torvalds 		tp->t_log_res = 0;
2661da177e4SLinus Torvalds 		tp->t_flags &= ~XFS_TRANS_PERM_LOG_RES;
2671da177e4SLinus Torvalds 	}
2681da177e4SLinus Torvalds 
2691da177e4SLinus Torvalds undo_blocks:
2701da177e4SLinus Torvalds 	if (blocks > 0) {
27196540c78SChristoph Hellwig 		xfs_icsb_modify_counters(tp->t_mountp, XFS_SBS_FDBLOCKS,
27220f4ebf2SDavid Chinner 					 (int64_t)blocks, rsvd);
2731da177e4SLinus Torvalds 		tp->t_blk_res = 0;
2741da177e4SLinus Torvalds 	}
2751da177e4SLinus Torvalds 
27659c1b082SNathan Scott 	current_restore_flags_nested(&tp->t_pflags, PF_FSTRANS);
2771da177e4SLinus Torvalds 
27859c1b082SNathan Scott 	return error;
2791da177e4SLinus Torvalds }
2801da177e4SLinus Torvalds 
2811da177e4SLinus Torvalds /*
2821da177e4SLinus Torvalds  * Record the indicated change to the given field for application
2831da177e4SLinus Torvalds  * to the file system's superblock when the transaction commits.
2841da177e4SLinus Torvalds  * For now, just store the change in the transaction structure.
2851da177e4SLinus Torvalds  *
2861da177e4SLinus Torvalds  * Mark the transaction structure to indicate that the superblock
2871da177e4SLinus Torvalds  * needs to be updated before committing.
28892821e2bSDavid Chinner  *
28992821e2bSDavid Chinner  * Because we may not be keeping track of allocated/free inodes and
29092821e2bSDavid Chinner  * used filesystem blocks in the superblock, we do not mark the
29192821e2bSDavid Chinner  * superblock dirty in this transaction if we modify these fields.
29292821e2bSDavid Chinner  * We still need to update the transaction deltas so that they get
29392821e2bSDavid Chinner  * applied to the incore superblock, but we don't want them to
29492821e2bSDavid Chinner  * cause the superblock to get locked and logged if these are the
29592821e2bSDavid Chinner  * only fields in the superblock that the transaction modifies.
2961da177e4SLinus Torvalds  */
2971da177e4SLinus Torvalds void
2981da177e4SLinus Torvalds xfs_trans_mod_sb(
2991da177e4SLinus Torvalds 	xfs_trans_t	*tp,
3001da177e4SLinus Torvalds 	uint		field,
30120f4ebf2SDavid Chinner 	int64_t		delta)
3021da177e4SLinus Torvalds {
30392821e2bSDavid Chinner 	uint32_t	flags = (XFS_TRANS_DIRTY|XFS_TRANS_SB_DIRTY);
30492821e2bSDavid Chinner 	xfs_mount_t	*mp = tp->t_mountp;
3051da177e4SLinus Torvalds 
3061da177e4SLinus Torvalds 	switch (field) {
3071da177e4SLinus Torvalds 	case XFS_TRANS_SB_ICOUNT:
3081da177e4SLinus Torvalds 		tp->t_icount_delta += delta;
30992821e2bSDavid Chinner 		if (xfs_sb_version_haslazysbcount(&mp->m_sb))
31092821e2bSDavid Chinner 			flags &= ~XFS_TRANS_SB_DIRTY;
3111da177e4SLinus Torvalds 		break;
3121da177e4SLinus Torvalds 	case XFS_TRANS_SB_IFREE:
3131da177e4SLinus Torvalds 		tp->t_ifree_delta += delta;
31492821e2bSDavid Chinner 		if (xfs_sb_version_haslazysbcount(&mp->m_sb))
31592821e2bSDavid Chinner 			flags &= ~XFS_TRANS_SB_DIRTY;
3161da177e4SLinus Torvalds 		break;
3171da177e4SLinus Torvalds 	case XFS_TRANS_SB_FDBLOCKS:
3181da177e4SLinus Torvalds 		/*
3191da177e4SLinus Torvalds 		 * Track the number of blocks allocated in the
3201da177e4SLinus Torvalds 		 * transaction.  Make sure it does not exceed the
3211da177e4SLinus Torvalds 		 * number reserved.
3221da177e4SLinus Torvalds 		 */
3231da177e4SLinus Torvalds 		if (delta < 0) {
3241da177e4SLinus Torvalds 			tp->t_blk_res_used += (uint)-delta;
3251da177e4SLinus Torvalds 			ASSERT(tp->t_blk_res_used <= tp->t_blk_res);
3261da177e4SLinus Torvalds 		}
3271da177e4SLinus Torvalds 		tp->t_fdblocks_delta += delta;
32892821e2bSDavid Chinner 		if (xfs_sb_version_haslazysbcount(&mp->m_sb))
32992821e2bSDavid Chinner 			flags &= ~XFS_TRANS_SB_DIRTY;
3301da177e4SLinus Torvalds 		break;
3311da177e4SLinus Torvalds 	case XFS_TRANS_SB_RES_FDBLOCKS:
3321da177e4SLinus Torvalds 		/*
3331da177e4SLinus Torvalds 		 * The allocation has already been applied to the
3341da177e4SLinus Torvalds 		 * in-core superblock's counter.  This should only
3351da177e4SLinus Torvalds 		 * be applied to the on-disk superblock.
3361da177e4SLinus Torvalds 		 */
3371da177e4SLinus Torvalds 		ASSERT(delta < 0);
3381da177e4SLinus Torvalds 		tp->t_res_fdblocks_delta += delta;
33992821e2bSDavid Chinner 		if (xfs_sb_version_haslazysbcount(&mp->m_sb))
34092821e2bSDavid Chinner 			flags &= ~XFS_TRANS_SB_DIRTY;
3411da177e4SLinus Torvalds 		break;
3421da177e4SLinus Torvalds 	case XFS_TRANS_SB_FREXTENTS:
3431da177e4SLinus Torvalds 		/*
3441da177e4SLinus Torvalds 		 * Track the number of blocks allocated in the
3451da177e4SLinus Torvalds 		 * transaction.  Make sure it does not exceed the
3461da177e4SLinus Torvalds 		 * number reserved.
3471da177e4SLinus Torvalds 		 */
3481da177e4SLinus Torvalds 		if (delta < 0) {
3491da177e4SLinus Torvalds 			tp->t_rtx_res_used += (uint)-delta;
3501da177e4SLinus Torvalds 			ASSERT(tp->t_rtx_res_used <= tp->t_rtx_res);
3511da177e4SLinus Torvalds 		}
3521da177e4SLinus Torvalds 		tp->t_frextents_delta += delta;
3531da177e4SLinus Torvalds 		break;
3541da177e4SLinus Torvalds 	case XFS_TRANS_SB_RES_FREXTENTS:
3551da177e4SLinus Torvalds 		/*
3561da177e4SLinus Torvalds 		 * The allocation has already been applied to the
357c41564b5SNathan Scott 		 * in-core superblock's counter.  This should only
3581da177e4SLinus Torvalds 		 * be applied to the on-disk superblock.
3591da177e4SLinus Torvalds 		 */
3601da177e4SLinus Torvalds 		ASSERT(delta < 0);
3611da177e4SLinus Torvalds 		tp->t_res_frextents_delta += delta;
3621da177e4SLinus Torvalds 		break;
3631da177e4SLinus Torvalds 	case XFS_TRANS_SB_DBLOCKS:
3641da177e4SLinus Torvalds 		ASSERT(delta > 0);
3651da177e4SLinus Torvalds 		tp->t_dblocks_delta += delta;
3661da177e4SLinus Torvalds 		break;
3671da177e4SLinus Torvalds 	case XFS_TRANS_SB_AGCOUNT:
3681da177e4SLinus Torvalds 		ASSERT(delta > 0);
3691da177e4SLinus Torvalds 		tp->t_agcount_delta += delta;
3701da177e4SLinus Torvalds 		break;
3711da177e4SLinus Torvalds 	case XFS_TRANS_SB_IMAXPCT:
3721da177e4SLinus Torvalds 		tp->t_imaxpct_delta += delta;
3731da177e4SLinus Torvalds 		break;
3741da177e4SLinus Torvalds 	case XFS_TRANS_SB_REXTSIZE:
3751da177e4SLinus Torvalds 		tp->t_rextsize_delta += delta;
3761da177e4SLinus Torvalds 		break;
3771da177e4SLinus Torvalds 	case XFS_TRANS_SB_RBMBLOCKS:
3781da177e4SLinus Torvalds 		tp->t_rbmblocks_delta += delta;
3791da177e4SLinus Torvalds 		break;
3801da177e4SLinus Torvalds 	case XFS_TRANS_SB_RBLOCKS:
3811da177e4SLinus Torvalds 		tp->t_rblocks_delta += delta;
3821da177e4SLinus Torvalds 		break;
3831da177e4SLinus Torvalds 	case XFS_TRANS_SB_REXTENTS:
3841da177e4SLinus Torvalds 		tp->t_rextents_delta += delta;
3851da177e4SLinus Torvalds 		break;
3861da177e4SLinus Torvalds 	case XFS_TRANS_SB_REXTSLOG:
3871da177e4SLinus Torvalds 		tp->t_rextslog_delta += delta;
3881da177e4SLinus Torvalds 		break;
3891da177e4SLinus Torvalds 	default:
3901da177e4SLinus Torvalds 		ASSERT(0);
3911da177e4SLinus Torvalds 		return;
3921da177e4SLinus Torvalds 	}
3931da177e4SLinus Torvalds 
394210c6f1cSDavid Chinner 	tp->t_flags |= flags;
3951da177e4SLinus Torvalds }
3961da177e4SLinus Torvalds 
3971da177e4SLinus Torvalds /*
3981da177e4SLinus Torvalds  * xfs_trans_apply_sb_deltas() is called from the commit code
3991da177e4SLinus Torvalds  * to bring the superblock buffer into the current transaction
4001da177e4SLinus Torvalds  * and modify it as requested by earlier calls to xfs_trans_mod_sb().
4011da177e4SLinus Torvalds  *
4021da177e4SLinus Torvalds  * For now we just look at each field allowed to change and change
4031da177e4SLinus Torvalds  * it if necessary.
4041da177e4SLinus Torvalds  */
4051da177e4SLinus Torvalds STATIC void
4061da177e4SLinus Torvalds xfs_trans_apply_sb_deltas(
4071da177e4SLinus Torvalds 	xfs_trans_t	*tp)
4081da177e4SLinus Torvalds {
4092bdf7cd0SChristoph Hellwig 	xfs_dsb_t	*sbp;
4101da177e4SLinus Torvalds 	xfs_buf_t	*bp;
4111da177e4SLinus Torvalds 	int		whole = 0;
4121da177e4SLinus Torvalds 
4131da177e4SLinus Torvalds 	bp = xfs_trans_getsb(tp, tp->t_mountp, 0);
4141da177e4SLinus Torvalds 	sbp = XFS_BUF_TO_SBP(bp);
4151da177e4SLinus Torvalds 
4161da177e4SLinus Torvalds 	/*
4171da177e4SLinus Torvalds 	 * Check that superblock mods match the mods made to AGF counters.
4181da177e4SLinus Torvalds 	 */
4191da177e4SLinus Torvalds 	ASSERT((tp->t_fdblocks_delta + tp->t_res_fdblocks_delta) ==
4201da177e4SLinus Torvalds 	       (tp->t_ag_freeblks_delta + tp->t_ag_flist_delta +
4211da177e4SLinus Torvalds 		tp->t_ag_btree_delta));
4221da177e4SLinus Torvalds 
42392821e2bSDavid Chinner 	/*
42492821e2bSDavid Chinner 	 * Only update the superblock counters if we are logging them
42592821e2bSDavid Chinner 	 */
42692821e2bSDavid Chinner 	if (!xfs_sb_version_haslazysbcount(&(tp->t_mountp->m_sb))) {
4272bdf7cd0SChristoph Hellwig 		if (tp->t_icount_delta)
428413d57c9SMarcin Slusarz 			be64_add_cpu(&sbp->sb_icount, tp->t_icount_delta);
4292bdf7cd0SChristoph Hellwig 		if (tp->t_ifree_delta)
430413d57c9SMarcin Slusarz 			be64_add_cpu(&sbp->sb_ifree, tp->t_ifree_delta);
4312bdf7cd0SChristoph Hellwig 		if (tp->t_fdblocks_delta)
432413d57c9SMarcin Slusarz 			be64_add_cpu(&sbp->sb_fdblocks, tp->t_fdblocks_delta);
4332bdf7cd0SChristoph Hellwig 		if (tp->t_res_fdblocks_delta)
434413d57c9SMarcin Slusarz 			be64_add_cpu(&sbp->sb_fdblocks, tp->t_res_fdblocks_delta);
4351da177e4SLinus Torvalds 	}
4361da177e4SLinus Torvalds 
4372bdf7cd0SChristoph Hellwig 	if (tp->t_frextents_delta)
438413d57c9SMarcin Slusarz 		be64_add_cpu(&sbp->sb_frextents, tp->t_frextents_delta);
4392bdf7cd0SChristoph Hellwig 	if (tp->t_res_frextents_delta)
440413d57c9SMarcin Slusarz 		be64_add_cpu(&sbp->sb_frextents, tp->t_res_frextents_delta);
4411da177e4SLinus Torvalds 
4422bdf7cd0SChristoph Hellwig 	if (tp->t_dblocks_delta) {
443413d57c9SMarcin Slusarz 		be64_add_cpu(&sbp->sb_dblocks, tp->t_dblocks_delta);
4441da177e4SLinus Torvalds 		whole = 1;
4451da177e4SLinus Torvalds 	}
4462bdf7cd0SChristoph Hellwig 	if (tp->t_agcount_delta) {
447413d57c9SMarcin Slusarz 		be32_add_cpu(&sbp->sb_agcount, tp->t_agcount_delta);
4481da177e4SLinus Torvalds 		whole = 1;
4491da177e4SLinus Torvalds 	}
4502bdf7cd0SChristoph Hellwig 	if (tp->t_imaxpct_delta) {
4512bdf7cd0SChristoph Hellwig 		sbp->sb_imax_pct += tp->t_imaxpct_delta;
4521da177e4SLinus Torvalds 		whole = 1;
4531da177e4SLinus Torvalds 	}
4542bdf7cd0SChristoph Hellwig 	if (tp->t_rextsize_delta) {
455413d57c9SMarcin Slusarz 		be32_add_cpu(&sbp->sb_rextsize, tp->t_rextsize_delta);
4561da177e4SLinus Torvalds 		whole = 1;
4571da177e4SLinus Torvalds 	}
4582bdf7cd0SChristoph Hellwig 	if (tp->t_rbmblocks_delta) {
459413d57c9SMarcin Slusarz 		be32_add_cpu(&sbp->sb_rbmblocks, tp->t_rbmblocks_delta);
4601da177e4SLinus Torvalds 		whole = 1;
4611da177e4SLinus Torvalds 	}
4622bdf7cd0SChristoph Hellwig 	if (tp->t_rblocks_delta) {
463413d57c9SMarcin Slusarz 		be64_add_cpu(&sbp->sb_rblocks, tp->t_rblocks_delta);
4641da177e4SLinus Torvalds 		whole = 1;
4651da177e4SLinus Torvalds 	}
4662bdf7cd0SChristoph Hellwig 	if (tp->t_rextents_delta) {
467413d57c9SMarcin Slusarz 		be64_add_cpu(&sbp->sb_rextents, tp->t_rextents_delta);
4681da177e4SLinus Torvalds 		whole = 1;
4691da177e4SLinus Torvalds 	}
4702bdf7cd0SChristoph Hellwig 	if (tp->t_rextslog_delta) {
4712bdf7cd0SChristoph Hellwig 		sbp->sb_rextslog += tp->t_rextslog_delta;
4721da177e4SLinus Torvalds 		whole = 1;
4731da177e4SLinus Torvalds 	}
4741da177e4SLinus Torvalds 
4753443a3bcSDave Chinner 	xfs_trans_buf_set_type(tp, bp, XFS_BLFT_SB_BUF);
4761da177e4SLinus Torvalds 	if (whole)
4771da177e4SLinus Torvalds 		/*
478c41564b5SNathan Scott 		 * Log the whole thing, the fields are noncontiguous.
4791da177e4SLinus Torvalds 		 */
4802bdf7cd0SChristoph Hellwig 		xfs_trans_log_buf(tp, bp, 0, sizeof(xfs_dsb_t) - 1);
4811da177e4SLinus Torvalds 	else
4821da177e4SLinus Torvalds 		/*
4831da177e4SLinus Torvalds 		 * Since all the modifiable fields are contiguous, we
4841da177e4SLinus Torvalds 		 * can get away with this.
4851da177e4SLinus Torvalds 		 */
4862bdf7cd0SChristoph Hellwig 		xfs_trans_log_buf(tp, bp, offsetof(xfs_dsb_t, sb_icount),
4872bdf7cd0SChristoph Hellwig 				  offsetof(xfs_dsb_t, sb_frextents) +
4881da177e4SLinus Torvalds 				  sizeof(sbp->sb_frextents) - 1);
4891da177e4SLinus Torvalds }
4901da177e4SLinus Torvalds 
4911da177e4SLinus Torvalds /*
49245c34141SDavid Chinner  * xfs_trans_unreserve_and_mod_sb() is called to release unused reservations
49345c34141SDavid Chinner  * and apply superblock counter changes to the in-core superblock.  The
49445c34141SDavid Chinner  * t_res_fdblocks_delta and t_res_frextents_delta fields are explicitly NOT
49545c34141SDavid Chinner  * applied to the in-core superblock.  The idea is that that has already been
49645c34141SDavid Chinner  * done.
4971da177e4SLinus Torvalds  *
4981da177e4SLinus Torvalds  * This is done efficiently with a single call to xfs_mod_incore_sb_batch().
49945c34141SDavid Chinner  * However, we have to ensure that we only modify each superblock field only
50045c34141SDavid Chinner  * once because the application of the delta values may not be atomic. That can
50145c34141SDavid Chinner  * lead to ENOSPC races occurring if we have two separate modifcations of the
50245c34141SDavid Chinner  * free space counter to put back the entire reservation and then take away
50345c34141SDavid Chinner  * what we used.
50445c34141SDavid Chinner  *
50545c34141SDavid Chinner  * If we are not logging superblock counters, then the inode allocated/free and
50645c34141SDavid Chinner  * used block counts are not updated in the on disk superblock. In this case,
50745c34141SDavid Chinner  * XFS_TRANS_SB_DIRTY will not be set when the transaction is updated but we
50845c34141SDavid Chinner  * still need to update the incore superblock with the changes.
5091da177e4SLinus Torvalds  */
51071e330b5SDave Chinner void
5111da177e4SLinus Torvalds xfs_trans_unreserve_and_mod_sb(
5121da177e4SLinus Torvalds 	xfs_trans_t	*tp)
5131da177e4SLinus Torvalds {
5141b040712SChristoph Hellwig 	xfs_mod_sb_t	msb[9];	/* If you add cases, add entries */
5151da177e4SLinus Torvalds 	xfs_mod_sb_t	*msbp;
51692821e2bSDavid Chinner 	xfs_mount_t	*mp = tp->t_mountp;
5171da177e4SLinus Torvalds 	/* REFERENCED */
5181da177e4SLinus Torvalds 	int		error;
5191da177e4SLinus Torvalds 	int		rsvd;
52045c34141SDavid Chinner 	int64_t		blkdelta = 0;
52145c34141SDavid Chinner 	int64_t		rtxdelta = 0;
5221b040712SChristoph Hellwig 	int64_t		idelta = 0;
5231b040712SChristoph Hellwig 	int64_t		ifreedelta = 0;
5241da177e4SLinus Torvalds 
5251da177e4SLinus Torvalds 	msbp = msb;
5261da177e4SLinus Torvalds 	rsvd = (tp->t_flags & XFS_TRANS_RESERVE) != 0;
5271da177e4SLinus Torvalds 
5281b040712SChristoph Hellwig 	/* calculate deltas */
52945c34141SDavid Chinner 	if (tp->t_blk_res > 0)
53045c34141SDavid Chinner 		blkdelta = tp->t_blk_res;
53145c34141SDavid Chinner 	if ((tp->t_fdblocks_delta != 0) &&
53245c34141SDavid Chinner 	    (xfs_sb_version_haslazysbcount(&mp->m_sb) ||
53345c34141SDavid Chinner 	     (tp->t_flags & XFS_TRANS_SB_DIRTY)))
53445c34141SDavid Chinner 	        blkdelta += tp->t_fdblocks_delta;
53545c34141SDavid Chinner 
53645c34141SDavid Chinner 	if (tp->t_rtx_res > 0)
53745c34141SDavid Chinner 		rtxdelta = tp->t_rtx_res;
53845c34141SDavid Chinner 	if ((tp->t_frextents_delta != 0) &&
53945c34141SDavid Chinner 	    (tp->t_flags & XFS_TRANS_SB_DIRTY))
54045c34141SDavid Chinner 		rtxdelta += tp->t_frextents_delta;
54145c34141SDavid Chinner 
5421b040712SChristoph Hellwig 	if (xfs_sb_version_haslazysbcount(&mp->m_sb) ||
5431b040712SChristoph Hellwig 	     (tp->t_flags & XFS_TRANS_SB_DIRTY)) {
5441b040712SChristoph Hellwig 		idelta = tp->t_icount_delta;
5451b040712SChristoph Hellwig 		ifreedelta = tp->t_ifree_delta;
5461b040712SChristoph Hellwig 	}
5471b040712SChristoph Hellwig 
5481b040712SChristoph Hellwig 	/* apply the per-cpu counters */
5491b040712SChristoph Hellwig 	if (blkdelta) {
5501b040712SChristoph Hellwig 		error = xfs_icsb_modify_counters(mp, XFS_SBS_FDBLOCKS,
5511b040712SChristoph Hellwig 						 blkdelta, rsvd);
5521b040712SChristoph Hellwig 		if (error)
5531b040712SChristoph Hellwig 			goto out;
5541b040712SChristoph Hellwig 	}
5551b040712SChristoph Hellwig 
5561b040712SChristoph Hellwig 	if (idelta) {
557*501ab323SDave Chinner 		error = xfs_mod_icount(mp, idelta);
5581b040712SChristoph Hellwig 		if (error)
5591b040712SChristoph Hellwig 			goto out_undo_fdblocks;
5601b040712SChristoph Hellwig 	}
5611b040712SChristoph Hellwig 
5621b040712SChristoph Hellwig 	if (ifreedelta) {
5631b040712SChristoph Hellwig 		error = xfs_icsb_modify_counters(mp, XFS_SBS_IFREE,
5641b040712SChristoph Hellwig 						 ifreedelta, rsvd);
5651b040712SChristoph Hellwig 		if (error)
5661b040712SChristoph Hellwig 			goto out_undo_icount;
5671b040712SChristoph Hellwig 	}
5681b040712SChristoph Hellwig 
5691b040712SChristoph Hellwig 	/* apply remaining deltas */
57045c34141SDavid Chinner 	if (rtxdelta != 0) {
5711da177e4SLinus Torvalds 		msbp->msb_field = XFS_SBS_FREXTENTS;
57245c34141SDavid Chinner 		msbp->msb_delta = rtxdelta;
5731da177e4SLinus Torvalds 		msbp++;
5741da177e4SLinus Torvalds 	}
5751da177e4SLinus Torvalds 
57692821e2bSDavid Chinner 	if (tp->t_flags & XFS_TRANS_SB_DIRTY) {
5771da177e4SLinus Torvalds 		if (tp->t_dblocks_delta != 0) {
5781da177e4SLinus Torvalds 			msbp->msb_field = XFS_SBS_DBLOCKS;
57920f4ebf2SDavid Chinner 			msbp->msb_delta = tp->t_dblocks_delta;
5801da177e4SLinus Torvalds 			msbp++;
5811da177e4SLinus Torvalds 		}
5821da177e4SLinus Torvalds 		if (tp->t_agcount_delta != 0) {
5831da177e4SLinus Torvalds 			msbp->msb_field = XFS_SBS_AGCOUNT;
58420f4ebf2SDavid Chinner 			msbp->msb_delta = tp->t_agcount_delta;
5851da177e4SLinus Torvalds 			msbp++;
5861da177e4SLinus Torvalds 		}
5871da177e4SLinus Torvalds 		if (tp->t_imaxpct_delta != 0) {
5881da177e4SLinus Torvalds 			msbp->msb_field = XFS_SBS_IMAX_PCT;
58920f4ebf2SDavid Chinner 			msbp->msb_delta = tp->t_imaxpct_delta;
5901da177e4SLinus Torvalds 			msbp++;
5911da177e4SLinus Torvalds 		}
5921da177e4SLinus Torvalds 		if (tp->t_rextsize_delta != 0) {
5931da177e4SLinus Torvalds 			msbp->msb_field = XFS_SBS_REXTSIZE;
59420f4ebf2SDavid Chinner 			msbp->msb_delta = tp->t_rextsize_delta;
5951da177e4SLinus Torvalds 			msbp++;
5961da177e4SLinus Torvalds 		}
5971da177e4SLinus Torvalds 		if (tp->t_rbmblocks_delta != 0) {
5981da177e4SLinus Torvalds 			msbp->msb_field = XFS_SBS_RBMBLOCKS;
59920f4ebf2SDavid Chinner 			msbp->msb_delta = tp->t_rbmblocks_delta;
6001da177e4SLinus Torvalds 			msbp++;
6011da177e4SLinus Torvalds 		}
6021da177e4SLinus Torvalds 		if (tp->t_rblocks_delta != 0) {
6031da177e4SLinus Torvalds 			msbp->msb_field = XFS_SBS_RBLOCKS;
60420f4ebf2SDavid Chinner 			msbp->msb_delta = tp->t_rblocks_delta;
6051da177e4SLinus Torvalds 			msbp++;
6061da177e4SLinus Torvalds 		}
6071da177e4SLinus Torvalds 		if (tp->t_rextents_delta != 0) {
6081da177e4SLinus Torvalds 			msbp->msb_field = XFS_SBS_REXTENTS;
60920f4ebf2SDavid Chinner 			msbp->msb_delta = tp->t_rextents_delta;
6101da177e4SLinus Torvalds 			msbp++;
6111da177e4SLinus Torvalds 		}
6121da177e4SLinus Torvalds 		if (tp->t_rextslog_delta != 0) {
6131da177e4SLinus Torvalds 			msbp->msb_field = XFS_SBS_REXTSLOG;
61420f4ebf2SDavid Chinner 			msbp->msb_delta = tp->t_rextslog_delta;
6151da177e4SLinus Torvalds 			msbp++;
6161da177e4SLinus Torvalds 		}
6171da177e4SLinus Torvalds 	}
6181da177e4SLinus Torvalds 
6191da177e4SLinus Torvalds 	/*
6201da177e4SLinus Torvalds 	 * If we need to change anything, do it.
6211da177e4SLinus Torvalds 	 */
6221da177e4SLinus Torvalds 	if (msbp > msb) {
6231da177e4SLinus Torvalds 		error = xfs_mod_incore_sb_batch(tp->t_mountp, msb,
6241da177e4SLinus Torvalds 			(uint)(msbp - msb), rsvd);
6251b040712SChristoph Hellwig 		if (error)
6261b040712SChristoph Hellwig 			goto out_undo_ifreecount;
6271da177e4SLinus Torvalds 	}
6281b040712SChristoph Hellwig 
6291b040712SChristoph Hellwig 	return;
6301b040712SChristoph Hellwig 
6311b040712SChristoph Hellwig out_undo_ifreecount:
6321b040712SChristoph Hellwig 	if (ifreedelta)
6331b040712SChristoph Hellwig 		xfs_icsb_modify_counters(mp, XFS_SBS_IFREE, -ifreedelta, rsvd);
6341b040712SChristoph Hellwig out_undo_icount:
6351b040712SChristoph Hellwig 	if (idelta)
636*501ab323SDave Chinner 		xfs_mod_icount(mp, -idelta);
6371b040712SChristoph Hellwig out_undo_fdblocks:
6381b040712SChristoph Hellwig 	if (blkdelta)
6391b040712SChristoph Hellwig 		xfs_icsb_modify_counters(mp, XFS_SBS_FDBLOCKS, -blkdelta, rsvd);
6401b040712SChristoph Hellwig out:
6411884bd83SJesper Juhl 	ASSERT(error == 0);
6421b040712SChristoph Hellwig 	return;
6431da177e4SLinus Torvalds }
6441da177e4SLinus Torvalds 
6451da177e4SLinus Torvalds /*
646e98c414fSChristoph Hellwig  * Add the given log item to the transaction's list of log items.
647e98c414fSChristoph Hellwig  *
648e98c414fSChristoph Hellwig  * The log item will now point to its new descriptor with its li_desc field.
649e98c414fSChristoph Hellwig  */
650e98c414fSChristoph Hellwig void
651e98c414fSChristoph Hellwig xfs_trans_add_item(
652e98c414fSChristoph Hellwig 	struct xfs_trans	*tp,
653e98c414fSChristoph Hellwig 	struct xfs_log_item	*lip)
654e98c414fSChristoph Hellwig {
655e98c414fSChristoph Hellwig 	struct xfs_log_item_desc *lidp;
656e98c414fSChristoph Hellwig 
657f65020a8SJesper Juhl 	ASSERT(lip->li_mountp == tp->t_mountp);
658f65020a8SJesper Juhl 	ASSERT(lip->li_ailp == tp->t_mountp->m_ail);
659e98c414fSChristoph Hellwig 
66043869706SDave Chinner 	lidp = kmem_zone_zalloc(xfs_log_item_desc_zone, KM_SLEEP | KM_NOFS);
661e98c414fSChristoph Hellwig 
662e98c414fSChristoph Hellwig 	lidp->lid_item = lip;
663e98c414fSChristoph Hellwig 	lidp->lid_flags = 0;
664e98c414fSChristoph Hellwig 	list_add_tail(&lidp->lid_trans, &tp->t_items);
665e98c414fSChristoph Hellwig 
666e98c414fSChristoph Hellwig 	lip->li_desc = lidp;
667e98c414fSChristoph Hellwig }
668e98c414fSChristoph Hellwig 
669e98c414fSChristoph Hellwig STATIC void
670e98c414fSChristoph Hellwig xfs_trans_free_item_desc(
671e98c414fSChristoph Hellwig 	struct xfs_log_item_desc *lidp)
672e98c414fSChristoph Hellwig {
673e98c414fSChristoph Hellwig 	list_del_init(&lidp->lid_trans);
674e98c414fSChristoph Hellwig 	kmem_zone_free(xfs_log_item_desc_zone, lidp);
675e98c414fSChristoph Hellwig }
676e98c414fSChristoph Hellwig 
677e98c414fSChristoph Hellwig /*
678e98c414fSChristoph Hellwig  * Unlink and free the given descriptor.
679e98c414fSChristoph Hellwig  */
680e98c414fSChristoph Hellwig void
681e98c414fSChristoph Hellwig xfs_trans_del_item(
682e98c414fSChristoph Hellwig 	struct xfs_log_item	*lip)
683e98c414fSChristoph Hellwig {
684e98c414fSChristoph Hellwig 	xfs_trans_free_item_desc(lip->li_desc);
685e98c414fSChristoph Hellwig 	lip->li_desc = NULL;
686e98c414fSChristoph Hellwig }
687e98c414fSChristoph Hellwig 
688e98c414fSChristoph Hellwig /*
689e98c414fSChristoph Hellwig  * Unlock all of the items of a transaction and free all the descriptors
690e98c414fSChristoph Hellwig  * of that transaction.
691e98c414fSChristoph Hellwig  */
692d17c701cSDave Chinner void
693e98c414fSChristoph Hellwig xfs_trans_free_items(
694e98c414fSChristoph Hellwig 	struct xfs_trans	*tp,
695e98c414fSChristoph Hellwig 	xfs_lsn_t		commit_lsn,
696e98c414fSChristoph Hellwig 	int			flags)
697e98c414fSChristoph Hellwig {
698e98c414fSChristoph Hellwig 	struct xfs_log_item_desc *lidp, *next;
699e98c414fSChristoph Hellwig 
700e98c414fSChristoph Hellwig 	list_for_each_entry_safe(lidp, next, &tp->t_items, lid_trans) {
701e98c414fSChristoph Hellwig 		struct xfs_log_item	*lip = lidp->lid_item;
702e98c414fSChristoph Hellwig 
703e98c414fSChristoph Hellwig 		lip->li_desc = NULL;
704e98c414fSChristoph Hellwig 
705e98c414fSChristoph Hellwig 		if (commit_lsn != NULLCOMMITLSN)
706904c17e6SDave Chinner 			lip->li_ops->iop_committing(lip, commit_lsn);
707e98c414fSChristoph Hellwig 		if (flags & XFS_TRANS_ABORT)
708e98c414fSChristoph Hellwig 			lip->li_flags |= XFS_LI_ABORTED;
709904c17e6SDave Chinner 		lip->li_ops->iop_unlock(lip);
710e98c414fSChristoph Hellwig 
711e98c414fSChristoph Hellwig 		xfs_trans_free_item_desc(lidp);
712e98c414fSChristoph Hellwig 	}
713e98c414fSChristoph Hellwig }
714e98c414fSChristoph Hellwig 
7150e57f6a3SDave Chinner static inline void
7160e57f6a3SDave Chinner xfs_log_item_batch_insert(
7170e57f6a3SDave Chinner 	struct xfs_ail		*ailp,
7181d8c95a3SDave Chinner 	struct xfs_ail_cursor	*cur,
7190e57f6a3SDave Chinner 	struct xfs_log_item	**log_items,
7200e57f6a3SDave Chinner 	int			nr_items,
7210e57f6a3SDave Chinner 	xfs_lsn_t		commit_lsn)
7220e57f6a3SDave Chinner {
7230e57f6a3SDave Chinner 	int	i;
7240e57f6a3SDave Chinner 
7250e57f6a3SDave Chinner 	spin_lock(&ailp->xa_lock);
7260e57f6a3SDave Chinner 	/* xfs_trans_ail_update_bulk drops ailp->xa_lock */
7271d8c95a3SDave Chinner 	xfs_trans_ail_update_bulk(ailp, cur, log_items, nr_items, commit_lsn);
7280e57f6a3SDave Chinner 
729904c17e6SDave Chinner 	for (i = 0; i < nr_items; i++) {
730904c17e6SDave Chinner 		struct xfs_log_item *lip = log_items[i];
731904c17e6SDave Chinner 
732904c17e6SDave Chinner 		lip->li_ops->iop_unpin(lip, 0);
733904c17e6SDave Chinner 	}
7340e57f6a3SDave Chinner }
7350e57f6a3SDave Chinner 
7360e57f6a3SDave Chinner /*
7370e57f6a3SDave Chinner  * Bulk operation version of xfs_trans_committed that takes a log vector of
7380e57f6a3SDave Chinner  * items to insert into the AIL. This uses bulk AIL insertion techniques to
7390e57f6a3SDave Chinner  * minimise lock traffic.
740e34a314cSDave Chinner  *
741e34a314cSDave Chinner  * If we are called with the aborted flag set, it is because a log write during
742e34a314cSDave Chinner  * a CIL checkpoint commit has failed. In this case, all the items in the
743904c17e6SDave Chinner  * checkpoint have already gone through iop_commited and iop_unlock, which
744e34a314cSDave Chinner  * means that checkpoint commit abort handling is treated exactly the same
745e34a314cSDave Chinner  * as an iclog write error even though we haven't started any IO yet. Hence in
746904c17e6SDave Chinner  * this case all we need to do is iop_committed processing, followed by an
747904c17e6SDave Chinner  * iop_unpin(aborted) call.
7481d8c95a3SDave Chinner  *
7491d8c95a3SDave Chinner  * The AIL cursor is used to optimise the insert process. If commit_lsn is not
7501d8c95a3SDave Chinner  * at the end of the AIL, the insert cursor avoids the need to walk
7511d8c95a3SDave Chinner  * the AIL to find the insertion point on every xfs_log_item_batch_insert()
7521d8c95a3SDave Chinner  * call. This saves a lot of needless list walking and is a net win, even
7531d8c95a3SDave Chinner  * though it slightly increases that amount of AIL lock traffic to set it up
7541d8c95a3SDave Chinner  * and tear it down.
7550e57f6a3SDave Chinner  */
7560e57f6a3SDave Chinner void
7570e57f6a3SDave Chinner xfs_trans_committed_bulk(
7580e57f6a3SDave Chinner 	struct xfs_ail		*ailp,
7590e57f6a3SDave Chinner 	struct xfs_log_vec	*log_vector,
7600e57f6a3SDave Chinner 	xfs_lsn_t		commit_lsn,
7610e57f6a3SDave Chinner 	int			aborted)
7620e57f6a3SDave Chinner {
7630e57f6a3SDave Chinner #define LOG_ITEM_BATCH_SIZE	32
7640e57f6a3SDave Chinner 	struct xfs_log_item	*log_items[LOG_ITEM_BATCH_SIZE];
7650e57f6a3SDave Chinner 	struct xfs_log_vec	*lv;
7661d8c95a3SDave Chinner 	struct xfs_ail_cursor	cur;
7670e57f6a3SDave Chinner 	int			i = 0;
7680e57f6a3SDave Chinner 
7691d8c95a3SDave Chinner 	spin_lock(&ailp->xa_lock);
7701d8c95a3SDave Chinner 	xfs_trans_ail_cursor_last(ailp, &cur, commit_lsn);
7711d8c95a3SDave Chinner 	spin_unlock(&ailp->xa_lock);
7721d8c95a3SDave Chinner 
7730e57f6a3SDave Chinner 	/* unpin all the log items */
7740e57f6a3SDave Chinner 	for (lv = log_vector; lv; lv = lv->lv_next ) {
7750e57f6a3SDave Chinner 		struct xfs_log_item	*lip = lv->lv_item;
7760e57f6a3SDave Chinner 		xfs_lsn_t		item_lsn;
7770e57f6a3SDave Chinner 
7780e57f6a3SDave Chinner 		if (aborted)
7790e57f6a3SDave Chinner 			lip->li_flags |= XFS_LI_ABORTED;
780904c17e6SDave Chinner 		item_lsn = lip->li_ops->iop_committed(lip, commit_lsn);
7810e57f6a3SDave Chinner 
7821316d4daSDave Chinner 		/* item_lsn of -1 means the item needs no further processing */
7830e57f6a3SDave Chinner 		if (XFS_LSN_CMP(item_lsn, (xfs_lsn_t)-1) == 0)
7840e57f6a3SDave Chinner 			continue;
7850e57f6a3SDave Chinner 
786e34a314cSDave Chinner 		/*
787e34a314cSDave Chinner 		 * if we are aborting the operation, no point in inserting the
788e34a314cSDave Chinner 		 * object into the AIL as we are in a shutdown situation.
789e34a314cSDave Chinner 		 */
790e34a314cSDave Chinner 		if (aborted) {
791e34a314cSDave Chinner 			ASSERT(XFS_FORCED_SHUTDOWN(ailp->xa_mount));
792904c17e6SDave Chinner 			lip->li_ops->iop_unpin(lip, 1);
793e34a314cSDave Chinner 			continue;
794e34a314cSDave Chinner 		}
795e34a314cSDave Chinner 
7960e57f6a3SDave Chinner 		if (item_lsn != commit_lsn) {
7970e57f6a3SDave Chinner 
7980e57f6a3SDave Chinner 			/*
7990e57f6a3SDave Chinner 			 * Not a bulk update option due to unusual item_lsn.
8000e57f6a3SDave Chinner 			 * Push into AIL immediately, rechecking the lsn once
8011d8c95a3SDave Chinner 			 * we have the ail lock. Then unpin the item. This does
8021d8c95a3SDave Chinner 			 * not affect the AIL cursor the bulk insert path is
8031d8c95a3SDave Chinner 			 * using.
8040e57f6a3SDave Chinner 			 */
8050e57f6a3SDave Chinner 			spin_lock(&ailp->xa_lock);
8060e57f6a3SDave Chinner 			if (XFS_LSN_CMP(item_lsn, lip->li_lsn) > 0)
8070e57f6a3SDave Chinner 				xfs_trans_ail_update(ailp, lip, item_lsn);
8080e57f6a3SDave Chinner 			else
8090e57f6a3SDave Chinner 				spin_unlock(&ailp->xa_lock);
810904c17e6SDave Chinner 			lip->li_ops->iop_unpin(lip, 0);
8110e57f6a3SDave Chinner 			continue;
8120e57f6a3SDave Chinner 		}
8130e57f6a3SDave Chinner 
8140e57f6a3SDave Chinner 		/* Item is a candidate for bulk AIL insert.  */
8150e57f6a3SDave Chinner 		log_items[i++] = lv->lv_item;
8160e57f6a3SDave Chinner 		if (i >= LOG_ITEM_BATCH_SIZE) {
8171d8c95a3SDave Chinner 			xfs_log_item_batch_insert(ailp, &cur, log_items,
8180e57f6a3SDave Chinner 					LOG_ITEM_BATCH_SIZE, commit_lsn);
8190e57f6a3SDave Chinner 			i = 0;
8200e57f6a3SDave Chinner 		}
8210e57f6a3SDave Chinner 	}
8220e57f6a3SDave Chinner 
8230e57f6a3SDave Chinner 	/* make sure we insert the remainder! */
8240e57f6a3SDave Chinner 	if (i)
8251d8c95a3SDave Chinner 		xfs_log_item_batch_insert(ailp, &cur, log_items, i, commit_lsn);
8261d8c95a3SDave Chinner 
8271d8c95a3SDave Chinner 	spin_lock(&ailp->xa_lock);
828e4a1e29cSEric Sandeen 	xfs_trans_ail_cursor_done(&cur);
8291d8c95a3SDave Chinner 	spin_unlock(&ailp->xa_lock);
8300e57f6a3SDave Chinner }
8310e57f6a3SDave Chinner 
832b1c1b5b6SDave Chinner /*
833b1037058SChristoph Hellwig  * Commit the given transaction to the log.
8340924378aSDave Chinner  *
8350924378aSDave Chinner  * XFS disk error handling mechanism is not based on a typical
8360924378aSDave Chinner  * transaction abort mechanism. Logically after the filesystem
8370924378aSDave Chinner  * gets marked 'SHUTDOWN', we can't let any new transactions
8380924378aSDave Chinner  * be durable - ie. committed to disk - because some metadata might
8390924378aSDave Chinner  * be inconsistent. In such cases, this returns an error, and the
8400924378aSDave Chinner  * caller may assume that all locked objects joined to the transaction
8410924378aSDave Chinner  * have already been unlocked as if the commit had succeeded.
8420924378aSDave Chinner  * Do not reference the transaction structure after this call.
8430924378aSDave Chinner  */
8440924378aSDave Chinner int
845b1037058SChristoph Hellwig xfs_trans_commit(
846a3ccd2caSChristoph Hellwig 	struct xfs_trans	*tp,
847b1037058SChristoph Hellwig 	uint			flags)
8480924378aSDave Chinner {
849a3ccd2caSChristoph Hellwig 	struct xfs_mount	*mp = tp->t_mountp;
8500924378aSDave Chinner 	xfs_lsn_t		commit_lsn = -1;
851a3ccd2caSChristoph Hellwig 	int			error = 0;
8520924378aSDave Chinner 	int			log_flags = 0;
8530924378aSDave Chinner 	int			sync = tp->t_flags & XFS_TRANS_SYNC;
8540924378aSDave Chinner 
8550924378aSDave Chinner 	/*
8560924378aSDave Chinner 	 * Determine whether this commit is releasing a permanent
8570924378aSDave Chinner 	 * log reservation or not.
8580924378aSDave Chinner 	 */
8590924378aSDave Chinner 	if (flags & XFS_TRANS_RELEASE_LOG_RES) {
8600924378aSDave Chinner 		ASSERT(tp->t_flags & XFS_TRANS_PERM_LOG_RES);
8610924378aSDave Chinner 		log_flags = XFS_LOG_REL_PERM_RESERV;
8620924378aSDave Chinner 	}
8630924378aSDave Chinner 
8640924378aSDave Chinner 	/*
8650924378aSDave Chinner 	 * If there is nothing to be logged by the transaction,
8660924378aSDave Chinner 	 * then unlock all of the items associated with the
8670924378aSDave Chinner 	 * transaction and free the transaction structure.
8680924378aSDave Chinner 	 * Also make sure to return any reserved blocks to
8690924378aSDave Chinner 	 * the free pool.
8700924378aSDave Chinner 	 */
871a3ccd2caSChristoph Hellwig 	if (!(tp->t_flags & XFS_TRANS_DIRTY))
872a3ccd2caSChristoph Hellwig 		goto out_unreserve;
873a3ccd2caSChristoph Hellwig 
874a3ccd2caSChristoph Hellwig 	if (XFS_FORCED_SHUTDOWN(mp)) {
8752451337dSDave Chinner 		error = -EIO;
876a3ccd2caSChristoph Hellwig 		goto out_unreserve;
8770924378aSDave Chinner 	}
878a3ccd2caSChristoph Hellwig 
8790924378aSDave Chinner 	ASSERT(tp->t_ticket != NULL);
8800924378aSDave Chinner 
8810924378aSDave Chinner 	/*
8820924378aSDave Chinner 	 * If we need to update the superblock, then do it now.
8830924378aSDave Chinner 	 */
8840924378aSDave Chinner 	if (tp->t_flags & XFS_TRANS_SB_DIRTY)
8850924378aSDave Chinner 		xfs_trans_apply_sb_deltas(tp);
8860924378aSDave Chinner 	xfs_trans_apply_dquot_deltas(tp);
8870924378aSDave Chinner 
888c6f97264SJie Liu 	xfs_log_commit_cil(mp, tp, &commit_lsn, flags);
8891da177e4SLinus Torvalds 
8900244b960SChristoph Hellwig 	current_restore_flags_nested(&tp->t_pflags, PF_FSTRANS);
8910244b960SChristoph Hellwig 	xfs_trans_free(tp);
8920244b960SChristoph Hellwig 
8931da177e4SLinus Torvalds 	/*
8941da177e4SLinus Torvalds 	 * If the transaction needs to be synchronous, then force the
8951da177e4SLinus Torvalds 	 * log out now and wait for it.
8961da177e4SLinus Torvalds 	 */
8971da177e4SLinus Torvalds 	if (sync) {
898c6f97264SJie Liu 		error = _xfs_log_force_lsn(mp, commit_lsn, XFS_LOG_SYNC, NULL);
8991da177e4SLinus Torvalds 		XFS_STATS_INC(xs_trans_sync);
9001da177e4SLinus Torvalds 	} else {
9011da177e4SLinus Torvalds 		XFS_STATS_INC(xs_trans_async);
9021da177e4SLinus Torvalds 	}
9031da177e4SLinus Torvalds 
904a3ccd2caSChristoph Hellwig 	return error;
905a3ccd2caSChristoph Hellwig 
906a3ccd2caSChristoph Hellwig out_unreserve:
907a3ccd2caSChristoph Hellwig 	xfs_trans_unreserve_and_mod_sb(tp);
908a3ccd2caSChristoph Hellwig 
909a3ccd2caSChristoph Hellwig 	/*
910a3ccd2caSChristoph Hellwig 	 * It is indeed possible for the transaction to be not dirty but
911a3ccd2caSChristoph Hellwig 	 * the dqinfo portion to be.  All that means is that we have some
912a3ccd2caSChristoph Hellwig 	 * (non-persistent) quota reservations that need to be unreserved.
913a3ccd2caSChristoph Hellwig 	 */
914a3ccd2caSChristoph Hellwig 	xfs_trans_unreserve_and_mod_dquots(tp);
915a3ccd2caSChristoph Hellwig 	if (tp->t_ticket) {
916a3ccd2caSChristoph Hellwig 		commit_lsn = xfs_log_done(mp, tp->t_ticket, NULL, log_flags);
917a3ccd2caSChristoph Hellwig 		if (commit_lsn == -1 && !error)
9182451337dSDave Chinner 			error = -EIO;
919a3ccd2caSChristoph Hellwig 	}
920a3ccd2caSChristoph Hellwig 	current_restore_flags_nested(&tp->t_pflags, PF_FSTRANS);
92171e330b5SDave Chinner 	xfs_trans_free_items(tp, NULLCOMMITLSN, error ? XFS_TRANS_ABORT : 0);
922a3ccd2caSChristoph Hellwig 	xfs_trans_free(tp);
923a3ccd2caSChristoph Hellwig 
924a3ccd2caSChristoph Hellwig 	XFS_STATS_INC(xs_trans_empty);
925a3ccd2caSChristoph Hellwig 	return error;
9261da177e4SLinus Torvalds }
9271da177e4SLinus Torvalds 
9281da177e4SLinus Torvalds /*
9291da177e4SLinus Torvalds  * Unlock all of the transaction's items and free the transaction.
9301da177e4SLinus Torvalds  * The transaction must not have modified any of its items, because
9311da177e4SLinus Torvalds  * there is no way to restore them to their previous state.
9321da177e4SLinus Torvalds  *
9331da177e4SLinus Torvalds  * If the transaction has made a log reservation, make sure to release
9341da177e4SLinus Torvalds  * it as well.
9351da177e4SLinus Torvalds  */
9361da177e4SLinus Torvalds void
9371da177e4SLinus Torvalds xfs_trans_cancel(
9381da177e4SLinus Torvalds 	xfs_trans_t		*tp,
9391da177e4SLinus Torvalds 	int			flags)
9401da177e4SLinus Torvalds {
9411da177e4SLinus Torvalds 	int			log_flags;
9420733af21SRyan Hankins 	xfs_mount_t		*mp = tp->t_mountp;
9431da177e4SLinus Torvalds 
9441da177e4SLinus Torvalds 	/*
9451da177e4SLinus Torvalds 	 * See if the caller is being too lazy to figure out if
9461da177e4SLinus Torvalds 	 * the transaction really needs an abort.
9471da177e4SLinus Torvalds 	 */
9481da177e4SLinus Torvalds 	if ((flags & XFS_TRANS_ABORT) && !(tp->t_flags & XFS_TRANS_DIRTY))
9491da177e4SLinus Torvalds 		flags &= ~XFS_TRANS_ABORT;
9501da177e4SLinus Torvalds 	/*
9511da177e4SLinus Torvalds 	 * See if the caller is relying on us to shut down the
9521da177e4SLinus Torvalds 	 * filesystem.  This happens in paths where we detect
9531da177e4SLinus Torvalds 	 * corruption and decide to give up.
9541da177e4SLinus Torvalds 	 */
95560a204f0SNathan Scott 	if ((tp->t_flags & XFS_TRANS_DIRTY) && !XFS_FORCED_SHUTDOWN(mp)) {
9560733af21SRyan Hankins 		XFS_ERROR_REPORT("xfs_trans_cancel", XFS_ERRLEVEL_LOW, mp);
9577d04a335SNathan Scott 		xfs_force_shutdown(mp, SHUTDOWN_CORRUPT_INCORE);
95860a204f0SNathan Scott 	}
9591da177e4SLinus Torvalds #ifdef DEBUG
960e98c414fSChristoph Hellwig 	if (!(flags & XFS_TRANS_ABORT) && !XFS_FORCED_SHUTDOWN(mp)) {
961e98c414fSChristoph Hellwig 		struct xfs_log_item_desc *lidp;
9621da177e4SLinus Torvalds 
963e98c414fSChristoph Hellwig 		list_for_each_entry(lidp, &tp->t_items, lid_trans)
964e98c414fSChristoph Hellwig 			ASSERT(!(lidp->lid_item->li_type == XFS_LI_EFD));
9651da177e4SLinus Torvalds 	}
9661da177e4SLinus Torvalds #endif
9671da177e4SLinus Torvalds 	xfs_trans_unreserve_and_mod_sb(tp);
9687d095257SChristoph Hellwig 	xfs_trans_unreserve_and_mod_dquots(tp);
9691da177e4SLinus Torvalds 
9701da177e4SLinus Torvalds 	if (tp->t_ticket) {
9711da177e4SLinus Torvalds 		if (flags & XFS_TRANS_RELEASE_LOG_RES) {
9721da177e4SLinus Torvalds 			ASSERT(tp->t_flags & XFS_TRANS_PERM_LOG_RES);
9731da177e4SLinus Torvalds 			log_flags = XFS_LOG_REL_PERM_RESERV;
9741da177e4SLinus Torvalds 		} else {
9751da177e4SLinus Torvalds 			log_flags = 0;
9761da177e4SLinus Torvalds 		}
9770733af21SRyan Hankins 		xfs_log_done(mp, tp->t_ticket, NULL, log_flags);
9781da177e4SLinus Torvalds 	}
9791da177e4SLinus Torvalds 
9801da177e4SLinus Torvalds 	/* mark this thread as no longer being in a transaction */
98159c1b082SNathan Scott 	current_restore_flags_nested(&tp->t_pflags, PF_FSTRANS);
9821da177e4SLinus Torvalds 
98371e330b5SDave Chinner 	xfs_trans_free_items(tp, NULLCOMMITLSN, flags);
9841da177e4SLinus Torvalds 	xfs_trans_free(tp);
9851da177e4SLinus Torvalds }
9861da177e4SLinus Torvalds 
987322ff6b8SNiv Sardi /*
988322ff6b8SNiv Sardi  * Roll from one trans in the sequence of PERMANENT transactions to
989322ff6b8SNiv Sardi  * the next: permanent transactions are only flushed out when
990322ff6b8SNiv Sardi  * committed with XFS_TRANS_RELEASE_LOG_RES, but we still want as soon
991322ff6b8SNiv Sardi  * as possible to let chunks of it go to the log. So we commit the
992322ff6b8SNiv Sardi  * chunk we've been working on and get a new transaction to continue.
993322ff6b8SNiv Sardi  */
994322ff6b8SNiv Sardi int
995322ff6b8SNiv Sardi xfs_trans_roll(
996322ff6b8SNiv Sardi 	struct xfs_trans	**tpp,
997322ff6b8SNiv Sardi 	struct xfs_inode	*dp)
998322ff6b8SNiv Sardi {
999322ff6b8SNiv Sardi 	struct xfs_trans	*trans;
10003d3c8b52SJie Liu 	struct xfs_trans_res	tres;
1001322ff6b8SNiv Sardi 	int			error;
1002322ff6b8SNiv Sardi 
1003322ff6b8SNiv Sardi 	/*
1004322ff6b8SNiv Sardi 	 * Ensure that the inode is always logged.
1005322ff6b8SNiv Sardi 	 */
1006322ff6b8SNiv Sardi 	trans = *tpp;
1007322ff6b8SNiv Sardi 	xfs_trans_log_inode(trans, dp, XFS_ILOG_CORE);
1008322ff6b8SNiv Sardi 
1009322ff6b8SNiv Sardi 	/*
1010322ff6b8SNiv Sardi 	 * Copy the critical parameters from one trans to the next.
1011322ff6b8SNiv Sardi 	 */
10123d3c8b52SJie Liu 	tres.tr_logres = trans->t_log_res;
10133d3c8b52SJie Liu 	tres.tr_logcount = trans->t_log_count;
1014322ff6b8SNiv Sardi 	*tpp = xfs_trans_dup(trans);
1015322ff6b8SNiv Sardi 
1016322ff6b8SNiv Sardi 	/*
1017322ff6b8SNiv Sardi 	 * Commit the current transaction.
1018322ff6b8SNiv Sardi 	 * If this commit failed, then it'd just unlock those items that
1019322ff6b8SNiv Sardi 	 * are not marked ihold. That also means that a filesystem shutdown
1020322ff6b8SNiv Sardi 	 * is in progress. The caller takes the responsibility to cancel
1021322ff6b8SNiv Sardi 	 * the duplicate transaction that gets returned.
1022322ff6b8SNiv Sardi 	 */
1023322ff6b8SNiv Sardi 	error = xfs_trans_commit(trans, 0);
1024322ff6b8SNiv Sardi 	if (error)
1025d99831ffSEric Sandeen 		return error;
1026322ff6b8SNiv Sardi 
1027322ff6b8SNiv Sardi 	trans = *tpp;
1028322ff6b8SNiv Sardi 
1029322ff6b8SNiv Sardi 	/*
1030cc09c0dcSDave Chinner 	 * transaction commit worked ok so we can drop the extra ticket
1031cc09c0dcSDave Chinner 	 * reference that we gained in xfs_trans_dup()
1032cc09c0dcSDave Chinner 	 */
1033cc09c0dcSDave Chinner 	xfs_log_ticket_put(trans->t_ticket);
1034cc09c0dcSDave Chinner 
1035cc09c0dcSDave Chinner 
1036cc09c0dcSDave Chinner 	/*
1037322ff6b8SNiv Sardi 	 * Reserve space in the log for th next transaction.
1038322ff6b8SNiv Sardi 	 * This also pushes items in the "AIL", the list of logged items,
1039322ff6b8SNiv Sardi 	 * out to disk if they are taking up space at the tail of the log
1040322ff6b8SNiv Sardi 	 * that we want to use.  This requires that either nothing be locked
1041322ff6b8SNiv Sardi 	 * across this call, or that anything that is locked be logged in
1042322ff6b8SNiv Sardi 	 * the prior and the next transactions.
1043322ff6b8SNiv Sardi 	 */
10443d3c8b52SJie Liu 	tres.tr_logflags = XFS_TRANS_PERM_LOG_RES;
10453d3c8b52SJie Liu 	error = xfs_trans_reserve(trans, &tres, 0, 0);
1046322ff6b8SNiv Sardi 	/*
1047322ff6b8SNiv Sardi 	 *  Ensure that the inode is in the new transaction and locked.
1048322ff6b8SNiv Sardi 	 */
1049322ff6b8SNiv Sardi 	if (error)
1050322ff6b8SNiv Sardi 		return error;
1051322ff6b8SNiv Sardi 
1052ddc3415aSChristoph Hellwig 	xfs_trans_ijoin(trans, dp, 0);
1053322ff6b8SNiv Sardi 	return 0;
1054322ff6b8SNiv Sardi }
1055