diff options
Diffstat (limited to 'sys/fs')
61 files changed, 1478 insertions, 700 deletions
| diff --git a/sys/fs/cd9660/cd9660_lookup.c b/sys/fs/cd9660/cd9660_lookup.c index 75fcdc9152cd..4d0bf73ab235 100644 --- a/sys/fs/cd9660/cd9660_lookup.c +++ b/sys/fs/cd9660/cd9660_lookup.c @@ -386,7 +386,7 @@ found:  			return (error);  		*vpp = tdp;  	} else if (dp->i_number == i_ino) { -		VREF(vdp);	/* we want ourself, ie "." */ +		vref(vdp);	/* we want ourself, ie "." */  		/*  		 * When we lookup "." we still can be asked to lock it  		 * differently. diff --git a/sys/fs/cd9660/cd9660_vfsops.c b/sys/fs/cd9660/cd9660_vfsops.c index b4db4c4f7331..ce6d03b73290 100644 --- a/sys/fs/cd9660/cd9660_vfsops.c +++ b/sys/fs/cd9660/cd9660_vfsops.c @@ -617,13 +617,13 @@ cd9660_fhtovp(struct mount *mp, struct fid *fhp, int flags, struct vnode **vpp)  #endif  	if ((error = VFS_VGET(mp, ifh.ifid_ino, LK_EXCLUSIVE, &nvp)) != 0) { -		*vpp = NULLVP; +		*vpp = NULL;  		return (error);  	}  	ip = VTOI(nvp);  	if (ip->inode.iso_mode == 0) {  		vput(nvp); -		*vpp = NULLVP; +		*vpp = NULL;  		return (ESTALE);  	}  	*vpp = nvp; @@ -704,7 +704,7 @@ cd9660_vget_internal(struct mount *mp, ino_t ino, int flags,  	/* Allocate a new vnode/iso_node. */  	if ((error = getnewvnode("isofs", mp, &cd9660_vnodeops, &vp)) != 0) { -		*vpp = NULLVP; +		*vpp = NULL;  		return (error);  	}  	ip = malloc(sizeof(struct iso_node), M_ISOFSNODE, @@ -717,7 +717,7 @@ cd9660_vget_internal(struct mount *mp, ino_t ino, int flags,  	error = insmntque(vp, mp);  	if (error != 0) {  		free(ip, M_ISOFSNODE); -		*vpp = NULLVP; +		*vpp = NULL;  		return (error);  	}  	error = vfs_hash_insert(vp, ino, flags, td, vpp, cd9660_vfs_hash_cmp, diff --git a/sys/fs/cd9660/cd9660_vnops.c b/sys/fs/cd9660/cd9660_vnops.c index c4d0e6ba7b30..4a2b80a7ccdd 100644 --- a/sys/fs/cd9660/cd9660_vnops.c +++ b/sys/fs/cd9660/cd9660_vnops.c @@ -124,7 +124,7 @@ cd9660_access(struct vop_access_args *ap)  	uid_t uid;  	gid_t gid; -	if (vp->v_type == VCHR || vp->v_type == VBLK) +	if (VN_ISDEV(vp))  		return (EOPNOTSUPP);  	/* @@ -162,7 +162,7 @@ cd9660_open(struct vop_open_args *ap)  	struct vnode *vp = ap->a_vp;  	struct iso_node *ip = VTOI(vp); -	if (vp->v_type == VCHR || vp->v_type == VBLK) +	if (VN_ISDEV(vp))  		return (EOPNOTSUPP);  	vnode_create_vobject(vp, ip->i_size, ap->a_td); @@ -191,7 +191,7 @@ cd9660_getattr(struct vop_getattr_args *ap)  	vap->va_atime	= ip->inode.iso_atime;  	vap->va_mtime	= ip->inode.iso_mtime;  	vap->va_ctime	= ip->inode.iso_ctime; -	vap->va_rdev	= ip->inode.iso_rdev; +	vap->va_rdev	= VN_ISDEV(vp) ? ip->inode.iso_rdev : NODEV;  	vap->va_size	= (u_quad_t) ip->i_size;  	if (ip->i_size == 0 && (vap->va_mode & S_IFMT) == S_IFLNK) { @@ -242,7 +242,7 @@ cd9660_ioctl(struct vop_ioctl_args *ap)  		VOP_UNLOCK(vp);  		return (EBADF);  	} -	if (vp->v_type == VCHR || vp->v_type == VBLK) { +	if (VN_ISDEV(vp)) {  		VOP_UNLOCK(vp);  		return (EOPNOTSUPP);  	} @@ -280,7 +280,7 @@ cd9660_read(struct vop_read_args *ap)  	int seqcount;  	long size, n, on; -	if (vp->v_type == VCHR || vp->v_type == VBLK) +	if (VN_ISDEV(vp))  		return (EOPNOTSUPP);  	seqcount = ap->a_ioflag >> IO_SEQSHIFT; @@ -711,7 +711,7 @@ cd9660_strategy(struct vop_strategy_args *ap)  	struct bufobj *bo;  	ip = VTOI(vp); -	if (vp->v_type == VBLK || vp->v_type == VCHR) +	if (VN_ISDEV(vp))  		panic("cd9660_strategy: spec");  	if (bp->b_blkno == bp->b_lblkno) {  		bp->b_blkno = (ip->iso_start + bp->b_lblkno) << @@ -818,7 +818,7 @@ cd9660_getpages(struct vop_getpages_args *ap)  	struct vnode *vp;  	vp = ap->a_vp; -	if (vp->v_type == VCHR || vp->v_type == VBLK) +	if (VN_ISDEV(vp))  		return (EOPNOTSUPP);  	if (use_buf_pager) diff --git a/sys/fs/cuse/cuse.c b/sys/fs/cuse/cuse.c index d63a7d4691cf..b2524324584a 100644 --- a/sys/fs/cuse/cuse.c +++ b/sys/fs/cuse/cuse.c @@ -195,12 +195,14 @@ static const struct filterops cuse_client_kqfilter_read_ops = {  	.f_isfd = 1,  	.f_detach = cuse_client_kqfilter_read_detach,  	.f_event = cuse_client_kqfilter_read_event, +	.f_copy = knote_triv_copy,  };  static const struct filterops cuse_client_kqfilter_write_ops = {  	.f_isfd = 1,  	.f_detach = cuse_client_kqfilter_write_detach,  	.f_event = cuse_client_kqfilter_write_event, +	.f_copy = knote_triv_copy,  };  static d_open_t cuse_client_open; diff --git a/sys/fs/deadfs/dead_vnops.c b/sys/fs/deadfs/dead_vnops.c index 296cf058f8c9..137c86b65058 100644 --- a/sys/fs/deadfs/dead_vnops.c +++ b/sys/fs/deadfs/dead_vnops.c @@ -122,18 +122,18 @@ dead_read(struct vop_read_args *ap)  {  	/* -	 * Return EOF for tty devices, EIO for others +	 * Return EOF for tty devices, ENXIO for others  	 */ -	if ((ap->a_vp->v_vflag & VV_ISTTY) == 0) -		return (EIO); -	return (0); +	if (ap->a_vp->v_vflag & VV_ISTTY) +		return (0); +	return (ENXIO);  }  int  dead_write(struct vop_write_args *ap)  { -	return (EIO); +	return (ENXIO);  }  int diff --git a/sys/fs/devfs/devfs_dir.c b/sys/fs/devfs/devfs_dir.c index 3dc87538017d..aad87606e738 100644 --- a/sys/fs/devfs/devfs_dir.c +++ b/sys/fs/devfs/devfs_dir.c @@ -162,7 +162,7 @@ int  devfs_pathpath(const char *p1, const char *p2)  { -	for (;;p1++, p2++) { +	for (;; p1++, p2++) {  		if (*p1 != *p2) {  			if (*p1 == '/' && *p2 == '\0')  				return (1); diff --git a/sys/fs/devfs/devfs_int.h b/sys/fs/devfs/devfs_int.h index 916297425b53..9fa75c0e90ad 100644 --- a/sys/fs/devfs/devfs_int.h +++ b/sys/fs/devfs/devfs_int.h @@ -67,6 +67,7 @@ struct cdev_priv {  	void			*cdp_dtr_cb_arg;  	LIST_HEAD(, cdev_privdata) cdp_fdpriv; +	u_int			cdp_fdpriv_dtrc;  	struct mtx		cdp_threadlock;  }; diff --git a/sys/fs/devfs/devfs_vnops.c b/sys/fs/devfs/devfs_vnops.c index 3a64c205186f..323f1e0fa961 100644 --- a/sys/fs/devfs/devfs_vnops.c +++ b/sys/fs/devfs/devfs_vnops.c @@ -200,14 +200,25 @@ devfs_foreach_cdevpriv(struct cdev *dev, int (*cb)(void *data, void *arg),  void  devfs_destroy_cdevpriv(struct cdev_privdata *p)  { +	struct file *fp; +	struct cdev_priv *cdp;  	mtx_assert(&cdevpriv_mtx, MA_OWNED); -	KASSERT(p->cdpd_fp->f_cdevpriv == p, -	    ("devfs_destoy_cdevpriv %p != %p", p->cdpd_fp->f_cdevpriv, p)); -	p->cdpd_fp->f_cdevpriv = NULL; +	fp = p->cdpd_fp; +	KASSERT(fp->f_cdevpriv == p, +	    ("devfs_destoy_cdevpriv %p != %p", fp->f_cdevpriv, p)); +	cdp = cdev2priv((struct cdev *)fp->f_data); +	cdp->cdp_fdpriv_dtrc++; +	fp->f_cdevpriv = NULL;  	LIST_REMOVE(p, cdpd_list);  	mtx_unlock(&cdevpriv_mtx);  	(p->cdpd_dtr)(p->cdpd_data); +	mtx_lock(&cdevpriv_mtx); +	MPASS(cdp->cdp_fdpriv_dtrc >= 1); +	cdp->cdp_fdpriv_dtrc--; +	if (cdp->cdp_fdpriv_dtrc == 0) +		wakeup(&cdp->cdp_fdpriv_dtrc); +	mtx_unlock(&cdevpriv_mtx);  	free(p, M_CDEVPDATA);  } @@ -1061,7 +1072,7 @@ devfs_lookupx(struct vop_lookup_args *ap, int *dm_unlock)  	mp = dvp->v_mount;  	dmp = VFSTODEVFS(mp);  	dd = dvp->v_data; -	*vpp = NULLVP; +	*vpp = NULL;  	if ((flags & ISLASTCN) && nameiop == RENAME)  		return (EOPNOTSUPP); @@ -1080,7 +1091,7 @@ devfs_lookupx(struct vop_lookup_args *ap, int *dm_unlock)  		if ((flags & ISLASTCN) && nameiop != LOOKUP)  			return (EINVAL);  		*vpp = dvp; -		VREF(dvp); +		vref(dvp);  		return (0);  	} @@ -1170,7 +1181,7 @@ devfs_lookupx(struct vop_lookup_args *ap, int *dm_unlock)  		if (error)  			return (error);  		if (*vpp == dvp) { -			VREF(dvp); +			vref(dvp);  			*vpp = dvp;  			return (0);  		} diff --git a/sys/fs/ext2fs/ext2_lookup.c b/sys/fs/ext2fs/ext2_lookup.c index c80e0f99ab56..bb830d07b126 100644 --- a/sys/fs/ext2fs/ext2_lookup.c +++ b/sys/fs/ext2fs/ext2_lookup.c @@ -579,7 +579,7 @@ found:  		if (dd_ino != NULL)  			return (0);  		if (dp->i_number == ino) { -			VREF(vdp); +			vref(vdp);  			*vpp = vdp;  			return (0);  		} @@ -675,7 +675,7 @@ found:  		}  		*vpp = tdp;  	} else if (dp->i_number == ino) { -		VREF(vdp);	/* we want ourself, ie "." */ +		vref(vdp);	/* we want ourself, ie "." */  		/*  		 * When we lookup "." we still can be asked to lock it  		 * differently. diff --git a/sys/fs/ext2fs/ext2_vfsops.c b/sys/fs/ext2fs/ext2_vfsops.c index 9e7a03fffd71..0f3808a7c747 100644 --- a/sys/fs/ext2fs/ext2_vfsops.c +++ b/sys/fs/ext2fs/ext2_vfsops.c @@ -1334,14 +1334,14 @@ ext2_fhtovp(struct mount *mp, struct fid *fhp, int flags, struct vnode **vpp)  	error = VFS_VGET(mp, ufhp->ufid_ino, LK_EXCLUSIVE, &nvp);  	if (error) { -		*vpp = NULLVP; +		*vpp = NULL;  		return (error);  	}  	ip = VTOI(nvp);  	if (ip->i_mode == 0 ||  	    ip->i_gen != ufhp->ufid_gen || ip->i_nlink <= 0) {  		vput(nvp); -		*vpp = NULLVP; +		*vpp = NULL;  		return (ESTALE);  	}  	*vpp = nvp; diff --git a/sys/fs/ext2fs/ext2_vnops.c b/sys/fs/ext2fs/ext2_vnops.c index 064c10bd18b2..35e7ca77c732 100644 --- a/sys/fs/ext2fs/ext2_vnops.c +++ b/sys/fs/ext2fs/ext2_vnops.c @@ -222,7 +222,7 @@ ext2_itimes_locked(struct vnode *vp)  	ip = VTOI(vp);  	if ((ip->i_flag & (IN_ACCESS | IN_CHANGE | IN_UPDATE)) == 0)  		return; -	if ((vp->v_type == VBLK || vp->v_type == VCHR)) +	if (VN_ISDEV(vp))  		ip->i_flag |= IN_LAZYMOD;  	else  		ip->i_flag |= IN_MODIFIED; @@ -276,7 +276,7 @@ static int  ext2_open(struct vop_open_args *ap)  { -	if (ap->a_vp->v_type == VBLK || ap->a_vp->v_type == VCHR) +	if (VN_ISDEV(ap->a_vp))  		return (EOPNOTSUPP);  	/* @@ -360,7 +360,7 @@ ext2_getattr(struct vop_getattr_args *ap)  	vap->va_nlink = ip->i_nlink;  	vap->va_uid = ip->i_uid;  	vap->va_gid = ip->i_gid; -	vap->va_rdev = ip->i_rdev; +	vap->va_rdev = VN_ISDEV(vp) ? ip->i_rdev : NODEV;  	vap->va_size = ip->i_size;  	vap->va_atime.tv_sec = ip->i_atime;  	vap->va_atime.tv_nsec = E2DI_HAS_XTIME(ip) ? ip->i_atimensec : 0; @@ -905,7 +905,7 @@ abortit:  		error = ext2_checkpath(ip, dp, tcnp->cn_cred);  		if (error)  			goto out; -		VREF(tdvp); +		vref(tdvp);  		error = vfs_relookup(tdvp, &tvp, tcnp, true);  		if (error)  			goto out; @@ -1031,7 +1031,7 @@ abortit:  	 */  	fcnp->cn_flags &= ~MODMASK;  	fcnp->cn_flags |= LOCKPARENT | LOCKLEAF; -	VREF(fdvp); +	vref(fdvp);  	error = vfs_relookup(fdvp, &fvp, fcnp, true);  	if (error == 0)  		vrele(fdvp); @@ -1571,7 +1571,7 @@ ext2_strategy(struct vop_strategy_args *ap)  	daddr_t blkno;  	int error; -	if (vp->v_type == VBLK || vp->v_type == VCHR) +	if (VN_ISDEV(vp))  		panic("ext2_strategy: spec");  	if (bp->b_blkno == bp->b_lblkno) {  		if (VTOI(ap->a_vp)->i_flag & IN_E4EXTENTS) @@ -1733,7 +1733,7 @@ ext2_deleteextattr(struct vop_deleteextattr_args *ap)  	if (!EXT2_HAS_COMPAT_FEATURE(ip->i_e2fs, EXT2F_COMPAT_EXT_ATTR))  		return (EOPNOTSUPP); -	if (ap->a_vp->v_type == VCHR || ap->a_vp->v_type == VBLK) +	if (VN_ISDEV(ap->a_vp))  		return (EOPNOTSUPP);  	error = extattr_check_cred(ap->a_vp, ap->a_attrnamespace, @@ -1771,7 +1771,7 @@ ext2_getextattr(struct vop_getextattr_args *ap)  	if (!EXT2_HAS_COMPAT_FEATURE(ip->i_e2fs, EXT2F_COMPAT_EXT_ATTR))  		return (EOPNOTSUPP); -	if (ap->a_vp->v_type == VCHR || ap->a_vp->v_type == VBLK) +	if (VN_ISDEV(ap->a_vp))  		return (EOPNOTSUPP);  	error = extattr_check_cred(ap->a_vp, ap->a_attrnamespace, @@ -1814,7 +1814,7 @@ ext2_listextattr(struct vop_listextattr_args *ap)  	if (!EXT2_HAS_COMPAT_FEATURE(ip->i_e2fs, EXT2F_COMPAT_EXT_ATTR))  		return (EOPNOTSUPP); -	if (ap->a_vp->v_type == VCHR || ap->a_vp->v_type == VBLK) +	if (VN_ISDEV(ap->a_vp))  		return (EOPNOTSUPP);  	error = extattr_check_cred(ap->a_vp, ap->a_attrnamespace, @@ -1855,7 +1855,7 @@ ext2_setextattr(struct vop_setextattr_args *ap)  	if (!EXT2_HAS_COMPAT_FEATURE(ip->i_e2fs, EXT2F_COMPAT_EXT_ATTR))  		return (EOPNOTSUPP); -	if (ap->a_vp->v_type == VCHR || ap->a_vp->v_type == VBLK) +	if (VN_ISDEV(ap->a_vp))  		return (EOPNOTSUPP);  	error = extattr_check_cred(ap->a_vp, ap->a_attrnamespace, diff --git a/sys/fs/fdescfs/fdesc_vnops.c b/sys/fs/fdescfs/fdesc_vnops.c index 58a22b8bdc50..c1188c3819e7 100644 --- a/sys/fs/fdescfs/fdesc_vnops.c +++ b/sys/fs/fdescfs/fdesc_vnops.c @@ -196,7 +196,7 @@ loop:  	if (error != 0) {  		vgone(vp);  		vput(vp); -		*vpp = NULLVP; +		*vpp = NULL;  		return (error);  	} @@ -211,7 +211,7 @@ loop:  		mtx_unlock(&fdesc_hashmtx);  		vgone(vp);  		vput(vp); -		*vpp = NULLVP; +		*vpp = NULL;  		return (-1);  	} @@ -227,7 +227,7 @@ loop:  			vput(vp);  			/* If we didn't get it, return no vnode. */  			if (error) -				vp2 = NULLVP; +				vp2 = NULL;  			*vpp = vp2;  			return (error);  		} @@ -301,7 +301,7 @@ fdesc_lookup(struct vop_lookup_args *ap)  	if (cnp->cn_namelen == 1 && *pname == '.') {  		*vpp = dvp; -		VREF(dvp); +		vref(dvp);  		return (0);  	} diff --git a/sys/fs/fuse/fuse_device.c b/sys/fs/fuse/fuse_device.c index 57b3559731f7..cee477865c42 100644 --- a/sys/fs/fuse/fuse_device.c +++ b/sys/fs/fuse/fuse_device.c @@ -126,11 +126,13 @@ static const struct filterops fuse_device_rfiltops = {  	.f_isfd = 1,  	.f_detach = fuse_device_filt_detach,  	.f_event = fuse_device_filt_read, +	.f_copy = knote_triv_copy,  };  static const struct filterops fuse_device_wfiltops = {  	.f_isfd = 1,  	.f_event = fuse_device_filt_write, +	.f_copy = knote_triv_copy,  };  /**************************** @@ -548,6 +550,13 @@ fuse_device_write(struct cdev *dev, struct uio *uio, int ioflag)  	} else if (ohead.unique == 0){  		/* unique == 0 means asynchronous notification */  		SDT_PROBE1(fusefs, , device, fuse_device_write_notify, &ohead); +		if (data->mp == NULL) { +			SDT_PROBE2(fusefs, , device, trace, 1, +				"asynchronous notification before mount" +				" or after unmount"); +			return (EXTERROR(ENODEV, +				"This FUSE session is not mounted")); +		}  		mp = data->mp;  		vfs_ref(mp);  		err = vfs_busy(mp, 0); diff --git a/sys/fs/fuse/fuse_ipc.c b/sys/fs/fuse/fuse_ipc.c index a751c09159ff..bc36f0070d7d 100644 --- a/sys/fs/fuse/fuse_ipc.c +++ b/sys/fs/fuse/fuse_ipc.c @@ -193,7 +193,6 @@ fuse_interrupt_send(struct fuse_ticket *otick, int err)  	struct fuse_data *data = otick->tk_data;  	struct fuse_ticket *tick, *xtick;  	struct ucred reused_creds; -	gid_t reused_groups[1];  	if (otick->irq_unique == 0) {  		/*  @@ -237,8 +236,7 @@ fuse_interrupt_send(struct fuse_ticket *otick, int err)  		 */  		ftick_hdr = fticket_in_header(otick);  		reused_creds.cr_uid = ftick_hdr->uid; -		reused_groups[0] = ftick_hdr->gid; -		reused_creds.cr_groups = reused_groups; +		reused_creds.cr_gid = ftick_hdr->gid;  		fdisp_init(&fdi, sizeof(*fii));  		fdisp_make_pid(&fdi, FUSE_INTERRUPT, data, ftick_hdr->nodeid,  			ftick_hdr->pid, &reused_creds); @@ -696,7 +694,7 @@ fuse_body_audit(struct fuse_ticket *ftick, size_t blen)  		break;  	case FUSE_FORGET: -		panic("FUSE: a handler has been intalled for FUSE_FORGET"); +		panic("FUSE: a handler has been installed for FUSE_FORGET");  		break;  	case FUSE_GETATTR: diff --git a/sys/fs/fuse/fuse_vfsops.c b/sys/fs/fuse/fuse_vfsops.c index 1b858a988289..b617925c4e5f 100644 --- a/sys/fs/fuse/fuse_vfsops.c +++ b/sys/fs/fuse/fuse_vfsops.c @@ -278,13 +278,13 @@ fuse_vfsop_fhtovp(struct mount *mp, struct fid *fhp, int flags,  	error = VFS_VGET(mp, ffhp->nid, LK_EXCLUSIVE, &nvp);  	if (error) { -		*vpp = NULLVP; +		*vpp = NULL;  		return (error);  	}  	fvdat = VTOFUD(nvp);  	if (fvdat->generation != ffhp->gen ) {  		vput(nvp); -		*vpp = NULLVP; +		*vpp = NULL;  		return (ESTALE);  	}  	*vpp = nvp; diff --git a/sys/fs/fuse/fuse_vnops.c b/sys/fs/fuse/fuse_vnops.c index b782146b7278..97aa23bfb0b0 100644 --- a/sys/fs/fuse/fuse_vnops.c +++ b/sys/fs/fuse/fuse_vnops.c @@ -284,7 +284,7 @@ fuse_flush(struct vnode *vp, struct ucred *cred, pid_t pid, int fflag)  	struct mount *mp = vnode_mount(vp);  	int err; -	if (fsess_not_impl(vnode_mount(vp), FUSE_FLUSH)) +	if (fsess_not_impl(mp, FUSE_FLUSH))  		return 0;  	err = fuse_filehandle_getrw(vp, fflag, &fufh, cred, pid); @@ -292,7 +292,7 @@ fuse_flush(struct vnode *vp, struct ucred *cred, pid_t pid, int fflag)  		return err;  	if (fufh->fuse_open_flags & FOPEN_NOFLUSH && -	    (!fsess_opt_writeback(vnode_mount(vp)))) +	    (!fsess_opt_writeback(mp)))  		return (0);  	fdisp_init(&fdi, sizeof(*ffi)); @@ -795,11 +795,15 @@ fuse_vnop_close(struct vop_close_args *ap)  	struct mount *mp = vnode_mount(vp);  	struct ucred *cred = ap->a_cred;  	int fflag = ap->a_fflag; -	struct thread *td = ap->a_td; -	pid_t pid = td->td_proc->p_pid; +	struct thread *td;  	struct fuse_vnode_data *fvdat = VTOFUD(vp); +	pid_t pid;  	int err = 0; +	/* NB: a_td will be NULL from some async kernel contexts */ +	td = ap->a_td ? ap->a_td : curthread; +	pid = td->td_proc->p_pid; +  	if (fuse_isdeadfs(vp))  		return 0;  	if (vnode_isdir(vp)) @@ -838,7 +842,7 @@ fuse_vnop_close(struct vop_close_args *ap)  	}  	/* TODO: close the file handle, if we're sure it's no longer used */  	if ((fvdat->flag & FN_SIZECHANGE) != 0) { -		fuse_vnode_savesize(vp, cred, td->td_proc->p_pid); +		fuse_vnode_savesize(vp, cred, pid);  	}  	return err;  } @@ -953,7 +957,7 @@ fuse_vnop_copy_file_range(struct vop_copy_file_range_args *ap)  		*ap->a_outoffp += fwo->size;  		fuse_internal_clear_suid_on_write(outvp, outcred, td);  		if (*ap->a_outoffp > outfvdat->cached_attrs.va_size) { -                        fuse_vnode_setsize(outvp, *ap->a_outoffp, false); +			fuse_vnode_setsize(outvp, *ap->a_outoffp, false);  			getnanouptime(&outfvdat->last_local_modify);  		}  		fuse_vnode_update(invp, FN_ATIMECHANGE); @@ -1748,7 +1752,7 @@ fuse_vnop_open(struct vop_open_args *ap)  	if (fuse_isdeadfs(vp))  		return (EXTERROR(ENXIO, "This FUSE session is about "  		    "to be closed")); -	if (vp->v_type == VCHR || vp->v_type == VBLK || vp->v_type == VFIFO) +	if (VN_ISDEV(vp) || vp->v_type == VFIFO)  		return (EXTERROR(EOPNOTSUPP, "Unsupported vnode type",  		    vp->v_type));  	if ((a_mode & (FREAD | FWRITE | FEXEC)) == 0) @@ -2752,7 +2756,7 @@ fuse_vnop_setextattr(struct vop_setextattr_args *ap)  		 */  		if (fsess_not_impl(mp, FUSE_REMOVEXATTR))  			return (EXTERROR(EOPNOTSUPP, "This server does not " -			    "implement removing extended attributess")); +			    "implement removing extended attributes"));  		else  			return (EXTERROR(EINVAL, "DELETEEXTATTR should be used "  			    "to remove extattrs")); diff --git a/sys/fs/msdosfs/bootsect.h b/sys/fs/msdosfs/bootsect.h index 170d94cb9512..94b1137a153e 100644 --- a/sys/fs/msdosfs/bootsect.h +++ b/sys/fs/msdosfs/bootsect.h @@ -20,7 +20,7 @@  /*   * Format of a boot sector.  This is the first sector on a DOS floppy disk - * or the fist sector of a partition on a hard disk.  But, it is not the + * or the first sector of a partition on a hard disk.  But, it is not the   * first sector of a partitioned hard disk.   */  struct bootsector33 { diff --git a/sys/fs/msdosfs/msdosfs_lookup.c b/sys/fs/msdosfs/msdosfs_lookup.c index 8ab6d35a2685..58ce8eff9dbd 100644 --- a/sys/fs/msdosfs/msdosfs_lookup.c +++ b/sys/fs/msdosfs/msdosfs_lookup.c @@ -515,7 +515,7 @@ foundroot:  		 * Save directory inode pointer in ndp->ni_dvp for dirremove().  		 */  		if (dp->de_StartCluster == scn && isadir) {	/* "." */ -			VREF(vdp); +			vref(vdp);  			*vpp = vdp;  			return (0);  		} @@ -602,7 +602,7 @@ foundroot:  			msdosfs_integrity_error(pmp);  			return (EBADF);  		} -		VREF(vdp);	/* we want ourself, ie "." */ +		vref(vdp);	/* we want ourself, ie "." */  		*vpp = vdp;  	} else {  		if ((error = deget(pmp, cluster, blkoff, LK_EXCLUSIVE, diff --git a/sys/fs/msdosfs/msdosfs_vfsops.c b/sys/fs/msdosfs/msdosfs_vfsops.c index 4431d36c8a8e..30c63cfa8a35 100644 --- a/sys/fs/msdosfs/msdosfs_vfsops.c +++ b/sys/fs/msdosfs/msdosfs_vfsops.c @@ -1184,7 +1184,7 @@ msdosfs_fhtovp(struct mount *mp, struct fid *fhp, int flags, struct vnode **vpp)  	error = deget(pmp, defhp->defid_dirclust, defhp->defid_dirofs,  	    LK_EXCLUSIVE, &dep);  	if (error) { -		*vpp = NULLVP; +		*vpp = NULL;  		return (error);  	}  	*vpp = DETOV(dep); diff --git a/sys/fs/msdosfs/msdosfs_vnops.c b/sys/fs/msdosfs/msdosfs_vnops.c index 33e0d94954d7..6dfac1b4ebd2 100644 --- a/sys/fs/msdosfs/msdosfs_vnops.c +++ b/sys/fs/msdosfs/msdosfs_vnops.c @@ -1944,6 +1944,9 @@ msdosfs_pathconf(struct vop_pathconf_args *ap)  	case _PC_HAS_HIDDENSYSTEM:  		*ap->a_retval = 1;  		return (0); +	case _PC_CASE_INSENSITIVE: +		*ap->a_retval = 1; +		return (0);  	default:  		return (vop_stdpathconf(ap));  	} diff --git a/sys/fs/nfs/nfs_commonkrpc.c b/sys/fs/nfs/nfs_commonkrpc.c index 0ae3b94bef89..1e4e8506790f 100644 --- a/sys/fs/nfs/nfs_commonkrpc.c +++ b/sys/fs/nfs/nfs_commonkrpc.c @@ -239,6 +239,7 @@ static bool nfscl_use_gss[NFSV42_NPROCS] = {  	true,  	true,  	true, +	true,  };  /* diff --git a/sys/fs/nfs/nfs_commonport.c b/sys/fs/nfs/nfs_commonport.c index e5fdb395c9f7..862780741ee7 100644 --- a/sys/fs/nfs/nfs_commonport.c +++ b/sys/fs/nfs/nfs_commonport.c @@ -371,8 +371,6 @@ nfsrv_atroot(struct vnode *vp, uint64_t *retp)  /*   * Set the credentials to refer to root. - * If only the various BSDen could agree on whether cr_gid is a separate - * field or cr_groups[0]...   */  void  newnfs_setroot(struct ucred *cred) diff --git a/sys/fs/nfs/nfs_commonsubs.c b/sys/fs/nfs/nfs_commonsubs.c index 67e33193ecec..f580a394a735 100644 --- a/sys/fs/nfs/nfs_commonsubs.c +++ b/sys/fs/nfs/nfs_commonsubs.c @@ -187,14 +187,13 @@ struct nfsv4_opflag nfsv4_opflag[NFSV42_NOPS] = {  	{ 0, 0, 0, 0, LK_EXCLUSIVE, 1, 1 },		/* Read Plus */  	{ 0, 1, 0, 0, LK_SHARED, 1, 0 },		/* Seek */  	{ 0, 0, 0, 0, LK_EXCLUSIVE, 1, 1 },		/* Write Same */ -	{ 0, 0, 0, 0, LK_EXCLUSIVE, 1, 1 },		/* Clone */ +	{ 2, 1, 1, 0, LK_SHARED, 1, 0 },		/* Clone */  	{ 0, 1, 0, 0, LK_SHARED, 1, 1 },		/* Getxattr */  	{ 0, 1, 1, 1, LK_EXCLUSIVE, 1, 1 },		/* Setxattr */  	{ 0, 1, 0, 0, LK_SHARED, 1, 1 },		/* Listxattrs */  	{ 0, 1, 1, 1, LK_EXCLUSIVE, 1, 1 },		/* Removexattr */  }; -static int ncl_mbuf_mhlen = MHLEN;  struct nfsrv_lughash {  	struct mtx		mtx;  	struct nfsuserhashhead	lughead; @@ -216,10 +215,17 @@ NFSD_VNET_DEFINE_STATIC(u_char *, nfsrv_dnsname) = NULL;   * marked 0 in this array, the code will still work, just not quite as   * efficiently.)   */ -static int nfs_bigreply[NFSV42_NPROCS] = { 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, -    0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -    0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, -    1, 0, 0, 1, 0, 0, 0, 0, 0, 0 }; +static bool nfs_bigreply[NFSV42_NPROCS] = { +	[NFSPROC_GETACL] = true, +	[NFSPROC_GETEXTATTR] = true, +	[NFSPROC_LISTEXTATTR] = true, +	[NFSPROC_LOOKUP] = true, +	[NFSPROC_READ] = true, +	[NFSPROC_READDIR] = true, +	[NFSPROC_READDIRPLUS] = true, +	[NFSPROC_READDS] = true, +	[NFSPROC_READLINK] = true, +};  /* local functions */  static int nfsrv_skipace(struct nfsrv_descript *nd, int *acesizep); @@ -232,6 +238,8 @@ static int nfsrv_getrefstr(struct nfsrv_descript *, u_char **, u_char **,  static void nfsrv_refstrbigenough(int, u_char **, u_char **, int *);  static uint32_t vtonfsv4_type(struct vattr *);  static __enum_uint8(vtype) nfsv4tov_type(uint32_t, uint16_t *); +static void nfsv4_setsequence(struct nfsmount *, struct nfsrv_descript *, +    struct nfsclsession *, bool, struct ucred *);  static struct {  	int	op; @@ -310,6 +318,7 @@ static struct {  	{ NFSV4OP_LAYOUTERROR, 1, "LayoutError", 11, },  	{ NFSV4OP_VERIFY, 3, "AppendWrite", 11, },  	{ NFSV4OP_OPENATTR, 3, "OpenAttr", 8, }, +	{ NFSV4OP_SAVEFH, 5, "Clone", 5, },  };  /* @@ -319,7 +328,7 @@ static int nfs_bigrequest[NFSV42_NPROCS] = {  	0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  	0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, -	0, 1, 0 +	0, 1, 0, 0  };  /* @@ -631,6 +640,7 @@ nfscl_fillsattr(struct nfsrv_descript *nd, struct vattr *vap,  		if ((flags & NFSSATTR_FULL) && vap->va_size != VNOVAL)  			NFSSETBIT_ATTRBIT(&attrbits, NFSATTRBIT_SIZE);  		if ((flags & NFSSATTR_FULL) && vap->va_flags != VNOVAL) { +			NFSSETBIT_ATTRBIT(&attrbits, NFSATTRBIT_ARCHIVE);  			NFSSETBIT_ATTRBIT(&attrbits, NFSATTRBIT_HIDDEN);  			NFSSETBIT_ATTRBIT(&attrbits, NFSATTRBIT_SYSTEM);  		} @@ -648,7 +658,7 @@ nfscl_fillsattr(struct nfsrv_descript *nd, struct vattr *vap,  			NFSSETBIT_ATTRBIT(&attrbits, NFSATTRBIT_TIMECREATE);  		(void) nfsv4_fillattr(nd, vp->v_mount, vp, NULL, vap, NULL, 0,  		    &attrbits, NULL, NULL, 0, 0, 0, 0, (uint64_t)0, NULL, -		    false, false, false); +		    false, false, false, 0);  		break;  	}  } @@ -759,7 +769,7 @@ nfsm_dissct(struct nfsrv_descript *nd, int siz, int how)  		nd->nd_dpos += siz;  	} else if (nd->nd_md->m_next == NULL) {  		return (retp); -	} else if (siz > ncl_mbuf_mhlen) { +	} else if (siz > MHLEN) {  		panic("nfs S too big");  	} else {  		MGET(mp2, how, MT_DATA); @@ -1302,7 +1312,7 @@ nfsv4_loadattr(struct nfsrv_descript *nd, vnode_t vp,      struct nfsv3_pathconf *pc, struct statfs *sbp, struct nfsstatfs *sfp,      struct nfsfsinfo *fsp, NFSACL_T *aclp, int compare, int *retcmpp,      u_int32_t *leasep, u_int32_t *rderrp, bool *has_namedattrp, -    NFSPROC_T *p, struct ucred *cred) +    uint32_t *clone_blksizep, NFSPROC_T *p, struct ucred *cred)  {  	u_int32_t *tl;  	int i = 0, j, k, l = 0, m, bitpos, attrsum = 0; @@ -1437,6 +1447,13 @@ nfsv4_loadattr(struct nfsrv_descript *nd, vnode_t vp,  				 NFSCLRBIT_ATTRBIT(&checkattrbits,  				    NFSATTRBIT_SYSTEM);  			   } +			   /* Some filesystems do not support block cloning */ +			   if (vp == NULL || VOP_PATHCONF(vp, +				_PC_CLONE_BLKSIZE, &has_pathconf) != 0) +			       has_pathconf = 0; +			   if (has_pathconf == 0) +				 NFSCLRBIT_ATTRBIT(&checkattrbits, +				    NFSATTRBIT_CLONEBLKSIZE);  			   if (!NFSEQUAL_ATTRBIT(&retattrbits, &checkattrbits)  			       || retnotsup)  				*retcmpp = NFSERR_NOTSAME; @@ -1655,9 +1672,17 @@ nfsv4_loadattr(struct nfsrv_descript *nd, vnode_t vp,  			attrsum += NFSX_UNSIGNED;  			break;  		case NFSATTRBIT_ARCHIVE: -			NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED); -			if (compare && !(*retcmpp)) -				*retcmpp = NFSERR_ATTRNOTSUPP; +			NFSM_DISSECT(tl, uint32_t *, NFSX_UNSIGNED); +			if (compare) { +				if (!(*retcmpp) && ((*tl == newnfs_true && +				    (nap->na_flags & UF_ARCHIVE) == 0) || +				    (*tl == newnfs_false && +				     (nap->na_flags & UF_ARCHIVE) != 0))) +					*retcmpp = NFSERR_NOTSAME; +			} else if (nap != NULL) { +				if (*tl == newnfs_true) +					nap->na_flags |= UF_ARCHIVE; +			}  			attrsum += NFSX_UNSIGNED;  			break;  		case NFSATTRBIT_CANSETTIME: @@ -2374,6 +2399,23 @@ nfsv4_loadattr(struct nfsrv_descript *nd, vnode_t vp,  			if (compare && !(*retcmpp) && i != nfs_srvmaxio)  				*retcmpp = NFSERR_NOTSAME;  			break; +		case NFSATTRBIT_CLONEBLKSIZE: +			NFSM_DISSECT(tl, uint32_t *, NFSX_UNSIGNED); +			if (compare) { +				if (!(*retcmpp)) { +					if (vp == NULL || VOP_PATHCONF(vp, +					    _PC_CLONE_BLKSIZE, &has_pathconf) +					    != 0) +						has_pathconf = 0; +					if (has_pathconf != +					    fxdr_unsigned(uint32_t, *tl)) +						*retcmpp = NFSERR_NOTSAME; +				} +			} else if (clone_blksizep != NULL) { +				*clone_blksizep = fxdr_unsigned(uint32_t, *tl); +			} +			attrsum += NFSX_UNSIGNED; +			break;  		case NFSATTRBIT_CHANGEATTRTYPE:  			NFSM_DISSECT(tl, uint32_t *, NFSX_UNSIGNED);  			if (compare) { @@ -2648,7 +2690,7 @@ nfsv4_fillattr(struct nfsrv_descript *nd, struct mount *mp, vnode_t vp,      nfsattrbit_t *attrbitp, struct ucred *cred, NFSPROC_T *p, int isdgram,      int reterr, int supports_nfsv4acls, int at_root, uint64_t mounted_on_fileno,      struct statfs *pnfssf, bool xattrsupp, bool has_hiddensystem, -    bool has_namedattr) +    bool has_namedattr, uint32_t clone_blksize)  {  	int bitpos, retnum = 0;  	u_int32_t *tl; @@ -2770,7 +2812,11 @@ nfsv4_fillattr(struct nfsrv_descript *nd, struct mount *mp, vnode_t vp,  			if (!has_hiddensystem) {  			    NFSCLRBIT_ATTRBIT(&attrbits, NFSATTRBIT_HIDDEN);  			    NFSCLRBIT_ATTRBIT(&attrbits, NFSATTRBIT_SYSTEM); +			    NFSCLRBIT_ATTRBIT(&attrbits, NFSATTRBIT_ARCHIVE);  			} +			if (clone_blksize == 0) +			    NFSCLRBIT_ATTRBIT(&attrbits, +				NFSATTRBIT_CLONEBLKSIZE);  			retnum += nfsrv_putattrbit(nd, &attrbits);  			break;  		case NFSATTRBIT_TYPE: @@ -2851,6 +2897,14 @@ nfsv4_fillattr(struct nfsrv_descript *nd, struct mount *mp, vnode_t vp,  			*tl = txdr_unsigned(NFSV4ACE_SUPTYPES);  			retnum += NFSX_UNSIGNED;  			break; +		case NFSATTRBIT_ARCHIVE: +			NFSM_BUILD(tl, uint32_t *, NFSX_UNSIGNED); +			if ((vap->va_flags & UF_ARCHIVE) != 0) +				*tl = newnfs_true; +			else +				*tl = newnfs_false; +			retnum += NFSX_UNSIGNED; +			break;  		case NFSATTRBIT_CANSETTIME:  			NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);  			if (fsinf.fs_properties & NFSV3FSINFO_CANSETTIME) @@ -3249,6 +3303,11 @@ nfsv4_fillattr(struct nfsrv_descript *nd, struct mount *mp, vnode_t vp,  			}  			retnum += NFSX_UNSIGNED;  			break; +		case NFSATTRBIT_CLONEBLKSIZE: +			NFSM_BUILD(tl, uint32_t *, NFSX_UNSIGNED); +			*tl = txdr_unsigned(clone_blksize); +			retnum += NFSX_UNSIGNED; +			break;  		default:  			printf("EEK! Bad V4 attribute bitpos=%d\n", bitpos);  		} @@ -4132,10 +4191,15 @@ nfssvc_idname(struct nfsd_idargs *nidp)  	    nidp->nid_namelen);  	if (error == 0 && nidp->nid_ngroup > 0 &&  	    (nidp->nid_flag & NFSID_ADDUID) != 0) { -		grps = malloc(sizeof(gid_t) * nidp->nid_ngroup, M_TEMP, -		    M_WAITOK); -		error = copyin(nidp->nid_grps, grps, -		    sizeof(gid_t) * nidp->nid_ngroup); +		grps = NULL; +		if (nidp->nid_ngroup > NGROUPS_MAX) +			error = EINVAL; +		if (error == 0) { +			grps = malloc(sizeof(gid_t) * nidp->nid_ngroup, M_TEMP, +			    M_WAITOK); +			error = copyin(nidp->nid_grps, grps, +			    sizeof(gid_t) * nidp->nid_ngroup); +		}  		if (error == 0) {  			/*  			 * Create a credential just like svc_getcred(), @@ -4988,9 +5052,9 @@ nfsv4_seqsess_cacherep(uint32_t slotid, struct nfsslot *slots, int repstat,  /*   * Generate the xdr for an NFSv4.1 Sequence Operation.   */ -void +static void  nfsv4_setsequence(struct nfsmount *nmp, struct nfsrv_descript *nd, -    struct nfsclsession *sep, int dont_replycache, struct ucred *cred) +    struct nfsclsession *sep, bool dont_replycache, struct ucred *cred)  {  	uint32_t *tl, slotseq = 0;  	int error, maxslot, slotpos; @@ -5021,7 +5085,7 @@ nfsv4_setsequence(struct nfsmount *nmp, struct nfsrv_descript *nd,  		*tl++ = txdr_unsigned(slotseq);  		*tl++ = txdr_unsigned(slotpos);  		*tl++ = txdr_unsigned(maxslot); -		if (dont_replycache == 0) +		if (!dont_replycache)  			*tl = newnfs_true;  		else  			*tl = newnfs_false; diff --git a/sys/fs/nfs/nfs_var.h b/sys/fs/nfs/nfs_var.h index 54f60a753c50..16a76c060e78 100644 --- a/sys/fs/nfs/nfs_var.h +++ b/sys/fs/nfs/nfs_var.h @@ -286,6 +286,8 @@ int nfsrvd_deallocate(struct nfsrv_descript *, int,      vnode_t, struct nfsexstuff *);  int nfsrvd_copy_file_range(struct nfsrv_descript *, int,      vnode_t, vnode_t, struct nfsexstuff *, struct nfsexstuff *); +int nfsrvd_clone(struct nfsrv_descript *, int, +    vnode_t, vnode_t, struct nfsexstuff *, struct nfsexstuff *);  int nfsrvd_seek(struct nfsrv_descript *, int,      vnode_t, struct nfsexstuff *);  int nfsrvd_getxattr(struct nfsrv_descript *, int, @@ -341,7 +343,8 @@ int nfsv4_loadattr(struct nfsrv_descript *, vnode_t,      struct nfsvattr *, struct nfsfh **, fhandle_t *, int,      struct nfsv3_pathconf *, struct statfs *, struct nfsstatfs *,      struct nfsfsinfo *, NFSACL_T *, -    int, int *, u_int32_t *, u_int32_t *, bool *, NFSPROC_T *, struct ucred *); +    int, int *, u_int32_t *, u_int32_t *, bool *, uint32_t *, NFSPROC_T *, +    struct ucred *);  int nfsv4_lock(struct nfsv4lock *, int, int *, struct mtx *, struct mount *);  void nfsv4_unlock(struct nfsv4lock *, int);  void nfsv4_relref(struct nfsv4lock *); @@ -358,8 +361,6 @@ int nfsv4_getipaddr(struct nfsrv_descript *, struct sockaddr_in *,  int nfsv4_seqsession(uint32_t, uint32_t, uint32_t, struct nfsslot *,      struct mbuf **, uint16_t);  void nfsv4_seqsess_cacherep(uint32_t, struct nfsslot *, int, struct mbuf **); -void nfsv4_setsequence(struct nfsmount *, struct nfsrv_descript *, -    struct nfsclsession *, int, struct ucred *);  int nfsv4_sequencelookup(struct nfsmount *, struct nfsclsession *, int *,      int *, uint32_t *, uint8_t *, bool);  void nfsv4_freeslot(struct nfsclsession *, int, bool); @@ -397,7 +398,7 @@ void nfsrv_wcc(struct nfsrv_descript *, int, struct nfsvattr *, int,  int nfsv4_fillattr(struct nfsrv_descript *, struct mount *, vnode_t, NFSACL_T *,      struct vattr *, fhandle_t *, int, nfsattrbit_t *, struct ucred *,      NFSPROC_T *, int, int, int, int, uint64_t, struct statfs *, bool, bool, -    bool); +    bool, uint32_t);  void nfsrv_fillattr(struct nfsrv_descript *, struct nfsvattr *);  struct mbuf *nfsrv_adj(struct mbuf *, int, int);  void nfsrv_postopattr(struct nfsrv_descript *, int, struct nfsvattr *); @@ -517,10 +518,10 @@ int nfsrpc_lock(struct nfsrv_descript *, struct nfsmount *, vnode_t,      u_int8_t *, int, struct nfscllockowner *, int, int, u_int64_t,      u_int64_t, short, struct ucred *, NFSPROC_T *, int);  int nfsrpc_statfs(vnode_t, struct nfsstatfs *, struct nfsfsinfo *, uint32_t *, -    struct ucred *, NFSPROC_T *, struct nfsvattr *, int *); +    uint32_t *, struct ucred *, NFSPROC_T *, struct nfsvattr *, int *);  int nfsrpc_fsinfo(vnode_t, struct nfsfsinfo *, struct ucred *,      NFSPROC_T *, struct nfsvattr *, int *); -int nfsrpc_pathconf(vnode_t, struct nfsv3_pathconf *, bool *, +int nfsrpc_pathconf(vnode_t, struct nfsv3_pathconf *, bool *, uint32_t *,      struct ucred *, NFSPROC_T *, struct nfsvattr *, int *);  int nfsrpc_renew(struct nfsclclient *, struct nfsclds *, struct ucred *,      NFSPROC_T *); @@ -562,6 +563,8 @@ int nfsrpc_deallocate(vnode_t, off_t, off_t, struct nfsvattr *, int *,  int nfsrpc_copy_file_range(vnode_t, off_t *, vnode_t, off_t *, size_t *,      unsigned int, int *, struct nfsvattr *, int *, struct nfsvattr *,      struct ucred *, bool, bool *); +int nfsrpc_clone(vnode_t, off_t *, vnode_t, off_t *, size_t *, bool, +    int *, struct nfsvattr *, int *, struct nfsvattr *, struct ucred *);  int nfsrpc_seek(vnode_t, off_t *, bool *, int, struct ucred *,      struct nfsvattr *, int *);  int nfsrpc_getextattr(vnode_t, const char *, struct uio *, ssize_t *, @@ -668,7 +671,7 @@ int nfscl_nget(mount_t, vnode_t, struct nfsfh *,  NFSPROC_T *nfscl_getparent(NFSPROC_T *);  void nfscl_start_renewthread(struct nfsclclient *);  void nfscl_loadsbinfo(struct nfsmount *, struct nfsstatfs *, void *); -void nfscl_loadfsinfo (struct nfsmount *, struct nfsfsinfo *); +void nfscl_loadfsinfo(struct nfsmount *, struct nfsfsinfo *, uint32_t);  void nfscl_delegreturn(struct nfscldeleg *, int, struct nfsmount *,      struct ucred *, NFSPROC_T *);  void nfsrvd_cbinit(int); @@ -737,7 +740,7 @@ int nfsvno_updfilerev(vnode_t, struct nfsvattr *, struct nfsrv_descript *,  int nfsvno_fillattr(struct nfsrv_descript *, struct mount *, vnode_t,      struct nfsvattr *, fhandle_t *, int, nfsattrbit_t *,      struct ucred *, NFSPROC_T *, int, int, int, int, uint64_t, bool, bool, -    bool); +    bool, uint32_t);  int nfsrv_sattr(struct nfsrv_descript *, vnode_t, struct nfsvattr *, nfsattrbit_t *,      NFSACL_T *, NFSPROC_T *);  int nfsv4_sattr(struct nfsrv_descript *, vnode_t, struct nfsvattr *, nfsattrbit_t *, diff --git a/sys/fs/nfs/nfsport.h b/sys/fs/nfs/nfsport.h index c30b46261df0..4e9aae70da6f 100644 --- a/sys/fs/nfs/nfsport.h +++ b/sys/fs/nfs/nfsport.h @@ -442,10 +442,13 @@  /* Do a NFSv4 Openattr. */  #define	NFSPROC_OPENATTR	70 +/* Do a NFSv4.2 Clone. */ +#define	NFSPROC_CLONE		71 +  /*   * Must be defined as one higher than the last NFSv4.2 Proc# above.   */ -#define	NFSV42_NPROCS		71 +#define	NFSV42_NPROCS		72  /* Value of NFSV42_NPROCS for old nfsstats structure. (Always 69) */  #define	NFSV42_OLDNPROCS	69 @@ -477,7 +480,7 @@ struct nfsstatsv1 {  	uint64_t	readlink_bios;  	uint64_t	biocache_readdirs;  	uint64_t	readdir_bios; -	uint64_t	rpccnt[NFSV42_NPROCS + 9]; +	uint64_t	rpccnt[NFSV42_NPROCS + 8];  	uint64_t	rpcretries;  	uint64_t	srvrpccnt[NFSV42_NOPS + NFSV4OP_FAKENOPS + 15];  	uint64_t	srvlayouts; @@ -906,15 +909,6 @@ int nfsmsleep(void *, void *, int, const char *, struct timespec *);  #define	NFSBZERO(s, l)		bzero((s), (l))  /* - * Some queue.h files don't have these dfined in them. - */ -#ifndef LIST_END -#define	LIST_END(head)		NULL -#define	SLIST_END(head)		NULL -#define	TAILQ_END(head)		NULL -#endif - -/*   * This must be defined to be a global variable that increments once   * per second, but never stops or goes backwards, even when a "date"   * command changes the TOD clock. It is used for delta times for @@ -1023,7 +1017,7 @@ MALLOC_DECLARE(M_NEWNFSDSESSION);  int nfscl_loadattrcache(struct vnode **, struct nfsvattr *, void *, int, int);  int newnfs_realign(struct mbuf **, int);  bool ncl_pager_setsize(struct vnode *vp, u_quad_t *nsizep); -void ncl_copy_vattr(struct vattr *dst, struct vattr *src); +void ncl_copy_vattr(struct vnode *vp, struct vattr *dst, struct vattr *src);  /*   * If the port runs on an SMP box that can enforce Atomic ops with low @@ -1035,9 +1029,6 @@ void ncl_copy_vattr(struct vattr *dst, struct vattr *src);  #define	NFSDECRGLOBAL(a)	((a)--)  /* - * Assorted funky stuff to make things work under Darwin8. - */ -/*   * These macros checks for a field in vattr being set.   */  #define	NFSATTRISSET(t, v, a)	((v)->a != (t)VNOVAL) diff --git a/sys/fs/nfs/nfsproto.h b/sys/fs/nfs/nfsproto.h index cb5a80e8df73..13fec8a102a3 100644 --- a/sys/fs/nfs/nfsproto.h +++ b/sys/fs/nfs/nfsproto.h @@ -411,10 +411,13 @@  /* Do a NFSv4 Openattr. */  #define	NFSPROC_OPENATTR	70 +/* Do a NFSv4.2 Clone. */ +#define	NFSPROC_CLONE		71 +  /*   * Must be defined as one higher than the last NFSv4.2 Proc# above.   */ -#define	NFSV42_NPROCS		71 +#define	NFSV42_NPROCS		72  /* Value of NFSV42_NPROCS for old nfsstats structure. (Always 69) */  #define	NFSV42_OLDNPROCS	69 @@ -1132,6 +1135,7 @@ struct nfsv3_sattr {   	NFSATTRBM_RDATTRERROR |						\   	NFSATTRBM_ACL |							\   	NFSATTRBM_ACLSUPPORT |						\ +	NFSATTRBM_ARCHIVE |						\   	NFSATTRBM_CANSETTIME |						\   	NFSATTRBM_CASEINSENSITIVE |					\   	NFSATTRBM_CASEPRESERVING |					\ @@ -1194,6 +1198,7 @@ struct nfsv3_sattr {  	NFSATTRBM_LAYOUTBLKSIZE |					\  	NFSATTRBM_LAYOUTALIGNMENT |					\  	NFSATTRBM_SUPPATTREXCLCREAT |					\ +	NFSATTRBM_CLONEBLKSIZE |					\  	NFSATTRBM_CHANGEATTRTYPE |					\  	NFSATTRBM_XATTRSUPPORT) @@ -1213,6 +1218,7 @@ struct nfsv3_sattr {  #define	NFSATTRBIT_SETABLE0						\  	(NFSATTRBM_SIZE |						\  	NFSATTRBM_HIDDEN |						\ +	NFSATTRBM_ARCHIVE |						\  	NFSATTRBM_ACL)  #define	NFSATTRBIT_SETABLE1						\   	(NFSATTRBM_MODE |						\ @@ -1242,7 +1248,8 @@ struct nfsv3_sattr {   * NFSATTRBIT_NFSV42 - Attributes only supported by NFSv4.2.   */  #define	NFSATTRBIT_NFSV42_2						\ -	(NFSATTRBM_CHANGEATTRTYPE |					\ +	(NFSATTRBM_CLONEBLKSIZE |					\ +	NFSATTRBM_CHANGEATTRTYPE |					\  	NFSATTRBM_XATTRSUPPORT |					\  	NFSATTRBM_MODEUMASK) @@ -1257,6 +1264,7 @@ struct nfsv3_sattr {   	NFSATTRBM_CHANGE |						\   	NFSATTRBM_SIZE |						\   	NFSATTRBM_FSID |						\ +	NFSATTRBM_ARCHIVE |						\   	NFSATTRBM_FILEID |						\  	NFSATTRBM_HIDDEN |						\   	NFSATTRBM_MAXREAD) @@ -1293,6 +1301,7 @@ struct nfsv3_sattr {   	NFSATTRBM_CHANGE |						\   	NFSATTRBM_SIZE |						\   	NFSATTRBM_FSID |						\ +	NFSATTRBM_ARCHIVE |						\   	NFSATTRBM_FILEID |						\  	NFSATTRBM_HIDDEN |						\   	NFSATTRBM_MAXREAD) @@ -1415,7 +1424,7 @@ struct nfsv3_sattr {  /*   * NFSGETATTRBIT_STATFS2 - bits 64<->95   */ -#define	NFSGETATTRBIT_STATFS2		0 +#define	NFSGETATTRBIT_STATFS2	(NFSATTRBM_CLONEBLKSIZE)  /*   * Set of attributes for the equivalent of an nfsv3 pathconf rpc. @@ -1438,7 +1447,7 @@ struct nfsv3_sattr {  /*   * NFSGETATTRBIT_PATHCONF2 - bits 64<->95   */ -#define	NFSGETATTRBIT_PATHCONF2		0 +#define	NFSGETATTRBIT_PATHCONF2	(NFSATTRBM_CLONEBLKSIZE)  /*   * Sets of attributes required by readdir and readdirplus. diff --git a/sys/fs/nfsclient/nfs_clcomsubs.c b/sys/fs/nfsclient/nfs_clcomsubs.c index bca0bdcd0df1..05963074e53d 100644 --- a/sys/fs/nfsclient/nfs_clcomsubs.c +++ b/sys/fs/nfsclient/nfs_clcomsubs.c @@ -272,7 +272,7 @@ nfsm_loadattr(struct nfsrv_descript *nd, struct nfsvattr *nap)  	if (nd->nd_flag & ND_NFSV4) {  		error = nfsv4_loadattr(nd, NULL, nap, NULL, NULL, 0, NULL,  		    NULL, NULL, NULL, NULL, 0, NULL, NULL, NULL, NULL, NULL, -		    NULL); +		    NULL, NULL);  	} else if (nd->nd_flag & ND_NFSV3) {  		NFSM_DISSECT(fp, struct nfs_fattr *, NFSX_V3FATTR);  		nap->na_type = nfsv34tov_type(fp->fa_type); diff --git a/sys/fs/nfsclient/nfs_clport.c b/sys/fs/nfsclient/nfs_clport.c index b25d967982a1..77e71d4153c9 100644 --- a/sys/fs/nfsclient/nfs_clport.c +++ b/sys/fs/nfsclient/nfs_clport.c @@ -412,7 +412,7 @@ nfscl_warn_fileid(struct nfsmount *nmp, struct nfsvattr *oldnap,  }  void -ncl_copy_vattr(struct vattr *dst, struct vattr *src) +ncl_copy_vattr(struct vnode *vp, struct vattr *dst, struct vattr *src)  {  	dst->va_type = src->va_type;  	dst->va_mode = src->va_mode; @@ -429,7 +429,7 @@ ncl_copy_vattr(struct vattr *dst, struct vattr *src)  	dst->va_birthtime = src->va_birthtime;  	dst->va_gen = src->va_gen;  	dst->va_flags = src->va_flags; -	dst->va_rdev = src->va_rdev; +	dst->va_rdev = VN_ISDEV(vp) ? src->va_rdev : NODEV;  	dst->va_bytes = src->va_bytes;  	dst->va_filerev = src->va_filerev;  } @@ -595,7 +595,7 @@ nfscl_loadattrcache(struct vnode **vpp, struct nfsvattr *nap, void *nvaper,  		KDTRACE_NFS_ATTRCACHE_FLUSH_DONE(vp);  	}  	if (vaper != NULL) { -		ncl_copy_vattr(vaper, vap); +		ncl_copy_vattr(vp, vaper, vap);  		if (np->n_flag & NCHG) {  			if (np->n_flag & NACC)  				vaper->va_atime = np->n_atim; @@ -828,7 +828,7 @@ nfscl_wcc_data(struct nfsrv_descript *nd, struct vnode *vp,  	    == (ND_NFSV4 | ND_V4WCCATTR)) {  		error = nfsv4_loadattr(nd, NULL, &nfsva, NULL,  		    NULL, 0, NULL, NULL, NULL, NULL, NULL, 0, -		    NULL, NULL, NULL, NULL, NULL, NULL); +		    NULL, NULL, NULL, NULL, NULL, NULL, NULL);  		if (error)  			return (error);  		/* @@ -963,7 +963,8 @@ nfscl_loadsbinfo(struct nfsmount *nmp, struct nfsstatfs *sfp, void *statfs)   * Use the fsinfo stuff to update the mount point.   */  void -nfscl_loadfsinfo(struct nfsmount *nmp, struct nfsfsinfo *fsp) +nfscl_loadfsinfo(struct nfsmount *nmp, struct nfsfsinfo *fsp, +    uint32_t clone_blksize)  {  	if ((nmp->nm_wsize == 0 || fsp->fs_wtpref < nmp->nm_wsize) && @@ -1003,6 +1004,14 @@ nfscl_loadfsinfo(struct nfsmount *nmp, struct nfsfsinfo *fsp)  	    fsp->fs_maxfilesize < nmp->nm_maxfilesize)  		nmp->nm_maxfilesize = fsp->fs_maxfilesize;  	nmp->nm_mountp->mnt_stat.f_iosize = newnfs_iosize(nmp); + +	/* +	 * Although ZFS reports a clone_blksize of 16Mbytes, +	 * 128Kbytes usually works, so set it to that. +	 */ +	if (clone_blksize > 128 * 1024) +		clone_blksize = 128 * 1024; +	nmp->nm_cloneblksize = clone_blksize;  	nmp->nm_state |= NFSSTA_GOTFSINFO;  } @@ -1089,9 +1098,10 @@ newnfs_copyincred(struct ucred *cr, struct nfscred *nfscr)  	KASSERT(cr->cr_ngroups >= 0,  	    ("newnfs_copyincred: negative cr_ngroups"));  	nfscr->nfsc_uid = cr->cr_uid; -	nfscr->nfsc_ngroups = MIN(cr->cr_ngroups, NFS_MAXGRPS + 1); -	for (i = 0; i < nfscr->nfsc_ngroups; i++) -		nfscr->nfsc_groups[i] = cr->cr_groups[i]; +	nfscr->nfsc_ngroups = MIN(cr->cr_ngroups + 1, NFS_MAXGRPS + 1); +	nfscr->nfsc_groups[0] = cr->cr_gid; +	for (i = 1; i < nfscr->nfsc_ngroups; i++) +		nfscr->nfsc_groups[i] = cr->cr_groups[i - 1];  }  /* diff --git a/sys/fs/nfsclient/nfs_clrpcops.c b/sys/fs/nfsclient/nfs_clrpcops.c index 920fcf7b8c61..b61218958550 100644 --- a/sys/fs/nfsclient/nfs_clrpcops.c +++ b/sys/fs/nfsclient/nfs_clrpcops.c @@ -225,6 +225,9 @@ static int nfsrpc_layoutgetres(struct nfsmount *, vnode_t, uint8_t *,  static int nfsrpc_copyrpc(vnode_t, off_t, vnode_t, off_t, size_t *,      nfsv4stateid_t *, nfsv4stateid_t *, struct nfsvattr *, int *,      struct nfsvattr *, int *, bool, int *, struct ucred *, NFSPROC_T *); +static int nfsrpc_clonerpc(vnode_t, off_t, vnode_t, off_t, size_t *, bool, +    nfsv4stateid_t *, nfsv4stateid_t *, struct nfsvattr *, int *, +    struct nfsvattr *, int *, struct ucred *, NFSPROC_T *);  static int nfsrpc_seekrpc(vnode_t, off_t *, nfsv4stateid_t *, bool *,      int, struct nfsvattr *, int *, struct ucred *);  static struct mbuf *nfsm_split(struct mbuf *, uint64_t); @@ -696,7 +699,7 @@ nfsrpc_openrpc(struct nfsmount *nmp, vnode_t vp, u_int8_t *nfhp, int fhlen,  			    ("nfsrpc_openrpc: Getattr repstat"));  			error = nfsv4_loadattr(nd, NULL, &nfsva, NULL,  			    NULL, 0, NULL, NULL, NULL, NULL, NULL, 0, -			    NULL, NULL, NULL, NULL, p, cred); +			    NULL, NULL, NULL, NULL, NULL, p, cred);  			if (error)  				goto nfsmout;  		} @@ -1355,7 +1358,7 @@ nfsrpc_getattrnovp(struct nfsmount *nmp, u_int8_t *fhp, int fhlen, int syscred,  		if ((nd->nd_flag & ND_NFSV4) != 0)  			error = nfsv4_loadattr(nd, NULL, nap, NULL, NULL, 0,  			    NULL, NULL, NULL, NULL, NULL, 0, NULL, leasep, NULL, -			    NULL, NULL, NULL); +			    NULL, NULL, NULL, NULL);  		else  			error = nfsm_loadattr(nd, nap);  	} else @@ -2209,7 +2212,7 @@ nfsrpc_writerpc(vnode_t vp, struct uio *uiop, int *iomode,  				NFSM_DISSECT(tl, u_int32_t *, 2 * NFSX_UNSIGNED  					+ NFSX_VERF);  				rlen = fxdr_unsigned(int, *tl++); -				if (rlen == 0) { +				if (rlen <= 0 || rlen > len) {  					error = NFSERR_IO;  					goto nfsmout;  				} else if (rlen < len) { @@ -3597,7 +3600,7 @@ nfsrpc_readdir(vnode_t vp, struct uio *uiop, nfsuint64 *cookiep,  				nfsva.na_mntonfileno = UINT64_MAX;  				error = nfsv4_loadattr(nd, NULL, &nfsva, NULL,  				    NULL, 0, NULL, NULL, NULL, NULL, NULL, 0, -				    NULL, NULL, NULL, NULL, p, cred); +				    NULL, NULL, NULL, NULL, NULL, p, cred);  				if (error) {  				    dotdotfileid = dotfileid;  				} else if (gotmnton) { @@ -3847,7 +3850,7 @@ nfsrpc_readdir(vnode_t vp, struct uio *uiop, nfsuint64 *cookiep,  				nfsva.na_mntonfileno = UINT64_MAX;  				error = nfsv4_loadattr(nd, NULL, &nfsva, NULL,  				    NULL, 0, NULL, NULL, NULL, NULL, NULL, 0, -				    NULL, NULL, &rderr, NULL, p, cred); +				    NULL, NULL, &rderr, NULL, NULL, p, cred);  				if (error)  					goto nfsmout;  				NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED); @@ -3978,7 +3981,7 @@ nfsrpc_readdirplus(vnode_t vp, struct uio *uiop, nfsuint64 *cookiep,  	int len, left;  	struct dirent *dp = NULL;  	u_int32_t *tl; -	vnode_t newvp = NULLVP; +	vnode_t newvp = NULL;  	struct nfsrv_descript nfsd, *nd = &nfsd;  	struct nameidata nami, *ndp = &nami;  	struct componentname *cnp = &ndp->ni_cnd; @@ -4072,7 +4075,7 @@ nfsrpc_readdirplus(vnode_t vp, struct uio *uiop, nfsuint64 *cookiep,  				nfsva.na_mntonfileno = UINT64_MAX;  				error = nfsv4_loadattr(nd, NULL, &nfsva, NULL,  				    NULL, 0, NULL, NULL, NULL, NULL, NULL, 0, -				    NULL, NULL, NULL, NULL, p, cred); +				    NULL, NULL, NULL, NULL, NULL, p, cred);  				if (error) {  				    dotdotfileid = dotfileid;  				} else if (gotmnton) { @@ -4159,9 +4162,12 @@ nfsrpc_readdirplus(vnode_t vp, struct uio *uiop, nfsuint64 *cookiep,  		    NFSATTRBIT_TIMECREATE))  			NFSCLRBIT_ATTRBIT(&attrbits, NFSATTRBIT_TIMECREATE);  		if (!NFSISSET_ATTRBIT(&dnp->n_vattr.na_suppattr, +		    NFSATTRBIT_ARCHIVE) || +		    !NFSISSET_ATTRBIT(&dnp->n_vattr.na_suppattr,  		    NFSATTRBIT_HIDDEN) ||  		    !NFSISSET_ATTRBIT(&dnp->n_vattr.na_suppattr,  		    NFSATTRBIT_SYSTEM)) { +			NFSCLRBIT_ATTRBIT(&attrbits, NFSATTRBIT_ARCHIVE);  			NFSCLRBIT_ATTRBIT(&attrbits, NFSATTRBIT_HIDDEN);  			NFSCLRBIT_ATTRBIT(&attrbits, NFSATTRBIT_SYSTEM);  		} @@ -4346,7 +4352,7 @@ nfsrpc_readdirplus(vnode_t vp, struct uio *uiop, nfsuint64 *cookiep,  				nfsva.na_mntonfileno = 0xffffffff;  				error = nfsv4_loadattr(nd, NULL, &nfsva, &nfhp,  				    NULL, 0, NULL, NULL, NULL, NULL, NULL, 0, -				    NULL, NULL, &rderr, NULL, p, cred); +				    NULL, NULL, &rderr, NULL, NULL, p, cred);  				if (error)  					goto nfsmout;  			} @@ -4384,7 +4390,7 @@ nfsrpc_readdirplus(vnode_t vp, struct uio *uiop, nfsuint64 *cookiep,  				attr_ok = true;  				if (NFSRV_CMPFH(nfhp->nfh_fh, nfhp->nfh_len,  				    dnp->n_fhp->nfh_fh, dnp->n_fhp->nfh_len)) { -				    VREF(vp); +				    vref(vp);  				    newvp = vp;  				    unlocknewvp = 0;  				    free(nfhp, M_NFSFH); @@ -4433,7 +4439,7 @@ nfsrpc_readdirplus(vnode_t vp, struct uio *uiop, nfsuint64 *cookiep,  				    }  				}  				nfhp = NULL; -				if (newvp != NULLVP) { +				if (newvp != NULL) {  				    if (attr_ok)  					error = nfscl_loadattrcache(&newvp,  					    &nfsva, NULL, 0, 0); @@ -4463,7 +4469,7 @@ nfsrpc_readdirplus(vnode_t vp, struct uio *uiop, nfsuint64 *cookiep,  					vput(newvp);  				    else  					vrele(newvp); -				    newvp = NULLVP; +				    newvp = NULL;  				}  			    }  			} else if (nfhp != NULL) { @@ -4981,8 +4987,8 @@ nfsmout:   */  int  nfsrpc_statfs(vnode_t vp, struct nfsstatfs *sbp, struct nfsfsinfo *fsp, -    uint32_t *leasep, struct ucred *cred, NFSPROC_T *p, struct nfsvattr *nap, -    int *attrflagp) +    uint32_t *leasep, uint32_t *cloneblksizep, struct ucred *cred, NFSPROC_T *p, +    struct nfsvattr *nap, int *attrflagp)  {  	u_int32_t *tl = NULL;  	struct nfsrv_descript nfsd, *nd = &nfsd; @@ -4991,6 +4997,8 @@ nfsrpc_statfs(vnode_t vp, struct nfsstatfs *sbp, struct nfsfsinfo *fsp,  	int error;  	*attrflagp = 0; +	if (cloneblksizep != NULL) +		*cloneblksizep = 0;  	nmp = VFSTONFS(vp->v_mount);  	if (NFSHASNFSV4(nmp)) {  		/* @@ -5009,7 +5017,7 @@ nfsrpc_statfs(vnode_t vp, struct nfsstatfs *sbp, struct nfsfsinfo *fsp,  		if (nd->nd_repstat == 0) {  			error = nfsv4_loadattr(nd, NULL, nap, NULL, NULL, 0,  			    NULL, NULL, sbp, fsp, NULL, 0, NULL, leasep, NULL, -			    NULL, p, cred); +			    NULL, cloneblksizep, p, cred);  			if (!error) {  				nmp->nm_fsid[0] = nap->na_filesid[0];  				nmp->nm_fsid[1] = nap->na_filesid[1]; @@ -5063,7 +5071,8 @@ nfsmout:   */  int  nfsrpc_pathconf(vnode_t vp, struct nfsv3_pathconf *pc, bool *has_namedattrp, -    struct ucred *cred, NFSPROC_T *p, struct nfsvattr *nap, int *attrflagp) +    uint32_t *clone_blksizep, struct ucred *cred, NFSPROC_T *p, +    struct nfsvattr *nap, int *attrflagp)  {  	struct nfsrv_descript nfsd, *nd = &nfsd;  	struct nfsmount *nmp; @@ -5074,6 +5083,7 @@ nfsrpc_pathconf(vnode_t vp, struct nfsv3_pathconf *pc, bool *has_namedattrp,  	*has_namedattrp = false;  	*attrflagp = 0; +	*clone_blksizep = 0;  	nmp = VFSTONFS(vp->v_mount);  	if (NFSHASNFSV4(nmp)) {  		np = VTONFS(vp); @@ -5100,7 +5110,7 @@ nfsrpc_pathconf(vnode_t vp, struct nfsv3_pathconf *pc, bool *has_namedattrp,  		if (nd->nd_repstat == 0) {  			error = nfsv4_loadattr(nd, NULL, nap, NULL, NULL, 0,  			    pc, NULL, NULL, NULL, NULL, 0, NULL, NULL, NULL, -			    has_namedattrp, p, cred); +			    has_namedattrp, clone_blksizep, p, cred);  			if (!error)  				*attrflagp = 1;  		} else { @@ -5274,7 +5284,7 @@ nfsrpc_getdirpath(struct nfsmount *nmp, u_char *dirpath, struct ucred *cred,  	struct nfsrv_descript nfsd;  	struct nfsrv_descript *nd = &nfsd;  	u_char *cp, *cp2, *fhp; -	int error, cnt, len, setnil; +	int error, cnt, i, len, setnil;  	u_int32_t *opcntp;  	nfscl_reqstart(nd, NFSPROC_PUTROOTFH, nmp, NULL, 0, &opcntp, NULL, 0, @@ -5315,8 +5325,12 @@ nfsrpc_getdirpath(struct nfsmount *nmp, u_char *dirpath, struct ucred *cred,  	if (error)  		return (error);  	if (nd->nd_repstat == 0) { -		NFSM_DISSECT(tl, u_int32_t *, (3 + 2 * cnt) * NFSX_UNSIGNED); -		tl += (2 + 2 * cnt); +		NFSM_DISSECT(tl, uint32_t *, 3 * NFSX_UNSIGNED); +		tl += 2; +		for (i = 0; i < cnt; i++) { +			NFSM_DISSECT(tl, uint32_t *, 2 * NFSX_UNSIGNED); +			tl++; +		}  		if ((len = fxdr_unsigned(int, *tl)) <= 0 ||  			len > NFSX_FHMAX) {  			nd->nd_repstat = NFSERR_BADXDR; @@ -5395,7 +5409,8 @@ nfsrpc_getacl(vnode_t vp, struct ucred *cred, NFSPROC_T *p, struct acl *aclp)  		return (error);  	if (!nd->nd_repstat)  		error = nfsv4_loadattr(nd, vp, NULL, NULL, NULL, 0, NULL, -		    NULL, NULL, NULL, aclp, 0, NULL, NULL, NULL, NULL, p, cred); +		    NULL, NULL, NULL, aclp, 0, NULL, NULL, NULL, NULL, NULL, p, +		    cred);  	else  		error = nd->nd_repstat;  	m_freem(nd->nd_mrep); @@ -5437,7 +5452,7 @@ nfsrpc_setaclrpc(vnode_t vp, struct ucred *cred, NFSPROC_T *p,  	NFSSETBIT_ATTRBIT(&attrbits, NFSATTRBIT_ACL);  	(void) nfsv4_fillattr(nd, vp->v_mount, vp, aclp, NULL, NULL, 0,  	    &attrbits, NULL, NULL, 0, 0, 0, 0, (uint64_t)0, NULL, false, false, -	    false); +	    false, 0);  	error = nfscl_request(nd, vp, p, cred);  	if (error)  		return (error); @@ -5588,7 +5603,7 @@ nfsrpc_createsession(struct nfsmount *nmp, struct nfsclsession *sep,  	}  	*tl++ = txdr_unsigned(4096);		/* Max response size cached */  	*tl++ = txdr_unsigned(20);		/* Max operations */ -	*tl++ = txdr_unsigned(64);		/* Max slots */ +	*tl++ = txdr_unsigned(NFSV4_SLOTS);	/* Max slots */  	*tl = 0;				/* No rdma ird */  	/* Fill in back channel attributes. */ @@ -5657,6 +5672,11 @@ nfsrpc_createsession(struct nfsmount *nmp, struct nfsclsession *sep,  		sep->nfsess_maxcache = fxdr_unsigned(int, *tl++);  		tl++;  		sep->nfsess_foreslots = fxdr_unsigned(uint16_t, *tl++); +		if (sep->nfsess_foreslots == 0) { +			error = NFSERR_BADXDR; +			goto nfsmout; +		} else if (sep->nfsess_foreslots > NFSV4_SLOTS) +			sep->nfsess_foreslots = NFSV4_SLOTS;  		NFSCL_DEBUG(4, "fore slots=%d\n", (int)sep->nfsess_foreslots);  		irdcnt = fxdr_unsigned(int, *tl);  		if (irdcnt < 0 || irdcnt > 1) { @@ -5670,6 +5690,8 @@ nfsrpc_createsession(struct nfsmount *nmp, struct nfsclsession *sep,  		NFSM_DISSECT(tl, uint32_t *, 7 * NFSX_UNSIGNED);  		tl += 5;  		sep->nfsess_backslots = fxdr_unsigned(uint16_t, *tl); +		if (sep->nfsess_backslots > NFSV4_CBSLOTS) +			sep->nfsess_backslots = NFSV4_CBSLOTS;  		NFSCL_DEBUG(4, "back slots=%d\n", (int)sep->nfsess_backslots);  	}  	error = nd->nd_repstat; @@ -5789,7 +5811,8 @@ nfsrpc_getdeviceinfo(struct nfsmount *nmp, uint8_t *deviceid, int layouttype,  			NFSM_DISSECT(tl, uint32_t *, NFSX_UNSIGNED);  			stripecnt = fxdr_unsigned(int, *tl);  			NFSCL_DEBUG(4, "stripecnt=%d\n", stripecnt); -			if (stripecnt < 1 || stripecnt > 4096) { +			if (stripecnt >= MHLEN / NFSX_UNSIGNED || +			    stripecnt < 1) {  				printf("pNFS File layout devinfo stripecnt %d:"  				    " out of range\n", stripecnt);  				error = NFSERR_BADXDR; @@ -7238,7 +7261,7 @@ nfsrpc_writeds(vnode_t vp, struct uio *uiop, int *iomode, int *must_commit,  		NFSM_DISSECT(tl, uint32_t *, 2 * NFSX_UNSIGNED + NFSX_VERF);  		rlen = fxdr_unsigned(int, *tl++);  		NFSCL_DEBUG(4, "nfsrpc_writeds: len=%d rlen=%d\n", len, rlen); -		if (rlen == 0) { +		if (rlen <= 0 || rlen > len) {  			error = NFSERR_IO;  			goto nfsmout;  		} else if (rlen < len) { @@ -8235,7 +8258,7 @@ nfsrv_parseug(struct nfsrv_descript *nd, int dogrp, uid_t *uidp, gid_t *gidp,      NFSPROC_T *p)  {  	uint32_t *tl; -	char *cp, *str, str0[NFSV4_SMALLSTR + 1]; +	char *str, str0[NFSV4_SMALLSTR + 1];  	uint32_t len = 0;  	int error = 0; @@ -8258,9 +8281,9 @@ nfsrv_parseug(struct nfsrv_descript *nd, int dogrp, uid_t *uidp, gid_t *gidp,  		str = malloc(len + 1, M_TEMP, M_WAITOK);  	else  		str = str0; -	NFSM_DISSECT(cp, char *, NFSM_RNDUP(len)); -	NFSBCOPY(cp, str, len); -	str[len] = '\0'; +	error = nfsrv_mtostr(nd, str, len); +	if (error != 0) +		goto nfsmout;  	NFSCL_DEBUG(4, "nfsrv_parseug: str=%s\n", str);  	if (dogrp != 0)  		error = nfsv4_strtogid(nd, str, len, gidp); @@ -8496,7 +8519,7 @@ nfsrpc_openlayoutrpc(struct nfsmount *nmp, vnode_t vp, u_int8_t *nfhp,  		if (*++tl == 0) {  			error = nfsv4_loadattr(nd, NULL, &nfsva, NULL,  			    NULL, 0, NULL, NULL, NULL, NULL, NULL, 0, -			    NULL, NULL, NULL, NULL, p, cred); +			    NULL, NULL, NULL, NULL, NULL, p, cred);  			if (error != 0)  				goto nfsmout;  			if (ndp != NULL) { @@ -9168,6 +9191,199 @@ nfsmout:  }  /* + * nfs clone operation. + */ +int +nfsrpc_clone(vnode_t invp, off_t *inoffp, vnode_t outvp, +    off_t *outoffp, size_t *lenp, bool toeof, int *inattrflagp, +    struct nfsvattr *innap, int *outattrflagp, struct nfsvattr *outnap, +    struct ucred *cred) +{ +	int error, expireret = 0, retrycnt; +	uint32_t clidrev = 0; +	struct nfsmount *nmp = VFSTONFS(invp->v_mount); +	struct nfsfh *innfhp = NULL, *outnfhp = NULL; +	nfsv4stateid_t instateid, outstateid; +	void *inlckp, *outlckp; + +	if (nmp->nm_clp != NULL) +		clidrev = nmp->nm_clp->nfsc_clientidrev; +	innfhp = VTONFS(invp)->n_fhp; +	outnfhp = VTONFS(outvp)->n_fhp; +	retrycnt = 0; +	do { +		/* Get both stateids. */ +		inlckp = NULL; +		nfscl_getstateid(invp, innfhp->nfh_fh, innfhp->nfh_len, +		    NFSV4OPEN_ACCESSREAD, 0, NULL, curthread, &instateid, +		    &inlckp); +		outlckp = NULL; +		nfscl_getstateid(outvp, outnfhp->nfh_fh, outnfhp->nfh_len, +		    NFSV4OPEN_ACCESSWRITE, 0, NULL, curthread, &outstateid, +		    &outlckp); + +		error = nfsrpc_clonerpc(invp, *inoffp, outvp, *outoffp, lenp, +		    toeof, &instateid, &outstateid, innap, inattrflagp, outnap, +		    outattrflagp, cred, curthread); +		if (error == 0) { +			*inoffp += *lenp; +			*outoffp += *lenp; +		} else if (error == NFSERR_STALESTATEID) +			nfscl_initiate_recovery(nmp->nm_clp); +		if (inlckp != NULL) +			nfscl_lockderef(inlckp); +		if (outlckp != NULL) +			nfscl_lockderef(outlckp); +		if (error == NFSERR_GRACE || error == NFSERR_STALESTATEID || +		    error == NFSERR_STALEDONTRECOVER || error == NFSERR_DELAY || +		    error == NFSERR_OLDSTATEID || error == NFSERR_BADSESSION) { +			(void) nfs_catnap(PZERO, error, "nfs_cfr"); +		} else if ((error == NFSERR_EXPIRED || (!NFSHASINT(nmp) && +		    error == NFSERR_BADSTATEID)) && clidrev != 0) { +			expireret = nfscl_hasexpired(nmp->nm_clp, clidrev, +			    curthread); +		} else if (error == NFSERR_BADSTATEID && NFSHASINT(nmp)) { +			error = EIO; +		} +		retrycnt++; +	} while (error == NFSERR_GRACE || error == NFSERR_DELAY || +	    error == NFSERR_STALESTATEID || error == NFSERR_BADSESSION || +	      error == NFSERR_STALEDONTRECOVER || +	    (error == NFSERR_OLDSTATEID && retrycnt < 20) || +	    ((error == NFSERR_EXPIRED || error == NFSERR_BADSTATEID) && +	     expireret == 0 && clidrev != 0 && retrycnt < 4)); +	if (error != 0 && (retrycnt >= 4 || +	    error == NFSERR_STALESTATEID || error == NFSERR_BADSESSION || +	      error == NFSERR_STALEDONTRECOVER)) +		error = EIO; +	return (error); +} + +/* + * The clone RPC. + */ +static int +nfsrpc_clonerpc(vnode_t invp, off_t inoff, vnode_t outvp, off_t outoff, +    size_t *lenp, bool toeof, nfsv4stateid_t *instateidp, +    nfsv4stateid_t *outstateidp, struct nfsvattr *innap, int *inattrflagp, +    struct nfsvattr *outnap, int *outattrflagp, struct ucred *cred, +    NFSPROC_T *p) +{ +	uint32_t *tl, *opcntp; +	int error; +	struct nfsrv_descript nfsd; +	struct nfsrv_descript *nd = &nfsd; +	struct nfsmount *nmp; +	nfsattrbit_t attrbits; +	struct vattr va; +	uint64_t len; + +	nmp = VFSTONFS(invp->v_mount); +	*inattrflagp = *outattrflagp = 0; +	len = *lenp; +	if (len == 0) +		return (0); +	if (toeof) +		len = 0; +	nfscl_reqstart(nd, NFSPROC_CLONE, nmp, VTONFS(invp)->n_fhp->nfh_fh, +	    VTONFS(invp)->n_fhp->nfh_len, &opcntp, NULL, 0, 0, cred); +	/* +	 * First do a Setattr of atime to the server's clock +	 * time.  The FreeBSD "collective" was of the opinion +	 * that setting atime was necessary for this syscall. +	 * Do the Setattr before the Clone, so that it can be +	 * handled well if the server replies NFSERR_DELAY to +	 * the Setattr operation. +	 */ +	if ((nmp->nm_mountp->mnt_flag & MNT_NOATIME) == 0) { +		NFSM_BUILD(tl, uint32_t *, NFSX_UNSIGNED); +		*tl = txdr_unsigned(NFSV4OP_SETATTR); +		nfsm_stateidtom(nd, instateidp, NFSSTATEID_PUTSTATEID); +		VATTR_NULL(&va); +		va.va_atime.tv_sec = va.va_atime.tv_nsec = 0; +		va.va_vaflags = VA_UTIMES_NULL; +		nfscl_fillsattr(nd, &va, invp, 0, 0); +		/* Bump opcnt from 7 to 8. */ +		*opcntp = txdr_unsigned(8); +	} + +	/* Now Getattr the invp attributes. */ +	NFSM_BUILD(tl, uint32_t *, NFSX_UNSIGNED); +	*tl = txdr_unsigned(NFSV4OP_GETATTR); +	NFSGETATTR_ATTRBIT(&attrbits); +	nfsrv_putattrbit(nd, &attrbits); + +	/* Set outvp. */ +	NFSM_BUILD(tl, uint32_t *, NFSX_UNSIGNED); +	*tl = txdr_unsigned(NFSV4OP_PUTFH); +	(void)nfsm_fhtom(nmp, nd, VTONFS(outvp)->n_fhp->nfh_fh, +	    VTONFS(outvp)->n_fhp->nfh_len, 0); + +	/* Do the Clone. */ +	NFSM_BUILD(tl, uint32_t *, NFSX_UNSIGNED); +	*tl = txdr_unsigned(NFSV4OP_CLONE); +	nfsm_stateidtom(nd, instateidp, NFSSTATEID_PUTSTATEID); +	nfsm_stateidtom(nd, outstateidp, NFSSTATEID_PUTSTATEID); +	NFSM_BUILD(tl, uint32_t *, 3 * NFSX_HYPER + NFSX_UNSIGNED); +	txdr_hyper(inoff, tl); tl += 2; +	txdr_hyper(outoff, tl); tl += 2; +	txdr_hyper(len, tl); tl += 2; + +	/* Get the outvp attributes. */ +	*tl = txdr_unsigned(NFSV4OP_GETATTR); +	NFSWRITEGETATTR_ATTRBIT(&attrbits); +	nfsrv_putattrbit(nd, &attrbits); + +	error = nfscl_request(nd, invp, p, cred); +	if (error != 0) +		return (error); +	/* Skip over the Setattr reply. */ +	if ((nd->nd_flag & ND_NOMOREDATA) == 0 && +	    (nmp->nm_mountp->mnt_flag & MNT_NOATIME) == 0) { +		NFSM_DISSECT(tl, uint32_t *, 2 * NFSX_UNSIGNED); +		if (*(tl + 1) == 0) { +			error = nfsrv_getattrbits(nd, &attrbits, NULL, NULL); +			if (error != 0) +				goto nfsmout; +		} else +			nd->nd_flag |= ND_NOMOREDATA; +	} +	if ((nd->nd_flag & ND_NOMOREDATA) == 0) { +		/* Get the input file's attributes. */ +		NFSM_DISSECT(tl, uint32_t *, 2 * NFSX_UNSIGNED); +		if (*(tl + 1) == 0) { +			error = nfsm_loadattr(nd, innap); +			if (error != 0) +				goto nfsmout; +			*inattrflagp = 1; +		} else +			nd->nd_flag |= ND_NOMOREDATA; +	} +	/* Skip over return stat for PutFH. */ +	if ((nd->nd_flag & ND_NOMOREDATA) == 0) { +		NFSM_DISSECT(tl, uint32_t *, 2 * NFSX_UNSIGNED); +		if (*++tl != 0) +			nd->nd_flag |= ND_NOMOREDATA; +	} +	/* Skip over return stat for Clone. */ +	if ((nd->nd_flag & ND_NOMOREDATA) == 0) +		NFSM_DISSECT(tl, uint32_t *, 2 * NFSX_UNSIGNED); +	if (nd->nd_repstat == 0) { +		NFSM_DISSECT(tl, uint32_t *, 2 * NFSX_UNSIGNED); +		error = nfsm_loadattr(nd, outnap); +		if (error == 0) +			*outattrflagp = NFS_LATTR_NOSHRINK; +	} else { +		*lenp = 0; +	} +	if (error == 0) +		error = nd->nd_repstat; +nfsmout: +	m_freem(nd->nd_mrep); +	return (error); +} + +/*   * Seek operation.   */  int @@ -9544,7 +9760,7 @@ nfsm_split(struct mbuf *mp, uint64_t xfer)  		pgno++;  	} while (pgno < m->m_epg_npgs);  	if (pgno == m->m_epg_npgs) -		panic("nfsm_split: eroneous ext_pgs mbuf"); +		panic("nfsm_split: erroneous ext_pgs mbuf");  	m2 = mb_alloc_ext_pgs(M_WAITOK, mb_free_mext_pgs, 0);  	m2->m_epg_flags |= EPG_FLAG_ANON; @@ -9724,13 +9940,13 @@ nfscl_statfs(struct vnode *vp, struct ucred *cred, NFSPROC_T *td)  	struct nfsstatfs sb;  	struct mount *mp;  	struct nfsmount *nmp; -	uint32_t lease; +	uint32_t clone_blksize, lease;  	int attrflag, error;  	mp = vp->v_mount;  	nmp = VFSTONFS(mp); -	error = nfsrpc_statfs(vp, &sb, &fs, &lease, cred, td, &nfsva, -	    &attrflag); +	error = nfsrpc_statfs(vp, &sb, &fs, &lease, &clone_blksize, cred, td, +	    &nfsva, &attrflag);  	if (attrflag != 0)  		(void) nfscl_loadattrcache(&vp, &nfsva, NULL, 0, 1);  	if (error == 0) { @@ -9739,7 +9955,7 @@ nfscl_statfs(struct vnode *vp, struct ucred *cred, NFSPROC_T *td)  			nmp->nm_clp->nfsc_renew = NFSCL_RENEW(lease);  		NFSUNLOCKCLSTATE();  		mtx_lock(&nmp->nm_mtx); -		nfscl_loadfsinfo(nmp, &fs); +		nfscl_loadfsinfo(nmp, &fs, clone_blksize);  		nfscl_loadsbinfo(nmp, &sb, &mp->mnt_stat);  		mp->mnt_stat.f_iosize = newnfs_iosize(nmp);  		mtx_unlock(&nmp->nm_mtx); diff --git a/sys/fs/nfsclient/nfs_clstate.c b/sys/fs/nfsclient/nfs_clstate.c index 99a781640c53..aa9d01fc4632 100644 --- a/sys/fs/nfsclient/nfs_clstate.c +++ b/sys/fs/nfsclient/nfs_clstate.c @@ -3701,7 +3701,7 @@ nfscl_docb(struct nfsrv_descript *nd, NFSPROC_T *p)  			if (!error)  				(void) nfsv4_fillattr(nd, NULL, NULL, NULL, &va,  				    NULL, 0, &rattrbits, NULL, p, 0, 0, 0, 0, -				    (uint64_t)0, NULL, false, false, false); +				    (uint64_t)0, NULL, false, false, false, 0);  			break;  		case NFSV4OP_CBRECALL:  			NFSCL_DEBUG(4, "cbrecall\n"); diff --git a/sys/fs/nfsclient/nfs_clvfsops.c b/sys/fs/nfsclient/nfs_clvfsops.c index 0bd05c03885b..212c88f28930 100644 --- a/sys/fs/nfsclient/nfs_clvfsops.c +++ b/sys/fs/nfsclient/nfs_clvfsops.c @@ -292,8 +292,10 @@ nfs_statfs(struct mount *mp, struct statfs *sbp)  	int error = 0, attrflag, gotfsinfo = 0, ret;  	struct nfsnode *np;  	char *fakefh; +	uint32_t clone_blksize;  	td = curthread; +	clone_blksize = 0;  	error = vfs_busy(mp, MBF_NOWAIT);  	if (error) @@ -337,8 +339,8 @@ nfs_statfs(struct mount *mp, struct statfs *sbp)  	} else  		mtx_unlock(&nmp->nm_mtx);  	if (!error) -		error = nfsrpc_statfs(vp, &sb, &fs, NULL, td->td_ucred, td, -		    &nfsva, &attrflag); +		error = nfsrpc_statfs(vp, &sb, &fs, NULL, &clone_blksize, +		    td->td_ucred, td, &nfsva, &attrflag);  	if ((nmp->nm_privflag & NFSMNTP_FAKEROOTFH) != 0 &&  	    error == NFSERR_WRONGSEC) {  		/* Cannot get new stats, so return what is in mnt_stat. */ @@ -375,7 +377,7 @@ nfs_statfs(struct mount *mp, struct statfs *sbp)  	if (!error) {  	    mtx_lock(&nmp->nm_mtx);  	    if (gotfsinfo || (nmp->nm_flag & NFSMNT_NFSV4)) -		nfscl_loadfsinfo(nmp, &fs); +		nfscl_loadfsinfo(nmp, &fs, clone_blksize);  	    nfscl_loadsbinfo(nmp, &sb, sbp);  	    sbp->f_iosize = newnfs_iosize(nmp);  	    mtx_unlock(&nmp->nm_mtx); @@ -408,7 +410,7 @@ ncl_fsinfo(struct nfsmount *nmp, struct vnode *vp, struct ucred *cred,  		if (attrflag)  			(void) nfscl_loadattrcache(&vp, &nfsva, NULL, 0, 1);  		mtx_lock(&nmp->nm_mtx); -		nfscl_loadfsinfo(nmp, &fs); +		nfscl_loadfsinfo(nmp, &fs, 0);  		mtx_unlock(&nmp->nm_mtx);  	}  	return (error); @@ -925,7 +927,7 @@ nfs_mount(struct mount *mp)  	struct vnode *vp;  	struct thread *td;  	char *hst; -	u_char nfh[NFSX_FHMAX], krbname[100], dirpath[100], srvkrbname[100]; +	u_char nfh[NFSX_FHMAX], krbname[100], *dirpath, srvkrbname[100];  	char *cp, *opt, *name, *secname, *tlscertname;  	int nametimeo = NFS_DEFAULT_NAMETIMEO;  	int negnametimeo = NFS_DEFAULT_NEGNAMETIMEO; @@ -941,6 +943,7 @@ nfs_mount(struct mount *mp)  	newflag = 0;  	tlscertname = NULL;  	hst = malloc(MNAMELEN, M_TEMP, M_WAITOK); +	dirpath = malloc(MNAMELEN, M_TEMP, M_WAITOK);  	if (vfs_filteropt(mp->mnt_optnew, nfs_opts)) {  		error = EINVAL;  		goto out; @@ -1327,7 +1330,7 @@ nfs_mount(struct mount *mp)  			goto out;  	} else if (nfs_mount_parse_from(mp->mnt_optnew,  	    &args.hostname, (struct sockaddr_in **)&nam, dirpath, -	    sizeof(dirpath), &dirlen) == 0) { +	    MNAMELEN, &dirlen) == 0) {  		has_nfs_from_opt = 1;  		bcopy(args.hostname, hst, MNAMELEN);  		hst[MNAMELEN - 1] = '\0'; @@ -1385,7 +1388,7 @@ nfs_mount(struct mount *mp)  	if (has_nfs_from_opt == 0) {  		if (vfs_getopt(mp->mnt_optnew,  		    "dirpath", (void **)&name, NULL) == 0) -			strlcpy(dirpath, name, sizeof (dirpath)); +			strlcpy(dirpath, name, MNAMELEN);  		else  			dirpath[0] = '\0';  		dirlen = strlen(dirpath); @@ -1470,6 +1473,7 @@ out:  		MNT_IUNLOCK(mp);  	}  	free(hst, M_TEMP); +	free(dirpath, M_TEMP);  	return (error);  } diff --git a/sys/fs/nfsclient/nfs_clvnops.c b/sys/fs/nfsclient/nfs_clvnops.c index fa451887e73e..f80cf30669ca 100644 --- a/sys/fs/nfsclient/nfs_clvnops.c +++ b/sys/fs/nfsclient/nfs_clvnops.c @@ -1026,7 +1026,7 @@ nfs_getattr(struct vop_getattr_args *ap)  	 * cached attributes should be ignored.  	 */  	if (nmp->nm_fhsize > 0 && ncl_getattrcache(vp, &vattr) == 0) { -		ncl_copy_vattr(vap, &vattr); +		ncl_copy_vattr(vp, vap, &vattr);  		/*  		 * Get the local modify time for the case of a write @@ -1081,12 +1081,14 @@ nfs_setattr(struct vop_setattr_args *ap)  #endif  	/* -	 * Only setting of UF_HIDDEN and UF_SYSTEM are supported and +	 * Only setting of UF_ARCHIVE, UF_HIDDEN and UF_SYSTEM are supported and  	 * only for NFSv4 servers that support them.  	 */  	nmp = VFSTONFS(vp->v_mount);  	if (vap->va_flags != VNOVAL && (!NFSHASNFSV4(nmp) || -	    (vap->va_flags & ~(UF_HIDDEN | UF_SYSTEM)) != 0 || +	    (vap->va_flags & ~(UF_ARCHIVE | UF_HIDDEN | UF_SYSTEM)) != 0 || +	    ((vap->va_flags & UF_ARCHIVE) != 0 && +	     !NFSISSET_ATTRBIT(&np->n_vattr.na_suppattr, NFSATTRBIT_ARCHIVE)) ||  	    ((vap->va_flags & UF_HIDDEN) != 0 &&  	     !NFSISSET_ATTRBIT(&np->n_vattr.na_suppattr, NFSATTRBIT_HIDDEN)) ||  	    ((vap->va_flags & UF_SYSTEM) != 0 && @@ -1284,7 +1286,7 @@ nfs_lookup(struct vop_lookup_args *ap)  	bool is_nameddir, needs_nameddir, opennamed;  	dattrflag = 0; -	*vpp = NULLVP; +	*vpp = NULL;  	nmp = VFSTONFS(mp);  	opennamed = (flags & (OPENNAMED | ISLASTCN)) == (OPENNAMED | ISLASTCN);  	if (opennamed && (!NFSHASNFSV4(nmp) || !NFSHASNFSV4N(nmp))) @@ -1309,7 +1311,7 @@ nfs_lookup(struct vop_lookup_args *ap)  	/*  	 * If the named attribute directory is needed, acquire it now.  	 */ -	newvp = NULLVP; +	newvp = NULL;  	if (needs_nameddir) {  		KASSERT(np->n_v4 == NULL, ("nfs_lookup: O_NAMEDATTR when"  		    " n_v4 not NULL")); @@ -1322,10 +1324,10 @@ nfs_lookup(struct vop_lookup_args *ap)  		}  		dvp = newvp;  		np = VTONFS(dvp); -		newvp = NULLVP; +		newvp = NULL;  	} else if (opennamed && cnp->cn_namelen == 1 &&  	    *cnp->cn_nameptr == '.') { -		VREF(dvp); +		vref(dvp);  		*vpp = dvp;  		return (0);  	} @@ -1399,7 +1401,7 @@ nfs_lookup(struct vop_lookup_args *ap)  				vput(newvp);  			else  				vrele(newvp); -			*vpp = NULLVP; +			*vpp = NULL;  		} else if (error == ENOENT) {  			if (VN_IS_DOOMED(dvp))  				return (ENOENT); @@ -1450,7 +1452,7 @@ nfs_lookup(struct vop_lookup_args *ap)  	NFSUNLOCKMNT(nmp);  #endif -	newvp = NULLVP; +	newvp = NULL;  	NFSINCRGLOBAL(nfsstatsv1.lookupcache_misses);  	nanouptime(&ts);  	error = nfsrpc_lookup(dvp, cnp->cn_nameptr, cnp->cn_namelen, @@ -1464,9 +1466,9 @@ nfs_lookup(struct vop_lookup_args *ap)  	}  handle_error:  	if (error) { -		if (newvp != NULLVP) { +		if (newvp != NULL) {  			vput(newvp); -			*vpp = NULLVP; +			*vpp = NULL;  		}  		if (error != ENOENT) { @@ -1587,7 +1589,7 @@ handle_error:  			    0, 1);  	} else if (NFS_CMPFH(np, nfhp->nfh_fh, nfhp->nfh_len)) {  		free(nfhp, M_NFSFH); -		VREF(dvp); +		vref(dvp);  		newvp = dvp;  		if (attrflag)  			(void) nfscl_loadattrcache(&newvp, &nfsva, NULL, @@ -1782,7 +1784,7 @@ nfs_mknodrpc(struct vnode *dvp, struct vnode **vpp, struct componentname *cnp,  	int error = 0, attrflag, dattrflag;  	u_int32_t rdev; -	if (vap->va_type == VCHR || vap->va_type == VBLK) +	if (VATTR_ISDEV(vap))  		rdev = vap->va_rdev;  	else if (vap->va_type == VFIFO || vap->va_type == VSOCK)  		rdev = 0xffffffff; @@ -2863,7 +2865,7 @@ nfs_sillyrename(struct vnode *dvp, struct vnode *vp, struct componentname *cnp)  	    M_NEWNFSREQ, M_WAITOK);  	sp->s_cred = crhold(cnp->cn_cred);  	sp->s_dvp = dvp; -	VREF(dvp); +	vref(dvp);  	/*   	 * Fudge together a funny name. @@ -2961,7 +2963,7 @@ nfs_lookitup(struct vnode *dvp, char *name, int len, struct ucred *cred,  		    newvp = NFSTOV(np);  		} else if (NFS_CMPFH(dnp, nfhp->nfh_fh, nfhp->nfh_len)) {  		    free(nfhp, M_NFSFH); -		    VREF(dvp); +		    vref(dvp);  		    newvp = dvp;  		} else {  		    cn.cn_nameptr = name; @@ -3474,7 +3476,7 @@ nfs_advlock(struct vop_advlock_args *ap)  	u_quad_t size;  	struct nfsmount *nmp; -	error = NFSVOPLOCK(vp, LK_SHARED); +	error = NFSVOPLOCK(vp, LK_EXCLUSIVE);  	if (error != 0)  		return (EBADF);  	nmp = VFSTONFS(vp->v_mount); @@ -3511,11 +3513,6 @@ nfs_advlock(struct vop_advlock_args *ap)  			cred = p->p_ucred;  		else  			cred = td->td_ucred; -		NFSVOPLOCK(vp, LK_UPGRADE | LK_RETRY); -		if (VN_IS_DOOMED(vp)) { -			error = EBADF; -			goto out; -		}  		/*  		 * If this is unlocking a write locked region, flush and @@ -4027,31 +4024,51 @@ nfs_copy_file_range(struct vop_copy_file_range_args *ap)  	struct vattr va, *vap;  	struct uio io;  	struct nfsmount *nmp; +	struct nfsnode *np;  	size_t len, len2;  	ssize_t r;  	int error, inattrflag, outattrflag, ret, ret2, invp_lock;  	off_t inoff, outoff; -	bool consecutive, must_commit, tryoutcred; +	bool consecutive, must_commit, onevp, toeof, tryclone, tryoutcred; +	bool mustclone;  	/*  	 * NFSv4.2 Copy is not permitted for infile == outfile. +	 * The NFSv4.2 Clone operation does work on non-overlapping +	 * byte ranges in the same file, but only if offsets +	 * (and len if not to EOF) are aligned properly.  	 * TODO: copy_file_range() between multiple NFS mountpoints +	 * --> This is not possible now, since each mount appears to +	 *     the NFSv4.n server as a separate client.  	 */ -	if (invp == outvp || invp->v_mount != outvp->v_mount) { +	if ((invp == outvp && (ap->a_flags & COPY_FILE_RANGE_CLONE) == 0) || +	    (invp != outvp && invp->v_mount != outvp->v_mount)) {  generic_copy:  		return (ENOSYS);  	} - -	invp_lock = LK_SHARED; +	if (invp == outvp) { +		onevp = true; +		invp_lock = LK_EXCLUSIVE; +	} else { +		onevp = false; +		invp_lock = LK_SHARED; +	} +	mustclone = false; +	if (onevp || (ap->a_flags & COPY_FILE_RANGE_CLONE) != 0) +		mustclone = true;  relock: +	inoff = *ap->a_inoffp; +	outoff = *ap->a_outoffp; -	/* Lock both vnodes, avoiding risk of deadlock. */ +	/* Lock vnode(s), avoiding risk of deadlock. */  	do {  		mp = NULL;  		error = vn_start_write(outvp, &mp, V_WAIT);  		if (error == 0) {  			error = vn_lock(outvp, LK_EXCLUSIVE);  			if (error == 0) { +				if (onevp) +					break;  				error = vn_lock(invp, invp_lock | LK_NOWAIT);  				if (error == 0)  					break; @@ -4071,16 +4088,24 @@ relock:  		return (error);  	/* -	 * More reasons to avoid nfs copy: not NFSv4.2, or explicitly -	 * disabled. +	 * More reasons to avoid nfs copy/clone: not NFSv4.2, explicitly +	 * disabled or requires cloning and unable to clone. +	 * Only clone if the clone_blksize attribute is supported +	 * and the clone_blksize is greater than 0. +	 * Alignment of offsets and length will be checked later.  	 */  	nmp = VFSTONFS(invp->v_mount); +	np = VTONFS(invp);  	mtx_lock(&nmp->nm_mtx); +	if ((nmp->nm_privflag & NFSMNTP_NOCOPY) != 0) +		mustclone = true;  	if (!NFSHASNFSV4(nmp) || nmp->nm_minorvers < NFSV42_MINORVERSION || -	    (nmp->nm_privflag & NFSMNTP_NOCOPY) != 0) { +	    (mustclone && (!NFSISSET_ATTRBIT(&np->n_vattr.na_suppattr, +	     NFSATTRBIT_CLONEBLKSIZE) || nmp->nm_cloneblksize == 0))) {  		mtx_unlock(&nmp->nm_mtx);  		VOP_UNLOCK(invp); -		VOP_UNLOCK(outvp); +		if (!onevp) +			VOP_UNLOCK(outvp);	/* For onevp, same as invp. */  		if (mp != NULL)  			vn_finished_write(mp);  		goto generic_copy; @@ -4111,6 +4136,8 @@ relock:  		invp_obj = invp->v_object;  		if (invp_obj != NULL && vm_object_mightbedirty(invp_obj)) {  			if (invp_lock != LK_EXCLUSIVE) { +				KASSERT(!onevp, ("nfs_copy_file_range: " +				    "invp_lock LK_SHARED for onevp"));  				invp_lock = LK_EXCLUSIVE;  				VOP_UNLOCK(invp);  				VOP_UNLOCK(outvp); @@ -4134,10 +4161,10 @@ relock:  	else  		consecutive = false;  	mtx_unlock(&nmp->nm_mtx); -	inoff = *ap->a_inoffp; -	outoff = *ap->a_outoffp;  	tryoutcred = true;  	must_commit = false; +	toeof = false; +  	if (error == 0) {  		vap = &VTONFS(invp)->n_vattr.na_vattr;  		error = VOP_GETATTR(invp, vap, ap->a_incred); @@ -4169,29 +4196,63 @@ relock:  					if (error == 0 && ret != 0)  						error = ret;  				} -			} else if (inoff + len > vap->va_size) +			} else if (inoff + len >= vap->va_size) { +				toeof = true;  				*ap->a_lenp = len = vap->va_size - inoff; +			}  		} else  			error = 0;  	}  	/* +	 * For cloning, the offsets must be clone blksize aligned and +	 * the len must be blksize aligned unless it goes to EOF on +	 * the input file. +	 */ +	tryclone = false; +	if (len > 0) { +		if (error == 0 && NFSISSET_ATTRBIT(&np->n_vattr.na_suppattr, +		    NFSATTRBIT_CLONEBLKSIZE) && nmp->nm_cloneblksize != 0 && +		    (inoff % nmp->nm_cloneblksize) == 0 && +		    (outoff % nmp->nm_cloneblksize) == 0 && +		    (toeof || (len % nmp->nm_cloneblksize) == 0)) +			tryclone = true; +		else if (mustclone) +			error = ENOSYS; +	} + +	/*  	 * len will be set to 0 upon a successful Copy RPC. -	 * As such, this only loops when the Copy RPC needs to be retried. +	 * As such, this only loops when the Copy/Clone RPC needs to be retried.  	 */  	while (len > 0 && error == 0) {  		inattrflag = outattrflag = 0;  		len2 = len; -		if (tryoutcred) -			error = nfsrpc_copy_file_range(invp, ap->a_inoffp, -			    outvp, ap->a_outoffp, &len2, ap->a_flags, -			    &inattrflag, &innfsva, &outattrflag, &outnfsva, -			    ap->a_outcred, consecutive, &must_commit); -		else -			error = nfsrpc_copy_file_range(invp, ap->a_inoffp, -			    outvp, ap->a_outoffp, &len2, ap->a_flags, -			    &inattrflag, &innfsva, &outattrflag, &outnfsva, -			    ap->a_incred, consecutive, &must_commit); +		if (tryclone) { +			if (tryoutcred) +				error = nfsrpc_clone(invp, ap->a_inoffp, outvp, +				    ap->a_outoffp, &len2, toeof, &inattrflag, +				    &innfsva, &outattrflag, &outnfsva, +				    ap->a_outcred); +			else +				error = nfsrpc_clone(invp, ap->a_inoffp, outvp, +				    ap->a_outoffp, &len2, toeof, &inattrflag, +				    &innfsva, &outattrflag, &outnfsva, +				    ap->a_incred); +		} else { +			if (tryoutcred) +				error = nfsrpc_copy_file_range(invp, +				    ap->a_inoffp, outvp, ap->a_outoffp, &len2, +				    ap->a_flags, &inattrflag, &innfsva, +				    &outattrflag, &outnfsva, +				    ap->a_outcred, consecutive, &must_commit); +			else +				error = nfsrpc_copy_file_range(invp, +				    ap->a_inoffp, outvp, ap->a_outoffp, &len2, +				    ap->a_flags, &inattrflag, &innfsva, +				    &outattrflag, &outnfsva, +				    ap->a_incred, consecutive, &must_commit); +		}  		if (inattrflag != 0)  			ret = nfscl_loadattrcache(&invp, &innfsva, NULL, 0, 1);  		if (outattrflag != 0) @@ -4230,6 +4291,13 @@ relock:  			/* Try again with incred. */  			tryoutcred = false;  			error = 0; +		} else if (tryclone && error != 0) { +			if (mustclone) { +				error = ENOSYS; +			} else { +				tryclone = false; +				error = 0; +			}  		}  		if (error == NFSERR_STALEWRITEVERF) {  			/* @@ -4243,11 +4311,12 @@ relock:  		}  	}  	VOP_UNLOCK(invp); -	VOP_UNLOCK(outvp); +	if (!onevp) +		VOP_UNLOCK(outvp);	/* For onevp, same as invp. */  	if (mp != NULL)  		vn_finished_write(mp);  	if (error == NFSERR_NOTSUPP || error == NFSERR_OFFLOADNOREQS || -	    error == NFSERR_ACCES) { +	    error == NFSERR_ACCES || error == ENOSYS) {  		/*  		 * Unlike the NFSv4.2 Copy, vn_generic_copy_file_range() can  		 * use a_incred for the read and a_outcred for the write, so @@ -4255,7 +4324,7 @@ relock:  		 * For NFSERR_NOTSUPP and NFSERR_OFFLOADNOREQS, the Copy can  		 * never succeed, so disable it.  		 */ -		if (error != NFSERR_ACCES) { +		if (error != NFSERR_ACCES && error != ENOSYS) {  			/* Can never do Copy on this mount. */  			mtx_lock(&nmp->nm_mtx);  			nmp->nm_privflag |= NFSMNTP_NOCOPY; @@ -4596,6 +4665,7 @@ nfs_pathconf(struct vop_pathconf_args *ap)  	struct nfsmount *nmp;  	struct thread *td = curthread;  	off_t off; +	uint32_t clone_blksize;  	bool eof, has_namedattr, named_enabled;  	int attrflag, error;  	struct nfsnode *np; @@ -4604,19 +4674,22 @@ nfs_pathconf(struct vop_pathconf_args *ap)  	np = VTONFS(vp);  	named_enabled = false;  	has_namedattr = false; +	clone_blksize = 0;  	if ((NFS_ISV34(vp) && (ap->a_name == _PC_LINK_MAX ||  	    ap->a_name == _PC_NAME_MAX || ap->a_name == _PC_CHOWN_RESTRICTED ||  	    ap->a_name == _PC_NO_TRUNC)) ||  	    (NFS_ISV4(vp) && (ap->a_name == _PC_ACL_NFS4 || -	     ap->a_name == _PC_HAS_NAMEDATTR))) { +	     ap->a_name == _PC_HAS_NAMEDATTR || +	     ap->a_name == _PC_CLONE_BLKSIZE))) {  		/*  		 * Since only the above 4 a_names are returned by the NFSv3  		 * Pathconf RPC, there is no point in doing it for others.  		 * For NFSv4, the Pathconf RPC (actually a Getattr Op.) can -		 * be used for _PC_ACL_NFS4 and _PC_HAS_NAMEDATTR as well. +		 * be used for _PC_ACL_NFS4, _PC_HAS_NAMEDATTR and +		 * _PC_CLONE_BLKSIZE as well.  		 */ -		error = nfsrpc_pathconf(vp, &pc, &has_namedattr, td->td_ucred, -		    td, &nfsva, &attrflag); +		error = nfsrpc_pathconf(vp, &pc, &has_namedattr, &clone_blksize, +		    td->td_ucred, td, &nfsva, &attrflag);  		if (attrflag != 0)  			(void) nfscl_loadattrcache(&vp, &nfsva, NULL, 0, 1);  		if (error != 0) @@ -4764,6 +4837,8 @@ nfs_pathconf(struct vop_pathconf_args *ap)  		break;  	case _PC_HAS_HIDDENSYSTEM:  		if (NFS_ISV4(vp) && NFSISSET_ATTRBIT(&np->n_vattr.na_suppattr, +		    NFSATTRBIT_ARCHIVE) && +		    NFSISSET_ATTRBIT(&np->n_vattr.na_suppattr,  		    NFSATTRBIT_HIDDEN) &&  		    NFSISSET_ATTRBIT(&np->n_vattr.na_suppattr,  		    NFSATTRBIT_SYSTEM)) @@ -4771,6 +4846,9 @@ nfs_pathconf(struct vop_pathconf_args *ap)  		else  			*ap->a_retval = 0;  		break; +	case _PC_CLONE_BLKSIZE: +		*ap->a_retval = clone_blksize; +		break;  	default:  		error = vop_stdpathconf(ap); diff --git a/sys/fs/nfsclient/nfsmount.h b/sys/fs/nfsclient/nfsmount.h index 37b84a015dab..ef876dd30e59 100644 --- a/sys/fs/nfsclient/nfsmount.h +++ b/sys/fs/nfsclient/nfsmount.h @@ -87,6 +87,7 @@ struct	nfsmount {  					/* unclipped, wraps to 0 */  	struct __rpc_client *nm_aconn[NFS_MAXNCONN - 1]; /* Additional nconn */  					/* Locked via nm_sockreq.nr_mtx */ +	uint32_t nm_cloneblksize;	/* Block cloning alignment */  	u_int16_t nm_krbnamelen;	/* Krb5 host principal, if any */  	u_int16_t nm_dirpathlen;	/* and mount dirpath, for V4 */  	u_int16_t nm_srvkrbnamelen;	/* and the server's target name */ diff --git a/sys/fs/nfsserver/nfs_nfsdport.c b/sys/fs/nfsserver/nfs_nfsdport.c index 8c427c66c156..9fe3f4426124 100644 --- a/sys/fs/nfsserver/nfs_nfsdport.c +++ b/sys/fs/nfsserver/nfs_nfsdport.c @@ -675,7 +675,7 @@ nfsvno_namei(struct nfsrv_descript *nd, struct nameidata *ndp,  	}  	if (islocked)  		NFSVOPUNLOCK(dp); -	VREF(dp); +	vref(dp);  	*retdirp = dp;  	if (NFSVNO_EXRDONLY(exp))  		cnp->cn_flags |= RDONLY; @@ -697,7 +697,7 @@ nfsvno_namei(struct nfsrv_descript *nd, struct nameidata *ndp,  				goto out;  			}  			dp = rootvnode; -			VREF(dp); +			vref(dp);  		}  	} else if ((nfsrv_enable_crossmntpt == 0 && NFSVNO_EXPORTED(exp)) ||  	    (nd->nd_flag & ND_NFSV4) == 0) { @@ -814,7 +814,7 @@ nfsvno_namei(struct nfsrv_descript *nd, struct nameidata *ndp,  		if (cnp->cn_pnbuf[0] == '/') {  			vrele(ndp->ni_dvp);  			ndp->ni_dvp = ndp->ni_rootdir; -			VREF(ndp->ni_dvp); +			vref(ndp->ni_dvp);  		}  		ndp->ni_startdir = ndp->ni_dvp;  		ndp->ni_dvp = NULL; @@ -2113,7 +2113,8 @@ nfsvno_fillattr(struct nfsrv_descript *nd, struct mount *mp, struct vnode *vp,      struct nfsvattr *nvap, fhandle_t *fhp, int rderror, nfsattrbit_t *attrbitp,      struct ucred *cred, struct thread *p, int isdgram, int reterr,      int supports_nfsv4acls, int at_root, uint64_t mounted_on_fileno, -    bool xattrsupp, bool has_hiddensystem, bool has_namedattr) +    bool xattrsupp, bool has_hiddensystem, bool has_namedattr, +    uint32_t clone_blksize)  {  	struct statfs *sf;  	int error; @@ -2130,9 +2131,11 @@ nfsvno_fillattr(struct nfsrv_descript *nd, struct mount *mp, struct vnode *vp,  			sf = NULL;  		}  	} +  	error = nfsv4_fillattr(nd, mp, vp, NULL, &nvap->na_vattr, fhp, rderror,  	    attrbitp, cred, p, isdgram, reterr, supports_nfsv4acls, at_root, -	    mounted_on_fileno, sf, xattrsupp, has_hiddensystem, has_namedattr); +	    mounted_on_fileno, sf, xattrsupp, has_hiddensystem, has_namedattr, +	    clone_blksize);  	free(sf, M_TEMP);  	NFSEXITCODE2(0, nd);  	return (error); @@ -2441,7 +2444,7 @@ nfsrvd_readdirplus(struct nfsrv_descript *nd, int isdgram,      struct vnode *vp, struct nfsexstuff *exp)  {  	struct dirent *dp; -	u_int32_t *tl; +	uint32_t clone_blksize, *tl;  	int dirlen;  	char *cpos, *cend, *rbuf;  	struct vnode *nvp; @@ -2604,6 +2607,7 @@ again:  	 * rpc reply  	 */  	if (siz == 0) { +ateof:  		vput(vp);  		if (nd->nd_flag & ND_NFSV3)  			nfsrv_postopattr(nd, getret, &at); @@ -2645,6 +2649,8 @@ again:  		ncookies--;  	}  	if (cpos >= cend || ncookies == 0) { +		if (eofflag != 0) +			goto ateof;  		siz = fullsiz;  		toff = off;  		goto again; @@ -2943,6 +2949,7 @@ again:  				xattrsupp = false;  				has_hiddensystem = false;  				has_namedattr = false; +				clone_blksize = 0;  				if (nvp != NULL) {  					supports_nfsv4acls =  					    nfs_supportsnfsv4acls(nvp); @@ -2966,6 +2973,11 @@ again:  					    &pathval) != 0)  						pathval = 0;  					has_namedattr = pathval > 0; +					pathval = 0; +					if (VOP_PATHCONF(nvp, _PC_CLONE_BLKSIZE, +					    &pathval) != 0) +						pathval = 0; +					clone_blksize = pathval;  					NFSVOPUNLOCK(nvp);  				} else  					supports_nfsv4acls = 0; @@ -2986,14 +2998,16 @@ again:  					    nd->nd_cred, p, isdgram, 0,  					    supports_nfsv4acls, at_root,  					    mounted_on_fileno, xattrsupp, -					    has_hiddensystem, has_namedattr); +					    has_hiddensystem, has_namedattr, +					    clone_blksize);  				} else {  					dirlen += nfsvno_fillattr(nd, new_mp,  					    nvp, nvap, &nfh, r, &attrbits,  					    nd->nd_cred, p, isdgram, 0,  					    supports_nfsv4acls, at_root,  					    mounted_on_fileno, xattrsupp, -					    has_hiddensystem, has_namedattr); +					    has_hiddensystem, has_namedattr, +					    clone_blksize);  				}  				if (nvp != NULL)  					vrele(nvp); @@ -3179,7 +3193,8 @@ nfsv4_sattr(struct nfsrv_descript *nd, vnode_t vp, struct nfsvattr *nvap,  		bitpos = NFSATTRBIT_MAX;  	} else {  		bitpos = 0; -		if (NFSISSET_ATTRBIT(attrbitp, NFSATTRBIT_HIDDEN) || +		if (NFSISSET_ATTRBIT(attrbitp, NFSATTRBIT_ARCHIVE) || +		    NFSISSET_ATTRBIT(attrbitp, NFSATTRBIT_HIDDEN) ||  		    NFSISSET_ATTRBIT(attrbitp, NFSATTRBIT_SYSTEM))  			nvap->na_flags = 0;  	} @@ -3212,9 +3227,11 @@ nfsv4_sattr(struct nfsrv_descript *nd, vnode_t vp, struct nfsvattr *nvap,  			attrsum += aclsize;  			break;  		case NFSATTRBIT_ARCHIVE: -			NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED); -			if (!nd->nd_repstat) -				nd->nd_repstat = NFSERR_ATTRNOTSUPP; +			NFSM_DISSECT(tl, uint32_t *, NFSX_UNSIGNED); +			if (nd->nd_repstat == 0) { +				if (*tl == newnfs_true) +					nvap->na_flags |= UF_ARCHIVE; +			}  			attrsum += NFSX_UNSIGNED;  			break;  		case NFSATTRBIT_HIDDEN: @@ -3464,11 +3481,6 @@ nfsd_excred(struct nfsrv_descript *nd, struct nfsexstuff *exp,  		     (nd->nd_flag & ND_AUTHNONE) != 0) {  			nd->nd_cred->cr_uid = credanon->cr_uid;  			nd->nd_cred->cr_gid = credanon->cr_gid; -			/* -			 * 'credanon' is already a 'struct ucred' that was built -			 * internally with calls to crsetgroups_and_egid(), so -			 * we don't need a fallback here. -			 */  			crsetgroups(nd->nd_cred, credanon->cr_ngroups,  			    credanon->cr_groups);  		} else if ((nd->nd_flag & ND_GSS) == 0) { @@ -3740,6 +3752,7 @@ nfsrv_v4rootexport(void *argp, struct ucred *cred, struct thread *p)  		NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, nfsexargp->fspec);  		if ((error = namei(&nd)) != 0)  			goto out; +		NDFREE_PNBUF(&nd);  		error = nfsvno_getfh(nd.ni_vp, &fh, p);  		vrele(nd.ni_vp);  		if (!error) { @@ -5690,7 +5703,8 @@ nfsrv_writedsdorpc(struct nfsmount *nmp, fhandle_t *fhp, off_t off, int len,  	if ((nd->nd_flag & (ND_NOMOREDATA | ND_NFSV4 | ND_V4WCCATTR)) ==  	    (ND_NFSV4 | ND_V4WCCATTR)) {  		error = nfsv4_loadattr(nd, NULL, nap, NULL, NULL, 0, NULL, NULL, -		    NULL, NULL, NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL); +		    NULL, NULL, NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL, +		    NULL);  		NFSD_DEBUG(4, "nfsrv_writedsdorpc: wcc attr=%d\n", error);  		if (error != 0)  			goto nfsmout; @@ -5721,7 +5735,8 @@ nfsrv_writedsdorpc(struct nfsmount *nmp, fhandle_t *fhp, off_t off, int len,  	if (error == 0) {  		NFSM_DISSECT(tl, uint32_t *, 2 * NFSX_UNSIGNED);  		error = nfsv4_loadattr(nd, NULL, nap, NULL, NULL, 0, NULL, NULL, -		    NULL, NULL, NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL); +		    NULL, NULL, NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL, +		    NULL);  	}  	NFSD_DEBUG(4, "nfsrv_writedsdorpc: aft loadattr=%d\n", error);  nfsmout: @@ -5887,7 +5902,8 @@ nfsrv_allocatedsdorpc(struct nfsmount *nmp, fhandle_t *fhp, off_t off,  	if (nd->nd_repstat == 0) {  		NFSM_DISSECT(tl, uint32_t *, 2 * NFSX_UNSIGNED);  		error = nfsv4_loadattr(nd, NULL, nap, NULL, NULL, 0, NULL, NULL, -		    NULL, NULL, NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL); +		    NULL, NULL, NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL, +		    NULL);  	} else  		error = nd->nd_repstat;  	NFSD_DEBUG(4, "nfsrv_allocatedsdorpc: aft loadattr=%d\n", error); @@ -6054,7 +6070,8 @@ nfsrv_deallocatedsdorpc(struct nfsmount *nmp, fhandle_t *fhp, off_t off,  	if ((nd->nd_flag & (ND_NOMOREDATA | ND_NFSV4 | ND_V4WCCATTR)) ==  	    (ND_NFSV4 | ND_V4WCCATTR)) {  		error = nfsv4_loadattr(nd, NULL, nap, NULL, NULL, 0, NULL, NULL, -		    NULL, NULL, NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL); +		    NULL, NULL, NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL, +		    NULL);  		NFSD_DEBUG(4, "nfsrv_deallocatedsdorpc: wcc attr=%d\n", error);  		if (error != 0)  			goto nfsmout; @@ -6068,7 +6085,8 @@ nfsrv_deallocatedsdorpc(struct nfsmount *nmp, fhandle_t *fhp, off_t off,  	if (nd->nd_repstat == 0) {  		NFSM_DISSECT(tl, uint32_t *, 2 * NFSX_UNSIGNED);  		error = nfsv4_loadattr(nd, NULL, nap, NULL, NULL, 0, NULL, NULL, -		    NULL, NULL, NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL); +		    NULL, NULL, NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL, +		    NULL);  	} else  		error = nd->nd_repstat;  	NFSD_DEBUG(4, "nfsrv_deallocatedsdorpc: aft loadattr=%d\n", error); @@ -6216,7 +6234,8 @@ nfsrv_setattrdsdorpc(fhandle_t *fhp, struct ucred *cred, NFSPROC_T *p,  	if ((nd->nd_flag & (ND_NOMOREDATA | ND_NFSV4 | ND_V4WCCATTR)) ==  	    (ND_NFSV4 | ND_V4WCCATTR)) {  		error = nfsv4_loadattr(nd, NULL, dsnap, NULL, NULL, 0, NULL, -		    NULL, NULL, NULL, NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL); +		    NULL, NULL, NULL, NULL, 0, NULL, NULL, NULL, NULL, NULL, +		    NULL, NULL);  		NFSD_DEBUG(4, "nfsrv_setattrdsdorpc: wcc attr=%d\n", error);  		if (error != 0)  			goto nfsmout; @@ -6241,7 +6260,7 @@ nfsrv_setattrdsdorpc(fhandle_t *fhp, struct ucred *cred, NFSPROC_T *p,  		NFSM_DISSECT(tl, uint32_t *, 2 * NFSX_UNSIGNED);  		error = nfsv4_loadattr(nd, NULL, dsnap, NULL, NULL, 0, NULL,  		    NULL, NULL, NULL, NULL, 0, NULL, NULL, NULL, NULL, NULL, -		    NULL); +		    NULL, NULL);  	}  	NFSD_DEBUG(4, "nfsrv_setattrdsdorpc: aft setattr loadattr=%d\n", error);  nfsmout: @@ -6386,7 +6405,7 @@ nfsrv_setacldsdorpc(fhandle_t *fhp, struct ucred *cred, NFSPROC_T *p,  	 * the same type (VREG).  	 */  	nfsv4_fillattr(nd, NULL, vp, aclp, NULL, NULL, 0, &attrbits, NULL, -	    NULL, 0, 0, 0, 0, 0, NULL, false, false, false); +	    NULL, 0, 0, 0, 0, 0, NULL, false, false, false, 0);  	error = newnfs_request(nd, nmp, NULL, &nmp->nm_sockreq, NULL, p, cred,  	    NFS_PROG, NFS_VER4, NULL, 1, NULL, NULL);  	if (error != 0) { @@ -6530,7 +6549,7 @@ nfsrv_getattrdsrpc(fhandle_t *fhp, struct ucred *cred, NFSPROC_T *p,  	if (nd->nd_repstat == 0) {  		error = nfsv4_loadattr(nd, NULL, nap, NULL, NULL, 0,  		    NULL, NULL, NULL, NULL, NULL, 0, NULL, NULL, NULL, -		    NULL, NULL, NULL); +		    NULL, NULL, NULL, NULL);  		/*  		 * We can only save the updated values in the extended  		 * attribute if the vp is exclusively locked. diff --git a/sys/fs/nfsserver/nfs_nfsdserv.c b/sys/fs/nfsserver/nfs_nfsdserv.c index 9eebcda548c6..67af0cf71175 100644 --- a/sys/fs/nfsserver/nfs_nfsdserv.c +++ b/sys/fs/nfsserver/nfs_nfsdserv.c @@ -253,6 +253,7 @@ nfsrvd_getattr(struct nfsrv_descript *nd, int isdgram,  	size_t atsiz;  	long pathval;  	bool has_hiddensystem, has_namedattr, xattrsupp; +	uint32_t clone_blksize;  	if (nd->nd_repstat)  		goto out; @@ -330,13 +331,18 @@ nfsrvd_getattr(struct nfsrv_descript *nd, int isdgram,  				    &pathval) != 0)  					pathval = 0;  				has_namedattr = pathval > 0; +				pathval = 0; +				if (VOP_PATHCONF(vp, _PC_CLONE_BLKSIZE, +				    &pathval) != 0) +					pathval = 0; +				clone_blksize = pathval;  				mp = vp->v_mount;  				if (nfsrv_enable_crossmntpt != 0 &&  				    vp->v_type == VDIR &&  				    (vp->v_vflag & VV_ROOT) != 0 &&  				    vp != rootvnode) {  					tvp = mp->mnt_vnodecovered; -					VREF(tvp); +					vref(tvp);  					at_root = 1;  				} else  					at_root = 0; @@ -365,7 +371,7 @@ nfsrvd_getattr(struct nfsrv_descript *nd, int isdgram,  					    isdgram, 1, supports_nfsv4acls,  					    at_root, mounted_on_fileno,  					    xattrsupp, has_hiddensystem, -					    has_namedattr); +					    has_namedattr, clone_blksize);  					vfs_unbusy(mp);  				}  				vrele(vp); @@ -430,6 +436,7 @@ nfsrvd_setattr(struct nfsrv_descript *nd, __unused int isdgram,  	/* For NFSv4, only va_uid and va_flags is used from nva2. */  	NFSSETBIT_ATTRBIT(&retbits, NFSATTRBIT_OWNER); +	NFSSETBIT_ATTRBIT(&retbits, NFSATTRBIT_ARCHIVE);  	NFSSETBIT_ATTRBIT(&retbits, NFSATTRBIT_HIDDEN);  	NFSSETBIT_ATTRBIT(&retbits, NFSATTRBIT_SYSTEM);  	preat_ret = nfsvno_getattr(vp, &nva2, nd, p, 1, &retbits); @@ -563,8 +570,15 @@ nfsrvd_setattr(struct nfsrv_descript *nd, __unused int isdgram,  		}  	    }  	    if (!nd->nd_repstat && -		(NFSISSET_ATTRBIT(&attrbits, NFSATTRBIT_HIDDEN) || +		(NFSISSET_ATTRBIT(&attrbits, NFSATTRBIT_ARCHIVE) || +		 NFSISSET_ATTRBIT(&attrbits, NFSATTRBIT_HIDDEN) ||  		 NFSISSET_ATTRBIT(&attrbits, NFSATTRBIT_SYSTEM))) { +		if (NFSISSET_ATTRBIT(&attrbits, NFSATTRBIT_ARCHIVE)) { +		    if ((nva.na_flags & UF_ARCHIVE) != 0) +			oldflags |= UF_ARCHIVE; +		    else +			oldflags &= ~UF_ARCHIVE; +		}  		if (NFSISSET_ATTRBIT(&attrbits, NFSATTRBIT_HIDDEN)) {  		    if ((nva.na_flags & UF_HIDDEN) != 0)  			oldflags |= UF_HIDDEN; @@ -582,6 +596,8 @@ nfsrvd_setattr(struct nfsrv_descript *nd, __unused int isdgram,  		nd->nd_repstat = nfsvno_setattr(vp, &nva2, nd->nd_cred, p,  		    exp);  		if (!nd->nd_repstat) { +		    if (NFSISSET_ATTRBIT(&attrbits, NFSATTRBIT_ARCHIVE)) +			NFSSETBIT_ATTRBIT(&retbits, NFSATTRBIT_ARCHIVE);  		    if (NFSISSET_ATTRBIT(&attrbits, NFSATTRBIT_HIDDEN))  			NFSSETBIT_ATTRBIT(&retbits, NFSATTRBIT_HIDDEN);  		    if (NFSISSET_ATTRBIT(&attrbits, NFSATTRBIT_SYSTEM)) @@ -1760,7 +1776,7 @@ nfsrvd_rename(struct nfsrv_descript *nd, int isdgram,  		/* If this is the same file handle, just VREF() the vnode. */  		if (!NFSBCMP(tfh.nfsrvfh_data, &fh, NFSX_MYFH)) { -			VREF(dp); +			vref(dp);  			tdp = dp;  			tnes = *exp;  			tdirfor_ret = nfsvno_getattr(tdp, &tdirfor, nd, p, 1, @@ -4347,7 +4363,7 @@ nfsrvd_verify(struct nfsrv_descript *nd, int isdgram,  	if (!nd->nd_repstat) {  		nfsvno_getfs(&fs, isdgram);  		error = nfsv4_loadattr(nd, vp, &nva, NULL, &fh, fhsize, NULL, -		    sf, NULL, &fs, NULL, 1, &ret, NULL, NULL, NULL, p, +		    sf, NULL, &fs, NULL, 1, &ret, NULL, NULL, NULL, NULL, p,  		    nd->nd_cred);  		if (!error) {  			if (nd->nd_procnum == NFSV4OP_NVERIFY) { @@ -5122,6 +5138,11 @@ nfsrvd_layoutcommit(struct nfsrv_descript *nd, __unused int isdgram,  		NFSM_DISSECT(tl, uint32_t *, 2 * NFSX_UNSIGNED);  	layouttype = fxdr_unsigned(int, *tl++);  	maxcnt = fxdr_unsigned(int, *tl); +	/* There is no limit in the RFC, so use 1000 as a sanity limit. */ +	if (maxcnt < 0 || maxcnt > 1000) { +		error = NFSERR_BADXDR; +		goto nfsmout; +	}  	if (maxcnt > 0) {  		layp = malloc(maxcnt + 1, M_TEMP, M_WAITOK);  		error = nfsrv_mtostr(nd, layp, maxcnt); @@ -6011,6 +6032,212 @@ nfsmout:  }  /* + * nfs clone service + */ +int +nfsrvd_clone(struct nfsrv_descript *nd, __unused int isdgram, +    vnode_t vp, vnode_t tovp, struct nfsexstuff *exp, struct nfsexstuff *toexp) +{ +	uint32_t *tl; +	struct nfsvattr at; +	int error = 0, ret; +	off_t inoff, outoff; +	uint64_t len; +	size_t xfer; +	struct nfsstate inst, outst, *instp = &inst, *outstp = &outst; +	struct nfslock inlo, outlo, *inlop = &inlo, *outlop = &outlo; +	nfsquad_t clientid; +	nfsv4stateid_t stateid; +	nfsattrbit_t attrbits; +	void *rl_rcookie, *rl_wcookie; +	long pathval; + +	rl_rcookie = rl_wcookie = NULL; +	pathval = 0; +	if (nfsrv_maxcopyrange == 0 || nfsrv_devidcnt > 0 || +	    VOP_PATHCONF(vp, _PC_CLONE_BLKSIZE, &pathval) != 0 || +	    pathval == 0) { +		/* +		 * For a pNFS server, reply NFSERR_NOTSUPP so that the client +		 * will not do the clone and will do I/O on the DS(s). +		 * If vfs.nfsd.maxcopyrange set to 0, disable Clone. +		 */ +		nd->nd_repstat = NFSERR_NOTSUPP; +		goto nfsmout; +	} +	NFSM_DISSECT(tl, uint32_t *, 2 * NFSX_STATEID + 3 * NFSX_HYPER); +	instp->ls_flags = (NFSLCK_CHECK | NFSLCK_READACCESS); +	inlop->lo_flags = NFSLCK_READ; +	instp->ls_ownerlen = 0; +	instp->ls_op = NULL; +	instp->ls_uid = nd->nd_cred->cr_uid; +	instp->ls_stateid.seqid = fxdr_unsigned(uint32_t, *tl++); +	clientid.lval[0] = instp->ls_stateid.other[0] = *tl++; +	clientid.lval[1] = instp->ls_stateid.other[1] = *tl++; +	if ((nd->nd_flag & ND_IMPLIEDCLID) != 0) +		clientid.qval = nd->nd_clientid.qval; +	instp->ls_stateid.other[2] = *tl++; +	outstp->ls_flags = (NFSLCK_CHECK | NFSLCK_WRITEACCESS); +	outlop->lo_flags = NFSLCK_WRITE; +	outstp->ls_ownerlen = 0; +	outstp->ls_op = NULL; +	outstp->ls_uid = nd->nd_cred->cr_uid; +	outstp->ls_stateid.seqid = fxdr_unsigned(uint32_t, *tl++); +	outstp->ls_stateid.other[0] = *tl++; +	outstp->ls_stateid.other[1] = *tl++; +	outstp->ls_stateid.other[2] = *tl++; +	inoff = fxdr_hyper(tl); tl += 2; +	inlop->lo_first = inoff; +	outoff = fxdr_hyper(tl); tl += 2; +	outlop->lo_first = outoff; +	len = fxdr_hyper(tl); +	if (len == 0) { +		/* len == 0 means to EOF. */ +		inlop->lo_end = OFF_MAX; +		outlop->lo_end = OFF_MAX; +	} else { +		inlop->lo_end = inlop->lo_first + len; +		outlop->lo_end = outlop->lo_first + len; +	} + +	if ((inoff > OFF_MAX || outoff > OFF_MAX || +	    inlop->lo_end > OFF_MAX || outlop->lo_end > OFF_MAX || +	    inlop->lo_end < inlop->lo_first || outlop->lo_end < +	    outlop->lo_first)) +		nd->nd_repstat = NFSERR_INVAL; + +	if (nd->nd_repstat == 0 && vp->v_type != VREG) +		nd->nd_repstat = NFSERR_WRONGTYPE; + +	/* Check permissions for the input file. */ +	NFSZERO_ATTRBIT(&attrbits); +	NFSSETBIT_ATTRBIT(&attrbits, NFSATTRBIT_OWNER); +	ret = nfsvno_getattr(vp, &at, nd, curthread, 1, &attrbits); +	if (nd->nd_repstat == 0) +		nd->nd_repstat = ret; +	if (nd->nd_repstat == 0 && (at.na_uid != nd->nd_cred->cr_uid || +	     NFSVNO_EXSTRICTACCESS(exp))) +		nd->nd_repstat = nfsvno_accchk(vp, VREAD, nd->nd_cred, exp, +		    curthread, NFSACCCHK_ALLOWOWNER, NFSACCCHK_VPISLOCKED, +		    NULL); +	if (nd->nd_repstat == 0) +		nd->nd_repstat = nfsrv_lockctrl(vp, &instp, &inlop, NULL, +		    clientid, &stateid, exp, nd, curthread); +	if (vp != tovp) { +		NFSVOPUNLOCK(vp); +		if (nd->nd_repstat != 0) +			goto out; + +		error = NFSVOPLOCK(tovp, LK_SHARED); +		if (error != 0) +			goto out; +		pathval = 0; +		if (VOP_PATHCONF(tovp, _PC_CLONE_BLKSIZE, &pathval) != 0 || +		    pathval == 0) +			nd->nd_repstat = NFSERR_NOTSUPP; +		else if (tovp->v_type != VREG) +			nd->nd_repstat = NFSERR_WRONGTYPE; +	} + +	/* For the output file, we only need the Owner attribute. */ +	ret = nfsvno_getattr(tovp, &at, nd, curthread, 1, &attrbits); +	if (nd->nd_repstat == 0) +		nd->nd_repstat = ret; +	if (nd->nd_repstat == 0 && (at.na_uid != nd->nd_cred->cr_uid || +	     NFSVNO_EXSTRICTACCESS(exp))) +		nd->nd_repstat = nfsvno_accchk(tovp, VWRITE, nd->nd_cred, toexp, +		    curthread, NFSACCCHK_ALLOWOWNER, NFSACCCHK_VPISLOCKED, +		    NULL); +	if (nd->nd_repstat == 0) +		nd->nd_repstat = nfsrv_lockctrl(tovp, &outstp, &outlop, NULL, +		    clientid, &stateid, toexp, nd, curthread); +	NFSVOPUNLOCK(tovp); + +	/* Range lock the byte ranges for both invp and outvp. */ +	if (nd->nd_repstat == 0) { +		for (;;) { +			if (len == 0) +				rl_wcookie = vn_rangelock_wlock(tovp, outoff, +				    OFF_MAX); +			else +				rl_wcookie = vn_rangelock_wlock(tovp, outoff, +				    outoff + len); +			if (vp != tovp) { +				if (len == 0) +					rl_rcookie = vn_rangelock_tryrlock(vp, +					    inoff, OFF_MAX); +				else +					rl_rcookie = vn_rangelock_tryrlock(vp, +					    inoff, inoff + len); +				if (rl_rcookie != NULL) +					break; +			} else { +				rl_rcookie = NULL; +				break; +			} +			vn_rangelock_unlock(tovp, rl_wcookie); +			if (len == 0) +				rl_rcookie = vn_rangelock_rlock(vp, inoff, +				    OFF_MAX); +			else +				rl_rcookie = vn_rangelock_rlock(vp, inoff, +				    inoff + len); +			vn_rangelock_unlock(vp, rl_rcookie); +		} + +		error = NFSVOPLOCK(vp, LK_SHARED); +		if (error == 0) { +			ret = nfsvno_getattr(vp, &at, nd, curthread, 1, NULL); +			if (ret == 0) { +				/* +				 * Since invp is range locked, na_size should +				 * not change. +				 */ +				if (len == 0 && at.na_size > inoff) +					len = SSIZE_MAX;	/* To EOF. */ +				else if (inoff + len > at.na_size) +					nd->nd_repstat = NFSERR_INVAL; +			} +			NFSVOPUNLOCK(vp); +			if (ret != 0 && nd->nd_repstat == 0) +				nd->nd_repstat = ret; +		} else if (nd->nd_repstat == 0) +			nd->nd_repstat = error; +	} + +	/* +	 * Do the actual copy to an upper limit of vfs.nfsd.maxcopyrange. +	 * This size limit can be set to limit the time a copy RPC will +	 * take. +	 */ +	xfer = len; +	if (nd->nd_repstat == 0) { +		nd->nd_repstat = vn_copy_file_range(vp, &inoff, tovp, &outoff, +		    &xfer, COPY_FILE_RANGE_CLONE, nd->nd_cred, nd->nd_cred, +		    NULL); +		if (nd->nd_repstat == ENOSYS) +			nd->nd_repstat = NFSERR_INVAL; +	} + +	/* Unlock the ranges. */ +	if (rl_rcookie != NULL) +		vn_rangelock_unlock(vp, rl_rcookie); +	if (rl_wcookie != NULL) +		vn_rangelock_unlock(tovp, rl_wcookie); + +out: +	vrele(vp); +	vrele(tovp); +	NFSEXITCODE2(error, nd); +	return (error); +nfsmout: +	vput(vp); +	vrele(tovp); +	NFSEXITCODE2(error, nd); +	return (error); +} + +/*   * nfs seek service   */  int diff --git a/sys/fs/nfsserver/nfs_nfsdsocket.c b/sys/fs/nfsserver/nfs_nfsdsocket.c index d6832b4f74be..201f3b74b946 100644 --- a/sys/fs/nfsserver/nfs_nfsdsocket.c +++ b/sys/fs/nfsserver/nfs_nfsdsocket.c @@ -371,7 +371,7 @@ int (*nfsrv4_ops2[NFSV42_NOPS])(struct nfsrv_descript *,  	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,  	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,  	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0, -	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0, +	nfsrvd_clone,  	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,  	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,  	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0, @@ -1110,7 +1110,7 @@ nfsrvd_compound(struct nfsrv_descript *nd, int isdgram, u_char *tag,  				if (vp != savevp) {  					if (savevp)  						vrele(savevp); -					VREF(vp); +					vref(vp);  					savevp = vp;  					savevpnes = vpnes;  					save_fsid = cur_fsid; @@ -1155,7 +1155,7 @@ nfsrvd_compound(struct nfsrv_descript *nd, int isdgram, u_char *tag,  						    nfsvno_testexp(nd,  						    &savevpnes);  					if (nd->nd_repstat == 0) { -						VREF(savevp); +						vref(savevp);  						vrele(vp);  						vp = savevp;  						vpnes = savevpnes; @@ -1235,7 +1235,7 @@ tryagain:  					break;  				}  			} -			VREF(vp); +			vref(vp);  			if (nfsv4_opflag[op].modifyfs)  				vn_start_write(vp, &temp_mp, V_WAIT);  			error = (*(nfsrv4_ops1[op]))(nd, isdgram, vp, @@ -1279,8 +1279,8 @@ tryagain:  			if (nfsv4_opflag[op].modifyfs)  				vn_start_write(savevp, &temp_mp, V_WAIT);  			if (NFSVOPLOCK(savevp, LK_EXCLUSIVE) == 0) { -				VREF(vp); -				VREF(savevp); +				vref(vp); +				vref(savevp);  				error = (*(nfsrv4_ops2[op]))(nd, isdgram,  				    savevp, vp, &savevpnes, &vpnes);  			} else @@ -1301,7 +1301,7 @@ tryagain:  							lktype = LK_SHARED;  					}  					if (NFSVOPLOCK(vp, lktype) == 0) -						VREF(vp); +						vref(vp);  					else  						nd->nd_repstat = NFSERR_PERM;  				} else { diff --git a/sys/fs/nfsserver/nfs_nfsdstate.c b/sys/fs/nfsserver/nfs_nfsdstate.c index 2e27817389dd..111b0f26d0b5 100644 --- a/sys/fs/nfsserver/nfs_nfsdstate.c +++ b/sys/fs/nfsserver/nfs_nfsdstate.c @@ -4675,7 +4675,7 @@ errout:  		} else if (error == 0 && procnum == NFSV4OP_CBGETATTR)  			error = nfsv4_loadattr(nd, NULL, nap, NULL, NULL, 0,  			    NULL, NULL, NULL, NULL, NULL, 0, NULL, NULL, NULL, -			    NULL, p, NULL); +			    NULL, NULL, p, NULL);  		m_freem(nd->nd_mrep);  	}  	NFSLOCKSTATE(); @@ -7731,6 +7731,7 @@ nfsrv_setdsserver(char *dspathp, char *mdspathp, NFSPROC_T *p,  	NFSD_DEBUG(4, "lookup=%d\n", error);  	if (error != 0)  		return (error); +	NDFREE_PNBUF(&nd);  	if (nd.ni_vp->v_type != VDIR) {  		vput(nd.ni_vp);  		NFSD_DEBUG(4, "dspath not dir\n"); @@ -7767,6 +7768,7 @@ nfsrv_setdsserver(char *dspathp, char *mdspathp, NFSPROC_T *p,  		NFSD_DEBUG(4, "dsdirpath=%s lookup=%d\n", dsdirpath, error);  		if (error != 0)  			break; +		NDFREE_PNBUF(&nd);  		if (nd.ni_vp->v_type != VDIR) {  			vput(nd.ni_vp);  			error = ENOTDIR; @@ -7795,6 +7797,7 @@ nfsrv_setdsserver(char *dspathp, char *mdspathp, NFSPROC_T *p,  		NFSD_DEBUG(4, "mds lookup=%d\n", error);  		if (error != 0)  			goto out; +		NDFREE_PNBUF(&nd);  		if (nd.ni_vp->v_type != VDIR) {  			vput(nd.ni_vp);  			error = ENOTDIR; @@ -8654,6 +8657,7 @@ nfsrv_mdscopymr(char *mdspathp, char *dspathp, char *curdspathp, char *buf,  	NFSD_DEBUG(4, "lookup=%d\n", error);  	if (error != 0)  		return (error); +	NDFREE_PNBUF(&nd);  	if (nd.ni_vp->v_type != VREG) {  		vput(nd.ni_vp);  		NFSD_DEBUG(4, "mdspath not reg\n"); @@ -8675,6 +8679,7 @@ nfsrv_mdscopymr(char *mdspathp, char *dspathp, char *curdspathp, char *buf,  			vput(vp);  			return (error);  		} +		NDFREE_PNBUF(&nd);  		if (nd.ni_vp->v_type != VDIR) {  			vput(nd.ni_vp);  			vput(vp); @@ -8717,6 +8722,7 @@ nfsrv_mdscopymr(char *mdspathp, char *dspathp, char *curdspathp, char *buf,  				vput(curvp);  			return (error);  		} +		NDFREE_PNBUF(&nd);  		if (nd.ni_vp->v_type != VDIR || nd.ni_vp == curvp) {  			vput(nd.ni_vp);  			vput(vp); diff --git a/sys/fs/nullfs/null.h b/sys/fs/nullfs/null.h index 0a93878c859f..7bfdc20a3f67 100644 --- a/sys/fs/nullfs/null.h +++ b/sys/fs/nullfs/null.h @@ -35,7 +35,11 @@  #ifndef	FS_NULL_H  #define	FS_NULL_H -#define	NULLM_CACHE	0x0001 +#include <sys/ck.h> +#include <vm/uma.h> + +#define	NULLM_CACHE		0x0001 +#define	NULLM_NOUNPBYPASS	0x0002  struct null_mount {  	struct mount	*nullm_vfs; @@ -50,7 +54,7 @@ struct null_mount {   * A cache of vnode references   */  struct null_node { -	LIST_ENTRY(null_node)	null_hash;	/* Hash list */ +	CK_SLIST_ENTRY(null_node) null_hash;	/* Hash list */  	struct vnode	        *null_lowervp;	/* VREFed once */  	struct vnode		*null_vnode;	/* Back pointer */  	u_int			null_flags; @@ -61,6 +65,7 @@ struct null_node {  #define	MOUNTTONULLMOUNT(mp) ((struct null_mount *)((mp)->mnt_data))  #define	VTONULL(vp) ((struct null_node *)(vp)->v_data) +#define	VTONULL_SMR(vp) ((struct null_node *)vn_load_v_data_smr(vp))  #define	NULLTOV(xp) ((xp)->null_vnode)  int nullfs_init(struct vfsconf *vfsp); @@ -78,10 +83,18 @@ struct vnode *null_checkvp(struct vnode *vp, char *fil, int lno);  #endif  extern struct vop_vector null_vnodeops; +extern struct vop_vector null_vnodeops_no_unp_bypass; -#ifdef MALLOC_DECLARE -MALLOC_DECLARE(M_NULLFSNODE); -#endif +static inline bool +null_is_nullfs_vnode(struct vnode *vp) +{ +	const struct vop_vector *op; + +	op = vp->v_op; +	return (op == &null_vnodeops || op == &null_vnodeops_no_unp_bypass); +} + +extern uma_zone_t null_node_zone;  #ifdef NULLFS_DEBUG  #define NULLFSDEBUG(format, args...) printf(format ,## args) diff --git a/sys/fs/nullfs/null_subr.c b/sys/fs/nullfs/null_subr.c index 7dcc83880bb9..a843ae44f121 100644 --- a/sys/fs/nullfs/null_subr.c +++ b/sys/fs/nullfs/null_subr.c @@ -36,14 +36,19 @@  #include <sys/systm.h>  #include <sys/kernel.h>  #include <sys/lock.h> -#include <sys/rwlock.h>  #include <sys/malloc.h>  #include <sys/mount.h>  #include <sys/proc.h> +#include <sys/rwlock.h> +#include <sys/smr.h>  #include <sys/vnode.h>  #include <fs/nullfs/null.h> +#include <vm/uma.h> + +VFS_SMR_DECLARE; +  /*   * Null layer cache:   * Each cache entry holds a reference to the lower vnode @@ -54,12 +59,12 @@  #define	NULL_NHASH(vp) (&null_node_hashtbl[vfs_hash_index(vp) & null_hash_mask]) -static LIST_HEAD(null_node_hashhead, null_node) *null_node_hashtbl; +static CK_SLIST_HEAD(null_node_hashhead, null_node) *null_node_hashtbl;  static struct rwlock null_hash_lock;  static u_long null_hash_mask;  static MALLOC_DEFINE(M_NULLFSHASH, "nullfs_hash", "NULLFS hash table"); -MALLOC_DEFINE(M_NULLFSNODE, "nullfs_node", "NULLFS vnode private part"); +uma_zone_t __read_mostly null_node_zone;  static void null_hashins(struct mount *, struct null_node *); @@ -73,6 +78,10 @@ nullfs_init(struct vfsconf *vfsp)  	null_node_hashtbl = hashinit(desiredvnodes, M_NULLFSHASH,  	    &null_hash_mask);  	rw_init(&null_hash_lock, "nullhs"); +	null_node_zone = uma_zcreate("nullfs node", sizeof(struct null_node), +	    NULL, NULL, NULL, NULL, 0, UMA_ZONE_ZINIT); +	VFS_SMR_ZONE_SET(null_node_zone); +  	return (0);  } @@ -80,6 +89,7 @@ int  nullfs_uninit(struct vfsconf *vfsp)  { +	uma_zdestroy(null_node_zone);  	rw_destroy(&null_hash_lock);  	hashdestroy(null_node_hashtbl, M_NULLFSHASH, null_hash_mask);  	return (0); @@ -96,7 +106,7 @@ null_hashget_locked(struct mount *mp, struct vnode *lowervp)  	struct null_node *a;  	struct vnode *vp; -	ASSERT_VOP_LOCKED(lowervp, "null_hashget"); +	ASSERT_VOP_LOCKED(lowervp, __func__);  	rw_assert(&null_hash_lock, RA_LOCKED);  	/* @@ -106,37 +116,57 @@ null_hashget_locked(struct mount *mp, struct vnode *lowervp)  	 * reference count (but NOT the lower vnode's VREF counter).  	 */  	hd = NULL_NHASH(lowervp); -	LIST_FOREACH(a, hd, null_hash) { -		if (a->null_lowervp == lowervp && NULLTOV(a)->v_mount == mp) { -			/* -			 * Since we have the lower node locked the nullfs -			 * node can not be in the process of recycling.  If -			 * it had been recycled before we grabed the lower -			 * lock it would not have been found on the hash. -			 */ -			vp = NULLTOV(a); -			vref(vp); -			return (vp); -		} +	CK_SLIST_FOREACH(a, hd, null_hash) { +		if (a->null_lowervp != lowervp) +			continue; +		/* +		 * Since we have the lower node locked the nullfs +		 * node can not be in the process of recycling.  If +		 * it had been recycled before we grabed the lower +		 * lock it would not have been found on the hash. +		 */ +		vp = NULLTOV(a); +		VNPASS(!VN_IS_DOOMED(vp), vp); +		if (vp->v_mount != mp) +			continue; +		vref(vp); +		return (vp);  	} -	return (NULLVP); +	return (NULL);  }  struct vnode *  null_hashget(struct mount *mp, struct vnode *lowervp)  {  	struct null_node_hashhead *hd; +	struct null_node *a;  	struct vnode *vp; +	enum vgetstate vs; -	hd = NULL_NHASH(lowervp); -	if (LIST_EMPTY(hd)) -		return (NULLVP); +	ASSERT_VOP_LOCKED(lowervp, __func__); +	rw_assert(&null_hash_lock, RA_UNLOCKED); -	rw_rlock(&null_hash_lock); -	vp = null_hashget_locked(mp, lowervp); -	rw_runlock(&null_hash_lock); - -	return (vp); +	vfs_smr_enter(); +	hd = NULL_NHASH(lowervp); +	CK_SLIST_FOREACH(a, hd, null_hash) { +		if (a->null_lowervp != lowervp) +			continue; +		/* +		 * See null_hashget_locked as to why the nullfs vnode can't be +		 * doomed here. +		 */ +		vp = NULLTOV(a); +		VNPASS(!VN_IS_DOOMED(vp), vp); +		if (vp->v_mount != mp) +			continue; +		vs = vget_prep_smr(vp); +		vfs_smr_exit(); +		VNPASS(vs != VGET_NONE, vp); +		vget_finish_ref(vp, vs); +		return (vp); +	} +	vfs_smr_exit(); +	return (NULL);  }  static void @@ -151,7 +181,7 @@ null_hashins(struct mount *mp, struct null_node *xp)  	hd = NULL_NHASH(xp->null_lowervp);  #ifdef INVARIANTS -	LIST_FOREACH(oxp, hd, null_hash) { +	CK_SLIST_FOREACH(oxp, hd, null_hash) {  		if (oxp->null_lowervp == xp->null_lowervp &&  		    NULLTOV(oxp)->v_mount == mp) {  			VNASSERT(0, NULLTOV(oxp), @@ -159,7 +189,7 @@ null_hashins(struct mount *mp, struct null_node *xp)  		}  	}  #endif -	LIST_INSERT_HEAD(hd, xp, null_hash); +	CK_SLIST_INSERT_HEAD(hd, xp, null_hash);  }  static void @@ -174,7 +204,7 @@ null_destroy_proto(struct vnode *vp, void *xp)  	VI_UNLOCK(vp);  	vgone(vp);  	vput(vp); -	free(xp, M_NULLFSNODE); +	uma_zfree_smr(null_node_zone, xp);  }  /* @@ -208,12 +238,14 @@ null_nodeget(struct mount *mp, struct vnode *lowervp, struct vnode **vpp)  	 * Note that duplicate can only appear in hash if the lowervp is  	 * locked LK_SHARED.  	 */ -	xp = malloc(sizeof(struct null_node), M_NULLFSNODE, M_WAITOK); +	xp = uma_zalloc_smr(null_node_zone, M_WAITOK); -	error = getnewvnode("nullfs", mp, &null_vnodeops, &vp); +	error = getnewvnode("nullfs", mp, (MOUNTTONULLMOUNT(mp)->nullm_flags & +	    NULLM_NOUNPBYPASS) != 0 ? &null_vnodeops_no_unp_bypass : +	    &null_vnodeops, &vp);  	if (error) {  		vput(lowervp); -		free(xp, M_NULLFSNODE); +		uma_zfree_smr(null_node_zone, xp);  		return (error);  	} @@ -261,8 +293,8 @@ null_nodeget(struct mount *mp, struct vnode *lowervp, struct vnode **vpp)  		return (error);  	} -	null_hashins(mp, xp);  	vn_set_state(vp, VSTATE_CONSTRUCTED); +	null_hashins(mp, xp);  	rw_wunlock(&null_hash_lock);  	*vpp = vp; @@ -275,9 +307,11 @@ null_nodeget(struct mount *mp, struct vnode *lowervp, struct vnode **vpp)  void  null_hashrem(struct null_node *xp)  { +	struct null_node_hashhead *hd; +	hd = NULL_NHASH(xp->null_lowervp);  	rw_wlock(&null_hash_lock); -	LIST_REMOVE(xp, null_hash); +	CK_SLIST_REMOVE(hd, xp, null_node, null_hash);  	rw_wunlock(&null_hash_lock);  } @@ -298,7 +332,7 @@ null_checkvp(struct vnode *vp, char *fil, int lno)  		panic("null_checkvp");  	}  #endif -	if (a->null_lowervp == NULLVP) { +	if (a->null_lowervp == NULL) {  		/* Should never happen */  		panic("null_checkvp %p", vp);  	} diff --git a/sys/fs/nullfs/null_vfsops.c b/sys/fs/nullfs/null_vfsops.c index 4cddf24a5745..170a3dd51cd8 100644 --- a/sys/fs/nullfs/null_vfsops.c +++ b/sys/fs/nullfs/null_vfsops.c @@ -85,6 +85,10 @@ nullfs_mount(struct mount *mp)  	char *target;  	int error, len;  	bool isvnunlocked; +	static const char cache_opt_name[] = "cache"; +	static const char nocache_opt_name[] = "nocache"; +	static const char unixbypass_opt_name[] = "unixbypass"; +	static const char nounixbypass_opt_name[] = "nounixbypass";  	NULLFSDEBUG("nullfs_mount(mp = %p)\n", (void *)mp); @@ -116,7 +120,7 @@ nullfs_mount(struct mount *mp)  	/*  	 * Unlock lower node to avoid possible deadlock.  	 */ -	if (mp->mnt_vnodecovered->v_op == &null_vnodeops && +	if (null_is_nullfs_vnode(mp->mnt_vnodecovered) &&  	    VOP_ISLOCKED(mp->mnt_vnodecovered) == LK_EXCLUSIVE) {  		VOP_UNLOCK(mp->mnt_vnodecovered);  		isvnunlocked = true; @@ -150,7 +154,7 @@ nullfs_mount(struct mount *mp)  	/*  	 * Check multi null mount to avoid `lock against myself' panic.  	 */ -	if (mp->mnt_vnodecovered->v_op == &null_vnodeops) { +	if (null_is_nullfs_vnode(mp->mnt_vnodecovered)) {  		nn = VTONULL(mp->mnt_vnodecovered);  		if (nn == NULL || lowerrootvp == nn->null_lowervp) {  			NULLFSDEBUG("nullfs_mount: multi null mount?\n"); @@ -205,9 +209,10 @@ nullfs_mount(struct mount *mp)  		MNT_IUNLOCK(mp);  	} -	if (vfs_getopt(mp->mnt_optnew, "cache", NULL, NULL) == 0) { +	if (vfs_getopt(mp->mnt_optnew, cache_opt_name, NULL, NULL) == 0) {  		xmp->nullm_flags |= NULLM_CACHE; -	} else if (vfs_getopt(mp->mnt_optnew, "nocache", NULL, NULL) == 0) { +	} else if (vfs_getopt(mp->mnt_optnew, nocache_opt_name, NULL, +	    NULL) == 0) {  		;  	} else if (null_cache_vnodes &&  	    (xmp->nullm_vfs->mnt_kern_flag & MNTK_NULL_NOCACHE) == 0) { @@ -219,6 +224,13 @@ nullfs_mount(struct mount *mp)  		    &xmp->notify_node);  	} +	if (vfs_getopt(mp->mnt_optnew, unixbypass_opt_name, NULL, NULL) == 0) { +		; +	} else if (vfs_getopt(mp->mnt_optnew, nounixbypass_opt_name, NULL, +	    NULL) == 0) { +		xmp->nullm_flags |= NULLM_NOUNPBYPASS; +	} +  	if (lowerrootvp == mp->mnt_vnodecovered) {  		vn_lock(lowerrootvp, LK_EXCLUSIVE | LK_RETRY | LK_CANRECURSE);  		lowerrootvp->v_vflag |= VV_CROSSLOCK; diff --git a/sys/fs/nullfs/null_vnops.c b/sys/fs/nullfs/null_vnops.c index 74c1a8f3acb6..d4baabeb40ab 100644 --- a/sys/fs/nullfs/null_vnops.c +++ b/sys/fs/nullfs/null_vnops.c @@ -174,6 +174,8 @@  #include <sys/mount.h>  #include <sys/mutex.h>  #include <sys/namei.h> +#include <sys/proc.h> +#include <sys/smr.h>  #include <sys/sysctl.h>  #include <sys/vnode.h>  #include <sys/stat.h> @@ -185,6 +187,8 @@  #include <vm/vm_object.h>  #include <vm/vnode_pager.h> +VFS_SMR_DECLARE; +  static int null_bug_bypass = 0;   /* for debugging: enables bypass printf'ing */  SYSCTL_INT(_debug, OID_AUTO, nullfs_bug_bypass, CTLFLAG_RW,   	&null_bug_bypass, 0, ""); @@ -273,9 +277,9 @@ null_bypass(struct vop_generic_args *ap)  		 * are of our type.  Check for and don't map any  		 * that aren't.  (We must always map first vp or vclean fails.)  		 */ -		if (i != 0 && (*this_vp_p == NULLVP || -		    (*this_vp_p)->v_op != &null_vnodeops)) { -			old_vps[i] = NULLVP; +		if (i != 0 && (*this_vp_p == NULL || +		    !null_is_nullfs_vnode(*this_vp_p))) { +			old_vps[i] = NULL;  		} else {  			old_vps[i] = *this_vp_p;  			*(vps_p[i]) = NULLVPTOLOWERVP(*this_vp_p); @@ -306,7 +310,7 @@ null_bypass(struct vop_generic_args *ap)  	 * with the modified argument structure.  	 */  	if (vps_p[0] != NULL && *vps_p[0] != NULL) { -		error = VCALL(ap); +		error = ap->a_desc->vdesc_call(ap);  	} else {  		printf("null_bypass: no map for %s\n", descp->vdesc_name);  		error = EINVAL; @@ -336,7 +340,7 @@ null_bypass(struct vop_generic_args *ap)  			 * must move lock ownership from lower to  			 * upper (reclaimed) vnode.  			 */ -			if (lvp != NULLVP) { +			if (lvp != NULL) {  				null_copy_inotify(old_vps[i], lvp,  				    VIRF_INOTIFY);  				null_copy_inotify(old_vps[i], lvp, @@ -494,7 +498,7 @@ null_lookup(struct vop_lookup_args *ap)  	if ((error == 0 || error == EJUSTRETURN) && lvp != NULL) {  		if (ldvp == lvp) {  			*ap->a_vpp = dvp; -			VREF(dvp); +			vref(dvp);  			vrele(lvp);  		} else {  			error = null_nodeget(mp, lvp, &vp); @@ -665,7 +669,7 @@ null_remove(struct vop_remove_args *ap)  	vp = ap->a_vp;  	if (vrefcnt(vp) > 1) {  		lvp = NULLVPTOLOWERVP(vp); -		VREF(lvp); +		vref(lvp);  		vreleit = 1;  	} else  		vreleit = 0; @@ -768,83 +772,111 @@ null_rmdir(struct vop_rmdir_args *ap)  }  /* - * We need to process our own vnode lock and then clear the - * interlock flag as it applies only to our vnode, not the - * vnodes below us on the stack. + * We need to process our own vnode lock and then clear the interlock flag as + * it applies only to our vnode, not the vnodes below us on the stack. + * + * We have to hold the vnode here to solve a potential reclaim race.  If we're + * forcibly vgone'd while we still have refs, a thread could be sleeping inside + * the lowervp's vop_lock routine.  When we vgone we will drop our last ref to + * the lowervp, which would allow it to be reclaimed.  The lowervp could then + * be recycled, in which case it is not legal to be sleeping in its VOP.  We + * prevent it from being recycled by holding the vnode here.   */ +static struct vnode * +null_lock_prep_with_smr(struct vop_lock1_args *ap) +{ +	struct null_node *nn; +	struct vnode *lvp; + +	lvp = NULL; + +	vfs_smr_enter(); + +	nn = VTONULL_SMR(ap->a_vp); +	if (__predict_true(nn != NULL)) { +		lvp = nn->null_lowervp; +		if (lvp != NULL && !vhold_smr(lvp)) +			lvp = NULL; +	} + +	vfs_smr_exit(); +	return (lvp); +} + +static struct vnode * +null_lock_prep_with_interlock(struct vop_lock1_args *ap) +{ +	struct null_node *nn; +	struct vnode *lvp; + +	ASSERT_VI_LOCKED(ap->a_vp, __func__); + +	ap->a_flags &= ~LK_INTERLOCK; + +	lvp = NULL; + +	nn = VTONULL(ap->a_vp); +	if (__predict_true(nn != NULL)) { +		lvp = nn->null_lowervp; +		if (lvp != NULL) +			vholdnz(lvp); +	} +	VI_UNLOCK(ap->a_vp); +	return (lvp); +} +  static int  null_lock(struct vop_lock1_args *ap)  { -	struct vnode *vp = ap->a_vp; -	int flags; -	struct null_node *nn;  	struct vnode *lvp; -	int error; +	int error, flags; -	if ((ap->a_flags & LK_INTERLOCK) == 0) -		VI_LOCK(vp); -	else -		ap->a_flags &= ~LK_INTERLOCK; -	flags = ap->a_flags; -	nn = VTONULL(vp); +	if (__predict_true((ap->a_flags & LK_INTERLOCK) == 0)) { +		lvp = null_lock_prep_with_smr(ap); +		if (__predict_false(lvp == NULL)) { +			VI_LOCK(ap->a_vp); +			lvp = null_lock_prep_with_interlock(ap); +		} +	} else { +		lvp = null_lock_prep_with_interlock(ap); +	} + +	ASSERT_VI_UNLOCKED(ap->a_vp, __func__); + +	if (__predict_false(lvp == NULL)) +		return (vop_stdlock(ap)); + +	VNPASS(lvp->v_holdcnt > 0, lvp); +	error = VOP_LOCK(lvp, ap->a_flags);  	/* -	 * If we're still active we must ask the lower layer to -	 * lock as ffs has special lock considerations in its -	 * vop lock. +	 * We might have slept to get the lock and someone might have +	 * clean our vnode already, switching vnode lock from one in +	 * lowervp to v_lock in our own vnode structure.  Handle this +	 * case by reacquiring correct lock in requested mode.  	 */ -	if (nn != NULL && (lvp = NULLVPTOLOWERVP(vp)) != NULL) { -		/* -		 * We have to hold the vnode here to solve a potential -		 * reclaim race.  If we're forcibly vgone'd while we -		 * still have refs, a thread could be sleeping inside -		 * the lowervp's vop_lock routine.  When we vgone we will -		 * drop our last ref to the lowervp, which would allow it -		 * to be reclaimed.  The lowervp could then be recycled, -		 * in which case it is not legal to be sleeping in its VOP. -		 * We prevent it from being recycled by holding the vnode -		 * here. -		 */ -		vholdnz(lvp); -		VI_UNLOCK(vp); -		error = VOP_LOCK(lvp, flags); - -		/* -		 * We might have slept to get the lock and someone might have -		 * clean our vnode already, switching vnode lock from one in -		 * lowervp to v_lock in our own vnode structure.  Handle this -		 * case by reacquiring correct lock in requested mode. -		 */ -		if (VTONULL(vp) == NULL && error == 0) { -			ap->a_flags &= ~LK_TYPE_MASK; -			switch (flags & LK_TYPE_MASK) { -			case LK_SHARED: -				ap->a_flags |= LK_SHARED; -				break; -			case LK_UPGRADE: -			case LK_EXCLUSIVE: -				ap->a_flags |= LK_EXCLUSIVE; -				break; -			default: -				panic("Unsupported lock request %d\n", -				    ap->a_flags); -			} -			VOP_UNLOCK(lvp); -			error = vop_stdlock(ap); +	if (VTONULL(ap->a_vp) == NULL && error == 0) { +		VOP_UNLOCK(lvp); + +		flags = ap->a_flags; +		ap->a_flags &= ~LK_TYPE_MASK; +		switch (flags & LK_TYPE_MASK) { +		case LK_SHARED: +			ap->a_flags |= LK_SHARED; +			break; +		case LK_UPGRADE: +		case LK_EXCLUSIVE: +			ap->a_flags |= LK_EXCLUSIVE; +			break; +		default: +			panic("Unsupported lock request %d\n", +			    flags);  		} -		vdrop(lvp); -	} else { -		VI_UNLOCK(vp);  		error = vop_stdlock(ap);  	} - +	vdrop(lvp);  	return (error);  } -/* - * We need to process our own vnode unlock and then clear the - * interlock flag as it applies only to our vnode, not the - * vnodes below us on the stack. - */  static int  null_unlock(struct vop_unlock_args *ap)  { @@ -853,11 +885,20 @@ null_unlock(struct vop_unlock_args *ap)  	struct vnode *lvp;  	int error; +	/* +	 * Contrary to null_lock, we don't need to hold the vnode around +	 * unlock. +	 * +	 * We hold the lock, which means we can't be racing against vgone. +	 * +	 * At the same time VOP_UNLOCK promises to not touch anything after +	 * it finishes unlock, just like we don't. +	 * +	 * vop_stdunlock for a doomed vnode matches doomed locking in null_lock. +	 */  	nn = VTONULL(vp);  	if (nn != NULL && (lvp = NULLVPTOLOWERVP(vp)) != NULL) { -		vholdnz(lvp);  		error = VOP_UNLOCK(lvp); -		vdrop(lvp);  	} else {  		error = vop_stdunlock(ap);  	} @@ -961,7 +1002,7 @@ null_reclaim(struct vop_reclaim_args *ap)  		vunref(lowervp);  	else  		vput(lowervp); -	free(xp, M_NULLFSNODE); +	uma_zfree_smr(null_node_zone, xp);  	return (0);  } @@ -1215,3 +1256,11 @@ struct vop_vector null_vnodeops = {  	.vop_copy_file_range =	VOP_PANIC,  };  VFS_VOP_VECTOR_REGISTER(null_vnodeops); + +struct vop_vector null_vnodeops_no_unp_bypass = { +	.vop_default =		&null_vnodeops, +	.vop_unp_bind =		vop_stdunp_bind, +	.vop_unp_connect =	vop_stdunp_connect, +	.vop_unp_detach =	vop_stdunp_detach, +}; +VFS_VOP_VECTOR_REGISTER(null_vnodeops_no_unp_bypass); diff --git a/sys/fs/p9fs/p9_transport.c b/sys/fs/p9fs/p9_transport.c index c82d81fedcd7..25eee984265c 100644 --- a/sys/fs/p9fs/p9_transport.c +++ b/sys/fs/p9fs/p9_transport.c @@ -34,9 +34,8 @@  TAILQ_HEAD(, p9_trans_module) transports;  static void -p9_transport_init(void) +p9_transport_init(void *dummy __unused)  { -          TAILQ_INIT(&transports);  } diff --git a/sys/fs/p9fs/p9fs_vfsops.c b/sys/fs/p9fs/p9fs_vfsops.c index e0e91e7e1709..953e6eda547a 100644 --- a/sys/fs/p9fs/p9fs_vfsops.c +++ b/sys/fs/p9fs/p9fs_vfsops.c @@ -287,7 +287,7 @@ p9fs_vget_common(struct mount *mp, struct p9fs_node *np, int flags,  			node->flags |= P9FS_NODE_DELETED;  			vput(vp); -			*vpp = NULLVP; +			*vpp = NULL;  			vp = NULL;  		} else {  			*vpp = vp; @@ -308,7 +308,7 @@ p9fs_vget_common(struct mount *mp, struct p9fs_node *np, int flags,  	/* Allocate a new vnode. */  	if ((error = getnewvnode("p9fs", mp, &p9fs_vnops, &vp)) != 0) { -		*vpp = NULLVP; +		*vpp = NULL;  		P9_DEBUG(ERROR, "%s: getnewvnode failed: %d\n", __func__, error);  		return (error);  	} @@ -397,7 +397,7 @@ out:  		vput(vp);  	} -	*vpp = NULLVP; +	*vpp = NULL;  	return (error);  } @@ -525,14 +525,14 @@ p9fs_root(struct mount *mp, int lkflags, struct vnode **vpp)  		if (vfid == NULL && clnt->trans_status == P9FS_BEGIN_DISCONNECT)  			vfid = vmp->p9fs_session.mnt_fid;  		else { -			*vpp = NULLVP; +			*vpp = NULL;  			return (error);  		}  	}  	error = p9fs_vget_common(mp, np, lkflags, np, vfid, vpp, NULL);  	if (error != 0) { -		*vpp = NULLVP; +		*vpp = NULL;  		return (error);  	}  	np->v_node = *vpp; diff --git a/sys/fs/p9fs/p9fs_vnops.c b/sys/fs/p9fs/p9fs_vnops.c index 227e2b93883e..2ed1be82b57f 100644 --- a/sys/fs/p9fs/p9fs_vnops.c +++ b/sys/fs/p9fs/p9fs_vnops.c @@ -233,7 +233,7 @@ p9fs_lookup(struct vop_lookup_args *ap)  	dnp = P9FS_VTON(dvp);  	error = 0;  	flags = cnp->cn_flags; -	*vpp = NULLVP; +	*vpp = NULL;  	if (dnp == NULL)  		return (ENOENT); @@ -329,7 +329,7 @@ p9fs_lookup(struct vop_lookup_args *ap)  		else  			vrele(vp); -		*vpp = NULLVP; +		*vpp = NULL;  	} else if (error == ENOENT) {  		if (VN_IS_DOOMED(dvp))  			goto out; @@ -341,7 +341,7 @@ p9fs_lookup(struct vop_lookup_args *ap)  	}  	/* Reset values */  	error = 0; -	vp = NULLVP; +	vp = NULL;  	tmpchr = cnp->cn_nameptr[cnp->cn_namelen];  	cnp->cn_nameptr[cnp->cn_namelen] = '\0'; @@ -1326,7 +1326,7 @@ p9fs_read(struct vop_read_args *ap)  	np = P9FS_VTON(vp);  	error = 0; -	if (vp->v_type == VCHR || vp->v_type == VBLK) +	if (VN_ISDEV(vp))  		return (EOPNOTSUPP);  	if (vp->v_type != VREG)  		return (EISDIR); diff --git a/sys/fs/procfs/procfs.c b/sys/fs/procfs/procfs.c index ab60ba47f322..cd66dd6f8b3b 100644 --- a/sys/fs/procfs/procfs.c +++ b/sys/fs/procfs/procfs.c @@ -156,42 +156,42 @@ procfs_init(PFS_INIT_ARGS)  	root = pi->pi_root; -	pfs_create_link(root, "curproc", procfs_docurproc, -	    NULL, NULL, NULL, 0); -	pfs_create_link(root, "self", procfs_docurproc, -	    NULL, NULL, NULL, 0); - -	dir = pfs_create_dir(root, "pid", -	    procfs_attr_all_rx, NULL, NULL, PFS_PROCDEP); -	pfs_create_file(dir, "cmdline", procfs_doproccmdline, -	    NULL, NULL, NULL, PFS_RD); -	pfs_create_file(dir, "dbregs", procfs_doprocdbregs, +	pfs_create_link(root, NULL, "curproc", procfs_docurproc, NULL, NULL, +	    NULL, 0); +	pfs_create_link(root, NULL, "self", procfs_docurproc, NULL, NULL, NULL, +	    0); + +	pfs_create_dir(root, &dir, "pid", procfs_attr_all_rx, NULL, NULL, +	    PFS_PROCDEP); +	pfs_create_file(dir, NULL, "cmdline", procfs_doproccmdline, NULL, NULL, +	    NULL, PFS_RD); +	pfs_create_file(dir, NULL, "dbregs", procfs_doprocdbregs,  	    procfs_attr_rw, procfs_candebug, NULL, PFS_RDWR | PFS_RAW); -	pfs_create_file(dir, "etype", procfs_doproctype, -	    NULL, NULL, NULL, PFS_RD); -	pfs_create_file(dir, "fpregs", procfs_doprocfpregs, +	pfs_create_file(dir, NULL, "etype", procfs_doproctype, NULL, NULL, NULL, +	    PFS_RD); +	pfs_create_file(dir, NULL, "fpregs", procfs_doprocfpregs,  	    procfs_attr_rw, procfs_candebug, NULL, PFS_RDWR | PFS_RAW); -	pfs_create_file(dir, "map", procfs_doprocmap, -	    NULL, procfs_notsystem, NULL, PFS_RD); -	pfs_create_file(dir, "mem", procfs_doprocmem, -	    procfs_attr_rw, procfs_candebug, NULL, PFS_RDWR | PFS_RAW); -	pfs_create_file(dir, "note", procfs_doprocnote, -	    procfs_attr_w, procfs_candebug, NULL, PFS_WR); -	pfs_create_file(dir, "notepg", procfs_doprocnote, -	    procfs_attr_w, procfs_candebug, NULL, PFS_WR); -	pfs_create_file(dir, "regs", procfs_doprocregs, -	    procfs_attr_rw, procfs_candebug, NULL, PFS_RDWR | PFS_RAW); -	pfs_create_file(dir, "rlimit", procfs_doprocrlimit, -	    NULL, NULL, NULL, PFS_RD); -	pfs_create_file(dir, "status", procfs_doprocstatus, -	    NULL, NULL, NULL, PFS_RD); -	pfs_create_file(dir, "osrel", procfs_doosrel, -	    procfs_attr_rw, procfs_candebug, NULL, PFS_RDWR); - -	pfs_create_link(dir, "file", procfs_doprocfile, -	    NULL, procfs_notsystem, NULL, 0); -	pfs_create_link(dir, "exe", procfs_doprocfile, -	    NULL, procfs_notsystem, NULL, 0); +	pfs_create_file(dir, NULL, "map", procfs_doprocmap, NULL, +	    procfs_notsystem, NULL, PFS_RD); +	pfs_create_file(dir, NULL, "mem", procfs_doprocmem, procfs_attr_rw, +	    procfs_candebug, NULL, PFS_RDWR | PFS_RAW); +	pfs_create_file(dir, NULL, "note", procfs_doprocnote, procfs_attr_w, +	    procfs_candebug, NULL, PFS_WR); +	pfs_create_file(dir, NULL, "notepg", procfs_doprocnote, procfs_attr_w, +	    procfs_candebug, NULL, PFS_WR); +	pfs_create_file(dir, NULL, "regs", procfs_doprocregs, procfs_attr_rw, +	    procfs_candebug, NULL, PFS_RDWR | PFS_RAW); +	pfs_create_file(dir, NULL, "rlimit", procfs_doprocrlimit, NULL, NULL, +	    NULL, PFS_RD); +	pfs_create_file(dir, NULL, "status", procfs_doprocstatus, NULL, NULL, +	    NULL, PFS_RD); +	pfs_create_file(dir, NULL, "osrel", procfs_doosrel, procfs_attr_rw, +	    procfs_candebug, NULL, PFS_RDWR); + +	pfs_create_link(dir, NULL, "file", procfs_doprocfile, NULL, +	    procfs_notsystem, NULL, 0); +	pfs_create_link(dir, NULL, "exe", procfs_doprocfile, NULL, +	    procfs_notsystem, NULL, 0);  	return (0);  } diff --git a/sys/fs/procfs/procfs_status.c b/sys/fs/procfs/procfs_status.c index 38070e0946bb..49c084d02ff8 100644 --- a/sys/fs/procfs/procfs_status.c +++ b/sys/fs/procfs/procfs_status.c @@ -141,13 +141,9 @@ procfs_doprocstatus(PFS_FILL_ARGS)  		(u_long)cr->cr_uid,  		(u_long)cr->cr_ruid,  		(u_long)cr->cr_rgid); - -	/* egid (cr->cr_svgid) is equal to cr_ngroups[0] -	   see also getegid(2) in /sys/kern/kern_prot.c */ - -	for (i = 0; i < cr->cr_ngroups; i++) { +	sbuf_printf(sb, ",%lu", (u_long)cr->cr_gid); +	for (i = 0; i < cr->cr_ngroups; i++)  		sbuf_printf(sb, ",%lu", (u_long)cr->cr_groups[i]); -	}  	if (jailed(cr)) {  		mtx_lock(&cr->cr_prison->pr_mtx); diff --git a/sys/fs/pseudofs/pseudofs.c b/sys/fs/pseudofs/pseudofs.c index ef45f96a6192..7a4e67455214 100644 --- a/sys/fs/pseudofs/pseudofs.c +++ b/sys/fs/pseudofs/pseudofs.c @@ -133,7 +133,7 @@ pfs_add_node(struct pfs_node *parent, struct pfs_node *pn)  	for (iter = parent->pn_nodes; iter != NULL; iter = iter->pn_next) {  		if (strcmp(pn->pn_name, iter->pn_name) != 0)  			continue; -		printf("pfs_add_node: homonymous siblings: '%s/%s' type %d", +		printf("pfs_add_node: homonymous siblings: '%s/%s' type %d\n",  		    parent->pn_name, pn->pn_name, pn->pn_type);  		/* Do not detach, because we are not yet attached. */  		pn->pn_parent = NULL; @@ -234,81 +234,101 @@ pfs_fixup_dir(struct pfs_node *parent)  /*   * Create a directory   */ -struct pfs_node	* -pfs_create_dir(struct pfs_node *parent, const char *name, -	       pfs_attr_t attr, pfs_vis_t vis, pfs_destroy_t destroy, -	       int flags) +int +pfs_create_dir(struct pfs_node *parent, struct pfs_node **opn, +	       const char *name, pfs_attr_t attr, pfs_vis_t vis, +	       pfs_destroy_t destroy, int flags)  { -	struct pfs_node *pn; +	struct pfs_node *pdir, *pn;  	int rc; -	pn = pfs_alloc_node_flags(parent->pn_info, name, +	/* Preserve in case the caller is reusing the one pointer for both. */ +	pdir = parent; +	if (opn != NULL) +		*opn = NULL; +	pn = pfs_alloc_node_flags(pdir->pn_info, name,  			 (flags & PFS_PROCDEP) ? pfstype_procdir : pfstype_dir, flags);  	if (pn == NULL) -		return (NULL); +		return (ENOMEM);  	pn->pn_attr = attr;  	pn->pn_vis = vis;  	pn->pn_destroy = destroy;  	pn->pn_flags = flags; -	rc = pfs_add_node(parent, pn); +	rc = pfs_add_node(pdir, pn);  	if (rc == 0)  		rc = pfs_fixup_dir_flags(pn, flags);  	if (rc != 0) {  		pfs_destroy(pn);  		pn = NULL; +	} else if (opn != NULL) { +		*opn = pn;  	} -	return (pn); + +	return (rc);  }  /*   * Create a file   */ -struct pfs_node	* -pfs_create_file(struct pfs_node *parent, const char *name, pfs_fill_t fill, -		pfs_attr_t attr, pfs_vis_t vis, pfs_destroy_t destroy, -		int flags) +int +pfs_create_file(struct pfs_node *parent, struct pfs_node **opn, +		const char *name, pfs_fill_t fill, pfs_attr_t attr, +		pfs_vis_t vis, pfs_destroy_t destroy, int flags)  {  	struct pfs_node *pn; +	int rc; +	if (opn != NULL) +		*opn = NULL;  	pn = pfs_alloc_node_flags(parent->pn_info, name, pfstype_file, flags);  	if (pn == NULL) -		return (NULL); +		return (ENOMEM); +  	pn->pn_fill = fill;  	pn->pn_attr = attr;  	pn->pn_vis = vis;  	pn->pn_destroy = destroy;  	pn->pn_flags = flags; -	if (pfs_add_node(parent, pn) != 0) { +	if ((rc = pfs_add_node(parent, pn)) != 0) {  		pfs_destroy(pn);  		pn = NULL; +	} else if (opn != NULL) { +		*opn = pn;  	} -	return (pn); + +	return (rc);  }  /*   * Create a symlink   */ -struct pfs_node	* -pfs_create_link(struct pfs_node *parent, const char *name, pfs_fill_t fill, -		pfs_attr_t attr, pfs_vis_t vis, pfs_destroy_t destroy, -		int flags) +int +pfs_create_link(struct pfs_node *parent, struct pfs_node **opn, +		const char *name, pfs_fill_t fill, pfs_attr_t attr, +		pfs_vis_t vis, pfs_destroy_t destroy, int flags)  {  	struct pfs_node *pn; +	int rc; +	if (opn != NULL) +		*opn = NULL;  	pn = pfs_alloc_node_flags(parent->pn_info, name, pfstype_symlink, flags);  	if (pn == NULL) -		return (NULL); +		return (ENOMEM); +  	pn->pn_fill = fill;  	pn->pn_attr = attr;  	pn->pn_vis = vis;  	pn->pn_destroy = destroy;  	pn->pn_flags = flags; -	if (pfs_add_node(parent, pn) != 0) { +	if ((rc = pfs_add_node(parent, pn)) != 0) {  		pfs_destroy(pn);  		pn = NULL; +	} else if (opn != NULL) { +		*opn = pn;  	} -	return (pn); +	return (rc);  }  /* @@ -475,6 +495,7 @@ pfs_init(struct pfs_info *pi, struct vfsconf *vfc)  	if (error) {  		pfs_destroy(root);  		pi->pi_root = NULL; +		pfs_fileno_uninit(pi);  		return (error);  	} diff --git a/sys/fs/pseudofs/pseudofs.h b/sys/fs/pseudofs/pseudofs.h index c60dd7b339d1..2b08dcad978d 100644 --- a/sys/fs/pseudofs/pseudofs.h +++ b/sys/fs/pseudofs/pseudofs.h @@ -255,17 +255,18 @@ int		 pfs_uninit	(struct pfs_info *pi, struct vfsconf *vfc);  /*   * Directory structure construction and manipulation   */ -struct pfs_node	*pfs_create_dir	(struct pfs_node *parent, const char *name, -				 pfs_attr_t attr, pfs_vis_t vis, -				 pfs_destroy_t destroy, int flags); -struct pfs_node	*pfs_create_file(struct pfs_node *parent, const char *name, -				 pfs_fill_t fill, pfs_attr_t attr, -				 pfs_vis_t vis, pfs_destroy_t destroy, -				 int flags); -struct pfs_node	*pfs_create_link(struct pfs_node *parent, const char *name, -				 pfs_fill_t fill, pfs_attr_t attr, +int pfs_create_dir		(struct pfs_node *parent, struct pfs_node **opn, +				 const char *name, pfs_attr_t attr,  				 pfs_vis_t vis, pfs_destroy_t destroy,  				 int flags); +int pfs_create_file		(struct pfs_node *parent, struct pfs_node **opn, +				 const char *name, pfs_fill_t fill, +				 pfs_attr_t attr, pfs_vis_t vis, +				 pfs_destroy_t destroy, int flags); +int pfs_create_link		(struct pfs_node *parent, struct pfs_node **opn, +				 const char *name, pfs_fill_t fill, +				 pfs_attr_t attr, pfs_vis_t vis, +				 pfs_destroy_t destroy, int flags);  struct pfs_node	*pfs_find_node	(struct pfs_node *parent, const char *name);  void		 pfs_purge	(struct pfs_node *pn);  int		 pfs_destroy	(struct pfs_node *pn); diff --git a/sys/fs/pseudofs/pseudofs_vncache.c b/sys/fs/pseudofs/pseudofs_vncache.c index e58aced7f81b..4fd493f8b9d3 100644 --- a/sys/fs/pseudofs/pseudofs_vncache.c +++ b/sys/fs/pseudofs/pseudofs_vncache.c @@ -202,7 +202,7 @@ alloc:  	error = insmntque(*vpp, mp);  	if (error != 0) {  		free(pvd, M_PFSVNCACHE); -		*vpp = NULLVP; +		*vpp = NULL;  		return (error);  	}  	vn_set_state(*vpp, VSTATE_CONSTRUCTED); diff --git a/sys/fs/pseudofs/pseudofs_vnops.c b/sys/fs/pseudofs/pseudofs_vnops.c index 8cd092118d0e..a30b5e4f551d 100644 --- a/sys/fs/pseudofs/pseudofs_vnops.c +++ b/sys/fs/pseudofs/pseudofs_vnops.c @@ -485,7 +485,7 @@ pfs_lookup(struct vop_cachedlookup_args *va)  	if (namelen == 1 && pname[0] == '.') {  		pn = pd;  		*vpp = vn; -		VREF(vn); +		vref(vn);  		PFS_RETURN (0);  	} diff --git a/sys/fs/smbfs/smbfs_vnops.c b/sys/fs/smbfs/smbfs_vnops.c index 63b249c93771..e960d8d78b66 100644 --- a/sys/fs/smbfs/smbfs_vnops.c +++ b/sys/fs/smbfs/smbfs_vnops.c @@ -1121,13 +1121,13 @@ smbfs_lookup(struct vop_lookup_args *ap)  			vput(vp);  		else  			vrele(vp); -		*vpp = NULLVP; +		*vpp = NULL;  	}  	/*   	 * entry is not in the cache or has been expired  	 */  	error = 0; -	*vpp = NULLVP; +	*vpp = NULL;  	scred = smbfs_malloc_scred();  	smb_makescred(scred, td, cnp->cn_cred);  	fap = &fattr; @@ -1174,7 +1174,7 @@ smbfs_lookup(struct vop_lookup_args *ap)  		if (error)  			goto out;  		if (isdot) { -			VREF(dvp); +			vref(dvp);  			*vpp = dvp;  			goto out;  		} diff --git a/sys/fs/tarfs/tarfs_vfsops.c b/sys/fs/tarfs/tarfs_vfsops.c index a534b18ebf34..4cc70e4d5781 100644 --- a/sys/fs/tarfs/tarfs_vfsops.c +++ b/sys/fs/tarfs/tarfs_vfsops.c @@ -1201,7 +1201,7 @@ tarfs_vget(struct mount *mp, ino_t ino, int lkflags, struct vnode **vpp)  	return (0);  bad: -	*vpp = NULLVP; +	*vpp = NULL;  	return (error);  } @@ -1220,7 +1220,7 @@ tarfs_fhtovp(struct mount *mp, struct fid *fhp, int flags, struct vnode **vpp)  	error = VFS_VGET(mp, tfp->ino, LK_EXCLUSIVE, &nvp);  	if (error != 0) { -		*vpp = NULLVP; +		*vpp = NULL;  		return (error);  	}  	tnp = VP_TO_TARFS_NODE(nvp); @@ -1228,7 +1228,7 @@ tarfs_fhtovp(struct mount *mp, struct fid *fhp, int flags, struct vnode **vpp)  	    tnp->gen != tfp->gen ||  	    tnp->nlink <= 0) {  		vput(nvp); -		*vpp = NULLVP; +		*vpp = NULL;  		return (ESTALE);  	}  	*vpp = nvp; diff --git a/sys/fs/tarfs/tarfs_vnops.c b/sys/fs/tarfs/tarfs_vnops.c index afb8e05f5929..70fd7a441d81 100644 --- a/sys/fs/tarfs/tarfs_vnops.c +++ b/sys/fs/tarfs/tarfs_vnops.c @@ -208,8 +208,7 @@ tarfs_getattr(struct vop_getattr_args *ap)  	vap->va_birthtime = tnp->birthtime;  	vap->va_gen = tnp->gen;  	vap->va_flags = tnp->flags; -	vap->va_rdev = (vp->v_type == VBLK || vp->v_type == VCHR) ? -	    tnp->rdev : NODEV; +	vap->va_rdev = VN_ISDEV(vp) ? tnp->rdev : NODEV;  	vap->va_bytes = round_page(tnp->physize);  	vap->va_filerev = 0; @@ -232,7 +231,7 @@ tarfs_lookup(struct vop_cachedlookup_args *ap)  	vpp = ap->a_vpp;  	cnp = ap->a_cnp; -	*vpp = NULLVP; +	*vpp = NULL;  	dirnode = VP_TO_TARFS_NODE(dvp);  	parent = dirnode->parent;  	tmp = dirnode->tmp; @@ -257,7 +256,7 @@ tarfs_lookup(struct vop_cachedlookup_args *ap)  		if (error != 0)  			return (error);  	} else if (cnp->cn_namelen == 1 && cnp->cn_nameptr[0] == '.') { -		VREF(dvp); +		vref(dvp);  		*vpp = dvp;  #ifdef TARFS_DEBUG  	} else if (dirnode == dirnode->tmp->root && @@ -335,6 +334,10 @@ tarfs_readdir(struct vop_readdir_args *ap)  	    tnp, tnp->name, uio->uio_offset, uio->uio_resid);  	if (uio->uio_offset == TARFS_COOKIE_EOF) { +		if (eofflag != NULL) { +			TARFS_DPF(VNODE, "%s: Setting EOF flag\n", __func__); +			*eofflag = 1; +		}  		TARFS_DPF(VNODE, "%s: EOF\n", __func__);  		return (0);  	} @@ -515,7 +518,7 @@ tarfs_read(struct vop_read_args *ap)  	uiop = ap->a_uio;  	vp = ap->a_vp; -	if (vp->v_type == VCHR || vp->v_type == VBLK) +	if (VN_ISDEV(vp))  		return (EOPNOTSUPP);  	if (vp->v_type != VREG) @@ -582,7 +585,7 @@ tarfs_reclaim(struct vop_reclaim_args *ap)  	vfs_hash_remove(vp);  	TARFS_NODE_LOCK(tnp); -	tnp->vnode = NULLVP; +	tnp->vnode = NULL;  	vp->v_data = NULL;  	TARFS_NODE_UNLOCK(tnp); diff --git a/sys/fs/tmpfs/tmpfs_subr.c b/sys/fs/tmpfs/tmpfs_subr.c index 1237f6b92cdb..dd281d18d87d 100644 --- a/sys/fs/tmpfs/tmpfs_subr.c +++ b/sys/fs/tmpfs/tmpfs_subr.c @@ -551,7 +551,7 @@ tmpfs_alloc_node(struct mount *mp, struct tmpfs_mount *tmp, __enum_uint8(vtype)  	MPASS(IMPLIES(tmp->tm_root == NULL, parent == NULL && type == VDIR));  	MPASS((type == VLNK) ^ (target == NULL)); -	MPASS((type == VBLK || type == VCHR) ^ (rdev == VNOVAL)); +	MPASS(VTYPE_ISDEV(type) ^ (rdev == VNOVAL));  	if (tmp->tm_nodes_inuse >= tmp->tm_nodes_max)  		return (ENOSPC); diff --git a/sys/fs/tmpfs/tmpfs_vnops.c b/sys/fs/tmpfs/tmpfs_vnops.c index 79b6c8b2e6a1..5082ee1ebdd0 100644 --- a/sys/fs/tmpfs/tmpfs_vnops.c +++ b/sys/fs/tmpfs/tmpfs_vnops.c @@ -98,7 +98,7 @@ tmpfs_lookup1(struct vnode *dvp, struct vnode **vpp, struct componentname *cnp)  	/* Caller assumes responsibility for ensuring access (VEXEC). */  	dnode = VP_TO_TMPFS_DIR(dvp); -	*vpp = NULLVP; +	*vpp = NULL;  	/* We cannot be requesting the parent directory of the root node. */  	MPASS(IMPLIES(dnode->tn_type == VDIR && @@ -120,7 +120,7 @@ tmpfs_lookup1(struct vnode *dvp, struct vnode **vpp, struct componentname *cnp)  		if (error != 0)  			goto out;  	} else if (cnp->cn_namelen == 1 && cnp->cn_nameptr[0] == '.') { -		VREF(dvp); +		vref(dvp);  		*vpp = dvp;  		error = 0;  	} else { @@ -222,7 +222,7 @@ out:  	 * locked.  	 */  	if (error == 0) { -		MPASS(*vpp != NULLVP); +		MPASS(*vpp != NULL);  		ASSERT_VOP_LOCKED(*vpp, __func__);  	} else {  		MPASS(*vpp == NULL); @@ -280,8 +280,7 @@ tmpfs_mknod(struct vop_mknod_args *v)  	struct componentname *cnp = v->a_cnp;  	struct vattr *vap = v->a_vap; -	if (vap->va_type != VBLK && vap->va_type != VCHR && -	    vap->va_type != VFIFO) +	if (!VATTR_ISDEV(vap) && vap->va_type != VFIFO)  		return (EINVAL);  	return (tmpfs_alloc_file(dvp, vpp, vap, cnp, NULL)); @@ -462,8 +461,7 @@ tmpfs_stat(struct vop_stat_args *v)  	sb->st_nlink = node->tn_links;  	sb->st_uid = node->tn_uid;  	sb->st_gid = node->tn_gid; -	sb->st_rdev = (vp->v_type == VBLK || vp->v_type == VCHR) ? -		node->tn_rdev : NODEV; +	sb->st_rdev = VN_ISDEV(vp) ? node->tn_rdev : NODEV;  	sb->st_size = node->tn_size;  	sb->st_atim.tv_sec = node->tn_atime.tv_sec;  	sb->st_atim.tv_nsec = node->tn_atime.tv_nsec; @@ -521,8 +519,7 @@ tmpfs_getattr(struct vop_getattr_args *v)  	vap->va_birthtime = node->tn_birthtime;  	vap->va_gen = node->tn_gen;  	vap->va_flags = node->tn_flags; -	vap->va_rdev = (vp->v_type == VBLK || vp->v_type == VCHR) ? -	    node->tn_rdev : NODEV; +	vap->va_rdev = VN_ISDEV(vp) ? node->tn_rdev : NODEV;  	if (vp->v_type == VREG) {  #ifdef __ILP32__  		vm_object_t obj = node->tn_reg.tn_aobj; @@ -1918,7 +1915,7 @@ tmpfs_deleteextattr(struct vop_deleteextattr_args *ap)  	node = VP_TO_TMPFS_NODE(vp);  	tmp = VFS_TO_TMPFS(vp->v_mount); -	if (ap->a_vp->v_type == VCHR || ap->a_vp->v_type == VBLK) +	if (VN_ISDEV(ap->a_vp))  		return (EOPNOTSUPP);  	error = extattr_check_cred(ap->a_vp, ap->a_attrnamespace,  	    ap->a_cred, ap->a_td, VWRITE); @@ -1956,7 +1953,7 @@ tmpfs_getextattr(struct vop_getextattr_args *ap)  	int error;  	node = VP_TO_TMPFS_NODE(vp); -	if (ap->a_vp->v_type == VCHR || ap->a_vp->v_type == VBLK) +	if (VN_ISDEV(ap->a_vp))  		return (EOPNOTSUPP);  	error = extattr_check_cred(ap->a_vp, ap->a_attrnamespace,  	    ap->a_cred, ap->a_td, VREAD); @@ -1993,7 +1990,7 @@ tmpfs_listextattr(struct vop_listextattr_args *ap)  	int error;  	node = VP_TO_TMPFS_NODE(vp); -	if (ap->a_vp->v_type == VCHR || ap->a_vp->v_type == VBLK) +	if (VN_ISDEV(ap->a_vp))  		return (EOPNOTSUPP);  	error = extattr_check_cred(ap->a_vp, ap->a_attrnamespace,  	    ap->a_cred, ap->a_td, VREAD); @@ -2037,7 +2034,7 @@ tmpfs_setextattr(struct vop_setextattr_args *ap)  	tmp = VFS_TO_TMPFS(vp->v_mount);  	attr_size = ap->a_uio->uio_resid;  	diff = 0; -	if (ap->a_vp->v_type == VCHR || ap->a_vp->v_type == VBLK) +	if (VN_ISDEV(ap->a_vp))  		return (EOPNOTSUPP);  	error = extattr_check_cred(ap->a_vp, ap->a_attrnamespace,  	    ap->a_cred, ap->a_td, VWRITE); diff --git a/sys/fs/udf/osta.c b/sys/fs/udf/osta.c index f79b86993367..1a083d8c26b1 100644 --- a/sys/fs/udf/osta.c +++ b/sys/fs/udf/osta.c @@ -383,7 +383,7 @@ int UDFTransName(  			int maxFilenameLen;  			/* Translate extension, and store it in ext. */  			for(index = 0; index<EXT_SIZE && -			    extIndex + index +1 < udfLen; index++ ) { +			    extIndex + index +1 < udfLen; index++) {  				current = udfName[extIndex + index + 1];  				if (IsIllegal(current) ||  				    !UnicodeIsPrint(current)) { @@ -432,7 +432,7 @@ int UDFTransName(  		/* Place a translated extension at end, if found. */  		if (hasExt) {  			newName[newIndex++] = PERIOD; -			for (index = 0;index < localExtIndex ;index++ ) { +			for (index = 0; index < localExtIndex; index++) {  				newName[newIndex++] = ext[index];  			}  		} diff --git a/sys/fs/udf/udf_vfsops.c b/sys/fs/udf/udf_vfsops.c index c5ef1f686093..c1627285a174 100644 --- a/sys/fs/udf/udf_vfsops.c +++ b/sys/fs/udf/udf_vfsops.c @@ -736,14 +736,14 @@ udf_fhtovp(struct mount *mp, struct fid *fhp, int flags, struct vnode **vpp)  	ifhp = (struct ifid *)fhp;  	if ((error = VFS_VGET(mp, ifhp->ifid_ino, LK_EXCLUSIVE, &nvp)) != 0) { -		*vpp = NULLVP; +		*vpp = NULL;  		return (error);  	}  	np = VTON(nvp);  	fsize = le64toh(np->fentry->inf_len);  	if (fsize > OFF_MAX) { -		*vpp = NULLVP; +		*vpp = NULL;  		return (EIO);  	} diff --git a/sys/fs/udf/udf_vnops.c b/sys/fs/udf/udf_vnops.c index 37889241e8c3..ec61618b6e18 100644 --- a/sys/fs/udf/udf_vnops.c +++ b/sys/fs/udf/udf_vnops.c @@ -1226,7 +1226,7 @@ lookloop:  		if (flags & ISDOTDOT) {  			error = vn_vget_ino(dvp, id, lkflags, &tdp);  		} else if (node->hash_id == id) { -			VREF(dvp);	/* we want ourself, ie "." */ +			vref(dvp);	/* we want ourself, ie "." */  			/*  			 * When we lookup "." we still can be asked to lock it  			 * differently. diff --git a/sys/fs/unionfs/union_subr.c b/sys/fs/unionfs/union_subr.c index edcc6716b674..b6d6db60ca3d 100644 --- a/sys/fs/unionfs/union_subr.c +++ b/sys/fs/unionfs/union_subr.c @@ -160,7 +160,7 @@ unionfs_get_cached_vnode_locked(struct vnode *lookup, struct vnode *dvp)  			if (VN_IS_DOOMED(vp) ||  			    ((vp->v_iflag & VI_DOINGINACT) != 0)) {  				VI_UNLOCK(vp); -				vp = NULLVP; +				vp = NULL;  			} else {  				vrefl(vp);  				VI_UNLOCK(vp); @@ -169,7 +169,7 @@ unionfs_get_cached_vnode_locked(struct vnode *lookup, struct vnode *dvp)  		}  	} -	return (NULLVP); +	return (NULL);  } @@ -182,11 +182,11 @@ unionfs_get_cached_vnode(struct vnode *uvp, struct vnode *lvp,  {  	struct vnode *vp; -	vp = NULLVP; +	vp = NULL;  	VI_LOCK(dvp); -	if (uvp != NULLVP) +	if (uvp != NULL)  		vp = unionfs_get_cached_vnode_locked(uvp, dvp); -	else if (lvp != NULLVP) +	else if (lvp != NULL)  		vp = unionfs_get_cached_vnode_locked(lvp, dvp);  	VI_UNLOCK(dvp); @@ -203,22 +203,22 @@ unionfs_ins_cached_vnode(struct unionfs_node *uncp,  	struct unionfs_node_hashhead *hd;  	struct vnode *vp; -	vp = NULLVP; +	vp = NULL;  	VI_LOCK(dvp); -	if (uncp->un_uppervp != NULLVP) { +	if (uncp->un_uppervp != NULL) {  		ASSERT_VOP_ELOCKED(uncp->un_uppervp, __func__);  		KASSERT(uncp->un_uppervp->v_type == VDIR,  		    ("%s: v_type != VDIR", __func__));  		vp = unionfs_get_cached_vnode_locked(uncp->un_uppervp, dvp); -	} else if (uncp->un_lowervp != NULLVP) { +	} else if (uncp->un_lowervp != NULL) {  		ASSERT_VOP_ELOCKED(uncp->un_lowervp, __func__);  		KASSERT(uncp->un_lowervp->v_type == VDIR,  		    ("%s: v_type != VDIR", __func__));  		vp = unionfs_get_cached_vnode_locked(uncp->un_lowervp, dvp);  	} -	if (vp == NULLVP) { -		hd = unionfs_get_hashhead(dvp, (uncp->un_uppervp != NULLVP ? -		    uncp->un_uppervp : uncp->un_lowervp)); +	if (vp == NULL) { +		hd = unionfs_get_hashhead(dvp, (uncp->un_uppervp != NULL ? +						uncp->un_uppervp : uncp->un_lowervp));  		LIST_INSERT_HEAD(hd, uncp, un_hash);  	}  	VI_UNLOCK(dvp); @@ -233,8 +233,8 @@ static void  unionfs_rem_cached_vnode(struct unionfs_node *unp, struct vnode *dvp)  {  	KASSERT(unp != NULL, ("%s: null node", __func__)); -	KASSERT(dvp != NULLVP, -	    ("%s: null parent vnode", __func__)); +	KASSERT(dvp != NULL, +		("%s: null parent vnode", __func__));  	VI_LOCK(dvp);  	if (unp->un_hash.le_prev != NULL) { @@ -274,13 +274,13 @@ unionfs_nodeget_cleanup(struct vnode *vp, struct unionfs_node *unp)  	vgone(vp);  	vput(vp); -	if (unp->un_dvp != NULLVP) +	if (unp->un_dvp != NULL)  		vrele(unp->un_dvp); -	if (unp->un_uppervp != NULLVP) { +	if (unp->un_uppervp != NULL) {  		vput(unp->un_uppervp); -		if (unp->un_lowervp != NULLVP) +		if (unp->un_lowervp != NULL)  			vrele(unp->un_lowervp); -	} else if (unp->un_lowervp != NULLVP) +	} else if (unp->un_lowervp != NULL)  		vput(unp->un_lowervp);  	if (unp->un_hashtbl != NULL)  		hashdestroy(unp->un_hashtbl, M_UNIONFSHASH, UNIONFSHASHMASK); @@ -313,21 +313,21 @@ unionfs_nodeget(struct mount *mp, struct vnode *uppervp,  	ump = MOUNTTOUNIONFSMOUNT(mp);  	lkflags = (cnp ? cnp->cn_lkflags : 0);  	path = (cnp ? cnp->cn_nameptr : NULL); -	*vpp = NULLVP; +	*vpp = NULL; -	if (uppervp == NULLVP && lowervp == NULLVP) +	if (uppervp == NULL && lowervp == NULL)  		panic("%s: upper and lower are both null", __func__); -	vt = (uppervp != NULLVP ? uppervp->v_type : lowervp->v_type); +	vt = (uppervp != NULL ? uppervp->v_type : lowervp->v_type);  	/* If it has no ISLASTCN flag, path check is skipped. */  	if (cnp && !(cnp->cn_flags & ISLASTCN))  		path = NULL;  	/* check the cache */ -	if (dvp != NULLVP && vt == VDIR) { +	if (dvp != NULL && vt == VDIR) {  		vp = unionfs_get_cached_vnode(uppervp, lowervp, dvp); -		if (vp != NULLVP) { +		if (vp != NULL) {  			*vpp = vp;  			if (lkflags != 0)  				vn_lock(*vpp, lkflags | LK_RETRY); @@ -343,11 +343,11 @@ unionfs_nodeget(struct mount *mp, struct vnode *uppervp,  		free(unp, M_UNIONFSNODE);  		return (error);  	} -	if (dvp != NULLVP) +	if (dvp != NULL)  		vref(dvp); -	if (uppervp != NULLVP) +	if (uppervp != NULL)  		vref(uppervp); -	if (lowervp != NULLVP) +	if (lowervp != NULL)  		vref(lowervp);  	if (vt == VDIR) { @@ -361,7 +361,7 @@ unionfs_nodeget(struct mount *mp, struct vnode *uppervp,  	unp->un_uppervp = uppervp;  	unp->un_lowervp = lowervp;  	unp->un_dvp = dvp; -	if (uppervp != NULLVP) +	if (uppervp != NULL)  		vp->v_vnlock = uppervp->v_vnlock;  	else  		vp->v_vnlock = lowervp->v_vnlock; @@ -407,7 +407,7 @@ unionfs_nodeget(struct mount *mp, struct vnode *uppervp,  	 * possibility of deadlock due to some other agent on the system  	 * attempting to lock those two specific vnodes in the opposite order.  	 */ -	if (uppervp != NULLVP) +	if (uppervp != NULL)  		vn_lock(uppervp, LK_EXCLUSIVE | LK_RETRY);  	else  		vn_lock(lowervp, LK_EXCLUSIVE | LK_RETRY); @@ -426,16 +426,16 @@ unionfs_nodeget(struct mount *mp, struct vnode *uppervp,  	 * blocked on our vnode lock, effectively also preventing unmount  	 * of the underlying filesystems.  	 */ -	VNASSERT(lowervp == NULLVP || !VN_IS_DOOMED(lowervp), vp, +	VNASSERT(lowervp == NULL || !VN_IS_DOOMED(lowervp), vp,  	    ("%s: doomed lowervp %p", __func__, lowervp)); -	VNASSERT(uppervp == NULLVP || !VN_IS_DOOMED(uppervp), vp, +	VNASSERT(uppervp == NULL || !VN_IS_DOOMED(uppervp), vp,  	    ("%s: doomed lowervp %p", __func__, uppervp));  	vn_set_state(vp, VSTATE_CONSTRUCTED); -	if (dvp != NULLVP && vt == VDIR) +	if (dvp != NULL && vt == VDIR)  		*vpp = unionfs_ins_cached_vnode(unp, dvp); -	if (*vpp != NULLVP) { +	if (*vpp != NULL) {  		unionfs_nodeget_cleanup(vp, unp);  		if (lkflags != 0)  			vn_lock(*vpp, lkflags | LK_RETRY); @@ -484,7 +484,7 @@ unionfs_noderem(struct vnode *vp)  	lvp = unp->un_lowervp;  	uvp = unp->un_uppervp;  	dvp = unp->un_dvp; -	unlock_lvp = (uvp == NULLVP); +	unlock_lvp = (uvp == NULL);  	/*  	 * Lock the lower vnode in addition to the upper vnode lock in order @@ -496,7 +496,7 @@ unionfs_noderem(struct vnode *vp)  	 * Moreover, during unmount of a non-"below" unionfs mount, the lower  	 * root vnode will already be locked as it is the covered vnode.  	 */ -	if (uvp != NULLVP && lvp != NULLVP && (vp->v_vflag & VV_ROOT) == 0) { +	if (uvp != NULL && lvp != NULL && (vp->v_vflag & VV_ROOT) == 0) {  		vn_lock_pair(uvp, true, LK_EXCLUSIVE, lvp, false, LK_EXCLUSIVE);  		unlock_lvp = true;  	} @@ -508,7 +508,7 @@ unionfs_noderem(struct vnode *vp)  	 * prevent faults in unionfs_lock().  	 */  	VI_LOCK(vp); -	unp->un_lowervp = unp->un_uppervp = NULLVP; +	unp->un_lowervp = unp->un_uppervp = NULL;  	vp->v_vnlock = &(vp->v_lock);  	vp->v_data = NULL;  	vp->v_object = NULL; @@ -543,14 +543,14 @@ unionfs_noderem(struct vnode *vp)  		    ("%s: write reference without upper vnode", __func__));  		VOP_ADD_WRITECOUNT(uvp, -writerefs);  	} -	if (uvp != NULLVP) +	if (uvp != NULL)  		vput(uvp);  	if (unlock_lvp)  		vput(lvp); -	else if (lvp != NULLVP) +	else if (lvp != NULL)  		vrele(lvp); -	if (dvp != NULLVP) +	if (dvp != NULL)  		unionfs_rem_cached_vnode(unp, dvp);  	if (unp->un_path != NULL) { @@ -567,7 +567,7 @@ unionfs_noderem(struct vnode *vp)  		LIST_REMOVE(unsp, uns_list);  		free(unsp, M_TEMP);  	} -	if (dvp != NULLVP) { +	if (dvp != NULL) {  		mtx_lock(&unionfs_deferred_rele_lock);  		STAILQ_INSERT_TAIL(&unionfs_deferred_rele_list, unp, un_rele);  		mtx_unlock(&unionfs_deferred_rele_lock); @@ -587,6 +587,7 @@ unionfs_find_node_status(struct unionfs_node *unp, struct thread *td)  	struct unionfs_node_status *unsp;  	pid_t pid; +	MPASS(td != NULL);  	pid = td->td_proc->p_pid;  	ASSERT_VOP_ELOCKED(UNIONFSTOV(unp), __func__); @@ -612,6 +613,7 @@ unionfs_get_node_status(struct unionfs_node *unp, struct thread *td,  	struct unionfs_node_status *unsp;  	pid_t pid; +	MPASS(td != NULL);  	pid = td->td_proc->p_pid;  	KASSERT(NULL != unspp, ("%s: NULL status", __func__)); @@ -793,7 +795,7 @@ unionfs_node_update(struct unionfs_node *unp, struct vnode *uvp,  	/*  	 * Re-cache the unionfs vnode against the upper vnode  	 */ -	if (dvp != NULLVP && vp->v_type == VDIR) { +	if (dvp != NULL && vp->v_type == VDIR) {  		VI_LOCK(dvp);  		if (unp->un_hash.le_prev != NULL) {  			LIST_REMOVE(unp, un_hash); @@ -841,7 +843,7 @@ unionfs_set_in_progress_flag(struct vnode *vp, unsigned int flag)  			if (unp == NULL)  				error = ENOENT;  			else if (flag == UNIONFS_COPY_IN_PROGRESS && -			    unp->un_uppervp != NULLVP) +			    unp->un_uppervp != NULL)  				error = EJUSTRETURN;  			else if (flag == UNIONFS_LOOKUP_IN_PROGRESS)  				error = ERELOOKUP; @@ -902,7 +904,7 @@ unionfs_mkshadowdir(struct vnode *dvp, struct vnode *vp,  	ASSERT_VOP_ELOCKED(vp, __func__);  	ump = MOUNTTOUNIONFSMOUNT(vp->v_mount);  	unp = VTOUNIONFS(vp); -	if (unp->un_uppervp != NULLVP) +	if (unp->un_uppervp != NULL)  		return (EEXIST);  	dunp = VTOUNIONFS(dvp);  	udvp = dunp->un_uppervp; @@ -914,7 +916,7 @@ unionfs_mkshadowdir(struct vnode *dvp, struct vnode *vp,  		return (error);  	lvp = unp->un_lowervp; -	uvp = NULLVP; +	uvp = NULL;  	credbk = cnp->cn_cred;  	/* Authority change to root */ @@ -953,7 +955,7 @@ unionfs_mkshadowdir(struct vnode *dvp, struct vnode *vp,  		vput(udvp);  		goto unionfs_mkshadowdir_relock;  	} -	if (uvp != NULLVP) { +	if (uvp != NULL) {  		if (udvp == uvp)  			vrele(uvp);  		else @@ -1218,7 +1220,7 @@ unionfs_mkwhiteout(struct vnode *dvp, struct vnode *vp,  	ASSERT_VOP_ELOCKED(vp, __func__);  	udvp = VTOUNIONFS(dvp)->un_uppervp; -	wvp = NULLVP; +	wvp = NULL;  	NDPREINIT(&nd);  	vref(udvp);  	VOP_UNLOCK(vp); @@ -1226,7 +1228,7 @@ unionfs_mkwhiteout(struct vnode *dvp, struct vnode *vp,  	    pathlen, CREATE))) {  		goto unionfs_mkwhiteout_cleanup;  	} -	if (wvp != NULLVP) { +	if (wvp != NULL) {  		if (udvp == wvp)  			vrele(wvp);  		else @@ -1281,7 +1283,7 @@ unionfs_vn_create_on_upper(struct vnode **vpp, struct vnode *udvp,  	ASSERT_VOP_ELOCKED(vp, __func__);  	unp = VTOUNIONFS(vp);  	ump = MOUNTTOUNIONFSMOUNT(UNIONFSTOV(unp)->v_mount); -	uvp = NULLVP; +	uvp = NULL;  	lvp = unp->un_lowervp;  	cred = td->td_ucred;  	fmode = FFLAGS(O_WRONLY | O_CREAT | O_TRUNC | O_EXCL); @@ -1310,7 +1312,7 @@ unionfs_vn_create_on_upper(struct vnode **vpp, struct vnode *udvp,  		return (error);  	} -	if (uvp != NULLVP) { +	if (uvp != NULL) {  		if (uvp == udvp)  			vrele(uvp);  		else @@ -1433,23 +1435,23 @@ unionfs_copyfile(struct vnode *vp, int docopy, struct ucred *cred,  	ASSERT_VOP_ELOCKED(vp, __func__);  	unp = VTOUNIONFS(vp);  	lvp = unp->un_lowervp; -	uvp = NULLVP; +	uvp = NULL;  	if ((UNIONFSTOV(unp)->v_mount->mnt_flag & MNT_RDONLY))  		return (EROFS); -	if (unp->un_dvp == NULLVP) +	if (unp->un_dvp == NULL)  		return (EINVAL); -	if (unp->un_uppervp != NULLVP) +	if (unp->un_uppervp != NULL)  		return (EEXIST); -	udvp = NULLVP; +	udvp = NULL;  	VI_LOCK(unp->un_dvp);  	dunp = VTOUNIONFS(unp->un_dvp);  	if (dunp != NULL)  		udvp = dunp->un_uppervp;  	VI_UNLOCK(unp->un_dvp); -	if (udvp == NULLVP) +	if (udvp == NULL)  		return (EROFS);  	if ((udvp->v_mount->mnt_flag & MNT_RDONLY))  		return (EROFS); @@ -1646,7 +1648,7 @@ unionfs_check_rmdir(struct vnode *vp, struct ucred *cred, struct thread *td)  		cn.cn_cred = cred;  		error = VOP_LOOKUP(uvp, &tvp, &cn); -		if (tvp != NULLVP) +		if (tvp != NULL)  			vput(tvp);  		if (error != 0 && error != ENOENT && error != EJUSTRETURN)  			break; diff --git a/sys/fs/unionfs/union_vfsops.c b/sys/fs/unionfs/union_vfsops.c index 9342317ad08e..284b24a604f4 100644 --- a/sys/fs/unionfs/union_vfsops.c +++ b/sys/fs/unionfs/union_vfsops.c @@ -256,7 +256,7 @@ unionfs_domount(struct mount *mp)  		ump->um_lowervp = lowerrootvp;  		ump->um_uppervp = upperrootvp;  	} -	ump->um_rootvp = NULLVP; +	ump->um_rootvp = NULL;  	ump->um_uid = uid;  	ump->um_gid = gid;  	ump->um_udir = udir; @@ -280,7 +280,7 @@ unionfs_domount(struct mount *mp)  	 * Get the unionfs root vnode.  	 */  	error = unionfs_nodeget(mp, ump->um_uppervp, ump->um_lowervp, -	    NULLVP, &(ump->um_rootvp), NULL); +	    NULL, &(ump->um_rootvp), NULL);  	if (error != 0) {  		vrele(upperrootvp);  		free(ump, M_UNIONFSMNT); @@ -558,7 +558,7 @@ unionfs_extattrctl(struct mount *mp, int cmd, struct vnode *filename_vp,  	ump = MOUNTTOUNIONFSMOUNT(mp);  	unp = VTOUNIONFS(filename_vp); -	if (unp->un_uppervp != NULLVP) { +	if (unp->un_uppervp != NULL) {  		return (VFS_EXTATTRCTL(ump->um_uppermp, cmd,  		    unp->un_uppervp, namespace, attrname));  	} else { diff --git a/sys/fs/unionfs/union_vnops.c b/sys/fs/unionfs/union_vnops.c index 03130f0ca949..66fee97a07d5 100644 --- a/sys/fs/unionfs/union_vnops.c +++ b/sys/fs/unionfs/union_vnops.c @@ -114,9 +114,9 @@ unionfs_lookup(struct vop_cachedlookup_args *ap)  	dunp = VTOUNIONFS(dvp);  	udvp = dunp->un_uppervp;  	ldvp = dunp->un_lowervp; -	vp = uvp = lvp = NULLVP; +	vp = uvp = lvp = NULL;  	td = curthread; -	*(ap->a_vpp) = NULLVP; +	*(ap->a_vpp) = NULL;  	UNIONFS_INTERNAL_DEBUG(  	    "unionfs_lookup: enter: nameiop=%ld, flags=%lx, path=%s\n", @@ -159,7 +159,7 @@ unionfs_lookup(struct vop_cachedlookup_args *ap)  	 * lookup dotdot  	 */  	if (cnflags & ISDOTDOT) { -		if (LOOKUP != nameiop && udvp == NULLVP) { +		if (LOOKUP != nameiop && udvp == NULL) {  			error = EROFS;  			goto unionfs_lookup_return;  		} @@ -170,7 +170,7 @@ unionfs_lookup(struct vop_cachedlookup_args *ap)  			goto unionfs_lookup_return;  		} -		if (udvp != NULLVP) +		if (udvp != NULL)  			dtmpvp = udvp;  		else  			dtmpvp = ldvp; @@ -186,7 +186,7 @@ unionfs_lookup(struct vop_cachedlookup_args *ap)  		 * reference, or (if dvp was reclaimed) we'll need to drop  		 * vp's lock and reference to return early.  		 */ -		if (vp != NULLVP) +		if (vp != NULL)  			vput(vp);  		dunp = VTOUNIONFS(dvp);  		if (error == 0 && dunp == NULL) @@ -202,7 +202,7 @@ unionfs_lookup(struct vop_cachedlookup_args *ap)  			if (VN_IS_DOOMED(dtmpvp)) {  				vput(dtmpvp); -				*(ap->a_vpp) = NULLVP; +				*(ap->a_vpp) = NULL;  				error = ENOENT;  			}  			vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY); @@ -219,11 +219,11 @@ unionfs_lookup(struct vop_cachedlookup_args *ap)  	 * The cost of this is that we may end up performing an unnecessary  	 * lower layer lookup if a whiteout is present in the upper layer.  	 */ -	if (ldvp != NULLVP && !(cnflags & DOWHITEOUT)) { +	if (ldvp != NULL && !(cnflags & DOWHITEOUT)) {  		struct componentname lcn;  		bool is_dot; -		if (udvp != NULLVP) { +		if (udvp != NULL) {  			vref(ldvp);  			VOP_UNLOCK(dvp);  			vn_lock(ldvp, LK_EXCLUSIVE | LK_RETRY); @@ -235,18 +235,18 @@ unionfs_lookup(struct vop_cachedlookup_args *ap)  		lcn.cn_flags = cnflags;  		is_dot = false; -		if (udvp == NULLVP) +		if (udvp == NULL)  			unionfs_forward_vop_start(ldvp, &lkflags);  		lerror = VOP_LOOKUP(ldvp, &lvp, &lcn); -		if (udvp == NULLVP && +		if (udvp == NULL &&  		    unionfs_forward_vop_finish(dvp, ldvp, lkflags)) { -			if (lvp != NULLVP) +			if (lvp != NULL)  				VOP_UNLOCK(lvp);  			error =  ENOENT;  			goto unionfs_lookup_cleanup;  		} -		if (udvp == NULLVP) +		if (udvp == NULL)  			cnp->cn_flags = lcn.cn_flags;  		if (lerror == 0) { @@ -256,11 +256,11 @@ unionfs_lookup(struct vop_cachedlookup_args *ap)  				vref(dvp);  				is_dot = true;  				error = lerror; -			} else if (lvp != NULLVP) +			} else if (lvp != NULL)  				VOP_UNLOCK(lvp);  		} -		if (udvp != NULLVP) { +		if (udvp != NULL) {  			vput(ldvp);  			vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY);  			if (VN_IS_DOOMED(dvp)) @@ -274,13 +274,13 @@ unionfs_lookup(struct vop_cachedlookup_args *ap)  	/*  	 * lookup upper layer  	 */ -	if (udvp != NULLVP) { +	if (udvp != NULL) {  		bool iswhiteout = false;  		unionfs_forward_vop_start(udvp, &lkflags);  		uerror = VOP_LOOKUP(udvp, &uvp, cnp);  		if (unionfs_forward_vop_finish(dvp, udvp, lkflags)) { -			if (uvp != NULLVP) +			if (uvp != NULL)  				VOP_UNLOCK(uvp);  			error = ENOENT;  			goto unionfs_lookup_cleanup; @@ -288,7 +288,7 @@ unionfs_lookup(struct vop_cachedlookup_args *ap)  		if (uerror == 0) {  			if (udvp == uvp) {	/* is dot */ -				if (lvp != NULLVP) +				if (lvp != NULL)  					vrele(lvp);  				vrele(uvp);  				*(ap->a_vpp) = dvp; @@ -296,7 +296,7 @@ unionfs_lookup(struct vop_cachedlookup_args *ap)  				error = uerror;  				goto unionfs_lookup_return; -			} else if (uvp != NULLVP) +			} else if (uvp != NULL)  				VOP_UNLOCK(uvp);  		} @@ -308,9 +308,9 @@ unionfs_lookup(struct vop_cachedlookup_args *ap)  		    (va.va_flags & OPAQUE))  			iswhiteout = true; -		if (iswhiteout && lvp != NULLVP) { +		if (iswhiteout && lvp != NULL) {  			vrele(lvp); -			lvp = NULLVP; +			lvp = NULL;  		}  #if 0 @@ -323,29 +323,29 @@ unionfs_lookup(struct vop_cachedlookup_args *ap)  	/*  	 * check lookup result  	 */ -	if (uvp == NULLVP && lvp == NULLVP) { -		error = (udvp != NULLVP ? uerror : lerror); +	if (uvp == NULL && lvp == NULL) { +		error = (udvp != NULL ? uerror : lerror);  		goto unionfs_lookup_return;  	}  	/*  	 * check vnode type  	 */ -	if (uvp != NULLVP && lvp != NULLVP && uvp->v_type != lvp->v_type) { +	if (uvp != NULL && lvp != NULL && uvp->v_type != lvp->v_type) {  		vrele(lvp); -		lvp = NULLVP; +		lvp = NULL;  	}  	/*  	 * check shadow dir  	 */ -	if (uerror != 0 && uerror != EJUSTRETURN && udvp != NULLVP && -	    lerror == 0 && lvp != NULLVP && lvp->v_type == VDIR && +	if (uerror != 0 && uerror != EJUSTRETURN && udvp != NULL && +	    lerror == 0 && lvp != NULL && lvp->v_type == VDIR &&  	    !(dvp->v_mount->mnt_flag & MNT_RDONLY) &&  	    (1 < cnp->cn_namelen || '.' != *(cnp->cn_nameptr))) {  		/* get unionfs vnode in order to create a new shadow dir. */ -		error = unionfs_nodeget(dvp->v_mount, NULLVP, lvp, dvp, &vp, -		    cnp); +		error = unionfs_nodeget(dvp->v_mount, NULL, lvp, dvp, &vp, +					cnp);  		if (error != 0)  			goto unionfs_lookup_cleanup; @@ -382,7 +382,7 @@ unionfs_lookup(struct vop_cachedlookup_args *ap)  	 * get unionfs vnode.  	 */  	else { -		if (uvp != NULLVP) +		if (uvp != NULL)  			error = uerror;  		else  			error = lerror; @@ -409,14 +409,14 @@ unionfs_lookup(struct vop_cachedlookup_args *ap)  		cache_enter(dvp, vp, cnp);  unionfs_lookup_cleanup: -	if (uvp != NULLVP) +	if (uvp != NULL)  		vrele(uvp); -	if (lvp != NULLVP) +	if (lvp != NULL)  		vrele(lvp);  	if (error == ENOENT && (cnflags & MAKEENTRY) != 0 &&  	    !VN_IS_DOOMED(dvp)) -		cache_enter(dvp, NULLVP, cnp); +		cache_enter(dvp, NULL, cnp);  unionfs_lookup_return:  	unionfs_clear_in_progress_flag(dvp, UNIONFS_LOOKUP_IN_PROGRESS); @@ -444,7 +444,7 @@ unionfs_create(struct vop_create_args *ap)  	udvp = dunp->un_uppervp;  	error = EROFS; -	if (udvp != NULLVP) { +	if (udvp != NULL) {  		int lkflags;  		bool vp_created = false;  		unionfs_forward_vop_start(udvp, &lkflags); @@ -457,8 +457,8 @@ unionfs_create(struct vop_create_args *ap)  		}  		if (error == 0) {  			VOP_UNLOCK(vp); -			error = unionfs_nodeget(ap->a_dvp->v_mount, vp, NULLVP, -			    ap->a_dvp, ap->a_vpp, cnp); +			error = unionfs_nodeget(ap->a_dvp->v_mount, vp, NULL, +						ap->a_dvp, ap->a_vpp, cnp);  			vrele(vp);  		} else if (vp_created)  			vput(vp); @@ -486,7 +486,7 @@ unionfs_whiteout(struct vop_whiteout_args *ap)  	udvp = dunp->un_uppervp;  	error = EOPNOTSUPP; -	if (udvp != NULLVP) { +	if (udvp != NULL) {  		int lkflags;  		switch (ap->a_flags) {  		case CREATE: @@ -525,7 +525,7 @@ unionfs_mknod(struct vop_mknod_args *ap)  	udvp = dunp->un_uppervp;  	error = EROFS; -	if (udvp != NULLVP) { +	if (udvp != NULL) {  		int lkflags;  		bool vp_created = false;  		unionfs_forward_vop_start(udvp, &lkflags); @@ -538,8 +538,8 @@ unionfs_mknod(struct vop_mknod_args *ap)  		}  		if (error == 0) {  			VOP_UNLOCK(vp); -			error = unionfs_nodeget(ap->a_dvp->v_mount, vp, NULLVP, -			    ap->a_dvp, ap->a_vpp, cnp); +			error = unionfs_nodeget(ap->a_dvp->v_mount, vp, NULL, +						ap->a_dvp, ap->a_vpp, cnp);  			vrele(vp);  		} else if (vp_created)  			vput(vp); @@ -611,7 +611,7 @@ unionfs_lock_lvp(struct vnode *vp, int *lkflags)  	vn_lock(lvp, *lkflags | LK_RETRY);  	if (VN_IS_DOOMED(lvp)) {  		vput(lvp); -		lvp = NULLVP; +		lvp = NULL;  		vn_lock(vp, *lkflags | LK_RETRY);  	}  	return (lvp); @@ -656,7 +656,7 @@ unionfs_open(struct vop_open_args *ap)  	error = 0;  	vp = ap->a_vp; -	targetvp = NULLVP; +	targetvp = NULL;  	cred = ap->a_cred;  	td = ap->a_td;  	open_lvp = lock_lvp = false; @@ -686,10 +686,10 @@ unionfs_open(struct vop_open_args *ap)  		if (targetvp == lvp &&  		    (ap->a_mode & FWRITE) && lvp->v_type == VREG) -			targetvp = NULLVP; +			targetvp = NULL;  	} -	if (targetvp == NULLVP) { -		if (uvp == NULLVP) { +	if (targetvp == NULL) { +		if (uvp == NULL) {  			if ((ap->a_mode & FWRITE) && lvp->v_type == VREG) {  				error = unionfs_copyfile(vp,  				    !(ap->a_mode & O_TRUNC), cred, td); @@ -704,16 +704,16 @@ unionfs_open(struct vop_open_args *ap)  			targetvp = uvp;  	} -	if (targetvp == uvp && uvp->v_type == VDIR && lvp != NULLVP && +	if (targetvp == uvp && uvp->v_type == VDIR && lvp != NULL &&  	    unsp->uns_lower_opencnt <= 0)  		open_lvp = true; -	else if (targetvp == lvp && uvp != NULLVP) +	else if (targetvp == lvp && uvp != NULL)  		lock_lvp = true;  	if (lock_lvp) {  		unp = NULL;  		lvp = unionfs_lock_lvp(vp, &lkflags); -		if (lvp == NULLVP) { +		if (lvp == NULL) {  			error = ENOENT;  			goto unionfs_open_abort;  		} @@ -736,7 +736,7 @@ unionfs_open(struct vop_open_args *ap)  		if (open_lvp) {  			unp = NULL;  			lvp = unionfs_lock_lvp(vp, &lkflags); -			if (lvp == NULLVP) { +			if (lvp == NULL) {  				error = ENOENT;  				goto unionfs_open_abort;  			} @@ -814,7 +814,7 @@ unionfs_close(struct vop_close_args *ap)  	unp = VTOUNIONFS(vp);  	lvp = unp->un_lowervp;  	uvp = unp->un_uppervp; -	unsp = unionfs_find_node_status(unp, td); +	unsp = (td != NULL) ? unionfs_find_node_status(unp, td) : NULL;  	if (unsp == NULL ||  	    (unsp->uns_lower_opencnt <= 0 && unsp->uns_upper_opencnt <= 0)) { @@ -822,7 +822,7 @@ unionfs_close(struct vop_close_args *ap)  		if (unsp != NULL)  			printf("unionfs_close: warning: open count is 0\n");  #endif -		if (uvp != NULLVP) +		if (uvp != NULL)  			ovp = uvp;  		else  			ovp = lvp; @@ -831,11 +831,11 @@ unionfs_close(struct vop_close_args *ap)  	else  		ovp = lvp; -	if (ovp == lvp && uvp != NULLVP) { +	if (ovp == lvp && uvp != NULL) {  		lock_lvp = true;  		unp = NULL;  		lvp = unionfs_lock_lvp(vp, &lkflags); -		if (lvp == NULLVP) { +		if (lvp == NULL) {  			error = ENOENT;  			goto unionfs_close_abort;  		} @@ -861,7 +861,7 @@ unionfs_close(struct vop_close_args *ap)  			if (unsp->uns_node_flag & UNS_OPENL_4_READDIR) {  				unp = NULL;  				lvp = unionfs_lock_lvp(vp, &lkflags); -				if (lvp == NULLVP) { +				if (lvp == NULL) {  					error = ENOENT;  					goto unionfs_close_abort;  				} @@ -978,7 +978,7 @@ unionfs_access(struct vop_access_args *ap)  		}  	} -	if (uvp != NULLVP) { +	if (uvp != NULL) {  		error = VOP_ACCESS(uvp, accmode, ap->a_cred, td);  		UNIONFS_INTERNAL_DEBUG("unionfs_access: leave (%d)\n", error); @@ -986,7 +986,7 @@ unionfs_access(struct vop_access_args *ap)  		return (error);  	} -	if (lvp != NULLVP) { +	if (lvp != NULL) {  		if (accmode & VWRITE) {  			if ((ump->um_uppermp->mnt_flag & MNT_RDONLY) != 0) {  				switch (ap->a_vp->v_type) { @@ -1044,7 +1044,7 @@ unionfs_getattr(struct vop_getattr_args *ap)  	lvp = unp->un_lowervp;  	td = curthread; -	if (uvp != NULLVP) { +	if (uvp != NULL) {  		if ((error = VOP_GETATTR(uvp, ap->a_vap, ap->a_cred)) == 0)  			ap->a_vap->va_fsid =  			    ap->a_vp->v_mount->mnt_stat.f_fsid.val[0]; @@ -1106,7 +1106,7 @@ unionfs_setattr(struct vop_setattr_args *ap)  	     vap->va_mtime.tv_sec != VNOVAL || vap->va_mode != (mode_t)VNOVAL))  		return (EROFS); -	if (uvp == NULLVP && lvp->v_type == VREG) { +	if (uvp == NULL && lvp->v_type == VREG) {  		error = unionfs_copyfile(ap->a_vp, (vap->va_size != 0),  		    ap->a_cred, td);  		if (error != 0) @@ -1114,7 +1114,7 @@ unionfs_setattr(struct vop_setattr_args *ap)  		uvp = unp->un_uppervp;  	} -	if (uvp != NULLVP) { +	if (uvp != NULL) {  		int lkflags;  		unionfs_forward_vop_start(uvp, &lkflags);  		error = VOP_SETATTR(uvp, vap, ap->a_cred); @@ -1138,7 +1138,7 @@ unionfs_read(struct vop_read_args *ap)  	KASSERT_UNIONFS_VNODE(ap->a_vp);  	unp = VTOUNIONFS(ap->a_vp); -	tvp = (unp->un_uppervp != NULLVP ? unp->un_uppervp : unp->un_lowervp); +	tvp = (unp->un_uppervp != NULL ? unp->un_uppervp : unp->un_lowervp);  	error = VOP_READ(tvp, ap->a_uio, ap->a_ioflag, ap->a_cred); @@ -1160,7 +1160,7 @@ unionfs_write(struct vop_write_args *ap)  	KASSERT_UNIONFS_VNODE(ap->a_vp);  	unp = VTOUNIONFS(ap->a_vp); -	tvp = (unp->un_uppervp != NULLVP ? unp->un_uppervp : unp->un_lowervp); +	tvp = (unp->un_uppervp != NULL ? unp->un_uppervp : unp->un_lowervp);  	unionfs_forward_vop_start(tvp, &lkflags);  	error = VOP_WRITE(tvp, ap->a_uio, ap->a_ioflag, ap->a_cred); @@ -1190,7 +1190,7 @@ unionfs_ioctl(struct vop_ioctl_args *ap)  	unionfs_tryrem_node_status(unp, unsp);  	VOP_UNLOCK(ap->a_vp); -	if (ovp == NULLVP) +	if (ovp == NULL)  		return (EBADF);  	error = VOP_IOCTL(ovp, ap->a_command, ap->a_data, ap->a_fflag, @@ -1217,7 +1217,7 @@ unionfs_poll(struct vop_poll_args *ap)  	unionfs_tryrem_node_status(unp, unsp);  	VOP_UNLOCK(ap->a_vp); -	if (ovp == NULLVP) +	if (ovp == NULL)  		return (EBADF);  	return (VOP_POLL(ovp, ap->a_events, ap->a_cred, ap->a_td)); @@ -1246,7 +1246,7 @@ unionfs_fsync(struct vop_fsync_args *ap)  	unionfs_downgrade_lock(ap->a_vp, lkstatus); -	if (ovp == NULLVP) +	if (ovp == NULL)  		return (EBADF);  	unionfs_forward_vop_start(ovp, &lkflags); @@ -1289,20 +1289,20 @@ unionfs_remove(struct vop_remove_args *ap)  	path = unp->un_path;  	pathlen = unp->un_pathlen; -	if (udvp == NULLVP) +	if (udvp == NULL)  		return (EROFS); -	if (uvp != NULLVP) { +	if (uvp != NULL) {  		int udvp_lkflags, uvp_lkflags;  		if (ump == NULL || ump->um_whitemode == UNIONFS_WHITE_ALWAYS || -		    lvp != NULLVP) +		    lvp != NULL)  			cnp->cn_flags |= DOWHITEOUT;  		unionfs_forward_vop_start_pair(udvp, &udvp_lkflags,  		    uvp, &uvp_lkflags);  		error = VOP_REMOVE(udvp, uvp, cnp);  		unionfs_forward_vop_finish_pair(ap->a_dvp, udvp, udvp_lkflags,  		    ap->a_vp, uvp, uvp_lkflags); -	} else if (lvp != NULLVP) { +	} else if (lvp != NULL) {  		error = unionfs_mkwhiteout(ap->a_dvp, ap->a_vp, cnp, td,  		    path, pathlen);  	} @@ -1332,16 +1332,16 @@ unionfs_link(struct vop_link_args *ap)  	dunp = VTOUNIONFS(ap->a_tdvp);  	unp = NULL;  	udvp = dunp->un_uppervp; -	uvp = NULLVP; +	uvp = NULL;  	cnp = ap->a_cnp;  	td = curthread; -	if (udvp == NULLVP) +	if (udvp == NULL)  		return (EROFS);  	unp = VTOUNIONFS(ap->a_vp); -	if (unp->un_uppervp == NULLVP) { +	if (unp->un_uppervp == NULL) {  		if (ap->a_vp->v_type != VREG)  			return (EOPNOTSUPP); @@ -1405,7 +1405,7 @@ unionfs_rename(struct vop_rename_args *ap)  	/* check for cross device rename */  	if (fvp->v_mount != tdvp->v_mount || -	    (tvp != NULLVP && fvp->v_mount != tvp->v_mount)) { +	    (tvp != NULL && fvp->v_mount != tvp->v_mount)) {  		if (fvp->v_op != &unionfs_vnodeops)  			error = ENODEV;  		else @@ -1418,7 +1418,7 @@ unionfs_rename(struct vop_rename_args *ap)  		goto unionfs_rename_abort;  	KASSERT_UNIONFS_VNODE(tdvp); -	if (tvp != NULLVP) +	if (tvp != NULL)  		KASSERT_UNIONFS_VNODE(tvp);  	if (fdvp != tdvp)  		VI_LOCK(fdvp); @@ -1433,7 +1433,7 @@ unionfs_rename(struct vop_rename_args *ap)  	UNIONFS_INTERNAL_DEBUG("fdvp=%p, ufdvp=%p, lfdvp=%p\n",  	    fdvp, unp->un_uppervp, unp->un_lowervp);  #endif -	if (unp->un_uppervp == NULLVP) { +	if (unp->un_uppervp == NULL) {  		error = ENODEV;  	} else {  		rfdvp = unp->un_uppervp; @@ -1460,10 +1460,10 @@ unionfs_rename(struct vop_rename_args *ap)  	 * If we only have a lower vnode, copy the source file to the upper  	 * FS so that the rename operation can be issued against the upper FS.  	 */ -	if (unp->un_uppervp == NULLVP) { +	if (unp->un_uppervp == NULL) {  		bool unlock_fdvp = false, relock_tdvp = false;  		VI_UNLOCK(fvp); -		if (tvp != NULLVP) +		if (tvp != NULL)  			VOP_UNLOCK(tvp);  		if (fvp->v_type == VREG) {  			/* @@ -1496,7 +1496,7 @@ unionfs_rename(struct vop_rename_args *ap)  		unp = VTOUNIONFS(fvp);  		if (unp == NULL)  			error = ENOENT; -		else if (unp->un_uppervp == NULLVP) { +		else if (unp->un_uppervp == NULL) {  			switch (fvp->v_type) {  			case VREG:  				error = unionfs_copyfile(fvp, 1, fcnp->cn_cred, td); @@ -1514,7 +1514,7 @@ unionfs_rename(struct vop_rename_args *ap)  			VOP_UNLOCK(fdvp);  		if (relock_tdvp)  			vn_lock(tdvp, LK_EXCLUSIVE | LK_RETRY); -		if (tvp != NULLVP) +		if (tvp != NULL)  			vn_lock(tvp, LK_EXCLUSIVE | LK_RETRY);  		/*  		 * Since we've dropped tdvp's lock at some point in the copy @@ -1526,7 +1526,7 @@ unionfs_rename(struct vop_rename_args *ap)  		goto unionfs_rename_abort;  	} -	if (unp->un_lowervp != NULLVP) +	if (unp->un_lowervp != NULL)  		fcnp->cn_flags |= DOWHITEOUT;  	rfvp = unp->un_uppervp;  	vref(rfvp); @@ -1539,14 +1539,14 @@ unionfs_rename(struct vop_rename_args *ap)  	UNIONFS_INTERNAL_DEBUG("tdvp=%p, utdvp=%p, ltdvp=%p\n",  	    tdvp, unp->un_uppervp, unp->un_lowervp);  #endif -	if (unp->un_uppervp == NULLVP) { +	if (unp->un_uppervp == NULL) {  		error = ENODEV;  		goto unionfs_rename_abort;  	}  	rtdvp = unp->un_uppervp;  	vref(rtdvp); -	if (tvp != NULLVP) { +	if (tvp != NULL) {  		unp = VTOUNIONFS(tvp);  		if (unp == NULL) {  			error = ENOENT; @@ -1556,8 +1556,8 @@ unionfs_rename(struct vop_rename_args *ap)  		UNIONFS_INTERNAL_DEBUG("tvp=%p, utvp=%p, ltvp=%p\n",  		    tvp, unp->un_uppervp, unp->un_lowervp);  #endif -		if (unp->un_uppervp == NULLVP) -			rtvp = NULLVP; +		if (unp->un_uppervp == NULL) +			rtvp = NULL;  		else {  			if (tvp->v_type == VDIR) {  				error = EINVAL; @@ -1574,7 +1574,7 @@ unionfs_rename(struct vop_rename_args *ap)  	error = VOP_RENAME(rfdvp, rfvp, fcnp, rtdvp, rtvp, tcnp);  	if (error == 0) { -		if (rtvp != NULLVP && rtvp->v_type == VDIR) +		if (rtvp != NULL && rtvp->v_type == VDIR)  			cache_purge(tdvp);  		if (fvp->v_type == VDIR && fdvp != tdvp)  			cache_purge(fdvp); @@ -1582,8 +1582,8 @@ unionfs_rename(struct vop_rename_args *ap)  	if (tdvp != rtdvp)  		vrele(tdvp); -	if (tvp != rtvp && tvp != NULLVP) { -		if (rtvp == NULLVP) +	if (tvp != rtvp && tvp != NULL) { +		if (rtvp == NULL)  			vput(tvp);  		else  			vrele(tvp); @@ -1601,13 +1601,13 @@ unionfs_rename_abort:  	vput(tdvp);  	if (tdvp != rtdvp)  		vrele(rtdvp); -	if (tvp != NULLVP) { +	if (tvp != NULL) {  		if (tdvp != tvp)  			vput(tvp);  		else  			vrele(tvp);  	} -	if (tvp != rtvp && rtvp != NULLVP) +	if (tvp != rtvp && rtvp != NULL)  		vrele(rtvp);  	if (fdvp != rfdvp)  		vrele(rfdvp); @@ -1644,7 +1644,7 @@ unionfs_mkdir(struct vop_mkdir_args *ap)  	lkflags = cnp->cn_lkflags;  	udvp = dunp->un_uppervp; -	if (udvp != NULLVP) { +	if (udvp != NULL) {  		/* check opaque */  		if (!(cnp->cn_flags & ISWHITEOUT)) {  			error = VOP_GETATTR(udvp, &va, cnp->cn_cred); @@ -1666,8 +1666,8 @@ unionfs_mkdir(struct vop_mkdir_args *ap)  		if (error == 0) {  			VOP_UNLOCK(uvp);  			cnp->cn_lkflags = LK_EXCLUSIVE; -			error = unionfs_nodeget(dvp->v_mount, uvp, NULLVP, -			    dvp, ap->a_vpp, cnp); +			error = unionfs_nodeget(dvp->v_mount, uvp, NULL, +						dvp, ap->a_vpp, cnp);  			vrele(uvp);  			cnp->cn_lkflags = lkflags;  		} else if (uvp_created) @@ -1707,14 +1707,14 @@ unionfs_rmdir(struct vop_rmdir_args *ap)  	uvp = unp->un_uppervp;  	lvp = unp->un_lowervp; -	if (udvp == NULLVP) +	if (udvp == NULL)  		return (EROFS);  	if (udvp == uvp)  		return (EOPNOTSUPP); -	if (uvp != NULLVP) { -		if (lvp != NULLVP) { +	if (uvp != NULL) { +		if (lvp != NULL) {  			/*  			 * We need to keep dvp and vp's upper vnodes locked  			 * going into the VOP_RMDIR() call, but the empty @@ -1752,7 +1752,7 @@ unionfs_rmdir(struct vop_rmdir_args *ap)  				return (error);  		}  		ump = MOUNTTOUNIONFSMOUNT(ap->a_vp->v_mount); -		if (ump->um_whitemode == UNIONFS_WHITE_ALWAYS || lvp != NULLVP) +		if (ump->um_whitemode == UNIONFS_WHITE_ALWAYS || lvp != NULL)  			cnp->cn_flags |= (DOWHITEOUT | IGNOREWHITEOUT);  		int udvp_lkflags, uvp_lkflags;  		unionfs_forward_vop_start_pair(udvp, &udvp_lkflags, @@ -1760,7 +1760,7 @@ unionfs_rmdir(struct vop_rmdir_args *ap)  		error = VOP_RMDIR(udvp, uvp, cnp);  		unionfs_forward_vop_finish_pair(ap->a_dvp, udvp, udvp_lkflags,  		    ap->a_vp, uvp, uvp_lkflags); -	} else if (lvp != NULLVP) { +	} else if (lvp != NULL) {  		error = unionfs_mkwhiteout(ap->a_dvp, ap->a_vp, cnp, td,  		    unp->un_path, unp->un_pathlen);  	} @@ -1795,7 +1795,7 @@ unionfs_symlink(struct vop_symlink_args *ap)  	lkflags = cnp->cn_lkflags;  	udvp = dunp->un_uppervp; -	if (udvp != NULLVP) { +	if (udvp != NULL) {  		int udvp_lkflags;  		bool uvp_created = false;  		unionfs_forward_vop_start(udvp, &udvp_lkflags); @@ -1808,8 +1808,8 @@ unionfs_symlink(struct vop_symlink_args *ap)  		if (error == 0) {  			VOP_UNLOCK(uvp);  			cnp->cn_lkflags = LK_EXCLUSIVE; -			error = unionfs_nodeget(ap->a_dvp->v_mount, uvp, NULLVP, -			    ap->a_dvp, ap->a_vpp, cnp); +			error = unionfs_nodeget(ap->a_dvp->v_mount, uvp, NULL, +						ap->a_dvp, ap->a_vpp, cnp);  			vrele(uvp);  			cnp->cn_lkflags = lkflags;  		} else if (uvp_created) @@ -1849,8 +1849,8 @@ unionfs_readdir(struct vop_readdir_args *ap)  	eofflag = 0;  	uio_offset_bk = 0;  	uio = ap->a_uio; -	uvp = NULLVP; -	lvp = NULLVP; +	uvp = NULL; +	lvp = NULL;  	td = uio->uio_td;  	ncookies_bk = 0;  	cookies_bk = NULL; @@ -1872,8 +1872,8 @@ unionfs_readdir(struct vop_readdir_args *ap)  		lvp = unp->un_lowervp;  		/* check the open count. unionfs needs open before readdir. */  		unionfs_get_node_status(unp, td, &unsp); -		if ((uvp != NULLVP && unsp->uns_upper_opencnt <= 0) || -			(lvp != NULLVP && unsp->uns_lower_opencnt <= 0)) { +		if ((uvp != NULL && unsp->uns_upper_opencnt <= 0) || +			(lvp != NULL && unsp->uns_lower_opencnt <= 0)) {  			unionfs_tryrem_node_status(unp, unsp);  			error = EBADF;  		} @@ -1883,15 +1883,15 @@ unionfs_readdir(struct vop_readdir_args *ap)  		goto unionfs_readdir_exit;  	/* check opaque */ -	if (uvp != NULLVP && lvp != NULLVP) { +	if (uvp != NULL && lvp != NULL) {  		if ((error = VOP_GETATTR(uvp, &va, ap->a_cred)) != 0)  			goto unionfs_readdir_exit;  		if (va.va_flags & OPAQUE) -			lvp = NULLVP; +			lvp = NULL;  	}  	/* upper only */ -	if (uvp != NULLVP && lvp == NULLVP) { +	if (uvp != NULL && lvp == NULL) {  		unionfs_forward_vop_start(uvp, &lkflags);  		error = VOP_READDIR(uvp, uio, ap->a_cred, ap->a_eofflag,  		    ap->a_ncookies, ap->a_cookies); @@ -1904,7 +1904,7 @@ unionfs_readdir(struct vop_readdir_args *ap)  	}  	/* lower only */ -	if (uvp == NULLVP && lvp != NULLVP) { +	if (uvp == NULL && lvp != NULL) {  		unionfs_forward_vop_start(lvp, &lkflags);  		error = VOP_READDIR(lvp, uio, ap->a_cred, ap->a_eofflag,  		    ap->a_ncookies, ap->a_cookies); @@ -1919,8 +1919,8 @@ unionfs_readdir(struct vop_readdir_args *ap)  	/*  	 * readdir upper and lower  	 */ -	KASSERT(uvp != NULLVP, ("unionfs_readdir: null upper vp")); -	KASSERT(lvp != NULLVP, ("unionfs_readdir: null lower vp")); +	KASSERT(uvp != NULL, ("unionfs_readdir: null upper vp")); +	KASSERT(lvp != NULL, ("unionfs_readdir: null lower vp"));  	if (uio->uio_offset == 0)  		unsp->uns_readdir_status = 0; @@ -2040,7 +2040,7 @@ unionfs_readlink(struct vop_readlink_args *ap)  	KASSERT_UNIONFS_VNODE(ap->a_vp);  	unp = VTOUNIONFS(ap->a_vp); -	vp = (unp->un_uppervp != NULLVP ? unp->un_uppervp : unp->un_lowervp); +	vp = (unp->un_uppervp != NULL ? unp->un_uppervp : unp->un_lowervp);  	error = VOP_READLINK(vp, ap->a_uio, ap->a_cred); @@ -2061,7 +2061,7 @@ unionfs_getwritemount(struct vop_getwritemount_args *ap)  	error = 0;  	vp = ap->a_vp; -	uvp = NULLVP; +	uvp = NULL;  	VI_LOCK(vp);  	unp = VTOUNIONFS(vp); @@ -2073,7 +2073,7 @@ unionfs_getwritemount(struct vop_getwritemount_args *ap)  	 * We may be initiating a write operation that will produce a  	 * new upper vnode through CoW.  	 */ -	if (uvp == NULLVP && unp != NULL) { +	if (uvp == NULL && unp != NULL) {  		ovp = vp;  		vp = unp->un_dvp;  		/* @@ -2086,11 +2086,11 @@ unionfs_getwritemount(struct vop_getwritemount_args *ap)  		unp = VTOUNIONFS(vp);  		if (unp != NULL)  			uvp = unp->un_uppervp; -		if (uvp == NULLVP) +		if (uvp == NULL)  			error = EACCES;  	} -	if (uvp != NULLVP) { +	if (uvp != NULL) {  		vholdnz(uvp);  		VI_UNLOCK(vp);  		error = VOP_GETWRITEMOUNT(uvp, ap->a_mpp); @@ -2141,9 +2141,9 @@ unionfs_print(struct vop_print_args *ap)  	    unsp->uns_upper_opencnt, unsp->uns_lower_opencnt);  	*/ -	if (unp->un_uppervp != NULLVP) +	if (unp->un_uppervp != NULL)  		vn_printf(unp->un_uppervp, "unionfs: upper "); -	if (unp->un_lowervp != NULLVP) +	if (unp->un_lowervp != NULL)  		vn_printf(unp->un_lowervp, "unionfs: lower ");  	return (0); @@ -2208,7 +2208,6 @@ unionfs_lock_restart:  	vholdnz(tvp);  	VI_UNLOCK(vp);  	error = VOP_LOCK(tvp, flags); -	vdrop(tvp);  	if (error == 0 && (lvp_locked || VTOUNIONFS(vp) == NULL)) {  		/*  		 * After dropping the interlock above, there exists a window @@ -2232,8 +2231,9 @@ unionfs_lock_restart:  		 * lower vnode lock here.  		 */  		unp = VTOUNIONFS(vp); -		if (unp == NULL || unp->un_uppervp != NULLVP) { +		if (unp == NULL || unp->un_uppervp != NULL) {  			VOP_UNLOCK(tvp); +			vdrop(tvp);  			/*  			 * If we previously held the lock, the upgrade may  			 * have temporarily dropped the lock, in which case @@ -2249,6 +2249,7 @@ unionfs_lock_restart:  			goto unionfs_lock_restart;  		}  	} +	vdrop(tvp);  	return (error);  } @@ -2259,7 +2260,6 @@ unionfs_unlock(struct vop_unlock_args *ap)  	struct vnode   *vp;  	struct vnode   *tvp;  	struct unionfs_node *unp; -	int		error;  	KASSERT_UNIONFS_VNODE(ap->a_vp); @@ -2271,11 +2271,7 @@ unionfs_unlock(struct vop_unlock_args *ap)  	tvp = (unp->un_uppervp != NULL ? unp->un_uppervp : unp->un_lowervp); -	vholdnz(tvp); -	error = VOP_UNLOCK(tvp); -	vdrop(tvp); - -	return (error); +	return (VOP_UNLOCK(tvp));  }  static int @@ -2287,7 +2283,7 @@ unionfs_pathconf(struct vop_pathconf_args *ap)  	KASSERT_UNIONFS_VNODE(ap->a_vp);  	unp = VTOUNIONFS(ap->a_vp); -	vp = (unp->un_uppervp != NULLVP ? unp->un_uppervp : unp->un_lowervp); +	vp = (unp->un_uppervp != NULL ? unp->un_uppervp : unp->un_lowervp);  	return (VOP_PATHCONF(vp, ap->a_name, ap->a_retval));  } @@ -2314,7 +2310,7 @@ unionfs_advlock(struct vop_advlock_args *ap)  	unp = VTOUNIONFS(ap->a_vp);  	uvp = unp->un_uppervp; -	if (uvp == NULLVP) { +	if (uvp == NULL) {  		error = unionfs_copyfile(ap->a_vp, 1, td->td_ucred, td);  		if (error != 0)  			goto unionfs_advlock_abort; @@ -2360,10 +2356,10 @@ unionfs_strategy(struct vop_strategy_args *ap)  	KASSERT_UNIONFS_VNODE(ap->a_vp);  	unp = VTOUNIONFS(ap->a_vp); -	vp = (unp->un_uppervp != NULLVP ? unp->un_uppervp : unp->un_lowervp); +	vp = (unp->un_uppervp != NULL ? unp->un_uppervp : unp->un_lowervp);  #ifdef DIAGNOSTIC -	if (vp == NULLVP) +	if (vp == NULL)  		panic("unionfs_strategy: nullvp");  	if (ap->a_bp->b_iocmd == BIO_WRITE && vp == unp->un_lowervp) @@ -2383,7 +2379,7 @@ unionfs_getacl(struct vop_getacl_args *ap)  	KASSERT_UNIONFS_VNODE(ap->a_vp);  	unp = VTOUNIONFS(ap->a_vp); -	vp = (unp->un_uppervp != NULLVP ? unp->un_uppervp : unp->un_lowervp); +	vp = (unp->un_uppervp != NULL ? unp->un_uppervp : unp->un_lowervp);  	UNIONFS_INTERNAL_DEBUG("unionfs_getacl: enter\n"); @@ -2416,13 +2412,13 @@ unionfs_setacl(struct vop_setacl_args *ap)  	if (ap->a_vp->v_mount->mnt_flag & MNT_RDONLY)  		return (EROFS); -	if (uvp == NULLVP && lvp->v_type == VREG) { +	if (uvp == NULL && lvp->v_type == VREG) {  		if ((error = unionfs_copyfile(ap->a_vp, 1, ap->a_cred, td)) != 0)  			return (error);  		uvp = unp->un_uppervp;  	} -	if (uvp != NULLVP) { +	if (uvp != NULL) {  		int lkflags;  		unionfs_forward_vop_start(uvp, &lkflags);  		error = VOP_SETACL(uvp, ap->a_type, ap->a_aclp, ap->a_cred, td); @@ -2446,7 +2442,7 @@ unionfs_aclcheck(struct vop_aclcheck_args *ap)  	KASSERT_UNIONFS_VNODE(ap->a_vp);  	unp = VTOUNIONFS(ap->a_vp); -	vp = (unp->un_uppervp != NULLVP ? unp->un_uppervp : unp->un_lowervp); +	vp = (unp->un_uppervp != NULL ? unp->un_uppervp : unp->un_lowervp);  	error = VOP_ACLCHECK(vp, ap->a_type, ap->a_aclp, ap->a_cred, ap->a_td); @@ -2467,7 +2463,7 @@ unionfs_openextattr(struct vop_openextattr_args *ap)  	vp = ap->a_vp;  	unp = VTOUNIONFS(vp); -	tvp = (unp->un_uppervp != NULLVP ? unp->un_uppervp : unp->un_lowervp); +	tvp = (unp->un_uppervp != NULL ? unp->un_uppervp : unp->un_lowervp);  	if ((tvp == unp->un_uppervp && (unp->un_flag & UNIONFS_OPENEXTU)) ||  	    (tvp == unp->un_lowervp && (unp->un_flag & UNIONFS_OPENEXTL))) @@ -2502,14 +2498,14 @@ unionfs_closeextattr(struct vop_closeextattr_args *ap)  	vp = ap->a_vp;  	unp = VTOUNIONFS(vp); -	tvp = NULLVP; +	tvp = NULL;  	if (unp->un_flag & UNIONFS_OPENEXTU)  		tvp = unp->un_uppervp;  	else if (unp->un_flag & UNIONFS_OPENEXTL)  		tvp = unp->un_lowervp; -	if (tvp == NULLVP) +	if (tvp == NULL)  		return (EOPNOTSUPP);  	error = VOP_CLOSEEXTATTR(tvp, ap->a_commit, ap->a_cred, ap->a_td); @@ -2538,14 +2534,14 @@ unionfs_getextattr(struct vop_getextattr_args *ap)  	KASSERT_UNIONFS_VNODE(ap->a_vp);  	unp = VTOUNIONFS(ap->a_vp); -	vp = NULLVP; +	vp = NULL;  	if (unp->un_flag & UNIONFS_OPENEXTU)  		vp = unp->un_uppervp;  	else if (unp->un_flag & UNIONFS_OPENEXTL)  		vp = unp->un_lowervp; -	if (vp == NULLVP) +	if (vp == NULL)  		return (EOPNOTSUPP);  	return (VOP_GETEXTATTR(vp, ap->a_attrnamespace, ap->a_name, @@ -2569,7 +2565,7 @@ unionfs_setextattr(struct vop_setextattr_args *ap)  	unp = VTOUNIONFS(ap->a_vp);  	uvp = unp->un_uppervp;  	lvp = unp->un_lowervp; -	ovp = NULLVP; +	ovp = NULL;  	cred = ap->a_cred;  	td = ap->a_td; @@ -2584,12 +2580,12 @@ unionfs_setextattr(struct vop_setextattr_args *ap)  	else if (unp->un_flag & UNIONFS_OPENEXTL)  		ovp = unp->un_lowervp; -	if (ovp == NULLVP) +	if (ovp == NULL)  		return (EOPNOTSUPP);  	if (ovp == lvp && lvp->v_type == VREG) {  		VOP_CLOSEEXTATTR(lvp, 0, cred, td); -		if (uvp == NULLVP && +		if (uvp == NULL &&  		    (error = unionfs_copyfile(ap->a_vp, 1, cred, td)) != 0) {  unionfs_setextattr_reopen:  			unp = VTOUNIONFS(ap->a_vp); @@ -2633,14 +2629,14 @@ unionfs_listextattr(struct vop_listextattr_args *ap)  	KASSERT_UNIONFS_VNODE(ap->a_vp);  	unp = VTOUNIONFS(ap->a_vp); -	vp = NULLVP; +	vp = NULL;  	if (unp->un_flag & UNIONFS_OPENEXTU)  		vp = unp->un_uppervp;  	else if (unp->un_flag & UNIONFS_OPENEXTL)  		vp = unp->un_lowervp; -	if (vp == NULLVP) +	if (vp == NULL)  		return (EOPNOTSUPP);  	return (VOP_LISTEXTATTR(vp, ap->a_attrnamespace, ap->a_uio, @@ -2664,7 +2660,7 @@ unionfs_deleteextattr(struct vop_deleteextattr_args *ap)  	unp = VTOUNIONFS(ap->a_vp);  	uvp = unp->un_uppervp;  	lvp = unp->un_lowervp; -	ovp = NULLVP; +	ovp = NULL;  	cred = ap->a_cred;  	td = ap->a_td; @@ -2679,12 +2675,12 @@ unionfs_deleteextattr(struct vop_deleteextattr_args *ap)  	else if (unp->un_flag & UNIONFS_OPENEXTL)  		ovp = unp->un_lowervp; -	if (ovp == NULLVP) +	if (ovp == NULL)  		return (EOPNOTSUPP);  	if (ovp == lvp && lvp->v_type == VREG) {  		VOP_CLOSEEXTATTR(lvp, 0, cred, td); -		if (uvp == NULLVP && +		if (uvp == NULL &&  		    (error = unionfs_copyfile(ap->a_vp, 1, cred, td)) != 0) {  unionfs_deleteextattr_reopen:  			unp = VTOUNIONFS(ap->a_vp); @@ -2737,13 +2733,13 @@ unionfs_setlabel(struct vop_setlabel_args *ap)  	if (ap->a_vp->v_mount->mnt_flag & MNT_RDONLY)  		return (EROFS); -	if (uvp == NULLVP && lvp->v_type == VREG) { +	if (uvp == NULL && lvp->v_type == VREG) {  		if ((error = unionfs_copyfile(ap->a_vp, 1, ap->a_cred, td)) != 0)  			return (error);  		uvp = unp->un_uppervp;  	} -	if (uvp != NULLVP) +	if (uvp != NULL)  		error = VOP_SETLABEL(uvp, ap->a_label, ap->a_cred, td);  	UNIONFS_INTERNAL_DEBUG("unionfs_setlabel: leave (%d)\n", error); @@ -2796,10 +2792,10 @@ unionfs_vput_pair(struct vop_vput_pair_args *ap)  	dvp = ap->a_dvp;  	vpp = ap->a_vpp; -	vp = NULLVP; -	lvp = NULLVP; -	uvp = NULLVP; -	tvp = NULLVP; +	vp = NULL; +	lvp = NULL; +	uvp = NULL; +	tvp = NULL;  	unp = NULL;  	dunp = VTOUNIONFS(dvp); @@ -2819,11 +2815,11 @@ unionfs_vput_pair(struct vop_vput_pair_args *ap)  	if (vpp != NULL)  		vp = *vpp; -	if (vp != NULLVP) { +	if (vp != NULL) {  		unp = VTOUNIONFS(vp);  		uvp = unp->un_uppervp;  		lvp = unp->un_lowervp; -		if (uvp != NULLVP) +		if (uvp != NULL)  			tvp = uvp;  		else  			tvp = lvp; @@ -2838,9 +2834,9 @@ unionfs_vput_pair(struct vop_vput_pair_args *ap)  		 */  		if (!ap->a_unlock_vp) {  			vhold(vp); -			if (uvp != NULLVP) +			if (uvp != NULL)  				vhold(uvp); -			if (lvp != NULLVP) +			if (lvp != NULL)  				vhold(lvp);  			mp = vp->v_mount;  			vfs_ref(mp); @@ -2850,12 +2846,12 @@ unionfs_vput_pair(struct vop_vput_pair_args *ap)  	ASSERT_VOP_LOCKED(tdvp, __func__);  	ASSERT_VOP_LOCKED(tvp, __func__); -	if (tdvp == dunp->un_uppervp && tvp != NULLVP && tvp == lvp) { +	if (tdvp == dunp->un_uppervp && tvp != NULL && tvp == lvp) {  		vput(tvp);  		vput(tdvp);  		res = 0;  	} else { -		res = VOP_VPUT_PAIR(tdvp, tvp != NULLVP ? &tvp : NULL, true); +		res = VOP_VPUT_PAIR(tdvp, tvp != NULL ? &tvp : NULL, true);  	}  	ASSERT_VOP_UNLOCKED(tdvp, __func__); @@ -2865,11 +2861,11 @@ unionfs_vput_pair(struct vop_vput_pair_args *ap)  	 * VOP_VPUT_PAIR() dropped the references we added to the underlying  	 * vnodes, now drop the caller's reference to the unionfs vnodes.  	 */ -	if (vp != NULLVP && ap->a_unlock_vp) +	if (vp != NULL && ap->a_unlock_vp)  		vrele(vp);  	vrele(dvp); -	if (vp == NULLVP || ap->a_unlock_vp) +	if (vp == NULL || ap->a_unlock_vp)  		return (res);  	/* @@ -2887,9 +2883,9 @@ unionfs_vput_pair(struct vop_vput_pair_args *ap)  			vget(vp, LK_EXCLUSIVE | LK_RETRY);  		vfs_unbusy(mp);  	} -	if (lvp != NULLVP) +	if (lvp != NULL)  		vdrop(lvp); -	if (uvp != NULLVP) +	if (uvp != NULL)  		vdrop(uvp);  	vdrop(vp);  	vfs_rel(mp); | 
