Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 94e1b69d authored by Christoph Hellwig's avatar Christoph Hellwig Committed by Niv Sardi
Browse files

[XFS] merge xfs_imap into xfs_dilocate



xfs_imap is the only caller of xfs_dilocate and doesn't add any significant
value.  Merge the two functions and document the various cases we have for
inode cluster lookup in the new xfs_imap.

Also remove the unused im_agblkno and im_ioffset fields from struct xfs_imap
while we're at it.

Signed-off-by: default avatarChristoph Hellwig <hch@lst.de>
Reviewed-by: default avatarDave Chinner <david@fromorbit.com>
Signed-off-by: default avatarNiv Sardi <xaiki@sgi.com>
parent a1941895
Loading
Loading
Loading
Loading
+82 −47
Original line number Diff line number Diff line
@@ -40,6 +40,7 @@
#include "xfs_rtalloc.h"
#include "xfs_error.h"
#include "xfs_bmap.h"
#include "xfs_imap.h"


/*
@@ -1196,36 +1197,28 @@ error0:
}

/*
 * Return the location of the inode in bno/off, for mapping it into a buffer.
 * Return the location of the inode in imap, for mapping it into a buffer.
 */
/*ARGSUSED*/
int
xfs_dilocate(
xfs_imap(
	xfs_mount_t	 *mp,	/* file system mount structure */
	xfs_trans_t	 *tp,	/* transaction pointer */
	xfs_ino_t	ino,	/* inode to locate */
	xfs_fsblock_t	*bno,	/* output: block containing inode */
	int		*len,	/* output: num blocks in inode cluster */
	int		*off,	/* output: index in block of inode */
	uint		flags)	/* flags concerning inode lookup */
	struct xfs_imap	*imap,	/* location map structure */
	uint		flags)	/* flags for inode btree lookup */
{
	xfs_agblock_t	agbno;	/* block number of inode in the alloc group */
	xfs_buf_t	*agbp;	/* agi buffer */
	xfs_agino_t	agino;	/* inode number within alloc group */
	xfs_agnumber_t	agno;	/* allocation group number */
	int		blks_per_cluster; /* num blocks per inode cluster */
	xfs_agblock_t	chunk_agbno;	/* first block in inode chunk */
	xfs_agino_t	chunk_agino;	/* first agino in inode chunk */
	__int32_t	chunk_cnt;	/* count of free inodes in chunk */
	xfs_inofree_t	chunk_free;	/* mask of free inodes in chunk */
	xfs_agblock_t	cluster_agbno;	/* first block in inode cluster */
	xfs_btree_cur_t	*cur;	/* inode btree cursor */
	int		error;	/* error code */
	int		i;	/* temp state */
	int		offset;	/* index of inode in its buffer */
	int		offset_agbno;	/* blks from chunk start to inode */

	ASSERT(ino != NULLFSINO);

	/*
	 * Split up the inode number into its parts.
	 */
@@ -1240,20 +1233,20 @@ xfs_dilocate(
			return XFS_ERROR(EINVAL);
		if (agno >= mp->m_sb.sb_agcount) {
			xfs_fs_cmn_err(CE_ALERT, mp,
					"xfs_dilocate: agno (%d) >= "
					"xfs_imap: agno (%d) >= "
					"mp->m_sb.sb_agcount (%d)",
					agno,  mp->m_sb.sb_agcount);
		}
		if (agbno >= mp->m_sb.sb_agblocks) {
			xfs_fs_cmn_err(CE_ALERT, mp,
					"xfs_dilocate: agbno (0x%llx) >= "
					"xfs_imap: agbno (0x%llx) >= "
					"mp->m_sb.sb_agblocks (0x%lx)",
					(unsigned long long) agbno,
					(unsigned long) mp->m_sb.sb_agblocks);
		}
		if (ino != XFS_AGINO_TO_INO(mp, agno, agino)) {
			xfs_fs_cmn_err(CE_ALERT, mp,
					"xfs_dilocate: ino (0x%llx) != "
					"xfs_imap: ino (0x%llx) != "
					"XFS_AGINO_TO_INO(mp, agno, agino) "
					"(0x%llx)",
					ino, XFS_AGINO_TO_INO(mp, agno, agino));
@@ -1262,63 +1255,89 @@ xfs_dilocate(
#endif /* DEBUG */
		return XFS_ERROR(EINVAL);
	}
	if ((mp->m_sb.sb_blocksize >= XFS_INODE_CLUSTER_SIZE(mp))) {

	/*
	 * If the inode cluster size is the same as the blocksize or
	 * smaller we get to the buffer by simple arithmetics.
	 */
	if (XFS_INODE_CLUSTER_SIZE(mp) <= mp->m_sb.sb_blocksize) {
		offset = XFS_INO_TO_OFFSET(mp, ino);
		ASSERT(offset < mp->m_sb.sb_inopblock);
		*bno = XFS_AGB_TO_FSB(mp, agno, agbno);
		*off = offset;
		*len = 1;

		imap->im_blkno = XFS_AGB_TO_DADDR(mp, agno, agbno);
		imap->im_len = XFS_FSB_TO_BB(mp, 1);
		imap->im_boffset = (ushort)(offset << mp->m_sb.sb_inodelog);
		return 0;
	}

	blks_per_cluster = XFS_INODE_CLUSTER_SIZE(mp) >> mp->m_sb.sb_blocklog;
	if (*bno != NULLFSBLOCK) {

	/*
	 * If we get a block number passed from bulkstat we can use it to
	 * find the buffer easily.
	 */
	if (imap->im_blkno) {
		offset = XFS_INO_TO_OFFSET(mp, ino);
		ASSERT(offset < mp->m_sb.sb_inopblock);
		cluster_agbno = XFS_FSB_TO_AGBNO(mp, *bno);
		*off = ((agbno - cluster_agbno) * mp->m_sb.sb_inopblock) +
			offset;
		*len = blks_per_cluster;

		cluster_agbno = XFS_DADDR_TO_AGBNO(mp, imap->im_blkno);
		offset += (agbno - cluster_agbno) * mp->m_sb.sb_inopblock;

		imap->im_len = XFS_FSB_TO_BB(mp, blks_per_cluster);
		imap->im_boffset = (ushort)(offset << mp->m_sb.sb_inodelog);
		return 0;
	}

	/*
	 * If the inode chunks are aligned then use simple maths to
	 * find the location. Otherwise we have to do a btree
	 * lookup to find the location.
	 */
	if (mp->m_inoalign_mask) {
		offset_agbno = agbno & mp->m_inoalign_mask;
		chunk_agbno = agbno - offset_agbno;
	} else {
		xfs_btree_cur_t	*cur;	/* inode btree cursor */
		xfs_agino_t	chunk_agino; /* first agino in inode chunk */
		__int32_t	chunk_cnt; /* count of free inodes in chunk */
		xfs_inofree_t	chunk_free; /* mask of free inodes in chunk */
		xfs_buf_t	*agbp;	/* agi buffer */
		int		i;	/* temp state */

		down_read(&mp->m_peraglock);
		error = xfs_ialloc_read_agi(mp, tp, agno, &agbp);
		up_read(&mp->m_peraglock);
		if (error) {
#ifdef DEBUG
			xfs_fs_cmn_err(CE_ALERT, mp, "xfs_dilocate: "
			xfs_fs_cmn_err(CE_ALERT, mp, "xfs_imap: "
					"xfs_ialloc_read_agi() returned "
					"error %d, agno %d",
					error, agno);
#endif /* DEBUG */
			return error;
		}

		cur = xfs_inobt_init_cursor(mp, tp, agbp, agno);
		if ((error = xfs_inobt_lookup_le(cur, agino, 0, 0, &i))) {
#ifdef DEBUG
			xfs_fs_cmn_err(CE_ALERT, mp, "xfs_dilocate: "
		error = xfs_inobt_lookup_le(cur, agino, 0, 0, &i);
		if (error) {
			xfs_fs_cmn_err(CE_ALERT, mp, "xfs_imap: "
					"xfs_inobt_lookup_le() failed");
#endif /* DEBUG */
			goto error0;
		}
		if ((error = xfs_inobt_get_rec(cur, &chunk_agino, &chunk_cnt,
				&chunk_free, &i))) {
#ifdef DEBUG
			xfs_fs_cmn_err(CE_ALERT, mp, "xfs_dilocate: "

		error = xfs_inobt_get_rec(cur, &chunk_agino, &chunk_cnt,
				&chunk_free, &i);
		if (error) {
			xfs_fs_cmn_err(CE_ALERT, mp, "xfs_imap: "
					"xfs_inobt_get_rec() failed");
#endif /* DEBUG */
			goto error0;
		}
		if (i == 0) {
#ifdef DEBUG
			xfs_fs_cmn_err(CE_ALERT, mp, "xfs_dilocate: "
			xfs_fs_cmn_err(CE_ALERT, mp, "xfs_imap: "
					"xfs_inobt_get_rec() failed");
#endif /* DEBUG */
			error = XFS_ERROR(EINVAL);
		}
 error0:
		xfs_trans_brelse(tp, agbp);
		xfs_btree_del_cursor(cur, XFS_BTREE_NOERROR);
		if (error)
@@ -1326,19 +1345,35 @@ xfs_dilocate(
		chunk_agbno = XFS_AGINO_TO_AGBNO(mp, chunk_agino);
		offset_agbno = agbno - chunk_agbno;
	}

	ASSERT(agbno >= chunk_agbno);
	cluster_agbno = chunk_agbno +
		((offset_agbno / blks_per_cluster) * blks_per_cluster);
	offset = ((agbno - cluster_agbno) * mp->m_sb.sb_inopblock) +
		XFS_INO_TO_OFFSET(mp, ino);
	*bno = XFS_AGB_TO_FSB(mp, agno, cluster_agbno);
	*off = offset;
	*len = blks_per_cluster;

	imap->im_blkno = XFS_AGB_TO_DADDR(mp, agno, cluster_agbno);
	imap->im_len = XFS_FSB_TO_BB(mp, blks_per_cluster);
	imap->im_boffset = (ushort)(offset << mp->m_sb.sb_inodelog);

	/*
	 * If the inode number maps to a block outside the bounds
	 * of the file system then return NULL rather than calling
	 * read_buf and panicing when we get an error from the
	 * driver.
	 */
	if ((imap->im_blkno + imap->im_len) >
	    XFS_FSB_TO_BB(mp, mp->m_sb.sb_dblocks)) {
		xfs_fs_cmn_err(CE_ALERT, mp, "xfs_imap: "
			"(imap->im_blkno (0x%llx) + imap->im_len (0x%llx)) > "
			" XFS_FSB_TO_BB(mp, mp->m_sb.sb_dblocks) (0x%llx)",
			(unsigned long long) imap->im_blkno,
			(unsigned long long) imap->im_len,
			XFS_FSB_TO_BB(mp, mp->m_sb.sb_dblocks));
		return XFS_ERROR(EINVAL);
	}

	return 0;
error0:
	xfs_trans_brelse(tp, agbp);
	xfs_btree_del_cursor(cur, XFS_BTREE_ERROR);
	return error;
}

/*
+4 −6
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@

struct xfs_buf;
struct xfs_dinode;
struct xfs_imap;
struct xfs_mount;
struct xfs_trans;

@@ -104,17 +105,14 @@ xfs_difree(
	xfs_ino_t	*first_ino);	/* first inode in deleted cluster */

/*
 * Return the location of the inode in bno/len/off,
 * for mapping it into a buffer.
 * Return the location of the inode in imap, for mapping it into a buffer.
 */
int
xfs_dilocate(
xfs_imap(
	struct xfs_mount *mp,		/* file system mount structure */
	struct xfs_trans *tp,		/* transaction pointer */
	xfs_ino_t	ino,		/* inode to locate */
	xfs_fsblock_t	*bno,		/* output: block containing inode */
	int		*len,		/* output: num blocks in cluster*/
	int		*off,		/* output: index in block of inode */
	struct xfs_imap	*imap,		/* location map structure */
	uint		flags);		/* flags for inode btree lookup */

/*
+0 −7
Original line number Diff line number Diff line
@@ -25,14 +25,7 @@
typedef struct xfs_imap {
	xfs_daddr_t	im_blkno;	/* starting BB of inode chunk */
	uint		im_len;		/* length in BBs of inode chunk */
	xfs_agblock_t	im_agblkno;	/* logical block of inode chunk in ag */
	ushort		im_ioffset;	/* inode offset in block in "inodes" */
	ushort		im_boffset;	/* inode offset in block in bytes */
} xfs_imap_t;

struct xfs_mount;
struct xfs_trans;
int	xfs_imap(struct xfs_mount *, struct xfs_trans *, xfs_ino_t,
		 xfs_imap_t *, uint);

#endif	/* __XFS_IMAP_H__ */
+1 −59
Original line number Diff line number Diff line
@@ -266,7 +266,7 @@ xfs_inotobp(
 * in once, thus we can use the mapping information stored in the inode
 * rather than calling xfs_imap().  This allows us to avoid the overhead
 * of looking at the inode btree for small block file systems
 * (see xfs_dilocate()).
 * (see xfs_imap()).
 */
int
xfs_itobp(
@@ -2508,64 +2508,6 @@ xfs_idata_realloc(
	ASSERT(ifp->if_bytes <= XFS_IFORK_SIZE(ip, whichfork));
}




/*
 * Map inode to disk block and offset.
 *
 * mp -- the mount point structure for the current file system
 * tp -- the current transaction
 * ino -- the inode number of the inode to be located
 * imap -- this structure is filled in with the information necessary
 *	 to retrieve the given inode from disk
 * flags -- flags to pass to xfs_dilocate indicating whether or not
 *	 lookups in the inode btree were OK or not
 */
int
xfs_imap(
	xfs_mount_t	*mp,
	xfs_trans_t	*tp,
	xfs_ino_t	ino,
	xfs_imap_t	*imap,
	uint		flags)
{
	xfs_fsblock_t	fsbno;
	int		len;
	int		off;
	int		error;

	fsbno = imap->im_blkno ?
		XFS_DADDR_TO_FSB(mp, imap->im_blkno) : NULLFSBLOCK;
	error = xfs_dilocate(mp, tp, ino, &fsbno, &len, &off, flags);
	if (error)
		return error;

	imap->im_blkno = XFS_FSB_TO_DADDR(mp, fsbno);
	imap->im_len = XFS_FSB_TO_BB(mp, len);
	imap->im_agblkno = XFS_FSB_TO_AGBNO(mp, fsbno);
	imap->im_ioffset = (ushort)off;
	imap->im_boffset = (ushort)(off << mp->m_sb.sb_inodelog);

	/*
	 * If the inode number maps to a block outside the bounds
	 * of the file system then return NULL rather than calling
	 * read_buf and panicing when we get an error from the
	 * driver.
	 */
	if ((imap->im_blkno + imap->im_len) >
	    XFS_FSB_TO_BB(mp, mp->m_sb.sb_dblocks)) {
		xfs_fs_cmn_err(CE_ALERT, mp, "xfs_imap: "
			"(imap->im_blkno (0x%llx) + imap->im_len (0x%llx)) > "
			" XFS_FSB_TO_BB(mp, mp->m_sb.sb_dblocks) (0x%llx)",
			(unsigned long long) imap->im_blkno,
			(unsigned long long) imap->im_len,
			XFS_FSB_TO_BB(mp, mp->m_sb.sb_dblocks));
		return EINVAL;
	}
	return 0;
}

void
xfs_idestroy_fork(
	xfs_inode_t	*ip,
+1 −1
Original line number Diff line number Diff line
@@ -157,7 +157,7 @@ typedef struct xfs_icdinode {
#define	XFS_IFEXTIREC	0x08	/* Indirection array of extent blocks */

/*
 * Flags for xfs_inotobp, xfs_imap() and xfs_dilocate().
 * Flags for xfs_inotobp and xfs_imap().
 */
#define XFS_IMAP_BULKSTAT	0x1