1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
//! What this server will accept, decided **before** the bytes arrive.
//!
//! # The two different things a "limit" means here
//!
//! They get confused, and confusing them is how a size cap gets treated as an
//! OOM defence it is not.
//!
//! * **[`Limits::max_object_bytes`] is a quota.** It protects disk and it
//! protects the client's time. It does *not* protect memory, because nothing
//! on this path allocates proportionally to the object.
//! * **[`CHUNK_BYTES`] is the memory bound**, and it is a constant. Every byte
//! of every LFS object passes through one buffer of this size, in both
//! directions. Peak resident memory for a transfer is that buffer plus the
//! hasher, whether the object is 4 KiB or 400 GiB. `tests/streaming.rs`
//! asserts it against the real process RSS, because a claim that something
//! "streams" is exactly the kind of claim a green unit test cannot make.
//!
//! # Enforced before arrival, following `gunnar-pack`
//!
//! `gunnar-pack`'s `alloc_limit_bytes` defaults to 1 GiB because a test in this
//! tree OOM'd a 499 GB machine by allocating what a header claimed. The same
//! discipline applies here and there are two places to apply it: the `batch`
//! request declares every object's size before any of them move, and
//! `put-object` declares one more time in its `size=` argument. **Both are
//! checked**, and the `put-object` check is the load-bearing one, because a
//! client is free to skip `batch` entirely.
/// The one buffer size every LFS byte passes through, in either direction.
///
/// It is `gunnar_pktline::MAX_PAYLOAD`, so an outbound chunk fills exactly one
/// pkt-line and no byte is copied twice to satisfy a smaller frame. The real
/// git-lfs client chunks its uploads at 32 KiB; both are legal and the reader on
/// each side is size-agnostic.
pub const CHUNK_BYTES: usize = MAX_PAYLOAD;
/// The default object quota: **8 GiB**.
///
/// Chosen to be generous rather than tight: LFS exists for large files and a
/// low default would make gunnar refuse the workloads it is for. It is finite
/// because "no limit" means a single client decides how much disk the server
/// has.
pub const DEFAULT_MAX_OBJECT_BYTES: u64 = 8 * 1024 * 1024 * 1024;
/// The default cap on objects named in one `batch` request: **10 000**.
pub const DEFAULT_MAX_BATCH_OBJECTS: usize = 10_000;
/// The default cap on `key=value` arguments attached to one command: **32**.
pub const DEFAULT_MAX_ARGS: usize = 32;
/// What a session will accept.