Path: utzoo!attcan!uunet!husc6!bloom-beacon!tut.cis.ohio-state.edu!cwjcc!hal!ncoast!allbery From: allbery@ncoast.UUCP (Brandon S. Allbery) Newsgroups: comp.unix.wizards Subject: Re: 4.3BSD rename() changes ctime Message-ID: <12112@ncoast.UUCP> Date: 8 Aug 88 00:26:55 GMT References: <26657@oliveb.olivetti.com> <2167@pixar.UUCP> Reply-To: allbery@ncoast.UUCP (Brandon S. Allbery) Followup-To: comp.unix.wizards Organization: Cleveland Public Access UN*X, Cleveland, Oh Lines: 73 As quoted from <2167@pixar.UUCP> by rta@pixar.UUCP (Rick Ace): +--------------- | The principal purpose of the ctime field in the I-node is to alert | /etc/dump that the file has changed in *some way* and must be backed up. | In the case of "rename", the file's name has changed; thus the file has | changed in some way, and that fact must be recorded by /etc/dump. +--------------- We have a misunderstanding here. Inodes do not have names, they have i-numbers!!! A "filename" is a key used by an index (the directory mechanism and namei()) to determine the i-number of the file. As a result, the file itself has not changed but the directories (index pages) searched to find the i-number have changed; so the directories should be backed up, but the file shouldn't. If this is not clear, here's a simplified example of the situation: struct inode { int i_nlink; int i_ctime; int i_data; /* could be anything */ } *x, *y; /* This function is invoked by the kernel whenever anything in the */ /* inode pointed to by "ip" changes. */ iupdat(ip) struct inode *ip; { extern int now; ip->i_ctime = now; } rename(xp, yp) char **xp, **yp; { /* unlink old "yp" */ if (--(*yp)->i_nlink == 0) /* dex causes an iupdat() */ free(*yp); *yp = (char *) NULL; /* link "xp" to "yp" */ (*yp = *xp)->i_nlink++; /* inx causes an iupdat() */ /* Things are consistent if the system crashes here! */ /* unlink old "xp" */ --(*xp)->i_nlink; /* dex causes an iupdat() */ /* should be like yp above, but nlink == 0 "can't happen" */ *xp = (char *) NULL; /* unlink old "x" */ } main() { rename(&x, &y); } The problem is that the object originally pointed to by "xp" has a value incremented and immediately decremented; this causes the kernel to change the ctime (the iupdat() comment). It's actually unnecessary overhead because it *is* immediately undone; however, note the comment above about a crash "here". fsck would not appreciate the incomplete rename() in the slightest if the nlink value weren't changed for the duration of the link. So the price of making the filesystem a bit more resistant to crashes is having unnecessary data in the next incremental dump. A fix would be to have rename() save and restore the ctime of the inode pointed to by "xp" above.... ++Brandon [DISCLAIMER: The above code is not taken from AT&T or Berkeley source code, it is merely a C version of a simplification of what I understand to be going on, with commonly-known function and structure element names used to make things clearer. I sincerely doubt that the code actually looks anything like that....] -- Brandon S. Allbery, uunet!marque!ncoast!allbery DELPHI: ALLBERY For comp.sources.misc send mail to ncoast!sources-misc