smbd: Remove unused [push_pull]_file_id_24
[samba.git] / source3 / modules / vfs_readahead.c
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
20 struct readahead_data {
21         SMB_OFF_T off_bound;
22         SMB_OFF_T len;
23         bool didmsg;
24 };
25
26 /* 
27  * This module copes with Vista AIO read requests on Linux
28  * by detecting the initial 0x80000 boundary reads and causing
29  * the buffer cache to be filled in advance.
30  */
31
32 /*******************************************************************
33  sendfile wrapper that does readahead/posix_fadvise.
34 *******************************************************************/
35
36 static ssize_t readahead_sendfile(struct vfs_handle_struct *handle,
37                                         int tofd,
38                                         files_struct *fromfsp,
39                                         const DATA_BLOB *header,
40                                         SMB_OFF_T offset,
41                                         size_t count)
42 {
43         struct readahead_data *rhd = (struct readahead_data *)handle->data;
44
45         if ( offset % rhd->off_bound == 0) {
46 #if defined(HAVE_LINUX_READAHEAD)
47                 int err = readahead(fromfsp->fh->fd, offset, (size_t)rhd->len);
48                 DEBUG(10,("readahead_sendfile: readahead on fd %u, offset %llu, len %u returned %d\n",
49                         (unsigned int)fromfsp->fh->fd,
50                         (unsigned long long)offset,
51                         (unsigned int)rhd->len,
52                         err ));
53 #elif defined(HAVE_POSIX_FADVISE)
54                 int err = posix_fadvise(fromfsp->fh->fd, offset, (off_t)rhd->len, POSIX_FADV_WILLNEED);
55                 DEBUG(10,("readahead_sendfile: posix_fadvise on fd %u, offset %llu, len %u returned %d\n",
56                         (unsigned int)fromfsp->fh->fd,
57                         (unsigned long long)offset,
58                         (unsigned int)rhd->len,
59                         err ));
60 #else
61                 if (!rhd->didmsg) {
62                         DEBUG(0,("readahead_sendfile: no readahead on this platform\n"));
63                         rhd->didmsg = True;
64                 }
65 #endif
66         }
67         return SMB_VFS_NEXT_SENDFILE(handle,
68                                         tofd,
69                                         fromfsp,
70                                         header,
71                                         offset,
72                                         count);
73 }
74
75 /*******************************************************************
76  pread wrapper that does readahead/posix_fadvise.
77 *******************************************************************/
78
79 static ssize_t readahead_pread(vfs_handle_struct *handle,
80                                 files_struct *fsp,
81                                 void *data,
82                                 size_t count,
83                                 SMB_OFF_T offset)
84 {
85         struct readahead_data *rhd = (struct readahead_data *)handle->data;
86
87         if ( offset % rhd->off_bound == 0) {
88 #if defined(HAVE_LINUX_READAHEAD)
89                 int err = readahead(fsp->fh->fd, offset, (size_t)rhd->len);
90                 DEBUG(10,("readahead_pread: readahead on fd %u, offset %llu, len %u returned %d\n",
91                         (unsigned int)fsp->fh->fd,
92                         (unsigned long long)offset,
93                         (unsigned int)rhd->len,
94                         err ));
95 #elif defined(HAVE_POSIX_FADVISE)
96                 int err = posix_fadvise(fsp->fh->fd, offset, (off_t)rhd->len, POSIX_FADV_WILLNEED);
97                 DEBUG(10,("readahead_pread: posix_fadvise on fd %u, offset %llu, len %u returned %d\n",
98                         (unsigned int)fsp->fh->fd,
99                         (unsigned long long)offset,
100                         (unsigned int)rhd->len,
101                         err ));
102 #else
103                 if (!rhd->didmsg) {
104                         DEBUG(0,("readahead_pread: no readahead on this platform\n"));
105                         rhd->didmsg = True;
106                 }
107 #endif
108         }
109         return SMB_VFS_NEXT_PREAD(handle, fsp, data, count, offset);
110 }
111
112 /*******************************************************************
113  Directly called from main smbd when freeing handle.
114 *******************************************************************/
115
116 static void free_readahead_data(void **pptr)
117 {
118         SAFE_FREE(*pptr);
119 }
120
121 /*******************************************************************
122  Allocate the handle specific data so we don't call the expensive
123  conv_str_size function for each sendfile/pread.
124 *******************************************************************/
125
126 static int readahead_connect(struct vfs_handle_struct *handle,
127                                 const char *service,
128                                 const char *user)
129 {
130         struct readahead_data *rhd;
131         int ret = SMB_VFS_NEXT_CONNECT(handle, service, user);
132
133         if (ret < 0) {
134                 return ret;
135         }
136         rhd = SMB_MALLOC_P(struct readahead_data);
137         if (!rhd) {
138                 SMB_VFS_NEXT_DISCONNECT(handle);
139                 DEBUG(0,("readahead_connect: out of memory\n"));
140                 return -1;
141         }
142         ZERO_STRUCTP(rhd);
143
144         rhd->didmsg = False;
145         rhd->off_bound = conv_str_size(lp_parm_const_string(SNUM(handle->conn),
146                                                 "readahead",
147                                                 "offset",
148                                                 NULL));
149         if (rhd->off_bound == 0) {
150                 rhd->off_bound = 0x80000;
151         }
152         rhd->len = conv_str_size(lp_parm_const_string(SNUM(handle->conn),
153                                                 "readahead",
154                                                 "length",
155                                                 NULL));
156         if (rhd->len == 0) {
157                 rhd->len = rhd->off_bound;
158         }
159
160         handle->data = (void *)rhd;
161         handle->free_data = free_readahead_data;
162         return 0;
163 }
164
165 static struct vfs_fn_pointers vfs_readahead_fns = {
166         .sendfile = readahead_sendfile,
167         .pread = readahead_pread,
168         .connect_fn = readahead_connect
169 };
170
171 /*******************************************************************
172  Module initialization boilerplate.
173 *******************************************************************/
174
175 NTSTATUS vfs_readahead_init(void);
176 NTSTATUS vfs_readahead_init(void)
177 {
178         return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, "readahead",
179                                 &vfs_readahead_fns);
180 }