Print this page
fixes to fsh


  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));