The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/fs/adosfs/advnops.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

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

Cache object: 54517e5ee0a698fda7fe552c09b9cf1d


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.