Remove v_bufobj from struct vnode, but move v_object into vnode. Define struct vnode_bo which consists of struct vnode and bufobj. It is backed by separate zone.
If a filesystem uses buffer cache, as indicated by MNTK_USES_BCACHE mount point flag, getnewvnode() allocates node_bo instead of vnode, and marks the vnode with VIRF_BUFOBJ flag. For convenience, syncer vnodes are also automatically extended with bufobj.
I considered not doing the co-location for vnode/bufobj, putting the bufobj into inodes for filesystems needed byffers. This appeared to be too problematic due to the lifetime issues, not for filesystems itself, but for use of vnodes from other filesystems. For instance devvp buffers cannot be reliably handled if bufobj for devvp is located in cdev_priv (devfs spec inode).
Right now this shrinks struct vnode from 448 to 304 bytes for filesystems that do not use buffer cache, i.e. at least zfs/tmpfs/nullfs. Filesystems using buffer cache still gets the 'large' struct vnode + struct bufobj blob when allocating the vnode.