linux内核源码阅读之facebook硬盘加速flashcache之五

正常流程到flashcache_map的1623行或1625行,按顺序先看读流程:
[cpp] view plain copy print ?
  1. 1221static void
  2. 1222flashcache_read(struct cache_c *dmc, struct bio *bio)
  3. 1223{
  4. 1224 int index;
  5. 1225 int res;
  6. 1226 struct cacheblock *cacheblk;
  7. 1227 int queued;
  8. 1228
  9. 1229 DPRINTK("Got a %s for %llu %u bytes)",
  10. 1230 (bio_rw(bio) == READ ? "READ":"READA"),
  11. 1231 bio->bi_sector, bio->bi_size);
  12. 1232
  13. 1233 spin_lock_irq(&dmc->cache_spin_lock);
  14. 1234 res = flashcache_lookup(dmc, bio, &index);
  15. 1235 /*
  16. 1236 * Handle Cache Hit case first.
  17. 1237 * We need to handle 2 cases, BUSY and !BUSY. If BUSY, we enqueue the
  18. 1238 * bio for later.
  19. 1239 */
  20. 1240 if (res > 0) {
  21. 1241 cacheblk = &dmc->cache[index];
  22. 1242 if ((cacheblk->cache_state & VALID) &&
  23. 1243 (cacheblk->dbn == bio->bi_sector)) {
  24. 1244 flashcache_read_hit(dmc, bio, index);
  25. 1245 return;
  26. 1246 }
  27. 1247 }
  28. 1248 /*
  29. 1249 * In all cases except for a cache hit (and VALID), test for potential
  30. 1250 * invalidations that we need to do.
  31. 1251 */
  32. 1252 queued = flashcache_inval_blocks(dmc, bio);
  33. 1253 if (queued) {
  34. 1254 if (unlikely(queued < 0))
  35. 1255 flashcache_bio_endio(bio, -EIO);
  36. 1256 spin_unlock_irq(&dmc->cache_spin_lock);
  37. 1257 return;
  38. 1258 }
  39. 1259 if (res == -1 || flashcache_uncacheable(dmc)) {
  40. 1260 /* No room or non-cacheable */
  41. 1261 spin_unlock_irq(&dmc->cache_spin_lock);
  42. 1262 DPRINTK("Cache read: Block %llu(%lu):%s",
  43. 1263 bio->bi_sector, bio->bi_size, "CACHE MISS & NO ROOM");
  44. 1264 if (res == -1)
  45. 1265 flashcache_clean_set(dmc, hash_block(dmc, bio->bi_sector));
  46. 1266 /* Start uncached IO */
  47. 1267 flashcache_start_uncached_io(dmc, bio);
  48. 1268 return;
  49. 1269 }
  50. 1270 /*
  51. 1271 * (res == INVALID) Cache Miss
  52. 1272 * And we found cache blocks to replace
  53. 1273 * Claim the cache blocks before giving up the spinlock
  54. 1274 */
  55. 1275 if (dmc->cache[index].cache_state & VALID)
  56. 1276 dmc->replace++;
  57. 1277 else
  58. 1278 dmc->cached_blocks++;
  59. 1279 dmc->cache[index].cache_state = VALID | DISKREADINPROG;
  60. 1280 dmc->cache[index].dbn = bio->bi_sector;
  61. 1281 spin_unlock_irq(&dmc->cache_spin_lock);
  62. 1282
  63. 1283 DPRINTK("Cache read: Block %llu(%lu), index = %d:%s",
  64. 1284 bio->bi_sector, bio->bi_size, index, "CACHE MISS & REPLACE");
  65. 1285 flashcache_read_miss(dmc, bio, index);
  66. 1286}
