Skip to content

Commit d187715

Browse files
tigran123torvalds
authored andcommitted
bfs: extra sanity checking and static inode bitmap
Strengthen validation of BFS superblock against corruption. Make in-core inode bitmap static part of superblock info structure. Print a warning when mounting a BFS filesystem created with "-N 512" option as only 510 files can be created in the root directory. Make the kernel messages more uniform. Update the 'prefix' passed to bfs_dump_imap() to match the current naming of operations. White space and comments cleanup. Link: http://lkml.kernel.org/r/CAK+_RLkFZMduoQF36wZFd3zLi-6ZutWKsydjeHFNdtRvZZEb4w@mail.gmail.com Signed-off-by: Tigran Aivazian <[email protected]> Reported-by: Tetsuo Handa <[email protected]> Signed-off-by: Andrew Morton <[email protected]> Signed-off-by: Linus Torvalds <[email protected]>
1 parent 655c16a commit d187715

File tree

5 files changed

+41
-43
lines changed

5 files changed

+41
-43
lines changed

fs/bfs/bfs.h

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,20 @@
11
/* SPDX-License-Identifier: GPL-2.0 */
22
/*
33
* fs/bfs/bfs.h
4-
* Copyright (C) 1999 Tigran Aivazian <tigran@veritas.com>
4+
* Copyright (C) 1999-2018 Tigran Aivazian <aivazian.tigran@gmail.com>
55
*/
66
#ifndef _FS_BFS_BFS_H
77
#define _FS_BFS_BFS_H
88

99
#include <linux/bfs_fs.h>
1010

11+
/* In theory BFS supports up to 512 inodes, numbered from 2 (for /) up to 513 inclusive.
12+
In actual fact, attempting to create the 512th inode (i.e. inode No. 513 or file No. 511)
13+
will fail with ENOSPC in bfs_add_entry(): the root directory cannot contain so many entries, counting '..'.
14+
So, mkfs.bfs(8) should really limit its -N option to 511 and not 512. For now, we just print a warning
15+
if a filesystem is mounted with such "impossible to fill up" number of inodes */
16+
#define BFS_MAX_LASTI 513
17+
1118
/*
1219
* BFS file system in-core superblock info
1320
*/
@@ -17,7 +24,7 @@ struct bfs_sb_info {
1724
unsigned long si_freei;
1825
unsigned long si_lf_eblk;
1926
unsigned long si_lasti;
20-
unsigned long *si_imap;
27+
DECLARE_BITMAP(si_imap, BFS_MAX_LASTI+1);
2128
struct mutex bfs_lock;
2229
};
2330

fs/bfs/dir.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22
/*
33
* fs/bfs/dir.c
44
* BFS directory operations.
5-
* Copyright (C) 1999,2000 Tigran Aivazian <tigran@veritas.com>
6-
* Made endianness-clean by Andrew Stribblehill <[email protected]> 2005
5+
* Copyright (C) 1999-2018 Tigran Aivazian <aivazian.tigran@gmail.com>
6+
* Made endianness-clean by Andrew Stribblehill <[email protected]> 2005
77
*/
88

99
#include <linux/time.h>

fs/bfs/file.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
/*
33
* fs/bfs/file.c
44
* BFS file operations.
5-
* Copyright (C) 1999,2000 Tigran Aivazian <tigran@veritas.com>
5+
* Copyright (C) 1999-2018 Tigran Aivazian <aivazian.tigran@gmail.com>
66
*
77
* Make the file block allocation algorithm understand the size
88
* of the underlying block device.

fs/bfs/inode.c

Lines changed: 28 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
11
/*
22
* fs/bfs/inode.c
33
* BFS superblock and inode operations.
4-
* Copyright (C) 1999-2006 Tigran Aivazian <[email protected]>
4+
* Copyright (C) 1999-2018 Tigran Aivazian <[email protected]>
55
* From fs/minix, Copyright (C) 1991, 1992 Linus Torvalds.
6-
*
7-
* Made endianness-clean by Andrew Stribblehill <[email protected]>, 2005.
6+
* Made endianness-clean by Andrew Stribblehill <[email protected]>, 2005.
87
*/
98

109
#include <linux/module.h>
@@ -118,12 +117,12 @@ static int bfs_write_inode(struct inode *inode, struct writeback_control *wbc)
118117
{
119118
struct bfs_sb_info *info = BFS_SB(inode->i_sb);
120119
unsigned int ino = (u16)inode->i_ino;
121-
unsigned long i_sblock;
120+
unsigned long i_sblock;
122121
struct bfs_inode *di;
123122
struct buffer_head *bh;
124123
int err = 0;
125124

126-
dprintf("ino=%08x\n", ino);
125+
dprintf("ino=%08x\n", ino);
127126

128127
di = find_inode(inode->i_sb, ino, &bh);
129128
if (IS_ERR(di))
@@ -144,7 +143,7 @@ static int bfs_write_inode(struct inode *inode, struct writeback_control *wbc)
144143
di->i_atime = cpu_to_le32(inode->i_atime.tv_sec);
145144
di->i_mtime = cpu_to_le32(inode->i_mtime.tv_sec);
146145
di->i_ctime = cpu_to_le32(inode->i_ctime.tv_sec);
147-
i_sblock = BFS_I(inode)->i_sblock;
146+
i_sblock = BFS_I(inode)->i_sblock;
148147
di->i_sblock = cpu_to_le32(i_sblock);
149148
di->i_eblock = cpu_to_le32(BFS_I(inode)->i_eblock);
150149
di->i_eoffset = cpu_to_le32(i_sblock * BFS_BSIZE + inode->i_size - 1);
@@ -188,13 +187,13 @@ static void bfs_evict_inode(struct inode *inode)
188187
mark_buffer_dirty(bh);
189188
brelse(bh);
190189

191-
if (bi->i_dsk_ino) {
190+
if (bi->i_dsk_ino) {
192191
if (bi->i_sblock)
193192
info->si_freeb += bi->i_eblock + 1 - bi->i_sblock;
194193
info->si_freei++;
195194
clear_bit(ino, info->si_imap);
196-
bfs_dump_imap("delete_inode", s);
197-
}
195+
bfs_dump_imap("evict_inode", s);
196+
}
198197

199198
/*
200199
* If this was the last file, make the previous block
@@ -214,7 +213,6 @@ static void bfs_put_super(struct super_block *s)
214213
return;
215214

216215
mutex_destroy(&info->bfs_lock);
217-
kfree(info->si_imap);
218216
kfree(info);
219217
s->s_fs_info = NULL;
220218
}
@@ -311,8 +309,7 @@ void bfs_dump_imap(const char *prefix, struct super_block *s)
311309
else
312310
strcat(tmpbuf, "0");
313311
}
314-
printf("BFS-fs: %s: lasti=%08lx <%s>\n",
315-
prefix, BFS_SB(s)->si_lasti, tmpbuf);
312+
printf("%s: lasti=%08lx <%s>\n", prefix, BFS_SB(s)->si_lasti, tmpbuf);
316313
free_page((unsigned long)tmpbuf);
317314
#endif
318315
}
@@ -322,7 +319,7 @@ static int bfs_fill_super(struct super_block *s, void *data, int silent)
322319
struct buffer_head *bh, *sbh;
323320
struct bfs_super_block *bfs_sb;
324321
struct inode *inode;
325-
unsigned i, imap_len;
322+
unsigned i;
326323
struct bfs_sb_info *info;
327324
int ret = -EINVAL;
328325
unsigned long i_sblock, i_eblock, i_eoff, s_size;
@@ -341,8 +338,7 @@ static int bfs_fill_super(struct super_block *s, void *data, int silent)
341338
bfs_sb = (struct bfs_super_block *)sbh->b_data;
342339
if (le32_to_cpu(bfs_sb->s_magic) != BFS_MAGIC) {
343340
if (!silent)
344-
printf("No BFS filesystem on %s (magic=%08x)\n",
345-
s->s_id, le32_to_cpu(bfs_sb->s_magic));
341+
printf("No BFS filesystem on %s (magic=%08x)\n", s->s_id, le32_to_cpu(bfs_sb->s_magic));
346342
goto out1;
347343
}
348344
if (BFS_UNCLEAN(bfs_sb, s) && !silent)
@@ -351,18 +347,16 @@ static int bfs_fill_super(struct super_block *s, void *data, int silent)
351347
s->s_magic = BFS_MAGIC;
352348

353349
if (le32_to_cpu(bfs_sb->s_start) > le32_to_cpu(bfs_sb->s_end) ||
354-
le32_to_cpu(bfs_sb->s_start) < BFS_BSIZE) {
355-
printf("Superblock is corrupted\n");
350+
le32_to_cpu(bfs_sb->s_start) < sizeof(struct bfs_super_block) + sizeof(struct bfs_dirent)) {
351+
printf("Superblock is corrupted on %s\n", s->s_id);
356352
goto out1;
357353
}
358354

359-
info->si_lasti = (le32_to_cpu(bfs_sb->s_start) - BFS_BSIZE) /
360-
sizeof(struct bfs_inode)
361-
+ BFS_ROOT_INO - 1;
362-
imap_len = (info->si_lasti / 8) + 1;
363-
info->si_imap = kzalloc(imap_len, GFP_KERNEL | __GFP_NOWARN);
364-
if (!info->si_imap) {
365-
printf("Cannot allocate %u bytes\n", imap_len);
355+
info->si_lasti = (le32_to_cpu(bfs_sb->s_start) - BFS_BSIZE) / sizeof(struct bfs_inode) + BFS_ROOT_INO - 1;
356+
if (info->si_lasti == BFS_MAX_LASTI)
357+
printf("WARNING: filesystem %s was created with 512 inodes, the real maximum is 511, mounting anyway\n", s->s_id);
358+
else if (info->si_lasti > BFS_MAX_LASTI) {
359+
printf("Impossible last inode number %lu > %d on %s\n", info->si_lasti, BFS_MAX_LASTI, s->s_id);
366360
goto out1;
367361
}
368362
for (i = 0; i < BFS_ROOT_INO; i++)
@@ -372,26 +366,25 @@ static int bfs_fill_super(struct super_block *s, void *data, int silent)
372366
inode = bfs_iget(s, BFS_ROOT_INO);
373367
if (IS_ERR(inode)) {
374368
ret = PTR_ERR(inode);
375-
goto out2;
369+
goto out1;
376370
}
377371
s->s_root = d_make_root(inode);
378372
if (!s->s_root) {
379373
ret = -ENOMEM;
380-
goto out2;
374+
goto out1;
381375
}
382376

383377
info->si_blocks = (le32_to_cpu(bfs_sb->s_end) + 1) >> BFS_BSIZE_BITS;
384-
info->si_freeb = (le32_to_cpu(bfs_sb->s_end) + 1
385-
- le32_to_cpu(bfs_sb->s_start)) >> BFS_BSIZE_BITS;
378+
info->si_freeb = (le32_to_cpu(bfs_sb->s_end) + 1 - le32_to_cpu(bfs_sb->s_start)) >> BFS_BSIZE_BITS;
386379
info->si_freei = 0;
387380
info->si_lf_eblk = 0;
388381

389382
/* can we read the last block? */
390383
bh = sb_bread(s, info->si_blocks - 1);
391384
if (!bh) {
392-
printf("Last block not available: %lu\n", info->si_blocks - 1);
385+
printf("Last block not available on %s: %lu\n", s->s_id, info->si_blocks - 1);
393386
ret = -EIO;
394-
goto out3;
387+
goto out2;
395388
}
396389
brelse(bh);
397390

@@ -425,11 +418,11 @@ static int bfs_fill_super(struct super_block *s, void *data, int silent)
425418
(i_eoff != le32_to_cpu(-1) && i_eoff > s_size) ||
426419
i_sblock * BFS_BSIZE > i_eoff) {
427420

428-
printf("Inode 0x%08x corrupted\n", i);
421+
printf("Inode 0x%08x corrupted on %s\n", i, s->s_id);
429422

430423
brelse(bh);
431424
ret = -EIO;
432-
goto out3;
425+
goto out2;
433426
}
434427

