LCOV - code coverage report
Current view: top level - ufs/ext2fs - ext2fs_vfsops.c (source / functions) Hit Total Coverage
Test: 6.4 Lines: 0 539 0.0 %
Date: 2018-10-19 03:25:38 Functions: 0 20 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*      $OpenBSD: ext2fs_vfsops.c,v 1.109 2018/05/29 14:29:52 visa Exp $        */
       2             : /*      $NetBSD: ext2fs_vfsops.c,v 1.1 1997/06/11 09:34:07 bouyer Exp $ */
       3             : 
       4             : /*
       5             :  * Copyright (c) 1997 Manuel Bouyer.
       6             :  * Copyright (c) 1989, 1991, 1993, 1994
       7             :  *      The Regents of the University of California.  All rights reserved.
       8             :  *
       9             :  * Redistribution and use in source and binary forms, with or without
      10             :  * modification, are permitted provided that the following conditions
      11             :  * are met:
      12             :  * 1. Redistributions of source code must retain the above copyright
      13             :  *      notice, this list of conditions and the following disclaimer.
      14             :  * 2. Redistributions in binary form must reproduce the above copyright
      15             :  *      notice, this list of conditions and the following disclaimer in the
      16             :  *      documentation and/or other materials provided with the distribution.
      17             :  * 3. Neither the name of the University nor the names of its contributors
      18             :  *      may be used to endorse or promote products derived from this software
      19             :  *      without specific prior written permission.
      20             :  *
      21             :  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
      22             :  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
      23             :  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
      24             :  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
      25             :  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
      26             :  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
      27             :  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
      28             :  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
      29             :  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
      30             :  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
      31             :  * SUCH DAMAGE.
      32             :  *
      33             :  *      @(#)ffs_vfsops.c        8.14 (Berkeley) 11/28/94
      34             :  * Modified for ext2fs by Manuel Bouyer.
      35             :  */
      36             : 
      37             : #include <sys/param.h>
      38             : #include <sys/systm.h>
      39             : #include <sys/namei.h>
      40             : #include <sys/proc.h>
      41             : #include <sys/kernel.h>
      42             : #include <sys/vnode.h>
      43             : #include <sys/socket.h>
      44             : #include <sys/mount.h>
      45             : #include <sys/buf.h>
      46             : #include <sys/disk.h>
      47             : #include <sys/mbuf.h>
      48             : #include <sys/fcntl.h>
      49             : #include <sys/disklabel.h>
      50             : #include <sys/ioctl.h>
      51             : #include <sys/errno.h>
      52             : #include <sys/malloc.h>
      53             : #include <sys/pool.h>
      54             : #include <sys/lock.h>
      55             : #include <sys/dkio.h>
      56             : #include <sys/specdev.h>
      57             : 
      58             : #include <ufs/ufs/quota.h>
      59             : #include <ufs/ufs/ufsmount.h>
      60             : #include <ufs/ufs/inode.h>
      61             : #include <ufs/ufs/dir.h>
      62             : #include <ufs/ufs/ufs_extern.h>
      63             : 
      64             : #include <ufs/ext2fs/ext2fs.h>
      65             : #include <ufs/ext2fs/ext2fs_extern.h>
      66             : 
      67             : extern struct lock ufs_hashlock;
      68             : 
      69             : int ext2fs_sbupdate(struct ufsmount *, int);
      70             : static int      e2fs_sbcheck(struct ext2fs *, int);
      71             : 
      72             : const struct vfsops ext2fs_vfsops = {
      73             :         ext2fs_mount,
      74             :         ufs_start,
      75             :         ext2fs_unmount,
      76             :         ufs_root,
      77             :         ufs_quotactl,
      78             :         ext2fs_statfs,
      79             :         ext2fs_sync,
      80             :         ext2fs_vget,
      81             :         ext2fs_fhtovp,
      82             :         ext2fs_vptofh,
      83             :         ext2fs_init,
      84             :         ext2fs_sysctl,
      85             :         ufs_check_export
      86             : };
      87             : 
      88             : struct pool ext2fs_inode_pool;
      89             : struct pool ext2fs_dinode_pool;
      90             : 
      91             : extern u_long ext2gennumber;
      92             : 
      93             : int
      94           0 : ext2fs_init(struct vfsconf *vfsp)
      95             : {
      96           0 :         pool_init(&ext2fs_inode_pool, sizeof(struct inode), 0,
      97             :             IPL_NONE, PR_WAITOK, "ext2inopl", NULL);
      98           0 :         pool_init(&ext2fs_dinode_pool, sizeof(struct ext2fs_dinode), 0,
      99             :             IPL_NONE, PR_WAITOK, "ext2dinopl", NULL);
     100             : 
     101           0 :         return (ufs_init(vfsp));
     102             : }
     103             : 
     104             : /*
     105             :  * Called by main() when ext2fs is going to be mounted as root.
     106             :  *
     107             :  * Name is updated by mount(8) after booting.
     108             :  */
     109             : #define ROOTNAME        "root_device"
     110             : 
     111             : int
     112           0 : ext2fs_mountroot(void)
     113             : {
     114             :         struct m_ext2fs *fs;
     115           0 :         struct mount *mp;
     116           0 :         struct proc *p = curproc;       /* XXX */
     117             :         struct ufsmount *ump;
     118             :         int error;
     119             : 
     120             :         /*
     121             :          * Get vnodes for swapdev and rootdev.
     122             :          */
     123           0 :         if (bdevvp(swapdev, &swapdev_vp) || bdevvp(rootdev, &rootvp))
     124           0 :                 panic("ext2fs_mountroot: can't setup bdevvp's");
     125             : 
     126           0 :         if ((error = vfs_rootmountalloc("ext2fs", "root_device", &mp)) != 0) {
     127           0 :                 vrele(rootvp);
     128           0 :                 return (error);
     129             :         }
     130             : 
     131           0 :         if ((error = ext2fs_mountfs(rootvp, mp, p)) != 0) {
     132           0 :                 mp->mnt_vfc->vfc_refcount--;
     133           0 :                 vfs_unbusy(mp);
     134           0 :                 free(mp, M_MOUNT, sizeof *mp);
     135           0 :                 vrele(rootvp);
     136           0 :                 return (error);
     137             :         }
     138             : 
     139           0 :         TAILQ_INSERT_TAIL(&mountlist, mp, mnt_list);
     140           0 :         ump = VFSTOUFS(mp);
     141           0 :         fs = ump->um_e2fs;
     142           0 :         memset(fs->e2fs_fsmnt, 0, sizeof(fs->e2fs_fsmnt));
     143           0 :         strlcpy(fs->e2fs_fsmnt, mp->mnt_stat.f_mntonname, sizeof(fs->e2fs_fsmnt));
     144           0 :         if (fs->e2fs.e2fs_rev > E2FS_REV0) {
     145           0 :                 memset(fs->e2fs.e2fs_fsmnt, 0, sizeof(fs->e2fs.e2fs_fsmnt));
     146           0 :                 strlcpy(fs->e2fs.e2fs_fsmnt, mp->mnt_stat.f_mntonname,
     147             :                     sizeof(fs->e2fs.e2fs_fsmnt));
     148           0 :         }
     149           0 :         (void)ext2fs_statfs(mp, &mp->mnt_stat, p);
     150           0 :         vfs_unbusy(mp);
     151           0 :         inittodr(fs->e2fs.e2fs_wtime);
     152           0 :         return (0);
     153           0 : }
     154             : 
     155             : /*
     156             :  * VFS Operations.
     157             :  *
     158             :  * mount system call
     159             :  */
     160             : int
     161           0 : ext2fs_mount(struct mount *mp, const char *path, void *data,
     162             :     struct nameidata *ndp, struct proc *p)
     163             : {
     164             :         struct vnode *devvp;
     165           0 :         struct ufs_args *args = data;
     166             :         struct ufsmount *ump = NULL;
     167             :         struct m_ext2fs *fs;
     168           0 :         char fname[MNAMELEN];
     169           0 :         char fspec[MNAMELEN];
     170             :         int error, flags;
     171             : 
     172             :         /*
     173             :          * If updating, check whether changing from read-only to
     174             :          * read/write; if there is no device name, that's all we do.
     175             :          */
     176           0 :         if (mp->mnt_flag & MNT_UPDATE) {
     177           0 :                 ump = VFSTOUFS(mp);
     178           0 :                 fs = ump->um_e2fs;
     179           0 :                 if (fs->e2fs_ronly == 0 && (mp->mnt_flag & MNT_RDONLY)) {
     180             :                         flags = WRITECLOSE;
     181           0 :                         if (mp->mnt_flag & MNT_FORCE)
     182           0 :                                 flags |= FORCECLOSE;
     183           0 :                         error = ext2fs_flushfiles(mp, flags, p);
     184           0 :                         if (error == 0 &&
     185           0 :                             ext2fs_cgupdate(ump, MNT_WAIT) == 0 &&
     186           0 :                             (fs->e2fs.e2fs_state & E2FS_ERRORS) == 0) {
     187           0 :                                 fs->e2fs.e2fs_state = E2FS_ISCLEAN;
     188           0 :                                 (void)ext2fs_sbupdate(ump, MNT_WAIT);
     189           0 :                         }
     190           0 :                         if (error)
     191           0 :                                 return (error);
     192           0 :                         fs->e2fs_ronly = 1;
     193           0 :                 }
     194           0 :                 if (mp->mnt_flag & MNT_RELOAD) {
     195           0 :                         error = ext2fs_reload(mp, ndp->ni_cnd.cn_cred, p);
     196           0 :                         if (error)
     197           0 :                                 return (error);
     198             :                 }
     199           0 :                 if (fs->e2fs_ronly && (mp->mnt_flag & MNT_WANTRDWR)) {
     200           0 :                         fs->e2fs_ronly = 0;
     201           0 :                         if (fs->e2fs.e2fs_state == E2FS_ISCLEAN)
     202           0 :                                 fs->e2fs.e2fs_state = 0;
     203             :                         else
     204           0 :                                 fs->e2fs.e2fs_state = E2FS_ERRORS;
     205           0 :                         fs->e2fs_fmod = 1;
     206           0 :                 }
     207           0 :                 if (args && args->fspec == NULL) {
     208             :                         /*
     209             :                          * Process export requests.
     210             :                          */
     211           0 :                         return (vfs_export(mp, &ump->um_export,
     212           0 :                             &args->export_info));
     213             :                 }
     214           0 :                 if (args == NULL)
     215             :                         goto success;
     216             :         }
     217             :         /*
     218             :          * Not an update, or updating the name: look up the name
     219             :          * and verify that it refers to a sensible block device.
     220             :          */
     221           0 :         error = copyinstr(args->fspec, fspec, sizeof(fspec), NULL);
     222           0 :         if (error)
     223             :                 goto error;
     224             : 
     225           0 :         if (disk_map(fspec, fname, MNAMELEN, DM_OPENBLCK) == -1)
     226           0 :                 memcpy(fname, fspec, sizeof(fname));
     227             : 
     228           0 :         NDINIT(ndp, LOOKUP, FOLLOW, UIO_SYSSPACE, fname, p);
     229           0 :         if ((error = namei(ndp)) != 0)
     230             :                 goto error;
     231           0 :         devvp = ndp->ni_vp;
     232             : 
     233           0 :         if (devvp->v_type != VBLK) {
     234             :                 error = ENOTBLK;
     235           0 :                 goto error_devvp;
     236             :         }
     237           0 :         if (major(devvp->v_rdev) >= nblkdev) {
     238             :                 error = ENXIO;
     239           0 :                 goto error_devvp;
     240             :         }
     241           0 :         if ((mp->mnt_flag & MNT_UPDATE) == 0)
     242           0 :                 error = ext2fs_mountfs(devvp, mp, p);
     243             :         else {
     244           0 :                 if (devvp != ump->um_devvp)
     245           0 :                         error = EINVAL; /* XXX needs translation */
     246             :                 else
     247           0 :                         vrele(devvp);
     248             :         }
     249           0 :         if (error)
     250             :                 goto error_devvp;
     251           0 :         ump = VFSTOUFS(mp);
     252           0 :         fs = ump->um_e2fs;
     253             : 
     254           0 :         memset(fs->e2fs_fsmnt, 0, sizeof(fs->e2fs_fsmnt));
     255           0 :         strlcpy(fs->e2fs_fsmnt, path, sizeof(fs->e2fs_fsmnt));
     256           0 :         if (fs->e2fs.e2fs_rev > E2FS_REV0) {
     257           0 :                 memset(fs->e2fs.e2fs_fsmnt, 0, sizeof(fs->e2fs.e2fs_fsmnt));
     258           0 :                 strlcpy(fs->e2fs.e2fs_fsmnt, mp->mnt_stat.f_mntonname,
     259             :                     sizeof(fs->e2fs.e2fs_fsmnt));
     260           0 :         }
     261           0 :         memcpy(mp->mnt_stat.f_mntonname, fs->e2fs_fsmnt, MNAMELEN);
     262           0 :         memset(mp->mnt_stat.f_mntfromname, 0, MNAMELEN);
     263           0 :         strlcpy(mp->mnt_stat.f_mntfromname, fname, MNAMELEN);
     264           0 :         memset(mp->mnt_stat.f_mntfromspec, 0, MNAMELEN);
     265           0 :         strlcpy(mp->mnt_stat.f_mntfromspec, fspec, MNAMELEN);
     266           0 :         memcpy(&mp->mnt_stat.mount_info.ufs_args, args, sizeof(*args));
     267             : 
     268           0 :         if (fs->e2fs_fmod != 0) {    /* XXX */
     269           0 :                 fs->e2fs_fmod = 0;
     270           0 :                 if (fs->e2fs.e2fs_state == 0)
     271           0 :                         fs->e2fs.e2fs_wtime = time_second;
     272             :                 else
     273           0 :                         printf("%s: file system not clean; please fsck(8)\n",
     274             :                             mp->mnt_stat.f_mntfromname);
     275           0 :                 ext2fs_cgupdate(ump, MNT_WAIT);
     276           0 :         }
     277             : 
     278             :         goto success;
     279             : 
     280             : error_devvp:
     281             :         /* Error with devvp held. */
     282           0 :         vrele(devvp);
     283             : 
     284             : error:
     285             :         /* Error with no state to backout. */
     286             : 
     287             : success:
     288           0 :         return (error);
     289           0 : }
     290             : 
     291             : int ext2fs_reload_vnode(struct vnode *, void *args);
     292             : 
     293             : struct ext2fs_reload_args {
     294             :         struct m_ext2fs *fs;
     295             :         struct proc *p;
     296             :         struct ucred *cred;
     297             :         struct vnode *devvp;
     298             : };
     299             : 
     300             : int
     301           0 : ext2fs_reload_vnode(struct vnode *vp, void *args)
     302             : {
     303           0 :         struct ext2fs_reload_args *era = args;
     304           0 :         struct buf *bp;
     305             :         struct inode *ip;
     306             :         int error;
     307             :         caddr_t cp;
     308             : 
     309             :         /*
     310             :          * Step 4: invalidate all inactive vnodes.
     311             :          */
     312           0 :         if (vp->v_usecount == 0) {
     313           0 :                 vgonel(vp, era->p);
     314           0 :                 return (0);
     315             :         }
     316             : 
     317             :         /*
     318             :          * Step 5: invalidate all cached file data.
     319             :          */
     320           0 :         if (vget(vp, LK_EXCLUSIVE))
     321           0 :                 return (0);
     322             : 
     323           0 :         if (vinvalbuf(vp, 0, era->cred, era->p, 0, 0))
     324           0 :                 panic("ext2fs_reload: dirty2");
     325             :         /*
     326             :          * Step 6: re-read inode data for all active vnodes.
     327             :          */
     328           0 :         ip = VTOI(vp);
     329           0 :         error = bread(era->devvp,
     330           0 :             fsbtodb(era->fs, ino_to_fsba(era->fs, ip->i_number)),
     331           0 :             (int)era->fs->e2fs_bsize, &bp);
     332           0 :         if (error) {
     333           0 :                 vput(vp);
     334           0 :                 return (error);
     335             :         }
     336           0 :         cp = (caddr_t)bp->b_data +
     337           0 :             (ino_to_fsbo(era->fs, ip->i_number) * EXT2_DINODE_SIZE(era->fs));
     338           0 :         e2fs_iload(era->fs, (struct ext2fs_dinode *)cp, ip->i_e2din);
     339           0 :         brelse(bp);
     340           0 :         vput(vp);
     341           0 :         return (0);
     342           0 : }
     343             : 
     344             : static off_t
     345           0 : ext2fs_maxfilesize(struct m_ext2fs *fs)
     346             : {
     347           0 :         bool huge = fs->e2fs.e2fs_features_rocompat & EXT2F_ROCOMPAT_HUGE_FILE;
     348           0 :         off_t b = fs->e2fs_bsize / 4;
     349             :         off_t physically, logically;
     350             : 
     351           0 :         physically = dbtob(huge ? ((1ULL << 48) - 1) : UINT_MAX);
     352           0 :         logically = (12ULL + b + b*b + b*b*b) * fs->e2fs_bsize;
     353             : 
     354           0 :         return MIN(logically, physically);
     355             : }
     356             : 
     357             : static int
     358           0 : e2fs_sbfill(struct vnode *devvp, struct m_ext2fs *fs)
     359             : {
     360           0 :         struct buf *bp = NULL;
     361             :         int i, error;
     362             : 
     363             :         /* XXX assume hardware block size == 512 */
     364           0 :         fs->e2fs_ncg = howmany(fs->e2fs.e2fs_bcount - fs->e2fs.e2fs_first_dblock,
     365             :             fs->e2fs.e2fs_bpg);
     366           0 :         fs->e2fs_fsbtodb = fs->e2fs.e2fs_log_bsize + 1;
     367           0 :         fs->e2fs_bsize = 1024 << fs->e2fs.e2fs_log_bsize;
     368           0 :         fs->e2fs_bshift = LOG_MINBSIZE + fs->e2fs.e2fs_log_bsize;
     369           0 :         fs->e2fs_fsize = 1024 << fs->e2fs.e2fs_log_fsize;
     370             : 
     371           0 :         fs->e2fs_qbmask = fs->e2fs_bsize - 1;
     372           0 :         fs->e2fs_bmask = ~fs->e2fs_qbmask;
     373             : 
     374           0 :         fs->e2fs_ipb = fs->e2fs_bsize / EXT2_DINODE_SIZE(fs);
     375           0 :         fs->e2fs_itpg = fs->e2fs.e2fs_ipg / fs->e2fs_ipb;
     376             : 
     377             :         /* Re-read group descriptors from the disk. */
     378           0 :         fs->e2fs_ngdb = howmany(fs->e2fs_ncg,
     379             :             fs->e2fs_bsize / sizeof(struct ext2_gd));
     380           0 :         fs->e2fs_gd = mallocarray(fs->e2fs_ngdb, fs->e2fs_bsize,
     381             :             M_UFSMNT, M_WAITOK);
     382             : 
     383           0 :         for (i = 0; i < fs->e2fs_ngdb; ++i) {
     384           0 :                 daddr_t dblk = ((fs->e2fs_bsize > 1024) ? 0 : 1) + i + 1;
     385           0 :                 size_t gdesc = i * fs->e2fs_bsize / sizeof(struct ext2_gd);
     386             :                 struct ext2_gd *gd;
     387             : 
     388           0 :                 error = bread(devvp, fsbtodb(fs, dblk), fs->e2fs_bsize, &bp);
     389           0 :                 if (error) {
     390           0 :                         size_t gdescs_space = fs->e2fs_ngdb * fs->e2fs_bsize;
     391             : 
     392           0 :                         free(fs->e2fs_gd, M_UFSMNT, gdescs_space);
     393           0 :                         fs->e2fs_gd = NULL;
     394           0 :                         brelse(bp);
     395             :                         return (error);
     396             :                 }
     397             : 
     398           0 :                 gd = (struct ext2_gd *) bp->b_data;
     399           0 :                 e2fs_cgload(gd, fs->e2fs_gd + gdesc, fs->e2fs_bsize);
     400           0 :                 brelse(bp);
     401           0 :                 bp = NULL;
     402           0 :         }
     403             : 
     404           0 :         if ((fs->e2fs.e2fs_features_rocompat & EXT2F_ROCOMPAT_LARGEFILE) == 0 ||
     405           0 :             (fs->e2fs.e2fs_rev == E2FS_REV0))
     406           0 :                 fs->e2fs_maxfilesize = INT_MAX;
     407             :         else
     408           0 :                 fs->e2fs_maxfilesize = ext2fs_maxfilesize(fs);
     409             : 
     410           0 :         if (fs->e2fs.e2fs_features_incompat & EXT2F_INCOMPAT_EXTENTS)
     411           0 :                 fs->e2fs_maxfilesize *= 4;
     412             : 
     413           0 :         return (0);
     414           0 : }
     415             : 
     416             : /*
     417             :  * Reload all incore data for a filesystem (used after running fsck on
     418             :  * the root filesystem and finding things to fix). The filesystem must
     419             :  * be mounted read-only.
     420             :  *
     421             :  * Things to do to update the mount:
     422             :  *      1) invalidate all cached meta-data.
     423             :  *      2) re-read superblock from disk.
     424             :  *      3) re-read summary information from disk.
     425             :  *      4) invalidate all inactive vnodes.
     426             :  *      5) invalidate all cached file data.
     427             :  *      6) re-read inode data for all active vnodes.
     428             :  */
     429             : int
     430           0 : ext2fs_reload(struct mount *mountp, struct ucred *cred, struct proc *p)
     431             : {
     432             :         struct vnode *devvp;
     433           0 :         struct buf *bp;
     434             :         struct m_ext2fs *fs;
     435             :         struct ext2fs *newfs;
     436             :         int error;
     437           0 :         struct ext2fs_reload_args era;
     438             : 
     439           0 :         if ((mountp->mnt_flag & MNT_RDONLY) == 0)
     440           0 :                 return (EINVAL);
     441             :         /*
     442             :          * Step 1: invalidate all cached meta-data.
     443             :          */
     444           0 :         devvp = VFSTOUFS(mountp)->um_devvp;
     445           0 :         vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY);
     446           0 :         error = vinvalbuf(devvp, 0, cred, p, 0, 0);
     447           0 :         VOP_UNLOCK(devvp);
     448           0 :         if (error != 0)
     449           0 :                 panic("ext2fs_reload: dirty1");
     450             : 
     451             :         /*
     452             :          * Step 2: re-read superblock from disk.
     453             :          */
     454           0 :         error = bread(devvp, (daddr_t)(SBOFF / DEV_BSIZE), SBSIZE, &bp);
     455           0 :         if (error) {
     456           0 :                 brelse(bp);
     457           0 :                 return (error);
     458             :         }
     459           0 :         newfs = (struct ext2fs *)bp->b_data;
     460           0 :         error = e2fs_sbcheck(newfs, (mountp->mnt_flag & MNT_RDONLY));
     461           0 :         if (error) {
     462           0 :                 brelse(bp);
     463           0 :                 return (error);
     464             :         }
     465             : 
     466           0 :         fs = VFSTOUFS(mountp)->um_e2fs;
     467             :         /*
     468             :          * Copy in the new superblock, compute in-memory values
     469             :          * and load group descriptors.
     470             :          */
     471           0 :         e2fs_sbload(newfs, &fs->e2fs);
     472           0 :         if ((error = e2fs_sbfill(devvp, fs)) != 0)
     473           0 :                 return (error);
     474             : 
     475           0 :         era.p = p;
     476           0 :         era.cred = cred;
     477           0 :         era.fs = fs;
     478           0 :         era.devvp = devvp;
     479             : 
     480           0 :         error = vfs_mount_foreach_vnode(mountp, ext2fs_reload_vnode, &era);
     481             : 
     482           0 :         return (error);
     483           0 : }
     484             : 
     485             : /*
     486             :  * Common code for mount and mountroot
     487             :  */
     488             : int
     489           0 : ext2fs_mountfs(struct vnode *devvp, struct mount *mp, struct proc *p)
     490             : {
     491             :         struct ufsmount *ump;
     492           0 :         struct buf *bp;
     493             :         struct ext2fs *fs;
     494             :         dev_t dev;
     495             :         int error, ronly;
     496             :         struct ucred *cred;
     497             : 
     498           0 :         dev = devvp->v_rdev;
     499           0 :         cred = p ? p->p_ucred : NOCRED;
     500             :         /*
     501             :          * Disallow multiple mounts of the same device.
     502             :          * Disallow mounting of a device that is currently in use
     503             :          * (except for root, which might share swap device for miniroot).
     504             :          * Flush out any old buffers remaining from a previous use.
     505             :          */
     506           0 :         if ((error = vfs_mountedon(devvp)) != 0)
     507           0 :                 return (error);
     508           0 :         if (vcount(devvp) > 1 && devvp != rootvp)
     509           0 :                 return (EBUSY);
     510           0 :         vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY);
     511           0 :         error = vinvalbuf(devvp, V_SAVE, cred, p, 0, 0);
     512           0 :         VOP_UNLOCK(devvp);
     513           0 :         if (error != 0)
     514           0 :                 return (error);
     515             : 
     516           0 :         ronly = (mp->mnt_flag & MNT_RDONLY) != 0;
     517           0 :         error = VOP_OPEN(devvp, ronly ? FREAD : FREAD|FWRITE, FSCRED, p);
     518           0 :         if (error)
     519           0 :                 return (error);
     520             : 
     521           0 :         bp = NULL;
     522             :         ump = NULL;
     523             : 
     524             :         /*
     525             :          * Read the superblock from disk.
     526             :          */
     527           0 :         error = bread(devvp, (daddr_t)(SBOFF / DEV_BSIZE), SBSIZE, &bp);
     528           0 :         if (error)
     529             :                 goto out;
     530           0 :         fs = (struct ext2fs *)bp->b_data;
     531           0 :         error = e2fs_sbcheck(fs, ronly);
     532           0 :         if (error)
     533             :                 goto out;
     534             : 
     535           0 :         ump = malloc(sizeof *ump, M_UFSMNT, M_WAITOK | M_ZERO);
     536           0 :         ump->um_e2fs = malloc(sizeof(struct m_ext2fs), M_UFSMNT,
     537             :             M_WAITOK | M_ZERO);
     538             : 
     539             :         /*
     540             :          * Copy in the superblock, compute in-memory values
     541             :          * and load group descriptors.
     542             :          */
     543           0 :         e2fs_sbload(fs, &ump->um_e2fs->e2fs);
     544           0 :         if ((error = e2fs_sbfill(devvp, ump->um_e2fs)) != 0)
     545             :                 goto out;
     546           0 :         brelse(bp);
     547           0 :         bp = NULL;
     548           0 :         fs = &ump->um_e2fs->e2fs;
     549           0 :         ump->um_e2fs->e2fs_ronly = ronly;
     550           0 :         ump->um_fstype = UM_EXT2FS;
     551             : 
     552           0 :         if (ronly == 0) {
     553           0 :                 if (fs->e2fs_state == E2FS_ISCLEAN)
     554           0 :                         fs->e2fs_state = 0;
     555             :                 else
     556           0 :                         fs->e2fs_state = E2FS_ERRORS;
     557           0 :                 ump->um_e2fs->e2fs_fmod = 1;
     558           0 :         }
     559             : 
     560           0 :         mp->mnt_data = ump;
     561           0 :         mp->mnt_stat.f_fsid.val[0] = (long)dev;
     562           0 :         mp->mnt_stat.f_fsid.val[1] = mp->mnt_vfc->vfc_typenum;
     563           0 :         mp->mnt_stat.f_namemax = MAXNAMLEN;
     564           0 :         mp->mnt_flag |= MNT_LOCAL;
     565           0 :         ump->um_mountp = mp;
     566           0 :         ump->um_dev = dev;
     567           0 :         ump->um_devvp = devvp;
     568           0 :         ump->um_nindir = NINDIR(ump->um_e2fs);
     569           0 :         ump->um_bptrtodb = ump->um_e2fs->e2fs_fsbtodb;
     570           0 :         ump->um_seqinc = 1; /* no frags */
     571           0 :         ump->um_maxsymlinklen = EXT2_MAXSYMLINKLEN;
     572           0 :         devvp->v_specmountpoint = mp;
     573           0 :         return (0);
     574             : out:
     575           0 :         if (devvp->v_specinfo)
     576           0 :                 devvp->v_specmountpoint = NULL;
     577           0 :         if (bp)
     578           0 :                 brelse(bp);
     579           0 :         vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY);
     580           0 :         (void)VOP_CLOSE(devvp, ronly ? FREAD : FREAD|FWRITE, cred, p);
     581           0 :         VOP_UNLOCK(devvp);
     582           0 :         if (ump) {
     583           0 :                 free(ump->um_e2fs, M_UFSMNT, sizeof *ump->um_e2fs);
     584           0 :                 free(ump, M_UFSMNT, sizeof *ump);
     585           0 :                 mp->mnt_data = NULL;
     586           0 :         }
     587           0 :         return (error);
     588           0 : }
     589             : 
     590             : /*
     591             :  * unmount system call
     592             :  */
     593             : int
     594           0 : ext2fs_unmount(struct mount *mp, int mntflags, struct proc *p)
     595             : {
     596             :         struct ufsmount *ump;
     597             :         struct m_ext2fs *fs;
     598             :         int error, flags;
     599             :         size_t gdescs_space;
     600             : 
     601             :         flags = 0;
     602           0 :         if (mntflags & MNT_FORCE)
     603           0 :                 flags |= FORCECLOSE;
     604           0 :         if ((error = ext2fs_flushfiles(mp, flags, p)) != 0)
     605           0 :                 return (error);
     606           0 :         ump = VFSTOUFS(mp);
     607           0 :         fs = ump->um_e2fs;
     608           0 :         gdescs_space = fs->e2fs_ngdb * fs->e2fs_bsize;
     609             : 
     610           0 :         if (!fs->e2fs_ronly && ext2fs_cgupdate(ump, MNT_WAIT) == 0 &&
     611           0 :             (fs->e2fs.e2fs_state & E2FS_ERRORS) == 0) {
     612           0 :                 fs->e2fs.e2fs_state = E2FS_ISCLEAN;
     613           0 :                 (void) ext2fs_sbupdate(ump, MNT_WAIT);
     614           0 :         }
     615             : 
     616           0 :         if (ump->um_devvp->v_type != VBAD)
     617           0 :                 ump->um_devvp->v_specmountpoint = NULL;
     618           0 :         vn_lock(ump->um_devvp, LK_EXCLUSIVE | LK_RETRY);
     619           0 :         (void)VOP_CLOSE(ump->um_devvp, fs->e2fs_ronly ? FREAD : FREAD|FWRITE,
     620             :             NOCRED, p);
     621           0 :         vput(ump->um_devvp);
     622           0 :         free(fs->e2fs_gd, M_UFSMNT, gdescs_space);
     623           0 :         free(fs, M_UFSMNT, sizeof *fs);
     624           0 :         free(ump, M_UFSMNT, sizeof *ump);
     625           0 :         mp->mnt_data = NULL;
     626           0 :         mp->mnt_flag &= ~MNT_LOCAL;
     627           0 :         return (0);
     628           0 : }
     629             : 
     630             : /*
     631             :  * Flush out all the files in a filesystem.
     632             :  */
     633             : int
     634           0 : ext2fs_flushfiles(struct mount *mp, int flags, struct proc *p)
     635             : {
     636             :         struct ufsmount *ump;
     637             :         int error;
     638             : 
     639           0 :         ump = VFSTOUFS(mp);
     640             :         /*
     641             :          * Flush all the files.
     642             :          */
     643           0 :         if ((error = vflush(mp, NULL, flags)) != 0)
     644           0 :                 return (error);
     645             :         /*
     646             :          * Flush filesystem metadata.
     647             :          */
     648           0 :         vn_lock(ump->um_devvp, LK_EXCLUSIVE | LK_RETRY);
     649           0 :         error = VOP_FSYNC(ump->um_devvp, p->p_ucred, MNT_WAIT, p);
     650           0 :         VOP_UNLOCK(ump->um_devvp);
     651           0 :         return (error);
     652           0 : }
     653             : 
     654             : /*
     655             :  * Get file system statistics.
     656             :  */
     657             : int
     658           0 : ext2fs_statfs(struct mount *mp, struct statfs *sbp, struct proc *p)
     659             : {
     660             :         struct ufsmount *ump;
     661             :         struct m_ext2fs *fs;
     662             :         u_int32_t overhead, overhead_per_group;
     663             :         int i, ngroups;
     664             : 
     665           0 :         ump = VFSTOUFS(mp);
     666           0 :         fs = ump->um_e2fs;
     667           0 :         if (fs->e2fs.e2fs_magic != E2FS_MAGIC)
     668           0 :                 panic("ext2fs_statfs");
     669             : 
     670             :         /*
     671             :          * Compute the overhead (FS structures)
     672             :          */
     673           0 :         overhead_per_group = 1 /* block bitmap */ + 1 /* inode bitmap */ +
     674           0 :             fs->e2fs_itpg;
     675           0 :         overhead = fs->e2fs.e2fs_first_dblock +
     676           0 :             fs->e2fs_ncg * overhead_per_group;
     677           0 :         if (fs->e2fs.e2fs_rev > E2FS_REV0 &&
     678           0 :             fs->e2fs.e2fs_features_rocompat & EXT2F_ROCOMPAT_SPARSESUPER) {
     679           0 :                 for (i = 0, ngroups = 0; i < fs->e2fs_ncg; i++) {
     680           0 :                         if (cg_has_sb(i))
     681           0 :                                 ngroups++;
     682             :                 }
     683             :         } else {
     684           0 :                 ngroups = fs->e2fs_ncg;
     685             :         }
     686           0 :         overhead += ngroups * (1 + fs->e2fs_ngdb);
     687             : 
     688           0 :         sbp->f_bsize = fs->e2fs_bsize;
     689           0 :         sbp->f_iosize = fs->e2fs_bsize;
     690           0 :         sbp->f_blocks = fs->e2fs.e2fs_bcount - overhead;
     691           0 :         sbp->f_bfree = fs->e2fs.e2fs_fbcount;
     692           0 :         sbp->f_bavail = sbp->f_bfree - fs->e2fs.e2fs_rbcount;
     693           0 :         sbp->f_files =  fs->e2fs.e2fs_icount;
     694           0 :         sbp->f_favail = sbp->f_ffree = fs->e2fs.e2fs_ficount;
     695           0 :         copy_statfs_info(sbp, mp);
     696             : 
     697           0 :         return (0);
     698             : }
     699             : 
     700             : int ext2fs_sync_vnode(struct vnode *vp, void *);
     701             : 
     702             : struct ext2fs_sync_args {
     703             :         int allerror;
     704             :         int waitfor;
     705             :         int nlink0;
     706             :         int inflight;
     707             :         struct proc *p;
     708             :         struct ucred *cred;
     709             : };
     710             : 
     711             : int
     712           0 : ext2fs_sync_vnode(struct vnode *vp, void *args)
     713             : {
     714           0 :         struct ext2fs_sync_args *esa = args;
     715             :         struct inode *ip;
     716             :         int error, nlink0 = 0;
     717             : 
     718           0 :         if (vp->v_type == VNON)
     719           0 :                 return (0);
     720             : 
     721           0 :         if (vp->v_inflight)
     722           0 :                 esa->inflight = MIN(esa->inflight+1, 65536);
     723             : 
     724           0 :         ip = VTOI(vp);
     725             :         
     726           0 :         if (ip->i_e2fs_nlink == 0)
     727           0 :                 nlink0 = 1;
     728             : 
     729           0 :         if ((ip->i_flag & (IN_ACCESS | IN_CHANGE | IN_MODIFIED | IN_UPDATE)) == 0 &&
     730           0 :             LIST_EMPTY(&vp->v_dirtyblkhd)) {
     731             :                 goto end;
     732             :         }
     733             : 
     734           0 :         if (vget(vp, LK_EXCLUSIVE | LK_NOWAIT)) {
     735             :                 nlink0 = 1;     /* potentially */
     736           0 :                 goto end;
     737             :         }
     738             : 
     739           0 :         if ((error = VOP_FSYNC(vp, esa->cred, esa->waitfor, esa->p)) != 0)
     740           0 :                 esa->allerror = error;
     741           0 :         vput(vp);
     742             : end:
     743           0 :         esa->nlink0 = MIN(esa->nlink0 + nlink0, 65536);
     744           0 :         return (0);
     745           0 : }
     746             : /*
     747             :  * Go through the disk queues to initiate sandbagged IO;
     748             :  * go through the inodes to write those that have been modified;
     749             :  * initiate the writing of the super block if it has been modified.
     750             :  *
     751             :  * Should always be called with the mount point locked.
     752             :  */
     753             : int
     754           0 : ext2fs_sync(struct mount *mp, int waitfor, int stall,
     755             :     struct ucred *cred, struct proc *p)
     756             : {
     757           0 :         struct ufsmount *ump = VFSTOUFS(mp);
     758             :         struct m_ext2fs *fs;
     759             :         int error, allerror = 0, state, fmod;
     760           0 :         struct ext2fs_sync_args esa;
     761             : 
     762           0 :         fs = ump->um_e2fs;
     763           0 :         if (fs->e2fs_ronly != 0) {           /* XXX */
     764           0 :                 printf("fs = %s\n", fs->e2fs_fsmnt);
     765           0 :                 panic("update: rofs mod");
     766             :         }
     767             : 
     768             :         /*
     769             :          * Write back each (modified) inode.
     770             :          */
     771           0 :         esa.p = p;
     772           0 :         esa.cred = cred;
     773           0 :         esa.allerror = 0;
     774           0 :         esa.waitfor = waitfor;
     775           0 :         esa.nlink0 = 0;
     776           0 :         esa.inflight = 0;
     777             : 
     778           0 :         vfs_mount_foreach_vnode(mp, ext2fs_sync_vnode, &esa);
     779           0 :         if (esa.allerror != 0)
     780           0 :                 allerror = esa.allerror;
     781             : 
     782             :         /*
     783             :          * Force stale file system control information to be flushed.
     784             :          */
     785           0 :         if (waitfor != MNT_LAZY) {
     786           0 :                 vn_lock(ump->um_devvp, LK_EXCLUSIVE | LK_RETRY);
     787           0 :                 if ((error = VOP_FSYNC(ump->um_devvp, cred, waitfor, p)) != 0)
     788           0 :                         allerror = error;
     789           0 :                 VOP_UNLOCK(ump->um_devvp);
     790           0 :         }
     791             :         /*
     792             :          * Write back modified superblock.
     793             :          */
     794           0 :         state = fs->e2fs.e2fs_state;
     795           0 :         fmod = fs->e2fs_fmod;
     796           0 :         if (stall && fs->e2fs_ronly == 0) {
     797           0 :                 fs->e2fs_fmod = 1;
     798           0 :                 if (allerror == 0 && esa.nlink0 == 0 && esa.inflight == 0) {
     799           0 :                         if ((fs->e2fs.e2fs_state & E2FS_ERRORS) == 0)
     800           0 :                                 fs->e2fs.e2fs_state = E2FS_ISCLEAN;
     801             : #if 0
     802             :                         printf("%s force clean (dangling %d inflight %d)\n",
     803             :                             mp->mnt_stat.f_mntonname, esa.nlink0, esa.inflight);
     804             : #endif
     805             :                 } else {
     806           0 :                         fs->e2fs.e2fs_state = 0;
     807             : #if 0
     808             :                         printf("%s force dirty (dangling %d inflight %d)\n",
     809             :                             mp->mnt_stat.f_mntonname, esa.nlink0, esa.inflight);
     810             : #endif
     811             :                 }
     812             :         }               
     813           0 :         if (fs->e2fs_fmod != 0) {
     814           0 :                 fs->e2fs_fmod = 0;
     815           0 :                 fs->e2fs.e2fs_wtime = time_second;
     816           0 :                 if ((error = ext2fs_cgupdate(ump, waitfor)))
     817           0 :                         allerror = error;
     818             :         }
     819           0 :         fs->e2fs.e2fs_state = state;
     820           0 :         fs->e2fs_fmod = fmod;
     821           0 :         return (allerror);
     822           0 : }
     823             : 
     824             : /*
     825             :  * Look up a EXT2FS dinode number to find its incore vnode, otherwise read it
     826             :  * in from disk.  If it is in core, wait for the lock bit to clear, then
     827             :  * return the inode locked.  Detection and handling of mount points must be
     828             :  * done by the calling routine.
     829             :  */
     830             : int
     831           0 : ext2fs_vget(struct mount *mp, ino_t ino, struct vnode **vpp)
     832             : {
     833             :         struct m_ext2fs *fs;
     834             :         struct inode *ip;
     835             :         struct ext2fs_dinode *dp;
     836             :         struct ufsmount *ump;
     837           0 :         struct buf *bp;
     838           0 :         struct vnode *vp;
     839             :         dev_t dev;
     840             :         int error;
     841             : 
     842           0 :         if (ino > (ufsino_t)-1)
     843           0 :                 panic("ext2fs_vget: alien ino_t %llu",
     844             :                     (unsigned long long)ino);
     845             : 
     846           0 :         ump = VFSTOUFS(mp);
     847           0 :         dev = ump->um_dev;
     848             : 
     849             :  retry:
     850           0 :         if ((*vpp = ufs_ihashget(dev, ino)) != NULL)
     851           0 :                 return (0);
     852             : 
     853             :         /* Allocate a new vnode/inode. */
     854           0 :         if ((error = getnewvnode(VT_EXT2FS, mp, &ext2fs_vops, &vp)) != 0) {
     855           0 :                 *vpp = NULL;
     856           0 :                 return (error);
     857             :         }
     858             : 
     859           0 :         ip = pool_get(&ext2fs_inode_pool, PR_WAITOK|PR_ZERO);
     860           0 :         rrw_init_flags(&ip->i_lock, "inode", RWL_DUPOK | RWL_IS_VNODE);
     861           0 :         vp->v_data = ip;
     862           0 :         ip->i_vnode = vp;
     863           0 :         ip->i_ump = ump;
     864           0 :         ip->i_e2fs = fs = ump->um_e2fs;
     865           0 :         ip->i_dev = dev;
     866           0 :         ip->i_number = ino;
     867           0 :         ip->i_e2fs_last_lblk = 0;
     868           0 :         ip->i_e2fs_last_blk = 0;
     869             : 
     870             :         /*
     871             :          * Put it onto its hash chain and lock it so that other requests for
     872             :          * this inode will block if they arrive while we are sleeping waiting
     873             :          * for old data structures to be purged or for the contents of the
     874             :          * disk portion of this inode to be read.
     875             :          */
     876           0 :         error = ufs_ihashins(ip);
     877             : 
     878           0 :         if (error) {
     879           0 :                 vrele(vp);
     880             : 
     881           0 :                 if (error == EEXIST)
     882           0 :                         goto retry;
     883             : 
     884           0 :                 return (error);
     885             :         }
     886             : 
     887             :         /* Read in the disk contents for the inode, copy into the inode. */
     888           0 :         error = bread(ump->um_devvp, fsbtodb(fs, ino_to_fsba(fs, ino)),
     889           0 :             (int)fs->e2fs_bsize, &bp);
     890           0 :         if (error) {
     891             :                 /*
     892             :                  * The inode does not contain anything useful, so it would
     893             :                  * be misleading to leave it on its hash chain. With mode
     894             :                  * still zero, it will be unlinked and returned to the free
     895             :                  * list by vput().
     896             :                  */
     897           0 :                 vput(vp);
     898           0 :                 brelse(bp);
     899           0 :                 *vpp = NULL;
     900           0 :                 return (error);
     901             :         }
     902             : 
     903           0 :         dp = (struct ext2fs_dinode *) ((char *)bp->b_data
     904           0 :             + EXT2_DINODE_SIZE(fs) * ino_to_fsbo(fs, ino));
     905             : 
     906           0 :         ip->i_e2din = pool_get(&ext2fs_dinode_pool, PR_WAITOK);
     907           0 :         e2fs_iload(fs, dp, ip->i_e2din);
     908           0 :         brelse(bp);
     909             : 
     910           0 :         ip->i_effnlink = ip->i_e2fs_nlink;
     911             : 
     912             :         /*
     913             :          * The fields for storing the UID and GID of an ext2fs inode are
     914             :          * limited to 16 bits. To overcome this limitation, Linux decided to
     915             :          * scatter the highest bits of these values into a previously reserved
     916             :          * area on the disk inode. We deal with this situation by having two
     917             :          * 32-bit fields *out* of the disk inode to hold the complete values.
     918             :          * Now that we are reading in the inode, compute these fields.
     919             :          */
     920           0 :         ip->i_e2fs_uid = ip->i_e2fs_uid_low | (ip->i_e2fs_uid_high << 16);
     921           0 :         ip->i_e2fs_gid = ip->i_e2fs_gid_low | (ip->i_e2fs_gid_high << 16);
     922             : 
     923             :         /* If the inode was deleted, reset all fields */
     924           0 :         if (ip->i_e2fs_dtime != 0) {
     925           0 :                 ip->i_e2fs_mode = ip->i_e2fs_nblock = 0;
     926           0 :                 (void)ext2fs_setsize(ip, 0);
     927           0 :         }
     928             : 
     929             :         /*
     930             :          * Initialize the vnode from the inode, check for aliases.
     931             :          * Note that the underlying vnode may have changed.
     932             :          */
     933           0 :         error = ext2fs_vinit(mp, &vp);
     934           0 :         if (error) {
     935           0 :                 vput(vp);
     936           0 :                 *vpp = NULL;
     937           0 :                 return (error);
     938             :         }
     939             : 
     940             :         /*
     941             :          * Finish inode initialization now that aliasing has been resolved.
     942             :          */
     943           0 :         vref(ip->i_devvp);
     944             :         /*
     945             :          * Set up a generation number for this inode if it does not
     946             :          * already have one. This should only happen on old filesystems.
     947             :          */
     948           0 :         if (ip->i_e2fs_gen == 0) {
     949           0 :                 if (++ext2gennumber < (u_long)time_second)
     950           0 :                         ext2gennumber = time_second;
     951           0 :                 ip->i_e2fs_gen = ext2gennumber;
     952           0 :                 if ((vp->v_mount->mnt_flag & MNT_RDONLY) == 0)
     953           0 :                         ip->i_flag |= IN_MODIFIED;
     954             :         }
     955             : 
     956           0 :         *vpp = vp;
     957           0 :         return (0);
     958           0 : }
     959             : 
     960             : /*
     961             :  * File handle to vnode
     962             :  *
     963             :  * Have to be really careful about stale file handles:
     964             :  * - check that the inode number is valid
     965             :  * - call ext2fs_vget() to get the locked inode
     966             :  * - check for an unallocated inode (i_mode == 0)
     967             :  * - check that the given client host has export rights and return
     968             :  *   those rights via. exflagsp and credanonp
     969             :  */
     970             : int
     971           0 : ext2fs_fhtovp(struct mount *mp, struct fid *fhp, struct vnode **vpp)
     972             : {
     973             :         struct inode *ip;
     974           0 :         struct vnode *nvp;
     975             :         int error;
     976             :         struct ufid *ufhp;
     977             :         struct m_ext2fs *fs;
     978             : 
     979           0 :         ufhp = (struct ufid *)fhp;
     980           0 :         fs = VFSTOUFS(mp)->um_e2fs;
     981           0 :         if ((ufhp->ufid_ino < EXT2_FIRSTINO && ufhp->ufid_ino != EXT2_ROOTINO) ||
     982           0 :             ufhp->ufid_ino > fs->e2fs_ncg * fs->e2fs.e2fs_ipg)
     983           0 :                 return (ESTALE);
     984             : 
     985           0 :         if ((error = VFS_VGET(mp, ufhp->ufid_ino, &nvp)) != 0) {
     986           0 :                 *vpp = NULLVP;
     987           0 :                 return (error);
     988             :         }
     989           0 :         ip = VTOI(nvp);
     990           0 :         if (ip->i_e2fs_mode == 0 || ip->i_e2fs_dtime != 0 ||
     991           0 :             ip->i_e2fs_gen != ufhp->ufid_gen) {
     992           0 :                 vput(nvp);
     993           0 :                 *vpp = NULLVP;
     994           0 :                 return (ESTALE);
     995             :         }
     996           0 :         *vpp = nvp;
     997           0 :         return (0);
     998           0 : }
     999             : 
    1000             : /*
    1001             :  * Vnode pointer to File handle
    1002             :  */
    1003             : /* ARGSUSED */
    1004             : int
    1005           0 : ext2fs_vptofh(struct vnode *vp, struct fid *fhp)
    1006             : {
    1007             :         struct inode *ip;
    1008             :         struct ufid *ufhp;
    1009             : 
    1010           0 :         ip = VTOI(vp);
    1011           0 :         ufhp = (struct ufid *)fhp;
    1012           0 :         ufhp->ufid_len = sizeof(struct ufid);
    1013           0 :         ufhp->ufid_ino = ip->i_number;
    1014           0 :         ufhp->ufid_gen = ip->i_e2fs_gen;
    1015           0 :         return (0);
    1016             : }
    1017             : 
    1018             : /*
    1019             :  * no sysctl for ext2fs
    1020             :  */
    1021             : 
    1022             : int
    1023           0 : ext2fs_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp,
    1024             :     void *newp, size_t newlen, struct proc *p)
    1025             : {
    1026           0 :         return (EOPNOTSUPP);
    1027             : }
    1028             : 
    1029             : /*
    1030             :  * Write a superblock and associated information back to disk.
    1031             :  */
    1032             : int
    1033           0 : ext2fs_sbupdate(struct ufsmount *mp, int waitfor)
    1034             : {
    1035           0 :         struct m_ext2fs *fs = mp->um_e2fs;
    1036             :         struct buf *bp;
    1037             :         int error = 0;
    1038             : 
    1039           0 :         bp = getblk(mp->um_devvp, SBLOCK, SBSIZE, 0, 0);
    1040           0 :         e2fs_sbsave(&fs->e2fs, (struct ext2fs *) bp->b_data);
    1041           0 :         if (waitfor == MNT_WAIT)
    1042           0 :                 error = bwrite(bp);
    1043             :         else
    1044           0 :                 bawrite(bp);
    1045           0 :         fs->e2fs_fmod = 0;
    1046           0 :         return (error);
    1047             : }
    1048             : 
    1049             : int
    1050           0 : ext2fs_cgupdate(struct ufsmount *mp, int waitfor)
    1051             : {
    1052           0 :         struct m_ext2fs *fs = mp->um_e2fs;
    1053             :         struct buf *bp;
    1054             :         int i, error = 0, allerror = 0;
    1055             : 
    1056           0 :         allerror = ext2fs_sbupdate(mp, waitfor);
    1057           0 :         for (i = 0; i < fs->e2fs_ngdb; i++) {
    1058           0 :                 bp = getblk(mp->um_devvp, fsbtodb(fs, ((fs->e2fs_bsize>1024)?0:1)+i+1),
    1059             :                     fs->e2fs_bsize, 0, 0);
    1060           0 :                 e2fs_cgsave(&fs->e2fs_gd[i* fs->e2fs_bsize / sizeof(struct ext2_gd)], (struct ext2_gd*)bp->b_data, fs->e2fs_bsize);
    1061           0 :                 if (waitfor == MNT_WAIT)
    1062           0 :                         error = bwrite(bp);
    1063             :                 else
    1064           0 :                         bawrite(bp);
    1065             :         }
    1066             : 
    1067           0 :         if (!allerror && error)
    1068           0 :                 allerror = error;
    1069           0 :         return (allerror);
    1070             : }
    1071             : 
    1072             : /* This is called before the superblock is copied.  Watch out for endianity! */
    1073             : static int
    1074           0 : e2fs_sbcheck(struct ext2fs *fs, int ronly)
    1075             : {
    1076             :         u_int32_t tmp;
    1077             : 
    1078           0 :         tmp = letoh16(fs->e2fs_magic);
    1079           0 :         if (tmp != E2FS_MAGIC) {
    1080           0 :                 printf("ext2fs: wrong magic number 0x%x\n", tmp);
    1081           0 :                 return (EIO);           /* XXX needs translation */
    1082             :         }
    1083             : 
    1084           0 :         tmp = letoh32(fs->e2fs_log_bsize);
    1085           0 :         if (tmp > 2) {
    1086             :                 /* skewed log(block size): 1024 -> 0 | 2048 -> 1 | 4096 -> 2 */
    1087           0 :                 tmp += 10;
    1088           0 :                 printf("ext2fs: wrong log2(block size) %d\n", tmp);
    1089           0 :                 return (EIO);      /* XXX needs translation */
    1090             :         }
    1091             : 
    1092           0 :         if (fs->e2fs_bpg == 0) {
    1093           0 :                 printf("ext2fs: zero blocks per group\n");
    1094           0 :                 return (EIO);
    1095             :         }
    1096             : 
    1097           0 :         tmp = letoh32(fs->e2fs_rev);
    1098           0 :         if (tmp > E2FS_REV1) {
    1099           0 :                 printf("ext2fs: wrong revision number 0x%x\n", tmp);
    1100           0 :                 return (EIO);           /* XXX needs translation */
    1101             :         }
    1102           0 :         else if (tmp == E2FS_REV0)
    1103           0 :                 return (0);
    1104             : 
    1105           0 :         tmp = letoh32(fs->e2fs_first_ino);
    1106           0 :         if (tmp != EXT2_FIRSTINO) {
    1107           0 :                 printf("ext2fs: first inode at 0x%x\n", tmp);
    1108           0 :                 return (EINVAL);      /* XXX needs translation */
    1109             :         }
    1110             : 
    1111           0 :         tmp = letoh32(fs->e2fs_features_incompat);
    1112           0 :         if (tmp & ~(EXT2F_INCOMPAT_SUPP | EXT4F_RO_INCOMPAT_SUPP)) {
    1113           0 :                 printf("ext2fs: unsupported incompat features 0x%x\n", tmp);
    1114           0 :                 return (EINVAL);      /* XXX needs translation */
    1115             :         }
    1116             : 
    1117           0 :         if (!ronly && (tmp & EXT4F_RO_INCOMPAT_SUPP)) {
    1118           0 :                 printf("ext4fs: only read-only support right now\n");
    1119           0 :                 return (EROFS);      /* XXX needs translation */
    1120             :         }
    1121             : 
    1122           0 :         if (tmp & EXT2F_INCOMPAT_RECOVER) {
    1123           0 :                 printf("ext2fs: your file system says it needs recovery\n");
    1124           0 :                 if (!ronly)
    1125           0 :                         return (EROFS); /* XXX needs translation */
    1126             :         }
    1127             : 
    1128           0 :         tmp = letoh32(fs->e2fs_features_rocompat);
    1129           0 :         if (!ronly && (tmp & ~EXT2F_ROCOMPAT_SUPP)) {
    1130           0 :                 printf("ext2fs: unsupported R/O compat features 0x%x\n", tmp);
    1131           0 :                 return (EROFS);      /* XXX needs translation */
    1132             :         }
    1133             : 
    1134           0 :         return (0);
    1135           0 : }

Generated by: LCOV version 1.13