[BACK]Return to advnops.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / adosfs

Annotation of src/sys/adosfs/advnops.c, Revision 1.60

1.60    ! mrg         1: /*     $NetBSD: advnops.c,v 1.59 2001/05/28 02:50:51 chs Exp $ */
1.8       cgd         2:
1.1       chopps      3: /*
                      4:  * Copyright (c) 1994 Christian E. Hopps
1.27      mhitch      5:  * Copyright (c) 1996 Matthias Scheler
1.1       chopps      6:  * All rights reserved.
                      7:  *
                      8:  * Redistribution and use in source and binary forms, with or without
                      9:  * modification, are permitted provided that the following conditions
                     10:  * are met:
                     11:  * 1. Redistributions of source code must retain the above copyright
                     12:  *    notice, this list of conditions and the following disclaimer.
                     13:  * 2. Redistributions in binary form must reproduce the above copyright
                     14:  *    notice, this list of conditions and the following disclaimer in the
                     15:  *    documentation and/or other materials provided with the distribution.
                     16:  * 3. All advertising materials mentioning features or use of this software
                     17:  *    must display the following acknowledgement:
                     18:  *      This product includes software developed by Christian E. Hopps.
                     19:  * 4. The name of the author may not be used to endorse or promote products
                     20:  *    derived from this software without specific prior written permission
                     21:  *
                     22:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
                     23:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
                     24:  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
                     25:  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
                     26:  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
                     27:  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
                     28:  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
                     29:  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
                     30:  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
                     31:  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
                     32:  */
1.38      scottr     33:
1.60    ! mrg        34: #if defined(_KERNEL_OPT)
1.38      scottr     35: #include "opt_quota.h"
1.39      scottr     36: #endif
1.38      scottr     37:
1.1       chopps     38: #include <sys/param.h>
1.13      cgd        39: #include <sys/systm.h>
1.1       chopps     40: #include <sys/vnode.h>
                     41: #include <sys/mount.h>
                     42: #include <sys/time.h>
                     43: #include <sys/queue.h>
                     44: #include <sys/namei.h>
                     45: #include <sys/buf.h>
                     46: #include <sys/dirent.h>
1.6       chopps     47: #include <sys/malloc.h>
1.46      thorpej    48: #include <sys/pool.h>
1.1       chopps     49: #include <sys/stat.h>
1.6       chopps     50: #include <sys/unistd.h>
1.25      christos   51: #include <sys/proc.h>
1.29      mycroft    52:
                     53: #include <miscfs/genfs/genfs.h>
1.1       chopps     54: #include <miscfs/specfs/specdev.h>
                     55: #include <adosfs/adosfs.h>
                     56:
                     57: extern struct vnodeops adosfs_vnodeops;
                     58:
1.29      mycroft    59: #define        adosfs_open     genfs_nullop
1.25      christos   60: int    adosfs_getattr  __P((void *));
                     61: int    adosfs_read     __P((void *));
                     62: int    adosfs_write    __P((void *));
1.51      wrstuden   63: #define        adosfs_fcntl    genfs_fcntl
1.43      matthias   64: #define        adosfs_ioctl    genfs_enoioctl
1.30      mycroft    65: #define        adosfs_poll     genfs_poll
1.25      christos   66: int    adosfs_strategy __P((void *));
1.26      christos   67: int    adosfs_link     __P((void *));
                     68: int    adosfs_symlink  __P((void *));
1.29      mycroft    69: #define        adosfs_abortop  genfs_abortop
1.25      christos   70: int    adosfs_bmap     __P((void *));
                     71: int    adosfs_print    __P((void *));
                     72: int    adosfs_readdir  __P((void *));
                     73: int    adosfs_access   __P((void *));
                     74: int    adosfs_readlink __P((void *));
                     75: int    adosfs_inactive __P((void *));
                     76: int    adosfs_reclaim  __P((void *));
                     77: int    adosfs_pathconf __P((void *));
                     78:
1.29      mycroft    79: #define adosfs_close   genfs_nullop
                     80: #define adosfs_fsync   genfs_nullop
1.40      thorpej    81: #define        adosfs_lease_check      genfs_lease_check
1.33      kleink     82: #define adosfs_seek    genfs_seek
1.29      mycroft    83: #define adosfs_vfree   genfs_nullop
1.25      christos   84:
1.44      kleink     85: #define adosfs_advlock         genfs_einval
1.29      mycroft    86: #define adosfs_blkatoff        genfs_eopnotsupp
                     87: #define adosfs_bwrite  genfs_eopnotsupp
                     88: #define adosfs_create  genfs_eopnotsupp
                     89: #define adosfs_mkdir   genfs_eopnotsupp
                     90: #define adosfs_mknod   genfs_eopnotsupp
1.37      fvdl       91: #define adosfs_revoke  genfs_revoke
1.59      chs        92: #define adosfs_mmap    genfs_mmap
1.29      mycroft    93: #define adosfs_remove  genfs_eopnotsupp
                     94: #define adosfs_rename  genfs_eopnotsupp
                     95: #define adosfs_rmdir   genfs_eopnotsupp
                     96: #define adosfs_setattr         genfs_eopnotsupp
                     97: #define adosfs_truncate        genfs_eopnotsupp
                     98: #define adosfs_update  genfs_nullop
                     99: #define adosfs_valloc  genfs_eopnotsupp
