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 /*
23 * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27 #include <fs/fs_subr.h>
28
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>
40
41 #include <sharefs/sharefs.h>
42
43 /*
44 * sharefs_snap_create: create a large character buffer with
45 * the shares enumerated.
46 */
47 static int
48 sharefs_snap_create(shnode_t *sft)
49 {
50 sharetab_t *sht;
51 share_t *sh;
52 size_t sWritten = 0;
53 int iCount = 0;
54 char *buf;
55
56 rw_enter(&sharefs_lock, RW_WRITER);
57 rw_enter(&sharetab_lock, RW_READER);
58
59 if (sft->sharefs_snap) {
60 /*
61 * Nothing has changed, so no need to grab a new copy!
62 */
63 if (sft->sharefs_generation == sharetab_generation) {
64 rw_exit(&sharetab_lock);
65 rw_exit(&sharefs_lock);
66 return (0);
67 }
68
69 ASSERT(sft->sharefs_size != 0);
70 kmem_free(sft->sharefs_snap, sft->sharefs_size + 1);
71 sft->sharefs_snap = NULL;
72 }
73
74 sft->sharefs_size = sharetab_size;
75 sft->sharefs_count = sharetab_count;
76
77 if (sft->sharefs_size == 0) {
78 rw_exit(&sharetab_lock);
79 rw_exit(&sharefs_lock);
80 return (0);
81 }
82
83 sft->sharefs_snap = kmem_zalloc(sft->sharefs_size + 1, KM_SLEEP);
84
85 buf = sft->sharefs_snap;
86
87 /*
88 * Walk the Sharetab, dumping each entry.
89 */
90 for (sht = sharefs_sharetab; sht != NULL; sht = sht->s_next) {
91 int i;
92
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;
98
99 if ((sWritten + sh->sh_size) >
100 sft->sharefs_size) {
101 goto error_fault;
102 }
103
104 /*
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.
115 sh->sh_path,
116 sh->sh_res,
117 sh->sh_fstype,
118 sh->sh_opts,
119 sh->sh_descr);
120
121 if (n != sh->sh_size) {
122 goto error_fault;
123 }
124
125 sWritten += n;
126 iCount++;
127 }
128 }
129 }
130
131 /*
132 * We want to record the generation number and
133 * mtime inside this snapshot.
134 */
135 gethrestime(&sharetab_snap_time);
136 sft->sharefs_snap_time = sharetab_snap_time;
137 sft->sharefs_generation = sharetab_generation;
138
139 ASSERT(iCount == sft->sharefs_count);
140
141 rw_exit(&sharetab_lock);
142 rw_exit(&sharefs_lock);
143 return (0);
144
145 error_fault:
146
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);
153
154 return (EFAULT);
155 }
156
157 /* ARGSUSED */
158 static int
159 sharefs_getattr(vnode_t *vp, vattr_t *vap, int flags, cred_t *cr,
160 caller_context_t *ct)
161 {
162 timestruc_t now;
163 shnode_t *sft = VTOSH(vp);
164
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;
169
170 rw_enter(&sharefs_lock, RW_READER);
171
172 /*
173 * If we get asked about a snapped vnode, then
174 * we must report the data in that vnode.
175 *
176 * Else we report what is currently in the
177 * sharetab.
178 */
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;
187 }
188 rw_exit(&sharefs_lock);
189
190 gethrestime(&now);
191 vap->va_atime = vap->va_ctime = now;
192
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;
200
201 return (0);
202 }
203
204 /* ARGSUSED */
205 static int
206 sharefs_access(vnode_t *vp, int mode, int flags, cred_t *cr,
207 caller_context_t *ct)
208 {
242
243 vp->v_flag |= VROOT | VNOCACHE | VNOMAP | VNOSWAP | VNOMOUNT;
244
245 *vpp = vp;
246 VN_RELE(ovp);
247
248 sft = VTOSH(vp);
249
250 /*
251 * No need for the lock, no other thread can be accessing
252 * this data structure.
253 */
254 atomic_inc_32(&sft->sharefs_refs);
255 sft->sharefs_real_vp = 0;
256
257 /*
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.
261 */
262 error = sharefs_snap_create(sft);
263
264 return (error);
265 }
266
267 /* ARGSUSED */
268 int
269 sharefs_close(vnode_t *vp, int flag, int count,
270 offset_t off, cred_t *cr, caller_context_t *ct)
271 {
272 shnode_t *sft = VTOSH(vp);
273
274 if (count > 1)
275 return (0);
276
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;
284 }
285 }
286 atomic_dec_32(&sft->sharefs_refs);
287 rw_exit(&sharefs_lock);
288
289 return (0);
290 }
291
292 /* ARGSUSED */
293 static int
294 sharefs_read(vnode_t *vp, uio_t *uio, int ioflag, cred_t *cr,
295 caller_context_t *ct)
296 {
297 shnode_t *sft = VTOSH(vp);
298 off_t off = uio->uio_offset;
299 size_t len = uio->uio_resid;
300 int error = 0;
301
302 rw_enter(&sharefs_lock, RW_READER);
303
304 /*
305 * First check to see if we need to grab a new snapshot.
306 */
307 if (off == (off_t)0) {
308 rw_exit(&sharefs_lock);
309 error = sharefs_snap_create(sft);
310 if (error) {
311 return (EFAULT);
312 }
313 rw_enter(&sharefs_lock, RW_READER);
314 }
315
316 /* LINTED */
317 if (len <= 0 || off >= sft->sharefs_size) {
318 rw_exit(&sharefs_lock);
319 return (error);
320 }
321
322 if ((size_t)(off + len) > sft->sharefs_size)
323 len = sft->sharefs_size - off;
324
325 if (off < 0 || len > sft->sharefs_size) {
326 rw_exit(&sharefs_lock);
327 return (EFAULT);
328 }
329
330 if (len != 0) {
331 error = uiomove(sft->sharefs_snap + off,
332 len, UIO_READ, uio);
333 }
334
335 rw_exit(&sharefs_lock);
336 return (error);
337 }
338
339 /* ARGSUSED */
340 static void
341 sharefs_inactive(vnode_t *vp, cred_t *cr, caller_context_t *tx)
342 {
343 gfs_file_t *fp = vp->v_data;
344 shnode_t *sft;
345
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);
351 }
352
353 kmem_free(sft, fp->gfs_size);
354 rw_exit(&sharefs_lock);
355 }
356 }
357
358 vnode_t *
359 sharefs_create_root_file(vfs_t *vfsp)
360 {
361 vnode_t *vp;
362 shnode_t *sft;
363
364 vp = gfs_root_create_file(sizeof (shnode_t),
365 vfsp, sharefs_ops_data, SHAREFS_INO_FILE);
366
367 sft = VTOSH(vp);
368
369 sft->sharefs_real_vp = 1;
370
371 return (vp);
372 }
373
374 const fs_operation_def_t sharefs_tops_data[] = {
|
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 /*
23 * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27 /*
28 * Copyright 2018 Nexenta Systems, Inc.
29 */
30
31 #include <fs/fs_subr.h>
32
33 #include <sys/errno.h>
34 #include <sys/file.h>
35 #include <sys/kmem.h>
36 #include <sys/kobj.h>
37 #include <sys/cmn_err.h>
38 #include <sys/stat.h>
39 #include <sys/systm.h>
40 #include <sys/sysmacros.h>
41 #include <sys/atomic.h>
42 #include <sys/vfs.h>
43 #include <sys/vfs_opreg.h>
44
45 #include <sharefs/sharefs.h>
46
47 /*
48 * sharefs_snap_create: create a large character buffer with
49 * the shares enumerated.
50 */
51 static int
52 sharefs_snap_create(sharetab_globals_t *sg, shnode_t *sft)
53 {
54 sharetab_t *sht;
55 share_t *sh;
56 size_t sWritten = 0;
57 int iCount = 0;
58 char *buf;
59
60 rw_enter(&sg->sharefs_lock, RW_WRITER);
61 rw_enter(&sg->sharetab_lock, RW_READER);
62
63 if (sft->sharefs_snap) {
64 /*
65 * Nothing has changed, so no need to grab a new copy!
66 */
67 if (sft->sharefs_generation == sg->sharetab_generation) {
68 rw_exit(&sg->sharetab_lock);
69 rw_exit(&sg->sharefs_lock);
70 return (0);
71 }
72
73 ASSERT(sft->sharefs_size != 0);
74 kmem_free(sft->sharefs_snap, sft->sharefs_size + 1);
75 sft->sharefs_snap = NULL;
76 }
77
78 sft->sharefs_size = sg->sharetab_size;
79 sft->sharefs_count = sg->sharetab_count;
80
81 if (sft->sharefs_size == 0) {
82 rw_exit(&sg->sharetab_lock);
83 rw_exit(&sg->sharefs_lock);
84 return (0);
85 }
86
87 sft->sharefs_snap = kmem_zalloc(sft->sharefs_size + 1, KM_SLEEP);
88
89 buf = sft->sharefs_snap;
90
91 /*
92 * Walk the Sharetab, dumping each entry.
93 */
94 for (sht = sg->sharefs_sharetab; sht != NULL; sht = sht->s_next) {
95 int i;
96
97 for (i = 0; i < SHARETAB_HASHES; i++) {
98 for (sh = sht->s_buckets[i].ssh_sh;
99 sh != NULL;
100 sh = sh->sh_next) {
101 int n;
102
103 if ((sWritten + sh->sh_size) >
104 sft->sharefs_size) {
105 goto error_fault;
106 }
107
108 /*
109 * Note that sh->sh_size accounts
110 * for the field seperators.
111 * We need to add one for the EOL
112 * marker. And we should note that
113 * the space is accounted for in
114 * each share by the EOS marker.
119 sh->sh_path,
120 sh->sh_res,
121 sh->sh_fstype,
122 sh->sh_opts,
123 sh->sh_descr);
124
125 if (n != sh->sh_size) {
126 goto error_fault;
127 }
128
129 sWritten += n;
130 iCount++;
131 }
132 }
133 }
134
135 /*
136 * We want to record the generation number and
137 * mtime inside this snapshot.
138 */
139 gethrestime(&sg->sharetab_snap_time);
140 sft->sharefs_snap_time = sg->sharetab_snap_time;
141 sft->sharefs_generation = sg->sharetab_generation;
142
143 ASSERT(iCount == sft->sharefs_count);
144
145 rw_exit(&sg->sharetab_lock);
146 rw_exit(&sg->sharefs_lock);
147 return (0);
148
149 error_fault:
150
151 kmem_free(sft->sharefs_snap, sft->sharefs_size + 1);
152 sft->sharefs_size = 0;
153 sft->sharefs_count = 0;
154 sft->sharefs_snap = NULL;
155 rw_exit(&sg->sharetab_lock);
156 rw_exit(&sg->sharefs_lock);
157
158 return (EFAULT);
159 }
160
161 /* ARGSUSED */
162 static int
163 sharefs_getattr(vnode_t *vp, vattr_t *vap, int flags, cred_t *cr,
164 caller_context_t *ct)
165 {
166 timestruc_t now;
167 shnode_t *sft = VTOSH(vp);
168 sharetab_globals_t *sg = sharetab_get_globals(vp->v_vfsp->vfs_zone);
169
170 vap->va_type = VREG;
171 vap->va_mode = S_IRUSR | S_IRGRP | S_IROTH;
172 vap->va_nodeid = SHAREFS_INO_FILE;
173 vap->va_nlink = 1;
174
175 rw_enter(&sg->sharefs_lock, RW_READER);
176
177 /*
178 * If we get asked about a snapped vnode, then
179 * we must report the data in that vnode.
180 *
181 * Else we report what is currently in the
182 * sharetab.
183 */
184 if (sft->sharefs_real_vp) {
185 rw_enter(&sg->sharetab_lock, RW_READER);
186 vap->va_size = sg->sharetab_size;
187 vap->va_mtime = sg->sharetab_mtime;
188 rw_exit(&sg->sharetab_lock);
189 } else {
190 vap->va_size = sft->sharefs_size;
191 vap->va_mtime = sft->sharefs_snap_time;
192 }
193 rw_exit(&sg->sharefs_lock);
194
195 gethrestime(&now);
196 vap->va_atime = vap->va_ctime = now;
197
198 vap->va_uid = 0;
199 vap->va_gid = 0;
200 vap->va_rdev = 0;
201 vap->va_blksize = DEV_BSIZE;
202 vap->va_nblocks = howmany(vap->va_size, vap->va_blksize);
203 vap->va_seq = 0;
204 vap->va_fsid = vp->v_vfsp->vfs_dev;
205
206 return (0);
207 }
208
209 /* ARGSUSED */
210 static int
211 sharefs_access(vnode_t *vp, int mode, int flags, cred_t *cr,
212 caller_context_t *ct)
213 {
247
248 vp->v_flag |= VROOT | VNOCACHE | VNOMAP | VNOSWAP | VNOMOUNT;
249
250 *vpp = vp;
251 VN_RELE(ovp);
252
253 sft = VTOSH(vp);
254
255 /*
256 * No need for the lock, no other thread can be accessing
257 * this data structure.
258 */
259 atomic_inc_32(&sft->sharefs_refs);
260 sft->sharefs_real_vp = 0;
261
262 /*
263 * Since the sharetab could easily change on us whilst we
264 * are dumping an extremely huge sharetab, we make a copy
265 * of it here and use it to dump instead.
266 */
267 error = sharefs_snap_create(sharetab_get_globals(vp->v_vfsp->vfs_zone),
268 sft);
269
270 return (error);
271 }
272
273 /* ARGSUSED */
274 int
275 sharefs_close(vnode_t *vp, int flag, int count,
276 offset_t off, cred_t *cr, caller_context_t *ct)
277 {
278 shnode_t *sft = VTOSH(vp);
279 sharetab_globals_t *sg = sharetab_get_globals(vp->v_vfsp->vfs_zone);
280
281 if (count > 1)
282 return (0);
283
284 rw_enter(&sg->sharefs_lock, RW_WRITER);
285 if (vp->v_count == 1) {
286 if (sft->sharefs_snap != NULL) {
287 kmem_free(sft->sharefs_snap, sft->sharefs_size + 1);
288 sft->sharefs_size = 0;
289 sft->sharefs_snap = NULL;
290 sft->sharefs_generation = 0;
291 }
292 }
293 atomic_dec_32(&sft->sharefs_refs);
294 rw_exit(&sg->sharefs_lock);
295
296 return (0);
297 }
298
299 /* ARGSUSED */
300 static int
301 sharefs_read(vnode_t *vp, uio_t *uio, int ioflag, cred_t *cr,
302 caller_context_t *ct)
303 {
304 shnode_t *sft = VTOSH(vp);
305 off_t off = uio->uio_offset;
306 size_t len = uio->uio_resid;
307 int error = 0;
308 sharetab_globals_t *sg = sharetab_get_globals(vp->v_vfsp->vfs_zone);
309
310 rw_enter(&sg->sharefs_lock, RW_READER);
311
312 /*
313 * First check to see if we need to grab a new snapshot.
314 */
315 if (off == (off_t)0) {
316 rw_exit(&sg->sharefs_lock);
317 error = sharefs_snap_create(sg, sft);
318 if (error) {
319 return (EFAULT);
320 }
321 rw_enter(&sg->sharefs_lock, RW_READER);
322 }
323
324 /* LINTED */
325 if (len <= 0 || off >= sft->sharefs_size) {
326 rw_exit(&sg->sharefs_lock);
327 return (error);
328 }
329
330 if ((size_t)(off + len) > sft->sharefs_size)
331 len = sft->sharefs_size - off;
332
333 if (off < 0 || len > sft->sharefs_size) {
334 rw_exit(&sg->sharefs_lock);
335 return (EFAULT);
336 }
337
338 if (len != 0) {
339 error = uiomove(sft->sharefs_snap + off,
340 len, UIO_READ, uio);
341 }
342
343 rw_exit(&sg->sharefs_lock);
344 return (error);
345 }
346
347 /* ARGSUSED */
348 static void
349 sharefs_inactive(vnode_t *vp, cred_t *cr, caller_context_t *tx)
350 {
351 gfs_file_t *fp = vp->v_data;
352 shnode_t *sft;
353 sharetab_globals_t *sg = sharetab_get_globals(vp->v_vfsp->vfs_zone);
354
355 sft = (shnode_t *)gfs_file_inactive(vp);
356 if (sft) {
357 rw_enter(&sg->sharefs_lock, RW_WRITER);
358 if (sft->sharefs_snap != NULL) {
359 kmem_free(sft->sharefs_snap, sft->sharefs_size + 1);
360 }
361
362 kmem_free(sft, fp->gfs_size);
363 rw_exit(&sg->sharefs_lock);
364 }
365 }
366
367 vnode_t *
368 sharefs_create_root_file(vfs_t *vfsp)
369 {
370 vnode_t *vp;
371 shnode_t *sft;
372
373 vp = gfs_root_create_file(sizeof (shnode_t),
374 vfsp, sharefs_ops_data, SHAREFS_INO_FILE);
375
376 sft = VTOSH(vp);
377
378 sft->sharefs_real_vp = 1;
379
380 return (vp);
381 }
382
383 const fs_operation_def_t sharefs_tops_data[] = {
|