MFS: do not crash when reading superblock fails

While MFS failing to do I/O on a block is generally fatal, reading
the superblock at mount time is an exception: this case may occur
when the given partition is too small to contain the superblock.
Therefore, MFS should not crash or even report anything in this
case, but rather refuse to mount cleanly.

This fixes #121.

Change-Id: I11326b48922a0e0ebefecbb8eec7c428f985f2b3
This commit is contained in:
David van Moolenbroek 2016-06-17 19:48:20 +00:00
parent 6c7e614940
commit ee0384891a
2 changed files with 20 additions and 4 deletions

View File

@ -176,6 +176,7 @@ static int rw_super(struct super_block *sp, int writing)
dev_t save_dev = sp->s_dev; dev_t save_dev = sp->s_dev;
struct buf *bp; struct buf *bp;
char *sbbuf; char *sbbuf;
int r;
/* To keep the 1kb on disk clean, only read/write up to and including /* To keep the 1kb on disk clean, only read/write up to and including
* this field. * this field.
@ -202,8 +203,18 @@ static int rw_super(struct super_block *sp, int writing)
assert(lmfs_fs_block_size() >= sizeof(struct super_block) + SUPER_BLOCK_BYTES); assert(lmfs_fs_block_size() >= sizeof(struct super_block) + SUPER_BLOCK_BYTES);
assert(SUPER_BLOCK_BYTES >= sizeof(struct super_block)); assert(SUPER_BLOCK_BYTES >= sizeof(struct super_block));
assert(SUPER_BLOCK_BYTES >= ondisk_bytes); assert(SUPER_BLOCK_BYTES >= ondisk_bytes);
if(!(bp = get_block(sp->s_dev, 0, NORMAL)))
panic("get_block of superblock failed"); /* Unlike accessing any other block, failure to read the superblock is a
* somewhat legitimate use case: it may happen when trying to mount a
* zero-sized partition. In that case, we'd rather faily cleanly than
* crash the MFS service.
*/
if ((r = lmfs_get_block(&bp, sp->s_dev, 0, NORMAL)) != OK) {
if (writing)
panic("get_block of superblock failed: %d", r);
else
return r;
}
/* sbbuf points to the disk block at the superblock offset */ /* sbbuf points to the disk block at the superblock offset */
sbbuf = (char *) b_data(bp) + SUPER_BLOCK_BYTES; sbbuf = (char *) b_data(bp) + SUPER_BLOCK_BYTES;

View File

@ -758,8 +758,13 @@ static int read_block(struct buf *bp, size_t block_size)
r = bdev_read(dev, pos, bp->data, block_size, BDEV_NOFLAGS); r = bdev_read(dev, pos, bp->data, block_size, BDEV_NOFLAGS);
} }
if (r != (ssize_t)block_size) { if (r != (ssize_t)block_size) {
printf("fs cache: I/O error on device %d/%d, block %"PRIu64" (%zd)\n", /* Aesthetics: do not report EOF errors on superblock reads, because
major(dev), minor(dev), bp->lmfs_blocknr, r); * this is a fairly common occurrence, e.g. during system installation.
*/
if (bp->lmfs_blocknr != 0 /*first block*/ || r != 0 /*EOF*/)
printf("fs cache: I/O error on device %d/%d, block %"PRIu64
" (%zd)\n", major(dev), minor(dev), bp->lmfs_blocknr, r);
if (r >= 0) if (r >= 0)
r = EIO; /* TODO: retry retrieving (just) the remaining part */ r = EIO; /* TODO: retry retrieving (just) the remaining part */