1221static void
1222flashcache_read(struct cache_c *dmc, struct bio *bio)
1223{
1224	int index;
1225	int res;
1226	struct cacheblock *cacheblk;
1227	int queued;
1228
1229	DPRINTK("Got a %s for %llu  %u bytes)",
1230	        (bio_rw(bio) == READ ? "READ":"READA"), 
1231		bio->bi_sector, bio->bi_size);
1232
1233	spin_lock_irq(&dmc->cache_spin_lock);
1234	res = flashcache_lookup(dmc, bio, &index);
1235	/* 
1236	 * Handle Cache Hit case first.
1237	 * We need to handle 2 cases, BUSY and !BUSY. If BUSY, we enqueue the
1238	 * bio for later.
1239	 */
1240	if (res > 0) {
1241		cacheblk = &dmc->cache[index];
1242		if ((cacheblk->cache_state & VALID) && 
1243		    (cacheblk->dbn == bio->bi_sector)) {
1244			flashcache_read_hit(dmc, bio, index);
1245			return;
1246		}
1247	}
1248	/*
1249	 * In all cases except for a cache hit (and VALID), test for potential 
1250	 * invalidations that we need to do.
1251	 */
1252	queued = flashcache_inval_blocks(dmc, bio);
1253	if (queued) {
1254		if (unlikely(queued < 0))
1255			flashcache_bio_endio(bio, -EIO);
1256		spin_unlock_irq(&dmc->cache_spin_lock);
1257		return;
1258	}
1259	if (res == -1 || flashcache_uncacheable(dmc)) {
1260		/* No room or non-cacheable */
1261		spin_unlock_irq(&dmc->cache_spin_lock);
1262		DPRINTK("Cache read: Block %llu(%lu):%s",
1263			bio->bi_sector, bio->bi_size, "CACHE MISS & NO ROOM");
1264		if (res == -1)
1265			flashcache_clean_set(dmc, hash_block(dmc, bio->bi_sector));
1266		/* Start uncached IO */
1267		flashcache_start_uncached_io(dmc, bio);
1268		return;
1269	}
1270	/* 
1271	 * (res == INVALID) Cache Miss 
1272	 * And we found cache blocks to replace
1273	 * Claim the cache blocks before giving up the spinlock
1274	 */
1275	if (dmc->cache[index].cache_state & VALID)
1276		dmc->replace++;
1277	else
1278		dmc->cached_blocks++;
1279	dmc->cache[index].cache_state = VALID | DISKREADINPROG;
1280	dmc->cache[index].dbn = bio->bi_sector;
1281	spin_unlock_irq(&dmc->cache_spin_lock);
1282
1283	DPRINTK("Cache read: Block %llu(%lu), index = %d:%s",
1284		bio->bi_sector, bio->bi_size, index, "CACHE MISS & REPLACE");
1285	flashcache_read_miss(dmc, bio, index);
1286}

