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: }