# 2.11BSD#431 - /usr/src/sys/sys/ufs_mount.c

##### Functions

    getmdev           X
    mount_updname     X
    mountfs           X
    smount            X
    umount            X
    unmount1          X

##### Macros

    _MF               X

##### struct's

    a                 X

       1: /*
       2:  * Copyright (c) 1986 Regents of the University of California.
       3:  * All rights reserved.  The Berkeley software License Agreement
       4:  * specifies the terms and conditions for redistribution.
       5:  *
       6:  *	@(#)ufs_mount.c	2.1 (2.11BSD GTE) 1997/6/29
       7:  */
       8:
       9: #include "param.h"
      10: #include "../machine/seg.h"
      11:
      12: #include "systm.h"
      13: #include "user.h"
      14: #include "inode.h"
      15: #include "fs.h"
      16: #include "buf.h"
      17: #include "mount.h"
      18: #include "file.h"
      19: #include "namei.h"
      20: #include "conf.h"
      21: #include "stat.h"
      22: #include "disklabel.h"
      23: #include "ioctl.h"
      24: #ifdef QUOTA
      25: #include "quota.h"
      26: #endif
      27:
      28: smount()
      29: {
      30:     register struct a {
      31:         char    *fspec;
      32:         char    *freg;
      33:         int flags;
      34:     } *uap = (struct a *)u.u_ap;
      35:     dev_t dev;
      36:     register struct inode *ip;
      37:     register struct fs *fs;
      38:     struct  nameidata nd;
      39:     struct  nameidata *ndp = &nd;
      40:     struct  mount   *mp;
      41:     u_int lenon, lenfrom;
      42:     int error = 0;
      43:     char    mnton[MNAMELEN], mntfrom[MNAMELEN];
      44:
      45:     if  (u.u_error = getmdev(&dev, uap->fspec))
      46:         return;
      47:     NDINIT(ndp, LOOKUP, FOLLOW, UIO_USERSPACE, uap->freg);
      48:     if  ((ip = namei(ndp)) == NULL)
      49:         return;
      50:     if ((ip->i_mode&IFMT) != IFDIR) {
      51:         error = ENOTDIR;
      52:         goto    cmnout;
      53:     }
      54: /*
      55:  * The following two copyinstr calls will not fault because getmdev() or
      56:  * namei() would have returned an error for invalid parameters.
      57: */
      58:     copyinstr(uap->freg, mnton, sizeof (mnton) - 1, &lenon);
      59:     copyinstr(uap->fspec, mntfrom, sizeof (mntfrom) - 1, &lenfrom);
      60:
      61:     if  (uap->flags & MNT_UPDATE)
      62:         {
      63:         fs = ip->i_fs;
      64:         mp = (struct mount *)
      65:             ((int)fs - offsetof(struct mount, m_filsys));
      66:         if  (ip->i_number != ROOTINO)
      67:             {
      68:             error = EINVAL;     /* Not a mount point */
      69:             goto    cmnout;
      70:             }
      71: /*
      72:  * Check that the device passed in is the same one that is in the mount
      73:  * table entry for this mount point.
      74: */
      75:         if  (dev != mp->m_dev)
      76:             {
      77:             error = EINVAL;     /* not right mount point */
      78:             goto    cmnout;
      79:             }
      80: /*
      81:  * This is where the RW to RO transformation would be done.  It is, for now,
      82:  * too much work to port pages of code to do (besides which most
      83:  * programs get very upset at having access yanked out from under them).
      84: */
      85:         if  (fs->fs_ronly == 0 && (uap->flags & MNT_RDONLY))
      86:             {
      87:             error = EPERM;      /* ! RW to RO updates */
      88:             goto    cmnout;
      89:             }
      90: /*
      91:  * However, going from RO to RW is easy.  Then merge in the new
      92:  * flags (async, sync, nodev, etc) passed in from the program.
      93: */
      94:         if  (fs->fs_ronly && ((uap->flags & MNT_RDONLY) == 0))
      95:             {
      96:             fs->fs_ronly = 0;
      97:             mp->m_flags &= ~MNT_RDONLY;
      98:             }
      99: #define _MF (MNT_NOSUID | MNT_NODEV | MNT_NOEXEC | MNT_ASYNC | MNT_SYNCHRONOUS | MNT_NOATIME)
     100:         mp->m_flags &= ~_MF;
     101:         mp->m_flags |= (uap->flags & _MF);
     102: #undef _MF
     103:         iput(ip);
     104:         u.u_error = 0;
     105:         goto    updname;
     106:         }
     107:     else
     108:         {
     109: /*
     110:  * This is where a new mount (not an update of an existing mount point) is
     111:  * done.
     112:  *
     113:  * The directory being mounted on can have no other references AND can not
     114:  * currently be a mount point.  Mount points have an inode number of (you
     115:  * guessed it) ROOTINO which is 2.
     116: */
     117:         if  (ip->i_count != 1 || (ip->i_number == ROOTINO))
     118:             {
     119:             error = EBUSY;
     120:             goto cmnout;
     121:             }
     122:         fs = mountfs(dev, uap->flags, ip);
     123:         if  (fs == 0)
     124:             return;
     125:         }
     126: /*
     127:  * Lastly, both for new mounts and updates of existing mounts, update the
     128:  * mounted-on and mounted-from fields.
     129: */
     130: updname:
     131:     mount_updname(fs, mnton, mntfrom, lenon, lenfrom);
     132:     return;
     133: cmnout:
     134:     iput(ip);
     135:     return(u.u_error = error);
     136: }
     137:
     138: mount_updname(fs, on, from, lenon, lenfrom)
     139:     struct  fs  *fs;
     140:     char    *on, *from;
     141:     int lenon, lenfrom;
     142:     {
     143:     struct  mount   *mp;
     144:     register struct xmount  *xmp;
     145:
     146:     bzero(fs->fs_fsmnt, sizeof (fs->fs_fsmnt));
     147:     bcopy(on, fs->fs_fsmnt, sizeof (fs->fs_fsmnt) - 1);
     148:     mp = (struct mount *)((int)fs - offsetof(struct mount, m_filsys));
     149:     xmp = (struct xmount *)SEG5;
     150:     mapseg5(mp->m_extern, XMOUNTDESC);
     151:     bzero(xmp, sizeof (struct xmount));
     152:     bcopy(on, xmp->xm_mnton, lenon);
     153:     bcopy(from, xmp->xm_mntfrom, lenfrom);
     154:     normalseg5();
     155:     }
     156:
     157: /* this routine has races if running twice */
     158: struct fs *
     159: mountfs(dev, flags, ip)
     160:     dev_t dev;
     161:     int flags;
     162:     struct inode *ip;
     163: {
     164:     register struct mount *mp = 0;
     165:     struct buf *tp = 0;
     166:     register struct fs *fs;
     167:     register int error;
     168:     int ronly = flags & MNT_RDONLY;
     169:     int needclose = 0;
     170:     int chrdev, (*ioctl)();
     171:     struct  partinfo dpart;
     172:
     173:     error =
     174:         (*bdevsw[major(dev)].d_open)(dev, ronly ? FREAD : FREAD|FWRITE, S_IFBLK);
     175:     if (error)
     176:         goto out;
     177: /*
     178:  * Now make a check that the partition is really a filesystem if the
     179:  * underlying driver supports disklabels (there is an ioctl entry point
     180:  * and calling it does not return an error).
     181:  *
     182:  * XXX - Check for NODEV because BLK only devices (i.e. the 'ram' driver) do not
     183:  * XXX - have a CHR counterpart.  Such drivers can not support labels due to
     184:  * XXX - the lack of an ioctl entry point.
     185: */
     186:     chrdev = blktochr(dev);
     187:     if  (chrdev == NODEV)
     188:         ioctl = NULL;
     189:     else
     190:         ioctl = cdevsw[chrdev].d_ioctl;
     191:     if  (ioctl && !(*ioctl)(dev, DIOCGPART, &dpart, FREAD))
     192:         {
     193:         if  (dpart.part->p_fstype != FS_V71K)
     194:             {
     195:             error = EINVAL;
     196:             goto out;
     197:             }
     198:         }
     199:     needclose = 1;
     200:     tp = bread(dev, SBLOCK);
     201:     if (tp->b_flags & B_ERROR)
     202:         goto out;
     203:     for (mp = &mount[0]; mp < &mount[NMOUNT]; mp++)
     204:         if (mp->m_inodp != 0 && dev == mp->m_dev) {
     205:             mp = 0;
     206:             error = EBUSY;
     207:             needclose = 0;
     208:             goto out;
     209:         }
     210:     for (mp = &mount[0]; mp < &mount[NMOUNT]; mp++)
     211:         if (mp->m_inodp == 0)
     212:             goto found;
     213:     mp = 0;
     214:     error = EMFILE;     /* needs translation */
     215:     goto out;
     216: found:
     217:     mp->m_inodp = ip;   /* reserve slot */
     218:     mp->m_dev = dev;
     219:     fs = &mp->m_filsys;
     220:     bcopy(mapin(tp), (caddr_t)fs, sizeof(struct fs));
     221:     mapout(tp);
     222:     brelse(tp);
     223:     tp = 0;
     224:     fs->fs_ronly = (ronly != 0);
     225:     if (ronly == 0)
     226:         fs->fs_fmod = 1;
     227:     fs->fs_ilock = 0;
     228:     fs->fs_flock = 0;
     229:     fs->fs_nbehind = 0;
     230:     fs->fs_lasti = 1;
     231:     fs->fs_flags = flags;
     232:     if (ip) {
     233:         ip->i_flag |= IMOUNT;
     234:         cacheinval(ip);
     235:         IUNLOCK(ip);
     236:     }
     237:     return (fs);
     238: out:
     239:     if (error == 0)
     240:         error = EIO;
     241:     if (ip)
     242:         iput(ip);
     243:     if (mp)
     244:         mp->m_inodp = 0;
     245:     if (tp)
     246:         brelse(tp);
     247:     if (needclose) {
     248:         (*bdevsw[major(dev)].d_close)(dev,
     249:             ronly? FREAD : FREAD|FWRITE, S_IFBLK);
     250:         binval(dev);
     251:     }
     252:     u.u_error = error;
     253:     return (0);
     254: }
     255:
     256: umount()
     257: {
     258:     struct a {
     259:         char    *fspec;
     260:     } *uap = (struct a *)u.u_ap;
     261:
     262:     u.u_error = unmount1(uap->fspec);
     263: }
     264:
     265: unmount1(fname)
     266:     caddr_t fname;
     267: {
     268:     dev_t dev;
     269:     register struct mount *mp;
     270:     register struct inode *ip;
     271:     register int error;
     272:     int aflag;
     273:
     274:     error = getmdev(&dev, fname);
     275:     if (error)
     276:         return (error);
     277:     for (mp = &mount[0]; mp < &mount[NMOUNT]; mp++)
     278:         if (mp->m_inodp != NULL && dev == mp->m_dev)
     279:             goto found;
     280:     return (EINVAL);
     281: found:
     282:     xumount(dev);   /* remove unused sticky files from text table */
     283:     nchinval(dev);  /* flush the name cache */
     284:     aflag = mp->m_flags & MNT_ASYNC;
     285:     mp->m_flags &= ~MNT_ASYNC;  /* Don't want async when unmounting */
     286:     ufs_sync(mp);
     287:
     288: #ifdef QUOTA
     289:     if (iflush(dev, mp->m_qinod) < 0)
     290: #else
     291:     if (iflush(dev) < 0)
     292: #endif
     293:         {
     294:         mp->m_flags |= aflag;
     295:         return (EBUSY);
     296:         }
     297: #ifdef QUOTA
     298:     QUOTAMAP();
     299:     closedq(mp);
     300:     QUOTAUNMAP();
     301:     /*
     302: 	 * Here we have to iflush again to get rid of the quota inode.
     303: 	 * A drag, but it would be ugly to cheat, & this doesn't happen often
     304: 	 */
     305:     (void)iflush(dev, (struct inode *)NULL);
     306: #endif
     307:     ip = mp->m_inodp;
     308:     ip->i_flag &= ~IMOUNT;
     309:     irele(ip);
     310:     mp->m_inodp = 0;
     311:     mp->m_dev = 0;
     312:     (*bdevsw[major(dev)].d_close)(dev, 0, S_IFBLK);
     313:     binval(dev);
     314:     return (0);
     315: }
     316:
     317: /*
     318:  * Common code for mount and umount.
     319:  * Check that the user's argument is a reasonable
     320:  * thing on which to mount, otherwise return error.
     321:  */
     322: getmdev(pdev, fname)
     323:     caddr_t fname;
     324:     dev_t *pdev;
     325: {
     326:     register dev_t dev;
     327:     register struct inode *ip;
     328:     struct  nameidata nd;
     329:     register struct nameidata *ndp = &nd;
     330:
     331:     if (!suser())
     332:         return (u.u_error);
     333:     NDINIT(ndp, LOOKUP, FOLLOW, UIO_USERSPACE, fname);
     334:     ip = namei(ndp);
     335:     if (ip == NULL) {
     336:         if (u.u_error == ENOENT)
     337:             return (ENODEV); /* needs translation */
     338:         return (u.u_error);
     339:     }
     340:     if ((ip->i_mode&IFMT) != IFBLK) {
     341:         iput(ip);
     342:         return (ENOTBLK);
     343:     }
     344:     dev = (dev_t)ip->i_rdev;
     345:     iput(ip);
     346:     if (major(dev) >= nblkdev)
     347:         return (ENXIO);
     348:     *pdev = dev;
     349:     return (0);
     350: }

#### Defined functions

getmdev defined in line 322; used 3 times

- in line 45, 274
- in /usr/src/sys/sys/quota_sys.c line 37

mount_updname defined in line 138; used 2 times

- in line 131
- in /usr/src/sys/sys/init_main.c line 196

mountfs defined in line 158; used 3 times

- in line 122
- in /usr/src/sys/h/fs.h line 133
- in /usr/src/sys/sys/init_main.c line 191

smount defined in line 28; used 2 times

- in /usr/src/sys/sys/init_sysent.c line 50, 131

umount defined in line 256; used 2 times

- in /usr/src/sys/sys/init_sysent.c line 50, 132

unmount1 defined in line 265; used 1 times

- in line 262

#### Defined struct's

a defined in line 258; used 4 times

- in line 34(2), 260(2)

#### Defined macros

_MF defined in line 99; used 3 times

- in line 100-102(3)

Last modified: 1997-06-30 Generated: 2016-12-26 | Generated by src2html V0.67 page hit count: 1008 |