PageRenderTime 37ms CodeModel.GetById 10ms RepoModel.GetById 0ms app.codeStats 0ms

/release/src/router/samba3/source/modules/vfs_readahead.c

https://gitlab.com/envieidoc/tomato
C | 188 lines | 125 code | 20 blank | 43 comment | 12 complexity | 8122bc6857a59eea2b143bdac1af67d3 MD5 | raw file
  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 2 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, write to the Free Software
  16. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17. */
  18. #include "includes.h"
  19. #if !defined(HAVE_LINUX_READAHEAD) && !defined(HAVE_POSIX_FADVISE)
  20. static BOOL didmsg;
  21. #endif
  22. struct readahead_data {
  23. SMB_OFF_T off_bound;
  24. SMB_OFF_T len;
  25. BOOL didmsg;
  26. };
  27. /*
  28. * This module copes with Vista AIO read requests on Linux
  29. * by detecting the initial 0x80000 boundary reads and causing
  30. * the buffer cache to be filled in advance.
  31. */
  32. /*******************************************************************
  33. sendfile wrapper that does readahead/posix_fadvise.
  34. *******************************************************************/
  35. static ssize_t readahead_sendfile(struct vfs_handle_struct *handle,
  36. int tofd,
  37. files_struct *fsp,
  38. int fromfd,
  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. if ( offset % rhd->off_bound == 0) {
  45. #if defined(HAVE_LINUX_READAHEAD)
  46. int err = readahead(fromfd, offset, (size_t)rhd->len);
  47. DEBUG(10,("readahead_sendfile: readahead on fd %u, offset %llu, len %u returned %d\n",
  48. (unsigned int)fromfd,
  49. (unsigned long long)offset,
  50. (unsigned int)rhd->len,
  51. err ));
  52. #elif defined(HAVE_POSIX_FADVISE)
  53. int err = posix_fadvise(fromfd, offset, (off_t)rhd->len, POSIX_FADV_WILLNEED);
  54. DEBUG(10,("readahead_sendfile: posix_fadvise on fd %u, offset %llu, len %u returned %d\n",
  55. (unsigned int)fromfd,
  56. (unsigned long long)offset,
  57. (unsigned int)rhd->len,
  58. err ));
  59. #else
  60. if (!rhd->didmsg) {
  61. DEBUG(0,("readahead_sendfile: no readahead on this platform\n"));
  62. rhd->didmsg = True;
  63. }
  64. #endif
  65. }
  66. return SMB_VFS_NEXT_SENDFILE(handle,
  67. tofd,
  68. fsp,
  69. fromfd,
  70. header,
  71. offset,
  72. count);
  73. }
  74. /*******************************************************************
  75. pread wrapper that does readahead/posix_fadvise.
  76. *******************************************************************/
  77. static ssize_t readahead_pread(vfs_handle_struct *handle,
  78. files_struct *fsp,
  79. int fd,
  80. void *data,
  81. size_t count,
  82. SMB_OFF_T offset)
  83. {
  84. struct readahead_data *rhd = (struct readahead_data *)handle->data;
  85. if ( offset % rhd->off_bound == 0) {
  86. #if defined(HAVE_LINUX_READAHEAD)
  87. int err = readahead(fd, offset, (size_t)rhd->len);
  88. DEBUG(10,("readahead_pread: readahead on fd %u, offset %llu, len %u returned %d\n",
  89. (unsigned int)fd,
  90. (unsigned long long)offset,
  91. (unsigned int)rhd->len,
  92. err ));
  93. #elif defined(HAVE_POSIX_FADVISE)
  94. int err = posix_fadvise(fd, offset, (off_t)rhd->len, POSIX_FADV_WILLNEED);
  95. DEBUG(10,("readahead_pread: posix_fadvise on fd %u, offset %llu, len %u returned %d\n",
  96. (unsigned int)fd,
  97. (unsigned long long)offset,
  98. (unsigned int)rhd->len,
  99. err ));
  100. #else
  101. if (!rhd->didmsg) {
  102. DEBUG(0,("readahead_pread: no readahead on this platform\n"));
  103. rhd->didmsg = True;
  104. }
  105. #endif
  106. }
  107. return SMB_VFS_NEXT_PREAD(handle, fsp, fd, data, count, offset);
  108. }
  109. /*******************************************************************
  110. Directly called from main smbd when freeing handle.
  111. *******************************************************************/
  112. static void free_readahead_data(void **pptr)
  113. {
  114. SAFE_FREE(*pptr);
  115. }
  116. /*******************************************************************
  117. Allocate the handle specific data so we don't call the expensive
  118. conv_str_size function for each sendfile/pread.
  119. *******************************************************************/
  120. static int readahead_connect(struct vfs_handle_struct *handle,
  121. const char *service,
  122. const char *user)
  123. {
  124. struct readahead_data *rhd = SMB_MALLOC_P(struct readahead_data);
  125. if (!rhd) {
  126. DEBUG(0,("readahead_connect: out of memory\n"));
  127. return -1;
  128. }
  129. ZERO_STRUCTP(rhd);
  130. rhd->didmsg = False;
  131. rhd->off_bound = conv_str_size(lp_parm_const_string(SNUM(handle->conn),
  132. "readahead",
  133. "offset",
  134. NULL));
  135. if (rhd->off_bound == 0) {
  136. rhd->off_bound = 0x80000;
  137. }
  138. rhd->len = conv_str_size(lp_parm_const_string(SNUM(handle->conn),
  139. "readahead",
  140. "length",
  141. NULL));
  142. if (rhd->len == 0) {
  143. rhd->len = rhd->off_bound;
  144. }
  145. handle->data = (void *)rhd;
  146. handle->free_data = free_readahead_data;
  147. return SMB_VFS_NEXT_CONNECT(handle, service, user);
  148. }
  149. /*******************************************************************
  150. Functions we're replacing.
  151. We don't replace read as it isn't used from smbd to read file
  152. data.
  153. *******************************************************************/
  154. static vfs_op_tuple readahead_ops [] =
  155. {
  156. {SMB_VFS_OP(readahead_sendfile), SMB_VFS_OP_SENDFILE, SMB_VFS_LAYER_TRANSPARENT},
  157. {SMB_VFS_OP(readahead_pread), SMB_VFS_OP_PREAD, SMB_VFS_LAYER_TRANSPARENT},
  158. {SMB_VFS_OP(readahead_connect), SMB_VFS_OP_CONNECT, SMB_VFS_LAYER_TRANSPARENT},
  159. {SMB_VFS_OP(NULL), SMB_VFS_OP_NOOP, SMB_VFS_LAYER_NOOP}
  160. };
  161. /*******************************************************************
  162. Module initialization boilerplate.
  163. *******************************************************************/
  164. NTSTATUS vfs_readahead_init(void);
  165. NTSTATUS vfs_readahead_init(void)
  166. {
  167. return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, "readahead", readahead_ops);
  168. }