📄 disk_cache.c
字号:
int DISK_cache_insert(SCSI_DISK *pdisk, int start_block, int length, int segment){ int n; int segment_size = (pdisk->cache_size * 1024) / (pdisk->cache_segments * SCSI_BLOCK_SIZE); int segment_full = pdisk->cache[segment].end_block - pdisk->cache[segment].start_block; DISK_cache_touch_segment(pdisk, segment); if (segment_full + length > segment_size) length = segment_size - segment_full; /* append to end of segment -----------------------------------------------*/ if (start_block == pdisk->cache[segment].end_block) pdisk->cache[segment].end_block += length; /* overwrite end of segment -----------------------------------------------*/ else if ((start_block >= pdisk->cache[segment].start_block) && (start_block < pdisk->cache[segment].end_block) && (start_block + length > pdisk->cache[segment].end_block)) pdisk->cache[segment].end_block = start_block + length; /* overwrite entire segment -----------------------------------------------*/ else { pdisk->cache[segment].start_block = start_block; pdisk->cache[segment].end_block = start_block + length; } pdisk->cache[segment].committed = 1; return(length);}/*===========================================================================*//* touch an entire block number range: look for segment containing *//* start_block and touch it, adjust start_block and length and repeat search *//*===========================================================================*/void DISK_cache_touch(SCSI_DISK *pdisk, int start_block, int length){ int n; for (n = 0; n < pdisk->cache_segments; n++) { if ((start_block >= pdisk->cache[n].start_block) && (start_block < pdisk->cache[n].end_block) && (start_block + length > pdisk->cache[n].end_block)) { DISK_cache_touch_segment(pdisk, n); length -= (pdisk->cache[n].end_block - start_block); start_block = pdisk->cache[n].end_block; n = -1; continue; } if ((start_block >= pdisk->cache[n].start_block) && (start_block < pdisk->cache[n].end_block) && (start_block + length <= pdisk->cache[n].end_block)) DISK_cache_touch_segment(pdisk, n); }}/*===========================================================================*//* Update LRU counters so that this segment is the youngest. *//* Set counter to the maximum value, and decrement all counters that are *//* greater than that counters old value. *//*===========================================================================*/void DISK_cache_touch_segment(SCSI_DISK *pdisk, int segment){ int n, old_age = pdisk->cache[segment].lru; for (n = 0; n < pdisk->cache_segments; n++) if (pdisk->cache[n].lru > old_age) pdisk->cache[n].lru--; pdisk->cache[segment].lru = pdisk->cache_segments - 1;}/*===========================================================================*//* Insert write data into the cache: check if number of write segments *//* exceed maximum number, otherwise get a new segment, insert data and set *//* set write flag. Repeat until all data is written or out of write segments *//*===========================================================================*/int DISK_cache_write(SCSI_DISK *pdisk, int start_block, int length){ int n, writes, current_length = 0, rc; writes = 0; for (n = 0; n < pdisk->cache_segments; n++) { if (pdisk->cache[n].write) writes++; } if (writes >= pdisk->cache_write_segments) return(0); do { n = DISK_cache_newsegment(pdisk); rc = DISK_cache_insert(pdisk, start_block, length, n); length -= rc; start_block += rc; current_length += rc; writes++; pdisk->cache[n].write = 1; pdisk->cache[n].committed = 0; } while ((writes < pdisk->cache_write_segments) && (length > 0)); return(current_length);}/*===========================================================================*//* Find first committed write segment and return start block/length and *//* segment number. *//*===========================================================================*/int DISK_cache_getwsegment(SCSI_DISK *pdisk, int *start_block, int *length){ int n; for (n = 0; n < pdisk->cache_segments; n++) if ((pdisk->cache[n].write == 1) && (pdisk->cache[n].committed == 1) && (*start_block <= pdisk->cache[n].start_block) && (*start_block + *length >= pdisk->cache[n].end_block)) { *start_block = pdisk->cache[n].start_block; *length = pdisk->cache[n].end_block - pdisk->cache[n].start_block; DISK_cache_touch_segment(pdisk, n); return(n); } return(-1);}/*===========================================================================*//* Commit a write request: find first write segment that contains *//* start_block, set the committed-flag, adjust start_block and length and *//* repeat until length is zero. In addition, invalidate all read segments *//* that overlap the write request. *//*===========================================================================*/void DISK_cache_commit_write(SCSI_DISK *pdisk, int start_block, int length){ int s; for (s = 0; s < pdisk->cache_segments; s++) { if (pdisk->cache[s].write) continue; if ((start_block <= pdisk->cache[s].start_block) && (start_block + length > pdisk->cache[s].start_block) && (start_block + length < pdisk->cache[s].end_block)) { pdisk->cache[s].start_block = start_block + length; continue; } if ((start_block > pdisk->cache[s].start_block) && (start_block + length <= pdisk->cache[s].end_block)) { pdisk->cache[s].start_block = 0; pdisk->cache[s].end_block = 0; pdisk->cache[s].committed = 0; pdisk->cache[s].lru = 0; continue; } if ((start_block > pdisk->cache[s].start_block) && (start_block <= pdisk->cache[s].end_block) && (start_block + length > pdisk->cache[s].start_block) && (start_block + length >= pdisk->cache[s].end_block)) { pdisk->cache[s].end_block = start_block; continue; } if ((start_block <= pdisk->cache[s].start_block) && (start_block + length >= pdisk->cache[s].end_block)) { pdisk->cache[s].start_block = 0; pdisk->cache[s].end_block = 0; pdisk->cache[s].committed = 0; pdisk->cache[s].lru = 0; continue; } } s = 0; do { if ((pdisk->cache[s].start_block == start_block) && (pdisk->cache[s].write == 1)) { pdisk->cache[s].committed = 1; start_block = pdisk->cache[s].end_block; length -= pdisk->cache[s].end_block - pdisk->cache[s].start_block; s = 0; continue; } s++; } while (s < pdisk->cache_segments);}/*===========================================================================*//* Complete a write operation by clearing the write bit. *//*===========================================================================*/void DISK_cache_complete_write(SCSI_DISK *pdisk, int segment){ pdisk->cache[segment].write = 0;}/*===========================================================================*//* Check if segment is full. *//*===========================================================================*/int DISK_cache_segment_full(SCSI_DISK *pdisk, int segment){ return(pdisk->cache[segment].end_block - pdisk->cache[segment].start_block >= (pdisk->cache_size*1024) / (pdisk->cache_segments*SCSI_BLOCK_SIZE));}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -