FS to physical disk block conversion

Rick C. Petty rick-freebsd2009 at kiwi-computer.com
Wed May 26 15:36:30 UTC 2010


On Wed, May 26, 2010 at 09:09:38PM +0000, Dima Naumov wrote:
> I am sorry for my English. OK my problem: i do not understand how i can 
> get real address of disk block, when i use macros fsbtodb() to convert 
> fs address to physical disk block address i receive odd result, explain 
> me please where my error.
> Example:
>         struct fs *sblock;
>         ino_t inode = 2;
>         caddr_t inoblock;
>         struct ufs2_dinode * ino;
>         ...
>         if(pread(dev_fd, ino, sizeof(struct ufs2_dinode),\
>                 (sblock->fs_bsize * fsbtodb(sblock, \
>                 ino_to_fsba(sblock, inode)))) != sizeof(struct 
> ufs2_dinode))
>                                 error(__LINE__, errno);
> After executing this string a not get correct inode in "ino". Please 
> explain, it important to me!

Your calculation isn't even close to correct.  First, ino_to_fsba() only
gives the filesystem fragment number of the containing inode block; you
need to add the offset to the actual inode.  Second, the fsbtodb() macro is
for computing the disk block number from the fragment number (disk blocks
are typically 512 bytes), but unless you know the disk block size this
macro is meaningless.  Instead you should multiply by fs_fsize (it's better
to shift by fs_fshift than to do the multiplication).  Don't multiply by
fs_bsize: the name "block" here is misleading since all UFS addresses are
in multiples of fragment size.

Another thing you may wish to consider (if you're concerned about
performance) is reading at least one UFS block at a time and using pointer
arithmetic to give you the dinode structs you need.  Something like this
makes more sense:

	uint8_t block_buffer[sblock->fs_bsize];
	...
	int64_t block_no = ino_to_fsba(sblock, inode);
	int64_t block_offset = block_no << sblock->fs_fshift;
	if (pread(dev_fd, block_buffer, sblock->fs_bsize, block_offset) !=
		sblock->fs_bsize) ...
	struct ufs2_dinode * ino =
		(struct ufs2_dinode *)block_buffer + ino_to_fsbo(sblock, inode);

HTH,

-- Rick C. Petty


More information about the freebsd-fs mailing list