File: /usr/src/linux/fs/minix/bitmap.c

1     /*
2      *  linux/fs/minix/bitmap.c
3      *
4      *  Copyright (C) 1991, 1992  Linus Torvalds
5      */
6     
7     /*
8      * Modified for 680x0 by Hamish Macdonald
9      * Fixed for 680x0 by Andreas Schwab
10      */
11     
12     /* bitmap.c contains the code that handles the inode and block bitmaps */
13     
14     #include <linux/fs.h>
15     #include <linux/minix_fs.h>
16     #include <linux/locks.h>
17     
18     #include <asm/bitops.h>
19     
20     static int nibblemap[] = { 4,3,3,2,3,2,2,1,3,2,2,1,2,1,1,0 };
21     
22     static unsigned long count_free(struct buffer_head *map[], unsigned numblocks, __u32 numbits)
23     {
24     	unsigned i, j, sum = 0;
25     	struct buffer_head *bh;
26       
27     	for (i=0; i<numblocks-1; i++) {
28     		if (!(bh=map[i])) 
29     			return(0);
30     		for (j=0; j<BLOCK_SIZE; j++)
31     			sum += nibblemap[bh->b_data[j] & 0xf]
32     				+ nibblemap[(bh->b_data[j]>>4) & 0xf];
33     	}
34     
35     	if (numblocks==0 || !(bh=map[numblocks-1]))
36     		return(0);
37     	i = ((numbits-(numblocks-1)*BLOCK_SIZE*8)/16)*2;
38     	for (j=0; j<i; j++) {
39     		sum += nibblemap[bh->b_data[j] & 0xf]
40     			+ nibblemap[(bh->b_data[j]>>4) & 0xf];
41     	}
42     
43     	i = numbits%16;
44     	if (i!=0) {
45     		i = *(__u16 *)(&bh->b_data[j]) | ~((1<<i) - 1);
46     		sum += nibblemap[i & 0xf] + nibblemap[(i>>4) & 0xf];
47     		sum += nibblemap[(i>>8) & 0xf] + nibblemap[(i>>12) & 0xf];
48     	}
49     	return(sum);
50     }
51     
52     void minix_free_block(struct inode * inode, int block)
53     {
54     	struct super_block * sb = inode->i_sb;
55     	struct buffer_head * bh;
56     	unsigned int bit,zone;
57     
58     	if (!sb) {
59     		printk("trying to free block on nonexistent device\n");
60     		return;
61     	}
62     	if (block < sb->u.minix_sb.s_firstdatazone ||
63     	    block >= sb->u.minix_sb.s_nzones) {
64     		printk("trying to free block not in datazone\n");
65     		return;
66     	}
67     	zone = block - sb->u.minix_sb.s_firstdatazone + 1;
68     	bit = zone & 8191;
69     	zone >>= 13;
70     	if (zone >= sb->u.minix_sb.s_zmap_blocks) {
71     		printk("minix_free_block: nonexistent bitmap buffer\n");
72     		return;
73     	}
74     	bh = sb->u.minix_sb.s_zmap[zone];
75     	if (!minix_test_and_clear_bit(bit,bh->b_data))
76     		printk("free_block (%s:%d): bit already cleared\n",
77     		       kdevname(sb->s_dev), block);
78     	mark_buffer_dirty(bh);
79     	return;
80     }
81     
82     int minix_new_block(struct inode * inode)
83     {
84     	struct super_block * sb = inode->i_sb;
85     	struct buffer_head * bh;
86     	int i,j;
87     
88     	if (!sb) {
89     		printk("trying to get new block from nonexistent device\n");
90     		return 0;
91     	}
92     repeat:
93     	j = 8192;
94     	bh = NULL;
95     	for (i = 0; i < sb->u.minix_sb.s_zmap_blocks; i++) {
96     		bh = sb->u.minix_sb.s_zmap[i];
97     		if ((j = minix_find_first_zero_bit(bh->b_data, 8192)) < 8192)
98     			break;
99     	}
100     	if (!bh || j >= 8192)
101     		return 0;
102     	if (minix_test_and_set_bit(j,bh->b_data)) {
103     		printk("new_block: bit already set");
104     		goto repeat;
105     	}
106     	mark_buffer_dirty(bh);
107     	j += i*8192 + sb->u.minix_sb.s_firstdatazone-1;
108     	if (j < sb->u.minix_sb.s_firstdatazone ||
109     	    j >= sb->u.minix_sb.s_nzones)
110     		return 0;
111     	return j;
112     }
113     
114     unsigned long minix_count_free_blocks(struct super_block *sb)
115     {
116     	return (count_free(sb->u.minix_sb.s_zmap, sb->u.minix_sb.s_zmap_blocks,
117     		sb->u.minix_sb.s_nzones - sb->u.minix_sb.s_firstdatazone + 1)
118     		<< sb->u.minix_sb.s_log_zone_size);
119     }
120     
121     struct minix_inode *
122     minix_V1_raw_inode(struct super_block *sb, ino_t ino, struct buffer_head **bh)
123     {
124     	int block;
125     	struct minix_sb_info *sbi = &sb->u.minix_sb;
126     	struct minix_inode *p;
127     
128     	if (!ino || ino > sbi->s_ninodes) {
129     		printk("Bad inode number on dev %s: %ld is out of range\n",
130     		       bdevname(sb->s_dev), ino);
131     		return NULL;
132     	}
133     	ino--;
134     	block = 2 + sbi->s_imap_blocks + sbi->s_zmap_blocks +
135     		 ino / MINIX_INODES_PER_BLOCK;
136     	*bh = bread(sb->s_dev, block, BLOCK_SIZE);
137     	if (!*bh) {
138     		printk("unable to read i-node block\n");
139     		return NULL;
140     	}
141     	p = (void *)(*bh)->b_data;
142     	return p + ino % MINIX_INODES_PER_BLOCK;
143     }
144     
145     struct minix2_inode *
146     minix_V2_raw_inode(struct super_block *sb, ino_t ino, struct buffer_head **bh)
147     {
148     	int block;
149     	struct minix_sb_info *sbi = &sb->u.minix_sb;
150     	struct minix2_inode *p;
151     
152     	*bh = NULL;
153     	if (!ino || ino > sbi->s_ninodes) {
154     		printk("Bad inode number on dev %s: %ld is out of range\n",
155     		       bdevname(sb->s_dev), ino);
156     		return NULL;
157     	}
158     	ino--;
159     	block = 2 + sbi->s_imap_blocks + sbi->s_zmap_blocks +
160     		 ino / MINIX2_INODES_PER_BLOCK;
161     	*bh = bread(sb->s_dev, block, BLOCK_SIZE);
162     	if (!*bh) {
163     		printk("unable to read i-node block\n");
164     		return NULL;
165     	}
166     	p = (void *)(*bh)->b_data;
167     	return p + ino % MINIX2_INODES_PER_BLOCK;
168     }
169     
170     /* Clear the link count and mode of a deleted inode on disk. */
171     
172     static void minix_clear_inode(struct inode *inode)
173     {
174     	struct buffer_head *bh;
175     	if (INODE_VERSION(inode) == MINIX_V1) {
176     		struct minix_inode *raw_inode;
177     		raw_inode = minix_V1_raw_inode(inode->i_sb, inode->i_ino, &bh);
178     		if (raw_inode) {
179     			raw_inode->i_nlinks = 0;
180     			raw_inode->i_mode = 0;
181     		}
182     	} else {
183     		struct minix2_inode *raw_inode;
184     		raw_inode = minix_V2_raw_inode(inode->i_sb, inode->i_ino, &bh);
185     		if (raw_inode) {
186     			raw_inode->i_nlinks = 0;
187     			raw_inode->i_mode = 0;
188     		}
189     	}
190     	if (bh) {
191     		mark_buffer_dirty(bh);
192     		brelse (bh);
193     	}
194     }
195     
196     void minix_free_inode(struct inode * inode)
197     {
198     	struct buffer_head * bh;
199     	unsigned long ino;
200     
201     	if (inode->i_ino < 1 || inode->i_ino > inode->i_sb->u.minix_sb.s_ninodes) {
202     		printk("free_inode: inode 0 or nonexistent inode\n");
203     		return;
204     	}
205     	ino = inode->i_ino;
206     	if ((ino >> 13) >= inode->i_sb->u.minix_sb.s_imap_blocks) {
207     		printk("free_inode: nonexistent imap in superblock\n");
208     		return;
209     	}
210     
211     	bh = inode->i_sb->u.minix_sb.s_imap[ino >> 13];
212     	minix_clear_inode(inode);
213     	clear_inode(inode);
214     	if (!minix_test_and_clear_bit(ino & 8191, bh->b_data))
215     		printk("free_inode: bit %lu already cleared.\n",ino);
216     	mark_buffer_dirty(bh);
217     }
218     
219     struct inode * minix_new_inode(const struct inode * dir, int * error)
220     {
221     	struct super_block * sb;
222     	struct inode * inode;
223     	struct buffer_head * bh;
224     	int i,j;
225     
226     	sb = dir->i_sb;
227     	inode = new_inode(sb);
228     	if (!inode) {
229     		*error = -ENOMEM;
230     		return NULL;
231     	}
232     	j = 8192;
233     	bh = NULL;
234     	*error = -ENOSPC;
235     	lock_super(sb);
236     	for (i = 0; i < sb->u.minix_sb.s_imap_blocks; i++) {
237     		bh = inode->i_sb->u.minix_sb.s_imap[i];
238     		if ((j = minix_find_first_zero_bit(bh->b_data, 8192)) < 8192)
239     			break;
240     	}
241     	if (!bh || j >= 8192) {
242     		iput(inode);
243     		unlock_super(sb);
244     		return NULL;
245     	}
246     	if (minix_test_and_set_bit(j,bh->b_data)) {	/* shouldn't happen */
247     		printk("new_inode: bit already set");
248     		iput(inode);
249     		unlock_super(sb);
250     		return NULL;
251     	}
252     	mark_buffer_dirty(bh);
253     	j += i*8192;
254     	if (!j || j > inode->i_sb->u.minix_sb.s_ninodes) {
255     		iput(inode);
256     		unlock_super(sb);
257     		return NULL;
258     	}
259     	inode->i_uid = current->fsuid;
260     	inode->i_gid = (dir->i_mode & S_ISGID) ? dir->i_gid : current->fsgid;
261     	inode->i_ino = j;
262     	inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
263     	inode->i_blocks = inode->i_blksize = 0;
264     	insert_inode_hash(inode);
265     	mark_inode_dirty(inode);
266     
267     	unlock_super(sb);
268     	*error = 0;
269     	return inode;
270     }
271     
272     unsigned long minix_count_free_inodes(struct super_block *sb)
273     {
274     	return count_free(sb->u.minix_sb.s_imap, sb->u.minix_sb.s_imap_blocks,
275     		sb->u.minix_sb.s_ninodes + 1);
276     }
277