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.8 2004/01/26 10:39:29 hannken 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.8 2004/01/26 10:39:29 hannken 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_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                         vsize_t bytelen = MIN(ap->fsize - uio->uio_offset,
  281                                               uio->uio_resid);
  282 
  283                         if (bytelen == 0) {
  284                                 break;
  285                         }
  286                         win = ubc_alloc(&vp->v_uobj, uio->uio_offset,
  287                                         &bytelen, UBC_READ);
  288                         error = uiomove(win, bytelen, uio);
  289                         ubc_release(win, 0);
  290                         if (error) {
  291                                 break;
  292                         }
  293                 }
  294                 goto out;
  295         }
  296 
  297         do {
  298                 size = amp->dbsize;
  299                 lbn = uio->uio_offset / size;
  300                 on = uio->uio_offset % size;
  301                 n = MIN(size - on, uio->uio_resid);
  302                 diff = ap->fsize - uio->uio_offset;
  303                 /* 
  304                  * check for EOF
  305                  */
  306                 if (diff <= 0)
  307                         return(0);
  308                 if (diff < n)
  309                         n = diff;
  310                 /*
  311                  * read ahead could possibly be worth something
  312                  * but not much as ados makes little attempt to 
  313                  * make things contigous
  314                  */
  315                 error = bread(sp->a_vp, lbn, amp->bsize, NOCRED, &bp);
  316                 if (error) {
  317                         brelse(bp);
  318                         goto reterr;
  319                 }
  320                 if (!IS_FFS(amp)) {
  321                         if (bp->b_resid > 0)
  322                                 error = EIO; /* OFS needs the complete block */
  323                         else if (adoswordn(bp, 0) != BPT_DATA) {
  324 #ifdef DIAGNOSTIC
  325                                 printf("adosfs: bad primary type blk %" PRId64 "\n",
  326                                     bp->b_blkno / (amp->bsize / DEV_BSIZE));
  327 #endif
  328                                 error = EINVAL;
  329                         } else if (adoscksum(bp, ap->nwords)) {
  330 #ifdef DIAGNOSTIC
  331                                 printf("adosfs: blk %" PRId64 " failed cksum.\n",
  332                                     bp->b_blkno / (amp->bsize / DEV_BSIZE));
  333 #endif
  334                                 error = EINVAL;
  335                         }
  336                 }
  337 
  338                 if (error) {
  339                         brelse(bp);
  340                         goto reterr;
  341                 }
  342 #ifdef ADOSFS_DIAGNOSTIC
  343                 printf(" %d+%d-%d+%d", lbn, on, lbn, n);
  344 #endif
  345                 n = MIN(n, size - bp->b_resid);
  346                 error = uiomove(bp->b_data + on +
  347                                 amp->bsize - amp->dbsize, (int)n, uio);
  348                 brelse(bp);
  349         } while (error == 0 && uio->uio_resid > 0 && n != 0);
  350 
  351 out:
  352 reterr:
  353 #ifdef ADOSFS_DIAGNOSTIC
  354         printf(" %d)", error);
  355 #endif
  356         return(error);
  357 }
  358 
  359 int
  360 adosfs_write(v)
  361         void *v;
  362 {
  363 #ifdef ADOSFS_DIAGNOSTIC
  364         struct vop_write_args /* {
  365                 struct vnode *a_vp;
  366                 struct uio *a_uio;
  367                 int a_ioflag;
  368                 struct ucred *a_cred;
  369         } */ *sp = v;
  370         advopprint(sp);
  371         printf(" EOPNOTSUPP)");
  372 #endif
  373         return(EOPNOTSUPP);
  374 }
  375 
  376 /*
  377  * Just call the device strategy routine
  378  */
  379 int
  380 adosfs_strategy(v)
  381         void *v;
  382 {
  383         struct vop_strategy_args /* {
  384                 struct vnode *a_vp;
  385                 struct buf *a_bp;
  386         } */ *sp = v;
  387         struct buf *bp;
  388         struct anode *ap;
  389         struct vnode *vp;
  390         int error;
  391 
  392 #ifdef ADOSFS_DIAGNOSTIC
  393         advopprint(sp);
  394 #endif
  395         bp = sp->a_bp;
  396         if (bp->b_vp == NULL) {
  397                 bp->b_flags |= B_ERROR;
  398                 biodone(bp);
  399                 error = EIO;
  400                 goto reterr;
  401         }
  402         vp = sp->a_vp;
  403         ap = VTOA(vp);
  404         if (bp->b_blkno == bp->b_lblkno) {
  405                 error = VOP_BMAP(vp, bp->b_lblkno, NULL, &bp->b_blkno, NULL);
  406                 if (error) {
  407                         bp->b_flags |= B_ERROR;
  408                         biodone(bp);
  409                         goto reterr;
  410                 }
  411         }
  412         if ((long)bp->b_blkno == -1) {
  413                 biodone(bp);
  414                 error = 0;
  415                 goto reterr;
  416         }
  417         vp = ap->amp->devvp;
  418         error = VOP_STRATEGY(vp, bp);
  419 reterr:
  420 #ifdef ADOSFS_DIAGNOSTIC
  421         printf(" %d)", error);
  422 #endif
  423         return(error);
  424 }
  425 
  426 int
  427 adosfs_link(v) 
  428         void *v;
  429 {
  430         struct vop_link_args /* {
  431                 struct vnode *a_dvp;
  432                 struct vnode *a_vp;  
  433                 struct componentname *a_cnp;
  434         } */ *ap = v;
  435  
  436         VOP_ABORTOP(ap->a_dvp, ap->a_cnp);
  437         vput(ap->a_dvp);
  438         return (EROFS);
  439 }
  440 
  441 int
  442 adosfs_symlink(v)
  443         void *v;
  444 {
  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;
  451         } */ *ap = v;
  452   
  453         VOP_ABORTOP(ap->a_dvp, ap->a_cnp);
  454         vput(ap->a_dvp);
  455         return (EROFS);
  456 }
  457 
  458 /*
  459  * Wait until the vnode has finished changing state.
  460  */
  461 int
  462 adosfs_bmap(v)
  463         void *v;
  464 {
  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;
  471         } */ *sp = v;
  472         struct anode *ap;
  473         struct buf *flbp;
  474         long nb, flblk, flblkoff, fcnt;
  475         daddr_t *bnp;
  476         daddr_t bn;
  477         int error; 
  478 
  479 #ifdef ADOSFS_DIAGNOSTIC
  480         advopprint(sp);
  481 #endif
  482         ap = VTOA(sp->a_vp);
  483         bn = sp->a_bn;
  484         bnp = sp->a_bnp;
  485         if (sp->a_runp) {
  486                 *sp->a_runp = 0;
  487         }
  488         error = 0;
  489 
  490         if (sp->a_vpp != NULL)
  491                 *sp->a_vpp = ap->amp->devvp;
  492         if (bnp == NULL)
  493                 goto reterr;
  494         if (bn < 0) {
  495                 error = EFBIG;
  496                 goto reterr;
  497         }
  498         if (sp->a_vp->v_type != VREG) {
  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;
  518 
  519         /*
  520          * check last indirect block cache
  521          */
  522         if (flblk < ap->lastlindblk) 
  523                 fcnt = 0;
  524         else {
  525                 flblk -= ap->lastlindblk;
  526                 fcnt = ap->lastlindblk;
  527                 nb = ap->lastindblk;
  528         }
  529         while (flblk >= 0) {
  530                 if (flbp)
  531                         brelse(flbp);
  532                 if (nb == 0) {
  533 #ifdef DIAGNOSTIC
  534                         printf("adosfs: bad file list chain.\n");
  535 #endif
  536                         error = EINVAL;
  537                         goto reterr;
  538                 }
  539                 error = bread(ap->amp->devvp, nb * ap->amp->bsize / DEV_BSIZE,
  540                               ap->amp->bsize, NOCRED, &flbp);
  541                 if (error) {
  542                         brelse(flbp);
  543                         goto reterr;
  544                 }
  545                 if (adoscksum(flbp, ap->nwords)) {
  546 #ifdef DIAGNOSTIC
  547                         printf("adosfs: blk %ld failed cksum.\n", nb);
  548 #endif
  549                         brelse(flbp);
  550                         error = EINVAL;
  551                         goto reterr;
  552                 }
  553                 /*
  554                  * update last indirect block cache
  555                  */
  556                 ap->lastlindblk = fcnt++;
  557                 ap->lastindblk = nb;
  558 
  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;
  570                 *bnp = adoswordn(flbp, flblkoff) * ap->amp->bsize / DEV_BSIZE;
  571         } else {
  572 #ifdef DIAGNOSTIC
  573                 printf("flblk offset %ld too large in lblk %ld blk %" PRId64 "\n", 
  574                     flblkoff, (long)bn, flbp->b_blkno);
  575 #endif
  576                 error = EINVAL;
  577         }
  578         brelse(flbp);
  579 reterr:
  580 #ifdef ADOSFS_DIAGNOSTIC
  581         if (error == 0 && bnp)
  582                 printf(" %lld => %lld", (long long)bn, (long long)*bnp);
  583         printf(" %d)\n", error);
  584 #endif
  585         return(error);
  586 }
  587 
  588 /*
  589  * Print out the contents of a adosfs vnode.
  590  */
  591 /* ARGSUSED */
  592 int
  593 adosfs_print(v)
  594         void *v;
  595 {
  596 #if 0
  597         struct vop_print_args /* {
  598                 struct vnode *a_vp;
  599         } */ *sp = v;
  600 #endif
  601         return(0);
  602 }
  603 
  604 struct adirent {
  605         u_long  fileno;
  606         u_short reclen;
  607         char    type;
  608         char    namlen;
  609         char    name[32];       /* maxlen of 30 plus 2 NUL's */
  610 };
  611         
  612 int 
  613 adosfs_readdir(v)
  614         void *v;
  615 {
  616         struct vop_readdir_args /* {
  617                 struct vnode *a_vp;
  618                 struct uio *a_uio;
  619                 struct ucred *a_cred;
  620                 int *a_eofflag;
  621                 off_t **a_cookies;
  622                 int *a_ncookies;
  623         } */ *sp = v;
  624         int error, useri, chainc, hashi, scanned, uavail;
  625         struct adirent ad, *adp;
  626         struct anode *pap, *ap;
  627         struct adosfsmount *amp;
  628         struct vnode *vp;
  629         struct uio *uio;
  630         u_long nextbn;
  631         off_t uoff, *cookies = NULL;
  632         int ncookies = 0;
  633 
  634 #ifdef ADOSFS_DIAGNOSTIC
  635         advopprint(sp);
  636 #endif
  637         if (sp->a_vp->v_type != VDIR) {
  638                 error = ENOTDIR;
  639                 goto reterr;
  640         }
  641 
  642         uio = sp->a_uio;
  643         uoff = uio->uio_offset;
  644         if (uoff < 0) {
  645                 error = EINVAL;
  646                 goto reterr;
  647         }
  648 
  649         pap = VTOA(sp->a_vp);
  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 
  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 
  664         if (sp->a_ncookies) {
  665                 ncookies = 0;
  666                 cookies = malloc(sizeof (off_t) * uavail, M_TEMP, M_WAITOK);
  667                 *sp->a_cookies = cookies;
  668         }
  669 
  670         while (uavail) {
  671                 if (hashi == pap->ntabent) {
  672                         *sp->a_eofflag = 1;
  673                         break;
  674                 }
  675                 if (pap->tab[hashi] == 0) {
  676                         hashi++;
  677                         continue;
  678                 }
  679                 if (nextbn == 0)
  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++;
  692                                 nextbn = 0;
  693                                 continue;
  694                         }
  695                 }
  696 
  697                 /*
  698                  * now [continue to] walk the chain
  699                  */
  700                 ap = NULL;
  701                 do {
  702                         error = VFS_VGET(amp->mp, (ino_t)nextbn, &vp);
  703                         if (error)
  704                                 goto reterr;
  705                         ap = VTOA(vp);
  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++;
  716                                 chainc = 0;
  717                         } else if (pap->tabi[hashi] <= 0 &&
  718                             -chainc < pap->tabi[hashi])
  719                                 pap->tabi[hashi] = -chainc;
  720 
  721                         if (useri >= scanned) {
  722                                 vput(vp);
  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                  */
  735                 memset(adp, 0, sizeof(struct adirent));
  736                 adp->fileno = ap->block;
  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                 }
  754                 adp->reclen = sizeof(struct adirent);
  755                 adp->namlen = strlen(ap->name);
  756                 memcpy(adp->name, ap->name, adp->namlen);
  757                 vput(vp);
  758 
  759                 error = uiomove((caddr_t) adp, sizeof(struct adirent), uio);
  760                 if (error)
  761                         break;
  762                 if (sp->a_ncookies) {
  763                         *cookies++ = uoff;
  764                         ncookies++;
  765                 }
  766                 uoff += sizeof(struct adirent);
  767                 useri++;
  768                 uavail--;
  769         }
  770 #if doesnt_uiomove_handle_this
  771         uio->uio_offset = uoff;
  772 #endif
  773 reterr:
  774 #ifdef ADOSFS_DIAGNOSTIC
  775         printf(" %d)", error);
  776 #endif
  777         if (sp->a_ncookies) {
  778                 if (error) {
  779                         free(*sp->a_cookies, M_TEMP);
  780                         *sp->a_ncookies = 0;
  781                         *sp->a_cookies = NULL;
  782                 } else
  783                         *sp->a_ncookies = ncookies;
  784         }
  785         return(error);
  786 }
  787 
  788 
  789 int
  790 adosfs_access(v)
  791         void *v;
  792 {
  793         struct vop_access_args /* {
  794                 struct vnode *a_vp;
  795                 int  a_mode;
  796                 struct ucred *a_cred;
  797                 struct proc *a_p;
  798         } */ *sp = v;
  799         struct anode *ap;
  800         struct vnode *vp = sp->a_vp;
  801         int error;
  802 
  803 #ifdef ADOSFS_DIAGNOSTIC
  804         advopprint(sp);
  805 #endif
  806 
  807         ap = VTOA(vp);
  808 #ifdef DIAGNOSTIC
  809         if (!VOP_ISLOCKED(vp)) {
  810                 vprint("adosfs_access: not locked", sp->a_vp);
  811                 panic("adosfs_access: not locked");
  812         }
  813 #endif
  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         }
  829 #ifdef QUOTA
  830 #endif
  831         error = vaccess(sp->a_vp->v_type, adunixprot(ap->adprot) & ap->amp->mask,
  832             ap->uid, ap->gid, sp->a_mode, sp->a_cred);
  833 #ifdef ADOSFS_DIAGNOSTIC
  834         printf(" %d)", error);
  835 #endif
  836         return(error);
  837 }
  838 
  839 int
  840 adosfs_readlink(v)
  841         void *v;
  842 {
  843         struct vop_readlink_args /* {
  844                 struct vnode *a_vp;
  845                 struct uio *a_uio;
  846                 struct ucred *a_cred;
  847         } */ *sp = v;
  848         struct anode *ap;
  849         int error;
  850 
  851 #ifdef ADOSFS_DIAGNOSTIC
  852         advopprint(sp);
  853 #endif
  854         ap = VTOA(sp->a_vp);
  855         error = uiomove(ap->slinkto, strlen(ap->slinkto), sp->a_uio);
  856 #ifdef ADOSFS_DIAGNOSTIC
  857         printf(" %d)", error);
  858 #endif
  859         return (error);
  860 }
  861 
  862 /*ARGSUSED*/
  863 int
  864 adosfs_inactive(v)
  865         void *v;
  866 {
  867         struct vop_inactive_args /* {
  868                 struct vnode *a_vp;
  869                 struct proc *a_p;
  870         } */ *sp = v;
  871         struct vnode *vp = sp->a_vp;
  872         struct proc *p = sp->a_p;
  873 #ifdef ADOSFS_DIAGNOSTIC
  874         advopprint(sp);
  875 #endif
  876         VOP_UNLOCK(vp, 0);
  877         /* XXX this needs to check if file was deleted */
  878         vrecycle(vp, NULL, p);
  879 
  880 #ifdef ADOSFS_DIAGNOSTIC
  881         printf(" 0)");
  882 #endif
  883         return(0);
  884 }
  885 
  886 /*
  887  * the kernel wants its vnode back.
  888  * no lock needed we are being called from vclean()
  889  */
  890 int
  891 adosfs_reclaim(v)
  892         void *v;
  893 {
  894         struct vop_reclaim_args /* {
  895                 struct vnode *a_vp;
  896         } */ *sp = v;
  897         struct vnode *vp;
  898         struct anode *ap;
  899 
  900 #ifdef ADOSFS_DIAGNOSTIC
  901         printf("(reclaim 0)");
  902 #endif
  903         vp = sp->a_vp;
  904         ap = VTOA(vp);
  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);
  911         pool_put(&adosfs_node_pool, ap);
  912         vp->v_data = NULL;
  913         return(0);
  914 }
  915 
  916 /*
  917  * POSIX pathconf info, grabbed from kern/u fs, probably need to 
  918  * investigate exactly what each return type means as they are probably
  919  * not valid currently
  920  */
  921 int
  922 adosfs_pathconf(v)
  923         void *v;
  924 {
  925         struct vop_pathconf_args /* {
  926                 struct vnode *a_vp;
  927                 int a_name;
  928                 register_t *a_retval;
  929         } */ *sp = v;
  930 
  931         switch (sp->a_name) {
  932         case _PC_LINK_MAX:
  933                 *sp->a_retval = LINK_MAX;
  934                 return (0);
  935         case _PC_PIPE_BUF:
  936                 *sp->a_retval = PIPE_BUF;
  937                 return (0);
  938         case _PC_CHOWN_RESTRICTED:
  939                 *sp->a_retval = 1;
  940                 return (0);
  941         case _PC_VDISABLE:
  942                 *sp->a_retval = _POSIX_VDISABLE;
  943                 return (0);
  944         case _PC_SYNC_IO:
  945                 *sp->a_retval = 1;
  946                 return (0);
  947         case _PC_FILESIZEBITS:
  948                 *sp->a_retval = 32;
  949                 return (0);
  950         default:
  951                 return (EINVAL);
  952         }
  953         /* NOTREACHED */
  954 }

Cache object: d2f4cff1b107842cc5533835511721c2


[ 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.