1: /* 2: * Copyright (c) 1982, 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 7.1 (Berkeley) 6/5/86 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: 27: int ino_rw(), ino_ioctl(), ino_select(), ino_close(); 28: struct fileops inodeops = 29: { ino_rw, ino_ioctl, ino_select, ino_close }; 30: 31: ino_rw(fp, rw, uio) 32: struct file *fp; 33: enum uio_rw rw; 34: struct uio *uio; 35: { 36: register struct inode *ip = (struct inode *)fp->f_data; 37: int error; 38: 39: if ((ip->i_mode&IFMT) == IFREG) { 40: ILOCK(ip); 41: if (fp->f_flag&FAPPEND && rw == UIO_WRITE) 42: uio->uio_offset = fp->f_offset = ip->i_size; 43: error = rwip(ip, uio, rw); 44: IUNLOCK(ip); 45: } else 46: error = rwip(ip, uio, rw); 47: return (error); 48: } 49: 50: rdwri(rw, ip, base, len, offset, segflg, aresid) 51: struct inode *ip; 52: caddr_t base; 53: int len, segflg; 54: off_t offset; 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: 495: switch (ip->i_mode&IFMT) { 496: 497: case IFCHR: 498: if ((u_int)maj >= nchrdev) 499: return (ENXIO); 500: return ((*cdevsw[maj].d_open)(dev, mode)); 501: 502: case IFBLK: 503: if ((u_int)maj >= nblkdev) 504: return (ENXIO); 505: return ((*bdevsw[maj].d_open)(dev, mode)); 506: } 507: return (0); 508: } 509: 510: /* 511: * Revoke access the current tty by all processes. 512: * Used only by the super-user in init 513: * to give ``clean'' terminals at login. 514: */ 515: vhangup() 516: { 517: 518: if (!suser()) 519: return; 520: if (u.u_ttyp == NULL) 521: return; 522: forceclose(u.u_ttyd); 523: if ((u.u_ttyp->t_state) & TS_ISOPEN) 524: gsignal(u.u_ttyp->t_pgrp, SIGHUP); 525: } 526: 527: forceclose(dev) 528: dev_t dev; 529: { 530: register struct file *fp; 531: register struct inode *ip; 532: 533: for (fp = file; fp < fileNFILE; fp++) { 534: if (fp->f_count == 0) 535: continue; 536: if (fp->f_type != DTYPE_INODE) 537: continue; 538: ip = (struct inode *)fp->f_data; 539: if (ip == 0) 540: continue; 541: if ((ip->i_mode & IFMT) != IFCHR) 542: continue; 543: if (ip->i_rdev != dev) 544: continue; 545: fp->f_flag &= ~(FREAD|FWRITE); 546: } 547: }