forked from Minki/linux
Pull request from git://github.com/prasad-joshi/logfs_upstream.git
There are few important bug fixes for LogFS Shortlog: Joern Engel (5): logfs: Prevent memory corruption logfs: remove useless BUG_ON logfs: Free areas before calling generic_shutdown_super() logfs: Grow inode in delete path Logfs: Allow NULL block_isbad() methods Prasad Joshi (5): logfs: update page reference count for pined pages logfs: take write mutex lock during fsync and sync logfs: set superblock shutdown flag after generic sb shutdown logfs: Propagate page parameter to __logfs_write_inode MAINTAINERS: Add Prasad Joshi in LogFS maintiners Diffstat: MAINTAINERS | 1 + fs/logfs/dev_mtd.c | 26 +++++++++++------------- fs/logfs/dir.c | 2 +- fs/logfs/file.c | 2 + fs/logfs/gc.c | 2 +- fs/logfs/inode.c | 4 ++- fs/logfs/journal.c | 1 - fs/logfs/logfs.h | 5 +++- fs/logfs/readwrite.c | 51 +++++++++++++++++++++++++++++++++---------------- fs/logfs/segment.c | 51 ++++++++++++++++++++++++++++++++++++++----------- fs/logfs/super.c | 3 +- 11 files changed, 99 insertions(+), 49 deletions(-) -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.11 (GNU/Linux) iQIcBAABAgAGBQJPKByhAAoJEDFA/f+3K+ZNQSUP/3gACcIwcsl+FnXPWBtz9XIG g0DjXoRDd/sR0u25nLgjCVdBJgx5FVEyA+PvLgvvUU2KCAsqI5F/EQ+fLJs21YEN TzepBO5aHtFZbNEjo6WiXOlDbBePTtk44WrN6jqoCHM/aDeT4Wof3NZBmHWNN1PX B2RtEZ0ypJ7/b1OY2LUNcQfTaJXNgVoP8Hkx4KGY5LUVxVrBXxvDTU7YbkS8a+ys 1Yje/EQ4XD4RyZB42TmFEuTenvGPRgMGVFdnkJKuON8EmJQ8Hc61jEf5d7Q8sWef dH5F/ptoAaR9a9LbbO8LoYuBZ8MR8848NPsrNPpr/gWntj46Z79yII8Jr7YoSDyw zq5G2dZbwlbVrtVWKGae47THkNB8bljR/g4cijvPAkvuIAku6mg+dgjVHAhZ/t+J xu8+Gy2sWHUH2gmoSXuoNyppOvYpPIRd5RB16PizMH3bw+sMad2K8/rfOKnmF1/r HTM2jZ5bDcHVDjSuVI6u2m/mQX+PmPXUTffreaFXuSI75YpT0dqN3nponTX4EgFI Ad9ZBQvdg8w1LGDsNxIAaqrGx4Q87RxqfUV4W/wo6N8gKsp+I2y4GtYMeD/CEKyi wncKg10YwoMXZj7cBAkWgPlgrOBYCPwYZc/1DVRHvqrHo/m13SJrWDKkNKVvoXzH 2y4Tfi5w1WDRUT7yeoyK =TA1A -----END PGP SIGNATURE----- Merge tag 'for-linus' of git://github.com/prasad-joshi/logfs_upstream There are few important bug fixes for LogFS * tag 'for-linus' of git://github.com/prasad-joshi/logfs_upstream: Logfs: Allow NULL block_isbad() methods logfs: Grow inode in delete path logfs: Free areas before calling generic_shutdown_super() logfs: remove useless BUG_ON MAINTAINERS: Add Prasad Joshi in LogFS maintiners logfs: Propagate page parameter to __logfs_write_inode logfs: set superblock shutdown flag after generic sb shutdown logfs: take write mutex lock during fsync and sync logfs: Prevent memory corruption logfs: update page reference count for pined pages Fix up conflict in fs/logfs/dev_mtd.c due to semantic change in what "mtd->block_isbad" means in commitf2933e86ad
: "Logfs: Allow NULL block_isbad() methods" clashing with the abstraction changes in the commits7086c19d07
: "mtd: introduce mtd_block_isbad interface" andd58b27ed58
: "logfs: do not use 'mtd->block_isbad' directly". This resolution takes the semantics from commitf2933e86ad
, and just makes mtd_block_isbad() return zero (false) if the 'block_isbad' function is NULL. But that also means that now "mtd_can_have_bb()" always returns 0. Now, "mtd_block_markbad()" will obviously return an error if the low-level driver doesn't support bad blocks, so this is somewhat non-symmetric, but it actually makes sense if a NULL "block_isbad" function is considered to mean "I assume that all my blocks are always good".
This commit is contained in:
commit
d3712b9dfc
@ -4140,6 +4140,7 @@ F: fs/partitions/ldm.*
|
||||
|
||||
LogFS
|
||||
M: Joern Engel <joern@logfs.org>
|
||||
M: Prasad Joshi <prasadjoshi.linux@gmail.com>
|
||||
L: logfs@logfs.org
|
||||
W: logfs.org
|
||||
S: Maintained
|
||||
|
@ -71,7 +71,7 @@ static int write_dir(struct inode *dir, struct logfs_disk_dentry *dd,
|
||||
|
||||
static int write_inode(struct inode *inode)
|
||||
{
|
||||
return __logfs_write_inode(inode, WF_LOCK);
|
||||
return __logfs_write_inode(inode, NULL, WF_LOCK);
|
||||
}
|
||||
|
||||
static s64 dir_seek_data(struct inode *inode, s64 pos)
|
||||
|
@ -230,7 +230,9 @@ int logfs_fsync(struct file *file, loff_t start, loff_t end, int datasync)
|
||||
return ret;
|
||||
|
||||
mutex_lock(&inode->i_mutex);
|
||||
logfs_get_wblocks(sb, NULL, WF_LOCK);
|
||||
logfs_write_anchor(sb);
|
||||
logfs_put_wblocks(sb, NULL, WF_LOCK);
|
||||
mutex_unlock(&inode->i_mutex);
|
||||
|
||||
return 0;
|
||||
|
@ -367,7 +367,7 @@ static struct gc_candidate *get_candidate(struct super_block *sb)
|
||||
int i, max_dist;
|
||||
struct gc_candidate *cand = NULL, *this;
|
||||
|
||||
max_dist = min(no_free_segments(sb), LOGFS_NO_AREAS);
|
||||
max_dist = min(no_free_segments(sb), LOGFS_NO_AREAS - 1);
|
||||
|
||||
for (i = max_dist; i >= 0; i--) {
|
||||
this = first_in_list(&super->s_low_list[i]);
|
||||
|
@ -286,7 +286,7 @@ static int logfs_write_inode(struct inode *inode, struct writeback_control *wbc)
|
||||
if (logfs_inode(inode)->li_flags & LOGFS_IF_STILLBORN)
|
||||
return 0;
|
||||
|
||||
ret = __logfs_write_inode(inode, flags);
|
||||
ret = __logfs_write_inode(inode, NULL, flags);
|
||||
LOGFS_BUG_ON(ret, inode->i_sb);
|
||||
return ret;
|
||||
}
|
||||
@ -363,7 +363,9 @@ static void logfs_init_once(void *_li)
|
||||
|
||||
static int logfs_sync_fs(struct super_block *sb, int wait)
|
||||
{
|
||||
logfs_get_wblocks(sb, NULL, WF_LOCK);
|
||||
logfs_write_anchor(sb);
|
||||
logfs_put_wblocks(sb, NULL, WF_LOCK);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -612,7 +612,6 @@ static size_t __logfs_write_je(struct super_block *sb, void *buf, u16 type,
|
||||
if (len == 0)
|
||||
return logfs_write_header(super, header, 0, type);
|
||||
|
||||
BUG_ON(len > sb->s_blocksize);
|
||||
compr_len = logfs_compress(buf, data, len, sb->s_blocksize);
|
||||
if (compr_len < 0 || type == JE_ANCHOR) {
|
||||
memcpy(data, buf, len);
|
||||
|
@ -528,7 +528,7 @@ void logfs_destroy_inode_cache(void);
|
||||
void logfs_set_blocks(struct inode *inode, u64 no);
|
||||
/* these logically belong into inode.c but actually reside in readwrite.c */
|
||||
int logfs_read_inode(struct inode *inode);
|
||||
int __logfs_write_inode(struct inode *inode, long flags);
|
||||
int __logfs_write_inode(struct inode *inode, struct page *, long flags);
|
||||
void logfs_evict_inode(struct inode *inode);
|
||||
|
||||
/* journal.c */
|
||||
@ -577,6 +577,8 @@ void initialize_block_counters(struct page *page, struct logfs_block *block,
|
||||
__be64 *array, int page_is_empty);
|
||||
int logfs_exist_block(struct inode *inode, u64 bix);
|
||||
int get_page_reserve(struct inode *inode, struct page *page);
|
||||
void logfs_get_wblocks(struct super_block *sb, struct page *page, int lock);
|
||||
void logfs_put_wblocks(struct super_block *sb, struct page *page, int lock);
|
||||
extern struct logfs_block_ops indirect_block_ops;
|
||||
|
||||
/* segment.c */
|
||||
@ -594,6 +596,7 @@ int logfs_init_mapping(struct super_block *sb);
|
||||
void logfs_sync_area(struct logfs_area *area);
|
||||
void logfs_sync_segments(struct super_block *sb);
|
||||
void freeseg(struct super_block *sb, u32 segno);
|
||||
void free_areas(struct super_block *sb);
|
||||
|
||||
/* area handling */
|
||||
int logfs_init_areas(struct super_block *sb);
|
||||
|
@ -244,8 +244,7 @@ static void preunlock_page(struct super_block *sb, struct page *page, int lock)
|
||||
* is waiting for s_write_mutex. We annotate this fact by setting PG_pre_locked
|
||||
* in addition to PG_locked.
|
||||
*/
|
||||
static void logfs_get_wblocks(struct super_block *sb, struct page *page,
|
||||
int lock)
|
||||
void logfs_get_wblocks(struct super_block *sb, struct page *page, int lock)
|
||||
{
|
||||
struct logfs_super *super = logfs_super(sb);
|
||||
|
||||
@ -260,8 +259,7 @@ static void logfs_get_wblocks(struct super_block *sb, struct page *page,
|
||||
}
|
||||
}
|
||||
|
||||
static void logfs_put_wblocks(struct super_block *sb, struct page *page,
|
||||
int lock)
|
||||
void logfs_put_wblocks(struct super_block *sb, struct page *page, int lock)
|
||||
{
|
||||
struct logfs_super *super = logfs_super(sb);
|
||||
|
||||
@ -424,7 +422,7 @@ static void inode_write_block(struct logfs_block *block)
|
||||
if (inode->i_ino == LOGFS_INO_MASTER)
|
||||
logfs_write_anchor(inode->i_sb);
|
||||
else {
|
||||
ret = __logfs_write_inode(inode, 0);
|
||||
ret = __logfs_write_inode(inode, NULL, 0);
|
||||
/* see indirect_write_block comment */
|
||||
BUG_ON(ret);
|
||||
}
|
||||
@ -560,8 +558,13 @@ static void inode_free_block(struct super_block *sb, struct logfs_block *block)
|
||||
static void indirect_free_block(struct super_block *sb,
|
||||
struct logfs_block *block)
|
||||
{
|
||||
ClearPagePrivate(block->page);
|
||||
block->page->private = 0;
|
||||
struct page *page = block->page;
|
||||
|
||||
if (PagePrivate(page)) {
|
||||
ClearPagePrivate(page);
|
||||
page_cache_release(page);
|
||||
set_page_private(page, 0);
|
||||
}
|
||||
__free_block(sb, block);
|
||||
}
|
||||
|
||||
@ -650,8 +653,11 @@ static void alloc_data_block(struct inode *inode, struct page *page)
|
||||
logfs_unpack_index(page->index, &bix, &level);
|
||||
block = __alloc_block(inode->i_sb, inode->i_ino, bix, level);
|
||||
block->page = page;
|
||||
|
||||
SetPagePrivate(page);
|
||||
page->private = (unsigned long)block;
|
||||
page_cache_get(page);
|
||||
set_page_private(page, (unsigned long) block);
|
||||
|
||||
block->ops = &indirect_block_ops;
|
||||
}
|
||||
|
||||
@ -1570,11 +1576,15 @@ int logfs_write_buf(struct inode *inode, struct page *page, long flags)
|
||||
static int __logfs_delete(struct inode *inode, struct page *page)
|
||||
{
|
||||
long flags = WF_DELETE;
|
||||
int err;
|
||||
|
||||
inode->i_ctime = inode->i_mtime = CURRENT_TIME;
|
||||
|
||||
if (page->index < I0_BLOCKS)
|
||||
return logfs_write_direct(inode, page, flags);
|
||||
err = grow_inode(inode, page->index, 0);
|
||||
if (err)
|
||||
return err;
|
||||
return logfs_write_rec(inode, page, page->index, 0, flags);
|
||||
}
|
||||
|
||||
@ -1623,7 +1633,7 @@ int logfs_rewrite_block(struct inode *inode, u64 bix, u64 ofs,
|
||||
if (inode->i_ino == LOGFS_INO_MASTER)
|
||||
logfs_write_anchor(inode->i_sb);
|
||||
else {
|
||||
err = __logfs_write_inode(inode, flags);
|
||||
err = __logfs_write_inode(inode, page, flags);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1873,7 +1883,7 @@ int logfs_truncate(struct inode *inode, u64 target)
|
||||
logfs_get_wblocks(sb, NULL, 1);
|
||||
err = __logfs_truncate(inode, size);
|
||||
if (!err)
|
||||
err = __logfs_write_inode(inode, 0);
|
||||
err = __logfs_write_inode(inode, NULL, 0);
|
||||
logfs_put_wblocks(sb, NULL, 1);
|
||||
}
|
||||
|
||||
@ -1901,8 +1911,11 @@ static void move_page_to_inode(struct inode *inode, struct page *page)
|
||||
li->li_block = block;
|
||||
|
||||
block->page = NULL;
|
||||
page->private = 0;
|
||||
ClearPagePrivate(page);
|
||||
if (PagePrivate(page)) {
|
||||
ClearPagePrivate(page);
|
||||
page_cache_release(page);
|
||||
set_page_private(page, 0);
|
||||
}
|
||||
}
|
||||
|
||||
static void move_inode_to_page(struct page *page, struct inode *inode)
|
||||
@ -1918,8 +1931,12 @@ static void move_inode_to_page(struct page *page, struct inode *inode)
|
||||
BUG_ON(PagePrivate(page));
|
||||
block->ops = &indirect_block_ops;
|
||||
block->page = page;
|
||||
page->private = (unsigned long)block;
|
||||
SetPagePrivate(page);
|
||||
|
||||
if (!PagePrivate(page)) {
|
||||
SetPagePrivate(page);
|
||||
page_cache_get(page);
|
||||
set_page_private(page, (unsigned long) block);
|
||||
}
|
||||
|
||||
block->inode = NULL;
|
||||
li->li_block = NULL;
|
||||
@ -2106,14 +2123,14 @@ void logfs_set_segment_unreserved(struct super_block *sb, u32 segno, u32 ec)
|
||||
ec_level);
|
||||
}
|
||||
|
||||
int __logfs_write_inode(struct inode *inode, long flags)
|
||||
int __logfs_write_inode(struct inode *inode, struct page *page, long flags)
|
||||
{
|
||||
struct super_block *sb = inode->i_sb;
|
||||
int ret;
|
||||
|
||||
logfs_get_wblocks(sb, NULL, flags & WF_LOCK);
|
||||
logfs_get_wblocks(sb, page, flags & WF_LOCK);
|
||||
ret = do_write_inode(inode);
|
||||
logfs_put_wblocks(sb, NULL, flags & WF_LOCK);
|
||||
logfs_put_wblocks(sb, page, flags & WF_LOCK);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -86,7 +86,11 @@ int __logfs_buf_write(struct logfs_area *area, u64 ofs, void *buf, size_t len,
|
||||
BUG_ON(!page); /* FIXME: reserve a pool */
|
||||
SetPageUptodate(page);
|
||||
memcpy(page_address(page) + offset, buf, copylen);
|
||||
SetPagePrivate(page);
|
||||
|
||||
if (!PagePrivate(page)) {
|
||||
SetPagePrivate(page);
|
||||
page_cache_get(page);
|
||||
}
|
||||
page_cache_release(page);
|
||||
|
||||
buf += copylen;
|
||||
@ -110,7 +114,10 @@ static void pad_partial_page(struct logfs_area *area)
|
||||
page = get_mapping_page(sb, index, 0);
|
||||
BUG_ON(!page); /* FIXME: reserve a pool */
|
||||
memset(page_address(page) + offset, 0xff, len);
|
||||
SetPagePrivate(page);
|
||||
if (!PagePrivate(page)) {
|
||||
SetPagePrivate(page);
|
||||
page_cache_get(page);
|
||||
}
|
||||
page_cache_release(page);
|
||||
}
|
||||
}
|
||||
@ -130,7 +137,10 @@ static void pad_full_pages(struct logfs_area *area)
|
||||
BUG_ON(!page); /* FIXME: reserve a pool */
|
||||
SetPageUptodate(page);
|
||||
memset(page_address(page), 0xff, PAGE_CACHE_SIZE);
|
||||
SetPagePrivate(page);
|
||||
if (!PagePrivate(page)) {
|
||||
SetPagePrivate(page);
|
||||
page_cache_get(page);
|
||||
}
|
||||
page_cache_release(page);
|
||||
index++;
|
||||
no_indizes--;
|
||||
@ -485,8 +495,12 @@ static void move_btree_to_page(struct inode *inode, struct page *page,
|
||||
mempool_free(item, super->s_alias_pool);
|
||||
}
|
||||
block->page = page;
|
||||
SetPagePrivate(page);
|
||||
page->private = (unsigned long)block;
|
||||
|
||||
if (!PagePrivate(page)) {
|
||||
SetPagePrivate(page);
|
||||
page_cache_get(page);
|
||||
set_page_private(page, (unsigned long) block);
|
||||
}
|
||||
block->ops = &indirect_block_ops;
|
||||
initialize_block_counters(page, block, data, 0);
|
||||
}
|
||||
@ -536,8 +550,12 @@ void move_page_to_btree(struct page *page)
|
||||
list_add(&item->list, &block->item_list);
|
||||
}
|
||||
block->page = NULL;
|
||||
ClearPagePrivate(page);
|
||||
page->private = 0;
|
||||
|
||||
if (PagePrivate(page)) {
|
||||
ClearPagePrivate(page);
|
||||
page_cache_release(page);
|
||||
set_page_private(page, 0);
|
||||
}
|
||||
block->ops = &btree_block_ops;
|
||||
err = alias_tree_insert(block->sb, block->ino, block->bix, block->level,
|
||||
block);
|
||||
@ -702,7 +720,10 @@ void freeseg(struct super_block *sb, u32 segno)
|
||||
page = find_get_page(mapping, ofs >> PAGE_SHIFT);
|
||||
if (!page)
|
||||
continue;
|
||||
ClearPagePrivate(page);
|
||||
if (PagePrivate(page)) {
|
||||
ClearPagePrivate(page);
|
||||
page_cache_release(page);
|
||||
}
|
||||
page_cache_release(page);
|
||||
}
|
||||
}
|
||||
@ -841,6 +862,16 @@ static void free_area(struct logfs_area *area)
|
||||
kfree(area);
|
||||
}
|
||||
|
||||
void free_areas(struct super_block *sb)
|
||||
{
|
||||
struct logfs_super *super = logfs_super(sb);
|
||||
int i;
|
||||
|
||||
for_each_area(i)
|
||||
free_area(super->s_area[i]);
|
||||
free_area(super->s_journal_area);
|
||||
}
|
||||
|
||||
static struct logfs_area *alloc_area(struct super_block *sb)
|
||||
{
|
||||
struct logfs_area *area;
|
||||
@ -923,10 +954,6 @@ err:
|
||||
void logfs_cleanup_areas(struct super_block *sb)
|
||||
{
|
||||
struct logfs_super *super = logfs_super(sb);
|
||||
int i;
|
||||
|
||||
btree_grim_visitor128(&super->s_object_alias_tree, 0, kill_alias);
|
||||
for_each_area(i)
|
||||
free_area(super->s_area[i]);
|
||||
free_area(super->s_journal_area);
|
||||
}
|
||||
|
@ -486,14 +486,15 @@ static void logfs_kill_sb(struct super_block *sb)
|
||||
/* Alias entries slow down mount, so evict as many as possible */
|
||||
sync_filesystem(sb);
|
||||
logfs_write_anchor(sb);
|
||||
free_areas(sb);
|
||||
|
||||
/*
|
||||
* From this point on alias entries are simply dropped - and any
|
||||
* writes to the object store are considered bugs.
|
||||
*/
|
||||
super->s_flags |= LOGFS_SB_FLAG_SHUTDOWN;
|
||||
log_super("LogFS: Now in shutdown\n");
|
||||
generic_shutdown_super(sb);
|
||||
super->s_flags |= LOGFS_SB_FLAG_SHUTDOWN;
|
||||
|
||||
BUG_ON(super->s_dirty_used_bytes || super->s_dirty_free_bytes);
|
||||
|
||||
|
@ -441,7 +441,7 @@ static inline void mtd_resume(struct mtd_info *mtd)
|
||||
static inline int mtd_block_isbad(struct mtd_info *mtd, loff_t ofs)
|
||||
{
|
||||
if (!mtd->block_isbad)
|
||||
return -EOPNOTSUPP;
|
||||
return 0;
|
||||
return mtd->block_isbad(mtd, ofs);
|
||||
}
|
||||
|
||||
@ -489,7 +489,7 @@ static inline int mtd_has_oob(const struct mtd_info *mtd)
|
||||
|
||||
static inline int mtd_can_have_bb(const struct mtd_info *mtd)
|
||||
{
|
||||
return !!mtd->block_isbad;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Kernel-side ioctl definitions */
|
||||
|
Loading…
Reference in New Issue
Block a user