Annotation of linux/fs/ext/bitmap.c, revision 1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.