コード例 #1
0
ファイル: phase3.c プロジェクト: djwong/xfsprogs
static void
process_agi_unlinked(
	struct xfs_mount	*mp,
	xfs_agnumber_t		agno)
{
	struct xfs_buf		*bp;
	struct xfs_agi		*agip;
	xfs_agnumber_t		i;
	int			agi_dirty = 0;

	bp = libxfs_readbuf(mp->m_dev,
			XFS_AG_DADDR(mp, agno, XFS_AGI_DADDR(mp)),
			mp->m_sb.sb_sectsize/BBSIZE, 0, &xfs_agi_buf_ops);
	if (!bp)
		do_error(_("cannot read agi block %" PRId64 " for ag %u\n"),
			XFS_AG_DADDR(mp, agno, XFS_AGI_DADDR(mp)), agno);

	agip = XFS_BUF_TO_AGI(bp);

	ASSERT(be32_to_cpu(agip->agi_seqno) == agno);

	for (i = 0; i < XFS_AGI_UNLINKED_BUCKETS; i++)  {
		if (agip->agi_unlinked[i] != cpu_to_be32(NULLAGINO)) {
			agip->agi_unlinked[i] = cpu_to_be32(NULLAGINO);
			agi_dirty = 1;
		}
	}

	if (agi_dirty)
		libxfs_writebuf(bp, 0);
	else
		libxfs_putbuf(bp);
}
コード例 #2
0
ファイル: xfsutil.c プロジェクト: brkt/fuse-xfs
int copy_extent_to_buffer(xfs_mount_t *mp, xfs_bmbt_irec_t rec, void *buffer, off_t offset, size_t len) {
    xfs_buf_t *block_buffer;
    int64_t copylen, copy_start;
    xfs_daddr_t block, start, end;
    char *src;
    off_t cofs = offset;
    
    xfs_off_t block_start;
    xfs_daddr_t block_size = XFS_FSB_TO_B(mp, 1);
    //xfs_daddr_t extent_size = XFS_FSB_TO_B(mp, rec.br_blockcount);
    xfs_daddr_t extent_start = XFS_FSB_TO_B(mp, rec.br_startoff);

    /* compute a block to start reading from */
    if (offset >= extent_start) {
        start = XFS_B_TO_FSBT(mp, offset - extent_start);
    } else {
        buffer = buffer + extent_start - offset;
        cofs += extent_start - offset;
        start = 0;
    }

    end = min(rec.br_blockcount, XFS_B_TO_FSBT(mp, offset + len - extent_start - 1) + 1);

    for (block=start; block<end; block++) {
        block_start = XFS_FSB_TO_B(mp, (rec.br_startoff + block));        
        block_buffer = libxfs_readbuf(mp->m_dev, XFS_FSB_TO_DADDR(mp, (rec.br_startblock + block)), 
                                      XFS_FSB_TO_BB(mp, 1), 0);
        if (block_buffer == NULL) {
            printf("Buffer error\n");
            return XFS_ERROR(EIO);
        }

        src = block_buffer->b_addr;
        copy_start = block_start;
        copylen = block_size;
        if (block_start < offset) {
            copylen = block_size + block_start - offset;
            copy_start = (block_size - copylen) + block_start;
            src = block_buffer->b_addr + (block_size - copylen);
        }
        if ((block_start + block_size) > (offset + len)) {
            copylen = offset + len - copy_start;
        }

        if (copylen > 0) {
            memcpy(buffer, src, copylen);
            buffer += copylen;
            cofs += copylen;
        }
        libxfs_putbuf(block_buffer);
    }
    
    return 0;
}
コード例 #3
0
ファイル: init.c プロジェクト: kenhys/partclone
/*
 * Initialize realtime fields in the mount structure.
 */
