diff options
author | Joern Engel <joern@logfs.org> | 2010-05-03 14:54:34 -0400 |
---|---|---|
committer | Joern Engel <joern@logfs.org> | 2010-05-04 13:37:04 -0400 |
commit | 20503664b008e17976bff1fdbc693c77ebd6f6c9 (patch) | |
tree | 7cff886995e42d0b90dd3ebe86993f0277e9345c | |
parent | ccc0197b02178f7e1707e659cbc5242fc94b499a (diff) |
logfs: survive logfs_buf_recover read errors
Refusing to mount beats a kernel crash.
Signed-off-by: Joern Engel <joern@logfs.org>
-rw-r--r-- | fs/logfs/journal.c | 7 | ||||
-rw-r--r-- | fs/logfs/logfs.h | 10 | ||||
-rw-r--r-- | fs/logfs/segment.c | 7 |
3 files changed, 13 insertions, 11 deletions
diff --git a/fs/logfs/journal.c b/fs/logfs/journal.c index fb0a613f885b..4b0e0616b357 100644 --- a/fs/logfs/journal.c +++ b/fs/logfs/journal.c | |||
@@ -132,10 +132,9 @@ static int read_area(struct super_block *sb, struct logfs_je_area *a) | |||
132 | 132 | ||
133 | ofs = dev_ofs(sb, area->a_segno, area->a_written_bytes); | 133 | ofs = dev_ofs(sb, area->a_segno, area->a_written_bytes); |
134 | if (super->s_writesize > 1) | 134 | if (super->s_writesize > 1) |
135 | logfs_buf_recover(area, ofs, a + 1, super->s_writesize); | 135 | return logfs_buf_recover(area, ofs, a + 1, super->s_writesize); |
136 | else | 136 | else |
137 | logfs_buf_recover(area, ofs, NULL, 0); | 137 | return logfs_buf_recover(area, ofs, NULL, 0); |
138 | return 0; | ||
139 | } | 138 | } |
140 | 139 | ||
141 | static void *unpack(void *from, void *to) | 140 | static void *unpack(void *from, void *to) |
@@ -245,7 +244,7 @@ static int read_je(struct super_block *sb, u64 ofs) | |||
245 | read_erasecount(sb, unpack(jh, scratch)); | 244 | read_erasecount(sb, unpack(jh, scratch)); |
246 | break; | 245 | break; |
247 | case JE_AREA: | 246 | case JE_AREA: |
248 | read_area(sb, unpack(jh, scratch)); | 247 | err = read_area(sb, unpack(jh, scratch)); |
249 | break; | 248 | break; |
250 | case JE_OBJ_ALIAS: | 249 | case JE_OBJ_ALIAS: |
251 | err = logfs_load_object_aliases(sb, unpack(jh, scratch), | 250 | err = logfs_load_object_aliases(sb, unpack(jh, scratch), |
diff --git a/fs/logfs/logfs.h b/fs/logfs/logfs.h index 0a3df1a0c936..32bf55616e56 100644 --- a/fs/logfs/logfs.h +++ b/fs/logfs/logfs.h | |||
@@ -598,19 +598,19 @@ void freeseg(struct super_block *sb, u32 segno); | |||
598 | int logfs_init_areas(struct super_block *sb); | 598 | int logfs_init_areas(struct super_block *sb); |
599 | void logfs_cleanup_areas(struct super_block *sb); | 599 | void logfs_cleanup_areas(struct super_block *sb); |
600 | int logfs_open_area(struct logfs_area *area, size_t bytes); | 600 | int logfs_open_area(struct logfs_area *area, size_t bytes); |
601 | void __logfs_buf_write(struct logfs_area *area, u64 ofs, void *buf, size_t len, | 601 | int __logfs_buf_write(struct logfs_area *area, u64 ofs, void *buf, size_t len, |
602 | int use_filler); | 602 | int use_filler); |
603 | 603 | ||
604 | static inline void logfs_buf_write(struct logfs_area *area, u64 ofs, | 604 | static inline int logfs_buf_write(struct logfs_area *area, u64 ofs, |
605 | void *buf, size_t len) | 605 | void *buf, size_t len) |
606 | { | 606 | { |
607 | __logfs_buf_write(area, ofs, buf, len, 0); | 607 | return __logfs_buf_write(area, ofs, buf, len, 0); |
608 | } | 608 | } |
609 | 609 | ||
610 | static inline void logfs_buf_recover(struct logfs_area *area, u64 ofs, | 610 | static inline int logfs_buf_recover(struct logfs_area *area, u64 ofs, |
611 | void *buf, size_t len) | 611 | void *buf, size_t len) |
612 | { | 612 | { |
613 | __logfs_buf_write(area, ofs, buf, len, 1); | 613 | return __logfs_buf_write(area, ofs, buf, len, 1); |
614 | } | 614 | } |
615 | 615 | ||
616 | /* super.c */ | 616 | /* super.c */ |
diff --git a/fs/logfs/segment.c b/fs/logfs/segment.c index f77ce2b470ba..a9657afb70ad 100644 --- a/fs/logfs/segment.c +++ b/fs/logfs/segment.c | |||
@@ -67,7 +67,7 @@ static struct page *get_mapping_page(struct super_block *sb, pgoff_t index, | |||
67 | return page; | 67 | return page; |
68 | } | 68 | } |
69 | 69 | ||
70 | void __logfs_buf_write(struct logfs_area *area, u64 ofs, void *buf, size_t len, | 70 | int __logfs_buf_write(struct logfs_area *area, u64 ofs, void *buf, size_t len, |
71 | int use_filler) | 71 | int use_filler) |
72 | { | 72 | { |
73 | pgoff_t index = ofs >> PAGE_SHIFT; | 73 | 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, | |||
81 | copylen = min((ulong)len, PAGE_SIZE - offset); | 81 | copylen = min((ulong)len, PAGE_SIZE - offset); |
82 | 82 | ||
83 | page = get_mapping_page(area->a_sb, index, use_filler); | 83 | page = get_mapping_page(area->a_sb, index, use_filler); |
84 | SetPageUptodate(page); | 84 | if (IS_ERR(page)) |
85 | return PTR_ERR(page); | ||
85 | BUG_ON(!page); /* FIXME: reserve a pool */ | 86 | BUG_ON(!page); /* FIXME: reserve a pool */ |
87 | SetPageUptodate(page); | ||
86 | memcpy(page_address(page) + offset, buf, copylen); | 88 | memcpy(page_address(page) + offset, buf, copylen); |
87 | SetPagePrivate(page); | 89 | SetPagePrivate(page); |
88 | page_cache_release(page); | 90 | page_cache_release(page); |
@@ -92,6 +94,7 @@ void __logfs_buf_write(struct logfs_area *area, u64 ofs, void *buf, size_t len, | |||
92 | offset = 0; | 94 | offset = 0; |
93 | index++; | 95 | index++; |
94 | } while (len); | 96 | } while (len); |
97 | return 0; | ||
95 | } | 98 | } |
96 | 99 | ||
97 | static void pad_partial_page(struct logfs_area *area) | 100 | static void pad_partial_page(struct logfs_area *area) |