Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F106130814
D33721.id100832.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
16 KB
Referenced Files
None
Subscribers
None
D33721.id100832.diff
View Options
diff --git a/sys/fs/msdosfs/msdosfs_denode.c b/sys/fs/msdosfs/msdosfs_denode.c
--- a/sys/fs/msdosfs/msdosfs_denode.c
+++ b/sys/fs/msdosfs/msdosfs_denode.c
@@ -142,9 +142,24 @@
return (error);
if (nvp != NULL) {
*depp = VTODE(nvp);
- KASSERT((*depp)->de_dirclust == dirclust, ("wrong dirclust"));
- KASSERT((*depp)->de_diroffset == diroffset, ("wrong diroffset"));
+ if ((*depp)->de_dirclust != dirclust) {
+ printf("wrong dir cluster %s %lu %lu\n",
+ pmp->pm_mountp->mnt_stat.f_mntonname,
+ (*depp)->de_dirclust, dirclust);
+ goto badoff;
+ }
+ if ((*depp)->de_diroffset != diroffset) {
+ printf("wrong dir offset %s %lu %lu\n",
+ pmp->pm_mountp->mnt_stat.f_mntonname,
+ (*depp)->de_diroffset, diroffset);
+ goto badoff;
+ }
return (0);
+badoff:
+ vgone(nvp);
+ vput(nvp);
+ msdosfs_integrity_error(pmp);
+ return (EBADF);
}
ldep = malloc(sizeof(struct denode), M_MSDOSFSNODE, M_WAITOK | M_ZERO);
diff --git a/sys/fs/msdosfs/msdosfs_fat.c b/sys/fs/msdosfs/msdosfs_fat.c
--- a/sys/fs/msdosfs/msdosfs_fat.c
+++ b/sys/fs/msdosfs/msdosfs_fat.c
@@ -80,8 +80,7 @@
u_long fatbn);
static __inline void
usemap_alloc(struct msdosfsmount *pmp, u_long cn);
-static __inline void
- usemap_free(struct msdosfsmount *pmp, u_long cn);
+static int usemap_free(struct msdosfsmount *pmp, u_long cn);
static int clusteralloc1(struct msdosfsmount *pmp, u_long start,
u_long count, u_long fillwith, u_long *retcluster,
u_long *got);
@@ -398,7 +397,7 @@
pmp->pm_flags |= MSDOSFS_FSIMOD;
}
-static __inline void
+static int
usemap_free(struct msdosfsmount *pmp, u_long cn)
{
@@ -408,13 +407,18 @@
pmp->pm_maxcluster));
KASSERT((pmp->pm_flags & MSDOSFSMNT_RONLY) == 0,
("usemap_free on ro msdosfs mount"));
+ if ((pmp->pm_inusemap[cn / N_INUSEBITS] &
+ (1U << (cn % N_INUSEBITS))) == 0) {
+ printf("%s: Freeing unused sector %ld %ld %x\n",
+ pmp->pm_mountp->mnt_stat.f_mntonname, cn, cn % N_INUSEBITS,
+ (unsigned)pmp->pm_inusemap[cn / N_INUSEBITS]);
+ msdosfs_integrity_error(pmp);
+ return (EINTEGRITY);
+ }
pmp->pm_freeclustercount++;
pmp->pm_flags |= MSDOSFS_FSIMOD;
- KASSERT((pmp->pm_inusemap[cn / N_INUSEBITS] &
- (1U << (cn % N_INUSEBITS))) != 0,
- ("Freeing unused sector %ld %ld %x", cn, cn % N_INUSEBITS,
- (unsigned)pmp->pm_inusemap[cn / N_INUSEBITS]));
pmp->pm_inusemap[cn / N_INUSEBITS] &= ~(1U << (cn % N_INUSEBITS));
+ return (0);
}
int
@@ -432,11 +436,11 @@
* bit in the "in use" cluster bit map.
*/
MSDOSFS_LOCK_MP(pmp);
- usemap_free(pmp, cluster);
+ error = usemap_free(pmp, cluster);
MSDOSFS_UNLOCK_MP(pmp);
- if (oldcnp)
+ if (error == 0 && oldcnp != NULL)
*oldcnp = oldcn;
- return (0);
+ return (error);
}
/*
@@ -712,7 +716,7 @@
error = fatchain(pmp, start, count, fillwith);
if (error != 0) {
for (cl = start, n = count; n-- > 0;)
- usemap_free(pmp, cl++);
+ (void)usemap_free(pmp, cl++);
return (error);
}
#ifdef MSDOSFS_DEBUG
@@ -846,7 +850,12 @@
}
lbn = bn;
}
- usemap_free(pmp, cluster);
+ error = usemap_free(pmp, cluster);
+ if (error != 0) {
+ bwrite(bp);
+ MSDOSFS_UNLOCK_MP(pmp);
+ return (error);
+ }
switch (pmp->pm_fatmask) {
case FAT12_MASK:
readcn = getushort(bp->b_data + bo);
@@ -940,8 +949,13 @@
#endif
brelse(bp);
return (EINVAL);
- } else if (readcn == CLUST_FREE)
- usemap_free(pmp, cn);
+ } else if (readcn == CLUST_FREE) {
+ error = usemap_free(pmp, cn);
+ if (error != 0) {
+ brelse(bp);
+ return (error);
+ }
+ }
}
if (bp != NULL)
brelse(bp);
diff --git a/sys/fs/msdosfs/msdosfs_lookup.c b/sys/fs/msdosfs/msdosfs_lookup.c
--- a/sys/fs/msdosfs/msdosfs_lookup.c
+++ b/sys/fs/msdosfs/msdosfs_lookup.c
@@ -63,6 +63,29 @@
#include <fs/msdosfs/fat.h>
#include <fs/msdosfs/msdosfsmount.h>
+static int
+msdosfs_lookup_checker(struct msdosfsmount *pmp, struct vnode *dvp,
+ struct denode *tdp, struct vnode **vpp)
+{
+ struct vnode *vp;
+
+ vp = DETOV(tdp);
+
+ /*
+ * Lookup assumes that directory cannot be hardlinked.
+ * Corrupted msdosfs filesystem could break this assumption.
+ */
+ if (vp == dvp) {
+ vput(vp); /* XXXKIB or vrele ? */
+ msdosfs_integrity_error(pmp);
+ *vpp = NULL;
+ return (EBADF);
+ }
+
+ *vpp = vp;
+ return (0);
+}
+
int
msdosfs_lookup(struct vop_cachedlookup_args *ap)
{
@@ -501,8 +524,7 @@
error = deget(pmp, cluster, blkoff, LK_EXCLUSIVE, &tdp);
if (error)
return (error);
- *vpp = DETOV(tdp);
- return (0);
+ return (msdosfs_lookup_checker(pmp, vdp, tdp, vpp));
}
/*
@@ -529,9 +551,8 @@
if ((error = deget(pmp, cluster, blkoff, LK_EXCLUSIVE,
&tdp)) != 0)
return (error);
- *vpp = DETOV(tdp);
cnp->cn_flags |= SAVENAME;
- return (0);
+ return (msdosfs_lookup_checker(pmp, vdp, tdp, vpp));
}
/*
@@ -572,14 +593,23 @@
vput(*vpp);
goto restart;
}
+ error = msdosfs_lookup_checker(pmp, vdp, VTODE(*vpp), vpp);
+ if (error != 0)
+ return (error);
} else if (dp->de_StartCluster == scn && isadir) {
+ if (cnp->cn_namelen != 1 || cnp->cn_nameptr[0] != '.') {
+ /* fs is corrupted, non-dot lookup returned dvp */
+ msdosfs_integrity_error(pmp);
+ return (EBADF);
+ }
VREF(vdp); /* we want ourself, ie "." */
*vpp = vdp;
} else {
if ((error = deget(pmp, cluster, blkoff, LK_EXCLUSIVE,
&tdp)) != 0)
return (error);
- *vpp = DETOV(tdp);
+ if ((error = msdosfs_lookup_checker(pmp, vdp, tdp, vpp)) != 0)
+ return (error);
}
/*
diff --git a/sys/fs/msdosfs/msdosfs_vfsops.c b/sys/fs/msdosfs/msdosfs_vfsops.c
--- 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 @@
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,8 @@
mp->mnt_flag &= ~MNT_RDONLY;
MNT_IUNLOCK(mp);
}
+ if ((pmp->pm_flags & MSDOSFS_ERR_RO) != 0)
+ return (0);
}
/*
* Not an update, or updating the name: look up the name
@@ -456,14 +460,14 @@
b710 = (struct byte_bpb710 *)bsp->bs710.bsBPB;
#ifndef MSDOSFS_NOCHECKSIG
- if (bsp->bs50.bsBootSectSig0 != BOOTSIG0
- || bsp->bs50.bsBootSectSig1 != BOOTSIG1) {
+ if (bsp->bs50.bsBootSectSig0 != BOOTSIG0 ||
+ bsp->bs50.bsBootSectSig1 != BOOTSIG1) {
error = EINVAL;
goto error_exit;
}
#endif
- pmp = malloc(sizeof *pmp, M_MSDOSFSMNT, M_WAITOK | M_ZERO);
+ pmp = malloc(sizeof(*pmp), M_MSDOSFSMNT, M_WAITOK | M_ZERO);
pmp->pm_mountp = mp;
pmp->pm_cp = cp;
pmp->pm_bo = bo;
@@ -471,6 +475,8 @@
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.
@@ -509,7 +515,7 @@
* use these anyway, so we're unaffected if they are
* invalid.
*/
- if (!pmp->pm_BytesPerSec || !SecPerClust) {
+ if (pmp->pm_BytesPerSec == 0 || SecPerClust == 0) {
error = EINVAL;
goto error_exit;
}
@@ -523,8 +529,7 @@
}
if (pmp->pm_RootDirEnts == 0) {
- if (pmp->pm_FATsecs
- || getushort(b710->bpbFSVers)) {
+ if (pmp->pm_FATsecs != 0 || getushort(b710->bpbFSVers) != 0) {
error = EINVAL;
#ifdef MSDOSFS_DEBUG
printf("mountmsdosfs(): bad FAT32 filesystem\n");
@@ -535,7 +540,7 @@
pmp->pm_fatmult = 4;
pmp->pm_fatdiv = 1;
pmp->pm_FATsecs = getulong(b710->bpbBigFATsecs);
- if (getushort(b710->bpbExtFlags) & FATMIRROR)
+ if ((getushort(b710->bpbExtFlags) & FATMIRROR) != 0)
pmp->pm_curfat = getushort(b710->bpbExtFlags) & FATNUM;
else
pmp->pm_flags |= MSDOSFS_FATMIRROR;
@@ -549,19 +554,24 @@
* - number of sectors: >= 1, <= size of partition
* - number of FAT sectors: >= 1
*/
- if ( (SecPerClust == 0)
- || (SecPerClust & (SecPerClust - 1))
- || (pmp->pm_BytesPerSec < DEV_BSIZE)
- || (pmp->pm_BytesPerSec & (pmp->pm_BytesPerSec - 1))
- || (pmp->pm_HugeSectors == 0)
- || (pmp->pm_FATsecs == 0)
- || (SecPerClust * pmp->pm_BlkPerSec > MAXBSIZE / DEV_BSIZE)
- ) {
+ if (SecPerClust == 0 || (SecPerClust & (SecPerClust - 1)) != 0 ||
+ pmp->pm_BytesPerSec < DEV_BSIZE ||
+ (pmp->pm_BytesPerSec & (pmp->pm_BytesPerSec - 1)) != 0 ||
+ pmp->pm_HugeSectors == 0 || pmp->pm_FATsecs == 0 ||
+ SecPerClust * pmp->pm_BlkPerSec > MAXBSIZE / DEV_BSIZE) {
error = EINVAL;
goto error_exit;
}
pmp->pm_HugeSectors *= pmp->pm_BlkPerSec;
+ if ((off_t)pmp->pm_HugeSectors * pmp->pm_BytesPerSec <
+ pmp->pm_HugeSectors /* overflow */ ||
+ (off_t)pmp->pm_HugeSectors * pmp->pm_BytesPerSec >
+ cp->provider->mediasize /* past end of vol */) {
+ error = EINVAL;
+ goto error_exit;
+ }
+
pmp->pm_HiddenSects *= pmp->pm_BlkPerSec; /* XXX not used? */
pmp->pm_FATsecs *= pmp->pm_BlkPerSec;
SecPerClust *= pmp->pm_BlkPerSec;
@@ -570,24 +580,28 @@
if (FAT32(pmp)) {
pmp->pm_rootdirblk = getulong(b710->bpbRootClust);
- pmp->pm_firstcluster = pmp->pm_fatblk
- + (pmp->pm_FATs * pmp->pm_FATsecs);
+ pmp->pm_firstcluster = pmp->pm_fatblk +
+ pmp->pm_FATs * pmp->pm_FATsecs;
pmp->pm_fsinfo = getushort(b710->bpbFSInfo) * pmp->pm_BlkPerSec;
} else {
pmp->pm_rootdirblk = pmp->pm_fatblk +
- (pmp->pm_FATs * pmp->pm_FATsecs);
+ pmp->pm_FATs * pmp->pm_FATsecs;
pmp->pm_rootdirsize = howmany(pmp->pm_RootDirEnts *
- sizeof(struct direntry), DEV_BSIZE); /* in blocks */
+ sizeof(struct direntry), DEV_BSIZE); /* in blocks */
pmp->pm_firstcluster = pmp->pm_rootdirblk + pmp->pm_rootdirsize;
}
+ if (pmp->pm_HugeSectors <= pmp->pm_firstcluster) {
+ error = EINVAL;
+ goto error_exit;
+ }
pmp->pm_maxcluster = (pmp->pm_HugeSectors - pmp->pm_firstcluster) /
SecPerClust + 1;
pmp->pm_fatsize = pmp->pm_FATsecs * DEV_BSIZE; /* XXX not used? */
if (pmp->pm_fatmask == 0) {
- if (pmp->pm_maxcluster
- <= ((CLUST_RSRVD - CLUST_FIRST) & FAT12_MASK)) {
+ if (pmp->pm_maxcluster <= ((CLUST_RSRVD - CLUST_FIRST) &
+ FAT12_MASK)) {
/*
* This will usually be a floppy disk. This size makes
* sure that one FAT entry will not be split across
@@ -633,7 +647,7 @@
* Check for valid cluster size
* must be a power of 2
*/
- if (pmp->pm_bpcluster ^ (1 << pmp->pm_cnshift)) {
+ if ((pmp->pm_bpcluster ^ (1 << pmp->pm_cnshift)) != 0) {
error = EINVAL;
goto error_exit;
}
@@ -657,9 +671,9 @@
NOCRED, &bp)) != 0)
goto error_exit;
fp = (struct fsinfo *)bp->b_data;
- if (!bcmp(fp->fsisig1, "RRaA", 4)
- && !bcmp(fp->fsisig2, "rrAa", 4)
- && !bcmp(fp->fsisig3, "\0\0\125\252", 4)) {
+ if (!bcmp(fp->fsisig1, "RRaA", 4) &&
+ !bcmp(fp->fsisig2, "rrAa", 4) &&
+ !bcmp(fp->fsisig3, "\0\0\125\252", 4)) {
pmp->pm_nxtfree = getulong(fp->fsinxtfree);
if (pmp->pm_nxtfree > pmp->pm_maxcluster)
pmp->pm_nxtfree = CLUST_FIRST;
@@ -683,9 +697,8 @@
* Allocate memory for the bitmap of allocated clusters, and then
* fill it in.
*/
- pmp->pm_inusemap = malloc(howmany(pmp->pm_maxcluster + 1, N_INUSEBITS)
- * sizeof(*pmp->pm_inusemap),
- M_MSDOSFSFAT, M_WAITOK);
+ pmp->pm_inusemap = malloc(howmany(pmp->pm_maxcluster + 1,
+ N_INUSEBITS) * sizeof(*pmp->pm_inusemap), M_MSDOSFSFAT, M_WAITOK);
/*
* fillinusemap() needs pm_devvp.
@@ -732,14 +745,14 @@
return (0);
error_exit:
- if (bp)
+ if (bp != NULL)
brelse(bp);
if (cp != NULL) {
g_topology_lock();
g_vfs_close(cp);
g_topology_unlock();
}
- if (pmp) {
+ if (pmp != NULL) {
lockdestroy(&pmp->pm_fatlock);
lockdestroy(&pmp->pm_checkpath_lock);
free(pmp->pm_inusemap, M_MSDOSFSFAT);
@@ -840,6 +853,47 @@
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("remounting %s read-only due to corruption\n",
+ pmp->pm_mountp->mnt_stat.f_mntfromname);
+ error = vfs_remount_ro(pmp->pm_mountp);
+ if (error != 0)
+ printf("remounting %s 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)
+{
+ if (vfs_busy(pmp->pm_mountp, MBF_NOWAIT) == 0)
+ taskqueue_enqueue(taskqueue_thread, &pmp->pm_rw2ro_task);
+}
+
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
--- 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>
@@ -116,6 +117,7 @@
struct lock pm_fatlock; /* lockmgr protecting allocations */
struct lock pm_checkpath_lock; /* protects doscheckpath result */
#endif
+ struct task pm_rw2ro_task;
};
/*
@@ -263,5 +265,10 @@
#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_ */
diff --git a/sys/geom/label/g_label_msdosfs.c b/sys/geom/label/g_label_msdosfs.c
--- a/sys/geom/label/g_label_msdosfs.c
+++ b/sys/geom/label/g_label_msdosfs.c
@@ -156,6 +156,12 @@
G_LABEL_DEBUG(2,
"MSDOSFS: FAT_FirstDataSector=0x%x, FAT_BytesPerSector=%d",
fat_FirstDataSector, fat_BytesPerSector);
+ if (fat_BytesPerSector == 0 ||
+ fat_BytesPerSector % pp->sectorsize != 0) {
+ G_LABEL_DEBUG(1, "MSDOSFS: %s: corrupted BPB",
+ pp->name);
+ goto error;
+ }
for (offset = fat_BytesPerSector * fat_FirstDataSector;;
offset += fat_BytesPerSector) {
diff --git a/sys/kern/vfs_mount.c b/sys/kern/vfs_mount.c
--- a/sys/kern/vfs_mount.c
+++ b/sys/kern/vfs_mount.c
@@ -2868,6 +2868,84 @@
free(buf, M_MOUNT);
}
+int
+vfs_remount_ro(struct mount *mp)
+{
+ struct vfsoptlist *opts;
+ struct vfsopt *opt;
+ struct vnode *vp_covered, *rootvp;
+ int error;
+
+ KASSERT(mp->mnt_lockref > 0, ("XXX"));
+ KASSERT((mp->mnt_kern_flag & MNTK_UNMOUNT) == 0, ("XXX"));
+
+ rootvp = NULL;
+ vp_covered = mp->mnt_vnodecovered;
+ error = vget(vp_covered, LK_EXCLUSIVE | LK_NOWAIT);
+ if (error != 0)
+ return (error);
+ VI_LOCK(vp_covered);
+ if ((vp_covered->v_iflag & VI_MOUNT) != 0) {
+ VI_UNLOCK(vp_covered);
+ vput(vp_covered);
+ return (EBUSY);
+ }
+ vp_covered->v_iflag |= VI_MOUNT;
+ VI_UNLOCK(vp_covered);
+ vfs_op_enter(mp);
+ vn_seqc_write_begin(vp_covered);
+
+ MNT_ILOCK(mp);
+ if ((mp->mnt_flag & MNT_RDONLY) != 0) {
+ MNT_IUNLOCK(mp);
+ error = EBUSY;
+ goto out;
+ }
+ mp->mnt_flag |= MNT_UPDATE | MNT_FORCE | MNT_RDONLY;
+ rootvp = vfs_cache_root_clear(mp);
+ MNT_IUNLOCK(mp);
+
+ opts = malloc(sizeof(struct vfsoptlist), M_MOUNT, M_WAITOK | M_ZERO);
+ TAILQ_INIT(opts);
+ opt = malloc(sizeof(struct vfsopt), M_MOUNT, M_WAITOK | M_ZERO);
+ opt->name = strdup("ro", M_MOUNT);
+ opt->value = NULL;
+ TAILQ_INSERT_TAIL(opts, opt, link);
+ vfs_mergeopts(opts, mp->mnt_opt);
+ mp->mnt_optnew = opts;
+
+ error = VFS_MOUNT(mp);
+
+ if (error == 0) {
+ MNT_ILOCK(mp);
+ mp->mnt_flag &= ~(MNT_UPDATE | MNT_FORCE);
+ MNT_IUNLOCK(mp);
+ vfs_deallocate_syncvnode(mp);
+ if (mp->mnt_opt != NULL)
+ vfs_freeopts(mp->mnt_opt);
+ mp->mnt_opt = mp->mnt_optnew;
+ } else {
+ MNT_ILOCK(mp);
+ mp->mnt_flag &= ~(MNT_UPDATE | MNT_FORCE | MNT_RDONLY);
+ MNT_IUNLOCK(mp);
+ vfs_freeopts(mp->mnt_optnew);
+ }
+ mp->mnt_optnew = NULL;
+
+out:
+ vfs_op_exit(mp);
+ VI_LOCK(vp_covered);
+ vp_covered->v_iflag &= ~VI_MOUNT;
+ VI_UNLOCK(vp_covered);
+ vput(vp_covered);
+ vn_seqc_write_end(vp_covered);
+ if (rootvp != NULL) {
+ vn_seqc_write_end(rootvp);
+ vrele(rootvp);
+ }
+ return (error);
+}
+
/*
* Suspend write operations on all local writeable filesystems. Does
* full sync of them in the process.
diff --git a/sys/sys/mount.h b/sys/sys/mount.h
--- a/sys/sys/mount.h
+++ b/sys/sys/mount.h
@@ -1036,6 +1036,8 @@
void vfs_unregister_for_notification(struct mount *,
struct mount_upper_node *);
void vfs_unregister_upper(struct mount *, struct mount_upper_node *);
+int vfs_remount_ro(struct mount *mp);
+
extern TAILQ_HEAD(mntlist, mount) mountlist; /* mounted filesystem list */
extern struct mtx_padalign mountlist_mtx;
extern struct nfs_public nfs_pub;
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Thu, Dec 26, 10:07 PM (10 h, 35 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
15608236
Default Alt Text
D33721.id100832.diff (16 KB)
Attached To
Mode
D33721: Improve msdosfs robustness
Attached
Detach File
Event Timeline
Log In to Comment