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$");
   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 /*
   59  * Return buffer with the contents of block "offset" from the beginning of
   60  * directory "ip".  If "res" is non-zero, fill it in with a pointer to the
   61  * remaining space in the directory.
   62  */
   63 int
   64 ffs_blkatoff(vp, offset, res, bpp)
   65         struct vnode *vp;
   66         off_t offset;
   67         char **res;
   68         struct buf **bpp;
   69 {
   70         struct inode *ip;
   71         struct fs *fs;
   72         struct buf *bp;
   73         ufs_lbn_t lbn;
   74         int bsize, error;
   75 
   76         ip = VTOI(vp);
   77         fs = ITOFS(ip);
   78         lbn = lblkno(fs, offset);
   79         bsize = blksize(fs, ip, lbn);
   80 
   81         *bpp = NULL;
   82         error = bread(vp, lbn, bsize, NOCRED, &bp);
   83         if (error) {
   84                 brelse(bp);
   85                 return (error);
   86         }
   87         if (res)
   88                 *res = (char *)bp->b_data + blkoff(fs, offset);
   89         *bpp = bp;
   90         return (0);
   91 }
   92 
   93 /*
   94  * Load up the contents of an inode and copy the appropriate pieces
   95  * to the incore copy.
   96  */
   97 void
   98 ffs_load_inode(bp, ip, fs, ino)
   99         struct buf *bp;
  100         struct inode *ip;
  101         struct fs *fs;
  102         ino_t ino;
  103 {
  104 
  105         if (I_IS_UFS1(ip)) {
  106                 *ip->i_din1 =
  107                     *((struct ufs1_dinode *)bp->b_data + ino_to_fsbo(fs, ino));
  108                 ip->i_mode = ip->i_din1->di_mode;
  109                 ip->i_nlink = ip->i_din1->di_nlink;
  110                 ip->i_size = ip->i_din1->di_size;
  111                 ip->i_flags = ip->i_din1->di_flags;
  112                 ip->i_gen = ip->i_din1->di_gen;
  113                 ip->i_uid = ip->i_din1->di_uid;
  114                 ip->i_gid = ip->i_din1->di_gid;
  115         } else {
  116                 *ip->i_din2 =
  117                     *((struct ufs2_dinode *)bp->b_data + ino_to_fsbo(fs, ino));
  118                 ip->i_mode = ip->i_din2->di_mode;
  119                 ip->i_nlink = ip->i_din2->di_nlink;
  120                 ip->i_size = ip->i_din2->di_size;
  121                 ip->i_flags = ip->i_din2->di_flags;
  122                 ip->i_gen = ip->i_din2->di_gen;
  123                 ip->i_uid = ip->i_din2->di_uid;
  124                 ip->i_gid = ip->i_din2->di_gid;
  125         }
  126 }
  127 #endif /* KERNEL */
  128 
  129 /*
  130  * Update the frsum fields to reflect addition or deletion
  131  * of some frags.
  132  */
  133 void
  134 ffs_fragacct(fs, fragmap, fraglist, cnt)
  135         struct fs *fs;
  136         int fragmap;
  137         int32_t fraglist[];
  138         int cnt;
  139 {
  140         int inblk;
  141         int field, subfield;
  142         int siz, pos;
  143 
  144         inblk = (int)(fragtbl[fs->fs_frag][fragmap]) << 1;
  145         fragmap <<= 1;
  146         for (siz = 1; siz < fs->fs_frag; siz++) {
  147                 if ((inblk & (1 << (siz + (fs->fs_frag % NBBY)))) == 0)
  148                         continue;
  149                 field = around[siz];
  150                 subfield = inside[siz];
  151                 for (pos = siz; pos <= fs->fs_frag; pos++) {
  152                         if ((fragmap & field) == subfield) {
  153                                 fraglist[siz] += cnt;
  154                                 pos += siz;
  155                                 field <<= siz;
  156                                 subfield <<= siz;
  157                         }
  158                         field <<= 1;
  159                         subfield <<= 1;
  160                 }
  161         }
  162 }
  163 
  164 /*
  165  * block operations
  166  *
  167  * check if a block is available
  168  */
  169 int
  170 ffs_isblock(fs, cp, h)
  171         struct fs *fs;
  172         unsigned char *cp;
  173         ufs1_daddr_t h;
  174 {
  175         unsigned char mask;
  176 
  177         switch ((int)fs->fs_frag) {
  178         case 8:
  179                 return (cp[h] == 0xff);
  180         case 4:
  181                 mask = 0x0f << ((h & 0x1) << 2);
  182                 return ((cp[h >> 1] & mask) == mask);
  183         case 2:
  184                 mask = 0x03 << ((h & 0x3) << 1);
  185                 return ((cp[h >> 2] & mask) == mask);
  186         case 1:
  187                 mask = 0x01 << (h & 0x7);
  188                 return ((cp[h >> 3] & mask) == mask);
  189         default:
  190 #ifdef _KERNEL
  191                 panic("ffs_isblock");
  192 #endif
  193                 break;
  194         }
  195         return (0);
  196 }
  197 
  198 /*
  199  * check if a block is free
  200  */
  201 int
  202 ffs_isfreeblock(fs, cp, h)
  203         struct fs *fs;
  204         u_char *cp;
  205         ufs1_daddr_t h;
  206 {
  207  
  208         switch ((int)fs->fs_frag) {
  209         case 8:
  210                 return (cp[h] == 0);
  211         case 4:
  212                 return ((cp[h >> 1] & (0x0f << ((h & 0x1) << 2))) == 0);
  213         case 2:
  214                 return ((cp[h >> 2] & (0x03 << ((h & 0x3) << 1))) == 0);
  215         case 1:
  216                 return ((cp[h >> 3] & (0x01 << (h & 0x7))) == 0);
  217         default:
  218 #ifdef _KERNEL
  219                 panic("ffs_isfreeblock");
  220 #endif
  221                 break;
  222         }
  223         return (0);
  224 }
  225 
  226 /*
  227  * take a block out of the map
  228  */
  229 void
  230 ffs_clrblock(fs, cp, h)
  231         struct fs *fs;
  232         u_char *cp;
  233         ufs1_daddr_t h;
  234 {
  235 
  236         switch ((int)fs->fs_frag) {
  237         case 8:
  238                 cp[h] = 0;
  239                 return;
  240         case 4:
  241                 cp[h >> 1] &= ~(0x0f << ((h & 0x1) << 2));
  242                 return;
  243         case 2:
  244                 cp[h >> 2] &= ~(0x03 << ((h & 0x3) << 1));
  245                 return;
  246         case 1:
  247                 cp[h >> 3] &= ~(0x01 << (h & 0x7));
  248                 return;
  249         default:
  250 #ifdef _KERNEL
  251                 panic("ffs_clrblock");
  252 #endif
  253                 break;
  254         }
  255 }
  256 
  257 /*
  258  * put a block into the map
  259  */
  260 void
  261 ffs_setblock(fs, cp, h)
  262         struct fs *fs;
  263         unsigned char *cp;
  264         ufs1_daddr_t h;
  265 {
  266 
  267         switch ((int)fs->fs_frag) {
  268 
  269         case 8:
  270                 cp[h] = 0xff;
  271                 return;
  272         case 4:
  273                 cp[h >> 1] |= (0x0f << ((h & 0x1) << 2));
  274                 return;
  275         case 2:
  276                 cp[h >> 2] |= (0x03 << ((h & 0x3) << 1));
  277                 return;
  278         case 1:
  279                 cp[h >> 3] |= (0x01 << (h & 0x7));
  280                 return;
  281         default:
  282 #ifdef _KERNEL
  283                 panic("ffs_setblock");
  284 #endif
  285                 break;
  286         }
  287 }
  288 
  289 /*
  290  * Update the cluster map because of an allocation or free.
  291  *
  292  * Cnt == 1 means free; cnt == -1 means allocating.
  293  */
  294 void
  295 ffs_clusteracct(fs, cgp, blkno, cnt)
  296         struct fs *fs;
  297         struct cg *cgp;
  298         ufs1_daddr_t blkno;
  299         int cnt;
  300 {
  301         int32_t *sump;
  302         int32_t *lp;
  303         u_char *freemapp, *mapp;
  304         int i, start, end, forw, back, map, bit;
  305 
  306         if (fs->fs_contigsumsize <= 0)
  307                 return;
  308         freemapp = cg_clustersfree(cgp);
  309         sump = cg_clustersum(cgp);
  310         /*
  311          * Allocate or clear the actual block.
  312          */
  313         if (cnt > 0)
  314                 setbit(freemapp, blkno);
  315         else
  316                 clrbit(freemapp, blkno);
  317         /*
  318          * Find the size of the cluster going forward.
  319          */
  320         start = blkno + 1;
  321         end = start + fs->fs_contigsumsize;
  322         if (end >= cgp->cg_nclusterblks)
  323                 end = cgp->cg_nclusterblks;
  324         mapp = &freemapp[start / NBBY];
  325         map = *mapp++;
  326         bit = 1 << (start % NBBY);
  327         for (i = start; i < end; i++) {
  328                 if ((map & bit) == 0)
  329                         break;
  330                 if ((i & (NBBY - 1)) != (NBBY - 1)) {
  331                         bit <<= 1;
  332                 } else {
  333                         map = *mapp++;
  334                         bit = 1;
  335                 }
  336         }
  337         forw = i - start;
  338         /*
  339          * Find the size of the cluster going backward.
  340          */
  341         start = blkno - 1;
  342         end = start - fs->fs_contigsumsize;
  343         if (end < 0)
  344                 end = -1;
  345         mapp = &freemapp[start / NBBY];
  346         map = *mapp--;
  347         bit = 1 << (start % NBBY);
  348         for (i = start; i > end; i--) {
  349                 if ((map & bit) == 0)
  350                         break;
  351                 if ((i & (NBBY - 1)) != 0) {
  352                         bit >>= 1;
  353                 } else {
  354                         map = *mapp--;
  355                         bit = 1 << (NBBY - 1);
  356                 }
  357         }
  358         back = start - i;
  359         /*
  360          * Account for old cluster and the possibly new forward and
  361          * back clusters.
  362          */
  363         i = back + forw + 1;
  364         if (i > fs->fs_contigsumsize)
  365                 i = fs->fs_contigsumsize;
  366         sump[i] += cnt;
  367         if (back > 0)
  368                 sump[back] -= cnt;
  369         if (forw > 0)
  370                 sump[forw] -= cnt;
  371         /*
  372          * Update cluster summary information.
  373          */
  374         lp = &sump[fs->fs_contigsumsize];
  375         for (i = fs->fs_contigsumsize; i > 0; i--)
  376                 if (*lp-- > 0)
  377                         break;
  378         fs->fs_maxcluster[cgp->cg_cgx] = i;
  379 }

Cache object: a6fe7e39878f084f73d6c43dd8a3f035


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