diff options
author | Steve French <smfrench@gmail.com> | 2013-11-11 17:42:37 -0500 |
---|---|---|
committer | Steve French <smfrench@gmail.com> | 2013-11-11 17:42:37 -0500 |
commit | dca692880e887739a669f6c41a80ca68ce2b09fc (patch) | |
tree | 358c5ff7ebab5e6ac77a4a8e4824e7b0ea96429a | |
parent | a8582159edb47a60dd1e5df5a21890f225270f62 (diff) |
[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>
-rw-r--r-- | fs/cifs/file.c | 22 |
1 files changed, 22 insertions, 0 deletions
diff --git a/fs/cifs/file.c b/fs/cifs/file.c index 7ddddf2e2504..5a5a87240fe2 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c | |||
@@ -3663,6 +3663,27 @@ void cifs_oplock_break(struct work_struct *work) | |||
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 | const struct address_space_operations cifs_addr_ops = { | 3687 | const struct address_space_operations cifs_addr_ops = { |
3667 | .readpage = cifs_readpage, | 3688 | .readpage = cifs_readpage, |
3668 | .readpages = cifs_readpages, | 3689 | .readpages = cifs_readpages, |
@@ -3672,6 +3693,7 @@ const struct address_space_operations cifs_addr_ops = { | |||
3672 | .write_end = cifs_write_end, | 3693 | .write_end = cifs_write_end, |
3673 | .set_page_dirty = __set_page_dirty_nobuffers, | 3694 | .set_page_dirty = __set_page_dirty_nobuffers, |
3674 | .releasepage = cifs_release_page, | 3695 | .releasepage = cifs_release_page, |
3696 | .direct_IO = cifs_direct_io, | ||
3675 | .invalidatepage = cifs_invalidate_page, | 3697 | .invalidatepage = cifs_invalidate_page, |
3676 | .launder_page = cifs_launder_page, | 3698 | .launder_page = cifs_launder_page, |
3677 | }; | 3699 | }; |