Ask for continuous discard where the runtime makes an ext4 - #870

Closed
MayCXC wants to merge 1 commit into
apple:mainfrom
MayCXC:online-discard
Closed

Ask for continuous discard where the runtime makes an ext4#870
MayCXC wants to merge 1 commit into
apple:mainfrom
MayCXC:online-discard

Conversation

@MayCXC

Copy link
Copy Markdown

Summary

A container's root filesystem and writable layer are sparse files, and the guest never returns the blocks it frees: deleting inside the guest frees guest blocks, the host file keeps every block it has ever touched, so its real size is the high water mark of everything ever written rather than what is live.

The filesystem hands freed blocks back the moment they are freed when its mount asks for discard, and the runtime forwards those discards to hole punches in the backing file. The ask belongs to the file: every ext4 the runtime creates is such a sparse file, so its mount options carry discard from the moment the mount exists, and every place the file is later mounted, container or pod, lower layer or writable, inherits the ask with the rest of the options. A read-only mount parses the option and leaves it idle.

Motivation and Context

This is the continuous counterpart to an explicit trim: rather than reclaiming in a sweep after the fact, the filesystem returns each block as it is freed, and the backing file stops growing to its high water mark.

Putting the option on the mount where the file is created, rather than at each place it is mounted, means a caller cannot forget it, and the two do not drift apart as more mount sites appear.

Relationship to #859

#859 adds an explicit trim that returns blocks on demand and reports how many. The two are complementary: continuous discard keeps a live filesystem from growing, while a trim reclaims what a filesystem that has been running without it already holds. Neither depends on the other, and they touch different files.

Testing

  • swift build and make check clean.
  • swift test: 595 tests in 82 suites passed.
  • Integration: the swap and reclaim tests watch the backing file's allocated blocks while a workload fills and frees, which is where a filesystem that keeps its high water mark shows up.

Type of Change

  • Bug fix
  • New feature
  • Breaking change
  • Documentation update

A container's root filesystem and writable layer are sparse files, and
the guest never returns the blocks it frees: deleting inside the guest
frees guest blocks, the host file keeps every block it has ever
touched, so its real size is the high water mark of everything ever
written rather than what is live.
The filesystem hands freed blocks back the moment they are freed when
its mount asks for discard, and the runtime forwards those discards to
hole punches in the backing file. The ask belongs to the file: every
ext4 the runtime creates is such a sparse file, so its mount options
carry discard from the moment the mount exists, and every place the
file is later mounted, container or pod, lower layer or writable,
inherits the ask with the rest of the options. A read-only mount
parses the option and leaves it idle, and a caller who builds a mount
of their own chooses their own options, as they do for everything
else. The swap area has asked for the same thing since it was added,
for the same reason.
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@MayCXC@crosbymichael
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Ask for continuous discard where the runtime makes an ext4 - #870

Closed
MayCXC wants to merge 1 commit into
apple:mainfrom
MayCXC:online-discard
Closed

Ask for continuous discard where the runtime makes an ext4#870
MayCXC wants to merge 1 commit into
apple:mainfrom
MayCXC:online-discard

Conversation

@MayCXC

Copy link
Copy Markdown

Summary

A container's root filesystem and writable layer are sparse files, and the guest never returns the blocks it frees: deleting inside the guest frees guest blocks, the host file keeps every block it has ever touched, so its real size is the high water mark of everything ever written rather than what is live.

The filesystem hands freed blocks back the moment they are freed when its mount asks for discard, and the runtime forwards those discards to hole punches in the backing file. The ask belongs to the file: every ext4 the runtime creates is such a sparse file, so its mount options carry discard from the moment the mount exists, and every place the file is later mounted, container or pod, lower layer or writable, inherits the ask with the rest of the options. A read-only mount parses the option and leaves it idle.

Motivation and Context

This is the continuous counterpart to an explicit trim: rather than reclaiming in a sweep after the fact, the filesystem returns each block as it is freed, and the backing file stops growing to its high water mark.

Putting the option on the mount where the file is created, rather than at each place it is mounted, means a caller cannot forget it, and the two do not drift apart as more mount sites appear.

Relationship to #859

#859 adds an explicit trim that returns blocks on demand and reports how many. The two are complementary: continuous discard keeps a live filesystem from growing, while a trim reclaims what a filesystem that has been running without it already holds. Neither depends on the other, and they touch different files.

