|
|
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.