static int
rtmount_init(
	xfs_mount_t	*mp,	/* file system mount structure */
	int		flags)
{
	xfs_buf_t	*bp;	/* buffer for last block of subvolume */
	xfs_daddr_t	d;	/* address of last block of subvolume */
	xfs_sb_t	*sbp;	/* filesystem superblock copy in mount */

	sbp = &mp->m_sb;
	if (sbp->sb_rblocks == 0)
		return 0;
	if (mp->m_rtdev_targp->dev == 0 && !(flags & LIBXFS_MOUNT_DEBUGGER)) {
		fprintf(stderr, _("%s: filesystem has a realtime subvolume\n"),
			progname);
		return -1;
	}
	mp->m_rsumlevels = sbp->sb_rextslog + 1;
	mp->m_rsumsize =
		(uint)sizeof(xfs_suminfo_t) * mp->m_rsumlevels *
		sbp->sb_rbmblocks;
	mp->m_rsumsize = roundup(mp->m_rsumsize, sbp->sb_blocksize);
	mp->m_rbmip = mp->m_rsumip = NULL;

	/*
	 * Allow debugger to be run without the realtime device present.
	 */
	if (flags & LIBXFS_MOUNT_DEBUGGER)
		return 0;

	/*
	 * Check that the realtime section is an ok size.
	 */
	d = (xfs_daddr_t)XFS_FSB_TO_BB(mp, mp->m_sb.sb_rblocks);
	if (XFS_BB_TO_FSB(mp, d) != mp->m_sb.sb_rblocks) {
		fprintf(stderr, _("%s: realtime init - %llu != %llu\n"),
			progname, (unsigned long long) XFS_BB_TO_FSB(mp, d),
			(unsigned long long) mp->m_sb.sb_rblocks);
		return -1;
	}
	bp = libxfs_readbuf(mp->m_rtdev,
			d - XFS_FSB_TO_BB(mp, 1), XFS_FSB_TO_BB(mp, 1), 0, NULL);
	if (bp == NULL) {
		fprintf(stderr, _("%s: realtime size check failed\n"),
			progname);
		return -1;
	}
	libxfs_putbuf(bp);
	return 0;
}
コード例 #4
0
ファイル: attr_repair.c プロジェクト: djwong/xfsprogs
/* 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);
}
コード例 #5
0
ファイル: trans.c プロジェクト: djwong/xfsprogs
void
libxfs_trans_brelse(
	xfs_trans_t		*tp,
	xfs_buf_t		*bp)
{
	xfs_buf_log_item_t	*bip;
#ifdef XACT_DEBUG
	fprintf(stderr, "released buffer %p, transaction %p\n", bp, tp);
#endif

	if (tp == NULL) {
		ASSERT(XFS_BUF_FSPRIVATE2(bp, void *) == NULL);
		libxfs_putbuf(bp);
		return;
	}
コード例 #6
0
ファイル: init.c プロジェクト: kenhys/partclone
/*
 * Mount structure initialization, provides a filled-in xfs_mount_t
 * such that the numerous XFS_* macros can be used.  If dev is zero,
 * no IO will be performed (no size checks, read root inodes).
 */
