diff options
-rw-r--r-- | Documentation/ABI/testing/sysfs-fs-f2fs | 17 | ||||
-rw-r--r-- | Documentation/filesystems/f2fs.txt | 8 | ||||
-rw-r--r-- | fs/f2fs/acl.c | 12 | ||||
-rw-r--r-- | fs/f2fs/acl.h | 5 | ||||
-rw-r--r-- | fs/f2fs/checkpoint.c | 94 | ||||
-rw-r--r-- | fs/f2fs/data.c | 220 | ||||
-rw-r--r-- | fs/f2fs/debug.c | 35 | ||||
-rw-r--r-- | fs/f2fs/dir.c | 30 | ||||
-rw-r--r-- | fs/f2fs/extent_cache.c | 134 | ||||
-rw-r--r-- | fs/f2fs/f2fs.h | 253 | ||||
-rw-r--r-- | fs/f2fs/file.c | 196 | ||||
-rw-r--r-- | fs/f2fs/gc.c | 115 | ||||
-rw-r--r-- | fs/f2fs/gc.h | 5 | ||||
-rw-r--r-- | fs/f2fs/hash.c | 5 | ||||
-rw-r--r-- | fs/f2fs/inline.c | 8 | ||||
-rw-r--r-- | fs/f2fs/inode.c | 28 | ||||
-rw-r--r-- | fs/f2fs/namei.c | 57 | ||||
-rw-r--r-- | fs/f2fs/node.c | 83 | ||||
-rw-r--r-- | fs/f2fs/node.h | 5 | ||||
-rw-r--r-- | fs/f2fs/recovery.c | 125 | ||||
-rw-r--r-- | fs/f2fs/segment.c | 240 | ||||
-rw-r--r-- | fs/f2fs/segment.h | 20 | ||||
-rw-r--r-- | fs/f2fs/shrinker.c | 5 | ||||
-rw-r--r-- | fs/f2fs/super.c | 415 | ||||
-rw-r--r-- | fs/f2fs/sysfs.c | 17 | ||||
-rw-r--r-- | fs/f2fs/trace.c | 5 | ||||
-rw-r--r-- | fs/f2fs/trace.h | 5 | ||||
-rw-r--r-- | fs/f2fs/xattr.c | 5 | ||||
-rw-r--r-- | fs/f2fs/xattr.h | 5 | ||||
-rw-r--r-- | include/linux/f2fs_fs.h | 10 |
30 files changed, 1594 insertions, 568 deletions
diff --git a/Documentation/ABI/testing/sysfs-fs-f2fs b/Documentation/ABI/testing/sysfs-fs-f2fs index 94a24aedcdb2..3ac41774ad3c 100644 --- a/Documentation/ABI/testing/sysfs-fs-f2fs +++ b/Documentation/ABI/testing/sysfs-fs-f2fs | |||
@@ -121,7 +121,22 @@ What: /sys/fs/f2fs/<disk>/idle_interval | |||
121 | Date: January 2016 | 121 | Date: January 2016 |
122 | Contact: "Jaegeuk Kim" <jaegeuk@kernel.org> | 122 | Contact: "Jaegeuk Kim" <jaegeuk@kernel.org> |
123 | Description: | 123 | Description: |
124 | Controls the idle timing. | 124 | Controls the idle timing for all paths other than |
125 | discard and gc path. | ||
126 | |||
127 | What: /sys/fs/f2fs/<disk>/discard_idle_interval | ||
128 | Date: September 2018 | ||
129 | Contact: "Chao Yu" <yuchao0@huawei.com> | ||
130 | Contact: "Sahitya Tummala" <stummala@codeaurora.org> | ||
131 | Description: | ||
132 | Controls the idle timing for discard path. | ||
133 | |||
134 | What: /sys/fs/f2fs/<disk>/gc_idle_interval | ||
135 | Date: September 2018 | ||
136 | Contact: "Chao Yu" <yuchao0@huawei.com> | ||
137 | Contact: "Sahitya Tummala" <stummala@codeaurora.org> | ||
138 | Description: | ||
139 | Controls the idle timing for gc path. | ||
125 | 140 | ||
126 | What: /sys/fs/f2fs/<disk>/iostat_enable | 141 | What: /sys/fs/f2fs/<disk>/iostat_enable |
127 | Date: August 2017 | 142 | Date: August 2017 |
diff --git a/Documentation/filesystems/f2fs.txt b/Documentation/filesystems/f2fs.txt index e5edd29687b5..e46c2147ddf8 100644 --- a/Documentation/filesystems/f2fs.txt +++ b/Documentation/filesystems/f2fs.txt | |||
@@ -172,9 +172,10 @@ fault_type=%d Support configuring fault injection type, should be | |||
172 | FAULT_DIR_DEPTH 0x000000100 | 172 | FAULT_DIR_DEPTH 0x000000100 |
173 | FAULT_EVICT_INODE 0x000000200 | 173 | FAULT_EVICT_INODE 0x000000200 |
174 | FAULT_TRUNCATE 0x000000400 | 174 | FAULT_TRUNCATE 0x000000400 |
175 | FAULT_IO 0x000000800 | 175 | FAULT_READ_IO 0x000000800 |
176 | FAULT_CHECKPOINT 0x000001000 | 176 | FAULT_CHECKPOINT 0x000001000 |
177 | FAULT_DISCARD 0x000002000 | 177 | FAULT_DISCARD 0x000002000 |
178 | FAULT_WRITE_IO 0x000004000 | ||
178 | mode=%s Control block allocation mode which supports "adaptive" | 179 | mode=%s Control block allocation mode which supports "adaptive" |
179 | and "lfs". In "lfs" mode, there should be no random | 180 | and "lfs". In "lfs" mode, there should be no random |
180 | writes towards main area. | 181 | writes towards main area. |
@@ -211,6 +212,11 @@ fsync_mode=%s Control the policy of fsync. Currently supports "posix", | |||
211 | non-atomic files likewise "nobarrier" mount option. | 212 | non-atomic files likewise "nobarrier" mount option. |
212 | test_dummy_encryption Enable dummy encryption, which provides a fake fscrypt | 213 | test_dummy_encryption Enable dummy encryption, which provides a fake fscrypt |
213 | context. The fake fscrypt context is used by xfstests. | 214 | context. The fake fscrypt context is used by xfstests. |
215 | checkpoint=%s Set to "disable" to turn off checkpointing. Set to "enable" | ||
216 | to reenable checkpointing. Is enabled by default. While | ||
217 | disabled, any unmounting or unexpected shutdowns will cause | ||
218 | the filesystem contents to appear as they did when the | ||
219 | filesystem was mounted with that option. | ||
214 | 220 | ||
215 | ================================================================================ | 221 | ================================================================================ |
216 | DEBUGFS ENTRIES | 222 | DEBUGFS ENTRIES |
diff --git a/fs/f2fs/acl.c b/fs/f2fs/acl.c index 111824199a88..fa707cdd4120 100644 --- a/fs/f2fs/acl.c +++ b/fs/f2fs/acl.c | |||
@@ -1,3 +1,4 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
1 | /* | 2 | /* |
2 | * fs/f2fs/acl.c | 3 | * fs/f2fs/acl.c |
3 | * | 4 | * |
@@ -7,10 +8,6 @@ | |||
7 | * Portions of this code from linux/fs/ext2/acl.c | 8 | * Portions of this code from linux/fs/ext2/acl.c |
8 | * | 9 | * |
9 | * Copyright (C) 2001-2003 Andreas Gruenbacher, <agruen@suse.de> | 10 | * Copyright (C) 2001-2003 Andreas Gruenbacher, <agruen@suse.de> |
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify | ||
12 | * it under the terms of the GNU General Public License version 2 as | ||
13 | * published by the Free Software Foundation. | ||
14 | */ | 11 | */ |
15 | #include <linux/f2fs_fs.h> | 12 | #include <linux/f2fs_fs.h> |
16 | #include "f2fs.h" | 13 | #include "f2fs.h" |
@@ -53,6 +50,9 @@ static struct posix_acl *f2fs_acl_from_disk(const char *value, size_t size) | |||
53 | struct f2fs_acl_entry *entry = (struct f2fs_acl_entry *)(hdr + 1); | 50 | struct f2fs_acl_entry *entry = (struct f2fs_acl_entry *)(hdr + 1); |
54 | const char *end = value + size; | 51 | const char *end = value + size; |
55 | 52 | ||
53 | if (size < sizeof(struct f2fs_acl_header)) | ||
54 | return ERR_PTR(-EINVAL); | ||
55 | |||
56 | if (hdr->a_version != cpu_to_le32(F2FS_ACL_VERSION)) | 56 | if (hdr->a_version != cpu_to_le32(F2FS_ACL_VERSION)) |
57 | return ERR_PTR(-EINVAL); | 57 | return ERR_PTR(-EINVAL); |
58 | 58 | ||
@@ -394,12 +394,16 @@ int f2fs_init_acl(struct inode *inode, struct inode *dir, struct page *ipage, | |||
394 | error = __f2fs_set_acl(inode, ACL_TYPE_DEFAULT, default_acl, | 394 | error = __f2fs_set_acl(inode, ACL_TYPE_DEFAULT, default_acl, |
395 | ipage); | 395 | ipage); |
396 | posix_acl_release(default_acl); | 396 | posix_acl_release(default_acl); |
397 | } else { | ||
398 | inode->i_default_acl = NULL; | ||
397 | } | 399 | } |
398 | if (acl) { | 400 | if (acl) { |
399 | if (!error) | 401 | if (!error) |
400 | error = __f2fs_set_acl(inode, ACL_TYPE_ACCESS, acl, | 402 | error = __f2fs_set_acl(inode, ACL_TYPE_ACCESS, acl, |
401 | ipage); | 403 | ipage); |
402 | posix_acl_release(acl); | 404 | posix_acl_release(acl); |
405 | } else { | ||
406 | inode->i_acl = NULL; | ||
403 | } | 407 | } |
404 | 408 | ||
405 | return error; | 409 | return error; |
diff --git a/fs/f2fs/acl.h b/fs/f2fs/acl.h index 2c685185c24d..b96823c59b15 100644 --- a/fs/f2fs/acl.h +++ b/fs/f2fs/acl.h | |||
@@ -1,3 +1,4 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
1 | /* | 2 | /* |
2 | * fs/f2fs/acl.h | 3 | * fs/f2fs/acl.h |
3 | * | 4 | * |
@@ -7,10 +8,6 @@ | |||
7 | * Portions of this code from linux/fs/ext2/acl.h | 8 | * Portions of this code from linux/fs/ext2/acl.h |
8 | * | 9 | * |
9 | * Copyright (C) 2001-2003 Andreas Gruenbacher, <agruen@suse.de> | 10 | * Copyright (C) 2001-2003 Andreas Gruenbacher, <agruen@suse.de> |
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify | ||
12 | * it under the terms of the GNU General Public License version 2 as | ||
13 | * published by the Free Software Foundation. | ||
14 | */ | 11 | */ |
15 | #ifndef __F2FS_ACL_H__ | 12 | #ifndef __F2FS_ACL_H__ |
16 | #define __F2FS_ACL_H__ | 13 | #define __F2FS_ACL_H__ |
diff --git a/fs/f2fs/checkpoint.c b/fs/f2fs/checkpoint.c index e8b6b89bddb8..9c28ea439e0b 100644 --- a/fs/f2fs/checkpoint.c +++ b/fs/f2fs/checkpoint.c | |||
@@ -1,12 +1,9 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
1 | /* | 2 | /* |
2 | * fs/f2fs/checkpoint.c | 3 | * fs/f2fs/checkpoint.c |
3 | * | 4 | * |
4 | * Copyright (c) 2012 Samsung Electronics Co., Ltd. | 5 | * Copyright (c) 2012 Samsung Electronics Co., Ltd. |
5 | * http://www.samsung.com/ | 6 | * http://www.samsung.com/ |
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | */ | 7 | */ |
11 | #include <linux/fs.h> | 8 | #include <linux/fs.h> |
12 | #include <linux/bio.h> | 9 | #include <linux/bio.h> |
@@ -122,11 +119,8 @@ retry: | |||
122 | if (PTR_ERR(page) == -EIO && | 119 | if (PTR_ERR(page) == -EIO && |
123 | ++count <= DEFAULT_RETRY_IO_COUNT) | 120 | ++count <= DEFAULT_RETRY_IO_COUNT) |
124 | goto retry; | 121 | goto retry; |
125 | |||
126 | f2fs_stop_checkpoint(sbi, false); | 122 | f2fs_stop_checkpoint(sbi, false); |
127 | f2fs_bug_on(sbi, 1); | ||
128 | } | 123 | } |
129 | |||
130 | return page; | 124 | return page; |
131 | } | 125 | } |
132 | 126 | ||
@@ -282,8 +276,7 @@ static int __f2fs_write_meta_page(struct page *page, | |||
282 | dec_page_count(sbi, F2FS_DIRTY_META); | 276 | dec_page_count(sbi, F2FS_DIRTY_META); |
283 | 277 | ||
284 | if (wbc->for_reclaim) | 278 | if (wbc->for_reclaim) |
285 | f2fs_submit_merged_write_cond(sbi, page->mapping->host, | 279 | f2fs_submit_merged_write_cond(sbi, NULL, page, 0, META); |
286 | 0, page->index, META); | ||
287 | 280 | ||
288 | unlock_page(page); | 281 | unlock_page(page); |
289 | 282 | ||
@@ -696,6 +689,8 @@ int f2fs_recover_orphan_inodes(struct f2fs_sb_info *sbi) | |||
696 | /* clear Orphan Flag */ | 689 | /* clear Orphan Flag */ |
697 | clear_ckpt_flags(sbi, CP_ORPHAN_PRESENT_FLAG); | 690 | clear_ckpt_flags(sbi, CP_ORPHAN_PRESENT_FLAG); |
698 | out: | 691 | out: |
692 | set_sbi_flag(sbi, SBI_IS_RECOVERED); | ||
693 | |||
699 | #ifdef CONFIG_QUOTA | 694 | #ifdef CONFIG_QUOTA |
700 | /* Turn quotas off */ | 695 | /* Turn quotas off */ |
701 | if (quota_enabled) | 696 | if (quota_enabled) |
@@ -1084,6 +1079,21 @@ static void __prepare_cp_block(struct f2fs_sb_info *sbi) | |||
1084 | ckpt->next_free_nid = cpu_to_le32(last_nid); | 1079 | ckpt->next_free_nid = cpu_to_le32(last_nid); |
1085 | } | 1080 | } |
1086 | 1081 | ||
1082 | static bool __need_flush_quota(struct f2fs_sb_info *sbi) | ||
1083 | { | ||
1084 | if (!is_journalled_quota(sbi)) | ||
1085 | return false; | ||
1086 | if (is_sbi_flag_set(sbi, SBI_QUOTA_SKIP_FLUSH)) | ||
1087 | return false; | ||
1088 | if (is_sbi_flag_set(sbi, SBI_QUOTA_NEED_REPAIR)) | ||
1089 | return false; | ||
1090 | if (is_sbi_flag_set(sbi, SBI_QUOTA_NEED_FLUSH)) | ||
1091 | return true; | ||
1092 | if (get_pages(sbi, F2FS_DIRTY_QDATA)) | ||
1093 | return true; | ||
1094 | return false; | ||
1095 | } | ||
1096 | |||
1087 | /* | 1097 | /* |
1088 | * Freeze all the FS-operations for checkpoint. | 1098 | * Freeze all the FS-operations for checkpoint. |
1089 | */ | 1099 | */ |
@@ -1095,12 +1105,36 @@ static int block_operations(struct f2fs_sb_info *sbi) | |||
1095 | .for_reclaim = 0, | 1105 | .for_reclaim = 0, |
1096 | }; | 1106 | }; |
1097 | struct blk_plug plug; | 1107 | struct blk_plug plug; |
1098 | int err = 0; | 1108 | int err = 0, cnt = 0; |
1099 | 1109 | ||
1100 | blk_start_plug(&plug); | 1110 | blk_start_plug(&plug); |
1101 | 1111 | ||
1102 | retry_flush_dents: | 1112 | retry_flush_quotas: |
1113 | if (__need_flush_quota(sbi)) { | ||
1114 | int locked; | ||
1115 | |||
1116 | if (++cnt > DEFAULT_RETRY_QUOTA_FLUSH_COUNT) { | ||
1117 | set_sbi_flag(sbi, SBI_QUOTA_SKIP_FLUSH); | ||
1118 | f2fs_lock_all(sbi); | ||
1119 | goto retry_flush_dents; | ||
1120 | } | ||
1121 | clear_sbi_flag(sbi, SBI_QUOTA_NEED_FLUSH); | ||
1122 | |||
1123 | /* only failed during mount/umount/freeze/quotactl */ | ||
1124 | locked = down_read_trylock(&sbi->sb->s_umount); | ||
1125 | f2fs_quota_sync(sbi->sb, -1); | ||
1126 | if (locked) | ||
1127 | up_read(&sbi->sb->s_umount); | ||
1128 | } | ||
1129 | |||
1103 | f2fs_lock_all(sbi); | 1130 | f2fs_lock_all(sbi); |
1131 | if (__need_flush_quota(sbi)) { | ||
1132 | f2fs_unlock_all(sbi); | ||
1133 | cond_resched(); | ||
1134 | goto retry_flush_quotas; | ||
1135 | } | ||
1136 | |||
1137 | retry_flush_dents: | ||
1104 | /* write all the dirty dentry pages */ | 1138 | /* write all the dirty dentry pages */ |
1105 | if (get_pages(sbi, F2FS_DIRTY_DENTS)) { | 1139 | if (get_pages(sbi, F2FS_DIRTY_DENTS)) { |
1106 | f2fs_unlock_all(sbi); | 1140 | f2fs_unlock_all(sbi); |
@@ -1108,7 +1142,7 @@ retry_flush_dents: | |||
1108 | if (err) | 1142 | if (err) |
1109 | goto out; | 1143 | goto out; |
1110 | cond_resched(); | 1144 | cond_resched(); |
1111 | goto retry_flush_dents; | 1145 | goto retry_flush_quotas; |
1112 | } | 1146 | } |
1113 | 1147 | ||
1114 | /* | 1148 | /* |
@@ -1117,6 +1151,12 @@ retry_flush_dents: | |||
1117 | */ | 1151 | */ |
1118 | down_write(&sbi->node_change); | 1152 | down_write(&sbi->node_change); |
1119 | 1153 | ||
1154 | if (__need_flush_quota(sbi)) { | ||
1155 | up_write(&sbi->node_change); | ||
1156 | f2fs_unlock_all(sbi); | ||
1157 | goto retry_flush_quotas; | ||
1158 | } | ||
1159 | |||
1120 | if (get_pages(sbi, F2FS_DIRTY_IMETA)) { | 1160 | if (get_pages(sbi, F2FS_DIRTY_IMETA)) { |
1121 | up_write(&sbi->node_change); | 1161 | up_write(&sbi->node_change); |
1122 | f2fs_unlock_all(sbi); | 1162 | f2fs_unlock_all(sbi); |
@@ -1124,7 +1164,7 @@ retry_flush_dents: | |||
1124 | if (err) | 1164 | if (err) |
1125 | goto out; | 1165 | goto out; |
1126 | cond_resched(); | 1166 | cond_resched(); |
1127 | goto retry_flush_dents; | 1167 | goto retry_flush_quotas; |
1128 | } | 1168 | } |
1129 | 1169 | ||
1130 | retry_flush_nodes: | 1170 | retry_flush_nodes: |
@@ -1215,6 +1255,19 @@ static void update_ckpt_flags(struct f2fs_sb_info *sbi, struct cp_control *cpc) | |||
1215 | if (is_sbi_flag_set(sbi, SBI_NEED_FSCK)) | 1255 | if (is_sbi_flag_set(sbi, SBI_NEED_FSCK)) |
1216 | __set_ckpt_flags(ckpt, CP_FSCK_FLAG); | 1256 | __set_ckpt_flags(ckpt, CP_FSCK_FLAG); |
1217 | 1257 | ||
1258 | if (is_sbi_flag_set(sbi, SBI_CP_DISABLED)) | ||
1259 | __set_ckpt_flags(ckpt, CP_DISABLED_FLAG); | ||
1260 | else | ||
1261 | __clear_ckpt_flags(ckpt, CP_DISABLED_FLAG); | ||
1262 | |||
1263 | if (is_sbi_flag_set(sbi, SBI_QUOTA_SKIP_FLUSH)) | ||
1264 | __set_ckpt_flags(ckpt, CP_QUOTA_NEED_FSCK_FLAG); | ||
1265 | else | ||
1266 | __clear_ckpt_flags(ckpt, CP_QUOTA_NEED_FSCK_FLAG); | ||
1267 | |||
1268 | if (is_sbi_flag_set(sbi, SBI_QUOTA_NEED_REPAIR)) | ||
1269 | __set_ckpt_flags(ckpt, CP_QUOTA_NEED_FSCK_FLAG); | ||
1270 | |||
1218 | /* set this flag to activate crc|cp_ver for recovery */ | 1271 | /* set this flag to activate crc|cp_ver for recovery */ |
1219 | __set_ckpt_flags(ckpt, CP_CRC_RECOVERY_FLAG); | 1272 | __set_ckpt_flags(ckpt, CP_CRC_RECOVERY_FLAG); |
1220 | __clear_ckpt_flags(ckpt, CP_NOCRC_RECOVERY_FLAG); | 1273 | __clear_ckpt_flags(ckpt, CP_NOCRC_RECOVERY_FLAG); |
@@ -1422,6 +1475,8 @@ static int do_checkpoint(struct f2fs_sb_info *sbi, struct cp_control *cpc) | |||
1422 | 1475 | ||
1423 | clear_sbi_flag(sbi, SBI_IS_DIRTY); | 1476 | clear_sbi_flag(sbi, SBI_IS_DIRTY); |
1424 | clear_sbi_flag(sbi, SBI_NEED_CP); | 1477 | clear_sbi_flag(sbi, SBI_NEED_CP); |
1478 | clear_sbi_flag(sbi, SBI_QUOTA_SKIP_FLUSH); | ||
1479 | sbi->unusable_block_count = 0; | ||
1425 | __set_cp_next_pack(sbi); | 1480 | __set_cp_next_pack(sbi); |
1426 | 1481 | ||
1427 | /* | 1482 | /* |
@@ -1446,6 +1501,12 @@ int f2fs_write_checkpoint(struct f2fs_sb_info *sbi, struct cp_control *cpc) | |||
1446 | unsigned long long ckpt_ver; | 1501 | unsigned long long ckpt_ver; |
1447 | int err = 0; | 1502 | int err = 0; |
1448 | 1503 | ||
1504 | if (unlikely(is_sbi_flag_set(sbi, SBI_CP_DISABLED))) { | ||
1505 | if (cpc->reason != CP_PAUSE) | ||
1506 | return 0; | ||
1507 | f2fs_msg(sbi->sb, KERN_WARNING, | ||
1508 | "Start checkpoint disabled!"); | ||
1509 | } | ||
1449 | mutex_lock(&sbi->cp_mutex); | 1510 | mutex_lock(&sbi->cp_mutex); |
1450 | 1511 | ||
1451 | if (!is_sbi_flag_set(sbi, SBI_IS_DIRTY) && | 1512 | if (!is_sbi_flag_set(sbi, SBI_IS_DIRTY) && |
@@ -1497,7 +1558,10 @@ int f2fs_write_checkpoint(struct f2fs_sb_info *sbi, struct cp_control *cpc) | |||
1497 | ckpt->checkpoint_ver = cpu_to_le64(++ckpt_ver); | 1558 | ckpt->checkpoint_ver = cpu_to_le64(++ckpt_ver); |
1498 | 1559 | ||
1499 | /* write cached NAT/SIT entries to NAT/SIT area */ | 1560 | /* write cached NAT/SIT entries to NAT/SIT area */ |
1500 | f2fs_flush_nat_entries(sbi, cpc); | 1561 | err = f2fs_flush_nat_entries(sbi, cpc); |
1562 | if (err) | ||
1563 | goto stop; | ||
1564 | |||
1501 | f2fs_flush_sit_entries(sbi, cpc); | 1565 | f2fs_flush_sit_entries(sbi, cpc); |
1502 | 1566 | ||
1503 | /* unlock all the fs_lock[] in do_checkpoint() */ | 1567 | /* unlock all the fs_lock[] in do_checkpoint() */ |
@@ -1506,7 +1570,7 @@ int f2fs_write_checkpoint(struct f2fs_sb_info *sbi, struct cp_control *cpc) | |||
1506 | f2fs_release_discard_addrs(sbi); | 1570 | f2fs_release_discard_addrs(sbi); |
1507 | else | 1571 | else |
1508 | f2fs_clear_prefree_segments(sbi, cpc); | 1572 | f2fs_clear_prefree_segments(sbi, cpc); |
1509 | 1573 | stop: | |
1510 | unblock_operations(sbi); | 1574 | unblock_operations(sbi); |
1511 | stat_inc_cp_count(sbi->stat_info); | 1575 | stat_inc_cp_count(sbi->stat_info); |
1512 | 1576 | ||
diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c index 382c1ef9a9e4..106f116466bf 100644 --- a/fs/f2fs/data.c +++ b/fs/f2fs/data.c | |||
@@ -1,12 +1,9 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
1 | /* | 2 | /* |
2 | * fs/f2fs/data.c | 3 | * fs/f2fs/data.c |
3 | * | 4 | * |
4 | * Copyright (c) 2012 Samsung Electronics Co., Ltd. | 5 | * Copyright (c) 2012 Samsung Electronics Co., Ltd. |
5 | * http://www.samsung.com/ | 6 | * http://www.samsung.com/ |
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | */ | 7 | */ |
11 | #include <linux/fs.h> | 8 | #include <linux/fs.h> |
12 | #include <linux/f2fs_fs.h> | 9 | #include <linux/f2fs_fs.h> |
@@ -49,12 +46,29 @@ static bool __is_cp_guaranteed(struct page *page) | |||
49 | inode->i_ino == F2FS_NODE_INO(sbi) || | 46 | inode->i_ino == F2FS_NODE_INO(sbi) || |
50 | S_ISDIR(inode->i_mode) || | 47 | S_ISDIR(inode->i_mode) || |
51 | (S_ISREG(inode->i_mode) && | 48 | (S_ISREG(inode->i_mode) && |
52 | is_inode_flag_set(inode, FI_ATOMIC_FILE)) || | 49 | (f2fs_is_atomic_file(inode) || IS_NOQUOTA(inode))) || |
53 | is_cold_data(page)) | 50 | is_cold_data(page)) |
54 | return true; | 51 | return true; |
55 | return false; | 52 | return false; |
56 | } | 53 | } |
57 | 54 | ||
55 | static enum count_type __read_io_type(struct page *page) | ||
56 | { | ||
57 | struct address_space *mapping = page->mapping; | ||
58 | |||
59 | if (mapping) { | ||
60 | struct inode *inode = mapping->host; | ||
61 | struct f2fs_sb_info *sbi = F2FS_I_SB(inode); | ||
62 | |||
63 | if (inode->i_ino == F2FS_META_INO(sbi)) | ||
64 | return F2FS_RD_META; | ||
65 | |||
66 | if (inode->i_ino == F2FS_NODE_INO(sbi)) | ||
67 | return F2FS_RD_NODE; | ||
68 | } | ||
69 | return F2FS_RD_DATA; | ||
70 | } | ||
71 | |||
58 | /* postprocessing steps for read bios */ | 72 | /* postprocessing steps for read bios */ |
59 | enum bio_post_read_step { | 73 | enum bio_post_read_step { |
60 | STEP_INITIAL = 0, | 74 | STEP_INITIAL = 0, |
@@ -80,10 +94,12 @@ static void __read_end_io(struct bio *bio) | |||
80 | /* PG_error was set if any post_read step failed */ | 94 | /* PG_error was set if any post_read step failed */ |
81 | if (bio->bi_status || PageError(page)) { | 95 | if (bio->bi_status || PageError(page)) { |
82 | ClearPageUptodate(page); | 96 | ClearPageUptodate(page); |
83 | SetPageError(page); | 97 | /* will re-read again later */ |
98 | ClearPageError(page); | ||
84 | } else { | 99 | } else { |
85 | SetPageUptodate(page); | 100 | SetPageUptodate(page); |
86 | } | 101 | } |
102 | dec_page_count(F2FS_P_SB(page), __read_io_type(page)); | ||
87 | unlock_page(page); | 103 | unlock_page(page); |
88 | } | 104 | } |
89 | if (bio->bi_private) | 105 | if (bio->bi_private) |
@@ -126,8 +142,9 @@ static bool f2fs_bio_post_read_required(struct bio *bio) | |||
126 | 142 | ||
127 | static void f2fs_read_end_io(struct bio *bio) | 143 | static void f2fs_read_end_io(struct bio *bio) |
128 | { | 144 | { |
129 | if (time_to_inject(F2FS_P_SB(bio_first_page_all(bio)), FAULT_IO)) { | 145 | if (time_to_inject(F2FS_P_SB(bio_first_page_all(bio)), |
130 | f2fs_show_injection_info(FAULT_IO); | 146 | FAULT_READ_IO)) { |
147 | f2fs_show_injection_info(FAULT_READ_IO); | ||
131 | bio->bi_status = BLK_STS_IOERR; | 148 | bio->bi_status = BLK_STS_IOERR; |
132 | } | 149 | } |
133 | 150 | ||
@@ -148,6 +165,11 @@ static void f2fs_write_end_io(struct bio *bio) | |||
148 | struct bio_vec *bvec; | 165 | struct bio_vec *bvec; |
149 | int i; | 166 | int i; |
150 | 167 | ||
168 | if (time_to_inject(sbi, FAULT_WRITE_IO)) { | ||
169 | f2fs_show_injection_info(FAULT_WRITE_IO); | ||
170 | bio->bi_status = BLK_STS_IOERR; | ||
171 | } | ||
172 | |||
151 | bio_for_each_segment_all(bvec, bio, i) { | 173 | bio_for_each_segment_all(bvec, bio, i) { |
152 | struct page *page = bvec->bv_page; | 174 | struct page *page = bvec->bv_page; |
153 | enum count_type type = WB_DATA_TYPE(page); | 175 | enum count_type type = WB_DATA_TYPE(page); |
@@ -319,8 +341,8 @@ static void __submit_merged_bio(struct f2fs_bio_info *io) | |||
319 | io->bio = NULL; | 341 | io->bio = NULL; |
320 | } | 342 | } |
321 | 343 | ||
322 | static bool __has_merged_page(struct f2fs_bio_info *io, | 344 | static bool __has_merged_page(struct f2fs_bio_info *io, struct inode *inode, |
323 | struct inode *inode, nid_t ino, pgoff_t idx) | 345 | struct page *page, nid_t ino) |
324 | { | 346 | { |
325 | struct bio_vec *bvec; | 347 | struct bio_vec *bvec; |
326 | struct page *target; | 348 | struct page *target; |
@@ -329,7 +351,7 @@ static bool __has_merged_page(struct f2fs_bio_info *io, | |||
329 | if (!io->bio) | 351 | if (!io->bio) |
330 | return false; | 352 | return false; |
331 | 353 | ||
332 | if (!inode && !ino) | 354 | if (!inode && !page && !ino) |
333 | return true; | 355 | return true; |
334 | 356 | ||
335 | bio_for_each_segment_all(bvec, io->bio, i) { | 357 | bio_for_each_segment_all(bvec, io->bio, i) { |
@@ -339,11 +361,10 @@ static bool __has_merged_page(struct f2fs_bio_info *io, | |||
339 | else | 361 | else |
340 | target = fscrypt_control_page(bvec->bv_page); | 362 | target = fscrypt_control_page(bvec->bv_page); |
341 | 363 | ||
342 | if (idx != target->index) | ||
343 | continue; | ||
344 | |||
345 | if (inode && inode == target->mapping->host) | 364 | if (inode && inode == target->mapping->host) |
346 | return true; | 365 | return true; |
366 | if (page && page == target) | ||
367 | return true; | ||
347 | if (ino && ino == ino_of_node(target)) | 368 | if (ino && ino == ino_of_node(target)) |
348 | return true; | 369 | return true; |
349 | } | 370 | } |
@@ -352,7 +373,8 @@ static bool __has_merged_page(struct f2fs_bio_info *io, | |||
352 | } | 373 | } |
353 | 374 | ||
354 | static bool has_merged_page(struct f2fs_sb_info *sbi, struct inode *inode, | 375 | static bool has_merged_page(struct f2fs_sb_info *sbi, struct inode *inode, |
355 | nid_t ino, pgoff_t idx, enum page_type type) | 376 | struct page *page, nid_t ino, |
377 | enum page_type type) | ||
356 | { | 378 | { |
357 | enum page_type btype = PAGE_TYPE_OF_BIO(type); | 379 | enum page_type btype = PAGE_TYPE_OF_BIO(type); |
358 | enum temp_type temp; | 380 | enum temp_type temp; |
@@ -363,7 +385,7 @@ static bool has_merged_page(struct f2fs_sb_info *sbi, struct inode *inode, | |||
363 | io = sbi->write_io[btype] + temp; | 385 | io = sbi->write_io[btype] + temp; |
364 | 386 | ||
365 | down_read(&io->io_rwsem); | 387 | down_read(&io->io_rwsem); |
366 | ret = __has_merged_page(io, inode, ino, idx); | 388 | ret = __has_merged_page(io, inode, page, ino); |
367 | up_read(&io->io_rwsem); | 389 | up_read(&io->io_rwsem); |
368 | 390 | ||
369 | /* TODO: use HOT temp only for meta pages now. */ | 391 | /* TODO: use HOT temp only for meta pages now. */ |
@@ -394,12 +416,12 @@ static void __f2fs_submit_merged_write(struct f2fs_sb_info *sbi, | |||
394 | } | 416 | } |
395 | 417 | ||
396 | static void __submit_merged_write_cond(struct f2fs_sb_info *sbi, | 418 | static void __submit_merged_write_cond(struct f2fs_sb_info *sbi, |
397 | struct inode *inode, nid_t ino, pgoff_t idx, | 419 | struct inode *inode, struct page *page, |
398 | enum page_type type, bool force) | 420 | nid_t ino, enum page_type type, bool force) |
399 | { | 421 | { |
400 | enum temp_type temp; | 422 | enum temp_type temp; |
401 | 423 | ||
402 | if (!force && !has_merged_page(sbi, inode, ino, idx, type)) | 424 | if (!force && !has_merged_page(sbi, inode, page, ino, type)) |
403 | return; | 425 | return; |
404 | 426 | ||
405 | for (temp = HOT; temp < NR_TEMP_TYPE; temp++) { | 427 | for (temp = HOT; temp < NR_TEMP_TYPE; temp++) { |
@@ -418,10 +440,10 @@ void f2fs_submit_merged_write(struct f2fs_sb_info *sbi, enum page_type type) | |||
418 | } | 440 | } |
419 | 441 | ||
420 | void f2fs_submit_merged_write_cond(struct f2fs_sb_info *sbi, | 442 | void f2fs_submit_merged_write_cond(struct f2fs_sb_info *sbi, |
421 | struct inode *inode, nid_t ino, pgoff_t idx, | 443 | struct inode *inode, struct page *page, |
422 | enum page_type type) | 444 | nid_t ino, enum page_type type) |
423 | { | 445 | { |
424 | __submit_merged_write_cond(sbi, inode, ino, idx, type, false); | 446 | __submit_merged_write_cond(sbi, inode, page, ino, type, false); |
425 | } | 447 | } |
426 | 448 | ||
427 | void f2fs_flush_merged_writes(struct f2fs_sb_info *sbi) | 449 | void f2fs_flush_merged_writes(struct f2fs_sb_info *sbi) |
@@ -456,12 +478,16 @@ int f2fs_submit_page_bio(struct f2fs_io_info *fio) | |||
456 | bio_put(bio); | 478 | bio_put(bio); |
457 | return -EFAULT; | 479 | return -EFAULT; |
458 | } | 480 | } |
481 | |||
482 | if (fio->io_wbc && !is_read_io(fio->op)) | ||
483 | wbc_account_io(fio->io_wbc, page, PAGE_SIZE); | ||
484 | |||
459 | bio_set_op_attrs(bio, fio->op, fio->op_flags); | 485 | bio_set_op_attrs(bio, fio->op, fio->op_flags); |
460 | 486 | ||
461 | __submit_bio(fio->sbi, bio, fio->type); | 487 | inc_page_count(fio->sbi, is_read_io(fio->op) ? |
488 | __read_io_type(page): WB_DATA_TYPE(fio->page)); | ||
462 | 489 | ||
463 | if (!is_read_io(fio->op)) | 490 | __submit_bio(fio->sbi, bio, fio->type); |
464 | inc_page_count(fio->sbi, WB_DATA_TYPE(fio->page)); | ||
465 | return 0; | 491 | return 0; |
466 | } | 492 | } |
467 | 493 | ||
@@ -533,6 +559,9 @@ skip: | |||
533 | if (fio->in_list) | 559 | if (fio->in_list) |
534 | goto next; | 560 | goto next; |
535 | out: | 561 | out: |
562 | if (is_sbi_flag_set(sbi, SBI_IS_SHUTDOWN) || | ||
563 | f2fs_is_checkpoint_ready(sbi)) | ||
564 | __submit_merged_bio(io); | ||
536 | up_write(&io->io_rwsem); | 565 | up_write(&io->io_rwsem); |
537 | } | 566 | } |
538 | 567 | ||
@@ -565,9 +594,6 @@ static struct bio *f2fs_grab_read_bio(struct inode *inode, block_t blkaddr, | |||
565 | ctx->bio = bio; | 594 | ctx->bio = bio; |
566 | ctx->enabled_steps = post_read_steps; | 595 | ctx->enabled_steps = post_read_steps; |
567 | bio->bi_private = ctx; | 596 | bio->bi_private = ctx; |
568 | |||
569 | /* wait the page to be moved by cleaning */ | ||
570 | f2fs_wait_on_block_writeback(sbi, blkaddr); | ||
571 | } | 597 | } |
572 | 598 | ||
573 | return bio; | 599 | return bio; |
@@ -582,10 +608,15 @@ static int f2fs_submit_page_read(struct inode *inode, struct page *page, | |||
582 | if (IS_ERR(bio)) | 608 | if (IS_ERR(bio)) |
583 | return PTR_ERR(bio); | 609 | return PTR_ERR(bio); |
584 | 610 | ||
611 | /* wait for GCed page writeback via META_MAPPING */ | ||
612 | f2fs_wait_on_block_writeback(inode, blkaddr); | ||
613 | |||
585 | if (bio_add_page(bio, page, PAGE_SIZE, 0) < PAGE_SIZE) { | 614 | if (bio_add_page(bio, page, PAGE_SIZE, 0) < PAGE_SIZE) { |
586 | bio_put(bio); | 615 | bio_put(bio); |
587 | return -EFAULT; | 616 | return -EFAULT; |
588 | } | 617 | } |
618 | ClearPageError(page); | ||
619 | inc_page_count(F2FS_I_SB(inode), F2FS_RD_DATA); | ||
589 | __submit_bio(F2FS_I_SB(inode), bio, DATA); | 620 | __submit_bio(F2FS_I_SB(inode), bio, DATA); |
590 | return 0; | 621 | return 0; |
591 | } | 622 | } |
@@ -876,7 +907,6 @@ static int __allocate_data_block(struct dnode_of_data *dn, int seg_type) | |||
876 | struct f2fs_summary sum; | 907 | struct f2fs_summary sum; |
877 | struct node_info ni; | 908 | struct node_info ni; |
878 | block_t old_blkaddr; | 909 | block_t old_blkaddr; |
879 | pgoff_t fofs; | ||
880 | blkcnt_t count = 1; | 910 | blkcnt_t count = 1; |
881 | int err; | 911 | int err; |
882 | 912 | ||
@@ -889,7 +919,7 @@ static int __allocate_data_block(struct dnode_of_data *dn, int seg_type) | |||
889 | 919 | ||
890 | dn->data_blkaddr = datablock_addr(dn->inode, | 920 | dn->data_blkaddr = datablock_addr(dn->inode, |
891 | dn->node_page, dn->ofs_in_node); | 921 | dn->node_page, dn->ofs_in_node); |
892 | if (dn->data_blkaddr == NEW_ADDR) | 922 | if (dn->data_blkaddr != NULL_ADDR) |
893 | goto alloc; | 923 | goto alloc; |
894 | 924 | ||
895 | if (unlikely((err = inc_valid_block_count(sbi, dn->inode, &count)))) | 925 | if (unlikely((err = inc_valid_block_count(sbi, dn->inode, &count)))) |
@@ -905,12 +935,10 @@ alloc: | |||
905 | old_blkaddr, old_blkaddr); | 935 | old_blkaddr, old_blkaddr); |
906 | f2fs_set_data_blkaddr(dn); | 936 | f2fs_set_data_blkaddr(dn); |
907 | 937 | ||
908 | /* update i_size */ | 938 | /* |
909 | fofs = f2fs_start_bidx_of_node(ofs_of_node(dn->node_page), dn->inode) + | 939 | * i_size will be updated by direct_IO. Otherwise, we'll get stale |
910 | dn->ofs_in_node; | 940 | * data from unwritten block via dio_read. |
911 | if (i_size_read(dn->inode) < ((loff_t)(fofs + 1) << PAGE_SHIFT)) | 941 | */ |
912 | f2fs_i_size_write(dn->inode, | ||
913 | ((loff_t)(fofs + 1) << PAGE_SHIFT)); | ||
914 | return 0; | 942 | return 0; |
915 | } | 943 | } |
916 | 944 | ||
@@ -945,7 +973,7 @@ int f2fs_preallocate_blocks(struct kiocb *iocb, struct iov_iter *from) | |||
945 | 973 | ||
946 | if (direct_io) { | 974 | if (direct_io) { |
947 | map.m_seg_type = f2fs_rw_hint_to_seg_type(iocb->ki_hint); | 975 | map.m_seg_type = f2fs_rw_hint_to_seg_type(iocb->ki_hint); |
948 | flag = f2fs_force_buffered_io(inode, WRITE) ? | 976 | flag = f2fs_force_buffered_io(inode, iocb, from) ? |
949 | F2FS_GET_BLOCK_PRE_AIO : | 977 | F2FS_GET_BLOCK_PRE_AIO : |
950 | F2FS_GET_BLOCK_PRE_DIO; | 978 | F2FS_GET_BLOCK_PRE_DIO; |
951 | goto map_blocks; | 979 | goto map_blocks; |
@@ -970,7 +998,7 @@ map_blocks: | |||
970 | return err; | 998 | return err; |
971 | } | 999 | } |
972 | 1000 | ||
973 | static inline void __do_map_lock(struct f2fs_sb_info *sbi, int flag, bool lock) | 1001 | void __do_map_lock(struct f2fs_sb_info *sbi, int flag, bool lock) |
974 | { | 1002 | { |
975 | if (flag == F2FS_GET_BLOCK_PRE_AIO) { | 1003 | if (flag == F2FS_GET_BLOCK_PRE_AIO) { |
976 | if (lock) | 1004 | if (lock) |
@@ -1025,6 +1053,11 @@ int f2fs_map_blocks(struct inode *inode, struct f2fs_map_blocks *map, | |||
1025 | map->m_flags = F2FS_MAP_MAPPED; | 1053 | map->m_flags = F2FS_MAP_MAPPED; |
1026 | if (map->m_next_extent) | 1054 | if (map->m_next_extent) |
1027 | *map->m_next_extent = pgofs + map->m_len; | 1055 | *map->m_next_extent = pgofs + map->m_len; |
1056 | |||
1057 | /* for hardware encryption, but to avoid potential issue in future */ | ||
1058 | if (flag == F2FS_GET_BLOCK_DIO) | ||
1059 | f2fs_wait_on_block_writeback_range(inode, | ||
1060 | map->m_pblk, map->m_len); | ||
1028 | goto out; | 1061 | goto out; |
1029 | } | 1062 | } |
1030 | 1063 | ||
@@ -1064,7 +1097,15 @@ next_block: | |||
1064 | goto sync_out; | 1097 | goto sync_out; |
1065 | } | 1098 | } |
1066 | 1099 | ||
1067 | if (!is_valid_data_blkaddr(sbi, blkaddr)) { | 1100 | if (is_valid_data_blkaddr(sbi, blkaddr)) { |
1101 | /* use out-place-update for driect IO under LFS mode */ | ||
1102 | if (test_opt(sbi, LFS) && create && | ||
1103 | flag == F2FS_GET_BLOCK_DIO) { | ||
1104 | err = __allocate_data_block(&dn, map->m_seg_type); | ||
1105 | if (!err) | ||
1106 | set_inode_flag(inode, FI_APPEND_WRITE); | ||
1107 | } | ||
1108 | } else { | ||
1068 | if (create) { | 1109 | if (create) { |
1069 | if (unlikely(f2fs_cp_error(sbi))) { | 1110 | if (unlikely(f2fs_cp_error(sbi))) { |
1070 | err = -EIO; | 1111 | err = -EIO; |
@@ -1076,6 +1117,8 @@ next_block: | |||
1076 | last_ofs_in_node = dn.ofs_in_node; | 1117 | last_ofs_in_node = dn.ofs_in_node; |
1077 | } | 1118 | } |
1078 | } else { | 1119 | } else { |
1120 | WARN_ON(flag != F2FS_GET_BLOCK_PRE_DIO && | ||
1121 | flag != F2FS_GET_BLOCK_DIO); | ||
1079 | err = __allocate_data_block(&dn, | 1122 | err = __allocate_data_block(&dn, |
1080 | map->m_seg_type); | 1123 | map->m_seg_type); |
1081 | if (!err) | 1124 | if (!err) |
@@ -1173,6 +1216,12 @@ skip: | |||
1173 | goto next_dnode; | 1216 | goto next_dnode; |
1174 | 1217 | ||
1175 | sync_out: | 1218 | sync_out: |
1219 | |||
1220 | /* for hardware encryption, but to avoid potential issue in future */ | ||
1221 | if (flag == F2FS_GET_BLOCK_DIO && map->m_flags & F2FS_MAP_MAPPED) | ||
1222 | f2fs_wait_on_block_writeback_range(inode, | ||
1223 | map->m_pblk, map->m_len); | ||
1224 | |||
1176 | if (flag == F2FS_GET_BLOCK_PRECACHE) { | 1225 | if (flag == F2FS_GET_BLOCK_PRECACHE) { |
1177 | if (map->m_flags & F2FS_MAP_MAPPED) { | 1226 | if (map->m_flags & F2FS_MAP_MAPPED) { |
1178 | unsigned int ofs = start_pgofs - map->m_lblk; | 1227 | unsigned int ofs = start_pgofs - map->m_lblk; |
@@ -1255,7 +1304,7 @@ static int get_data_block_dio(struct inode *inode, sector_t iblock, | |||
1255 | struct buffer_head *bh_result, int create) | 1304 | struct buffer_head *bh_result, int create) |
1256 | { | 1305 | { |
1257 | return __get_data_block(inode, iblock, bh_result, create, | 1306 | return __get_data_block(inode, iblock, bh_result, create, |
1258 | F2FS_GET_BLOCK_DEFAULT, NULL, | 1307 | F2FS_GET_BLOCK_DIO, NULL, |
1259 | f2fs_rw_hint_to_seg_type( | 1308 | f2fs_rw_hint_to_seg_type( |
1260 | inode->i_write_hint)); | 1309 | inode->i_write_hint)); |
1261 | } | 1310 | } |
@@ -1558,9 +1607,17 @@ submit_and_realloc: | |||
1558 | } | 1607 | } |
1559 | } | 1608 | } |
1560 | 1609 | ||
1610 | /* | ||
1611 | * If the page is under writeback, we need to wait for | ||
1612 | * its completion to see the correct decrypted data. | ||
1613 | */ | ||
1614 | f2fs_wait_on_block_writeback(inode, block_nr); | ||
1615 | |||
1561 | if (bio_add_page(bio, page, blocksize, 0) < blocksize) | 1616 | if (bio_add_page(bio, page, blocksize, 0) < blocksize) |
1562 | goto submit_and_realloc; | 1617 | goto submit_and_realloc; |
1563 | 1618 | ||
1619 | inc_page_count(F2FS_I_SB(inode), F2FS_RD_DATA); | ||
1620 | ClearPageError(page); | ||
1564 | last_block_in_bio = block_nr; | 1621 | last_block_in_bio = block_nr; |
1565 | goto next_page; | 1622 | goto next_page; |
1566 | set_error_page: | 1623 | set_error_page: |
@@ -1625,7 +1682,7 @@ static int encrypt_one_page(struct f2fs_io_info *fio) | |||
1625 | return 0; | 1682 | return 0; |
1626 | 1683 | ||
1627 | /* wait for GCed page writeback via META_MAPPING */ | 1684 | /* wait for GCed page writeback via META_MAPPING */ |
1628 | f2fs_wait_on_block_writeback(fio->sbi, fio->old_blkaddr); | 1685 | f2fs_wait_on_block_writeback(inode, fio->old_blkaddr); |
1629 | 1686 | ||
1630 | retry_encrypt: | 1687 | retry_encrypt: |
1631 | fio->encrypted_page = fscrypt_encrypt_page(inode, fio->page, | 1688 | fio->encrypted_page = fscrypt_encrypt_page(inode, fio->page, |
@@ -1682,6 +1739,10 @@ static inline bool check_inplace_update_policy(struct inode *inode, | |||
1682 | is_inode_flag_set(inode, FI_NEED_IPU)) | 1739 | is_inode_flag_set(inode, FI_NEED_IPU)) |
1683 | return true; | 1740 | return true; |
1684 | 1741 | ||
1742 | if (unlikely(fio && is_sbi_flag_set(sbi, SBI_CP_DISABLED) && | ||
1743 | !f2fs_is_checkpointed_data(sbi, fio->old_blkaddr))) | ||
1744 | return true; | ||
1745 | |||
1685 | return false; | 1746 | return false; |
1686 | } | 1747 | } |
1687 | 1748 | ||
@@ -1705,6 +1766,8 @@ bool f2fs_should_update_outplace(struct inode *inode, struct f2fs_io_info *fio) | |||
1705 | return true; | 1766 | return true; |
1706 | if (S_ISDIR(inode->i_mode)) | 1767 | if (S_ISDIR(inode->i_mode)) |
1707 | return true; | 1768 | return true; |
1769 | if (IS_NOQUOTA(inode)) | ||
1770 | return true; | ||
1708 | if (f2fs_is_atomic_file(inode)) | 1771 | if (f2fs_is_atomic_file(inode)) |
1709 | return true; | 1772 | return true; |
1710 | if (fio) { | 1773 | if (fio) { |
@@ -1712,6 +1775,9 @@ bool f2fs_should_update_outplace(struct inode *inode, struct f2fs_io_info *fio) | |||
1712 | return true; | 1775 | return true; |
1713 | if (IS_ATOMIC_WRITTEN_PAGE(fio->page)) | 1776 | if (IS_ATOMIC_WRITTEN_PAGE(fio->page)) |
1714 | return true; | 1777 | return true; |
1778 | if (unlikely(is_sbi_flag_set(sbi, SBI_CP_DISABLED) && | ||
1779 | f2fs_is_checkpointed_data(sbi, fio->old_blkaddr))) | ||
1780 | return true; | ||
1715 | } | 1781 | } |
1716 | return false; | 1782 | return false; |
1717 | } | 1783 | } |
@@ -1763,6 +1829,7 @@ int f2fs_do_write_data_page(struct f2fs_io_info *fio) | |||
1763 | /* This page is already truncated */ | 1829 | /* This page is already truncated */ |
1764 | if (fio->old_blkaddr == NULL_ADDR) { | 1830 | if (fio->old_blkaddr == NULL_ADDR) { |
1765 | ClearPageUptodate(page); | 1831 | ClearPageUptodate(page); |
1832 | clear_cold_data(page); | ||
1766 | goto out_writepage; | 1833 | goto out_writepage; |
1767 | } | 1834 | } |
1768 | got_it: | 1835 | got_it: |
@@ -1938,18 +2005,20 @@ done: | |||
1938 | 2005 | ||
1939 | out: | 2006 | out: |
1940 | inode_dec_dirty_pages(inode); | 2007 | inode_dec_dirty_pages(inode); |
1941 | if (err) | 2008 | if (err) { |
1942 | ClearPageUptodate(page); | 2009 | ClearPageUptodate(page); |
2010 | clear_cold_data(page); | ||
2011 | } | ||
1943 | 2012 | ||
1944 | if (wbc->for_reclaim) { | 2013 | if (wbc->for_reclaim) { |
1945 | f2fs_submit_merged_write_cond(sbi, inode, 0, page->index, DATA); | 2014 | f2fs_submit_merged_write_cond(sbi, NULL, page, 0, DATA); |
1946 | clear_inode_flag(inode, FI_HOT_DATA); | 2015 | clear_inode_flag(inode, FI_HOT_DATA); |
1947 | f2fs_remove_dirty_inode(inode); | 2016 | f2fs_remove_dirty_inode(inode); |
1948 | submitted = NULL; | 2017 | submitted = NULL; |
1949 | } | 2018 | } |
1950 | 2019 | ||
1951 | unlock_page(page); | 2020 | unlock_page(page); |
1952 | if (!S_ISDIR(inode->i_mode)) | 2021 | if (!S_ISDIR(inode->i_mode) && !IS_NOQUOTA(inode)) |
1953 | f2fs_balance_fs(sbi, need_balance_fs); | 2022 | f2fs_balance_fs(sbi, need_balance_fs); |
1954 | 2023 | ||
1955 | if (unlikely(f2fs_cp_error(sbi))) { | 2024 | if (unlikely(f2fs_cp_error(sbi))) { |
@@ -2000,10 +2069,10 @@ static int f2fs_write_cache_pages(struct address_space *mapping, | |||
2000 | pgoff_t index; | 2069 | pgoff_t index; |
2001 | pgoff_t end; /* Inclusive */ | 2070 | pgoff_t end; /* Inclusive */ |
2002 | pgoff_t done_index; | 2071 | pgoff_t done_index; |
2003 | pgoff_t last_idx = ULONG_MAX; | ||
2004 | int cycled; | 2072 | int cycled; |
2005 | int range_whole = 0; | 2073 | int range_whole = 0; |
2006 | int tag; | 2074 | int tag; |
2075 | int nwritten = 0; | ||
2007 | 2076 | ||
2008 | pagevec_init(&pvec); | 2077 | pagevec_init(&pvec); |
2009 | 2078 | ||
@@ -2106,7 +2175,7 @@ continue_unlock: | |||
2106 | done = 1; | 2175 | done = 1; |
2107 | break; | 2176 | break; |
2108 | } else if (submitted) { | 2177 | } else if (submitted) { |
2109 | last_idx = page->index; | 2178 | nwritten++; |
2110 | } | 2179 | } |
2111 | 2180 | ||
2112 | if (--wbc->nr_to_write <= 0 && | 2181 | if (--wbc->nr_to_write <= 0 && |
@@ -2128,9 +2197,9 @@ continue_unlock: | |||
2128 | if (wbc->range_cyclic || (range_whole && wbc->nr_to_write > 0)) | 2197 | if (wbc->range_cyclic || (range_whole && wbc->nr_to_write > 0)) |
2129 | mapping->writeback_index = done_index; | 2198 | mapping->writeback_index = done_index; |
2130 | 2199 | ||
2131 | if (last_idx != ULONG_MAX) | 2200 | if (nwritten) |
2132 | f2fs_submit_merged_write_cond(F2FS_M_SB(mapping), mapping->host, | 2201 | f2fs_submit_merged_write_cond(F2FS_M_SB(mapping), mapping->host, |
2133 | 0, last_idx, DATA); | 2202 | NULL, 0, DATA); |
2134 | 2203 | ||
2135 | return ret; | 2204 | return ret; |
2136 | } | 2205 | } |
@@ -2140,6 +2209,8 @@ static inline bool __should_serialize_io(struct inode *inode, | |||
2140 | { | 2209 | { |
2141 | if (!S_ISREG(inode->i_mode)) | 2210 | if (!S_ISREG(inode->i_mode)) |
2142 | return false; | 2211 | return false; |
2212 | if (IS_NOQUOTA(inode)) | ||
2213 | return false; | ||
2143 | if (wbc->sync_mode != WB_SYNC_ALL) | 2214 | if (wbc->sync_mode != WB_SYNC_ALL) |
2144 | return true; | 2215 | return true; |
2145 | if (get_dirty_pages(inode) >= SM_I(F2FS_I_SB(inode))->min_seq_blocks) | 2216 | if (get_dirty_pages(inode) >= SM_I(F2FS_I_SB(inode))->min_seq_blocks) |
@@ -2169,7 +2240,8 @@ static int __f2fs_write_data_pages(struct address_space *mapping, | |||
2169 | if (unlikely(is_sbi_flag_set(sbi, SBI_POR_DOING))) | 2240 | if (unlikely(is_sbi_flag_set(sbi, SBI_POR_DOING))) |
2170 | goto skip_write; | 2241 | goto skip_write; |
2171 | 2242 | ||
2172 | if (S_ISDIR(inode->i_mode) && wbc->sync_mode == WB_SYNC_NONE && | 2243 | if ((S_ISDIR(inode->i_mode) || IS_NOQUOTA(inode)) && |
2244 | wbc->sync_mode == WB_SYNC_NONE && | ||
2173 | get_dirty_pages(inode) < nr_pages_to_skip(sbi, DATA) && | 2245 | get_dirty_pages(inode) < nr_pages_to_skip(sbi, DATA) && |
2174 | f2fs_available_free_memory(sbi, DIRTY_DENTS)) | 2246 | f2fs_available_free_memory(sbi, DIRTY_DENTS)) |
2175 | goto skip_write; | 2247 | goto skip_write; |
@@ -2234,7 +2306,7 @@ static void f2fs_write_failed(struct address_space *mapping, loff_t to) | |||
2234 | down_write(&F2FS_I(inode)->i_mmap_sem); | 2306 | down_write(&F2FS_I(inode)->i_mmap_sem); |
2235 | 2307 | ||
2236 | truncate_pagecache(inode, i_size); | 2308 | truncate_pagecache(inode, i_size); |
2237 | f2fs_truncate_blocks(inode, i_size, true); | 2309 | f2fs_truncate_blocks(inode, i_size, true, true); |
2238 | 2310 | ||
2239 | up_write(&F2FS_I(inode)->i_mmap_sem); | 2311 | up_write(&F2FS_I(inode)->i_mmap_sem); |
2240 | up_write(&F2FS_I(inode)->i_gc_rwsem[WRITE]); | 2312 | up_write(&F2FS_I(inode)->i_gc_rwsem[WRITE]); |
@@ -2332,6 +2404,10 @@ static int f2fs_write_begin(struct file *file, struct address_space *mapping, | |||
2332 | 2404 | ||
2333 | trace_f2fs_write_begin(inode, pos, len, flags); | 2405 | trace_f2fs_write_begin(inode, pos, len, flags); |
2334 | 2406 | ||
2407 | err = f2fs_is_checkpoint_ready(sbi); | ||
2408 | if (err) | ||
2409 | goto fail; | ||
2410 | |||
2335 | if ((f2fs_is_atomic_file(inode) && | 2411 | if ((f2fs_is_atomic_file(inode) && |
2336 | !f2fs_available_free_memory(sbi, INMEM_PAGES)) || | 2412 | !f2fs_available_free_memory(sbi, INMEM_PAGES)) || |
2337 | is_inode_flag_set(inode, FI_ATOMIC_REVOKE_REQUEST)) { | 2413 | is_inode_flag_set(inode, FI_ATOMIC_REVOKE_REQUEST)) { |
@@ -2369,7 +2445,8 @@ repeat: | |||
2369 | if (err) | 2445 | if (err) |
2370 | goto fail; | 2446 | goto fail; |
2371 | 2447 | ||
2372 | if (need_balance && has_not_enough_free_secs(sbi, 0, 0)) { | 2448 | if (need_balance && !IS_NOQUOTA(inode) && |
2449 | has_not_enough_free_secs(sbi, 0, 0)) { | ||
2373 | unlock_page(page); | 2450 | unlock_page(page); |
2374 | f2fs_balance_fs(sbi, true); | 2451 | f2fs_balance_fs(sbi, true); |
2375 | lock_page(page); | 2452 | lock_page(page); |
@@ -2382,10 +2459,6 @@ repeat: | |||
2382 | 2459 | ||
2383 | f2fs_wait_on_page_writeback(page, DATA, false); | 2460 | f2fs_wait_on_page_writeback(page, DATA, false); |
2384 | 2461 | ||
2385 | /* wait for GCed page writeback via META_MAPPING */ | ||
2386 | if (f2fs_post_read_required(inode)) | ||
2387 | f2fs_wait_on_block_writeback(sbi, blkaddr); | ||
2388 | |||
2389 | if (len == PAGE_SIZE || PageUptodate(page)) | 2462 | if (len == PAGE_SIZE || PageUptodate(page)) |
2390 | return 0; | 2463 | return 0; |
2391 | 2464 | ||
@@ -2480,36 +2553,53 @@ static ssize_t f2fs_direct_IO(struct kiocb *iocb, struct iov_iter *iter) | |||
2480 | struct address_space *mapping = iocb->ki_filp->f_mapping; | 2553 | struct address_space *mapping = iocb->ki_filp->f_mapping; |
2481 | struct inode *inode = mapping->host; | 2554 | struct inode *inode = mapping->host; |
2482 | struct f2fs_sb_info *sbi = F2FS_I_SB(inode); | 2555 | struct f2fs_sb_info *sbi = F2FS_I_SB(inode); |
2556 | struct f2fs_inode_info *fi = F2FS_I(inode); | ||
2483 | size_t count = iov_iter_count(iter); | 2557 | size_t count = iov_iter_count(iter); |
2484 | loff_t offset = iocb->ki_pos; | 2558 | loff_t offset = iocb->ki_pos; |
2485 | int rw = iov_iter_rw(iter); | 2559 | int rw = iov_iter_rw(iter); |
2486 | int err; | 2560 | int err; |
2487 | enum rw_hint hint = iocb->ki_hint; | 2561 | enum rw_hint hint = iocb->ki_hint; |
2488 | int whint_mode = F2FS_OPTION(sbi).whint_mode; | 2562 | int whint_mode = F2FS_OPTION(sbi).whint_mode; |
2563 | bool do_opu; | ||
2489 | 2564 | ||
2490 | err = check_direct_IO(inode, iter, offset); | 2565 | err = check_direct_IO(inode, iter, offset); |
2491 | if (err) | 2566 | if (err) |
2492 | return err < 0 ? err : 0; | 2567 | return err < 0 ? err : 0; |
2493 | 2568 | ||
2494 | if (f2fs_force_buffered_io(inode, rw)) | 2569 | if (f2fs_force_buffered_io(inode, iocb, iter)) |
2495 | return 0; | 2570 | return 0; |
2496 | 2571 | ||
2572 | do_opu = allow_outplace_dio(inode, iocb, iter); | ||
2573 | |||
2497 | trace_f2fs_direct_IO_enter(inode, offset, count, rw); | 2574 | trace_f2fs_direct_IO_enter(inode, offset, count, rw); |
2498 | 2575 | ||
2499 | if (rw == WRITE && whint_mode == WHINT_MODE_OFF) | 2576 | if (rw == WRITE && whint_mode == WHINT_MODE_OFF) |
2500 | iocb->ki_hint = WRITE_LIFE_NOT_SET; | 2577 | iocb->ki_hint = WRITE_LIFE_NOT_SET; |
2501 | 2578 | ||
2502 | if (!down_read_trylock(&F2FS_I(inode)->i_gc_rwsem[rw])) { | 2579 | if (iocb->ki_flags & IOCB_NOWAIT) { |
2503 | if (iocb->ki_flags & IOCB_NOWAIT) { | 2580 | if (!down_read_trylock(&fi->i_gc_rwsem[rw])) { |
2504 | iocb->ki_hint = hint; | 2581 | iocb->ki_hint = hint; |
2505 | err = -EAGAIN; | 2582 | err = -EAGAIN; |
2506 | goto out; | 2583 | goto out; |
2507 | } | 2584 | } |
2508 | down_read(&F2FS_I(inode)->i_gc_rwsem[rw]); | 2585 | if (do_opu && !down_read_trylock(&fi->i_gc_rwsem[READ])) { |
2586 | up_read(&fi->i_gc_rwsem[rw]); | ||
2587 | iocb->ki_hint = hint; | ||
2588 | err = -EAGAIN; | ||
2589 | goto out; | ||
2590 | } | ||
2591 | } else { | ||
2592 | down_read(&fi->i_gc_rwsem[rw]); | ||
2593 | if (do_opu) | ||
2594 | down_read(&fi->i_gc_rwsem[READ]); | ||
2509 | } | 2595 | } |
2510 | 2596 | ||
2511 | err = blockdev_direct_IO(iocb, inode, iter, get_data_block_dio); | 2597 | err = blockdev_direct_IO(iocb, inode, iter, get_data_block_dio); |
2512 | up_read(&F2FS_I(inode)->i_gc_rwsem[rw]); | 2598 | |
2599 | if (do_opu) | ||
2600 | up_read(&fi->i_gc_rwsem[READ]); | ||
2601 | |||
2602 | up_read(&fi->i_gc_rwsem[rw]); | ||
2513 | 2603 | ||
2514 | if (rw == WRITE) { | 2604 | if (rw == WRITE) { |
2515 | if (whint_mode == WHINT_MODE_OFF) | 2605 | if (whint_mode == WHINT_MODE_OFF) |
@@ -2517,7 +2607,8 @@ static ssize_t f2fs_direct_IO(struct kiocb *iocb, struct iov_iter *iter) | |||
2517 | if (err > 0) { | 2607 | if (err > 0) { |
2518 | f2fs_update_iostat(F2FS_I_SB(inode), APP_DIRECT_IO, | 2608 | f2fs_update_iostat(F2FS_I_SB(inode), APP_DIRECT_IO, |
2519 | err); | 2609 | err); |
2520 | set_inode_flag(inode, FI_UPDATE_WRITE); | 2610 | if (!do_opu) |
2611 | set_inode_flag(inode, FI_UPDATE_WRITE); | ||
2521 | } else if (err < 0) { | 2612 | } else if (err < 0) { |
2522 | f2fs_write_failed(mapping, offset + count); | 2613 | f2fs_write_failed(mapping, offset + count); |
2523 | } | 2614 | } |
@@ -2550,6 +2641,8 @@ void f2fs_invalidate_page(struct page *page, unsigned int offset, | |||
2550 | } | 2641 | } |
2551 | } | 2642 | } |
2552 | 2643 | ||
2644 | clear_cold_data(page); | ||
2645 | |||
2553 | /* This is atomic written page, keep Private */ | 2646 | /* This is atomic written page, keep Private */ |
2554 | if (IS_ATOMIC_WRITTEN_PAGE(page)) | 2647 | if (IS_ATOMIC_WRITTEN_PAGE(page)) |
2555 | return f2fs_drop_inmem_page(inode, page); | 2648 | return f2fs_drop_inmem_page(inode, page); |
@@ -2568,6 +2661,7 @@ int f2fs_release_page(struct page *page, gfp_t wait) | |||
2568 | if (IS_ATOMIC_WRITTEN_PAGE(page)) | 2661 | if (IS_ATOMIC_WRITTEN_PAGE(page)) |
2569 | return 0; | 2662 | return 0; |
2570 | 2663 | ||
2664 | clear_cold_data(page); | ||
2571 | set_page_private(page, 0); | 2665 | set_page_private(page, 0); |
2572 | ClearPagePrivate(page); | 2666 | ClearPagePrivate(page); |
2573 | return 1; | 2667 | return 1; |
@@ -2583,10 +2677,6 @@ static int f2fs_set_data_page_dirty(struct page *page) | |||
2583 | if (!PageUptodate(page)) | 2677 | if (!PageUptodate(page)) |
2584 | SetPageUptodate(page); | 2678 | SetPageUptodate(page); |
2585 | 2679 | ||
2586 | /* don't remain PG_checked flag which was set during GC */ | ||
2587 | if (is_cold_data(page)) | ||
2588 | clear_cold_data(page); | ||
2589 | |||
2590 | if (f2fs_is_atomic_file(inode) && !f2fs_is_commit_atomic_write(inode)) { | 2680 | if (f2fs_is_atomic_file(inode) && !f2fs_is_commit_atomic_write(inode)) { |
2591 | if (!IS_ATOMIC_WRITTEN_PAGE(page)) { | 2681 | if (!IS_ATOMIC_WRITTEN_PAGE(page)) { |
2592 | f2fs_register_inmem_page(inode, page); | 2682 | f2fs_register_inmem_page(inode, page); |
diff --git a/fs/f2fs/debug.c b/fs/f2fs/debug.c index 214a968962a1..139b4d5c83d5 100644 --- a/fs/f2fs/debug.c +++ b/fs/f2fs/debug.c | |||
@@ -1,3 +1,4 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
1 | /* | 2 | /* |
2 | * f2fs debugging statistics | 3 | * f2fs debugging statistics |
3 | * | 4 | * |
@@ -5,10 +6,6 @@ | |||
5 | * http://www.samsung.com/ | 6 | * http://www.samsung.com/ |
6 | * Copyright (c) 2012 Linux Foundation | 7 | * Copyright (c) 2012 Linux Foundation |
7 | * Copyright (c) 2012 Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 8 | * Copyright (c) 2012 Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License version 2 as | ||
11 | * published by the Free Software Foundation. | ||
12 | */ | 9 | */ |
13 | 10 | ||
14 | #include <linux/fs.h> | 11 | #include <linux/fs.h> |
@@ -58,6 +55,9 @@ static void update_general_status(struct f2fs_sb_info *sbi) | |||
58 | si->max_vw_cnt = atomic_read(&sbi->max_vw_cnt); | 55 | si->max_vw_cnt = atomic_read(&sbi->max_vw_cnt); |
59 | si->nr_wb_cp_data = get_pages(sbi, F2FS_WB_CP_DATA); | 56 | si->nr_wb_cp_data = get_pages(sbi, F2FS_WB_CP_DATA); |
60 | si->nr_wb_data = get_pages(sbi, F2FS_WB_DATA); | 57 | si->nr_wb_data = get_pages(sbi, F2FS_WB_DATA); |
58 | si->nr_rd_data = get_pages(sbi, F2FS_RD_DATA); | ||
59 | si->nr_rd_node = get_pages(sbi, F2FS_RD_NODE); | ||
60 | si->nr_rd_meta = get_pages(sbi, F2FS_RD_META); | ||
61 | if (SM_I(sbi) && SM_I(sbi)->fcc_info) { | 61 | if (SM_I(sbi) && SM_I(sbi)->fcc_info) { |
62 | si->nr_flushed = | 62 | si->nr_flushed = |
63 | atomic_read(&SM_I(sbi)->fcc_info->issued_flush); | 63 | atomic_read(&SM_I(sbi)->fcc_info->issued_flush); |
@@ -104,6 +104,8 @@ static void update_general_status(struct f2fs_sb_info *sbi) | |||
104 | si->avail_nids = NM_I(sbi)->available_nids; | 104 | si->avail_nids = NM_I(sbi)->available_nids; |
105 | si->alloc_nids = NM_I(sbi)->nid_cnt[PREALLOC_NID]; | 105 | si->alloc_nids = NM_I(sbi)->nid_cnt[PREALLOC_NID]; |
106 | si->bg_gc = sbi->bg_gc; | 106 | si->bg_gc = sbi->bg_gc; |
107 | si->io_skip_bggc = sbi->io_skip_bggc; | ||
108 | si->other_skip_bggc = sbi->other_skip_bggc; | ||
107 | si->skipped_atomic_files[BG_GC] = sbi->skipped_atomic_files[BG_GC]; | 109 | si->skipped_atomic_files[BG_GC] = sbi->skipped_atomic_files[BG_GC]; |
108 | si->skipped_atomic_files[FG_GC] = sbi->skipped_atomic_files[FG_GC]; | 110 | si->skipped_atomic_files[FG_GC] = sbi->skipped_atomic_files[FG_GC]; |
109 | si->util_free = (int)(free_user_blocks(sbi) >> sbi->log_blocks_per_seg) | 111 | si->util_free = (int)(free_user_blocks(sbi) >> sbi->log_blocks_per_seg) |
@@ -121,6 +123,9 @@ static void update_general_status(struct f2fs_sb_info *sbi) | |||
121 | si->curzone[i] = GET_ZONE_FROM_SEC(sbi, si->cursec[i]); | 123 | si->curzone[i] = GET_ZONE_FROM_SEC(sbi, si->cursec[i]); |
122 | } | 124 | } |
123 | 125 | ||
126 | for (i = META_CP; i < META_MAX; i++) | ||
127 | si->meta_count[i] = atomic_read(&sbi->meta_count[i]); | ||
128 | |||
124 | for (i = 0; i < 2; i++) { | 129 | for (i = 0; i < 2; i++) { |
125 | si->segment_count[i] = sbi->segment_count[i]; | 130 | si->segment_count[i] = sbi->segment_count[i]; |
126 | si->block_count[i] = sbi->block_count[i]; | 131 | si->block_count[i] = sbi->block_count[i]; |
@@ -190,8 +195,7 @@ static void update_mem_info(struct f2fs_sb_info *sbi) | |||
190 | si->base_mem += MAIN_SEGS(sbi) * sizeof(struct seg_entry); | 195 | si->base_mem += MAIN_SEGS(sbi) * sizeof(struct seg_entry); |
191 | si->base_mem += f2fs_bitmap_size(MAIN_SEGS(sbi)); | 196 | si->base_mem += f2fs_bitmap_size(MAIN_SEGS(sbi)); |
192 | si->base_mem += 2 * SIT_VBLOCK_MAP_SIZE * MAIN_SEGS(sbi); | 197 | si->base_mem += 2 * SIT_VBLOCK_MAP_SIZE * MAIN_SEGS(sbi); |
193 | if (f2fs_discard_en(sbi)) | 198 | si->base_mem += SIT_VBLOCK_MAP_SIZE * MAIN_SEGS(sbi); |
194 | si->base_mem += SIT_VBLOCK_MAP_SIZE * MAIN_SEGS(sbi); | ||
195 | si->base_mem += SIT_VBLOCK_MAP_SIZE; | 199 | si->base_mem += SIT_VBLOCK_MAP_SIZE; |
196 | if (sbi->segs_per_sec > 1) | 200 | if (sbi->segs_per_sec > 1) |
197 | si->base_mem += MAIN_SECS(sbi) * sizeof(struct sec_entry); | 201 | si->base_mem += MAIN_SECS(sbi) * sizeof(struct sec_entry); |
@@ -271,7 +275,8 @@ static int stat_show(struct seq_file *s, void *v) | |||
271 | seq_printf(s, "\n=====[ partition info(%pg). #%d, %s, CP: %s]=====\n", | 275 | seq_printf(s, "\n=====[ partition info(%pg). #%d, %s, CP: %s]=====\n", |
272 | si->sbi->sb->s_bdev, i++, | 276 | si->sbi->sb->s_bdev, i++, |
273 | f2fs_readonly(si->sbi->sb) ? "RO": "RW", | 277 | f2fs_readonly(si->sbi->sb) ? "RO": "RW", |
274 | f2fs_cp_error(si->sbi) ? "Error": "Good"); | 278 | is_set_ckpt_flags(si->sbi, CP_DISABLED_FLAG) ? |
279 | "Disabled": (f2fs_cp_error(si->sbi) ? "Error": "Good")); | ||
275 | seq_printf(s, "[SB: 1] [CP: 2] [SIT: %d] [NAT: %d] ", | 280 | seq_printf(s, "[SB: 1] [CP: 2] [SIT: %d] [NAT: %d] ", |
276 | si->sit_area_segs, si->nat_area_segs); | 281 | si->sit_area_segs, si->nat_area_segs); |
277 | seq_printf(s, "[SSA: %d] [MAIN: %d", | 282 | seq_printf(s, "[SSA: %d] [MAIN: %d", |
@@ -333,6 +338,13 @@ static int stat_show(struct seq_file *s, void *v) | |||
333 | si->prefree_count, si->free_segs, si->free_secs); | 338 | si->prefree_count, si->free_segs, si->free_secs); |
334 | seq_printf(s, "CP calls: %d (BG: %d)\n", | 339 | seq_printf(s, "CP calls: %d (BG: %d)\n", |
335 | si->cp_count, si->bg_cp_count); | 340 | si->cp_count, si->bg_cp_count); |
341 | seq_printf(s, " - cp blocks : %u\n", si->meta_count[META_CP]); | ||
342 | seq_printf(s, " - sit blocks : %u\n", | ||
343 | si->meta_count[META_SIT]); | ||
344 | seq_printf(s, " - nat blocks : %u\n", | ||
345 | si->meta_count[META_NAT]); | ||
346 | seq_printf(s, " - ssa blocks : %u\n", | ||
347 | si->meta_count[META_SSA]); | ||
336 | seq_printf(s, "GC calls: %d (BG: %d)\n", | 348 | seq_printf(s, "GC calls: %d (BG: %d)\n", |
337 | si->call_count, si->bg_gc); | 349 | si->call_count, si->bg_gc); |
338 | seq_printf(s, " - data segments : %d (%d)\n", | 350 | seq_printf(s, " - data segments : %d (%d)\n", |
@@ -349,6 +361,8 @@ static int stat_show(struct seq_file *s, void *v) | |||
349 | si->skipped_atomic_files[BG_GC] + | 361 | si->skipped_atomic_files[BG_GC] + |
350 | si->skipped_atomic_files[FG_GC], | 362 | si->skipped_atomic_files[FG_GC], |
351 | si->skipped_atomic_files[BG_GC]); | 363 | si->skipped_atomic_files[BG_GC]); |
364 | seq_printf(s, "BG skip : IO: %u, Other: %u\n", | ||
365 | si->io_skip_bggc, si->other_skip_bggc); | ||
352 | seq_puts(s, "\nExtent Cache:\n"); | 366 | seq_puts(s, "\nExtent Cache:\n"); |
353 | seq_printf(s, " - Hit Count: L1-1:%llu L1-2:%llu L2:%llu\n", | 367 | seq_printf(s, " - Hit Count: L1-1:%llu L1-2:%llu L2:%llu\n", |
354 | si->hit_largest, si->hit_cached, | 368 | si->hit_largest, si->hit_cached, |
@@ -360,7 +374,9 @@ static int stat_show(struct seq_file *s, void *v) | |||
360 | seq_printf(s, " - Inner Struct Count: tree: %d(%d), node: %d\n", | 374 | seq_printf(s, " - Inner Struct Count: tree: %d(%d), node: %d\n", |
361 | si->ext_tree, si->zombie_tree, si->ext_node); | 375 | si->ext_tree, si->zombie_tree, si->ext_node); |
362 | seq_puts(s, "\nBalancing F2FS Async:\n"); | 376 | seq_puts(s, "\nBalancing F2FS Async:\n"); |
363 | seq_printf(s, " - IO (CP: %4d, Data: %4d, Flush: (%4d %4d %4d), " | 377 | seq_printf(s, " - IO_R (Data: %4d, Node: %4d, Meta: %4d\n", |
378 | si->nr_rd_data, si->nr_rd_node, si->nr_rd_meta); | ||
379 | seq_printf(s, " - IO_W (CP: %4d, Data: %4d, Flush: (%4d %4d %4d), " | ||
364 | "Discard: (%4d %4d)) cmd: %4d undiscard:%4u\n", | 380 | "Discard: (%4d %4d)) cmd: %4d undiscard:%4u\n", |
365 | si->nr_wb_cp_data, si->nr_wb_data, | 381 | si->nr_wb_cp_data, si->nr_wb_data, |
366 | si->nr_flushing, si->nr_flushed, | 382 | si->nr_flushing, si->nr_flushed, |
@@ -445,6 +461,7 @@ int f2fs_build_stats(struct f2fs_sb_info *sbi) | |||
445 | { | 461 | { |
446 | struct f2fs_super_block *raw_super = F2FS_RAW_SUPER(sbi); | 462 | struct f2fs_super_block *raw_super = F2FS_RAW_SUPER(sbi); |
447 | struct f2fs_stat_info *si; | 463 | struct f2fs_stat_info *si; |
464 | int i; | ||
448 | 465 | ||
449 | si = f2fs_kzalloc(sbi, sizeof(struct f2fs_stat_info), GFP_KERNEL); | 466 | si = f2fs_kzalloc(sbi, sizeof(struct f2fs_stat_info), GFP_KERNEL); |
450 | if (!si) | 467 | if (!si) |
@@ -470,6 +487,8 @@ int f2fs_build_stats(struct f2fs_sb_info *sbi) | |||
470 | atomic_set(&sbi->inline_inode, 0); | 487 | atomic_set(&sbi->inline_inode, 0); |
471 | atomic_set(&sbi->inline_dir, 0); | 488 | atomic_set(&sbi->inline_dir, 0); |
472 | atomic_set(&sbi->inplace_count, 0); | 489 | atomic_set(&sbi->inplace_count, 0); |
490 | for (i = META_CP; i < META_MAX; i++) | ||
491 | atomic_set(&sbi->meta_count[i], 0); | ||
473 | 492 | ||
474 | atomic_set(&sbi->aw_cnt, 0); | 493 | atomic_set(&sbi->aw_cnt, 0); |
475 | atomic_set(&sbi->vw_cnt, 0); | 494 | atomic_set(&sbi->vw_cnt, 0); |
diff --git a/fs/f2fs/dir.c b/fs/f2fs/dir.c index ecc3a4e2be96..2ef84b4590ea 100644 --- a/fs/f2fs/dir.c +++ b/fs/f2fs/dir.c | |||
@@ -1,12 +1,9 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
1 | /* | 2 | /* |
2 | * fs/f2fs/dir.c | 3 | * fs/f2fs/dir.c |
3 | * | 4 | * |
4 | * Copyright (c) 2012 Samsung Electronics Co., Ltd. | 5 | * Copyright (c) 2012 Samsung Electronics Co., Ltd. |
5 | * http://www.samsung.com/ | 6 | * http://www.samsung.com/ |
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | */ | 7 | */ |
11 | #include <linux/fs.h> | 8 | #include <linux/fs.h> |
12 | #include <linux/f2fs_fs.h> | 9 | #include <linux/f2fs_fs.h> |
@@ -658,9 +655,9 @@ int f2fs_do_tmpfile(struct inode *inode, struct inode *dir) | |||
658 | f2fs_put_page(page, 1); | 655 | f2fs_put_page(page, 1); |
659 | 656 | ||
660 | clear_inode_flag(inode, FI_NEW_INODE); | 657 | clear_inode_flag(inode, FI_NEW_INODE); |
658 | f2fs_update_time(F2FS_I_SB(inode), REQ_TIME); | ||
661 | fail: | 659 | fail: |
662 | up_write(&F2FS_I(inode)->i_sem); | 660 | up_write(&F2FS_I(inode)->i_sem); |
663 | f2fs_update_time(F2FS_I_SB(inode), REQ_TIME); | ||
664 | return err; | 661 | return err; |
665 | } | 662 | } |
666 | 663 | ||
@@ -733,6 +730,7 @@ void f2fs_delete_entry(struct f2fs_dir_entry *dentry, struct page *page, | |||
733 | clear_page_dirty_for_io(page); | 730 | clear_page_dirty_for_io(page); |
734 | ClearPagePrivate(page); | 731 | ClearPagePrivate(page); |
735 | ClearPageUptodate(page); | 732 | ClearPageUptodate(page); |
733 | clear_cold_data(page); | ||
736 | inode_dec_dirty_pages(dir); | 734 | inode_dec_dirty_pages(dir); |
737 | f2fs_remove_dirty_inode(dir); | 735 | f2fs_remove_dirty_inode(dir); |
738 | } | 736 | } |
@@ -784,9 +782,15 @@ int f2fs_fill_dentries(struct dir_context *ctx, struct f2fs_dentry_ptr *d, | |||
784 | struct f2fs_dir_entry *de = NULL; | 782 | struct f2fs_dir_entry *de = NULL; |
785 | struct fscrypt_str de_name = FSTR_INIT(NULL, 0); | 783 | struct fscrypt_str de_name = FSTR_INIT(NULL, 0); |
786 | struct f2fs_sb_info *sbi = F2FS_I_SB(d->inode); | 784 | struct f2fs_sb_info *sbi = F2FS_I_SB(d->inode); |
785 | struct blk_plug plug; | ||
786 | bool readdir_ra = sbi->readdir_ra == 1; | ||
787 | int err = 0; | ||
787 | 788 | ||
788 | bit_pos = ((unsigned long)ctx->pos % d->max); | 789 | bit_pos = ((unsigned long)ctx->pos % d->max); |
789 | 790 | ||
791 | if (readdir_ra) | ||
792 | blk_start_plug(&plug); | ||
793 | |||
790 | while (bit_pos < d->max) { | 794 | while (bit_pos < d->max) { |
791 | bit_pos = find_next_bit_le(d->bitmap, d->max, bit_pos); | 795 | bit_pos = find_next_bit_le(d->bitmap, d->max, bit_pos); |
792 | if (bit_pos >= d->max) | 796 | if (bit_pos >= d->max) |
@@ -806,29 +810,33 @@ int f2fs_fill_dentries(struct dir_context *ctx, struct f2fs_dentry_ptr *d, | |||
806 | 810 | ||
807 | if (f2fs_encrypted_inode(d->inode)) { | 811 | if (f2fs_encrypted_inode(d->inode)) { |
808 | int save_len = fstr->len; | 812 | int save_len = fstr->len; |
809 | int err; | ||
810 | 813 | ||
811 | err = fscrypt_fname_disk_to_usr(d->inode, | 814 | err = fscrypt_fname_disk_to_usr(d->inode, |
812 | (u32)de->hash_code, 0, | 815 | (u32)de->hash_code, 0, |
813 | &de_name, fstr); | 816 | &de_name, fstr); |
814 | if (err) | 817 | if (err) |
815 | return err; | 818 | goto out; |
816 | 819 | ||
817 | de_name = *fstr; | 820 | de_name = *fstr; |
818 | fstr->len = save_len; | 821 | fstr->len = save_len; |
819 | } | 822 | } |
820 | 823 | ||
821 | if (!dir_emit(ctx, de_name.name, de_name.len, | 824 | if (!dir_emit(ctx, de_name.name, de_name.len, |
822 | le32_to_cpu(de->ino), d_type)) | 825 | le32_to_cpu(de->ino), d_type)) { |
823 | return 1; | 826 | err = 1; |
827 | goto out; | ||
828 | } | ||
824 | 829 | ||
825 | if (sbi->readdir_ra == 1) | 830 | if (readdir_ra) |
826 | f2fs_ra_node_page(sbi, le32_to_cpu(de->ino)); | 831 | f2fs_ra_node_page(sbi, le32_to_cpu(de->ino)); |
827 | 832 | ||
828 | bit_pos += GET_DENTRY_SLOTS(le16_to_cpu(de->name_len)); | 833 | bit_pos += GET_DENTRY_SLOTS(le16_to_cpu(de->name_len)); |
829 | ctx->pos = start_pos + bit_pos; | 834 | ctx->pos = start_pos + bit_pos; |
830 | } | 835 | } |
831 | return 0; | 836 | out: |
837 | if (readdir_ra) | ||
838 | blk_finish_plug(&plug); | ||
839 | return err; | ||
832 | } | 840 | } |
833 | 841 | ||
834 | static int f2fs_readdir(struct file *file, struct dir_context *ctx) | 842 | static int f2fs_readdir(struct file *file, struct dir_context *ctx) |
diff --git a/fs/f2fs/extent_cache.c b/fs/f2fs/extent_cache.c index 231b77ef5a53..1cb0fcc67d2d 100644 --- a/fs/f2fs/extent_cache.c +++ b/fs/f2fs/extent_cache.c | |||
@@ -1,3 +1,4 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
1 | /* | 2 | /* |
2 | * f2fs extent cache support | 3 | * f2fs extent cache support |
3 | * | 4 | * |
@@ -5,10 +6,6 @@ | |||
5 | * Copyright (c) 2015 Samsung Electronics | 6 | * Copyright (c) 2015 Samsung Electronics |
6 | * Authors: Jaegeuk Kim <jaegeuk@kernel.org> | 7 | * Authors: Jaegeuk Kim <jaegeuk@kernel.org> |
7 | * Chao Yu <chao2.yu@samsung.com> | 8 | * Chao Yu <chao2.yu@samsung.com> |
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License version 2 as | ||
11 | * published by the Free Software Foundation. | ||
12 | */ | 9 | */ |
13 | 10 | ||
14 | #include <linux/fs.h> | 11 | #include <linux/fs.h> |
@@ -30,10 +27,10 @@ static struct rb_entry *__lookup_rb_tree_fast(struct rb_entry *cached_re, | |||
30 | return NULL; | 27 | return NULL; |
31 | } | 28 | } |
32 | 29 | ||
33 | static struct rb_entry *__lookup_rb_tree_slow(struct rb_root *root, | 30 | static struct rb_entry *__lookup_rb_tree_slow(struct rb_root_cached *root, |
34 | unsigned int ofs) | 31 | unsigned int ofs) |
35 | { | 32 | { |
36 | struct rb_node *node = root->rb_node; | 33 | struct rb_node *node = root->rb_root.rb_node; |
37 | struct rb_entry *re; | 34 | struct rb_entry *re; |
38 | 35 | ||
39 | while (node) { | 36 | while (node) { |
@@ -49,7 +46,7 @@ static struct rb_entry *__lookup_rb_tree_slow(struct rb_root *root, | |||
49 | return NULL; | 46 | return NULL; |
50 | } | 47 | } |
51 | 48 | ||
52 | struct rb_entry *f2fs_lookup_rb_tree(struct rb_root *root, | 49 | struct rb_entry *f2fs_lookup_rb_tree(struct rb_root_cached *root, |
53 | struct rb_entry *cached_re, unsigned int ofs) | 50 | struct rb_entry *cached_re, unsigned int ofs) |
54 | { | 51 | { |
55 | struct rb_entry *re; | 52 | struct rb_entry *re; |
@@ -62,22 +59,25 @@ struct rb_entry *f2fs_lookup_rb_tree(struct rb_root *root, | |||
62 | } | 59 | } |
63 | 60 | ||
64 | struct rb_node **f2fs_lookup_rb_tree_for_insert(struct f2fs_sb_info *sbi, | 61 | struct rb_node **f2fs_lookup_rb_tree_for_insert(struct f2fs_sb_info *sbi, |
65 | struct rb_root *root, struct rb_node **parent, | 62 | struct rb_root_cached *root, |
66 | unsigned int ofs) | 63 | struct rb_node **parent, |
64 | unsigned int ofs, bool *leftmost) | ||
67 | { | 65 | { |
68 | struct rb_node **p = &root->rb_node; | 66 | struct rb_node **p = &root->rb_root.rb_node; |
69 | struct rb_entry *re; | 67 | struct rb_entry *re; |
70 | 68 | ||
71 | while (*p) { | 69 | while (*p) { |
72 | *parent = *p; | 70 | *parent = *p; |
73 | re = rb_entry(*parent, struct rb_entry, rb_node); | 71 | re = rb_entry(*parent, struct rb_entry, rb_node); |
74 | 72 | ||
75 | if (ofs < re->ofs) | 73 | if (ofs < re->ofs) { |
76 | p = &(*p)->rb_left; | 74 | p = &(*p)->rb_left; |
77 | else if (ofs >= re->ofs + re->len) | 75 | } else if (ofs >= re->ofs + re->len) { |
78 | p = &(*p)->rb_right; | 76 | p = &(*p)->rb_right; |
79 | else | 77 | *leftmost = false; |
78 | } else { | ||
80 | f2fs_bug_on(sbi, 1); | 79 | f2fs_bug_on(sbi, 1); |
80 | } | ||
81 | } | 81 | } |
82 | 82 | ||
83 | return p; | 83 | return p; |
@@ -92,16 +92,16 @@ struct rb_node **f2fs_lookup_rb_tree_for_insert(struct f2fs_sb_info *sbi, | |||
92 | * in order to simpfy the insertion after. | 92 | * in order to simpfy the insertion after. |
93 | * tree must stay unchanged between lookup and insertion. | 93 | * tree must stay unchanged between lookup and insertion. |
94 | */ | 94 | */ |
95 | struct rb_entry *f2fs_lookup_rb_tree_ret(struct rb_root *root, | 95 | struct rb_entry *f2fs_lookup_rb_tree_ret(struct rb_root_cached *root, |
96 | struct rb_entry *cached_re, | 96 | struct rb_entry *cached_re, |
97 | unsigned int ofs, | 97 | unsigned int ofs, |
98 | struct rb_entry **prev_entry, | 98 | struct rb_entry **prev_entry, |
99 | struct rb_entry **next_entry, | 99 | struct rb_entry **next_entry, |
100 | struct rb_node ***insert_p, | 100 | struct rb_node ***insert_p, |
101 | struct rb_node **insert_parent, | 101 | struct rb_node **insert_parent, |
102 | bool force) | 102 | bool force, bool *leftmost) |
103 | { | 103 | { |
104 | struct rb_node **pnode = &root->rb_node; | 104 | struct rb_node **pnode = &root->rb_root.rb_node; |
105 | struct rb_node *parent = NULL, *tmp_node; | 105 | struct rb_node *parent = NULL, *tmp_node; |
106 | struct rb_entry *re = cached_re; | 106 | struct rb_entry *re = cached_re; |
107 | 107 | ||
@@ -110,7 +110,7 @@ struct rb_entry *f2fs_lookup_rb_tree_ret(struct rb_root *root, | |||
110 | *prev_entry = NULL; | 110 | *prev_entry = NULL; |
111 | *next_entry = NULL; | 111 | *next_entry = NULL; |
112 | 112 | ||
113 | if (RB_EMPTY_ROOT(root)) | 113 | if (RB_EMPTY_ROOT(&root->rb_root)) |
114 | return NULL; | 114 | return NULL; |
115 | 115 | ||
116 | if (re) { | 116 | if (re) { |
@@ -118,16 +118,22 @@ struct rb_entry *f2fs_lookup_rb_tree_ret(struct rb_root *root, | |||
118 | goto lookup_neighbors; | 118 | goto lookup_neighbors; |
119 | } | 119 | } |
120 | 120 | ||
121 | if (leftmost) | ||
122 | *leftmost = true; | ||
123 | |||
121 | while (*pnode) { | 124 | while (*pnode) { |
122 | parent = *pnode; | 125 | parent = *pnode; |
123 | re = rb_entry(*pnode, struct rb_entry, rb_node); | 126 | re = rb_entry(*pnode, struct rb_entry, rb_node); |
124 | 127 | ||
125 | if (ofs < re->ofs) | 128 | if (ofs < re->ofs) { |
126 | pnode = &(*pnode)->rb_left; | 129 | pnode = &(*pnode)->rb_left; |
127 | else if (ofs >= re->ofs + re->len) | 130 | } else if (ofs >= re->ofs + re->len) { |
128 | pnode = &(*pnode)->rb_right; | 131 | pnode = &(*pnode)->rb_right; |
129 | else | 132 | if (leftmost) |
133 | *leftmost = false; | ||
134 | } else { | ||
130 | goto lookup_neighbors; | 135 | goto lookup_neighbors; |
136 | } | ||
131 | } | 137 | } |
132 | 138 | ||
133 | *insert_p = pnode; | 139 | *insert_p = pnode; |
@@ -160,10 +166,10 @@ lookup_neighbors: | |||
160 | } | 166 | } |
161 | 167 | ||
162 | bool f2fs_check_rb_tree_consistence(struct f2fs_sb_info *sbi, | 168 | bool f2fs_check_rb_tree_consistence(struct f2fs_sb_info *sbi, |
163 | struct rb_root *root) | 169 | struct rb_root_cached *root) |
164 | { | 170 | { |
165 | #ifdef CONFIG_F2FS_CHECK_FS | 171 | #ifdef CONFIG_F2FS_CHECK_FS |
166 | struct rb_node *cur = rb_first(root), *next; | 172 | struct rb_node *cur = rb_first_cached(root), *next; |
167 | struct rb_entry *cur_re, *next_re; | 173 | struct rb_entry *cur_re, *next_re; |
168 | 174 | ||
169 | if (!cur) | 175 | if (!cur) |
@@ -196,7 +202,8 @@ static struct kmem_cache *extent_node_slab; | |||
196 | 202 | ||
197 | static struct extent_node *__attach_extent_node(struct f2fs_sb_info *sbi, | 203 | static struct extent_node *__attach_extent_node(struct f2fs_sb_info *sbi, |
198 | struct extent_tree *et, struct extent_info *ei, | 204 | struct extent_tree *et, struct extent_info *ei, |
199 | struct rb_node *parent, struct rb_node **p) | 205 | struct rb_node *parent, struct rb_node **p, |
206 | bool leftmost) | ||
200 | { | 207 | { |
201 | struct extent_node *en; | 208 | struct extent_node *en; |
202 | 209 | ||
@@ -209,7 +216,7 @@ static struct extent_node *__attach_extent_node(struct f2fs_sb_info *sbi, | |||
209 | en->et = et; | 216 | en->et = et; |
210 | 217 | ||
211 | rb_link_node(&en->rb_node, parent, p); | 218 | rb_link_node(&en->rb_node, parent, p); |
212 | rb_insert_color(&en->rb_node, &et->root); | 219 | rb_insert_color_cached(&en->rb_node, &et->root, leftmost); |
213 | atomic_inc(&et->node_cnt); | 220 | atomic_inc(&et->node_cnt); |
214 | atomic_inc(&sbi->total_ext_node); | 221 | atomic_inc(&sbi->total_ext_node); |
215 | return en; | 222 | return en; |
@@ -218,7 +225,7 @@ static struct extent_node *__attach_extent_node(struct f2fs_sb_info *sbi, | |||
218 | static void __detach_extent_node(struct f2fs_sb_info *sbi, | 225 | static void __detach_extent_node(struct f2fs_sb_info *sbi, |
219 | struct extent_tree *et, struct extent_node *en) | 226 | struct extent_tree *et, struct extent_node *en) |
220 | { | 227 | { |
221 | rb_erase(&en->rb_node, &et->root); | 228 | rb_erase_cached(&en->rb_node, &et->root); |
222 | atomic_dec(&et->node_cnt); | 229 | atomic_dec(&et->node_cnt); |
223 | atomic_dec(&sbi->total_ext_node); | 230 | atomic_dec(&sbi->total_ext_node); |
224 | 231 | ||
@@ -257,7 +264,7 @@ static struct extent_tree *__grab_extent_tree(struct inode *inode) | |||
257 | f2fs_radix_tree_insert(&sbi->extent_tree_root, ino, et); | 264 | f2fs_radix_tree_insert(&sbi->extent_tree_root, ino, et); |
258 | memset(et, 0, sizeof(struct extent_tree)); | 265 | memset(et, 0, sizeof(struct extent_tree)); |
259 | et->ino = ino; | 266 | et->ino = ino; |
260 | et->root = RB_ROOT; | 267 | et->root = RB_ROOT_CACHED; |
261 | et->cached_en = NULL; | 268 | et->cached_en = NULL; |
262 | rwlock_init(&et->lock); | 269 | rwlock_init(&et->lock); |
263 | INIT_LIST_HEAD(&et->list); | 270 | INIT_LIST_HEAD(&et->list); |
@@ -278,10 +285,10 @@ static struct extent_tree *__grab_extent_tree(struct inode *inode) | |||
278 | static struct extent_node *__init_extent_tree(struct f2fs_sb_info *sbi, | 285 | static struct extent_node *__init_extent_tree(struct f2fs_sb_info *sbi, |
279 | struct extent_tree *et, struct extent_info *ei) | 286 | struct extent_tree *et, struct extent_info *ei) |
280 | { | 287 | { |
281 | struct rb_node **p = &et->root.rb_node; | 288 | struct rb_node **p = &et->root.rb_root.rb_node; |
282 | struct extent_node *en; | 289 | struct extent_node *en; |
283 | 290 | ||
284 | en = __attach_extent_node(sbi, et, ei, NULL, p); | 291 | en = __attach_extent_node(sbi, et, ei, NULL, p, true); |
285 | if (!en) | 292 | if (!en) |
286 | return NULL; | 293 | return NULL; |
287 | 294 | ||
@@ -297,7 +304,7 @@ static unsigned int __free_extent_tree(struct f2fs_sb_info *sbi, | |||
297 | struct extent_node *en; | 304 | struct extent_node *en; |
298 | unsigned int count = atomic_read(&et->node_cnt); | 305 | unsigned int count = atomic_read(&et->node_cnt); |
299 | 306 | ||
300 | node = rb_first(&et->root); | 307 | node = rb_first_cached(&et->root); |
301 | while (node) { | 308 | while (node) { |
302 | next = rb_next(node); | 309 | next = rb_next(node); |
303 | en = rb_entry(node, struct extent_node, rb_node); | 310 | en = rb_entry(node, struct extent_node, rb_node); |
@@ -308,14 +315,13 @@ static unsigned int __free_extent_tree(struct f2fs_sb_info *sbi, | |||
308 | return count - atomic_read(&et->node_cnt); | 315 | return count - atomic_read(&et->node_cnt); |
309 | } | 316 | } |
310 | 317 | ||
311 | static void __drop_largest_extent(struct inode *inode, | 318 | static void __drop_largest_extent(struct extent_tree *et, |
312 | pgoff_t fofs, unsigned int len) | 319 | pgoff_t fofs, unsigned int len) |
313 | { | 320 | { |
314 | struct extent_info *largest = &F2FS_I(inode)->extent_tree->largest; | 321 | if (fofs < et->largest.fofs + et->largest.len && |
315 | 322 | fofs + len > et->largest.fofs) { | |
316 | if (fofs < largest->fofs + largest->len && fofs + len > largest->fofs) { | 323 | et->largest.len = 0; |
317 | largest->len = 0; | 324 | et->largest_updated = true; |
318 | f2fs_mark_inode_dirty_sync(inode, true); | ||
319 | } | 325 | } |
320 | } | 326 | } |
321 | 327 | ||
@@ -416,12 +422,11 @@ out: | |||
416 | return ret; | 422 | return ret; |
417 | } | 423 | } |
418 | 424 | ||
419 | static struct extent_node *__try_merge_extent_node(struct inode *inode, | 425 | static struct extent_node *__try_merge_extent_node(struct f2fs_sb_info *sbi, |
420 | struct extent_tree *et, struct extent_info *ei, | 426 | struct extent_tree *et, struct extent_info *ei, |
421 | struct extent_node *prev_ex, | 427 | struct extent_node *prev_ex, |
422 | struct extent_node *next_ex) | 428 | struct extent_node *next_ex) |
423 | { | 429 | { |
424 | struct f2fs_sb_info *sbi = F2FS_I_SB(inode); | ||
425 | struct extent_node *en = NULL; | 430 | struct extent_node *en = NULL; |
426 | 431 | ||
427 | if (prev_ex && __is_back_mergeable(ei, &prev_ex->ei)) { | 432 | if (prev_ex && __is_back_mergeable(ei, &prev_ex->ei)) { |
@@ -443,7 +448,7 @@ static struct extent_node *__try_merge_extent_node(struct inode *inode, | |||
443 | if (!en) | 448 | if (!en) |
444 | return NULL; | 449 | return NULL; |
445 | 450 | ||
446 | __try_update_largest_extent(inode, et, en); | 451 | __try_update_largest_extent(et, en); |
447 | 452 | ||
448 | spin_lock(&sbi->extent_lock); | 453 | spin_lock(&sbi->extent_lock); |
449 | if (!list_empty(&en->list)) { | 454 | if (!list_empty(&en->list)) { |
@@ -454,12 +459,12 @@ static struct extent_node *__try_merge_extent_node(struct inode *inode, | |||
454 | return en; | 459 | return en; |
455 | } | 460 | } |
456 | 461 | ||
457 | static struct extent_node *__insert_extent_tree(struct inode *inode, | 462 | static struct extent_node *__insert_extent_tree(struct f2fs_sb_info *sbi, |
458 | struct extent_tree *et, struct extent_info *ei, | 463 | struct extent_tree *et, struct extent_info *ei, |
459 | struct rb_node **insert_p, | 464 | struct rb_node **insert_p, |
460 | struct rb_node *insert_parent) | 465 | struct rb_node *insert_parent, |
466 | bool leftmost) | ||
461 | { | 467 | { |
462 | struct f2fs_sb_info *sbi = F2FS_I_SB(inode); | ||
463 | struct rb_node **p; | 468 | struct rb_node **p; |
464 | struct rb_node *parent = NULL; | 469 | struct rb_node *parent = NULL; |
465 | struct extent_node *en = NULL; | 470 | struct extent_node *en = NULL; |
@@ -470,13 +475,16 @@ static struct extent_node *__insert_extent_tree(struct inode *inode, | |||
470 | goto do_insert; | 475 | goto do_insert; |
471 | } | 476 | } |
472 | 477 | ||
473 | p = f2fs_lookup_rb_tree_for_insert(sbi, &et->root, &parent, ei->fofs); | 478 | leftmost = true; |
479 | |||
480 | p = f2fs_lookup_rb_tree_for_insert(sbi, &et->root, &parent, | ||
481 | ei->fofs, &leftmost); | ||
474 | do_insert: | 482 | do_insert: |
475 | en = __attach_extent_node(sbi, et, ei, parent, p); | 483 | en = __attach_extent_node(sbi, et, ei, parent, p, leftmost); |
476 | if (!en) | 484 | if (!en) |
477 | return NULL; | 485 | return NULL; |
478 | 486 | ||
479 | __try_update_largest_extent(inode, et, en); | 487 | __try_update_largest_extent(et, en); |
480 | 488 | ||
481 | /* update in global extent list */ | 489 | /* update in global extent list */ |
482 | spin_lock(&sbi->extent_lock); | 490 | spin_lock(&sbi->extent_lock); |
@@ -497,6 +505,8 @@ static void f2fs_update_extent_tree_range(struct inode *inode, | |||
497 | struct rb_node **insert_p = NULL, *insert_parent = NULL; | 505 | struct rb_node **insert_p = NULL, *insert_parent = NULL; |
498 | unsigned int end = fofs + len; | 506 | unsigned int end = fofs + len; |
499 | unsigned int pos = (unsigned int)fofs; | 507 | unsigned int pos = (unsigned int)fofs; |
508 | bool updated = false; | ||
509 | bool leftmost; | ||
500 | 510 | ||
501 | if (!et) | 511 | if (!et) |
502 | return; | 512 | return; |
@@ -517,14 +527,15 @@ static void f2fs_update_extent_tree_range(struct inode *inode, | |||
517 | * drop largest extent before lookup, in case it's already | 527 | * drop largest extent before lookup, in case it's already |
518 | * been shrunk from extent tree | 528 | * been shrunk from extent tree |
519 | */ | 529 | */ |
520 | __drop_largest_extent(inode, fofs, len); | 530 | __drop_largest_extent(et, fofs, len); |
521 | 531 | ||
522 | /* 1. lookup first extent node in range [fofs, fofs + len - 1] */ | 532 | /* 1. lookup first extent node in range [fofs, fofs + len - 1] */ |
523 | en = (struct extent_node *)f2fs_lookup_rb_tree_ret(&et->root, | 533 | en = (struct extent_node *)f2fs_lookup_rb_tree_ret(&et->root, |
524 | (struct rb_entry *)et->cached_en, fofs, | 534 | (struct rb_entry *)et->cached_en, fofs, |
525 | (struct rb_entry **)&prev_en, | 535 | (struct rb_entry **)&prev_en, |
526 | (struct rb_entry **)&next_en, | 536 | (struct rb_entry **)&next_en, |
527 | &insert_p, &insert_parent, false); | 537 | &insert_p, &insert_parent, false, |
538 | &leftmost); | ||
528 | if (!en) | 539 | if (!en) |
529 | en = next_en; | 540 | en = next_en; |
530 | 541 | ||
@@ -550,8 +561,8 @@ static void f2fs_update_extent_tree_range(struct inode *inode, | |||
550 | set_extent_info(&ei, end, | 561 | set_extent_info(&ei, end, |
551 | end - dei.fofs + dei.blk, | 562 | end - dei.fofs + dei.blk, |
552 | org_end - end); | 563 | org_end - end); |
553 | en1 = __insert_extent_tree(inode, et, &ei, | 564 | en1 = __insert_extent_tree(sbi, et, &ei, |
554 | NULL, NULL); | 565 | NULL, NULL, true); |
555 | next_en = en1; | 566 | next_en = en1; |
556 | } else { | 567 | } else { |
557 | en->ei.fofs = end; | 568 | en->ei.fofs = end; |
@@ -570,7 +581,7 @@ static void f2fs_update_extent_tree_range(struct inode *inode, | |||
570 | } | 581 | } |
571 | 582 | ||
572 | if (parts) | 583 | if (parts) |
573 | __try_update_largest_extent(inode, et, en); | 584 | __try_update_largest_extent(et, en); |
574 | else | 585 | else |
575 | __release_extent_node(sbi, et, en); | 586 | __release_extent_node(sbi, et, en); |
576 | 587 | ||
@@ -590,15 +601,16 @@ static void f2fs_update_extent_tree_range(struct inode *inode, | |||
590 | if (blkaddr) { | 601 | if (blkaddr) { |
591 | 602 | ||
592 | set_extent_info(&ei, fofs, blkaddr, len); | 603 | set_extent_info(&ei, fofs, blkaddr, len); |
593 | if (!__try_merge_extent_node(inode, et, &ei, prev_en, next_en)) | 604 | if (!__try_merge_extent_node(sbi, et, &ei, prev_en, next_en)) |
594 | __insert_extent_tree(inode, et, &ei, | 605 | __insert_extent_tree(sbi, et, &ei, |
595 | insert_p, insert_parent); | 606 | insert_p, insert_parent, leftmost); |
596 | 607 | ||
597 | /* give up extent_cache, if split and small updates happen */ | 608 | /* give up extent_cache, if split and small updates happen */ |
598 | if (dei.len >= 1 && | 609 | if (dei.len >= 1 && |
599 | prev.len < F2FS_MIN_EXTENT_LEN && | 610 | prev.len < F2FS_MIN_EXTENT_LEN && |
600 | et->largest.len < F2FS_MIN_EXTENT_LEN) { | 611 | et->largest.len < F2FS_MIN_EXTENT_LEN) { |
601 | __drop_largest_extent(inode, 0, UINT_MAX); | 612 | et->largest.len = 0; |
613 | et->largest_updated = true; | ||
602 | set_inode_flag(inode, FI_NO_EXTENT); | 614 | set_inode_flag(inode, FI_NO_EXTENT); |
603 | } | 615 | } |
604 | } | 616 | } |
@@ -606,7 +618,15 @@ static void f2fs_update_extent_tree_range(struct inode *inode, | |||
606 | if (is_inode_flag_set(inode, FI_NO_EXTENT)) | 618 | if (is_inode_flag_set(inode, FI_NO_EXTENT)) |
607 | __free_extent_tree(sbi, et); | 619 | __free_extent_tree(sbi, et); |
608 | 620 | ||
621 | if (et->largest_updated) { | ||
622 | et->largest_updated = false; | ||
623 | updated = true; | ||
624 | } | ||
625 | |||
609 | write_unlock(&et->lock); | 626 | write_unlock(&et->lock); |
627 | |||
628 | if (updated) | ||
629 | f2fs_mark_inode_dirty_sync(inode, true); | ||
610 | } | 630 | } |
611 | 631 | ||
612 | unsigned int f2fs_shrink_extent_tree(struct f2fs_sb_info *sbi, int nr_shrink) | 632 | unsigned int f2fs_shrink_extent_tree(struct f2fs_sb_info *sbi, int nr_shrink) |
@@ -705,6 +725,7 @@ void f2fs_drop_extent_tree(struct inode *inode) | |||
705 | { | 725 | { |
706 | struct f2fs_sb_info *sbi = F2FS_I_SB(inode); | 726 | struct f2fs_sb_info *sbi = F2FS_I_SB(inode); |
707 | struct extent_tree *et = F2FS_I(inode)->extent_tree; | 727 | struct extent_tree *et = F2FS_I(inode)->extent_tree; |
728 | bool updated = false; | ||
708 | 729 | ||
709 | if (!f2fs_may_extent_tree(inode)) | 730 | if (!f2fs_may_extent_tree(inode)) |
710 | return; | 731 | return; |
@@ -713,8 +734,13 @@ void f2fs_drop_extent_tree(struct inode *inode) | |||
713 | 734 | ||
714 | write_lock(&et->lock); | 735 | write_lock(&et->lock); |
715 | __free_extent_tree(sbi, et); | 736 | __free_extent_tree(sbi, et); |
716 | __drop_largest_extent(inode, 0, UINT_MAX); | 737 | if (et->largest.len) { |
738 | et->largest.len = 0; | ||
739 | updated = true; | ||
740 | } | ||
717 | write_unlock(&et->lock); | 741 | write_unlock(&et->lock); |
742 | if (updated) | ||
743 | f2fs_mark_inode_dirty_sync(inode, true); | ||
718 | } | 744 | } |
719 | 745 | ||
720 | void f2fs_destroy_extent_tree(struct inode *inode) | 746 | void f2fs_destroy_extent_tree(struct inode *inode) |
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index abf925664d9c..56204a8f8a12 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h | |||
@@ -1,16 +1,14 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
1 | /* | 2 | /* |
2 | * fs/f2fs/f2fs.h | 3 | * fs/f2fs/f2fs.h |
3 | * | 4 | * |
4 | * Copyright (c) 2012 Samsung Electronics Co., Ltd. | 5 | * Copyright (c) 2012 Samsung Electronics Co., Ltd. |
5 | * http://www.samsung.com/ | 6 | * http://www.samsung.com/ |
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | */ | 7 | */ |
11 | #ifndef _LINUX_F2FS_H | 8 | #ifndef _LINUX_F2FS_H |
12 | #define _LINUX_F2FS_H | 9 | #define _LINUX_F2FS_H |
13 | 10 | ||
11 | #include <linux/uio.h> | ||
14 | #include <linux/types.h> | 12 | #include <linux/types.h> |
15 | #include <linux/page-flags.h> | 13 | #include <linux/page-flags.h> |
16 | #include <linux/buffer_head.h> | 14 | #include <linux/buffer_head.h> |
@@ -53,9 +51,10 @@ enum { | |||
53 | FAULT_DIR_DEPTH, | 51 | FAULT_DIR_DEPTH, |
54 | FAULT_EVICT_INODE, | 52 | FAULT_EVICT_INODE, |
55 | FAULT_TRUNCATE, | 53 | FAULT_TRUNCATE, |
56 | FAULT_IO, | 54 | FAULT_READ_IO, |
57 | FAULT_CHECKPOINT, | 55 | FAULT_CHECKPOINT, |
58 | FAULT_DISCARD, | 56 | FAULT_DISCARD, |
57 | FAULT_WRITE_IO, | ||
59 | FAULT_MAX, | 58 | FAULT_MAX, |
60 | }; | 59 | }; |
61 | 60 | ||
@@ -100,6 +99,7 @@ extern char *f2fs_fault_name[FAULT_MAX]; | |||
100 | #define F2FS_MOUNT_QUOTA 0x00400000 | 99 | #define F2FS_MOUNT_QUOTA 0x00400000 |
101 | #define F2FS_MOUNT_INLINE_XATTR_SIZE 0x00800000 | 100 | #define F2FS_MOUNT_INLINE_XATTR_SIZE 0x00800000 |
102 | #define F2FS_MOUNT_RESERVE_ROOT 0x01000000 | 101 | #define F2FS_MOUNT_RESERVE_ROOT 0x01000000 |
102 | #define F2FS_MOUNT_DISABLE_CHECKPOINT 0x02000000 | ||
103 | 103 | ||
104 | #define F2FS_OPTION(sbi) ((sbi)->mount_opt) | 104 | #define F2FS_OPTION(sbi) ((sbi)->mount_opt) |
105 | #define clear_opt(sbi, option) (F2FS_OPTION(sbi).opt &= ~F2FS_MOUNT_##option) | 105 | #define clear_opt(sbi, option) (F2FS_OPTION(sbi).opt &= ~F2FS_MOUNT_##option) |
@@ -150,6 +150,7 @@ struct f2fs_mount_info { | |||
150 | #define F2FS_FEATURE_INODE_CRTIME 0x0100 | 150 | #define F2FS_FEATURE_INODE_CRTIME 0x0100 |
151 | #define F2FS_FEATURE_LOST_FOUND 0x0200 | 151 | #define F2FS_FEATURE_LOST_FOUND 0x0200 |
152 | #define F2FS_FEATURE_VERITY 0x0400 /* reserved */ | 152 | #define F2FS_FEATURE_VERITY 0x0400 /* reserved */ |
153 | #define F2FS_FEATURE_SB_CHKSUM 0x0800 | ||
153 | 154 | ||
154 | #define F2FS_HAS_FEATURE(sb, mask) \ | 155 | #define F2FS_HAS_FEATURE(sb, mask) \ |
155 | ((F2FS_SB(sb)->raw_super->feature & cpu_to_le32(mask)) != 0) | 156 | ((F2FS_SB(sb)->raw_super->feature & cpu_to_le32(mask)) != 0) |
@@ -178,6 +179,7 @@ enum { | |||
178 | #define CP_RECOVERY 0x00000008 | 179 | #define CP_RECOVERY 0x00000008 |
179 | #define CP_DISCARD 0x00000010 | 180 | #define CP_DISCARD 0x00000010 |
180 | #define CP_TRIMMED 0x00000020 | 181 | #define CP_TRIMMED 0x00000020 |
182 | #define CP_PAUSE 0x00000040 | ||
181 | 183 | ||
182 | #define MAX_DISCARD_BLOCKS(sbi) BLKS_PER_SEC(sbi) | 184 | #define MAX_DISCARD_BLOCKS(sbi) BLKS_PER_SEC(sbi) |
183 | #define DEF_MAX_DISCARD_REQUEST 8 /* issue 8 discards per round */ | 185 | #define DEF_MAX_DISCARD_REQUEST 8 /* issue 8 discards per round */ |
@@ -187,6 +189,7 @@ enum { | |||
187 | #define DEF_DISCARD_URGENT_UTIL 80 /* do more discard over 80% */ | 189 | #define DEF_DISCARD_URGENT_UTIL 80 /* do more discard over 80% */ |
188 | #define DEF_CP_INTERVAL 60 /* 60 secs */ | 190 | #define DEF_CP_INTERVAL 60 /* 60 secs */ |
189 | #define DEF_IDLE_INTERVAL 5 /* 5 secs */ | 191 | #define DEF_IDLE_INTERVAL 5 /* 5 secs */ |
192 | #define DEF_DISABLE_INTERVAL 5 /* 5 secs */ | ||
190 | 193 | ||
191 | struct cp_control { | 194 | struct cp_control { |
192 | int reason; | 195 | int reason; |
@@ -203,6 +206,7 @@ enum { | |||
203 | META_NAT, | 206 | META_NAT, |
204 | META_SIT, | 207 | META_SIT, |
205 | META_SSA, | 208 | META_SSA, |
209 | META_MAX, | ||
206 | META_POR, | 210 | META_POR, |
207 | DATA_GENERIC, | 211 | DATA_GENERIC, |
208 | META_GENERIC, | 212 | META_GENERIC, |
@@ -324,7 +328,7 @@ struct discard_cmd_control { | |||
324 | atomic_t issued_discard; /* # of issued discard */ | 328 | atomic_t issued_discard; /* # of issued discard */ |
325 | atomic_t issing_discard; /* # of issing discard */ | 329 | atomic_t issing_discard; /* # of issing discard */ |
326 | atomic_t discard_cmd_cnt; /* # of cached cmd count */ | 330 | atomic_t discard_cmd_cnt; /* # of cached cmd count */ |
327 | struct rb_root root; /* root of discard rb-tree */ | 331 | struct rb_root_cached root; /* root of discard rb-tree */ |
328 | bool rbtree_check; /* config for consistence check */ | 332 | bool rbtree_check; /* config for consistence check */ |
329 | }; | 333 | }; |
330 | 334 | ||
@@ -527,6 +531,9 @@ enum { | |||
527 | 531 | ||
528 | #define DEFAULT_RETRY_IO_COUNT 8 /* maximum retry read IO count */ | 532 | #define DEFAULT_RETRY_IO_COUNT 8 /* maximum retry read IO count */ |
529 | 533 | ||
534 | /* maximum retry quota flush count */ | ||
535 | #define DEFAULT_RETRY_QUOTA_FLUSH_COUNT 8 | ||
536 | |||
530 | #define F2FS_LINK_MAX 0xffffffff /* maximum link count per file */ | 537 | #define F2FS_LINK_MAX 0xffffffff /* maximum link count per file */ |
531 | 538 | ||
532 | #define MAX_DIR_RA_PAGES 4 /* maximum ra pages of dir */ | 539 | #define MAX_DIR_RA_PAGES 4 /* maximum ra pages of dir */ |
@@ -566,12 +573,13 @@ struct extent_node { | |||
566 | 573 | ||
567 | struct extent_tree { | 574 | struct extent_tree { |
568 | nid_t ino; /* inode number */ | 575 | nid_t ino; /* inode number */ |
569 | struct rb_root root; /* root of extent info rb-tree */ | 576 | struct rb_root_cached root; /* root of extent info rb-tree */ |
570 | struct extent_node *cached_en; /* recently accessed extent node */ | 577 | struct extent_node *cached_en; /* recently accessed extent node */ |
571 | struct extent_info largest; /* largested extent info */ | 578 | struct extent_info largest; /* largested extent info */ |
572 | struct list_head list; /* to be used by sbi->zombie_list */ | 579 | struct list_head list; /* to be used by sbi->zombie_list */ |
573 | rwlock_t lock; /* protect extent info rb-tree */ | 580 | rwlock_t lock; /* protect extent info rb-tree */ |
574 | atomic_t node_cnt; /* # of extent node in rb-tree*/ | 581 | atomic_t node_cnt; /* # of extent node in rb-tree*/ |
582 | bool largest_updated; /* largest extent updated */ | ||
575 | }; | 583 | }; |
576 | 584 | ||
577 | /* | 585 | /* |
@@ -600,6 +608,7 @@ enum { | |||
600 | F2FS_GET_BLOCK_DEFAULT, | 608 | F2FS_GET_BLOCK_DEFAULT, |
601 | F2FS_GET_BLOCK_FIEMAP, | 609 | F2FS_GET_BLOCK_FIEMAP, |
602 | F2FS_GET_BLOCK_BMAP, | 610 | F2FS_GET_BLOCK_BMAP, |
611 | F2FS_GET_BLOCK_DIO, | ||
603 | F2FS_GET_BLOCK_PRE_DIO, | 612 | F2FS_GET_BLOCK_PRE_DIO, |
604 | F2FS_GET_BLOCK_PRE_AIO, | 613 | F2FS_GET_BLOCK_PRE_AIO, |
605 | F2FS_GET_BLOCK_PRECACHE, | 614 | F2FS_GET_BLOCK_PRECACHE, |
@@ -754,12 +763,12 @@ static inline bool __is_front_mergeable(struct extent_info *cur, | |||
754 | } | 763 | } |
755 | 764 | ||
756 | extern void f2fs_mark_inode_dirty_sync(struct inode *inode, bool sync); | 765 | extern void f2fs_mark_inode_dirty_sync(struct inode *inode, bool sync); |
757 | static inline void __try_update_largest_extent(struct inode *inode, | 766 | static inline void __try_update_largest_extent(struct extent_tree *et, |
758 | struct extent_tree *et, struct extent_node *en) | 767 | struct extent_node *en) |
759 | { | 768 | { |
760 | if (en->ei.len > et->largest.len) { | 769 | if (en->ei.len > et->largest.len) { |
761 | et->largest = en->ei; | 770 | et->largest = en->ei; |
762 | f2fs_mark_inode_dirty_sync(inode, true); | 771 | et->largest_updated = true; |
763 | } | 772 | } |
764 | } | 773 | } |
765 | 774 | ||
@@ -944,6 +953,9 @@ enum count_type { | |||
944 | F2FS_DIRTY_IMETA, | 953 | F2FS_DIRTY_IMETA, |
945 | F2FS_WB_CP_DATA, | 954 | F2FS_WB_CP_DATA, |
946 | F2FS_WB_DATA, | 955 | F2FS_WB_DATA, |
956 | F2FS_RD_DATA, | ||
957 | F2FS_RD_NODE, | ||
958 | F2FS_RD_META, | ||
947 | NR_COUNT_TYPE, | 959 | NR_COUNT_TYPE, |
948 | }; | 960 | }; |
949 | 961 | ||
@@ -1088,11 +1100,19 @@ enum { | |||
1088 | SBI_NEED_SB_WRITE, /* need to recover superblock */ | 1100 | SBI_NEED_SB_WRITE, /* need to recover superblock */ |
1089 | SBI_NEED_CP, /* need to checkpoint */ | 1101 | SBI_NEED_CP, /* need to checkpoint */ |
1090 | SBI_IS_SHUTDOWN, /* shutdown by ioctl */ | 1102 | SBI_IS_SHUTDOWN, /* shutdown by ioctl */ |
1103 | SBI_IS_RECOVERED, /* recovered orphan/data */ | ||
1104 | SBI_CP_DISABLED, /* CP was disabled last mount */ | ||
1105 | SBI_QUOTA_NEED_FLUSH, /* need to flush quota info in CP */ | ||
1106 | SBI_QUOTA_SKIP_FLUSH, /* skip flushing quota in current CP */ | ||
1107 | SBI_QUOTA_NEED_REPAIR, /* quota file may be corrupted */ | ||
1091 | }; | 1108 | }; |
1092 | 1109 | ||
1093 | enum { | 1110 | enum { |
1094 | CP_TIME, | 1111 | CP_TIME, |
1095 | REQ_TIME, | 1112 | REQ_TIME, |
1113 | DISCARD_TIME, | ||
1114 | GC_TIME, | ||
1115 | DISABLE_TIME, | ||
1096 | MAX_TIME, | 1116 | MAX_TIME, |
1097 | }; | 1117 | }; |
1098 | 1118 | ||
@@ -1209,7 +1229,6 @@ struct f2fs_sb_info { | |||
1209 | unsigned int total_valid_node_count; /* valid node block count */ | 1229 | unsigned int total_valid_node_count; /* valid node block count */ |
1210 | loff_t max_file_blocks; /* max block index of file */ | 1230 | loff_t max_file_blocks; /* max block index of file */ |
1211 | int dir_level; /* directory level */ | 1231 | int dir_level; /* directory level */ |
1212 | unsigned int trigger_ssr_threshold; /* threshold to trigger ssr */ | ||
1213 | int readdir_ra; /* readahead inode in readdir */ | 1232 | int readdir_ra; /* readahead inode in readdir */ |
1214 | 1233 | ||
1215 | block_t user_block_count; /* # of user blocks */ | 1234 | block_t user_block_count; /* # of user blocks */ |
@@ -1219,6 +1238,9 @@ struct f2fs_sb_info { | |||
1219 | block_t reserved_blocks; /* configurable reserved blocks */ | 1238 | block_t reserved_blocks; /* configurable reserved blocks */ |
1220 | block_t current_reserved_blocks; /* current reserved blocks */ | 1239 | block_t current_reserved_blocks; /* current reserved blocks */ |
1221 | 1240 | ||
1241 | /* Additional tracking for no checkpoint mode */ | ||
1242 | block_t unusable_block_count; /* # of blocks saved by last cp */ | ||
1243 | |||
1222 | unsigned int nquota_files; /* # of quota sysfile */ | 1244 | unsigned int nquota_files; /* # of quota sysfile */ |
1223 | 1245 | ||
1224 | u32 s_next_generation; /* for NFS support */ | 1246 | u32 s_next_generation; /* for NFS support */ |
@@ -1257,6 +1279,7 @@ struct f2fs_sb_info { | |||
1257 | */ | 1279 | */ |
1258 | #ifdef CONFIG_F2FS_STAT_FS | 1280 | #ifdef CONFIG_F2FS_STAT_FS |
1259 | struct f2fs_stat_info *stat_info; /* FS status information */ | 1281 | struct f2fs_stat_info *stat_info; /* FS status information */ |
1282 | atomic_t meta_count[META_MAX]; /* # of meta blocks */ | ||
1260 | unsigned int segment_count[2]; /* # of allocated segments */ | 1283 | unsigned int segment_count[2]; /* # of allocated segments */ |
1261 | unsigned int block_count[2]; /* # of allocated blocks */ | 1284 | unsigned int block_count[2]; /* # of allocated blocks */ |
1262 | atomic_t inplace_count; /* # of inplace update */ | 1285 | atomic_t inplace_count; /* # of inplace update */ |
@@ -1272,6 +1295,8 @@ struct f2fs_sb_info { | |||
1272 | atomic_t max_aw_cnt; /* max # of atomic writes */ | 1295 | atomic_t max_aw_cnt; /* max # of atomic writes */ |
1273 | atomic_t max_vw_cnt; /* max # of volatile writes */ | 1296 | atomic_t max_vw_cnt; /* max # of volatile writes */ |
1274 | int bg_gc; /* background gc calls */ | 1297 | int bg_gc; /* background gc calls */ |
1298 | unsigned int io_skip_bggc; /* skip background gc for in-flight IO */ | ||
1299 | unsigned int other_skip_bggc; /* skip background gc for other reasons */ | ||
1275 | unsigned int ndirty_inode[NR_INODE_TYPE]; /* # of dirty inodes */ | 1300 | unsigned int ndirty_inode[NR_INODE_TYPE]; /* # of dirty inodes */ |
1276 | #endif | 1301 | #endif |
1277 | spinlock_t stat_lock; /* lock for stat operations */ | 1302 | spinlock_t stat_lock; /* lock for stat operations */ |
@@ -1306,9 +1331,9 @@ struct f2fs_sb_info { | |||
1306 | }; | 1331 | }; |
1307 | 1332 | ||
1308 | #ifdef CONFIG_F2FS_FAULT_INJECTION | 1333 | #ifdef CONFIG_F2FS_FAULT_INJECTION |
1309 | #define f2fs_show_injection_info(type) \ | 1334 | #define f2fs_show_injection_info(type) \ |
1310 | printk("%sF2FS-fs : inject %s in %s of %pF\n", \ | 1335 | printk_ratelimited("%sF2FS-fs : inject %s in %s of %pF\n", \ |
1311 | KERN_INFO, f2fs_fault_name[type], \ | 1336 | KERN_INFO, f2fs_fault_name[type], \ |
1312 | __func__, __builtin_return_address(0)) | 1337 | __func__, __builtin_return_address(0)) |
1313 | static inline bool time_to_inject(struct f2fs_sb_info *sbi, int type) | 1338 | static inline bool time_to_inject(struct f2fs_sb_info *sbi, int type) |
1314 | { | 1339 | { |
@@ -1344,7 +1369,15 @@ static inline bool time_to_inject(struct f2fs_sb_info *sbi, int type) | |||
1344 | 1369 | ||
1345 | static inline void f2fs_update_time(struct f2fs_sb_info *sbi, int type) | 1370 | static inline void f2fs_update_time(struct f2fs_sb_info *sbi, int type) |
1346 | { | 1371 | { |
1347 | sbi->last_time[type] = jiffies; | 1372 | unsigned long now = jiffies; |
1373 | |||
1374 | sbi->last_time[type] = now; | ||
1375 | |||
1376 | /* DISCARD_TIME and GC_TIME are based on REQ_TIME */ | ||
1377 | if (type == REQ_TIME) { | ||
1378 | sbi->last_time[DISCARD_TIME] = now; | ||
1379 | sbi->last_time[GC_TIME] = now; | ||
1380 | } | ||
1348 | } | 1381 | } |
1349 | 1382 | ||
1350 | static inline bool f2fs_time_over(struct f2fs_sb_info *sbi, int type) | 1383 | static inline bool f2fs_time_over(struct f2fs_sb_info *sbi, int type) |
@@ -1354,16 +1387,18 @@ static inline bool f2fs_time_over(struct f2fs_sb_info *sbi, int type) | |||
1354 | return time_after(jiffies, sbi->last_time[type] + interval); | 1387 | return time_after(jiffies, sbi->last_time[type] + interval); |
1355 | } | 1388 | } |
1356 | 1389 | ||
1357 | static inline bool is_idle(struct f2fs_sb_info *sbi) | 1390 | static inline unsigned int f2fs_time_to_wait(struct f2fs_sb_info *sbi, |
1391 | int type) | ||
1358 | { | 1392 | { |
1359 | struct block_device *bdev = sbi->sb->s_bdev; | 1393 | unsigned long interval = sbi->interval_time[type] * HZ; |
1360 | struct request_queue *q = bdev_get_queue(bdev); | 1394 | unsigned int wait_ms = 0; |
1361 | struct request_list *rl = &q->root_rl; | 1395 | long delta; |
1362 | 1396 | ||
1363 | if (rl->count[BLK_RW_SYNC] || rl->count[BLK_RW_ASYNC]) | 1397 | delta = (sbi->last_time[type] + interval) - jiffies; |
1364 | return false; | 1398 | if (delta > 0) |
1399 | wait_ms = jiffies_to_msecs(delta); | ||
1365 | 1400 | ||
1366 | return f2fs_time_over(sbi, REQ_TIME); | 1401 | return wait_ms; |
1367 | } | 1402 | } |
1368 | 1403 | ||
1369 | /* | 1404 | /* |
@@ -1704,7 +1739,8 @@ static inline int inc_valid_block_count(struct f2fs_sb_info *sbi, | |||
1704 | 1739 | ||
1705 | if (!__allow_reserved_blocks(sbi, inode, true)) | 1740 | if (!__allow_reserved_blocks(sbi, inode, true)) |
1706 | avail_user_block_count -= F2FS_OPTION(sbi).root_reserved_blocks; | 1741 | avail_user_block_count -= F2FS_OPTION(sbi).root_reserved_blocks; |
1707 | 1742 | if (unlikely(is_sbi_flag_set(sbi, SBI_CP_DISABLED))) | |
1743 | avail_user_block_count -= sbi->unusable_block_count; | ||
1708 | if (unlikely(sbi->total_valid_block_count > avail_user_block_count)) { | 1744 | if (unlikely(sbi->total_valid_block_count > avail_user_block_count)) { |
1709 | diff = sbi->total_valid_block_count - avail_user_block_count; | 1745 | diff = sbi->total_valid_block_count - avail_user_block_count; |
1710 | if (diff > *count) | 1746 | if (diff > *count) |
@@ -1755,7 +1791,9 @@ static inline void inc_page_count(struct f2fs_sb_info *sbi, int count_type) | |||
1755 | atomic_inc(&sbi->nr_pages[count_type]); | 1791 | atomic_inc(&sbi->nr_pages[count_type]); |
1756 | 1792 | ||
1757 | if (count_type == F2FS_DIRTY_DATA || count_type == F2FS_INMEM_PAGES || | 1793 | if (count_type == F2FS_DIRTY_DATA || count_type == F2FS_INMEM_PAGES || |
1758 | count_type == F2FS_WB_CP_DATA || count_type == F2FS_WB_DATA) | 1794 | count_type == F2FS_WB_CP_DATA || count_type == F2FS_WB_DATA || |
1795 | count_type == F2FS_RD_DATA || count_type == F2FS_RD_NODE || | ||
1796 | count_type == F2FS_RD_META) | ||
1759 | return; | 1797 | return; |
1760 | 1798 | ||
1761 | set_sbi_flag(sbi, SBI_IS_DIRTY); | 1799 | set_sbi_flag(sbi, SBI_IS_DIRTY); |
@@ -1891,12 +1929,18 @@ static inline int inc_valid_node_count(struct f2fs_sb_info *sbi, | |||
1891 | { | 1929 | { |
1892 | block_t valid_block_count; | 1930 | block_t valid_block_count; |
1893 | unsigned int valid_node_count; | 1931 | unsigned int valid_node_count; |
1894 | bool quota = inode && !is_inode; | 1932 | int err; |
1895 | 1933 | ||
1896 | if (quota) { | 1934 | if (is_inode) { |
1897 | int ret = dquot_reserve_block(inode, 1); | 1935 | if (inode) { |
1898 | if (ret) | 1936 | err = dquot_alloc_inode(inode); |
1899 | return ret; | 1937 | if (err) |
1938 | return err; | ||
1939 | } | ||
1940 | } else { | ||
1941 | err = dquot_reserve_block(inode, 1); | ||
1942 | if (err) | ||
1943 | return err; | ||
1900 | } | 1944 | } |
1901 | 1945 | ||
1902 | if (time_to_inject(sbi, FAULT_BLOCK)) { | 1946 | if (time_to_inject(sbi, FAULT_BLOCK)) { |
@@ -1911,6 +1955,8 @@ static inline int inc_valid_node_count(struct f2fs_sb_info *sbi, | |||
1911 | 1955 | ||
1912 | if (!__allow_reserved_blocks(sbi, inode, false)) | 1956 | if (!__allow_reserved_blocks(sbi, inode, false)) |
1913 | valid_block_count += F2FS_OPTION(sbi).root_reserved_blocks; | 1957 | valid_block_count += F2FS_OPTION(sbi).root_reserved_blocks; |
1958 | if (unlikely(is_sbi_flag_set(sbi, SBI_CP_DISABLED))) | ||
1959 | valid_block_count += sbi->unusable_block_count; | ||
1914 | 1960 | ||
1915 | if (unlikely(valid_block_count > sbi->user_block_count)) { | 1961 | if (unlikely(valid_block_count > sbi->user_block_count)) { |
1916 | spin_unlock(&sbi->stat_lock); | 1962 | spin_unlock(&sbi->stat_lock); |
@@ -1938,8 +1984,12 @@ static inline int inc_valid_node_count(struct f2fs_sb_info *sbi, | |||
1938 | return 0; | 1984 | return 0; |
1939 | 1985 | ||
1940 | enospc: | 1986 | enospc: |
1941 | if (quota) | 1987 | if (is_inode) { |
1988 | if (inode) | ||
1989 | dquot_free_inode(inode); | ||
1990 | } else { | ||
1942 | dquot_release_reservation_block(inode, 1); | 1991 | dquot_release_reservation_block(inode, 1); |
1992 | } | ||
1943 | return -ENOSPC; | 1993 | return -ENOSPC; |
1944 | } | 1994 | } |
1945 | 1995 | ||
@@ -1960,7 +2010,9 @@ static inline void dec_valid_node_count(struct f2fs_sb_info *sbi, | |||
1960 | 2010 | ||
1961 | spin_unlock(&sbi->stat_lock); | 2011 | spin_unlock(&sbi->stat_lock); |
1962 | 2012 | ||
1963 | if (!is_inode) | 2013 | if (is_inode) |
2014 | dquot_free_inode(inode); | ||
2015 | else | ||
1964 | f2fs_i_blocks_write(inode, 1, false, true); | 2016 | f2fs_i_blocks_write(inode, 1, false, true); |
1965 | } | 2017 | } |
1966 | 2018 | ||
@@ -2090,6 +2142,15 @@ static inline struct bio *f2fs_bio_alloc(struct f2fs_sb_info *sbi, | |||
2090 | return bio_alloc(GFP_KERNEL, npages); | 2142 | return bio_alloc(GFP_KERNEL, npages); |
2091 | } | 2143 | } |
2092 | 2144 | ||
2145 | static inline bool is_idle(struct f2fs_sb_info *sbi, int type) | ||
2146 | { | ||
2147 | if (get_pages(sbi, F2FS_RD_DATA) || get_pages(sbi, F2FS_RD_NODE) || | ||
2148 | get_pages(sbi, F2FS_RD_META) || get_pages(sbi, F2FS_WB_DATA) || | ||
2149 | get_pages(sbi, F2FS_WB_CP_DATA)) | ||
2150 | return false; | ||
2151 | return f2fs_time_over(sbi, type); | ||
2152 | } | ||
2153 | |||
2093 | static inline void f2fs_radix_tree_insert(struct radix_tree_root *root, | 2154 | static inline void f2fs_radix_tree_insert(struct radix_tree_root *root, |
2094 | unsigned long index, void *item) | 2155 | unsigned long index, void *item) |
2095 | { | 2156 | { |
@@ -2739,7 +2800,8 @@ static inline bool is_valid_data_blkaddr(struct f2fs_sb_info *sbi, | |||
2739 | */ | 2800 | */ |
2740 | int f2fs_sync_file(struct file *file, loff_t start, loff_t end, int datasync); | 2801 | int f2fs_sync_file(struct file *file, loff_t start, loff_t end, int datasync); |
2741 | void f2fs_truncate_data_blocks(struct dnode_of_data *dn); | 2802 | void f2fs_truncate_data_blocks(struct dnode_of_data *dn); |
2742 | int f2fs_truncate_blocks(struct inode *inode, u64 from, bool lock); | 2803 | int f2fs_truncate_blocks(struct inode *inode, u64 from, bool lock, |
2804 | bool buf_write); | ||
2743 | int f2fs_truncate(struct inode *inode); | 2805 | int f2fs_truncate(struct inode *inode); |
2744 | int f2fs_getattr(const struct path *path, struct kstat *stat, | 2806 | int f2fs_getattr(const struct path *path, struct kstat *stat, |
2745 | u32 request_mask, unsigned int flags); | 2807 | u32 request_mask, unsigned int flags); |
@@ -2749,6 +2811,7 @@ void f2fs_truncate_data_blocks_range(struct dnode_of_data *dn, int count); | |||
2749 | int f2fs_precache_extents(struct inode *inode); | 2811 | int f2fs_precache_extents(struct inode *inode); |
2750 | long f2fs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg); | 2812 | long f2fs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg); |
2751 | long f2fs_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg); | 2813 | long f2fs_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg); |
2814 | int f2fs_transfer_project_quota(struct inode *inode, kprojid_t kprojid); | ||
2752 | int f2fs_pin_file_control(struct inode *inode, bool inc); | 2815 | int f2fs_pin_file_control(struct inode *inode, bool inc); |
2753 | 2816 | ||
2754 | /* | 2817 | /* |
@@ -2827,6 +2890,7 @@ static inline int f2fs_add_link(struct dentry *dentry, struct inode *inode) | |||
2827 | int f2fs_inode_dirtied(struct inode *inode, bool sync); | 2890 | int f2fs_inode_dirtied(struct inode *inode, bool sync); |
2828 | void f2fs_inode_synced(struct inode *inode); | 2891 | void f2fs_inode_synced(struct inode *inode); |
2829 | int f2fs_enable_quota_files(struct f2fs_sb_info *sbi, bool rdonly); | 2892 | int f2fs_enable_quota_files(struct f2fs_sb_info *sbi, bool rdonly); |
2893 | int f2fs_quota_sync(struct super_block *sb, int type); | ||
2830 | void f2fs_quota_off_umount(struct super_block *sb); | 2894 | void f2fs_quota_off_umount(struct super_block *sb); |
2831 | int f2fs_commit_super(struct f2fs_sb_info *sbi, bool recover); | 2895 | int f2fs_commit_super(struct f2fs_sb_info *sbi, bool recover); |
2832 | int f2fs_sync_fs(struct super_block *sb, int sync); | 2896 | int f2fs_sync_fs(struct super_block *sb, int sync); |
@@ -2869,7 +2933,7 @@ struct page *f2fs_new_node_page(struct dnode_of_data *dn, unsigned int ofs); | |||
2869 | void f2fs_ra_node_page(struct f2fs_sb_info *sbi, nid_t nid); | 2933 | void f2fs_ra_node_page(struct f2fs_sb_info *sbi, nid_t nid); |
2870 | struct page *f2fs_get_node_page(struct f2fs_sb_info *sbi, pgoff_t nid); | 2934 | struct page *f2fs_get_node_page(struct f2fs_sb_info *sbi, pgoff_t nid); |
2871 | struct page *f2fs_get_node_page_ra(struct page *parent, int start); | 2935 | struct page *f2fs_get_node_page_ra(struct page *parent, int start); |
2872 | void f2fs_move_node_page(struct page *node_page, int gc_type); | 2936 | int f2fs_move_node_page(struct page *node_page, int gc_type); |
2873 | int f2fs_fsync_node_pages(struct f2fs_sb_info *sbi, struct inode *inode, | 2937 | int f2fs_fsync_node_pages(struct f2fs_sb_info *sbi, struct inode *inode, |
2874 | struct writeback_control *wbc, bool atomic, | 2938 | struct writeback_control *wbc, bool atomic, |
2875 | unsigned int *seq_id); | 2939 | unsigned int *seq_id); |
@@ -2886,7 +2950,7 @@ int f2fs_recover_xattr_data(struct inode *inode, struct page *page); | |||
2886 | int f2fs_recover_inode_page(struct f2fs_sb_info *sbi, struct page *page); | 2950 | int f2fs_recover_inode_page(struct f2fs_sb_info *sbi, struct page *page); |
2887 | int f2fs_restore_node_summary(struct f2fs_sb_info *sbi, | 2951 | int f2fs_restore_node_summary(struct f2fs_sb_info *sbi, |
2888 | unsigned int segno, struct f2fs_summary_block *sum); | 2952 | unsigned int segno, struct f2fs_summary_block *sum); |
2889 | void f2fs_flush_nat_entries(struct f2fs_sb_info *sbi, struct cp_control *cpc); | 2953 | int f2fs_flush_nat_entries(struct f2fs_sb_info *sbi, struct cp_control *cpc); |
2890 | int f2fs_build_node_manager(struct f2fs_sb_info *sbi); | 2954 | int f2fs_build_node_manager(struct f2fs_sb_info *sbi); |
2891 | void f2fs_destroy_node_manager(struct f2fs_sb_info *sbi); | 2955 | void f2fs_destroy_node_manager(struct f2fs_sb_info *sbi); |
2892 | int __init f2fs_create_node_manager_caches(void); | 2956 | int __init f2fs_create_node_manager_caches(void); |
@@ -2914,6 +2978,8 @@ void f2fs_stop_discard_thread(struct f2fs_sb_info *sbi); | |||
2914 | bool f2fs_wait_discard_bios(struct f2fs_sb_info *sbi); | 2978 | bool f2fs_wait_discard_bios(struct f2fs_sb_info *sbi); |
2915 | void f2fs_clear_prefree_segments(struct f2fs_sb_info *sbi, | 2979 | void f2fs_clear_prefree_segments(struct f2fs_sb_info *sbi, |
2916 | struct cp_control *cpc); | 2980 | struct cp_control *cpc); |
2981 | void f2fs_dirty_to_prefree(struct f2fs_sb_info *sbi); | ||
2982 | int f2fs_disable_cp_again(struct f2fs_sb_info *sbi); | ||
2917 | void f2fs_release_discard_addrs(struct f2fs_sb_info *sbi); | 2983 | void f2fs_release_discard_addrs(struct f2fs_sb_info *sbi); |
2918 | int f2fs_npages_for_summary_flush(struct f2fs_sb_info *sbi, bool for_ra); | 2984 | int f2fs_npages_for_summary_flush(struct f2fs_sb_info *sbi, bool for_ra); |
2919 | void f2fs_allocate_new_segments(struct f2fs_sb_info *sbi); | 2985 | void f2fs_allocate_new_segments(struct f2fs_sb_info *sbi); |
@@ -2942,7 +3008,9 @@ void f2fs_allocate_data_block(struct f2fs_sb_info *sbi, struct page *page, | |||
2942 | struct f2fs_io_info *fio, bool add_list); | 3008 | struct f2fs_io_info *fio, bool add_list); |
2943 | void f2fs_wait_on_page_writeback(struct page *page, | 3009 | void f2fs_wait_on_page_writeback(struct page *page, |
2944 | enum page_type type, bool ordered); | 3010 | enum page_type type, bool ordered); |
2945 | void f2fs_wait_on_block_writeback(struct f2fs_sb_info *sbi, block_t blkaddr); | 3011 | void f2fs_wait_on_block_writeback(struct inode *inode, block_t blkaddr); |
3012 | void f2fs_wait_on_block_writeback_range(struct inode *inode, block_t blkaddr, | ||
3013 | block_t len); | ||
2946 | void f2fs_write_data_summaries(struct f2fs_sb_info *sbi, block_t start_blk); | 3014 | void f2fs_write_data_summaries(struct f2fs_sb_info *sbi, block_t start_blk); |
2947 | void f2fs_write_node_summaries(struct f2fs_sb_info *sbi, block_t start_blk); | 3015 | void f2fs_write_node_summaries(struct f2fs_sb_info *sbi, block_t start_blk); |
2948 | int f2fs_lookup_journal_in_cursum(struct f2fs_journal *journal, int type, | 3016 | int f2fs_lookup_journal_in_cursum(struct f2fs_journal *journal, int type, |
@@ -3002,8 +3070,8 @@ int f2fs_init_post_read_processing(void); | |||
3002 | void f2fs_destroy_post_read_processing(void); | 3070 | void f2fs_destroy_post_read_processing(void); |
3003 | void f2fs_submit_merged_write(struct f2fs_sb_info *sbi, enum page_type type); | 3071 | void f2fs_submit_merged_write(struct f2fs_sb_info *sbi, enum page_type type); |
3004 | void f2fs_submit_merged_write_cond(struct f2fs_sb_info *sbi, | 3072 | void f2fs_submit_merged_write_cond(struct f2fs_sb_info *sbi, |
3005 | struct inode *inode, nid_t ino, pgoff_t idx, | 3073 | struct inode *inode, struct page *page, |
3006 | enum page_type type); | 3074 | nid_t ino, enum page_type type); |
3007 | void f2fs_flush_merged_writes(struct f2fs_sb_info *sbi); | 3075 | void f2fs_flush_merged_writes(struct f2fs_sb_info *sbi); |
3008 | int f2fs_submit_page_bio(struct f2fs_io_info *fio); | 3076 | int f2fs_submit_page_bio(struct f2fs_io_info *fio); |
3009 | void f2fs_submit_page_write(struct f2fs_io_info *fio); | 3077 | void f2fs_submit_page_write(struct f2fs_io_info *fio); |
@@ -3025,6 +3093,7 @@ struct page *f2fs_get_lock_data_page(struct inode *inode, pgoff_t index, | |||
3025 | struct page *f2fs_get_new_data_page(struct inode *inode, | 3093 | struct page *f2fs_get_new_data_page(struct inode *inode, |
3026 | struct page *ipage, pgoff_t index, bool new_i_size); | 3094 | struct page *ipage, pgoff_t index, bool new_i_size); |
3027 | int f2fs_do_write_data_page(struct f2fs_io_info *fio); | 3095 | int f2fs_do_write_data_page(struct f2fs_io_info *fio); |
3096 | void __do_map_lock(struct f2fs_sb_info *sbi, int flag, bool lock); | ||
3028 | int f2fs_map_blocks(struct inode *inode, struct f2fs_map_blocks *map, | 3097 | int f2fs_map_blocks(struct inode *inode, struct f2fs_map_blocks *map, |
3029 | int create, int flag); | 3098 | int create, int flag); |
3030 | int f2fs_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, | 3099 | int f2fs_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, |
@@ -3077,6 +3146,8 @@ struct f2fs_stat_info { | |||
3077 | int free_nids, avail_nids, alloc_nids; | 3146 | int free_nids, avail_nids, alloc_nids; |
3078 | int total_count, utilization; | 3147 | int total_count, utilization; |
3079 | int bg_gc, nr_wb_cp_data, nr_wb_data; | 3148 | int bg_gc, nr_wb_cp_data, nr_wb_data; |
3149 | int nr_rd_data, nr_rd_node, nr_rd_meta; | ||
3150 | unsigned int io_skip_bggc, other_skip_bggc; | ||
3080 | int nr_flushing, nr_flushed, flush_list_empty; | 3151 | int nr_flushing, nr_flushed, flush_list_empty; |
3081 | int nr_discarding, nr_discarded; | 3152 | int nr_discarding, nr_discarded; |
3082 | int nr_discard_cmd; | 3153 | int nr_discard_cmd; |
@@ -3098,6 +3169,7 @@ struct f2fs_stat_info { | |||
3098 | int cursec[NR_CURSEG_TYPE]; | 3169 | int cursec[NR_CURSEG_TYPE]; |
3099 | int curzone[NR_CURSEG_TYPE]; | 3170 | int curzone[NR_CURSEG_TYPE]; |
3100 | 3171 | ||
3172 | unsigned int meta_count[META_MAX]; | ||
3101 | unsigned int segment_count[2]; | 3173 | unsigned int segment_count[2]; |
3102 | unsigned int block_count[2]; | 3174 | unsigned int block_count[2]; |
3103 | unsigned int inplace_count; | 3175 | unsigned int inplace_count; |
@@ -3113,6 +3185,8 @@ static inline struct f2fs_stat_info *F2FS_STAT(struct f2fs_sb_info *sbi) | |||
3113 | #define stat_inc_bg_cp_count(si) ((si)->bg_cp_count++) | 3185 | #define stat_inc_bg_cp_count(si) ((si)->bg_cp_count++) |
3114 | #define stat_inc_call_count(si) ((si)->call_count++) | 3186 | #define stat_inc_call_count(si) ((si)->call_count++) |
3115 | #define stat_inc_bggc_count(sbi) ((sbi)->bg_gc++) | 3187 | #define stat_inc_bggc_count(sbi) ((sbi)->bg_gc++) |
3188 | #define stat_io_skip_bggc_count(sbi) ((sbi)->io_skip_bggc++) | ||
3189 | #define stat_other_skip_bggc_count(sbi) ((sbi)->other_skip_bggc++) | ||
3116 | #define stat_inc_dirty_inode(sbi, type) ((sbi)->ndirty_inode[type]++) | 3190 | #define stat_inc_dirty_inode(sbi, type) ((sbi)->ndirty_inode[type]++) |
3117 | #define stat_dec_dirty_inode(sbi, type) ((sbi)->ndirty_inode[type]--) | 3191 | #define stat_dec_dirty_inode(sbi, type) ((sbi)->ndirty_inode[type]--) |
3118 | #define stat_inc_total_hit(sbi) (atomic64_inc(&(sbi)->total_hit_ext)) | 3192 | #define stat_inc_total_hit(sbi) (atomic64_inc(&(sbi)->total_hit_ext)) |
@@ -3149,6 +3223,17 @@ static inline struct f2fs_stat_info *F2FS_STAT(struct f2fs_sb_info *sbi) | |||
3149 | if (f2fs_has_inline_dentry(inode)) \ | 3223 | if (f2fs_has_inline_dentry(inode)) \ |
3150 | (atomic_dec(&F2FS_I_SB(inode)->inline_dir)); \ | 3224 | (atomic_dec(&F2FS_I_SB(inode)->inline_dir)); \ |
3151 | } while (0) | 3225 | } while (0) |
3226 | #define stat_inc_meta_count(sbi, blkaddr) \ | ||
3227 | do { \ | ||
3228 | if (blkaddr < SIT_I(sbi)->sit_base_addr) \ | ||
3229 | atomic_inc(&(sbi)->meta_count[META_CP]); \ | ||
3230 | else if (blkaddr < NM_I(sbi)->nat_blkaddr) \ | ||
3231 | atomic_inc(&(sbi)->meta_count[META_SIT]); \ | ||
3232 | else if (blkaddr < SM_I(sbi)->ssa_blkaddr) \ | ||
3233 | atomic_inc(&(sbi)->meta_count[META_NAT]); \ | ||
3234 | else if (blkaddr < SM_I(sbi)->main_blkaddr) \ | ||
3235 | atomic_inc(&(sbi)->meta_count[META_SSA]); \ | ||
3236 | } while (0) | ||
3152 | #define stat_inc_seg_type(sbi, curseg) \ | 3237 | #define stat_inc_seg_type(sbi, curseg) \ |
3153 | ((sbi)->segment_count[(curseg)->alloc_type]++) | 3238 | ((sbi)->segment_count[(curseg)->alloc_type]++) |
3154 | #define stat_inc_block_count(sbi, curseg) \ | 3239 | #define stat_inc_block_count(sbi, curseg) \ |
@@ -3218,6 +3303,8 @@ void f2fs_destroy_root_stats(void); | |||
3218 | #define stat_inc_bg_cp_count(si) do { } while (0) | 3303 | #define stat_inc_bg_cp_count(si) do { } while (0) |
3219 | #define stat_inc_call_count(si) do { } while (0) | 3304 | #define stat_inc_call_count(si) do { } while (0) |
3220 | #define stat_inc_bggc_count(si) do { } while (0) | 3305 | #define stat_inc_bggc_count(si) do { } while (0) |
3306 | #define stat_io_skip_bggc_count(sbi) do { } while (0) | ||
3307 | #define stat_other_skip_bggc_count(sbi) do { } while (0) | ||
3221 | #define stat_inc_dirty_inode(sbi, type) do { } while (0) | 3308 | #define stat_inc_dirty_inode(sbi, type) do { } while (0) |
3222 | #define stat_dec_dirty_inode(sbi, type) do { } while (0) | 3309 | #define stat_dec_dirty_inode(sbi, type) do { } while (0) |
3223 | #define stat_inc_total_hit(sb) do { } while (0) | 3310 | #define stat_inc_total_hit(sb) do { } while (0) |
@@ -3236,6 +3323,7 @@ void f2fs_destroy_root_stats(void); | |||
3236 | #define stat_inc_volatile_write(inode) do { } while (0) | 3323 | #define stat_inc_volatile_write(inode) do { } while (0) |
3237 | #define stat_dec_volatile_write(inode) do { } while (0) | 3324 | #define stat_dec_volatile_write(inode) do { } while (0) |
3238 | #define stat_update_max_volatile_write(inode) do { } while (0) | 3325 | #define stat_update_max_volatile_write(inode) do { } while (0) |
3326 | #define stat_inc_meta_count(sbi, blkaddr) do { } while (0) | ||
3239 | #define stat_inc_seg_type(sbi, curseg) do { } while (0) | 3327 | #define stat_inc_seg_type(sbi, curseg) do { } while (0) |
3240 | #define stat_inc_block_count(sbi, curseg) do { } while (0) | 3328 | #define stat_inc_block_count(sbi, curseg) do { } while (0) |
3241 | #define stat_inc_inplace_blocks(sbi) do { } while (0) | 3329 | #define stat_inc_inplace_blocks(sbi) do { } while (0) |
@@ -3305,18 +3393,19 @@ void f2fs_leave_shrinker(struct f2fs_sb_info *sbi); | |||
3305 | /* | 3393 | /* |
3306 | * extent_cache.c | 3394 | * extent_cache.c |
3307 | */ | 3395 | */ |
3308 | struct rb_entry *f2fs_lookup_rb_tree(struct rb_root *root, | 3396 | struct rb_entry *f2fs_lookup_rb_tree(struct rb_root_cached *root, |
3309 | struct rb_entry *cached_re, unsigned int ofs); | 3397 | struct rb_entry *cached_re, unsigned int ofs); |
3310 | struct rb_node **f2fs_lookup_rb_tree_for_insert(struct f2fs_sb_info *sbi, | 3398 | struct rb_node **f2fs_lookup_rb_tree_for_insert(struct f2fs_sb_info *sbi, |
3311 | struct rb_root *root, struct rb_node **parent, | 3399 | struct rb_root_cached *root, |
3312 | unsigned int ofs); | 3400 | struct rb_node **parent, |
3313 | struct rb_entry *f2fs_lookup_rb_tree_ret(struct rb_root *root, | 3401 | unsigned int ofs, bool *leftmost); |
3402 | struct rb_entry *f2fs_lookup_rb_tree_ret(struct rb_root_cached *root, | ||
3314 | struct rb_entry *cached_re, unsigned int ofs, | 3403 | struct rb_entry *cached_re, unsigned int ofs, |
3315 | struct rb_entry **prev_entry, struct rb_entry **next_entry, | 3404 | struct rb_entry **prev_entry, struct rb_entry **next_entry, |
3316 | struct rb_node ***insert_p, struct rb_node **insert_parent, | 3405 | struct rb_node ***insert_p, struct rb_node **insert_parent, |
3317 | bool force); | 3406 | bool force, bool *leftmost); |
3318 | bool f2fs_check_rb_tree_consistence(struct f2fs_sb_info *sbi, | 3407 | bool f2fs_check_rb_tree_consistence(struct f2fs_sb_info *sbi, |
3319 | struct rb_root *root); | 3408 | struct rb_root_cached *root); |
3320 | unsigned int f2fs_shrink_extent_tree(struct f2fs_sb_info *sbi, int nr_shrink); | 3409 | unsigned int f2fs_shrink_extent_tree(struct f2fs_sb_info *sbi, int nr_shrink); |
3321 | bool f2fs_init_extent_tree(struct inode *inode, struct f2fs_extent *i_ext); | 3410 | bool f2fs_init_extent_tree(struct inode *inode, struct f2fs_extent *i_ext); |
3322 | void f2fs_drop_extent_tree(struct inode *inode); | 3411 | void f2fs_drop_extent_tree(struct inode *inode); |
@@ -3356,7 +3445,7 @@ static inline void f2fs_set_encrypted_inode(struct inode *inode) | |||
3356 | { | 3445 | { |
3357 | #ifdef CONFIG_F2FS_FS_ENCRYPTION | 3446 | #ifdef CONFIG_F2FS_FS_ENCRYPTION |
3358 | file_set_encrypt(inode); | 3447 | file_set_encrypt(inode); |
3359 | inode->i_flags |= S_ENCRYPTED; | 3448 | f2fs_set_inode_flags(inode); |
3360 | #endif | 3449 | #endif |
3361 | } | 3450 | } |
3362 | 3451 | ||
@@ -3384,6 +3473,7 @@ F2FS_FEATURE_FUNCS(flexible_inline_xattr, FLEXIBLE_INLINE_XATTR); | |||
3384 | F2FS_FEATURE_FUNCS(quota_ino, QUOTA_INO); | 3473 | F2FS_FEATURE_FUNCS(quota_ino, QUOTA_INO); |
3385 | F2FS_FEATURE_FUNCS(inode_crtime, INODE_CRTIME); | 3474 | F2FS_FEATURE_FUNCS(inode_crtime, INODE_CRTIME); |
3386 | F2FS_FEATURE_FUNCS(lost_found, LOST_FOUND); | 3475 | F2FS_FEATURE_FUNCS(lost_found, LOST_FOUND); |
3476 | F2FS_FEATURE_FUNCS(sb_chksum, SB_CHKSUM); | ||
3387 | 3477 | ||
3388 | #ifdef CONFIG_BLK_DEV_ZONED | 3478 | #ifdef CONFIG_BLK_DEV_ZONED |
3389 | static inline int get_blkz_type(struct f2fs_sb_info *sbi, | 3479 | static inline int get_blkz_type(struct f2fs_sb_info *sbi, |
@@ -3399,11 +3489,20 @@ static inline int get_blkz_type(struct f2fs_sb_info *sbi, | |||
3399 | } | 3489 | } |
3400 | #endif | 3490 | #endif |
3401 | 3491 | ||
3402 | static inline bool f2fs_discard_en(struct f2fs_sb_info *sbi) | 3492 | static inline bool f2fs_hw_should_discard(struct f2fs_sb_info *sbi) |
3403 | { | 3493 | { |
3404 | struct request_queue *q = bdev_get_queue(sbi->sb->s_bdev); | 3494 | return f2fs_sb_has_blkzoned(sbi->sb); |
3495 | } | ||
3405 | 3496 | ||
3406 | return blk_queue_discard(q) || f2fs_sb_has_blkzoned(sbi->sb); | 3497 | static inline bool f2fs_hw_support_discard(struct f2fs_sb_info *sbi) |
3498 | { | ||
3499 | return blk_queue_discard(bdev_get_queue(sbi->sb->s_bdev)); | ||
3500 | } | ||
3501 | |||
3502 | static inline bool f2fs_realtime_discard_enable(struct f2fs_sb_info *sbi) | ||
3503 | { | ||
3504 | return (test_opt(sbi, DISCARD) && f2fs_hw_support_discard(sbi)) || | ||
3505 | f2fs_hw_should_discard(sbi); | ||
3407 | } | 3506 | } |
3408 | 3507 | ||
3409 | static inline void set_opt_mode(struct f2fs_sb_info *sbi, unsigned int mt) | 3508 | static inline void set_opt_mode(struct f2fs_sb_info *sbi, unsigned int mt) |
@@ -3432,11 +3531,50 @@ static inline bool f2fs_may_encrypt(struct inode *inode) | |||
3432 | #endif | 3531 | #endif |
3433 | } | 3532 | } |
3434 | 3533 | ||
3435 | static inline bool f2fs_force_buffered_io(struct inode *inode, int rw) | 3534 | static inline int block_unaligned_IO(struct inode *inode, |
3535 | struct kiocb *iocb, struct iov_iter *iter) | ||
3436 | { | 3536 | { |
3437 | return (f2fs_post_read_required(inode) || | 3537 | unsigned int i_blkbits = READ_ONCE(inode->i_blkbits); |
3438 | (rw == WRITE && test_opt(F2FS_I_SB(inode), LFS)) || | 3538 | unsigned int blocksize_mask = (1 << i_blkbits) - 1; |
3439 | F2FS_I_SB(inode)->s_ndevs); | 3539 | loff_t offset = iocb->ki_pos; |
3540 | unsigned long align = offset | iov_iter_alignment(iter); | ||
3541 | |||
3542 | return align & blocksize_mask; | ||
3543 | } | ||
3544 | |||
3545 | static inline int allow_outplace_dio(struct inode *inode, | ||
3546 | struct kiocb *iocb, struct iov_iter *iter) | ||
3547 | { | ||
3548 | struct f2fs_sb_info *sbi = F2FS_I_SB(inode); | ||
3549 | int rw = iov_iter_rw(iter); | ||
3550 | |||
3551 | return (test_opt(sbi, LFS) && (rw == WRITE) && | ||
3552 | !block_unaligned_IO(inode, iocb, iter)); | ||
3553 | } | ||
3554 | |||
3555 | static inline bool f2fs_force_buffered_io(struct inode *inode, | ||
3556 | struct kiocb *iocb, struct iov_iter *iter) | ||
3557 | { | ||
3558 | struct f2fs_sb_info *sbi = F2FS_I_SB(inode); | ||
3559 | int rw = iov_iter_rw(iter); | ||
3560 | |||
3561 | if (f2fs_post_read_required(inode)) | ||
3562 | return true; | ||
3563 | if (sbi->s_ndevs) | ||
3564 | return true; | ||
3565 | /* | ||
3566 | * for blkzoned device, fallback direct IO to buffered IO, so | ||
3567 | * all IOs can be serialized by log-structured write. | ||
3568 | */ | ||
3569 | if (f2fs_sb_has_blkzoned(sbi->sb)) | ||
3570 | return true; | ||
3571 | if (test_opt(sbi, LFS) && (rw == WRITE) && | ||
3572 | block_unaligned_IO(inode, iocb, iter)) | ||
3573 | return true; | ||
3574 | if (is_sbi_flag_set(F2FS_I_SB(inode), SBI_CP_DISABLED)) | ||
3575 | return true; | ||
3576 | |||
3577 | return false; | ||
3440 | } | 3578 | } |
3441 | 3579 | ||
3442 | #ifdef CONFIG_F2FS_FAULT_INJECTION | 3580 | #ifdef CONFIG_F2FS_FAULT_INJECTION |
@@ -3447,3 +3585,16 @@ extern void f2fs_build_fault_attr(struct f2fs_sb_info *sbi, unsigned int rate, | |||
3447 | #endif | 3585 | #endif |
3448 | 3586 | ||
3449 | #endif | 3587 | #endif |
3588 | |||
3589 | static inline bool is_journalled_quota(struct f2fs_sb_info *sbi) | ||
3590 | { | ||
3591 | #ifdef CONFIG_QUOTA | ||
3592 | if (f2fs_sb_has_quota_ino(sbi->sb)) | ||
3593 | return true; | ||
3594 | if (F2FS_OPTION(sbi).s_qf_names[USRQUOTA] || | ||
3595 | F2FS_OPTION(sbi).s_qf_names[GRPQUOTA] || | ||
3596 | F2FS_OPTION(sbi).s_qf_names[PRJQUOTA]) | ||
3597 | return true; | ||
3598 | #endif | ||
3599 | return false; | ||
3600 | } | ||
diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c index 5474aaa274b9..88b124677189 100644 --- a/fs/f2fs/file.c +++ b/fs/f2fs/file.c | |||
@@ -1,12 +1,9 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
1 | /* | 2 | /* |
2 | * fs/f2fs/file.c | 3 | * fs/f2fs/file.c |
3 | * | 4 | * |
4 | * Copyright (c) 2012 Samsung Electronics Co., Ltd. | 5 | * Copyright (c) 2012 Samsung Electronics Co., Ltd. |
5 | * http://www.samsung.com/ | 6 | * http://www.samsung.com/ |
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | */ | 7 | */ |
11 | #include <linux/fs.h> | 8 | #include <linux/fs.h> |
12 | #include <linux/f2fs_fs.h> | 9 | #include <linux/f2fs_fs.h> |
@@ -50,7 +47,7 @@ static vm_fault_t f2fs_vm_page_mkwrite(struct vm_fault *vmf) | |||
50 | struct page *page = vmf->page; | 47 | struct page *page = vmf->page; |
51 | struct inode *inode = file_inode(vmf->vma->vm_file); | 48 | struct inode *inode = file_inode(vmf->vma->vm_file); |
52 | struct f2fs_sb_info *sbi = F2FS_I_SB(inode); | 49 | struct f2fs_sb_info *sbi = F2FS_I_SB(inode); |
53 | struct dnode_of_data dn; | 50 | struct dnode_of_data dn = { .node_changed = false }; |
54 | int err; | 51 | int err; |
55 | 52 | ||
56 | if (unlikely(f2fs_cp_error(sbi))) { | 53 | if (unlikely(f2fs_cp_error(sbi))) { |
@@ -62,19 +59,6 @@ static vm_fault_t f2fs_vm_page_mkwrite(struct vm_fault *vmf) | |||
62 | 59 | ||
63 | f2fs_bug_on(sbi, f2fs_has_inline_data(inode)); | 60 | f2fs_bug_on(sbi, f2fs_has_inline_data(inode)); |
64 | 61 | ||
65 | /* block allocation */ | ||
66 | f2fs_lock_op(sbi); | ||
67 | set_new_dnode(&dn, inode, NULL, NULL, 0); | ||
68 | err = f2fs_reserve_block(&dn, page->index); | ||
69 | if (err) { | ||
70 | f2fs_unlock_op(sbi); | ||
71 | goto out; | ||
72 | } | ||
73 | f2fs_put_dnode(&dn); | ||
74 | f2fs_unlock_op(sbi); | ||
75 | |||
76 | f2fs_balance_fs(sbi, dn.node_changed); | ||
77 | |||
78 | file_update_time(vmf->vma->vm_file); | 62 | file_update_time(vmf->vma->vm_file); |
79 | down_read(&F2FS_I(inode)->i_mmap_sem); | 63 | down_read(&F2FS_I(inode)->i_mmap_sem); |
80 | lock_page(page); | 64 | lock_page(page); |
@@ -86,11 +70,28 @@ static vm_fault_t f2fs_vm_page_mkwrite(struct vm_fault *vmf) | |||
86 | goto out_sem; | 70 | goto out_sem; |
87 | } | 71 | } |
88 | 72 | ||
73 | /* block allocation */ | ||
74 | __do_map_lock(sbi, F2FS_GET_BLOCK_PRE_AIO, true); | ||
75 | set_new_dnode(&dn, inode, NULL, NULL, 0); | ||
76 | err = f2fs_get_block(&dn, page->index); | ||
77 | f2fs_put_dnode(&dn); | ||
78 | __do_map_lock(sbi, F2FS_GET_BLOCK_PRE_AIO, false); | ||
79 | if (err) { | ||
80 | unlock_page(page); | ||
81 | goto out_sem; | ||
82 | } | ||
83 | |||
84 | /* fill the page */ | ||
85 | f2fs_wait_on_page_writeback(page, DATA, false); | ||
86 | |||
87 | /* wait for GCed page writeback via META_MAPPING */ | ||
88 | f2fs_wait_on_block_writeback(inode, dn.data_blkaddr); | ||
89 | |||
89 | /* | 90 | /* |
90 | * check to see if the page is mapped already (no holes) | 91 | * check to see if the page is mapped already (no holes) |
91 | */ | 92 | */ |
92 | if (PageMappedToDisk(page)) | 93 | if (PageMappedToDisk(page)) |
93 | goto mapped; | 94 | goto out_sem; |
94 | 95 | ||
95 | /* page is wholly or partially inside EOF */ | 96 | /* page is wholly or partially inside EOF */ |
96 | if (((loff_t)(page->index + 1) << PAGE_SHIFT) > | 97 | if (((loff_t)(page->index + 1) << PAGE_SHIFT) > |
@@ -105,21 +106,15 @@ static vm_fault_t f2fs_vm_page_mkwrite(struct vm_fault *vmf) | |||
105 | SetPageUptodate(page); | 106 | SetPageUptodate(page); |
106 | 107 | ||
107 | f2fs_update_iostat(sbi, APP_MAPPED_IO, F2FS_BLKSIZE); | 108 | f2fs_update_iostat(sbi, APP_MAPPED_IO, F2FS_BLKSIZE); |
109 | f2fs_update_time(sbi, REQ_TIME); | ||
108 | 110 | ||
109 | trace_f2fs_vm_page_mkwrite(page, DATA); | 111 | trace_f2fs_vm_page_mkwrite(page, DATA); |
110 | mapped: | ||
111 | /* fill the page */ | ||
112 | f2fs_wait_on_page_writeback(page, DATA, false); | ||
113 | |||
114 | /* wait for GCed page writeback via META_MAPPING */ | ||
115 | if (f2fs_post_read_required(inode)) | ||
116 | f2fs_wait_on_block_writeback(sbi, dn.data_blkaddr); | ||
117 | |||
118 | out_sem: | 112 | out_sem: |
119 | up_read(&F2FS_I(inode)->i_mmap_sem); | 113 | up_read(&F2FS_I(inode)->i_mmap_sem); |
120 | out: | 114 | |
115 | f2fs_balance_fs(sbi, dn.node_changed); | ||
116 | |||
121 | sb_end_pagefault(inode->i_sb); | 117 | sb_end_pagefault(inode->i_sb); |
122 | f2fs_update_time(sbi, REQ_TIME); | ||
123 | err: | 118 | err: |
124 | return block_page_mkwrite_return(err); | 119 | return block_page_mkwrite_return(err); |
125 | } | 120 | } |
@@ -215,7 +210,8 @@ static int f2fs_do_sync_file(struct file *file, loff_t start, loff_t end, | |||
215 | }; | 210 | }; |
216 | unsigned int seq_id = 0; | 211 | unsigned int seq_id = 0; |
217 | 212 | ||
218 | if (unlikely(f2fs_readonly(inode->i_sb))) | 213 | if (unlikely(f2fs_readonly(inode->i_sb) || |
214 | is_sbi_flag_set(sbi, SBI_CP_DISABLED))) | ||
219 | return 0; | 215 | return 0; |
220 | 216 | ||
221 | trace_f2fs_sync_file_enter(inode); | 217 | trace_f2fs_sync_file_enter(inode); |
@@ -590,7 +586,8 @@ truncate_out: | |||
590 | return 0; | 586 | return 0; |
591 | } | 587 | } |
592 | 588 | ||
593 | int f2fs_truncate_blocks(struct inode *inode, u64 from, bool lock) | 589 | int f2fs_truncate_blocks(struct inode *inode, u64 from, bool lock, |
590 | bool buf_write) | ||
594 | { | 591 | { |
595 | struct f2fs_sb_info *sbi = F2FS_I_SB(inode); | 592 | struct f2fs_sb_info *sbi = F2FS_I_SB(inode); |
596 | struct dnode_of_data dn; | 593 | struct dnode_of_data dn; |
@@ -598,6 +595,7 @@ int f2fs_truncate_blocks(struct inode *inode, u64 from, bool lock) | |||
598 | int count = 0, err = 0; | 595 | int count = 0, err = 0; |
599 | struct page *ipage; | 596 | struct page *ipage; |
600 | bool truncate_page = false; | 597 | bool truncate_page = false; |
598 | int flag = buf_write ? F2FS_GET_BLOCK_PRE_AIO : F2FS_GET_BLOCK_PRE_DIO; | ||
601 | 599 | ||
602 | trace_f2fs_truncate_blocks_enter(inode, from); | 600 | trace_f2fs_truncate_blocks_enter(inode, from); |
603 | 601 | ||
@@ -607,7 +605,7 @@ int f2fs_truncate_blocks(struct inode *inode, u64 from, bool lock) | |||
607 | goto free_partial; | 605 | goto free_partial; |
608 | 606 | ||
609 | if (lock) | 607 | if (lock) |
610 | f2fs_lock_op(sbi); | 608 | __do_map_lock(sbi, flag, true); |
611 | 609 | ||
612 | ipage = f2fs_get_node_page(sbi, inode->i_ino); | 610 | ipage = f2fs_get_node_page(sbi, inode->i_ino); |
613 | if (IS_ERR(ipage)) { | 611 | if (IS_ERR(ipage)) { |
@@ -645,7 +643,7 @@ free_next: | |||
645 | err = f2fs_truncate_inode_blocks(inode, free_from); | 643 | err = f2fs_truncate_inode_blocks(inode, free_from); |
646 | out: | 644 | out: |
647 | if (lock) | 645 | if (lock) |
648 | f2fs_unlock_op(sbi); | 646 | __do_map_lock(sbi, flag, false); |
649 | free_partial: | 647 | free_partial: |
650 | /* lastly zero out the first data page */ | 648 | /* lastly zero out the first data page */ |
651 | if (!err) | 649 | if (!err) |
@@ -680,7 +678,7 @@ int f2fs_truncate(struct inode *inode) | |||
680 | return err; | 678 | return err; |
681 | } | 679 | } |
682 | 680 | ||
683 | err = f2fs_truncate_blocks(inode, i_size_read(inode), true); | 681 | err = f2fs_truncate_blocks(inode, i_size_read(inode), true, false); |
684 | if (err) | 682 | if (err) |
685 | return err; | 683 | return err; |
686 | 684 | ||
@@ -789,9 +787,24 @@ int f2fs_setattr(struct dentry *dentry, struct iattr *attr) | |||
789 | !uid_eq(attr->ia_uid, inode->i_uid)) || | 787 | !uid_eq(attr->ia_uid, inode->i_uid)) || |
790 | (attr->ia_valid & ATTR_GID && | 788 | (attr->ia_valid & ATTR_GID && |
791 | !gid_eq(attr->ia_gid, inode->i_gid))) { | 789 | !gid_eq(attr->ia_gid, inode->i_gid))) { |
790 | f2fs_lock_op(F2FS_I_SB(inode)); | ||
792 | err = dquot_transfer(inode, attr); | 791 | err = dquot_transfer(inode, attr); |
793 | if (err) | 792 | if (err) { |
793 | set_sbi_flag(F2FS_I_SB(inode), | ||
794 | SBI_QUOTA_NEED_REPAIR); | ||
795 | f2fs_unlock_op(F2FS_I_SB(inode)); | ||
794 | return err; | 796 | return err; |
797 | } | ||
798 | /* | ||
799 | * update uid/gid under lock_op(), so that dquot and inode can | ||
800 | * be updated atomically. | ||
801 | */ | ||
802 | if (attr->ia_valid & ATTR_UID) | ||
803 | inode->i_uid = attr->ia_uid; | ||
804 | if (attr->ia_valid & ATTR_GID) | ||
805 | inode->i_gid = attr->ia_gid; | ||
806 | f2fs_mark_inode_dirty_sync(inode, true); | ||
807 | f2fs_unlock_op(F2FS_I_SB(inode)); | ||
795 | } | 808 | } |
796 | 809 | ||
797 | if (attr->ia_valid & ATTR_SIZE) { | 810 | if (attr->ia_valid & ATTR_SIZE) { |
@@ -1246,7 +1259,7 @@ static int f2fs_collapse_range(struct inode *inode, loff_t offset, loff_t len) | |||
1246 | new_size = i_size_read(inode) - len; | 1259 | new_size = i_size_read(inode) - len; |
1247 | truncate_pagecache(inode, new_size); | 1260 | truncate_pagecache(inode, new_size); |
1248 | 1261 | ||
1249 | ret = f2fs_truncate_blocks(inode, new_size, true); | 1262 | ret = f2fs_truncate_blocks(inode, new_size, true, false); |
1250 | up_write(&F2FS_I(inode)->i_mmap_sem); | 1263 | up_write(&F2FS_I(inode)->i_mmap_sem); |
1251 | if (!ret) | 1264 | if (!ret) |
1252 | f2fs_i_size_write(inode, new_size); | 1265 | f2fs_i_size_write(inode, new_size); |
@@ -1431,7 +1444,7 @@ static int f2fs_insert_range(struct inode *inode, loff_t offset, loff_t len) | |||
1431 | f2fs_balance_fs(sbi, true); | 1444 | f2fs_balance_fs(sbi, true); |
1432 | 1445 | ||
1433 | down_write(&F2FS_I(inode)->i_mmap_sem); | 1446 | down_write(&F2FS_I(inode)->i_mmap_sem); |
1434 | ret = f2fs_truncate_blocks(inode, i_size_read(inode), true); | 1447 | ret = f2fs_truncate_blocks(inode, i_size_read(inode), true, false); |
1435 | up_write(&F2FS_I(inode)->i_mmap_sem); | 1448 | up_write(&F2FS_I(inode)->i_mmap_sem); |
1436 | if (ret) | 1449 | if (ret) |
1437 | return ret; | 1450 | return ret; |
@@ -1978,7 +1991,7 @@ static int f2fs_ioc_fitrim(struct file *filp, unsigned long arg) | |||
1978 | if (!capable(CAP_SYS_ADMIN)) | 1991 | if (!capable(CAP_SYS_ADMIN)) |
1979 | return -EPERM; | 1992 | return -EPERM; |
1980 | 1993 | ||
1981 | if (!blk_queue_discard(q)) | 1994 | if (!f2fs_hw_support_discard(F2FS_SB(sb))) |
1982 | return -EOPNOTSUPP; | 1995 | return -EOPNOTSUPP; |
1983 | 1996 | ||
1984 | if (copy_from_user(&range, (struct fstrim_range __user *)arg, | 1997 | if (copy_from_user(&range, (struct fstrim_range __user *)arg, |
@@ -2162,6 +2175,12 @@ static int f2fs_ioc_write_checkpoint(struct file *filp, unsigned long arg) | |||
2162 | if (f2fs_readonly(sbi->sb)) | 2175 | if (f2fs_readonly(sbi->sb)) |
2163 | return -EROFS; | 2176 | return -EROFS; |
2164 | 2177 | ||
2178 | if (unlikely(is_sbi_flag_set(sbi, SBI_CP_DISABLED))) { | ||
2179 | f2fs_msg(sbi->sb, KERN_INFO, | ||
2180 | "Skipping Checkpoint. Checkpoints currently disabled."); | ||
2181 | return -EINVAL; | ||
2182 | } | ||
2183 | |||
2165 | ret = mnt_want_write_file(filp); | 2184 | ret = mnt_want_write_file(filp); |
2166 | if (ret) | 2185 | if (ret) |
2167 | return ret; | 2186 | return ret; |
@@ -2533,6 +2552,9 @@ static int f2fs_ioc_flush_device(struct file *filp, unsigned long arg) | |||
2533 | if (f2fs_readonly(sbi->sb)) | 2552 | if (f2fs_readonly(sbi->sb)) |
2534 | return -EROFS; | 2553 | return -EROFS; |
2535 | 2554 | ||
2555 | if (unlikely(is_sbi_flag_set(sbi, SBI_CP_DISABLED))) | ||
2556 | return -EINVAL; | ||
2557 | |||
2536 | if (copy_from_user(&range, (struct f2fs_flush_device __user *)arg, | 2558 | if (copy_from_user(&range, (struct f2fs_flush_device __user *)arg, |
2537 | sizeof(range))) | 2559 | sizeof(range))) |
2538 | return -EFAULT; | 2560 | return -EFAULT; |
@@ -2591,13 +2613,29 @@ static int f2fs_ioc_get_features(struct file *filp, unsigned long arg) | |||
2591 | } | 2613 | } |
2592 | 2614 | ||
2593 | #ifdef CONFIG_QUOTA | 2615 | #ifdef CONFIG_QUOTA |
2616 | int f2fs_transfer_project_quota(struct inode *inode, kprojid_t kprojid) | ||
2617 | { | ||
2618 | struct dquot *transfer_to[MAXQUOTAS] = {}; | ||
2619 | struct f2fs_sb_info *sbi = F2FS_I_SB(inode); | ||
2620 | struct super_block *sb = sbi->sb; | ||
2621 | int err = 0; | ||
2622 | |||
2623 | transfer_to[PRJQUOTA] = dqget(sb, make_kqid_projid(kprojid)); | ||
2624 | if (!IS_ERR(transfer_to[PRJQUOTA])) { | ||
2625 | err = __dquot_transfer(inode, transfer_to); | ||
2626 | if (err) | ||
2627 | set_sbi_flag(sbi, SBI_QUOTA_NEED_REPAIR); | ||
2628 | dqput(transfer_to[PRJQUOTA]); | ||
2629 | } | ||
2630 | return err; | ||
2631 | } | ||
2632 | |||
2594 | static int f2fs_ioc_setproject(struct file *filp, __u32 projid) | 2633 | static int f2fs_ioc_setproject(struct file *filp, __u32 projid) |
2595 | { | 2634 | { |
2596 | struct inode *inode = file_inode(filp); | 2635 | struct inode *inode = file_inode(filp); |
2597 | struct f2fs_inode_info *fi = F2FS_I(inode); | 2636 | struct f2fs_inode_info *fi = F2FS_I(inode); |
2598 | struct f2fs_sb_info *sbi = F2FS_I_SB(inode); | 2637 | struct f2fs_sb_info *sbi = F2FS_I_SB(inode); |
2599 | struct super_block *sb = sbi->sb; | 2638 | struct super_block *sb = sbi->sb; |
2600 | struct dquot *transfer_to[MAXQUOTAS] = {}; | ||
2601 | struct page *ipage; | 2639 | struct page *ipage; |
2602 | kprojid_t kprojid; | 2640 | kprojid_t kprojid; |
2603 | int err; | 2641 | int err; |
@@ -2617,53 +2655,45 @@ static int f2fs_ioc_setproject(struct file *filp, __u32 projid) | |||
2617 | if (projid_eq(kprojid, F2FS_I(inode)->i_projid)) | 2655 | if (projid_eq(kprojid, F2FS_I(inode)->i_projid)) |
2618 | return 0; | 2656 | return 0; |
2619 | 2657 | ||
2620 | err = mnt_want_write_file(filp); | ||
2621 | if (err) | ||
2622 | return err; | ||
2623 | |||
2624 | err = -EPERM; | 2658 | err = -EPERM; |
2625 | inode_lock(inode); | ||
2626 | |||
2627 | /* Is it quota file? Do not allow user to mess with it */ | 2659 | /* Is it quota file? Do not allow user to mess with it */ |
2628 | if (IS_NOQUOTA(inode)) | 2660 | if (IS_NOQUOTA(inode)) |
2629 | goto out_unlock; | 2661 | return err; |
2630 | 2662 | ||
2631 | ipage = f2fs_get_node_page(sbi, inode->i_ino); | 2663 | ipage = f2fs_get_node_page(sbi, inode->i_ino); |
2632 | if (IS_ERR(ipage)) { | 2664 | if (IS_ERR(ipage)) |
2633 | err = PTR_ERR(ipage); | 2665 | return PTR_ERR(ipage); |
2634 | goto out_unlock; | ||
2635 | } | ||
2636 | 2666 | ||
2637 | if (!F2FS_FITS_IN_INODE(F2FS_INODE(ipage), fi->i_extra_isize, | 2667 | if (!F2FS_FITS_IN_INODE(F2FS_INODE(ipage), fi->i_extra_isize, |
2638 | i_projid)) { | 2668 | i_projid)) { |
2639 | err = -EOVERFLOW; | 2669 | err = -EOVERFLOW; |
2640 | f2fs_put_page(ipage, 1); | 2670 | f2fs_put_page(ipage, 1); |
2641 | goto out_unlock; | 2671 | return err; |
2642 | } | 2672 | } |
2643 | f2fs_put_page(ipage, 1); | 2673 | f2fs_put_page(ipage, 1); |
2644 | 2674 | ||
2645 | err = dquot_initialize(inode); | 2675 | err = dquot_initialize(inode); |
2646 | if (err) | 2676 | if (err) |
2647 | goto out_unlock; | 2677 | return err; |
2648 | 2678 | ||
2649 | transfer_to[PRJQUOTA] = dqget(sb, make_kqid_projid(kprojid)); | 2679 | f2fs_lock_op(sbi); |
2650 | if (!IS_ERR(transfer_to[PRJQUOTA])) { | 2680 | err = f2fs_transfer_project_quota(inode, kprojid); |
2651 | err = __dquot_transfer(inode, transfer_to); | 2681 | if (err) |
2652 | dqput(transfer_to[PRJQUOTA]); | 2682 | goto out_unlock; |
2653 | if (err) | ||
2654 | goto out_dirty; | ||
2655 | } | ||
2656 | 2683 | ||
2657 | F2FS_I(inode)->i_projid = kprojid; | 2684 | F2FS_I(inode)->i_projid = kprojid; |
2658 | inode->i_ctime = current_time(inode); | 2685 | inode->i_ctime = current_time(inode); |
2659 | out_dirty: | ||
2660 | f2fs_mark_inode_dirty_sync(inode, true); | 2686 | f2fs_mark_inode_dirty_sync(inode, true); |
2661 | out_unlock: | 2687 | out_unlock: |
2662 | inode_unlock(inode); | 2688 | f2fs_unlock_op(sbi); |
2663 | mnt_drop_write_file(filp); | ||
2664 | return err; | 2689 | return err; |
2665 | } | 2690 | } |
2666 | #else | 2691 | #else |
2692 | int f2fs_transfer_project_quota(struct inode *inode, kprojid_t kprojid) | ||
2693 | { | ||
2694 | return 0; | ||
2695 | } | ||
2696 | |||
2667 | static int f2fs_ioc_setproject(struct file *filp, __u32 projid) | 2697 | static int f2fs_ioc_setproject(struct file *filp, __u32 projid) |
2668 | { | 2698 | { |
2669 | if (projid != F2FS_DEF_PROJID) | 2699 | if (projid != F2FS_DEF_PROJID) |
@@ -2736,6 +2766,30 @@ static int f2fs_ioc_fsgetxattr(struct file *filp, unsigned long arg) | |||
2736 | return 0; | 2766 | return 0; |
2737 | } | 2767 | } |
2738 | 2768 | ||
2769 | static int f2fs_ioctl_check_project(struct inode *inode, struct fsxattr *fa) | ||
2770 | { | ||
2771 | /* | ||
2772 | * Project Quota ID state is only allowed to change from within the init | ||
2773 | * namespace. Enforce that restriction only if we are trying to change | ||
2774 | * the quota ID state. Everything else is allowed in user namespaces. | ||
2775 | */ | ||
2776 | if (current_user_ns() == &init_user_ns) | ||
2777 | return 0; | ||
2778 | |||
2779 | if (__kprojid_val(F2FS_I(inode)->i_projid) != fa->fsx_projid) | ||
2780 | return -EINVAL; | ||
2781 | |||
2782 | if (F2FS_I(inode)->i_flags & F2FS_PROJINHERIT_FL) { | ||
2783 | if (!(fa->fsx_xflags & FS_XFLAG_PROJINHERIT)) | ||
2784 | return -EINVAL; | ||
2785 | } else { | ||
2786 | if (fa->fsx_xflags & FS_XFLAG_PROJINHERIT) | ||
2787 | return -EINVAL; | ||
2788 | } | ||
2789 | |||
2790 | return 0; | ||
2791 | } | ||
2792 | |||
2739 | static int f2fs_ioc_fssetxattr(struct file *filp, unsigned long arg) | 2793 | static int f2fs_ioc_fssetxattr(struct file *filp, unsigned long arg) |
2740 | { | 2794 | { |
2741 | struct inode *inode = file_inode(filp); | 2795 | struct inode *inode = file_inode(filp); |
@@ -2763,19 +2817,20 @@ static int f2fs_ioc_fssetxattr(struct file *filp, unsigned long arg) | |||
2763 | return err; | 2817 | return err; |
2764 | 2818 | ||
2765 | inode_lock(inode); | 2819 | inode_lock(inode); |
2820 | err = f2fs_ioctl_check_project(inode, &fa); | ||
2821 | if (err) | ||
2822 | goto out; | ||
2766 | flags = (fi->i_flags & ~F2FS_FL_XFLAG_VISIBLE) | | 2823 | flags = (fi->i_flags & ~F2FS_FL_XFLAG_VISIBLE) | |
2767 | (flags & F2FS_FL_XFLAG_VISIBLE); | 2824 | (flags & F2FS_FL_XFLAG_VISIBLE); |
2768 | err = __f2fs_ioc_setflags(inode, flags); | 2825 | err = __f2fs_ioc_setflags(inode, flags); |
2769 | inode_unlock(inode); | ||
2770 | mnt_drop_write_file(filp); | ||
2771 | if (err) | 2826 | if (err) |
2772 | return err; | 2827 | goto out; |
2773 | 2828 | ||
2774 | err = f2fs_ioc_setproject(filp, fa.fsx_projid); | 2829 | err = f2fs_ioc_setproject(filp, fa.fsx_projid); |
2775 | if (err) | 2830 | out: |
2776 | return err; | 2831 | inode_unlock(inode); |
2777 | 2832 | mnt_drop_write_file(filp); | |
2778 | return 0; | 2833 | return err; |
2779 | } | 2834 | } |
2780 | 2835 | ||
2781 | int f2fs_pin_file_control(struct inode *inode, bool inc) | 2836 | int f2fs_pin_file_control(struct inode *inode, bool inc) |
@@ -2992,7 +3047,8 @@ static ssize_t f2fs_file_write_iter(struct kiocb *iocb, struct iov_iter *from) | |||
2992 | if (!f2fs_overwrite_io(inode, iocb->ki_pos, | 3047 | if (!f2fs_overwrite_io(inode, iocb->ki_pos, |
2993 | iov_iter_count(from)) || | 3048 | iov_iter_count(from)) || |
2994 | f2fs_has_inline_data(inode) || | 3049 | f2fs_has_inline_data(inode) || |
2995 | f2fs_force_buffered_io(inode, WRITE)) { | 3050 | f2fs_force_buffered_io(inode, |
3051 | iocb, from)) { | ||
2996 | clear_inode_flag(inode, | 3052 | clear_inode_flag(inode, |
2997 | FI_NO_PREALLOC); | 3053 | FI_NO_PREALLOC); |
2998 | inode_unlock(inode); | 3054 | inode_unlock(inode); |
diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c index 5c8d00422237..a07241fb8537 100644 --- a/fs/f2fs/gc.c +++ b/fs/f2fs/gc.c | |||
@@ -1,12 +1,9 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
1 | /* | 2 | /* |
2 | * fs/f2fs/gc.c | 3 | * fs/f2fs/gc.c |
3 | * | 4 | * |
4 | * Copyright (c) 2012 Samsung Electronics Co., Ltd. | 5 | * Copyright (c) 2012 Samsung Electronics Co., Ltd. |
5 | * http://www.samsung.com/ | 6 | * http://www.samsung.com/ |
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | */ | 7 | */ |
11 | #include <linux/fs.h> | 8 | #include <linux/fs.h> |
12 | #include <linux/module.h> | 9 | #include <linux/module.h> |
@@ -43,13 +40,16 @@ static int gc_thread_func(void *data) | |||
43 | if (gc_th->gc_wake) | 40 | if (gc_th->gc_wake) |
44 | gc_th->gc_wake = 0; | 41 | gc_th->gc_wake = 0; |
45 | 42 | ||
46 | if (try_to_freeze()) | 43 | if (try_to_freeze()) { |
44 | stat_other_skip_bggc_count(sbi); | ||
47 | continue; | 45 | continue; |
46 | } | ||
48 | if (kthread_should_stop()) | 47 | if (kthread_should_stop()) |
49 | break; | 48 | break; |
50 | 49 | ||
51 | if (sbi->sb->s_writers.frozen >= SB_FREEZE_WRITE) { | 50 | if (sbi->sb->s_writers.frozen >= SB_FREEZE_WRITE) { |
52 | increase_sleep_time(gc_th, &wait_ms); | 51 | increase_sleep_time(gc_th, &wait_ms); |
52 | stat_other_skip_bggc_count(sbi); | ||
53 | continue; | 53 | continue; |
54 | } | 54 | } |
55 | 55 | ||
@@ -58,8 +58,10 @@ static int gc_thread_func(void *data) | |||
58 | f2fs_stop_checkpoint(sbi, false); | 58 | f2fs_stop_checkpoint(sbi, false); |
59 | } | 59 | } |
60 | 60 | ||
61 | if (!sb_start_write_trylock(sbi->sb)) | 61 | if (!sb_start_write_trylock(sbi->sb)) { |
62 | stat_other_skip_bggc_count(sbi); | ||
62 | continue; | 63 | continue; |
64 | } | ||
63 | 65 | ||
64 | /* | 66 | /* |
65 | * [GC triggering condition] | 67 | * [GC triggering condition] |
@@ -80,12 +82,15 @@ static int gc_thread_func(void *data) | |||
80 | goto do_gc; | 82 | goto do_gc; |
81 | } | 83 | } |
82 | 84 | ||
83 | if (!mutex_trylock(&sbi->gc_mutex)) | 85 | if (!mutex_trylock(&sbi->gc_mutex)) { |
86 | stat_other_skip_bggc_count(sbi); | ||
84 | goto next; | 87 | goto next; |
88 | } | ||
85 | 89 | ||
86 | if (!is_idle(sbi)) { | 90 | if (!is_idle(sbi, GC_TIME)) { |
87 | increase_sleep_time(gc_th, &wait_ms); | 91 | increase_sleep_time(gc_th, &wait_ms); |
88 | mutex_unlock(&sbi->gc_mutex); | 92 | mutex_unlock(&sbi->gc_mutex); |
93 | stat_io_skip_bggc_count(sbi); | ||
89 | goto next; | 94 | goto next; |
90 | } | 95 | } |
91 | 96 | ||
@@ -365,6 +370,10 @@ static int get_victim_by_default(struct f2fs_sb_info *sbi, | |||
365 | 370 | ||
366 | if (sec_usage_check(sbi, secno)) | 371 | if (sec_usage_check(sbi, secno)) |
367 | goto next; | 372 | goto next; |
373 | /* Don't touch checkpointed data */ | ||
374 | if (unlikely(is_sbi_flag_set(sbi, SBI_CP_DISABLED) && | ||
375 | get_ckpt_valid_blocks(sbi, segno))) | ||
376 | goto next; | ||
368 | if (gc_type == BG_GC && test_bit(secno, dirty_i->victim_secmap)) | 377 | if (gc_type == BG_GC && test_bit(secno, dirty_i->victim_secmap)) |
369 | goto next; | 378 | goto next; |
370 | 379 | ||
@@ -464,7 +473,7 @@ static int check_valid_map(struct f2fs_sb_info *sbi, | |||
464 | * On validity, copy that node with cold status, otherwise (invalid node) | 473 | * On validity, copy that node with cold status, otherwise (invalid node) |
465 | * ignore that. | 474 | * ignore that. |
466 | */ | 475 | */ |
467 | static void gc_node_segment(struct f2fs_sb_info *sbi, | 476 | static int gc_node_segment(struct f2fs_sb_info *sbi, |
468 | struct f2fs_summary *sum, unsigned int segno, int gc_type) | 477 | struct f2fs_summary *sum, unsigned int segno, int gc_type) |
469 | { | 478 | { |
470 | struct f2fs_summary *entry; | 479 | struct f2fs_summary *entry; |
@@ -472,6 +481,7 @@ static void gc_node_segment(struct f2fs_sb_info *sbi, | |||
472 | int off; | 481 | int off; |
473 | int phase = 0; | 482 | int phase = 0; |
474 | bool fggc = (gc_type == FG_GC); | 483 | bool fggc = (gc_type == FG_GC); |
484 | int submitted = 0; | ||
475 | 485 | ||
476 | start_addr = START_BLOCK(sbi, segno); | 486 | start_addr = START_BLOCK(sbi, segno); |
477 | 487 | ||
@@ -485,10 +495,11 @@ next_step: | |||
485 | nid_t nid = le32_to_cpu(entry->nid); | 495 | nid_t nid = le32_to_cpu(entry->nid); |
486 | struct page *node_page; | 496 | struct page *node_page; |
487 | struct node_info ni; | 497 | struct node_info ni; |
498 | int err; | ||
488 | 499 | ||
489 | /* stop BG_GC if there is not enough free sections. */ | 500 | /* stop BG_GC if there is not enough free sections. */ |
490 | if (gc_type == BG_GC && has_not_enough_free_secs(sbi, 0, 0)) | 501 | if (gc_type == BG_GC && has_not_enough_free_secs(sbi, 0, 0)) |
491 | return; | 502 | return submitted; |
492 | 503 | ||
493 | if (check_valid_map(sbi, segno, off) == 0) | 504 | if (check_valid_map(sbi, segno, off) == 0) |
494 | continue; | 505 | continue; |
@@ -525,7 +536,9 @@ next_step: | |||
525 | continue; | 536 | continue; |
526 | } | 537 | } |
527 | 538 | ||
528 | f2fs_move_node_page(node_page, gc_type); | 539 | err = f2fs_move_node_page(node_page, gc_type); |
540 | if (!err && gc_type == FG_GC) | ||
541 | submitted++; | ||
529 | stat_inc_node_blk_count(sbi, 1, gc_type); | 542 | stat_inc_node_blk_count(sbi, 1, gc_type); |
530 | } | 543 | } |
531 | 544 | ||
@@ -534,6 +547,7 @@ next_step: | |||
534 | 547 | ||
535 | if (fggc) | 548 | if (fggc) |
536 | atomic_dec(&sbi->wb_sync_req[NODE]); | 549 | atomic_dec(&sbi->wb_sync_req[NODE]); |
550 | return submitted; | ||
537 | } | 551 | } |
538 | 552 | ||
539 | /* | 553 | /* |
@@ -669,7 +683,7 @@ put_page: | |||
669 | * Move data block via META_MAPPING while keeping locked data page. | 683 | * Move data block via META_MAPPING while keeping locked data page. |
670 | * This can be used to move blocks, aka LBAs, directly on disk. | 684 | * This can be used to move blocks, aka LBAs, directly on disk. |
671 | */ | 685 | */ |
672 | static void move_data_block(struct inode *inode, block_t bidx, | 686 | static int move_data_block(struct inode *inode, block_t bidx, |
673 | int gc_type, unsigned int segno, int off) | 687 | int gc_type, unsigned int segno, int off) |
674 | { | 688 | { |
675 | struct f2fs_io_info fio = { | 689 | struct f2fs_io_info fio = { |
@@ -688,25 +702,29 @@ static void move_data_block(struct inode *inode, block_t bidx, | |||
688 | struct node_info ni; | 702 | struct node_info ni; |
689 | struct page *page, *mpage; | 703 | struct page *page, *mpage; |
690 | block_t newaddr; | 704 | block_t newaddr; |
691 | int err; | 705 | int err = 0; |
692 | bool lfs_mode = test_opt(fio.sbi, LFS); | 706 | bool lfs_mode = test_opt(fio.sbi, LFS); |
693 | 707 | ||
694 | /* do not read out */ | 708 | /* do not read out */ |
695 | page = f2fs_grab_cache_page(inode->i_mapping, bidx, false); | 709 | page = f2fs_grab_cache_page(inode->i_mapping, bidx, false); |
696 | if (!page) | 710 | if (!page) |
697 | return; | 711 | return -ENOMEM; |
698 | 712 | ||
699 | if (!check_valid_map(F2FS_I_SB(inode), segno, off)) | 713 | if (!check_valid_map(F2FS_I_SB(inode), segno, off)) { |
714 | err = -ENOENT; | ||
700 | goto out; | 715 | goto out; |
716 | } | ||
701 | 717 | ||
702 | if (f2fs_is_atomic_file(inode)) { | 718 | if (f2fs_is_atomic_file(inode)) { |
703 | F2FS_I(inode)->i_gc_failures[GC_FAILURE_ATOMIC]++; | 719 | F2FS_I(inode)->i_gc_failures[GC_FAILURE_ATOMIC]++; |
704 | F2FS_I_SB(inode)->skipped_atomic_files[gc_type]++; | 720 | F2FS_I_SB(inode)->skipped_atomic_files[gc_type]++; |
721 | err = -EAGAIN; | ||
705 | goto out; | 722 | goto out; |
706 | } | 723 | } |
707 | 724 | ||
708 | if (f2fs_is_pinned_file(inode)) { | 725 | if (f2fs_is_pinned_file(inode)) { |
709 | f2fs_pin_file_control(inode, true); | 726 | f2fs_pin_file_control(inode, true); |
727 | err = -EAGAIN; | ||
710 | goto out; | 728 | goto out; |
711 | } | 729 | } |
712 | 730 | ||
@@ -717,6 +735,7 @@ static void move_data_block(struct inode *inode, block_t bidx, | |||
717 | 735 | ||
718 | if (unlikely(dn.data_blkaddr == NULL_ADDR)) { | 736 | if (unlikely(dn.data_blkaddr == NULL_ADDR)) { |
719 | ClearPageUptodate(page); | 737 | ClearPageUptodate(page); |
738 | err = -ENOENT; | ||
720 | goto put_out; | 739 | goto put_out; |
721 | } | 740 | } |
722 | 741 | ||
@@ -799,6 +818,7 @@ write_page: | |||
799 | fio.new_blkaddr = newaddr; | 818 | fio.new_blkaddr = newaddr; |
800 | f2fs_submit_page_write(&fio); | 819 | f2fs_submit_page_write(&fio); |
801 | if (fio.retry) { | 820 | if (fio.retry) { |
821 | err = -EAGAIN; | ||
802 | if (PageWriteback(fio.encrypted_page)) | 822 | if (PageWriteback(fio.encrypted_page)) |
803 | end_page_writeback(fio.encrypted_page); | 823 | end_page_writeback(fio.encrypted_page); |
804 | goto put_page_out; | 824 | goto put_page_out; |
@@ -822,34 +842,42 @@ put_out: | |||
822 | f2fs_put_dnode(&dn); | 842 | f2fs_put_dnode(&dn); |
823 | out: | 843 | out: |
824 | f2fs_put_page(page, 1); | 844 | f2fs_put_page(page, 1); |
845 | return err; | ||
825 | } | 846 | } |
826 | 847 | ||
827 | static void move_data_page(struct inode *inode, block_t bidx, int gc_type, | 848 | static int move_data_page(struct inode *inode, block_t bidx, int gc_type, |
828 | unsigned int segno, int off) | 849 | unsigned int segno, int off) |
829 | { | 850 | { |
830 | struct page *page; | 851 | struct page *page; |
852 | int err = 0; | ||
831 | 853 | ||
832 | page = f2fs_get_lock_data_page(inode, bidx, true); | 854 | page = f2fs_get_lock_data_page(inode, bidx, true); |
833 | if (IS_ERR(page)) | 855 | if (IS_ERR(page)) |
834 | return; | 856 | return PTR_ERR(page); |
835 | 857 | ||
836 | if (!check_valid_map(F2FS_I_SB(inode), segno, off)) | 858 | if (!check_valid_map(F2FS_I_SB(inode), segno, off)) { |
859 | err = -ENOENT; | ||
837 | goto out; | 860 | goto out; |
861 | } | ||
838 | 862 | ||
839 | if (f2fs_is_atomic_file(inode)) { | 863 | if (f2fs_is_atomic_file(inode)) { |
840 | F2FS_I(inode)->i_gc_failures[GC_FAILURE_ATOMIC]++; | 864 | F2FS_I(inode)->i_gc_failures[GC_FAILURE_ATOMIC]++; |
841 | F2FS_I_SB(inode)->skipped_atomic_files[gc_type]++; | 865 | F2FS_I_SB(inode)->skipped_atomic_files[gc_type]++; |
866 | err = -EAGAIN; | ||
842 | goto out; | 867 | goto out; |
843 | } | 868 | } |
844 | if (f2fs_is_pinned_file(inode)) { | 869 | if (f2fs_is_pinned_file(inode)) { |
845 | if (gc_type == FG_GC) | 870 | if (gc_type == FG_GC) |
846 | f2fs_pin_file_control(inode, true); | 871 | f2fs_pin_file_control(inode, true); |
872 | err = -EAGAIN; | ||
847 | goto out; | 873 | goto out; |
848 | } | 874 | } |
849 | 875 | ||
850 | if (gc_type == BG_GC) { | 876 | if (gc_type == BG_GC) { |
851 | if (PageWriteback(page)) | 877 | if (PageWriteback(page)) { |
878 | err = -EAGAIN; | ||
852 | goto out; | 879 | goto out; |
880 | } | ||
853 | set_page_dirty(page); | 881 | set_page_dirty(page); |
854 | set_cold_data(page); | 882 | set_cold_data(page); |
855 | } else { | 883 | } else { |
@@ -867,7 +895,6 @@ static void move_data_page(struct inode *inode, block_t bidx, int gc_type, | |||
867 | .io_type = FS_GC_DATA_IO, | 895 | .io_type = FS_GC_DATA_IO, |
868 | }; | 896 | }; |
869 | bool is_dirty = PageDirty(page); | 897 | bool is_dirty = PageDirty(page); |
870 | int err; | ||
871 | 898 | ||
872 | retry: | 899 | retry: |
873 | set_page_dirty(page); | 900 | set_page_dirty(page); |
@@ -892,6 +919,7 @@ retry: | |||
892 | } | 919 | } |
893 | out: | 920 | out: |
894 | f2fs_put_page(page, 1); | 921 | f2fs_put_page(page, 1); |
922 | return err; | ||
895 | } | 923 | } |
896 | 924 | ||
897 | /* | 925 | /* |
@@ -901,7 +929,7 @@ out: | |||
901 | * If the parent node is not valid or the data block address is different, | 929 | * If the parent node is not valid or the data block address is different, |
902 | * the victim data block is ignored. | 930 | * the victim data block is ignored. |
903 | */ | 931 | */ |
904 | static void gc_data_segment(struct f2fs_sb_info *sbi, struct f2fs_summary *sum, | 932 | static int gc_data_segment(struct f2fs_sb_info *sbi, struct f2fs_summary *sum, |
905 | struct gc_inode_list *gc_list, unsigned int segno, int gc_type) | 933 | struct gc_inode_list *gc_list, unsigned int segno, int gc_type) |
906 | { | 934 | { |
907 | struct super_block *sb = sbi->sb; | 935 | struct super_block *sb = sbi->sb; |
@@ -909,6 +937,7 @@ static void gc_data_segment(struct f2fs_sb_info *sbi, struct f2fs_summary *sum, | |||
909 | block_t start_addr; | 937 | block_t start_addr; |
910 | int off; | 938 | int off; |
911 | int phase = 0; | 939 | int phase = 0; |
940 | int submitted = 0; | ||
912 | 941 | ||
913 | start_addr = START_BLOCK(sbi, segno); | 942 | start_addr = START_BLOCK(sbi, segno); |
914 | 943 | ||
@@ -925,7 +954,7 @@ next_step: | |||
925 | 954 | ||
926 | /* stop BG_GC if there is not enough free sections. */ | 955 | /* stop BG_GC if there is not enough free sections. */ |
927 | if (gc_type == BG_GC && has_not_enough_free_secs(sbi, 0, 0)) | 956 | if (gc_type == BG_GC && has_not_enough_free_secs(sbi, 0, 0)) |
928 | return; | 957 | return submitted; |
929 | 958 | ||
930 | if (check_valid_map(sbi, segno, off) == 0) | 959 | if (check_valid_map(sbi, segno, off) == 0) |
931 | continue; | 960 | continue; |
@@ -997,6 +1026,7 @@ next_step: | |||
997 | if (inode) { | 1026 | if (inode) { |
998 | struct f2fs_inode_info *fi = F2FS_I(inode); | 1027 | struct f2fs_inode_info *fi = F2FS_I(inode); |
999 | bool locked = false; | 1028 | bool locked = false; |
1029 | int err; | ||
1000 | 1030 | ||
1001 | if (S_ISREG(inode->i_mode)) { | 1031 | if (S_ISREG(inode->i_mode)) { |
1002 | if (!down_write_trylock(&fi->i_gc_rwsem[READ])) | 1032 | if (!down_write_trylock(&fi->i_gc_rwsem[READ])) |
@@ -1016,12 +1046,16 @@ next_step: | |||
1016 | start_bidx = f2fs_start_bidx_of_node(nofs, inode) | 1046 | start_bidx = f2fs_start_bidx_of_node(nofs, inode) |
1017 | + ofs_in_node; | 1047 | + ofs_in_node; |
1018 | if (f2fs_post_read_required(inode)) | 1048 | if (f2fs_post_read_required(inode)) |
1019 | move_data_block(inode, start_bidx, gc_type, | 1049 | err = move_data_block(inode, start_bidx, |
1020 | segno, off); | 1050 | gc_type, segno, off); |
1021 | else | 1051 | else |
1022 | move_data_page(inode, start_bidx, gc_type, | 1052 | err = move_data_page(inode, start_bidx, gc_type, |
1023 | segno, off); | 1053 | segno, off); |
1024 | 1054 | ||
1055 | if (!err && (gc_type == FG_GC || | ||
1056 | f2fs_post_read_required(inode))) | ||
1057 | submitted++; | ||
1058 | |||
1025 | if (locked) { | 1059 | if (locked) { |
1026 | up_write(&fi->i_gc_rwsem[WRITE]); | 1060 | up_write(&fi->i_gc_rwsem[WRITE]); |
1027 | up_write(&fi->i_gc_rwsem[READ]); | 1061 | up_write(&fi->i_gc_rwsem[READ]); |
@@ -1033,6 +1067,8 @@ next_step: | |||
1033 | 1067 | ||
1034 | if (++phase < 5) | 1068 | if (++phase < 5) |
1035 | goto next_step; | 1069 | goto next_step; |
1070 | |||
1071 | return submitted; | ||
1036 | } | 1072 | } |
1037 | 1073 | ||
1038 | static int __get_victim(struct f2fs_sb_info *sbi, unsigned int *victim, | 1074 | static int __get_victim(struct f2fs_sb_info *sbi, unsigned int *victim, |
@@ -1060,6 +1096,7 @@ static int do_garbage_collect(struct f2fs_sb_info *sbi, | |||
1060 | int seg_freed = 0; | 1096 | int seg_freed = 0; |
1061 | unsigned char type = IS_DATASEG(get_seg_entry(sbi, segno)->type) ? | 1097 | unsigned char type = IS_DATASEG(get_seg_entry(sbi, segno)->type) ? |
1062 | SUM_TYPE_DATA : SUM_TYPE_NODE; | 1098 | SUM_TYPE_DATA : SUM_TYPE_NODE; |
1099 | int submitted = 0; | ||
1063 | 1100 | ||
1064 | /* readahead multi ssa blocks those have contiguous address */ | 1101 | /* readahead multi ssa blocks those have contiguous address */ |
1065 | if (sbi->segs_per_sec > 1) | 1102 | if (sbi->segs_per_sec > 1) |
@@ -1069,6 +1106,18 @@ static int do_garbage_collect(struct f2fs_sb_info *sbi, | |||
1069 | /* reference all summary page */ | 1106 | /* reference all summary page */ |
1070 | while (segno < end_segno) { | 1107 | while (segno < end_segno) { |
1071 | sum_page = f2fs_get_sum_page(sbi, segno++); | 1108 | sum_page = f2fs_get_sum_page(sbi, segno++); |
1109 | if (IS_ERR(sum_page)) { | ||
1110 | int err = PTR_ERR(sum_page); | ||
1111 | |||
1112 | end_segno = segno - 1; | ||
1113 | for (segno = start_segno; segno < end_segno; segno++) { | ||
1114 | sum_page = find_get_page(META_MAPPING(sbi), | ||
1115 | GET_SUM_BLOCK(sbi, segno)); | ||
1116 | f2fs_put_page(sum_page, 0); | ||
1117 | f2fs_put_page(sum_page, 0); | ||
1118 | } | ||
1119 | return err; | ||
1120 | } | ||
1072 | unlock_page(sum_page); | 1121 | unlock_page(sum_page); |
1073 | } | 1122 | } |
1074 | 1123 | ||
@@ -1103,10 +1152,11 @@ static int do_garbage_collect(struct f2fs_sb_info *sbi, | |||
1103 | * - lock_page(sum_page) | 1152 | * - lock_page(sum_page) |
1104 | */ | 1153 | */ |
1105 | if (type == SUM_TYPE_NODE) | 1154 | if (type == SUM_TYPE_NODE) |
1106 | gc_node_segment(sbi, sum->entries, segno, gc_type); | 1155 | submitted += gc_node_segment(sbi, sum->entries, segno, |
1107 | else | ||
1108 | gc_data_segment(sbi, sum->entries, gc_list, segno, | ||
1109 | gc_type); | 1156 | gc_type); |
1157 | else | ||
1158 | submitted += gc_data_segment(sbi, sum->entries, gc_list, | ||
1159 | segno, gc_type); | ||
1110 | 1160 | ||
1111 | stat_inc_seg_count(sbi, type, gc_type); | 1161 | stat_inc_seg_count(sbi, type, gc_type); |
1112 | 1162 | ||
@@ -1117,7 +1167,7 @@ next: | |||
1117 | f2fs_put_page(sum_page, 0); | 1167 | f2fs_put_page(sum_page, 0); |
1118 | } | 1168 | } |
1119 | 1169 | ||
1120 | if (gc_type == FG_GC) | 1170 | if (submitted) |
1121 | f2fs_submit_merged_write(sbi, | 1171 | f2fs_submit_merged_write(sbi, |
1122 | (type == SUM_TYPE_NODE) ? NODE : DATA); | 1172 | (type == SUM_TYPE_NODE) ? NODE : DATA); |
1123 | 1173 | ||
@@ -1172,7 +1222,8 @@ gc_more: | |||
1172 | * threshold, we can make them free by checkpoint. Then, we | 1222 | * threshold, we can make them free by checkpoint. Then, we |
1173 | * secure free segments which doesn't need fggc any more. | 1223 | * secure free segments which doesn't need fggc any more. |
1174 | */ | 1224 | */ |
1175 | if (prefree_segments(sbi)) { | 1225 | if (prefree_segments(sbi) && |
1226 | !is_sbi_flag_set(sbi, SBI_CP_DISABLED)) { | ||
1176 | ret = f2fs_write_checkpoint(sbi, &cpc); | 1227 | ret = f2fs_write_checkpoint(sbi, &cpc); |
1177 | if (ret) | 1228 | if (ret) |
1178 | goto stop; | 1229 | goto stop; |
@@ -1224,7 +1275,7 @@ gc_more: | |||
1224 | segno = NULL_SEGNO; | 1275 | segno = NULL_SEGNO; |
1225 | goto gc_more; | 1276 | goto gc_more; |
1226 | } | 1277 | } |
1227 | if (gc_type == FG_GC) | 1278 | if (gc_type == FG_GC && !is_sbi_flag_set(sbi, SBI_CP_DISABLED)) |
1228 | ret = f2fs_write_checkpoint(sbi, &cpc); | 1279 | ret = f2fs_write_checkpoint(sbi, &cpc); |
1229 | } | 1280 | } |
1230 | stop: | 1281 | stop: |
@@ -1244,7 +1295,7 @@ stop: | |||
1244 | 1295 | ||
1245 | put_gc_inode(&gc_list); | 1296 | put_gc_inode(&gc_list); |
1246 | 1297 | ||
1247 | if (sync) | 1298 | if (sync && !ret) |
1248 | ret = sec_freed ? 0 : -EAGAIN; | 1299 | ret = sec_freed ? 0 : -EAGAIN; |
1249 | return ret; | 1300 | return ret; |
1250 | } | 1301 | } |
diff --git a/fs/f2fs/gc.h b/fs/f2fs/gc.h index c8619e408009..bbac9d3787bd 100644 --- a/fs/f2fs/gc.h +++ b/fs/f2fs/gc.h | |||
@@ -1,12 +1,9 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
1 | /* | 2 | /* |
2 | * fs/f2fs/gc.h | 3 | * fs/f2fs/gc.h |
3 | * | 4 | * |
4 | * Copyright (c) 2012 Samsung Electronics Co., Ltd. | 5 | * Copyright (c) 2012 Samsung Electronics Co., Ltd. |
5 | * http://www.samsung.com/ | 6 | * http://www.samsung.com/ |
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | */ | 7 | */ |
11 | #define GC_THREAD_MIN_WB_PAGES 1 /* | 8 | #define GC_THREAD_MIN_WB_PAGES 1 /* |
12 | * a threshold to determine | 9 | * a threshold to determine |
diff --git a/fs/f2fs/hash.c b/fs/f2fs/hash.c index eb2e031ea887..cc82f142f811 100644 --- a/fs/f2fs/hash.c +++ b/fs/f2fs/hash.c | |||
@@ -1,3 +1,4 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
1 | /* | 2 | /* |
2 | * fs/f2fs/hash.c | 3 | * fs/f2fs/hash.c |
3 | * | 4 | * |
@@ -7,10 +8,6 @@ | |||
7 | * Portions of this code from linux/fs/ext3/hash.c | 8 | * Portions of this code from linux/fs/ext3/hash.c |
8 | * | 9 | * |
9 | * Copyright (C) 2002 by Theodore Ts'o | 10 | * Copyright (C) 2002 by Theodore Ts'o |
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify | ||
12 | * it under the terms of the GNU General Public License version 2 as | ||
13 | * published by the Free Software Foundation. | ||
14 | */ | 11 | */ |
15 | #include <linux/types.h> | 12 | #include <linux/types.h> |
16 | #include <linux/fs.h> | 13 | #include <linux/fs.h> |
diff --git a/fs/f2fs/inline.c b/fs/f2fs/inline.c index 115dc219344b..cb31a719b048 100644 --- a/fs/f2fs/inline.c +++ b/fs/f2fs/inline.c | |||
@@ -1,11 +1,9 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
1 | /* | 2 | /* |
2 | * fs/f2fs/inline.c | 3 | * fs/f2fs/inline.c |
3 | * Copyright (c) 2013, Intel Corporation | 4 | * Copyright (c) 2013, Intel Corporation |
4 | * Authors: Huajun Li <huajun.li@intel.com> | 5 | * Authors: Huajun Li <huajun.li@intel.com> |
5 | * Haicheng Li <haicheng.li@intel.com> | 6 | * Haicheng Li <haicheng.li@intel.com> |
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | */ | 7 | */ |
10 | 8 | ||
11 | #include <linux/fs.h> | 9 | #include <linux/fs.h> |
@@ -300,7 +298,7 @@ process_inline: | |||
300 | clear_inode_flag(inode, FI_INLINE_DATA); | 298 | clear_inode_flag(inode, FI_INLINE_DATA); |
301 | f2fs_put_page(ipage, 1); | 299 | f2fs_put_page(ipage, 1); |
302 | } else if (ri && (ri->i_inline & F2FS_INLINE_DATA)) { | 300 | } else if (ri && (ri->i_inline & F2FS_INLINE_DATA)) { |
303 | if (f2fs_truncate_blocks(inode, 0, false)) | 301 | if (f2fs_truncate_blocks(inode, 0, false, false)) |
304 | return false; | 302 | return false; |
305 | goto process_inline; | 303 | goto process_inline; |
306 | } | 304 | } |
@@ -472,7 +470,7 @@ static int f2fs_add_inline_entries(struct inode *dir, void *inline_dentry) | |||
472 | return 0; | 470 | return 0; |
473 | punch_dentry_pages: | 471 | punch_dentry_pages: |
474 | truncate_inode_pages(&dir->i_data, 0); | 472 | truncate_inode_pages(&dir->i_data, 0); |
475 | f2fs_truncate_blocks(dir, 0, false); | 473 | f2fs_truncate_blocks(dir, 0, false, false); |
476 | f2fs_remove_dirty_inode(dir); | 474 | f2fs_remove_dirty_inode(dir); |
477 | return err; | 475 | return err; |
478 | } | 476 | } |
diff --git a/fs/f2fs/inode.c b/fs/f2fs/inode.c index 959df2249875..91ceee0ed4c4 100644 --- a/fs/f2fs/inode.c +++ b/fs/f2fs/inode.c | |||
@@ -1,12 +1,9 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
1 | /* | 2 | /* |
2 | * fs/f2fs/inode.c | 3 | * fs/f2fs/inode.c |
3 | * | 4 | * |
4 | * Copyright (c) 2012 Samsung Electronics Co., Ltd. | 5 | * Copyright (c) 2012 Samsung Electronics Co., Ltd. |
5 | * http://www.samsung.com/ | 6 | * http://www.samsung.com/ |
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | */ | 7 | */ |
11 | #include <linux/fs.h> | 8 | #include <linux/fs.h> |
12 | #include <linux/f2fs_fs.h> | 9 | #include <linux/f2fs_fs.h> |
@@ -368,6 +365,12 @@ static int do_read_inode(struct inode *inode) | |||
368 | if (f2fs_has_inline_data(inode) && !f2fs_exist_data(inode)) | 365 | if (f2fs_has_inline_data(inode) && !f2fs_exist_data(inode)) |
369 | __recover_inline_status(inode, node_page); | 366 | __recover_inline_status(inode, node_page); |
370 | 367 | ||
368 | /* try to recover cold bit for non-dir inode */ | ||
369 | if (!S_ISDIR(inode->i_mode) && !is_cold_node(node_page)) { | ||
370 | set_cold_node(node_page, false); | ||
371 | set_page_dirty(node_page); | ||
372 | } | ||
373 | |||
371 | /* get rdev by using inline_info */ | 374 | /* get rdev by using inline_info */ |
372 | __get_inode_rdev(inode, ri); | 375 | __get_inode_rdev(inode, ri); |
373 | 376 | ||
@@ -610,6 +613,9 @@ int f2fs_write_inode(struct inode *inode, struct writeback_control *wbc) | |||
610 | if (!is_inode_flag_set(inode, FI_DIRTY_INODE)) | 613 | if (!is_inode_flag_set(inode, FI_DIRTY_INODE)) |
611 | return 0; | 614 | return 0; |
612 | 615 | ||
616 | if (f2fs_is_checkpoint_ready(sbi)) | ||
617 | return -ENOSPC; | ||
618 | |||
613 | /* | 619 | /* |
614 | * We need to balance fs here to prevent from producing dirty node pages | 620 | * We need to balance fs here to prevent from producing dirty node pages |
615 | * during the urgent cleaning time when runing out of free sections. | 621 | * during the urgent cleaning time when runing out of free sections. |
@@ -648,7 +654,11 @@ void f2fs_evict_inode(struct inode *inode) | |||
648 | if (inode->i_nlink || is_bad_inode(inode)) | 654 | if (inode->i_nlink || is_bad_inode(inode)) |
649 | goto no_delete; | 655 | goto no_delete; |
650 | 656 | ||
651 | dquot_initialize(inode); | 657 | err = dquot_initialize(inode); |
658 | if (err) { | ||
659 | err = 0; | ||
660 | set_sbi_flag(sbi, SBI_QUOTA_NEED_REPAIR); | ||
661 | } | ||
652 | 662 | ||
653 | f2fs_remove_ino_entry(sbi, inode->i_ino, APPEND_INO); | 663 | f2fs_remove_ino_entry(sbi, inode->i_ino, APPEND_INO); |
654 | f2fs_remove_ino_entry(sbi, inode->i_ino, UPDATE_INO); | 664 | f2fs_remove_ino_entry(sbi, inode->i_ino, UPDATE_INO); |
@@ -680,9 +690,10 @@ retry: | |||
680 | goto retry; | 690 | goto retry; |
681 | } | 691 | } |
682 | 692 | ||
683 | if (err) | 693 | if (err) { |
684 | f2fs_update_inode_page(inode); | 694 | f2fs_update_inode_page(inode); |
685 | dquot_free_inode(inode); | 695 | set_sbi_flag(sbi, SBI_QUOTA_NEED_REPAIR); |
696 | } | ||
686 | sb_end_intwrite(inode->i_sb); | 697 | sb_end_intwrite(inode->i_sb); |
687 | no_delete: | 698 | no_delete: |
688 | dquot_drop(inode); | 699 | dquot_drop(inode); |
@@ -691,7 +702,8 @@ no_delete: | |||
691 | stat_dec_inline_dir(inode); | 702 | stat_dec_inline_dir(inode); |
692 | stat_dec_inline_inode(inode); | 703 | stat_dec_inline_inode(inode); |
693 | 704 | ||
694 | if (likely(!is_set_ckpt_flags(sbi, CP_ERROR_FLAG))) | 705 | if (likely(!is_set_ckpt_flags(sbi, CP_ERROR_FLAG) && |
706 | !is_sbi_flag_set(sbi, SBI_CP_DISABLED))) | ||
695 | f2fs_bug_on(sbi, is_inode_flag_set(inode, FI_DIRTY_INODE)); | 707 | f2fs_bug_on(sbi, is_inode_flag_set(inode, FI_DIRTY_INODE)); |
696 | else | 708 | else |
697 | f2fs_inode_synced(inode); | 709 | f2fs_inode_synced(inode); |
diff --git a/fs/f2fs/namei.c b/fs/f2fs/namei.c index 1f67e389169f..99299ede7429 100644 --- a/fs/f2fs/namei.c +++ b/fs/f2fs/namei.c | |||
@@ -1,12 +1,9 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
1 | /* | 2 | /* |
2 | * fs/f2fs/namei.c | 3 | * fs/f2fs/namei.c |
3 | * | 4 | * |
4 | * Copyright (c) 2012 Samsung Electronics Co., Ltd. | 5 | * Copyright (c) 2012 Samsung Electronics Co., Ltd. |
5 | * http://www.samsung.com/ | 6 | * http://www.samsung.com/ |
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | */ | 7 | */ |
11 | #include <linux/fs.h> | 8 | #include <linux/fs.h> |
12 | #include <linux/f2fs_fs.h> | 9 | #include <linux/f2fs_fs.h> |
@@ -19,6 +16,7 @@ | |||
19 | 16 | ||
20 | #include "f2fs.h" | 17 | #include "f2fs.h" |
21 | #include "node.h" | 18 | #include "node.h" |
19 | #include "segment.h" | ||
22 | #include "xattr.h" | 20 | #include "xattr.h" |
23 | #include "acl.h" | 21 | #include "acl.h" |
24 | #include <trace/events/f2fs.h> | 22 | #include <trace/events/f2fs.h> |
@@ -74,10 +72,6 @@ static struct inode *f2fs_new_inode(struct inode *dir, umode_t mode) | |||
74 | if (err) | 72 | if (err) |
75 | goto fail_drop; | 73 | goto fail_drop; |
76 | 74 | ||
77 | err = dquot_alloc_inode(inode); | ||
78 | if (err) | ||
79 | goto fail_drop; | ||
80 | |||
81 | set_inode_flag(inode, FI_NEW_INODE); | 75 | set_inode_flag(inode, FI_NEW_INODE); |
82 | 76 | ||
83 | /* If the directory encrypted, then we should encrypt the inode. */ | 77 | /* If the directory encrypted, then we should encrypt the inode. */ |
@@ -124,6 +118,8 @@ static struct inode *f2fs_new_inode(struct inode *dir, umode_t mode) | |||
124 | if (F2FS_I(inode)->i_flags & F2FS_PROJINHERIT_FL) | 118 | if (F2FS_I(inode)->i_flags & F2FS_PROJINHERIT_FL) |
125 | set_inode_flag(inode, FI_PROJ_INHERIT); | 119 | set_inode_flag(inode, FI_PROJ_INHERIT); |
126 | 120 | ||
121 | f2fs_set_inode_flags(inode); | ||
122 | |||
127 | trace_f2fs_new_inode(inode, 0); | 123 | trace_f2fs_new_inode(inode, 0); |
128 | return inode; | 124 | return inode; |
129 | 125 | ||
@@ -184,16 +180,19 @@ static inline void set_file_temperature(struct f2fs_sb_info *sbi, struct inode * | |||
184 | hot_count = sbi->raw_super->hot_ext_count; | 180 | hot_count = sbi->raw_super->hot_ext_count; |
185 | 181 | ||
186 | for (i = 0; i < cold_count + hot_count; i++) { | 182 | for (i = 0; i < cold_count + hot_count; i++) { |
187 | if (!is_extension_exist(name, extlist[i])) | 183 | if (is_extension_exist(name, extlist[i])) |
188 | continue; | 184 | break; |
189 | if (i < cold_count) | ||
190 | file_set_cold(inode); | ||
191 | else | ||
192 | file_set_hot(inode); | ||
193 | break; | ||
194 | } | 185 | } |
195 | 186 | ||
196 | up_read(&sbi->sb_lock); | 187 | up_read(&sbi->sb_lock); |
188 | |||
189 | if (i == cold_count + hot_count) | ||
190 | return; | ||
191 | |||
192 | if (i < cold_count) | ||
193 | file_set_cold(inode); | ||
194 | else | ||
195 | file_set_hot(inode); | ||
197 | } | 196 | } |
198 | 197 | ||
199 | int f2fs_update_extension_list(struct f2fs_sb_info *sbi, const char *name, | 198 | int f2fs_update_extension_list(struct f2fs_sb_info *sbi, const char *name, |
@@ -272,6 +271,9 @@ static int f2fs_create(struct inode *dir, struct dentry *dentry, umode_t mode, | |||
272 | 271 | ||
273 | if (unlikely(f2fs_cp_error(sbi))) | 272 | if (unlikely(f2fs_cp_error(sbi))) |
274 | return -EIO; | 273 | return -EIO; |
274 | err = f2fs_is_checkpoint_ready(sbi); | ||
275 | if (err) | ||
276 | return err; | ||
275 | 277 | ||
276 | err = dquot_initialize(dir); | 278 | err = dquot_initialize(dir); |
277 | if (err) | 279 | if (err) |
@@ -318,6 +320,9 @@ static int f2fs_link(struct dentry *old_dentry, struct inode *dir, | |||
318 | 320 | ||
319 | if (unlikely(f2fs_cp_error(sbi))) | 321 | if (unlikely(f2fs_cp_error(sbi))) |
320 | return -EIO; | 322 | return -EIO; |
323 | err = f2fs_is_checkpoint_ready(sbi); | ||
324 | if (err) | ||
325 | return err; | ||
321 | 326 | ||
322 | err = fscrypt_prepare_link(old_dentry, dir, dentry); | 327 | err = fscrypt_prepare_link(old_dentry, dir, dentry); |
323 | if (err) | 328 | if (err) |
@@ -564,6 +569,9 @@ static int f2fs_symlink(struct inode *dir, struct dentry *dentry, | |||
564 | 569 | ||
565 | if (unlikely(f2fs_cp_error(sbi))) | 570 | if (unlikely(f2fs_cp_error(sbi))) |
566 | return -EIO; | 571 | return -EIO; |
572 | err = f2fs_is_checkpoint_ready(sbi); | ||
573 | if (err) | ||
574 | return err; | ||
567 | 575 | ||
568 | err = fscrypt_prepare_symlink(dir, symname, len, dir->i_sb->s_blocksize, | 576 | err = fscrypt_prepare_symlink(dir, symname, len, dir->i_sb->s_blocksize, |
569 | &disk_link); | 577 | &disk_link); |
@@ -693,6 +701,9 @@ static int f2fs_mknod(struct inode *dir, struct dentry *dentry, | |||
693 | 701 | ||
694 | if (unlikely(f2fs_cp_error(sbi))) | 702 | if (unlikely(f2fs_cp_error(sbi))) |
695 | return -EIO; | 703 | return -EIO; |
704 | err = f2fs_is_checkpoint_ready(sbi); | ||
705 | if (err) | ||
706 | return err; | ||
696 | 707 | ||
697 | err = dquot_initialize(dir); | 708 | err = dquot_initialize(dir); |
698 | if (err) | 709 | if (err) |
@@ -823,10 +834,13 @@ static int f2fs_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
823 | struct f2fs_dir_entry *old_entry; | 834 | struct f2fs_dir_entry *old_entry; |
824 | struct f2fs_dir_entry *new_entry; | 835 | struct f2fs_dir_entry *new_entry; |
825 | bool is_old_inline = f2fs_has_inline_dentry(old_dir); | 836 | bool is_old_inline = f2fs_has_inline_dentry(old_dir); |
826 | int err = -ENOENT; | 837 | int err; |
827 | 838 | ||
828 | if (unlikely(f2fs_cp_error(sbi))) | 839 | if (unlikely(f2fs_cp_error(sbi))) |
829 | return -EIO; | 840 | return -EIO; |
841 | err = f2fs_is_checkpoint_ready(sbi); | ||
842 | if (err) | ||
843 | return err; | ||
830 | 844 | ||
831 | if (is_inode_flag_set(new_dir, FI_PROJ_INHERIT) && | 845 | if (is_inode_flag_set(new_dir, FI_PROJ_INHERIT) && |
832 | (!projid_eq(F2FS_I(new_dir)->i_projid, | 846 | (!projid_eq(F2FS_I(new_dir)->i_projid, |
@@ -847,6 +861,7 @@ static int f2fs_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
847 | goto out; | 861 | goto out; |
848 | } | 862 | } |
849 | 863 | ||
864 | err = -ENOENT; | ||
850 | old_entry = f2fs_find_entry(old_dir, &old_dentry->d_name, &old_page); | 865 | old_entry = f2fs_find_entry(old_dir, &old_dentry->d_name, &old_page); |
851 | if (!old_entry) { | 866 | if (!old_entry) { |
852 | if (IS_ERR(old_page)) | 867 | if (IS_ERR(old_page)) |
@@ -983,6 +998,8 @@ static int f2fs_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
983 | 998 | ||
984 | if (IS_DIRSYNC(old_dir) || IS_DIRSYNC(new_dir)) | 999 | if (IS_DIRSYNC(old_dir) || IS_DIRSYNC(new_dir)) |
985 | f2fs_sync_fs(sbi->sb, 1); | 1000 | f2fs_sync_fs(sbi->sb, 1); |
1001 | |||
1002 | f2fs_update_time(sbi, REQ_TIME); | ||
986 | return 0; | 1003 | return 0; |
987 | 1004 | ||
988 | put_out_dir: | 1005 | put_out_dir: |
@@ -1012,10 +1029,13 @@ static int f2fs_cross_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
1012 | struct f2fs_dir_entry *old_dir_entry = NULL, *new_dir_entry = NULL; | 1029 | struct f2fs_dir_entry *old_dir_entry = NULL, *new_dir_entry = NULL; |
1013 | struct f2fs_dir_entry *old_entry, *new_entry; | 1030 | struct f2fs_dir_entry *old_entry, *new_entry; |
1014 | int old_nlink = 0, new_nlink = 0; | 1031 | int old_nlink = 0, new_nlink = 0; |
1015 | int err = -ENOENT; | 1032 | int err; |
1016 | 1033 | ||
1017 | if (unlikely(f2fs_cp_error(sbi))) | 1034 | if (unlikely(f2fs_cp_error(sbi))) |
1018 | return -EIO; | 1035 | return -EIO; |
1036 | err = f2fs_is_checkpoint_ready(sbi); | ||
1037 | if (err) | ||
1038 | return err; | ||
1019 | 1039 | ||
1020 | if ((is_inode_flag_set(new_dir, FI_PROJ_INHERIT) && | 1040 | if ((is_inode_flag_set(new_dir, FI_PROJ_INHERIT) && |
1021 | !projid_eq(F2FS_I(new_dir)->i_projid, | 1041 | !projid_eq(F2FS_I(new_dir)->i_projid, |
@@ -1033,6 +1053,7 @@ static int f2fs_cross_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
1033 | if (err) | 1053 | if (err) |
1034 | goto out; | 1054 | goto out; |
1035 | 1055 | ||
1056 | err = -ENOENT; | ||
1036 | old_entry = f2fs_find_entry(old_dir, &old_dentry->d_name, &old_page); | 1057 | old_entry = f2fs_find_entry(old_dir, &old_dentry->d_name, &old_page); |
1037 | if (!old_entry) { | 1058 | if (!old_entry) { |
1038 | if (IS_ERR(old_page)) | 1059 | if (IS_ERR(old_page)) |
@@ -1136,6 +1157,8 @@ static int f2fs_cross_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
1136 | 1157 | ||
1137 | if (IS_DIRSYNC(old_dir) || IS_DIRSYNC(new_dir)) | 1158 | if (IS_DIRSYNC(old_dir) || IS_DIRSYNC(new_dir)) |
1138 | f2fs_sync_fs(sbi->sb, 1); | 1159 | f2fs_sync_fs(sbi->sb, 1); |
1160 | |||
1161 | f2fs_update_time(sbi, REQ_TIME); | ||
1139 | return 0; | 1162 | return 0; |
1140 | out_new_dir: | 1163 | out_new_dir: |
1141 | if (new_dir_entry) { | 1164 | if (new_dir_entry) { |
diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c index dd2e45a661aa..2b34206486d8 100644 --- a/fs/f2fs/node.c +++ b/fs/f2fs/node.c | |||
@@ -1,12 +1,9 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
1 | /* | 2 | /* |
2 | * fs/f2fs/node.c | 3 | * fs/f2fs/node.c |
3 | * | 4 | * |
4 | * Copyright (c) 2012 Samsung Electronics Co., Ltd. | 5 | * Copyright (c) 2012 Samsung Electronics Co., Ltd. |
5 | * http://www.samsung.com/ | 6 | * http://www.samsung.com/ |
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | */ | 7 | */ |
11 | #include <linux/fs.h> | 8 | #include <linux/fs.h> |
12 | #include <linux/f2fs_fs.h> | 9 | #include <linux/f2fs_fs.h> |
@@ -129,6 +126,8 @@ static struct page *get_next_nat_page(struct f2fs_sb_info *sbi, nid_t nid) | |||
129 | 126 | ||
130 | /* get current nat block page with lock */ | 127 | /* get current nat block page with lock */ |
131 | src_page = get_current_nat_page(sbi, nid); | 128 | src_page = get_current_nat_page(sbi, nid); |
129 | if (IS_ERR(src_page)) | ||
130 | return src_page; | ||
132 | dst_page = f2fs_grab_meta_page(sbi, dst_off); | 131 | dst_page = f2fs_grab_meta_page(sbi, dst_off); |
133 | f2fs_bug_on(sbi, PageDirty(src_page)); | 132 | f2fs_bug_on(sbi, PageDirty(src_page)); |
134 | 133 | ||
@@ -1542,8 +1541,10 @@ static int __write_node_page(struct page *page, bool atomic, bool *submitted, | |||
1542 | } | 1541 | } |
1543 | 1542 | ||
1544 | if (__is_valid_data_blkaddr(ni.blk_addr) && | 1543 | if (__is_valid_data_blkaddr(ni.blk_addr) && |
1545 | !f2fs_is_valid_blkaddr(sbi, ni.blk_addr, DATA_GENERIC)) | 1544 | !f2fs_is_valid_blkaddr(sbi, ni.blk_addr, DATA_GENERIC)) { |
1545 | up_read(&sbi->node_write); | ||
1546 | goto redirty_out; | 1546 | goto redirty_out; |
1547 | } | ||
1547 | 1548 | ||
1548 | if (atomic && !test_opt(sbi, NOBARRIER)) | 1549 | if (atomic && !test_opt(sbi, NOBARRIER)) |
1549 | fio.op_flags |= REQ_PREFLUSH | REQ_FUA; | 1550 | fio.op_flags |= REQ_PREFLUSH | REQ_FUA; |
@@ -1564,8 +1565,7 @@ static int __write_node_page(struct page *page, bool atomic, bool *submitted, | |||
1564 | up_read(&sbi->node_write); | 1565 | up_read(&sbi->node_write); |
1565 | 1566 | ||
1566 | if (wbc->for_reclaim) { | 1567 | if (wbc->for_reclaim) { |
1567 | f2fs_submit_merged_write_cond(sbi, page->mapping->host, 0, | 1568 | f2fs_submit_merged_write_cond(sbi, NULL, page, 0, NODE); |
1568 | page->index, NODE); | ||
1569 | submitted = NULL; | 1569 | submitted = NULL; |
1570 | } | 1570 | } |
1571 | 1571 | ||
@@ -1587,8 +1587,10 @@ redirty_out: | |||
1587 | return AOP_WRITEPAGE_ACTIVATE; | 1587 | return AOP_WRITEPAGE_ACTIVATE; |
1588 | } | 1588 | } |
1589 | 1589 | ||
1590 | void f2fs_move_node_page(struct page *node_page, int gc_type) | 1590 | int f2fs_move_node_page(struct page *node_page, int gc_type) |
1591 | { | 1591 | { |
1592 | int err = 0; | ||
1593 | |||
1592 | if (gc_type == FG_GC) { | 1594 | if (gc_type == FG_GC) { |
1593 | struct writeback_control wbc = { | 1595 | struct writeback_control wbc = { |
1594 | .sync_mode = WB_SYNC_ALL, | 1596 | .sync_mode = WB_SYNC_ALL, |
@@ -1600,12 +1602,16 @@ void f2fs_move_node_page(struct page *node_page, int gc_type) | |||
1600 | f2fs_wait_on_page_writeback(node_page, NODE, true); | 1602 | f2fs_wait_on_page_writeback(node_page, NODE, true); |
1601 | 1603 | ||
1602 | f2fs_bug_on(F2FS_P_SB(node_page), PageWriteback(node_page)); | 1604 | f2fs_bug_on(F2FS_P_SB(node_page), PageWriteback(node_page)); |
1603 | if (!clear_page_dirty_for_io(node_page)) | 1605 | if (!clear_page_dirty_for_io(node_page)) { |
1606 | err = -EAGAIN; | ||
1604 | goto out_page; | 1607 | goto out_page; |
1608 | } | ||
1605 | 1609 | ||
1606 | if (__write_node_page(node_page, false, NULL, | 1610 | if (__write_node_page(node_page, false, NULL, |
1607 | &wbc, false, FS_GC_NODE_IO, NULL)) | 1611 | &wbc, false, FS_GC_NODE_IO, NULL)) { |
1612 | err = -EAGAIN; | ||
1608 | unlock_page(node_page); | 1613 | unlock_page(node_page); |
1614 | } | ||
1609 | goto release_page; | 1615 | goto release_page; |
1610 | } else { | 1616 | } else { |
1611 | /* set page dirty and write it */ | 1617 | /* set page dirty and write it */ |
@@ -1616,6 +1622,7 @@ out_page: | |||
1616 | unlock_page(node_page); | 1622 | unlock_page(node_page); |
1617 | release_page: | 1623 | release_page: |
1618 | f2fs_put_page(node_page, 0); | 1624 | f2fs_put_page(node_page, 0); |
1625 | return err; | ||
1619 | } | 1626 | } |
1620 | 1627 | ||
1621 | static int f2fs_write_node_page(struct page *page, | 1628 | static int f2fs_write_node_page(struct page *page, |
@@ -1630,13 +1637,13 @@ int f2fs_fsync_node_pages(struct f2fs_sb_info *sbi, struct inode *inode, | |||
1630 | unsigned int *seq_id) | 1637 | unsigned int *seq_id) |
1631 | { | 1638 | { |
1632 | pgoff_t index; | 1639 | pgoff_t index; |
1633 | pgoff_t last_idx = ULONG_MAX; | ||
1634 | struct pagevec pvec; | 1640 | struct pagevec pvec; |
1635 | int ret = 0; | 1641 | int ret = 0; |
1636 | struct page *last_page = NULL; | 1642 | struct page *last_page = NULL; |
1637 | bool marked = false; | 1643 | bool marked = false; |
1638 | nid_t ino = inode->i_ino; | 1644 | nid_t ino = inode->i_ino; |
1639 | int nr_pages; | 1645 | int nr_pages; |
1646 | int nwritten = 0; | ||
1640 | 1647 | ||
1641 | if (atomic) { | 1648 | if (atomic) { |
1642 | last_page = last_fsync_dnode(sbi, ino); | 1649 | last_page = last_fsync_dnode(sbi, ino); |
@@ -1714,7 +1721,7 @@ continue_unlock: | |||
1714 | f2fs_put_page(last_page, 0); | 1721 | f2fs_put_page(last_page, 0); |
1715 | break; | 1722 | break; |
1716 | } else if (submitted) { | 1723 | } else if (submitted) { |
1717 | last_idx = page->index; | 1724 | nwritten++; |
1718 | } | 1725 | } |
1719 | 1726 | ||
1720 | if (page == last_page) { | 1727 | if (page == last_page) { |
@@ -1740,8 +1747,8 @@ continue_unlock: | |||
1740 | goto retry; | 1747 | goto retry; |
1741 | } | 1748 | } |
1742 | out: | 1749 | out: |
1743 | if (last_idx != ULONG_MAX) | 1750 | if (nwritten) |
1744 | f2fs_submit_merged_write_cond(sbi, NULL, ino, last_idx, NODE); | 1751 | f2fs_submit_merged_write_cond(sbi, NULL, NULL, ino, NODE); |
1745 | return ret ? -EIO: 0; | 1752 | return ret ? -EIO: 0; |
1746 | } | 1753 | } |
1747 | 1754 | ||
@@ -2268,15 +2275,19 @@ static int __f2fs_build_free_nids(struct f2fs_sb_info *sbi, | |||
2268 | nm_i->nat_block_bitmap)) { | 2275 | nm_i->nat_block_bitmap)) { |
2269 | struct page *page = get_current_nat_page(sbi, nid); | 2276 | struct page *page = get_current_nat_page(sbi, nid); |
2270 | 2277 | ||
2271 | ret = scan_nat_page(sbi, page, nid); | 2278 | if (IS_ERR(page)) { |
2272 | f2fs_put_page(page, 1); | 2279 | ret = PTR_ERR(page); |
2280 | } else { | ||
2281 | ret = scan_nat_page(sbi, page, nid); | ||
2282 | f2fs_put_page(page, 1); | ||
2283 | } | ||
2273 | 2284 | ||
2274 | if (ret) { | 2285 | if (ret) { |
2275 | up_read(&nm_i->nat_tree_lock); | 2286 | up_read(&nm_i->nat_tree_lock); |
2276 | f2fs_bug_on(sbi, !mount); | 2287 | f2fs_bug_on(sbi, !mount); |
2277 | f2fs_msg(sbi->sb, KERN_ERR, | 2288 | f2fs_msg(sbi->sb, KERN_ERR, |
2278 | "NAT is corrupt, run fsck to fix it"); | 2289 | "NAT is corrupt, run fsck to fix it"); |
2279 | return -EINVAL; | 2290 | return ret; |
2280 | } | 2291 | } |
2281 | } | 2292 | } |
2282 | 2293 | ||
@@ -2353,8 +2364,9 @@ retry: | |||
2353 | spin_unlock(&nm_i->nid_list_lock); | 2364 | spin_unlock(&nm_i->nid_list_lock); |
2354 | 2365 | ||
2355 | /* Let's scan nat pages and its caches to get free nids */ | 2366 | /* Let's scan nat pages and its caches to get free nids */ |
2356 | f2fs_build_free_nids(sbi, true, false); | 2367 | if (!f2fs_build_free_nids(sbi, true, false)) |
2357 | goto retry; | 2368 | goto retry; |
2369 | return false; | ||
2358 | } | 2370 | } |
2359 | 2371 | ||
2360 | /* | 2372 | /* |
@@ -2537,7 +2549,7 @@ retry: | |||
2537 | if (!PageUptodate(ipage)) | 2549 | if (!PageUptodate(ipage)) |
2538 | SetPageUptodate(ipage); | 2550 | SetPageUptodate(ipage); |
2539 | fill_node_footer(ipage, ino, ino, 0, true); | 2551 | fill_node_footer(ipage, ino, ino, 0, true); |
2540 | set_cold_node(page, false); | 2552 | set_cold_node(ipage, false); |
2541 | 2553 | ||
2542 | src = F2FS_INODE(page); | 2554 | src = F2FS_INODE(page); |
2543 | dst = F2FS_INODE(ipage); | 2555 | dst = F2FS_INODE(ipage); |
@@ -2560,6 +2572,13 @@ retry: | |||
2560 | F2FS_FITS_IN_INODE(src, le16_to_cpu(src->i_extra_isize), | 2572 | F2FS_FITS_IN_INODE(src, le16_to_cpu(src->i_extra_isize), |
2561 | i_projid)) | 2573 | i_projid)) |
2562 | dst->i_projid = src->i_projid; | 2574 | dst->i_projid = src->i_projid; |
2575 | |||
2576 | if (f2fs_sb_has_inode_crtime(sbi->sb) && | ||
2577 | F2FS_FITS_IN_INODE(src, le16_to_cpu(src->i_extra_isize), | ||
2578 | i_crtime_nsec)) { | ||
2579 | dst->i_crtime = src->i_crtime; | ||
2580 | dst->i_crtime_nsec = src->i_crtime_nsec; | ||
2581 | } | ||
2563 | } | 2582 | } |
2564 | 2583 | ||
2565 | new_ni = old_ni; | 2584 | new_ni = old_ni; |
@@ -2703,7 +2722,7 @@ static void __update_nat_bits(struct f2fs_sb_info *sbi, nid_t start_nid, | |||
2703 | __clear_bit_le(nat_index, nm_i->full_nat_bits); | 2722 | __clear_bit_le(nat_index, nm_i->full_nat_bits); |
2704 | } | 2723 | } |
2705 | 2724 | ||
2706 | static void __flush_nat_entry_set(struct f2fs_sb_info *sbi, | 2725 | static int __flush_nat_entry_set(struct f2fs_sb_info *sbi, |
2707 | struct nat_entry_set *set, struct cp_control *cpc) | 2726 | struct nat_entry_set *set, struct cp_control *cpc) |
2708 | { | 2727 | { |
2709 | struct curseg_info *curseg = CURSEG_I(sbi, CURSEG_HOT_DATA); | 2728 | struct curseg_info *curseg = CURSEG_I(sbi, CURSEG_HOT_DATA); |
@@ -2727,6 +2746,9 @@ static void __flush_nat_entry_set(struct f2fs_sb_info *sbi, | |||
2727 | down_write(&curseg->journal_rwsem); | 2746 | down_write(&curseg->journal_rwsem); |
2728 | } else { | 2747 | } else { |
2729 | page = get_next_nat_page(sbi, start_nid); | 2748 | page = get_next_nat_page(sbi, start_nid); |
2749 | if (IS_ERR(page)) | ||
2750 | return PTR_ERR(page); | ||
2751 | |||
2730 | nat_blk = page_address(page); | 2752 | nat_blk = page_address(page); |
2731 | f2fs_bug_on(sbi, !nat_blk); | 2753 | f2fs_bug_on(sbi, !nat_blk); |
2732 | } | 2754 | } |
@@ -2772,12 +2794,13 @@ static void __flush_nat_entry_set(struct f2fs_sb_info *sbi, | |||
2772 | radix_tree_delete(&NM_I(sbi)->nat_set_root, set->set); | 2794 | radix_tree_delete(&NM_I(sbi)->nat_set_root, set->set); |
2773 | kmem_cache_free(nat_entry_set_slab, set); | 2795 | kmem_cache_free(nat_entry_set_slab, set); |
2774 | } | 2796 | } |
2797 | return 0; | ||
2775 | } | 2798 | } |
2776 | 2799 | ||
2777 | /* | 2800 | /* |
2778 | * This function is called during the checkpointing process. | 2801 | * This function is called during the checkpointing process. |
2779 | */ | 2802 | */ |
2780 | void f2fs_flush_nat_entries(struct f2fs_sb_info *sbi, struct cp_control *cpc) | 2803 | int f2fs_flush_nat_entries(struct f2fs_sb_info *sbi, struct cp_control *cpc) |
2781 | { | 2804 | { |
2782 | struct f2fs_nm_info *nm_i = NM_I(sbi); | 2805 | struct f2fs_nm_info *nm_i = NM_I(sbi); |
2783 | struct curseg_info *curseg = CURSEG_I(sbi, CURSEG_HOT_DATA); | 2806 | struct curseg_info *curseg = CURSEG_I(sbi, CURSEG_HOT_DATA); |
@@ -2787,6 +2810,7 @@ void f2fs_flush_nat_entries(struct f2fs_sb_info *sbi, struct cp_control *cpc) | |||
2787 | unsigned int found; | 2810 | unsigned int found; |
2788 | nid_t set_idx = 0; | 2811 | nid_t set_idx = 0; |
2789 | LIST_HEAD(sets); | 2812 | LIST_HEAD(sets); |
2813 | int err = 0; | ||
2790 | 2814 | ||
2791 | /* during unmount, let's flush nat_bits before checking dirty_nat_cnt */ | 2815 | /* during unmount, let's flush nat_bits before checking dirty_nat_cnt */ |
2792 | if (enabled_nat_bits(sbi, cpc)) { | 2816 | if (enabled_nat_bits(sbi, cpc)) { |
@@ -2796,7 +2820,7 @@ void f2fs_flush_nat_entries(struct f2fs_sb_info *sbi, struct cp_control *cpc) | |||
2796 | } | 2820 | } |
2797 | 2821 | ||
2798 | if (!nm_i->dirty_nat_cnt) | 2822 | if (!nm_i->dirty_nat_cnt) |
2799 | return; | 2823 | return 0; |
2800 | 2824 | ||
2801 | down_write(&nm_i->nat_tree_lock); | 2825 | down_write(&nm_i->nat_tree_lock); |
2802 | 2826 | ||
@@ -2819,11 +2843,16 @@ void f2fs_flush_nat_entries(struct f2fs_sb_info *sbi, struct cp_control *cpc) | |||
2819 | } | 2843 | } |
2820 | 2844 | ||
2821 | /* flush dirty nats in nat entry set */ | 2845 | /* flush dirty nats in nat entry set */ |
2822 | list_for_each_entry_safe(set, tmp, &sets, set_list) | 2846 | list_for_each_entry_safe(set, tmp, &sets, set_list) { |
2823 | __flush_nat_entry_set(sbi, set, cpc); | 2847 | err = __flush_nat_entry_set(sbi, set, cpc); |
2848 | if (err) | ||
2849 | break; | ||
2850 | } | ||
2824 | 2851 | ||
2825 | up_write(&nm_i->nat_tree_lock); | 2852 | up_write(&nm_i->nat_tree_lock); |
2826 | /* Allow dirty nats by node block allocation in write_begin */ | 2853 | /* Allow dirty nats by node block allocation in write_begin */ |
2854 | |||
2855 | return err; | ||
2827 | } | 2856 | } |
2828 | 2857 | ||
2829 | static int __get_nat_bitmaps(struct f2fs_sb_info *sbi) | 2858 | static int __get_nat_bitmaps(struct f2fs_sb_info *sbi) |
@@ -2850,10 +2879,8 @@ static int __get_nat_bitmaps(struct f2fs_sb_info *sbi) | |||
2850 | struct page *page; | 2879 | struct page *page; |
2851 | 2880 | ||
2852 | page = f2fs_get_meta_page(sbi, nat_bits_addr++); | 2881 | page = f2fs_get_meta_page(sbi, nat_bits_addr++); |
2853 | if (IS_ERR(page)) { | 2882 | if (IS_ERR(page)) |
2854 | disable_nat_bits(sbi, true); | ||
2855 | return PTR_ERR(page); | 2883 | return PTR_ERR(page); |
2856 | } | ||
2857 | 2884 | ||
2858 | memcpy(nm_i->nat_bits + (i << F2FS_BLKSIZE_BITS), | 2885 | memcpy(nm_i->nat_bits + (i << F2FS_BLKSIZE_BITS), |
2859 | page_address(page), F2FS_BLKSIZE); | 2886 | page_address(page), F2FS_BLKSIZE); |
diff --git a/fs/f2fs/node.h b/fs/f2fs/node.h index 0f4db7a61254..1c73d879a9bc 100644 --- a/fs/f2fs/node.h +++ b/fs/f2fs/node.h | |||
@@ -1,12 +1,9 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
1 | /* | 2 | /* |
2 | * fs/f2fs/node.h | 3 | * fs/f2fs/node.h |
3 | * | 4 | * |
4 | * Copyright (c) 2012 Samsung Electronics Co., Ltd. | 5 | * Copyright (c) 2012 Samsung Electronics Co., Ltd. |
5 | * http://www.samsung.com/ | 6 | * http://www.samsung.com/ |
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | */ | 7 | */ |
11 | /* start node id of a node block dedicated to the given node id */ | 8 | /* start node id of a node block dedicated to the given node id */ |
12 | #define START_NID(nid) (((nid) / NAT_ENTRY_PER_BLOCK) * NAT_ENTRY_PER_BLOCK) | 9 | #define START_NID(nid) (((nid) / NAT_ENTRY_PER_BLOCK) * NAT_ENTRY_PER_BLOCK) |
diff --git a/fs/f2fs/recovery.c b/fs/f2fs/recovery.c index 95511ed11a22..1dfb17f9f9ff 100644 --- a/fs/f2fs/recovery.c +++ b/fs/f2fs/recovery.c | |||
@@ -1,12 +1,9 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
1 | /* | 2 | /* |
2 | * fs/f2fs/recovery.c | 3 | * fs/f2fs/recovery.c |
3 | * | 4 | * |
4 | * Copyright (c) 2012 Samsung Electronics Co., Ltd. | 5 | * Copyright (c) 2012 Samsung Electronics Co., Ltd. |
5 | * http://www.samsung.com/ | 6 | * http://www.samsung.com/ |
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | */ | 7 | */ |
11 | #include <linux/fs.h> | 8 | #include <linux/fs.h> |
12 | #include <linux/f2fs_fs.h> | 9 | #include <linux/f2fs_fs.h> |
@@ -99,8 +96,12 @@ err_out: | |||
99 | return ERR_PTR(err); | 96 | return ERR_PTR(err); |
100 | } | 97 | } |
101 | 98 | ||
102 | static void del_fsync_inode(struct fsync_inode_entry *entry) | 99 | static void del_fsync_inode(struct fsync_inode_entry *entry, int drop) |
103 | { | 100 | { |
101 | if (drop) { | ||
102 | /* inode should not be recovered, drop it */ | ||
103 | f2fs_inode_synced(entry->inode); | ||
104 | } | ||
104 | iput(entry->inode); | 105 | iput(entry->inode); |
105 | list_del(&entry->list); | 106 | list_del(&entry->list); |
106 | kmem_cache_free(fsync_entry_slab, entry); | 107 | kmem_cache_free(fsync_entry_slab, entry); |
@@ -194,6 +195,33 @@ out: | |||
194 | return err; | 195 | return err; |
195 | } | 196 | } |
196 | 197 | ||
198 | static int recover_quota_data(struct inode *inode, struct page *page) | ||
199 | { | ||
200 | struct f2fs_inode *raw = F2FS_INODE(page); | ||
201 | struct iattr attr; | ||
202 | uid_t i_uid = le32_to_cpu(raw->i_uid); | ||
203 | gid_t i_gid = le32_to_cpu(raw->i_gid); | ||
204 | int err; | ||
205 | |||
206 | memset(&attr, 0, sizeof(attr)); | ||
207 | |||
208 | attr.ia_uid = make_kuid(inode->i_sb->s_user_ns, i_uid); | ||
209 | attr.ia_gid = make_kgid(inode->i_sb->s_user_ns, i_gid); | ||
210 | |||
211 | if (!uid_eq(attr.ia_uid, inode->i_uid)) | ||
212 | attr.ia_valid |= ATTR_UID; | ||
213 | if (!gid_eq(attr.ia_gid, inode->i_gid)) | ||
214 | attr.ia_valid |= ATTR_GID; | ||
215 | |||
216 | if (!attr.ia_valid) | ||
217 | return 0; | ||
218 | |||
219 | err = dquot_transfer(inode, &attr); | ||
220 | if (err) | ||
221 | set_sbi_flag(F2FS_I_SB(inode), SBI_QUOTA_NEED_REPAIR); | ||
222 | return err; | ||
223 | } | ||
224 | |||
197 | static void recover_inline_flags(struct inode *inode, struct f2fs_inode *ri) | 225 | static void recover_inline_flags(struct inode *inode, struct f2fs_inode *ri) |
198 | { | 226 | { |
199 | if (ri->i_inline & F2FS_PIN_FILE) | 227 | if (ri->i_inline & F2FS_PIN_FILE) |
@@ -206,12 +234,41 @@ static void recover_inline_flags(struct inode *inode, struct f2fs_inode *ri) | |||
206 | clear_inode_flag(inode, FI_DATA_EXIST); | 234 | clear_inode_flag(inode, FI_DATA_EXIST); |
207 | } | 235 | } |
208 | 236 | ||
209 | static void recover_inode(struct inode *inode, struct page *page) | 237 | static int recover_inode(struct inode *inode, struct page *page) |
210 | { | 238 | { |
211 | struct f2fs_inode *raw = F2FS_INODE(page); | 239 | struct f2fs_inode *raw = F2FS_INODE(page); |
212 | char *name; | 240 | char *name; |
241 | int err; | ||
213 | 242 | ||
214 | inode->i_mode = le16_to_cpu(raw->i_mode); | 243 | inode->i_mode = le16_to_cpu(raw->i_mode); |
244 | |||
245 | err = recover_quota_data(inode, page); | ||
246 | if (err) | ||
247 | return err; | ||
248 | |||
249 | i_uid_write(inode, le32_to_cpu(raw->i_uid)); | ||
250 | i_gid_write(inode, le32_to_cpu(raw->i_gid)); | ||
251 | |||
252 | if (raw->i_inline & F2FS_EXTRA_ATTR) { | ||
253 | if (f2fs_sb_has_project_quota(F2FS_I_SB(inode)->sb) && | ||
254 | F2FS_FITS_IN_INODE(raw, le16_to_cpu(raw->i_extra_isize), | ||
255 | i_projid)) { | ||
256 | projid_t i_projid; | ||
257 | kprojid_t kprojid; | ||
258 | |||
259 | i_projid = (projid_t)le32_to_cpu(raw->i_projid); | ||
260 | kprojid = make_kprojid(&init_user_ns, i_projid); | ||
261 | |||
262 | if (!projid_eq(kprojid, F2FS_I(inode)->i_projid)) { | ||
263 | err = f2fs_transfer_project_quota(inode, | ||
264 | kprojid); | ||
265 | if (err) | ||
266 | return err; | ||
267 | F2FS_I(inode)->i_projid = kprojid; | ||
268 | } | ||
269 | } | ||
270 | } | ||
271 | |||
215 | f2fs_i_size_write(inode, le64_to_cpu(raw->i_size)); | 272 | f2fs_i_size_write(inode, le64_to_cpu(raw->i_size)); |
216 | inode->i_atime.tv_sec = le64_to_cpu(raw->i_atime); | 273 | inode->i_atime.tv_sec = le64_to_cpu(raw->i_atime); |
217 | inode->i_ctime.tv_sec = le64_to_cpu(raw->i_ctime); | 274 | inode->i_ctime.tv_sec = le64_to_cpu(raw->i_ctime); |
@@ -221,9 +278,15 @@ static void recover_inode(struct inode *inode, struct page *page) | |||
221 | inode->i_mtime.tv_nsec = le32_to_cpu(raw->i_mtime_nsec); | 278 | inode->i_mtime.tv_nsec = le32_to_cpu(raw->i_mtime_nsec); |
222 | 279 | ||
223 | F2FS_I(inode)->i_advise = raw->i_advise; | 280 | F2FS_I(inode)->i_advise = raw->i_advise; |
281 | F2FS_I(inode)->i_flags = le32_to_cpu(raw->i_flags); | ||
282 | f2fs_set_inode_flags(inode); | ||
283 | F2FS_I(inode)->i_gc_failures[GC_FAILURE_PIN] = | ||
284 | le16_to_cpu(raw->i_gc_failures); | ||
224 | 285 | ||
225 | recover_inline_flags(inode, raw); | 286 | recover_inline_flags(inode, raw); |
226 | 287 | ||
288 | f2fs_mark_inode_dirty_sync(inode, true); | ||
289 | |||
227 | if (file_enc_name(inode)) | 290 | if (file_enc_name(inode)) |
228 | name = "<encrypted>"; | 291 | name = "<encrypted>"; |
229 | else | 292 | else |
@@ -232,6 +295,7 @@ static void recover_inode(struct inode *inode, struct page *page) | |||
232 | f2fs_msg(inode->i_sb, KERN_NOTICE, | 295 | f2fs_msg(inode->i_sb, KERN_NOTICE, |
233 | "recover_inode: ino = %x, name = %s, inline = %x", | 296 | "recover_inode: ino = %x, name = %s, inline = %x", |
234 | ino_of_node(page), name, raw->i_inline); | 297 | ino_of_node(page), name, raw->i_inline); |
298 | return 0; | ||
235 | } | 299 | } |
236 | 300 | ||
237 | static int find_fsync_dnodes(struct f2fs_sb_info *sbi, struct list_head *head, | 301 | static int find_fsync_dnodes(struct f2fs_sb_info *sbi, struct list_head *head, |
@@ -320,12 +384,12 @@ next: | |||
320 | return err; | 384 | return err; |
321 | } | 385 | } |
322 | 386 | ||
323 | static void destroy_fsync_dnodes(struct list_head *head) | 387 | static void destroy_fsync_dnodes(struct list_head *head, int drop) |
324 | { | 388 | { |
325 | struct fsync_inode_entry *entry, *tmp; | 389 | struct fsync_inode_entry *entry, *tmp; |
326 | 390 | ||
327 | list_for_each_entry_safe(entry, tmp, head, list) | 391 | list_for_each_entry_safe(entry, tmp, head, list) |
328 | del_fsync_inode(entry); | 392 | del_fsync_inode(entry, drop); |
329 | } | 393 | } |
330 | 394 | ||
331 | static int check_index_in_prev_nodes(struct f2fs_sb_info *sbi, | 395 | static int check_index_in_prev_nodes(struct f2fs_sb_info *sbi, |
@@ -358,6 +422,8 @@ static int check_index_in_prev_nodes(struct f2fs_sb_info *sbi, | |||
358 | } | 422 | } |
359 | 423 | ||
360 | sum_page = f2fs_get_sum_page(sbi, segno); | 424 | sum_page = f2fs_get_sum_page(sbi, segno); |
425 | if (IS_ERR(sum_page)) | ||
426 | return PTR_ERR(sum_page); | ||
361 | sum_node = (struct f2fs_summary_block *)page_address(sum_page); | 427 | sum_node = (struct f2fs_summary_block *)page_address(sum_page); |
362 | sum = sum_node->entries[blkoff]; | 428 | sum = sum_node->entries[blkoff]; |
363 | f2fs_put_page(sum_page, 1); | 429 | f2fs_put_page(sum_page, 1); |
@@ -560,7 +626,7 @@ out: | |||
560 | } | 626 | } |
561 | 627 | ||
562 | static int recover_data(struct f2fs_sb_info *sbi, struct list_head *inode_list, | 628 | static int recover_data(struct f2fs_sb_info *sbi, struct list_head *inode_list, |
563 | struct list_head *dir_list) | 629 | struct list_head *tmp_inode_list, struct list_head *dir_list) |
564 | { | 630 | { |
565 | struct curseg_info *curseg; | 631 | struct curseg_info *curseg; |
566 | struct page *page = NULL; | 632 | struct page *page = NULL; |
@@ -598,8 +664,11 @@ static int recover_data(struct f2fs_sb_info *sbi, struct list_head *inode_list, | |||
598 | * In this case, we can lose the latest inode(x). | 664 | * In this case, we can lose the latest inode(x). |
599 | * So, call recover_inode for the inode update. | 665 | * So, call recover_inode for the inode update. |
600 | */ | 666 | */ |
601 | if (IS_INODE(page)) | 667 | if (IS_INODE(page)) { |
602 | recover_inode(entry->inode, page); | 668 | err = recover_inode(entry->inode, page); |
669 | if (err) | ||
670 | break; | ||
671 | } | ||
603 | if (entry->last_dentry == blkaddr) { | 672 | if (entry->last_dentry == blkaddr) { |
604 | err = recover_dentry(entry->inode, page, dir_list); | 673 | err = recover_dentry(entry->inode, page, dir_list); |
605 | if (err) { | 674 | if (err) { |
@@ -614,7 +683,7 @@ static int recover_data(struct f2fs_sb_info *sbi, struct list_head *inode_list, | |||
614 | } | 683 | } |
615 | 684 | ||
616 | if (entry->blkaddr == blkaddr) | 685 | if (entry->blkaddr == blkaddr) |
617 | del_fsync_inode(entry); | 686 | list_move_tail(&entry->list, tmp_inode_list); |
618 | next: | 687 | next: |
619 | /* check next segment */ | 688 | /* check next segment */ |
620 | blkaddr = next_blkaddr_of_node(page); | 689 | blkaddr = next_blkaddr_of_node(page); |
@@ -627,7 +696,7 @@ next: | |||
627 | 696 | ||
628 | int f2fs_recover_fsync_data(struct f2fs_sb_info *sbi, bool check_only) | 697 | int f2fs_recover_fsync_data(struct f2fs_sb_info *sbi, bool check_only) |
629 | { | 698 | { |
630 | struct list_head inode_list; | 699 | struct list_head inode_list, tmp_inode_list; |
631 | struct list_head dir_list; | 700 | struct list_head dir_list; |
632 | int err; | 701 | int err; |
633 | int ret = 0; | 702 | int ret = 0; |
@@ -658,6 +727,7 @@ int f2fs_recover_fsync_data(struct f2fs_sb_info *sbi, bool check_only) | |||
658 | } | 727 | } |
659 | 728 | ||
660 | INIT_LIST_HEAD(&inode_list); | 729 | INIT_LIST_HEAD(&inode_list); |
730 | INIT_LIST_HEAD(&tmp_inode_list); | ||
661 | INIT_LIST_HEAD(&dir_list); | 731 | INIT_LIST_HEAD(&dir_list); |
662 | 732 | ||
663 | /* prevent checkpoint */ | 733 | /* prevent checkpoint */ |
@@ -676,11 +746,16 @@ int f2fs_recover_fsync_data(struct f2fs_sb_info *sbi, bool check_only) | |||
676 | need_writecp = true; | 746 | need_writecp = true; |
677 | 747 | ||
678 | /* step #2: recover data */ | 748 | /* step #2: recover data */ |
679 | err = recover_data(sbi, &inode_list, &dir_list); | 749 | err = recover_data(sbi, &inode_list, &tmp_inode_list, &dir_list); |
680 | if (!err) | 750 | if (!err) |
681 | f2fs_bug_on(sbi, !list_empty(&inode_list)); | 751 | f2fs_bug_on(sbi, !list_empty(&inode_list)); |
752 | else { | ||
753 | /* restore s_flags to let iput() trash data */ | ||
754 | sbi->sb->s_flags = s_flags; | ||
755 | } | ||
682 | skip: | 756 | skip: |
683 | destroy_fsync_dnodes(&inode_list); | 757 | destroy_fsync_dnodes(&inode_list, err); |
758 | destroy_fsync_dnodes(&tmp_inode_list, err); | ||
684 | 759 | ||
685 | /* truncate meta pages to be used by the recovery */ | 760 | /* truncate meta pages to be used by the recovery */ |
686 | truncate_inode_pages_range(META_MAPPING(sbi), | 761 | truncate_inode_pages_range(META_MAPPING(sbi), |
@@ -689,19 +764,23 @@ skip: | |||
689 | if (err) { | 764 | if (err) { |
690 | truncate_inode_pages_final(NODE_MAPPING(sbi)); | 765 | truncate_inode_pages_final(NODE_MAPPING(sbi)); |
691 | truncate_inode_pages_final(META_MAPPING(sbi)); | 766 | truncate_inode_pages_final(META_MAPPING(sbi)); |
767 | } else { | ||
768 | clear_sbi_flag(sbi, SBI_POR_DOING); | ||
692 | } | 769 | } |
693 | |||
694 | clear_sbi_flag(sbi, SBI_POR_DOING); | ||
695 | mutex_unlock(&sbi->cp_mutex); | 770 | mutex_unlock(&sbi->cp_mutex); |
696 | 771 | ||
697 | /* let's drop all the directory inodes for clean checkpoint */ | 772 | /* let's drop all the directory inodes for clean checkpoint */ |
698 | destroy_fsync_dnodes(&dir_list); | 773 | destroy_fsync_dnodes(&dir_list, err); |
699 | 774 | ||
700 | if (!err && need_writecp) { | 775 | if (need_writecp) { |
701 | struct cp_control cpc = { | 776 | set_sbi_flag(sbi, SBI_IS_RECOVERED); |
702 | .reason = CP_RECOVERY, | 777 | |
703 | }; | 778 | if (!err) { |
704 | err = f2fs_write_checkpoint(sbi, &cpc); | 779 | struct cp_control cpc = { |
780 | .reason = CP_RECOVERY, | ||
781 | }; | ||
782 | err = f2fs_write_checkpoint(sbi, &cpc); | ||
783 | } | ||
705 | } | 784 | } |
706 | 785 | ||
707 | kmem_cache_destroy(fsync_entry_slab); | 786 | kmem_cache_destroy(fsync_entry_slab); |
diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c index 30779aaa9dba..6edcf8391dd3 100644 --- a/fs/f2fs/segment.c +++ b/fs/f2fs/segment.c | |||
@@ -1,12 +1,9 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
1 | /* | 2 | /* |
2 | * fs/f2fs/segment.c | 3 | * fs/f2fs/segment.c |
3 | * | 4 | * |
4 | * Copyright (c) 2012 Samsung Electronics Co., Ltd. | 5 | * Copyright (c) 2012 Samsung Electronics Co., Ltd. |
5 | * http://www.samsung.com/ | 6 | * http://www.samsung.com/ |
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | */ | 7 | */ |
11 | #include <linux/fs.h> | 8 | #include <linux/fs.h> |
12 | #include <linux/f2fs_fs.h> | 9 | #include <linux/f2fs_fs.h> |
@@ -179,6 +176,8 @@ bool f2fs_need_SSR(struct f2fs_sb_info *sbi) | |||
179 | return false; | 176 | return false; |
180 | if (sbi->gc_mode == GC_URGENT) | 177 | if (sbi->gc_mode == GC_URGENT) |
181 | return true; | 178 | return true; |
179 | if (unlikely(is_sbi_flag_set(sbi, SBI_CP_DISABLED))) | ||
180 | return true; | ||
182 | 181 | ||
183 | return free_sections(sbi) <= (node_secs + 2 * dent_secs + imeta_secs + | 182 | return free_sections(sbi) <= (node_secs + 2 * dent_secs + imeta_secs + |
184 | SM_I(sbi)->min_ssr_sections + reserved_sections(sbi)); | 183 | SM_I(sbi)->min_ssr_sections + reserved_sections(sbi)); |
@@ -267,8 +266,10 @@ retry: | |||
267 | } | 266 | } |
268 | next: | 267 | next: |
269 | /* we don't need to invalidate this in the sccessful status */ | 268 | /* we don't need to invalidate this in the sccessful status */ |
270 | if (drop || recover) | 269 | if (drop || recover) { |
271 | ClearPageUptodate(page); | 270 | ClearPageUptodate(page); |
271 | clear_cold_data(page); | ||
272 | } | ||
272 | set_page_private(page, 0); | 273 | set_page_private(page, 0); |
273 | ClearPagePrivate(page); | 274 | ClearPagePrivate(page); |
274 | f2fs_put_page(page, 1); | 275 | f2fs_put_page(page, 1); |
@@ -374,7 +375,7 @@ static int __f2fs_commit_inmem_pages(struct inode *inode) | |||
374 | .io_type = FS_DATA_IO, | 375 | .io_type = FS_DATA_IO, |
375 | }; | 376 | }; |
376 | struct list_head revoke_list; | 377 | struct list_head revoke_list; |
377 | pgoff_t last_idx = ULONG_MAX; | 378 | bool submit_bio = false; |
378 | int err = 0; | 379 | int err = 0; |
379 | 380 | ||
380 | INIT_LIST_HEAD(&revoke_list); | 381 | INIT_LIST_HEAD(&revoke_list); |
@@ -409,14 +410,14 @@ retry: | |||
409 | } | 410 | } |
410 | /* record old blkaddr for revoking */ | 411 | /* record old blkaddr for revoking */ |
411 | cur->old_addr = fio.old_blkaddr; | 412 | cur->old_addr = fio.old_blkaddr; |
412 | last_idx = page->index; | 413 | submit_bio = true; |
413 | } | 414 | } |
414 | unlock_page(page); | 415 | unlock_page(page); |
415 | list_move_tail(&cur->list, &revoke_list); | 416 | list_move_tail(&cur->list, &revoke_list); |
416 | } | 417 | } |
417 | 418 | ||
418 | if (last_idx != ULONG_MAX) | 419 | if (submit_bio) |
419 | f2fs_submit_merged_write_cond(sbi, inode, 0, last_idx, DATA); | 420 | f2fs_submit_merged_write_cond(sbi, inode, NULL, 0, DATA); |
420 | 421 | ||
421 | if (err) { | 422 | if (err) { |
422 | /* | 423 | /* |
@@ -483,6 +484,9 @@ void f2fs_balance_fs(struct f2fs_sb_info *sbi, bool need) | |||
483 | if (need && excess_cached_nats(sbi)) | 484 | if (need && excess_cached_nats(sbi)) |
484 | f2fs_balance_fs_bg(sbi); | 485 | f2fs_balance_fs_bg(sbi); |
485 | 486 | ||
487 | if (f2fs_is_checkpoint_ready(sbi)) | ||
488 | return; | ||
489 | |||
486 | /* | 490 | /* |
487 | * We should do GC or end up with checkpoint, if there are so many dirty | 491 | * We should do GC or end up with checkpoint, if there are so many dirty |
488 | * dir/node pages without enough free segments. | 492 | * dir/node pages without enough free segments. |
@@ -511,7 +515,7 @@ void f2fs_balance_fs_bg(struct f2fs_sb_info *sbi) | |||
511 | else | 515 | else |
512 | f2fs_build_free_nids(sbi, false, false); | 516 | f2fs_build_free_nids(sbi, false, false); |
513 | 517 | ||
514 | if (!is_idle(sbi) && | 518 | if (!is_idle(sbi, REQ_TIME) && |
515 | (!excess_dirty_nats(sbi) && !excess_dirty_nodes(sbi))) | 519 | (!excess_dirty_nats(sbi) && !excess_dirty_nodes(sbi))) |
516 | return; | 520 | return; |
517 | 521 | ||
@@ -799,7 +803,7 @@ static void __remove_dirty_segment(struct f2fs_sb_info *sbi, unsigned int segno, | |||
799 | static void locate_dirty_segment(struct f2fs_sb_info *sbi, unsigned int segno) | 803 | static void locate_dirty_segment(struct f2fs_sb_info *sbi, unsigned int segno) |
800 | { | 804 | { |
801 | struct dirty_seglist_info *dirty_i = DIRTY_I(sbi); | 805 | struct dirty_seglist_info *dirty_i = DIRTY_I(sbi); |
802 | unsigned short valid_blocks; | 806 | unsigned short valid_blocks, ckpt_valid_blocks; |
803 | 807 | ||
804 | if (segno == NULL_SEGNO || IS_CURSEG(sbi, segno)) | 808 | if (segno == NULL_SEGNO || IS_CURSEG(sbi, segno)) |
805 | return; | 809 | return; |
@@ -807,8 +811,10 @@ static void locate_dirty_segment(struct f2fs_sb_info *sbi, unsigned int segno) | |||
807 | mutex_lock(&dirty_i->seglist_lock); | 811 | mutex_lock(&dirty_i->seglist_lock); |
808 | 812 | ||
809 | valid_blocks = get_valid_blocks(sbi, segno, false); | 813 | valid_blocks = get_valid_blocks(sbi, segno, false); |
814 | ckpt_valid_blocks = get_ckpt_valid_blocks(sbi, segno); | ||
810 | 815 | ||
811 | if (valid_blocks == 0) { | 816 | if (valid_blocks == 0 && (!is_sbi_flag_set(sbi, SBI_CP_DISABLED) || |
817 | ckpt_valid_blocks == sbi->blocks_per_seg)) { | ||
812 | __locate_dirty_segment(sbi, segno, PRE); | 818 | __locate_dirty_segment(sbi, segno, PRE); |
813 | __remove_dirty_segment(sbi, segno, DIRTY); | 819 | __remove_dirty_segment(sbi, segno, DIRTY); |
814 | } else if (valid_blocks < sbi->blocks_per_seg) { | 820 | } else if (valid_blocks < sbi->blocks_per_seg) { |
@@ -821,6 +827,66 @@ static void locate_dirty_segment(struct f2fs_sb_info *sbi, unsigned int segno) | |||
821 | mutex_unlock(&dirty_i->seglist_lock); | 827 | mutex_unlock(&dirty_i->seglist_lock); |
822 | } | 828 | } |
823 | 829 | ||
830 | /* This moves currently empty dirty blocks to prefree. Must hold seglist_lock */ | ||
831 | void f2fs_dirty_to_prefree(struct f2fs_sb_info *sbi) | ||
832 | { | ||
833 | struct dirty_seglist_info *dirty_i = DIRTY_I(sbi); | ||
834 | unsigned int segno; | ||
835 | |||
836 | mutex_lock(&dirty_i->seglist_lock); | ||
837 | for_each_set_bit(segno, dirty_i->dirty_segmap[DIRTY], MAIN_SEGS(sbi)) { | ||
838 | if (get_valid_blocks(sbi, segno, false)) | ||
839 | continue; | ||
840 | if (IS_CURSEG(sbi, segno)) | ||
841 | continue; | ||
842 | __locate_dirty_segment(sbi, segno, PRE); | ||
843 | __remove_dirty_segment(sbi, segno, DIRTY); | ||
844 | } | ||
845 | mutex_unlock(&dirty_i->seglist_lock); | ||
846 | } | ||
847 | |||
848 | int f2fs_disable_cp_again(struct f2fs_sb_info *sbi) | ||
849 | { | ||
850 | struct dirty_seglist_info *dirty_i = DIRTY_I(sbi); | ||
851 | block_t ovp = overprovision_segments(sbi) << sbi->log_blocks_per_seg; | ||
852 | block_t holes[2] = {0, 0}; /* DATA and NODE */ | ||
853 | struct seg_entry *se; | ||
854 | unsigned int segno; | ||
855 | |||
856 | mutex_lock(&dirty_i->seglist_lock); | ||
857 | for_each_set_bit(segno, dirty_i->dirty_segmap[DIRTY], MAIN_SEGS(sbi)) { | ||
858 | se = get_seg_entry(sbi, segno); | ||
859 | if (IS_NODESEG(se->type)) | ||
860 | holes[NODE] += sbi->blocks_per_seg - se->valid_blocks; | ||
861 | else | ||
862 | holes[DATA] += sbi->blocks_per_seg - se->valid_blocks; | ||
863 | } | ||
864 | mutex_unlock(&dirty_i->seglist_lock); | ||
865 | |||
866 | if (holes[DATA] > ovp || holes[NODE] > ovp) | ||
867 | return -EAGAIN; | ||
868 | return 0; | ||
869 | } | ||
870 | |||
871 | /* This is only used by SBI_CP_DISABLED */ | ||
872 | static unsigned int get_free_segment(struct f2fs_sb_info *sbi) | ||
873 | { | ||
874 | struct dirty_seglist_info *dirty_i = DIRTY_I(sbi); | ||
875 | unsigned int segno = 0; | ||
876 | |||
877 | mutex_lock(&dirty_i->seglist_lock); | ||
878 | for_each_set_bit(segno, dirty_i->dirty_segmap[DIRTY], MAIN_SEGS(sbi)) { | ||
879 | if (get_valid_blocks(sbi, segno, false)) | ||
880 | continue; | ||
881 | if (get_ckpt_valid_blocks(sbi, segno)) | ||
882 | continue; | ||
883 | mutex_unlock(&dirty_i->seglist_lock); | ||
884 | return segno; | ||
885 | } | ||
886 | mutex_unlock(&dirty_i->seglist_lock); | ||
887 | return NULL_SEGNO; | ||
888 | } | ||
889 | |||
824 | static struct discard_cmd *__create_discard_cmd(struct f2fs_sb_info *sbi, | 890 | static struct discard_cmd *__create_discard_cmd(struct f2fs_sb_info *sbi, |
825 | struct block_device *bdev, block_t lstart, | 891 | struct block_device *bdev, block_t lstart, |
826 | block_t start, block_t len) | 892 | block_t start, block_t len) |
@@ -856,7 +922,8 @@ static struct discard_cmd *__create_discard_cmd(struct f2fs_sb_info *sbi, | |||
856 | static struct discard_cmd *__attach_discard_cmd(struct f2fs_sb_info *sbi, | 922 | static struct discard_cmd *__attach_discard_cmd(struct f2fs_sb_info *sbi, |
857 | struct block_device *bdev, block_t lstart, | 923 | struct block_device *bdev, block_t lstart, |
858 | block_t start, block_t len, | 924 | block_t start, block_t len, |
859 | struct rb_node *parent, struct rb_node **p) | 925 | struct rb_node *parent, struct rb_node **p, |
926 | bool leftmost) | ||
860 | { | 927 | { |
861 | struct discard_cmd_control *dcc = SM_I(sbi)->dcc_info; | 928 | struct discard_cmd_control *dcc = SM_I(sbi)->dcc_info; |
862 | struct discard_cmd *dc; | 929 | struct discard_cmd *dc; |
@@ -864,7 +931,7 @@ static struct discard_cmd *__attach_discard_cmd(struct f2fs_sb_info *sbi, | |||
864 | dc = __create_discard_cmd(sbi, bdev, lstart, start, len); | 931 | dc = __create_discard_cmd(sbi, bdev, lstart, start, len); |
865 | 932 | ||
866 | rb_link_node(&dc->rb_node, parent, p); | 933 | rb_link_node(&dc->rb_node, parent, p); |
867 | rb_insert_color(&dc->rb_node, &dcc->root); | 934 | rb_insert_color_cached(&dc->rb_node, &dcc->root, leftmost); |
868 | 935 | ||
869 | return dc; | 936 | return dc; |
870 | } | 937 | } |
@@ -876,7 +943,7 @@ static void __detach_discard_cmd(struct discard_cmd_control *dcc, | |||
876 | atomic_sub(dc->issuing, &dcc->issing_discard); | 943 | atomic_sub(dc->issuing, &dcc->issing_discard); |
877 | 944 | ||
878 | list_del(&dc->list); | 945 | list_del(&dc->list); |
879 | rb_erase(&dc->rb_node, &dcc->root); | 946 | rb_erase_cached(&dc->rb_node, &dcc->root); |
880 | dcc->undiscard_blks -= dc->len; | 947 | dcc->undiscard_blks -= dc->len; |
881 | 948 | ||
882 | kmem_cache_free(discard_cmd_slab, dc); | 949 | kmem_cache_free(discard_cmd_slab, dc); |
@@ -905,9 +972,9 @@ static void __remove_discard_cmd(struct f2fs_sb_info *sbi, | |||
905 | dc->error = 0; | 972 | dc->error = 0; |
906 | 973 | ||
907 | if (dc->error) | 974 | if (dc->error) |
908 | f2fs_msg(sbi->sb, KERN_INFO, | 975 | printk_ratelimited( |
909 | "Issue discard(%u, %u, %u) failed, ret: %d", | 976 | "%sF2FS-fs: Issue discard(%u, %u, %u) failed, ret: %d", |
910 | dc->lstart, dc->start, dc->len, dc->error); | 977 | KERN_INFO, dc->lstart, dc->start, dc->len, dc->error); |
911 | __detach_discard_cmd(dcc, dc); | 978 | __detach_discard_cmd(dcc, dc); |
912 | } | 979 | } |
913 | 980 | ||
@@ -1113,6 +1180,7 @@ static struct discard_cmd *__insert_discard_tree(struct f2fs_sb_info *sbi, | |||
1113 | struct rb_node **p; | 1180 | struct rb_node **p; |
1114 | struct rb_node *parent = NULL; | 1181 | struct rb_node *parent = NULL; |
1115 | struct discard_cmd *dc = NULL; | 1182 | struct discard_cmd *dc = NULL; |
1183 | bool leftmost = true; | ||
1116 | 1184 | ||
1117 | if (insert_p && insert_parent) { | 1185 | if (insert_p && insert_parent) { |
1118 | parent = insert_parent; | 1186 | parent = insert_parent; |
@@ -1120,9 +1188,11 @@ static struct discard_cmd *__insert_discard_tree(struct f2fs_sb_info *sbi, | |||
1120 | goto do_insert; | 1188 | goto do_insert; |
1121 | } | 1189 | } |
1122 | 1190 | ||
1123 | p = f2fs_lookup_rb_tree_for_insert(sbi, &dcc->root, &parent, lstart); | 1191 | p = f2fs_lookup_rb_tree_for_insert(sbi, &dcc->root, &parent, |
1192 | lstart, &leftmost); | ||
1124 | do_insert: | 1193 | do_insert: |
1125 | dc = __attach_discard_cmd(sbi, bdev, lstart, start, len, parent, p); | 1194 | dc = __attach_discard_cmd(sbi, bdev, lstart, start, len, parent, |
1195 | p, leftmost); | ||
1126 | if (!dc) | 1196 | if (!dc) |
1127 | return NULL; | 1197 | return NULL; |
1128 | 1198 | ||
@@ -1190,7 +1260,7 @@ static void __update_discard_tree_range(struct f2fs_sb_info *sbi, | |||
1190 | NULL, lstart, | 1260 | NULL, lstart, |
1191 | (struct rb_entry **)&prev_dc, | 1261 | (struct rb_entry **)&prev_dc, |
1192 | (struct rb_entry **)&next_dc, | 1262 | (struct rb_entry **)&next_dc, |
1193 | &insert_p, &insert_parent, true); | 1263 | &insert_p, &insert_parent, true, NULL); |
1194 | if (dc) | 1264 | if (dc) |
1195 | prev_dc = dc; | 1265 | prev_dc = dc; |
1196 | 1266 | ||
@@ -1298,7 +1368,7 @@ static unsigned int __issue_discard_cmd_orderly(struct f2fs_sb_info *sbi, | |||
1298 | NULL, pos, | 1368 | NULL, pos, |
1299 | (struct rb_entry **)&prev_dc, | 1369 | (struct rb_entry **)&prev_dc, |
1300 | (struct rb_entry **)&next_dc, | 1370 | (struct rb_entry **)&next_dc, |
1301 | &insert_p, &insert_parent, true); | 1371 | &insert_p, &insert_parent, true, NULL); |
1302 | if (!dc) | 1372 | if (!dc) |
1303 | dc = next_dc; | 1373 | dc = next_dc; |
1304 | 1374 | ||
@@ -1311,7 +1381,7 @@ static unsigned int __issue_discard_cmd_orderly(struct f2fs_sb_info *sbi, | |||
1311 | if (dc->state != D_PREP) | 1381 | if (dc->state != D_PREP) |
1312 | goto next; | 1382 | goto next; |
1313 | 1383 | ||
1314 | if (dpolicy->io_aware && !is_idle(sbi)) { | 1384 | if (dpolicy->io_aware && !is_idle(sbi, DISCARD_TIME)) { |
1315 | io_interrupted = true; | 1385 | io_interrupted = true; |
1316 | break; | 1386 | break; |
1317 | } | 1387 | } |
@@ -1371,7 +1441,7 @@ static int __issue_discard_cmd(struct f2fs_sb_info *sbi, | |||
1371 | f2fs_bug_on(sbi, dc->state != D_PREP); | 1441 | f2fs_bug_on(sbi, dc->state != D_PREP); |
1372 | 1442 | ||
1373 | if (dpolicy->io_aware && i < dpolicy->io_aware_gran && | 1443 | if (dpolicy->io_aware && i < dpolicy->io_aware_gran && |
1374 | !is_idle(sbi)) { | 1444 | !is_idle(sbi, DISCARD_TIME)) { |
1375 | io_interrupted = true; | 1445 | io_interrupted = true; |
1376 | break; | 1446 | break; |
1377 | } | 1447 | } |
@@ -1600,7 +1670,9 @@ static int issue_discard_thread(void *data) | |||
1600 | __wait_all_discard_cmd(sbi, &dpolicy); | 1670 | __wait_all_discard_cmd(sbi, &dpolicy); |
1601 | wait_ms = dpolicy.min_interval; | 1671 | wait_ms = dpolicy.min_interval; |
1602 | } else if (issued == -1){ | 1672 | } else if (issued == -1){ |
1603 | wait_ms = dpolicy.mid_interval; | 1673 | wait_ms = f2fs_time_to_wait(sbi, DISCARD_TIME); |
1674 | if (!wait_ms) | ||
1675 | wait_ms = dpolicy.mid_interval; | ||
1604 | } else { | 1676 | } else { |
1605 | wait_ms = dpolicy.max_interval; | 1677 | wait_ms = dpolicy.max_interval; |
1606 | } | 1678 | } |
@@ -1725,11 +1797,11 @@ static bool add_discard_addrs(struct f2fs_sb_info *sbi, struct cp_control *cpc, | |||
1725 | struct list_head *head = &SM_I(sbi)->dcc_info->entry_list; | 1797 | struct list_head *head = &SM_I(sbi)->dcc_info->entry_list; |
1726 | int i; | 1798 | int i; |
1727 | 1799 | ||
1728 | if (se->valid_blocks == max_blocks || !f2fs_discard_en(sbi)) | 1800 | if (se->valid_blocks == max_blocks || !f2fs_hw_support_discard(sbi)) |
1729 | return false; | 1801 | return false; |
1730 | 1802 | ||
1731 | if (!force) { | 1803 | if (!force) { |
1732 | if (!test_opt(sbi, DISCARD) || !se->valid_blocks || | 1804 | if (!f2fs_realtime_discard_enable(sbi) || !se->valid_blocks || |
1733 | SM_I(sbi)->dcc_info->nr_discards >= | 1805 | SM_I(sbi)->dcc_info->nr_discards >= |
1734 | SM_I(sbi)->dcc_info->max_discards) | 1806 | SM_I(sbi)->dcc_info->max_discards) |
1735 | return false; | 1807 | return false; |
@@ -1835,7 +1907,7 @@ void f2fs_clear_prefree_segments(struct f2fs_sb_info *sbi, | |||
1835 | dirty_i->nr_dirty[PRE]--; | 1907 | dirty_i->nr_dirty[PRE]--; |
1836 | } | 1908 | } |
1837 | 1909 | ||
1838 | if (!test_opt(sbi, DISCARD)) | 1910 | if (!f2fs_realtime_discard_enable(sbi)) |
1839 | continue; | 1911 | continue; |
1840 | 1912 | ||
1841 | if (force && start >= cpc->trim_start && | 1913 | if (force && start >= cpc->trim_start && |
@@ -1928,7 +2000,7 @@ static int create_discard_cmd_control(struct f2fs_sb_info *sbi) | |||
1928 | dcc->max_discards = MAIN_SEGS(sbi) << sbi->log_blocks_per_seg; | 2000 | dcc->max_discards = MAIN_SEGS(sbi) << sbi->log_blocks_per_seg; |
1929 | dcc->undiscard_blks = 0; | 2001 | dcc->undiscard_blks = 0; |
1930 | dcc->next_pos = 0; | 2002 | dcc->next_pos = 0; |
1931 | dcc->root = RB_ROOT; | 2003 | dcc->root = RB_ROOT_CACHED; |
1932 | dcc->rbtree_check = false; | 2004 | dcc->rbtree_check = false; |
1933 | 2005 | ||
1934 | init_waitqueue_head(&dcc->discard_wait_queue); | 2006 | init_waitqueue_head(&dcc->discard_wait_queue); |
@@ -2025,12 +2097,12 @@ static void update_sit_entry(struct f2fs_sb_info *sbi, block_t blkaddr, int del) | |||
2025 | del = 0; | 2097 | del = 0; |
2026 | } | 2098 | } |
2027 | 2099 | ||
2028 | if (f2fs_discard_en(sbi) && | 2100 | if (!f2fs_test_and_set_bit(offset, se->discard_map)) |
2029 | !f2fs_test_and_set_bit(offset, se->discard_map)) | ||
2030 | sbi->discard_blks--; | 2101 | sbi->discard_blks--; |
2031 | 2102 | ||
2032 | /* don't overwrite by SSR to keep node chain */ | 2103 | /* don't overwrite by SSR to keep node chain */ |
2033 | if (IS_NODESEG(se->type)) { | 2104 | if (IS_NODESEG(se->type) && |
2105 | !is_sbi_flag_set(sbi, SBI_CP_DISABLED)) { | ||
2034 | if (!f2fs_test_and_set_bit(offset, se->ckpt_valid_map)) | 2106 | if (!f2fs_test_and_set_bit(offset, se->ckpt_valid_map)) |
2035 | se->ckpt_valid_blocks++; | 2107 | se->ckpt_valid_blocks++; |
2036 | } | 2108 | } |
@@ -2052,10 +2124,18 @@ static void update_sit_entry(struct f2fs_sb_info *sbi, block_t blkaddr, int del) | |||
2052 | f2fs_bug_on(sbi, 1); | 2124 | f2fs_bug_on(sbi, 1); |
2053 | se->valid_blocks++; | 2125 | se->valid_blocks++; |
2054 | del = 0; | 2126 | del = 0; |
2127 | } else if (unlikely(is_sbi_flag_set(sbi, SBI_CP_DISABLED))) { | ||
2128 | /* | ||
2129 | * If checkpoints are off, we must not reuse data that | ||
2130 | * was used in the previous checkpoint. If it was used | ||
2131 | * before, we must track that to know how much space we | ||
2132 | * really have. | ||
2133 | */ | ||
2134 | if (f2fs_test_bit(offset, se->ckpt_valid_map)) | ||
2135 | sbi->unusable_block_count++; | ||
2055 | } | 2136 | } |
2056 | 2137 | ||
2057 | if (f2fs_discard_en(sbi) && | 2138 | if (f2fs_test_and_clear_bit(offset, se->discard_map)) |
2058 | f2fs_test_and_clear_bit(offset, se->discard_map)) | ||
2059 | sbi->discard_blks++; | 2139 | sbi->discard_blks++; |
2060 | } | 2140 | } |
2061 | if (!f2fs_test_bit(offset, se->ckpt_valid_map)) | 2141 | if (!f2fs_test_bit(offset, se->ckpt_valid_map)) |
@@ -2335,6 +2415,9 @@ static unsigned int __get_next_segno(struct f2fs_sb_info *sbi, int type) | |||
2335 | if (sbi->segs_per_sec != 1) | 2415 | if (sbi->segs_per_sec != 1) |
2336 | return CURSEG_I(sbi, type)->segno; | 2416 | return CURSEG_I(sbi, type)->segno; |
2337 | 2417 | ||
2418 | if (unlikely(is_sbi_flag_set(sbi, SBI_CP_DISABLED))) | ||
2419 | return 0; | ||
2420 | |||
2338 | if (test_opt(sbi, NOHEAP) && | 2421 | if (test_opt(sbi, NOHEAP) && |
2339 | (type == CURSEG_HOT_DATA || IS_NODESEG(type))) | 2422 | (type == CURSEG_HOT_DATA || IS_NODESEG(type))) |
2340 | return 0; | 2423 | return 0; |
@@ -2432,6 +2515,7 @@ static void change_curseg(struct f2fs_sb_info *sbi, int type) | |||
2432 | __next_free_blkoff(sbi, curseg, 0); | 2515 | __next_free_blkoff(sbi, curseg, 0); |
2433 | 2516 | ||
2434 | sum_page = f2fs_get_sum_page(sbi, new_segno); | 2517 | sum_page = f2fs_get_sum_page(sbi, new_segno); |
2518 | f2fs_bug_on(sbi, IS_ERR(sum_page)); | ||
2435 | sum_node = (struct f2fs_summary_block *)page_address(sum_page); | 2519 | sum_node = (struct f2fs_summary_block *)page_address(sum_page); |
2436 | memcpy(curseg->sum_blk, sum_node, SUM_ENTRY_SIZE); | 2520 | memcpy(curseg->sum_blk, sum_node, SUM_ENTRY_SIZE); |
2437 | f2fs_put_page(sum_page, 1); | 2521 | f2fs_put_page(sum_page, 1); |
@@ -2478,6 +2562,15 @@ static int get_ssr_segment(struct f2fs_sb_info *sbi, int type) | |||
2478 | return 1; | 2562 | return 1; |
2479 | } | 2563 | } |
2480 | } | 2564 | } |
2565 | |||
2566 | /* find valid_blocks=0 in dirty list */ | ||
2567 | if (unlikely(is_sbi_flag_set(sbi, SBI_CP_DISABLED))) { | ||
2568 | segno = get_free_segment(sbi); | ||
2569 | if (segno != NULL_SEGNO) { | ||
2570 | curseg->next_segno = segno; | ||
2571 | return 1; | ||
2572 | } | ||
2573 | } | ||
2481 | return 0; | 2574 | return 0; |
2482 | } | 2575 | } |
2483 | 2576 | ||
@@ -2495,7 +2588,8 @@ static void allocate_segment_by_default(struct f2fs_sb_info *sbi, | |||
2495 | else if (!is_set_ckpt_flags(sbi, CP_CRC_RECOVERY_FLAG) && | 2588 | else if (!is_set_ckpt_flags(sbi, CP_CRC_RECOVERY_FLAG) && |
2496 | type == CURSEG_WARM_NODE) | 2589 | type == CURSEG_WARM_NODE) |
2497 | new_curseg(sbi, type, false); | 2590 | new_curseg(sbi, type, false); |
2498 | else if (curseg->alloc_type == LFS && is_next_segment_free(sbi, type)) | 2591 | else if (curseg->alloc_type == LFS && is_next_segment_free(sbi, type) && |
2592 | likely(!is_sbi_flag_set(sbi, SBI_CP_DISABLED))) | ||
2499 | new_curseg(sbi, type, false); | 2593 | new_curseg(sbi, type, false); |
2500 | else if (f2fs_need_SSR(sbi) && get_ssr_segment(sbi, type)) | 2594 | else if (f2fs_need_SSR(sbi) && get_ssr_segment(sbi, type)) |
2501 | change_curseg(sbi, type); | 2595 | change_curseg(sbi, type); |
@@ -2570,7 +2664,7 @@ next: | |||
2570 | NULL, start, | 2664 | NULL, start, |
2571 | (struct rb_entry **)&prev_dc, | 2665 | (struct rb_entry **)&prev_dc, |
2572 | (struct rb_entry **)&next_dc, | 2666 | (struct rb_entry **)&next_dc, |
2573 | &insert_p, &insert_parent, true); | 2667 | &insert_p, &insert_parent, true, NULL); |
2574 | if (!dc) | 2668 | if (!dc) |
2575 | dc = next_dc; | 2669 | dc = next_dc; |
2576 | 2670 | ||
@@ -2671,7 +2765,7 @@ int f2fs_trim_fs(struct f2fs_sb_info *sbi, struct fstrim_range *range) | |||
2671 | * discard option. User configuration looks like using runtime discard | 2765 | * discard option. User configuration looks like using runtime discard |
2672 | * or periodic fstrim instead of it. | 2766 | * or periodic fstrim instead of it. |
2673 | */ | 2767 | */ |
2674 | if (test_opt(sbi, DISCARD)) | 2768 | if (f2fs_realtime_discard_enable(sbi)) |
2675 | goto out; | 2769 | goto out; |
2676 | 2770 | ||
2677 | start_block = START_BLOCK(sbi, start_segno); | 2771 | start_block = START_BLOCK(sbi, start_segno); |
@@ -3020,6 +3114,7 @@ void f2fs_do_write_meta_page(struct f2fs_sb_info *sbi, struct page *page, | |||
3020 | ClearPageError(page); | 3114 | ClearPageError(page); |
3021 | f2fs_submit_page_write(&fio); | 3115 | f2fs_submit_page_write(&fio); |
3022 | 3116 | ||
3117 | stat_inc_meta_count(sbi, page->index); | ||
3023 | f2fs_update_iostat(sbi, io_type, F2FS_BLKSIZE); | 3118 | f2fs_update_iostat(sbi, io_type, F2FS_BLKSIZE); |
3024 | } | 3119 | } |
3025 | 3120 | ||
@@ -3182,8 +3277,7 @@ void f2fs_wait_on_page_writeback(struct page *page, | |||
3182 | if (PageWriteback(page)) { | 3277 | if (PageWriteback(page)) { |
3183 | struct f2fs_sb_info *sbi = F2FS_P_SB(page); | 3278 | struct f2fs_sb_info *sbi = F2FS_P_SB(page); |
3184 | 3279 | ||
3185 | f2fs_submit_merged_write_cond(sbi, page->mapping->host, | 3280 | f2fs_submit_merged_write_cond(sbi, NULL, page, 0, type); |
3186 | 0, page->index, type); | ||
3187 | if (ordered) | 3281 | if (ordered) |
3188 | wait_on_page_writeback(page); | 3282 | wait_on_page_writeback(page); |
3189 | else | 3283 | else |
@@ -3191,10 +3285,14 @@ void f2fs_wait_on_page_writeback(struct page *page, | |||
3191 | } | 3285 | } |
3192 | } | 3286 | } |
3193 | 3287 | ||
3194 | void f2fs_wait_on_block_writeback(struct f2fs_sb_info *sbi, block_t blkaddr) | 3288 | void f2fs_wait_on_block_writeback(struct inode *inode, block_t blkaddr) |
3195 | { | 3289 | { |
3290 | struct f2fs_sb_info *sbi = F2FS_I_SB(inode); | ||
3196 | struct page *cpage; | 3291 | struct page *cpage; |
3197 | 3292 | ||
3293 | if (!f2fs_post_read_required(inode)) | ||
3294 | return; | ||
3295 | |||
3198 | if (!is_valid_data_blkaddr(sbi, blkaddr)) | 3296 | if (!is_valid_data_blkaddr(sbi, blkaddr)) |
3199 | return; | 3297 | return; |
3200 | 3298 | ||
@@ -3205,6 +3303,15 @@ void f2fs_wait_on_block_writeback(struct f2fs_sb_info *sbi, block_t blkaddr) | |||
3205 | } | 3303 | } |
3206 | } | 3304 | } |
3207 | 3305 | ||
3306 | void f2fs_wait_on_block_writeback_range(struct inode *inode, block_t blkaddr, | ||
3307 | block_t len) | ||
3308 | { | ||
3309 | block_t i; | ||
3310 | |||
3311 | for (i = 0; i < len; i++) | ||
3312 | f2fs_wait_on_block_writeback(inode, blkaddr + i); | ||
3313 | } | ||
3314 | |||
3208 | static int read_compacted_summaries(struct f2fs_sb_info *sbi) | 3315 | static int read_compacted_summaries(struct f2fs_sb_info *sbi) |
3209 | { | 3316 | { |
3210 | struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi); | 3317 | struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi); |
@@ -3762,13 +3869,11 @@ static int build_sit_info(struct f2fs_sb_info *sbi) | |||
3762 | return -ENOMEM; | 3869 | return -ENOMEM; |
3763 | #endif | 3870 | #endif |
3764 | 3871 | ||
3765 | if (f2fs_discard_en(sbi)) { | 3872 | sit_i->sentries[start].discard_map |
3766 | sit_i->sentries[start].discard_map | 3873 | = f2fs_kzalloc(sbi, SIT_VBLOCK_MAP_SIZE, |
3767 | = f2fs_kzalloc(sbi, SIT_VBLOCK_MAP_SIZE, | 3874 | GFP_KERNEL); |
3768 | GFP_KERNEL); | 3875 | if (!sit_i->sentries[start].discard_map) |
3769 | if (!sit_i->sentries[start].discard_map) | 3876 | return -ENOMEM; |
3770 | return -ENOMEM; | ||
3771 | } | ||
3772 | } | 3877 | } |
3773 | 3878 | ||
3774 | sit_i->tmp_map = f2fs_kzalloc(sbi, SIT_VBLOCK_MAP_SIZE, GFP_KERNEL); | 3879 | sit_i->tmp_map = f2fs_kzalloc(sbi, SIT_VBLOCK_MAP_SIZE, GFP_KERNEL); |
@@ -3904,6 +4009,8 @@ static int build_sit_entries(struct f2fs_sb_info *sbi) | |||
3904 | 4009 | ||
3905 | se = &sit_i->sentries[start]; | 4010 | se = &sit_i->sentries[start]; |
3906 | page = get_current_sit_page(sbi, start); | 4011 | page = get_current_sit_page(sbi, start); |
4012 | if (IS_ERR(page)) | ||
4013 | return PTR_ERR(page); | ||
3907 | sit_blk = (struct f2fs_sit_block *)page_address(page); | 4014 | sit_blk = (struct f2fs_sit_block *)page_address(page); |
3908 | sit = sit_blk->entries[SIT_ENTRY_OFFSET(sit_i, start)]; | 4015 | sit = sit_blk->entries[SIT_ENTRY_OFFSET(sit_i, start)]; |
3909 | f2fs_put_page(page, 1); | 4016 | f2fs_put_page(page, 1); |
@@ -3916,18 +4023,16 @@ static int build_sit_entries(struct f2fs_sb_info *sbi) | |||
3916 | total_node_blocks += se->valid_blocks; | 4023 | total_node_blocks += se->valid_blocks; |
3917 | 4024 | ||
3918 | /* build discard map only one time */ | 4025 | /* build discard map only one time */ |
3919 | if (f2fs_discard_en(sbi)) { | 4026 | if (is_set_ckpt_flags(sbi, CP_TRIMMED_FLAG)) { |
3920 | if (is_set_ckpt_flags(sbi, CP_TRIMMED_FLAG)) { | 4027 | memset(se->discard_map, 0xff, |
3921 | memset(se->discard_map, 0xff, | 4028 | SIT_VBLOCK_MAP_SIZE); |
3922 | SIT_VBLOCK_MAP_SIZE); | 4029 | } else { |
3923 | } else { | 4030 | memcpy(se->discard_map, |
3924 | memcpy(se->discard_map, | 4031 | se->cur_valid_map, |
3925 | se->cur_valid_map, | 4032 | SIT_VBLOCK_MAP_SIZE); |
3926 | SIT_VBLOCK_MAP_SIZE); | 4033 | sbi->discard_blks += |
3927 | sbi->discard_blks += | 4034 | sbi->blocks_per_seg - |
3928 | sbi->blocks_per_seg - | 4035 | se->valid_blocks; |
3929 | se->valid_blocks; | ||
3930 | } | ||
3931 | } | 4036 | } |
3932 | 4037 | ||
3933 | if (sbi->segs_per_sec > 1) | 4038 | if (sbi->segs_per_sec > 1) |
@@ -3965,16 +4070,13 @@ static int build_sit_entries(struct f2fs_sb_info *sbi) | |||
3965 | if (IS_NODESEG(se->type)) | 4070 | if (IS_NODESEG(se->type)) |
3966 | total_node_blocks += se->valid_blocks; | 4071 | total_node_blocks += se->valid_blocks; |
3967 | 4072 | ||
3968 | if (f2fs_discard_en(sbi)) { | 4073 | if (is_set_ckpt_flags(sbi, CP_TRIMMED_FLAG)) { |
3969 | if (is_set_ckpt_flags(sbi, CP_TRIMMED_FLAG)) { | 4074 | memset(se->discard_map, 0xff, SIT_VBLOCK_MAP_SIZE); |
3970 | memset(se->discard_map, 0xff, | 4075 | } else { |
3971 | SIT_VBLOCK_MAP_SIZE); | 4076 | memcpy(se->discard_map, se->cur_valid_map, |
3972 | } else { | 4077 | SIT_VBLOCK_MAP_SIZE); |
3973 | memcpy(se->discard_map, se->cur_valid_map, | 4078 | sbi->discard_blks += old_valid_blocks; |
3974 | SIT_VBLOCK_MAP_SIZE); | 4079 | sbi->discard_blks -= se->valid_blocks; |
3975 | sbi->discard_blks += old_valid_blocks; | ||
3976 | sbi->discard_blks -= se->valid_blocks; | ||
3977 | } | ||
3978 | } | 4080 | } |
3979 | 4081 | ||
3980 | if (sbi->segs_per_sec > 1) { | 4082 | if (sbi->segs_per_sec > 1) { |
diff --git a/fs/f2fs/segment.h b/fs/f2fs/segment.h index b3d9e317ff0c..ab3465faddf1 100644 --- a/fs/f2fs/segment.h +++ b/fs/f2fs/segment.h | |||
@@ -1,12 +1,9 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
1 | /* | 2 | /* |
2 | * fs/f2fs/segment.h | 3 | * fs/f2fs/segment.h |
3 | * | 4 | * |
4 | * Copyright (c) 2012 Samsung Electronics Co., Ltd. | 5 | * Copyright (c) 2012 Samsung Electronics Co., Ltd. |
5 | * http://www.samsung.com/ | 6 | * http://www.samsung.com/ |
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | */ | 7 | */ |
11 | #include <linux/blkdev.h> | 8 | #include <linux/blkdev.h> |
12 | #include <linux/backing-dev.h> | 9 | #include <linux/backing-dev.h> |
@@ -342,6 +339,12 @@ static inline unsigned int get_valid_blocks(struct f2fs_sb_info *sbi, | |||
342 | return get_seg_entry(sbi, segno)->valid_blocks; | 339 | return get_seg_entry(sbi, segno)->valid_blocks; |
343 | } | 340 | } |
344 | 341 | ||
342 | static inline unsigned int get_ckpt_valid_blocks(struct f2fs_sb_info *sbi, | ||
343 | unsigned int segno) | ||
344 | { | ||
345 | return get_seg_entry(sbi, segno)->ckpt_valid_blocks; | ||
346 | } | ||
347 | |||
345 | static inline void seg_info_from_raw_sit(struct seg_entry *se, | 348 | static inline void seg_info_from_raw_sit(struct seg_entry *se, |
346 | struct f2fs_sit_entry *rs) | 349 | struct f2fs_sit_entry *rs) |
347 | { | 350 | { |
@@ -579,6 +582,15 @@ static inline bool has_not_enough_free_secs(struct f2fs_sb_info *sbi, | |||
579 | reserved_sections(sbi) + needed); | 582 | reserved_sections(sbi) + needed); |
580 | } | 583 | } |
581 | 584 | ||
585 | static inline int f2fs_is_checkpoint_ready(struct f2fs_sb_info *sbi) | ||
586 | { | ||
587 | if (likely(!is_sbi_flag_set(sbi, SBI_CP_DISABLED))) | ||
588 | return 0; | ||
589 | if (likely(!has_not_enough_free_secs(sbi, 0, 0))) | ||
590 | return 0; | ||
591 | return -ENOSPC; | ||
592 | } | ||
593 | |||
582 | static inline bool excess_prefree_segs(struct f2fs_sb_info *sbi) | 594 | static inline bool excess_prefree_segs(struct f2fs_sb_info *sbi) |
583 | { | 595 | { |
584 | return prefree_segments(sbi) > SM_I(sbi)->rec_prefree_segments; | 596 | return prefree_segments(sbi) > SM_I(sbi)->rec_prefree_segments; |
diff --git a/fs/f2fs/shrinker.c b/fs/f2fs/shrinker.c index 36cfd816c160..9e13db994fdf 100644 --- a/fs/f2fs/shrinker.c +++ b/fs/f2fs/shrinker.c | |||
@@ -1,13 +1,10 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
1 | /* | 2 | /* |
2 | * f2fs shrinker support | 3 | * f2fs shrinker support |
3 | * the basic infra was copied from fs/ubifs/shrinker.c | 4 | * the basic infra was copied from fs/ubifs/shrinker.c |
4 | * | 5 | * |
5 | * Copyright (c) 2015 Motorola Mobility | 6 | * Copyright (c) 2015 Motorola Mobility |
6 | * Copyright (c) 2015 Jaegeuk Kim <jaegeuk@kernel.org> | 7 | * Copyright (c) 2015 Jaegeuk Kim <jaegeuk@kernel.org> |
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | */ | 8 | */ |
12 | #include <linux/fs.h> | 9 | #include <linux/fs.h> |
13 | #include <linux/f2fs_fs.h> | 10 | #include <linux/f2fs_fs.h> |
diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c index 896b885f504e..af58b2cc21b8 100644 --- a/fs/f2fs/super.c +++ b/fs/f2fs/super.c | |||
@@ -1,12 +1,9 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
1 | /* | 2 | /* |
2 | * fs/f2fs/super.c | 3 | * fs/f2fs/super.c |
3 | * | 4 | * |
4 | * Copyright (c) 2012 Samsung Electronics Co., Ltd. | 5 | * Copyright (c) 2012 Samsung Electronics Co., Ltd. |
5 | * http://www.samsung.com/ | 6 | * http://www.samsung.com/ |
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | */ | 7 | */ |
11 | #include <linux/module.h> | 8 | #include <linux/module.h> |
12 | #include <linux/init.h> | 9 | #include <linux/init.h> |
@@ -53,9 +50,10 @@ char *f2fs_fault_name[FAULT_MAX] = { | |||
53 | [FAULT_DIR_DEPTH] = "too big dir depth", | 50 | [FAULT_DIR_DEPTH] = "too big dir depth", |
54 | [FAULT_EVICT_INODE] = "evict_inode fail", | 51 | [FAULT_EVICT_INODE] = "evict_inode fail", |
55 | [FAULT_TRUNCATE] = "truncate fail", | 52 | [FAULT_TRUNCATE] = "truncate fail", |
56 | [FAULT_IO] = "IO error", | 53 | [FAULT_READ_IO] = "read IO error", |
57 | [FAULT_CHECKPOINT] = "checkpoint error", | 54 | [FAULT_CHECKPOINT] = "checkpoint error", |
58 | [FAULT_DISCARD] = "discard error", | 55 | [FAULT_DISCARD] = "discard error", |
56 | [FAULT_WRITE_IO] = "write IO error", | ||
59 | }; | 57 | }; |
60 | 58 | ||
61 | void f2fs_build_fault_attr(struct f2fs_sb_info *sbi, unsigned int rate, | 59 | void f2fs_build_fault_attr(struct f2fs_sb_info *sbi, unsigned int rate, |
@@ -138,6 +136,7 @@ enum { | |||
138 | Opt_alloc, | 136 | Opt_alloc, |
139 | Opt_fsync, | 137 | Opt_fsync, |
140 | Opt_test_dummy_encryption, | 138 | Opt_test_dummy_encryption, |
139 | Opt_checkpoint, | ||
141 | Opt_err, | 140 | Opt_err, |
142 | }; | 141 | }; |
143 | 142 | ||
@@ -196,6 +195,7 @@ static match_table_t f2fs_tokens = { | |||
196 | {Opt_alloc, "alloc_mode=%s"}, | 195 | {Opt_alloc, "alloc_mode=%s"}, |
197 | {Opt_fsync, "fsync_mode=%s"}, | 196 | {Opt_fsync, "fsync_mode=%s"}, |
198 | {Opt_test_dummy_encryption, "test_dummy_encryption"}, | 197 | {Opt_test_dummy_encryption, "test_dummy_encryption"}, |
198 | {Opt_checkpoint, "checkpoint=%s"}, | ||
199 | {Opt_err, NULL}, | 199 | {Opt_err, NULL}, |
200 | }; | 200 | }; |
201 | 201 | ||
@@ -207,7 +207,7 @@ void f2fs_msg(struct super_block *sb, const char *level, const char *fmt, ...) | |||
207 | va_start(args, fmt); | 207 | va_start(args, fmt); |
208 | vaf.fmt = fmt; | 208 | vaf.fmt = fmt; |
209 | vaf.va = &args; | 209 | vaf.va = &args; |
210 | printk_ratelimited("%sF2FS-fs (%s): %pV\n", level, sb->s_id, &vaf); | 210 | printk("%sF2FS-fs (%s): %pV\n", level, sb->s_id, &vaf); |
211 | va_end(args); | 211 | va_end(args); |
212 | } | 212 | } |
213 | 213 | ||
@@ -360,7 +360,6 @@ static int f2fs_check_quota_options(struct f2fs_sb_info *sbi) | |||
360 | static int parse_options(struct super_block *sb, char *options) | 360 | static int parse_options(struct super_block *sb, char *options) |
361 | { | 361 | { |
362 | struct f2fs_sb_info *sbi = F2FS_SB(sb); | 362 | struct f2fs_sb_info *sbi = F2FS_SB(sb); |
363 | struct request_queue *q; | ||
364 | substring_t args[MAX_OPT_ARGS]; | 363 | substring_t args[MAX_OPT_ARGS]; |
365 | char *p, *name; | 364 | char *p, *name; |
366 | int arg = 0; | 365 | int arg = 0; |
@@ -415,14 +414,7 @@ static int parse_options(struct super_block *sb, char *options) | |||
415 | return -EINVAL; | 414 | return -EINVAL; |
416 | break; | 415 | break; |
417 | case Opt_discard: | 416 | case Opt_discard: |
418 | q = bdev_get_queue(sb->s_bdev); | 417 | set_opt(sbi, DISCARD); |
419 | if (blk_queue_discard(q)) { | ||
420 | set_opt(sbi, DISCARD); | ||
421 | } else if (!f2fs_sb_has_blkzoned(sb)) { | ||
422 | f2fs_msg(sb, KERN_WARNING, | ||
423 | "mounting with \"discard\" option, but " | ||
424 | "the device does not support discard"); | ||
425 | } | ||
426 | break; | 418 | break; |
427 | case Opt_nodiscard: | 419 | case Opt_nodiscard: |
428 | if (f2fs_sb_has_blkzoned(sb)) { | 420 | if (f2fs_sb_has_blkzoned(sb)) { |
@@ -602,28 +594,31 @@ static int parse_options(struct super_block *sb, char *options) | |||
602 | } | 594 | } |
603 | F2FS_OPTION(sbi).write_io_size_bits = arg; | 595 | F2FS_OPTION(sbi).write_io_size_bits = arg; |
604 | break; | 596 | break; |
597 | #ifdef CONFIG_F2FS_FAULT_INJECTION | ||
605 | case Opt_fault_injection: | 598 | case Opt_fault_injection: |
606 | if (args->from && match_int(args, &arg)) | 599 | if (args->from && match_int(args, &arg)) |
607 | return -EINVAL; | 600 | return -EINVAL; |
608 | #ifdef CONFIG_F2FS_FAULT_INJECTION | ||
609 | f2fs_build_fault_attr(sbi, arg, F2FS_ALL_FAULT_TYPE); | 601 | f2fs_build_fault_attr(sbi, arg, F2FS_ALL_FAULT_TYPE); |
610 | set_opt(sbi, FAULT_INJECTION); | 602 | set_opt(sbi, FAULT_INJECTION); |
611 | #else | ||
612 | f2fs_msg(sb, KERN_INFO, | ||
613 | "FAULT_INJECTION was not selected"); | ||
614 | #endif | ||
615 | break; | 603 | break; |
604 | |||
616 | case Opt_fault_type: | 605 | case Opt_fault_type: |
617 | if (args->from && match_int(args, &arg)) | 606 | if (args->from && match_int(args, &arg)) |
618 | return -EINVAL; | 607 | return -EINVAL; |
619 | #ifdef CONFIG_F2FS_FAULT_INJECTION | ||
620 | f2fs_build_fault_attr(sbi, 0, arg); | 608 | f2fs_build_fault_attr(sbi, 0, arg); |
621 | set_opt(sbi, FAULT_INJECTION); | 609 | set_opt(sbi, FAULT_INJECTION); |
610 | break; | ||
622 | #else | 611 | #else |
612 | case Opt_fault_injection: | ||
623 | f2fs_msg(sb, KERN_INFO, | 613 | f2fs_msg(sb, KERN_INFO, |
624 | "FAULT_INJECTION was not selected"); | 614 | "fault_injection options not supported"); |
625 | #endif | 615 | break; |
616 | |||
617 | case Opt_fault_type: | ||
618 | f2fs_msg(sb, KERN_INFO, | ||
619 | "fault_type options not supported"); | ||
626 | break; | 620 | break; |
621 | #endif | ||
627 | case Opt_lazytime: | 622 | case Opt_lazytime: |
628 | sb->s_flags |= SB_LAZYTIME; | 623 | sb->s_flags |= SB_LAZYTIME; |
629 | break; | 624 | break; |
@@ -776,6 +771,23 @@ static int parse_options(struct super_block *sb, char *options) | |||
776 | "Test dummy encryption mount option ignored"); | 771 | "Test dummy encryption mount option ignored"); |
777 | #endif | 772 | #endif |
778 | break; | 773 | break; |
774 | case Opt_checkpoint: | ||
775 | name = match_strdup(&args[0]); | ||
776 | if (!name) | ||
777 | return -ENOMEM; | ||
778 | |||
779 | if (strlen(name) == 6 && | ||
780 | !strncmp(name, "enable", 6)) { | ||
781 | clear_opt(sbi, DISABLE_CHECKPOINT); | ||
782 | } else if (strlen(name) == 7 && | ||
783 | !strncmp(name, "disable", 7)) { | ||
784 | set_opt(sbi, DISABLE_CHECKPOINT); | ||
785 | } else { | ||
786 | kfree(name); | ||
787 | return -EINVAL; | ||
788 | } | ||
789 | kfree(name); | ||
790 | break; | ||
779 | default: | 791 | default: |
780 | f2fs_msg(sb, KERN_ERR, | 792 | f2fs_msg(sb, KERN_ERR, |
781 | "Unrecognized mount option \"%s\" or missing value", | 793 | "Unrecognized mount option \"%s\" or missing value", |
@@ -834,6 +846,12 @@ static int parse_options(struct super_block *sb, char *options) | |||
834 | } | 846 | } |
835 | } | 847 | } |
836 | 848 | ||
849 | if (test_opt(sbi, DISABLE_CHECKPOINT) && test_opt(sbi, LFS)) { | ||
850 | f2fs_msg(sb, KERN_ERR, | ||
851 | "LFS not compatible with checkpoint=disable\n"); | ||
852 | return -EINVAL; | ||
853 | } | ||
854 | |||
837 | /* Not pass down write hints if the number of active logs is lesser | 855 | /* Not pass down write hints if the number of active logs is lesser |
838 | * than NR_CURSEG_TYPE. | 856 | * than NR_CURSEG_TYPE. |
839 | */ | 857 | */ |
@@ -1021,8 +1039,8 @@ static void f2fs_put_super(struct super_block *sb) | |||
1021 | * But, the previous checkpoint was not done by umount, it needs to do | 1039 | * But, the previous checkpoint was not done by umount, it needs to do |
1022 | * clean checkpoint again. | 1040 | * clean checkpoint again. |
1023 | */ | 1041 | */ |
1024 | if (is_sbi_flag_set(sbi, SBI_IS_DIRTY) || | 1042 | if ((is_sbi_flag_set(sbi, SBI_IS_DIRTY) || |
1025 | !is_set_ckpt_flags(sbi, CP_UMOUNT_FLAG)) { | 1043 | !is_set_ckpt_flags(sbi, CP_UMOUNT_FLAG))) { |
1026 | struct cp_control cpc = { | 1044 | struct cp_control cpc = { |
1027 | .reason = CP_UMOUNT, | 1045 | .reason = CP_UMOUNT, |
1028 | }; | 1046 | }; |
@@ -1032,7 +1050,8 @@ static void f2fs_put_super(struct super_block *sb) | |||
1032 | /* be sure to wait for any on-going discard commands */ | 1050 | /* be sure to wait for any on-going discard commands */ |
1033 | dropped = f2fs_wait_discard_bios(sbi); | 1051 | dropped = f2fs_wait_discard_bios(sbi); |
1034 | 1052 | ||
1035 | if (f2fs_discard_en(sbi) && !sbi->discard_blks && !dropped) { | 1053 | if ((f2fs_hw_support_discard(sbi) || f2fs_hw_should_discard(sbi)) && |
1054 | !sbi->discard_blks && !dropped) { | ||
1036 | struct cp_control cpc = { | 1055 | struct cp_control cpc = { |
1037 | .reason = CP_UMOUNT | CP_TRIMMED, | 1056 | .reason = CP_UMOUNT | CP_TRIMMED, |
1038 | }; | 1057 | }; |
@@ -1093,6 +1112,8 @@ int f2fs_sync_fs(struct super_block *sb, int sync) | |||
1093 | 1112 | ||
1094 | if (unlikely(f2fs_cp_error(sbi))) | 1113 | if (unlikely(f2fs_cp_error(sbi))) |
1095 | return 0; | 1114 | return 0; |
1115 | if (unlikely(is_sbi_flag_set(sbi, SBI_CP_DISABLED))) | ||
1116 | return 0; | ||
1096 | 1117 | ||
1097 | trace_f2fs_sync_fs(sb, sync); | 1118 | trace_f2fs_sync_fs(sb, sync); |
1098 | 1119 | ||
@@ -1192,6 +1213,11 @@ static int f2fs_statfs(struct dentry *dentry, struct kstatfs *buf) | |||
1192 | buf->f_blocks = total_count - start_count; | 1213 | buf->f_blocks = total_count - start_count; |
1193 | buf->f_bfree = user_block_count - valid_user_blocks(sbi) - | 1214 | buf->f_bfree = user_block_count - valid_user_blocks(sbi) - |
1194 | sbi->current_reserved_blocks; | 1215 | sbi->current_reserved_blocks; |
1216 | if (unlikely(buf->f_bfree <= sbi->unusable_block_count)) | ||
1217 | buf->f_bfree = 0; | ||
1218 | else | ||
1219 | buf->f_bfree -= sbi->unusable_block_count; | ||
1220 | |||
1195 | if (buf->f_bfree > F2FS_OPTION(sbi).root_reserved_blocks) | 1221 | if (buf->f_bfree > F2FS_OPTION(sbi).root_reserved_blocks) |
1196 | buf->f_bavail = buf->f_bfree - | 1222 | buf->f_bavail = buf->f_bfree - |
1197 | F2FS_OPTION(sbi).root_reserved_blocks; | 1223 | F2FS_OPTION(sbi).root_reserved_blocks; |
@@ -1336,7 +1362,8 @@ static int f2fs_show_options(struct seq_file *seq, struct dentry *root) | |||
1336 | from_kgid_munged(&init_user_ns, | 1362 | from_kgid_munged(&init_user_ns, |
1337 | F2FS_OPTION(sbi).s_resgid)); | 1363 | F2FS_OPTION(sbi).s_resgid)); |
1338 | if (F2FS_IO_SIZE_BITS(sbi)) | 1364 | if (F2FS_IO_SIZE_BITS(sbi)) |
1339 | seq_printf(seq, ",io_size=%uKB", F2FS_IO_SIZE_KB(sbi)); | 1365 | seq_printf(seq, ",io_bits=%u", |
1366 | F2FS_OPTION(sbi).write_io_size_bits); | ||
1340 | #ifdef CONFIG_F2FS_FAULT_INJECTION | 1367 | #ifdef CONFIG_F2FS_FAULT_INJECTION |
1341 | if (test_opt(sbi, FAULT_INJECTION)) { | 1368 | if (test_opt(sbi, FAULT_INJECTION)) { |
1342 | seq_printf(seq, ",fault_injection=%u", | 1369 | seq_printf(seq, ",fault_injection=%u", |
@@ -1370,6 +1397,9 @@ static int f2fs_show_options(struct seq_file *seq, struct dentry *root) | |||
1370 | else if (F2FS_OPTION(sbi).alloc_mode == ALLOC_MODE_REUSE) | 1397 | else if (F2FS_OPTION(sbi).alloc_mode == ALLOC_MODE_REUSE) |
1371 | seq_printf(seq, ",alloc_mode=%s", "reuse"); | 1398 | seq_printf(seq, ",alloc_mode=%s", "reuse"); |
1372 | 1399 | ||
1400 | if (test_opt(sbi, DISABLE_CHECKPOINT)) | ||
1401 | seq_puts(seq, ",checkpoint=disable"); | ||
1402 | |||
1373 | if (F2FS_OPTION(sbi).fsync_mode == FSYNC_MODE_POSIX) | 1403 | if (F2FS_OPTION(sbi).fsync_mode == FSYNC_MODE_POSIX) |
1374 | seq_printf(seq, ",fsync_mode=%s", "posix"); | 1404 | seq_printf(seq, ",fsync_mode=%s", "posix"); |
1375 | else if (F2FS_OPTION(sbi).fsync_mode == FSYNC_MODE_STRICT) | 1405 | else if (F2FS_OPTION(sbi).fsync_mode == FSYNC_MODE_STRICT) |
@@ -1397,10 +1427,10 @@ static void default_options(struct f2fs_sb_info *sbi) | |||
1397 | set_opt(sbi, INLINE_DENTRY); | 1427 | set_opt(sbi, INLINE_DENTRY); |
1398 | set_opt(sbi, EXTENT_CACHE); | 1428 | set_opt(sbi, EXTENT_CACHE); |
1399 | set_opt(sbi, NOHEAP); | 1429 | set_opt(sbi, NOHEAP); |
1430 | clear_opt(sbi, DISABLE_CHECKPOINT); | ||
1400 | sbi->sb->s_flags |= SB_LAZYTIME; | 1431 | sbi->sb->s_flags |= SB_LAZYTIME; |
1401 | set_opt(sbi, FLUSH_MERGE); | 1432 | set_opt(sbi, FLUSH_MERGE); |
1402 | if (blk_queue_discard(bdev_get_queue(sbi->sb->s_bdev))) | 1433 | set_opt(sbi, DISCARD); |
1403 | set_opt(sbi, DISCARD); | ||
1404 | if (f2fs_sb_has_blkzoned(sbi->sb)) | 1434 | if (f2fs_sb_has_blkzoned(sbi->sb)) |
1405 | set_opt_mode(sbi, F2FS_MOUNT_LFS); | 1435 | set_opt_mode(sbi, F2FS_MOUNT_LFS); |
1406 | else | 1436 | else |
@@ -1419,6 +1449,57 @@ static void default_options(struct f2fs_sb_info *sbi) | |||
1419 | #ifdef CONFIG_QUOTA | 1449 | #ifdef CONFIG_QUOTA |
1420 | static int f2fs_enable_quotas(struct super_block *sb); | 1450 | static int f2fs_enable_quotas(struct super_block *sb); |
1421 | #endif | 1451 | #endif |
1452 | |||
1453 | static int f2fs_disable_checkpoint(struct f2fs_sb_info *sbi) | ||
1454 | { | ||
1455 | struct cp_control cpc; | ||
1456 | int err; | ||
1457 | |||
1458 | sbi->sb->s_flags |= SB_ACTIVE; | ||
1459 | |||
1460 | mutex_lock(&sbi->gc_mutex); | ||
1461 | f2fs_update_time(sbi, DISABLE_TIME); | ||
1462 | |||
1463 | while (!f2fs_time_over(sbi, DISABLE_TIME)) { | ||
1464 | err = f2fs_gc(sbi, true, false, NULL_SEGNO); | ||
1465 | if (err == -ENODATA) | ||
1466 | break; | ||
1467 | if (err && err != -EAGAIN) { | ||
1468 | mutex_unlock(&sbi->gc_mutex); | ||
1469 | return err; | ||
1470 | } | ||
1471 | } | ||
1472 | mutex_unlock(&sbi->gc_mutex); | ||
1473 | |||
1474 | err = sync_filesystem(sbi->sb); | ||
1475 | if (err) | ||
1476 | return err; | ||
1477 | |||
1478 | if (f2fs_disable_cp_again(sbi)) | ||
1479 | return -EAGAIN; | ||
1480 | |||
1481 | mutex_lock(&sbi->gc_mutex); | ||
1482 | cpc.reason = CP_PAUSE; | ||
1483 | set_sbi_flag(sbi, SBI_CP_DISABLED); | ||
1484 | f2fs_write_checkpoint(sbi, &cpc); | ||
1485 | |||
1486 | sbi->unusable_block_count = 0; | ||
1487 | mutex_unlock(&sbi->gc_mutex); | ||
1488 | return 0; | ||
1489 | } | ||
1490 | |||
1491 | static void f2fs_enable_checkpoint(struct f2fs_sb_info *sbi) | ||
1492 | { | ||
1493 | mutex_lock(&sbi->gc_mutex); | ||
1494 | f2fs_dirty_to_prefree(sbi); | ||
1495 | |||
1496 | clear_sbi_flag(sbi, SBI_CP_DISABLED); | ||
1497 | set_sbi_flag(sbi, SBI_IS_DIRTY); | ||
1498 | mutex_unlock(&sbi->gc_mutex); | ||
1499 | |||
1500 | f2fs_sync_fs(sbi->sb, 1); | ||
1501 | } | ||
1502 | |||
1422 | static int f2fs_remount(struct super_block *sb, int *flags, char *data) | 1503 | static int f2fs_remount(struct super_block *sb, int *flags, char *data) |
1423 | { | 1504 | { |
1424 | struct f2fs_sb_info *sbi = F2FS_SB(sb); | 1505 | struct f2fs_sb_info *sbi = F2FS_SB(sb); |
@@ -1428,6 +1509,8 @@ static int f2fs_remount(struct super_block *sb, int *flags, char *data) | |||
1428 | bool need_restart_gc = false; | 1509 | bool need_restart_gc = false; |
1429 | bool need_stop_gc = false; | 1510 | bool need_stop_gc = false; |
1430 | bool no_extent_cache = !test_opt(sbi, EXTENT_CACHE); | 1511 | bool no_extent_cache = !test_opt(sbi, EXTENT_CACHE); |
1512 | bool disable_checkpoint = test_opt(sbi, DISABLE_CHECKPOINT); | ||
1513 | bool checkpoint_changed; | ||
1431 | #ifdef CONFIG_QUOTA | 1514 | #ifdef CONFIG_QUOTA |
1432 | int i, j; | 1515 | int i, j; |
1433 | #endif | 1516 | #endif |
@@ -1472,6 +1555,8 @@ static int f2fs_remount(struct super_block *sb, int *flags, char *data) | |||
1472 | err = parse_options(sb, data); | 1555 | err = parse_options(sb, data); |
1473 | if (err) | 1556 | if (err) |
1474 | goto restore_opts; | 1557 | goto restore_opts; |
1558 | checkpoint_changed = | ||
1559 | disable_checkpoint != test_opt(sbi, DISABLE_CHECKPOINT); | ||
1475 | 1560 | ||
1476 | /* | 1561 | /* |
1477 | * Previous and new state of filesystem is RO, | 1562 | * Previous and new state of filesystem is RO, |
@@ -1485,7 +1570,7 @@ static int f2fs_remount(struct super_block *sb, int *flags, char *data) | |||
1485 | err = dquot_suspend(sb, -1); | 1570 | err = dquot_suspend(sb, -1); |
1486 | if (err < 0) | 1571 | if (err < 0) |
1487 | goto restore_opts; | 1572 | goto restore_opts; |
1488 | } else if (f2fs_readonly(sb) && !(*flags & MS_RDONLY)) { | 1573 | } else if (f2fs_readonly(sb) && !(*flags & SB_RDONLY)) { |
1489 | /* dquot_resume needs RW */ | 1574 | /* dquot_resume needs RW */ |
1490 | sb->s_flags &= ~SB_RDONLY; | 1575 | sb->s_flags &= ~SB_RDONLY; |
1491 | if (sb_any_quota_suspended(sb)) { | 1576 | if (sb_any_quota_suspended(sb)) { |
@@ -1505,6 +1590,13 @@ static int f2fs_remount(struct super_block *sb, int *flags, char *data) | |||
1505 | goto restore_opts; | 1590 | goto restore_opts; |
1506 | } | 1591 | } |
1507 | 1592 | ||
1593 | if ((*flags & SB_RDONLY) && test_opt(sbi, DISABLE_CHECKPOINT)) { | ||
1594 | err = -EINVAL; | ||
1595 | f2fs_msg(sbi->sb, KERN_WARNING, | ||
1596 | "disabling checkpoint not compatible with read-only"); | ||
1597 | goto restore_opts; | ||
1598 | } | ||
1599 | |||
1508 | /* | 1600 | /* |
1509 | * We stop the GC thread if FS is mounted as RO | 1601 | * We stop the GC thread if FS is mounted as RO |
1510 | * or if background_gc = off is passed in mount | 1602 | * or if background_gc = off is passed in mount |
@@ -1533,6 +1625,16 @@ static int f2fs_remount(struct super_block *sb, int *flags, char *data) | |||
1533 | clear_sbi_flag(sbi, SBI_IS_CLOSE); | 1625 | clear_sbi_flag(sbi, SBI_IS_CLOSE); |
1534 | } | 1626 | } |
1535 | 1627 | ||
1628 | if (checkpoint_changed) { | ||
1629 | if (test_opt(sbi, DISABLE_CHECKPOINT)) { | ||
1630 | err = f2fs_disable_checkpoint(sbi); | ||
1631 | if (err) | ||
1632 | goto restore_gc; | ||
1633 | } else { | ||
1634 | f2fs_enable_checkpoint(sbi); | ||
1635 | } | ||
1636 | } | ||
1637 | |||
1536 | /* | 1638 | /* |
1537 | * We stop issue flush thread if FS is mounted as RO | 1639 | * We stop issue flush thread if FS is mounted as RO |
1538 | * or if flush_merge is not passed in mount option. | 1640 | * or if flush_merge is not passed in mount option. |
@@ -1556,6 +1658,7 @@ skip: | |||
1556 | (test_opt(sbi, POSIX_ACL) ? SB_POSIXACL : 0); | 1658 | (test_opt(sbi, POSIX_ACL) ? SB_POSIXACL : 0); |
1557 | 1659 | ||
1558 | limit_reserve_root(sbi); | 1660 | limit_reserve_root(sbi); |
1661 | *flags = (*flags & ~SB_LAZYTIME) | (sb->s_flags & SB_LAZYTIME); | ||
1559 | return 0; | 1662 | return 0; |
1560 | restore_gc: | 1663 | restore_gc: |
1561 | if (need_restart_gc) { | 1664 | if (need_restart_gc) { |
@@ -1608,6 +1711,7 @@ repeat: | |||
1608 | congestion_wait(BLK_RW_ASYNC, HZ/50); | 1711 | congestion_wait(BLK_RW_ASYNC, HZ/50); |
1609 | goto repeat; | 1712 | goto repeat; |
1610 | } | 1713 | } |
1714 | set_sbi_flag(F2FS_SB(sb), SBI_QUOTA_NEED_REPAIR); | ||
1611 | return PTR_ERR(page); | 1715 | return PTR_ERR(page); |
1612 | } | 1716 | } |
1613 | 1717 | ||
@@ -1619,6 +1723,7 @@ repeat: | |||
1619 | } | 1723 | } |
1620 | if (unlikely(!PageUptodate(page))) { | 1724 | if (unlikely(!PageUptodate(page))) { |
1621 | f2fs_put_page(page, 1); | 1725 | f2fs_put_page(page, 1); |
1726 | set_sbi_flag(F2FS_SB(sb), SBI_QUOTA_NEED_REPAIR); | ||
1622 | return -EIO; | 1727 | return -EIO; |
1623 | } | 1728 | } |
1624 | 1729 | ||
@@ -1660,6 +1765,7 @@ retry: | |||
1660 | congestion_wait(BLK_RW_ASYNC, HZ/50); | 1765 | congestion_wait(BLK_RW_ASYNC, HZ/50); |
1661 | goto retry; | 1766 | goto retry; |
1662 | } | 1767 | } |
1768 | set_sbi_flag(F2FS_SB(sb), SBI_QUOTA_NEED_REPAIR); | ||
1663 | break; | 1769 | break; |
1664 | } | 1770 | } |
1665 | 1771 | ||
@@ -1696,6 +1802,12 @@ static qsize_t *f2fs_get_reserved_space(struct inode *inode) | |||
1696 | 1802 | ||
1697 | static int f2fs_quota_on_mount(struct f2fs_sb_info *sbi, int type) | 1803 | static int f2fs_quota_on_mount(struct f2fs_sb_info *sbi, int type) |
1698 | { | 1804 | { |
1805 | if (is_set_ckpt_flags(sbi, CP_QUOTA_NEED_FSCK_FLAG)) { | ||
1806 | f2fs_msg(sbi->sb, KERN_ERR, | ||
1807 | "quota sysfile may be corrupted, skip loading it"); | ||
1808 | return 0; | ||
1809 | } | ||
1810 | |||
1699 | return dquot_quota_on_mount(sbi->sb, F2FS_OPTION(sbi).s_qf_names[type], | 1811 | return dquot_quota_on_mount(sbi->sb, F2FS_OPTION(sbi).s_qf_names[type], |
1700 | F2FS_OPTION(sbi).s_jquota_fmt, type); | 1812 | F2FS_OPTION(sbi).s_jquota_fmt, type); |
1701 | } | 1813 | } |
@@ -1766,7 +1878,14 @@ static int f2fs_enable_quotas(struct super_block *sb) | |||
1766 | test_opt(F2FS_SB(sb), PRJQUOTA), | 1878 | test_opt(F2FS_SB(sb), PRJQUOTA), |
1767 | }; | 1879 | }; |
1768 | 1880 | ||
1769 | sb_dqopt(sb)->flags |= DQUOT_QUOTA_SYS_FILE | DQUOT_NOLIST_DIRTY; | 1881 | if (is_set_ckpt_flags(F2FS_SB(sb), CP_QUOTA_NEED_FSCK_FLAG)) { |
1882 | f2fs_msg(sb, KERN_ERR, | ||
1883 | "quota file may be corrupted, skip loading it"); | ||
1884 | return 0; | ||
1885 | } | ||
1886 | |||
1887 | sb_dqopt(sb)->flags |= DQUOT_QUOTA_SYS_FILE; | ||
1888 | |||
1770 | for (type = 0; type < MAXQUOTAS; type++) { | 1889 | for (type = 0; type < MAXQUOTAS; type++) { |
1771 | qf_inum = f2fs_qf_ino(sb, type); | 1890 | qf_inum = f2fs_qf_ino(sb, type); |
1772 | if (qf_inum) { | 1891 | if (qf_inum) { |
@@ -1780,6 +1899,8 @@ static int f2fs_enable_quotas(struct super_block *sb) | |||
1780 | "fsck to fix.", type, err); | 1899 | "fsck to fix.", type, err); |
1781 | for (type--; type >= 0; type--) | 1900 | for (type--; type >= 0; type--) |
1782 | dquot_quota_off(sb, type); | 1901 | dquot_quota_off(sb, type); |
1902 | set_sbi_flag(F2FS_SB(sb), | ||
1903 | SBI_QUOTA_NEED_REPAIR); | ||
1783 | return err; | 1904 | return err; |
1784 | } | 1905 | } |
1785 | } | 1906 | } |
@@ -1787,35 +1908,51 @@ static int f2fs_enable_quotas(struct super_block *sb) | |||
1787 | return 0; | 1908 | return 0; |
1788 | } | 1909 | } |
1789 | 1910 | ||
1790 | static int f2fs_quota_sync(struct super_block *sb, int type) | 1911 | int f2fs_quota_sync(struct super_block *sb, int type) |
1791 | { | 1912 | { |
1913 | struct f2fs_sb_info *sbi = F2FS_SB(sb); | ||
1792 | struct quota_info *dqopt = sb_dqopt(sb); | 1914 | struct quota_info *dqopt = sb_dqopt(sb); |
1793 | int cnt; | 1915 | int cnt; |
1794 | int ret; | 1916 | int ret; |
1795 | 1917 | ||
1796 | ret = dquot_writeback_dquots(sb, type); | 1918 | ret = dquot_writeback_dquots(sb, type); |
1797 | if (ret) | 1919 | if (ret) |
1798 | return ret; | 1920 | goto out; |
1799 | 1921 | ||
1800 | /* | 1922 | /* |
1801 | * Now when everything is written we can discard the pagecache so | 1923 | * Now when everything is written we can discard the pagecache so |
1802 | * that userspace sees the changes. | 1924 | * that userspace sees the changes. |
1803 | */ | 1925 | */ |
1804 | for (cnt = 0; cnt < MAXQUOTAS; cnt++) { | 1926 | for (cnt = 0; cnt < MAXQUOTAS; cnt++) { |
1927 | struct address_space *mapping; | ||
1928 | |||
1805 | if (type != -1 && cnt != type) | 1929 | if (type != -1 && cnt != type) |
1806 | continue; | 1930 | continue; |
1807 | if (!sb_has_quota_active(sb, cnt)) | 1931 | if (!sb_has_quota_active(sb, cnt)) |
1808 | continue; | 1932 | continue; |
1809 | 1933 | ||
1810 | ret = filemap_write_and_wait(dqopt->files[cnt]->i_mapping); | 1934 | mapping = dqopt->files[cnt]->i_mapping; |
1935 | |||
1936 | ret = filemap_fdatawrite(mapping); | ||
1937 | if (ret) | ||
1938 | goto out; | ||
1939 | |||
1940 | /* if we are using journalled quota */ | ||
1941 | if (is_journalled_quota(sbi)) | ||
1942 | continue; | ||
1943 | |||
1944 | ret = filemap_fdatawait(mapping); | ||
1811 | if (ret) | 1945 | if (ret) |
1812 | return ret; | 1946 | set_sbi_flag(F2FS_SB(sb), SBI_QUOTA_NEED_REPAIR); |
1813 | 1947 | ||
1814 | inode_lock(dqopt->files[cnt]); | 1948 | inode_lock(dqopt->files[cnt]); |
1815 | truncate_inode_pages(&dqopt->files[cnt]->i_data, 0); | 1949 | truncate_inode_pages(&dqopt->files[cnt]->i_data, 0); |
1816 | inode_unlock(dqopt->files[cnt]); | 1950 | inode_unlock(dqopt->files[cnt]); |
1817 | } | 1951 | } |
1818 | return 0; | 1952 | out: |
1953 | if (ret) | ||
1954 | set_sbi_flag(F2FS_SB(sb), SBI_QUOTA_NEED_REPAIR); | ||
1955 | return ret; | ||
1819 | } | 1956 | } |
1820 | 1957 | ||
1821 | static int f2fs_quota_on(struct super_block *sb, int type, int format_id, | 1958 | static int f2fs_quota_on(struct super_block *sb, int type, int format_id, |
@@ -1836,8 +1973,7 @@ static int f2fs_quota_on(struct super_block *sb, int type, int format_id, | |||
1836 | 1973 | ||
1837 | inode_lock(inode); | 1974 | inode_lock(inode); |
1838 | F2FS_I(inode)->i_flags |= F2FS_NOATIME_FL | F2FS_IMMUTABLE_FL; | 1975 | F2FS_I(inode)->i_flags |= F2FS_NOATIME_FL | F2FS_IMMUTABLE_FL; |
1839 | inode_set_flags(inode, S_NOATIME | S_IMMUTABLE, | 1976 | f2fs_set_inode_flags(inode); |
1840 | S_NOATIME | S_IMMUTABLE); | ||
1841 | inode_unlock(inode); | 1977 | inode_unlock(inode); |
1842 | f2fs_mark_inode_dirty_sync(inode, false); | 1978 | f2fs_mark_inode_dirty_sync(inode, false); |
1843 | 1979 | ||
@@ -1852,7 +1988,9 @@ static int f2fs_quota_off(struct super_block *sb, int type) | |||
1852 | if (!inode || !igrab(inode)) | 1988 | if (!inode || !igrab(inode)) |
1853 | return dquot_quota_off(sb, type); | 1989 | return dquot_quota_off(sb, type); |
1854 | 1990 | ||
1855 | f2fs_quota_sync(sb, type); | 1991 | err = f2fs_quota_sync(sb, type); |
1992 | if (err) | ||
1993 | goto out_put; | ||
1856 | 1994 | ||
1857 | err = dquot_quota_off(sb, type); | 1995 | err = dquot_quota_off(sb, type); |
1858 | if (err || f2fs_sb_has_quota_ino(sb)) | 1996 | if (err || f2fs_sb_has_quota_ino(sb)) |
@@ -1860,7 +1998,7 @@ static int f2fs_quota_off(struct super_block *sb, int type) | |||
1860 | 1998 | ||
1861 | inode_lock(inode); | 1999 | inode_lock(inode); |
1862 | F2FS_I(inode)->i_flags &= ~(F2FS_NOATIME_FL | F2FS_IMMUTABLE_FL); | 2000 | F2FS_I(inode)->i_flags &= ~(F2FS_NOATIME_FL | F2FS_IMMUTABLE_FL); |
1863 | inode_set_flags(inode, 0, S_NOATIME | S_IMMUTABLE); | 2001 | f2fs_set_inode_flags(inode); |
1864 | inode_unlock(inode); | 2002 | inode_unlock(inode); |
1865 | f2fs_mark_inode_dirty_sync(inode, false); | 2003 | f2fs_mark_inode_dirty_sync(inode, false); |
1866 | out_put: | 2004 | out_put: |
@@ -1871,9 +2009,88 @@ out_put: | |||
1871 | void f2fs_quota_off_umount(struct super_block *sb) | 2009 | void f2fs_quota_off_umount(struct super_block *sb) |
1872 | { | 2010 | { |
1873 | int type; | 2011 | int type; |
2012 | int err; | ||
2013 | |||
2014 | for (type = 0; type < MAXQUOTAS; type++) { | ||
2015 | err = f2fs_quota_off(sb, type); | ||
2016 | if (err) { | ||
2017 | int ret = dquot_quota_off(sb, type); | ||
2018 | |||
2019 | f2fs_msg(sb, KERN_ERR, | ||
2020 | "Fail to turn off disk quota " | ||
2021 | "(type: %d, err: %d, ret:%d), Please " | ||
2022 | "run fsck to fix it.", type, err, ret); | ||
2023 | set_sbi_flag(F2FS_SB(sb), SBI_QUOTA_NEED_REPAIR); | ||
2024 | } | ||
2025 | } | ||
2026 | } | ||
2027 | |||
2028 | static void f2fs_truncate_quota_inode_pages(struct super_block *sb) | ||
2029 | { | ||
2030 | struct quota_info *dqopt = sb_dqopt(sb); | ||
2031 | int type; | ||
2032 | |||
2033 | for (type = 0; type < MAXQUOTAS; type++) { | ||
2034 | if (!dqopt->files[type]) | ||
2035 | continue; | ||
2036 | f2fs_inode_synced(dqopt->files[type]); | ||
2037 | } | ||
2038 | } | ||
2039 | |||
2040 | static int f2fs_dquot_commit(struct dquot *dquot) | ||
2041 | { | ||
2042 | int ret; | ||
2043 | |||
2044 | ret = dquot_commit(dquot); | ||
2045 | if (ret < 0) | ||
2046 | set_sbi_flag(F2FS_SB(dquot->dq_sb), SBI_QUOTA_NEED_REPAIR); | ||
2047 | return ret; | ||
2048 | } | ||
2049 | |||
2050 | static int f2fs_dquot_acquire(struct dquot *dquot) | ||
2051 | { | ||
2052 | int ret; | ||
2053 | |||
2054 | ret = dquot_acquire(dquot); | ||
2055 | if (ret < 0) | ||
2056 | set_sbi_flag(F2FS_SB(dquot->dq_sb), SBI_QUOTA_NEED_REPAIR); | ||
2057 | |||
2058 | return ret; | ||
2059 | } | ||
2060 | |||
2061 | static int f2fs_dquot_release(struct dquot *dquot) | ||
2062 | { | ||
2063 | int ret; | ||
2064 | |||
2065 | ret = dquot_release(dquot); | ||
2066 | if (ret < 0) | ||
2067 | set_sbi_flag(F2FS_SB(dquot->dq_sb), SBI_QUOTA_NEED_REPAIR); | ||
2068 | return ret; | ||
2069 | } | ||
2070 | |||
2071 | static int f2fs_dquot_mark_dquot_dirty(struct dquot *dquot) | ||
2072 | { | ||
2073 | struct super_block *sb = dquot->dq_sb; | ||
2074 | struct f2fs_sb_info *sbi = F2FS_SB(sb); | ||
2075 | int ret; | ||
2076 | |||
2077 | ret = dquot_mark_dquot_dirty(dquot); | ||
2078 | |||
2079 | /* if we are using journalled quota */ | ||
2080 | if (is_journalled_quota(sbi)) | ||
2081 | set_sbi_flag(sbi, SBI_QUOTA_NEED_FLUSH); | ||
2082 | |||
2083 | return ret; | ||
2084 | } | ||
1874 | 2085 | ||
1875 | for (type = 0; type < MAXQUOTAS; type++) | 2086 | static int f2fs_dquot_commit_info(struct super_block *sb, int type) |
1876 | f2fs_quota_off(sb, type); | 2087 | { |
2088 | int ret; | ||
2089 | |||
2090 | ret = dquot_commit_info(sb, type); | ||
2091 | if (ret < 0) | ||
2092 | set_sbi_flag(F2FS_SB(sb), SBI_QUOTA_NEED_REPAIR); | ||
2093 | return ret; | ||
1877 | } | 2094 | } |
1878 | 2095 | ||
1879 | static int f2fs_get_projid(struct inode *inode, kprojid_t *projid) | 2096 | static int f2fs_get_projid(struct inode *inode, kprojid_t *projid) |
@@ -1884,11 +2101,11 @@ static int f2fs_get_projid(struct inode *inode, kprojid_t *projid) | |||
1884 | 2101 | ||
1885 | static const struct dquot_operations f2fs_quota_operations = { | 2102 | static const struct dquot_operations f2fs_quota_operations = { |
1886 | .get_reserved_space = f2fs_get_reserved_space, | 2103 | .get_reserved_space = f2fs_get_reserved_space, |
1887 | .write_dquot = dquot_commit, | 2104 | .write_dquot = f2fs_dquot_commit, |
1888 | .acquire_dquot = dquot_acquire, | 2105 | .acquire_dquot = f2fs_dquot_acquire, |
1889 | .release_dquot = dquot_release, | 2106 | .release_dquot = f2fs_dquot_release, |
1890 | .mark_dirty = dquot_mark_dquot_dirty, | 2107 | .mark_dirty = f2fs_dquot_mark_dquot_dirty, |
1891 | .write_info = dquot_commit_info, | 2108 | .write_info = f2fs_dquot_commit_info, |
1892 | .alloc_dquot = dquot_alloc, | 2109 | .alloc_dquot = dquot_alloc, |
1893 | .destroy_dquot = dquot_destroy, | 2110 | .destroy_dquot = dquot_destroy, |
1894 | .get_projid = f2fs_get_projid, | 2111 | .get_projid = f2fs_get_projid, |
@@ -1906,6 +2123,11 @@ static const struct quotactl_ops f2fs_quotactl_ops = { | |||
1906 | .get_nextdqblk = dquot_get_next_dqblk, | 2123 | .get_nextdqblk = dquot_get_next_dqblk, |
1907 | }; | 2124 | }; |
1908 | #else | 2125 | #else |
2126 | int f2fs_quota_sync(struct super_block *sb, int type) | ||
2127 | { | ||
2128 | return 0; | ||
2129 | } | ||
2130 | |||
1909 | void f2fs_quota_off_umount(struct super_block *sb) | 2131 | void f2fs_quota_off_umount(struct super_block *sb) |
1910 | { | 2132 | { |
1911 | } | 2133 | } |
@@ -2170,6 +2392,26 @@ static int sanity_check_raw_super(struct f2fs_sb_info *sbi, | |||
2170 | (bh->b_data + F2FS_SUPER_OFFSET); | 2392 | (bh->b_data + F2FS_SUPER_OFFSET); |
2171 | struct super_block *sb = sbi->sb; | 2393 | struct super_block *sb = sbi->sb; |
2172 | unsigned int blocksize; | 2394 | unsigned int blocksize; |
2395 | size_t crc_offset = 0; | ||
2396 | __u32 crc = 0; | ||
2397 | |||
2398 | /* Check checksum_offset and crc in superblock */ | ||
2399 | if (le32_to_cpu(raw_super->feature) & F2FS_FEATURE_SB_CHKSUM) { | ||
2400 | crc_offset = le32_to_cpu(raw_super->checksum_offset); | ||
2401 | if (crc_offset != | ||
2402 | offsetof(struct f2fs_super_block, crc)) { | ||
2403 | f2fs_msg(sb, KERN_INFO, | ||
2404 | "Invalid SB checksum offset: %zu", | ||
2405 | crc_offset); | ||
2406 | return 1; | ||
2407 | } | ||
2408 | crc = le32_to_cpu(raw_super->crc); | ||
2409 | if (!f2fs_crc_valid(sbi, crc, raw_super, crc_offset)) { | ||
2410 | f2fs_msg(sb, KERN_INFO, | ||
2411 | "Invalid SB checksum value: %u", crc); | ||
2412 | return 1; | ||
2413 | } | ||
2414 | } | ||
2173 | 2415 | ||
2174 | if (F2FS_SUPER_MAGIC != le32_to_cpu(raw_super->magic)) { | 2416 | if (F2FS_SUPER_MAGIC != le32_to_cpu(raw_super->magic)) { |
2175 | f2fs_msg(sb, KERN_INFO, | 2417 | f2fs_msg(sb, KERN_INFO, |
@@ -2320,7 +2562,7 @@ int f2fs_sanity_check_ckpt(struct f2fs_sb_info *sbi) | |||
2320 | unsigned int segment_count_main; | 2562 | unsigned int segment_count_main; |
2321 | unsigned int cp_pack_start_sum, cp_payload; | 2563 | unsigned int cp_pack_start_sum, cp_payload; |
2322 | block_t user_block_count; | 2564 | block_t user_block_count; |
2323 | int i; | 2565 | int i, j; |
2324 | 2566 | ||
2325 | total = le32_to_cpu(raw_super->segment_count); | 2567 | total = le32_to_cpu(raw_super->segment_count); |
2326 | fsmeta = le32_to_cpu(raw_super->segment_count_ckpt); | 2568 | fsmeta = le32_to_cpu(raw_super->segment_count_ckpt); |
@@ -2361,11 +2603,43 @@ int f2fs_sanity_check_ckpt(struct f2fs_sb_info *sbi) | |||
2361 | if (le32_to_cpu(ckpt->cur_node_segno[i]) >= main_segs || | 2603 | if (le32_to_cpu(ckpt->cur_node_segno[i]) >= main_segs || |
2362 | le16_to_cpu(ckpt->cur_node_blkoff[i]) >= blocks_per_seg) | 2604 | le16_to_cpu(ckpt->cur_node_blkoff[i]) >= blocks_per_seg) |
2363 | return 1; | 2605 | return 1; |
2606 | for (j = i + 1; j < NR_CURSEG_NODE_TYPE; j++) { | ||
2607 | if (le32_to_cpu(ckpt->cur_node_segno[i]) == | ||
2608 | le32_to_cpu(ckpt->cur_node_segno[j])) { | ||
2609 | f2fs_msg(sbi->sb, KERN_ERR, | ||
2610 | "Node segment (%u, %u) has the same " | ||
2611 | "segno: %u", i, j, | ||
2612 | le32_to_cpu(ckpt->cur_node_segno[i])); | ||
2613 | return 1; | ||
2614 | } | ||
2615 | } | ||
2364 | } | 2616 | } |
2365 | for (i = 0; i < NR_CURSEG_DATA_TYPE; i++) { | 2617 | for (i = 0; i < NR_CURSEG_DATA_TYPE; i++) { |
2366 | if (le32_to_cpu(ckpt->cur_data_segno[i]) >= main_segs || | 2618 | if (le32_to_cpu(ckpt->cur_data_segno[i]) >= main_segs || |
2367 | le16_to_cpu(ckpt->cur_data_blkoff[i]) >= blocks_per_seg) | 2619 | le16_to_cpu(ckpt->cur_data_blkoff[i]) >= blocks_per_seg) |
2368 | return 1; | 2620 | return 1; |
2621 | for (j = i + 1; j < NR_CURSEG_DATA_TYPE; j++) { | ||
2622 | if (le32_to_cpu(ckpt->cur_data_segno[i]) == | ||
2623 | le32_to_cpu(ckpt->cur_data_segno[j])) { | ||
2624 | f2fs_msg(sbi->sb, KERN_ERR, | ||
2625 | "Data segment (%u, %u) has the same " | ||
2626 | "segno: %u", i, j, | ||
2627 | le32_to_cpu(ckpt->cur_data_segno[i])); | ||
2628 | return 1; | ||
2629 | } | ||
2630 | } | ||
2631 | } | ||
2632 | for (i = 0; i < NR_CURSEG_NODE_TYPE; i++) { | ||
2633 | for (j = i; j < NR_CURSEG_DATA_TYPE; j++) { | ||
2634 | if (le32_to_cpu(ckpt->cur_node_segno[i]) == | ||
2635 | le32_to_cpu(ckpt->cur_data_segno[j])) { | ||
2636 | f2fs_msg(sbi->sb, KERN_ERR, | ||
2637 | "Data segment (%u) and Data segment (%u)" | ||
2638 | " has the same segno: %u", i, j, | ||
2639 | le32_to_cpu(ckpt->cur_node_segno[i])); | ||
2640 | return 1; | ||
2641 | } | ||
2642 | } | ||
2369 | } | 2643 | } |
2370 | 2644 | ||
2371 | sit_bitmap_size = le32_to_cpu(ckpt->sit_ver_bitmap_bytesize); | 2645 | sit_bitmap_size = le32_to_cpu(ckpt->sit_ver_bitmap_bytesize); |
@@ -2423,6 +2697,9 @@ static void init_sb_info(struct f2fs_sb_info *sbi) | |||
2423 | sbi->dir_level = DEF_DIR_LEVEL; | 2697 | sbi->dir_level = DEF_DIR_LEVEL; |
2424 | sbi->interval_time[CP_TIME] = DEF_CP_INTERVAL; | 2698 | sbi->interval_time[CP_TIME] = DEF_CP_INTERVAL; |
2425 | sbi->interval_time[REQ_TIME] = DEF_IDLE_INTERVAL; | 2699 | sbi->interval_time[REQ_TIME] = DEF_IDLE_INTERVAL; |
2700 | sbi->interval_time[DISCARD_TIME] = DEF_IDLE_INTERVAL; | ||
2701 | sbi->interval_time[GC_TIME] = DEF_IDLE_INTERVAL; | ||
2702 | sbi->interval_time[DISABLE_TIME] = DEF_DISABLE_INTERVAL; | ||
2426 | clear_sbi_flag(sbi, SBI_NEED_FSCK); | 2703 | clear_sbi_flag(sbi, SBI_NEED_FSCK); |
2427 | 2704 | ||
2428 | for (i = 0; i < NR_COUNT_TYPE; i++) | 2705 | for (i = 0; i < NR_COUNT_TYPE; i++) |
@@ -2453,8 +2730,12 @@ static int init_percpu_info(struct f2fs_sb_info *sbi) | |||
2453 | if (err) | 2730 | if (err) |
2454 | return err; | 2731 | return err; |
2455 | 2732 | ||
2456 | return percpu_counter_init(&sbi->total_valid_inode_count, 0, | 2733 | err = percpu_counter_init(&sbi->total_valid_inode_count, 0, |
2457 | GFP_KERNEL); | 2734 | GFP_KERNEL); |
2735 | if (err) | ||
2736 | percpu_counter_destroy(&sbi->alloc_valid_block_count); | ||
2737 | |||
2738 | return err; | ||
2458 | } | 2739 | } |
2459 | 2740 | ||
2460 | #ifdef CONFIG_BLK_DEV_ZONED | 2741 | #ifdef CONFIG_BLK_DEV_ZONED |
@@ -2589,6 +2870,7 @@ static int read_raw_super_block(struct f2fs_sb_info *sbi, | |||
2589 | int f2fs_commit_super(struct f2fs_sb_info *sbi, bool recover) | 2870 | int f2fs_commit_super(struct f2fs_sb_info *sbi, bool recover) |
2590 | { | 2871 | { |
2591 | struct buffer_head *bh; | 2872 | struct buffer_head *bh; |
2873 | __u32 crc = 0; | ||
2592 | int err; | 2874 | int err; |
2593 | 2875 | ||
2594 | if ((recover && f2fs_readonly(sbi->sb)) || | 2876 | if ((recover && f2fs_readonly(sbi->sb)) || |
@@ -2597,6 +2879,13 @@ int f2fs_commit_super(struct f2fs_sb_info *sbi, bool recover) | |||
2597 | return -EROFS; | 2879 | return -EROFS; |
2598 | } | 2880 | } |
2599 | 2881 | ||
2882 | /* we should update superblock crc here */ | ||
2883 | if (!recover && f2fs_sb_has_sb_chksum(sbi->sb)) { | ||
2884 | crc = f2fs_crc32(sbi, F2FS_RAW_SUPER(sbi), | ||
2885 | offsetof(struct f2fs_super_block, crc)); | ||
2886 | F2FS_RAW_SUPER(sbi)->crc = cpu_to_le32(crc); | ||
2887 | } | ||
2888 | |||
2600 | /* write back-up superblock first */ | 2889 | /* write back-up superblock first */ |
2601 | bh = sb_bread(sbi->sb, sbi->valid_super_block ? 0 : 1); | 2890 | bh = sb_bread(sbi->sb, sbi->valid_super_block ? 0 : 1); |
2602 | if (!bh) | 2891 | if (!bh) |
@@ -2866,7 +3155,7 @@ try_onemore: | |||
2866 | GFP_KERNEL); | 3155 | GFP_KERNEL); |
2867 | if (!sbi->write_io[i]) { | 3156 | if (!sbi->write_io[i]) { |
2868 | err = -ENOMEM; | 3157 | err = -ENOMEM; |
2869 | goto free_options; | 3158 | goto free_bio_info; |
2870 | } | 3159 | } |
2871 | 3160 | ||
2872 | for (j = HOT; j < n; j++) { | 3161 | for (j = HOT; j < n; j++) { |
@@ -2909,6 +3198,9 @@ try_onemore: | |||
2909 | goto free_meta_inode; | 3198 | goto free_meta_inode; |
2910 | } | 3199 | } |
2911 | 3200 | ||
3201 | if (__is_set_ckpt_flags(F2FS_CKPT(sbi), CP_QUOTA_NEED_FSCK_FLAG)) | ||
3202 | set_sbi_flag(sbi, SBI_QUOTA_NEED_REPAIR); | ||
3203 | |||
2912 | /* Initialize device list */ | 3204 | /* Initialize device list */ |
2913 | err = f2fs_scan_devices(sbi); | 3205 | err = f2fs_scan_devices(sbi); |
2914 | if (err) { | 3206 | if (err) { |
@@ -3007,11 +3299,9 @@ try_onemore: | |||
3007 | /* Enable quota usage during mount */ | 3299 | /* Enable quota usage during mount */ |
3008 | if (f2fs_sb_has_quota_ino(sb) && !f2fs_readonly(sb)) { | 3300 | if (f2fs_sb_has_quota_ino(sb) && !f2fs_readonly(sb)) { |
3009 | err = f2fs_enable_quotas(sb); | 3301 | err = f2fs_enable_quotas(sb); |
3010 | if (err) { | 3302 | if (err) |
3011 | f2fs_msg(sb, KERN_ERR, | 3303 | f2fs_msg(sb, KERN_ERR, |
3012 | "Cannot turn on quotas: error %d", err); | 3304 | "Cannot turn on quotas: error %d", err); |
3013 | goto free_sysfs; | ||
3014 | } | ||
3015 | } | 3305 | } |
3016 | #endif | 3306 | #endif |
3017 | /* if there are nt orphan nodes free them */ | 3307 | /* if there are nt orphan nodes free them */ |
@@ -3019,6 +3309,9 @@ try_onemore: | |||
3019 | if (err) | 3309 | if (err) |
3020 | goto free_meta; | 3310 | goto free_meta; |
3021 | 3311 | ||
3312 | if (unlikely(is_set_ckpt_flags(sbi, CP_DISABLED_FLAG))) | ||
3313 | goto skip_recovery; | ||
3314 | |||
3022 | /* recover fsynced data */ | 3315 | /* recover fsynced data */ |
3023 | if (!test_opt(sbi, DISABLE_ROLL_FORWARD)) { | 3316 | if (!test_opt(sbi, DISABLE_ROLL_FORWARD)) { |
3024 | /* | 3317 | /* |
@@ -3058,6 +3351,14 @@ skip_recovery: | |||
3058 | /* f2fs_recover_fsync_data() cleared this already */ | 3351 | /* f2fs_recover_fsync_data() cleared this already */ |
3059 | clear_sbi_flag(sbi, SBI_POR_DOING); | 3352 | clear_sbi_flag(sbi, SBI_POR_DOING); |
3060 | 3353 | ||
3354 | if (test_opt(sbi, DISABLE_CHECKPOINT)) { | ||
3355 | err = f2fs_disable_checkpoint(sbi); | ||
3356 | if (err) | ||
3357 | goto free_meta; | ||
3358 | } else if (is_set_ckpt_flags(sbi, CP_DISABLED_FLAG)) { | ||
3359 | f2fs_enable_checkpoint(sbi); | ||
3360 | } | ||
3361 | |||
3061 | /* | 3362 | /* |
3062 | * If filesystem is not mounted as read-only then | 3363 | * If filesystem is not mounted as read-only then |
3063 | * do start the gc_thread. | 3364 | * do start the gc_thread. |
@@ -3090,10 +3391,10 @@ skip_recovery: | |||
3090 | 3391 | ||
3091 | free_meta: | 3392 | free_meta: |
3092 | #ifdef CONFIG_QUOTA | 3393 | #ifdef CONFIG_QUOTA |
3394 | f2fs_truncate_quota_inode_pages(sb); | ||
3093 | if (f2fs_sb_has_quota_ino(sb) && !f2fs_readonly(sb)) | 3395 | if (f2fs_sb_has_quota_ino(sb) && !f2fs_readonly(sb)) |
3094 | f2fs_quota_off_umount(sbi->sb); | 3396 | f2fs_quota_off_umount(sbi->sb); |
3095 | #endif | 3397 | #endif |
3096 | f2fs_sync_inode_meta(sbi); | ||
3097 | /* | 3398 | /* |
3098 | * Some dirty meta pages can be produced by f2fs_recover_orphan_inodes() | 3399 | * Some dirty meta pages can be produced by f2fs_recover_orphan_inodes() |
3099 | * failed by EIO. Then, iput(node_inode) can trigger balance_fs_bg() | 3400 | * failed by EIO. Then, iput(node_inode) can trigger balance_fs_bg() |
@@ -3101,9 +3402,6 @@ free_meta: | |||
3101 | * falls into an infinite loop in f2fs_sync_meta_pages(). | 3402 | * falls into an infinite loop in f2fs_sync_meta_pages(). |
3102 | */ | 3403 | */ |
3103 | truncate_inode_pages_final(META_MAPPING(sbi)); | 3404 | truncate_inode_pages_final(META_MAPPING(sbi)); |
3104 | #ifdef CONFIG_QUOTA | ||
3105 | free_sysfs: | ||
3106 | #endif | ||
3107 | f2fs_unregister_sysfs(sbi); | 3405 | f2fs_unregister_sysfs(sbi); |
3108 | free_root_inode: | 3406 | free_root_inode: |
3109 | dput(sb->s_root); | 3407 | dput(sb->s_root); |
@@ -3175,6 +3473,9 @@ static void kill_f2fs_super(struct super_block *sb) | |||
3175 | }; | 3473 | }; |
3176 | f2fs_write_checkpoint(sbi, &cpc); | 3474 | f2fs_write_checkpoint(sbi, &cpc); |
3177 | } | 3475 | } |
3476 | |||
3477 | if (is_sbi_flag_set(sbi, SBI_IS_RECOVERED) && f2fs_readonly(sb)) | ||
3478 | sb->s_flags &= ~SB_RDONLY; | ||
3178 | } | 3479 | } |
3179 | kill_block_super(sb); | 3480 | kill_block_super(sb); |
3180 | } | 3481 | } |
diff --git a/fs/f2fs/sysfs.c b/fs/f2fs/sysfs.c index 81c0e5337443..b777cbdd796b 100644 --- a/fs/f2fs/sysfs.c +++ b/fs/f2fs/sysfs.c | |||
@@ -1,13 +1,10 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
1 | /* | 2 | /* |
2 | * f2fs sysfs interface | 3 | * f2fs sysfs interface |
3 | * | 4 | * |
4 | * Copyright (c) 2012 Samsung Electronics Co., Ltd. | 5 | * Copyright (c) 2012 Samsung Electronics Co., Ltd. |
5 | * http://www.samsung.com/ | 6 | * http://www.samsung.com/ |
6 | * Copyright (c) 2017 Chao Yu <chao@kernel.org> | 7 | * Copyright (c) 2017 Chao Yu <chao@kernel.org> |
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | */ | 8 | */ |
12 | #include <linux/compiler.h> | 9 | #include <linux/compiler.h> |
13 | #include <linux/proc_fs.h> | 10 | #include <linux/proc_fs.h> |
@@ -120,6 +117,9 @@ static ssize_t features_show(struct f2fs_attr *a, | |||
120 | if (f2fs_sb_has_lost_found(sb)) | 117 | if (f2fs_sb_has_lost_found(sb)) |
121 | len += snprintf(buf + len, PAGE_SIZE - len, "%s%s", | 118 | len += snprintf(buf + len, PAGE_SIZE - len, "%s%s", |
122 | len ? ", " : "", "lost_found"); | 119 | len ? ", " : "", "lost_found"); |
120 | if (f2fs_sb_has_sb_chksum(sb)) | ||
121 | len += snprintf(buf + len, PAGE_SIZE - len, "%s%s", | ||
122 | len ? ", " : "", "sb_checksum"); | ||
123 | len += snprintf(buf + len, PAGE_SIZE - len, "\n"); | 123 | len += snprintf(buf + len, PAGE_SIZE - len, "\n"); |
124 | return len; | 124 | return len; |
125 | } | 125 | } |
@@ -337,6 +337,7 @@ enum feat_id { | |||
337 | FEAT_QUOTA_INO, | 337 | FEAT_QUOTA_INO, |
338 | FEAT_INODE_CRTIME, | 338 | FEAT_INODE_CRTIME, |
339 | FEAT_LOST_FOUND, | 339 | FEAT_LOST_FOUND, |
340 | FEAT_SB_CHECKSUM, | ||
340 | }; | 341 | }; |
341 | 342 | ||
342 | static ssize_t f2fs_feature_show(struct f2fs_attr *a, | 343 | static ssize_t f2fs_feature_show(struct f2fs_attr *a, |
@@ -353,6 +354,7 @@ static ssize_t f2fs_feature_show(struct f2fs_attr *a, | |||
353 | case FEAT_QUOTA_INO: | 354 | case FEAT_QUOTA_INO: |
354 | case FEAT_INODE_CRTIME: | 355 | case FEAT_INODE_CRTIME: |
355 | case FEAT_LOST_FOUND: | 356 | case FEAT_LOST_FOUND: |
357 | case FEAT_SB_CHECKSUM: | ||
356 | return snprintf(buf, PAGE_SIZE, "supported\n"); | 358 | return snprintf(buf, PAGE_SIZE, "supported\n"); |
357 | } | 359 | } |
358 | return 0; | 360 | return 0; |
@@ -407,6 +409,9 @@ F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, max_victim_search, max_victim_search); | |||
407 | F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, dir_level, dir_level); | 409 | F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, dir_level, dir_level); |
408 | F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, cp_interval, interval_time[CP_TIME]); | 410 | F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, cp_interval, interval_time[CP_TIME]); |
409 | F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, idle_interval, interval_time[REQ_TIME]); | 411 | F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, idle_interval, interval_time[REQ_TIME]); |
412 | F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, discard_idle_interval, | ||
413 | interval_time[DISCARD_TIME]); | ||
414 | F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, gc_idle_interval, interval_time[GC_TIME]); | ||
410 | F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, iostat_enable, iostat_enable); | 415 | F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, iostat_enable, iostat_enable); |
411 | F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, readdir_ra, readdir_ra); | 416 | F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, readdir_ra, readdir_ra); |
412 | F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, gc_pin_file_thresh, gc_pin_file_threshold); | 417 | F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, gc_pin_file_thresh, gc_pin_file_threshold); |
@@ -434,6 +439,7 @@ F2FS_FEATURE_RO_ATTR(flexible_inline_xattr, FEAT_FLEXIBLE_INLINE_XATTR); | |||
434 | F2FS_FEATURE_RO_ATTR(quota_ino, FEAT_QUOTA_INO); | 439 | F2FS_FEATURE_RO_ATTR(quota_ino, FEAT_QUOTA_INO); |
435 | F2FS_FEATURE_RO_ATTR(inode_crtime, FEAT_INODE_CRTIME); | 440 | F2FS_FEATURE_RO_ATTR(inode_crtime, FEAT_INODE_CRTIME); |
436 | F2FS_FEATURE_RO_ATTR(lost_found, FEAT_LOST_FOUND); | 441 | F2FS_FEATURE_RO_ATTR(lost_found, FEAT_LOST_FOUND); |
442 | F2FS_FEATURE_RO_ATTR(sb_checksum, FEAT_SB_CHECKSUM); | ||
437 | 443 | ||
438 | #define ATTR_LIST(name) (&f2fs_attr_##name.attr) | 444 | #define ATTR_LIST(name) (&f2fs_attr_##name.attr) |
439 | static struct attribute *f2fs_attrs[] = { | 445 | static struct attribute *f2fs_attrs[] = { |
@@ -460,6 +466,8 @@ static struct attribute *f2fs_attrs[] = { | |||
460 | ATTR_LIST(dirty_nats_ratio), | 466 | ATTR_LIST(dirty_nats_ratio), |
461 | ATTR_LIST(cp_interval), | 467 | ATTR_LIST(cp_interval), |
462 | ATTR_LIST(idle_interval), | 468 | ATTR_LIST(idle_interval), |
469 | ATTR_LIST(discard_idle_interval), | ||
470 | ATTR_LIST(gc_idle_interval), | ||
463 | ATTR_LIST(iostat_enable), | 471 | ATTR_LIST(iostat_enable), |
464 | ATTR_LIST(readdir_ra), | 472 | ATTR_LIST(readdir_ra), |
465 | ATTR_LIST(gc_pin_file_thresh), | 473 | ATTR_LIST(gc_pin_file_thresh), |
@@ -491,6 +499,7 @@ static struct attribute *f2fs_feat_attrs[] = { | |||
491 | ATTR_LIST(quota_ino), | 499 | ATTR_LIST(quota_ino), |
492 | ATTR_LIST(inode_crtime), | 500 | ATTR_LIST(inode_crtime), |
493 | ATTR_LIST(lost_found), | 501 | ATTR_LIST(lost_found), |
502 | ATTR_LIST(sb_checksum), | ||
494 | NULL, | 503 | NULL, |
495 | }; | 504 | }; |
496 | 505 | ||
diff --git a/fs/f2fs/trace.c b/fs/f2fs/trace.c index a1fcd00bbb2b..ce2a5eb210b6 100644 --- a/fs/f2fs/trace.c +++ b/fs/f2fs/trace.c | |||
@@ -1,12 +1,9 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
1 | /* | 2 | /* |
2 | * f2fs IO tracer | 3 | * f2fs IO tracer |
3 | * | 4 | * |
4 | * Copyright (c) 2014 Motorola Mobility | 5 | * Copyright (c) 2014 Motorola Mobility |
5 | * Copyright (c) 2014 Jaegeuk Kim <jaegeuk@kernel.org> | 6 | * Copyright (c) 2014 Jaegeuk Kim <jaegeuk@kernel.org> |
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | */ | 7 | */ |
11 | #include <linux/fs.h> | 8 | #include <linux/fs.h> |
12 | #include <linux/f2fs_fs.h> | 9 | #include <linux/f2fs_fs.h> |
diff --git a/fs/f2fs/trace.h b/fs/f2fs/trace.h index 67db24ac1e85..e8075fc5b228 100644 --- a/fs/f2fs/trace.h +++ b/fs/f2fs/trace.h | |||
@@ -1,12 +1,9 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
1 | /* | 2 | /* |
2 | * f2fs IO tracer | 3 | * f2fs IO tracer |
3 | * | 4 | * |
4 | * Copyright (c) 2014 Motorola Mobility | 5 | * Copyright (c) 2014 Motorola Mobility |
5 | * Copyright (c) 2014 Jaegeuk Kim <jaegeuk@kernel.org> | 6 | * Copyright (c) 2014 Jaegeuk Kim <jaegeuk@kernel.org> |
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | */ | 7 | */ |
11 | #ifndef __F2FS_TRACE_H__ | 8 | #ifndef __F2FS_TRACE_H__ |
12 | #define __F2FS_TRACE_H__ | 9 | #define __F2FS_TRACE_H__ |
diff --git a/fs/f2fs/xattr.c b/fs/f2fs/xattr.c index 77a010e625f5..7261245c208d 100644 --- a/fs/f2fs/xattr.c +++ b/fs/f2fs/xattr.c | |||
@@ -1,3 +1,4 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
1 | /* | 2 | /* |
2 | * fs/f2fs/xattr.c | 3 | * fs/f2fs/xattr.c |
3 | * | 4 | * |
@@ -13,10 +14,6 @@ | |||
13 | * suggestion of Luka Renko <luka.renko@hermes.si>. | 14 | * suggestion of Luka Renko <luka.renko@hermes.si>. |
14 | * xattr consolidation Copyright (c) 2004 James Morris <jmorris@redhat.com>, | 15 | * xattr consolidation Copyright (c) 2004 James Morris <jmorris@redhat.com>, |
15 | * Red Hat Inc. | 16 | * Red Hat Inc. |
16 | * | ||
17 | * This program is free software; you can redistribute it and/or modify | ||
18 | * it under the terms of the GNU General Public License version 2 as | ||
19 | * published by the Free Software Foundation. | ||
20 | */ | 17 | */ |
21 | #include <linux/rwsem.h> | 18 | #include <linux/rwsem.h> |
22 | #include <linux/f2fs_fs.h> | 19 | #include <linux/f2fs_fs.h> |
diff --git a/fs/f2fs/xattr.h b/fs/f2fs/xattr.h index dbcd1d16e669..67db134da0f5 100644 --- a/fs/f2fs/xattr.h +++ b/fs/f2fs/xattr.h | |||
@@ -1,3 +1,4 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
1 | /* | 2 | /* |
2 | * fs/f2fs/xattr.h | 3 | * fs/f2fs/xattr.h |
3 | * | 4 | * |
@@ -9,10 +10,6 @@ | |||
9 | * On-disk format of extended attributes for the ext2 filesystem. | 10 | * On-disk format of extended attributes for the ext2 filesystem. |
10 | * | 11 | * |
11 | * (C) 2001 Andreas Gruenbacher, <a.gruenbacher@computer.org> | 12 | * (C) 2001 Andreas Gruenbacher, <a.gruenbacher@computer.org> |
12 | * | ||
13 | * This program is free software; you can redistribute it and/or modify | ||
14 | * it under the terms of the GNU General Public License version 2 as | ||
15 | * published by the Free Software Foundation. | ||
16 | */ | 13 | */ |
17 | #ifndef __F2FS_XATTR_H__ | 14 | #ifndef __F2FS_XATTR_H__ |
18 | #define __F2FS_XATTR_H__ | 15 | #define __F2FS_XATTR_H__ |
diff --git a/include/linux/f2fs_fs.h b/include/linux/f2fs_fs.h index f70f8ac9c4f4..d7711048ef93 100644 --- a/include/linux/f2fs_fs.h +++ b/include/linux/f2fs_fs.h | |||
@@ -1,12 +1,9 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
1 | /** | 2 | /** |
2 | * include/linux/f2fs_fs.h | 3 | * include/linux/f2fs_fs.h |
3 | * | 4 | * |
4 | * Copyright (c) 2012 Samsung Electronics Co., Ltd. | 5 | * Copyright (c) 2012 Samsung Electronics Co., Ltd. |
5 | * http://www.samsung.com/ | 6 | * http://www.samsung.com/ |
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | */ | 7 | */ |
11 | #ifndef _LINUX_F2FS_FS_H | 8 | #ifndef _LINUX_F2FS_FS_H |
12 | #define _LINUX_F2FS_FS_H | 9 | #define _LINUX_F2FS_FS_H |
@@ -112,12 +109,15 @@ struct f2fs_super_block { | |||
112 | struct f2fs_device devs[MAX_DEVICES]; /* device list */ | 109 | struct f2fs_device devs[MAX_DEVICES]; /* device list */ |
113 | __le32 qf_ino[F2FS_MAX_QUOTAS]; /* quota inode numbers */ | 110 | __le32 qf_ino[F2FS_MAX_QUOTAS]; /* quota inode numbers */ |
114 | __u8 hot_ext_count; /* # of hot file extension */ | 111 | __u8 hot_ext_count; /* # of hot file extension */ |
115 | __u8 reserved[314]; /* valid reserved region */ | 112 | __u8 reserved[310]; /* valid reserved region */ |
113 | __le32 crc; /* checksum of superblock */ | ||
116 | } __packed; | 114 | } __packed; |
117 | 115 | ||
118 | /* | 116 | /* |
119 | * For checkpoint | 117 | * For checkpoint |
120 | */ | 118 | */ |
119 | #define CP_DISABLED_FLAG 0x00001000 | ||
120 | #define CP_QUOTA_NEED_FSCK_FLAG 0x00000800 | ||
121 | #define CP_LARGE_NAT_BITMAP_FLAG 0x00000400 | 121 | #define CP_LARGE_NAT_BITMAP_FLAG 0x00000400 |
122 | #define CP_NOCRC_RECOVERY_FLAG 0x00000200 | 122 | #define CP_NOCRC_RECOVERY_FLAG 0x00000200 |
123 | #define CP_TRIMMED_FLAG 0x00000100 | 123 | #define CP_TRIMMED_FLAG 0x00000100 |