/** * blk_execute_rq - insert a request into queue for execution * @q: queue to insert the request in * @bd_disk: matching gendisk * @rq: request to insert * @at_head: insert request at head or tail of queue * * Description: * Insert a fully prepared request at the back of the I/O scheduler queue * for execution and wait for completion. */ int blk_execute_rq(struct request_queue *q, struct gendisk *bd_disk, struct request *rq, int at_head) { DECLARE_COMPLETION_ONSTACK(wait); char sense[SCSI_SENSE_BUFFERSIZE]; int err = 0; unsigned long hang_check; /* * we need an extra reference to the request, so we can look at * it after io completion */ rq->ref_count++; if (!rq->sense) { memset(sense, 0, sizeof(sense)); rq->sense = sense; rq->sense_len = 0; } rq->end_io_data = &wait; blk_execute_rq_nowait(q, bd_disk, rq, at_head, blk_end_sync_rq); /* Prevent hang_check timer from firing at us during very long I/O */ hang_check = sysctl_hung_task_timeout_secs; if (hang_check) while (!wait_for_completion_io_timeout(&wait, hang_check * (HZ/2))); else wait_for_completion_io(&wait); if (rq->errors) err = -EIO; return err; }
/** * mmc_wait_for_req - start a request and wait for completion * @host: MMC host to start command * @mrq: MMC request to start * * Start a new MMC custom command request for a host, and wait * for the command to complete. Does not attempt to parse the * response. */ void mmc_wait_for_req(struct mmc_host *host, struct mmc_request *mrq) { #ifdef CONFIG_WIMAX int ret = 0; struct msmsdcc_host *msm_host = mmc_priv(host); #endif DECLARE_COMPLETION_ONSTACK(complete); mrq->done_data = &complete; mrq->done = mmc_wait_done; mmc_start_request(host, mrq); #ifdef CONFIG_WIMAX #ifdef CONFIG_WIMAX_MMC if ( !(strcmp(mmc_hostname(host), CONFIG_WIMAX_MMC))) { ret = wait_for_completion_timeout(&complete, msecs_to_jiffies(5000)); if (ret <= 0) { printk("[ERR] %s: %s wait_for_completion_timeout!\n", __func__, mmc_hostname(host)); msmsdcc_stop_data(msm_host); mrq->cmd->error = -ETIMEDOUT; msmsdcc_request_end(msm_host, mrq); } } else #endif #endif wait_for_completion_io(&complete); }
static int sync_io(struct dm_io_client *client, unsigned int num_regions, struct dm_io_region *where, int rw, struct dpages *dp, unsigned long *error_bits) { struct io *io; struct sync_io sio; if (num_regions > 1 && (rw & RW_MASK) != WRITE) { WARN_ON(1); return -EIO; } init_completion(&sio.wait); io = mempool_alloc(client->pool, GFP_NOIO); io->error_bits = 0; atomic_set(&io->count, 1); /* see dispatch_io() */ io->client = client; io->callback = sync_io_complete; io->context = &sio; io->vma_invalidate_address = dp->vma_invalidate_address; io->vma_invalidate_size = dp->vma_invalidate_size; dispatch_io(rw, num_regions, where, dp, io, 1); wait_for_completion_io(&sio.wait); if (error_bits) *error_bits = sio.error_bits; return sio.error_bits ? -EIO : 0; }
/** * blk_execute_rq - insert a request into queue for execution * @q: queue to insert the request in * @bd_disk: matching gendisk * @rq: request to insert * @at_head: insert request at head or tail of queue * * Description: * Insert a fully prepared request at the back of the I/O scheduler queue * for execution and wait for completion. */ int blk_execute_rq(struct request_queue *q, struct gendisk *bd_disk, struct request *rq, int at_head) { DECLARE_COMPLETION_ONSTACK(wait); char sense[SCSI_SENSE_BUFFERSIZE]; int err = 0; /* * we need an extra reference to the request, so we can look at * it after io completion */ rq->ref_count++; if (!rq->sense) { memset(sense, 0, sizeof(sense)); rq->sense = sense; rq->sense_len = 0; } rq->end_io_data = &wait; blk_execute_rq_nowait(q, bd_disk, rq, at_head, blk_end_sync_rq); wait_for_completion_io(&wait); if (rq->errors) err = -EIO; return err; }
int blk_execute_rq(struct request_queue *q, struct gendisk *bd_disk, struct request *rq, int at_head) { DECLARE_COMPLETION_ONSTACK(wait); char sense[SCSI_SENSE_BUFFERSIZE]; int err = 0; unsigned long hang_check; rq->ref_count++; if (!rq->sense) { memset(sense, 0, sizeof(sense)); rq->sense = sense; rq->sense_len = 0; } rq->end_io_data = &wait; blk_execute_rq_nowait(q, bd_disk, rq, at_head, blk_end_sync_rq); hang_check = sysctl_hung_task_timeout_secs; if (hang_check) while (!wait_for_completion_io_timeout(&wait, hang_check * (HZ/2))); else wait_for_completion_io(&wait); if (rq->errors) err = -EIO; return err; }
/** * blkdev_issue_write_same - queue a write same operation * @bdev: target blockdev * @sector: start sector * @nr_sects: number of sectors to write * @gfp_mask: memory allocation flags (for bio_alloc) * @page: page containing data to write * * Description: * Issue a write same request for the sectors in question. */ int blkdev_issue_write_same(struct block_device *bdev, sector_t sector, sector_t nr_sects, gfp_t gfp_mask, struct page *page) { DECLARE_COMPLETION_ONSTACK(wait); struct request_queue *q = bdev_get_queue(bdev); unsigned int max_write_same_sectors; struct bio_batch bb; struct bio *bio; int ret = 0; if (!q) return -ENXIO; /* Ensure that max_write_same_sectors doesn't overflow bi_size */ max_write_same_sectors = UINT_MAX >> 9; atomic_set(&bb.done, 1); bb.error = 0; bb.wait = &wait; while (nr_sects) { bio = bio_alloc(gfp_mask, 1); if (!bio) { ret = -ENOMEM; break; } bio->bi_iter.bi_sector = sector; bio->bi_end_io = bio_batch_end_io; bio->bi_bdev = bdev; bio->bi_private = &bb; bio->bi_vcnt = 1; bio->bi_io_vec->bv_page = page; bio->bi_io_vec->bv_offset = 0; bio->bi_io_vec->bv_len = bdev_logical_block_size(bdev); if (nr_sects > max_write_same_sectors) { bio->bi_iter.bi_size = max_write_same_sectors << 9; nr_sects -= max_write_same_sectors; sector += max_write_same_sectors; } else { bio->bi_iter.bi_size = nr_sects << 9; nr_sects = 0; } atomic_inc(&bb.done); submit_bio(REQ_WRITE | REQ_WRITE_SAME, bio); } /* Wait for bios in-flight */ if (!atomic_dec_and_test(&bb.done)) wait_for_completion_io(&wait); if (bb.error) return bb.error; return ret; }
/** * mmc_wait_for_req - start a request and wait for completion * @host: MMC host to start command * @mrq: MMC request to start * * Start a new MMC custom command request for a host, and wait * for the command to complete. Does not attempt to parse the * response. */ void mmc_wait_for_req(struct mmc_host *host, struct mmc_request *mrq) { DECLARE_COMPLETION_ONSTACK(complete); mrq->done_data = &complete; mrq->done = mmc_wait_done; mmc_start_request(host, mrq); wait_for_completion_io(&complete); }
static int __blkdev_issue_zeroout(struct block_device *bdev, sector_t sector, sector_t nr_sects, gfp_t gfp_mask) { int ret; struct bio *bio; struct bio_batch bb; unsigned int sz; DECLARE_COMPLETION_ONSTACK(wait); atomic_set(&bb.done, 1); bb.error = 0; bb.wait = &wait; ret = 0; while (nr_sects != 0) { bio = bio_alloc(gfp_mask, min(nr_sects, (sector_t)BIO_MAX_PAGES)); if (!bio) { ret = -ENOMEM; break; } bio->bi_iter.bi_sector = sector; bio->bi_bdev = bdev; bio->bi_end_io = bio_batch_end_io; bio->bi_private = &bb; while (nr_sects != 0) { sz = min((sector_t) PAGE_SIZE >> 9 , nr_sects); ret = bio_add_page(bio, ZERO_PAGE(0), sz << 9, 0); nr_sects -= ret >> 9; sector += ret >> 9; if (ret < (sz << 9)) break; } ret = 0; atomic_inc(&bb.done); submit_bio(WRITE, bio); } /* Wait for bios in-flight */ if (!atomic_dec_and_test(&bb.done)) wait_for_completion_io(&wait); if (bb.error) return bb.error; return ret; }
static int sync_io(struct dm_io_client *client, unsigned int num_regions, struct dm_io_region *where, int rw, struct dpages *dp, unsigned long *error_bits) { /* * gcc <= 4.3 can't do the alignment for stack variables, so we must * align it on our own. * volatile prevents the optimizer from removing or reusing * "io_" field from the stack frame (allowed in ANSI C). */ volatile char io_[sizeof(struct io) + __alignof__(struct io) - 1]; struct io *io = (struct io *)PTR_ALIGN(&io_, __alignof__(struct io)); DECLARE_COMPLETION_ONSTACK(wait); if (num_regions > 1 && (rw & RW_MASK) != WRITE) { WARN_ON(1); return -EIO; } io->error_bits = 0; atomic_set(&io->count, 1); /* see dispatch_io() */ io->wait = &wait; io->client = client; io->vma_invalidate_address = dp->vma_invalidate_address; io->vma_invalidate_size = dp->vma_invalidate_size; dispatch_io(rw, num_regions, where, dp, io, 1); wait_for_completion_io(&wait); if (error_bits) *error_bits = io->error_bits; return io->error_bits ? -EIO : 0; }
static int ide_pm_execute_rq(struct request *rq) { struct request_queue *q = rq->q; DECLARE_COMPLETION_ONSTACK(wait); rq->end_io_data = &wait; rq->end_io = ide_end_sync_rq; spin_lock_irq(q->queue_lock); if (unlikely(blk_queue_dying(q))) { rq->rq_flags |= RQF_QUIET; scsi_req(rq)->result = -ENXIO; __blk_end_request_all(rq, BLK_STS_OK); spin_unlock_irq(q->queue_lock); return -ENXIO; } __elv_add_request(q, rq, ELEVATOR_INSERT_FRONT); __blk_run_queue_uncond(q); spin_unlock_irq(q->queue_lock); wait_for_completion_io(&wait); return scsi_req(rq)->result ? -EIO : 0; }
/* * rrpc_move_valid_pages -- migrate live data off the block * @rrpc: the 'rrpc' structure * @block: the block from which to migrate live pages * * Description: * GC algorithms may call this function to migrate remaining live * pages off the block prior to erasing it. This function blocks * further execution until the operation is complete. */ static int rrpc_move_valid_pages(struct rrpc *rrpc, struct rrpc_block *rblk) { struct request_queue *q = rrpc->dev->q; struct rrpc_rev_addr *rev; struct nvm_rq *rqd; struct bio *bio; struct page *page; int slot; int nr_sec_per_blk = rrpc->dev->sec_per_blk; u64 phys_addr; DECLARE_COMPLETION_ONSTACK(wait); if (bitmap_full(rblk->invalid_pages, nr_sec_per_blk)) return 0; bio = bio_alloc(GFP_NOIO, 1); if (!bio) { pr_err("nvm: could not alloc bio to gc\n"); return -ENOMEM; } page = mempool_alloc(rrpc->page_pool, GFP_NOIO); if (!page) { bio_put(bio); return -ENOMEM; } while ((slot = find_first_zero_bit(rblk->invalid_pages, nr_sec_per_blk)) < nr_sec_per_blk) { /* Lock laddr */ phys_addr = rblk->parent->id * nr_sec_per_blk + slot; try: spin_lock(&rrpc->rev_lock); /* Get logical address from physical to logical table */ rev = &rrpc->rev_trans_map[phys_addr - rrpc->poffset]; /* already updated by previous regular write */ if (rev->addr == ADDR_EMPTY) { spin_unlock(&rrpc->rev_lock); continue; } rqd = rrpc_inflight_laddr_acquire(rrpc, rev->addr, 1); if (IS_ERR_OR_NULL(rqd)) { spin_unlock(&rrpc->rev_lock); schedule(); goto try; } spin_unlock(&rrpc->rev_lock); /* Perform read to do GC */ bio->bi_iter.bi_sector = rrpc_get_sector(rev->addr); bio->bi_rw = READ; bio->bi_private = &wait; bio->bi_end_io = rrpc_end_sync_bio; /* TODO: may fail when EXP_PG_SIZE > PAGE_SIZE */ bio_add_pc_page(q, bio, page, RRPC_EXPOSED_PAGE_SIZE, 0); if (rrpc_submit_io(rrpc, bio, rqd, NVM_IOTYPE_GC)) { pr_err("rrpc: gc read failed.\n"); rrpc_inflight_laddr_release(rrpc, rqd); goto finished; } wait_for_completion_io(&wait); if (bio->bi_error) { rrpc_inflight_laddr_release(rrpc, rqd); goto finished; } bio_reset(bio); reinit_completion(&wait); bio->bi_iter.bi_sector = rrpc_get_sector(rev->addr); bio->bi_rw = WRITE; bio->bi_private = &wait; bio->bi_end_io = rrpc_end_sync_bio; bio_add_pc_page(q, bio, page, RRPC_EXPOSED_PAGE_SIZE, 0); /* turn the command around and write the data back to a new * address */ if (rrpc_submit_io(rrpc, bio, rqd, NVM_IOTYPE_GC)) { pr_err("rrpc: gc write failed.\n"); rrpc_inflight_laddr_release(rrpc, rqd); goto finished; } wait_for_completion_io(&wait); rrpc_inflight_laddr_release(rrpc, rqd); if (bio->bi_error) goto finished; bio_reset(bio); } finished: mempool_free(page, rrpc->page_pool); bio_put(bio); if (!bitmap_full(rblk->invalid_pages, nr_sec_per_blk)) { pr_err("nvm: failed to garbage collect block\n"); return -EIO; } return 0; } static void rrpc_block_gc(struct work_struct *work) { struct rrpc_block_gc *gcb = container_of(work, struct rrpc_block_gc, ws_gc); struct rrpc *rrpc = gcb->rrpc; struct rrpc_block *rblk = gcb->rblk; struct nvm_dev *dev = rrpc->dev; struct nvm_lun *lun = rblk->parent->lun; struct rrpc_lun *rlun = &rrpc->luns[lun->id - rrpc->lun_offset]; mempool_free(gcb, rrpc->gcb_pool); pr_debug("nvm: block '%lu' being reclaimed\n", rblk->parent->id); if (rrpc_move_valid_pages(rrpc, rblk)) goto put_back; if (nvm_erase_blk(dev, rblk->parent)) goto put_back; rrpc_put_blk(rrpc, rblk); return; put_back: spin_lock(&rlun->lock); list_add_tail(&rblk->prio, &rlun->prio_list); spin_unlock(&rlun->lock); } /* the block with highest number of invalid pages, will be in the beginning * of the list */ static struct rrpc_block *rblock_max_invalid(struct rrpc_block *ra, struct rrpc_block *rb) { if (ra->nr_invalid_pages == rb->nr_invalid_pages) return ra; return (ra->nr_invalid_pages < rb->nr_invalid_pages) ? rb : ra; } /* linearly find the block with highest number of invalid pages * requires lun->lock */ static struct rrpc_block *block_prio_find_max(struct rrpc_lun *rlun) { struct list_head *prio_list = &rlun->prio_list; struct rrpc_block *rblock, *max; BUG_ON(list_empty(prio_list)); max = list_first_entry(prio_list, struct rrpc_block, prio); list_for_each_entry(rblock, prio_list, prio) max = rblock_max_invalid(max, rblock); return max; } static void rrpc_lun_gc(struct work_struct *work) { struct rrpc_lun *rlun = container_of(work, struct rrpc_lun, ws_gc); struct rrpc *rrpc = rlun->rrpc; struct nvm_lun *lun = rlun->parent; struct rrpc_block_gc *gcb; unsigned int nr_blocks_need; nr_blocks_need = rrpc->dev->blks_per_lun / GC_LIMIT_INVERSE; if (nr_blocks_need < rrpc->nr_luns) nr_blocks_need = rrpc->nr_luns; spin_lock(&rlun->lock); while (nr_blocks_need > lun->nr_free_blocks && !list_empty(&rlun->prio_list)) { struct rrpc_block *rblock = block_prio_find_max(rlun); struct nvm_block *block = rblock->parent; if (!rblock->nr_invalid_pages) break; gcb = mempool_alloc(rrpc->gcb_pool, GFP_ATOMIC); if (!gcb) break; list_del_init(&rblock->prio); BUG_ON(!block_is_full(rrpc, rblock)); pr_debug("rrpc: selected block '%lu' for GC\n", block->id); gcb->rrpc = rrpc; gcb->rblk = rblock; INIT_WORK(&gcb->ws_gc, rrpc_block_gc); queue_work(rrpc->kgc_wq, &gcb->ws_gc); nr_blocks_need--; } spin_unlock(&rlun->lock); /* TODO: Hint that request queue can be started again */ } static void rrpc_gc_queue(struct work_struct *work) { struct rrpc_block_gc *gcb = container_of(work, struct rrpc_block_gc, ws_gc); struct rrpc *rrpc = gcb->rrpc; struct rrpc_block *rblk = gcb->rblk; struct nvm_lun *lun = rblk->parent->lun; struct nvm_block *blk = rblk->parent; struct rrpc_lun *rlun = &rrpc->luns[lun->id - rrpc->lun_offset]; spin_lock(&rlun->lock); list_add_tail(&rblk->prio, &rlun->prio_list); spin_unlock(&rlun->lock); spin_lock(&lun->lock); lun->nr_open_blocks--; lun->nr_closed_blocks++; blk->state &= ~NVM_BLK_ST_OPEN; blk->state |= NVM_BLK_ST_CLOSED; list_move_tail(&rblk->list, &rlun->closed_list); spin_unlock(&lun->lock); mempool_free(gcb, rrpc->gcb_pool); pr_debug("nvm: block '%lu' is full, allow GC (sched)\n", rblk->parent->id); } static const struct block_device_operations rrpc_fops = { .owner = THIS_MODULE, }; static struct rrpc_lun *rrpc_get_lun_rr(struct rrpc *rrpc, int is_gc) { unsigned int i; struct rrpc_lun *rlun, *max_free; if (!is_gc) return get_next_lun(rrpc); /* during GC, we don't care about RR, instead we want to make * sure that we maintain evenness between the block luns. */ max_free = &rrpc->luns[0]; /* prevent GC-ing lun from devouring pages of a lun with * little free blocks. We don't take the lock as we only need an * estimate. */ rrpc_for_each_lun(rrpc, rlun, i) { if (rlun->parent->nr_free_blocks > max_free->parent->nr_free_blocks) max_free = rlun; } return max_free; }
/** * 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) * @flags: BLKDEV_IFL_* flags to control behaviour * * Description: * Issue a discard request for the sectors in question. */ int blkdev_issue_discard(struct block_device *bdev, sector_t sector, sector_t nr_sects, gfp_t gfp_mask, unsigned long flags) { DECLARE_COMPLETION_ONSTACK(wait); struct request_queue *q = bdev_get_queue(bdev); int type = REQ_WRITE | REQ_DISCARD; struct bio_batch bb; struct bio *bio; int ret = 0; struct blk_plug plug; if (!q) return -ENXIO; if (!blk_queue_discard(q)) return -EOPNOTSUPP; if (flags & BLKDEV_DISCARD_SECURE) { if (!blk_queue_secdiscard(q)) return -EOPNOTSUPP; type |= REQ_SECURE; } atomic_set(&bb.done, 1); bb.error = 0; bb.wait = &wait; blk_start_plug(&plug); while (nr_sects) { unsigned int req_sects; sector_t end_sect; bio = bio_alloc(gfp_mask, 1); if (!bio) { ret = -ENOMEM; break; } req_sects = min_t(sector_t, nr_sects, MAX_BIO_SECTORS); end_sect = sector + req_sects; bio->bi_iter.bi_sector = sector; bio->bi_end_io = bio_batch_end_io; bio->bi_bdev = bdev; bio->bi_private = &bb; bio->bi_iter.bi_size = req_sects << 9; nr_sects -= req_sects; sector = end_sect; atomic_inc(&bb.done); submit_bio(type, bio); /* * We can loop for a long time in here, if someone does * full device discards (like mkfs). Be nice and allow * us to schedule out to avoid softlocking if preempt * is disabled. */ cond_resched(); } blk_finish_plug(&plug); /* Wait for bios in-flight */ if (!atomic_dec_and_test(&bb.done)) wait_for_completion_io(&wait); if (bb.error) return bb.error; return ret; }