Coverage Report

Created: 2025-12-31 07:01

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/git/fsmonitor.c
Line
Count
Source
1
#define USE_THE_REPOSITORY_VARIABLE
2
#define DISABLE_SIGN_COMPARE_WARNINGS
3
4
#include "git-compat-util.h"
5
#include "config.h"
6
#include "dir.h"
7
#include "environment.h"
8
#include "ewah/ewok.h"
9
#include "fsmonitor.h"
10
#include "fsmonitor-ipc.h"
11
#include "name-hash.h"
12
#include "repository.h"
13
#include "run-command.h"
14
#include "strbuf.h"
15
#include "trace2.h"
16
17
0
#define INDEX_EXTENSION_VERSION1  (1)
18
0
#define INDEX_EXTENSION_VERSION2  (2)
19
0
#define HOOK_INTERFACE_VERSION1   (1)
20
0
#define HOOK_INTERFACE_VERSION2   (2)
21
22
struct trace_key trace_fsmonitor = TRACE_KEY_INIT(FSMONITOR);
23
24
static void assert_index_minimum(struct index_state *istate, size_t pos)
25
0
{
26
0
  if (pos > istate->cache_nr)
27
0
    BUG("fsmonitor_dirty has more entries than the index (%"PRIuMAX" > %u)",
28
0
        (uintmax_t)pos, istate->cache_nr);
29
0
}
30
31
static void fsmonitor_ewah_callback(size_t pos, void *is)
32
0
{
33
0
  struct index_state *istate = (struct index_state *)is;
34
0
  struct cache_entry *ce;
35
36
0
  assert_index_minimum(istate, pos + 1);
37
38
0
  ce = istate->cache[pos];
39
0
  ce->ce_flags &= ~CE_FSMONITOR_VALID;
40
0
}
41
42
static int fsmonitor_hook_version(void)
43
0
{
44
0
  int hook_version;
45
46
0
  if (repo_config_get_int(the_repository, "core.fsmonitorhookversion", &hook_version))
47
0
    return -1;
48
49
0
  if (hook_version == HOOK_INTERFACE_VERSION1 ||
50
0
      hook_version == HOOK_INTERFACE_VERSION2)
51
0
    return hook_version;
52
53
0
  warning("Invalid hook version '%i' in core.fsmonitorhookversion. "
54
0
    "Must be 1 or 2.", hook_version);
55
0
  return -1;
56
0
}
57
58
int read_fsmonitor_extension(struct index_state *istate, const void *data,
59
  unsigned long sz)
