root/ufs/ext2fs/ext2fs_vfsops.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. ext2fs_init
  2. ext2fs_mountroot
  3. ext2fs_mount
  4. ext2fs_reload_vnode
  5. ext2fs_reload
  6. ext2fs_mountfs
  7. ext2fs_unmount
  8. ext2fs_flushfiles
  9. ext2fs_statfs
  10. ext2fs_sync_vnode
  11. ext2fs_sync
  12. ext2fs_vget
  13. ext2fs_fhtovp
  14. ext2fs_vptofh
  15. ext2fs_sysctl
  16. ext2fs_sbupdate
  17. ext2fs_cgupdate
  18. ext2fs_checksb

    1 /*      $OpenBSD: ext2fs_vfsops.c,v 1.48 2007/06/17 20:15:25 jasper 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/device.h>
   47 #include <sys/mbuf.h>
   48 #include <sys/file.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 
   56 #include <miscfs/specfs/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 ext2fs_checksb(struct ext2fs *, int);
   71 
   72 extern struct vnodeopv_desc ext2fs_vnodeop_opv_desc;
   73 extern struct vnodeopv_desc ext2fs_specop_opv_desc;
   74 #ifdef FIFO
   75 extern struct vnodeopv_desc ext2fs_fifoop_opv_desc;
   76 #endif
   77 
   78 struct vnodeopv_desc *ext2fs_vnodeopv_descs[] = {
   79         &ext2fs_vnodeop_opv_desc,
   80         &ext2fs_specop_opv_desc,
   81 #ifdef FIFO
   82         &ext2fs_fifoop_opv_desc,
   83 #endif
   84         NULL,
   85 };
   86 
   87 const struct vfsops ext2fs_vfsops = {
   88         ext2fs_mount,
   89         ufs_start,
   90         ext2fs_unmount,
   91         ufs_root,
   92         ufs_quotactl,
   93         ext2fs_statfs,
   94         ext2fs_sync,
   95         ext2fs_vget,
   96         ext2fs_fhtovp,
   97         ext2fs_vptofh,
   98         ext2fs_init,
   99         ext2fs_sysctl,
  100         ufs_check_export
  101 };
  102 
  103 struct pool ext2fs_inode_pool;
  104 struct pool ext2fs_dinode_pool;
  105 
  106 extern u_long ext2gennumber;
  107 
  108 int
  109 ext2fs_init(struct vfsconf *vfsp)
  110 {
  111         pool_init(&ext2fs_inode_pool, sizeof(struct inode), 0, 0, 0,
  112             "ext2inopl", &pool_allocator_nointr);
  113         pool_init(&ext2fs_dinode_pool, sizeof(struct ext2fs_dinode), 0, 0, 0,
  114             "ext2dinopl", &pool_allocator_nointr);
  115 
  116         return (ufs_init(vfsp));
  117 }
  118 
  119 /*
  120  * Called by main() when ext2fs is going to be mounted as root.
  121  *
  122  * Name is updated by mount(8) after booting.
  123  */
  124 #define ROOTNAME        "root_device"
  125 
  126 int
  127 ext2fs_mountroot(void)
  128 {
  129         struct m_ext2fs *fs;
  130         struct mount *mp;
  131         struct proc *p = curproc;       /* XXX */
  132         struct ufsmount *ump;
  133         int error;
  134 
  135         /*
  136          * Get vnodes for swapdev and rootdev.
  137          */
  138         if (bdevvp(swapdev, &swapdev_vp) || bdevvp(rootdev, &rootvp))
  139                 panic("ext2fs_mountroot: can't setup bdevvp's");
  140 
  141         if ((error = vfs_rootmountalloc("ext2fs", "root_device", &mp)) != 0) {
  142                 vrele(rootvp);
  143                 return (error);
  144         }
  145 
  146         if ((error = ext2fs_mountfs(rootvp, mp, p)) != 0) {
  147                 mp->mnt_vfc->vfc_refcount--;
  148                 vfs_unbusy(mp);
  149                 free(mp, M_MOUNT);
  150                 vrele(rootvp);
  151                 return (error);
  152         }
  153 
  154         CIRCLEQ_INSERT_TAIL(&mountlist, mp, mnt_list);
  155         ump = VFSTOUFS(mp);
  156         fs = ump->um_e2fs;
  157         bzero(fs->e2fs_fsmnt, sizeof(fs->e2fs_fsmnt));
  158         (void) copystr(mp->mnt_stat.f_mntonname, fs->e2fs_fsmnt, 
  159             sizeof(fs->e2fs_fsmnt) - 1, 0);
  160         if (fs->e2fs.e2fs_rev > E2FS_REV0) {
  161                 bzero(fs->e2fs.e2fs_fsmnt, sizeof(fs->e2fs.e2fs_fsmnt));
  162                 (void) copystr(mp->mnt_stat.f_mntonname, fs->e2fs.e2fs_fsmnt,
  163                     sizeof(fs->e2fs.e2fs_fsmnt) - 1, 0);
  164         }
  165         (void)ext2fs_statfs(mp, &mp->mnt_stat, p);
  166         vfs_unbusy(mp);
  167         inittodr(fs->e2fs.e2fs_wtime);
  168         return (0);
  169 }
  170 
  171 /*
  172  * VFS Operations.
  173  *
  174  * mount system call
  175  */
  176 int
  177 ext2fs_mount(struct mount *mp, const char *path, void *data,
  178     struct nameidata *ndp, struct proc *p)
  179 {
  180         struct vnode *devvp;
  181         struct ufs_args args;
  182         struct ufsmount *ump = NULL;
  183         struct m_ext2fs *fs;
  184         size_t size;
  185         int error, flags;
  186         mode_t accessmode;
  187 
  188         error = copyin(data, (caddr_t)&args, sizeof (struct ufs_args));
  189         if (error)
  190                 return (error);
  191         /*
  192          * If updating, check whether changing from read-only to
  193          * read/write; if there is no device name, that's all we do.
  194          */
  195         if (mp->mnt_flag & MNT_UPDATE) {
  196                 ump = VFSTOUFS(mp);
  197                 fs = ump->um_e2fs;
  198                 if (fs->e2fs_ronly == 0 && (mp->mnt_flag & MNT_RDONLY)) {
  199                         flags = WRITECLOSE;
  200                         if (mp->mnt_flag & MNT_FORCE)
  201                                 flags |= FORCECLOSE;
  202                         error = ext2fs_flushfiles(mp, flags, p);
  203                         if (error == 0 &&
  204                                 ext2fs_cgupdate(ump, MNT_WAIT) == 0 &&
  205                                 (fs->e2fs.e2fs_state & E2FS_ERRORS) == 0) {
  206                                 fs->e2fs.e2fs_state = E2FS_ISCLEAN;
  207                                 (void) ext2fs_sbupdate(ump, MNT_WAIT);
  208                         }
  209                         if (error)
  210                                 return (error);
  211                         fs->e2fs_ronly = 1;
  212                 }
  213                 if (mp->mnt_flag & MNT_RELOAD) {
  214                         error = ext2fs_reload(mp, ndp->ni_cnd.cn_cred, p);
  215                         if (error)
  216                                 return (error);
  217                 }
  218                 if (fs->e2fs_ronly && (mp->mnt_flag & MNT_WANTRDWR)) {
  219                         /*
  220                          * If upgrade to read-write by non-root, then verify
  221                          * that user has necessary permissions on the device.
  222                          */
  223                         if (p->p_ucred->cr_uid != 0) {
  224                                 devvp = ump->um_devvp;
  225                                 vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, p);
  226                                 error = VOP_ACCESS(devvp, VREAD | VWRITE,
  227                                                    p->p_ucred, p);
  228                                 if (error) {
  229                                         VOP_UNLOCK(devvp, 0, p);
  230                                         return (error);
  231                                 }
  232                                 VOP_UNLOCK(devvp, 0, p);
  233                         }
  234                         fs->e2fs_ronly = 0;
  235                         if (fs->e2fs.e2fs_state == E2FS_ISCLEAN)
  236                                 fs->e2fs.e2fs_state = 0;
  237                         else
  238                                 fs->e2fs.e2fs_state = E2FS_ERRORS;
  239                         fs->e2fs_fmod = 1;
  240                 }
  241                 if (args.fspec == 0) {
  242                         /*
  243                          * Process export requests.
  244                          */
  245                         return (vfs_export(mp, &ump->um_export, 
  246                             &args.export_info));
  247                 }
  248         }
  249         /*
  250          * Not an update, or updating the name: look up the name
  251          * and verify that it refers to a sensible block device.
  252          */
  253         NDINIT(ndp, LOOKUP, FOLLOW, UIO_USERSPACE, args.fspec, p);
  254         if ((error = namei(ndp)) != 0)
  255                 return (error);
  256         devvp = ndp->ni_vp;
  257 
  258         if (devvp->v_type != VBLK) {
  259                 vrele(devvp);
  260                 return (ENOTBLK);
  261         }
  262         if (major(devvp->v_rdev) >= nblkdev) {
  263                 vrele(devvp);
  264                 return (ENXIO);
  265         }
  266         /*
  267          * If mount by non-root, then verify that user has necessary
  268          * permissions on the device.
  269          */
  270         if (p->p_ucred->cr_uid != 0) {
  271                 accessmode = VREAD;
  272                 if ((mp->mnt_flag & MNT_RDONLY) == 0)
  273                         accessmode |= VWRITE;
  274                 vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, p);
  275                 error = VOP_ACCESS(devvp, accessmode, p->p_ucred, p);
  276                 if (error) {
  277                         vput(devvp);
  278                         return (error);
  279                 }
  280                 VOP_UNLOCK(devvp, 0, p);
  281         }
  282         if ((mp->mnt_flag & MNT_UPDATE) == 0)
  283                 error = ext2fs_mountfs(devvp, mp, p);
  284         else {
  285                 if (devvp != ump->um_devvp)
  286                         error = EINVAL; /* XXX needs translation */
  287                 else
  288                         vrele(devvp);
  289         }
  290         if (error) {
  291                 vrele(devvp);
  292                 return (error);
  293         }
  294         ump = VFSTOUFS(mp);
  295         fs = ump->um_e2fs;
  296         (void) copyinstr(path, fs->e2fs_fsmnt, sizeof(fs->e2fs_fsmnt) - 1,
  297             &size);
  298         bzero(fs->e2fs_fsmnt + size, sizeof(fs->e2fs_fsmnt) - size);
  299         if (fs->e2fs.e2fs_rev > E2FS_REV0) {
  300                 (void) copystr(mp->mnt_stat.f_mntonname, fs->e2fs.e2fs_fsmnt,
  301                     sizeof(fs->e2fs.e2fs_fsmnt) - 1, &size);
  302                 bzero(fs->e2fs.e2fs_fsmnt, sizeof(fs->e2fs.e2fs_fsmnt) - size);
  303         }
  304         bcopy(fs->e2fs_fsmnt, mp->mnt_stat.f_mntonname, MNAMELEN);
  305         (void) copyinstr(args.fspec, mp->mnt_stat.f_mntfromname, MNAMELEN - 1, 
  306                 &size);
  307         bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size);
  308         if (fs->e2fs_fmod != 0) {       /* XXX */
  309                 fs->e2fs_fmod = 0;
  310                 if (fs->e2fs.e2fs_state == 0)
  311                         fs->e2fs.e2fs_wtime = time_second;
  312                 else
  313                         printf("%s: file system not clean; please fsck(8)\n",
  314                                 mp->mnt_stat.f_mntfromname);
  315                 (void) ext2fs_cgupdate(ump, MNT_WAIT);
  316         }
  317         return (0);
  318 }
  319 
  320 int ext2fs_reload_vnode(struct vnode *, void *args);
  321 
  322 struct ext2fs_reload_args {
  323         struct m_ext2fs *fs;
  324         struct proc *p;
  325         struct ucred *cred;
  326         struct vnode *devvp;
  327 };
  328 
  329 int
  330 ext2fs_reload_vnode(struct vnode *vp, void *args)
  331 {
  332         struct ext2fs_reload_args *era = args;
  333         struct buf *bp;
  334         struct inode *ip;
  335         int error;
  336         caddr_t cp;
  337 
  338         /*
  339          * Step 4: invalidate all inactive vnodes.
  340          */
  341         if (vp->v_usecount == 0) {
  342                 vgonel(vp, era->p);
  343                 return (0);
  344         }
  345 
  346         /*
  347          * Step 5: invalidate all cached file data.
  348          */
  349         if (vget(vp, LK_EXCLUSIVE, era->p))
  350                 return (0);
  351         
  352         if (vinvalbuf(vp, 0, era->cred, era->p, 0, 0))
  353                 panic("ext2fs_reload: dirty2");
  354         /*
  355          * Step 6: re-read inode data for all active vnodes.
  356          */
  357         ip = VTOI(vp);
  358         error = bread(era->devvp, 
  359             fsbtodb(era->fs, ino_to_fsba(era->fs, ip->i_number)),
  360             (int)era->fs->e2fs_bsize, NOCRED, &bp);
  361         if (error) {
  362                 vput(vp);
  363                 return (error);
  364         }
  365         cp = (caddr_t)bp->b_data +
  366             (ino_to_fsbo(era->fs, ip->i_number) * EXT2_DINODE_SIZE);
  367         e2fs_iload((struct ext2fs_dinode *)cp, ip->i_e2din);
  368         brelse(bp);
  369         vput(vp);
  370         return (0);
  371 }
  372 
  373 /*
  374  * Reload all incore data for a filesystem (used after running fsck on
  375  * the root filesystem and finding things to fix). The filesystem must
  376  * be mounted read-only.
  377  *
  378  * Things to do to update the mount:
  379  *      1) invalidate all cached meta-data.
  380  *      2) re-read superblock from disk.
  381  *      3) re-read summary information from disk.
  382  *      4) invalidate all inactive vnodes.
  383  *      5) invalidate all cached file data.
  384  *      6) re-read inode data for all active vnodes.
  385  */
  386 int
  387 ext2fs_reload(struct mount *mountp, struct ucred *cred, struct proc *p)
  388 {
  389         struct vnode *devvp;
  390         struct buf *bp;
  391         struct m_ext2fs *fs;
  392         struct ext2fs *newfs;
  393         struct partinfo dpart;
  394         int i, size, error;
  395         struct ext2fs_reload_args era;
  396 
  397         if ((mountp->mnt_flag & MNT_RDONLY) == 0)
  398                 return (EINVAL);
  399         /*
  400          * Step 1: invalidate all cached meta-data.
  401          */
  402         devvp = VFSTOUFS(mountp)->um_devvp;
  403         if (vinvalbuf(devvp, 0, cred, p, 0, 0))
  404                 panic("ext2fs_reload: dirty1");
  405 
  406         /*
  407          * Step 2: re-read superblock from disk.
  408          */
  409         if (VOP_IOCTL(devvp, DIOCGPART, (caddr_t)&dpart, FREAD, NOCRED, p) != 0)
  410                 size = DEV_BSIZE;
  411         else
  412                 size = dpart.disklab->d_secsize;
  413         error = bread(devvp, (int32_t)(SBOFF / size), SBSIZE, NOCRED, &bp);
  414         if (error) {
  415                 brelse(bp);
  416                 return (error);
  417         }
  418         newfs = (struct ext2fs *)bp->b_data;
  419         error = ext2fs_checksb(newfs, (mountp->mnt_flag & MNT_RDONLY) != 0);
  420         if (error) {
  421                 brelse(bp);
  422                 return (error);
  423         }
  424 
  425         fs = VFSTOUFS(mountp)->um_e2fs;
  426         /* 
  427          * copy in new superblock, and compute in-memory values
  428          */
  429         e2fs_sbload(newfs, &fs->e2fs);
  430         fs->e2fs_ncg =
  431             howmany(fs->e2fs.e2fs_bcount - fs->e2fs.e2fs_first_dblock,
  432             fs->e2fs.e2fs_bpg);
  433         /* XXX assume hw bsize = 512 */
  434         fs->e2fs_fsbtodb = fs->e2fs.e2fs_log_bsize + 1;
  435         fs->e2fs_bsize = 1024 << fs->e2fs.e2fs_log_bsize;
  436         fs->e2fs_bshift = LOG_MINBSIZE + fs->e2fs.e2fs_log_bsize;
  437         fs->e2fs_qbmask = fs->e2fs_bsize - 1;
  438         fs->e2fs_bmask = ~fs->e2fs_qbmask;
  439         fs->e2fs_ngdb = howmany(fs->e2fs_ncg,
  440                         fs->e2fs_bsize / sizeof(struct ext2_gd));
  441         fs->e2fs_ipb = fs->e2fs_bsize / EXT2_DINODE_SIZE;
  442         fs->e2fs_itpg = fs->e2fs.e2fs_ipg/fs->e2fs_ipb;
  443 
  444         /*
  445          * Step 3: re-read summary information from disk.
  446          */
  447 
  448         for (i=0; i < fs->e2fs_ngdb; i++) {
  449                 error = bread(devvp ,
  450                     fsbtodb(fs, ((fs->e2fs_bsize>1024)? 0 : 1) + i + 1),
  451                     fs->e2fs_bsize, NOCRED, &bp);
  452                 if (error) {
  453                         brelse(bp);
  454                         return (error);
  455                 }
  456                 e2fs_cgload((struct ext2_gd*)bp->b_data,
  457                     &fs->e2fs_gd[i* fs->e2fs_bsize / sizeof(struct ext2_gd)],
  458                     fs->e2fs_bsize);
  459                 brelse(bp);
  460         }
  461 
  462         era.p = p;
  463         era.cred = cred;
  464         era.fs = fs;
  465         era.devvp = devvp;
  466 
  467         error = vfs_mount_foreach_vnode(mountp, ext2fs_reload_vnode, &era);
  468 
  469         return (error);
  470 }
  471 
  472 /*
  473  * Common code for mount and mountroot
  474  */
  475 int
  476 ext2fs_mountfs(struct vnode *devvp, struct mount *mp, struct proc *p)
  477 {
  478         struct ufsmount *ump;
  479         struct buf *bp;
  480         struct ext2fs *fs;
  481         struct m_ext2fs *m_fs;
  482         dev_t dev;
  483         struct partinfo dpart;
  484         int error, i, size, ronly;
  485         struct ucred *cred;
  486 
  487         dev = devvp->v_rdev;
  488         cred = p ? p->p_ucred : NOCRED;
  489         /*
  490          * Disallow multiple mounts of the same device.
  491          * Disallow mounting of a device that is currently in use
  492          * (except for root, which might share swap device for miniroot).
  493          * Flush out any old buffers remaining from a previous use.
  494          */
  495         if ((error = vfs_mountedon(devvp)) != 0)
  496                 return (error);
  497         if (vcount(devvp) > 1 && devvp != rootvp)
  498                 return (EBUSY);
  499         if ((error = vinvalbuf(devvp, V_SAVE, cred, p, 0, 0)) != 0)
  500                 return (error);
  501 
  502         ronly = (mp->mnt_flag & MNT_RDONLY) != 0;
  503         error = VOP_OPEN(devvp, ronly ? FREAD : FREAD|FWRITE, FSCRED, p);
  504         if (error)
  505                 return (error);
  506         if (VOP_IOCTL(devvp, DIOCGPART, (caddr_t)&dpart, FREAD, cred, p) != 0)
  507                 size = DEV_BSIZE;
  508         else
  509                 size = dpart.disklab->d_secsize;
  510 
  511         bp = NULL;
  512         ump = NULL;
  513 
  514 #ifdef DEBUG_EXT2
  515         printf("sb size: %d ino size %d\n", sizeof(struct ext2fs),
  516             EXT2_DINODE_SIZE);
  517 #endif
  518         error = bread(devvp, (SBOFF / DEV_BSIZE), SBSIZE, cred, &bp);
  519         if (error)
  520                 goto out;
  521         fs = (struct ext2fs *)bp->b_data;
  522         error = ext2fs_checksb(fs, ronly);
  523         if (error)
  524                 goto out;
  525         ump = malloc(sizeof *ump, M_UFSMNT, M_WAITOK);
  526         memset((caddr_t)ump, 0, sizeof *ump);
  527         ump->um_e2fs = malloc(sizeof(struct m_ext2fs), M_UFSMNT, M_WAITOK);
  528         memset((caddr_t)ump->um_e2fs, 0, sizeof(struct m_ext2fs));
  529         e2fs_sbload((struct ext2fs*)bp->b_data, &ump->um_e2fs->e2fs);
  530         brelse(bp);
  531         bp = NULL;
  532         m_fs = ump->um_e2fs;
  533         m_fs->e2fs_ronly = ronly;
  534         ump->um_fstype = UM_EXT2FS;
  535         if (ronly == 0) {
  536                 if (m_fs->e2fs.e2fs_state == E2FS_ISCLEAN)
  537                         m_fs->e2fs.e2fs_state = 0;
  538                 else
  539                         m_fs->e2fs.e2fs_state = E2FS_ERRORS;
  540                 m_fs->e2fs_fmod = 1;
  541         }
  542 
  543         /* compute dynamic sb infos */
  544         m_fs->e2fs_ncg =
  545                 howmany(m_fs->e2fs.e2fs_bcount - m_fs->e2fs.e2fs_first_dblock,
  546                 m_fs->e2fs.e2fs_bpg);
  547         /* XXX assume hw bsize = 512 */
  548         m_fs->e2fs_fsbtodb = m_fs->e2fs.e2fs_log_bsize + 1;
  549         m_fs->e2fs_bsize = 1024 << m_fs->e2fs.e2fs_log_bsize;
  550         m_fs->e2fs_bshift = LOG_MINBSIZE + m_fs->e2fs.e2fs_log_bsize;
  551         m_fs->e2fs_qbmask = m_fs->e2fs_bsize - 1;
  552         m_fs->e2fs_bmask = ~m_fs->e2fs_qbmask;
  553         m_fs->e2fs_ngdb = howmany(m_fs->e2fs_ncg,
  554                 m_fs->e2fs_bsize / sizeof(struct ext2_gd));
  555         m_fs->e2fs_ipb = m_fs->e2fs_bsize / EXT2_DINODE_SIZE;
  556         m_fs->e2fs_itpg = m_fs->e2fs.e2fs_ipg/m_fs->e2fs_ipb;
  557 
  558         m_fs->e2fs_gd = malloc(m_fs->e2fs_ngdb * m_fs->e2fs_bsize,
  559                 M_UFSMNT, M_WAITOK);
  560         for (i=0; i < m_fs->e2fs_ngdb; i++) {
  561                 error = bread(devvp ,
  562                     fsbtodb(m_fs, ((m_fs->e2fs_bsize>1024)? 0 : 1) + i + 1),
  563                     m_fs->e2fs_bsize, NOCRED, &bp);
  564                 if (error) {
  565                         free(m_fs->e2fs_gd, M_UFSMNT);
  566                         goto out;
  567                 }
  568                 e2fs_cgload((struct ext2_gd*)bp->b_data,
  569                     &m_fs->e2fs_gd[
  570                         i * m_fs->e2fs_bsize / sizeof(struct ext2_gd)],
  571                     m_fs->e2fs_bsize);
  572                 brelse(bp);
  573                 bp = NULL;
  574         }
  575 
  576         mp->mnt_data = (qaddr_t)ump;
  577         mp->mnt_stat.f_fsid.val[0] = (long)dev;
  578         mp->mnt_stat.f_fsid.val[1] = mp->mnt_vfc->vfc_typenum;
  579         mp->mnt_maxsymlinklen = EXT2_MAXSYMLINKLEN;
  580         mp->mnt_flag |= MNT_LOCAL;
  581         ump->um_mountp = mp;
  582         ump->um_dev = dev;
  583         ump->um_devvp = devvp;
  584         ump->um_nindir = NINDIR(m_fs);
  585         ump->um_bptrtodb = m_fs->e2fs_fsbtodb;
  586         ump->um_seqinc = 1; /* no frags */
  587         devvp->v_specmountpoint = mp;
  588         return (0);
  589 out:
  590         if (bp)
  591                 brelse(bp);
  592         vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, p);
  593         (void)VOP_CLOSE(devvp, ronly ? FREAD : FREAD|FWRITE, cred, p);
  594         VOP_UNLOCK(devvp, 0, p);
  595         if (ump) {
  596                 free(ump->um_e2fs, M_UFSMNT);
  597                 free(ump, M_UFSMNT);
  598                 mp->mnt_data = (qaddr_t)0;
  599         }
  600         return (error);
  601 }
  602 
  603 /*
  604  * unmount system call
  605  */
  606 int
  607 ext2fs_unmount(struct mount *mp, int mntflags, struct proc *p)
  608 {
  609         struct ufsmount *ump;
  610         struct m_ext2fs *fs;
  611         int error, flags;
  612 
  613         flags = 0;
  614         if (mntflags & MNT_FORCE)
  615                 flags |= FORCECLOSE;
  616         if ((error = ext2fs_flushfiles(mp, flags, p)) != 0)
  617                 return (error);
  618         ump = VFSTOUFS(mp);
  619         fs = ump->um_e2fs;
  620         if (fs->e2fs_ronly == 0 &&
  621                 ext2fs_cgupdate(ump, MNT_WAIT) == 0 &&
  622                 (fs->e2fs.e2fs_state & E2FS_ERRORS) == 0) {
  623                 fs->e2fs.e2fs_state = E2FS_ISCLEAN;
  624                 (void) ext2fs_sbupdate(ump, MNT_WAIT);
  625         }
  626 
  627         if (ump->um_devvp->v_type != VBAD)
  628                 ump->um_devvp->v_specmountpoint = NULL;
  629         vn_lock(ump->um_devvp, LK_EXCLUSIVE | LK_RETRY, p);
  630         error = VOP_CLOSE(ump->um_devvp, fs->e2fs_ronly ? FREAD : FREAD|FWRITE,
  631                 NOCRED, p);
  632         vput(ump->um_devvp);
  633         free(fs->e2fs_gd, M_UFSMNT);
  634         free(fs, M_UFSMNT);
  635         free(ump, M_UFSMNT);
  636         mp->mnt_data = (qaddr_t)0;
  637         mp->mnt_flag &= ~MNT_LOCAL;
  638         return (error);
  639 }
  640 
  641 /*
  642  * Flush out all the files in a filesystem.
  643  */
  644 int
  645 ext2fs_flushfiles(struct mount *mp, int flags, struct proc *p)
  646 {
  647         struct ufsmount *ump;
  648         int error;
  649 
  650         ump = VFSTOUFS(mp);
  651         /*
  652          * Flush all the files.
  653          */
  654         if ((error = vflush(mp, NULL, flags)) != 0)
  655                 return (error);
  656         /*
  657          * Flush filesystem metadata.
  658          */
  659         vn_lock(ump->um_devvp, LK_EXCLUSIVE | LK_RETRY, p);
  660         error = VOP_FSYNC(ump->um_devvp, p->p_ucred, MNT_WAIT, p);
  661         VOP_UNLOCK(ump->um_devvp, 0, p);
  662         return (error);
  663 }
  664 
  665 /*
  666  * Get file system statistics.
  667  */
  668 int
  669 ext2fs_statfs(struct mount *mp, struct statfs *sbp, struct proc *p)
  670 {
  671         struct ufsmount *ump;
  672         struct m_ext2fs *fs;
  673         u_int32_t overhead, overhead_per_group;
  674         int i, ngroups;
  675 
  676         ump = VFSTOUFS(mp);
  677         fs = ump->um_e2fs;
  678         if (fs->e2fs.e2fs_magic != E2FS_MAGIC)
  679                 panic("ext2fs_statfs");
  680 
  681         /*
  682          * Compute the overhead (FS structures)
  683          */
  684         overhead_per_group = 1 /* block bitmap */ +
  685                                  1 /* inode bitmap */ +
  686                                  fs->e2fs_itpg;
  687         overhead = fs->e2fs.e2fs_first_dblock +
  688                    fs->e2fs_ncg * overhead_per_group;
  689         if (fs->e2fs.e2fs_rev > E2FS_REV0 &&
  690             fs->e2fs.e2fs_features_rocompat & EXT2F_ROCOMPAT_SPARSESUPER) {
  691                 for (i = 0, ngroups = 0; i < fs->e2fs_ncg; i++) {
  692                         if (cg_has_sb(i))
  693                                 ngroups++;
  694                 }
  695         } else {
  696                 ngroups = fs->e2fs_ncg;
  697         }
  698         overhead += ngroups * (1 + fs->e2fs_ngdb);
  699 
  700         sbp->f_bsize = fs->e2fs_bsize;
  701         sbp->f_iosize = fs->e2fs_bsize;
  702         sbp->f_blocks = fs->e2fs.e2fs_bcount - overhead;
  703         sbp->f_bfree = fs->e2fs.e2fs_fbcount;
  704         sbp->f_bavail = sbp->f_bfree - fs->e2fs.e2fs_rbcount;
  705         sbp->f_files =  fs->e2fs.e2fs_icount;
  706         sbp->f_ffree = fs->e2fs.e2fs_ficount;
  707         if (sbp != &mp->mnt_stat) {
  708                 bcopy(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN);
  709                 bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN);
  710         }
  711         strncpy(sbp->f_fstypename, mp->mnt_vfc->vfc_name, MFSNAMELEN);
  712         return (0);
  713 }
  714 
  715 int ext2fs_sync_vnode(struct vnode *vp, void *);
  716 
  717 struct ext2fs_sync_args {
  718         int allerror;
  719         int waitfor;
  720         struct proc *p;
  721         struct ucred *cred;
  722 };
  723 
  724 int
  725 ext2fs_sync_vnode(struct vnode *vp, void *args) 
  726 {
  727         struct ext2fs_sync_args *esa = args;
  728         struct inode *ip;
  729         int error;
  730 
  731         ip = VTOI(vp);
  732         if (vp->v_type == VNON || 
  733             ((ip->i_flag & (IN_ACCESS | IN_CHANGE | IN_MODIFIED | IN_UPDATE)) == 0 &&
  734                 LIST_EMPTY(&vp->v_dirtyblkhd)) ||
  735             esa->waitfor == MNT_LAZY) {
  736                 return (0);
  737         }
  738 
  739         if (vget(vp, LK_EXCLUSIVE | LK_NOWAIT, esa->p))
  740                 return (0);
  741 
  742         if ((error = VOP_FSYNC(vp, esa->cred, esa->waitfor, esa->p)) != 0)
  743                 esa->allerror = error;
  744         vput(vp);
  745         return (0);
  746 }
  747 /*
  748  * Go through the disk queues to initiate sandbagged IO;
  749  * go through the inodes to write those that have been modified;
  750  * initiate the writing of the super block if it has been modified.
  751  *
  752  * Should always be called with the mount point locked.
  753  */
  754 int
  755 ext2fs_sync(struct mount *mp, int waitfor, struct ucred *cred, struct proc *p)
  756 {
  757         struct ufsmount *ump = VFSTOUFS(mp);
  758         struct m_ext2fs *fs;
  759         int error, allerror = 0;
  760         struct ext2fs_sync_args esa;
  761 
  762         fs = ump->um_e2fs;
  763         if (fs->e2fs_ronly != 0) {              /* XXX */
  764                 printf("fs = %s\n", fs->e2fs_fsmnt);
  765                 panic("update: rofs mod");
  766         }
  767 
  768         /*
  769          * Write back each (modified) inode.
  770          */
  771         esa.p = p;
  772         esa.cred = cred;
  773         esa.allerror = 0;
  774         esa.waitfor = waitfor;
  775 
  776         vfs_mount_foreach_vnode(mp, ext2fs_sync_vnode, &esa);
  777         if (esa.allerror != 0)
  778                 allerror = esa.allerror;
  779 
  780         /*
  781          * Force stale file system control information to be flushed.
  782          */
  783         if (waitfor != MNT_LAZY) {
  784                 vn_lock(ump->um_devvp, LK_EXCLUSIVE | LK_RETRY, p);
  785                 if ((error = VOP_FSYNC(ump->um_devvp, cred, waitfor, p)) != 0)
  786                         allerror = error;
  787                 VOP_UNLOCK(ump->um_devvp, 0, p);
  788         }
  789         /*
  790          * Write back modified superblock.
  791          */
  792         if (fs->e2fs_fmod != 0) {
  793                 fs->e2fs_fmod = 0;
  794                 fs->e2fs.e2fs_wtime = time_second;
  795                 if ((error = ext2fs_cgupdate(ump, waitfor)))
  796                         allerror = error;
  797         }
  798         return (allerror);
  799 }
  800 
  801 /*
  802  * Look up a EXT2FS dinode number to find its incore vnode, otherwise read it
  803  * in from disk.  If it is in core, wait for the lock bit to clear, then
  804  * return the inode locked.  Detection and handling of mount points must be
  805  * done by the calling routine.
  806  */
  807 int
  808 ext2fs_vget(struct mount *mp, ino_t ino, struct vnode **vpp)
  809 {
  810         struct m_ext2fs *fs;
  811         struct inode *ip;
  812         struct ext2fs_dinode *dp;
  813         struct ufsmount *ump;
  814         struct buf *bp;
  815         struct vnode *vp;
  816         dev_t dev;
  817         int error;
  818 
  819         ump = VFSTOUFS(mp);
  820         dev = ump->um_dev;
  821 
  822  retry:
  823         if ((*vpp = ufs_ihashget(dev, ino)) != NULL)
  824                 return (0);
  825 
  826         /* Allocate a new vnode/inode. */
  827         if ((error = getnewvnode(VT_EXT2FS, mp, ext2fs_vnodeop_p, &vp)) != 0) {
  828                 *vpp = NULL;
  829                 return (error);
  830         }
  831 
  832         ip = pool_get(&ext2fs_inode_pool, PR_WAITOK);
  833         memset(ip, 0, sizeof(struct inode));
  834         lockinit(&ip->i_lock, PINOD, "inode", 0, 0);
  835         vp->v_data = ip;
  836         ip->i_vnode = vp;
  837         ip->i_ump = ump;
  838         ip->i_e2fs = fs = ump->um_e2fs;
  839         ip->i_dev = dev;
  840         ip->i_number = ino;
  841         ip->i_e2fs_last_lblk = 0;
  842         ip->i_e2fs_last_blk = 0;
  843 
  844         /*
  845          * Put it onto its hash chain and lock it so that other requests for
  846          * this inode will block if they arrive while we are sleeping waiting
  847          * for old data structures to be purged or for the contents of the
  848          * disk portion of this inode to be read.
  849          */
  850         error = ufs_ihashins(ip);
  851 
  852         if (error) {
  853                 vrele(vp);
  854 
  855                 if (error == EEXIST)
  856                         goto retry;
  857 
  858                 return (error);
  859         }
  860 
  861         /* Read in the disk contents for the inode, copy into the inode. */
  862         error = bread(ump->um_devvp, fsbtodb(fs, ino_to_fsba(fs, ino)),
  863                           (int)fs->e2fs_bsize, NOCRED, &bp);
  864         if (error) {
  865                 /*
  866                  * The inode does not contain anything useful, so it would
  867                  * be misleading to leave it on its hash chain. With mode
  868                  * still zero, it will be unlinked and returned to the free
  869                  * list by vput().
  870                  */
  871                 vput(vp);
  872                 brelse(bp);
  873                 *vpp = NULL;
  874                 return (error);
  875         }
  876 
  877         dp = (struct ext2fs_dinode *) bp->b_data + ino_to_fsbo(fs, ino);
  878         ip->i_e2din = pool_get(&ext2fs_dinode_pool, PR_WAITOK);
  879         e2fs_iload(dp, ip->i_e2din);
  880         brelse(bp);
  881 
  882         ip->i_effnlink = ip->i_e2fs_nlink;
  883 
  884         /*
  885          * The fields for storing the UID and GID of an ext2fs inode are
  886          * limited to 16 bits. To overcome this limitation, Linux decided to
  887          * scatter the highest bits of these values into a previously reserved
  888          * area on the disk inode. We deal with this situation by having two
  889          * 32-bit fields *out* of the disk inode to hold the complete values.
  890          * Now that we are reading in the inode, compute these fields.
  891          */
  892         ip->i_e2fs_uid = ip->i_e2fs_uid_low | (ip->i_e2fs_uid_high << 16);
  893         ip->i_e2fs_gid = ip->i_e2fs_gid_low | (ip->i_e2fs_gid_high << 16);
  894 
  895         /* If the inode was deleted, reset all fields */
  896         if (ip->i_e2fs_dtime != 0) {
  897                 ip->i_e2fs_mode = ip->i_e2fs_nblock = 0;
  898                 (void)ext2fs_setsize(ip, 0);
  899         }
  900 
  901         /*
  902          * Initialize the vnode from the inode, check for aliases.
  903          * Note that the underlying vnode may have changed.
  904          */
  905         error = ext2fs_vinit(mp, ext2fs_specop_p, EXT2FS_FIFOOPS, &vp);
  906         if (error) {
  907                 vput(vp);
  908                 *vpp = NULL;
  909                 return (error);
  910         }
  911 
  912         /*
  913          * Finish inode initialization now that aliasing has been resolved.
  914          */
  915         VREF(ip->i_devvp);
  916         /*
  917          * Set up a generation number for this inode if it does not
  918          * already have one. This should only happen on old filesystems.
  919          */
  920         if (ip->i_e2fs_gen == 0) {
  921                 if (++ext2gennumber < (u_long)time_second)
  922                         ext2gennumber = time_second;
  923                 ip->i_e2fs_gen = ext2gennumber;
  924                 if ((vp->v_mount->mnt_flag & MNT_RDONLY) == 0)
  925                         ip->i_flag |= IN_MODIFIED;
  926         }
  927 
  928         *vpp = vp;
  929         return (0);
  930 }
  931 
  932 /*
  933  * File handle to vnode
  934  *
  935  * Have to be really careful about stale file handles:
  936  * - check that the inode number is valid
  937  * - call ext2fs_vget() to get the locked inode
  938  * - check for an unallocated inode (i_mode == 0)
  939  * - check that the given client host has export rights and return
  940  *   those rights via. exflagsp and credanonp
  941  */
  942 int
  943 ext2fs_fhtovp(struct mount *mp, struct fid *fhp, struct vnode **vpp)
  944 {
  945         struct inode *ip;
  946         struct vnode *nvp;
  947         int error;
  948         struct ufid *ufhp;
  949         struct m_ext2fs *fs;
  950 
  951         ufhp = (struct ufid *)fhp;
  952         fs = VFSTOUFS(mp)->um_e2fs;
  953         if ((ufhp->ufid_ino < EXT2_FIRSTINO && ufhp->ufid_ino != EXT2_ROOTINO) ||
  954                 ufhp->ufid_ino > fs->e2fs_ncg * fs->e2fs.e2fs_ipg)
  955                 return (ESTALE);
  956 
  957         if ((error = VFS_VGET(mp, ufhp->ufid_ino, &nvp)) != 0) {
  958                 *vpp = NULLVP;
  959                 return (error);
  960         }
  961         ip = VTOI(nvp);
  962         if (ip->i_e2fs_mode == 0 || ip->i_e2fs_dtime != 0 || 
  963                 ip->i_e2fs_gen != ufhp->ufid_gen) {
  964                 vput(nvp);
  965                 *vpp = NULLVP;
  966                 return (ESTALE);
  967         }
  968         *vpp = nvp;
  969         return (0);
  970 }
  971 
  972 /*
  973  * Vnode pointer to File handle
  974  */
  975 /* ARGSUSED */
  976 int
  977 ext2fs_vptofh(struct vnode *vp, struct fid *fhp)
  978 {
  979         struct inode *ip;
  980         struct ufid *ufhp;
  981 
  982         ip = VTOI(vp);
  983         ufhp = (struct ufid *)fhp;
  984         ufhp->ufid_len = sizeof(struct ufid);
  985         ufhp->ufid_ino = ip->i_number;
  986         ufhp->ufid_gen = ip->i_e2fs_gen;
  987         return (0);
  988 }
  989 
  990 /*
  991  * no sysctl for ext2fs
  992  */
  993 
  994 int
  995 ext2fs_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp,
  996     void *newp, size_t newlen, struct proc *p)
  997 {
  998         return (EOPNOTSUPP);
  999 }
 1000 
 1001 /*
 1002  * Write a superblock and associated information back to disk.
 1003  */
 1004 int
 1005 ext2fs_sbupdate(struct ufsmount *mp, int waitfor)
 1006 {
 1007         struct m_ext2fs *fs = mp->um_e2fs;
 1008         struct buf *bp;
 1009         int error = 0;
 1010 
 1011         bp = getblk(mp->um_devvp, SBLOCK, SBSIZE, 0, 0);
 1012         e2fs_sbsave(&fs->e2fs, (struct ext2fs *) bp->b_data);
 1013         if (waitfor == MNT_WAIT)
 1014                 error = bwrite(bp);
 1015         else
 1016                 bawrite(bp);
 1017         return (error);
 1018 }
 1019 
 1020 int
 1021 ext2fs_cgupdate(struct ufsmount *mp, int waitfor)
 1022 {
 1023         struct m_ext2fs *fs = mp->um_e2fs;
 1024         struct buf *bp;
 1025         int i, error = 0, allerror = 0;
 1026 
 1027         allerror = ext2fs_sbupdate(mp, waitfor);
 1028         for (i = 0; i < fs->e2fs_ngdb; i++) {
 1029                 bp = getblk(mp->um_devvp, fsbtodb(fs, ((fs->e2fs_bsize>1024)?0:1)+i+1),
 1030                     fs->e2fs_bsize, 0, 0);
 1031                 e2fs_cgsave(&fs->e2fs_gd[i* fs->e2fs_bsize / sizeof(struct ext2_gd)], (struct ext2_gd*)bp->b_data, fs->e2fs_bsize);
 1032                 if (waitfor == MNT_WAIT)
 1033                         error = bwrite(bp);
 1034                 else
 1035                         bawrite(bp);
 1036         }
 1037         
 1038         if (!allerror && error)
 1039                 allerror = error;
 1040         return (allerror);
 1041 }
 1042 
 1043 static int
 1044 ext2fs_checksb(struct ext2fs *fs, int ronly)
 1045 {
 1046         if (fs2h16(fs->e2fs_magic) != E2FS_MAGIC) {
 1047                 return (EIO);           /* XXX needs translation */
 1048         }
 1049         if (fs2h32(fs->e2fs_rev) > E2FS_REV1) {
 1050 #ifdef DIAGNOSTIC
 1051                 printf("Ext2 fs: unsupported revision number: %x\n",
 1052                     fs2h32(fs->e2fs_rev));
 1053 #endif
 1054                 return (EIO);           /* XXX needs translation */
 1055         }
 1056         if (fs2h32(fs->e2fs_log_bsize) > 2) { /* block size = 1024|2048|4096 */
 1057 #ifdef DIAGNOSTIC
 1058                 printf("Ext2 fs: bad block size: %d (expected <=2 for ext2 fs)\n",
 1059                     fs2h32(fs->e2fs_log_bsize));
 1060 #endif
 1061                 return (EIO);      /* XXX needs translation */
 1062         }
 1063         if (fs2h32(fs->e2fs_rev) > E2FS_REV0) {
 1064                 if (fs2h32(fs->e2fs_first_ino) != EXT2_FIRSTINO ||
 1065                     fs2h16(fs->e2fs_inode_size) != EXT2_DINODE_SIZE) {
 1066                         printf("Ext2 fs: unsupported inode size\n");
 1067                         return (EINVAL);      /* XXX needs translation */
 1068                 }
 1069                 if (fs2h32(fs->e2fs_features_incompat) &
 1070                     ~EXT2F_INCOMPAT_SUPP) {
 1071                         printf("Ext2 fs: unsupported optional feature\n");
 1072                         return (EINVAL);      /* XXX needs translation */
 1073                 }
 1074                 if (!ronly && fs2h32(fs->e2fs_features_rocompat) &
 1075                     ~EXT2F_ROCOMPAT_SUPP) {
 1076                         return (EROFS);      /* XXX needs translation */
 1077                 }
 1078         }
 1079         return (0);
 1080 }

/* [<][>][^][v][top][bottom][index][help] */