Skip to content

Commit d3712b9

Browse files
committed
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 commit f2933e8: "Logfs: Allow NULL block_isbad() methods" clashing with the abstraction changes in the commits 7086c19: "mtd: introduce mtd_block_isbad interface" and d58b27e: "logfs: do not use 'mtd->block_isbad' directly". This resolution takes the semantics from commit f2933e8, 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".
2 parents c5d2bc1 + f2933e8 commit d3712b9

File tree

11 files changed

+89
-37
lines changed

11 files changed

+89
-37
lines changed

MAINTAINERS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4140,6 +4140,7 @@ F: fs/partitions/ldm.*
41404140

41414141
LogFS
41424142
M: Joern Engel <[email protected]>
4143+
M: Prasad Joshi <[email protected]>
41434144
41444145
W: logfs.org
41454146
S: Maintained

fs/logfs/dir.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ static int write_dir(struct inode *dir, struct logfs_disk_dentry *dd,
7171

7272
static int write_inode(struct inode *inode)
7373
{
74-
return __logfs_write_inode(inode, WF_LOCK);
74+
return __logfs_write_inode(inode, NULL, WF_LOCK);
7575
}
7676

7777
static s64 dir_seek_data(struct inode *inode, s64 pos)

fs/logfs/file.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -230,7 +230,9 @@ int logfs_fsync(struct file *file, loff_t start, loff_t end, int datasync)
230230
return ret;
231231

232232
mutex_lock(&inode->i_mutex);
233+
logfs_get_wblocks(sb, NULL, WF_LOCK);
233234
logfs_write_anchor(sb);
235+
logfs_put_wblocks(sb, NULL, WF_LOCK);
234236
mutex_unlock(&inode->i_mutex);
235237

236238
return 0;

fs/logfs/gc.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -367,7 +367,7 @@ static struct gc_candidate *get_candidate(struct super_block *sb)
367367
int i, max_dist;
368368
struct gc_candidate *cand = NULL, *this;
369369

370-
max_dist = min(no_free_segments(sb), LOGFS_NO_AREAS);
370+
max_dist = min(no_free_segments(sb), LOGFS_NO_AREAS - 1);
371371

372372
for (i = max_dist; i >= 0; i--) {
373373
this = first_in_list(&super->s_low_list[i]);

fs/logfs/inode.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -286,7 +286,7 @@ static int logfs_write_inode(struct inode *inode, struct writeback_control *wbc)
286286
if (logfs_inode(inode)->li_flags & LOGFS_IF_STILLBORN)
287287
return 0;
288288

289-
ret = __logfs_write_inode(inode, flags);
289+
ret = __logfs_write_inode(inode, NULL, flags);
290290
LOGFS_BUG_ON(ret, inode->i_sb);
291291
return ret;
292292
}
@@ -363,7 +363,9 @@ static void logfs_init_once(void *_li)
363363

364364
static int logfs_sync_fs(struct super_block *sb, int wait)
365365
{
366+
logfs_get_wblocks(sb, NULL, WF_LOCK);
366367
logfs_write_anchor(sb);
368+
logfs_put_wblocks(sb, NULL, WF_LOCK);
367369
return 0;
368370
}
369371

fs/logfs/journal.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -612,7 +612,6 @@ static size_t __logfs_write_je(struct super_block *sb, void *buf, u16 type,
612612
if (len == 0)
613613
return logfs_write_header(super, header, 0, type);
614614

615-
BUG_ON(len > sb->s_blocksize);
616615
compr_len = logfs_compress(buf, data, len, sb->s_blocksize);
617616
if (compr_len < 0 || type == JE_ANCHOR) {
618617
memcpy(data, buf, len);

fs/logfs/logfs.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -528,7 +528,7 @@ void logfs_destroy_inode_cache(void);
528528
void logfs_set_blocks(struct inode *inode, u64 no);
529529
/* these logically belong into inode.c but actually reside in readwrite.c */
530530
int logfs_read_inode(struct inode *inode);
531-
int __logfs_write_inode(struct inode *inode, long flags);
531+
int __logfs_write_inode(struct inode *inode, struct page *, long flags);
532532
void logfs_evict_inode(struct inode *inode);
533533

534534
/* journal.c */
@@ -577,6 +577,8 @@ void initialize_block_counters(struct page *page, struct logfs_block *block,
577577
__be64 *array, int page_is_empty);
578578
int logfs_exist_block(struct inode *inode, u64 bix);
579579
int get_page_reserve(struct inode *inode, struct page *page);
580+
void logfs_get_wblocks(struct super_block *sb, struct page *page, int lock);
581+
void logfs_put_wblocks(struct super_block *sb, struct page *page, int lock);
580582
extern struct logfs_block_ops indirect_block_ops;
581583

582584
/* segment.c */
@@ -594,6 +596,7 @@ int logfs_init_mapping(struct super_block *sb);
594596
void logfs_sync_area(struct logfs_area *area);
595597
void logfs_sync_segments(struct super_block *sb);
596598
void freeseg(struct super_block *sb, u32 segno);
599+
void free_areas(struct super_block *sb);
597600

598601
/* area handling */
599602
int logfs_init_areas(struct super_block *sb);

fs/logfs/readwrite.c

Lines changed: 34 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -244,8 +244,7 @@ static void preunlock_page(struct super_block *sb, struct page *page, int lock)
244244
* is waiting for s_write_mutex. We annotate this fact by setting PG_pre_locked
245245
* in addition to PG_locked.
246246
*/
247-
static void logfs_get_wblocks(struct super_block *sb, struct page *page,
248-
int lock)
247+
void logfs_get_wblocks(struct super_block *sb, struct page *page, int lock)
249248
{
250249
struct logfs_super *super = logfs_super(sb);
251250

@@ -260,8 +259,7 @@ static void logfs_get_wblocks(struct super_block *sb, struct page *page,
260259
}
261260
}
262261

263-
static void logfs_put_wblocks(struct super_block *sb, struct page *page,
264-
int lock)
262+
void logfs_put_wblocks(struct super_block *sb, struct page *page, int lock)
265263
{
266264
struct logfs_super *super = logfs_super(sb);
267265

@@ -424,7 +422,7 @@ static void inode_write_block(struct logfs_block *block)
424422
if (inode->i_ino == LOGFS_INO_MASTER)
425423
logfs_write_anchor(inode->i_sb);
426424
else {
427-
ret = __logfs_write_inode(inode, 0);
425+
ret = __logfs_write_inode(inode, NULL, 0);
428426
/* see indirect_write_block comment */
429427
BUG_ON(ret);
430428
}
@@ -560,8 +558,13 @@ static void inode_free_block(struct super_block *sb, struct logfs_block *block)
560558
static void indirect_free_block(struct super_block *sb,
561559
struct logfs_block *block)
562560
{
563-
ClearPagePrivate(block->page);
564-
block->page->private = 0;
561+
struct page *page = block->page;
562+
563+
if (PagePrivate(page)) {
564+
ClearPagePrivate(page);
565+
page_cache_release(page);
566+
set_page_private(page, 0);
567+
}
565568
__free_block(sb, block);
566569
}
567570

@@ -650,8 +653,11 @@ static void alloc_data_block(struct inode *inode, struct page *page)
650653
logfs_unpack_index(page->index, &bix, &level);
651654
block = __alloc_block(inode->i_sb, inode->i_ino, bix, level);
652655
block->page = page;
656+
653657
SetPagePrivate(page);
654-
page->private = (unsigned long)block;
658+
page_cache_get(page);
659+
set_page_private(page, (unsigned long) block);
660+
655661
block->ops = &indirect_block_ops;
656662
}
657663

@@ -1570,11 +1576,15 @@ int logfs_write_buf(struct inode *inode, struct page *page, long flags)
15701576
static int __logfs_delete(struct inode *inode, struct page *page)
15711577
{
15721578
long flags = WF_DELETE;
1579+
int err;
15731580

15741581
inode->i_ctime = inode->i_mtime = CURRENT_TIME;
15751582

15761583
if (page->index < I0_BLOCKS)
15771584
return logfs_write_direct(inode, page, flags);
1585+
err = grow_inode(inode, page->index, 0);
1586+
if (err)
1587+
return err;
15781588
return logfs_write_rec(inode, page, page->index, 0, flags);
15791589
}
15801590

@@ -1623,7 +1633,7 @@ int logfs_rewrite_block(struct inode *inode, u64 bix, u64 ofs,
16231633
if (inode->i_ino == LOGFS_INO_MASTER)
16241634
logfs_write_anchor(inode->i_sb);
16251635
else {
1626-
err = __logfs_write_inode(inode, flags);
1636+
err = __logfs_write_inode(inode, page, flags);
16271637
}
16281638
}
16291639
}
@@ -1873,7 +1883,7 @@ int logfs_truncate(struct inode *inode, u64 target)
18731883
logfs_get_wblocks(sb, NULL, 1);
18741884
err = __logfs_truncate(inode, size);
18751885
if (!err)
1876-
err = __logfs_write_inode(inode, 0);
1886+
err = __logfs_write_inode(inode, NULL, 0);
18771887
logfs_put_wblocks(sb, NULL, 1);
18781888
}
18791889

@@ -1901,8 +1911,11 @@ static void move_page_to_inode(struct inode *inode, struct page *page)
19011911
li->li_block = block;
19021912

19031913
block->page = NULL;
1904-
page->private = 0;
1905-
ClearPagePrivate(page);
1914+
if (PagePrivate(page)) {
1915+
ClearPagePrivate(page);
1916+
page_cache_release(page);
1917+
set_page_private(page, 0);
1918+
}
19061919
}
19071920

