2007-04-06 22:56:47 +04:00
/*
* Copyright ( c ) Jeremy Allison 2007.
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
2007-07-09 23:25:36 +04:00
* the Free Software Foundation ; either version 3 of the License , or
2007-04-06 22:56:47 +04:00
* ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
2007-07-10 09:23:25 +04:00
* along with this program ; if not , see < http : //www.gnu.org/licenses/>.
2007-04-06 22:56:47 +04:00
*/
# include "includes.h"
2011-02-26 01:20:06 +03:00
# include "system/filesys.h"
2011-03-23 00:34:22 +03:00
# include "smbd/smbd.h"
2007-04-06 22:56:47 +04:00
2011-04-14 02:52:45 +04:00
# if defined(HAVE_LINUX_READAHEAD) && ! defined(HAVE_READAHEAD_DECL)
2012-03-28 03:03:24 +04:00
ssize_t readahead ( int fd , off_t offset , size_t count ) ;
2011-04-14 02:52:45 +04:00
# endif
2007-04-08 23:41:47 +04:00
struct readahead_data {
2012-04-05 08:53:08 +04:00
off_t off_bound ;
off_t len ;
2007-10-19 04:40:25 +04:00
bool didmsg ;
2007-04-08 23:41:47 +04:00
} ;
2007-04-06 22:56:47 +04:00
/*
* This module copes with Vista AIO read requests on Linux
* by detecting the initial 0x80000 boundary reads and causing
* the buffer cache to be filled in advance .
*/
2007-04-08 23:41:47 +04:00
/*******************************************************************
sendfile wrapper that does readahead / posix_fadvise .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-04-07 01:12:44 +04:00
2007-04-06 22:56:47 +04:00
static ssize_t readahead_sendfile ( struct vfs_handle_struct * handle ,
int tofd ,
2008-01-11 02:51:19 +03:00
files_struct * fromfsp ,
2007-04-06 22:56:47 +04:00
const DATA_BLOB * header ,
2012-04-05 08:53:08 +04:00
off_t offset ,
2007-04-06 22:56:47 +04:00
size_t count )
{
2007-04-08 23:41:47 +04:00
struct readahead_data * rhd = ( struct readahead_data * ) handle - > data ;
if ( offset % rhd - > off_bound = = 0 ) {
2007-04-06 22:56:47 +04:00
# if defined(HAVE_LINUX_READAHEAD)
2008-01-11 02:51:19 +03:00
int err = readahead ( fromfsp - > fh - > fd , offset , ( size_t ) rhd - > len ) ;
2007-04-06 22:56:47 +04:00
DEBUG ( 10 , ( " readahead_sendfile: readahead on fd %u, offset %llu, len %u returned %d \n " ,
2008-01-11 02:51:19 +03:00
( unsigned int ) fromfsp - > fh - > fd ,
2007-04-06 22:56:47 +04:00
( unsigned long long ) offset ,
2007-04-08 23:41:47 +04:00
( unsigned int ) rhd - > len ,
2007-04-06 22:56:47 +04:00
err ) ) ;
# elif defined(HAVE_POSIX_FADVISE)
2008-01-11 02:51:19 +03:00
int err = posix_fadvise ( fromfsp - > fh - > fd , offset , ( off_t ) rhd - > len , POSIX_FADV_WILLNEED ) ;
2007-04-06 22:56:47 +04:00
DEBUG ( 10 , ( " readahead_sendfile: posix_fadvise on fd %u, offset %llu, len %u returned %d \n " ,
2008-01-11 02:51:19 +03:00
( unsigned int ) fromfsp - > fh - > fd ,
2007-04-06 22:56:47 +04:00
( unsigned long long ) offset ,
2007-04-08 23:41:47 +04:00
( unsigned int ) rhd - > len ,
2007-04-06 22:56:47 +04:00
err ) ) ;
# else
2007-04-08 23:41:47 +04:00
if ( ! rhd - > didmsg ) {
2007-04-06 22:56:47 +04:00
DEBUG ( 0 , ( " readahead_sendfile: no readahead on this platform \n " ) ) ;
2007-04-08 23:41:47 +04:00
rhd - > didmsg = True ;
2007-04-06 22:56:47 +04:00
}
# endif
}
return SMB_VFS_NEXT_SENDFILE ( handle ,
tofd ,
2008-01-11 02:51:19 +03:00
fromfsp ,
2007-04-06 22:56:47 +04:00
header ,
offset ,
count ) ;
}
2007-04-08 23:41:47 +04:00
/*******************************************************************
pread wrapper that does readahead / posix_fadvise .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-04-06 22:56:47 +04:00
static ssize_t readahead_pread ( vfs_handle_struct * handle ,
files_struct * fsp ,
void * data ,
size_t count ,
2012-04-05 08:53:08 +04:00
off_t offset )
2007-04-06 22:56:47 +04:00
{
2007-04-08 23:41:47 +04:00
struct readahead_data * rhd = ( struct readahead_data * ) handle - > data ;
if ( offset % rhd - > off_bound = = 0 ) {
2007-04-06 22:56:47 +04:00
# if defined(HAVE_LINUX_READAHEAD)
2008-01-07 02:14:19 +03:00
int err = readahead ( fsp - > fh - > fd , offset , ( size_t ) rhd - > len ) ;
2007-04-06 22:56:47 +04:00
DEBUG ( 10 , ( " readahead_pread: readahead on fd %u, offset %llu, len %u returned %d \n " ,
2008-01-07 02:14:19 +03:00
( unsigned int ) fsp - > fh - > fd ,
2007-04-06 22:56:47 +04:00
( unsigned long long ) offset ,
2007-04-08 23:41:47 +04:00
( unsigned int ) rhd - > len ,
2007-04-06 22:56:47 +04:00
err ) ) ;
# elif defined(HAVE_POSIX_FADVISE)
2008-01-07 02:14:19 +03:00
int err = posix_fadvise ( fsp - > fh - > fd , offset , ( off_t ) rhd - > len , POSIX_FADV_WILLNEED ) ;
2007-04-06 22:56:47 +04:00
DEBUG ( 10 , ( " readahead_pread: posix_fadvise on fd %u, offset %llu, len %u returned %d \n " ,
2008-01-07 02:14:19 +03:00
( unsigned int ) fsp - > fh - > fd ,
2007-04-06 22:56:47 +04:00
( unsigned long long ) offset ,
2007-04-08 23:41:47 +04:00
( unsigned int ) rhd - > len ,
2007-04-10 11:33:14 +04:00
err ) ) ;
2007-04-06 22:56:47 +04:00
# else
2007-04-08 23:41:47 +04:00
if ( ! rhd - > didmsg ) {
2007-04-06 22:56:47 +04:00
DEBUG ( 0 , ( " readahead_pread: no readahead on this platform \n " ) ) ;
2007-04-08 23:41:47 +04:00
rhd - > didmsg = True ;
2007-04-06 22:56:47 +04:00
}
# endif
}
2008-01-07 02:14:19 +03:00
return SMB_VFS_NEXT_PREAD ( handle , fsp , data , count , offset ) ;
2007-04-06 22:56:47 +04:00
}
2007-04-08 23:41:47 +04:00
/*******************************************************************
Directly called from main smbd when freeing handle .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static void free_readahead_data ( void * * pptr )
{
SAFE_FREE ( * pptr ) ;
}
/*******************************************************************
Allocate the handle specific data so we don ' t call the expensive
conv_str_size function for each sendfile / pread .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static int readahead_connect ( struct vfs_handle_struct * handle ,
const char * service ,
const char * user )
{
2009-12-01 02:53:04 +03:00
struct readahead_data * rhd ;
int ret = SMB_VFS_NEXT_CONNECT ( handle , service , user ) ;
if ( ret < 0 ) {
return ret ;
}
rhd = SMB_MALLOC_P ( struct readahead_data ) ;
2007-04-08 23:41:47 +04:00
if ( ! rhd ) {
2009-12-01 02:53:04 +03:00
SMB_VFS_NEXT_DISCONNECT ( handle ) ;
2007-04-08 23:41:47 +04:00
DEBUG ( 0 , ( " readahead_connect: out of memory \n " ) ) ;
return - 1 ;
}
ZERO_STRUCTP ( rhd ) ;
rhd - > didmsg = False ;
rhd - > off_bound = conv_str_size ( lp_parm_const_string ( SNUM ( handle - > conn ) ,
" readahead " ,
" offset " ,
NULL ) ) ;
if ( rhd - > off_bound = = 0 ) {
rhd - > off_bound = 0x80000 ;
}
rhd - > len = conv_str_size ( lp_parm_const_string ( SNUM ( handle - > conn ) ,
" readahead " ,
" length " ,
NULL ) ) ;
if ( rhd - > len = = 0 ) {
rhd - > len = rhd - > off_bound ;
}
handle - > data = ( void * ) rhd ;
handle - > free_data = free_readahead_data ;
2009-12-01 02:53:04 +03:00
return 0 ;
2007-04-08 23:41:47 +04:00
}
2009-07-24 04:28:58 +04:00
static struct vfs_fn_pointers vfs_readahead_fns = {
2011-12-04 08:45:04 +04:00
. sendfile_fn = readahead_sendfile ,
. pread_fn = readahead_pread ,
2009-07-24 04:28:58 +04:00
. connect_fn = readahead_connect
2007-04-06 22:56:47 +04:00
} ;
2007-04-08 23:41:47 +04:00
/*******************************************************************
Module initialization boilerplate .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2017-12-16 01:32:12 +03:00
static_decl_vfs ;
2017-04-20 22:24:43 +03:00
NTSTATUS vfs_readahead_init ( TALLOC_CTX * ctx )
2007-04-06 22:56:47 +04:00
{
2009-07-24 04:28:58 +04:00
return smb_register_vfs ( SMB_VFS_INTERFACE_VERSION , " readahead " ,
& vfs_readahead_fns ) ;
2007-04-06 22:56:47 +04:00
}