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

Commit 5ad12102 authored by Jaegeuk Kim's avatar Jaegeuk Kim
Browse files

Merge remote-tracking branch 'aosp/upstream-f2fs-stable-linux-5.4.y' into android-5.4-stable



* aosp/upstream-f2fs-stable-linux-5.4.y:
  f2fs: attach IO flags to the missing cases
  f2fs: add node_io_flag for bio flags likewise data_io_flag
  f2fs: remove unused parameter of f2fs_put_rpages_mapping()
  f2fs: handle readonly filesystem in f2fs_ioc_shutdown()
  f2fs: avoid utf8_strncasecmp() with unstable name
  f2fs: don't return vmalloc() memory from f2fs_kmalloc()
  f2fs: fix retry logic in f2fs_write_cache_pages()
  f2fs: fix wrong discard space
  f2fs: compress: don't compress any datas after cp stop
  f2fs: remove unneeded return value of __insert_discard_tree()
  f2fs: fix wrong value of tracepoint parameter
  f2fs: protect new segment allocation in expand_inode_data
  f2fs: code cleanup by removing ifdef macro surrounding
  writeback: Avoid skipping inode writeback
  f2fs: avoid inifinite loop to wait for flushing node pages at cp_error
  f2fs: compress: fix zstd data corruption
  f2fs: add compressed/gc data read IO stat
  f2fs: fix potential use-after-free issue
  f2fs: compress: don't handle non-compressed data in workqueue
  f2fs: remove redundant assignment to variable err
  f2fs: refactor resize_fs to avoid meta updates in progress
  f2fs: use round_up to enhance calculation
  f2fs: introduce F2FS_IOC_RESERVE_COMPRESS_BLOCKS
  f2fs: Avoid double lock for cp_rwsem during checkpoint
  f2fs: report delalloc reserve as non-free in statfs for project quota
  f2fs: Fix wrong stub helper update_sit_info
  f2fs: compress: let lz4 compressor handle output buffer budget properly
  f2fs: remove blk_plugging in block_operations
  f2fs: introduce F2FS_IOC_RELEASE_COMPRESS_BLOCKS
  f2fs: shrink spinlock coverage
  f2fs: correctly fix the parent inode number during fsync()
  f2fs: compress: support lzo-rle compress algorithm
  f2fs: introduce mempool for {,de}compress intermediate page allocation
  f2fs: introduce f2fs_bmap_compress()
  f2fs: support fiemap on compressed inode
  f2fs: support partial truncation on compressed inode
  f2fs: remove redundant compress inode check
  f2fs: use strcmp() in parse_options()
  f2fs: Use the correct style for SPDX License Identifier

 Conflicts:
	fs/f2fs/data.c
	fs/f2fs/dir.c

Bug: 154167995
Change-Id: I04ec97a9cafef2d7b8736f36a2a8d244965cae9a
Signed-off-by: default avatarJaegeuk Kim <jaegeuk@google.com>
parents 11e8c6dc c01d16a6
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -333,6 +333,15 @@ Description: Give a way to attach REQ_META|FUA to data writes
		*    5 |    4 |   3 |    2 |    1 |   0 |
		* Cold | Warm | Hot | Cold | Warm | Hot |

What:		/sys/fs/f2fs/<disk>/node_io_flag
Date:		June 2020
Contact:	"Jaegeuk Kim" <jaegeuk@kernel.org>
Description:	Give a way to attach REQ_META|FUA to node writes
		given temperature-based bits. Now the bits indicate:
		*      REQ_META     |      REQ_FUA      |
		*    5 |    4 |   3 |    2 |    1 |   0 |
		* Cold | Warm | Hot | Cold | Warm | Hot |

What:		/sys/fs/f2fs/<disk>/iostat_period_ms
Date:		April 2020
Contact:	"Daeho Jeong" <daehojeong@google.com>
+10 −0
Original line number Diff line number Diff line
@@ -127,3 +127,13 @@ config F2FS_FS_ZSTD
	default y
	help
	  Support ZSTD compress algorithm, if unsure, say Y.

