Your assumption is wrong. xfs_bmapi takes the 3rd parameter as a file system
block number.
Look at xfs_iomap_read(). It converts the given offset into
the offset_fsb by using:
offset_fsb = XFS_B_TO_FSBT(mp, offset);
This is what is passed to XFS_BMAPI.
The macro does:
#define XFS_B_TO_FSBT(mp,b) (((__uint64_t)(b)) >> (mp)->m_sb.sb_blocklog)
This is:
__uint8_t sb_blocklog; /* log2 of sb_blocksize */
sb_blocklog is 12 when your file system blocksize is 4096. We can create
other file system block sizes which are bigger/smaller (hasn't been tested
yet on Linux and there is a work item for this).
Anywho, the offset gets converted to the file system block # using
the above macro and xfs_bmapi returns an array of imap's that are once
again in sb_blocksize units (for startblock). This then gets converted
in _xfs_imap_to_bmap into the sector size units (512 byte units) using
pbmapp->pbm_bn = XFS_FSB_TO_DB_IO(io, start_block);
This is really just doing:
XFS_FSB_TO_DADDR()
which is doing:
XFS_AGB_TO_DADDR(mp, XFS_FSB_TO_AGNO(mp,fsbno), XFS_FSB_TO_AGBNO(mp,fsbno))
which is doing:
#define XFS_AGB_TO_DADDR(mp,agno,agbno) \
((daddr_t)(XFS_FSB_TO_BB(mp, (xfs_fsblock_t)(agno) *
(mp)->m_sb.sb_agblocks + (agbno))))
which is doing:
XFS_FSB_TO_BB(mp,fsbno) ((fsbno) << (mp)->m_blkbb_log)
Note that XFS_AGB_TO_DADDR adds some for each ag header space beyond the zeroth
AG.
The m_blkbb_log is really sb_blocklog - BBSHIFT.
BBSHIFT (basic block shift) is always 9 since 2^9 is 512.
sb_blocklog varies with the file system block size. In the current default
case, sb_blocklog is 12 so XFS_FSB_TO_DB_IO will left shift by 3 in the zeroth
AG and will add a header area and then left shift by 3 for other ags.
Summarizing, the input to xfs_bmapi's 3rd parameter is in file system block
units which varies depending on the file system block size. see mkfs' output.
The output from xfs_bmapi are xfs_bmbt_irec_t structures which contain
a block number in file system block units without adjustment for all but
the zeroth AG headers. XFS_FSB_TO_DB_IO() converts these block numbers into
512 units such that one can find the block on disk.
The pagebuf_bmap routine handles all this conversion. It's input is
byte offset and the output is actual 512 block number to read.
Jim
>
>On May 08, Rajagopal Ananthanarayanan wrote:
>> Phil Schwan wrote:
>> > Am I correct in seeing that xfs_bmapi() treats argument 3 (block
>> > number) as pagesize blocks? (If not, the rest of my questions don't
>> > really apply...)
>>
>> I don't think so. xfs_bmapi & in fact most of xfs works
>> with 512-byte blocks. The exception is fs/page_buf.c,
>> where the I/O paths work on PAGE_SIZE sized buffers.
>
>Hmm, this is very odd then.
>
>xfs_bmapi(bno=x) returns y, and xfs_bmapi(bno=x+1) returns y + 8, and
>I continue along those lines and reach the end of the file 8 times
>faster than expected.
>
>In the end, I do something like this:
>
> xfsblock = block >> 3;
>
> error = xfs_bmapi(NULL, xfs_inode, xfsblock, 1, 0, NULL, 0, &mval,
> &nmaps, NULL);
> return XFS_FSB_TO_DB(xfs_inode, mval.br_startblock) + (block & 7);
>
>and it seems to work. Oh well, I guess I can slather it in FIXMEs and
>cross that bridge when we come to it.
>
>-Phil
>
|