1.25      christos  100:
1.56      jdolecek  101: const struct vnodeopv_entry_desc adosfs_vnodeop_entries[] = {
1.29      mycroft   102:        { &vop_default_desc, vn_default_error },
                    103:        { &vop_lookup_desc, adosfs_lookup },            /* lookup */
                    104:        { &vop_create_desc, adosfs_create },            /* create */
                    105:        { &vop_mknod_desc, adosfs_mknod },              /* mknod */
                    106:        { &vop_open_desc, adosfs_open },                /* open */
                    107:        { &vop_close_desc, adosfs_close },              /* close */
                    108:        { &vop_access_desc, adosfs_access },            /* access */
                    109:        { &vop_getattr_desc, adosfs_getattr },          /* getattr */
                    110:        { &vop_setattr_desc, adosfs_setattr },          /* setattr */
                    111:        { &vop_read_desc, adosfs_read },                /* read */
                    112:        { &vop_write_desc, adosfs_write },              /* write */
                    113:        { &vop_lease_desc, adosfs_lease_check },        /* lease */
1.51      wrstuden  114:        { &vop_fcntl_desc, adosfs_fcntl },              /* fcntl */
1.29      mycroft   115:        { &vop_ioctl_desc, adosfs_ioctl },              /* ioctl */
1.30      mycroft   116:        { &vop_poll_desc, adosfs_poll },                /* poll */
1.52      itohy     117:        { &vop_revoke_desc, adosfs_revoke },            /* revoke */
1.29      mycroft   118:        { &vop_mmap_desc, adosfs_mmap },                /* mmap */
                    119:        { &vop_fsync_desc, adosfs_fsync },              /* fsync */
                    120:        { &vop_seek_desc, adosfs_seek },                /* seek */
                    121:        { &vop_remove_desc, adosfs_remove },            /* remove */
                    122:        { &vop_link_desc, adosfs_link },                /* link */
                    123:        { &vop_rename_desc, adosfs_rename },            /* rename */
                    124:        { &vop_mkdir_desc, adosfs_mkdir },              /* mkdir */
                    125:        { &vop_rmdir_desc, adosfs_rmdir },              /* rmdir */
                    126:        { &vop_symlink_desc, adosfs_symlink },          /* symlink */
                    127:        { &vop_readdir_desc, adosfs_readdir },          /* readdir */
                    128:        { &vop_readlink_desc, adosfs_readlink },        /* readlink */
                    129:        { &vop_abortop_desc, adosfs_abortop },          /* abortop */
                    130:        { &vop_inactive_desc, adosfs_inactive },        /* inactive */
                    131:        { &vop_reclaim_desc, adosfs_reclaim },          /* reclaim */
1.50      wrstuden  132:        { &vop_lock_desc, genfs_lock },                 /* lock */
                    133:        { &vop_unlock_desc, genfs_unlock },             /* unlock */
1.29      mycroft   134:        { &vop_bmap_desc, adosfs_bmap },                /* bmap */
                    135:        { &vop_strategy_desc, adosfs_strategy },        /* strategy */
                    136:        { &vop_print_desc, adosfs_print },              /* print */
1.50      wrstuden  137:        { &vop_islocked_desc, genfs_islocked },         /* islocked */
1.29      mycroft   138:        { &vop_pathconf_desc, adosfs_pathconf },        /* pathconf */
                    139:        { &vop_advlock_desc, adosfs_advlock },          /* advlock */
                    140:        { &vop_blkatoff_desc, adosfs_blkatoff },        /* blkatoff */
                    141:        { &vop_valloc_desc, adosfs_valloc },            /* valloc */
                    142:        { &vop_vfree_desc, adosfs_vfree },              /* vfree */
                    143:        { &vop_truncate_desc, adosfs_truncate },        /* truncate */
                    144:        { &vop_update_desc, adosfs_update },            /* update */
                    145:        { &vop_bwrite_desc, adosfs_bwrite },            /* bwrite */
1.55      chs       146:        { &vop_getpages_desc, genfs_getpages },         /* getpages */
                    147:        { &vop_size_desc, genfs_size },                 /* size */
                    148:        { NULL, NULL }
1.25      christos  149: };
                    150:
1.56      jdolecek  151: const struct vnodeopv_desc adosfs_vnodeop_opv_desc =
1.25      christos  152:        { &adosfs_vnodeop_p, adosfs_vnodeop_entries };
                    153:
