offset <<= PAGE_CACHE_SHIFT;
offset += p_offset;
- pb = pagebuf_lookup(iomapp->iomap_target,
- iomapp->iomap_offset, iomapp->iomap_bsize, 0);
+ /* get an "empty" pagebuf to manage IO completion
+ * Proper values will be set before returning */
+ pb = pagebuf_lookup(iomapp->iomap_target, 0, 0, 0);
+
if (!pb)
return -EAGAIN;
nblocks += bs;
atomic_add(bs, &pb->pb_io_remaining);
convert_page(inode, page, iomapp, pb, startio, all_bh);
+ /* stop if converting the next page might add
+ * enough blocks that the corresponding byte
+ * count won't fit in our ulong page buf length */
+ if (nblocks >= ((ULONG_MAX - PAGE_SIZE) >> block_bits))
+ goto enough;
}
if (tindex == tlast &&
nblocks += bs;
atomic_add(bs, &pb->pb_io_remaining);
convert_page(inode, page, iomapp, pb, startio, all_bh);
+ if (nblocks >= ((ULONG_MAX - PAGE_SIZE) >> block_bits))
+ goto enough;
}
}
}
+enough:
size = nblocks; /* NB: using 64bit number here */
size <<= block_bits; /* convert fsb's to byte range */
XFS_BUF_DATAIO(pb);
XFS_BUF_ASYNC(pb);
XFS_BUF_SET_SIZE(pb, size);
+ XFS_BUF_SET_COUNT(pb, size);
XFS_BUF_SET_OFFSET(pb, offset);
XFS_BUF_SET_FSPRIVATE(pb, LINVFS_GET_VP(inode));
XFS_BUF_SET_IODONE_FUNC(pb, linvfs_unwritten_convert);
}
if (blocks) {
- size = (iomap.iomap_bsize - iomap.iomap_delta);
- bh_result->b_size = min_t(ssize_t, size, blocks << inode->i_blkbits);
+ loff_t iosize;
+ iosize = (iomap.iomap_bsize - iomap.iomap_delta);
+ bh_result->b_size =
+ (ssize_t)min(iosize, (loff_t)(blocks << inode->i_blkbits));
}
return 0;
/*
* xfs_iomap_t: File system I/O map
*
- * The iomap_bn, iomap_offset and iomap_length fields are expressed in disk blocks.
- * The iomap_length field specifies the size of the underlying backing store
- * for the particular mapping.
+ * The iomap_bn field is expressed in 512-byte blocks, and is where the
+ * mapping starts on disk.
*
- * The iomap_bsize, iomap_size and iomap_delta fields are in bytes and indicate
- * the size of the mapping, the number of bytes that are valid to access
- * (read or write), and the offset into the mapping, given the offset
- * supplied to the file I/O map routine. iomap_delta is the offset of the
- * desired data from the beginning of the mapping.
+ * The iomap_offset, iomap_bsize and iomap_delta fields are in bytes.
+ * iomap_offset is the offset of the mapping in the file itself.
+ * iomap_bsize is the size of the mapping, iomap_delta is the
+ * desired data's offset into the mapping, given the offset supplied
+ * to the file I/O map routine.
*
* When a request is made to read beyond the logical end of the object,
- * iomap_size may be set to 0, but iomap_offset and iomap_length should be set to
- * the actual amount of underlying storage that has been allocated, if any.
+ * iomap_size may be set to 0, but iomap_offset and iomap_length should be set
+ * to the actual amount of underlying storage that has been allocated, if any.
*/
typedef struct xfs_iomap {
- xfs_daddr_t iomap_bn;
+ xfs_daddr_t iomap_bn; /* first 512b blk of mapping */
xfs_buftarg_t *iomap_target;
- loff_t iomap_offset;
- size_t iomap_delta;
- size_t iomap_bsize;
+ loff_t iomap_offset; /* offset of mapping, bytes */
+ loff_t iomap_bsize; /* size of mapping, bytes */
+ size_t iomap_delta; /* offset into mapping, bytes */
iomap_flags_t iomap_flags;
} xfs_iomap_t;