xfs_mount_t *
libxfs_mount(
	xfs_mount_t	*mp,
	xfs_sb_t	*sb,
	dev_t		dev,
	dev_t		logdev,
	dev_t		rtdev,
	int		flags)
{
	xfs_daddr_t	d;
	xfs_buf_t	*bp;
	xfs_sb_t	*sbp;
	int		error;

	libxfs_buftarg_init(mp, dev, logdev, rtdev);

	mp->m_flags = (LIBXFS_MOUNT_32BITINODES|LIBXFS_MOUNT_32BITINOOPT);
	mp->m_sb = *sb;
	INIT_RADIX_TREE(&mp->m_perag_tree, GFP_KERNEL);
	sbp = &(mp->m_sb);

	xfs_sb_mount_common(mp, sb);

	xfs_alloc_compute_maxlevels(mp);
	xfs_bmap_compute_maxlevels(mp, XFS_DATA_FORK);
	xfs_bmap_compute_maxlevels(mp, XFS_ATTR_FORK);
	xfs_ialloc_compute_maxlevels(mp);

	if (sbp->sb_imax_pct) {
		/* Make sure the maximum inode count is a multiple of the
		 * units we allocate inodes in.
		 */
		mp->m_maxicount = (sbp->sb_dblocks * sbp->sb_imax_pct) / 100;
		mp->m_maxicount = ((mp->m_maxicount / mp->m_ialloc_blks) *
				  mp->m_ialloc_blks)  << sbp->sb_inopblog;
	} else
		mp->m_maxicount = 0;

	mp->m_inode_cluster_size = XFS_INODE_BIG_CLUSTER_SIZE;

	/*
	 * Set whether we're using stripe alignment.
	 */
	if (xfs_sb_version_hasdalign(&mp->m_sb)) {
		mp->m_dalign = sbp->sb_unit;
		mp->m_swidth = sbp->sb_width;
	}

	/*
	 * Set whether we're using inode alignment.
	 */
	if (xfs_sb_version_hasalign(&mp->m_sb) &&
	    mp->m_sb.sb_inoalignmt >=
	    XFS_B_TO_FSBT(mp, mp->m_inode_cluster_size))
		mp->m_inoalign_mask = mp->m_sb.sb_inoalignmt - 1;
	else
		mp->m_inoalign_mask = 0;
	/*
	 * If we are using stripe alignment, check whether
	 * the stripe unit is a multiple of the inode alignment
	 */
	if (mp->m_dalign && mp->m_inoalign_mask &&
					!(mp->m_dalign & mp->m_inoalign_mask))
		mp->m_sinoalign = mp->m_dalign;
	else
		mp->m_sinoalign = 0;

	/*
	 * Check that the data (and log if separate) are an ok size.
	 */
	d = (xfs_daddr_t) XFS_FSB_TO_BB(mp, mp->m_sb.sb_dblocks);
	if (XFS_BB_TO_FSB(mp, d) != mp->m_sb.sb_dblocks) {
		fprintf(stderr, _("%s: size check failed\n"), progname);
		if (!(flags & LIBXFS_MOUNT_DEBUGGER))
			return NULL;
	}

	/*
	 * We automatically convert v1 inodes to v2 inodes now, so if
	 * the NLINK bit is not set we can't operate on the filesystem.
	 */
	if (!(sbp->sb_versionnum & XFS_SB_VERSION_NLINKBIT)) {

		fprintf(stderr, _(
	"%s: V1 inodes unsupported. Please try an older xfsprogs.\n"),
				 progname);
		exit(1);
	}

	/* Check for supported directory formats */
	if (!(sbp->sb_versionnum & XFS_SB_VERSION_DIRV2BIT)) {

		fprintf(stderr, _(
	"%s: V1 directories unsupported. Please try an older xfsprogs.\n"),
				 progname);
		exit(1);
	}

	/* check for unsupported other features */
	if (!xfs_sb_good_version(sbp)) {
		fprintf(stderr, _(
	"%s: Unsupported features detected. Please try a newer xfsprogs.\n"),
				 progname);
		exit(1);
	}

	xfs_da_mount(mp);

	if (xfs_sb_version_hasattr2(&mp->m_sb))
		mp->m_flags |= LIBXFS_MOUNT_ATTR2;

	/* Initialize the precomputed transaction reservations values */
	xfs_trans_init(mp);

	if (dev == 0)	/* maxtrres, we have no device so leave now */
		return mp;

	bp = libxfs_readbuf(mp->m_dev,
			d - XFS_FSS_TO_BB(mp, 1), XFS_FSS_TO_BB(mp, 1),
			!(flags & LIBXFS_MOUNT_DEBUGGER), NULL);
	if (!bp) {
		fprintf(stderr, _("%s: data size check failed\n"), progname);
		if (!(flags & LIBXFS_MOUNT_DEBUGGER))
			return NULL;
	} else
		libxfs_putbuf(bp);

	if (mp->m_logdev_targp->dev &&
	    mp->m_logdev_targp->dev != mp->m_ddev_targp->dev) {
		d = (xfs_daddr_t) XFS_FSB_TO_BB(mp, mp->m_sb.sb_logblocks);
		if ( (XFS_BB_TO_FSB(mp, d) != mp->m_sb.sb_logblocks) ||
		     (!(bp = libxfs_readbuf(mp->m_logdev_targp,
					d - XFS_FSB_TO_BB(mp, 1),
					XFS_FSB_TO_BB(mp, 1),
					!(flags & LIBXFS_MOUNT_DEBUGGER), NULL))) ) {
			fprintf(stderr, _("%s: log size checks failed\n"),
					progname);
			if (!(flags & LIBXFS_MOUNT_DEBUGGER))
				return NULL;
		}
		if (bp)
			libxfs_putbuf(bp);
	}

	/* Initialize realtime fields in the mount structure */
	if (rtmount_init(mp, flags)) {
		fprintf(stderr, _("%s: realtime device init failed\n"),
			progname);
			return NULL;
	}

	error = libxfs_initialize_perag(mp, sbp->sb_agcount, &mp->m_maxagi);
	if (error) {
		fprintf(stderr, _("%s: perag init failed\n"),
			progname);
		exit(1);
	}

	return mp;
}
コード例 #7
0
ファイル: attr_repair.c プロジェクト: djwong/xfsprogs
/*
 * Start processing for a leaf or fuller btree.
 * A leaf directory is one where the attribute fork is too big for
 * the inode  but is small enough to fit into one btree block
 * outside the inode. This code is modelled after process_leaf_dir_block.
 *
 * returns 0 if things are ok, 1 if bad (attributes needs to be junked)
 * repair is set, if anything was changed, but attributes can live thru it
 */
