diff options
| author | Jaegeuk Kim <jaegeuk@google.com> | 2018-07-30 17:25:04 -0700 |
|---|---|---|
| committer | Jaegeuk Kim <jaegeuk@google.com> | 2018-07-30 17:25:04 -0700 |
| commit | 8ddb600e033f69a1316e65d6af21eb3dc11501f2 (patch) | |
| tree | c58c940325459ce055936aa7abaabdc0ea640ded /fs/f2fs/inode.c | |
| parent | b826c97998ef8d98843e9207214a869f4ca3e448 (diff) | |
| parent | 6944da0a68ca00f8f27bd71e0e0e292ea14b5ca5 (diff) | |
Merge remote-tracking branch 'origin/upstream-f2fs-stable-linux-4.4.y' into android-4.4
6944da0a68ca treewide: Use array_size in f2fs_kvzalloc()
f15443db99c3 treewide: Use array_size() in f2fs_kzalloc()
3ea03ea4bd09 treewide: Use array_size() in f2fs_kmalloc()
c41203299a52 overflow.h: Add allocation size calculation helpers
d400752f547f f2fs: fix to clear FI_VOLATILE_FILE correctly
853e7339b634 f2fs: let sync node IO interrupt async one
6a4540cf1984 f2fs: don't change wbc->sync_mode
588ecdfd7d02 f2fs: fix to update mtime correctly
1ae5aadab191 fs: f2fs: insert space around that ':' and ', '
39ee53e22320 fs: f2fs: add missing blank lines after declarations
d5b4710fcf38 fs: f2fs: changed variable type of offset "unsigned" to "loff_t"
c35da89531b3 f2fs: clean up symbol namespace
fcf37e16f3cb f2fs: make set_de_type() static
5d1633aa1071 f2fs: make __f2fs_write_data_pages() static
cc8093af7c42 f2fs: fix to avoid accessing cross the boundary
b7f559467095 f2fs: fix to let caller retry allocating block address
e48fcd857657 disable loading f2fs module on PAGE_SIZE > 4KB
02afc275a5bd f2fs: fix error path of move_data_page
0291bd36d076 f2fs: don't drop dentry pages after fs shutdown
a1259450b6db f2fs: fix to avoid race during access gc_thread pointer
d2e0f2f786a6 f2fs: clean up with clear_radix_tree_dirty_tag
c74034518fdc f2fs: fix to don't trigger writeback during recovery
e72a2cca82d8 f2fs: clear discard_wake earlier
b25a1872e9a5 f2fs: let discard thread wait a little longer if dev is busy
b125dfb20d18 f2fs: avoid stucking GC due to atomic write
405909e7f532 f2fs: introduce sbi->gc_mode to determine the policy
1f62e4702a34 f2fs: keep migration IO order in LFS mode
c4408c238722 f2fs: fix to wait page writeback during revoking atomic write
9db5be4af890 f2fs: Fix deadlock in shutdown ioctl
ed74404955cd f2fs: detect synchronous writeback more earlier
91e7d9d2ddbf mm: remove nr_pages argument from pagevec_lookup_{,range}_tag()
feb94dc82928 ceph: use pagevec_lookup_range_nr_tag()
f3aa4a25b8b0 mm: add variant of pagevec_lookup_range_tag() taking number of pages
8914877e374a mm: use pagevec_lookup_range_tag() in write_cache_pages()
26778b87a006 mm: use pagevec_lookup_range_tag() in __filemap_fdatawait_range()
94f1b99298bd nilfs2: use pagevec_lookup_range_tag()
160355d69f46 gfs2: use pagevec_lookup_range_tag()
564108e83a74 f2fs: use find_get_pages_tag() for looking up single page
6cf6fb8645ff f2fs: simplify page iteration loops
a05d8a6a2bde f2fs: use pagevec_lookup_range_tag()
18a4848ffded ext4: use pagevec_lookup_range_tag()
1c7be24f65cd ceph: use pagevec_lookup_range_tag()
e25fadabb5c7 btrfs: use pagevec_lookup_range_tag()
bf9510b162c4 mm: implement find_get_pages_range_tag()
461247b21fde f2fs: clean up with is_valid_blkaddr()
a5d0ccbc189a f2fs: fix to initialize min_mtime with ULLONG_MAX
9bb4d22cf5de f2fs: fix to let checkpoint guarantee atomic page persistence
cdcf2b3e2559 f2fs: fix to initialize i_current_depth according to inode type
331ae0c25b44 Revert "f2fs: add ovp valid_blocks check for bg gc victim to fg_gc"
2494cc7c0bcd f2fs: don't drop any page on f2fs_cp_error() case
0037c639e63d f2fs: fix spelling mistake: "extenstion" -> "extension"
2bba5b8eb867 f2fs: enhance sanity_check_raw_super() to avoid potential overflows
9bb86b63dc0f f2fs: treat volatile file's data as hot one
2cf64590361e f2fs: introduce release_discard_addr() for cleanup
03279ce90b46 f2fs: fix potential overflow
f46eddc4da48 f2fs: rename dio_rwsem to i_gc_rwsem
bb015824532c f2fs: move mnt_want_write_file after range check
8bb9a8da75d1 f2fs: fix missing clear FI_NO_PREALLOC in some error case
cb38cc4e1d02 f2fs: enforce fsync_mode=strict for renamed directory
26bf4e8a96aa f2fs: sanity check for total valid node blocks
78f8b0f46fa2 f2fs: sanity check on sit entry
ab758ada220f f2fs: avoid bug_on on corrupted inode
1a5d1966c0ca f2fs: give message and set need_fsck given broken node id
b025f6dfc018 f2fs: clean up commit_inmem_pages()
7aff5c69da4c f2fs: do not check F2FS_INLINE_DOTS in recover
23d00b02878e f2fs: remove duplicated dquot_initialize and fix error handling
937f4ef79e25 f2fs: stop issue discard if something wrong with f2fs
a6d74bb282ad f2fs: fix return value in f2fs_ioc_commit_atomic_write
258489ec5220 f2fs: allocate hot_data for atomic write more strictly
aa857e0f3b09 f2fs: check if inmem_pages list is empty correctly
9d77ded0a71d f2fs: fix race in between GC and atomic open
0d17eb90b56a f2fs: change le32 to le16 of f2fs_inode->i_extra_size
ea2813111f1f f2fs: check cur_valid_map_mir & raw_sit block count when flush sit entries
9190cadf38db f2fs: correct return value of f2fs_trim_fs
17f85d070886 f2fs: fix to show missing bits in FS_IOC_GETFLAGS
3e90db63fcfc f2fs: remove unneeded F2FS_PROJINHERIT_FL
298032d4d4a6 f2fs: don't use GFP_ZERO for page caches
fdf61219dc25 f2fs: issue all big range discards in umount process
cd79eb2b5e45 f2fs: remove redundant block plug
ec034d0f14ca f2fs: remove unmatched zero_user_segment when convert inline dentry
71aaced0e1ee f2fs: introduce private inode status mapping
e7724207f71e fscrypt: log the crypto algorithm implementations
4cbda579cd3d crypto: api - Add crypto_type_has_alg helper
b24dcaae8753 crypto: skcipher - Add low-level skcipher interface
a9146e423547 crypto: skcipher - Add helper to retrieve driver name
a0ca4bdf4744 crypto: skcipher - Add default key size helper
eb13e0b69296 fscrypt: add Speck128/256 support
27a0e77380a3 fscrypt: only derive the needed portion of the key
f68a71fa8f77 fscrypt: separate key lookup from key derivation
52359cf4fd6d fscrypt: use a common logging function
ff8e7c745e2b fscrypt: remove internal key size constants
7149dd4d39b5 fscrypt: remove unnecessary check for non-logon key type
56446c91422e fscrypt: make fscrypt_operations.max_namelen an integer
f572a22ef9a5 fscrypt: drop empty name check from fname_decrypt()
0077eff1d2e3 fscrypt: drop max_namelen check from fname_decrypt()
3f7af9d27fd6 fscrypt: don't special-case EOPNOTSUPP from fscrypt_get_encryption_info()
52c51f7b7bde fscrypt: don't clear flags on crypto transform
89b7fb82982f fscrypt: remove stale comment from fscrypt_d_revalidate()
d56de4e926ad fscrypt: remove error messages for skcipher_request_alloc() failure
f68d3b84aef1 fscrypt: remove unnecessary NULL check when allocating skcipher
fb10231825e9 fscrypt: clean up after fscrypt_prepare_lookup() conversions
39b144490606 fscrypt: use unbound workqueue for decryption
Change-Id: Ied79ecd97385c05ef26e6b7b24d250eee9ec4e47
Signed-off-by: Jaegeuk Kim <jaegeuk@google.com>
Diffstat (limited to 'fs/f2fs/inode.c')
| -rw-r--r-- | fs/f2fs/inode.c | 115 |
1 files changed, 70 insertions, 45 deletions
diff --git a/fs/f2fs/inode.c b/fs/f2fs/inode.c index 51846fc54fbd..27e18b5cb459 100644 --- a/fs/f2fs/inode.c +++ b/fs/f2fs/inode.c @@ -36,15 +36,15 @@ void f2fs_set_inode_flags(struct inode *inode) unsigned int flags = F2FS_I(inode)->i_flags; unsigned int new_fl = 0; - if (flags & FS_SYNC_FL) + if (flags & F2FS_SYNC_FL) new_fl |= S_SYNC; - if (flags & FS_APPEND_FL) + if (flags & F2FS_APPEND_FL) new_fl |= S_APPEND; - if (flags & FS_IMMUTABLE_FL) + if (flags & F2FS_IMMUTABLE_FL) new_fl |= S_IMMUTABLE; - if (flags & FS_NOATIME_FL) + if (flags & F2FS_NOATIME_FL) new_fl |= S_NOATIME; - if (flags & FS_DIRSYNC_FL) + if (flags & F2FS_DIRSYNC_FL) new_fl |= S_DIRSYNC; if (f2fs_encrypted_inode(inode)) new_fl |= S_ENCRYPTED; @@ -72,7 +72,7 @@ static bool __written_first_block(struct f2fs_inode *ri) { block_t addr = le32_to_cpu(ri->i_addr[offset_in_addr(ri)]); - if (addr != NEW_ADDR && addr != NULL_ADDR) + if (is_valid_blkaddr(addr)) return true; return false; } @@ -117,7 +117,6 @@ static void __recover_inline_status(struct inode *inode, struct page *ipage) static bool f2fs_enable_inode_chksum(struct f2fs_sb_info *sbi, struct page *page) { struct f2fs_inode *ri = &F2FS_NODE(page)->i; - int extra_isize = le32_to_cpu(ri->i_extra_isize); if (!f2fs_sb_has_inode_chksum(sbi->sb)) return false; @@ -125,7 +124,8 @@ static bool f2fs_enable_inode_chksum(struct f2fs_sb_info *sbi, struct page *page if (!RAW_IS_INODE(F2FS_NODE(page)) || !(ri->i_inline & F2FS_EXTRA_ATTR)) return false; - if (!F2FS_FITS_IN_INODE(ri, extra_isize, i_inode_checksum)) + if (!F2FS_FITS_IN_INODE(ri, le16_to_cpu(ri->i_extra_isize), + i_inode_checksum)) return false; return true; @@ -185,6 +185,21 @@ void f2fs_inode_chksum_set(struct f2fs_sb_info *sbi, struct page *page) ri->i_inode_checksum = cpu_to_le32(f2fs_inode_chksum(sbi, page)); } +static bool sanity_check_inode(struct inode *inode) +{ + struct f2fs_sb_info *sbi = F2FS_I_SB(inode); + + if (f2fs_sb_has_flexible_inline_xattr(sbi->sb) + && !f2fs_has_extra_attr(inode)) { + set_sbi_flag(sbi, SBI_NEED_FSCK); + f2fs_msg(sbi->sb, KERN_WARNING, + "%s: corrupted inode ino=%lx, run fsck to fix.", + __func__, inode->i_ino); + return false; + } + return true; +} + static int do_read_inode(struct inode *inode) { struct f2fs_sb_info *sbi = F2FS_I_SB(inode); @@ -194,14 +209,10 @@ static int do_read_inode(struct inode *inode) projid_t i_projid; /* Check if ino is within scope */ - if (check_nid_range(sbi, inode->i_ino)) { - f2fs_msg(inode->i_sb, KERN_ERR, "bad inode number: %lu", - (unsigned long) inode->i_ino); - WARN_ON(1); + if (f2fs_check_nid_range(sbi, inode->i_ino)) return -EINVAL; - } - node_page = get_node_page(sbi, inode->i_ino); + node_page = f2fs_get_node_page(sbi, inode->i_ino); if (IS_ERR(node_page)) return PTR_ERR(node_page); @@ -221,8 +232,11 @@ static int do_read_inode(struct inode *inode) inode->i_ctime.tv_nsec = le32_to_cpu(ri->i_ctime_nsec); inode->i_mtime.tv_nsec = le32_to_cpu(ri->i_mtime_nsec); inode->i_generation = le32_to_cpu(ri->i_generation); - - fi->i_current_depth = le32_to_cpu(ri->i_current_depth); + if (S_ISDIR(inode->i_mode)) + fi->i_current_depth = le32_to_cpu(ri->i_current_depth); + else if (S_ISREG(inode->i_mode)) + fi->i_gc_failures[GC_FAILURE_PIN] = + le16_to_cpu(ri->i_gc_failures); fi->i_xattr_nid = le32_to_cpu(ri->i_xattr_nid); fi->i_flags = le32_to_cpu(ri->i_flags); fi->flags = 0; @@ -239,7 +253,6 @@ static int do_read_inode(struct inode *inode) le16_to_cpu(ri->i_extra_isize) : 0; if (f2fs_sb_has_flexible_inline_xattr(sbi->sb)) { - f2fs_bug_on(sbi, !f2fs_has_extra_attr(inode)); fi->i_inline_xattr_size = le16_to_cpu(ri->i_inline_xattr_size); } else if (f2fs_has_inline_xattr(inode) || f2fs_has_inline_dentry(inode)) { @@ -265,10 +278,10 @@ static int do_read_inode(struct inode *inode) if (__written_first_block(ri)) set_inode_flag(inode, FI_FIRST_BLOCK_WRITTEN); - if (!need_inode_block_update(sbi, inode->i_ino)) + if (!f2fs_need_inode_block_update(sbi, inode->i_ino)) fi->last_disk_size = inode->i_size; - if (fi->i_flags & FS_PROJINHERIT_FL) + if (fi->i_flags & F2FS_PROJINHERIT_FL) set_inode_flag(inode, FI_PROJ_INHERIT); if (f2fs_has_extra_attr(inode) && f2fs_sb_has_project_quota(sbi->sb) && @@ -317,13 +330,17 @@ struct inode *f2fs_iget(struct super_block *sb, unsigned long ino) ret = do_read_inode(inode); if (ret) goto bad_inode; + if (!sanity_check_inode(inode)) { + ret = -EINVAL; + goto bad_inode; + } make_now: if (ino == F2FS_NODE_INO(sbi)) { inode->i_mapping->a_ops = &f2fs_node_aops; - mapping_set_gfp_mask(inode->i_mapping, GFP_F2FS_ZERO); + mapping_set_gfp_mask(inode->i_mapping, GFP_NOFS); } else if (ino == F2FS_META_INO(sbi)) { inode->i_mapping->a_ops = &f2fs_meta_aops; - mapping_set_gfp_mask(inode->i_mapping, GFP_F2FS_ZERO); + mapping_set_gfp_mask(inode->i_mapping, GFP_NOFS); } else if (S_ISREG(inode->i_mode)) { inode->i_op = &f2fs_file_inode_operations; inode->i_fop = &f2fs_file_operations; @@ -373,7 +390,7 @@ retry: return inode; } -void update_inode(struct inode *inode, struct page *node_page) +void f2fs_update_inode(struct inode *inode, struct page *node_page) { struct f2fs_inode *ri; struct extent_tree *et = F2FS_I(inode)->extent_tree; @@ -408,7 +425,12 @@ void update_inode(struct inode *inode, struct page *node_page) ri->i_atime_nsec = cpu_to_le32(inode->i_atime.tv_nsec); ri->i_ctime_nsec = cpu_to_le32(inode->i_ctime.tv_nsec); ri->i_mtime_nsec = cpu_to_le32(inode->i_mtime.tv_nsec); - ri->i_current_depth = cpu_to_le32(F2FS_I(inode)->i_current_depth); + if (S_ISDIR(inode->i_mode)) + ri->i_current_depth = + cpu_to_le32(F2FS_I(inode)->i_current_depth); + else if (S_ISREG(inode->i_mode)) + ri->i_gc_failures = + cpu_to_le16(F2FS_I(inode)->i_gc_failures[GC_FAILURE_PIN]); 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); @@ -454,12 +476,12 @@ void update_inode(struct inode *inode, struct page *node_page) F2FS_I(inode)->i_disk_time[3] = F2FS_I(inode)->i_crtime; } -void update_inode_page(struct inode *inode) +void f2fs_update_inode_page(struct inode *inode) { struct f2fs_sb_info *sbi = F2FS_I_SB(inode); struct page *node_page; retry: - node_page = get_node_page(sbi, inode->i_ino); + node_page = f2fs_get_node_page(sbi, inode->i_ino); if (IS_ERR(node_page)) { int err = PTR_ERR(node_page); if (err == -ENOMEM) { @@ -470,7 +492,7 @@ retry: } return; } - update_inode(inode, node_page); + f2fs_update_inode(inode, node_page); f2fs_put_page(node_page, 1); } @@ -489,7 +511,7 @@ int f2fs_write_inode(struct inode *inode, struct writeback_control *wbc) * We need to balance fs here to prevent from producing dirty node pages * during the urgent cleaning time when runing out of free sections. */ - update_inode_page(inode); + f2fs_update_inode_page(inode); if (wbc && wbc->nr_to_write) f2fs_balance_fs(sbi, true); return 0; @@ -506,7 +528,7 @@ void f2fs_evict_inode(struct inode *inode) /* some remained atomic pages should discarded */ if (f2fs_is_atomic_file(inode)) - drop_inmem_pages(inode); + f2fs_drop_inmem_pages(inode); trace_f2fs_evict_inode(inode); truncate_inode_pages_final(&inode->i_data); @@ -516,7 +538,7 @@ void f2fs_evict_inode(struct inode *inode) goto out_clear; f2fs_bug_on(sbi, get_dirty_pages(inode)); - remove_dirty_inode(inode); + f2fs_remove_dirty_inode(inode); f2fs_destroy_extent_tree(inode); @@ -525,9 +547,9 @@ void f2fs_evict_inode(struct inode *inode) dquot_initialize(inode); - remove_ino_entry(sbi, inode->i_ino, APPEND_INO); - remove_ino_entry(sbi, inode->i_ino, UPDATE_INO); - remove_ino_entry(sbi, inode->i_ino, FLUSH_INO); + f2fs_remove_ino_entry(sbi, inode->i_ino, APPEND_INO); + f2fs_remove_ino_entry(sbi, inode->i_ino, UPDATE_INO); + f2fs_remove_ino_entry(sbi, inode->i_ino, FLUSH_INO); sb_start_intwrite(inode->i_sb); set_inode_flag(inode, FI_NO_ALLOC); @@ -544,7 +566,7 @@ retry: #endif if (!err) { f2fs_lock_op(sbi); - err = remove_inode_page(inode); + err = f2fs_remove_inode_page(inode); f2fs_unlock_op(sbi); if (err == -ENOENT) err = 0; @@ -557,7 +579,7 @@ retry: } if (err) - update_inode_page(inode); + f2fs_update_inode_page(inode); dquot_free_inode(inode); sb_end_intwrite(inode->i_sb); no_delete: @@ -580,16 +602,19 @@ no_delete: invalidate_mapping_pages(NODE_MAPPING(sbi), xnid, xnid); if (inode->i_nlink) { if (is_inode_flag_set(inode, FI_APPEND_WRITE)) - add_ino_entry(sbi, inode->i_ino, APPEND_INO); + f2fs_add_ino_entry(sbi, inode->i_ino, APPEND_INO); if (is_inode_flag_set(inode, FI_UPDATE_WRITE)) - add_ino_entry(sbi, inode->i_ino, UPDATE_INO); + f2fs_add_ino_entry(sbi, inode->i_ino, UPDATE_INO); } if (is_inode_flag_set(inode, FI_FREE_NID)) { - alloc_nid_failed(sbi, inode->i_ino); + f2fs_alloc_nid_failed(sbi, inode->i_ino); clear_inode_flag(inode, FI_FREE_NID); } else { - f2fs_bug_on(sbi, err && - !exist_written_data(sbi, inode->i_ino, ORPHAN_INO)); + /* + * If xattr nid is corrupted, we can reach out error condition, + * err & !f2fs_exist_written_data(sbi, inode->i_ino, ORPHAN_INO)). + * In that case, f2fs_check_nid_range() is enough to give a clue. + */ } out_clear: fscrypt_put_encryption_info(inode, NULL); @@ -597,7 +622,7 @@ out_clear: } /* caller should call f2fs_lock_op() */ -void handle_failed_inode(struct inode *inode) +void f2fs_handle_failed_inode(struct inode *inode) { struct f2fs_sb_info *sbi = F2FS_I_SB(inode); struct node_info ni; @@ -612,7 +637,7 @@ void handle_failed_inode(struct inode *inode) * we must call this to avoid inode being remained as dirty, resulting * in a panic when flushing dirty inodes in gdirty_list. */ - update_inode_page(inode); + f2fs_update_inode_page(inode); f2fs_inode_synced(inode); /* don't make bad inode, since it becomes a regular file. */ @@ -623,18 +648,18 @@ void handle_failed_inode(struct inode *inode) * so we can prevent losing this orphan when encoutering checkpoint * and following suddenly power-off. */ - get_node_info(sbi, inode->i_ino, &ni); + f2fs_get_node_info(sbi, inode->i_ino, &ni); if (ni.blk_addr != NULL_ADDR) { - int err = acquire_orphan_inode(sbi); + int err = f2fs_acquire_orphan_inode(sbi); if (err) { set_sbi_flag(sbi, SBI_NEED_FSCK); f2fs_msg(sbi->sb, KERN_WARNING, "Too many orphan inodes, run fsck to fix."); } else { - add_orphan_inode(inode); + f2fs_add_orphan_inode(inode); } - alloc_nid_done(sbi, inode->i_ino); + f2fs_alloc_nid_done(sbi, inode->i_ino); } else { set_inode_flag(inode, FI_FREE_NID); } |
