freebsd-dev/include/sys
Richard Yao cd3939c5f0 Linux AIO Support
nfsd uses do_readv_writev() to implement fops->read and fops->write.
do_readv_writev() will attempt to read/write using fops->aio_read and
fops->aio_write, but it will fallback to fops->read and fops->write when
AIO is not available. However, the fallback will perform a call for each
individual data page. Since our default recordsize is 128KB, sequential
operations on NFS will generate 32 DMU transactions where only 1
transaction was needed. That was unnecessary overhead and we implement
fops->aio_read and fops->aio_write to eliminate it.

ZFS originated in OpenSolaris, where the AIO API is entirely implemented
in userland's libc by intelligently mapping them to VOP_WRITE, VOP_READ
and VOP_FSYNC.  Linux implements AIO inside the kernel itself. Linux
filesystems therefore must implement their own AIO logic and nearly all
of them implement fops->aio_write synchronously. Consequently, they do
not implement aio_fsync(). However, since the ZPL works by mapping
Linux's VFS calls to the functions implementing Illumos' VFS operations,
we instead implement AIO in the kernel by mapping the operations to the
VOP_READ, VOP_WRITE and VOP_FSYNC equivalents. We therefore implement
fops->aio_fsync.

One might be inclined to make our fops->aio_write implementation
synchronous to make software that expects this behavior safe. However,
there are several reasons not to do this:

1. Other platforms do not implement aio_write() synchronously and since
the majority of userland software using AIO should be cross platform,
expectations of synchronous behavior should not be a problem.

2. We would hurt the performance of programs that use POSIX interfaces
properly while simultaneously encouraging the creation of more
non-compliant software.

3. The broader community concluded that userland software should be
patched to properly use POSIX interfaces instead of implementing hacks
in filesystems to cater to broken software. This concept is best
described as the O_PONIES debate.

4. Making an asynchronous write synchronous is non sequitur.

Any software dependent on synchronous aio_write behavior will suffer
data loss on ZFSOnLinux in a kernel panic / system failure of at most
zfs_txg_timeout seconds, which by default is 5 seconds. This seems like
a reasonable consequence of using non-compliant software.

It should be noted that this is also a problem in the kernel itself
where nfsd does not pass O_SYNC on files opened with it and instead
relies on a open()/write()/close() to enforce synchronous behavior when
the flush is only guarenteed on last close.

Exporting any filesystem that does not implement AIO via NFS risks data
loss in the event of a kernel panic / system failure when something else
is also accessing the file. Exporting any file system that implements
AIO the way this patch does bears similar risk. However, it seems
reasonable to forgo crippling our AIO implementation in favor of
developing patches to fix this problem in Linux's nfsd for the reasons
stated earlier. In the interim, the risk will remain. Failing to
implement AIO will not change the problem that nfsd created, so there is
no reason for nfsd's mistake to block our implementation of AIO.

It also should be noted that `aio_cancel()` will always return
`AIO_NOTCANCELED` under this implementation. It is possible to implement
aio_cancel by deferring work to taskqs and use `kiocb_set_cancel_fn()`
to set a callback function for cancelling work sent to taskqs, but the
simpler approach is allowed by the specification:

```
Which operations are cancelable is implementation-defined.
```

http://pubs.opengroup.org/onlinepubs/009695399/functions/aio_cancel.html

The only programs on my system that are capable of using `aio_cancel()`
are QEMU, beecrypt and fio use it according to a recursive grep of my
system's `/usr/src/debug`. That suggests that `aio_cancel()` users are
rare. Implementing aio_cancel() is left to a future date when it is
clear that there are consumers that benefit from its implementation to
justify the work.

Lastly, it is important to know that handling of the iovec updates differs
between Illumos and Linux in the implementation of read/write. On Linux,
it is the VFS' responsibility whle on Illumos, it is the filesystem's
responsibility.  We take the intermediate solution of copying the iovec
so that the ZFS code can update it like on Solaris while leaving the
originals alone. This imposes some overhead. We could always revisit
this should profiling show that the allocations are a problem.

