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 odb_transaction_nesting ;
15
17
18
+ static struct tmp_objdir * bulk_fsync_objdir ;
19
+
20
+ static struct bulk_checkin_packfile {
16
21
char * pack_tmp_name ;
17
22
struct hashfile * f ;
18
23
off_t offset ;
@@ -21,7 +26,7 @@ static struct bulk_checkin_state {
21
26
struct pack_idx_entry * * written ;
22
27
uint32_t alloc_written ;
23
28
uint32_t nr_written ;
24
- } state ;
29
+ } bulk_checkin_packfile ;
25
30
26
31
static void finish_tmp_packfile (struct strbuf * basename ,
27
32
const char * pack_tmp_name ,
@@ -39,7 +44,7 @@ static void finish_tmp_packfile(struct strbuf *basename,
39
44
free (idx_tmp_name );
40
45
}
41
46
42
- static void finish_bulk_checkin (struct bulk_checkin_state * state )
47
+ static void flush_bulk_checkin_packfile (struct bulk_checkin_packfile * state )
43
48
{
44
49
unsigned char hash [GIT_MAX_RAWSZ ];
45
50
struct strbuf packname = STRBUF_INIT ;
@@ -80,7 +85,41 @@ static void finish_bulk_checkin(struct bulk_checkin_state *state)
80
85
reprepare_packed_git (the_repository );
81
86
}
82
87
83
- static int already_written (struct bulk_checkin_state * state , struct object_id * oid )
88
+ /*
89
+ * Cleanup after batch-mode fsync_object_files.
90
+ */
91
+ static void flush_batch_fsync (void )
92
+ {
93
+ struct strbuf temp_path = STRBUF_INIT ;
94
+ struct tempfile * temp ;
95
+
96
+ if (!bulk_fsync_objdir )
97
+ return ;
98
+
99
+ /*
100
+ * Issue a full hardware flush against a temporary file to ensure
101
+ * that all objects are durable before any renames occur. The code in
102
+ * fsync_loose_object_bulk_checkin has already issued a writeout
103
+ * request, but it has not flushed any writeback cache in the storage
104
+ * hardware or any filesystem logs. This fsync call acts as a barrier
105
+ * to ensure that the data in each new object file is durable before
106
+ * the final name is visible.
107
+ */
108
+ strbuf_addf (& temp_path , "%s/bulk_fsync_XXXXXX" , get_object_directory ());
109
+ temp = xmks_tempfile (temp_path .buf );
110
+ fsync_or_die (get_tempfile_fd (temp ), get_tempfile_path (temp ));
111
+ delete_tempfile (& temp );
112
+ strbuf_release (& temp_path );
113
+
114
+ /*
115
+ * Make the object files visible in the primary ODB after their data is
116
+ * fully durable.
117
+ */
118
+ tmp_objdir_migrate (bulk_fsync_objdir );
119
+ bulk_fsync_objdir = NULL ;
120
+ }
121
+
122
+ static int already_written (struct bulk_checkin_packfile * state , struct object_id * oid )
84
123
{
85
124
int i ;
86
125
@@ -112,7 +151,7 @@ static int already_written(struct bulk_checkin_state *state, struct object_id *o
112
151
* status before calling us just in case we ask it to call us again
113
152
* with a new pack.
114
153
*/
115
- static int stream_to_pack (struct bulk_checkin_state * state ,
154
+ static int stream_to_pack (struct bulk_checkin_packfile * state ,
116
155
git_hash_ctx * ctx , off_t * already_hashed_to ,
117
156
int fd , size_t size , enum object_type type ,
118
157
const char * path , unsigned flags )
@@ -189,7 +228,7 @@ static int stream_to_pack(struct bulk_checkin_state *state,
189
228
}
190
229
191
230
/* Lazily create backing packfile for the state */
192
- static void prepare_to_stream (struct bulk_checkin_state * state ,
231
+ static void prepare_to_stream (struct bulk_checkin_packfile * state ,
193
232
unsigned flags )
194
233
{
195
234
if (!(flags & HASH_WRITE_OBJECT ) || state -> f )
@@ -204,7 +243,7 @@ static void prepare_to_stream(struct bulk_checkin_state *state,
204
243
die_errno ("unable to write pack header" );
205
244
}
206
245
207
- static int deflate_to_pack (struct bulk_checkin_state * state ,
246
+ static int deflate_to_pack (struct bulk_checkin_packfile * state ,
208
247
struct object_id * result_oid ,
209
248
int fd , size_t size ,
210
249
enum object_type type , const char * path ,
@@ -251,7 +290,7 @@ static int deflate_to_pack(struct bulk_checkin_state *state,
251
290
BUG ("should not happen" );
252
291
hashfile_truncate (state -> f , & checkpoint );
253
292
state -> offset = checkpoint .offset ;
254
- finish_bulk_checkin (state );
293
+ flush_bulk_checkin_packfile (state );
255
294
if (lseek (fd , seekback , SEEK_SET ) == (off_t ) - 1 )
256
295
return error ("cannot seek back" );
257
296
}
@@ -274,25 +313,67 @@ static int deflate_to_pack(struct bulk_checkin_state *state,
274
313
return 0 ;
275
314
}
276
315
316
+ void prepare_loose_object_bulk_checkin (void )
317
+ {
318
+ /*
319
+ * We lazily create the temporary object directory
320
+ * the first time an object might be added, since
321
+ * callers may not know whether any objects will be
322
+ * added at the time they call begin_odb_transaction.
323
+ */
324
+ if (!odb_transaction_nesting || bulk_fsync_objdir )
325
+ return ;
326
+
327
+ bulk_fsync_objdir = tmp_objdir_create ("bulk-fsync" );
328
+ if (bulk_fsync_objdir )
329
+ tmp_objdir_replace_primary_odb (bulk_fsync_objdir , 0 );
330
+ }
331
+
332
+ void fsync_loose_object_bulk_checkin (int fd , const char * filename )
333
+ {
334
+ /*
335
+ * If we have an active ODB transaction, we issue a call that
336
+ * cleans the filesystem page cache but avoids a hardware flush
337
+ * command. Later on we will issue a single hardware flush
338
+ * before renaming the objects to their final names as part of
339
+ * flush_batch_fsync.
340
+ */
341
+ if (!bulk_fsync_objdir ||
342
+ git_fsync (fd , FSYNC_WRITEOUT_ONLY ) < 0 ) {
343
+ fsync_or_die (fd , filename );
344
+ }
345
+ }
346
+
277
347
int index_bulk_checkin (struct object_id * oid ,
278
348
int fd , size_t size , enum object_type type ,
279
349
const char * path , unsigned flags )
280
350
{
281
- int status = deflate_to_pack (& state , oid , fd , size , type ,
351
+ int status = deflate_to_pack (& bulk_checkin_packfile , oid , fd , size , type ,
282
352
path , flags );
283
- if (!state . plugged )
284
- finish_bulk_checkin ( & state );
353
+ if (!odb_transaction_nesting )
354
+ flush_bulk_checkin_packfile ( & bulk_checkin_packfile );
285
355
return status ;
286
356
}
287
357
288
- void plug_bulk_checkin (void )
358
+ void begin_odb_transaction (void )
289
359
{
290
- state . plugged = 1 ;
360
+ odb_transaction_nesting + = 1 ;
291
361
}
292
362
293
- void unplug_bulk_checkin (void )
363
+ void flush_odb_transaction (void )
294
364
{
295
- state .plugged = 0 ;
296
- if (state .f )
297
- finish_bulk_checkin (& state );
365
+ flush_batch_fsync ();
366
+ flush_bulk_checkin_packfile (& bulk_checkin_packfile );
367
+ }
368
+
369
+ void end_odb_transaction (void )
370
+ {
371
+ odb_transaction_nesting -= 1 ;
372
+ if (odb_transaction_nesting < 0 )
373
+ BUG ("Unbalanced ODB transaction nesting" );
374
+
375
+ if (odb_transaction_nesting )
376
+ return ;
377
+
378
+ flush_odb_transaction ();
298
379
}
0 commit comments