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.
53 NukeProc(struct ViceInodeInfo
*ainfo
, VolumeId avolid
, void *arock
)
55 struct ilist
**allInodes
= (struct ilist
**)arock
;
59 #ifndef AFS_PTHREAD_ENV
60 IOMGR_Poll(); /* poll so we don't kill the RPC connection */
61 #endif /* !AFS_PTHREAD_ENV */
63 /* check if this is the volume we're looking for */
64 if (ainfo
->u
.vnode
.vnodeNumber
== INODESPECIAL
) {
65 /* For special inodes, look at both the volume id and the parent id.
66 * If we were given an RW vol id to nuke, we should delete the special
67 * inodes for all volumes in the VG, since we're deleting all of the
68 * regular inodes, too. If we don't do this, on namei would be
69 * impossible to nuke the special inodes for a non-RW volume. */
70 if (ainfo
->u
.special
.volumeId
!= avolid
&& ainfo
->u
.special
.parentId
!= avolid
) {
74 if (ainfo
->u
.vnode
.volumeId
!= avolid
) {
75 return 0; /* don't want this one */
80 if (!*allInodes
|| (*allInodes
)->freePtr
>= MAXATONCE
) {
81 ti
= calloc(1, sizeof(struct ilist
));
82 ti
->next
= *allInodes
;
85 ti
= *allInodes
; /* use the one with space */
86 i
= ti
->freePtr
++; /* find our slot in this mess */
87 ti
->inode
[i
] = ainfo
->inodeNumber
;
88 ti
->count
[i
] = ainfo
->linkCount
;
89 return 0; /* don't care if anything's written out, actually */
92 /* function called with partition name and volid ID, and which removes all
93 * inodes marked with the specified volume ID. If the volume is a read-only
94 * clone, we'll only remove the header inodes, since they're the only inodes
95 * marked with that volume ID. If you want to reclaim all the data, you should
96 * nuke the read-write volume ID.
98 * Note also that nuking a read-write volume effectively nukes all RO volumes
99 * cloned from that RW volume ID, too, since everything except for their
100 * indices will be gone.
103 nuke(char *aname
, VolumeId avolid
)
105 /* first process the partition containing this junk */
106 struct afs_stat_st tstat
;
107 struct ilist
*ti
, *ni
, *li
=NULL
;
112 struct DiskPartition64
*dp
;
117 #endif /* AFS_NAMEI_ENV */
118 #ifndef AFS_NAMEI_ENV
120 #endif /* !AFS_NAMEI_ENV */
122 struct ilist
*allInodes
= 0;
126 code
= afs_stat(aname
, &tstat
);
127 if (code
|| (dp
= VGetPartition(aname
, 0)) == NULL
) {
128 printf("volnuke: partition %s does not exist.\n", aname
);
134 /* get the device name for the partition */
135 #if defined(AFS_NAMEI_ENV) && !defined(AFS_NT40_ENV)
139 lastDevComp
= &aname
[strlen(aname
) - 1];
140 *lastDevComp
= toupper(*lastDevComp
);
143 char *tfile
= vol_DevName(tstat
.st_dev
, wpath
);
145 printf("volnuke: can't find %s's device.\n", aname
);
148 strcpy(devName
, tfile
); /* save this from the static buffer */
150 /* aim lastDevComp at the 'foo' of '/dev/foo' */
151 lastDevComp
= strrchr(devName
, OS_DIRSEPC
);
152 /* either points at slash, or there is no slash; adjust appropriately */
156 lastDevComp
= devName
;
157 #endif /* AFS_NT40_ENV */
158 #endif /* AFS_NAMEI_ENV && !AFS_NT40_ENV */
160 ObtainWriteLock(&localLock
);
161 /* OK, we have the mounted on place, aname, the device name (in devName).
162 * all we need to do to call ListViceInodes is find the inodes for the
163 * volume we're nuking.
166 ListViceInodes(lastDevComp
, aname
, INVALID_FD
, NukeProc
, avolid
, &forceSal
,
167 0, wpath
, &allInodes
);
169 /* actually do the idecs now */
170 for (ti
= allInodes
; ti
; ti
= ti
->next
) {
171 for (i
= 0; i
< ti
->freePtr
; i
++) {
172 #ifndef AFS_PTHREAD_ENV
173 IOMGR_Poll(); /* keep RPC running */
174 #endif /* !AFS_PTHREAD_ENV */
175 /* idec this inode into oblivion */
178 IH_INIT(fileH
, (int)(*lastDevComp
- 'A'), avolid
,
181 IH_INIT(fileH
, (int)volutil_GetPartitionID(aname
), avolid
,
183 #endif /* AFS_NT40_ENV */
184 namei_HandleToName(&ufs_name
, fileH
);
185 path
= ufs_name
.n_path
;
187 if (OS_UNLINK(path
) < 0) {
188 Log("Nuke: Failed to remove %s\n", path
);
190 #else /* AFS_NAMEI_ENV */
191 IH_INIT(fileH
, (int)tstat
.st_dev
, avolid
, ti
->inode
[i
]);
194 for (j
= 0; j
< ti
->count
[i
]; j
++) {
195 code
= IH_DEC(fileH
, ti
->inode
[i
], avolid
);
199 #endif /* AFS_NAMEI_ENV */
208 /* at this point, we should try to remove the volume header file itself.
209 * the volume header file is the file named VNNNNN.vol in the UFS file
210 * system, and is a normal file. As such, it is not stamped with the
211 * volume's ID in its inode, and has to be removed explicitly.
213 code
= VDestroyVolumeDiskHeader(dp
, avolid
, 0);
215 /* just free things */
216 for (ti
= allInodes
; ti
; ti
= ni
) {
224 ReleaseWriteLock(&localLock
);