- /*
- * Force every operations vector to have a default routine.
- */
- opv_desc_vector = *opv_desc_vector_p;
- if (opv_desc_vector[VOFFSET(vnop_default)] == NULL)
- panic("vfs_fsadd: operation vector without default routine.");
- for (j = 0; j < vfs_opv_numops; j++)
- if (opv_desc_vector[j] == NULL)
- opv_desc_vector[j] =
- opv_desc_vector[VOFFSET(vnop_default)];
+ /* Silently skip known-disabled operations */
+ if (opve_descp->opve_op->vdesc_flags & VDESC_DISABLED) {
+ printf("vfs_fsadd: Ignoring reference in %p to disabled operation %s.\n",
+ vfe->vfe_opvdescs[i], opve_descp->opve_op->vdesc_name);
+ continue;
+ }
+
+ /*
+ * Sanity check: is this operation listed
+ * in the list of operations? We check this
+ * by seeing if its offset is zero. Since
+ * the default routine should always be listed
+ * first, it should be the only one with a zero
+ * offset. Any other operation with a zero
+ * offset is probably not listed in
+ * vfs_op_descs, and so is probably an error.
+ *
+ * A panic here means the layer programmer
+ * has committed the all-too common bug
+ * of adding a new operation to the layer's
+ * list of vnode operations but
+ * not adding the operation to the system-wide
+ * list of supported operations.
+ */
+ if (opve_descp->opve_op->vdesc_offset == 0 &&
+ opve_descp->opve_op != VDESC(vnop_default)) {
+ printf("vfs_fsadd: operation %s not listed in %s.\n",
+ opve_descp->opve_op->vdesc_name,
+ "vfs_op_descs");
+ panic("vfs_fsadd: bad operation");
+ }
+ /*
+ * Fill in this entry.
+ */
+ opv_desc_vector[opve_descp->opve_op->vdesc_offset] =
+ opve_descp->opve_impl;
+ }
+
+
+ /*
+ * Finally, go back and replace unfilled routines
+ * with their default. (Sigh, an O(n^3) algorithm. I
+ * could make it better, but that'd be work, and n is small.)
+ */
+ opv_desc_vector_p = vfe->vfe_opvdescs[i]->opv_desc_vector_p;
+
+ /*
+ * Force every operations vector to have a default routine.
+ */
+ opv_desc_vector = *opv_desc_vector_p;
+ if (opv_desc_vector[VOFFSET(vnop_default)] == NULL) {
+ panic("vfs_fsadd: operation vector without default routine.");
+ }
+ for (j = 0; j < vfs_opv_numops; j++) {
+ if (opv_desc_vector[j] == NULL) {
+ opv_desc_vector[j] =
+ opv_desc_vector[VOFFSET(vnop_default)];
+ }
+ }
+ } /* end of each vnodeopv_desc parsing */