Register a new filesystem type in the global table */
| 372 | |
| 373 | /* Register a new filesystem type in the global table */ |
| 374 | static int |
| 375 | vfs_register(struct vfsconf *vfc) |
| 376 | { |
| 377 | struct sysctl_oid *oidp; |
| 378 | struct vfsops *vfsops; |
| 379 | static int once; |
| 380 | struct vfsconf *tvfc; |
| 381 | uint32_t hashval; |
| 382 | int secondpass; |
| 383 | |
| 384 | if (!once) { |
| 385 | vattr_null(&va_null); |
| 386 | once = 1; |
| 387 | } |
| 388 | |
| 389 | if (vfc->vfc_version != VFS_VERSION) { |
| 390 | printf("ERROR: filesystem %s, unsupported ABI version %x\n", |
| 391 | vfc->vfc_name, vfc->vfc_version); |
| 392 | return (EINVAL); |
| 393 | } |
| 394 | vfsconf_lock(); |
| 395 | if (vfs_byname_locked(vfc->vfc_name) != NULL) { |
| 396 | vfsconf_unlock(); |
| 397 | return (EEXIST); |
| 398 | } |
| 399 | |
| 400 | if (vfs_typenumhash != 0) { |
| 401 | /* |
| 402 | * Calculate a hash on vfc_name to use for vfc_typenum. Unless |
| 403 | * all of 1<->255 are assigned, it is limited to 8bits since |
| 404 | * that is what ZFS uses from vfc_typenum and is also the |
| 405 | * preferred range for vfs_getnewfsid(). |
| 406 | */ |
| 407 | hashval = fnv_32_str(vfc->vfc_name, FNV1_32_INIT); |
| 408 | hashval &= 0xff; |
| 409 | secondpass = 0; |
| 410 | do { |
| 411 | /* Look for and fix any collision. */ |
| 412 | TAILQ_FOREACH(tvfc, &vfsconf, vfc_list) { |
| 413 | if (hashval == tvfc->vfc_typenum) { |
| 414 | if (hashval == 255 && secondpass == 0) { |
| 415 | hashval = 1; |
| 416 | secondpass = 1; |
| 417 | } else |
| 418 | hashval++; |
| 419 | break; |
| 420 | } |
| 421 | } |
| 422 | } while (tvfc != NULL); |
| 423 | vfc->vfc_typenum = hashval; |
| 424 | if (vfc->vfc_typenum >= maxvfsconf) |
| 425 | maxvfsconf = vfc->vfc_typenum + 1; |
| 426 | } else |
| 427 | vfc->vfc_typenum = maxvfsconf++; |
| 428 | TAILQ_INSERT_TAIL(&vfsconf, vfc, vfc_list); |
| 429 | |
| 430 | /* |
| 431 | * Initialise unused ``struct vfsops'' fields, to use |
no test coverage detected