Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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 f2933e86ad93: "Logfs: Allow NULL
block_isbad() methods" clashing with the abstraction changes in the
commits 7086c19d0742: "mtd: introduce mtd_block_isbad interface" and
d58b27ed58a3: "logfs: do not use 'mtd->block_isbad' directly".

This resolution takes the semantics from commit f2933e86ad93, 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".

+89 -37
+1
MAINTAINERS
··· 4140 4140 4141 4141 LogFS 4142 4142 M: Joern Engel <joern@logfs.org> 4143 + M: Prasad Joshi <prasadjoshi.linux@gmail.com> 4143 4144 L: logfs@logfs.org 4144 4145 W: logfs.org 4145 4146 S: Maintained
+1 -1
fs/logfs/dir.c
··· 71 71 72 72 static int write_inode(struct inode *inode) 73 73 { 74 - return __logfs_write_inode(inode, WF_LOCK); 74 + return __logfs_write_inode(inode, NULL, WF_LOCK); 75 75 } 76 76 77 77 static s64 dir_seek_data(struct inode *inode, s64 pos)
+2
fs/logfs/file.c
··· 230 230 return ret; 231 231 232 232 mutex_lock(&inode->i_mutex); 233 + logfs_get_wblocks(sb, NULL, WF_LOCK); 233 234 logfs_write_anchor(sb); 235 + logfs_put_wblocks(sb, NULL, WF_LOCK); 234 236 mutex_unlock(&inode->i_mutex); 235 237 236 238 return 0;
+1 -1
fs/logfs/gc.c
··· 367 367 int i, max_dist; 368 368 struct gc_candidate *cand = NULL, *this; 369 369 370 - max_dist = min(no_free_segments(sb), LOGFS_NO_AREAS); 370 + max_dist = min(no_free_segments(sb), LOGFS_NO_AREAS - 1); 371 371 372 372 for (i = max_dist; i >= 0; i--) { 373 373 this = first_in_list(&super->s_low_list[i]);
+3 -1
fs/logfs/inode.c
··· 286 286 if (logfs_inode(inode)->li_flags & LOGFS_IF_STILLBORN) 287 287 return 0; 288 288 289 - ret = __logfs_write_inode(inode, flags); 289 + ret = __logfs_write_inode(inode, NULL, flags); 290 290 LOGFS_BUG_ON(ret, inode->i_sb); 291 291 return ret; 292 292 } ··· 363 363 364 364 static int logfs_sync_fs(struct super_block *sb, int wait) 365 365 { 366 + logfs_get_wblocks(sb, NULL, WF_LOCK); 366 367 logfs_write_anchor(sb); 368 + logfs_put_wblocks(sb, NULL, WF_LOCK); 367 369 return 0; 368 370 } 369 371
-1
fs/logfs/journal.c
··· 612 612 if (len == 0) 613 613 return logfs_write_header(super, header, 0, type); 614 614 615 - BUG_ON(len > sb->s_blocksize); 616 615 compr_len = logfs_compress(buf, data, len, sb->s_blocksize); 617 616 if (compr_len < 0 || type == JE_ANCHOR) { 618 617 memcpy(data, buf, len);
+4 -1
fs/logfs/logfs.h
··· 528 528 void logfs_set_blocks(struct inode *inode, u64 no); 529 529 /* these logically belong into inode.c but actually reside in readwrite.c */ 530 530 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); 532 532 void logfs_evict_inode(struct inode *inode); 533 533 534 534 /* journal.c */ ··· 577 577 __be64 *array, int page_is_empty); 578 578 int logfs_exist_block(struct inode *inode, u64 bix); 579 579 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); 580 582 extern struct logfs_block_ops indirect_block_ops; 581 583 582 584 /* segment.c */ ··· 596 594 void logfs_sync_area(struct logfs_area *area); 597 595 void logfs_sync_segments(struct super_block *sb); 598 596 void freeseg(struct super_block *sb, u32 segno); 597 + void free_areas(struct super_block *sb); 599 598 600 599 /* area handling */ 601 600 int logfs_init_areas(struct super_block *sb);
+34 -17
fs/logfs/readwrite.c
··· 244 244 * is waiting for s_write_mutex. We annotate this fact by setting PG_pre_locked 245 245 * in addition to PG_locked. 246 246 */ 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) 249 248 { 250 249 struct logfs_super *super = logfs_super(sb); 251 250 ··· 259 260 } 260 261 } 261 262 262 - static void logfs_put_wblocks(struct super_block *sb, struct page *page, 263 - int lock) 263 + void logfs_put_wblocks(struct super_block *sb, struct page *page, int lock) 264 264 { 265 265 struct logfs_super *super = logfs_super(sb); 266 266 ··· 422 424 if (inode->i_ino == LOGFS_INO_MASTER) 423 425 logfs_write_anchor(inode->i_sb); 424 426 else { 425 - ret = __logfs_write_inode(inode, 0); 427 + ret = __logfs_write_inode(inode, NULL, 0); 426 428 /* see indirect_write_block comment */ 427 429 BUG_ON(ret); 428 430 } ··· 558 560 static void indirect_free_block(struct super_block *sb, 559 561 struct logfs_block *block) 560 562 { 561 - ClearPagePrivate(block->page); 562 - block->page->private = 0; 563 + struct page *page = block->page; 564 + 565 + if (PagePrivate(page)) { 566 + ClearPagePrivate(page); 567 + page_cache_release(page); 568 + set_page_private(page, 0); 569 + } 563 570 __free_block(sb, block); 564 571 } 565 572 ··· 653 650 logfs_unpack_index(page->index, &bix, &level); 654 651 block = __alloc_block(inode->i_sb, inode->i_ino, bix, level); 655 652 block->page = page; 653 + 656 654 SetPagePrivate(page); 657 - page->private = (unsigned long)block; 655 + page_cache_get(page); 656 + set_page_private(page, (unsigned long) block); 657 + 658 658 block->ops = &indirect_block_ops; 659 659 } 660 660 ··· 1576 1570 static int __logfs_delete(struct inode *inode, struct page *page) 1577 1571 { 1578 1572 long flags = WF_DELETE; 1573 + int err; 1579 1574 1580 1575 inode->i_ctime = inode->i_mtime = CURRENT_TIME; 1581 1576 1582 1577 if (page->index < I0_BLOCKS) 1583 1578 return logfs_write_direct(inode, page, flags); 1579 + err = grow_inode(inode, page->index, 0); 1580 + if (err) 1581 + return err; 1584 1582 return logfs_write_rec(inode, page, page->index, 0, flags); 1585 1583 } 1586 1584 ··· 1633 1623 if (inode->i_ino == LOGFS_INO_MASTER) 1634 1624 logfs_write_anchor(inode->i_sb); 1635 1625 else { 1636 - err = __logfs_write_inode(inode, flags); 1626 + err = __logfs_write_inode(inode, page, flags); 1637 1627 } 1638 1628 } 1639 1629 } ··· 1883 1873 logfs_get_wblocks(sb, NULL, 1); 1884 1874 err = __logfs_truncate(inode, size); 1885 1875 if (!err) 1886 - err = __logfs_write_inode(inode, 0); 1876 + err = __logfs_write_inode(inode, NULL, 0); 1887 1877 logfs_put_wblocks(sb, NULL, 1); 1888 1878 } 1889 1879 ··· 1911 1901 li->li_block = block; 1912 1902 1913 1903 block->page = NULL; 1914 - page->private = 0; 1915 - ClearPagePrivate(page); 1904 + if (PagePrivate(page)) { 1905 + ClearPagePrivate(page); 1906 + page_cache_release(page); 1907 + set_page_private(page, 0); 1908 + } 1916 1909 } 1917 1910 1918 1911 static void move_inode_to_page(struct page *page, struct inode *inode) ··· 1931 1918 BUG_ON(PagePrivate(page)); 1932 1919 block->ops = &indirect_block_ops; 1933 1920 block->page = page; 1934 - page->private = (unsigned long)block; 1935 - SetPagePrivate(page); 1921 + 1922 + if (!PagePrivate(page)) { 1923 + SetPagePrivate(page); 1924 + page_cache_get(page); 1925 + set_page_private(page, (unsigned long) block); 1926 + } 1936 1927 1937 1928 block->inode = NULL; 1938 1929 li->li_block = NULL; ··· 2123 2106 ec_level); 2124 2107 } 2125 2108 2126 - int __logfs_write_inode(struct inode *inode, long flags) 2109 + int __logfs_write_inode(struct inode *inode, struct page *page, long flags) 2127 2110 { 2128 2111 struct super_block *sb = inode->i_sb; 2129 2112 int ret; 2130 2113 2131 - logfs_get_wblocks(sb, NULL, flags & WF_LOCK); 2114 + logfs_get_wblocks(sb, page, flags & WF_LOCK); 2132 2115 ret = do_write_inode(inode); 2133 - logfs_put_wblocks(sb, NULL, flags & WF_LOCK); 2116 + logfs_put_wblocks(sb, page, flags & WF_LOCK); 2134 2117 return ret; 2135 2118 } 2136 2119
+39 -12
fs/logfs/segment.c
··· 86 86 BUG_ON(!page); /* FIXME: reserve a pool */ 87 87 SetPageUptodate(page); 88 88 memcpy(page_address(page) + offset, buf, copylen); 89 - SetPagePrivate(page); 89 + 90 + if (!PagePrivate(page)) { 91 + SetPagePrivate(page); 92 + page_cache_get(page); 93 + } 90 94 page_cache_release(page); 91 95 92 96 buf += copylen; ··· 114 110 page = get_mapping_page(sb, index, 0); 115 111 BUG_ON(!page); /* FIXME: reserve a pool */ 116 112 memset(page_address(page) + offset, 0xff, len); 117 - SetPagePrivate(page); 113 + if (!PagePrivate(page)) { 114 + SetPagePrivate(page); 115 + page_cache_get(page); 116 + } 118 117 page_cache_release(page); 119 118 } 120 119 } ··· 137 130 BUG_ON(!page); /* FIXME: reserve a pool */ 138 131 SetPageUptodate(page); 139 132 memset(page_address(page), 0xff, PAGE_CACHE_SIZE); 140 - SetPagePrivate(page); 133 + if (!PagePrivate(page)) { 134 + SetPagePrivate(page); 135 + page_cache_get(page); 136 + } 141 137 page_cache_release(page); 142 138 index++; 143 139 no_indizes--; ··· 495 485 mempool_free(item, super->s_alias_pool); 496 486 } 497 487 block->page = page; 498 - SetPagePrivate(page); 499 - page->private = (unsigned long)block; 488 + 489 + if (!PagePrivate(page)) { 490 + SetPagePrivate(page); 491 + page_cache_get(page); 492 + set_page_private(page, (unsigned long) block); 493 + } 500 494 block->ops = &indirect_block_ops; 501 495 initialize_block_counters(page, block, data, 0); 502 496 } ··· 550 536 list_add(&item->list, &block->item_list); 551 537 } 552 538 block->page = NULL; 553 - ClearPagePrivate(page); 554 - page->private = 0; 539 + 540 + if (PagePrivate(page)) { 541 + ClearPagePrivate(page); 542 + page_cache_release(page); 543 + set_page_private(page, 0); 544 + } 555 545 block->ops = &btree_block_ops; 556 546 err = alias_tree_insert(block->sb, block->ino, block->bix, block->level, 557 547 block); ··· 720 702 page = find_get_page(mapping, ofs >> PAGE_SHIFT); 721 703 if (!page) 722 704 continue; 723 - ClearPagePrivate(page); 705 + if (PagePrivate(page)) { 706 + ClearPagePrivate(page); 707 + page_cache_release(page); 708 + } 724 709 page_cache_release(page); 725 710 } 726 711 } ··· 862 841 kfree(area); 863 842 } 864 843 844 + void free_areas(struct super_block *sb) 845 + { 846 + struct logfs_super *super = logfs_super(sb); 847 + int i; 848 + 849 + for_each_area(i) 850 + free_area(super->s_area[i]); 851 + free_area(super->s_journal_area); 852 + } 853 + 865 854 static struct logfs_area *alloc_area(struct super_block *sb) 866 855 { 867 856 struct logfs_area *area; ··· 954 923 void logfs_cleanup_areas(struct super_block *sb) 955 924 { 956 925 struct logfs_super *super = logfs_super(sb); 957 - int i; 958 926 959 927 btree_grim_visitor128(&super->s_object_alias_tree, 0, kill_alias); 960 - for_each_area(i) 961 - free_area(super->s_area[i]); 962 - free_area(super->s_journal_area); 963 928 }
+2 -1
fs/logfs/super.c
··· 486 486 /* Alias entries slow down mount, so evict as many as possible */ 487 487 sync_filesystem(sb); 488 488 logfs_write_anchor(sb); 489 + free_areas(sb); 489 490 490 491 /* 491 492 * From this point on alias entries are simply dropped - and any 492 493 * writes to the object store are considered bugs. 493 494 */ 494 - super->s_flags |= LOGFS_SB_FLAG_SHUTDOWN; 495 495 log_super("LogFS: Now in shutdown\n"); 496 496 generic_shutdown_super(sb); 497 + super->s_flags |= LOGFS_SB_FLAG_SHUTDOWN; 497 498 498 499 BUG_ON(super->s_dirty_used_bytes || super->s_dirty_free_bytes); 499 500
+2 -2
include/linux/mtd/mtd.h
··· 441 441 static inline int mtd_block_isbad(struct mtd_info *mtd, loff_t ofs) 442 442 { 443 443 if (!mtd->block_isbad) 444 - return -EOPNOTSUPP; 444 + return 0; 445 445 return mtd->block_isbad(mtd, ofs); 446 446 } 447 447 ··· 489 489 490 490 static inline int mtd_can_have_bb(const struct mtd_info *mtd) 491 491 { 492 - return !!mtd->block_isbad; 492 + return 0; 493 493 } 494 494 495 495 /* Kernel-side ioctl definitions */