Merge tag 'block-5.10-2020-10-24' of git://git.kernel.dk/linux-block
authorLinus Torvalds <torvalds@linux-foundation.org>
Sat, 24 Oct 2020 19:46:42 +0000 (12:46 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sat, 24 Oct 2020 19:46:42 +0000 (12:46 -0700)
Pull block fixes from Jens Axboe:

 - NVMe pull request from Christoph
     - rdma error handling fixes (Chao Leng)
     - fc error handling and reconnect fixes (James Smart)
     - fix the qid displace when tracing ioctl command (Keith Busch)
     - don't use BLK_MQ_REQ_NOWAIT for passthru (Chaitanya Kulkarni)
     - fix MTDT for passthru (Logan Gunthorpe)
     - blacklist Write Same on more devices (Kai-Heng Feng)
     - fix an uninitialized work struct (zhenwei pi)"

 - lightnvm out-of-bounds fix (Colin)

 - SG allocation leak fix (Doug)

 - rnbd fixes (Gioh, Guoqing, Jack)

 - zone error translation fixes (Keith)

 - kerneldoc markup fix (Mauro)

 - zram lockdep fix (Peter)

 - Kill unused io_context members (Yufen)

 - NUMA memory allocation cleanup (Xianting)

 - NBD config wakeup fix (Xiubo)

* tag 'block-5.10-2020-10-24' of git://git.kernel.dk/linux-block: (27 commits)
  block: blk-mq: fix a kernel-doc markup
  nvme-fc: shorten reconnect delay if possible for FC
  nvme-fc: wait for queues to freeze before calling update_hr_hw_queues
  nvme-fc: fix error loop in create_hw_io_queues
  nvme-fc: fix io timeout to abort I/O
  null_blk: use zone status for max active/open
  nvmet: don't use BLK_MQ_REQ_NOWAIT for passthru
  nvmet: cleanup nvmet_passthru_map_sg()
  nvmet: limit passthru MTDS by BIO_MAX_PAGES
  nvmet: fix uninitialized work for zero kato
  nvme-pci: disable Write Zeroes on Sandisk Skyhawk
  nvme: use queuedata for nvme_req_qid
  nvme-rdma: fix crash due to incorrect cqe
  nvme-rdma: fix crash when connect rejected
  block: remove unused members for io_context
  blk-mq: remove the calling of local_memory_node()
  zram: Fix __zram_bvec_{read,write}() locking order
  skd_main: remove unused including <linux/version.h>
  sgl_alloc_order: fix memory leak
  lightnvm: fix out-of-bounds write to array devices->info[]
  ...

1  2 
block/blk-mq.c
drivers/block/nbd.c
drivers/block/zram/zram_drv.c
drivers/scsi/scsi_lib.c
lib/scatterlist.c

diff --combined block/blk-mq.c
@@@ -1664,7 -1664,7 +1664,7 @@@ void blk_mq_run_hw_queue(struct blk_mq_
  EXPORT_SYMBOL(blk_mq_run_hw_queue);
  
  /**
-  * blk_mq_run_hw_queue - Run all hardware queues in a request queue.
+  * blk_mq_run_hw_queues - Run all hardware queues in a request queue.
   * @q: Pointer to the request queue to run.
   * @async: If we want to run the queue asynchronously.
   */
@@@ -2270,6 -2270,7 +2270,6 @@@ queue_exit
        blk_queue_exit(q);
        return BLK_QC_T_NONE;
  }
 -EXPORT_SYMBOL_GPL(blk_mq_submit_bio); /* only for request based dm */
  
  void blk_mq_free_rqs(struct blk_mq_tag_set *set, struct blk_mq_tags *tags,
                     unsigned int hctx_idx)
@@@ -2743,7 -2744,7 +2743,7 @@@ static void blk_mq_init_cpu_queues(stru
                for (j = 0; j < set->nr_maps; j++) {
                        hctx = blk_mq_map_queue_type(q, j, i);
                        if (nr_hw_queues > 1 && hctx->numa_node == NUMA_NO_NODE)
-                               hctx->numa_node = local_memory_node(cpu_to_node(i));
+                               hctx->numa_node = cpu_to_node(i);
                }
        }
  }
diff --combined drivers/block/nbd.c
@@@ -802,9 -802,9 +802,9 @@@ static void recv_work(struct work_struc
                if (likely(!blk_should_fake_timeout(rq->q)))
                        blk_mq_complete_request(rq);
        }
