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 <afsconfig.h>
11 #include <afs/param.h>
17 #include <afs/afsint.h>
19 #ifdef AFS_PTHREAD_ENV
21 #else /* AFS_PTHREAD_ENV */
22 #include <afs/assert.h>
23 #endif /* AFS_PTHREAD_ENV */
27 #if defined(AFS_SUN5_ENV) || defined(AFS_NT40_ENV)
33 #include <afs/assert.h>
37 #include <afs/afssyscalls.h>
41 #include "partition.h"
42 #include "viceinode.h"
44 #include "daemon_com.h"
48 #define afs_stat stat64
49 #else /* !O_LARGEFILE */
51 #endif /* !O_LARGEFILE */
53 /*@printflike@*/ extern void Log(const char *format, ...);
56 struct Lock localLock;
60 /* structure containing neatly packed set of inodes and the # of times we'll have
61 * to idec them in order to reclaim their storage. NukeProc, called by ListViceInodes,
62 * builds this list for us.
66 afs_int32 freePtr; /* first free index in this table */
67 Inode inode[MAXATONCE]; /* inode # */
68 afs_int32 count[MAXATONCE]; /* link count */
71 /* called with a structure specifying info about the inode, and our rock (which
72 * is the volume ID. Returns true if we should keep this inode, otherwise false.
73 * Note that ainfo->u.param[0] is always the volume ID, for any vice inode.
76 NukeProc(struct ViceInodeInfo *ainfo, afs_int32 avolid, struct ilist *allInodes)
81 #ifndef AFS_PTHREAD_ENV
82 IOMGR_Poll(); /* poll so we don't kill the RPC connection */
83 #endif /* !AFS_PTHREAD_ENV */
85 /* check if this is the volume we're looking for */
86 if (ainfo->u.param[0] != avolid)
87 return 0; /* don't want this one */
89 if (!allInodes || allInodes->freePtr >= MAXATONCE) {
90 ti = (struct ilist *)malloc(sizeof(struct ilist));
91 memset(ti, 0, sizeof(*ti));
95 ti = allInodes; /* use the one with space */
96 i = ti->freePtr++; /* find our slot in this mess */
97 ti->inode[i] = ainfo->inodeNumber;
98 ti->count[i] = ainfo->linkCount;
99 return 0; /* don't care if anything's written out, actually */
102 /* function called with partition name and volid ID, and which removes all
103 * inodes marked with the specified volume ID. If the volume is a read-only
104 * clone, we'll only remove the header inodes, since they're the only inodes
105 * marked with that volume ID. If you want to reclaim all the data, you should
106 * nuke the read-write volume ID.
108 * Note also that nuking a read-write volume effectively nukes all RO volumes
109 * cloned from that RW volume ID, too, since everything except for their
110 * indices will be gone.
113 nuke(char *aname, afs_int32 avolid)
115 /* first process the partition containing this junk */
116 struct afs_stat tstat;
117 struct ilist *ti, *ni, *li=NULL;
118 register afs_int32 code;
120 char devName[64], wpath[100];
129 #endif /* AFS_NAMEI_ENV */
131 struct ilist *allInodes = 0;
135 code = afs_stat(aname, &tstat);
137 printf("volnuke: partition %s does not exist.\n", aname);
140 /* get the device name for the partition */
141 #if defined(AFS_NAMEI_ENV) && !defined(AFS_NT40_ENV)
145 lastDevComp = &aname[strlen(aname) - 1];
146 *lastDevComp = toupper(*lastDevComp);
149 char *tfile = vol_DevName(tstat.st_dev, wpath);
151 printf("volnuke: can't find %s's device.\n", aname);
154 strcpy(devName, tfile); /* save this from the static buffer */
156 /* aim lastDevComp at the 'foo' of '/dev/foo' */
157 lastDevComp = strrchr(devName, '/');
158 /* either points at slash, or there is no slash; adjust appropriately */
162 lastDevComp = devName;
163 #endif /* AFS_NT40_ENV */
164 #endif /* AFS_NAMEI_ENV && !AFS_NT40_ENV */
166 ObtainWriteLock(&localLock);
167 /* OK, we have the mounted on place, aname, the device name (in devName).
168 * all we need to do to call ListViceInodes is find the inodes for the
169 * volume we're nuking.
173 ListViceInodes(lastDevComp, aname, NULL, NukeProc, avolid, &forceSal,
174 0, wpath, allInodes);
177 ListViceInodes(lastDevComp, aname, "/tmp/vNukeXX", NukeProc, avolid,
178 &forceSal, 0, wpath, allInodes);
179 unlink("/tmp/vNukeXX"); /* clean it up now */
182 /* actually do the idecs now */
183 for (ti = allInodes; ti; ti = ti->next) {
184 for (i = 0; i < ti->freePtr; i++) {
185 #ifndef AFS_PTHREAD_ENV
186 IOMGR_Poll(); /* keep RPC running */
187 #endif /* !AFS_PTHREAD_ENV */
188 /* idec this inode into oblivion */
191 IH_INIT(fileH, (int)(*lastDevComp - 'A'), avolid,
193 nt_HandleToName(path, fileH);
195 IH_INIT(fileH, (int)volutil_GetPartitionID(aname), avolid,
197 namei_HandleToName(&ufs_name, fileH);
198 path = ufs_name.n_path;
199 #endif /* AFS_NT40_ENV */
201 if (unlink(path) < 0) {
202 Log("Nuke: Failed to remove %s\n", path);
204 #else /* AFS_NAMEI_ENV */
205 IH_INIT(fileH, (int)tstat.st_dev, avolid, ti->inode[i]);
208 for (j = 0; j < ti->count[i]; j++) {
209 code = IH_DEC(fileH, ti->inode[i], avolid);
213 #endif /* AFS_NAMEI_ENV */
220 code = 0; /* we really don't care about it except for debugging */
223 /* at this point, we should try to remove the volume header file itself.
224 * the volume header file is the file named VNNNNN.vol in the UFS file
225 * system, and is a normal file. As such, it is not stamped with the
226 * volume's ID in its inode, and has to be removed explicitly.
228 /* reuse devName buffer now */
230 afs_snprintf(devName, sizeof devName, "%c:\\%s", *lastDevComp,
231 VolumeExternalName(avolid));
233 afs_snprintf(devName, sizeof devName, "%s/%s", aname,
234 VolumeExternalName(avolid));
235 #endif /* AFS_NT40_ENV */
236 code = unlink(devName);
240 /* just free things */
241 for (ti = allInodes; ti; ti = ni) {
249 ReleaseWriteLock(&localLock);