LCOV - code coverage report
Current view: top level - source3/modules - vfs_readahead.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 2 37 5.4 %
Date: 2024-04-21 15:09:00 Functions: 1 5 20.0 %

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) Jeremy Allison 2007.
       3             :  *
       4             :  * This program is free software; you can redistribute it and/or modify
       5             :  * it under the terms of the GNU General Public License as published by
       6             :  * the Free Software Foundation; either version 3 of the License, or
       7             :  * (at your option) any later version.
       8             :  *
       9             :  * This program is distributed in the hope that it will be useful,
      10             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      11             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      12             :  * GNU General Public License for more details.
      13             :  *
      14             :  * You should have received a copy of the GNU General Public License
      15             :  * along with this program; if not, see <http://www.gnu.org/licenses/>.
      16             :  */
      17             : 
      18             : #include "includes.h"
      19             : #include "system/filesys.h"
      20             : #include "smbd/smbd.h"
      21             : 
      22             : #if defined(HAVE_LINUX_READAHEAD) && ! defined(HAVE_READAHEAD_DECL)
      23             : ssize_t readahead(int fd, off_t offset, size_t count);
      24             : #endif
      25             : 
      26             : struct readahead_data {
      27             :         off_t off_bound;
      28             :         off_t len;
      29             :         bool didmsg;
      30             : };
      31             : 
      32             : /* 
      33             :  * This module copes with Vista AIO read requests on Linux
      34             :  * by detecting the initial 0x80000 boundary reads and causing
      35             :  * the buffer cache to be filled in advance.
      36             :  */
      37             : 
      38             : /*******************************************************************
      39             :  sendfile wrapper that does readahead/posix_fadvise.
      40             : *******************************************************************/
      41             : 
      42           0 : static ssize_t readahead_sendfile(struct vfs_handle_struct *handle,
      43             :                                         int tofd,
      44             :                                         files_struct *fromfsp,
      45             :                                         const DATA_BLOB *header,
      46             :                                         off_t offset,
      47             :                                         size_t count)
      48             : {
      49           0 :         struct readahead_data *rhd = (struct readahead_data *)handle->data;
      50             : 
      51           0 :         if ( offset % rhd->off_bound == 0) {
      52             : #if defined(HAVE_LINUX_READAHEAD)
      53           0 :                 int err = readahead(fsp_get_io_fd(fromfsp), offset, (size_t)rhd->len);
      54           0 :                 DEBUG(10,("readahead_sendfile: readahead on fd %u, offset %llu, len %u returned %d\n",
      55             :                         (unsigned int)fsp_get_io_fd(fromfsp),
      56             :                         (unsigned long long)offset,
      57             :                         (unsigned int)rhd->len,
      58             :                         err ));
      59             : #elif defined(HAVE_POSIX_FADVISE)
      60             :                 int err = posix_fadvise(fsp_get_io_fd(fromfsp), offset, (off_t)rhd->len, POSIX_FADV_WILLNEED);
      61             :                 DEBUG(10,("readahead_sendfile: posix_fadvise on fd %u, offset %llu, len %u returned %d\n",
      62             :                         (unsigned int)fsp_get_io_fd(fromfsp),
      63             :                         (unsigned long long)offset,
      64             :                         (unsigned int)rhd->len,
      65             :                         err ));
      66             : #else
      67             :                 if (!rhd->didmsg) {
      68             :                         DEBUG(0,("readahead_sendfile: no readahead on this platform\n"));
      69             :                         rhd->didmsg = True;
      70             :                 }
      71             : #endif
      72             :         }
      73           0 :         return SMB_VFS_NEXT_SENDFILE(handle,
      74             :                                         tofd,
      75             :                                         fromfsp,
      76             :                                         header,
      77             :                                         offset,
      78             :                                         count);
      79             : }
      80             : 
      81             : /*******************************************************************
      82             :  pread wrapper that does readahead/posix_fadvise.
      83             : *******************************************************************/
      84             : 
      85           0 : static ssize_t readahead_pread(vfs_handle_struct *handle,
      86             :                                 files_struct *fsp,
      87             :                                 void *data,
      88             :                                 size_t count,
      89             :                                 off_t offset)
      90             : {
      91           0 :         struct readahead_data *rhd = (struct readahead_data *)handle->data;
      92             : 
      93           0 :         if ( offset % rhd->off_bound == 0) {
      94             : #if defined(HAVE_LINUX_READAHEAD)
      95           0 :                 int err = readahead(fsp_get_io_fd(fsp), offset, (size_t)rhd->len);
      96           0 :                 DEBUG(10,("readahead_pread: readahead on fd %u, offset %llu, len %u returned %d\n",
      97             :                         (unsigned int)fsp_get_io_fd(fsp),
      98             :                         (unsigned long long)offset,
      99             :                         (unsigned int)rhd->len,
     100             :                         err ));
     101             : #elif defined(HAVE_POSIX_FADVISE)
     102             :                 int err = posix_fadvise(fsp_get_io_fd(fsp), offset, (off_t)rhd->len, POSIX_FADV_WILLNEED);
     103             :                 DEBUG(10,("readahead_pread: posix_fadvise on fd %u, offset %llu, len %u returned %d\n",
     104             :                         (unsigned int)fsp_get_io_fd(fsp),
     105             :                         (unsigned long long)offset,
     106             :                         (unsigned int)rhd->len,
     107             :                         err ));
     108             : #else
     109             :                 if (!rhd->didmsg) {
     110             :                         DEBUG(0,("readahead_pread: no readahead on this platform\n"));
     111             :                         rhd->didmsg = True;
     112             :                 }
     113             : #endif
     114             :         }
     115           0 :         return SMB_VFS_NEXT_PREAD(handle, fsp, data, count, offset);
     116             : }
     117             : 
     118             : /*******************************************************************
     119             :  Directly called from main smbd when freeing handle.
     120             : *******************************************************************/
     121             : 
     122           0 : static void free_readahead_data(void **pptr)
     123             : {
     124           0 :         SAFE_FREE(*pptr);
     125           0 : }
     126             : 
     127             : /*******************************************************************
     128             :  Allocate the handle specific data so we don't call the expensive
     129             :  conv_str_size function for each sendfile/pread.
     130             : *******************************************************************/
     131             : 
     132           0 : static int readahead_connect(struct vfs_handle_struct *handle,
     133             :                                 const char *service,
     134             :                                 const char *user)
     135             : {
     136             :         struct readahead_data *rhd;
     137           0 :         int ret = SMB_VFS_NEXT_CONNECT(handle, service, user);
     138             : 
     139           0 :         if (ret < 0) {
     140           0 :                 return ret;
     141             :         }
     142           0 :         rhd = SMB_MALLOC_P(struct readahead_data);
     143           0 :         if (!rhd) {
     144           0 :                 SMB_VFS_NEXT_DISCONNECT(handle);
     145           0 :                 DEBUG(0,("readahead_connect: out of memory\n"));
     146           0 :                 return -1;
     147             :         }
     148           0 :         ZERO_STRUCTP(rhd);
     149             : 
     150           0 :         rhd->didmsg = False;
     151           0 :         rhd->off_bound = conv_str_size(lp_parm_const_string(SNUM(handle->conn),
     152             :                                                 "readahead",
     153             :                                                 "offset",
     154             :                                                 NULL));
     155           0 :         if (rhd->off_bound == 0) {
     156           0 :                 rhd->off_bound = 0x80000;
     157             :         }
     158           0 :         rhd->len = conv_str_size(lp_parm_const_string(SNUM(handle->conn),
     159             :                                                 "readahead",
     160             :                                                 "length",
     161             :                                                 NULL));
     162           0 :         if (rhd->len == 0) {
     163           0 :                 rhd->len = rhd->off_bound;
     164             :         }
     165             : 
     166           0 :         handle->data = (void *)rhd;
     167           0 :         handle->free_data = free_readahead_data;
     168           0 :         return 0;
     169             : }
     170             : 
     171             : static struct vfs_fn_pointers vfs_readahead_fns = {
     172             :         .sendfile_fn = readahead_sendfile,
     173             :         .pread_fn = readahead_pread,
     174             :         .connect_fn = readahead_connect
     175             : };
     176             : 
     177             : /*******************************************************************
     178             :  Module initialization boilerplate.
     179             : *******************************************************************/
     180             : 
     181             : static_decl_vfs;
     182          27 : NTSTATUS vfs_readahead_init(TALLOC_CTX *ctx)
     183             : {
     184          27 :         return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, "readahead",
     185             :                                 &vfs_readahead_fns);
     186             : }

Generated by: LCOV version 1.14