我非常喜欢flashcache这种小资的感觉,每个函数都比较短,大部分都没有超过100行的。不像neil大哥写的md代码的函数动则几百行,上千行,总是望啊望啊望不到边。当然不是说我不喜欢neil的代码,实际上他的代码是非常非常好的,因为md代码已经有十多年的历史了,大的框架仍然没有太大的改变,仍能保持那么优雅已经是十分难得了。最新版本的md还加了许多新功能,像bad block和replacement机制都是非常实用的。所以对于一名优秀的软件工程师来说,并不在于写了多少行代码,而是编写的软件运行在多少台机器上,为用户创造了多少价值。
第1234行是查找bio是否命中,flashcache_lookup函数我们在之前的文章里已经分析过了。第1244行是命中的情况,我们跟进看看
[cpp] view plain copy print ?
  1. 1119static void
  2. 1120flashcache_read_hit(struct cache_c *dmc, struct bio* bio, int index)
  3. 1121{
  4. 1122 struct cacheblock *cacheblk;
  5. 1123 struct pending_job *pjob;
  6. 1124
  7. 1125 cacheblk = &dmc->cache[index];
  8. 1126 if (!(cacheblk->cache_state & BLOCK_IO_INPROG) && (cacheblk->head == NULL)) {
  9. 1127 struct kcached_job *job;
  10. 1128
  11. 1129 cacheblk->cache_state |= CACHEREADINPROG;
  12. 1130 dmc->read_hits++;
  13. 1131 spin_unlock_irq(&dmc->cache_spin_lock);
  14. 1132 DPRINTK("Cache read: Block %llu(%lu), index = %d:%s",
  15. 1133 bio->bi_sector, bio->bi_size, index, "CACHE HIT");
  16. 1134 job = new_kcached_job(dmc, bio, index);
  17. 1135 if (unlikely(sysctl_flashcache_error_inject & READ_HIT_JOB_ALLOC_FAIL)) {
  18. 1136 if (job)
  19. 1137 flashcache_free_cache_job(job);
  20. 1138 job = NULL;
  21. 1139 sysctl_flashcache_error_inject &= ~READ_HIT_JOB_ALLOC_FAIL;
  22. 1140 }
  23. 1141 if (unlikely(job == NULL)) {
  24. 1142 /*
  25. 1143 * We have a read hit, and can't allocate a job.
  26. 1144 * Since we dropped the spinlock, we have to drain any
  27. 1145 * pending jobs.
  28. 1146 */
  29. 1147 DMERR("flashcache: Read (hit) failed ! Can't allocate memory for cache IO, block %lu",
  30. 1148 cacheblk->dbn);
  31. 1149 flashcache_bio_endio(bio, -EIO);
  32. 1150 spin_lock_irq(&dmc->cache_spin_lock);
  33. 1151 flashcache_free_pending_jobs(dmc, cacheblk, -EIO);
  34. 1152 cacheblk->cache_state &= ~(BLOCK_IO_INPROG);
  35. 1153 spin_unlock_irq(&dmc->cache_spin_lock);
  36. 1154 } else {
  37. 1155 job->action = READCACHE; /* Fetch data from cache */
  38. 1156 atomic_inc(&dmc->nr_jobs);
  39. 1157 dmc->ssd_reads++;
  40. 1158 dm_io_async_bvec(1, &job->cache, READ,
  41. 1159 bio->bi_io_vec + bio->bi_idx,
  42. 1160 flashcache_io_callback, job);
  43. 1161 flashcache_unplug_device(dmc->cache_dev->bdev);
  44. 1162 }
  45. 1163 } else {
  46. 1164 pjob = flashcache_alloc_pending_job(dmc);
  47. 1165 if (unlikely(sysctl_flashcache_error_inject & READ_HIT_PENDING_JOB_ALLOC_FAIL)) {
  48. 1166 if (pjob) {
  49. 1167 flashcache_free_pending_job(pjob);
  50. 1168 pjob = NULL;
  51. 1169 }
  52. 1170 sysctl_flashcache_error_inject &= ~READ_HIT_PENDING_JOB_ALLOC_FAIL;
  53. 1171 }
  54. 1172 if (pjob == NULL)
  55. 1173 flashcache_bio_endio(bio, -EIO);
  56. 1174 else
  57. 1175 flashcache_enq_pending(dmc, bio, index, READCACHE, pjob);
  58. 1176 spin_unlock_irq(&dmc->cache_spin_lock);
  59. 1177 }
  60. 1178}
