summaryrefslogtreecommitdiffstats
path: root/module/zfs
diff options
context:
space:
mode:
Diffstat (limited to 'module/zfs')
-rw-r--r--module/zfs/arc.c24
-rw-r--r--module/zfs/dbuf.c18
2 files changed, 31 insertions, 11 deletions
diff --git a/module/zfs/arc.c b/module/zfs/arc.c
index 2c7abe6ec..b42bb4050 100644
--- a/module/zfs/arc.c
+++ b/module/zfs/arc.c
@@ -1434,12 +1434,12 @@ arc_space_return(uint64_t space, arc_space_type_t type)
}
arc_buf_t *
-arc_buf_alloc(spa_t *spa, int size, void *tag, arc_buf_contents_t type)
+arc_buf_alloc(spa_t *spa, uint64_t size, void *tag, arc_buf_contents_t type)
{
arc_buf_hdr_t *hdr;
arc_buf_t *buf;
- ASSERT3U(size, >, 0);
+ VERIFY3U(size, <=, SPA_MAXBLOCKSIZE);
hdr = kmem_cache_alloc(hdr_cache, KM_PUSHPAGE);
ASSERT(BUF_EMPTY(hdr));
hdr->b_size = size;
@@ -1477,7 +1477,7 @@ static char *arc_onloan_tag = "onloan";
* freed.
*/
arc_buf_t *
-arc_loan_buf(spa_t *spa, int size)
+arc_loan_buf(spa_t *spa, uint64_t size)
{
arc_buf_t *buf;
@@ -1837,7 +1837,7 @@ arc_buf_remove_ref(arc_buf_t *buf, void* tag)
return (no_callback);
}
-int
+uint64_t
arc_buf_size(arc_buf_t *buf)
{
return (buf->b_hdr->b_size);
@@ -3307,6 +3307,22 @@ top:
enum zio_compress b_compress = ZIO_COMPRESS_OFF;
uint64_t b_asize = 0;
+ /*
+ * Gracefully handle a damaged logical block size as a
+ * checksum error by passing a dummy zio to the done callback.
+ */
+ if (size > SPA_MAXBLOCKSIZE) {
+ if (done) {
+ rzio = zio_null(pio, spa, NULL,
+ NULL, NULL, zio_flags);
+ rzio->io_error = ECKSUM;
+ done(rzio, buf, private);
+ zio_nowait(rzio);
+ }
+ rc = ECKSUM;
+ goto out;
+ }
+
if (hdr == NULL) {
/* this block is not in the cache */
arc_buf_hdr_t *exists = NULL;
diff --git a/module/zfs/dbuf.c b/module/zfs/dbuf.c
index 76a8a99ab..b31957094 100644
--- a/module/zfs/dbuf.c
+++ b/module/zfs/dbuf.c
@@ -571,12 +571,13 @@ dbuf_read_done(zio_t *zio, arc_buf_t *buf, void *vdb)
dbuf_rele_and_unlock(db, NULL);
}
-static void
+static int
dbuf_read_impl(dmu_buf_impl_t *db, zio_t *zio, uint32_t *flags)
{
dnode_t *dn;
zbookmark_phys_t zb;
uint32_t aflags = ARC_NOWAIT;
+ int err;
DB_DNODE_ENTER(db);
dn = DB_DNODE(db);
@@ -601,7 +602,7 @@ dbuf_read_impl(dmu_buf_impl_t *db, zio_t *zio, uint32_t *flags)
dbuf_update_data(db);
db->db_state = DB_CACHED;
mutex_exit(&db->db_mtx);
- return;
+ return (0);
}
/*
@@ -621,7 +622,7 @@ dbuf_read_impl(dmu_buf_impl_t *db, zio_t *zio, uint32_t *flags)
db->db_state = DB_CACHED;
*flags |= DB_RF_CACHED;
mutex_exit(&db->db_mtx);
- return;
+ return (0);
}
DB_DNODE_EXIT(db);
@@ -640,12 +641,14 @@ dbuf_read_impl(dmu_buf_impl_t *db, zio_t *zio, uint32_t *flags)
dbuf_add_ref(db, NULL);
- (void) arc_read(zio, db->db_objset->os_spa, db->db_blkptr,
+ err = arc_read(zio, db->db_objset->os_spa, db->db_blkptr,
dbuf_read_done, db, ZIO_PRIORITY_SYNC_READ,
(*flags & DB_RF_CANFAIL) ? ZIO_FLAG_CANFAIL : ZIO_FLAG_MUSTSUCCEED,
&aflags, &zb);
if (aflags & ARC_CACHED)
*flags |= DB_RF_CACHED;
+
+ return (SET_ERROR(err));
}
int
@@ -688,11 +691,12 @@ dbuf_read(dmu_buf_impl_t *db, zio_t *zio, uint32_t flags)
if (zio == NULL)
zio = zio_root(spa, NULL, NULL, ZIO_FLAG_CANFAIL);
- dbuf_read_impl(db, zio, &flags);
+
+ err = dbuf_read_impl(db, zio, &flags);
/* dbuf_read_impl has dropped db_mtx for us */
- if (prefetch)
+ if (!err && prefetch)
dmu_zfetch(&dn->dn_zfetch, db->db.db_offset,
db->db.db_size, flags & DB_RF_CACHED);
@@ -700,7 +704,7 @@ dbuf_read(dmu_buf_impl_t *db, zio_t *zio, uint32_t flags)
rw_exit(&dn->dn_struct_rwlock);
DB_DNODE_EXIT(db);
- if (!havepzio)
+ if (!err && !havepzio)
err = zio_wait(zio);
} else {
/*