📄 hd.c
字号:
} DKS(node,ctrl,unit).errnoVal = 0; DKS(node,ctrl,unit).done = 1; }#endif /* SIM_ALPHA || IRIX6_4 */ return; case CMD_TST_UNIT_RDY: /* * XXX When does this return an error? * XXX What errors does it return? */ DKS(node,ctrl,unit).errnoVal = 0; DKS(node,ctrl,unit).done = 1; return; case CMD_MODE_SENSE: /* * Return that disk is not write protected and block size is 512 bytes * WARNING: Watch this. I omitted the last section of the * mode_sense_data data structure so that we could easily use * this structure when running on other platforms. SAH */ bzero((char *)&msd, sizeof(msd)); msd.wprot = 0; msd.bd_len = 8; msd.block_descrip[5] = 0; msd.block_descrip[6] = SectorSize >> 8; msd.block_descrip[7] = 0; /* this information needs to be DMA'ed to memory. Set up correct * transfer size and place info in buffer. */ DKS(node,ctrl,unit).isRead = 1; DKS(node,ctrl,unit).bytesTransferred = sizeof(struct mode_sense_data); DKS(node,ctrl,unit).errnoVal = 0; DKS(node,ctrl,unit).sectorNum = -1; /* signal this is sense */ bcopy((char *)&msd, DKS(node,ctrl,unit).c.dataBuffer, sizeof(struct mode_sense_data)); return; case CMD_INQUIRY: /* * XXX When does this return an error? * XXX What errors does it return? */ DKS(node,ctrl,unit).errnoVal = 0; if (DKS(node,ctrl,unit).pAddr[0]) { /* * XXX This MIGHT now work on a cross-endian * XXX simualtion */ ALL_INQ_DATA inq; DKS(node,ctrl,unit).isRead = 1; DKS(node,ctrl,unit).bytesTransferred = sizeof(inq); DKS(node,ctrl,unit).sectorNum = -1; /* signal this is sense */ bzero((char*)&inq,sizeof(inq)); inq.dtype = 0; /* ALL_DTYPE_DIRECT */ if (rmtdiskfd) { if (!strncmp(DKS_filename(node,ctrl,unit),"NOTDEF",strlen("NOTDEF"))) { inq.pqual = 3; /* ALL_PQUAL_NO_PHYS */ } else { inq.pqual = 0; /* ALL_PQUAL_CONN */ } } else { if (access(DKS_filename(node,ctrl,unit),R_OK) !=0) {#if 0 CPUWarning("simos::hd,c: CMD_INQUIRY fails for %s\n",DKS_filename(node,ctrl,unit));#endif inq.pqual = 3; /* ALL_PQUAL_NO_PHYS */ } else {#if 0 CPUWarning("simos::hd,c: CMD_INQUIRY succeeds for %s\n",DKS_filename(node,ctrl,unit));#endif inq.pqual = 0; /* ALL_PQUAL_CONN */ } } inq.dmodify = 0; inq.rmb = 0; inq.ansi = 0x2; /* ALL_SCSI2 */ inq.ecma = 0; inq.iso = 0; inq.rdf =0; inq.trmiop = 0; strcpy((char *)inq.vid,"simosVID"); strcpy((char *)inq.pid,"simosPID"); bcopy((char *)&inq, DKS(node,ctrl,unit).c.dataBuffer, sizeof(ALL_INQ_DATA)); /* * actually need to transfer data */ } else { DKS(node,ctrl,unit).done = 1; } return; default: CPUError("hd.c: scsi command not supported (0x%x)\n", DKS(node,ctrl,unit).cmd[0]); return; }error: DKS(node,ctrl,unit).errnoVal = -1; DKS(node,ctrl,unit).done = 1; DKS(node,ctrl,unit).bytesTransferred = 0;#undef UNSUPPORTED}/*************************************************************************** * * Modify map utilities * ***************************************************************************/intSimhdSetupModifyMap(int node, int ctrl, int unit){ SimhdSaveInfo *hd = &(DKS(node,ctrl,unit).hdcpt.simhdStats); char nameBuf[256]; unsigned long size; /* First time we are writing to the disk */ /* allocate bitmap of modified sectors, shadow file, etc. */ sprintf(nameBuf, "%s/.%s_XXXXXX", MemFileDir, DKS_diskname(node,ctrl,unit)); mktemp(nameBuf); if((hd->sfd = open(nameBuf, O_RDWR|O_CREAT|O_TRUNC , 0)) == -1) { Sim_Warning("Could not open shadow file %s\n", nameBuf); return -1; } unlink(nameBuf); size = (unsigned long) (hd->fileSize + (SIM_DISK_SHADOW_BLKSIZE-1)) & ~(SIM_DISK_SHADOW_BLKSIZE-1); size = size/SectorSize/(8) + 1; /* 8 extra */ sprintf(nameBuf, "SHADOWMAP%d.%d.%d", node, ctrl, unit); hd->modifyMap = (char *) ZMALLOC(hd->modifyMapSize, nameBuf); size = (unsigned long) (hd->fileSize/SIM_DISK_SHADOW_BLKSIZE + 1)*sizeof(int); sprintf(nameBuf, "shadowOffset%d.%d.%d", node, ctrl, unit); hd->shadowOffset = (int *) MALLOC(size, nameBuf); if((hd->modifyMap == NULL) || (hd->shadowOffset == NULL)) { Sim_Warning("Can't alloc. bitmap for shadow file\n"); return -1; } return 0;}/* * Given a disk number and a sector number, return a file * descriptor and an offset */intSimhdFindSector(int node, int ctrl, int unit, int64 sectorNum, int *fd, unsigned long *offset, int isRead) { SimhdSaveInfo *hd = &(DKS(node,ctrl,unit).hdcpt.simhdStats); int remote = (rmtdiskfd >= 0); ASSERT( sectorNum/8 < hd->modifyMapSize); if (!isRead) { if (hd->modifyMap == NULL) { if (SimhdSetupModifyMap(node, ctrl, unit)) { /* this is a fatal error */ ASSERT(0); exit(-1); } } /* Check if this sector has been previously modified */ if (!(hd->modifyMap[sectorNum/8] & (1 << (sectorNum % 8)))) { /* * check if the block is allocated on the shadow disk * This code explicitly assumes that the block size is 8 times * the sector size. If this is changed, we need a more complicated * computation here. */ if (!(hd->modifyMap[sectorNum/8])) { /* * Every 100 extend the file by a chunk * Reduces the number of times metadata has to be written */ if (!(hd->nextWriteOffset%100)){ int k; if ((k = lseek (hd->sfd, (hd->nextWriteOffset+100) * SIM_DISK_SHADOW_BLKSIZE, SEEK_SET)) != (hd->nextWriteOffset+100)*SIM_DISK_SHADOW_BLKSIZE) { perror("lseek"); Sim_Warning("Can't seek to offset %#x in shadow file (%d) " "for %s return %d\n", (hd->nextWriteOffset+1000)*SIM_DISK_SHADOW_BLKSIZE, hd->sfd, DKS_diskname(node,ctrl,unit), k); exit( -1); } } hd->shadowOffset[sectorNum*SectorSize/SIM_DISK_SHADOW_BLKSIZE] = (int)(hd->nextWriteOffset++);#ifdef DEBUG_HD Sim_Warning("Block %#x allocated offset %#x\n", sectorNum*SectorSize/SIM_DISK_SHADOW_BLKSIZE, hd->nextWriteOffset-1);#endif } hd->modifyMap[sectorNum/8] |= (char) (1 << (sectorNum % 8)); } } if ((hd->modifyMap == NULL) || (!(hd->modifyMap[sectorNum/8] & (1 << (sectorNum % 8))))) { *fd = hd->dfd; *offset = sectorNum*SectorSize; } else { remote = 0; *fd = hd->sfd; *offset = hd->shadowOffset[sectorNum*SectorSize/SIM_DISK_SHADOW_BLKSIZE]* SIM_DISK_SHADOW_BLKSIZE + (sectorNum % 8)*SectorSize;#ifdef DEBUG_HD Sim_Warning("%s of %#x at offset %#x\n", isRead?"Read":"Write", sectorNum, *offset);#endif } return remote;}/***************************************************************** * Given an encoded controller and unit, return the disk number. *****************************************************************/intSimhdGetDiskNum(int encoded_ctrl_unit){ int node = DECODE_NODE(encoded_ctrl_unit); int ctrl = DECODE_CTRL(encoded_ctrl_unit); int unit = DECODE_UNIT(encoded_ctrl_unit); return DKS(node,ctrl,unit).dmodel_no;}/*************************************************************************** * * Ckeckpoint support * ***************************************************************************//* XXX Note: * XXX * The former hd.c only supported one controller / node. To maintain * backward compatibility with the old checkpoints, we now use the * following encoding when writing the *.diskdev file: * * Accessed[<node>,<disk>] ... * * becomes * * Accessed[<node>,<ctrldisk>] ... * * where <ctrldisk> has the disk number in the ls 16 bits and the * controller number in the following 16 bits. */#define ENCODE_CD(_CTRL,_DISK) ((((_CTRL) & 0xffff)<<16) | ((_DISK) & 0xffff))#define DECODE_C(_CD) (((_CD)>>16) & 0xffff)#define DECODE_D(_CD) (((_CD)>>0) & 0xffff)intDiskCheckpointCB(CptDescriptor *cptd){ int node, c, u; int j; bool modified; uint diskAccessed = 0; char *fnptr; long val; if (cptd->mode == CPT_SAVE) { /* * Check ownership */ for (node = 0; node < nnode; node++) { if (!dks[node]) continue; for (c = 0; c < nctrl[node]; c++) { if (!dks[node][c]) continue; /* controller never used */ for (u = 0; u < nunit[node][c]; u++) { if (!dks[node][c][u]) continue; /* unit never used */ if( DKS(node,c,u).done != 0) CPUError("DiskCheckpointCB: disk I/O in progress, can't ckpt.\n"); diskAccessed |= DKS(node,c,u).hdcpt.accessed; /* DT: I think this check could be removed */ if (!DKS(node,c,u).isReady) { ASSERT(0); return -1; } } } } } if (cptd->mode == CPT_RESTORE) { DevFileDir = 0; } Simcpt_CptString(cptd, "DiskPath", NO_INDEX, NO_INDEX, &DevFileDir); for (node = 0; node < nnode; node++) { for (c = 0; c < nctrl[node]; c++) { for (u = 0; u < nunit[node][c]; u++) { /* Note: have to be careful to ensure backward compatibility */ int cu = ENCODE_CD(c,u); SimhdSaveInfo *hd; if (dks[node] && dks[node][c] && dks[node][c][u]) { diskAccessed = DKS(node,c,u).hdcpt.accessed; } else { diskAccessed = 0; } if (diskAccessed && (DKS(node,c,u).hdcpt.simhdStats.fileSize == 0)) { diskAccessed = 0; } Simcpt_OptionalUint(cptd, "Accessed", node, cu, 0); Simcpt_CptUint(cptd, "Accessed", node, cu, &diskAccessed); if (!diskAccessed) { /* This disk was never accessed OR * this is a compatibility case and we're restoring from * an old checkpoint. */ continue; } if (!(dks[node] && dks[node][c] && dks[node][c][u])) { ASSERT(cptd->mode == CPT_RESTORE); sim_disk_touch(node,c,u); /* alloc mem for disk data structures */ } DKS(node,c,u).hdcpt.accessed = 1; hd = &(DKS(node,c,u).hdcpt.simhdStats); if( hd->writeable ) { Sim_Warning("Cannot take checkpoint with writable %s\n", DKS_diskname(node,c,u)); return -1; } fnptr = hd->filename; Simcpt_CptString(cptd, "Filename", node, cu, &fnptr); ASSERT (strlen(hd->filename) < sizeof(hd->filename)-1); val = (long)hd->fileSize; Simcpt_CptLong(cptd, "Filesize", node, cu, &val); hd->fileSize = val; Simcpt_CptLong(cptd, "LastModified", node, cu, &(hd->modifyTime)); Simcpt_CptUint(cptd, "ChecksumDone", node, cu, &(hd->doCheckSum)); if (hd->doCheckSum) Simcpt_CptInt(cptd, "Checksum", node, cu, &(hd->checkSum)); else hd->checkSum = 0; if (cptd->mode == CPT_RESTORE) { int ret = SimhdOpenCOWDisk(node,c,u,hd); if (ret != 0) return ret; } Simcpt_CptUint(cptd, "Writeable", node, cu, &(hd->writeable)); Simcpt_CptInt(cptd, "ModifyMapSize", node,cu, &(hd->modifyMapSize)); modified = (hd->modifyMap != NULL); Simcpt_CptUint(cptd, "Modified", node, cu, &(modified)); if (modified) { char *modMap, *origModMap; if (cptd->mode == CPT_RESTORE) { long pageSize=getpagesize(); modMap = (char *) ZMALLOC(hd->modifyMapSize+pageSize, "DiskCheckpointTemp"); if(modMap == NULL) { Sim_Warning("Can't alloc. bitmap for shadow file\n"); return -1; } origModMap = modMap; modMap = (char *) (((VA)modMap +(PAGE_SIZE-1))&~(PAGE_SIZE-1)); } else { modMap = hd->modifyMap; } Simcpt_CptBlock(cptd,"ModifyMap", node, cu, modMap, hd->modifyMapSize, -1); for (j = 0; j < hd->modifyMapSize; j++) { if (modMap[j] == 0) { continue; } else { int k; for (k = 0; k < 8; k++) { if ((modMap[j] >> k) & 1) { int fd; unsigned long offset; char buf[SectorSize]; int sectorNum = j * 8 + k; if (cptd->mode == CPT_RESTORE) { Simcpt_CptBlock(cptd, "ModifiedSector", /* DT this was: c*1000+u */ c*1000000+node*1000+u, sectorNum, buf, SectorSize,-1); SimhdFindSector(node, c, u, sectorNum, &fd, &offset, 0); lseek (fd, offset, SEEK_SET); write (fd, buf, SectorSize); } else { SimhdFindSector(node, c, u, sectorNum, &fd, &offset, 1); lseek (fd, offset, SEEK_SET); read (fd, buf, SectorSize); Simcpt_CptBlock(cptd, "ModifiedSector", /* DT this was: c*1000+u */ c*1000000+node*1000+u, sectorNum, buf, SectorSize,-1); } } } } } if (cptd->mode == CPT_RESTORE) { free(origModMap); } } } } } return 0;}static long DetermineDeviceSize(int fd){ long delta = 1024 * 1024 * 1024,size = 0; char buf[1]; if ( (size = (off_t)lseek(fd, 0 ,SEEK_END)) < 0 ) { perror("Lseeking disk in simhd"); ASSERT(0); } if (size) return size; size = 0; while(delta) { lseek(fd,(off_t)size + delta - sizeof(buf),SEEK_SET); if (read(fd,buf,sizeof(buf)) > 0) { size = lseek(fd,0,SEEK_CUR); } else { delta /= 2; } } CPUWarning("SimHD: Use binsearch to determine size of disk to %lld MB \n", size / 1024 / 1024); return size;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -