78 } fsh_fsrecord_t;
79
80
81 typedef struct fsh_callback_node {
82 fsh_callback_t fshcn_callback;
83 struct fsh_callback_node *fshcn_next;
84 } fsh_callback_node_t;
85
86 typedef struct fsh_callback_list {
87 krwlock_t fshcl_lock;
88 fsh_callback_node_t *fshcl_head;
89 } fsh_callback_list_t;
90
91 fsh_callback_list_t fsh_global_callback_list;
92
93 /*
94 * It is assumed that VFS_HOLD() has been called before calling any of the
95 * fsh_fs_xxx()/fsh_hook_xxx() API. VFS_RELE() should be called after.
96 */
97
98 #define FSH_GET_FSREC(vfsp) (vfsp->vfs_fshrecord)
99
100 int
101 fsh_fs_enable(vfs_t *vfsp)
102 {
103 fsh_fsrecord_t *fsrec;
104
105 fsrec = FSH_GET_FSREC(vfsp);
106 rw_enter(&fsrec->fshfsr_en_lock, RW_WRITER);
107 fsrec->fshfsr_enabled = 1;
108 rw_exit(&fsrec->fshfsr_en_lock);
109
110 return (0);
111 }
112
113 int
114 fsh_fs_disable(vfs_t *vfsp)
115 {
116 fsh_fsrecord_t *fsrec;
117
118 fsrec = FSH_GET_FSREC(vfsp);
119 rw_enter(&fsrec->fshfsr_en_lock, RW_WRITER);
120 fsrec->fshfsr_enabled = 0;
121 rw_exit(&fsrec->fshfsr_en_lock);
122
123 return (0);
124 }
125
126
127 #define FSH_INSTALL(type, hooks, fsrecp, listp, nodep, lower, upper) \
128 do { \
129 if (hooks->hook_##lower) { \
130 nodep = (fsh_node_t *) kmem_alloc(sizeof (*nodep), \
131 KM_SLEEP); \
132 nodep->fshn_hooki.fshi_fn.hook_##lower = \
133 hooks->hook_##lower; \
134 nodep->fshn_hooki.fshi_arg = hooks->arg; \
135 \
136 rw_enter(&listp->fshl_lock, RW_WRITER); \
137 nodep->fshn_next = \
138 fsrecp \
139 ->fshfsr_opv[FSH_##type##_##upper].fshl_head; \
140 fsrecp->fshfsr_opv[FSH_##type##_##upper].fshl_head \
141 = nodep; \
142 rw_exit(&listp->fshl_lock); \
143 } \
144 } while (0)
145
146 #define FSH_INSTALL_VN(hooks, fsrecp, listp, nodep, lower, upper) \
147 FSH_INSTALL(VOP, hooks, fsrecp, listp, nodep, lower, upper)
148
149 #define FSH_INSTALL_VFS(hooks, fsrecp, listp, nodep, lower, upper) \
150 FSH_INSTALL(VFS, hooks, fsrecp, listp, nodep, lower, upper)
151
152 int
153 fsh_hook_install(vfs_t *vfsp, fsh_t *hooks)
154 {
155 fsh_fsrecord_t *fsrec;
156 fsh_list_t *list;
157 fsh_node_t *node;
158
159 fsrec = FSH_GET_FSREC(vfsp);
160
161 FSH_INSTALL_VN(hooks, fsrec, list, node, open, OPEN);
162 FSH_INSTALL_VN(hooks, fsrec, list, node, close, CLOSE);
163 FSH_INSTALL_VN(hooks, fsrec, list, node, read, READ);
164 FSH_INSTALL_VN(hooks, fsrec, list, node, write, WRITE);
165 FSH_INSTALL_VFS(hooks, fsrec, list, node, mount, MOUNT);
166 FSH_INSTALL_VFS(hooks, fsrec, list, node, unmount, UNMOUNT);
167 FSH_INSTALL_VFS(hooks, fsrec, list, node, root, ROOT);
168 FSH_INSTALL_VFS(hooks, fsrec, list, node, vget, VGET);
169 FSH_INSTALL_VFS(hooks, fsrec, list, node, statfs, STATFS);
170
171 return (0);
172 }
173
174
175 #define FSH_REMOVE(type, hooks, fsrec, list, node, prev, lower, upper) \
176 do { \
177 if (hooks->hook_ ## lower == NULL) \
178 break; \
179 \
189 while (node && \
190 !(node->fshn_hooki.fshi_fn.hook_ ## lower == \
191 hooks->hook_ ## lower && \
192 node->fshn_hooki.fshi_arg == hooks->arg)) { \
193 prev = node; \
194 node = node->fshn_next; \
195 } \
196 \
197 if (node == NULL) { \
198 rw_exit(&list->fshl_lock); \
199 break; \
200 } \
201 \
202 if (node == list->fshl_head) \
203 list->fshl_head = node->fshn_next; \
204 else \
205 prev->fshn_next = node->fshn_next; \
206 rw_exit(&list->fshl_lock); \
207 \
208 kmem_free(node, sizeof (*node)); \
209 } while (0)
210
211 #define FSH_REMOVE_VN(hooks, fsrec, list, node, prev, lower, upper) \
212 FSH_REMOVE(VOP, hooks, fsrec, list, node, prev, lower, upper)
213
214 #define FSH_REMOVE_VFS(hooks, fsrec, list, node, prev, lower, upper) \
215 FSH_REMOVE(VFS, hooks, fsrec, list, node, prev, lower, upper)
216
217 int
218 fsh_hook_remove(vfs_t *vfsp, fsh_t *hooks)
219 {
220 fsh_fsrecord_t *fsrec;
221 fsh_list_t *list;
222 fsh_node_t *node;
223 fsh_node_t *prev;
224
225 fsrec = FSH_GET_FSREC(vfsp);
226
227 FSH_REMOVE_VN(hooks, fsrec, list, node, prev, open, OPEN);
228 FSH_REMOVE_VN(hooks, fsrec, list, node, prev, close, CLOSE);
229 FSH_REMOVE_VN(hooks, fsrec, list, node, prev, read, READ);
230 FSH_REMOVE_VN(hooks, fsrec, list, node, prev, write, WRITE);
231 FSH_REMOVE_VFS(hooks, fsrec, list, node, prev, mount, MOUNT);
232 FSH_REMOVE_VFS(hooks, fsrec, list, node, prev, unmount, UNMOUNT);
233 FSH_REMOVE_VFS(hooks, fsrec, list, node, prev, root, ROOT);
234 FSH_REMOVE_VFS(hooks, fsrec, list, node, prev, vget, VGET);
235 FSH_REMOVE_VFS(hooks, fsrec, list, node, prev, statfs, STATFS);
236
237 return (0);
238 }
239
240
241 int
242 fsh_callback_install(fsh_callback_t *fsh_callback)
243 {
244 fsh_callback_node_t *node;
245
277 node = node->fshcn_next;
278 }
279
280 if (node == NULL) {
281 rw_exit(&list->fshcl_lock);
282 return (0);
283 }
284
285 prev->fshcn_next = node->fshcn_next;
286 kmem_free(node, sizeof (*node));
287
288 rw_exit(&list->fshcl_lock);
289 return (0);
290 }
291
292
293
294
295 #define FSH_ENABLED(vfsp, enabled) \
296 do { \
297 rw_enter(&FSH_GET_FSREC(vfsp)->fshfsr_en_lock, RW_READER); \
298 *enabled = FSH_GET_FSREC(vfsp)->fshfsr_enabled; \
299 rw_exit(&FSH_GET_FSREC(vfsp)->fshfsr_en_lock); \
300 } while (0)
301
302 int
303 fsh_open(vnode_t **vpp, int mode, cred_t *cr, caller_context_t *ct)
304 {
305 fsh_list_t *list;
306 int enabled;
307 int ret;
308
309 FSH_ENABLED((*vpp)->v_vfsp, &enabled);
310 if (!enabled)
311 return ((*((*vpp)->v_op->vop_open))(vpp, mode, cr, ct));
312
313 list = &FSH_GET_FSREC((*vpp)->v_vfsp)->fshfsr_opv[FSH_VOP_OPEN];
314 rw_enter(&list->fshl_lock, RW_READER);
315 if (list->fshl_head == NULL)
316 ret = (*((*vpp)->v_op->vop_open))(vpp, mode, cr, ct);
317 else
318 ret = fsh_next_open(list->fshl_head, vpp, mode, cr, ct);
319 rw_exit(&list->fshl_lock);
320
321 return (ret);
322 }
323
324 int
325 fsh_close(vnode_t *vp, int flag, int count, offset_t offset, cred_t *cr,
326 caller_context_t *ct)
327 {
328 fsh_list_t *list;
329 int enabled;
330 int ret;
331
332 FSH_ENABLED(vp->v_vfsp, &enabled);
333 if (!enabled)
334 return ((*(vp->v_op->vop_close))(vp, flag, count, offset,
335 cr, ct));
336
337 list = &FSH_GET_FSREC(vp->v_vfsp)->fshfsr_opv[FSH_VOP_CLOSE];
338 rw_enter(&list->fshl_lock, RW_READER);
339 if (list->fshl_head == NULL)
340 ret = (*(vp->v_op->vop_close))(vp, flag, count, offset,
341 cr, ct);
342 else
343 ret = fsh_next_close(list->fshl_head, vp, flag, count,
344 offset, cr, ct);
345 rw_exit(&list->fshl_lock);
346
347 return (ret);
348 }
349
350 int
351 fsh_read(vnode_t *vp, uio_t *uiop, int ioflag, cred_t *cr,
352 caller_context_t *ct)
353 {
354 fsh_list_t *list;
355 int enabled;
356 int ret;
357
358 FSH_ENABLED(vp->v_vfsp, &enabled);
359 if (!enabled)
360 return ((*(vp->v_op->vop_read))(vp, uiop, ioflag, cr, ct));
361
362 list = &FSH_GET_FSREC(vp->v_vfsp)->fshfsr_opv[FSH_VOP_READ];
363 rw_enter(&list->fshl_lock, RW_READER);
364 if (list->fshl_head == NULL)
365 ret = (*(vp->v_op->vop_read))(vp, uiop, ioflag, cr, ct);
366 else
367 ret = fsh_next_read(list->fshl_head, vp, uiop, ioflag,
368 cr, ct);
369 rw_exit(&list->fshl_lock);
370
371 return (ret);
372 }
373
374 int
375 fsh_write(vnode_t *vp, uio_t *uiop, int ioflag, cred_t *cr,
376 caller_context_t *ct)
377 {
378 fsh_list_t *list;
379 int enabled;
380 int ret;
381
382 FSH_ENABLED(vp->v_vfsp, &enabled);
383 if (!enabled)
384 return ((*(vp->v_op->vop_write))(vp, uiop, ioflag, cr, ct));
385
386 list = &FSH_GET_FSREC(vp->v_vfsp)->fshfsr_opv[FSH_VOP_WRITE];
387 rw_enter(&list->fshl_lock, RW_READER);
388 if (list->fshl_head == NULL)
389 ret = (*(vp->v_op->vop_write))(vp, uiop, ioflag, cr, ct);
390 else
391 ret = fsh_next_write(list->fshl_head, vp, uiop, ioflag,
392 cr, ct);
393 rw_exit(&list->fshl_lock);
394
395 return (ret);
396 }
397
398 int
399 fsh_mount(vfs_t *vfsp, vnode_t *mvp, struct mounta *uap, cred_t *cr)
400 {
401 fsh_list_t *list;
402 int ret;
403
404 list = &FSH_GET_FSREC(vfsp)->fshfsr_opv[FSH_VFS_MOUNT];
405 rw_enter(&list->fshl_lock, RW_READER);
406 if (list->fshl_head == NULL)
407 ret = (*(vfsp->vfs_op->vfs_mount))(vfsp, mvp, uap, cr);
408 else
409 ret = fsh_next_mount(list->fshl_head, vfsp, mvp, uap,
410 cr);
411 rw_exit(&list->fshl_lock);
412
413 return (ret);
414 }
415
416 int
417 fsh_unmount(vfs_t *vfsp, int flag, cred_t *cr)
418 {
419 fsh_list_t *list;
420 int ret;
421
422 list = &FSH_GET_FSREC(vfsp)->fshfsr_opv[FSH_VFS_UNMOUNT];
423 rw_enter(&list->fshl_lock, RW_READER);
424 if (list->fshl_head == NULL)
425 ret = (*(vfsp->vfs_op->vfs_unmount))(vfsp, flag, cr);
426 else
427 ret = fsh_next_unmount(list->fshl_head, vfsp, flag, cr);
428 rw_exit(&list->fshl_lock);
429
430 return (ret);
431 }
432
433 int
434 fsh_root(vfs_t *vfsp, vnode_t **vpp)
435 {
436 fsh_list_t *list;
437 int ret;
438
439 list = &FSH_GET_FSREC(vfsp)->fshfsr_opv[FSH_VFS_ROOT];
440 rw_enter(&list->fshl_lock, RW_READER);
441 if (list->fshl_head == NULL)
442 ret = (*(vfsp->vfs_op->vfs_root))(vfsp, vpp);
443 else
444 ret = fsh_next_root(list->fshl_head, vfsp, vpp);
445 rw_exit(&list->fshl_lock);
446
447 return (ret);
448 }
449
450 int
451 fsh_statfs(vfs_t *vfsp, statvfs64_t *sp)
452 {
453 fsh_list_t *list;
454 int ret;
455
456 list = &FSH_GET_FSREC(vfsp)->fshfsr_opv[FSH_VFS_STATFS];
457 rw_enter(&list->fshl_lock, RW_READER);
458 if (list->fshl_head == NULL)
459 ret = (*(vfsp->vfs_op->vfs_statvfs))(vfsp, sp);
460 else
461 ret = fsh_next_statfs(list->fshl_head, vfsp, sp);
462 rw_exit(&list->fshl_lock);
463
464 return (ret);
465 }
466
467 int
468 fsh_vget(vfs_t *vfsp, vnode_t **vpp, fid_t *fidp)
469 {
470 fsh_list_t *list;
471 int ret;
472
473 list = &FSH_GET_FSREC(vfsp)->fshfsr_opv[FSH_VFS_VGET];
474 rw_enter(&list->fshl_lock, RW_READER);
475 if (list->fshl_head == NULL)
476 ret = (*(vfsp->vfs_op->vfs_vget))(vfsp, vpp, fidp);
477 else
478 ret = fsh_next_vget(list->fshl_head, vfsp, vpp, fidp);
479 rw_exit(&list->fshl_lock);
480
481 return (ret);
482 }
483
484 void
485 fsh_exec_create_callbacks(vfs_t *vfsp)
486 {
487 fsh_callback_node_t *node;
488 fsh_callback_t *callback;
489
490 rw_enter(&fsh_global_callback_list.fshcl_lock, RW_READER);
491 node = fsh_global_callback_list.fshcl_head;
492 while (node) {
493 callback = &node->fshcn_callback;
507 node = fsh_global_callback_list.fshcl_head;
508 while (node) {
509 callback = &node->fshcn_callback;
510 (*(callback->fshc_destroy))(vfsp, callback->fshc_arg);
511 node = node->fshcn_next;
512 }
513 rw_exit(&fsh_global_callback_list.fshcl_lock);
514 }
515
516 /* To be used ONLY in vfs_alloc() */
517 struct fsh_fsrecord *
518 fsh_fsrec_create()
519 {
520 struct fsh_fsrecord *fsrecp;
521 int i;
522
523 fsrecp = (fsh_fsrecord_t *) kmem_alloc(sizeof (*fsrecp), KM_SLEEP);
524 bzero(fsrecp, sizeof (*fsrecp));
525
526 rw_init(&fsrecp->fshfsr_en_lock, NULL, RW_DRIVER, NULL);
527 fsrecp->fshfsr_enabled = 1;
528
529 for (i = 0; i < FSH_SUPPORTED_OPS_COUNT; i++)
530 rw_init(&fsrecp->fshfsr_opv[i].fshl_lock, NULL, RW_DRIVER,
531 NULL);
532 return fsrecp;
533 }
534
535 /* To be used ONLY in vfs_free() */
536 void
537 fsh_fsrec_destroy(fsh_fsrecord_t *fsrecp)
538 {
539 int i;
540 fsh_node_t *node, *next_node;
541
542 for (i = 0; i < FSH_SUPPORTED_OPS_COUNT; i++) {
543 node = fsrecp->fshfsr_opv[i].fshl_head;
544 while (node) {
545 next_node = node->fshn_next;
546 kmem_free(node, sizeof (*node));
547 node = next_node;
548 }
549 rw_destroy(&fsrecp->fshfsr_opv[i].fshl_lock);
550 }
551 rw_destroy(&fsrecp->fshfsr_en_lock);
552 kmem_free(fsrecp, sizeof (*fsrecp));
|
78 } fsh_fsrecord_t;
79
80
81 typedef struct fsh_callback_node {
82 fsh_callback_t fshcn_callback;
83 struct fsh_callback_node *fshcn_next;
84 } fsh_callback_node_t;
85
86 typedef struct fsh_callback_list {
87 krwlock_t fshcl_lock;
88 fsh_callback_node_t *fshcl_head;
89 } fsh_callback_list_t;
90
91 fsh_callback_list_t fsh_global_callback_list;
92
93 /*
94 * It is assumed that VFS_HOLD() has been called before calling any of the
95 * fsh_fs_xxx()/fsh_hook_xxx() API. VFS_RELE() should be called after.
96 */
97
98 #define FSH_GET_FSRECP(vfsp) (vfsp->vfs_fshrecord)
99
100 int
101 fsh_fs_enable(vfs_t *vfsp)
102 {
103 fsh_fsrecord_t *fsrec;
104
105 fsrec = FSH_GET_FSRECP(vfsp);
106 rw_enter(&fsrec->fshfsr_en_lock, RW_WRITER);
107 fsrec->fshfsr_enabled = 1;
108 rw_exit(&fsrec->fshfsr_en_lock);
109
110 return (0);
111 }
112
113 int
114 fsh_fs_disable(vfs_t *vfsp)
115 {
116 fsh_fsrecord_t *fsrec;
117
118 fsrec = FSH_GET_FSRECP(vfsp);
119 rw_enter(&fsrec->fshfsr_en_lock, RW_WRITER);
120 fsrec->fshfsr_enabled = 0;
121 rw_exit(&fsrec->fshfsr_en_lock);
122
123 return (0);
124 }
125
126
127 #define FSH_INSTALL(type, hooks, fsrecp, listp, nodep, lower, upper) \
128 do { \
129 if (hooks->hook_##lower) { \
130 nodep = (fsh_node_t *) kmem_alloc(sizeof (*nodep), \
131 KM_SLEEP); \
132 nodep->fshn_hooki.fshi_fn.hook_##lower = \
133 hooks->hook_##lower; \
134 nodep->fshn_hooki.fshi_arg = hooks->arg; \
135 \
136 listp = &fsrecp->fshfsr_opv[FSH_##type##_##upper]; \
137 rw_enter(&listp->fshl_lock, RW_WRITER); \
138 nodep->fshn_next = \
139 fsrecp \
140 ->fshfsr_opv[FSH_##type##_##upper].fshl_head; \
141 fsrecp->fshfsr_opv[FSH_##type##_##upper].fshl_head \
142 = nodep; \
143 rw_exit(&listp->fshl_lock); \
144 } \
145 _NOTE(CONSTCOND) \
146 } while (0)
147
148 #define FSH_INSTALL_VN(hooks, fsrecp, listp, nodep, lower, upper) \
149 FSH_INSTALL(VOP, hooks, fsrecp, listp, nodep, lower, upper)
150
151 #define FSH_INSTALL_VFS(hooks, fsrecp, listp, nodep, lower, upper) \
152 FSH_INSTALL(VFS, hooks, fsrecp, listp, nodep, lower, upper)
153
154 int
155 fsh_hook_install(vfs_t *vfsp, fsh_t *hooks)
156 {
157 fsh_fsrecord_t *fsrec;
158 fsh_list_t *list;
159 fsh_node_t *node;
160
161 fsrec = FSH_GET_FSRECP(vfsp);
162
163 FSH_INSTALL_VN(hooks, fsrec, list, node, open, OPEN);
164 FSH_INSTALL_VN(hooks, fsrec, list, node, close, CLOSE);
165 FSH_INSTALL_VN(hooks, fsrec, list, node, read, READ);
166 FSH_INSTALL_VN(hooks, fsrec, list, node, write, WRITE);
167 FSH_INSTALL_VFS(hooks, fsrec, list, node, mount, MOUNT);
168 FSH_INSTALL_VFS(hooks, fsrec, list, node, unmount, UNMOUNT);
169 FSH_INSTALL_VFS(hooks, fsrec, list, node, root, ROOT);
170 FSH_INSTALL_VFS(hooks, fsrec, list, node, vget, VGET);
171 FSH_INSTALL_VFS(hooks, fsrec, list, node, statfs, STATFS);
172
173 return (0);
174 }
175
176
177 #define FSH_REMOVE(type, hooks, fsrec, list, node, prev, lower, upper) \
178 do { \
179 if (hooks->hook_ ## lower == NULL) \
180 break; \
181 \
191 while (node && \
192 !(node->fshn_hooki.fshi_fn.hook_ ## lower == \
193 hooks->hook_ ## lower && \
194 node->fshn_hooki.fshi_arg == hooks->arg)) { \
195 prev = node; \
196 node = node->fshn_next; \
197 } \
198 \
199 if (node == NULL) { \
200 rw_exit(&list->fshl_lock); \
201 break; \
202 } \
203 \
204 if (node == list->fshl_head) \
205 list->fshl_head = node->fshn_next; \
206 else \
207 prev->fshn_next = node->fshn_next; \
208 rw_exit(&list->fshl_lock); \
209 \
210 kmem_free(node, sizeof (*node)); \
211 _NOTE(CONSTCOND) \
212 } while (0)
213
214 #define FSH_REMOVE_VN(hooks, fsrec, list, node, prev, lower, upper) \
215 FSH_REMOVE(VOP, hooks, fsrec, list, node, prev, lower, upper)
216
217 #define FSH_REMOVE_VFS(hooks, fsrec, list, node, prev, lower, upper) \
218 FSH_REMOVE(VFS, hooks, fsrec, list, node, prev, lower, upper)
219
220 int
221 fsh_hook_remove(vfs_t *vfsp, fsh_t *hooks)
222 {
223 fsh_fsrecord_t *fsrec;
224 fsh_list_t *list;
225 fsh_node_t *node;
226 fsh_node_t *prev;
227
228 fsrec = FSH_GET_FSRECP(vfsp);
229
230 FSH_REMOVE_VN(hooks, fsrec, list, node, prev, open, OPEN);
231 FSH_REMOVE_VN(hooks, fsrec, list, node, prev, close, CLOSE);
232 FSH_REMOVE_VN(hooks, fsrec, list, node, prev, read, READ);
233 FSH_REMOVE_VN(hooks, fsrec, list, node, prev, write, WRITE);
234 FSH_REMOVE_VFS(hooks, fsrec, list, node, prev, mount, MOUNT);
235 FSH_REMOVE_VFS(hooks, fsrec, list, node, prev, unmount, UNMOUNT);
236 FSH_REMOVE_VFS(hooks, fsrec, list, node, prev, root, ROOT);
237 FSH_REMOVE_VFS(hooks, fsrec, list, node, prev, vget, VGET);
238 FSH_REMOVE_VFS(hooks, fsrec, list, node, prev, statfs, STATFS);
239
240 return (0);
241 }
242
243
244 int
245 fsh_callback_install(fsh_callback_t *fsh_callback)
246 {
247 fsh_callback_node_t *node;
248
280 node = node->fshcn_next;
281 }
282
283 if (node == NULL) {
284 rw_exit(&list->fshcl_lock);
285 return (0);
286 }
287
288 prev->fshcn_next = node->fshcn_next;
289 kmem_free(node, sizeof (*node));
290
291 rw_exit(&list->fshcl_lock);
292 return (0);
293 }
294
295
296
297
298 #define FSH_ENABLED(vfsp, enabled) \
299 do { \
300 rw_enter(&FSH_GET_FSRECP(vfsp)->fshfsr_en_lock, RW_READER); \
301 *enabled = FSH_GET_FSRECP(vfsp)->fshfsr_enabled; \
302 rw_exit(&FSH_GET_FSRECP(vfsp)->fshfsr_en_lock); \
303 _NOTE(CONSTCOND) \
304 } while (0)
305
306 int
307 fsh_open(vnode_t **vpp, int mode, cred_t *cr, caller_context_t *ct)
308 {
309 fsh_list_t *list;
310 int enabled;
311 int ret;
312
313 FSH_ENABLED((*vpp)->v_vfsp, &enabled);
314 if (!enabled)
315 return ((*((*vpp)->v_op->vop_open))(vpp, mode, cr, ct));
316
317 list = &FSH_GET_FSRECP((*vpp)->v_vfsp)->fshfsr_opv[FSH_VOP_OPEN];
318 rw_enter(&list->fshl_lock, RW_READER);
319 if (list->fshl_head == NULL)
320 ret = (*((*vpp)->v_op->vop_open))(vpp, mode, cr, ct);
321 else
322 ret = fsh_next_open(list->fshl_head, vpp, mode, cr, ct);
323 rw_exit(&list->fshl_lock);
324
325 return (ret);
326 }
327
328 int
329 fsh_close(vnode_t *vp, int flag, int count, offset_t offset, cred_t *cr,
330 caller_context_t *ct)
331 {
332 fsh_list_t *list;
333 int enabled;
334 int ret;
335
336 FSH_ENABLED(vp->v_vfsp, &enabled);
337 if (!enabled)
338 return ((*(vp->v_op->vop_close))(vp, flag, count, offset,
339 cr, ct));
340
341 list = &FSH_GET_FSRECP(vp->v_vfsp)->fshfsr_opv[FSH_VOP_CLOSE];
342 rw_enter(&list->fshl_lock, RW_READER);
343 if (list->fshl_head == NULL)
344 ret = (*(vp->v_op->vop_close))(vp, flag, count, offset,
345 cr, ct);
346 else
347 ret = fsh_next_close(list->fshl_head, vp, flag, count,
348 offset, cr, ct);
349 rw_exit(&list->fshl_lock);
350
351 return (ret);
352 }
353
354 int
355 fsh_read(vnode_t *vp, uio_t *uiop, int ioflag, cred_t *cr,
356 caller_context_t *ct)
357 {
358 fsh_list_t *list;
359 int enabled;
360 int ret;
361
362 FSH_ENABLED(vp->v_vfsp, &enabled);
363 if (!enabled)
364 return ((*(vp->v_op->vop_read))(vp, uiop, ioflag, cr, ct));
365
366 list = &FSH_GET_FSRECP(vp->v_vfsp)->fshfsr_opv[FSH_VOP_READ];
367 rw_enter(&list->fshl_lock, RW_READER);
368 if (list->fshl_head == NULL)
369 ret = (*(vp->v_op->vop_read))(vp, uiop, ioflag, cr, ct);
370 else
371 ret = fsh_next_read(list->fshl_head, vp, uiop, ioflag,
372 cr, ct);
373 rw_exit(&list->fshl_lock);
374
375 return (ret);
376 }
377
378 int
379 fsh_write(vnode_t *vp, uio_t *uiop, int ioflag, cred_t *cr,
380 caller_context_t *ct)
381 {
382 fsh_list_t *list;
383 int enabled;
384 int ret;
385
386 FSH_ENABLED(vp->v_vfsp, &enabled);
387 if (!enabled)
388 return ((*(vp->v_op->vop_write))(vp, uiop, ioflag, cr, ct));
389
390 list = &FSH_GET_FSRECP(vp->v_vfsp)->fshfsr_opv[FSH_VOP_WRITE];
391 rw_enter(&list->fshl_lock, RW_READER);
392 if (list->fshl_head == NULL)
393 ret = (*(vp->v_op->vop_write))(vp, uiop, ioflag, cr, ct);
394 else
395 ret = fsh_next_write(list->fshl_head, vp, uiop, ioflag,
396 cr, ct);
397 rw_exit(&list->fshl_lock);
398
399 return (ret);
400 }
401
402 int
403 fsh_mount(vfs_t *vfsp, vnode_t *mvp, struct mounta *uap, cred_t *cr)
404 {
405 fsh_list_t *list;
406 int ret;
407
408 list = &FSH_GET_FSRECP(vfsp)->fshfsr_opv[FSH_VFS_MOUNT];
409 rw_enter(&list->fshl_lock, RW_READER);
410 if (list->fshl_head == NULL)
411 ret = (*(vfsp->vfs_op->vfs_mount))(vfsp, mvp, uap, cr);
412 else
413 ret = fsh_next_mount(list->fshl_head, vfsp, mvp, uap,
414 cr);
415 rw_exit(&list->fshl_lock);
416
417 return (ret);
418 }
419
420 int
421 fsh_unmount(vfs_t *vfsp, int flag, cred_t *cr)
422 {
423 fsh_list_t *list;
424 int ret;
425
426 list = &FSH_GET_FSRECP(vfsp)->fshfsr_opv[FSH_VFS_UNMOUNT];
427 rw_enter(&list->fshl_lock, RW_READER);
428 if (list->fshl_head == NULL)
429 ret = (*(vfsp->vfs_op->vfs_unmount))(vfsp, flag, cr);
430 else
431 ret = fsh_next_unmount(list->fshl_head, vfsp, flag, cr);
432 rw_exit(&list->fshl_lock);
433
434 return (ret);
435 }
436
437 int
438 fsh_root(vfs_t *vfsp, vnode_t **vpp)
439 {
440 fsh_list_t *list;
441 int ret;
442
443 list = &FSH_GET_FSRECP(vfsp)->fshfsr_opv[FSH_VFS_ROOT];
444 rw_enter(&list->fshl_lock, RW_READER);
445 if (list->fshl_head == NULL)
446 ret = (*(vfsp->vfs_op->vfs_root))(vfsp, vpp);
447 else
448 ret = fsh_next_root(list->fshl_head, vfsp, vpp);
449 rw_exit(&list->fshl_lock);
450
451 return (ret);
452 }
453
454 int
455 fsh_statfs(vfs_t *vfsp, statvfs64_t *sp)
456 {
457 fsh_list_t *list;
458 int ret;
459
460 list = &FSH_GET_FSRECP(vfsp)->fshfsr_opv[FSH_VFS_STATFS];
461 rw_enter(&list->fshl_lock, RW_READER);
462 if (list->fshl_head == NULL)
463 ret = (*(vfsp->vfs_op->vfs_statvfs))(vfsp, sp);
464 else
465 ret = fsh_next_statfs(list->fshl_head, vfsp, sp);
466 rw_exit(&list->fshl_lock);
467
468 return (ret);
469 }
470
471 int
472 fsh_vget(vfs_t *vfsp, vnode_t **vpp, fid_t *fidp)
473 {
474 fsh_list_t *list;
475 int ret;
476
477 list = &FSH_GET_FSRECP(vfsp)->fshfsr_opv[FSH_VFS_VGET];
478 rw_enter(&list->fshl_lock, RW_READER);
479 if (list->fshl_head == NULL)
480 ret = (*(vfsp->vfs_op->vfs_vget))(vfsp, vpp, fidp);
481 else
482 ret = fsh_next_vget(list->fshl_head, vfsp, vpp, fidp);
483 rw_exit(&list->fshl_lock);
484
485 return (ret);
486 }
487
488 void
489 fsh_exec_create_callbacks(vfs_t *vfsp)
490 {
491 fsh_callback_node_t *node;
492 fsh_callback_t *callback;
493
494 rw_enter(&fsh_global_callback_list.fshcl_lock, RW_READER);
495 node = fsh_global_callback_list.fshcl_head;
496 while (node) {
497 callback = &node->fshcn_callback;
511 node = fsh_global_callback_list.fshcl_head;
512 while (node) {
513 callback = &node->fshcn_callback;
514 (*(callback->fshc_destroy))(vfsp, callback->fshc_arg);
515 node = node->fshcn_next;
516 }
517 rw_exit(&fsh_global_callback_list.fshcl_lock);
518 }
519
520 /* To be used ONLY in vfs_alloc() */
521 struct fsh_fsrecord *
522 fsh_fsrec_create()
523 {
524 struct fsh_fsrecord *fsrecp;
525 int i;
526
527 fsrecp = (fsh_fsrecord_t *) kmem_alloc(sizeof (*fsrecp), KM_SLEEP);
528 bzero(fsrecp, sizeof (*fsrecp));
529
530 rw_init(&fsrecp->fshfsr_en_lock, NULL, RW_DRIVER, NULL);
531 fsrecp->fshfsr_enabled = 0; // DEBUG
532
533 for (i = 0; i < FSH_SUPPORTED_OPS_COUNT; i++)
534 rw_init(&fsrecp->fshfsr_opv[i].fshl_lock, NULL, RW_DRIVER,
535 NULL);
536 return (fsrecp);
537 }
538
539 /* To be used ONLY in vfs_free() */
540 void
541 fsh_fsrec_destroy(fsh_fsrecord_t *fsrecp)
542 {
543 int i;
544 fsh_node_t *node, *next_node;
545
546 for (i = 0; i < FSH_SUPPORTED_OPS_COUNT; i++) {
547 node = fsrecp->fshfsr_opv[i].fshl_head;
548 while (node) {
549 next_node = node->fshn_next;
550 kmem_free(node, sizeof (*node));
551 node = next_node;
552 }
553 rw_destroy(&fsrecp->fshfsr_opv[i].fshl_lock);
554 }
555 rw_destroy(&fsrecp->fshfsr_en_lock);
556 kmem_free(fsrecp, sizeof (*fsrecp));
|