[PATCH AUTOSEL 7.0-5.10] JFS: always load filesystem UUID during mount

From: Sasha Levin

Date: Mon Apr 20 2026 - 11:36:31 EST


From: João Paredes <joaommp@xxxxxxxxx>

[ Upstream commit 679330e4a7af1d102d035b13b2b9d41bc1dfbbf7 ]

The filesystem UUID was only being loaded into super_block sb when an
external journal device was in use. When mounting without an external
journal, the UUID remained unset, which prevented the computation of
a filesystem ID (fsid), which could be confirmed via `stat -f -c "%i"`
and thus user space could not use fanotify correctly.

A missing filesystem ID causes fanotify to return ENODEV when marking
the filesystem for events like FAN_CREATE, FAN_DELETE, FAN_MOVED_TO,
and FAN_MOVED_FROM. As a result, applications relying on fanotify
could not monitor these events on JFS filesystems without an external
journal.

Moved the UUID initialization so it is always performed during mount,
ensuring the superblock UUID is consistently available.

Signed-off-by: João Paredes <joaommp@xxxxxxxxx>
Signed-off-by: Dave Kleikamp <dave.kleikamp@xxxxxxxxxx>
Signed-off-by: Sasha Levin <sashal@xxxxxxxxxx>
---

LLM Generated explanations, may be completely bogus:

Now I have all the information needed for a thorough analysis. Let me
compile it.

---

## PHASE 1: COMMIT MESSAGE FORENSICS

### Step 1.1: PARSE THE SUBJECT LINE
- **Subsystem:** JFS (Journaled File System)
- **Action verb:** "always load" (correcting behavior that should have
been unconditional)
- **Summary:** Ensures the filesystem UUID is always loaded during
mount, not just when external journal is configured
- Record: [JFS] [always load / ensure] [Fix UUID not being loaded for
inline-log configurations, breaking fsid and fanotify]

### Step 1.2: PARSE ALL COMMIT MESSAGE TAGS
- **Signed-off-by: João Paredes <joaommp@xxxxxxxxx>** - Author of the
fix (no prior JFS commits found)
- **Signed-off-by: Dave Kleikamp <dave.kleikamp@xxxxxxxxxx>** - JFS
maintainer, signed off = reviewed and accepted
- No Fixes: tag, no Reported-by, no Cc: stable (expected for this
pipeline)
- Record: Fix accepted by JFS subsystem maintainer. No explicit stable
nomination.

### Step 1.3: ANALYZE THE COMMIT BODY TEXT
The commit clearly describes the bug:
- **Bug:** UUID only loaded when external journal used (`!JFS_INLINELOG`
path); inline log (the default) left `sbi->uuid` unset (all zeros)
- **Symptom:** `stat -f -c "%i"` returns 0 (no filesystem ID); fanotify
returns `ENODEV` for `FAN_CREATE`, `FAN_DELETE`, `FAN_MOVED_TO`,
`FAN_MOVED_FROM`
- **Root cause:** `uuid_copy` was inside the else branch of the inline-
log conditional
- **Impact:** Applications relying on fanotify cannot monitor filesystem
events on JFS
- Record: Real functional bug with clear user-visible symptoms. Fanotify
breaks for the default JFS configuration.

### Step 1.4: DETECT HIDDEN BUG FIXES
Not hidden at all. The commit message is direct about the bug mechanism
and user-visible impact.

## PHASE 2: DIFF ANALYSIS - LINE BY LINE

### Step 2.1: INVENTORY THE CHANGES
- **File:** `fs/jfs/jfs_mount.c` only
- **Lines added:** 2 (uuid_copy + blank line before if/else)
- **Lines removed:** 1 (uuid_copy from else block)
- **Net change:** +1 line
- **Function modified:** `chkSuper()`
- **Scope:** Single-file, surgical one-line fix
- Record: [fs/jfs/jfs_mount.c: +2/-1] [chkSuper()] [Single-file surgical
fix]

### Step 2.2: UNDERSTAND THE CODE FLOW CHANGE

**Before:**

```381:387:fs/jfs/jfs_mount.c
if (sbi->mntflag & JFS_INLINELOG)
sbi->logpxd = j_sb->s_logpxd;
else {
sbi->logdev =
new_decode_dev(le32_to_cpu(j_sb->s_logdev));
uuid_copy(&sbi->uuid, &j_sb->s_uuid);
uuid_copy(&sbi->loguuid, &j_sb->s_loguuid);
}
```

**After:** `uuid_copy(&sbi->uuid, &j_sb->s_uuid)` is moved BEFORE the
if/else block, making it unconditional. `uuid_copy(&sbi->loguuid, ...)`
stays in else (correct - only needed for external log).

### Step 2.3: IDENTIFY THE BUG MECHANISM
- **Category:** Logic/correctness fix - conditional initialization that
should be unconditional
- **What was broken:** UUID needed unconditionally (for fsid computation
in `jfs_statfs()`), but was only loaded in the external-log path
- **How the fix works:** Moves the uuid_copy call outside the
conditional

