LCOV - code coverage report
Current view: top level - drivers/block - virtio_blk.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 297 0.0 %
Date: 2014-02-18 Functions: 0 22 0.0 %
Branches: 0 141 0.0 %

           Branch data     Line data    Source code
       1                 :            : //#define DEBUG
       2                 :            : #include <linux/spinlock.h>
       3                 :            : #include <linux/slab.h>
       4                 :            : #include <linux/blkdev.h>
       5                 :            : #include <linux/hdreg.h>
       6                 :            : #include <linux/module.h>
       7                 :            : #include <linux/mutex.h>
       8                 :            : #include <linux/virtio.h>
       9                 :            : #include <linux/virtio_blk.h>
      10                 :            : #include <linux/scatterlist.h>
      11                 :            : #include <linux/string_helpers.h>
      12                 :            : #include <scsi/scsi_cmnd.h>
      13                 :            : #include <linux/idr.h>
      14                 :            : #include <linux/blk-mq.h>
      15                 :            : #include <linux/numa.h>
      16                 :            : 
      17                 :            : #define PART_BITS 4
      18                 :            : 
      19                 :            : static int major;
      20                 :            : static DEFINE_IDA(vd_index_ida);
      21                 :            : 
      22                 :            : static struct workqueue_struct *virtblk_wq;
      23                 :            : 
      24                 :            : struct virtio_blk
      25                 :            : {
      26                 :            :         struct virtio_device *vdev;
      27                 :            :         struct virtqueue *vq;
      28                 :            :         spinlock_t vq_lock;
      29                 :            : 
      30                 :            :         /* The disk structure for the kernel. */
      31                 :            :         struct gendisk *disk;
      32                 :            : 
      33                 :            :         /* Process context for config space updates */
      34                 :            :         struct work_struct config_work;
      35                 :            : 
      36                 :            :         /* Lock for config space updates */
      37                 :            :         struct mutex config_lock;
      38                 :            : 
      39                 :            :         /* enable config space updates */
      40                 :            :         bool config_enable;
      41                 :            : 
      42                 :            :         /* What host tells us, plus 2 for header & tailer. */
      43                 :            :         unsigned int sg_elems;
      44                 :            : 
      45                 :            :         /* Ida index - used to track minor number allocations. */
      46                 :            :         int index;
      47                 :            : };
      48                 :            : 
      49                 :            : struct virtblk_req
      50                 :            : {
      51                 :            :         struct request *req;
      52                 :            :         struct virtio_blk_outhdr out_hdr;
      53                 :            :         struct virtio_scsi_inhdr in_hdr;
      54                 :            :         u8 status;
      55                 :            :         struct scatterlist sg[];
      56                 :            : };
      57                 :            : 
      58                 :            : static inline int virtblk_result(struct virtblk_req *vbr)
      59                 :            : {
      60      [ #  #  # ]:          0 :         switch (vbr->status) {
      61                 :            :         case VIRTIO_BLK_S_OK:
      62                 :            :                 return 0;
      63                 :            :         case VIRTIO_BLK_S_UNSUPP:
      64                 :            :                 return -ENOTTY;
      65                 :            :         default:
      66                 :            :                 return -EIO;
      67                 :            :         }
      68                 :            : }
      69                 :            : 
      70                 :          0 : static int __virtblk_add_req(struct virtqueue *vq,
      71                 :            :                              struct virtblk_req *vbr,
      72                 :            :                              struct scatterlist *data_sg,
      73                 :            :                              bool have_data)
      74                 :            : {
      75                 :            :         struct scatterlist hdr, status, cmd, sense, inhdr, *sgs[6];
      76                 :            :         unsigned int num_out = 0, num_in = 0;
      77                 :          0 :         int type = vbr->out_hdr.type & ~VIRTIO_BLK_T_OUT;
      78                 :            : 
      79                 :          0 :         sg_init_one(&hdr, &vbr->out_hdr, sizeof(vbr->out_hdr));
      80                 :          0 :         sgs[num_out++] = &hdr;
      81                 :            : 
      82                 :            :         /*
      83                 :            :          * If this is a packet command we need a couple of additional headers.
      84                 :            :          * Behind the normal outhdr we put a segment with the scsi command
      85                 :            :          * block, and before the normal inhdr we put the sense data and the
      86                 :            :          * inhdr with additional status information.
      87                 :            :          */
      88         [ #  # ]:          0 :         if (type == VIRTIO_BLK_T_SCSI_CMD) {
      89                 :          0 :                 sg_init_one(&cmd, vbr->req->cmd, vbr->req->cmd_len);
      90                 :          0 :                 sgs[num_out++] = &cmd;
      91                 :            :         }
      92                 :            : 
      93         [ #  # ]:          0 :         if (have_data) {
      94         [ #  # ]:          0 :                 if (vbr->out_hdr.type & VIRTIO_BLK_T_OUT)
      95                 :          0 :                         sgs[num_out++] = data_sg;
      96                 :            :                 else
      97                 :          0 :                         sgs[num_out + num_in++] = data_sg;
      98                 :            :         }
      99                 :            : 
     100         [ #  # ]:          0 :         if (type == VIRTIO_BLK_T_SCSI_CMD) {
     101                 :          0 :                 sg_init_one(&sense, vbr->req->sense, SCSI_SENSE_BUFFERSIZE);
     102                 :          0 :                 sgs[num_out + num_in++] = &sense;
     103                 :          0 :                 sg_init_one(&inhdr, &vbr->in_hdr, sizeof(vbr->in_hdr));
     104                 :          0 :                 sgs[num_out + num_in++] = &inhdr;
     105                 :            :         }
     106                 :            : 
     107                 :          0 :         sg_init_one(&status, &vbr->status, sizeof(vbr->status));
     108                 :          0 :         sgs[num_out + num_in++] = &status;
     109                 :            : 
     110                 :          0 :         return virtqueue_add_sgs(vq, sgs, num_out, num_in, vbr, GFP_ATOMIC);
     111                 :            : }
     112                 :            : 
     113                 :            : static inline void virtblk_request_done(struct virtblk_req *vbr)
     114                 :            : {
     115                 :          0 :         struct request *req = vbr->req;
     116                 :            :         int error = virtblk_result(vbr);
     117                 :            : 
     118         [ #  # ]:          0 :         if (req->cmd_type == REQ_TYPE_BLOCK_PC) {
     119                 :          0 :                 req->resid_len = vbr->in_hdr.residual;
     120                 :          0 :                 req->sense_len = vbr->in_hdr.sense_len;
     121                 :          0 :                 req->errors = vbr->in_hdr.errors;
     122         [ #  # ]:          0 :         } else if (req->cmd_type == REQ_TYPE_SPECIAL) {
     123                 :          0 :                 req->errors = (error != 0);
     124                 :            :         }
     125                 :            : 
     126                 :          0 :         blk_mq_end_io(req, error);
     127                 :            : }
     128                 :            : 
     129                 :          0 : static void virtblk_done(struct virtqueue *vq)
     130                 :            : {
     131                 :          0 :         struct virtio_blk *vblk = vq->vdev->priv;
     132                 :            :         bool req_done = false;
     133                 :            :         struct virtblk_req *vbr;
     134                 :            :         unsigned long flags;
     135                 :            :         unsigned int len;
     136                 :            : 
     137                 :          0 :         spin_lock_irqsave(&vblk->vq_lock, flags);
     138                 :            :         do {
     139                 :          0 :                 virtqueue_disable_cb(vq);
     140         [ #  # ]:          0 :                 while ((vbr = virtqueue_get_buf(vblk->vq, &len)) != NULL) {
     141                 :            :                         virtblk_request_done(vbr);
     142                 :            :                         req_done = true;
     143                 :            :                 }
     144         [ #  # ]:          0 :                 if (unlikely(virtqueue_is_broken(vq)))
     145                 :            :                         break;
     146         [ #  # ]:          0 :         } while (!virtqueue_enable_cb(vq));
     147                 :            :         spin_unlock_irqrestore(&vblk->vq_lock, flags);
     148                 :            : 
     149                 :            :         /* In case queue is stopped waiting for more buffers. */
     150         [ #  # ]:          0 :         if (req_done)
     151                 :          0 :                 blk_mq_start_stopped_hw_queues(vblk->disk->queue);
     152                 :          0 : }
     153                 :            : 
     154                 :          0 : static int virtio_queue_rq(struct blk_mq_hw_ctx *hctx, struct request *req)
     155                 :            : {
     156                 :          0 :         struct virtio_blk *vblk = hctx->queue->queuedata;
     157                 :          0 :         struct virtblk_req *vbr = req->special;
     158                 :            :         unsigned long flags;
     159                 :            :         unsigned int num;
     160                 :          0 :         const bool last = (req->cmd_flags & REQ_END) != 0;
     161                 :            : 
     162         [ #  # ]:          0 :         BUG_ON(req->nr_phys_segments + 2 > vblk->sg_elems);
     163                 :            : 
     164                 :          0 :         vbr->req = req;
     165         [ #  # ]:          0 :         if (req->cmd_flags & REQ_FLUSH) {
     166                 :          0 :                 vbr->out_hdr.type = VIRTIO_BLK_T_FLUSH;
     167                 :          0 :                 vbr->out_hdr.sector = 0;
     168                 :          0 :                 vbr->out_hdr.ioprio = req_get_ioprio(vbr->req);
     169                 :            :         } else {
     170   [ #  #  #  # ]:          0 :                 switch (req->cmd_type) {
     171                 :            :                 case REQ_TYPE_FS:
     172                 :          0 :                         vbr->out_hdr.type = 0;
     173                 :          0 :                         vbr->out_hdr.sector = blk_rq_pos(vbr->req);
     174                 :          0 :                         vbr->out_hdr.ioprio = req_get_ioprio(vbr->req);
     175                 :          0 :                         break;
     176                 :            :                 case REQ_TYPE_BLOCK_PC:
     177                 :          0 :                         vbr->out_hdr.type = VIRTIO_BLK_T_SCSI_CMD;
     178                 :          0 :                         vbr->out_hdr.sector = 0;
     179                 :          0 :                         vbr->out_hdr.ioprio = req_get_ioprio(vbr->req);
     180                 :          0 :                         break;
     181                 :            :                 case REQ_TYPE_SPECIAL:
     182                 :          0 :                         vbr->out_hdr.type = VIRTIO_BLK_T_GET_ID;
     183                 :          0 :                         vbr->out_hdr.sector = 0;
     184                 :          0 :                         vbr->out_hdr.ioprio = req_get_ioprio(vbr->req);
     185                 :          0 :                         break;
     186                 :            :                 default:
     187                 :            :                         /* We don't put anything else in the queue. */
     188                 :          0 :                         BUG();
     189                 :            :                 }
     190                 :            :         }
     191                 :            : 
     192                 :          0 :         num = blk_rq_map_sg(hctx->queue, vbr->req, vbr->sg);
     193         [ #  # ]:          0 :         if (num) {
     194         [ #  # ]:          0 :                 if (rq_data_dir(vbr->req) == WRITE)
     195                 :          0 :                         vbr->out_hdr.type |= VIRTIO_BLK_T_OUT;
     196                 :            :                 else
     197                 :            :                         vbr->out_hdr.type |= VIRTIO_BLK_T_IN;
     198                 :            :         }
     199                 :            : 
     200                 :          0 :         spin_lock_irqsave(&vblk->vq_lock, flags);
     201         [ #  # ]:          0 :         if (__virtblk_add_req(vblk->vq, vbr, vbr->sg, num) < 0) {
     202                 :          0 :                 virtqueue_kick(vblk->vq);
     203                 :            :                 spin_unlock_irqrestore(&vblk->vq_lock, flags);
     204                 :          0 :                 blk_mq_stop_hw_queue(hctx);
     205                 :          0 :                 return BLK_MQ_RQ_QUEUE_BUSY;
     206                 :            :         }
     207                 :            : 
     208         [ #  # ]:          0 :         if (last)
     209                 :          0 :                 virtqueue_kick(vblk->vq);
     210                 :            : 
     211                 :            :         spin_unlock_irqrestore(&vblk->vq_lock, flags);
     212                 :          0 :         return BLK_MQ_RQ_QUEUE_OK;
     213                 :            : }
     214                 :            : 
     215                 :            : /* return id (s/n) string for *disk to *id_str
     216                 :            :  */
     217                 :          0 : static int virtblk_get_id(struct gendisk *disk, char *id_str)
     218                 :            : {
     219                 :          0 :         struct virtio_blk *vblk = disk->private_data;
     220                 :            :         struct request *req;
     221                 :            :         struct bio *bio;
     222                 :            :         int err;
     223                 :            : 
     224                 :          0 :         bio = bio_map_kern(vblk->disk->queue, id_str, VIRTIO_BLK_ID_BYTES,
     225                 :            :                            GFP_KERNEL);
     226         [ #  # ]:          0 :         if (IS_ERR(bio))
     227                 :            :                 return PTR_ERR(bio);
     228                 :            : 
     229                 :          0 :         req = blk_make_request(vblk->disk->queue, bio, GFP_KERNEL);
     230         [ #  # ]:          0 :         if (IS_ERR(req)) {
     231                 :          0 :                 bio_put(bio);
     232                 :            :                 return PTR_ERR(req);
     233                 :            :         }
     234                 :            : 
     235                 :          0 :         req->cmd_type = REQ_TYPE_SPECIAL;
     236                 :          0 :         err = blk_execute_rq(vblk->disk->queue, vblk->disk, req, false);
     237                 :          0 :         blk_put_request(req);
     238                 :            : 
     239                 :            :         return err;
     240                 :            : }
     241                 :            : 
     242                 :          0 : static int virtblk_ioctl(struct block_device *bdev, fmode_t mode,
     243                 :            :                              unsigned int cmd, unsigned long data)
     244                 :            : {
     245                 :          0 :         struct gendisk *disk = bdev->bd_disk;
     246                 :          0 :         struct virtio_blk *vblk = disk->private_data;
     247                 :            : 
     248                 :            :         /*
     249                 :            :          * Only allow the generic SCSI ioctls if the host can support it.
     250                 :            :          */
     251         [ #  # ]:          0 :         if (!virtio_has_feature(vblk->vdev, VIRTIO_BLK_F_SCSI))
     252                 :            :                 return -ENOTTY;
     253                 :            : 
     254                 :          0 :         return scsi_cmd_blk_ioctl(bdev, mode, cmd,
     255                 :            :                                   (void __user *)data);
     256                 :            : }
     257                 :            : 
     258                 :            : /* We provide getgeo only to please some old bootloader/partitioning tools */
     259                 :          0 : static int virtblk_getgeo(struct block_device *bd, struct hd_geometry *geo)
     260                 :            : {
     261                 :          0 :         struct virtio_blk *vblk = bd->bd_disk->private_data;
     262                 :            : 
     263                 :            :         /* see if the host passed in geometry config */
     264         [ #  # ]:          0 :         if (virtio_has_feature(vblk->vdev, VIRTIO_BLK_F_GEOMETRY)) {
     265                 :          0 :                 virtio_cread(vblk->vdev, struct virtio_blk_config,
     266                 :            :                              geometry.cylinders, &geo->cylinders);
     267                 :          0 :                 virtio_cread(vblk->vdev, struct virtio_blk_config,
     268                 :            :                              geometry.heads, &geo->heads);
     269                 :          0 :                 virtio_cread(vblk->vdev, struct virtio_blk_config,
     270                 :            :                              geometry.sectors, &geo->sectors);
     271                 :            :         } else {
     272                 :            :                 /* some standard values, similar to sd */
     273                 :          0 :                 geo->heads = 1 << 6;
     274                 :          0 :                 geo->sectors = 1 << 5;
     275                 :          0 :                 geo->cylinders = get_capacity(bd->bd_disk) >> 11;
     276                 :            :         }
     277                 :          0 :         return 0;
     278                 :            : }
     279                 :            : 
     280                 :            : static const struct block_device_operations virtblk_fops = {
     281                 :            :         .ioctl  = virtblk_ioctl,
     282                 :            :         .owner  = THIS_MODULE,
     283                 :            :         .getgeo = virtblk_getgeo,
     284                 :            : };
     285                 :            : 
     286                 :            : static int index_to_minor(int index)
     287                 :            : {
     288                 :          0 :         return index << PART_BITS;
     289                 :            : }
     290                 :            : 
     291                 :            : static int minor_to_index(int minor)
     292                 :            : {
     293                 :            :         return minor >> PART_BITS;
     294                 :            : }
     295                 :            : 
     296                 :          0 : static ssize_t virtblk_serial_show(struct device *dev,
     297                 :            :                                 struct device_attribute *attr, char *buf)
     298                 :            : {
     299                 :          0 :         struct gendisk *disk = dev_to_disk(dev);
     300                 :            :         int err;
     301                 :            : 
     302                 :            :         /* sysfs gives us a PAGE_SIZE buffer */
     303                 :            :         BUILD_BUG_ON(PAGE_SIZE < VIRTIO_BLK_ID_BYTES);
     304                 :            : 
     305                 :          0 :         buf[VIRTIO_BLK_ID_BYTES] = '\0';
     306                 :          0 :         err = virtblk_get_id(disk, buf);
     307         [ #  # ]:          0 :         if (!err)
     308                 :          0 :                 return strlen(buf);
     309                 :            : 
     310         [ #  # ]:          0 :         if (err == -EIO) /* Unsupported? Make it empty. */
     311                 :            :                 return 0;
     312                 :            : 
     313                 :          0 :         return err;
     314                 :            : }
     315                 :            : DEVICE_ATTR(serial, S_IRUGO, virtblk_serial_show, NULL);
     316                 :            : 
     317                 :          0 : static void virtblk_config_changed_work(struct work_struct *work)
     318                 :            : {
     319                 :            :         struct virtio_blk *vblk =
     320                 :            :                 container_of(work, struct virtio_blk, config_work);
     321                 :          0 :         struct virtio_device *vdev = vblk->vdev;
     322                 :          0 :         struct request_queue *q = vblk->disk->queue;
     323                 :            :         char cap_str_2[10], cap_str_10[10];
     324                 :          0 :         char *envp[] = { "RESIZE=1", NULL };
     325                 :            :         u64 capacity, size;
     326                 :            : 
     327                 :          0 :         mutex_lock(&vblk->config_lock);
     328         [ #  # ]:          0 :         if (!vblk->config_enable)
     329                 :            :                 goto done;
     330                 :            : 
     331                 :            :         /* Host must always specify the capacity. */
     332                 :            :         virtio_cread(vdev, struct virtio_blk_config, capacity, &capacity);
     333                 :            : 
     334                 :            :         /* If capacity is too big, truncate with warning. */
     335                 :            :         if ((sector_t)capacity != capacity) {
     336                 :            :                 dev_warn(&vdev->dev, "Capacity %llu too large: truncating\n",
     337                 :            :                          (unsigned long long)capacity);
     338                 :            :                 capacity = (sector_t)-1;
     339                 :            :         }
     340                 :            : 
     341                 :          0 :         size = capacity * queue_logical_block_size(q);
     342                 :          0 :         string_get_size(size, STRING_UNITS_2, cap_str_2, sizeof(cap_str_2));
     343                 :          0 :         string_get_size(size, STRING_UNITS_10, cap_str_10, sizeof(cap_str_10));
     344                 :            : 
     345                 :          0 :         dev_notice(&vdev->dev,
     346                 :            :                   "new size: %llu %d-byte logical blocks (%s/%s)\n",
     347                 :            :                   (unsigned long long)capacity,
     348                 :            :                   queue_logical_block_size(q),
     349                 :            :                   cap_str_10, cap_str_2);
     350                 :            : 
     351                 :          0 :         set_capacity(vblk->disk, capacity);
     352                 :          0 :         revalidate_disk(vblk->disk);
     353                 :          0 :         kobject_uevent_env(&disk_to_dev(vblk->disk)->kobj, KOBJ_CHANGE, envp);
     354                 :            : done:
     355                 :          0 :         mutex_unlock(&vblk->config_lock);
     356                 :          0 : }
     357                 :            : 
     358                 :          0 : static void virtblk_config_changed(struct virtio_device *vdev)
     359                 :            : {
     360                 :          0 :         struct virtio_blk *vblk = vdev->priv;
     361                 :            : 
     362                 :          0 :         queue_work(virtblk_wq, &vblk->config_work);
     363                 :          0 : }
     364                 :            : 
     365                 :          0 : static int init_vq(struct virtio_blk *vblk)
     366                 :            : {
     367                 :            :         int err = 0;
     368                 :            : 
     369                 :            :         /* We expect one virtqueue, for output. */
     370                 :          0 :         vblk->vq = virtio_find_single_vq(vblk->vdev, virtblk_done, "requests");
     371         [ #  # ]:          0 :         if (IS_ERR(vblk->vq))
     372                 :            :                 err = PTR_ERR(vblk->vq);
     373                 :            : 
     374                 :          0 :         return err;
     375                 :            : }
     376                 :            : 
     377                 :            : /*
     378                 :            :  * Legacy naming scheme used for virtio devices.  We are stuck with it for
     379                 :            :  * virtio blk but don't ever use it for any new driver.
     380                 :            :  */
     381                 :          0 : static int virtblk_name_format(char *prefix, int index, char *buf, int buflen)
     382                 :            : {
     383                 :            :         const int base = 'z' - 'a' + 1;
     384                 :          0 :         char *begin = buf + strlen(prefix);
     385                 :          0 :         char *end = buf + buflen;
     386                 :            :         char *p;
     387                 :            :         int unit;
     388                 :            : 
     389                 :          0 :         p = end - 1;
     390                 :          0 :         *p = '\0';
     391                 :            :         unit = base;
     392                 :            :         do {
     393         [ #  # ]:          0 :                 if (p == begin)
     394                 :            :                         return -EINVAL;
     395                 :          0 :                 *--p = 'a' + (index % unit);
     396                 :          0 :                 index = (index / unit) - 1;
     397         [ #  # ]:          0 :         } while (index >= 0);
     398                 :            : 
     399                 :          0 :         memmove(begin, p, end - p);
     400                 :          0 :         memcpy(buf, prefix, strlen(prefix));
     401                 :            : 
     402                 :          0 :         return 0;
     403                 :            : }
     404                 :            : 
     405                 :          0 : static int virtblk_get_cache_mode(struct virtio_device *vdev)
     406                 :            : {
     407                 :            :         u8 writeback;
     408                 :            :         int err;
     409                 :            : 
     410         [ #  # ]:          0 :         err = virtio_cread_feature(vdev, VIRTIO_BLK_F_CONFIG_WCE,
     411                 :            :                                    struct virtio_blk_config, wce,
     412                 :            :                                    &writeback);
     413         [ #  # ]:          0 :         if (err)
     414                 :          0 :                 writeback = virtio_has_feature(vdev, VIRTIO_BLK_F_WCE);
     415                 :            : 
     416                 :          0 :         return writeback;
     417                 :            : }
     418                 :            : 
     419                 :          0 : static void virtblk_update_cache_mode(struct virtio_device *vdev)
     420                 :            : {
     421                 :          0 :         u8 writeback = virtblk_get_cache_mode(vdev);
     422                 :          0 :         struct virtio_blk *vblk = vdev->priv;
     423                 :            : 
     424         [ #  # ]:          0 :         if (writeback)
     425                 :          0 :                 blk_queue_flush(vblk->disk->queue, REQ_FLUSH);
     426                 :            :         else
     427                 :          0 :                 blk_queue_flush(vblk->disk->queue, 0);
     428                 :            : 
     429                 :          0 :         revalidate_disk(vblk->disk);
     430                 :          0 : }
     431                 :            : 
     432                 :            : static const char *const virtblk_cache_types[] = {
     433                 :            :         "write through", "write back"
     434                 :            : };
     435                 :            : 
     436                 :            : static ssize_t
     437                 :          0 : virtblk_cache_type_store(struct device *dev, struct device_attribute *attr,
     438                 :            :                          const char *buf, size_t count)
     439                 :            : {
     440                 :            :         struct gendisk *disk = dev_to_disk(dev);
     441                 :          0 :         struct virtio_blk *vblk = disk->private_data;
     442                 :          0 :         struct virtio_device *vdev = vblk->vdev;
     443                 :            :         int i;
     444                 :            : 
     445         [ #  # ]:          0 :         BUG_ON(!virtio_has_feature(vblk->vdev, VIRTIO_BLK_F_CONFIG_WCE));
     446         [ #  # ]:          0 :         for (i = ARRAY_SIZE(virtblk_cache_types); --i >= 0; )
     447         [ #  # ]:          0 :                 if (sysfs_streq(buf, virtblk_cache_types[i]))
     448                 :            :                         break;
     449                 :            : 
     450         [ #  # ]:          0 :         if (i < 0)
     451                 :            :                 return -EINVAL;
     452                 :            : 
     453                 :          0 :         virtio_cwrite8(vdev, offsetof(struct virtio_blk_config, wce), i);
     454                 :          0 :         virtblk_update_cache_mode(vdev);
     455                 :          0 :         return count;
     456                 :            : }
     457                 :            : 
     458                 :            : static ssize_t
     459                 :          0 : virtblk_cache_type_show(struct device *dev, struct device_attribute *attr,
     460                 :            :                          char *buf)
     461                 :            : {
     462                 :            :         struct gendisk *disk = dev_to_disk(dev);
     463                 :          0 :         struct virtio_blk *vblk = disk->private_data;
     464                 :          0 :         u8 writeback = virtblk_get_cache_mode(vblk->vdev);
     465                 :            : 
     466         [ #  # ]:          0 :         BUG_ON(writeback >= ARRAY_SIZE(virtblk_cache_types));
     467                 :          0 :         return snprintf(buf, 40, "%s\n", virtblk_cache_types[writeback]);
     468                 :            : }
     469                 :            : 
     470                 :            : static const struct device_attribute dev_attr_cache_type_ro =
     471                 :            :         __ATTR(cache_type, S_IRUGO,
     472                 :            :                virtblk_cache_type_show, NULL);
     473                 :            : static const struct device_attribute dev_attr_cache_type_rw =
     474                 :            :         __ATTR(cache_type, S_IRUGO|S_IWUSR,
     475                 :            :                virtblk_cache_type_show, virtblk_cache_type_store);
     476                 :            : 
     477                 :            : static struct blk_mq_ops virtio_mq_ops = {
     478                 :            :         .queue_rq       = virtio_queue_rq,
     479                 :            :         .map_queue      = blk_mq_map_queue,
     480                 :            :         .alloc_hctx     = blk_mq_alloc_single_hw_queue,
     481                 :            :         .free_hctx      = blk_mq_free_single_hw_queue,
     482                 :            : };
     483                 :            : 
     484                 :            : static struct blk_mq_reg virtio_mq_reg = {
     485                 :            :         .ops            = &virtio_mq_ops,
     486                 :            :         .nr_hw_queues   = 1,
     487                 :            :         .queue_depth    = 64,
     488                 :            :         .numa_node      = NUMA_NO_NODE,
     489                 :            :         .flags          = BLK_MQ_F_SHOULD_MERGE,
     490                 :            : };
     491                 :            : 
     492                 :          0 : static void virtblk_init_vbr(void *data, struct blk_mq_hw_ctx *hctx,
     493                 :            :                              struct request *rq, unsigned int nr)
     494                 :            : {
     495                 :            :         struct virtio_blk *vblk = data;
     496                 :          0 :         struct virtblk_req *vbr = rq->special;
     497                 :            : 
     498                 :          0 :         sg_init_table(vbr->sg, vblk->sg_elems);
     499                 :          0 : }
     500                 :            : 
     501                 :          0 : static int virtblk_probe(struct virtio_device *vdev)
     502                 :            : {
     503                 :          0 :         struct virtio_blk *vblk;
     504                 :            :         struct request_queue *q;
     505                 :            :         int err, index;
     506                 :            : 
     507                 :            :         u64 cap;
     508                 :            :         u32 v, blk_size, sg_elems, opt_io_size;
     509                 :            :         u16 min_io_size;
     510                 :            :         u8 physical_block_exp, alignment_offset;
     511                 :            : 
     512                 :          0 :         err = ida_simple_get(&vd_index_ida, 0, minor_to_index(1 << MINORBITS),
     513                 :            :                              GFP_KERNEL);
     514         [ #  # ]:          0 :         if (err < 0)
     515                 :            :                 goto out;
     516                 :            :         index = err;
     517                 :            : 
     518                 :            :         /* We need to know how many segments before we allocate. */
     519         [ #  # ]:          0 :         err = virtio_cread_feature(vdev, VIRTIO_BLK_F_SEG_MAX,
     520                 :            :                                    struct virtio_blk_config, seg_max,
     521                 :            :                                    &sg_elems);
     522                 :            : 
     523                 :            :         /* We need at least one SG element, whatever they say. */
     524 [ #  # ][ #  # ]:          0 :         if (err || !sg_elems)
     525                 :            :                 sg_elems = 1;
     526                 :            : 
     527                 :            :         /* We need an extra sg elements at head and tail. */
     528                 :          0 :         sg_elems += 2;
     529                 :          0 :         vdev->priv = vblk = kmalloc(sizeof(*vblk), GFP_KERNEL);
     530         [ #  # ]:          0 :         if (!vblk) {
     531                 :            :                 err = -ENOMEM;
     532                 :            :                 goto out_free_index;
     533                 :            :         }
     534                 :            : 
     535                 :          0 :         vblk->vdev = vdev;
     536                 :          0 :         vblk->sg_elems = sg_elems;
     537                 :          0 :         mutex_init(&vblk->config_lock);
     538                 :            : 
     539                 :          0 :         INIT_WORK(&vblk->config_work, virtblk_config_changed_work);
     540                 :          0 :         vblk->config_enable = true;
     541                 :            : 
     542                 :          0 :         err = init_vq(vblk);
     543         [ #  # ]:          0 :         if (err)
     544                 :            :                 goto out_free_vblk;
     545                 :          0 :         spin_lock_init(&vblk->vq_lock);
     546                 :            : 
     547                 :            :         /* FIXME: How many partitions?  How long is a piece of string? */
     548                 :          0 :         vblk->disk = alloc_disk(1 << PART_BITS);
     549         [ #  # ]:          0 :         if (!vblk->disk) {
     550                 :            :                 err = -ENOMEM;
     551                 :            :                 goto out_free_vq;
     552                 :            :         }
     553                 :            : 
     554                 :          0 :         virtio_mq_reg.cmd_size =
     555                 :          0 :                 sizeof(struct virtblk_req) +
     556                 :            :                 sizeof(struct scatterlist) * sg_elems;
     557                 :            : 
     558                 :          0 :         q = vblk->disk->queue = blk_mq_init_queue(&virtio_mq_reg, vblk);
     559         [ #  # ]:          0 :         if (!q) {
     560                 :            :                 err = -ENOMEM;
     561                 :            :                 goto out_put_disk;
     562                 :            :         }
     563                 :            : 
     564                 :          0 :         blk_mq_init_commands(q, virtblk_init_vbr, vblk);
     565                 :            : 
     566                 :          0 :         q->queuedata = vblk;
     567                 :            : 
     568                 :          0 :         virtblk_name_format("vd", index, vblk->disk->disk_name, DISK_NAME_LEN);
     569                 :            : 
     570                 :          0 :         vblk->disk->major = major;
     571                 :          0 :         vblk->disk->first_minor = index_to_minor(index);
     572                 :          0 :         vblk->disk->private_data = vblk;
     573                 :          0 :         vblk->disk->fops = &virtblk_fops;
     574                 :          0 :         vblk->disk->driverfs_dev = &vdev->dev;
     575                 :          0 :         vblk->index = index;
     576                 :            : 
     577                 :            :         /* configure queue flush support */
     578                 :          0 :         virtblk_update_cache_mode(vdev);
     579                 :            : 
     580                 :            :         /* If disk is read-only in the host, the guest should obey */
     581         [ #  # ]:          0 :         if (virtio_has_feature(vdev, VIRTIO_BLK_F_RO))
     582                 :          0 :                 set_disk_ro(vblk->disk, 1);
     583                 :            : 
     584                 :            :         /* Host must always specify the capacity. */
     585                 :            :         virtio_cread(vdev, struct virtio_blk_config, capacity, &cap);
     586                 :            : 
     587                 :            :         /* If capacity is too big, truncate with warning. */
     588                 :            :         if ((sector_t)cap != cap) {
     589                 :            :                 dev_warn(&vdev->dev, "Capacity %llu too large: truncating\n",
     590                 :            :                          (unsigned long long)cap);
     591                 :            :                 cap = (sector_t)-1;
     592                 :            :         }
     593                 :          0 :         set_capacity(vblk->disk, cap);
     594                 :            : 
     595                 :            :         /* We can handle whatever the host told us to handle. */
     596                 :          0 :         blk_queue_max_segments(q, vblk->sg_elems-2);
     597                 :            : 
     598                 :            :         /* No need to bounce any requests */
     599                 :          0 :         blk_queue_bounce_limit(q, BLK_BOUNCE_ANY);
     600                 :            : 
     601                 :            :         /* No real sector limit. */
     602                 :          0 :         blk_queue_max_hw_sectors(q, -1U);
     603                 :            : 
     604                 :            :         /* Host can optionally specify maximum segment size and number of
     605                 :            :          * segments. */
     606         [ #  # ]:          0 :         err = virtio_cread_feature(vdev, VIRTIO_BLK_F_SIZE_MAX,
     607                 :            :                                    struct virtio_blk_config, size_max, &v);
     608         [ #  # ]:          0 :         if (!err)
     609                 :          0 :                 blk_queue_max_segment_size(q, v);
     610                 :            :         else
     611                 :          0 :                 blk_queue_max_segment_size(q, -1U);
     612                 :            : 
     613                 :            :         /* Host can optionally specify the block size of the device */
     614         [ #  # ]:          0 :         err = virtio_cread_feature(vdev, VIRTIO_BLK_F_BLK_SIZE,
     615                 :            :                                    struct virtio_blk_config, blk_size,
     616                 :            :                                    &blk_size);
     617         [ #  # ]:          0 :         if (!err)
     618                 :          0 :                 blk_queue_logical_block_size(q, blk_size);
     619                 :            :         else
     620                 :          0 :                 blk_size = queue_logical_block_size(q);
     621                 :            : 
     622                 :            :         /* Use topology information if available */
     623         [ #  # ]:          0 :         err = virtio_cread_feature(vdev, VIRTIO_BLK_F_TOPOLOGY,
     624                 :            :                                    struct virtio_blk_config, physical_block_exp,
     625                 :            :                                    &physical_block_exp);
     626 [ #  # ][ #  # ]:          0 :         if (!err && physical_block_exp)
     627                 :          0 :                 blk_queue_physical_block_size(q,
     628                 :            :                                 blk_size * (1 << physical_block_exp));
     629                 :            : 
     630         [ #  # ]:          0 :         err = virtio_cread_feature(vdev, VIRTIO_BLK_F_TOPOLOGY,
     631                 :            :                                    struct virtio_blk_config, alignment_offset,
     632                 :            :                                    &alignment_offset);
     633 [ #  # ][ #  # ]:          0 :         if (!err && alignment_offset)
     634                 :          0 :                 blk_queue_alignment_offset(q, blk_size * alignment_offset);
     635                 :            : 
     636         [ #  # ]:          0 :         err = virtio_cread_feature(vdev, VIRTIO_BLK_F_TOPOLOGY,
     637                 :            :                                    struct virtio_blk_config, min_io_size,
     638                 :            :                                    &min_io_size);
     639 [ #  # ][ #  # ]:          0 :         if (!err && min_io_size)
     640                 :          0 :                 blk_queue_io_min(q, blk_size * min_io_size);
     641                 :            : 
     642         [ #  # ]:          0 :         err = virtio_cread_feature(vdev, VIRTIO_BLK_F_TOPOLOGY,
     643                 :            :                                    struct virtio_blk_config, opt_io_size,
     644                 :            :                                    &opt_io_size);
     645 [ #  # ][ #  # ]:          0 :         if (!err && opt_io_size)
     646                 :          0 :                 blk_queue_io_opt(q, blk_size * opt_io_size);
     647                 :            : 
     648                 :          0 :         add_disk(vblk->disk);
     649                 :          0 :         err = device_create_file(disk_to_dev(vblk->disk), &dev_attr_serial);
     650         [ #  # ]:          0 :         if (err)
     651                 :            :                 goto out_del_disk;
     652                 :            : 
     653         [ #  # ]:          0 :         if (virtio_has_feature(vdev, VIRTIO_BLK_F_CONFIG_WCE))
     654                 :          0 :                 err = device_create_file(disk_to_dev(vblk->disk),
     655                 :            :                                          &dev_attr_cache_type_rw);
     656                 :            :         else
     657                 :          0 :                 err = device_create_file(disk_to_dev(vblk->disk),
     658                 :            :                                          &dev_attr_cache_type_ro);
     659         [ #  # ]:          0 :         if (err)
     660                 :            :                 goto out_del_disk;
     661                 :            :         return 0;
     662                 :            : 
     663                 :            : out_del_disk:
     664                 :          0 :         del_gendisk(vblk->disk);
     665                 :          0 :         blk_cleanup_queue(vblk->disk->queue);
     666                 :            : out_put_disk:
     667                 :          0 :         put_disk(vblk->disk);
     668                 :            : out_free_vq:
     669                 :          0 :         vdev->config->del_vqs(vdev);
     670                 :            : out_free_vblk:
     671                 :          0 :         kfree(vblk);
     672                 :            : out_free_index:
     673                 :          0 :         ida_simple_remove(&vd_index_ida, index);
     674                 :            : out:
     675                 :          0 :         return err;
     676                 :            : }
     677                 :            : 
     678                 :          0 : static void virtblk_remove(struct virtio_device *vdev)
     679                 :            : {
     680                 :          0 :         struct virtio_blk *vblk = vdev->priv;
     681                 :          0 :         int index = vblk->index;
     682                 :            :         int refc;
     683                 :            : 
     684                 :            :         /* Prevent config work handler from accessing the device. */
     685                 :          0 :         mutex_lock(&vblk->config_lock);
     686                 :          0 :         vblk->config_enable = false;
     687                 :          0 :         mutex_unlock(&vblk->config_lock);
     688                 :            : 
     689                 :          0 :         del_gendisk(vblk->disk);
     690                 :          0 :         blk_cleanup_queue(vblk->disk->queue);
     691                 :            : 
     692                 :            :         /* Stop all the virtqueues. */
     693                 :          0 :         vdev->config->reset(vdev);
     694                 :            : 
     695                 :          0 :         flush_work(&vblk->config_work);
     696                 :            : 
     697                 :          0 :         refc = atomic_read(&disk_to_dev(vblk->disk)->kobj.kref.refcount);
     698                 :          0 :         put_disk(vblk->disk);
     699                 :          0 :         vdev->config->del_vqs(vdev);
     700                 :          0 :         kfree(vblk);
     701                 :            : 
     702                 :            :         /* Only free device id if we don't have any users */
     703         [ #  # ]:          0 :         if (refc == 1)
     704                 :          0 :                 ida_simple_remove(&vd_index_ida, index);
     705                 :          0 : }
     706                 :            : 
     707                 :            : #ifdef CONFIG_PM_SLEEP
     708                 :          0 : static int virtblk_freeze(struct virtio_device *vdev)
     709                 :            : {
     710                 :          0 :         struct virtio_blk *vblk = vdev->priv;
     711                 :            : 
     712                 :            :         /* Ensure we don't receive any more interrupts */
     713                 :          0 :         vdev->config->reset(vdev);
     714                 :            : 
     715                 :            :         /* Prevent config work handler from accessing the device. */
     716                 :          0 :         mutex_lock(&vblk->config_lock);
     717                 :          0 :         vblk->config_enable = false;
     718                 :          0 :         mutex_unlock(&vblk->config_lock);
     719                 :            : 
     720                 :          0 :         flush_work(&vblk->config_work);
     721                 :            : 
     722                 :          0 :         blk_mq_stop_hw_queues(vblk->disk->queue);
     723                 :            : 
     724                 :          0 :         vdev->config->del_vqs(vdev);
     725                 :          0 :         return 0;
     726                 :            : }
     727                 :            : 
     728                 :          0 : static int virtblk_restore(struct virtio_device *vdev)
     729                 :            : {
     730                 :          0 :         struct virtio_blk *vblk = vdev->priv;
     731                 :            :         int ret;
     732                 :            : 
     733                 :          0 :         vblk->config_enable = true;
     734                 :          0 :         ret = init_vq(vdev->priv);
     735         [ #  # ]:          0 :         if (!ret)
     736                 :          0 :                 blk_mq_start_stopped_hw_queues(vblk->disk->queue);
     737                 :            : 
     738                 :          0 :         return ret;
     739                 :            : }
     740                 :            : #endif
     741                 :            : 
     742                 :            : static const struct virtio_device_id id_table[] = {
     743                 :            :         { VIRTIO_ID_BLOCK, VIRTIO_DEV_ANY_ID },
     744                 :            :         { 0 },
     745                 :            : };
     746                 :            : 
     747                 :            : static unsigned int features[] = {
     748                 :            :         VIRTIO_BLK_F_SEG_MAX, VIRTIO_BLK_F_SIZE_MAX, VIRTIO_BLK_F_GEOMETRY,
     749                 :            :         VIRTIO_BLK_F_RO, VIRTIO_BLK_F_BLK_SIZE, VIRTIO_BLK_F_SCSI,
     750                 :            :         VIRTIO_BLK_F_WCE, VIRTIO_BLK_F_TOPOLOGY, VIRTIO_BLK_F_CONFIG_WCE
     751                 :            : };
     752                 :            : 
     753                 :            : static struct virtio_driver virtio_blk = {
     754                 :            :         .feature_table          = features,
     755                 :            :         .feature_table_size     = ARRAY_SIZE(features),
     756                 :            :         .driver.name            = KBUILD_MODNAME,
     757                 :            :         .driver.owner           = THIS_MODULE,
     758                 :            :         .id_table               = id_table,
     759                 :            :         .probe                  = virtblk_probe,
     760                 :            :         .remove                 = virtblk_remove,
     761                 :            :         .config_changed         = virtblk_config_changed,
     762                 :            : #ifdef CONFIG_PM_SLEEP
     763                 :            :         .freeze                 = virtblk_freeze,
     764                 :            :         .restore                = virtblk_restore,
     765                 :            : #endif
     766                 :            : };
     767                 :            : 
     768                 :          0 : static int __init init(void)
     769                 :            : {
     770                 :            :         int error;
     771                 :            : 
     772                 :          0 :         virtblk_wq = alloc_workqueue("virtio-blk", 0, 0);
     773         [ #  # ]:          0 :         if (!virtblk_wq)
     774                 :            :                 return -ENOMEM;
     775                 :            : 
     776                 :          0 :         major = register_blkdev(0, "virtblk");
     777         [ #  # ]:          0 :         if (major < 0) {
     778                 :            :                 error = major;
     779                 :            :                 goto out_destroy_workqueue;
     780                 :            :         }
     781                 :            : 
     782                 :          0 :         error = register_virtio_driver(&virtio_blk);
     783         [ #  # ]:          0 :         if (error)
     784                 :            :                 goto out_unregister_blkdev;
     785                 :            :         return 0;
     786                 :            : 
     787                 :            : out_unregister_blkdev:
     788                 :          0 :         unregister_blkdev(major, "virtblk");
     789                 :            : out_destroy_workqueue:
     790                 :          0 :         destroy_workqueue(virtblk_wq);
     791                 :          0 :         return error;
     792                 :            : }
     793                 :            : 
     794                 :          0 : static void __exit fini(void)
     795                 :            : {
     796                 :          0 :         unregister_blkdev(major, "virtblk");
     797                 :          0 :         unregister_virtio_driver(&virtio_blk);
     798                 :          0 :         destroy_workqueue(virtblk_wq);
     799                 :          0 : }
     800                 :            : module_init(init);
     801                 :            : module_exit(fini);
     802                 :            : 
     803                 :            : MODULE_DEVICE_TABLE(virtio, id_table);
     804                 :            : MODULE_DESCRIPTION("Virtio block driver");
     805                 :            : MODULE_LICENSE("GPL");

Generated by: LCOV version 1.9