~ubuntu-branches/ubuntu/trusty/systemd/trusty

« back to all changes in this revision

Viewing changes to src/journal/sd-journal.c

Tags: upstream-202
ImportĀ upstreamĀ versionĀ 202

Show diffs side-by-side

added added

removed removed

Lines of Context:
49
49
 
50
50
#define DEFAULT_DATA_THRESHOLD (64*1024)
51
51
 
 
52
/* We return an error here only if we didn't manage to
 
53
   memorize the real error. */
 
54
static int set_put_error(sd_journal *j, int r) {
 
55
        int k;
 
56
 
 
57
        if (r >= 0)
 
58
                return r;
 
59
 
 
60
        k = set_ensure_allocated(&j->errors, trivial_hash_func, trivial_compare_func);
 
61
        if (k < 0)
 
62
                return k;
 
63
 
 
64
        return set_put(j->errors, INT_TO_PTR(r));
 
65
}
 
66
 
52
67
static void detach_location(sd_journal *j) {
53
68
        Iterator i;
54
69
        JournalFile *f;
94
109
 
95
110
        init_location(&j->current_location, type, f, o);
96
111
 
 
112
        if (j->current_file)
 
113
                j->current_file->current_offset = 0;
 
114
 
97
115
        j->current_file = f;
98
116
        j->current_field = 0;
99
117
 
188
206
}
189
207
 
