[The following two patches, from Tom Hageman and Matthias Heubi, both do roughly the same thing, which is to try removing files several times to work around the fact that many implementations of NFS (Networked File System), at least for unix, won't remove the files the first time. More technical discussion: typically NFS clients don't remove files in response to an unlink() call but instead rename to a file whose name starts with ".nfs". This is because the file might still be open, and you can't issue an NFS REMOVE request until you are done with the file (for details see RFC1813, the NFS specification). I would think that a NFS client could fix this problem by using the renaming workaround only if the file is open at the time, but I don't know if any NFS clients do this (it would seem to have possible problems in the case where other clients may have the file open). Or perhaps a client might make an rmdir() on a directory which contains only ".nfs" files block until they go away. It is not clear to me that the patches to CVS below, which specify two attempts, suffice. It would seem to me that anything which specifies a fixed number of attempts creates a race condition. So, yes, I find the patch ugly, but on the other hand I'm not sure it really harms much. Aside from whether the general idea is sound, both of the patches below probably need at least minor tidying before being made official. -kingdon] From: tom@basil.icce.rug.nl Date: Fri, 15 Nov 96 15:29:11 +0100 To: bug-cvs@prep.ai.mit.edu Subject: CVS fails to remove directories on NFS-mounted filesystems. [ChangeLog entry from Tom Hageman: * filesubr.c (deep_remove_dir): If necessary, make second pass over directory to remove stale NFS handles. ] >Submitter-Id: net >Originator: Tom Hageman >Organization: net >Confidential: no >Synopsis: CVS fails to remove directories on NFS-mounted filesystems. >Severity: critical >Priority: high >Category: cvs >Class: sw-bug >Release: cvs-1.9 >Environment: m68k i386 hppa sparc, NEXTSTEP 3.x/OPENSTEP 4.x >Description: CVS fails to remove directories on NFS-mounted filesystems. This problem generally aborts the current cvs command. >How-To-Repeat: This can be observed with "cvs update -P" when there are empty directories to be removed from the working directory. >Fix: This can be worked around by making another pass over the directory. *** cvs-1.9/src/%filesubr.c Wed Sep 25 16:42:48 1996 --- cvs-1.9/src/filesubr.c Fri Nov 8 22:21:35 1996 *************** deep_remove_dir (path) *** 469,474 **** --- 469,482 ---- struct dirent *dp; char buf[PATH_MAX]; + int status; + int attempt = 2; + #if 0 if (rmdir (path) != 0 && (errno == ENOTEMPTY || errno == EEXIST)) + #endif + /* This is an attempt to defeat stale .nfsXXXXX handles, + as left around by NeXTSTEPs NFS at least. */ + while ((status = rmdir (path)) != 0 && attempt-- > 0 && + (errno == ENOTEMPTY || errno == EEXIST)) { if ((dirp = opendir (path)) == NULL) *************** deep_remove_dir (path) *** 507,515 **** } closedir (dirp); return rmdir (path); ! } /* Was able to remove the directory return 0 */ return 0; } --- 515,528 ---- } closedir (dirp); + #if 0 return rmdir (path); ! #endif ! } + #if 0 /* Was able to remove the directory return 0 */ return 0; + #endif + return status; } From: "matthias.heubi" Date: Tue, 26 Nov 96 10:02:20 +0100 To: bug-cvs@prep.ai.mit.edu Subject: filesubr.c : deep_remove_dir() may fail on NFS mounted directories Reply-To: mh@uptime.ch >Submitter-Id: net >Originator: >Organization: Uptime Object Factory Inc >Confidential: no >Synopsis: deep_remove_dir() may fail on NFS mounted directories >Severity: serious >Priority: low >Category: cvs >Class: sw-bug >Release: cvs-1.7 >Environment: NEXTSTEP; bug valid for all unix plattforms >Description: When the wrapper functionality is used, checkin may fail, without any changes to the repository but with the developer's local copy destroyed. On checkin the local copy is deleted and checked out again. This deletion may partly fail when the file is a wrapped directory, since the function deep_remove_dir() first unlinks the directory's contents and then the directory itself. If the repository is NFS mounted, unlinking the contents may leave .nfs* files behind in which case unlinking the directory itself will fail, because it's not empty. This bug is still valid in CVS 1.9. >How-To-Repeat: >Fix: When deleting the directory, its contents must be enumerated twice. First to remove all the files in the directory, second to remove any .nfs* files which my have resulted from the first iteration. Deleting an .nfs* file will always delete the file and not leave another .nfs* file behind, therefore iterating twice should be safe. This is the patch for filesubr.c in cvs release 1.7: 497a498,538 > > /* do the whole thing twice, to make sure that any .nfs* files will be > * removed as well > */ > if ((dirp = opendir (path)) == NULL) > /* If unable to open the directory return > * an error > */ > return -1; > > while ((dp = readdir (dirp)) != NULL) > { > if (strcmp (dp->d_name, ".") == 0 || > strcmp (dp->d_name, "..") == 0) > continue; > > sprintf (buf, "%s/%s", path, dp->d_name); > > if (unlink (buf) != 0 ) > { > if (errno == EISDIR || errno == EPERM) > { > if (deep_remove_dir (buf)) > { > closedir (dirp); > return -1; > } > } > else > { > /* buf isn't a directory, or there are > * some sort of permision problems > */ > closedir (dirp); > return -1; > } > } > } > closedir (dirp); > >