Bug Summary

File:vol/vutil.c
Location:line 811, column 8
Description:Value stored to 'p' during its initialization is never read

Annotated Source Code

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#include <roken.h>
21
22#ifdef HAVE_SYS_FILE_H1
23#include <sys/file.h>
24#endif
25
26#ifdef HAVE_SYS_LOCKF_H1
27#include <sys/lockf.h>
28#endif
29
30#include <afs/afs_assert.h>
31
32#include <rx/xdr.h>
33#include <afs/afsint.h>
34#include "nfs.h"
35#include <afs/errors.h>
36#include "lock.h"
37#include "lwp.h"
38#include <afs/afssyscalls.h>
39#include "ihandle.h"
40#include <afs/afsutil.h>
41#ifdef AFS_NT40_ENV
42#include "ntops.h"
43#endif
44#include "vnode.h"
45#include "volume.h"
46#include "volume_inline.h"
47#include "partition.h"
48#include "viceinode.h"
49
50#include "volinodes.h"
51#include "vol_prototypes.h"
52#include "common.h"
53
54#ifndef AFS_NT40_ENV
55# ifdef O_LARGEFILE
56# define AFS_SETLKW13 F_SETLKW64
57# define AFS_SETLK12 F_SETLK64
58# define afs_st_flockflock flock64
59# else
60# define AFS_SETLKW13 F_SETLKW13
61# define AFS_SETLK12 F_SETLK12
62# define afs_st_flockflock flock
63# endif
64#endif
65
66/* Note: the volume creation functions herein leave the destroyMe flag in the
67 volume header ON: this means that the volumes will not be attached by the
68 file server and WILL BE DESTROYED the next time a system salvage is performed */
69
70#ifdef FSSYNC_BUILD_CLIENT1
71static void
72RemoveInodes(struct afs_inode_info *stuff, Device dev, VolumeId vid)
73{
74 int i;
75 IHandle_t *handle;
76
77 /* This relies on the fact that IDEC only needs the device and NT only
78 * needs the dev and vid to decrement volume special files.
79 */
80 IH_INIT(handle, dev, vid, -1)((handle) = ih_init((dev), (vid), (-1)));
81 for (i = 0; i < MAXINODETYPE6; i++) {
82 Inode inode = *stuff[i].inode;
83 if (VALID_INO(inode)((inode) != (Inode)-1 && (inode) != (Inode)0))
84 IH_DEC(handle, inode, vid)namei_dec(handle, inode, vid);
85 }
86 IH_RELEASE(handle)(ih_release(handle), (handle)=((void *)0), 0);
87}
88
89Volume *
90VCreateVolume(Errorbit32 * ec, char *partname, VolId volumeId, VolId parentId)
91{ /* Should be the same as volumeId if there is
92 * no parent */
93 Volume *retVal;
94 VOL_LOCK;
95 retVal = VCreateVolume_r(ec, partname, volumeId, parentId);
96 VOL_UNLOCK;
97 return retVal;
98}
99
100Volume *
101VCreateVolume_r(Errorbit32 * ec, char *partname, VolId volumeId, VolId parentId)
102{ /* Should be the same as volumeId if there is
103 * no parent */
104 VolumeDiskData vol;
105 int i, rc;
106 char headerName[VMAXPATHLEN64], volumePath[VMAXPATHLEN64];
107 Device device;
108 struct DiskPartition64 *partition;
109 struct VolumeDiskHeader diskHeader;
110 IHandle_t *handle;
111 FdHandle_t *fdP;
112 Inode nearInode AFS_UNUSED__attribute__((unused)) = 0;
113 char *part, *name;
114 struct stat st;
115 struct VolumeHeader tempHeader;
116 struct afs_inode_info stuff[MAXINODETYPE6];
117 afs_ino_str_t stmp;
118# ifdef AFS_DEMAND_ATTACH_FS
119 int locktype = 0;
120# endif /* AFS_DEMAND_ATTACH_FS */
121
122 init_inode_info(&tempHeader, stuff);
123
124 *ec = 0;
125 memset(&vol, 0, sizeof(vol));
126 vol.id = volumeId;
127 vol.parentId = parentId;
128 vol.copyDate = time(0); /* The only date which really means when this
129 * @i(instance) of this volume was created.
130 * Creation date does not mean this */
131
132 /* Initialize handle for error case below. */
133 handle = NULL((void *)0);
134
135 /* Verify that the parition is valid before writing to it. */
136 if (!(partition = VGetPartition_r(partname, 0))) {
137 Log("VCreateVolume: partition %s is not in service.\n", partname);
138 *ec = VNOVOL103;
139 return NULL((void *)0);
140 }
141#if defined(NEARINODE_HINT)
142 nearInodeHash(volumeId, nearInode);
143 nearInode %= partition->f_files;
144#endif
145 VGetVolumePath(ec, vol.id, &part, &name);
146 if (*ec == VNOVOL103 || !strcmp(partition->name, part)) {
147 /* this case is ok */
148 } else {
149 /* return EXDEV if it's a clone to an alternate partition
150 * otherwise assume it's a move */
151 if (vol.parentId != vol.id) {
152 *ec = EXDEV18;
153 return NULL((void *)0);
154 }
155 }
156 *ec = 0;
157
158# ifdef AFS_DEMAND_ATTACH_FS
159 /* volume doesn't exist yet, but we must lock it to try to prevent something
160 * else from reading it when we're e.g. half way through creating it (or
161 * something tries to create the same volume at the same time) */
162 locktype = VVolLockType(V_VOLUPD3, 1);
163 rc = VLockVolumeByIdNB(volumeId, partition, locktype);
164 if (rc) {
165 Log("VCreateVolume: vol %lu already locked by someone else\n",
166 afs_printable_uint32_lu(volumeId));
167 *ec = VNOVOL103;
168 return NULL((void *)0);
169 }
170# else /* AFS_DEMAND_ATTACH_FS */
171 VLockPartition_r(partname);
172# endif /* !AFS_DEMAND_ATTACH_FS */
173
174 memset(&tempHeader, 0, sizeof(tempHeader));
175 tempHeader.stamp.magic = VOLUMEHEADERMAGIC((bit32)0x88a1bb3c);
176 tempHeader.stamp.version = VOLUMEHEADERVERSION1;
177 tempHeader.id = vol.id;
178 tempHeader.parent = vol.parentId;
179 vol.stamp.magic = VOLUMEINFOMAGIC((bit32)0x78a1b2c5);
180 vol.stamp.version = VOLUMEINFOVERSION1;
181 vol.destroyMe = DESTROY_ME0xD3;
182 snprintf(headerName, sizeof headerName, VFORMAT"V%010lu.vol",
183 afs_printable_uint32_lu(vol.id));
184 snprintf(volumePath, sizeof volumePath, "%s" OS_DIRSEP"/" "%s",
185 VPartitionPath(partition), headerName);
186 rc = stat(volumePath, &st);
187 if (rc == 0 || errno(* __error()) != ENOENT2) {
188 if (rc == 0) {
189 Log("VCreateVolume: Header file %s already exists!\n",
190 volumePath);
191 *ec = VVOLEXISTS104;
192 } else {
193 Log("VCreateVolume: Error %d trying to stat header file %s\n",
194 errno(* __error()), volumePath);
195 *ec = VNOVOL103;
196 }
197 goto bad_noheader;
198 }
199 device = partition->device;
200
201 for (i = 0; i < MAXINODETYPE6; i++) {
202 struct afs_inode_info *p = &stuff[i];
203 if (p->obsolete)
204 continue;
205#ifdef AFS_NAMEI_ENV1
206 *(p->inode) =
207 IH_CREATE(NULL, device, VPartitionPath(partition), nearInode,namei_icreate(((void *)0), VPartitionPath(partition), (p->
inodeType == 6) ? vol.parentId : vol.id, 0xffffffff, p->inodeType
, vol.parentId)
208 (p->inodeType == VI_LINKTABLE) ? vol.parentId : vol.id,namei_icreate(((void *)0), VPartitionPath(partition), (p->
inodeType == 6) ? vol.parentId : vol.id, 0xffffffff, p->inodeType
, vol.parentId)
209 INODESPECIAL, p->inodeType, vol.parentId)namei_icreate(((void *)0), VPartitionPath(partition), (p->
inodeType == 6) ? vol.parentId : vol.id, 0xffffffff, p->inodeType
, vol.parentId)
;
210 if (!(VALID_INO(*(p->inode))((*(p->inode)) != (Inode)-1 && (*(p->inode)) !=
(Inode)0)
)) {
211 if (errno(* __error()) == EEXIST17 && (p->inodeType == VI_LINKTABLE6)) {
212 /* Increment the reference count instead. */
213 IHandle_t *lh;
214 int code;
215
216 *(p->inode) = namei_MakeSpecIno(vol.parentId, VI_LINKTABLE6);
217 IH_INIT(lh, device, parentId, *(p->inode))((lh) = ih_init((device), (parentId), (*(p->inode))));
218 fdP = IH_OPEN(lh)ih_open(lh);
219 if (fdP == NULL((void *)0)) {
220 IH_RELEASE(lh)(ih_release(lh), (lh)=((void *)0), 0);
221 goto bad;
222 }
223 code = IH_INC(lh, *(p->inode), parentId)namei_inc(lh, *(p->inode), parentId);
224 FDH_REALLYCLOSE(fdP)(fd_reallyclose(fdP), (fdP)=((void *)0), 0);
225 IH_RELEASE(lh)(ih_release(lh), (lh)=((void *)0), 0);
226 if (code < 0)
227 goto bad;
228 continue;
229 }
230 }
231#else
232 *(p->inode) =
233 IH_CREATE(NULL, device, VPartitionPath(partition), nearInode,namei_icreate(((void *)0), VPartitionPath(partition), vol.id,
0xffffffff, p->inodeType, vol.parentId)
234 vol.id, INODESPECIAL, p->inodeType, vol.parentId)namei_icreate(((void *)0), VPartitionPath(partition), vol.id,
0xffffffff, p->inodeType, vol.parentId)
;
235#endif
236
237 if (!VALID_INO(*(p->inode))((*(p->inode)) != (Inode)-1 && (*(p->inode)) !=
(Inode)0)
) {
238 Log("VCreateVolume: Problem creating %s file associated with volume header %s\n", p->description, volumePath);
239 bad:
240 if (handle)
241 IH_RELEASE(handle)(ih_release(handle), (handle)=((void *)0), 0);
242 RemoveInodes(stuff, device, vol.id);
243 if (!*ec) {
244 *ec = VNOVOL103;
245 }
246 VDestroyVolumeDiskHeader(partition, volumeId, parentId);
247 bad_noheader:
248# ifdef AFS_DEMAND_ATTACH_FS
249 if (locktype) {
250 VUnlockVolumeById(volumeId, partition);
251 }
252# endif /* AFS_DEMAND_ATTACH_FS */
253 return NULL((void *)0);
254 }
255 IH_INIT(handle, device, vol.parentId, *(p->inode))((handle) = ih_init((device), (vol.parentId), (*(p->inode)
)))
;
256 fdP = IH_OPEN(handle)ih_open(handle);
257 if (fdP == NULL((void *)0)) {
258 Log("VCreateVolume: Problem iopen inode %s (err=%d)\n",
259 PrintInode(stmp, *(p->inode)), errno(* __error()));
260 goto bad;
261 }
262 if (FDH_PWRITE(fdP, (char *)&p->stamp, sizeof(p->stamp), 0)pwrite((fdP)->fd_fd, (char *)&p->stamp, sizeof(p->
stamp), 0)
!=
263 sizeof(p->stamp)) {
264 Log("VCreateVolume: Problem writing to inode %s (err=%d)\n",
265 PrintInode(stmp, *(p->inode)), errno(* __error()));
266 FDH_REALLYCLOSE(fdP)(fd_reallyclose(fdP), (fdP)=((void *)0), 0);
267 goto bad;
268 }
269 FDH_REALLYCLOSE(fdP)(fd_reallyclose(fdP), (fdP)=((void *)0), 0);
270 IH_RELEASE(handle)(ih_release(handle), (handle)=((void *)0), 0);
271 nearInode = *(p->inode);
272 }
273
274 IH_INIT(handle, device, vol.parentId, tempHeader.volumeInfo)((handle) = ih_init((device), (vol.parentId), (tempHeader.volumeInfo
)))
;
275 fdP = IH_OPEN(handle)ih_open(handle);
276 if (fdP == NULL((void *)0)) {
277 Log("VCreateVolume: Problem iopen inode %s (err=%d)\n",
278 PrintInode(stmp, tempHeader.volumeInfo), errno(* __error()));
279 goto bad;
280 }
281 if (FDH_PWRITE(fdP, (char *)&vol, sizeof(vol), 0)pwrite((fdP)->fd_fd, (char *)&vol, sizeof(vol), 0) != sizeof(vol)) {
282 Log("VCreateVolume: Problem writing to inode %s (err=%d)\n",
283 PrintInode(stmp, tempHeader.volumeInfo), errno(* __error()));
284 FDH_REALLYCLOSE(fdP)(fd_reallyclose(fdP), (fdP)=((void *)0), 0);
285 goto bad;
286 }
287 FDH_CLOSE(fdP)(fd_close(fdP), (fdP)=((void *)0), 0);
288 IH_RELEASE(handle)(ih_release(handle), (handle)=((void *)0), 0);
289
290 VolumeHeaderToDisk(&diskHeader, &tempHeader);
291 rc = VCreateVolumeDiskHeader(&diskHeader, partition);
292 if (rc) {
293 Log("VCreateVolume: Error %d trying to write volume header for "
294 "volume %u on partition %s; volume not created\n", rc,
295 vol.id, VPartitionPath(partition));
296 if (rc == EEXIST17) {
297 *ec = VVOLEXISTS104;
298 }
299 goto bad;
300 }
301
302# ifdef AFS_DEMAND_ATTACH_FS
303 if (locktype) {
304 VUnlockVolumeById(volumeId, partition);
305 }
306# endif /* AFS_DEMAND_ATTACH_FS */
307 return (VAttachVolumeByName_r(ec, partname, headerName, V_SECRETLY5));
308}
309#endif /* FSSYNC_BUILD_CLIENT */
310
311
312void
313AssignVolumeName(VolumeDiskData * vol, char *name, char *ext)
314{
315 VOL_LOCK;
316 AssignVolumeName_r(vol, name, ext);
317 VOL_UNLOCK;
318}
319
320void
321AssignVolumeName_r(VolumeDiskData * vol, char *name, char *ext)
322{
323 char *dot;
324 strncpy(vol->name, name, VNAMESIZE32 - 1);
325 vol->name[VNAMESIZE32 - 1] = '\0';
326 dot = strrchr(vol->name, '.');
327 if (dot && (strcmp(dot, ".backup") == 0 || strcmp(dot, ".readonly") == 0))
328 *dot = 0;
329 if (ext)
330 strncat(vol->name, ext, VNAMESIZE32 - 1 - strlen(vol->name));
331}
332
333afs_int32
334CopyVolumeHeader_r(VolumeDiskData * from, VolumeDiskData * to)
335{
336 /* The id and parentId fields are not copied; these are inviolate--the to volume
337 * is assumed to have already been created. The id's cannot be changed once
338 * creation has taken place, since they are embedded in the various inodes associated
339 * with the volume. The copydate is also inviolate--it always reflects the time
340 * this volume was created (compare with the creation date--the creation date of
341 * a backup volume is the creation date of the original parent, because the backup
342 * is used to backup the parent volume). */
343 Dateafs_uint32 copydate;
344 VolumeId id, parent;
345 id = to->id;
346 parent = to->parentId;
347 copydate = to->copyDate;
348 memcpy(to, from, sizeof(*from));
349 to->id = id;
350 to->parentId = parent;
351 to->copyDate = copydate;
352 to->destroyMe = DESTROY_ME0xD3; /* Caller must always clear this!!! */
353 to->stamp.magic = VOLUMEINFOMAGIC((bit32)0x78a1b2c5);
354 to->stamp.version = VOLUMEINFOVERSION1;
355 return 0;
356}
357
358afs_int32
359CopyVolumeHeader(VolumeDiskData * from, VolumeDiskData * to)
360{
361 afs_int32 code;
362
363 VOL_LOCK;
364 code = CopyVolumeHeader_r(from, to);
365 VOL_UNLOCK;
366 return (code);
367}
368
369void
370ClearVolumeStats(VolumeDiskData * vol)
371{
372 VOL_LOCK;
373 ClearVolumeStats_r(vol);
374 VOL_UNLOCK;
375}
376
377void
378ClearVolumeStats_r(VolumeDiskData * vol)
379{
380 memset(vol->weekUse, 0, sizeof(vol->weekUse));
381 vol->dayUse = 0;
382 vol->dayUseDate = 0;
383}
384
385/**
386 * read an existing volume disk header.
387 *
388 * @param[in] volid volume id
389 * @param[in] dp disk partition object
390 * @param[out] hdr volume disk header or NULL
391 *
392 * @note if hdr is NULL, this is essentially an existence test for the vol
393 * header
394 *
395 * @return operation status
396 * @retval 0 success
397 * @retval -1 volume header doesn't exist
398 * @retval EIO failed to read volume header
399 *
400 * @internal
401 */
402afs_int32
403VReadVolumeDiskHeader(VolumeId volid,
404 struct DiskPartition64 * dp,
405 VolumeDiskHeader_t * hdr)
406{
407 afs_int32 code = 0;
408 int fd;
409 char path[MAXPATHLEN1024];
410
411 snprintf(path, sizeof(path), "%s" OS_DIRSEP"/" VFORMAT"V%010lu.vol",
412 VPartitionPath(dp), afs_printable_uint32_lu(volid));
413 fd = open(path, O_RDONLY0x0000);
414 if (fd < 0) {
415 Log("VReadVolumeDiskHeader: Couldn't open header for volume %lu (errno %d).\n",
416 afs_printable_uint32_lu(volid), errno(* __error()));
417 code = -1;
418
419 } else if (hdr && read(fd, hdr, sizeof(*hdr)) != sizeof(*hdr)) {
420 Log("VReadVolumeDiskHeader: Couldn't read header for volume %lu.\n",
421 afs_printable_uint32_lu(volid));
422 code = EIO5;
423 }
424
425 if (fd >= 0) {
426 close(fd);
427 }
428 return code;
429}
430
431#ifdef FSSYNC_BUILD_CLIENT1
432/**
433 * write an existing volume disk header.
434 *
435 * @param[in] hdr volume disk header
436 * @param[in] dp disk partition object
437 * @param[in] cr assert if O_CREAT | O_EXCL should be passed to open()
438 *
439 * @return operation status
440 * @retval 0 success
441 * @retval -1 volume header doesn't exist
442 * @retval EIO failed to write volume header
443 *
444 * @internal
445 */
446static afs_int32
447_VWriteVolumeDiskHeader(VolumeDiskHeader_t * hdr,
448 struct DiskPartition64 * dp,
449 int flags)
450{
451 afs_int32 code = 0;
452 int fd;
453 char path[MAXPATHLEN1024];
454
455#ifdef AFS_DEMAND_ATTACH_FS
456 /* prevent racing with VGC scanners reading the vol header while we are
457 * writing it */
458 code = VPartHeaderLock(dp, READ_LOCK1);
459 if (code) {
460 return EIO5;
461 }
462#endif /* AFS_DEMAND_ATTACH_FS */
463
464 flags |= O_RDWR0x0002;
465
466 snprintf(path, sizeof(path), "%s" OS_DIRSEP"/" VFORMAT"V%010lu.vol",
467 VPartitionPath(dp), afs_printable_uint32_lu(hdr->id));
468 fd = open(path, flags, 0644);
469 if (fd < 0) {
470 code = errno(* __error());
471 Log("_VWriteVolumeDiskHeader: Couldn't open header for volume %lu, "
472 "error = %d\n", afs_printable_uint32_lu(hdr->id), errno(* __error()));
473 } else if (write(fd, hdr, sizeof(*hdr)) != sizeof(*hdr)) {
474 Log("_VWriteVolumeDiskHeader: Couldn't write header for volume %lu, "
475 "error = %d\n", afs_printable_uint32_lu(hdr->id), errno(* __error()));
476 code = EIO5;
477 }
478
479 if (fd >= 0) {
480 if (close(fd) != 0) {
481 Log("_VWriteVolumeDiskHeader: Error closing header for volume "
482 "%lu, errno %d\n", afs_printable_uint32_lu(hdr->id), errno(* __error()));
483 }
484 }
485
486#ifdef AFS_DEMAND_ATTACH_FS
487 VPartHeaderUnlock(dp, READ_LOCK1);
488#endif /* AFS_DEMAND_ATTACH_FS */
489
490 return code;
491}
492
493/**
494 * write an existing volume disk header.
495 *
496 * @param[in] hdr volume disk header
497 * @param[in] dp disk partition object
498 *
499 * @return operation status
500 * @retval 0 success
501 * @retval ENOENT volume header doesn't exist
502 * @retval EIO failed to write volume header
503 */
504afs_int32
505VWriteVolumeDiskHeader(VolumeDiskHeader_t * hdr,
506 struct DiskPartition64 * dp)
507{
508 afs_int32 code;
509
510#ifdef AFS_DEMAND_ATTACH_FS
511 VolumeDiskHeader_t oldhdr;
512 int delvgc = 0, addvgc = 0;
513 SYNC_response res;
514
515 /* first, see if anything with the volume IDs have changed; if so, we
516 * need to update the VGC */
517
518 code = VReadVolumeDiskHeader(hdr->id, dp, &oldhdr);
519 if (code == 0 && (oldhdr.id != hdr->id || oldhdr.parent != hdr->parent)) {
520 /* the vol id or parent vol id changed; need to delete the VGC entry
521 * for the old vol id/parent, and add the new one */
522 delvgc = 1;
523 addvgc = 1;
524
525 } else if (code) {
526 /* couldn't get the old header info; add the new header info to the
527 * VGC in case it hasn't been added yet */
528 addvgc = 1;
529 }
530
531#endif /* AFS_DEMAND_ATTACH_FS */
532
533 code = _VWriteVolumeDiskHeader(hdr, dp, 0);
534 if (code) {
535 goto done;
536 }
537
538#ifdef AFS_DEMAND_ATTACH_FS
539 if (delvgc) {
540 memset(&res, 0, sizeof(res));
541 code = FSYNC_VGCDel(dp->name, oldhdr.parent, oldhdr.id, FSYNC_WHATEVER, &res);
542
543 /* unknown vol id is okay; it just further suggests the old header
544 * data was bogus, which is fine since we're trying to fix it */
545 if (code && res.hdr.reason != FSYNC_UNKNOWN_VOLID) {
546 Log("VWriteVolumeDiskHeader: FSYNC_VGCDel(%s, %lu, %lu) "
547 "failed with code %ld reason %ld\n", dp->name,
548 afs_printable_uint32_lu(oldhdr.parent),
549 afs_printable_uint32_lu(oldhdr.id),
550 afs_printable_int32_ld(code),
551 afs_printable_int32_ld(res.hdr.reason));
552 }
553
554 }
555 if (addvgc) {
556 memset(&res, 0, sizeof(res));
557 code = FSYNC_VGCAdd(dp->name, hdr->parent, hdr->id, FSYNC_WHATEVER, &res);
558 if (code) {
559 Log("VWriteVolumeDiskHeader: FSYNC_VGCAdd(%s, %lu, %lu) "
560 "failed with code %ld reason %ld\n", dp->name,
561 afs_printable_uint32_lu(hdr->parent),
562 afs_printable_uint32_lu(hdr->id),
563 afs_printable_int32_ld(code),
564 afs_printable_int32_ld(res.hdr.reason));
565 }
566 }
567
568#endif /* AFS_DEMAND_ATTACH_FS */
569
570 done:
571 return code;
572}
573
574/**
575 * create and write a volume disk header to disk.
576 *
577 * @param[in] hdr volume disk header
578 * @param[in] dp disk partition object
579 *
580 * @return operation status
581 * @retval 0 success
582 * @retval EEXIST volume header already exists
583 * @retval EIO failed to write volume header
584 *
585 * @internal
586 */
587afs_int32
588VCreateVolumeDiskHeader(VolumeDiskHeader_t * hdr,
589 struct DiskPartition64 * dp)
590{
591 afs_int32 code = 0;
592#ifdef AFS_DEMAND_ATTACH_FS
593 SYNC_response res;
594#endif /* AFS_DEMAND_ATTACH_FS */
595
596 code = _VWriteVolumeDiskHeader(hdr, dp, O_CREAT0x0200 | O_EXCL0x0800);
597 if (code) {
598 goto done;
599 }
600
601#ifdef AFS_DEMAND_ATTACH_FS
602 memset(&res, 0, sizeof(res));
603 code = FSYNC_VGCAdd(dp->name, hdr->parent, hdr->id, FSYNC_WHATEVER, &res);
604 if (code) {
605 Log("VCreateVolumeDiskHeader: FSYNC_VGCAdd(%s, %lu, %lu) failed "
606 "with code %ld reason %ld\n", dp->name,
607 afs_printable_uint32_lu(hdr->parent),
608 afs_printable_uint32_lu(hdr->id),
609 afs_printable_int32_ld(code),
610 afs_printable_int32_ld(res.hdr.reason));
611 }
612#endif /* AFS_DEMAND_ATTACH_FS */
613
614 done:
615 return code;
616}
617
618
619/**
620 * destroy a volume disk header.
621 *
622 * @param[in] dp disk partition object
623 * @param[in] volid volume id
624 * @param[in] parent parent's volume id, 0 if unknown
625 *
626 * @return operation status
627 * @retval 0 success
628 *
629 * @note if parent is 0, the parent volume ID will be looked up from the
630 * fileserver
631 *
632 * @note for non-DAFS, parent is currently ignored
633 */
634afs_int32
635VDestroyVolumeDiskHeader(struct DiskPartition64 * dp,
636 VolumeId volid,
637 VolumeId parent)
638{
639 afs_int32 code = 0;
640 char path[MAXPATHLEN1024];
641#ifdef AFS_DEMAND_ATTACH_FS
642 SYNC_response res;
643#endif /* AFS_DEMAND_ATTACH_FS */
644
645 snprintf(path, sizeof(path), "%s" OS_DIRSEP"/" VFORMAT"V%010lu.vol",
646 VPartitionPath(dp), afs_printable_uint32_lu(volid));
647 code = unlink(path);
648 if (code) {
649 Log("VDestroyVolumeDiskHeader: Couldn't unlink disk header, error = %d\n", errno(* __error()));
650 goto done;
651 }
652
653#ifdef AFS_DEMAND_ATTACH_FS
654 memset(&res, 0, sizeof(res));
655 if (!parent) {
656 FSSYNC_VGQry_response_t q_res;
657
658 code = FSYNC_VGCQuery(dp->name, volid, &q_res, &res);
659 if (code) {
660 Log("VDestroyVolumeDiskHeader: FSYNC_VGCQuery(%s, %lu) failed "
661 "with code %ld, reason %ld\n", dp->name,
662 afs_printable_uint32_lu(volid), afs_printable_int32_ld(code),
663 afs_printable_int32_ld(res.hdr.reason));
664 goto done;
665 }
666
667 parent = q_res.rw;
668
669 }
670 code = FSYNC_VGCDel(dp->name, parent, volid, FSYNC_WHATEVER, &res);
671 if (code) {
672 Log("VDestroyVolumeDiskHeader: FSYNC_VGCDel(%s, %lu, %lu) failed "
673 "with code %ld reason %ld\n", dp->name,
674 afs_printable_uint32_lu(parent),
675 afs_printable_uint32_lu(volid),
676 afs_printable_int32_ld(code),
677 afs_printable_int32_ld(res.hdr.reason));
678 }
679#endif /* AFS_DEMAND_ATTACH_FS */
680
681 done:
682 return code;
683}
684#endif /* FSSYNC_BUILD_CLIENT */
685
686/**
687 * handle a single vol header as part of VWalkVolumeHeaders.
688 *
689 * @param[in] dp disk partition
690 * @param[in] volfunc function to call when a vol header is successfully read
691 * @param[in] name full path name to the .vol header
692 * @param[out] hdr header data read in from the .vol header
693 * @param[in] locked 1 if the partition headers are locked, 0 otherwise
694 * @param[in] rock the rock to pass to volfunc
695 *
696 * @return operation status
697 * @retval 0 success
698 * @retval -1 fatal error, stop scanning
699 * @retval 1 failed to read header
700 * @retval 2 volfunc callback indicated error after header read
701 */
702static int
703_VHandleVolumeHeader(struct DiskPartition64 *dp, VWalkVolFunc volfunc,
704 const char *name, struct VolumeDiskHeader *hdr,
705 int locked, void *rock)
706{
707 int error = 0;
708 FD_t fd;
709
710 if ((fd = OS_OPEN(name, O_RDONLY, 0)open(name, 0x0000, 0)) == INVALID_FD((FD_t)-1)
711 || OS_READ(fd, hdr, sizeof(*hdr))read(fd, hdr, sizeof(*hdr))
712 != sizeof(*hdr)
713 || hdr->stamp.magic != VOLUMEHEADERMAGIC((bit32)0x88a1bb3c)) {
714 error = 1;
715 }
716
717 if (fd != INVALID_FD((FD_t)-1)) {
718 OS_CLOSE(fd)close(fd);
719 }
720
721#ifdef AFSFS_DEMAND_ATTACH_FS
722 if (locked) {
723 VPartHeaderUnlock(dp);
724 }
725#endif /* AFS_DEMAND_ATTACH_FS */
726
727 if (!error && volfunc) {
728 /* the volume header seems fine; call the caller-supplied
729 * 'we-found-a-volume-header' function */
730 int last = 1;
731
732#ifdef AFS_DEMAND_ATTACH_FS
733 if (!locked) {
734 last = 0;
735 }
736#endif /* AFS_DEMAND_ATTACH_FS */
737
738 error = (*volfunc) (dp, name, hdr, last, rock);
739 if (error < 0) {
740 return -1;
741 }
742 if (error) {
743 error = 2;
744 }
745 }
746
747#ifdef AFS_DEMAND_ATTACH_FS
748 if (error && !locked) {
749 int code;
750 /* retry reading the volume header under the partition
751 * header lock, just to be safe and ensure we're not
752 * racing something rewriting the vol header */
753 code = VPartHeaderLock(dp, WRITE_LOCK2);
754 if (code) {
755 Log("Error acquiring partition write lock when "
756 "looking at header %s\n", name);
757 return -1;
758 }
759
760 return _VHandleVolumeHeader(dp, volfunc, name, hdr, 1, rock);
761 }
762#endif /* AFS_DEMAND_ATTACH_FS */
763
764 return error;
765}
766
767/**
768 * walk through the list of volume headers on a partition.
769 *
770 * This function looks through all of the .vol headers on a partition, reads in
771 * each header, and calls the supplied volfunc function on each one. If the
772 * header cannot be read (or volfunc returns a positive error code), DAFS will
773 * VPartHeaderExLock() and retry. If that fails, or if we are non-DAFS, errfunc
774 * will be called (which typically will unlink the problem volume header).
775 *
776 * If volfunc returns a negative error code, walking the partition will stop
777 * and we will return an error immediately.
778 *
779 * @param[in] dp partition to walk
780 * @param[in] partpath the path opendir()
781 * @param[in] volfunc the function to call when a header is encountered, or
782 * NULL to just skip over valid headers
783 * @param[in] errfunc the function to call when a problematic header is
784 * encountered, or NULL to just skip over bad headers
785 * @param[in] rock rock for volfunc and errfunc
786 *
787 * @see VWalkVolFunc
788 * @see VWalkErrFunc
789 *
790 * @return operation status
791 * @retval 0 success
792 * @retval negative fatal error, walk did not finish
793 */
794int
795VWalkVolumeHeaders(struct DiskPartition64 *dp, const char *partpath,
796 VWalkVolFunc volfunc, VWalkErrFunc errfunc, void *rock)
797{
798 DIR *dirp = NULL((void *)0);
799 struct dirent *dentry = NULL((void *)0);
800 int code = 0;
801 struct VolumeDiskHeader diskHeader;
802
803 dirp = opendir(partpath);
804 if (!dirp) {
805 Log("VWalkVolumeHeaders: cannot open directory %s\n", partpath);
806 code = -1;
807 goto done;
808 }
809
810 while ((dentry = readdir(dirp))) {
811 char *p = dentry->d_name;
Value stored to 'p' during its initialization is never read
812 p = strrchr(dentry->d_name, '.');
813 if (p != NULL((void *)0) && strcmp(p, VHDREXT".vol") == 0) {
814 char name[VMAXPATHLEN64];
815
816 sprintf(name, "%s" OS_DIRSEP"/" "%s", partpath, dentry->d_name);
817
818 code = _VHandleVolumeHeader(dp, volfunc, name, &diskHeader, -1, rock);
819 if (code < 0) {
820 /* fatal error, stop walking */
821 goto done;
822 }
823 if (code && errfunc) {
824 /* error with header; call the caller-supplied vol error
825 * function */
826
827 struct VolumeDiskHeader *hdr = &diskHeader;
828 if (code == 1) {
829 /* we failed to read the header at all, so don't pass in
830 * the header ptr */
831 hdr = NULL((void *)0);
832 }
833 (*errfunc) (dp, name, hdr, rock);
834 }
835 code = 0;
836 }
837 }
838 done:
839 if (dirp) {
840 closedir(dirp);
841 dirp = NULL((void *)0);
842 }
843
844 return code;
845}
846
847/**
848 * initialize a struct VLockFile.
849 *
850 * @param[in] lf struct VLockFile to initialize
851 * @param[in] path Full path to the file to use for locks. The string contents
852 * are copied.
853 */
854void
855VLockFileInit(struct VLockFile *lf, const char *path)
856{
857 memset(lf, 0, sizeof(*lf));
858 lf->path = strdup(path);
859 lf->fd = INVALID_FD((FD_t)-1);
860 MUTEX_INIT(&lf->mutex, "vlockfile", MUTEX_DEFAULT, 0);
861}
862
863#ifdef AFS_NT40_ENV
864static_inlinestatic inline FD_t
865_VOpenPath(const char *path)
866{
867 HANDLE handle;
868
869 handle = CreateFile(path,
870 GENERIC_READ | GENERIC_WRITE,
871 FILE_SHARE_READ | FILE_SHARE_WRITE,
872 NULL((void *)0),
873 OPEN_ALWAYS,
874 FILE_ATTRIBUTE_HIDDEN,
875 NULL((void *)0));
876 if (handle == INVALID_HANDLE_VALUE) {
877 return INVALID_FD((FD_t)-1);
878 }
879
880 return handle;
881}
882
883static_inlinestatic inline int
884_VLockFd(FD_t handle, afs_uint32 offset, int locktype, int nonblock)
885{
886 DWORD flags = 0;
887 OVERLAPPED lap;
888
889 if (locktype == WRITE_LOCK2) {
890 flags |= LOCKFILE_EXCLUSIVE_LOCK;
891 }
892 if (nonblock) {
893 flags |= LOCKFILE_FAIL_IMMEDIATELY;
894 }
895
896 memset(&lap, 0, sizeof(lap));
897 lap.Offset = offset;
898
899 if (!LockFileEx(handle, flags, 0, 1, 0, &lap)) {
900 if (GetLastError() == ERROR_LOCK_VIOLATION) {
901 return EBUSY16;
902 }
903 return EIO5;
904 }
905
906 return 0;
907}
908
909static_inlinestatic inline void
910_VUnlockFd(FD_t handle, afs_uint32 offset)
911{
912 OVERLAPPED lap;
913
914 memset(&lap, 0, sizeof(lap));
915 lap.Offset = offset;
916
917 UnlockFileEx(handle, 0, 1, 0, &lap);
918}
919
920static_inlinestatic inline void
921_VCloseFd(FD_t handle)
922{
923 CloseHandle(handle);
924}
925
926#else /* !AFS_NT40_ENV */
927
928/**
929 * open a file on the local filesystem suitable for locking
930 *
931 * @param[in] path abs path of the file to open
932 *
933 * @return file descriptor
934 * @retval INVALID_FD failure opening file
935 */
936static_inlinestatic inline FD_t
937_VOpenPath(const char *path)
938{
939 int fd;
940
941 fd = open(path, O_RDWR0x0002 | O_CREAT0x0200, 0660);
942 if (fd < 0) {
943 return INVALID_FD((FD_t)-1);
944 }
945 return fd;
946}
947
948/**
949 * lock an offset in a file descriptor.
950 *
951 * @param[in] fd file descriptor to lock
952 * @param[in] offset offset in file to lock
953 * @param[in] locktype READ_LOCK or WRITE_LOCK
954 * @param[in] nonblock 1 to fail immediately, 0 to wait to acquire lock
955 *
956 * @return operation status
957 * @retval 0 success
958 * @retval EBUSY someone else is holding a conflicting lock and nonblock=1 was
959 * specified
960 * @retval EIO error acquiring file lock
961 */
962static_inlinestatic inline int
963_VLockFd(FD_t fd, afs_uint32 offset, int locktype, int nonblock)
964{
965 int l_type = F_WRLCK3;
966 int cmd = AFS_SETLKW13;
967 struct afs_st_flockflock sf;
968
969 if (locktype == READ_LOCK1) {
970 l_type = F_RDLCK1;
971 }
972 if (nonblock) {
973 cmd = AFS_SETLK12;
974 }
975
976 sf.l_start = offset;
977 sf.l_len = 1;
978 sf.l_type = l_type;
979 sf.l_whence = SEEK_SET0;
980
981 if (fcntl(fd, cmd, &sf)) {
982 if (nonblock && (errno(* __error()) == EACCES13 || errno(* __error()) == EAGAIN35)) {
983 /* We asked for a nonblocking lock, and it was already locked */
984 sf.l_pid = 0;
985 if (fcntl(fd, F_GETLK11, &sf) != 0 || sf.l_pid == 0) {
986 Log("_VLockFd: fcntl failed with error %d when trying to "
987 "query the conflicting lock for fd %d (locktype=%d, "
988 "offset=%lu)\n", errno(* __error()), fd, locktype,
989 afs_printable_uint32_lu(offset));
990 } else {
991 Log("_VLockFd: conflicting lock held on fd %d, offset %lu by "
992 "pid %ld (locktype=%d)\n", fd,
993 afs_printable_uint32_lu(offset), (long int)sf.l_pid,
994 locktype);
995 }
996 return EBUSY16;
997 }
998 Log("_VLockFd: fcntl failed with error %d when trying to lock "
999 "fd %d (locktype=%d, offset=%lu)\n", errno(* __error()), fd, locktype,
1000 afs_printable_uint32_lu(offset));
1001 return EIO5;
1002 }
1003
1004 return 0;
1005}
1006
1007/**
1008 * close a file descriptor used for file locking.
1009 *
1010 * @param[in] fd file descriptor to close
1011 */
1012static_inlinestatic inline void
1013_VCloseFd(FD_t fd)
1014{
1015 if (close(fd)) {
1016 Log("_VCloseFd: error %d closing fd %d\n",
1017 errno(* __error()), fd);
1018 }
1019}
1020
1021/**
1022 * unlock a file offset in a file descriptor.
1023 *
1024 * @param[in] fd file descriptor to unlock
1025 * @param[in] offset offset to unlock
1026 */
1027static_inlinestatic inline void
1028_VUnlockFd(FD_t fd, afs_uint32 offset)
1029{
1030 struct afs_st_flockflock sf;
1031
1032 sf.l_start = offset;
1033 sf.l_len = 1;
1034 sf.l_type = F_UNLCK2;
1035 sf.l_whence = SEEK_SET0;
1036
1037 if (fcntl(fd, AFS_SETLK12, &sf)) {
1038 Log("_VUnlockFd: fcntl failed with error %d when trying to unlock "
1039 "fd %d\n", errno(* __error()), fd);
1040 }
1041}
1042#endif /* !AFS_NT40_ENV */
1043
1044/**
1045 * reinitialize a struct VLockFile.
1046 *
1047 * Use this to close the lock file (unlocking any locks in it), and effectively
1048 * restore lf to the state it was in when it was initialized. This is the same
1049 * as unlocking all of the locks on the file, without having to remember what
1050 * all of the locks were. Do not unlock previously held locks after calling
1051 * this.
1052 *
1053 * @param[in] lf struct VLockFile to reinit
1054 *
1055 * @pre nobody is waiting for a lock on this lockfile or otherwise using
1056 * this lockfile at all
1057 */
1058void
1059VLockFileReinit(struct VLockFile *lf)
1060{
1061 MUTEX_ENTER(&lf->mutex);
1062
1063 if (lf->fd != INVALID_FD((FD_t)-1)) {
1064 _VCloseFd(lf->fd);
1065 lf->fd = INVALID_FD((FD_t)-1);
1066 }
1067
1068 lf->refcount = 0;
1069
1070 MUTEX_EXIT(&lf->mutex);
1071}
1072
1073/**
1074 * lock a file on disk for the process.
1075 *
1076 * @param[in] lf the struct VLockFile representing the file to lock
1077 * @param[in] offset the offset in the file to lock
1078 * @param[in] locktype READ_LOCK or WRITE_LOCK
1079 * @param[in] nonblock 0 to wait for conflicting locks to clear before
1080 * obtaining the lock; 1 to fail immediately if a
1081 * conflicting lock is held by someone else
1082 *
1083 * @return operation status
1084 * @retval 0 success
1085 * @retval EBUSY someone else is holding a conflicting lock and nonblock=1 was
1086 * specified
1087 * @retval EIO error acquiring file lock
1088 *
1089 * @note DAFS only
1090 *
1091 * @note do not try to lock/unlock the same offset in the same file from
1092 * different threads; use VGetDiskLock to protect threads from each other in
1093 * addition to other processes
1094 */
1095int
1096VLockFileLock(struct VLockFile *lf, afs_uint32 offset, int locktype, int nonblock)
1097{
1098 int code;
1099
1100 osi_Assert(locktype == READ_LOCK || locktype == WRITE_LOCK)(void)((locktype == 1 || locktype == 2) || (osi_AssertFailU("locktype == READ_LOCK || locktype == WRITE_LOCK"
, "vutil.c", 1100), 0))
;
1101
1102 MUTEX_ENTER(&lf->mutex);
1103
1104 if (lf->fd == INVALID_FD((FD_t)-1)) {
1105 lf->fd = _VOpenPath(lf->path);
1106 if (lf->fd == INVALID_FD((FD_t)-1)) {
1107 MUTEX_EXIT(&lf->mutex);
1108 return EIO5;
1109 }
1110 }
1111
1112 lf->refcount++;
1113
1114 MUTEX_EXIT(&lf->mutex);
1115
1116 code = _VLockFd(lf->fd, offset, locktype, nonblock);
1117
1118 if (code) {
1119 MUTEX_ENTER(&lf->mutex);
1120 if (--lf->refcount < 1) {
1121 _VCloseFd(lf->fd);
1122 lf->fd = INVALID_FD((FD_t)-1);
1123 }
1124 MUTEX_EXIT(&lf->mutex);
1125 }
1126
1127 return code;
1128}
1129
1130void
1131VLockFileUnlock(struct VLockFile *lf, afs_uint32 offset)
1132{
1133 MUTEX_ENTER(&lf->mutex);
1134
1135 osi_Assert(lf->fd != INVALID_FD)(void)((lf->fd != ((FD_t)-1)) || (osi_AssertFailU("lf->fd != INVALID_FD"
, "vutil.c", 1135), 0))
;
1136
1137 if (--lf->refcount < 1) {
1138 _VCloseFd(lf->fd);
1139 lf->fd = INVALID_FD((FD_t)-1);
1140 } else {
1141 _VUnlockFd(lf->fd, offset);
1142 }
1143
1144 MUTEX_EXIT(&lf->mutex);
1145}
1146
1147#ifdef AFS_DEMAND_ATTACH_FS
1148
1149/**
1150 * initialize a struct VDiskLock.
1151 *
1152 * @param[in] dl struct VDiskLock to initialize
1153 * @param[in] lf the struct VLockFile to associate with this disk lock
1154 */
1155void
1156VDiskLockInit(struct VDiskLock *dl, struct VLockFile *lf, afs_uint32 offset)
1157{
1158 osi_Assert(lf)(void)((lf) || (osi_AssertFailU("lf", "vutil.c", 1158), 0));
1159 memset(dl, 0, sizeof(*dl));
1160 Lock_Init(&dl->rwlock);
1161 MUTEX_INIT(&dl->mutex, "disklock", MUTEX_DEFAULT, 0);
1162 CV_INIT(&dl->cv, "disklock cv", CV_DEFAULT, 0);
1163 dl->lockfile = lf;
1164 dl->offset = offset;
1165}
1166
1167/**
1168 * acquire a lock on a file on local disk.
1169 *
1170 * @param[in] dl the VDiskLock structure corresponding to the file on disk
1171 * @param[in] locktype READ_LOCK if you want a read lock, or WRITE_LOCK if
1172 * you want a write lock
1173 * @param[in] nonblock 0 to wait for conflicting locks to clear before
1174 * obtaining the lock; 1 to fail immediately if a
1175 * conflicting lock is held by someone else
1176 *
1177 * @return operation status
1178 * @retval 0 success
1179 * @retval EBUSY someone else is holding a conflicting lock and nonblock=1 was
1180 * specified
1181 * @retval EIO error acquiring file lock
1182 *
1183 * @note DAFS only
1184 *
1185 * @note while normal fcntl-y locks on Unix systems generally only work per-
1186 * process, this interface also deals with locks between threads in the
1187 * process in addition to different processes acquiring the lock
1188 */
1189int
1190VGetDiskLock(struct VDiskLock *dl, int locktype, int nonblock)
1191{
1192 int code = 0;
1193 osi_Assert(locktype == READ_LOCK || locktype == WRITE_LOCK)(void)((locktype == 1 || locktype == 2) || (osi_AssertFailU("locktype == READ_LOCK || locktype == WRITE_LOCK"
, "vutil.c", 1193), 0))
;
1194
1195 if (nonblock) {
1196 if (locktype == READ_LOCK1) {
1197 ObtainReadLockNoBlock(&dl->rwlock, code)do { ; if (!((&dl->rwlock)->excl_locked & 2) &&
!(&dl->rwlock)->wait_states) { (&dl->rwlock
) -> readers_reading++; code = 0; } else code = -1; ; } while
(0)
;
1198 } else {
1199 ObtainWriteLockNoBlock(&dl->rwlock, code)do { ; if (!(&dl->rwlock)->excl_locked && !
(&dl->rwlock)->readers_reading) { (&dl->rwlock
) -> excl_locked = 2; code = 0; } else code = -1; ; } while
(0)
;
1200 }
1201
1202 if (code) {
1203 return EBUSY16;
1204 }
1205
1206 } else if (locktype == READ_LOCK1) {
1207 ObtainReadLock(&dl->rwlock)do { ; if (!((&dl->rwlock)->excl_locked & 2) &&
!(&dl->rwlock)->wait_states) (&dl->rwlock) ->
readers_reading++; else Afs_Lock_Obtain(&dl->rwlock, 1
); ; } while (0)
;
1208 } else {
1209 ObtainWriteLock(&dl->rwlock)do { ; if (!(&dl->rwlock)->excl_locked && !
(&dl->rwlock)->readers_reading) (&dl->rwlock
) -> excl_locked = 2; else Afs_Lock_Obtain(&dl->rwlock
, 2); ; } while (0)
;
1210 }
1211
1212 MUTEX_ENTER(&dl->mutex);
1213
1214 if ((dl->flags & VDISKLOCK_ACQUIRING)) {
1215 /* Some other thread is waiting to acquire an fs lock. If nonblock=1,
1216 * we can return immediately, since we know we'll need to wait to
1217 * acquire. Otherwise, wait for the other thread to finish acquiring
1218 * the fs lock */
1219 if (nonblock) {
1220 code = EBUSY16;
1221 } else {
1222 while ((dl->flags & VDISKLOCK_ACQUIRING)) {
1223 CV_WAIT(&dl->cv, &dl->mutex);
1224 }
1225 }
1226 }
1227
1228 if (code == 0 && !(dl->flags & VDISKLOCK_ACQUIRED)) {
1229 /* no other thread holds the lock on the actual file; so grab one */
1230
1231 /* first try, don't block on the lock to see if we can get it without
1232 * waiting */
1233 code = VLockFileLock(dl->lockfile, dl->offset, locktype, 1);
1234
1235 if (code == EBUSY16 && !nonblock) {
1236
1237 /* mark that we are waiting on the fs lock */
1238 dl->flags |= VDISKLOCK_ACQUIRING;
1239
1240 MUTEX_EXIT(&dl->mutex);
1241 code = VLockFileLock(dl->lockfile, dl->offset, locktype, nonblock);
1242 MUTEX_ENTER(&dl->mutex);
1243
1244 dl->flags &= ~VDISKLOCK_ACQUIRING;
1245
1246 if (code == 0) {
1247 dl->flags |= VDISKLOCK_ACQUIRED;
1248 }
1249
1250 CV_BROADCAST(&dl->cv);
1251 }
1252 }
1253
1254 if (code) {
1255 if (locktype == READ_LOCK1) {
1256 ReleaseReadLock(&dl->rwlock)do { ; if (!--(&dl->rwlock)->readers_reading &&
(&dl->rwlock)->wait_states) Afs_Lock_ReleaseW(&
dl->rwlock) ; ; } while (0)
;
1257 } else {
1258 ReleaseWriteLock(&dl->rwlock)do { ; (&dl->rwlock)->excl_locked &= ~2; if ((&
dl->rwlock)->wait_states) Afs_Lock_ReleaseR(&dl->
rwlock); ; } while (0)
;
1259 }
1260 } else {
1261 /* successfully got the lock, so inc the number of unlocks we need
1262 * to do before we can unlock the actual file */
1263 ++dl->lockers;
1264 }
1265
1266 MUTEX_EXIT(&dl->mutex);
1267
1268 return code;
1269}
1270
1271/**
1272 * release a lock on a file on local disk.
1273 *
1274 * @param[in] dl the struct VDiskLock to release
1275 * @param[in] locktype READ_LOCK if you are unlocking a read lock, or
1276 * WRITE_LOCK if you are unlocking a write lock
1277 *
1278 * @return operation status
1279 * @retval 0 success
1280 */
1281void
1282VReleaseDiskLock(struct VDiskLock *dl, int locktype)
1283{
1284 osi_Assert(locktype == READ_LOCK || locktype == WRITE_LOCK)(void)((locktype == 1 || locktype == 2) || (osi_AssertFailU("locktype == READ_LOCK || locktype == WRITE_LOCK"
, "vutil.c", 1284), 0))
;
1285
1286 MUTEX_ENTER(&dl->mutex);
1287 osi_Assert(dl->lockers > 0)(void)((dl->lockers > 0) || (osi_AssertFailU("dl->lockers > 0"
, "vutil.c", 1287), 0))
;
1288
1289 if (--dl->lockers < 1) {
1290 /* no threads are holding this lock anymore, so we can release the
1291 * actual disk lock */
1292 VLockFileUnlock(dl->lockfile, dl->offset);
1293 dl->flags &= ~VDISKLOCK_ACQUIRED;
1294 }
1295
1296 MUTEX_EXIT(&dl->mutex);
1297
1298 if (locktype == READ_LOCK1) {
1299 ReleaseReadLock(&dl->rwlock)do { ; if (!--(&dl->rwlock)->readers_reading &&
(&dl->rwlock)->wait_states) Afs_Lock_ReleaseW(&
dl->rwlock) ; ; } while (0)
;
1300 } else {
1301 ReleaseWriteLock(&dl->rwlock)do { ; (&dl->rwlock)->excl_locked &= ~2; if ((&
dl->rwlock)->wait_states) Afs_Lock_ReleaseR(&dl->
rwlock); ; } while (0)
;
1302 }
1303}
1304
1305#endif /* AFS_DEMAND_ATTACH_FS */