Commit 7d32c0ac authored by Linus Torvalds's avatar Linus Torvalds

Merge git://git.kernel.org/pub/scm/linux/kernel/git/joern/logfs

* git://git.kernel.org/pub/scm/linux/kernel/git/joern/logfs:
  logfs: handle powerfail on NAND flash
  logfs: handle errors from get_mtd_device()
  logfs: remove unused variable
  logfs: fix sync
  logfs: fix compile failure
  logfs: initialize li->li_refcount
  logfs: commit reservations under space pressure
  logfs: survive logfs_buf_recover read errors
  logfs: Close i_ino reuse race
  logfs: fix logfs_seek_hole()
  logfs: Return -EINVAL if filesystem image doesn't match
  LogFS: Fix typo in b6349ac8
  logfs: testing the wrong variable
parents 3d2c978e 6f485b41
...@@ -303,6 +303,11 @@ static void bdev_put_device(struct super_block *sb) ...@@ -303,6 +303,11 @@ static void bdev_put_device(struct super_block *sb)
close_bdev_exclusive(logfs_super(sb)->s_bdev, FMODE_READ|FMODE_WRITE); close_bdev_exclusive(logfs_super(sb)->s_bdev, FMODE_READ|FMODE_WRITE);
} }
static int bdev_can_write_buf(struct super_block *sb, u64 ofs)
{
return 0;
}
static const struct logfs_device_ops bd_devops = { static const struct logfs_device_ops bd_devops = {
.find_first_sb = bdev_find_first_sb, .find_first_sb = bdev_find_first_sb,
.find_last_sb = bdev_find_last_sb, .find_last_sb = bdev_find_last_sb,
...@@ -310,6 +315,7 @@ static const struct logfs_device_ops bd_devops = { ...@@ -310,6 +315,7 @@ static const struct logfs_device_ops bd_devops = {
.readpage = bdev_readpage, .readpage = bdev_readpage,
.writeseg = bdev_writeseg, .writeseg = bdev_writeseg,
.erase = bdev_erase, .erase = bdev_erase,
.can_write_buf = bdev_can_write_buf,
.sync = bdev_sync, .sync = bdev_sync,
.put_device = bdev_put_device, .put_device = bdev_put_device,
}; };
......
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
#include <linux/completion.h> #include <linux/completion.h>
#include <linux/mount.h> #include <linux/mount.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/slab.h>
#define PAGE_OFS(ofs) ((ofs) & (PAGE_SIZE-1)) #define PAGE_OFS(ofs) ((ofs) & (PAGE_SIZE-1))
...@@ -126,7 +127,8 @@ static int mtd_readpage(void *_sb, struct page *page) ...@@ -126,7 +127,8 @@ static int mtd_readpage(void *_sb, struct page *page)
err = mtd_read(sb, page->index << PAGE_SHIFT, PAGE_SIZE, err = mtd_read(sb, page->index << PAGE_SHIFT, PAGE_SIZE,
page_address(page)); page_address(page));
if (err == -EUCLEAN) { if (err == -EUCLEAN || err == -EBADMSG) {
/* -EBADMSG happens regularly on power failures */
err = 0; err = 0;
/* FIXME: force GC this segment */ /* FIXME: force GC this segment */
} }
...@@ -233,12 +235,32 @@ static void mtd_put_device(struct super_block *sb) ...@@ -233,12 +235,32 @@ static void mtd_put_device(struct super_block *sb)
put_mtd_device(logfs_super(sb)->s_mtd); put_mtd_device(logfs_super(sb)->s_mtd);
} }
static int mtd_can_write_buf(struct super_block *sb, u64 ofs)
{
struct logfs_super *super = logfs_super(sb);
void *buf;
int err;
buf = kmalloc(super->s_writesize, GFP_KERNEL);
if (!buf)
return -ENOMEM;
err = mtd_read(sb, ofs, super->s_writesize, buf);
if (err)
goto out;
if (memchr_inv(buf, 0xff, super->s_writesize))
err = -EIO;
kfree(buf);
out:
return err;
}
static const struct logfs_device_ops mtd_devops = { static const struct logfs_device_ops mtd_devops = {
.find_first_sb = mtd_find_first_sb, .find_first_sb = mtd_find_first_sb,
.find_last_sb = mtd_find_last_sb, .find_last_sb = mtd_find_last_sb,
.readpage = mtd_readpage, .readpage = mtd_readpage,
.writeseg = mtd_writeseg, .writeseg = mtd_writeseg,
.erase = mtd_erase, .erase = mtd_erase,
.can_write_buf = mtd_can_write_buf,
.sync = mtd_sync, .sync = mtd_sync,
.put_device = mtd_put_device, .put_device = mtd_put_device,
}; };
...@@ -250,5 +272,7 @@ int logfs_get_sb_mtd(struct file_system_type *type, int flags, ...@@ -250,5 +272,7 @@ int logfs_get_sb_mtd(struct file_system_type *type, int flags,
const struct logfs_device_ops *devops = &mtd_devops; const struct logfs_device_ops *devops = &mtd_devops;
mtd = get_mtd_device(NULL, mtdnr); mtd = get_mtd_device(NULL, mtdnr);
if (IS_ERR(mtd))
return PTR_ERR(mtd);
return logfs_get_sb_device(type, flags, mtd, NULL, devops, mnt); return logfs_get_sb_device(type, flags, mtd, NULL, devops, mnt);
} }
...@@ -161,7 +161,17 @@ static int logfs_writepage(struct page *page, struct writeback_control *wbc) ...@@ -161,7 +161,17 @@ static int logfs_writepage(struct page *page, struct writeback_control *wbc)
static void logfs_invalidatepage(struct page *page, unsigned long offset) static void logfs_invalidatepage(struct page *page, unsigned long offset)
{ {
move_page_to_btree(page); struct logfs_block *block = logfs_block(page);
if (block->reserved_bytes) {
struct super_block *sb = page->mapping->host->i_sb;
struct logfs_super *super = logfs_super(sb);
super->s_dirty_pages -= block->reserved_bytes;
block->ops->free_block(sb, block);
BUG_ON(bitmap_weight(block->alias_map, LOGFS_BLOCK_FACTOR));
} else
move_page_to_btree(page);
BUG_ON(PagePrivate(page) || page->private); BUG_ON(PagePrivate(page) || page->private);
} }
...@@ -212,10 +222,8 @@ int logfs_ioctl(struct inode *inode, struct file *file, unsigned int cmd, ...@@ -212,10 +222,8 @@ int logfs_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
int logfs_fsync(struct file *file, struct dentry *dentry, int datasync) int logfs_fsync(struct file *file, struct dentry *dentry, int datasync)
{ {
struct super_block *sb = dentry->d_inode->i_sb; struct super_block *sb = dentry->d_inode->i_sb;
struct logfs_super *super = logfs_super(sb);
/* FIXME: write anchor */ logfs_write_anchor(sb);
super->s_devops->sync(sb);
return 0; return 0;
} }
......
...@@ -122,7 +122,7 @@ static void logfs_cleanse_block(struct super_block *sb, u64 ofs, u64 ino, ...@@ -122,7 +122,7 @@ static void logfs_cleanse_block(struct super_block *sb, u64 ofs, u64 ino,
logfs_safe_iput(inode, cookie); logfs_safe_iput(inode, cookie);
} }
static u32 logfs_gc_segment(struct super_block *sb, u32 segno, u8 dist) static u32 logfs_gc_segment(struct super_block *sb, u32 segno)
{ {
struct logfs_super *super = logfs_super(sb); struct logfs_super *super = logfs_super(sb);
struct logfs_segment_header sh; struct logfs_segment_header sh;
...@@ -401,7 +401,7 @@ static int __logfs_gc_once(struct super_block *sb, struct gc_candidate *cand) ...@@ -401,7 +401,7 @@ static int __logfs_gc_once(struct super_block *sb, struct gc_candidate *cand)
segno, (u64)segno << super->s_segshift, segno, (u64)segno << super->s_segshift,
dist, no_free_segments(sb), valid, dist, no_free_segments(sb), valid,
super->s_free_bytes); super->s_free_bytes);
cleaned = logfs_gc_segment(sb, segno, dist); cleaned = logfs_gc_segment(sb, segno);
log_gc("GC segment #%02x complete - now %x valid\n", segno, log_gc("GC segment #%02x complete - now %x valid\n", segno,
valid - cleaned); valid - cleaned);
BUG_ON(cleaned != valid); BUG_ON(cleaned != valid);
...@@ -632,38 +632,31 @@ static int check_area(struct super_block *sb, int i) ...@@ -632,38 +632,31 @@ static int check_area(struct super_block *sb, int i)
{ {
struct logfs_super *super = logfs_super(sb); struct logfs_super *super = logfs_super(sb);
struct logfs_area *area = super->s_area[i]; struct logfs_area *area = super->s_area[i];
struct logfs_object_header oh; gc_level_t gc_level;
u32 cleaned, valid, ec;
u32 segno = area->a_segno; u32 segno = area->a_segno;
u32 ofs = area->a_used_bytes; u64 ofs = dev_ofs(sb, area->a_segno, area->a_written_bytes);
__be32 crc;
int err;
if (!area->a_is_open) if (!area->a_is_open)
return 0; return 0;
for (ofs = area->a_used_bytes; if (super->s_devops->can_write_buf(sb, ofs) == 0)
ofs <= super->s_segsize - sizeof(oh); return 0;
ofs += (u32)be16_to_cpu(oh.len) + sizeof(oh)) {
err = wbuf_read(sb, dev_ofs(sb, segno, ofs), sizeof(oh), &oh);
if (err)
return err;
if (!memchr_inv(&oh, 0xff, sizeof(oh)))
break;
crc = logfs_crc32(&oh, sizeof(oh) - 4, 4); printk(KERN_INFO"LogFS: Possibly incomplete write at %llx\n", ofs);
if (crc != oh.crc) { /*
printk(KERN_INFO "interrupted header at %llx\n", * The device cannot write back the write buffer. Most likely the
dev_ofs(sb, segno, ofs)); * wbuf was already written out and the system crashed at some point
return 0; * before the journal commit happened. In that case we wouldn't have
} * to do anything. But if the crash happened before the wbuf was
} * written out correctly, we must GC this segment. So assume the
if (ofs != area->a_used_bytes) { * worst and always do the GC run.
printk(KERN_INFO "%x bytes unaccounted data found at %llx\n", */
ofs - area->a_used_bytes, area->a_is_open = 0;
dev_ofs(sb, segno, area->a_used_bytes)); valid = logfs_valid_bytes(sb, segno, &ec, &gc_level);
area->a_used_bytes = ofs; cleaned = logfs_gc_segment(sb, segno);
} if (cleaned != valid)
return -EIO;
return 0; return 0;
} }
......
...@@ -193,6 +193,7 @@ static void logfs_init_inode(struct super_block *sb, struct inode *inode) ...@@ -193,6 +193,7 @@ static void logfs_init_inode(struct super_block *sb, struct inode *inode)
inode->i_ctime = CURRENT_TIME; inode->i_ctime = CURRENT_TIME;
inode->i_mtime = CURRENT_TIME; inode->i_mtime = CURRENT_TIME;
inode->i_nlink = 1; inode->i_nlink = 1;
li->li_refcount = 1;
INIT_LIST_HEAD(&li->li_freeing_list); INIT_LIST_HEAD(&li->li_freeing_list);
for (i = 0; i < LOGFS_EMBEDDED_FIELDS; i++) for (i = 0; i < LOGFS_EMBEDDED_FIELDS; i++)
...@@ -326,7 +327,7 @@ static void logfs_set_ino_generation(struct super_block *sb, ...@@ -326,7 +327,7 @@ static void logfs_set_ino_generation(struct super_block *sb,
u64 ino; u64 ino;
mutex_lock(&super->s_journal_mutex); mutex_lock(&super->s_journal_mutex);
ino = logfs_seek_hole(super->s_master_inode, super->s_last_ino); ino = logfs_seek_hole(super->s_master_inode, super->s_last_ino + 1);
super->s_last_ino = ino; super->s_last_ino = ino;
super->s_inos_till_wrap--; super->s_inos_till_wrap--;
if (super->s_inos_till_wrap < 0) { if (super->s_inos_till_wrap < 0) {
...@@ -386,8 +387,7 @@ static void logfs_init_once(void *_li) ...@@ -386,8 +387,7 @@ static void logfs_init_once(void *_li)
static int logfs_sync_fs(struct super_block *sb, int wait) static int logfs_sync_fs(struct super_block *sb, int wait)
{ {
/* FIXME: write anchor */ logfs_write_anchor(sb);
logfs_super(sb)->s_devops->sync(sb);
return 0; return 0;
} }
......
...@@ -132,10 +132,9 @@ static int read_area(struct super_block *sb, struct logfs_je_area *a) ...@@ -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); ofs = dev_ofs(sb, area->a_segno, area->a_written_bytes);
if (super->s_writesize > 1) 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 else
logfs_buf_recover(area, ofs, NULL, 0); return logfs_buf_recover(area, ofs, NULL, 0);
return 0;
} }
static void *unpack(void *from, void *to) static void *unpack(void *from, void *to)
...@@ -245,7 +244,7 @@ static int read_je(struct super_block *sb, u64 ofs) ...@@ -245,7 +244,7 @@ static int read_je(struct super_block *sb, u64 ofs)
read_erasecount(sb, unpack(jh, scratch)); read_erasecount(sb, unpack(jh, scratch));
break; break;
case JE_AREA: case JE_AREA:
read_area(sb, unpack(jh, scratch)); err = read_area(sb, unpack(jh, scratch));
break; break;
case JE_OBJ_ALIAS: case JE_OBJ_ALIAS:
err = logfs_load_object_aliases(sb, unpack(jh, scratch), err = logfs_load_object_aliases(sb, unpack(jh, scratch),
......
...@@ -144,6 +144,7 @@ struct logfs_area_ops { ...@@ -144,6 +144,7 @@ struct logfs_area_ops {
* @erase: erase one segment * @erase: erase one segment
* @read: read from the device * @read: read from the device
* @erase: erase part of the device * @erase: erase part of the device
* @can_write_buf: decide whether wbuf can be written to ofs
*/ */
struct logfs_device_ops { struct logfs_device_ops {
struct page *(*find_first_sb)(struct super_block *sb, u64 *ofs); struct page *(*find_first_sb)(struct super_block *sb, u64 *ofs);
...@@ -153,6 +154,7 @@ struct logfs_device_ops { ...@@ -153,6 +154,7 @@ struct logfs_device_ops {
void (*writeseg)(struct super_block *sb, u64 ofs, size_t len); void (*writeseg)(struct super_block *sb, u64 ofs, size_t len);
int (*erase)(struct super_block *sb, loff_t ofs, size_t len, int (*erase)(struct super_block *sb, loff_t ofs, size_t len,
int ensure_write); int ensure_write);
int (*can_write_buf)(struct super_block *sb, u64 ofs);
void (*sync)(struct super_block *sb); void (*sync)(struct super_block *sb);
void (*put_device)(struct super_block *sb); void (*put_device)(struct super_block *sb);
}; };
...@@ -394,6 +396,7 @@ struct logfs_super { ...@@ -394,6 +396,7 @@ struct logfs_super {
int s_lock_count; int s_lock_count;
mempool_t *s_block_pool; /* struct logfs_block pool */ mempool_t *s_block_pool; /* struct logfs_block pool */
mempool_t *s_shadow_pool; /* struct logfs_shadow pool */ mempool_t *s_shadow_pool; /* struct logfs_shadow pool */
struct list_head s_writeback_list; /* writeback pages */
/* /*
* Space accounting: * Space accounting:
* - s_used_bytes specifies space used to store valid data objects. * - s_used_bytes specifies space used to store valid data objects.
...@@ -598,19 +601,19 @@ void freeseg(struct super_block *sb, u32 segno); ...@@ -598,19 +601,19 @@ void freeseg(struct super_block *sb, u32 segno);
int logfs_init_areas(struct super_block *sb); int logfs_init_areas(struct super_block *sb);
void logfs_cleanup_areas(struct super_block *sb); void logfs_cleanup_areas(struct super_block *sb);
int logfs_open_area(struct logfs_area *area, size_t bytes); 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); 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) 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) void *buf, size_t len)
{ {
__logfs_buf_write(area, ofs, buf, len, 1); return __logfs_buf_write(area, ofs, buf, len, 1);
} }
/* super.c */ /* super.c */
......
...@@ -892,6 +892,8 @@ u64 logfs_seek_hole(struct inode *inode, u64 bix) ...@@ -892,6 +892,8 @@ u64 logfs_seek_hole(struct inode *inode, u64 bix)
return bix; return bix;
else if (li->li_data[INDIRECT_INDEX] & LOGFS_FULLY_POPULATED) else if (li->li_data[INDIRECT_INDEX] & LOGFS_FULLY_POPULATED)
bix = maxbix(li->li_height); bix = maxbix(li->li_height);
else if (bix >= maxbix(li->li_height))
return bix;
else { else {
bix = seek_holedata_loop(inode, bix, 0); bix = seek_holedata_loop(inode, bix, 0);
if (bix < maxbix(li->li_height)) if (bix < maxbix(li->li_height))
...@@ -1093,17 +1095,25 @@ static int logfs_reserve_bytes(struct inode *inode, int bytes) ...@@ -1093,17 +1095,25 @@ static int logfs_reserve_bytes(struct inode *inode, int bytes)
int get_page_reserve(struct inode *inode, struct page *page) int get_page_reserve(struct inode *inode, struct page *page)
{ {
struct logfs_super *super = logfs_super(inode->i_sb); struct logfs_super *super = logfs_super(inode->i_sb);
struct logfs_block *block = logfs_block(page);
int ret; int ret;
if (logfs_block(page) && logfs_block(page)->reserved_bytes) if (block && block->reserved_bytes)
return 0; return 0;
logfs_get_wblocks(inode->i_sb, page, WF_LOCK); logfs_get_wblocks(inode->i_sb, page, WF_LOCK);
ret = logfs_reserve_bytes(inode, 6 * LOGFS_MAX_OBJECTSIZE); while ((ret = logfs_reserve_bytes(inode, 6 * LOGFS_MAX_OBJECTSIZE)) &&
!list_empty(&super->s_writeback_list)) {
block = list_entry(super->s_writeback_list.next,
struct logfs_block, alias_list);
block->ops->write_block(block);
}
if (!ret) { if (!ret) {
alloc_data_block(inode, page); alloc_data_block(inode, page);
logfs_block(page)->reserved_bytes += 6 * LOGFS_MAX_OBJECTSIZE; block = logfs_block(page);
block->reserved_bytes += 6 * LOGFS_MAX_OBJECTSIZE;
super->s_dirty_pages += 6 * LOGFS_MAX_OBJECTSIZE; super->s_dirty_pages += 6 * LOGFS_MAX_OBJECTSIZE;
list_move_tail(&block->alias_list, &super->s_writeback_list);
} }
logfs_put_wblocks(inode->i_sb, page, WF_LOCK); logfs_put_wblocks(inode->i_sb, page, WF_LOCK);
return ret; return ret;
...@@ -1861,7 +1871,7 @@ int logfs_truncate(struct inode *inode, u64 target) ...@@ -1861,7 +1871,7 @@ int logfs_truncate(struct inode *inode, u64 target)
size = target; size = target;
logfs_get_wblocks(sb, NULL, 1); logfs_get_wblocks(sb, NULL, 1);
err = __logfs_truncate(inode, target); err = __logfs_truncate(inode, size);
if (!err) if (!err)
err = __logfs_write_inode(inode, 0); err = __logfs_write_inode(inode, 0);
logfs_put_wblocks(sb, NULL, 1); logfs_put_wblocks(sb, NULL, 1);
...@@ -2249,6 +2259,7 @@ int logfs_init_rw(struct super_block *sb) ...@@ -2249,6 +2259,7 @@ int logfs_init_rw(struct super_block *sb)
int min_fill = 3 * super->s_no_blocks; int min_fill = 3 * super->s_no_blocks;
INIT_LIST_HEAD(&super->s_object_alias); INIT_LIST_HEAD(&super->s_object_alias);
INIT_LIST_HEAD(&super->s_writeback_list);
mutex_init(&super->s_write_mutex); mutex_init(&super->s_write_mutex);
super->s_block_pool = mempool_create_kmalloc_pool(min_fill, super->s_block_pool = mempool_create_kmalloc_pool(min_fill,
sizeof(struct logfs_block)); sizeof(struct logfs_block));
......
...@@ -67,7 +67,7 @@ static struct page *get_mapping_page(struct super_block *sb, pgoff_t index, ...@@ -67,7 +67,7 @@ static struct page *get_mapping_page(struct super_block *sb, pgoff_t index,
return page; 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) int use_filler)
{ {
pgoff_t index = ofs >> PAGE_SHIFT; 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,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); copylen = min((ulong)len, PAGE_SIZE - offset);
page = get_mapping_page(area->a_sb, index, use_filler); 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 */ BUG_ON(!page); /* FIXME: reserve a pool */
SetPageUptodate(page);
memcpy(page_address(page) + offset, buf, copylen); memcpy(page_address(page) + offset, buf, copylen);
SetPagePrivate(page); SetPagePrivate(page);
page_cache_release(page); page_cache_release(page);
...@@ -92,6 +94,7 @@ void __logfs_buf_write(struct logfs_area *area, u64 ofs, void *buf, size_t len, ...@@ -92,6 +94,7 @@ void __logfs_buf_write(struct logfs_area *area, u64 ofs, void *buf, size_t len,
offset = 0; offset = 0;
index++; index++;
} while (len); } while (len);
return 0;
} }
static void pad_partial_page(struct logfs_area *area) static void pad_partial_page(struct logfs_area *area)
......
...@@ -138,10 +138,14 @@ static int logfs_sb_set(struct super_block *sb, void *_super) ...@@ -138,10 +138,14 @@ static int logfs_sb_set(struct super_block *sb, void *_super)
sb->s_fs_info = super; sb->s_fs_info = super;
sb->s_mtd = super->s_mtd; sb->s_mtd = super->s_mtd;
sb->s_bdev = super->s_bdev; sb->s_bdev = super->s_bdev;
#ifdef CONFIG_BLOCK
if (sb->s_bdev) if (sb->s_bdev)
sb->s_bdi = &bdev_get_queue(sb->s_bdev)->backing_dev_info; sb->s_bdi = &bdev_get_queue(sb->s_bdev)->backing_dev_info;
#endif
#ifdef CONFIG_MTD
if (sb->s_mtd) if (sb->s_mtd)
sb->s_bdi = sb->s_mtd->backing_dev_info; sb->s_bdi = sb->s_mtd->backing_dev_info;
#endif
return 0; return 0;
} }
...@@ -382,7 +386,7 @@ static struct page *find_super_block(struct super_block *sb) ...@@ -382,7 +386,7 @@ static struct page *find_super_block(struct super_block *sb)
if (!first || IS_ERR(first)) if (!first || IS_ERR(first))
return NULL; return NULL;
last = super->s_devops->find_last_sb(sb, &super->s_sb_ofs[1]); last = super->s_devops->find_last_sb(sb, &super->s_sb_ofs[1]);
if (!last || IS_ERR(first)) { if (!last || IS_ERR(last)) {
page_cache_release(first); page_cache_release(first);
return NULL; return NULL;
} }
...@@ -413,7 +417,7 @@ static int __logfs_read_sb(struct super_block *sb) ...@@ -413,7 +417,7 @@ static int __logfs_read_sb(struct super_block *sb)
page = find_super_block(sb); page = find_super_block(sb);
if (!page) if (!page)
return -EIO; return -EINVAL;
ds = page_address(page); ds = page_address(page);
super->s_size = be64_to_cpu(ds->ds_filesystem_size); super->s_size = be64_to_cpu(ds->ds_filesystem_size);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment