~ubuntu-branches/ubuntu/warty/openafs/warty

« back to all changes in this revision

Viewing changes to src/vol/vutil.c

  • Committer: Bazaar Package Importer
  • Author(s): Sam Hartman
  • Date: 2004-01-10 16:37:33 UTC
  • Revision ID: james.westby@ubuntu.com-20040110163733-jvr0n1uahshlb1uu
Tags: upstream-1.2.11
ImportĀ upstreamĀ versionĀ 1.2.11

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright 2000, International Business Machines Corporation and others.
 
3
 * All Rights Reserved.
 
4
 * 
 
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
 
8
 */
 
9
 
 
10
/*
 
11
        System:         VICE-TWO
 
12
        Module:         vutil.c
 
13
        Institution:    The Information Technology Center, Carnegie-Mellon University
 
14
 
 
15
 */
 
16
 
 
17
#include <afsconfig.h>
 
18
#include <afs/param.h>
 
19
 
 
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 $");
 
21
 
 
22
#include <stdio.h>
 
23
#include <sys/types.h>
 
24
#include <errno.h>
 
25
#ifdef AFS_NT40_ENV
 
26
#include <time.h>
 
27
#include <fcntl.h>
 
28
#else
 
29
#include <sys/time.h>
 
30
#include <sys/file.h>
 
31
#include <unistd.h>
 
32
#endif
 
33
#include <sys/stat.h>
 
34
#ifdef AFS_PTHREAD_ENV
 
35
#include <assert.h>
 
36
#else /* AFS_PTHREAD_ENV */
 
37
#include <afs/assert.h>
 
38
#endif /* AFS_PTHREAD_ENV */
 
39
 
 
40
#include <rx/xdr.h>
 
41
#include <afs/afsint.h>
 
42
#include "nfs.h"
 
43
#include <afs/errors.h>
 
44
#include "lock.h"
 
45
#include "lwp.h"
 
46
#include <afs/afssyscalls.h>
 
47
#include "ihandle.h"
 
48
#ifdef AFS_NT40_ENV
 
49
#include "ntops.h"
 
50
#include <io.h>
 
51
#endif
 
52
#include "vnode.h"
 
53
#include "volume.h"
 
54
#include "partition.h"
 
55
#include "viceinode.h"
 
56
 
 
57
#include "volinodes.h"
 
58
#ifdef  AFS_AIX_ENV
 
59
#include <sys/lockf.h>
 
60
#endif
 
61
#if defined(AFS_SUN5_ENV) || defined(AFS_NT40_ENV) || defined(AFS_LINUX20_ENV)
 
62
#include <string.h>
 
63
#else
 
64
#include <strings.h>
 
65
#endif
 
66
 
 
67
void AssignVolumeName();
 
68
void AssignVolumeName_r();
 
69
void ClearVolumeStats();
 
70
void ClearVolumeStats_r();
 
71
 
 
72
 
 
73
#define nFILES  (sizeof (stuff)/sizeof(struct stuff))
 
74
 
 
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 */
 
78
 
 
79
static void RemoveInodes(Device dev, int vid)
 
80
{
 
81
    register int i;
 
82
    IHandle_t *handle;
 
83
 
 
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.
 
86
     */
 
87
    IH_INIT(handle, dev, vid, -1);
 
88
    for (i = 0; i<nFILES; i++) {
 
89
        Inode inode = *stuff[i].inode;
 
90
        if (VALID_INO(inode))
 
91
            IH_DEC(handle, inode, vid);
 
92
    }
 
93
    IH_RELEASE(handle);
 
94
}
 
95
 
 
96
Volume *VCreateVolume(ec, partname, volumeId, parentId)
 
97
    Error *ec;
 
98
    char *partname;
 
99
    VolId volumeId;
 
100
    VolId parentId;     /* Should be the same as volumeId if there is
 
101
                           no parent */
 
102
{
 
103
    Volume *retVal;
 
104
    VOL_LOCK
 
105
    retVal = VCreateVolume_r(ec, partname, volumeId, parentId);
 
106
    VOL_UNLOCK
 
107
    return retVal;
 
108
}
 
109
 
 
110
Volume *VCreateVolume_r(ec, partname, volumeId, parentId)
 
111
    Error *ec;
 
112
    char *partname;
 
113
    VolId volumeId;
 
114
    VolId parentId;     /* Should be the same as volumeId if there is
 
115
                           no parent */
 
116
{
 
117
    VolumeDiskData vol;
 
118
    int fd, i;
 
119
    char headerName[32], volumePath[64];
 
120
    Device device;
 
121
    struct DiskPartition *partition;
 
122
    struct VolumeDiskHeader diskHeader;
 
123
    IHandle_t *handle;
 
124
    FdHandle_t *fdP;
 
125
    Inode nearInode=0; 
 
126
 
 
127
    *ec = 0;
 
128
    memset(&vol, 0, sizeof (vol));
 
129
    vol.id = volumeId;
 
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 */
 
134
 
 
135
    /* Initialize handle for error case below. */
 
136
    handle = NULL;
 
137
 
 
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);
 
141
        *ec = VNOVOL;
 
142
        return NULL;
 
143
    }
 
144
#if     defined(NEARINODE_HINT)
 
145
    nearInodeHash(volumeId,nearInode);
 
146
    nearInode %= partition->f_files;
 
147
#endif
 
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);
 
160
    if (fd == -1) {
 
161
        if (errno == EEXIST) {
 
162
            Log("VCreateVolume: Header file %s already exists!\n", volumePath);
 
163
            *ec = VVOLEXISTS;
 
164
        }
 
165
        else {
 
166
            Log("VCreateVolume: Couldn't create header file %s for volume %u\n", volumePath, vol.id);
 
167
            *ec = VNOVOL;
 
168
        }
 
169
        return NULL;
 
170
    }
 
171
    device = partition->device;
 
172
 
 
173
    for (i = 0; i<nFILES; i++) {
 
174
        register struct stuff *p = &stuff[i];
 
175
        if (p->obsolete)
 
176
            continue;
 
177
#ifdef AFS_NAMEI_ENV
 
178
        *(p->inode) = IH_CREATE(NULL, device, VPartitionPath(partition),
 
179
                                nearInode, 
 
180
                                (p->inodeType == VI_LINKTABLE) ? vol.parentId :
 
181
                                vol.id,
 
182
                                INODESPECIAL, p->inodeType,
 
183
                                vol.parentId);
 
184
        if (!(VALID_INO(*(p->inode)))) {
 
185
            if (errno == EEXIST) {
 
186
                /* Increment the reference count instead. */
 
187
                IHandle_t *lh;
 
188
                int code;
 
189
 
 
190
#ifdef AFS_NT40_ENV
 
191
                *(p->inode) = nt_MakeSpecIno(VI_LINKTABLE);
 
192
#else
 
193
                *(p->inode) = namei_MakeSpecIno(vol.parentId, VI_LINKTABLE);
 
194
#endif
 
195
                IH_INIT(lh, device, parentId, *(p->inode));
 
196
                fdP = IH_OPEN(lh);
 
197
                if (fdP == NULL) {
 
198
                    IH_RELEASE(lh);
 
199
                    goto bad;
 
200
                }
 
201
                code = IH_INC(lh, *(p->inode), parentId);
 
202
                FDH_REALLYCLOSE(fdP);
 
203
                IH_RELEASE(lh);
 
204
                if (code<0)
 
205
                    goto bad;
 
206
                continue;
 
207
            }
 
208
        }
 
209
#else
 
210
        *(p->inode) = IH_CREATE(NULL, device, VPartitionPath(partition),
 
211
                                nearInode, vol.id, INODESPECIAL, p->inodeType,
 
212
                                vol.parentId);
 
213
#endif
 
214
 
 
215
        if (!VALID_INO(*(p->inode))) {
 
216
            Log("VCreateVolume:  Problem creating %s file associated with volume header %s\n", p->description, volumePath);
 
217
          bad:
 
218
            if(handle)
 
219
                IH_RELEASE(handle);
 
220
            RemoveInodes(device, vol.id);
 
221
            *ec = VNOVOL;
 
222
            close(fd);
 
223
            return NULL;
 
224
        }
 
225
        IH_INIT(handle, device, vol.parentId, *(p->inode));
 
226
        fdP = IH_OPEN(handle);
 
227
        if (fdP == NULL) {
 
228
            Log("VCreateVolume:  Problem iopen inode %s (err=%d)\n",
 
229
                PrintInode(NULL, *(p->inode)), errno);
 
230
           goto bad;
 
231
       }
 
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);
 
236
           goto bad;
 
237
       }
 
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);
 
242
           goto bad;
 
243
       }
 
244
        FDH_REALLYCLOSE(fdP);
 
245
        IH_RELEASE(handle);
 
246
       nearInode = *(p->inode);
 
247
    }
 
248
 
 
249
    IH_INIT(handle, device, vol.parentId, tempHeader.volumeInfo);
 
250
    fdP = IH_OPEN(handle);
 
251
    if (fdP == NULL) {
 
252
        Log("VCreateVolume:  Problem iopen inode %d (err=%d)\n", tempHeader.volumeInfo, errno);
 
253
        unlink(volumePath);
 
254
        goto bad;
 
255
       }
 
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);
 
259
        unlink(volumePath);
 
260
        goto bad;
 
261
       }
 
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);
 
265
        unlink(volumePath);
 
266
        goto bad;
 
267
       }
 
268
    FDH_CLOSE(fdP);
 
269
    IH_RELEASE(handle);
 
270
 
 
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);
 
274
        unlink(volumePath);
 
275
        goto bad;
 
276
    }
 
277
    fsync(fd);
 
278
    close(fd);
 
279
    return (VAttachVolumeByName(ec, partname, headerName, V_SECRETLY));
 
280
}
 
281
 
 
282
 
 
283
void
 
284
AssignVolumeName(vol, name, ext)
 
285
    register VolumeDiskData *vol;
 
286
    char *name,*ext;
 
287
{
 
288
    VOL_LOCK
 
289
    AssignVolumeName_r(vol, name, ext);
 
290
    VOL_UNLOCK
 
291
}
 
292
 
 
293
void
 
294
AssignVolumeName_r(vol, name, ext)
 
295
    register VolumeDiskData *vol;
 
296
    char *name,*ext;
 
297
{
 
298
    register char *dot;
 
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))
 
303
        *dot = 0;
 
304
    if (ext)
 
305
        strncat(vol->name, ext, VNAMESIZE-1-strlen(vol->name));
 
306
}
 
307
 
 
308
afs_int32 CopyVolumeHeader_r(from, to)
 
309
    VolumeDiskData *from, *to;
 
310
{
 
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). */
 
318
    Date copydate;
 
319
    VolumeId id, parent;
 
320
    id = to->id;
 
321
    parent = to->parentId;
 
322
    copydate = to->copyDate;
 
323
    memcpy(to, from, sizeof(*from));
 
324
    to->id = id;
 
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;
 
330
    return 0;
 
331
}
 
332
 
 
333
afs_int32 CopyVolumeHeader(from, to)
 
334
    VolumeDiskData *from, *to;
 
335
{
 
336
    afs_int32 code;
 
337
 
 
338
    VOL_LOCK
 
339
    code = CopyVolumeHeader_r(from, to);
 
340
    VOL_UNLOCK
 
341
    return(code);
 
342
}
 
343
 
 
344
void
 
345
ClearVolumeStats(vol)
 
346
    register VolumeDiskData *vol;
 
347
{
 
348
    VOL_LOCK
 
349
    ClearVolumeStats_r(vol);
 
350
    VOL_UNLOCK
 
351
}
 
352
 
 
353
void
 
354
ClearVolumeStats_r(vol)
 
355
    register VolumeDiskData *vol;
 
356
{
 
357
    memset(vol->weekUse, 0, sizeof(vol->weekUse));
 
358
    vol->dayUse = 0;
 
359
    vol->dayUseDate = 0;
 
360
}