1: /*
   2:  * Copyright (c) 1982 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	6.13 (Berkeley) 8/4/85
   7:  */
   8: 
   9: #include "param.h"
  10: #include "systm.h"
  11: #include "dir.h"
  12: #include "user.h"
  13: #include "inode.h"
  14: #include "proc.h"
  15: #include "fs.h"
  16: #include "conf.h"
  17: #include "buf.h"
  18: #include "mount.h"
  19: #include "file.h"
  20: #include "uio.h"
  21: #include "ioctl.h"
  22: #include "tty.h"
  23: #include "cmap.h"
  24: #include "stat.h"
  25: #include "kernel.h"
  26: #include "quota.h"
  27: 
  28: int ino_rw(), ino_ioctl(), ino_select(), ino_close();
  29: struct  fileops inodeops =
  30:     { ino_rw, ino_ioctl, ino_select, ino_close };
  31: 
  32: ino_rw(fp, rw, uio)
  33:     struct file *fp;
  34:     enum uio_rw rw;
  35:     struct uio *uio;
  36: {
  37:     register struct inode *ip = (struct inode *)fp->f_data;
  38:     int error;
  39: 
  40:     if ((ip->i_mode&IFMT) == IFREG) {
  41:         ILOCK(ip);
  42:         if (fp->f_flag&FAPPEND && rw == UIO_WRITE)
  43:             uio->uio_offset = fp->f_offset = ip->i_size;
  44:         error = rwip(ip, uio, rw);
  45:         IUNLOCK(ip);
  46:     } else
  47:         error = rwip(ip, uio, rw);
  48:     return (error);
  49: }
  50: 
  51: rdwri(rw, ip, base, len, offset, segflg, aresid)
  52:     struct inode *ip;
  53:     caddr_t base;
  54:     int len, offset, segflg;
  55:     int *aresid;
  56:     enum uio_rw rw;
  57: {
  58:     struct uio auio;
  59:     struct iovec aiov;
  60:     int error;
  61: 
  62:     auio.uio_iov = &aiov;
  63:     auio.uio_iovcnt = 1;
  64:     aiov.iov_base = base;
  65:     aiov.iov_len = len;
  66:     auio.uio_resid = len;
  67:     auio.uio_offset = offset;
  68:     auio.uio_segflg = segflg;
  69:     error = rwip(ip, &auio, rw);
  70:     if (aresid)
  71:         *aresid = auio.uio_resid;
  72:     else
  73:         if (auio.uio_resid)
  74:             error = EIO;
  75:     return (error);
  76: }
  77: 
  78: rwip(ip, uio, rw)
  79:     register struct inode *ip;
  80:     register struct uio *uio;
  81:     enum uio_rw rw;
  82: {
  83:     dev_t dev = (dev_t)ip->i_rdev;
  84:     struct buf *bp;
  85:     struct fs *fs;
  86:     daddr_t lbn, bn;
  87:     register int n, on, type;
  88:     int size;
  89:     long bsize;
  90:     extern int mem_no;
  91:     int error = 0;
  92: 
  93:     if (rw != UIO_READ && rw != UIO_WRITE)
  94:         panic("rwip");
  95:     if (rw == UIO_READ && uio->uio_resid == 0)
  96:         return (0);
  97:     if (uio->uio_offset < 0 &&
  98:         ((ip->i_mode&IFMT) != IFCHR || mem_no != major(dev)))
  99:         return (EINVAL);
 100:     if (rw == UIO_READ)
 101:         ip->i_flag |= IACC;
 102:     type = ip->i_mode&IFMT;
 103:     if (type == IFCHR) {
 104:         if (rw == UIO_READ)
 105:             error = (*cdevsw[major(dev)].d_read)(dev, uio);
 106:         else {
 107:             ip->i_flag |= IUPD|ICHG;
 108:             error = (*cdevsw[major(dev)].d_write)(dev, uio);
 109:         }
 110:         return (error);
 111:     }
 112:     if (uio->uio_resid == 0)
 113:         return (0);
 114:     if (rw == UIO_WRITE && type == IFREG &&
 115:         uio->uio_offset + uio->uio_resid >
 116:           u.u_rlimit[RLIMIT_FSIZE].rlim_cur) {
 117:         psignal(u.u_procp, SIGXFSZ);
 118:         return (EFBIG);
 119:     }
 120:     if (type != IFBLK) {
 121:         dev = ip->i_dev;
 122:         fs = ip->i_fs;
 123:         bsize = fs->fs_bsize;
 124:     } else
 125:         bsize = BLKDEV_IOSIZE;
 126:     do {
 127:         lbn = uio->uio_offset / bsize;
 128:         on = uio->uio_offset % bsize;
 129:         n = MIN((unsigned)(bsize - on), uio->uio_resid);
 130:         if (type != IFBLK) {
 131:             if (rw == UIO_READ) {
 132:                 int diff = ip->i_size - uio->uio_offset;
 133:                 if (diff <= 0)
 134:                     return (0);
 135:                 if (diff < n)
 136:                     n = diff;
 137:             }
 138:             bn = fsbtodb(fs,
 139:                 bmap(ip, lbn, rw == UIO_WRITE ? B_WRITE: B_READ, (int)(on+n)));
 140:             if (u.u_error || rw == UIO_WRITE && (long)bn<0)
 141:                 return (u.u_error);
 142:             if (rw == UIO_WRITE && uio->uio_offset + n > ip->i_size &&
 143:                (type == IFDIR || type == IFREG || type == IFLNK))
 144:                 ip->i_size = uio->uio_offset + n;
 145:             size = blksize(fs, ip, lbn);
 146:         } else {
 147:             bn = lbn * (BLKDEV_IOSIZE/DEV_BSIZE);
 148:             rablock = bn + (BLKDEV_IOSIZE/DEV_BSIZE);
 149:             rasize = size = bsize;
 150:         }
 151:         if (rw == UIO_READ) {
 152:             if ((long)bn<0) {
 153:                 bp = geteblk(size);
 154:                 clrbuf(bp);
 155:             } else if (ip->i_lastr + 1 == lbn)
 156:                 bp = breada(dev, bn, size, rablock, rasize);
 157:             else
 158:                 bp = bread(dev, bn, size);
 159:             ip->i_lastr = lbn;
 160:         } else {
 161:             int i, count, s;
 162:             extern struct cmap *mfind();
 163: 
 164:             count = howmany(size, DEV_BSIZE);
 165:             s = splimp();
 166:             for (i = 0; i < count; i += CLBYTES / DEV_BSIZE)
 167:                 if (mfind(dev, bn + i))
 168:                     munhash(dev, bn + i);
 169:             splx(s);
 170:             if (n == bsize)
 171:                 bp = getblk(dev, bn, size);
 172:             else
 173:                 bp = bread(dev, bn, size);
 174:         }
 175:         n = MIN(n, size - bp->b_resid);
 176:         if (bp->b_flags & B_ERROR) {
 177:             error = EIO;
 178:             brelse(bp);
 179:             goto bad;
 180:         }
 181:         u.u_error =
 182:             uiomove(bp->b_un.b_addr+on, n, rw, uio);
 183:         if (rw == UIO_READ) {
 184:             if (n + on == bsize || uio->uio_offset == ip->i_size)
 185:                 bp->b_flags |= B_AGE;
 186:             brelse(bp);
 187:         } else {
 188:             if ((ip->i_mode&IFMT) == IFDIR)
 189:                 bwrite(bp);
 190:             else if (n + on == bsize) {
 191:                 bp->b_flags |= B_AGE;
 192:                 bawrite(bp);
 193:             } else
 194:                 bdwrite(bp);
 195:             ip->i_flag |= IUPD|ICHG;
 196:             if (u.u_ruid != 0)
 197:                 ip->i_mode &= ~(ISUID|ISGID);
 198:         }
 199:     } while (u.u_error == 0 && uio->uio_resid > 0 && n != 0);
 200:     if (error == 0)             /* XXX */
 201:         error = u.u_error;      /* XXX */
 202: bad:
 203:     return (error);
 204: }
 205: 
 206: ino_ioctl(fp, com, data)
 207:     struct file *fp;
 208:     register int com;
 209:     caddr_t data;
 210: {
 211:     register struct inode *ip = ((struct inode *)fp->f_data);
 212:     register int fmt = ip->i_mode & IFMT;
 213:     dev_t dev;
 214: 
 215:     switch (fmt) {
 216: 
 217:     case IFREG:
 218:     case IFDIR:
 219:         if (com == FIONREAD) {
 220:             *(off_t *)data = ip->i_size - fp->f_offset;
 221:             return (0);
 222:         }
 223:         if (com == FIONBIO || com == FIOASYNC)  /* XXX */
 224:             return (0);         /* XXX */
 225:         /* fall into ... */
 226: 
 227:     default:
 228:         return (ENOTTY);
 229: 
 230:     case IFCHR:
 231:         dev = ip->i_rdev;
 232:         u.u_r.r_val1 = 0;
 233:         if (setjmp(&u.u_qsave)) {
 234:             if ((u.u_sigintr & sigmask(u.u_procp->p_cursig)) != 0)
 235:                 return(EINTR);
 236:             u.u_eosys = RESTARTSYS;
 237:             return (0);
 238:         }
 239:         return ((*cdevsw[major(dev)].d_ioctl)(dev, com, data,
 240:             fp->f_flag));
 241:     }
 242: }
 243: 
 244: ino_select(fp, which)
 245:     struct file *fp;
 246:     int which;
 247: {
 248:     register struct inode *ip = (struct inode *)fp->f_data;
 249:     register dev_t dev;
 250: 
 251:     switch (ip->i_mode & IFMT) {
 252: 
 253:     default:
 254:         return (1);     /* XXX */
 255: 
 256:     case IFCHR:
 257:         dev = ip->i_rdev;
 258:         return (*cdevsw[major(dev)].d_select)(dev, which);
 259:     }
 260: }
 261: 
 262: #ifdef notdef
 263: ino_clone()
 264: {
 265: 
 266:     return (EOPNOTSUPP);
 267: }
 268: #endif
 269: 
 270: ino_stat(ip, sb)
 271:     register struct inode *ip;
 272:     register struct stat *sb;
 273: {
 274: 
 275:     ITIMES(ip, &time, &time);
 276:     /*
 277: 	 * Copy from inode table
 278: 	 */
 279:     sb->st_dev = ip->i_dev;
 280:     sb->st_ino = ip->i_number;
 281:     sb->st_mode = ip->i_mode;
 282:     sb->st_nlink = ip->i_nlink;
 283:     sb->st_uid = ip->i_uid;
 284:     sb->st_gid = ip->i_gid;
 285:     sb->st_rdev = (dev_t)ip->i_rdev;
 286:     sb->st_size = ip->i_size;
 287:     sb->st_atime = ip->i_atime;
 288:     sb->st_spare1 = 0;
 289:     sb->st_mtime = ip->i_mtime;
 290:     sb->st_spare2 = 0;
 291:     sb->st_ctime = ip->i_ctime;
 292:     sb->st_spare3 = 0;
 293:     /* this doesn't belong here */
 294:     if ((ip->i_mode&IFMT) == IFBLK)
 295:         sb->st_blksize = BLKDEV_IOSIZE;
 296:     else if ((ip->i_mode&IFMT) == IFCHR)
 297:         sb->st_blksize = MAXBSIZE;
 298:     else
 299:         sb->st_blksize = ip->i_fs->fs_bsize;
 300:     sb->st_blocks = ip->i_blocks;
 301:     sb->st_spare4[0] = sb->st_spare4[1] = 0;
 302:     return (0);
 303: }
 304: 
 305: ino_close(fp)
 306:     register struct file *fp;
 307: {
 308:     register struct inode *ip = (struct inode *)fp->f_data;
 309:     register struct mount *mp;
 310:     int flag, mode;
 311:     dev_t dev;
 312:     register int (*cfunc)();
 313: 
 314:     if (fp->f_flag & (FSHLOCK|FEXLOCK))
 315:         ino_unlock(fp, FSHLOCK|FEXLOCK);
 316:     flag = fp->f_flag;
 317:     dev = (dev_t)ip->i_rdev;
 318:     mode = ip->i_mode & IFMT;
 319:     ilock(ip);
 320:     iput(ip);
 321:     fp->f_data = (caddr_t) 0;       /* XXX */
 322:     switch (mode) {
 323: 
 324:     case IFCHR:
 325:         cfunc = cdevsw[major(dev)].d_close;
 326:         break;
 327: 
 328:     case IFBLK:
 329:         /*
 330: 		 * We don't want to really close the device if it is mounted
 331: 		 */
 332: /* MOUNT TABLE SHOULD HOLD INODE */
 333:         for (mp = mount; mp < &mount[NMOUNT]; mp++)
 334:             if (mp->m_bufp != NULL && mp->m_dev == dev)
 335:                 return;
 336:         cfunc = bdevsw[major(dev)].d_close;
 337:         break;
 338: 
 339:     default:
 340:         return;
 341:     }
 342: 
 343:     /*
 344: 	 * Check that another inode for the same device isn't active.
 345: 	 * This is because the same device can be referenced by
 346: 	 * two different inodes.
 347: 	 */
 348:     for (fp = file; fp < fileNFILE; fp++) {
 349:         if (fp->f_type != DTYPE_INODE)      /* XXX */
 350:             continue;
 351:         if (fp->f_count && (ip = (struct inode *)fp->f_data) &&
 352:             ip->i_rdev == dev && (ip->i_mode&IFMT) == mode)
 353:             return;
 354:     }
 355:     if (mode == IFBLK) {
 356:         /*
 357: 		 * On last close of a block device (that isn't mounted)
 358: 		 * we must invalidate any in core blocks, so that
 359: 		 * we can, for instance, change floppy disks.
 360: 		 */
 361:         bflush(dev);
 362:         binval(dev);
 363:     }
 364:     if (setjmp(&u.u_qsave)) {
 365:         /*
 366: 		 * If device close routine is interrupted,
 367: 		 * must return so closef can clean up.
 368: 		 */
 369:         if (u.u_error == 0)
 370:             u.u_error = EINTR;  /* ??? */
 371:         return;
 372:     }
 373:     (*cfunc)(dev, flag);
 374: }
 375: 
 376: /*
 377:  * Place an advisory lock on an inode.
 378:  */
 379: ino_lock(fp, cmd)
 380:     register struct file *fp;
 381:     int cmd;
 382: {
 383:     register int priority = PLOCK;
 384:     register struct inode *ip = (struct inode *)fp->f_data;
 385: 
 386:     if ((cmd & LOCK_EX) == 0)
 387:         priority += 4;
 388:     if (setjmp(&u.u_qsave)) {
 389:         if ((u.u_sigintr & sigmask(u.u_procp->p_cursig)) != 0)
 390:             return(EINTR);
 391:         u.u_eosys = RESTARTSYS;
 392:         return (0);
 393:     }
 394:     /*
 395: 	 * If there's a exclusive lock currently applied
 396: 	 * to the file, then we've gotta wait for the
 397: 	 * lock with everyone else.
 398: 	 */
 399: again:
 400:     while (ip->i_flag & IEXLOCK) {
 401:         /*
 402: 		 * If we're holding an exclusive
 403: 		 * lock, then release it.
 404: 		 */
 405:         if (fp->f_flag & FEXLOCK) {
 406:             ino_unlock(fp, FEXLOCK);
 407:             continue;
 408:         }
 409:         if (cmd & LOCK_NB)
 410:             return (EWOULDBLOCK);
 411:         ip->i_flag |= ILWAIT;
 412:         sleep((caddr_t)&ip->i_exlockc, priority);
 413:     }
 414:     if ((cmd & LOCK_EX) && (ip->i_flag & ISHLOCK)) {
 415:         /*
 416: 		 * Must wait for any shared locks to finish
 417: 		 * before we try to apply a exclusive lock.
 418: 		 *
 419: 		 * If we're holding a shared
 420: 		 * lock, then release it.
 421: 		 */
 422:         if (fp->f_flag & FSHLOCK) {
 423:             ino_unlock(fp, FSHLOCK);
 424:             goto again;
 425:         }
 426:         if (cmd & LOCK_NB)
 427:             return (EWOULDBLOCK);
 428:         ip->i_flag |= ILWAIT;
 429:         sleep((caddr_t)&ip->i_shlockc, PLOCK);
 430:         goto again;
 431:     }
 432:     if (fp->f_flag & FEXLOCK)
 433:         panic("ino_lock");
 434:     if (cmd & LOCK_EX) {
 435:         cmd &= ~LOCK_SH;
 436:         ip->i_exlockc++;
 437:         ip->i_flag |= IEXLOCK;
 438:         fp->f_flag |= FEXLOCK;
 439:     }
 440:     if ((cmd & LOCK_SH) && (fp->f_flag & FSHLOCK) == 0) {
 441:         ip->i_shlockc++;
 442:         ip->i_flag |= ISHLOCK;
 443:         fp->f_flag |= FSHLOCK;
 444:     }
 445:     return (0);
 446: }
 447: 
 448: /*
 449:  * Unlock a file.
 450:  */
 451: ino_unlock(fp, kind)
 452:     register struct file *fp;
 453:     int kind;
 454: {
 455:     register struct inode *ip = (struct inode *)fp->f_data;
 456:     int flags;
 457: 
 458:     kind &= fp->f_flag;
 459:     if (ip == NULL || kind == 0)
 460:         return;
 461:     flags = ip->i_flag;
 462:     if (kind & FSHLOCK) {
 463:         if ((flags & ISHLOCK) == 0)
 464:             panic("ino_unlock: SHLOCK");
 465:         if (--ip->i_shlockc == 0) {
 466:             ip->i_flag &= ~ISHLOCK;
 467:             if (flags & ILWAIT)
 468:                 wakeup((caddr_t)&ip->i_shlockc);
 469:         }
 470:         fp->f_flag &= ~FSHLOCK;
 471:     }
 472:     if (kind & FEXLOCK) {
 473:         if ((flags & IEXLOCK) == 0)
 474:             panic("ino_unlock: EXLOCK");
 475:         if (--ip->i_exlockc == 0) {
 476:             ip->i_flag &= ~(IEXLOCK|ILWAIT);
 477:             if (flags & ILWAIT)
 478:                 wakeup((caddr_t)&ip->i_exlockc);
 479:         }
 480:         fp->f_flag &= ~FEXLOCK;
 481:     }
 482: }
 483: 
 484: /*
 485:  * Openi called to allow handler
 486:  * of special files to initialize and
 487:  * validate before actual IO.
 488:  */
 489: openi(ip, mode)
 490:     register struct inode *ip;
 491: {
 492:     dev_t dev = (dev_t)ip->i_rdev;
 493:     register int maj = major(dev);
 494:     int minnum = minor(dev);
 495:     register int error;
 496: 
 497:     switch (ip->i_mode&IFMT) {
 498: 
 499:     case IFCHR:
 500:         if ((u_int)maj >= nchrdev)
 501:             return (ENXIO);
 502:         error = (*cdevsw[maj].d_open)(dev, mode, &minnum);
 503: 
 504:         /*
 505: 		 * Test for new minor device inode allocation
 506: 		 */
 507:         if ((error == 0) && (minnum != minor(dev))) {
 508:             register struct inode *nip;
 509: 
 510:             /*
 511: 			 * Allocate new inode with new minor device
 512: 			 * Release old inode. Set vpp to point to new one.
 513: 			 * This inode will go away when the last reference
 514: 			 * to it goes away.
 515: 			 * Warning: if you stat this, and try to match it
 516: 			 * with a name in the filesystem you will fail,
 517: 			 * unless you had previously put names in that match.
 518: 			 */
 519:             nip = ialloc(ip, dirpref(ip->i_fs), (int)ip->i_mode);
 520:             if (nip == (struct inode *)0) {
 521:                 /*
 522: 				 * Give driver a chance to clean up;
 523: 				 * this is iffy since other instances
 524: 				 * of this device could be active.
 525: 				 */
 526:                 cdevsw[maj].d_close(makedev(maj, minnum),
 527:                                 mode&FMASK);
 528:                 return (ENXIO);
 529:             }
 530:             nip->i_flag |= IACC|IUPD|ICHG;
 531:             nip->i_mode = ip->i_mode;
 532:             nip->i_nlink = 0;
 533:             nip->i_uid = ip->i_uid;
 534:             nip->i_gid = ip->i_gid;
 535:             nip->i_rdev = makedev(maj, minnum);
 536: #ifdef QUOTA
 537:             nip->i_dquot = inoquota(nip);
 538: #endif
 539:             irele(ip);
 540:             ip = nip;
 541:             iunlock(ip);
 542:             /*
 543: 			 * This next line depends on the way copen()
 544: 			 * works; it's a kludge.
 545: 			 */
 546:             u.u_ofile[u.u_r.r_val1]->f_data = (caddr_t)ip;
 547:         }
 548:         return(error);
 549: 
 550:     case IFBLK:
 551:         if ((u_int)maj >= nblkdev)
 552:             return (ENXIO);
 553:         return ((*bdevsw[maj].d_open)(dev, mode));
 554:     }
 555:     return (0);
 556: }
 557: 
 558: /*
 559:  * Revoke access the current tty by all processes.
 560:  * Used only by the super-user in init
 561:  * to give ``clean'' terminals at login.
 562:  */
 563: vhangup()
 564: {
 565: 
 566:     if (!suser())
 567:         return;
 568:     if (u.u_ttyp == NULL)
 569:         return;
 570:     forceclose(u.u_ttyd);
 571:     if ((u.u_ttyp->t_state) & TS_ISOPEN)
 572:         gsignal(u.u_ttyp->t_pgrp, SIGHUP);
 573: }
 574: 
 575: forceclose(dev)
 576:     dev_t dev;
 577: {
 578:     register struct file *fp;
 579:     register struct inode *ip;
 580: 
 581:     for (fp = file; fp < fileNFILE; fp++) {
 582:         if (fp->f_count == 0)
 583:             continue;
 584:         if (fp->f_type != DTYPE_INODE)
 585:             continue;
 586:         ip = (struct inode *)fp->f_data;
 587:         if (ip == 0)
 588:             continue;
 589:         if ((ip->i_mode & IFMT) != IFCHR)
 590:             continue;
 591:         if (ip->i_rdev != dev)
 592:             continue;
 593:         fp->f_flag &= ~(FREAD|FWRITE);
 594:     }
 595: }

Defined functions

forceclose defined in line 575; used 1 times
ino_clone defined in line 263; never used
ino_close defined in line 305; used 2 times
ino_ioctl defined in line 206; used 2 times
ino_lock defined in line 379; never used
ino_rw defined in line 32; used 2 times
ino_select defined in line 244; used 2 times
ino_stat defined in line 270; never used
ino_unlock defined in line 451; used 3 times
openi defined in line 489; never used
rdwri defined in line 51; never used
rwip defined in line 78; used 3 times
vhangup defined in line 563; never used

Defined variables

inodeops defined in line 29; never used
Last modified: 1985-11-11
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 784
Valid CSS Valid XHTML 1.0 Strict