} /*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
newFdP = IH_OPEN(newH);
opr_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 */