1.1       chopps    154: int
1.25      christos  155: adosfs_getattr(v)
                    156:        void *v;
                    157: {
1.6       chopps    158:        struct vop_getattr_args /* {
                    159:                struct vnode *a_vp;
                    160:                struct vattr *a_vap;
                    161:                struct ucred *a_cred;
                    162:                struct proc *a_p;
1.25      christos  163:        } */ *sp = v;
1.1       chopps    164:        struct vattr *vap;
1.20      mycroft   165:        struct adosfsmount *amp;
1.1       chopps    166:        struct anode *ap;
1.2       chopps    167:        u_long fblks;
1.1       chopps    168:
                    169: #ifdef ADOSFS_DIAGNOSTIC
1.6       chopps    170:        advopprint(sp);
1.1       chopps    171: #endif
1.6       chopps    172:        vap = sp->a_vap;
                    173:        ap = VTOA(sp->a_vp);
1.1       chopps    174:        amp = ap->amp;
                    175:        vattr_null(vap);
1.18      chopps    176:        vap->va_uid = ap->uid;
                    177:        vap->va_gid = ap->gid;
1.6       chopps    178:        vap->va_fsid = sp->a_vp->v_mount->mnt_stat.f_fsid.val[0];
1.23      jtc       179:        vap->va_atime.tv_sec = vap->va_mtime.tv_sec = vap->va_ctime.tv_sec =
1.18      chopps    180:                ap->mtime.days * 24 * 60 * 60 + ap->mtime.mins * 60 +
                    181:                ap->mtime.ticks / 50 + (8 * 365 + 2) * 24 * 60 * 60;
1.23      jtc       182:        vap->va_atime.tv_nsec = vap->va_mtime.tv_nsec = vap->va_ctime.tv_nsec = 0;
1.1       chopps    183:        vap->va_gen = 0;
                    184:        vap->va_flags = 0;
1.2       chopps    185:        vap->va_rdev = NODEV;
                    186:        vap->va_fileid = ap->block;
1.6       chopps    187:        vap->va_type = sp->a_vp->v_type;
1.34      mycroft   188:        vap->va_mode = adunixprot(ap->adprot) & amp->mask;
1.6       chopps    189:        if (sp->a_vp->v_type == VDIR) {
1.3       chopps    190:                vap->va_nlink = 1;      /* XXX bogus, oh well */
1.1       chopps    191:                vap->va_bytes = amp->bsize;
                    192:                vap->va_size = amp->bsize;
1.2       chopps    193:        } else {
                    194:                /*
                    195:                 * XXX actually we can track this if we were to walk the list
                    196:                 * of links if it exists.
1.27      mhitch    197:                 * XXX for now, just set nlink to 2 if this is a hard link
                    198:                 * to a file, or a file with a hard link.
1.2       chopps    199:                 */
1.27      mhitch    200:                vap->va_nlink = 1 + (ap->linkto != 0);
1.2       chopps    201:                /*
                    202:                 * round up to nearest blocks add number of file list
                    203:                 * blocks needed and mutiply by number of bytes per block.
                    204:                 */
1.27      mhitch    205:                fblks = howmany(ap->fsize, amp->dbsize);
1.2       chopps    206:                fblks += howmany(fblks, ANODENDATBLKENT(ap));
1.27      mhitch    207:                vap->va_bytes = fblks * amp->dbsize;
1.2       chopps    208:                vap->va_size = ap->fsize;
1.21      chopps    209:
1.27      mhitch    210:                vap->va_blocksize = amp->dbsize;
1.1       chopps    211:        }
                    212: #ifdef ADOSFS_DIAGNOSTIC
1.32      christos  213:        printf(" 0)");
1.1       chopps    214: #endif
                    215:        return(0);
                    216: }
                    217: /*
                    218:  * are things locked??? they need to be to avoid this being
                    219:  * deleted or changed (data block pointer blocks moving about.)
                    220:  */
                    221: int
1.25      christos  222: adosfs_read(v)
                    223:        void *v;
                    224: {
1.6       chopps    225:        struct vop_read_args /* {
                    226:                struct vnode *a_vp;
                    227:                struct uio *a_uio;
                    228:                int a_ioflag;
                    229:                struct ucred *a_cred;
1.25      christos  230:        } */ *sp = v;
1.55      chs       231:        struct vnode *vp = sp->a_vp;
1.20      mycroft   232:        struct adosfsmount *amp;
1.1       chopps    233:        struct anode *ap;
1.6       chopps    234:        struct uio *uio;
                    235:        struct buf *bp;
1.25      christos  236:        daddr_t lbn;
1.1       chopps    237:        int size, diff, error;
                    238:        long n, on;
                    239:
                    240: #ifdef ADOSFS_DIAGNOSTIC
1.6       chopps    241:        advopprint(sp);
1.1       chopps    242: #endif
                    243:        error = 0;
1.6       chopps    244:        uio = sp->a_uio;
                    245:        ap = VTOA(sp->a_vp);
1.1       chopps    246:        amp = ap->amp;
                    247:        /*
                    248:         * Return EOF for character devices, EIO for others
                    249:         */
1.6       chopps    250:        if (sp->a_vp->v_type != VREG) {
1.1       chopps    251:                error = EIO;
                    252:                goto reterr;
                    253:        }
                    254:        if (uio->uio_resid == 0)
                    255:                goto reterr;
                    256:        if (uio->uio_offset < 0) {
                    257:                error = EINVAL;
                    258:                goto reterr;
                    259:        }
                    260:
                    261:        /*
                    262:         * to expensive to let general algorithm figure out that
                    263:         * we are beyond the file.  Do it now.
                    264:         */
                    265:        if (uio->uio_offset >= ap->fsize)
                    266:                goto reterr;
                    267:
                    268:        /*
                    269:         * taken from ufs_read()
                    270:         */
1.55      chs       271:
1.58      chs       272:        if (vp->v_type == VREG && IS_FFS(amp)) {
1.55      chs       273:                error = 0;
                    274:                while (uio->uio_resid > 0) {
                    275:                        void *win;
1.57      chs       276:                        vsize_t bytelen = MIN(ap->fsize - uio->uio_offset,
1.55      chs       277:                                              uio->uio_resid);
                    278:
                    279:                        if (bytelen == 0) {
                    280:                                break;
                    281:                        }
                    282:                        win = ubc_alloc(&vp->v_uvm.u_obj, uio->uio_offset,
                    283:                                        &bytelen, UBC_READ);
                    284:                        error = uiomove(win, bytelen, uio);
                    285:                        ubc_release(win, 0);
                    286:                        if (error) {
                    287:                                break;
                    288:                        }
                    289:                }
                    290:                goto out;
                    291:        }
                    292:
1.1       chopps    293:        do {
1.27      mhitch    294:                size = amp->dbsize;
1.1       chopps    295:                lbn = uio->uio_offset / size;
                    296:                on = uio->uio_offset % size;
1.57      chs       297:                n = MIN(size - on, uio->uio_resid);
1.1       chopps    298:                diff = ap->fsize - uio->uio_offset;
                    299:                /*
                    300:                 * check for EOF
                    301:                 */
                    302:                if (diff <= 0)
                    303:                        return(0);
                    304:                if (diff < n)
                    305:                        n = diff;
                    306:                /*
                    307:                 * read ahead could possibly be worth something
                    308:                 * but not much as ados makes little attempt to
                    309:                 * make things contigous
                    310:                 */
1.49      is        311:                error = bread(sp->a_vp, lbn * amp->bsize / DEV_BSIZE,
1.27      mhitch    312:                              amp->bsize, NOCRED, &bp);
1.47      bouyer    313:                if (error) {
                    314:                        brelse(bp);
                    315:                        goto reterr;
                    316:                }
1.6       chopps    317:                sp->a_vp->v_lastr = lbn;
1.27      mhitch    318:
                    319:                if (!IS_FFS(amp)) {
                    320:                        if (bp->b_resid > 0)
                    321:                                error = EIO; /* OFS needs the complete block */
                    322:                        else if (adoswordn(bp, 0) != BPT_DATA) {
                    323: #ifdef DIAGNOSTIC
1.32      christos  324:                                printf("adosfs: bad primary type blk %ld\n",
1.49      is        325:                                    bp->b_blkno / (amp->bsize / DEV_BSIZE));
1.27      mhitch    326: #endif
1.58      chs       327:                                error = EINVAL;
                    328:                        } else if (adoscksum(bp, ap->nwords)) {
1.27      mhitch    329: #ifdef DIAGNOSTIC
1.32      christos  330:                                printf("adosfs: blk %ld failed cksum.\n",
1.49      is        331:                                    bp->b_blkno / (amp->bsize / DEV_BSIZE));
1.27      mhitch    332: #endif
1.58      chs       333:                                error = EINVAL;
1.27      mhitch    334:                        }
                    335:                }
                    336:
1.1       chopps    337:                if (error) {
                    338:                        brelse(bp);
                    339:                        goto reterr;
                    340:                }
                    341: #ifdef ADOSFS_DIAGNOSTIC
1.32      christos  342:                printf(" %d+%d-%d+%d", lbn, on, lbn, n);
1.1       chopps    343: #endif
1.57      chs       344:                n = MIN(n, size - bp->b_resid);
1.53      thorpej   345:                error = uiomove(bp->b_data + on +
1.27      mhitch    346:                                amp->bsize - amp->dbsize, (int)n, uio);
1.1       chopps    347:                brelse(bp);
                    348:        } while (error == 0 && uio->uio_resid > 0 && n != 0);
1.55      chs       349:
                    350: out:
1.1       chopps    351: reterr:
                    352: #ifdef ADOSFS_DIAGNOSTIC
1.32      christos  353:        printf(" %d)", error);
1.1       chopps    354: #endif
                    355:        return(error);
                    356: }
                    357:
                    358: int
