Commit 20503664 authored by Joern Engel's avatar Joern Engel
Browse files

logfs: survive logfs_buf_recover read errors



Refusing to mount beats a kernel crash.

Signed-off-by: default avatarJoern Engel <joern@logfs.org>
parent ccc0197b
Loading
Loading
Loading
Loading
+3 −4
Original line number Diff line number Diff line
@@ -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),
+5 −5
Original line number Diff line number Diff line
@@ -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 */
+5 −2
Original line number Diff line number Diff line
@@ -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)