vol: Tidy header includes
[openafs.git] / src / vol / nuke.c
1 /*
2  * Copyright 2000, International Business Machines Corporation and others.
3  * All Rights Reserved.
4  *
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
8  */
9
10 #include <afsconfig.h>
11 #include <afs/param.h>
12
13 #include <roken.h>
14
15 #include <rx/xdr.h>
16 #include <afs/afsint.h>
17 #include <stdio.h>
18 #include <afs/afs_assert.h>
19 #include <sys/stat.h>
20 #include <fcntl.h>
21 #include <errno.h>
22 #if defined(AFS_SUN5_ENV) || defined(AFS_NT40_ENV)
23 #include <string.h>
24 #else
25 #include <strings.h>
26 #endif
27 #ifndef AFS_NT40_ENV
28 #include <unistd.h>
29 #endif
30
31 #include <afs/afsutil.h>
32
33 #include "nfs.h"
34 #include "lwp.h"
35 #include "lock.h"
36 #include <afs/afssyscalls.h>
37 #include "ihandle.h"
38 #include "vnode.h"
39 #include "volume.h"
40 #include "partition.h"
41 #include "viceinode.h"
42 #include "salvage.h"
43 #include "daemon_com.h"
44 #include "fssync.h"
45 #include "common.h"
46
47 struct Lock localLock;
48
49 #define MAXATONCE       100
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.
53  */
54 struct ilist {
55     struct ilist *next;
56     afs_int32 freePtr;          /* first free index in this table */
57     Inode inode[MAXATONCE];     /* inode # */
58     afs_int32 count[MAXATONCE]; /* link count */
59 };
60
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.
64  */
65 static int
66 NukeProc(struct ViceInodeInfo *ainfo, afs_uint32 avolid, void *arock)
67 {
68     struct ilist **allInodes = (struct ilist **)arock;
69     struct ilist *ti;
70     afs_int32 i;
71
72 #ifndef AFS_PTHREAD_ENV
73     IOMGR_Poll();               /* poll so we don't kill the RPC connection */
74 #endif /* !AFS_PTHREAD_ENV */
75
76     /* check if this is the volume we're looking for */
77     if (ainfo->u.param[0] != avolid)
78         return 0;               /* don't want this one */
79     /* record the info */
80     if (!*allInodes || (*allInodes)->freePtr >= MAXATONCE) {
81         ti = (struct ilist *)malloc(sizeof(struct ilist));
82         memset(ti, 0, sizeof(*ti));
83         ti->next = *allInodes;
84         *allInodes = ti;
85     } else
86         ti = *allInodes;                /* use the one with space */
87     i = ti->freePtr++;          /* find our slot in this mess */
88     ti->inode[i] = ainfo->inodeNumber;
89     ti->count[i] = ainfo->linkCount;
90     return 0;                   /* don't care if anything's written out, actually */
91 }
92
93 /* function called with partition name and volid ID, and which removes all
94  * inodes marked with the specified volume ID.  If the volume is a read-only
95  * clone, we'll only remove the header inodes, since they're the only inodes
96  * marked with that volume ID.  If you want to reclaim all the data, you should
97  * nuke the read-write volume ID.
98  *
99  * Note also that nuking a read-write volume effectively nukes all RO volumes
100  * cloned from that RW volume ID, too, since everything except for their
101  * indices will be gone.
102  */
103 int
104 nuke(char *aname, afs_int32 avolid)
105 {
106     /* first process the partition containing this junk */
107     struct afs_stat_st tstat;
108     struct ilist *ti, *ni, *li=NULL;
109     afs_int32 code;
110     int i, forceSal;
111     char wpath[100];
112     char *lastDevComp;
113     struct DiskPartition64 *dp;
114 #ifdef AFS_NAMEI_ENV
115     char *path;
116
117     namei_t ufs_name;
118 #endif /* AFS_NAMEI_ENV */
119 #ifndef AFS_NAMEI_ENV
120     char devName[64];
121 #endif /* !AFS_NAMEI_ENV */
122     IHandle_t *fileH;
123     struct ilist *allInodes = 0;
124
125     if (avolid == 0)
126         return EINVAL;
127     code = afs_stat(aname, &tstat);
128     if (code || (dp = VGetPartition(aname, 0)) == NULL) {
129         printf("volnuke: partition %s does not exist.\n", aname);
130         if (!code) {
131             code = EINVAL;
132         }
133         return code;
134     }
135     /* get the device name for the partition */
136 #if defined(AFS_NAMEI_ENV) && !defined(AFS_NT40_ENV)
137     lastDevComp = aname;
138 #else
139 #ifdef AFS_NT40_ENV
140     lastDevComp = &aname[strlen(aname) - 1];
141     *lastDevComp = toupper(*lastDevComp);
142 #else
143     {
144         char *tfile = vol_DevName(tstat.st_dev, wpath);
145         if (!tfile) {
146             printf("volnuke: can't find %s's device.\n", aname);
147             return 1;
148         }
149         strcpy(devName, tfile); /* save this from the static buffer */
150     }
151     /* aim lastDevComp at the 'foo' of '/dev/foo' */
152     lastDevComp = strrchr(devName, OS_DIRSEPC);
153     /* either points at slash, or there is no slash; adjust appropriately */
154     if (lastDevComp)
155         lastDevComp++;
156     else
157         lastDevComp = devName;
158 #endif /* AFS_NT40_ENV */
159 #endif /* AFS_NAMEI_ENV && !AFS_NT40_ENV */
160
161     ObtainWriteLock(&localLock);
162     /* OK, we have the mounted on place, aname, the device name (in devName).
163      * all we need to do to call ListViceInodes is find the inodes for the
164      * volume we're nuking.
165      */
166     code =
167         ListViceInodes(lastDevComp, aname, INVALID_FD, NukeProc, avolid, &forceSal,
168                        0, wpath, &allInodes);
169     if (code == 0) {
170         /* actually do the idecs now */
171         for (ti = allInodes; ti; ti = ti->next) {
172             for (i = 0; i < ti->freePtr; i++) {
173 #ifndef AFS_PTHREAD_ENV
174                 IOMGR_Poll();   /* keep RPC running */
175 #endif /* !AFS_PTHREAD_ENV */
176                 /* idec this inode into oblivion */
177 #ifdef AFS_NAMEI_ENV
178 #ifdef AFS_NT40_ENV
179                 IH_INIT(fileH, (int)(*lastDevComp - 'A'), avolid,
180                         ti->inode[i]);
181 #else
182                 IH_INIT(fileH, (int)volutil_GetPartitionID(aname), avolid,
183                         ti->inode[i]);
184 #endif /* AFS_NT40_ENV */
185                 namei_HandleToName(&ufs_name, fileH);
186                 path = ufs_name.n_path;
187                 IH_RELEASE(fileH);
188                 if (OS_UNLINK(path) < 0) {
189                     Log("Nuke: Failed to remove %s\n", path);
190                 }
191 #else /* AFS_NAMEI_ENV */
192                 IH_INIT(fileH, (int)tstat.st_dev, avolid, ti->inode[i]);
193                 {
194                     int j;
195                     for (j = 0; j < ti->count[i]; j++) {
196                         code = IH_DEC(fileH, ti->inode[i], avolid);
197                     }
198                 }
199                 IH_RELEASE(fileH);
200 #endif /* AFS_NAMEI_ENV */
201             }
202             ni = ti->next;
203             if (li) free(li);
204             li = ti;
205         }
206         if (li) free(li);
207         code = 0;               /* we really don't care about it except for debugging */
208         allInodes = NULL;
209
210         /* at this point, we should try to remove the volume header file itself.
211          * the volume header file is the file named VNNNNN.vol in the UFS file
212          * system, and is a normal file.  As such, it is not stamped with the
213          * volume's ID in its inode, and has to be removed explicitly.
214          */
215         code = VDestroyVolumeDiskHeader(dp, avolid, 0);
216     } else {
217         /* just free things */
218         for (ti = allInodes; ti; ti = ni) {
219             ni = ti->next;
220             if (li) free(li);
221             li = ti;
222         }
223         if (li) free(li);
224         allInodes = NULL;
225     }
226     ReleaseWriteLock(&localLock);
227     return code;
228 }