1.25      christos  359: adosfs_write(v)
                    360:        void *v;
                    361: {
                    362: #ifdef ADOSFS_DIAGNOSTIC
1.6       chopps    363:        struct vop_write_args /* {
                    364:                struct vnode *a_vp;
                    365:                struct uio *a_uio;
                    366:                int a_ioflag;
                    367:                struct ucred *a_cred;
1.25      christos  368:        } */ *sp = v;
1.6       chopps    369:        advopprint(sp);
1.32      christos  370:        printf(" EOPNOTSUPP)");
1.1       chopps    371: #endif
                    372:        return(EOPNOTSUPP);
                    373: }
                    374:
                    375: /*
                    376:  * Just call the device strategy routine
                    377:  */
                    378: int
1.25      christos  379: adosfs_strategy(v)
                    380:        void *v;
                    381: {
1.6       chopps    382:        struct vop_strategy_args /* {
                    383:                struct buf *a_bp;
1.25      christos  384:        } */ *sp = v;
1.1       chopps    385:        struct buf *bp;
                    386:        struct anode *ap;
                    387:        struct vnode *vp;
                    388:        int error;
                    389:
                    390: #ifdef ADOSFS_DIAGNOSTIC
1.6       chopps    391:        advopprint(sp);
1.1       chopps    392: #endif
                    393:        error = 0;
1.6       chopps    394:        bp = sp->a_bp;
1.1       chopps    395:        if (bp->b_vp == NULL) {
                    396:                bp->b_flags |= B_ERROR;
                    397:                biodone(bp);
                    398:                error = EIO;
                    399:                goto reterr;
                    400:        }
                    401:        vp = bp->b_vp;
                    402:        ap = VTOA(vp);
1.6       chopps    403:        if (bp->b_blkno == bp->b_lblkno) {
1.25      christos  404:                error = VOP_BMAP(vp, bp->b_lblkno, NULL, &bp->b_blkno, NULL);
                    405:                if (error) {
1.1       chopps    406:                        bp->b_flags |= B_ERROR;
                    407:                        biodone(bp);
                    408:                        goto reterr;
                    409:                }
1.6       chopps    410:        }
                    411:        if ((long)bp->b_blkno == -1) {
                    412:                biodone(bp);
                    413:                error = 0;
                    414:                goto reterr;
                    415:        }
1.1       chopps    416:        vp = ap->amp->devvp;
                    417:        bp->b_dev = vp->v_rdev;
1.6       chopps    418:        VOCALL(vp->v_op, VOFFSET(vop_strategy), sp);
1.1       chopps    419: reterr:
                    420: #ifdef ADOSFS_DIAGNOSTIC
1.32      christos  421:        printf(" %d)", error);
1.1       chopps    422: #endif
                    423:        return(error);
                    424: }
                    425:
