mirror of
https://github.com/torvalds/linux.git
synced 2024-11-11 06:31:49 +00:00
[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:
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;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -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 */
|
||||
|
||||
/*
|
||||
|
@ -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__ */
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user