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
15 Institution: The Information Technology Center, Carnegie-Mellon University
19 #include <afs/param.h>
21 #include <sys/types.h>
32 #ifdef AFS_PTHREAD_ENV
34 #else /* AFS_PTHREAD_ENV */
35 #include <afs/assert.h>
36 #endif /* AFS_PTHREAD_ENV */
39 #include <afs/afsint.h>
41 #include <afs/errors.h>
44 #include <afs/afssyscalls.h>
52 #include "partition.h"
53 #include "viceinode.h"
55 #include "volinodes.h"
57 #include <sys/lockf.h>
59 #if defined(AFS_SUN5_ENV) || defined(AFS_NT40_ENV) || defined(AFS_LINUX20_ENV)
66 #define nFILES (sizeof (stuff)/sizeof(struct stuff))
68 /* Note: the volume creation functions herein leave the destroyMe flag in the
69 volume header ON: this means that the volumes will not be attached by the
70 file server and WILL BE DESTROYED the next time a system salvage is performed */
72 static void RemoveInodes(Device dev, int vid)
77 /* This relies on the fact that IDEC only needs the device and NT only
78 * needs the dev and vid to decrement volume special files.
80 IH_INIT(handle, dev, vid, -1);
81 for (i = 0; i<nFILES; i++) {
82 Inode inode = *stuff[i].inode;
84 IH_DEC(handle, inode, vid);
89 Volume *VCreateVolume(ec, partname, volumeId, parentId)
93 VolId parentId; /* Should be the same as volumeId if there is
98 retVal = VCreateVolume_r(ec, partname, volumeId, parentId);
103 Volume *VCreateVolume_r(ec, partname, volumeId, parentId)
107 VolId parentId; /* Should be the same as volumeId if there is
112 char headerName[32], volumePath[64];
115 struct DiskPartition *partition;
116 struct VolumeDiskHeader diskHeader;
125 bzero(&vol, sizeof (vol));
127 vol.parentId = parentId;
128 vol.copyDate = time(0); /* The only date which really means when this
129 @i(instance) of this volume was created.
130 Creation date does not mean this */
132 /* Initialize handle for error case below. */
135 /* Verify that the parition is valid before writing to it. */
136 if (!(partition = VGetPartition(partname, 0))) {
137 Log("VCreateVolume: partition %s is not in service.\n", partname);
141 #if defined(NEARINODE_HINT)
142 nearInodeHash(volumeId,nearInode);
143 nearInode %= partition->f_files;
145 VLockPartition(partname);
146 bzero(&tempHeader, sizeof (tempHeader));
147 tempHeader.stamp.magic = VOLUMEHEADERMAGIC;
148 tempHeader.stamp.version = VOLUMEHEADERVERSION;
149 tempHeader.id = vol.id;
150 tempHeader.parent = vol.parentId;
151 vol.stamp.magic = VOLUMEINFOMAGIC;
152 vol.stamp.version = VOLUMEINFOVERSION;
153 vol.destroyMe = DESTROY_ME;
154 sprintf(headerName, VFORMAT, vol.id);
155 sprintf(volumePath, "%s/%s", VPartitionPath(partition), headerName);
156 fd = open(volumePath, O_CREAT|O_EXCL|O_WRONLY, 0600);
158 if (errno == EEXIST) {
159 Log("VCreateVolume: Header file %s already exists!\n", volumePath);
163 Log("VCreateVolume: Couldn't create header file %s for volume %u\n", volumePath, vol.id);
168 device = partition->device;
170 for (i = 0; i<nFILES; i++) {
171 register struct stuff *p = &stuff[i];
175 *(p->inode) = IH_CREATE(NULL, device, VPartitionPath(partition),
177 (p->inodeType == VI_LINKTABLE) ? vol.parentId :
179 INODESPECIAL, p->inodeType,
181 if (!(VALID_INO(*(p->inode)))) {
182 if (errno == EEXIST) {
183 /* Increment the reference count instead. */
188 *(p->inode) = nt_MakeSpecIno(VI_LINKTABLE);
190 *(p->inode) = namei_MakeSpecIno(vol.parentId, VI_LINKTABLE);
192 IH_INIT(lh, device, parentId, *(p->inode));
198 code = IH_INC(lh, *(p->inode), parentId);
199 FDH_REALLYCLOSE(fdP);
207 *(p->inode) = IH_CREATE(NULL, device, VPartitionPath(partition),
208 nearInode, vol.id, INODESPECIAL, p->inodeType,
212 if (!VALID_INO(*(p->inode))) {
213 Log("VCreateVolume: Problem creating %s file associated with volume header %s\n", p->description, volumePath);
217 RemoveInodes(device, vol.id);
222 IH_INIT(handle, device, vol.parentId, *(p->inode));
223 fdP = IH_OPEN(handle);
225 Log("VCreateVolume: Problem iopen inode %s (err=%d)\n",
226 PrintInode(NULL, *(p->inode)), errno);
229 if (FDH_SEEK(fdP, 0, SEEK_SET) < 0) {
230 Log("VCreateVolume: Problem lseek inode %s (err=%d)\n",
231 PrintInode(NULL, *(p->inode)), errno);
232 FDH_REALLYCLOSE(fdP);
235 if (FDH_WRITE(fdP, (char*)&p->stamp, sizeof(p->stamp)) != sizeof(p->stamp)) {
236 Log("VCreateVolume: Problem writing to inode %s (err=%d)\n",
237 PrintInode(NULL, *(p->inode)), errno);
238 FDH_REALLYCLOSE(fdP);
241 FDH_REALLYCLOSE(fdP);
243 nearInode = *(p->inode);
246 IH_INIT(handle, device, vol.parentId, tempHeader.volumeInfo);
247 fdP = IH_OPEN(handle);
249 Log("VCreateVolume: Problem iopen inode %d (err=%d)\n", tempHeader.volumeInfo, errno);
253 if (FDH_SEEK(fdP, 0, SEEK_SET) < 0) {
254 Log("VCreateVolume: Problem lseek inode %d (err=%d)\n", tempHeader.volumeInfo, errno);
255 FDH_REALLYCLOSE(fdP);
259 if (FDH_WRITE(fdP, (char*)&vol, sizeof(vol)) != sizeof(vol)) {
260 Log("VCreateVolume: Problem writing to inode %d (err=%d)\n", tempHeader.volumeInfo, errno);
261 FDH_REALLYCLOSE(fdP);
268 VolumeHeaderToDisk(&diskHeader, &tempHeader);
269 if (write(fd, &diskHeader, sizeof (diskHeader)) != sizeof (diskHeader)) {
270 Log("VCreateVolume: Unable to write volume header %s; volume %u not created\n", volumePath, vol.id);
276 return (VAttachVolumeByName(ec, partname, headerName, V_SECRETLY));
280 AssignVolumeName(vol, name, ext)
281 register VolumeDiskData *vol;
285 AssignVolumeName_r(vol, name, ext);
289 AssignVolumeName_r(vol, name, ext)
290 register VolumeDiskData *vol;
294 strncpy(vol->name, name, VNAMESIZE-1);
295 vol->name[VNAMESIZE-1] = '\0';
296 dot = strrchr(vol->name, '.');
297 if (dot && (strcmp(dot,".backup") == 0 || strcmp(dot, ".readonly") == 0))
300 strncat(vol->name, ext, VNAMESIZE-1-strlen(vol->name));
303 afs_int32 CopyVolumeHeader_r(from, to)
304 VolumeDiskData *from, *to;
306 /* The id and parentId fields are not copied; these are inviolate--the to volume
307 is assumed to have already been created. The id's cannot be changed once
308 creation has taken place, since they are embedded in the various inodes associated
309 with the volume. The copydate is also inviolate--it always reflects the time
310 this volume was created (compare with the creation date--the creation date of
311 a backup volume is the creation date of the original parent, because the backup
312 is used to backup the parent volume). */
316 parent = to->parentId;
317 copydate = to->copyDate;
318 bcopy(from, to, sizeof(*from));
320 to->parentId = parent;
321 to->copyDate = copydate;
322 to->destroyMe = DESTROY_ME; /* Caller must always clear this!!! */
323 to->stamp.magic = VOLUMEINFOMAGIC;
324 to->stamp.version = VOLUMEINFOVERSION;
328 afs_int32 CopyVolumeHeader(from, to)
329 VolumeDiskData *from, *to;
334 code = CopyVolumeHeader_r(from, to);
339 ClearVolumeStats(vol)
340 register VolumeDiskData *vol;
343 ClearVolumeStats_r(vol);
347 ClearVolumeStats_r(vol)
348 register VolumeDiskData *vol;
350 bzero(vol->weekUse, sizeof(vol->weekUse));