static int
process_longform_attr(
	xfs_mount_t	*mp,
	xfs_ino_t	ino,
	xfs_dinode_t	*dip,
	blkmap_t	*blkmap,
	int		*repair)	/* out - 1 if something was fixed */
{
	xfs_attr_leafblock_t	*leaf;
	xfs_fsblock_t	bno;
	xfs_buf_t	*bp;
	xfs_dahash_t	next_hashval;
	int		repairlinks = 0;
	struct xfs_attr3_icleaf_hdr leafhdr;
	int		error;

	*repair = 0;

	bno = blkmap_get(blkmap, 0);

	if ( bno == NULLFSBLOCK ) {
		if (dip->di_aformat == XFS_DINODE_FMT_EXTENTS &&
				be16_to_cpu(dip->di_anextents) == 0)
			return(0); /* the kernel can handle this state */
		do_warn(
	_("block 0 of inode %" PRIu64 " attribute fork is missing\n"),
			ino);
		return(1);
	}
	/* FIX FOR bug 653709 -- EKN */
	if (mp->m_sb.sb_agcount < XFS_FSB_TO_AGNO(mp, bno)) {
		do_warn(
	_("agno of attribute fork of inode %" PRIu64 " out of regular partition\n"), ino);
		return(1);
	}

	bp = libxfs_readbuf(mp->m_dev, XFS_FSB_TO_DADDR(mp, bno),
				XFS_FSB_TO_BB(mp, 1), 0, &xfs_da3_node_buf_ops);
	if (!bp) {
		do_warn(
	_("can't read block 0 of inode %" PRIu64 " attribute fork\n"),
			ino);
		return(1);
	}
	if (bp->b_error == -EFSBADCRC)
		(*repair)++;

	/* is this block sane? */
	if (__check_attr_header(mp, bp, ino)) {
		*repair = 0;
		libxfs_putbuf(bp);
		return 1;
	}

	/* verify leaf block */
	leaf = bp->b_addr;
	xfs_attr3_leaf_hdr_from_disk(mp->m_attr_geo, &leafhdr, leaf);

	/* check sibling pointers in leaf block or root block 0 before
	* we have to release the btree block
	*/
	if (leafhdr.forw != 0 || leafhdr.back != 0)  {
		if (!no_modify)  {
			do_warn(
	_("clearing forw/back pointers in block 0 for attributes in inode %" PRIu64 "\n"),
				ino);
			repairlinks = 1;
			leafhdr.forw = 0;
			leafhdr.back = 0;
			xfs_attr3_leaf_hdr_to_disk(mp->m_attr_geo,
						   leaf, &leafhdr);
		} else  {
			do_warn(
	_("would clear forw/back pointers in block 0 for attributes in inode %" PRIu64 "\n"), ino);
		}
	}

	/*
	 * use magic number to tell us what type of attribute this is.
	 * it's possible to have a node or leaf attribute in either an
	 * extent format or btree format attribute fork.
	 */
	switch (leafhdr.magic) {
	case XFS_ATTR_LEAF_MAGIC:	/* leaf-form attribute */
	case XFS_ATTR3_LEAF_MAGIC:
		if (process_leaf_attr_block(mp, leaf, 0, ino, blkmap,
				0, &next_hashval, repair)) {
			*repair = 0;
			/* the block is bad.  lose the attribute fork. */
			libxfs_putbuf(bp);
			return(1);
		}
		*repair = *repair || repairlinks;
		break;

	case XFS_DA_NODE_MAGIC:		/* btree-form attribute */
	case XFS_DA3_NODE_MAGIC:
		/* must do this now, to release block 0 before the traversal */
		if ((*repair || repairlinks) && !no_modify) {
			*repair = 1;
			libxfs_writebuf(bp, 0);
		} else
			libxfs_putbuf(bp);
		error = process_node_attr(mp, ino, dip, blkmap); /* + repair */
		if (error)
			*repair = 0;
		return error;
	default:
		do_warn(
	_("bad attribute leaf magic # %#x for dir ino %" PRIu64 "\n"),
			be16_to_cpu(leaf->hdr.info.magic), ino);
		libxfs_putbuf(bp);
		*repair = 0;
		return(1);
	}

	if (*repair && !no_modify)
		libxfs_writebuf(bp, 0);
	else
		libxfs_putbuf(bp);

	return(0);  /* repair may be set */
}
コード例 #8
0
ファイル: attr_repair.c プロジェクト: djwong/xfsprogs
/*
 * returns 0 if the attribute fork is ok, 1 if it has to be junked.
 */
