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 <afs/param.h>
18 #include <afsconfig.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)
68 #define nFILES (sizeof (stuff)/sizeof(struct stuff))
70 /* Note: the volume creation functions herein leave the destroyMe flag in the
71 volume header ON: this means that the volumes will not be attached by the
72 file server and WILL BE DESTROYED the next time a system salvage is performed */
74 static void RemoveInodes(Device dev, int vid)
79 /* This relies on the fact that IDEC only needs the device and NT only
80 * needs the dev and vid to decrement volume special files.
82 IH_INIT(handle, dev, vid, -1);
83 for (i = 0; i<nFILES; i++) {
84 Inode inode = *stuff[i].inode;
86 IH_DEC(handle, inode, vid);
91 Volume *VCreateVolume(ec, partname, volumeId, parentId)
95 VolId parentId; /* Should be the same as volumeId if there is
100 retVal = VCreateVolume_r(ec, partname, volumeId, parentId);
105 Volume *VCreateVolume_r(ec, partname, volumeId, parentId)
109 VolId parentId; /* Should be the same as volumeId if there is
114 char headerName[32], volumePath[64];
117 struct DiskPartition *partition;
118 struct VolumeDiskHeader diskHeader;
127 bzero(&vol, sizeof (vol));
129 vol.parentId = parentId;
130 vol.copyDate = time(0); /* The only date which really means when this
131 @i(instance) of this volume was created.
132 Creation date does not mean this */
134 /* Initialize handle for error case below. */
137 /* Verify that the parition is valid before writing to it. */
138 if (!(partition = VGetPartition(partname, 0))) {
139 Log("VCreateVolume: partition %s is not in service.\n", partname);
143 #if defined(NEARINODE_HINT)
144 nearInodeHash(volumeId,nearInode);
145 nearInode %= partition->f_files;
147 VLockPartition(partname);
148 bzero(&tempHeader, sizeof (tempHeader));
149 tempHeader.stamp.magic = VOLUMEHEADERMAGIC;
150 tempHeader.stamp.version = VOLUMEHEADERVERSION;
151 tempHeader.id = vol.id;
152 tempHeader.parent = vol.parentId;
153 vol.stamp.magic = VOLUMEINFOMAGIC;
154 vol.stamp.version = VOLUMEINFOVERSION;
155 vol.destroyMe = DESTROY_ME;
156 sprintf(headerName, VFORMAT, vol.id);
157 sprintf(volumePath, "%s/%s", VPartitionPath(partition), headerName);
158 fd = open(volumePath, O_CREAT|O_EXCL|O_WRONLY, 0600);
160 if (errno == EEXIST) {
161 Log("VCreateVolume: Header file %s already exists!\n", volumePath);
165 Log("VCreateVolume: Couldn't create header file %s for volume %u\n", volumePath, vol.id);
170 device = partition->device;
172 for (i = 0; i<nFILES; i++) {
173 register struct stuff *p = &stuff[i];
177 *(p->inode) = IH_CREATE(NULL, device, VPartitionPath(partition),
179 (p->inodeType == VI_LINKTABLE) ? vol.parentId :
181 INODESPECIAL, p->inodeType,
183 if (!(VALID_INO(*(p->inode)))) {
184 if (errno == EEXIST) {
185 /* Increment the reference count instead. */
190 *(p->inode) = nt_MakeSpecIno(VI_LINKTABLE);
192 *(p->inode) = namei_MakeSpecIno(vol.parentId, VI_LINKTABLE);
194 IH_INIT(lh, device, parentId, *(p->inode));
200 code = IH_INC(lh, *(p->inode), parentId);
201 FDH_REALLYCLOSE(fdP);
209 *(p->inode) = IH_CREATE(NULL, device, VPartitionPath(partition),
210 nearInode, vol.id, INODESPECIAL, p->inodeType,
214 if (!VALID_INO(*(p->inode))) {
215 Log("VCreateVolume: Problem creating %s file associated with volume header %s\n", p->description, volumePath);
219 RemoveInodes(device, vol.id);
224 IH_INIT(handle, device, vol.parentId, *(p->inode));
225 fdP = IH_OPEN(handle);
227 Log("VCreateVolume: Problem iopen inode %s (err=%d)\n",
228 PrintInode(NULL, *(p->inode)), errno);
231 if (FDH_SEEK(fdP, 0, SEEK_SET) < 0) {
232 Log("VCreateVolume: Problem lseek inode %s (err=%d)\n",
233 PrintInode(NULL, *(p->inode)), errno);
234 FDH_REALLYCLOSE(fdP);
237 if (FDH_WRITE(fdP, (char*)&p->stamp, sizeof(p->stamp)) != sizeof(p->stamp)) {
238 Log("VCreateVolume: Problem writing to inode %s (err=%d)\n",
239 PrintInode(NULL, *(p->inode)), errno);
240 FDH_REALLYCLOSE(fdP);
243 FDH_REALLYCLOSE(fdP);
245 nearInode = *(p->inode);
248 IH_INIT(handle, device, vol.parentId, tempHeader.volumeInfo);
249 fdP = IH_OPEN(handle);
251 Log("VCreateVolume: Problem iopen inode %d (err=%d)\n", tempHeader.volumeInfo, errno);
255 if (FDH_SEEK(fdP, 0, SEEK_SET) < 0) {
256 Log("VCreateVolume: Problem lseek inode %d (err=%d)\n", tempHeader.volumeInfo, errno);
257 FDH_REALLYCLOSE(fdP);
261 if (FDH_WRITE(fdP, (char*)&vol, sizeof(vol)) != sizeof(vol)) {
262 Log("VCreateVolume: Problem writing to inode %d (err=%d)\n", tempHeader.volumeInfo, errno);
263 FDH_REALLYCLOSE(fdP);
270 VolumeHeaderToDisk(&diskHeader, &tempHeader);
271 if (write(fd, &diskHeader, sizeof (diskHeader)) != sizeof (diskHeader)) {
272 Log("VCreateVolume: Unable to write volume header %s; volume %u not created\n", volumePath, vol.id);
278 return (VAttachVolumeByName(ec, partname, headerName, V_SECRETLY));
282 AssignVolumeName(vol, name, ext)
283 register VolumeDiskData *vol;
287 AssignVolumeName_r(vol, name, ext);
291 AssignVolumeName_r(vol, name, ext)
292 register VolumeDiskData *vol;
296 strncpy(vol->name, name, VNAMESIZE-1);
297 vol->name[VNAMESIZE-1] = '\0';
298 dot = strrchr(vol->name, '.');
299 if (dot && (strcmp(dot,".backup") == 0 || strcmp(dot, ".readonly") == 0))
302 strncat(vol->name, ext, VNAMESIZE-1-strlen(vol->name));
305 afs_int32 CopyVolumeHeader_r(from, to)
306 VolumeDiskData *from, *to;
308 /* The id and parentId fields are not copied; these are inviolate--the to volume
309 is assumed to have already been created. The id's cannot be changed once
310 creation has taken place, since they are embedded in the various inodes associated
311 with the volume. The copydate is also inviolate--it always reflects the time
312 this volume was created (compare with the creation date--the creation date of
313 a backup volume is the creation date of the original parent, because the backup
314 is used to backup the parent volume). */
318 parent = to->parentId;
319 copydate = to->copyDate;
320 bcopy(from, to, sizeof(*from));
322 to->parentId = parent;
323 to->copyDate = copydate;
324 to->destroyMe = DESTROY_ME; /* Caller must always clear this!!! */
325 to->stamp.magic = VOLUMEINFOMAGIC;
326 to->stamp.version = VOLUMEINFOVERSION;
330 afs_int32 CopyVolumeHeader(from, to)
331 VolumeDiskData *from, *to;
336 code = CopyVolumeHeader_r(from, to);
341 ClearVolumeStats(vol)
342 register VolumeDiskData *vol;
345 ClearVolumeStats_r(vol);
349 ClearVolumeStats_r(vol)
350 register VolumeDiskData *vol;
352 bzero(vol->weekUse, sizeof(vol->weekUse));