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>
48 #include <afs/afsutil.h>
55 #include "partition.h"
56 #include "viceinode.h"
58 #include "volinodes.h"
60 #include <sys/lockf.h>
62 #if defined(AFS_SUN5_ENV) || defined(AFS_NT40_ENV) || defined(AFS_LINUX20_ENV)
69 /*@printflike@*/ extern void Log(const char *format, ...);
71 void AssignVolumeName();
72 void AssignVolumeName_r();
73 void ClearVolumeStats();
74 void ClearVolumeStats_r();
77 #define nFILES (sizeof (stuff)/sizeof(struct stuff))
79 /* Note: the volume creation functions herein leave the destroyMe flag in the
80 volume header ON: this means that the volumes will not be attached by the
81 file server and WILL BE DESTROYED the next time a system salvage is performed */
83 static void RemoveInodes(Device dev, VolumeId vid)
88 /* This relies on the fact that IDEC only needs the device and NT only
89 * needs the dev and vid to decrement volume special files.
91 IH_INIT(handle, dev, vid, -1);
92 for (i = 0; i<nFILES; i++) {
93 Inode inode = *stuff[i].inode;
95 IH_DEC(handle, inode, vid);
100 Volume *VCreateVolume(
104 VolId parentId) /* Should be the same as volumeId if there is
109 retVal = VCreateVolume_r(ec, partname, volumeId, parentId);
114 Volume *VCreateVolume_r(
118 VolId parentId) /* Should be the same as volumeId if there is
123 char headerName[32], volumePath[64];
125 struct DiskPartition *partition;
126 struct VolumeDiskHeader diskHeader;
132 memset(&vol, 0, sizeof (vol));
134 vol.parentId = parentId;
135 vol.copyDate = time(0); /* The only date which really means when this
136 @i(instance) of this volume was created.
137 Creation date does not mean this */
139 /* Initialize handle for error case below. */
142 /* Verify that the parition is valid before writing to it. */
143 if (!(partition = VGetPartition(partname, 0))) {
144 Log("VCreateVolume: partition %s is not in service.\n", partname);
148 #if defined(NEARINODE_HINT)
149 nearInodeHash(volumeId,nearInode);
150 nearInode %= partition->f_files;
152 VLockPartition(partname);
153 memset(&tempHeader, 0, sizeof (tempHeader));
154 tempHeader.stamp.magic = VOLUMEHEADERMAGIC;
155 tempHeader.stamp.version = VOLUMEHEADERVERSION;
156 tempHeader.id = vol.id;
157 tempHeader.parent = vol.parentId;
158 vol.stamp.magic = VOLUMEINFOMAGIC;
159 vol.stamp.version = VOLUMEINFOVERSION;
160 vol.destroyMe = DESTROY_ME;
161 (void) afs_snprintf(headerName, sizeof headerName, VFORMAT, vol.id);
162 (void) afs_snprintf(volumePath, sizeof volumePath,
163 "%s/%s", VPartitionPath(partition), headerName);
164 fd = open(volumePath, O_CREAT|O_EXCL|O_WRONLY, 0600);
166 if (errno == EEXIST) {
167 Log("VCreateVolume: Header file %s already exists!\n", volumePath);
171 Log("VCreateVolume: Couldn't create header file %s for volume %u\n", volumePath, vol.id);
176 device = partition->device;
178 for (i = 0; i<nFILES; i++) {
179 register struct stuff *p = &stuff[i];
183 *(p->inode) = IH_CREATE(NULL, device, VPartitionPath(partition),
185 (p->inodeType == VI_LINKTABLE) ? vol.parentId :
187 INODESPECIAL, p->inodeType,
189 if (!(VALID_INO(*(p->inode)))) {
190 if (errno == EEXIST) {
191 /* Increment the reference count instead. */
196 *(p->inode) = nt_MakeSpecIno(VI_LINKTABLE);
198 *(p->inode) = namei_MakeSpecIno(vol.parentId, VI_LINKTABLE);
200 IH_INIT(lh, device, parentId, *(p->inode));
206 code = IH_INC(lh, *(p->inode), parentId);
207 FDH_REALLYCLOSE(fdP);
215 *(p->inode) = IH_CREATE(NULL, device, VPartitionPath(partition),
216 nearInode, vol.id, INODESPECIAL, p->inodeType,
220 if (!VALID_INO(*(p->inode))) {
221 Log("VCreateVolume: Problem creating %s file associated with volume header %s\n", p->description, volumePath);
225 RemoveInodes(device, vol.id);
230 IH_INIT(handle, device, vol.parentId, *(p->inode));
231 fdP = IH_OPEN(handle);
233 Log("VCreateVolume: Problem iopen inode %s (err=%d)\n",
234 PrintInode(NULL, *(p->inode)), errno);
237 if (FDH_SEEK(fdP, 0, SEEK_SET) < 0) {
238 Log("VCreateVolume: Problem lseek inode %s (err=%d)\n",
239 PrintInode(NULL, *(p->inode)), errno);
240 FDH_REALLYCLOSE(fdP);
243 if (FDH_WRITE(fdP, (char*)&p->stamp, sizeof(p->stamp)) != sizeof(p->stamp)) {
244 Log("VCreateVolume: Problem writing to inode %s (err=%d)\n",
245 PrintInode(NULL, *(p->inode)), errno);
246 FDH_REALLYCLOSE(fdP);
249 FDH_REALLYCLOSE(fdP);
251 nearInode = *(p->inode);
254 IH_INIT(handle, device, vol.parentId, tempHeader.volumeInfo);
255 fdP = IH_OPEN(handle);
257 Log("VCreateVolume: Problem iopen inode %llu (err=%d)\n",
258 (afs_uintmax_t)tempHeader.volumeInfo, errno);
262 if (FDH_SEEK(fdP, 0, SEEK_SET) < 0) {
263 Log("VCreateVolume: Problem lseek inode %llu (err=%d)\n",
264 (afs_uintmax_t)tempHeader.volumeInfo, errno);
265 FDH_REALLYCLOSE(fdP);
269 if (FDH_WRITE(fdP, (char*)&vol, sizeof(vol)) != sizeof(vol)) {
270 Log("VCreateVolume: Problem writing to inode %llu (err=%d)\n",
271 (afs_uintmax_t)tempHeader.volumeInfo, errno);
272 FDH_REALLYCLOSE(fdP);
279 VolumeHeaderToDisk(&diskHeader, &tempHeader);
280 if (write(fd, &diskHeader, sizeof (diskHeader)) != sizeof (diskHeader)) {
281 Log("VCreateVolume: Unable to write volume header %s; volume %u not created\n", volumePath, vol.id);
287 return (VAttachVolumeByName(ec, partname, headerName, V_SECRETLY));
292 AssignVolumeName(register VolumeDiskData *vol, char *name, char *ext)
295 AssignVolumeName_r(vol, name, ext);
300 AssignVolumeName_r(register VolumeDiskData *vol, char *name, char *ext)
303 strncpy(vol->name, name, VNAMESIZE-1);
304 vol->name[VNAMESIZE-1] = '\0';
305 dot = strrchr(vol->name, '.');
306 if (dot && (strcmp(dot,".backup") == 0 || strcmp(dot, ".readonly") == 0))
309 strncat(vol->name, ext, VNAMESIZE-1-strlen(vol->name));
312 afs_int32 CopyVolumeHeader_r(VolumeDiskData *from, VolumeDiskData *to)
314 /* The id and parentId fields are not copied; these are inviolate--the to volume
315 is assumed to have already been created. The id's cannot be changed once
316 creation has taken place, since they are embedded in the various inodes associated
317 with the volume. The copydate is also inviolate--it always reflects the time
318 this volume was created (compare with the creation date--the creation date of
319 a backup volume is the creation date of the original parent, because the backup
320 is used to backup the parent volume). */
324 parent = to->parentId;
325 copydate = to->copyDate;
326 memcpy(to, from, sizeof(*from));
328 to->parentId = parent;
329 to->copyDate = copydate;
330 to->destroyMe = DESTROY_ME; /* Caller must always clear this!!! */
331 to->stamp.magic = VOLUMEINFOMAGIC;
332 to->stamp.version = VOLUMEINFOVERSION;
336 afs_int32 CopyVolumeHeader(VolumeDiskData *from, VolumeDiskData *to)
341 code = CopyVolumeHeader_r(from, to);
347 ClearVolumeStats(register VolumeDiskData *vol)
350 ClearVolumeStats_r(vol);
355 ClearVolumeStats_r(register VolumeDiskData *vol)
357 memset(vol->weekUse, 0, sizeof(vol->weekUse));