/** * blk_rq_map_user_iov - map user data to a request, for REQ_TYPE_BLOCK_PC usage * @q: request queue where request should be inserted * @rq: request to map data to * @map_data: pointer to the rq_map_data holding pages (if necessary) * @iov: pointer to the iovec * @iov_count: number of elements in the iovec * @len: I/O byte count * @gfp_mask: memory allocation flags * * Description: * Data will be mapped directly for zero copy I/O, if possible. Otherwise * a kernel bounce buffer is used. * * A matching blk_rq_unmap_user() must be issued at the end of I/O, while * still in process context. * * Note: The mapped bio may need to be bounced through blk_queue_bounce() * before being submitted to the device, as pages mapped may be out of * reach. It's the callers responsibility to make sure this happens. The * original bio must be passed back in to blk_rq_unmap_user() for proper * unmapping. */ int blk_rq_map_user_iov(struct request_queue *q, struct request *rq, struct rq_map_data *map_data, struct sg_iovec *iov, int iov_count, unsigned int len, gfp_t gfp_mask) { struct bio *bio; int i, read = rq_data_dir(rq) == READ; int unaligned = 0; if (!iov || iov_count <= 0) return -EINVAL; for (i = 0; i < iov_count; i++) { unsigned long uaddr = (unsigned long)iov[i].iov_base; if (!iov[i].iov_len) return -EINVAL; /* * Keep going so we check length of all segments */ if (uaddr & queue_dma_alignment(q)) unaligned = 1; } if (unaligned || (q->dma_pad_mask & len) || map_data) bio = bio_copy_user_iov(q, map_data, iov, iov_count, read, gfp_mask); else bio = bio_map_user_iov(q, NULL, iov, iov_count, read, gfp_mask); if (IS_ERR(bio)) return PTR_ERR(bio); if (bio->bi_size != len) { /* * Grab an extra reference to this bio, as bio_unmap_user() * expects to be able to drop it twice as it happens on the * normal IO completion path */ bio_get(bio); bio_endio(bio, 0); __blk_rq_unmap_user(bio); return -EINVAL; } if (!bio_flagged(bio, BIO_USER_MAPPED)) rq->cmd_flags |= REQ_COPY_USER; blk_queue_bounce(q, &bio); bio_get(bio); blk_rq_bio_prep(q, rq, bio); rq->buffer = NULL; return 0; }
static int rrpc_submit_io(struct rrpc *rrpc, struct bio *bio, struct nvm_rq *rqd, unsigned long flags) { int err; struct rrpc_rq *rrq = nvm_rq_to_pdu(rqd); uint8_t nr_pages = rrpc_get_pages(bio); int bio_size = bio_sectors(bio) << 9; if (bio_size < rrpc->dev->sec_size) return NVM_IO_ERR; else if (bio_size > rrpc->dev->max_rq_size) return NVM_IO_ERR; err = rrpc_setup_rq(rrpc, bio, rqd, flags, nr_pages); if (err) return err; bio_get(bio); rqd->bio = bio; rqd->ins = &rrpc->instance; rqd->nr_pages = nr_pages; rrq->flags = flags; err = nvm_submit_io(rrpc->dev, rqd); if (err) { pr_err("rrpc: I/O submission failed: %d\n", err); return NVM_IO_ERR; } return NVM_IO_OK; }
static int xixfs_raw_submit( struct block_device *bdev, sector_t startsector, int32 size, int32 sectorsize, PXIX_BUF xbuf, int32 rw) { struct bio * bio; int ret = 0; bio = bio_alloc(GFP_NOIO, 1); bio->bi_sector = startsector; bio->bi_bdev = bdev; bio_add_page(bio, xbuf->xix_page, size, xbuf->xixcore_buffer.xcb_offset); bio->bi_private = (void *)xbuf; bio->bi_end_io = end_bio_xbuf_io_async; bio->bi_rw = rw; bio_get(bio); submit_bio(rw, bio); if(bio_flagged(bio, BIO_EOPNOTSUPP)) ret = -EOPNOTSUPP; bio_put(bio); return ret; }
static int submit(int rw, pgoff_t page_off, void * page) { int error = 0; struct bio * bio; bio = bio_alloc(GFP_ATOMIC,1); if (!bio) return -ENOMEM; bio->bi_sector = page_off * (PAGE_SIZE >> 9); bio_get(bio); bio->bi_bdev = resume_bdev; bio->bi_end_io = end_io; if (bio_add_page(bio, virt_to_page(page), PAGE_SIZE, 0) < PAGE_SIZE) { printk("pmdisk: ERROR: adding page to bio at %ld\n",page_off); error = -EFAULT; goto Done; } if (rw == WRITE) bio_set_pages_dirty(bio); start_io(); submit_bio(rw | (1 << BIO_RW_SYNC), bio); wait_io(); Done: bio_put(bio); return error; }
/** * submit - submit BIO request * @writing: READ or WRITE. * @dev: The block device we're using. * @first_block: The first sector we're using. * @page: The page being used for I/O. * @free_group: If writing, the group that was used in allocating the page * and which will be used in freeing the page from the completion * routine. * * Based on Patrick Mochell's pmdisk code from long ago: "Straight from the * textbook - allocate and initialize the bio. If we're writing, make sure * the page is marked as dirty. Then submit it and carry on." * * If we're just testing the speed of our own code, we fake having done all * the hard work and all toi_end_bio immediately. **/ static int submit(int writing, struct block_device *dev, sector_t first_block, struct page *page, int free_group) { struct bio *bio = NULL; int cur_outstanding_io, result; /* * Shouldn't throttle if reading - can deadlock in the single * threaded case as pages are only freed when we use the * readahead. */ if (writing) { result = throttle_if_needed(MEMORY_ONLY | THROTTLE_WAIT); if (result) return result; } while (!bio) { bio = bio_alloc(TOI_ATOMIC_GFP, 1); if (!bio) { set_free_mem_throttle(); do_bio_wait(1); } } bio->bi_bdev = dev; bio->bi_sector = first_block; bio->bi_private = (void *)((unsigned long)free_group); bio->bi_end_io = toi_end_bio; bio->bi_flags |= (1 << BIO_TOI); if (bio_add_page(bio, page, PAGE_SIZE, 0) < PAGE_SIZE) { printk(KERN_DEBUG "ERROR: adding page to bio at %lld\n", (unsigned long long)first_block); bio_put(bio); return -EFAULT; } bio_get(bio); cur_outstanding_io = atomic_add_return(1, &toi_io_in_progress); if (writing) { if (cur_outstanding_io > max_outstanding_writes) max_outstanding_writes = cur_outstanding_io; } else { if (cur_outstanding_io > max_outstanding_reads) max_outstanding_reads = cur_outstanding_io; } /* Still read the header! */ if (unlikely(test_action_state(TOI_TEST_BIO) && writing)) { /* Fake having done the hard work */ set_bit(BIO_UPTODATE, &bio->bi_flags); toi_end_bio(bio, 0); } else submit_bio(writing | REQ_SYNC, bio); return 0; }
uint16_t *bio_get_string16(struct binder_io *bio, unsigned *sz) { unsigned len; len = bio_get_uint32(bio); if (sz) *sz = len; return bio_get(bio, (len + 1) * sizeof(uint16_t)); }
uint16_t* bio_get_string16(struct binder_io* bio, size_t* sz) { size_t len; /* Note: The payload will carry 32bit size instead of size_t */ len = (size_t) bio_get_uint32(bio); if (sz) *sz = len; return bio_get(bio, (len + 1) * sizeof(uint16_t)); }
static struct flat_binder_object* _bio_get_obj(struct binder_io* bio) { size_t n; size_t off = bio->data - bio->data0; /* TODO: be smarter about this? */ for (n = 0; n < bio->offs_avail; n++) { if (bio->offs[n] == off) return bio_get(bio, sizeof(struct flat_binder_object)); } bio->data_avail = 0; bio->flags |= BIO_F_OVERFLOW; return NULL; }
void ext4_io_submit(struct ext4_io_submit *io) { struct bio *bio = io->io_bio; if (bio) { bio_get(io->io_bio); submit_bio(io->io_op, io->io_bio); BUG_ON(bio_flagged(io->io_bio, BIO_EOPNOTSUPP)); bio_put(io->io_bio); } io->io_bio = NULL; io->io_op = 0; io->io_end = NULL; }
/** * blkdev_issue_discard - queue a discard * @bdev: blockdev to issue discard for * @sector: start sector * @nr_sects: number of sectors to discard * @gfp_mask: memory allocation flags (for bio_alloc) * * Description: * Issue a discard request for the sectors in question. Does not wait. */ int blkdev_issue_discard(struct block_device *bdev, sector_t sector, sector_t nr_sects, gfp_t gfp_mask) { struct request_queue *q; struct bio *bio; int ret = 0; if (bdev->bd_disk == NULL) return -ENXIO; q = bdev_get_queue(bdev); if (!q) return -ENXIO; if (!q->prepare_discard_fn) return -EOPNOTSUPP; while (nr_sects && !ret) { bio = bio_alloc(gfp_mask, 0); if (!bio) return -ENOMEM; bio->bi_end_io = blkdev_discard_end_io; bio->bi_bdev = bdev; bio->bi_sector = sector; if (nr_sects > q->max_hw_sectors) { bio->bi_size = q->max_hw_sectors << 9; nr_sects -= q->max_hw_sectors; sector += q->max_hw_sectors; } else { bio->bi_size = nr_sects << 9; nr_sects = 0; } bio_get(bio); submit_bio(DISCARD_BARRIER, bio); /* Check if it failed immediately */ if (bio_flagged(bio, BIO_EOPNOTSUPP)) ret = -EOPNOTSUPP; else if (!bio_flagged(bio, BIO_UPTODATE)) ret = -EIO; bio_put(bio); } return ret; }
/** * __blkdev_issue_flush - queue a flush * @bdev: blockdev to issue flush for * @gfp_mask: memory allocation flags (for bio_alloc) * @error_sector: error sector * * Description: * Issue a flush for the block device in question. Caller can supply * room for storing the error offset in case of a flush error, if they * wish to. If WAIT flag is not passed then caller may check only what * request was pushed in some internal queue for later handling. */ int __blkdev_issue_flush(struct block_device *bdev, gfp_t gfp_mask, sector_t *error_sector) { DECLARE_COMPLETION_ONSTACK(wait); struct request_queue *q; struct bio *bio; int ret = 0; if (bdev->bd_disk == NULL) return -ENXIO; q = bdev_get_queue(bdev); if (!q) return -ENXIO; /* * some block devices may not have their queue correctly set up here * (e.g. loop device without a backing file) and so issuing a flush * here will panic. Ensure there is a request function before issuing * the flush. */ if (!q->make_request_fn) return -ENXIO; bio = bio_alloc(gfp_mask, 0); bio->bi_end_io = bio_end_flush; bio->bi_bdev = bdev; bio->bi_private = &wait; bio_get(bio); submit_bio(WRITE_FLUSH, bio); wait_for_completion(&wait); /* * The driver must store the error location in ->bi_sector, if * it supports it. For non-stacked drivers, this should be * copied from blk_rq_pos(rq). */ if (error_sector) *error_sector = bio->bi_sector; if (!bio_flagged(bio, BIO_UPTODATE)) ret = -EIO; bio_put(bio); return ret; }
static int __blk_rq_map_user(struct request_queue *q, struct request *rq, struct rq_map_data *map_data, void __user *ubuf, unsigned int len, gfp_t gfp_mask) { unsigned long uaddr; struct bio *bio, *orig_bio; int reading, ret; reading = rq_data_dir(rq) == READ; /* * if alignment requirement is satisfied, map in user pages for * direct dma. else, set up kernel bounce buffers */ uaddr = (unsigned long) ubuf; if (blk_rq_aligned(q, uaddr, len) && !map_data) bio = bio_map_user(q, NULL, uaddr, len, reading, gfp_mask); else bio = bio_copy_user(q, map_data, uaddr, len, reading, gfp_mask); if (IS_ERR(bio)) return PTR_ERR(bio); if (map_data && map_data->null_mapped) bio->bi_flags |= (1 << BIO_NULL_MAPPED); orig_bio = bio; blk_queue_bounce(q, &bio); /* * We link the bounce buffer in and could have to traverse it * later so we have to get a ref to prevent it from being freed */ bio_get(bio); ret = blk_rq_append_bio(q, rq, bio); if (!ret) return bio->bi_size; /* if it was boucned we must call the end io function */ bio_endio(bio, 0); __blk_rq_unmap_user(orig_bio); bio_put(bio); return ret; }
/** * blk_rq_map_user_iov - map user data to a request, for REQ_BLOCK_PC usage * @q: request queue where request should be inserted * @rq: request to map data to * @iov: pointer to the iovec * @iov_count: number of elements in the iovec * @len: I/O byte count * * Description: * Data will be mapped directly for zero copy io, if possible. Otherwise * a kernel bounce buffer is used. * * A matching blk_rq_unmap_user() must be issued at the end of io, while * still in process context. * * Note: The mapped bio may need to be bounced through blk_queue_bounce() * before being submitted to the device, as pages mapped may be out of * reach. It's the callers responsibility to make sure this happens. The * original bio must be passed back in to blk_rq_unmap_user() for proper * unmapping. */ int blk_rq_map_user_iov(struct request_queue *q, struct request *rq, struct sg_iovec *iov, int iov_count, unsigned int len) { struct bio *bio; int i, read = rq_data_dir(rq) == READ; int unaligned = 0; if (!iov || iov_count <= 0) return -EINVAL; for (i = 0; i < iov_count; i++) { unsigned long uaddr = (unsigned long)iov[i].iov_base; if (uaddr & queue_dma_alignment(q)) { unaligned = 1; break; } if (!iov[i].iov_len) return -EINVAL; } if (unaligned || (q->dma_pad_mask & len)) bio = bio_copy_user_iov(q, iov, iov_count, read); else bio = bio_map_user_iov(q, NULL, iov, iov_count, read); if (IS_ERR(bio)) return PTR_ERR(bio); if (bio->bi_size != len) { bio_endio(bio, 0); bio_unmap_user(bio); return -EINVAL; } if (!bio_flagged(bio, BIO_USER_MAPPED)) rq->cmd_flags |= REQ_COPY_USER; blk_queue_bounce(q, &bio); bio_get(bio); blk_rq_bio_prep(q, rq, bio); rq->buffer = rq->data = NULL; return 0; }
static int __blk_rq_map_user(struct request_queue *q, struct request *rq, void __user *ubuf, unsigned int len) { unsigned long uaddr; unsigned int alignment; struct bio *bio, *orig_bio; int reading, ret; reading = rq_data_dir(rq) == READ; /* * if alignment requirement is satisfied, map in user pages for * direct dma. else, set up kernel bounce buffers */ uaddr = (unsigned long) ubuf; alignment = queue_dma_alignment(q) | q->dma_pad_mask; if (!(uaddr & alignment) && !(len & alignment)) bio = bio_map_user(q, NULL, uaddr, len, reading); else bio = bio_copy_user(q, uaddr, len, reading); if (IS_ERR(bio)) return PTR_ERR(bio); orig_bio = bio; blk_queue_bounce(q, &bio); /* * We link the bounce buffer in and could have to traverse it * later so we have to get a ref to prevent it from being freed */ bio_get(bio); ret = blk_rq_append_bio(q, rq, bio); if (!ret) return bio->bi_size; /* if it was boucned we must call the end io function */ bio_endio(bio, 0); __blk_rq_unmap_user(orig_bio); bio_put(bio); return ret; }
static int __blk_rq_map_user_iov(struct request *rq, struct rq_map_data *map_data, struct iov_iter *iter, gfp_t gfp_mask, bool copy) { struct request_queue *q = rq->q; struct bio *bio, *orig_bio; int ret; if (copy) bio = bio_copy_user_iov(q, map_data, iter, gfp_mask); else bio = bio_map_user_iov(q, iter, gfp_mask); if (IS_ERR(bio)) return PTR_ERR(bio); if (map_data && map_data->null_mapped) bio_set_flag(bio, BIO_NULL_MAPPED); iov_iter_advance(iter, bio->bi_iter.bi_size); if (map_data) map_data->offset += bio->bi_iter.bi_size; orig_bio = bio; blk_queue_bounce(q, &bio); /* * We link the bounce buffer in and could have to traverse it * later so we have to get a ref to prevent it from being freed */ bio_get(bio); ret = blk_rq_append_bio(q, rq, bio); if (ret) { bio_endio(bio); __blk_rq_unmap_user(orig_bio); bio_put(bio); return ret; } return 0; }
/** * submit - submit BIO request. * @rw: READ or WRITE. * @off physical offset of page. * @page: page we're reading or writing. * @bio_chain: list of pending biod (for async reading) * * Straight from the textbook - allocate and initialize the bio. * If we're reading, make sure the page is marked as dirty. * Then submit it and, if @bio_chain == NULL, wait. */ static int submit(int rw, struct block_device *bdev, sector_t sector, struct page *page, struct bio **bio_chain) { const int bio_rw = rw | REQ_SYNC; struct bio *bio; bio = bio_alloc(__GFP_WAIT | __GFP_HIGH, 1); bio->bi_sector = sector; bio->bi_bdev = bdev; bio->bi_end_io = end_swap_bio_read; if (bio_add_page(bio, page, PAGE_SIZE, 0) < PAGE_SIZE) { printk(KERN_ERR "PM: Adding page to bio failed at %llu\n", (unsigned long long)sector); bio_put(bio); return -EFAULT; } lock_page(page); bio_get(bio); if (bio_chain == NULL) { submit_bio(bio_rw, bio); wait_on_page_locked(page); if (rw == READ) bio_set_pages_dirty(bio); bio_put(bio); } else { if (rw == READ) get_page(page); /* These pages are freed later */ bio->bi_private = *bio_chain; *bio_chain = bio; submit_bio(bio_rw, bio); } return 0; }
uint32_t bio_get_uint32(struct binder_io* bio) { uint32_t* ptr = bio_get(bio, sizeof(*ptr)); return ptr ? *ptr : 0; }
struct ceph_osd_request *ceph_osdc_alloc_request(struct ceph_osd_client *osdc, int flags, struct ceph_snap_context *snapc, struct ceph_osd_req_op *ops, bool use_mempool, gfp_t gfp_flags, struct page **pages, struct bio *bio) { struct ceph_osd_request *req; struct ceph_msg *msg; int needs_trail; int num_op = get_num_ops(ops, &needs_trail); size_t msg_size = sizeof(struct ceph_osd_request_head); msg_size += num_op*sizeof(struct ceph_osd_op); if (use_mempool) { req = mempool_alloc(osdc->req_mempool, gfp_flags); memset(req, 0, sizeof(*req)); } else { req = kzalloc(sizeof(*req), gfp_flags); } if (req == NULL) return NULL; req->r_osdc = osdc; req->r_mempool = use_mempool; kref_init(&req->r_kref); init_completion(&req->r_completion); init_completion(&req->r_safe_completion); rb_init_node(&req->r_node); INIT_LIST_HEAD(&req->r_unsafe_item); INIT_LIST_HEAD(&req->r_linger_item); INIT_LIST_HEAD(&req->r_linger_osd); INIT_LIST_HEAD(&req->r_req_lru_item); INIT_LIST_HEAD(&req->r_osd_item); req->r_flags = flags; WARN_ON((flags & (CEPH_OSD_FLAG_READ|CEPH_OSD_FLAG_WRITE)) == 0); /* create reply message */ if (use_mempool) msg = ceph_msgpool_get(&osdc->msgpool_op_reply, 0); else msg = ceph_msg_new(CEPH_MSG_OSD_OPREPLY, OSD_OPREPLY_FRONT_LEN, gfp_flags, true); if (!msg) { ceph_osdc_put_request(req); return NULL; } req->r_reply = msg; /* allocate space for the trailing data */ if (needs_trail) { req->r_trail = kmalloc(sizeof(struct ceph_pagelist), gfp_flags); if (!req->r_trail) { ceph_osdc_put_request(req); return NULL; } ceph_pagelist_init(req->r_trail); } /* create request message; allow space for oid */ msg_size += MAX_OBJ_NAME_SIZE; if (snapc) msg_size += sizeof(u64) * snapc->num_snaps; if (use_mempool) msg = ceph_msgpool_get(&osdc->msgpool_op, 0); else msg = ceph_msg_new(CEPH_MSG_OSD_OP, msg_size, gfp_flags, true); if (!msg) { ceph_osdc_put_request(req); return NULL; } memset(msg->front.iov_base, 0, msg->front.iov_len); req->r_request = msg; req->r_pages = pages; #ifdef CONFIG_BLOCK if (bio) { req->r_bio = bio; bio_get(req->r_bio); } #endif return req; }