From 1686cffde898b88dcabbf6ecaa46b81196b42bab Mon Sep 17 00:00:00 2001
From: ahenriksson <sausageboy@gmail.com>
Date: Wed, 15 Aug 2012 19:04:36 +0200
Subject: [PATCH] Handle discarded blocks in unflushed transaction
If a block had been discarded, but was still in an unflushed
transaction, old cached data would be read instead of the data on the
disk.
---
src/system/kernel/cache/block_cache.cpp | 32 ++++++++++++++++++++++++++++++++
1 fil ändrad, 32 tillägg(+)
diff --git a/src/system/kernel/cache/block_cache.cpp b/src/system/kernel/cache/block_cache.cpp
index 943e651..a66afc6 100644
a
|
b
|
retry:
|
1840 | 1840 | // The block is currently busy_reading - wait and try again later |
1841 | 1841 | wait_for_busy_reading_block(cache, block); |
1842 | 1842 | goto retry; |
| 1843 | } else if (block->discard) { |
| 1844 | // The block has been discarded, but the transaction is not yet |
| 1845 | // flushed. We remove the block from the transaction and discard |
| 1846 | // it ourselves. |
| 1847 | |
| 1848 | ASSERT(block->transaction != NULL); |
| 1849 | |
| 1850 | // Search through the singly linked transaction list, and remove the |
| 1851 | // block once we find it |
| 1852 | // TODO: This is slow, but it should be an uncommon operation anyways |
| 1853 | cached_block** previousLink = &block->transaction->first_block; |
| 1854 | cached_block* current = block->transaction->first_block; |
| 1855 | |
| 1856 | while (true) { |
| 1857 | if (current == block) { |
| 1858 | // remove the block from its transaction |
| 1859 | *previousLink = block->transaction_next; |
| 1860 | block->transaction->num_blocks--; |
| 1861 | break; |
| 1862 | } |
| 1863 | |
| 1864 | previousLink = ¤t->transaction_next; |
| 1865 | current = current->transaction_next; |
| 1866 | |
| 1867 | if (current == NULL) { |
| 1868 | panic("Discarded block was not in its transaction!"); |
| 1869 | return NULL; |
| 1870 | } |
| 1871 | } |
| 1872 | |
| 1873 | cache->DiscardBlock(block); |
| 1874 | goto retry; |
1843 | 1875 | } |
1844 | 1876 | |
1845 | 1877 | if (block->unused) { |