Annotation of 43BSD/contrib/enet/sys/sys_inode.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.