static void __loop_update_dio(struct loop_device *lo, bool dio) { struct file *file = lo->lo_backing_file; struct address_space *mapping = file->f_mapping; struct inode *inode = mapping->host; unsigned short sb_bsize = 0; unsigned dio_align = 0; bool use_dio; if (inode->i_sb->s_bdev) { sb_bsize = bdev_logical_block_size(inode->i_sb->s_bdev); dio_align = sb_bsize - 1; } /* * We support direct I/O only if lo_offset is aligned with the * logical I/O size of backing device, and the logical block * size of loop is bigger than the backing device's and the loop * needn't transform transfer. * * TODO: the above condition may be loosed in the future, and * direct I/O may be switched runtime at that time because most * of requests in sane appplications should be PAGE_SIZE algined */ if (dio) { if (queue_logical_block_size(lo->lo_queue) >= sb_bsize && !(lo->lo_offset & dio_align) && mapping->a_ops->direct_IO && !lo->transfer) use_dio = true; else use_dio = false; } else { use_dio = false; } if (lo->use_dio == use_dio) return; /* flush dirty pages before changing direct IO */ vfs_fsync(file, 0); /* * The flag of LO_FLAGS_DIRECT_IO is handled similarly with * LO_FLAGS_READ_ONLY, both are set from kernel, and losetup * will get updated by ioctl(LOOP_GET_STATUS) */ blk_mq_freeze_queue(lo->lo_queue); lo->use_dio = use_dio; if (use_dio) lo->lo_flags |= LO_FLAGS_DIRECT_IO; else lo->lo_flags &= ~LO_FLAGS_DIRECT_IO; blk_mq_unfreeze_queue(lo->lo_queue); }
/** * blk_revalidate_disk_zones - (re)allocate and initialize zone bitmaps * @disk: Target disk * * Helper function for low-level device drivers to (re) allocate and initialize * a disk request queue zone bitmaps. This functions should normally be called * within the disk ->revalidate method. For BIO based queues, no zone bitmap * is allocated. */ int blk_revalidate_disk_zones(struct gendisk *disk) { struct request_queue *q = disk->queue; unsigned int nr_zones = __blkdev_nr_zones(q, get_capacity(disk)); unsigned long *seq_zones_wlock = NULL, *seq_zones_bitmap = NULL; unsigned int i, rep_nr_zones = 0, z = 0, nrz; struct blk_zone *zones = NULL; sector_t sector = 0; int ret = 0; /* * BIO based queues do not use a scheduler so only q->nr_zones * needs to be updated so that the sysfs exposed value is correct. */ if (!queue_is_rq_based(q)) { q->nr_zones = nr_zones; return 0; } if (!blk_queue_is_zoned(q) || !nr_zones) { nr_zones = 0; goto update; } /* Allocate bitmaps */ ret = -ENOMEM; seq_zones_wlock = blk_alloc_zone_bitmap(q->node, nr_zones); if (!seq_zones_wlock) goto out; seq_zones_bitmap = blk_alloc_zone_bitmap(q->node, nr_zones); if (!seq_zones_bitmap) goto out; /* Get zone information and initialize seq_zones_bitmap */ rep_nr_zones = nr_zones; zones = blk_alloc_zones(q->node, &rep_nr_zones); if (!zones) goto out; while (z < nr_zones) { nrz = min(nr_zones - z, rep_nr_zones); ret = blk_report_zones(disk, sector, zones, &nrz, GFP_NOIO); if (ret) goto out; if (!nrz) break; for (i = 0; i < nrz; i++) { if (zones[i].type != BLK_ZONE_TYPE_CONVENTIONAL) set_bit(z, seq_zones_bitmap); z++; } sector += nrz * blk_queue_zone_sectors(q); } if (WARN_ON(z != nr_zones)) { ret = -EIO; goto out; } update: /* * Install the new bitmaps, making sure the queue is stopped and * all I/Os are completed (i.e. a scheduler is not referencing the * bitmaps). */ blk_mq_freeze_queue(q); q->nr_zones = nr_zones; swap(q->seq_zones_wlock, seq_zones_wlock); swap(q->seq_zones_bitmap, seq_zones_bitmap); blk_mq_unfreeze_queue(q); out: free_pages((unsigned long)zones, get_order(rep_nr_zones * sizeof(struct blk_zone))); kfree(seq_zones_wlock); kfree(seq_zones_bitmap); if (ret) { pr_warn("%s: failed to revalidate zones\n", disk->disk_name); blk_mq_freeze_queue(q); blk_queue_free_zone_bitmaps(q); blk_mq_unfreeze_queue(q); } return ret; }