[PROOF CHECKLIST]
1. Claim -> Evidence line -> Pass/Fail.
2. Reproduction command list.
3. Counterexample path.
4. Closure check: no orphan claim.
[PRIMARY REPORT LINKS]
- [user_trigger_raw_openat_trace_report.md](https://github.com/raikrahul/what-happens-when-open-is-called/blob/main/kernel/user/stage3/case17_do_filp_open_deep_trace/reports/user_trigger_raw_openat_trace_report.md)
- [user_trigger_trace_report.md](https://github.com/raikrahul/what-happens-when-open-is-called/blob/main/kernel/user/stage3/case17_do_filp_open_deep_trace/reports/user_trigger_trace_report.md)
[PRIMARY DMESG LINKS]
- [user_trigger_dmesg.txt](https://github.com/raikrahul/what-happens-when-open-is-called/blob/main/kernel/user/stage3/case17_do_filp_open_deep_trace/reports/user_trigger_dmesg.txt)
- [user_trigger_raw_openat_dmesg.txt](https://github.com/raikrahul/what-happens-when-open-is-called/blob/main/kernel/user/stage3/case17_do_filp_open_deep_trace/reports/user_trigger_raw_openat_dmesg.txt)
[SECONDARY PROOF INPUTS]
- worksheet index: [STAGE3_WORKSHEET_INDEX](https://github.com/raikrahul/what-happens-when-open-is-called/blob/main/kernel/user/stage3/planning/STAGE3_WORKSHEET_INDEX.md)
- axiom index: [STAGE3_AXIOM_WORKSHEET_INDEX](https://github.com/raikrahul/what-happens-when-open-is-called/blob/main/kernel/user/stage3/planning/STAGE3_AXIOM_WORKSHEET_INDEX.md)
- hard index: [STAGE3_AXIOM_HARD_WORKSHEET_INDEX](https://github.com/raikrahul/what-happens-when-open-is-called/blob/main/kernel/user/stage3/planning/STAGE3_AXIOM_HARD_WORKSHEET_INDEX.md)
<!-- AUTO-EMBED START -->
[AUTO] case=case17
[USERDIR] kernel/user/stage3/case17_do_filp_open_deep_trace
================================================================================
[EMBED] user_trigger_raw_openat_trace_report.md
[SOURCE] kernel/user/stage3/case17_do_filp_open_deep_trace/reports/user_trigger_raw_openat_trace_report.md
================================================================================
# Trace Report: user_trigger_raw_openat.S
- Userspace source: `kernel/user/stage3/case17_do_filp_open_deep_trace/user_trigger_raw_openat.S`
- Driver source: `kernel/drivers/stage3/case17_do_filp_open_deep_trace/trace_user_trigger_raw_openat/trace_user_trigger_raw_openat.c`
- Module: `trace_user_trigger_raw_openat`
- Binary: `kernel/user/stage3/case17_do_filp_open_deep_trace/openat_raw`
- Run timestamp: `2026-02-15T23:32:18`
- Final status: `pass_probe_hits`
## Probe Counts
- do_filp_open.entry: 1
- do_filp_open.ret: 1
- __d_alloc.entry: 0
- __d_alloc.ret: 0
## Return Signature Counts
- ERR_PTR(-ENOENT) observed (fffffffffffffffe): 1
- Non-error pointer returns observed: 0
## Commands
make -C kernel/drivers/stage3/case17_do_filp_open_deep_trace/trace_user_trigger_raw_openat
kernel/user/stage3/case17_do_filp_open_deep_trace/openat_raw
sudo dmesg -C
sudo insmod kernel/drivers/stage3/case17_do_filp_open_deep_trace/trace_user_trigger_raw_openat/trace_user_trigger_raw_openat.ko target_comm="openat_raw"
sudo rmmod trace_user_trigger_raw_openat
## Dmesg
`kernel/user/stage3/case17_do_filp_open_deep_trace/reports/user_trigger_raw_openat_dmesg.txt`
================================================================================
[EMBED] user_trigger_trace_report.md
[SOURCE] kernel/user/stage3/case17_do_filp_open_deep_trace/reports/user_trigger_trace_report.md
================================================================================
# Trace Report: user_trigger.c
- Userspace source: `kernel/user/stage3/case17_do_filp_open_deep_trace/user_trigger.c`
- Driver source: `kernel/drivers/stage3/case17_do_filp_open_deep_trace/trace_user_trigger/trace_user_trigger.c`
- Module: `trace_user_trigger`
- Binary: `kernel/user/stage3/case17_do_filp_open_deep_trace/user_trigger`
- Run timestamp: `2026-02-15T23:32:16`
- Final status: `pass_probe_hits`
## Probe Counts
- do_filp_open.entry: 9
- do_filp_open.ret: 9
- __d_alloc.entry: 1
- __d_alloc.ret: 1
## Return Signature Counts
- ERR_PTR(-ENOENT) observed (fffffffffffffffe): 7
- Non-error pointer returns observed: 2
## Commands
make -C kernel/drivers/stage3/case17_do_filp_open_deep_trace/trace_user_trigger
kernel/user/stage3/case17_do_filp_open_deep_trace/user_trigger
sudo dmesg -C
sudo insmod kernel/drivers/stage3/case17_do_filp_open_deep_trace/trace_user_trigger/trace_user_trigger.ko target_comm="user_trigger"
sudo rmmod trace_user_trigger
## Dmesg
`kernel/user/stage3/case17_do_filp_open_deep_trace/reports/user_trigger_dmesg.txt`
================================================================================
[EMBED] user_trigger_dmesg.txt
[SOURCE] kernel/user/stage3/case17_do_filp_open_deep_trace/reports/user_trigger_dmesg.txt
================================================================================
[38317.947023] [trace_user_trigger] loaded target_comm=user_trigger user=kernel/user/stage3/case17_do_filp_open_deep_trace/user_trigger.c
[38317.949977] [trace_user_trigger] do_filp_open.entry pid=181836 comm=user_trigger dfd=4294967196 pathname=ffff8dda12eb4000 op=ffffd0c940c9fbb4
[38317.949990] [trace_user_trigger] do_filp_open.ret pid=181836 comm=user_trigger ret=fffffffffffffffe
[38317.949997] [trace_user_trigger] do_filp_open.entry pid=181836 comm=user_trigger dfd=4294967196 pathname=ffff8dda12eb4000 op=ffffd0c940c9fe34
[38317.950002] [trace_user_trigger] do_filp_open.ret pid=181836 comm=user_trigger ret=fffffffffffffffe
[38317.950007] [trace_user_trigger] do_filp_open.entry pid=181836 comm=user_trigger dfd=4294967196 pathname=ffff8dda12eb4000 op=ffffd0c940c9fdb4
[38317.950012] [trace_user_trigger] do_filp_open.ret pid=181836 comm=user_trigger ret=fffffffffffffffe
[38317.950019] [trace_user_trigger] do_filp_open.entry pid=181836 comm=user_trigger dfd=4294967196 pathname=ffff8dda12eb4000 op=ffffd0c940c9fe44
[38317.950023] [trace_user_trigger] do_filp_open.ret pid=181836 comm=user_trigger ret=fffffffffffffffe
[38317.950026] [trace_user_trigger] do_filp_open.entry pid=181836 comm=user_trigger dfd=4294967196 pathname=ffff8dda12eb4000 op=ffffd0c940c9fb94
[38317.950029] [trace_user_trigger] do_filp_open.ret pid=181836 comm=user_trigger ret=fffffffffffffffe
[38317.950032] [trace_user_trigger] do_filp_open.entry pid=181836 comm=user_trigger dfd=4294967196 pathname=ffff8dda12eb4000 op=ffffd0c940c9faa4
[38317.950035] [trace_user_trigger] do_filp_open.ret pid=181836 comm=user_trigger ret=fffffffffffffffe
[38317.950039] [trace_user_trigger] do_filp_open.entry pid=181836 comm=user_trigger dfd=4294967196 pathname=ffff8dda12eb4000 op=ffffd0c940c9fdf4
[38317.950043] [trace_user_trigger] do_filp_open.ret pid=181836 comm=user_trigger ret=ffff8dda03350000
[38317.950060] [trace_user_trigger] do_filp_open.entry pid=181836 comm=user_trigger dfd=4294967196 pathname=ffff8dda12eb4000 op=ffffd0c940c9fe34
[38317.950065] [trace_user_trigger] do_filp_open.ret pid=181836 comm=user_trigger ret=ffff8dda03350c00
[38317.950273] [trace_user_trigger] do_filp_open.entry pid=181836 comm=user_trigger dfd=4294967196 pathname=ffff8dda12eb4000 op=ffffd0c940c9fd04
[38317.950279] [trace_user_trigger] __d_alloc.entry pid=181836 comm=user_trigger sb=ffff8dda0bce8000 name_qstr=ffffd0c940c9fbd0
[38317.950283] [trace_user_trigger] __d_alloc.ret pid=181836 comm=user_trigger dentry=ffff8dda130d76c0
[38317.950296] [trace_user_trigger] do_filp_open.ret pid=181836 comm=user_trigger ret=fffffffffffffffe
================================================================================
[EMBED] user_trigger_raw_openat_dmesg.txt
[SOURCE] kernel/user/stage3/case17_do_filp_open_deep_trace/reports/user_trigger_raw_openat_dmesg.txt
================================================================================
[38319.132835] [trace_user_trigger_raw_openat] loaded target_comm=openat_raw user=kernel/user/stage3/case17_do_filp_open_deep_trace/user_trigger_raw_openat.S
[38319.136527] [trace_user_trigger_raw_openat] do_filp_open.entry pid=182093 comm=openat_raw dfd=4294967196 pathname=ffff8dda0eca3000 op=ffffd0c940cf7d44
[38319.136545] [trace_user_trigger_raw_openat] do_filp_open.ret pid=182093 comm=openat_raw ret=fffffffffffffffe
================================================================================
[EMBED] DLOOKUP_REPLAY_RUN_LOG.txt
[SOURCE] kernel/user/stage3/case17_do_filp_open_deep_trace/DLOOKUP_REPLAY_RUN_LOG.txt
================================================================================
[RUN] Case17 d_lookup replay proof
Step1: capture with probe driver
- module: driver.ko
- params: target_comm=user_trigger target_name=missing_case17_filp_
- trigger: ./user_trigger
Captured lines:
[C17][d_alloc_parallel][ENTRY] pid=75221 tgid=75221 parent=ffff8dda3ba6f0c0 parent_inode=ffff8ddb28e95d98 parent_name=case17_do_filp_open_deep_trace child_name=missing_case17_filp_75221.txt parent_sb=ffff8dda0bce8000 sb_magic=0xef53 sb_blocksize=4096
[C17][__d_alloc][ENTRY] pid=75221 tgid=75221 qstr_ptr=ffffd0c941f33a80 name_ptr=ffff8dda082a8083 len=29 hash=0xf168d14a name=missing_case17_filp_75221.txt
[C17][__d_alloc][RET] pid=75221 tgid=75221 dentry=ffff8ddc063cb3c0 inode=0000000000000000 unhashed=1 in_lookup=0 name.hash=0xf168d14a name.len=29 name_ptr=ffff8ddc063cb3f8
[C17][do_filp_open][RET] pid=75221 tgid=75221 ret_ptr=fffffffffffffffe is_err=1 err=2
Parsed replay inputs:
- parent_addr=0xffff8dda3ba6f0c0
- child_name=missing_case17_filp_75221.txt
- child_hash=0xf168d14a
Step2: replay with direct d_lookup module
- module: dlookup_replay_driver.ko
- params: parent_addr=0xffff8dda3ba6f0c0 child_name=missing_case17_filp_75221.txt child_hash=0xf168d14a
Replay output:
[DLOOKUP_REPLAY] init parent=ffff8dda3ba6f0c0 child_name=missing_case17_filp_75221.txt child_hash=0xf168d14a
[DLOOKUP_REPLAY] d_lookup HIT dentry=ffff8ddc063cb3c0 inode=0000000000000000 negative=1 unhashed=0
Result:
- d_lookup returned non-NULL HIT for captured parent+qstr
- returned dentry is negative (inode=NULL)
================================================================================
[EMBED] REVERSE_FULL_TRACE_MISSING_FILE_CASE17_PSTREE.md
[SOURCE] kernel/user/stage3/case17_do_filp_open_deep_trace/REVERSE_FULL_TRACE_MISSING_FILE_CASE17_PSTREE.md
================================================================================
# Reverse Full Trace (Case17 Missing File) (pstree style, end -> start)
Run data source: `kernel/user/stage3/case17_do_filp_open_deep_trace/DLOOKUP_REPLAY_RUN_LOG.txt`
Kernel source anchors: `/usr/src/linux-hwe-6.17-6.17.0`
Legend (tokens used inline per-line): `CALL`=enter function, `RET`=return from function, `RESUME`=caller continues after callee returns.
0. [ROOT] user_trigger(pid=75221 tgid=75221 comm="user_trigger") -> open("/home/r/Desktop/what-happens-when-open-is-called/kernel/user/stage3/case17_do_filp_open_deep_trace/missing_case17_filp_75221.txt", O_RDONLY=0x0)
|
|-- #1 RET userspace:open() -> fd=-1 errno=2(ENOENT) path_len=114 flags=0x0 (result printed by `user_trigger.c`)
| |
| `-- #2 RET kernel:do_sys_openat2 /usr/src/linux-hwe-6.17-6.17.0/fs/open.c:1420 caller=__x64_sys_openat2/? fd_result=-2 (ENOENT)
| |
| `-- #3 RESUME fs/open.c:1437 do_sys_openat2 resumes after do_filp_open(dfd=AT_FDCWD? or abs path) returned IS_ERR(f)=1
| |
| `-- #4 RET kernel:do_filp_open /usr/src/linux-hwe-6.17-6.17.0/fs/namei.c:4073 pid=75221 ret_ptr=0xfffffffffffffffe is_err=1 err=2
| |
| `-- #5 RESUME fs/namei.c:4040-4063 path_openat() had alloc_empty_file() already; error path executed -> fput_close(file) (fs/namei.c:4063)
| |
| `-- #6 RET kernel:path_openat /usr/src/linux-hwe-6.17-6.17.0/fs/namei.c:4034 pid=75221 error=-2
| |
| `-- #7 RESUME fs/namei.c:4049-4055 while-loop ended with error=-2 from do_open() path (not ECHILD/ESTALE)
| |
| `-- #8 RET kernel:do_open /usr/src/linux-hwe-6.17-6.17.0/fs/namei.c:3851 pid=75221 error=-2
| |
| `-- #9 RET kernel:may_open /usr/src/linux-hwe-6.17-6.17.0/fs/namei.c:3447 pid=75221 inode=0x0 -> return -2
| |
| `-- #10 DATA fs/namei.c:3450-3455 dentry=nd->path.dentry=(NEGATIVE) inode=dentry->d_inode=0x0 if(!inode) return -ENOENT
|
|-- #11 RESUME (how nd->path.dentry became NEGATIVE) do_open() at fs/namei.c:3860-3864 saw file->f_mode lacks FMODE_OPENED|FMODE_CREATED -> complete_walk() then audit/idmap then may_open()
| |
| `-- #12 RET kernel:open_last_lookups /usr/src/linux-hwe-6.17-6.17.0/fs/namei.c:3768 pid=75221 returns NULL/err-sentinel such that path_openat while-loop exits
| |
| `-- #13 RESUME fs/namei.c:3815 open_last_lookups called lookup_open() under inode_lock_shared()
| |
| `-- #14 RET kernel:lookup_open /usr/src/linux-hwe-6.17-6.17.0/fs/namei.c:3618 pid=75221 returns dentry=0xffff8ddc063cb3c0 d_inode=0x0 (negative)
| |
| |-- #15 DATA fs/namei.c:3634 file->f_mode &= ~FMODE_CREATED (O_CREAT not set; open_flag=0x0 from userspace O_RDONLY)
| |
| |-- #16 RESUME fs/namei.c:3635 dentry = d_lookup(dir=0xffff8dda3ba6f0c0, name=&nd->last)
| | |
| | `-- #17 RET kernel:d_lookup /usr/src/linux-hwe-6.17-6.17.0/fs/dcache.c:2332 parent=0xffff8dda3ba6f0c0 qstr.hash=0xf168d14a -> returns NULL (cache miss)
| | |
| | `-- #18 RET kernel:__d_lookup /usr/src/linux-hwe-6.17-6.17.0/fs/dcache.c:2362 bucket=d_hash(0xf168d14a) scan count>=0 found=0x0
| |
| |-- #19 RESUME fs/namei.c:3637 if(!dentry) -> dentry=d_alloc_parallel(dir,&nd->last,&wq)
| | |
| | `-- #20 RET kernel:d_alloc_parallel /usr/src/linux-hwe-6.17-6.17.0/fs/dcache.c:2542 pid=75221
| | parent=0xffff8dda3ba6f0c0 parent_inode=0xffff8ddb28e95d98 parent_sb=0xffff8dda0bce8000 sb_magic=0xef53 sb_blocksize=4096
| | child_name="missing_case17_filp_75221.txt" len=29 hash=0xf168d14a
| | returns new=0xffff8ddc063cb3c0
| | |
| | |-- #21 DATA fs/dcache.c:2549 new = __d_alloc(parent->d_sb, name)
| | | |
| | | `-- #22 RET kernel:__d_alloc /usr/src/linux-hwe-6.17-6.17.0/fs/dcache.c:1684 qstr_ptr=0xffffd0c941f33a80 name_ptr=0xffff8dda082a8083 len=29 hash=0xf168d14a
| | | -> dentry=0xffff8ddc063cb3c0 inode=0x0 unhashed=1 in_lookup=0 (captured at __d_alloc RET)
| | |
| | |-- #23 DATA fs/dcache.c:2558-2559 new->d_parent = dget_dlock(parent) AND hlist_add_head(&new->d_sib,&parent->d_children)
| | |-- #24 DATA fs/dcache.c:2647-2649 new->d_wait=&wq AND hlist_bl_add_head(&new->d_u.d_in_lookup_hash, in_lookup_bucket(parent,hash))
| | `-- #25 NOTE fs/dcache.c:2648 this is NOT global dentry_hashtable; it is the per-parent “in-lookup” chain to dedupe parallel lookups
| |
| |-- #26 RESUME fs/namei.c:3642-3643 if(d_in_lookup(dentry)) break; (dentry is in-lookup now)
| |
| `-- #27 RESUME fs/namei.c:3693-3705 because d_in_lookup(dentry)=1:
| |
| |-- #28 CALL kernel:FS->lookup (ext4) dir_inode->i_op->lookup(dir_inode=0xffff8ddb28e95d98, dentry=0xffff8ddc063cb3c0, flags=nd->flags)
| | |
| | `-- #29 RET kernel:ext4_lookup /usr/src/linux-hwe-6.17-6.17.0/fs/ext4/namei.c:1762
| | inode=0x0 (miss) -> return d_splice_alias(inode=0x0, dentry=0xffff8ddc063cb3c0) at fs/ext4/namei.c:1814
| |
| |-- #30 RESUME (FS -> VFS callback) d_splice_alias(NULL,dentry) enters dcache attach path:
| | |
| | |-- #31 CALL kernel:__d_add /usr/src/linux-hwe-6.17-6.17.0/fs/dcache.c:2692 dentry=0xffff8ddc063cb3c0 inode=0x0 ops=0x0
| | |-- #32 DATA fs/dcache.c:2699-2703 d_in_lookup(dentry)=1 -> __d_lookup_unhash(dentry) removes d_u.d_in_lookup_hash node (ends “lookup in progress” chain)
| | |-- #33 DATA fs/dcache.c:2714 __d_rehash(dentry)
| | | |
| | | `-- #34 DATA kernel:__d_rehash /usr/src/linux-hwe-6.17-6.17.0/fs/dcache.c:2484 b=d_hash(dentry->d_name.hash=0xf168d14a) -> hlist_bl_add_head_rcu(&dentry->d_hash,b) at fs/dcache.c:2489
| | | RESULT: dentry=0xffff8ddc063cb3c0 now reachable by future __d_lookup(parent,qstr) bucket scan
| | `-- #35 RET __d_add returns (still inside lookup_open call stack)
| |
| |-- #36 RESUME fs/namei.c:3696 d_lookup_done(dentry) executes after FS lookup returns (clears in-lookup state / wakes waiters)
| |-- #37 RESUME fs/namei.c:3697-3704 res!=NULL (ext4 returned dentry*) -> dput(old_dentry) then dentry=res (same pointer in this run)
| `-- #38 RET fs/namei.c:3725 lookup_open returns negative dentry 0xffff8ddc063cb3c0 (open_flag lacks O_CREAT)
|
`-- [POST-PROOF] replay verification (separate module, after the failed open)
|
|-- #39 CALL d_lookup_replay_driver:init parent=0xffff8dda3ba6f0c0 child_name="missing_case17_filp_75221.txt" child_hash=0xf168d14a
`-- #40 RET d_lookup(parent,qstr) HIT dentry=0xffff8ddc063cb3c0 inode=0x0 negative=1 unhashed=0 (proves global dentry_hashtable insert happened at fs/dcache.c:2489)
================================================================================
[EMBED] DLOOKUP_CRITICAL_BLOCK_NUMERIC.md
[SOURCE] kernel/user/stage3/case17_do_filp_open_deep_trace/DLOOKUP_CRITICAL_BLOCK_NUMERIC.md
================================================================================
# `__d_lookup` Critical Block: Numeric Worksheet (One Block Only)
Code block under study:
spin_lock(&dentry->d_lock);
if (dentry->d_parent != parent)
goto next;
if (d_unhashed(dentry))
goto next;
if (!d_same_name(dentry, parent, name))
goto next;
dentry->d_lockref.count++;
found = dentry;
spin_unlock(&dentry->d_lock);
break;
Middle-first concrete run (from your logs):
1. `parent = 0xffff8dda3ba6f0c0`.
2. `target child name = "missing_case17_filp_75221.txt"`.
3. `target hash = 0xf168d14a`.
4. replay hit: `dentry = 0xffff8ddc063cb3c0`, `inode = 0x0`, `negative=1`, `unhashed=0`.
---
## Numeric walk: one pass of the loop body
1. lock op: `spin_lock(&dentry->d_lock)` on `dentry=0xffff8ddc063cb3c0`.
2. parent compare: `dentry->d_parent == 0xffff8dda3ba6f0c0` -> `true` -> no `goto next`.
3. hash-link check: `d_unhashed(dentry) == 0` -> `false` branch not taken -> no `goto next`.
4. name compare: `d_same_name(...) == 1` -> `!1 == 0` -> no `goto next`.
5. refcount step: `dentry->d_lockref.count = k` -> `k+1`.
6. assign: `found = 0xffff8ddc063cb3c0`.
7. unlock: `spin_unlock(&dentry->d_lock)`.
8. `break` exits bucket loop immediately.
9. function return later: `return found` -> non-NULL hit pointer.
---
## Failure branches in same block (numbers only)
1. branch A: `d_parent mismatch` -> `goto next` -> unlock -> continue bucket scan.
2. branch B: `d_unhashed(dentry)=1` -> `goto next` -> unlock -> continue.
3. branch C: `d_same_name=0` -> `goto next` -> unlock -> continue.
4. all branches A/B/C keep `found=NULL` unless later candidate passes all checks.
---
## Small / mid / large bucket arithmetic
1. small: bucket size `k=1` -> comparisons max `1` -> hit at index `0` -> cost ~`1` candidate.
2. mid: bucket size `k=7` -> indices `{0,1,2,3,4,5,6}` -> hit at index `3` -> `4` candidates tested.
3. large: bucket size `k=1000000` -> worst case miss checks `1000000` candidates.
4. strict worst-case complexity: `O(k)` where `k = bucket chain length`.
5. average expected with good hash spread: small `k` => near-constant behavior.
---
## Fractional and edge arithmetic
1. load factor style toy: `N=1000 dentries`, `B=256 buckets` -> avg `N/B=3 remainder 232`.
2. bucket occupancy example: `232` buckets with `4`, `24` buckets with `3`.
3. edge 1: `N=0` -> all buckets empty -> immediate miss.
4. edge 2: all names collide into one bucket -> `k=N` -> worst-case linear scan.
---
## Concrete memory-state sketch (`found` path)
Stack frame (`__d_lookup`):
[stack @ SP+0x00] parent = 0xffff8dda3ba6f0c0
[stack @ SP+0x08] name.ptr -> "missing_case17_filp_75221.txt"
[stack @ SP+0x10] hash = 0xf168d14a
[stack @ SP+0x18] found = 0x0000000000000000 (init)
[stack @ SP+0x20] dentry = 0xffff8ddc063cb3c0 (candidate)
Transition:
1. before checks: `found = 0x0`.
2. after all three checks pass: `found = 0xffff8ddc063cb3c0`.
3. return value: `0xffff8ddc063cb3c0`.
Observed replay output aligns:
[DLOOKUP_REPLAY] d_lookup HIT dentry=ffff8ddc063cb3c0 inode=0000000000000000 negative=1 unhashed=0
---
## W-table (numbers-first)
1. What: `3` gate checks + `1` refcount increment + `1` pointer assignment.
2. Why: avoid false hit (`parent`, `hashed`, `full-name`) before returning pointer.
3. Where: `fs/dcache.c::__d_lookup` bucket scan loop.
4. Who: caller `d_lookup(parent,qstr)` -> `__d_lookup`.
5. When: after bucket select by `d_hash(hash)`.
6. Without: skipping any check can produce wrong hit probability `>0` under collisions/moves.
7. Which: winning candidate in this run = `0xffff8ddc063cb3c0`.
---
## Failure predictions for this block
1. F1: stale parent pointer -> parent check fails for all candidates -> miss.
2. F2: stale unhashed dentry -> `d_unhashed=1` -> skip.
3. F3: hash collision but different name -> `d_same_name=0` -> skip.
4. F4: lock/refcount bug -> use-after-free risk if count not incremented before return.
================================================================================
[EMBED] LOOKUP_OPEN_PSEUDODEBUG_TRACE_MISSING_FILE.md
[SOURCE] kernel/user/stage3/case17_do_filp_open_deep_trace/LOOKUP_OPEN_PSEUDODEBUG_TRACE_MISSING_FILE.md
================================================================================
# lookup_open() Pseudo-Debug Trace (Case17 Missing File) (single caller, no race)
Data source (captured): `kernel/user/stage3/case17_do_filp_open_deep_trace/DLOOKUP_REPLAY_RUN_LOG.txt`
Kernel source anchors: `/usr/src/linux-hwe-6.17-6.17.0`
Target run (captured):
- pid=75221 tgid=75221 comm=`user_trigger`
- parent dentry (dir)=`0xffff8dda3ba6f0c0`
- parent inode (dir_inode)=`0xffff8ddb28e95d98`
- superblock (parent->d_sb)=`0xffff8dda0bce8000` magic=`0xef53` blocksize=`4096`
- last component (nd->last): name=`"missing_case17_filp_75221.txt"` len=`29` hash=`0xf168d14a`
Format per line:
`#N FUNC STATE file:line caller(file:line) values work result`
1. lookup_open CALL fs/namei.c:3618 open_last_lookups(fs/namei.c:3815) dir=`0xffff8dda3ba6f0c0` dir_inode=`0xffff8ddb28e95d98` open_flag=`0x0` got_write=`0` enter ok
2. lookup_open DATA fs/namei.c:3634 lookup_open(fs/namei.c:3618) file->f_mode: (old)=? work=`file->f_mode &= ~FMODE_CREATED` file->f_mode (new)=old&~FMODE_CREATED
3. d_lookup CALL fs/dcache.c:2332 lookup_open(fs/namei.c:3635) parent=`0xffff8dda3ba6f0c0` qstr.name=`"missing_case17_filp_75221.txt"` qstr.len=`29` qstr.hash=`0xf168d14a` begin ->
4. __d_lookup CALL fs/dcache.c:2362 d_lookup(fs/dcache.c:2339) hash=`0xf168d14a` bucket=`d_hash(0xf168d14a)` scan `dentry_hashtable` bucket-chain found=`NULL`
5. d_lookup RET fs/dcache.c:2332 lookup_open(fs/namei.c:3635) ret=`NULL` cache-miss dentry=`NULL`
6. lookup_open BRANCH fs/namei.c:3637 lookup_open(fs/namei.c:3636) cond=`(!dentry)` -> TRUE allocate candidate via d_alloc_parallel ->
7. d_alloc_parallel CALL fs/dcache.c:2542 lookup_open(fs/namei.c:3638) parent=`0xffff8dda3ba6f0c0` name=`"missing_case17_filp_75221.txt"` len=`29` hash=`0xf168d14a` wq=`&wq(stack)` allocate+publish(in-lookup) ->
8. __d_alloc CALL fs/dcache.c:1684 d_alloc_parallel(fs/dcache.c:2549) sb=`0xffff8dda0bce8000` qstr_ptr=`0xffffd0c941f33a80` name_ptr=`0xffff8dda082a8083` len=`29` hash=`0xf168d14a` slab alloc (`kmem_cache_alloc_lru`) + init name fields ->
9. __d_alloc RET fs/dcache.c:1684 d_alloc_parallel(fs/dcache.c:2549) ret(new)=`0xffff8ddc063cb3c0` new->d_inode=`0x0` new unhashed=`1` new in_lookup=`0` name.hash=`0xf168d14a` name.len=`29` name_ptr_field_addr=`0xffff8ddc063cb3f8` dentry object exists (negative, not hashed yet) ok
10. d_alloc_parallel DATA fs/dcache.c:2556 d_alloc_parallel(fs/dcache.c:2542) new=`0xffff8ddc063cb3c0` set `DCACHE_PAR_LOOKUP` ok
11. d_alloc_parallel DATA fs/dcache.c:2558 d_alloc_parallel(fs/dcache.c:2542) new->d_parent=`dget_dlock(parent=0xffff8dda3ba6f0c0)` attach to parent pointer ok
12. d_alloc_parallel DATA fs/dcache.c:2559 d_alloc_parallel(fs/dcache.c:2542) link-list: `hlist_add_head(&new->d_sib,&parent->d_children)` attach into parent child list ok
13. d_alloc_parallel DATA fs/dcache.c:2647 d_alloc_parallel(fs/dcache.c:2542) new->d_wait=`&wq(stack)` publish waiter queue pointer ok
14. d_alloc_parallel DATA fs/dcache.c:2648 d_alloc_parallel(fs/dcache.c:2542) `hlist_bl_add_head(&new->d_u.d_in_lookup_hash, in_lookup_hash(parent,hash))` publish “lookup-in-progress” node ok
15. d_alloc_parallel RET fs/dcache.c:2650 lookup_open(fs/namei.c:3638) ret=`0xffff8ddc063cb3c0` return candidate dentry dentry!=ERR
16. lookup_open BRANCH fs/namei.c:3642 lookup_open(fs/namei.c:3636) cond=`d_in_lookup(dentry)` -> TRUE break out of for(;;) ->
17. lookup_open BRANCH fs/namei.c:3654 lookup_open(fs/namei.c:3618) cond=`dentry->d_inode` -> FALSE (`0x0`) continue (not cached positive) ->
18. lookup_open BRANCH fs/namei.c:3686 lookup_open(fs/namei.c:3618) cond=`dir_inode->i_op->atomic_open` -> FALSE in this run (path uses ->lookup) ->
19. FS->lookup CALL fs/namei.c:3694 lookup_open(fs/namei.c:3693) call=`dir_inode->i_op->lookup(dir_inode=0xffff8ddb28e95d98, dentry=0xffff8ddc063cb3c0, flags=nd->flags)` ask FS “does this name exist?” ->
20. ext4_lookup CALL fs/ext4/namei.c:1762 lookup_open(fs/namei.c:3694) dentry=`0xffff8ddc063cb3c0` directory search ->
21. ext4_lookup DATA fs/ext4/namei.c:1774 ext4_lookup(fs/ext4/namei.c:1762) inode=`NULL` on miss missing file confirmed by FS directory scan inode=`0x0`
22. ext4_lookup RET fs/ext4/namei.c:1814 lookup_open(fs/namei.c:3694) return=`d_splice_alias(inode=0x0,dentry=0xffff8ddc063cb3c0)` FS hands result to VFS dcache res=`dentry*` (usually same)
23. __d_add CALL fs/dcache.c:2692 (via d_splice_alias) dentry=`0xffff8ddc063cb3c0` inode=`0x0` ops=`0x0` finalize dentry + hash it (NOT PROBED in this run)
24. __d_add DATA fs/dcache.c:2699 __d_add(fs/dcache.c:2692) cond=`d_in_lookup(dentry)` -> TRUE remove in-lookup state via `__d_lookup_unhash(dentry)` (NOT PROBED)
25. __d_add DATA fs/dcache.c:2714 __d_add(fs/dcache.c:2692) call=`__d_rehash(dentry)` insert into global dentry_hashtable (NOT PROBED)
26. __d_rehash DATA fs/dcache.c:2489 __d_rehash(fs/dcache.c:2484) `hlist_bl_add_head_rcu(&dentry->d_hash, d_hash(dentry->d_name.hash=0xf168d14a))` global-hash attach happens here (NOT PROBED)
27. lookup_open DATA fs/namei.c:3696 lookup_open(fs/namei.c:3693) `d_lookup_done(dentry)` clear lookup-in-progress flag/wake waiters (NOT PROBED)
28. lookup_open BRANCH fs/namei.c:3697 lookup_open(fs/namei.c:3693) cond=`res` -> TRUE (ext4 returned non-NULL) if(res==dentry) net effect is keep same pointer; code does `dput(dentry); dentry=res;` (NOT PROBED)
29. lookup_open BRANCH fs/namei.c:3708 lookup_open(fs/namei.c:3618) cond=`(!dentry->d_inode && (open_flag & O_CREAT))` -> FALSE (open_flag=`0x0`) skip create ->
30. lookup_open RET fs/namei.c:3725 open_last_lookups(fs/namei.c:3815) ret=`0xffff8ddc063cb3c0` inode=`0x0` negative dentry returned to caller ok
Post-proof (captured separately, confirms step #26 happened):
31. d_lookup (replay) RET fs/dcache.c:2332 dlookup_replay_driver HIT ret=`0xffff8ddc063cb3c0` inode=`0x0` negative=`1` unhashed=`0` (means: global dentry_hashtable contains it)
Notes:
- Steps marked “NOT PROBED” are kernel-source steps that were *proven indirectly* by the replay HIT (`unhashed=0`) plus the captured pre/post pointers.
- If you want direct brute proof, add kprobe+kretprobe on: `__d_add`, `__d_rehash`, and `__d_lookup_unhash` and re-run the same trigger.
<!-- AUTO-EMBED END -->