Skip to content

Commit 1f01e50

Browse files
bonziniFam Zheng
authored and
Fam Zheng
committed
qed: protect table cache with CoMutex
This makes the driver thread-safe. The CoMutex is dropped temporarily while accessing the data clusters or the backing file. Signed-off-by: Paolo Bonzini <[email protected]> Message-Id: <[email protected]> Reviewed-by: Stefan Hajnoczi <[email protected]> Reviewed-by: Fam Zheng <[email protected]> Signed-off-by: Fam Zheng <[email protected]>
1 parent 61c7887 commit 1f01e50

File tree

5 files changed

+129
-54
lines changed

5 files changed

+129
-54
lines changed

block/qed-cluster.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,8 @@ static unsigned int qed_count_contiguous_clusters(BDRVQEDState *s,
8585
*
8686
* On failure QED_CLUSTER_L2 or QED_CLUSTER_L1 is returned for missing L2 or L1
8787
* table offset, respectively. len is number of contiguous unallocated bytes.
88+
*
89+
* Called with table_lock held.
8890
*/
8991
int coroutine_fn qed_find_cluster(BDRVQEDState *s, QEDRequest *request,
9092
uint64_t pos, size_t *len,
@@ -112,7 +114,6 @@ int coroutine_fn qed_find_cluster(BDRVQEDState *s, QEDRequest *request,
112114
}
113115

114116
ret = qed_read_l2_table(s, request, l2_offset);
115-
qed_acquire(s);
116117
if (ret) {
117118
goto out;
118119
}
@@ -137,6 +138,5 @@ int coroutine_fn qed_find_cluster(BDRVQEDState *s, QEDRequest *request,
137138

138139
out:
139140
*img_offset = offset;
140-
qed_release(s);
141141
return ret;
142142
}

block/qed-l2-cache.c

+6
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,8 @@ CachedL2Table *qed_alloc_l2_cache_entry(L2TableCache *l2_cache)
101101
/**
102102
* Decrease an entry's reference count and free if necessary when the reference
103103
* count drops to zero.
104+
*
105+
* Called with table_lock held.
104106
*/
105107
void qed_unref_l2_cache_entry(CachedL2Table *entry)
106108
{
@@ -122,6 +124,8 @@ void qed_unref_l2_cache_entry(CachedL2Table *entry)
122124
*
123125
* For a cached entry, this function increases the reference count and returns
124126
* the entry.
127+
*
128+
* Called with table_lock held.
125129
*/
126130
CachedL2Table *qed_find_l2_cache_entry(L2TableCache *l2_cache, uint64_t offset)
127131
{
@@ -150,6 +154,8 @@ CachedL2Table *qed_find_l2_cache_entry(L2TableCache *l2_cache, uint64_t offset)
150154
* N.B. This function steals a reference to the l2_table from the caller so the
151155
* caller must obtain a new reference by issuing a call to
152156
* qed_find_l2_cache_entry().
157+
*
158+
* Called with table_lock held.
153159
*/
154160
void qed_commit_l2_cache_entry(L2TableCache *l2_cache, CachedL2Table *l2_table)
155161
{

block/qed-table.c

+18-6
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include "qed.h"
1919
#include "qemu/bswap.h"
2020

21+
/* Called either from qed_check or with table_lock held. */
2122
static int qed_read_table(BDRVQEDState *s, uint64_t offset, QEDTable *table)
2223
{
2324
QEMUIOVector qiov;
@@ -32,18 +33,22 @@ static int qed_read_table(BDRVQEDState *s, uint64_t offset, QEDTable *table)
3233

3334
trace_qed_read_table(s, offset, table);
3435

36+
if (qemu_in_coroutine()) {
37+
qemu_co_mutex_unlock(&s->table_lock);
38+
}
3539
ret = bdrv_preadv(s->bs->file, offset, &qiov);
40+
if (qemu_in_coroutine()) {
41+
qemu_co_mutex_lock(&s->table_lock);
42+
}
3643
if (ret < 0) {
3744
goto out;
3845
}
3946

4047
/* Byteswap offsets */
41-
qed_acquire(s);
4248
noffsets = qiov.size / sizeof(uint64_t);
4349
for (i = 0; i < noffsets; i++) {
4450
table->offsets[i] = le64_to_cpu(table->offsets[i]);
4551
}
46-
qed_release(s);
4752

4853
ret = 0;
4954
out:
@@ -61,6 +66,8 @@ static int qed_read_table(BDRVQEDState *s, uint64_t offset, QEDTable *table)
6166
* @index: Index of first element
6267
* @n: Number of elements
6368
* @flush: Whether or not to sync to disk
69+
*
70+
* Called either from qed_check or with table_lock held.
6471
*/
6572
static int qed_write_table(BDRVQEDState *s, uint64_t offset, QEDTable *table,
6673
unsigned int index, unsigned int n, bool flush)
@@ -97,16 +104,20 @@ static int qed_write_table(BDRVQEDState *s, uint64_t offset, QEDTable *table,
97104
/* Adjust for offset into table */
98105
offset += start * sizeof(uint64_t);
99106

107+
if (qemu_in_coroutine()) {
108+
qemu_co_mutex_unlock(&s->table_lock);
109+
}
100110
ret = bdrv_pwritev(s->bs->file, offset, &qiov);
111+
if (qemu_in_coroutine()) {
112+
qemu_co_mutex_lock(&s->table_lock);
113+
}
101114
trace_qed_write_table_cb(s, table, flush, ret);
102115
if (ret < 0) {
103116
goto out;
104117
}
105118

106119
if (flush) {
107-
qed_acquire(s);
108120
ret = bdrv_flush(s->bs);
109-
qed_release(s);
110121
if (ret < 0) {
111122
goto out;
112123
}
@@ -123,6 +134,7 @@ int qed_read_l1_table_sync(BDRVQEDState *s)
123134
return qed_read_table(s, s->header.l1_table_offset, s->l1_table);
124135
}
125136

137+
/* Called either from qed_check or with table_lock held. */
126138
int qed_write_l1_table(BDRVQEDState *s, unsigned int index, unsigned int n)
127139
{
128140
BLKDBG_EVENT(s->bs->file, BLKDBG_L1_UPDATE);
@@ -136,6 +148,7 @@ int qed_write_l1_table_sync(BDRVQEDState *s, unsigned int index,
136148
return qed_write_l1_table(s, index, n);
137149
}
138150

151+
/* Called either from qed_check or with table_lock held. */
139152
int qed_read_l2_table(BDRVQEDState *s, QEDRequest *request, uint64_t offset)
140153
{
141154
int ret;
@@ -154,7 +167,6 @@ int qed_read_l2_table(BDRVQEDState *s, QEDRequest *request, uint64_t offset)
154167
BLKDBG_EVENT(s->bs->file, BLKDBG_L2_LOAD);
155168
ret = qed_read_table(s, offset, request->l2_table->table);
156169

157-
qed_acquire(s);
158170
if (ret) {
159171
/* can't trust loaded L2 table anymore */
160172
qed_unref_l2_cache_entry(request->l2_table);
@@ -170,7 +182,6 @@ int qed_read_l2_table(BDRVQEDState *s, QEDRequest *request, uint64_t offset)
170182
request->l2_table = qed_find_l2_cache_entry(&s->l2_cache, offset);
171183
assert(request->l2_table != NULL);
172184
}
173-
qed_release(s);
174185

175186
return ret;
176187
}
@@ -180,6 +191,7 @@ int qed_read_l2_table_sync(BDRVQEDState *s, QEDRequest *request, uint64_t offset
180191
return qed_read_l2_table(s, request, offset);
181192
}
182193

194+
/* Called either from qed_check or with table_lock held. */
183195
int qed_write_l2_table(BDRVQEDState *s, QEDRequest *request,
184196
unsigned int index, unsigned int n, bool flush)
185197
{

0 commit comments

Comments
 (0)