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 /*@printflike@*/ extern void Log(const char *format, ...);
69 void AssignVolumeName();
70 void AssignVolumeName_r();
71 void ClearVolumeStats();
72 void ClearVolumeStats_r();
75 #define nFILES (sizeof (stuff)/sizeof(struct stuff))
77 /* Note: the volume creation functions herein leave the destroyMe flag in the
78 volume header ON: this means that the volumes will not be attached by the
79 file server and WILL BE DESTROYED the next time a system salvage is performed */
81 static void RemoveInodes(Device dev, VolumeId vid)
86 /* This relies on the fact that IDEC only needs the device and NT only
87 * needs the dev and vid to decrement volume special files.
89 IH_INIT(handle, dev, vid, -1);
90 for (i = 0; i<nFILES; i++) {
91 Inode inode = *stuff[i].inode;
93 IH_DEC(handle, inode, vid);
98 Volume *VCreateVolume(ec, partname, volumeId, parentId)
102 VolId parentId; /* Should be the same as volumeId if there is
107 retVal = VCreateVolume_r(ec, partname, volumeId, parentId);
112 Volume *VCreateVolume_r(ec, partname, volumeId, parentId)
116 VolId parentId; /* Should be the same as volumeId if there is
121 char headerName[32], volumePath[64];
123 struct DiskPartition *partition;
124 struct VolumeDiskHeader diskHeader;
130 memset(&vol, 0, sizeof (vol));
132 vol.parentId = parentId;
133 vol.copyDate = time(0); /* The only date which really means when this
134 @i(instance) of this volume was created.
135 Creation date does not mean this */
137 /* Initialize handle for error case below. */
140 /* Verify that the parition is valid before writing to it. */
141 if (!(partition = VGetPartition(partname, 0))) {
142 Log("VCreateVolume: partition %s is not in service.\n", partname);
146 #if defined(NEARINODE_HINT)
147 nearInodeHash(volumeId,nearInode);
148 nearInode %= partition->f_files;
150 VLockPartition(partname);
151 memset(&tempHeader, 0, sizeof (tempHeader));
152 tempHeader.stamp.magic = VOLUMEHEADERMAGIC;
153 tempHeader.stamp.version = VOLUMEHEADERVERSION;
154 tempHeader.id = vol.id;
155 tempHeader.parent = vol.parentId;
156 vol.stamp.magic = VOLUMEINFOMAGIC;
157 vol.stamp.version = VOLUMEINFOVERSION;
158 vol.destroyMe = DESTROY_ME;
159 sprintf(headerName, VFORMAT, vol.id);
160 sprintf(volumePath, "%s/%s", VPartitionPath(partition), headerName);
161 fd = open(volumePath, O_CREAT|O_EXCL|O_WRONLY, 0600);
163 if (errno == EEXIST) {
164 Log("VCreateVolume: Header file %s already exists!\n", volumePath);
168 Log("VCreateVolume: Couldn't create header file %s for volume %u\n", volumePath, vol.id);
173 device = partition->device;
175 for (i = 0; i<nFILES; i++) {
176 register struct stuff *p = &stuff[i];
180 *(p->inode) = IH_CREATE(NULL, device, VPartitionPath(partition),
182 (p->inodeType == VI_LINKTABLE) ? vol.parentId :
184 INODESPECIAL, p->inodeType,
186 if (!(VALID_INO(*(p->inode)))) {
187 if (errno == EEXIST) {
188 /* Increment the reference count instead. */
193 *(p->inode) = nt_MakeSpecIno(VI_LINKTABLE);
195 *(p->inode) = namei_MakeSpecIno(vol.parentId, VI_LINKTABLE);
197 IH_INIT(lh, device, parentId, *(p->inode));
203 code = IH_INC(lh, *(p->inode), parentId);
204 FDH_REALLYCLOSE(fdP);
212 *(p->inode) = IH_CREATE(NULL, device, VPartitionPath(partition),
213 nearInode, vol.id, INODESPECIAL, p->inodeType,
217 if (!VALID_INO(*(p->inode))) {
218 Log("VCreateVolume: Problem creating %s file associated with volume header %s\n", p->description, volumePath);
222 RemoveInodes(device, vol.id);
227 IH_INIT(handle, device, vol.parentId, *(p->inode));
228 fdP = IH_OPEN(handle);
230 Log("VCreateVolume: Problem iopen inode %s (err=%d)\n",
231 PrintInode(NULL, *(p->inode)), errno);
234 if (FDH_SEEK(fdP, 0, SEEK_SET) < 0) {
235 Log("VCreateVolume: Problem lseek inode %s (err=%d)\n",
236 PrintInode(NULL, *(p->inode)), errno);
237 FDH_REALLYCLOSE(fdP);
240 if (FDH_WRITE(fdP, (char*)&p->stamp, sizeof(p->stamp)) != sizeof(p->stamp)) {
241 Log("VCreateVolume: Problem writing to inode %s (err=%d)\n",
242 PrintInode(NULL, *(p->inode)), errno);
243 FDH_REALLYCLOSE(fdP);
246 FDH_REALLYCLOSE(fdP);
248 nearInode = *(p->inode);
251 IH_INIT(handle, device, vol.parentId, tempHeader.volumeInfo);
252 fdP = IH_OPEN(handle);
254 Log("VCreateVolume: Problem iopen inode %d (err=%d)\n", tempHeader.volumeInfo, errno);
258 if (FDH_SEEK(fdP, 0, SEEK_SET) < 0) {
259 Log("VCreateVolume: Problem lseek inode %d (err=%d)\n", tempHeader.volumeInfo, errno);
260 FDH_REALLYCLOSE(fdP);
264 if (FDH_WRITE(fdP, (char*)&vol, sizeof(vol)) != sizeof(vol)) {
265 Log("VCreateVolume: Problem writing to inode %d (err=%d)\n", tempHeader.volumeInfo, errno);
266 FDH_REALLYCLOSE(fdP);
273 VolumeHeaderToDisk(&diskHeader, &tempHeader);
274 if (write(fd, &diskHeader, sizeof (diskHeader)) != sizeof (diskHeader)) {
275 Log("VCreateVolume: Unable to write volume header %s; volume %u not created\n", volumePath, vol.id);
281 return (VAttachVolumeByName(ec, partname, headerName, V_SECRETLY));
286 AssignVolumeName(vol, name, ext)
287 register VolumeDiskData *vol;
291 AssignVolumeName_r(vol, name, ext);
296 AssignVolumeName_r(vol, name, ext)
297 register VolumeDiskData *vol;
301 strncpy(vol->name, name, VNAMESIZE-1);
302 vol->name[VNAMESIZE-1] = '\0';
303 dot = strrchr(vol->name, '.');
304 if (dot && (strcmp(dot,".backup") == 0 || strcmp(dot, ".readonly") == 0))
307 strncat(vol->name, ext, VNAMESIZE-1-strlen(vol->name));
310 afs_int32 CopyVolumeHeader_r(from, to)
311 VolumeDiskData *from, *to;
313 /* The id and parentId fields are not copied; these are inviolate--the to volume
314 is assumed to have already been created. The id's cannot be changed once
315 creation has taken place, since they are embedded in the various inodes associated
316 with the volume. The copydate is also inviolate--it always reflects the time
317 this volume was created (compare with the creation date--the creation date of
318 a backup volume is the creation date of the original parent, because the backup
319 is used to backup the parent volume). */
323 parent = to->parentId;
324 copydate = to->copyDate;
325 memcpy(to, from, sizeof(*from));
327 to->parentId = parent;
328 to->copyDate = copydate;
329 to->destroyMe = DESTROY_ME; /* Caller must always clear this!!! */
330 to->stamp.magic = VOLUMEINFOMAGIC;
331 to->stamp.version = VOLUMEINFOVERSION;
335 afs_int32 CopyVolumeHeader(from, to)
336 VolumeDiskData *from, *to;
341 code = CopyVolumeHeader_r(from, to);
347 ClearVolumeStats(vol)
348 register VolumeDiskData *vol;
351 ClearVolumeStats_r(vol);
356 ClearVolumeStats_r(vol)
357 register VolumeDiskData *vol;
359 memset(vol->weekUse, 0, sizeof(vol->weekUse));