diff --git a/fs/ntfs/super.c b/fs/ntfs/super.c index 6a107ec0d0f6..716ba775f1f3 100644 --- a/fs/ntfs/super.c +++ b/fs/ntfs/super.c @@ -1571,6 +1571,7 @@ static bool load_system_files(struct ntfs_volume *vol) struct ntfs_attr_search_ctx *ctx; struct restart_page_header *rp; int err; + u8 saved_on_errors; ntfs_debug("Entering."); /* Get mft mirror inode compare the contents of $MFT and $MFTMirr. */ @@ -1745,8 +1746,19 @@ static bool load_system_files(struct ntfs_volume *vol) * NVolErrors() without setting the dirty volume flag and mount * read-only. This will prevent read-write remounting and it will also * prevent all writes. + * + * Nested lookup and inode-loading errors must not panic before the + * read-only fallback has run. Temporarily use errors=remount-ro + * instead of errors=panic, preserving any read-only transition even + * if an error is not propagated to the check's return value or + * recorded in NVolErrors(). This is safe during initial mount, + * before the super block is published. */ + saved_on_errors = vol->on_errors; + if (saved_on_errors == ON_ERRORS_PANIC) + vol->on_errors = ON_ERRORS_REMOUNT_RO; err = check_windows_hibernation_status(vol); + vol->on_errors = saved_on_errors; if (unlikely(err)) { static const char *es1a = "Failed to determine if Windows is hibernated"; static const char *es1b = "Windows is hibernated"; @@ -1754,17 +1766,21 @@ static bool load_system_files(struct ntfs_volume *vol) const char *es1; es1 = err < 0 ? es1a : es1b; - /* If a read-write mount, convert it to a read-only mount. */ - if (!sb_rdonly(sb) && vol->on_errors == ON_ERRORS_REMOUNT_RO) { - sb->s_flags |= SB_RDONLY; - ntfs_error(sb, "%s. Mounting read-only%s", es1, es2); - } + /* Hibernation safety takes precedence over the errors= policy. */ + sb->s_flags |= SB_RDONLY; NVolSetErrors(vol); + ntfs_error(sb, "%s. Mounting read-only%s", es1, es2); + /* * Remember it for the lifetime of the mount: see * ntfs_sync_volume_dirty_state(). */ NVolSetHibernated(vol); + } else if (!sb_rdonly(sb) && NVolErrors(vol)) { + /* Match the read-write remount restriction for recorded errors. */ + sb->s_flags |= SB_RDONLY; + ntfs_error(sb, + "Errors were recorded during mount. Mounting read-only. Run chkdsk."); } /* If (still) a read-write mount, empty the logfile. */