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

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

unix.superglobalmegacorp.com

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