60
0
{
61
0
  const char *index = data;
62
0
  uint32_t hdr_version;
63
0
  uint32_t ewah_size;
64
0
  struct ewah_bitmap *fsmonitor_dirty;
65
0
  int ret;
66
0
  uint64_t timestamp;
67
0
  struct strbuf last_update = STRBUF_INIT;
68
69
0
  if (sz < sizeof(uint32_t) + 1 + sizeof(uint32_t))
70
0
    return error("corrupt fsmonitor extension (too short)");
71
72
0
  hdr_version = get_be32(index);
73
0
  index += sizeof(uint32_t);
74
0
  if (hdr_version == INDEX_EXTENSION_VERSION1) {
75
0
    timestamp = get_be64(index);
76
0
    strbuf_addf(&last_update, "%"PRIu64"", timestamp);
77
0
    index += sizeof(uint64_t);
78
0
  } else if (hdr_version == INDEX_EXTENSION_VERSION2) {
79
0
    strbuf_addstr(&last_update, index);
80
0
    index += last_update.len + 1;
81
0
  } else {
82
0
    return error("bad fsmonitor version %d", hdr_version);
83
0
  }
84
85
0
  istate->fsmonitor_last_update = strbuf_detach(&last_update, NULL);
86
87
0
  ewah_size = get_be32(index);
88
0
  index += sizeof(uint32_t);
89
90
0
  fsmonitor_dirty = ewah_new();
91
0
  ret = ewah_read_mmap(fsmonitor_dirty, index, ewah_size);
92
0
  if (ret != ewah_size) {
93
0
    ewah_free(fsmonitor_dirty);
94
0
    return error("failed to parse ewah bitmap reading fsmonitor index extension");
95
0
  }
96
0
  istate->fsmonitor_dirty = fsmonitor_dirty;
97
98
0
  if (!istate->split_index)
99
0
    assert_index_minimum(istate, istate->fsmonitor_dirty->bit_size);
100
101
0
  trace2_data_string("index", NULL, "extension/fsmn/read/token",
102
0
         istate->fsmonitor_last_update);
103
0
  trace_printf_key(&trace_fsmonitor,
104
0
       "read fsmonitor extension successful '%s'",
105
0
       istate->fsmonitor_last_update);
106
0
  return 0;
107
0
}
108
109
void fill_fsmonitor_bitmap(struct index_state *istate)
110
0
{
111
0
  unsigned int i, skipped = 0;
112
0
  istate->fsmonitor_dirty = ewah_new();
113
0
  for (i = 0; i < istate->cache_nr; i++) {
114
0
    if (istate->cache[i]->ce_flags & CE_REMOVE)
115
0
      skipped++;
116
0
    else if (!(istate->cache[i]->ce_flags & CE_FSMONITOR_VALID))
117
0
      ewah_set(istate->fsmonitor_dirty, i - skipped);
118
0
  }
119
0
}
120
121
void write_fsmonitor_extension(struct strbuf *sb, struct index_state *istate)
122
0
{
123
0
  uint32_t hdr_version;
124
0
  uint32_t ewah_start;
125
0
  uint32_t ewah_size = 0;
126
0
  int fixup = 0;
127
128
0
  if (!istate->split_index)
129
0
    assert_index_minimum(istate, istate->fsmonitor_dirty->bit_size);
130
131
0
  put_be32(&hdr_version, INDEX_EXTENSION_VERSION2);
132
0
  strbuf_add(sb, &hdr_version, sizeof(uint32_t));
133
134
0
  strbuf_addstr(sb, istate->fsmonitor_last_update);
135
0
  strbuf_addch(sb, 0); /* Want to keep a NUL */
136
137
0
  fixup = sb->len;
138
0
  strbuf_add(sb, &ewah_size, sizeof(uint32_t)); /* we'll fix this up later */
139
140
0
  ewah_start = sb->len;
141
0
  ewah_serialize_strbuf(istate->fsmonitor_dirty, sb);
142
0
  ewah_free(istate->fsmonitor_dirty);
143
0
  istate->fsmonitor_dirty = NULL;
144
145
  /* fix up size field */
146
0
  put_be32(&ewah_size, sb->len - ewah_start);
147
0
  memcpy(sb->buf + fixup, &ewah_size, sizeof(uint32_t));
148
149
0
  trace2_data_string("index", NULL, "extension/fsmn/write/token",
150
0
         istate->fsmonitor_last_update);
151
0
  trace_printf_key(&trace_fsmonitor,
152
0
       "write fsmonitor extension successful '%s'",
153
0
       istate->fsmonitor_last_update);
154
0
}
155
156
/*
157
 * Call the query-fsmonitor hook passing the last update token of the saved results.
158
 */
159
static int query_fsmonitor_hook(struct repository *r,
160
        int version,
161
        const char *last_update,
162
        struct strbuf *query_result)
163
0
{
164
0
  struct child_process cp = CHILD_PROCESS_INIT;
165
0
  int result;
166
167
0
  if (fsm_settings__get_mode(r) != FSMONITOR_MODE_HOOK)
168
0
    return -1;
169
170
0
  strvec_push(&cp.args, fsm_settings__get_hook_path(r));
171
0
  strvec_pushf(&cp.args, "%d", version);
172
0
  strvec_pushf(&cp.args, "%s", last_update);
173
0
  cp.use_shell = 1;
174
0
  cp.dir = repo_get_work_tree(the_repository);
175
176
0
  trace2_region_enter("fsm_hook", "query", NULL);
177
178
0
  result = capture_command(&cp, query_result, 1024);
179
180
0
  if (result)
181
0
    trace2_data_intmax("fsm_hook", NULL, "query/failed", result);
182
0
  else
183
0
    trace2_data_intmax("fsm_hook", NULL, "query/response-length",
184
0
           query_result->len);
185
186
0
  trace2_region_leave("fsm_hook", "query", NULL);
187
188
0
  return result;
189
0
}
190
191
/*
192
 * Invalidate the FSM bit on this CE.  This is like mark_fsmonitor_invalid()
193
 * but we've already handled the untracked-cache, so let's not repeat that
194
 * work.  This also lets us have a different trace message so that we can
195
 * see everything that was done as part of the refresh-callback.
196
 */