static int
process_leaf_attr_level(xfs_mount_t	*mp,
			da_bt_cursor_t	*da_cursor)
{
	int			repair;
	xfs_attr_leafblock_t	*leaf;
	xfs_buf_t		*bp;
	xfs_ino_t		ino;
	xfs_fsblock_t		dev_bno;
	xfs_dablk_t		da_bno;
	xfs_dablk_t		prev_bno;
	xfs_dahash_t		current_hashval = 0;
	xfs_dahash_t		greatest_hashval;
	struct xfs_attr3_icleaf_hdr leafhdr;

	da_bno = da_cursor->level[0].bno;
	ino = da_cursor->ino;
	prev_bno = 0;

	do {
		repair = 0;
		dev_bno = blkmap_get(da_cursor->blkmap, da_bno);
		/*
		 * 0 is the root block and no block
		 * pointer can point to the root block of the btree
		 */
		ASSERT(da_bno != 0);

		if (dev_bno == NULLFSBLOCK) {
			do_warn(
	_("can't map block %u for attribute fork for inode %" PRIu64 "\n"),
				da_bno, ino);
			goto error_out;
		}

		bp = libxfs_readbuf(mp->m_dev, XFS_FSB_TO_DADDR(mp, dev_bno),
				    XFS_FSB_TO_BB(mp, 1), 0,
				    &xfs_attr3_leaf_buf_ops);
		if (!bp) {
			do_warn(
	_("can't read file block %u (fsbno %" PRIu64 ") for attribute fork of inode %" PRIu64 "\n"),
				da_bno, dev_bno, ino);
			goto error_out;
		}

		leaf = bp->b_addr;
		xfs_attr3_leaf_hdr_from_disk(mp->m_attr_geo, &leafhdr, leaf);

		/* check magic number for leaf directory btree block */
		if (!(leafhdr.magic == XFS_ATTR_LEAF_MAGIC ||
		      leafhdr.magic == XFS_ATTR3_LEAF_MAGIC)) {
			do_warn(
	_("bad attribute leaf magic %#x for inode %" PRIu64 "\n"),
				 leafhdr.magic, ino);
			libxfs_putbuf(bp);
			goto error_out;
		}

		/*
		 * for each block, process the block, verify its path,
		 * then get next block.  update cursor values along the way
		 */
		if (process_leaf_attr_block(mp, leaf, da_bno, ino,
				da_cursor->blkmap, current_hashval,
				&greatest_hashval, &repair))  {
			libxfs_putbuf(bp);
			goto error_out;
		}

		/*
		 * index can be set to hdr.count so match the
		 * indexes of the interior blocks -- which at the
		 * end of the block will point to 1 after the final
		 * real entry in the block
		 */
		da_cursor->level[0].hashval = greatest_hashval;
		da_cursor->level[0].bp = bp;
		da_cursor->level[0].bno = da_bno;
		da_cursor->level[0].index = leafhdr.count;
		da_cursor->level[0].dirty = repair;

		if (leafhdr.back != prev_bno)  {
			do_warn(
	_("bad sibling back pointer for block %u in attribute fork for inode %" PRIu64 "\n"),
				da_bno, ino);
			libxfs_putbuf(bp);
			goto error_out;
		}

		prev_bno = da_bno;
		da_bno = leafhdr.forw;

		if (da_bno != 0) {
			if (verify_da_path(mp, da_cursor, 0, XFS_ATTR_FORK)) {
				libxfs_putbuf(bp);
				goto error_out;
			}
		}

		current_hashval = greatest_hashval;
                /*
		 * If block looks ok but CRC didn't match, make sure to
		 * recompute it.
		 */
		if (!no_modify && bp->b_error == -EFSBADCRC)
			repair++;

		if (repair && !no_modify)
			libxfs_writebuf(bp, 0);
		else
			libxfs_putbuf(bp);
	} while (da_bno != 0);

	if (verify_final_da_path(mp, da_cursor, 0, XFS_ATTR_FORK))  {
		/*
		 * verify the final path up (right-hand-side) if still ok
		 */
		do_warn(
	_("bad hash path in attribute fork for inode %" PRIu64 "\n"),
			da_cursor->ino);
		goto error_out;
	}

	/* releases all buffers holding interior btree blocks */
	release_da_cursor(mp, da_cursor, 0);
	return(0);

error_out:
	/* release all buffers holding interior btree blocks */
	err_release_da_cursor(mp, da_cursor, 0);
	return(1);
}