xref: /illumos-gate/usr/src/uts/common/fs/ctfs/ctfs_tmpl.c (revision 2654012f83cec5dc15b61dfe3e4a4915f186e7a6)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #pragma ident	"%Z%%M%	%I%	%E% SMI"
27 
28 #include <sys/types.h>
29 #include <sys/param.h>
30 #include <sys/time.h>
31 #include <sys/cred.h>
32 #include <sys/vfs.h>
33 #include <sys/vfs_opreg.h>
34 #include <sys/gfs.h>
35 #include <sys/vnode.h>
36 #include <sys/systm.h>
37 #include <sys/errno.h>
38 #include <sys/sysmacros.h>
39 #include <fs/fs_subr.h>
40 #include <sys/contract.h>
41 #include <sys/contract_impl.h>
42 #include <sys/ctfs.h>
43 #include <sys/ctfs_impl.h>
44 #include <sys/file.h>
45 #include <sys/model.h>
46 
47 /*
48  * CTFS routines for the /system/contract/<type>/template vnode.
49  */
50 
51 /*
52  * ctfs_create_tmplnode
53  *
54  * Creates a new template and tdirnode, and returns the tdirnode.
55  */
56 vnode_t *
57 ctfs_create_tmplnode(vnode_t *pvp)
58 {
59 	vnode_t *vp;
60 	ctfs_tmplnode_t *tmplnode;
61 
62 	ASSERT(gfs_file_index(pvp) < ct_ntypes);
63 
64 	vp = gfs_file_create(sizeof (ctfs_tmplnode_t), pvp, ctfs_ops_tmpl);
65 	tmplnode = vp->v_data;
66 	tmplnode->ctfs_tmn_tmpl =
67 	    ct_types[gfs_file_index(pvp)]->ct_type_default();
68 
69 	return (vp);
70 }
71 
72 /*
73  * ctfs_tmpl_open - VOP_OPEN entry point
74  *
75  * Just ensures the right mode bits are set.
76  */
77 /* ARGSUSED */
78 static int
79 ctfs_tmpl_open(vnode_t **vpp, int flag, cred_t *cr, caller_context_t *ct)
80 {
81 	if (flag != (FREAD | FWRITE | FOFFMAX))
82 		return (EINVAL);
83 
84 	return (0);
85 }
86 
87 /*
88  * ctfs_tmpl_getattr - VOP_GETATTR entry point
89  */
90 /* ARGSUSED */
91 static int
92 ctfs_tmpl_getattr(
93 	vnode_t *vp,
94 	vattr_t *vap,
95 	int flags,
96 	cred_t *cr,
97 	caller_context_t *ct)
98 {
99 	vap->va_type = VREG;
100 	vap->va_mode = 0666;
101 	vap->va_nlink = 1;
102 	vap->va_size = 0;
103 	vap->va_ctime.tv_sec = vp->v_vfsp->vfs_mtime;
104 	vap->va_ctime.tv_nsec = 0;
105 	vap->va_atime = vap->va_mtime = vap->va_ctime;
106 	ctfs_common_getattr(vp, vap);
107 
108 	return (0);
109 }
110 
111 /*
112  * ctfs_tmpl_ioctl - VOP_IOCTL entry point
113  *
114  * All the ct_tmpl_*(3contract) interfaces point here.
115  */
116 /* ARGSUSED */
117 static int
118 ctfs_tmpl_ioctl(
119 	vnode_t *vp,
120 	int cmd,
121 	intptr_t arg,
122 	int flag,
123 	cred_t *cr,
124 	int *rvalp,
125 	caller_context_t *ct)
126 {
127 	ctfs_tmplnode_t	*tmplnode = vp->v_data;
128 	ct_param_t param;
129 	STRUCT_DECL(ct_param, uarg);
130 	ctid_t ctid;
131 	uint32_t local_ctpm_size;
132 	int error;
133 
134 	STRUCT_INIT(uarg, flag);
135 
136 	switch (cmd) {
137 	case CT_TACTIVATE:
138 		ASSERT(tmplnode->ctfs_tmn_tmpl != NULL);
139 		ctmpl_activate(tmplnode->ctfs_tmn_tmpl);
140 		break;
141 	case CT_TCLEAR:
142 		ASSERT(tmplnode->ctfs_tmn_tmpl != NULL);
143 		ctmpl_clear(tmplnode->ctfs_tmn_tmpl);
144 		break;
145 	case CT_TCREATE:
146 		ASSERT(tmplnode->ctfs_tmn_tmpl != NULL);
147 		error = ctmpl_create(tmplnode->ctfs_tmn_tmpl, &ctid);
148 		if (error)
149 			return (error);
150 		*rvalp = ctid;
151 		break;
152 	case CT_TSET:
153 		if (copyin((void *)arg, STRUCT_BUF(uarg), STRUCT_SIZE(uarg)))
154 			return (EFAULT);
155 		param.ctpm_id = STRUCT_FGET(uarg, ctpm_id);
156 		param.ctpm_size = STRUCT_FGET(uarg, ctpm_size);
157 		if (param.ctpm_size > CT_PARAM_MAX_SIZE ||
158 		    param.ctpm_size == 0)
159 			return (EINVAL);
160 		param.ctpm_value = kmem_alloc(param.ctpm_size, KM_SLEEP);
161 		if (copyin(STRUCT_FGETP(uarg, ctpm_value), param.ctpm_value,
162 		    param.ctpm_size))
163 			return (EFAULT);
164 		error = ctmpl_set(tmplnode->ctfs_tmn_tmpl, &param, cr);
165 		kmem_free(param.ctpm_value, param.ctpm_size);
166 		return (error);
167 	case CT_TGET:
168 		if (copyin((void *)arg, STRUCT_BUF(uarg), STRUCT_SIZE(uarg)))
169 			return (EFAULT);
170 		param.ctpm_id = STRUCT_FGET(uarg, ctpm_id);
171 		param.ctpm_size = STRUCT_FGET(uarg, ctpm_size);
172 		if (param.ctpm_size > CT_PARAM_MAX_SIZE)
173 			param.ctpm_size = CT_PARAM_MAX_SIZE;
174 		if (param.ctpm_size == 0)
175 			return (EINVAL);
176 		local_ctpm_size = param.ctpm_size;
177 		param.ctpm_value = kmem_alloc(param.ctpm_size, KM_SLEEP);
178 		error = ctmpl_get(tmplnode->ctfs_tmn_tmpl, &param);
179 		STRUCT_FSET(uarg, ctpm_size, param.ctpm_size);
180 		if (!error &&
181 		    (copyout(param.ctpm_value, STRUCT_FGETP(uarg, ctpm_value),
182 		    MIN(local_ctpm_size, param.ctpm_size))) ||
183 		    copyout(STRUCT_BUF(uarg), (void *)arg, STRUCT_SIZE(uarg)))
184 			error = EFAULT;
185 		kmem_free(param.ctpm_value, local_ctpm_size);
186 		return (error);
187 	default:
188 		return (EINVAL);
189 	}
190 
191 	return (0);
192 }
193 
194 /*
195  * ctfs_tmpl_inactive - VOP_INACTIVE entry point
196  */
197 /* ARGSUSED */
198 static void
199 ctfs_tmpl_inactive(vnode_t *vp, cred_t *cr, caller_context_t *ct)
200 {
201 	ctfs_tmplnode_t *tmplnode;
202 
203 	if ((tmplnode = gfs_file_inactive(vp)) != NULL) {
204 		ctmpl_free(tmplnode->ctfs_tmn_tmpl);
205 		kmem_free(tmplnode, sizeof (ctfs_tmplnode_t));
206 	}
207 }
208 
209 const fs_operation_def_t ctfs_tops_tmpl[] = {
210 	{ VOPNAME_OPEN,		{ .vop_open = ctfs_tmpl_open } },
211 	{ VOPNAME_CLOSE,	{ .vop_close = ctfs_close } },
212 	{ VOPNAME_IOCTL,	{ .vop_ioctl = ctfs_tmpl_ioctl } },
213 	{ VOPNAME_GETATTR,	{ .vop_getattr = ctfs_tmpl_getattr } },
214 	{ VOPNAME_ACCESS,	{ .vop_access = ctfs_access_readwrite } },
215 	{ VOPNAME_READDIR,	{ .error = fs_notdir } },
216 	{ VOPNAME_LOOKUP,	{ .error = fs_notdir } },
217 	{ VOPNAME_INACTIVE,	{ .vop_inactive = ctfs_tmpl_inactive } },
218 	{ NULL, NULL }
219 };
220