add option to control amount of fsync()ing

This commit is contained in:
Oswald Buddenhagen 2012-09-15 15:15:22 +02:00
parent 49223b2df2
commit 35851f133b
8 changed files with 50 additions and 6 deletions

2
NEWS
View File

@ -10,6 +10,8 @@ UIDPLUS extension (e.g., M$ Exchange).
More automatic handling of SSL certificates. More automatic handling of SSL certificates.
Data safety in case of system crashes is improved.
[1.0.0] [1.0.0]
Essentially a rewrite. Synchronization state storage concept, configuration Essentially a rewrite. Synchronization state storage concept, configuration

2
TODO
View File

@ -1,5 +1,7 @@
find out why mutt's message size calc is confused. find out why mutt's message size calc is confused.
f{,data}sync() usage could be optimized by batching the calls.
add some marker about message being already [remotely] trashed. add some marker about message being already [remotely] trashed.
real transactions would be certainly not particularly useful ... real transactions would be certainly not particularly useful ...

View File

@ -39,6 +39,7 @@ channel_conf_t *channels;
group_conf_t *groups; group_conf_t *groups;
int global_ops[2]; int global_ops[2];
char *global_sync_state; char *global_sync_state;
int FSyncLevel = FSYNC_NORMAL;
#define ARG_OPTIONAL 0 #define ARG_OPTIONAL 0
#define ARG_REQUIRED 1 #define ARG_REQUIRED 1
@ -448,6 +449,16 @@ load_config( const char *where, int pseudo )
} }
break; break;
} }
else if (!strcasecmp( "FSync", cfile.cmd ))
{
arg = cfile.val;
if (!strcasecmp( "None", arg ))
FSyncLevel = FSYNC_NONE;
else if (!strcasecmp( "Normal", arg ))
FSyncLevel = FSYNC_NORMAL;
else if (!strcasecmp( "Thorough", arg ))
FSyncLevel = FSYNC_THOROUGH;
}
else if (!getopt_helper( &cfile, &gcops, global_ops, &global_sync_state )) else if (!getopt_helper( &cfile, &gcops, global_ops, &global_sync_state ))
{ {
error( "%s:%d: unknown section keyword '%s'\n", error( "%s:%d: unknown section keyword '%s'\n",

View File

@ -432,7 +432,7 @@ maildir_store_uid( maildir_store_t *ctx )
n = sprintf( buf, "%d\n%d\n", ctx->gen.uidvalidity, ctx->nuid ); n = sprintf( buf, "%d\n%d\n", ctx->gen.uidvalidity, ctx->nuid );
lseek( ctx->uvfd, 0, SEEK_SET ); lseek( ctx->uvfd, 0, SEEK_SET );
if (write( ctx->uvfd, buf, n ) != n || ftruncate( ctx->uvfd, n ) || fdatasync( ctx->uvfd )) { if (write( ctx->uvfd, buf, n ) != n || ftruncate( ctx->uvfd, n ) || (FSyncLevel >= FSYNC_NORMAL && fdatasync( ctx->uvfd ))) {
error( "Maildir error: cannot write UIDVALIDITY.\n" ); error( "Maildir error: cannot write UIDVALIDITY.\n" );
return DRV_BOX_BAD; return DRV_BOX_BAD;
} }
@ -1204,7 +1204,7 @@ maildir_store_msg( store_t *gctx, msg_data_t *data, int to_trash,
} }
ret = write( fd, data->data, data->len ); ret = write( fd, data->data, data->len );
free( data->data ); free( data->data );
if (ret != data->len || (ret = fsync( fd ))) { if (ret != data->len || ((FSyncLevel >= FSYNC_NORMAL) && (ret = fsync( fd )))) {
if (ret < 0) if (ret < 0)
sys_error( "Maildir error: cannot write %s", buf ); sys_error( "Maildir error: cannot write %s", buf );
else else

View File

@ -481,6 +481,12 @@ extern group_conf_t *groups;
extern int global_ops[2]; extern int global_ops[2];
extern char *global_sync_state; extern char *global_sync_state;
#define FSYNC_NONE 0
#define FSYNC_NORMAL 1
#define FSYNC_THOROUGH 2
extern int FSyncLevel;
int parse_bool( conffile_t *cfile ); int parse_bool( conffile_t *cfile );
int parse_int( conffile_t *cfile ); int parse_int( conffile_t *cfile );
int parse_size( conffile_t *cfile ); int parse_size( conffile_t *cfile );

View File

@ -20,7 +20,7 @@
\" As a special exception, mbsync may be linked with the OpenSSL library, \" As a special exception, mbsync may be linked with the OpenSSL library,
\" despite that library's more restrictive license. \" despite that library's more restrictive license.
.. ..
.TH mbsync 1 "2012 Aug 25" .TH mbsync 1 "2012 Sep 15"
.. ..
.SH NAME .SH NAME
mbsync - synchronize IMAP4 and Maildir mailboxes mbsync - synchronize IMAP4 and Maildir mailboxes
@ -477,6 +477,26 @@ line, except that there newlines can be used as mailbox name separators as well.
Add the specified channels to the group. This option can be specified multiple Add the specified channels to the group. This option can be specified multiple
times within a Group. times within a Group.
.. ..
.SS Global Options
.TP
\fBFSync\fR {\fINone\fR|\fINormal\fR|\fIThorough\fR}
.br
Select the amount of forced flushing \fBmbsync\fR performs, which determines
the level of data safety after system crashes and power outages:
.br
\fBNone\fR - no flushing at all. This is reasonably safe for file systems
which are mounted with data=ordered mode.
.br
\fBNormal\fR - message and critical metadata writes are flushed. No data
should be lost due to crashes, though it is still possible that messages
are duplicated after crashes. This is the default, and is a wise choice for
file systems mounted with data=writeback, in particular modern systems like
ext4, btrfs and xfs. The performance impact on older file systems may be
disproportionate.
.br
\fBThorough\fR - this avoids message duplication after crashes as well,
at some additional performance cost.
..
.SH SSL CERTIFICATES .SH SSL CERTIFICATES
[to be done] [to be done]
.. ..

View File

@ -256,7 +256,9 @@ sub writecfg($$$)
open(FILE, ">", ".mbsyncrc") or open(FILE, ">", ".mbsyncrc") or
die "Cannot open .mbsyncrc.\n"; die "Cannot open .mbsyncrc.\n";
print FILE print FILE
"MaildirStore master "FSync None
MaildirStore master
Path ./ Path ./
Inbox ./master Inbox ./master
".shift()." ".shift()."

View File

@ -42,7 +42,7 @@ const char *str_ms[] = { "master", "slave" }, *str_hl[] = { "push", "pull" };
void void
Fclose( FILE *f, int safe ) Fclose( FILE *f, int safe )
{ {
if ((safe && (fflush( f ) || fdatasync( fileno( f ) ))) || fclose( f ) == EOF) { if ((safe && (fflush( f ) || (FSyncLevel >= FSYNC_NORMAL && fdatasync( fileno( f ) )))) || fclose( f ) == EOF) {
sys_error( "Error: cannot close file. Disk full?" ); sys_error( "Error: cannot close file. Disk full?" );
exit( 1 ); exit( 1 );
} }
@ -1202,6 +1202,7 @@ box_loaded( int sts, void *aux )
cv->srec = srec; cv->srec = srec;
cv->msg = tmsg; cv->msg = tmsg;
Fprintf( svars->jfp, "# %d %d %." stringify(TUIDL) "s\n", srec->uid[M], srec->uid[S], srec->tuid ); Fprintf( svars->jfp, "# %d %d %." stringify(TUIDL) "s\n", srec->uid[M], srec->uid[S], srec->tuid );
if (FSyncLevel >= FSYNC_THOROUGH)
fdatasync( fileno( svars->jfp ) ); fdatasync( fileno( svars->jfp ) );
debug( " -> %sing message, TUID %." stringify(TUIDL) "s\n", str_hl[t], srec->tuid ); debug( " -> %sing message, TUID %." stringify(TUIDL) "s\n", str_hl[t], srec->tuid );
if (copy_msg( cv )) if (copy_msg( cv ))