/* Close all cached file descriptors for this inode. */ int ih_reallyclose(IHandle_t * ihP) { if (!ihP) return 0; IH_LOCK; ihP->ih_refcnt++; /* must not disappear over unlock */ if (ihP->ih_synced) { FdHandle_t *fdP; ihP->ih_synced = 0; IH_UNLOCK; fdP = IH_OPEN(ihP); if (fdP) { OS_SYNC(fdP->fd_fd); FDH_CLOSE(fdP); } IH_LOCK; } osi_Assert(ihP->ih_refcnt > 0); ih_fdclose(ihP); if (ihP->ih_refcnt > 1) ihP->ih_refcnt--; else _ih_release_r(ihP); IH_UNLOCK; return 0; }
void ih_sync_all(void) { int ihash; IH_LOCK; for (ihash = 0; ihash < I_HANDLE_HASH_SIZE; ihash++) { IHandle_t *ihP, *ihPnext; ihP = ihashTable[ihash].ihash_head; if (ihP) ihP->ih_refcnt++; /* must not disappear over unlock */ for (; ihP; ihP = ihPnext) { if (ihP->ih_synced) { FdHandle_t *fdP; ihP->ih_synced = 0; IH_UNLOCK; fdP = IH_OPEN(ihP); if (fdP) { OS_SYNC(fdP->fd_fd); FDH_CLOSE(fdP); } IH_LOCK; } /* when decrementing the refcount, the ihandle might disappear and we might not even be able to proceed to the next one. Hence the gymnastics putting a hold on the next one already */ ihPnext = ihP->ih_next; if (ihPnext) ihPnext->ih_refcnt++; if (ihP->ih_refcnt > 1) { ihP->ih_refcnt--; } else { IH_UNLOCK; ih_release(ihP); IH_LOCK; } } } IH_UNLOCK; }
/* 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; }