Date: Wed, 26 May 2010 10:09:46 -0500 From: "Rick C. Petty" <rick-freebsd2009@kiwi-computer.com> To: Dima Naumov <shadow_user@rambler.ru> Cc: freebsd-fs@freebsd.org Subject: Re: FS to physical disk block conversion Message-ID: <20100526150946.GA70983@kay.kiwi-computer.com> In-Reply-To: <4BFD8E12.9040909@rambler.ru> References: <4BFD8E12.9040909@rambler.ru>
next in thread | previous in thread | raw e-mail | index | archive | help
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
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20100526150946.GA70983>