197
static void invalidate_ce_fsm(struct cache_entry *ce)
198
0
{
199
0
  if (ce->ce_flags & CE_FSMONITOR_VALID) {
200
0
    trace_printf_key(&trace_fsmonitor,
201
0
         "fsmonitor_refresh_callback INV: '%s'",
202
0
         ce->name);
203
0
    ce->ce_flags &= ~CE_FSMONITOR_VALID;
204
0
  }
205
0
}
206
207
static size_t handle_path_with_trailing_slash(
208
  struct index_state *istate, const char *name, int pos);
209
210
/*
211
 * Use the name-hash to do a case-insensitive cache-entry lookup with
212
 * the pathname and invalidate the cache-entry.
213
 *
214
 * Returns the number of cache-entries that we invalidated.
215
 */
216
static size_t handle_using_name_hash_icase(
217
  struct index_state *istate, const char *name)
218
0
{
219
0
  struct cache_entry *ce = NULL;
220
221
0
  ce = index_file_exists(istate, name, strlen(name), 1);
222
0
  if (!ce)
223
0
    return 0;
224
225
  /*
226
   * A case-insensitive search in the name-hash using the
227
   * observed pathname found a cache-entry, so the observed path
228
   * is case-incorrect.  Invalidate the cache-entry and use the
229
   * correct spelling from the cache-entry to invalidate the
230
   * untracked-cache.  Since we now have sparse-directories in
231
   * the index, the observed pathname may represent a regular
232
   * file or a sparse-index directory.
233
   *
234
   * Note that we should not have seen FSEvents for a
235
   * sparse-index directory, but we handle it just in case.
236
   *
237
   * Either way, we know that there are not any cache-entries for
238
   * children inside the cone of the directory, so we don't need to
239
   * do the usual scan.
240
   */
241
0
  trace_printf_key(&trace_fsmonitor,
242
0
       "fsmonitor_refresh_callback MAP: '%s' '%s'",
243
0
       name, ce->name);
244
245
  /*
246
   * NEEDSWORK: We used the name-hash to find the correct
247
   * case-spelling of the pathname in the cache-entry[], so
248
   * technically this is a tracked file or a sparse-directory.
249
   * It should not have any entries in the untracked-cache, so
250
   * we should not need to use the case-corrected spelling to
251
   * invalidate the untracked-cache.  So we may not need to
252
   * do this.  For now, I'm going to be conservative and always
253
   * do it; we can revisit this later.
254
   */
255
0
  untracked_cache_invalidate_trimmed_path(istate, ce->name, 0);
256
257
0
  invalidate_ce_fsm(ce);
258
0
  return 1;
259
0
}
260
261
/*
262
 * Use the dir-name-hash to find the correct-case spelling of the
263
 * directory.  Use the canonical spelling to invalidate all of the
264
 * cache-entries within the matching cone.
265
 *
266
 * Returns the number of cache-entries that we invalidated.
267
 */
268
static size_t handle_using_dir_name_hash_icase(
269
  struct index_state *istate, const char *name)
270
0
{
271
0
  struct strbuf canonical_path = STRBUF_INIT;
272
0
  int pos;
273
0
  size_t len = strlen(name);
274
0
  size_t nr_in_cone;
275
276
0
  if (name[len - 1] == '/')
277
0
    len--;
278
279
0
  if (!index_dir_find(istate, name, len, &canonical_path))
280
0
    return 0; /* name is untracked */
281
282
0
  if (!memcmp(name, canonical_path.buf, canonical_path.len)) {
283
0
    strbuf_release(&canonical_path);
284
    /*
285
     * NEEDSWORK: Our caller already tried an exact match
286
     * and failed to find one.  They called us to do an
287
     * ICASE match, so we should never get an exact match,
288
     * so we could promote this to a BUG() here if we
289
     * wanted to.  It doesn't hurt anything to just return
290
     * 0 and go on because we should never get here.  Or we
291
     * could just get rid of the memcmp() and this "if"
292
     * clause completely.
293
     */
294
0
    BUG("handle_using_dir_name_hash_icase(%s) did not exact match",
295
0
        name);
296
0
  }
297
298
0
  trace_printf_key(&trace_fsmonitor,
299
0
       "fsmonitor_refresh_callback MAP: '%s' '%s'",
300
0
       name, canonical_path.buf);
301
302
  /*
303
   * The dir-name-hash only tells us the corrected spelling of
304
   * the prefix.  We have to use this canonical path to do a
305
   * lookup in the cache-entry array so that we repeat the
306
   * original search using the case-corrected spelling.
307
   */
308
0
  strbuf_addch(&canonical_path, '/');
309
0
  pos = index_name_pos(istate, canonical_path.buf,
310
0
           canonical_path.len);
311
0
  nr_in_cone = handle_path_with_trailing_slash(
312
0
    istate, canonical_path.buf, pos);
313
0
  strbuf_release(&canonical_path);
314
0
  return nr_in_cone;
315
0
}
316
317
/*
318
 * The daemon sent an observed pathname without a trailing slash.
319
 * (This is the normal case.)  We do not know if it is a tracked or
320
 * untracked file, a sparse-directory, or a populated directory (on a
321
 * platform such as Windows where FSEvents are not qualified).
322
 *
323
 * The pathname contains the observed case reported by the FS. We
324
 * do not know it is case-correct or -incorrect.
325
 *
326
 * Assume it is case-correct and try an exact match.
327
 *
328
 * Return the number of cache-entries that we invalidated.
329
 */
