The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/kern/vfs_init.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * SPDX-License-Identifier: BSD-3-Clause
    3  *
    4  * Copyright (c) 1989, 1993
    5  *      The Regents of the University of California.  All rights reserved.
    6  *
    7  * This code is derived from software contributed
    8  * to Berkeley by John Heidemann of the UCLA Ficus project.
    9  *
   10  * Source: * @(#)i405_init.c 2.10 92/04/27 UCLA Ficus project
   11  *
   12  * Redistribution and use in source and binary forms, with or without
   13  * modification, are permitted provided that the following conditions
   14  * are met:
   15  * 1. Redistributions of source code must retain the above copyright
   16  *    notice, this list of conditions and the following disclaimer.
   17  * 2. Redistributions in binary form must reproduce the above copyright
   18  *    notice, this list of conditions and the following disclaimer in the
   19  *    documentation and/or other materials provided with the distribution.
   20  * 3. Neither the name of the University nor the names of its contributors
   21  *    may be used to endorse or promote products derived from this software
   22  *    without specific prior written permission.
   23  *
   24  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   25  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   26  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   27  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   28  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   29  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   30  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   31  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   32  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   33  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   34  * SUCH DAMAGE.
   35  *
   36  *      @(#)vfs_init.c  8.3 (Berkeley) 1/4/94
   37  */
   38 
   39 #include <sys/cdefs.h>
   40 __FBSDID("$FreeBSD$");
   41 
   42 #include <sys/param.h>
   43 #include <sys/systm.h>
   44 #include <sys/fnv_hash.h>
   45 #include <sys/jail.h>
   46 #include <sys/kernel.h>
   47 #include <sys/linker.h>
   48 #include <sys/mount.h>
   49 #include <sys/proc.h>
   50 #include <sys/sx.h>
   51 #include <sys/syscallsubr.h>
   52 #include <sys/sysctl.h>
   53 #include <sys/vnode.h>
   54 #include <sys/malloc.h>
   55 
   56 static int      vfs_register(struct vfsconf *);
   57 static int      vfs_unregister(struct vfsconf *);
   58 
   59 MALLOC_DEFINE(M_VNODE, "vnodes", "Dynamically allocated vnodes");
   60 
   61 /*
   62  * The highest defined VFS number.
   63  */
   64 int maxvfsconf = VFS_GENERIC + 1;
   65 
   66 /*
   67  * Single-linked list of configured VFSes.
   68  * New entries are added/deleted by vfs_register()/vfs_unregister()
   69  */
   70 struct vfsconfhead vfsconf = TAILQ_HEAD_INITIALIZER(vfsconf);
   71 struct sx vfsconf_sx;
   72 SX_SYSINIT(vfsconf, &vfsconf_sx, "vfsconf");
   73 
   74 /*
   75  * Loader.conf variable vfs.typenumhash enables setting vfc_typenum using a hash
   76  * calculation on vfc_name, so that it doesn't change when file systems are
   77  * loaded in a different order. This will avoid the NFS server file handles from
   78  * changing for file systems that use vfc_typenum in their fsid.
   79  */
   80 static int      vfs_typenumhash = 1;
   81 SYSCTL_INT(_vfs, OID_AUTO, typenumhash, CTLFLAG_RDTUN, &vfs_typenumhash, 0,
   82     "Set vfc_typenum using a hash calculation on vfc_name, so that it does not"
   83     " change when file systems are loaded in a different order.");
   84 
   85 /*
   86  * A Zen vnode attribute structure.
   87  *
   88  * Initialized when the first filesystem registers by vfs_register().
   89  */
   90 struct vattr va_null;
   91 
   92 /*
   93  * vfs_init.c
   94  *
   95  * Allocate and fill in operations vectors.
   96  *
   97  * An undocumented feature of this approach to defining operations is that
   98  * there can be multiple entries in vfs_opv_descs for the same operations
   99  * vector. This allows third parties to extend the set of operations
  100  * supported by another layer in a binary compatibile way. For example,
  101  * assume that NFS needed to be modified to support Ficus. NFS has an entry
  102  * (probably nfs_vnopdeop_decls) declaring all the operations NFS supports by
  103  * default. Ficus could add another entry (ficus_nfs_vnodeop_decl_entensions)
  104  * listing those new operations Ficus adds to NFS, all without modifying the
  105  * NFS code. (Of couse, the OTW NFS protocol still needs to be munged, but
  106  * that is a(whole)nother story.) This is a feature.
  107  */
  108 
  109 /*
  110  * Routines having to do with the management of the vnode table.
  111  */
  112 
  113 static struct vfsconf *
  114 vfs_byname_locked(const char *name)
  115 {
  116         struct vfsconf *vfsp;
  117 
  118         sx_assert(&vfsconf_sx, SA_LOCKED);
  119         if (!strcmp(name, "ffs"))
  120                 name = "ufs";
  121         TAILQ_FOREACH(vfsp, &vfsconf, vfc_list) {
  122                 if (!strcmp(name, vfsp->vfc_name))
  123                         return (vfsp);
  124         }
  125         return (NULL);
  126 }
  127 
  128 struct vfsconf *
  129 vfs_byname(const char *name)
  130 {
  131         struct vfsconf *vfsp;
  132 
  133         vfsconf_slock();
  134         vfsp = vfs_byname_locked(name);
  135         vfsconf_sunlock();
  136         return (vfsp);
  137 }
  138 
  139 struct vfsconf *
  140 vfs_byname_kld(const char *fstype, struct thread *td, int *error)
  141 {
  142         struct vfsconf *vfsp;
  143         int fileid, loaded;
  144 
  145         vfsp = vfs_byname(fstype);
  146         if (vfsp != NULL)
  147                 return (vfsp);
  148 
  149         /* Try to load the respective module. */
  150         *error = kern_kldload(td, fstype, &fileid);
  151         loaded = (*error == 0);
  152         if (*error == EEXIST)
  153                 *error = 0;
  154         if (*error)
  155                 return (NULL);
  156 
  157         /* Look up again to see if the VFS was loaded. */
  158         vfsp = vfs_byname(fstype);
  159         if (vfsp == NULL) {
  160                 if (loaded)
  161                         (void)kern_kldunload(td, fileid, LINKER_UNLOAD_FORCE);
  162                 *error = ENODEV;
  163                 return (NULL);
  164         }
  165         return (vfsp);
  166 }
  167 
  168 static int
  169 vfs_mount_sigdefer(struct mount *mp)
  170 {
  171         int prev_stops, rc;
  172 
  173         TSRAW(curthread, TS_ENTER, "VFS_MOUNT", mp->mnt_vfc->vfc_name);
  174         prev_stops = sigdeferstop(SIGDEFERSTOP_SILENT);
  175         rc = (*mp->mnt_vfc->vfc_vfsops_sd->vfs_mount)(mp);
  176         sigallowstop(prev_stops);
  177         TSRAW(curthread, TS_EXIT, "VFS_MOUNT", mp->mnt_vfc->vfc_name);
  178         return (rc);
  179 }
  180 
  181 static int
  182 vfs_unmount_sigdefer(struct mount *mp, int mntflags)
  183 {
  184         int prev_stops, rc;
  185 
  186         prev_stops = sigdeferstop(SIGDEFERSTOP_SILENT);
  187         rc = (*mp->mnt_vfc->vfc_vfsops_sd->vfs_unmount)(mp, mntflags);
  188         sigallowstop(prev_stops);
  189         return (rc);
  190 }
  191 
  192 static int
  193 vfs_root_sigdefer(struct mount *mp, int flags, struct vnode **vpp)
  194 {
  195         int prev_stops, rc;
  196 
  197         prev_stops = sigdeferstop(SIGDEFERSTOP_SILENT);
  198         rc = (*mp->mnt_vfc->vfc_vfsops_sd->vfs_root)(mp, flags, vpp);
  199         sigallowstop(prev_stops);
  200         return (rc);
  201 }
  202 
  203 static int
  204 vfs_cachedroot_sigdefer(struct mount *mp, int flags, struct vnode **vpp)
  205 {
  206         int prev_stops, rc;
  207 
  208         prev_stops = sigdeferstop(SIGDEFERSTOP_SILENT);
  209         rc = (*mp->mnt_vfc->vfc_vfsops_sd->vfs_cachedroot)(mp, flags, vpp);
  210         sigallowstop(prev_stops);
  211         return (rc);
  212 }
  213 
  214 static int
  215 vfs_quotactl_sigdefer(struct mount *mp, int cmd, uid_t uid, void *arg,
  216     bool *mp_busy)
  217 {
  218         int prev_stops, rc;
  219 
  220         prev_stops = sigdeferstop(SIGDEFERSTOP_SILENT);
  221         rc = (*mp->mnt_vfc->vfc_vfsops_sd->vfs_quotactl)(mp, cmd, uid, arg,
  222             mp_busy);
  223         sigallowstop(prev_stops);
  224         return (rc);
  225 }
  226 
  227 static int
  228 vfs_statfs_sigdefer(struct mount *mp, struct statfs *sbp)
  229 {
  230         int prev_stops, rc;
  231 
  232         prev_stops = sigdeferstop(SIGDEFERSTOP_SILENT);
  233         rc = (*mp->mnt_vfc->vfc_vfsops_sd->vfs_statfs)(mp, sbp);
  234         sigallowstop(prev_stops);
  235         return (rc);
  236 }
  237 
  238 static int
  239 vfs_sync_sigdefer(struct mount *mp, int waitfor)
  240 {
  241         int prev_stops, rc;
  242 
  243         prev_stops = sigdeferstop(SIGDEFERSTOP_SILENT);
  244         rc = (*mp->mnt_vfc->vfc_vfsops_sd->vfs_sync)(mp, waitfor);
  245         sigallowstop(prev_stops);
  246         return (rc);
  247 }
  248 
  249 static int
  250 vfs_vget_sigdefer(struct mount *mp, ino_t ino, int flags, struct vnode **vpp)
  251 {
  252         int prev_stops, rc;
  253 
  254         prev_stops = sigdeferstop(SIGDEFERSTOP_SILENT);
  255         rc = (*mp->mnt_vfc->vfc_vfsops_sd->vfs_vget)(mp, ino, flags, vpp);
  256         sigallowstop(prev_stops);
  257         return (rc);
  258 }
  259 
  260 static int
  261 vfs_fhtovp_sigdefer(struct mount *mp, struct fid *fidp, int flags,
  262     struct vnode **vpp)
  263 {
  264         int prev_stops, rc;
  265 
  266         prev_stops = sigdeferstop(SIGDEFERSTOP_SILENT);
  267         rc = (*mp->mnt_vfc->vfc_vfsops_sd->vfs_fhtovp)(mp, fidp, flags, vpp);
  268         sigallowstop(prev_stops);
  269         return (rc);
  270 }
  271 
  272 static int
  273 vfs_checkexp_sigdefer(struct mount *mp, struct sockaddr *nam, uint64_t *exflg,
  274     struct ucred **credp, int *numsecflavors, int *secflavors)
  275 {
  276         int prev_stops, rc;
  277 
  278         prev_stops = sigdeferstop(SIGDEFERSTOP_SILENT);
  279         rc = (*mp->mnt_vfc->vfc_vfsops_sd->vfs_checkexp)(mp, nam, exflg, credp,
  280             numsecflavors, secflavors);
  281         sigallowstop(prev_stops);
  282         return (rc);
  283 }
  284 
  285 static int
  286 vfs_extattrctl_sigdefer(struct mount *mp, int cmd, struct vnode *filename_vp,
  287     int attrnamespace, const char *attrname)
  288 {
  289         int prev_stops, rc;
  290 
  291         prev_stops = sigdeferstop(SIGDEFERSTOP_SILENT);
  292         rc = (*mp->mnt_vfc->vfc_vfsops_sd->vfs_extattrctl)(mp, cmd,
  293             filename_vp, attrnamespace, attrname);
  294         sigallowstop(prev_stops);
  295         return (rc);
  296 }
  297 
  298 static int
  299 vfs_sysctl_sigdefer(struct mount *mp, fsctlop_t op, struct sysctl_req *req)
  300 {
  301         int prev_stops, rc;
  302 
  303         prev_stops = sigdeferstop(SIGDEFERSTOP_SILENT);
  304         rc = (*mp->mnt_vfc->vfc_vfsops_sd->vfs_sysctl)(mp, op, req);
  305         sigallowstop(prev_stops);
  306         return (rc);
  307 }
  308 
  309 static void
  310 vfs_susp_clean_sigdefer(struct mount *mp)
  311 {
  312         int prev_stops;
  313 
  314         if (*mp->mnt_vfc->vfc_vfsops_sd->vfs_susp_clean == NULL)
  315                 return;
  316         prev_stops = sigdeferstop(SIGDEFERSTOP_SILENT);
  317         (*mp->mnt_vfc->vfc_vfsops_sd->vfs_susp_clean)(mp);
  318         sigallowstop(prev_stops);
  319 }
  320 
  321 static void
  322 vfs_reclaim_lowervp_sigdefer(struct mount *mp, struct vnode *vp)
  323 {
  324         int prev_stops;
  325 
  326         if (*mp->mnt_vfc->vfc_vfsops_sd->vfs_reclaim_lowervp == NULL)
  327                 return;
  328         prev_stops = sigdeferstop(SIGDEFERSTOP_SILENT);
  329         (*mp->mnt_vfc->vfc_vfsops_sd->vfs_reclaim_lowervp)(mp, vp);
  330         sigallowstop(prev_stops);
  331 }
  332 
  333 static void
  334 vfs_unlink_lowervp_sigdefer(struct mount *mp, struct vnode *vp)
  335 {
  336         int prev_stops;
  337 
  338         if (*mp->mnt_vfc->vfc_vfsops_sd->vfs_unlink_lowervp == NULL)
  339                 return;
  340         prev_stops = sigdeferstop(SIGDEFERSTOP_SILENT);
  341         (*(mp)->mnt_vfc->vfc_vfsops_sd->vfs_unlink_lowervp)(mp, vp);
  342         sigallowstop(prev_stops);
  343 }
  344 
  345 static void
  346 vfs_purge_sigdefer(struct mount *mp)
  347 {
  348         int prev_stops;
  349 
  350         prev_stops = sigdeferstop(SIGDEFERSTOP_SILENT);
  351         (*mp->mnt_vfc->vfc_vfsops_sd->vfs_purge)(mp);
  352         sigallowstop(prev_stops);
  353 }
  354 
  355 static int
  356 vfs_report_lockf_sigdefer(struct mount *mp, struct sbuf *sb)
  357 {
  358         int prev_stops, rc;
  359 
  360         prev_stops = sigdeferstop(SIGDEFERSTOP_SILENT);
  361         rc = (*mp->mnt_vfc->vfc_vfsops_sd->vfs_report_lockf)(mp, sb);
  362         sigallowstop(prev_stops);
  363         return (rc);
  364 }
  365 
  366 static struct vfsops vfsops_sigdefer = {
  367         .vfs_mount =            vfs_mount_sigdefer,
  368         .vfs_unmount =          vfs_unmount_sigdefer,
  369         .vfs_root =             vfs_root_sigdefer,
  370         .vfs_cachedroot =       vfs_cachedroot_sigdefer,
  371         .vfs_quotactl =         vfs_quotactl_sigdefer,
  372         .vfs_statfs =           vfs_statfs_sigdefer,
  373         .vfs_sync =             vfs_sync_sigdefer,
  374         .vfs_vget =             vfs_vget_sigdefer,
  375         .vfs_fhtovp =           vfs_fhtovp_sigdefer,
  376         .vfs_checkexp =         vfs_checkexp_sigdefer,
  377         .vfs_extattrctl =       vfs_extattrctl_sigdefer,
  378         .vfs_sysctl =           vfs_sysctl_sigdefer,
  379         .vfs_susp_clean =       vfs_susp_clean_sigdefer,
  380         .vfs_reclaim_lowervp =  vfs_reclaim_lowervp_sigdefer,
  381         .vfs_unlink_lowervp =   vfs_unlink_lowervp_sigdefer,
  382         .vfs_purge =            vfs_purge_sigdefer,
  383         .vfs_report_lockf =     vfs_report_lockf_sigdefer,
  384 };
  385 
  386 /* Register a new filesystem type in the global table */
  387 static int
  388 vfs_register(struct vfsconf *vfc)
  389 {
  390         struct sysctl_oid *oidp;
  391         struct vfsops *vfsops;
  392         static int once;
  393         struct vfsconf *tvfc;
  394         uint32_t hashval;
  395         int secondpass;
  396 
  397         if (!once) {
  398                 vattr_null(&va_null);
  399                 once = 1;
  400         }
  401 
  402         if (vfc->vfc_version != VFS_VERSION) {
  403                 printf("ERROR: filesystem %s, unsupported ABI version %x\n",
  404                     vfc->vfc_name, vfc->vfc_version);
  405                 return (EINVAL);
  406         }
  407         vfsconf_lock();
  408         if (vfs_byname_locked(vfc->vfc_name) != NULL) {
  409                 vfsconf_unlock();
  410                 return (EEXIST);
  411         }
  412 
  413         if (vfs_typenumhash != 0) {
  414                 /*
  415                  * Calculate a hash on vfc_name to use for vfc_typenum. Unless
  416                  * all of 1<->255 are assigned, it is limited to 8bits since
  417                  * that is what ZFS uses from vfc_typenum and is also the
  418                  * preferred range for vfs_getnewfsid().
  419                  */
  420                 hashval = fnv_32_str(vfc->vfc_name, FNV1_32_INIT);
  421                 hashval &= 0xff;
  422                 secondpass = 0;
  423                 do {
  424                         /* Look for and fix any collision. */
  425                         TAILQ_FOREACH(tvfc, &vfsconf, vfc_list) {
  426                                 if (hashval == tvfc->vfc_typenum) {
  427                                         if (hashval == 255 && secondpass == 0) {
  428                                                 hashval = 1;
  429                                                 secondpass = 1;
  430                                         } else
  431                                                 hashval++;
  432                                         break;
  433                                 }
  434                         }
  435                 } while (tvfc != NULL);
  436                 vfc->vfc_typenum = hashval;
  437                 if (vfc->vfc_typenum >= maxvfsconf)
  438                         maxvfsconf = vfc->vfc_typenum + 1;
  439         } else
  440                 vfc->vfc_typenum = maxvfsconf++;
  441         TAILQ_INSERT_TAIL(&vfsconf, vfc, vfc_list);
  442 
  443         /*
  444          * Initialise unused ``struct vfsops'' fields, to use
  445          * the vfs_std*() functions.  Note, we need the mount
  446          * and unmount operations, at the least.  The check
  447          * for vfsops available is just a debugging aid.
  448          */
  449         KASSERT(vfc->vfc_vfsops != NULL,
  450             ("Filesystem %s has no vfsops", vfc->vfc_name));
  451         /*
  452          * Check the mount and unmount operations.
  453          */
  454         vfsops = vfc->vfc_vfsops;
  455         KASSERT(vfsops->vfs_mount != NULL,
  456             ("Filesystem %s has no mount op", vfc->vfc_name));
  457         KASSERT(vfsops->vfs_unmount != NULL,
  458             ("Filesystem %s has no unmount op", vfc->vfc_name));
  459 
  460         if (vfsops->vfs_root == NULL)
  461                 /* return file system's root vnode */
  462                 vfsops->vfs_root =      vfs_stdroot;
  463         if (vfsops->vfs_quotactl == NULL)
  464                 /* quota control */
  465                 vfsops->vfs_quotactl =  vfs_stdquotactl;
  466         if (vfsops->vfs_statfs == NULL)
  467                 /* return file system's status */
  468                 vfsops->vfs_statfs =    vfs_stdstatfs;
  469         if (vfsops->vfs_sync == NULL)
  470                 /*
  471                  * flush unwritten data (nosync)
  472                  * file systems can use vfs_stdsync
  473                  * explicitly by setting it in the
  474                  * vfsop vector.
  475                  */
  476                 vfsops->vfs_sync =      vfs_stdnosync;
  477         if (vfsops->vfs_vget == NULL)
  478                 /* convert an inode number to a vnode */
  479                 vfsops->vfs_vget =      vfs_stdvget;
  480         if (vfsops->vfs_fhtovp == NULL)
  481                 /* turn an NFS file handle into a vnode */
  482                 vfsops->vfs_fhtovp =    vfs_stdfhtovp;
  483         if (vfsops->vfs_checkexp == NULL)
  484                 /* check if file system is exported */
  485                 vfsops->vfs_checkexp =  vfs_stdcheckexp;
  486         if (vfsops->vfs_init == NULL)
  487                 /* file system specific initialisation */
  488                 vfsops->vfs_init =      vfs_stdinit;
  489         if (vfsops->vfs_uninit == NULL)
  490                 /* file system specific uninitialisation */
  491                 vfsops->vfs_uninit =    vfs_stduninit;
  492         if (vfsops->vfs_extattrctl == NULL)
  493                 /* extended attribute control */
  494                 vfsops->vfs_extattrctl = vfs_stdextattrctl;
  495         if (vfsops->vfs_sysctl == NULL)
  496                 vfsops->vfs_sysctl = vfs_stdsysctl;
  497         if (vfsops->vfs_report_lockf == NULL)
  498                 vfsops->vfs_report_lockf = vfs_report_lockf;
  499 
  500         if ((vfc->vfc_flags & VFCF_SBDRY) != 0) {
  501                 vfc->vfc_vfsops_sd = vfc->vfc_vfsops;
  502                 vfc->vfc_vfsops = &vfsops_sigdefer;
  503         }
  504 
  505         if (vfc->vfc_flags & VFCF_JAIL)
  506                 prison_add_vfs(vfc);
  507 
  508         /*
  509          * Call init function for this VFS...
  510          */
  511         if ((vfc->vfc_flags & VFCF_SBDRY) != 0)
  512                 vfc->vfc_vfsops_sd->vfs_init(vfc);
  513         else
  514                 vfc->vfc_vfsops->vfs_init(vfc);
  515         vfsconf_unlock();
  516 
  517         /*
  518          * If this filesystem has a sysctl node under vfs
  519          * (i.e. vfs.xxfs), then change the oid number of that node to
  520          * match the filesystem's type number.  This allows user code
  521          * which uses the type number to read sysctl variables defined
  522          * by the filesystem to continue working. Since the oids are
  523          * in a sorted list, we need to make sure the order is
  524          * preserved by re-registering the oid after modifying its
  525          * number.
  526          */
  527         sysctl_wlock();
  528         RB_FOREACH(oidp, sysctl_oid_list, SYSCTL_CHILDREN(&sysctl___vfs)) {
  529                 if (strcmp(oidp->oid_name, vfc->vfc_name) == 0) {
  530                         sysctl_unregister_oid(oidp);
  531                         oidp->oid_number = vfc->vfc_typenum;
  532                         sysctl_register_oid(oidp);
  533                         break;
  534                 }
  535         }
  536         sysctl_wunlock();
  537 
  538         return (0);
  539 }
  540 
  541 /* Remove registration of a filesystem type */
  542 static int
  543 vfs_unregister(struct vfsconf *vfc)
  544 {
  545         struct vfsconf *vfsp;
  546         int error, maxtypenum;
  547 
  548         vfsconf_lock();
  549         vfsp = vfs_byname_locked(vfc->vfc_name);
  550         if (vfsp == NULL) {
  551                 vfsconf_unlock();
  552                 return (EINVAL);
  553         }
  554         if (vfsp->vfc_refcount != 0) {
  555                 vfsconf_unlock();
  556                 return (EBUSY);
  557         }
  558         error = 0;
  559         if ((vfc->vfc_flags & VFCF_SBDRY) != 0) {
  560                 if (vfc->vfc_vfsops_sd->vfs_uninit != NULL)
  561                         error = vfc->vfc_vfsops_sd->vfs_uninit(vfsp);
  562         } else {
  563                 if (vfc->vfc_vfsops->vfs_uninit != NULL)
  564                         error = vfc->vfc_vfsops->vfs_uninit(vfsp);
  565         }
  566         if (error != 0) {
  567                 vfsconf_unlock();
  568                 return (error);
  569         }
  570         TAILQ_REMOVE(&vfsconf, vfsp, vfc_list);
  571         maxtypenum = VFS_GENERIC;
  572         TAILQ_FOREACH(vfsp, &vfsconf, vfc_list)
  573                 if (maxtypenum < vfsp->vfc_typenum)
  574                         maxtypenum = vfsp->vfc_typenum;
  575         maxvfsconf = maxtypenum + 1;
  576         vfsconf_unlock();
  577         return (0);
  578 }
  579 
  580 /*
  581  * Standard kernel module handling code for filesystem modules.
  582  * Referenced from VFS_SET().
  583  */
  584 int
  585 vfs_modevent(module_t mod, int type, void *data)
  586 {
  587         struct vfsconf *vfc;
  588         int error = 0;
  589 
  590         vfc = (struct vfsconf *)data;
  591 
  592         switch (type) {
  593         case MOD_LOAD:
  594                 if (vfc)
  595                         error = vfs_register(vfc);
  596                 break;
  597 
  598         case MOD_UNLOAD:
  599                 if (vfc)
  600                         error = vfs_unregister(vfc);
  601                 break;
  602         default:
  603                 error = EOPNOTSUPP;
  604                 break;
  605         }
  606         return (error);
  607 }

Cache object: 830cca9419e2dcfc085c9e2adb886c4b


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.