2
2
* ensure meta data operations are performed synchronously
4
4
* Copyright (C) Andrew Tridgell 2007
5
* Copyright (C) Christian Ambach, 2010-2011
6
7
* This program is free software; you can redistribute it and/or modify
7
8
* it under the terms of the GNU General Public License as published by
32
35
On those filesystems this module provides a way to perform those
37
38
most of the performance loss with this module is in fsync on close().
38
You can disable that with syncops:onclose = no
39
You can disable that with
41
that can be set either globally or per share.
43
On certain filesystems that only require the last data written to be
44
fsync()'ed, you can disable the metadata synchronization of this module with
46
This option can be set either globally or per share.
48
you can also disable the module completely for a share with
49
syncops:disable = true
40
static bool sync_onclose;
53
struct syncops_config_data {
43
60
given a filename, find the parent directory
125
142
const struct smb_filename *smb_fname_src,
126
143
const struct smb_filename *smb_fname_dst)
128
int ret = SMB_VFS_NEXT_RENAME(handle, smb_fname_src, smb_fname_dst);
147
struct syncops_config_data *config;
149
SMB_VFS_HANDLE_GET_DATA(handle, config,
150
struct syncops_config_data,
153
ret = SMB_VFS_NEXT_RENAME(handle, smb_fname_src, smb_fname_dst);
154
if (ret == 0 && config->onmeta && !config->disable) {
130
155
syncops_two_names(smb_fname_src->base_name,
131
156
smb_fname_dst->base_name);
136
161
/* handle the rest with a macro */
137
162
#define SYNCOPS_NEXT(op, fname, args) do { \
138
int ret = SMB_VFS_NEXT_ ## op args; \
139
if (ret == 0 && fname) syncops_name(fname); \
164
struct syncops_config_data *config; \
165
SMB_VFS_HANDLE_GET_DATA(handle, config, \
166
struct syncops_config_data, \
168
ret = SMB_VFS_NEXT_ ## op args; \
170
&& config->onmeta && !config->disable \
171
&& fname) syncops_name(fname); \
143
175
#define SYNCOPS_NEXT_SMB_FNAME(op, fname, args) do { \
144
int ret = SMB_VFS_NEXT_ ## op args; \
145
if (ret == 0 && fname) syncops_smb_fname(fname); \
177
struct syncops_config_data *config; \
178
SMB_VFS_HANDLE_GET_DATA(handle, config, \
179
struct syncops_config_data, \
181
ret = SMB_VFS_NEXT_ ## op args; \
183
&& config->onmeta && !config->disable \
184
&& fname) syncops_smb_fname(fname); \
191
230
/* close needs to be handled specially */
192
231
static int syncops_close(vfs_handle_struct *handle, files_struct *fsp)
194
if (fsp->can_write && sync_onclose) {
233
struct syncops_config_data *config;
235
SMB_VFS_HANDLE_GET_DATA(handle, config,
236
struct syncops_config_data,
239
if (fsp->can_write && config->onclose) {
195
240
/* ideally we'd only do this if we have written some
196
241
data, but there is no flag for that in fsp yet. */
197
242
fsync(fsp->fh->fd);
199
244
return SMB_VFS_NEXT_CLOSE(handle, fsp);
247
static int syncops_connect(struct vfs_handle_struct *handle, const char *service,
251
struct syncops_config_data *config;
252
int ret = SMB_VFS_NEXT_CONNECT(handle, service, user);
257
config = talloc_zero(handle->conn, struct syncops_config_data);
259
SMB_VFS_NEXT_DISCONNECT(handle);
260
DEBUG(0, ("talloc_zero() failed\n"));
264
config->onclose = lp_parm_bool(SNUM(handle->conn), "syncops",
267
config->onmeta = lp_parm_bool(SNUM(handle->conn), "syncops",
270
config->disable = lp_parm_bool(SNUM(handle->conn), "syncops",
273
SMB_VFS_HANDLE_SET_DATA(handle, config,
274
NULL, struct syncops_config_data,
203
281
static struct vfs_fn_pointers vfs_syncops_fns = {
282
.connect_fn = syncops_connect,
204
283
.mkdir = syncops_mkdir,
205
284
.rmdir = syncops_rmdir,
206
.open = syncops_open,
285
.open_fn = syncops_open,
207
286
.rename = syncops_rename,
208
287
.unlink = syncops_unlink,
209
288
.symlink = syncops_symlink,