1119static void
1120flashcache_read_hit(struct cache_c *dmc, struct bio* bio, int index)
1121{
1122	struct cacheblock *cacheblk;
1123	struct pending_job *pjob;
1124
1125	cacheblk = &dmc->cache[index];
1126	if (!(cacheblk->cache_state & BLOCK_IO_INPROG) && (cacheblk->head == NULL)) {
1127		struct kcached_job *job;
1128			
1129		cacheblk->cache_state |= CACHEREADINPROG;
1130		dmc->read_hits++;
1131		spin_unlock_irq(&dmc->cache_spin_lock);
1132		DPRINTK("Cache read: Block %llu(%lu), index = %d:%s",
1133			bio->bi_sector, bio->bi_size, index, "CACHE HIT");
1134		job = new_kcached_job(dmc, bio, index);
1135		if (unlikely(sysctl_flashcache_error_inject & READ_HIT_JOB_ALLOC_FAIL)) {
1136			if (job)
1137				flashcache_free_cache_job(job);
1138			job = NULL;
1139			sysctl_flashcache_error_inject &= ~READ_HIT_JOB_ALLOC_FAIL;
1140		}
1141		if (unlikely(job == NULL)) {
1142			/* 
1143			 * We have a read hit, and can't allocate a job.
1144			 * Since we dropped the spinlock, we have to drain any 
1145			 * pending jobs.
1146			 */
1147			DMERR("flashcache: Read (hit) failed ! Can't allocate memory for cache IO, block %lu", 
1148			      cacheblk->dbn);
1149			flashcache_bio_endio(bio, -EIO);
1150			spin_lock_irq(&dmc->cache_spin_lock);
1151			flashcache_free_pending_jobs(dmc, cacheblk, -EIO);
1152			cacheblk->cache_state &= ~(BLOCK_IO_INPROG);
1153			spin_unlock_irq(&dmc->cache_spin_lock);
1154		} else {
1155			job->action = READCACHE; /* Fetch data from cache */
1156			atomic_inc(&dmc->nr_jobs);
1157			dmc->ssd_reads++;
1158			dm_io_async_bvec(1, &job->cache, READ,
1159					 bio->bi_io_vec + bio->bi_idx,
1160					 flashcache_io_callback, job);
1161			flashcache_unplug_device(dmc->cache_dev->bdev);
1162		}
1163	} else {
1164		pjob = flashcache_alloc_pending_job(dmc);
1165		if (unlikely(sysctl_flashcache_error_inject & READ_HIT_PENDING_JOB_ALLOC_FAIL)) {
1166			if (pjob) {
1167				flashcache_free_pending_job(pjob);
1168				pjob = NULL;
1169			}
1170			sysctl_flashcache_error_inject &= ~READ_HIT_PENDING_JOB_ALLOC_FAIL;
1171		}
1172		if (pjob == NULL)
1173			flashcache_bio_endio(bio, -EIO);
1174		else
1175			flashcache_enq_pending(dmc, bio, index, READCACHE, pjob);
1176		spin_unlock_irq(&dmc->cache_spin_lock);
1177	}
1178}

首先获取这个cache块管理结构,第1126行判断cache块不忙的情况,进入1129行设置状态为从cache读,第1134行创建一个kcached_job,在1141行申请kcached_job失败时就对bio返回失败。申请成功到1155行将kcached_job设置为READCACHE,再调用dm_io_async_bvec下发请求,当请求回来时就会调用这里设置的回调函数flashcache_io_callback。再继续看读SSD返回是怎么处理的?我们只看该函数是对READCACHE的处理:
[cpp] view plain copy print ?
  1. 151 case READCACHE:
  2. 152 DPRINTK("flashcache_io_callback: READCACHE %d",
  3. 153 index);
  4. 154 spin_lock_irqsave(&dmc->cache_spin_lock, flags);
  5. 155 if (unlikely(sysctl_flashcache_error_inject & READCACHE_ERROR)) {
  6. 156 job->error = error = -EIO;
  7. 157 sysctl_flashcache_error_inject &= ~READCACHE_ERROR;
  8. 158 }
  9. 159 VERIFY(cacheblk->cache_state & CACHEREADINPROG);
  10. 160 spin_unlock_irqrestore(&dmc->cache_spin_lock, flags);
  11. 161 if (unlikely(error))
  12. 162 dmc->ssd_read_errors++;
  13. 163#ifdef FLASHCACHE_DO_CHECKSUMS
  14. 164 if (likely(error == 0)) {
  15. 165 if (flashcache_validate_checksum(job)) {
  16. 166 DMERR("flashcache_io_callback: Checksum mismatch at disk offset %lu",
  17. 167 job->disk.sector);
  18. 168 error = -EIO;
  19. 169 }
  20. 170 }
  21. 171#endif
  22. 172 flashcache_bio_endio(bio, error);
  23. 173 break;