### Step 2.4: ASSESS THE FIX QUALITY
- **Obviously correct:** Yes - the UUID is a filesystem property, not a
journal-specific property
- **Minimal:** Yes - moving one line
- **Regression risk:** Essentially zero. For the inline-log case, UUID
is now properly populated (was zeros before). For the external-log
case, behavior is identical.

## PHASE 3: GIT HISTORY INVESTIGATION

### Step 3.1: BLAME THE CHANGED LINES
- The if/else structure dates to `^1da177e4c3f41` (Linux 2.6.12-rc2,
2005-04-16, Linus Torvalds) - present since initial git history
- The `uuid_copy` line was updated by `2e3bc6125154c6` (Andy Shevchenko,
2019-01-10) - UUID API conversion only, didn't change the placement
- The original code ALWAYS had the UUID copy inside the else branch
- Record: Buggy placement dates to the initial Linux git import
(v2.6.12). Present in ALL stable trees.

### Step 3.2: THE REAL FIXES TARGET
The fsid computation using `sbi->uuid` was added by `b5c816a4f1776`
(Coly Li, 2009-01-21, "jfs: return f_fsid for statfs(2)"). This commit
added the CRC32-based fsid computation but didn't realize the UUID was
only loaded for external-log configurations. So the actual bug was
introduced in 2009 when the UUID became functionally significant beyond
just external log tracking.

### Step 3.3-3.5: RELATED CHANGES
- No recent JFS changes to jfs_mount.c affect this area
- This is a standalone fix with no dependencies
- Author João Paredes has no other JFS commits (first-time contributor),
but the fix was accepted by JFS maintainer Dave Kleikamp

## PHASE 4: MAILING LIST AND EXTERNAL RESEARCH

### Step 4.1-4.5
- Could not find the original patch submission on lore.kernel.org due to
bot protection
- The fix was accepted by Dave Kleikamp (JFS maintainer) which provides
strong quality signal
- No CVE was found for this specific issue

## PHASE 5: CODE SEMANTIC ANALYSIS

### Step 5.1-5.2: KEY FUNCTIONS AND CALLERS
The impacted code path:
1. `chkSuper()` is called during `jfs_mount()` (line 83) and during
`jfs_mount_rw()` remount (line 232)
2. `sbi->uuid` is consumed by:
- `jfs_statfs()` in `fs/jfs/super.c` (lines 146-150) - computes
`f_fsid` via CRC32 of UUID
- `lmLogFileSystem()` in `fs/jfs/jfs_logmgr.c` (line 1713) - tracks
active filesystems in log
3. `jfs_statfs()` is the VFS `.statfs` operation, called via
`vfs_statfs()` and `vfs_get_fsid()`
4. `fanotify_test_fsid()` calls `vfs_get_fsid()` which calls
`jfs_statfs()` - confirmed in `fs/notify/fanotify/fanotify_user.c`
line 1771

### Step 5.3-5.4: FANOTIFY ENODEV MECHANISM CONFIRMED
In `fanotify_test_fsid()` (line 1776):

```1776:1779:fs/notify/fanotify/fanotify_user.c
if (!fsid->id.val[0] && !fsid->id.val[1]) {
err = -ENODEV;
goto weak;
}
```

