/* * This function is called to verify that our callers have logged * all the bytes that they changed. * * It does this by comparing the original copy of the buffer stored in * the buf log item's bli_orig array to the current copy of the buffer * and ensuring that all bytes which mismatch are set in the bli_logged * array of the buf log item. */ STATIC void xfs_buf_item_log_check( xfs_buf_log_item_t *bip) { char *orig; char *buffer; int x; xfs_buf_t *bp; ASSERT(bip->bli_orig != NULL); ASSERT(bip->bli_logged != NULL); bp = bip->bli_buf; ASSERT(XFS_BUF_COUNT(bp) > 0); ASSERT(XFS_BUF_PTR(bp) != NULL); orig = bip->bli_orig; buffer = XFS_BUF_PTR(bp); for (x = 0; x < XFS_BUF_COUNT(bp); x++) { if (orig[x] != buffer[x] && !btst(bip->bli_logged, x)) { xfs_emerg(bp->b_mount, "%s: bip %x buffer %x orig %x index %d", __func__, bip, bp, orig, x); ASSERT(0); } } }
static int newfile( xfs_trans_t *tp, xfs_inode_t *ip, xfs_bmap_free_t *flist, xfs_fsblock_t *first, int dolocal, int logit, char *buf, int len) { xfs_buf_t *bp; xfs_daddr_t d; int error; int flags; xfs_bmbt_irec_t map; xfs_mount_t *mp; xfs_extlen_t nb; int nmap; flags = 0; mp = ip->i_mount; if (dolocal && len <= XFS_IFORK_DSIZE(ip)) { xfs_idata_realloc(ip, len, XFS_DATA_FORK); if (buf) memmove(ip->i_df.if_u1.if_data, buf, len); ip->i_d.di_size = len; ip->i_df.if_flags &= ~XFS_IFEXTENTS; ip->i_df.if_flags |= XFS_IFINLINE; ip->i_d.di_format = XFS_DINODE_FMT_LOCAL; flags = XFS_ILOG_DDATA; } else if (len > 0) { nb = XFS_B_TO_FSB(mp, len); nmap = 1; error = libxfs_bmapi(tp, ip, 0, nb, XFS_BMAPI_WRITE, first, nb, &map, &nmap, flist); if (error) { fail(_("error allocating space for a file"), error); } if (nmap != 1) { fprintf(stderr, _("%s: cannot allocate space for file\n"), progname); exit(1); } d = XFS_FSB_TO_DADDR(mp, map.br_startblock); bp = libxfs_trans_get_buf(logit ? tp : 0, mp->m_dev, d, nb << mp->m_blkbb_log, 0); memmove(XFS_BUF_PTR(bp), buf, len); if (len < XFS_BUF_COUNT(bp)) memset(XFS_BUF_PTR(bp) + len, 0, XFS_BUF_COUNT(bp) - len); if (logit) libxfs_trans_log_buf(tp, bp, 0, XFS_BUF_COUNT(bp) - 1); else libxfs_writebuf(bp, LIBXFS_EXIT_ON_FAILURE); } ip->i_d.di_size = len; return flags; }
/* * initialize a buffer full of dquots and log the whole thing */ STATIC void xfs_qm_init_dquot_blk( xfs_trans_t *tp, xfs_mount_t *mp, xfs_dqid_t id, uint type, xfs_buf_t *bp) { xfs_dqblk_t *d; int curid, i; ASSERT(tp); ASSERT(XFS_BUF_ISBUSY(bp)); ASSERT(XFS_BUF_VALUSEMA(bp) <= 0); d = (xfs_dqblk_t *)XFS_BUF_PTR(bp); /* * ID of the first dquot in the block - id's are zero based. */ curid = id - (id % XFS_QM_DQPERBLK(mp)); ASSERT(curid >= 0); memset(d, 0, BBTOB(XFS_QI_DQCHUNKLEN(mp))); for (i = 0; i < XFS_QM_DQPERBLK(mp); i++, d++, curid++) xfs_qm_dqinit_core(curid, type, d); xfs_trans_dquot_buf(tp, bp, (type & XFS_DQ_USER ? XFS_BLI_UDQUOT_BUF : ((type & XFS_DQ_PROJ) ? XFS_BLI_PDQUOT_BUF : XFS_BLI_GDQUOT_BUF))); xfs_trans_log_buf(tp, bp, 0, BBTOB(XFS_QI_DQCHUNKLEN(mp)) - 1); }
/* * This function is called to verify that our caller's have logged * all the bytes that they changed. * * It does this by comparing the original copy of the buffer stored in * the buf log item's bli_orig array to the current copy of the buffer * and ensuring that all bytes which miscompare are set in the bli_logged * array of the buf log item. */ STATIC void xfs_buf_item_log_check( xfs_buf_log_item_t *bip) { char *orig; char *buffer; int x; xfs_buf_t *bp; ASSERT(bip->bli_orig != NULL); ASSERT(bip->bli_logged != NULL); bp = bip->bli_buf; ASSERT(XFS_BUF_COUNT(bp) > 0); ASSERT(XFS_BUF_PTR(bp) != NULL); orig = bip->bli_orig; buffer = XFS_BUF_PTR(bp); for (x = 0; x < XFS_BUF_COUNT(bp); x++) { if (orig[x] != buffer[x] && !btst(bip->bli_logged, x)) cmn_err(CE_PANIC, "xfs_buf_item_log_check bip %x buffer %x orig %x index %d", bip, bp, orig, x); } }
/* * Maps a dquot to the buffer containing its on-disk version. * This returns a ptr to the buffer containing the on-disk dquot * in the bpp param, and a ptr to the on-disk dquot within that buffer */ STATIC int xfs_qm_dqtobp( xfs_trans_t **tpp, xfs_dquot_t *dqp, xfs_disk_dquot_t **O_ddpp, xfs_buf_t **O_bpp, uint flags) { xfs_bmbt_irec_t map; int nmaps, error; xfs_buf_t *bp; xfs_inode_t *quotip; xfs_mount_t *mp; xfs_disk_dquot_t *ddq; xfs_dqid_t id; boolean_t newdquot; xfs_trans_t *tp = (tpp ? *tpp : NULL); mp = dqp->q_mount; id = be32_to_cpu(dqp->q_core.d_id); nmaps = 1; newdquot = B_FALSE; /* * If we don't know where the dquot lives, find out. */ if (dqp->q_blkno == (xfs_daddr_t) 0) { /* We use the id as an index */ dqp->q_fileoffset = (xfs_fileoff_t)id / XFS_QM_DQPERBLK(mp); nmaps = 1; quotip = XFS_DQ_TO_QIP(dqp); xfs_ilock(quotip, XFS_ILOCK_SHARED); /* * Return if this type of quotas is turned off while we didn't * have an inode lock */ if (XFS_IS_THIS_QUOTA_OFF(dqp)) { xfs_iunlock(quotip, XFS_ILOCK_SHARED); return (ESRCH); } /* * Find the block map; no allocations yet */ error = xfs_bmapi(NULL, quotip, dqp->q_fileoffset, XFS_DQUOT_CLUSTER_SIZE_FSB, XFS_BMAPI_METADATA, NULL, 0, &map, &nmaps, NULL); xfs_iunlock(quotip, XFS_ILOCK_SHARED); if (error) return (error); ASSERT(nmaps == 1); ASSERT(map.br_blockcount == 1); /* * offset of dquot in the (fixed sized) dquot chunk. */ dqp->q_bufoffset = (id % XFS_QM_DQPERBLK(mp)) * sizeof(xfs_dqblk_t); if (map.br_startblock == HOLESTARTBLOCK) { /* * We don't allocate unless we're asked to */ if (!(flags & XFS_QMOPT_DQALLOC)) return (ENOENT); ASSERT(tp); if ((error = xfs_qm_dqalloc(tpp, mp, dqp, quotip, dqp->q_fileoffset, &bp))) return (error); tp = *tpp; newdquot = B_TRUE; } else { /* * store the blkno etc so that we don't have to do the * mapping all the time */ dqp->q_blkno = XFS_FSB_TO_DADDR(mp, map.br_startblock); } } ASSERT(dqp->q_blkno != DELAYSTARTBLOCK); ASSERT(dqp->q_blkno != HOLESTARTBLOCK); /* * Read in the buffer, unless we've just done the allocation * (in which case we already have the buf). */ if (! newdquot) { xfs_dqtrace_entry(dqp, "DQTOBP READBUF"); if ((error = xfs_trans_read_buf(mp, tp, mp->m_ddev_targp, dqp->q_blkno, XFS_QI_DQCHUNKLEN(mp), 0, &bp))) { return (error); } if (error || !bp) return XFS_ERROR(error); } ASSERT(XFS_BUF_ISBUSY(bp)); ASSERT(XFS_BUF_VALUSEMA(bp) <= 0); /* * calculate the location of the dquot inside the buffer. */ ddq = (xfs_disk_dquot_t *)((char *)XFS_BUF_PTR(bp) + dqp->q_bufoffset); /* * A simple sanity check in case we got a corrupted dquot... */ if (xfs_qm_dqcheck(ddq, id, dqp->dq_flags & XFS_DQ_ALLTYPES, flags & (XFS_QMOPT_DQREPAIR|XFS_QMOPT_DOWARN), "dqtobp")) { if (!(flags & XFS_QMOPT_DQREPAIR)) { xfs_trans_brelse(tp, bp); return XFS_ERROR(EIO); } XFS_BUF_BUSY(bp); /* We dirtied this */ } *O_bpp = bp; *O_ddpp = ddq; return (0); }