aboutsummaryrefslogtreecommitdiffstats
path: root/fs/bfs/inode.c
diff options
context:
space:
mode:
authorDmitri Vorobiev <dmitri.vorobiev@gmail.com>2007-11-14 19:59:47 -0500
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-11-14 21:45:40 -0500
commitf433dc56344cb72cc3de5ba0819021cec3aef807 (patch)
tree19fa9052a2787c84417dc306eda1eae8b02f14f2 /fs/bfs/inode.c
parentcfb5285660aad4931b2ebbfa902ea48a37dfffa1 (diff)
Fixes to the BFS filesystem driver
I found a few bugs in the BFS driver. Detailed description of the bugs as well as the steps to reproduce the errors are given in the kernel bugzilla. Please follow these links for more information: http://bugzilla.kernel.org/show_bug.cgi?id=9363 http://bugzilla.kernel.org/show_bug.cgi?id=9364 http://bugzilla.kernel.org/show_bug.cgi?id=9365 http://bugzilla.kernel.org/show_bug.cgi?id=9366 This patch fixes the bugs described above. Besides, the patch introduces coding style changes to make the BFS driver conform to the requirements specified for Linux kernel code. Finally, I made a few cosmetic changes such as removal of trivial debug output. Also, the patch removes the fields `si_lf_ioff' and `si_lf_sblk' of the in-core superblock structure. These fields are initialized but never actually used. If you are wondering why I need BFS, here is the answer: I am using this driver in the context of Linux kernel classes I am teaching in the Moscow State University and in the International Institute of Information Technology in Pune, India. Signed-off-by: Dmitri Vorobiev <dmitri.vorobiev@gmail.com> Cc: Tigran Aivazian <tigran@veritas.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs/bfs/inode.c')
-rw-r--r--fs/bfs/inode.c127
1 files changed, 64 insertions, 63 deletions
diff --git a/fs/bfs/inode.c b/fs/bfs/inode.c
index 7bd9c2bbe6ee..294c41baef6e 100644
--- a/fs/bfs/inode.c
+++ b/fs/bfs/inode.c
@@ -30,25 +30,26 @@ MODULE_LICENSE("GPL");
30#define dprintf(x...) 30#define dprintf(x...)
31#endif 31#endif
32 32
33void dump_imap(const char *prefix, struct super_block * s); 33void dump_imap(const char *prefix, struct super_block *s);
34 34
35static void bfs_read_inode(struct inode * inode) 35static void bfs_read_inode(struct inode *inode)
36{ 36{
37 unsigned long ino = inode->i_ino; 37 unsigned long ino = inode->i_ino;
38 struct bfs_inode * di; 38 struct bfs_inode *di;
39 struct buffer_head * bh; 39 struct buffer_head *bh;
40 int block, off; 40 int block, off;
41 41
42 if (ino < BFS_ROOT_INO || ino > BFS_SB(inode->i_sb)->si_lasti) { 42 if ((ino < BFS_ROOT_INO) || (ino > BFS_SB(inode->i_sb)->si_lasti)) {
43 printf("Bad inode number %s:%08lx\n", inode->i_sb->s_id, ino); 43 printf("Bad inode number %s:%08lx\n", inode->i_sb->s_id, ino);
44 make_bad_inode(inode); 44 make_bad_inode(inode);
45 return; 45 return;
46 } 46 }
47 47
48 block = (ino - BFS_ROOT_INO)/BFS_INODES_PER_BLOCK + 1; 48 block = (ino - BFS_ROOT_INO) / BFS_INODES_PER_BLOCK + 1;
49 bh = sb_bread(inode->i_sb, block); 49 bh = sb_bread(inode->i_sb, block);
50 if (!bh) { 50 if (!bh) {
51 printf("Unable to read inode %s:%08lx\n", inode->i_sb->s_id, ino); 51 printf("Unable to read inode %s:%08lx\n", inode->i_sb->s_id,
52 ino);
52 make_bad_inode(inode); 53 make_bad_inode(inode);
53 return; 54 return;
54 } 55 }
@@ -56,7 +57,7 @@ static void bfs_read_inode(struct inode * inode)
56 off = (ino - BFS_ROOT_INO) % BFS_INODES_PER_BLOCK; 57 off = (ino - BFS_ROOT_INO) % BFS_INODES_PER_BLOCK;
57 di = (struct bfs_inode *)bh->b_data + off; 58 di = (struct bfs_inode *)bh->b_data + off;
58 59
59 inode->i_mode = 0x0000FFFF & le32_to_cpu(di->i_mode); 60 inode->i_mode = 0x0000FFFF & le32_to_cpu(di->i_mode);
60 if (le32_to_cpu(di->i_vtype) == BFS_VDIR) { 61 if (le32_to_cpu(di->i_vtype) == BFS_VDIR) {
61 inode->i_mode |= S_IFDIR; 62 inode->i_mode |= S_IFDIR;
62 inode->i_op = &bfs_dir_inops; 63 inode->i_op = &bfs_dir_inops;
@@ -70,48 +71,48 @@ static void bfs_read_inode(struct inode * inode)
70 71
71 BFS_I(inode)->i_sblock = le32_to_cpu(di->i_sblock); 72 BFS_I(inode)->i_sblock = le32_to_cpu(di->i_sblock);
72 BFS_I(inode)->i_eblock = le32_to_cpu(di->i_eblock); 73 BFS_I(inode)->i_eblock = le32_to_cpu(di->i_eblock);
74 BFS_I(inode)->i_dsk_ino = le16_to_cpu(di->i_ino);
73 inode->i_uid = le32_to_cpu(di->i_uid); 75 inode->i_uid = le32_to_cpu(di->i_uid);
74 inode->i_gid = le32_to_cpu(di->i_gid); 76 inode->i_gid = le32_to_cpu(di->i_gid);
75 inode->i_nlink = le32_to_cpu(di->i_nlink); 77 inode->i_nlink = le32_to_cpu(di->i_nlink);
76 inode->i_size = BFS_FILESIZE(di); 78 inode->i_size = BFS_FILESIZE(di);
77 inode->i_blocks = BFS_FILEBLOCKS(di); 79 inode->i_blocks = BFS_FILEBLOCKS(di);
78 if (inode->i_size || inode->i_blocks) dprintf("Registered inode with %lld size, %ld blocks\n", inode->i_size, inode->i_blocks);
79 inode->i_atime.tv_sec = le32_to_cpu(di->i_atime); 80 inode->i_atime.tv_sec = le32_to_cpu(di->i_atime);
80 inode->i_mtime.tv_sec = le32_to_cpu(di->i_mtime); 81 inode->i_mtime.tv_sec = le32_to_cpu(di->i_mtime);
81 inode->i_ctime.tv_sec = le32_to_cpu(di->i_ctime); 82 inode->i_ctime.tv_sec = le32_to_cpu(di->i_ctime);
82 inode->i_atime.tv_nsec = 0; 83 inode->i_atime.tv_nsec = 0;
83 inode->i_mtime.tv_nsec = 0; 84 inode->i_mtime.tv_nsec = 0;
84 inode->i_ctime.tv_nsec = 0; 85 inode->i_ctime.tv_nsec = 0;
85 BFS_I(inode)->i_dsk_ino = le16_to_cpu(di->i_ino); /* can be 0 so we store a copy */
86 86
87 brelse(bh); 87 brelse(bh);
88} 88}
89 89
90static int bfs_write_inode(struct inode * inode, int unused) 90static int bfs_write_inode(struct inode *inode, int unused)
91{ 91{
92 unsigned int ino = (u16)inode->i_ino; 92 unsigned int ino = (u16)inode->i_ino;
93 unsigned long i_sblock; 93 unsigned long i_sblock;
94 struct bfs_inode * di; 94 struct bfs_inode *di;
95 struct buffer_head * bh; 95 struct buffer_head *bh;
96 int block, off; 96 int block, off;
97 97
98 dprintf("ino=%08x\n", ino); 98 dprintf("ino=%08x\n", ino);
99 99
100 if (ino < BFS_ROOT_INO || ino > BFS_SB(inode->i_sb)->si_lasti) { 100 if ((ino < BFS_ROOT_INO) || (ino > BFS_SB(inode->i_sb)->si_lasti)) {
101 printf("Bad inode number %s:%08x\n", inode->i_sb->s_id, ino); 101 printf("Bad inode number %s:%08x\n", inode->i_sb->s_id, ino);
102 return -EIO; 102 return -EIO;
103 } 103 }
104 104
105 lock_kernel(); 105 lock_kernel();
106 block = (ino - BFS_ROOT_INO)/BFS_INODES_PER_BLOCK + 1; 106 block = (ino - BFS_ROOT_INO) / BFS_INODES_PER_BLOCK + 1;
107 bh = sb_bread(inode->i_sb, block); 107 bh = sb_bread(inode->i_sb, block);
108 if (!bh) { 108 if (!bh) {
109 printf("Unable to read inode %s:%08x\n", inode->i_sb->s_id, ino); 109 printf("Unable to read inode %s:%08x\n",
110 inode->i_sb->s_id, ino);
110 unlock_kernel(); 111 unlock_kernel();
111 return -EIO; 112 return -EIO;
112 } 113 }
113 114
114 off = (ino - BFS_ROOT_INO)%BFS_INODES_PER_BLOCK; 115 off = (ino - BFS_ROOT_INO) % BFS_INODES_PER_BLOCK;
115 di = (struct bfs_inode *)bh->b_data + off; 116 di = (struct bfs_inode *)bh->b_data + off;
116 117
117 if (ino == BFS_ROOT_INO) 118 if (ino == BFS_ROOT_INO)
@@ -133,27 +134,26 @@ static int bfs_write_inode(struct inode * inode, int unused)
133 di->i_eoffset = cpu_to_le32(i_sblock * BFS_BSIZE + inode->i_size - 1); 134 di->i_eoffset = cpu_to_le32(i_sblock * BFS_BSIZE + inode->i_size - 1);
134 135
135 mark_buffer_dirty(bh); 136 mark_buffer_dirty(bh);
136 dprintf("Written ino=%d into %d:%d\n",le16_to_cpu(di->i_ino),block,off);
137 brelse(bh); 137 brelse(bh);
138 unlock_kernel(); 138 unlock_kernel();
139 return 0; 139 return 0;
140} 140}
141 141
142static void bfs_delete_inode(struct inode * inode) 142static void bfs_delete_inode(struct inode *inode)
143{ 143{
144 unsigned long ino = inode->i_ino; 144 unsigned long ino = inode->i_ino;
145 struct bfs_inode * di; 145 struct bfs_inode *di;
146 struct buffer_head * bh; 146 struct buffer_head *bh;
147 int block, off; 147 int block, off;
148 struct super_block * s = inode->i_sb; 148 struct super_block *s = inode->i_sb;
149 struct bfs_sb_info * info = BFS_SB(s); 149 struct bfs_sb_info *info = BFS_SB(s);
150 struct bfs_inode_info * bi = BFS_I(inode); 150 struct bfs_inode_info *bi = BFS_I(inode);
151 151
152 dprintf("ino=%08lx\n", ino); 152 dprintf("ino=%08lx\n", ino);
153 153
154 truncate_inode_pages(&inode->i_data, 0); 154 truncate_inode_pages(&inode->i_data, 0);
155 155
156 if (ino < BFS_ROOT_INO || ino > info->si_lasti) { 156 if ((ino < BFS_ROOT_INO) || (ino > info->si_lasti)) {
157 printf("invalid ino=%08lx\n", ino); 157 printf("invalid ino=%08lx\n", ino);
158 return; 158 return;
159 } 159 }
@@ -162,31 +162,35 @@ static void bfs_delete_inode(struct inode * inode)
162 inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME_SEC; 162 inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME_SEC;
163 lock_kernel(); 163 lock_kernel();
164 mark_inode_dirty(inode); 164 mark_inode_dirty(inode);
165 block = (ino - BFS_ROOT_INO)/BFS_INODES_PER_BLOCK + 1; 165
166 block = (ino - BFS_ROOT_INO) / BFS_INODES_PER_BLOCK + 1;
166 bh = sb_bread(s, block); 167 bh = sb_bread(s, block);
167 if (!bh) { 168 if (!bh) {
168 printf("Unable to read inode %s:%08lx\n", inode->i_sb->s_id, ino); 169 printf("Unable to read inode %s:%08lx\n",
170 inode->i_sb->s_id, ino);
169 unlock_kernel(); 171 unlock_kernel();
170 return; 172 return;
171 } 173 }
172 off = (ino - BFS_ROOT_INO)%BFS_INODES_PER_BLOCK; 174 off = (ino - BFS_ROOT_INO) % BFS_INODES_PER_BLOCK;
173 di = (struct bfs_inode *) bh->b_data + off; 175 di = (struct bfs_inode *)bh->b_data + off;
176 memset((void *)di, 0, sizeof(struct bfs_inode));
177 mark_buffer_dirty(bh);
178 brelse(bh);
179
174 if (bi->i_dsk_ino) { 180 if (bi->i_dsk_ino) {
175 info->si_freeb += 1 + bi->i_eblock - bi->i_sblock; 181 info->si_freeb += BFS_FILEBLOCKS(bi);
176 info->si_freei++; 182 info->si_freei++;
177 clear_bit(ino, info->si_imap); 183 clear_bit(ino, info->si_imap);
178 dump_imap("delete_inode", s); 184 dump_imap("delete_inode", s);
179 } 185 }
180 di->i_ino = 0;
181 di->i_sblock = 0;
182 mark_buffer_dirty(bh);
183 brelse(bh);
184 186
185 /* if this was the last file, make the previous 187 /*
186 block "last files last block" even if there is no real file there, 188 * If this was the last file, make the previous block
187 saves us 1 gap */ 189 * "last block of the last file" even if there is no
188 if (info->si_lf_eblk == BFS_I(inode)->i_eblock) { 190 * real file there, saves us 1 gap.
189 info->si_lf_eblk = BFS_I(inode)->i_sblock - 1; 191 */
192 if (info->si_lf_eblk == bi->i_eblock) {
193 info->si_lf_eblk = bi->i_sblock - 1;
190 mark_buffer_dirty(info->si_sbh); 194 mark_buffer_dirty(info->si_sbh);
191 } 195 }
192 unlock_kernel(); 196 unlock_kernel();
@@ -228,7 +232,7 @@ static void bfs_write_super(struct super_block *s)
228 unlock_kernel(); 232 unlock_kernel();
229} 233}
230 234
231static struct kmem_cache * bfs_inode_cachep; 235static struct kmem_cache *bfs_inode_cachep;
232 236
233static struct inode *bfs_alloc_inode(struct super_block *sb) 237static struct inode *bfs_alloc_inode(struct super_block *sb)
234{ 238{
@@ -279,7 +283,7 @@ static const struct super_operations bfs_sops = {
279 .statfs = bfs_statfs, 283 .statfs = bfs_statfs,
280}; 284};
281 285
282void dump_imap(const char *prefix, struct super_block * s) 286void dump_imap(const char *prefix, struct super_block *s)
283{ 287{
284#ifdef DEBUG 288#ifdef DEBUG
285 int i; 289 int i;
@@ -287,25 +291,26 @@ void dump_imap(const char *prefix, struct super_block * s)
287 291
288 if (!tmpbuf) 292 if (!tmpbuf)
289 return; 293 return;
290 for (i=BFS_SB(s)->si_lasti; i>=0; i--) { 294 for (i = BFS_SB(s)->si_lasti; i >= 0; i--) {
291 if (i > PAGE_SIZE-100) break; 295 if (i > PAGE_SIZE - 100) break;
292 if (test_bit(i, BFS_SB(s)->si_imap)) 296 if (test_bit(i, BFS_SB(s)->si_imap))
293 strcat(tmpbuf, "1"); 297 strcat(tmpbuf, "1");
294 else 298 else
295 strcat(tmpbuf, "0"); 299 strcat(tmpbuf, "0");
296 } 300 }
297 printk(KERN_ERR "BFS-fs: %s: lasti=%08lx <%s>\n", prefix, BFS_SB(s)->si_lasti, tmpbuf); 301 printf("BFS-fs: %s: lasti=%08lx <%s>\n",
302 prefix, BFS_SB(s)->si_lasti, tmpbuf);
298 free_page((unsigned long)tmpbuf); 303 free_page((unsigned long)tmpbuf);
299#endif 304#endif
300} 305}
301 306
302static int bfs_fill_super(struct super_block *s, void *data, int silent) 307static int bfs_fill_super(struct super_block *s, void *data, int silent)
303{ 308{
304 struct buffer_head * bh; 309 struct buffer_head *bh;
305 struct bfs_super_block * bfs_sb; 310 struct bfs_super_block *bfs_sb;
306 struct inode * inode; 311 struct inode *inode;
307 unsigned i, imap_len; 312 unsigned i, imap_len;
308 struct bfs_sb_info * info; 313 struct bfs_sb_info *info;
309 314
310 info = kzalloc(sizeof(*info), GFP_KERNEL); 315 info = kzalloc(sizeof(*info), GFP_KERNEL);
311 if (!info) 316 if (!info)
@@ -329,14 +334,14 @@ static int bfs_fill_super(struct super_block *s, void *data, int silent)
329 334
330 s->s_magic = BFS_MAGIC; 335 s->s_magic = BFS_MAGIC;
331 info->si_sbh = bh; 336 info->si_sbh = bh;
332 info->si_lasti = (le32_to_cpu(bfs_sb->s_start) - BFS_BSIZE)/sizeof(struct bfs_inode) 337 info->si_lasti = (le32_to_cpu(bfs_sb->s_start) - BFS_BSIZE) /
333 + BFS_ROOT_INO - 1; 338 sizeof(struct bfs_inode)
334 339 + BFS_ROOT_INO - 1;
335 imap_len = info->si_lasti/8 + 1; 340 imap_len = (info->si_lasti / 8) + 1;
336 info->si_imap = kzalloc(imap_len, GFP_KERNEL); 341 info->si_imap = kzalloc(imap_len, GFP_KERNEL);
337 if (!info->si_imap) 342 if (!info->si_imap)
338 goto out; 343 goto out;
339 for (i=0; i<BFS_ROOT_INO; i++) 344 for (i = 0; i < BFS_ROOT_INO; i++)
340 set_bit(i, info->si_imap); 345 set_bit(i, info->si_imap);
341 346
342 s->s_op = &bfs_sops; 347 s->s_op = &bfs_sops;
@@ -352,16 +357,15 @@ static int bfs_fill_super(struct super_block *s, void *data, int silent)
352 goto out; 357 goto out;
353 } 358 }
354 359
355 info->si_blocks = (le32_to_cpu(bfs_sb->s_end) + 1)>>BFS_BSIZE_BITS; /* for statfs(2) */ 360 info->si_blocks = (le32_to_cpu(bfs_sb->s_end) + 1) >> BFS_BSIZE_BITS;
356 info->si_freeb = (le32_to_cpu(bfs_sb->s_end) + 1 - le32_to_cpu(bfs_sb->s_start))>>BFS_BSIZE_BITS; 361 info->si_freeb = (le32_to_cpu(bfs_sb->s_end) + 1
362 - le32_to_cpu(bfs_sb->s_start)) >> BFS_BSIZE_BITS;
357 info->si_freei = 0; 363 info->si_freei = 0;
358 info->si_lf_eblk = 0; 364 info->si_lf_eblk = 0;
359 info->si_lf_sblk = 0;
360 info->si_lf_ioff = 0;
361 bh = NULL; 365 bh = NULL;
362 for (i=BFS_ROOT_INO; i<=info->si_lasti; i++) { 366 for (i = BFS_ROOT_INO; i <= info->si_lasti; i++) {
363 struct bfs_inode *di; 367 struct bfs_inode *di;
364 int block = (i - BFS_ROOT_INO)/BFS_INODES_PER_BLOCK + 1; 368 int block = (i - BFS_ROOT_INO) / BFS_INODES_PER_BLOCK + 1;
365 int off = (i - BFS_ROOT_INO) % BFS_INODES_PER_BLOCK; 369 int off = (i - BFS_ROOT_INO) % BFS_INODES_PER_BLOCK;
366 unsigned long sblock, eblock; 370 unsigned long sblock, eblock;
367 371
@@ -384,11 +388,8 @@ static int bfs_fill_super(struct super_block *s, void *data, int silent)
384 388
385 sblock = le32_to_cpu(di->i_sblock); 389 sblock = le32_to_cpu(di->i_sblock);
386 eblock = le32_to_cpu(di->i_eblock); 390 eblock = le32_to_cpu(di->i_eblock);
387 if (eblock > info->si_lf_eblk) { 391 if (eblock > info->si_lf_eblk)
388 info->si_lf_eblk = eblock; 392 info->si_lf_eblk = eblock;
389 info->si_lf_sblk = sblock;
390 info->si_lf_ioff = BFS_INO2OFF(i);
391 }
392 } 393 }
393 brelse(bh); 394 brelse(bh);
394 if (!(s->s_flags & MS_RDONLY)) { 395 if (!(s->s_flags & MS_RDONLY)) {