8322 nl: misleading-indentation
[unleashed/tickless.git] / usr / src / uts / common / fs / sharefs / sharefs_vnops.c
blob2ca3f293a5181590888a225a9f7df84f44577c5b
1 /*
2 * CDDL HEADER START
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.
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.
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]
19 * CDDL HEADER END
23 * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 #include <fs/fs_subr.h>
29 #include <sys/errno.h>
30 #include <sys/file.h>
31 #include <sys/kmem.h>
32 #include <sys/kobj.h>
33 #include <sys/cmn_err.h>
34 #include <sys/stat.h>
35 #include <sys/systm.h>
36 #include <sys/sysmacros.h>
37 #include <sys/atomic.h>
38 #include <sys/vfs.h>
39 #include <sys/vfs_opreg.h>
41 #include <sharefs/sharefs.h>
44 * sharefs_snap_create: create a large character buffer with
45 * the shares enumerated.
47 static int
48 sharefs_snap_create(shnode_t *sft)
50 sharetab_t *sht;
51 share_t *sh;
52 size_t sWritten = 0;
53 int iCount = 0;
54 char *buf;
56 rw_enter(&sharefs_lock, RW_WRITER);
57 rw_enter(&sharetab_lock, RW_READER);
59 if (sft->sharefs_snap) {
61 * Nothing has changed, so no need to grab a new copy!
63 if (sft->sharefs_generation == sharetab_generation) {
64 rw_exit(&sharetab_lock);
65 rw_exit(&sharefs_lock);
66 return (0);
69 ASSERT(sft->sharefs_size != 0);
70 kmem_free(sft->sharefs_snap, sft->sharefs_size + 1);
71 sft->sharefs_snap = NULL;
74 sft->sharefs_size = sharetab_size;
75 sft->sharefs_count = sharetab_count;
77 if (sft->sharefs_size == 0) {
78 rw_exit(&sharetab_lock);
79 rw_exit(&sharefs_lock);
80 return (0);
83 sft->sharefs_snap = kmem_zalloc(sft->sharefs_size + 1, KM_SLEEP);
85 buf = sft->sharefs_snap;
88 * Walk the Sharetab, dumping each entry.
90 for (sht = sharefs_sharetab; sht != NULL; sht = sht->s_next) {
91 int i;
93 for (i = 0; i < SHARETAB_HASHES; i++) {
94 for (sh = sht->s_buckets[i].ssh_sh;
95 sh != NULL;
96 sh = sh->sh_next) {
97 int n;
99 if ((sWritten + sh->sh_size) >
100 sft->sharefs_size) {
101 goto error_fault;
105 * Note that sh->sh_size accounts
106 * for the field seperators.
107 * We need to add one for the EOL
108 * marker. And we should note that
109 * the space is accounted for in
110 * each share by the EOS marker.
112 n = snprintf(&buf[sWritten],
113 sh->sh_size + 1,
114 "%s\t%s\t%s\t%s\t%s\n",
115 sh->sh_path,
116 sh->sh_res,
117 sh->sh_fstype,
118 sh->sh_opts,
119 sh->sh_descr);
121 if (n != sh->sh_size) {
122 goto error_fault;
125 sWritten += n;
126 iCount++;
132 * We want to record the generation number and
133 * mtime inside this snapshot.
135 gethrestime(&sharetab_snap_time);
136 sft->sharefs_snap_time = sharetab_snap_time;
137 sft->sharefs_generation = sharetab_generation;
139 ASSERT(iCount == sft->sharefs_count);
141 rw_exit(&sharetab_lock);
142 rw_exit(&sharefs_lock);
143 return (0);
145 error_fault:
147 kmem_free(sft->sharefs_snap, sft->sharefs_size + 1);
148 sft->sharefs_size = 0;
149 sft->sharefs_count = 0;
150 sft->sharefs_snap = NULL;
151 rw_exit(&sharetab_lock);
152 rw_exit(&sharefs_lock);
154 return (EFAULT);
157 /* ARGSUSED */
158 static int
159 sharefs_getattr(vnode_t *vp, vattr_t *vap, int flags, cred_t *cr,
160 caller_context_t *ct)
162 timestruc_t now;
163 shnode_t *sft = VTOSH(vp);
165 vap->va_type = VREG;
166 vap->va_mode = S_IRUSR | S_IRGRP | S_IROTH;
167 vap->va_nodeid = SHAREFS_INO_FILE;
168 vap->va_nlink = 1;
170 rw_enter(&sharefs_lock, RW_READER);
173 * If we get asked about a snapped vnode, then
174 * we must report the data in that vnode.
176 * Else we report what is currently in the
177 * sharetab.
179 if (sft->sharefs_real_vp) {
180 rw_enter(&sharetab_lock, RW_READER);
181 vap->va_size = sharetab_size;
182 vap->va_mtime = sharetab_mtime;
183 rw_exit(&sharetab_lock);
184 } else {
185 vap->va_size = sft->sharefs_size;
186 vap->va_mtime = sft->sharefs_snap_time;
188 rw_exit(&sharefs_lock);
190 gethrestime(&now);
191 vap->va_atime = vap->va_ctime = now;
193 vap->va_uid = 0;
194 vap->va_gid = 0;
195 vap->va_rdev = 0;
196 vap->va_blksize = DEV_BSIZE;
197 vap->va_nblocks = howmany(vap->va_size, vap->va_blksize);
198 vap->va_seq = 0;
199 vap->va_fsid = vp->v_vfsp->vfs_dev;
201 return (0);
204 /* ARGSUSED */
205 static int
206 sharefs_access(vnode_t *vp, int mode, int flags, cred_t *cr,
207 caller_context_t *ct)
209 if (mode & (VWRITE|VEXEC))
210 return (EROFS);
212 return (0);
215 /* ARGSUSED */
217 sharefs_open(vnode_t **vpp, int flag, cred_t *cr, caller_context_t *ct)
219 vnode_t *vp;
220 vnode_t *ovp = *vpp;
221 shnode_t *sft;
222 int error = 0;
224 if (flag & FWRITE)
225 return (EINVAL);
228 * Create a new sharefs vnode for each operation. In order to
229 * avoid locks, we create a snapshot which can not change during
230 * reads.
232 vp = gfs_file_create(sizeof (shnode_t), NULL, sharefs_ops_data);
234 ((gfs_file_t *)vp->v_data)->gfs_ino = SHAREFS_INO_FILE;
237 * Hold the parent!
239 VFS_HOLD(ovp->v_vfsp);
241 VN_SET_VFS_TYPE_DEV(vp, ovp->v_vfsp, VREG, 0);
243 vp->v_flag |= VROOT | VNOCACHE | VNOMAP | VNOSWAP | VNOMOUNT;
245 *vpp = vp;
246 VN_RELE(ovp);
248 sft = VTOSH(vp);
251 * No need for the lock, no other thread can be accessing
252 * this data structure.
254 atomic_inc_32(&sft->sharefs_refs);
255 sft->sharefs_real_vp = 0;
258 * Since the sharetab could easily change on us whilst we
259 * are dumping an extremely huge sharetab, we make a copy
260 * of it here and use it to dump instead.
262 error = sharefs_snap_create(sft);
264 return (error);
267 /* ARGSUSED */
269 sharefs_close(vnode_t *vp, int flag, int count,
270 offset_t off, cred_t *cr, caller_context_t *ct)
272 shnode_t *sft = VTOSH(vp);
274 if (count > 1)
275 return (0);
277 rw_enter(&sharefs_lock, RW_WRITER);
278 if (vp->v_count == 1) {
279 if (sft->sharefs_snap != NULL) {
280 kmem_free(sft->sharefs_snap, sft->sharefs_size + 1);
281 sft->sharefs_size = 0;
282 sft->sharefs_snap = NULL;
283 sft->sharefs_generation = 0;
286 atomic_dec_32(&sft->sharefs_refs);
287 rw_exit(&sharefs_lock);
289 return (0);
292 /* ARGSUSED */
293 static int
294 sharefs_read(vnode_t *vp, uio_t *uio, int ioflag, cred_t *cr,
295 caller_context_t *ct)
297 shnode_t *sft = VTOSH(vp);
298 off_t off = uio->uio_offset;
299 size_t len = uio->uio_resid;
300 int error = 0;
302 rw_enter(&sharefs_lock, RW_READER);
305 * First check to see if we need to grab a new snapshot.
307 if (off == (off_t)0) {
308 rw_exit(&sharefs_lock);
309 error = sharefs_snap_create(sft);
310 if (error) {
311 return (EFAULT);
313 rw_enter(&sharefs_lock, RW_READER);
316 /* LINTED */
317 if (len <= 0 || off >= sft->sharefs_size) {
318 rw_exit(&sharefs_lock);
319 return (error);
322 if ((size_t)(off + len) > sft->sharefs_size)
323 len = sft->sharefs_size - off;
325 if (off < 0 || len > sft->sharefs_size) {
326 rw_exit(&sharefs_lock);
327 return (EFAULT);
330 if (len != 0) {
331 error = uiomove(sft->sharefs_snap + off,
332 len, UIO_READ, uio);
335 rw_exit(&sharefs_lock);
336 return (error);
339 /* ARGSUSED */
340 static void
341 sharefs_inactive(vnode_t *vp, cred_t *cr, caller_context_t *tx)
343 gfs_file_t *fp = vp->v_data;
344 shnode_t *sft;
346 sft = (shnode_t *)gfs_file_inactive(vp);
347 if (sft) {
348 rw_enter(&sharefs_lock, RW_WRITER);
349 if (sft->sharefs_snap != NULL) {
350 kmem_free(sft->sharefs_snap, sft->sharefs_size + 1);
353 kmem_free(sft, fp->gfs_size);
354 rw_exit(&sharefs_lock);
358 vnode_t *
359 sharefs_create_root_file(vfs_t *vfsp)
361 vnode_t *vp;
362 shnode_t *sft;
364 vp = gfs_root_create_file(sizeof (shnode_t),
365 vfsp, sharefs_ops_data, SHAREFS_INO_FILE);
367 sft = VTOSH(vp);
369 sft->sharefs_real_vp = 1;
371 return (vp);
374 const fs_operation_def_t sharefs_tops_data[] = {
375 { VOPNAME_OPEN, { .vop_open = sharefs_open } },
376 { VOPNAME_CLOSE, { .vop_close = sharefs_close } },
377 { VOPNAME_IOCTL, { .error = fs_inval } },
378 { VOPNAME_GETATTR, { .vop_getattr = sharefs_getattr } },
379 { VOPNAME_ACCESS, { .vop_access = sharefs_access } },
380 { VOPNAME_INACTIVE, { .vop_inactive = sharefs_inactive } },
381 { VOPNAME_READ, { .vop_read = sharefs_read } },
382 { VOPNAME_SEEK, { .vop_seek = fs_seek } },
383 { NULL }