Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4660d3d2 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
* git://git.kernel.org/pub/scm/linux/kernel/git/joern/logfs:
  [LogFS] Erase new journal segments
  [LogFS] Move reserved segments with journal
  [LogFS] Clear PagePrivate when moving journal
  Simplify and fix pad_wbuf
  Prevent data corruption in logfs_rewrite_block()
  Use deactivate_locked_super
  Fix logfs_get_sb_final error path
  Write out both superblocks on mismatch
  Prevent schedule while atomic in __logfs_readdir
  Plug memory leak in writeseg_end_io
  Limit max_pages for insane devices
  Open segment file before using it
parents be3fd3cc 6be7fa06
Loading
Loading
Loading
Loading
+7 −2
Original line number Diff line number Diff line
@@ -80,6 +80,7 @@ static void writeseg_end_io(struct bio *bio, int err)
			prefetchw(&bvec->bv_page->flags);

		end_page_writeback(page);
		page_cache_release(page);
	} while (bvec >= bio->bi_io_vec);
	bio_put(bio);
	if (atomic_dec_and_test(&super->s_pending_writes))
@@ -97,8 +98,10 @@ static int __bdev_writeseg(struct super_block *sb, u64 ofs, pgoff_t index,
	unsigned int max_pages = queue_max_hw_sectors(q) >> (PAGE_SHIFT - 9);
	int i;

	if (max_pages > BIO_MAX_PAGES)
		max_pages = BIO_MAX_PAGES;
	bio = bio_alloc(GFP_NOFS, max_pages);
	BUG_ON(!bio); /* FIXME: handle this */
	BUG_ON(!bio);

	for (i = 0; i < nr_pages; i++) {
		if (i >= max_pages) {
@@ -191,8 +194,10 @@ static int do_erase(struct super_block *sb, u64 ofs, pgoff_t index,
	unsigned int max_pages = queue_max_hw_sectors(q) >> (PAGE_SHIFT - 9);
	int i;

	if (max_pages > BIO_MAX_PAGES)
		max_pages = BIO_MAX_PAGES;
	bio = bio_alloc(GFP_NOFS, max_pages);
	BUG_ON(!bio); /* FIXME: handle this */
	BUG_ON(!bio);

	for (i = 0; i < nr_pages; i++) {
		if (i >= max_pages) {
+2 −2
Original line number Diff line number Diff line
@@ -303,12 +303,12 @@ static int __logfs_readdir(struct file *file, void *buf, filldir_t filldir)
				(filler_t *)logfs_readpage, NULL);
		if (IS_ERR(page))
			return PTR_ERR(page);
		dd = kmap_atomic(page, KM_USER0);
		dd = kmap(page);
		BUG_ON(dd->namelen == 0);

		full = filldir(buf, (char *)dd->name, be16_to_cpu(dd->namelen),
				pos, be64_to_cpu(dd->ino), dd->type);
		kunmap_atomic(dd, KM_USER0);
		kunmap(page);
		page_cache_release(page);
		if (full)
			break;
+7 −0
Original line number Diff line number Diff line
@@ -800,6 +800,7 @@ void do_logfs_journal_wl_pass(struct super_block *sb)
{
	struct logfs_super *super = logfs_super(sb);
	struct logfs_area *area = super->s_journal_area;
	struct btree_head32 *head = &super->s_reserved_segments;
	u32 segno, ec;
	int i, err;

@@ -807,6 +808,7 @@ void do_logfs_journal_wl_pass(struct super_block *sb)
	/* Drop old segments */
	journal_for_each(i)
		if (super->s_journal_seg[i]) {
			btree_remove32(head, super->s_journal_seg[i]);
			logfs_set_segment_unreserved(sb,
					super->s_journal_seg[i],
					super->s_journal_ec[i]);
@@ -819,8 +821,13 @@ void do_logfs_journal_wl_pass(struct super_block *sb)
		super->s_journal_seg[i] = segno;
		super->s_journal_ec[i] = ec;
		logfs_set_segment_reserved(sb, segno);
		err = btree_insert32(head, segno, (void *)1, GFP_KERNEL);
		BUG_ON(err); /* mempool should prevent this */
		err = logfs_erase_segment(sb, segno, 1);
		BUG_ON(err); /* FIXME: remount-ro would be nicer */
	}
	/* Manually move journal_area */
	freeseg(sb, area->a_segno);
	area->a_segno = super->s_journal_seg[0];
	area->a_is_open = 0;
	area->a_used_bytes = 0;
+1 −0
Original line number Diff line number Diff line
@@ -587,6 +587,7 @@ void move_page_to_btree(struct page *page);
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);

/* area handling */
int logfs_init_areas(struct super_block *sb);
+12 −1
Original line number Diff line number Diff line
@@ -1594,7 +1594,6 @@ int logfs_delete(struct inode *inode, pgoff_t index,
	return ret;
}

/* Rewrite cannot mark the inode dirty but has to write it immediatly. */
int logfs_rewrite_block(struct inode *inode, u64 bix, u64 ofs,
		gc_level_t gc_level, long flags)
{
@@ -1611,6 +1610,18 @@ int logfs_rewrite_block(struct inode *inode, u64 bix, u64 ofs,
		if (level != 0)
			alloc_indirect_block(inode, page, 0);
		err = logfs_write_buf(inode, page, flags);
		if (!err && shrink_level(gc_level) == 0) {
			/* Rewrite cannot mark the inode dirty but has to
			 * write it immediatly.
			 * Q: Can't we just create an alias for the inode
			 * instead?  And if not, why not?
			 */
			if (inode->i_ino == LOGFS_INO_MASTER)
				logfs_write_anchor(inode->i_sb);
			else {
				err = __logfs_write_inode(inode, flags);
			}
		}
	}
	logfs_put_write_page(page);
	return err;
Loading