Volume * AttachVolume(struct DiskPartition64 * dp, char *volname, struct VolumeHeader * header) { Volume *vp; afs_int32 ec = 0; vp = (Volume *) calloc(1, sizeof(Volume)); vp->specialStatus = 0; vp->device = dp->device; vp->partition = dp; IH_INIT(vp->vnodeIndex[vLarge].handle, dp->device, header->parent, header->largeVnodeIndex); IH_INIT(vp->vnodeIndex[vSmall].handle, dp->device, header->parent, header->smallVnodeIndex); IH_INIT(vp->diskDataHandle, dp->device, header->parent, header->volumeInfo); IH_INIT(V_linkHandle(vp), dp->device, header->parent, header->linkTable); vp->cacheCheck = 0; /* XXXX */ vp->shuttingDown = 0; vp->goingOffline = 0; vp->nUsers = 1; vp->header = (struct volHeader *)calloc(1, sizeof(*vp->header)); ec = ReadHdr1(V_diskDataHandle(vp), (char *)&V_disk(vp), sizeof(V_disk(vp)), VOLUMEINFOMAGIC, VOLUMEINFOVERSION); if (!ec) { struct IndexFileHeader iHead; ec = ReadHdr1(vp->vnodeIndex[vSmall].handle, (char *)&iHead, sizeof(iHead), SMALLINDEXMAGIC, SMALLINDEXVERSION); } if (!ec) { struct IndexFileHeader iHead; ec = ReadHdr1(vp->vnodeIndex[vLarge].handle, (char *)&iHead, sizeof(iHead), LARGEINDEXMAGIC, LARGEINDEXVERSION); } #ifdef AFS_NAMEI_ENV if (!ec) { struct versionStamp stamp; ec = ReadHdr1(V_linkHandle(vp), (char *)&stamp, sizeof(stamp), LINKTABLEMAGIC, LINKTABLEVERSION); } #endif if (ec) return (Volume *) 0; return vp; }
/* delete a portion of an index, adjusting offset appropriately. Returns 0 if things work and we should be called again, 1 if success full and done, and -1 if an error occurred. It adjusts offset appropriately on 0 or 1 return codes, and otherwise doesn't touch it */ static int ObliterateRegion(Volume * avp, VnodeClass aclass, StreamHandle_t * afile, afs_int32 * aoffset) { register struct VnodeClassInfo *vcp; Inode inodes[MAXOBLITATONCE]; register afs_int32 iindex, nscanned; afs_int32 offset; char buf[SIZEOF_LARGEDISKVNODE]; int hitEOF; register int i; register afs_int32 code; register struct VnodeDiskObject *vnode = (struct VnodeDiskObject *)buf; hitEOF = 0; vcp = &VnodeClassInfo[aclass]; offset = *aoffset; /* original offset */ iindex = 0; nscanned = 0; /* advance over up to MAXOBLITATONCE inodes. nscanned tells us how many we examined. * We remember the inodes in an array, and idec them after zeroing them in the index. * The reason for these contortions is to make volume deletion idempotent, even * if we crash in the middle of a delete operation. */ STREAM_SEEK(afile, offset, 0); while (1) { if (iindex >= MAXOBLITATONCE) { break; } code = STREAM_READ(vnode, vcp->diskSize, 1, afile); nscanned++; offset += vcp->diskSize; if (code != 1) { hitEOF = 1; break; } if (vnode->type != vNull) { if (vnode->vnodeMagic != vcp->magic) goto fail; /* something really wrong; let salvager take care of it */ if (VNDISK_GET_INO(vnode)) inodes[iindex++] = VNDISK_GET_INO(vnode); } } /* next, obliterate the index and fflush (and fsync) it */ STREAM_SEEK(afile, *aoffset, 0); /* seek back to start of vnode index region */ memset(buf, 0, sizeof(buf)); /* zero out our proto-vnode */ for (i = 0; i < nscanned; i++) { if (STREAM_WRITE(buf, vcp->diskSize, 1, afile) != 1) goto fail; } STREAM_FLUSH(afile); /* ensure 0s are on the disk */ OS_SYNC(afile->str_fd); /* finally, do the idec's */ for (i = 0; i < iindex; i++) { IH_DEC(V_linkHandle(avp), inodes[i], V_parentId(avp)); DOPOLL; } /* return the new offset */ *aoffset = offset; return hitEOF; /* return 1 if hit EOF (don't call again), otherwise 0 */ fail: return -1; }