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);
186 NTSTATUS
vfs_commit_init(void)
188 return smb_register_vfs(SMB_VFS_INTERFACE_VERSION
, MODULE
, commit_ops
);