Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

tmpfs: support aio

We have a request for tmpfs to support the AIO interface: easily done, no
more than replacing the old shmem_file_read by shmem_file_aio_read,
cribbed from generic_file_aio_read. (In 2.6.25 its write side was already
changed to use generic_file_aio_write.)

Incorporate cleanups from Andrew Morton and Harvey Harrison.

Tests out fine with LTP's ltp-aiodio.sh, given hacks (not included) to
support O_DIRECT. tmpfs cannot honestly support O_DIRECT: its
cache-avoiding-IO nature is at odds with direct IO-avoiding-cache.

Signed-off-by: Hugh Dickins <hugh@veritas.com>
Tested-by: Lawrence Greenfield <leg@google.com>
Cc: Christoph Rohland <hans-christoph.rohland@sap.com>
Cc: Badari Pulavarty <pbadari@us.ibm.com>
Cc: Zach Brown <zach.brown@oracle.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

authored by

Hugh Dickins and committed by
Linus Torvalds
bcd78e49 11fa977e

+30 -17
+30 -17
mm/shmem.c
··· 1690 1690 file_accessed(filp); 1691 1691 } 1692 1692 1693 - static ssize_t shmem_file_read(struct file *filp, char __user *buf, size_t count, loff_t *ppos) 1693 + static ssize_t shmem_file_aio_read(struct kiocb *iocb, 1694 + const struct iovec *iov, unsigned long nr_segs, loff_t pos) 1694 1695 { 1695 - read_descriptor_t desc; 1696 + struct file *filp = iocb->ki_filp; 1697 + ssize_t retval; 1698 + unsigned long seg; 1699 + size_t count; 1700 + loff_t *ppos = &iocb->ki_pos; 1696 1701 1697 - if ((ssize_t) count < 0) 1698 - return -EINVAL; 1699 - if (!access_ok(VERIFY_WRITE, buf, count)) 1700 - return -EFAULT; 1701 - if (!count) 1702 - return 0; 1702 + retval = generic_segment_checks(iov, &nr_segs, &count, VERIFY_WRITE); 1703 + if (retval) 1704 + return retval; 1703 1705 1704 - desc.written = 0; 1705 - desc.count = count; 1706 - desc.arg.buf = buf; 1707 - desc.error = 0; 1706 + for (seg = 0; seg < nr_segs; seg++) { 1707 + read_descriptor_t desc; 1708 1708 1709 - do_shmem_file_read(filp, ppos, &desc, file_read_actor); 1710 - if (desc.written) 1711 - return desc.written; 1712 - return desc.error; 1709 + desc.written = 0; 1710 + desc.arg.buf = iov[seg].iov_base; 1711 + desc.count = iov[seg].iov_len; 1712 + if (desc.count == 0) 1713 + continue; 1714 + desc.error = 0; 1715 + do_shmem_file_read(filp, ppos, &desc, file_read_actor); 1716 + retval += desc.written; 1717 + if (desc.error) { 1718 + retval = retval ?: desc.error; 1719 + break; 1720 + } 1721 + if (desc.count > 0) 1722 + break; 1723 + } 1724 + return retval; 1713 1725 } 1714 1726 1715 1727 static int shmem_statfs(struct dentry *dentry, struct kstatfs *buf) ··· 2381 2369 .mmap = shmem_mmap, 2382 2370 #ifdef CONFIG_TMPFS 2383 2371 .llseek = generic_file_llseek, 2384 - .read = shmem_file_read, 2372 + .read = do_sync_read, 2385 2373 .write = do_sync_write, 2374 + .aio_read = shmem_file_aio_read, 2386 2375 .aio_write = generic_file_aio_write, 2387 2376 .fsync = simple_sync_file, 2388 2377 .splice_read = generic_file_splice_read,