aboutsummaryrefslogtreecommitdiffstats
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
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>
-rw-r--r--fs/bfs/bfs.h4
-rw-r--r--fs/bfs/dir.c146
-rw-r--r--fs/bfs/file.c62
-rw-r--r--fs/bfs/inode.c127
4 files changed, 184 insertions, 155 deletions
diff --git a/fs/bfs/bfs.h b/fs/bfs/bfs.h
index 130f6c66c5ba..ac7a8b1d6c3a 100644
--- a/fs/bfs/bfs.h
+++ b/fs/bfs/bfs.h
@@ -14,8 +14,6 @@ struct bfs_sb_info {
14 unsigned long si_blocks; 14 unsigned long si_blocks;
15 unsigned long si_freeb; 15 unsigned long si_freeb;
16 unsigned long si_freei; 16 unsigned long si_freei;
17 unsigned long si_lf_ioff;
18 unsigned long si_lf_sblk;
19 unsigned long si_lf_eblk; 17 unsigned long si_lf_eblk;
20 unsigned long si_lasti; 18 unsigned long si_lasti;
21 unsigned long * si_imap; 19 unsigned long * si_imap;
@@ -39,7 +37,7 @@ static inline struct bfs_sb_info *BFS_SB(struct super_block *sb)
39 37
40static inline struct bfs_inode_info *BFS_I(struct inode *inode) 38static inline struct bfs_inode_info *BFS_I(struct inode *inode)
41{ 39{
42 return list_entry(inode, struct bfs_inode_info, vfs_inode); 40 return container_of(inode, struct bfs_inode_info, vfs_inode);
43} 41}
44 42
45 43
diff --git a/fs/bfs/dir.c b/fs/bfs/dir.c
index 097f1497f743..1fd056d0fc3d 100644
--- a/fs/bfs/dir.c
+++ b/fs/bfs/dir.c
@@ -21,29 +21,32 @@
21#define dprintf(x...) 21#define dprintf(x...)
22#endif 22#endif
23 23
24static int bfs_add_entry(struct inode * dir, const unsigned char * name, int namelen, int ino); 24static int bfs_add_entry(struct inode *dir, const unsigned char *name,
25static struct buffer_head * bfs_find_entry(struct inode * dir, 25 int namelen, int ino);
26 const unsigned char * name, int namelen, struct bfs_dirent ** res_dir); 26static struct buffer_head *bfs_find_entry(struct inode *dir,
27 const unsigned char *name, int namelen,
28 struct bfs_dirent **res_dir);
27 29
28static int bfs_readdir(struct file * f, void * dirent, filldir_t filldir) 30static int bfs_readdir(struct file *f, void *dirent, filldir_t filldir)
29{ 31{
30 struct inode * dir = f->f_path.dentry->d_inode; 32 struct inode *dir = f->f_path.dentry->d_inode;
31 struct buffer_head * bh; 33 struct buffer_head *bh;
32 struct bfs_dirent * de; 34 struct bfs_dirent *de;
33 unsigned int offset; 35 unsigned int offset;
34 int block; 36 int block;
35 37
36 lock_kernel(); 38 lock_kernel();
37 39
38 if (f->f_pos & (BFS_DIRENT_SIZE-1)) { 40 if (f->f_pos & (BFS_DIRENT_SIZE - 1)) {
39 printf("Bad f_pos=%08lx for %s:%08lx\n", (unsigned long)f->f_pos, 41 printf("Bad f_pos=%08lx for %s:%08lx\n",
40 dir->i_sb->s_id, dir->i_ino); 42 (unsigned long)f->f_pos,
43 dir->i_sb->s_id, dir->i_ino);
41 unlock_kernel(); 44 unlock_kernel();
42 return -EBADF; 45 return -EBADF;
43 } 46 }
44 47
45 while (f->f_pos < dir->i_size) { 48 while (f->f_pos < dir->i_size) {
46 offset = f->f_pos & (BFS_BSIZE-1); 49 offset = f->f_pos & (BFS_BSIZE - 1);
47 block = BFS_I(dir)->i_sblock + (f->f_pos >> BFS_BSIZE_BITS); 50 block = BFS_I(dir)->i_sblock + (f->f_pos >> BFS_BSIZE_BITS);
48 bh = sb_bread(dir->i_sb, block); 51 bh = sb_bread(dir->i_sb, block);
49 if (!bh) { 52 if (!bh) {
@@ -54,7 +57,9 @@ static int bfs_readdir(struct file * f, void * dirent, filldir_t filldir)
54 de = (struct bfs_dirent *)(bh->b_data + offset); 57 de = (struct bfs_dirent *)(bh->b_data + offset);
55 if (de->ino) { 58 if (de->ino) {
56 int size = strnlen(de->name, BFS_NAMELEN); 59 int size = strnlen(de->name, BFS_NAMELEN);
57 if (filldir(dirent, de->name, size, f->f_pos, le16_to_cpu(de->ino), DT_UNKNOWN) < 0) { 60 if (filldir(dirent, de->name, size, f->f_pos,
61 le16_to_cpu(de->ino),
62 DT_UNKNOWN) < 0) {
58 brelse(bh); 63 brelse(bh);
59 unlock_kernel(); 64 unlock_kernel();
60 return 0; 65 return 0;
@@ -62,7 +67,7 @@ static int bfs_readdir(struct file * f, void * dirent, filldir_t filldir)
62 } 67 }
63 offset += BFS_DIRENT_SIZE; 68 offset += BFS_DIRENT_SIZE;
64 f->f_pos += BFS_DIRENT_SIZE; 69 f->f_pos += BFS_DIRENT_SIZE;
65 } while (offset < BFS_BSIZE && f->f_pos < dir->i_size); 70 } while ((offset < BFS_BSIZE) && (f->f_pos < dir->i_size));
66 brelse(bh); 71 brelse(bh);
67 } 72 }
68 73
@@ -78,13 +83,13 @@ const struct file_operations bfs_dir_operations = {
78 83
79extern void dump_imap(const char *, struct super_block *); 84extern void dump_imap(const char *, struct super_block *);
80 85
81static int bfs_create(struct inode * dir, struct dentry * dentry, int mode, 86static int bfs_create(struct inode *dir, struct dentry *dentry, int mode,
82 struct nameidata *nd) 87 struct nameidata *nd)
83{ 88{
84 int err; 89 int err;
85 struct inode * inode; 90 struct inode *inode;
86 struct super_block * s = dir->i_sb; 91 struct super_block *s = dir->i_sb;
87 struct bfs_sb_info * info = BFS_SB(s); 92 struct bfs_sb_info *info = BFS_SB(s);
88 unsigned long ino; 93 unsigned long ino;
89 94
90 inode = new_inode(s); 95 inode = new_inode(s);
@@ -97,7 +102,7 @@ static int bfs_create(struct inode * dir, struct dentry * dentry, int mode,
97 iput(inode); 102 iput(inode);
98 return -ENOSPC; 103 return -ENOSPC;
99 } 104 }
100 set_bit(ino, info->si_imap); 105 set_bit(ino, info->si_imap);
101 info->si_freei--; 106 info->si_freei--;
102 inode->i_uid = current->fsuid; 107 inode->i_uid = current->fsuid;
103 inode->i_gid = (dir->i_mode & S_ISGID) ? dir->i_gid : current->fsgid; 108 inode->i_gid = (dir->i_mode & S_ISGID) ? dir->i_gid : current->fsgid;
@@ -113,9 +118,10 @@ static int bfs_create(struct inode * dir, struct dentry * dentry, int mode,
113 BFS_I(inode)->i_eblock = 0; 118 BFS_I(inode)->i_eblock = 0;
114 insert_inode_hash(inode); 119 insert_inode_hash(inode);
115 mark_inode_dirty(inode); 120 mark_inode_dirty(inode);
116 dump_imap("create",s); 121 dump_imap("create", s);
117 122
118 err = bfs_add_entry(dir, dentry->d_name.name, dentry->d_name.len, inode->i_ino); 123 err = bfs_add_entry(dir, dentry->d_name.name, dentry->d_name.len,
124 inode->i_ino);
119 if (err) { 125 if (err) {
120 inode_dec_link_count(inode); 126 inode_dec_link_count(inode);
121 iput(inode); 127 iput(inode);
@@ -127,11 +133,12 @@ static int bfs_create(struct inode * dir, struct dentry * dentry, int mode,
127 return 0; 133 return 0;
128} 134}
129 135
130static struct dentry * bfs_lookup(struct inode * dir, struct dentry * dentry, struct nameidata *nd) 136static struct dentry *bfs_lookup(struct inode *dir, struct dentry *dentry,
137 struct nameidata *nd)
131{ 138{
132 struct inode * inode = NULL; 139 struct inode *inode = NULL;
133 struct buffer_head * bh; 140 struct buffer_head *bh;
134 struct bfs_dirent * de; 141 struct bfs_dirent *de;
135 142
136 if (dentry->d_name.len > BFS_NAMELEN) 143 if (dentry->d_name.len > BFS_NAMELEN)
137 return ERR_PTR(-ENAMETOOLONG); 144 return ERR_PTR(-ENAMETOOLONG);
@@ -152,13 +159,15 @@ static struct dentry * bfs_lookup(struct inode * dir, struct dentry * dentry, st
152 return NULL; 159 return NULL;
153} 160}
154 161
155static int bfs_link(struct dentry * old, struct inode * dir, struct dentry * new) 162static int bfs_link(struct dentry *old, struct inode *dir,
163 struct dentry *new)
156{ 164{
157 struct inode * inode = old->d_inode; 165 struct inode *inode = old->d_inode;
158 int err; 166 int err;
159 167
160 lock_kernel(); 168 lock_kernel();
161 err = bfs_add_entry(dir, new->d_name.name, new->d_name.len, inode->i_ino); 169 err = bfs_add_entry(dir, new->d_name.name, new->d_name.len,
170 inode->i_ino);
162 if (err) { 171 if (err) {
163 unlock_kernel(); 172 unlock_kernel();
164 return err; 173 return err;
@@ -172,23 +181,23 @@ static int bfs_link(struct dentry * old, struct inode * dir, struct dentry * new
172 return 0; 181 return 0;
173} 182}
174 183
175 184static int bfs_unlink(struct inode *dir, struct dentry *dentry)
176static int bfs_unlink(struct inode * dir, struct dentry * dentry)
177{ 185{
178 int error = -ENOENT; 186 int error = -ENOENT;
179 struct inode * inode; 187 struct inode *inode;
180 struct buffer_head * bh; 188 struct buffer_head *bh;
181 struct bfs_dirent * de; 189 struct bfs_dirent *de;
182 190
183 inode = dentry->d_inode; 191 inode = dentry->d_inode;
184 lock_kernel(); 192 lock_kernel();
185 bh = bfs_find_entry(dir, dentry->d_name.name, dentry->d_name.len, &de); 193 bh = bfs_find_entry(dir, dentry->d_name.name, dentry->d_name.len, &de);
186 if (!bh || le16_to_cpu(de->ino) != inode->i_ino) 194 if (!bh || (le16_to_cpu(de->ino) != inode->i_ino))
187 goto out_brelse; 195 goto out_brelse;
188 196
189 if (!inode->i_nlink) { 197 if (!inode->i_nlink) {
190 printf("unlinking non-existent file %s:%lu (nlink=%d)\n", inode->i_sb->s_id, 198 printf("unlinking non-existent file %s:%lu (nlink=%d)\n",
191 inode->i_ino, inode->i_nlink); 199 inode->i_sb->s_id, inode->i_ino,
200 inode->i_nlink);
192 inode->i_nlink = 1; 201 inode->i_nlink = 1;
193 } 202 }
194 de->ino = 0; 203 de->ino = 0;
@@ -205,12 +214,12 @@ out_brelse:
205 return error; 214 return error;
206} 215}
207 216
208static int bfs_rename(struct inode * old_dir, struct dentry * old_dentry, 217static int bfs_rename(struct inode *old_dir, struct dentry *old_dentry,
209 struct inode * new_dir, struct dentry * new_dentry) 218 struct inode *new_dir, struct dentry *new_dentry)
210{ 219{
211 struct inode * old_inode, * new_inode; 220 struct inode *old_inode, *new_inode;
212 struct buffer_head * old_bh, * new_bh; 221 struct buffer_head *old_bh, *new_bh;
213 struct bfs_dirent * old_de, * new_de; 222 struct bfs_dirent *old_de, *new_de;
214 int error = -ENOENT; 223 int error = -ENOENT;
215 224
216 old_bh = new_bh = NULL; 225 old_bh = new_bh = NULL;
@@ -223,7 +232,7 @@ static int bfs_rename(struct inode * old_dir, struct dentry * old_dentry,
223 old_dentry->d_name.name, 232 old_dentry->d_name.name,
224 old_dentry->d_name.len, &old_de); 233 old_dentry->d_name.len, &old_de);
225 234
226 if (!old_bh || le16_to_cpu(old_de->ino) != old_inode->i_ino) 235 if (!old_bh || (le16_to_cpu(old_de->ino) != old_inode->i_ino))
227 goto end_rename; 236 goto end_rename;
228 237
229 error = -EPERM; 238 error = -EPERM;
@@ -239,7 +248,8 @@ static int bfs_rename(struct inode * old_dir, struct dentry * old_dentry,
239 if (!new_bh) { 248 if (!new_bh) {
240 error = bfs_add_entry(new_dir, 249 error = bfs_add_entry(new_dir,
241 new_dentry->d_name.name, 250 new_dentry->d_name.name,
242 new_dentry->d_name.len, old_inode->i_ino); 251 new_dentry->d_name.len,
252 old_inode->i_ino);
243 if (error) 253 if (error)
244 goto end_rename; 254 goto end_rename;
245 } 255 }
@@ -268,11 +278,12 @@ const struct inode_operations bfs_dir_inops = {
268 .rename = bfs_rename, 278 .rename = bfs_rename,
269}; 279};
270 280
271static int bfs_add_entry(struct inode * dir, const unsigned char * name, int namelen, int ino) 281static int bfs_add_entry(struct inode *dir, const unsigned char *name,
282 int namelen, int ino)
272{ 283{
273 struct buffer_head * bh; 284 struct buffer_head *bh;
274 struct bfs_dirent * de; 285 struct bfs_dirent *de;
275 int block, sblock, eblock, off, eoff; 286 int block, sblock, eblock, off, pos;
276 int i; 287 int i;
277 288
278 dprintf("name=%s, namelen=%d\n", name, namelen); 289 dprintf("name=%s, namelen=%d\n", name, namelen);
@@ -284,27 +295,24 @@ static int bfs_add_entry(struct inode * dir, const unsigned char * name, int nam
284 295
285 sblock = BFS_I(dir)->i_sblock; 296 sblock = BFS_I(dir)->i_sblock;
286 eblock = BFS_I(dir)->i_eblock; 297 eblock = BFS_I(dir)->i_eblock;
287 eoff = dir->i_size % BFS_BSIZE; 298 for (block = sblock; block <= eblock; block++) {
288 for (block=sblock; block<=eblock; block++) {
289 bh = sb_bread(dir->i_sb, block); 299 bh = sb_bread(dir->i_sb, block);
290 if(!bh) 300 if (!bh)
291 return -ENOSPC; 301 return -ENOSPC;
292 for (off=0; off<BFS_BSIZE; off+=BFS_DIRENT_SIZE) { 302 for (off = 0; off < BFS_BSIZE; off += BFS_DIRENT_SIZE) {
293 de = (struct bfs_dirent *)(bh->b_data + off); 303 de = (struct bfs_dirent *)(bh->b_data + off);
294 if (block==eblock && off>=eoff) {
295 /* Do not read/interpret the garbage in the end of eblock. */
296 de->ino = 0;
297 }
298 if (!de->ino) { 304 if (!de->ino) {
299 if ((block-sblock)*BFS_BSIZE + off >= dir->i_size) { 305 pos = (block - sblock) * BFS_BSIZE + off;
306 if (pos >= dir->i_size) {
300 dir->i_size += BFS_DIRENT_SIZE; 307 dir->i_size += BFS_DIRENT_SIZE;
301 dir->i_ctime = CURRENT_TIME_SEC; 308 dir->i_ctime = CURRENT_TIME_SEC;
302 } 309 }
303 dir->i_mtime = CURRENT_TIME_SEC; 310 dir->i_mtime = CURRENT_TIME_SEC;
304 mark_inode_dirty(dir); 311 mark_inode_dirty(dir);
305 de->ino = cpu_to_le16((u16)ino); 312 de->ino = cpu_to_le16((u16)ino);
306 for (i=0; i<BFS_NAMELEN; i++) 313 for (i = 0; i < BFS_NAMELEN; i++)
307 de->name[i] = (i < namelen) ? name[i] : 0; 314 de->name[i] =
315 (i < namelen) ? name[i] : 0;
308 mark_buffer_dirty(bh); 316 mark_buffer_dirty(bh);
309 brelse(bh); 317 brelse(bh);
310 return 0; 318 return 0;
@@ -315,25 +323,26 @@ static int bfs_add_entry(struct inode * dir, const unsigned char * name, int nam
315 return -ENOSPC; 323 return -ENOSPC;
316} 324}
317 325
318static inline int bfs_namecmp(int len, const unsigned char * name, const char * buffer) 326static inline int bfs_namecmp(int len, const unsigned char *name,
327 const char *buffer)
319{ 328{
320 if (len < BFS_NAMELEN && buffer[len]) 329 if ((len < BFS_NAMELEN) && buffer[len])
321 return 0; 330 return 0;
322 return !memcmp(name, buffer, len); 331 return !memcmp(name, buffer, len);
323} 332}
324 333
325static struct buffer_head * bfs_find_entry(struct inode * dir, 334static struct buffer_head *bfs_find_entry(struct inode *dir,
326 const unsigned char * name, int namelen, struct bfs_dirent ** res_dir) 335 const unsigned char *name, int namelen,
336 struct bfs_dirent **res_dir)
327{ 337{
328 unsigned long block, offset; 338 unsigned long block = 0, offset = 0;
329 struct buffer_head * bh; 339 struct buffer_head *bh = NULL;
330 struct bfs_dirent * de; 340 struct bfs_dirent *de;
331 341
332 *res_dir = NULL; 342 *res_dir = NULL;
333 if (namelen > BFS_NAMELEN) 343 if (namelen > BFS_NAMELEN)
334 return NULL; 344 return NULL;
335 bh = NULL; 345
336 block = offset = 0;
337 while (block * BFS_BSIZE + offset < dir->i_size) { 346 while (block * BFS_BSIZE + offset < dir->i_size) {
338 if (!bh) { 347 if (!bh) {
339 bh = sb_bread(dir->i_sb, BFS_I(dir)->i_sblock + block); 348 bh = sb_bread(dir->i_sb, BFS_I(dir)->i_sblock + block);
@@ -344,7 +353,8 @@ static struct buffer_head * bfs_find_entry(struct inode * dir,
344 } 353 }
345 de = (struct bfs_dirent *)(bh->b_data + offset); 354 de = (struct bfs_dirent *)(bh->b_data + offset);
346 offset += BFS_DIRENT_SIZE; 355 offset += BFS_DIRENT_SIZE;
347 if (le16_to_cpu(de->ino) && bfs_namecmp(namelen, name, de->name)) { 356 if (le16_to_cpu(de->ino) &&
357 bfs_namecmp(namelen, name, de->name)) {
348 *res_dir = de; 358 *res_dir = de;
349 return bh; 359 return bh;
350 } 360 }
diff --git a/fs/bfs/file.c b/fs/bfs/file.c
index 911b4ccf470f..b11e63e8fbcd 100644
--- a/fs/bfs/file.c
+++ b/fs/bfs/file.c
@@ -2,6 +2,11 @@
2 * fs/bfs/file.c 2 * fs/bfs/file.c
3 * BFS file operations. 3 * BFS file operations.
4 * Copyright (C) 1999,2000 Tigran Aivazian <tigran@veritas.com> 4 * Copyright (C) 1999,2000 Tigran Aivazian <tigran@veritas.com>
5 *
6 * Make the file block allocation algorithm understand the size
7 * of the underlying block device.
8 * Copyright (C) 2007 Dmitri Vorobiev <dmitri.vorobiev@gmail.com>
9 *
5 */ 10 */
6 11
7#include <linux/fs.h> 12#include <linux/fs.h>
@@ -27,7 +32,8 @@ const struct file_operations bfs_file_operations = {
27 .splice_read = generic_file_splice_read, 32 .splice_read = generic_file_splice_read,
28}; 33};
29 34
30static int bfs_move_block(unsigned long from, unsigned long to, struct super_block *sb) 35static int bfs_move_block(unsigned long from, unsigned long to,
36 struct super_block *sb)
31{ 37{
32 struct buffer_head *bh, *new; 38 struct buffer_head *bh, *new;
33 39
@@ -43,21 +49,22 @@ static int bfs_move_block(unsigned long from, unsigned long to, struct super_blo
43} 49}
44 50
45static int bfs_move_blocks(struct super_block *sb, unsigned long start, 51static int bfs_move_blocks(struct super_block *sb, unsigned long start,
46 unsigned long end, unsigned long where) 52 unsigned long end, unsigned long where)
47{ 53{
48 unsigned long i; 54 unsigned long i;
49 55
50 dprintf("%08lx-%08lx->%08lx\n", start, end, where); 56 dprintf("%08lx-%08lx->%08lx\n", start, end, where);
51 for (i = start; i <= end; i++) 57 for (i = start; i <= end; i++)
52 if(bfs_move_block(i, where + i, sb)) { 58 if(bfs_move_block(i, where + i, sb)) {
53 dprintf("failed to move block %08lx -> %08lx\n", i, where + i); 59 dprintf("failed to move block %08lx -> %08lx\n", i,
60 where + i);
54 return -EIO; 61 return -EIO;
55 } 62 }
56 return 0; 63 return 0;
57} 64}
58 65
59static int bfs_get_block(struct inode * inode, sector_t block, 66static int bfs_get_block(struct inode *inode, sector_t block,
60 struct buffer_head * bh_result, int create) 67 struct buffer_head *bh_result, int create)
61{ 68{
62 unsigned long phys; 69 unsigned long phys;
63 int err; 70 int err;
@@ -66,9 +73,6 @@ static int bfs_get_block(struct inode * inode, sector_t block,
66 struct bfs_inode_info *bi = BFS_I(inode); 73 struct bfs_inode_info *bi = BFS_I(inode);
67 struct buffer_head *sbh = info->si_sbh; 74 struct buffer_head *sbh = info->si_sbh;
68 75
69 if (block > info->si_blocks)
70 return -EIO;
71
72 phys = bi->i_sblock + block; 76 phys = bi->i_sblock + block;
73 if (!create) { 77 if (!create) {
74 if (phys <= bi->i_eblock) { 78 if (phys <= bi->i_eblock) {
@@ -79,21 +83,29 @@ static int bfs_get_block(struct inode * inode, sector_t block,
79 return 0; 83 return 0;
80 } 84 }
81 85
82 /* if the file is not empty and the requested block is within the range 86 /*
83 of blocks allocated for this file, we can grant it */ 87 * If the file is not empty and the requested block is within the
84 if (inode->i_size && phys <= bi->i_eblock) { 88 * range of blocks allocated for this file, we can grant it.
89 */
90 if (bi->i_sblock && (phys <= bi->i_eblock)) {
85 dprintf("c=%d, b=%08lx, phys=%08lx (interim block granted)\n", 91 dprintf("c=%d, b=%08lx, phys=%08lx (interim block granted)\n",
86 create, (unsigned long)block, phys); 92 create, (unsigned long)block, phys);
87 map_bh(bh_result, sb, phys); 93 map_bh(bh_result, sb, phys);
88 return 0; 94 return 0;
89 } 95 }
90 96
91 /* the rest has to be protected against itself */ 97 /* The file will be extended, so let's see if there is enough space. */
98 if (phys >= info->si_blocks)
99 return -ENOSPC;
100
101 /* The rest has to be protected against itself. */
92 lock_kernel(); 102 lock_kernel();
93 103
94 /* if the last data block for this file is the last allocated 104 /*
95 block, we can extend the file trivially, without moving it 105 * If the last data block for this file is the last allocated
96 anywhere */ 106 * block, we can extend the file trivially, without moving it
107 * anywhere.
108 */
97 if (bi->i_eblock == info->si_lf_eblk) { 109 if (bi->i_eblock == info->si_lf_eblk) {
98 dprintf("c=%d, b=%08lx, phys=%08lx (simple extension)\n", 110 dprintf("c=%d, b=%08lx, phys=%08lx (simple extension)\n",
99 create, (unsigned long)block, phys); 111 create, (unsigned long)block, phys);
@@ -106,13 +118,19 @@ static int bfs_get_block(struct inode * inode, sector_t block,
106 goto out; 118 goto out;
107 } 119 }
108 120
109 /* Ok, we have to move this entire file to the next free block */ 121 /* Ok, we have to move this entire file to the next free block. */
110 phys = info->si_lf_eblk + 1; 122 phys = info->si_lf_eblk + 1;
111 if (bi->i_sblock) { /* if data starts on block 0 then there is no data */ 123 if (phys + block >= info->si_blocks) {
124 err = -ENOSPC;
125 goto out;
126 }
127
128 if (bi->i_sblock) {
112 err = bfs_move_blocks(inode->i_sb, bi->i_sblock, 129 err = bfs_move_blocks(inode->i_sb, bi->i_sblock,
113 bi->i_eblock, phys); 130 bi->i_eblock, phys);
114 if (err) { 131 if (err) {
115 dprintf("failed to move ino=%08lx -> fs corruption\n", inode->i_ino); 132 dprintf("failed to move ino=%08lx -> fs corruption\n",
133 inode->i_ino);
116 goto out; 134 goto out;
117 } 135 }
118 } else 136 } else
@@ -124,8 +142,10 @@ static int bfs_get_block(struct inode * inode, sector_t block,
124 phys += block; 142 phys += block;
125 info->si_lf_eblk = bi->i_eblock = phys; 143 info->si_lf_eblk = bi->i_eblock = phys;
126 144
127 /* this assumes nothing can write the inode back while we are here 145 /*
128 * and thus update inode->i_blocks! (XXX)*/ 146 * This assumes nothing can write the inode back while we are here
147 * and thus update inode->i_blocks! (XXX)
148 */
129 info->si_freeb -= bi->i_eblock - bi->i_sblock + 1 - inode->i_blocks; 149 info->si_freeb -= bi->i_eblock - bi->i_sblock + 1 - inode->i_blocks;
130 mark_inode_dirty(inode); 150 mark_inode_dirty(inode);
131 mark_buffer_dirty(sbh); 151 mark_buffer_dirty(sbh);
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)) {