Testing

  • swift build and make check clean.
  • swift test: 595 tests in 82 suites passed.
  • Integration: the swap and reclaim tests watch the backing file's allocated blocks while a workload fills and frees, which is where a filesystem that keeps its high water mark shows up.

Type of Change

  • Bug fix
  • New feature
  • Breaking change
  • Documentation update

A container's root filesystem and writable layer are sparse files, and
the guest never returns the blocks it frees: deleting inside the guest
frees guest blocks, the host file keeps every block it has ever
touched, so its real size is the high water mark of everything ever
written rather than what is live.
The filesystem hands freed blocks back the moment they are freed when
its mount asks for discard, and the runtime forwards those discards to
hole punches in the backing file. The ask belongs to the file: every
ext4 the runtime creates is such a sparse file, so its mount options
carry discard from the moment the mount exists, and every place the
file is later mounted, container or pod, lower layer or writable,
inherits the ask with the rest of the options. A read-only mount
parses the option and leaves it idle, and a caller who builds a mount
of their own chooses their own options, as they do for everything
else. The swap area has asked for the same thing since it was added,
for the same reason.
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@MayCXC@crosbymichael
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Ask for continuous discard where the runtime makes an ext4 - #870

Closed
MayCXC wants to merge 1 commit into
apple:mainfrom
MayCXC:online-discard
Closed

Ask for continuous discard where the runtime makes an ext4#870
MayCXC wants to merge 1 commit into
apple:mainfrom
MayCXC:online-discard

Conversation

@MayCXC

Copy link
Copy Markdown

Summary

A container's root filesystem and writable layer are sparse files, and the guest never returns the blocks it frees: deleting inside the guest frees guest blocks, the host file keeps every block it has ever touched, so its real size is the high water mark of everything ever written rather than what is live.

The filesystem hands freed blocks back the moment they are freed when its mount asks for discard, and the runtime forwards those discards to hole punches in the backing file. The ask belongs to the file: every ext4 the runtime creates is such a sparse file, so its mount options carry discard from the moment the mount exists, and every place the file is later mounted, container or pod, lower layer or writable, inherits the ask with the rest of the options. A read-only mount parses the option and leaves it idle.

Motivation and Context

This is the continuous counterpart to an explicit trim: rather than reclaiming in a sweep after the fact, the filesystem returns each block as it is freed, and the backing file stops growing to its high water mark.

Putting the option on the mount where the file is created, rather than at each place it is mounted, means a caller cannot forget it, and the two do not drift apart as more mount sites appear.

Relationship to #859

#859 adds an explicit trim that returns blocks on demand and reports how many. The two are complementary: continuous discard keeps a live filesystem from growing, while a trim reclaims what a filesystem that has been running without it already holds. Neither depends on the other, and they touch different files.

Testing

  • swift build and make check clean.
  • swift test: 595 tests in 82 suites passed.
  • Integration: the swap and reclaim tests watch the backing file's allocated blocks while a workload fills and frees, which is where a filesystem that keeps its high water mark shows up.

Type of Change

  • Bug fix
  • New feature
  • Breaking change
  • Documentation update

A container's root filesystem and writable layer are sparse files, and
the guest never returns the blocks it frees: deleting inside the guest
frees guest blocks, the host file keeps every block it has ever
touched, so its real size is the high water mark of everything ever
written rather than what is live.
The filesystem hands freed blocks back the moment they are freed when
its mount asks for discard, and the runtime forwards those discards to
hole punches in the backing file. The ask belongs to the file: every
ext4 the runtime creates is such a sparse file, so its mount options
carry discard from the moment the mount exists, and every place the
file is later mounted, container or pod, lower layer or writable,
inherits the ask with the rest of the options. A read-only mount
parses the option and leaves it idle, and a caller who builds a mount
of their own chooses their own options, as they do for everything
else. The swap area has asked for the same thing since it was added,
for the same reason.
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@MayCXC@crosbymichael
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Ask for continuous discard where the runtime makes an ext4 - #870

Closed
MayCXC wants to merge 1 commit into
apple:mainfrom
MayCXC:online-discard
Closed

Ask for continuous discard where the runtime makes an ext4#870
MayCXC wants to merge 1 commit into
apple:mainfrom
MayCXC:online-discard

Conversation

@MayCXC

Copy link
Copy Markdown

Summary

A container's root filesystem and writable layer are sparse files, and the guest never returns the blocks it frees: deleting inside the guest frees guest blocks, the host file keeps every block it has ever touched, so its real size is the high water mark of everything ever written rather than what is live.