19081921
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)
19181931
BUG_ON(PagePrivate(page));
19191932
block->ops = &indirect_block_ops;
19201933
block->page = page;
1921-
page->private = (unsigned long)block;
1922-
SetPagePrivate(page);
1934+
1935+
if (!PagePrivate(page)) {
1936+
SetPagePrivate(page);
1937+
page_cache_get(page);
1938+
set_page_private(page, (unsigned long) block);
1939+
}
19231940

19241941
block->inode = NULL;
19251942
li->li_block = NULL;
@@ -2106,14 +2123,14 @@ void logfs_set_segment_unreserved(struct super_block *sb, u32 segno, u32 ec)
21062123
ec_level);
21072124
}
21082125

2109-
int __logfs_write_inode(struct inode *inode, long flags)
2126+
int __logfs_write_inode(struct inode *inode, struct page *page, long flags)
21102127
{
21112128
struct super_block *sb = inode->i_sb;
21122129
int ret;
21132130

2114-
logfs_get_wblocks(sb, NULL, flags & WF_LOCK);
2131+
logfs_get_wblocks(sb, page, flags & WF_LOCK);
21152132
ret = do_write_inode(inode);
2116-
logfs_put_wblocks(sb, NULL, flags & WF_LOCK);
2133+
logfs_put_wblocks(sb, page, flags & WF_LOCK);
21172134
return ret;
21182135
}
21192136