330
static size_t handle_path_without_trailing_slash(
331
  struct index_state *istate, const char *name, int pos)
332
0
{
333
  /*
334
   * Mark the untracked cache dirty for this path (regardless of
335
   * whether or not we find an exact match for it in the index).
336
   * Since the path is unqualified (no trailing slash hint in the
337
   * FSEvent), it may refer to a file or directory. So we should
338
   * not assume one or the other and should always let the untracked
339
   * cache decide what needs to invalidated.
340
   */
341
0
  untracked_cache_invalidate_trimmed_path(istate, name, 0);
342
343
0
  if (pos >= 0) {
344
    /*
345
     * An exact match on a tracked file. We assume that we
346
     * do not need to scan forward for a sparse-directory
347
     * cache-entry with the same pathname, nor for a cone
348
     * at that directory. (That is, assume no D/F conflicts.)
349
     */
350
0
    invalidate_ce_fsm(istate->cache[pos]);
351
0
    return 1;
352
0
  } else {
353
0
    size_t nr_in_cone;
354
0
    struct strbuf work_path = STRBUF_INIT;
355
356
    /*
357
     * The negative "pos" gives us the suggested insertion
358
     * point for the pathname (without the trailing slash).
359
     * We need to see if there is a directory with that
360
     * prefix, but there can be lots of pathnames between
361
     * "foo" and "foo/" like "foo-" or "foo-bar", so we
362
     * don't want to do our own scan.
363
     */
364
0
    strbuf_add(&work_path, name, strlen(name));
365
0
    strbuf_addch(&work_path, '/');
366
0
    pos = index_name_pos(istate, work_path.buf, work_path.len);
367
0
    nr_in_cone = handle_path_with_trailing_slash(
368
0
      istate, work_path.buf, pos);
369
0
    strbuf_release(&work_path);
370
0
    return nr_in_cone;
371
0
  }
372
0
}
373
374
/*
375
 * The daemon can decorate directory events, such as a move or rename,
376
 * by adding a trailing slash to the observed name.  Use this to
377
 * explicitly invalidate the entire cone under that directory.
378
 *
379
 * The daemon can only reliably do that if the OS FSEvent contains
380
 * sufficient information in the event.
381
 *
382
 * macOS FSEvents have enough information.
383
 *
384
 * Other platforms may or may not be able to do it (and it might
385
 * depend on the type of event (for example, a daemon could lstat() an
386
 * observed pathname after a rename, but not after a delete)).
387
 *
388
 * If we find an exact match in the index for a path with a trailing
389
 * slash, it means that we matched a sparse-index directory in a
390
 * cone-mode sparse-checkout (since that's the only time we have
391
 * directories in the index).  We should never see this in practice
392
 * (because sparse directories should not be present and therefore
393
 * not generating FS events).  Either way, we can treat them in the
394
 * same way and just invalidate the cache-entry and the untracked
395
 * cache (and in this case, the forward cache-entry scan won't find
396
 * anything and it doesn't hurt to let it run).
397
 *
398
 * Return the number of cache-entries that we invalidated.  We will
399
 * use this later to determine if we need to attempt a second
400
 * case-insensitive search on case-insensitive file systems.  That is,
401
 * if the search using the observed-case in the FSEvent yields any
402
 * results, we assume the prefix is case-correct.  If there are no
403
 * matches, we still don't know if the observed path is simply
404
 * untracked or case-incorrect.
405
 */
