logfs: survive logfs_buf_recover read errors
authorJoern Engel <joern@logfs.org>
Mon, 3 May 2010 18:54:34 +0000 (20:54 +0200)
committerJoern Engel <joern@logfs.org>
Tue, 4 May 2010 17:37:04 +0000 (19:37 +0200)
Refusing to mount beats a kernel crash.

Signed-off-by: Joern Engel <joern@logfs.org>
fs/logfs/journal.c
fs/logfs/logfs.h
fs/logfs/segment.c

index fb0a613f885b768c12a49ef52f1ab0fac42e12be..4b0e0616b357d59ba89fda8f7450c24e85a2abba 100644 (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),
index 0a3df1a0c93687932b729174c10a4960ec48265b..32bf55616e5605593e7be2333157b8b8347702a8 100644 (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 */
index f77ce2b470ba667183dede53386219d40e729bb8..a9657afb70ad1a562bdb36a2f789d8eda672deec 100644 (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)