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/ufs/ffs/ffs_subr.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 /*-
    2  * Copyright (c) 1982, 1986, 1989, 1993
    3  *      The Regents of the University of California.  All rights reserved.
    4  *
    5  * Redistribution and use in source and binary forms, with or without
    6  * modification, are permitted provided that the following conditions
    7  * are met:
    8  * 1. Redistributions of source code must retain the above copyright
    9  *    notice, this list of conditions and the following disclaimer.
   10  * 2. Redistributions in binary form must reproduce the above copyright
   11  *    notice, this list of conditions and the following disclaimer in the
   12  *    documentation and/or other materials provided with the distribution.
   13  * 4. Neither the name of the University nor the names of its contributors
   14  *    may be used to endorse or promote products derived from this software
   15  *    without specific prior written permission.
   16  *
   17  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   27  * SUCH DAMAGE.
   28  *
   29  *      @(#)ffs_subr.c  8.5 (Berkeley) 3/21/95
   30  */
   31 
   32 #include <sys/cdefs.h>
   33 __FBSDID("$FreeBSD: releng/10.1/sys/ufs/ffs/ffs_subr.c 207141 2010-04-24 07:05:35Z jeff $");
   34 
   35 #include <sys/param.h>
   36 
   37 #ifndef _KERNEL
   38 #include <ufs/ufs/dinode.h>
   39 #include <ufs/ffs/fs.h>
   40 #else
   41 #include <sys/systm.h>
   42 #include <sys/lock.h>
   43 #include <sys/malloc.h>
   44 #include <sys/mount.h>
   45 #include <sys/vnode.h>
   46 #include <sys/bio.h>
   47 #include <sys/buf.h>
   48 #include <sys/ucred.h>
   49 
   50 #include <ufs/ufs/quota.h>
   51 #include <ufs/ufs/inode.h>
   52 #include <ufs/ufs/extattr.h>
   53 #include <ufs/ufs/ufsmount.h>
   54 #include <ufs/ufs/ufs_extern.h>
   55 #include <ufs/ffs/ffs_extern.h>
   56 #include <ufs/ffs/fs.h>
   57 
   58 #ifdef KDB
   59 void    ffs_checkoverlap(struct buf *, struct inode *);
   60 #endif
   61 
   62 /*
   63  * Return buffer with the contents of block "offset" from the beginning of
   64  * directory "ip".  If "res" is non-zero, fill it in with a pointer to the
   65  * remaining space in the directory.
   66  */
   67 int
   68 ffs_blkatoff(vp, offset, res, bpp)
   69         struct vnode *vp;
   70         off_t offset;
   71         char **res;
   72         struct buf **bpp;
   73 {
   74         struct inode *ip;
   75         struct fs *fs;
   76         struct buf *bp;
   77         ufs_lbn_t lbn;
   78         int bsize, error;
   79 
   80         ip = VTOI(vp);
   81         fs = ip->i_fs;
   82         lbn = lblkno(fs, offset);
   83         bsize = blksize(fs, ip, lbn);
   84 
   85         *bpp = NULL;
   86         error = bread(vp, lbn, bsize, NOCRED, &bp);
   87         if (error) {
   88                 brelse(bp);
   89                 return (error);
   90         }
   91         if (res)
   92                 *res = (char *)bp->b_data + blkoff(fs, offset);
   93         *bpp = bp;
   94         return (0);
   95 }
   96 
   97 /*
   98  * Load up the contents of an inode and copy the appropriate pieces
   99  * to the incore copy.
  100  */
  101 void
  102 ffs_load_inode(bp, ip, fs, ino)
  103         struct buf *bp;
  104         struct inode *ip;
  105         struct fs *fs;
  106         ino_t ino;
  107 {
  108 
  109         if (ip->i_ump->um_fstype == UFS1) {
  110                 *ip->i_din1 =
  111                     *((struct ufs1_dinode *)bp->b_data + ino_to_fsbo(fs, ino));
  112                 ip->i_mode = ip->i_din1->di_mode;
  113                 ip->i_nlink = ip->i_din1->di_nlink;
  114                 ip->i_size = ip->i_din1->di_size;
  115                 ip->i_flags = ip->i_din1->di_flags;
  116                 ip->i_gen = ip->i_din1->di_gen;
  117                 ip->i_uid = ip->i_din1->di_uid;
  118                 ip->i_gid = ip->i_din1->di_gid;
  119         } else {
  120                 *ip->i_din2 =
  121                     *((struct ufs2_dinode *)bp->b_data + ino_to_fsbo(fs, ino));
  122                 ip->i_mode = ip->i_din2->di_mode;
  123                 ip->i_nlink = ip->i_din2->di_nlink;
  124                 ip->i_size = ip->i_din2->di_size;
  125                 ip->i_flags = ip->i_din2->di_flags;
  126                 ip->i_gen = ip->i_din2->di_gen;
  127                 ip->i_uid = ip->i_din2->di_uid;
  128                 ip->i_gid = ip->i_din2->di_gid;
  129         }
  130 }
  131 #endif /* KERNEL */
  132 
  133 /*
  134  * Update the frsum fields to reflect addition or deletion
  135  * of some frags.
  136  */
  137 void
  138 ffs_fragacct(fs, fragmap, fraglist, cnt)
  139         struct fs *fs;
  140         int fragmap;
  141         int32_t fraglist[];
  142         int cnt;
  143 {
  144         int inblk;
  145         int field, subfield;
  146         int siz, pos;
  147 
  148         inblk = (int)(fragtbl[fs->fs_frag][fragmap]) << 1;
  149         fragmap <<= 1;
  150         for (siz = 1; siz < fs->fs_frag; siz++) {
  151                 if ((inblk & (1 << (siz + (fs->fs_frag % NBBY)))) == 0)
  152                         continue;
  153                 field = around[siz];
  154                 subfield = inside[siz];
  155                 for (pos = siz; pos <= fs->fs_frag; pos++) {
  156                         if ((fragmap & field) == subfield) {
  157                                 fraglist[siz] += cnt;
  158                                 pos += siz;
  159                                 field <<= siz;
  160                                 subfield <<= siz;
  161                         }
  162                         field <<= 1;
  163                         subfield <<= 1;
  164                 }
  165         }
  166 }
  167 
  168 #ifdef KDB
  169 void
  170 ffs_checkoverlap(bp, ip)
  171         struct buf *bp;
  172         struct inode *ip;
  173 {
  174         struct buf *ebp, *ep;
  175         ufs2_daddr_t start, last;
  176         struct vnode *vp;
  177 
  178         ebp = &buf[nbuf];
  179         start = bp->b_blkno;
  180         last = start + btodb(bp->b_bcount) - 1;
  181         for (ep = buf; ep < ebp; ep++) {
  182                 if (ep == bp || (ep->b_flags & B_INVAL) ||
  183                     ep->b_vp == NULLVP)
  184                         continue;
  185                 vp = ip->i_devvp;
  186                 /* look for overlap */
  187                 if (ep->b_bcount == 0 || ep->b_blkno > last ||
  188                     ep->b_blkno + btodb(ep->b_bcount) <= start)
  189                         continue;
  190                 vprint("Disk overlap", vp);
  191                 printf("\tstart %jd, end %jd overlap start %jd, end %jd\n",
  192                     (intmax_t)start, (intmax_t)last, (intmax_t)ep->b_blkno,
  193                     (intmax_t)(ep->b_blkno + btodb(ep->b_bcount) - 1));
  194                 panic("ffs_checkoverlap: Disk buffer overlap");
  195         }
  196 }
  197 #endif /* KDB */
  198 
  199 /*
  200  * block operations
  201  *
  202  * check if a block is available
  203  */
  204 int
  205 ffs_isblock(fs, cp, h)
  206         struct fs *fs;
  207         unsigned char *cp;
  208         ufs1_daddr_t h;
  209 {
  210         unsigned char mask;
  211 
  212         switch ((int)fs->fs_frag) {
  213         case 8:
  214                 return (cp[h] == 0xff);
  215         case 4:
  216                 mask = 0x0f << ((h & 0x1) << 2);
  217                 return ((cp[h >> 1] & mask) == mask);
  218         case 2:
  219                 mask = 0x03 << ((h & 0x3) << 1);
  220                 return ((cp[h >> 2] & mask) == mask);
  221         case 1:
  222                 mask = 0x01 << (h & 0x7);
  223                 return ((cp[h >> 3] & mask) == mask);
  224         default:
  225 #ifdef _KERNEL
  226                 panic("ffs_isblock");
  227 #endif
  228                 break;
  229         }
  230         return (0);
  231 }
  232 
  233 /*
  234  * check if a block is free
  235  */
  236 int
  237 ffs_isfreeblock(fs, cp, h)
  238         struct fs *fs;
  239         u_char *cp;
  240         ufs1_daddr_t h;
  241 {
  242  
  243         switch ((int)fs->fs_frag) {
  244         case 8:
  245                 return (cp[h] == 0);
  246         case 4:
  247                 return ((cp[h >> 1] & (0x0f << ((h & 0x1) << 2))) == 0);
  248         case 2:
  249                 return ((cp[h >> 2] & (0x03 << ((h & 0x3) << 1))) == 0);
  250         case 1:
  251                 return ((cp[h >> 3] & (0x01 << (h & 0x7))) == 0);
  252         default:
  253 #ifdef _KERNEL
  254                 panic("ffs_isfreeblock");
  255 #endif
  256                 break;
  257         }
  258         return (0);
  259 }
  260 
  261 /*
  262  * take a block out of the map
  263  */
  264 void
  265 ffs_clrblock(fs, cp, h)
  266         struct fs *fs;
  267         u_char *cp;
  268         ufs1_daddr_t h;
  269 {
  270 
  271         switch ((int)fs->fs_frag) {
  272         case 8:
  273                 cp[h] = 0;
  274                 return;
  275         case 4:
  276                 cp[h >> 1] &= ~(0x0f << ((h & 0x1) << 2));
  277                 return;
  278         case 2:
  279                 cp[h >> 2] &= ~(0x03 << ((h & 0x3) << 1));
  280                 return;
  281         case 1:
  282                 cp[h >> 3] &= ~(0x01 << (h & 0x7));
  283                 return;
  284         default:
  285 #ifdef _KERNEL
  286                 panic("ffs_clrblock");
  287 #endif
  288                 break;
  289         }
  290 }
  291 
  292 /*
  293  * put a block into the map
  294  */
  295 void
  296 ffs_setblock(fs, cp, h)
  297         struct fs *fs;
  298         unsigned char *cp;
  299         ufs1_daddr_t h;
  300 {
  301 
  302         switch ((int)fs->fs_frag) {
  303 
  304         case 8:
  305                 cp[h] = 0xff;
  306                 return;
  307         case 4:
  308                 cp[h >> 1] |= (0x0f << ((h & 0x1) << 2));
  309                 return;
  310         case 2:
  311                 cp[h >> 2] |= (0x03 << ((h & 0x3) << 1));
  312                 return;
  313         case 1:
  314                 cp[h >> 3] |= (0x01 << (h & 0x7));
  315                 return;
  316         default:
  317 #ifdef _KERNEL
  318                 panic("ffs_setblock");
  319 #endif
  320                 break;
  321         }
  322 }
  323 
  324 /*
  325  * Update the cluster map because of an allocation or free.
  326  *
  327  * Cnt == 1 means free; cnt == -1 means allocating.
  328  */
  329 void
  330 ffs_clusteracct(fs, cgp, blkno, cnt)
  331         struct fs *fs;
  332         struct cg *cgp;
  333         ufs1_daddr_t blkno;
  334         int cnt;
  335 {
  336         int32_t *sump;
  337         int32_t *lp;
  338         u_char *freemapp, *mapp;
  339         int i, start, end, forw, back, map, bit;
  340 
  341         if (fs->fs_contigsumsize <= 0)
  342                 return;
  343         freemapp = cg_clustersfree(cgp);
  344         sump = cg_clustersum(cgp);
  345         /*
  346          * Allocate or clear the actual block.
  347          */
  348         if (cnt > 0)
  349                 setbit(freemapp, blkno);
  350         else
  351                 clrbit(freemapp, blkno);
  352         /*
  353          * Find the size of the cluster going forward.
  354          */
  355         start = blkno + 1;
  356         end = start + fs->fs_contigsumsize;
  357         if (end >= cgp->cg_nclusterblks)
  358                 end = cgp->cg_nclusterblks;
  359         mapp = &freemapp[start / NBBY];
  360         map = *mapp++;
  361         bit = 1 << (start % NBBY);
  362         for (i = start; i < end; i++) {
  363                 if ((map & bit) == 0)
  364                         break;
  365                 if ((i & (NBBY - 1)) != (NBBY - 1)) {
  366                         bit <<= 1;
  367                 } else {
  368                         map = *mapp++;
  369                         bit = 1;
  370                 }
  371         }
  372         forw = i - start;
  373         /*
  374          * Find the size of the cluster going backward.
  375          */
  376         start = blkno - 1;
  377         end = start - fs->fs_contigsumsize;
  378         if (end < 0)
  379                 end = -1;
  380         mapp = &freemapp[start / NBBY];
  381         map = *mapp--;
  382         bit = 1 << (start % NBBY);
  383         for (i = start; i > end; i--) {
  384                 if ((map & bit) == 0)
  385                         break;
  386                 if ((i & (NBBY - 1)) != 0) {
  387                         bit >>= 1;
  388                 } else {
  389                         map = *mapp--;
  390                         bit = 1 << (NBBY - 1);
  391                 }
  392         }
  393         back = start - i;
  394         /*
  395          * Account for old cluster and the possibly new forward and
  396          * back clusters.
  397          */
  398         i = back + forw + 1;
  399         if (i > fs->fs_contigsumsize)
  400                 i = fs->fs_contigsumsize;
  401         sump[i] += cnt;
  402         if (back > 0)
  403                 sump[back] -= cnt;
  404         if (forw > 0)
  405                 sump[forw] -= cnt;
  406         /*
  407          * Update cluster summary information.
  408          */
  409         lp = &sump[fs->fs_contigsumsize];
  410         for (i = fs->fs_contigsumsize; i > 0; i--)
  411                 if (*lp-- > 0)
  412                         break;
  413         fs->fs_maxcluster[cgp->cg_cgx] = i;
  414 }

Cache object: d36461879cbe7a646a35fcafccf0df33


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