1.24      mycroft   426: int
1.25      christos  427: adosfs_link(v)
                    428:        void *v;
                    429: {
1.24      mycroft   430:        struct vop_link_args /* {
                    431:                struct vnode *a_dvp;
                    432:                struct vnode *a_vp;
                    433:                struct componentname *a_cnp;
1.25      christos  434:        } */ *ap = v;
1.24      mycroft   435:
                    436:        VOP_ABORTOP(ap->a_dvp, ap->a_cnp);
                    437:        vput(ap->a_dvp);
                    438:        return (EROFS);
                    439: }
                    440:
                    441: int
1.25      christos  442: adosfs_symlink(v)
                    443:        void *v;
                    444: {
1.24      mycroft   445:        struct vop_symlink_args /* {
                    446:                struct vnode *a_dvp;
                    447:                struct vnode **a_vpp;
                    448:                struct componentname *a_cnp;
                    449:                struct vattr *a_vap;
                    450:                char *a_target;
1.25      christos  451:        } */ *ap = v;
1.24      mycroft   452:
                    453:        VOP_ABORTOP(ap->a_dvp, ap->a_cnp);
                    454:        vput(ap->a_dvp);
                    455:        return (EROFS);
                    456: }
                    457:
1.1       chopps    458: /*
                    459:  * Wait until the vnode has finished changing state.
                    460:  */
                    461: int
1.25      christos  462: adosfs_bmap(v)
                    463:        void *v;
                    464: {
1.6       chopps    465:        struct vop_bmap_args /* {
                    466:                struct vnode *a_vp;
                    467:                daddr_t  a_bn;
                    468:                struct vnode **a_vpp;
                    469:                daddr_t *a_bnp;
                    470:                int *a_runp;
1.25      christos  471:        } */ *sp = v;
1.1       chopps    472:        struct anode *ap;
                    473:        struct buf *flbp;
1.9       chopps    474:        long nb, flblk, flblkoff, fcnt;
1.6       chopps    475:        daddr_t *bnp;
                    476:        daddr_t bn;
1.1       chopps    477:        int error;
                    478:
                    479: #ifdef ADOSFS_DIAGNOSTIC
1.6       chopps    480:        advopprint(sp);
1.1       chopps    481: #endif
1.27      mhitch    482:        ap = VTOA(sp->a_vp);
1.49      is        483:        bn = sp->a_bn / (ap->amp->bsize / DEV_BSIZE);
1.6       chopps    484:        bnp = sp->a_bnp;
1.58      chs       485:        if (sp->a_runp) {
                    486:                *sp->a_runp = 0;
                    487:        }
1.1       chopps    488:        error = 0;
                    489:
1.6       chopps    490:        if (sp->a_vpp != NULL)
                    491:                *sp->a_vpp = ap->amp->devvp;
                    492:        if (bnp == NULL)
                    493:                goto reterr;
1.1       chopps    494:        if (bn < 0) {
                    495:                error = EFBIG;
                    496:                goto reterr;
                    497:        }
1.6       chopps    498:        if (sp->a_vp->v_type != VREG) {
1.1       chopps    499:                error = EINVAL;
                    500:                goto reterr;
                    501:        }
                    502:
                    503:        /*
                    504:         * walk the chain of file list blocks until we find
                    505:         * the one that will yield the block pointer we need.
                    506:         */
                    507:        if (ap->type == AFILE)
                    508:                nb = ap->block;                 /* pointer to ourself */
                    509:        else if (ap->type == ALFILE)
                    510:                nb = ap->linkto;                /* pointer to real file */
                    511:        else {
                    512:                error = EINVAL;
                    513:                goto reterr;
                    514:        }
                    515:
                    516:        flblk = bn / ANODENDATBLKENT(ap);
                    517:        flbp = NULL;
1.9       chopps    518:
                    519:        /*
                    520:         * check last indirect block cache
                    521:         */
1.18      chopps    522:        if (flblk < ap->lastlindblk)
1.9       chopps    523:                fcnt = 0;
                    524:        else {
                    525:                flblk -= ap->lastlindblk;
                    526:                fcnt = ap->lastlindblk;
                    527:                nb = ap->lastindblk;
                    528:        }
1.1       chopps    529:        while (flblk >= 0) {
                    530:                if (flbp)
                    531:                        brelse(flbp);
                    532:                if (nb == 0) {
                    533: #ifdef DIAGNOSTIC
1.32      christos  534:                        printf("adosfs: bad file list chain.\n");
1.1       chopps    535: #endif
                    536:                        error = EINVAL;
                    537:                        goto reterr;
                    538:                }
1.49      is        539:                error = bread(ap->amp->devvp, nb * ap->amp->bsize / DEV_BSIZE,
1.27      mhitch    540:                              ap->amp->bsize, NOCRED, &flbp);
1.47      bouyer    541:                if (error) {
                    542:                        brelse(flbp);
1.1       chopps    543:                        goto reterr;
1.47      bouyer    544:                }
1.1       chopps    545:                if (adoscksum(flbp, ap->nwords)) {
                    546: #ifdef DIAGNOSTIC
1.32      christos  547:                        printf("adosfs: blk %ld failed cksum.\n", nb);
1.1       chopps    548: #endif
                    549:                        brelse(flbp);
                    550:                        error = EINVAL;
                    551:                        goto reterr;
                    552:                }
1.9       chopps    553:                /*
                    554:                 * update last indirect block cache
                    555:                 */
                    556:                ap->lastlindblk = fcnt++;
                    557:                ap->lastindblk = nb;
                    558:
1.1       chopps    559:                nb = adoswordn(flbp, ap->nwords - 2);
                    560:                flblk--;
                    561:        }
                    562:        /*
                    563:         * calculate offset of block number in table.  The table starts
                    564:         * at nwords - 51 and goes to offset 6 or less if indicated by the
                    565:         * valid table entries stored at offset ADBI_NBLKTABENT.
                    566:         */
                    567:        flblkoff = bn % ANODENDATBLKENT(ap);
                    568:        if (flblkoff < adoswordn(flbp, 2 /* ADBI_NBLKTABENT */)) {
                    569:                flblkoff = (ap->nwords - 51) - flblkoff;
1.49      is        570:                *bnp = adoswordn(flbp, flblkoff) * ap->amp->bsize / DEV_BSIZE;
1.1       chopps    571:        } else {
                    572: #ifdef DIAGNOSTIC
1.32      christos  573:                printf("flblk offset %ld too large in lblk %ld blk %d\n",
1.49      is        574:                    flblkoff, bn / (ap->amp->bsize / DEV_BSIZE), flbp->b_blkno);
1.1       chopps    575: #endif
                    576:                error = EINVAL;
                    577:        }
                    578:        brelse(flbp);
                    579: reterr:
                    580: #ifdef ADOSFS_DIAGNOSTIC
                    581:        if (error == 0 && bnp)
1.32      christos  582:                printf(" %d => %d", bn, *bnp);
                    583:        printf(" %d)", error);
1.1       chopps    584: #endif
                    585:        return(error);
                    586: }
                    587:
                    588: /*
                    589:  * Print out the contents of a adosfs vnode.
                    590:  */
                    591: /* ARGSUSED */
                    592: int
