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.
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
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;
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,
53 struct commit_info *c;
55 if ((c = VFS_FETCH_FSP_EXTENSION(handle, fsp))) {
58 ("%s: flushing %lu dirty bytes\n",
59 MODULE, (unsigned long)c->dbytes));
61 fdatasync(fsp->fh->fd);
68 struct vfs_handle_struct * handle,
72 struct commit_info *c;
74 if ((c = VFS_FETCH_FSP_EXTENSION(handle, fsp))) {
77 c->dbytes += last_write;
80 if (c->dbytes > c->dthresh) {
82 ("%s: flushing %lu dirty bytes\n",
83 MODULE, (unsigned long)c->dbytes));
85 fdatasync(fsp->fh->fd);
91 static int commit_connect(
92 struct vfs_handle_struct * handle,
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,
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));
118 struct commit_info * c;
119 c = VFS_ADD_FSP_EXTENSION(handle, fsp, struct commit_info);
121 c->dthresh = dthresh;
126 return SMB_VFS_NEXT_OPEN(handle, fname, fsp, flags, mode);
129 static ssize_t commit_write(
130 vfs_handle_struct * handle,
138 ret = SMB_VFS_NEXT_WRITE(handle, fsp, fd, data, count);
139 commit(handle, fsp, ret);
144 static ssize_t commit_pwrite(
145 vfs_handle_struct * handle,
154 ret = SMB_VFS_NEXT_PWRITE(handle, fsp, fd, data, count, offset);
155 commit(handle, fsp, ret);
160 static ssize_t commit_close(
161 vfs_handle_struct * handle,
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)
187 return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, MODULE, commit_ops);