static void VInitPartition_r(char *path, char *devname, Device dev) { struct DiskPartition64 *dp, *op; dp = malloc(sizeof(struct DiskPartition64)); /* Add it to the end, to preserve order when we print statistics */ for (op = DiskPartitionList; op; op = op->next) { if (!op->next) break; } if (op) op->next = dp; else DiskPartitionList = dp; dp->next = 0; dp->name = strdup(path); dp->index = volutil_GetPartitionID(path); #if defined(AFS_NAMEI_ENV) && !defined(AFS_NT40_ENV) /* Create a lockfile for the partition, of the form /vicepa/Lock/vicepa */ dp->devName = malloc(2 * strlen(path) + 6); strcpy(dp->devName, path); strcat(dp->devName, OS_DIRSEP); strcat(dp->devName, "Lock"); mkdir(dp->devName, 0700); strcat(dp->devName, path); close(afs_open(dp->devName, O_RDWR | O_CREAT, 0600)); dp->device = dp->index; #else dp->devName = strdup(devname); dp->device = dev; #endif dp->lock_fd = INVALID_FD; dp->flags = 0; dp->f_files = 1; /* just a default value */ #if defined(AFS_NAMEI_ENV) && !defined(AFS_NT40_ENV) if (programType == fileServer) (void)namei_ViceREADME(VPartitionPath(dp)); #endif VSetPartitionDiskUsage_r(dp); #ifdef AFS_DEMAND_ATTACH_FS AddPartitionToTable_r(dp); queue_Init(&dp->vol_list.head); CV_INIT(&dp->vol_list.cv, "vol list", CV_DEFAULT, 0); dp->vol_list.len = 0; dp->vol_list.busy = 0; { char lockpath[MAXPATHLEN+1]; snprintf(lockpath, MAXPATHLEN, "%s/" AFS_PARTLOCK_FILE, dp->name); lockpath[MAXPATHLEN] = '\0'; VLockFileInit(&dp->headerLockFile, lockpath); snprintf(lockpath, MAXPATHLEN, "%s/" AFS_VOLUMELOCK_FILE, dp->name); lockpath[MAXPATHLEN] = '\0'; VLockFileInit(&dp->volLockFile, lockpath); } VDiskLockInit(&dp->headerLock, &dp->headerLockFile, 1); #endif /* AFS_DEMAND_ATTACH_FS */ }
static int fs_stateLoadDump(struct fs_dump_state * state) { afs_uint64 z; int fd, ret = 0; struct afs_stat status; afs_int32 now = FT_ApproxTime(); ZeroInt64(z); if ((fd = afs_open(state->fn, O_RDWR)) == -1 || (afs_fstat(fd, &status) == -1)) { ViceLog(0, ("fs_stateLoadDump: failed to load state dump file '%s'\n", state->fn)); ret = 1; goto done; } state->fd = fd; state->mode = FS_STATE_LOAD_MODE; state->file_len = status.st_size; #ifdef FS_STATE_USE_MMAP if (fs_stateMapFile(state)) { ViceLog(0, ("fs_stateLoadDump: failed to memory map state dump file '%s'\n", state->fn)); ret = 1; goto done; } #endif if (fs_stateReadHeader(state, &z, state->hdr, sizeof(struct fs_state_header))) { ViceLog(0, ("fs_stateLoadDump: failed to read header from dump file '%s'\n", state->fn)); ret = 1; goto done; } /* check the validity of the header */ if (fs_stateCheckHeader(state->hdr)) { ViceLog(1, ("fs_stateLoadDump: header failed validity checks; not restoring '%s'\n", state->fn)); ret = 1; goto done; } if ((state->hdr->timestamp + HOST_STATE_VALID_WINDOW) >= now) { state->flags.do_host_restore = 1; } else { ViceLog(0, ("fs_stateLoadDump: warning: dump is too old for host and callback restore; skipping those steps\n")); } done: return ret; }
/* * open an AFS directory file */ static int afs_dir_open(struct inode *inode, struct file *file) { _enter("{%lu}", inode->i_ino); BUILD_BUG_ON(sizeof(union afs_dir_block) != 2048); BUILD_BUG_ON(sizeof(union afs_dirent) != 32); if (test_bit(AFS_VNODE_DELETED, &AFS_FS_I(inode)->flags)) return -ENOENT; return afs_open(inode, file); }
static int fs_stateCreateDump(struct fs_dump_state * state) { int fd, ret = 0; char savedump[MAXPATHLEN]; struct afs_stat status; afs_snprintf(savedump, sizeof(savedump), "%s.old", state->fn); if (afs_stat(state->fn, &status) == 0) { renamefile(state->fn, savedump); } if (((fd = afs_open(state->fn, O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR)) == -1) || (afs_fstat(fd, &status) == -1)) { ViceLog(0, ("fs_stateCreateDump: failed to create state dump file '%s'\n", state->fn)); ret = 1; goto done; } state->fd = fd; state->mode = FS_STATE_DUMP_MODE; memset(state->hdr, 0, sizeof(struct fs_state_header)); fs_stateIncEOF(state, sizeof(struct fs_state_header)); #ifdef FS_STATE_USE_MMAP if (fs_stateSizeFile(state)) { ViceLog(0, ("fs_stateCreateDump: failed to resize state dump file '%s'\n", state->fn)); ret = 1; goto done; } if (fs_stateMapFile(state)) { ViceLog(0, ("fs_stateCreateDump: failed to memory map state dump file '%s'\n", state->fn)); ret = 1; goto done; } #endif ret = fs_stateInvalidateDump(state); done: return ret; }
void HandleVolume(struct DiskPartition64 *dp, char *name, char *filename, int fromtime) { struct VolumeHeader header; struct VolumeDiskHeader diskHeader; struct afs_stat status, stat; register int fd; Volume *vp; IHandle_t *ih; char headerName[1024]; afs_int32 n; (void)afs_snprintf(headerName, sizeof headerName, "%s/%s", VPartitionPath(dp), name); if ((fd = afs_open(headerName, O_RDONLY)) == -1 || afs_fstat(fd, &status) == -1) { fprintf(stderr, "Cannot read volume header %s\n", name); close(fd); exit(1); } n = read(fd, &diskHeader, sizeof(diskHeader)); if (n != sizeof(diskHeader) || diskHeader.stamp.magic != VOLUMEHEADERMAGIC) { fprintf(stderr, "Error reading volume header %s\n", name); exit(1); } if (diskHeader.stamp.version != VOLUMEHEADERVERSION) { fprintf(stderr, "Volume %s, version number is incorrect; volume needs salvage\n", name); exit(1); } DiskToVolumeHeader(&header, &diskHeader); close(fd); vp = AttachVolume(dp, name, &header); if (!vp) { fprintf(stderr, "Error attaching volume header %s\n", name); exit(1); } DoMyVolDump(vp, dp, filename, fromtime); }
static int openFile(char * path) { int ret = 0; struct afs_stat status; dump_fd = afs_open(path, O_RDWR); if (dump_fd == -1) { fprintf(stderr, "dump file '%s' failed to open\n", path); ret = 1; goto done; } printf("opened dump file '%s'\n", path); if (afs_fstat(dump_fd, &status) == -1) { fprintf(stderr, "failed to stat file\n"); ret = 1; goto done; } map_len = status.st_size; map = afs_mmap(NULL, map_len, PROT_READ, MAP_SHARED, dump_fd, 0); if (map == MAP_FAILED) { fprintf(stderr, "failed to mmap file\n"); ret = 1; goto done; } printf("mapped %lu bytes at %"AFS_PTR_FMT"\n", (unsigned long)map_len, map); done: if (ret) { if (map) { munmap(map, map_len); map = NULL; } if (dump_fd != -1) { close(dump_fd); dump_fd = -1; } } return ret; }
void HandleVolume(struct DiskPartition64 *dp, char *name) { struct VolumeHeader header; struct VolumeDiskHeader diskHeader; struct afs_stat status, stat; int fd; Volume *vp; IHandle_t *ih; char headerName[1024]; if (online) { printf("volinfo: -online not supported\n"); exit(1); } else { afs_int32 n; (void)afs_snprintf(headerName, sizeof headerName, "%s/%s", VPartitionPath(dp), name); if ((fd = afs_open(headerName, O_RDONLY)) == -1 || afs_fstat(fd, &status) == -1) { printf("Volinfo: Cannot read volume header %s\n", name); close(fd); exit(1); } n = read(fd, &diskHeader, sizeof(diskHeader)); if (n != sizeof(diskHeader) || diskHeader.stamp.magic != VOLUMEHEADERMAGIC) { printf("Volinfo: Error reading volume header %s\n", name); exit(1); } if (diskHeader.stamp.version != VOLUMEHEADERVERSION) { printf ("Volinfo: Volume %s, version number is incorrect; volume needs salvage\n", name); exit(1); } DiskToVolumeHeader(&header, &diskHeader); if (dheader) { FdHandle_t *fdP; afs_sfsize_t size = 0; afs_sfsize_t code; if (afs_fstat(fd, &stat) == -1) { perror("stat"); exit(1); } if (!dsizeOnly && !saveinodes) { size = stat.st_size; printf("Volume header (size = %d):\n", (int)size); printf("\tstamp\t= 0x%x\n", header.stamp.version); printf("\tVolId\t= %u\n", header.id); } IH_INIT(ih, dp->device, header.parent, header.volumeInfo); fdP = IH_OPEN(ih); if (fdP == NULL) { perror("opening volume info"); exit(1); } code = FDH_SIZE(fdP); if (code == -1) { perror("fstat"); exit(1); } FDH_REALLYCLOSE(fdP); IH_RELEASE(ih); size += code; if (!dsizeOnly && !saveinodes) { printf("\tparent\t= %u\n", header.parent); printf("\tInfo inode\t= %s (size = %d)\n", PrintInode(NULL, header.volumeInfo), (int)code); } IH_INIT(ih, dp->device, header.parent, header.smallVnodeIndex); fdP = IH_OPEN(ih); if (fdP == NULL) { perror("opening small vnode index"); exit(1); } code = FDH_SIZE(fdP); if (code == -1) { perror("fstat"); exit(1); } FDH_REALLYCLOSE(fdP); IH_RELEASE(ih); size += code; if (!dsizeOnly && !saveinodes) { printf("\tSmall inode\t= %s (size = %d)\n", PrintInode(NULL, header.smallVnodeIndex), (int)code); } IH_INIT(ih, dp->device, header.parent, header.largeVnodeIndex); fdP = IH_OPEN(ih); if (fdP == NULL) { perror("opening large vnode index"); exit(1); } code = FDH_SIZE(fdP); if (code == -1) { perror("fstat"); exit(1); } FDH_REALLYCLOSE(fdP); IH_RELEASE(ih); size += code; if (!dsizeOnly && !saveinodes) { printf("\tLarge inode\t= %s (size = %d)\n", PrintInode(NULL, header.largeVnodeIndex), (int)code); #ifndef AFS_NT40_ENV printf("Total aux volume size = %d\n\n", (int)size); #endif } #ifdef AFS_NAMEI_ENV IH_INIT(ih, dp->device, header.parent, header.linkTable); fdP = IH_OPEN(ih); if (fdP == NULL) { perror("opening link table index"); exit(1); } code = FDH_SIZE(fdP); if (code == -1) { perror("fstat"); exit(1); } FDH_REALLYCLOSE(fdP); IH_RELEASE(ih); size += code; if (!dsizeOnly && !saveinodes) { printf("\tLink inode\t= %s (size = %d)\n", PrintInode(NULL, header.linkTable), (int)code); printf("Total aux volume size = %d\n\n", (int)size); } #endif Vauxsize = size; Vauxsize_k = size / 1024; } close(fd); vp = AttachVolume(dp, name, &header); if (!vp) { printf("Volinfo: Error attaching volume header %s\n", name); return; } } PrintHeader(vp); if (DumpVnodes) { if (!dsizeOnly && !saveinodes) printf("\nLarge vnodes (directories)\n"); PrintVnodes(vp, vLarge); if (!dsizeOnly && !saveinodes) { printf("\nSmall vnodes(files, symbolic links)\n"); fflush(stdout); } if (saveinodes) printf("Saving all volume files to current directory ...\n"); PrintVnodes(vp, vSmall); } if (dsizeOnly) { totvolsize = Vauxsize_k + Vvnodesize_k; if (saveinodes) printf ("Volume-Id\t Volsize Auxsize Inodesize AVolsize SizeDiff (VolName)\n"); printf("%u\t%9d%9d%10d%10d%9d\t%24s\n", V_id(vp), Vdiskused, Vauxsize_k, Vvnodesize_k, totvolsize, totvolsize - Vdiskused, V_name(vp)); } free(vp->header); free(vp); }
void VLockPartition_r(char *name) { register struct DiskPartition64 *dp = VGetPartition_r(name, 0); char *partitionName; int retries, code; struct timeval pausing; #if defined(AFS_HPUX_ENV) int lockfRtn; struct privgrp_map privGrpList[PRIV_MAXGRPS]; unsigned int *globalMask; int globalMaskIndex; #endif /* defined(AFS_HPUX_ENV) */ #if defined(AFS_DARWIN_ENV) char lockfile[MAXPATHLEN]; #endif /* defined(AFS_DARWIN_ENV) */ #ifdef AFS_NAMEI_ENV #ifdef AFS_AIX42_ENV char LockFileName[MAXPATHLEN + 1]; sprintf((char *)&LockFileName, "%s/AFSINODE_FSLock", name); partitionName = (char *)&LockFileName; #endif #endif if (!dp) return; /* no partition, will fail later */ if (dp->lock_fd != -1) return; #if defined(AFS_SUN5_ENV) || defined(AFS_AIX41_ENV) #if !defined(AFS_AIX42_ENV) || !defined(AFS_NAMEI_ENV) partitionName = dp->devName; #endif code = O_RDWR; #elif defined(AFS_DARWIN_ENV) strlcpy((partitionName = lockfile), dp->name, sizeof(lockfile)); strlcat(lockfile, "/.lock.afs", sizeof(lockfile)); code = O_RDONLY | O_CREAT; #else partitionName = dp->name; code = O_RDONLY; #endif for (retries = 25; retries; retries--) { dp->lock_fd = afs_open(partitionName, code); if (dp->lock_fd != -1) break; if (errno == ENOENT) code |= O_CREAT; pausing.tv_sec = 0; pausing.tv_usec = 500000; select(0, NULL, NULL, NULL, &pausing); } assert(retries != 0); #if defined (AFS_HPUX_ENV) assert(getprivgrp(privGrpList) == 0); /* * In general, it will difficult and time-consuming ,if not impossible, * to try to find the privgroup to which this process belongs that has the * smallest membership, to minimise the security hole. So, we use the privgrp * to which everybody belongs. */ /* first, we have to find the global mask */ for (globalMaskIndex = 0; globalMaskIndex < PRIV_MAXGRPS; globalMaskIndex++) { if (privGrpList[globalMaskIndex].priv_groupno == PRIV_GLOBAL) { globalMask = &(privGrpList[globalMaskIndex].priv_mask[LOCKRDONLY_OFFSET]); break; } } if (((*globalMask) & privmask(PRIV_LOCKRDONLY)) == 0) { /* allow everybody to set a lock on a read-only file descriptor */ (*globalMask) |= privmask(PRIV_LOCKRDONLY); assert(setprivgrp(PRIV_GLOBAL, privGrpList[globalMaskIndex].priv_mask) == 0); lockfRtn = lockf(dp->lock_fd, F_LOCK, 0); /* remove the privilege granted to everybody to lock a read-only fd */ (*globalMask) &= ~(privmask(PRIV_LOCKRDONLY)); assert(setprivgrp(PRIV_GLOBAL, privGrpList[globalMaskIndex].priv_mask) == 0); } else { /* in this case, we should be able to do this with impunity, anyway */ lockfRtn = lockf(dp->lock_fd, F_LOCK, 0); } assert(lockfRtn != -1); #else #if defined(AFS_AIX_ENV) || defined(AFS_SUN5_ENV) assert(lockf(dp->lock_fd, F_LOCK, 0) != -1); #else assert(flock(dp->lock_fd, LOCK_EX) == 0); #endif /* defined(AFS_AIX_ENV) || defined(AFS_SUN5_ENV) */ #endif }
/** * 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; int fd; if ((fd = afs_open(name, O_RDONLY)) == -1 || read(fd, hdr, sizeof(*hdr)) != sizeof(*hdr) || hdr->stamp.magic != VOLUMEHEADERMAGIC) { error = 1; } if (fd >= 0) { 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; }