"cache_creation":{"ephemeral_1h_input_tokens":210,"ephemeral_5m_input_tokens":0},"inference_geo":"","iterations":[],"speed":"standard"}},"requestId":"req_011CYWpK5u6H6Pq2E5tBmqUi","type":"assistant","uuid":"33fcc02f-096d-4922-8347-5e47edfcfb0e","timestamp":"2026-02-26T14:11:58.713Z"} {"parentUuid":"33fcc02f-096d-4922-8347-5e47edfcfb0e","isSidechain":false,"userType":"external","cwd":"/home/josie/notes","sessionId":"86c1fab3-7cc6-4988-afc5-b6d71f120498","version":"2.1.51","gitBranch":"HEAD","slug":"structured-marinating-quiche","type":"progress","data":{"type":"hook_progress","hookEvent":"PreToolUse","hookName":"PreToolUse:Bash","command":"python3 ${CLAUDE_PLUGIN_ROOT}/hooks/pretooluse.py"},"toolUseID":"toolu_01A6Zwrr8cAhqgBtrc2kwyHe","parentToolUseID":"toolu_01A6Zwrr8cAhqgBtrc2kwyHe","uuid":"a3ee70fa-4624-41b3-b1c2-d00e5980a4b4","timestamp":"2026-02-26T14:11:58.716Z"} {"parentUuid":"33fcc02f-096d-4922-8347-5e47edfcfb0e","isSidechain":false,"userType":"external","cwd":"/home/josie/notes","sessionId":"86c1fab3-7cc6-4988-afc5-b6d71f120498","version":"2.1.51","gitBranch":"HEAD","slug":"structured-marinating-quiche","type":"user","message":{"role":"user","content":[{"type":"tool_result","content":"Exit code 1\n File \"/home/josie/notes/index_cdn_froggie.py\", line 296\n global MAX_CONCURRENT\n ^^^^^^^^^^^^^^^^^^^^^\nSyntaxError: name 'MAX_CONCURRENT' is used prior to global declaration\n\n File \"/home/josie/notes/index_cdn_froggie.py\", line 296\n global MAX_CONCURRENT\n ^^^^^^^^^^^^^^^^^^^^^\nSyntaxError: name 'MAX_CONCURRENT' is used prior to global declaration","is_error":true,"tool_use_id":"toolu_01A6Zwrr8cAhqgBtrc2kwyHe"}]},"uuid":"f4d9ea06-82e7-4717-a4c7-fc06adba391a","timestamp":"2026-02-26T14:12:04.858Z","toolUseResult":"Error: Exit code 1\n File \"/home/josie/notes/index_cdn_froggie.py\", line 296\n global MAX_CONCURRENT\n ^^^^^^^^^^^^^^^^^^^^^\nSyntaxError: name 'MAX_CONCURRENT' is used prior to global declaration\n\n File \"/home/josie/notes/index_cdn_froggie.py\", line 296\n global MAX_CONCURRENT\n ^^^^^^^^^^^^^^^^^^^^^\nSyntaxError: name 'MAX_CONCURRENT' is used prior to global declaration","sourceToolAssistantUUID":"33fcc02f-096d-4922-8347-5e47edfcfb0e"} {"parentUuid":"f4d9ea06-82e7-4717-a4c7-fc06adba391a","isSidechain":false,"userType":"external","cwd":"/home/josie/notes","sessionId":"86c1fab3-7cc6-4988-afc5-b6d71f120498","version":"2.1.51","gitBranch":"HEAD","slug":"structured-marinating-quiche","message":{"model":"claude-opus-4-6","id":"msg_01LH8ZoWgoyDoArrzgT17Tqi","type":"message","role":"assistant","content":[{"type":"text","text":"Need to fix the global usage -- the semaphore in `brute_force_probe` reads `MAX_CONCURRENT` before the global declaration in `main`. Let me restructure to pass concurrency as a parameter instead."}],"stop_reason":null,"stop_sequence":null,"usage":{"input_tokens":1,"cache_creation_input_tokens":268,"cache_read_input_tokens":35097,"cache_creation":{"ephemeral_5m_input_tokens":0,"ephemeral_1h_input_tokens":268},"output_tokens":1,"service_tier":"standard","inference_geo":"not_available"}},"requestId":"req_011CYWpL5eVSWpn7jaAniWcx","type":"assistant","uuid":"e6eb24f8-9fe0-4d72-a371-66ac0260dc47","timestamp":"2026-02-26T14:12:09.260Z"} {"parentUuid":"e6eb24f8-9fe0-4d72-a371-66ac0260dc47","isSidechain":false,"userType":"external","cwd":"/home/josie/notes","sessionId":"86c1fab3-7cc6-4988-afc5-b6d71f120498","version":"2.1.51","gitBranch":"HEAD","slug":"structured-marinating-quiche","message":{"model":"claude-opus-4-6","id":"msg_01LH8ZoWgoyDoArrzgT17Tqi","type":"message","role":"assistant","content":[{"type":"tool_use","id":"toolu_01MPv1yw2EFrSVQYyZB3spuy","name":"Read","input":{"file_path":"/home/josie/notes/index_cdn_froggie.py","offset":170,"limit":50},"caller":{"type":"direct"}}],"stop_reason":null,"stop_sequence":null,"usage":{"input_tokens":1,"cache_creation_input_tokens":268,"cache_read_input_tokens":35097,"cache_creation":{"ephemeral_5m_input_tokens":0,"ephemeral_1h_input_tokens":268},"output_tokens":1,"service_tier":"standard","inference_geo":"not_available"}},"requestId":"req_011CYWpL5eVSWpn7jaAniWcx","type":"assistant","uuid":"bdccfa94-e99d-4f02-b4b9-696519f7a25b","timestamp":"2026-02-26T14:12:09.968Z"} {"parentUuid":"bdccfa94-e99d-4f02-b4b9-696519f7a25b","isSidechain":false,"userType":"external","cwd":"/home/josie/notes","sessionId":"86c1fab3-7cc6-4988-afc5-b6d71f120498","version":"2.1.51","gitBranch":"HEAD","slug":"structured-marinating-quiche","type":"progress","data":{"type":"hook_progress","hookEvent":"PreToolUse","hookName":"PreToolUse:Read","command":"python3 ${CLAUDE_PLUGIN_ROOT}/hooks/pretooluse.py"},"toolUseID":"toolu_01MPv1yw2EFrSVQYyZB3spuy","parentToolUseID":"toolu_01MPv1yw2EFrSVQYyZB3spuy","uuid":"c5e8ba71-12bd-4c83-a679-55a9ea72cd4e","timestamp":"2026-02-26T14:12:09.970Z"} {"parentUuid":"c5e8ba71-12bd-4c83-a679-55a9ea72cd4e","isSidechain":false,"userType":"external","cwd":"/home/josie/notes","sessionId":"86c1fab3-7cc6-4988-afc5-b6d71f120498","version":"2.1.51","gitBranch":"HEAD","slug":"structured-marinating-quiche","type":"progress","data":{"type":"hook_progress","hookEvent":"PostToolUse","hookName":"PostToolUse:Read","command":"python3 ${CLAUDE_PLUGIN_ROOT}/hooks/posttooluse.py"},"parentToolUseID":"toolu_01MPv1yw2EFrSVQYyZB3spuy","toolUseID":"toolu_01MPv1yw2EFrSVQYyZB3spuy","timestamp":"2026-02-26T14:12:10.041Z","uuid":"b9269542-e2a8-47a7-869f-e47d59a4710d"} {"parentUuid":"b9269542-e2a8-47a7-869f-e47d59a4710d","isSidechain":false,"userType":"external","cwd":"/home/josie/notes","sessionId":"86c1fab3-7cc6-4988-afc5-b6d71f120498","version":"2.1.51","gitBranch":"HEAD","slug":"structured-marinating-quiche","type":"progress","data":{"type":"hook_progress","hookEvent":"PostToolUse","hookName":"PostToolUse:Read","command":"callback"},"parentToolUseID":"toolu_01MPv1yw2EFrSVQYyZB3spuy","toolUseID":"toolu_01MPv1yw2EFrSVQYyZB3spuy","timestamp":"2026-02-26T14:12:10.041Z","uuid":"6b51ad28-e3a3-46d2-b0bb-c821b4d6f17e"} {"parentUuid":"bdccfa94-e99d-4f02-b4b9-696519f7a25b","isSidechain":false,"userType":"external","cwd":"/home/josie/notes","sessionId":"86c1fab3-7cc6-4988-afc5-b6d71f120498","version":"2.1.51","gitBranch":"HEAD","slug":"structured-marinating-quiche","type":"user","message":{"role":"user","content":[{"tool_use_id":"toolu_01MPv1yw2EFrSVQYyZB3spuy","type":"tool_result","content":" 170→ \"\"\"Recursively crawl directory listings starting from path.\"\"\"\n 171→ if found is None:\n 172→ found = set()\n 173→\n 174→ url = urljoin(base, path)\n 175→ if not path.endswith(\"/\"):\n 176→ path += \"/\"\n 177→\n 178→ hrefs = await fetch_directory_listing(client, url)\n 179→ for href in hrefs:\n 180→ full_path = urljoin(path, href)\n 181→ if full_path in found:\n 182→ continue\n 183→ if href.endswith(\"/\"):\n 184→ found.add(full_path)\n 185→ await crawl(client, base, full_path, found)\n 186→ else:\n 187→ found.add(full_path)\n 188→\n 189→ return found\n 190→\n 191→\n 192→async def probe_path(client: httpx.AsyncClient, base: str, path: str, semaphore: asyncio.Semaphore) -> str | None:\n 193→ \"\"\"Check if a path exists via HEAD request. Returns path if found.\"\"\"\n 194→ url = urljoin(base, path)\n 195→ async with semaphore:\n 196→ try:\n 197→ resp = await client.head(url, follow_redirects=True)\n 198→ if resp.status_code == 200:\n 199→ final_url = str(resp.url)\n 200→ if not final_url.rstrip(\"/\").endswith(base.rstrip(\"/\")):\n 201→ return path\n 202→ except httpx.HTTPError:\n 203→ pass\n 204→ return None\n 205→\n 206→\n 207→async def brute_force_probe(client: httpx.AsyncClient, base: str, known: set[str]) -> set[str]:\n 208→ \"\"\"Probe for common filenames and basename+extension combos.\"\"\"\n 209→ candidates = set()\n 210→\n 211→ for name in COMMON_FILENAMES:\n 212→ p = f\"/{name}\"\n 213→ if p not in known:\n 214→ candidates.add(p)\n 215→\n 216→ for basename in PROBE_BASENAMES:\n 217→ p = f\"/{basename}\"\n 218→ if p not in known:\n 219→ candidates.add(p)"}]},"uuid":"c5c8a8f0-28c6-4604-b99b-19260f024619","timestamp":"2026-02-26T14:12:10.039Z","toolUseResult":{"type":"text","file":{"filePath":"/home/josie/notes/index_cdn_froggie.py","content":" \"\"\"Recursively crawl directory listings starting from path.\"\"\"\n if found is None:\n found = set()\n\n url = urljoin(base, path)\n if not path.endswith(\"/\"):\n path += \"/\"\n\n hrefs = await fetch_directory_listing(client, url)\n for href in hrefs:\n full_path = urljoin(path, href)\n if full_path in found:\n continue\n if href.endswith(\"/\"):\n found.add(full_path)\n await crawl(client, base, full_path, found)\n else:\n found.add(full_path)\n\n return found\n\n\nasync def probe_path(client: httpx.AsyncClient, base: str, path: str, semaphore: asyncio.Semaphore) -> str | None:\n \"\"\"Check if a path exists via HEAD request. Returns path if found.\"\"\"\n url = urljoin(base, path)\n async with semaphore:\n try:\n resp = await client.head(url, follow_redirects=True)\n if resp.status_code == 200:\n final_url = str(resp.url)\n if not final_url.rstrip(\"/\").endswith(base.rstrip(\"/\")):\n return path\n except httpx.HTTPError:\n pass\n return None\n\n\nasync def brute_force_probe(client: httpx.AsyncClient, base: str, known: set[str]) -> set[str]:\n \"\"\"Probe for common filenames and basename+extension combos.\"\"\"\n candidates = set()\n\n for name in COMMON_FILENAMES:\n p = f\"/{name}\"\n if p not in known:\n candidates.add(p)\n\n for basename in PROBE_BASENAMES:\n p = f\"/{basename}\"\n if p not in known:\n candidates.add(p)","numLines":50,"startLine":170,"totalLines":304}},"sourceToolAssistantUUID":"bdccfa94-e99d-4f02-b4b9-696519f7a25b"} {"parentUuid":"c5c8a8f0-28c6-4604-b99b-19260f024619","isSidechain":false,"userType":"external","cwd":"/home/josie/notes","sessionId":"86c1fab3-7cc6-4988-afc5-b6d71f120498","version":"2.1.51","gitBranch":"HEAD","slug":"structured-marinating-quiche","message":{"model":"claude-opus-4-6","id":"msg_017jHpMYnvtZMCfSnaAiwqw6","type":"message","role":"assistant","content":[{"type":"tool_use","id":"toolu_01GT7LXvR4cWPiyeCyVBHtXX","name":"Read","input":{"file_path":"/home/josie/notes/index_cdn_froggie.py","offset":220,"limit":90},"caller":{"type":"direct"}}],"stop_reason":null,"stop_sequence":null,"usage":{"input_tokens":1,"cache_creation_input_tokens":774,"cache_read_input_tokens":35365,"output_tokens":103,"server_tool_use":{"web_search_requests":0,"web_fetch_requests":0},"service_tier":"standard","cache_creation":{"ephemeral_1h_input_tokens":774,"ephemeral_5m_input_tokens":0},"inference_geo":"","iterations":[],"speed":"standard"}},"requestId":"req_011CYWpLT6qL2SYDgmjCqykd","type":"assistant","uuid":"d9e4610a-7dad-4442-aa1d-99e35bd848c7","timestamp":"2026-02-26T14:12:13.600Z"} {"parentUuid":"d9e4610a-7dad-4442-aa1d-99e35bd848c7","isSidechain":false,"userType":"external","cwd":"/home/josie/notes","sessionId":"86c1fab3-7cc6-4988-afc5-b6d71f120498","version":"2.1.51","gitBranch":"HEAD","slug":"structured-marinating-quiche","type":"progress","data":{"type":"hook_progress","hookEvent":"PreToolUse","hookName":"PreToolUse:Read","command":"python3 ${CLAUDE_PLUGIN_ROOT}/hooks/pretooluse.py"},"toolUseID":"toolu_01GT7LXvR4cWPiyeCyVBHtXX","parentToolUseID":"toolu_01GT7LXvR4cWPiyeCyVBHtXX","uuid":"0c64b564-d1d4-44d5-b2db-5c775140fa07","timestamp":"2026-02-26T14:12:13.602Z"} {"parentUuid":"0c64b564-d1d4-44d5-b2db-5c775140fa07","isSidechain":false,"userType":"external","cwd":"/home/josie/notes","sessionId":"86c1fab3-7cc6-4988-afc5-b6d71f120498","version":"2.1.51","gitBranch":"HEAD","slug":"structured-marinating-quiche","type":"progress","data":{"type":"hook_progress","hookEvent":"PostToolUse","hookName":"PostToolUse:Read","command":"python3 ${CLAUDE_PLUGIN_ROOT}/hooks/posttooluse.py"},"parentToolUseID":"toolu_01GT7LXvR4cWPiyeCyVBHtXX","toolUseID":"toolu_01GT7LXvR4cWPiyeCyVBHtXX","timestamp":"2026-02-26T14:12:13.668Z","uuid":"093a1e25-d4a5-4d04-bbac-1657aa2e257d"} {"parentUuid":"093a1e25-d4a5-4d04-bbac-1657aa2e257d","isSidechain":false,"userType":"external","cwd":"/home/josie/notes","sessionId":"86c1fab3-7cc6-4988-afc5-b6d71f120498","version":"2.1.51","gitBranch":"HEAD","slug":"structured-marinating-quiche","type":"progress","data":{"type":"hook_progress","hookEvent":"PostToolUse","hookName":"PostToolUse:Read","command":"callback"},"parentToolUseID":"toolu_01GT7LXvR4cWPiyeCyVBHtXX","toolUseID":"toolu_01GT7LXvR4cWPiyeCyVBHtXX","timestamp":"2026-02-26T14:12:13.668Z","uuid":"2765212c-facc-473b-8ae8-4782cdd6548d"} {"parentUuid":"d9e4610a-7dad-4442-aa1d-99e35bd848c7","isSidechain":false,"userType":"external","cwd":"/home/josie/notes","sessionId":"86c1fab3-7cc6-4988-afc5-b6d71f120498","version":"2.1.51","gitBranch":"HEAD","slug":"structured-marinating-quiche","type":"user","message":{"role":"user","content":[{"tool_use_id":"toolu_01GT7LXvR4cWPiyeCyVBHtXX","type":"tool_result","content":" 220→ p_dir = f\"/{basename}/\"\n 221→ if p_dir not in known:\n 222→ candidates.add(p_dir)\n 223→ for ext in PROBE_EXTENSIONS:\n 224→ p = f\"/{basename}{ext}\"\n 225→ if p not in known:\n 226→ candidates.add(p)\n 227→\n 228→ semaphore = asyncio.Semaphore(MAX_CONCURRENT)\n 229→ tasks = [probe_path(client, base, path, semaphore) for path in candidates]\n 230→\n 231→ discovered = set()\n 232→ results = await asyncio.gather(*tasks)\n 233→ for result in results:\n 234→ if result is not None:\n 235→ discovered.add(result)\n 236→\n 237→ return discovered\n 238→\n 239→\n 240→async def crawl_discovered_dirs(client: httpx.AsyncClient, base: str, discovered: set[str], known: set[str]) -> set[str]:\n 241→ \"\"\"For any newly discovered directories, crawl their listings too.\"\"\"\n 242→ extra = set()\n 243→ dirs = [p for p in discovered if p.endswith(\"/\")]\n 244→ for d in dirs:\n 245→ sub = await crawl(client, base, d, set())\n 246→ extra.update(sub)\n 247→ return extra\n 248→\n 249→\n 250→async def run(base_url: str, output_file: str | None) -> None:\n 251→ async with httpx.AsyncClient(timeout=10.0) as client:\n 252→ print(f\"Crawling directory listings on {base_url}...\", file=sys.stderr)\n 253→ crawled = await crawl(client, base_url)\n 254→ print(f\" Found {len(crawled)} paths from directory listings\", file=sys.stderr)\n 255→\n 256→ print(\"Probing common paths...\", file=sys.stderr)\n 257→ probed = await brute_force_probe(client, base_url, crawled)\n 258→ print(f\" Discovered {len(probed)} additional paths\", file=sys.stderr)\n 259→\n 260→ print(\"Crawling newly discovered directories...\", file=sys.stderr)\n 261→ extra = await crawl_discovered_dirs(client, base_url, probed, crawled)\n 262→ print(f\" Found {len(extra)} more paths in new directories\", file=sys.stderr)\n 263→\n 264→ all_paths = crawled | probed | extra\n 265→ files = sorted(p for p in all_paths if not p.endswith(\"/\"))\n 266→ dirs = sorted(p for p in all_paths if p.endswith(\"/\"))\n 267→\n 268→ result = {\n 269→ \"base_url\": base_url,\n 270→ \"indexed_at\": datetime.now(timezone.utc).isoformat(),\n 271→ \"total_files\": len(files),\n 272→ \"total_dirs\": len(dirs),\n 273→ \"directories\": dirs,\n 274→ \"files\": files,\n 275→ }\n 276→\n 277→ output = json.dumps(result, indent=2)\n 278→ if output_file:\n 279→ with open(output_file, \"w\") as f:\n 280→ f.write(output)\n 281→ f.write(\"\\n\")\n 282→ print(f\"Wrote index to {output_file}\", file=sys.stderr)\n 283→ else:\n 284→ print(output)\n 285→\n 286→ print(f\"Total: {len(files)} files in {len(dirs)} directories\", file=sys.stderr)\n 287→\n 288→\n 289→def main():\n 290→ parser = argparse.ArgumentParser(description=\"Index all files on cdn.frogg.ie\")\n 291→ parser.add_argument(\"--url\", default=BASE_URL, help=\"Base URL to index (default: %(default)s)\")\n 292→ parser.add_argument(\"-o\", \"--output\", help=\"Output file path (default: stdout)\")\n 293→ parser.add_argument(\"--concurrency\", type=int, default=MAX_CONCURRENT, help=\"Max concurrent requests (default: %(default)s)\")\n 294→ args = parser.parse_args()\n 295→\n 296→ global MAX_CONCURRENT\n 297→ MAX_CONCURRENT = args.concurrency\n 298→\n 299→ asyncio.run(run(args.url, args.output))\n 300→\n 301→\n 302→if __name__ == \"__main__\":\n 303→ main()\n 304→"}]},"uuid":"d623ac8d-327a-4905-81b8-0cda592676f9","timestamp":"2026-02-26T14:12:13.666Z","toolUseResult":{"type":"text","file":{"filePath":"/home/josie/notes/index_cdn_froggie.py","content":" p_dir = f\"/{basename}/\"\n if p_dir not in known:\n candidates.add(p_dir)\n for ext in PROBE_EXTENSIONS:\n p = f\"/{basename}{ext}\"\n if p not in known:\n candidates.add(p)\n\n semaphore = asyncio.Semaphore(MAX_CONCURRENT)\n tasks = [probe_path(client, base, path, semaphore) for path in candidates]\n\n discovered = set()\n results = await asyncio.gather(*tasks)\n for result in results:\n if result is not None:\n discovered.add(result)\n\n return discovered\n\n\nasync def crawl_discovered_dirs(client: httpx.AsyncClient, base: str, discovered: set[str], known: set[str]) -> set[str]:\n \"\"\"For any newly discovered directories, crawl their listings too.\"\"\"\n extra = set()\n dirs = [p for p in discovered if p.endswith(\"/\")]\n for d in dirs:\n sub = await crawl(client, base, d, set())\n extra.update(sub)\n return extra\n\n\nasync def run(base_url: str, output_file: str | None) -> None:\n async with httpx.AsyncClient(timeout=10.0) as client:\n print(f\"Crawling directory listings on {base_url}...\", file=sys.stderr)\n crawled = await crawl(client, base_url)\n print(f\" Found {len(crawled)} paths from directory listings\", file=sys.stderr)\n\n print(\"Probing common paths...\", file=sys.stderr)\n probed = await brute_force_probe(client, base_url, crawled)\n print(f\" Discovered {len(probed)} additional paths\", file=sys.stderr)\n\n print(\"Crawling newly discovered directories...\", file=sys.stderr)\n extra = await crawl_discovered_dirs(client, base_url, probed, crawled)\n print(f\" Found {len(extra)} more paths in new directories\", file=sys.stderr)\n\n all_paths = crawled | probed | extra\n files = sorted(p for p in all_paths if not p.endswith(\"/\"))\n dirs = sorted(p for p in all_paths if p.endswith(\"/\"))\n\n result = {\n \"base_url\": base_url,\n \"indexed_at\": datetime.now(timezone.utc).isoformat(),\n \"total_files\": len(files),\n \"total_dirs\": len(dirs),\n \"directories\": dirs,\n \"files\": files,\n }\n\n output = json.dumps(result, indent=2)\n if output_file:\n with open(output_file, \"w\") as f:\n f.write(output)\n f.write(\"\\n\")\n print(f\"Wrote index to {output_file}\", file=sys.stderr)\n else:\n print(output)\n\n print(f\"Total: {len(files)} files in {len(dirs)} directories\", file=sys.stderr)\n\n\ndef main():\n parser = argparse.ArgumentParser(description=\"Index all files on cdn.frogg.ie\")\n parser.add_argument(\"--url\", default=BASE_URL, help=\"Base URL to index (default: %(default)s)\")\n parser.add_argument(\"-o\", \"--output\", help=\"Output file path (default: stdout)\")\n parser.add_argument(\"--concurrency\", type=int, default=MAX_CONCURRENT, help=\"Max concurrent requests (default: %(default)s)\")\n args = parser.parse_args()\n\n global MAX_CONCURRENT\n MAX_CONCURRENT = args.concurrency\n\n asyncio.run(run(args.url, args.output))\n\n\nif __name__ == \"__main__\":\n main()\n","numLines":85,"startLine":220,"totalLines":304}},"sourceToolAssistantUUID":"d9e4610a-7dad-4442-aa1d-99e35bd848c7"} {"parentUuid":"d623ac8d-327a-4905-81b8-0cda592676f9","isSidechain":false,"userType":"external","cwd":"/home/josie/notes","sessionId":"86c1fab3-7cc6-4988-afc5-b6d71f120498","version":"2.1.51","gitBranch":"HEAD","slug":"structured-marinating-quiche","message":{"model":"claude-opus-4-6","id":"msg_01QfnHWTD6FGYPEmjP3jAxef","type":"message","role":"assistant","content":[{"type":"tool_use","id":"toolu_01Nnjr7Rrar5J7yNBaRz87Lk","name":"Edit","input":{"replace_all":false,"file_path":"/home/josie/notes/index_cdn_froggie.py","old_string":"async def brute_force_probe(client: httpx.AsyncClient, base: str, known: set[str]) -> set[str]:\n \"\"\"Probe for common filenames and basename+extension combos.\"\"\"\n candidates = set()\n\n for name in COMMON_FILENAMES:\n p = f\"/{name}\"\n if p not in known:\n candidates.add(p)\n\n for basename in PROBE_BASENAMES:\n p = f\"/{basename}\"\n if p not in known:\n candidates.add(p)\n p_dir = f\"/{basename}/\"\n if p_dir not in known:\n candidates.add(p_dir)\n for ext in PROBE_EXTENSIONS:\n p = f\"/{basename}{ext}\"\n if p not in known:\n candidates.add(p)\n\n semaphore = asyncio.Semaphore(MAX_CONCURRENT)\n tasks = [probe_path(client, base, path, semaphore) for path in candidates]","new_string":"async def brute_force_probe(client: httpx.AsyncClient, base: str, known: set[str], concurrency: int = 20) -> set[str]:\n \"\"\"Probe for common filenames and basename+extension combos.\"\"\"\n candidates = set()\n\n for name in COMMON_FILENAMES:\n p = f\"/{name}\"\n if p not in known:\n candidates.add(p)\n\n for basename in PROBE_BASENAMES:\n p = f\"/{basename}\"\n if p not in known:\n candidates.add(p)\n p_dir = f\"/{basename}/\"\n if p_dir not in known:\n candidates.add(p_dir)\n for ext in PROBE_EXTENSIONS:\n p = f\"/{basename}{ext}\"\n if p not in known:\n candidates.add(p)\n\n semaphore = asyncio.Semaphore(concurrency)\n tasks = [probe_path(client, base, path, semaphore) for path in candidates]"},"caller":{"type":"direct"}}],"stop_reason":null,"stop_sequence":null,"usage":{"input_tokens":1,"cache_creation_input_tokens":1311,"cache_read_input_tokens":36139,"output_tokens":593,"server_tool_use":{"web_search_requests":0,"web_fetch_requests":0},"service_tier":"standard","cache_creation":{"ephemeral_1h_input_tokens":1311,"ephemeral_5m_input_tokens":0},"inference_geo":"","iterations":[],"speed":"standard"}},"requestId":"req_011CYWpLiY2JiaGQWYEYPpXG","type":"assistant","uuid":"5dfb578c-97c6-4527-889b-3409e109c2a3","timestamp":"2026-02-26T14:12:20.648Z"} {"parentUuid":"5dfb578c-97c6-4527-889b-3409e109c2a3","isSidechain":false,"userType":"external","cwd":"/home/josie/notes","sessionId":"86c1fab3-7cc6-4988-afc5-b6d71f120498","version":"2.1.51","gitBranch":"HEAD","slug":"structured-marinating-quiche","type":"progress","data":{"type":"hook_progress","hookEvent":"PreToolUse","hookName":"PreToolUse:Edit","command":"python3 ${CLAUDE_PLUGIN_ROOT}/hooks/pretooluse.py"},"toolUseID":"toolu_01Nnjr7Rrar5J7yNBaRz87Lk","parentToolUseID":"toolu_01Nnjr7Rrar5J7yNBaRz87Lk","uuid":"a7fc5f57-9ce2-4c0ults:i=1; smtp.subspace.kernel.org; dmarc=fail (p=none dis=none) header.from=lst.de; spf=none smtp.mailfrom=bombadil.srs.infradead.org; dkim=pass (2048-bit key) header.d=infradead.org header.i=@infradead.org header.b=EAxX0MWJ; arc=none smtp.client-ip=198.137.202.133 Authentication-Results: smtp.subspace.kernel.org; dmarc=fail (p=none dis=none) header.from=lst.de Authentication-Results: smtp.subspace.kernel.org; spf=none smtp.mailfrom=bombadil.srs.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=infradead.org; s=bombadil.20210309; h=Content-Transfer-Encoding: MIME-Version:References:In-Reply-To:Message-ID:Date:Subject:Cc:To:From:Sender :Reply-To:Content-Type:Content-ID:Content-Description; bh=ZIOXjuXhndRAAhVng/XDk+LUr70HSW+t14vf2BX5Fos=; b=EAxX0MWJLwxOzvaeUkAIR8eFqm Ux9w9WMFI+Ub23IMkQAsEQeNG6RI3ihr1tTi7OF1POAvpF/zXo4ixNddsRgXuQxhgS9+v19NoQerw PnJMESNcbqZ0VkxYmERMPLMFdkVqwUlFeZKkLbyF6QEPI8o+kXRvWeMu//an1l4jHcQniQKWPE5QA 9sGERDdOIFRzrctGz8HH7xCGIQoOZUCN0fOO9j+Pki7x81y1P9DBlWoYFftarGhk46QglAqt2XVmI c/z4GgufgUUhyScknND6skAIceSYhrf5U9QjOwZnBqzhC92Wo/vXfVJ+t5MYZXlqiPraqZYMIIQUB qauBxtSA==; Received: from [4.28.11.157] (helo=localhost) by bombadil.infradead.org with esmtpsa (Exim 4.98.2 #2 (Red Hat Linux)) id 1vvd1K-00000006Q2T-0dvm; Thu, 26 Feb 2026 15:11:18 +0000 From: Christoph Hellwig To: Andrew Morton Cc: Richard Henderson , Matt Turner , Magnus Lindholm , Russell King , Catalin Marinas , Will Deacon , Huacai Chen , WANG Xuerui , Madhavan Srinivasan , Michael Ellerman , Nicholas Piggin , "Christophe Leroy (CS GROUP)" , Paul Walmsley , Palmer Dabbelt , Albert Ou , Alexandre Ghiti , Heiko Carstens , Vasily Gorbik , Alexander Gordeev , Christian Borntraeger , Sven Schnelle , "David S. Miller" , Andreas Larsson , Richard Weinberger , Anton Ivanov , Johannes Berg , Thomas Gleixner , Ingo Molnar , Borislav Petkov , Dave Hansen , x86@kernel.org, "H. Peter Anvin" , Herbert Xu , Dan Williams , Chris Mason , David Sterba , Arnd Bergmann , Song Liu , Yu Kuai , Li Nan , linux-alpha@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, loongarch@lists.linux.dev, linuxppc-dev@lists.ozlabs.org, linux-riscv@lists.infradead.org, linux-s390@vger.kernel.org, sparclinux@vger.kernel.org, linux-um@lists.infradead.org, linux-crypto@vger.kernel.org, linux-btrfs@vger.kernel.org, linux-arch@vger.kernel.org, linux-raid@vger.kernel.org Subject: [PATCH 08/25] xor: remove macro abuse for XOR implementation registrations Date: Thu, 26 Feb 2026 07:10:20 -0800 Message-ID: <20260226151106.144735-9-hch@lst.de> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20260226151106.144735-1-hch@lst.de> References: <20260226151106.144735-1-hch@lst.de> Precedence: bulk X-Mailing-List: linux-s390@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-SRS-Rewrite: SMTP reverse-path rewritten from by bombadil.infradead.org. See http://www.infradead.org/rpr.html X-DKIM: signer='infradead.org' status='pass' reason='' DKIMCheck: Server passes DKIM test, 0 Spam score X-Spam-Score: 0.5 (/) X-Spam-Report: Spam detection software, running on the system "witcher.mxrouting.net", has performed the tests listed below against this email. Information: https://docs.mxroute.com/docs/expert-spam-filtering.html --- Content analysis details: (0.5 points) --- pts rule name description ---- ---------------------- ----------------------------------------- 0.0 URIBL_BLOCKED ADMINISTRATOR NOTICE: The query to URIBL was blocked. See http://wiki.apache.org/spamassassin/DnsBlocklists#dnsbl-block for more information. [URIs: infradead.org] 0.0 URIBL_DBL_BLOCKED_OPENDNS ADMINISTRATOR NOTICE: The query to dbl.spamhaus.org was blocked due to usage of an open resolver. See https://www.spamhaus.org/returnc/pub/ [URIs: infradead.org] 0.0 RCVD_IN_ZEN_BLOCKED_OPENDNS RBL: ADMINISTRATOR NOTICE: The query to zen.spamhaus.org was blocked due to usage of an open resolver. See https://www.spamhaus.org/returnc/pub/ [172.105.105.114 listed in zen.spamhaus.org] 0.0 URIBL_ZEN_BLOCKED_OPENDNS ADMINISTRATOR NOTICE: The query to zen.spamhaus.org was blocked due to usage of an open resolver. See https://www.spamhaus.org/returnc/pub/ [URIs: infradead.org] 1.5 HEADER_FROM_DIFFERENT_DOMAINS From and EnvelopeFrom 2nd level mail domains are different 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature -1.0 MAILING_LIST_MULTI Multiple indicators imply a widely-seen list manager SpamTally: Final spam score: 5 Drop the pretty confusing historic XOR_TRY_TEMPLATES and XOR_SELECT_TEMPLATE, and instead let the architectures provide a arch_xor_init that calls either xor_register to register candidates or xor_force to force a specific implementation. Signed-off-by: Christoph Hellwig --- arch/alpha/include/asm/xor.h | 29 ++++++++++++---------- arch/arm/include/asm/xor.h | 25 +++++++++---------- arch/arm64/include/asm/xor.h | 18 +++++++------- arch/loongarch/include/asm/xor.h | 42 ++++++++++++-------------------- arch/powerpc/include/asm/xor.h | 31 ++++++++++------------- arch/riscv/include/asm/xor.h | 19 ++++++++------- arch/s390/include/asm/xor.h | 12 ++++----- arch/sparc/include/asm/xor_32.h | 14 +++++------ arch/sparc/include/asm/xor_64.h | 31 +++++++++++------------ arch/x86/include/asm/xor.h | 3 --- arch/x86/include/asm/xor_32.h | 36 ++++++++++++++------------- arch/x86/include/asm/xor_64.h | 18 ++++++++------ arch/x86/include/asm/xor_avx.h | 9 ------- include/asm-generic/xor.h | 8 ------ include/linux/raid/xor_impl.h | 5 ++++ lib/raid/xor/xor-core.c | 41 +++++++++++++++++++++++-------- 16 files changed, 168 insertions(+), 173 deletions(-) diff --git a/arch/alpha/include/asm/xor.h b/arch/alpha/include/asm/xor.h index e0de0c233ab9..4c8085711df1 100644 --- a/arch/alpha/include/asm/xor.h +++ b/arch/alpha/include/asm/xor.h @@ -851,16 +851,19 @@ static struct xor_block_template xor_block_alpha_prefetch = { /* For grins, also test the generic routines. */ #include -#undef XOR_TRY_TEMPLATES -#define XOR_TRY_TEMPLATES \ - do { \ - xor_speed(&xor_block_8regs); \ - xor_speed(&xor_block_32regs); \ - xor_speed(&xor_block_alpha); \ - xor_speed(&xor_block_alpha_prefetch); \ - } while (0) - -/* Force the use of alpha_prefetch if EV6, as it is significantly - faster in the cold cache case. */ -#define XOR_SELECT_TEMPLATE(FASTEST) \ - (implver() == IMPLVER_EV6 ? &xor_block_alpha_prefetch : FASTEST) +/* + * Force the use of alpha_prefetch if EV6, as it is significantly faster in the + * cold cache case. + */ +#define arch_xor_init arch_xor_init +static __always_inline void __init arch_xor_init(void) +{ + if (implver() == IMPLVER_EV6) { + xor_force(&xor_block_alpha_prefetch); + } else { + xor_register(&xor_block_8regs); + xor_register(&xor_block_32regs); + xor_register(&xor_block_alpha); + xor_register(&xor_block_alpha_prefetch); + } +} diff --git a/arch/arm/include/asm/xor.h b/arch/arm/include/asm/xor.h index bca2a6514746..b2dcd49186e2 100644 --- a/arch/arm/include/asm/xor.h +++ b/arch/arm/include/asm/xor.h @@ -138,15 +138,6 @@ static struct xor_block_template xor_block_arm4regs = { .do_5 = xor_arm4regs_5, }; -#undef XOR_TRY_TEMPLATES -#define XOR_TRY_TEMPLATES \ - do { \ - xor_speed(&xor_block_arm4regs); \ - xor_speed(&xor_block_8regs); \ - xor_speed(&xor_block_32regs); \ - NEON_TEMPLATES; \ - } while (0) - #ifdef CONFIG_KERNEL_MODE_NEON extern struct xor_block_template const xor_block_neon_inner; @@ -201,8 +192,16 @@ static struct xor_block_template xor_block_neon = { .do_5 = xor_neon_5 }; -#define NEON_TEMPLATES \ - do { if (cpu_has_neon()) xor_speed(&xor_block_neon); } while (0) -#else -#define NEON_TEMPLATES +#endif /* CONFIG_KERNEL_MODE_NEON */ + +#define arch_xor_init arch_xor_init +static __always_inline void __init arch_xor_init(void) +{ + xor_register(&xor_block_arm4regs); + xor_register(&xor_block_8regs); + xor_register(&xor_block_32regs); +#ifdef CONFIG_KERNEL_MODE_NEON + if (cpu_has_neon()) + xor_register(&xor_block_neon); #endif +} diff --git a/arch/arm64/include/asm/xor.h b/arch/arm64/include/asm/xor.h index c38e3d017a79..bfa6122f55ce 100644 --- a/arch/arm64/include/asm/xor.h +++ b/arch/arm64/include/asm/xor.h @@ -60,14 +60,14 @@ static struct xor_block_template xor_block_arm64 = { .do_4 = xor_neon_4, .do_5 = xor_neon_5 }; -#undef XOR_TRY_TEMPLATES -#define XOR_TRY_TEMPLATES \ - do { \ - xor_speed(&xor_block_8regs); \ - xor_speed(&xor_block_32regs); \ - if (cpu_has_neon()) { \ - xor_speed(&xor_block_arm64);\ - } \ - } while (0) + +#define arch_xor_init arch_xor_init +static __always_inline void __init arch_xor_init(void) +{ + xor_register(&xor_block_8regs); + xor_register(&xor_block_32regs); + if (cpu_has_neon()) + xor_register(&xor_block_arm64); +} #endif /* ! CONFIG_KERNEL_MODE_NEON */ diff --git a/arch/loongarch/include/asm/xor.h b/arch/loongarch/include/asm/xor.h index 12467fffee46..d17c0e3b047f 100644 --- a/arch/loongarch/include/asm/xor.h +++ b/arch/loongarch/include/asm/xor.h @@ -16,14 +16,6 @@ static struct xor_block_template xor_block_lsx = { .do_4 = xor_lsx_4, .do_5 = xor_lsx_5, }; - -#define XOR_SPEED_LSX() \ - do { \ - if (cpu_has_lsx) \ - xor_speed(&xor_block_lsx); \ - } while (0) -#else /* CONFIG_CPU_HAS_LSX */ -#define XOR_SPEED_LSX() #endif /* CONFIG_CPU_HAS_LSX */ #ifdef CONFIG_CPU_HAS_LASX @@ -34,14 +26,6 @@ static struct xor_block_template xor_block_lasx = { .do_4 = xor_lasx_4, .do_5 = xor_lasx_5, }; - -#define XOR_SPEED_LASX() \ - do { \ - if (cpu_has_lasx) \ - xor_speed(&xor_block_lasx); \ - } while (0) -#else /* CONFIG_CPU_HAS_LASX */ -#define XOR_SPEED_LASX() #endif /* CONFIG_CPU_HAS_LASX */ /* @@ -54,15 +38,21 @@ static struct xor_block_template xor_block_lasx = { */ #include -#undef XOR_TRY_TEMPLATES -#define XOR_TRY_TEMPLATES \ -do { \ - xor_speed(&xor_block_8regs); \ - xor_speed(&xor_block_8regs_p); \ - xor_speed(&xor_block_32regs); \ - xor_speed(&xor_block_32regs_p); \ - XOR_SPEED_LSX(); \ - XOR_SPEED_LASX(); \ -} while (0) +#define arch_xor_init arch_xor_init +static __always_inline void __init arch_xor_init(void) +{ + xor_register(&xor_block_8regs); + xor_register(&xor_block_8regs_p); + xor_register(&xor_block_32regs); + xor_register(&xor_block_32regs_p); +#ifdef CONFIG_CPU_HAS_LSX + if (cpu_has_lsx) + xor_register(&xor_block_lsx); +#endif +#ifdef CONFIG_CPU_HAS_LASX + if (cpu_has_lasx) + xor_register(&xor_block_lasx); +#endif +} #endif /* _ASM_LOONGARCH_XOR_H */ diff --git a/arch/powerpc/include/asm/xor.h b/arch/powerpc/include/asm/xor.h index 37d05c11d09c..30224c5279c4 100644 --- a/arch/powerpc/include/asm/xor.h +++ b/arch/powerpc/include/asm/xor.h @@ -21,27 +21,22 @@ static struct xor_block_template xor_block_altivec = { .do_4 = xor_altivec_4, .do_5 = xor_altivec_5, }; - -#define XOR_SPEED_ALTIVEC() \ - do { \ - if (cpu_has_feature(CPU_FTR_ALTIVEC)) \ - xor_speed(&xor_block_altivec); \ - } while (0) -#else -#define XOR_SPEED_ALTIVEC() -#endif +#endif /* CONFIG_ALTIVEC */ /* Also try the generic routines. */ #include -#undef XOR_TRY_TEMPLATES -#define XOR_TRY_TEMPLATES \ -do { \ - xor_speed(&xor_block_8regs); \ - xor_speed(&xor_block_8regs_p); \ - xor_speed(&xor_block_32regs); \ - xor_speed(&xor_block_32regs_p); \ - XOR_SPEED_ALTIVEC(); \ -} while (0) +#define arch_xor_init arch_xor_init +static __always_inline void __init arch_xor_init(void) +{ + xor_register(&xor_block_8regs); + xor_register(&xor_block_8regs_p); + xor_register(&xor_block_32regs); + xor_register(&xor_block_32regs_p); +#ifdef CONFIG_ALTIVEC + if (cpu_has_feature(CPU_FTR_ALTIVEC)) + xor_register(&xor_block_altivec); +#endif +} #endif /* _ASM_POWERPC_XOR_H */ diff --git a/arch/riscv/include/asm/xor.h b/arch/riscv/include/asm/xor.h index 96011861e46b..ed5f27903efc 100644 --- a/arch/riscv/include/asm/xor.h +++ b/arch/riscv/include/asm/xor.h @@ -55,14 +55,15 @@ static struct xor_block_template xor_block_rvv = { .do_4 = xor_vector_4, .do_5 = xor_vector_5 }; +#endif /* CONFIG_RISCV_ISA_V */ -#undef XOR_TRY_TEMPLATES -#define XOR_TRY_TEMPLATES \ - do { \ - xor_speed(&xor_block_8regs); \ - xor_speed(&xor_block_32regs); \ - if (has_vector()) { \ - xor_speed(&xor_block_rvv);\ - } \ - } while (0) +#define arch_xor_init arch_xor_init +static __always_inline void __init arch_xor_init(void) +{ + xor_register(&xor_block_8regs); + xor_register(&xor_block_32regs); +#ifdef CONFIG_RISCV_ISA_V + if (has_vector()) + xor_register(&xor_block_rvv); #endif +} diff --git a/arch/s390/include/asm/xor.h b/arch/s390/include/asm/xor.h index 857d6759b67f..4e2233f64da9 100644 --- a/arch/s390/include/asm/xor.h +++ b/arch/s390/include/asm/xor.h @@ -10,12 +10,10 @@ extern struct xor_block_template xor_block_xc; -#undef XOR_TRY_TEMPLATES -#define XOR_TRY_TEMPLATES \ -do { \ - xor_speed(&xor_block_xc); \ -} while (0) - -#define XOR_SELECT_TEMPLATE(FASTEST) (&xor_block_xc) +#define arch_xor_init arch_xor_init +static __always_inline void __init arch_xor_init(void) +{ + xor_force(&xor_block_xc); +} #endif /* _ASM_S390_XOR_H */ diff --git a/arch/sparc/include/asm/xor_32.h b/arch/sparc/include/asm/xor_32.h index 0351813cf3af..8fbf0c07ec28 100644 --- a/arch/sparc/include/asm/xor_32.h +++ b/arch/sparc/include/asm/xor_32.h @@ -259,10 +259,10 @@ static struct xor_block_template xor_block_SPARC = { /* For grins, also test the generic routines. */ #include -#undef XOR_TRY_TEMPLATES -#define XOR_TRY_TEMPLATES \ - do { \ - xor_speed(&xor_block_8regs); \ - xor_speed(&xor_block_32regs); \ - xor_speed(&xor_block_SPARC); \ - } while (0) +#define arch_xor_init arch_xor_init +static __always_inline void __init arch_xor_init(void) +{ + xor_register(&xor_block_8regs); + xor_register(&xor_block_32regs); + xor_register(&xor_block_SPARC); +} diff --git a/arch/sparc/include/asm/xor_64.h b/arch/sparc/include/asm/xor_64.h index caaddea8ad79..e0482ecc0a68 100644 --- a/arch/sparc/include/asm/xor_64.h +++ b/arch/sparc/include/asm/xor_64.h @@ -60,20 +60,17 @@ static struct xor_block_template xor_block_niagara = { .do_5 = xor_niagara_5, }; -#undef XOR_TRY_TEMPLATES -#define XOR_TRY_TEMPLATES \ - do { \ - xor_speed(&xor_block_VIS); \ - xor_speed(&xor_block_niagara); \ - } while (0) - -/* For VIS for everything except Niagara. */ -#define XOR_SELECT_TEMPLATE(FASTEST) \ - ((tlb_type == hypervisor && \ - (sun4v_chip_type == SUN4V_CHIP_NIAGARA1 || \ - sun4v_chip_type == SUN4V_CHIP_NIAGARA2 || \ - sun4v_chip_type == SUN4V_CHIP_NIAGARA3 || \ - sun4v_chip_type == SUN4V_CHIP_NIAGARA4 || \ - sun4v_chip_type == SUN4V_CHIP_NIAGARA5)) ? \ - &xor_block_niagara : \ - &xor_block_VIS) +#define arch_xor_init arch_xor_init +static __always_inline void __init arch_xor_init(void) +{ + /* Force VIS for everything except Niagara. */ + if (tlb_type == hypervisor && + (sun4v_chip_type == SUN4V_CHIP_NIAGARA1 || + sun4v_chip_type == SUN4V_CHIP_NIAGARA2 || + sun4v_chip_type == SUN4V_CHIP_NIAGARA3 || + sun4v_chip_type == SUN4V_CHIP_NIAGARA4 || + sun4v_chip_type == SUN4V_CHIP_NIAGARA5)) + xor_force(&xor_block_niagara); + else + xor_force(&xor_block_VIS); +} diff --git a/arch/x86/include/asm/xor.h b/arch/x86/include/asm/xor.h index 7b0307acc410..33f5620d8d69 100644 --- a/arch/x86/include/asm/xor.h +++ b/arch/x86/include/asm/xor.h @@ -496,7 +496,4 @@ static struct xor_block_template xor_block_sse_pf64 = { # include #endif -#define XOR_SELECT_TEMPLATE(FASTEST) \ - AVX_SELECT(FASTEST) - #endif /* _ASM_X86_XOR_H */ diff --git a/arch/x86/include/asm/xor_32.h b/arch/x86/include/asm/xor_32.h index 7a6b9474591e..ee32d08c27bc 100644 --- a/arch/x86/include/asm/xor_32.h +++ b/arch/x86/include/asm/xor_32.h @@ -552,22 +552,24 @@ static struct xor_block_template xor_block_pIII_sse = { /* We force the use of the SSE xor block because it can write around L2. We may also be able to load into the L1 only depending on how the cpu deals with a load to a line that is being prefetched. */ -#undef XOR_TRY_TEMPLATES -#define XOR_TRY_TEMPLATES \ -do { \ - AVX_XOR_SPEED; \ - if (boot_cpu_has(X86_FEATURE_XMM)) { \ - xor_speed(&xor_block_pIII_sse); \ - xor_speed(&xor_block_sse_pf64); \ - } else if (boot_cpu_has(X86_FEATURE_MMX)) { \ - xor_speed(&xor_block_pII_mmx); \ - xor_speed(&xor_block_p5_mmx); \ - } else { \ - xor_speed(&xor_block_8regs); \ - xor_speed(&xor_block_8regs_p); \ - xor_speed(&xor_block_32regs); \ - xor_speed(&xor_block_32regs_p); \ - } \ -} while (0) +#define arch_xor_init arch_xor_init +static __always_inline void __init arch_xor_init(void) +{ + if (boot_cpu_has(X86_FEATURE_AVX) && + boot_cpu_has(X86_FEATURE_OSXSAVE)) { + xor_force(&xor_block_avx); + } else if (boot_cpu_has(X86_FEATURE_XMM)) { + xor_register(&xor_block_pIII_sse); + xor_register(&xor_block_sse_pf64); + } else if (boot_cpu_has(X86_FEATURE_MMX)) { + xor_register(&xor_block_pII_mmx); + xor_register(&xor_block_p5_mmx); + } else { + xor_register(&xor_block_8regs); + xor_register(&xor_block_8regs_p); + xor_register(&xor_block_32regs); + xor_register(&xor_block_32regs_p); + } +} #endif /* _ASM_X86_XOR_32_H */ diff --git a/arch/x86/include/asm/xor_64.h b/arch/x86/include/asm/xor_64.h index 0307e4ec5044..2d2ceb241866 100644 --- a/arch/x86/include/asm/xor_64.h +++ b/arch/x86/include/asm/xor_64.h @@ -17,12 +17,16 @@ static struct xor_block_template xor_block_sse = { /* We force the use of the SSE xor block because it can write around L2. We may also be able to load into the L1 only depending on how the cpu deals with a load to a line that is being prefetched. */ -#undef XOR_TRY_TEMPLATES -#define XOR_TRY_TEMPLATES \ -do { \ - AVX_XOR_SPEED; \ - xor_speed(&xor_block_sse_pf64); \ - xor_speed(&xor_block_sse); \ -} while (0) +#define arch_xor_init arch_xor_init +static __always_inline void __init arch_xor_init(void) +{ + if (boot_cpu_has(X86_FEATURE_AVX) && + boot_cpu_has(X86_FEATURE_OSXSAVE)) { + xor_force(&xor_block_avx); + } else { + xor_register(&xor_block_sse_pf64); + xor_register(&xor_block_sse); + } +} #endif /* _ASM_X86_XOR_64_H */ diff --git a/arch/x86/include/asm/xor_avx.h b/arch/x86/include/asm/xor_avx.h index 7f81dd5897f4..c600888436bb 100644 --- a/arch/x86/include/asm/xor_avx.h +++ b/arch/x86/include/asm/xor_avx.h @@ -166,13 +166,4 @@ static struct xor_block_template xor_block_avx = { .do_5 = xor_avx_5, }; -#define AVX_XOR_SPEED \ -do { \ - if (boot_cpu_has(X86_FEATURE_AVX) && boot_cpu_has(X86_FEATURE_OSXSAVE)) \ - xor_speed(&xor_block_avx); \ -} while (0) - -#define AVX_SELECT(FASTEST) \ - (boot_cpu_has(X86_FEATURE_AVX) && boot_cpu_has(X86_FEATURE_OSXSAVE) ? &xor_block_avx : FASTEST) - #endif diff --git a/include/asm-generic/xor.h b/include/asm-generic/xor.h index 44509d48fca2..79c0096aa9d9 100644 --- a/include/asm-generic/xor.h +++ b/include/asm-generic/xor.h @@ -728,11 +728,3 @@ static struct xor_block_template xor_block_32regs_p __maybe_unused = { .do_4 = xor_32regs_p_4, .do_5 = xor_32regs_p_5, }; - -#define XOR_TRY_TEMPLATES \ - do { \ - xor_speed(&xor_block_8regs); \ - xor_speed(&xor_block_8regs_p); \ - xor_speed(&xor_block_32regs); \ - xor_speed(&xor_block_32regs_p); \ - } while (0) diff --git a/include/linux/raid/xor_impl.h b/include/linux/raid/xor_impl.h index a1890cd66812..6ed4c445ab24 100644 --- a/include/linux/raid/xor_impl.h +++ b/include/linux/raid/xor_impl.h @@ -2,6 +2,8 @@ #ifndef _XOR_IMPL_H #define _XOR_IMPL_H +#include + struct xor_block_template { struct xor_block_template *next; const char *name; @@ -22,4 +24,7 @@ struct xor_block_template { const unsigned long * __restrict); }; +void __init xor_register(struct xor_block_template *tmpl); +void __init xor_force(struct xor_block_template *tmpl); + #endif /* _XOR_IMPL_H */ diff --git a/lib/raid/xor/xor-core.c b/lib/raid/xor/xor-core.c index ddb39dca1026..3b53c70ba615 100644 --- a/lib/raid/xor/xor-core.c +++ b/lib/raid/xor/xor-core.c @@ -14,10 +14,6 @@ #include #include -#ifndef XOR_SELECT_TEMPLATE -#define XOR_SELECT_TEMPLATE(x) (x) -#endif - /* The xor routines to use. */ static struct xor_block_template *active_template; @@ -55,12 +51,33 @@ EXPORT_SYMBOL(xor_blocks); static struct xor_block_template *__initdata template_list; static int __initdata xor_forced = false; -static void __init do_xor_register(struct xor_block_template *tmpl) +/** + * xor_register - register a XOR template + * @tmpl: template to register + * + * Register a XOR implementation with the core. Registered implementations + * will be measured by a trivial benchmark, and the fastest one is chosen + * unless an implementation is forced using xor_force(). + */ +void __init xor_register(struct xor_block_template *tmpl) { tmpl->next = template_list; template_list = tmpl; } +/** + * xor_force - force use of a XOR template + * @tmpl: template to register + * + * Register a XOR implementation with the core and force using it. Forcing + * an implementation will make the core ignore any template registered using + * xor_register(), or any previous implementation forced using xor_force(). + */ +void __init xor_force(struct xor_block_template *tmpl) +{ + active_template = tmpl; +} + #define BENCH_SIZE 4096 #define REPS 800U @@ -126,11 +143,19 @@ static int __init calibrate_xor_blocks(void) static int __init xor_init(void) { +#ifdef arch_xor_init + arch_xor_init(); +#else + xor_register(&xor_block_8regs); + xor_register(&xor_block_8regs_p); + xor_register(&xor_block_32regs); + xor_register(&xor_block_32regs_p); +#endif + /* * If this arch/cpu has a short-circuited selection, don't loop through * all the possible functions, just use the best one. */ - active_template = XOR_SELECT_TEMPLATE(NULL); if (active_template) { pr_info("xor: automatically using best checksumming function %-10s\n", active_template->name); @@ -138,10 +163,6 @@ static int __init xor_init(void) return 0; } -#define xor_speed do_xor_register - XOR_TRY_TEMPLATES; -#undef xor_speed - #ifdef MODULE return calibrate_xor_blocks(); #else -- 2.47.3 From - Thu Feb 26 15:21:01 2026 X-Mozilla-Status: 0001 X-Mozilla-Status2: 00000000 Return-Path: Delivered-To: hi@josie.lol Received: from witcher.mxrouting.net by witcher.mxrouting.net with LMTP id MKISG9hkoGkfoDgAYBR5ng (envelope-from ) for ; Thu, 26 Feb 2026 15:20:56 +0000 Return-path: Envelope-to: hi@josie.lol Delivery-date: Thu, 26 Feb 2026 15:20:56 +0000 Received: from sea.lore.kernel.org ([172.234.253.10]) by witcher.mxrouting.net with esmtps (TLS1.3) tls TLS_AES_256_GCM_SHA384 (Exim 4.98) (envelope-from ) id 1vvdAe-0000000G4zb-0k3f for hi@josie.lol; Thu, 26 Feb 2026 15:20:56 +0000 Received: from smtp.subspace.kernel.org (conduit.subspace.kernel.org [100.90.174.1]) by sea.lore.kernel.org (Postfix) with ESMTP id 361A431C3F09 for ; Thu, 26 Feb 2026 15:13:39 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id CE5E440756D; Thu, 26 Feb 2026 15:11:52 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=infradead.org header.i=@infradead.org header.b="UWlx2aQX" X-Original-To: linux-s390@vger.kernel.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C981A3ED12B; Thu, 26 Feb 2026 15:11:48 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.137.202.133 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772118712; cv=none; b=r2TpLsR4vCxyMEew2nBCpRstKMbWNP2cWaTMlLorRE88KoaaM1blx7vGGQXZ+nTcFo4jwtjhX6p3pl0V+2HkX1jwuk0+o4WV48REcfJm6lr701aPAd6KEC4qb709UHtd4MNheyjmRM5jcXJvUupLXHOGJdconLLj+QleZzNAMTw= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772118712; c=relaxed/simple; bh=jUtVm1Rf7JOGz4LmP8y/DP4SURG9c7LcQziH6LkHkZw=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=utVBw7TRhHS8Nw5Ay74aqX7gSAkzRPY+wKyATxwudZJeUoL0D/P4jY181TGlBLrHRnLtrgfumRO0FJ9lTPle5didMzeXQHeF7zTr/JK0iByA6N9LCs54ugHLfWlc+Way5VaRWTAfOTtEDJ60ukB1ZusaxmKxyZ+qJl/dasZZSqA= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=fail (p=none dis=none) header.from=lst.de; spf=none smtp.mailfrom=bombadil.srs.infradead.org; dkim=pass (2048-bit key) header.d=infradead.org header.i=@infradead.org header.b=UWlx2aQX; arc=none smtp.client-ip=198.137.202.133 Authentication-Results: smtp.subspace.kernel.org; dmarc=fail (p=none dis=none) header.from=lst.de Authentication-Results: smtp.subspace.kernel.org; spf=none smtp.mailfrom=bombadil.srs.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=infradead.org; s=bombadil.20210309; h=Content-Transfer-Encoding: MIME-Version:References:In-Reply-To:Message-ID:Date:Subject:Cc:To:From:Sender :Reply-To:Content-Type:Content-ID:Content-Description; bh=8SFAAXJP1oJfa/3lZX/8e4dND94zooHILcdc+qXS2PE=; b=UWlx2aQX7+I5jhBsL1ur96gEDD F1ApAr+kLKJJXFWZ8yGweCxQnqnlRFj8YYYWcsPkhsA55s0l4a9adlrUHJnSOJ1KmF7w/iqybktB+ SAiSzTUqnUoNLrkfktxBv6U6bDYHYCexRKVLVn3VyhGXRSC6pA43Mt2Yp62xCGaUwdvIszrjlz1fd M/N9kS7v7H/vFSRk0hXqEI/NXjCGKUg5N6UNXchlbtSCwpm/wq+Gc7kxFinGZ4QIJg7/W1/BPb8N1 pQu7+Iswt2inOesa11lKpYDfB1QcN5cNL4R72idHXrYlZubhGMLq3yBo59JEyhOZGmM6+3UHmbEId uqPGcxMQ==; Received: from [4.28.11.157] (helo=localhost) by bombadil.infradead.org with esmtpsa (Exim 4.98.2 #2 (Red Hat Linux)) id 1vvd1D-00000006PyK-4AqV; Thu, 26 Feb 2026 15:11:12 +0000 From: Christoph Hellwig To: Andrew Morton Cc: Richard Henderson , Matt Turner , Magnus Lindholm , Russell King , Catalin Marinas , Will Deacon , Huacai Chen , WANG Xuerui , Madhavan Srinivasan , Michael Ellerman , Nicholas Piggin , "Christophe Leroy (CS GROUP)" , Paul Walmsley , Palmer Dabbelt , Albert Ou , Alexandre Ghiti , Heiko Carstens , Vasily Gorbik , Alexander Gordeev , Christian Borntraeger , Sven Schnelle , "David S. Miller" , Andreas Larsson , Richard Weinberger , Anton Ivanov , Johannes Berg , Thomas Gleixner , Ingo Molnar , Borislav Petkov , Dave Hansen , x86@kernel.org, "H. Peter Anvin" , Herbert Xu , Dan Williams , Chris Mason , David Sterba , Arnd Bergmann , Song Liu , Yu Kuai , Li Nan , linux-alpha@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, loongarch@lists.linux.dev, linuxppc-dev@lists.ozlabs.org, linux-riscv@lists.infradead.org, linux-s390@vger.kernel.org, sparclinux@vger.kernel.org, linux-um@lists.infradead.org, linux-crypto@vger.kernel.org, linux-btrfs@vger.kernel.org, linux-arch@vger.kernel.org, linux-raid@vger.kernel.org Subject: [PATCH 03/25] um/xor: don't override XOR_SELECT_TEMPLATE Date: Thu, 26 Feb 2026 07:10:15 -0800 Message-ID: <20260226151106.144735-4-hch@lst.de> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20260226151106.144735-1-hch@lst.de> References: <20260226151106.144735-1-hch@lst.de> Precedence: bulk X-Mailing-List: linux-s390@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-SRS-Rewrite: SMTP reverse-path rewritten from by bombadil.infradead.org. See http://www.infradead.org/rpr.html X-DKIM: signer='infradead.org' status='pass' reason='' DKIMCheck: Server passes DKIM test, 0 Spam score X-Spam-Score: 0.5 (/) X-Spam-Report: Spam detection software, running on the system "witcher.mxrouting.net", has performed the tests listed below against this email. Information: https://docs.mxroute.com/docs/expert-spam-filtering.html --- Content analysis details: (0.5 points) --- pts rule name description ---- ---------------------- ----------------------------------------- 0.0 URIBL_BLOCKED ADMINISTRATOR NOTICE: The query to URIBL was blocked. See http://wiki.apache.org/spamassassin/DnsBlocklists#dnsbl-block for more information. [URIs: infradead.org] 0.0 URIBL_DBL_BLOCKED_OPENDNS ADMINISTRATOR NOTICE: The query to dbl.spamhaus.org was blocked due to usage of an open resolver. See https://www.spamhaus.org/returnc/pub/ [URIs: infradead.org] 0.0 RCVD_IN_ZEN_BLOCKED_OPENDNS RBL: ADMINISTRATOR NOTICE: The query to zen.spamhaus.org was blocked due to usage of an open resolver. See https://www.spamhaus.org/returnc/pub/ [172.234.253.10 listed in zen.spamhaus.org] 0.0 RCVD_IN_DNSWL_BLOCKED RBL: ADMINISTRATOR NOTICE: The query to DNSWL was blocked. See http://wiki.apache.org/spamassassin/DnsBlocklists#DnsBlocklists-dnsbl-block for more information. [172.234.253.10 listed in list.dnswl.org] 0.0 URIBL_ZEN_BLOCKED_OPENDNS ADMINISTRATOR NOTICE: The query to zen.spamhaus.org was blocked due to usage of an open resolver. See https://www.spamhaus.org/returnc/pub/ [URIs: infradead.org] 1.5 HEADER_FROM_DIFFERENT_DOMAINS From and EnvelopeFrom 2nd level mail domains are different 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature -1.0 MAILING_LIST_MULTI Multiple indicators imply a widely-seen list manager SpamTally: Final spam score: 5 XOR_SELECT_TEMPLATE is only ever called with a NULL argument, so all the ifdef'ery doesn't do anything. With our without this, the time travel mode should work fine on CPUs that support AVX2, as the AVX2 implementation is forced in this case, and won't work otherwise. Signed-off-by: Christoph Hellwig --- arch/um/include/asm/xor.h | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/arch/um/include/asm/xor.h b/arch/um/include/asm/xor.h index 647fae200c5d..c9ddedc19301 100644 --- a/arch/um/include/asm/xor.h +++ b/arch/um/include/asm/xor.h @@ -4,21 +4,11 @@ #ifdef CONFIG_64BIT #undef CONFIG_X86_32 -#define TT_CPU_INF_XOR_DEFAULT (AVX_SELECT(&xor_block_sse_pf64)) #else #define CONFIG_X86_32 1 -#define TT_CPU_INF_XOR_DEFAULT (AVX_SELECT(&xor_block_8regs)) #endif #include #include <../../x86/include/asm/xor.h> -#include - -#ifdef CONFIG_UML_TIME_TRAVEL_SUPPORT -#undef XOR_SELECT_TEMPLATE -/* pick an arbitrary one - measuring isn't possible with inf-cpu */ -#define XOR_SELECT_TEMPLATE(x) \ - (time_travel_mode == TT_MODE_INFCPU ? TT_CPU_INF_XOR_DEFAULT : x) -#endif #endif -- 2.47.3 From - Thu Feb 26 15:21:55 2026 X-Mozilla-Status: 0001 X-Mozilla-Status2: 00000000 Return-Path: Delivered-To: hi@josie.lol Received: from witcher.mxrouting.net by witcher.mxrouting.net with LMTP id QIfJKA5loGnFfDoAYBR5ng (envelope-from ) for ; Thu, 26 Feb 2026 15:21:50 +0000 Return-path: Envelope-to: hi@josie.lol Delivery-date: Thu, 26 Feb 2026 15:21:50 +0000 Received: from sea.lore.kernel.org ([172.234.253.10]) by witcher.mxrouting.net with esmtps (TLS1.3) tls TLS_AES_256_GCM_SHA384 (Exim 4.98) (envelope-from ) id 1vvdBV-0000000G7h4-0ujJ for hi@josie.lol; Thu, 26 Feb 2026 15:21:50 +0000 Received: from smtp.subspace.kernel.org (conduit.subspace.kernel.org [100.90.174.1]) by sea.lore.kernel.org (Postfix) with ESMTP id AD7E731D4A44 for ; Thu, 26 Feb 2026 15:14:09 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 5999440B6F1; Thu, 26 Feb 2026 15:11:56 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=infradead.org header.