3
3
*/
4
4
#include "cache.h"
5
5
#include "bulk-checkin.h"
6
+ #include "lockfile.h"
6
7
#include "repository.h"
7
8
#include "csum-file.h"
8
9
#include "pack.h"
9
10
#include "strbuf.h"
11
+ #include "string-list.h"
12
+ #include "tmp-objdir.h"
10
13
#include "packfile.h"
11
14
#include "object-store.h"
12
15
13
- static struct bulk_checkin_state {
14
- unsigned plugged :1 ;
16
+ static int bulk_checkin_plugged ;
17
+ static int needs_batch_fsync ;
18
+
19
+ static struct tmp_objdir * bulk_fsync_objdir ;
15
20
21
+ static struct bulk_checkin_state {
16
22
char * pack_tmp_name ;
17
23
struct hashfile * f ;
18
24
off_t offset ;
@@ -21,7 +27,7 @@ static struct bulk_checkin_state {
21
27
struct pack_idx_entry * * written ;
22
28
uint32_t alloc_written ;
23
29
uint32_t nr_written ;
24
- } state ;
30
+ } bulk_checkin_state ;
25
31
26
32
static void finish_tmp_packfile (struct strbuf * basename ,
27
33
const char * pack_tmp_name ,
@@ -79,6 +85,34 @@ static void finish_bulk_checkin(struct bulk_checkin_state *state)
79
85
reprepare_packed_git (the_repository );
80
86
}
81
87
88
+ /*
89
+ * Cleanup after batch-mode fsync_object_files.
90
+ */
91
+ static void do_batch_fsync (void )
92
+ {
93
+ /*
94
+ * Issue a full hardware flush against a temporary file to ensure
95
+ * that all objects are durable before any renames occur. The code in
96
+ * fsync_loose_object_bulk_checkin has already issued a writeout
97
+ * request, but it has not flushed any writeback cache in the storage
98
+ * hardware.
99
+ */
100
+
101
+ if (needs_batch_fsync ) {
102
+ struct strbuf temp_path = STRBUF_INIT ;
103
+ struct tempfile * temp ;
104
+
105
+ strbuf_addf (& temp_path , "%s/bulk_fsync_XXXXXX" , get_object_directory ());
106
+ temp = xmks_tempfile (temp_path .buf );
107
+ fsync_or_die (get_tempfile_fd (temp ), get_tempfile_path (temp ));
108
+ delete_tempfile (& temp );
109
+ strbuf_release (& temp_path );
110
+ }
111
+
112
+ if (bulk_fsync_objdir )
113
+ tmp_objdir_migrate (bulk_fsync_objdir );
114
+ }
115
+
82
116
static int already_written (struct bulk_checkin_state * state , struct object_id * oid )
83
117
{
84
118
int i ;
@@ -273,25 +307,61 @@ static int deflate_to_pack(struct bulk_checkin_state *state,
273
307
return 0 ;
274
308
}
275
309
310
+ void fsync_loose_object_bulk_checkin (int fd )
311
+ {
312
+ assert (fsync_object_files == FSYNC_OBJECT_FILES_BATCH );
313
+
314
+ /*
315
+ * If we have a plugged bulk checkin, we issue a call that
316
+ * cleans the filesystem page cache but avoids a hardware flush
317
+ * command. Later on we will issue a single hardware flush
318
+ * before as part of do_batch_fsync.
319
+ */
320
+ if (bulk_checkin_plugged &&
321
+ git_fsync (fd , FSYNC_WRITEOUT_ONLY ) >= 0 ) {
322
+ if (!needs_batch_fsync )
323
+ needs_batch_fsync = 1 ;
324
+ } else {
325
+ fsync_or_die (fd , "loose object file" );
326
+ }
327
+ }
328
+
276
329
int index_bulk_checkin (struct object_id * oid ,
277
330
int fd , size_t size , enum object_type type ,
278
331
const char * path , unsigned flags )
279
332
{
280
- int status = deflate_to_pack (& state , oid , fd , size , type ,
333
+ int status = deflate_to_pack (& bulk_checkin_state , oid , fd , size , type ,
281
334
path , flags );
282
- if (!state . plugged )
283
- finish_bulk_checkin (& state );
335
+ if (!bulk_checkin_plugged )
336
+ finish_bulk_checkin (& bulk_checkin_state );
284
337
return status ;
285
338
}
286
339
287
340
void plug_bulk_checkin (void )
288
341
{
289
- state .plugged = 1 ;
342
+ assert (!bulk_checkin_plugged );
343
+
344
+ /*
345
+ * A temporary object directory is used to hold the files
346
+ * while they are not fsynced.
347
+ */
348
+ if (fsync_object_files == FSYNC_OBJECT_FILES_BATCH ) {
349
+ bulk_fsync_objdir = tmp_objdir_create ("bulk-fsync" );
350
+ if (!bulk_fsync_objdir )
351
+ die (_ ("Could not create temporary object directory for core.fsyncobjectfiles=batch" ));
352
+
353
+ tmp_objdir_replace_primary_odb (bulk_fsync_objdir , 0 );
354
+ }
355
+
356
+ bulk_checkin_plugged = 1 ;
290
357
}
291
358
292
359
void unplug_bulk_checkin (void )
293
360
{
294
- state .plugged = 0 ;
295
- if (state .f )
296
- finish_bulk_checkin (& state );
361
+ assert (bulk_checkin_plugged );
362
+ bulk_checkin_plugged = 0 ;
363
+ if (bulk_checkin_state .f )
364
+ finish_bulk_checkin (& bulk_checkin_state );
365
+
366
+ do_batch_fsync ();
297
367
}
0 commit comments