Simple refactoring of the sg_vma_fault() function.

Signed-off-by: Douglas Gilbert <dgilb...@interlog.com>
---
 drivers/scsi/sg.c | 33 +++++++++++++++++++++++----------
 1 file changed, 23 insertions(+), 10 deletions(-)

diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index 903faafaeff9..befcbfbcece1 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -1389,14 +1389,16 @@ sg_fasync(int fd, struct file *filp, int mode)
        return fasync_helper(fd, filp, mode, &sfp->async_qp);
 }
 
+/* Note: the error return: VM_FAULT_SIGBUS causes a "bus error" */
 static vm_fault_t
 sg_vma_fault(struct vm_fault *vmf)
 {
-       struct vm_area_struct *vma = vmf->vma;
-       struct sg_fd *sfp;
+       int k, length;
        unsigned long offset, len, sa;
+       struct vm_area_struct *vma = vmf->vma;
        struct sg_scatter_hold *rsv_schp;
-       int k, length;
+       struct sg_device *sdp;
+       struct sg_fd *sfp;
        const char *nbp = "==NULL, bad";
 
        if (!vma) {
@@ -1408,20 +1410,31 @@ sg_vma_fault(struct vm_fault *vmf)
                pr_warn("%s: sfp%s\n", __func__, nbp);
                goto out_err;
        }
+       sdp = sfp->parentdp;
+       if (sdp && unlikely(SG_IS_DETACHING(sdp))) {
+               SG_LOG(1, sfp, "%s: device detaching\n", __func__);
+               goto out_err;
+       }
        rsv_schp = &sfp->reserve;
        offset = vmf->pgoff << PAGE_SHIFT;
-       if (offset >= rsv_schp->buflen)
-               return VM_FAULT_SIGBUS;
+       if (offset >= (unsigned int)rsv_schp->buflen) {
+               SG_LOG(1, sfp, "%s: offset[%lu] >= rsv.buflen\n", __func__,
+                      offset);
+               goto out_err;
+       }
        sa = vma->vm_start;
        SG_LOG(3, sfp, "%s: vm_start=0x%lx, off=%lu\n", __func__, sa, offset);
        length = 1 << (PAGE_SHIFT + rsv_schp->page_order);
-       for (k = 0; k < rsv_schp->num_sgat && sa < vma->vm_end; k++) {
+       for (k = 0; k < rsv_schp->num_sgat && sa < vma->vm_end; ++k) {
                len = vma->vm_end - sa;
-               len = (len < length) ? len : length;
+               len = min_t(int, len, (int)length);
                if (offset < len) {
-                       struct page *page = nth_page(rsv_schp->pages[k],
-                                                    offset >> PAGE_SHIFT);
-                       get_page(page); /* increment page count */
+                       struct page *page;
+                       struct page *pp;
+
+                       pp = rsv_schp->pages[k];
+                       page = nth_page(pp, offset >> PAGE_SHIFT);
+                       get_page(page); /* increment page count */
                        vmf->page = page;
                        return 0; /* success */
                }
-- 
2.23.0

Reply via email to