home *** CD-ROM | disk | FTP | other *** search
/ Il CD di internet / CD.iso / SOURCE / KERNEL-S / V1.0 / LINUX-1.0 / LINUX-1 / linux / fs / minix / bitmap.c next >
Encoding:
C/C++ Source or Header  |  1993-12-01  |  5.4 KB  |  231 lines

  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,
  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)
  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.     bh->b_dirt = 1;
  97.     return;
  98. }
  99.  
  100. int minix_new_block(struct super_block * sb)
  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.     bh->b_dirt = 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.     bh->b_dirt = 1;
  133.     brelse(bh);
  134.     return j;
  135. }
  136.  
  137. unsigned long minix_count_free_blocks(struct super_block *sb)
  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)
  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.     bh->b_dirt = 1;
  179. }
  180.  
  181. struct inode * minix_new_inode(const struct inode * dir)
  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.     bh->b_dirt = 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)
  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. }
  231.