diff options
Diffstat (limited to 'sys/fs')
28 files changed, 276 insertions, 112 deletions
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 caadf257b8ad..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);  } 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_internal.c b/sys/fs/fuse/fuse_internal.c index 61fe2ed032f6..eba0a8a79ff3 100644 --- a/sys/fs/fuse/fuse_internal.c +++ b/sys/fs/fuse/fuse_internal.c @@ -1063,6 +1063,8 @@ fuse_internal_init_callback(struct fuse_ticket *tick, struct uio *uio)  	if (!fuse_libabi_geq(data, 7, 28))  		fsess_set_notimpl(data->mp, FUSE_COPY_FILE_RANGE); +	if (fuse_libabi_geq(data, 7, 33) && (fiio->flags & FUSE_SETXATTR_EXT)) +		data->dataflags |= FSESS_SETXATTR_EXT;  out:  	if (err) {  		fdata_set_dead(data); @@ -1115,7 +1117,8 @@ fuse_internal_send_init(struct fuse_data *data, struct thread *td)  	 */  	fiii->flags = FUSE_ASYNC_READ | FUSE_POSIX_LOCKS | FUSE_EXPORT_SUPPORT  		| FUSE_BIG_WRITES | FUSE_WRITEBACK_CACHE -		| FUSE_NO_OPEN_SUPPORT | FUSE_NO_OPENDIR_SUPPORT; +		| FUSE_NO_OPEN_SUPPORT | FUSE_NO_OPENDIR_SUPPORT +		| FUSE_SETXATTR_EXT;  	fuse_insert_callback(fdi.tick, fuse_internal_init_callback);  	fuse_insert_message(fdi.tick, false); diff --git a/sys/fs/fuse/fuse_ipc.c b/sys/fs/fuse/fuse_ipc.c index 7f754ab7f1d4..bc36f0070d7d 100644 --- a/sys/fs/fuse/fuse_ipc.c +++ b/sys/fs/fuse/fuse_ipc.c @@ -694,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_ipc.h b/sys/fs/fuse/fuse_ipc.h index 3bfc859dbac9..d9d79f38c269 100644 --- a/sys/fs/fuse/fuse_ipc.h +++ b/sys/fs/fuse/fuse_ipc.h @@ -243,6 +243,7 @@ struct fuse_data {  #define FSESS_MNTOPTS_MASK	( \  	FSESS_DAEMON_CAN_SPY | FSESS_PUSH_SYMLINKS_IN | \  	FSESS_DEFAULT_PERMISSIONS | FSESS_INTR) +#define	FSESS_SETXATTR_EXT	  0x8000000 /* extended fuse_setxattr_in */  extern int fuse_data_cache_mode; diff --git a/sys/fs/fuse/fuse_vnops.c b/sys/fs/fuse/fuse_vnops.c index 5c28db29fc63..6c79e646d2f3 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)); @@ -2756,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")); @@ -2777,7 +2777,7 @@ fuse_vnop_setextattr(struct vop_setextattr_args *ap)  	    strlen(ap->a_name) + 1;  	/* older FUSE servers  use a smaller fuse_setxattr_in struct*/ -	if (fuse_libabi_geq(fuse_get_mpdata(mp), 7, 33)) +	if (fuse_get_mpdata(mp)->dataflags & FSESS_SETXATTR_EXT)  		struct_size = sizeof(*set_xattr_in);  	fdisp_init(&fdi, len + struct_size + uio->uio_resid); @@ -2786,7 +2786,7 @@ fuse_vnop_setextattr(struct vop_setextattr_args *ap)  	set_xattr_in = fdi.indata;  	set_xattr_in->size = uio->uio_resid; -	if (fuse_libabi_geq(fuse_get_mpdata(mp), 7, 33)) { +	if (fuse_get_mpdata(mp)->dataflags & FSESS_SETXATTR_EXT) {  		set_xattr_in->setxattr_flags = 0;  		set_xattr_in->padding = 0;  	} 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_commonsubs.c b/sys/fs/nfs/nfs_commonsubs.c index 7f5b29ca2085..707ad5749ab2 100644 --- a/sys/fs/nfs/nfs_commonsubs.c +++ b/sys/fs/nfs/nfs_commonsubs.c @@ -194,7 +194,6 @@ struct nfsv4_opflag nfsv4_opflag[NFSV42_NOPS] = {  	{ 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, 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; @@ -632,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);  		} @@ -649,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, 0); +		    false, false, false, 0, NULL, false);  		break;  	}  } @@ -760,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); @@ -1663,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: @@ -1689,11 +1706,18 @@ nfsv4_loadattr(struct nfsrv_descript *nd, vnode_t vp,  			attrsum += NFSX_UNSIGNED;  			break;  		case NFSATTRBIT_CASEINSENSITIVE: -			NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED); +			NFSM_DISSECT(tl, uint32_t *, NFSX_UNSIGNED);  			if (compare) {  				if (!(*retcmpp)) { -				    if (*tl != newnfs_false) -					*retcmpp = NFSERR_NOTSAME; +					if (vp == NULL || VOP_PATHCONF(vp, +					    _PC_CASE_INSENSITIVE, +					    &has_pathconf) != 0) +						has_pathconf = 0; +					if ((has_pathconf != 0 && +					     *tl != newnfs_true) || +					    (has_pathconf == 0 && +					    *tl != newnfs_false)) +						*retcmpp = NFSERR_NOTSAME;  				}  			} else if (pc != NULL) {  				pc->pc_caseinsensitive = @@ -2673,7 +2697,8 @@ 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, uint32_t clone_blksize) +    bool has_namedattr, uint32_t clone_blksize, fsid_t *fsidp, +    bool has_caseinsensitive)  {  	int bitpos, retnum = 0;  	u_int32_t *tl; @@ -2795,6 +2820,7 @@ 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, @@ -2847,10 +2873,12 @@ nfsv4_fillattr(struct nfsrv_descript *nd, struct mount *mp, vnode_t vp,  			break;  		case NFSATTRBIT_FSID:  			NFSM_BUILD(tl, u_int32_t *, NFSX_V4FSID); +			if (fsidp == NULL) +				fsidp = &mp->mnt_stat.f_fsid;  			*tl++ = 0; -			*tl++ = txdr_unsigned(mp->mnt_stat.f_fsid.val[0]); +			*tl++ = txdr_unsigned(fsidp->val[0]);  			*tl++ = 0; -			*tl = txdr_unsigned(mp->mnt_stat.f_fsid.val[1]); +			*tl = txdr_unsigned(fsidp->val[1]);  			retnum += NFSX_V4FSID;  			break;  		case NFSATTRBIT_UNIQUEHANDLES: @@ -2879,6 +2907,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) @@ -2888,8 +2924,11 @@ nfsv4_fillattr(struct nfsrv_descript *nd, struct mount *mp, vnode_t vp,  			retnum += NFSX_UNSIGNED;  			break;  		case NFSATTRBIT_CASEINSENSITIVE: -			NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED); -			*tl = newnfs_false; +			NFSM_BUILD(tl, uint32_t *, NFSX_UNSIGNED); +			if (has_caseinsensitive) +				*tl = newnfs_true; +			else +				*tl = newnfs_false;  			retnum += NFSX_UNSIGNED;  			break;  		case NFSATTRBIT_CASEPRESERVING: @@ -4165,10 +4204,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(), @@ -5021,9 +5065,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; @@ -5054,7 +5098,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 61083ecf2d66..7db3952ecf5c 100644 --- a/sys/fs/nfs/nfs_var.h +++ b/sys/fs/nfs/nfs_var.h @@ -361,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); @@ -400,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, uint32_t); +    bool, uint32_t, fsid_t *, bool);  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 *); @@ -742,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, uint32_t); +    bool, uint32_t, bool);  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/nfsproto.h b/sys/fs/nfs/nfsproto.h index d628108bdc1a..13fec8a102a3 100644 --- a/sys/fs/nfs/nfsproto.h +++ b/sys/fs/nfs/nfsproto.h @@ -1135,6 +1135,7 @@ struct nfsv3_sattr {   	NFSATTRBM_RDATTRERROR |						\   	NFSATTRBM_ACL |							\   	NFSATTRBM_ACLSUPPORT |						\ +	NFSATTRBM_ARCHIVE |						\   	NFSATTRBM_CANSETTIME |						\   	NFSATTRBM_CASEINSENSITIVE |					\   	NFSATTRBM_CASEPRESERVING |					\ @@ -1217,6 +1218,7 @@ struct nfsv3_sattr {  #define	NFSATTRBIT_SETABLE0						\  	(NFSATTRBM_SIZE |						\  	NFSATTRBM_HIDDEN |						\ +	NFSATTRBM_ARCHIVE |						\  	NFSATTRBM_ACL)  #define	NFSATTRBIT_SETABLE1						\   	(NFSATTRBM_MODE |						\ @@ -1262,6 +1264,7 @@ struct nfsv3_sattr {   	NFSATTRBM_CHANGE |						\   	NFSATTRBM_SIZE |						\   	NFSATTRBM_FSID |						\ +	NFSATTRBM_ARCHIVE |						\   	NFSATTRBM_FILEID |						\  	NFSATTRBM_HIDDEN |						\   	NFSATTRBM_MAXREAD) @@ -1298,6 +1301,7 @@ struct nfsv3_sattr {   	NFSATTRBM_CHANGE |						\   	NFSATTRBM_SIZE |						\   	NFSATTRBM_FSID |						\ +	NFSATTRBM_ARCHIVE |						\   	NFSATTRBM_FILEID |						\  	NFSATTRBM_HIDDEN |						\   	NFSATTRBM_MAXREAD) diff --git a/sys/fs/nfsclient/nfs_clrpcops.c b/sys/fs/nfsclient/nfs_clrpcops.c index ad9404a18fc8..f5deef183efb 100644 --- a/sys/fs/nfsclient/nfs_clrpcops.c +++ b/sys/fs/nfsclient/nfs_clrpcops.c @@ -2212,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) { @@ -4162,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);  		} @@ -5281,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, @@ -5322,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; @@ -5445,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, 0); +	    false, 0, NULL, false);  	error = nfscl_request(nd, vp, p, cred);  	if (error)  		return (error); @@ -5596,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. */ @@ -5665,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) { @@ -5678,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; @@ -5797,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; @@ -7246,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) { @@ -8243,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; @@ -8266,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); @@ -9745,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; diff --git a/sys/fs/nfsclient/nfs_clstate.c b/sys/fs/nfsclient/nfs_clstate.c index aa9d01fc4632..712d49c7160c 100644 --- a/sys/fs/nfsclient/nfs_clstate.c +++ b/sys/fs/nfsclient/nfs_clstate.c @@ -3701,7 +3701,8 @@ 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, 0); +				    (uint64_t)0, NULL, false, false, false, 0, +				    NULL, false);  			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 5ea7eab07632..212c88f28930 100644 --- a/sys/fs/nfsclient/nfs_clvfsops.c +++ b/sys/fs/nfsclient/nfs_clvfsops.c @@ -927,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; @@ -943,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; @@ -1329,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'; @@ -1387,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); @@ -1472,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 e9ae91e046e7..795a8d106051 100644 --- a/sys/fs/nfsclient/nfs_clvnops.c +++ b/sys/fs/nfsclient/nfs_clvnops.c @@ -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 && @@ -4675,12 +4677,13 @@ nfs_pathconf(struct vop_pathconf_args *ap)  	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)) || +	    ap->a_name == _PC_NO_TRUNC || +	    ap->a_name == _PC_CASE_INSENSITIVE)) ||  	    (NFS_ISV4(vp) && (ap->a_name == _PC_ACL_NFS4 ||  	     ap->a_name == _PC_HAS_NAMEDATTR ||  	     ap->a_name == _PC_CLONE_BLKSIZE))) {  		/* -		 * Since only the above 4 a_names are returned by the NFSv3 +		 * Since only the above 5 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, _PC_HAS_NAMEDATTR and @@ -4835,6 +4838,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)) @@ -4845,6 +4850,9 @@ nfs_pathconf(struct vop_pathconf_args *ap)  	case _PC_CLONE_BLKSIZE:  		*ap->a_retval = clone_blksize;  		break; +	case _PC_CASE_INSENSITIVE: +		*ap->a_retval = pc.pc_caseinsensitive; +		break;  	default:  		error = vop_stdpathconf(ap); diff --git a/sys/fs/nfsserver/nfs_nfsdport.c b/sys/fs/nfsserver/nfs_nfsdport.c index eb6ba285f8fe..841ec2315f1c 100644 --- a/sys/fs/nfsserver/nfs_nfsdport.c +++ b/sys/fs/nfsserver/nfs_nfsdport.c @@ -2114,7 +2114,7 @@ nfsvno_fillattr(struct nfsrv_descript *nd, struct mount *mp, struct vnode *vp,      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, -    uint32_t clone_blksize) +    uint32_t clone_blksize, bool has_caseinsensitive)  {  	struct statfs *sf;  	int error; @@ -2135,7 +2135,7 @@ nfsvno_fillattr(struct nfsrv_descript *nd, struct mount *mp, struct vnode *vp,  	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, -	    clone_blksize); +	    clone_blksize, NULL, has_caseinsensitive);  	free(sf, M_TEMP);  	NFSEXITCODE2(0, nd);  	return (error); @@ -2468,7 +2468,7 @@ nfsrvd_readdirplus(struct nfsrv_descript *nd, int isdgram,  	int bextpg0, bextpg1, bextpgsiz0, bextpgsiz1;  	size_t atsiz;  	long pathval; -	bool has_hiddensystem, has_namedattr, xattrsupp; +	bool has_caseinsensitive, has_hiddensystem, has_namedattr, xattrsupp;  	if (nd->nd_repstat) {  		nfsrv_postopattr(nd, getret, &at); @@ -2949,6 +2949,7 @@ ateof:  				xattrsupp = false;  				has_hiddensystem = false;  				has_namedattr = false; +				has_caseinsensitive = false;  				clone_blksize = 0;  				if (nvp != NULL) {  					supports_nfsv4acls = @@ -2978,6 +2979,11 @@ ateof:  					    &pathval) != 0)  						pathval = 0;  					clone_blksize = pathval; +					if (VOP_PATHCONF(nvp, +					    _PC_CASE_INSENSITIVE, +					    &pathval) != 0) +						pathval = 0; +					has_caseinsensitive = pathval > 0;  					NFSVOPUNLOCK(nvp);  				} else  					supports_nfsv4acls = 0; @@ -2999,7 +3005,7 @@ ateof:  					    supports_nfsv4acls, at_root,  					    mounted_on_fileno, xattrsupp,  					    has_hiddensystem, has_namedattr, -					    clone_blksize); +					    clone_blksize, has_caseinsensitive);  				} else {  					dirlen += nfsvno_fillattr(nd, new_mp,  					    nvp, nvap, &nfh, r, &attrbits, @@ -3007,7 +3013,7 @@ ateof:  					    supports_nfsv4acls, at_root,  					    mounted_on_fileno, xattrsupp,  					    has_hiddensystem, has_namedattr, -					    clone_blksize); +					    clone_blksize, has_caseinsensitive);  				}  				if (nvp != NULL)  					vrele(nvp); @@ -3193,7 +3199,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;  	} @@ -3226,9 +3233,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: @@ -6402,7 +6411,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, 0); +	    NULL, 0, 0, 0, 0, 0, NULL, false, false, false, 0, NULL, false);  	error = newnfs_request(nd, nmp, NULL, &nmp->nm_sockreq, NULL, p, cred,  	    NFS_PROG, NFS_VER4, NULL, 1, NULL, NULL);  	if (error != 0) { diff --git a/sys/fs/nfsserver/nfs_nfsdserv.c b/sys/fs/nfsserver/nfs_nfsdserv.c index 921ea4887af1..394b63c2ab07 100644 --- a/sys/fs/nfsserver/nfs_nfsdserv.c +++ b/sys/fs/nfsserver/nfs_nfsdserv.c @@ -252,7 +252,7 @@ nfsrvd_getattr(struct nfsrv_descript *nd, int isdgram,  	struct thread *p = curthread;  	size_t atsiz;  	long pathval; -	bool has_hiddensystem, has_namedattr, xattrsupp; +	bool has_caseinsensitive, has_hiddensystem, has_namedattr, xattrsupp;  	uint32_t clone_blksize;  	if (nd->nd_repstat) @@ -336,6 +336,10 @@ nfsrvd_getattr(struct nfsrv_descript *nd, int isdgram,  				    &pathval) != 0)  					pathval = 0;  				clone_blksize = pathval; +				if (VOP_PATHCONF(vp, _PC_CASE_INSENSITIVE, +				    &pathval) != 0) +					pathval = 0; +				has_caseinsensitive = pathval > 0;  				mp = vp->v_mount;  				if (nfsrv_enable_crossmntpt != 0 &&  				    vp->v_type == VDIR && @@ -371,7 +375,8 @@ nfsrvd_getattr(struct nfsrv_descript *nd, int isdgram,  					    isdgram, 1, supports_nfsv4acls,  					    at_root, mounted_on_fileno,  					    xattrsupp, has_hiddensystem, -					    has_namedattr, clone_blksize); +					    has_namedattr, clone_blksize, +					    has_caseinsensitive);  					vfs_unbusy(mp);  				}  				vrele(vp); @@ -436,6 +441,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); @@ -569,8 +575,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; @@ -588,6 +601,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)) @@ -5128,6 +5143,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); diff --git a/sys/fs/nullfs/null.h b/sys/fs/nullfs/null.h index aa7a689bec34..7bfdc20a3f67 100644 --- a/sys/fs/nullfs/null.h +++ b/sys/fs/nullfs/null.h @@ -35,11 +35,12 @@  #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;  	struct vnode	*nullm_lowerrootvp;	/* Ref to lower root vnode */ @@ -53,7 +54,7 @@ struct null_mount {   * A cache of vnode references   */  struct null_node { -	CK_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; @@ -82,6 +83,16 @@ 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; + +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; diff --git a/sys/fs/nullfs/null_subr.c b/sys/fs/nullfs/null_subr.c index 146d3bbdaedd..a843ae44f121 100644 --- a/sys/fs/nullfs/null_subr.c +++ b/sys/fs/nullfs/null_subr.c @@ -36,12 +36,12 @@  #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/vnode.h> +#include <sys/rwlock.h>  #include <sys/smr.h> +#include <sys/vnode.h>  #include <fs/nullfs/null.h> @@ -59,7 +59,7 @@ VFS_SMR_DECLARE;  #define	NULL_NHASH(vp) (&null_node_hashtbl[vfs_hash_index(vp) & null_hash_mask]) -static CK_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; @@ -116,7 +116,7 @@ null_hashget_locked(struct mount *mp, struct vnode *lowervp)  	 * reference count (but NOT the lower vnode's VREF counter).  	 */  	hd = NULL_NHASH(lowervp); -	CK_LIST_FOREACH(a, hd, null_hash) { +	CK_SLIST_FOREACH(a, hd, null_hash) {  		if (a->null_lowervp != lowervp)  			continue;  		/* @@ -143,12 +143,12 @@ null_hashget(struct mount *mp, struct vnode *lowervp)  	struct vnode *vp;  	enum vgetstate vs; -	ASSERT_VOP_LOCKED(lowervp, "null_hashget"); +	ASSERT_VOP_LOCKED(lowervp, __func__);  	rw_assert(&null_hash_lock, RA_UNLOCKED);  	vfs_smr_enter();  	hd = NULL_NHASH(lowervp); -	CK_LIST_FOREACH(a, hd, null_hash) { +	CK_SLIST_FOREACH(a, hd, null_hash) {  		if (a->null_lowervp != lowervp)  			continue;  		/* @@ -181,7 +181,7 @@ null_hashins(struct mount *mp, struct null_node *xp)  	hd = NULL_NHASH(xp->null_lowervp);  #ifdef INVARIANTS -	CK_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), @@ -189,7 +189,7 @@ null_hashins(struct mount *mp, struct null_node *xp)  		}  	}  #endif -	CK_LIST_INSERT_HEAD(hd, xp, null_hash); +	CK_SLIST_INSERT_HEAD(hd, xp, null_hash);  }  static void @@ -240,7 +240,9 @@ null_nodeget(struct mount *mp, struct vnode *lowervp, struct vnode **vpp)  	 */  	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);  		uma_zfree_smr(null_node_zone, xp); @@ -305,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); -	CK_LIST_REMOVE(xp, null_hash); +	CK_SLIST_REMOVE(hd, xp, null_node, null_hash);  	rw_wunlock(&null_hash_lock);  } 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 375b6aa27531..d4baabeb40ab 100644 --- a/sys/fs/nullfs/null_vnops.c +++ b/sys/fs/nullfs/null_vnops.c @@ -278,7 +278,7 @@ null_bypass(struct vop_generic_args *ap)  		 * that aren't.  (We must always map first vp or vclean fails.)  		 */  		if (i != 0 && (*this_vp_p == NULL || -			       (*this_vp_p)->v_op != &null_vnodeops)) { +		    !null_is_nullfs_vnode(*this_vp_p))) {  			old_vps[i] = NULL;  		} else {  			old_vps[i] = *this_vp_p; @@ -788,10 +788,10 @@ null_lock_prep_with_smr(struct vop_lock1_args *ap)  	struct null_node *nn;  	struct vnode *lvp; -	vfs_smr_enter(); -  	lvp = NULL; +	vfs_smr_enter(); +  	nn = VTONULL_SMR(ap->a_vp);  	if (__predict_true(nn != NULL)) {  		lvp = nn->null_lowervp; @@ -855,6 +855,8 @@ null_lock(struct vop_lock1_args *ap)  	 * case by reacquiring correct lock in requested mode.  	 */  	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) { @@ -869,7 +871,6 @@ null_lock(struct vop_lock1_args *ap)  			panic("Unsupported lock request %d\n",  			    flags);  		} -		VOP_UNLOCK(lvp);  		error = vop_stdlock(ap);  	}  	vdrop(lvp); @@ -1255,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/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/unionfs/union_subr.c b/sys/fs/unionfs/union_subr.c index a14f9ca74305..b6d6db60ca3d 100644 --- a/sys/fs/unionfs/union_subr.c +++ b/sys/fs/unionfs/union_subr.c @@ -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__)); diff --git a/sys/fs/unionfs/union_vnops.c b/sys/fs/unionfs/union_vnops.c index 627b2f6e9a1d..66fee97a07d5 100644 --- a/sys/fs/unionfs/union_vnops.c +++ b/sys/fs/unionfs/union_vnops.c @@ -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)) { @@ -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 @@ -2234,6 +2233,7 @@ unionfs_lock_restart:  		unp = VTOUNIONFS(vp);  		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  | 
