@@ -333,6 +333,7 @@ mdb_sem_wait(sem_t *sem)
333
333
*/
334
334
#ifndef MDB_FDATASYNC
335
335
# define MDB_FDATASYNC fdatasync
336
+ # define HAVE_FDATASYNC 1
336
337
#endif
337
338
338
339
#ifndef MDB_MSYNC
@@ -1112,7 +1113,7 @@ struct MDB_env {
1112
1113
MDB_txn * me_txn ; /**< current write transaction */
1113
1114
MDB_txn * me_txn0 ; /**< prealloc'd write transaction */
1114
1115
size_t me_mapsize ; /**< size of the data memory map */
1115
- off_t me_size ; /**< current file size */
1116
+ size_t me_size ; /**< current file size */
1116
1117
pgno_t me_maxpg ; /**< me_mapsize / me_psize */
1117
1118
MDB_dbx * me_dbxs ; /**< array of static DB info */
1118
1119
uint16_t * me_dbflags ; /**< array of flags from MDB_db.md_flags */
@@ -2298,10 +2299,19 @@ mdb_page_touch(MDB_cursor *mc)
2298
2299
return rc ;
2299
2300
}
2300
2301
2301
- int
2302
- mdb_env_sync (MDB_env * env , int force )
2302
+ /* internal env_sync flags: */
2303
+ #define FORCE 1 /* as before, force a flush */
2304
+ #define FGREW 0x8000 /* file has grown, do a full fsync instead of just
2305
+ fdatasync. We shouldn't have to do this, according to the POSIX spec.
2306
+ But common Linux FSs violate the spec and won't sync required metadata
2307
+ correctly when the file grows. This only makes a difference if the
2308
+ platform actually distinguishes fdatasync from fsync.
2309
+ http://www.openldap.org/lists/openldap-devel/201411/msg00000.html */
2310
+
2311
+ static int
2312
+ mdb_env_sync0 (MDB_env * env , int flag )
2303
2313
{
2304
- int rc = 0 ;
2314
+ int rc = 0 , force = flag & FORCE ;
2305
2315
if (force || !F_ISSET (env -> me_flags , MDB_NOSYNC )) {
2306
2316
if (env -> me_flags & MDB_WRITEMAP ) {
2307
2317
int flags = ((env -> me_flags & MDB_MAPASYNC ) && !force )
@@ -2313,13 +2323,25 @@ mdb_env_sync(MDB_env *env, int force)
2313
2323
rc = ErrCode ();
2314
2324
#endif
2315
2325
} else {
2326
+ #ifdef HAVE_FDATASYNC
2327
+ if (flag & FGREW ) {
2328
+ if (fsync (env -> me_fd )) /* Avoid ext-fs bugs, do full sync */
2329
+ rc = ErrCode ();
2330
+ } else
2331
+ #endif
2316
2332
if (MDB_FDATASYNC (env -> me_fd ))
2317
2333
rc = ErrCode ();
2318
2334
}
2319
2335
}
2320
2336
return rc ;
2321
2337
}
2322
2338
2339
+ int
2340
+ mdb_env_sync (MDB_env * env , int force )
2341
+ {
2342
+ return mdb_env_sync0 (env , force != 0 );
2343
+ }
2344
+
2323
2345
/** Back up parent txn's cursors, then grab the originals for tracking */
2324
2346
static int
2325
2347
mdb_cursor_shadow (MDB_txn * src , MDB_txn * dst )
@@ -3372,8 +3394,15 @@ mdb_txn_commit(MDB_txn *txn)
3372
3394
mdb_audit (txn );
3373
3395
#endif
3374
3396
3397
+ i = 0 ;
3398
+ #ifdef HAVE_FDATASYNC
3399
+ if (txn -> mt_next_pgno * env -> me_psize > env -> me_size ) {
3400
+ i |= FGREW ;
3401
+ env -> me_size = txn -> mt_next_pgno * env -> me_psize ;
3402
+ }
3403
+ #endif
3375
3404
if ((rc = mdb_page_flush (txn , 0 )) ||
3376
- (rc = mdb_env_sync (env , 0 )) ||
3405
+ (rc = mdb_env_sync (env , i )) ||
3377
3406
(rc = mdb_env_write_meta (txn )))
3378
3407
goto fail ;
3379
3408
@@ -3897,6 +3926,10 @@ mdb_env_open2(MDB_env *env)
3897
3926
env -> me_mapsize = minsize ;
3898
3927
}
3899
3928
3929
+ rc = mdb_fsize (env -> me_fd , & env -> me_size );
3930
+ if (rc )
3931
+ return rc ;
3932
+
3900
3933
rc = mdb_env_map (env , (flags & MDB_FIXEDMAP ) ? meta .mm_address : NULL );
3901
3934
if (rc )
3902
3935
return rc ;
0 commit comments