190
208
_public_ int sd_journal_add_match(sd_journal *j, const void *data, size_t size) {
191
 
        Match *l2, *l3, *add_here = NULL, *m;
 
209
        Match *l3, *l4, *add_here = NULL, *m;
192
210
        le64_t le_hash;
193
211
 
194
212
        if (!j)
203
221
        if (!match_is_valid(data, size))
204
222
                return -EINVAL;
205
223
 
206
 
        /* level 0: OR term
207
 
         * level 1: AND terms
208
 
         * level 2: OR terms
209
 
         * level 3: concrete matches */
 
224
        /* level 0: AND term
 
225
         * level 1: OR terms
 
226
         * level 2: AND terms
 
227
         * level 3: OR terms
 
228
         * level 4: concrete matches */
210
229
 
211
230
        if (!j->level0) {
212
 
                j->level0 = match_new(NULL, MATCH_OR_TERM);
 
231
                j->level0 = match_new(NULL, MATCH_AND_TERM);
213
232
                if (!j->level0)
214
233
                        return -ENOMEM;
215
234
        }
216
235
 
217
236
        if (!j->level1) {
218
 
                j->level1 = match_new(j->level0, MATCH_AND_TERM);
 
237
                j->level1 = match_new(j->level0, MATCH_OR_TERM);
219
238
                if (!j->level1)
220
239
                        return -ENOMEM;
221
240
        }
222
241
 
223
 
        assert(j->level0->type == MATCH_OR_TERM);
224
 
        assert(j->level1->type == MATCH_AND_TERM);
 
242
        if (!j->level2) {
 
243
                j->level2 = match_new(j->level1, MATCH_AND_TERM);
 
244
                if (!j->level2)
 
245
                        return -ENOMEM;
 
246
        }
 
247
 
 
248
        assert(j->level0->type == MATCH_AND_TERM);
 
249
        assert(j->level1->type == MATCH_OR_TERM);
 
250
        assert(j->level2->type == MATCH_AND_TERM);
225
251
 
226
252
        le_hash = htole64(hash64(data, size));
227
253
 
228
 
        LIST_FOREACH(matches, l2, j->level1->matches) {
229
 
                assert(l2->type == MATCH_OR_TERM);
 
254
        LIST_FOREACH(matches, l3, j->level2->matches) {
 
255
                assert(l3->type == MATCH_OR_TERM);
230
256
 
231
 
                LIST_FOREACH(matches, l3, l2->matches) {
232
 
                        assert(l3->type == MATCH_DISCRETE);
 
257
                LIST_FOREACH(matches, l4, l3->matches) {
 
258
                        assert(l4->type == MATCH_DISCRETE);
233
259
 
234
260
                        /* Exactly the same match already? Then ignore
235
261
                         * this addition */
236
 
                        if (l3->le_hash == le_hash &&
237
 
                            l3->size == size &&
238
 
                            memcmp(l3->data, data, size) == 0)
 
262
                        if (l4->le_hash == le_hash &&
 
263
                            l4->size == size &&
 
264
                            memcmp(l4->data, data, size) == 0)
239
265
                                return 0;
240
266
 
241
267
                        /* Same field? Then let's add this to this OR term */
242
 
                        if (same_field(data, size, l3->data, l3->size)) {
243
 
                                add_here = l2;
 
268
                        if (same_field(data, size, l4->data, l4->size)) {
 
269
                                add_here = l3;
244
270
                                break;
245
271
                        }
246
272
                }
250
276
        }
251
277
 
252
278
        if (!add_here) {
253
 
                add_here = match_new(j->level1, MATCH_OR_TERM);
 
279
                add_here = match_new(j->level2, MATCH_OR_TERM);
254
280
                if (!add_here)
255
281
                        goto fail;
256
282
        }
273
299
        if (add_here)
274
300
                match_free_if_empty(add_here);
275
301
 
 
302
        if (j->level2)
 
303
                match_free_if_empty(j->level2);
 
304
 
276
305
        if (j->level1)
277
306
                match_free_if_empty(j->level1);
278
307
 
282
311
        return -ENOMEM;
283
312
}
284
313
 
 
314
_public_ int sd_journal_add_conjunction(sd_journal *j) {
 
315
        assert(j);
 
316
 
 
317
        if (!j->level0)
 
318
                return 0;
 
319
 
 
320
        if (!j->level1)
 
321
                return 0;
 
322
 
 
323
        if (!j->level1->matches)
 
324
                return 0;
 
325
 
 
326
        j->level1 = NULL;
 
327
        j->level2 = NULL;
 
328
 
 
329
        return 0;
 
330
}
 
331
 
285
332
_public_ int sd_journal_add_disjunction(sd_journal *j) {
286
 
        Match *m;
287
 
 
288
333
        assert(j);
289
334
 
290
335
        if (!j->level0)
293
338
        if (!j->level1)
294
339
                return 0;
295
340
 
296
 
        if (!j->level1->matches)
297
 
                return 0;
298
 
 
299
 
        m = match_new(j->level0, MATCH_AND_TERM);
300
 
        if (!m)
301
 
                return -ENOMEM;
302
 
 
303
 
        j->level1 = m;
 
341
        if (!j->level2)
 
342
                return 0;
 
343
 
 
344
        if (!j->level2->matches)
 
345
                return 0;
 
346
 
 
347
        j->level2 = NULL;
304
348
        return 0;
305
349
}
306
350
 
365
409
        if (j->level0)
366
410
                match_free(j->level0);
367
411
 
368
 
        j->level0 = j->level1 = NULL;
 
412
        j->level0 = j->level1 = j->level2 = NULL;
369
413
 
370
414
        detach_location(j);
371
415
}
587
631
                                        return r;
588
632
 
589
633
                                if ((direction == DIRECTION_DOWN ? cp >= after_offset : cp <= after_offset) &&
590
 
                                    (np == 0 || (direction == DIRECTION_DOWN ? cp > np : np < cp))) {
 
634
                                    (np == 0 || (direction == DIRECTION_DOWN ? cp > np : cp < np))) {
591
635
                                        np = cp;
592
636
                                        continue_looking = true;
593
637
                                }
1207
1251
                return;
1208
1252
 
1209
1253
        j->on_network =
1210
 
                (long)sfs.f_type == (long)CIFS_MAGIC_NUMBER ||
1211
 
                sfs.f_type == CODA_SUPER_MAGIC ||
1212
 
                sfs.f_type == NCP_SUPER_MAGIC ||
1213
 
                sfs.f_type == NFS_SUPER_MAGIC ||
1214
 
                sfs.f_type == SMB_SUPER_MAGIC;
 
1254
                sfs.f_type == (__SWORD_TYPE) CIFS_MAGIC_NUMBER ||
 
1255
                sfs.f_type == (__SWORD_TYPE) CODA_SUPER_MAGIC ||
 
1256
                sfs.f_type == (__SWORD_TYPE) NCP_SUPER_MAGIC ||
 
1257
                sfs.f_type == (__SWORD_TYPE) NFS_SUPER_MAGIC ||
 
1258
                sfs.f_type == (__SWORD_TYPE) SMB_SUPER_MAGIC;
1215
1259
}
1216
1260
 
1217
1261
static int add_file(sd_journal *j, const char *prefix, const char *filename) {
1218
 
        char *path;
 
1262
        _cleanup_free_ char *path = NULL;
1219
1263
        int r;
1220
1264
        JournalFile *f;
1221
1265
 
1234
1278
        if (!path)
1235
1279
                return -ENOMEM;
1236
1280
 
1237
 
        if (hashmap_get(j->files, path)) {
1238
 
                free(path);
 
1281
        if (hashmap_get(j->files, path))
1239
1282
                return 0;
1240
 
        }
1241
1283
 
1242
1284
        if (hashmap_size(j->files) >= JOURNAL_FILES_MAX) {
1243
1285
                log_debug("Too many open journal files, not adding %s, ignoring.", path);
1244
 
                free(path);
1245
 
                return 0;
 
1286
                return set_put_error(j, -ETOOMANYREFS);
1246
1287
        }
1247
1288
 
1248
1289
        r = journal_file_open(path, O_RDONLY, 0, false, false, NULL, j->mmap, NULL, &f);
1249
 
        free(path);
1250
 
 
1251
1290
        if (r < 0) {
1252
1291
                if (errno == ENOENT)
1253
1292
                        return 0;
1263
1302
                return r;
1264
1303
        }
1265
1304
 
 
1305
        log_debug("File %s got added.", f->path);
 
1306
 
1266
1307
        check_network(j, f->fd);
1267
1308
 
1268
1309
        j->current_invalidate_counter ++;
1269
1310
 
1270
 
        log_debug("File %s got added.", f->path);
1271
 
 
1272
1311
        return 0;
1273
1312
}
1274
1313
 
1311
1350
}
1312
1351
 