The filesystem hands freed blocks back the moment they are freed when its mount asks for discard, and the runtime forwards those discards to hole punches in the backing file. The ask belongs to the file: every ext4 the runtime creates is such a sparse file, so its mount options carry discard from the moment the mount exists, and every place the file is later mounted, container or pod, lower layer or writable, inherits the ask with the rest of the options. A read-only mount parses the option and leaves it idle.

Motivation and Context

This is the continuous counterpart to an explicit trim: rather than reclaiming in a sweep after the fact, the filesystem returns each block as it is freed, and the backing file stops growing to its high water mark.

Putting the option on the mount where the file is created, rather than at each place it is mounted, means a caller cannot forget it, and the two do not drift apart as more mount sites appear.

Relationship to #859

#859 adds an explicit trim that returns blocks on demand and reports how many. The two are complementary: continuous discard keeps a live filesystem from growing, while a trim reclaims what a filesystem that has been running without it already holds. Neither depends on the other, and they touch different files.

Testing

  • swift build and make check clean.
  • swift test: 595 tests in 82 suites passed.
  • Integration: the swap and reclaim tests watch the backing file's allocated blocks while a workload fills and frees, which is where a filesystem that keeps its high water mark shows up.

Type of Change

  • Bug fix
  • New feature
  • Breaking change
  • Documentation update

A container's root filesystem and writable layer are sparse files, and
the guest never returns the blocks it frees: deleting inside the guest
frees guest blocks, the host file keeps every block it has ever
touched, so its real size is the high water mark of everything ever
written rather than what is live.
The filesystem hands freed blocks back the moment they are freed when
its mount asks for discard, and the runtime forwards those discards to
hole punches in the backing file. The ask belongs to the file: every
ext4 the runtime creates is such a sparse file, so its mount options
carry discard from the moment the mount exists, and every place the
file is later mounted, container or pod, lower layer or writable,
inherits the ask with the rest of the options. A read-only mount
parses the option and leaves it idle, and a caller who builds a mount
of their own chooses their own options, as they do for everything
else. The swap area has asked for the same thing since it was added,
for the same reason.
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@MayCXC@crosbymichael
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Ask for continuous discard where the runtime makes an ext4 - #870

Closed
MayCXC wants to merge 1 commit into
apple:mainfrom
MayCXC:online-discard
Closed

Ask for continuous discard where the runtime makes an ext4#870
MayCXC wants to merge 1 commit into
apple:mainfrom
MayCXC:online-discard

Conversation

@MayCXC

Copy link
Copy Markdown

Summary

A container's root filesystem and writable layer are sparse files, and the guest never returns the blocks it frees: deleting inside the guest frees guest blocks, the host file keeps every block it has ever touched, so its real size is the high water mark of everything ever written rather than what is live.

The filesystem hands freed blocks back the moment they are freed when its mount asks for discard, and the runtime forwards those discards to hole punches in the backing file. The ask belongs to the file: every ext4 the runtime creates is such a sparse file, so its mount options carry discard from the moment the mount exists, and every place the file is later mounted, container or pod, lower layer or writable, inherits the ask with the rest of the options. A read-only mount parses the option and leaves it idle.

Motivation and Context

This is the continuous counterpart to an explicit trim: rather than reclaiming in a sweep after the fact, the filesystem returns each block as it is freed, and the backing file stops growing to its high water mark.

Putting the option on the mount where the file is created, rather than at each place it is mounted, means a caller cannot forget it, and the two do not drift apart as more mount sites appear.

Relationship to #859

#859 adds an explicit trim that returns blocks on demand and reports how many. The two are complementary: continuous discard keeps a live filesystem from growing, while a trim reclaims what a filesystem that has been running without it already holds. Neither depends on the other, and they touch different files.

Testing

  • swift build and make check clean.
  • swift test: 595 tests in 82 suites passed.
  • Integration: the swap and reclaim tests watch the backing file's allocated blocks while a workload fills and frees, which is where a filesystem that keeps its high water mark shows up.

Type of Change

  • Bug fix
  • New feature
  • Breaking change
  • Documentation update

