Skip to content

Commit 4e0f33f

Browse files
sensillebehlendorf
authored andcommitted
Illumos 6214 - zpools going south
6214 zpools going south Reviewed by: Igor Kozhukhov <ikozhukhov@gmail.com> Reviewed by: George Wilson <george.wilson@delphix.com> Reviewed by: Dan McDonald <danmcd@omniti.com> Reviewed by: Saso Kiselkov <skiselkov.ml@gmail.com> References: https://www.illumos.org/issues/6214 http://cr.illumos.org/~webrev/sensille/6214_zpools_going_south/ Porting Notes: Reintroduce b_compress to the l2arc_buf_hdr_t. In commit b9541d6 the compression flags were moved to the generic b_flags in the arc_buf_hdr_t. This is a problem because l2arc_compress_buf() may manipulate the compression flags and this can only be done safely under the hash lock which is not held. See Illumos 6214 for a detailed analysis of the race. HDR_GET_COMPRESS() macro was removed from arc_buf_info(). Ported-by: Brian Behlendorf <behlendorf1@llnl.gov> Closes #3757
1 parent 9965059 commit 4e0f33f

File tree

3 files changed

+16
-34
lines changed

3 files changed

+16
-34
lines changed

include/sys/arc.h

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -105,20 +105,6 @@ typedef enum arc_flags
105105
/* Flags specifying whether optional hdr struct fields are defined */
106106
ARC_FLAG_HAS_L1HDR = 1 << 17,
107107
ARC_FLAG_HAS_L2HDR = 1 << 18,
108-
109-
/*
110-
* The arc buffer's compression mode is stored in the top 7 bits of the
111-
* flags field, so these dummy flags are included so that MDB can
112-
* interpret the enum properly.
113-
*/
114-
ARC_FLAG_COMPRESS_0 = 1 << 24,
115-
ARC_FLAG_COMPRESS_1 = 1 << 25,
116-
ARC_FLAG_COMPRESS_2 = 1 << 26,
117-
ARC_FLAG_COMPRESS_3 = 1 << 27,
118-
ARC_FLAG_COMPRESS_4 = 1 << 28,
119-
ARC_FLAG_COMPRESS_5 = 1 << 29,
120-
ARC_FLAG_COMPRESS_6 = 1 << 30
121-
122108
} arc_flags_t;
123109

124110
struct arc_buf {

include/sys/arc_impl.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,7 @@ typedef struct l2arc_buf_hdr {
187187
/* real alloc'd buffer size depending on b_compress applied */
188188
uint32_t b_hits;
189189
int32_t b_asize;
190+
uint8_t b_compress;
190191

191192
list_node_t b_l2node;
192193
} l2arc_buf_hdr_t;

module/zfs/arc.c

Lines changed: 15 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -677,15 +677,6 @@ static arc_buf_hdr_t arc_eviction_hdr;
677677
#define HDR_HAS_L1HDR(hdr) ((hdr)->b_flags & ARC_FLAG_HAS_L1HDR)
678678
#define HDR_HAS_L2HDR(hdr) ((hdr)->b_flags & ARC_FLAG_HAS_L2HDR)
679679

680-
/* For storing compression mode in b_flags */
681-
#define HDR_COMPRESS_OFFSET 24
682-
#define HDR_COMPRESS_NBITS 7
683-
684-
#define HDR_GET_COMPRESS(hdr) ((enum zio_compress)BF32_GET(hdr->b_flags, \
685-
HDR_COMPRESS_OFFSET, HDR_COMPRESS_NBITS))
686-
#define HDR_SET_COMPRESS(hdr, cmp) BF32_SET(hdr->b_flags, \
687-
HDR_COMPRESS_OFFSET, HDR_COMPRESS_NBITS, (cmp))
688-
689680
/*
690681
* Other sizes
691682
*/
@@ -1483,7 +1474,7 @@ arc_buf_info(arc_buf_t *ab, arc_buf_info_t *abi, int state_index)
14831474
if (l2hdr) {
14841475
abi->abi_l2arc_dattr = l2hdr->b_daddr;
14851476
abi->abi_l2arc_asize = l2hdr->b_asize;
1486-
abi->abi_l2arc_compress = HDR_GET_COMPRESS(hdr);
1477+
abi->abi_l2arc_compress = l2hdr->b_compress;
14871478
abi->abi_l2arc_hits = l2hdr->b_hits;
14881479
}
14891480