+       nbd_config_put(nbd);
        atomic_dec(&config->recv_threads);
        wake_up(&config->recv_wq);
-       nbd_config_put(nbd);
        kfree(args);
  }
  
@@@ -2184,7 -2184,7 +2184,7 @@@ out
        return ret;
  }
  
 -static const struct genl_ops nbd_connect_genl_ops[] = {
 +static const struct genl_small_ops nbd_connect_genl_ops[] = {
        {
                .cmd    = NBD_CMD_CONNECT,
                .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
@@@ -2216,8 -2216,8 +2216,8 @@@ static struct genl_family nbd_genl_fami
        .name           = NBD_GENL_FAMILY_NAME,
        .version        = NBD_GENL_VERSION,
        .module         = THIS_MODULE,
 -      .ops            = nbd_connect_genl_ops,
 -      .n_ops          = ARRAY_SIZE(nbd_connect_genl_ops),
 +      .small_ops      = nbd_connect_genl_ops,
 +      .n_small_ops    = ARRAY_SIZE(nbd_connect_genl_ops),
        .maxattr        = NBD_ATTR_MAX,
        .policy = nbd_attr_policy,
        .mcgrps         = nbd_mcast_grps,
  static int __zram_bvec_read(struct zram *zram, struct page *page, u32 index,
                                struct bio *bio, bool partial_io)
  {
-       int ret;
+       struct zcomp_strm *zstrm;
        unsigned long handle;
        unsigned int size;
        void *src, *dst;
+       int ret;
  
        zram_slot_lock(zram, index);
        if (zram_test_flag(zram, index, ZRAM_WB)) {
  
        size = zram_get_obj_size(zram, index);
  
+       if (size != PAGE_SIZE)
+               zstrm = zcomp_stream_get(zram->comp);
        src = zs_map_object(zram->mem_pool, handle, ZS_MM_RO);
        if (size == PAGE_SIZE) {
                dst = kmap_atomic(page);
                kunmap_atomic(dst);
                ret = 0;
        } else {
-               struct zcomp_strm *zstrm = zcomp_stream_get(zram->comp);
                dst = kmap_atomic(page);
                ret = zcomp_decompress(zstrm, src, size, dst);
                kunmap_atomic(dst);
        zram_slot_unlock(zram, index);
  
        /* Should NEVER happen. Return bio error if it does. */
 -      if (unlikely(ret))
 +      if (WARN_ON(ret))
                pr_err("Decompression failed! err=%d, page=%u\n", ret, index);
  
        return ret;
diff --combined drivers/scsi/scsi_lib.c
@@@ -293,6 -293,21 +293,6 @@@ int __scsi_execute(struct scsi_device *
  }
  EXPORT_SYMBOL(__scsi_execute);
  
 -/**
 - * scsi_init_cmd_errh - Initialize cmd fields related to error handling.
 - * @cmd:  command that is ready to be queued.
 - *
 - * This function has the job of initializing a number of fields related to error
 - * handling. Typically this will be called once for each command, as required.
 - */
 -static void scsi_init_cmd_errh(struct scsi_cmnd *cmd)
 -{
 -      scsi_set_resid(cmd, 0);
 -      memset(cmd->sense_buffer, 0, SCSI_SENSE_BUFFERSIZE);
 -      if (cmd->cmd_len == 0)
 -              cmd->cmd_len = scsi_command_size(cmd->cmnd);
 -}
 -
  /*
   * Wake up the error handler if necessary. Avoid as follows that the error
   * handler is not woken up if host in-flight requests number ==
@@@ -515,7 -530,7 +515,7 @@@ static void scsi_uninit_cmd(struct scsi
        }
  }
  
 -static void scsi_free_sgtables(struct scsi_cmnd *cmd)
 +void scsi_free_sgtables(struct scsi_cmnd *cmd)
  {
        if (cmd->sdb.table.nents)
                sg_free_table_chained(&cmd->sdb.table,
                sg_free_table_chained(&cmd->prot_sdb->table,
                                SCSI_INLINE_PROT_SG_CNT);
  }
 +EXPORT_SYMBOL_GPL(scsi_free_sgtables);
  
  static void scsi_mq_uninit_cmd(struct scsi_cmnd *cmd)
  {
  static void scsi_run_queue_async(struct scsi_device *sdev)
  {
        if (scsi_target(sdev)->single_lun ||
 -          !list_empty(&sdev->host->starved_list))
 +          !list_empty(&sdev->host->starved_list)) {
                kblockd_schedule_work(&sdev->requeue_work);
 -      else
 -              blk_mq_run_hw_queues(sdev->request_queue, true);
 +      } else {
 +              /*
 +               * smp_mb() present in sbitmap_queue_clear() or implied in
 +               * .end_io is for ordering writing .device_busy in
 +               * scsi_device_unbusy() and reading sdev->restarts.
 +               */
 +              int old = atomic_read(&sdev->restarts);
 +
 +              /*
 +               * ->restarts has to be kept as non-zero if new budget
 +               *  contention occurs.
 +               *
 +               *  No need to run queue when either another re-run
 +               *  queue wins in updating ->restarts or a new budget
 +               *  contention occurs.
 +               */
 +              if (old && atomic_cmpxchg(&sdev->restarts, old, 0) == old)
 +                      blk_mq_run_hw_queues(sdev->request_queue, true);
 +      }
  }
  
  /* Returns false when no more bytes to process, true if there are more */
@@@ -655,23 -652,6 +655,23 @@@ static void scsi_io_completion_reprep(s
        scsi_mq_requeue_cmd(cmd);
  }
  
 +static bool scsi_cmd_runtime_exceeced(struct scsi_cmnd *cmd)
 +{
 +      struct request *req = cmd->request;
 +      unsigned long wait_for;
 +
 +      if (cmd->allowed == SCSI_CMD_RETRIES_NO_LIMIT)
 +              return false;
 +
 +      wait_for = (cmd->allowed + 1) * req->timeout;
 +      if (time_before(cmd->jiffies_at_alloc + wait_for, jiffies)) {
 +              scmd_printk(KERN_ERR, cmd, "timing out command, waited %lus\n",
 +                          wait_for/HZ);
 +              return true;
 +      }
 +      return false;
 +}
 +
  /* Helper for scsi_io_completion() when special action required. */
  static void scsi_io_completion_action(struct scsi_cmnd *cmd, int result)
  {
        int level = 0;
        enum {ACTION_FAIL, ACTION_REPREP, ACTION_RETRY,
              ACTION_DELAYED_RETRY} action;
 -      unsigned long wait_for = (cmd->allowed + 1) * req->timeout;
        struct scsi_sense_hdr sshdr;
        bool sense_valid;
        bool sense_current = true;      /* false implies "deferred sense" */
                        /* See SSC3rXX or current. */
                        action = ACTION_FAIL;
                        break;
+               case DATA_PROTECT:
+                       action = ACTION_FAIL;
+                       if ((sshdr.asc == 0x0C && sshdr.ascq == 0x12) ||
+                           (sshdr.asc == 0x55 &&
+                            (sshdr.ascq == 0x0E || sshdr.ascq == 0x0F))) {
+                               /* Insufficient zone resources */
+                               blk_stat = BLK_STS_ZONE_OPEN_RESOURCE;
+                       }
+                       break;
                default:
                        action = ACTION_FAIL;
                        break;
        } else
                action = ACTION_FAIL;
  
 -      if (action != ACTION_FAIL &&
 -          time_before(cmd->jiffies_at_alloc + wait_for, jiffies))
 +      if (action != ACTION_FAIL && scsi_cmd_runtime_exceeced(cmd))
                action = ACTION_FAIL;
  
        switch (action) {
@@@ -984,7 -975,7 +993,7 @@@ static inline bool scsi_cmd_needs_dma_d
  }
  
  /**
 - * scsi_init_io - SCSI I/O initialization function.
 + * scsi_alloc_sgtables - allocate S/G tables for a command
   * @cmd:  command descriptor we wish to initialize
   *
   * Returns:
   * * BLK_STS_RESOURCE - if the failure is retryable
   * * BLK_STS_IOERR    - if the failure is fatal
   */
 -blk_status_t scsi_init_io(struct scsi_cmnd *cmd)
 +blk_status_t scsi_alloc_sgtables(struct scsi_cmnd *cmd)
  {
        struct scsi_device *sdev = cmd->device;
        struct request *rq = cmd->request;
@@@ -1084,7 -1075,7 +1093,7 @@@ out_free_sgtables
        scsi_free_sgtables(cmd);
        return ret;
  }
 -EXPORT_SYMBOL(scsi_init_io);
 +EXPORT_SYMBOL(scsi_alloc_sgtables);
  
  /**
   * scsi_initialize_rq - initialize struct scsi_cmnd partially
@@@ -1172,7 -1163,7 +1181,7 @@@ static blk_status_t scsi_setup_scsi_cmn
         * submit a request without an attached bio.
         */
        if (req->bio) {
 -              blk_status_t ret = scsi_init_io(cmd);
 +              blk_status_t ret = scsi_alloc_sgtables(cmd);
                if (unlikely(ret != BLK_STS_OK))
                        return ret;
        } else {
        }
  
        cmd->cmd_len = scsi_req(req)->cmd_len;
 +      if (cmd->cmd_len == 0)
 +              cmd->cmd_len = scsi_command_size(cmd->cmnd);
        cmd->cmnd = scsi_req(req)->cmd;
        cmd->transfersize = blk_rq_bytes(req);
        cmd->allowed = scsi_req(req)->retries;
        return BLK_STS_OK;
  }
  
 -/*
 - * Setup a normal block command.  These are simple request from filesystems
 - * that still need to be translated to SCSI CDBs from the ULD.
 - */
 -static blk_status_t scsi_setup_fs_cmnd(struct scsi_device *sdev,
 -              struct request *req)
 -{
 -      struct scsi_cmnd *cmd = blk_mq_rq_to_pdu(req);
 -
 -      if (unlikely(sdev->handler && sdev->handler->prep_fn)) {
 -              blk_status_t ret = sdev->handler->prep_fn(sdev, req);
 -              if (ret != BLK_STS_OK)
 -                      return ret;
 -      }
 -
 -      cmd->cmnd = scsi_req(req)->cmd = scsi_req(req)->__cmd;
 -      memset(cmd->cmnd, 0, BLK_MAX_CDB);
 -      return scsi_cmd_to_driver(cmd)->init_command(cmd);
 -}
 -
 -static blk_status_t scsi_setup_cmnd(struct scsi_device *sdev,
 -              struct request *req)
 -{
 -      struct scsi_cmnd *cmd = blk_mq_rq_to_pdu(req);
 -      blk_status_t ret;
 -
 -      if (!blk_rq_bytes(req))
 -              cmd->sc_data_direction = DMA_NONE;
 -      else if (rq_data_dir(req) == WRITE)
 -              cmd->sc_data_direction = DMA_TO_DEVICE;
 -      else
 -              cmd->sc_data_direction = DMA_FROM_DEVICE;
 -
 -      if (blk_rq_is_scsi(req))
 -              ret = scsi_setup_scsi_cmnd(sdev, req);
 -      else
 -              ret = scsi_setup_fs_cmnd(sdev, req);
 -
 -      if (ret != BLK_STS_OK)
 -              scsi_free_sgtables(cmd);
 -
 -      return ret;
 -}
 -
  static blk_status_t
 -scsi_prep_state_check(struct scsi_device *sdev, struct request *req)
 +scsi_device_state_check(struct scsi_device *sdev, struct request *req)
  {
        switch (sdev->sdev_state) {
        case SDEV_OFFLINE:
@@@ -1415,6 -1448,7 +1424,6 @@@ static bool scsi_mq_lld_busy(struct req
  static void scsi_softirq_done(struct request *rq)
  {
        struct scsi_cmnd *cmd = blk_mq_rq_to_pdu(rq);
 -      unsigned long wait_for = (cmd->allowed + 1) * rq->timeout;
        int disposition;
  
        INIT_LIST_HEAD(&cmd->eh_entry);
                atomic_inc(&cmd->device->ioerr_cnt);
  
        disposition = scsi_decide_disposition(cmd);
 -      if (disposition != SUCCESS &&
 -          time_before(cmd->jiffies_at_alloc + wait_for, jiffies)) {
 -              scmd_printk(KERN_ERR, cmd,
 -                          "timing out command, waited %lus\n",
 -                          wait_for/HZ);
 +      if (disposition != SUCCESS && scsi_cmd_runtime_exceeced(cmd))
                disposition = SUCCESS;
 -      }
  
        scsi_log_completion(cmd, disposition);
  
@@@ -1533,7 -1572,7 +1542,7 @@@ static unsigned int scsi_mq_inline_sgl_
                sizeof(struct scatterlist);
  }
  
 -static blk_status_t scsi_mq_prep_fn(struct request *req)
 +static blk_status_t scsi_prepare_cmd(struct request *req)
  {
        struct scsi_cmnd *cmd = blk_mq_rq_to_pdu(req);
        struct scsi_device *sdev = req->q->queuedata;
        cmd->request = req;
        cmd->tag = req->tag;
        cmd->prot_op = SCSI_PROT_NORMAL;
 +      if (blk_rq_bytes(req))
 +              cmd->sc_data_direction = rq_dma_dir(req);
 +      else
 +              cmd->sc_data_direction = DMA_NONE;
  
        sg = (void *)cmd + sizeof(struct scsi_cmnd) + shost->hostt->cmd_size;
        cmd->sdb.table.sgl = sg;
                        (struct scatterlist *)(cmd->prot_sdb + 1);
        }
  
 -      blk_mq_start_request(req);
 +      /*
 +       * Special handling for passthrough commands, which don't go to the ULP
 +       * at all:
 +       */
 +      if (blk_rq_is_scsi(req))
 +              return scsi_setup_scsi_cmnd(sdev, req);
 +
 +      if (sdev->handler && sdev->handler->prep_fn) {
 +              blk_status_t ret = sdev->handler->prep_fn(sdev, req);
 +
 +              if (ret != BLK_STS_OK)
 +                      return ret;
 +      }
  
 -      return scsi_setup_cmnd(sdev, req);
 +      cmd->cmnd = scsi_req(req)->cmd = scsi_req(req)->__cmd;
 +      memset(cmd->cmnd, 0, BLK_MAX_CDB);
 +      return scsi_cmd_to_driver(cmd)->init_command(cmd);
  }
  
  static void scsi_mq_done(struct scsi_cmnd *cmd)
@@@ -1600,30 -1621,7 +1609,30 @@@ static bool scsi_mq_get_budget(struct r
  {
        struct scsi_device *sdev = q->queuedata;
  
 -      return scsi_dev_queue_ready(q, sdev);
 +      if (scsi_dev_queue_ready(q, sdev))
 +              return true;
 +
 +      atomic_inc(&sdev->restarts);
 +
 +      /*
 +       * Orders atomic_inc(&sdev->restarts) and atomic_read(&sdev->device_busy).
 +       * .restarts must be incremented before .device_busy is read because the
 +       * code in scsi_run_queue_async() depends on the order of these operations.
 +       */
 +      smp_mb__after_atomic();
 +
 +      /*
 +       * If all in-flight requests originated from this LUN are completed
 +       * before reading .device_busy, sdev->device_busy will be observed as
 +       * zero, then blk_mq_delay_run_hw_queues() will dispatch this request
 +       * soon. Otherwise, completion of one of these requests will observe
 +       * the .restarts flag, and the request queue will be run for handling
 +       * this request, see scsi_end_request().
 +       */
 +      if (unlikely(atomic_read(&sdev->device_busy) == 0 &&
 +                              !scsi_device_blocked(sdev)))
 +              blk_mq_delay_run_hw_queues(sdev->request_queue, SCSI_QUEUE_DELAY);
 +      return false;
  }
  
  static blk_status_t scsi_queue_rq(struct blk_mq_hw_ctx *hctx,
         * commands.
         */
        if (unlikely(sdev->sdev_state != SDEV_RUNNING)) {
 -              ret = scsi_prep_state_check(sdev, req);
 +              ret = scsi_device_state_check(sdev, req);
                if (ret != BLK_STS_OK)
                        goto out_put_budget;
        }
                goto out_dec_target_busy;
  
        if (!(req->rq_flags & RQF_DONTPREP)) {
 -              ret = scsi_mq_prep_fn(req);
 +              ret = scsi_prepare_cmd(req);
                if (ret != BLK_STS_OK)
                        goto out_dec_host_busy;
                req->rq_flags |= RQF_DONTPREP;
        } else {
                clear_bit(SCMD_STATE_COMPLETE, &cmd->state);
 -              blk_mq_start_request(req);
        }
  
        cmd->flags &= SCMD_PRESERVED_FLAGS;
        if (bd->last)
                cmd->flags |= SCMD_LAST;
  
 -      scsi_init_cmd_errh(cmd);
 +      scsi_set_resid(cmd, 0);
 +      memset(cmd->sense_buffer, 0, SCSI_SENSE_BUFFERSIZE);
        cmd->scsi_done = scsi_mq_done;
  
 +      blk_mq_start_request(req);
        reason = scsi_dispatch_cmd(cmd);
        if (reason) {
                scsi_set_blocked(cmd, reason);
@@@ -1933,6 -1930,7 +1942,6 @@@ struct scsi_device *scsi_device_from_qu
  
        return sdev;
  }
 -EXPORT_SYMBOL_GPL(scsi_device_from_queue);
  
  /**
   * scsi_block_requests - Utility function used by low-level drivers to prevent
diff --combined lib/scatterlist.c
@@@ -365,37 -365,6 +365,37 @@@ int sg_alloc_table(struct sg_table *tab
  }
  EXPORT_SYMBOL(sg_alloc_table);
  
 +static struct scatterlist *get_next_sg(struct sg_table *table,
 +                                     struct scatterlist *cur,
 +                                     unsigned long needed_sges,
 +                                     gfp_t gfp_mask)
 +{
 +      struct scatterlist *new_sg, *next_sg;
 +      unsigned int alloc_size;
 +
 +      if (cur) {
 +              next_sg = sg_next(cur);
 +              /* Check if last entry should be keeped for chainning */
 +              if (!sg_is_last(next_sg) || needed_sges == 1)
 +                      return next_sg;
 +      }
 +
 +      alloc_size = min_t(unsigned long, needed_sges, SG_MAX_SINGLE_ALLOC);
 +      new_sg = sg_kmalloc(alloc_size, gfp_mask);
 +      if (!new_sg)
 +              return ERR_PTR(-ENOMEM);
 +      sg_init_table(new_sg, alloc_size);
 +      if (cur) {
 +              __sg_chain(next_sg, new_sg);
 +              table->orig_nents += alloc_size - 1;
 +      } else {
 +              table->sgl = new_sg;
 +              table->orig_nents = alloc_size;
 +              table->nents = 0;
 +      }
 +      return new_sg;
 +}
 +
  /**
   * __sg_alloc_table_from_pages - Allocate and initialize an sg table from
   *                             an array of pages
   * @n_pages:   Number of pages in the pages array
   * @offset:      Offset from start of the first page to the start of a buffer
   * @size:        Number of valid bytes in the buffer (after offset)
 - * @max_segment: Maximum size of a scatterlist node in bytes (page aligned)
 + * @max_segment: Maximum size of a scatterlist element in bytes
 + * @prv:       Last populated sge in sgt
 + * @left_pages:  Left pages caller have to set after this call
   * @gfp_mask:  GFP allocation mask
   *
 - *  Description:
 - *    Allocate and initialize an sg table from a list of pages. Contiguous
 - *    ranges of the pages are squashed into a single scatterlist node up to the
 - *    maximum size specified in @max_segment. An user may provide an offset at a
 - *    start and a size of valid data in a buffer specified by the page array.
 - *    The returned sg table is released by sg_free_table.
 + * Description:
 + *    If @prv is NULL, allocate and initialize an sg table from a list of pages,
 + *    else reuse the scatterlist passed in at @prv.
 + *    Contiguous ranges of the pages are squashed into a single scatterlist
 + *    entry up to the maximum size specified in @max_segment.  A user may
 + *    provide an offset at a start and a size of valid data in a buffer
 + *    specified by the page array.
   *
   * Returns:
 - *   0 on success, negative error on failure
 + *   Last SGE in sgt on success, PTR_ERR on otherwise.
 + *   The allocation in @sgt must be released by sg_free_table.
 + *
 + * Notes:
 + *   If this function returns non-0 (eg failure), the caller must call
 + *   sg_free_table() to cleanup any leftover allocations.
   */
 -int __sg_alloc_table_from_pages(struct sg_table *sgt, struct page **pages,
 -                              unsigned int n_pages, unsigned int offset,
 -                              unsigned long size, unsigned int max_segment,
 -                              gfp_t gfp_mask)
 +struct scatterlist *__sg_alloc_table_from_pages(struct sg_table *sgt,
 +              struct page **pages, unsigned int n_pages, unsigned int offset,
 +              unsigned long size, unsigned int max_segment,
 +              struct scatterlist *prv, unsigned int left_pages,
 +              gfp_t gfp_mask)
  {
 -      unsigned int chunks, cur_page, seg_len, i;
 -      int ret;
 -      struct scatterlist *s;
 -
 -      if (WARN_ON(!max_segment || offset_in_page(max_segment)))
 -              return -EINVAL;
 +      unsigned int chunks, cur_page, seg_len, i, prv_len = 0;
 +      unsigned int added_nents = 0;
 +      struct scatterlist *s = prv;
 +
 +      /*
 +       * The algorithm below requires max_segment to be aligned to PAGE_SIZE
 +       * otherwise it can overshoot.
 +       */
 +      max_segment = ALIGN_DOWN(max_segment, PAGE_SIZE);
 +      if (WARN_ON(max_segment < PAGE_SIZE))
 +              return ERR_PTR(-EINVAL);
 +
 +      if (IS_ENABLED(CONFIG_ARCH_NO_SG_CHAIN) && prv)
 +              return ERR_PTR(-EOPNOTSUPP);
 +
 +      if (prv) {
 +              unsigned long paddr = (page_to_pfn(sg_page(prv)) * PAGE_SIZE +
 +                                     prv->offset + prv->length) /
 +                                    PAGE_SIZE;
 +
 +              if (WARN_ON(offset))
 +                      return ERR_PTR(-EINVAL);
 +
 +              /* Merge contiguous pages into the last SG */
 +              prv_len = prv->length;
 +              while (n_pages && page_to_pfn(pages[0]) == paddr) {
 +                      if (prv->length + PAGE_SIZE > max_segment)
 +                              break;
 +                      prv->length += PAGE_SIZE;
 +                      paddr++;
 +                      pages++;
 +                      n_pages--;
 +              }
 +              if (!n_pages)
 +                      goto out;
 +      }
  
        /* compute number of contiguous chunks */
        chunks = 1;
                }
        }
  
 -      ret = sg_alloc_table(sgt, chunks, gfp_mask);
 -      if (unlikely(ret))
 -              return ret;
 -
        /* merging chunks and putting them into the scatterlist */
        cur_page = 0;
 -      for_each_sg(sgt->sgl, s, sgt->orig_nents, i) {
 +      for (i = 0; i < chunks; i++) {
                unsigned int j, chunk_size;
  
                /* look for the end of the current chunk */
                                break;
                }
  
 +              /* Pass how many chunks might be left */
 +              s = get_next_sg(sgt, s, chunks - i + left_pages, gfp_mask);
 +              if (IS_ERR(s)) {
 +                      /*
 +                       * Adjust entry length to be as before function was
 +                       * called.
 +                       */
 +                      if (prv)
 +                              prv->length = prv_len;
 +                      return s;
 +              }
                chunk_size = ((j - cur_page) << PAGE_SHIFT) - offset;
                sg_set_page(s, pages[cur_page],
                            min_t(unsigned long, size, chunk_size), offset);
 +              added_nents++;
                size -= chunk_size;
                offset = 0;
                cur_page = j;
        }
 -
 -      return 0;
 +      sgt->nents += added_nents;
 +out:
 +      if (!left_pages)
 +              sg_mark_end(s);
 +      return s;
  }
  EXPORT_SYMBOL(__sg_alloc_table_from_pages);
  
@@@ -546,8 -465,8 +546,8 @@@ int sg_alloc_table_from_pages(struct sg
                              unsigned int n_pages, unsigned int offset,
                              unsigned long size, gfp_t gfp_mask)
  {
 -      return __sg_alloc_table_from_pages(sgt, pages, n_pages, offset, size,
 -                                         SCATTERLIST_MAX_SEGMENT, gfp_mask);
 +      return PTR_ERR_OR_ZERO(__sg_alloc_table_from_pages(sgt, pages, n_pages,
 +                      offset, size, UINT_MAX, NULL, 0, gfp_mask));
  }
  EXPORT_SYMBOL(sg_alloc_table_from_pages);
  
@@@ -585,7 -504,7 +585,7 @@@ struct scatterlist *sgl_alloc_order(uns
                nalloc++;
        }
        sgl = kmalloc_array(nalloc, sizeof(struct scatterlist),
 -                          (gfp & ~GFP_DMA) | __GFP_ZERO);
 +                          gfp & ~GFP_DMA);
        if (!sgl)
                return NULL;
  
                elem_len = min_t(u64, length, PAGE_SIZE << order);
                page = alloc_pages(gfp, order);
                if (!page) {
-                       sgl_free(sgl);
+                       sgl_free_order(sgl, order);
                        return NULL;
                }