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/fs/ext2fs/ext2_vfsops.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  *  modified for EXT2FS support in Lites 1.1
    3  *
    4  *  Aug 1995, Godmar Back (gback@cs.utah.edu)
    5  *  University of Utah, Department of Computer Science
    6  */
    7 /*-
    8  * SPDX-License-Identifier: BSD-3-Clause
    9  *
   10  * Copyright (c) 1989, 1991, 1993, 1994
   11  *      The Regents of the University of California.  All rights reserved.
   12  *
   13  * Redistribution and use in source and binary forms, with or without
   14  * modification, are permitted provided that the following conditions
   15  * are met:
   16  * 1. Redistributions of source code must retain the above copyright
   17  *    notice, this list of conditions and the following disclaimer.
   18  * 2. Redistributions in binary form must reproduce the above copyright
   19  *    notice, this list of conditions and the following disclaimer in the
   20  *    documentation and/or other materials provided with the distribution.
   21  * 3. Neither the name of the University nor the names of its contributors
   22  *    may be used to endorse or promote products derived from this software
   23  *    without specific prior written permission.
   24  *
   25  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   26  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   27  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   28  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   29  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   30  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   31  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   32  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   33  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   34  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   35  * SUCH DAMAGE.
   36  *
   37  *      @(#)ffs_vfsops.c        8.8 (Berkeley) 4/18/94
   38  * $FreeBSD: releng/12.0/sys/fs/ext2fs/ext2_vfsops.c 333584 2018-05-13 19:19:10Z fsu $
   39  */
   40 
   41 #include <sys/param.h>
   42 #include <sys/systm.h>
   43 #include <sys/namei.h>
   44 #include <sys/priv.h>
   45 #include <sys/proc.h>
   46 #include <sys/kernel.h>
   47 #include <sys/vnode.h>
   48 #include <sys/mount.h>
   49 #include <sys/bio.h>
   50 #include <sys/buf.h>
   51 #include <sys/conf.h>
   52 #include <sys/endian.h>
   53 #include <sys/fcntl.h>
   54 #include <sys/malloc.h>
   55 #include <sys/stat.h>
   56 #include <sys/mutex.h>
   57 
   58 #include <geom/geom.h>
   59 #include <geom/geom_vfs.h>
   60 
   61 #include <fs/ext2fs/fs.h>
   62 #include <fs/ext2fs/ext2_mount.h>
   63 #include <fs/ext2fs/inode.h>
   64 
   65 #include <fs/ext2fs/ext2fs.h>
   66 #include <fs/ext2fs/ext2_dinode.h>
   67 #include <fs/ext2fs/ext2_extern.h>
   68 #include <fs/ext2fs/ext2_extents.h>
   69 
   70 
   71 static int      ext2_flushfiles(struct mount *mp, int flags, struct thread *td);
   72 static int      ext2_mountfs(struct vnode *, struct mount *);
   73 static int      ext2_reload(struct mount *mp, struct thread *td);
   74 static int      ext2_sbupdate(struct ext2mount *, int);
   75 static int      ext2_cgupdate(struct ext2mount *, int);
   76 static vfs_unmount_t            ext2_unmount;
   77 static vfs_root_t               ext2_root;
   78 static vfs_statfs_t             ext2_statfs;
   79 static vfs_sync_t               ext2_sync;
   80 static vfs_vget_t               ext2_vget;
   81 static vfs_fhtovp_t             ext2_fhtovp;
   82 static vfs_mount_t              ext2_mount;
   83 
   84 MALLOC_DEFINE(M_EXT2NODE, "ext2_node", "EXT2 vnode private part");
   85 static MALLOC_DEFINE(M_EXT2MNT, "ext2_mount", "EXT2 mount structure");
   86 
   87 static struct vfsops ext2fs_vfsops = {
   88         .vfs_fhtovp =           ext2_fhtovp,
   89         .vfs_mount =            ext2_mount,
   90         .vfs_root =             ext2_root,      /* root inode via vget */
   91         .vfs_statfs =           ext2_statfs,
   92         .vfs_sync =             ext2_sync,
   93         .vfs_unmount =          ext2_unmount,
   94         .vfs_vget =             ext2_vget,
   95 };
   96 
   97 VFS_SET(ext2fs_vfsops, ext2fs, 0);
   98 
   99 static int      ext2_check_sb_compat(struct ext2fs *es, struct cdev *dev,
  100                     int ronly);
  101 static int      compute_sb_data(struct vnode * devvp,
  102                     struct ext2fs * es, struct m_ext2fs * fs);
  103 
  104 static const char *ext2_opts[] = { "acls", "async", "noatime", "noclusterr", 
  105     "noclusterw", "noexec", "export", "force", "from", "multilabel",
  106     "suiddir", "nosymfollow", "sync", "union", NULL };
  107 
  108 /*
  109  * VFS Operations.
  110  *
  111  * mount system call
  112  */
  113 static int
  114 ext2_mount(struct mount *mp)
  115 {
  116         struct vfsoptlist *opts;
  117         struct vnode *devvp;
  118         struct thread *td;
  119         struct ext2mount *ump = NULL;
  120         struct m_ext2fs *fs;
  121         struct nameidata nd, *ndp = &nd;
  122         accmode_t accmode;
  123         char *path, *fspec;
  124         int error, flags, len;
  125 
  126         td = curthread;
  127         opts = mp->mnt_optnew;
  128 
  129         if (vfs_filteropt(opts, ext2_opts))
  130                 return (EINVAL);
  131 
  132         vfs_getopt(opts, "fspath", (void **)&path, NULL);
  133         /* Double-check the length of path.. */
  134         if (strlen(path) >= MAXMNTLEN)
  135                 return (ENAMETOOLONG);
  136 
  137         fspec = NULL;
  138         error = vfs_getopt(opts, "from", (void **)&fspec, &len);
  139         if (!error && fspec[len - 1] != '\0')
  140                 return (EINVAL);
  141 
  142         /*
  143          * If updating, check whether changing from read-only to
  144          * read/write; if there is no device name, that's all we do.
  145          */
  146         if (mp->mnt_flag & MNT_UPDATE) {
  147                 ump = VFSTOEXT2(mp);
  148                 fs = ump->um_e2fs;
  149                 error = 0;
  150                 if (fs->e2fs_ronly == 0 &&
  151                     vfs_flagopt(opts, "ro", NULL, 0)) {
  152                         error = VFS_SYNC(mp, MNT_WAIT);
  153                         if (error)
  154                                 return (error);
  155                         flags = WRITECLOSE;
  156                         if (mp->mnt_flag & MNT_FORCE)
  157                                 flags |= FORCECLOSE;
  158                         error = ext2_flushfiles(mp, flags, td);
  159                         if (error == 0 && fs->e2fs_wasvalid &&
  160                             ext2_cgupdate(ump, MNT_WAIT) == 0) {
  161                                 fs->e2fs->e2fs_state |= E2FS_ISCLEAN;
  162                                 ext2_sbupdate(ump, MNT_WAIT);
  163                         }
  164                         fs->e2fs_ronly = 1;
  165                         vfs_flagopt(opts, "ro", &mp->mnt_flag, MNT_RDONLY);
  166                         g_topology_lock();
  167                         g_access(ump->um_cp, 0, -1, 0);
  168                         g_topology_unlock();
  169                 }
  170                 if (!error && (mp->mnt_flag & MNT_RELOAD))
  171                         error = ext2_reload(mp, td);
  172                 if (error)
  173                         return (error);
  174                 devvp = ump->um_devvp;
  175                 if (fs->e2fs_ronly && !vfs_flagopt(opts, "ro", NULL, 0)) {
  176                         if (ext2_check_sb_compat(fs->e2fs, devvp->v_rdev, 0))
  177                                 return (EPERM);
  178 
  179                         /*
  180                          * If upgrade to read-write by non-root, then verify
  181                          * that user has necessary permissions on the device.
  182                          */
  183                         vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY);
  184                         error = VOP_ACCESS(devvp, VREAD | VWRITE,
  185                             td->td_ucred, td);
  186                         if (error)
  187                                 error = priv_check(td, PRIV_VFS_MOUNT_PERM);
  188                         if (error) {
  189                                 VOP_UNLOCK(devvp, 0);
  190                                 return (error);
  191                         }
  192                         VOP_UNLOCK(devvp, 0);
  193                         g_topology_lock();
  194                         error = g_access(ump->um_cp, 0, 1, 0);
  195                         g_topology_unlock();
  196                         if (error)
  197                                 return (error);
  198 
  199                         if ((fs->e2fs->e2fs_state & E2FS_ISCLEAN) == 0 ||
  200                             (fs->e2fs->e2fs_state & E2FS_ERRORS)) {
  201                                 if (mp->mnt_flag & MNT_FORCE) {
  202                                         printf(
  203 "WARNING: %s was not properly dismounted\n", fs->e2fs_fsmnt);
  204                                 } else {
  205                                         printf(
  206 "WARNING: R/W mount of %s denied.  Filesystem is not clean - run fsck\n",
  207                                             fs->e2fs_fsmnt);
  208                                         return (EPERM);
  209                                 }
  210                         }
  211                         fs->e2fs->e2fs_state &= ~E2FS_ISCLEAN;
  212                         (void)ext2_cgupdate(ump, MNT_WAIT);
  213                         fs->e2fs_ronly = 0;
  214                         MNT_ILOCK(mp);
  215                         mp->mnt_flag &= ~MNT_RDONLY;
  216                         MNT_IUNLOCK(mp);
  217                 }
  218                 if (vfs_flagopt(opts, "export", NULL, 0)) {
  219                         /* Process export requests in vfs_mount.c. */
  220                         return (error);
  221                 }
  222         }
  223 
  224         /*
  225          * Not an update, or updating the name: look up the name
  226          * and verify that it refers to a sensible disk device.
  227          */
  228         if (fspec == NULL)
  229                 return (EINVAL);
  230         NDINIT(ndp, LOOKUP, FOLLOW | LOCKLEAF, UIO_SYSSPACE, fspec, td);
  231         if ((error = namei(ndp)) != 0)
  232                 return (error);
  233         NDFREE(ndp, NDF_ONLY_PNBUF);
  234         devvp = ndp->ni_vp;
  235 
  236         if (!vn_isdisk(devvp, &error)) {
  237                 vput(devvp);
  238                 return (error);
  239         }
  240 
  241         /*
  242          * If mount by non-root, then verify that user has necessary
  243          * permissions on the device.
  244          *
  245          * XXXRW: VOP_ACCESS() enough?
  246          */
  247         accmode = VREAD;
  248         if ((mp->mnt_flag & MNT_RDONLY) == 0)
  249                 accmode |= VWRITE;
  250         error = VOP_ACCESS(devvp, accmode, td->td_ucred, td);
  251         if (error)
  252                 error = priv_check(td, PRIV_VFS_MOUNT_PERM);
  253         if (error) {
  254                 vput(devvp);
  255                 return (error);
  256         }
  257 
  258         if ((mp->mnt_flag & MNT_UPDATE) == 0) {
  259                 error = ext2_mountfs(devvp, mp);
  260         } else {
  261                 if (devvp != ump->um_devvp) {
  262                         vput(devvp);
  263                         return (EINVAL);        /* needs translation */
  264                 } else
  265                         vput(devvp);
  266         }
  267         if (error) {
  268                 vrele(devvp);
  269                 return (error);
  270         }
  271         ump = VFSTOEXT2(mp);
  272         fs = ump->um_e2fs;
  273 
  274         /*
  275          * Note that this strncpy() is ok because of a check at the start
  276          * of ext2_mount().
  277          */
  278         strncpy(fs->e2fs_fsmnt, path, MAXMNTLEN);
  279         fs->e2fs_fsmnt[MAXMNTLEN - 1] = '\0';
  280         vfs_mountedfrom(mp, fspec);
  281         return (0);
  282 }
  283 
  284 static int
  285 ext2_check_sb_compat(struct ext2fs *es, struct cdev *dev, int ronly)
  286 {
  287         uint32_t i, mask;
  288 
  289         if (es->e2fs_magic != E2FS_MAGIC) {
  290                 printf("ext2fs: %s: wrong magic number %#x (expected %#x)\n",
  291                     devtoname(dev), es->e2fs_magic, E2FS_MAGIC);
  292                 return (1);
  293         }
  294         if (es->e2fs_rev > E2FS_REV0) {
  295                 mask = es->e2fs_features_incompat & ~(EXT2F_INCOMPAT_SUPP);
  296                 if (mask) {
  297                         printf("WARNING: mount of %s denied due to "
  298                             "unsupported optional features:\n", devtoname(dev));
  299                         for (i = 0;
  300                             i < sizeof(incompat)/sizeof(struct ext2_feature);
  301                             i++)
  302                                 if (mask & incompat[i].mask)
  303                                         printf("%s ", incompat[i].name);
  304                         printf("\n");
  305                         return (1);
  306                 }
  307                 mask = es->e2fs_features_rocompat & ~EXT2F_ROCOMPAT_SUPP;
  308                 if (!ronly && mask) {
  309                         printf("WARNING: R/W mount of %s denied due to "
  310                             "unsupported optional features:\n", devtoname(dev));
  311                         for (i = 0;
  312                             i < sizeof(ro_compat)/sizeof(struct ext2_feature);
  313                             i++)
  314                                 if (mask & ro_compat[i].mask)
  315                                         printf("%s ", ro_compat[i].name);
  316                         printf("\n");
  317                         return (1);
  318                 }
  319         }
  320         return (0);
  321 }
  322 
  323 static e4fs_daddr_t
  324 cg_location(struct m_ext2fs *fs, int number)
  325 {
  326         int cg, descpb, logical_sb, has_super = 0;
  327 
  328         /*
  329          * Adjust logical superblock block number.
  330          * Godmar thinks: if the blocksize is greater than 1024, then
  331          * the superblock is logically part of block zero.
  332          */
  333         logical_sb = fs->e2fs_bsize > SBSIZE ? 0 : 1;
  334 
  335         if (!EXT2_HAS_INCOMPAT_FEATURE(fs, EXT2F_INCOMPAT_META_BG) ||
  336             number < fs->e2fs->e3fs_first_meta_bg)
  337                 return (logical_sb + number + 1);
  338 
  339         if (EXT2_HAS_INCOMPAT_FEATURE(fs, EXT2F_INCOMPAT_64BIT))
  340                 descpb = fs->e2fs_bsize / sizeof(struct ext2_gd);
  341         else
  342                 descpb = fs->e2fs_bsize / E2FS_REV0_GD_SIZE;
  343 
  344         cg = descpb * number;
  345 
  346         if (ext2_cg_has_sb(fs, cg))
  347                 has_super = 1;
  348 
  349         return (has_super + cg * (e4fs_daddr_t)EXT2_BLOCKS_PER_GROUP(fs) +
  350             fs->e2fs->e2fs_first_dblock);
  351 }
  352 
  353 /*
  354  * This computes the fields of the m_ext2fs structure from the
  355  * data in the ext2fs structure read in.
  356  */
  357 static int
  358 compute_sb_data(struct vnode *devvp, struct ext2fs *es,
  359     struct m_ext2fs *fs)
  360 {
  361         int g_count = 0, error;
  362         int i, j;
  363         struct buf *bp;
  364         uint32_t e2fs_descpb, e2fs_gdbcount_alloc;
  365 
  366         fs->e2fs_bcount = es->e2fs_bcount;
  367         fs->e2fs_rbcount = es->e2fs_rbcount;
  368         fs->e2fs_fbcount = es->e2fs_fbcount;
  369         if (EXT2_HAS_INCOMPAT_FEATURE(fs, EXT2F_INCOMPAT_64BIT)) {
  370                 fs->e2fs_bcount |= (uint64_t)(es->e4fs_bcount_hi) << 32;
  371                 fs->e2fs_rbcount |= (uint64_t)(es->e4fs_rbcount_hi) << 32;
  372                 fs->e2fs_fbcount |= (uint64_t)(es->e4fs_fbcount_hi) << 32;
  373         }
  374         fs->e2fs_bshift = EXT2_MIN_BLOCK_LOG_SIZE + es->e2fs_log_bsize;
  375         fs->e2fs_bsize = 1U << fs->e2fs_bshift;
  376         fs->e2fs_fsbtodb = es->e2fs_log_bsize + 1;
  377         fs->e2fs_qbmask = fs->e2fs_bsize - 1;
  378         fs->e2fs_fsize = EXT2_MIN_FRAG_SIZE << es->e2fs_log_fsize;
  379         if (fs->e2fs_fsize)
  380                 fs->e2fs_fpb = fs->e2fs_bsize / fs->e2fs_fsize;
  381         fs->e2fs_bpg = es->e2fs_bpg;
  382         fs->e2fs_fpg = es->e2fs_fpg;
  383         fs->e2fs_ipg = es->e2fs_ipg;
  384         if (es->e2fs_rev == E2FS_REV0) {
  385                 fs->e2fs_isize = E2FS_REV0_INODE_SIZE;
  386         } else {
  387                 fs->e2fs_isize = es->e2fs_inode_size;
  388 
  389                 /*
  390                  * Simple sanity check for superblock inode size value.
  391                  */
  392                 if (EXT2_INODE_SIZE(fs) < E2FS_REV0_INODE_SIZE ||
  393                     EXT2_INODE_SIZE(fs) > fs->e2fs_bsize ||
  394                     (fs->e2fs_isize & (fs->e2fs_isize - 1)) != 0) {
  395                         printf("ext2fs: invalid inode size %d\n",
  396                             fs->e2fs_isize);
  397                         return (EIO);
  398                 }
  399         }
  400         /* Check for extra isize in big inodes. */
  401         if (EXT2_HAS_RO_COMPAT_FEATURE(fs, EXT2F_ROCOMPAT_EXTRA_ISIZE) &&
  402             EXT2_INODE_SIZE(fs) < sizeof(struct ext2fs_dinode)) {
  403                 printf("ext2fs: no space for extra inode timestamps\n");
  404                 return (EINVAL);
  405         }
  406         /* Check checksum features */
  407         if (EXT2_HAS_RO_COMPAT_FEATURE(fs, EXT2F_ROCOMPAT_GDT_CSUM) &&
  408             EXT2_HAS_RO_COMPAT_FEATURE(fs, EXT2F_ROCOMPAT_METADATA_CKSUM)) {
  409                 printf("ext2fs: incorrect checksum features combination\n");
  410                 return (EINVAL);
  411         }
  412         /* Check for group descriptor size */
  413         if (EXT2_HAS_INCOMPAT_FEATURE(fs, EXT2F_INCOMPAT_64BIT) &&
  414             (es->e3fs_desc_size != sizeof(struct ext2_gd))) {
  415                 printf("ext2fs: group descriptor size unsupported %d\n",
  416                     es->e3fs_desc_size);
  417                 return (EINVAL);
  418         }
  419         /* Check for group size */
  420         if (fs->e2fs_bpg != fs->e2fs_bsize * 8) {
  421                 printf("ext2fs: non-standard group size unsupported %d\n",
  422                     fs->e2fs_bpg);
  423                 return (EINVAL);
  424         }
  425 
  426         fs->e2fs_ipb = fs->e2fs_bsize / EXT2_INODE_SIZE(fs);
  427         fs->e2fs_itpg = fs->e2fs_ipg / fs->e2fs_ipb;
  428         /* s_resuid / s_resgid ? */
  429         fs->e2fs_gcount = howmany(fs->e2fs_bcount - es->e2fs_first_dblock,
  430             EXT2_BLOCKS_PER_GROUP(fs));
  431         if (EXT2_HAS_INCOMPAT_FEATURE(fs, EXT2F_INCOMPAT_64BIT)) {
  432                 e2fs_descpb = fs->e2fs_bsize / sizeof(struct ext2_gd);
  433                 e2fs_gdbcount_alloc = howmany(fs->e2fs_gcount, e2fs_descpb);
  434         } else {
  435                 e2fs_descpb = fs->e2fs_bsize / E2FS_REV0_GD_SIZE;
  436                 e2fs_gdbcount_alloc = howmany(fs->e2fs_gcount,
  437                     fs->e2fs_bsize / sizeof(struct ext2_gd));
  438         }
  439         fs->e2fs_gdbcount = howmany(fs->e2fs_gcount, e2fs_descpb);
  440         fs->e2fs_gd = malloc(e2fs_gdbcount_alloc * fs->e2fs_bsize,
  441             M_EXT2MNT, M_WAITOK | M_ZERO);
  442         fs->e2fs_contigdirs = malloc(fs->e2fs_gcount *
  443             sizeof(*fs->e2fs_contigdirs), M_EXT2MNT, M_WAITOK | M_ZERO);
  444 
  445         for (i = 0; i < fs->e2fs_gdbcount; i++) {
  446                 error = bread(devvp,
  447                     fsbtodb(fs, cg_location(fs, i)),
  448                     fs->e2fs_bsize, NOCRED, &bp);
  449                 if (error) {
  450                         free(fs->e2fs_contigdirs, M_EXT2MNT);
  451                         free(fs->e2fs_gd, M_EXT2MNT);
  452                         brelse(bp);
  453                         return (error);
  454                 }
  455                 if (EXT2_HAS_INCOMPAT_FEATURE(fs, EXT2F_INCOMPAT_64BIT)) {
  456                         memcpy(&fs->e2fs_gd[
  457                             i * fs->e2fs_bsize / sizeof(struct ext2_gd)],
  458                             bp->b_data, fs->e2fs_bsize);
  459                 } else {
  460                         for (j = 0; j < e2fs_descpb &&
  461                             g_count < fs->e2fs_gcount; j++, g_count++)
  462                                 memcpy(&fs->e2fs_gd[g_count],
  463                                     bp->b_data + j * E2FS_REV0_GD_SIZE,
  464                                     E2FS_REV0_GD_SIZE);
  465                 }
  466                 brelse(bp);
  467                 bp = NULL;
  468         }
  469         /* Precompute checksum seed for all metadata */
  470         ext2_sb_csum_set_seed(fs);
  471         /* Verfy cg csum */
  472         if (EXT2_HAS_RO_COMPAT_FEATURE(fs, EXT2F_ROCOMPAT_GDT_CSUM) ||
  473             EXT2_HAS_RO_COMPAT_FEATURE(fs, EXT2F_ROCOMPAT_METADATA_CKSUM)) {
  474                 error = ext2_gd_csum_verify(fs, devvp->v_rdev);
  475                 if (error)
  476                         return (error);
  477         }
  478         /* Initialization for the ext2 Orlov allocator variant. */
  479         fs->e2fs_total_dir = 0;
  480         for (i = 0; i < fs->e2fs_gcount; i++)
  481                 fs->e2fs_total_dir += e2fs_gd_get_ndirs(&fs->e2fs_gd[i]);
  482 
  483         if (es->e2fs_rev == E2FS_REV0 ||
  484             !EXT2_HAS_RO_COMPAT_FEATURE(fs, EXT2F_ROCOMPAT_LARGEFILE))
  485                 fs->e2fs_maxfilesize = 0x7fffffff;
  486         else {
  487                 fs->e2fs_maxfilesize = 0xffffffffffff;
  488                 if (EXT2_HAS_RO_COMPAT_FEATURE(fs, EXT2F_ROCOMPAT_HUGE_FILE))
  489                         fs->e2fs_maxfilesize = 0x7fffffffffffffff;
  490         }
  491         if (es->e4fs_flags & E2FS_UNSIGNED_HASH) {
  492                 fs->e2fs_uhash = 3;
  493         } else if ((es->e4fs_flags & E2FS_SIGNED_HASH) == 0) {
  494 #ifdef __CHAR_UNSIGNED__
  495                 es->e4fs_flags |= E2FS_UNSIGNED_HASH;
  496                 fs->e2fs_uhash = 3;
  497 #else
  498                 es->e4fs_flags |= E2FS_SIGNED_HASH;
  499 #endif
  500         }
  501         if (EXT2_HAS_RO_COMPAT_FEATURE(fs, EXT2F_ROCOMPAT_METADATA_CKSUM))
  502                 error = ext2_sb_csum_verify(fs);
  503 
  504         return (error);
  505 }
  506 
  507 /*
  508  * Reload all incore data for a filesystem (used after running fsck on
  509  * the root filesystem and finding things to fix). The filesystem must
  510  * be mounted read-only.
  511  *
  512  * Things to do to update the mount:
  513  *      1) invalidate all cached meta-data.
  514  *      2) re-read superblock from disk.
  515  *      3) invalidate all cluster summary information.
  516  *      4) invalidate all inactive vnodes.
  517  *      5) invalidate all cached file data.
  518  *      6) re-read inode data for all active vnodes.
  519  * XXX we are missing some steps, in particular # 3, this has to be reviewed.
  520  */
  521 static int
  522 ext2_reload(struct mount *mp, struct thread *td)
  523 {
  524         struct vnode *vp, *mvp, *devvp;
  525         struct inode *ip;
  526         struct buf *bp;
  527         struct ext2fs *es;
  528         struct m_ext2fs *fs;
  529         struct csum *sump;
  530         int error, i;
  531         int32_t *lp;
  532 
  533         if ((mp->mnt_flag & MNT_RDONLY) == 0)
  534                 return (EINVAL);
  535         /*
  536          * Step 1: invalidate all cached meta-data.
  537          */
  538         devvp = VFSTOEXT2(mp)->um_devvp;
  539         vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY);
  540         if (vinvalbuf(devvp, 0, 0, 0) != 0)
  541                 panic("ext2_reload: dirty1");
  542         VOP_UNLOCK(devvp, 0);
  543 
  544         /*
  545          * Step 2: re-read superblock from disk.
  546          * constants have been adjusted for ext2
  547          */
  548         if ((error = bread(devvp, SBLOCK, SBSIZE, NOCRED, &bp)) != 0)
  549                 return (error);
  550         es = (struct ext2fs *)bp->b_data;
  551         if (ext2_check_sb_compat(es, devvp->v_rdev, 0) != 0) {
  552                 brelse(bp);
  553                 return (EIO);           /* XXX needs translation */
  554         }
  555         fs = VFSTOEXT2(mp)->um_e2fs;
  556         bcopy(bp->b_data, fs->e2fs, sizeof(struct ext2fs));
  557 
  558         if ((error = compute_sb_data(devvp, es, fs)) != 0) {
  559                 brelse(bp);
  560                 return (error);
  561         }
  562 #ifdef UNKLAR
  563         if (fs->fs_sbsize < SBSIZE)
  564                 bp->b_flags |= B_INVAL;
  565 #endif
  566         brelse(bp);
  567 
  568         /*
  569          * Step 3: invalidate all cluster summary information.
  570          */
  571         if (fs->e2fs_contigsumsize > 0) {
  572                 lp = fs->e2fs_maxcluster;
  573                 sump = fs->e2fs_clustersum;
  574                 for (i = 0; i < fs->e2fs_gcount; i++, sump++) {
  575                         *lp++ = fs->e2fs_contigsumsize;
  576                         sump->cs_init = 0;
  577                         bzero(sump->cs_sum, fs->e2fs_contigsumsize + 1);
  578                 }
  579         }
  580 
  581 loop:
  582         MNT_VNODE_FOREACH_ALL(vp, mp, mvp) {
  583                 /*
  584                  * Step 4: invalidate all cached file data.
  585                  */
  586                 if (vget(vp, LK_EXCLUSIVE | LK_INTERLOCK, td)) {
  587                         MNT_VNODE_FOREACH_ALL_ABORT(mp, mvp);
  588                         goto loop;
  589                 }
  590                 if (vinvalbuf(vp, 0, 0, 0))
  591                         panic("ext2_reload: dirty2");
  592 
  593                 /*
  594                  * Step 5: re-read inode data for all active vnodes.
  595                  */
  596                 ip = VTOI(vp);
  597                 error = bread(devvp, fsbtodb(fs, ino_to_fsba(fs, ip->i_number)),
  598                     (int)fs->e2fs_bsize, NOCRED, &bp);
  599                 if (error) {
  600                         VOP_UNLOCK(vp, 0);
  601                         vrele(vp);
  602                         MNT_VNODE_FOREACH_ALL_ABORT(mp, mvp);
  603                         return (error);
  604                 }
  605                 ext2_ei2i((struct ext2fs_dinode *)((char *)bp->b_data +
  606                     EXT2_INODE_SIZE(fs) * ino_to_fsbo(fs, ip->i_number)), ip);
  607                 brelse(bp);
  608                 VOP_UNLOCK(vp, 0);
  609                 vrele(vp);
  610         }
  611         return (0);
  612 }
  613 
  614 /*
  615  * Common code for mount and mountroot.
  616  */
  617 static int
  618 ext2_mountfs(struct vnode *devvp, struct mount *mp)
  619 {
  620         struct ext2mount *ump;
  621         struct buf *bp;
  622         struct m_ext2fs *fs;
  623         struct ext2fs *es;
  624         struct cdev *dev = devvp->v_rdev;
  625         struct g_consumer *cp;
  626         struct bufobj *bo;
  627         struct csum *sump;
  628         int error;
  629         int ronly;
  630         int i;
  631         u_long size;
  632         int32_t *lp;
  633         int32_t e2fs_maxcontig;
  634 
  635         ronly = vfs_flagopt(mp->mnt_optnew, "ro", NULL, 0);
  636         /* XXX: use VOP_ACESS to check FS perms */
  637         g_topology_lock();
  638         error = g_vfs_open(devvp, &cp, "ext2fs", ronly ? 0 : 1);
  639         g_topology_unlock();
  640         VOP_UNLOCK(devvp, 0);
  641         if (error)
  642                 return (error);
  643 
  644         /* XXX: should we check for some sectorsize or 512 instead? */
  645         if (((SBSIZE % cp->provider->sectorsize) != 0) ||
  646             (SBSIZE < cp->provider->sectorsize)) {
  647                 g_topology_lock();
  648                 g_vfs_close(cp);
  649                 g_topology_unlock();
  650                 return (EINVAL);
  651         }
  652 
  653         bo = &devvp->v_bufobj;
  654         bo->bo_private = cp;
  655         bo->bo_ops = g_vfs_bufops;
  656         if (devvp->v_rdev->si_iosize_max != 0)
  657                 mp->mnt_iosize_max = devvp->v_rdev->si_iosize_max;
  658         if (mp->mnt_iosize_max > MAXPHYS)
  659                 mp->mnt_iosize_max = MAXPHYS;
  660 
  661         bp = NULL;
  662         ump = NULL;
  663         if ((error = bread(devvp, SBLOCK, SBSIZE, NOCRED, &bp)) != 0)
  664                 goto out;
  665         es = (struct ext2fs *)bp->b_data;
  666         if (ext2_check_sb_compat(es, dev, ronly) != 0) {
  667                 error = EINVAL;         /* XXX needs translation */
  668                 goto out;
  669         }
  670         if ((es->e2fs_state & E2FS_ISCLEAN) == 0 ||
  671             (es->e2fs_state & E2FS_ERRORS)) {
  672                 if (ronly || (mp->mnt_flag & MNT_FORCE)) {
  673                         printf(
  674 "WARNING: Filesystem was not properly dismounted\n");
  675                 } else {
  676                         printf(
  677 "WARNING: R/W mount denied.  Filesystem is not clean - run fsck\n");
  678                         error = EPERM;
  679                         goto out;
  680                 }
  681         }
  682         ump = malloc(sizeof(*ump), M_EXT2MNT, M_WAITOK | M_ZERO);
  683 
  684         /*
  685          * I don't know whether this is the right strategy. Note that
  686          * we dynamically allocate both an m_ext2fs and an ext2fs
  687          * while Linux keeps the super block in a locked buffer.
  688          */
  689         ump->um_e2fs = malloc(sizeof(struct m_ext2fs),
  690             M_EXT2MNT, M_WAITOK | M_ZERO);
  691         ump->um_e2fs->e2fs = malloc(sizeof(struct ext2fs),
  692             M_EXT2MNT, M_WAITOK);
  693         mtx_init(EXT2_MTX(ump), "EXT2FS", "EXT2FS Lock", MTX_DEF);
  694         bcopy(es, ump->um_e2fs->e2fs, (u_int)sizeof(struct ext2fs));
  695         if ((error = compute_sb_data(devvp, ump->um_e2fs->e2fs, ump->um_e2fs)))
  696                 goto out;
  697 
  698         /*
  699          * Calculate the maximum contiguous blocks and size of cluster summary
  700          * array.  In FFS this is done by newfs; however, the superblock
  701          * in ext2fs doesn't have these variables, so we can calculate
  702          * them here.
  703          */
  704         e2fs_maxcontig = MAX(1, MAXPHYS / ump->um_e2fs->e2fs_bsize);
  705         ump->um_e2fs->e2fs_contigsumsize = MIN(e2fs_maxcontig, EXT2_MAXCONTIG);
  706         if (ump->um_e2fs->e2fs_contigsumsize > 0) {
  707                 size = ump->um_e2fs->e2fs_gcount * sizeof(int32_t);
  708                 ump->um_e2fs->e2fs_maxcluster = malloc(size, M_EXT2MNT, M_WAITOK);
  709                 size = ump->um_e2fs->e2fs_gcount * sizeof(struct csum);
  710                 ump->um_e2fs->e2fs_clustersum = malloc(size, M_EXT2MNT, M_WAITOK);
  711                 lp = ump->um_e2fs->e2fs_maxcluster;
  712                 sump = ump->um_e2fs->e2fs_clustersum;
  713                 for (i = 0; i < ump->um_e2fs->e2fs_gcount; i++, sump++) {
  714                         *lp++ = ump->um_e2fs->e2fs_contigsumsize;
  715                         sump->cs_init = 0;
  716                         sump->cs_sum = malloc((ump->um_e2fs->e2fs_contigsumsize + 1) *
  717                             sizeof(int32_t), M_EXT2MNT, M_WAITOK | M_ZERO);
  718                 }
  719         }
  720 
  721         brelse(bp);
  722         bp = NULL;
  723         fs = ump->um_e2fs;
  724         fs->e2fs_ronly = ronly; /* ronly is set according to mnt_flags */
  725 
  726         /*
  727          * If the fs is not mounted read-only, make sure the super block is
  728          * always written back on a sync().
  729          */
  730         fs->e2fs_wasvalid = fs->e2fs->e2fs_state & E2FS_ISCLEAN ? 1 : 0;
  731         if (ronly == 0) {
  732                 fs->e2fs_fmod = 1;      /* mark it modified */
  733                 fs->e2fs->e2fs_state &= ~E2FS_ISCLEAN;  /* set fs invalid */
  734         }
  735         mp->mnt_data = ump;
  736         mp->mnt_stat.f_fsid.val[0] = dev2udev(dev);
  737         mp->mnt_stat.f_fsid.val[1] = mp->mnt_vfc->vfc_typenum;
  738         mp->mnt_maxsymlinklen = EXT2_MAXSYMLINKLEN;
  739         MNT_ILOCK(mp);
  740         mp->mnt_flag |= MNT_LOCAL;
  741         MNT_IUNLOCK(mp);
  742         ump->um_mountp = mp;
  743         ump->um_dev = dev;
  744         ump->um_devvp = devvp;
  745         ump->um_bo = &devvp->v_bufobj;
  746         ump->um_cp = cp;
  747 
  748         /*
  749          * Setting those two parameters allowed us to use
  750          * ufs_bmap w/o changse!
  751          */
  752         ump->um_nindir = EXT2_ADDR_PER_BLOCK(fs);
  753         ump->um_bptrtodb = fs->e2fs->e2fs_log_bsize + 1;
  754         ump->um_seqinc = EXT2_FRAGS_PER_BLOCK(fs);
  755         if (ronly == 0)
  756                 ext2_sbupdate(ump, MNT_WAIT);
  757         /*
  758          * Initialize filesystem stat information in mount struct.
  759          */
  760         MNT_ILOCK(mp);
  761         mp->mnt_kern_flag |= MNTK_LOOKUP_SHARED | MNTK_EXTENDED_SHARED |
  762             MNTK_USES_BCACHE;
  763         MNT_IUNLOCK(mp);
  764         return (0);
  765 out:
  766         if (bp)
  767                 brelse(bp);
  768         if (cp != NULL) {
  769                 g_topology_lock();
  770                 g_vfs_close(cp);
  771                 g_topology_unlock();
  772         }
  773         if (ump) {
  774                 mtx_destroy(EXT2_MTX(ump));
  775                 free(ump->um_e2fs->e2fs_gd, M_EXT2MNT);
  776                 free(ump->um_e2fs->e2fs_contigdirs, M_EXT2MNT);
  777                 free(ump->um_e2fs->e2fs, M_EXT2MNT);
  778                 free(ump->um_e2fs, M_EXT2MNT);
  779                 free(ump, M_EXT2MNT);
  780                 mp->mnt_data = NULL;
  781         }
  782         return (error);
  783 }
  784 
  785 /*
  786  * Unmount system call.
  787  */
  788 static int
  789 ext2_unmount(struct mount *mp, int mntflags)
  790 {
  791         struct ext2mount *ump;
  792         struct m_ext2fs *fs;
  793         struct csum *sump;
  794         int error, flags, i, ronly;
  795 
  796         flags = 0;
  797         if (mntflags & MNT_FORCE) {
  798                 if (mp->mnt_flag & MNT_ROOTFS)
  799                         return (EINVAL);
  800                 flags |= FORCECLOSE;
  801         }
  802         if ((error = ext2_flushfiles(mp, flags, curthread)) != 0)
  803                 return (error);
  804         ump = VFSTOEXT2(mp);
  805         fs = ump->um_e2fs;
  806         ronly = fs->e2fs_ronly;
  807         if (ronly == 0 && ext2_cgupdate(ump, MNT_WAIT) == 0) {
  808                 if (fs->e2fs_wasvalid)
  809                         fs->e2fs->e2fs_state |= E2FS_ISCLEAN;
  810                 ext2_sbupdate(ump, MNT_WAIT);
  811         }
  812 
  813         g_topology_lock();
  814         g_vfs_close(ump->um_cp);
  815         g_topology_unlock();
  816         vrele(ump->um_devvp);
  817         sump = fs->e2fs_clustersum;
  818         for (i = 0; i < fs->e2fs_gcount; i++, sump++)
  819                 free(sump->cs_sum, M_EXT2MNT);
  820         free(fs->e2fs_clustersum, M_EXT2MNT);
  821         free(fs->e2fs_maxcluster, M_EXT2MNT);
  822         free(fs->e2fs_gd, M_EXT2MNT);
  823         free(fs->e2fs_contigdirs, M_EXT2MNT);
  824         free(fs->e2fs, M_EXT2MNT);
  825         free(fs, M_EXT2MNT);
  826         free(ump, M_EXT2MNT);
  827         mp->mnt_data = NULL;
  828         MNT_ILOCK(mp);
  829         mp->mnt_flag &= ~MNT_LOCAL;
  830         MNT_IUNLOCK(mp);
  831         return (error);
  832 }
  833 
  834 /*
  835  * Flush out all the files in a filesystem.
  836  */
  837 static int
  838 ext2_flushfiles(struct mount *mp, int flags, struct thread *td)
  839 {
  840         int error;
  841 
  842         error = vflush(mp, 0, flags, td);
  843         return (error);
  844 }
  845 
  846 /*
  847  * Get filesystem statistics.
  848  */
  849 int
  850 ext2_statfs(struct mount *mp, struct statfs *sbp)
  851 {
  852         struct ext2mount *ump;
  853         struct m_ext2fs *fs;
  854         uint32_t overhead, overhead_per_group, ngdb;
  855         int i, ngroups;
  856 
  857         ump = VFSTOEXT2(mp);
  858         fs = ump->um_e2fs;
  859         if (fs->e2fs->e2fs_magic != E2FS_MAGIC)
  860                 panic("ext2_statfs");
  861 
  862         /*
  863          * Compute the overhead (FS structures)
  864          */
  865         overhead_per_group =
  866             1 /* block bitmap */ +
  867             1 /* inode bitmap */ +
  868             fs->e2fs_itpg;
  869         overhead = fs->e2fs->e2fs_first_dblock +
  870             fs->e2fs_gcount * overhead_per_group;
  871         if (fs->e2fs->e2fs_rev > E2FS_REV0 &&
  872             fs->e2fs->e2fs_features_rocompat & EXT2F_ROCOMPAT_SPARSESUPER) {
  873                 for (i = 0, ngroups = 0; i < fs->e2fs_gcount; i++) {
  874                         if (ext2_cg_has_sb(fs, i))
  875                                 ngroups++;
  876                 }
  877         } else {
  878                 ngroups = fs->e2fs_gcount;
  879         }
  880         ngdb = fs->e2fs_gdbcount;
  881         if (fs->e2fs->e2fs_rev > E2FS_REV0 &&
  882             fs->e2fs->e2fs_features_compat & EXT2F_COMPAT_RESIZE)
  883                 ngdb += fs->e2fs->e2fs_reserved_ngdb;
  884         overhead += ngroups * (1 /* superblock */ + ngdb);
  885 
  886         sbp->f_bsize = EXT2_FRAG_SIZE(fs);
  887         sbp->f_iosize = EXT2_BLOCK_SIZE(fs);
  888         sbp->f_blocks = fs->e2fs_bcount - overhead;
  889         sbp->f_bfree = fs->e2fs_fbcount;
  890         sbp->f_bavail = sbp->f_bfree - fs->e2fs_rbcount;
  891         sbp->f_files = fs->e2fs->e2fs_icount;
  892         sbp->f_ffree = fs->e2fs->e2fs_ficount;
  893         return (0);
  894 }
  895 
  896 /*
  897  * Go through the disk queues to initiate sandbagged IO;
  898  * go through the inodes to write those that have been modified;
  899  * initiate the writing of the super block if it has been modified.
  900  *
  901  * Note: we are always called with the filesystem marked `MPBUSY'.
  902  */
  903 static int
  904 ext2_sync(struct mount *mp, int waitfor)
  905 {
  906         struct vnode *mvp, *vp;
  907         struct thread *td;
  908         struct inode *ip;
  909         struct ext2mount *ump = VFSTOEXT2(mp);
  910         struct m_ext2fs *fs;
  911         int error, allerror = 0;
  912 
  913         td = curthread;
  914         fs = ump->um_e2fs;
  915         if (fs->e2fs_fmod != 0 && fs->e2fs_ronly != 0) {                /* XXX */
  916                 printf("fs = %s\n", fs->e2fs_fsmnt);
  917                 panic("ext2_sync: rofs mod");
  918         }
  919 
  920         /*
  921          * Write back each (modified) inode.
  922          */
  923 loop:
  924         MNT_VNODE_FOREACH_ALL(vp, mp, mvp) {
  925                 if (vp->v_type == VNON) {
  926                         VI_UNLOCK(vp);
  927                         continue;
  928                 }
  929                 ip = VTOI(vp);
  930                 if ((ip->i_flag &
  931                     (IN_ACCESS | IN_CHANGE | IN_MODIFIED | IN_UPDATE)) == 0 &&
  932                     (vp->v_bufobj.bo_dirty.bv_cnt == 0 ||
  933                     waitfor == MNT_LAZY)) {
  934                         VI_UNLOCK(vp);
  935                         continue;
  936                 }
  937                 error = vget(vp, LK_EXCLUSIVE | LK_NOWAIT | LK_INTERLOCK, td);
  938                 if (error) {
  939                         if (error == ENOENT) {
  940                                 MNT_VNODE_FOREACH_ALL_ABORT(mp, mvp);
  941                                 goto loop;
  942                         }
  943                         continue;
  944                 }
  945                 if ((error = VOP_FSYNC(vp, waitfor, td)) != 0)
  946                         allerror = error;
  947                 VOP_UNLOCK(vp, 0);
  948                 vrele(vp);
  949         }
  950 
  951         /*
  952          * Force stale filesystem control information to be flushed.
  953          */
  954         if (waitfor != MNT_LAZY) {
  955                 vn_lock(ump->um_devvp, LK_EXCLUSIVE | LK_RETRY);
  956                 if ((error = VOP_FSYNC(ump->um_devvp, waitfor, td)) != 0)
  957                         allerror = error;
  958                 VOP_UNLOCK(ump->um_devvp, 0);
  959         }
  960 
  961         /*
  962          * Write back modified superblock.
  963          */
  964         if (fs->e2fs_fmod != 0) {
  965                 fs->e2fs_fmod = 0;
  966                 fs->e2fs->e2fs_wtime = time_second;
  967                 if ((error = ext2_cgupdate(ump, waitfor)) != 0)
  968                         allerror = error;
  969         }
  970         return (allerror);
  971 }
  972 
  973 /*
  974  * Look up an EXT2FS dinode number to find its incore vnode, otherwise read it
  975  * in from disk.  If it is in core, wait for the lock bit to clear, then
  976  * return the inode locked.  Detection and handling of mount points must be
  977  * done by the calling routine.
  978  */
  979 static int
  980 ext2_vget(struct mount *mp, ino_t ino, int flags, struct vnode **vpp)
  981 {
  982         struct m_ext2fs *fs;
  983         struct inode *ip;
  984         struct ext2mount *ump;
  985         struct buf *bp;
  986         struct vnode *vp;
  987         struct thread *td;
  988         int i, error;
  989         int used_blocks;
  990 
  991         td = curthread;
  992         error = vfs_hash_get(mp, ino, flags, td, vpp, NULL, NULL);
  993         if (error || *vpp != NULL)
  994                 return (error);
  995 
  996         ump = VFSTOEXT2(mp);
  997         ip = malloc(sizeof(struct inode), M_EXT2NODE, M_WAITOK | M_ZERO);
  998 
  999         /* Allocate a new vnode/inode. */
 1000         if ((error = getnewvnode("ext2fs", mp, &ext2_vnodeops, &vp)) != 0) {
 1001                 *vpp = NULL;
 1002                 free(ip, M_EXT2NODE);
 1003                 return (error);
 1004         }
 1005         vp->v_data = ip;
 1006         ip->i_vnode = vp;
 1007         ip->i_e2fs = fs = ump->um_e2fs;
 1008         ip->i_ump = ump;
 1009         ip->i_number = ino;
 1010 
 1011         lockmgr(vp->v_vnlock, LK_EXCLUSIVE, NULL);
 1012         error = insmntque(vp, mp);
 1013         if (error != 0) {
 1014                 free(ip, M_EXT2NODE);
 1015                 *vpp = NULL;
 1016                 return (error);
 1017         }
 1018         error = vfs_hash_insert(vp, ino, flags, td, vpp, NULL, NULL);
 1019         if (error || *vpp != NULL)
 1020                 return (error);
 1021 
 1022         /* Read in the disk contents for the inode, copy into the inode. */
 1023         if ((error = bread(ump->um_devvp, fsbtodb(fs, ino_to_fsba(fs, ino)),
 1024             (int)fs->e2fs_bsize, NOCRED, &bp)) != 0) {
 1025                 /*
 1026                  * The inode does not contain anything useful, so it would
 1027                  * be misleading to leave it on its hash chain. With mode
 1028                  * still zero, it will be unlinked and returned to the free
 1029                  * list by vput().
 1030                  */
 1031                 brelse(bp);
 1032                 vput(vp);
 1033                 *vpp = NULL;
 1034                 return (error);
 1035         }
 1036         /* convert ext2 inode to dinode */
 1037         error = ext2_ei2i((struct ext2fs_dinode *)((char *)bp->b_data +
 1038             EXT2_INODE_SIZE(fs) * ino_to_fsbo(fs, ino)), ip);
 1039         if (error) {
 1040                 printf("ext2fs: Bad inode %lu csum - run fsck\n",
 1041                     (unsigned long)ino);
 1042                 brelse(bp);
 1043                 vput(vp);
 1044                 *vpp = NULL;
 1045                 return (error);
 1046         }
 1047         ip->i_block_group = ino_to_cg(fs, ino);
 1048         ip->i_next_alloc_block = 0;
 1049         ip->i_next_alloc_goal = 0;
 1050 
 1051         /*
 1052          * Now we want to make sure that block pointers for unused
 1053          * blocks are zeroed out - ext2_balloc depends on this
 1054          * although for regular files and directories only
 1055          *
 1056          * If IN_E4EXTENTS is enabled, unused blocks are not zeroed
 1057          * out because we could corrupt the extent tree.
 1058          */
 1059         if (!(ip->i_flag & IN_E4EXTENTS) &&
 1060             (S_ISDIR(ip->i_mode) || S_ISREG(ip->i_mode))) {
 1061                 used_blocks = howmany(ip->i_size, fs->e2fs_bsize);
 1062                 for (i = used_blocks; i < EXT2_NDIR_BLOCKS; i++)
 1063                         ip->i_db[i] = 0;
 1064         }
 1065 #ifdef EXT2FS_DEBUG
 1066         ext2_print_inode(ip);
 1067         ext4_ext_print_extent_tree_status(ip);
 1068 #endif
 1069         bqrelse(bp);
 1070 
 1071         /*
 1072          * Initialize the vnode from the inode, check for aliases.
 1073          * Note that the underlying vnode may have changed.
 1074          */
 1075         if ((error = ext2_vinit(mp, &ext2_fifoops, &vp)) != 0) {
 1076                 vput(vp);
 1077                 *vpp = NULL;
 1078                 return (error);
 1079         }
 1080 
 1081         /*
 1082          * Finish inode initialization.
 1083          */
 1084 
 1085         *vpp = vp;
 1086         return (0);
 1087 }
 1088 
 1089 /*
 1090  * File handle to vnode
 1091  *
 1092  * Have to be really careful about stale file handles:
 1093  * - check that the inode number is valid
 1094  * - call ext2_vget() to get the locked inode
 1095  * - check for an unallocated inode (i_mode == 0)
 1096  * - check that the given client host has export rights and return
 1097  *   those rights via. exflagsp and credanonp
 1098  */
 1099 static int
 1100 ext2_fhtovp(struct mount *mp, struct fid *fhp, int flags, struct vnode **vpp)
 1101 {
 1102         struct inode *ip;
 1103         struct ufid *ufhp;
 1104         struct vnode *nvp;
 1105         struct m_ext2fs *fs;
 1106         int error;
 1107 
 1108         ufhp = (struct ufid *)fhp;
 1109         fs = VFSTOEXT2(mp)->um_e2fs;
 1110         if (ufhp->ufid_ino < EXT2_ROOTINO ||
 1111             ufhp->ufid_ino > fs->e2fs_gcount * fs->e2fs->e2fs_ipg)
 1112                 return (ESTALE);
 1113 
 1114         error = VFS_VGET(mp, ufhp->ufid_ino, LK_EXCLUSIVE, &nvp);
 1115         if (error) {
 1116                 *vpp = NULLVP;
 1117                 return (error);
 1118         }
 1119         ip = VTOI(nvp);
 1120         if (ip->i_mode == 0 ||
 1121             ip->i_gen != ufhp->ufid_gen || ip->i_nlink <= 0) {
 1122                 vput(nvp);
 1123                 *vpp = NULLVP;
 1124                 return (ESTALE);
 1125         }
 1126         *vpp = nvp;
 1127         vnode_create_vobject(*vpp, 0, curthread);
 1128         return (0);
 1129 }
 1130 
 1131 /*
 1132  * Write a superblock and associated information back to disk.
 1133  */
 1134 static int
 1135 ext2_sbupdate(struct ext2mount *mp, int waitfor)
 1136 {
 1137         struct m_ext2fs *fs = mp->um_e2fs;
 1138         struct ext2fs *es = fs->e2fs;
 1139         struct buf *bp;
 1140         int error = 0;
 1141 
 1142         es->e2fs_bcount = fs->e2fs_bcount & 0xffffffff;
 1143         es->e2fs_rbcount = fs->e2fs_rbcount & 0xffffffff;
 1144         es->e2fs_fbcount = fs->e2fs_fbcount & 0xffffffff;
 1145         if (EXT2_HAS_INCOMPAT_FEATURE(fs, EXT2F_INCOMPAT_64BIT)) {
 1146                 es->e4fs_bcount_hi = fs->e2fs_bcount >> 32;
 1147                 es->e4fs_rbcount_hi = fs->e2fs_rbcount >> 32;
 1148                 es->e4fs_fbcount_hi = fs->e2fs_fbcount >> 32;
 1149         }
 1150 
 1151         if (EXT2_HAS_RO_COMPAT_FEATURE(fs, EXT2F_ROCOMPAT_METADATA_CKSUM))
 1152                 ext2_sb_csum_set(fs);
 1153 
 1154         bp = getblk(mp->um_devvp, SBLOCK, SBSIZE, 0, 0, 0);
 1155         bcopy((caddr_t)es, bp->b_data, (u_int)sizeof(struct ext2fs));
 1156         if (waitfor == MNT_WAIT)
 1157                 error = bwrite(bp);
 1158         else
 1159                 bawrite(bp);
 1160 
 1161         /*
 1162          * The buffers for group descriptors, inode bitmaps and block bitmaps
 1163          * are not busy at this point and are (hopefully) written by the
 1164          * usual sync mechanism. No need to write them here.
 1165          */
 1166         return (error);
 1167 }
 1168 int
 1169 ext2_cgupdate(struct ext2mount *mp, int waitfor)
 1170 {
 1171         struct m_ext2fs *fs = mp->um_e2fs;
 1172         struct buf *bp;
 1173         int i, j, g_count = 0, error = 0, allerror = 0;
 1174 
 1175         allerror = ext2_sbupdate(mp, waitfor);
 1176 
 1177         /* Update gd csums */
 1178         if (EXT2_HAS_RO_COMPAT_FEATURE(fs, EXT2F_ROCOMPAT_GDT_CSUM) ||
 1179             EXT2_HAS_RO_COMPAT_FEATURE(fs, EXT2F_ROCOMPAT_METADATA_CKSUM))
 1180                 ext2_gd_csum_set(fs);
 1181 
 1182         for (i = 0; i < fs->e2fs_gdbcount; i++) {
 1183                 bp = getblk(mp->um_devvp, fsbtodb(fs,
 1184                     cg_location(fs, i)),
 1185                     fs->e2fs_bsize, 0, 0, 0);
 1186                 if (EXT2_HAS_INCOMPAT_FEATURE(fs, EXT2F_INCOMPAT_64BIT)) {
 1187                         memcpy(bp->b_data, &fs->e2fs_gd[
 1188                             i * fs->e2fs_bsize / sizeof(struct ext2_gd)],
 1189                             fs->e2fs_bsize);
 1190                 } else {
 1191                         for (j = 0; j < fs->e2fs_bsize / E2FS_REV0_GD_SIZE &&
 1192                             g_count < fs->e2fs_gcount; j++, g_count++)
 1193                                 memcpy(bp->b_data + j * E2FS_REV0_GD_SIZE,
 1194                                     &fs->e2fs_gd[g_count], E2FS_REV0_GD_SIZE);
 1195                 }
 1196                 if (waitfor == MNT_WAIT)
 1197                         error = bwrite(bp);
 1198                 else
 1199                         bawrite(bp);
 1200         }
 1201 
 1202         if (!allerror && error)
 1203                 allerror = error;
 1204         return (allerror);
 1205 }
 1206 
 1207 /*
 1208  * Return the root of a filesystem.
 1209  */
 1210 static int
 1211 ext2_root(struct mount *mp, int flags, struct vnode **vpp)
 1212 {
 1213         struct vnode *nvp;
 1214         int error;
 1215 
 1216         error = VFS_VGET(mp, EXT2_ROOTINO, LK_EXCLUSIVE, &nvp);
 1217         if (error)
 1218                 return (error);
 1219         *vpp = nvp;
 1220         return (0);
 1221 }

Cache object: 1a43399d71f2dea1f87ee78ea45915b9


[ 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.