xfs
[Top] [All Lists]

Re: xfs_bmapi

To: phil@xxxxxxxxxxxxx (Phil Schwan)
Subject: Re: xfs_bmapi
From: Jim Mostek <mostek@xxxxxxx>
Date: Mon, 8 May 2000 12:53:09 -0500 (CDT)
Cc: ananth@xxxxxxx (Rajagopal Ananthanarayanan), linux-xfs@xxxxxxxxxxx
In-reply-to: <20000508130243.C2426@linuxcare.com> from "Phil Schwan" at May 08, 2000 01:02:43 PM
Sender: owner-linux-xfs@xxxxxxxxxxx
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
>


<Prev in Thread] Current Thread [Next in Thread>