From owner-freebsd-fs@FreeBSD.ORG Wed May 26 15:36:30 2010 Return-Path: Delivered-To: freebsd-fs@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 3E1481065670 for ; Wed, 26 May 2010 15:36:30 +0000 (UTC) (envelope-from rick@svn.kiwi-computer.com) Received: from svn.kiwi-computer.com (174-20-208-22.mpls.qwest.net [174.20.208.22]) by mx1.freebsd.org (Postfix) with SMTP id BC7DB8FC1D for ; Wed, 26 May 2010 15:36:29 +0000 (UTC) Received: (qmail 71128 invoked by uid 2000); 26 May 2010 15:09:46 -0000 Date: Wed, 26 May 2010 10:09:46 -0500 From: "Rick C. Petty" To: Dima Naumov Message-ID: <20100526150946.GA70983@kay.kiwi-computer.com> References: <4BFD8E12.9040909@rambler.ru> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <4BFD8E12.9040909@rambler.ru> User-Agent: Mutt/1.4.2.3i Cc: freebsd-fs@freebsd.org Subject: Re: FS to physical disk block conversion X-BeenThere: freebsd-fs@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list Reply-To: rick-freebsd2009@kiwi-computer.com List-Id: Filesystems List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 26 May 2010 15:36:30 -0000 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