1.25      christos  593: adosfs_print(v)
                    594:        void *v;
                    595: {
                    596: #if 0
1.6       chopps    597:        struct vop_print_args /* {
                    598:                struct vnode *a_vp;
1.25      christos  599:        } */ *sp = v;
                    600: #endif
1.1       chopps    601:        return(0);
                    602: }
                    603:
                    604: struct adirent {
                    605:        u_long  fileno;
                    606:        u_short reclen;
1.6       chopps    607:        char    type;
                    608:        char    namlen;
1.1       chopps    609:        char    name[32];       /* maxlen of 30 plus 2 NUL's */
                    610: };
                    611:
                    612: int
1.25      christos  613: adosfs_readdir(v)
                    614:        void *v;
                    615: {
1.6       chopps    616:        struct vop_readdir_args /* {
                    617:                struct vnode *a_vp;
                    618:                struct uio *a_uio;
                    619:                struct ucred *a_cred;
                    620:                int *a_eofflag;
1.37      fvdl      621:                off_t **a_cookies;
                    622:                int *a_ncookies;
1.25      christos  623:        } */ *sp = v;
1.1       chopps    624:        int error, useri, chainc, hashi, scanned, uavail;
                    625:        struct adirent ad, *adp;
                    626:        struct anode *pap, *ap;
1.20      mycroft   627:        struct adosfsmount *amp;
1.6       chopps    628:        struct vnode *vp;
                    629:        struct uio *uio;
1.25      christos  630:        u_long nextbn;
1.37      fvdl      631:        off_t uoff, *cookies = NULL;
                    632:        int ncookies = 0;
1.1       chopps    633:
                    634: #ifdef ADOSFS_DIAGNOSTIC
1.6       chopps    635:        advopprint(sp);
1.1       chopps    636: #endif
1.6       chopps    637:        if (sp->a_vp->v_type != VDIR) {
1.1       chopps    638:                error = ENOTDIR;
                    639:                goto reterr;
                    640:        }
1.37      fvdl      641:
1.6       chopps    642:        uio = sp->a_uio;
1.1       chopps    643:        uoff = uio->uio_offset;
                    644:        if (uoff < 0) {
                    645:                error = EINVAL;
                    646:                goto reterr;
                    647:        }
                    648:
1.6       chopps    649:        pap = VTOA(sp->a_vp);
1.1       chopps    650:        amp = pap->amp;
                    651:        adp = &ad;
                    652:        error = nextbn = hashi = chainc = scanned = 0;
                    653:        uavail = uio->uio_resid / sizeof(ad);
                    654:        useri = uoff / sizeof(ad);
                    655:
1.2       chopps    656:        /*
                    657:         * if no slots available or offset requested is not on a slot boundry
                    658:         */
                    659:        if (uavail < 1 || uoff % sizeof(ad)) {
                    660:                error = EINVAL;
                    661:                goto reterr;
                    662:        }
                    663:
1.37      fvdl      664:        if (sp->a_ncookies) {
                    665:                ncookies = 0;
1.54      thorpej   666:                cookies = malloc(sizeof (off_t) * uavail, M_TEMP, M_WAITOK);
1.37      fvdl      667:                *sp->a_cookies = cookies;
                    668:        }
                    669:
                    670:        while (uavail) {
1.1       chopps    671:                if (hashi == pap->ntabent) {
1.6       chopps    672:                        *sp->a_eofflag = 1;
1.1       chopps    673:                        break;
                    674:                }
                    675:                if (pap->tab[hashi] == 0) {
                    676:                        hashi++;
                    677:                        continue;
                    678:                }
1.2       chopps    679:                if (nextbn == 0)
1.1       chopps    680:                        nextbn = pap->tab[hashi];
                    681:
                    682:                /*
                    683:                 * first determine if we can skip this chain
                    684:                 */
                    685:                if (chainc == 0) {
                    686:                        int skip;
                    687:
                    688:                        skip = useri - scanned;
                    689:                        if (pap->tabi[hashi] > 0 && pap->tabi[hashi] <= skip) {
                    690:                                scanned += pap->tabi[hashi];
                    691:                                hashi++;
1.2       chopps    692:                                nextbn = 0;
1.1       chopps    693:                                continue;
                    694:                        }
                    695:                }
                    696:
                    697:                /*
                    698:                 * now [continue to] walk the chain
                    699:                 */
                    700:                ap = NULL;
                    701:                do {
1.25      christos  702:                        error = VFS_VGET(amp->mp, (ino_t)nextbn, &vp);
                    703:                        if (error)
1.1       chopps    704:                                goto reterr;
1.6       chopps    705:                        ap = VTOA(vp);
1.1       chopps    706:                        scanned++;
                    707:                        chainc++;
                    708:                        nextbn = ap->hashf;
                    709:
                    710:                        /*
                    711:                         * check for end of chain.
                    712:                         */
                    713:                        if (nextbn == 0) {
                    714:                                pap->tabi[hashi] = chainc;
                    715:                                hashi++;
1.2       chopps    716:                                chainc = 0;
1.1       chopps    717:                        } else if (pap->tabi[hashi] <= 0 &&
                    718:                            -chainc < pap->tabi[hashi])
                    719:                                pap->tabi[hashi] = -chainc;
                    720:
1.2       chopps    721:                        if (useri >= scanned) {
1.6       chopps    722:                                vput(vp);
1.1       chopps    723:                                ap = NULL;
                    724:                        }
                    725:                } while (ap == NULL && nextbn != 0);
                    726:
                    727:                /*
                    728:                 * we left the loop but without a result so do main over.
                    729:                 */
                    730:                if (ap == NULL)
                    731:                        continue;
                    732:                /*
                    733:                 * Fill in dirent record
                    734:                 */
1.42      perry     735:                memset(adp, 0, sizeof(struct adirent));
1.1       chopps    736:                adp->fileno = ap->block;
1.6       chopps    737:                /*
                    738:                 * this deserves an function in kern/vfs_subr.c
                    739:                 */
                    740:                switch (ATOV(ap)->v_type) {
                    741:                case VREG:
                    742:                        adp->type = DT_REG;
                    743:                        break;
                    744:                case VDIR:
                    745:                        adp->type = DT_DIR;
                    746:                        break;
                    747:                case VLNK:
                    748:                        adp->type = DT_LNK;
                    749:                        break;
                    750:                default:
                    751:                        adp->type = DT_UNKNOWN;
                    752:                        break;
                    753:                }
1.1       chopps    754:                adp->reclen = sizeof(struct adirent);
                    755:                adp->namlen = strlen(ap->name);
1.42      perry     756:                memcpy(adp->name, ap->name, adp->namlen);
1.6       chopps    757:                vput(vp);
1.1       chopps    758:
1.25      christos  759:                error = uiomove((caddr_t) adp, sizeof(struct adirent), uio);
1.1       chopps    760:                if (error)
                    761:                        break;
1.37      fvdl      762:                if (sp->a_ncookies) {
                    763:                        *cookies++ = uoff;
                    764:                        ncookies++;
1.1       chopps    765:                }
                    766:                uoff += sizeof(struct adirent);
                    767:                useri++;
                    768:                uavail--;
                    769:        }
1.2       chopps    770: #if doesnt_uiomove_handle_this
1.1       chopps    771:        uio->uio_offset = uoff;
1.2       chopps    772: #endif
1.1       chopps    773: reterr:
                    774: #ifdef ADOSFS_DIAGNOSTIC
1.32      christos  775:        printf(" %d)", error);
1.1       chopps    776: #endif
1.37      fvdl      777:        if (sp->a_ncookies) {
                    778:                if (error) {
1.54      thorpej   779:                        free(*sp->a_cookies, M_TEMP);
1.37      fvdl      780:                        *sp->a_ncookies = 0;
                    781:                        *sp->a_cookies = NULL;
                    782:                } else
                    783:                        *sp->a_ncookies = ncookies;
                    784:        }
1.1       chopps    785:        return(error);
                    786: }
                    787:
                    788:
                    789: int
