source: branches/samba-3.0/source/modules/vfs_commit.c

Last change on this file was 1, checked in by Paul Smedley, 18 years ago

Initial code import

File size: 5.5 KB
Line 
1/*
2 * Copyright (c) James Peach 2006
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
19#include "includes.h"
20
21/* Commit data module.
22 *
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.
29 *
30 * Tunables:
31 *
32 * commit: dthresh Amount of dirty data that can accumulate
33 * before we commit (sync) it.
34 *
35 * commit: debug Debug level at which to emit messages.
36 *
37 */
38
39#define MODULE "commit"
40
41static int module_debug;
42
43struct commit_info
44{
45 SMB_OFF_T dbytes; /* Dirty (uncommitted) bytes */
46 SMB_OFF_T dthresh; /* Dirty data threshold */
47};
48
49static void commit_all(
50 struct vfs_handle_struct * handle,
51 files_struct * fsp)
52{
53 struct commit_info *c;
54
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));
60
61 fdatasync(fsp->fh->fd);
62 c->dbytes = 0;
63 }
64 }
65}
66
67static void commit(
68 struct vfs_handle_struct * handle,
69 files_struct * fsp,
70 ssize_t last_write)
71{
72 struct commit_info *c;
73
74 if ((c = VFS_FETCH_FSP_EXTENSION(handle, fsp))) {
75
76 if (last_write > 0) {
77 c->dbytes += last_write;
78 }
79
80 if (c->dbytes > c->dthresh) {
81 DEBUG(module_debug,
82 ("%s: flushing %lu dirty bytes\n",
83 MODULE, (unsigned long)c->dbytes));
84
85 fdatasync(fsp->fh->fd);
86 c->dbytes = 0;
87 }
88 }
89}
90
91static int commit_connect(
92 struct vfs_handle_struct * handle,
93 const char * service,
94 const char * user)
95{
96 module_debug = lp_parm_int(SNUM(handle->conn), MODULE, "debug", 100);
97 return SMB_VFS_NEXT_CONNECT(handle, service, user);
98}
99
100static int commit_open(
101 vfs_handle_struct * handle,
102 const char * fname,
103 files_struct * fsp,
104 int flags,
105 mode_t mode)
106{
107 SMB_OFF_T dthresh;
108
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);
112 }
113
114 dthresh = conv_str_size(lp_parm_const_string(SNUM(handle->conn),
115 MODULE, "dthresh", NULL));
116
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;
123 }
124 }
125
126 return SMB_VFS_NEXT_OPEN(handle, fname, fsp, flags, mode);
127}
128
129static ssize_t commit_write(
130 vfs_handle_struct * handle,
131 files_struct * fsp,
132 int fd,
133 void * data,
134 size_t count)
135{
136 ssize_t ret;
137
138 ret = SMB_VFS_NEXT_WRITE(handle, fsp, fd, data, count);
139 commit(handle, fsp, ret);
140
141 return ret;
142}
143
144static 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)
151{
152 ssize_t ret;
153
154 ret = SMB_VFS_NEXT_PWRITE(handle, fsp, fd, data, count, offset);
155 commit(handle, fsp, ret);
156
157 return ret;
158}
159
160static ssize_t commit_close(
161 vfs_handle_struct * handle,
162 files_struct * fsp,
163 int fd)
164{
165 commit_all(handle, fsp);
166 return SMB_VFS_NEXT_CLOSE(handle, fsp, fd);
167}
168
169static vfs_op_tuple commit_ops [] =
170{
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},
181
182 {SMB_VFS_OP(NULL), SMB_VFS_OP_NOOP, SMB_VFS_LAYER_NOOP}
183};
184
185NTSTATUS vfs_commit_init(void);
186NTSTATUS vfs_commit_init(void)
187{
188 return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, MODULE, commit_ops);
189}
190
Note: See TracBrowser for help on using the repository browser.