* Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER).
* Rewritten for Linux by Brian Behlendorf <behlendorf1@llnl.gov>.
* LLNL-CODE-403049.
- * Copyright (c) 2013 by Delphix. All rights reserved.
+ * Copyright (c) 2012, 2014 by Delphix. All rights reserved.
*/
#include <sys/zfs_context.h>
goto skip_open;
}
- vd = kmem_zalloc(sizeof (vdev_disk_t), KM_PUSHPAGE);
+ vd = kmem_zalloc(sizeof (vdev_disk_t), KM_SLEEP);
if (vd == NULL)
return (ENOMEM);
*max_psize = *psize;
/* Based on the minimum sector size set the block size */
- *ashift = highbit(MAX(block_size, SPA_MINBLOCKSIZE)) - 1;
+ *ashift = highbit64(MAX(block_size, SPA_MINBLOCKSIZE)) - 1;
/* Try to set the io scheduler elevator algorithm */
(void) vdev_elevator_switch(v, zfs_vdev_scheduler);
int i;
dr = kmem_zalloc(sizeof (dio_request_t) +
- sizeof (struct bio *) * bio_count, KM_PUSHPAGE);
+ sizeof (struct bio *) * bio_count, KM_SLEEP);
if (dr) {
init_completion(&dr->dr_comp);
atomic_set(&dr->dr_ref, 0);
"bi_next: %p, bi_flags: %lx, bi_rw: %lu, bi_vcnt: %d\n"
"bi_idx: %d, bi_size: %d, bi_end_io: %p, bi_cnt: %d\n",
bio->bi_next, bio->bi_flags, bio->bi_rw, bio->bi_vcnt,
- bio->bi_idx, bio->bi_size, bio->bi_end_io,
+ BIO_BI_IDX(bio), BIO_BI_SIZE(bio), bio->bi_end_io,
atomic_read(&bio->bi_cnt));
#ifndef HAVE_2ARGS_BIO_END_IO_T
- if (bio->bi_size)
+ if (BIO_BI_SIZE(bio))
return (1);
#endif /* HAVE_2ARGS_BIO_END_IO_T */
if (size > bio_size)
size = bio_size;
- if (kmem_virt(bio_ptr))
+ if (is_vmalloc_addr(bio_ptr))
page = vmalloc_to_page(bio_ptr);
else
page = virt_to_page(bio_ptr);
+ /*
+ * Some network related block device uses tcp_sendpage, which
+ * doesn't behave well when using 0-count page, this is a
+ * safety net to catch them.
+ */
+ ASSERT3S(page_count(page), >, 0);
+
if (bio_add_page(bio, page, size, offset) != size)
break;
return (ENOMEM);
if (zio && !(zio->io_flags & (ZIO_FLAG_IO_RETRY | ZIO_FLAG_TRYHARD)))
- bio_set_flags_failfast(bdev, &flags);
+ bio_set_flags_failfast(bdev, &flags);
dr->dr_zio = zio;
dr->dr_rw = flags;
dr->dr_bio[i] = bio_alloc(GFP_NOIO,
bio_nr_pages(bio_ptr, bio_size));
- if (dr->dr_bio[i] == NULL) {
+ /* bio_alloc() with __GFP_WAIT never returns NULL */
+ if (unlikely(dr->dr_bio[i] == NULL)) {
vdev_disk_dio_free(dr);
return (ENOMEM);
}
vdev_disk_dio_get(dr);
dr->dr_bio[i]->bi_bdev = bdev;
- dr->dr_bio[i]->bi_sector = bio_offset >> 9;
+ BIO_BI_SECTOR(dr->dr_bio[i]) = bio_offset >> 9;
dr->dr_bio[i]->bi_rw = dr->dr_rw;
dr->dr_bio[i]->bi_end_io = vdev_disk_physio_completion;
dr->dr_bio[i]->bi_private = dr;
bio_size = bio_map(dr->dr_bio[i], bio_ptr, bio_size);
/* Advance in buffer and construct another bio if needed */
- bio_ptr += dr->dr_bio[i]->bi_size;
- bio_offset += dr->dr_bio[i]->bi_size;
+ bio_ptr += BIO_BI_SIZE(dr->dr_bio[i]);
+ bio_offset += BIO_BI_SIZE(dr->dr_bio[i]);
}
/* Extra reference to protect dio_request during submit_bio */
return (ENXIO);
bio = bio_alloc(GFP_NOIO, 0);
- if (!bio)
+ /* bio_alloc() with __GFP_WAIT never returns NULL */
+ if (unlikely(bio == NULL))
return (ENOMEM);
bio->bi_end_io = vdev_disk_io_flush_completion;
bio->bi_bdev = bdev;
zio->io_delay = jiffies_64;
submit_bio(VDEV_WRITE_FLUSH_FUA, bio);
+ invalidate_bdev(bdev);
return (0);
}
}
size = P2ALIGN_TYPED(s, sizeof (vdev_label_t), uint64_t);
- label = vmem_alloc(sizeof (vdev_label_t), KM_PUSHPAGE);
+ label = vmem_alloc(sizeof (vdev_label_t), KM_SLEEP);
for (i = 0; i < VDEV_LABELS; i++) {
uint64_t offset, state, txg = 0;