git: b2e4b6358440 - main - msdosfs: add msdosfs_integrity_error()
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Sat, 08 Jan 2022 04:29:37 UTC
The branch main has been updated by kib: URL: https://cgit.FreeBSD.org/src/commit/?id=b2e4b635844091de0601f5b7157d87115386b2a9 commit b2e4b635844091de0601f5b7157d87115386b2a9 Author: Konstantin Belousov <kib@FreeBSD.org> AuthorDate: 2021-12-25 21:20:56 +0000 Commit: Konstantin Belousov <kib@FreeBSD.org> CommitDate: 2022-01-08 04:20:48 +0000 msdosfs: add msdosfs_integrity_error() A function to remount the filesystem from rw to ro on integrity error. The work is performed in taskqueue to allow the call to be done from almost arbitrary context where erronous state was detected. Tested by: pho Reviewed by: markj, mckusick Sponsored by: The FreeBSD Foundation MFC after: 1 week Differential revision: https://reviews.freebsd.org/D33721 --- 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 8ef46e063420..3c2606ab5a91 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_ */