Annotation of 43BSDReno/sys/kern/vfs_vnops.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 1982, 1986, 1989 Regents of the University of California.
                      3:  * All rights reserved.
                      4:  *
                      5:  * Redistribution is only permitted until one year after the first shipment
                      6:  * of 4.4BSD by the Regents.  Otherwise, redistribution and use in source and
                      7:  * binary forms are permitted provided that: (1) source distributions retain
                      8:  * this entire copyright notice and comment, and (2) distributions including
                      9:  * binaries display the following acknowledgement:  This product includes
                     10:  * software developed by the University of California, Berkeley and its
                     11:  * contributors'' in the documentation or other materials provided with the
                     12:  * distribution and in all advertising materials mentioning features or use
                     13:  * of this software.  Neither the name of the University nor the names of
                     14:  * its contributors may be used to endorse or promote products derived from
                     15:  * this software without specific prior written permission.
                     16:  * THIS SOFTWARE IS PROVIDED AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
                     17:  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
                     18:  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
                     19:  *
                     20:  *     @(#)vfs_vnops.c 7.23 (Berkeley) 6/28/90
                     21:  */
                     22: 
                     23: #include "param.h"
                     24: #include "systm.h"
                     25: #include "user.h"
                     26: #include "kernel.h"
                     27: #include "file.h"
                     28: #include "stat.h"
                     29: #include "buf.h"
                     30: #include "proc.h"
                     31: #include "uio.h"
                     32: #include "socket.h"
                     33: #include "socketvar.h"
                     34: #include "mount.h"
                     35: #include "vnode.h"
                     36: #include "ioctl.h"
                     37: #include "tty.h"
                     38: 
                     39: int    vn_read(), vn_write(), vn_ioctl(), vn_select(), vn_close();
                     40: struct         fileops vnops =
                     41:        { vn_read, vn_write, vn_ioctl, vn_select, vn_close };
                     42: 
                     43: /*
                     44:  * Common code for vnode open operations.
                     45:  * Check permissions, and call the VOP_OPEN or VOP_CREATE routine.
                     46:  */
                     47: vn_open(ndp, fmode, cmode)
                     48:        register struct nameidata *ndp;
                     49:        int fmode, cmode;
                     50: {
                     51:        register struct vnode *vp;
                     52:        struct vattr vat;
                     53:        struct vattr *vap = &vat;
                     54:        int error;
                     55: 
                     56:        if (fmode & FCREAT) {
                     57:                ndp->ni_nameiop = CREATE | LOCKPARENT | LOCKLEAF;
                     58:                if ((fmode & FEXCL) == 0)
                     59:                        ndp->ni_nameiop |= FOLLOW;
                     60:                if (error = namei(ndp))
                     61:                        return (error);
                     62:                if (ndp->ni_vp == NULL) {
                     63:                        VATTR_NULL(vap);
                     64:                        vap->va_type = VREG;
                     65:                        vap->va_mode = cmode;
                     66:                        if (error = VOP_CREATE(ndp, vap))
                     67:                                return (error);
                     68:                        fmode &= ~FTRUNC;
                     69:                        vp = ndp->ni_vp;
                     70:                } else {
                     71:                        if (ndp->ni_dvp == ndp->ni_vp)
                     72:                                vrele(ndp->ni_dvp);
                     73:                        else
                     74:                                vput(ndp->ni_dvp);
                     75:                        ndp->ni_dvp = NULL;
                     76:                        vp = ndp->ni_vp;
                     77:                        if (fmode & FEXCL) {
                     78:                                error = EEXIST;
                     79:                                goto bad;
                     80:                        }
                     81:                        fmode &= ~FCREAT;
                     82:                }
                     83:        } else {
                     84:                ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF;
                     85:                if (error = namei(ndp))
                     86:                        return (error);
                     87:                vp = ndp->ni_vp;
                     88:        }
                     89:        if (vp->v_type == VSOCK) {
                     90:                error = EOPNOTSUPP;
                     91:                goto bad;
                     92:        }
                     93:        if ((fmode & FCREAT) == 0) {
                     94:                if (fmode & FREAD) {
                     95:                        if (error = VOP_ACCESS(vp, VREAD, ndp->ni_cred))
                     96:                                goto bad;
                     97:                }
                     98:                if (fmode & (FWRITE|FTRUNC)) {
                     99:                        if (vp->v_type == VDIR) {
                    100:                                error = EISDIR;
                    101:                                goto bad;
                    102:                        }
                    103:                        if ((error = vn_writechk(vp)) ||
                    104:                            (error = VOP_ACCESS(vp, VWRITE, ndp->ni_cred)))
                    105:                                goto bad;
                    106:                }
                    107:        }
                    108:        if (fmode & FTRUNC) {
                    109:                VATTR_NULL(vap);
                    110:                vap->va_size = 0;
                    111:                if (error = VOP_SETATTR(vp, vap, ndp->ni_cred))
                    112:                        goto bad;
                    113:        }
                    114:        VOP_UNLOCK(vp);
                    115:        error = VOP_OPEN(vp, fmode, ndp->ni_cred);
                    116:        if (error)
                    117:                vrele(vp);
                    118:        return (error);
                    119: 
                    120: bad:
                    121:        vput(vp);
                    122:        return (error);
                    123: }
                    124: 
                    125: /*
                    126:  * Check for write permissions on the specified vnode.
                    127:  * The read-only status of the file system is checked.
                    128:  * Also, prototype text segments cannot be written.
                    129:  */
                    130: vn_writechk(vp)
                    131:        register struct vnode *vp;
                    132: {
                    133: 
                    134:        /*
                    135:         * Disallow write attempts on read-only file systems;
                    136:         * unless the file is a socket or a block or character
                    137:         * device resident on the file system.
                    138:         */
                    139:        if ((vp->v_mount->mnt_flag & MNT_RDONLY) && vp->v_type != VCHR &&
                    140:            vp->v_type != VBLK && vp->v_type != VSOCK)
                    141:                return (EROFS);
                    142:        /*
                    143:         * If there's shared text associated with
                    144:         * the vnode, try to free it up once.  If
                    145:         * we fail, we can't allow writing.
                    146:         */
                    147:        if (vp->v_flag & VTEXT)
                    148:                xrele(vp);
                    149:        if (vp->v_flag & VTEXT)
                    150:                return (ETXTBSY);
                    151:        return (0);
                    152: }
                    153: 
                    154: /*
                    155:  * Vnode version of rdwri() for calls on file systems.
                    156:  */
                    157: vn_rdwr(rw, vp, base, len, offset, segflg, ioflg, cred, aresid)
                    158:        enum uio_rw rw;
                    159:        struct vnode *vp;
                    160:        caddr_t base;
                    161:        int len;
                    162:        off_t offset;
                    163:        enum uio_seg segflg;
                    164:        int ioflg;
                    165:        struct ucred *cred;
                    166:        int *aresid;
                    167: {
                    168:        struct uio auio;
                    169:        struct iovec aiov;
                    170:        int error;
                    171: 
                    172:        if ((ioflg & IO_NODELOCKED) == 0)
                    173:                VOP_LOCK(vp);
                    174:        auio.uio_iov = &aiov;
                    175:        auio.uio_iovcnt = 1;
                    176:        aiov.iov_base = base;
                    177:        aiov.iov_len = len;
                    178:        auio.uio_resid = len;
                    179:        auio.uio_offset = offset;
                    180:        auio.uio_segflg = segflg;
                    181:        auio.uio_rw = rw;
                    182:        if (rw == UIO_READ)
                    183:                error = VOP_READ(vp, &auio, ioflg, cred);
                    184:        else
                    185:                error = VOP_WRITE(vp, &auio, ioflg, cred);
                    186:        if (aresid)
                    187:                *aresid = auio.uio_resid;
                    188:        else
                    189:                if (auio.uio_resid && error == 0)
                    190:                        error = EIO;
                    191:        if ((ioflg & IO_NODELOCKED) == 0)
                    192:                VOP_UNLOCK(vp);
                    193:        return (error);
                    194: }
                    195: 
                    196: vn_read(fp, uio, cred)
                    197:        struct file *fp;
                    198:        struct uio *uio;
                    199:        struct ucred *cred;
                    200: {
                    201:        register struct vnode *vp = (struct vnode *)fp->f_data;
                    202:        int count, error;
                    203: 
                    204:        VOP_LOCK(vp);
                    205:        uio->uio_offset = fp->f_offset;
                    206:        count = uio->uio_resid;
                    207:        error = VOP_READ(vp, uio, (fp->f_flag & FNDELAY) ? IO_NDELAY : 0, cred);
                    208:        fp->f_offset += count - uio->uio_resid;
                    209:        VOP_UNLOCK(vp);
                    210:        return (error);
                    211: }
                    212: 
                    213: vn_write(fp, uio, cred)
                    214:        struct file *fp;
                    215:        struct uio *uio;
                    216:        struct ucred *cred;
                    217: {
                    218:        register struct vnode *vp = (struct vnode *)fp->f_data;
                    219:        int count, error, ioflag = 0;
                    220: 
                    221:        if (vp->v_type == VREG && (fp->f_flag & FAPPEND))
                    222:                ioflag |= IO_APPEND;
                    223:        if (fp->f_flag & FNDELAY)
                    224:                ioflag |= IO_NDELAY;
                    225:        VOP_LOCK(vp);
                    226:        uio->uio_offset = fp->f_offset;
                    227:        count = uio->uio_resid;
                    228:        error = VOP_WRITE(vp, uio, ioflag, cred);
                    229:        if (ioflag & IO_APPEND)
                    230:                fp->f_offset = uio->uio_offset;
                    231:        else
                    232:                fp->f_offset += count - uio->uio_resid;
                    233:        VOP_UNLOCK(vp);
                    234:        return (error);
                    235: }
                    236: 
                    237: /*
                    238:  * Get stat info for a vnode.
                    239:  */
                    240: vn_stat(vp, sb)
                    241:        struct vnode *vp;
                    242:        register struct stat *sb;
                    243: {
                    244:        struct vattr vattr;
                    245:        register struct vattr *vap;
                    246:        int error;
                    247:        u_short mode;
                    248: 
                    249:        vap = &vattr;
                    250:        error = VOP_GETATTR(vp, vap, u.u_cred);
                    251:        if (error)
                    252:                return (error);
                    253:        /*
                    254:         * Copy from vattr table
                    255:         */
                    256:        sb->st_dev = vap->va_fsid;
                    257:        sb->st_ino = vap->va_fileid;
                    258:        mode = vap->va_mode;
                    259:        switch (vp->v_type) {
                    260:        case VREG:
                    261:                mode |= S_IFREG;
                    262:                break;
                    263:        case VDIR:
                    264:                mode |= S_IFDIR;
                    265:                break;
                    266:        case VBLK:
                    267:                mode |= S_IFBLK;
                    268:                break;
                    269:        case VCHR:
                    270:                mode |= S_IFCHR;
                    271:                break;
                    272:        case VLNK:
                    273:                mode |= S_IFLNK;
                    274:                break;
                    275:        case VSOCK:
                    276:                mode |= S_IFSOCK;
                    277:                break;
                    278:        case VFIFO:
                    279:                mode |= S_IFIFO;
                    280:                break;
                    281:        default:
                    282:                return (EBADF);
                    283:        };
                    284:        sb->st_mode = mode;
                    285:        sb->st_nlink = vap->va_nlink;
                    286:        sb->st_uid = vap->va_uid;
                    287:        sb->st_gid = vap->va_gid;
                    288:        sb->st_rdev = vap->va_rdev;
                    289:        sb->st_size = vap->va_size;
                    290:        sb->st_atime = vap->va_atime.tv_sec;
                    291:        sb->st_spare1 = 0;
                    292:        sb->st_mtime = vap->va_mtime.tv_sec;
                    293:        sb->st_spare2 = 0;
                    294:        sb->st_ctime = vap->va_ctime.tv_sec;
                    295:        sb->st_spare3 = 0;
                    296:        sb->st_blksize = vap->va_blocksize;
                    297:        sb->st_flags = vap->va_flags;
                    298:        sb->st_gen = vap->va_gen;
                    299:        sb->st_blocks = vap->va_bytes / S_BLKSIZE;
                    300:        return (0);
                    301: }
                    302: 
                    303: /*
                    304:  * Vnode ioctl call
                    305:  */
                    306: vn_ioctl(fp, com, data)
                    307:        struct file *fp;
                    308:        int com;
                    309:        caddr_t data;
                    310: {
                    311:        register struct vnode *vp = ((struct vnode *)fp->f_data);
                    312:        struct vattr vattr;
                    313:        int error;
                    314: 
                    315:        switch (vp->v_type) {
                    316: 
                    317:        case VREG:
                    318:        case VDIR:
                    319:                if (com == FIONREAD) {
                    320:                        if (error = VOP_GETATTR(vp, &vattr, u.u_cred))
                    321:                                return (error);
                    322:                        *(off_t *)data = vattr.va_size - fp->f_offset;
                    323:                        return (0);
                    324:                }
                    325:                if (com == FIONBIO || com == FIOASYNC)  /* XXX */
                    326:                        return (0);                     /* XXX */
                    327:                /* fall into ... */
                    328: 
                    329:        default:
                    330:                return (ENOTTY);
                    331: 
                    332:        case VFIFO:
                    333:        case VCHR:
                    334:        case VBLK:
                    335:                error = VOP_IOCTL(vp, com, data, fp->f_flag, u.u_cred);
                    336:                if (error == 0 && com == TIOCSCTTY) {
                    337:                        u.u_procp->p_session->s_ttyvp = vp;
                    338:                        VREF(vp);
                    339:                }
                    340:                return (error);
                    341:        }
                    342: }
                    343: 
                    344: /*
                    345:  * Vnode select call
                    346:  */
                    347: vn_select(fp, which)
                    348:        struct file *fp;
                    349:        int which;
                    350: {
                    351:        return (VOP_SELECT(((struct vnode *)fp->f_data), which, fp->f_flag,
                    352:                u.u_cred));
                    353: }
                    354: 
                    355: /*
                    356:  * Vnode close call
                    357:  */
                    358: vn_close(fp)
                    359:        register struct file *fp;
                    360: {
                    361:        struct vnode *vp = ((struct vnode *)fp->f_data);
                    362:        int error;
                    363: 
                    364:        if (fp->f_flag & (FSHLOCK|FEXLOCK))
                    365:                vn_unlock(fp, FSHLOCK|FEXLOCK);
                    366:        /*
                    367:         * Must delete vnode reference from this file entry
                    368:         * before VOP_CLOSE, so that only other references
                    369:         * will prevent close.
                    370:         */
                    371:        fp->f_data = (caddr_t) 0;
                    372:        error = VOP_CLOSE(vp, fp->f_flag, u.u_cred);
                    373:        vrele(vp);
                    374:        return (error);
                    375: }
                    376: 
                    377: /*
                    378:  * Place an advisory lock on a vnode.
                    379:  * !! THIS IMPLIES THAT ALL STATEFUL FILE SERVERS WILL USE file table entries
                    380:  */
                    381: vn_lock(fp, cmd)
                    382:        register struct file *fp;
                    383:        int cmd;
                    384: {
                    385:        register int priority = PLOCK;
                    386:        register struct vnode *vp = (struct vnode *)fp->f_data;
                    387:        int error = 0;
                    388:        static char lockstr[] = "flock";
                    389: 
                    390:        if ((cmd & LOCK_EX) == 0)
                    391:                priority += 4;
                    392:        priority |= PCATCH;
                    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 (vp->v_flag & VEXLOCK) {
                    401:                /*
                    402:                 * If we're holding an exclusive
                    403:                 * lock, then release it.
                    404:                 */
                    405:                if (fp->f_flag & FEXLOCK) {
                    406:                        vn_unlock(fp, FEXLOCK);
                    407:                        continue;
                    408:                }
                    409:                if (cmd & LOCK_NB)
                    410:                        return (EWOULDBLOCK);
                    411:                vp->v_flag |= VLWAIT;
                    412:                if (error = tsleep((caddr_t)&vp->v_exlockc, priority,
                    413:                    lockstr, 0))
                    414:                        return (error);
                    415:        }
                    416:        if (error = 0 && (cmd & LOCK_EX) && (vp->v_flag & VSHLOCK)) {
                    417:                /*
                    418:                 * Must wait for any shared locks to finish
                    419:                 * before we try to apply a exclusive lock.
                    420:                 *
                    421:                 * If we're holding a shared
                    422:                 * lock, then release it.
                    423:                 */
                    424:                if (fp->f_flag & FSHLOCK) {
                    425:                        vn_unlock(fp, FSHLOCK);
                    426:                        goto again;
                    427:                }
                    428:                if (cmd & LOCK_NB)
                    429:                        return (EWOULDBLOCK);
                    430:                vp->v_flag |= VLWAIT;
                    431:                if (error = tsleep((caddr_t)&vp->v_shlockc, PLOCK | PCATCH,
                    432:                    lockstr, 0) == 0)
                    433:                        return (error);
                    434:        }
                    435:        if (fp->f_flag & FEXLOCK)
                    436:                panic("vn_lock");
                    437:        if (cmd & LOCK_EX) {
                    438:                cmd &= ~LOCK_SH;
                    439:                vp->v_exlockc++;
                    440:                vp->v_flag |= VEXLOCK;
                    441:                fp->f_flag |= FEXLOCK;
                    442:        }
                    443:        if ((cmd & LOCK_SH) && (fp->f_flag & FSHLOCK) == 0) {
                    444:                vp->v_shlockc++;
                    445:                vp->v_flag |= VSHLOCK;
                    446:                fp->f_flag |= FSHLOCK;
                    447:        }
                    448:        return (0);
                    449: }
                    450: 
                    451: /*
                    452:  * Unlock a file.
                    453:  */
                    454: vn_unlock(fp, kind)
                    455:        register struct file *fp;
                    456:        int kind;
                    457: {
                    458:        register struct vnode *vp = (struct vnode *)fp->f_data;
                    459:        int flags;
                    460: 
                    461:        kind &= fp->f_flag;
                    462:        if (vp == NULL || kind == 0)
                    463:                return;
                    464:        flags = vp->v_flag;
                    465:        if (kind & FSHLOCK) {
                    466:                if ((flags & VSHLOCK) == 0)
                    467:                        panic("vn_unlock: SHLOCK");
                    468:                if (--vp->v_shlockc == 0) {
                    469:                        vp->v_flag &= ~VSHLOCK;
                    470:                        if (flags & VLWAIT)
                    471:                                wakeup((caddr_t)&vp->v_shlockc);
                    472:                }
                    473:                fp->f_flag &= ~FSHLOCK;
                    474:        }
                    475:        if (kind & FEXLOCK) {
                    476:                if ((flags & VEXLOCK) == 0)
                    477:                        panic("vn_unlock: EXLOCK");
                    478:                if (--vp->v_exlockc == 0) {
                    479:                        vp->v_flag &= ~(VEXLOCK|VLWAIT);
                    480:                        if (flags & VLWAIT)
                    481:                                wakeup((caddr_t)&vp->v_exlockc);
                    482:                }
                    483:                fp->f_flag &= ~FEXLOCK;
                    484:        }
                    485: }
                    486: 
                    487: /*
                    488:  * vn_fhtovp() - convert a fh to a vnode ptr (optionally locked)
                    489:  *     - look up fsid in mount list (if not found ret error)
                    490:  *     - get vp by calling VFS_FHTOVP() macro
                    491:  *     - if lockflag lock it with VOP_LOCK()
                    492:  */
                    493: vn_fhtovp(fhp, lockflag, vpp)
                    494:        fhandle_t *fhp;
                    495:        int lockflag;
                    496:        struct vnode **vpp;
                    497: {
                    498:        register struct mount *mp;
                    499: 
                    500:        if ((mp = getvfs(&fhp->fh_fsid)) == NULL)
                    501:                return (ESTALE);
                    502:        if (VFS_FHTOVP(mp, &fhp->fh_fid, vpp))
                    503:                return (ESTALE);
                    504:        if (!lockflag)
                    505:                VOP_UNLOCK(*vpp);
                    506:        return (0);
                    507: }
                    508: 
                    509: /*
                    510:  * Noop
                    511:  */
                    512: vfs_noop()
                    513: {
                    514: 
                    515:        return (ENXIO);
                    516: }
                    517: 
                    518: /*
                    519:  * Null op
                    520:  */
                    521: vfs_nullop()
                    522: {
                    523: 
                    524:        return (0);
                    525: }

unix.superglobalmegacorp.com

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