config F2FS_FS_LZORLE
	bool "LZO-RLE compression support"
	depends on F2FS_FS_COMPRESSION
	depends on F2FS_FS_LZO
	select LZO_COMPRESS
	select LZO_DECOMPRESS
	default y
	help
	  Support LZO-RLE compress algorithm, if unsure, say Y.
+1 −1
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0
/* SPDX-License-Identifier: GPL-2.0 */
/*
 * fs/f2fs/acl.h
 *
+13 −11
Original line number Diff line number Diff line
@@ -895,7 +895,7 @@ int f2fs_get_valid_checkpoint(struct f2fs_sb_info *sbi)
	int i;
	int err;

	sbi->ckpt = f2fs_kzalloc(sbi, array_size(blk_size, cp_blks),
	sbi->ckpt = f2fs_kvzalloc(sbi, array_size(blk_size, cp_blks),
				  GFP_KERNEL);
	if (!sbi->ckpt)
		return -ENOMEM;
@@ -1166,10 +1166,12 @@ static int block_operations(struct f2fs_sb_info *sbi)
		.nr_to_write = LONG_MAX,
		.for_reclaim = 0,
	};
	struct blk_plug plug;
	int err = 0, cnt = 0;

	blk_start_plug(&plug);
	/*
	 * Let's flush inline_data in dirty node pages.
	 */
	f2fs_flush_inline_data(sbi);

retry_flush_quotas:
	f2fs_lock_all(sbi);
@@ -1198,7 +1200,7 @@ static int block_operations(struct f2fs_sb_info *sbi)
		f2fs_unlock_all(sbi);
		err = f2fs_sync_dirty_inodes(sbi, DIR_INODE);
		if (err)
			goto out;
			return err;
		cond_resched();
		goto retry_flush_quotas;
	}
@@ -1214,7 +1216,7 @@ static int block_operations(struct f2fs_sb_info *sbi)
		f2fs_unlock_all(sbi);
		err = f2fs_sync_inode_meta(sbi);
		if (err)
			goto out;
			return err;
		cond_resched();
		goto retry_flush_quotas;
	}
@@ -1230,7 +1232,7 @@ static int block_operations(struct f2fs_sb_info *sbi)
		if (err) {
			up_write(&sbi->node_change);
			f2fs_unlock_all(sbi);
			goto out;
			return err;
		}
		cond_resched();
		goto retry_flush_nodes;
@@ -1242,8 +1244,6 @@ static int block_operations(struct f2fs_sb_info *sbi)
	 */
	__prepare_cp_block(sbi);
	up_write(&sbi->node_change);
out:
	blk_finish_plug(&plug);
	return err;
}

@@ -1562,6 +1562,7 @@ int f2fs_write_checkpoint(struct f2fs_sb_info *sbi, struct cp_control *cpc)
			return 0;
		f2fs_warn(sbi, "Start checkpoint disabled!");
	}
	if (cpc->reason != CP_RESIZE)
		mutex_lock(&sbi->cp_mutex);

	if (!is_sbi_flag_set(sbi, SBI_IS_DIRTY) &&
@@ -1631,6 +1632,7 @@ int f2fs_write_checkpoint(struct f2fs_sb_info *sbi, struct cp_control *cpc)
	f2fs_update_time(sbi, CP_TIME);
	trace_f2fs_write_checkpoint(sbi->sb, cpc->reason, "finish checkpoint");
out:
	if (cpc->reason != CP_RESIZE)
		mutex_unlock(&sbi->cp_mutex);
	return err;
}
+143 −32
Original line number Diff line number Diff line
@@ -12,6 +12,7 @@
#include <linux/lzo.h>
#include <linux/lz4.h>
#include <linux/zstd.h>
#include <linux/moduleparam.h>

