|
|
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
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.