162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Copyright (c) 2000-2003,2005 Silicon Graphics, Inc. 462306a36Sopenharmony_ci * Copyright (C) 2010 Red Hat, Inc. 562306a36Sopenharmony_ci * All Rights Reserved. 662306a36Sopenharmony_ci */ 762306a36Sopenharmony_ci#include "xfs.h" 862306a36Sopenharmony_ci#include "xfs_fs.h" 962306a36Sopenharmony_ci#include "xfs_shared.h" 1062306a36Sopenharmony_ci#include "xfs_format.h" 1162306a36Sopenharmony_ci#include "xfs_log_format.h" 1262306a36Sopenharmony_ci#include "xfs_trans_resv.h" 1362306a36Sopenharmony_ci#include "xfs_mount.h" 1462306a36Sopenharmony_ci#include "xfs_extent_busy.h" 1562306a36Sopenharmony_ci#include "xfs_quota.h" 1662306a36Sopenharmony_ci#include "xfs_trans.h" 1762306a36Sopenharmony_ci#include "xfs_trans_priv.h" 1862306a36Sopenharmony_ci#include "xfs_log.h" 1962306a36Sopenharmony_ci#include "xfs_log_priv.h" 2062306a36Sopenharmony_ci#include "xfs_trace.h" 2162306a36Sopenharmony_ci#include "xfs_error.h" 2262306a36Sopenharmony_ci#include "xfs_defer.h" 2362306a36Sopenharmony_ci#include "xfs_inode.h" 2462306a36Sopenharmony_ci#include "xfs_dquot_item.h" 2562306a36Sopenharmony_ci#include "xfs_dquot.h" 2662306a36Sopenharmony_ci#include "xfs_icache.h" 2762306a36Sopenharmony_ci 2862306a36Sopenharmony_cistruct kmem_cache *xfs_trans_cache; 2962306a36Sopenharmony_ci 3062306a36Sopenharmony_ci#if defined(CONFIG_TRACEPOINTS) 3162306a36Sopenharmony_cistatic void 3262306a36Sopenharmony_cixfs_trans_trace_reservations( 3362306a36Sopenharmony_ci struct xfs_mount *mp) 3462306a36Sopenharmony_ci{ 3562306a36Sopenharmony_ci struct xfs_trans_res *res; 3662306a36Sopenharmony_ci struct xfs_trans_res *end_res; 3762306a36Sopenharmony_ci int i; 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_ci res = (struct xfs_trans_res *)M_RES(mp); 4062306a36Sopenharmony_ci end_res = (struct xfs_trans_res *)(M_RES(mp) + 1); 4162306a36Sopenharmony_ci for (i = 0; res < end_res; i++, res++) 4262306a36Sopenharmony_ci trace_xfs_trans_resv_calc(mp, i, res); 4362306a36Sopenharmony_ci} 4462306a36Sopenharmony_ci#else 4562306a36Sopenharmony_ci# define xfs_trans_trace_reservations(mp) 4662306a36Sopenharmony_ci#endif 4762306a36Sopenharmony_ci 4862306a36Sopenharmony_ci/* 4962306a36Sopenharmony_ci * Initialize the precomputed transaction reservation values 5062306a36Sopenharmony_ci * in the mount structure. 5162306a36Sopenharmony_ci */ 5262306a36Sopenharmony_civoid 5362306a36Sopenharmony_cixfs_trans_init( 5462306a36Sopenharmony_ci struct xfs_mount *mp) 5562306a36Sopenharmony_ci{ 5662306a36Sopenharmony_ci xfs_trans_resv_calc(mp, M_RES(mp)); 5762306a36Sopenharmony_ci xfs_trans_trace_reservations(mp); 5862306a36Sopenharmony_ci} 5962306a36Sopenharmony_ci 6062306a36Sopenharmony_ci/* 6162306a36Sopenharmony_ci * Free the transaction structure. If there is more clean up 6262306a36Sopenharmony_ci * to do when the structure is freed, add it here. 6362306a36Sopenharmony_ci */ 6462306a36Sopenharmony_ciSTATIC void 6562306a36Sopenharmony_cixfs_trans_free( 6662306a36Sopenharmony_ci struct xfs_trans *tp) 6762306a36Sopenharmony_ci{ 6862306a36Sopenharmony_ci xfs_extent_busy_sort(&tp->t_busy); 6962306a36Sopenharmony_ci xfs_extent_busy_clear(tp->t_mountp, &tp->t_busy, false); 7062306a36Sopenharmony_ci 7162306a36Sopenharmony_ci trace_xfs_trans_free(tp, _RET_IP_); 7262306a36Sopenharmony_ci xfs_trans_clear_context(tp); 7362306a36Sopenharmony_ci if (!(tp->t_flags & XFS_TRANS_NO_WRITECOUNT)) 7462306a36Sopenharmony_ci sb_end_intwrite(tp->t_mountp->m_super); 7562306a36Sopenharmony_ci xfs_trans_free_dqinfo(tp); 7662306a36Sopenharmony_ci kmem_cache_free(xfs_trans_cache, tp); 7762306a36Sopenharmony_ci} 7862306a36Sopenharmony_ci 7962306a36Sopenharmony_ci/* 8062306a36Sopenharmony_ci * This is called to create a new transaction which will share the 8162306a36Sopenharmony_ci * permanent log reservation of the given transaction. The remaining 8262306a36Sopenharmony_ci * unused block and rt extent reservations are also inherited. This 8362306a36Sopenharmony_ci * implies that the original transaction is no longer allowed to allocate 8462306a36Sopenharmony_ci * blocks. Locks and log items, however, are no inherited. They must 8562306a36Sopenharmony_ci * be added to the new transaction explicitly. 8662306a36Sopenharmony_ci */ 8762306a36Sopenharmony_ciSTATIC struct xfs_trans * 8862306a36Sopenharmony_cixfs_trans_dup( 8962306a36Sopenharmony_ci struct xfs_trans *tp) 9062306a36Sopenharmony_ci{ 9162306a36Sopenharmony_ci struct xfs_trans *ntp; 9262306a36Sopenharmony_ci 9362306a36Sopenharmony_ci trace_xfs_trans_dup(tp, _RET_IP_); 9462306a36Sopenharmony_ci 9562306a36Sopenharmony_ci ntp = kmem_cache_zalloc(xfs_trans_cache, GFP_KERNEL | __GFP_NOFAIL); 9662306a36Sopenharmony_ci 9762306a36Sopenharmony_ci /* 9862306a36Sopenharmony_ci * Initialize the new transaction structure. 9962306a36Sopenharmony_ci */ 10062306a36Sopenharmony_ci ntp->t_magic = XFS_TRANS_HEADER_MAGIC; 10162306a36Sopenharmony_ci ntp->t_mountp = tp->t_mountp; 10262306a36Sopenharmony_ci INIT_LIST_HEAD(&ntp->t_items); 10362306a36Sopenharmony_ci INIT_LIST_HEAD(&ntp->t_busy); 10462306a36Sopenharmony_ci INIT_LIST_HEAD(&ntp->t_dfops); 10562306a36Sopenharmony_ci ntp->t_highest_agno = NULLAGNUMBER; 10662306a36Sopenharmony_ci 10762306a36Sopenharmony_ci ASSERT(tp->t_flags & XFS_TRANS_PERM_LOG_RES); 10862306a36Sopenharmony_ci ASSERT(tp->t_ticket != NULL); 10962306a36Sopenharmony_ci 11062306a36Sopenharmony_ci ntp->t_flags = XFS_TRANS_PERM_LOG_RES | 11162306a36Sopenharmony_ci (tp->t_flags & XFS_TRANS_RESERVE) | 11262306a36Sopenharmony_ci (tp->t_flags & XFS_TRANS_NO_WRITECOUNT) | 11362306a36Sopenharmony_ci (tp->t_flags & XFS_TRANS_RES_FDBLKS); 11462306a36Sopenharmony_ci /* We gave our writer reference to the new transaction */ 11562306a36Sopenharmony_ci tp->t_flags |= XFS_TRANS_NO_WRITECOUNT; 11662306a36Sopenharmony_ci ntp->t_ticket = xfs_log_ticket_get(tp->t_ticket); 11762306a36Sopenharmony_ci 11862306a36Sopenharmony_ci ASSERT(tp->t_blk_res >= tp->t_blk_res_used); 11962306a36Sopenharmony_ci ntp->t_blk_res = tp->t_blk_res - tp->t_blk_res_used; 12062306a36Sopenharmony_ci tp->t_blk_res = tp->t_blk_res_used; 12162306a36Sopenharmony_ci 12262306a36Sopenharmony_ci ntp->t_rtx_res = tp->t_rtx_res - tp->t_rtx_res_used; 12362306a36Sopenharmony_ci tp->t_rtx_res = tp->t_rtx_res_used; 12462306a36Sopenharmony_ci 12562306a36Sopenharmony_ci xfs_trans_switch_context(tp, ntp); 12662306a36Sopenharmony_ci 12762306a36Sopenharmony_ci /* move deferred ops over to the new tp */ 12862306a36Sopenharmony_ci xfs_defer_move(ntp, tp); 12962306a36Sopenharmony_ci 13062306a36Sopenharmony_ci xfs_trans_dup_dqinfo(tp, ntp); 13162306a36Sopenharmony_ci return ntp; 13262306a36Sopenharmony_ci} 13362306a36Sopenharmony_ci 13462306a36Sopenharmony_ci/* 13562306a36Sopenharmony_ci * This is called to reserve free disk blocks and log space for the 13662306a36Sopenharmony_ci * given transaction. This must be done before allocating any resources 13762306a36Sopenharmony_ci * within the transaction. 13862306a36Sopenharmony_ci * 13962306a36Sopenharmony_ci * This will return ENOSPC if there are not enough blocks available. 14062306a36Sopenharmony_ci * It will sleep waiting for available log space. 14162306a36Sopenharmony_ci * The only valid value for the flags parameter is XFS_RES_LOG_PERM, which 14262306a36Sopenharmony_ci * is used by long running transactions. If any one of the reservations 14362306a36Sopenharmony_ci * fails then they will all be backed out. 14462306a36Sopenharmony_ci * 14562306a36Sopenharmony_ci * This does not do quota reservations. That typically is done by the 14662306a36Sopenharmony_ci * caller afterwards. 14762306a36Sopenharmony_ci */ 14862306a36Sopenharmony_cistatic int 14962306a36Sopenharmony_cixfs_trans_reserve( 15062306a36Sopenharmony_ci struct xfs_trans *tp, 15162306a36Sopenharmony_ci struct xfs_trans_res *resp, 15262306a36Sopenharmony_ci uint blocks, 15362306a36Sopenharmony_ci uint rtextents) 15462306a36Sopenharmony_ci{ 15562306a36Sopenharmony_ci struct xfs_mount *mp = tp->t_mountp; 15662306a36Sopenharmony_ci int error = 0; 15762306a36Sopenharmony_ci bool rsvd = (tp->t_flags & XFS_TRANS_RESERVE) != 0; 15862306a36Sopenharmony_ci 15962306a36Sopenharmony_ci /* 16062306a36Sopenharmony_ci * Attempt to reserve the needed disk blocks by decrementing 16162306a36Sopenharmony_ci * the number needed from the number available. This will 16262306a36Sopenharmony_ci * fail if the count would go below zero. 16362306a36Sopenharmony_ci */ 16462306a36Sopenharmony_ci if (blocks > 0) { 16562306a36Sopenharmony_ci error = xfs_mod_fdblocks(mp, -((int64_t)blocks), rsvd); 16662306a36Sopenharmony_ci if (error != 0) 16762306a36Sopenharmony_ci return -ENOSPC; 16862306a36Sopenharmony_ci tp->t_blk_res += blocks; 16962306a36Sopenharmony_ci } 17062306a36Sopenharmony_ci 17162306a36Sopenharmony_ci /* 17262306a36Sopenharmony_ci * Reserve the log space needed for this transaction. 17362306a36Sopenharmony_ci */ 17462306a36Sopenharmony_ci if (resp->tr_logres > 0) { 17562306a36Sopenharmony_ci bool permanent = false; 17662306a36Sopenharmony_ci 17762306a36Sopenharmony_ci ASSERT(tp->t_log_res == 0 || 17862306a36Sopenharmony_ci tp->t_log_res == resp->tr_logres); 17962306a36Sopenharmony_ci ASSERT(tp->t_log_count == 0 || 18062306a36Sopenharmony_ci tp->t_log_count == resp->tr_logcount); 18162306a36Sopenharmony_ci 18262306a36Sopenharmony_ci if (resp->tr_logflags & XFS_TRANS_PERM_LOG_RES) { 18362306a36Sopenharmony_ci tp->t_flags |= XFS_TRANS_PERM_LOG_RES; 18462306a36Sopenharmony_ci permanent = true; 18562306a36Sopenharmony_ci } else { 18662306a36Sopenharmony_ci ASSERT(tp->t_ticket == NULL); 18762306a36Sopenharmony_ci ASSERT(!(tp->t_flags & XFS_TRANS_PERM_LOG_RES)); 18862306a36Sopenharmony_ci } 18962306a36Sopenharmony_ci 19062306a36Sopenharmony_ci if (tp->t_ticket != NULL) { 19162306a36Sopenharmony_ci ASSERT(resp->tr_logflags & XFS_TRANS_PERM_LOG_RES); 19262306a36Sopenharmony_ci error = xfs_log_regrant(mp, tp->t_ticket); 19362306a36Sopenharmony_ci } else { 19462306a36Sopenharmony_ci error = xfs_log_reserve(mp, resp->tr_logres, 19562306a36Sopenharmony_ci resp->tr_logcount, 19662306a36Sopenharmony_ci &tp->t_ticket, permanent); 19762306a36Sopenharmony_ci } 19862306a36Sopenharmony_ci 19962306a36Sopenharmony_ci if (error) 20062306a36Sopenharmony_ci goto undo_blocks; 20162306a36Sopenharmony_ci 20262306a36Sopenharmony_ci tp->t_log_res = resp->tr_logres; 20362306a36Sopenharmony_ci tp->t_log_count = resp->tr_logcount; 20462306a36Sopenharmony_ci } 20562306a36Sopenharmony_ci 20662306a36Sopenharmony_ci /* 20762306a36Sopenharmony_ci * Attempt to reserve the needed realtime extents by decrementing 20862306a36Sopenharmony_ci * the number needed from the number available. This will 20962306a36Sopenharmony_ci * fail if the count would go below zero. 21062306a36Sopenharmony_ci */ 21162306a36Sopenharmony_ci if (rtextents > 0) { 21262306a36Sopenharmony_ci error = xfs_mod_frextents(mp, -((int64_t)rtextents)); 21362306a36Sopenharmony_ci if (error) { 21462306a36Sopenharmony_ci error = -ENOSPC; 21562306a36Sopenharmony_ci goto undo_log; 21662306a36Sopenharmony_ci } 21762306a36Sopenharmony_ci tp->t_rtx_res += rtextents; 21862306a36Sopenharmony_ci } 21962306a36Sopenharmony_ci 22062306a36Sopenharmony_ci return 0; 22162306a36Sopenharmony_ci 22262306a36Sopenharmony_ci /* 22362306a36Sopenharmony_ci * Error cases jump to one of these labels to undo any 22462306a36Sopenharmony_ci * reservations which have already been performed. 22562306a36Sopenharmony_ci */ 22662306a36Sopenharmony_ciundo_log: 22762306a36Sopenharmony_ci if (resp->tr_logres > 0) { 22862306a36Sopenharmony_ci xfs_log_ticket_ungrant(mp->m_log, tp->t_ticket); 22962306a36Sopenharmony_ci tp->t_ticket = NULL; 23062306a36Sopenharmony_ci tp->t_log_res = 0; 23162306a36Sopenharmony_ci tp->t_flags &= ~XFS_TRANS_PERM_LOG_RES; 23262306a36Sopenharmony_ci } 23362306a36Sopenharmony_ci 23462306a36Sopenharmony_ciundo_blocks: 23562306a36Sopenharmony_ci if (blocks > 0) { 23662306a36Sopenharmony_ci xfs_mod_fdblocks(mp, (int64_t)blocks, rsvd); 23762306a36Sopenharmony_ci tp->t_blk_res = 0; 23862306a36Sopenharmony_ci } 23962306a36Sopenharmony_ci return error; 24062306a36Sopenharmony_ci} 24162306a36Sopenharmony_ci 24262306a36Sopenharmony_ciint 24362306a36Sopenharmony_cixfs_trans_alloc( 24462306a36Sopenharmony_ci struct xfs_mount *mp, 24562306a36Sopenharmony_ci struct xfs_trans_res *resp, 24662306a36Sopenharmony_ci uint blocks, 24762306a36Sopenharmony_ci uint rtextents, 24862306a36Sopenharmony_ci uint flags, 24962306a36Sopenharmony_ci struct xfs_trans **tpp) 25062306a36Sopenharmony_ci{ 25162306a36Sopenharmony_ci struct xfs_trans *tp; 25262306a36Sopenharmony_ci bool want_retry = true; 25362306a36Sopenharmony_ci int error; 25462306a36Sopenharmony_ci 25562306a36Sopenharmony_ci /* 25662306a36Sopenharmony_ci * Allocate the handle before we do our freeze accounting and setting up 25762306a36Sopenharmony_ci * GFP_NOFS allocation context so that we avoid lockdep false positives 25862306a36Sopenharmony_ci * by doing GFP_KERNEL allocations inside sb_start_intwrite(). 25962306a36Sopenharmony_ci */ 26062306a36Sopenharmony_ciretry: 26162306a36Sopenharmony_ci tp = kmem_cache_zalloc(xfs_trans_cache, GFP_KERNEL | __GFP_NOFAIL); 26262306a36Sopenharmony_ci if (!(flags & XFS_TRANS_NO_WRITECOUNT)) 26362306a36Sopenharmony_ci sb_start_intwrite(mp->m_super); 26462306a36Sopenharmony_ci xfs_trans_set_context(tp); 26562306a36Sopenharmony_ci 26662306a36Sopenharmony_ci /* 26762306a36Sopenharmony_ci * Zero-reservation ("empty") transactions can't modify anything, so 26862306a36Sopenharmony_ci * they're allowed to run while we're frozen. 26962306a36Sopenharmony_ci */ 27062306a36Sopenharmony_ci WARN_ON(resp->tr_logres > 0 && 27162306a36Sopenharmony_ci mp->m_super->s_writers.frozen == SB_FREEZE_COMPLETE); 27262306a36Sopenharmony_ci ASSERT(!(flags & XFS_TRANS_RES_FDBLKS) || 27362306a36Sopenharmony_ci xfs_has_lazysbcount(mp)); 27462306a36Sopenharmony_ci 27562306a36Sopenharmony_ci tp->t_magic = XFS_TRANS_HEADER_MAGIC; 27662306a36Sopenharmony_ci tp->t_flags = flags; 27762306a36Sopenharmony_ci tp->t_mountp = mp; 27862306a36Sopenharmony_ci INIT_LIST_HEAD(&tp->t_items); 27962306a36Sopenharmony_ci INIT_LIST_HEAD(&tp->t_busy); 28062306a36Sopenharmony_ci INIT_LIST_HEAD(&tp->t_dfops); 28162306a36Sopenharmony_ci tp->t_highest_agno = NULLAGNUMBER; 28262306a36Sopenharmony_ci 28362306a36Sopenharmony_ci error = xfs_trans_reserve(tp, resp, blocks, rtextents); 28462306a36Sopenharmony_ci if (error == -ENOSPC && want_retry) { 28562306a36Sopenharmony_ci xfs_trans_cancel(tp); 28662306a36Sopenharmony_ci 28762306a36Sopenharmony_ci /* 28862306a36Sopenharmony_ci * We weren't able to reserve enough space for the transaction. 28962306a36Sopenharmony_ci * Flush the other speculative space allocations to free space. 29062306a36Sopenharmony_ci * Do not perform a synchronous scan because callers can hold 29162306a36Sopenharmony_ci * other locks. 29262306a36Sopenharmony_ci */ 29362306a36Sopenharmony_ci error = xfs_blockgc_flush_all(mp); 29462306a36Sopenharmony_ci if (error) 29562306a36Sopenharmony_ci return error; 29662306a36Sopenharmony_ci want_retry = false; 29762306a36Sopenharmony_ci goto retry; 29862306a36Sopenharmony_ci } 29962306a36Sopenharmony_ci if (error) { 30062306a36Sopenharmony_ci xfs_trans_cancel(tp); 30162306a36Sopenharmony_ci return error; 30262306a36Sopenharmony_ci } 30362306a36Sopenharmony_ci 30462306a36Sopenharmony_ci trace_xfs_trans_alloc(tp, _RET_IP_); 30562306a36Sopenharmony_ci 30662306a36Sopenharmony_ci *tpp = tp; 30762306a36Sopenharmony_ci return 0; 30862306a36Sopenharmony_ci} 30962306a36Sopenharmony_ci 31062306a36Sopenharmony_ci/* 31162306a36Sopenharmony_ci * Create an empty transaction with no reservation. This is a defensive 31262306a36Sopenharmony_ci * mechanism for routines that query metadata without actually modifying them -- 31362306a36Sopenharmony_ci * if the metadata being queried is somehow cross-linked (think a btree block 31462306a36Sopenharmony_ci * pointer that points higher in the tree), we risk deadlock. However, blocks 31562306a36Sopenharmony_ci * grabbed as part of a transaction can be re-grabbed. The verifiers will 31662306a36Sopenharmony_ci * notice the corrupt block and the operation will fail back to userspace 31762306a36Sopenharmony_ci * without deadlocking. 31862306a36Sopenharmony_ci * 31962306a36Sopenharmony_ci * Note the zero-length reservation; this transaction MUST be cancelled without 32062306a36Sopenharmony_ci * any dirty data. 32162306a36Sopenharmony_ci * 32262306a36Sopenharmony_ci * Callers should obtain freeze protection to avoid a conflict with fs freezing 32362306a36Sopenharmony_ci * where we can be grabbing buffers at the same time that freeze is trying to 32462306a36Sopenharmony_ci * drain the buffer LRU list. 32562306a36Sopenharmony_ci */ 32662306a36Sopenharmony_ciint 32762306a36Sopenharmony_cixfs_trans_alloc_empty( 32862306a36Sopenharmony_ci struct xfs_mount *mp, 32962306a36Sopenharmony_ci struct xfs_trans **tpp) 33062306a36Sopenharmony_ci{ 33162306a36Sopenharmony_ci struct xfs_trans_res resv = {0}; 33262306a36Sopenharmony_ci 33362306a36Sopenharmony_ci return xfs_trans_alloc(mp, &resv, 0, 0, XFS_TRANS_NO_WRITECOUNT, tpp); 33462306a36Sopenharmony_ci} 33562306a36Sopenharmony_ci 33662306a36Sopenharmony_ci/* 33762306a36Sopenharmony_ci * Record the indicated change to the given field for application 33862306a36Sopenharmony_ci * to the file system's superblock when the transaction commits. 33962306a36Sopenharmony_ci * For now, just store the change in the transaction structure. 34062306a36Sopenharmony_ci * 34162306a36Sopenharmony_ci * Mark the transaction structure to indicate that the superblock 34262306a36Sopenharmony_ci * needs to be updated before committing. 34362306a36Sopenharmony_ci * 34462306a36Sopenharmony_ci * Because we may not be keeping track of allocated/free inodes and 34562306a36Sopenharmony_ci * used filesystem blocks in the superblock, we do not mark the 34662306a36Sopenharmony_ci * superblock dirty in this transaction if we modify these fields. 34762306a36Sopenharmony_ci * We still need to update the transaction deltas so that they get 34862306a36Sopenharmony_ci * applied to the incore superblock, but we don't want them to 34962306a36Sopenharmony_ci * cause the superblock to get locked and logged if these are the 35062306a36Sopenharmony_ci * only fields in the superblock that the transaction modifies. 35162306a36Sopenharmony_ci */ 35262306a36Sopenharmony_civoid 35362306a36Sopenharmony_cixfs_trans_mod_sb( 35462306a36Sopenharmony_ci xfs_trans_t *tp, 35562306a36Sopenharmony_ci uint field, 35662306a36Sopenharmony_ci int64_t delta) 35762306a36Sopenharmony_ci{ 35862306a36Sopenharmony_ci uint32_t flags = (XFS_TRANS_DIRTY|XFS_TRANS_SB_DIRTY); 35962306a36Sopenharmony_ci xfs_mount_t *mp = tp->t_mountp; 36062306a36Sopenharmony_ci 36162306a36Sopenharmony_ci switch (field) { 36262306a36Sopenharmony_ci case XFS_TRANS_SB_ICOUNT: 36362306a36Sopenharmony_ci tp->t_icount_delta += delta; 36462306a36Sopenharmony_ci if (xfs_has_lazysbcount(mp)) 36562306a36Sopenharmony_ci flags &= ~XFS_TRANS_SB_DIRTY; 36662306a36Sopenharmony_ci break; 36762306a36Sopenharmony_ci case XFS_TRANS_SB_IFREE: 36862306a36Sopenharmony_ci tp->t_ifree_delta += delta; 36962306a36Sopenharmony_ci if (xfs_has_lazysbcount(mp)) 37062306a36Sopenharmony_ci flags &= ~XFS_TRANS_SB_DIRTY; 37162306a36Sopenharmony_ci break; 37262306a36Sopenharmony_ci case XFS_TRANS_SB_FDBLOCKS: 37362306a36Sopenharmony_ci /* 37462306a36Sopenharmony_ci * Track the number of blocks allocated in the transaction. 37562306a36Sopenharmony_ci * Make sure it does not exceed the number reserved. If so, 37662306a36Sopenharmony_ci * shutdown as this can lead to accounting inconsistency. 37762306a36Sopenharmony_ci */ 37862306a36Sopenharmony_ci if (delta < 0) { 37962306a36Sopenharmony_ci tp->t_blk_res_used += (uint)-delta; 38062306a36Sopenharmony_ci if (tp->t_blk_res_used > tp->t_blk_res) 38162306a36Sopenharmony_ci xfs_force_shutdown(mp, SHUTDOWN_CORRUPT_INCORE); 38262306a36Sopenharmony_ci } else if (delta > 0 && (tp->t_flags & XFS_TRANS_RES_FDBLKS)) { 38362306a36Sopenharmony_ci int64_t blkres_delta; 38462306a36Sopenharmony_ci 38562306a36Sopenharmony_ci /* 38662306a36Sopenharmony_ci * Return freed blocks directly to the reservation 38762306a36Sopenharmony_ci * instead of the global pool, being careful not to 38862306a36Sopenharmony_ci * overflow the trans counter. This is used to preserve 38962306a36Sopenharmony_ci * reservation across chains of transaction rolls that 39062306a36Sopenharmony_ci * repeatedly free and allocate blocks. 39162306a36Sopenharmony_ci */ 39262306a36Sopenharmony_ci blkres_delta = min_t(int64_t, delta, 39362306a36Sopenharmony_ci UINT_MAX - tp->t_blk_res); 39462306a36Sopenharmony_ci tp->t_blk_res += blkres_delta; 39562306a36Sopenharmony_ci delta -= blkres_delta; 39662306a36Sopenharmony_ci } 39762306a36Sopenharmony_ci tp->t_fdblocks_delta += delta; 39862306a36Sopenharmony_ci if (xfs_has_lazysbcount(mp)) 39962306a36Sopenharmony_ci flags &= ~XFS_TRANS_SB_DIRTY; 40062306a36Sopenharmony_ci break; 40162306a36Sopenharmony_ci case XFS_TRANS_SB_RES_FDBLOCKS: 40262306a36Sopenharmony_ci /* 40362306a36Sopenharmony_ci * The allocation has already been applied to the 40462306a36Sopenharmony_ci * in-core superblock's counter. This should only 40562306a36Sopenharmony_ci * be applied to the on-disk superblock. 40662306a36Sopenharmony_ci */ 40762306a36Sopenharmony_ci tp->t_res_fdblocks_delta += delta; 40862306a36Sopenharmony_ci if (xfs_has_lazysbcount(mp)) 40962306a36Sopenharmony_ci flags &= ~XFS_TRANS_SB_DIRTY; 41062306a36Sopenharmony_ci break; 41162306a36Sopenharmony_ci case XFS_TRANS_SB_FREXTENTS: 41262306a36Sopenharmony_ci /* 41362306a36Sopenharmony_ci * Track the number of blocks allocated in the 41462306a36Sopenharmony_ci * transaction. Make sure it does not exceed the 41562306a36Sopenharmony_ci * number reserved. 41662306a36Sopenharmony_ci */ 41762306a36Sopenharmony_ci if (delta < 0) { 41862306a36Sopenharmony_ci tp->t_rtx_res_used += (uint)-delta; 41962306a36Sopenharmony_ci ASSERT(tp->t_rtx_res_used <= tp->t_rtx_res); 42062306a36Sopenharmony_ci } 42162306a36Sopenharmony_ci tp->t_frextents_delta += delta; 42262306a36Sopenharmony_ci break; 42362306a36Sopenharmony_ci case XFS_TRANS_SB_RES_FREXTENTS: 42462306a36Sopenharmony_ci /* 42562306a36Sopenharmony_ci * The allocation has already been applied to the 42662306a36Sopenharmony_ci * in-core superblock's counter. This should only 42762306a36Sopenharmony_ci * be applied to the on-disk superblock. 42862306a36Sopenharmony_ci */ 42962306a36Sopenharmony_ci ASSERT(delta < 0); 43062306a36Sopenharmony_ci tp->t_res_frextents_delta += delta; 43162306a36Sopenharmony_ci break; 43262306a36Sopenharmony_ci case XFS_TRANS_SB_DBLOCKS: 43362306a36Sopenharmony_ci tp->t_dblocks_delta += delta; 43462306a36Sopenharmony_ci break; 43562306a36Sopenharmony_ci case XFS_TRANS_SB_AGCOUNT: 43662306a36Sopenharmony_ci ASSERT(delta > 0); 43762306a36Sopenharmony_ci tp->t_agcount_delta += delta; 43862306a36Sopenharmony_ci break; 43962306a36Sopenharmony_ci case XFS_TRANS_SB_IMAXPCT: 44062306a36Sopenharmony_ci tp->t_imaxpct_delta += delta; 44162306a36Sopenharmony_ci break; 44262306a36Sopenharmony_ci case XFS_TRANS_SB_REXTSIZE: 44362306a36Sopenharmony_ci tp->t_rextsize_delta += delta; 44462306a36Sopenharmony_ci break; 44562306a36Sopenharmony_ci case XFS_TRANS_SB_RBMBLOCKS: 44662306a36Sopenharmony_ci tp->t_rbmblocks_delta += delta; 44762306a36Sopenharmony_ci break; 44862306a36Sopenharmony_ci case XFS_TRANS_SB_RBLOCKS: 44962306a36Sopenharmony_ci tp->t_rblocks_delta += delta; 45062306a36Sopenharmony_ci break; 45162306a36Sopenharmony_ci case XFS_TRANS_SB_REXTENTS: 45262306a36Sopenharmony_ci tp->t_rextents_delta += delta; 45362306a36Sopenharmony_ci break; 45462306a36Sopenharmony_ci case XFS_TRANS_SB_REXTSLOG: 45562306a36Sopenharmony_ci tp->t_rextslog_delta += delta; 45662306a36Sopenharmony_ci break; 45762306a36Sopenharmony_ci default: 45862306a36Sopenharmony_ci ASSERT(0); 45962306a36Sopenharmony_ci return; 46062306a36Sopenharmony_ci } 46162306a36Sopenharmony_ci 46262306a36Sopenharmony_ci tp->t_flags |= flags; 46362306a36Sopenharmony_ci} 46462306a36Sopenharmony_ci 46562306a36Sopenharmony_ci/* 46662306a36Sopenharmony_ci * xfs_trans_apply_sb_deltas() is called from the commit code 46762306a36Sopenharmony_ci * to bring the superblock buffer into the current transaction 46862306a36Sopenharmony_ci * and modify it as requested by earlier calls to xfs_trans_mod_sb(). 46962306a36Sopenharmony_ci * 47062306a36Sopenharmony_ci * For now we just look at each field allowed to change and change 47162306a36Sopenharmony_ci * it if necessary. 47262306a36Sopenharmony_ci */ 47362306a36Sopenharmony_ciSTATIC void 47462306a36Sopenharmony_cixfs_trans_apply_sb_deltas( 47562306a36Sopenharmony_ci xfs_trans_t *tp) 47662306a36Sopenharmony_ci{ 47762306a36Sopenharmony_ci struct xfs_dsb *sbp; 47862306a36Sopenharmony_ci struct xfs_buf *bp; 47962306a36Sopenharmony_ci int whole = 0; 48062306a36Sopenharmony_ci 48162306a36Sopenharmony_ci bp = xfs_trans_getsb(tp); 48262306a36Sopenharmony_ci sbp = bp->b_addr; 48362306a36Sopenharmony_ci 48462306a36Sopenharmony_ci /* 48562306a36Sopenharmony_ci * Only update the superblock counters if we are logging them 48662306a36Sopenharmony_ci */ 48762306a36Sopenharmony_ci if (!xfs_has_lazysbcount((tp->t_mountp))) { 48862306a36Sopenharmony_ci if (tp->t_icount_delta) 48962306a36Sopenharmony_ci be64_add_cpu(&sbp->sb_icount, tp->t_icount_delta); 49062306a36Sopenharmony_ci if (tp->t_ifree_delta) 49162306a36Sopenharmony_ci be64_add_cpu(&sbp->sb_ifree, tp->t_ifree_delta); 49262306a36Sopenharmony_ci if (tp->t_fdblocks_delta) 49362306a36Sopenharmony_ci be64_add_cpu(&sbp->sb_fdblocks, tp->t_fdblocks_delta); 49462306a36Sopenharmony_ci if (tp->t_res_fdblocks_delta) 49562306a36Sopenharmony_ci be64_add_cpu(&sbp->sb_fdblocks, tp->t_res_fdblocks_delta); 49662306a36Sopenharmony_ci } 49762306a36Sopenharmony_ci 49862306a36Sopenharmony_ci /* 49962306a36Sopenharmony_ci * Updating frextents requires careful handling because it does not 50062306a36Sopenharmony_ci * behave like the lazysb counters because we cannot rely on log 50162306a36Sopenharmony_ci * recovery in older kenels to recompute the value from the rtbitmap. 50262306a36Sopenharmony_ci * This means that the ondisk frextents must be consistent with the 50362306a36Sopenharmony_ci * rtbitmap. 50462306a36Sopenharmony_ci * 50562306a36Sopenharmony_ci * Therefore, log the frextents change to the ondisk superblock and 50662306a36Sopenharmony_ci * update the incore superblock so that future calls to xfs_log_sb 50762306a36Sopenharmony_ci * write the correct value ondisk. 50862306a36Sopenharmony_ci * 50962306a36Sopenharmony_ci * Don't touch m_frextents because it includes incore reservations, 51062306a36Sopenharmony_ci * and those are handled by the unreserve function. 51162306a36Sopenharmony_ci */ 51262306a36Sopenharmony_ci if (tp->t_frextents_delta || tp->t_res_frextents_delta) { 51362306a36Sopenharmony_ci struct xfs_mount *mp = tp->t_mountp; 51462306a36Sopenharmony_ci int64_t rtxdelta; 51562306a36Sopenharmony_ci 51662306a36Sopenharmony_ci rtxdelta = tp->t_frextents_delta + tp->t_res_frextents_delta; 51762306a36Sopenharmony_ci 51862306a36Sopenharmony_ci spin_lock(&mp->m_sb_lock); 51962306a36Sopenharmony_ci be64_add_cpu(&sbp->sb_frextents, rtxdelta); 52062306a36Sopenharmony_ci mp->m_sb.sb_frextents += rtxdelta; 52162306a36Sopenharmony_ci spin_unlock(&mp->m_sb_lock); 52262306a36Sopenharmony_ci } 52362306a36Sopenharmony_ci 52462306a36Sopenharmony_ci if (tp->t_dblocks_delta) { 52562306a36Sopenharmony_ci be64_add_cpu(&sbp->sb_dblocks, tp->t_dblocks_delta); 52662306a36Sopenharmony_ci whole = 1; 52762306a36Sopenharmony_ci } 52862306a36Sopenharmony_ci if (tp->t_agcount_delta) { 52962306a36Sopenharmony_ci be32_add_cpu(&sbp->sb_agcount, tp->t_agcount_delta); 53062306a36Sopenharmony_ci whole = 1; 53162306a36Sopenharmony_ci } 53262306a36Sopenharmony_ci if (tp->t_imaxpct_delta) { 53362306a36Sopenharmony_ci sbp->sb_imax_pct += tp->t_imaxpct_delta; 53462306a36Sopenharmony_ci whole = 1; 53562306a36Sopenharmony_ci } 53662306a36Sopenharmony_ci if (tp->t_rextsize_delta) { 53762306a36Sopenharmony_ci be32_add_cpu(&sbp->sb_rextsize, tp->t_rextsize_delta); 53862306a36Sopenharmony_ci whole = 1; 53962306a36Sopenharmony_ci } 54062306a36Sopenharmony_ci if (tp->t_rbmblocks_delta) { 54162306a36Sopenharmony_ci be32_add_cpu(&sbp->sb_rbmblocks, tp->t_rbmblocks_delta); 54262306a36Sopenharmony_ci whole = 1; 54362306a36Sopenharmony_ci } 54462306a36Sopenharmony_ci if (tp->t_rblocks_delta) { 54562306a36Sopenharmony_ci be64_add_cpu(&sbp->sb_rblocks, tp->t_rblocks_delta); 54662306a36Sopenharmony_ci whole = 1; 54762306a36Sopenharmony_ci } 54862306a36Sopenharmony_ci if (tp->t_rextents_delta) { 54962306a36Sopenharmony_ci be64_add_cpu(&sbp->sb_rextents, tp->t_rextents_delta); 55062306a36Sopenharmony_ci whole = 1; 55162306a36Sopenharmony_ci } 55262306a36Sopenharmony_ci if (tp->t_rextslog_delta) { 55362306a36Sopenharmony_ci sbp->sb_rextslog += tp->t_rextslog_delta; 55462306a36Sopenharmony_ci whole = 1; 55562306a36Sopenharmony_ci } 55662306a36Sopenharmony_ci 55762306a36Sopenharmony_ci xfs_trans_buf_set_type(tp, bp, XFS_BLFT_SB_BUF); 55862306a36Sopenharmony_ci if (whole) 55962306a36Sopenharmony_ci /* 56062306a36Sopenharmony_ci * Log the whole thing, the fields are noncontiguous. 56162306a36Sopenharmony_ci */ 56262306a36Sopenharmony_ci xfs_trans_log_buf(tp, bp, 0, sizeof(struct xfs_dsb) - 1); 56362306a36Sopenharmony_ci else 56462306a36Sopenharmony_ci /* 56562306a36Sopenharmony_ci * Since all the modifiable fields are contiguous, we 56662306a36Sopenharmony_ci * can get away with this. 56762306a36Sopenharmony_ci */ 56862306a36Sopenharmony_ci xfs_trans_log_buf(tp, bp, offsetof(struct xfs_dsb, sb_icount), 56962306a36Sopenharmony_ci offsetof(struct xfs_dsb, sb_frextents) + 57062306a36Sopenharmony_ci sizeof(sbp->sb_frextents) - 1); 57162306a36Sopenharmony_ci} 57262306a36Sopenharmony_ci 57362306a36Sopenharmony_ci/* 57462306a36Sopenharmony_ci * xfs_trans_unreserve_and_mod_sb() is called to release unused reservations and 57562306a36Sopenharmony_ci * apply superblock counter changes to the in-core superblock. The 57662306a36Sopenharmony_ci * t_res_fdblocks_delta and t_res_frextents_delta fields are explicitly NOT 57762306a36Sopenharmony_ci * applied to the in-core superblock. The idea is that that has already been 57862306a36Sopenharmony_ci * done. 57962306a36Sopenharmony_ci * 58062306a36Sopenharmony_ci * If we are not logging superblock counters, then the inode allocated/free and 58162306a36Sopenharmony_ci * used block counts are not updated in the on disk superblock. In this case, 58262306a36Sopenharmony_ci * XFS_TRANS_SB_DIRTY will not be set when the transaction is updated but we 58362306a36Sopenharmony_ci * still need to update the incore superblock with the changes. 58462306a36Sopenharmony_ci * 58562306a36Sopenharmony_ci * Deltas for the inode count are +/-64, hence we use a large batch size of 128 58662306a36Sopenharmony_ci * so we don't need to take the counter lock on every update. 58762306a36Sopenharmony_ci */ 58862306a36Sopenharmony_ci#define XFS_ICOUNT_BATCH 128 58962306a36Sopenharmony_ci 59062306a36Sopenharmony_civoid 59162306a36Sopenharmony_cixfs_trans_unreserve_and_mod_sb( 59262306a36Sopenharmony_ci struct xfs_trans *tp) 59362306a36Sopenharmony_ci{ 59462306a36Sopenharmony_ci struct xfs_mount *mp = tp->t_mountp; 59562306a36Sopenharmony_ci bool rsvd = (tp->t_flags & XFS_TRANS_RESERVE) != 0; 59662306a36Sopenharmony_ci int64_t blkdelta = 0; 59762306a36Sopenharmony_ci int64_t rtxdelta = 0; 59862306a36Sopenharmony_ci int64_t idelta = 0; 59962306a36Sopenharmony_ci int64_t ifreedelta = 0; 60062306a36Sopenharmony_ci int error; 60162306a36Sopenharmony_ci 60262306a36Sopenharmony_ci /* calculate deltas */ 60362306a36Sopenharmony_ci if (tp->t_blk_res > 0) 60462306a36Sopenharmony_ci blkdelta = tp->t_blk_res; 60562306a36Sopenharmony_ci if ((tp->t_fdblocks_delta != 0) && 60662306a36Sopenharmony_ci (xfs_has_lazysbcount(mp) || 60762306a36Sopenharmony_ci (tp->t_flags & XFS_TRANS_SB_DIRTY))) 60862306a36Sopenharmony_ci blkdelta += tp->t_fdblocks_delta; 60962306a36Sopenharmony_ci 61062306a36Sopenharmony_ci if (tp->t_rtx_res > 0) 61162306a36Sopenharmony_ci rtxdelta = tp->t_rtx_res; 61262306a36Sopenharmony_ci if ((tp->t_frextents_delta != 0) && 61362306a36Sopenharmony_ci (tp->t_flags & XFS_TRANS_SB_DIRTY)) 61462306a36Sopenharmony_ci rtxdelta += tp->t_frextents_delta; 61562306a36Sopenharmony_ci 61662306a36Sopenharmony_ci if (xfs_has_lazysbcount(mp) || 61762306a36Sopenharmony_ci (tp->t_flags & XFS_TRANS_SB_DIRTY)) { 61862306a36Sopenharmony_ci idelta = tp->t_icount_delta; 61962306a36Sopenharmony_ci ifreedelta = tp->t_ifree_delta; 62062306a36Sopenharmony_ci } 62162306a36Sopenharmony_ci 62262306a36Sopenharmony_ci /* apply the per-cpu counters */ 62362306a36Sopenharmony_ci if (blkdelta) { 62462306a36Sopenharmony_ci error = xfs_mod_fdblocks(mp, blkdelta, rsvd); 62562306a36Sopenharmony_ci ASSERT(!error); 62662306a36Sopenharmony_ci } 62762306a36Sopenharmony_ci 62862306a36Sopenharmony_ci if (idelta) 62962306a36Sopenharmony_ci percpu_counter_add_batch(&mp->m_icount, idelta, 63062306a36Sopenharmony_ci XFS_ICOUNT_BATCH); 63162306a36Sopenharmony_ci 63262306a36Sopenharmony_ci if (ifreedelta) 63362306a36Sopenharmony_ci percpu_counter_add(&mp->m_ifree, ifreedelta); 63462306a36Sopenharmony_ci 63562306a36Sopenharmony_ci if (rtxdelta) { 63662306a36Sopenharmony_ci error = xfs_mod_frextents(mp, rtxdelta); 63762306a36Sopenharmony_ci ASSERT(!error); 63862306a36Sopenharmony_ci } 63962306a36Sopenharmony_ci 64062306a36Sopenharmony_ci if (!(tp->t_flags & XFS_TRANS_SB_DIRTY)) 64162306a36Sopenharmony_ci return; 64262306a36Sopenharmony_ci 64362306a36Sopenharmony_ci /* apply remaining deltas */ 64462306a36Sopenharmony_ci spin_lock(&mp->m_sb_lock); 64562306a36Sopenharmony_ci mp->m_sb.sb_fdblocks += tp->t_fdblocks_delta + tp->t_res_fdblocks_delta; 64662306a36Sopenharmony_ci mp->m_sb.sb_icount += idelta; 64762306a36Sopenharmony_ci mp->m_sb.sb_ifree += ifreedelta; 64862306a36Sopenharmony_ci /* 64962306a36Sopenharmony_ci * Do not touch sb_frextents here because we are dealing with incore 65062306a36Sopenharmony_ci * reservation. sb_frextents is not part of the lazy sb counters so it 65162306a36Sopenharmony_ci * must be consistent with the ondisk rtbitmap and must never include 65262306a36Sopenharmony_ci * incore reservations. 65362306a36Sopenharmony_ci */ 65462306a36Sopenharmony_ci mp->m_sb.sb_dblocks += tp->t_dblocks_delta; 65562306a36Sopenharmony_ci mp->m_sb.sb_agcount += tp->t_agcount_delta; 65662306a36Sopenharmony_ci mp->m_sb.sb_imax_pct += tp->t_imaxpct_delta; 65762306a36Sopenharmony_ci mp->m_sb.sb_rextsize += tp->t_rextsize_delta; 65862306a36Sopenharmony_ci mp->m_sb.sb_rbmblocks += tp->t_rbmblocks_delta; 65962306a36Sopenharmony_ci mp->m_sb.sb_rblocks += tp->t_rblocks_delta; 66062306a36Sopenharmony_ci mp->m_sb.sb_rextents += tp->t_rextents_delta; 66162306a36Sopenharmony_ci mp->m_sb.sb_rextslog += tp->t_rextslog_delta; 66262306a36Sopenharmony_ci spin_unlock(&mp->m_sb_lock); 66362306a36Sopenharmony_ci 66462306a36Sopenharmony_ci /* 66562306a36Sopenharmony_ci * Debug checks outside of the spinlock so they don't lock up the 66662306a36Sopenharmony_ci * machine if they fail. 66762306a36Sopenharmony_ci */ 66862306a36Sopenharmony_ci ASSERT(mp->m_sb.sb_imax_pct >= 0); 66962306a36Sopenharmony_ci ASSERT(mp->m_sb.sb_rextslog >= 0); 67062306a36Sopenharmony_ci return; 67162306a36Sopenharmony_ci} 67262306a36Sopenharmony_ci 67362306a36Sopenharmony_ci/* Add the given log item to the transaction's list of log items. */ 67462306a36Sopenharmony_civoid 67562306a36Sopenharmony_cixfs_trans_add_item( 67662306a36Sopenharmony_ci struct xfs_trans *tp, 67762306a36Sopenharmony_ci struct xfs_log_item *lip) 67862306a36Sopenharmony_ci{ 67962306a36Sopenharmony_ci ASSERT(lip->li_log == tp->t_mountp->m_log); 68062306a36Sopenharmony_ci ASSERT(lip->li_ailp == tp->t_mountp->m_ail); 68162306a36Sopenharmony_ci ASSERT(list_empty(&lip->li_trans)); 68262306a36Sopenharmony_ci ASSERT(!test_bit(XFS_LI_DIRTY, &lip->li_flags)); 68362306a36Sopenharmony_ci 68462306a36Sopenharmony_ci list_add_tail(&lip->li_trans, &tp->t_items); 68562306a36Sopenharmony_ci trace_xfs_trans_add_item(tp, _RET_IP_); 68662306a36Sopenharmony_ci} 68762306a36Sopenharmony_ci 68862306a36Sopenharmony_ci/* 68962306a36Sopenharmony_ci * Unlink the log item from the transaction. the log item is no longer 69062306a36Sopenharmony_ci * considered dirty in this transaction, as the linked transaction has 69162306a36Sopenharmony_ci * finished, either by abort or commit completion. 69262306a36Sopenharmony_ci */ 69362306a36Sopenharmony_civoid 69462306a36Sopenharmony_cixfs_trans_del_item( 69562306a36Sopenharmony_ci struct xfs_log_item *lip) 69662306a36Sopenharmony_ci{ 69762306a36Sopenharmony_ci clear_bit(XFS_LI_DIRTY, &lip->li_flags); 69862306a36Sopenharmony_ci list_del_init(&lip->li_trans); 69962306a36Sopenharmony_ci} 70062306a36Sopenharmony_ci 70162306a36Sopenharmony_ci/* Detach and unlock all of the items in a transaction */ 70262306a36Sopenharmony_cistatic void 70362306a36Sopenharmony_cixfs_trans_free_items( 70462306a36Sopenharmony_ci struct xfs_trans *tp, 70562306a36Sopenharmony_ci bool abort) 70662306a36Sopenharmony_ci{ 70762306a36Sopenharmony_ci struct xfs_log_item *lip, *next; 70862306a36Sopenharmony_ci 70962306a36Sopenharmony_ci trace_xfs_trans_free_items(tp, _RET_IP_); 71062306a36Sopenharmony_ci 71162306a36Sopenharmony_ci list_for_each_entry_safe(lip, next, &tp->t_items, li_trans) { 71262306a36Sopenharmony_ci xfs_trans_del_item(lip); 71362306a36Sopenharmony_ci if (abort) 71462306a36Sopenharmony_ci set_bit(XFS_LI_ABORTED, &lip->li_flags); 71562306a36Sopenharmony_ci if (lip->li_ops->iop_release) 71662306a36Sopenharmony_ci lip->li_ops->iop_release(lip); 71762306a36Sopenharmony_ci } 71862306a36Sopenharmony_ci} 71962306a36Sopenharmony_ci 72062306a36Sopenharmony_cistatic inline void 72162306a36Sopenharmony_cixfs_log_item_batch_insert( 72262306a36Sopenharmony_ci struct xfs_ail *ailp, 72362306a36Sopenharmony_ci struct xfs_ail_cursor *cur, 72462306a36Sopenharmony_ci struct xfs_log_item **log_items, 72562306a36Sopenharmony_ci int nr_items, 72662306a36Sopenharmony_ci xfs_lsn_t commit_lsn) 72762306a36Sopenharmony_ci{ 72862306a36Sopenharmony_ci int i; 72962306a36Sopenharmony_ci 73062306a36Sopenharmony_ci spin_lock(&ailp->ail_lock); 73162306a36Sopenharmony_ci /* xfs_trans_ail_update_bulk drops ailp->ail_lock */ 73262306a36Sopenharmony_ci xfs_trans_ail_update_bulk(ailp, cur, log_items, nr_items, commit_lsn); 73362306a36Sopenharmony_ci 73462306a36Sopenharmony_ci for (i = 0; i < nr_items; i++) { 73562306a36Sopenharmony_ci struct xfs_log_item *lip = log_items[i]; 73662306a36Sopenharmony_ci 73762306a36Sopenharmony_ci if (lip->li_ops->iop_unpin) 73862306a36Sopenharmony_ci lip->li_ops->iop_unpin(lip, 0); 73962306a36Sopenharmony_ci } 74062306a36Sopenharmony_ci} 74162306a36Sopenharmony_ci 74262306a36Sopenharmony_ci/* 74362306a36Sopenharmony_ci * Bulk operation version of xfs_trans_committed that takes a log vector of 74462306a36Sopenharmony_ci * items to insert into the AIL. This uses bulk AIL insertion techniques to 74562306a36Sopenharmony_ci * minimise lock traffic. 74662306a36Sopenharmony_ci * 74762306a36Sopenharmony_ci * If we are called with the aborted flag set, it is because a log write during 74862306a36Sopenharmony_ci * a CIL checkpoint commit has failed. In this case, all the items in the 74962306a36Sopenharmony_ci * checkpoint have already gone through iop_committed and iop_committing, which 75062306a36Sopenharmony_ci * means that checkpoint commit abort handling is treated exactly the same 75162306a36Sopenharmony_ci * as an iclog write error even though we haven't started any IO yet. Hence in 75262306a36Sopenharmony_ci * this case all we need to do is iop_committed processing, followed by an 75362306a36Sopenharmony_ci * iop_unpin(aborted) call. 75462306a36Sopenharmony_ci * 75562306a36Sopenharmony_ci * The AIL cursor is used to optimise the insert process. If commit_lsn is not 75662306a36Sopenharmony_ci * at the end of the AIL, the insert cursor avoids the need to walk 75762306a36Sopenharmony_ci * the AIL to find the insertion point on every xfs_log_item_batch_insert() 75862306a36Sopenharmony_ci * call. This saves a lot of needless list walking and is a net win, even 75962306a36Sopenharmony_ci * though it slightly increases that amount of AIL lock traffic to set it up 76062306a36Sopenharmony_ci * and tear it down. 76162306a36Sopenharmony_ci */ 76262306a36Sopenharmony_civoid 76362306a36Sopenharmony_cixfs_trans_committed_bulk( 76462306a36Sopenharmony_ci struct xfs_ail *ailp, 76562306a36Sopenharmony_ci struct list_head *lv_chain, 76662306a36Sopenharmony_ci xfs_lsn_t commit_lsn, 76762306a36Sopenharmony_ci bool aborted) 76862306a36Sopenharmony_ci{ 76962306a36Sopenharmony_ci#define LOG_ITEM_BATCH_SIZE 32 77062306a36Sopenharmony_ci struct xfs_log_item *log_items[LOG_ITEM_BATCH_SIZE]; 77162306a36Sopenharmony_ci struct xfs_log_vec *lv; 77262306a36Sopenharmony_ci struct xfs_ail_cursor cur; 77362306a36Sopenharmony_ci int i = 0; 77462306a36Sopenharmony_ci 77562306a36Sopenharmony_ci spin_lock(&ailp->ail_lock); 77662306a36Sopenharmony_ci xfs_trans_ail_cursor_last(ailp, &cur, commit_lsn); 77762306a36Sopenharmony_ci spin_unlock(&ailp->ail_lock); 77862306a36Sopenharmony_ci 77962306a36Sopenharmony_ci /* unpin all the log items */ 78062306a36Sopenharmony_ci list_for_each_entry(lv, lv_chain, lv_list) { 78162306a36Sopenharmony_ci struct xfs_log_item *lip = lv->lv_item; 78262306a36Sopenharmony_ci xfs_lsn_t item_lsn; 78362306a36Sopenharmony_ci 78462306a36Sopenharmony_ci if (aborted) 78562306a36Sopenharmony_ci set_bit(XFS_LI_ABORTED, &lip->li_flags); 78662306a36Sopenharmony_ci 78762306a36Sopenharmony_ci if (lip->li_ops->flags & XFS_ITEM_RELEASE_WHEN_COMMITTED) { 78862306a36Sopenharmony_ci lip->li_ops->iop_release(lip); 78962306a36Sopenharmony_ci continue; 79062306a36Sopenharmony_ci } 79162306a36Sopenharmony_ci 79262306a36Sopenharmony_ci if (lip->li_ops->iop_committed) 79362306a36Sopenharmony_ci item_lsn = lip->li_ops->iop_committed(lip, commit_lsn); 79462306a36Sopenharmony_ci else 79562306a36Sopenharmony_ci item_lsn = commit_lsn; 79662306a36Sopenharmony_ci 79762306a36Sopenharmony_ci /* item_lsn of -1 means the item needs no further processing */ 79862306a36Sopenharmony_ci if (XFS_LSN_CMP(item_lsn, (xfs_lsn_t)-1) == 0) 79962306a36Sopenharmony_ci continue; 80062306a36Sopenharmony_ci 80162306a36Sopenharmony_ci /* 80262306a36Sopenharmony_ci * if we are aborting the operation, no point in inserting the 80362306a36Sopenharmony_ci * object into the AIL as we are in a shutdown situation. 80462306a36Sopenharmony_ci */ 80562306a36Sopenharmony_ci if (aborted) { 80662306a36Sopenharmony_ci ASSERT(xlog_is_shutdown(ailp->ail_log)); 80762306a36Sopenharmony_ci if (lip->li_ops->iop_unpin) 80862306a36Sopenharmony_ci lip->li_ops->iop_unpin(lip, 1); 80962306a36Sopenharmony_ci continue; 81062306a36Sopenharmony_ci } 81162306a36Sopenharmony_ci 81262306a36Sopenharmony_ci if (item_lsn != commit_lsn) { 81362306a36Sopenharmony_ci 81462306a36Sopenharmony_ci /* 81562306a36Sopenharmony_ci * Not a bulk update option due to unusual item_lsn. 81662306a36Sopenharmony_ci * Push into AIL immediately, rechecking the lsn once 81762306a36Sopenharmony_ci * we have the ail lock. Then unpin the item. This does 81862306a36Sopenharmony_ci * not affect the AIL cursor the bulk insert path is 81962306a36Sopenharmony_ci * using. 82062306a36Sopenharmony_ci */ 82162306a36Sopenharmony_ci spin_lock(&ailp->ail_lock); 82262306a36Sopenharmony_ci if (XFS_LSN_CMP(item_lsn, lip->li_lsn) > 0) 82362306a36Sopenharmony_ci xfs_trans_ail_update(ailp, lip, item_lsn); 82462306a36Sopenharmony_ci else 82562306a36Sopenharmony_ci spin_unlock(&ailp->ail_lock); 82662306a36Sopenharmony_ci if (lip->li_ops->iop_unpin) 82762306a36Sopenharmony_ci lip->li_ops->iop_unpin(lip, 0); 82862306a36Sopenharmony_ci continue; 82962306a36Sopenharmony_ci } 83062306a36Sopenharmony_ci 83162306a36Sopenharmony_ci /* Item is a candidate for bulk AIL insert. */ 83262306a36Sopenharmony_ci log_items[i++] = lv->lv_item; 83362306a36Sopenharmony_ci if (i >= LOG_ITEM_BATCH_SIZE) { 83462306a36Sopenharmony_ci xfs_log_item_batch_insert(ailp, &cur, log_items, 83562306a36Sopenharmony_ci LOG_ITEM_BATCH_SIZE, commit_lsn); 83662306a36Sopenharmony_ci i = 0; 83762306a36Sopenharmony_ci } 83862306a36Sopenharmony_ci } 83962306a36Sopenharmony_ci 84062306a36Sopenharmony_ci /* make sure we insert the remainder! */ 84162306a36Sopenharmony_ci if (i) 84262306a36Sopenharmony_ci xfs_log_item_batch_insert(ailp, &cur, log_items, i, commit_lsn); 84362306a36Sopenharmony_ci 84462306a36Sopenharmony_ci spin_lock(&ailp->ail_lock); 84562306a36Sopenharmony_ci xfs_trans_ail_cursor_done(&cur); 84662306a36Sopenharmony_ci spin_unlock(&ailp->ail_lock); 84762306a36Sopenharmony_ci} 84862306a36Sopenharmony_ci 84962306a36Sopenharmony_ci/* 85062306a36Sopenharmony_ci * Sort transaction items prior to running precommit operations. This will 85162306a36Sopenharmony_ci * attempt to order the items such that they will always be locked in the same 85262306a36Sopenharmony_ci * order. Items that have no sort function are moved to the end of the list 85362306a36Sopenharmony_ci * and so are locked last. 85462306a36Sopenharmony_ci * 85562306a36Sopenharmony_ci * This may need refinement as different types of objects add sort functions. 85662306a36Sopenharmony_ci * 85762306a36Sopenharmony_ci * Function is more complex than it needs to be because we are comparing 64 bit 85862306a36Sopenharmony_ci * values and the function only returns 32 bit values. 85962306a36Sopenharmony_ci */ 86062306a36Sopenharmony_cistatic int 86162306a36Sopenharmony_cixfs_trans_precommit_sort( 86262306a36Sopenharmony_ci void *unused_arg, 86362306a36Sopenharmony_ci const struct list_head *a, 86462306a36Sopenharmony_ci const struct list_head *b) 86562306a36Sopenharmony_ci{ 86662306a36Sopenharmony_ci struct xfs_log_item *lia = container_of(a, 86762306a36Sopenharmony_ci struct xfs_log_item, li_trans); 86862306a36Sopenharmony_ci struct xfs_log_item *lib = container_of(b, 86962306a36Sopenharmony_ci struct xfs_log_item, li_trans); 87062306a36Sopenharmony_ci int64_t diff; 87162306a36Sopenharmony_ci 87262306a36Sopenharmony_ci /* 87362306a36Sopenharmony_ci * If both items are non-sortable, leave them alone. If only one is 87462306a36Sopenharmony_ci * sortable, move the non-sortable item towards the end of the list. 87562306a36Sopenharmony_ci */ 87662306a36Sopenharmony_ci if (!lia->li_ops->iop_sort && !lib->li_ops->iop_sort) 87762306a36Sopenharmony_ci return 0; 87862306a36Sopenharmony_ci if (!lia->li_ops->iop_sort) 87962306a36Sopenharmony_ci return 1; 88062306a36Sopenharmony_ci if (!lib->li_ops->iop_sort) 88162306a36Sopenharmony_ci return -1; 88262306a36Sopenharmony_ci 88362306a36Sopenharmony_ci diff = lia->li_ops->iop_sort(lia) - lib->li_ops->iop_sort(lib); 88462306a36Sopenharmony_ci if (diff < 0) 88562306a36Sopenharmony_ci return -1; 88662306a36Sopenharmony_ci if (diff > 0) 88762306a36Sopenharmony_ci return 1; 88862306a36Sopenharmony_ci return 0; 88962306a36Sopenharmony_ci} 89062306a36Sopenharmony_ci 89162306a36Sopenharmony_ci/* 89262306a36Sopenharmony_ci * Run transaction precommit functions. 89362306a36Sopenharmony_ci * 89462306a36Sopenharmony_ci * If there is an error in any of the callouts, then stop immediately and 89562306a36Sopenharmony_ci * trigger a shutdown to abort the transaction. There is no recovery possible 89662306a36Sopenharmony_ci * from errors at this point as the transaction is dirty.... 89762306a36Sopenharmony_ci */ 89862306a36Sopenharmony_cistatic int 89962306a36Sopenharmony_cixfs_trans_run_precommits( 90062306a36Sopenharmony_ci struct xfs_trans *tp) 90162306a36Sopenharmony_ci{ 90262306a36Sopenharmony_ci struct xfs_mount *mp = tp->t_mountp; 90362306a36Sopenharmony_ci struct xfs_log_item *lip, *n; 90462306a36Sopenharmony_ci int error = 0; 90562306a36Sopenharmony_ci 90662306a36Sopenharmony_ci /* 90762306a36Sopenharmony_ci * Sort the item list to avoid ABBA deadlocks with other transactions 90862306a36Sopenharmony_ci * running precommit operations that lock multiple shared items such as 90962306a36Sopenharmony_ci * inode cluster buffers. 91062306a36Sopenharmony_ci */ 91162306a36Sopenharmony_ci list_sort(NULL, &tp->t_items, xfs_trans_precommit_sort); 91262306a36Sopenharmony_ci 91362306a36Sopenharmony_ci /* 91462306a36Sopenharmony_ci * Precommit operations can remove the log item from the transaction 91562306a36Sopenharmony_ci * if the log item exists purely to delay modifications until they 91662306a36Sopenharmony_ci * can be ordered against other operations. Hence we have to use 91762306a36Sopenharmony_ci * list_for_each_entry_safe() here. 91862306a36Sopenharmony_ci */ 91962306a36Sopenharmony_ci list_for_each_entry_safe(lip, n, &tp->t_items, li_trans) { 92062306a36Sopenharmony_ci if (!test_bit(XFS_LI_DIRTY, &lip->li_flags)) 92162306a36Sopenharmony_ci continue; 92262306a36Sopenharmony_ci if (lip->li_ops->iop_precommit) { 92362306a36Sopenharmony_ci error = lip->li_ops->iop_precommit(tp, lip); 92462306a36Sopenharmony_ci if (error) 92562306a36Sopenharmony_ci break; 92662306a36Sopenharmony_ci } 92762306a36Sopenharmony_ci } 92862306a36Sopenharmony_ci if (error) 92962306a36Sopenharmony_ci xfs_force_shutdown(mp, SHUTDOWN_CORRUPT_INCORE); 93062306a36Sopenharmony_ci return error; 93162306a36Sopenharmony_ci} 93262306a36Sopenharmony_ci 93362306a36Sopenharmony_ci/* 93462306a36Sopenharmony_ci * Commit the given transaction to the log. 93562306a36Sopenharmony_ci * 93662306a36Sopenharmony_ci * XFS disk error handling mechanism is not based on a typical 93762306a36Sopenharmony_ci * transaction abort mechanism. Logically after the filesystem 93862306a36Sopenharmony_ci * gets marked 'SHUTDOWN', we can't let any new transactions 93962306a36Sopenharmony_ci * be durable - ie. committed to disk - because some metadata might 94062306a36Sopenharmony_ci * be inconsistent. In such cases, this returns an error, and the 94162306a36Sopenharmony_ci * caller may assume that all locked objects joined to the transaction 94262306a36Sopenharmony_ci * have already been unlocked as if the commit had succeeded. 94362306a36Sopenharmony_ci * Do not reference the transaction structure after this call. 94462306a36Sopenharmony_ci */ 94562306a36Sopenharmony_cistatic int 94662306a36Sopenharmony_ci__xfs_trans_commit( 94762306a36Sopenharmony_ci struct xfs_trans *tp, 94862306a36Sopenharmony_ci bool regrant) 94962306a36Sopenharmony_ci{ 95062306a36Sopenharmony_ci struct xfs_mount *mp = tp->t_mountp; 95162306a36Sopenharmony_ci struct xlog *log = mp->m_log; 95262306a36Sopenharmony_ci xfs_csn_t commit_seq = 0; 95362306a36Sopenharmony_ci int error = 0; 95462306a36Sopenharmony_ci int sync = tp->t_flags & XFS_TRANS_SYNC; 95562306a36Sopenharmony_ci 95662306a36Sopenharmony_ci trace_xfs_trans_commit(tp, _RET_IP_); 95762306a36Sopenharmony_ci 95862306a36Sopenharmony_ci error = xfs_trans_run_precommits(tp); 95962306a36Sopenharmony_ci if (error) { 96062306a36Sopenharmony_ci if (tp->t_flags & XFS_TRANS_PERM_LOG_RES) 96162306a36Sopenharmony_ci xfs_defer_cancel(tp); 96262306a36Sopenharmony_ci goto out_unreserve; 96362306a36Sopenharmony_ci } 96462306a36Sopenharmony_ci 96562306a36Sopenharmony_ci /* 96662306a36Sopenharmony_ci * Finish deferred items on final commit. Only permanent transactions 96762306a36Sopenharmony_ci * should ever have deferred ops. 96862306a36Sopenharmony_ci */ 96962306a36Sopenharmony_ci WARN_ON_ONCE(!list_empty(&tp->t_dfops) && 97062306a36Sopenharmony_ci !(tp->t_flags & XFS_TRANS_PERM_LOG_RES)); 97162306a36Sopenharmony_ci if (!regrant && (tp->t_flags & XFS_TRANS_PERM_LOG_RES)) { 97262306a36Sopenharmony_ci error = xfs_defer_finish_noroll(&tp); 97362306a36Sopenharmony_ci if (error) 97462306a36Sopenharmony_ci goto out_unreserve; 97562306a36Sopenharmony_ci 97662306a36Sopenharmony_ci /* Run precommits from final tx in defer chain. */ 97762306a36Sopenharmony_ci error = xfs_trans_run_precommits(tp); 97862306a36Sopenharmony_ci if (error) 97962306a36Sopenharmony_ci goto out_unreserve; 98062306a36Sopenharmony_ci } 98162306a36Sopenharmony_ci 98262306a36Sopenharmony_ci /* 98362306a36Sopenharmony_ci * If there is nothing to be logged by the transaction, 98462306a36Sopenharmony_ci * then unlock all of the items associated with the 98562306a36Sopenharmony_ci * transaction and free the transaction structure. 98662306a36Sopenharmony_ci * Also make sure to return any reserved blocks to 98762306a36Sopenharmony_ci * the free pool. 98862306a36Sopenharmony_ci */ 98962306a36Sopenharmony_ci if (!(tp->t_flags & XFS_TRANS_DIRTY)) 99062306a36Sopenharmony_ci goto out_unreserve; 99162306a36Sopenharmony_ci 99262306a36Sopenharmony_ci /* 99362306a36Sopenharmony_ci * We must check against log shutdown here because we cannot abort log 99462306a36Sopenharmony_ci * items and leave them dirty, inconsistent and unpinned in memory while 99562306a36Sopenharmony_ci * the log is active. This leaves them open to being written back to 99662306a36Sopenharmony_ci * disk, and that will lead to on-disk corruption. 99762306a36Sopenharmony_ci */ 99862306a36Sopenharmony_ci if (xlog_is_shutdown(log)) { 99962306a36Sopenharmony_ci error = -EIO; 100062306a36Sopenharmony_ci goto out_unreserve; 100162306a36Sopenharmony_ci } 100262306a36Sopenharmony_ci 100362306a36Sopenharmony_ci ASSERT(tp->t_ticket != NULL); 100462306a36Sopenharmony_ci 100562306a36Sopenharmony_ci /* 100662306a36Sopenharmony_ci * If we need to update the superblock, then do it now. 100762306a36Sopenharmony_ci */ 100862306a36Sopenharmony_ci if (tp->t_flags & XFS_TRANS_SB_DIRTY) 100962306a36Sopenharmony_ci xfs_trans_apply_sb_deltas(tp); 101062306a36Sopenharmony_ci xfs_trans_apply_dquot_deltas(tp); 101162306a36Sopenharmony_ci 101262306a36Sopenharmony_ci xlog_cil_commit(log, tp, &commit_seq, regrant); 101362306a36Sopenharmony_ci 101462306a36Sopenharmony_ci xfs_trans_free(tp); 101562306a36Sopenharmony_ci 101662306a36Sopenharmony_ci /* 101762306a36Sopenharmony_ci * If the transaction needs to be synchronous, then force the 101862306a36Sopenharmony_ci * log out now and wait for it. 101962306a36Sopenharmony_ci */ 102062306a36Sopenharmony_ci if (sync) { 102162306a36Sopenharmony_ci error = xfs_log_force_seq(mp, commit_seq, XFS_LOG_SYNC, NULL); 102262306a36Sopenharmony_ci XFS_STATS_INC(mp, xs_trans_sync); 102362306a36Sopenharmony_ci } else { 102462306a36Sopenharmony_ci XFS_STATS_INC(mp, xs_trans_async); 102562306a36Sopenharmony_ci } 102662306a36Sopenharmony_ci 102762306a36Sopenharmony_ci return error; 102862306a36Sopenharmony_ci 102962306a36Sopenharmony_ciout_unreserve: 103062306a36Sopenharmony_ci xfs_trans_unreserve_and_mod_sb(tp); 103162306a36Sopenharmony_ci 103262306a36Sopenharmony_ci /* 103362306a36Sopenharmony_ci * It is indeed possible for the transaction to be not dirty but 103462306a36Sopenharmony_ci * the dqinfo portion to be. All that means is that we have some 103562306a36Sopenharmony_ci * (non-persistent) quota reservations that need to be unreserved. 103662306a36Sopenharmony_ci */ 103762306a36Sopenharmony_ci xfs_trans_unreserve_and_mod_dquots(tp); 103862306a36Sopenharmony_ci if (tp->t_ticket) { 103962306a36Sopenharmony_ci if (regrant && !xlog_is_shutdown(log)) 104062306a36Sopenharmony_ci xfs_log_ticket_regrant(log, tp->t_ticket); 104162306a36Sopenharmony_ci else 104262306a36Sopenharmony_ci xfs_log_ticket_ungrant(log, tp->t_ticket); 104362306a36Sopenharmony_ci tp->t_ticket = NULL; 104462306a36Sopenharmony_ci } 104562306a36Sopenharmony_ci xfs_trans_free_items(tp, !!error); 104662306a36Sopenharmony_ci xfs_trans_free(tp); 104762306a36Sopenharmony_ci 104862306a36Sopenharmony_ci XFS_STATS_INC(mp, xs_trans_empty); 104962306a36Sopenharmony_ci return error; 105062306a36Sopenharmony_ci} 105162306a36Sopenharmony_ci 105262306a36Sopenharmony_ciint 105362306a36Sopenharmony_cixfs_trans_commit( 105462306a36Sopenharmony_ci struct xfs_trans *tp) 105562306a36Sopenharmony_ci{ 105662306a36Sopenharmony_ci return __xfs_trans_commit(tp, false); 105762306a36Sopenharmony_ci} 105862306a36Sopenharmony_ci 105962306a36Sopenharmony_ci/* 106062306a36Sopenharmony_ci * Unlock all of the transaction's items and free the transaction. If the 106162306a36Sopenharmony_ci * transaction is dirty, we must shut down the filesystem because there is no 106262306a36Sopenharmony_ci * way to restore them to their previous state. 106362306a36Sopenharmony_ci * 106462306a36Sopenharmony_ci * If the transaction has made a log reservation, make sure to release it as 106562306a36Sopenharmony_ci * well. 106662306a36Sopenharmony_ci * 106762306a36Sopenharmony_ci * This is a high level function (equivalent to xfs_trans_commit()) and so can 106862306a36Sopenharmony_ci * be called after the transaction has effectively been aborted due to the mount 106962306a36Sopenharmony_ci * being shut down. However, if the mount has not been shut down and the 107062306a36Sopenharmony_ci * transaction is dirty we will shut the mount down and, in doing so, that 107162306a36Sopenharmony_ci * guarantees that the log is shut down, too. Hence we don't need to be as 107262306a36Sopenharmony_ci * careful with shutdown state and dirty items here as we need to be in 107362306a36Sopenharmony_ci * xfs_trans_commit(). 107462306a36Sopenharmony_ci */ 107562306a36Sopenharmony_civoid 107662306a36Sopenharmony_cixfs_trans_cancel( 107762306a36Sopenharmony_ci struct xfs_trans *tp) 107862306a36Sopenharmony_ci{ 107962306a36Sopenharmony_ci struct xfs_mount *mp = tp->t_mountp; 108062306a36Sopenharmony_ci struct xlog *log = mp->m_log; 108162306a36Sopenharmony_ci bool dirty = (tp->t_flags & XFS_TRANS_DIRTY); 108262306a36Sopenharmony_ci 108362306a36Sopenharmony_ci trace_xfs_trans_cancel(tp, _RET_IP_); 108462306a36Sopenharmony_ci 108562306a36Sopenharmony_ci /* 108662306a36Sopenharmony_ci * It's never valid to cancel a transaction with deferred ops attached, 108762306a36Sopenharmony_ci * because the transaction is effectively dirty. Complain about this 108862306a36Sopenharmony_ci * loudly before freeing the in-memory defer items and shutting down the 108962306a36Sopenharmony_ci * filesystem. 109062306a36Sopenharmony_ci */ 109162306a36Sopenharmony_ci if (!list_empty(&tp->t_dfops)) { 109262306a36Sopenharmony_ci ASSERT(tp->t_flags & XFS_TRANS_PERM_LOG_RES); 109362306a36Sopenharmony_ci dirty = true; 109462306a36Sopenharmony_ci xfs_defer_cancel(tp); 109562306a36Sopenharmony_ci } 109662306a36Sopenharmony_ci 109762306a36Sopenharmony_ci /* 109862306a36Sopenharmony_ci * See if the caller is relying on us to shut down the filesystem. We 109962306a36Sopenharmony_ci * only want an error report if there isn't already a shutdown in 110062306a36Sopenharmony_ci * progress, so we only need to check against the mount shutdown state 110162306a36Sopenharmony_ci * here. 110262306a36Sopenharmony_ci */ 110362306a36Sopenharmony_ci if (dirty && !xfs_is_shutdown(mp)) { 110462306a36Sopenharmony_ci XFS_ERROR_REPORT("xfs_trans_cancel", XFS_ERRLEVEL_LOW, mp); 110562306a36Sopenharmony_ci xfs_force_shutdown(mp, SHUTDOWN_CORRUPT_INCORE); 110662306a36Sopenharmony_ci } 110762306a36Sopenharmony_ci#ifdef DEBUG 110862306a36Sopenharmony_ci /* Log items need to be consistent until the log is shut down. */ 110962306a36Sopenharmony_ci if (!dirty && !xlog_is_shutdown(log)) { 111062306a36Sopenharmony_ci struct xfs_log_item *lip; 111162306a36Sopenharmony_ci 111262306a36Sopenharmony_ci list_for_each_entry(lip, &tp->t_items, li_trans) 111362306a36Sopenharmony_ci ASSERT(!xlog_item_is_intent_done(lip)); 111462306a36Sopenharmony_ci } 111562306a36Sopenharmony_ci#endif 111662306a36Sopenharmony_ci xfs_trans_unreserve_and_mod_sb(tp); 111762306a36Sopenharmony_ci xfs_trans_unreserve_and_mod_dquots(tp); 111862306a36Sopenharmony_ci 111962306a36Sopenharmony_ci if (tp->t_ticket) { 112062306a36Sopenharmony_ci xfs_log_ticket_ungrant(log, tp->t_ticket); 112162306a36Sopenharmony_ci tp->t_ticket = NULL; 112262306a36Sopenharmony_ci } 112362306a36Sopenharmony_ci 112462306a36Sopenharmony_ci xfs_trans_free_items(tp, dirty); 112562306a36Sopenharmony_ci xfs_trans_free(tp); 112662306a36Sopenharmony_ci} 112762306a36Sopenharmony_ci 112862306a36Sopenharmony_ci/* 112962306a36Sopenharmony_ci * Roll from one trans in the sequence of PERMANENT transactions to 113062306a36Sopenharmony_ci * the next: permanent transactions are only flushed out when 113162306a36Sopenharmony_ci * committed with xfs_trans_commit(), but we still want as soon 113262306a36Sopenharmony_ci * as possible to let chunks of it go to the log. So we commit the 113362306a36Sopenharmony_ci * chunk we've been working on and get a new transaction to continue. 113462306a36Sopenharmony_ci */ 113562306a36Sopenharmony_ciint 113662306a36Sopenharmony_cixfs_trans_roll( 113762306a36Sopenharmony_ci struct xfs_trans **tpp) 113862306a36Sopenharmony_ci{ 113962306a36Sopenharmony_ci struct xfs_trans *trans = *tpp; 114062306a36Sopenharmony_ci struct xfs_trans_res tres; 114162306a36Sopenharmony_ci int error; 114262306a36Sopenharmony_ci 114362306a36Sopenharmony_ci trace_xfs_trans_roll(trans, _RET_IP_); 114462306a36Sopenharmony_ci 114562306a36Sopenharmony_ci /* 114662306a36Sopenharmony_ci * Copy the critical parameters from one trans to the next. 114762306a36Sopenharmony_ci */ 114862306a36Sopenharmony_ci tres.tr_logres = trans->t_log_res; 114962306a36Sopenharmony_ci tres.tr_logcount = trans->t_log_count; 115062306a36Sopenharmony_ci 115162306a36Sopenharmony_ci *tpp = xfs_trans_dup(trans); 115262306a36Sopenharmony_ci 115362306a36Sopenharmony_ci /* 115462306a36Sopenharmony_ci * Commit the current transaction. 115562306a36Sopenharmony_ci * If this commit failed, then it'd just unlock those items that 115662306a36Sopenharmony_ci * are not marked ihold. That also means that a filesystem shutdown 115762306a36Sopenharmony_ci * is in progress. The caller takes the responsibility to cancel 115862306a36Sopenharmony_ci * the duplicate transaction that gets returned. 115962306a36Sopenharmony_ci */ 116062306a36Sopenharmony_ci error = __xfs_trans_commit(trans, true); 116162306a36Sopenharmony_ci if (error) 116262306a36Sopenharmony_ci return error; 116362306a36Sopenharmony_ci 116462306a36Sopenharmony_ci /* 116562306a36Sopenharmony_ci * Reserve space in the log for the next transaction. 116662306a36Sopenharmony_ci * This also pushes items in the "AIL", the list of logged items, 116762306a36Sopenharmony_ci * out to disk if they are taking up space at the tail of the log 116862306a36Sopenharmony_ci * that we want to use. This requires that either nothing be locked 116962306a36Sopenharmony_ci * across this call, or that anything that is locked be logged in 117062306a36Sopenharmony_ci * the prior and the next transactions. 117162306a36Sopenharmony_ci */ 117262306a36Sopenharmony_ci tres.tr_logflags = XFS_TRANS_PERM_LOG_RES; 117362306a36Sopenharmony_ci return xfs_trans_reserve(*tpp, &tres, 0, 0); 117462306a36Sopenharmony_ci} 117562306a36Sopenharmony_ci 117662306a36Sopenharmony_ci/* 117762306a36Sopenharmony_ci * Allocate an transaction, lock and join the inode to it, and reserve quota. 117862306a36Sopenharmony_ci * 117962306a36Sopenharmony_ci * The caller must ensure that the on-disk dquots attached to this inode have 118062306a36Sopenharmony_ci * already been allocated and initialized. The caller is responsible for 118162306a36Sopenharmony_ci * releasing ILOCK_EXCL if a new transaction is returned. 118262306a36Sopenharmony_ci */ 118362306a36Sopenharmony_ciint 118462306a36Sopenharmony_cixfs_trans_alloc_inode( 118562306a36Sopenharmony_ci struct xfs_inode *ip, 118662306a36Sopenharmony_ci struct xfs_trans_res *resv, 118762306a36Sopenharmony_ci unsigned int dblocks, 118862306a36Sopenharmony_ci unsigned int rblocks, 118962306a36Sopenharmony_ci bool force, 119062306a36Sopenharmony_ci struct xfs_trans **tpp) 119162306a36Sopenharmony_ci{ 119262306a36Sopenharmony_ci struct xfs_trans *tp; 119362306a36Sopenharmony_ci struct xfs_mount *mp = ip->i_mount; 119462306a36Sopenharmony_ci bool retried = false; 119562306a36Sopenharmony_ci int error; 119662306a36Sopenharmony_ci 119762306a36Sopenharmony_ciretry: 119862306a36Sopenharmony_ci error = xfs_trans_alloc(mp, resv, dblocks, 119962306a36Sopenharmony_ci rblocks / mp->m_sb.sb_rextsize, 120062306a36Sopenharmony_ci force ? XFS_TRANS_RESERVE : 0, &tp); 120162306a36Sopenharmony_ci if (error) 120262306a36Sopenharmony_ci return error; 120362306a36Sopenharmony_ci 120462306a36Sopenharmony_ci xfs_ilock(ip, XFS_ILOCK_EXCL); 120562306a36Sopenharmony_ci xfs_trans_ijoin(tp, ip, 0); 120662306a36Sopenharmony_ci 120762306a36Sopenharmony_ci error = xfs_qm_dqattach_locked(ip, false); 120862306a36Sopenharmony_ci if (error) { 120962306a36Sopenharmony_ci /* Caller should have allocated the dquots! */ 121062306a36Sopenharmony_ci ASSERT(error != -ENOENT); 121162306a36Sopenharmony_ci goto out_cancel; 121262306a36Sopenharmony_ci } 121362306a36Sopenharmony_ci 121462306a36Sopenharmony_ci error = xfs_trans_reserve_quota_nblks(tp, ip, dblocks, rblocks, force); 121562306a36Sopenharmony_ci if ((error == -EDQUOT || error == -ENOSPC) && !retried) { 121662306a36Sopenharmony_ci xfs_trans_cancel(tp); 121762306a36Sopenharmony_ci xfs_iunlock(ip, XFS_ILOCK_EXCL); 121862306a36Sopenharmony_ci xfs_blockgc_free_quota(ip, 0); 121962306a36Sopenharmony_ci retried = true; 122062306a36Sopenharmony_ci goto retry; 122162306a36Sopenharmony_ci } 122262306a36Sopenharmony_ci if (error) 122362306a36Sopenharmony_ci goto out_cancel; 122462306a36Sopenharmony_ci 122562306a36Sopenharmony_ci *tpp = tp; 122662306a36Sopenharmony_ci return 0; 122762306a36Sopenharmony_ci 122862306a36Sopenharmony_ciout_cancel: 122962306a36Sopenharmony_ci xfs_trans_cancel(tp); 123062306a36Sopenharmony_ci xfs_iunlock(ip, XFS_ILOCK_EXCL); 123162306a36Sopenharmony_ci return error; 123262306a36Sopenharmony_ci} 123362306a36Sopenharmony_ci 123462306a36Sopenharmony_ci/* 123562306a36Sopenharmony_ci * Allocate an transaction in preparation for inode creation by reserving quota 123662306a36Sopenharmony_ci * against the given dquots. Callers are not required to hold any inode locks. 123762306a36Sopenharmony_ci */ 123862306a36Sopenharmony_ciint 123962306a36Sopenharmony_cixfs_trans_alloc_icreate( 124062306a36Sopenharmony_ci struct xfs_mount *mp, 124162306a36Sopenharmony_ci struct xfs_trans_res *resv, 124262306a36Sopenharmony_ci struct xfs_dquot *udqp, 124362306a36Sopenharmony_ci struct xfs_dquot *gdqp, 124462306a36Sopenharmony_ci struct xfs_dquot *pdqp, 124562306a36Sopenharmony_ci unsigned int dblocks, 124662306a36Sopenharmony_ci struct xfs_trans **tpp) 124762306a36Sopenharmony_ci{ 124862306a36Sopenharmony_ci struct xfs_trans *tp; 124962306a36Sopenharmony_ci bool retried = false; 125062306a36Sopenharmony_ci int error; 125162306a36Sopenharmony_ci 125262306a36Sopenharmony_ciretry: 125362306a36Sopenharmony_ci error = xfs_trans_alloc(mp, resv, dblocks, 0, 0, &tp); 125462306a36Sopenharmony_ci if (error) 125562306a36Sopenharmony_ci return error; 125662306a36Sopenharmony_ci 125762306a36Sopenharmony_ci error = xfs_trans_reserve_quota_icreate(tp, udqp, gdqp, pdqp, dblocks); 125862306a36Sopenharmony_ci if ((error == -EDQUOT || error == -ENOSPC) && !retried) { 125962306a36Sopenharmony_ci xfs_trans_cancel(tp); 126062306a36Sopenharmony_ci xfs_blockgc_free_dquots(mp, udqp, gdqp, pdqp, 0); 126162306a36Sopenharmony_ci retried = true; 126262306a36Sopenharmony_ci goto retry; 126362306a36Sopenharmony_ci } 126462306a36Sopenharmony_ci if (error) { 126562306a36Sopenharmony_ci xfs_trans_cancel(tp); 126662306a36Sopenharmony_ci return error; 126762306a36Sopenharmony_ci } 126862306a36Sopenharmony_ci 126962306a36Sopenharmony_ci *tpp = tp; 127062306a36Sopenharmony_ci return 0; 127162306a36Sopenharmony_ci} 127262306a36Sopenharmony_ci 127362306a36Sopenharmony_ci/* 127462306a36Sopenharmony_ci * Allocate an transaction, lock and join the inode to it, and reserve quota 127562306a36Sopenharmony_ci * in preparation for inode attribute changes that include uid, gid, or prid 127662306a36Sopenharmony_ci * changes. 127762306a36Sopenharmony_ci * 127862306a36Sopenharmony_ci * The caller must ensure that the on-disk dquots attached to this inode have 127962306a36Sopenharmony_ci * already been allocated and initialized. The ILOCK will be dropped when the 128062306a36Sopenharmony_ci * transaction is committed or cancelled. 128162306a36Sopenharmony_ci */ 128262306a36Sopenharmony_ciint 128362306a36Sopenharmony_cixfs_trans_alloc_ichange( 128462306a36Sopenharmony_ci struct xfs_inode *ip, 128562306a36Sopenharmony_ci struct xfs_dquot *new_udqp, 128662306a36Sopenharmony_ci struct xfs_dquot *new_gdqp, 128762306a36Sopenharmony_ci struct xfs_dquot *new_pdqp, 128862306a36Sopenharmony_ci bool force, 128962306a36Sopenharmony_ci struct xfs_trans **tpp) 129062306a36Sopenharmony_ci{ 129162306a36Sopenharmony_ci struct xfs_trans *tp; 129262306a36Sopenharmony_ci struct xfs_mount *mp = ip->i_mount; 129362306a36Sopenharmony_ci struct xfs_dquot *udqp; 129462306a36Sopenharmony_ci struct xfs_dquot *gdqp; 129562306a36Sopenharmony_ci struct xfs_dquot *pdqp; 129662306a36Sopenharmony_ci bool retried = false; 129762306a36Sopenharmony_ci int error; 129862306a36Sopenharmony_ci 129962306a36Sopenharmony_ciretry: 130062306a36Sopenharmony_ci error = xfs_trans_alloc(mp, &M_RES(mp)->tr_ichange, 0, 0, 0, &tp); 130162306a36Sopenharmony_ci if (error) 130262306a36Sopenharmony_ci return error; 130362306a36Sopenharmony_ci 130462306a36Sopenharmony_ci xfs_ilock(ip, XFS_ILOCK_EXCL); 130562306a36Sopenharmony_ci xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL); 130662306a36Sopenharmony_ci 130762306a36Sopenharmony_ci error = xfs_qm_dqattach_locked(ip, false); 130862306a36Sopenharmony_ci if (error) { 130962306a36Sopenharmony_ci /* Caller should have allocated the dquots! */ 131062306a36Sopenharmony_ci ASSERT(error != -ENOENT); 131162306a36Sopenharmony_ci goto out_cancel; 131262306a36Sopenharmony_ci } 131362306a36Sopenharmony_ci 131462306a36Sopenharmony_ci /* 131562306a36Sopenharmony_ci * For each quota type, skip quota reservations if the inode's dquots 131662306a36Sopenharmony_ci * now match the ones that came from the caller, or the caller didn't 131762306a36Sopenharmony_ci * pass one in. The inode's dquots can change if we drop the ILOCK to 131862306a36Sopenharmony_ci * perform a blockgc scan, so we must preserve the caller's arguments. 131962306a36Sopenharmony_ci */ 132062306a36Sopenharmony_ci udqp = (new_udqp != ip->i_udquot) ? new_udqp : NULL; 132162306a36Sopenharmony_ci gdqp = (new_gdqp != ip->i_gdquot) ? new_gdqp : NULL; 132262306a36Sopenharmony_ci pdqp = (new_pdqp != ip->i_pdquot) ? new_pdqp : NULL; 132362306a36Sopenharmony_ci if (udqp || gdqp || pdqp) { 132462306a36Sopenharmony_ci unsigned int qflags = XFS_QMOPT_RES_REGBLKS; 132562306a36Sopenharmony_ci 132662306a36Sopenharmony_ci if (force) 132762306a36Sopenharmony_ci qflags |= XFS_QMOPT_FORCE_RES; 132862306a36Sopenharmony_ci 132962306a36Sopenharmony_ci /* 133062306a36Sopenharmony_ci * Reserve enough quota to handle blocks on disk and reserved 133162306a36Sopenharmony_ci * for a delayed allocation. We'll actually transfer the 133262306a36Sopenharmony_ci * delalloc reservation between dquots at chown time, even 133362306a36Sopenharmony_ci * though that part is only semi-transactional. 133462306a36Sopenharmony_ci */ 133562306a36Sopenharmony_ci error = xfs_trans_reserve_quota_bydquots(tp, mp, udqp, gdqp, 133662306a36Sopenharmony_ci pdqp, ip->i_nblocks + ip->i_delayed_blks, 133762306a36Sopenharmony_ci 1, qflags); 133862306a36Sopenharmony_ci if ((error == -EDQUOT || error == -ENOSPC) && !retried) { 133962306a36Sopenharmony_ci xfs_trans_cancel(tp); 134062306a36Sopenharmony_ci xfs_blockgc_free_dquots(mp, udqp, gdqp, pdqp, 0); 134162306a36Sopenharmony_ci retried = true; 134262306a36Sopenharmony_ci goto retry; 134362306a36Sopenharmony_ci } 134462306a36Sopenharmony_ci if (error) 134562306a36Sopenharmony_ci goto out_cancel; 134662306a36Sopenharmony_ci } 134762306a36Sopenharmony_ci 134862306a36Sopenharmony_ci *tpp = tp; 134962306a36Sopenharmony_ci return 0; 135062306a36Sopenharmony_ci 135162306a36Sopenharmony_ciout_cancel: 135262306a36Sopenharmony_ci xfs_trans_cancel(tp); 135362306a36Sopenharmony_ci return error; 135462306a36Sopenharmony_ci} 135562306a36Sopenharmony_ci 135662306a36Sopenharmony_ci/* 135762306a36Sopenharmony_ci * Allocate an transaction, lock and join the directory and child inodes to it, 135862306a36Sopenharmony_ci * and reserve quota for a directory update. If there isn't sufficient space, 135962306a36Sopenharmony_ci * @dblocks will be set to zero for a reservationless directory update and 136062306a36Sopenharmony_ci * @nospace_error will be set to a negative errno describing the space 136162306a36Sopenharmony_ci * constraint we hit. 136262306a36Sopenharmony_ci * 136362306a36Sopenharmony_ci * The caller must ensure that the on-disk dquots attached to this inode have 136462306a36Sopenharmony_ci * already been allocated and initialized. The ILOCKs will be dropped when the 136562306a36Sopenharmony_ci * transaction is committed or cancelled. 136662306a36Sopenharmony_ci */ 136762306a36Sopenharmony_ciint 136862306a36Sopenharmony_cixfs_trans_alloc_dir( 136962306a36Sopenharmony_ci struct xfs_inode *dp, 137062306a36Sopenharmony_ci struct xfs_trans_res *resv, 137162306a36Sopenharmony_ci struct xfs_inode *ip, 137262306a36Sopenharmony_ci unsigned int *dblocks, 137362306a36Sopenharmony_ci struct xfs_trans **tpp, 137462306a36Sopenharmony_ci int *nospace_error) 137562306a36Sopenharmony_ci{ 137662306a36Sopenharmony_ci struct xfs_trans *tp; 137762306a36Sopenharmony_ci struct xfs_mount *mp = ip->i_mount; 137862306a36Sopenharmony_ci unsigned int resblks; 137962306a36Sopenharmony_ci bool retried = false; 138062306a36Sopenharmony_ci int error; 138162306a36Sopenharmony_ci 138262306a36Sopenharmony_ciretry: 138362306a36Sopenharmony_ci *nospace_error = 0; 138462306a36Sopenharmony_ci resblks = *dblocks; 138562306a36Sopenharmony_ci error = xfs_trans_alloc(mp, resv, resblks, 0, 0, &tp); 138662306a36Sopenharmony_ci if (error == -ENOSPC) { 138762306a36Sopenharmony_ci *nospace_error = error; 138862306a36Sopenharmony_ci resblks = 0; 138962306a36Sopenharmony_ci error = xfs_trans_alloc(mp, resv, resblks, 0, 0, &tp); 139062306a36Sopenharmony_ci } 139162306a36Sopenharmony_ci if (error) 139262306a36Sopenharmony_ci return error; 139362306a36Sopenharmony_ci 139462306a36Sopenharmony_ci xfs_lock_two_inodes(dp, XFS_ILOCK_EXCL, ip, XFS_ILOCK_EXCL); 139562306a36Sopenharmony_ci 139662306a36Sopenharmony_ci xfs_trans_ijoin(tp, dp, XFS_ILOCK_EXCL); 139762306a36Sopenharmony_ci xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL); 139862306a36Sopenharmony_ci 139962306a36Sopenharmony_ci error = xfs_qm_dqattach_locked(dp, false); 140062306a36Sopenharmony_ci if (error) { 140162306a36Sopenharmony_ci /* Caller should have allocated the dquots! */ 140262306a36Sopenharmony_ci ASSERT(error != -ENOENT); 140362306a36Sopenharmony_ci goto out_cancel; 140462306a36Sopenharmony_ci } 140562306a36Sopenharmony_ci 140662306a36Sopenharmony_ci error = xfs_qm_dqattach_locked(ip, false); 140762306a36Sopenharmony_ci if (error) { 140862306a36Sopenharmony_ci /* Caller should have allocated the dquots! */ 140962306a36Sopenharmony_ci ASSERT(error != -ENOENT); 141062306a36Sopenharmony_ci goto out_cancel; 141162306a36Sopenharmony_ci } 141262306a36Sopenharmony_ci 141362306a36Sopenharmony_ci if (resblks == 0) 141462306a36Sopenharmony_ci goto done; 141562306a36Sopenharmony_ci 141662306a36Sopenharmony_ci error = xfs_trans_reserve_quota_nblks(tp, dp, resblks, 0, false); 141762306a36Sopenharmony_ci if (error == -EDQUOT || error == -ENOSPC) { 141862306a36Sopenharmony_ci if (!retried) { 141962306a36Sopenharmony_ci xfs_trans_cancel(tp); 142062306a36Sopenharmony_ci xfs_blockgc_free_quota(dp, 0); 142162306a36Sopenharmony_ci retried = true; 142262306a36Sopenharmony_ci goto retry; 142362306a36Sopenharmony_ci } 142462306a36Sopenharmony_ci 142562306a36Sopenharmony_ci *nospace_error = error; 142662306a36Sopenharmony_ci resblks = 0; 142762306a36Sopenharmony_ci error = 0; 142862306a36Sopenharmony_ci } 142962306a36Sopenharmony_ci if (error) 143062306a36Sopenharmony_ci goto out_cancel; 143162306a36Sopenharmony_ci 143262306a36Sopenharmony_cidone: 143362306a36Sopenharmony_ci *tpp = tp; 143462306a36Sopenharmony_ci *dblocks = resblks; 143562306a36Sopenharmony_ci return 0; 143662306a36Sopenharmony_ci 143762306a36Sopenharmony_ciout_cancel: 143862306a36Sopenharmony_ci xfs_trans_cancel(tp); 143962306a36Sopenharmony_ci return error; 144062306a36Sopenharmony_ci} 1441