151	case READCACHE:
152		DPRINTK("flashcache_io_callback: READCACHE %d",
153			index);
154		spin_lock_irqsave(&dmc->cache_spin_lock, flags);
155		if (unlikely(sysctl_flashcache_error_inject & READCACHE_ERROR)) {
156			job->error = error = -EIO;
157			sysctl_flashcache_error_inject &= ~READCACHE_ERROR;
158		}
159		VERIFY(cacheblk->cache_state & CACHEREADINPROG);
160		spin_unlock_irqrestore(&dmc->cache_spin_lock, flags);
161		if (unlikely(error))
162			dmc->ssd_read_errors++;
163#ifdef FLASHCACHE_DO_CHECKSUMS
164		if (likely(error == 0)) {
165			if (flashcache_validate_checksum(job)) {
166				DMERR("flashcache_io_callback: Checksum mismatch at disk offset %lu", 
167				      job->disk.sector);
168				error = -EIO;
169			}
170		}
171#endif
172		flashcache_bio_endio(bio, error);
173		break;		       

实际上真正有意义的就是第172行,将请求done回去了。这样我们就完成的一次读命中的处理。
读命中处理还有一种情况就是第1163行cache块忙的情况,这个时候就申请一个pending_job,挂到cache块上,等cache块上一个请求回来的时候调度。

继续回到flashcache_read,看不命中的情况。
到第1259行flashcache_uncacheable函数是管理命令相关的,加了黑名单之后会跳过cache,直接下发到磁盘。
到1264行res是flashcache_lookup返回的,为-1就表示获取不到可用的cache块,这时就调用flashcache_clean_set清除一下脏块。但获取不到cache块并不是说请求就结束了,还得下发到磁盘,1267行flashcache_start_uncached_io将请求直接下发到磁盘。
第1275行到1278行是统计信息,根据这些信息可以知道flashcache的运行状况,用于flashcache的性能优化。
接着1279行设置cache块的状态,1280行设置cache块对应磁盘上的扇区,最后调用flashcache_read_miss下发请求:
[cpp] view plain copy print ?
  1. 1180static void
  2. 1181flashcache_read_miss(struct cache_c *dmc, struct bio* bio,
  3. 1182 int index)
  4. 1183{
  5. 1184 struct kcached_job *job;
  6. 1185 struct cacheblock *cacheblk = &dmc->cache[index];
  7. 1186
  8. 1187 job = new_kcached_job(dmc, bio, index);
  9. 1188 if (unlikely(sysctl_flashcache_error_inject & READ_MISS_JOB_ALLOC_FAIL)) {
  10. 1189 if (job)
  11. 1190 flashcache_free_cache_job(job);
  12. 1191 job = NULL;
  13. 1192 sysctl_flashcache_error_inject &= ~READ_MISS_JOB_ALLOC_FAIL;
  14. 1193 }
  15. 1194 if (unlikely(job == NULL)) {
  16. 1195 /*
  17. 1196 * We have a read miss, and can't allocate a job.
  18. 1197 * Since we dropped the spinlock, we have to drain any
  19. 1198 * pending jobs.
  20. 1199 */
  21. 1200 DMERR("flashcache: Read (miss) failed ! Can't allocate memory for cache IO, block %lu",
  22. 1201 cacheblk->dbn);
  23. 1202 flashcache_bio_endio(bio, -EIO);
  24. 1203 spin_lock_irq(&dmc->cache_spin_lock);
  25. 1204 dmc->cached_blocks--;
  26. 1205 cacheblk->cache_state &= ~VALID;
  27. 1206 cacheblk->cache_state |= INVALID;
  28. 1207 flashcache_free_pending_jobs(dmc, cacheblk, -EIO);
  29. 1208 cacheblk->cache_state &= ~(BLOCK_IO_INPROG);
  30. 1209 spin_unlock_irq(&dmc->cache_spin_lock);
  31. 1210 } else {
  32. 1211 job->action = READDISK; /* Fetch data from the source device */
  33. 1212 atomic_inc(&dmc->nr_jobs);
  34. 1213 dmc->disk_reads++;
  35. 1214 dm_io_async_bvec(1, &job->disk, READ,
  36. 1215 bio->bi_io_vec + bio->bi_idx,
  37. 1216 flashcache_io_callback, job);
  38. 1217 flashcache_clean_set(dmc, index / dmc->assoc);
  39. 1218 }
  40. 1219}
