/* * 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; }
/* This routine brings in blocks from disk one by one and assembles them * in the value buffer. If get_bmapi gets smarter later to return an extent * or list of extents, that would be great. For now, we don't expect too * many blocks per remote value, so one by one is sufficient. */ static int rmtval_get(xfs_mount_t *mp, xfs_ino_t ino, blkmap_t *blkmap, xfs_dablk_t blocknum, int valuelen, char* value) { xfs_fsblock_t bno; xfs_buf_t *bp; int clearit = 0, i = 0, length = 0, amountdone = 0; int hdrsize = 0; if (xfs_sb_version_hascrc(&mp->m_sb)) hdrsize = sizeof(struct xfs_attr3_rmt_hdr); /* ASSUMPTION: valuelen is a valid number, so use it for looping */ /* Note that valuelen is not a multiple of blocksize */ while (amountdone < valuelen) { bno = blkmap_get(blkmap, blocknum + i); if (bno == NULLFSBLOCK) { do_warn( _("remote block for attributes of inode %" PRIu64 " is missing\n"), ino); clearit = 1; break; } bp = libxfs_readbuf(mp->m_dev, XFS_FSB_TO_DADDR(mp, bno), XFS_FSB_TO_BB(mp, 1), 0, &xfs_attr3_rmt_buf_ops); if (!bp) { do_warn( _("can't read remote block for attributes of inode %" PRIu64 "\n"), ino); clearit = 1; break; } if (bp->b_error == -EFSBADCRC || bp->b_error == -EFSCORRUPTED) { do_warn( _("Corrupt remote block for attributes of inode %" PRIu64 "\n"), ino); clearit = 1; break; } ASSERT(mp->m_sb.sb_blocksize == XFS_BUF_COUNT(bp)); length = MIN(XFS_BUF_COUNT(bp) - hdrsize, valuelen - amountdone); memmove(value, bp->b_addr + hdrsize, length); amountdone += length; value += length; i++; libxfs_putbuf(bp); } return (clearit); }
/* * Prints out an ALERT message about I/O error. */ void xfs_ioerror_alert( char *func, struct xfs_mount *mp, xfs_buf_t *bp, xfs_daddr_t blkno) { xfs_alert(mp, "I/O error occurred: meta-data dev %s block 0x%llx" " (\"%s\") error %d buf count %zd", XFS_BUFTARG_NAME(XFS_BUF_TARGET(bp)), (__uint64_t)blkno, func, XFS_BUF_GETERROR(bp), XFS_BUF_COUNT(bp)); }
/* * Prints out an ALERT message about I/O error. */ void xfs_ioerror_alert( char *func, struct xfs_mount *mp, xfs_buf_t *bp, xfs_daddr_t blkno) { cmn_err(CE_ALERT, "I/O error in filesystem (\"%s\") meta-data dev %s block 0x%llx" " (\"%s\") error %d buf count %zd", (!mp || !mp->m_fsname) ? "(fs name not set)" : mp->m_fsname, XFS_BUFTARG_NAME(XFS_BUF_TARGET(bp)), (__uint64_t)blkno, func, XFS_BUF_GETERROR(bp), XFS_BUF_COUNT(bp)); }
/* * 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); } }
/* * This is called to mark bytes first through last inclusive of the given * buffer as needing to be logged when the transaction is committed. * The buffer must already be associated with the given transaction. * * First and last are numbers relative to the beginning of this buffer, * so the first byte in the buffer is numbered 0 regardless of the * value of b_blkno. */ void libxfs_trans_log_buf( xfs_trans_t *tp, xfs_buf_t *bp, uint first, uint last) { xfs_buf_log_item_t *bip; ASSERT(XFS_BUF_FSPRIVATE2(bp, xfs_trans_t *) == tp); ASSERT(XFS_BUF_FSPRIVATE(bp, void *) != NULL); ASSERT((first <= last) && (last < XFS_BUF_COUNT(bp))); #ifdef XACT_DEBUG fprintf(stderr, "dirtied buffer %p, transaction %p\n", bp, tp); #endif bip = XFS_BUF_FSPRIVATE(bp, xfs_buf_log_item_t *); tp->t_flags |= XFS_TRANS_DIRTY; bip->bli_item.li_desc->lid_flags |= XFS_LID_DIRTY; xfs_buf_item_log(bip, first, last); }