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 #include <sys/types.h>
27 #include <sys/param.h>
28 #include <sys/time.h>
29 #include <sys/cred.h>
30 #include <sys/vfs.h>
31 #include <sys/vfs_opreg.h>
32 #include <sys/gfs.h>
33 #include <sys/vnode.h>
34 #include <sys/systm.h>
35 #include <sys/errno.h>
36 #include <sys/sysmacros.h>
37 #include <fs/fs_subr.h>
38 #include <sys/contract.h>
39 #include <sys/contract_impl.h>
40 #include <sys/ctfs.h>
41 #include <sys/ctfs_impl.h>
42 #include <sys/file.h>
43 #include <sys/model.h>
44
45 /*
46 * CTFS routines for the /system/contract/<type>/template vnode.
47 */
48
49 /*
50 * ctfs_create_tmplnode
51 *
52 * Creates a new template and tdirnode, and returns the tdirnode.
53 */
54 vnode_t *
ctfs_create_tmplnode(vnode_t * pvp)55 ctfs_create_tmplnode(vnode_t *pvp)
56 {
57 vnode_t *vp;
58 ctfs_tmplnode_t *tmplnode;
59
60 ASSERT(gfs_file_index(pvp) < ct_ntypes);
61
62 vp = gfs_file_create(sizeof (ctfs_tmplnode_t), pvp, ctfs_ops_tmpl);
63 tmplnode = vp->v_data;
64 tmplnode->ctfs_tmn_tmpl =
65 ct_types[gfs_file_index(pvp)]->ct_type_default();
66
67 return (vp);
68 }
69
70 /*
71 * ctfs_tmpl_open - VOP_OPEN entry point
72 *
73 * Just ensures the right mode bits are set.
74 */
75 /* ARGSUSED */
76 static int
ctfs_tmpl_open(vnode_t ** vpp,int flag,cred_t * cr,caller_context_t * ct)77 ctfs_tmpl_open(vnode_t **vpp, int flag, cred_t *cr, caller_context_t *ct)
78 {
79 if (flag != (FREAD | FWRITE | FOFFMAX))
80 return (EINVAL);
81
82 return (0);
83 }
84
85 /*
86 * ctfs_tmpl_getattr - VOP_GETATTR entry point
87 */
88 /* ARGSUSED */
89 static int
ctfs_tmpl_getattr(vnode_t * vp,vattr_t * vap,int flags,cred_t * cr,caller_context_t * ct)90 ctfs_tmpl_getattr(
91 vnode_t *vp,
92 vattr_t *vap,
93 int flags,
94 cred_t *cr,
95 caller_context_t *ct)
96 {
97 vap->va_type = VREG;
98 vap->va_mode = 0666;
99 vap->va_nlink = 1;
100 vap->va_size = 0;
101 vap->va_ctime.tv_sec = vp->v_vfsp->vfs_mtime;
102 vap->va_ctime.tv_nsec = 0;
103 vap->va_atime = vap->va_mtime = vap->va_ctime;
104 ctfs_common_getattr(vp, vap);
105
106 return (0);
107 }
108
109 /*
110 * ctfs_tmpl_ioctl - VOP_IOCTL entry point
111 *
112 * All the ct_tmpl_*(3contract) interfaces point here.
113 */
114 /* ARGSUSED */
115 static int
ctfs_tmpl_ioctl(vnode_t * vp,int cmd,intptr_t arg,int flag,cred_t * cr,int * rvalp,caller_context_t * ct)116 ctfs_tmpl_ioctl(
117 vnode_t *vp,
118 int cmd,
119 intptr_t arg,
120 int flag,
121 cred_t *cr,
122 int *rvalp,
123 caller_context_t *ct)
124 {
125 ctfs_tmplnode_t *tmplnode = vp->v_data;
126 ct_kparam_t kparam;
127 ct_param_t *param = &kparam.param;
128 ctid_t ctid;
129 int error;
130
131 switch (cmd) {
132 case CT_TACTIVATE:
133 ASSERT(tmplnode->ctfs_tmn_tmpl != NULL);
134 ctmpl_activate(tmplnode->ctfs_tmn_tmpl);
135 break;
136 case CT_TCLEAR:
137 ASSERT(tmplnode->ctfs_tmn_tmpl != NULL);
138 ctmpl_clear(tmplnode->ctfs_tmn_tmpl);
139 break;
140 case CT_TCREATE:
141 ASSERT(tmplnode->ctfs_tmn_tmpl != NULL);
142 error = ctmpl_create(tmplnode->ctfs_tmn_tmpl, &ctid);
143 if (error)
144 return (error);
145 *rvalp = ctid;
146 break;
147 case CT_TSET:
148 error = ctparam_copyin((void *)arg, &kparam, flag, cmd);
149 if (error != 0)
150 return (error);
151 error = ctmpl_set(tmplnode->ctfs_tmn_tmpl, &kparam, cr);
152 kmem_free(kparam.ctpm_kbuf, param->ctpm_size);
153
154 return (error);
155 case CT_TGET:
156 error = ctparam_copyin((void *)arg, &kparam, flag, cmd);
157 if (error != 0)
158 return (error);
159 error = ctmpl_get(tmplnode->ctfs_tmn_tmpl, &kparam);
160 if (error != 0) {
161 kmem_free(kparam.ctpm_kbuf, param->ctpm_size);
162 } else {
163 error = ctparam_copyout(&kparam, (void *)arg, flag);
164 }
165
166 return (error);
167 default:
168 return (EINVAL);
169 }
170
171 return (0);
172 }
173
174 /*
175 * ctfs_tmpl_inactive - VOP_INACTIVE entry point
176 */
177 /* ARGSUSED */
178 static void
ctfs_tmpl_inactive(vnode_t * vp,cred_t * cr,caller_context_t * ct)179 ctfs_tmpl_inactive(vnode_t *vp, cred_t *cr, caller_context_t *ct)
180 {
181 ctfs_tmplnode_t *tmplnode;
182
183 if ((tmplnode = gfs_file_inactive(vp)) != NULL) {
184 ctmpl_free(tmplnode->ctfs_tmn_tmpl);
185 kmem_free(tmplnode, sizeof (ctfs_tmplnode_t));
186 }
187 }
188
189 const fs_operation_def_t ctfs_tops_tmpl[] = {
190 { VOPNAME_OPEN, { .vop_open = ctfs_tmpl_open } },
191 { VOPNAME_CLOSE, { .vop_close = ctfs_close } },
192 { VOPNAME_IOCTL, { .vop_ioctl = ctfs_tmpl_ioctl } },
193 { VOPNAME_GETATTR, { .vop_getattr = ctfs_tmpl_getattr } },
194 { VOPNAME_ACCESS, { .vop_access = ctfs_access_readwrite } },
195 { VOPNAME_READDIR, { .error = fs_notdir } },
196 { VOPNAME_LOOKUP, { .error = fs_notdir } },
197 { VOPNAME_INACTIVE, { .vop_inactive = ctfs_tmpl_inactive } },
198 { NULL, NULL }
199 };
200