[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: Christoph Hellwig <hch@lst.de> Reviewed-by: Dave Chinner <david@fromorbit.com> Signed-off-by: Niv Sardi <xaiki@sgi.com>
This commit is contained in:
committed by
Niv Sardi
parent
a194189503
commit
94e1b69d1a
@@ -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_mount_t *mp, /* file system mount structure */
|
||||
xfs_trans_t *tp, /* transaction pointer */
|
||||
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;
|
||||
}
|
||||
|
||||
/*
|
||||
|
Reference in New Issue
Block a user