git: 171b75b0efd0 - stable/13 - msdosfs: add msdosfs_integrity_error()
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Sat, 15 Jan 2022 00:51:44 UTC
The branch stable/13 has been updated by kib: URL: https://cgit.FreeBSD.org/src/commit/?id=171b75b0efd0bb56597acb3c12f57db03fabc660 commit 171b75b0efd0bb56597acb3c12f57db03fabc660 Author: Konstantin Belousov <kib@FreeBSD.org> AuthorDate: 2021-12-25 21:20:56 +0000 Commit: Konstantin Belousov <kib@FreeBSD.org> CommitDate: 2022-01-14 18:11:02 +0000 msdosfs: add msdosfs_integrity_error() (cherry picked from commit b2e4b635844091de0601f5b7157d87115386b2a9) --- sys/fs/msdosfs/msdosfs_vfsops.c | 58 +++++++++++++++++++++++++++++++++++++++++ sys/fs/msdosfs/msdosfsmount.h | 7 +++++ 2 files changed, 65 insertions(+) diff --git a/sys/fs/msdosfs/msdosfs_vfsops.c b/sys/fs/msdosfs/msdosfs_vfsops.c index 77942ed88ce4..e09a75a698d7 100644 --- a/sys/fs/msdosfs/msdosfs_vfsops.c +++ b/sys/fs/msdosfs/msdosfs_vfsops.c @@ -65,6 +65,7 @@ #include <sys/priv.h> #include <sys/proc.h> #include <sys/stat.h> +#include <sys/taskqueue.h> #include <sys/vnode.h> #include <geom/geom.h> @@ -112,6 +113,7 @@ struct iconv_functions *msdosfs_iconv; static int update_mp(struct mount *mp, struct thread *td); static int mountmsdosfs(struct vnode *devvp, struct mount *mp); +static void msdosfs_remount_ro(void *arg, int pending); static vfs_fhtovp_t msdosfs_fhtovp; static vfs_mount_t msdosfs_mount; static vfs_root_t msdosfs_root; @@ -337,6 +339,13 @@ msdosfs_mount(struct mount *mp) mp->mnt_flag &= ~MNT_RDONLY; MNT_IUNLOCK(mp); } + + /* + * Avoid namei() below. The "from" option is not set. + * Update of the devvp is pointless for this case. + */ + if ((pmp->pm_flags & MSDOSFS_ERR_RO) != 0) + return (0); } /* * Not an update, or updating the name: look up the name @@ -471,6 +480,8 @@ mountmsdosfs(struct vnode *devvp, struct mount *mp) lockinit(&pmp->pm_fatlock, 0, msdosfs_lock_msg, 0, 0); lockinit(&pmp->pm_checkpath_lock, 0, "msdoscp", 0, 0); + TASK_INIT(&pmp->pm_rw2ro_task, 0, msdosfs_remount_ro, pmp); + /* * Initialize ownerships and permissions, since nothing else will * initialize them iff we are mounting root. @@ -847,6 +858,53 @@ msdosfs_unmount(struct mount *mp, int mntflags) return (error); } +static void +msdosfs_remount_ro(void *arg, int pending) +{ + struct msdosfsmount *pmp; + int error; + + pmp = arg; + + MSDOSFS_LOCK_MP(pmp); + if ((pmp->pm_flags & MSDOSFS_ERR_RO) != 0) { + while ((pmp->pm_flags & MSDOSFS_ERR_RO) != 0) + msleep(&pmp->pm_flags, &pmp->pm_fatlock, PVFS, + "msdoserrro", hz); + } else if ((pmp->pm_mountp->mnt_flag & MNT_RDONLY) == 0) { + pmp->pm_flags |= MSDOSFS_ERR_RO; + MSDOSFS_UNLOCK_MP(pmp); + printf("%s: remounting read-only due to corruption\n", + pmp->pm_mountp->mnt_stat.f_mntfromname); + error = vfs_remount_ro(pmp->pm_mountp); + if (error != 0) + printf("%s: remounting read-only failed: error %d\n", + pmp->pm_mountp->mnt_stat.f_mntfromname, error); + else + printf("remounted %s read-only\n", + pmp->pm_mountp->mnt_stat.f_mntfromname); + MSDOSFS_LOCK_MP(pmp); + pmp->pm_flags &= ~MSDOSFS_ERR_RO; + wakeup(&pmp->pm_flags); + } + MSDOSFS_UNLOCK_MP(pmp); + + vfs_unbusy(pmp->pm_mountp); +} + +void +msdosfs_integrity_error(struct msdosfsmount *pmp) +{ + int error; + + error = vfs_busy(pmp->pm_mountp, MBF_NOWAIT); + if (error == 0) + taskqueue_enqueue(taskqueue_thread, &pmp->pm_rw2ro_task); + else + printf("%s: integrity error busying failed, error %d\n", + pmp->pm_mountp->mnt_stat.f_mntfromname, error); +} + static int msdosfs_root(struct mount *mp, int flags, struct vnode **vpp) { diff --git a/sys/fs/msdosfs/msdosfsmount.h b/sys/fs/msdosfs/msdosfsmount.h index 46a02e611cf5..6a0ba896dff5 100644 --- a/sys/fs/msdosfs/msdosfsmount.h +++ b/sys/fs/msdosfs/msdosfsmount.h @@ -59,6 +59,7 @@ #ifndef MAKEFS #include <sys/lock.h> #include <sys/lockmgr.h> +#include <sys/_task.h> #endif #include <sys/tree.h> @@ -115,6 +116,7 @@ struct msdosfsmount { #ifndef MAKEFS struct lock pm_fatlock; /* lockmgr protecting allocations */ struct lock pm_checkpath_lock; /* protects doscheckpath result */ + struct task pm_rw2ro_task; /* context for emergency remount ro */ #endif }; @@ -263,5 +265,10 @@ struct msdosfs_args { #define MSDOSFSMNT_WAITONFAT 0x40000000 /* mounted synchronous */ #define MSDOSFS_FATMIRROR 0x20000000 /* FAT is mirrored */ #define MSDOSFS_FSIMOD 0x01000000 +#define MSDOSFS_ERR_RO 0x00800000 /* remouning ro due to error */ + +#ifdef _KERNEL +void msdosfs_integrity_error(struct msdosfsmount *pmp); +#endif #endif /* !_MSDOSFS_MSDOSFSMOUNT_H_ */