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

##### Functions

    closei            X
    forceclose        X
    ino_ioctl         X
    ino_lock          X
    ino_rw            X
    ino_select        X
    ino_stat          X
    ino_unlock        X
    openi             X
    rdwri             X
    rwip              X
    vhangup           X

##### Variables

    inodeops          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:  *	@(#)sys_inode.c	1.11 (2.11BSD) 1999/9/10
       7:  */
       8:
       9: #include "param.h"
      10: #include "../machine/seg.h"
      11:
      12: #include "user.h"
      13: #include "proc.h"
      14: #include "signalvar.h"
      15: #include "inode.h"
      16: #include "buf.h"
      17: #include "fs.h"
      18: #include "file.h"
      19: #include "stat.h"
      20: #include "mount.h"
      21: #include "conf.h"
      22: #include "uio.h"
      23: #include "ioctl.h"
      24: #include "tty.h"
      25: #include "kernel.h"
      26: #include "systm.h"
      27: #include "syslog.h"
      28: #ifdef QUOTA
      29: #include "quota.h"
      30: #endif
      31:
      32: extern  int vn_closefile();
      33: int ino_rw(), ino_ioctl(), ino_select();
      34:
      35: struct  fileops inodeops =
      36:     { ino_rw, ino_ioctl, ino_select, vn_closefile };
      37:
      38: ino_rw(fp, uio)
      39:     struct file *fp;
      40: register struct uio *uio;
      41: {
      42:     register struct inode *ip = (struct inode *)fp->f_data;
      43:     u_int count, error;
      44:     int ioflag;
      45:
      46:     if ((ip->i_mode&IFMT) != IFCHR)
      47:         ILOCK(ip);
      48:     uio->uio_offset = fp->f_offset;
      49:     count = uio->uio_resid;
      50:     if  (uio->uio_rw == UIO_READ)
      51:         {
      52:         error = rwip(ip, uio, fp->f_flag & FNONBLOCK ? IO_NDELAY : 0);
      53:         fp->f_offset += (count - uio->uio_resid);
      54:         }
      55:     else
      56:         {
      57:         ioflag = 0;
      58:         if  ((ip->i_mode&IFMT) == IFREG && (fp->f_flag & FAPPEND))
      59:             ioflag |= IO_APPEND;
      60:         if  (fp->f_flag & FNONBLOCK)
      61:             ioflag |= IO_NDELAY;
      62:         if  (fp->f_flag & FFSYNC ||
      63:              (ip->i_fs->fs_flags & MNT_SYNCHRONOUS))
      64:             ioflag |= IO_SYNC;
      65:         error = rwip(ip, uio, ioflag);
      66:         if  (ioflag & IO_APPEND)
      67:             fp->f_offset = uio->uio_offset;
      68:         else
      69:             fp->f_offset += (count - uio->uio_resid);
      70:         }
      71:     if ((ip->i_mode&IFMT) != IFCHR)
      72:         IUNLOCK(ip);
      73:     return (error);
      74: }
      75:
      76: rdwri(rw, ip, base, len, offset, segflg, ioflg, aresid)
      77:     enum uio_rw rw;
      78:     struct inode *ip;
      79:     caddr_t base;
      80:     int len;
      81:     off_t offset;
      82:     enum uio_seg segflg;
      83:     int ioflg;
      84: register int *aresid;
      85: {
      86:     struct uio auio;
      87:     struct iovec aiov;
      88: register int error;
      89:
      90:     auio.uio_iov = &aiov;
      91:     auio.uio_iovcnt = 1;
      92:     aiov.iov_base = base;
      93:     aiov.iov_len = len;
      94:     auio.uio_rw = rw;
      95:     auio.uio_resid = len;
      96:     auio.uio_offset = offset;
      97:     auio.uio_segflg = segflg;
      98:     error = rwip(ip, &auio, ioflg);
      99:     if (aresid)
     100:         *aresid = auio.uio_resid;
     101:     else
     102:         if (auio.uio_resid)
     103:             error = EIO;
     104:     return (error);
     105: }
     106:
     107: rwip(ip, uio, ioflag)
     108:     register struct inode *ip;
     109:     register struct uio *uio;
     110:     int ioflag;
     111: {
     112:     dev_t dev = (dev_t)ip->i_rdev;
     113:     register struct buf *bp;
     114:     off_t osize;
     115:     daddr_t lbn, bn;
     116:     int n, on, type, resid;
     117:     int error = 0;
     118:     int flags;
     119:
     120:     if  (uio->uio_offset < 0)
     121:         return (EINVAL);
     122:     type = ip->i_mode&IFMT;
     123: /*
     124:  * The write case below checks that i/o is done synchronously to directories
     125:  * and that i/o to append only files takes place at the end of file.
     126:  * We do not panic on non-sync directory i/o - the sync bit is forced on.
     127: */
     128:     if (uio->uio_rw == UIO_READ)
     129:         {
     130:         if  (!(ip->i_fs->fs_flags & MNT_NOATIME))
     131:             ip->i_flag |= IACC;
     132:         }
     133:     else
     134:        {
     135:        switch (type)
     136:         {
     137:         case IFREG:
     138:             if  (ioflag & IO_APPEND)
     139:             uio->uio_offset = ip->i_size;
     140:             if  (ip->i_flags & APPEND && uio->uio_offset != ip->i_size)
     141:             return(EPERM);
     142:             break;
     143:         case IFDIR:
     144:             if  ((ioflag & IO_SYNC) == 0)
     145:             ioflag |= IO_SYNC;
     146:             break;
     147:         case IFLNK:
     148:         case IFBLK:
     149:         case IFCHR:
     150:             break;
     151:         default:
     152:             return(EFTYPE);
     153:         }
     154:        }
     155:
     156: /*
     157:  * The IO_SYNC flag is turned off here if the 'async' mount flag is on.
     158:  * Otherwise directory I/O (which is done by the kernel) would still
     159:  * synchronous (because the kernel carefully passes IO_SYNC for all directory
     160:  * I/O) even if the fs was mounted with "-o async".
     161:  *
     162:  * A side effect of this is that if the system administrator mounts a filesystem
     163:  * 'async' then the O_FSYNC flag to open() is ignored.
     164:  *
     165:  * This behaviour should probably be selectable via "sysctl fs.async.dirs" and
     166:  * "fs.async.ofsync".  A project for a rainy day.
     167: */
     168:     if (type == IFREG  || type == IFDIR && (ip->i_fs->fs_flags & MNT_ASYNC))
     169:         ioflag &= ~IO_SYNC;
     170:
     171:     if (type == IFCHR)
     172:         {
     173:         if  (uio->uio_rw == UIO_READ)
     174:             {
     175:             if  (!(ip->i_fs->fs_flags & MNT_NOATIME))
     176:             ip->i_flag |= IACC;
     177:             error = (*cdevsw[major(dev)].d_read)(dev, uio, ioflag);
     178:             }
     179:         else
     180:             {
     181:             ip->i_flag |= IUPD|ICHG;
     182:             error = (*cdevsw[major(dev)].d_write)(dev, uio, ioflag);
     183:             }
     184:         return (error);
     185:         }
     186:     if (uio->uio_resid == 0)
     187:         return (0);
     188:     if (uio->uio_rw == UIO_WRITE && type == IFREG &&
     189:         uio->uio_offset + uio->uio_resid >
     190:           u.u_rlimit[RLIMIT_FSIZE].rlim_cur) {
     191:         psignal(u.u_procp, SIGXFSZ);
     192:         return (EFBIG);
     193:     }
     194: #ifdef  QUOTA
     195:     /*
     196: 	 * we do bytes, see the comment on 'blocks' in ino_stat().
     197: 	 *
     198: 	 * the simplfying assumption is made that the entire write will
     199: 	 * succeed, otherwise we have to check the quota on each block.
     200: 	 * can you say slow?  i knew you could.  SMS
     201: 	*/
     202:     if ((type == IFREG || type == IFDIR || type == IFLNK) &&
     203:         uio->uio_rw == UIO_WRITE && !(ip->i_flag & IPIPE)) {
     204:         if (uio->uio_offset + uio->uio_resid > ip->i_size) {
     205:             QUOTAMAP();
     206:             error = chkdq(ip,
     207:                 uio->uio_offset+uio->uio_resid - ip->i_size,0);
     208:             QUOTAUNMAP();
     209:             if (error)
     210:                 return (error);
     211:         }
     212:     }
     213: #endif
     214:     if (type != IFBLK)
     215:         dev = ip->i_dev;
     216:     resid = uio->uio_resid;
     217:     osize = ip->i_size;
     218:
     219:     flags = ioflag & IO_SYNC ? B_SYNC : 0;
     220:
     221:     do {
     222:         lbn = lblkno(uio->uio_offset);
     223:         on = blkoff(uio->uio_offset);
     224:         n = MIN((u_int)(DEV_BSIZE - on), uio->uio_resid);
     225:         if (type != IFBLK) {
     226:             if (uio->uio_rw == UIO_READ) {
     227:                 off_t diff = ip->i_size - uio->uio_offset;
     228:                 if (diff <= 0)
     229:                     return (0);
     230:                 if (diff < n)
     231:                     n = diff;
     232:             bn = bmap(ip, lbn, B_READ, flags);
     233:             }
     234:             else
     235:                 bn = bmap(ip,lbn,B_WRITE,
     236:                        n == DEV_BSIZE ? flags : flags|B_CLRBUF);
     237:             if (u.u_error || uio->uio_rw == UIO_WRITE && (long)bn<0)
     238:                 return (u.u_error);
     239:             if (uio->uio_rw == UIO_WRITE && uio->uio_offset + n > ip->i_size &&
     240:                (type == IFDIR || type == IFREG || type == IFLNK))
     241:                 ip->i_size = uio->uio_offset + n;
     242:         } else {
     243:             bn = lbn;
     244:             rablock = bn + 1;
     245:         }
     246:         if (uio->uio_rw == UIO_READ) {
     247:             if ((long)bn<0) {
     248:                 bp = geteblk();
     249:                 clrbuf(bp);
     250:             } else if (ip->i_lastr + 1 == lbn)
     251:                 bp = breada(dev, bn, rablock);
     252:             else
     253:                 bp = bread(dev, bn);
     254:             ip->i_lastr = lbn;
     255:         } else {
     256:             if (n == DEV_BSIZE)
     257:                 bp = getblk(dev, bn);
     258:             else
     259:                 bp = bread(dev, bn);
     260: /*
     261:  * 4.3 didn't do this, but 2.10 did.  not sure why.
     262:  * something about tape drivers don't clear buffers on end-of-tape
     263:  * any longer (clrbuf can't be called from interrupt).
     264: */
     265:             if (bp->b_resid == DEV_BSIZE) {
     266:                 bp->b_resid = 0;
     267:                 clrbuf(bp);
     268:             }
     269:         }
     270:         n = MIN(n, DEV_BSIZE - bp->b_resid);
     271:         if (bp->b_flags & B_ERROR) {
     272:             error = EIO;
     273:             brelse(bp);
     274:             break;
     275:         }
     276:         u.u_error = uiomove(mapin(bp)+on, n, uio);
     277:         mapout(bp);
     278:         if (uio->uio_rw == UIO_READ) {
     279:             if (n + on == DEV_BSIZE || uio->uio_offset == ip->i_size) {
     280:                 bp->b_flags |= B_AGE;
     281:                 if (ip->i_flag & IPIPE)
     282:                     bp->b_flags &= ~B_DELWRI;
     283:             }
     284:             brelse(bp);
     285:         } else {
     286:             if (ioflag & IO_SYNC)
     287:                 bwrite(bp);
     288: /*
     289:  * The check below interacts _very_ badly with virtual memory tmp files
     290:  * such as those used by 'ld'.   These files tend to be small and repeatedly
     291:  * rewritten in 1kb chunks.  The check below causes the device driver to be
     292:  * called (and I/O initiated)  constantly.  Not sure what to do about this yet
     293:  * but this comment is being placed here as a reminder.
     294: */
     295:             else if (n + on == DEV_BSIZE && !(ip->i_flag & IPIPE)) {
     296:                 bp->b_flags |= B_AGE;
     297:                 bawrite(bp);
     298:             } else
     299:                 bdwrite(bp);
     300:             ip->i_flag |= IUPD|ICHG;
     301:             if (u.u_ruid != 0)
     302:                 ip->i_mode &= ~(ISUID|ISGID);
     303:         }
     304:     } while (u.u_error == 0 && uio->uio_resid && n != 0);
     305:     if (error == 0)             /* XXX */
     306:         error = u.u_error;      /* XXX */
     307:     if (error && (uio->uio_rw == UIO_WRITE) && (ioflag & IO_UNIT) &&
     308:         (type != IFBLK)) {
     309:         itrunc(ip, osize, ioflag & IO_SYNC);
     310:         uio->uio_offset -= (resid - uio->uio_resid);
     311:         uio->uio_resid = resid;
     312: /*
     313:  * Should back out the change to the quota here but that would be a lot
     314:  * of work for little benefit.  Besides we've already made the assumption
     315:  * that the entire write would succeed and users can't turn on the IO_UNIT
     316:  * bit for their writes anyways.
     317: */
     318:     }
     319: #ifdef whybother
     320:     if (!error && (ioflag & IO_SYNC))
     321:         IUPDAT(ip, &time, &time, 1);
     322: #endif
     323:     return (error);
     324: }
     325:
     326:
     327: ino_ioctl(fp, com, data)
     328:     register struct file *fp;
     329:     register u_int com;
     330:     caddr_t data;
     331: {
     332:     register struct inode *ip = ((struct inode *)fp->f_data);
     333:     dev_t dev;
     334:
     335:     switch (ip->i_mode & IFMT) {
     336:
     337:     case IFREG:
     338:     case IFDIR:
     339:         if (com == FIONREAD) {
     340:             if (fp->f_type==DTYPE_PIPE && !(fp->f_flag&FREAD))
     341:                 *(off_t *)data = 0;
     342:             else
     343:                 *(off_t *)data = ip->i_size - fp->f_offset;
     344:             return (0);
     345:         }
     346:         if (com == FIONBIO || com == FIOASYNC)  /* XXX */
     347:             return (0);         /* XXX */
     348:         /* fall into ... */
     349:
     350:     default:
     351:         return (ENOTTY);
     352:
     353:     case IFCHR:
     354:         dev = ip->i_rdev;
     355:         u.u_r.r_val1 = 0;
     356:         if  (setjmp(&u.u_qsave))
     357: /*
     358:  * The ONLY way we can get here is via the longjump in sleep.  Signals have
     359:  * been checked for and u_error set accordingly.  All that remains to do
     360:  * is 'return'.
     361: */
     362:             return(u.u_error);
     363:         return((*cdevsw[major(dev)].d_ioctl)(dev,com,data,fp->f_flag));
     364:     }
     365: }
     366:
     367: ino_select(fp, which)
     368:     struct file *fp;
     369:     int which;
     370: {
     371:     register struct inode *ip = (struct inode *)fp->f_data;
     372:     register dev_t dev;
     373:
     374:     switch (ip->i_mode & IFMT) {
     375:
     376:     default:
     377:         return (1);     /* XXX */
     378:
     379:     case IFCHR:
     380:         dev = ip->i_rdev;
     381:         return (*cdevsw[major(dev)].d_select)(dev, which);
     382:     }
     383: }
     384:
     385: ino_stat(ip, sb)
     386:     register struct inode *ip;
     387:     register struct stat *sb;
     388: {
     389:     register struct icommon2 *ic2;
     390:
     391: #ifdef  EXTERNALITIMES
     392:     mapseg5(xitimes, xitdesc);
     393:     ic2 = &((struct icommon2 *)SEG5)[ip - inode];
     394: #else
     395:     ic2 = &ip->i_ic2;
     396: #endif
     397:
     398: /*
     399:  * inlined ITIMES which takes advantage of the common times pointer.
     400: */
     401:     if (ip->i_flag & (IUPD|IACC|ICHG)) {
     402:         ip->i_flag |= IMOD;
     403:         if (ip->i_flag & IACC)
     404:             ic2->ic_atime = time.tv_sec;
     405:         if (ip->i_flag & IUPD)
     406:             ic2->ic_mtime = time.tv_sec;
     407:         if (ip->i_flag & ICHG)
     408:             ic2->ic_ctime = time.tv_sec;
     409:         ip->i_flag &= ~(IUPD|IACC|ICHG);
     410:     }
     411:     sb->st_dev = ip->i_dev;
     412:     sb->st_ino = ip->i_number;
     413:     sb->st_mode = ip->i_mode;
     414:     sb->st_nlink = ip->i_nlink;
     415:     sb->st_uid = ip->i_uid;
     416:     sb->st_gid = ip->i_gid;
     417:     sb->st_rdev = (dev_t)ip->i_rdev;
     418:     sb->st_size = ip->i_size;
     419:     sb->st_atime = ic2->ic_atime;
     420:     sb->st_spare1 = 0;
     421:     sb->st_mtime = ic2->ic_mtime;
     422:     sb->st_spare2 = 0;
     423:     sb->st_ctime = ic2->ic_ctime;
     424:     sb->st_spare3 = 0;
     425:     sb->st_blksize = MAXBSIZE;
     426:     /*
     427: 	 * blocks are too tough to do; it's not worth the effort.
     428: 	 */
     429:     sb->st_blocks = btodb(ip->i_size + MAXBSIZE - 1);
     430:     sb->st_flags = ip->i_flags;
     431:     sb->st_spare4[0] = 0;
     432:     sb->st_spare4[1] = 0;
     433:     sb->st_spare4[2] = 0;
     434: #ifdef  EXTERNALITIMES
     435:     normalseg5();
     436: #endif
     437:     return (0);
     438: }
     439:
     440: /*
     441:  * This routine, like its counterpart openi(), calls the device driver for
     442:  * special (IBLK, ICHR) files.  Normal files simply return early (the default
     443:  * case in the switch statement).  Pipes and sockets do NOT come here because
     444:  * they have their own close routines.
     445: */
     446:
     447: closei(ip, flag)
     448:     register struct inode *ip;
     449:     int flag;
     450:     {
     451:     register struct mount *mp;
     452:     register struct file *fp;
     453:     int mode, error;
     454:     dev_t   dev;
     455:     int (*cfunc)();
     456:
     457:     mode = ip->i_mode & IFMT;
     458:     dev = ip->i_rdev;
     459:
     460:     switch  (mode)
     461:         {
     462:         case    IFCHR:
     463:             cfunc = cdevsw[major(dev)].d_close;
     464:             break;
     465:         case    IFBLK:
     466:         /*
     467: 		 * We don't want to really close the device if it is mounted
     468: 		 */
     469: /* MOUNT TABLE SHOULD HOLD INODE */
     470:             for (mp = mount; mp < &mount[NMOUNT]; mp++)
     471:                 if (mp->m_inodp != NULL && mp->m_dev == dev)
     472:                     return;
     473:             cfunc = bdevsw[major(dev)].d_close;
     474:             break;
     475:         default:
     476:             return(0);
     477:         }
     478:     /*
     479: 	 * Check that another inode for the same device isn't active.
     480: 	 * This is because the same device can be referenced by two
     481: 	 * different inodes.
     482: 	 */
     483:     for (fp = file; fp < fileNFILE; fp++)
     484:         {
     485:         if (fp->f_type != DTYPE_INODE)
     486:             continue;
     487:         if (fp->f_count && (ip = (struct inode *)fp->f_data) &&
     488:             ip->i_rdev == dev && (ip->i_mode&IFMT) == mode)
     489:             return(0);
     490:         }
     491:     if  (mode == IFBLK)
     492:         {
     493:         /*
     494: 		 * On last close of a block device (that isn't mounted)
     495: 		 * we must invalidate any in core blocks, so that
     496: 		 * we can, for instance, change floppy disks.
     497: 		 */
     498:         bflush(dev);
     499:         binval(dev);
     500:         }
     501: /*
     502:  * NOTE:  none of the device drivers appear to either set u_error OR return
     503:  *	  anything meaningful from their close routines.  It's a good thing
     504:  *	  programs don't bother checking the error status on close() calls.
     505:  *	  Apparently the only time "errno" is meaningful after a "close" is
     506:  *	  when the process is interrupted.
     507: */
     508:     if  (setjmp(&u.u_qsave))
     509:         {
     510:         /*
     511: 		 * If device close routine is interrupted,
     512: 		 * must return so closef can clean up.
     513: 		 */
     514:         if  ((error = u.u_error) == 0)
     515:             error = EINTR;
     516:         }
     517:     else
     518:         error = (*cfunc)(dev, flag, mode);
     519:     return(error);
     520:     }
     521:
     522: /*
     523:  * Place an advisory lock on an inode.
     524:  * NOTE: callers of this routine must be prepared to deal with the pseudo
     525:  *       error return ERESTART.
     526:  */
     527: ino_lock(fp, cmd)
     528:     register struct file *fp;
     529:     int cmd;
     530: {
     531:     register int priority = PLOCK;
     532:     register struct inode *ip = (struct inode *)fp->f_data;
     533:     int error;
     534:
     535:     if ((cmd & LOCK_EX) == 0)
     536:         priority += 4;
     537: /*
     538:  * If there's a exclusive lock currently applied to the file then we've
     539:  * gotta wait for the lock with everyone else.
     540:  *
     541:  * NOTE:  We can NOT sleep on i_exlockc because it is on an odd byte boundary
     542:  *	  and the low (oddness) bit is reserved for networking/supervisor mode
     543:  *	  sleep channels.  Thus we always sleep on i_shlockc and simply check
     544:  *	  the proper bits to see if the lock we want is granted.  This may
     545:  *	  mean an extra wakeup/sleep event is done once in a while but
     546:  *	  everything will work correctly.
     547: */
     548: again:
     549:     while (ip->i_flag & IEXLOCK) {
     550:         /*
     551: 		 * If we're holding an exclusive
     552: 		 * lock, then release it.
     553: 		 */
     554:         if (fp->f_flag & FEXLOCK) {
     555:             ino_unlock(fp, FEXLOCK);
     556:             continue;
     557:         }
     558:         if (cmd & LOCK_NB)
     559:             return (EWOULDBLOCK);
     560:         ip->i_flag |= ILWAIT;
     561:         error = tsleep((caddr_t)&ip->i_shlockc, priority | PCATCH, 0);
     562:         if  (error)
     563:             return(error);
     564:     }
     565:     if ((cmd & LOCK_EX) && (ip->i_flag & ISHLOCK)) {
     566:         /*
     567: 		 * Must wait for any shared locks to finish
     568: 		 * before we try to apply a exclusive lock.
     569: 		 *
     570: 		 * If we're holding a shared
     571: 		 * lock, then release it.
     572: 		 */
     573:         if (fp->f_flag & FSHLOCK) {
     574:             ino_unlock(fp, FSHLOCK);
     575:             goto again;
     576:         }
     577:         if (cmd & LOCK_NB)
     578:             return (EWOULDBLOCK);
     579:         ip->i_flag |= ILWAIT;
     580:         error = tsleep((caddr_t)&ip->i_shlockc, PLOCK | PCATCH, 0);
     581:         if  (error)
     582:             return(error);
     583:         goto again;
     584:     }
     585:     if (cmd & LOCK_EX) {
     586:         cmd &= ~LOCK_SH;
     587:         ip->i_exlockc++;
     588:         ip->i_flag |= IEXLOCK;
     589:         fp->f_flag |= FEXLOCK;
     590:     }
     591:     if ((cmd & LOCK_SH) && (fp->f_flag & FSHLOCK) == 0) {
     592:         ip->i_shlockc++;
     593:         ip->i_flag |= ISHLOCK;
     594:         fp->f_flag |= FSHLOCK;
     595:     }
     596:     return (0);
     597: }
     598:
     599: /*
     600:  * Unlock a file.
     601:  */
     602: ino_unlock(fp, kind)
     603:     register struct file *fp;
     604:     int kind;
     605: {
     606:     register struct inode *ip = (struct inode *)fp->f_data;
     607:     register int flags;
     608:
     609:     kind &= fp->f_flag;
     610:     if (ip == NULL || kind == 0)
     611:         return;
     612:     flags = ip->i_flag;
     613:     if (kind & FSHLOCK) {
     614:         if (--ip->i_shlockc == 0) {
     615:             ip->i_flag &= ~ISHLOCK;
     616:             if (flags & ILWAIT)
     617:                 wakeup((caddr_t)&ip->i_shlockc);
     618:         }
     619:         fp->f_flag &= ~FSHLOCK;
     620:     }
     621:     if (kind & FEXLOCK) {
     622:         if (--ip->i_exlockc == 0) {
     623:             ip->i_flag &= ~(IEXLOCK|ILWAIT);
     624:             if (flags & ILWAIT)
     625:                 wakeup((caddr_t)&ip->i_shlockc);
     626:         }
     627:         fp->f_flag &= ~FEXLOCK;
     628:     }
     629: }
     630:
     631: /*
     632:  * Openi called to allow handler of special files to initialize and
     633:  * validate before actual IO.
     634:  */
     635: openi(ip, mode)
     636:     register struct inode *ip;
     637: {
     638:     register dev_t dev = ip->i_rdev;
     639:     register int maj = major(dev);
     640:     dev_t bdev;
     641:     int error;
     642:
     643:     switch (ip->i_mode&IFMT) {
     644:
     645:     case IFCHR:
     646:         if (ip->i_fs->fs_flags & MNT_NODEV)
     647:             return(ENXIO);
     648:         if ((u_int)maj >= nchrdev)
     649:             return (ENXIO);
     650:         if (mode & FWRITE) {
     651:             /*
     652: 			 * When running in very secure mode, do not allow
     653: 			 * opens for writing of any disk character devices.
     654: 			 */
     655:             if (securelevel >= 2 && isdisk(dev, IFCHR))
     656:                 return(EPERM);
     657:             /*
     658: 			 * When running in secure mode, do not allow opens
     659: 			 * for writing of /dev/mem, /dev/kmem, or character
     660: 			 * devices whose corresponding block devices are
     661: 			 * currently mounted.
     662: 			 */
     663:             if (securelevel >= 1) {
     664:                 if ((bdev = chrtoblk(dev)) != NODEV &&
     665:                     (error = ufs_mountedon(bdev)))
     666:                         return(error);
     667:                 if (iskmemdev(dev))
     668:                     return(EPERM);
     669:             }
     670:         }
     671:         return ((*cdevsw[maj].d_open)(dev, mode, S_IFCHR));
     672:
     673:     case IFBLK:
     674:         if (ip->i_fs->fs_flags & MNT_NODEV)
     675:             return(ENXIO);
     676:         if ((u_int)maj >= nblkdev)
     677:             return (ENXIO);
     678:         /*
     679: 		 * When running in very secure mode, do not allow
     680: 		 * opens for writing of any disk block devices.
     681: 		 */
     682:         if (securelevel >= 2 && (mode & FWRITE) && isdisk(dev, IFBLK))
     683:             return(EPERM);
     684:         /*
     685: 		 * Do not allow opens of block devices that are
     686: 		 * currently mounted.
     687: 		 *
     688: 		 * 2.11BSD must relax this restriction to allow 'fsck' to
     689:  		 * open the root filesystem (which is always mounted) during
     690: 		 * a reboot.  Once in secure or very secure mode the
     691: 		 * above restriction is fully effective.  On the otherhand
     692: 		 * fsck should 1) use the raw device, 2) not do sync calls...
     693: 		 */
     694:         if (securelevel > 0 && (error = ufs_mountedon(dev)))
     695:             return(error);
     696:         return ((*bdevsw[maj].d_open)(dev, mode, S_IFBLK));
     697:     }
     698:     return (0);
     699: }
     700:
     701: /*
     702:  * Revoke access the current tty by all processes.
     703:  * Used only by the super-user in init
     704:  * to give ``clean'' terminals at login.
     705:  */
     706: vhangup()
     707: {
     708:
     709:     if (!suser())
     710:         return;
     711:     if (u.u_ttyp == NULL)
     712:         return;
     713:     forceclose(u.u_ttyd);
     714:     if ((u.u_ttyp->t_state) & TS_ISOPEN)
     715:         gsignal(u.u_ttyp->t_pgrp, SIGHUP);
     716: }
     717:
     718: forceclose(dev)
     719:     register dev_t dev;
     720: {
     721:     register struct file *fp;
     722:     register struct inode *ip;
     723:
     724:     for (fp = file; fp < fileNFILE; fp++) {
     725:         if (fp->f_count == 0)
     726:             continue;
     727:         if (fp->f_type != DTYPE_INODE)
     728:             continue;
     729:         ip = (struct inode *)fp->f_data;
     730:         if (ip == 0)
     731:             continue;
     732:         if ((ip->i_mode & IFMT) != IFCHR)
     733:             continue;
     734:         if (ip->i_rdev != dev)
     735:             continue;
     736:         fp->f_flag &= ~(FREAD|FWRITE);
     737:     }
     738: }

#### Defined functions

closei defined in line 447; used 2 times

- in /usr/src/sys/sys/vfs_vnops.c line 192, 220

forceclose defined in line 718; used 1 times

- in line 713

ino_ioctl defined in line 327; used 4 times

- in line 33-36(2)
- in /usr/src/sys/sys/sys_pipe.c line 19-22(2)

ino_lock defined in line 527; used 2 times

- in /usr/src/sys/sys/kern_descrip.c line 397
- in /usr/src/sys/sys/ufs_syscalls.c line 181

ino_rw defined in line 38; used 2 times

- in line 33-36(2)

ino_select defined in line 367; used 2 times

- in line 33-36(2)

ino_stat defined in line 385; used 2 times

- in /usr/src/sys/sys/kern_descrip.c line 249
- in /usr/src/sys/sys/ufs_syscalls.c line 449

ino_unlock defined in line 602; used 4 times

- in line 555, 574
- in /usr/src/sys/sys/kern_descrip.c line 360, 386

openi defined in line 635; used 1 times

- in /usr/src/sys/sys/vfs_vnops.c line 153

rdwri defined in line 76; used 26 times

- in /usr/src/sys/sys/init_main.c line 361, 383, 393, 403
- in /usr/src/sys/sys/kern_exec.c line 114, 507, 600
- in /usr/src/sys/sys/kern_sig.c line 663, 669-674(2)
- in /usr/src/sys/sys/quota_kern.c line 408, 415, 642, 649
- in /usr/src/sys/sys/ufs_namei.c line 913, 1021, 1051, 1116, 1174
- in /usr/src/sys/sys/ufs_syscalls.c line 328, 477, 1031, 1042, 1222
- in /usr/src/sys/sys/vm_text.c line 221, 233

rwip defined in line 107; used 5 times

- in line 52, 65, 98
- in /usr/src/sys/sys/sys_pipe.c line 130, 209

vhangup defined in line 706; used 2 times

- in /usr/src/sys/sys/init_sysent.c line 89, 186

#### Defined variables

inodeops defined in line 35; used 1 times

- in /usr/src/sys/sys/sys_generic.c line 34

Last modified: 1999-09-14 Generated: 2016-12-26 | Generated by src2html V0.67 page hit count: 1696 |