1313
1352
static int add_directory(sd_journal *j, const char *prefix, const char *dirname) {
1314
 
        char *path;
 
1353
        _cleanup_free_ char *path = NULL;
1315
1354
        int r;
1316
 
        DIR *d;
 
1355
        _cleanup_closedir_ DIR *d = NULL;
1317
1356
        sd_id128_t id, mid;
1318
1357
        Directory *m;
1319
1358
 
1336
1375
        d = opendir(path);
1337
1376
        if (!d) {
1338
1377
                log_debug("Failed to open %s: %m", path);
1339
 
                free(path);
1340
 
 
1341
1378
                if (errno == ENOENT)
1342
1379
                        return 0;
1343
1380
                return -errno;
1346
1383
        m = hashmap_get(j->directories_by_path, path);
1347
1384
        if (!m) {
1348
1385
                m = new0(Directory, 1);
1349
 
                if (!m) {
1350
 
                        closedir(d);
1351
 
                        free(path);
 
1386
                if (!m)
1352
1387
                        return -ENOMEM;
1353
 
                }
1354
1388
 
1355
1389
                m->is_root = false;
1356
1390
                m->path = path;
1357
1391
 
1358
1392
                if (hashmap_put(j->directories_by_path, m->path, m) < 0) {
1359
 
                        closedir(d);
1360
 
                        free(m->path);
1361
1393
                        free(m);
1362
1394
                        return -ENOMEM;
1363
1395
                }
1364
1396
 
 
1397
                path = NULL; /* avoid freeing in cleanup */
1365
1398
                j->current_invalidate_counter ++;
1366
1399
 
1367
1400
                log_debug("Directory %s got added.", m->path);
1368
1401
 
1369
 
        } else if (m->is_root) {
1370
 
                free (path);
1371
 
                closedir(d);
 
1402
        } else if (m->is_root)
1372
1403
                return 0;
1373
 
        }  else
1374
 
                free(path);
1375
1404
 
1376
1405
        if (m->wd <= 0 && j->inotify_fd >= 0) {
1377
1406
 
1395
1424
                if (dirent_is_file_with_suffix(de, ".journal") ||
1396
1425
                    dirent_is_file_with_suffix(de, ".journal~")) {
1397
1426
                        r = add_file(j, m->path, de->d_name);
1398
 
                        if (r < 0)
1399
 
                                log_debug("Failed to add file %s/%s: %s", m->path, de->d_name, strerror(-r));
 
1427
                        if (r < 0) {
 
1428
                                log_debug("Failed to add file %s/%s: %s",
 
1429
                                          m->path, de->d_name, strerror(-r));
 
1430
                                r = set_put_error(j, r);
 
1431
                                if (r < 0)
 
1432
                                        return r;
 
1433
                        }
1400
1434
                }
1401
1435
        }
1402
1436
 
1403
1437
        check_network(j, dirfd(d));
1404
1438
 
1405
 
        closedir(d);
1406
 
 
1407
1439
        return 0;
1408
1440
}
1409
1441
 
