xref: /onnv-gate/usr/src/uts/common/fs/sockfs/sockcommon_vnops.c (revision 8348:4137e18bfaf0)
1*8348SEric.Yu@Sun.COM /*
2*8348SEric.Yu@Sun.COM  * CDDL HEADER START
3*8348SEric.Yu@Sun.COM  *
4*8348SEric.Yu@Sun.COM  * The contents of this file are subject to the terms of the
5*8348SEric.Yu@Sun.COM  * Common Development and Distribution License (the "License").
6*8348SEric.Yu@Sun.COM  * You may not use this file except in compliance with the License.
7*8348SEric.Yu@Sun.COM  *
8*8348SEric.Yu@Sun.COM  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*8348SEric.Yu@Sun.COM  * or http://www.opensolaris.org/os/licensing.
10*8348SEric.Yu@Sun.COM  * See the License for the specific language governing permissions
11*8348SEric.Yu@Sun.COM  * and limitations under the License.
12*8348SEric.Yu@Sun.COM  *
13*8348SEric.Yu@Sun.COM  * When distributing Covered Code, include this CDDL HEADER in each
14*8348SEric.Yu@Sun.COM  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*8348SEric.Yu@Sun.COM  * If applicable, add the following below this CDDL HEADER, with the
16*8348SEric.Yu@Sun.COM  * fields enclosed by brackets "[]" replaced with your own identifying
17*8348SEric.Yu@Sun.COM  * information: Portions Copyright [yyyy] [name of copyright owner]
18*8348SEric.Yu@Sun.COM  *
19*8348SEric.Yu@Sun.COM  * CDDL HEADER END
20*8348SEric.Yu@Sun.COM  */
21*8348SEric.Yu@Sun.COM 
22*8348SEric.Yu@Sun.COM /*
23*8348SEric.Yu@Sun.COM  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
24*8348SEric.Yu@Sun.COM  * Use is subject to license terms.
25*8348SEric.Yu@Sun.COM  */
26*8348SEric.Yu@Sun.COM 
27*8348SEric.Yu@Sun.COM #include <sys/types.h>
28*8348SEric.Yu@Sun.COM #include <sys/t_lock.h>
29*8348SEric.Yu@Sun.COM #include <sys/param.h>
30*8348SEric.Yu@Sun.COM #include <sys/systm.h>
31*8348SEric.Yu@Sun.COM #include <sys/bitmap.h>
32*8348SEric.Yu@Sun.COM #include <sys/debug.h>
33*8348SEric.Yu@Sun.COM #include <sys/errno.h>
34*8348SEric.Yu@Sun.COM #include <sys/strsubr.h>
35*8348SEric.Yu@Sun.COM #include <sys/cmn_err.h>
36*8348SEric.Yu@Sun.COM #include <sys/sysmacros.h>
37*8348SEric.Yu@Sun.COM #include <sys/filio.h>
38*8348SEric.Yu@Sun.COM #include <sys/flock.h>
39*8348SEric.Yu@Sun.COM #include <sys/stat.h>
40*8348SEric.Yu@Sun.COM #include <sys/share.h>
41*8348SEric.Yu@Sun.COM 
42*8348SEric.Yu@Sun.COM #include <sys/vfs.h>
43*8348SEric.Yu@Sun.COM #include <sys/vfs_opreg.h>
44*8348SEric.Yu@Sun.COM 
45*8348SEric.Yu@Sun.COM #include <sys/sockio.h>
46*8348SEric.Yu@Sun.COM #include <sys/socket.h>
47*8348SEric.Yu@Sun.COM #include <sys/socketvar.h>
48*8348SEric.Yu@Sun.COM #include <sys/strsun.h>
49*8348SEric.Yu@Sun.COM 
50*8348SEric.Yu@Sun.COM #include <fs/sockfs/sockcommon.h>
51*8348SEric.Yu@Sun.COM #include <fs/sockfs/socktpi.h>
52*8348SEric.Yu@Sun.COM 
53*8348SEric.Yu@Sun.COM /*
54*8348SEric.Yu@Sun.COM  * Generic vnode ops
55*8348SEric.Yu@Sun.COM  */
56*8348SEric.Yu@Sun.COM static int	socket_vop_open(struct vnode **, int, struct cred *,
57*8348SEric.Yu@Sun.COM 		    caller_context_t *);
58*8348SEric.Yu@Sun.COM static int	socket_vop_close(struct vnode *, int, int, offset_t,
59*8348SEric.Yu@Sun.COM 		    struct cred *, caller_context_t *);
60*8348SEric.Yu@Sun.COM static int	socket_vop_read(struct vnode *, struct uio *, int,
61*8348SEric.Yu@Sun.COM 		    struct cred *, caller_context_t *);
62*8348SEric.Yu@Sun.COM static int	socket_vop_write(struct vnode *, struct uio *, int,
63*8348SEric.Yu@Sun.COM 		    struct cred *, caller_context_t *);
64*8348SEric.Yu@Sun.COM static int	socket_vop_ioctl(struct vnode *, int, intptr_t, int,
65*8348SEric.Yu@Sun.COM 		    struct cred *, int32_t *, caller_context_t *);
66*8348SEric.Yu@Sun.COM static int	socket_vop_setfl(struct vnode *, int, int, cred_t *,
67*8348SEric.Yu@Sun.COM 		    caller_context_t *);
68*8348SEric.Yu@Sun.COM static int 	socket_vop_getattr(struct vnode *, struct vattr *, int,
69*8348SEric.Yu@Sun.COM 		    struct cred *, caller_context_t *);
70*8348SEric.Yu@Sun.COM static int 	socket_vop_setattr(struct vnode *, struct vattr *, int,
71*8348SEric.Yu@Sun.COM 		    struct cred *, caller_context_t *);
72*8348SEric.Yu@Sun.COM static int 	socket_vop_access(struct vnode *, int, int, struct cred *,
73*8348SEric.Yu@Sun.COM 		    caller_context_t *);
74*8348SEric.Yu@Sun.COM static int 	socket_vop_fsync(struct vnode *, int, struct cred *,
75*8348SEric.Yu@Sun.COM 		    caller_context_t *);
76*8348SEric.Yu@Sun.COM static void	socket_vop_inactive(struct vnode *, struct cred *,
77*8348SEric.Yu@Sun.COM 		    caller_context_t *);
78*8348SEric.Yu@Sun.COM static int 	socket_vop_fid(struct vnode *, struct fid *,
79*8348SEric.Yu@Sun.COM 		    caller_context_t *);
80*8348SEric.Yu@Sun.COM static int 	socket_vop_seek(struct vnode *, offset_t, offset_t *,
81*8348SEric.Yu@Sun.COM 		    caller_context_t *);
82*8348SEric.Yu@Sun.COM static int	socket_vop_poll(struct vnode *, short, int, short *,
83*8348SEric.Yu@Sun.COM 		    struct pollhead **, caller_context_t *);
84*8348SEric.Yu@Sun.COM 
85*8348SEric.Yu@Sun.COM extern int	socket_close_internal(struct sonode *, int, cred_t *);
86*8348SEric.Yu@Sun.COM extern void	socket_destroy_internal(struct sonode *, cred_t *);
87*8348SEric.Yu@Sun.COM 
88*8348SEric.Yu@Sun.COM struct vnodeops *socket_vnodeops;
89*8348SEric.Yu@Sun.COM const fs_operation_def_t socket_vnodeops_template[] = {
90*8348SEric.Yu@Sun.COM 	VOPNAME_OPEN,		{ .vop_open = socket_vop_open },
91*8348SEric.Yu@Sun.COM 	VOPNAME_CLOSE,		{ .vop_close = socket_vop_close },
92*8348SEric.Yu@Sun.COM 	VOPNAME_READ,		{ .vop_read = socket_vop_read },
93*8348SEric.Yu@Sun.COM 	VOPNAME_WRITE,		{ .vop_write = socket_vop_write },
94*8348SEric.Yu@Sun.COM 	VOPNAME_IOCTL,		{ .vop_ioctl = socket_vop_ioctl },
95*8348SEric.Yu@Sun.COM 	VOPNAME_SETFL,		{ .vop_setfl = socket_vop_setfl },
96*8348SEric.Yu@Sun.COM 	VOPNAME_GETATTR,	{ .vop_getattr = socket_vop_getattr },
97*8348SEric.Yu@Sun.COM 	VOPNAME_SETATTR,	{ .vop_setattr = socket_vop_setattr },
98*8348SEric.Yu@Sun.COM 	VOPNAME_ACCESS,		{ .vop_access = socket_vop_access },
99*8348SEric.Yu@Sun.COM 	VOPNAME_FSYNC,		{ .vop_fsync = socket_vop_fsync },
100*8348SEric.Yu@Sun.COM 	VOPNAME_INACTIVE,	{ .vop_inactive = socket_vop_inactive },
101*8348SEric.Yu@Sun.COM 	VOPNAME_FID,		{ .vop_fid = socket_vop_fid },
102*8348SEric.Yu@Sun.COM 	VOPNAME_SEEK,		{ .vop_seek = socket_vop_seek },
103*8348SEric.Yu@Sun.COM 	VOPNAME_POLL,		{ .vop_poll = socket_vop_poll },
104*8348SEric.Yu@Sun.COM 	VOPNAME_DISPOSE,	{ .error = fs_error },
105*8348SEric.Yu@Sun.COM 	NULL,			NULL
106*8348SEric.Yu@Sun.COM };
107*8348SEric.Yu@Sun.COM 
108*8348SEric.Yu@Sun.COM 
109*8348SEric.Yu@Sun.COM /*
110*8348SEric.Yu@Sun.COM  * generic vnode ops
111*8348SEric.Yu@Sun.COM  */
112*8348SEric.Yu@Sun.COM 
113*8348SEric.Yu@Sun.COM /*ARGSUSED*/
114*8348SEric.Yu@Sun.COM static int
socket_vop_open(struct vnode ** vpp,int flag,struct cred * cr,caller_context_t * ct)115*8348SEric.Yu@Sun.COM socket_vop_open(struct vnode **vpp, int flag, struct cred *cr,
116*8348SEric.Yu@Sun.COM     caller_context_t *ct)
117*8348SEric.Yu@Sun.COM {
118*8348SEric.Yu@Sun.COM 	struct vnode *vp = *vpp;
119*8348SEric.Yu@Sun.COM 	struct sonode *so = VTOSO(vp);
120*8348SEric.Yu@Sun.COM 
121*8348SEric.Yu@Sun.COM 	flag &= ~FCREAT;		/* paranoia */
122*8348SEric.Yu@Sun.COM 	mutex_enter(&so->so_lock);
123*8348SEric.Yu@Sun.COM 	so->so_count++;
124*8348SEric.Yu@Sun.COM 	mutex_exit(&so->so_lock);
125*8348SEric.Yu@Sun.COM 
126*8348SEric.Yu@Sun.COM 	ASSERT(so->so_count != 0);	/* wraparound */
127*8348SEric.Yu@Sun.COM 	ASSERT(vp->v_type == VSOCK);
128*8348SEric.Yu@Sun.COM 
129*8348SEric.Yu@Sun.COM 	return (0);
130*8348SEric.Yu@Sun.COM }
131*8348SEric.Yu@Sun.COM 
132*8348SEric.Yu@Sun.COM /*ARGSUSED*/
133*8348SEric.Yu@Sun.COM static int
socket_vop_close(struct vnode * vp,int flag,int count,offset_t offset,struct cred * cr,caller_context_t * ct)134*8348SEric.Yu@Sun.COM socket_vop_close(struct vnode *vp, int flag, int count, offset_t offset,
135*8348SEric.Yu@Sun.COM     struct cred *cr, caller_context_t *ct)
136*8348SEric.Yu@Sun.COM {
137*8348SEric.Yu@Sun.COM 	struct sonode *so;
138*8348SEric.Yu@Sun.COM 	int error = 0;
139*8348SEric.Yu@Sun.COM 
140*8348SEric.Yu@Sun.COM 	so = VTOSO(vp);
141*8348SEric.Yu@Sun.COM 	ASSERT(vp->v_type == VSOCK);
142*8348SEric.Yu@Sun.COM 
143*8348SEric.Yu@Sun.COM 	cleanlocks(vp, ttoproc(curthread)->p_pid, 0);
144*8348SEric.Yu@Sun.COM 	cleanshares(vp, ttoproc(curthread)->p_pid);
145*8348SEric.Yu@Sun.COM 
146*8348SEric.Yu@Sun.COM 	if (vp->v_stream)
147*8348SEric.Yu@Sun.COM 		strclean(vp);
148*8348SEric.Yu@Sun.COM 
149*8348SEric.Yu@Sun.COM 	if (count > 1) {
150*8348SEric.Yu@Sun.COM 		dprint(2, ("socket_vop_close: count %d\n", count));
151*8348SEric.Yu@Sun.COM 		return (0);
152*8348SEric.Yu@Sun.COM 	}
153*8348SEric.Yu@Sun.COM 
154*8348SEric.Yu@Sun.COM 	mutex_enter(&so->so_lock);
155*8348SEric.Yu@Sun.COM 	if (--so->so_count == 0) {
156*8348SEric.Yu@Sun.COM 		/*
157*8348SEric.Yu@Sun.COM 		 * Initiate connection shutdown.
158*8348SEric.Yu@Sun.COM 		 */
159*8348SEric.Yu@Sun.COM 		mutex_exit(&so->so_lock);
160*8348SEric.Yu@Sun.COM 		error = socket_close_internal(so, flag, cr);
161*8348SEric.Yu@Sun.COM 	} else {
162*8348SEric.Yu@Sun.COM 		mutex_exit(&so->so_lock);
163*8348SEric.Yu@Sun.COM 	}
164*8348SEric.Yu@Sun.COM 
165*8348SEric.Yu@Sun.COM 	return (error);
166*8348SEric.Yu@Sun.COM }
167*8348SEric.Yu@Sun.COM 
168*8348SEric.Yu@Sun.COM /*ARGSUSED2*/
169*8348SEric.Yu@Sun.COM static int
socket_vop_read(struct vnode * vp,struct uio * uiop,int ioflag,struct cred * cr,caller_context_t * ct)170*8348SEric.Yu@Sun.COM socket_vop_read(struct vnode *vp, struct uio *uiop, int ioflag, struct cred *cr,
171*8348SEric.Yu@Sun.COM     caller_context_t *ct)
172*8348SEric.Yu@Sun.COM {
173*8348SEric.Yu@Sun.COM 	struct sonode *so = VTOSO(vp);
174*8348SEric.Yu@Sun.COM 	struct nmsghdr lmsg;
175*8348SEric.Yu@Sun.COM 
176*8348SEric.Yu@Sun.COM 	ASSERT(vp->v_type == VSOCK);
177*8348SEric.Yu@Sun.COM 	bzero((void *)&lmsg, sizeof (lmsg));
178*8348SEric.Yu@Sun.COM 
179*8348SEric.Yu@Sun.COM 	return (socket_recvmsg(so, &lmsg, uiop, cr));
180*8348SEric.Yu@Sun.COM }
181*8348SEric.Yu@Sun.COM 
182*8348SEric.Yu@Sun.COM /*ARGSUSED2*/
183*8348SEric.Yu@Sun.COM static int
socket_vop_write(struct vnode * vp,struct uio * uiop,int ioflag,struct cred * cr,caller_context_t * ct)184*8348SEric.Yu@Sun.COM socket_vop_write(struct vnode *vp, struct uio *uiop, int ioflag,
185*8348SEric.Yu@Sun.COM     struct cred *cr, caller_context_t *ct)
186*8348SEric.Yu@Sun.COM {
187*8348SEric.Yu@Sun.COM 	struct sonode *so = VTOSO(vp);
188*8348SEric.Yu@Sun.COM 	struct nmsghdr lmsg;
189*8348SEric.Yu@Sun.COM 
190*8348SEric.Yu@Sun.COM 	ASSERT(vp->v_type == VSOCK);
191*8348SEric.Yu@Sun.COM 	bzero((void *)&lmsg, sizeof (lmsg));
192*8348SEric.Yu@Sun.COM 
193*8348SEric.Yu@Sun.COM 	if (!(so->so_mode & SM_BYTESTREAM)) {
194*8348SEric.Yu@Sun.COM 		/*
195*8348SEric.Yu@Sun.COM 		 * If the socket is not byte stream set MSG_EOR
196*8348SEric.Yu@Sun.COM 		 */
197*8348SEric.Yu@Sun.COM 		lmsg.msg_flags = MSG_EOR;
198*8348SEric.Yu@Sun.COM 	}
199*8348SEric.Yu@Sun.COM 
200*8348SEric.Yu@Sun.COM 	return (socket_sendmsg(so, &lmsg, uiop, cr));
201*8348SEric.Yu@Sun.COM }
202*8348SEric.Yu@Sun.COM 
203*8348SEric.Yu@Sun.COM /*ARGSUSED4*/
204*8348SEric.Yu@Sun.COM static int
socket_vop_ioctl(struct vnode * vp,int cmd,intptr_t arg,int mode,struct cred * cr,int32_t * rvalp,caller_context_t * ct)205*8348SEric.Yu@Sun.COM socket_vop_ioctl(struct vnode *vp, int cmd, intptr_t arg, int mode,
206*8348SEric.Yu@Sun.COM     struct cred *cr, int32_t *rvalp, caller_context_t *ct)
207*8348SEric.Yu@Sun.COM {
208*8348SEric.Yu@Sun.COM 	struct sonode *so = VTOSO(vp);
209*8348SEric.Yu@Sun.COM 
210*8348SEric.Yu@Sun.COM 	ASSERT(vp->v_type == VSOCK);
211*8348SEric.Yu@Sun.COM 
212*8348SEric.Yu@Sun.COM 	return (socket_ioctl(so, cmd, arg, mode, cr, rvalp));
213*8348SEric.Yu@Sun.COM }
214*8348SEric.Yu@Sun.COM 
215*8348SEric.Yu@Sun.COM /*
216*8348SEric.Yu@Sun.COM  * Allow any flags. Record FNDELAY and FNONBLOCK so that they can be inherited
217*8348SEric.Yu@Sun.COM  * from listener to acceptor.
218*8348SEric.Yu@Sun.COM  */
219*8348SEric.Yu@Sun.COM /* ARGSUSED */
220*8348SEric.Yu@Sun.COM static int
socket_vop_setfl(vnode_t * vp,int oflags,int nflags,cred_t * cr,caller_context_t * ct)221*8348SEric.Yu@Sun.COM socket_vop_setfl(vnode_t *vp, int oflags, int nflags, cred_t *cr,
222*8348SEric.Yu@Sun.COM     caller_context_t *ct)
223*8348SEric.Yu@Sun.COM {
224*8348SEric.Yu@Sun.COM 	struct sonode *so = VTOSO(vp);
225*8348SEric.Yu@Sun.COM 	int error = 0;
226*8348SEric.Yu@Sun.COM 
227*8348SEric.Yu@Sun.COM 	ASSERT(vp->v_type == VSOCK);
228*8348SEric.Yu@Sun.COM 
229*8348SEric.Yu@Sun.COM 	mutex_enter(&so->so_lock);
230*8348SEric.Yu@Sun.COM 	if (nflags & FNDELAY)
231*8348SEric.Yu@Sun.COM 		so->so_state |= SS_NDELAY;
232*8348SEric.Yu@Sun.COM 	else
233*8348SEric.Yu@Sun.COM 		so->so_state &= ~SS_NDELAY;
234*8348SEric.Yu@Sun.COM 	if (nflags & FNONBLOCK)
235*8348SEric.Yu@Sun.COM 		so->so_state |= SS_NONBLOCK;
236*8348SEric.Yu@Sun.COM 	else
237*8348SEric.Yu@Sun.COM 		so->so_state &= ~SS_NONBLOCK;
238*8348SEric.Yu@Sun.COM 	mutex_exit(&so->so_lock);
239*8348SEric.Yu@Sun.COM 
240*8348SEric.Yu@Sun.COM 	if (so->so_state & SS_ASYNC)
241*8348SEric.Yu@Sun.COM 		oflags |= FASYNC;
242*8348SEric.Yu@Sun.COM 	/*
243*8348SEric.Yu@Sun.COM 	 * Sets/clears the SS_ASYNC flag based on the presence/absence
244*8348SEric.Yu@Sun.COM 	 * of the FASYNC flag passed to fcntl(F_SETFL).
245*8348SEric.Yu@Sun.COM 	 * This exists solely for BSD fcntl() FASYNC compatibility.
246*8348SEric.Yu@Sun.COM 	 */
247*8348SEric.Yu@Sun.COM 	if ((oflags ^ nflags) & FASYNC && so->so_version != SOV_STREAM) {
248*8348SEric.Yu@Sun.COM 		int async = nflags & FASYNC;
249*8348SEric.Yu@Sun.COM 		int32_t rv;
250*8348SEric.Yu@Sun.COM 
251*8348SEric.Yu@Sun.COM 		/*
252*8348SEric.Yu@Sun.COM 		 * For non-TPI sockets all we have to do is set/remove the
253*8348SEric.Yu@Sun.COM 		 * SS_ASYNC bit, but for TPI it is more involved. For that
254*8348SEric.Yu@Sun.COM 		 * reason we delegate the job to the protocol's ioctl handler.
255*8348SEric.Yu@Sun.COM 		 */
256*8348SEric.Yu@Sun.COM 		error = socket_ioctl(so, FIOASYNC, (intptr_t)&async, FKIOCTL,
257*8348SEric.Yu@Sun.COM 		    cr, &rv);
258*8348SEric.Yu@Sun.COM 	}
259*8348SEric.Yu@Sun.COM 	return (error);
260*8348SEric.Yu@Sun.COM }
261*8348SEric.Yu@Sun.COM 
262*8348SEric.Yu@Sun.COM 
263*8348SEric.Yu@Sun.COM /*
264*8348SEric.Yu@Sun.COM  * Get the made up attributes for the vnode.
265*8348SEric.Yu@Sun.COM  * 4.3BSD returns the current time for all the timestamps.
266*8348SEric.Yu@Sun.COM  * 4.4BSD returns 0 for all the timestamps.
267*8348SEric.Yu@Sun.COM  * Here we use the access and modified times recorded in the sonode.
268*8348SEric.Yu@Sun.COM  *
269*8348SEric.Yu@Sun.COM  * Just like in BSD there is not effect on the underlying file system node
270*8348SEric.Yu@Sun.COM  * bound to an AF_UNIX pathname.
271*8348SEric.Yu@Sun.COM  *
272*8348SEric.Yu@Sun.COM  * When sockmod has been popped this will act just like a stream. Since
273*8348SEric.Yu@Sun.COM  * a socket is always a clone there is no need to inspect the attributes
274*8348SEric.Yu@Sun.COM  * of the "realvp".
275*8348SEric.Yu@Sun.COM  */
276*8348SEric.Yu@Sun.COM /* ARGSUSED */
277*8348SEric.Yu@Sun.COM int
socket_vop_getattr(struct vnode * vp,struct vattr * vap,int flags,struct cred * cr,caller_context_t * ct)278*8348SEric.Yu@Sun.COM socket_vop_getattr(struct vnode *vp, struct vattr *vap, int flags,
279*8348SEric.Yu@Sun.COM     struct cred *cr, caller_context_t *ct)
280*8348SEric.Yu@Sun.COM {
281*8348SEric.Yu@Sun.COM 	dev_t		fsid;
282*8348SEric.Yu@Sun.COM 	struct sonode 	*so;
283*8348SEric.Yu@Sun.COM 	static int	sonode_shift = 0;
284*8348SEric.Yu@Sun.COM 
285*8348SEric.Yu@Sun.COM 	/*
286*8348SEric.Yu@Sun.COM 	 * Calculate the amount of bitshift to a sonode pointer which will
287*8348SEric.Yu@Sun.COM 	 * still keep it unique.  See below.
288*8348SEric.Yu@Sun.COM 	 */
289*8348SEric.Yu@Sun.COM 	if (sonode_shift == 0)
290*8348SEric.Yu@Sun.COM 		sonode_shift = highbit(sizeof (struct sonode));
291*8348SEric.Yu@Sun.COM 	ASSERT(sonode_shift > 0);
292*8348SEric.Yu@Sun.COM 
293*8348SEric.Yu@Sun.COM 	so = VTOSO(vp);
294*8348SEric.Yu@Sun.COM 	fsid = sockdev;
295*8348SEric.Yu@Sun.COM 
296*8348SEric.Yu@Sun.COM 	if (so->so_version == SOV_STREAM) {
297*8348SEric.Yu@Sun.COM 		/*
298*8348SEric.Yu@Sun.COM 		 * The imaginary "sockmod" has been popped - act
299*8348SEric.Yu@Sun.COM 		 * as a stream
300*8348SEric.Yu@Sun.COM 		 */
301*8348SEric.Yu@Sun.COM 		vap->va_type = VCHR;
302*8348SEric.Yu@Sun.COM 		vap->va_mode = 0;
303*8348SEric.Yu@Sun.COM 	} else {
304*8348SEric.Yu@Sun.COM 		vap->va_type = vp->v_type;
305*8348SEric.Yu@Sun.COM 		vap->va_mode = S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|
306*8348SEric.Yu@Sun.COM 		    S_IROTH|S_IWOTH;
307*8348SEric.Yu@Sun.COM 	}
308*8348SEric.Yu@Sun.COM 	vap->va_uid = vap->va_gid = 0;
309*8348SEric.Yu@Sun.COM 	vap->va_fsid = fsid;
310*8348SEric.Yu@Sun.COM 	/*
311*8348SEric.Yu@Sun.COM 	 * If the va_nodeid is > MAX_USHORT, then i386 stats might fail.
312*8348SEric.Yu@Sun.COM 	 * So we shift down the sonode pointer to try and get the most
313*8348SEric.Yu@Sun.COM 	 * uniqueness into 16-bits.
314*8348SEric.Yu@Sun.COM 	 */
315*8348SEric.Yu@Sun.COM 	vap->va_nodeid = ((ino_t)so >> sonode_shift) & 0xFFFF;
316*8348SEric.Yu@Sun.COM 	vap->va_nlink = 0;
317*8348SEric.Yu@Sun.COM 	vap->va_size = 0;
318*8348SEric.Yu@Sun.COM 
319*8348SEric.Yu@Sun.COM 	/*
320*8348SEric.Yu@Sun.COM 	 * We need to zero out the va_rdev to avoid some fstats getting
321*8348SEric.Yu@Sun.COM 	 * EOVERFLOW.  This also mimics SunOS 4.x and BSD behavior.
322*8348SEric.Yu@Sun.COM 	 */
323*8348SEric.Yu@Sun.COM 	vap->va_rdev = (dev_t)0;
324*8348SEric.Yu@Sun.COM 	vap->va_blksize = MAXBSIZE;
325*8348SEric.Yu@Sun.COM 	vap->va_nblocks = btod(vap->va_size);
326*8348SEric.Yu@Sun.COM 
327*8348SEric.Yu@Sun.COM 	if (!SOCK_IS_NONSTR(so)) {
328*8348SEric.Yu@Sun.COM 		sotpi_info_t *sti = SOTOTPI(so);
329*8348SEric.Yu@Sun.COM 
330*8348SEric.Yu@Sun.COM 		mutex_enter(&so->so_lock);
331*8348SEric.Yu@Sun.COM 		vap->va_atime.tv_sec = sti->sti_atime;
332*8348SEric.Yu@Sun.COM 		vap->va_mtime.tv_sec = sti->sti_mtime;
333*8348SEric.Yu@Sun.COM 		vap->va_ctime.tv_sec = sti->sti_ctime;
334*8348SEric.Yu@Sun.COM 		mutex_exit(&so->so_lock);
335*8348SEric.Yu@Sun.COM 	} else {
336*8348SEric.Yu@Sun.COM 		vap->va_atime.tv_sec = 0;
337*8348SEric.Yu@Sun.COM 		vap->va_mtime.tv_sec = 0;
338*8348SEric.Yu@Sun.COM 		vap->va_ctime.tv_sec = 0;
339*8348SEric.Yu@Sun.COM 	}
340*8348SEric.Yu@Sun.COM 
341*8348SEric.Yu@Sun.COM 	vap->va_atime.tv_nsec = 0;
342*8348SEric.Yu@Sun.COM 	vap->va_mtime.tv_nsec = 0;
343*8348SEric.Yu@Sun.COM 	vap->va_ctime.tv_nsec = 0;
344*8348SEric.Yu@Sun.COM 	vap->va_seq = 0;
345*8348SEric.Yu@Sun.COM 
346*8348SEric.Yu@Sun.COM 	return (0);
347*8348SEric.Yu@Sun.COM }
348*8348SEric.Yu@Sun.COM 
349*8348SEric.Yu@Sun.COM /*
350*8348SEric.Yu@Sun.COM  * Set attributes.
351*8348SEric.Yu@Sun.COM  * Just like in BSD there is not effect on the underlying file system node
352*8348SEric.Yu@Sun.COM  * bound to an AF_UNIX pathname.
353*8348SEric.Yu@Sun.COM  *
354*8348SEric.Yu@Sun.COM  * When sockmod has been popped this will act just like a stream. Since
355*8348SEric.Yu@Sun.COM  * a socket is always a clone there is no need to modify the attributes
356*8348SEric.Yu@Sun.COM  * of the "realvp".
357*8348SEric.Yu@Sun.COM  */
358*8348SEric.Yu@Sun.COM /* ARGSUSED */
359*8348SEric.Yu@Sun.COM int
socket_vop_setattr(struct vnode * vp,struct vattr * vap,int flags,struct cred * cr,caller_context_t * ct)360*8348SEric.Yu@Sun.COM socket_vop_setattr(struct vnode *vp, struct vattr *vap, int flags,
361*8348SEric.Yu@Sun.COM     struct cred *cr, caller_context_t *ct)
362*8348SEric.Yu@Sun.COM {
363*8348SEric.Yu@Sun.COM 	struct sonode *so = VTOSO(vp);
364*8348SEric.Yu@Sun.COM 
365*8348SEric.Yu@Sun.COM 	/*
366*8348SEric.Yu@Sun.COM 	 * If times were changed, and we have a STREAMS socket, then update
367*8348SEric.Yu@Sun.COM 	 * the sonode.
368*8348SEric.Yu@Sun.COM 	 */
369*8348SEric.Yu@Sun.COM 	if (!SOCK_IS_NONSTR(so)) {
370*8348SEric.Yu@Sun.COM 		sotpi_info_t *sti = SOTOTPI(so);
371*8348SEric.Yu@Sun.COM 
372*8348SEric.Yu@Sun.COM 		mutex_enter(&so->so_lock);
373*8348SEric.Yu@Sun.COM 		if (vap->va_mask & AT_ATIME)
374*8348SEric.Yu@Sun.COM 			sti->sti_atime = vap->va_atime.tv_sec;
375*8348SEric.Yu@Sun.COM 		if (vap->va_mask & AT_MTIME) {
376*8348SEric.Yu@Sun.COM 			sti->sti_mtime = vap->va_mtime.tv_sec;
377*8348SEric.Yu@Sun.COM 			sti->sti_ctime = gethrestime_sec();
378*8348SEric.Yu@Sun.COM 		}
379*8348SEric.Yu@Sun.COM 		mutex_exit(&so->so_lock);
380*8348SEric.Yu@Sun.COM 	}
381*8348SEric.Yu@Sun.COM 
382*8348SEric.Yu@Sun.COM 	return (0);
383*8348SEric.Yu@Sun.COM }
384*8348SEric.Yu@Sun.COM 
385*8348SEric.Yu@Sun.COM /*
386*8348SEric.Yu@Sun.COM  * Check if user is allowed to access vp. For non-STREAMS based sockets,
387*8348SEric.Yu@Sun.COM  * there might not be a device attached to the file system. So for those
388*8348SEric.Yu@Sun.COM  * types of sockets there are no permissions to check.
389*8348SEric.Yu@Sun.COM  *
390*8348SEric.Yu@Sun.COM  * XXX Should there be some other mechanism to check access rights?
391*8348SEric.Yu@Sun.COM  */
392*8348SEric.Yu@Sun.COM /*ARGSUSED*/
393*8348SEric.Yu@Sun.COM int
socket_vop_access(struct vnode * vp,int mode,int flags,struct cred * cr,caller_context_t * ct)394*8348SEric.Yu@Sun.COM socket_vop_access(struct vnode *vp, int mode, int flags, struct cred *cr,
395*8348SEric.Yu@Sun.COM     caller_context_t *ct)
396*8348SEric.Yu@Sun.COM {
397*8348SEric.Yu@Sun.COM 	struct sonode *so = VTOSO(vp);
398*8348SEric.Yu@Sun.COM 
399*8348SEric.Yu@Sun.COM 	if (!SOCK_IS_NONSTR(so)) {
400*8348SEric.Yu@Sun.COM 		ASSERT(so->so_sockparams->sp_sdev_info.sd_vnode != NULL);
401*8348SEric.Yu@Sun.COM 		return (VOP_ACCESS(so->so_sockparams->sp_sdev_info.sd_vnode,
402*8348SEric.Yu@Sun.COM 		    mode, flags, cr, NULL));
403*8348SEric.Yu@Sun.COM 	}
404*8348SEric.Yu@Sun.COM 	return (0);
405*8348SEric.Yu@Sun.COM }
406*8348SEric.Yu@Sun.COM 
407*8348SEric.Yu@Sun.COM /*
408*8348SEric.Yu@Sun.COM  * 4.3BSD and 4.4BSD fail a fsync on a socket with EINVAL.
409*8348SEric.Yu@Sun.COM  * This code does the same to be compatible and also to not give an
410*8348SEric.Yu@Sun.COM  * application the impression that the data has actually been "synced"
411*8348SEric.Yu@Sun.COM  * to the other end of the connection.
412*8348SEric.Yu@Sun.COM  */
413*8348SEric.Yu@Sun.COM /* ARGSUSED */
414*8348SEric.Yu@Sun.COM int
socket_vop_fsync(struct vnode * vp,int syncflag,struct cred * cr,caller_context_t * ct)415*8348SEric.Yu@Sun.COM socket_vop_fsync(struct vnode *vp, int syncflag, struct cred *cr,
416*8348SEric.Yu@Sun.COM     caller_context_t *ct)
417*8348SEric.Yu@Sun.COM {
418*8348SEric.Yu@Sun.COM 	return (EINVAL);
419*8348SEric.Yu@Sun.COM }
420*8348SEric.Yu@Sun.COM 
421*8348SEric.Yu@Sun.COM /*ARGSUSED*/
422*8348SEric.Yu@Sun.COM static void
socket_vop_inactive(struct vnode * vp,struct cred * cr,caller_context_t * ct)423*8348SEric.Yu@Sun.COM socket_vop_inactive(struct vnode *vp, struct cred *cr, caller_context_t *ct)
424*8348SEric.Yu@Sun.COM {
425*8348SEric.Yu@Sun.COM 	struct sonode *so = VTOSO(vp);
426*8348SEric.Yu@Sun.COM 
427*8348SEric.Yu@Sun.COM 	ASSERT(vp->v_type == VSOCK);
428*8348SEric.Yu@Sun.COM 
429*8348SEric.Yu@Sun.COM 	mutex_enter(&vp->v_lock);
430*8348SEric.Yu@Sun.COM 	/*
431*8348SEric.Yu@Sun.COM 	 * If no one has reclaimed the vnode, remove from the
432*8348SEric.Yu@Sun.COM 	 * cache now.
433*8348SEric.Yu@Sun.COM 	 */
434*8348SEric.Yu@Sun.COM 	if (vp->v_count < 1)
435*8348SEric.Yu@Sun.COM 		cmn_err(CE_PANIC, "socket_inactive: Bad v_count");
436*8348SEric.Yu@Sun.COM 
437*8348SEric.Yu@Sun.COM 	/*
438*8348SEric.Yu@Sun.COM 	 * Drop the temporary hold by vn_rele now
439*8348SEric.Yu@Sun.COM 	 */
440*8348SEric.Yu@Sun.COM 	if (--vp->v_count != 0) {
441*8348SEric.Yu@Sun.COM 		mutex_exit(&vp->v_lock);
442*8348SEric.Yu@Sun.COM 		return;
443*8348SEric.Yu@Sun.COM 	}
444*8348SEric.Yu@Sun.COM 	mutex_exit(&vp->v_lock);
445*8348SEric.Yu@Sun.COM 
446*8348SEric.Yu@Sun.COM 
447*8348SEric.Yu@Sun.COM 	ASSERT(!vn_has_cached_data(vp));
448*8348SEric.Yu@Sun.COM 
449*8348SEric.Yu@Sun.COM 	/* socket specfic clean-up */
450*8348SEric.Yu@Sun.COM 	socket_destroy_internal(so, cr);
451*8348SEric.Yu@Sun.COM }
452*8348SEric.Yu@Sun.COM 
453*8348SEric.Yu@Sun.COM /* ARGSUSED */
454*8348SEric.Yu@Sun.COM int
socket_vop_fid(struct vnode * vp,struct fid * fidp,caller_context_t * ct)455*8348SEric.Yu@Sun.COM socket_vop_fid(struct vnode *vp, struct fid *fidp, caller_context_t *ct)
456*8348SEric.Yu@Sun.COM {
457*8348SEric.Yu@Sun.COM 	return (EINVAL);
458*8348SEric.Yu@Sun.COM }
459*8348SEric.Yu@Sun.COM 
460*8348SEric.Yu@Sun.COM /*
461*8348SEric.Yu@Sun.COM  * Sockets are not seekable.
462*8348SEric.Yu@Sun.COM  * (and there is a bug to fix STREAMS to make them fail this as well).
463*8348SEric.Yu@Sun.COM  */
464*8348SEric.Yu@Sun.COM /*ARGSUSED*/
465*8348SEric.Yu@Sun.COM int
socket_vop_seek(struct vnode * vp,offset_t ooff,offset_t * noffp,caller_context_t * ct)466*8348SEric.Yu@Sun.COM socket_vop_seek(struct vnode *vp, offset_t ooff, offset_t *noffp,
467*8348SEric.Yu@Sun.COM     caller_context_t *ct)
468*8348SEric.Yu@Sun.COM {
469*8348SEric.Yu@Sun.COM 	return (ESPIPE);
470*8348SEric.Yu@Sun.COM }
471*8348SEric.Yu@Sun.COM 
472*8348SEric.Yu@Sun.COM /*ARGSUSED*/
473*8348SEric.Yu@Sun.COM static int
socket_vop_poll(struct vnode * vp,short events,int anyyet,short * reventsp,struct pollhead ** phpp,caller_context_t * ct)474*8348SEric.Yu@Sun.COM socket_vop_poll(struct vnode *vp, short events, int anyyet, short *reventsp,
475*8348SEric.Yu@Sun.COM     struct pollhead **phpp, caller_context_t *ct)
476*8348SEric.Yu@Sun.COM {
477*8348SEric.Yu@Sun.COM 	struct sonode *so = VTOSO(vp);
478*8348SEric.Yu@Sun.COM 
479*8348SEric.Yu@Sun.COM 	ASSERT(vp->v_type == VSOCK);
480*8348SEric.Yu@Sun.COM 
481*8348SEric.Yu@Sun.COM 	return (socket_poll(so, events, anyyet, reventsp, phpp));
482*8348SEric.Yu@Sun.COM }
483