|
10 | 10 | #include <linux/buffer_head.h> |
11 | 11 | #include <linux/writeback.h> |
12 | 12 | #include <linux/sched/mm.h> |
| 13 | +#include <linux/lz4.h> |
| 14 | +#include <linux/zstd.h> |
13 | 15 |
|
14 | 16 | #include "f2fs.h" |
15 | 17 | #include "node.h" |
@@ -202,6 +204,80 @@ void f2fs_inode_chksum_set(struct f2fs_sb_info *sbi, struct page *page) |
202 | 204 | ri->i_inode_checksum = cpu_to_le32(f2fs_inode_chksum(sbi, page)); |
203 | 205 | } |
204 | 206 |
|
| 207 | +static bool sanity_check_compress_inode(struct inode *inode, |
| 208 | + struct f2fs_inode *ri) |
| 209 | +{ |
| 210 | + struct f2fs_sb_info *sbi = F2FS_I_SB(inode); |
| 211 | + unsigned char clevel; |
| 212 | + |
| 213 | + if (ri->i_compress_algorithm >= COMPRESS_MAX) { |
| 214 | + f2fs_warn(sbi, |
| 215 | + "%s: inode (ino=%lx) has unsupported compress algorithm: %u, run fsck to fix", |
| 216 | + __func__, inode->i_ino, ri->i_compress_algorithm); |
| 217 | + goto err; |
| 218 | + } |
| 219 | + if (le64_to_cpu(ri->i_compr_blocks) > |
| 220 | + SECTOR_TO_BLOCK(inode->i_blocks)) { |
| 221 | + f2fs_warn(sbi, |
| 222 | + "%s: inode (ino=%lx) has inconsistent i_compr_blocks:%llu, i_blocks:%llu, run fsck to fix", |
| 223 | + __func__, inode->i_ino, le64_to_cpu(ri->i_compr_blocks), |
| 224 | + SECTOR_TO_BLOCK(inode->i_blocks)); |
| 225 | + goto err; |
| 226 | + } |
| 227 | + if (ri->i_log_cluster_size < MIN_COMPRESS_LOG_SIZE || |
| 228 | + ri->i_log_cluster_size > MAX_COMPRESS_LOG_SIZE) { |
| 229 | + f2fs_warn(sbi, |
| 230 | + "%s: inode (ino=%lx) has unsupported log cluster size: %u, run fsck to fix", |
| 231 | + __func__, inode->i_ino, ri->i_log_cluster_size); |
| 232 | + goto err; |
| 233 | + } |
| 234 | + |
| 235 | + clevel = le16_to_cpu(ri->i_compress_flag) >> |
| 236 | + COMPRESS_LEVEL_OFFSET; |
| 237 | + switch (ri->i_compress_algorithm) { |
| 238 | + case COMPRESS_LZO: |
| 239 | +#ifdef CONFIG_F2FS_FS_LZO |
| 240 | + if (clevel) |
| 241 | + goto err_level; |
| 242 | +#endif |
| 243 | + break; |
| 244 | + case COMPRESS_LZORLE: |
| 245 | +#ifdef CONFIG_F2FS_FS_LZORLE |
| 246 | + if (clevel) |
| 247 | + goto err_level; |
| 248 | +#endif |
| 249 | + break; |
| 250 | + case COMPRESS_LZ4: |
| 251 | +#ifdef CONFIG_F2FS_FS_LZ4 |
| 252 | +#ifdef CONFIG_F2FS_FS_LZ4HC |
| 253 | + if (clevel && |
| 254 | + (clevel < LZ4HC_MIN_CLEVEL || clevel > LZ4HC_MAX_CLEVEL)) |
| 255 | + goto err_level; |
| 256 | +#else |
| 257 | + if (clevel) |
| 258 | + goto err_level; |
| 259 | +#endif |
| 260 | +#endif |
| 261 | + break; |
| 262 | + case COMPRESS_ZSTD: |
| 263 | +#ifdef CONFIG_F2FS_FS_ZSTD |
| 264 | + if (clevel < zstd_min_clevel() || clevel > zstd_max_clevel()) |
| 265 | + goto err_level; |
| 266 | +#endif |
| 267 | + break; |
| 268 | + default: |
| 269 | + goto err_level; |
| 270 | + } |
| 271 | + |
| 272 | + return true; |
| 273 | +err_level: |
| 274 | + f2fs_warn(sbi, "%s: inode (ino=%lx) has unsupported compress level: %u, run fsck to fix", |
| 275 | + __func__, inode->i_ino, clevel); |
| 276 | +err: |
| 277 | + set_sbi_flag(sbi, SBI_NEED_FSCK); |
| 278 | + return false; |
| 279 | +} |
| 280 | + |
205 | 281 | static bool sanity_check_inode(struct inode *inode, struct page *node_page) |
206 | 282 | { |
207 | 283 | struct f2fs_sb_info *sbi = F2FS_I_SB(inode); |
@@ -286,35 +362,8 @@ static bool sanity_check_inode(struct inode *inode, struct page *node_page) |
286 | 362 | if (f2fs_has_extra_attr(inode) && f2fs_sb_has_compression(sbi) && |
287 | 363 | fi->i_flags & F2FS_COMPR_FL && |
288 | 364 | F2FS_FITS_IN_INODE(ri, fi->i_extra_isize, |
289 | | - i_log_cluster_size)) { |
290 | | - if (ri->i_compress_algorithm >= COMPRESS_MAX) { |
291 | | - set_sbi_flag(sbi, SBI_NEED_FSCK); |
292 | | - f2fs_warn(sbi, "%s: inode (ino=%lx) has unsupported " |
293 | | - "compress algorithm: %u, run fsck to fix", |
294 | | - __func__, inode->i_ino, |
295 | | - ri->i_compress_algorithm); |
296 | | - return false; |
297 | | - } |
298 | | - if (le64_to_cpu(ri->i_compr_blocks) > |
299 | | - SECTOR_TO_BLOCK(inode->i_blocks)) { |
300 | | - set_sbi_flag(sbi, SBI_NEED_FSCK); |
301 | | - f2fs_warn(sbi, "%s: inode (ino=%lx) has inconsistent " |
302 | | - "i_compr_blocks:%llu, i_blocks:%llu, run fsck to fix", |
303 | | - __func__, inode->i_ino, |
304 | | - le64_to_cpu(ri->i_compr_blocks), |
305 | | - SECTOR_TO_BLOCK(inode->i_blocks)); |
306 | | - return false; |
307 | | - } |
308 | | - if (ri->i_log_cluster_size < MIN_COMPRESS_LOG_SIZE || |
309 | | - ri->i_log_cluster_size > MAX_COMPRESS_LOG_SIZE) { |
310 | | - set_sbi_flag(sbi, SBI_NEED_FSCK); |
311 | | - f2fs_warn(sbi, "%s: inode (ino=%lx) has unsupported " |
312 | | - "log cluster size: %u, run fsck to fix", |
313 | | - __func__, inode->i_ino, |
314 | | - ri->i_log_cluster_size); |
315 | | - return false; |
316 | | - } |
317 | | - } |
| 365 | + i_log_cluster_size)) |
| 366 | + return sanity_check_compress_inode(inode, ri); |
318 | 367 |
|
319 | 368 | return true; |
320 | 369 | } |
|
0 commit comments