fs/logfs/segment.c

Lines changed: 39 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,11 @@ int __logfs_buf_write(struct logfs_area *area, u64 ofs, void *buf, size_t len,
8686
BUG_ON(!page); /* FIXME: reserve a pool */
8787
SetPageUptodate(page);
8888
memcpy(page_address(page) + offset, buf, copylen);
89-
SetPagePrivate(page);
89+
90+
if (!PagePrivate(page)) {
91+
SetPagePrivate(page);
92+
page_cache_get(page);
93+
}
9094
page_cache_release(page);
9195

9296
buf += copylen;
@@ -110,7 +114,10 @@ static void pad_partial_page(struct logfs_area *area)
110114
page = get_mapping_page(sb, index, 0);
111115
BUG_ON(!page); /* FIXME: reserve a pool */
112116
memset(page_address(page) + offset, 0xff, len);
113-
SetPagePrivate(page);
117+
if (!PagePrivate(page)) {
118+
SetPagePrivate(page);
119+
page_cache_get(page);
120+
}
114121
page_cache_release(page);
115122
}
116123
}
@@ -130,7 +137,10 @@ static void pad_full_pages(struct logfs_area *area)
130137
BUG_ON(!page); /* FIXME: reserve a pool */
131138
SetPageUptodate(page);
132139
memset(page_address(page), 0xff, PAGE_CACHE_SIZE);
133-
SetPagePrivate(page);
140+
if (!PagePrivate(page)) {
141+
SetPagePrivate(page);
142+
page_cache_get(page);
143+
}
134144
page_cache_release(page);
135145
index++;
136146
no_indizes--;
@@ -485,8 +495,12 @@ static void move_btree_to_page(struct inode *inode, struct page *page,
485495
mempool_free(item, super->s_alias_pool);
486496
}
487497
block->page = page;
488-
SetPagePrivate(page);
489-
page->private = (unsigned long)block;
498+
499+
if (!PagePrivate(page)) {
500+
SetPagePrivate(page);
501+
page_cache_get(page);
502+
set_page_private(page, (unsigned long) block);
503+
}
490504
block->ops = &indirect_block_ops;
491505
initialize_block_counters(page, block, data, 0);
492506
}
@@ -536,8 +550,12 @@ void move_page_to_btree(struct page *page)
536550
list_add(&item->list, &block->item_list);
537551
}
538552
block->page = NULL;
539-
ClearPagePrivate(page);
540-
page->private = 0;
553+
554+
if (PagePrivate(page)) {
555+
ClearPagePrivate(page);
556+
page_cache_release(page);
557+
set_page_private(page, 0);
558+
}
541559
block->ops = &btree_block_ops;
542560
err = alias_tree_insert(block->sb, block->ino, block->bix, block->level,
543561
block);
@@ -702,7 +720,10 @@ void freeseg(struct super_block *sb, u32 segno)
702720
page = find_get_page(mapping, ofs >> PAGE_SHIFT);
703721
if (!page)
704722
continue;
705-
ClearPagePrivate(page);
723+
if (PagePrivate(page)) {
724+
ClearPagePrivate(page);
725+
page_cache_release(page);
726+
}
706727
page_cache_release(page);
707728
}
708729
}
@@ -841,6 +862,16 @@ static void free_area(struct logfs_area *area)
841862
kfree(area);
842863
}
843864

