viced: Sanity check file link count during CoW

A few ihandle bugs in the past have caused the CopyOnWrite code to
open cached file handles for files which have been deleted. When we
CoW, both of the files we're dealing with had better actually be on
disk, so bail out and flag an error if either of them appear unlinked.

FIXES 131530

Reviewed-on: http://gerrit.openafs.org/8839
Tested-by: BuildBot <buildbot@rampaginggeek.com>
Reviewed-by: Derrick Brashear <shadow@your-file-system.com>
(cherry picked from commit 752514bd1c8eaae487d25116dc59853552f77d12)

Change-Id: I2aa70145b12e9babd1a1eb881bf7f48151c20f6c
Reviewed-on: http://gerrit.openafs.org/9508
Reviewed-by: Derrick Brashear <shadow@your-file-system.com>
Reviewed-by: Andrew Deason <adeason@sinenomine.net>
Reviewed-by: Stephan Wiesand <stephan.wiesand@desy.de>
Tested-by: BuildBot <buildbot@rampaginggeek.com>
This commit is contained in:
Andrew Deason 2012-12-18 18:49:49 -06:00 committed by Stephan Wiesand
parent 5e05f22798
commit 0508bdf0be

View File

@ -1234,6 +1234,26 @@ RXStore_AccessList(Vnode * targetptr, struct AFSOpaque *AccessList)
} /*RXStore_AccessList */
static int
CheckLink(Volume *volptr, FdHandle_t *fdP, const char *descr)
{
int code;
afs_ino_str_t ino;
code = FDH_ISUNLINKED(fdP);
if (code < 0) {
ViceLog(0, ("CopyOnWrite: error fstating volume %u inode %s (%s), errno %d\n",
V_id(volptr), PrintInode(ino, fdP->fd_ih->ih_ino), descr, errno));
return -1;
}
if (code) {
ViceLog(0, ("CopyOnWrite corruption prevention: detected zero nlink for "
"volume %u inode %s (%s), forcing volume offline\n",
V_id(volptr), PrintInode(ino, fdP->fd_ih->ih_ino), descr));
return -1;
}
return 0;
}
/* In our current implementation, each successive data store (new file
* data version) creates a new inode. This function creates the new
@ -1313,6 +1333,20 @@ CopyOnWrite(Vnode * targetptr, Volume * volptr, afs_foff_t off, afs_fsize_t len)
newFdP = IH_OPEN(newH);
osi_Assert(newFdP != NULL);
rc = CheckLink(volptr, targFdP, "source");
if (!rc) {
rc = CheckLink(volptr, newFdP, "dest");
}
if (rc) {
FDH_REALLYCLOSE(newFdP);
IH_RELEASE(newH);
FDH_REALLYCLOSE(targFdP);
IH_DEC(V_linkHandle(volptr), ino, V_parentId(volptr));
free(buff);
VTakeOffline(volptr);
return VSALVAGE;
}
done = off;
while (size > 0) {
if (size > COPYBUFFSIZE) { /* more than a buffer */