// SPDX-License-Identifier: GPL-2.0
/*
* f2fs extent cache support
*
* Copyright (c) 2015 Motorola Mobility
* Copyright (c) 2015 Samsung Electronics
* Authors: Jaegeuk Kim <jaegeuk@kernel.org>
* Chao Yu <chao2.yu@samsung.com>
*
* block_age-based extent cache added by:
* Copyright (c) 2022 xiaomi Co., Ltd.
* http://www.xiaomi.com/
*/
#include <linux/fs.h>
#include <linux/f2fs_fs.h>
#include "f2fs.h"
#include "node.h"
#include <trace/events/f2fs.h>
bool sanity_check_extent_cache(struct inode *inode, struct folio *ifolio)
{
struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
struct f2fs_extent *i_ext = &F2FS_INODE(ifolio)->i_ext;
struct extent_info ei;
int devi;
get_read_extent_info(&ei, i_ext);
if (!ei.len)
return true;
if (!f2fs_is_valid_blkaddr(sbi, ei.blk, DATA_GENERIC_ENHANCE) ||
!f2fs_is_valid_blkaddr(sbi, ei.blk + ei.len - 1,
DATA_GENERIC_ENHANCE)) {
f2fs_warn(sbi, "%s: inode (ino=%lx) extent info [%u, %u, %u] is incorrect, run fsck to fix",
__func__, inode->i_ino,
ei.blk, ei.fofs, ei.len);
return false;
}
if (!IS_DEVICE_ALIASING(inode))
return true;
for (devi = 0; devi < sbi->s_ndevs; devi++) {
if (FDEV(devi).start_blk != ei.blk ||
FDEV(devi).end_blk != ei.blk + ei.len - 1)
continue;
if (devi == 0) {
f2fs_warn(sbi,
"%s: inode (ino=%lx) is an alias of meta device",
__func__, inode->i_ino);
return false;
}
if (bdev_is_zoned(FDEV(devi).bdev)) {
f2fs_warn(sbi,
"%s: device alias inode (ino=%lx)'s extent info "
"[%u, %u, %u] maps to zoned block device",
__func__, inode->i_ino, ei.blk, ei.fofs, ei.len);
return false;
}
return true;
}
f2fs_warn(sbi, "%s: device alias inode (ino=%lx)'s extent info "
"[%u, %u, %u] is inconsistent w/ any devices",
__func__, inode->i_ino, ei.blk, ei.fofs, ei.len);
return false;
}
static void __set_extent_info(struct extent_info *ei,
unsigned int fofs, unsigned int len,
block_t blk, bool keep_clen,
unsigned long age, unsigned long last_blocks,
enum<