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>
16 #include <afs/afsint.h>
17 #include <rx/rx_queue.h>
19 #include <afs/afsutil.h>
24 #include <afs/afssyscalls.h>
28 #include "partition.h"
29 #include "viceinode.h"
31 #include "daemon_com.h"
35 struct Lock localLock;
38 /* structure containing neatly packed set of inodes and the # of times we'll have
39 * to idec them in order to reclaim their storage. NukeProc, called by ListViceInodes,
40 * builds this list for us.
44 afs_int32 freePtr; /* first free index in this table */
45 Inode inode[MAXATONCE]; /* inode # */
46 afs_int32 count[MAXATONCE]; /* link count */
49 /* called with a structure specifying info about the inode, and our rock (which
50 * is the volume ID. Returns true if we should keep this inode, otherwise false.
51 * Note that ainfo->u.param[0] is always the volume ID, for any vice inode.
54 NukeProc(struct ViceInodeInfo *ainfo, VolumeId avolid, void *arock)
56 struct ilist **allInodes = (struct ilist **)arock;
60 #ifndef AFS_PTHREAD_ENV
61 IOMGR_Poll(); /* poll so we don't kill the RPC connection */
62 #endif /* !AFS_PTHREAD_ENV */
64 /* check if this is the volume we're looking for */
65 if (ainfo->u.param[0] != avolid)
66 return 0; /* don't want this one */
68 if (!*allInodes || (*allInodes)->freePtr >= MAXATONCE) {
69 ti = calloc(1, sizeof(struct ilist));
70 ti->next = *allInodes;
73 ti = *allInodes; /* use the one with space */
74 i = ti->freePtr++; /* find our slot in this mess */
75 ti->inode[i] = ainfo->inodeNumber;
76 ti->count[i] = ainfo->linkCount;
77 return 0; /* don't care if anything's written out, actually */
80 /* function called with partition name and volid ID, and which removes all
81 * inodes marked with the specified volume ID. If the volume is a read-only
82 * clone, we'll only remove the header inodes, since they're the only inodes
83 * marked with that volume ID. If you want to reclaim all the data, you should
84 * nuke the read-write volume ID.
86 * Note also that nuking a read-write volume effectively nukes all RO volumes
87 * cloned from that RW volume ID, too, since everything except for their
88 * indices will be gone.
91 nuke(char *aname, VolumeId avolid)
93 /* first process the partition containing this junk */
94 struct afs_stat_st tstat;
95 struct ilist *ti, *ni, *li=NULL;
100 struct DiskPartition64 *dp;
105 #endif /* AFS_NAMEI_ENV */
106 #ifndef AFS_NAMEI_ENV
108 #endif /* !AFS_NAMEI_ENV */
110 struct ilist *allInodes = 0;
114 code = afs_stat(aname, &tstat);
115 if (code || (dp = VGetPartition(aname, 0)) == NULL) {
116 printf("volnuke: partition %s does not exist.\n", aname);
122 /* get the device name for the partition */
123 #if defined(AFS_NAMEI_ENV) && !defined(AFS_NT40_ENV)
127 lastDevComp = &aname[strlen(aname) - 1];
128 *lastDevComp = toupper(*lastDevComp);
131 char *tfile = vol_DevName(tstat.st_dev, wpath);
133 printf("volnuke: can't find %s's device.\n", aname);
136 strcpy(devName, tfile); /* save this from the static buffer */
138 /* aim lastDevComp at the 'foo' of '/dev/foo' */
139 lastDevComp = strrchr(devName, OS_DIRSEPC);
140 /* either points at slash, or there is no slash; adjust appropriately */
144 lastDevComp = devName;
145 #endif /* AFS_NT40_ENV */
146 #endif /* AFS_NAMEI_ENV && !AFS_NT40_ENV */
148 ObtainWriteLock(&localLock);
149 /* OK, we have the mounted on place, aname, the device name (in devName).
150 * all we need to do to call ListViceInodes is find the inodes for the
151 * volume we're nuking.
154 ListViceInodes(lastDevComp, aname, INVALID_FD, NukeProc, avolid, &forceSal,
155 0, wpath, &allInodes);
157 /* actually do the idecs now */
158 for (ti = allInodes; ti; ti = ti->next) {
159 for (i = 0; i < ti->freePtr; i++) {
160 #ifndef AFS_PTHREAD_ENV
161 IOMGR_Poll(); /* keep RPC running */
162 #endif /* !AFS_PTHREAD_ENV */
163 /* idec this inode into oblivion */
166 IH_INIT(fileH, (int)(*lastDevComp - 'A'), avolid,
169 IH_INIT(fileH, (int)volutil_GetPartitionID(aname), avolid,
171 #endif /* AFS_NT40_ENV */
172 namei_HandleToName(&ufs_name, fileH);
173 path = ufs_name.n_path;
175 if (OS_UNLINK(path) < 0) {
176 Log("Nuke: Failed to remove %s\n", path);
178 #else /* AFS_NAMEI_ENV */
179 IH_INIT(fileH, (int)tstat.st_dev, avolid, ti->inode[i]);
182 for (j = 0; j < ti->count[i]; j++) {
183 code = IH_DEC(fileH, ti->inode[i], avolid);
187 #endif /* AFS_NAMEI_ENV */
194 code = 0; /* we really don't care about it except for debugging */
197 /* at this point, we should try to remove the volume header file itself.
198 * the volume header file is the file named VNNNNN.vol in the UFS file
199 * system, and is a normal file. As such, it is not stamped with the
200 * volume's ID in its inode, and has to be removed explicitly.
202 code = VDestroyVolumeDiskHeader(dp, avolid, 0);
204 /* just free things */
205 for (ti = allInodes; ti; ti = ni) {
213 ReleaseWriteLock(&localLock);