/* * This is called to create a new transaction which will share the * permanent log reservation of the given transaction. The remaining * unused block and rt extent reservations are also inherited. This * implies that the original transaction is no longer allowed to allocate * blocks. Locks and log items, however, are no inherited. They must * be added to the new transaction explicitly. */ xfs_trans_t * xfs_trans_dup( xfs_trans_t *tp) { xfs_trans_t *ntp; ntp = kmem_zone_zalloc(xfs_trans_zone, KM_SLEEP); /* * Initialize the new transaction structure. */ ntp->t_magic = XFS_TRANS_MAGIC; ntp->t_type = tp->t_type; ntp->t_mountp = tp->t_mountp; ntp->t_items_free = XFS_LIC_NUM_SLOTS; ntp->t_busy_free = XFS_LBC_NUM_SLOTS; XFS_LIC_INIT(&(ntp->t_items)); XFS_LBC_INIT(&(ntp->t_busy)); ASSERT(tp->t_flags & XFS_TRANS_PERM_LOG_RES); ASSERT(tp->t_ticket != NULL); ntp->t_flags = XFS_TRANS_PERM_LOG_RES | (tp->t_flags & XFS_TRANS_RESERVE); ntp->t_ticket = tp->t_ticket; ntp->t_blk_res = tp->t_blk_res - tp->t_blk_res_used; tp->t_blk_res = tp->t_blk_res_used; ntp->t_rtx_res = tp->t_rtx_res - tp->t_rtx_res_used; tp->t_rtx_res = tp->t_rtx_res_used; PFLAGS_DUP(&tp->t_pflags, &ntp->t_pflags); XFS_TRANS_DUP_DQINFO(tp->t_mountp, tp, ntp); atomic_inc(&tp->t_mountp->m_active_trans); return ntp; }
/* * xfs_trans_free_busy * Free all of the busy lists from a transaction */ void xfs_trans_free_busy(xfs_trans_t *tp) { xfs_log_busy_chunk_t *lbcp; xfs_log_busy_chunk_t *lbcq; lbcp = tp->t_busy.lbc_next; while (lbcp != NULL) { lbcq = lbcp->lbc_next; kmem_free(lbcp); lbcp = lbcq; } XFS_LBC_INIT(&tp->t_busy); tp->t_busy.lbc_unused = 0; }
xfs_trans_t * _xfs_trans_alloc( xfs_mount_t *mp, uint type) { xfs_trans_t *tp; atomic_inc(&mp->m_active_trans); tp = kmem_zone_zalloc(xfs_trans_zone, KM_SLEEP); tp->t_magic = XFS_TRANS_MAGIC; tp->t_type = type; tp->t_mountp = mp; tp->t_items_free = XFS_LIC_NUM_SLOTS; tp->t_busy_free = XFS_LBC_NUM_SLOTS; XFS_LIC_INIT(&(tp->t_items)); XFS_LBC_INIT(&(tp->t_busy)); return tp; }
xfs_trans_t * _xfs_trans_alloc( xfs_mount_t *mp, uint type) { xfs_trans_t *tp; ASSERT(xfs_trans_zone != NULL); tp = kmem_zone_zalloc(xfs_trans_zone, KM_SLEEP); /* * Initialize the transaction structure. */ tp->t_magic = XFS_TRANS_MAGIC; tp->t_type = type; tp->t_mountp = mp; tp->t_items_free = XFS_LIC_NUM_SLOTS; tp->t_busy_free = XFS_LBC_NUM_SLOTS; XFS_LIC_INIT(&(tp->t_items)); XFS_LBC_INIT(&(tp->t_busy)); return (tp); }
/* * This is called to add the given busy item to the transaction's * list of busy items. It must find a free busy item descriptor * or allocate a new one and add the item to that descriptor. * The function returns a pointer to busy descriptor used to point * to the new busy entry. The log busy entry will now point to its new * descriptor with its ???? field. */ xfs_log_busy_slot_t * xfs_trans_add_busy(xfs_trans_t *tp, xfs_agnumber_t ag, xfs_extlen_t idx) { xfs_log_busy_chunk_t *lbcp; xfs_log_busy_slot_t *lbsp; int i=0; /* * If there are no free descriptors, allocate a new chunk * of them and put it at the front of the chunk list. */ if (tp->t_busy_free == 0) { lbcp = (xfs_log_busy_chunk_t*) kmem_alloc(sizeof(xfs_log_busy_chunk_t), KM_SLEEP); ASSERT(lbcp != NULL); /* * Initialize the chunk, and then * claim the first slot in the newly allocated chunk. */ XFS_LBC_INIT(lbcp); XFS_LBC_CLAIM(lbcp, 0); lbcp->lbc_unused = 1; lbsp = XFS_LBC_SLOT(lbcp, 0); /* * Link in the new chunk and update the free count. */ lbcp->lbc_next = tp->t_busy.lbc_next; tp->t_busy.lbc_next = lbcp; tp->t_busy_free = XFS_LIC_NUM_SLOTS - 1; /* * Initialize the descriptor and the generic portion * of the log item. * * Point the new slot at this item and return it. * Also point the log item at its currently active * descriptor and set the item's mount pointer. */ lbsp->lbc_ag = ag; lbsp->lbc_idx = idx; return lbsp; } /* * Find the free descriptor. It is somewhere in the chunklist * of descriptors. */ lbcp = &tp->t_busy; while (lbcp != NULL) { if (XFS_LBC_VACANCY(lbcp)) { if (lbcp->lbc_unused <= XFS_LBC_MAX_SLOT) { i = lbcp->lbc_unused; break; } else { /* out-of-order vacancy */ cmn_err(CE_DEBUG, "OOO vacancy lbcp 0x%p\n", lbcp); ASSERT(0); } } lbcp = lbcp->lbc_next; } ASSERT(lbcp != NULL); /* * If we find a free descriptor, claim it, * initialize it, and return it. */ XFS_LBC_CLAIM(lbcp, i); if (lbcp->lbc_unused <= i) { lbcp->lbc_unused = i + 1; } lbsp = XFS_LBC_SLOT(lbcp, i); tp->t_busy_free--; lbsp->lbc_ag = ag; lbsp->lbc_idx = idx; return lbsp; }