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

1.1     ! root        1: /*
        !             2:  *  linux/fs/ext/freelists.c
        !             3:  *
        !             4:  *  (C) 1992  Remy Card ([email protected])
        !             5:  *
        !             6:  */
        !             7: 
        !             8: /* freelists.c contains the code that handles the inode and block free lists */
        !             9: 
        !            10: 
        !            11: /*
        !            12: 
        !            13:    The free blocks are managed by a linked list. The super block contains the
        !            14:    number of the first free block. This block contains 254 numbers of other
        !            15:    free blocks and the number of the next block in the list.
        !            16: 
        !            17:    When an ext fs is mounted, the number of the first free block is stored
        !            18:    in s->s_zmap[0] and the block header is stored in s->s_zmap[1]. s_zmap[2]
        !            19:    contains the count of free blocks.
        !            20: 
        !            21:    Currently, it is a hack to allow this kind of management with the super_block
        !            22:    structure.
        !            23:    Perhaps, in the future, we may have to change the super_block structure to
        !            24:    include dedicated fields.
        !            25: 
        !            26:    The free inodes are also managed by a linked list in a similar way. The
        !            27:    super block contains the number of the first free inode. This inode contains
        !            28:    14 numbers of other free inodes and the number of the next inode in the list.
        !            29:    
        !            30:    The number of the first free inode is stored in s->s_imap[0] and the header
        !            31:    of the block containing the inode is stored in s->s_imap[1]. s_imap[2] contains
        !            32:    the count of free inodes.
        !            33: 
        !            34: */
        !            35: 
        !            36: #include <linux/string.h>
        !            37: 
        !            38: #include <linux/sched.h>
        !            39: #include <linux/ext_fs.h>
        !            40: #include <linux/kernel.h>
        !            41: 
        !            42: #ifdef EXTFS_FREELIST
        !            43: 
        !            44: #define clear_block(addr) \
        !            45: __asm__("cld\n\t" \
        !            46:         "rep\n\t" \
        !            47:         "stosl" \
        !            48:         ::"a" (0),"c" (BLOCK_SIZE/4),"D" ((long) (addr)):"cx","di")
        !            49: 
        !            50: int ext_free_block(int dev, int block)
        !            51: {
        !            52:        struct super_block * sb;
        !            53:        struct buffer_head * bh;
        !            54:        struct ext_free_block * efb;
        !            55: 
        !            56:        if (!(sb = get_super(dev)))
        !            57:                panic("trying to free block on nonexistent device");
        !            58:        lock_super (sb);
        !            59:        if (block < sb->s_firstdatazone || block >= sb->s_nzones)
        !            60:                panic("trying to free block not in datazone");
        !            61:        bh = get_hash_table(dev,block);
        !            62:        if (bh) {
        !            63:                if (bh->b_count > 1) {
        !            64:                        brelse(bh);
        !            65:                        free_super (sb);
        !            66:                        return 0;
        !            67:                }
        !            68:                bh->b_dirt=0;
        !            69:                bh->b_uptodate=0;
        !            70:                if (bh->b_count)
        !            71:                        brelse(bh);
        !            72:        }
        !            73:        efb = (struct ext_free_block *) sb->s_zmap[1]->b_data;
        !            74:        if (efb->count == 254) {
        !            75: #ifdef EXTFS_DEBUG
        !            76: printk("ext_free_block: block full, skipping to %d\n", block);
        !            77: #endif
        !            78:                brelse (sb->s_zmap[1]);
        !            79:                if (!(sb->s_zmap[1] = bread (dev, block)))
        !            80:                        panic ("ext_free_block: unable to read block to free\n");
        !            81:                efb = (struct ext_free_block *) sb->s_zmap[1]->b_data;
        !            82:                efb->next = (unsigned long) sb->s_zmap[0];
        !            83:                efb->count = 0;
        !            84:                sb->s_zmap[0] = (struct buffer_head *) block;
        !            85:        } else {
        !            86:                efb->free[efb->count++] = block;
        !            87:        }
        !            88:        sb->s_zmap[2] = (struct buffer_head *) (((unsigned long) sb->s_zmap[2]) + 1);
        !            89:        sb->s_dirt = 1;
        !            90:        sb->s_zmap[1]->b_dirt = 1;
        !            91:        free_super (sb);
        !            92:        return 1;
        !            93: }
        !            94: 
        !            95: int ext_new_block(int dev)
        !            96: {
        !            97:        struct buffer_head * bh;
        !            98:        struct super_block * sb;
        !            99:        struct ext_free_block * efb;
        !           100:        int /* i, */ j;
        !           101: 
        !           102:        if (!(sb = get_super(dev)))
        !           103:                panic("trying to get new block from nonexistant device");
        !           104:        if (!sb->s_zmap[1])
        !           105:                return 0;
        !           106:        lock_super (sb);
        !           107:        efb = (struct ext_free_block *) sb->s_zmap[1]->b_data;
        !           108:        if (efb->count) {
        !           109:                j = efb->free[--efb->count];
        !           110:                sb->s_zmap[1]->b_dirt = 1;
        !           111:        } else {
        !           112: #ifdef EXTFS_DEBUG
        !           113: printk("ext_new_block: block empty, skipping to %d\n", efb->next);
        !           114: #endif
        !           115:                j = (unsigned long) sb->s_zmap[0];
        !           116:                sb->s_zmap[0] = (struct buffer_head *) efb->next;
        !           117:                brelse (sb->s_zmap[1]);
        !           118:                if (!sb->s_zmap[0]) {
        !           119:                        sb->s_zmap[1] = NULL;
        !           120:                } else {
        !           121:                        if (!(sb->s_zmap[1] = bread (dev, (unsigned long) sb->s_zmap[0])))
        !           122:                                panic ("ext_new_block: unable to read next free block\n");
        !           123:                }
        !           124:        }
        !           125:        if (j < sb->s_firstdatazone || j > sb->s_nzones) {
        !           126:                printk ("ext_new_block: blk = %d\n", j);
        !           127:                panic ("allocating block not in data zone\n");
        !           128:        }
        !           129:        sb->s_zmap[2] = (struct buffer_head *) (((unsigned long) sb->s_zmap[2]) - 1);
        !           130:        sb->s_dirt = 1;
        !           131: 
        !           132:        if (!(bh=getblk(dev,j)))
        !           133:                panic("new_block: cannot get block");
        !           134:        if (bh->b_count != 1)
        !           135:                panic("new block: count is != 1");
        !           136:        clear_block(bh->b_data);
        !           137:        bh->b_uptodate = 1;
        !           138:        bh->b_dirt = 1;
        !           139:        brelse(bh);
        !           140: #ifdef EXTFS_DEBUG
        !           141: printk("ext_new_block: allocating block %d\n", j);
        !           142: #endif
        !           143:        free_super (sb);
        !           144:        return j;
        !           145: }
        !           146: 
        !           147: unsigned long ext_count_free_blocks(struct super_block *sb)
        !           148: {
        !           149: #ifdef EXTFS_DEBUG
        !           150:        struct buffer_head * bh;
        !           151:        struct ext_free_block * efb;
        !           152:        unsigned long count, block;
        !           153: 
        !           154:        lock_super (sb);
        !           155:        if (!sb->s_zmap[1])
        !           156:                count = 0;
        !           157:        else {
        !           158:                efb = (struct ext_free_block *) sb->s_zmap[1]->b_data;
        !           159:                count = efb->count + 1;
        !           160:                block = efb->next;
        !           161:                while (block) {
        !           162:                        if (!(bh = bread (sb->s_dev, block))) {
        !           163:                                printk ("ext_count_free: error while reading free blocks list\n");
        !           164:                                block = 0;
        !           165:                        } else {
        !           166:                                efb = (struct ext_free_block *) bh->b_data;
        !           167:                                count += efb->count + 1;
        !           168:                                block = efb->next;
        !           169:                                brelse (bh);
        !           170:                        }
        !           171:                }
        !           172:        }
        !           173: printk("ext_count_free_blocks: stored = %d, computed = %d\n",
        !           174:        (unsigned long) sb->s_zmap[2], count);
        !           175:        free_super (sb);
        !           176:        return count;
        !           177: #else
        !           178:        return (unsigned long) sb->s_zmap[2];
        !           179: #endif
        !           180: }
        !           181: 
        !           182: void ext_free_inode(struct inode * inode)
        !           183: {
        !           184:        struct buffer_head * bh;
        !           185:        struct ext_free_inode * efi;
        !           186:        unsigned long block;
        !           187: 
        !           188:        if (!inode)
        !           189:                return;
        !           190:        if (!inode->i_dev) {
        !           191:                memset(inode,0,sizeof(*inode));
        !           192:                return;
        !           193:        }
        !           194:        if (inode->i_count>1) {
        !           195:                printk("free_inode: inode has count=%d\n",inode->i_count);
        !           196:                return;
        !           197:        }
        !           198:        if (inode->i_nlink) {
        !           199:                printk("free_inode: inode has nlink=%d\n",inode->i_nlink);
        !           200:                return;
        !           201:        }
        !           202:        if (!inode->i_sb) {
        !           203:                printk("free_inode: inode on nonexistent device\n");
        !           204:                return;
        !           205:        }
        !           206:        lock_super (inode->i_sb);
        !           207:        if (inode->i_ino < 1 || inode->i_ino > inode->i_sb->s_ninodes) {
        !           208:                printk("free_inode: inode 0 or nonexistent inode\n");
        !           209:                free_super (inode->i_sb);
        !           210:                return;
        !           211:        }
        !           212:        efi = ((struct ext_free_inode *) inode->i_sb->s_imap[1]->b_data) +
        !           213:                (((unsigned long) inode->i_sb->s_imap[0])-1)%EXT_INODES_PER_BLOCK;
        !           214:        if (efi->count == 14) {
        !           215: #ifdef EXTFS_DEBUG
        !           216: printk("ext_free_inode: inode full, skipping to %d\n", inode->i_ino);
        !           217: #endif
        !           218:                brelse (inode->i_sb->s_imap[1]);
        !           219:                block = 2 + (inode->i_ino - 1) / EXT_INODES_PER_BLOCK;
        !           220:                if (!(bh = bread(inode->i_dev, block)))
        !           221:                        panic("ext_free_inode: unable to read inode block\n");
        !           222:                efi = ((struct ext_free_inode *) bh->b_data) +
        !           223:                        (inode->i_ino - 1) % EXT_INODES_PER_BLOCK;
        !           224:                efi->next = (unsigned long) inode->i_sb->s_imap[0];
        !           225:                efi->count = 0;
        !           226:                inode->i_sb->s_imap[0] = (struct buffer_head *) inode->i_ino;
        !           227:                inode->i_sb->s_imap[1] = bh;
        !           228:        } else {
        !           229:                efi->free[efi->count++] = inode->i_ino;
        !           230:        }
        !           231:        inode->i_sb->s_imap[2] = (struct buffer_head *) (((unsigned long) inode->i_sb->s_imap[2]) + 1);
        !           232:        inode->i_sb->s_dirt = 1;
        !           233:        inode->i_sb->s_imap[1]->b_dirt = 1;
        !           234:        free_super (inode->i_sb);
        !           235:        memset(inode,0,sizeof(*inode));
        !           236: }
        !           237: 
        !           238: struct inode * ext_new_inode(int dev)
        !           239: {
        !           240:        struct inode * inode;
        !           241:        struct ext_free_inode * efi;
        !           242:        unsigned long block;
        !           243:        int /* i, */ j;
        !           244: 
        !           245:        if (!(inode=get_empty_inode()))
        !           246:                return NULL;
        !           247:        if (!(inode->i_sb = get_super(dev))) {
        !           248:                printk("new_inode: unknown device\n");
        !           249:                iput(inode);
        !           250:                return NULL;
        !           251:        }
        !           252:        if (!inode->i_sb->s_imap[1])
        !           253:                return 0;
        !           254:        lock_super (inode->i_sb);
        !           255:        efi = ((struct ext_free_inode *) inode->i_sb->s_imap[1]->b_data) +
        !           256:                (((unsigned long) inode->i_sb->s_imap[0])-1)%EXT_INODES_PER_BLOCK;
        !           257:        if (efi->count) {
        !           258:                j = efi->free[--efi->count];
        !           259:                inode->i_sb->s_imap[1]->b_dirt = 1;
        !           260:        } else {
        !           261: #ifdef EXTFS_DEBUG
        !           262: printk("ext_free_inode: inode empty, skipping to %d\n", efi->next);
        !           263: #endif
        !           264:                j = (unsigned long) inode->i_sb->s_imap[0];
        !           265:                if (efi->next < 1 || efi->next > inode->i_sb->s_ninodes) {
        !           266:                        printk ("efi->next = %d\n", efi->next);
        !           267:                        panic ("ext_new_inode: bad inode number in free list\n");
        !           268:                }
        !           269:                inode->i_sb->s_imap[0] = (struct buffer_head *) efi->next;
        !           270:                block = 2 + (((unsigned long) efi->next) - 1) / EXT_INODES_PER_BLOCK;
        !           271:                brelse (inode->i_sb->s_imap[1]);
        !           272:                if (!inode->i_sb->s_imap[0]) {
        !           273:                        inode->i_sb->s_imap[1] = NULL;
        !           274:                } else {
        !           275:                        if (!(inode->i_sb->s_imap[1] = bread (dev, block)))
        !           276:                                panic ("ext_new_inode: unable to read next free inode block\n");
        !           277:                }
        !           278:        }
        !           279:        inode->i_sb->s_imap[2] = (struct buffer_head *) (((unsigned long) inode->i_sb->s_imap[2]) - 1);
        !           280:        inode->i_sb->s_dirt = 1;
        !           281:        inode->i_count = 1;
        !           282:        inode->i_nlink = 1;
        !           283:        inode->i_dev = dev;
        !           284:        inode->i_uid = current->euid;
        !           285:        inode->i_gid = current->egid;
        !           286:        inode->i_dirt = 1;
        !           287:        inode->i_ino = j;
        !           288:        inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
        !           289:        inode->i_op = NULL;
        !           290: #ifdef EXTFS_DEBUG
        !           291: printk("ext_new_inode : allocating inode %d\n", inode->i_ino);
        !           292: #endif
        !           293:        free_super (inode->i_sb);
        !           294:        return inode;
        !           295: }
        !           296: 
        !           297: unsigned long ext_count_free_inodes(struct super_block *sb)
        !           298: {
        !           299: #ifdef EXTFS_DEBUG
        !           300:        struct buffer_head * bh;
        !           301:        struct ext_free_inode * efi;
        !           302:        unsigned long count, block, ino;
        !           303: 
        !           304:        lock_super (sb);
        !           305:        if (!sb->s_imap[1])
        !           306:                count = 0;
        !           307:        else {
        !           308:                efi = ((struct ext_free_inode *) sb->s_imap[1]->b_data) +
        !           309:                        ((((unsigned long) sb->s_imap[0])-1)%EXT_INODES_PER_BLOCK);
        !           310:                count = efi->count + 1;
        !           311:                ino = efi->next;
        !           312:                while (ino) {
        !           313:                        if (ino < 1 || ino > sb->s_ninodes) {
        !           314:                                printk ("s_imap[0] = %d, ino = %d\n", 
        !           315:                                        (int) sb->s_imap[0],ino);
        !           316:                                panic ("ext_count_fre_inodes: bad inode number in free list\n");
        !           317:                        }
        !           318:                        block = 2 + ((ino - 1) / EXT_INODES_PER_BLOCK);
        !           319:                        if (!(bh = bread (sb->s_dev, block))) {
        !           320:                                printk ("ext_count_free_inodes: error while reading free inodes list\n");
        !           321:                                block = 0;
        !           322:                        } else {
        !           323:                                efi = ((struct ext_free_inode *) bh->b_data) +
        !           324:                                        ((ino - 1) % EXT_INODES_PER_BLOCK);
        !           325:                                count += efi->count + 1;
        !           326:                                ino = efi->next;
        !           327:                                brelse (bh);
        !           328:                        }
        !           329:                }
        !           330:        }
        !           331: printk("ext_count_free_inodes: stored = %d, computed = %d\n",
        !           332:        (unsigned long) sb->s_imap[2], count);
        !           333:        free_super (sb);
        !           334:        return count;
        !           335: #else
        !           336:        return (unsigned long) sb->s_imap[2];
        !           337: #endif
        !           338: }
        !           339: 
        !           340: #endif

unix.superglobalmegacorp.com

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