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

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