A container's root filesystem and writable layer are sparse files, and
the guest never returns the blocks it frees: deleting inside the guest
frees guest blocks, the host file keeps every block it has ever
touched, so its real size is the high water mark of everything ever
written rather than what is live.
The filesystem hands freed blocks back the moment they are freed when
its mount asks for discard, and the runtime forwards those discards to
hole punches in the backing file. The ask belongs to the file: every
ext4 the runtime creates is such a sparse file, so its mount options
carry discard from the moment the mount exists, and every place the
file is later mounted, container or pod, lower layer or writable,
inherits the ask with the rest of the options. A read-only mount
parses the option and leaves it idle, and a caller who builds a mount
of their own chooses their own options, as they do for everything
else. The swap area has asked for the same thing since it was added,
for the same reason.
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@MayCXC@crosbymichael
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Ask for continuous discard where the runtime makes an ext4 - #870

Closed
MayCXC wants to merge 1 commit into
apple:mainfrom
MayCXC:online-discard
Closed

Ask for continuous discard where the runtime makes an ext4#870
MayCXC wants to merge 1 commit into
apple:mainfrom
MayCXC:online-discard

Conversation

@MayCXC

Copy link
Copy Markdown

Summary

A container's root filesystem and writable layer are sparse files, and the guest never returns the blocks it frees: deleting inside the guest frees guest blocks, the host file keeps every block it has ever touched, so its real size is the high water mark of everything ever written rather than what is live.

The filesystem hands freed blocks back the moment they are freed when its mount asks for discard, and the runtime forwards those discards to hole punches in the backing file. The ask belongs to the file: every ext4 the runtime creates is such a sparse file, so its mount options carry discard from the moment the mount exists, and every place the file is later mounted, container or pod, lower layer or writable, inherits the ask with the rest of the options. A read-only mount parses the option and leaves it idle.

Motivation and Context

This is the continuous counterpart to an explicit trim: rather than reclaiming in a sweep after the fact, the filesystem returns each block as it is freed, and the backing file stops growing to its high water mark.

Putting the option on the mount where the file is created, rather than at each place it is mounted, means a caller cannot forget it, and the two do not drift apart as more mount sites appear.

Relationship to #859

#859 adds an explicit trim that returns blocks on demand and reports how many. The two are complementary: continuous discard keeps a live filesystem from growing, while a trim reclaims what a filesystem that has been running without it already holds. Neither depends on the other, and they touch different files.

Testing

  • swift build and make check clean.
  • swift test: 595 tests in 82 suites passed.
  • Integration: the swap and reclaim tests watch the backing file's allocated blocks while a workload fills and frees, which is where a filesystem that keeps its high water mark shows up.

Type of Change

  • Bug fix
  • New feature
  • Breaking change
  • Documentation update

A container's root filesystem and writable layer are sparse files, and
the guest never returns the blocks it frees: deleting inside the guest
frees guest blocks, the host file keeps every block it has ever
touched, so its real size is the high water mark of everything ever
written rather than what is live.
The filesystem hands freed blocks back the moment they are freed when
its mount asks for discard, and the runtime forwards those discards to
hole punches in the backing file. The ask belongs to the file: every
ext4 the runtime creates is such a sparse file, so its mount options
carry discard from the moment the mount exists, and every place the
file is later mounted, container or pod, lower layer or writable,
inherits the ask with the rest of the options. A read-only mount
parses the option and leaves it idle, and a caller who builds a mount
of their own chooses their own options, as they do for everything
else. The swap area has asked for the same thing since it was added,
for the same reason.
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@MayCXC@crosbymichael
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Ask for continuous discard where the runtime makes an ext4 - #870

Closed
MayCXC wants to merge 1 commit into
apple:mainfrom
MayCXC:online-discard
Closed

Ask for continuous discard where the runtime makes an ext4#870
MayCXC wants to merge 1 commit into
apple:mainfrom
MayCXC:online-discard

Conversation

@MayCXC

Copy link
Copy Markdown

Summary

A container's root filesystem and writable layer are sparse files, and the guest never returns the blocks it frees: deleting inside the guest frees guest blocks, the host file keeps every block it has ever touched, so its real size is the high water mark of everything ever written rather than what is live.

The filesystem hands freed blocks back the moment they are freed when its mount asks for discard, and the runtime forwards those discards to hole punches in the backing file. The ask belongs to the file: every ext4 the runtime creates is such a sparse file, so its mount options carry discard from the moment the mount exists, and every place the file is later mounted, container or pod, lower layer or writable, inherits the ask with the rest of the options. A read-only mount parses the option and leaves it idle.

Motivation and Context

