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
13 Institution: The Information Technology Center, Carnegie-Mellon University
17 #include <afsconfig.h>
18 #include <afs/param.h>
23 #include <sys/types.h>
34 #ifdef AFS_PTHREAD_ENV
36 #else /* AFS_PTHREAD_ENV */
37 #include <afs/assert.h>
38 #endif /* AFS_PTHREAD_ENV */
41 #include <afs/afsint.h>
43 #include <afs/errors.h>
46 #include <afs/afssyscalls.h>
54 #include "partition.h"
55 #include "viceinode.h"
57 #include "volinodes.h"
59 #include <sys/lockf.h>
61 #if defined(AFS_SUN5_ENV) || defined(AFS_NT40_ENV) || defined(AFS_LINUX20_ENV)
67 void AssignVolumeName();
68 void AssignVolumeName_r();
69 void ClearVolumeStats();
70 void ClearVolumeStats_r();
73 #define nFILES (sizeof (stuff)/sizeof(struct stuff))
75 /* Note: the volume creation functions herein leave the destroyMe flag in the
76 volume header ON: this means that the volumes will not be attached by the
77 file server and WILL BE DESTROYED the next time a system salvage is performed */
79 static void RemoveInodes(Device dev, int vid)
84 /* This relies on the fact that IDEC only needs the device and NT only
85 * needs the dev and vid to decrement volume special files.
87 IH_INIT(handle, dev, vid, -1);
88 for (i = 0; i<nFILES; i++) {
89 Inode inode = *stuff[i].inode;
91 IH_DEC(handle, inode, vid);
96 Volume *VCreateVolume(ec, partname, volumeId, parentId)
100 VolId parentId; /* Should be the same as volumeId if there is
105 retVal = VCreateVolume_r(ec, partname, volumeId, parentId);
110 Volume *VCreateVolume_r(ec, partname, volumeId, parentId)
114 VolId parentId; /* Should be the same as volumeId if there is
119 char headerName[32], volumePath[64];
121 struct DiskPartition *partition;
122 struct VolumeDiskHeader diskHeader;
128 memset(&vol, 0, sizeof (vol));
130 vol.parentId = parentId;
131 vol.copyDate = time(0); /* The only date which really means when this
132 @i(instance) of this volume was created.
133 Creation date does not mean this */
135 /* Initialize handle for error case below. */
138 /* Verify that the parition is valid before writing to it. */
139 if (!(partition = VGetPartition(partname, 0))) {
140 Log("VCreateVolume: partition %s is not in service.\n", partname);
144 #if defined(NEARINODE_HINT)
145 nearInodeHash(volumeId,nearInode);
146 nearInode %= partition->f_files;
148 VLockPartition(partname);
149 memset(&tempHeader, 0, sizeof (tempHeader));
150 tempHeader.stamp.magic = VOLUMEHEADERMAGIC;
151 tempHeader.stamp.version = VOLUMEHEADERVERSION;
152 tempHeader.id = vol.id;
153 tempHeader.parent = vol.parentId;
154 vol.stamp.magic = VOLUMEINFOMAGIC;
155 vol.stamp.version = VOLUMEINFOVERSION;
156 vol.destroyMe = DESTROY_ME;
157 sprintf(headerName, VFORMAT, vol.id);
158 sprintf(volumePath, "%s/%s", VPartitionPath(partition), headerName);
159 fd = open(volumePath, O_CREAT|O_EXCL|O_WRONLY, 0600);
161 if (errno == EEXIST) {
162 Log("VCreateVolume: Header file %s already exists!\n", volumePath);
166 Log("VCreateVolume: Couldn't create header file %s for volume %u\n", volumePath, vol.id);
171 device = partition->device;
173 for (i = 0; i<nFILES; i++) {
174 register struct stuff *p = &stuff[i];
178 *(p->inode) = IH_CREATE(NULL, device, VPartitionPath(partition),
180 (p->inodeType == VI_LINKTABLE) ? vol.parentId :
182 INODESPECIAL, p->inodeType,
184 if (!(VALID_INO(*(p->inode)))) {
185 if (errno == EEXIST) {
186 /* Increment the reference count instead. */
191 *(p->inode) = nt_MakeSpecIno(VI_LINKTABLE);
193 *(p->inode) = namei_MakeSpecIno(vol.parentId, VI_LINKTABLE);
195 IH_INIT(lh, device, parentId, *(p->inode));
201 code = IH_INC(lh, *(p->inode), parentId);
202 FDH_REALLYCLOSE(fdP);
210 *(p->inode) = IH_CREATE(NULL, device, VPartitionPath(partition),
211 nearInode, vol.id, INODESPECIAL, p->inodeType,
215 if (!VALID_INO(*(p->inode))) {
216 Log("VCreateVolume: Problem creating %s file associated with volume header %s\n", p->description, volumePath);
220 RemoveInodes(device, vol.id);
225 IH_INIT(handle, device, vol.parentId, *(p->inode));
226 fdP = IH_OPEN(handle);
228 Log("VCreateVolume: Problem iopen inode %s (err=%d)\n",
229 PrintInode(NULL, *(p->inode)), errno);
232 if (FDH_SEEK(fdP, 0, SEEK_SET) < 0) {
233 Log("VCreateVolume: Problem lseek inode %s (err=%d)\n",
234 PrintInode(NULL, *(p->inode)), errno);
235 FDH_REALLYCLOSE(fdP);
238 if (FDH_WRITE(fdP, (char*)&p->stamp, sizeof(p->stamp)) != sizeof(p->stamp)) {
239 Log("VCreateVolume: Problem writing to inode %s (err=%d)\n",
240 PrintInode(NULL, *(p->inode)), errno);
241 FDH_REALLYCLOSE(fdP);
244 FDH_REALLYCLOSE(fdP);
246 nearInode = *(p->inode);
249 IH_INIT(handle, device, vol.parentId, tempHeader.volumeInfo);
250 fdP = IH_OPEN(handle);
252 Log("VCreateVolume: Problem iopen inode %d (err=%d)\n", tempHeader.volumeInfo, errno);
256 if (FDH_SEEK(fdP, 0, SEEK_SET) < 0) {
257 Log("VCreateVolume: Problem lseek inode %d (err=%d)\n", tempHeader.volumeInfo, errno);
258 FDH_REALLYCLOSE(fdP);
262 if (FDH_WRITE(fdP, (char*)&vol, sizeof(vol)) != sizeof(vol)) {
263 Log("VCreateVolume: Problem writing to inode %d (err=%d)\n", tempHeader.volumeInfo, errno);
264 FDH_REALLYCLOSE(fdP);
271 VolumeHeaderToDisk(&diskHeader, &tempHeader);
272 if (write(fd, &diskHeader, sizeof (diskHeader)) != sizeof (diskHeader)) {
273 Log("VCreateVolume: Unable to write volume header %s; volume %u not created\n", volumePath, vol.id);
279 return (VAttachVolumeByName(ec, partname, headerName, V_SECRETLY));
284 AssignVolumeName(vol, name, ext)
285 register VolumeDiskData *vol;
289 AssignVolumeName_r(vol, name, ext);
294 AssignVolumeName_r(vol, name, ext)
295 register VolumeDiskData *vol;
299 strncpy(vol->name, name, VNAMESIZE-1);
300 vol->name[VNAMESIZE-1] = '\0';
301 dot = strrchr(vol->name, '.');
302 if (dot && (strcmp(dot,".backup") == 0 || strcmp(dot, ".readonly") == 0))
305 strncat(vol->name, ext, VNAMESIZE-1-strlen(vol->name));
308 afs_int32 CopyVolumeHeader_r(from, to)
309 VolumeDiskData *from, *to;
311 /* The id and parentId fields are not copied; these are inviolate--the to volume
312 is assumed to have already been created. The id's cannot be changed once
313 creation has taken place, since they are embedded in the various inodes associated
314 with the volume. The copydate is also inviolate--it always reflects the time
315 this volume was created (compare with the creation date--the creation date of
316 a backup volume is the creation date of the original parent, because the backup
317 is used to backup the parent volume). */
321 parent = to->parentId;
322 copydate = to->copyDate;
323 memcpy(to, from, sizeof(*from));
325 to->parentId = parent;
326 to->copyDate = copydate;
327 to->destroyMe = DESTROY_ME; /* Caller must always clear this!!! */
328 to->stamp.magic = VOLUMEINFOMAGIC;
329 to->stamp.version = VOLUMEINFOVERSION;
333 afs_int32 CopyVolumeHeader(from, to)
334 VolumeDiskData *from, *to;
339 code = CopyVolumeHeader_r(from, to);
345 ClearVolumeStats(vol)
346 register VolumeDiskData *vol;
349 ClearVolumeStats_r(vol);
354 ClearVolumeStats_r(vol)
355 register VolumeDiskData *vol;
357 memset(vol->weekUse, 0, sizeof(vol->weekUse));