f2fs update for 6.11-rc1

It's a pretty small update including mostly minor bug fixes in zoned storage
 along with the large section support.
 
 Enhancement:
  - add support for FS_IOC_GETFSSYSFSPATH
  - enable atgc dynamically if conditions are met
  - use new ioprio Macro to get ckpt thread ioprio level
  - remove unreachable lazytime mount option parsing
 
 Bug fix:
  - fix null reference error when checking end of zone
  - fix start segno of large section
  - fix to cover read extent cache access with lock
  - don't dirty inode for readonly filesystem
  - allocate a new section if curseg is not the first seg in its zone
  - only fragment segment in the same section
  - truncate preallocated blocks in f2fs_file_open()
  - fix to avoid use SSR allocate when do defragment
  - fix to force buffered IO on inline_data inode
 
 And, it includes some minor code clean-ups, and sanity checks.
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCgAdFiEE00UqedjCtOrGVvQiQBSofoJIUNIFAmagGLkACgkQQBSofoJI
 UNLsvA//U1u2hr+VEmSIxZ+CcM8vBM7wmbuggdUikEW0uj07YpvovLikifV7p6kK
 00p/GsqIqNRsVcTxRI9wBTPiltJRei/w6K3EXnSGKgTPtq1QMSv/GKiBUUaYsRu0
 F6W5AqouTquDZz61/ULhMc7WvWqUIZ1m4QX/DMEUGPSnQ2+yIsnz/PT4ZXaKBH7K
 lIh4WiFAyKO6/UWftcGmnvPiqj4YvqFOhLLV/fgF/VY8IVcENrDH+8+SJM2NtT0F
 6gT0bN2Jscc8o43ejo6dlwc7+0qhmH7H2IOCC1XSYGCsveUYgqgKgpBP4ryKjZvt
 LrbYKaL+auGuJMcLYCG/6IDPl5xkJo3SuRE7YnJdeTNc3InC6BUr17pkmU8n5ib4
 xKSeH2XQXk/nu3l9srtKb87Zdwjr90GgvjEZwsCTe+6ihjJ7SGWfpvVLhm3pHale
 SHPSLaVGqTlqdrNLtfhtNEg6xcvUVxTPbqzoCAmS6onEZfv8BldtQDSea0Tuw7UG
 Ic4AbfJ/gVCKyCDw/QiV0B1n8GHsVIhlBXss2/xEuO2/2Pso8YFIAXCyH0kBXIN2
 0/VesfguJLBIGyyFZ2M5AGZehr5s1n2IThe+qGjeoHfNQz7Br+xBTc25VpowUenC
 nET3UoAmUkLFrItDMMqJbJ8DwW/Idei+YH/xnDZSKkz5rgHclsg=
 =4m67
 -----END PGP SIGNATURE-----

Merge tag 'f2fs-for-6.11-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/jaegeuk/f2fs

Pull f2fs updates from Jaegeuk Kim:
 "A pretty small update including mostly minor bug fixes in zoned
  storage along with the large section support.

  Enhancements:
   - add support for FS_IOC_GETFSSYSFSPATH
   - enable atgc dynamically if conditions are met
   - use new ioprio Macro to get ckpt thread ioprio level
   - remove unreachable lazytime mount option parsing

  Bug fixes:
   - fix null reference error when checking end of zone
   - fix start segno of large section
   - fix to cover read extent cache access with lock
   - don't dirty inode for readonly filesystem
   - allocate a new section if curseg is not the first seg in its zone
   - only fragment segment in the same section
   - truncate preallocated blocks in f2fs_file_open()
   - fix to avoid use SSR allocate when do defragment
   - fix to force buffered IO on inline_data inode

  And some minor code clean-ups and sanity checks"

* tag 'f2fs-for-6.11-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/jaegeuk/f2fs: (26 commits)
  f2fs: clean up addrs_per_{inode,block}()
  f2fs: clean up F2FS_I()
  f2fs: use meta inode for GC of COW file
  f2fs: use meta inode for GC of atomic file
  f2fs: only fragment segment in the same section
  f2fs: fix to update user block counts in block_operations()
  f2fs: remove unreachable lazytime mount option parsing
  f2fs: fix null reference error when checking end of zone
  f2fs: fix start segno of large section
  f2fs: remove redundant sanity check in sanity_check_inode()
  f2fs: assign CURSEG_ALL_DATA_ATGC if blkaddr is valid
  f2fs: fix to use mnt_{want,drop}_write_file replace file_{start,end}_wrtie
  f2fs: clean up set REQ_RAHEAD given rac
  f2fs: enable atgc dynamically if conditions are met
  f2fs: fix to truncate preallocated blocks in f2fs_file_open()
  f2fs: fix to cover read extent cache access with lock
  f2fs: fix return value of f2fs_convert_inline_inode()
  f2fs: use new ioprio Macro to get ckpt thread ioprio level
  f2fs: fix to don't dirty inode for readonly filesystem
  f2fs: fix to avoid use SSR allocate when do defragment
  ...
This commit is contained in:
Linus Torvalds 2024-07-23 15:21:19 -07:00
commit 5ad7ff8738
16 changed files with 330 additions and 227 deletions

View File

@ -1186,6 +1186,11 @@ static void __prepare_cp_block(struct f2fs_sb_info *sbi)
ckpt->valid_node_count = cpu_to_le32(valid_node_count(sbi));
ckpt->valid_inode_count = cpu_to_le32(valid_inode_count(sbi));
ckpt->next_free_nid = cpu_to_le32(last_nid);
/* update user_block_counts */
sbi->last_valid_block_count = sbi->total_valid_block_count;
percpu_counter_set(&sbi->alloc_valid_block_count, 0);
percpu_counter_set(&sbi->rf_node_block_count, 0);
}
static bool __need_flush_quota(struct f2fs_sb_info *sbi)
@ -1575,11 +1580,6 @@ static int do_checkpoint(struct f2fs_sb_info *sbi, struct cp_control *cpc)
start_blk += NR_CURSEG_NODE_TYPE;
}
/* update user_block_counts */
sbi->last_valid_block_count = sbi->total_valid_block_count;
percpu_counter_set(&sbi->alloc_valid_block_count, 0);
percpu_counter_set(&sbi->rf_node_block_count, 0);
/* Here, we have one bio having CP pack except cp pack 2 page */
f2fs_sync_meta_pages(sbi, META, LONG_MAX, FS_CP_META_IO);
/* Wait for all dirty meta pages to be submitted for IO */
@ -1718,6 +1718,7 @@ int f2fs_write_checkpoint(struct f2fs_sb_info *sbi, struct cp_control *cpc)
}
f2fs_restore_inmem_curseg(sbi);
f2fs_reinit_atgc_curseg(sbi);
stat_inc_cp_count(sbi);
stop:
unblock_operations(sbi);

View File

@ -1100,7 +1100,7 @@ static int prepare_compress_overwrite(struct compress_ctx *cc,
struct bio *bio = NULL;
ret = f2fs_read_multi_pages(cc, &bio, cc->cluster_size,
&last_block_in_bio, false, true);
&last_block_in_bio, NULL, true);
f2fs_put_rpages(cc);
f2fs_destroy_compress_ctx(cc, true);
if (ret)

View File