@@ -1954,7 +1945,7 @@ arc_buf_l2_cdata_free(arc_buf_hdr_t *hdr)
19541945
* separately compressed buffer, so there's nothing to free (it
19551946
* points to the same buffer as the arc_buf_t's b_data field).
19561947
*/
1957-
if (HDR_GET_COMPRESS(hdr) == ZIO_COMPRESS_OFF) {
1948+
if (hdr->b_l2hdr.b_compress == ZIO_COMPRESS_OFF) {
19581949
hdr->b_l1hdr.b_tmp_cdata = NULL;
19591950
return;
19601951
}
@@ -1963,12 +1954,12 @@ arc_buf_l2_cdata_free(arc_buf_hdr_t *hdr)
19631954
* There's nothing to free since the buffer was all zero's and
19641955
* compressed to a zero length buffer.
19651956
*/
1966-
if (HDR_GET_COMPRESS(hdr) == ZIO_COMPRESS_EMPTY) {
1957+
if (hdr->b_l2hdr.b_compress == ZIO_COMPRESS_EMPTY) {
19671958
ASSERT3P(hdr->b_l1hdr.b_tmp_cdata, ==, NULL);
19681959
return;
19691960
}
19701961

1971-
ASSERT(L2ARC_IS_VALID_COMPRESS(HDR_GET_COMPRESS(hdr)));
1962+
ASSERT(L2ARC_IS_VALID_COMPRESS(hdr->b_l2hdr.b_compress));
19721963

19731964
arc_buf_free_on_write(hdr->b_l1hdr.b_tmp_cdata,
19741965
hdr->b_size, zio_data_buf_free);
@@ -4429,7 +4420,7 @@ arc_read(zio_t *pio, spa_t *spa, const blkptr_t *bp, arc_done_func_t *done,
44294420
(vd = hdr->b_l2hdr.b_dev->l2ad_vdev) != NULL) {
44304421
devw = hdr->b_l2hdr.b_dev->l2ad_writing;
44314422
addr = hdr->b_l2hdr.b_daddr;
4432-
b_compress = HDR_GET_COMPRESS(hdr);
4423+
b_compress = hdr->b_l2hdr.b_compress;
44334424
b_asize = hdr->b_l2hdr.b_asize;
44344425
/*
44354426
* Lock out device removal.
@@ -6037,6 +6028,8 @@ l2arc_read_done(zio_t *zio)
60376028
if (cb->l2rcb_compress != ZIO_COMPRESS_OFF)
60386029
l2arc_decompress_zio(zio, hdr, cb->l2rcb_compress);
60396030
ASSERT(zio->io_data != NULL);
6031+
ASSERT3U(zio->io_size, ==, hdr->b_size);
6032+
ASSERT3U(BP_GET_LSIZE(&cb->l2rcb_bp), ==, hdr->b_size);
60406033

60416034
/*
60426035
* Check this survived the L2ARC journey.
@@ -6073,7 +6066,7 @@ l2arc_read_done(zio_t *zio)
60736066
ASSERT(!pio || pio->io_child_type == ZIO_CHILD_LOGICAL);
60746067

60756068
zio_nowait(zio_read(pio, cb->l2rcb_spa, &cb->l2rcb_bp,
6076-
buf->b_data, zio->io_size, arc_read_done, buf,
6069+
buf->b_data, hdr->b_size, arc_read_done, buf,
60776070
zio->io_priority, cb->l2rcb_flags, &cb->l2rcb_zb));
60786071
}
60796072
}
@@ -6381,7 +6374,7 @@ l2arc_write_buffers(spa_t *spa, l2arc_dev_t *dev, uint64_t target_sz,
63816374
* can't access without holding the ARC list locks
63826375
* (which we want to avoid during compression/writing)
63836376
*/
6384-
HDR_SET_COMPRESS(hdr, ZIO_COMPRESS_OFF);
6377+
hdr->b_l2hdr.b_compress = ZIO_COMPRESS_OFF;
63856378
hdr->b_l2hdr.b_asize = hdr->b_size;
63866379
hdr->b_l2hdr.b_hits = 0;
63876380
hdr->b_l1hdr.b_tmp_cdata = hdr->b_l1hdr.b_buf->b_data;
@@ -6587,7 +6580,7 @@ l2arc_compress_buf(arc_buf_hdr_t *hdr)
65876580
l2hdr = &hdr->b_l2hdr;
65886581

65896582
ASSERT(HDR_HAS_L1HDR(hdr));
6590-
ASSERT(HDR_GET_COMPRESS(hdr) == ZIO_COMPRESS_OFF);
6583+
ASSERT3U(l2hdr->b_compress, ==, ZIO_COMPRESS_OFF);
65916584
ASSERT(hdr->b_l1hdr.b_tmp_cdata != NULL);
65926585

65936586
len = l2hdr->b_asize;
@@ -6605,7 +6598,7 @@ l2arc_compress_buf(arc_buf_hdr_t *hdr)
66056598
if (csize == 0) {
66066599
/* zero block, indicate that there's nothing to write */
66076600
zio_data_buf_free(cdata, len);
6608-
HDR_SET_COMPRESS(hdr, ZIO_COMPRESS_EMPTY);
6601+
l2hdr->b_compress = ZIO_COMPRESS_EMPTY;
66096602
l2hdr->b_asize = 0;
66106603
hdr->b_l1hdr.b_tmp_cdata = NULL;
66116604
ARCSTAT_BUMP(arcstat_l2_compress_zeros);
@@ -6615,7 +6608,7 @@ l2arc_compress_buf(arc_buf_hdr_t *hdr)
66156608
* Compression succeeded, we'll keep the cdata around for
66166609
* writing and release it afterwards.
66176610
*/
6618-
HDR_SET_COMPRESS(hdr, ZIO_COMPRESS_LZ4);
6611+
l2hdr->b_compress = ZIO_COMPRESS_LZ4;
66196612
l2hdr->b_asize = csize;
66206613
hdr->b_l1hdr.b_tmp_cdata = cdata;
66216614
ARCSTAT_BUMP(arcstat_l2_compress_successes);
@@ -6702,9 +6695,11 @@ l2arc_decompress_zio(zio_t *zio, arc_buf_hdr_t *hdr, enum zio_compress c)
67026695
static void
67036696
l2arc_release_cdata_buf(arc_buf_hdr_t *hdr)
67046697
{
6705-
enum zio_compress comp = HDR_GET_COMPRESS(hdr);
6698+
enum zio_compress comp;
67066699

67076700
ASSERT(HDR_HAS_L1HDR(hdr));
6701+
ASSERT(HDR_HAS_L2HDR(hdr));
6702+
comp = hdr->b_l2hdr.b_compress;
67086703
ASSERT(comp == ZIO_COMPRESS_OFF || L2ARC_IS_VALID_COMPRESS(comp));
67096704

67106705
if (comp == ZIO_COMPRESS_OFF) {

0 commit comments

Comments
 (0)