aboutsummaryrefslogtreecommitdiff
path: root/sys/ufs
diff options
context:
space:
mode:
authorChuck Silvers <chs@FreeBSD.org>2020-03-06 18:41:37 +0000
committerChuck Silvers <chs@FreeBSD.org>2020-03-06 18:41:37 +0000
commitf15ccf8836d9d42b92f999dbd6c4746c9547f8a6 (patch)
tree38fe0edcbd4e53a2582d03f803e6da6ade9f1dac /sys/ufs
parent6c37d6032ed296370371f8c9f79068ba7c6a54df (diff)
downloadsrc-f15ccf8836d9d42b92f999dbd6c4746c9547f8a6.tar.gz
src-f15ccf8836d9d42b92f999dbd6c4746c9547f8a6.zip
Add a new "mntfs" pseudo file system which provides private device vnodes for
file systems to safely access their disk devices, and adapt FFS to use it. Also add a new BO_NOBUFS flag to allow enforcing that file systems using mntfs vnodes do not accidentally use the original devfs vnode to create buffers. Reviewed by: kib, mckusick Approved by: imp (mentor) Sponsored by: Netflix Differential Revision: https://reviews.freebsd.org/D23787
Notes
Notes: svn path=/head/; revision=358714
Diffstat (limited to 'sys/ufs')
-rw-r--r--sys/ufs/ffs/ffs_alloc.c5
-rw-r--r--sys/ufs/ffs/ffs_vfsops.c48
-rw-r--r--sys/ufs/ufs/ufsmount.h3
3 files changed, 43 insertions, 13 deletions
diff --git a/sys/ufs/ffs/ffs_alloc.c b/sys/ufs/ffs/ffs_alloc.c
index fb270b11d912..0b8068db0da7 100644
--- a/sys/ufs/ffs/ffs_alloc.c
+++ b/sys/ufs/ffs/ffs_alloc.c
@@ -3594,6 +3594,7 @@ buffered_write(fp, uio, active_cred, flags, td)
struct inode *ip;
struct buf *bp;
struct fs *fs;
+ struct ufsmount *ump;
struct filedesc *fdp;
int error;
daddr_t lbn;
@@ -3622,10 +3623,12 @@ buffered_write(fp, uio, active_cred, flags, td)
return (EINVAL);
}
ip = VTOI(vp);
- if (ITODEVVP(ip) != devvp) {
+ ump = ip->i_ump;
+ if (ump->um_odevvp != devvp) {
vput(vp);
return (EINVAL);
}
+ devvp = ump->um_devvp;
fs = ITOFS(ip);
vput(vp);
foffset_lock_uio(fp, uio, flags);
diff --git a/sys/ufs/ffs/ffs_vfsops.c b/sys/ufs/ffs/ffs_vfsops.c
index 5051c0a11eb8..1ae7fdc6184f 100644
--- a/sys/ufs/ffs/ffs_vfsops.c
+++ b/sys/ufs/ffs/ffs_vfsops.c
@@ -151,7 +151,7 @@ static const char *ffs_opts[] = { "acls", "async", "noatime", "noclusterr",
static int
ffs_mount(struct mount *mp)
{
- struct vnode *devvp;
+ struct vnode *devvp, *odevvp;
struct thread *td;
struct ufsmount *ump = NULL;
struct fs *fs;
@@ -246,6 +246,7 @@ ffs_mount(struct mount *mp)
if (mp->mnt_flag & MNT_UPDATE) {
ump = VFSTOUFS(mp);
fs = ump->um_fs;
+ odevvp = ump->um_odevvp;
devvp = ump->um_devvp;
if (fsckpid == -1 && ump->um_fsckpid > 0) {
if ((error = ffs_flushfiles(mp, WRITECLOSE, td)) != 0 ||
@@ -337,16 +338,15 @@ ffs_mount(struct mount *mp)
* If upgrade to read-write by non-root, then verify
* that user has necessary permissions on the device.
*/
- vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY);
- error = VOP_ACCESS(devvp, VREAD | VWRITE,
+ vn_lock(odevvp, LK_EXCLUSIVE | LK_RETRY);
+ error = VOP_ACCESS(odevvp, VREAD | VWRITE,
td->td_ucred, td);
if (error)
error = priv_check(td, PRIV_VFS_MOUNT_PERM);
+ VOP_UNLOCK(odevvp);
if (error) {
- VOP_UNLOCK(devvp);
return (error);
}
- VOP_UNLOCK(devvp);
fs->fs_flags &= ~FS_UNCLEAN;
if (fs->fs_clean == 0) {
fs->fs_flags |= FS_UNCLEAN;
@@ -782,8 +782,8 @@ loop:
* Common code for mount and mountroot
*/
static int
-ffs_mountfs(devvp, mp, td)
- struct vnode *devvp;
+ffs_mountfs(odevvp, mp, td)
+ struct vnode *odevvp;
struct mount *mp;
struct thread *td;
{
@@ -794,6 +794,7 @@ ffs_mountfs(devvp, mp, td)
struct ucred *cred;
struct g_consumer *cp;
struct mount *nmp;
+ struct vnode *devvp;
int candelete, canspeedup;
off_t loc;
@@ -802,11 +803,13 @@ ffs_mountfs(devvp, mp, td)
cred = td ? td->td_ucred : NOCRED;
ronly = (mp->mnt_flag & MNT_RDONLY) != 0;
+ devvp = mntfs_allocvp(mp, odevvp);
+ VOP_UNLOCK(odevvp);
KASSERT(devvp->v_type == VCHR, ("reclaimed devvp"));
dev = devvp->v_rdev;
if (atomic_cmpset_acq_ptr((uintptr_t *)&dev->si_mountpt, 0,
(uintptr_t)mp) == 0) {
- VOP_UNLOCK(devvp);
+ mntfs_freevp(devvp);
return (EBUSY);
}
g_topology_lock();
@@ -814,12 +817,14 @@ ffs_mountfs(devvp, mp, td)
g_topology_unlock();
if (error != 0) {
atomic_store_rel_ptr((uintptr_t *)&dev->si_mountpt, 0);
- VOP_UNLOCK(devvp);
+ mntfs_freevp(devvp);
return (error);
}
dev_ref(dev);
devvp->v_bufobj.bo_ops = &ffs_ops;
- VOP_UNLOCK(devvp);
+ BO_LOCK(&odevvp->v_bufobj);
+ odevvp->v_bufobj.bo_flag |= BO_NOBUFS;
+ BO_UNLOCK(&odevvp->v_bufobj);
if (dev->si_iosize_max != 0)
mp->mnt_iosize_max = dev->si_iosize_max;
if (mp->mnt_iosize_max > MAXPHYS)
@@ -1020,6 +1025,7 @@ ffs_mountfs(devvp, mp, td)
ump->um_mountp = mp;
ump->um_dev = dev;
ump->um_devvp = devvp;
+ ump->um_odevvp = odevvp;
ump->um_nindir = fs->fs_nindir;
ump->um_bptrtodb = fs->fs_fsbtodb;
ump->um_seqinc = fs->fs_frag;
@@ -1099,7 +1105,11 @@ out:
free(ump, M_UFSMNT);
mp->mnt_data = NULL;
}
+ BO_LOCK(&odevvp->v_bufobj);
+ odevvp->v_bufobj.bo_flag &= ~BO_NOBUFS;
+ BO_UNLOCK(&odevvp->v_bufobj);
atomic_store_rel_ptr((uintptr_t *)&dev->si_mountpt, 0);
+ mntfs_freevp(devvp);
dev_rel(dev);
return (error);
}
@@ -1304,8 +1314,12 @@ ffs_unmount(mp, mntflags)
}
g_vfs_close(ump->um_cp);
g_topology_unlock();
+ BO_LOCK(&ump->um_odevvp->v_bufobj);
+ ump->um_odevvp->v_bufobj.bo_flag &= ~BO_NOBUFS;
+ BO_UNLOCK(&ump->um_odevvp->v_bufobj);
atomic_store_rel_ptr((uintptr_t *)&ump->um_dev->si_mountpt, 0);
- vrele(ump->um_devvp);
+ mntfs_freevp(ump->um_devvp);
+ vrele(ump->um_odevvp);
dev_rel(ump->um_dev);
mtx_destroy(UFS_MTX(ump));
if (mp->mnt_gjprovider != NULL) {
@@ -2293,7 +2307,19 @@ ffs_geom_strategy(struct bufobj *bo, struct buf *bp)
struct buf *tbp;
int error, nocopy;
+ /*
+ * This is the bufobj strategy for the private VCHR vnodes
+ * used by FFS to access the underlying storage device.
+ * We override the default bufobj strategy and thus bypass
+ * VOP_STRATEGY() for these vnodes.
+ */
vp = bo2vnode(bo);
+ KASSERT(bp->b_vp == NULL || bp->b_vp->v_type != VCHR ||
+ bp->b_vp->v_rdev == NULL ||
+ bp->b_vp->v_rdev->si_mountpt == NULL ||
+ VFSTOUFS(bp->b_vp->v_rdev->si_mountpt) == NULL ||
+ vp == VFSTOUFS(bp->b_vp->v_rdev->si_mountpt)->um_devvp,
+ ("ffs_geom_strategy() with wrong vp"));
if (bp->b_iocmd == BIO_WRITE) {
if ((bp->b_flags & B_VALIDSUSPWRT) == 0 &&
bp->b_vp != NULL && bp->b_vp->v_mount != NULL &&
diff --git a/sys/ufs/ufs/ufsmount.h b/sys/ufs/ufs/ufsmount.h
index 493571442d67..2d669338f98c 100644
--- a/sys/ufs/ufs/ufsmount.h
+++ b/sys/ufs/ufs/ufsmount.h
@@ -83,7 +83,8 @@ struct ufsmount {
struct cdev *um_dev; /* (r) device mounted */
struct g_consumer *um_cp; /* (r) GEOM access point */
struct bufobj *um_bo; /* (r) Buffer cache object */
- struct vnode *um_devvp; /* (r) blk dev mounted vnode */
+ struct vnode *um_odevvp; /* (r) devfs dev vnode */
+ struct vnode *um_devvp; /* (r) mntfs private vnode */
u_long um_fstype; /* (c) type of filesystem */
struct fs *um_fs; /* (r) pointer to superblock */
struct ufs_extattr_per_mount um_extattr; /* (c) extended attrs */