Signed-off-by: Richard Yao <ryao@gentoo.org>
Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
Closes #223
Closes #2373
2014-09-05 15:11:43 -07:00
..
fm Fixed memory leaks in zevent handling 2014-08-20 10:45:16 -07:00
fs Illumos 4976-4984 - metaslab improvements 2014-08-18 08:40:49 -07:00
arc.h Illumos 4631 - zvol_get_stats triggering too many reads 2014-08-20 09:17:00 -07:00
avl_impl.h Support custom build directories and move includes 2010-09-08 12:38:56 -07:00
avl.h Support custom build directories and move includes 2010-09-08 12:38:56 -07:00
blkptr.h Illumos 4757, 4913 2014-08-01 14:28:05 -07:00
bplist.h Support custom build directories and move includes 2010-09-08 12:38:56 -07:00
bpobj.h Illumos #3104: eliminate empty bpobjs 2013-01-08 10:35:43 -08:00
bptree.h Illumos 4914 - zfs on-disk bookmark structure should be named *_phys_t 2014-08-06 14:48:41 -07:00
dbuf.h Illumos 4757, 4913 2014-08-01 14:28:05 -07:00
ddt.h Add ddt, ddt_entry, and l2arc_hdr caches 2014-01-07 10:33:11 -08:00
dmu_impl.h Illumos 4757, 4913 2014-08-01 14:28:05 -07:00
dmu_objset.h Illumos 3835 zfs need not store 2 copies of all metadata 2014-07-31 09:49:34 -07:00
dmu_send.h Illumos 4757, 4913 2014-08-01 14:28:05 -07:00
dmu_traverse.h Illumos 4914 - zfs on-disk bookmark structure should be named *_phys_t 2014-08-06 14:48:41 -07:00
dmu_tx.h dmu_tx kstat cleanup 2014-03-04 12:22:24 -08:00
dmu_zfetch.h Fix zstream_t incorrect type 2013-12-10 10:09:27 -08:00
dmu.h Illumos 4914 - zfs on-disk bookmark structure should be named *_phys_t 2014-08-06 14:48:41 -07:00
dnode.h Illumos #4374 2014-07-30 09:20:35 -07:00
dsl_bookmark.h Illumos 4368, 4369. 2014-07-29 10:55:29 -07:00
dsl_dataset.h Illumos 4368, 4369. 2014-07-29 10:55:29 -07:00
dsl_deadlist.h Support custom build directories and move includes 2010-09-08 12:38:56 -07:00
dsl_deleg.h Illumos 4368, 4369. 2014-07-29 10:55:29 -07:00
dsl_destroy.h Illumos #3888 2013-11-04 11:18:14 -08:00
dsl_dir.h Illumos 4390 - I/O errors can corrupt space map when deleting fs/vol 2014-08-04 11:50:52 -07:00
dsl_pool.h Illumos 4390 - I/O errors can corrupt space map when deleting fs/vol 2014-08-04 11:50:52 -07:00
dsl_prop.h Illumos #3464 2013-09-04 16:01:24 -07:00
dsl_scan.h Illumos 4914 - zfs on-disk bookmark structure should be named *_phys_t 2014-08-06 14:48:41 -07:00
dsl_synctask.h Illumos #3464 2013-09-04 16:01:24 -07:00
dsl_userhold.h Illumos #3740 2013-11-04 11:17:48 -08:00
efi_partition.h Move partition scanning from userspace to module. 2012-07-17 09:17:31 -07:00
Makefile.am Illumos 4757, 4913 2014-08-01 14:28:05 -07:00
metaslab_impl.h Illumos 4976-4984 - metaslab improvements 2014-08-18 08:40:49 -07:00
metaslab.h Illumos 4976-4984 - metaslab improvements 2014-08-18 08:40:49 -07:00
nvpair_impl.h Support custom build directories and move includes 2010-09-08 12:38:56 -07:00
nvpair.h Replace __va_list with va_list 2014-08-13 10:35:00 -07:00
range_tree.h Illumos #4374 2014-07-30 09:20:35 -07:00
refcount.h Illumos #3464 2013-09-04 16:01:24 -07:00
rrwlock.h Illumos #3464 2013-09-04 16:01:24 -07:00
sa_impl.h Illumos #4045 write throttle & i/o scheduler performance work 2013-12-06 09:32:43 -08:00
sa.h Add sa_spill_rele() interface 2012-03-07 16:28:00 -08:00
spa_boot.h Support custom build directories and move includes 2010-09-08 12:38:56 -07:00
spa_impl.h Illumos 4914 - zfs on-disk bookmark structure should be named *_phys_t 2014-08-06 14:48:41 -07:00
spa.h Illumos 4914 - zfs on-disk bookmark structure should be named *_phys_t 2014-08-06 14:48:41 -07:00
space_map.h Illumos 4976-4984 - metaslab improvements 2014-08-18 08:40:49 -07:00
space_reftree.h Illumos #4101, #4102, #4103, #4105, #4106 2014-07-22 09:39:16 -07:00
txg_impl.h Illumos #4045 write throttle & i/o scheduler performance work 2013-12-06 09:32:43 -08:00
txg.h Illumos #4045 write throttle & i/o scheduler performance work 2013-12-06 09:32:43 -08:00
u8_textprep_data.h Support custom build directories and move includes 2010-09-08 12:38:56 -07:00
u8_textprep.h Support custom build directories and move includes 2010-09-08 12:38:56 -07:00
uberblock_impl.h Support custom build directories and move includes 2010-09-08 12:38:56 -07:00
uberblock.h Support custom build directories and move includes 2010-09-08 12:38:56 -07:00
uio_impl.h Add basic uio support 2011-02-10 09:21:43 -08:00
unique.h Illumos #3742 2013-11-04 10:55:25 -08:00
uuid.h Support custom build directories and move includes 2010-09-08 12:38:56 -07:00
vdev_disk.h cstyle: Resolve C style issues 2013-12-18 16:46:35 -08:00
vdev_file.h Use a dedicated taskq for vdev_file 2014-05-14 16:20:21 -07:00
vdev_impl.h Avoid dynamic allocation of 'search zio' 2014-08-11 08:44:54 -07:00
vdev.h Illumos 4370, 4371 2014-07-28 14:29:58 -07:00
xvattr.h Add xvattr support 2011-03-02 11:43:50 -08:00
zap_impl.h Support custom build directories and move includes 2010-09-08 12:38:56 -07:00
zap_leaf.h Illumos #3742 2013-11-04 10:55:25 -08:00
zap.h Illumos 4171, 4172 2014-07-25 16:40:07 -07:00
zfeature.h Illumos 4370, 4371 2014-07-28 14:29:58 -07:00
zfs_acl.h Illumos #3742 2013-11-04 10:55:25 -08:00
zfs_context.h Replace __va_list with va_list 2014-08-13 10:35:00 -07:00
zfs_ctldir.h Linux 3.7 compat, schedule_delayed_work() 2012-12-12 10:47:05 -08:00
zfs_debug.h Illumos 4976-4984 - metaslab improvements 2014-08-18 08:40:49 -07:00
zfs_delay.h cstyle: Resolve C style issues 2013-12-18 16:46:35 -08:00
zfs_dir.h Prototype/structure update for Linux 2011-02-10 09:27:21 -08:00
zfs_fuid.h Prototype/structure update for Linux 2011-02-10 09:27:21 -08:00
zfs_ioctl.h Illumos 4757, 4913 2014-08-01 14:28:05 -07:00
zfs_onexit.h Support custom build directories and move includes 2010-09-08 12:38:56 -07:00
zfs_rlock.h Illumos #3742 2013-11-04 10:55:25 -08:00
zfs_sa.h cstyle: Resolve C style issues 2013-12-18 16:46:35 -08:00
zfs_stat.h Support custom build directories and move includes 2010-09-08 12:38:56 -07:00
zfs_vfsops.h Implement relatime. 2014-01-29 15:50:44 -08:00
zfs_vnops.h Add zfs_iput_async() interface 2014-08-11 16:11:43 -07:00
zfs_znode.h Fix zil_commit() NULL dereference 2014-07-17 15:15:07 -07:00
zil_impl.h cstyle: Resolve C style issues 2013-12-18 16:46:35 -08:00
zil.h cstyle: Resolve C style issues 2013-12-18 16:46:35 -08:00
zio_checksum.h Constify structures containing function pointers 2013-03-04 08:49:32 -08:00
zio_compress.h Illumos #3742 2013-11-04 10:55:25 -08:00
zio_impl.h Illumos #3836 2013-11-05 12:14:56 -08:00
zio.h Illumos 4914 - zfs on-disk bookmark structure should be named *_phys_t 2014-08-06 14:48:41 -07:00
zpl.h Linux AIO Support 2014-09-05 15:11:43 -07:00
zrlock.h Support custom build directories and move includes 2010-09-08 12:38:56 -07:00
zvol.h Remove ZFC_IOC_*_MINOR ioctl()s 2013-12-16 09:15:57 -08:00