2 * Copyright 2000, International Business Machines Corporation and others.
5 * This software has been released under the terms of the IBM Public
6 * License. For details, see the LICENSE file in the top-level source
7 * directory or online at http://www.openafs.org/dl/license10.html
10 #include <afs/param.h>
11 #include <afsconfig.h>
16 #include <afs/afsint.h>
18 #ifdef AFS_PTHREAD_ENV
20 #else /* AFS_PTHREAD_ENV */
21 #include <afs/assert.h>
22 #endif /* AFS_PTHREAD_ENV */
26 #if defined(AFS_SUN5_ENV) || defined(AFS_NT40_ENV)
32 #include <afs/assert.h>
36 #include <afs/afssyscalls.h>
40 #include "partition.h"
41 #include "viceinode.h"
46 struct Lock localLock;
50 /* structure containing neatly packed set of inodes and the # of times we'll have
51 * to idec them in order to reclaim their storage. NukeProc, called by ListViceInodes,
52 * builds this list for us.
56 afs_int32 freePtr; /* first free index in this table */
57 Inode inode[MAXATONCE]; /* inode # */
58 afs_int32 count[MAXATONCE]; /* link count */
61 /* called with a structure specifying info about the inode, and our rock (which
62 * is the volume ID. Returns true if we should keep this inode, otherwise false.
63 * Note that ainfo->u.param[0] is always the volume ID, for any vice inode.
65 static NukeProc(ainfo, avolid)
66 struct ViceInodeInfo *ainfo;
71 #ifndef AFS_PTHREAD_ENV
72 IOMGR_Poll(); /* poll so we don't kill the RPC connection */
73 #endif /* !AFS_PTHREAD_ENV */
75 /* check if this is the volume we're looking for */
76 if (ainfo->u.param[0] != avolid) return 0; /* don't want this one */
78 if (!allInodes || allInodes->freePtr >= MAXATONCE) {
79 ti = (struct ilist *) malloc(sizeof(struct ilist));
80 bzero(ti, sizeof(*ti));
84 else ti = allInodes; /* use the one with space */
85 i = ti->freePtr++; /* find our slot in this mess */
86 ti->inode[i] = ainfo->inodeNumber;
87 ti->count[i] = ainfo->linkCount;
88 return 0; /* don't care if anything's written out, actually */
91 /* function called with partition name and volid ID, and which removes all
92 * inodes marked with the specified volume ID. If the volume is a read-only
93 * clone, we'll only remove the header inodes, since they're the only inodes
94 * marked with that volume ID. If you want to reclaim all the data, you should
95 * nuke the read-write volume ID.
97 * Note also that nuking a read-write volume effectively nukes all RO volumes
98 * cloned from that RW volume ID, too, since everything except for their
99 * indices will be gone.
104 /* first process the partition containing this junk */
106 struct ilist *ti, *ni;
107 register afs_int32 code;
110 char devName[64], wpath[100];
119 #endif /* AFS_NAMEI_ENV */
122 if (avolid == 0) return EINVAL;
123 code = stat(aname, &tstat);
125 printf("volnuke: partition %s does not exist.\n", aname);
128 /* get the device name for the partition */
129 #if defined(AFS_NAMEI_ENV) && !defined(AFS_NT40_ENV)
133 lastDevComp = &aname[strlen(aname)-1];
134 *lastDevComp = toupper(*lastDevComp);
136 tfile = vol_DevName(tstat.st_dev, wpath);
138 printf("volnuke: can't find %s's device.\n", aname);
141 strcpy(devName, tfile); /* save this from the static buffer */
142 /* aim lastDevComp at the 'foo' of '/dev/foo' */
143 lastDevComp = strrchr(devName, '/');
144 /* either points at slash, or there is no slash; adjust appropriately */
147 else lastDevComp = devName;
148 #endif /* AFS_NT40_ENV */
149 #endif /* AFS_NAMEI_ENV && !AFS_NT40_ENV */
151 ObtainWriteLock(&localLock);
152 /* OK, we have the mounted on place, aname, the device name (in devName).
153 * all we need to do to call ListViceInodes is find the inodes for the
154 * volume we're nuking.
157 code = ListViceInodes(lastDevComp, aname, NULL, NukeProc, avolid,
158 &forceSal, 0, wpath);
160 code = ListViceInodes(lastDevComp, aname, "/tmp/vNukeXX", NukeProc, avolid, &forceSal, 0, wpath);
161 unlink("/tmp/vNukeXX"); /* clean it up now */
164 /* actually do the idecs now */
165 for(ti=allInodes; ti; ti=ti->next) {
166 for(i=0;i<ti->freePtr;i++) {
167 #ifndef AFS_PTHREAD_ENV
168 IOMGR_Poll(); /* keep RPC running */
169 #endif /* !AFS_PTHREAD_ENV */
170 /* idec this inode into oblivion */
173 IH_INIT(fileH, (int) (*lastDevComp - 'A'), avolid,
175 nt_HandleToName(path, fileH);
177 IH_INIT(fileH, (int) volutil_GetPartitionID(aname), avolid,
179 namei_HandleToName(&ufs_name, fileH);
180 path = ufs_name.n_path;
181 #endif /* AFS_NT40_ENV */
183 if (unlink(path)<0) {
184 Log("Nuke: Failed to remove %s\n", path);
186 #else /* AFS_NAMEI_ENV */
187 IH_INIT(fileH, (int) tstat.st_dev, avolid,
189 for(j=0;j<ti->count[i];j++) {
190 code = IH_DEC(fileH, ti->inode[i], avolid);
193 #endif /* AFS_NAMEI_ENV */
198 code = 0; /* we really don't care about it except for debugging */
199 allInodes = (struct ilist *) 0;
201 /* at this point, we should try to remove the volume header file itself.
202 * the volume header file is the file named VNNNNN.vol in the UFS file
203 * system, and is a normal file. As such, it is not stamped with the
204 * volume's ID in its inode, and has to be removed explicitly.
206 /* reuse devName buffer now */
208 sprintf(devName, "%c:\\%s", *lastDevComp , VolumeExternalName(avolid));
210 sprintf(devName, "%s/%s", aname, VolumeExternalName(avolid));
211 #endif /* AFS_NAMEI_ENV */
212 code = unlink(devName);
213 if (code) code = errno;
216 /* just free things */
217 for(ti=allInodes; ti; ti = ni) {
221 allInodes = (struct ilist *) 0;
223 ReleaseWriteLock(&localLock);