diff options
Diffstat (limited to 'fs/xfs/xfs_buf.c')
-rw-r--r-- | fs/xfs/xfs_buf.c | 171 |
1 files changed, 24 insertions, 147 deletions
diff --git a/fs/xfs/xfs_buf.c b/fs/xfs/xfs_buf.c index 548344e25128..ca0849043f54 100644 --- a/fs/xfs/xfs_buf.c +++ b/fs/xfs/xfs_buf.c @@ -4,24 +4,9 @@ * All Rights Reserved. */ #include "xfs.h" -#include <linux/stddef.h> -#include <linux/errno.h> -#include <linux/gfp.h> -#include <linux/pagemap.h> -#include <linux/init.h> -#include <linux/vmalloc.h> -#include <linux/bio.h> -#include <linux/sysctl.h> -#include <linux/proc_fs.h> -#include <linux/workqueue.h> -#include <linux/percpu.h> -#include <linux/blkdev.h> -#include <linux/hash.h> -#include <linux/kthread.h> -#include <linux/migrate.h> #include <linux/backing-dev.h> -#include <linux/freezer.h> +#include "xfs_shared.h" #include "xfs_format.h" #include "xfs_log_format.h" #include "xfs_trans_resv.h" @@ -213,7 +198,7 @@ xfs_buf_free_maps( } } -struct xfs_buf * +static struct xfs_buf * _xfs_buf_alloc( struct xfs_buftarg *target, struct xfs_buf_map *map, @@ -243,6 +228,7 @@ _xfs_buf_alloc( sema_init(&bp->b_sema, 0); /* held, no waiters */ spin_lock_init(&bp->b_lock); bp->b_target = target; + bp->b_mount = target->bt_mount; bp->b_flags = flags; /* @@ -263,12 +249,11 @@ _xfs_buf_alloc( bp->b_maps[i].bm_len = map[i].bm_len; bp->b_length += map[i].bm_len; } - bp->b_io_length = bp->b_length; atomic_set(&bp->b_pin_count, 0); init_waitqueue_head(&bp->b_waiters); - XFS_STATS_INC(target->bt_mount, xb_create); + XFS_STATS_INC(bp->b_mount, xb_create); trace_xfs_buf_init(bp, _RET_IP_); return bp; @@ -425,12 +410,12 @@ retry: current->comm, current->pid, __func__, gfp_mask); - XFS_STATS_INC(bp->b_target->bt_mount, xb_page_retries); + XFS_STATS_INC(bp->b_mount, xb_page_retries); congestion_wait(BLK_RW_ASYNC, HZ/50); goto retry; } - XFS_STATS_INC(bp->b_target->bt_mount, xb_page_found); + XFS_STATS_INC(bp->b_mount, xb_page_found); nbytes = min_t(size_t, size, PAGE_SIZE - offset); size -= nbytes; @@ -909,83 +894,6 @@ xfs_buf_read_uncached( return 0; } -/* - * Return a buffer allocated as an empty buffer and associated to external - * memory via xfs_buf_associate_memory() back to it's empty state. - */ -void -xfs_buf_set_empty( - struct xfs_buf *bp, - size_t numblks) -{ - if (bp->b_pages) - _xfs_buf_free_pages(bp); - - bp->b_pages = NULL; - bp->b_page_count = 0; - bp->b_addr = NULL; - bp->b_length = numblks; - bp->b_io_length = numblks; - - ASSERT(bp->b_map_count == 1); - bp->b_bn = XFS_BUF_DADDR_NULL; - bp->b_maps[0].bm_bn = XFS_BUF_DADDR_NULL; - bp->b_maps[0].bm_len = bp->b_length; -} - -static inline struct page * -mem_to_page( - void *addr) -{ - if ((!is_vmalloc_addr(addr))) { - return virt_to_page(addr); - } else { - return vmalloc_to_page(addr); - } -} - -int -xfs_buf_associate_memory( - xfs_buf_t *bp, - void *mem, - size_t len) -{ - int rval; - int i = 0; - unsigned long pageaddr; - unsigned long offset; - size_t buflen; - int page_count; - - pageaddr = (unsigned long)mem & PAGE_MASK; - offset = (unsigned long)mem - pageaddr; - buflen = PAGE_ALIGN(len + offset); - page_count = buflen >> PAGE_SHIFT; - - /* Free any previous set of page pointers */ - if (bp->b_pages) - _xfs_buf_free_pages(bp); - - bp->b_pages = NULL; - bp->b_addr = mem; - - rval = _xfs_buf_get_pages(bp, page_count); - if (rval) - return rval; - - bp->b_offset = offset; - - for (i = 0; i < bp->b_page_count; i++) { - bp->b_pages[i] = mem_to_page((void *)pageaddr); - pageaddr += PAGE_SIZE; - } - - bp->b_io_length = BTOBB(len); - bp->b_length = BTOBB(buflen); - - return 0; -} - xfs_buf_t * xfs_buf_get_uncached( struct xfs_buftarg *target, @@ -1180,7 +1088,7 @@ xfs_buf_lock( trace_xfs_buf_lock(bp, _RET_IP_); if (atomic_read(&bp->b_pin_count) && (bp->b_flags & XBF_STALE)) - xfs_log_force(bp->b_target->bt_mount, 0); + xfs_log_force(bp->b_mount, 0); down(&bp->b_sema); trace_xfs_buf_lock_done(bp, _RET_IP_); @@ -1269,7 +1177,7 @@ xfs_buf_ioend_async( struct xfs_buf *bp) { INIT_WORK(&bp->b_ioend_work, xfs_buf_ioend_work); - queue_work(bp->b_ioend_wq, &bp->b_ioend_work); + queue_work(bp->b_mount->m_buf_workqueue, &bp->b_ioend_work); } void @@ -1288,7 +1196,7 @@ xfs_buf_ioerror_alert( struct xfs_buf *bp, const char *func) { - xfs_alert(bp->b_target->bt_mount, + xfs_alert(bp->b_mount, "metadata I/O error in \"%s\" at daddr 0x%llx len %d error %d", func, (uint64_t)XFS_BUF_ADDR(bp), bp->b_length, -bp->b_error); @@ -1307,10 +1215,8 @@ xfs_bwrite( XBF_WRITE_FAIL | XBF_DONE); error = xfs_buf_submit(bp); - if (error) { - xfs_force_shutdown(bp->b_target->bt_mount, - SHUTDOWN_META_IO_ERROR); - } + if (error) + xfs_force_shutdown(bp->b_mount, SHUTDOWN_META_IO_ERROR); return error; } @@ -1436,21 +1342,8 @@ _xfs_buf_ioapply( */ bp->b_error = 0; - /* - * Initialize the I/O completion workqueue if we haven't yet or the - * submitter has not opted to specify a custom one. - */ - if (!bp->b_ioend_wq) - bp->b_ioend_wq = bp->b_target->bt_mount->m_buf_workqueue; - if (bp->b_flags & XBF_WRITE) { op = REQ_OP_WRITE; - if (bp->b_flags & XBF_SYNCIO) - op_flags = REQ_SYNC; - if (bp->b_flags & XBF_FUA) - op_flags |= REQ_FUA; - if (bp->b_flags & XBF_FLUSH) - op_flags |= REQ_PREFLUSH; /* * Run the write verifier callback function if it exists. If @@ -1460,12 +1353,12 @@ _xfs_buf_ioapply( if (bp->b_ops) { bp->b_ops->verify_write(bp); if (bp->b_error) { - xfs_force_shutdown(bp->b_target->bt_mount, + xfs_force_shutdown(bp->b_mount, SHUTDOWN_CORRUPT_INCORE); return; } } else if (bp->b_bn != XFS_BUF_DADDR_NULL) { - struct xfs_mount *mp = bp->b_target->bt_mount; + struct xfs_mount *mp = bp->b_mount; /* * non-crc filesystems don't attach verifiers during @@ -1497,7 +1390,7 @@ _xfs_buf_ioapply( * subsequent call. */ offset = bp->b_offset; - size = BBTOB(bp->b_io_length); + size = BBTOB(bp->b_length); blk_start_plug(&plug); for (i = 0; i < bp->b_map_count; i++) { xfs_buf_ioapply_map(bp, i, &offset, &size, op, op_flags); @@ -1543,7 +1436,7 @@ __xfs_buf_submit( ASSERT(!(bp->b_flags & _XBF_DELWRI_Q)); /* on shutdown we stale and complete the buffer immediately */ - if (XFS_FORCED_SHUTDOWN(bp->b_target->bt_mount)) { + if (XFS_FORCED_SHUTDOWN(bp->b_mount)) { xfs_buf_ioerror(bp, -EIO); bp->b_flags &= ~XBF_DONE; xfs_buf_stale(bp); @@ -1613,16 +1506,11 @@ xfs_buf_offset( return page_address(page) + (offset & (PAGE_SIZE-1)); } -/* - * Move data into or out of a buffer. - */ void -xfs_buf_iomove( - xfs_buf_t *bp, /* buffer to process */ - size_t boff, /* starting buffer offset */ - size_t bsize, /* length to copy */ - void *data, /* data address */ - xfs_buf_rw_t mode) /* read/write/zero flag */ +xfs_buf_zero( + struct xfs_buf *bp, + size_t boff, + size_t bsize) { size_t bend; @@ -1635,23 +1523,13 @@ xfs_buf_iomove( page_offset = (boff + bp->b_offset) & ~PAGE_MASK; page = bp->b_pages[page_index]; csize = min_t(size_t, PAGE_SIZE - page_offset, - BBTOB(bp->b_io_length) - boff); + BBTOB(bp->b_length) - boff); ASSERT((csize + page_offset) <= PAGE_SIZE); - switch (mode) { - case XBRW_ZERO: - memset(page_address(page) + page_offset, 0, csize); - break; - case XBRW_READ: - memcpy(data, page_address(page) + page_offset, csize); - break; - case XBRW_WRITE: - memcpy(page_address(page) + page_offset, data, csize); - } + memset(page_address(page) + page_offset, 0, csize); boff += csize; - data += csize; } } @@ -2198,8 +2076,7 @@ void xfs_buf_set_ref(struct xfs_buf *bp, int lru_ref) * This allows userspace to disrupt buffer caching for debug/testing * purposes. */ - if (XFS_TEST_ERROR(false, bp->b_target->bt_mount, - XFS_ERRTAG_BUF_LRU_REF)) + if (XFS_TEST_ERROR(false, bp->b_mount, XFS_ERRTAG_BUF_LRU_REF)) lru_ref = 0; atomic_set(&bp->b_lru_ref, lru_ref); @@ -2215,7 +2092,7 @@ xfs_verify_magic( struct xfs_buf *bp, __be32 dmagic) { - struct xfs_mount *mp = bp->b_target->bt_mount; + struct xfs_mount *mp = bp->b_mount; int idx; idx = xfs_sb_version_hascrc(&mp->m_sb); @@ -2233,7 +2110,7 @@ xfs_verify_magic16( struct xfs_buf *bp, __be16 dmagic) { - struct xfs_mount *mp = bp->b_target->bt_mount; + struct xfs_mount *mp = bp->b_mount; int idx; idx = xfs_sb_version_hascrc(&mp->m_sb); |