406
static size_t handle_path_with_trailing_slash(
407
  struct index_state *istate, const char *name, int pos)
408
0
{
409
0
  int i;
410
0
  size_t nr_in_cone = 0;
411
412
  /*
413
   * Mark the untracked cache dirty for this directory path
414
   * (regardless of whether or not we find an exact match for it
415
   * in the index or find it to be proper prefix of one or more
416
   * files in the index), since the FSEvent is hinting that
417
   * there may be changes on or within the directory.
418
   */
419
0
  untracked_cache_invalidate_trimmed_path(istate, name, 0);
420
421
0
  if (pos < 0)
422
0
    pos = -pos - 1;
423
424
  /* Mark all entries for the folder invalid */
425
0
  for (i = pos; i < istate->cache_nr; i++) {
426
0
    if (!starts_with(istate->cache[i]->name, name))
427
0
      break;
428
0
    invalidate_ce_fsm(istate->cache[i]);
429
0
    nr_in_cone++;
430
0
  }
431
432
0
  return nr_in_cone;
433
0
}
434
435
static void fsmonitor_refresh_callback(struct index_state *istate, char *name)
436
0
{
437
0
  int len = strlen(name);
438
0
  int pos = index_name_pos(istate, name, len);
439
0
  size_t nr_in_cone;
440
441
0
  trace_printf_key(&trace_fsmonitor,
442
0
       "fsmonitor_refresh_callback '%s' (pos %d)",
443
0
       name, pos);
444
445
0
  if (name[len - 1] == '/')
446
0
    nr_in_cone = handle_path_with_trailing_slash(istate, name, pos);
447
0
  else
448
0
    nr_in_cone = handle_path_without_trailing_slash(istate, name, pos);
449
450
  /*
451
   * If we did not find an exact match for this pathname or any
452
   * cache-entries with this directory prefix and we're on a
453
   * case-insensitive file system, try again using the name-hash
454
   * and dir-name-hash.
455
   */
456
0
  if (!nr_in_cone && ignore_case) {
457
0
    nr_in_cone = handle_using_name_hash_icase(istate, name);
458
0
    if (!nr_in_cone)
459
0
      nr_in_cone = handle_using_dir_name_hash_icase(
460
0
        istate, name);
461
0
  }
462
463
0
  if (nr_in_cone)
464
0
    trace_printf_key(&trace_fsmonitor,
465
0
         "fsmonitor_refresh_callback CNT: %d",
466
0
         (int)nr_in_cone);
467
0
}
468
469
/*
470
 * The number of pathnames that we need to receive from FSMonitor
471
 * before we force the index to be updated.
472
 *
473
 * Note that any pathname within the set of received paths MAY cause
474
 * cache-entry or istate flag bits to be updated and thus cause the
475
 * index to be updated on disk.
476
 *
477
 * However, the response may contain many paths (such as ignored
478
 * paths) that will not update any flag bits.  And thus not force the
479
 * index to be updated.  (This is fine and normal.)  It also means
480
 * that the token will not be updated in the FSMonitor index
481
 * extension.  So the next Git command will find the same token in the
482
 * index, make the same token-relative request, and receive the same
483
 * response (plus any newly changed paths).  If this response is large
484
 * (and continues to grow), performance could be impacted.
485
 *
486
 * For example, if the user runs a build and it writes 100K object
487
 * files but doesn't modify any source files, the index would not need
488
 * to be updated.  The FSMonitor response (after the build and
489
 * relative to a pre-build token) might be 5MB.  Each subsequent Git
490
 * command will receive that same 100K/5MB response until something
491
 * causes the index to be updated.  And `refresh_fsmonitor()` will
492
 * have to iterate over those 100K paths each time.
493
 *
494
 * Performance could be improved if we optionally force update the
495
 * index after a very large response and get an updated token into
496
 * the FSMonitor index extension.  This should allow subsequent
497
 * commands to get smaller and more current responses.
498
 *
499
 * The value chosen here does not need to be precise.  The index
500
 * will be updated automatically the first time the user touches
501
 * a tracked file and causes a command like `git status` to
502
 * update an mtime to be updated and/or set a flag bit.
503
 */
