Return to BSD News archive
Xref: sserve comp.unix.internals:7052 comp.unix.bsd:13719 Path: sserve!newshost.anu.edu.au!harbinger.cc.monash.edu.au!yeshua.marcam.com!zip.eecs.umich.edu!newsxfer.itd.umich.edu!gatech!news.byu.edu!cwis.isu.edu!u.cc.utah.edu!cs.weber.edu!terry From: terry@cs.weber.edu (Terry Lambert) Newsgroups: comp.unix.internals,comp.unix.bsd Subject: Re: UFS directory entry - when is d_reclen == 0? Date: 9 Apr 1994 02:03:47 GMT Organization: Weber State University, Ogden, UT Lines: 63 Message-ID: <2o52e3$io6@u.cc.utah.edu> References: <2nq066$h2f@courier.urbana.mcd.mot.com> NNTP-Posting-Host: cs.weber.edu In article <2nq066$h2f@courier.urbana.mcd.mot.com> smadhur@urbana.mcd.mot.com writes: > >In a lot of places in UFS code, I see code like > > if (...d_reclen == 0 || ...) > skip DIRBLKSZ bytes > >implying that d_reclen == 0 indicates an invalid directory entry. >I checked fsck code and in the case of invalid entry, d_ino and >d_namlen are being set to 0 but no where could I find d_reclen >being set to 0. Can someone tell me where/when d_reclen will be >set to 0? This is not what it implies. You reference "the UFS code"; it would be nice to know which vender you refer to, since the explanation is different for at least one of them. I will assume you are referring to the majority of UFS code, ie: SVR4 or BSD but not some recent Solaris and not MP safe. The 0 record length is the indicator that there are no valid directory entries following the current one. Basically, each directory block is divided into an offset list (by record length of each record in the block being relative to the start of the current record); records other than the first record can be made to "not exist" by adjusting the record length in the previous record in the block to include both the previous and the current record. A process whereby this space is cleaned up is in the direnter() code (it's usually called ufs_direnter) and is called "compaction". The purpose of compaction is to put free space on the end of a directory block instead of fragmented throughout the directory block. Compaction is possible because the dirctory entry blocks are treated atomically (this is also done by the vfsop readdir as a result of the getdents() system call). The difference between the record length and the results of the DIRSIZ() macro indicate how much free space follows a record (NOTE: there is an invalid structure packing alignment assumption in this macro on most systems! Change entry sizes to non-word-aligned values at your own risk!). For records which are the first record in a directory block, there is no previous block that could include the current block. Therefore, if there is no compaction that can take place (ie: there are no more entries in the block), the record size is set to 0 to indicate that the current block should be ignored by the scanning routine. Older systems and systems that can't compact immediately have a different lookup philosophy; instead of zeroing the record, they zero the inode number of the first record and leave its reclen as a pointer to the first valid entry. This is a dumb thing to do, since it can prohibit recovery of deleted information by preventing reassociation of the name with a valid inode. I suggest you get some OS architecture books, like the Bach book and the Daemon book, and take a look at fs_dir.h (or ufs_dir.h), which will normally be located in either /usr/include/ufs or /usr/include/sys/fs. Terry Lambert terry@cs.weber.edu --- Any opinions in this posting are my own and not those of my present or previous employers.