/** * write an existing volume disk header. * * @param[in] hdr volume disk header * @param[in] dp disk partition object * @param[in] cr assert if O_CREAT | O_EXCL should be passed to open() * * @return operation status * @retval 0 success * @retval -1 volume header doesn't exist * @retval EIO failed to write volume header * * @internal */ static afs_int32 _VWriteVolumeDiskHeader(VolumeDiskHeader_t * hdr, struct DiskPartition64 * dp, int flags) { afs_int32 code = 0; int fd; char path[MAXPATHLEN]; #ifdef AFS_DEMAND_ATTACH_FS /* prevent racing with VGC scanners reading the vol header while we are * writing it */ code = VPartHeaderLock(dp, READ_LOCK); if (code) { return EIO; } #endif /* AFS_DEMAND_ATTACH_FS */ flags |= O_RDWR; (void)afs_snprintf(path, sizeof(path), "%s/" VFORMAT, VPartitionPath(dp), afs_printable_uint32_lu(hdr->id)); fd = open(path, flags, 0644); if (fd < 0) { code = errno; Log("_VWriteVolumeDiskHeader: Couldn't open header for volume %lu, " "error = %d\n", afs_printable_uint32_lu(hdr->id), errno); } else if (write(fd, hdr, sizeof(*hdr)) != sizeof(*hdr)) { Log("_VWriteVolumeDiskHeader: Couldn't write header for volume %lu, " "error = %d\n", afs_printable_uint32_lu(hdr->id), errno); code = EIO; } if (fd >= 0) { if (close(fd) != 0) { Log("_VWriteVolumeDiskHeader: Error closing header for volume " "%lu, errno %d\n", afs_printable_uint32_lu(hdr->id), errno); } } #ifdef AFS_DEMAND_ATTACH_FS VPartHeaderUnlock(dp, READ_LOCK); #endif /* AFS_DEMAND_ATTACH_FS */ return code; }
/** * handle a single vol header as part of VWalkVolumeHeaders. * * @param[in] dp disk partition * @param[in] volfunc function to call when a vol header is successfully read * @param[in] name full path name to the .vol header * @param[out] hdr header data read in from the .vol header * @param[in] locked 1 if the partition headers are locked, 0 otherwise * @param[in] rock the rock to pass to volfunc * * @return operation status * @retval 0 success * @retval -1 fatal error, stop scanning * @retval 1 failed to read header * @retval 2 volfunc callback indicated error after header read */ static int _VHandleVolumeHeader(struct DiskPartition64 *dp, VWalkVolFunc volfunc, const char *name, struct VolumeDiskHeader *hdr, int locked, void *rock) { int error = 0; FD_t fd; if ((fd = OS_OPEN(name, O_RDONLY, 0)) == INVALID_FD || OS_READ(fd, hdr, sizeof(*hdr)) != sizeof(*hdr) || hdr->stamp.magic != VOLUMEHEADERMAGIC) { error = 1; } if (fd != INVALID_FD) { OS_CLOSE(fd); } #ifdef AFSFS_DEMAND_ATTACH_FS if (locked) { VPartHeaderUnlock(dp); } #endif /* AFS_DEMAND_ATTACH_FS */ if (!error && volfunc) { /* the volume header seems fine; call the caller-supplied * 'we-found-a-volume-header' function */ int last = 1; #ifdef AFS_DEMAND_ATTACH_FS if (!locked) { last = 0; } #endif /* AFS_DEMAND_ATTACH_FS */ error = (*volfunc) (dp, name, hdr, last, rock); if (error < 0) { return -1; } if (error) { error = 2; } } #ifdef AFS_DEMAND_ATTACH_FS if (error && !locked) { int code; /* retry reading the volume header under the partition * header lock, just to be safe and ensure we're not * racing something rewriting the vol header */ code = VPartHeaderLock(dp, WRITE_LOCK); if (code) { Log("Error acquiring partition write lock when " "looking at header %s\n", name); return -1; } return _VHandleVolumeHeader(dp, volfunc, name, hdr, 1, rock); } #endif /* AFS_DEMAND_ATTACH_FS */ return error; }