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