When `sbi->uuid` is all zeros (kzalloc'd), `crc32_le(0, zeros, N) = 0`
(CRC is linear, zero input with zero init = zero output). So `f_fsid =
{0, 0}`, triggering the ENODEV path. The `weak` label returns `-ENODEV`
for non-inode marks (FAN_MARK_FILESYSTEM, FAN_MARK_MOUNT).

### Step 5.5: SIMILAR PATTERNS
The comment at line 1769 explicitly says: "Make sure dentry is not of a
filesystem with zero fsid (e.g. fuse)." JFS was silently in this same
broken category for inline-log configs.

## PHASE 6: CROSS-REFERENCING AND STABLE TREE ANALYSIS

### Step 6.1: BUGGY CODE EXISTS IN ALL STABLE TREES
Confirmed via `git show v7.0-rc7:fs/jfs/jfs_mount.c` - the buggy
conditional UUID loading is present. The code has been this way since
the initial Linux git import and exists in ALL active stable trees.

### Step 6.2: BACKPORT COMPLICATIONS
None. The patch will apply cleanly - the surrounding code in
`chkSuper()` has been unchanged for years.

## PHASE 7: SUBSYSTEM AND MAINTAINER CONTEXT

### Step 7.1: SUBSYSTEM CRITICALITY
- **Subsystem:** JFS filesystem (fs/jfs/)
- **Criticality:** IMPORTANT - filesystem correctness affects data and
application behavior
- JFS is a mature filesystem used particularly in enterprise
environments

### Step 7.2: SUBSYSTEM ACTIVITY
JFS receives minimal but ongoing maintenance, mostly bug fixes.

## PHASE 8: IMPACT AND RISK ASSESSMENT

### Step 8.1: WHO IS AFFECTED
All JFS users mounting without an external journal (the default
configuration). This is the vast majority of JFS users.

### Step 8.2: TRIGGER CONDITIONS
- **How common:** Every single mount of a JFS filesystem with inline log
- **User trigger:** Any application using fanotify with
`FAN_MARK_FILESYSTEM` or `FAN_MARK_MOUNT` on JFS
- **No special privileges needed** beyond normal fanotify access

### Step 8.3: FAILURE MODE SEVERITY
- **Failure:** Applications using fanotify (file monitoring, security
tools, backup software) get ENODEV and cannot monitor JFS filesystems
- **Severity:** HIGH - functional breakage of a standard kernel
interface for a standard filesystem configuration
- Not a crash or security issue, but a clear functional bug affecting
userspace applications

### Step 8.4: RISK-BENEFIT RATIO
- **Benefit:** HIGH - fixes fanotify for all JFS users with inline log
(the common case)
- **Risk:** VERY LOW - 1 line moved, obviously correct, no possible
regression
- **Ratio:** Excellent

## PHASE 9: FINAL SYNTHESIS

### Step 9.1: EVIDENCE COMPILATION

**FOR backporting:**
- Fixes a real, user-visible bug: fanotify returns ENODEV for default
JFS configurations
- Extremely small and surgical fix: 1 line moved
- Obviously correct: UUID is a filesystem property, not journal-specific
- Accepted by JFS maintainer (Dave Kleikamp)
- Bug affects ALL stable trees (code unchanged since initial git import)
- Patch applies cleanly
- Zero regression risk
- Bug has existed since 2009 (fsid computation added)

**AGAINST backporting:**
- No Fixes: tag or Cc: stable (expected - that's why it needs review)
- No syzbot/KASAN/crash - it's a functional bug, not a memory safety
issue
- Author is a first-time contributor (but fix accepted by maintainer)

### Step 9.2: STABLE RULES CHECKLIST
1. Obviously correct and tested? **YES** - trivially verifiable,
accepted by maintainer
2. Fixes a real bug? **YES** - fanotify ENODEV for default JFS
configuration
3. Important issue? **YES** - breaks standard kernel interface for
application monitoring
4. Small and contained? **YES** - 1 line moved in 1 file
5. No new features or APIs? **YES** - just fixes existing behavior
6. Can apply to stable? **YES** - will apply cleanly to all stable trees

### Step 9.3: EXCEPTION CATEGORIES
Not an exception category - this is a standard bug fix.

## Verification

- [Phase 1] Parsed tags: Signed-off-by from author and JFS maintainer
Dave Kleikamp
- [Phase 2] Diff analysis: 1 line moved from else block to unconditional
execution in `chkSuper()`
- [Phase 3] git blame: buggy conditional structure present since
`^1da177e4c3f41` (v2.6.12, 2005); fsid computation added in
`b5c816a4f1776` (2009) made it functionally significant
- [Phase 3] git show v7.0-rc7: confirmed buggy code exists unchanged in
v7.0 stable tree
- [Phase 5] Traced call chain: `fanotify_test_fsid()` ->
`vfs_get_fsid()` -> `jfs_statfs()` -> CRC32 of `sbi->uuid`; confirmed
zero-UUID produces zero fsid which triggers ENODEV at
fanotify_user.c:1776-1777
- [Phase 5] Confirmed `sbi` allocated via `kzalloc_obj` in super.c:452,
so uuid is zero-initialized
- [Phase 5] Confirmed `JFS_INLINELOG` (0x00000800) is the default/common
JFS configuration
- [Phase 6] Code is identical across all stable trees - patch applies
cleanly
- [Phase 8] Failure mode: fanotify returns -ENODEV for
FAN_MARK_FILESYSTEM/MOUNT on default JFS, severity HIGH
- UNVERIFIED: Could not access lore.kernel.org for original patch
discussion (bot protection blocked access)

**YES**

fs/jfs/jfs_mount.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/fs/jfs/jfs_mount.c b/fs/jfs/jfs_mount.c
index 52e6b58c5dbd2..dac822f150701 100644
--- a/fs/jfs/jfs_mount.c
+++ b/fs/jfs/jfs_mount.c
@@ -378,11 +378,12 @@ static int chkSuper(struct super_block *sb)
sbi->nbperpage = PSIZE >> sbi->l2bsize;
sbi->l2nbperpage = L2PSIZE - sbi->l2bsize;
sbi->l2niperblk = sbi->l2bsize - L2DISIZE;
+ uuid_copy(&sbi->uuid, &j_sb->s_uuid);
+
if (sbi->mntflag & JFS_INLINELOG)
sbi->logpxd = j_sb->s_logpxd;
else {
sbi->logdev = new_decode_dev(le32_to_cpu(j_sb->s_logdev));
- uuid_copy(&sbi->uuid, &j_sb->s_uuid);
uuid_copy(&sbi->loguuid, &j_sb->s_loguuid);
}
sbi->fsckpxd = j_sb->s_fsckpxd;
--
2.53.0