/* returns 0 on success, errno on failure */ int ReallyRead(DirHandle * file, int block, char *data) { FdHandle_t *fdP; int code; errno = 0; fdP = IH_OPEN(file->dirh_handle); if (fdP == NULL) { code = errno; return code; } if (FDH_SEEK(fdP, block * AFS_PAGESIZE, SEEK_SET) < 0) { code = errno; FDH_REALLYCLOSE(fdP); return code; } code = FDH_READ(fdP, data, (afs_fsize_t) AFS_PAGESIZE); if (code != AFS_PAGESIZE) { if (code < 0) code = errno; else code = EIO; FDH_REALLYCLOSE(fdP); return code; } FDH_CLOSE(fdP); return 0; }
/* returns 0 on success, errno on failure */ int ReallyWrite(DirHandle * file, int block, char *data) { FdHandle_t *fdP; extern int VolumeChanged; int code; ssize_t nBytes; errno = 0; fdP = IH_OPEN(file->dirh_handle); if (fdP == NULL) { code = errno; return code; } if (FDH_SEEK(fdP, ((afs_foff_t)block) * AFS_PAGESIZE, SEEK_SET) < 0) { code = errno; FDH_REALLYCLOSE(fdP); return code; } nBytes = FDH_WRITE(fdP, data, (afs_fsize_t) AFS_PAGESIZE); if (nBytes != AFS_PAGESIZE) { if (nBytes < 0) code = errno; else code = EIO; FDH_REALLYCLOSE(fdP); return code; } FDH_CLOSE(fdP); VolumeChanged = 1; return 0; }
/* returns 0 on success, errno on failure */ int ReallyRead(DirHandle * file, int block, char *data) { int code; FdHandle_t *fdP; fdP = IH_OPEN(file->dirh_handle); if (fdP == NULL) { code = errno; ViceLog(0, ("ReallyRead(): open failed device %X inode %s errno %d\n", file->dirh_handle->ih_dev, PrintInode(NULL, file->dirh_handle-> ih_ino), code)); return code; } if (FDH_SEEK(fdP, block * PAGESIZE, SEEK_SET) < 0) { code = errno; ViceLog(0, ("ReallyRead(): lseek failed device %X inode %s errno %d\n", file->dirh_handle->ih_dev, PrintInode(NULL, file->dirh_handle-> ih_ino), code)); FDH_REALLYCLOSE(fdP); return code; } code = FDH_READ(fdP, data, PAGESIZE); if (code != PAGESIZE) { if (code < 0) code = errno; else code = EIO; ViceLog(0, ("ReallyRead(): read failed device %X inode %s errno %d\n", file->dirh_handle->ih_dev, PrintInode(NULL, file->dirh_handle-> ih_ino), code)); FDH_REALLYCLOSE(fdP); return code; } FDH_CLOSE(fdP); return 0; }
/* returns 0 on success, errno on failure */ int ReallyWrite(DirHandle * file, int block, char *data) { afs_int32 count; FdHandle_t *fdP; fdP = IH_OPEN(file->dirh_handle); if (fdP == NULL) { ViceLog(0, ("ReallyWrite(): open failed device %X inode %s errno %d\n", file->dirh_handle->ih_dev, PrintInode(NULL, file->dirh_handle-> ih_ino), errno)); lpErrno = errno; return 0; } if (FDH_SEEK(fdP, block * PAGESIZE, SEEK_SET) < 0) { ViceLog(0, ("ReallyWrite(): lseek failed device %X inode %s errno %d\n", file->dirh_handle->ih_dev, PrintInode(NULL, file->dirh_handle-> ih_ino), errno)); lpErrno = errno; FDH_REALLYCLOSE(fdP); return 0; } if ((count = FDH_WRITE(fdP, data, PAGESIZE)) != PAGESIZE) { ViceLog(0, ("ReallyWrite(): write failed device %X inode %s errno %d\n", file->dirh_handle->ih_dev, PrintInode(NULL, file->dirh_handle-> ih_ino), errno)); lpCount = count; lpErrno = errno; FDH_REALLYCLOSE(fdP); return 0; } FDH_CLOSE(fdP); return 0; }
static int DumpFile(int dumpfd, int vnode, FdHandle_t * handleP, struct VnodeDiskObject *v) { int code = 0, failed_seek = 0, failed_write = 0; afs_int32 pad = 0; afs_int32 offset = 0; afs_sfsize_t n, nbytes, howMany, howBig; byte *p; #ifndef AFS_NT40_ENV struct afs_stat status; #endif afs_sfsize_t size, tmpsize; #ifdef AFS_AIX_ENV #include <sys/statfs.h> struct statfs tstatfs; #endif if (verbose) fprintf(stderr, "dumping file for vnode %d\n", vnode); #ifdef AFS_NT40_ENV howBig = _filelength(handleP->fd_fd); howMany = 4096; #else afs_fstat(handleP->fd_fd, &status); howBig = status.st_size; #ifdef AFS_AIX_ENV /* Unfortunately in AIX valuable fields such as st_blksize are * gone from the stat structure. */ fstatfs(handleP->fd_fd, &tstatfs); howMany = tstatfs.f_bsize; #else howMany = status.st_blksize; #endif /* AFS_AIX_ENV */ #endif /* AFS_NT40_ENV */ size = FDH_SIZE(handleP); if (verbose) fprintf(stderr, " howBig = %u, howMany = %u, fdh size = %u\n", howBig, howMany, size); #ifdef AFS_LARGEFILE_ENV { afs_uint32 hi, lo; SplitInt64(size, hi, lo); if (hi == 0L) { code = DumpInt32(dumpfd, 'f', lo); } else { code = DumpDouble(dumpfd, 'h', hi, lo); } } #else /* !AFS_LARGEFILE_ENV */ code = DumpInt32(dumpfd, 'f', size); #endif /* !AFS_LARGEFILE_ENV */ if (code) { return VOLSERDUMPERROR; } p = (unsigned char *)malloc(howMany); if (!p) { fprintf(stderr, "out of memory!\n"); return VOLSERDUMPERROR; } /* loop through whole file, while we still have bytes left, and no errors, in chunks of howMany bytes */ for (nbytes = size; (nbytes && !failed_write); nbytes -= howMany) { if (nbytes < howMany) howMany = nbytes; /* Read the data - unless we know we can't */ n = (failed_seek ? 0 : FDH_READ(handleP, p, howMany)); /* If read any good data and we null padded previously, log the * amount that we had null padded. */ if ((n > 0) && pad) { fprintf(stderr, "Null padding file %d bytes at offset %u\n", pad, offset); pad = 0; } /* If didn't read enough data, null padd the rest of the buffer. This * can happen if, for instance, the media has some bad spots. We don't * want to quit the dump, so we start null padding. */ if (n < howMany) { if (verbose) fprintf(stderr, " read %u instead of %u bytes.\n", n, howMany); /* Record the read error */ if (n < 0) { n = 0; fprintf(stderr, "Error %d reading inode %s for vnode %d\n", errno, PrintInode(NULL, handleP->fd_ih->ih_ino), vnode); } else if (!pad) { fprintf(stderr, "Error reading inode %s for vnode %d\n", PrintInode(NULL, handleP->fd_ih->ih_ino), vnode); } /* Pad the rest of the buffer with zeros. Remember offset we started * padding. Keep total tally of padding. */ memset(p + n, 0, howMany - n); if (!pad) offset = (howBig - nbytes) + n; pad += (howMany - n); /* Now seek over the data we could not get. An error here means we * can't do the next read. */ failed_seek = FDH_SEEK(handleP, ((size - nbytes) + howMany), SEEK_SET); if (failed_seek != ((size - nbytes) + howMany)) { if (failed_seek < 0) { fprintf(stderr, "Error %d seeking in inode %s for vnode %d\n", errno, PrintInode(NULL, handleP->fd_ih->ih_ino), vnode); } else { fprintf(stderr, "Error seeking in inode %s for vnode %d\n", PrintInode(NULL, handleP->fd_ih->ih_ino), vnode); failed_seek = -1; } } else { failed_seek = 0; } } /* Now write the data out */ if (write(dumpfd, (char *)p, howMany) != howMany) failed_write = VOLSERDUMPERROR; } if (pad) { /* Any padding we hadn't reported yet */ fprintf(stderr, "Null padding file: %d bytes at offset %u\n", pad, offset); } free(p); return failed_write; }
Volume * VCreateVolume_r(Error * ec, char *partname, VolId volumeId, VolId parentId) { /* Should be the same as volumeId if there is * no parent */ VolumeDiskData vol; int i, rc; char headerName[VMAXPATHLEN], volumePath[VMAXPATHLEN]; Device device; struct DiskPartition64 *partition; struct VolumeDiskHeader diskHeader; IHandle_t *handle; FdHandle_t *fdP; Inode nearInode = 0; char *part, *name; struct stat st; # ifdef AFS_DEMAND_ATTACH_FS int locktype = 0; # endif /* AFS_DEMAND_ATTACH_FS */ *ec = 0; memset(&vol, 0, sizeof(vol)); vol.id = volumeId; vol.parentId = parentId; vol.copyDate = time(0); /* The only date which really means when this * @i(instance) of this volume was created. * Creation date does not mean this */ /* Initialize handle for error case below. */ handle = NULL; /* Verify that the parition is valid before writing to it. */ if (!(partition = VGetPartition_r(partname, 0))) { Log("VCreateVolume: partition %s is not in service.\n", partname); *ec = VNOVOL; return NULL; } #if defined(NEARINODE_HINT) nearInodeHash(volumeId, nearInode); nearInode %= partition->f_files; #endif VGetVolumePath(ec, vol.id, &part, &name); if (*ec == VNOVOL || !strcmp(partition->name, part)) { /* this case is ok */ } else { /* return EXDEV if it's a clone to an alternate partition * otherwise assume it's a move */ if (vol.parentId != vol.id) { *ec = EXDEV; return NULL; } } *ec = 0; # ifdef AFS_DEMAND_ATTACH_FS /* volume doesn't exist yet, but we must lock it to try to prevent something * else from reading it when we're e.g. half way through creating it (or * something tries to create the same volume at the same time) */ locktype = VVolLockType(V_VOLUPD, 1); rc = VLockVolumeByIdNB(volumeId, partition, locktype); if (rc) { Log("VCreateVolume: vol %lu already locked by someone else\n", afs_printable_uint32_lu(volumeId)); *ec = VNOVOL; return NULL; } # else /* AFS_DEMAND_ATTACH_FS */ VLockPartition_r(partname); # endif /* !AFS_DEMAND_ATTACH_FS */ memset(&tempHeader, 0, sizeof(tempHeader)); tempHeader.stamp.magic = VOLUMEHEADERMAGIC; tempHeader.stamp.version = VOLUMEHEADERVERSION; tempHeader.id = vol.id; tempHeader.parent = vol.parentId; vol.stamp.magic = VOLUMEINFOMAGIC; vol.stamp.version = VOLUMEINFOVERSION; vol.destroyMe = DESTROY_ME; (void)afs_snprintf(headerName, sizeof headerName, VFORMAT, afs_printable_uint32_lu(vol.id)); (void)afs_snprintf(volumePath, sizeof volumePath, "%s/%s", VPartitionPath(partition), headerName); rc = stat(volumePath, &st); if (rc == 0 || errno != ENOENT) { if (rc == 0) { Log("VCreateVolume: Header file %s already exists!\n", volumePath); *ec = VVOLEXISTS; } else { Log("VCreateVolume: Error %d trying to stat header file %s\n", errno, volumePath); *ec = VNOVOL; } goto bad_noheader; } device = partition->device; for (i = 0; i < nFILES; i++) { register struct stuff *p = &stuff[i]; if (p->obsolete) continue; #ifdef AFS_NAMEI_ENV *(p->inode) = IH_CREATE(NULL, device, VPartitionPath(partition), nearInode, (p->inodeType == VI_LINKTABLE) ? vol.parentId : vol.id, INODESPECIAL, p->inodeType, vol.parentId); if (!(VALID_INO(*(p->inode)))) { if (errno == EEXIST) { /* Increment the reference count instead. */ IHandle_t *lh; int code; #ifdef AFS_NT40_ENV *(p->inode) = nt_MakeSpecIno(VI_LINKTABLE); #else *(p->inode) = namei_MakeSpecIno(vol.parentId, VI_LINKTABLE); #endif IH_INIT(lh, device, parentId, *(p->inode)); fdP = IH_OPEN(lh); if (fdP == NULL) { IH_RELEASE(lh); goto bad; } code = IH_INC(lh, *(p->inode), parentId); FDH_REALLYCLOSE(fdP); IH_RELEASE(lh); if (code < 0) goto bad; continue; } } #else *(p->inode) = IH_CREATE(NULL, device, VPartitionPath(partition), nearInode, vol.id, INODESPECIAL, p->inodeType, vol.parentId); #endif if (!VALID_INO(*(p->inode))) { Log("VCreateVolume: Problem creating %s file associated with volume header %s\n", p->description, volumePath); bad: if (handle) IH_RELEASE(handle); RemoveInodes(device, vol.id); if (!*ec) { *ec = VNOVOL; } VDestroyVolumeDiskHeader(partition, volumeId, parentId); bad_noheader: # ifdef AFS_DEMAND_ATTACH_FS if (locktype) { VUnlockVolumeById(volumeId, partition); } # endif /* AFS_DEMAND_ATTACH_FS */ return NULL; } IH_INIT(handle, device, vol.parentId, *(p->inode)); fdP = IH_OPEN(handle); if (fdP == NULL) { Log("VCreateVolume: Problem iopen inode %s (err=%d)\n", PrintInode(NULL, *(p->inode)), errno); goto bad; } if (FDH_SEEK(fdP, 0, SEEK_SET) < 0) { Log("VCreateVolume: Problem lseek inode %s (err=%d)\n", PrintInode(NULL, *(p->inode)), errno); FDH_REALLYCLOSE(fdP); goto bad; } if (FDH_WRITE(fdP, (char *)&p->stamp, sizeof(p->stamp)) != sizeof(p->stamp)) { Log("VCreateVolume: Problem writing to inode %s (err=%d)\n", PrintInode(NULL, *(p->inode)), errno); FDH_REALLYCLOSE(fdP); goto bad; } FDH_REALLYCLOSE(fdP); IH_RELEASE(handle); nearInode = *(p->inode); } IH_INIT(handle, device, vol.parentId, tempHeader.volumeInfo); fdP = IH_OPEN(handle); if (fdP == NULL) { Log("VCreateVolume: Problem iopen inode %s (err=%d)\n", PrintInode(NULL, tempHeader.volumeInfo), errno); goto bad; } if (FDH_SEEK(fdP, 0, SEEK_SET) < 0) { Log("VCreateVolume: Problem lseek inode %s (err=%d)\n", PrintInode(NULL, tempHeader.volumeInfo), errno); FDH_REALLYCLOSE(fdP); goto bad; } if (FDH_WRITE(fdP, (char *)&vol, sizeof(vol)) != sizeof(vol)) { Log("VCreateVolume: Problem writing to inode %s (err=%d)\n", PrintInode(NULL, tempHeader.volumeInfo), errno); FDH_REALLYCLOSE(fdP); goto bad; } FDH_CLOSE(fdP); IH_RELEASE(handle); VolumeHeaderToDisk(&diskHeader, &tempHeader); rc = VCreateVolumeDiskHeader(&diskHeader, partition); if (rc) { Log("VCreateVolume: Error %d trying to write volume header for " "volume %u on partition %s; volume not created\n", rc, vol.id, VPartitionPath(partition)); if (rc == EEXIST) { *ec = VVOLEXISTS; } goto bad; } # ifdef AFS_DEMAND_ATTACH_FS if (locktype) { VUnlockVolumeById(volumeId, partition); } # endif /* AFS_DEMAND_ATTACH_FS */ return (VAttachVolumeByName_r(ec, partname, headerName, V_SECRETLY)); }
/* * Get a file descriptor handle given an Inode handle */ FdHandle_t * ih_open(IHandle_t * ihP) { FdHandle_t *fdP; FD_t fd; FD_t closeFd; if (!ihP) /* XXX should log here in the fileserver */ return NULL; IH_LOCK; /* Do we already have an open file handle for this Inode? */ for (fdP = ihP->ih_fdtail; fdP != NULL; fdP = fdP->fd_ihprev) { if (fdP->fd_status != FD_HANDLE_INUSE) { assert(fdP->fd_status == FD_HANDLE_OPEN); fdP->fd_status = FD_HANDLE_INUSE; DLL_DELETE(fdP, fdLruHead, fdLruTail, fd_next, fd_prev); ihP->ih_refcnt++; IH_UNLOCK; (void)FDH_SEEK(fdP, 0, SEEK_SET); return fdP; } } /* * Try to open the Inode, return NULL on error. */ fdInUseCount += 1; IH_UNLOCK; ih_open_retry: fd = OS_IOPEN(ihP); IH_LOCK; if (fd == INVALID_FD && (errno != EMFILE || fdLruHead == NULL) ) { fdInUseCount -= 1; IH_UNLOCK; return NULL; } /* fdCacheSize limits the size of the descriptor cache, but * we permit the number of open files to exceed fdCacheSize. * We only recycle open file descriptors when the number * of open files reaches the size of the cache */ if ((fdInUseCount > fdCacheSize || fd == INVALID_FD) && fdLruHead != NULL) { fdP = fdLruHead; assert(fdP->fd_status == FD_HANDLE_OPEN); DLL_DELETE(fdP, fdLruHead, fdLruTail, fd_next, fd_prev); DLL_DELETE(fdP, fdP->fd_ih->ih_fdhead, fdP->fd_ih->ih_fdtail, fd_ihnext, fd_ihprev); closeFd = fdP->fd_fd; if (fd == INVALID_FD) { fdCacheSize--; /* reduce in order to not run into here too often */ DLL_INSERT_TAIL(fdP, fdAvailHead, fdAvailTail, fd_next, fd_prev); fdP->fd_status = FD_HANDLE_AVAIL; fdP->fd_ih = NULL; fdP->fd_fd = INVALID_FD; IH_UNLOCK; OS_CLOSE(closeFd); goto ih_open_retry; } } else { if (fdAvailHead == NULL) { fdHandleAllocateChunk(); } fdP = fdAvailHead; assert(fdP->fd_status == FD_HANDLE_AVAIL); DLL_DELETE(fdP, fdAvailHead, fdAvailTail, fd_next, fd_prev); closeFd = INVALID_FD; } fdP->fd_status = FD_HANDLE_INUSE; fdP->fd_fd = fd; fdP->fd_ih = ihP; ihP->ih_refcnt++; /* Add this handle to the Inode's list of open descriptors */ DLL_INSERT_TAIL(fdP, ihP->ih_fdhead, ihP->ih_fdtail, fd_ihnext, fd_ihprev); if (closeFd != INVALID_FD) { IH_UNLOCK; OS_CLOSE(closeFd); IH_LOCK; fdInUseCount -= 1; } IH_UNLOCK; return fdP; }