1410
1442
static int add_root_directory(sd_journal *j, const char *p) {
1411
 
        DIR *d;
 
1443
        _cleanup_closedir_ DIR *d = NULL;
1412
1444
        Directory *m;
1413
1445
        int r;
1414
1446
 
1426
1458
        m = hashmap_get(j->directories_by_path, p);
1427
1459
        if (!m) {
1428
1460
                m = new0(Directory, 1);
1429
 
                if (!m) {
1430
 
                        closedir(d);
 
1461
                if (!m)
1431
1462
                        return -ENOMEM;
1432
 
                }
1433
1463
 
1434
1464
                m->is_root = true;
1435
1465
                m->path = strdup(p);
1436
1466
                if (!m->path) {
1437
 
                        closedir(d);
1438
1467
                        free(m);
1439
1468
                        return -ENOMEM;
1440
1469
                }
1441
1470
 
1442
1471
                if (hashmap_put(j->directories_by_path, m->path, m) < 0) {
1443
 
                        closedir(d);
1444
1472
                        free(m->path);
1445
1473
                        free(m);
1446
1474
                        return -ENOMEM;
1450
1478
 
1451
1479
                log_debug("Root directory %s got added.", m->path);
1452
1480
 
1453
 
        } else if (!m->is_root) {
1454
 
                closedir(d);
 
1481
        } else if (!m->is_root)
1455
1482
                return 0;
1456
 
        }
1457
1483
 
1458
1484
        if (m->wd <= 0 && j->inotify_fd >= 0) {
1459
1485
 
1477
1503
                if (dirent_is_file_with_suffix(de, ".journal") ||
1478
1504
                    dirent_is_file_with_suffix(de, ".journal~")) {
1479
1505
                        r = add_file(j, m->path, de->d_name);
1480
 
                        if (r < 0)
1481
 
                                log_debug("Failed to add file %s/%s: %s", m->path, de->d_name, strerror(-r));
1482
 
 
 
1506
                        if (r < 0) {
 
1507
                                log_debug("Failed to add file %s/%s: %s",
 
1508
                                          m->path, de->d_name, strerror(-r));
 
1509
                                r = set_put_error(j, r);
 
1510
                                if (r < 0)
 
1511
                                        return r;
 
1512
                        }
1483
1513
                } else if ((de->d_type == DT_DIR || de->d_type == DT_LNK || de->d_type == DT_UNKNOWN) &&
1484
1514
                           sd_id128_from_string(de->d_name, &id) >= 0) {
1485
1515
 
1491
1521
 
1492
1522
        check_network(j, dirfd(d));
1493
1523
 
1494
 
        closedir(d);
1495
 
 
1496
1524
        return 0;
1497
1525
}
1498
1526
 
1520
1548
}
1521
1549
 
1522
1550
static int add_search_paths(sd_journal *j) {
1523
 
 
 
1551
        int r;
1524
1552
        const char search_paths[] =
1525
1553
                "/run/log/journal\0"
1526
1554
                "/var/log/journal\0";
1531
1559
        /* We ignore most errors here, since the idea is to only open
1532
1560
         * what's actually accessible, and ignore the rest. */
1533
1561
 
1534
 
        NULSTR_FOREACH(p, search_paths)
1535
 
                add_root_directory(j, p);
 
1562
        NULSTR_FOREACH(p, search_paths) {
 
1563
                r = add_root_directory(j, p);
 
1564
                if (r < 0 && r != -ENOENT) {
 
1565
                        r = set_put_error(j, r);
 
1566
                        if (r < 0)
 
1567
                                return r;
 
1568
                }
 
1569
        }
1536
1570
 
1537
1571
        return 0;
1538
1572
}
1568
1602
 
1569
1603
        if (path) {
1570
1604
                j->path = strdup(path);
1571
 
                if (!j->path) {
1572
 
                        free(j);
1573
 
                        return NULL;
1574
 
                }
 
1605
                if (!j->path)
 
1606
                        goto fail;
1575
1607
        }
1576
1608
 
1577
1609
        j->files = hashmap_new(string_hash_func, string_compare_func);
1578
 
        if (!j->files) {
1579
 
                free(j->path);
1580
 
                free(j);
1581
 
                return NULL;
1582
 
        }
1583
 
 
1584
1610
        j->directories_by_path = hashmap_new(string_hash_func, string_compare_func);
1585
 
        if (!j->directories_by_path) {
1586
 
                hashmap_free(j->files);
1587
 
                free(j->path);
1588
 
                free(j);
1589
 
                return NULL;
1590
 
        }
1591
 
 
1592
1611
        j->mmap = mmap_cache_new();
1593
 
        if (!j->mmap) {
1594
 
                hashmap_free(j->files);
1595
 
                hashmap_free(j->directories_by_path);
1596
 
                free(j->path);
1597
 
                free(j);
1598
 
                return NULL;
1599
 
        }
 
1612
        if (!j->files || !j->directories_by_path || !j->mmap)
 
1613
                goto fail;
1600
1614
 
1601
1615
        return j;
 
1616
 
 
1617
fail:
 
1618
        sd_journal_close(j);
 
1619
        return NULL;
1602
1620
}
1603
1621
 
