root/fs/minix/bitmap.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. count_used
  2. minix_free_block
  3. minix_new_block
  4. minix_count_free_blocks
  5. minix_free_inode
  6. minix_new_inode
  7. minix_count_free_inodes

   1 /*
   2  *  linux/fs/minix/bitmap.c
   3  *
   4  *  Copyright (C) 1991, 1992  Linus Torvalds
   5  */
   6 
   7 /* bitmap.c contains the code that handles the inode and block bitmaps */
   8 
   9 #include <linux/sched.h>
  10 #include <linux/minix_fs.h>
  11 #include <linux/stat.h>
  12 #include <linux/kernel.h>
  13 #include <linux/string.h>
  14 
  15 #include <asm/bitops.h>
  16 
  17 #define clear_block(addr) \
  18 __asm__("cld\n\t" \
  19         "rep\n\t" \
  20         "stosl" \
  21         : \
  22         :"a" (0),"c" (BLOCK_SIZE/4),"D" ((long) (addr)):"cx","di")
  23 
  24 #define find_first_zero(addr) ({ \
  25 int __res; \
  26 __asm__("cld\n" \
  27         "1:\tlodsl\n\t" \
  28         "notl %%eax\n\t" \
  29         "bsfl %%eax,%%edx\n\t" \
  30         "jne 2f\n\t" \
  31         "addl $32,%%ecx\n\t" \
  32         "cmpl $8192,%%ecx\n\t" \
  33         "jl 1b\n\t" \
  34         "xorl %%edx,%%edx\n" \
  35         "2:\taddl %%edx,%%ecx" \
  36         :"=c" (__res):"0" (0),"S" (addr):"ax","dx","si"); \
  37 __res;})
  38 
  39 static int nibblemap[] = { 0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4 };
  40 
  41 static unsigned long count_used(struct buffer_head *map[], unsigned numblocks,
     /* [previous][next][first][last][top][bottom][index][help] */
  42         unsigned numbits)
  43 {
  44         unsigned i, j, end, sum = 0;
  45         struct buffer_head *bh;
  46   
  47         for (i=0; (i<numblocks) && numbits; i++) {
  48                 if (!(bh=map[i])) 
  49                         return(0);
  50                 if (numbits >= (8*BLOCK_SIZE)) { 
  51                         end = BLOCK_SIZE;
  52                         numbits -= 8*BLOCK_SIZE;
  53                 } else {
  54                         int tmp;
  55                         end = numbits >> 3;
  56                         numbits &= 0x7;
  57                         tmp = bh->b_data[end] & ((1<<numbits)-1);
  58                         sum += nibblemap[tmp&0xf] + nibblemap[(tmp>>4)&0xf];
  59                         numbits = 0;
  60                 }  
  61                 for (j=0; j<end; j++)
  62                         sum += nibblemap[bh->b_data[j] & 0xf] 
  63                                 + nibblemap[(bh->b_data[j]>>4)&0xf];
  64         }
  65         return(sum);
  66 }
  67 
  68 void minix_free_block(struct super_block * sb, int block)
     /* [previous][next][first][last][top][bottom][index][help] */
  69 {
  70         struct buffer_head * bh;
  71         unsigned int bit,zone;
  72 
  73         if (!sb) {
  74                 printk("trying to free block on nonexistent device\n");
  75                 return;
  76         }
  77         if (block < sb->u.minix_sb.s_firstdatazone ||
  78             block >= sb->u.minix_sb.s_nzones) {
  79                 printk("trying to free block not in datazone\n");
  80                 return;
  81         }
  82         bh = get_hash_table(sb->s_dev,block,BLOCK_SIZE);
  83         if (bh)
  84                 bh->b_dirt=0;
  85         brelse(bh);
  86         zone = block - sb->u.minix_sb.s_firstdatazone + 1;
  87         bit = zone & 8191;
  88         zone >>= 13;
  89         bh = sb->u.minix_sb.s_zmap[zone];
  90         if (!bh) {
  91                 printk("minix_free_block: nonexistent bitmap buffer\n");
  92                 return;
  93         }
  94         if (!clear_bit(bit,bh->b_data))
  95                 printk("free_block (%04x:%d): bit already cleared\n",sb->s_dev,block);
  96         mark_buffer_dirty(bh, 1);
  97         return;
  98 }
  99 
 100 int minix_new_block(struct super_block * sb)
     /* [previous][next][first][last][top][bottom][index][help] */
 101 {
 102         struct buffer_head * bh;
 103         int i,j;
 104 
 105         if (!sb) {
 106                 printk("trying to get new block from nonexistent device\n");
 107                 return 0;
 108         }
 109 repeat:
 110         j = 8192;
 111         for (i=0 ; i<8 ; i++)
 112                 if ((bh=sb->u.minix_sb.s_zmap[i]) != NULL)
 113                         if ((j=find_first_zero(bh->b_data))<8192)
 114                                 break;
 115         if (i>=8 || !bh || j>=8192)
 116                 return 0;
 117         if (set_bit(j,bh->b_data)) {
 118                 printk("new_block: bit already set");
 119                 goto repeat;
 120         }
 121         mark_buffer_dirty(bh, 1);
 122         j += i*8192 + sb->u.minix_sb.s_firstdatazone-1;
 123         if (j < sb->u.minix_sb.s_firstdatazone ||
 124             j >= sb->u.minix_sb.s_nzones)
 125                 return 0;
 126         if (!(bh = getblk(sb->s_dev,j,BLOCK_SIZE))) {
 127                 printk("new_block: cannot get block");
 128                 return 0;
 129         }
 130         clear_block(bh->b_data);
 131         bh->b_uptodate = 1;
 132         mark_buffer_dirty(bh, 1);
 133         brelse(bh);
 134         return j;
 135 }
 136 
 137 unsigned long minix_count_free_blocks(struct super_block *sb)
     /* [previous][next][first][last][top][bottom][index][help] */
 138 {
 139         return (sb->u.minix_sb.s_nzones - count_used(sb->u.minix_sb.s_zmap,sb->u.minix_sb.s_zmap_blocks,sb->u.minix_sb.s_nzones))
 140                  << sb->u.minix_sb.s_log_zone_size;
 141 }
 142 
 143 void minix_free_inode(struct inode * inode)
     /* [previous][next][first][last][top][bottom][index][help] */
 144 {
 145         struct buffer_head * bh;
 146         unsigned long ino;
 147 
 148         if (!inode)
 149                 return;
 150         if (!inode->i_dev) {
 151                 printk("free_inode: inode has no device\n");
 152                 return;
 153         }
 154         if (inode->i_count != 1) {
 155                 printk("free_inode: inode has count=%d\n",inode->i_count);
 156                 return;
 157         }
 158         if (inode->i_nlink) {
 159                 printk("free_inode: inode has nlink=%d\n",inode->i_nlink);
 160                 return;
 161         }
 162         if (!inode->i_sb) {
 163                 printk("free_inode: inode on nonexistent device\n");
 164                 return;
 165         }
 166         if (inode->i_ino < 1 || inode->i_ino >= inode->i_sb->u.minix_sb.s_ninodes) {
 167                 printk("free_inode: inode 0 or nonexistent inode\n");
 168                 return;
 169         }
 170         ino = inode->i_ino;
 171         if (!(bh=inode->i_sb->u.minix_sb.s_imap[ino >> 13])) {
 172                 printk("free_inode: nonexistent imap in superblock\n");
 173                 return;
 174         }
 175         clear_inode(inode);
 176         if (!clear_bit(ino & 8191, bh->b_data))
 177                 printk("free_inode: bit %lu already cleared.\n",ino);
 178         mark_buffer_dirty(bh, 1);
 179 }
 180 
 181 struct inode * minix_new_inode(const struct inode * dir)
     /* [previous][next][first][last][top][bottom][index][help] */
 182 {
 183         struct super_block * sb;
 184         struct inode * inode;
 185         struct buffer_head * bh;
 186         int i,j;
 187 
 188         if (!dir || !(inode = get_empty_inode()))
 189                 return NULL;
 190         sb = dir->i_sb;
 191         inode->i_sb = sb;
 192         inode->i_flags = inode->i_sb->s_flags;
 193         j = 8192;
 194         for (i=0 ; i<8 ; i++)
 195                 if ((bh = inode->i_sb->u.minix_sb.s_imap[i]) != NULL)
 196                         if ((j=find_first_zero(bh->b_data))<8192)
 197                                 break;
 198         if (!bh || j >= 8192) {
 199                 iput(inode);
 200                 return NULL;
 201         }
 202         if (set_bit(j,bh->b_data)) {    /* shouldn't happen */
 203                 printk("new_inode: bit already set");
 204                 iput(inode);
 205                 return NULL;
 206         }
 207         mark_buffer_dirty(bh, 1);
 208         j += i*8192;
 209         if (!j || j >= inode->i_sb->u.minix_sb.s_ninodes) {
 210                 iput(inode);
 211                 return NULL;
 212         }
 213         inode->i_count = 1;
 214         inode->i_nlink = 1;
 215         inode->i_dev = sb->s_dev;
 216         inode->i_uid = current->euid;
 217         inode->i_gid = (dir->i_mode & S_ISGID) ? dir->i_gid : current->egid;
 218         inode->i_dirt = 1;
 219         inode->i_ino = j;
 220         inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
 221         inode->i_op = NULL;
 222         inode->i_blocks = inode->i_blksize = 0;
 223         insert_inode_hash(inode);
 224         return inode;
 225 }
 226 
 227 unsigned long minix_count_free_inodes(struct super_block *sb)
     /* [previous][next][first][last][top][bottom][index][help] */
 228 {
 229         return sb->u.minix_sb.s_ninodes - count_used(sb->u.minix_sb.s_imap,sb->u.minix_sb.s_imap_blocks,sb->u.minix_sb.s_ninodes);
 230 }

/* [previous][next][first][last][top][bottom][index][help] */