504
static int fsmonitor_force_update_threshold = 100;
505
506
void refresh_fsmonitor(struct index_state *istate)
507
0
{
508
0
  static int warn_once = 0;
509
0
  struct strbuf query_result = STRBUF_INIT;
510
0
  int query_success = 0, hook_version = -1;
511
0
  size_t bol = 0; /* beginning of line */
512
0
  uint64_t last_update;
513
0
  struct strbuf last_update_token = STRBUF_INIT;
514
0
  char *buf;
515
0
  unsigned int i;
516
0
  int is_trivial = 0;
517
0
  struct repository *r = istate->repo;
518
0
  enum fsmonitor_mode fsm_mode = fsm_settings__get_mode(r);
519
0
  enum fsmonitor_reason reason = fsm_settings__get_reason(r);
520
521
0
  if (!warn_once && reason > FSMONITOR_REASON_OK) {
522
0
    char *msg = fsm_settings__get_incompatible_msg(r, reason);
523
0
    warn_once = 1;
524
0
    warning("%s", msg);
525
0
    free(msg);
526
0
  }
527
528
0
  if (fsm_mode <= FSMONITOR_MODE_DISABLED ||
529
0
      istate->fsmonitor_has_run_once)
530
0
    return;
531
532
0
  istate->fsmonitor_has_run_once = 1;
533
534
0
  trace_printf_key(&trace_fsmonitor, "refresh fsmonitor");
535
536
0
  if (fsm_mode == FSMONITOR_MODE_IPC) {
537
0
    query_success = !fsmonitor_ipc__send_query(
538
0
      istate->fsmonitor_last_update ?
539
0
      istate->fsmonitor_last_update : "builtin:fake",
540
0
      &query_result);
541
0
    if (query_success) {
542
      /*
543
       * The response contains a series of nul terminated
544
       * strings.  The first is the new token.
545
       *
546
       * Use `char *buf` as an interlude to trick the CI
547
       * static analysis to let us use `strbuf_addstr()`
548
       * here (and only copy the token) rather than
549
       * `strbuf_addbuf()`.
550
       */
551
0
      buf = query_result.buf;
552
0
      strbuf_addstr(&last_update_token, buf);
553
0
      bol = last_update_token.len + 1;
554
0
      is_trivial = query_result.buf[bol] == '/';
555
0
      if (is_trivial)
556
0
        trace2_data_intmax("fsm_client", NULL,
557
0
               "query/trivial-response", 1);
558
0
    } else {
559
      /*
560
       * The builtin daemon is not available on this
561
       * platform -OR- we failed to get a response.
562
       *
563
       * Generate a fake token (rather than a V1
564
       * timestamp) for the index extension.  (If
565
       * they switch back to the hook API, we don't
566
       * want ambiguous state.)
567
       */
568
0
      strbuf_addstr(&last_update_token, "builtin:fake");
569
0
    }
570
571
0
    goto apply_results;
572
0
  }
573
574
0
  assert(fsm_mode == FSMONITOR_MODE_HOOK);
575
576
0
  hook_version = fsmonitor_hook_version();
577
578
  /*
579
   * This could be racy so save the date/time now and query_fsmonitor_hook
580
   * should be inclusive to ensure we don't miss potential changes.
581
   */
582
0
  last_update = getnanotime();
583
0
  if (hook_version == HOOK_INTERFACE_VERSION1)
584
0
    strbuf_addf(&last_update_token, "%"PRIu64"", last_update);
585
586
  /*
587
   * If we have a last update token, call query_fsmonitor_hook for the set of
588
   * changes since that token, else assume everything is possibly dirty
589
   * and check it all.
590
   */
591
0
  if (istate->fsmonitor_last_update) {
592
0
    if (hook_version == -1 || hook_version == HOOK_INTERFACE_VERSION2) {
593
0
      query_success = !query_fsmonitor_hook(
594
0
        r, HOOK_INTERFACE_VERSION2,
595
0
        istate->fsmonitor_last_update, &query_result);
596
597
0
      if (query_success) {
598
0
        if (hook_version < 0)
599
0
          hook_version = HOOK_INTERFACE_VERSION2;
600
601
        /*
602
         * First entry will be the last update token
603
         * Need to use a char * variable because static
604
         * analysis was suggesting to use strbuf_addbuf
605
         * but we don't want to copy the entire strbuf
606
         * only the chars up to the first NUL
607
         */
608
0
        buf = query_result.buf;
609
0
        strbuf_addstr(&last_update_token, buf);
610
0
        if (!last_update_token.len) {
611
0
          warning("Empty last update token.");
612
0
          query_success = 0;
613
0
        } else {
614
0
          bol = last_update_token.len + 1;
615
0
          is_trivial = query_result.buf[bol] == '/';
616
0
        }
617
0
      } else if (hook_version < 0) {
618
0
        hook_version = HOOK_INTERFACE_VERSION1;
619
0
        if (!last_update_token.len)
620
0
          strbuf_addf(&last_update_token, "%"PRIu64"", last_update);
621
0
      }
622
0
    }
623
624
0
    if (hook_version == HOOK_INTERFACE_VERSION1) {
625
0
      query_success = !query_fsmonitor_hook(
626
0
        r, HOOK_INTERFACE_VERSION1,
627
0
        istate->fsmonitor_last_update, &query_result);
628
0
      if (query_success)
629
0
        is_trivial = query_result.buf[0] == '/';
630
0
    }
631
632
0
    if (is_trivial)
633
0
      trace2_data_intmax("fsm_hook", NULL,
634
0
             "query/trivial-response", 1);
635
636
0
    trace_performance_since(last_update, "fsmonitor process '%s'",
637
0
          fsm_settings__get_hook_path(r));
638
0
    trace_printf_key(&trace_fsmonitor,
639
0
         "fsmonitor process '%s' returned %s",
640
0
         fsm_settings__get_hook_path(r),
641
0
         query_success ? "success" : "failure");
642
0
  }
643
644
0
apply_results:
645
  /*
646
   * The response from FSMonitor (excluding the header token) is
647
   * either:
648
   *
649
   * [a] a (possibly empty) list of NUL delimited relative
650
   *     pathnames of changed paths.  This list can contain
651
   *     files and directories.  Directories have a trailing
652
   *     slash.
653
   *
654
   * [b] a single '/' to indicate the provider had no
655
   *     information and that we should consider everything
656
   *     invalid.  We call this a trivial response.
657
   */
658
0
  trace2_region_enter("fsmonitor", "apply_results", istate->repo);
659
660
0
  if (query_success && !is_trivial) {
661
    /*
662
     * Mark all pathnames returned by the monitor as dirty.
663
     *
664
     * This updates both the cache-entries and the untracked-cache.
665
     */
666
0
    int count = 0;
667
668
0
    buf = query_result.buf;
669
0
    for (i = bol; i < query_result.len; i++) {
670
0
      if (buf[i] != '\0')
671
0
        continue;
672
0
      fsmonitor_refresh_callback(istate, buf + bol);
673
0
      bol = i + 1;
674
0
      count++;
675
0
    }
676
0
    if (bol < query_result.len) {
677
0
      fsmonitor_refresh_callback(istate, buf + bol);
678
0
      count++;
679
0
    }
680
681
    /* Now mark the untracked cache for fsmonitor usage */
682
0
    if (istate->untracked)
683
0
      istate->untracked->use_fsmonitor = 1;
684
685
0
    if (count > fsmonitor_force_update_threshold)
686
0
      istate->cache_changed |= FSMONITOR_CHANGED;
687
688
0
    trace2_data_intmax("fsmonitor", istate->repo, "apply_count",
689
0
           count);
690
691
0
  } else {
692
    /*
693
     * We failed to get a response or received a trivial response,
694
     * so invalidate everything.
695
     *
696
     * We only want to run the post index changed hook if
697
     * we've actually changed entries, so keep track if we
698
     * actually changed entries or not.
699
     */
700
0
    int is_cache_changed = 0;
701
702
0
    for (i = 0; i < istate->cache_nr; i++) {
703
0
      if (istate->cache[i]->ce_flags & CE_FSMONITOR_VALID) {
704
0
        is_cache_changed = 1;
705
0
        istate->cache[i]->ce_flags &= ~CE_FSMONITOR_VALID;
706
0
      }
707
0
    }
708
709
    /*
710
     * If we're going to check every file, ensure we save
711
     * the results.
712
     */
713
0
    if (is_cache_changed)
714
0
      istate->cache_changed |= FSMONITOR_CHANGED;
715
716
0
    if (istate->untracked)
717
0
      istate->untracked->use_fsmonitor = 0;
718
0
  }
719
0
  trace2_region_leave("fsmonitor", "apply_results", istate->repo);
720
721
0
  strbuf_release(&query_result);
722
723
  /* Now that we've updated istate, save the last_update_token */
724
0
  FREE_AND_NULL(istate->fsmonitor_last_update);
725
0
  istate->fsmonitor_last_update = strbuf_detach(&last_update_token, NULL);
726
0
}
727
728
/*
729
 * The caller wants to turn on FSMonitor.  And when the caller writes
730
 * the index to disk, a FSMonitor extension should be included.  This
731
 * requires that `istate->fsmonitor_last_update` not be NULL.  But we
732
 * have not actually talked to a FSMonitor process yet, so we don't
733
 * have an initial value for this field.
734
 *
735
 * For a protocol V1 FSMonitor process, this field is a formatted
736
 * "nanoseconds since epoch" field.  However, for a protocol V2
737
 * FSMonitor process, this field is an opaque token.
738
 *
739
 * Historically, `add_fsmonitor()` has initialized this field to the
740
 * current time for protocol V1 processes.  There are lots of race
741
 * conditions here, but that code has shipped...
742
 *
743
 * The only true solution is to use a V2 FSMonitor and get a current
744
 * or default token value (that it understands), but we cannot do that
745
 * until we have actually talked to an instance of the FSMonitor process
746
 * (but the protocol requires that we send a token first...).
747
 *
748
 * For simplicity, just initialize like we have a V1 process and require
749
 * that V2 processes adapt.
750
 */
751
static void initialize_fsmonitor_last_update(struct index_state *istate)
752
0
{
753
0
  struct strbuf last_update = STRBUF_INIT;
754
755
0
  strbuf_addf(&last_update, "%"PRIu64"", getnanotime());
756
0
  istate->fsmonitor_last_update = strbuf_detach(&last_update, NULL);
757
0
}
758
759
void add_fsmonitor(struct index_state *istate)
760
0
{
761
0
  unsigned int i;
762
763
0
  if (!istate->fsmonitor_last_update) {
764
0
    trace_printf_key(&trace_fsmonitor, "add fsmonitor");
765
0
    istate->cache_changed |= FSMONITOR_CHANGED;
766
0
    initialize_fsmonitor_last_update(istate);
767
768
    /* reset the fsmonitor state */
769
0
    for (i = 0; i < istate->cache_nr; i++)
770
0
      istate->cache[i]->ce_flags &= ~CE_FSMONITOR_VALID;
771
772
    /* reset the untracked cache */
773
0
    if (istate->untracked) {
774
0
      add_untracked_cache(istate);
775
0
      istate->untracked->use_fsmonitor = 1;
776
0
    }
777
778
    /* Update the fsmonitor state */
779
0
    refresh_fsmonitor(istate);
780
0
  }
781
0
}
782
783
void remove_fsmonitor(struct index_state *istate)
784
0
{
785
0
  if (istate->fsmonitor_last_update) {
786
0
    trace_printf_key(&trace_fsmonitor, "remove fsmonitor");
787
0
    istate->cache_changed |= FSMONITOR_CHANGED;
788
0
    FREE_AND_NULL(istate->fsmonitor_last_update);
789
0
  }
790
0
}
791
792
void tweak_fsmonitor(struct index_state *istate)
793
0
{
794
0
  unsigned int i;
795
0
  int fsmonitor_enabled = (fsm_settings__get_mode(istate->repo)
796
0
         > FSMONITOR_MODE_DISABLED);
797
798
0
  if (istate->fsmonitor_dirty) {
799
0
    if (fsmonitor_enabled) {
800
      /* Mark all entries valid */
801
0
      for (i = 0; i < istate->cache_nr; i++) {
802
0
        if (S_ISGITLINK(istate->cache[i]->ce_mode))
803
0
          continue;
804
0
        istate->cache[i]->ce_flags |= CE_FSMONITOR_VALID;
805
0
      }
806
807
      /* Mark all previously saved entries as dirty */
808
0
      assert_index_minimum(istate, istate->fsmonitor_dirty->bit_size);
809
0
      ewah_each_bit(istate->fsmonitor_dirty, fsmonitor_ewah_callback, istate);
810
811
0
      refresh_fsmonitor(istate);
812
0
    }
813
814
0
    ewah_free(istate->fsmonitor_dirty);
815
0
    istate->fsmonitor_dirty = NULL;
816
0
  }
817
818
0
  if (fsmonitor_enabled)
819
0
    add_fsmonitor(istate);
820
0
  else
821
0
    remove_fsmonitor(istate);
822
0
}