~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
Linux/fs/minix/bitmap.c

Version: ~ [ 2.4.0 ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

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

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.