865+
void free_areas(struct super_block *sb)
866+
{
867+
struct logfs_super *super = logfs_super(sb);
868+
int i;
869+
870+
for_each_area(i)
871+
free_area(super->s_area[i]);
872+
free_area(super->s_journal_area);
873+
}
874+
844875
static struct logfs_area *alloc_area(struct super_block *sb)
845876
{
846877
struct logfs_area *area;
@@ -923,10 +954,6 @@ int logfs_init_areas(struct super_block *sb)
923954
void logfs_cleanup_areas(struct super_block *sb)
924955
{
925956
struct logfs_super *super = logfs_super(sb);
926-
int i;
927957

928958
btree_grim_visitor128(&super->s_object_alias_tree, 0, kill_alias);
929-
for_each_area(i)
930-
free_area(super->s_area[i]);
931-
free_area(super->s_journal_area);
932959
}

fs/logfs/super.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -486,14 +486,15 @@ static void logfs_kill_sb(struct super_block *sb)
486486
/* Alias entries slow down mount, so evict as many as possible */
487487
sync_filesystem(sb);
488488
logfs_write_anchor(sb);
489+
free_areas(sb);
489490

490491
/*
491492
* From this point on alias entries are simply dropped - and any
492493
* writes to the object store are considered bugs.
493494
*/
494-
super->s_flags |= LOGFS_SB_FLAG_SHUTDOWN;
495495
log_super("LogFS: Now in shutdown\n");
496496
generic_shutdown_super(sb);
497+
super->s_flags |= LOGFS_SB_FLAG_SHUTDOWN;
497498

498499
BUG_ON(super->s_dirty_used_bytes || super->s_dirty_free_bytes);
499500

include/linux/mtd/mtd.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -441,7 +441,7 @@ static inline void mtd_resume(struct mtd_info *mtd)
441441
static inline int mtd_block_isbad(struct mtd_info *mtd, loff_t ofs)
442442
{
443443
if (!mtd->block_isbad)
444-
return -EOPNOTSUPP;
444+
return 0;
445445
return mtd->block_isbad(mtd, ofs);
446446
}
447447

@@ -489,7 +489,7 @@ static inline int mtd_has_oob(const struct mtd_info *mtd)
489489

490490
static inline int mtd_can_have_bb(const struct mtd_info *mtd)
491491
{
492-
return !!mtd->block_isbad;
492+
return 0;
493493
}
494494

495495
/* Kernel-side ioctl definitions */

0 commit comments

Comments
 (0)