*BSD News Article 29341


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.