These changes are the raw update to linux-4.4.6-rt14. Kernel sources
[kvmfornfv.git] / kernel / fs / xfs / xfs_buf.c
index 1790b00..39090fc 100644 (file)
@@ -201,7 +201,7 @@ _xfs_buf_alloc(
        atomic_set(&bp->b_pin_count, 0);
        init_waitqueue_head(&bp->b_waiters);
 
-       XFS_STATS_INC(xb_create);
+       XFS_STATS_INC(target->bt_mount, xb_create);
        trace_xfs_buf_init(bp, _RET_IP_);
 
        return bp;
@@ -354,15 +354,16 @@ retry:
                         */
                        if (!(++retries % 100))
                                xfs_err(NULL,
-               "possible memory allocation deadlock in %s (mode:0x%x)",
+               "%s(%u) possible memory allocation deadlock in %s (mode:0x%x)",
+                                       current->comm, current->pid,
                                        __func__, gfp_mask);
 
-                       XFS_STATS_INC(xb_page_retries);
+                       XFS_STATS_INC(bp->b_target->bt_mount, xb_page_retries);
                        congestion_wait(BLK_RW_ASYNC, HZ/50);
                        goto retry;
                }
 
-               XFS_STATS_INC(xb_page_found);
+               XFS_STATS_INC(bp->b_target->bt_mount, xb_page_found);
 
                nbytes = min_t(size_t, size, PAGE_SIZE - offset);
                size -= nbytes;
@@ -438,7 +439,6 @@ _xfs_buf_find(
        xfs_buf_flags_t         flags,
        xfs_buf_t               *new_bp)
 {
-       size_t                  numbytes;
        struct xfs_perag        *pag;
        struct rb_node          **rbp;
        struct rb_node          *parent;
@@ -450,10 +450,9 @@ _xfs_buf_find(
 
        for (i = 0; i < nmaps; i++)
                numblks += map[i].bm_len;
-       numbytes = BBTOB(numblks);
 
        /* Check for IOs smaller than the sector size / not sector aligned */
-       ASSERT(!(numbytes < btp->bt_meta_sectorsize));
+       ASSERT(!(BBTOB(numblks) < btp->bt_meta_sectorsize));
        ASSERT(!(BBTOB(blkno) & (xfs_off_t)btp->bt_meta_sectormask));
 
        /*
@@ -518,7 +517,7 @@ _xfs_buf_find(
                new_bp->b_pag = pag;
                spin_unlock(&pag->pag_buf_lock);
        } else {
-               XFS_STATS_INC(xb_miss_locked);
+               XFS_STATS_INC(btp->bt_mount, xb_miss_locked);
                spin_unlock(&pag->pag_buf_lock);
                xfs_perag_put(pag);
        }
@@ -531,11 +530,11 @@ found:
        if (!xfs_buf_trylock(bp)) {
                if (flags & XBF_TRYLOCK) {
                        xfs_buf_rele(bp);
-                       XFS_STATS_INC(xb_busy_locked);
+                       XFS_STATS_INC(btp->bt_mount, xb_busy_locked);
                        return NULL;
                }
                xfs_buf_lock(bp);
-               XFS_STATS_INC(xb_get_locked_waited);
+               XFS_STATS_INC(btp->bt_mount, xb_get_locked_waited);
        }
 
        /*
@@ -551,7 +550,7 @@ found:
        }
 
        trace_xfs_buf_find(bp, flags, _RET_IP_);
-       XFS_STATS_INC(xb_get_locked);
+       XFS_STATS_INC(btp->bt_mount, xb_get_locked);
        return bp;
 }
 
@@ -605,7 +604,14 @@ found:
                }
        }
 
-       XFS_STATS_INC(xb_get);
+       /*
+        * Clear b_error if this is a lookup from a caller that doesn't expect
+        * valid data to be found in the buffer.
+        */
+       if (!(flags & XBF_READ))
+               xfs_buf_ioerror(bp, 0);
+
+       XFS_STATS_INC(target->bt_mount, xb_get);
        trace_xfs_buf_get(bp, flags, _RET_IP_);
        return bp;
 }
@@ -645,7 +651,7 @@ xfs_buf_read_map(
                trace_xfs_buf_read(bp, flags, _RET_IP_);
 
                if (!XFS_BUF_ISDONE(bp)) {
-                       XFS_STATS_INC(xb_get_read);
+                       XFS_STATS_INC(target->bt_mount, xb_get_read);
                        bp->b_ops = ops;
                        _xfs_buf_read(bp, flags);
                } else if (flags & XBF_ASYNC) {
@@ -1096,8 +1102,7 @@ xfs_bwrite(
 
 STATIC void
 xfs_buf_bio_end_io(
-       struct bio              *bio,
-       int                     error)
+       struct bio              *bio)
 {
        xfs_buf_t               *bp = (xfs_buf_t *)bio->bi_private;
 
@@ -1105,10 +1110,10 @@ xfs_buf_bio_end_io(
         * don't overwrite existing errors - otherwise we can lose errors on
         * buffers that require multiple bios to complete.
         */
-       if (error) {
+       if (bio->bi_error) {
                spin_lock(&bp->b_lock);
                if (!bp->b_io_error)
-                       bp->b_io_error = error;
+                       bp->b_io_error = bio->bi_error;
                spin_unlock(&bp->b_lock);
        }
 
@@ -1419,9 +1424,9 @@ xfs_buf_submit_wait(
        return error;
 }
 
-xfs_caddr_t
+void *
 xfs_buf_offset(
-       xfs_buf_t               *bp,
+       struct xfs_buf          *bp,
        size_t                  offset)
 {
        struct page             *page;
@@ -1431,7 +1436,7 @@ xfs_buf_offset(
 
        offset += bp->b_offset;
        page = bp->b_pages[offset >> PAGE_SHIFT];
-       return (xfs_caddr_t)page_address(page) + (offset & (PAGE_SIZE-1));
+       return page_address(page) + (offset & (PAGE_SIZE-1));
 }
 
 /*
@@ -1522,6 +1527,16 @@ xfs_wait_buftarg(
        LIST_HEAD(dispose);
        int loop = 0;
 
+       /*
+        * We need to flush the buffer workqueue to ensure that all IO
+        * completion processing is 100% done. Just waiting on buffer locks is
+        * not sufficient for async IO as the reference count held over IO is
+        * not released until after the buffer lock is dropped. Hence we need to
+        * ensure here that all reference counts have been dropped before we
+        * start walking the LRU list.
+        */
+       drain_workqueue(btp->bt_mount->m_buf_workqueue);
+
        /* loop until there is nothing left on the lru list. */
        while (list_lru_count(&btp->bt_lru)) {
                list_lru_walk(&btp->bt_lru, xfs_buftarg_wait_rele,
@@ -1533,9 +1548,10 @@ xfs_wait_buftarg(
                        list_del_init(&bp->b_lru);
                        if (bp->b_flags & XBF_WRITE_FAIL) {
                                xfs_alert(btp->bt_mount,
-"Corruption Alert: Buffer at block 0x%llx had permanent write failures!\n"
-"Please run xfs_repair to determine the extent of the problem.",
+"Corruption Alert: Buffer at block 0x%llx had permanent write failures!",
                                        (long long)bp->b_bn);
+                               xfs_alert(btp->bt_mount,
+"Please run xfs_repair to determine the extent of the problem.");
                        }
                        xfs_buf_rele(bp);
                }