This is the continuous counterpart to an explicit trim: rather than reclaiming in a sweep after the fact, the filesystem returns each block as it is freed, and the backing file stops growing to its high water mark.

Putting the option on the mount where the file is created, rather than at each place it is mounted, means a caller cannot forget it, and the two do not drift apart as more mount sites appear.

Relationship to #859

#859 adds an explicit trim that returns blocks on demand and reports how many. The two are complementary: continuous discard keeps a live filesystem from growing, while a trim reclaims what a filesystem that has been running without it already holds. Neither depends on the other, and they touch different files.

Testing

  • swift build and make check clean.
  • swift test: 595 tests in 82 suites passed.
  • Integration: the swap and reclaim tests watch the backing file's allocated blocks while a workload fills and frees, which is where a filesystem that keeps its high water mark shows up.

Type of Change

  • Bug fix
  • New feature
  • Breaking change
  • Documentation update

A container's root filesystem and writable layer are sparse files, and
the guest never returns the blocks it frees: deleting inside the guest
frees guest blocks, the host file keeps every block it has ever
touched, so its real size is the high water mark of everything ever
written rather than what is live.
The filesystem hands freed blocks back the moment they are freed when
its mount asks for discard, and the runtime forwards those discards to
hole punches in the backing file. The ask belongs to the file: every
ext4 the runtime creates is such a sparse file, so its mount options
carry discard from the moment the mount exists, and every place the
file is later mounted, container or pod, lower layer or writable,
inherits the ask with the rest of the options. A read-only mount
parses the option and leaves it idle, and a caller who builds a mount
of their own chooses their own options, as they do for everything
else. The swap area has asked for the same thing since it was added,
for the same reason.
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@MayCXC@crosbymichael
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Ask for continuous discard where the runtime makes an ext4 - #870

Closed
MayCXC wants to merge 1 commit into
apple:mainfrom
MayCXC:online-discard
Closed

Ask for continuous discard where the runtime makes an ext4#870
MayCXC wants to merge 1 commit into
apple:mainfrom
MayCXC:online-discard

Conversation

@MayCXC

Copy link
Copy Markdown

Summary

A container's root filesystem and writable layer are sparse files, and the guest never returns the blocks it frees: deleting inside the guest frees guest blocks, the host file keeps every block it has ever touched, so its real size is the high water mark of everything ever written rather than what is live.

The filesystem hands freed blocks back the moment they are freed when its mount asks for discard, and the runtime forwards those discards to hole punches in the backing file. The ask belongs to the file: every ext4 the runtime creates is such a sparse file, so its mount options carry discard from the moment the mount exists, and every place the file is later mounted, container or pod, lower layer or writable, inherits the ask with the rest of the options. A read-only mount parses the option and leaves it idle.

Motivation and Context

This is the continuous counterpart to an explicit trim: rather than reclaiming in a sweep after the fact, the filesystem returns each block as it is freed, and the backing file stops growing to its high water mark.

Putting the option on the mount where the file is created, rather than at each place it is mounted, means a caller cannot forget it, and the two do not drift apart as more mount sites appear.

Relationship to #859

#859 adds an explicit trim that returns blocks on demand and reports how many. The two are complementary: continuous discard keeps a live filesystem from growing, while a trim reclaims what a filesystem that has been running without it already holds. Neither depends on the other, and they touch different files.

Testing

  • swift build and make check clean.
  • swift test: 595 tests in 82 suites passed.
  • Integration: the swap and reclaim tests watch the backing file's allocated blocks while a workload fills and frees, which is where a filesystem that keeps its high water mark shows up.

Type of Change

  • Bug fix
  • New feature
  • Breaking change
  • Documentation update

A container's root filesystem and writable layer are sparse files, and
the guest never returns the blocks it frees: deleting inside the guest
frees guest blocks, the host file keeps every block it has ever
touched, so its real size is the high water mark of everything ever
written rather than what is live.
The filesystem hands freed blocks back the moment they are freed when
its mount asks for discard, and the runtime forwards those discards to
hole punches in the backing file. The ask belongs to the file: every
ext4 the runtime creates is such a sparse file, so its mount options
carry discard from the moment the mount exists, and every place the
file is later mounted, container or pod, lower layer or writable,
inherits the ask with the rest of the options. A read-only mount
parses the option and leaves it idle, and a caller who builds a mount
of their own chooses their own options, as they do for everything
else. The swap area has asked for the same thing since it was added,
for the same reason.
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@MayCXC@crosbymichael