@ -925,6 +925,7 @@ int f2fs_merge_page_bio(struct f2fs_io_info *fio)
#ifdef CONFIG_BLK_DEV_ZONED
static bool is_end_zone_blkaddr(struct f2fs_sb_info *sbi, block_t blkaddr)
{
struct block_device *bdev = sbi->sb->s_bdev;
int devi = 0;
if (f2fs_is_multi_device(sbi)) {
@ -935,8 +936,9 @@ static bool is_end_zone_blkaddr(struct f2fs_sb_info *sbi, block_t blkaddr)
return false;
}
blkaddr -= FDEV(devi).start_blk;
bdev = FDEV(devi).bdev;
}
return bdev_is_zoned(FDEV(devi).bdev) &&
return bdev_is_zoned(bdev) &&
f2fs_blkz_is_seq(sbi, devi, blkaddr) &&
(blkaddr % sbi->blocks_per_blkz == sbi->blocks_per_blkz - 1);
}
@ -2067,12 +2069,17 @@ static inline loff_t f2fs_readpage_limit(struct inode *inode)
return i_size_read(inode);
}
static inline blk_opf_t f2fs_ra_op_flags(struct readahead_control *rac)
{
return rac ? REQ_RAHEAD : 0;
}
static int f2fs_read_single_page(struct inode *inode, struct folio *folio,
unsigned nr_pages,
struct f2fs_map_blocks *map,
struct bio **bio_ret,
sector_t *last_block_in_bio,
bool is_readahead)
struct readahead_control *rac)
{
struct bio *bio = *bio_ret;
const unsigned blocksize = blks_to_bytes(inode, 1);
@ -2148,7 +2155,7 @@ static int f2fs_read_single_page(struct inode *inode, struct folio *folio,
}
if (bio == NULL) {
bio = f2fs_grab_read_bio(inode, block_nr, nr_pages,
is_readahead ? REQ_RAHEAD : 0, index,
f2fs_ra_op_flags(rac), index,
false);
if (IS_ERR(bio)) {
ret = PTR_ERR(bio);
@ -2178,7 +2185,7 @@ static int f2fs_read_single_page(struct inode *inode, struct folio *folio,
#ifdef CONFIG_F2FS_FS_COMPRESSION
int f2fs_read_multi_pages(struct compress_ctx *cc, struct bio **bio_ret,
unsigned nr_pages, sector_t *last_block_in_bio,
bool is_readahead, bool for_write)
struct readahead_control *rac, bool for_write)
{
struct dnode_of_data dn;
struct inode *inode = cc->inode;
@ -2301,7 +2308,7 @@ int f2fs_read_multi_pages(struct compress_ctx *cc, struct bio **bio_ret,
if (!bio) {
bio = f2fs_grab_read_bio(inode, blkaddr, nr_pages,
is_readahead ? REQ_RAHEAD : 0,
f2fs_ra_op_flags(rac),
page->index, for_write);
if (IS_ERR(bio)) {
ret = PTR_ERR(bio);
@ -2399,7 +2406,7 @@ static int f2fs_mpage_readpages(struct inode *inode,
ret = f2fs_read_multi_pages(&cc, &bio,
max_nr_pages,
&last_block_in_bio,
rac != NULL, false);
rac, false);
f2fs_destroy_compress_ctx(&cc, false);
if (ret)
goto set_error_page;
@ -2449,7 +2456,7 @@ static int f2fs_mpage_readpages(struct inode *inode,
ret = f2fs_read_multi_pages(&cc, &bio,
max_nr_pages,
&last_block_in_bio,
rac != NULL, false);
rac, false);
f2fs_destroy_compress_ctx(&cc, false);
}
}
@ -2601,7 +2608,7 @@ bool f2fs_should_update_outplace(struct inode *inode, struct f2fs_io_info *fio)
return true;
if (IS_NOQUOTA(inode))
return true;
if (f2fs_is_atomic_file(inode))
if (f2fs_used_in_atomic_write(inode))
return true;
/* rewrite low ratio compress data w/ OPU mode to avoid fragmentation */
if (f2fs_compressed_file(inode) &&
@ -2688,7 +2695,7 @@ int f2fs_do_write_data_page(struct f2fs_io_info *fio)
}
/* wait for GCed page writeback via META_MAPPING */
if (fio->post_read)
if (fio->meta_gc)
f2fs_wait_on_block_writeback(inode, fio->old_blkaddr);
/*
@ -2783,7 +2790,7 @@ int f2fs_write_single_data_page(struct page *page, int *submitted,
.submitted = 0,
.compr_blocks = compr_blocks,
.need_lock = compr_blocks ? LOCK_DONE : LOCK_RETRY,
.post_read = f2fs_post_read_required(inode) ? 1 : 0,
.meta_gc = f2fs_meta_inode_gc_required(inode) ? 1 : 0,
.io_type = io_type,
.io_wbc = wbc,
.bio = bio,

View File

@ -19,33 +19,23 @@
#include "node.h"
#include <trace/events/f2fs.h>
bool sanity_check_extent_cache(struct inode *inode)
bool sanity_check_extent_cache(struct inode *inode, struct page *ipage)
{
struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
struct f2fs_inode_info *fi = F2FS_I(inode);
struct extent_tree *et = fi->extent_tree[EX_READ];
struct extent_info *ei;
struct f2fs_extent *i_ext = &F2FS_INODE(ipage)->i_ext;
struct extent_info ei;
if (!et)
get_read_extent_info(&ei, i_ext);
if (!ei.len)
return true;
ei = &et->largest;
if (!ei->len)
return true;
/* Let's drop, if checkpoint got corrupted. */
if (is_set_ckpt_flags(sbi, CP_ERROR_FLAG)) {
ei->len = 0;
et->largest_updated = true;
return true;
}
if (!f2fs_is_valid_blkaddr(sbi, ei->blk, DATA_GENERIC_ENHANCE) ||
!f2fs_is_valid_blkaddr(sbi, ei->blk + ei->len - 1,
if (!f2fs_is_valid_blkaddr(sbi, ei.blk, DATA_GENERIC_ENHANCE) ||
!f2fs_is_valid_blkaddr(sbi, ei.blk + ei.len - 1,
DATA_GENERIC_ENHANCE)) {
f2fs_warn(sbi, "%s: inode (ino=%lx) extent info [%u, %u, %u] is incorrect, run fsck to fix",
__func__, inode->i_ino,
ei->blk, ei->fofs, ei->len);
ei.blk, ei.fofs, ei.len);
return false;
}
return true;
@ -394,24 +384,22 @@ void f2fs_init_read_extent_tree(struct inode *inode, struct page *ipage)
if (!__may_extent_tree(inode, EX_READ)) {
/* drop largest read extent */
if (i_ext && i_ext->len) {
if (i_ext->len) {
f2fs_wait_on_page_writeback(ipage, NODE, true, true);
i_ext->len = 0;
set_page_dirty(ipage);
}
goto out;
set_inode_flag(inode, FI_NO_EXTENT);
return;
}
et = __grab_extent_tree(inode, EX_READ);
if (!i_ext || !i_ext->len)
goto out;
get_read_extent_info(&ei, i_ext);
write_lock(&et->lock);
if (atomic_read(&et->node_cnt))
goto unlock_out;
if (atomic_read(&et->node_cnt) || !ei.len)
goto skip;
en = __attach_extent_node(sbi, et, &ei, NULL,
&et->root.rb_root.rb_node, true);
@ -423,11 +411,13 @@ void f2fs_init_read_extent_tree(struct inode *inode, struct page *ipage)
list_add_tail(&en->list, &eti->extent_list);
spin_unlock(&eti->extent_lock);
}
unlock_out:
skip:
/* Let's drop, if checkpoint got corrupted. */
if (f2fs_cp_error(sbi)) {
et->largest.len = 0;
et->largest_updated = true;
}
write_unlock(&et->lock);
out:
if (!F2FS_I(inode)->extent_tree[EX_READ])
set_inode_flag(inode, FI_NO_EXTENT);
}
void f2fs_init_age_extent_tree(struct inode *inode)

View File

@ -803,6 +803,7 @@ enum {
FI_COW_FILE, /* indicate COW file */
FI_ATOMIC_COMMITTED, /* indicate atomic commit completed except disk sync */
FI_ATOMIC_REPLACE, /* indicate atomic replace */
FI_OPENED_FILE, /* indicate file has been opened */
FI_MAX, /* max flag, never be used */
};
@ -842,7 +843,11 @@ struct f2fs_inode_info {
struct task_struct *atomic_write_task; /* store atomic write task */
struct extent_tree *extent_tree[NR_EXTENT_CACHES];
/* cached extent_tree entry */
struct inode *cow_inode; /* copy-on-write inode for atomic write */
union {
struct inode *cow_inode; /* copy-on-write inode for atomic write */
struct inode *atomic_inode;
/* point to atomic_inode, available only for cow_inode */
};
/* avoid racing between foreground op and gc */
struct f2fs_rwsem i_gc_rwsem[2];
@ -1210,7 +1215,7 @@ struct f2fs_io_info {
unsigned int in_list:1; /* indicate fio is in io_list */
unsigned int is_por:1; /* indicate IO is from recovery or not */
unsigned int encrypted:1; /* indicate file is encrypted */
unsigned int post_read:1; /* require post read */
unsigned int meta_gc:1; /* require meta inode GC */
enum iostat_type io_type; /* io type */
struct writeback_control *io_wbc; /* writeback control */
struct bio **bio; /* bio for ipu */
@ -3222,21 +3227,15 @@ static inline bool f2fs_need_compress_data(struct inode *inode)
return false;
}
static inline unsigned int addrs_per_inode(struct inode *inode)
static inline unsigned int addrs_per_page(struct inode *inode,
bool is_inode)
{
unsigned int addrs = CUR_ADDRS_PER_INODE(inode) -
get_inline_xattr_addrs(inode);
unsigned int addrs = is_inode ? (CUR_ADDRS_PER_INODE(inode) -
get_inline_xattr_addrs(inode)) : DEF_ADDRS_PER_BLOCK;
if (!f2fs_compressed_file(inode))
return addrs;
return ALIGN_DOWN(addrs, F2FS_I(inode)->i_cluster_size);
}
static inline unsigned int addrs_per_block(struct inode *inode)
{
if (!f2fs_compressed_file(inode))
return DEF_ADDRS_PER_BLOCK;
return ALIGN_DOWN(DEF_ADDRS_PER_BLOCK, F2FS_I(inode)->i_cluster_size);
if (f2fs_compressed_file(inode))
return ALIGN_DOWN(addrs, F2FS_I(inode)->i_cluster_size);
return addrs;
}
static inline void *inline_xattr_addr(struct inode *inode, struct page *page)
@ -3706,6 +3705,7 @@ void f2fs_release_discard_addrs(struct f2fs_sb_info *sbi);
int f2fs_npages_for_summary_flush(struct f2fs_sb_info *sbi, bool for_ra);
bool f2fs_segment_has_free_slot(struct f2fs_sb_info *sbi, int segno);
int f2fs_init_inmem_curseg(struct f2fs_sb_info *sbi);
int f2fs_reinit_atgc_curseg(struct f2fs_sb_info *sbi);
void f2fs_save_inmem_curseg(struct f2fs_sb_info *sbi);
void f2fs_restore_inmem_curseg(struct f2fs_sb_info *sbi);
int f2fs_allocate_segment_for_resize(struct f2fs_sb_info *sbi, int type,
@ -4163,7 +4163,7 @@ extern struct kmem_cache *f2fs_inode_entry_slab;
* inline.c
*/
bool f2fs_may_inline_data(struct inode *inode);
bool f2fs_sanity_check_inline_data(struct inode *inode);
bool f2fs_sanity_check_inline_data(struct inode *inode, struct page *ipage);
bool f2fs_may_inline_dentry(struct inode *inode);
void f2fs_do_read_inline_data(struct folio *folio, struct page *ipage);
void f2fs_truncate_inline_inode(struct inode *inode,
@ -4204,7 +4204,7 @@ void f2fs_leave_shrinker(struct f2fs_sb_info *sbi);
/*
* extent_cache.c
*/
bool sanity_check_extent_cache(struct inode *inode);
bool sanity_check_extent_cache(struct inode *inode, struct page *ipage);
void f2fs_init_extent_tree(struct inode *inode);
void f2fs_drop_extent_tree(struct inode *inode);
void f2fs_destroy_extent_node(struct inode *inode);
@ -4275,6 +4275,16 @@ static inline bool f2fs_post_read_required(struct inode *inode)
f2fs_compressed_file(inode);
}
static inline bool f2fs_used_in_atomic_write(struct inode *inode)
{
return f2fs_is_atomic_file(inode) || f2fs_is_cow_file(inode);
}
static inline bool f2fs_meta_inode_gc_required(struct inode *inode)
{
return f2fs_post_read_required(inode) || f2fs_used_in_atomic_write(inode);
}
/*
* compress.c
*/
@ -4310,7 +4320,7 @@ void f2fs_update_read_extent_tree_range_compressed(struct inode *inode,
unsigned int llen, unsigned int c_len);
int f2fs_read_multi_pages(struct compress_ctx *cc, struct bio **bio_ret,
unsigned nr_pages, sector_t *last_block_in_bio,
bool is_readahead, bool for_write);
struct readahead_control *rac, bool for_write);
struct decompress_io_ctx *f2fs_alloc_dic(struct compress_ctx *cc);
void f2fs_decompress_end_io(struct decompress_io_ctx *dic, bool failed,
bool in_task);
@ -4401,22 +4411,18 @@ static inline int set_compress_context(struct inode *inode)
{
#ifdef CONFIG_F2FS_FS_COMPRESSION
struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
struct f2fs_inode_info *fi = F2FS_I(inode);
F2FS_I(inode)->i_compress_algorithm =
F2FS_OPTION(sbi).compress_algorithm;
F2FS_I(inode)->i_log_cluster_size =
F2FS_OPTION(sbi).compress_log_size;
F2FS_I(inode)->i_compress_flag =
F2FS_OPTION(sbi).compress_chksum ?
BIT(COMPRESS_CHKSUM) : 0;
F2FS_I(inode)->i_cluster_size =
BIT(F2FS_I(inode)->i_log_cluster_size);
if ((F2FS_I(inode)->i_compress_algorithm == COMPRESS_LZ4 ||
F2FS_I(inode)->i_compress_algorithm == COMPRESS_ZSTD) &&
fi->i_compress_algorithm = F2FS_OPTION(sbi).compress_algorithm;
fi->i_log_cluster_size = F2FS_OPTION(sbi).compress_log_size;
fi->i_compress_flag = F2FS_OPTION(sbi).compress_chksum ?
BIT(COMPRESS_CHKSUM) : 0;
fi->i_cluster_size = BIT(fi->i_log_cluster_size);
if ((fi->i_compress_algorithm == COMPRESS_LZ4 ||
fi->i_compress_algorithm == COMPRESS_ZSTD) &&
F2FS_OPTION(sbi).compress_level)
F2FS_I(inode)->i_compress_level =
F2FS_OPTION(sbi).compress_level;
F2FS_I(inode)->i_flags |= F2FS_COMPR_FL;
fi->i_compress_level = F2FS_OPTION(sbi).compress_level;
fi->i_flags |= F2FS_COMPR_FL;
set_inode_flag(inode, FI_COMPRESSED_FILE);
stat_inc_compr_inode(inode);
inc_compr_inode_stat(inode);
@ -4431,15 +4437,15 @@ static inline bool f2fs_disable_compressed_file(struct inode *inode)
{
struct f2fs_inode_info *fi = F2FS_I(inode);
f2fs_down_write(&F2FS_I(inode)->i_sem);
f2fs_down_write(&fi->i_sem);
if (!f2fs_compressed_file(inode)) {
f2fs_up_write(&F2FS_I(inode)->i_sem);
f2fs_up_write(&fi->i_sem);
return true;
}
if (f2fs_is_mmap_file(inode) ||
(S_ISREG(inode->i_mode) && F2FS_HAS_BLOCKS(inode))) {
f2fs_up_write(&F2FS_I(inode)->i_sem);
f2fs_up_write(&fi->i_sem);
return false;
}
@ -4448,7 +4454,7 @@ static inline bool f2fs_disable_compressed_file(struct inode *inode)
clear_inode_flag(inode, FI_COMPRESSED_FILE);
f2fs_mark_inode_dirty_sync(inode, true);
f2fs_up_write(&F2FS_I(inode)->i_sem);
f2fs_up_write(&fi->i_sem);
return true;
}

View File

@ -554,6 +554,42 @@ static int f2fs_file_mmap(struct file *file, struct vm_area_struct *vma)
return 0;
}
static int finish_preallocate_blocks(struct inode *inode)
{
int ret;
inode_lock(inode);
if (is_inode_flag_set(inode, FI_OPENED_FILE)) {
inode_unlock(inode);
return 0;
}
if (!file_should_truncate(inode)) {
set_inode_flag(inode, FI_OPENED_FILE);
inode_unlock(inode);
return 0;
}
f2fs_down_write(&F2FS_I(inode)->i_gc_rwsem[WRITE]);
filemap_invalidate_lock(inode->i_mapping);
truncate_setsize(inode, i_size_read(inode));
ret = f2fs_truncate(inode);
filemap_invalidate_unlock(inode->i_mapping);
f2fs_up_write(&F2FS_I(inode)->i_gc_rwsem[WRITE]);
if (!ret)
set_inode_flag(inode, FI_OPENED_FILE);
inode_unlock(inode);
if (ret)
return ret;
file_dont_truncate(inode);
return 0;
}
static int f2fs_file_open(struct inode *inode, struct file *filp)
{
int err = fscrypt_file_open(inode, filp);
@ -571,7 +607,11 @@ static int f2fs_file_open(struct inode *inode, struct file *filp)
filp->f_mode |= FMODE_NOWAIT;
filp->f_mode |= FMODE_CAN_ODIRECT;
return dquot_file_open(inode, filp);
err = dquot_file_open(inode, filp);
if (err)
return err;
return finish_preallocate_blocks(inode);
}
void f2fs_truncate_data_blocks_range(struct dnode_of_data *dn, int count)
@ -825,6 +865,8 @@ static bool f2fs_force_buffered_io(struct inode *inode, int rw)
return true;
if (f2fs_compressed_file(inode))
return true;
if (f2fs_has_inline_data(inode))
return true;
/* disallow direct IO if any of devices has unaligned blksize */
if (f2fs_is_multi_device(sbi) && !sbi->aligned_blksize)
@ -937,6 +979,7 @@ int f2fs_setattr(struct mnt_idmap *idmap, struct dentry *dentry,
struct iattr *attr)
{
struct inode *inode = d_inode(dentry);
struct f2fs_inode_info *fi = F2FS_I(inode);
int err;
if (unlikely(f2fs_cp_error(F2FS_I_SB(inode))))
@ -955,7 +998,7 @@ int f2fs_setattr(struct mnt_idmap *idmap, struct dentry *dentry,
return -EOPNOTSUPP;
if (is_inode_flag_set(inode, FI_COMPRESS_RELEASED) &&
!IS_ALIGNED(attr->ia_size,
F2FS_BLK_TO_BYTES(F2FS_I(inode)->i_cluster_size)))
F2FS_BLK_TO_BYTES(fi->i_cluster_size)))
return -EINVAL;
}
@ -1009,7 +1052,7 @@ int f2fs_setattr(struct mnt_idmap *idmap, struct dentry *dentry,
return err;
}
f2fs_down_write(&F2FS_I(inode)->i_gc_rwsem[WRITE]);
f2fs_down_write(&fi->i_gc_rwsem[WRITE]);
filemap_invalidate_lock(inode->i_mapping);
truncate_setsize(inode, attr->ia_size);
@ -1021,14 +1064,14 @@ int f2fs_setattr(struct mnt_idmap *idmap, struct dentry *dentry,
* larger than i_size.
*/
filemap_invalidate_unlock(inode->i_mapping);
f2fs_up_write(&F2FS_I(inode)->i_gc_rwsem[WRITE]);
f2fs_up_write(&fi->i_gc_rwsem[WRITE]);
if (err)
return err;
spin_lock(&F2FS_I(inode)->i_size_lock);
spin_lock(&fi->i_size_lock);
inode_set_mtime_to_ts(inode, inode_set_ctime_current(inode));
F2FS_I(inode)->last_disk_size = i_size_read(inode);
spin_unlock(&F2FS_I(inode)->i_size_lock);
fi->last_disk_size = i_size_read(inode);
spin_unlock(&fi->i_size_lock);
}
__setattr_copy(idmap, inode, attr);
@ -1038,7 +1081,7 @@ int f2fs_setattr(struct mnt_idmap *idmap, struct dentry *dentry,
if (is_inode_flag_set(inode, FI_ACL_MODE)) {
if (!err)
inode->i_mode = F2FS_I(inode)->i_acl_mode;
inode->i_mode = fi->i_acl_mode;
clear_inode_flag(inode, FI_ACL_MODE);
}
}
@ -1946,15 +1989,15 @@ static int f2fs_setflags_common(struct inode *inode, u32 iflags, u32 mask)
if (err)
return err;
f2fs_down_write(&F2FS_I(inode)->i_sem);
f2fs_down_write(&fi->i_sem);
if (!f2fs_may_compress(inode) ||
(S_ISREG(inode->i_mode) &&
F2FS_HAS_BLOCKS(inode))) {
f2fs_up_write(&F2FS_I(inode)->i_sem);
f2fs_up_write(&fi->i_sem);
return -EINVAL;
}
err = set_compress_context(inode);
f2fs_up_write(&F2FS_I(inode)->i_sem);
f2fs_up_write(&fi->i_sem);
if (err)
return err;
@ -2139,6 +2182,9 @@ static int f2fs_ioc_start_atomic_write(struct file *filp, bool truncate)
set_inode_flag(fi->cow_inode, FI_COW_FILE);
clear_inode_flag(fi->cow_inode, FI_INLINE_DATA);
/* Set the COW inode's atomic_inode to the atomic inode */
F2FS_I(fi->cow_inode)->atomic_inode = inode;
} else {
/* Reuse the already created COW inode */
ret = f2fs_do_truncate_blocks(fi->cow_inode, 0, true);
@ -3541,6 +3587,7 @@ static int release_compress_blocks(struct dnode_of_data *dn, pgoff_t count)
static int f2fs_release_compress_blocks(struct file *filp, unsigned long arg)
{
struct inode *inode = file_inode(filp);
struct f2fs_inode_info *fi = F2FS_I(inode);
struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
pgoff_t page_idx = 0, last_idx;
unsigned int released_blocks = 0;
@ -3578,7 +3625,7 @@ static int f2fs_release_compress_blocks(struct file *filp, unsigned long arg)
if (ret)
goto out;
if (!atomic_read(&F2FS_I(inode)->i_compr_blocks)) {
if (!atomic_read(&fi->i_compr_blocks)) {
ret = -EPERM;
goto out;
}
@ -3587,7 +3634,7 @@ static int f2fs_release_compress_blocks(struct file *filp, unsigned long arg)
inode_set_ctime_current(inode);
f2fs_mark_inode_dirty_sync(inode, true);
f2fs_down_write(&F2FS_I(inode)->i_gc_rwsem[WRITE]);
f2fs_down_write(&fi->i_gc_rwsem[WRITE]);
filemap_invalidate_lock(inode->i_mapping);
last_idx = DIV_ROUND_UP(i_size_read(inode), PAGE_SIZE);
@ -3613,7 +3660,7 @@ static int f2fs_release_compress_blocks(struct file *filp, unsigned long arg)
end_offset = ADDRS_PER_PAGE(dn.node_page, inode);
count = min(end_offset - dn.ofs_in_node, last_idx - page_idx);
count = round_up(count, F2FS_I(inode)->i_cluster_size);
count = round_up(count, fi->i_cluster_size);
ret = release_compress_blocks(&dn, count);
@ -3629,7 +3676,7 @@ static int f2fs_release_compress_blocks(struct file *filp, unsigned long arg)
}
filemap_invalidate_unlock(inode->i_mapping);
f2fs_up_write(&F2FS_I(inode)->i_gc_rwsem[WRITE]);
f2fs_up_write(&fi->i_gc_rwsem[WRITE]);
out:
if (released_blocks)
f2fs_update_time(sbi, REQ_TIME);
@ -3640,14 +3687,14 @@ static int f2fs_release_compress_blocks(struct file *filp, unsigned long arg)
if (ret >= 0) {
ret = put_user(released_blocks, (u64 __user *)arg);
} else if (released_blocks &&
atomic_read(&F2FS_I(inode)->i_compr_blocks)) {
atomic_read(&fi->i_compr_blocks)) {
set_sbi_flag(sbi, SBI_NEED_FSCK);
f2fs_warn(sbi, "%s: partial blocks were released i_ino=%lx "
"iblocks=%llu, released=%u, compr_blocks=%u, "
"run fsck to fix.",
__func__, inode->i_ino, inode->i_blocks,
released_blocks,
atomic_read(&F2FS_I(inode)->i_compr_blocks));
atomic_read(&fi->i_compr_blocks));
}
return ret;
@ -3736,6 +3783,7 @@ static int reserve_compress_blocks(struct dnode_of_data *dn, pgoff_t count,
static int f2fs_reserve_compress_blocks(struct file *filp, unsigned long arg)
{
struct inode *inode = file_inode(filp);
struct f2fs_inode_info *fi = F2FS_I(inode);
struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
pgoff_t page_idx = 0, last_idx;
unsigned int reserved_blocks = 0;
@ -3761,10 +3809,10 @@ static int f2fs_reserve_compress_blocks(struct file *filp, unsigned long arg)
goto unlock_inode;
}
if (atomic_read(&F2FS_I(inode)->i_compr_blocks))
if (atomic_read(&fi->i_compr_blocks))
goto unlock_inode;
f2fs_down_write(&F2FS_I(inode)->i_gc_rwsem[WRITE]);
f2fs_down_write(&fi->i_gc_rwsem[WRITE]);
filemap_invalidate_lock(inode->i_mapping);
last_idx = DIV_ROUND_UP(i_size_read(inode), PAGE_SIZE);
@ -3790,7 +3838,7 @@ static int f2fs_reserve_compress_blocks(struct file *filp, unsigned long arg)
end_offset = ADDRS_PER_PAGE(dn.node_page, inode);
count = min(end_offset - dn.ofs_in_node, last_idx - page_idx);
count = round_up(count, F2FS_I(inode)->i_cluster_size);
count = round_up(count, fi->i_cluster_size);
ret = reserve_compress_blocks(&dn, count, &reserved_blocks);
@ -3805,7 +3853,7 @@ static int f2fs_reserve_compress_blocks(struct file *filp, unsigned long arg)
}
filemap_invalidate_unlock(inode->i_mapping);
f2fs_up_write(&F2FS_I(inode)->i_gc_rwsem[WRITE]);
f2fs_up_write(&fi->i_gc_rwsem[WRITE]);
if (!ret) {
clear_inode_flag(inode, FI_COMPRESS_RELEASED);
@ -3821,14 +3869,14 @@ static int f2fs_reserve_compress_blocks(struct file *filp, unsigned long arg)
if (!ret) {
ret = put_user(reserved_blocks, (u64 __user *)arg);
} else if (reserved_blocks &&
atomic_read(&F2FS_I(inode)->i_compr_blocks)) {
atomic_read(&fi->i_compr_blocks)) {
set_sbi_flag(sbi, SBI_NEED_FSCK);
f2fs_warn(sbi, "%s: partial blocks were reserved i_ino=%lx "
"iblocks=%llu, reserved=%u, compr_blocks=%u, "
"run fsck to fix.",
__func__, inode->i_ino, inode->i_blocks,
reserved_blocks,
atomic_read(&F2FS_I(inode)->i_compr_blocks));
atomic_read(&fi->i_compr_blocks));
}
return ret;
@ -3891,7 +3939,9 @@ static int f2fs_sec_trim_file(struct file *filp, unsigned long arg)
IS_ENCRYPTED(inode) && f2fs_is_multi_device(sbi)))
return -EOPNOTSUPP;
file_start_write(filp);
ret = mnt_want_write_file(filp);
if (ret)
return ret;
inode_lock(inode);
if (f2fs_is_atomic_file(inode) || f2fs_compressed_file(inode) ||
@ -4017,7 +4067,7 @@ static int f2fs_sec_trim_file(struct file *filp, unsigned long arg)
f2fs_up_write(&F2FS_I(inode)->i_gc_rwsem[WRITE]);
err:
inode_unlock(inode);
file_end_write(filp);
mnt_drop_write_file(filp);
return ret;
}
@ -4052,6 +4102,7 @@ static int f2fs_ioc_get_compress_option(struct file *filp, unsigned long arg)
static int f2fs_ioc_set_compress_option(struct file *filp, unsigned long arg)
{
struct inode *inode = file_inode(filp);
struct f2fs_inode_info *fi = F2FS_I(inode);
struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
struct f2fs_comp_option option;
int ret = 0;
@ -4071,7 +4122,9 @@ static int f2fs_ioc_set_compress_option(struct file *filp, unsigned long arg)
option.algorithm >= COMPRESS_MAX)
return -EINVAL;
file_start_write(filp);
ret = mnt_want_write_file(filp);
if (ret)
return ret;
inode_lock(inode);
f2fs_down_write(&F2FS_I(inode)->i_sem);
@ -4090,27 +4143,27 @@ static int f2fs_ioc_set_compress_option(struct file *filp, unsigned long arg)
goto out;
}
F2FS_I(inode)->i_compress_algorithm = option.algorithm;
F2FS_I(inode)->i_log_cluster_size = option.log_cluster_size;
F2FS_I(inode)->i_cluster_size = BIT(option.log_cluster_size);
fi->i_compress_algorithm = option.algorithm;
fi->i_log_cluster_size = option.log_cluster_size;
fi->i_cluster_size = BIT(option.log_cluster_size);
/* Set default level */
if (F2FS_I(inode)->i_compress_algorithm == COMPRESS_ZSTD)
F2FS_I(inode)->i_compress_level = F2FS_ZSTD_DEFAULT_CLEVEL;
if (fi->i_compress_algorithm == COMPRESS_ZSTD)
fi->i_compress_level = F2FS_ZSTD_DEFAULT_CLEVEL;
else
F2FS_I(inode)->i_compress_level = 0;
fi->i_compress_level = 0;
/* Adjust mount option level */
if (option.algorithm == F2FS_OPTION(sbi).compress_algorithm &&
F2FS_OPTION(sbi).compress_level)
F2FS_I(inode)->i_compress_level = F2FS_OPTION(sbi).compress_level;
fi->i_compress_level = F2FS_OPTION(sbi).compress_level;
f2fs_mark_inode_dirty_sync(inode, true);
if (!f2fs_is_compress_backend_ready(inode))
f2fs_warn(sbi, "compression algorithm is successfully set, "
"but current kernel doesn't support this algorithm.");
out:
f2fs_up_write(&F2FS_I(inode)->i_sem);
f2fs_up_write(&fi->i_sem);
inode_unlock(inode);
file_end_write(filp);
mnt_drop_write_file(filp);
return ret;
}
@ -4167,7 +4220,9 @@ static int f2fs_ioc_decompress_file(struct file *filp)
f2fs_balance_fs(sbi, true);
file_start_write(filp);
ret = mnt_want_write_file(filp);
if (ret)
return ret;
inode_lock(inode);
if (!f2fs_is_compress_backend_ready(inode)) {
@ -4222,7 +4277,7 @@ static int f2fs_ioc_decompress_file(struct file *filp)
f2fs_update_time(sbi, REQ_TIME);
out:
inode_unlock(inode);
file_end_write(filp);
mnt_drop_write_file(filp);
return ret;
}
@ -4244,7 +4299,9 @@ static int f2fs_ioc_compress_file(struct file *filp)
f2fs_balance_fs(sbi, true);
file_start_write(filp);
ret = mnt_want_write_file(filp);
if (ret)
return ret;
inode_lock(inode);
if (!f2fs_is_compress_backend_ready(inode)) {
@ -4300,7 +4357,7 @@ static int f2fs_ioc_compress_file(struct file *filp)
f2fs_update_time(sbi, REQ_TIME);
out:
inode_unlock(inode);
file_end_write(filp);
mnt_drop_write_file(filp);
return ret;
}

View File

@ -1171,7 +1171,8 @@ static bool is_alive(struct f2fs_sb_info *sbi, struct f2fs_summary *sum,
static int ra_data_block(struct inode *inode, pgoff_t index)
{
struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
struct address_space *mapping = inode->i_mapping;
struct address_space *mapping = f2fs_is_cow_file(inode) ?
F2FS_I(inode)->atomic_inode->i_mapping : inode->i_mapping;
struct dnode_of_data dn;
struct page *page;
struct f2fs_io_info fio = {
@ -1260,6 +1261,8 @@ static int ra_data_block(struct inode *inode, pgoff_t index)
static int move_data_block(struct inode *inode, block_t bidx,
int gc_type, unsigned int segno, int off)
{
struct address_space *mapping = f2fs_is_cow_file(inode) ?
F2FS_I(inode)->atomic_inode->i_mapping : inode->i_mapping;
struct f2fs_io_info fio = {
.sbi = F2FS_I_SB(inode),
.ino = inode->i_ino,
@ -1282,7 +1285,7 @@ static int move_data_block(struct inode *inode, block_t bidx,
CURSEG_ALL_DATA_ATGC : CURSEG_COLD_DATA;
/* do not read out */
page = f2fs_grab_cache_page(inode->i_mapping, bidx, false);
page = f2fs_grab_cache_page(mapping, bidx, false);
if (!page)
return -ENOMEM;
@ -1563,6 +1566,16 @@ static int gc_data_segment(struct f2fs_sb_info *sbi, struct f2fs_summary *sum,
continue;
}
if (f2fs_has_inline_data(inode)) {
iput(inode);
set_sbi_flag(sbi, SBI_NEED_FSCK);
f2fs_err_ratelimited(sbi,
"inode %lx has both inline_data flag and "
"data block, nid=%u, ofs_in_node=%u",
inode->i_ino, dni.nid, ofs_in_node);
continue;
}
err = f2fs_gc_pinned_control(inode, gc_type, segno);
if (err == -EAGAIN) {
iput(inode);
@ -1579,7 +1592,7 @@ static int gc_data_segment(struct f2fs_sb_info *sbi, struct f2fs_summary *sum,
start_bidx = f2fs_start_bidx_of_node(nofs, inode) +
ofs_in_node;
if (f2fs_post_read_required(inode)) {
if (f2fs_meta_inode_gc_required(inode)) {
int err = ra_data_block(inode, start_bidx);
f2fs_up_write(&F2FS_I(inode)->i_gc_rwsem[WRITE]);
@ -1630,7 +1643,7 @@ static int gc_data_segment(struct f2fs_sb_info *sbi, struct f2fs_summary *sum,
start_bidx = f2fs_start_bidx_of_node(nofs, inode)
+ ofs_in_node;
if (f2fs_post_read_required(inode))
if (f2fs_meta_inode_gc_required(inode))
err = move_data_block(inode, start_bidx,
gc_type, segno, off);
else
@ -1638,7 +1651,7 @@ static int gc_data_segment(struct f2fs_sb_info *sbi, struct f2fs_summary *sum,
segno, off);
if (!err && (gc_type == FG_GC ||
f2fs_post_read_required(inode)))
f2fs_meta_inode_gc_required(inode)))
submitted++;
if (locked) {
@ -1742,7 +1755,6 @@ static int do_garbage_collect(struct f2fs_sb_info *sbi,
if (type != GET_SUM_TYPE((&sum->footer))) {
f2fs_err(sbi, "Inconsistent segment (%u) type [%d, %d] in SSA and SIT",
segno, type, GET_SUM_TYPE((&sum->footer)));
set_sbi_flag(sbi, SBI_NEED_FSCK);
f2fs_stop_checkpoint(sbi, false,
STOP_CP_REASON_CORRUPTED_SUMMARY);
goto skip;

View File

@ -16,7 +16,7 @@
static bool support_inline_data(struct inode *inode)
{
if (f2fs_is_atomic_file(inode))
if (f2fs_used_in_atomic_write(inode))
return false;
if (!S_ISREG(inode->i_mode) && !S_ISLNK(inode->i_mode))
return false;
@ -33,11 +33,29 @@ bool f2fs_may_inline_data(struct inode *inode)
return !f2fs_post_read_required(inode);
}
bool f2fs_sanity_check_inline_data(struct inode *inode)
static bool inode_has_blocks(struct inode *inode, struct page *ipage)
{
struct f2fs_inode *ri = F2FS_INODE(ipage);
int i;
if (F2FS_HAS_BLOCKS(inode))
return true;
for (i = 0; i < DEF_NIDS_PER_INODE; i++) {
if (ri->i_nid[i])
return true;
}
return false;
}
bool f2fs_sanity_check_inline_data(struct inode *inode, struct page *ipage)
{
if (!f2fs_has_inline_data(inode))
return false;
if (inode_has_blocks(inode, ipage))
return false;
if (!support_inline_data(inode))
return true;
@ -203,8 +221,10 @@ int f2fs_convert_inline_inode(struct inode *inode)
struct page *ipage, *page;
int err = 0;
if (!f2fs_has_inline_data(inode) ||
f2fs_hw_is_readonly(sbi) || f2fs_readonly(sbi->sb))
if (f2fs_hw_is_readonly(sbi) || f2fs_readonly(sbi->sb))
return -EROFS;
if (!f2fs_has_inline_data(inode))
return 0;
err = f2fs_dquot_initialize(inode);

View File

@ -29,6 +29,9 @@ void f2fs_mark_inode_dirty_sync(struct inode *inode, bool sync)
if (is_inode_flag_set(inode, FI_NEW_INODE))
return;
if (f2fs_readonly(F2FS_I_SB(inode)->sb))
return;
if (f2fs_inode_dirtied(inode, sync))
return;
@ -310,10 +313,6 @@ static bool sanity_check_inode(struct inode *inode, struct page *node_page)
if (!sanity_check_compress_inode(inode, ri))
return false;
}
} else if (f2fs_sb_has_flexible_inline_xattr(sbi)) {
f2fs_warn(sbi, "%s: corrupted inode ino=%lx, run fsck to fix.",
__func__, inode->i_ino);
return false;
}
if (!f2fs_sb_has_extra_attr(sbi)) {
@ -344,7 +343,7 @@ static bool sanity_check_inode(struct inode *inode, struct page *node_page)
}
}
if (f2fs_sanity_check_inline_data(inode)) {
if (f2fs_sanity_check_inline_data(inode, node_page)) {
f2fs_warn(sbi, "%s: inode (ino=%lx, mode=%u) should not have inline_data, run fsck to fix",
__func__, inode->i_ino, inode->i_mode);
return false;
@ -508,16 +507,16 @@ static int do_read_inode(struct inode *inode)
init_idisk_time(inode);
/* Need all the flag bits */
f2fs_init_read_extent_tree(inode, node_page);
f2fs_init_age_extent_tree(inode);
if (!sanity_check_extent_cache(inode)) {
if (!sanity_check_extent_cache(inode, node_page)) {
f2fs_put_page(node_page, 1);
f2fs_handle_error(sbi, ERROR_CORRUPTED_INODE);
return -EFSCORRUPTED;
}
/* Need all the flag bits */
f2fs_init_read_extent_tree(inode, node_page);
f2fs_init_age_extent_tree(inode);
f2fs_put_page(node_page, 1);
stat_inc_inline_xattr(inode);
@ -610,14 +609,6 @@ struct inode *f2fs_iget(struct super_block *sb, unsigned long ino)
}
f2fs_set_inode_flags(inode);
if (file_should_truncate(inode) &&
!is_sbi_flag_set(sbi, SBI_POR_DOING)) {
ret = f2fs_truncate(inode);
if (ret)
goto bad_inode;
file_dont_truncate(inode);
}
unlock_new_inode(inode);
trace_f2fs_iget(inode);
return inode;
@ -645,8 +636,9 @@ struct inode *f2fs_iget_retry(struct super_block *sb, unsigned long ino)
void f2fs_update_inode(struct inode *inode, struct page *node_page)
{
struct f2fs_inode_info *fi = F2FS_I(inode);
struct f2fs_inode *ri;
struct extent_tree *et = F2FS_I(inode)->extent_tree[EX_READ];
struct extent_tree *et = fi->extent_tree[EX_READ];
f2fs_wait_on_page_writeback(node_page, NODE, true, true);
set_page_dirty(node_page);
@ -656,7 +648,7 @@ void f2fs_update_inode(struct inode *inode, struct page *node_page)
ri = F2FS_INODE(node_page);
ri->i_mode = cpu_to_le16(inode->i_mode);
ri->i_advise = F2FS_I(inode)->i_advise;
ri->i_advise = fi->i_advise;
ri->i_uid = cpu_to_le32(i_uid_read(inode));
ri->i_gid = cpu_to_le32(i_gid_read(inode));
ri->i_links = cpu_to_le32(inode->i_nlink);
@ -682,58 +674,49 @@ void f2fs_update_inode(struct inode *inode, struct page *node_page)
ri->i_ctime_nsec = cpu_to_le32(inode_get_ctime_nsec(inode));
ri->i_mtime_nsec = cpu_to_le32(inode_get_mtime_nsec(inode));
if (S_ISDIR(inode->i_mode))
ri->i_current_depth =
cpu_to_le32(F2FS_I(inode)->i_current_depth);
ri->i_current_depth = cpu_to_le32(fi->i_current_depth);
else if (S_ISREG(inode->i_mode))
ri->i_gc_failures = cpu_to_le16(F2FS_I(inode)->i_gc_failures);
ri->i_xattr_nid = cpu_to_le32(F2FS_I(inode)->i_xattr_nid);
ri->i_flags = cpu_to_le32(F2FS_I(inode)->i_flags);
ri->i_pino = cpu_to_le32(F2FS_I(inode)->i_pino);
ri->i_gc_failures = cpu_to_le16(fi->i_gc_failures);
ri->i_xattr_nid = cpu_to_le32(fi->i_xattr_nid);
ri->i_flags = cpu_to_le32(fi->i_flags);
ri->i_pino = cpu_to_le32(fi->i_pino);
ri->i_generation = cpu_to_le32(inode->i_generation);
ri->i_dir_level = F2FS_I(inode)->i_dir_level;
ri->i_dir_level = fi->i_dir_level;
if (f2fs_has_extra_attr(inode)) {
ri->i_extra_isize = cpu_to_le16(F2FS_I(inode)->i_extra_isize);
ri->i_extra_isize = cpu_to_le16(fi->i_extra_isize);
if (f2fs_sb_has_flexible_inline_xattr(F2FS_I_SB(inode)))
ri->i_inline_xattr_size =
cpu_to_le16(F2FS_I(inode)->i_inline_xattr_size);
cpu_to_le16(fi->i_inline_xattr_size);
if (f2fs_sb_has_project_quota(F2FS_I_SB(inode)) &&
F2FS_FITS_IN_INODE(ri, F2FS_I(inode)->i_extra_isize,
i_projid)) {
F2FS_FITS_IN_INODE(ri, fi->i_extra_isize, i_projid)) {
projid_t i_projid;
i_projid = from_kprojid(&init_user_ns,
F2FS_I(inode)->i_projid);
i_projid = from_kprojid(&init_user_ns, fi->i_projid);
ri->i_projid = cpu_to_le32(i_projid);
}
if (f2fs_sb_has_inode_crtime(F2FS_I_SB(inode)) &&
F2FS_FITS_IN_INODE(ri, F2FS_I(inode)->i_extra_isize,
i_crtime)) {
ri->i_crtime =
cpu_to_le64(F2FS_I(inode)->i_crtime.tv_sec);
ri->i_crtime_nsec =
cpu_to_le32(F2FS_I(inode)->i_crtime.tv_nsec);
F2FS_FITS_IN_INODE(ri, fi->i_extra_isize, i_crtime)) {
ri->i_crtime = cpu_to_le64(fi->i_crtime.tv_sec);
ri->i_crtime_nsec = cpu_to_le32(fi->i_crtime.tv_nsec);
}
if (f2fs_sb_has_compression(F2FS_I_SB(inode)) &&
F2FS_FITS_IN_INODE(ri, F2FS_I(inode)->i_extra_isize,
F2FS_FITS_IN_INODE(ri, fi->i_extra_isize,
i_compress_flag)) {
unsigned short compress_flag;
ri->i_compr_blocks =
cpu_to_le64(atomic_read(
&F2FS_I(inode)->i_compr_blocks));
ri->i_compress_algorithm =
F2FS_I(inode)->i_compress_algorithm;
compress_flag = F2FS_I(inode)->i_compress_flag |
F2FS_I(inode)->i_compress_level <<
ri->i_compr_blocks = cpu_to_le64(
atomic_read(&fi->i_compr_blocks));
ri->i_compress_algorithm = fi->i_compress_algorithm;
compress_flag = fi->i_compress_flag |
fi->i_compress_level <<
COMPRESS_LEVEL_OFFSET;
ri->i_compress_flag = cpu_to_le16(compress_flag);
ri->i_log_cluster_size =
F2FS_I(inode)->i_log_cluster_size;
ri->i_log_cluster_size = fi->i_log_cluster_size;
}
}
@ -813,8 +796,9 @@ void f2fs_evict_inode(struct inode *inode)
f2fs_abort_atomic_write(inode, true);
if (fi->cow_inode) {
if (fi->cow_inode && f2fs_is_cow_file(fi->cow_inode)) {
clear_inode_flag(fi->cow_inode, FI_COW_FILE);
F2FS_I(fi->cow_inode)->atomic_inode = NULL;
iput(fi->cow_inode);
fi->cow_inode = NULL;
}

View File

@ -221,6 +221,7 @@ static struct inode *f2fs_new_inode(struct mnt_idmap *idmap,
const char *name)
{
struct f2fs_sb_info *sbi = F2FS_I_SB(dir);
struct f2fs_inode_info *fi;
nid_t ino;
struct inode *inode;
bool nid_free = false;
@ -241,14 +242,15 @@ static struct inode *f2fs_new_inode(struct mnt_idmap *idmap,
inode_init_owner(idmap, inode, dir, mode);
fi = F2FS_I(inode);
inode->i_ino = ino;
inode->i_blocks = 0;
simple_inode_init_ts(inode);
F2FS_I(inode)->i_crtime = inode_get_mtime(inode);
fi->i_crtime = inode_get_mtime(inode);
inode->i_generation = get_random_u32();
if (S_ISDIR(inode->i_mode))
F2FS_I(inode)->i_current_depth = 1;
fi->i_current_depth = 1;
err = insert_inode_locked(inode);
if (err) {
@ -258,9 +260,9 @@ static struct inode *f2fs_new_inode(struct mnt_idmap *idmap,
if (f2fs_sb_has_project_quota(sbi) &&
(F2FS_I(dir)->i_flags & F2FS_PROJINHERIT_FL))
F2FS_I(inode)->i_projid = F2FS_I(dir)->i_projid;
fi->i_projid = F2FS_I(dir)->i_projid;
else
F2FS_I(inode)->i_projid = make_kprojid(&init_user_ns,
fi->i_projid = make_kprojid(&init_user_ns,
F2FS_DEF_PROJID);
err = fscrypt_prepare_new_inode(dir, inode, &encrypt);
@ -278,7 +280,7 @@ static struct inode *f2fs_new_inode(struct mnt_idmap *idmap,
if (f2fs_sb_has_extra_attr(sbi)) {
set_inode_flag(inode, FI_EXTRA_ATTR);
F2FS_I(inode)->i_extra_isize = F2FS_TOTAL_EXTRA_ATTR_SIZE;
fi->i_extra_isize = F2FS_TOTAL_EXTRA_ATTR_SIZE;
}
if (test_opt(sbi, INLINE_XATTR))
@ -296,15 +298,15 @@ static struct inode *f2fs_new_inode(struct mnt_idmap *idmap,
f2fs_has_inline_dentry(inode)) {
xattr_size = DEFAULT_INLINE_XATTR_ADDRS;
}
F2FS_I(inode)->i_inline_xattr_size = xattr_size;
fi->i_inline_xattr_size = xattr_size;
F2FS_I(inode)->i_flags =
fi->i_flags =
f2fs_mask_flags(mode, F2FS_I(dir)->i_flags & F2FS_FL_INHERITED);
if (S_ISDIR(inode->i_mode))
F2FS_I(inode)->i_flags |= F2FS_INDEX_FL;
fi->i_flags |= F2FS_INDEX_FL;
if (F2FS_I(inode)->i_flags & F2FS_PROJINHERIT_FL)
if (fi->i_flags & F2FS_PROJINHERIT_FL)
set_inode_flag(inode, FI_PROJ_INHERIT);
/* Check compression first. */

View File

@ -280,6 +280,7 @@ static void recover_inline_flags(struct inode *inode, struct f2fs_inode *ri)
static int recover_inode(struct inode *inode, struct page *page)
{
struct f2fs_inode *raw = F2FS_INODE(page);
struct f2fs_inode_info *fi = F2FS_I(inode);
char *name;
int err;
@ -302,12 +303,12 @@ static int recover_inode(struct inode *inode, struct page *page)
i_projid = (projid_t)le32_to_cpu(raw->i_projid);
kprojid = make_kprojid(&init_user_ns, i_projid);
if (!projid_eq(kprojid, F2FS_I(inode)->i_projid)) {
if (!projid_eq(kprojid, fi->i_projid)) {
err = f2fs_transfer_project_quota(inode,
kprojid);
if (err)
return err;
F2FS_I(inode)->i_projid = kprojid;
fi->i_projid = kprojid;
}
}
}
@ -320,10 +321,10 @@ static int recover_inode(struct inode *inode, struct page *page)
inode_set_mtime(inode, le64_to_cpu(raw->i_mtime),
le32_to_cpu(raw->i_mtime_nsec));
F2FS_I(inode)->i_advise = raw->i_advise;
F2FS_I(inode)->i_flags = le32_to_cpu(raw->i_flags);
fi->i_advise = raw->i_advise;
fi->i_flags = le32_to_cpu(raw->i_flags);
f2fs_set_inode_flags(inode);
F2FS_I(inode)->i_gc_failures = le16_to_cpu(raw->i_gc_failures);
fi->i_gc_failures = le16_to_cpu(raw->i_gc_failures);
recover_inline_flags(inode, raw);

View File

@ -2784,11 +2784,19 @@ static unsigned int __get_next_segno(struct f2fs_sb_info *sbi, int type)
unsigned short seg_type = curseg->seg_type;
sanity_check_seg_type(sbi, seg_type);
if (f2fs_need_rand_seg(sbi))
return get_random_u32_below(MAIN_SECS(sbi) * SEGS_PER_SEC(sbi));
if (__is_large_section(sbi)) {
if (f2fs_need_rand_seg(sbi)) {
unsigned int hint = GET_SEC_FROM_SEG(sbi, curseg->segno);
if (__is_large_section(sbi))
if (GET_SEC_FROM_SEG(sbi, curseg->segno + 1) != hint)
return curseg->segno;
return get_random_u32_inclusive(curseg->segno + 1,
GET_SEG_FROM_SEC(sbi, hint + 1) - 1);
}
return curseg->segno;
} else if (f2fs_need_rand_seg(sbi)) {
return get_random_u32_below(MAIN_SECS(sbi) * SEGS_PER_SEC(sbi));
}
/* inmem log may not locate on any segment after mount */
if (!curseg->inited)
@ -2931,12 +2939,12 @@ static int get_atssr_segment(struct f2fs_sb_info *sbi, int type,
return ret;
}
static int __f2fs_init_atgc_curseg(struct f2fs_sb_info *sbi)
static int __f2fs_init_atgc_curseg(struct f2fs_sb_info *sbi, bool force)
{
struct curseg_info *curseg = CURSEG_I(sbi, CURSEG_ALL_DATA_ATGC);
int ret = 0;
if (!sbi->am.atgc_enabled)
if (!sbi->am.atgc_enabled && !force)
return 0;
f2fs_down_read(&SM_I(sbi)->curseg_lock);
@ -2953,9 +2961,30 @@ static int __f2fs_init_atgc_curseg(struct f2fs_sb_info *sbi)
f2fs_up_read(&SM_I(sbi)->curseg_lock);
return ret;
}
int f2fs_init_inmem_curseg(struct f2fs_sb_info *sbi)
{
return __f2fs_init_atgc_curseg(sbi);
return __f2fs_init_atgc_curseg(sbi, false);
}
int f2fs_reinit_atgc_curseg(struct f2fs_sb_info *sbi)
{
int ret;
if (!test_opt(sbi, ATGC))
return 0;
if (sbi->am.atgc_enabled)
return 0;
if (le64_to_cpu(F2FS_CKPT(sbi)->elapsed_time) <
sbi->am.age_threshold)
return 0;
ret = __f2fs_init_atgc_curseg(sbi, true);
if (!ret) {
sbi->am.atgc_enabled = true;
f2fs_info(sbi, "reenabled age threshold GC");
}
return ret;
}
static void __f2fs_save_inmem_curseg(struct f2fs_sb_info *sbi, int type)
@ -3483,7 +3512,9 @@ static int __get_segment_type_6(struct f2fs_io_info *fio)
if (page_private_gcing(fio->page)) {
if (fio->sbi->am.atgc_enabled &&
(fio->io_type == FS_DATA_IO) &&
(fio->sbi->gc_mode != GC_URGENT_HIGH))
(fio->sbi->gc_mode != GC_URGENT_HIGH) &&
__is_valid_data_blkaddr(fio->old_blkaddr) &&
!is_inode_flag_set(inode, FI_OPU_WRITE))
return CURSEG_ALL_DATA_ATGC;
else
return CURSEG_COLD_DATA;
@ -3828,7 +3859,7 @@ int f2fs_inplace_write_data(struct f2fs_io_info *fio)
goto drop_bio;
}
if (fio->post_read)
if (fio->meta_gc)
f2fs_truncate_meta_inode_pages(sbi, fio->new_blkaddr, 1);
stat_inc_inplace_blocks(fio->sbi);
@ -3998,7 +4029,7 @@ void f2fs_wait_on_block_writeback(struct inode *inode, block_t blkaddr)
struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
struct page *cpage;
if (!f2fs_post_read_required(inode))
if (!f2fs_meta_inode_gc_required(inode))
return;
if (!__is_valid_data_blkaddr(blkaddr))
@ -4017,7 +4048,7 @@ void f2fs_wait_on_block_writeback_range(struct inode *inode, block_t blkaddr,
struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
block_t i;
if (!f2fs_post_read_required(inode))
if (!f2fs_meta_inode_gc_required(inode))
return;
for (i = 0; i < len; i++)
@ -5187,7 +5218,8 @@ static int fix_curseg_write_pointer(struct f2fs_sb_info *sbi, int type)
}
/* Allocate a new section if it's not new. */
if (cs->next_blkoff) {
if (cs->next_blkoff ||
cs->segno != GET_SEG_FROM_SEC(sbi, GET_ZONE_FROM_SEC(sbi, cs_section))) {
unsigned int old_segno = cs->segno, old_blkoff = cs->next_blkoff;
f2fs_allocate_new_section(sbi, type, true);

View File

@ -347,7 +347,8 @@ static inline unsigned int get_ckpt_valid_blocks(struct f2fs_sb_info *sbi,
unsigned int segno, bool use_section)
{
if (use_section && __is_large_section(sbi)) {
unsigned int start_segno = START_SEGNO(segno);
unsigned int secno = GET_SEC_FROM_SEG(sbi, segno);
unsigned int start_segno = GET_SEG_FROM_SEC(sbi, secno);
unsigned int blocks = 0;
int i;

View File

@ -151,8 +151,6 @@ enum {
Opt_mode,
Opt_fault_injection,
Opt_fault_type,
Opt_lazytime,
Opt_nolazytime,
Opt_quota,
Opt_noquota,
Opt_usrquota,
@ -229,8 +227,6 @@ static match_table_t f2fs_tokens = {
{Opt_mode, "mode=%s"},
{Opt_fault_injection, "fault_injection=%u"},
{Opt_fault_type, "fault_type=%u"},
{Opt_lazytime, "lazytime"},
{Opt_nolazytime, "nolazytime"},
{Opt_quota, "quota"},
{Opt_noquota, "noquota"},
{Opt_usrquota, "usrquota"},
@ -918,12 +914,6 @@ static int parse_options(struct super_block *sb, char *options, bool is_remount)
f2fs_info(sbi, "fault_type options not supported");
break;
#endif
case Opt_lazytime:
sb->s_flags |= SB_LAZYTIME;
break;
case Opt_nolazytime:
sb->s_flags &= ~SB_LAZYTIME;
break;
#ifdef CONFIG_QUOTA
case Opt_quota:
case Opt_usrquota:
@ -4481,6 +4471,7 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent)
sb->s_flags = (sb->s_flags & ~SB_POSIXACL) |
(test_opt(sbi, POSIX_ACL) ? SB_POSIXACL : 0);
super_set_uuid(sb, (void *) raw_super->uuid, sizeof(raw_super->uuid));
super_set_sysfs_name_bdev(sb);
sb->s_iflags |= SB_I_CGROUPWB;
/* init f2fs-specific super block info */

View File

@ -340,13 +340,13 @@ static ssize_t f2fs_sbi_show(struct f2fs_attr *a,
if (!strcmp(a->attr.name, "ckpt_thread_ioprio")) {
struct ckpt_req_control *cprc = &sbi->cprc_info;
int class = IOPRIO_PRIO_CLASS(cprc->ckpt_thread_ioprio);
int data = IOPRIO_PRIO_DATA(cprc->ckpt_thread_ioprio);
int level = IOPRIO_PRIO_LEVEL(cprc->ckpt_thread_ioprio);
if (class != IOPRIO_CLASS_RT && class != IOPRIO_CLASS_BE)
return -EINVAL;
return sysfs_emit(buf, "%s,%d\n",
class == IOPRIO_CLASS_RT ? "rt" : "be", data);
class == IOPRIO_CLASS_RT ? "rt" : "be", level);
}
#ifdef CONFIG_F2FS_FS_COMPRESSION
@ -450,7 +450,7 @@ static ssize_t __sbi_store(struct f2fs_attr *a,
const char *name = strim((char *)buf);
struct ckpt_req_control *cprc = &sbi->cprc_info;
int class;
long data;
long level;
int ret;
if (!strncmp(name, "rt,", 3))
@ -461,13 +461,13 @@ static ssize_t __sbi_store(struct f2fs_attr *a,
return -EINVAL;
name += 3;
ret = kstrtol(name, 10, &data);
ret = kstrtol(name, 10, &level);
if (ret)
return ret;
if (data >= IOPRIO_NR_LEVELS || data < 0)
if (level >= IOPRIO_NR_LEVELS || level < 0)
return -EINVAL;
cprc->ckpt_thread_ioprio = IOPRIO_PRIO_VALUE(class, data);
cprc->ckpt_thread_ioprio = IOPRIO_PRIO_VALUE(class, level);
if (test_opt(sbi, MERGE_CHECKPOINT)) {
ret = set_task_ioprio(cprc->f2fs_issue_ckpt,
cprc->ckpt_thread_ioprio);

View File

@ -259,15 +259,14 @@ struct node_footer {
#define CUR_ADDRS_PER_INODE(inode) (DEF_ADDRS_PER_INODE - \
get_extra_isize(inode))
#define DEF_NIDS_PER_INODE 5 /* Node IDs in an Inode */
#define ADDRS_PER_INODE(inode) addrs_per_inode(inode)
#define ADDRS_PER_INODE(inode) addrs_per_page(inode, true)
/* Address Pointers in a Direct Block */
#define DEF_ADDRS_PER_BLOCK ((F2FS_BLKSIZE - sizeof(struct node_footer)) / sizeof(__le32))
#define ADDRS_PER_BLOCK(inode) addrs_per_block(inode)
#define ADDRS_PER_BLOCK(inode) addrs_per_page(inode, false)
/* Node IDs in an Indirect Block */
#define NIDS_PER_BLOCK ((F2FS_BLKSIZE - sizeof(struct node_footer)) / sizeof(__le32))
#define ADDRS_PER_PAGE(page, inode) \
(IS_INODE(page) ? ADDRS_PER_INODE(inode) : ADDRS_PER_BLOCK(inode))
#define ADDRS_PER_PAGE(page, inode) (addrs_per_page(inode, IS_INODE(page)))
#define NODE_DIR1_BLOCK (DEF_ADDRS_PER_INODE + 1)
#define NODE_DIR2_BLOCK (DEF_ADDRS_PER_INODE + 2)