Commit 3da90b15 authored by Linus Torvalds's avatar Linus Torvalds

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

Pull f2fs updates from Jaegeuk Kim:
 "In this round, we've followed up to support some generic features such
  as cgroup, block reservation, linking fscrypt_ops, delivering
  write_hints, and some ioctls. And, we could fix some corner cases in
  terms of power-cut recovery and subtle deadlocks.

  Enhancements:
   - bitmap operations to handle NAT blocks
   - readahead to improve readdir speed
   - switch to use fscrypt_*
   - apply write hints for direct IO
   - add reserve_root=%u,resuid=%u,resgid=%u to reserve blocks for root/uid/gid
   - modify b_avail and b_free to consider root reserved blocks
   - support cgroup writeback
   - support FIEMAP_FLAG_XATTR for fibmap
   - add F2FS_IOC_PRECACHE_EXTENTS to pre-cache extents
   - add F2FS_IOC_{GET/SET}_PIN_FILE to pin LBAs for data blocks
   - support inode creation time

  Bug fixs:
   - sysfile-based quota operations
   - memory footprint accounting
   - allow to write data on partial preallocation case
   - fix deadlock case on fallocate
   - fix to handle fill_super errors
   - fix missing inode updates of fsync'ed file
   - recover renamed file which was fsycn'ed before
   - drop inmemory pages in corner error case
   - keep last_disk_size correctly
   - recover missing i_inline flags during roll-forward

  Various clean-up patches were added as well"

* tag 'f2fs-for-4.16-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/jaegeuk/f2fs: (72 commits)
  f2fs: support inode creation time
  f2fs: rebuild sit page from sit info in mem
  f2fs: stop issuing discard if fs is readonly
  f2fs: clean up duplicated assignment in init_discard_policy
  f2fs: use GFP_F2FS_ZERO for cleanup
  f2fs: allow to recover node blocks given updated checkpoint
  f2fs: recover some i_inline flags
  f2fs: correct removexattr behavior for null valued extended attribute
  f2fs: drop page cache after fs shutdown
  f2fs: stop gc/discard thread after fs shutdown
  f2fs: hanlde error case in f2fs_ioc_shutdown
  f2fs: split need_inplace_update
  f2fs: fix to update last_disk_size correctly
  f2fs: kill F2FS_INLINE_XATTR_ADDRS for cleanup
  f2fs: clean up error path of fill_super
  f2fs: avoid hungtask when GC encrypted block if io_bits is set
  f2fs: allow quota to use reserved blocks
  f2fs: fix to drop all inmem pages correctly
  f2fs: speed up defragment on sparse file
  f2fs: support F2FS_IOC_PRECACHE_EXTENTS
  ...