1180static void
1181flashcache_read_miss(struct cache_c *dmc, struct bio* bio,
1182               int index)
1183{
1184     struct kcached_job *job;
1185     struct cacheblock *cacheblk = &dmc->cache[index];
1186
1187     job = new_kcached_job(dmc, bio, index);
1188     if (unlikely(sysctl_flashcache_error_inject & READ_MISS_JOB_ALLOC_FAIL)) {
1189          if (job)
1190               flashcache_free_cache_job(job);
1191          job = NULL;
1192          sysctl_flashcache_error_inject &= ~READ_MISS_JOB_ALLOC_FAIL;
1193     }
1194     if (unlikely(job == NULL)) {
1195          /* 
1196          * We have a read miss, and can't allocate a job.
1197          * Since we dropped the spinlock, we have to drain any 
1198          * pending jobs.
1199          */
1200          DMERR("flashcache: Read (miss) failed ! Can't allocate memory for cache IO, block %lu", 
1201                cacheblk->dbn);
1202          flashcache_bio_endio(bio, -EIO);
1203          spin_lock_irq(&dmc->cache_spin_lock);
1204          dmc->cached_blocks--;
1205          cacheblk->cache_state &= ~VALID;
1206          cacheblk->cache_state |= INVALID;
1207          flashcache_free_pending_jobs(dmc, cacheblk, -EIO);
1208          cacheblk->cache_state &= ~(BLOCK_IO_INPROG);
1209          spin_unlock_irq(&dmc->cache_spin_lock);
1210     } else {
1211          job->action = READDISK; /* Fetch data from the source device */
1212          atomic_inc(&dmc->nr_jobs);
1213          dmc->disk_reads++;
1214          dm_io_async_bvec(1, &job->disk, READ,
1215                    bio->bi_io_vec + bio->bi_idx,
1216                    flashcache_io_callback, job);
1217          flashcache_clean_set(dmc, index / dmc->assoc);
1218     }
1219}

