diff options
author | Chuck Silvers <chs@FreeBSD.org> | 2022-06-22 21:52:42 +0000 |
---|---|---|
committer | Chuck Silvers <chs@FreeBSD.org> | 2022-06-22 21:57:29 +0000 |
commit | f1b4324b81a5b09094111c378ed5cef3b5f8b299 (patch) | |
tree | 8d45342490b12c6f8b3abea0b02a0a8cceeb5839 | |
parent | 5d3fe02c5a7649d35b9eaae1357376a643addb70 (diff) | |
download | src-f1b4324b81a5b09094111c378ed5cef3b5f8b299.tar.gz src-f1b4324b81a5b09094111c378ed5cef3b5f8b299.zip |
ffs: fix vn_read_from_obj() usage for PAGE_SIZE > block size
vn_read_from_obj() requires that all pages of a vnode (except the last
partial page) be either completely valid or completely invalid,
but for file systems with block size smaller than PAGE_SIZE,
partially valid pages may exist anywhere in the file.
Do not enable the vn_read_from_obj() path in this case.
Reviewed by: mckusick, kib, markj
Sponsored by: Netflix
Differential Revision: https://reviews.freebsd.org/D34836
-rw-r--r-- | sys/ufs/ffs/ffs_vfsops.c | 2 | ||||
-rw-r--r-- | sys/ufs/ufs/ufs_vnops.c | 3 | ||||
-rw-r--r-- | sys/ufs/ufs/ufsmount.h | 1 |
3 files changed, 5 insertions, 1 deletions
diff --git a/sys/ufs/ffs/ffs_vfsops.c b/sys/ufs/ffs/ffs_vfsops.c index 0dc5753e0172..d1414b81bb1e 100644 --- a/sys/ufs/ffs/ffs_vfsops.c +++ b/sys/ufs/ffs/ffs_vfsops.c @@ -801,6 +801,7 @@ ffs_reload(struct mount *mp, int flags) sblockloc = fs->fs_sblockloc; bcopy(newfs, fs, (u_int)fs->fs_sbsize); brelse(bp); + ump->um_bsize = fs->fs_bsize; ump->um_maxsymlinklen = fs->fs_maxsymlinklen; ffs_oldfscompat_read(fs, VFSTOUFS(mp), sblockloc); UFS_LOCK(ump); @@ -1064,6 +1065,7 @@ ffs_mountfs(odevvp, mp, td) vfs_rel(nmp); vfs_getnewfsid(mp); } + ump->um_bsize = fs->fs_bsize; ump->um_maxsymlinklen = fs->fs_maxsymlinklen; MNT_ILOCK(mp); mp->mnt_flag |= MNT_LOCAL; diff --git a/sys/ufs/ufs/ufs_vnops.c b/sys/ufs/ufs/ufs_vnops.c index 2def837c157a..0a7e6a7875ec 100644 --- a/sys/ufs/ufs/ufs_vnops.c +++ b/sys/ufs/ufs/ufs_vnops.c @@ -314,7 +314,8 @@ ufs_open(struct vop_open_args *ap) ip = VTOI(vp); vnode_create_vobject(vp, DIP(ip, i_size), ap->a_td); - if (vp->v_type == VREG && (vn_irflag_read(vp) & VIRF_PGREAD) == 0) { + if (vp->v_type == VREG && (vn_irflag_read(vp) & VIRF_PGREAD) == 0 && + ip->i_ump->um_bsize >= PAGE_SIZE) { vn_irflag_set_cond(vp, VIRF_PGREAD); } diff --git a/sys/ufs/ufs/ufsmount.h b/sys/ufs/ufs/ufsmount.h index a1a2cdb3f741..d4225eee64dd 100644 --- a/sys/ufs/ufs/ufsmount.h +++ b/sys/ufs/ufs/ufsmount.h @@ -96,6 +96,7 @@ struct ufsmount { u_long um_nindir; /* (c) indirect ptrs per blk */ u_long um_bptrtodb; /* (c) indir disk block ptr */ u_long um_seqinc; /* (c) inc between seq blocks */ + u_long um_bsize; /* (c) fs block size */ uint64_t um_maxsymlinklen; /* (c) max size of short symlink */ struct mtx um_lock; /* (c) Protects ufsmount & fs */ |