1.25      christos  790: adosfs_access(v)
                    791:        void *v;
                    792: {
1.6       chopps    793:        struct vop_access_args /* {
                    794:                struct vnode *a_vp;
                    795:                int  a_mode;
                    796:                struct ucred *a_cred;
                    797:                struct proc *a_p;
1.25      christos  798:        } */ *sp = v;
1.1       chopps    799:        struct anode *ap;
1.37      fvdl      800:        struct vnode *vp = sp->a_vp;
1.19      chopps    801:        int error;
1.1       chopps    802:
                    803: #ifdef ADOSFS_DIAGNOSTIC
1.6       chopps    804:        advopprint(sp);
1.1       chopps    805: #endif
                    806:
1.37      fvdl      807:        ap = VTOA(vp);
1.1       chopps    808: #ifdef DIAGNOSTIC
1.37      fvdl      809:        if (!VOP_ISLOCKED(vp)) {
1.6       chopps    810:                vprint("adosfs_access: not locked", sp->a_vp);
1.1       chopps    811:                panic("adosfs_access: not locked");
                    812:        }
                    813: #endif
1.37      fvdl      814:        /*
                    815:         * Disallow write attempts unless the file is a socket,
                    816:         * fifo, or a block or character device resident on the
                    817:         * file system.
                    818:         */
                    819:        if (sp->a_mode & VWRITE) {
                    820:                switch (vp->v_type) {
                    821:                case VDIR:
                    822:                case VLNK:
                    823:                case VREG:
                    824:                        return (EROFS);
                    825:                default:
                    826:                        break;
                    827:                }
                    828:        }
1.1       chopps    829: #ifdef QUOTA
                    830: #endif
1.35      veego     831:        error = vaccess(sp->a_vp->v_type, adunixprot(ap->adprot) & ap->amp->mask,
1.34      mycroft   832:            ap->uid, ap->gid, sp->a_mode, sp->a_cred);
1.1       chopps    833: #ifdef ADOSFS_DIAGNOSTIC
1.32      christos  834:        printf(" %d)", error);
1.1       chopps    835: #endif
                    836:        return(error);
                    837: }
                    838:
                    839: int
