static int IDecProc(Inode adata, struct clone_rock *aparm) { IH_DEC(aparm->h, adata, aparm->vol); DOPOLL; return 0; }
static void RemoveInodes(struct afs_inode_info *stuff, Device dev, VolumeId parent, VolumeId vid) { int i; IHandle_t *handle; /* This relies on the fact that IDEC only needs the device and NT only * needs the dev and vid to decrement volume special files. */ IH_INIT(handle, dev, parent, -1); for (i = 0; i < MAXINODETYPE; i++) { Inode inode = *stuff[i].inode; if (VALID_INO(inode)) { if (stuff[i].inodeType == VI_LINKTABLE) { IH_DEC(handle, inode, parent); } else { IH_DEC(handle, inode, vid); } } } IH_RELEASE(handle); }
static void RemoveInodes(Device dev, VolumeId vid) { register int i; IHandle_t *handle; /* This relies on the fact that IDEC only needs the device and NT only * needs the dev and vid to decrement volume special files. */ IH_INIT(handle, dev, vid, -1); for (i = 0; i < nFILES; i++) { Inode inode = *stuff[i].inode; if (VALID_INO(inode)) IH_DEC(handle, inode, vid); } IH_RELEASE(handle); }
/* 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; }
/* function called with partition name and volid ID, and which removes all * inodes marked with the specified volume ID. If the volume is a read-only * clone, we'll only remove the header inodes, since they're the only inodes * marked with that volume ID. If you want to reclaim all the data, you should * nuke the read-write volume ID. * * Note also that nuking a read-write volume effectively nukes all RO volumes * cloned from that RW volume ID, too, since everything except for their * indices will be gone. */ int nuke(char *aname, afs_int32 avolid) { /* first process the partition containing this junk */ struct afs_stat_st tstat; struct ilist *ti, *ni, *li=NULL; afs_int32 code; int i, forceSal; char wpath[100]; char *lastDevComp; struct DiskPartition64 *dp; #ifdef AFS_NAMEI_ENV char *path; namei_t ufs_name; #endif /* AFS_NAMEI_ENV */ #ifndef AFS_NAMEI_ENV char devName[64]; #endif /* !AFS_NAMEI_ENV */ IHandle_t *fileH; struct ilist *allInodes = 0; if (avolid == 0) return EINVAL; code = afs_stat(aname, &tstat); if (code || (dp = VGetPartition(aname, 0)) == NULL) { printf("volnuke: partition %s does not exist.\n", aname); if (!code) { code = EINVAL; } return code; } /* get the device name for the partition */ #if defined(AFS_NAMEI_ENV) && !defined(AFS_NT40_ENV) lastDevComp = aname; #else #ifdef AFS_NT40_ENV lastDevComp = &aname[strlen(aname) - 1]; *lastDevComp = toupper(*lastDevComp); #else { char *tfile = vol_DevName(tstat.st_dev, wpath); if (!tfile) { printf("volnuke: can't find %s's device.\n", aname); return 1; } strcpy(devName, tfile); /* save this from the static buffer */ } /* aim lastDevComp at the 'foo' of '/dev/foo' */ lastDevComp = strrchr(devName, OS_DIRSEPC); /* either points at slash, or there is no slash; adjust appropriately */ if (lastDevComp) lastDevComp++; else lastDevComp = devName; #endif /* AFS_NT40_ENV */ #endif /* AFS_NAMEI_ENV && !AFS_NT40_ENV */ ObtainWriteLock(&localLock); /* OK, we have the mounted on place, aname, the device name (in devName). * all we need to do to call ListViceInodes is find the inodes for the * volume we're nuking. */ code = ListViceInodes(lastDevComp, aname, INVALID_FD, NukeProc, avolid, &forceSal, 0, wpath, &allInodes); if (code == 0) { /* actually do the idecs now */ for (ti = allInodes; ti; ti = ti->next) { for (i = 0; i < ti->freePtr; i++) { #ifndef AFS_PTHREAD_ENV IOMGR_Poll(); /* keep RPC running */ #endif /* !AFS_PTHREAD_ENV */ /* idec this inode into oblivion */ #ifdef AFS_NAMEI_ENV #ifdef AFS_NT40_ENV IH_INIT(fileH, (int)(*lastDevComp - 'A'), avolid, ti->inode[i]); #else IH_INIT(fileH, (int)volutil_GetPartitionID(aname), avolid, ti->inode[i]); #endif /* AFS_NT40_ENV */ namei_HandleToName(&ufs_name, fileH); path = ufs_name.n_path; IH_RELEASE(fileH); if (OS_UNLINK(path) < 0) { Log("Nuke: Failed to remove %s\n", path); } #else /* AFS_NAMEI_ENV */ IH_INIT(fileH, (int)tstat.st_dev, avolid, ti->inode[i]); { int j; for (j = 0; j < ti->count[i]; j++) { code = IH_DEC(fileH, ti->inode[i], avolid); } } IH_RELEASE(fileH); #endif /* AFS_NAMEI_ENV */ } ni = ti->next; if (li) free(li); li = ti; } if (li) free(li); code = 0; /* we really don't care about it except for debugging */ allInodes = NULL; /* at this point, we should try to remove the volume header file itself. * the volume header file is the file named VNNNNN.vol in the UFS file * system, and is a normal file. As such, it is not stamped with the * volume's ID in its inode, and has to be removed explicitly. */ code = VDestroyVolumeDiskHeader(dp, avolid, 0); } else { /* just free things */ for (ti = allInodes; ti; ti = ni) { ni = ti->next; if (li) free(li); li = ti; } if (li) free(li); allInodes = NULL; } ReleaseWriteLock(&localLock); return code; }