435428
if (!di->i_ino) {
@@ -445,14 +438,12 @@ static int bfs_fill_super(struct super_block *s, void *data, int silent)
445438
}
446439
brelse(bh);
447440
brelse(sbh);
448-
bfs_dump_imap("read_super", s);
441+
bfs_dump_imap("fill_super", s);
449442
return 0;
450443

451-
out3:
444+
out2:
452445
dput(s->s_root);
453446
s->s_root = NULL;
454-
out2:
455-
kfree(info->si_imap);
456447
out1:
457448
brelse(sbh);
458449
out:
@@ -482,7 +473,7 @@ static int __init init_bfs_fs(void)
482473
int err = init_inodecache();
483474
if (err)
484475
goto out1;
485-
err = register_filesystem(&bfs_fs_type);
476+
err = register_filesystem(&bfs_fs_type);
486477
if (err)
487478
goto out;
488479
return 0;

include/uapi/linux/bfs_fs.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
22
/*
33
* include/linux/bfs_fs.h - BFS data structures on disk.
4-
* Copyright (C) 1999 Tigran Aivazian <tigran@veritas.com>
4+
* Copyright (C) 1999-2018 Tigran Aivazian <aivazian.tigran@gmail.com>
55
*/
66

77
#ifndef _LINUX_BFS_FS_H

0 commit comments

Comments
 (0)