-STATIC int
-linvfs_get_block_core(
- struct inode *inode,
- sector_t iblock,
- unsigned long blocks,
- struct buffer_head *bh_result,
- int create,
- int direct,
- bmapi_flags_t flags)
-{
- vnode_t *vp = LINVFS_GET_VP(inode);
- xfs_iomap_t iomap;
- int retpbbm = 1;
- int error;
- ssize_t size;
- loff_t offset = (loff_t)iblock << inode->i_blkbits;
-
- if (blocks)
- size = blocks << inode->i_blkbits;
- else
- size = 1 << inode->i_blkbits;
-
- VOP_BMAP(vp, offset, size,
- create ? flags : BMAPI_READ, &iomap, &retpbbm, error);
- if (error)
- return -error;
-
- if (retpbbm == 0)
- return 0;
-
- if (iomap.iomap_bn != IOMAP_DADDR_NULL) {
- xfs_daddr_t bn;
- loff_t delta;
-
- /* For unwritten extents do not report a disk address on
- * the read case (treat as if we're reading into a hole).
- */
- if (create || !(iomap.iomap_flags & IOMAP_UNWRITTEN)) {
- delta = offset - iomap.iomap_offset;
- delta >>= inode->i_blkbits;
-
- bn = iomap.iomap_bn >> (inode->i_blkbits - BBSHIFT);
- bn += delta;
- BUG_ON(!bn && !(iomap.iomap_flags & IOMAP_REALTIME));
- bh_result->b_blocknr = bn;
- set_buffer_mapped(bh_result);
- }
- if (create && (iomap.iomap_flags & IOMAP_UNWRITTEN)) {
- if (direct)
- bh_result->b_private = inode;
- set_buffer_unwritten(bh_result);
- set_buffer_delay(bh_result);
- }
- }
-
- /* If this is a realtime file, data might be on a new device */
- bh_result->b_bdev = iomap.iomap_target->pbr_bdev;
-
- /* If we previously allocated a block out beyond eof and
- * we are now coming back to use it then we will need to
- * flag it as new even if it has a disk address.
- */
- if (create &&
- ((!buffer_mapped(bh_result) && !buffer_uptodate(bh_result)) ||
- (offset >= i_size_read(inode)) || (iomap.iomap_flags & IOMAP_NEW))) {
- set_buffer_new(bh_result);
- }
-
- if (iomap.iomap_flags & IOMAP_DELAY) {
- BUG_ON(direct);
- if (create) {
- set_buffer_mapped(bh_result);
- set_buffer_uptodate(bh_result);
- }
- set_buffer_delay(bh_result);
- }
-
- if (blocks) {
- bh_result->b_size = (ssize_t)min(
- (loff_t)(iomap.iomap_bsize - iomap.iomap_delta),
- (loff_t)(blocks << inode->i_blkbits));
- }
-
- return 0;
-}
-
-int
-linvfs_get_block(
- struct inode *inode,
- sector_t iblock,
- struct buffer_head *bh_result,
- int create)
-{
- return linvfs_get_block_core(inode, iblock, 0, bh_result,
- create, 0, BMAPI_WRITE);
-}
-
-STATIC int
-linvfs_get_blocks_direct(
- struct inode *inode,
- sector_t iblock,
- unsigned long max_blocks,
- struct buffer_head *bh_result,
- int create)
-{
- return linvfs_get_block_core(inode, iblock, max_blocks, bh_result,
- create, 1, BMAPI_WRITE|BMAPI_DIRECT);
-}
-
-STATIC ssize_t
-linvfs_direct_IO(
- int rw,
- struct kiocb *iocb,
- const struct iovec *iov,
- loff_t offset,
- unsigned long nr_segs)
-{
- struct file *file = iocb->ki_filp;
- struct inode *inode = file->f_mapping->host;
- vnode_t *vp = LINVFS_GET_VP(inode);
- xfs_iomap_t iomap;
- int maps = 1;
- int error;
-
- VOP_BMAP(vp, offset, 0, BMAPI_DEVICE, &iomap, &maps, error);
- if (error)
- return -error;
-
- return blockdev_direct_IO_own_locking(rw, iocb, inode,
- iomap.iomap_target->pbr_bdev,
- iov, offset, nr_segs,
- linvfs_get_blocks_direct,
- linvfs_unwritten_convert_direct);
-}
-
-
-STATIC sector_t
-linvfs_bmap(
- struct address_space *mapping,
- sector_t block)
-{
- struct inode *inode = (struct inode *)mapping->host;
- vnode_t *vp = LINVFS_GET_VP(inode);
- int error;
-
- vn_trace_entry(vp, "linvfs_bmap", (inst_t *)__return_address);
-
- VOP_RWLOCK(vp, VRWLOCK_READ);
- VOP_FLUSH_PAGES(vp, (xfs_off_t)0, -1, 0, FI_REMAPF, error);
- VOP_RWUNLOCK(vp, VRWLOCK_READ);
- return generic_block_bmap(mapping, block, linvfs_get_block);
-}
-
-STATIC int
-linvfs_readpage(
- struct file *unused,
- struct page *page)
-{
- return mpage_readpage(page, linvfs_get_block);
-}
-
-STATIC int
-linvfs_readpages(
- struct file *unused,
- struct address_space *mapping,
- struct list_head *pages,
- unsigned nr_pages)
-{
- return mpage_readpages(mapping, pages, nr_pages, linvfs_get_block);
-}
-
-STATIC void
-xfs_count_page_state(
- struct page *page,
- int *delalloc,
- int *unmapped,
- int *unwritten)
-{
- struct buffer_head *bh, *head;
-
- *delalloc = *unmapped = *unwritten = 0;
-
- bh = head = page_buffers(page);
- do {
- if (buffer_uptodate(bh) && !buffer_mapped(bh))
- (*unmapped) = 1;
- else if (buffer_unwritten(bh) && !buffer_delay(bh))
- clear_buffer_unwritten(bh);
- else if (buffer_unwritten(bh))
- (*unwritten) = 1;
- else if (buffer_delay(bh))
- (*delalloc) = 1;
- } while ((bh = bh->b_this_page) != head);
-}
-
-