r20774: I thought I committed this before Xmas holidays ...
[Samba.git] / source / modules / vfs_commit.c
blob4407490d2232cb4df8e45835b44e5184d192f641
1 /*
2 * Copyright (c) James Peach 2006
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.
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.
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.
19 #include "includes.h"
21 /* Commit data module.
23 * The purpose of this module is to flush data to disk at regular intervals,
24 * just like the NFS commit operation. There's two rationales for this. First,
25 * it minimises the data loss in case of a power outage without incurring
26 * the poor performance of synchronous I/O. Second, a steady flush rate
27 * can produce better throughput than suddenly dumping massive amounts of
28 * writes onto a disk.
30 * Tunables:
32 * commit: dthresh Amount of dirty data that can accumulate
33 * before we commit (sync) it.
35 * commit: debug Debug level at which to emit messages.
39 #define MODULE "commit"
41 static int module_debug;
43 struct commit_info
45 SMB_OFF_T dbytes; /* Dirty (uncommitted) bytes */
46 SMB_OFF_T dthresh; /* Dirty data threshold */
49 static void commit_all(
50 struct vfs_handle_struct * handle,
51 files_struct * fsp)
53 struct commit_info *c;
55 if ((c = VFS_FETCH_FSP_EXTENSION(handle, fsp))) {
56 if (c->dbytes) {
57 DEBUG(module_debug,
58 ("%s: flushing %lu dirty bytes\n",
59 MODULE, (unsigned long)c->dbytes));
61 fdatasync(fsp->fh->fd);
62 c->dbytes = 0;
67 static void commit(
68 struct vfs_handle_struct * handle,
69 files_struct * fsp,
70 ssize_t last_write)
72 struct commit_info *c;
74 if ((c = VFS_FETCH_FSP_EXTENSION(handle, fsp))) {
76 if (last_write > 0) {
77 c->dbytes += last_write;
80 if (c->dbytes > c->dthresh) {
81 DEBUG(module_debug,
82 ("%s: flushing %lu dirty bytes\n",
83 MODULE, (unsigned long)c->dbytes));
85 fdatasync(fsp->fh->fd);
86 c->dbytes = 0;
91 static int commit_connect(
92 struct vfs_handle_struct * handle,
93 const char * service,
94 const char * user)
96 module_debug = lp_parm_int(SNUM(handle->conn), MODULE, "debug", 100);
97 return SMB_VFS_NEXT_CONNECT(handle, service, user);
100 static int commit_open(
101 vfs_handle_struct * handle,
102 const char * fname,
103 files_struct * fsp,
104 int flags,
105 mode_t mode)
107 SMB_OFF_T dthresh;
109 /* Don't bother with read-only files. */
110 if ((flags & O_ACCMODE) == O_RDONLY) {
111 return SMB_VFS_NEXT_OPEN(handle, fname, fsp, flags, mode);
114 dthresh = conv_str_size(lp_parm_const_string(SNUM(handle->conn),
115 MODULE, "dthresh", NULL));
117 if (dthresh > 0) {
118 struct commit_info * c;
119 c = VFS_ADD_FSP_EXTENSION(handle, fsp, struct commit_info);
120 if (c) {
121 c->dthresh = dthresh;
122 c->dbytes = 0;
126 return SMB_VFS_NEXT_OPEN(handle, fname, fsp, flags, mode);
129 static ssize_t commit_write(
130 vfs_handle_struct * handle,
131 files_struct * fsp,
132 int fd,
133 void * data,
134 size_t count)
136 ssize_t ret;
138 ret = SMB_VFS_NEXT_WRITE(handle, fsp, fd, data, count);
139 commit(handle, fsp, ret);
141 return ret;
144 static ssize_t commit_pwrite(
145 vfs_handle_struct * handle,
146 files_struct * fsp,
147 int fd,
148 void * data,
149 size_t count,
150 SMB_OFF_T offset)
152 ssize_t ret;
154 ret = SMB_VFS_NEXT_PWRITE(handle, fsp, fd, data, count, offset);
155 commit(handle, fsp, ret);
157 return ret;
160 static ssize_t commit_close(
161 vfs_handle_struct * handle,
162 files_struct * fsp,
163 int fd)
165 commit_all(handle, fsp);
166 return SMB_VFS_NEXT_CLOSE(handle, fsp, fd);
169 static vfs_op_tuple commit_ops [] =
171 {SMB_VFS_OP(commit_open),
172 SMB_VFS_OP_OPEN, SMB_VFS_LAYER_TRANSPARENT},
173 {SMB_VFS_OP(commit_close),
174 SMB_VFS_OP_CLOSE, SMB_VFS_LAYER_TRANSPARENT},
175 {SMB_VFS_OP(commit_write),
176 SMB_VFS_OP_WRITE, SMB_VFS_LAYER_TRANSPARENT},
177 {SMB_VFS_OP(commit_pwrite),
178 SMB_VFS_OP_PWRITE, SMB_VFS_LAYER_TRANSPARENT},
179 {SMB_VFS_OP(commit_connect),
180 SMB_VFS_OP_CONNECT, SMB_VFS_LAYER_TRANSPARENT},
182 {SMB_VFS_OP(NULL), SMB_VFS_OP_NOOP, SMB_VFS_LAYER_NOOP}
185 NTSTATUS vfs_commit_init(void);
186 NTSTATUS vfs_commit_init(void)
188 return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, MODULE, commit_ops);