mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
synced 2025-01-04 04:02:26 +00:00
new primitive: iov_iter_alignment()
returns the value aligned as badly as the worst remaining segment in iov_iter is. Use instead of open-coded equivalents. Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:
parent
26978b8b4d
commit
886a391150
@ -391,11 +391,8 @@ static ssize_t ll_direct_IO_26(int rw, struct kiocb *iocb,
|
|||||||
MAX_DIO_SIZE >> PAGE_CACHE_SHIFT);
|
MAX_DIO_SIZE >> PAGE_CACHE_SHIFT);
|
||||||
|
|
||||||
/* Check that all user buffers are aligned as well */
|
/* Check that all user buffers are aligned as well */
|
||||||
for (seg = 0; seg < iter->nr_segs; seg++) {
|
if (iov_iter_alignment(iter) & ~CFS_PAGE_MASK)
|
||||||
if (((unsigned long)iter->iov[seg].iov_base & ~CFS_PAGE_MASK) ||
|
return -EINVAL;
|
||||||
(iter->iov[seg].iov_len & ~CFS_PAGE_MASK))
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
env = cl_env_get(&refcheck);
|
env = cl_env_get(&refcheck);
|
||||||
LASSERT(!IS_ERR(env));
|
LASSERT(!IS_ERR(env));
|
||||||
|
@ -1112,19 +1112,18 @@ do_blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode,
|
|||||||
dio_submit_t submit_io, int flags)
|
dio_submit_t submit_io, int flags)
|
||||||
{
|
{
|
||||||
int seg;
|
int seg;
|
||||||
size_t size;
|
|
||||||
unsigned long addr;
|
|
||||||
unsigned i_blkbits = ACCESS_ONCE(inode->i_blkbits);
|
unsigned i_blkbits = ACCESS_ONCE(inode->i_blkbits);
|
||||||
unsigned blkbits = i_blkbits;
|
unsigned blkbits = i_blkbits;
|
||||||
unsigned blocksize_mask = (1 << blkbits) - 1;
|
unsigned blocksize_mask = (1 << blkbits) - 1;
|
||||||
ssize_t retval = -EINVAL;
|
ssize_t retval = -EINVAL;
|
||||||
loff_t end = offset;
|
loff_t end = offset + iov_iter_count(iter);
|
||||||
struct dio *dio;
|
struct dio *dio;
|
||||||
struct dio_submit sdio = { 0, };
|
struct dio_submit sdio = { 0, };
|
||||||
unsigned long user_addr;
|
unsigned long user_addr;
|
||||||
size_t bytes;
|
size_t bytes;
|
||||||
struct buffer_head map_bh = { 0, };
|
struct buffer_head map_bh = { 0, };
|
||||||
struct blk_plug plug;
|
struct blk_plug plug;
|
||||||
|
unsigned long align = offset | iov_iter_alignment(iter);
|
||||||
|
|
||||||
if (rw & WRITE)
|
if (rw & WRITE)
|
||||||
rw = WRITE_ODIRECT;
|
rw = WRITE_ODIRECT;
|
||||||
@ -1134,32 +1133,16 @@ do_blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode,
|
|||||||
* the early prefetch in the caller enough time.
|
* the early prefetch in the caller enough time.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (offset & blocksize_mask) {
|
if (align & blocksize_mask) {
|
||||||
if (bdev)
|
if (bdev)
|
||||||
blkbits = blksize_bits(bdev_logical_block_size(bdev));
|
blkbits = blksize_bits(bdev_logical_block_size(bdev));
|
||||||
blocksize_mask = (1 << blkbits) - 1;
|
blocksize_mask = (1 << blkbits) - 1;
|
||||||
if (offset & blocksize_mask)
|
if (align & blocksize_mask)
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check the memory alignment. Blocks cannot straddle pages */
|
|
||||||
for (seg = 0; seg < iter->nr_segs; seg++) {
|
|
||||||
addr = (unsigned long)iter->iov[seg].iov_base;
|
|
||||||
size = iter->iov[seg].iov_len;
|
|
||||||
end += size;
|
|
||||||
if (unlikely((addr & blocksize_mask) ||
|
|
||||||
(size & blocksize_mask))) {
|
|
||||||
if (bdev)
|
|
||||||
blkbits = blksize_bits(
|
|
||||||
bdev_logical_block_size(bdev));
|
|
||||||
blocksize_mask = (1 << blkbits) - 1;
|
|
||||||
if ((addr & blocksize_mask) || (size & blocksize_mask))
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* watch out for a 0 len io from a tricksy fs */
|
/* watch out for a 0 len io from a tricksy fs */
|
||||||
if (rw == READ && end == offset)
|
if (rw == READ && !iov_iter_count(iter))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
dio = kmem_cache_alloc(dio_cache, GFP_KERNEL);
|
dio = kmem_cache_alloc(dio_cache, GFP_KERNEL);
|
||||||
|
@ -67,6 +67,7 @@ int iov_iter_fault_in_readable(struct iov_iter *i, size_t bytes);
|
|||||||
size_t iov_iter_single_seg_count(const struct iov_iter *i);
|
size_t iov_iter_single_seg_count(const struct iov_iter *i);
|
||||||
size_t copy_page_to_iter(struct page *page, size_t offset, size_t bytes,
|
size_t copy_page_to_iter(struct page *page, size_t offset, size_t bytes,
|
||||||
struct iov_iter *i);
|
struct iov_iter *i);
|
||||||
|
unsigned long iov_iter_alignment(const struct iov_iter *i);
|
||||||
|
|
||||||
static inline void iov_iter_init(struct iov_iter *i,
|
static inline void iov_iter_init(struct iov_iter *i,
|
||||||
const struct iovec *iov, unsigned long nr_segs,
|
const struct iovec *iov, unsigned long nr_segs,
|
||||||
@ -88,4 +89,5 @@ static inline size_t iov_iter_count(struct iov_iter *i)
|
|||||||
int memcpy_fromiovec(unsigned char *kdata, struct iovec *iov, int len);
|
int memcpy_fromiovec(unsigned char *kdata, struct iovec *iov, int len);
|
||||||
int memcpy_toiovec(struct iovec *iov, unsigned char *kdata, int len);
|
int memcpy_toiovec(struct iovec *iov, unsigned char *kdata, int len);
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -195,3 +195,28 @@ size_t iov_iter_single_seg_count(const struct iov_iter *i)
|
|||||||
return min(i->count, iov->iov_len - i->iov_offset);
|
return min(i->count, iov->iov_len - i->iov_offset);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(iov_iter_single_seg_count);
|
EXPORT_SYMBOL(iov_iter_single_seg_count);
|
||||||
|
|
||||||
|
unsigned long iov_iter_alignment(const struct iov_iter *i)
|
||||||
|
{
|
||||||
|
const struct iovec *iov = i->iov;
|
||||||
|
unsigned long res;
|
||||||
|
size_t size = i->count;
|
||||||
|
size_t n;
|
||||||
|
|
||||||
|
if (!size)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
res = (unsigned long)iov->iov_base + i->iov_offset;
|
||||||
|
n = iov->iov_len - i->iov_offset;
|
||||||
|
if (n >= size)
|
||||||
|
return res | size;
|
||||||
|
size -= n;
|
||||||
|
res |= n;
|
||||||
|
while (size > (++iov)->iov_len) {
|
||||||
|
res |= (unsigned long)iov->iov_base | iov->iov_len;
|
||||||
|
size -= iov->iov_len;
|
||||||
|
}
|
||||||
|
res |= (unsigned long)iov->iov_base | size;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(iov_iter_alignment);
|
||||||
|
Loading…
Reference in New Issue
Block a user