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
mount_updname defined in line 138; used 2 times
mountfs defined in line 158; used 3 times
smount defined in line 28; used 2 times
umount defined in line 256; used 2 times
unmount1 defined in line 265; used 1 times

Defined struct's

a defined in line 258; used 4 times

Defined macros

_MF defined in line 99; used 3 times
Last modified: 1997-06-30
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 3631
Valid CSS Valid XHTML 1.0 Strict