/* * Allocate and initialize an efd item with the given number of extents. */ xfs_efd_log_item_t * xfs_efd_init(xfs_mount_t *mp, xfs_efi_log_item_t *efip, uint nextents) { xfs_efd_log_item_t *efdp; uint size; ASSERT(nextents > 0); if (nextents > XFS_EFD_MAX_FAST_EXTENTS) { size = (uint)(sizeof(xfs_efd_log_item_t) + ((nextents - 1) * sizeof(xfs_extent_t))); efdp = (xfs_efd_log_item_t*)kmem_zalloc(size, KM_SLEEP); } else { efdp = (xfs_efd_log_item_t*)kmem_zone_zalloc(xfs_efd_zone, KM_SLEEP); } efdp->efd_item.li_type = XFS_LI_EFD; efdp->efd_item.li_ops = &xfs_efd_item_ops; efdp->efd_item.li_mountp = mp; efdp->efd_efip = efip; efdp->efd_format.efd_nextents = nextents; efdp->efd_format.efd_efi_id = efip->efi_format.efi_id; return (efdp); }
/* * Allocate and initialize an efd item with the given number of extents. */ struct xfs_efd_log_item * xfs_efd_init( struct xfs_mount *mp, struct xfs_efi_log_item *efip, uint nextents) { struct xfs_efd_log_item *efdp; uint size; ASSERT(nextents > 0); if (nextents > XFS_EFD_MAX_FAST_EXTENTS) { size = (uint)(sizeof(xfs_efd_log_item_t) + ((nextents - 1) * sizeof(xfs_extent_t))); efdp = kmem_zalloc(size, KM_SLEEP); } else { efdp = kmem_zone_zalloc(xfs_efd_zone, KM_SLEEP); } xfs_log_item_init(mp, &efdp->efd_item, XFS_LI_EFD, &xfs_efd_item_ops); efdp->efd_efip = efip; efdp->efd_format.efd_nextents = nextents; efdp->efd_format.efd_efi_id = efip->efi_format.efi_id; return efdp; }
/* * 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; }
/* * Initialize the inode log item for a newly allocated (in-core) inode. */ void xfs_inode_item_init( xfs_inode_t *ip, xfs_mount_t *mp) { xfs_inode_log_item_t *iip; ASSERT(ip->i_itemp == NULL); iip = ip->i_itemp = kmem_zone_zalloc(xfs_ili_zone, KM_SLEEP); iip->ili_item.li_type = XFS_LI_INODE; iip->ili_item.li_ops = &xfs_inode_item_ops; iip->ili_item.li_mountp = mp; iip->ili_item.li_ailp = mp->m_ail; iip->ili_inode = ip; /* We have zeroed memory. No need ... iip->ili_extents_buf = NULL; iip->ili_pushbuf_flag = 0; */ iip->ili_format.ilf_type = XFS_LI_INODE; iip->ili_format.ilf_ino = ip->i_ino; iip->ili_format.ilf_blkno = ip->i_imap.im_blkno; iip->ili_format.ilf_len = ip->i_imap.im_len; iip->ili_format.ilf_boffset = ip->i_imap.im_boffset; }
/* * Allocate and initialize an efi item with the given number of extents. */ xfs_efi_log_item_t * xfs_efi_init(xfs_mount_t *mp, uint nextents) { xfs_efi_log_item_t *efip; uint size; ASSERT(nextents > 0); if (nextents > XFS_EFI_MAX_FAST_EXTENTS) { size = (uint)(sizeof(xfs_efi_log_item_t) + ((nextents - 1) * sizeof(xfs_extent_t))); efip = (xfs_efi_log_item_t*)kmem_zalloc(size, KM_SLEEP); } else { efip = (xfs_efi_log_item_t*)kmem_zone_zalloc(xfs_efi_zone, KM_SLEEP); } efip->efi_item.li_type = XFS_LI_EFI; efip->efi_item.li_ops = &xfs_efi_item_ops; efip->efi_item.li_mountp = mp; efip->efi_item.li_ailp = mp->m_ail; efip->efi_format.efi_nextents = nextents; efip->efi_format.efi_id = (__psint_t)(void*)efip; return (efip); }
/* * Allocate and initialize an efi item with the given number of extents. */ struct xfs_efi_log_item * xfs_efi_init( struct xfs_mount *mp, uint nextents) { struct xfs_efi_log_item *efip; uint size; ASSERT(nextents > 0); if (nextents > XFS_EFI_MAX_FAST_EXTENTS) { size = (uint)(sizeof(xfs_efi_log_item_t) + ((nextents - 1) * sizeof(xfs_extent_t))); efip = kmem_zalloc(size, KM_SLEEP); } else { efip = kmem_zone_zalloc(xfs_efi_zone, KM_SLEEP); } xfs_log_item_init(mp, &efip->efi_item, XFS_LI_EFI, &xfs_efi_item_ops); efip->efi_format.efi_nextents = nextents; efip->efi_format.efi_id = (__psint_t)(void*)efip; atomic_set(&efip->efi_next_extent, 0); return efip; }
/* * Allocate a new allocation btree cursor. */ struct xfs_btree_cur * /* new alloc btree cursor */ xfs_allocbt_init_cursor( struct xfs_mount *mp, /* file system mount point */ struct xfs_trans *tp, /* transaction pointer */ struct xfs_buf *agbp, /* buffer for agf structure */ xfs_agnumber_t agno, /* allocation group number */ xfs_btnum_t btnum) /* btree identifier */ { struct xfs_agf *agf = XFS_BUF_TO_AGF(agbp); struct xfs_btree_cur *cur; ASSERT(btnum == XFS_BTNUM_BNO || btnum == XFS_BTNUM_CNT); cur = kmem_zone_zalloc(xfs_btree_cur_zone, KM_SLEEP); cur->bc_tp = tp; cur->bc_mp = mp; cur->bc_btnum = btnum; cur->bc_blocklog = mp->m_sb.sb_blocklog; cur->bc_ops = &xfs_allocbt_ops; if (btnum == XFS_BTNUM_CNT) { cur->bc_nlevels = be32_to_cpu(agf->agf_levels[XFS_BTNUM_CNT]); cur->bc_flags = XFS_BTREE_LASTREC_UPDATE; } else { cur->bc_nlevels = be32_to_cpu(agf->agf_levels[XFS_BTNUM_BNO]); } cur->bc_private.a.agbp = agbp; cur->bc_private.a.agno = agno; return cur; }
/* * Initialize the inode log item for a newly allocated (in-core) inode. * * Inode extents can only reside within an AG. Hence specify the starting * block for the inode chunk by offset within an AG as well as the * length of the allocated extent. * * This joins the item to the transaction and marks it dirty so * that we don't need a separate call to do this, nor does the * caller need to know anything about the icreate item. */ void xfs_icreate_log( struct xfs_trans *tp, xfs_agnumber_t agno, xfs_agblock_t agbno, unsigned int count, unsigned int inode_size, xfs_agblock_t length, unsigned int generation) { struct xfs_icreate_item *icp; icp = kmem_zone_zalloc(xfs_icreate_zone, KM_SLEEP); xfs_log_item_init(tp->t_mountp, &icp->ic_item, XFS_LI_ICREATE, &xfs_icreate_item_ops); icp->ic_format.icl_type = XFS_LI_ICREATE; icp->ic_format.icl_size = 1; /* single vector */ icp->ic_format.icl_ag = cpu_to_be32(agno); icp->ic_format.icl_agbno = cpu_to_be32(agbno); icp->ic_format.icl_count = cpu_to_be32(count); icp->ic_format.icl_isize = cpu_to_be32(inode_size); icp->ic_format.icl_length = cpu_to_be32(length); icp->ic_format.icl_gen = cpu_to_be32(generation); xfs_trans_add_item(tp, &icp->ic_item); tp->t_flags |= XFS_TRANS_DIRTY; icp->ic_item.li_desc->lid_flags |= XFS_LID_DIRTY; }
/* * Allocate a new buf log item to go with the given buffer. * Set the buffer's b_fsprivate field to point to the new * buf log item. If there are other item's attached to the * buffer (see xfs_buf_attach_iodone() below), then put the * buf log item at the front. */ void xfs_buf_item_init( xfs_buf_t *bp, xfs_mount_t *mp) { xfs_log_item_t *lip = bp->b_fspriv; xfs_buf_log_item_t *bip; int chunks; int map_size; int error; int i; /* * Check to see if there is already a buf log item for * this buffer. If there is, it is guaranteed to be * the first. If we do already have one, there is * nothing to do here so return. */ ASSERT(bp->b_target->bt_mount == mp); if (lip != NULL && lip->li_type == XFS_LI_BUF) return; bip = kmem_zone_zalloc(xfs_buf_item_zone, KM_SLEEP); xfs_log_item_init(mp, &bip->bli_item, XFS_LI_BUF, &xfs_buf_item_ops); bip->bli_buf = bp; xfs_buf_hold(bp); /* * chunks is the number of XFS_BLF_CHUNK size pieces the buffer * can be divided into. Make sure not to truncate any pieces. * map_size is the size of the bitmap needed to describe the * chunks of the buffer. * * Discontiguous buffer support follows the layout of the underlying * buffer. This makes the implementation as simple as possible. */ error = xfs_buf_item_get_format(bip, bp->b_map_count); ASSERT(error == 0); for (i = 0; i < bip->bli_format_count; i++) { chunks = DIV_ROUND_UP(BBTOB(bp->b_maps[i].bm_len), XFS_BLF_CHUNK); map_size = DIV_ROUND_UP(chunks, NBWORD); bip->bli_formats[i].blf_type = XFS_LI_BUF; bip->bli_formats[i].blf_blkno = bp->b_maps[i].bm_bn; bip->bli_formats[i].blf_len = bp->b_maps[i].bm_len; bip->bli_formats[i].blf_map_size = map_size; } /* * Put the buf item into the list of items attached to the * buffer at the front. */ if (bp->b_fspriv) bip->bli_item.li_bio_list = bp->b_fspriv; bp->b_fspriv = bip; }
/* Allocate and initialize everything we need for an incore dquot. */ STATIC struct xfs_dquot * xfs_dquot_alloc( struct xfs_mount *mp, xfs_dqid_t id, uint type) { struct xfs_dquot *dqp; dqp = kmem_zone_zalloc(xfs_qm_dqzone, KM_SLEEP); dqp->dq_flags = type; dqp->q_core.d_id = cpu_to_be32(id); dqp->q_mount = mp; INIT_LIST_HEAD(&dqp->q_lru); mutex_init(&dqp->q_qlock); init_waitqueue_head(&dqp->q_pinwait); dqp->q_fileoffset = (xfs_fileoff_t)id / mp->m_quotainfo->qi_dqperchunk; /* * Offset of dquot in the (fixed sized) dquot chunk. */ dqp->q_bufoffset = (id % mp->m_quotainfo->qi_dqperchunk) * sizeof(xfs_dqblk_t); /* * Because we want to use a counting completion, complete * the flush completion once to allow a single access to * the flush completion without blocking. */ init_completion(&dqp->q_flush); complete(&dqp->q_flush); /* * Make sure group quotas have a different lock class than user * quotas. */ switch (type) { case XFS_DQ_USER: /* uses the default lock class */ break; case XFS_DQ_GROUP: lockdep_set_class(&dqp->q_qlock, &xfs_dquot_group_class); break; case XFS_DQ_PROJ: lockdep_set_class(&dqp->q_qlock, &xfs_dquot_project_class); break; default: ASSERT(0); break; } xfs_qm_dquot_logitem_init(dqp); XFS_STATS_INC(mp, xs_qm_dquot); return dqp; }
/* * ktrace_alloc() * * Allocate a ktrace header and enough buffering for the given * number of entries. */ ktrace_t * ktrace_alloc(int nentries, int sleep) { ktrace_t *ktp; ktrace_entry_t *ktep; ktp = (ktrace_t*)kmem_zone_alloc(ktrace_hdr_zone, sleep); if (ktp == (ktrace_t*)NULL) { /* * KM_SLEEP callers don't expect failure. */ if (sleep & KM_SLEEP) panic("ktrace_alloc: NULL memory on KM_SLEEP request!"); return NULL; } /* * Special treatment for buffers with the ktrace_zentries entries */ if (nentries == ktrace_zentries) { ktep = (ktrace_entry_t*)kmem_zone_zalloc(ktrace_ent_zone, sleep); } else { ktep = (ktrace_entry_t*)kmem_zalloc((nentries * sizeof(*ktep)), sleep); } if (ktep == NULL) { /* * KM_SLEEP callers don't expect failure. */ if (sleep & KM_SLEEP) panic("ktrace_alloc: NULL memory on KM_SLEEP request!"); kmem_free(ktp, sizeof(*ktp)); return NULL; } spinlock_init(&(ktp->kt_lock), "kt_lock"); ktp->kt_entries = ktep; ktp->kt_nentries = nentries; ktp->kt_index = 0; ktp->kt_rollover = 0; return ktp; }
/* * Initialize the inode log item for a newly allocated (in-core) inode. */ void xfs_inode_item_init( struct xfs_inode *ip, struct xfs_mount *mp) { struct xfs_inode_log_item *iip; ASSERT(ip->i_itemp == NULL); iip = ip->i_itemp = kmem_zone_zalloc(xfs_ili_zone, KM_SLEEP); iip->ili_inode = ip; xfs_log_item_init(mp, &iip->ili_item, XFS_LI_INODE, &xfs_inode_item_ops); }
/* * Allocate and initialize an cud item with the given number of extents. */ struct xfs_cud_log_item * xfs_cud_init( struct xfs_mount *mp, struct xfs_cui_log_item *cuip) { struct xfs_cud_log_item *cudp; cudp = kmem_zone_zalloc(xfs_cud_zone, KM_SLEEP); xfs_log_item_init(mp, &cudp->cud_item, XFS_LI_CUD, &xfs_cud_item_ops); cudp->cud_cuip = cuip; cudp->cud_format.cud_cui_id = cuip->cui_format.cui_id; return cudp; }
/* * Allocate and initialize an bud item with the given number of extents. */ struct xfs_bud_log_item * xfs_bud_init( struct xfs_mount *mp, struct xfs_bui_log_item *buip) { struct xfs_bud_log_item *budp; budp = kmem_zone_zalloc(xfs_bud_zone, KM_SLEEP); xfs_log_item_init(mp, &budp->bud_item, XFS_LI_BUD, &xfs_bud_item_ops); budp->bud_buip = buip; budp->bud_format.bud_bui_id = buip->bui_format.bui_id; return budp; }
/* * Allocate and initialize an bui item with the given number of extents. */ struct xfs_bui_log_item * xfs_bui_init( struct xfs_mount *mp) { struct xfs_bui_log_item *buip; buip = kmem_zone_zalloc(xfs_bui_zone, KM_SLEEP); xfs_log_item_init(mp, &buip->bui_item, XFS_LI_BUI, &xfs_bui_item_ops); buip->bui_format.bui_nextents = XFS_BUI_MAX_FAST_EXTENTS; buip->bui_format.bui_id = (uintptr_t)(void *)buip; atomic_set(&buip->bui_next_extent, 0); atomic_set(&buip->bui_refcount, 2); return buip; }
/* * Initialize the inode log item for a newly allocated (in-core) inode. */ void xfs_inode_item_init( struct xfs_inode *ip, struct xfs_mount *mp) { struct xfs_inode_log_item *iip; ASSERT(ip->i_itemp == NULL); iip = ip->i_itemp = kmem_zone_zalloc(xfs_ili_zone, KM_SLEEP); iip->ili_inode = ip; xfs_log_item_init(mp, &iip->ili_item, XFS_LI_INODE, &xfs_inode_item_ops); iip->ili_format.ilf_type = XFS_LI_INODE; iip->ili_format.ilf_ino = ip->i_ino; iip->ili_format.ilf_blkno = ip->i_imap.im_blkno; iip->ili_format.ilf_len = ip->i_imap.im_len; iip->ili_format.ilf_boffset = ip->i_imap.im_boffset; }
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); }
/* * Allocate and initialize an cui item with the given number of extents. */ struct xfs_cui_log_item * xfs_cui_init( struct xfs_mount *mp, uint nextents) { struct xfs_cui_log_item *cuip; ASSERT(nextents > 0); if (nextents > XFS_CUI_MAX_FAST_EXTENTS) cuip = kmem_zalloc(xfs_cui_log_item_sizeof(nextents), KM_SLEEP); else cuip = kmem_zone_zalloc(xfs_cui_zone, KM_SLEEP); xfs_log_item_init(mp, &cuip->cui_item, XFS_LI_CUI, &xfs_cui_item_ops); cuip->cui_format.cui_nextents = nextents; cuip->cui_format.cui_id = (uintptr_t)(void *)cuip; atomic_set(&cuip->cui_next_extent, 0); atomic_set(&cuip->cui_refcount, 2); return cuip; }
/* * Read in the ondisk dquot using dqtobp() then copy it to an incore version, * and release the buffer immediately. * * If XFS_QMOPT_DQALLOC is set, allocate a dquot on disk if it needed. */ int xfs_qm_dqread( struct xfs_mount *mp, xfs_dqid_t id, uint type, uint flags, struct xfs_dquot **O_dqpp) { struct xfs_dquot *dqp; struct xfs_disk_dquot *ddqp; struct xfs_buf *bp; struct xfs_trans *tp = NULL; int error; int cancelflags = 0; dqp = kmem_zone_zalloc(xfs_qm_dqzone, KM_SLEEP); dqp->dq_flags = type; dqp->q_core.d_id = cpu_to_be32(id); dqp->q_mount = mp; INIT_LIST_HEAD(&dqp->q_lru); mutex_init(&dqp->q_qlock); init_waitqueue_head(&dqp->q_pinwait); /* * Because we want to use a counting completion, complete * the flush completion once to allow a single access to * the flush completion without blocking. */ init_completion(&dqp->q_flush); complete(&dqp->q_flush); /* * Make sure group quotas have a different lock class than user * quotas. */ switch (type) { case XFS_DQ_USER: /* uses the default lock class */ break; case XFS_DQ_GROUP: lockdep_set_class(&dqp->q_qlock, &xfs_dquot_group_class); break; case XFS_DQ_PROJ: lockdep_set_class(&dqp->q_qlock, &xfs_dquot_project_class); break; default: ASSERT(0); break; } XFS_STATS_INC(xs_qm_dquot); trace_xfs_dqread(dqp); if (flags & XFS_QMOPT_DQALLOC) { tp = xfs_trans_alloc(mp, XFS_TRANS_QM_DQALLOC); error = xfs_trans_reserve(tp, &M_RES(mp)->tr_qm_dqalloc, XFS_QM_DQALLOC_SPACE_RES(mp), 0); if (error) goto error1; cancelflags = XFS_TRANS_RELEASE_LOG_RES; } /* * get a pointer to the on-disk dquot and the buffer containing it * dqp already knows its own type (GROUP/USER). */ error = xfs_qm_dqtobp(&tp, dqp, &ddqp, &bp, flags); if (error) { /* * This can happen if quotas got turned off (ESRCH), * or if the dquot didn't exist on disk and we ask to * allocate (ENOENT). */ trace_xfs_dqread_fail(dqp); cancelflags |= XFS_TRANS_ABORT; goto error1; } /* copy everything from disk dquot to the incore dquot */ memcpy(&dqp->q_core, ddqp, sizeof(xfs_disk_dquot_t)); xfs_qm_dquot_logitem_init(dqp); /* * Reservation counters are defined as reservation plus current usage * to avoid having to add every time. */ dqp->q_res_bcount = be64_to_cpu(ddqp->d_bcount); dqp->q_res_icount = be64_to_cpu(ddqp->d_icount); dqp->q_res_rtbcount = be64_to_cpu(ddqp->d_rtbcount); /* initialize the dquot speculative prealloc thresholds */ xfs_dquot_set_prealloc_limits(dqp); /* Mark the buf so that this will stay incore a little longer */ xfs_buf_set_ref(bp, XFS_DQUOT_REF); /* * We got the buffer with a xfs_trans_read_buf() (in dqtobp()) * So we need to release with xfs_trans_brelse(). * The strategy here is identical to that of inodes; we lock * the dquot in xfs_qm_dqget() before making it accessible to * others. This is because dquots, like inodes, need a good level of * concurrency, and we don't want to take locks on the entire buffers * for dquot accesses. * Note also that the dquot buffer may even be dirty at this point, if * this particular dquot was repaired. We still aren't afraid to * brelse it because we have the changes incore. */ ASSERT(xfs_buf_islocked(bp)); xfs_trans_brelse(tp, bp); if (tp) { error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES); if (error) goto error0; } *O_dqpp = dqp; return error; error1: if (tp) xfs_trans_cancel(tp, cancelflags); error0: xfs_qm_dqdestroy(dqp); *O_dqpp = NULL; return error; }
/* * Allocate a new buf log item to go with the given buffer. * Set the buffer's b_fsprivate field to point to the new * buf log item. If there are other item's attached to the * buffer (see xfs_buf_attach_iodone() below), then put the * buf log item at the front. */ void xfs_buf_item_init( xfs_buf_t *bp, xfs_mount_t *mp) { xfs_log_item_t *lip = bp->b_fspriv; xfs_buf_log_item_t *bip; int chunks; int map_size; int error; int i; /* * Check to see if there is already a buf log item for * this buffer. If there is, it is guaranteed to be * the first. If we do already have one, there is * nothing to do here so return. */ ASSERT(bp->b_target->bt_mount == mp); if (lip != NULL && lip->li_type == XFS_LI_BUF) return; bip = kmem_zone_zalloc(xfs_buf_item_zone, KM_SLEEP); xfs_log_item_init(mp, &bip->bli_item, XFS_LI_BUF, &xfs_buf_item_ops); bip->bli_buf = bp; xfs_buf_hold(bp); /* * chunks is the number of XFS_BLF_CHUNK size pieces the buffer * can be divided into. Make sure not to truncate any pieces. * map_size is the size of the bitmap needed to describe the * chunks of the buffer. * * Discontiguous buffer support follows the layout of the underlying * buffer. This makes the implementation as simple as possible. */ error = xfs_buf_item_get_format(bip, bp->b_map_count); ASSERT(error == 0); for (i = 0; i < bip->bli_format_count; i++) { chunks = DIV_ROUND_UP(BBTOB(bp->b_maps[i].bm_len), XFS_BLF_CHUNK); map_size = DIV_ROUND_UP(chunks, NBWORD); bip->bli_formats[i].blf_type = XFS_LI_BUF; bip->bli_formats[i].blf_blkno = bp->b_maps[i].bm_bn; bip->bli_formats[i].blf_len = bp->b_maps[i].bm_len; bip->bli_formats[i].blf_map_size = map_size; } #ifdef XFS_TRANS_DEBUG /* * Allocate the arrays for tracking what needs to be logged * and what our callers request to be logged. bli_orig * holds a copy of the original, clean buffer for comparison * against, and bli_logged keeps a 1 bit flag per byte in * the buffer to indicate which bytes the callers have asked * to have logged. */ bip->bli_orig = kmem_alloc(BBTOB(bp->b_length), KM_SLEEP); memcpy(bip->bli_orig, bp->b_addr, BBTOB(bp->b_length)); bip->bli_logged = kmem_zalloc(BBTOB(bp->b_length) / NBBY, KM_SLEEP); #endif /* * Put the buf item into the list of items attached to the * buffer at the front. */ if (bp->b_fspriv) bip->bli_item.li_bio_list = bp->b_fspriv; bp->b_fspriv = bip; }
void xfs_trans_alloc_dqinfo( xfs_trans_t *tp) { (tp)->t_dqinfo = kmem_zone_zalloc(xfs_Gqm->qm_dqtrxzone, KM_SLEEP); }
STATIC void xfs_trans_alloc_dqinfo( xfs_trans_t *tp) { tp->t_dqinfo = kmem_zone_zalloc(xfs_qm_dqtrxzone, KM_SLEEP); }
static int _xfs_filestream_update_ag( xfs_inode_t *ip, xfs_inode_t *pip, xfs_agnumber_t ag) { int err = 0; xfs_mount_t *mp; xfs_mru_cache_t *cache; fstrm_item_t *item; xfs_agnumber_t old_ag; xfs_inode_t *old_pip; /* * Either ip is a regular file and pip is a directory, or ip is a * directory and pip is NULL. */ ASSERT(ip && (((ip->i_d.di_mode & S_IFREG) && pip && (pip->i_d.di_mode & S_IFDIR)) || ((ip->i_d.di_mode & S_IFDIR) && !pip))); mp = ip->i_mount; cache = mp->m_filestream; item = xfs_mru_cache_lookup(cache, ip->i_ino); if (item) { ASSERT(item->ip == ip); old_ag = item->ag; item->ag = ag; old_pip = item->pip; item->pip = pip; xfs_mru_cache_done(cache); /* * If the AG has changed, drop the old ref and take a new one, * effectively transferring the reference from old to new AG. */ if (ag != old_ag) { xfs_filestream_put_ag(mp, old_ag); xfs_filestream_get_ag(mp, ag); } /* * If ip is a file and its pip has changed, drop the old ref and * take a new one. */ if (pip && pip != old_pip) { IRELE(old_pip); IHOLD(pip); } TRACE_UPDATE(mp, ip, old_ag, xfs_filestream_peek_ag(mp, old_ag), ag, xfs_filestream_peek_ag(mp, ag)); return 0; } item = kmem_zone_zalloc(item_zone, KM_MAYFAIL); if (!item) return ENOMEM; item->ag = ag; item->ip = ip; item->pip = pip; err = xfs_mru_cache_insert(cache, ip->i_ino, item); if (err) { kmem_zone_free(item_zone, item); return err; } /* Take a reference on the AG. */ xfs_filestream_get_ag(mp, ag); /* * Take a reference on the inode itself regardless of whether it's a * regular file or a directory. */ IHOLD(ip); /* * In the case of a regular file, take a reference on the parent inode * as well to ensure it remains in-core. */ if (pip) IHOLD(pip); TRACE_UPDATE(mp, ip, ag, xfs_filestream_peek_ag(mp, ag), ag, xfs_filestream_peek_ag(mp, ag)); return 0; }
static int _xfs_filestream_update_ag( xfs_inode_t *ip, xfs_inode_t *pip, xfs_agnumber_t ag) { int err = 0; xfs_mount_t *mp; xfs_mru_cache_t *cache; fstrm_item_t *item; xfs_agnumber_t old_ag; xfs_inode_t *old_pip; ASSERT(ip && ((S_ISREG(ip->i_d.di_mode) && pip && S_ISDIR(pip->i_d.di_mode)) || (S_ISDIR(ip->i_d.di_mode) && !pip))); mp = ip->i_mount; cache = mp->m_filestream; item = xfs_mru_cache_lookup(cache, ip->i_ino); if (item) { ASSERT(item->ip == ip); old_ag = item->ag; item->ag = ag; old_pip = item->pip; item->pip = pip; xfs_mru_cache_done(cache); if (ag != old_ag) { xfs_filestream_put_ag(mp, old_ag); xfs_filestream_get_ag(mp, ag); } if (pip && pip != old_pip) { IRELE(old_pip); IHOLD(pip); } TRACE_UPDATE(mp, ip, old_ag, xfs_filestream_peek_ag(mp, old_ag), ag, xfs_filestream_peek_ag(mp, ag)); return 0; } item = kmem_zone_zalloc(item_zone, KM_MAYFAIL); if (!item) return ENOMEM; item->ag = ag; item->ip = ip; item->pip = pip; err = xfs_mru_cache_insert(cache, ip->i_ino, item); if (err) { kmem_zone_free(item_zone, item); return err; } xfs_filestream_get_ag(mp, ag); IHOLD(ip); if (pip) IHOLD(pip); TRACE_UPDATE(mp, ip, ag, xfs_filestream_peek_ag(mp, ag), ag, xfs_filestream_peek_ag(mp, ag)); return 0; }