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>
20
RCSID("$Header: /afs/sipb.mit.edu/project/openafs/debian/cvs/openafs/src/vol/vutil.c,v 1.1.1.8 2001/10/14 18:07:26 hartmans Exp $");
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));