1.25      christos  840: adosfs_readlink(v)
                    841:        void *v;
                    842: {
1.6       chopps    843:        struct vop_readlink_args /* {
                    844:                struct vnode *a_vp;
                    845:                struct uio *a_uio;
                    846:                struct ucred *a_cred;
1.25      christos  847:        } */ *sp = v;
1.6       chopps    848:        struct anode *ap;
                    849:        int error;
                    850:
1.1       chopps    851: #ifdef ADOSFS_DIAGNOSTIC
1.6       chopps    852:        advopprint(sp);
1.1       chopps    853: #endif
1.6       chopps    854:        ap = VTOA(sp->a_vp);
1.45      kleink    855:        error = uiomove(ap->slinkto, strlen(ap->slinkto), sp->a_uio);
1.1       chopps    856: #ifdef ADOSFS_DIAGNOSTIC
1.32      christos  857:        printf(" %d)", error);
1.1       chopps    858: #endif
1.45      kleink    859:        return (error);
1.1       chopps    860: }
                    861:
                    862: /*ARGSUSED*/
                    863: int
1.25      christos  864: adosfs_inactive(v)
                    865:        void *v;
                    866: {
1.6       chopps    867:        struct vop_inactive_args /* {
                    868:                struct vnode *a_vp;
1.37      fvdl      869:                struct proc *a_p;
1.25      christos  870:        } */ *sp = v;
1.37      fvdl      871:        struct vnode *vp = sp->a_vp;
                    872:        struct proc *p = sp->a_p;
1.1       chopps    873: #ifdef ADOSFS_DIAGNOSTIC
1.6       chopps    874:        advopprint(sp);
1.1       chopps    875: #endif
1.37      fvdl      876:        VOP_UNLOCK(vp, 0);
                    877:        /* XXX this needs to check if file was deleted */
                    878:        vrecycle(vp, (struct simplelock *)0, p);
1.1       chopps    879:
                    880: #ifdef ADOSFS_DIAGNOSTIC
1.32      christos  881:        printf(" 0)");
1.1       chopps    882: #endif
                    883:        return(0);
                    884: }
                    885:
1.6       chopps    886: /*
                    887:  * the kernel wants its vnode back.
                    888:  * no lock needed we are being called from vclean()
                    889:  */
1.1       chopps    890: int
1.25      christos  891: adosfs_reclaim(v)
                    892:        void *v;
                    893: {
1.6       chopps    894:        struct vop_reclaim_args /* {
                    895:                struct vnode *a_vp;
1.25      christos  896:        } */ *sp = v;
1.1       chopps    897:        struct vnode *vp;
                    898:        struct anode *ap;
                    899:
                    900: #ifdef ADOSFS_DIAGNOSTIC
1.32      christos  901:        printf("(reclaim 0)");
1.1       chopps    902: #endif
1.6       chopps    903:        vp = sp->a_vp;
1.1       chopps    904:        ap = VTOA(vp);
1.6       chopps    905:        LIST_REMOVE(ap, link);
                    906:        cache_purge(vp);
                    907:        if (vp->v_type == VDIR && ap->tab)
                    908:                free(ap->tab, M_ANODE);
                    909:        else if (vp->v_type == VLNK && ap->slinkto)
                    910:                free(ap->slinkto, M_ANODE);
1.46      thorpej   911:        pool_put(&adosfs_node_pool, ap);
1.6       chopps    912:        vp->v_data = NULL;
                    913:        return(0);
1.1       chopps    914: }
                    915:
                    916:
1.6       chopps    917: /*
                    918:  * POSIX pathconf info, grabbed from kern/u fs, probably need to
                    919:  * investigate exactly what each return type means as they are probably
                    920:  * not valid currently
                    921:  */
1.25      christos  922: int
                    923: adosfs_pathconf(v)
                    924:        void *v;
                    925: {
1.6       chopps    926:        struct vop_pathconf_args /* {
                    927:                struct vnode *a_vp;
                    928:                int a_name;
1.12      cgd       929:                register_t *a_retval;
1.25      christos  930:        } */ *sp = v;
1.1       chopps    931:
1.6       chopps    932:        switch (sp->a_name) {
                    933:        case _PC_LINK_MAX:
                    934:                *sp->a_retval = LINK_MAX;
                    935:                return (0);
                    936:        case _PC_MAX_CANON:
                    937:                *sp->a_retval = MAX_CANON;
                    938:                return (0);
                    939:        case _PC_MAX_INPUT:
                    940:                *sp->a_retval = MAX_INPUT;
                    941:                return (0);
                    942:        case _PC_PIPE_BUF:
                    943:                *sp->a_retval = PIPE_BUF;
                    944:                return (0);
                    945:        case _PC_CHOWN_RESTRICTED:
                    946:                *sp->a_retval = 1;
                    947:                return (0);
                    948:        case _PC_VDISABLE:
                    949:                *sp->a_retval = _POSIX_VDISABLE;
1.41      kleink    950:                return (0);
                    951:        case _PC_SYNC_IO:
                    952:                *sp->a_retval = 1;
1.48      kleink    953:                return (0);
                    954:        case _PC_FILESIZEBITS:
                    955:                *sp->a_retval = 32;
1.6       chopps    956:                return (0);
                    957:        default:
                    958:                return (EINVAL);
                    959:        }
                    960:        /* NOTREACHED */
1.1       chopps    961: }

CVSweb <webmaster@jp.NetBSD.org>