]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
ocfs2: add ocfs2_emergency_state helper and apply to setattr
authorAhmet Eray Karadag <eraykrdg1@gmail.com>
Wed, 3 Dec 2025 03:34:25 +0000 (06:34 +0300)
committerAndrew Morton <akpm@linux-foundation.org>
Thu, 11 Dec 2025 00:07:43 +0000 (16:07 -0800)
Patch series "ocfs2: Refactor read-only checks to use
ocfs2_emergency_state", v4.

Following the fix for the `make_bad_inode` validation failure (syzbot ID:
b93b65ee321c97861072), this separate series introduces a new helper
function, `ocfs2_emergency_state()`, to improve and centralize read-only
and error state checking.

This is modeled after the `ext4_emergency_state()` pattern, providing a
single, unified location for checking all filesystem-level emergency
conditions.  This makes the code cleaner and ensures that any future
checks (e.g., for fatal error states) can be added in one place.

This series is structured as follows:

1.  The first patch introduces the `ocfs2_emergency_state()` helper
    (currently checking for -EROFS) and applies it to `ocfs2_setattr`
    to provide a "fail-fast" mechanism, as suggested by Albin
    Babu Varghese.
2.  The second patch completes the refactoring by converting all
    remaining read-only checks throughout OCFS2 to use this new helper.

This patch (of 2):

To centralize error checking, follow the pattern of other filesystems like
ext4 (which uses `ext4_emergency_state()`), and prepare for future
enhancements, this patch introduces a new helper function:
`ocfs2_emergency_state()`.

The purpose of this helper is to provide a single, unified location for
checking all filesystem-level emergency conditions.  In this initial
implementation, the function only checks for the existing hard and soft
read-only modes, returning -EROFS if either is set.

This provides a foundation where future checks (e.g., for fatal error
states returning -EIO, or shutdown states) can be easily added in one
place.

This patch also adds this new check to the beginning of `ocfs2_setattr()`.
This ensures that operations like `ftruncate` (which triggered the
original BUG) fail-fast with -EROFS when the filesystem is already in a
read-only state.

Link: https://lkml.kernel.org/r/cover.1764728893.git.eraykrdg1@gmail.com
Link: https://lkml.kernel.org/r/e9e975bcaaff8dbc155b70fbc1b2798a2e36e96f.1764728893.git.eraykrdg1@gmail.com
Co-developed-by: Albin Babu Varghese <albinbabuvarghese20@gmail.com>
Signed-off-by: Albin Babu Varghese <albinbabuvarghese20@gmail.com>
Signed-off-by: Ahmet Eray Karadag <eraykrdg1@gmail.com>
Suggested-by: Heming Zhao <heming.zhao@suse.com>
Reviewed-by: Heming Zhao <heming.zhao@suse.com>
Reviewed-by: Joseph Qi <joseph.qi@linux.alibaba.com>
Cc: Mark Fasheh <mark@fasheh.com>
Cc: Joel Becker <jlbec@evilplan.org>
Cc: Junxiao Bi <junxiao.bi@oracle.com>
Cc: Changwei Ge <gechangwei@live.cn>
Cc: Jun Piao <piaojun@huawei.com>
Cc: David Hunter <david.hunter.linux@gmail.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
fs/ocfs2/file.c
fs/ocfs2/ocfs2.h

index 21d797ccccd068c46a923f2ec255d470fc8cad3f..ddca292944d7061564abf99e4a30d94cd5586670 100644 (file)
@@ -1136,6 +1136,12 @@ int ocfs2_setattr(struct mnt_idmap *idmap, struct dentry *dentry,
                                attr->ia_valid & ATTR_GID ?
                                        from_kgid(&init_user_ns, attr->ia_gid) : 0);
 
+       status = ocfs2_emergency_state(osb);
+       if (unlikely(status)) {
+               mlog_errno(status);
+               goto bail;
+       }
+
        /* ensuring we don't even attempt to truncate a symlink */
        if (S_ISLNK(inode->i_mode))
                attr->ia_valid &= ~ATTR_SIZE;
index 6aaa94c554c12a694175dc21c8b81f1f538e483d..7b50e03dfa664a2b69eadc7e5230bc38963d0a85 100644 (file)
@@ -680,6 +680,24 @@ static inline int ocfs2_is_soft_readonly(struct ocfs2_super *osb)
        return ret;
 }
 
+static inline int ocfs2_is_readonly(struct ocfs2_super *osb)
+{
+       int ret;
+       spin_lock(&osb->osb_lock);
+       ret = osb->osb_flags & (OCFS2_OSB_SOFT_RO | OCFS2_OSB_HARD_RO);
+       spin_unlock(&osb->osb_lock);
+
+       return ret;
+}
+
+static inline int ocfs2_emergency_state(struct ocfs2_super *osb)
+{
+       if (ocfs2_is_readonly(osb))
+               return -EROFS;
+
+       return 0;
+}
+
 static inline int ocfs2_clusterinfo_valid(struct ocfs2_super *osb)
 {
        return (osb->s_feature_incompat &