Not a member of Pastebin yet?
                        Sign Up,
                        it unlocks many cool features!                    
                - fs/f2fs/Kconfig | 13 +++-
 - fs/f2fs/checkpoint.c | 44 +++++++++++--
 - fs/f2fs/data.c | 205 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
 - fs/f2fs/dir.c | 23 ++++++-
 - fs/f2fs/f2fs.h | 208 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-----
 - fs/f2fs/file.c | 54 +++++++++++++---
 - fs/f2fs/gc.c | 40 ++++++++++--
 - fs/f2fs/inline.c | 18 ++++++
 - fs/f2fs/inode.c | 14 +++++
 - fs/f2fs/namei.c | 28 ++++++---
 - fs/f2fs/node.c | 54 +++++++++++++---
 - fs/f2fs/segment.c | 80 ++++++++++++++++++++----
 - fs/f2fs/segment.h | 3 +
 - fs/f2fs/super.c | 219 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------
 - fs/f2fs/sysfs.c | 197 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 - 15 files changed, 1109 insertions(+), 91 deletions(-)
 - diff --git a/fs/f2fs/Kconfig b/fs/f2fs/Kconfig
 - index 378c221d68a92..02c0616c8181d 100644
 - --- a/fs/f2fs/Kconfig
 - +++ b/fs/f2fs/Kconfig
 - @@ -68,12 +68,23 @@ config F2FS_FS_SECURITY
 - config F2FS_CHECK_FS
 - bool "F2FS consistency checking feature"
 - - depends on F2FS_FS
 - + depends on F2FS_FS && SEC_FACTORY
 - + default y
 - help
 - Enables BUG_ONs which check the filesystem consistency in runtime.
 - If you want to improve the performance, say N.
 - +config F2FS_STRICT_BUG_ON
 - + bool "F2FS consistency checking feature"
 - + depends on F2FS_FS
 - + default y
 - + help
 - + Use BUG_ON() instead of WARN_ON(), when there is an error
 - + in the filesystem consistency.
 - +
 - + Default Y.
 - +
 - config F2FS_FS_ENCRYPTION
 - bool "F2FS Encryption"
 - depends on F2FS_FS
 - diff --git a/fs/f2fs/checkpoint.c b/fs/f2fs/checkpoint.c
 - index 6d72a47162699..f451c7e5207fd 100644
 - --- a/fs/f2fs/checkpoint.c
 - +++ b/fs/f2fs/checkpoint.c
 - @@ -22,6 +22,8 @@
 - static struct kmem_cache *ino_entry_slab;
 - struct kmem_cache *f2fs_inode_entry_slab;
 - +unsigned long long priv_cp_time;
 - +unsigned long long curr_cp_time;
 - void f2fs_stop_checkpoint(struct f2fs_sb_info *sbi, bool end_io)
 - {
 - @@ -345,7 +347,7 @@ long f2fs_sync_meta_pages(struct f2fs_sb_info *sbi, enum page_type type,
 - blk_start_plug(&plug);
 - while ((nr_pages = pagevec_lookup_tag(&pvec, mapping, &index,
 - - PAGECACHE_TAG_DIRTY))) {
 - + PAGECACHE_TAG_DIRTY, PAGEVEC_SIZE))) {
 - int i;
 - for (i = 0; i < nr_pages; i++) {
 - @@ -680,6 +682,8 @@ int f2fs_recover_orphan_inodes(struct f2fs_sb_info *sbi)
 - nid_t ino = le32_to_cpu(orphan_blk->ino[j]);
 - err = recover_orphan_inode(sbi, ino);
 - if (err) {
 - + print_block_data(sbi->sb, start_blk + i,
 - + page_address(page), 0, F2FS_BLKSIZE);
 - f2fs_put_page(page, 1);
 - goto out;
 - }
 - @@ -777,18 +781,22 @@ static int get_checkpoint_version(struct f2fs_sb_info *sbi, block_t cp_addr,
 - f2fs_put_page(*cp_page, 1);
 - f2fs_msg(sbi->sb, KERN_WARNING,
 - "invalid crc_offset: %zu", crc_offset);
 - - return -EINVAL;
 - + goto error;
 - }
 - crc = cur_cp_crc(*cp_block);
 - if (!f2fs_crc_valid(sbi, crc, *cp_block, crc_offset)) {
 - f2fs_put_page(*cp_page, 1);
 - f2fs_msg(sbi->sb, KERN_WARNING, "invalid crc value");
 - - return -EINVAL;
 - + goto error;
 - }
 - *version = cur_cp_version(*cp_block);
 - return 0;
 - +
 - +error:
 - + print_block_data(sbi->sb, cp_addr, page_address(*cp_page), 0, blk_size);
 - + return -EINVAL;
 - }
 - static struct page *validate_checkpoint(struct f2fs_sb_info *sbi,
 - @@ -881,8 +889,13 @@ int f2fs_get_valid_checkpoint(struct f2fs_sb_info *sbi)
 - sbi->cur_cp_pack = 2;
 - /* Sanity checking of checkpoint */
 - - if (f2fs_sanity_check_ckpt(sbi))
 - + if (f2fs_sanity_check_ckpt(sbi)) {
 - + print_block_data(sbi->sb, cur_page->index,
 - + page_address(cur_page), 0, blk_size);
 - goto free_fail_no_cp;
 - + }
 - +
 - + f2fs_get_fsck_stat(sbi);
 - if (cp_blks <= 1)
 - goto done;
 - @@ -1141,6 +1154,7 @@ static int block_operations(struct f2fs_sb_info *sbi)
 - err = f2fs_sync_dirty_inodes(sbi, DIR_INODE);
 - if (err)
 - goto out;
 - + blk_flush_plug(current);
 - cond_resched();
 - goto retry_flush_quotas;
 - }
 - @@ -1163,6 +1177,7 @@ static int block_operations(struct f2fs_sb_info *sbi)
 - err = f2fs_sync_inode_meta(sbi);
 - if (err)
 - goto out;
 - + blk_flush_plug(current);
 - cond_resched();
 - goto retry_flush_quotas;
 - }
 - @@ -1180,6 +1195,7 @@ static int block_operations(struct f2fs_sb_info *sbi)
 - f2fs_unlock_all(sbi);
 - goto out;
 - }
 - + blk_flush_plug(current);
 - cond_resched();
 - goto retry_flush_nodes;
 - }
 - @@ -1492,6 +1508,24 @@ static int do_checkpoint(struct f2fs_sb_info *sbi, struct cp_control *cpc)
 - return unlikely(f2fs_cp_error(sbi)) ? -EIO : 0;
 - }
 - +#define CP_TIME_RECORD_UNIT 1000000
 - +static void f2fs_update_max_cp_interval(struct f2fs_sb_info *sbi)
 - +{
 - + unsigned long long cp_interval = 0;
 - +
 - + curr_cp_time = local_clock();
 - + if (!priv_cp_time)
 - + goto out;
 - +
 - + cp_interval = ((curr_cp_time - priv_cp_time) / CP_TIME_RECORD_UNIT) ?
 - + ((curr_cp_time - priv_cp_time) / CP_TIME_RECORD_UNIT) : 1;
 - +
 - + if (sbi->sec_stat.cp_max_interval < cp_interval)
 - + sbi->sec_stat.cp_max_interval = cp_interval;
 - +out:
 - + priv_cp_time = curr_cp_time;
 - +}
 - +
 - /*
 - * We guarantee that this checkpoint procedure will not fail.
 - */
 - @@ -1573,6 +1607,8 @@ int f2fs_write_checkpoint(struct f2fs_sb_info *sbi, struct cp_control *cpc)
 - stop:
 - unblock_operations(sbi);
 - stat_inc_cp_count(sbi->stat_info);
 - + sbi->sec_stat.cp_cnt[STAT_CP_ALL]++;
 - + f2fs_update_max_cp_interval(sbi);
 - if (cpc->reason & CP_RECOVERY)
 - f2fs_msg(sbi->sb, KERN_NOTICE,
 - diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
 - index 15a4a5703a39c..94ff230c26e4e 100644
 - --- a/fs/f2fs/data.c
 - +++ b/fs/f2fs/data.c
 - @@ -24,6 +24,7 @@
 - #include "segment.h"
 - #include "trace.h"
 - #include <trace/events/f2fs.h>
 - +#include <trace/events/android_fs.h>
 - #define NUM_PREALLOC_POST_READ_CTXS 128
 - @@ -82,6 +83,77 @@ struct bio_post_read_ctx {
 - unsigned int enabled_steps;
 - };
 - +#ifdef CONFIG_FS_INLINE_ENCRYPTION
 - +static inline bool f2fs_inline_encrypted(struct inode *inode,
 - + struct f2fs_io_info *fio)
 - +{
 - + if (fio && (fio->type != DATA || fio->encrypted_page))
 - + return false;
 - +
 - + return (f2fs_encrypted_file(inode) &&
 - + fscrypt_inline_encrypted(inode));
 - +}
 - +
 - +static inline bool __bio_inline_encrypted(struct bio *bio)
 - +{
 - + if (!bio)
 - + return false;
 - +
 - + if (bio->bi_opf & REQ_CRYPT)
 - + return true;
 - +
 - + return false;
 - +}
 - +
 - +static bool try_merge_bio_encrypted(struct bio *bio, u64 dun, void *ci, bool encrypted)
 - +{
 - + if (!bio)
 - + return true;
 - +
 - + /* if both of them are not encrypted, no further check is needed */
 - + if (!__bio_inline_encrypted(bio) && !encrypted)
 - + return true;
 - +
 - + if (bio->bi_cryptd != ci)
 - + return false;
 - +
 - +#ifdef CONFIG_BLK_DEV_CRYPT_DUN
 - + if (bio_end_dun(bio) != dun)
 - + return false;
 - +#endif
 - + return true;
 - +}
 - +
 - +static inline void set_fio_inline_encrypted(struct f2fs_io_info *fio, int set)
 - +{
 - + if (!fio)
 - + return;
 - +
 - + if (set) {
 - + fio->op_flags |= REQ_CRYPT;
 - + return;
 - + }
 - +
 - + fio->op_flags &= ~REQ_CRYPT;
 - +}
 - +#else /* !defined(CONFIG_FS_INLINE_ENCRYPTION) */
 - +static inline bool f2fs_inline_encrypted(struct inode *inode,
 - + struct f2fs_io_info *fio)
 - +{
 - + return false;
 - +}
 - +
 - +static bool try_merge_bio_encrypted(struct bio *bio, u64 dun, void *ci, bool encrypted)
 - +{
 - + return true;
 - +}
 - +
 - +static inline void set_fio_inline_encrypted(struct f2fs_io_info *fio, int set)
 - +{
 - + /* DO NOTHING */
 - +}
 - +#endif
 - +
 - static void __read_end_io(struct bio *bio)
 - {
 - struct page *page;
 - @@ -188,8 +260,10 @@ static void f2fs_write_end_io(struct bio *bio)
 - if (unlikely(bio->bi_status)) {
 - mapping_set_error(page->mapping, -EIO);
 - - if (type == F2FS_WB_CP_DATA)
 - + if (type == F2FS_WB_CP_DATA) {
 - f2fs_stop_checkpoint(sbi, true);
 - + f2fs_bug_on(sbi, 1);
 - + }
 - }
 - f2fs_bug_on(sbi, page->mapping == NODE_MAPPING(sbi) &&
 - @@ -319,6 +393,15 @@ static inline void __submit_bio(struct f2fs_sb_info *sbi,
 - trace_f2fs_submit_read_bio(sbi->sb, type, bio);
 - else
 - trace_f2fs_submit_write_bio(sbi->sb, type, bio);
 - +
 - +#ifdef CONFIG_DDAR
 - + if (type == DATA) {
 - + if (fscrypt_dd_may_submit_bio(bio) == -EOPNOTSUPP)
 - + submit_bio(bio);
 - + return;
 - + }
 - +#endif
 - +
 - submit_bio(bio);
 - }
 - @@ -461,6 +544,7 @@ int f2fs_submit_page_bio(struct f2fs_io_info *fio)
 - struct bio *bio;
 - struct page *page = fio->encrypted_page ?
 - fio->encrypted_page : fio->page;
 - + struct inode *inode = fio->page->mapping->host;
 - if (!f2fs_is_valid_blkaddr(fio->sbi, fio->new_blkaddr,
 - __is_meta_io(fio) ? META_GENERIC : DATA_GENERIC))
 - @@ -486,6 +570,9 @@ int f2fs_submit_page_bio(struct f2fs_io_info *fio)
 - inc_page_count(fio->sbi, is_read_io(fio->op) ?
 - __read_io_type(page): WB_DATA_TYPE(fio->page));
 - + if (f2fs_inline_encrypted(inode, fio))
 - + fscrypt_set_bio_cryptd_dun(inode, bio, FSCRYPT_PG_DUN(inode, fio->page));
 - +
 - __submit_bio(fio->sbi, bio, fio->type);
 - return 0;
 - }
 - @@ -496,6 +583,9 @@ void f2fs_submit_page_write(struct f2fs_io_info *fio)
 - enum page_type btype = PAGE_TYPE_OF_BIO(fio->type);
 - struct f2fs_bio_info *io = sbi->write_io[btype] + fio->temp;
 - struct page *bio_page;
 - + struct inode *inode;
 - + bool enc;
 - + u64 dun;
 - f2fs_bug_on(sbi, is_read_io(fio->op));
 - @@ -518,6 +608,10 @@ void f2fs_submit_page_write(struct f2fs_io_info *fio)
 - verify_block_addr(fio, fio->new_blkaddr);
 - bio_page = fio->encrypted_page ? fio->encrypted_page : fio->page;
 - + inode = fio->page->mapping->host;
 - + dun = FSCRYPT_PG_DUN(inode, fio->page);
 - + enc = f2fs_inline_encrypted(inode, fio);
 - + set_fio_inline_encrypted(fio, enc);
 - /* set submitted = true as a return value */
 - fio->submitted = true;
 - @@ -528,17 +622,30 @@ void f2fs_submit_page_write(struct f2fs_io_info *fio)
 - (io->fio.op != fio->op || io->fio.op_flags != fio->op_flags) ||
 - !__same_bdev(sbi, fio->new_blkaddr, io->bio)))
 - __submit_merged_bio(io);
 - +
 - + if (!try_merge_bio_encrypted(io->bio, dun, fscrypt_get_bio_cryptd(inode), enc))
 - + __submit_merged_bio(io);
 - +#ifdef CONFIG_DDAR
 - + /* DDAR support */
 - + if (!fscrypt_dd_can_merge_bio(io->bio, fio->page->mapping))
 - + __submit_merged_bio(io);
 - +#endif
 - +
 - alloc_new:
 - if (io->bio == NULL) {
 - if ((fio->type == DATA || fio->type == NODE) &&
 - fio->new_blkaddr & F2FS_IO_SIZE_MASK(sbi)) {
 - dec_page_count(sbi, WB_DATA_TYPE(bio_page));
 - fio->retry = true;
 - + set_fio_inline_encrypted(fio, false);
 - goto skip;
 - }
 - io->bio = __bio_alloc(sbi, fio->new_blkaddr, fio->io_wbc,
 - BIO_MAX_PAGES, false,
 - fio->type, fio->temp);
 - + if (enc)
 - + fscrypt_set_bio_cryptd_dun(inode, io->bio, dun);
 - +
 - io->fio = *fio;
 - }
 - @@ -582,7 +689,7 @@ static struct bio *f2fs_grab_read_bio(struct inode *inode, block_t blkaddr,
 - bio->bi_end_io = f2fs_read_end_io;
 - bio_set_op_attrs(bio, REQ_OP_READ, op_flag);
 - - if (f2fs_encrypted_file(inode))
 - + if (f2fs_encrypted_file(inode) && !fscrypt_inline_encrypted(inode))
 - post_read_steps |= 1 << STEP_DECRYPT;
 - if (post_read_steps) {
 - ctx = mempool_alloc(bio_post_read_ctx_pool, GFP_NOFS);
 - @@ -616,6 +723,10 @@ static int f2fs_submit_page_read(struct inode *inode, struct page *page,
 - }
 - ClearPageError(page);
 - inc_page_count(F2FS_I_SB(inode), F2FS_RD_DATA);
 - +
 - + if (f2fs_inline_encrypted(inode, NULL))
 - + fscrypt_set_bio_cryptd_dun(inode, bio, FSCRYPT_PG_DUN(inode, page));
 - +
 - __submit_bio(F2FS_I_SB(inode), bio, DATA);
 - return 0;
 - }
 - @@ -1516,6 +1627,8 @@ static int f2fs_mpage_readpages(struct address_space *mapping,
 - sector_t last_block_in_file;
 - sector_t block_nr;
 - struct f2fs_map_blocks map;
 - + bool enc;
 - + u64 dun;
 - map.m_pblk = 0;
 - map.m_lblk = 0;
 - @@ -1597,6 +1710,20 @@ static int f2fs_mpage_readpages(struct address_space *mapping,
 - __submit_bio(F2FS_I_SB(inode), bio, DATA);
 - bio = NULL;
 - }
 - +
 - + dun = FSCRYPT_PG_DUN(inode, page);
 - + enc = f2fs_inline_encrypted(inode, NULL);
 - + if (!try_merge_bio_encrypted(bio, dun, fscrypt_get_bio_cryptd(inode), enc)) {
 - + __submit_bio(F2FS_I_SB(inode), bio, DATA);
 - + bio = NULL;
 - + }
 - +
 - + /* DDAR changes */
 - + if (!fscrypt_dd_can_merge_bio(bio, mapping)) {
 - + __submit_bio(F2FS_I_SB(inode), bio, DATA);
 - + bio = NULL;
 - + }
 - +
 - if (bio == NULL) {
 - bio = f2fs_grab_read_bio(inode, block_nr, nr_pages,
 - is_readahead ? REQ_RAHEAD : 0);
 - @@ -1604,6 +1731,8 @@ static int f2fs_mpage_readpages(struct address_space *mapping,
 - bio = NULL;
 - goto set_error_page;
 - }
 - + if (f2fs_inline_encrypted(inode, NULL))
 - + fscrypt_set_bio_cryptd_dun(inode, bio, dun);
 - }
 - /*
 - @@ -1684,6 +1813,14 @@ static int encrypt_one_page(struct f2fs_io_info *fio)
 - f2fs_wait_on_block_writeback(inode, fio->old_blkaddr);
 - retry_encrypt:
 - + if (fscrypt_inline_encrypted(inode))
 - + return 0;
 - +
 - +#ifdef CONFIG_DDAR
 - + if (fscrypt_dd_encrypted_inode(inode))
 - + return 0;
 - +#endif
 - +
 - fio->encrypted_page = fscrypt_encrypt_page(inode, fio->page,
 - PAGE_SIZE, 0, fio->page->index, gfp_flags);
 - if (IS_ERR(fio->encrypted_page)) {
 - @@ -1838,6 +1975,14 @@ int f2fs_do_write_data_page(struct f2fs_io_info *fio)
 - err = -EFAULT;
 - goto out_writepage;
 - }
 - +
 - + if (file_is_hot(inode))
 - + F2FS_I_SB(inode)->sec_stat.hot_file_written_blocks++;
 - + else if (file_is_cold(inode))
 - + F2FS_I_SB(inode)->sec_stat.cold_file_written_blocks++;
 - + else
 - + F2FS_I_SB(inode)->sec_stat.warm_file_written_blocks++;
 - +
 - /*
 - * If current allocation needs SSR,
 - * it had better in-place writes for updated data.
 - @@ -2107,8 +2252,8 @@ static int f2fs_write_cache_pages(struct address_space *mapping,
 - while (!done && (index <= end)) {
 - int i;
 - - nr_pages = pagevec_lookup_range_tag(&pvec, mapping, &index, end,
 - - tag);
 - + nr_pages = pagevec_lookup_tag(&pvec, mapping, &index, tag,
 - + min(end - index, (pgoff_t)PAGEVEC_SIZE - 1) + 1);
 - if (nr_pages == 0)
 - break;
 - @@ -2116,6 +2261,11 @@ static int f2fs_write_cache_pages(struct address_space *mapping,
 - struct page *page = pvec.pages[i];
 - bool submitted = false;
 - + if (page->index > end) {
 - + done = 1;
 - + break;
 - + }
 - +
 - /* give a priority to WB_SYNC threads */
 - if (atomic_read(&sbi->wb_sync_req[DATA]) &&
 - wbc->sync_mode == WB_SYNC_NONE) {
 - @@ -2290,6 +2440,12 @@ static int f2fs_write_data_pages(struct address_space *mapping,
 - {
 - struct inode *inode = mapping->host;
 - + /* W/A - prevent panic while shutdown */
 - + if (unlikely(ignore_fs_panic)) {
 - + //pr_err("%s: Ignore panic\n", __func__);
 - + return -EIO;
 - + }
 - +
 - return __f2fs_write_data_pages(mapping, wbc,
 - F2FS_I(inode)->cp_task == current ?
 - FS_CP_DATA_IO : FS_DATA_IO);
 - @@ -2401,6 +2557,16 @@ static int f2fs_write_begin(struct file *file, struct address_space *mapping,
 - block_t blkaddr = NULL_ADDR;
 - int err = 0;
 - + if (trace_android_fs_datawrite_start_enabled()) {
 - + char *path, pathbuf[MAX_TRACE_PATHBUF_LEN];
 - +
 - + path = android_fstrace_get_pathname(pathbuf,
 - + MAX_TRACE_PATHBUF_LEN,
 - + inode);
 - + trace_android_fs_datawrite_start(inode, pos, len,
 - + current->pid, path,
 - + current->comm);
 - + }
 - trace_f2fs_write_begin(inode, pos, len, flags);
 - err = f2fs_is_checkpoint_ready(sbi);
 - @@ -2501,6 +2667,7 @@ static int f2fs_write_end(struct file *file,
 - {
 - struct inode *inode = page->mapping->host;
 - + trace_android_fs_datawrite_end(inode, pos, len);
 - trace_f2fs_write_end(inode, pos, len, copied);
 - /*
 - @@ -2572,6 +2739,28 @@ static ssize_t f2fs_direct_IO(struct kiocb *iocb, struct iov_iter *iter)
 - trace_f2fs_direct_IO_enter(inode, offset, count, rw);
 - + if (trace_android_fs_dataread_start_enabled() &&
 - + (rw == READ)) {
 - + char *path, pathbuf[MAX_TRACE_PATHBUF_LEN];
 - +
 - + path = android_fstrace_get_pathname(pathbuf,
 - + MAX_TRACE_PATHBUF_LEN,
 - + inode);
 - + trace_android_fs_dataread_start(inode, offset,
 - + count, current->pid, path,
 - + current->comm);
 - + }
 - + if (trace_android_fs_datawrite_start_enabled() &&
 - + (rw == WRITE)) {
 - + char *path, pathbuf[MAX_TRACE_PATHBUF_LEN];
 - +
 - + path = android_fstrace_get_pathname(pathbuf,
 - + MAX_TRACE_PATHBUF_LEN,
 - + inode);
 - + trace_android_fs_datawrite_start(inode, offset, count,
 - + current->pid, path,
 - + current->comm);
 - + }
 - if (rw == WRITE && whint_mode == WHINT_MODE_OFF)
 - iocb->ki_hint = WRITE_LIFE_NOT_SET;
 - @@ -2612,8 +2801,14 @@ static ssize_t f2fs_direct_IO(struct kiocb *iocb, struct iov_iter *iter)
 - f2fs_write_failed(mapping, offset + count);
 - }
 - }
 - -
 - out:
 - + if (trace_android_fs_dataread_start_enabled() &&
 - + (rw == READ))
 - + trace_android_fs_dataread_end(inode, offset, count);
 - + if (trace_android_fs_datawrite_start_enabled() &&
 - + (rw == WRITE))
 - + trace_android_fs_datawrite_end(inode, offset, count);
 - +
 - trace_f2fs_direct_IO_exit(inode, offset, count, rw, err);
 - return err;
 - diff --git a/fs/f2fs/dir.c b/fs/f2fs/dir.c
 - index 2ef84b4590ead..d9cfd31b3819c 100644
 - --- a/fs/f2fs/dir.c
 - +++ b/fs/f2fs/dir.c
 - @@ -808,6 +808,18 @@ int f2fs_fill_dentries(struct dir_context *ctx, struct f2fs_dentry_ptr *d,
 - de_name.name = d->filename[bit_pos];
 - de_name.len = le16_to_cpu(de->name_len);
 - + /* check memory boundary before moving forward */
 - + bit_pos += GET_DENTRY_SLOTS(le16_to_cpu(de->name_len));
 - + if (unlikely(bit_pos > d->max ||
 - + le16_to_cpu(de->name_len) > F2FS_NAME_LEN)) {
 - + f2fs_msg(sbi->sb, KERN_WARNING,
 - + "%s: corrupted namelen=%d, run fsck to fix.",
 - + __func__, le16_to_cpu(de->name_len));
 - + set_sbi_flag(sbi, SBI_NEED_FSCK);
 - + err = -EINVAL;
 - + goto out;
 - + }
 - +
 - if (f2fs_encrypted_inode(d->inode)) {
 - int save_len = fstr->len;
 - @@ -830,7 +842,6 @@ int f2fs_fill_dentries(struct dir_context *ctx, struct f2fs_dentry_ptr *d,
 - if (readdir_ra)
 - f2fs_ra_node_page(sbi, le32_to_cpu(de->ino));
 - - bit_pos += GET_DENTRY_SLOTS(le16_to_cpu(de->name_len));
 - ctx->pos = start_pos + bit_pos;
 - }
 - out:
 - @@ -867,6 +878,9 @@ static int f2fs_readdir(struct file *file, struct dir_context *ctx)
 - goto out_free;
 - }
 - + if (IS_I_VERSION(inode) && file->f_version != inode->i_version)
 - + file->f_version = inode->i_version;
 - +
 - for (; n < npages; n++, ctx->pos = n * NR_DENTRY_IN_BLOCK) {
 - /* allow readdir() to be interrupted */
 - @@ -899,6 +913,13 @@ static int f2fs_readdir(struct file *file, struct dir_context *ctx)
 - err = f2fs_fill_dentries(ctx, &d,
 - n * NR_DENTRY_IN_BLOCK, &fstr);
 - if (err) {
 - + struct f2fs_sb_info *sbi = F2FS_P_SB(dentry_page);
 - +
 - + if (err == -EINVAL) {
 - + print_block_data(sbi->sb, n,
 - + page_address(dentry_page), 0, F2FS_BLKSIZE);
 - + f2fs_bug_on(sbi, 1);
 - + }
 - f2fs_put_page(dentry_page, 1);
 - break;
 - }
 - diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
 - index 9c7510c98481e..f796c31a6d53d 100644
 - --- a/fs/f2fs/f2fs.h
 - +++ b/fs/f2fs/f2fs.h
 - @@ -24,22 +24,40 @@
 - #include <linux/quotaops.h>
 - #include <crypto/hash.h>
 - #include <linux/overflow.h>
 - +#include <linux/android_aid.h>
 - +#include <linux/ctype.h>
 - +#include "../mount.h"
 - #define __FS_HAS_ENCRYPTION IS_ENABLED(CONFIG_F2FS_FS_ENCRYPTION)
 - #include <linux/fscrypt.h>
 - -#ifdef CONFIG_F2FS_CHECK_FS
 - -#define f2fs_bug_on(sbi, condition) BUG_ON(condition)
 - +#ifdef CONFIG_F2FS_STRICT_BUG_ON
 - +#define BUG_ON_CHKFS BUG_ON
 - #else
 - -#define f2fs_bug_on(sbi, condition) \
 - - do { \
 - - if (unlikely(condition)) { \
 - - WARN_ON(1); \
 - - set_sbi_flag(sbi, SBI_NEED_FSCK); \
 - - } \
 - - } while (0)
 - +#define BUG_ON_CHKFS WARN_ON
 - #endif
 - +extern int ignore_fs_panic;
 - +extern void (*ufs_debug_func)(void *);
 - +
 - +#define f2fs_bug_on(sbi, condition) \
 - + do { \
 - + if (unlikely(condition)) { \
 - + if (ufs_debug_func) \
 - + ufs_debug_func(NULL); \
 - + if (is_sbi_flag_set(sbi, SBI_POR_DOING)) { \
 - + set_sbi_flag(sbi, SBI_NEED_FSCK); \
 - + sbi->sec_stat.fs_por_error++; \
 - + WARN_ON(1); \
 - + } else if (unlikely(!ignore_fs_panic)) { \
 - + f2fs_set_sb_extra_flag(sbi, \
 - + F2FS_SEC_EXTRA_FSCK_MAGIC); \
 - + sbi->sec_stat.fs_error++; \
 - + BUG_ON_CHKFS(1); \
 - + } \
 - + } \
 - + } while (0)
 - +
 - enum {
 - FAULT_KMALLOC,
 - FAULT_KVMALLOC,
 - @@ -121,6 +139,7 @@ struct f2fs_mount_info {
 - unsigned int opt;
 - int write_io_size_bits; /* Write IO size bits */
 - block_t root_reserved_blocks; /* root reserved blocks */
 - + block_t core_reserved_blocks; /* core reserved blocks */
 - kuid_t s_resuid; /* reserved blocks for uid */
 - kgid_t s_resgid; /* reserved blocks for gid */
 - int active_logs; /* # of active logs */
 - @@ -191,6 +210,7 @@ enum {
 - #define DEF_CP_INTERVAL 60 /* 60 secs */
 - #define DEF_IDLE_INTERVAL 5 /* 5 secs */
 - #define DEF_DISABLE_INTERVAL 5 /* 5 secs */
 - +#define DEF_UMOUNT_DISCARD_TIMEOUT 5 /* 5 secs */
 - struct cp_control {
 - int reason;
 - @@ -310,6 +330,7 @@ struct discard_policy {
 - bool sync; /* submit discard with REQ_SYNC flag */
 - bool ordered; /* issue discard by lba order */
 - unsigned int granularity; /* discard granularity */
 - + int timeout; /* discard timeout for put_super */
 - };
 - struct discard_cmd_control {
 - @@ -383,6 +404,8 @@ static inline bool __has_cursum_space(struct f2fs_journal *journal,
 - #define F2FS_IOC_SETFLAGS FS_IOC_SETFLAGS
 - #define F2FS_IOC_GETVERSION FS_IOC_GETVERSION
 - +#define F2FS_CORE_FILE_FL 0x40000000
 - +
 - #define F2FS_IOCTL_MAGIC 0xf5
 - #define F2FS_IOC_START_ATOMIC_WRITE _IO(F2FS_IOCTL_MAGIC, 1)
 - #define F2FS_IOC_COMMIT_ATOMIC_WRITE _IO(F2FS_IOCTL_MAGIC, 2)
 - @@ -430,6 +453,12 @@ static inline bool __has_cursum_space(struct f2fs_journal *journal,
 - #define F2FS_IOC_FSGETXATTR FS_IOC_FSGETXATTR
 - #define F2FS_IOC_FSSETXATTR FS_IOC_FSSETXATTR
 - +#ifdef CONFIG_DDAR
 - +#define F2FS_IOC_GET_DD_POLICY FS_IOC_GET_DD_POLICY
 - +#define F2FS_IOC_SET_DD_POLICY FS_IOC_SET_DD_POLICY
 - +#endif
 - +
 - +
 - struct f2fs_gc_range {
 - u32 sync;
 - u64 start;
 - @@ -773,6 +802,72 @@ static inline void __try_update_largest_extent(struct extent_tree *et,
 - }
 - }
 - +static inline void print_block_data(struct super_block *sb, sector_t blocknr,
 - + unsigned char *data_to_dump, int start, int len)
 - +{
 - + int i, j;
 - + int bh_offset = (start / 16) * 16;
 - + char row_data[17] = { 0, };
 - + char row_hex[50] = { 0, };
 - + char ch;
 - + struct mount *mnt = NULL;
 - +
 - + if (ignore_fs_panic)
 - + return;
 - +
 - + printk(KERN_ERR "As F2FS-fs error, printing data in hex\n");
 - + printk(KERN_ERR " [partition info] s_id : %s, start sector# : %lu\n"
 - + , sb->s_id, sb->s_bdev->bd_part->start_sect);
 - + printk(KERN_ERR " dump block# : %lu, start offset(byte) : %d\n"
 - + , blocknr, start);
 - + printk(KERN_ERR " length(byte) : %d, data_to_dump 0x%p\n"
 - + , len, (void *)data_to_dump);
 - + if (!list_empty(&sb->s_mounts)) {
 - + mnt = list_first_entry(&sb->s_mounts, struct mount, mnt_instance);
 - + if (mnt)
 - + printk(KERN_ERR " mountpoint : %s\n"
 - + , mnt->mnt_mountpoint->d_name.name);
 - + }
 - + printk(KERN_ERR "-------------------------------------------------\n");
 - + for (i = 0; i < (len + 15) / 16; i++) {
 - + for (j = 0; j < 16; j++) {
 - + ch = *(data_to_dump + bh_offset + j);
 - + if (start <= bh_offset + j
 - + && start + len > bh_offset + j) {
 - +
 - + if (isascii(ch) && isprint(ch))
 - + sprintf(row_data + j, "%c", ch);
 - + else
 - + sprintf(row_data + j, ".");
 - +
 - + sprintf(row_hex + (j * 3), "%2.2x ", ch);
 - + } else {
 - + sprintf(row_data + j, " ");
 - + sprintf(row_hex + (j * 3), "-- ");
 - + }
 - + }
 - + printk(KERN_ERR "0x%4.4x : %s | %s\n"
 - + , bh_offset, row_hex, row_data);
 - + bh_offset += 16;
 - + }
 - + printk(KERN_ERR "-------------------------------------------------\n");
 - +}
 - +
 - +
 - +static inline void print_bh(struct super_block *sb, struct buffer_head *bh
 - + , int start, int len)
 - +{
 - + if (bh) {
 - + printk(KERN_ERR " print_bh: bh %p,"
 - + " bh->b_size %lu, bh->b_data %p\n",
 - + (void *) bh, bh->b_size, (void *) bh->b_data);
 - + print_block_data(sb, bh->b_blocknr, bh->b_data, start, len);
 - +
 - + } else {
 - + printk(KERN_ERR " print_bh: bh is null!\n");
 - + }
 - +}
 - +
 - /*
 - * For free nid management
 - */
 - @@ -1010,6 +1105,7 @@ enum cp_reason_type {
 - CP_FASTBOOT_MODE,
 - CP_SPEC_LOG_NUM,
 - CP_RECOVER_DIR,
 - + NR_CP_REASON,
 - };
 - enum iostat_type {
 - @@ -1114,6 +1210,7 @@ enum {
 - DISCARD_TIME,
 - GC_TIME,
 - DISABLE_TIME,
 - + UMOUNT_DISCARD_TIMEOUT,
 - MAX_TIME,
 - };
 - @@ -1148,6 +1245,51 @@ enum fsync_mode {
 - #define DUMMY_ENCRYPTION_ENABLED(sbi) (0)
 - #endif
 - +enum sec_stat_cp_type {
 - + STAT_CP_ALL,
 - + STAT_CP_BG,
 - + STAT_CP_FSYNC,
 - + NR_STAT_CP,
 - +};
 - +
 - +struct f2fs_sec_stat_info {
 - + u64 gc_count[2]; /* FG_GC, BG_GC */
 - + u64 gc_node_seg_count[2];
 - + u64 gc_data_seg_count[2];
 - + u64 gc_node_blk_count[2];
 - + u64 gc_data_blk_count[2];
 - + u64 gc_ttime[2];
 - +
 - + u64 cp_cnt[NR_STAT_CP]; /* total, balance, fsync */
 - + u64 cpr_cnt[NR_CP_REASON]; /* cp reason by fsync */
 - + u64 cp_max_interval; /* max checkpoint interval */
 - + u64 alloc_seg_type[2]; /* LFS, SSR */
 - + u64 alloc_blk_count[2];
 - + atomic64_t inplace_count; /* atomic */
 - + u64 fsync_count;
 - + u64 fsync_dirty_pages;
 - + u64 hot_file_written_blocks; /* db, db-journal, db-wal, db-shm */
 - + u64 cold_file_written_blocks;
 - + u64 warm_file_written_blocks;
 - +
 - + u64 max_inmem_pages; /* get_pages(sbi, F2FS_INMEM_PAGES) */
 - + u64 drop_inmem_all;
 - + u64 drop_inmem_files;
 - + u64 kwritten_byte;
 - + u32 fs_por_error;
 - + u32 fs_error;
 - + u32 max_undiscard_blks; /* # of undiscard blocks */
 - +};
 - +
 - +struct f2fs_sec_fsck_info {
 - + u64 fsck_read_bytes;
 - + u64 fsck_written_bytes;
 - + u64 fsck_elapsed_time;
 - + u32 fsck_exit_code;
 - + u32 valid_node_count;
 - + u32 valid_inode_count;
 - +};
 - +
 - struct f2fs_sb_info {
 - struct super_block *sb; /* pointer to VFS super block */
 - struct proc_dir_entry *s_proc; /* proc entry */
 - @@ -1329,6 +1471,17 @@ struct f2fs_sb_info {
 - /* Precomputed FS UUID checksum for seeding other checksums */
 - __u32 s_chksum_seed;
 - +
 - + struct f2fs_sec_stat_info sec_stat;
 - + struct f2fs_sec_fsck_info sec_fsck_stat;
 - +
 - + /* To gather information of fragmentation */
 - + unsigned int s_sec_part_best_extents;
 - + unsigned int s_sec_part_current_extents;
 - + unsigned int s_sec_part_score;
 - + unsigned int s_sec_defrag_writes_kb;
 - + unsigned int s_sec_num_apps;
 - + unsigned int s_sec_capacity_apps_kb;
 - };
 - #ifdef CONFIG_F2FS_FAULT_INJECTION
 - @@ -1402,6 +1555,19 @@ static inline unsigned int f2fs_time_to_wait(struct f2fs_sb_info *sbi,
 - return wait_ms;
 - }
 - +/*
 - + * SEC Specific Patch
 - + * <------ SB -----><----------- CP -------------><-------- .... ----->
 - + * [SB0][SB1]....[ ][CP1][CP Payload...]...[CP2]....
 - + * ^ (cp_blkaddr - 1) Reserved block for extra flags
 - + * - struct f2fs_sb_extra_flag_blk
 - + * - need_fsck : force fsck request flags - F2FS_SEC_EXTRA_FSC_MAGIC
 - + * - spo_counter : count by fsck (!CP_UMOUNT)
 - + * - rsvd
 - + */
 - +void f2fs_set_sb_extra_flag(struct f2fs_sb_info *sbi, int flag);
 - +void f2fs_get_fsck_stat(struct f2fs_sb_info *sbi);
 - +
 - /*
 - * Inline functions
 - */
 - @@ -1609,7 +1775,11 @@ static inline void disable_nat_bits(struct f2fs_sb_info *sbi, bool lock)
 - {
 - unsigned long flags;
 - - set_sbi_flag(sbi, SBI_NEED_FSCK);
 - + /*
 - + * In order to re-enable nat_bits we need to call fsck.f2fs by
 - + * set_sbi_flag(sbi, SBI_NEED_FSCK). But it may give huge cost,
 - + * so let's rely on regular fsck or unclean shutdown.
 - + */
 - if (lock)
 - spin_lock_irqsave(&sbi->cp_lock, flags);
 - @@ -1738,8 +1908,13 @@ static inline int inc_valid_block_count(struct f2fs_sb_info *sbi,
 - avail_user_block_count = sbi->user_block_count -
 - sbi->current_reserved_blocks;
 - - if (!__allow_reserved_blocks(sbi, inode, true))
 - + if (!__allow_reserved_blocks(sbi, inode, true)) {
 - avail_user_block_count -= F2FS_OPTION(sbi).root_reserved_blocks;
 - +
 - + if (!(F2FS_I(inode)->i_flags & F2FS_CORE_FILE_FL))
 - + avail_user_block_count -= F2FS_OPTION(sbi).core_reserved_blocks;
 - + }
 - +
 - if (unlikely(is_sbi_flag_set(sbi, SBI_CP_DISABLED)))
 - avail_user_block_count -= sbi->unusable_block_count;
 - if (unlikely(sbi->total_valid_block_count > avail_user_block_count)) {
 - @@ -1954,8 +2129,12 @@ static inline int inc_valid_node_count(struct f2fs_sb_info *sbi,
 - valid_block_count = sbi->total_valid_block_count +
 - sbi->current_reserved_blocks + 1;
 - - if (!__allow_reserved_blocks(sbi, inode, false))
 - + if (!__allow_reserved_blocks(sbi, inode, false)) {
 - valid_block_count += F2FS_OPTION(sbi).root_reserved_blocks;
 - + if (!(F2FS_I(inode)->i_flags & F2FS_CORE_FILE_FL))
 - + valid_block_count += F2FS_OPTION(sbi).core_reserved_blocks;
 - + }
 - +
 - if (unlikely(is_sbi_flag_set(sbi, SBI_CP_DISABLED)))
 - valid_block_count += sbi->unusable_block_count;
 - @@ -2976,7 +3155,7 @@ void f2fs_invalidate_blocks(struct f2fs_sb_info *sbi, block_t addr);
 - bool f2fs_is_checkpointed_data(struct f2fs_sb_info *sbi, block_t blkaddr);
 - void f2fs_drop_discard_cmd(struct f2fs_sb_info *sbi);
 - void f2fs_stop_discard_thread(struct f2fs_sb_info *sbi);
 - -bool f2fs_wait_discard_bios(struct f2fs_sb_info *sbi);
 - +bool f2fs_issue_discard_timeout(struct f2fs_sb_info *sbi);
 - void f2fs_clear_prefree_segments(struct f2fs_sb_info *sbi,
 - struct cp_control *cpc);
 - void f2fs_dirty_to_prefree(struct f2fs_sb_info *sbi);
 - @@ -3559,7 +3738,8 @@ static inline bool f2fs_force_buffered_io(struct inode *inode,
 - struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
 - int rw = iov_iter_rw(iter);
 - - if (f2fs_post_read_required(inode))
 - + if (f2fs_post_read_required(inode) &&
 - + !fscrypt_inline_encrypted(inode))
 - return true;
 - if (sbi->s_ndevs)
 - return true;
 - diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
 - index ad83382078806..5b86e4da2a0a7 100644
 - --- a/fs/f2fs/file.c
 - +++ b/fs/f2fs/file.c
 - @@ -30,6 +30,10 @@
 - #include "trace.h"
 - #include <trace/events/f2fs.h>
 - +#ifdef CONFIG_FSCRYPT_SDP
 - +#include <linux/fscrypto_sdp_ioctl.h>
 - +#endif
 - +
 - static int f2fs_filemap_fault(struct vm_fault *vmf)
 - {
 - struct inode *inode = file_inode(vmf->vma->vm_file);
 - @@ -167,6 +171,8 @@ static inline enum cp_reason_type need_do_checkpoint(struct inode *inode)
 - TRANS_DIR_INO))
 - cp_reason = CP_RECOVER_DIR;
 - + sbi->sec_stat.cpr_cnt[cp_reason]++;
 - +
 - return cp_reason;
 - }
 - @@ -216,6 +222,9 @@ static int f2fs_do_sync_file(struct file *file, loff_t start, loff_t end,
 - trace_f2fs_sync_file_enter(inode);
 - + sbi->sec_stat.fsync_count++;
 - + sbi->sec_stat.fsync_dirty_pages += get_dirty_pages(inode);
 - +
 - /* if fdatasync is triggered, let's do in-place-update */
 - if (datasync || get_dirty_pages(inode) <= SM_I(sbi)->min_fsync_blocks)
 - set_inode_flag(inode, FI_NEED_IPU);
 - @@ -268,6 +277,7 @@ static int f2fs_do_sync_file(struct file *file, loff_t start, loff_t end,
 - try_to_fix_pino(inode);
 - clear_inode_flag(inode, FI_APPEND_WRITE);
 - clear_inode_flag(inode, FI_UPDATE_WRITE);
 - + sbi->sec_stat.cp_cnt[STAT_CP_FSYNC]++;
 - goto out;
 - }
 - sync_nodes:
 - @@ -1648,7 +1658,7 @@ static int f2fs_ioc_getflags(struct file *filp, unsigned long arg)
 - if (f2fs_has_inline_data(inode) || f2fs_has_inline_dentry(inode))
 - flags |= F2FS_INLINE_DATA_FL;
 - - flags &= F2FS_FL_USER_VISIBLE;
 - + flags &= (F2FS_FL_USER_VISIBLE | F2FS_CORE_FILE_FL);
 - return put_user(flags, (int __user *)arg);
 - }
 - @@ -1670,8 +1680,8 @@ static int __f2fs_ioc_setflags(struct inode *inode, unsigned int flags)
 - if (!capable(CAP_LINUX_IMMUTABLE))
 - return -EPERM;
 - - flags = flags & F2FS_FL_USER_MODIFIABLE;
 - - flags |= oldflags & ~F2FS_FL_USER_MODIFIABLE;
 - + flags = flags & (F2FS_FL_USER_MODIFIABLE | F2FS_CORE_FILE_FL);
 - + flags |= oldflags & ~(F2FS_FL_USER_MODIFIABLE | F2FS_CORE_FILE_FL);
 - fi->i_flags = flags;
 - if (fi->i_flags & F2FS_PROJINHERIT_FL)
 - @@ -1746,10 +1756,12 @@ static int f2fs_ioc_start_atomic_write(struct file *filp)
 - down_write(&F2FS_I(inode)->i_gc_rwsem[WRITE]);
 - - if (!get_dirty_pages(inode))
 - - goto skip_flush;
 - -
 - - f2fs_msg(F2FS_I_SB(inode)->sb, KERN_WARNING,
 - + /*
 - + * Should wait end_io to count F2FS_WB_CP_DATA correctly by
 - + * f2fs_is_atomic_file.
 - + */
 - + if (get_dirty_pages(inode))
 - + f2fs_msg(F2FS_I_SB(inode)->sb, KERN_WARNING,
 - "Unexpected flush for atomic writes: ino=%lu, npages=%u",
 - inode->i_ino, get_dirty_pages(inode));
 - ret = filemap_write_and_wait_range(inode->i_mapping, 0, LLONG_MAX);
 - @@ -1757,7 +1769,7 @@ static int f2fs_ioc_start_atomic_write(struct file *filp)
 - up_write(&F2FS_I(inode)->i_gc_rwsem[WRITE]);
 - goto out;
 - }
 - -skip_flush:
 - +
 - set_inode_flag(inode, FI_ATOMIC_FILE);
 - clear_inode_flag(inode, FI_ATOMIC_REVOKE_REQUEST);
 - up_write(&F2FS_I(inode)->i_gc_rwsem[WRITE]);
 - @@ -3010,6 +3022,20 @@ long f2fs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 - return f2fs_ioc_set_pin_file(filp, arg);
 - case F2FS_IOC_PRECACHE_EXTENTS:
 - return f2fs_ioc_precache_extents(filp, arg);
 - +#ifdef CONFIG_FSCRYPT_SDP
 - + case FS_IOC_GET_SDP_INFO:
 - + case FS_IOC_SET_SDP_POLICY:
 - + case FS_IOC_SET_SENSITIVE:
 - + case FS_IOC_SET_PROTECTED:
 - + case FS_IOC_ADD_CHAMBER:
 - + case FS_IOC_REMOVE_CHAMBER:
 - + return fscrypt_sdp_ioctl(filp, cmd, arg);
 - +#endif
 - +#ifdef CONFIG_DDAR
 - + case F2FS_IOC_GET_DD_POLICY:
 - + case F2FS_IOC_SET_DD_POLICY:
 - + return fscrypt_dd_ioctl(cmd, &arg, file_inode(filp));
 - +#endif
 - default:
 - return -ENOTTY;
 - }
 - @@ -3117,6 +3143,18 @@ long f2fs_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 - case F2FS_IOC_GET_PIN_FILE:
 - case F2FS_IOC_SET_PIN_FILE:
 - case F2FS_IOC_PRECACHE_EXTENTS:
 - +#ifdef CONFIG_FSCRYPT_SDP
 - + case FS_IOC_GET_SDP_INFO:
 - + case FS_IOC_SET_SDP_POLICY:
 - + case FS_IOC_SET_SENSITIVE:
 - + case FS_IOC_SET_PROTECTED:
 - + case FS_IOC_ADD_CHAMBER:
 - + case FS_IOC_REMOVE_CHAMBER:
 - +#endif
 - +#ifdef CONFIG_DDAR
 - + case F2FS_IOC_GET_DD_POLICY:
 - + case F2FS_IOC_SET_DD_POLICY:
 - +#endif
 - break;
 - default:
 - return -ENOIOCTLCMD;
 - diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c
 - index 12394086b8488..95ad4bcc1e49d 100644
 - --- a/fs/f2fs/gc.c
 - +++ b/fs/f2fs/gc.c
 - @@ -376,6 +376,9 @@ static int get_victim_by_default(struct f2fs_sb_info *sbi,
 - goto next;
 - if (gc_type == BG_GC && test_bit(secno, dirty_i->victim_secmap))
 - goto next;
 - + /* W/A for FG_GC failure due to Atomic Write File */
 - + if (test_bit(secno, dirty_i->blacklist_victim_secmap))
 - + goto next;
 - cost = get_gc_cost(sbi, segno, &p);
 - @@ -540,6 +543,7 @@ static int gc_node_segment(struct f2fs_sb_info *sbi,
 - if (!err && gc_type == FG_GC)
 - submitted++;
 - stat_inc_node_blk_count(sbi, 1, gc_type);
 - + sbi->sec_stat.gc_node_blk_count[gc_type]++;
 - }
 - if (++phase < 3)
 - @@ -716,6 +720,9 @@ static int move_data_block(struct inode *inode, block_t bidx,
 - }
 - if (f2fs_is_atomic_file(inode)) {
 - + /* W/A for FG_GC failure due to Atomic Write File */
 - + set_bit(GET_SEC_FROM_SEG(F2FS_I_SB(inode), segno),
 - + DIRTY_I(F2FS_I_SB(inode))->blacklist_victim_secmap);
 - F2FS_I(inode)->i_gc_failures[GC_FAILURE_ATOMIC]++;
 - F2FS_I_SB(inode)->skipped_atomic_files[gc_type]++;
 - err = -EAGAIN;
 - @@ -861,6 +868,9 @@ static int move_data_page(struct inode *inode, block_t bidx, int gc_type,
 - }
 - if (f2fs_is_atomic_file(inode)) {
 - + /* W/A for FG_GC failure due to Atomic Write File */
 - + set_bit(GET_SEC_FROM_SEG(F2FS_I_SB(inode), segno),
 - + DIRTY_I(F2FS_I_SB(inode))->blacklist_victim_secmap);
 - F2FS_I(inode)->i_gc_failures[GC_FAILURE_ATOMIC]++;
 - F2FS_I_SB(inode)->skipped_atomic_files[gc_type]++;
 - err = -EAGAIN;
 - @@ -1062,6 +1072,7 @@ static int gc_data_segment(struct f2fs_sb_info *sbi, struct f2fs_summary *sum,
 - }
 - stat_inc_data_blk_count(sbi, 1, gc_type);
 - + sbi->sec_stat.gc_data_blk_count[gc_type]++;
 - }
 - }
 - @@ -1151,13 +1162,15 @@ static int do_garbage_collect(struct f2fs_sb_info *sbi,
 - * - down_read(sentry_lock) - change_curseg()
 - * - lock_page(sum_page)
 - */
 - - if (type == SUM_TYPE_NODE)
 - + if (type == SUM_TYPE_NODE) {
 - submitted += gc_node_segment(sbi, sum->entries, segno,
 - gc_type);
 - - else
 - + sbi->sec_stat.gc_node_seg_count[gc_type]++;
 - + } else {
 - submitted += gc_data_segment(sbi, sum->entries, gc_list,
 - segno, gc_type);
 - -
 - + sbi->sec_stat.gc_data_seg_count[gc_type]++;
 - + }
 - stat_inc_seg_count(sbi, type, gc_type);
 - if (gc_type == FG_GC &&
 - @@ -1178,6 +1191,17 @@ static int do_garbage_collect(struct f2fs_sb_info *sbi,
 - return seg_freed;
 - }
 - +/* For record miliseconds */
 - +#define GC_TIME_RECORD_UNIT 1000000
 - +static void f2fs_update_gc_total_time(struct f2fs_sb_info *sbi,
 - + unsigned long long start, unsigned long long end, int gc_type)
 - +{
 - + if (!((end - start) / GC_TIME_RECORD_UNIT))
 - + sbi->sec_stat.gc_ttime[gc_type]++;
 - + else
 - + sbi->sec_stat.gc_ttime[gc_type] += ((end - start) / GC_TIME_RECORD_UNIT);
 - +}
 - +
 - int f2fs_gc(struct f2fs_sb_info *sbi, bool sync,
 - bool background, unsigned int segno)
 - {
 - @@ -1191,7 +1215,7 @@ int f2fs_gc(struct f2fs_sb_info *sbi, bool sync,
 - .iroot = RADIX_TREE_INIT(GFP_NOFS),
 - };
 - unsigned long long last_skipped = sbi->skipped_atomic_files[FG_GC];
 - - unsigned long long first_skipped;
 - + unsigned long long first_skipped, gc_start_time = 0, gc_end_time = 0;
 - unsigned int skipped_round = 0, round = 0;
 - trace_f2fs_gc_begin(sbi->sb, sync, background,
 - @@ -1203,6 +1227,11 @@ int f2fs_gc(struct f2fs_sb_info *sbi, bool sync,
 - reserved_segments(sbi),
 - prefree_segments(sbi));
 - + gc_start_time = local_clock();
 - + /* W/A for FG_GC failure due to Atomic Write File */
 - + memset(DIRTY_I(sbi)->blacklist_victim_secmap, 0,
 - + f2fs_bitmap_size(MAIN_SECS(sbi)));
 - +
 - cpc.reason = __get_cp_reason(sbi);
 - sbi->skipped_gc_rwsem = 0;
 - first_skipped = last_skipped;
 - @@ -1282,6 +1311,7 @@ int f2fs_gc(struct f2fs_sb_info *sbi, bool sync,
 - SIT_I(sbi)->last_victim[ALLOC_NEXT] = 0;
 - SIT_I(sbi)->last_victim[FLUSH_DEVICE] = init_segno;
 - + gc_end_time = local_clock();
 - trace_f2fs_gc_end(sbi->sb, ret, total_freed, sec_freed,
 - get_pages(sbi, F2FS_DIRTY_NODES),
 - get_pages(sbi, F2FS_DIRTY_DENTS),
 - @@ -1291,6 +1321,8 @@ int f2fs_gc(struct f2fs_sb_info *sbi, bool sync,
 - reserved_segments(sbi),
 - prefree_segments(sbi));
 - + sbi->sec_stat.gc_count[gc_type]++;
 - + f2fs_update_gc_total_time(sbi, gc_start_time, gc_end_time, gc_type);
 - mutex_unlock(&sbi->gc_mutex);
 - put_gc_inode(&gc_list);
 - diff --git a/fs/f2fs/inline.c b/fs/f2fs/inline.c
 - index cb31a719b0488..36389278beebc 100644
 - --- a/fs/f2fs/inline.c
 - +++ b/fs/f2fs/inline.c
 - @@ -11,6 +11,7 @@
 - #include "f2fs.h"
 - #include "node.h"
 - +#include <trace/events/android_fs.h>
 - bool f2fs_may_inline_data(struct inode *inode)
 - {
 - @@ -84,14 +85,29 @@ int f2fs_read_inline_data(struct inode *inode, struct page *page)
 - {
 - struct page *ipage;
 - + if (trace_android_fs_dataread_start_enabled()) {
 - + char *path, pathbuf[MAX_TRACE_PATHBUF_LEN];
 - +
 - + path = android_fstrace_get_pathname(pathbuf,
 - + MAX_TRACE_PATHBUF_LEN,
 - + inode);
 - + trace_android_fs_dataread_start(inode, page_offset(page),
 - + PAGE_SIZE, current->pid,
 - + path, current->comm);
 - + }
 - +
 - ipage = f2fs_get_node_page(F2FS_I_SB(inode), inode->i_ino);
 - if (IS_ERR(ipage)) {
 - + trace_android_fs_dataread_end(inode, page_offset(page),
 - + PAGE_SIZE);
 - unlock_page(page);
 - return PTR_ERR(ipage);
 - }
 - if (!f2fs_has_inline_data(inode)) {
 - f2fs_put_page(ipage, 1);
 - + trace_android_fs_dataread_end(inode, page_offset(page),
 - + PAGE_SIZE);
 - return -EAGAIN;
 - }
 - @@ -103,6 +119,8 @@ int f2fs_read_inline_data(struct inode *inode, struct page *page)
 - if (!PageUptodate(page))
 - SetPageUptodate(page);
 - f2fs_put_page(ipage, 1);
 - + trace_android_fs_dataread_end(inode, page_offset(page),
 - + PAGE_SIZE);
 - unlock_page(page);
 - return 0;
 - }
 - diff --git a/fs/f2fs/inode.c b/fs/f2fs/inode.c
 - index 91ceee0ed4c40..b216783c5d05e 100644
 - --- a/fs/f2fs/inode.c
 - +++ b/fs/f2fs/inode.c
 - @@ -22,6 +22,9 @@ void f2fs_mark_inode_dirty_sync(struct inode *inode, bool sync)
 - if (is_inode_flag_set(inode, FI_NEW_INODE))
 - return;
 - + if (IS_I_VERSION(inode))
 - + inode_inc_iversion(inode);
 - +
 - if (f2fs_inode_dirtied(inode, sync))
 - return;
 - @@ -320,6 +323,10 @@ static int do_read_inode(struct inode *inode)
 - inode->i_ctime.tv_nsec = le32_to_cpu(ri->i_ctime_nsec);
 - inode->i_mtime.tv_nsec = le32_to_cpu(ri->i_mtime_nsec);
 - inode->i_generation = le32_to_cpu(ri->i_generation);
 - +
 - + if (IS_I_VERSION(inode))
 - + inode->i_version++;
 - +
 - if (S_ISDIR(inode->i_mode))
 - fi->i_current_depth = le32_to_cpu(ri->i_current_depth);
 - else if (S_ISREG(inode->i_mode))
 - @@ -407,6 +414,13 @@ static int do_read_inode(struct inode *inode)
 - F2FS_I(inode)->i_disk_time[1] = inode->i_ctime;
 - F2FS_I(inode)->i_disk_time[2] = inode->i_mtime;
 - F2FS_I(inode)->i_disk_time[3] = F2FS_I(inode)->i_crtime;
 - +
 - + if (unlikely((inode->i_mode & S_IFMT) == 0)) {
 - + print_block_data(sbi->sb, inode->i_ino, page_address(node_page),
 - + 0, F2FS_BLKSIZE);
 - + f2fs_bug_on(sbi, 1);
 - + }
 - +
 - f2fs_put_page(node_page, 1);
 - stat_inc_inline_xattr(inode);
 - diff --git a/fs/f2fs/namei.c b/fs/f2fs/namei.c
 - index aa53748e426a0..178176e7fccc3 100644
 - --- a/fs/f2fs/namei.c
 - +++ b/fs/f2fs/namei.c
 - @@ -48,6 +48,10 @@ static struct inode *f2fs_new_inode(struct inode *dir, umode_t mode)
 - inode->i_ino = ino;
 - inode->i_blocks = 0;
 - +
 - + if (IS_I_VERSION(inode))
 - + inode->i_version++;
 - +
 - inode->i_mtime = inode->i_atime = inode->i_ctime =
 - F2FS_I(inode)->i_crtime = current_time(inode);
 - inode->i_generation = sbi->s_next_generation++;
 - @@ -299,8 +303,7 @@ static int f2fs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
 - f2fs_alloc_nid_done(sbi, ino);
 - - unlock_new_inode(inode);
 - - d_instantiate(dentry, inode);
 - + d_instantiate_new(dentry, inode);
 - if (IS_DIRSYNC(dir))
 - f2fs_sync_fs(sbi->sb, 1);
 - @@ -458,13 +461,23 @@ static struct dentry *f2fs_lookup(struct inode *dir, struct dentry *dentry,
 - }
 - ino = le32_to_cpu(de->ino);
 - - f2fs_put_page(page, 0);
 - inode = f2fs_iget(dir->i_sb, ino);
 - if (IS_ERR(inode)) {
 - + if (PTR_ERR(inode) != -ENOMEM) {
 - + struct f2fs_sb_info *sbi = F2FS_I_SB(dir);
 - +
 - + printk_ratelimited(KERN_ERR "F2FS-fs: Invalid inode referenced: %u"
 - + "at parent inode : %lu\n",ino, dir->i_ino);
 - + print_block_data(sbi->sb, page->index,
 - + page_address(page), 0, F2FS_BLKSIZE);
 - + f2fs_bug_on(sbi, 1);
 - + }
 - + f2fs_put_page(page, 0);
 - err = PTR_ERR(inode);
 - goto out;
 - }
 - + f2fs_put_page(page, 0);
 - if ((dir->i_ino == root_ino) && f2fs_has_inline_dots(dir)) {
 - err = __recover_dot_dentries(dir, root_ino);
 - @@ -608,8 +621,7 @@ static int f2fs_symlink(struct inode *dir, struct dentry *dentry,
 - err = page_symlink(inode, disk_link.name, disk_link.len);
 - err_out:
 - - unlock_new_inode(inode);
 - - d_instantiate(dentry, inode);
 - + d_instantiate_new(dentry, inode);
 - /*
 - * Let's flush symlink data in order to avoid broken symlink as much as
 - @@ -672,8 +684,7 @@ static int f2fs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
 - f2fs_alloc_nid_done(sbi, inode->i_ino);
 - - unlock_new_inode(inode);
 - - d_instantiate(dentry, inode);
 - + d_instantiate_new(dentry, inode);
 - if (IS_DIRSYNC(dir))
 - f2fs_sync_fs(sbi->sb, 1);
 - @@ -727,8 +738,7 @@ static int f2fs_mknod(struct inode *dir, struct dentry *dentry,
 - f2fs_alloc_nid_done(sbi, inode->i_ino);
 - - unlock_new_inode(inode);
 - - d_instantiate(dentry, inode);
 - + d_instantiate_new(dentry, inode);
 - if (IS_DIRSYNC(dir))
 - f2fs_sync_fs(sbi->sb, 1);
 - diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c
 - index bea66bd7fdcb1..ebb71c5072a02 100644
 - --- a/fs/f2fs/node.c
 - +++ b/fs/f2fs/node.c
 - @@ -88,9 +88,9 @@ bool f2fs_available_free_memory(struct f2fs_sb_info *sbi, int type)
 - sizeof(struct extent_node)) >> PAGE_SHIFT;
 - res = mem_size < ((avail_ram * nm_i->ram_thresh / 100) >> 1);
 - } else if (type == INMEM_PAGES) {
 - - /* it allows 20% / total_ram for inmemory pages */
 - + /* it allows 50% / total_ram for inmemory pages */
 - mem_size = get_pages(sbi, F2FS_INMEM_PAGES);
 - - res = mem_size < (val.totalram / 5);
 - + res = mem_size < (val.totalram / 2);
 - } else {
 - if (!sbi->sb->s_bdi->wb.dirty_exceeded)
 - return true;
 - @@ -1372,6 +1372,10 @@ static struct page *__get_node_page(struct f2fs_sb_info *sbi, pgoff_t nid,
 - next_blkaddr_of_node(page));
 - err = -EINVAL;
 - out_err:
 - + if (PageUptodate(page)) {
 - + print_block_data(sbi->sb, nid, page_address(page), 0, F2FS_BLKSIZE);
 - + f2fs_bug_on(sbi, 1);
 - + }
 - ClearPageUptodate(page);
 - f2fs_put_page(page, 1);
 - return ERR_PTR(err);
 - @@ -1439,7 +1443,7 @@ static struct page *last_fsync_dnode(struct f2fs_sb_info *sbi, nid_t ino)
 - index = 0;
 - while ((nr_pages = pagevec_lookup_tag(&pvec, NODE_MAPPING(sbi), &index,
 - - PAGECACHE_TAG_DIRTY))) {
 - + PAGECACHE_TAG_DIRTY, PAGEVEC_SIZE))) {
 - int i;
 - for (i = 0; i < nr_pages; i++) {
 - @@ -1655,7 +1659,7 @@ int f2fs_fsync_node_pages(struct f2fs_sb_info *sbi, struct inode *inode,
 - index = 0;
 - while ((nr_pages = pagevec_lookup_tag(&pvec, NODE_MAPPING(sbi), &index,
 - - PAGECACHE_TAG_DIRTY))) {
 - + PAGECACHE_TAG_DIRTY, PAGEVEC_SIZE))) {
 - int i;
 - for (i = 0; i < nr_pages; i++) {
 - @@ -1768,8 +1772,8 @@ int f2fs_sync_node_pages(struct f2fs_sb_info *sbi,
 - next_step:
 - index = 0;
 - - while (!done && (nr_pages = pagevec_lookup_tag(&pvec,
 - - NODE_MAPPING(sbi), &index, PAGECACHE_TAG_DIRTY))) {
 - + while (!done && (nr_pages = pagevec_lookup_tag(&pvec, NODE_MAPPING(sbi), &index,
 - + PAGECACHE_TAG_DIRTY, PAGEVEC_SIZE))) {
 - int i;
 - for (i = 0; i < nr_pages; i++) {
 - @@ -1918,6 +1922,12 @@ static int f2fs_write_node_pages(struct address_space *mapping,
 - if (unlikely(is_sbi_flag_set(sbi, SBI_POR_DOING)))
 - goto skip_write;
 - + /* W/A - prevent panic while shutdown */
 - + if (unlikely(ignore_fs_panic)) {
 - + //pr_err("%s: Ignore panic\n", __func__);
 - + return -EIO;
 - + }
 - +
 - /* balancing f2fs's metadata in background */
 - f2fs_balance_fs_bg(sbi);
 - @@ -2171,8 +2181,11 @@ static int scan_nat_page(struct f2fs_sb_info *sbi,
 - blk_addr = le32_to_cpu(nat_blk->entries[i].block_addr);
 - - if (blk_addr == NEW_ADDR)
 - + if (blk_addr == NEW_ADDR) {
 - + print_block_data(sbi->sb, current_nat_addr(sbi, start_nid),
 - + page_address(nat_page), 0, F2FS_BLKSIZE);
 - return -EINVAL;
 - + }
 - if (blk_addr == NULL_ADDR) {
 - add_free_nid(sbi, start_nid, true, true);
 - @@ -2324,6 +2337,30 @@ int f2fs_build_free_nids(struct f2fs_sb_info *sbi, bool sync, bool mount)
 - return ret;
 - }
 - +/*
 - + * f2fs_has_free_inodes()
 - + * @sbi: in-core super block structure.
 - + *
 - + * Check if filesystem has inodes available for allocation.
 - + * On success return 1, return 0 on failure.
 - + */
 - +static inline bool f2fs_has_free_inodes(struct f2fs_sb_info *sbi)
 - +{
 - + struct f2fs_nm_info *nm_i = NM_I(sbi);
 - +
 - +#define F2FS_DEF_RESERVE_INODE 8192
 - + if (likely(nm_i->available_nids > F2FS_DEF_RESERVE_INODE))
 - + return true;
 - +
 - + /* Hm, nope. Are (enough) root reserved inodes available? */
 - + if (uid_eq(F2FS_OPTION(sbi).s_resuid, current_fsuid()) ||
 - + (!gid_eq(F2FS_OPTION(sbi).s_resgid, GLOBAL_ROOT_GID) &&
 - + in_group_p(F2FS_OPTION(sbi).s_resgid)) ||
 - + capable(CAP_SYS_RESOURCE))
 - + return true;
 - + return false;
 - +}
 - +
 - /*
 - * If this function returns success, caller can obtain a new nid
 - * from second parameter of this function.
 - @@ -2341,7 +2378,8 @@ bool f2fs_alloc_nid(struct f2fs_sb_info *sbi, nid_t *nid)
 - spin_lock(&nm_i->nid_list_lock);
 - - if (unlikely(nm_i->available_nids == 0)) {
 - + if (unlikely(nm_i->available_nids == 0)
 - + || f2fs_has_free_inodes(sbi) == 0) {
 - spin_unlock(&nm_i->nid_list_lock);
 - return false;
 - }
 - diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
 - index 6edcf8391dd3d..fd8db93a6ee2a 100644
 - --- a/fs/f2fs/segment.c
 - +++ b/fs/f2fs/segment.c
 - @@ -84,6 +84,14 @@ static inline unsigned long __reverse_ffs(unsigned long word)
 - return num;
 - }
 - +static inline void update_max_undiscard_blks(struct f2fs_sb_info *sbi)
 - +{
 - + struct discard_cmd_control *dcc = SM_I(sbi)->dcc_info;
 - +
 - + if (dcc->undiscard_blks > sbi->sec_stat.max_undiscard_blks)
 - + sbi->sec_stat.max_undiscard_blks = dcc->undiscard_blks;
 - +}
 - +
 - /*
 - * __find_rev_next(_zero)_bit is copied from lib/find_next_bit.c because
 - * f2fs_set_bit makes MSB and LSB reversed in a byte.
 - @@ -209,6 +217,8 @@ void f2fs_register_inmem_page(struct inode *inode, struct page *page)
 - list_add_tail(&fi->inmem_ilist, &sbi->inode_list[ATOMIC_FILE]);
 - spin_unlock(&sbi->inode_lock[ATOMIC_FILE]);
 - inc_page_count(F2FS_I_SB(inode), F2FS_INMEM_PAGES);
 - + if (F2FS_I_SB(inode)->sec_stat.max_inmem_pages < get_pages(sbi, F2FS_INMEM_PAGES))
 - + F2FS_I_SB(inode)->sec_stat.max_inmem_pages = get_pages(sbi, F2FS_INMEM_PAGES);
 - mutex_unlock(&fi->inmem_lock);
 - trace_f2fs_register_inmem_page(page, INMEM);
 - @@ -286,6 +296,8 @@ void f2fs_drop_inmem_pages_all(struct f2fs_sb_info *sbi, bool gc_failure)
 - struct list_head *head = &sbi->inode_list[ATOMIC_FILE];
 - struct inode *inode;
 - struct f2fs_inode_info *fi;
 - +
 - + sbi->sec_stat.drop_inmem_all++;
 - next:
 - spin_lock(&sbi->inode_lock[ATOMIC_FILE]);
 - if (list_empty(head)) {
 - @@ -294,6 +306,7 @@ void f2fs_drop_inmem_pages_all(struct f2fs_sb_info *sbi, bool gc_failure)
 - }
 - fi = list_first_entry(head, struct f2fs_inode_info, inmem_ilist);
 - inode = igrab(&fi->vfs_inode);
 - + sbi->sec_stat.drop_inmem_files++;
 - spin_unlock(&sbi->inode_lock[ATOMIC_FILE]);
 - if (inode) {
 - @@ -535,6 +548,7 @@ void f2fs_balance_fs_bg(struct f2fs_sb_info *sbi)
 - }
 - f2fs_sync_fs(sbi->sb, true);
 - stat_inc_bg_cp_count(sbi->stat_info);
 - + sbi->sec_stat.cp_cnt[STAT_CP_BG]++;
 - }
 - }
 - @@ -915,6 +929,7 @@ static struct discard_cmd *__create_discard_cmd(struct f2fs_sb_info *sbi,
 - dc->bio_ref = 0;
 - atomic_inc(&dcc->discard_cmd_cnt);
 - dcc->undiscard_blks += len;
 - + update_max_undiscard_blks(sbi);
 - return dc;
 - }
 - @@ -1033,13 +1048,18 @@ static void __init_discard_policy(struct f2fs_sb_info *sbi,
 - dpolicy->granularity = granularity;
 - dpolicy->max_requests = DEF_MAX_DISCARD_REQUEST;
 - - dpolicy->io_aware_gran = MAX_PLIST_NUM;
 - + dpolicy->io_aware_gran = MAX_PLIST_NUM - 1;
 - + dpolicy->timeout = 0;
 - if (discard_type == DPOLICY_BG) {
 - dpolicy->min_interval = DEF_MIN_DISCARD_ISSUE_TIME;
 - dpolicy->mid_interval = DEF_MID_DISCARD_ISSUE_TIME;
 - dpolicy->max_interval = DEF_MAX_DISCARD_ISSUE_TIME;
 - +#ifdef CONFIG_F2FS_CHECK_FS
 - dpolicy->io_aware = true;
 - +#else
 - + dpolicy->io_aware = false;
 - +#endif
 - dpolicy->sync = false;
 - dpolicy->ordered = true;
 - if (utilization(sbi) > DEF_DISCARD_URGENT_UTIL) {
 - @@ -1222,6 +1242,7 @@ static void __punch_discard_cmd(struct f2fs_sb_info *sbi,
 - if (blkaddr > di.lstart) {
 - dc->len = blkaddr - dc->lstart;
 - dcc->undiscard_blks += dc->len;
 - + update_max_undiscard_blks(sbi);
 - __relocate_discard_cmd(dcc, dc);
 - modified = true;
 - }
 - @@ -1237,6 +1258,7 @@ static void __punch_discard_cmd(struct f2fs_sb_info *sbi,
 - dc->len--;
 - dc->start++;
 - dcc->undiscard_blks += dc->len;
 - + update_max_undiscard_blks(sbi);
 - __relocate_discard_cmd(dcc, dc);
 - }
 - }
 - @@ -1299,6 +1321,7 @@ static void __update_discard_tree_range(struct f2fs_sb_info *sbi,
 - max_discard_blocks)) {
 - prev_dc->di.len += di.len;
 - dcc->undiscard_blks += di.len;
 - + update_max_undiscard_blks(sbi);
 - __relocate_discard_cmd(dcc, prev_dc);
 - di = prev_dc->di;
 - tdc = prev_dc;
 - @@ -1313,6 +1336,7 @@ static void __update_discard_tree_range(struct f2fs_sb_info *sbi,
 - next_dc->di.len += di.len;
 - next_dc->di.start = di.start;
 - dcc->undiscard_blks += di.len;
 - + update_max_undiscard_blks(sbi);
 - __relocate_discard_cmd(dcc, next_dc);
 - if (tdc)
 - __remove_discard_cmd(sbi, tdc);
 - @@ -1421,11 +1445,18 @@ static int __issue_discard_cmd(struct f2fs_sb_info *sbi,
 - int i, issued = 0;
 - bool io_interrupted = false;
 - + if (dpolicy->timeout != 0)
 - + f2fs_update_time(sbi, dpolicy->timeout);
 - +
 - for (i = MAX_PLIST_NUM - 1; i >= 0; i--) {
 - + if (dpolicy->timeout != 0 &&
 - + f2fs_time_over(sbi, dpolicy->timeout))
 - + break;
 - +
 - if (i + 1 < dpolicy->granularity)
 - break;
 - - if (i < DEFAULT_DISCARD_GRANULARITY && dpolicy->ordered)
 - + if (i + 1 < DEFAULT_DISCARD_GRANULARITY && dpolicy->ordered)
 - return __issue_discard_cmd_orderly(sbi, dpolicy);
 - pend_list = &dcc->pend_list[i];
 - @@ -1608,7 +1639,7 @@ void f2fs_stop_discard_thread(struct f2fs_sb_info *sbi)
 - }
 - /* This comes from f2fs_put_super */
 - -bool f2fs_wait_discard_bios(struct f2fs_sb_info *sbi)
 - +bool f2fs_issue_discard_timeout(struct f2fs_sb_info *sbi)
 - {
 - struct discard_cmd_control *dcc = SM_I(sbi)->dcc_info;
 - struct discard_policy dpolicy;
 - @@ -1616,6 +1647,7 @@ bool f2fs_wait_discard_bios(struct f2fs_sb_info *sbi)
 - __init_discard_policy(sbi, &dpolicy, DPOLICY_UMOUNT,
 - dcc->discard_granularity);
 - + dpolicy.timeout = UMOUNT_DISCARD_TIMEOUT;
 - __issue_discard_cmd(sbi, &dpolicy);
 - dropped = __drop_discard_cmd(sbi);
 - @@ -2516,6 +2548,13 @@ static void change_curseg(struct f2fs_sb_info *sbi, int type)
 - sum_page = f2fs_get_sum_page(sbi, new_segno);
 - f2fs_bug_on(sbi, IS_ERR(sum_page));
 - +
 - + /* W/A - prevent panic while shutdown */
 - + if (unlikely(ignore_fs_panic && IS_ERR(sum_page))) {
 - + //pr_err("%s: Ignore panic err=%ld\n", __func__, PTR_ERR(sum_page));
 - + return;
 - + }
 - +
 - sum_node = (struct f2fs_summary_block *)page_address(sum_page);
 - memcpy(curseg->sum_blk, sum_node, SUM_ENTRY_SIZE);
 - f2fs_put_page(sum_page, 1);
 - @@ -2597,6 +2636,7 @@ static void allocate_segment_by_default(struct f2fs_sb_info *sbi,
 - new_curseg(sbi, type, false);
 - stat_inc_seg_type(sbi, curseg);
 - + sbi->sec_stat.alloc_seg_type[curseg->alloc_type]++;
 - }
 - void f2fs_allocate_new_segments(struct f2fs_sb_info *sbi)
 - @@ -2773,10 +2813,10 @@ int f2fs_trim_fs(struct f2fs_sb_info *sbi, struct fstrim_range *range)
 - __init_discard_policy(sbi, &dpolicy, DPOLICY_FSTRIM, cpc.trim_minlen);
 - trimmed = __issue_discard_cmd_range(sbi, &dpolicy,
 - - start_block, end_block);
 - + start_block, end_block);
 - trimmed += __wait_discard_cmd_range(sbi, &dpolicy,
 - - start_block, end_block);
 - + start_block, end_block);
 - out:
 - if (!err)
 - range->len = F2FS_BLK_TO_BYTES(trimmed);
 - @@ -2998,7 +3038,7 @@ void f2fs_allocate_data_block(struct f2fs_sb_info *sbi, struct page *page,
 - __refresh_next_blkoff(sbi, curseg);
 - stat_inc_block_count(sbi, curseg);
 - -
 - + sbi->sec_stat.alloc_blk_count[curseg->alloc_type]++;
 - /*
 - * SIT information should be updated before segment allocation,
 - * since SSR needs latest valid block information.
 - @@ -3155,6 +3195,7 @@ int f2fs_inplace_write_data(struct f2fs_io_info *fio)
 - GET_SEGNO(sbi, fio->new_blkaddr))->type));
 - stat_inc_inplace_blocks(fio->sbi);
 - + atomic64_inc(&(sbi->sec_stat.inplace_count));
 - err = f2fs_submit_page_bio(fio);
 - if (!err)
 - @@ -3748,6 +3789,7 @@ void f2fs_flush_sit_entries(struct f2fs_sb_info *sbi, struct cp_control *cpc)
 - unsigned int end = min(start_segno + SIT_ENTRY_PER_BLOCK,
 - (unsigned long)MAIN_SEGS(sbi));
 - unsigned int segno = start_segno;
 - + int err = 0;
 - if (to_journal &&
 - !__has_cursum_space(journal, ses->entry_cnt, SIT_JOURNAL))
 - @@ -3785,16 +3827,16 @@ void f2fs_flush_sit_entries(struct f2fs_sb_info *sbi, struct cp_control *cpc)
 - cpu_to_le32(segno);
 - seg_info_to_raw_sit(se,
 - &sit_in_journal(journal, offset));
 - - check_block_count(sbi, segno,
 - + err = check_block_count(sbi, segno,
 - &sit_in_journal(journal, offset));
 - } else {
 - sit_offset = SIT_ENTRY_OFFSET(sit_i, segno);
 - seg_info_to_raw_sit(se,
 - &raw_sit->entries[sit_offset]);
 - - check_block_count(sbi, segno,
 - + err = check_block_count(sbi, segno,
 - &raw_sit->entries[sit_offset]);
 - }
 - -
 - + f2fs_bug_on(sbi, err);
 - __clear_bit(segno, bitmap);
 - sit_i->dirty_sentries--;
 - ses->entry_cnt--;
 - @@ -4016,8 +4058,11 @@ static int build_sit_entries(struct f2fs_sb_info *sbi)
 - f2fs_put_page(page, 1);
 - err = check_block_count(sbi, start, &sit);
 - - if (err)
 - + if (err) {
 - + print_block_data(sbi->sb, current_sit_addr(sbi, start),
 - + page_address(page), 0, F2FS_BLKSIZE);
 - return err;
 - + }
 - seg_info_from_raw_sit(se, &sit);
 - if (IS_NODESEG(se->type))
 - total_node_blocks += se->valid_blocks;
 - @@ -4064,8 +4109,11 @@ static int build_sit_entries(struct f2fs_sb_info *sbi)
 - total_node_blocks -= old_valid_blocks;
 - err = check_block_count(sbi, start, &sit);
 - - if (err)
 - + if (err) {
 - + print_block_data(sbi->sb, 0, (void *)&sit, 0,
 - + sizeof(struct f2fs_sit_entry));
 - break;
 - + }
 - seg_info_from_raw_sit(se, &sit);
 - if (IS_NODESEG(se->type))
 - total_node_blocks += se->valid_blocks;
 - @@ -4154,6 +4202,13 @@ static int init_victim_secmap(struct f2fs_sb_info *sbi)
 - dirty_i->victim_secmap = f2fs_kvzalloc(sbi, bitmap_size, GFP_KERNEL);
 - if (!dirty_i->victim_secmap)
 - return -ENOMEM;
 - +
 - + /* W/A for FG_GC failure due to Atomic Write File */
 - + dirty_i->blacklist_victim_secmap = f2fs_kvzalloc(sbi, bitmap_size,
 - + GFP_KERNEL);
 - + if (!dirty_i->blacklist_victim_secmap)
 - + return -ENOMEM;
 - +
 - return 0;
 - }
 - @@ -4298,6 +4353,9 @@ static void destroy_victim_secmap(struct f2fs_sb_info *sbi)
 - {
 - struct dirty_seglist_info *dirty_i = DIRTY_I(sbi);
 - kvfree(dirty_i->victim_secmap);
 - +
 - + /* W/A for FG_GC failure due to Atomic Write File */
 - + kvfree(dirty_i->blacklist_victim_secmap);
 - }
 - static void destroy_dirty_segmap(struct f2fs_sb_info *sbi)
 - diff --git a/fs/f2fs/segment.h b/fs/f2fs/segment.h
 - index ab3465faddf13..00ea8f3decada 100644
 - --- a/fs/f2fs/segment.h
 - +++ b/fs/f2fs/segment.h
 - @@ -277,6 +277,9 @@ struct dirty_seglist_info {
 - struct mutex seglist_lock; /* lock for segment bitmaps */
 - int nr_dirty[NR_DIRTY_TYPE]; /* # of dirty segments */
 - unsigned long *victim_secmap; /* background GC victims */
 - +
 - + /* W/A for FG_GC failure due to Atomic Write File */
 - + unsigned long *blacklist_victim_secmap; /* GC Failed Bitmap */
 - };
 - /* victim selection function for cleaning and SSR */
 - diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
 - index ec91486957644..eb86d6b680fbd 100644
 - --- a/fs/f2fs/super.c
 - +++ b/fs/f2fs/super.c
 - @@ -34,6 +34,10 @@
 - #define CREATE_TRACE_POINTS
 - #include <trace/events/f2fs.h>
 - +#ifdef CONFIG_FSCRYPT_SDP
 - +#include <linux/fscrypto_sdp_cache.h>
 - +#endif
 - +
 - static struct kmem_cache *f2fs_inode_cachep;
 - #ifdef CONFIG_F2FS_FAULT_INJECTION
 - @@ -110,6 +114,7 @@ enum {
 - Opt_noinline_data,
 - Opt_data_flush,
 - Opt_reserve_root,
 - + Opt_reserve_core,
 - Opt_resgid,
 - Opt_resuid,
 - Opt_mode,
 - @@ -169,6 +174,7 @@ static match_table_t f2fs_tokens = {
 - {Opt_noinline_data, "noinline_data"},
 - {Opt_data_flush, "data_flush"},
 - {Opt_reserve_root, "reserve_root=%u"},
 - + {Opt_reserve_core, "reserve_core=%u"},
 - {Opt_resgid, "resgid=%u"},
 - {Opt_resuid, "resuid=%u"},
 - {Opt_mode, "mode=%s"},
 - @@ -211,11 +217,107 @@ void f2fs_msg(struct super_block *sb, const char *level, const char *fmt, ...)
 - va_end(args);
 - }
 - +void f2fs_set_sb_extra_flag(struct f2fs_sb_info *sbi, int flag)
 - +{
 - + struct f2fs_super_block *fsb = sbi->raw_super;
 - + unsigned long long extra_flag_blk_no = le32_to_cpu(fsb->cp_blkaddr) - 1;
 - +
 - + struct buffer_head *bh;
 - + struct f2fs_sb_extra_flag_blk *extra_blk;
 - +
 - + if (extra_flag_blk_no < 2) {
 - + // 0 -> SB 0, 1 -> SB 1,
 - + // 2 or more : RSVD
 - + f2fs_msg(sbi->sb, KERN_WARNING,
 - + "extra_flag: No free blks for extra flags");
 - + return;
 - + }
 - +
 - + bh = sb_bread(sbi->sb, (sector_t)extra_flag_blk_no);
 - + if(!bh) {
 - + f2fs_msg(sbi->sb, KERN_WARNING,
 - + "extra_flag: Fail to allocate buffer_head");
 - + return;
 - + }
 - +
 - + lock_buffer(bh);
 - + extra_blk = (struct f2fs_sb_extra_flag_blk*)bh->b_data;
 - +
 - + switch(flag) {
 - + case F2FS_SEC_EXTRA_FSCK_MAGIC:
 - + if (extra_blk->need_fsck ==
 - + cpu_to_le32(F2FS_SEC_EXTRA_FSCK_MAGIC))
 - + goto out_unlock;
 - +
 - + extra_blk->need_fsck = cpu_to_le32(F2FS_SEC_EXTRA_FSCK_MAGIC);
 - + break;
 - + default:
 - + f2fs_msg(sbi->sb, KERN_WARNING,
 - + "extra_flag: Undefined flag - %x", flag);
 - + goto out_unlock;
 - + }
 - +
 - + set_buffer_uptodate(bh);
 - + set_buffer_dirty(bh);
 - + unlock_buffer(bh);
 - +
 - + if (__sync_dirty_buffer(bh, REQ_SYNC | REQ_FUA))
 - + f2fs_msg(sbi->sb, KERN_WARNING, "extra_flag: EIO");
 - +
 - + brelse(bh);
 - +
 - + return;
 - +
 - +out_unlock:
 - + unlock_buffer(bh);
 - + brelse(bh);
 - +
 - + return;
 - +}
 - +
 - +void f2fs_get_fsck_stat(struct f2fs_sb_info *sbi)
 - +{
 - + struct f2fs_super_block *fsb = sbi->raw_super;
 - + unsigned long long extra_flag_blk_no = le32_to_cpu(fsb->cp_blkaddr) - 1;
 - +
 - + struct buffer_head *bh;
 - + struct f2fs_sb_extra_flag_blk *extra_blk;
 - +
 - + if (extra_flag_blk_no < 2) {
 - + f2fs_msg(sbi->sb, KERN_WARNING,
 - + "extra_flag: No free blks for extra flags");
 - + return;
 - + }
 - +
 - + bh = sb_bread(sbi->sb, (sector_t)extra_flag_blk_no);
 - + if (!bh) {
 - + f2fs_msg(sbi->sb, KERN_WARNING,
 - + "extra_flag: Fail to allocate buffer_head");
 - + return;
 - + }
 - +
 - + extra_blk = (struct f2fs_sb_extra_flag_blk*)bh->b_data;
 - + sbi->sec_fsck_stat.fsck_elapsed_time =
 - + le64_to_cpu(extra_blk->fsck_elapsed_time);
 - + sbi->sec_fsck_stat.fsck_read_bytes =
 - + le64_to_cpu(extra_blk->fsck_read_bytes);
 - + sbi->sec_fsck_stat.fsck_written_bytes =
 - + le64_to_cpu(extra_blk->fsck_written_bytes);
 - + sbi->sec_fsck_stat.fsck_exit_code =
 - + le32_to_cpu(extra_blk->fsck_exit_code);
 - + sbi->sec_fsck_stat.valid_node_count =
 - + le32_to_cpu(extra_blk->valid_node_count);
 - + sbi->sec_fsck_stat.valid_inode_count =
 - + le32_to_cpu(extra_blk->valid_inode_count);
 - +
 - + brelse(bh);
 - +}
 - +
 - static inline void limit_reserve_root(struct f2fs_sb_info *sbi)
 - {
 - - block_t limit = (sbi->user_block_count << 1) / 1000;
 - + block_t limit = sbi->user_block_count / 100;
 - - /* limit is 0.2% */
 - + /* limit is 1.0% */
 - if (test_opt(sbi, RESERVE_ROOT) &&
 - F2FS_OPTION(sbi).root_reserved_blocks > limit) {
 - F2FS_OPTION(sbi).root_reserved_blocks = limit;
 - @@ -223,17 +325,26 @@ static inline void limit_reserve_root(struct f2fs_sb_info *sbi)
 - "Reduce reserved blocks for root = %u",
 - F2FS_OPTION(sbi).root_reserved_blocks);
 - }
 - + if (test_opt(sbi, RESERVE_ROOT) &&
 - + F2FS_OPTION(sbi).core_reserved_blocks > limit) {
 - + F2FS_OPTION(sbi).core_reserved_blocks = limit;
 - + f2fs_msg(sbi->sb, KERN_INFO,
 - + "Reduce reserved blocks for core = %u",
 - + F2FS_OPTION(sbi).core_reserved_blocks);
 - + }
 - if (!test_opt(sbi, RESERVE_ROOT) &&
 - (!uid_eq(F2FS_OPTION(sbi).s_resuid,
 - make_kuid(&init_user_ns, F2FS_DEF_RESUID)) ||
 - !gid_eq(F2FS_OPTION(sbi).s_resgid,
 - - make_kgid(&init_user_ns, F2FS_DEF_RESGID))))
 - + make_kgid(&init_user_ns, F2FS_DEF_RESGID)) ||
 - + F2FS_OPTION(sbi).core_reserved_blocks != 0))
 - f2fs_msg(sbi->sb, KERN_INFO,
 - - "Ignore s_resuid=%u, s_resgid=%u w/o reserve_root",
 - + "Ignore s_resuid=%u, s_resgid=%u reserve_core=%u w/o reserve_root",
 - from_kuid_munged(&init_user_ns,
 - F2FS_OPTION(sbi).s_resuid),
 - from_kgid_munged(&init_user_ns,
 - - F2FS_OPTION(sbi).s_resgid));
 - + F2FS_OPTION(sbi).s_resgid),
 - + F2FS_OPTION(sbi).core_reserved_blocks);
 - }
 - static void init_once(void *foo)
 - @@ -537,6 +648,11 @@ static int parse_options(struct super_block *sb, char *options)
 - set_opt(sbi, RESERVE_ROOT);
 - }
 - break;
 - + case Opt_reserve_core:
 - + if (args->from && match_int(args, &arg))
 - + return -EINVAL;
 - + F2FS_OPTION(sbi).core_reserved_blocks = arg;
 - + break;
 - case Opt_resuid:
 - if (args->from && match_int(args, &arg))
 - return -EINVAL;
 - @@ -871,6 +987,9 @@ static struct inode *f2fs_alloc_inode(struct super_block *sb)
 - init_once((void *) fi);
 - /* Initialize f2fs-specific inode info */
 - + /* F2FS doesn't write value of i_version to disk and
 - + it will be reinitialize after a reboot.*/
 - + fi->vfs_inode.i_version = 1;
 - atomic_set(&fi->dirty_pages, 0);
 - init_rwsem(&fi->i_sem);
 - INIT_LIST_HEAD(&fi->dirty_list);
 - @@ -927,6 +1046,12 @@ static int f2fs_drop_inode(struct inode *inode)
 - return 0;
 - }
 - ret = generic_drop_inode(inode);
 - +#ifdef CONFIG_FSCRYPT_SDP
 - + if (!ret && fscrypt_sdp_is_locked_sensitive_inode(inode)) {
 - + fscrypt_sdp_drop_inode(inode);
 - + ret = 1;
 - + }
 - +#endif
 - trace_f2fs_drop_inode(inode, ret);
 - return ret;
 - }
 - @@ -1048,7 +1173,7 @@ static void f2fs_put_super(struct super_block *sb)
 - }
 - /* be sure to wait for any on-going discard commands */
 - - dropped = f2fs_wait_discard_bios(sbi);
 - + dropped = f2fs_issue_discard_timeout(sbi);
 - if ((f2fs_hw_support_discard(sbi) || f2fs_hw_should_discard(sbi)) &&
 - !sbi->discard_blks && !dropped) {
 - @@ -1078,7 +1203,10 @@ static void f2fs_put_super(struct super_block *sb)
 - f2fs_bug_on(sbi, sbi->fsync_node_num);
 - iput(sbi->node_inode);
 - + sbi->node_inode = NULL;
 - +
 - iput(sbi->meta_inode);
 - + sbi->meta_inode = NULL;
 - /* destroy f2fs internal modules */
 - f2fs_destroy_node_manager(sbi);
 - @@ -1218,9 +1346,11 @@ static int f2fs_statfs(struct dentry *dentry, struct kstatfs *buf)
 - else
 - buf->f_bfree -= sbi->unusable_block_count;
 - - if (buf->f_bfree > F2FS_OPTION(sbi).root_reserved_blocks)
 - + if (buf->f_bfree > F2FS_OPTION(sbi).root_reserved_blocks +
 - + F2FS_OPTION(sbi).core_reserved_blocks)
 - buf->f_bavail = buf->f_bfree -
 - - F2FS_OPTION(sbi).root_reserved_blocks;
 - + F2FS_OPTION(sbi).root_reserved_blocks -
 - + F2FS_OPTION(sbi).core_reserved_blocks;
 - else
 - buf->f_bavail = 0;
 - @@ -1355,8 +1485,9 @@ static int f2fs_show_options(struct seq_file *seq, struct dentry *root)
 - seq_puts(seq, "lfs");
 - seq_printf(seq, ",active_logs=%u", F2FS_OPTION(sbi).active_logs);
 - if (test_opt(sbi, RESERVE_ROOT))
 - - seq_printf(seq, ",reserve_root=%u,resuid=%u,resgid=%u",
 - + seq_printf(seq, ",reserve_root=%u,reserve_core=%u,resuid=%u,resgid=%u",
 - F2FS_OPTION(sbi).root_reserved_blocks,
 - + F2FS_OPTION(sbi).core_reserved_blocks,
 - from_kuid_munged(&init_user_ns,
 - F2FS_OPTION(sbi).s_resuid),
 - from_kgid_munged(&init_user_ns,
 - @@ -1429,7 +1560,8 @@ static void default_options(struct f2fs_sb_info *sbi)
 - set_opt(sbi, NOHEAP);
 - sbi->sb->s_flags |= MS_LAZYTIME;
 - clear_opt(sbi, DISABLE_CHECKPOINT);
 - - set_opt(sbi, FLUSH_MERGE);
 - + /* P190412-00841 diable flush_merge by default */
 - + //set_opt(sbi, FLUSH_MERGE);
 - set_opt(sbi, DISCARD);
 - if (f2fs_sb_has_blkzoned(sbi->sb))
 - set_opt_mode(sbi, F2FS_MOUNT_LFS);
 - @@ -1457,19 +1589,16 @@ static int f2fs_disable_checkpoint(struct f2fs_sb_info *sbi)
 - sbi->sb->s_flags |= SB_ACTIVE;
 - - mutex_lock(&sbi->gc_mutex);
 - f2fs_update_time(sbi, DISABLE_TIME);
 - while (!f2fs_time_over(sbi, DISABLE_TIME)) {
 - + mutex_lock(&sbi->gc_mutex);
 - err = f2fs_gc(sbi, true, false, NULL_SEGNO);
 - if (err == -ENODATA)
 - break;
 - - if (err && err != -EAGAIN) {
 - - mutex_unlock(&sbi->gc_mutex);
 - + if (err && err != -EAGAIN)
 - return err;
 - - }
 - }
 - - mutex_unlock(&sbi->gc_mutex);
 - err = sync_filesystem(sbi->sb);
 - if (err)
 - @@ -1500,7 +1629,8 @@ static void f2fs_enable_checkpoint(struct f2fs_sb_info *sbi)
 - f2fs_sync_fs(sbi->sb, 1);
 - }
 - -static int f2fs_remount(struct super_block *sb, int *flags, char *data)
 - +static int f2fs_remount(struct vfsmount *mnt, struct super_block *sb,
 - + int *flags, char *data)
 - {
 - struct f2fs_sb_info *sbi = F2FS_SB(sb);
 - struct f2fs_mount_info org_mount_opt;
 - @@ -1567,15 +1697,18 @@ static int f2fs_remount(struct super_block *sb, int *flags, char *data)
 - #ifdef CONFIG_QUOTA
 - if (!f2fs_readonly(sb) && (*flags & MS_RDONLY)) {
 - - err = dquot_suspend(sb, -1);
 - - if (err < 0)
 - - goto restore_opts;
 - + if (!IS_ERR(mnt)) {
 - + err = dquot_suspend(sb, -1);
 - + if (err < 0)
 - + goto restore_opts;
 - + }
 - } else if (f2fs_readonly(sb) && !(*flags & SB_RDONLY)) {
 - /* dquot_resume needs RW */
 - sb->s_flags &= ~MS_RDONLY;
 - if (sb_any_quota_suspended(sb)) {
 - dquot_resume(sb, -1);
 - - } else if (f2fs_sb_has_quota_ino(sb)) {
 - + } else if (!sb_any_quota_loaded(sb) &&
 - + f2fs_sb_has_quota_ino(sb)) {
 - err = f2fs_enable_quotas(sb);
 - if (err)
 - goto restore_opts;
 - @@ -1659,6 +1792,8 @@ static int f2fs_remount(struct super_block *sb, int *flags, char *data)
 - limit_reserve_root(sbi);
 - *flags = (*flags & ~SB_LAZYTIME) | (sb->s_flags & SB_LAZYTIME);
 - + f2fs_msg(sb, KERN_NOTICE, "re-mounted. Opts: %s", data);
 - +
 - return 0;
 - restore_gc:
 - if (need_restart_gc) {
 - @@ -2151,7 +2286,7 @@ static const struct super_operations f2fs_sops = {
 - .freeze_fs = f2fs_freeze,
 - .unfreeze_fs = f2fs_unfreeze,
 - .statfs = f2fs_statfs,
 - - .remount_fs = f2fs_remount,
 - + .remount_fs2 = f2fs_remount,
 - };
 - #ifdef CONFIG_F2FS_FS_ENCRYPTION
 - @@ -2182,6 +2317,20 @@ static int f2fs_set_context(struct inode *inode, const void *ctx, size_t len,
 - ctx, len, fs_data, XATTR_CREATE);
 - }
 - +#if defined(CONFIG_DDAR) || defined(CONFIG_FSCRYPT_SDP)
 - +static int f2fs_get_knox_context(struct inode *inode, const char *name, void *val, size_t len)
 - +{
 - + return f2fs_getxattr(inode, F2FS_XATTR_INDEX_ENCRYPTION,
 - + name, val, len, NULL);
 - +}
 - +
 - +static int f2fs_set_knox_context(struct inode *inode, const char *name, const void *val, size_t len, void *fs_data)
 - +{
 - + return f2fs_setxattr(inode, F2FS_XATTR_INDEX_ENCRYPTION,
 - + name ? name : F2FS_XATTR_NAME_ENCRYPTION_CONTEXT, val, len, fs_data, 0);
 - +}
 - +#endif
 - +
 - static bool f2fs_dummy_context(struct inode *inode)
 - {
 - return DUMMY_ENCRYPTION_ENABLED(F2FS_I_SB(inode));
 - @@ -2191,6 +2340,13 @@ static const struct fscrypt_operations f2fs_cryptops = {
 - .key_prefix = "f2fs:",
 - .get_context = f2fs_get_context,
 - .set_context = f2fs_set_context,
 - +#if defined(CONFIG_DDAR) || defined(CONFIG_FSCRYPT_SDP)
 - + .get_knox_context = f2fs_get_knox_context,
 - + .set_knox_context = f2fs_set_knox_context,
 - +#endif
 - +#ifdef CONFIG_FS_INLINE_ENCRYPTION
 - + .get_dun = __fscrypt_make_dun,
 - +#endif
 - .dummy_context = f2fs_dummy_context,
 - .empty_dir = f2fs_empty_dir,
 - .max_namelen = F2FS_NAME_LEN,
 - @@ -2700,6 +2856,8 @@ static void init_sb_info(struct f2fs_sb_info *sbi)
 - sbi->interval_time[DISCARD_TIME] = DEF_IDLE_INTERVAL;
 - sbi->interval_time[GC_TIME] = DEF_IDLE_INTERVAL;
 - sbi->interval_time[DISABLE_TIME] = DEF_DISABLE_INTERVAL;
 - + sbi->interval_time[UMOUNT_DISCARD_TIMEOUT] =
 - + DEF_UMOUNT_DISCARD_TIMEOUT;
 - clear_sbi_flag(sbi, SBI_NEED_FSCK);
 - for (i = 0; i < NR_COUNT_TYPE; i++)
 - @@ -2814,7 +2972,7 @@ static int init_blkz_info(struct f2fs_sb_info *sbi, int devi)
 - */
 - static int read_raw_super_block(struct f2fs_sb_info *sbi,
 - struct f2fs_super_block **raw_super,
 - - int *valid_super_block, int *recovery)
 - + int *valid_super_block, int *recovery, bool verbose)
 - {
 - struct super_block *sb = sbi->sb;
 - int block;
 - @@ -2841,6 +2999,8 @@ static int read_raw_super_block(struct f2fs_sb_info *sbi,
 - "Can't find valid F2FS filesystem in %dth superblock",
 - block + 1);
 - err = -EINVAL;
 - + if (verbose)
 - + print_bh(sb, bh, 0, sb->s_blocksize);
 - brelse(bh);
 - continue;
 - }
 - @@ -3024,6 +3184,7 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent)
 - int err;
 - bool retry = true, need_fsck = false;
 - char *options = NULL;
 - + char *orig_data = kstrdup(data, GFP_KERNEL);
 - int recovery, i, valid_super_block;
 - struct curseg_info *seg_i;
 - @@ -3056,7 +3217,7 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent)
 - }
 - err = read_raw_super_block(sbi, &raw_super, &valid_super_block,
 - - &recovery);
 - + &recovery, retry);
 - if (err)
 - goto free_sbi;
 - @@ -3125,6 +3286,9 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent)
 - sb->s_time_gran = 1;
 - sb->s_flags = (sb->s_flags & ~MS_POSIXACL) |
 - (test_opt(sbi, POSIX_ACL) ? MS_POSIXACL : 0);
 - +#ifdef CONFIG_FIVE
 - + sb->s_flags |= SB_I_VERSION;
 - +#endif
 - memcpy(&sb->s_uuid, raw_super->uuid, sizeof(raw_super->uuid));
 - sb->s_iflags |= SB_I_CGROUPWB;
 - @@ -3382,8 +3546,10 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent)
 - f2fs_tuning_parameters(sbi);
 - - f2fs_msg(sbi->sb, KERN_NOTICE, "Mounted with checkpoint version = %llx",
 - - cur_cp_version(F2FS_CKPT(sbi)));
 - + f2fs_msg(sbi->sb, KERN_NOTICE, "Mounted with checkpoint version = %llx"
 - + "Opts: %s", cur_cp_version(F2FS_CKPT(sbi)), orig_data);
 - + kfree(orig_data);
 - +
 - f2fs_update_time(sbi, CP_TIME);
 - f2fs_update_time(sbi, REQ_TIME);
 - return 0;
 - @@ -3411,6 +3577,7 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent)
 - f2fs_release_ino_entry(sbi, true);
 - truncate_inode_pages_final(NODE_MAPPING(sbi));
 - iput(sbi->node_inode);
 - + sbi->node_inode = NULL;
 - free_nm:
 - f2fs_destroy_node_manager(sbi);
 - free_sm:
 - @@ -3421,6 +3588,7 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent)
 - free_meta_inode:
 - make_bad_inode(sbi->meta_inode);
 - iput(sbi->meta_inode);
 - + sbi->meta_inode = NULL;
 - free_io_dummy:
 - mempool_destroy(sbi->write_io_dummy);
 - free_percpu:
 - @@ -3447,6 +3615,7 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent)
 - shrink_dcache_sb(sb);
 - goto try_onemore;
 - }
 - + kfree(orig_data);
 - return err;
 - }
 - diff --git a/fs/f2fs/sysfs.c b/fs/f2fs/sysfs.c
 - index db89741b219b1..cb145c09a899e 100644
 - --- a/fs/f2fs/sysfs.c
 - +++ b/fs/f2fs/sysfs.c
 - @@ -10,6 +10,7 @@
 - #include <linux/proc_fs.h>
 - #include <linux/f2fs_fs.h>
 - #include <linux/seq_file.h>
 - +#include <linux/statfs.h>
 - #include "f2fs.h"
 - #include "segment.h"
 - @@ -81,6 +82,38 @@ static ssize_t lifetime_write_kbytes_show(struct f2fs_attr *a,
 - BD_PART_WRITTEN(sbi)));
 - }
 - +static ssize_t sec_fs_stat_show(struct f2fs_attr *a,
 - + struct f2fs_sb_info *sbi, char *buf)
 - +{
 - + struct dentry *root = sbi->sb->s_root;
 - + struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi);
 - + struct kstatfs statbuf;
 - + int ret;
 - +
 - + if (!root->d_sb->s_op->statfs)
 - + goto errout;
 - +
 - + ret = root->d_sb->s_op->statfs(root, &statbuf);
 - + if (ret)
 - + goto errout;
 - +
 - + return snprintf(buf, PAGE_SIZE, "\"%s\":\"%llu\",\"%s\":\"%llu\",\"%s\":\"%u\","
 - + "\"%s\":\"%llu\",\"%s\":\"%llu\",\"%s\":\"%u\",\"%s\":\"%u\"\n",
 - + "F_BLOCKS", statbuf.f_blocks,
 - + "F_BFREE", statbuf.f_bfree,
 - + "F_SFREE", free_sections(sbi),
 - + "F_FILES", statbuf.f_files,
 - + "F_FFREE", statbuf.f_ffree,
 - + "F_FUSED", ckpt->valid_inode_count,
 - + "F_NUSED", ckpt->valid_node_count);
 - +
 - +errout:
 - + return snprintf(buf, PAGE_SIZE, "\"%s\":\"%d\",\"%s\":\"%d\",\"%s\":\"%d\","
 - + "\"%s\":\"%d\",\"%s\":\"%d\",\"%s\":\"%d\",\"%s\":\"%d\"\n",
 - + "F_BLOCKS", 0, "F_BFREE", 0, "F_SFREE", 0, "F_FILES", 0,
 - + "F_FFREE", 0, "F_FUSED", 0, "F_NUSED", 0);
 - +}
 - +
 - static ssize_t features_show(struct f2fs_attr *a,
 - struct f2fs_sb_info *sbi, char *buf)
 - {
 - @@ -159,6 +192,80 @@ static ssize_t f2fs_sbi_show(struct f2fs_attr *a,
 - len += snprintf(buf + len, PAGE_SIZE - len, "%s\n",
 - extlist[i]);
 - return len;
 - + } else if (!strcmp(a->attr.name, "sec_gc_stat")) {
 - + return snprintf(buf, PAGE_SIZE, "\"%s\":\"%llu\",\"%s\":\"%llu\","
 - + "\"%s\":\"%llu\",\"%s\":\"%llu\",\"%s\":\"%llu\",\"%s\":\"%llu\","
 - + "\"%s\":\"%llu\",\"%s\":\"%llu\",\"%s\":\"%llu\",\"%s\":\"%llu\","
 - + "\"%s\":\"%llu\",\"%s\":\"%llu\"\n",
 - + "FGGC", sbi->sec_stat.gc_count[FG_GC],
 - + "FGGC_NSEG", sbi->sec_stat.gc_node_seg_count[FG_GC],
 - + "FGGC_NBLK", sbi->sec_stat.gc_node_blk_count[FG_GC],
 - + "FGGC_DSEG", sbi->sec_stat.gc_data_seg_count[FG_GC],
 - + "FGGC_DBLK", sbi->sec_stat.gc_data_blk_count[FG_GC],
 - + "FGGC_TTIME", sbi->sec_stat.gc_ttime[FG_GC],
 - + "BGGC", sbi->sec_stat.gc_count[BG_GC],
 - + "BGGC_NSEG", sbi->sec_stat.gc_node_seg_count[BG_GC],
 - + "BGGC_NBLK", sbi->sec_stat.gc_node_blk_count[BG_GC],
 - + "BGGC_DSEG", sbi->sec_stat.gc_data_seg_count[BG_GC],
 - + "BGGC_DBLK", sbi->sec_stat.gc_data_blk_count[BG_GC],
 - + "BGGC_TTIME", sbi->sec_stat.gc_ttime[BG_GC]);
 - + } else if (!strcmp(a->attr.name, "sec_io_stat")) {
 - + u64 kbytes_written = 0;
 - +
 - + if (sbi->sb->s_bdev->bd_part)
 - + kbytes_written = BD_PART_WRITTEN(sbi) -
 - + sbi->sec_stat.kwritten_byte;
 - +
 - + return snprintf(buf, PAGE_SIZE, "\"%s\":\"%llu\",\"%s\":\"%llu\","
 - + "\"%s\":\"%llu\",\"%s\":\"%llu\",\"%s\":\"%llu\",\"%s\":\"%llu\","
 - + "\"%s\":\"%llu\",\"%s\":\"%llu\",\"%s\":\"%llu\",\"%s\":\"%llu\","
 - + "\"%s\":\"%llu\",\"%s\":\"%llu\",\"%s\":\"%llu\",\"%s\":\"%llu\","
 - + "\"%s\":\"%llu\",\"%s\":\"%llu\",\"%s\":\"%llu\",\"%s\":\"%llu\","
 - + "\"%s\":\"%llu\",\"%s\":\"%llu\",\"%s\":\"%llu\",\"%s\":\"%u\","
 - + "\"%s\":\"%u\",\"%s\":\"%u\"\n",
 - + "CP", sbi->sec_stat.cp_cnt[STAT_CP_ALL],
 - + "CPBG", sbi->sec_stat.cp_cnt[STAT_CP_BG],
 - + "CPSYNC", sbi->sec_stat.cp_cnt[STAT_CP_FSYNC],
 - + "CPNONRE", sbi->sec_stat.cpr_cnt[CP_NON_REGULAR],
 - + "CPSBNEED", sbi->sec_stat.cpr_cnt[CP_SB_NEED_CP],
 - + "CPWPINO", sbi->sec_stat.cpr_cnt[CP_WRONG_PINO],
 - + "CP_MAX_INT", sbi->sec_stat.cp_max_interval,
 - + "LFSSEG", sbi->sec_stat.alloc_seg_type[LFS],
 - + "SSRSEG", sbi->sec_stat.alloc_seg_type[SSR],
 - + "LFSBLK", sbi->sec_stat.alloc_blk_count[LFS],
 - + "SSRBLK", sbi->sec_stat.alloc_blk_count[SSR],
 - + "IPU", (u64)atomic64_read(&sbi->sec_stat.inplace_count),
 - + "FSYNC", sbi->sec_stat.fsync_count,
 - + "FSYNC_MB", sbi->sec_stat.fsync_dirty_pages >> 8,
 - + "HOT_DATA", sbi->sec_stat.hot_file_written_blocks >> 8,
 - + "COLD_DATA", sbi->sec_stat.cold_file_written_blocks >> 8,
 - + "WARM_DATA", sbi->sec_stat.warm_file_written_blocks >> 8,
 - + "MAX_INMEM", sbi->sec_stat.max_inmem_pages,
 - + "DROP_INMEM", sbi->sec_stat.drop_inmem_all,
 - + "DROP_INMEMF", sbi->sec_stat.drop_inmem_files,
 - + "WRITE_MB", (u64)(kbytes_written >> 10),
 - + "FS_PERROR", sbi->sec_stat.fs_por_error,
 - + "FS_ERROR", sbi->sec_stat.fs_error,
 - + "MAX_UNDSCD", sbi->sec_stat.max_undiscard_blks);
 - + } else if (!strcmp(a->attr.name, "sec_fsck_stat")) {
 - + return snprintf(buf, PAGE_SIZE,
 - + "\"%s\":\"%llu\",\"%s\":\"%llu\",\"%s\":\"%llu\",\"%s\":\"%u\","
 - + "\"%s\":\"%u\",\"%s\":\"%u\"\n",
 - + "FSCK_RBYTES", sbi->sec_fsck_stat.fsck_read_bytes,
 - + "FSCK_WBYTES", sbi->sec_fsck_stat.fsck_written_bytes,
 - + "FSCK_TIME_MS", sbi->sec_fsck_stat.fsck_elapsed_time,
 - + "FSCK_EXIT", sbi->sec_fsck_stat.fsck_exit_code,
 - + "FSCK_VNODES", sbi->sec_fsck_stat.valid_node_count,
 - + "FSCK_VINODES", sbi->sec_fsck_stat.valid_inode_count);
 - + } else if (!strcmp(a->attr.name, "sec_defrag_stat")) {
 - + return snprintf(buf, PAGE_SIZE,
 - + "\"%s\":\"%u\",\"%s\":\"%u\",\"%s\":\"%u\",\"%s\":\"%u\",\"%s\":\"%u\",\"%s\":\"%u\"\n",
 - + "BESTEXT", sbi->s_sec_part_best_extents,
 - + "CUREXT", sbi->s_sec_part_current_extents,
 - + "DEFSCORE", sbi->s_sec_part_score,
 - + "DEFWRITE", sbi->s_sec_defrag_writes_kb,
 - + "NUMAPP", sbi->s_sec_num_apps,
 - + "CAPAPP", sbi->s_sec_capacity_apps_kb);
 - }
 - ui = (unsigned int *)(ptr + a->offset);
 - @@ -174,6 +281,7 @@ static ssize_t __sbi_store(struct f2fs_attr *a,
 - unsigned long t;
 - unsigned int *ui;
 - ssize_t ret;
 - + unsigned int i = 0;
 - ptr = __struct_ptr(sbi, a->struct_type);
 - if (!ptr)
 - @@ -212,6 +320,62 @@ static ssize_t __sbi_store(struct f2fs_attr *a,
 - out:
 - up_write(&sbi->sb_lock);
 - return ret ? ret : count;
 - + } else if(!strcmp(a->attr.name, "sec_gc_stat")) {
 - + sbi->sec_stat.gc_count[BG_GC] = 0;
 - + sbi->sec_stat.gc_count[FG_GC] = 0;
 - + sbi->sec_stat.gc_node_seg_count[BG_GC] = 0;
 - + sbi->sec_stat.gc_node_seg_count[FG_GC] = 0;
 - + sbi->sec_stat.gc_data_seg_count[BG_GC] = 0;
 - + sbi->sec_stat.gc_data_seg_count[FG_GC] = 0;
 - + sbi->sec_stat.gc_node_blk_count[BG_GC] = 0;
 - + sbi->sec_stat.gc_node_blk_count[FG_GC] = 0;
 - + sbi->sec_stat.gc_data_blk_count[BG_GC] = 0;
 - + sbi->sec_stat.gc_data_blk_count[FG_GC] = 0;
 - + sbi->sec_stat.gc_ttime[BG_GC] = 0;
 - + sbi->sec_stat.gc_ttime[FG_GC] = 0;
 - + return count;
 - + } else if (!strcmp(a->attr.name, "sec_io_stat")) {
 - + sbi->sec_stat.cp_cnt[STAT_CP_ALL] = 0;
 - + sbi->sec_stat.cp_cnt[STAT_CP_BG] = 0;
 - + sbi->sec_stat.cp_cnt[STAT_CP_FSYNC] = 0;
 - + for (i = 0; i < NR_CP_REASON; i++)
 - + sbi->sec_stat.cpr_cnt[i] = 0;
 - + sbi->sec_stat.cp_max_interval= 0;
 - + sbi->sec_stat.alloc_seg_type[LFS] = 0;
 - + sbi->sec_stat.alloc_seg_type[SSR] = 0;
 - + sbi->sec_stat.alloc_blk_count[LFS] = 0;
 - + sbi->sec_stat.alloc_blk_count[SSR] = 0;
 - + atomic64_set(&sbi->sec_stat.inplace_count, 0);
 - + sbi->sec_stat.fsync_count = 0;
 - + sbi->sec_stat.fsync_dirty_pages = 0;
 - + sbi->sec_stat.hot_file_written_blocks = 0;
 - + sbi->sec_stat.cold_file_written_blocks = 0;
 - + sbi->sec_stat.warm_file_written_blocks = 0;
 - + sbi->sec_stat.max_inmem_pages = 0;
 - + sbi->sec_stat.drop_inmem_all = 0;
 - + sbi->sec_stat.drop_inmem_files = 0;
 - + if (sbi->sb->s_bdev->bd_part)
 - + sbi->sec_stat.kwritten_byte = BD_PART_WRITTEN(sbi);
 - + sbi->sec_stat.fs_por_error = 0;
 - + sbi->sec_stat.fs_error = 0;
 - + sbi->sec_stat.max_undiscard_blks = 0;
 - + return count;
 - + } else if (!strcmp(a->attr.name, "sec_fsck_stat")) {
 - + sbi->sec_fsck_stat.fsck_read_bytes = 0;
 - + sbi->sec_fsck_stat.fsck_written_bytes = 0;
 - + sbi->sec_fsck_stat.fsck_elapsed_time = 0;
 - + sbi->sec_fsck_stat.fsck_exit_code = 0;
 - + sbi->sec_fsck_stat.valid_node_count = 0;
 - + sbi->sec_fsck_stat.valid_inode_count = 0;
 - + return count;
 - + } else if (!strcmp(a->attr.name, "sec_defrag_stat")) {
 - + sbi->s_sec_part_best_extents = 0;
 - + sbi->s_sec_part_current_extents = 0;
 - + sbi->s_sec_part_score = 0;
 - + sbi->s_sec_defrag_writes_kb = 0;
 - + sbi->s_sec_num_apps = 0;
 - + sbi->s_sec_capacity_apps_kb = 0;
 - + return count;
 - }
 - ui = (unsigned int *)(ptr + a->offset);
 - @@ -226,7 +390,8 @@ static ssize_t __sbi_store(struct f2fs_attr *a,
 - if (a->struct_type == RESERVED_BLOCKS) {
 - spin_lock(&sbi->stat_lock);
 - if (t > (unsigned long)(sbi->user_block_count -
 - - F2FS_OPTION(sbi).root_reserved_blocks)) {
 - + F2FS_OPTION(sbi).root_reserved_blocks -
 - + F2FS_OPTION(sbi).core_reserved_blocks)) {
 - spin_unlock(&sbi->stat_lock);
 - return -EINVAL;
 - }
 - @@ -412,6 +577,8 @@ F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, idle_interval, interval_time[REQ_TIME]);
 - F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, discard_idle_interval,
 - interval_time[DISCARD_TIME]);
 - F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, gc_idle_interval, interval_time[GC_TIME]);
 - +F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info,
 - + umount_discard_timeout, interval_time[UMOUNT_DISCARD_TIMEOUT]);
 - F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, iostat_enable, iostat_enable);
 - F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, readdir_ra, readdir_ra);
 - F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, gc_pin_file_thresh, gc_pin_file_threshold);
 - @@ -420,8 +587,19 @@ F2FS_RW_ATTR(F2FS_SBI, f2fs_super_block, extension_list, extension_list);
 - F2FS_RW_ATTR(FAULT_INFO_RATE, f2fs_fault_info, inject_rate, inject_rate);
 - F2FS_RW_ATTR(FAULT_INFO_TYPE, f2fs_fault_info, inject_type, inject_type);
 - #endif
 - +F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, sec_gc_stat, sec_stat);
 - +F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, sec_io_stat, sec_stat);
 - +F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, sec_fsck_stat, sec_fsck_stat);
 - +F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, sec_part_best_extents, s_sec_part_best_extents);
 - +F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, sec_part_current_extents, s_sec_part_current_extents);
 - +F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, sec_part_score, s_sec_part_score);
 - +F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, sec_defrag_writes_kb, s_sec_defrag_writes_kb);
 - +F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, sec_num_apps, s_sec_num_apps);
 - +F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, sec_capacity_apps_kb, s_sec_capacity_apps_kb);
 - +F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, sec_defrag_stat, s_sec_part_best_extents);
 - F2FS_GENERAL_RO_ATTR(dirty_segments);
 - F2FS_GENERAL_RO_ATTR(lifetime_write_kbytes);
 - +F2FS_GENERAL_RO_ATTR(sec_fs_stat);
 - F2FS_GENERAL_RO_ATTR(features);
 - F2FS_GENERAL_RO_ATTR(current_reserved_blocks);
 - @@ -468,16 +646,28 @@ static struct attribute *f2fs_attrs[] = {
 - ATTR_LIST(idle_interval),
 - ATTR_LIST(discard_idle_interval),
 - ATTR_LIST(gc_idle_interval),
 - + ATTR_LIST(umount_discard_timeout),
 - ATTR_LIST(iostat_enable),
 - ATTR_LIST(readdir_ra),
 - ATTR_LIST(gc_pin_file_thresh),
 - ATTR_LIST(extension_list),
 - + ATTR_LIST(sec_gc_stat),
 - + ATTR_LIST(sec_io_stat),
 - + ATTR_LIST(sec_fsck_stat),
 - + ATTR_LIST(sec_part_best_extents),
 - + ATTR_LIST(sec_part_current_extents),
 - + ATTR_LIST(sec_part_score),
 - + ATTR_LIST(sec_defrag_writes_kb),
 - + ATTR_LIST(sec_num_apps),
 - + ATTR_LIST(sec_capacity_apps_kb),
 - + ATTR_LIST(sec_defrag_stat),
 - #ifdef CONFIG_F2FS_FAULT_INJECTION
 - ATTR_LIST(inject_rate),
 - ATTR_LIST(inject_type),
 - #endif
 - ATTR_LIST(dirty_segments),
 - ATTR_LIST(lifetime_write_kbytes),
 - + ATTR_LIST(sec_fs_stat),
 - ATTR_LIST(features),
 - ATTR_LIST(reserved_blocks),
 - ATTR_LIST(current_reserved_blocks),
 - @@ -706,6 +896,10 @@ int f2fs_register_sysfs(struct f2fs_sb_info *sbi)
 - if (err)
 - return err;
 - + err = sysfs_create_link(&f2fs_kset.kobj, &sbi->s_kobj, "userdata");
 - + if (err)
 - + printk(KERN_ERR "Can not create sysfs link for userdata(%d)\n", err);
 - +
 - if (f2fs_proc_root)
 - sbi->s_proc = proc_mkdir(sb->s_id, f2fs_proc_root);
 - @@ -731,5 +925,6 @@ void f2fs_unregister_sysfs(struct f2fs_sb_info *sbi)
 - remove_proc_entry("victim_bits", sbi->s_proc);
 - remove_proc_entry(sbi->sb->s_id, f2fs_proc_root);
 - }
 - + sysfs_delete_link(&f2fs_kset.kobj, &sbi->s_kobj, "userdata");
 - kobject_del(&sbi->s_kobj);
 - }
 
Advertisement
 
                    Add Comment                
                
                        Please, Sign In to add comment