#include "f2fs.h"
#include "node.h"
@@ -65,15 +66,6 @@ static void f2fs_set_compressed_page(struct page *page,
	page->mapping = inode->i_mapping;
}

static void f2fs_put_compressed_page(struct page *page)
{
	set_page_private(page, (unsigned long)NULL);
	ClearPagePrivate(page);
	page->mapping = NULL;
	unlock_page(page);
	put_page(page);
}

static void f2fs_drop_rpages(struct compress_ctx *cc, int len, bool unlock)
{
	int i;
@@ -98,8 +90,7 @@ static void f2fs_unlock_rpages(struct compress_ctx *cc, int len)
	f2fs_drop_rpages(cc, len, true);
}

static void f2fs_put_rpages_mapping(struct compress_ctx *cc,
				struct address_space *mapping,
static void f2fs_put_rpages_mapping(struct address_space *mapping,
				pgoff_t start, int len)
{
	int i;
@@ -236,7 +227,12 @@ static int lz4_init_compress_ctx(struct compress_ctx *cc)
	if (!cc->private)
		return -ENOMEM;

	cc->clen = LZ4_compressBound(PAGE_SIZE << cc->log_cluster_size);
	/*
	 * we do not change cc->clen to LZ4_compressBound(inputsize) to
	 * adapt worst compress case, because lz4 compressor can handle
	 * output budget properly.
	 */
	cc->clen = cc->rlen - PAGE_SIZE - COMPRESS_HEADER_SIZE;
	return 0;
}

@@ -252,11 +248,9 @@ static int lz4_compress_pages(struct compress_ctx *cc)

	len = LZ4_compress_default(cc->rbuf, cc->cbuf->cdata, cc->rlen,
						cc->clen, cc->private);
	if (!len) {
		printk_ratelimited("%sF2FS-fs (%s): lz4 compress failed\n",
				KERN_ERR, F2FS_I_SB(cc->inode)->sb->s_id);
		return -EIO;
	}
	if (!len)
		return -EAGAIN;

	cc->clen = len;
	return 0;
}
@@ -366,6 +360,13 @@ static int zstd_compress_pages(struct compress_ctx *cc)
		return -EIO;
	}

	/*
	 * there is compressed data remained in intermediate buffer due to
	 * no more space in cbuf.cdata
	 */
	if (ret)
		return -EAGAIN;

	cc->clen = outbuf.pos;
	return 0;
}
@@ -451,6 +452,31 @@ static const struct f2fs_compress_ops f2fs_zstd_ops = {
};
#endif

#ifdef CONFIG_F2FS_FS_LZO
#ifdef CONFIG_F2FS_FS_LZORLE
static int lzorle_compress_pages(struct compress_ctx *cc)
{
	int ret;

	ret = lzorle1x_1_compress(cc->rbuf, cc->rlen, cc->cbuf->cdata,
					&cc->clen, cc->private);
	if (ret != LZO_E_OK) {
		printk_ratelimited("%sF2FS-fs (%s): lzo-rle compress failed, ret:%d\n",
				KERN_ERR, F2FS_I_SB(cc->inode)->sb->s_id, ret);
		return -EIO;
	}
	return 0;
}

static const struct f2fs_compress_ops f2fs_lzorle_ops = {
	.init_compress_ctx	= lzo_init_compress_ctx,
	.destroy_compress_ctx	= lzo_destroy_compress_ctx,
	.compress_pages		= lzorle_compress_pages,
	.decompress_pages	= lzo_decompress_pages,
};
#endif
#endif