在第1187行申请了一个kcached_job,申请成功就到1211行,设置job->action=READDISK,调用dm_io_async_bvec直接从磁盘读取数据。接着调用flashcache_clean_set检查一下水位线。再看这里读磁盘的回调函数flashcache_io_callback,按理说读完磁盘就可以直接向上层返回数据,但这里还要把数据缓存起来之后再返回。
[cpp] view plain copy print ?
  1. 113void
  2. 114flashcache_io_callback(unsigned long error, void *context)
  3. 115{
  4. 116 struct kcached_job *job = (struct kcached_job *) context;
  5. 117 struct cache_c *dmc = job->dmc;
  6. 118 struct bio *bio;
  7. 119 unsigned long flags;
  8. 120 int index = job->index;
  9. 121 struct cacheblock *cacheblk = &dmc->cache[index];
  10. 122
  11. 123 VERIFY(index != -1);
  12. 124 bio = job->bio;
  13. 125 VERIFY(bio != NULL);
  14. 126 if (error)
  15. 127 DMERR("flashcache_io_callback: io error %ld block %lu action %d",
  16. 128 error, job->disk.sector, job->action);
  17. 129 job->error = error;
  18. 130 switch (job->action) {
  19. 131 case READDISK:
  20. 132 DPRINTK("flashcache_io_callback: READDISK %d",
  21. 133 index);
  22. 134 spin_lock_irqsave(&dmc->cache_spin_lock, flags);
  23. 135 if (unlikely(sysctl_flashcache_error_inject & READDISK_ERROR)) {
  24. 136 job->error = error = -EIO;
  25. 137 sysctl_flashcache_error_inject &= ~READDISK_ERROR;
  26. 138 }
  27. 139 VERIFY(cacheblk->cache_state & DISKREADINPROG);
  28. 140 spin_unlock_irqrestore(&dmc->cache_spin_lock, flags);
  29. 141 if (likely(error == 0)) {
  30. 142 /* Kick off the write to the cache */
  31. 143 job->action = READFILL;
  32. 144 flashcache_enqueue_readfill(dmc, job);
  33. 145 return;
  34. 146 } else {
  35. 147 dmc->disk_read_errors++;
  36. 148 flashcache_bio_endio(bio, error);
  37. 149 }
  38. 150 break;
  39. 174 case READFILL:
  40. 175 DPRINTK("flashcache_io_callback: READFILL %d",
  41. 176 index);
  42. 177 spin_lock_irqsave(&dmc->cache_spin_lock, flags);
  43. 178 if (unlikely(sysctl_flashcache_error_inject & READFILL_ERROR)) {
  44. 179 job->error = error = -EIO;
  45. 180 sysctl_flashcache_error_inject &= ~READFILL_ERROR;
  46. 181 }
  47. 182 if (unlikely(error))
  48. 183 dmc->ssd_write_errors++;
  49. 184 VERIFY(cacheblk->cache_state & DISKREADINPROG);
  50. 185 spin_unlock_irqrestore(&dmc->cache_spin_lock, flags);
  51. 186 flashcache_bio_endio(bio, error);
  52. 187 break;
113void 
114flashcache_io_callback(unsigned long error, void *context)
115{
116     struct kcached_job *job = (struct kcached_job *) context;
117     struct cache_c *dmc = job->dmc;
118     struct bio *bio;
119     unsigned long flags;
120     int index = job->index;
121     struct cacheblock *cacheblk = &dmc->cache[index];
122
123     VERIFY(index != -1);          
124     bio = job->bio;
125     VERIFY(bio != NULL);
126     if (error)
127          DMERR("flashcache_io_callback: io error %ld block %lu action %d", 
128                error, job->disk.sector, job->action);
129     job->error = error;
130     switch (job->action) {
131     case READDISK:
132          DPRINTK("flashcache_io_callback: READDISK  %d",
133               index);
134          spin_lock_irqsave(&dmc->cache_spin_lock, flags);
135          if (unlikely(sysctl_flashcache_error_inject & READDISK_ERROR)) {
136               job->error = error = -EIO;
137               sysctl_flashcache_error_inject &= ~READDISK_ERROR;
138          }
139          VERIFY(cacheblk->cache_state & DISKREADINPROG);
140          spin_unlock_irqrestore(&dmc->cache_spin_lock, flags);
141          if (likely(error == 0)) {
142               /* Kick off the write to the cache */
143               job->action = READFILL;
144               flashcache_enqueue_readfill(dmc, job);
145               return;
146          } else {
147               dmc->disk_read_errors++;               
148               flashcache_bio_endio(bio, error);
149          }
150          break;
          
174     case READFILL:
175          DPRINTK("flashcache_io_callback: READFILL %d",
176               index);
177          spin_lock_irqsave(&dmc->cache_spin_lock, flags);
178          if (unlikely(sysctl_flashcache_error_inject & READFILL_ERROR)) {
179               job->error = error = -EIO;
180               sysctl_flashcache_error_inject &= ~READFILL_ERROR;
181          }
182          if (unlikely(error))
183               dmc->ssd_write_errors++;
184          VERIFY(cacheblk->cache_state & DISKREADINPROG);
185          spin_unlock_irqrestore(&dmc->cache_spin_lock, flags);
186          flashcache_bio_endio(bio, error);
187          break;

归纳一下读不命中的流程:
1)创建一个kcached_job,直接下发到磁盘
2)读磁盘返回到flashcache_io_callback,到131行下发READFILL,将读出来的数据写到缓存中
3)写缓存成功并返回到flashcache_io_callback,到174行将数据返回给上层
到这里已经将读流程简单过了一遍,下一个小节介绍写流程。

你可能感兴趣的:(linux内核源码阅读之facebook硬盘加速flashcache之五)