1604
1622
_public_ int sd_journal_open(sd_journal **ret, int flags) {
1637
1655
        if (!ret)
1638
1656
                return -EINVAL;
1639
1657
 
1640
 
        if (!path || !path_is_absolute(path))
 
1658
        if (!path)
1641
1659
                return -EINVAL;
1642
1660
 
1643
1661
        if (flags != 0)
1648
1666
                return -ENOMEM;
1649
1667
 
1650
1668
        r = add_root_directory(j, path);
1651
 
        if (r < 0)
 
1669
        if (r < 0) {
 
1670
                set_put_error(j, r);
1652
1671
                goto fail;
 
1672
        }
1653
1673
 
1654
1674
        *ret = j;
1655
1675
        return 0;
1667
1687
        if (!j)
1668
1688
                return;
1669
1689
 
 
1690
        sd_journal_flush_matches(j);
 
1691
 
1670
1692
        while ((f = hashmap_steal_first(j->files)))
1671
1693
                journal_file_close(f);
1672
1694
 
1684
1706
        if (j->inotify_fd >= 0)
1685
1707
                close_nointr_nofail(j->inotify_fd);
1686
1708
 
1687
 
        sd_journal_flush_matches(j);
1688
 
 
1689
1709
        if (j->mmap)
1690
1710
                mmap_cache_unref(j->mmap);
1691
1711
 
1692
1712
        free(j->path);
1693
1713
        free(j->unique_field);
 
1714
        set_free(j->errors);
1694
1715
        free(j);
1695
1716
}
1696
1717
 
1989
2010
        return j->inotify_fd;
1990
2011
}
1991
2012
 
 
2013
_public_ int sd_journal_get_events(sd_journal *j) {
 
2014
        int fd;
 
2015
 
 
2016
        if (!j)
 
2017
                return -EINVAL;
 
2018
 
 
2019
        fd = sd_journal_get_fd(j);
 
2020
        if (fd < 0)
 
2021
                return fd;
 
2022
 
 
2023
        return POLLIN;
 
2024
}
 
2025
 
 
2026
_public_ int sd_journal_get_timeout(sd_journal *j, uint64_t *timeout_usec) {
 
2027
        int fd;
 
2028
 
 
2029
        if (!j)
 
2030
                return -EINVAL;
 
2031
        if (!timeout_usec)
 
2032
                return -EINVAL;
 
2033
 
 
2034
        fd = sd_journal_get_fd(j);
 
2035
        if (fd < 0)
 
2036
                return fd;
 
2037
 
 
2038
        if (!j->on_network) {
 
2039
                *timeout_usec = (uint64_t) -1;
 
2040
                return 0;
 
2041
        }
 
2042
 
 
2043
        /* If we are on the network we need to regularly check for
 
2044
         * changes manually */
 
2045
 
 
2046
        *timeout_usec = j->last_process_usec + JOURNAL_FILES_RECHECK_USEC;
 
2047
        return 1;
 
2048
}
 
2049
 
1992
2050
static void process_inotify_event(sd_journal *j, struct inotify_event *e) {
1993
2051
        Directory *d;
1994
2052
        int r;
2009
2067
 
2010
2068
                        if (e->mask & (IN_CREATE|IN_MOVED_TO|IN_MODIFY|IN_ATTRIB)) {
2011
2069
                                r = add_file(j, d->path, e->name);
2012
 
                                if (r < 0)
2013
 
                                        log_debug("Failed to add file %s/%s: %s", d->path, e->name, strerror(-r));
 
2070
                                if (r < 0) {
 
2071
                                        log_debug("Failed to add file %s/%s: %s",
 
2072
                                                  d->path, e->name, strerror(-r));
 
2073
                                        set_put_error(j, r);
 
2074
                                }
2014
2075
 
2015
2076
                        } else if (e->mask & (IN_DELETE|IN_MOVED_FROM|IN_UNMOUNT)) {
2016
2077
 
2068
2129
        if (!j)
2069
2130
                return -EINVAL;
2070
2131
 
 
2132
        j->last_process_usec = now(CLOCK_MONOTONIC);
 
2133
 
2071
2134
        for (;;) {
2072
2135
                struct inotify_event *e;
2073
2136
                ssize_t l;
2101
2164
 
2102
2165
_public_ int sd_journal_wait(sd_journal *j, uint64_t timeout_usec) {
2103
2166
        int r;
 
2167
        uint64_t t;
2104
2168
 
2105
2169
        assert(j);
2106
2170
 
2119
2183
                return determine_change(j);
2120
2184
        }
2121
2185
 
2122
 
        if (j->on_network) {
2123
 
                /* If we are on the network we need to regularly check
2124
 
                 * for changes manually */
2125
 
 
2126
 
                if (timeout_usec == (uint64_t) -1 || timeout_usec > JOURNAL_FILES_RECHECK_USEC)
2127
 
                        timeout_usec = JOURNAL_FILES_RECHECK_USEC;
 
2186
        r = sd_journal_get_timeout(j, &t);
 
2187
        if (r < 0)
 
2188
                return r;
 
2189
 
 
2190
        if (t != (uint64_t) -1) {
 
2191
                usec_t n;
 
2192
 
 
2193
                n = now(CLOCK_MONOTONIC);
 
2194
                t = t > n ? t - n : 0;
 
2195
 
 
2196
                if (timeout_usec == (uint64_t) -1 || timeout_usec > t)
 
2197
                        timeout_usec = t;
2128
2198
        }
2129
2199
 
2130
2200
        do {
2444
2514
        if (r < 0)
2445
2515
                return r;
2446
2516
 
2447
 
        r = catalog_get(id, &text);
 
2517
        r = catalog_get(CATALOG_DATABASE, id, &text);
2448
2518
        if (r < 0)
2449
2519
                return r;
2450
2520
 
2460
2530
        if (!ret)
2461
2531
                return -EINVAL;
2462
2532
 
2463
 
        return catalog_get(id, ret);
 
2533
        return catalog_get(CATALOG_DATABASE, id, ret);
2464
2534
}
2465
2535
 
2466
2536
_public_ int sd_journal_set_data_threshold(sd_journal *j, size_t sz) {