// SPDX-License-Identifier: GPL-2.0
/*
* fs/f2fs/inode.c
*
* Copyright (c) 2012 Samsung Electronics Co., Ltd.
* http://www.samsung.com/
*/
#include <linux/fs.h>
#include <linux/f2fs_fs.h>
#include <linux/writeback.h>
#include <linux/sched/mm.h>
#include <linux/lz4.h>
#include <linux/zstd.h>
#include <linux/fserror.h>
#include "f2fs.h"
#include "node.h"
#include "segment.h"
#include "xattr.h"
#include <trace/events/f2fs.h>
#ifdef CONFIG_F2FS_FS_COMPRESSION
extern const struct address_space_operations f2fs_compress_aops;
#endif
void f2fs_mark_inode_dirty_sync(struct inode *inode, bool sync)
{
if (is_inode_flag_set(inode, FI_NEW_INODE))
return;
if (f2fs_readonly(F2FS_I_SB(inode)->sb))
return;
if (f2fs_inode_dirtied(inode, sync))
return;
/* only atomic file w/ FI_ATOMIC_COMMITTED can be set vfs dirty */
if (f2fs_is_atomic_file(inode) &&
!is_inode_flag_set(inode, FI_ATOMIC_COMMITTED))
return;
mark_inode_dirty_sync(inode);
}
void f2fs_set_inode_flags(struct inode *inode)
{
unsigned int flags = F2FS_I(inode)->i_flags;
unsigned int new_fl = 0;
if (flags & F2FS_SYNC_FL)
new_fl |= S_SYNC;
if (flags & F2FS_APPEND_FL)
new_fl |= S_APPEND;
if (flags & F2FS_IMMUTABLE_FL)
new_fl |= S_IMMUTABLE;
if (flags & F2FS_NOATIME_FL)
new_fl |= S_NOATIME;
if (flags & F2FS_DIRSYNC_FL)
new_fl |= S_DIRSYNC;
if (file_is_encrypt(inode))
new_fl |= S_ENCRYPTED;
if (file_is_verity(inode))
new_fl |= S_VERITY;
if (flags & F2FS_CASEFOLD_FL)
new_fl |= S_CASEFOLD;
inode_set_flags(inode, new_fl,
S_SYNC|S_APPEND|S_IMMUTABLE|S_NOATIME|S_DIRSYNC|
S_ENCRYPTED|S_VERITY|S_CASEFOLD);
}
static void __get_inode_rdev(struct inode *inode, struct folio *node_folio)
{
__le32 *addr = get_dnode_addr(inode, node_folio);
if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode) ||
S_ISFIFO(inode->i_mode) || S_ISSOCK(inode->i_mode)) {
if (addr[0])
inode->i_rdev = old_decode_dev(le32_to_cpu(addr[0]));
else
inode->i_rdev = new_decode_dev(le32_to_cpu(addr[1]));
}
}
static void __set_inode_rdev(struct inode *inode, struct folio *node_folio)
{
__le32 *addr = get_dnode_addr(inode, node_folio);
if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) {
if (old_valid_dev(inode->i_rdev)) {
addr[0] = cpu_to_le32(old_encode_dev(inode->i_rdev));
addr[1] = 0;
} else {
addr[0] = 0;
addr[1] = cpu_to_le32(new_encode_dev(inode->i_rdev));
addr[2] = 0;
}
}
}
static void __recover_inline_status(struct inode *inode, struct folio *ifolio)
{
void *inline_data = inline_data_addr(inode, ifolio);
__le32 *start = inline_data;
__le32 *end = start + MAX_INLINE_DATA(inode) / sizeof(__le32);
while (start < end) {
if (*start++) {
f2fs_folio_wait_writeback(ifolio, NODE, true, true);
set_inode_flag(inode, FI_DATA_EXI