[BACK]Return to ext2fs_vnops.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / ufs / ext2fs

Annotation of src/sys/ufs/ext2fs/ext2fs_vnops.c, Revision 1.42

1.42    ! jdolecek    1: /*     $NetBSD: ext2fs_vnops.c,v 1.41 2002/09/22 19:32:56 jdolecek Exp $       */
1.1       bouyer      2:
                      3: /*
                      4:  * Copyright (c) 1997 Manuel Bouyer.
                      5:  * Copyright (c) 1982, 1986, 1989, 1993
                      6:  *     The Regents of the University of California.  All rights reserved.
                      7:  * (c) UNIX System Laboratories, Inc.
                      8:  * All or some portions of this file are derived from material licensed
                      9:  * to the University of California by American Telephone and Telegraph
                     10:  * Co. or Unix System Laboratories, Inc. and are reproduced herein with
                     11:  * the permission of UNIX System Laboratories, Inc.
                     12:  *
                     13:  * Redistribution and use in source and binary forms, with or without
                     14:  * modification, are permitted provided that the following conditions
                     15:  * are met:
                     16:  * 1. Redistributions of source code must retain the above copyright
                     17:  *    notice, this list of conditions and the following disclaimer.
                     18:  * 2. Redistributions in binary form must reproduce the above copyright
                     19:  *    notice, this list of conditions and the following disclaimer in the
                     20:  *    documentation and/or other materials provided with the distribution.
                     21:  * 3. All advertising materials mentioning features or use of this software
                     22:  *    must display the following acknowledgement:
                     23:  *     This product includes software developed by the University of
                     24:  *     California, Berkeley and its contributors.
                     25:  * 4. Neither the name of the University nor the names of its contributors
                     26:  *    may be used to endorse or promote products derived from this software
                     27:  *    without specific prior written permission.
                     28:  *
                     29:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     30:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     31:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     32:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     33:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     34:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     35:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     36:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     37:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     38:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     39:  * SUCH DAMAGE.
                     40:  *
                     41:  *     @(#)ufs_vnops.c 8.14 (Berkeley) 10/26/94
                     42:  * Modified for ext2fs by Manuel Bouyer.
                     43:  */
1.40      lukem      44:
                     45: #include <sys/cdefs.h>
1.42    ! jdolecek   46: __KERNEL_RCSID(0, "$NetBSD: ext2fs_vnops.c,v 1.41 2002/09/22 19:32:56 jdolecek Exp $");
1.7       mrg        47:
1.1       bouyer     48: #include <sys/param.h>
                     49: #include <sys/systm.h>
                     50: #include <sys/resourcevar.h>
                     51: #include <sys/kernel.h>
                     52: #include <sys/file.h>
                     53: #include <sys/stat.h>
                     54: #include <sys/buf.h>
                     55: #include <sys/proc.h>
                     56: #include <sys/mount.h>
                     57: #include <sys/namei.h>
                     58: #include <sys/vnode.h>
                     59: #include <sys/lockf.h>
                     60: #include <sys/malloc.h>
1.14      thorpej    61: #include <sys/pool.h>
1.1       bouyer     62: #include <sys/signalvar.h>
                     63:
                     64: #include <miscfs/fifofs/fifo.h>
                     65: #include <miscfs/genfs/genfs.h>
                     66: #include <miscfs/specfs/specdev.h>
                     67:
                     68: #include <ufs/ufs/inode.h>
                     69: #include <ufs/ufs/ufs_extern.h>
                     70: #include <ufs/ufs/ufsmount.h>
                     71:
                     72: #include <ufs/ext2fs/ext2fs.h>
                     73: #include <ufs/ext2fs/ext2fs_extern.h>
                     74: #include <ufs/ext2fs/ext2fs_dir.h>
                     75:
1.32      tsutsui    76: extern int prtactive;
1.1       bouyer     77:
                     78: static int ext2fs_chmod
                     79:        __P((struct vnode *, int, struct ucred *, struct proc *));
                     80: static int ext2fs_chown
                     81:        __P((struct vnode *, uid_t, gid_t, struct ucred *, struct proc *));
                     82:
                     83: union _qcvt {
                     84:        int64_t qcvt;
                     85:        int32_t val[2];
                     86: };
                     87: #define SETHIGH(q, h) { \
                     88:        union _qcvt tmp; \
                     89:        tmp.qcvt = (q); \
                     90:        tmp.val[_QUAD_HIGHWORD] = (h); \
                     91:        (q) = tmp.qcvt; \
                     92: }
                     93: #define SETLOW(q, l) { \
                     94:        union _qcvt tmp; \
                     95:        tmp.qcvt = (q); \
                     96:        tmp.val[_QUAD_LOWWORD] = (l); \
                     97:        (q) = tmp.qcvt; \
                     98: }
                     99:
                    100: /*
                    101:  * Create a regular file
                    102:  */
                    103: int
                    104: ext2fs_create(v)
                    105:        void *v;
                    106: {
                    107:        struct vop_create_args /* {
                    108:                struct vnode *a_dvp;
                    109:                struct vnode **a_vpp;
                    110:                struct componentname *a_cnp;
                    111:                struct vattr *a_vap;
                    112:        } */ *ap = v;
1.42    ! jdolecek  113:        int     error;
        !           114:
        !           115:        error =
        !           116:            ext2fs_makeinode(MAKEIMODE(ap->a_vap->va_type, ap->a_vap->va_mode),
        !           117:                             ap->a_dvp, ap->a_vpp, ap->a_cnp);
        !           118:
        !           119:        if (error)
        !           120:                return (error);
        !           121:        VN_KNOTE(ap->a_dvp, NOTE_WRITE);
        !           122:        return (0);
1.1       bouyer    123: }
                    124:
                    125: /*
                    126:  * Mknod vnode call
                    127:  */
                    128: /* ARGSUSED */
                    129: int
                    130: ext2fs_mknod(v)
                    131:        void *v;
                    132: {
                    133:        struct vop_mknod_args /* {
                    134:                struct vnode *a_dvp;
                    135:                struct vnode **a_vpp;
                    136:                struct componentname *a_cnp;
                    137:                struct vattr *a_vap;
                    138:        } */ *ap = v;
1.25      augustss  139:        struct vattr *vap = ap->a_vap;
                    140:        struct vnode **vpp = ap->a_vpp;
                    141:        struct inode *ip;
1.1       bouyer    142:        int error;
1.34      assar     143:        struct mount    *mp;
                    144:        ino_t           ino;
1.1       bouyer    145:
1.8       fvdl      146:        if ((error = ext2fs_makeinode(MAKEIMODE(vap->va_type, vap->va_mode),
                    147:                    ap->a_dvp, vpp, ap->a_cnp)) != 0)
1.1       bouyer    148:                return (error);
1.42    ! jdolecek  149:        VN_KNOTE(ap->a_dvp, NOTE_WRITE);
1.1       bouyer    150:        ip = VTOI(*vpp);
1.34      assar     151:        mp  = (*vpp)->v_mount;
                    152:        ino = ip->i_number;
1.1       bouyer    153:        ip->i_flag |= IN_ACCESS | IN_CHANGE | IN_UPDATE;
                    154:        if (vap->va_rdev != VNOVAL) {
                    155:                /*
                    156:                 * Want to be able to use this to make badblock
                    157:                 * inodes, so don't truncate the dev number.
                    158:                 */
1.4       bouyer    159:                ip->i_din.e2fs_din.e2di_rdev = h2fs32(vap->va_rdev);
1.1       bouyer    160:        }
                    161:        /*
                    162:         * Remove inode so that it will be reloaded by VFS_VGET and
                    163:         * checked to see if it is an alias of an existing entry in
                    164:         * the inode cache.
                    165:         */
                    166:        vput(*vpp);
                    167:        (*vpp)->v_type = VNON;
                    168:        vgone(*vpp);
1.34      assar     169:        error = VFS_VGET(mp, ino, vpp);
                    170:        if (error != 0) {
                    171:                *vpp = NULL;
                    172:                return (error);
                    173:        }
1.1       bouyer    174:        return (0);
                    175: }
                    176:
                    177: /*
                    178:  * Open called.
                    179:  *
                    180:  * Just check the APPEND flag.
                    181:  */
                    182: /* ARGSUSED */
                    183: int
                    184: ext2fs_open(v)
                    185:        void *v;
                    186: {
                    187:        struct vop_open_args /* {
                    188:                struct vnode *a_vp;
                    189:                int  a_mode;
                    190:                struct ucred *a_cred;
                    191:                struct proc *a_p;
                    192:        } */ *ap = v;
                    193:
                    194:        /*
                    195:         * Files marked append-only must be opened for appending.
                    196:         */
                    197:        if ((VTOI(ap->a_vp)->i_e2fs_flags & EXT2_APPEND) &&
                    198:                (ap->a_mode & (FWRITE | O_APPEND)) == FWRITE)
                    199:                return (EPERM);
                    200:        return (0);
                    201: }
                    202:
                    203: int
                    204: ext2fs_access(v)
                    205:        void *v;
                    206: {
                    207:        struct vop_access_args /* {
                    208:                struct vnode *a_vp;
                    209:                int  a_mode;
                    210:                struct ucred *a_cred;
                    211:                struct proc *a_p;
                    212:        } */ *ap = v;
1.8       fvdl      213:        struct vnode *vp = ap->a_vp;
                    214:        struct inode *ip = VTOI(vp);
1.1       bouyer    215:        mode_t mode = ap->a_mode;
                    216:
1.8       fvdl      217:        /*
                    218:         * Disallow write attempts on read-only file systems;
                    219:         * unless the file is a socket, fifo, or a block or
                    220:         * character device resident on the file system.
                    221:         */
                    222:        if (mode & VWRITE) {
                    223:                switch (vp->v_type) {
                    224:                case VDIR:
                    225:                case VLNK:
                    226:                case VREG:
                    227:                        if (vp->v_mount->mnt_flag & MNT_RDONLY)
                    228:                                return (EROFS);
                    229:                        break;
                    230:                default:
                    231:                        break;
                    232:                }
1.1       bouyer    233:        }
                    234:
                    235:        /* If immutable bit set, nobody gets to write it. */
                    236:        if ((mode & VWRITE) && (ip->i_e2fs_flags & EXT2_IMMUTABLE))
                    237:                return (EPERM);
                    238:
                    239:        return (vaccess(vp->v_type, ip->i_e2fs_mode & ALLPERMS,
                    240:                        ip->i_e2fs_uid, ip->i_e2fs_gid, mode, ap->a_cred));
                    241: }
                    242:
                    243: /* ARGSUSED */
                    244: int
                    245: ext2fs_getattr(v)
                    246:        void *v;
                    247: {
                    248:        struct vop_getattr_args /* {
                    249:                struct vnode *a_vp;
                    250:                struct vattr *a_vap;
                    251:                struct ucred *a_cred;
                    252:                struct proc *a_p;
                    253:        } */ *ap = v;
1.25      augustss  254:        struct vnode *vp = ap->a_vp;
                    255:        struct inode *ip = VTOI(vp);
                    256:        struct vattr *vap = ap->a_vap;
1.1       bouyer    257:        struct timespec ts;
                    258:
                    259:        TIMEVAL_TO_TIMESPEC(&time, &ts);
                    260:        EXT2FS_ITIMES(ip, &ts, &ts, &ts);
                    261:        /*
                    262:         * Copy from inode table
                    263:         */
                    264:        vap->va_fsid = ip->i_dev;
                    265:        vap->va_fileid = ip->i_number;
                    266:        vap->va_mode = ip->i_e2fs_mode & ALLPERMS;
                    267:        vap->va_nlink = ip->i_e2fs_nlink;
                    268:        vap->va_uid = ip->i_e2fs_uid;
                    269:        vap->va_gid = ip->i_e2fs_gid;
1.4       bouyer    270:        vap->va_rdev = (dev_t)fs2h32(ip->i_din.e2fs_din.e2di_rdev);
1.37      chs       271:        vap->va_size = vp->v_size;
1.1       bouyer    272:        vap->va_atime.tv_sec = ip->i_e2fs_atime;
                    273:        vap->va_atime.tv_nsec = 0;
                    274:        vap->va_mtime.tv_sec = ip->i_e2fs_mtime;
                    275:        vap->va_mtime.tv_nsec = 0;
                    276:        vap->va_ctime.tv_sec = ip->i_e2fs_ctime;
                    277:        vap->va_ctime.tv_nsec = 0;
                    278: #ifdef EXT2FS_SYSTEM_FLAGS
                    279:        vap->va_flags = (ip->i_e2fs_flags & EXT2_APPEND) ? SF_APPEND : 0;
                    280:        vap->va_flags |= (ip->i_e2fs_flags & EXT2_IMMUTABLE) ? SF_IMMUTABLE : 0;
                    281: #else
                    282:        vap->va_flags = (ip->i_e2fs_flags & EXT2_APPEND) ? UF_APPEND : 0;
                    283:        vap->va_flags |= (ip->i_e2fs_flags & EXT2_IMMUTABLE) ? UF_IMMUTABLE : 0;
                    284: #endif
                    285:        vap->va_gen = ip->i_e2fs_gen;
                    286:        /* this doesn't belong here */
                    287:        if (vp->v_type == VBLK)
                    288:                vap->va_blocksize = BLKDEV_IOSIZE;
                    289:        else if (vp->v_type == VCHR)
                    290:                vap->va_blocksize = MAXBSIZE;
                    291:        else
                    292:                vap->va_blocksize = vp->v_mount->mnt_stat.f_iosize;
1.8       fvdl      293:        vap->va_bytes = dbtob((u_quad_t)ip->i_e2fs_nblock);
1.1       bouyer    294:        vap->va_type = vp->v_type;
                    295:        vap->va_filerev = ip->i_modrev;
                    296:        return (0);
                    297: }
                    298:
                    299: /*
                    300:  * Set attribute vnode op. called from several syscalls
                    301:  */
                    302: int
                    303: ext2fs_setattr(v)
                    304:        void *v;
                    305: {
                    306:        struct vop_setattr_args /* {
                    307:                struct vnode *a_vp;
                    308:                struct vattr *a_vap;
                    309:                struct ucred *a_cred;
                    310:                struct proc *a_p;
                    311:        } */ *ap = v;
1.8       fvdl      312:        struct vattr *vap = ap->a_vap;
                    313:        struct vnode *vp = ap->a_vp;
                    314:        struct inode *ip = VTOI(vp);
                    315:        struct ucred *cred = ap->a_cred;
                    316:        struct proc *p = ap->a_p;
1.1       bouyer    317:        int error;
                    318:
                    319:        /*
                    320:         * Check for unsettable attributes.
                    321:         */
1.5       christos  322:        if ((vap->va_type != VNON) || (vap->va_nlink != (nlink_t)VNOVAL) ||
1.24      thorpej   323:            (vap->va_fsid != VNOVAL) || (vap->va_fileid != VNOVAL) ||
                    324:            (vap->va_blocksize != VNOVAL) || (vap->va_rdev != VNOVAL) ||
                    325:            ((int)vap->va_bytes != VNOVAL) || (vap->va_gen != VNOVAL)) {
1.1       bouyer    326:                return (EINVAL);
                    327:        }
                    328:        if (vap->va_flags != VNOVAL) {
1.8       fvdl      329:                if (vp->v_mount->mnt_flag & MNT_RDONLY)
                    330:                        return (EROFS);
1.1       bouyer    331:                if (cred->cr_uid != ip->i_e2fs_uid &&
                    332:                        (error = suser(cred, &p->p_acflag)))
                    333:                        return (error);
                    334: #ifdef EXT2FS_SYSTEM_FLAGS
                    335:                if (cred->cr_uid == 0) {
1.24      thorpej   336:                        if ((ip->i_e2fs_flags &
                    337:                            (EXT2_APPEND | EXT2_IMMUTABLE)) && securelevel > 0)
1.1       bouyer    338:                                return (EPERM);
                    339:                        ip->i_e2fs_flags &= ~(EXT2_APPEND | EXT2_IMMUTABLE);
1.24      thorpej   340:                        ip->i_e2fs_flags |=
                    341:                            (vap->va_flags & SF_APPEND) ?  EXT2_APPEND : 0 |
                    342:                            (vap->va_flags & SF_IMMUTABLE) ? EXT2_IMMUTABLE : 0;
                    343:                } else
1.1       bouyer    344:                        return (EPERM);
                    345: #else
                    346:                ip->i_e2fs_flags &= ~(EXT2_APPEND | EXT2_IMMUTABLE);
1.24      thorpej   347:                ip->i_e2fs_flags |=
                    348:                    (vap->va_flags & UF_APPEND) ? EXT2_APPEND : 0 |
                    349:                    (vap->va_flags & UF_IMMUTABLE) ? EXT2_IMMUTABLE : 0;
1.1       bouyer    350: #endif
                    351:                ip->i_flag |= IN_CHANGE;
                    352:                if (vap->va_flags & (IMMUTABLE | APPEND))
                    353:                        return (0);
                    354:        }
                    355:        if (ip->i_e2fs_flags & (EXT2_APPEND | EXT2_IMMUTABLE))
                    356:                return (EPERM);
                    357:        /*
                    358:         * Go through the fields and update iff not VNOVAL.
                    359:         */
                    360:        if (vap->va_uid != (uid_t)VNOVAL || vap->va_gid != (gid_t)VNOVAL) {
1.8       fvdl      361:                if (vp->v_mount->mnt_flag & MNT_RDONLY)
                    362:                        return (EROFS);
1.1       bouyer    363:                error = ext2fs_chown(vp, vap->va_uid, vap->va_gid, cred, p);
                    364:                if (error)
                    365:                        return (error);
                    366:        }
                    367:        if (vap->va_size != VNOVAL) {
1.8       fvdl      368:                /*
                    369:                 * Disallow write attempts on read-only file systems;
                    370:                 * unless the file is a socket, fifo, or a block or
                    371:                 * character device resident on the file system.
                    372:                 */
                    373:                switch (vp->v_type) {
                    374:                case VDIR:
1.1       bouyer    375:                        return (EISDIR);
1.8       fvdl      376:                case VLNK:
                    377:                case VREG:
                    378:                        if (vp->v_mount->mnt_flag & MNT_RDONLY)
                    379:                                return (EROFS);
                    380:                default:
                    381:                        break;
                    382:                }
1.1       bouyer    383:                error = VOP_TRUNCATE(vp, vap->va_size, 0, cred, p);
                    384:                if (error)
                    385:                        return (error);
                    386:        }
                    387:        ip = VTOI(vp);
                    388:        if (vap->va_atime.tv_sec != VNOVAL || vap->va_mtime.tv_sec != VNOVAL) {
1.8       fvdl      389:                if (vp->v_mount->mnt_flag & MNT_RDONLY)
                    390:                        return (EROFS);
1.1       bouyer    391:                if (cred->cr_uid != ip->i_e2fs_uid &&
                    392:                        (error = suser(cred, &p->p_acflag)) &&
                    393:                        ((vap->va_vaflags & VA_UTIMES_NULL) == 0 ||
                    394:                        (error = VOP_ACCESS(vp, VWRITE, cred, p))))
                    395:                        return (error);
                    396:                if (vap->va_atime.tv_sec != VNOVAL)
                    397:                        if (!(vp->v_mount->mnt_flag & MNT_NOATIME))
                    398:                                ip->i_flag |= IN_ACCESS;
                    399:                if (vap->va_mtime.tv_sec != VNOVAL)
                    400:                        ip->i_flag |= IN_CHANGE | IN_UPDATE;
1.26      perseant  401:                error = VOP_UPDATE(vp, &vap->va_atime, &vap->va_mtime,
                    402:                        UPDATE_WAIT);
1.1       bouyer    403:                if (error)
                    404:                        return (error);
                    405:        }
                    406:        error = 0;
1.8       fvdl      407:        if (vap->va_mode != (mode_t)VNOVAL) {
                    408:                if (vp->v_mount->mnt_flag & MNT_RDONLY)
                    409:                        return (EROFS);
1.1       bouyer    410:                error = ext2fs_chmod(vp, (int)vap->va_mode, cred, p);
1.8       fvdl      411:        }
1.42    ! jdolecek  412:        VN_KNOTE(vp, NOTE_ATTRIB);
1.1       bouyer    413:        return (error);
                    414: }
                    415:
                    416: /*
                    417:  * Change the mode on a file.
                    418:  * Inode must be locked before calling.
                    419:  */
                    420: static int
                    421: ext2fs_chmod(vp, mode, cred, p)
1.25      augustss  422:        struct vnode *vp;
                    423:        int mode;
                    424:        struct ucred *cred;
1.1       bouyer    425:        struct proc *p;
                    426: {
1.25      augustss  427:        struct inode *ip = VTOI(vp);
1.1       bouyer    428:        int error;
                    429:
                    430:        if (cred->cr_uid != ip->i_e2fs_uid &&
                    431:                (error = suser(cred, &p->p_acflag)))
                    432:                return (error);
                    433:        if (cred->cr_uid) {
                    434:                if (vp->v_type != VDIR && (mode & S_ISTXT))
                    435:                        return (EFTYPE);
                    436:                if (!groupmember(ip->i_e2fs_gid, cred) && (mode & ISGID))
                    437:                        return (EPERM);
                    438:        }
                    439:        ip->i_e2fs_mode &= ~ALLPERMS;
                    440:        ip->i_e2fs_mode |= (mode & ALLPERMS);
                    441:        ip->i_flag |= IN_CHANGE;
                    442:        return (0);
                    443: }
                    444:
                    445: /*
                    446:  * Perform chown operation on inode ip;
                    447:  * inode must be locked prior to call.
                    448:  */
                    449: static int
                    450: ext2fs_chown(vp, uid, gid, cred, p)
1.25      augustss  451:        struct vnode *vp;
1.1       bouyer    452:        uid_t uid;
                    453:        gid_t gid;
                    454:        struct ucred *cred;
                    455:        struct proc *p;
                    456: {
1.25      augustss  457:        struct inode *ip = VTOI(vp);
1.1       bouyer    458:        uid_t ouid;
                    459:        gid_t ogid;
                    460:        int error = 0;
                    461:
                    462:        if (uid == (uid_t)VNOVAL)
                    463:                uid = ip->i_e2fs_uid;
                    464:        if (gid == (gid_t)VNOVAL)
                    465:                gid = ip->i_e2fs_gid;
                    466:        /*
                    467:         * If we don't own the file, are trying to change the owner
                    468:         * of the file, or are not a member of the target group,
                    469:         * the caller must be superuser or the call fails.
                    470:         */
                    471:        if ((cred->cr_uid != ip->i_e2fs_uid || uid != ip->i_e2fs_uid ||
                    472:                (gid != ip->i_e2fs_gid && !groupmember((gid_t)gid, cred))) &&
                    473:                (error = suser(cred, &p->p_acflag)))
                    474:                return (error);
                    475:        ogid = ip->i_e2fs_gid;
                    476:        ouid = ip->i_e2fs_uid;
                    477:
                    478:        ip->i_e2fs_gid = gid;
                    479:        ip->i_e2fs_uid = uid;
                    480:        if (ouid != uid || ogid != gid)
                    481:                ip->i_flag |= IN_CHANGE;
                    482:        if (ouid != uid && cred->cr_uid != 0)
                    483:                ip->i_e2fs_mode &= ~ISUID;
                    484:        if (ogid != gid && cred->cr_uid != 0)
                    485:                ip->i_e2fs_mode &= ~ISGID;
                    486:        return (0);
                    487: }
                    488:
                    489: int
                    490: ext2fs_remove(v)
                    491:        void *v;
                    492: {
                    493:        struct vop_remove_args /* {
                    494:                struct vnode *a_dvp;
                    495:                struct vnode *a_vp;
                    496:                struct componentname *a_cnp;
                    497:        } */ *ap = v;
1.8       fvdl      498:        struct inode *ip;
                    499:        struct vnode *vp = ap->a_vp;
                    500:        struct vnode *dvp = ap->a_dvp;
1.1       bouyer    501:        int error;
                    502:
                    503:        ip = VTOI(vp);
1.2       fvdl      504:        if (vp->v_type == VDIR ||
                    505:                (ip->i_e2fs_flags & (EXT2_IMMUTABLE | EXT2_APPEND)) ||
1.1       bouyer    506:                (VTOI(dvp)->i_e2fs_flags & EXT2_APPEND)) {
                    507:                error = EPERM;
                    508:                goto out;
                    509:        }
                    510:        error = ext2fs_dirremove(dvp, ap->a_cnp);
                    511:        if (error == 0) {
                    512:                ip->i_e2fs_nlink--;
                    513:                ip->i_flag |= IN_CHANGE;
                    514:        }
                    515: out:
1.42    ! jdolecek  516:        VN_KNOTE(vp, NOTE_DELETE);
        !           517:        VN_KNOTE(dvp, NOTE_WRITE);
1.1       bouyer    518:        if (dvp == vp)
                    519:                vrele(vp);
                    520:        else
                    521:                vput(vp);
                    522:        vput(dvp);
                    523:        return (error);
                    524: }
                    525:
                    526: /*
                    527:  * link vnode call
                    528:  */
                    529: int
                    530: ext2fs_link(v)
                    531:        void *v;
                    532: {
                    533:        struct vop_link_args /* {
                    534:                struct vnode *a_dvp;
                    535:                struct vnode *a_vp;
                    536:                struct componentname *a_cnp;
                    537:        } */ *ap = v;
1.8       fvdl      538:        struct vnode *dvp = ap->a_dvp;
                    539:        struct vnode *vp = ap->a_vp;
                    540:        struct componentname *cnp = ap->a_cnp;
                    541:        struct inode *ip;
1.1       bouyer    542:        int error;
                    543:
                    544: #ifdef DIAGNOSTIC
                    545:        if ((cnp->cn_flags & HASBUF) == 0)
                    546:                panic("ext2fs_link: no name");
                    547: #endif
                    548:        if (vp->v_type == VDIR) {
                    549:                VOP_ABORTOP(dvp, cnp);
                    550:                error = EISDIR;
                    551:                goto out2;
                    552:        }
                    553:        if (dvp->v_mount != vp->v_mount) {
                    554:                VOP_ABORTOP(dvp, cnp);
                    555:                error = EXDEV;
                    556:                goto out2;
                    557:        }
1.8       fvdl      558:        if (dvp != vp && (error = vn_lock(vp, LK_EXCLUSIVE))) {
1.1       bouyer    559:                VOP_ABORTOP(dvp, cnp);
                    560:                goto out2;
                    561:        }
                    562:        ip = VTOI(vp);
                    563:        if ((nlink_t)ip->i_e2fs_nlink >= LINK_MAX) {
                    564:                VOP_ABORTOP(dvp, cnp);
                    565:                error = EMLINK;
                    566:                goto out1;
                    567:        }
                    568:        if (ip->i_e2fs_flags & (EXT2_IMMUTABLE | EXT2_APPEND)) {
                    569:                VOP_ABORTOP(dvp, cnp);
                    570:                error = EPERM;
                    571:                goto out1;
                    572:        }
                    573:        ip->i_e2fs_nlink++;
                    574:        ip->i_flag |= IN_CHANGE;
1.26      perseant  575:        error = VOP_UPDATE(vp, NULL, NULL, UPDATE_WAIT);
1.1       bouyer    576:        if (!error)
                    577:                error = ext2fs_direnter(ip, dvp, cnp);
                    578:        if (error) {
                    579:                ip->i_e2fs_nlink--;
                    580:                ip->i_flag |= IN_CHANGE;
                    581:        }
1.29      thorpej   582:        PNBUF_PUT(cnp->cn_pnbuf);
1.1       bouyer    583: out1:
                    584:        if (dvp != vp)
1.8       fvdl      585:                VOP_UNLOCK(vp, 0);
1.1       bouyer    586: out2:
1.42    ! jdolecek  587:        VN_KNOTE(vp, NOTE_LINK);
        !           588:        VN_KNOTE(dvp, NOTE_WRITE);
1.1       bouyer    589:        vput(dvp);
                    590:        return (error);
                    591: }
                    592:
                    593: /*
                    594:  * Rename system call.
                    595:  *     rename("foo", "bar");
                    596:  * is essentially
                    597:  *     unlink("bar");
                    598:  *     link("foo", "bar");
                    599:  *     unlink("foo");
                    600:  * but ``atomically''.  Can't do full commit without saving state in the
                    601:  * inode on disk which isn't feasible at this time.  Best we can do is
                    602:  * always guarantee the target exists.
                    603:  *
                    604:  * Basic algorithm is:
                    605:  *
                    606:  * 1) Bump link count on source while we're linking it to the
                    607:  *    target.  This also ensure the inode won't be deleted out
                    608:  *    from underneath us while we work (it may be truncated by
                    609:  *    a concurrent `trunc' or `open' for creation).
                    610:  * 2) Link source to destination.  If destination already exists,
                    611:  *    delete it first.
                    612:  * 3) Unlink source reference to inode if still around. If a
                    613:  *    directory was moved and the parent of the destination
                    614:  *    is different from the source, patch the ".." entry in the
                    615:  *    directory.
                    616:  */
                    617: int
                    618: ext2fs_rename(v)
                    619:        void *v;
                    620: {
                    621:        struct vop_rename_args  /* {
                    622:                struct vnode *a_fdvp;
                    623:                struct vnode *a_fvp;
                    624:                struct componentname *a_fcnp;
                    625:                struct vnode *a_tdvp;
                    626:                struct vnode *a_tvp;
                    627:                struct componentname *a_tcnp;
                    628:        } */ *ap = v;
                    629:        struct vnode *tvp = ap->a_tvp;
1.25      augustss  630:        struct vnode *tdvp = ap->a_tdvp;
1.1       bouyer    631:        struct vnode *fvp = ap->a_fvp;
1.8       fvdl      632:        struct vnode *fdvp = ap->a_fdvp;
                    633:        struct componentname *tcnp = ap->a_tcnp;
                    634:        struct componentname *fcnp = ap->a_fcnp;
                    635:        struct inode *ip, *xp, *dp;
1.1       bouyer    636:        struct ext2fs_dirtemplate dirbuf;
                    637:        int doingdirectory = 0, oldparent = 0, newparent = 0;
                    638:        int error = 0;
                    639:        u_char namlen;
                    640:
                    641: #ifdef DIAGNOSTIC
                    642:        if ((tcnp->cn_flags & HASBUF) == 0 ||
                    643:            (fcnp->cn_flags & HASBUF) == 0)
                    644:                panic("ext2fs_rename: no name");
                    645: #endif
                    646:        /*
                    647:         * Check for cross-device rename.
                    648:         */
                    649:        if ((fvp->v_mount != tdvp->v_mount) ||
                    650:            (tvp && (fvp->v_mount != tvp->v_mount))) {
                    651:                error = EXDEV;
                    652: abortit:
                    653:                VOP_ABORTOP(tdvp, tcnp); /* XXX, why not in NFS? */
                    654:                if (tdvp == tvp)
                    655:                        vrele(tdvp);
                    656:                else
                    657:                        vput(tdvp);
                    658:                if (tvp)
                    659:                        vput(tvp);
                    660:                VOP_ABORTOP(fdvp, fcnp); /* XXX, why not in NFS? */
                    661:                vrele(fdvp);
                    662:                vrele(fvp);
                    663:                return (error);
                    664:        }
                    665:
                    666:        /*
                    667:         * Check if just deleting a link name.
                    668:         */
                    669:        if (tvp && ((VTOI(tvp)->i_e2fs_flags & (EXT2_IMMUTABLE | EXT2_APPEND)) ||
                    670:            (VTOI(tdvp)->i_e2fs_flags & EXT2_APPEND))) {
                    671:                error = EPERM;
                    672:                goto abortit;
                    673:        }
                    674:        if (fvp == tvp) {
                    675:                if (fvp->v_type == VDIR) {
                    676:                        error = EINVAL;
                    677:                        goto abortit;
                    678:                }
                    679:
                    680:                /* Release destination completely. */
                    681:                VOP_ABORTOP(tdvp, tcnp);
                    682:                vput(tdvp);
                    683:                vput(tvp);
                    684:
                    685:                /* Delete source. */
                    686:                vrele(fdvp);
                    687:                vrele(fvp);
                    688:                fcnp->cn_flags &= ~MODMASK;
                    689:                fcnp->cn_flags |= LOCKPARENT | LOCKLEAF;
                    690:                if ((fcnp->cn_flags & SAVESTART) == 0)
                    691:                        panic("ext2fs_rename: lost from startdir");
                    692:                fcnp->cn_nameiop = DELETE;
                    693:                (void) relookup(fdvp, &fvp, fcnp);
                    694:                return (VOP_REMOVE(fdvp, fvp, fcnp));
                    695:        }
1.8       fvdl      696:        if ((error = vn_lock(fvp, LK_EXCLUSIVE)) != 0)
1.1       bouyer    697:                goto abortit;
                    698:        dp = VTOI(fdvp);
                    699:        ip = VTOI(fvp);
1.17      mrg       700:        if ((nlink_t) ip->i_e2fs_nlink >= LINK_MAX) {
                    701:                VOP_UNLOCK(fvp, 0);
                    702:                error = EMLINK;
                    703:                goto abortit;
                    704:        }
1.1       bouyer    705:        if ((ip->i_e2fs_flags & (EXT2_IMMUTABLE | EXT2_APPEND)) ||
                    706:                (dp->i_e2fs_flags & EXT2_APPEND)) {
1.8       fvdl      707:                VOP_UNLOCK(fvp, 0);
1.1       bouyer    708:                error = EPERM;
                    709:                goto abortit;
                    710:        }
                    711:        if ((ip->i_e2fs_mode & IFMT) == IFDIR) {
1.16      bouyer    712:                error = VOP_ACCESS(fvp, VWRITE, tcnp->cn_cred, tcnp->cn_proc);
                    713:                if (!error && tvp)
                    714:                        error = VOP_ACCESS(tvp, VWRITE, tcnp->cn_cred,
                    715:                            tcnp->cn_proc);
                    716:                if (error) {
                    717:                        VOP_UNLOCK(fvp, 0);
                    718:                        error = EACCES;
                    719:                        goto abortit;
                    720:                }
1.1       bouyer    721:                /*
                    722:                 * Avoid ".", "..", and aliases of "." for obvious reasons.
                    723:                 */
                    724:                if ((fcnp->cn_namelen == 1 && fcnp->cn_nameptr[0] == '.') ||
1.3       bouyer    725:                    dp == ip ||
1.16      bouyer    726:                    (fcnp->cn_flags&ISDOTDOT) ||
                    727:                    (tcnp->cn_flags & ISDOTDOT) ||
1.1       bouyer    728:                    (ip->i_flag & IN_RENAME)) {
1.8       fvdl      729:                        VOP_UNLOCK(fvp, 0);
1.1       bouyer    730:                        error = EINVAL;
                    731:                        goto abortit;
                    732:                }
                    733:                ip->i_flag |= IN_RENAME;
                    734:                oldparent = dp->i_number;
                    735:                doingdirectory++;
                    736:        }
1.42    ! jdolecek  737:        VN_KNOTE(fdvp, NOTE_WRITE);             /* XXXLUKEM/XXX: right place? */
1.1       bouyer    738:        vrele(fdvp);
                    739:
                    740:        /*
                    741:         * When the target exists, both the directory
                    742:         * and target vnodes are returned locked.
                    743:         */
                    744:        dp = VTOI(tdvp);
                    745:        xp = NULL;
                    746:        if (tvp)
                    747:                xp = VTOI(tvp);
                    748:
                    749:        /*
                    750:         * 1) Bump link count while we're moving stuff
                    751:         *    around.  If we crash somewhere before
                    752:         *    completing our work, the link count
                    753:         *    may be wrong, but correctable.
                    754:         */
                    755:        ip->i_e2fs_nlink++;
                    756:        ip->i_flag |= IN_CHANGE;
1.26      perseant  757:        if ((error = VOP_UPDATE(fvp, NULL, NULL, UPDATE_WAIT)) != 0) {
1.8       fvdl      758:                VOP_UNLOCK(fvp, 0);
1.1       bouyer    759:                goto bad;
                    760:        }
                    761:
                    762:        /*
                    763:         * If ".." must be changed (ie the directory gets a new
                    764:         * parent) then the source directory must not be in the
1.36      wiz       765:         * directory hierarchy above the target, as this would
1.1       bouyer    766:         * orphan everything below the source directory. Also
                    767:         * the user must have write permission in the source so
                    768:         * as to be able to change "..". We must repeat the call
                    769:         * to namei, as the parent directory is unlocked by the
                    770:         * call to checkpath().
                    771:         */
                    772:        error = VOP_ACCESS(fvp, VWRITE, tcnp->cn_cred, tcnp->cn_proc);
1.8       fvdl      773:        VOP_UNLOCK(fvp, 0);
1.1       bouyer    774:        if (oldparent != dp->i_number)
                    775:                newparent = dp->i_number;
                    776:        if (doingdirectory && newparent) {
                    777:                if (error)      /* write access check above */
                    778:                        goto bad;
                    779:                if (xp != NULL)
                    780:                        vput(tvp);
                    781:                error = ext2fs_checkpath(ip, dp, tcnp->cn_cred);
                    782:                if (error != 0)
                    783:                        goto out;
                    784:                if ((tcnp->cn_flags & SAVESTART) == 0)
                    785:                        panic("ext2fs_rename: lost to startdir");
                    786:                if ((error = relookup(tdvp, &tvp, tcnp)) != 0)
                    787:                        goto out;
                    788:                dp = VTOI(tdvp);
                    789:                xp = NULL;
                    790:                if (tvp)
                    791:                        xp = VTOI(tvp);
                    792:        }
                    793:        /*
                    794:         * 2) If target doesn't exist, link the target
                    795:         *    to the source and unlink the source.
                    796:         *    Otherwise, rewrite the target directory
                    797:         *    entry to reference the source inode and
                    798:         *    expunge the original entry's existence.
                    799:         */
                    800:        if (xp == NULL) {
                    801:                if (dp->i_dev != ip->i_dev)
                    802:                        panic("rename: EXDEV");
                    803:                /*
                    804:                 * Account for ".." in new directory.
                    805:                 * When source and destination have the same
                    806:                 * parent we don't fool with the link count.
                    807:                 */
                    808:                if (doingdirectory && newparent) {
                    809:                        if ((nlink_t)dp->i_e2fs_nlink >= LINK_MAX) {
                    810:                                error = EMLINK;
                    811:                                goto bad;
                    812:                        }
                    813:                        dp->i_e2fs_nlink++;
                    814:                        dp->i_flag |= IN_CHANGE;
1.26      perseant  815:                        if ((error = VOP_UPDATE(tdvp, NULL, NULL, UPDATE_WAIT))
                    816:                            != 0)
1.1       bouyer    817:                                goto bad;
                    818:                }
                    819:                error = ext2fs_direnter(ip, tdvp, tcnp);
                    820:                if (error != 0) {
                    821:                        if (doingdirectory && newparent) {
                    822:                                dp->i_e2fs_nlink--;
                    823:                                dp->i_flag |= IN_CHANGE;
1.26      perseant  824:                                (void)VOP_UPDATE(tdvp, NULL, NULL, UPDATE_WAIT);
1.1       bouyer    825:                        }
                    826:                        goto bad;
                    827:                }
1.42    ! jdolecek  828:                VN_KNOTE(tdvp, NOTE_WRITE);
1.1       bouyer    829:                vput(tdvp);
                    830:        } else {
                    831:                if (xp->i_dev != dp->i_dev || xp->i_dev != ip->i_dev)
                    832:                        panic("rename: EXDEV");
                    833:                /*
                    834:                 * Short circuit rename(foo, foo).
                    835:                 */
                    836:                if (xp->i_number == ip->i_number)
                    837:                        panic("rename: same file");
                    838:                /*
                    839:                 * If the parent directory is "sticky", then the user must
                    840:                 * own the parent directory, or the destination of the rename,
                    841:                 * otherwise the destination may not be changed (except by
                    842:                 * root). This implements append-only directories.
                    843:                 */
                    844:                if ((dp->i_e2fs_mode & S_ISTXT) && tcnp->cn_cred->cr_uid != 0 &&
                    845:                    tcnp->cn_cred->cr_uid != dp->i_e2fs_uid &&
                    846:                    xp->i_e2fs_uid != tcnp->cn_cred->cr_uid) {
                    847:                        error = EPERM;
                    848:                        goto bad;
                    849:                }
                    850:                /*
                    851:                 * Target must be empty if a directory and have no links
                    852:                 * to it. Also, ensure source and target are compatible
                    853:                 * (both directories, or both not directories).
                    854:                 */
                    855:                if ((xp->i_e2fs_mode & IFMT) == IFDIR) {
                    856:                        if (!ext2fs_dirempty(xp, dp->i_number, tcnp->cn_cred) ||
                    857:                                xp->i_e2fs_nlink > 2) {
                    858:                                error = ENOTEMPTY;
                    859:                                goto bad;
                    860:                        }
                    861:                        if (!doingdirectory) {
                    862:                                error = ENOTDIR;
                    863:                                goto bad;
                    864:                        }
                    865:                        cache_purge(tdvp);
                    866:                } else if (doingdirectory) {
                    867:                        error = EISDIR;
                    868:                        goto bad;
                    869:                }
                    870:                error = ext2fs_dirrewrite(dp, ip, tcnp);
                    871:                if (error != 0)
                    872:                        goto bad;
                    873:                /*
                    874:                 * If the target directory is in the same
                    875:                 * directory as the source directory,
                    876:                 * decrement the link count on the parent
                    877:                 * of the target directory.
                    878:                 */
                    879:                 if (doingdirectory && !newparent) {
                    880:                        dp->i_e2fs_nlink--;
                    881:                        dp->i_flag |= IN_CHANGE;
                    882:                }
1.42    ! jdolecek  883:                VN_KNOTE(tdvp, NOTE_WRITE);
1.1       bouyer    884:                vput(tdvp);
                    885:                /*
                    886:                 * Adjust the link count of the target to
                    887:                 * reflect the dirrewrite above.  If this is
                    888:                 * a directory it is empty and there are
                    889:                 * no links to it, so we can squash the inode and
                    890:                 * any space associated with it.  We disallowed
                    891:                 * renaming over top of a directory with links to
                    892:                 * it above, as the remaining link would point to
                    893:                 * a directory without "." or ".." entries.
                    894:                 */
                    895:                xp->i_e2fs_nlink--;
                    896:                if (doingdirectory) {
                    897:                        if (--xp->i_e2fs_nlink != 0)
                    898:                                panic("rename: linked directory");
                    899:                        error = VOP_TRUNCATE(tvp, (off_t)0, IO_SYNC,
                    900:                            tcnp->cn_cred, tcnp->cn_proc);
                    901:                }
                    902:                xp->i_flag |= IN_CHANGE;
1.42    ! jdolecek  903:                VN_KNOTE(tvp, NOTE_DELETE);
1.1       bouyer    904:                vput(tvp);
                    905:                xp = NULL;
                    906:        }
                    907:
                    908:        /*
                    909:         * 3) Unlink the source.
                    910:         */
                    911:        fcnp->cn_flags &= ~MODMASK;
                    912:        fcnp->cn_flags |= LOCKPARENT | LOCKLEAF;
                    913:        if ((fcnp->cn_flags & SAVESTART) == 0)
                    914:                panic("ext2fs_rename: lost from startdir");
                    915:        (void) relookup(fdvp, &fvp, fcnp);
                    916:        if (fvp != NULL) {
                    917:                xp = VTOI(fvp);
                    918:                dp = VTOI(fdvp);
                    919:        } else {
                    920:                /*
                    921:                 * From name has disappeared.
                    922:                 */
                    923:                if (doingdirectory)
                    924:                        panic("ext2fs_rename: lost dir entry");
                    925:                vrele(ap->a_fvp);
                    926:                return (0);
                    927:        }
                    928:        /*
                    929:         * Ensure that the directory entry still exists and has not
                    930:         * changed while the new name has been entered. If the source is
                    931:         * a file then the entry may have been unlinked or renamed. In
                    932:         * either case there is no further work to be done. If the source
                    933:         * is a directory then it cannot have been rmdir'ed; its link
                    934:         * count of three would cause a rmdir to fail with ENOTEMPTY.
                    935:         * The IRENAME flag ensures that it cannot be moved by another
                    936:         * rename.
                    937:         */
                    938:        if (xp != ip) {
                    939:                if (doingdirectory)
                    940:                        panic("ext2fs_rename: lost dir entry");
                    941:        } else {
                    942:                /*
                    943:                 * If the source is a directory with a
                    944:                 * new parent, the link count of the old
                    945:                 * parent directory must be decremented
                    946:                 * and ".." set to point to the new parent.
                    947:                 */
                    948:                if (doingdirectory && newparent) {
                    949:                        dp->i_e2fs_nlink--;
                    950:                        dp->i_flag |= IN_CHANGE;
                    951:                        error = vn_rdwr(UIO_READ, fvp, (caddr_t)&dirbuf,
                    952:                                sizeof (struct ext2fs_dirtemplate), (off_t)0,
                    953:                                UIO_SYSSPACE, IO_NODELOCKED,
1.12      mjacob    954:                                tcnp->cn_cred, (size_t *)0, (struct proc *)0);
1.1       bouyer    955:                        if (error == 0) {
1.22      bouyer    956:                                        namlen = dirbuf.dotdot_namlen;
1.1       bouyer    957:                                if (namlen != 2 ||
                    958:                                    dirbuf.dotdot_name[0] != '.' ||
                    959:                                    dirbuf.dotdot_name[1] != '.') {
                    960:                                        ufs_dirbad(xp, (doff_t)12,
                    961:                                            "ext2fs_rename: mangled dir");
                    962:                                } else {
1.4       bouyer    963:                                        dirbuf.dotdot_ino = h2fs32(newparent);
1.1       bouyer    964:                                        (void) vn_rdwr(UIO_WRITE, fvp,
                    965:                                            (caddr_t)&dirbuf,
                    966:                                            sizeof (struct dirtemplate),
                    967:                                            (off_t)0, UIO_SYSSPACE,
                    968:                                            IO_NODELOCKED|IO_SYNC,
1.12      mjacob    969:                                            tcnp->cn_cred, (size_t *)0,
1.1       bouyer    970:                                            (struct proc *)0);
                    971:                                        cache_purge(fdvp);
                    972:                                }
                    973:                        }
                    974:                }
                    975:                error = ext2fs_dirremove(fdvp, fcnp);
                    976:                if (!error) {
                    977:                        xp->i_e2fs_nlink--;
                    978:                        xp->i_flag |= IN_CHANGE;
                    979:                }
                    980:                xp->i_flag &= ~IN_RENAME;
                    981:        }
1.42    ! jdolecek  982:        VN_KNOTE(fvp, NOTE_RENAME);
1.1       bouyer    983:        if (dp)
                    984:                vput(fdvp);
                    985:        if (xp)
                    986:                vput(fvp);
                    987:        vrele(ap->a_fvp);
                    988:        return (error);
                    989:
                    990: bad:
                    991:        if (xp)
                    992:                vput(ITOV(xp));
                    993:        vput(ITOV(dp));
                    994: out:
                    995:        if (doingdirectory)
                    996:                ip->i_flag &= ~IN_RENAME;
1.8       fvdl      997:        if (vn_lock(fvp, LK_EXCLUSIVE) == 0) {
1.1       bouyer    998:                ip->i_e2fs_nlink--;
                    999:                ip->i_flag |= IN_CHANGE;
                   1000:                vput(fvp);
                   1001:        } else
                   1002:                vrele(fvp);
                   1003:        return (error);
                   1004: }
                   1005:
                   1006: /*
                   1007:  * Mkdir system call
                   1008:  */
                   1009: int
                   1010: ext2fs_mkdir(v)
                   1011:        void *v;
                   1012: {
                   1013:        struct vop_mkdir_args /* {
                   1014:                struct vnode *a_dvp;
                   1015:                struct vnode **a_vpp;
                   1016:                struct componentname *a_cnp;
                   1017:                struct vattr *a_vap;
                   1018:        } */ *ap = v;
1.25      augustss 1019:        struct vnode *dvp = ap->a_dvp;
                   1020:        struct vattr *vap = ap->a_vap;
                   1021:        struct componentname *cnp = ap->a_cnp;
                   1022:        struct inode *ip, *dp;
1.1       bouyer   1023:        struct vnode *tvp;
1.4       bouyer   1024:        struct ext2fs_dirtemplate dirtemplate;
1.1       bouyer   1025:        int error, dmode;
                   1026:
                   1027: #ifdef DIAGNOSTIC
                   1028:        if ((cnp->cn_flags & HASBUF) == 0)
                   1029:                panic("ext2fs_mkdir: no name");
                   1030: #endif
                   1031:        dp = VTOI(dvp);
                   1032:        if ((nlink_t)dp->i_e2fs_nlink >= LINK_MAX) {
                   1033:                error = EMLINK;
                   1034:                goto out;
                   1035:        }
                   1036:        dmode = vap->va_mode & ACCESSPERMS;
                   1037:        dmode |= IFDIR;
                   1038:        /*
                   1039:         * Must simulate part of ext2fs_makeinode here to acquire the inode,
                   1040:         * but not have it entered in the parent directory. The entry is
                   1041:         * made later after writing "." and ".." entries.
                   1042:         */
                   1043:        if ((error = VOP_VALLOC(dvp, dmode, cnp->cn_cred, &tvp)) != 0)
                   1044:                goto out;
                   1045:        ip = VTOI(tvp);
                   1046:        ip->i_e2fs_uid = cnp->cn_cred->cr_uid;
                   1047:        ip->i_e2fs_gid = dp->i_e2fs_gid;
                   1048:        ip->i_flag |= IN_ACCESS | IN_CHANGE | IN_UPDATE;
                   1049:        ip->i_e2fs_mode = dmode;
                   1050:        tvp->v_type = VDIR;     /* Rest init'd in getnewvnode(). */
                   1051:        ip->i_e2fs_nlink = 2;
1.26      perseant 1052:        error = VOP_UPDATE(tvp, NULL, NULL, UPDATE_WAIT);
1.1       bouyer   1053:
                   1054:        /*
                   1055:         * Bump link count in parent directory
                   1056:         * to reflect work done below.  Should
                   1057:         * be done before reference is created
                   1058:         * so reparation is possible if we crash.
                   1059:         */
                   1060:        dp->i_e2fs_nlink++;
                   1061:        dp->i_flag |= IN_CHANGE;
1.26      perseant 1062:        if ((error = VOP_UPDATE(dvp, NULL, NULL, UPDATE_WAIT)) != 0)
1.1       bouyer   1063:                goto bad;
                   1064:
                   1065:        /* Initialize directory with "." and ".." from static template. */
1.13      perry    1066:        memset(&dirtemplate, 0, sizeof(dirtemplate));
1.4       bouyer   1067:        dirtemplate.dot_ino = h2fs32(ip->i_number);
                   1068:        dirtemplate.dot_reclen = h2fs16(12);
1.22      bouyer   1069:        dirtemplate.dot_namlen = 1;
                   1070:        if (ip->i_e2fs->e2fs.e2fs_rev > E2FS_REV0 &&
                   1071:            (ip->i_e2fs->e2fs.e2fs_features_incompat & EXT2F_INCOMPAT_FTYPE)) {
1.23      bouyer   1072:                dirtemplate.dot_type = EXT2_FT_DIR;
1.22      bouyer   1073:        }
1.4       bouyer   1074:        dirtemplate.dot_name[0] = '.';
                   1075:        dirtemplate.dotdot_ino = h2fs32(dp->i_number);
                   1076:     dirtemplate.dotdot_reclen = h2fs16(VTOI(dvp)->i_e2fs->e2fs_bsize - 12);
1.22      bouyer   1077:        dirtemplate.dotdot_namlen = 2;
                   1078:        if (ip->i_e2fs->e2fs.e2fs_rev > E2FS_REV0 &&
                   1079:            (ip->i_e2fs->e2fs.e2fs_features_incompat & EXT2F_INCOMPAT_FTYPE)) {
1.23      bouyer   1080:                dirtemplate.dotdot_type = EXT2_FT_DIR;
1.22      bouyer   1081:        }
1.4       bouyer   1082:        dirtemplate.dotdot_name[0] = dirtemplate.dotdot_name[1] = '.';
1.1       bouyer   1083:        error = vn_rdwr(UIO_WRITE, tvp, (caddr_t)&dirtemplate,
                   1084:            sizeof (dirtemplate), (off_t)0, UIO_SYSSPACE,
1.12      mjacob   1085:            IO_NODELOCKED|IO_SYNC, cnp->cn_cred, (size_t *)0, (struct proc *)0);
1.1       bouyer   1086:        if (error) {
                   1087:                dp->i_e2fs_nlink--;
                   1088:                dp->i_flag |= IN_CHANGE;
                   1089:                goto bad;
                   1090:        }
                   1091:        if (VTOI(dvp)->i_e2fs->e2fs_bsize >
                   1092:                                                        VFSTOUFS(dvp->v_mount)->um_mountp->mnt_stat.f_bsize)
                   1093:                panic("ext2fs_mkdir: blksize"); /* XXX should grow with balloc() */
                   1094:        else {
                   1095:                ip->i_e2fs_size = VTOI(dvp)->i_e2fs->e2fs_bsize;
                   1096:                ip->i_flag |= IN_CHANGE;
                   1097:        }
                   1098:
                   1099:        /* Directory set up, now install it's entry in the parent directory. */
                   1100:        error = ext2fs_direnter(ip, dvp, cnp);
                   1101:        if (error != 0) {
                   1102:                dp->i_e2fs_nlink--;
                   1103:                dp->i_flag |= IN_CHANGE;
                   1104:        }
                   1105: bad:
                   1106:        /*
                   1107:         * No need to do an explicit VOP_TRUNCATE here, vrele will do this
                   1108:         * for us because we set the link count to 0.
                   1109:         */
                   1110:        if (error) {
                   1111:                ip->i_e2fs_nlink = 0;
                   1112:                ip->i_flag |= IN_CHANGE;
                   1113:                vput(tvp);
1.42    ! jdolecek 1114:        } else {
        !          1115:                VN_KNOTE(dvp, NOTE_WRITE | NOTE_LINK);
1.1       bouyer   1116:                *ap->a_vpp = tvp;
1.42    ! jdolecek 1117:        }
1.1       bouyer   1118: out:
1.29      thorpej  1119:        PNBUF_PUT(cnp->cn_pnbuf);
1.1       bouyer   1120:        vput(dvp);
                   1121:        return (error);
                   1122: }
                   1123:
                   1124: /*
                   1125:  * Rmdir system call.
                   1126:  */
                   1127: int
                   1128: ext2fs_rmdir(v)
                   1129:        void *v;
                   1130: {
                   1131:        struct vop_rmdir_args /* {
                   1132:                struct vnode *a_dvp;
                   1133:                struct vnode *a_vp;
                   1134:                struct componentname *a_cnp;
                   1135:        } */ *ap = v;
1.25      augustss 1136:        struct vnode *vp = ap->a_vp;
                   1137:        struct vnode *dvp = ap->a_dvp;
                   1138:        struct componentname *cnp = ap->a_cnp;
                   1139:        struct inode *ip, *dp;
1.1       bouyer   1140:        int error;
                   1141:
                   1142:        ip = VTOI(vp);
                   1143:        dp = VTOI(dvp);
                   1144:        /*
                   1145:         * No rmdir "." please.
                   1146:         */
                   1147:        if (dp == ip) {
                   1148:                vrele(dvp);
                   1149:                vput(vp);
                   1150:                return (EINVAL);
                   1151:        }
                   1152:        /*
                   1153:         * Verify the directory is empty (and valid).
                   1154:         * (Rmdir ".." won't be valid since
                   1155:         *  ".." will contain a reference to
                   1156:         *  the current directory and thus be
                   1157:         *  non-empty.)
                   1158:         */
                   1159:        error = 0;
                   1160:        if (ip->i_e2fs_nlink != 2 ||
                   1161:            !ext2fs_dirempty(ip, dp->i_number, cnp->cn_cred)) {
                   1162:                error = ENOTEMPTY;
                   1163:                goto out;
                   1164:        }
                   1165:        if ((dp->i_e2fs_flags & EXT2_APPEND) ||
                   1166:                                 (ip->i_e2fs_flags & (EXT2_IMMUTABLE | EXT2_APPEND))) {
                   1167:                error = EPERM;
                   1168:                goto out;
                   1169:        }
                   1170:        /*
                   1171:         * Delete reference to directory before purging
                   1172:         * inode.  If we crash in between, the directory
                   1173:         * will be reattached to lost+found,
                   1174:         */
                   1175:        error = ext2fs_dirremove(dvp, cnp);
                   1176:        if (error != 0)
                   1177:                goto out;
                   1178:        dp->i_e2fs_nlink--;
                   1179:        dp->i_flag |= IN_CHANGE;
1.42    ! jdolecek 1180:        VN_KNOTE(dvp, NOTE_WRITE | NOTE_LINK);
1.1       bouyer   1181:        cache_purge(dvp);
                   1182:        vput(dvp);
                   1183:        dvp = NULL;
                   1184:        /*
                   1185:         * Truncate inode.  The only stuff left
                   1186:         * in the directory is "." and "..".  The
                   1187:         * "." reference is inconsequential since
                   1188:         * we're quashing it.  The ".." reference
                   1189:         * has already been adjusted above.  We've
                   1190:         * removed the "." reference and the reference
                   1191:         * in the parent directory, but there may be
                   1192:         * other hard links so decrement by 2 and
                   1193:         * worry about them later.
                   1194:         */
                   1195:        ip->i_e2fs_nlink -= 2;
                   1196:        error = VOP_TRUNCATE(vp, (off_t)0, IO_SYNC, cnp->cn_cred,
                   1197:            cnp->cn_proc);
                   1198:        cache_purge(ITOV(ip));
                   1199: out:
1.42    ! jdolecek 1200:        VN_KNOTE(vp, NOTE_DELETE);
1.1       bouyer   1201:        if (dvp)
                   1202:                vput(dvp);
                   1203:        vput(vp);
                   1204:        return (error);
                   1205: }
                   1206:
                   1207: /*
                   1208:  * symlink -- make a symbolic link
                   1209:  */
                   1210: int
                   1211: ext2fs_symlink(v)
                   1212:        void *v;
                   1213: {
                   1214:        struct vop_symlink_args /* {
                   1215:                struct vnode *a_dvp;
                   1216:                struct vnode **a_vpp;
                   1217:                struct componentname *a_cnp;
                   1218:                struct vattr *a_vap;
                   1219:                char *a_target;
                   1220:        } */ *ap = v;
1.25      augustss 1221:        struct vnode *vp, **vpp = ap->a_vpp;
                   1222:        struct inode *ip;
1.1       bouyer   1223:        int len, error;
                   1224:
                   1225:        error = ext2fs_makeinode(IFLNK | ap->a_vap->va_mode, ap->a_dvp,
                   1226:                              vpp, ap->a_cnp);
                   1227:        if (error)
                   1228:                return (error);
1.42    ! jdolecek 1229:        VN_KNOTE(ap->a_dvp, NOTE_WRITE);
1.1       bouyer   1230:        vp = *vpp;
                   1231:        len = strlen(ap->a_target);
                   1232:        if (len < vp->v_mount->mnt_maxsymlinklen) {
                   1233:                ip = VTOI(vp);
1.13      perry    1234:                memcpy((char *)ip->i_din.e2fs_din.e2di_shortlink, ap->a_target, len);
1.1       bouyer   1235:                ip->i_e2fs_size = len;
                   1236:                ip->i_flag |= IN_CHANGE | IN_UPDATE;
                   1237:        } else
                   1238:                error = vn_rdwr(UIO_WRITE, vp, ap->a_target, len, (off_t)0,
1.12      mjacob   1239:                    UIO_SYSSPACE, IO_NODELOCKED, ap->a_cnp->cn_cred,
                   1240:                    (size_t *)0, (struct proc *)0);
1.34      assar    1241:        if (error)
                   1242:                vput(vp);
1.1       bouyer   1243:        return (error);
                   1244: }
                   1245:
                   1246: /*
                   1247:  * Return target name of a symbolic link
                   1248:  */
                   1249: int
                   1250: ext2fs_readlink(v)
                   1251:        void *v;
                   1252: {
                   1253:        struct vop_readlink_args /* {
                   1254:                struct vnode *a_vp;
                   1255:                struct uio *a_uio;
                   1256:                struct ucred *a_cred;
                   1257:        } */ *ap = v;
1.25      augustss 1258:        struct vnode *vp = ap->a_vp;
                   1259:        struct inode *ip = VTOI(vp);
1.1       bouyer   1260:        int isize;
                   1261:
                   1262:        isize = ip->i_e2fs_size;
                   1263:        if (isize < vp->v_mount->mnt_maxsymlinklen ||
                   1264:            (vp->v_mount->mnt_maxsymlinklen == 0 && ip->i_e2fs_nblock == 0)) {
                   1265:                uiomove((char *)ip->i_din.e2fs_din.e2di_shortlink, isize, ap->a_uio);
                   1266:                return (0);
                   1267:        }
                   1268:        return (VOP_READ(vp, ap->a_uio, 0, ap->a_cred));
                   1269: }
                   1270:
                   1271: /*
                   1272:  * Advisory record locking support
                   1273:  */
                   1274: int
                   1275: ext2fs_advlock(v)
                   1276:        void *v;
                   1277: {
                   1278:        struct vop_advlock_args /* {
                   1279:                struct vnode *a_vp;
                   1280:                caddr_t  a_id;
                   1281:                int  a_op;
                   1282:                struct flock *a_fl;
                   1283:                int  a_flags;
                   1284:        } */ *ap = v;
1.25      augustss 1285:        struct inode *ip = VTOI(ap->a_vp);
1.1       bouyer   1286:
1.28      jdolecek 1287:        return lf_advlock(ap, &ip->i_lockf, ip->i_e2fs_size);
1.1       bouyer   1288: }
                   1289:
                   1290: /*
                   1291:  * Initialize the vnode associated with a new inode, handle aliased
                   1292:  * vnodes.
                   1293:  */
                   1294: int
                   1295: ext2fs_vinit(mntp, specops, fifoops, vpp)
                   1296:        struct mount *mntp;
                   1297:        int (**specops) __P((void *));
                   1298:        int (**fifoops) __P((void *));
                   1299:        struct vnode **vpp;
                   1300: {
                   1301:        struct inode *ip;
                   1302:        struct vnode *vp, *nvp;
                   1303:
                   1304:        vp = *vpp;
                   1305:        ip = VTOI(vp);
                   1306:        switch(vp->v_type = IFTOVT(ip->i_e2fs_mode)) {
                   1307:        case VCHR:
                   1308:        case VBLK:
                   1309:                vp->v_op = specops;
1.16      bouyer   1310:                if ((nvp = checkalias(vp,
                   1311:                    fs2h32(ip->i_din.e2fs_din.e2di_rdev), mntp)) != NULL) {
1.1       bouyer   1312:                        /*
                   1313:                         * Discard unneeded vnode, but save its inode.
                   1314:                         */
                   1315:                        nvp->v_data = vp->v_data;
                   1316:                        vp->v_data = NULL;
1.33      fvdl     1317:                        VOP_UNLOCK(vp, 0);
1.1       bouyer   1318:                        vp->v_op = spec_vnodeop_p;
1.33      fvdl     1319:                        vrele(vp);
1.1       bouyer   1320:                        vgone(vp);
1.20      wrstuden 1321:                        lockmgr(&nvp->v_lock, LK_EXCLUSIVE, &nvp->v_interlock);
1.1       bouyer   1322:                        /*
                   1323:                         * Reinitialize aliased inode.
                   1324:                         */
                   1325:                        vp = nvp;
                   1326:                        ip->i_vnode = vp;
                   1327:                }
                   1328:                break;
                   1329:        case VFIFO:
                   1330:                vp->v_op = fifoops;
                   1331:                break;
                   1332:        case VNON:
                   1333:        case VBAD:
                   1334:        case VSOCK:
                   1335:        case VLNK:
                   1336:        case VDIR:
                   1337:        case VREG:
                   1338:                break;
                   1339:        }
                   1340:        if (ip->i_number == ROOTINO)
                   1341:                 vp->v_flag |= VROOT;
                   1342:        /*
                   1343:         * Initialize modrev times
                   1344:         */
                   1345:        SETHIGH(ip->i_modrev, mono_time.tv_sec);
                   1346:        SETLOW(ip->i_modrev, mono_time.tv_usec * 4294);
                   1347:        *vpp = vp;
                   1348:        return (0);
                   1349: }
                   1350:
                   1351: /*
                   1352:  * Allocate a new inode.
                   1353:  */
                   1354: int
                   1355: ext2fs_makeinode(mode, dvp, vpp, cnp)
                   1356:        int mode;
                   1357:        struct vnode *dvp;
                   1358:        struct vnode **vpp;
                   1359:        struct componentname *cnp;
                   1360: {
1.25      augustss 1361:        struct inode *ip, *pdir;
1.1       bouyer   1362:        struct vnode *tvp;
                   1363:        int error;
                   1364:
                   1365:        pdir = VTOI(dvp);
                   1366: #ifdef DIAGNOSTIC
                   1367:        if ((cnp->cn_flags & HASBUF) == 0)
                   1368:                panic("ext2fs_makeinode: no name");
                   1369: #endif
                   1370:        *vpp = NULL;
                   1371:        if ((mode & IFMT) == 0)
                   1372:                mode |= IFREG;
                   1373:
                   1374:        if ((error = VOP_VALLOC(dvp, mode, cnp->cn_cred, &tvp)) != 0) {
1.29      thorpej  1375:                PNBUF_PUT(cnp->cn_pnbuf);
1.1       bouyer   1376:                vput(dvp);
                   1377:                return (error);
                   1378:        }
                   1379:        ip = VTOI(tvp);
                   1380:        ip->i_e2fs_gid = pdir->i_e2fs_gid;
                   1381:        ip->i_e2fs_uid = cnp->cn_cred->cr_uid;
                   1382:        ip->i_flag |= IN_ACCESS | IN_CHANGE | IN_UPDATE;
                   1383:        ip->i_e2fs_mode = mode;
                   1384:        tvp->v_type = IFTOVT(mode);     /* Rest init'd in getnewvnode(). */
                   1385:        ip->i_e2fs_nlink = 1;
                   1386:        if ((ip->i_e2fs_mode & ISGID) &&
                   1387:                !groupmember(ip->i_e2fs_gid, cnp->cn_cred) &&
                   1388:            suser(cnp->cn_cred, NULL))
                   1389:                ip->i_e2fs_mode &= ~ISGID;
                   1390:
                   1391:        /*
                   1392:         * Make sure inode goes to disk before directory entry.
                   1393:         */
1.26      perseant 1394:        if ((error = VOP_UPDATE(tvp, NULL, NULL, UPDATE_WAIT)) != 0)
1.1       bouyer   1395:                goto bad;
                   1396:        error = ext2fs_direnter(ip, dvp, cnp);
                   1397:        if (error != 0)
                   1398:                goto bad;
                   1399:        if ((cnp->cn_flags & SAVESTART) == 0)
1.29      thorpej  1400:                PNBUF_PUT(cnp->cn_pnbuf);
1.1       bouyer   1401:        vput(dvp);
                   1402:        *vpp = tvp;
                   1403:        return (0);
                   1404:
                   1405: bad:
                   1406:        /*
                   1407:         * Write error occurred trying to update the inode
                   1408:         * or the directory so must deallocate the inode.
                   1409:         */
1.29      thorpej  1410:        PNBUF_PUT(cnp->cn_pnbuf);
1.1       bouyer   1411:        vput(dvp);
                   1412:        ip->i_e2fs_nlink = 0;
                   1413:        ip->i_flag |= IN_CHANGE;
                   1414:        vput(tvp);
                   1415:        return (error);
                   1416: }
                   1417:
                   1418: /*
                   1419:  * Reclaim an inode so that it can be used for other purposes.
                   1420:  */
                   1421: int
                   1422: ext2fs_reclaim(v)
                   1423:        void *v;
                   1424: {
                   1425:        struct vop_reclaim_args /* {
                   1426:                struct vnode *a_vp;
                   1427:        } */ *ap = v;
1.25      augustss 1428:        struct vnode *vp = ap->a_vp;
1.1       bouyer   1429:        struct inode *ip;
                   1430:
1.8       fvdl     1431:        if (prtactive && vp->v_usecount != 0)
                   1432:                vprint("ext2fs_reclaim: pushing active", vp);
                   1433:        /*
                   1434:         * Remove the inode from its hash chain.
                   1435:         */
                   1436:        ip = VTOI(vp);
                   1437:        ufs_ihashrem(ip);
                   1438:        /*
                   1439:         * Purge old data structures associated with the inode.
                   1440:         */
                   1441:        cache_purge(vp);
                   1442:        if (ip->i_devvp) {
                   1443:                vrele(ip->i_devvp);
                   1444:                ip->i_devvp = 0;
                   1445:        }
1.1       bouyer   1446:
1.14      thorpej  1447:        pool_put(&ext2fs_inode_pool, vp->v_data);
1.1       bouyer   1448:        vp->v_data = NULL;
                   1449:        return (0);
                   1450: }
                   1451:
                   1452: /* Global vfs data structures for ext2fs. */
                   1453: int (**ext2fs_vnodeop_p) __P((void *));
1.31      jdolecek 1454: const struct vnodeopv_entry_desc ext2fs_vnodeop_entries[] = {
1.1       bouyer   1455:        { &vop_default_desc, vn_default_error },
1.8       fvdl     1456:        { &vop_lookup_desc, ext2fs_lookup },            /* lookup */
                   1457:        { &vop_create_desc, ext2fs_create },            /* create */
1.1       bouyer   1458:        { &vop_mknod_desc, ext2fs_mknod },              /* mknod */
                   1459:        { &vop_open_desc, ext2fs_open },                /* open */
                   1460:        { &vop_close_desc, ufs_close },                 /* close */
1.8       fvdl     1461:        { &vop_access_desc, ext2fs_access },            /* access */
                   1462:        { &vop_getattr_desc, ext2fs_getattr },          /* getattr */
                   1463:        { &vop_setattr_desc, ext2fs_setattr },          /* setattr */
1.1       bouyer   1464:        { &vop_read_desc, ext2fs_read },                /* read */
                   1465:        { &vop_write_desc, ext2fs_write },              /* write */
1.8       fvdl     1466:        { &vop_lease_desc, ufs_lease_check },           /* lease */
1.1       bouyer   1467:        { &vop_ioctl_desc, ufs_ioctl },                 /* ioctl */
1.21      wrstuden 1468:        { &vop_fcntl_desc, ufs_fcntl },                 /* fcntl */
1.1       bouyer   1469:        { &vop_poll_desc, ufs_poll },                   /* poll */
1.42    ! jdolecek 1470:        { &vop_kqfilter_desc, genfs_kqfilter },         /* kqfilter */
1.8       fvdl     1471:        { &vop_revoke_desc, ufs_revoke },               /* revoke */
1.1       bouyer   1472:        { &vop_mmap_desc, ufs_mmap },                   /* mmap */
                   1473:        { &vop_fsync_desc, ext2fs_fsync },              /* fsync */
                   1474:        { &vop_seek_desc, ufs_seek },                   /* seek */
1.8       fvdl     1475:        { &vop_remove_desc, ext2fs_remove },            /* remove */
1.1       bouyer   1476:        { &vop_link_desc, ext2fs_link },                /* link */
1.8       fvdl     1477:        { &vop_rename_desc, ext2fs_rename },            /* rename */
1.1       bouyer   1478:        { &vop_mkdir_desc, ext2fs_mkdir },              /* mkdir */
                   1479:        { &vop_rmdir_desc, ext2fs_rmdir },              /* rmdir */
1.8       fvdl     1480:        { &vop_symlink_desc, ext2fs_symlink },          /* symlink */
                   1481:        { &vop_readdir_desc, ext2fs_readdir },          /* readdir */
                   1482:        { &vop_readlink_desc, ext2fs_readlink },        /* readlink */
1.1       bouyer   1483:        { &vop_abortop_desc, ufs_abortop },             /* abortop */
1.8       fvdl     1484:        { &vop_inactive_desc, ext2fs_inactive },        /* inactive */
                   1485:        { &vop_reclaim_desc, ext2fs_reclaim },          /* reclaim */
1.1       bouyer   1486:        { &vop_lock_desc, ufs_lock },                   /* lock */
                   1487:        { &vop_unlock_desc, ufs_unlock },               /* unlock */
                   1488:        { &vop_bmap_desc, ext2fs_bmap },                /* bmap */
1.8       fvdl     1489:        { &vop_strategy_desc, ufs_strategy },           /* strategy */
1.1       bouyer   1490:        { &vop_print_desc, ufs_print },                 /* print */
1.8       fvdl     1491:        { &vop_islocked_desc, ufs_islocked },           /* islocked */
                   1492:        { &vop_pathconf_desc, ufs_pathconf },           /* pathconf */
                   1493:        { &vop_advlock_desc, ext2fs_advlock },          /* advlock */
                   1494:        { &vop_blkatoff_desc, ext2fs_blkatoff },        /* blkatoff */
                   1495:        { &vop_valloc_desc, ext2fs_valloc },            /* valloc */
1.1       bouyer   1496:        { &vop_vfree_desc, ext2fs_vfree },              /* vfree */
1.8       fvdl     1497:        { &vop_truncate_desc, ext2fs_truncate },        /* truncate */
                   1498:        { &vop_update_desc, ext2fs_update },            /* update */
1.1       bouyer   1499:        { &vop_bwrite_desc, vn_bwrite },                /* bwrite */
1.30      chs      1500:        { &vop_getpages_desc, genfs_getpages },         /* getpages */
                   1501:        { &vop_putpages_desc, genfs_putpages },         /* putpages */
                   1502:        { NULL, NULL }
1.1       bouyer   1503: };
1.31      jdolecek 1504: const struct vnodeopv_desc ext2fs_vnodeop_opv_desc =
1.1       bouyer   1505:        { &ext2fs_vnodeop_p, ext2fs_vnodeop_entries };
                   1506:
                   1507: int (**ext2fs_specop_p) __P((void *));
1.31      jdolecek 1508: const struct vnodeopv_entry_desc ext2fs_specop_entries[] = {
1.1       bouyer   1509:        { &vop_default_desc, vn_default_error },
                   1510:        { &vop_lookup_desc, spec_lookup },              /* lookup */
                   1511:        { &vop_create_desc, spec_create },              /* create */
                   1512:        { &vop_mknod_desc, spec_mknod },                /* mknod */
                   1513:        { &vop_open_desc, spec_open },                  /* open */
                   1514:        { &vop_close_desc, ufsspec_close },             /* close */
1.8       fvdl     1515:        { &vop_access_desc, ext2fs_access },            /* access */
                   1516:        { &vop_getattr_desc, ext2fs_getattr },          /* getattr */
                   1517:        { &vop_setattr_desc, ext2fs_setattr },          /* setattr */
1.1       bouyer   1518:        { &vop_read_desc, ufsspec_read },               /* read */
                   1519:        { &vop_write_desc, ufsspec_write },             /* write */
1.8       fvdl     1520:        { &vop_lease_desc, spec_lease_check },          /* lease */
1.1       bouyer   1521:        { &vop_ioctl_desc, spec_ioctl },                /* ioctl */
1.21      wrstuden 1522:        { &vop_fcntl_desc, ufs_fcntl },                 /* fcntl */
1.1       bouyer   1523:        { &vop_poll_desc, spec_poll },                  /* poll */
1.42    ! jdolecek 1524:        { &vop_kqfilter_desc, spec_kqfilter },          /* kqfilter */
1.8       fvdl     1525:        { &vop_revoke_desc, spec_revoke },              /* revoke */
1.1       bouyer   1526:        { &vop_mmap_desc, spec_mmap },                  /* mmap */
                   1527:        { &vop_fsync_desc, ext2fs_fsync },              /* fsync */
                   1528:        { &vop_seek_desc, spec_seek },                  /* seek */
                   1529:        { &vop_remove_desc, spec_remove },              /* remove */
                   1530:        { &vop_link_desc, spec_link },                  /* link */
                   1531:        { &vop_rename_desc, spec_rename },              /* rename */
                   1532:        { &vop_mkdir_desc, spec_mkdir },                /* mkdir */
                   1533:        { &vop_rmdir_desc, spec_rmdir },                /* rmdir */
1.8       fvdl     1534:        { &vop_symlink_desc, spec_symlink },            /* symlink */
                   1535:        { &vop_readdir_desc, spec_readdir },            /* readdir */
                   1536:        { &vop_readlink_desc, spec_readlink },          /* readlink */
                   1537:        { &vop_abortop_desc, spec_abortop },            /* abortop */
                   1538:        { &vop_inactive_desc, ext2fs_inactive },        /* inactive */
                   1539:        { &vop_reclaim_desc, ext2fs_reclaim },          /* reclaim */
1.1       bouyer   1540:        { &vop_lock_desc, ufs_lock },                   /* lock */
                   1541:        { &vop_unlock_desc, ufs_unlock },               /* unlock */
                   1542:        { &vop_bmap_desc, spec_bmap },                  /* bmap */
1.8       fvdl     1543:        { &vop_strategy_desc, spec_strategy },          /* strategy */
1.1       bouyer   1544:        { &vop_print_desc, ufs_print },                 /* print */
1.8       fvdl     1545:        { &vop_islocked_desc, ufs_islocked },           /* islocked */
                   1546:        { &vop_pathconf_desc, spec_pathconf },          /* pathconf */
                   1547:        { &vop_advlock_desc, spec_advlock },            /* advlock */
                   1548:        { &vop_blkatoff_desc, spec_blkatoff },          /* blkatoff */
1.1       bouyer   1549:        { &vop_valloc_desc, spec_valloc },              /* valloc */
                   1550:        { &vop_vfree_desc, ext2fs_vfree },              /* vfree */
1.8       fvdl     1551:        { &vop_truncate_desc, spec_truncate },          /* truncate */
                   1552:        { &vop_update_desc, ext2fs_update },            /* update */
1.1       bouyer   1553:        { &vop_bwrite_desc, vn_bwrite },                /* bwrite */
1.35      chs      1554:        { &vop_getpages_desc, spec_getpages },          /* getpages */
                   1555:        { &vop_putpages_desc, spec_putpages },          /* putpages */
1.30      chs      1556:        { NULL, NULL }
1.1       bouyer   1557: };
1.31      jdolecek 1558: const struct vnodeopv_desc ext2fs_specop_opv_desc =
1.1       bouyer   1559:        { &ext2fs_specop_p, ext2fs_specop_entries };
                   1560:
                   1561: int (**ext2fs_fifoop_p) __P((void *));
1.31      jdolecek 1562: const struct vnodeopv_entry_desc ext2fs_fifoop_entries[] = {
1.1       bouyer   1563:        { &vop_default_desc, vn_default_error },
                   1564:        { &vop_lookup_desc, fifo_lookup },              /* lookup */
                   1565:        { &vop_create_desc, fifo_create },              /* create */
                   1566:        { &vop_mknod_desc, fifo_mknod },                /* mknod */
                   1567:        { &vop_open_desc, fifo_open },                  /* open */
                   1568:        { &vop_close_desc, ufsfifo_close },             /* close */
1.8       fvdl     1569:        { &vop_access_desc, ext2fs_access },            /* access */
                   1570:        { &vop_getattr_desc, ext2fs_getattr },          /* getattr */
                   1571:        { &vop_setattr_desc, ext2fs_setattr },          /* setattr */
1.1       bouyer   1572:        { &vop_read_desc, ufsfifo_read },               /* read */
                   1573:        { &vop_write_desc, ufsfifo_write },             /* write */
1.8       fvdl     1574:        { &vop_lease_desc, fifo_lease_check },          /* lease */
1.1       bouyer   1575:        { &vop_ioctl_desc, fifo_ioctl },                /* ioctl */
1.21      wrstuden 1576:        { &vop_fcntl_desc, ufs_fcntl },                 /* fcntl */
1.1       bouyer   1577:        { &vop_poll_desc, fifo_poll },                  /* poll */
1.42    ! jdolecek 1578:        { &vop_kqfilter_desc, fifo_kqfilter },          /* kqfilter */
1.8       fvdl     1579:        { &vop_revoke_desc, fifo_revoke },              /* revoke */
1.1       bouyer   1580:        { &vop_mmap_desc, fifo_mmap },                  /* mmap */
                   1581:        { &vop_fsync_desc, ext2fs_fsync },              /* fsync */
                   1582:        { &vop_seek_desc, fifo_seek },                  /* seek */
                   1583:        { &vop_remove_desc, fifo_remove },              /* remove */
                   1584:        { &vop_link_desc, fifo_link },                  /* link */
                   1585:        { &vop_rename_desc, fifo_rename },              /* rename */
                   1586:        { &vop_mkdir_desc, fifo_mkdir },                /* mkdir */
                   1587:        { &vop_rmdir_desc, fifo_rmdir },                /* rmdir */
1.8       fvdl     1588:        { &vop_symlink_desc, fifo_symlink },            /* symlink */
                   1589:        { &vop_readdir_desc, fifo_readdir },            /* readdir */
                   1590:        { &vop_readlink_desc, fifo_readlink },          /* readlink */
                   1591:        { &vop_abortop_desc, fifo_abortop },            /* abortop */
                   1592:        { &vop_inactive_desc, ext2fs_inactive },        /* inactive */
                   1593:        { &vop_reclaim_desc, ext2fs_reclaim },          /* reclaim */
1.1       bouyer   1594:        { &vop_lock_desc, ufs_lock },                   /* lock */
                   1595:        { &vop_unlock_desc, ufs_unlock },               /* unlock */
                   1596:        { &vop_bmap_desc, fifo_bmap },                  /* bmap */
1.8       fvdl     1597:        { &vop_strategy_desc, fifo_strategy },          /* strategy */
1.1       bouyer   1598:        { &vop_print_desc, ufs_print },                 /* print */
1.8       fvdl     1599:        { &vop_islocked_desc, ufs_islocked },           /* islocked */
                   1600:        { &vop_pathconf_desc, fifo_pathconf },          /* pathconf */
                   1601:        { &vop_advlock_desc, fifo_advlock },            /* advlock */
                   1602:        { &vop_blkatoff_desc, fifo_blkatoff },          /* blkatoff */
1.1       bouyer   1603:        { &vop_valloc_desc, fifo_valloc },              /* valloc */
                   1604:        { &vop_vfree_desc, ext2fs_vfree },              /* vfree */
1.8       fvdl     1605:        { &vop_truncate_desc, fifo_truncate },          /* truncate */
                   1606:        { &vop_update_desc, ext2fs_update },            /* update */
1.1       bouyer   1607:        { &vop_bwrite_desc, vn_bwrite },                /* bwrite */
1.38      sommerfe 1608:        { &vop_putpages_desc, fifo_putpages },          /* putpages */
1.30      chs      1609:        { NULL, NULL }
1.1       bouyer   1610: };
1.31      jdolecek 1611: const struct vnodeopv_desc ext2fs_fifoop_opv_desc =
1.1       bouyer   1612:        { &ext2fs_fifoop_p, ext2fs_fifoop_entries };

CVSweb <webmaster@jp.NetBSD.org>