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/ext2fs/ext2_alloc.c

Version: -  FREEBSD  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-2  -  FREEBSD-11-1  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-4  -  FREEBSD-10-3  -  FREEBSD-10-2  -  FREEBSD-10-1  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-3  -  FREEBSD-9-2  -  FREEBSD-9-1  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-4  -  FREEBSD-8-3  -  FREEBSD-8-2  -  FREEBSD-8-1  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-4  -  FREEBSD-7-3  -  FREEBSD-7-2  -  FREEBSD-7-1  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-4  -  FREEBSD-6-3  -  FREEBSD-6-2  -  FREEBSD-6-1  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-5  -  FREEBSD-5-4  -  FREEBSD-5-3  -  FREEBSD-5-2  -  FREEBSD-5-1  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  linux-2.6  -  linux-2.4.22  -  MK83  -  MK84  -  PLAN9  -  DFBSD  -  NETBSD  -  NETBSD5  -  NETBSD4  -  NETBSD3  -  NETBSD20  -  OPENBSD  -  xnu-517  -  xnu-792  -  xnu-792.6.70  -  xnu-1228  -  xnu-1456.1.26  -  xnu-1699.24.8  -  xnu-2050.18.24  -  OPENSOLARIS  -  minix-3-1-1 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  *  modified for Lites 1.1
    3  *
    4  *  Aug 1995, Godmar Back (gback@cs.utah.edu)
    5  *  University of Utah, Department of Computer Science
    6  */
    7 /*-
    8  * Copyright (c) 1982, 1986, 1989, 1993
    9  *      The Regents of the University of California.  All rights reserved.
   10  *
   11  * Redistribution and use in source and binary forms, with or without
   12  * modification, are permitted provided that the following conditions
   13  * are met:
   14  * 1. Redistributions of source code must retain the above copyright
   15  *    notice, this list of conditions and the following disclaimer.
   16  * 2. Redistributions in binary form must reproduce the above copyright
   17  *    notice, this list of conditions and the following disclaimer in the
   18  *    documentation and/or other materials provided with the distribution.
   19  * 4. Neither the name of the University nor the names of its contributors
   20  *    may be used to endorse or promote products derived from this software
   21  *    without specific prior written permission.
   22  *
   23  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   24  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   26  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   27  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   28  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   29  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   32  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   33  * SUCH DAMAGE.
   34  *
   35  *      @(#)ffs_alloc.c 8.8 (Berkeley) 2/21/94
   36  * $FreeBSD: releng/9.1/sys/fs/ext2fs/ext2_alloc.c 233322 2012-03-22 20:31:52Z pfg $
   37  */
   38 
   39 #include <sys/param.h>
   40 #include <sys/systm.h>
   41 #include <sys/conf.h>
   42 #include <sys/vnode.h>
   43 #include <sys/stat.h>
   44 #include <sys/mount.h>
   45 #include <sys/sysctl.h>
   46 #include <sys/syslog.h>
   47 #include <sys/buf.h>
   48 
   49 #include <fs/ext2fs/inode.h>
   50 #include <fs/ext2fs/ext2_mount.h>
   51 #include <fs/ext2fs/ext2fs.h>
   52 #include <fs/ext2fs/fs.h>
   53 #include <fs/ext2fs/ext2_extern.h>
   54 
   55 static daddr_t  ext2_alloccg(struct inode *, int, daddr_t, int);
   56 static daddr_t  ext2_clusteralloc(struct inode *, int, daddr_t, int);
   57 static u_long   ext2_dirpref(struct inode *);
   58 static void     ext2_fserr(struct m_ext2fs *, uid_t, char *);
   59 static u_long   ext2_hashalloc(struct inode *, int, long, int,
   60                                 daddr_t (*)(struct inode *, int, daddr_t, 
   61                                                 int));
   62 static daddr_t  ext2_nodealloccg(struct inode *, int, daddr_t, int);
   63 static daddr_t  ext2_mapsearch(struct m_ext2fs *, char *, daddr_t);
   64 
   65 /*
   66  * Allocate a block in the file system.
   67  *
   68  * A preference may be optionally specified. If a preference is given
   69  * the following hierarchy is used to allocate a block:
   70  *   1) allocate the requested block.
   71  *   2) allocate a rotationally optimal block in the same cylinder.
   72  *   3) allocate a block in the same cylinder group.
   73  *   4) quadradically rehash into other cylinder groups, until an
   74  *        available block is located.
   75  * If no block preference is given the following hierarchy is used
   76  * to allocate a block:
   77  *   1) allocate a block in the cylinder group that contains the
   78  *        inode for the file.
   79  *   2) quadradically rehash into other cylinder groups, until an
   80  *        available block is located.
   81  */
   82 int
   83 ext2_alloc(ip, lbn, bpref, size, cred, bnp)
   84         struct inode *ip;
   85         int32_t lbn, bpref;
   86         int size;
   87         struct ucred *cred;
   88         int32_t *bnp;
   89 {
   90         struct m_ext2fs *fs;
   91         struct ext2mount *ump;
   92         int32_t bno;
   93         int cg; 
   94         *bnp = 0;
   95         fs = ip->i_e2fs;
   96         ump = ip->i_ump;
   97         mtx_assert(EXT2_MTX(ump), MA_OWNED);
   98 #ifdef DIAGNOSTIC
   99         if ((u_int)size > fs->e2fs_bsize || blkoff(fs, size) != 0) {
  100                 vn_printf(ip->i_devvp, "bsize = %lu, size = %d, fs = %s\n",
  101                     (long unsigned int)fs->e2fs_bsize, size, fs->e2fs_fsmnt);
  102                 panic("ext2_alloc: bad size");
  103         }
  104         if (cred == NOCRED)
  105                 panic("ext2_alloc: missing credential");
  106 #endif /* DIAGNOSTIC */
  107         if (size == fs->e2fs_bsize && fs->e2fs->e2fs_fbcount == 0)
  108                 goto nospace;
  109         if (cred->cr_uid != 0 && 
  110                 fs->e2fs->e2fs_fbcount < fs->e2fs->e2fs_rbcount)
  111                 goto nospace;
  112         if (bpref >= fs->e2fs->e2fs_bcount)
  113                 bpref = 0;
  114         if (bpref == 0)
  115                 cg = ino_to_cg(fs, ip->i_number);
  116         else
  117                 cg = dtog(fs, bpref);
  118         bno = (daddr_t)ext2_hashalloc(ip, cg, bpref, fs->e2fs_bsize,
  119                                       ext2_alloccg);
  120         if (bno > 0) {
  121                 /* set next_alloc fields as done in block_getblk */
  122                 ip->i_next_alloc_block = lbn;
  123                 ip->i_next_alloc_goal = bno;
  124 
  125                 ip->i_blocks += btodb(fs->e2fs_bsize);
  126                 ip->i_flag |= IN_CHANGE | IN_UPDATE;
  127                 *bnp = bno;
  128                 return (0);
  129         }
  130 nospace:
  131         EXT2_UNLOCK(ump);
  132         ext2_fserr(fs, cred->cr_uid, "file system full");
  133         uprintf("\n%s: write failed, file system is full\n", fs->e2fs_fsmnt);
  134         return (ENOSPC);
  135 }
  136 
  137 /*
  138  * Reallocate a sequence of blocks into a contiguous sequence of blocks.
  139  *
  140  * The vnode and an array of buffer pointers for a range of sequential
  141  * logical blocks to be made contiguous is given. The allocator attempts
  142  * to find a range of sequential blocks starting as close as possible to
  143  * an fs_rotdelay offset from the end of the allocation for the logical
  144  * block immediately preceding the current range. If successful, the
  145  * physical block numbers in the buffer pointers and in the inode are
  146  * changed to reflect the new allocation. If unsuccessful, the allocation
  147  * is left unchanged. The success in doing the reallocation is returned.
  148  * Note that the error return is not reflected back to the user. Rather
  149  * the previous block allocation will be used.
  150  */
  151 
  152 SYSCTL_NODE(_vfs, OID_AUTO, ext2fs, CTLFLAG_RW, 0, "EXT2FS filesystem");
  153 
  154 static int doasyncfree = 1;
  155 SYSCTL_INT(_vfs_ext2fs, OID_AUTO, doasyncfree, CTLFLAG_RW, &doasyncfree, 0,
  156     "Use asychronous writes to update block pointers when freeing blocks");
  157 
  158 static int doreallocblks = 1;
  159 SYSCTL_INT(_vfs_ext2fs, OID_AUTO, doreallocblks, CTLFLAG_RW, &doreallocblks, 0, "");
  160 
  161 int
  162 ext2_reallocblks(ap)
  163         struct vop_reallocblks_args /* {
  164                 struct vnode *a_vp;
  165                 struct cluster_save *a_buflist;
  166         } */ *ap;
  167 {
  168         struct m_ext2fs *fs;
  169         struct inode *ip;
  170         struct vnode *vp;
  171         struct buf *sbp, *ebp;
  172         int32_t *bap, *sbap, *ebap = 0;
  173         struct ext2mount *ump;
  174         struct cluster_save *buflist;
  175         struct indir start_ap[NIADDR + 1], end_ap[NIADDR + 1], *idp;
  176         int32_t start_lbn, end_lbn, soff, newblk, blkno;
  177         int i, len, start_lvl, end_lvl, pref, ssize;
  178 
  179         if (doreallocblks == 0)
  180                   return (ENOSPC);
  181 
  182         vp = ap->a_vp;
  183         ip = VTOI(vp);
  184         fs = ip->i_e2fs;
  185         ump = ip->i_ump;
  186 
  187         if (fs->e2fs_contigsumsize <= 0)
  188                 return (ENOSPC);
  189 
  190         buflist = ap->a_buflist;
  191         len = buflist->bs_nchildren;
  192         start_lbn = buflist->bs_children[0]->b_lblkno;
  193         end_lbn = start_lbn + len - 1;
  194 #ifdef DIAGNOSTIC
  195         for (i = 1; i < len; i++)
  196                 if (buflist->bs_children[i]->b_lblkno != start_lbn + i)
  197                         panic("ext2_reallocblks: non-cluster");
  198 #endif
  199         /*
  200          * If the latest allocation is in a new cylinder group, assume that
  201          * the filesystem has decided to move and do not force it back to
  202          * the previous cylinder group.
  203          */
  204         if (dtog(fs, dbtofsb(fs, buflist->bs_children[0]->b_blkno)) !=
  205             dtog(fs, dbtofsb(fs, buflist->bs_children[len - 1]->b_blkno)))
  206                 return (ENOSPC);
  207         if (ext2_getlbns(vp, start_lbn, start_ap, &start_lvl) ||
  208             ext2_getlbns(vp, end_lbn, end_ap, &end_lvl))
  209                 return (ENOSPC);
  210         /*
  211          * Get the starting offset and block map for the first block.
  212          */
  213         if (start_lvl == 0) {
  214                 sbap = &ip->i_db[0];
  215                 soff = start_lbn;
  216         } else {
  217                 idp = &start_ap[start_lvl - 1];
  218                 if (bread(vp, idp->in_lbn, (int)fs->e2fs_bsize, NOCRED, &sbp)) {
  219                         brelse(sbp);
  220                         return (ENOSPC);
  221                 }
  222                 sbap = (int32_t *)sbp->b_data;
  223                 soff = idp->in_off;
  224         }
  225         /*
  226          * If the block range spans two block maps, get the second map.
  227          */
  228         if (end_lvl == 0 || (idp = &end_ap[end_lvl - 1])->in_off + 1 >= len) {
  229                 ssize = len;
  230         } else {
  231 #ifdef DIAGNOSTIC
  232                 if (start_ap[start_lvl-1].in_lbn == idp->in_lbn)
  233                         panic("ext2_reallocblk: start == end");
  234 #endif
  235                 ssize = len - (idp->in_off + 1);
  236                 if (bread(vp, idp->in_lbn, (int)fs->e2fs_bsize, NOCRED, &ebp))
  237                         goto fail;
  238                 ebap = (int32_t *)ebp->b_data;
  239         }
  240         /*
  241          * Find the preferred location for the cluster.
  242          */
  243         EXT2_LOCK(ump);
  244         pref = ext2_blkpref(ip, start_lbn, soff, sbap, 0);
  245         /*
  246          * Search the block map looking for an allocation of the desired size.
  247          */
  248         if ((newblk = (int32_t)ext2_hashalloc(ip, dtog(fs, pref), pref,
  249             len, ext2_clusteralloc)) == 0){
  250                 EXT2_UNLOCK(ump);
  251                 goto fail;
  252         }       
  253         /*
  254          * We have found a new contiguous block.
  255          *
  256          * First we have to replace the old block pointers with the new
  257          * block pointers in the inode and indirect blocks associated
  258          * with the file.
  259          */
  260 #ifdef DEBUG
  261         printf("realloc: ino %d, lbns %jd-%jd\n\told:", ip->i_number,
  262             (intmax_t)start_lbn, (intmax_t)end_lbn);
  263 #endif /* DEBUG */
  264         blkno = newblk;
  265         for (bap = &sbap[soff], i = 0; i < len; i++, blkno += fs->e2fs_fpb) {
  266                 if (i == ssize) {
  267                         bap = ebap;
  268                         soff = -i;
  269                 }
  270 #ifdef DIAGNOSTIC
  271                 if (buflist->bs_children[i]->b_blkno != fsbtodb(fs, *bap))
  272                         panic("ext2_reallocblks: alloc mismatch");
  273 #endif
  274 #ifdef DEBUG
  275         printf(" %d,", *bap);
  276 #endif /* DEBUG */
  277                 *bap++ = blkno;
  278         }
  279         /*
  280          * Next we must write out the modified inode and indirect blocks.
  281          * For strict correctness, the writes should be synchronous since
  282          * the old block values may have been written to disk. In practise
  283          * they are almost never written, but if we are concerned about 
  284          * strict correctness, the `doasyncfree' flag should be set to zero.
  285          *
  286          * The test on `doasyncfree' should be changed to test a flag
  287          * that shows whether the associated buffers and inodes have
  288          * been written. The flag should be set when the cluster is
  289          * started and cleared whenever the buffer or inode is flushed.
  290          * We can then check below to see if it is set, and do the
  291          * synchronous write only when it has been cleared.
  292          */
  293         if (sbap != &ip->i_db[0]) {
  294                 if (doasyncfree)
  295                         bdwrite(sbp);
  296                 else
  297                         bwrite(sbp);
  298         } else {
  299                 ip->i_flag |= IN_CHANGE | IN_UPDATE;
  300                 if (!doasyncfree)
  301                         ext2_update(vp, 1);
  302         }
  303         if (ssize < len) {
  304                 if (doasyncfree)
  305                         bdwrite(ebp);
  306                 else
  307                         bwrite(ebp);
  308         }
  309         /*
  310          * Last, free the old blocks and assign the new blocks to the buffers.
  311          */
  312 #ifdef DEBUG
  313         printf("\n\tnew:");
  314 #endif /* DEBUG */
  315         for (blkno = newblk, i = 0; i < len; i++, blkno += fs->e2fs_fpb) {
  316                 ext2_blkfree(ip, dbtofsb(fs, buflist->bs_children[i]->b_blkno),
  317                     fs->e2fs_bsize);
  318                 buflist->bs_children[i]->b_blkno = fsbtodb(fs, blkno);
  319 #ifdef DEBUG
  320                 printf(" %d,", blkno);
  321 #endif /* DEBUG */
  322         }
  323 #ifdef DEBUG
  324         printf("\n");
  325 #endif /* DEBUG */
  326         return (0);
  327 
  328 fail:
  329         if (ssize < len)
  330                 brelse(ebp);
  331         if (sbap != &ip->i_db[0])
  332                 brelse(sbp);
  333         return (ENOSPC);
  334 }
  335 
  336 /*
  337  * Allocate an inode in the file system.
  338  * 
  339  */
  340 int
  341 ext2_valloc(pvp, mode, cred, vpp)
  342         struct vnode *pvp;
  343         int mode;
  344         struct ucred *cred;
  345         struct vnode **vpp;
  346 {
  347         struct timespec ts;
  348         struct inode *pip;
  349         struct m_ext2fs *fs;
  350         struct inode *ip;
  351         struct ext2mount *ump;
  352         ino_t ino, ipref;
  353         int i, error, cg;
  354         
  355         *vpp = NULL;
  356         pip = VTOI(pvp);
  357         fs = pip->i_e2fs;
  358         ump = pip->i_ump;
  359 
  360         EXT2_LOCK(ump);
  361         if (fs->e2fs->e2fs_ficount == 0)
  362                 goto noinodes;
  363         /*
  364          * If it is a directory then obtain a cylinder group based on
  365          * ext2_dirpref else obtain it using ino_to_cg. The preferred inode is
  366          * always the next inode.
  367          */
  368         if ((mode & IFMT) == IFDIR) {
  369                 cg = ext2_dirpref(pip);
  370                 if (fs->e2fs_contigdirs[cg] < 255)
  371                         fs->e2fs_contigdirs[cg]++;
  372         } else {
  373                 cg = ino_to_cg(fs, pip->i_number);
  374                 if (fs->e2fs_contigdirs[cg] > 0)
  375                         fs->e2fs_contigdirs[cg]--;
  376         }
  377         ipref = cg * fs->e2fs->e2fs_ipg + 1;
  378         ino = (ino_t)ext2_hashalloc(pip, cg, (long)ipref, mode, ext2_nodealloccg);
  379 
  380         if (ino == 0) 
  381                 goto noinodes;
  382         error = VFS_VGET(pvp->v_mount, ino, LK_EXCLUSIVE, vpp);
  383         if (error) {
  384                 ext2_vfree(pvp, ino, mode);
  385                 return (error);
  386         }
  387         ip = VTOI(*vpp);
  388 
  389         /*
  390          * The question is whether using VGET was such good idea at all:
  391          * Linux doesn't read the old inode in when it is allocating a
  392          * new one. I will set at least i_size and i_blocks to zero.
  393          */
  394         ip->i_size = 0;
  395         ip->i_blocks = 0;
  396         ip->i_mode = 0;
  397         ip->i_flags = 0;
  398         /* now we want to make sure that the block pointers are zeroed out */
  399         for (i = 0; i < NDADDR; i++)
  400                 ip->i_db[i] = 0;
  401         for (i = 0; i < NIADDR; i++)
  402                 ip->i_ib[i] = 0;
  403 
  404         /*
  405          * Set up a new generation number for this inode.
  406          * XXX check if this makes sense in ext2
  407          */
  408         if (ip->i_gen == 0 || ++ip->i_gen == 0)
  409                 ip->i_gen = random() / 2 + 1;
  410 
  411         vfs_timestamp(&ts);
  412         ip->i_birthtime = ts.tv_sec;
  413         ip->i_birthnsec = ts.tv_nsec;
  414 
  415 /*
  416 printf("ext2_valloc: allocated inode %d\n", ino);
  417 */
  418         return (0);
  419 noinodes:
  420         EXT2_UNLOCK(ump);
  421         ext2_fserr(fs, cred->cr_uid, "out of inodes");
  422         uprintf("\n%s: create/symlink failed, no inodes free\n", fs->e2fs_fsmnt);
  423         return (ENOSPC);
  424 }
  425 
  426 /*
  427  * Find a cylinder to place a directory.
  428  *
  429  * The policy implemented by this algorithm is to allocate a
  430  * directory inode in the same cylinder group as its parent
  431  * directory, but also to reserve space for its files inodes
  432  * and data. Restrict the number of directories which may be
  433  * allocated one after another in the same cylinder group
  434  * without intervening allocation of files.
  435  *
  436  * If we allocate a first level directory then force allocation
  437  * in another cylinder group.
  438  *
  439  */
  440 static u_long
  441 ext2_dirpref(struct inode *pip)
  442 {
  443         struct m_ext2fs *fs;
  444         int cg, prefcg, dirsize, cgsize;
  445         int avgifree, avgbfree, avgndir, curdirsize;
  446         int minifree, minbfree, maxndir;
  447         int mincg, minndir;
  448         int maxcontigdirs;
  449 
  450         mtx_assert(EXT2_MTX(pip->i_ump), MA_OWNED);
  451         fs = pip->i_e2fs;
  452 
  453         avgifree = fs->e2fs->e2fs_ficount / fs->e2fs_gcount;
  454         avgbfree = fs->e2fs->e2fs_fbcount / fs->e2fs_gcount;
  455         avgndir  = fs->e2fs_total_dir / fs->e2fs_gcount;
  456 
  457         /*
  458          * Force allocation in another cg if creating a first level dir.
  459          */
  460         ASSERT_VOP_LOCKED(ITOV(pip), "ext2fs_dirpref");
  461         if (ITOV(pip)->v_vflag & VV_ROOT) {
  462                 prefcg = arc4random() % fs->e2fs_gcount;
  463                 mincg = prefcg;
  464                 minndir = fs->e2fs_ipg;
  465                 for (cg = prefcg; cg < fs->e2fs_gcount; cg++)
  466                         if (fs->e2fs_gd[cg].ext2bgd_ndirs < minndir &&
  467                             fs->e2fs_gd[cg].ext2bgd_nifree >= avgifree &&
  468                             fs->e2fs_gd[cg].ext2bgd_nbfree >= avgbfree) {
  469                                 mincg = cg;
  470                                 minndir = fs->e2fs_gd[cg].ext2bgd_ndirs;
  471                         }
  472                 for (cg = 0; cg < prefcg; cg++)
  473                         if (fs->e2fs_gd[cg].ext2bgd_ndirs < minndir &&
  474                             fs->e2fs_gd[cg].ext2bgd_nifree >= avgifree &&
  475                             fs->e2fs_gd[cg].ext2bgd_nbfree >= avgbfree) {
  476                                 mincg = cg;
  477                                 minndir = fs->e2fs_gd[cg].ext2bgd_ndirs;
  478                         }
  479 
  480                 return (mincg);
  481         }
  482 
  483         /*
  484          * Count various limits which used for
  485          * optimal allocation of a directory inode.
  486          */
  487         maxndir = min(avgndir + fs->e2fs_ipg / 16, fs->e2fs_ipg);
  488         minifree = avgifree - avgifree / 4;
  489         if (minifree < 1)
  490                 minifree = 1;
  491         minbfree = avgbfree - avgbfree / 4;
  492         if (minbfree < 1)
  493                 minbfree = 1;
  494         cgsize = fs->e2fs_fsize * fs->e2fs_fpg;
  495         dirsize = AVGDIRSIZE;
  496         curdirsize = avgndir ? (cgsize - avgbfree * fs->e2fs_bsize) / avgndir : 0;
  497         if (dirsize < curdirsize)
  498                 dirsize = curdirsize;
  499         if (dirsize <= 0)
  500                 maxcontigdirs = 0;              /* dirsize overflowed */
  501         else
  502                 maxcontigdirs = min((avgbfree * fs->e2fs_bsize) / dirsize, 255);
  503         maxcontigdirs = min(maxcontigdirs, fs->e2fs_ipg / AFPDIR);
  504         if (maxcontigdirs == 0)
  505                 maxcontigdirs = 1;
  506 
  507         /*
  508          * Limit number of dirs in one cg and reserve space for 
  509          * regular files, but only if we have no deficit in
  510          * inodes or space.
  511          */
  512         prefcg = ino_to_cg(fs, pip->i_number);
  513         for (cg = prefcg; cg < fs->e2fs_gcount; cg++)
  514                 if (fs->e2fs_gd[cg].ext2bgd_ndirs < maxndir &&
  515                     fs->e2fs_gd[cg].ext2bgd_nifree >= minifree &&
  516                     fs->e2fs_gd[cg].ext2bgd_nbfree >= minbfree) {
  517                         if (fs->e2fs_contigdirs[cg] < maxcontigdirs)
  518                                 return (cg);
  519                 }
  520         for (cg = 0; cg < prefcg; cg++)
  521                 if (fs->e2fs_gd[cg].ext2bgd_ndirs < maxndir &&
  522                     fs->e2fs_gd[cg].ext2bgd_nifree >= minifree &&
  523                     fs->e2fs_gd[cg].ext2bgd_nbfree >= minbfree) {
  524                         if (fs->e2fs_contigdirs[cg] < maxcontigdirs)
  525                                 return (cg);
  526                 }
  527         /*
  528          * This is a backstop when we have deficit in space.
  529          */
  530         for (cg = prefcg; cg < fs->e2fs_gcount; cg++)
  531                 if (fs->e2fs_gd[cg].ext2bgd_nifree >= avgifree)
  532                         return (cg);
  533         for (cg = 0; cg < prefcg; cg++)
  534                 if (fs->e2fs_gd[cg].ext2bgd_nifree >= avgifree)
  535                         break;
  536         return (cg);
  537 }
  538 
  539 /*
  540  * Select the desired position for the next block in a file.  
  541  *
  542  * we try to mimic what Remy does in inode_getblk/block_getblk
  543  *
  544  * we note: blocknr == 0 means that we're about to allocate either
  545  * a direct block or a pointer block at the first level of indirection
  546  * (In other words, stuff that will go in i_db[] or i_ib[])
  547  *
  548  * blocknr != 0 means that we're allocating a block that is none
  549  * of the above. Then, blocknr tells us the number of the block
  550  * that will hold the pointer
  551  */
  552 int32_t
  553 ext2_blkpref(ip, lbn, indx, bap, blocknr)
  554         struct inode *ip;
  555         int32_t lbn;
  556         int indx;
  557         int32_t *bap;
  558         int32_t blocknr;
  559 {
  560         int     tmp;
  561         mtx_assert(EXT2_MTX(ip->i_ump), MA_OWNED);
  562 
  563         /* if the next block is actually what we thought it is,
  564            then set the goal to what we thought it should be
  565         */
  566         if (ip->i_next_alloc_block == lbn && ip->i_next_alloc_goal != 0)
  567                 return ip->i_next_alloc_goal;
  568 
  569         /* now check whether we were provided with an array that basically
  570            tells us previous blocks to which we want to stay closeby
  571         */
  572         if (bap) 
  573                 for (tmp = indx - 1; tmp >= 0; tmp--) 
  574                         if (bap[tmp]) 
  575                                 return bap[tmp];
  576 
  577         /* else let's fall back to the blocknr, or, if there is none,
  578            follow the rule that a block should be allocated near its inode
  579         */
  580         return blocknr ? blocknr :
  581                         (int32_t)(ip->i_block_group * 
  582                         EXT2_BLOCKS_PER_GROUP(ip->i_e2fs)) + 
  583                         ip->i_e2fs->e2fs->e2fs_first_dblock;
  584 }
  585 
  586 /*
  587  * Implement the cylinder overflow algorithm.
  588  *
  589  * The policy implemented by this algorithm is:
  590  *   1) allocate the block in its requested cylinder group.
  591  *   2) quadradically rehash on the cylinder group number.
  592  *   3) brute force search for a free block.
  593  */
  594 static u_long
  595 ext2_hashalloc(struct inode *ip, int cg, long pref, int size,
  596                 daddr_t (*allocator)(struct inode *, int, daddr_t, int))
  597 {
  598         struct m_ext2fs *fs;
  599         ino_t result;
  600         int i, icg = cg;
  601 
  602         mtx_assert(EXT2_MTX(ip->i_ump), MA_OWNED);
  603         fs = ip->i_e2fs;
  604         /*
  605          * 1: preferred cylinder group
  606          */
  607         result = (*allocator)(ip, cg, pref, size);
  608         if (result)
  609                 return (result);
  610         /*
  611          * 2: quadratic rehash
  612          */
  613         for (i = 1; i < fs->e2fs_gcount; i *= 2) {
  614                 cg += i;
  615                 if (cg >= fs->e2fs_gcount)
  616                         cg -= fs->e2fs_gcount;
  617                 result = (*allocator)(ip, cg, 0, size);
  618                 if (result)
  619                         return (result);
  620         }
  621         /*
  622          * 3: brute force search
  623          * Note that we start at i == 2, since 0 was checked initially,
  624          * and 1 is always checked in the quadratic rehash.
  625          */
  626         cg = (icg + 2) % fs->e2fs_gcount;
  627         for (i = 2; i < fs->e2fs_gcount; i++) {
  628                 result = (*allocator)(ip, cg, 0, size);
  629                 if (result)
  630                         return (result);
  631                 cg++;
  632                 if (cg == fs->e2fs_gcount)
  633                         cg = 0;
  634         }
  635         return (0);
  636 }
  637 
  638 /*
  639  * Determine whether a block can be allocated.
  640  *
  641  * Check to see if a block of the appropriate size is available,
  642  * and if it is, allocate it.
  643  */
  644 static daddr_t
  645 ext2_alloccg(struct inode *ip, int cg, daddr_t bpref, int size)
  646 {
  647         struct m_ext2fs *fs;
  648         struct buf *bp;
  649         struct ext2mount *ump;
  650         daddr_t bno, runstart, runlen;
  651         int bit, loc, end, error, start;
  652         char *bbp;
  653         /* XXX ondisk32 */
  654         fs = ip->i_e2fs;
  655         ump = ip->i_ump;
  656         if (fs->e2fs_gd[cg].ext2bgd_nbfree == 0)
  657                 return (0);
  658         EXT2_UNLOCK(ump);
  659         error = bread(ip->i_devvp, fsbtodb(fs,
  660                 fs->e2fs_gd[cg].ext2bgd_b_bitmap),
  661                 (int)fs->e2fs_bsize, NOCRED, &bp);
  662         if (error) {
  663                 brelse(bp);
  664                 EXT2_LOCK(ump);
  665                 return (0);
  666         }
  667         if (fs->e2fs_gd[cg].ext2bgd_nbfree == 0) {
  668                 /*
  669                  * Another thread allocated the last block in this
  670                  * group while we were waiting for the buffer.
  671                  */
  672                 brelse(bp);
  673                 EXT2_LOCK(ump);
  674                 return (0);
  675         }
  676         bbp = (char *)bp->b_data;
  677 
  678         if (dtog(fs, bpref) != cg)
  679                 bpref = 0;
  680         if (bpref != 0) {
  681                 bpref = dtogd(fs, bpref);
  682                 /*
  683                  * if the requested block is available, use it
  684                  */
  685                 if (isclr(bbp, bpref)) {
  686                         bno = bpref;
  687                         goto gotit;
  688                 }
  689         }
  690         /*
  691          * no blocks in the requested cylinder, so take next
  692          * available one in this cylinder group.
  693          * first try to get 8 contigous blocks, then fall back to a single
  694          * block.
  695          */
  696         if (bpref)
  697                 start = dtogd(fs, bpref) / NBBY;
  698         else
  699                 start = 0;
  700         end = howmany(fs->e2fs->e2fs_fpg, NBBY) - start;
  701 retry:
  702         runlen = 0;
  703         runstart = 0;
  704         for (loc = start; loc < end; loc++) {
  705                 if (bbp[loc] == (char)0xff) {
  706                         runlen = 0;
  707                         continue;
  708                 }
  709 
  710                 /* Start of a run, find the number of high clear bits. */
  711                 if (runlen == 0) {
  712                         bit = fls(bbp[loc]);
  713                         runlen = NBBY - bit;
  714                         runstart = loc * NBBY + bit;
  715                 } else if (bbp[loc] == 0) {
  716                         /* Continue a run. */
  717                         runlen += NBBY;
  718                 } else {
  719                         /*
  720                          * Finish the current run.  If it isn't long
  721                          * enough, start a new one.
  722                          */
  723                         bit = ffs(bbp[loc]) - 1;
  724                         runlen += bit;
  725                         if (runlen >= 8) {
  726                                 bno = runstart;
  727                                 goto gotit;
  728                         }
  729 
  730                         /* Run was too short, start a new one. */
  731                         bit = fls(bbp[loc]);
  732                         runlen = NBBY - bit;
  733                         runstart = loc * NBBY + bit;
  734                 }
  735 
  736                 /* If the current run is long enough, use it. */
  737                 if (runlen >= 8) {
  738                         bno = runstart;
  739                         goto gotit;
  740                 }
  741         }
  742         if (start != 0) {
  743                 end = start;
  744                 start = 0;
  745                 goto retry;
  746         }
  747 
  748         bno = ext2_mapsearch(fs, bbp, bpref);
  749         if (bno < 0){
  750                 brelse(bp);
  751                 EXT2_LOCK(ump);
  752                 return (0);
  753         }
  754 gotit:
  755 #ifdef DIAGNOSTIC
  756         if (isset(bbp, bno)) {
  757                 printf("ext2fs_alloccgblk: cg=%d bno=%jd fs=%s\n",
  758                         cg, (intmax_t)bno, fs->e2fs_fsmnt);
  759                 panic("ext2fs_alloccg: dup alloc");
  760         }
  761 #endif
  762         setbit(bbp, bno);
  763         EXT2_LOCK(ump);
  764         ext2_clusteracct(fs, bbp, cg, bno, -1);
  765         fs->e2fs->e2fs_fbcount--;
  766         fs->e2fs_gd[cg].ext2bgd_nbfree--;
  767         fs->e2fs_fmod = 1;
  768         EXT2_UNLOCK(ump);
  769         bdwrite(bp);
  770         return (cg * fs->e2fs->e2fs_fpg + fs->e2fs->e2fs_first_dblock + bno);
  771 }
  772 
  773 /*
  774  * Determine whether a cluster can be allocated.
  775  */
  776 static daddr_t
  777 ext2_clusteralloc(struct inode *ip, int cg, daddr_t bpref, int len)
  778 {
  779         struct m_ext2fs *fs;
  780         struct ext2mount *ump;
  781         struct buf *bp;
  782         char *bbp;
  783         int bit, error, got, i, loc, run;
  784         int32_t *lp;
  785         daddr_t bno;
  786 
  787         fs = ip->i_e2fs;
  788         ump = ip->i_ump;
  789 
  790         if (fs->e2fs_maxcluster[cg] < len)
  791                 return (0);
  792 
  793         EXT2_UNLOCK(ump);
  794         error = bread(ip->i_devvp,
  795             fsbtodb(fs, fs->e2fs_gd[cg].ext2bgd_b_bitmap),
  796             (int)fs->e2fs_bsize, NOCRED, &bp);
  797         if (error)
  798                 goto fail_lock;
  799 
  800         bbp = (char *)bp->b_data;
  801         bp->b_xflags |= BX_BKGRDWRITE;
  802 
  803         EXT2_LOCK(ump);
  804         /*
  805          * Check to see if a cluster of the needed size (or bigger) is
  806          * available in this cylinder group.
  807          */
  808         lp = &fs->e2fs_clustersum[cg].cs_sum[len];
  809         for (i = len; i <= fs->e2fs_contigsumsize; i++)
  810                 if (*lp++ > 0)
  811                         break;
  812         if (i > fs->e2fs_contigsumsize) {
  813                 /*
  814                  * Update the cluster summary information to reflect
  815                  * the true maximum-sized cluster so that future cluster
  816                  * allocation requests can avoid reading the bitmap only
  817                  * to find no cluster.
  818                  */
  819                 lp = &fs->e2fs_clustersum[cg].cs_sum[len - 1];
  820                         for (i = len - 1; i > 0; i--)
  821                                 if (*lp-- > 0)
  822                                         break;
  823                 fs->e2fs_maxcluster[cg] = i;
  824                 goto fail;
  825         }
  826         EXT2_UNLOCK(ump);
  827 
  828         /* Search the bitmap to find a big enough cluster like in FFS. */
  829         if (dtog(fs, bpref) != cg)
  830                 bpref = 0;
  831         if (bpref != 0)
  832                 bpref = dtogd(fs, bpref);
  833         loc = bpref / NBBY;
  834         bit = 1 << (bpref % NBBY);
  835         for (run = 0, got = bpref; got < fs->e2fs->e2fs_fpg; got++) {
  836                 if ((bbp[loc] & bit) != 0)
  837                         run = 0;
  838                 else {
  839                         run++;
  840                         if (run == len)
  841                                 break;
  842                 }
  843                 if ((got & (NBBY - 1)) != (NBBY - 1))
  844                         bit <<= 1;
  845                 else {
  846                         loc++;
  847                         bit = 1;
  848                 }
  849         }
  850 
  851         if (got >= fs->e2fs->e2fs_fpg)
  852                 goto fail_lock;
  853 
  854         /* Allocate the cluster that we found. */
  855         for (i = 1; i < len; i++)
  856                 if (!isclr(bbp, got - run + i))
  857                         panic("ext2_clusteralloc: map mismatch");
  858 
  859         bno = got - run + 1;
  860         if (bno >= fs->e2fs->e2fs_fpg)
  861                 panic("ext2_clusteralloc: allocated out of group");
  862 
  863         EXT2_LOCK(ump);
  864         for (i = 0; i < len; i += fs->e2fs_fpb) {
  865                 setbit(bbp, bno + i);
  866                 ext2_clusteracct(fs, bbp, cg, bno + i, -1);
  867                 fs->e2fs->e2fs_fbcount--;
  868                 fs->e2fs_gd[cg].ext2bgd_nbfree--;
  869         }
  870         fs->e2fs_fmod = 1;
  871         EXT2_UNLOCK(ump);
  872 
  873         bdwrite(bp);
  874         return (cg * fs->e2fs->e2fs_fpg + fs->e2fs->e2fs_first_dblock + bno);
  875 
  876 fail_lock:
  877         EXT2_LOCK(ump);
  878 fail:
  879         brelse(bp);
  880         return (0);
  881 }
  882 
  883 /*
  884  * Determine whether an inode can be allocated.
  885  *
  886  * Check to see if an inode is available, and if it is,
  887  * allocate it using tode in the specified cylinder group.
  888  */
  889 static daddr_t
  890 ext2_nodealloccg(struct inode *ip, int cg, daddr_t ipref, int mode)
  891 {
  892         struct m_ext2fs *fs;
  893         struct buf *bp;
  894         struct ext2mount *ump;
  895         int error, start, len, loc, map, i;
  896         char *ibp;
  897         ipref--; /* to avoid a lot of (ipref -1) */
  898         if (ipref == -1)
  899                 ipref = 0;
  900         fs = ip->i_e2fs;
  901         ump = ip->i_ump;
  902         if (fs->e2fs_gd[cg].ext2bgd_nifree == 0)
  903                 return (0);
  904         EXT2_UNLOCK(ump);       
  905         error = bread(ip->i_devvp, fsbtodb(fs,
  906                 fs->e2fs_gd[cg].ext2bgd_i_bitmap),
  907                 (int)fs->e2fs_bsize, NOCRED, &bp);
  908         if (error) {
  909                 brelse(bp);
  910                 EXT2_LOCK(ump);
  911                 return (0);
  912         }
  913         if (fs->e2fs_gd[cg].ext2bgd_nifree == 0) {
  914                 /*
  915                  * Another thread allocated the last i-node in this
  916                  * group while we were waiting for the buffer.
  917                  */
  918                 brelse(bp);
  919                 EXT2_LOCK(ump);
  920                 return (0);
  921         }
  922         ibp = (char *)bp->b_data;
  923         if (ipref) {
  924                 ipref %= fs->e2fs->e2fs_ipg;
  925                 if (isclr(ibp, ipref))
  926                         goto gotit;
  927         }
  928         start = ipref / NBBY;
  929         len = howmany(fs->e2fs->e2fs_ipg - ipref, NBBY);
  930         loc = skpc(0xff, len, &ibp[start]);
  931         if (loc == 0) {
  932                 len = start + 1;
  933                 start = 0;
  934                 loc = skpc(0xff, len, &ibp[0]);
  935                 if (loc == 0) {
  936                         printf("cg = %d, ipref = %lld, fs = %s\n",
  937                                 cg, (long long)ipref, fs->e2fs_fsmnt);
  938                         panic("ext2fs_nodealloccg: map corrupted");
  939                         /* NOTREACHED */
  940                 }
  941         } 
  942         i = start + len - loc;
  943         map = ibp[i] ^ 0xff;
  944         if (map == 0) {
  945                 printf("fs = %s\n", fs->e2fs_fsmnt);
  946                 panic("ext2fs_nodealloccg: block not in map");
  947         }
  948         ipref = i * NBBY + ffs(map) - 1;
  949 gotit:
  950         setbit(ibp, ipref);
  951         EXT2_LOCK(ump);
  952         fs->e2fs_gd[cg].ext2bgd_nifree--;
  953         fs->e2fs->e2fs_ficount--;
  954         fs->e2fs_fmod = 1;
  955         if ((mode & IFMT) == IFDIR) {
  956                 fs->e2fs_gd[cg].ext2bgd_ndirs++;
  957                 fs->e2fs_total_dir++;
  958         }
  959         EXT2_UNLOCK(ump);
  960         bdwrite(bp);
  961         return (cg * fs->e2fs->e2fs_ipg + ipref +1);
  962 }
  963 
  964 /*
  965  * Free a block or fragment.
  966  *
  967  */
  968 void
  969 ext2_blkfree(ip, bno, size)
  970         struct inode *ip;
  971         int32_t bno;
  972         long size;
  973 {
  974         struct m_ext2fs *fs;
  975         struct buf *bp;
  976         struct ext2mount *ump;
  977         int cg, error;
  978         char *bbp;
  979 
  980         fs = ip->i_e2fs;
  981         ump = ip->i_ump;
  982         cg = dtog(fs, bno);
  983         if ((u_int)bno >= fs->e2fs->e2fs_bcount) {
  984                 printf("bad block %lld, ino %llu\n", (long long)bno,
  985                     (unsigned long long)ip->i_number);
  986                 ext2_fserr(fs, ip->i_uid, "bad block");
  987                 return;
  988         }
  989         error = bread(ip->i_devvp,
  990                 fsbtodb(fs, fs->e2fs_gd[cg].ext2bgd_b_bitmap),
  991                 (int)fs->e2fs_bsize, NOCRED, &bp);
  992         if (error) {
  993                 brelse(bp);
  994                 return;
  995         }
  996         bbp = (char *)bp->b_data;
  997         bno = dtogd(fs, bno);
  998         if (isclr(bbp, bno)) {
  999                 printf("block = %lld, fs = %s\n",
 1000                      (long long)bno, fs->e2fs_fsmnt);
 1001                 panic("blkfree: freeing free block");
 1002         }
 1003         clrbit(bbp, bno);
 1004         EXT2_LOCK(ump);
 1005         ext2_clusteracct(fs, bbp, cg, bno, 1);
 1006         fs->e2fs->e2fs_fbcount++;
 1007         fs->e2fs_gd[cg].ext2bgd_nbfree++;
 1008         fs->e2fs_fmod = 1;
 1009         EXT2_UNLOCK(ump);
 1010         bdwrite(bp);
 1011 }
 1012 
 1013 /*
 1014  * Free an inode.
 1015  *
 1016  */
 1017 int
 1018 ext2_vfree(pvp, ino, mode)
 1019         struct vnode *pvp;
 1020         ino_t ino;
 1021         int mode;
 1022 {
 1023         struct m_ext2fs *fs;
 1024         struct inode *pip;
 1025         struct buf *bp;
 1026         struct ext2mount *ump;
 1027         int error, cg;
 1028         char * ibp;
 1029 /*      mode_t save_i_mode; */
 1030 
 1031         pip = VTOI(pvp);
 1032         fs = pip->i_e2fs;
 1033         ump = pip->i_ump;
 1034         if ((u_int)ino > fs->e2fs_ipg * fs->e2fs_gcount)
 1035                 panic("ext2_vfree: range: devvp = %p, ino = %d, fs = %s",
 1036                     pip->i_devvp, ino, fs->e2fs_fsmnt);
 1037 
 1038         cg = ino_to_cg(fs, ino);
 1039         error = bread(pip->i_devvp,
 1040                 fsbtodb(fs, fs->e2fs_gd[cg].ext2bgd_i_bitmap),
 1041                 (int)fs->e2fs_bsize, NOCRED, &bp);
 1042         if (error) {
 1043                 brelse(bp);
 1044                 return (0);
 1045         }
 1046         ibp = (char *)bp->b_data;
 1047         ino = (ino - 1) % fs->e2fs->e2fs_ipg;
 1048         if (isclr(ibp, ino)) {
 1049                 printf("ino = %llu, fs = %s\n",
 1050                          (unsigned long long)ino, fs->e2fs_fsmnt);
 1051                 if (fs->e2fs_ronly == 0)
 1052                         panic("ifree: freeing free inode");
 1053         }
 1054         clrbit(ibp, ino);
 1055         EXT2_LOCK(ump);
 1056         fs->e2fs->e2fs_ficount++;
 1057         fs->e2fs_gd[cg].ext2bgd_nifree++;
 1058         if ((mode & IFMT) == IFDIR) {
 1059                 fs->e2fs_gd[cg].ext2bgd_ndirs--;
 1060                 fs->e2fs_total_dir--;
 1061         }
 1062         fs->e2fs_fmod = 1;
 1063         EXT2_UNLOCK(ump);
 1064         bdwrite(bp);
 1065         return (0);
 1066 }
 1067 
 1068 /*
 1069  * Find a block in the specified cylinder group.
 1070  *
 1071  * It is a panic if a request is made to find a block if none are
 1072  * available.
 1073  */
 1074 static daddr_t
 1075 ext2_mapsearch(struct m_ext2fs *fs, char *bbp, daddr_t bpref)
 1076 {
 1077         int start, len, loc, i, map;
 1078 
 1079         /*
 1080          * find the fragment by searching through the free block
 1081          * map for an appropriate bit pattern
 1082          */
 1083         if (bpref)
 1084                 start = dtogd(fs, bpref) / NBBY;
 1085         else
 1086                 start = 0;
 1087         len = howmany(fs->e2fs->e2fs_fpg, NBBY) - start;
 1088         loc = skpc(0xff, len, &bbp[start]);
 1089         if (loc == 0) {
 1090                 len = start + 1;
 1091                 start = 0;
 1092                 loc = skpc(0xff, len, &bbp[start]);
 1093                 if (loc == 0) {
 1094                         printf("start = %d, len = %d, fs = %s\n",
 1095                                 start, len, fs->e2fs_fsmnt);
 1096                         panic("ext2fs_alloccg: map corrupted");
 1097                         /* NOTREACHED */
 1098                 }
 1099         }
 1100         i = start + len - loc;
 1101         map = bbp[i] ^ 0xff;
 1102         if (map == 0) {
 1103                 printf("fs = %s\n", fs->e2fs_fsmnt);
 1104                 panic("ext2fs_mapsearch: block not in map");
 1105         }
 1106         return (i * NBBY + ffs(map) - 1);
 1107 }
 1108 
 1109 /*
 1110  * Fserr prints the name of a file system with an error diagnostic.
 1111  * 
 1112  * The form of the error message is:
 1113  *      fs: error message
 1114  */
 1115 static void
 1116 ext2_fserr(fs, uid, cp)
 1117         struct m_ext2fs *fs;
 1118         uid_t uid;
 1119         char *cp;
 1120 {
 1121 
 1122         log(LOG_ERR, "uid %u on %s: %s\n", uid, fs->e2fs_fsmnt, cp);
 1123 }
 1124 
 1125 int
 1126 cg_has_sb(int i)
 1127 {
 1128         int a3, a5, a7;
 1129 
 1130         if (i == 0 || i == 1)
 1131                 return 1;
 1132         for (a3 = 3, a5 = 5, a7 = 7;
 1133             a3 <= i || a5 <= i || a7 <= i;
 1134             a3 *= 3, a5 *= 5, a7 *= 7)
 1135                 if (i == a3 || i == a5 || i == a7)
 1136                         return 1;
 1137         return 0;
 1138 }

Cache object: 67acd66a3d7b88a7c6565c3db0dcbc40


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