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

[CIFS] O_DIRECT opens should work on directio mounts

Opens on current cifs/smb2/smb3 mounts with O_DIRECT flag fail
even when caching is disabled on the mount. This was
reported by those running SMB2 benchmarks who need to
be able to pass O_DIRECT on many of their open calls to
reduce caching effects, but would also be needed by other
applications.

When mounting with forcedirectio ("cache=none") cifs and smb2/smb3
do not go through the page cache and thus opens with O_DIRECT flag
should work (when posix extensions are negotiated we even are
able to send the flag to the server). This patch fixes that
in a simple way.

The 9P client has a similar situation (caching is often disabled)
and takes the same approach to O_DIRECT support ie works if caching
disabled, but if client caching enabled it fails with EINVAL.

A followon idea for a future patch as Pavel noted, could
be that files opened with O_DIRECT could cause us to change
inode->i_fop on the fly from

cifs_file_strict_ops

to

cifs_file_direct_ops

which would allow us to support this on non-forcedirectio mounts
(cache=strict and cache=loose) as well.

Reviewed-by: Pavel Shilovsky <piastry@etersoft.ru>
Signed-off-by: Steve French <smfrench@gmail.com>

+22
+22
fs/cifs/file.c
··· 3663 3663 } 3664 3664 } 3665 3665 3666 + /* 3667 + * The presence of cifs_direct_io() in the address space ops vector 3668 + * allowes open() O_DIRECT flags which would have failed otherwise. 3669 + * 3670 + * In the non-cached mode (mount with cache=none), we shunt off direct read and write requests 3671 + * so this method should never be called. 3672 + * 3673 + * Direct IO is not yet supported in the cached mode. 3674 + */ 3675 + static ssize_t 3676 + cifs_direct_io(int rw, struct kiocb *iocb, const struct iovec *iov, 3677 + loff_t pos, unsigned long nr_segs) 3678 + { 3679 + /* 3680 + * FIXME 3681 + * Eventually need to support direct IO for non forcedirectio mounts 3682 + */ 3683 + return -EINVAL; 3684 + } 3685 + 3686 + 3666 3687 const struct address_space_operations cifs_addr_ops = { 3667 3688 .readpage = cifs_readpage, 3668 3689 .readpages = cifs_readpages, ··· 3693 3672 .write_end = cifs_write_end, 3694 3673 .set_page_dirty = __set_page_dirty_nobuffers, 3695 3674 .releasepage = cifs_release_page, 3675 + .direct_IO = cifs_direct_io, 3696 3676 .invalidatepage = cifs_invalidate_page, 3697 3677 .launder_page = cifs_launder_page, 3698 3678 };