static const struct f2fs_compress_ops *f2fs_cops[COMPRESS_MAX] = {
#ifdef CONFIG_F2FS_FS_LZO
	&f2fs_lzo_ops,
@@ -467,6 +493,11 @@ static const struct f2fs_compress_ops *f2fs_cops[COMPRESS_MAX] = {
#else
	NULL,
#endif
#if defined(CONFIG_F2FS_FS_LZO) && defined(CONFIG_F2FS_FS_LZORLE)
	&f2fs_lzorle_ops,
#else
	NULL,
#endif
};

bool f2fs_is_compress_backend_ready(struct inode *inode)
@@ -476,17 +507,47 @@ bool f2fs_is_compress_backend_ready(struct inode *inode)
	return f2fs_cops[F2FS_I(inode)->i_compress_algorithm];
}

static struct page *f2fs_grab_page(void)
static mempool_t *compress_page_pool = NULL;
static int num_compress_pages = 512;
module_param(num_compress_pages, uint, 0444);
MODULE_PARM_DESC(num_compress_pages,
		"Number of intermediate compress pages to preallocate");

int f2fs_init_compress_mempool(void)
{
	compress_page_pool = mempool_create_page_pool(num_compress_pages, 0);
	if (!compress_page_pool)
		return -ENOMEM;

	return 0;
}

void f2fs_destroy_compress_mempool(void)
{
	mempool_destroy(compress_page_pool);
}

static struct page *f2fs_compress_alloc_page(void)
{
	struct page *page;

	page = alloc_page(GFP_NOFS);
	if (!page)
		return NULL;
	page = mempool_alloc(compress_page_pool, GFP_NOFS);
	lock_page(page);

	return page;
}

static void f2fs_compress_free_page(struct page *page)
{
	if (!page)
		return;
	set_page_private(page, (unsigned long)NULL);
	ClearPagePrivate(page);
	page->mapping = NULL;
	unlock_page(page);
	mempool_free(page, compress_page_pool);
}

