logfs: survive logfs_buf_recover read errors

Refusing to mount beats a kernel crash.

Signed-off-by: Joern Engel <joern@logfs.org>
This commit is contained in:
Joern Engel 2010-05-03 20:54:34 +02:00
parent ccc0197b02
commit 20503664b0
3 changed files with 13 additions and 11 deletions

View File

@ -132,10 +132,9 @@ static int read_area(struct super_block *sb, struct logfs_je_area *a)
ofs = dev_ofs(sb, area->a_segno, area->a_written_bytes);
if (super->s_writesize > 1)
logfs_buf_recover(area, ofs, a + 1, super->s_writesize);
return logfs_buf_recover(area, ofs, a + 1, super->s_writesize);
else
logfs_buf_recover(area, ofs, NULL, 0);
return 0;
return logfs_buf_recover(area, ofs, NULL, 0);
}
static void *unpack(void *from, void *to)
@ -245,7 +244,7 @@ static int read_je(struct super_block *sb, u64 ofs)
read_erasecount(sb, unpack(jh, scratch));
break;
case JE_AREA:
read_area(sb, unpack(jh, scratch));
err = read_area(sb, unpack(jh, scratch));
break;
case JE_OBJ_ALIAS:
err = logfs_load_object_aliases(sb, unpack(jh, scratch),

View File

@ -598,19 +598,19 @@ void freeseg(struct super_block *sb, u32 segno);
int logfs_init_areas(struct super_block *sb);
void logfs_cleanup_areas(struct super_block *sb);
int logfs_open_area(struct logfs_area *area, size_t bytes);
void __logfs_buf_write(struct logfs_area *area, u64 ofs, void *buf, size_t len,
int __logfs_buf_write(struct logfs_area *area, u64 ofs, void *buf, size_t len,
int use_filler);
static inline void logfs_buf_write(struct logfs_area *area, u64 ofs,
static inline int logfs_buf_write(struct logfs_area *area, u64 ofs,
void *buf, size_t len)
{
__logfs_buf_write(area, ofs, buf, len, 0);
return __logfs_buf_write(area, ofs, buf, len, 0);
}
static inline void logfs_buf_recover(struct logfs_area *area, u64 ofs,
static inline int logfs_buf_recover(struct logfs_area *area, u64 ofs,
void *buf, size_t len)
{
__logfs_buf_write(area, ofs, buf, len, 1);
return __logfs_buf_write(area, ofs, buf, len, 1);
}
/* super.c */

View File

@ -67,7 +67,7 @@ static struct page *get_mapping_page(struct super_block *sb, pgoff_t index,
return page;
}
void __logfs_buf_write(struct logfs_area *area, u64 ofs, void *buf, size_t len,
int __logfs_buf_write(struct logfs_area *area, u64 ofs, void *buf, size_t len,
int use_filler)
{
pgoff_t index = ofs >> PAGE_SHIFT;
@ -81,8 +81,10 @@ void __logfs_buf_write(struct logfs_area *area, u64 ofs, void *buf, size_t len,
copylen = min((ulong)len, PAGE_SIZE - offset);
page = get_mapping_page(area->a_sb, index, use_filler);
SetPageUptodate(page);
if (IS_ERR(page))
return PTR_ERR(page);
BUG_ON(!page); /* FIXME: reserve a pool */
SetPageUptodate(page);
memcpy(page_address(page) + offset, buf, copylen);
SetPagePrivate(page);
page_cache_release(page);
@ -92,6 +94,7 @@ void __logfs_buf_write(struct logfs_area *area, u64 ofs, void *buf, size_t len,
offset = 0;
index++;
} while (len);
return 0;
}
static void pad_partial_page(struct logfs_area *area)