modules/vfs_readahead.c

説明を見る。
00001 /*
00002  * Copyright (c) Jeremy Allison 2007.
00003  *
00004  * This program is free software; you can redistribute it and/or modify
00005  * it under the terms of the GNU General Public License as published by
00006  * the Free Software Foundation; either version 2 of the License, or
00007  * (at your option) any later version.
00008  *
00009  * This program is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  * GNU General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software
00016  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00017  */
00018 
00019 #include "includes.h"
00020 
00021 #if !defined(HAVE_LINUX_READAHEAD) && !defined(HAVE_POSIX_FADVISE)
00022 static BOOL didmsg;
00023 #endif
00024 
00025 struct readahead_data {
00026         SMB_OFF_T off_bound;
00027         SMB_OFF_T len;
00028         BOOL didmsg;
00029 };
00030 
00031 /* 
00032  * This module copes with Vista AIO read requests on Linux
00033  * by detecting the initial 0x80000 boundary reads and causing
00034  * the buffer cache to be filled in advance.
00035  */
00036 
00037 /*******************************************************************
00038  sendfile wrapper that does readahead/posix_fadvise.
00039 *******************************************************************/
00040 
00041 static ssize_t readahead_sendfile(struct vfs_handle_struct *handle,
00042                                         int tofd,
00043                                         files_struct *fsp,
00044                                         int fromfd,
00045                                         const DATA_BLOB *header,
00046                                         SMB_OFF_T offset,
00047                                         size_t count)
00048 {
00049         struct readahead_data *rhd = (struct readahead_data *)handle->data;
00050 
00051         if ( offset % rhd->off_bound == 0) {
00052 #if defined(HAVE_LINUX_READAHEAD)
00053                 int err = readahead(fromfd, offset, (size_t)rhd->len);
00054                 DEBUG(10,("readahead_sendfile: readahead on fd %u, offset %llu, len %u returned %d\n",
00055                         (unsigned int)fromfd,
00056                         (unsigned long long)offset,
00057                         (unsigned int)rhd->len,
00058                         err ));
00059 #elif defined(HAVE_POSIX_FADVISE)
00060                 int err = posix_fadvise(fromfd, offset, (off_t)rhd->len, POSIX_FADV_WILLNEED);
00061                 DEBUG(10,("readahead_sendfile: posix_fadvise on fd %u, offset %llu, len %u returned %d\n",
00062                         (unsigned int)fromfd,
00063                         (unsigned long long)offset,
00064                         (unsigned int)rhd->len,
00065                         err ));
00066 #else
00067                 if (!rhd->didmsg) {
00068                         DEBUG(0,("readahead_sendfile: no readahead on this platform\n"));
00069                         rhd->didmsg = True;
00070                 }
00071 #endif
00072         }
00073         return SMB_VFS_NEXT_SENDFILE(handle,
00074                                         tofd,
00075                                         fsp,
00076                                         fromfd,
00077                                         header,
00078                                         offset,
00079                                         count);
00080 }
00081 
00082 /*******************************************************************
00083  pread wrapper that does readahead/posix_fadvise.
00084 *******************************************************************/
00085 
00086 static ssize_t readahead_pread(vfs_handle_struct *handle,
00087                                 files_struct *fsp,
00088                                 int fd,
00089                                 void *data,
00090                                 size_t count,
00091                                 SMB_OFF_T offset)
00092 {
00093         struct readahead_data *rhd = (struct readahead_data *)handle->data;
00094 
00095         if ( offset % rhd->off_bound == 0) {
00096 #if defined(HAVE_LINUX_READAHEAD)
00097                 int err = readahead(fd, offset, (size_t)rhd->len);
00098                 DEBUG(10,("readahead_pread: readahead on fd %u, offset %llu, len %u returned %d\n",
00099                         (unsigned int)fd,
00100                         (unsigned long long)offset,
00101                         (unsigned int)rhd->len,
00102                         err ));
00103 #elif defined(HAVE_POSIX_FADVISE)
00104                 int err = posix_fadvise(fd, offset, (off_t)rhd->len, POSIX_FADV_WILLNEED);
00105                 DEBUG(10,("readahead_pread: posix_fadvise on fd %u, offset %llu, len %u returned %d\n",
00106                         (unsigned int)fd,
00107                         (unsigned long long)offset,
00108                         (unsigned int)rhd->len,
00109                         err ));
00110 #else
00111                 if (!rhd->didmsg) {
00112                         DEBUG(0,("readahead_pread: no readahead on this platform\n"));
00113                         rhd->didmsg = True;
00114                 }
00115 #endif
00116         }
00117         return SMB_VFS_NEXT_PREAD(handle, fsp, fd, data, count, offset);
00118 }
00119 
00120 /*******************************************************************
00121  Directly called from main smbd when freeing handle.
00122 *******************************************************************/
00123 
00124 static void free_readahead_data(void **pptr)
00125 {
00126         SAFE_FREE(*pptr);
00127 }
00128 
00129 /*******************************************************************
00130  Allocate the handle specific data so we don't call the expensive
00131  conv_str_size function for each sendfile/pread.
00132 *******************************************************************/
00133 
00134 static int readahead_connect(struct vfs_handle_struct *handle,
00135                                 const char *service,
00136                                 const char *user)
00137 {
00138         struct readahead_data *rhd = SMB_MALLOC_P(struct readahead_data);
00139         if (!rhd) {
00140                 DEBUG(0,("readahead_connect: out of memory\n"));
00141                 return -1;
00142         }
00143         ZERO_STRUCTP(rhd);
00144 
00145         rhd->didmsg = False;
00146         rhd->off_bound = conv_str_size(lp_parm_const_string(SNUM(handle->conn),
00147                                                 "readahead",
00148                                                 "offset",
00149                                                 NULL));
00150         if (rhd->off_bound == 0) {
00151                 rhd->off_bound = 0x80000;
00152         }
00153         rhd->len = conv_str_size(lp_parm_const_string(SNUM(handle->conn),
00154                                                 "readahead",
00155                                                 "length",
00156                                                 NULL));
00157         if (rhd->len == 0) {
00158                 rhd->len = rhd->off_bound;
00159         }
00160 
00161         handle->data = (void *)rhd;
00162         handle->free_data = free_readahead_data;
00163         return SMB_VFS_NEXT_CONNECT(handle, service, user);
00164 }
00165 
00166 /*******************************************************************
00167  Functions we're replacing.
00168  We don't replace read as it isn't used from smbd to read file
00169  data.
00170 *******************************************************************/
00171 
00172 static vfs_op_tuple readahead_ops [] =
00173 {
00174         {SMB_VFS_OP(readahead_sendfile), SMB_VFS_OP_SENDFILE, SMB_VFS_LAYER_TRANSPARENT},
00175         {SMB_VFS_OP(readahead_pread), SMB_VFS_OP_PREAD, SMB_VFS_LAYER_TRANSPARENT},
00176         {SMB_VFS_OP(readahead_connect), SMB_VFS_OP_CONNECT,  SMB_VFS_LAYER_TRANSPARENT},
00177         {SMB_VFS_OP(NULL), SMB_VFS_OP_NOOP, SMB_VFS_LAYER_NOOP}
00178 };
00179 
00180 /*******************************************************************
00181  Module initialization boilerplate.
00182 *******************************************************************/
00183 
00184 NTSTATUS vfs_readahead_init(void);
00185 NTSTATUS vfs_readahead_init(void)
00186 {
00187         return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, "readahead", readahead_ops);
00188 }

Sambaに対してSat Aug 29 21:23:07 2009に生成されました。  doxygen 1.4.7