static int f2fs_compress_pages(struct compress_ctx *cc)
{
	struct f2fs_sb_info *sbi = F2FS_I_SB(cc->inode);
@@ -516,7 +577,7 @@ static int f2fs_compress_pages(struct compress_ctx *cc)
	}

	for (i = 0; i < cc->nr_cpages; i++) {
		cc->cpages[i] = f2fs_grab_page();
		cc->cpages[i] = f2fs_compress_alloc_page();
		if (!cc->cpages[i]) {
			ret = -ENOMEM;
			goto out_free_cpages;
@@ -561,7 +622,7 @@ static int f2fs_compress_pages(struct compress_ctx *cc)
	vunmap(cc->rbuf);

	for (i = nr_cpages; i < cc->nr_cpages; i++) {
		f2fs_put_compressed_page(cc->cpages[i]);
		f2fs_compress_free_page(cc->cpages[i]);
		cc->cpages[i] = NULL;
	}

@@ -581,7 +642,7 @@ static int f2fs_compress_pages(struct compress_ctx *cc)
out_free_cpages:
	for (i = 0; i < cc->nr_cpages; i++) {
		if (cc->cpages[i])
			f2fs_put_compressed_page(cc->cpages[i]);
			f2fs_compress_free_page(cc->cpages[i]);
	}
	kfree(cc->cpages);
	cc->cpages = NULL;
@@ -788,6 +849,8 @@ static bool cluster_may_compress(struct compress_ctx *cc)
		return false;
	if (!f2fs_cluster_is_full(cc))
		return false;
	if (unlikely(f2fs_cp_error(F2FS_I_SB(cc->inode))))
		return false;
	return __cluster_may_compress(cc);
}

@@ -879,7 +942,7 @@ static int prepare_compress_overwrite(struct compress_ctx *cc,

		if (!PageUptodate(page)) {
			f2fs_unlock_rpages(cc, i + 1);
			f2fs_put_rpages_mapping(cc, mapping, start_idx,
			f2fs_put_rpages_mapping(mapping, start_idx,
					cc->cluster_size);
			f2fs_destroy_compress_ctx(cc);
			goto retry;
@@ -914,7 +977,7 @@ static int prepare_compress_overwrite(struct compress_ctx *cc,
unlock_pages:
	f2fs_unlock_rpages(cc, i);
release_pages:
	f2fs_put_rpages_mapping(cc, mapping, start_idx, i);
	f2fs_put_rpages_mapping(mapping, start_idx, i);
	f2fs_destroy_compress_ctx(cc);
	return ret;
}
@@ -954,6 +1017,55 @@ bool f2fs_compress_write_end(struct inode *inode, void *fsdata,
	return first_index;
}

int f2fs_truncate_partial_cluster(struct inode *inode, u64 from, bool lock)
{
	void *fsdata = NULL;
	struct page *pagep;
	int log_cluster_size = F2FS_I(inode)->i_log_cluster_size;
	pgoff_t start_idx = from >> (PAGE_SHIFT + log_cluster_size) <<
							log_cluster_size;
	int err;

	err = f2fs_is_compressed_cluster(inode, start_idx);
	if (err < 0)
		return err;

	/* truncate normal cluster */
	if (!err)
		return f2fs_do_truncate_blocks(inode, from, lock);

	/* truncate compressed cluster */
	err = f2fs_prepare_compress_overwrite(inode, &pagep,
						start_idx, &fsdata);

	/* should not be a normal cluster */
	f2fs_bug_on(F2FS_I_SB(inode), err == 0);

	if (err <= 0)
		return err;

	if (err > 0) {
		struct page **rpages = fsdata;
		int cluster_size = F2FS_I(inode)->i_cluster_size;
		int i;

		for (i = cluster_size - 1; i >= 0; i--) {
			loff_t start = rpages[i]->index << PAGE_SHIFT;

			if (from <= start) {
				zero_user_segment(rpages[i], 0, PAGE_SIZE);
			} else {
				zero_user_segment(rpages[i], from - start,
								PAGE_SIZE);
				break;
			}
		}

		f2fs_compress_write_end(inode, fsdata, start_idx, true);
	}
	return 0;
}

static int f2fs_write_compressed_pages(struct compress_ctx *cc,
					int *submitted,
					struct writeback_control *wbc,
@@ -1135,7 +1247,7 @@ void f2fs_compress_write_end_io(struct bio *bio, struct page *page)
	if (unlikely(bio->bi_status))
		mapping_set_error(cic->inode->i_mapping, -EIO);

	f2fs_put_compressed_page(page);
	f2fs_compress_free_page(page);

	dec_page_count(sbi, F2FS_WB_DATA);

@@ -1296,7 +1408,7 @@ struct decompress_io_ctx *f2fs_alloc_dic(struct compress_ctx *cc)
	for (i = 0; i < dic->nr_cpages; i++) {
		struct page *page;

		page = f2fs_grab_page();
		page = f2fs_compress_alloc_page();
		if (!page)
			goto out_free;

@@ -1316,7 +1428,7 @@ struct decompress_io_ctx *f2fs_alloc_dic(struct compress_ctx *cc)
			continue;
		}

		dic->tpages[i] = f2fs_grab_page();
		dic->tpages[i] = f2fs_compress_alloc_page();
		if (!dic->tpages[i])
			goto out_free;
	}
@@ -1338,8 +1450,7 @@ void f2fs_free_dic(struct decompress_io_ctx *dic)
				continue;
			if (!dic->tpages[i])
				continue;
			unlock_page(dic->tpages[i]);
			put_page(dic->tpages[i]);
			f2fs_compress_free_page(dic->tpages[i]);
		}
		kfree(dic->tpages);
	}
@@ -1348,7 +1459,7 @@ void f2fs_free_dic(struct decompress_io_ctx *dic)
		for (i = 0; i < dic->nr_cpages; i++) {
			if (!dic->cpages[i])
				continue;
			f2fs_put_compressed_page(dic->cpages[i]);
			f2fs_compress_free_page(dic->cpages[i]);
		}
		kfree(dic->cpages);
	}
Loading