parents efd52b5d 1c1d35df
...@@ -186,3 +186,9 @@ Date: August 2017 ...@@ -186,3 +186,9 @@ Date: August 2017
Contact: "Jaegeuk Kim" <jaegeuk@kernel.org> Contact: "Jaegeuk Kim" <jaegeuk@kernel.org>
Description: Description:
Controls sleep time of GC urgent mode Controls sleep time of GC urgent mode
What: /sys/fs/f2fs/<disk>/readdir_ra
Date: November 2017
Contact: "Sheng Yong" <shengyong1@huawei.com>
Description:
Controls readahead inode block in readdir.
...@@ -270,7 +270,7 @@ static struct posix_acl *f2fs_acl_clone(const struct posix_acl *acl, ...@@ -270,7 +270,7 @@ static struct posix_acl *f2fs_acl_clone(const struct posix_acl *acl,
sizeof(struct posix_acl_entry); sizeof(struct posix_acl_entry);
clone = kmemdup(acl, size, flags); clone = kmemdup(acl, size, flags);
if (clone) if (clone)
atomic_set(&clone->a_refcount, 1); refcount_set(&clone->a_refcount, 1);
} }
return clone; return clone;
} }
......
...@@ -237,12 +237,15 @@ static int __f2fs_write_meta_page(struct page *page, ...@@ -237,12 +237,15 @@ static int __f2fs_write_meta_page(struct page *page,
trace_f2fs_writepage(page, META); trace_f2fs_writepage(page, META);
if (unlikely(f2fs_cp_error(sbi))) {
dec_page_count(sbi, F2FS_DIRTY_META);
unlock_page(page);
return 0;
}
if (unlikely(is_sbi_flag_set(sbi, SBI_POR_DOING))) if (unlikely(is_sbi_flag_set(sbi, SBI_POR_DOING)))
goto redirty_out; goto redirty_out;
if (wbc->for_reclaim && page->index < GET_SUM_BLOCK(sbi, 0)) if (wbc->for_reclaim && page->index < GET_SUM_BLOCK(sbi, 0))
goto redirty_out; goto redirty_out;
if (unlikely(f2fs_cp_error(sbi)))
goto redirty_out;
write_meta_page(sbi, page, io_type); write_meta_page(sbi, page, io_type);
dec_page_count(sbi, F2FS_DIRTY_META); dec_page_count(sbi, F2FS_DIRTY_META);
...@@ -793,7 +796,7 @@ int get_valid_checkpoint(struct f2fs_sb_info *sbi) ...@@ -793,7 +796,7 @@ int get_valid_checkpoint(struct f2fs_sb_info *sbi)
block_t cp_blk_no; block_t cp_blk_no;
int i; int i;
sbi->ckpt = kzalloc(cp_blks * blk_size, GFP_KERNEL); sbi->ckpt = f2fs_kzalloc(sbi, cp_blks * blk_size, GFP_KERNEL);
if (!sbi->ckpt) if (!sbi->ckpt)
return -ENOMEM; return -ENOMEM;
/* /*
...@@ -1154,6 +1157,7 @@ static void update_ckpt_flags(struct f2fs_sb_info *sbi, struct cp_control *cpc) ...@@ -1154,6 +1157,7 @@ static void update_ckpt_flags(struct f2fs_sb_info *sbi, struct cp_control *cpc)
/* set this flag to activate crc|cp_ver for recovery */ /* set this flag to activate crc|cp_ver for recovery */
__set_ckpt_flags(ckpt, CP_CRC_RECOVERY_FLAG); __set_ckpt_flags(ckpt, CP_CRC_RECOVERY_FLAG);
__clear_ckpt_flags(ckpt, CP_NOCRC_RECOVERY_FLAG);
spin_unlock_irqrestore(&sbi->cp_lock, flags); spin_unlock_irqrestore(&sbi->cp_lock, flags);
} }
......
This diff is collapsed.
...@@ -49,14 +49,7 @@ static void update_general_status(struct f2fs_sb_info *sbi) ...@@ -49,14 +49,7 @@ static void update_general_status(struct f2fs_sb_info *sbi)
si->ndirty_imeta = get_pages(sbi, F2FS_DIRTY_IMETA); si->ndirty_imeta = get_pages(sbi, F2FS_DIRTY_IMETA);
si->ndirty_dirs = sbi->ndirty_inode[DIR_INODE]; si->ndirty_dirs = sbi->ndirty_inode[DIR_INODE];
si->ndirty_files = sbi->ndirty_inode[FILE_INODE]; si->ndirty_files = sbi->ndirty_inode[FILE_INODE];
si->nquota_files = sbi->nquota_files;
si->nquota_files = 0;
if (f2fs_sb_has_quota_ino(sbi->sb)) {
for (i = 0; i < MAXQUOTAS; i++) {
if (f2fs_qf_ino(sbi->sb, i))
si->nquota_files++;
}
}
si->ndirty_all = sbi->ndirty_inode[DIRTY_META]; si->ndirty_all = sbi->ndirty_inode[DIRTY_META];
si->inmem_pages = get_pages(sbi, F2FS_INMEM_PAGES); si->inmem_pages = get_pages(sbi, F2FS_INMEM_PAGES);
si->aw_cnt = atomic_read(&sbi->aw_cnt); si->aw_cnt = atomic_read(&sbi->aw_cnt);
...@@ -186,7 +179,6 @@ static void update_mem_info(struct f2fs_sb_info *sbi) ...@@ -186,7 +179,6 @@ static void update_mem_info(struct f2fs_sb_info *sbi)
si->base_mem += sizeof(struct f2fs_sb_info) + sbi->sb->s_blocksize; si->base_mem += sizeof(struct f2fs_sb_info) + sbi->sb->s_blocksize;
si->base_mem += 2 * sizeof(struct f2fs_inode_info); si->base_mem += 2 * sizeof(struct f2fs_inode_info);
si->base_mem += sizeof(*sbi->ckpt); si->base_mem += sizeof(*sbi->ckpt);
si->base_mem += sizeof(struct percpu_counter) * NR_COUNT_TYPE;
/* build sm */ /* build sm */
si->base_mem += sizeof(struct f2fs_sm_info); si->base_mem += sizeof(struct f2fs_sm_info);
...@@ -447,7 +439,7 @@ int f2fs_build_stats(struct f2fs_sb_info *sbi) ...@@ -447,7 +439,7 @@ int f2fs_build_stats(struct f2fs_sb_info *sbi)
struct f2fs_super_block *raw_super = F2FS_RAW_SUPER(sbi); struct f2fs_super_block *raw_super = F2FS_RAW_SUPER(sbi);
struct f2fs_stat_info *si; struct f2fs_stat_info *si;
si = kzalloc(sizeof(struct f2fs_stat_info), GFP_KERNEL); si = f2fs_kzalloc(sbi, sizeof(struct f2fs_stat_info), GFP_KERNEL);
if (!si) if (!si)
return -ENOMEM; return -ENOMEM;
......
...@@ -713,6 +713,8 @@ void f2fs_delete_entry(struct f2fs_dir_entry *dentry, struct page *page, ...@@ -713,6 +713,8 @@ void f2fs_delete_entry(struct f2fs_dir_entry *dentry, struct page *page,
f2fs_update_time(F2FS_I_SB(dir), REQ_TIME); f2fs_update_time(F2FS_I_SB(dir), REQ_TIME);
add_ino_entry(F2FS_I_SB(dir), dir->i_ino, TRANS_DIR_INO);
if (f2fs_has_inline_dentry(dir)) if (f2fs_has_inline_dentry(dir))
return f2fs_delete_inline_entry(dentry, page, dir, inode); return f2fs_delete_inline_entry(dentry, page, dir, inode);
...@@ -798,6 +800,7 @@ int f2fs_fill_dentries(struct dir_context *ctx, struct f2fs_dentry_ptr *d, ...@@ -798,6 +800,7 @@ int f2fs_fill_dentries(struct dir_context *ctx, struct f2fs_dentry_ptr *d,
unsigned int bit_pos; unsigned int bit_pos;
struct f2fs_dir_entry *de = NULL; struct f2fs_dir_entry *de = NULL;
struct fscrypt_str de_name = FSTR_INIT(NULL, 0); struct fscrypt_str de_name = FSTR_INIT(NULL, 0);
struct f2fs_sb_info *sbi = F2FS_I_SB(d->inode);
bit_pos = ((unsigned long)ctx->pos % d->max); bit_pos = ((unsigned long)ctx->pos % d->max);
...@@ -836,6 +839,9 @@ int f2fs_fill_dentries(struct dir_context *ctx, struct f2fs_dentry_ptr *d, ...@@ -836,6 +839,9 @@ int f2fs_fill_dentries(struct dir_context *ctx, struct f2fs_dentry_ptr *d,
le32_to_cpu(de->ino), d_type)) le32_to_cpu(de->ino), d_type))
return 1; return 1;
if (sbi->readdir_ra == 1)
ra_node_page(sbi, le32_to_cpu(de->ino));
bit_pos += GET_DENTRY_SLOTS(le16_to_cpu(de->name_len)); bit_pos += GET_DENTRY_SLOTS(le16_to_cpu(de->name_len));
ctx->pos = start_pos + bit_pos; ctx->pos = start_pos + bit_pos;
} }
......
This diff is collapsed.
This diff is collapsed.
...@@ -624,6 +624,11 @@ static void move_data_block(struct inode *inode, block_t bidx, ...@@ -624,6 +624,11 @@ static void move_data_block(struct inode *inode, block_t bidx,
if (f2fs_is_atomic_file(inode)) if (f2fs_is_atomic_file(inode))
goto out; goto out;
if (f2fs_is_pinned_file(inode)) {
f2fs_pin_file_control(inode, true);
goto out;
}
set_new_dnode(&dn, inode, NULL, NULL, 0); set_new_dnode(&dn, inode, NULL, NULL, 0);
err = get_dnode_of_data(&dn, bidx, LOOKUP_NODE); err = get_dnode_of_data(&dn, bidx, LOOKUP_NODE);
if (err) if (err)
...@@ -686,7 +691,12 @@ static void move_data_block(struct inode *inode, block_t bidx, ...@@ -686,7 +691,12 @@ static void move_data_block(struct inode *inode, block_t bidx,
fio.op = REQ_OP_WRITE; fio.op = REQ_OP_WRITE;
fio.op_flags = REQ_SYNC; fio.op_flags = REQ_SYNC;
fio.new_blkaddr = newaddr; fio.new_blkaddr = newaddr;
f2fs_submit_page_write(&fio); err = f2fs_submit_page_write(&fio);
if (err) {
if (PageWriteback(fio.encrypted_page))
end_page_writeback(fio.encrypted_page);
goto put_page_out;
}
f2fs_update_iostat(fio.sbi, FS_GC_DATA_IO, F2FS_BLKSIZE); f2fs_update_iostat(fio.sbi, FS_GC_DATA_IO, F2FS_BLKSIZE);
...@@ -720,6 +730,11 @@ static void move_data_page(struct inode *inode, block_t bidx, int gc_type, ...@@ -720,6 +730,11 @@ static void move_data_page(struct inode *inode, block_t bidx, int gc_type,
if (f2fs_is_atomic_file(inode)) if (f2fs_is_atomic_file(inode))
goto out; goto out;
if (f2fs_is_pinned_file(inode)) {
if (gc_type == FG_GC)
f2fs_pin_file_control(inode, true);
goto out;
}
if (gc_type == BG_GC) { if (gc_type == BG_GC) {
if (PageWriteback(page)) if (PageWriteback(page))
...@@ -1091,6 +1106,7 @@ void build_gc_manager(struct f2fs_sb_info *sbi) ...@@ -1091,6 +1106,7 @@ void build_gc_manager(struct f2fs_sb_info *sbi)
sbi->fggc_threshold = div64_u64((main_count - ovp_count) * sbi->fggc_threshold = div64_u64((main_count - ovp_count) *
BLKS_PER_SEC(sbi), (main_count - resv_count)); BLKS_PER_SEC(sbi), (main_count - resv_count));
sbi->gc_pin_file_threshold = DEF_GC_FAILED_PINNED_FILES;
/* give warm/cold data area from slower device */ /* give warm/cold data area from slower device */
if (sbi->s_ndevs && sbi->segs_per_sec == 1) if (sbi->s_ndevs && sbi->segs_per_sec == 1)
......
...@@ -20,6 +20,8 @@ ...@@ -20,6 +20,8 @@
#define LIMIT_INVALID_BLOCK 40 /* percentage over total user space */ #define LIMIT_INVALID_BLOCK 40 /* percentage over total user space */
#define LIMIT_FREE_BLOCK 40 /* percentage over invalid + free space */ #define LIMIT_FREE_BLOCK 40 /* percentage over invalid + free space */
#define DEF_GC_FAILED_PINNED_FILES 2048
/* Search max. number of dirty segments to select a victim segment */ /* Search max. number of dirty segments to select a victim segment */
#define DEF_MAX_VICTIM_SEARCH 4096 /* covers 8GB */ #define DEF_MAX_VICTIM_SEARCH 4096 /* covers 8GB */
......
...@@ -22,6 +22,9 @@ ...@@ -22,6 +22,9 @@
void f2fs_mark_inode_dirty_sync(struct inode *inode, bool sync) void f2fs_mark_inode_dirty_sync(struct inode *inode, bool sync)
{ {
if (is_inode_flag_set(inode, FI_NEW_INODE))
return;
if (f2fs_inode_dirtied(inode, sync)) if (f2fs_inode_dirtied(inode, sync))
return; return;
...@@ -275,6 +278,12 @@ static int do_read_inode(struct inode *inode) ...@@ -275,6 +278,12 @@ static int do_read_inode(struct inode *inode)
i_projid = F2FS_DEF_PROJID; i_projid = F2FS_DEF_PROJID;
fi->i_projid = make_kprojid(&init_user_ns, i_projid); fi->i_projid = make_kprojid(&init_user_ns, i_projid);
if (f2fs_has_extra_attr(inode) && f2fs_sb_has_inode_crtime(sbi->sb) &&
F2FS_FITS_IN_INODE(ri, fi->i_extra_isize, i_crtime)) {
fi->i_crtime.tv_sec = le64_to_cpu(ri->i_crtime);
fi->i_crtime.tv_nsec = le32_to_cpu(ri->i_crtime_nsec);
}
f2fs_put_page(node_page, 1); f2fs_put_page(node_page, 1);
stat_inc_inline_xattr(inode); stat_inc_inline_xattr(inode);
...@@ -360,14 +369,15 @@ struct inode *f2fs_iget_retry(struct super_block *sb, unsigned long ino) ...@@ -360,14 +369,15 @@ struct inode *f2fs_iget_retry(struct super_block *sb, unsigned long ino)
return inode; return inode;
} }
int update_inode(struct inode *inode, struct page *node_page) void update_inode(struct inode *inode, struct page *node_page)
{ {
struct f2fs_inode *ri; struct f2fs_inode *ri;
struct extent_tree *et = F2FS_I(inode)->extent_tree; struct extent_tree *et = F2FS_I(inode)->extent_tree;
f2fs_inode_synced(inode);
f2fs_wait_on_page_writeback(node_page, NODE, true); f2fs_wait_on_page_writeback(node_page, NODE, true);
set_page_dirty(node_page);
f2fs_inode_synced(inode);
ri = F2FS_INODE(node_page); ri = F2FS_INODE(node_page);
...@@ -417,6 +427,15 @@ int update_inode(struct inode *inode, struct page *node_page) ...@@ -417,6 +427,15 @@ int update_inode(struct inode *inode, struct page *node_page)
F2FS_I(inode)->i_projid); F2FS_I(inode)->i_projid);
ri->i_projid = cpu_to_le32(i_projid); ri->i_projid = cpu_to_le32(i_projid);
} }
if (f2fs_sb_has_inode_crtime(F2FS_I_SB(inode)->sb) &&
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);
}
} }
__set_inode_rdev(inode, ri); __set_inode_rdev(inode, ri);
...@@ -426,14 +445,12 @@ int update_inode(struct inode *inode, struct page *node_page) ...@@ -426,14 +445,12 @@ int update_inode(struct inode *inode, struct page *node_page)
if (inode->i_nlink == 0) if (inode->i_nlink == 0)
clear_inline_node(node_page); clear_inline_node(node_page);
return set_page_dirty(node_page);
} }
int update_inode_page(struct inode *inode) void update_inode_page(struct inode *inode)
{ {
struct f2fs_sb_info *sbi = F2FS_I_SB(inode); struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
struct page *node_page; struct page *node_page;
int ret = 0;
retry: retry:
node_page = get_node_page(sbi, inode->i_ino); node_page = get_node_page(sbi, inode->i_ino);
if (IS_ERR(node_page)) { if (IS_ERR(node_page)) {
...@@ -444,11 +461,10 @@ int update_inode_page(struct inode *inode) ...@@ -444,11 +461,10 @@ int update_inode_page(struct inode *inode)
} else if (err != -ENOENT) { } else if (err != -ENOENT) {
f2fs_stop_checkpoint(sbi, false); f2fs_stop_checkpoint(sbi, false);
} }
return 0; return;
} }
ret = update_inode(inode, node_page); update_inode(inode, node_page);
f2fs_put_page(node_page, 1); f2fs_put_page(node_page, 1);
return ret;
} }
int f2fs_write_inode(struct inode *inode, struct writeback_control *wbc) int f2fs_write_inode(struct inode *inode, struct writeback_control *wbc)
......
...@@ -50,7 +50,8 @@ static struct inode *f2fs_new_inode(struct inode *dir, umode_t mode) ...@@ -50,7 +50,8 @@ static struct inode *f2fs_new_inode(struct inode *dir, umode_t mode)
inode->i_ino = ino; inode->i_ino = ino;
inode->i_blocks = 0; inode->i_blocks = 0;
inode->i_mtime = inode->i_atime = inode->i_ctime = current_time(inode); inode->i_mtime = inode->i_atime = inode->i_ctime =
F2FS_I(inode)->i_crtime = current_time(inode);
inode->i_generation = sbi->s_next_generation++; inode->i_generation = sbi->s_next_generation++;
err = insert_inode_locked(inode); err = insert_inode_locked(inode);
...@@ -74,12 +75,12 @@ static struct inode *f2fs_new_inode(struct inode *dir, umode_t mode) ...@@ -74,12 +75,12 @@ static struct inode *f2fs_new_inode(struct inode *dir, umode_t mode)
if (err) if (err)
goto fail_drop; goto fail_drop;
set_inode_flag(inode, FI_NEW_INODE);
/* If the directory encrypted, then we should encrypt the inode. */ /* If the directory encrypted, then we should encrypt the inode. */
if (f2fs_encrypted_inode(dir) && f2fs_may_encrypt(inode)) if (f2fs_encrypted_inode(dir) && f2fs_may_encrypt(inode))
f2fs_set_encrypted_inode(inode); f2fs_set_encrypted_inode(inode);
set_inode_flag(inode, FI_NEW_INODE);
if (f2fs_sb_has_extra_attr(sbi->sb)) { if (f2fs_sb_has_extra_attr(sbi->sb)) {
set_inode_flag(inode, FI_EXTRA_ATTR); set_inode_flag(inode, FI_EXTRA_ATTR);
F2FS_I(inode)->i_extra_isize = F2FS_TOTAL_EXTRA_ATTR_SIZE; F2FS_I(inode)->i_extra_isize = F2FS_TOTAL_EXTRA_ATTR_SIZE;
...@@ -240,9 +241,9 @@ static int f2fs_link(struct dentry *old_dentry, struct inode *dir, ...@@ -240,9 +241,9 @@ static int f2fs_link(struct dentry *old_dentry, struct inode *dir,
if (unlikely(f2fs_cp_error(sbi))) if (unlikely(f2fs_cp_error(sbi)))
return -EIO; return -EIO;
if (f2fs_encrypted_inode(dir) && err = fscrypt_prepare_link(old_dentry, dir, dentry);
!fscrypt_has_permitted_context(dir, inode)) if (err)
return -EPERM; return err;
if (is_inode_flag_set(dir, FI_PROJ_INHERIT) && if (is_inode_flag_set(dir, FI_PROJ_INHERIT) &&
(!projid_eq(F2FS_I(dir)->i_projid, (!projid_eq(F2FS_I(dir)->i_projid,
...@@ -357,20 +358,9 @@ static struct dentry *f2fs_lookup(struct inode *dir, struct dentry *dentry, ...@@ -357,20 +358,9 @@ static struct dentry *f2fs_lookup(struct inode *dir, struct dentry *dentry,
trace_f2fs_lookup_start(dir, dentry, flags); trace_f2fs_lookup_start(dir, dentry, flags);
if (f2fs_encrypted_inode(dir)) { err = fscrypt_prepare_lookup(dir, dentry, flags);
err = fscrypt_get_encryption_info(dir); if (err)
/*
* DCACHE_ENCRYPTED_WITH_KEY is set if the dentry is
* created while the directory was encrypted and we
* don't have access to the key.
*/
if (fscrypt_has_encryption_key(dir))
fscrypt_set_encrypted_dentry(dentry);
fscrypt_set_d_op(dentry);
if (err && err != -ENOKEY)
goto out; goto out;
}
if (dentry->d_name.len > F2FS_NAME_LEN) { if (dentry->d_name.len > F2FS_NAME_LEN) {
err = -ENAMETOOLONG; err = -ENAMETOOLONG;
...@@ -544,7 +534,7 @@ static int f2fs_symlink(struct inode *dir, struct dentry *dentry, ...@@ -544,7 +534,7 @@ static int f2fs_symlink(struct inode *dir, struct dentry *dentry,
struct qstr istr = QSTR_INIT(symname, len); struct qstr istr = QSTR_INIT(symname, len);
struct fscrypt_str ostr; struct fscrypt_str ostr;
sd = kzalloc(disk_link.len, GFP_NOFS); sd = f2fs_kzalloc(sbi, disk_link.len, GFP_NOFS);
if (!sd) { if (!sd) {
err = -ENOMEM; err = -ENOMEM;
goto err_out; goto err_out;
...@@ -800,18 +790,6 @@ static int f2fs_rename(struct inode *old_dir, struct dentry *old_dentry, ...@@ -800,18 +790,6 @@ static int f2fs_rename(struct inode *old_dir, struct dentry *old_dentry,
if (unlikely(f2fs_cp_error(sbi))) if (unlikely(f2fs_cp_error(sbi)))
return -EIO; return -EIO;
if ((f2fs_encrypted_inode(old_dir) &&
!fscrypt_has_encryption_key(old_dir)) ||
(f2fs_encrypted_inode(new_dir) &&
!fscrypt_has_encryption_key(new_dir)))
return -ENOKEY;
if ((old_dir != new_dir) && f2fs_encrypted_inode(new_dir) &&
!fscrypt_has_permitted_context(new_dir, old_inode)) {
err = -EPERM;
goto out;
}
if (is_inode_flag_set(new_dir, FI_PROJ_INHERIT) && if (is_inode_flag_set(new_dir, FI_PROJ_INHERIT) &&
(!projid_eq(F2FS_I(new_dir)->i_projid, (!projid_eq(F2FS_I(new_dir)->i_projid,
F2FS_I(old_dentry->d_inode)->i_projid))) F2FS_I(old_dentry->d_inode)->i_projid)))
...@@ -958,6 +936,7 @@ static int f2fs_rename(struct inode *old_dir, struct dentry *old_dentry, ...@@ -958,6 +936,7 @@ static int f2fs_rename(struct inode *old_dir, struct dentry *old_dentry,
} }
f2fs_i_links_write(old_dir, false); f2fs_i_links_write(old_dir, false);
} }
add_ino_entry(sbi, new_dir->i_ino, TRANS_DIR_INO);
f2fs_unlock_op(sbi); f2fs_unlock_op(sbi);
...@@ -1002,18 +981,6 @@ static int f2fs_cross_rename(struct inode *old_dir, struct dentry *old_dentry, ...@@ -1002,18 +981,6 @@ static int f2fs_cross_rename(struct inode *old_dir, struct dentry *old_dentry,
if (unlikely(f2fs_cp_error(sbi))) if (unlikely(f2fs_cp_error(sbi)))
return -EIO; return -EIO;
if ((f2fs_encrypted_inode(old_dir) &&
!fscrypt_has_encryption_key(old_dir)) ||
(f2fs_encrypted_inode(new_dir) &&
!fscrypt_has_encryption_key(new_dir)))
return -ENOKEY;
if ((f2fs_encrypted_inode(old_dir) || f2fs_encrypted_inode(new_dir)) &&
(old_dir != new_dir) &&
(!fscrypt_has_permitted_context(new_dir, old_inode) ||
!fscrypt_has_permitted_context(old_dir, new_inode)))
return -EPERM;
if ((is_inode_flag_set(new_dir, FI_PROJ_INHERIT) && if ((is_inode_flag_set(new_dir, FI_PROJ_INHERIT) &&
!projid_eq(F2FS_I(new_dir)->i_projid, !projid_eq(F2FS_I(new_dir)->i_projid,
F2FS_I(old_dentry->d_inode)->i_projid)) || F2FS_I(old_dentry->d_inode)->i_projid)) ||
...@@ -1124,6 +1091,9 @@ static int f2fs_cross_rename(struct inode *old_dir, struct dentry *old_dentry, ...@@ -1124,6 +1091,9 @@ static int f2fs_cross_rename(struct inode *old_dir, struct dentry *old_dentry,
} }
f2fs_mark_inode_dirty_sync(new_dir, false); f2fs_mark_inode_dirty_sync(new_dir, false);
add_ino_entry(sbi, old_dir->i_ino, TRANS_DIR_INO);
add_ino_entry(sbi, new_dir->i_ino, TRANS_DIR_INO);
f2fs_unlock_op(sbi); f2fs_unlock_op(sbi);
if (IS_DIRSYNC(old_dir) || IS_DIRSYNC(new_dir)) if (IS_DIRSYNC(old_dir) || IS_DIRSYNC(new_dir))
...@@ -1153,9 +1123,16 @@ static int f2fs_rename2(struct inode *old_dir, struct dentry *old_dentry, ...@@ -1153,9 +1123,16 @@ static int f2fs_rename2(struct inode *old_dir, struct dentry *old_dentry,
struct inode *new_dir, struct dentry *new_dentry, struct inode *new_dir, struct dentry *new_dentry,
unsigned int flags) unsigned int flags)
{ {
int err;
if (flags & ~(RENAME_NOREPLACE | RENAME_EXCHANGE | RENAME_WHITEOUT)) if (flags & ~(RENAME_NOREPLACE | RENAME_EXCHANGE | RENAME_WHITEOUT))
return -EINVAL; return -EINVAL;
err = fscrypt_prepare_rename(old_dir, old_dentry, new_dir, new_dentry,
flags);
if (err)
return err;
if (flags & RENAME_EXCHANGE) { if (flags & RENAME_EXCHANGE) {
return f2fs_cross_rename(old_dir, old_dentry, return f2fs_cross_rename(old_dir, old_dentry,
new_dir, new_dentry); new_dir, new_dentry);
......
This diff is collapsed.
...@@ -305,6 +305,10 @@ static inline bool is_recoverable_dnode(struct page *page) ...@@ -305,6 +305,10 @@ static inline bool is_recoverable_dnode(struct page *page)
struct f2fs_checkpoint *ckpt = F2FS_CKPT(F2FS_P_SB(page)); struct f2fs_checkpoint *ckpt = F2FS_CKPT(F2FS_P_SB(page));
__u64 cp_ver = cur_cp_version(ckpt); __u64 cp_ver = cur_cp_version(ckpt);
/* Don't care crc part, if fsck.f2fs sets it. */
if (__is_set_ckpt_flags(ckpt, CP_NOCRC_RECOVERY_FLAG))
return (cp_ver << 32) == (cpver_of_node(page) << 32);
if (__is_set_ckpt_flags(ckpt, CP_CRC_RECOVERY_FLAG)) if (__is_set_ckpt_flags(ckpt, CP_CRC_RECOVERY_FLAG))
cp_ver |= (cur_cp_crc(ckpt) << 32); cp_ver |= (cur_cp_crc(ckpt) << 32);
......
...@@ -195,6 +195,20 @@ static int recover_dentry(struct inode *inode, struct page *ipage, ...@@ -195,6 +195,20 @@ static int recover_dentry(struct inode *inode, struct page *ipage,
return err; return err;
} }
static void recover_inline_flags(struct inode *inode, struct f2fs_inode *ri)
{
if (ri->i_inline & F2FS_PIN_FILE)
set_inode_flag(inode, FI_PIN_FILE);
else
clear_inode_flag(inode, FI_PIN_FILE);
if (ri->i_inline & F2FS_DATA_EXIST)
set_inode_flag(inode, FI_DATA_EXIST);
else
clear_inode_flag(inode, FI_DATA_EXIST);
if (!(ri->i_inline & F2FS_INLINE_DOTS))
clear_inode_flag(inode, FI_INLINE_DOTS);
}
static void recover_inode(struct inode *inode, struct page *page) static void recover_inode(struct inode *inode, struct page *page)
{ {
struct f2fs_inode *raw = F2FS_INODE(page); struct f2fs_inode *raw = F2FS_INODE(page);
...@@ -211,13 +225,16 @@ static void recover_inode(struct inode *inode, struct page *page) ...@@ -211,13 +225,16 @@ static void recover_inode(struct inode *inode, struct page *page)
F2FS_I(inode)->i_advise = raw->i_advise; F2FS_I(inode)->i_advise = raw->i_advise;
recover_inline_flags(inode, raw);
if (file_enc_name(inode)) if (file_enc_name(inode))
name = "<encrypted>"; name = "<encrypted>";
else else
name = F2FS_INODE(page)->i_name; name = F2FS_INODE(page)->i_name;
f2fs_msg(inode->i_sb, KERN_NOTICE, "recover_inode: ino = %x, name = %s", f2fs_msg(inode->i_sb, KERN_NOTICE,
ino_of_node(page), name); "recover_inode: ino = %x, name = %s, inline = %x",
ino_of_node(page), name, raw->i_inline);
} }
static int find_fsync_dnodes(struct f2fs_sb_info *sbi, struct list_head *head, static int find_fsync_dnodes(struct f2fs_sb_info *sbi, struct list_head *head,
...@@ -404,7 +421,7 @@ static int check_index_in_prev_nodes(struct f2fs_sb_info *sbi, ...@@ -404,7 +421,7 @@ static int check_index_in_prev_nodes(struct f2fs_sb_info *sbi,
} }
static int do_recover_data(struct f2fs_sb_info *sbi, struct inode *inode, static int do_recover_data(struct f2fs_sb_info *sbi, struct inode *inode,
struct page *page, block_t blkaddr) struct page *page)
{ {
struct dnode_of_data dn; struct dnode_of_data dn;
struct node_info ni; struct node_info ni;
...@@ -415,7 +432,7 @@ static int do_recover_data(struct f2fs_sb_info *sbi, struct inode *inode, ...@@ -415,7 +432,7 @@ static int do_recover_data(struct f2fs_sb_info *sbi, struct inode *inode,
if (IS_INODE(page)) { if (IS_INODE(page)) {
recover_inline_xattr(inode, page); recover_inline_xattr(inode, page);
} else if (f2fs_has_xattr_block(ofs_of_node(page))) { } else if (f2fs_has_xattr_block(ofs_of_node(page))) {
err = recover_xattr_data(inode, page, blkaddr); err = recover_xattr_data(inode, page);
if (!err) if (!err)
recovered++; recovered++;
goto out; goto out;
...@@ -568,7 +585,7 @@ static int recover_data(struct f2fs_sb_info *sbi, struct list_head *inode_list, ...@@ -568,7 +585,7 @@ static int recover_data(struct f2fs_sb_info *sbi, struct list_head *inode_list,
break; break;
} }
} }
err = do_recover_data(sbi, entry->inode, page, blkaddr); err = do_recover_data(sbi, entry->inode, page);
if (err) { if (err) {
f2fs_put_page(page, 1); f2fs_put_page(page, 1);
break; break;
......
This diff is collapsed.
...@@ -348,16 +348,41 @@ static inline void seg_info_from_raw_sit(struct seg_entry *se, ...@@ -348,16 +348,41 @@ static inline void seg_info_from_raw_sit(struct seg_entry *se,
se->mtime = le64_to_cpu(rs->mtime); se->mtime = le64_to_cpu(rs->mtime);
} }
static inline void seg_info_to_raw_sit(struct seg_entry *se, static inline void __seg_info_to_raw_sit(struct seg_entry *se,
struct f2fs_sit_entry *rs) struct f2fs_sit_entry *rs)
{ {
unsigned short raw_vblocks = (se->type << SIT_VBLOCKS_SHIFT) | unsigned short raw_vblocks = (se->type << SIT_VBLOCKS_SHIFT) |
se->valid_blocks; se->valid_blocks;
rs->vblocks = cpu_to_le16(raw_vblocks); rs->vblocks = cpu_to_le16(raw_vblocks);
memcpy(rs->valid_map, se->cur_valid_map, SIT_VBLOCK_MAP_SIZE); memcpy(rs->valid_map, se->cur_valid_map, SIT_VBLOCK_MAP_SIZE);
rs->mtime = cpu_to_le64(se->mtime);
}
static inline void seg_info_to_sit_page(struct f2fs_sb_info *sbi,
struct page *page, unsigned int start)
{
struct f2fs_sit_block *raw_sit;
struct seg_entry *se;
struct f2fs_sit_entry *rs;
unsigned int end = min(start + SIT_ENTRY_PER_BLOCK,
(unsigned long)MAIN_SEGS(sbi));
int i;
raw_sit = (struct f2fs_sit_block *)page_address(page);
for (i = 0; i < end - start; i++) {
rs = &raw_sit->entries[i];
se = get_seg_entry(sbi, start + i);
__seg_info_to_raw_sit(se, rs);
}
}
static inline void seg_info_to_raw_sit(struct seg_entry *se,
struct f2fs_sit_entry *rs)
{
__seg_info_to_raw_sit(se, rs);
memcpy(se->ckpt_valid_map, rs->valid_map, SIT_VBLOCK_MAP_SIZE); memcpy(se->ckpt_valid_map, rs->valid_map, SIT_VBLOCK_MAP_SIZE);
se->ckpt_valid_blocks = se->valid_blocks; se->ckpt_valid_blocks = se->valid_blocks;
rs->mtime = cpu_to_le64(se->mtime);
} }
static inline unsigned int find_next_inuse(struct free_segmap_info *free_i, static inline unsigned int find_next_inuse(struct free_segmap_info *free_i,
...@@ -580,47 +605,6 @@ enum { ...@@ -580,47 +605,6 @@ enum {
F2FS_IPU_ASYNC, F2FS_IPU_ASYNC,
}; };
static inline bool need_inplace_update_policy(struct inode *inode,
struct f2fs_io_info *fio)
{
struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
unsigned int policy = SM_I(sbi)->ipu_policy;
if (test_opt(sbi, LFS))
return false;
/* if this is cold file, we should overwrite to avoid fragmentation */
if (file_is_cold(inode))
return true;
if (policy & (0x1 << F2FS_IPU_FORCE))
return true;
if (policy & (0x1 << F2FS_IPU_SSR) && need_SSR(sbi))
return true;
if (policy & (0x1 << F2FS_IPU_UTIL) &&
utilization(sbi) > SM_I(sbi)->min_ipu_util)
return true;
if (policy & (0x1 << F2FS_IPU_SSR_UTIL) && need_SSR(sbi) &&
utilization(sbi) > SM_I(sbi)->min_ipu_util)
return true;
/*
* IPU for rewrite async pages
*/
if (policy & (0x1 << F2FS_IPU_ASYNC) &&
fio && fio->op == REQ_OP_WRITE &&
!(fio->op_flags & REQ_SYNC) &&
!f2fs_encrypted_inode(inode))
return true;
/* this is only set during fdatasync */
if (policy & (0x1 << F2FS_IPU_FSYNC) &&
is_inode_flag_set(inode, FI_NEED_IPU))
return true;
return false;
}
static inline unsigned int curseg_segno(struct f2fs_sb_info *sbi, static inline unsigned int curseg_segno(struct f2fs_sb_info *sbi,
int type) int type)
{ {
...@@ -655,7 +639,7 @@ static inline void verify_block_addr(struct f2fs_sb_info *sbi, block_t blk_addr) ...@@ -655,7 +639,7 @@ static inline void verify_block_addr(struct f2fs_sb_info *sbi, block_t blk_addr)
/* /*
* Summary block is always treated as an invalid block * Summary block is always treated as an invalid block
*/ */
static inline void check_block_count(struct f2fs_sb_info *sbi, static inline int check_block_count(struct f2fs_sb_info *sbi,
int segno, struct f2fs_sit_entry *raw_sit) int segno, struct f2fs_sit_entry *raw_sit)
{ {
#ifdef CONFIG_F2FS_CHECK_FS #ifdef CONFIG_F2FS_CHECK_FS
...@@ -677,11 +661,25 @@ static inline void check_block_count(struct f2fs_sb_info *sbi, ...@@ -677,11 +661,25 @@ static inline void check_block_count(struct f2fs_sb_info *sbi,
cur_pos = next_pos; cur_pos = next_pos;
is_valid = !is_valid; is_valid = !is_valid;
} while (cur_pos < sbi->blocks_per_seg); } while (cur_pos < sbi->blocks_per_seg);
BUG_ON(GET_SIT_VBLOCKS(raw_sit) != valid_blocks);
if (unlikely(GET_SIT_VBLOCKS(raw_sit) != valid_blocks)) {
f2fs_msg(sbi->sb, KERN_ERR,
"Mismatch valid blocks %d vs. %d",
GET_SIT_VBLOCKS(raw_sit), valid_blocks);
set_sbi_flag(sbi, SBI_NEED_FSCK);
return -EINVAL;
}
#endif #endif
/* check segment usage, and check boundary of a given segment number */ /* check segment usage, and check boundary of a given segment number */
f2fs_bug_on(sbi, GET_SIT_VBLOCKS(raw_sit) > sbi->blocks_per_seg if (unlikely(GET_SIT_VBLOCKS(raw_sit) > sbi->blocks_per_seg
|| segno > TOTAL_SEGS(sbi) - 1); || segno > TOTAL_SEGS(sbi) - 1)) {
f2fs_msg(sbi->sb, KERN_ERR,
"Wrong valid blocks %d or segno %u",
GET_SIT_VBLOCKS(raw_sit), segno);
set_sbi_flag(sbi, SBI_NEED_FSCK);
return -EINVAL;
}
return 0;
} }
static inline pgoff_t current_sit_addr(struct f2fs_sb_info *sbi, static inline pgoff_t current_sit_addr(struct f2fs_sb_info *sbi,
......
This diff is collapsed.
...@@ -113,6 +113,9 @@ static ssize_t features_show(struct f2fs_attr *a, ...@@ -113,6 +113,9 @@ static ssize_t features_show(struct f2fs_attr *a,
if (f2fs_sb_has_quota_ino(sb)) if (f2fs_sb_has_quota_ino(sb))
len += snprintf(buf + len, PAGE_SIZE - len, "%s%s", len += snprintf(buf + len, PAGE_SIZE - len, "%s%s",
len ? ", " : "", "quota_ino"); len ? ", " : "", "quota_ino");
if (f2fs_sb_has_inode_crtime(sb))
len += snprintf(buf + len, PAGE_SIZE - len, "%s%s",
len ? ", " : "", "inode_crtime");
len += snprintf(buf + len, PAGE_SIZE - len, "\n"); len += snprintf(buf + len, PAGE_SIZE - len, "\n");
return len; return len;
} }
...@@ -162,7 +165,8 @@ static ssize_t f2fs_sbi_store(struct f2fs_attr *a, ...@@ -162,7 +165,8 @@ static ssize_t f2fs_sbi_store(struct f2fs_attr *a,
#endif #endif
if (a->struct_type == RESERVED_BLOCKS) { if (a->struct_type == RESERVED_BLOCKS) {
spin_lock(&sbi->stat_lock); spin_lock(&sbi->stat_lock);
if (t > (unsigned long)sbi->user_block_count) { if (t > (unsigned long)(sbi->user_block_count -
sbi->root_reserved_blocks)) {
spin_unlock(&sbi->stat_lock); spin_unlock(&sbi->stat_lock);
return -EINVAL; return -EINVAL;
} }
...@@ -231,6 +235,7 @@ enum feat_id { ...@@ -231,6 +235,7 @@ enum feat_id {
FEAT_INODE_CHECKSUM, FEAT_INODE_CHECKSUM,
FEAT_FLEXIBLE_INLINE_XATTR, FEAT_FLEXIBLE_INLINE_XATTR,
FEAT_QUOTA_INO, FEAT_QUOTA_INO,
FEAT_INODE_CRTIME,
}; };
static ssize_t f2fs_feature_show(struct f2fs_attr *a, static ssize_t f2fs_feature_show(struct f2fs_attr *a,
...@@ -245,6 +250,7 @@ static ssize_t f2fs_feature_show(struct f2fs_attr *a, ...@@ -245,6 +250,7 @@ static ssize_t f2fs_feature_show(struct f2fs_attr *a,
case FEAT_INODE_CHECKSUM: case FEAT_INODE_CHECKSUM:
case FEAT_FLEXIBLE_INLINE_XATTR: case FEAT_FLEXIBLE_INLINE_XATTR:
case FEAT_QUOTA_INO: case FEAT_QUOTA_INO:
case FEAT_INODE_CRTIME:
return snprintf(buf, PAGE_SIZE, "supported\n"); return snprintf(buf, PAGE_SIZE, "supported\n");
} }
return 0; return 0;
...@@ -299,6 +305,8 @@ F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, dir_level, dir_level); ...@@ -299,6 +305,8 @@ F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, dir_level, dir_level);
F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, cp_interval, interval_time[CP_TIME]); F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, cp_interval, interval_time[CP_TIME]);
F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, idle_interval, interval_time[REQ_TIME]); F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, idle_interval, interval_time[REQ_TIME]);
F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, iostat_enable, iostat_enable); 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);
#ifdef CONFIG_F2FS_FAULT_INJECTION #ifdef CONFIG_F2FS_FAULT_INJECTION
F2FS_RW_ATTR(FAULT_INFO_RATE, f2fs_fault_info, inject_rate, inject_rate); 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); F2FS_RW_ATTR(FAULT_INFO_TYPE, f2fs_fault_info, inject_type, inject_type);
...@@ -320,6 +328,7 @@ F2FS_FEATURE_RO_ATTR(project_quota, FEAT_PROJECT_QUOTA); ...@@ -320,6 +328,7 @@ F2FS_FEATURE_RO_ATTR(project_quota, FEAT_PROJECT_QUOTA);
F2FS_FEATURE_RO_ATTR(inode_checksum, FEAT_INODE_CHECKSUM); F2FS_FEATURE_RO_ATTR(inode_checksum, FEAT_INODE_CHECKSUM);
F2FS_FEATURE_RO_ATTR(flexible_inline_xattr, FEAT_FLEXIBLE_INLINE_XATTR); F2FS_FEATURE_RO_ATTR(flexible_inline_xattr, FEAT_FLEXIBLE_INLINE_XATTR);
F2FS_FEATURE_RO_ATTR(quota_ino, FEAT_QUOTA_INO); F2FS_FEATURE_RO_ATTR(quota_ino, FEAT_QUOTA_INO);
F2FS_FEATURE_RO_ATTR(inode_crtime, FEAT_INODE_CRTIME);
#define ATTR_LIST(name) (&f2fs_attr_##name.attr) #define ATTR_LIST(name) (&f2fs_attr_##name.attr)
static struct attribute *f2fs_attrs[] = { static struct attribute *f2fs_attrs[] = {
...@@ -346,6 +355,8 @@ static struct attribute *f2fs_attrs[] = { ...@@ -346,6 +355,8 @@ static struct attribute *f2fs_attrs[] = {
ATTR_LIST(cp_interval), ATTR_LIST(cp_interval),
ATTR_LIST(idle_interval), ATTR_LIST(idle_interval),
ATTR_LIST(iostat_enable), ATTR_LIST(iostat_enable),
ATTR_LIST(readdir_ra),
ATTR_LIST(gc_pin_file_thresh),
#ifdef CONFIG_F2FS_FAULT_INJECTION #ifdef CONFIG_F2FS_FAULT_INJECTION
ATTR_LIST(inject_rate), ATTR_LIST(inject_rate),
ATTR_LIST(inject_type), ATTR_LIST(inject_type),
...@@ -371,6 +382,7 @@ static struct attribute *f2fs_feat_attrs[] = { ...@@ -371,6 +382,7 @@ static struct attribute *f2fs_feat_attrs[] = {
ATTR_LIST(inode_checksum), ATTR_LIST(inode_checksum),
ATTR_LIST(flexible_inline_xattr), ATTR_LIST(flexible_inline_xattr),
ATTR_LIST(quota_ino), ATTR_LIST(quota_ino),
ATTR_LIST(inode_crtime),
NULL, NULL,
}; };
......
...@@ -17,7 +17,7 @@ ...@@ -17,7 +17,7 @@
#include "trace.h" #include "trace.h"
static RADIX_TREE(pids, GFP_ATOMIC); static RADIX_TREE(pids, GFP_ATOMIC);
static spinlock_t pids_lock; static struct mutex pids_lock;
static struct last_io_info last_io; static struct last_io_info last_io;
static inline void __print_last_io(void) static inline void __print_last_io(void)
...@@ -64,7 +64,7 @@ void f2fs_trace_pid(struct page *page) ...@@ -64,7 +64,7 @@ void f2fs_trace_pid(struct page *page)
if (radix_tree_preload(GFP_NOFS)) if (radix_tree_preload(GFP_NOFS))
return; return;
spin_lock(&pids_lock); mutex_lock(&pids_lock);
p = radix_tree_lookup(&pids, pid); p = radix_tree_lookup(&pids, pid);
if (p == current) if (p == current)
goto out; goto out;
...@@ -77,7 +77,7 @@ void f2fs_trace_pid(struct page *page) ...@@ -77,7 +77,7 @@ void f2fs_trace_pid(struct page *page)
MAJOR(inode->i_sb->s_dev), MINOR(inode->i_sb->s_dev), MAJOR(inode->i_sb->s_dev), MINOR(inode->i_sb->s_dev),
pid, current->comm); pid, current->comm);
out: out:
spin_unlock(&pids_lock); mutex_unlock(&pids_lock);
radix_tree_preload_end(); radix_tree_preload_end();
} }
...@@ -122,7 +122,7 @@ void f2fs_trace_ios(struct f2fs_io_info *fio, int flush) ...@@ -122,7 +122,7 @@ void f2fs_trace_ios(struct f2fs_io_info *fio, int flush)
void f2fs_build_trace_ios(void) void f2fs_build_trace_ios(void)
{ {
spin_lock_init(&pids_lock); mutex_init(&pids_lock);
} }
#define PIDVEC_SIZE 128 #define PIDVEC_SIZE 128
...@@ -150,7 +150,7 @@ void f2fs_destroy_trace_ios(void) ...@@ -150,7 +150,7 @@ void f2fs_destroy_trace_ios(void)
pid_t next_pid = 0; pid_t next_pid = 0;
unsigned int found; unsigned int found;
spin_lock(&pids_lock); mutex_lock(&pids_lock);
while ((found = gang_lookup_pids(pid, next_pid, PIDVEC_SIZE))) { while ((found = gang_lookup_pids(pid, next_pid, PIDVEC_SIZE))) {
unsigned idx; unsigned idx;
...@@ -158,5 +158,5 @@ void f2fs_destroy_trace_ios(void) ...@@ -158,5 +158,5 @@ void f2fs_destroy_trace_ios(void)
for (idx = 0; idx < found; idx++) for (idx = 0; idx < found; idx++)
radix_tree_delete(&pids, pid[idx]); radix_tree_delete(&pids, pid[idx]);
} }
spin_unlock(&pids_lock); mutex_unlock(&pids_lock);
} }
...@@ -298,8 +298,8 @@ static int lookup_all_xattrs(struct inode *inode, struct page *ipage, ...@@ -298,8 +298,8 @@ static int lookup_all_xattrs(struct inode *inode, struct page *ipage,
if (!size && !inline_size) if (!size && !inline_size)
return -ENODATA; return -ENODATA;
txattr_addr = kzalloc(inline_size + size + XATTR_PADDING_SIZE, txattr_addr = f2fs_kzalloc(F2FS_I_SB(inode),
GFP_F2FS_ZERO); inline_size + size + XATTR_PADDING_SIZE, GFP_NOFS);
if (!txattr_addr) if (!txattr_addr)
return -ENOMEM; return -ENOMEM;
...@@ -351,8 +351,8 @@ static int read_all_xattrs(struct inode *inode, struct page *ipage, ...@@ -351,8 +351,8 @@ static int read_all_xattrs(struct inode *inode, struct page *ipage,
void *txattr_addr; void *txattr_addr;
int err; int err;
txattr_addr = kzalloc(inline_size + size + XATTR_PADDING_SIZE, txattr_addr = f2fs_kzalloc(F2FS_I_SB(inode),
GFP_F2FS_ZERO); inline_size + size + XATTR_PADDING_SIZE, GFP_NOFS);
if (!txattr_addr) if (!txattr_addr)
return -ENOMEM; return -ENOMEM;
...@@ -433,6 +433,7 @@ static inline int write_all_xattrs(struct inode *inode, __u32 hsize, ...@@ -433,6 +433,7 @@ static inline int write_all_xattrs(struct inode *inode, __u32 hsize,
if (F2FS_I(inode)->i_xattr_nid) { if (F2FS_I(inode)->i_xattr_nid) {
xpage = get_node_page(sbi, F2FS_I(inode)->i_xattr_nid); xpage = get_node_page(sbi, F2FS_I(inode)->i_xattr_nid);
if (IS_ERR(xpage)) { if (IS_ERR(xpage)) {
err = PTR_ERR(xpage);
alloc_nid_failed(sbi, new_nid); alloc_nid_failed(sbi, new_nid);
goto in_page_out; goto in_page_out;
} }
...@@ -443,6 +444,7 @@ static inline int write_all_xattrs(struct inode *inode, __u32 hsize, ...@@ -443,6 +444,7 @@ static inline int write_all_xattrs(struct inode *inode, __u32 hsize,
set_new_dnode(&dn, inode, NULL, NULL, new_nid); set_new_dnode(&dn, inode, NULL, NULL, new_nid);
xpage = new_node_page(&dn, XATTR_NODE_OFFSET); xpage = new_node_page(&dn, XATTR_NODE_OFFSET);
if (IS_ERR(xpage)) { if (IS_ERR(xpage)) {
err = PTR_ERR(xpage);
alloc_nid_failed(sbi, new_nid); alloc_nid_failed(sbi, new_nid);
goto in_page_out; goto in_page_out;
} }
...@@ -598,7 +600,7 @@ static int __f2fs_setxattr(struct inode *inode, int index, ...@@ -598,7 +600,7 @@ static int __f2fs_setxattr(struct inode *inode, int index,
goto exit; goto exit;
} }
if (f2fs_xattr_value_same(here, value, size)) if (value && f2fs_xattr_value_same(here, value, size))
goto exit; goto exit;
} else if ((flags & XATTR_REPLACE)) { } else if ((flags & XATTR_REPLACE)) {
error = -ENODATA; error = -ENODATA;
......
...@@ -43,7 +43,7 @@ struct posix_acl *get_cached_acl(struct inode *inode, int type) ...@@ -43,7 +43,7 @@ struct posix_acl *get_cached_acl(struct inode *inode, int type)
rcu_read_lock(); rcu_read_lock();
acl = rcu_dereference(*p); acl = rcu_dereference(*p);
if (!acl || is_uncached_acl(acl) || if (!acl || is_uncached_acl(acl) ||
atomic_inc_not_zero(&acl->a_refcount)) refcount_inc_not_zero(&acl->a_refcount))
break; break;
rcu_read_unlock(); rcu_read_unlock();
cpu_relax(); cpu_relax();
...@@ -164,7 +164,7 @@ EXPORT_SYMBOL(get_acl); ...@@ -164,7 +164,7 @@ EXPORT_SYMBOL(get_acl);
void void
posix_acl_init(struct posix_acl *acl, int count) posix_acl_init(struct posix_acl *acl, int count)
{ {
atomic_set(&acl->a_refcount, 1); refcount_set(&acl->a_refcount, 1);
acl->a_count = count; acl->a_count = count;
} }
EXPORT_SYMBOL(posix_acl_init); EXPORT_SYMBOL(posix_acl_init);
...@@ -197,7 +197,7 @@ posix_acl_clone(const struct posix_acl *acl, gfp_t flags) ...@@ -197,7 +197,7 @@ posix_acl_clone(const struct posix_acl *acl, gfp_t flags)
sizeof(struct posix_acl_entry); sizeof(struct posix_acl_entry);
clone = kmemdup(acl, size, flags); clone = kmemdup(acl, size, flags);
if (clone) if (clone)
atomic_set(&clone->a_refcount, 1); refcount_set(&clone->a_refcount, 1);
} }
return clone; return clone;
} }
......
...@@ -117,6 +117,7 @@ struct f2fs_super_block { ...@@ -117,6 +117,7 @@ struct f2fs_super_block {
/* /*
* For checkpoint * For checkpoint
*/ */
#define CP_NOCRC_RECOVERY_FLAG 0x00000200
#define CP_TRIMMED_FLAG 0x00000100 #define CP_TRIMMED_FLAG 0x00000100
#define CP_NAT_BITS_FLAG 0x00000080 #define CP_NAT_BITS_FLAG 0x00000080
#define CP_CRC_RECOVERY_FLAG 0x00000040 #define CP_CRC_RECOVERY_FLAG 0x00000040
...@@ -212,6 +213,7 @@ struct f2fs_extent { ...@@ -212,6 +213,7 @@ struct f2fs_extent {
#define F2FS_DATA_EXIST 0x08 /* file inline data exist flag */ #define F2FS_DATA_EXIST 0x08 /* file inline data exist flag */
#define F2FS_INLINE_DOTS 0x10 /* file having implicit dot dentries */ #define F2FS_INLINE_DOTS 0x10 /* file having implicit dot dentries */
#define F2FS_EXTRA_ATTR 0x20 /* file having extra attribute */ #define F2FS_EXTRA_ATTR 0x20 /* file having extra attribute */
#define F2FS_PIN_FILE 0x40 /* file should not be gced */
struct f2fs_inode { struct f2fs_inode {
__le16 i_mode; /* file mode */ __le16 i_mode; /* file mode */
...@@ -229,7 +231,13 @@ struct f2fs_inode { ...@@ -229,7 +231,13 @@ struct f2fs_inode {
__le32 i_ctime_nsec; /* change time in nano scale */ __le32 i_ctime_nsec; /* change time in nano scale */
__le32 i_mtime_nsec; /* modification time in nano scale */ __le32 i_mtime_nsec; /* modification time in nano scale */
__le32 i_generation; /* file version (for NFS) */ __le32 i_generation; /* file version (for NFS) */
union {
__le32 i_current_depth; /* only for directory depth */ __le32 i_current_depth; /* only for directory depth */
__le16 i_gc_failures; /*
* # of gc failures on pinned file.
* only for regular files.
*/
};
__le32 i_xattr_nid; /* nid to save xattr */ __le32 i_xattr_nid; /* nid to save xattr */
__le32 i_flags; /* file attributes */ __le32 i_flags; /* file attributes */
__le32 i_pino; /* parent inode number */ __le32 i_pino; /* parent inode number */
...@@ -245,8 +253,10 @@ struct f2fs_inode { ...@@ -245,8 +253,10 @@ struct f2fs_inode {
__le16 i_inline_xattr_size; /* inline xattr size, unit: 4 bytes */ __le16 i_inline_xattr_size; /* inline xattr size, unit: 4 bytes */
__le32 i_projid; /* project id */ __le32 i_projid; /* project id */
__le32 i_inode_checksum;/* inode meta checksum */ __le32 i_inode_checksum;/* inode meta checksum */
__le64 i_crtime; /* creation time */
__le32 i_crtime_nsec; /* creation time in nano scale */
__le32 i_extra_end[0]; /* for attribute size calculation */ __le32 i_extra_end[0]; /* for attribute size calculation */
}; } __packed;
__le32 i_addr[DEF_ADDRS_PER_INODE]; /* Pointers to data blocks */ __le32 i_addr[DEF_ADDRS_PER_INODE]; /* Pointers to data blocks */
}; };
__le32 i_nid[DEF_NIDS_PER_INODE]; /* direct(2), indirect(2), __le32 i_nid[DEF_NIDS_PER_INODE]; /* direct(2), indirect(2),
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include <linux/bug.h> #include <linux/bug.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/rcupdate.h> #include <linux/rcupdate.h>
#include <linux/refcount.h>
#include <uapi/linux/posix_acl.h> #include <uapi/linux/posix_acl.h>
struct posix_acl_entry { struct posix_acl_entry {
...@@ -24,7 +25,7 @@ struct posix_acl_entry { ...@@ -24,7 +25,7 @@ struct posix_acl_entry {
}; };
struct posix_acl { struct posix_acl {
atomic_t a_refcount; refcount_t a_refcount;
struct rcu_head a_rcu; struct rcu_head a_rcu;
unsigned int a_count; unsigned int a_count;
struct posix_acl_entry a_entries[0]; struct posix_acl_entry a_entries[0];
...@@ -41,7 +42,7 @@ static inline struct posix_acl * ...@@ -41,7 +42,7 @@ static inline struct posix_acl *
posix_acl_dup(struct posix_acl *acl) posix_acl_dup(struct posix_acl *acl)
{ {
if (acl) if (acl)
atomic_inc(&acl->a_refcount); refcount_inc(&acl->a_refcount);
return acl; return acl;
} }
...@@ -51,7 +52,7 @@ posix_acl_dup(struct posix_acl *acl) ...@@ -51,7 +52,7 @@ posix_acl_dup(struct posix_acl *acl)
static inline void static inline void
posix_acl_release(struct posix_acl *acl) posix_acl_release(struct posix_acl *acl)
{ {
if (acl && atomic_dec_and_test(&acl->a_refcount)) if (acl && refcount_dec_and_test(&acl->a_refcount))
kfree_rcu(acl, a_rcu); kfree_rcu(acl, a_rcu);
} }
......
...@@ -147,7 +147,8 @@ TRACE_DEFINE_ENUM(CP_TRIMMED); ...@@ -147,7 +147,8 @@ TRACE_DEFINE_ENUM(CP_TRIMMED);
{ CP_NO_SPC_ROLL, "no space roll forward" }, \ { CP_NO_SPC_ROLL, "no space roll forward" }, \
{ CP_NODE_NEED_CP, "node needs cp" }, \ { CP_NODE_NEED_CP, "node needs cp" }, \
{ CP_FASTBOOT_MODE, "fastboot mode" }, \ { CP_FASTBOOT_MODE, "fastboot mode" }, \
{ CP_SPEC_LOG_NUM, "log type is 2" }) { CP_SPEC_LOG_NUM, "log type is 2" }, \
{ CP_RECOVER_DIR, "dir needs recovery" })
struct victim_sel_policy; struct victim_sel_policy;
struct f2fs_map_blocks; struct f2fs_map_blocks;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment