18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
28c2ecf20Sopenharmony_ci/* -*- mode: c; c-basic-offset: 8; -*-
38c2ecf20Sopenharmony_ci * vim: noexpandtab sw=8 ts=8 sts=0:
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * inode.c
68c2ecf20Sopenharmony_ci *
78c2ecf20Sopenharmony_ci * vfs' aops, fops, dops and iops
88c2ecf20Sopenharmony_ci *
98c2ecf20Sopenharmony_ci * Copyright (C) 2002, 2004 Oracle.  All rights reserved.
108c2ecf20Sopenharmony_ci */
118c2ecf20Sopenharmony_ci
128c2ecf20Sopenharmony_ci#include <linux/fs.h>
138c2ecf20Sopenharmony_ci#include <linux/types.h>
148c2ecf20Sopenharmony_ci#include <linux/highmem.h>
158c2ecf20Sopenharmony_ci#include <linux/pagemap.h>
168c2ecf20Sopenharmony_ci#include <linux/quotaops.h>
178c2ecf20Sopenharmony_ci#include <linux/iversion.h>
188c2ecf20Sopenharmony_ci
198c2ecf20Sopenharmony_ci#include <asm/byteorder.h>
208c2ecf20Sopenharmony_ci
218c2ecf20Sopenharmony_ci#include <cluster/masklog.h>
228c2ecf20Sopenharmony_ci
238c2ecf20Sopenharmony_ci#include "ocfs2.h"
248c2ecf20Sopenharmony_ci
258c2ecf20Sopenharmony_ci#include "alloc.h"
268c2ecf20Sopenharmony_ci#include "dir.h"
278c2ecf20Sopenharmony_ci#include "blockcheck.h"
288c2ecf20Sopenharmony_ci#include "dlmglue.h"
298c2ecf20Sopenharmony_ci#include "extent_map.h"
308c2ecf20Sopenharmony_ci#include "file.h"
318c2ecf20Sopenharmony_ci#include "heartbeat.h"
328c2ecf20Sopenharmony_ci#include "inode.h"
338c2ecf20Sopenharmony_ci#include "journal.h"
348c2ecf20Sopenharmony_ci#include "namei.h"
358c2ecf20Sopenharmony_ci#include "suballoc.h"
368c2ecf20Sopenharmony_ci#include "super.h"
378c2ecf20Sopenharmony_ci#include "symlink.h"
388c2ecf20Sopenharmony_ci#include "sysfile.h"
398c2ecf20Sopenharmony_ci#include "uptodate.h"
408c2ecf20Sopenharmony_ci#include "xattr.h"
418c2ecf20Sopenharmony_ci#include "refcounttree.h"
428c2ecf20Sopenharmony_ci#include "ocfs2_trace.h"
438c2ecf20Sopenharmony_ci#include "filecheck.h"
448c2ecf20Sopenharmony_ci
458c2ecf20Sopenharmony_ci#include "buffer_head_io.h"
468c2ecf20Sopenharmony_ci
478c2ecf20Sopenharmony_cistruct ocfs2_find_inode_args
488c2ecf20Sopenharmony_ci{
498c2ecf20Sopenharmony_ci	u64		fi_blkno;
508c2ecf20Sopenharmony_ci	unsigned long	fi_ino;
518c2ecf20Sopenharmony_ci	unsigned int	fi_flags;
528c2ecf20Sopenharmony_ci	unsigned int	fi_sysfile_type;
538c2ecf20Sopenharmony_ci};
548c2ecf20Sopenharmony_ci
558c2ecf20Sopenharmony_cistatic struct lock_class_key ocfs2_sysfile_lock_key[NUM_SYSTEM_INODES];
568c2ecf20Sopenharmony_ci
578c2ecf20Sopenharmony_cistatic int ocfs2_read_locked_inode(struct inode *inode,
588c2ecf20Sopenharmony_ci				   struct ocfs2_find_inode_args *args);
598c2ecf20Sopenharmony_cistatic int ocfs2_init_locked_inode(struct inode *inode, void *opaque);
608c2ecf20Sopenharmony_cistatic int ocfs2_find_actor(struct inode *inode, void *opaque);
618c2ecf20Sopenharmony_cistatic int ocfs2_truncate_for_delete(struct ocfs2_super *osb,
628c2ecf20Sopenharmony_ci				    struct inode *inode,
638c2ecf20Sopenharmony_ci				    struct buffer_head *fe_bh);
648c2ecf20Sopenharmony_ci
658c2ecf20Sopenharmony_cistatic int ocfs2_filecheck_read_inode_block_full(struct inode *inode,
668c2ecf20Sopenharmony_ci						 struct buffer_head **bh,
678c2ecf20Sopenharmony_ci						 int flags, int type);
688c2ecf20Sopenharmony_cistatic int ocfs2_filecheck_validate_inode_block(struct super_block *sb,
698c2ecf20Sopenharmony_ci						struct buffer_head *bh);
708c2ecf20Sopenharmony_cistatic int ocfs2_filecheck_repair_inode_block(struct super_block *sb,
718c2ecf20Sopenharmony_ci					      struct buffer_head *bh);
728c2ecf20Sopenharmony_ci
738c2ecf20Sopenharmony_civoid ocfs2_set_inode_flags(struct inode *inode)
748c2ecf20Sopenharmony_ci{
758c2ecf20Sopenharmony_ci	unsigned int flags = OCFS2_I(inode)->ip_attr;
768c2ecf20Sopenharmony_ci
778c2ecf20Sopenharmony_ci	inode->i_flags &= ~(S_IMMUTABLE |
788c2ecf20Sopenharmony_ci		S_SYNC | S_APPEND | S_NOATIME | S_DIRSYNC);
798c2ecf20Sopenharmony_ci
808c2ecf20Sopenharmony_ci	if (flags & OCFS2_IMMUTABLE_FL)
818c2ecf20Sopenharmony_ci		inode->i_flags |= S_IMMUTABLE;
828c2ecf20Sopenharmony_ci
838c2ecf20Sopenharmony_ci	if (flags & OCFS2_SYNC_FL)
848c2ecf20Sopenharmony_ci		inode->i_flags |= S_SYNC;
858c2ecf20Sopenharmony_ci	if (flags & OCFS2_APPEND_FL)
868c2ecf20Sopenharmony_ci		inode->i_flags |= S_APPEND;
878c2ecf20Sopenharmony_ci	if (flags & OCFS2_NOATIME_FL)
888c2ecf20Sopenharmony_ci		inode->i_flags |= S_NOATIME;
898c2ecf20Sopenharmony_ci	if (flags & OCFS2_DIRSYNC_FL)
908c2ecf20Sopenharmony_ci		inode->i_flags |= S_DIRSYNC;
918c2ecf20Sopenharmony_ci}
928c2ecf20Sopenharmony_ci
938c2ecf20Sopenharmony_ci/* Propagate flags from i_flags to OCFS2_I(inode)->ip_attr */
948c2ecf20Sopenharmony_civoid ocfs2_get_inode_flags(struct ocfs2_inode_info *oi)
958c2ecf20Sopenharmony_ci{
968c2ecf20Sopenharmony_ci	unsigned int flags = oi->vfs_inode.i_flags;
978c2ecf20Sopenharmony_ci
988c2ecf20Sopenharmony_ci	oi->ip_attr &= ~(OCFS2_SYNC_FL|OCFS2_APPEND_FL|
998c2ecf20Sopenharmony_ci			OCFS2_IMMUTABLE_FL|OCFS2_NOATIME_FL|OCFS2_DIRSYNC_FL);
1008c2ecf20Sopenharmony_ci	if (flags & S_SYNC)
1018c2ecf20Sopenharmony_ci		oi->ip_attr |= OCFS2_SYNC_FL;
1028c2ecf20Sopenharmony_ci	if (flags & S_APPEND)
1038c2ecf20Sopenharmony_ci		oi->ip_attr |= OCFS2_APPEND_FL;
1048c2ecf20Sopenharmony_ci	if (flags & S_IMMUTABLE)
1058c2ecf20Sopenharmony_ci		oi->ip_attr |= OCFS2_IMMUTABLE_FL;
1068c2ecf20Sopenharmony_ci	if (flags & S_NOATIME)
1078c2ecf20Sopenharmony_ci		oi->ip_attr |= OCFS2_NOATIME_FL;
1088c2ecf20Sopenharmony_ci	if (flags & S_DIRSYNC)
1098c2ecf20Sopenharmony_ci		oi->ip_attr |= OCFS2_DIRSYNC_FL;
1108c2ecf20Sopenharmony_ci}
1118c2ecf20Sopenharmony_ci
1128c2ecf20Sopenharmony_cistruct inode *ocfs2_ilookup(struct super_block *sb, u64 blkno)
1138c2ecf20Sopenharmony_ci{
1148c2ecf20Sopenharmony_ci	struct ocfs2_find_inode_args args;
1158c2ecf20Sopenharmony_ci
1168c2ecf20Sopenharmony_ci	args.fi_blkno = blkno;
1178c2ecf20Sopenharmony_ci	args.fi_flags = 0;
1188c2ecf20Sopenharmony_ci	args.fi_ino = ino_from_blkno(sb, blkno);
1198c2ecf20Sopenharmony_ci	args.fi_sysfile_type = 0;
1208c2ecf20Sopenharmony_ci
1218c2ecf20Sopenharmony_ci	return ilookup5(sb, blkno, ocfs2_find_actor, &args);
1228c2ecf20Sopenharmony_ci}
1238c2ecf20Sopenharmony_cistruct inode *ocfs2_iget(struct ocfs2_super *osb, u64 blkno, unsigned flags,
1248c2ecf20Sopenharmony_ci			 int sysfile_type)
1258c2ecf20Sopenharmony_ci{
1268c2ecf20Sopenharmony_ci	int rc = -ESTALE;
1278c2ecf20Sopenharmony_ci	struct inode *inode = NULL;
1288c2ecf20Sopenharmony_ci	struct super_block *sb = osb->sb;
1298c2ecf20Sopenharmony_ci	struct ocfs2_find_inode_args args;
1308c2ecf20Sopenharmony_ci	journal_t *journal = OCFS2_SB(sb)->journal->j_journal;
1318c2ecf20Sopenharmony_ci
1328c2ecf20Sopenharmony_ci	trace_ocfs2_iget_begin((unsigned long long)blkno, flags,
1338c2ecf20Sopenharmony_ci			       sysfile_type);
1348c2ecf20Sopenharmony_ci
1358c2ecf20Sopenharmony_ci	/* Ok. By now we've either got the offsets passed to us by the
1368c2ecf20Sopenharmony_ci	 * caller, or we just pulled them off the bh. Lets do some
1378c2ecf20Sopenharmony_ci	 * sanity checks to make sure they're OK. */
1388c2ecf20Sopenharmony_ci	if (blkno == 0) {
1398c2ecf20Sopenharmony_ci		inode = ERR_PTR(-EINVAL);
1408c2ecf20Sopenharmony_ci		mlog_errno(PTR_ERR(inode));
1418c2ecf20Sopenharmony_ci		goto bail;
1428c2ecf20Sopenharmony_ci	}
1438c2ecf20Sopenharmony_ci
1448c2ecf20Sopenharmony_ci	args.fi_blkno = blkno;
1458c2ecf20Sopenharmony_ci	args.fi_flags = flags;
1468c2ecf20Sopenharmony_ci	args.fi_ino = ino_from_blkno(sb, blkno);
1478c2ecf20Sopenharmony_ci	args.fi_sysfile_type = sysfile_type;
1488c2ecf20Sopenharmony_ci
1498c2ecf20Sopenharmony_ci	inode = iget5_locked(sb, args.fi_ino, ocfs2_find_actor,
1508c2ecf20Sopenharmony_ci			     ocfs2_init_locked_inode, &args);
1518c2ecf20Sopenharmony_ci	/* inode was *not* in the inode cache. 2.6.x requires
1528c2ecf20Sopenharmony_ci	 * us to do our own read_inode call and unlock it
1538c2ecf20Sopenharmony_ci	 * afterwards. */
1548c2ecf20Sopenharmony_ci	if (inode == NULL) {
1558c2ecf20Sopenharmony_ci		inode = ERR_PTR(-ENOMEM);
1568c2ecf20Sopenharmony_ci		mlog_errno(PTR_ERR(inode));
1578c2ecf20Sopenharmony_ci		goto bail;
1588c2ecf20Sopenharmony_ci	}
1598c2ecf20Sopenharmony_ci	trace_ocfs2_iget5_locked(inode->i_state);
1608c2ecf20Sopenharmony_ci	if (inode->i_state & I_NEW) {
1618c2ecf20Sopenharmony_ci		rc = ocfs2_read_locked_inode(inode, &args);
1628c2ecf20Sopenharmony_ci		unlock_new_inode(inode);
1638c2ecf20Sopenharmony_ci	}
1648c2ecf20Sopenharmony_ci	if (is_bad_inode(inode)) {
1658c2ecf20Sopenharmony_ci		iput(inode);
1668c2ecf20Sopenharmony_ci		inode = ERR_PTR(rc);
1678c2ecf20Sopenharmony_ci		goto bail;
1688c2ecf20Sopenharmony_ci	}
1698c2ecf20Sopenharmony_ci
1708c2ecf20Sopenharmony_ci	/*
1718c2ecf20Sopenharmony_ci	 * Set transaction id's of transactions that have to be committed
1728c2ecf20Sopenharmony_ci	 * to finish f[data]sync. We set them to currently running transaction
1738c2ecf20Sopenharmony_ci	 * as we cannot be sure that the inode or some of its metadata isn't
1748c2ecf20Sopenharmony_ci	 * part of the transaction - the inode could have been reclaimed and
1758c2ecf20Sopenharmony_ci	 * now it is reread from disk.
1768c2ecf20Sopenharmony_ci	 */
1778c2ecf20Sopenharmony_ci	if (journal) {
1788c2ecf20Sopenharmony_ci		transaction_t *transaction;
1798c2ecf20Sopenharmony_ci		tid_t tid;
1808c2ecf20Sopenharmony_ci		struct ocfs2_inode_info *oi = OCFS2_I(inode);
1818c2ecf20Sopenharmony_ci
1828c2ecf20Sopenharmony_ci		read_lock(&journal->j_state_lock);
1838c2ecf20Sopenharmony_ci		if (journal->j_running_transaction)
1848c2ecf20Sopenharmony_ci			transaction = journal->j_running_transaction;
1858c2ecf20Sopenharmony_ci		else
1868c2ecf20Sopenharmony_ci			transaction = journal->j_committing_transaction;
1878c2ecf20Sopenharmony_ci		if (transaction)
1888c2ecf20Sopenharmony_ci			tid = transaction->t_tid;
1898c2ecf20Sopenharmony_ci		else
1908c2ecf20Sopenharmony_ci			tid = journal->j_commit_sequence;
1918c2ecf20Sopenharmony_ci		read_unlock(&journal->j_state_lock);
1928c2ecf20Sopenharmony_ci		oi->i_sync_tid = tid;
1938c2ecf20Sopenharmony_ci		oi->i_datasync_tid = tid;
1948c2ecf20Sopenharmony_ci	}
1958c2ecf20Sopenharmony_ci
1968c2ecf20Sopenharmony_cibail:
1978c2ecf20Sopenharmony_ci	if (!IS_ERR(inode)) {
1988c2ecf20Sopenharmony_ci		trace_ocfs2_iget_end(inode,
1998c2ecf20Sopenharmony_ci			(unsigned long long)OCFS2_I(inode)->ip_blkno);
2008c2ecf20Sopenharmony_ci	}
2018c2ecf20Sopenharmony_ci
2028c2ecf20Sopenharmony_ci	return inode;
2038c2ecf20Sopenharmony_ci}
2048c2ecf20Sopenharmony_ci
2058c2ecf20Sopenharmony_ci
2068c2ecf20Sopenharmony_ci/*
2078c2ecf20Sopenharmony_ci * here's how inodes get read from disk:
2088c2ecf20Sopenharmony_ci * iget5_locked -> find_actor -> OCFS2_FIND_ACTOR
2098c2ecf20Sopenharmony_ci * found? : return the in-memory inode
2108c2ecf20Sopenharmony_ci * not found? : get_new_inode -> OCFS2_INIT_LOCKED_INODE
2118c2ecf20Sopenharmony_ci */
2128c2ecf20Sopenharmony_ci
2138c2ecf20Sopenharmony_cistatic int ocfs2_find_actor(struct inode *inode, void *opaque)
2148c2ecf20Sopenharmony_ci{
2158c2ecf20Sopenharmony_ci	struct ocfs2_find_inode_args *args = NULL;
2168c2ecf20Sopenharmony_ci	struct ocfs2_inode_info *oi = OCFS2_I(inode);
2178c2ecf20Sopenharmony_ci	int ret = 0;
2188c2ecf20Sopenharmony_ci
2198c2ecf20Sopenharmony_ci	args = opaque;
2208c2ecf20Sopenharmony_ci
2218c2ecf20Sopenharmony_ci	mlog_bug_on_msg(!inode, "No inode in find actor!\n");
2228c2ecf20Sopenharmony_ci
2238c2ecf20Sopenharmony_ci	trace_ocfs2_find_actor(inode, inode->i_ino, opaque, args->fi_blkno);
2248c2ecf20Sopenharmony_ci
2258c2ecf20Sopenharmony_ci	if (oi->ip_blkno != args->fi_blkno)
2268c2ecf20Sopenharmony_ci		goto bail;
2278c2ecf20Sopenharmony_ci
2288c2ecf20Sopenharmony_ci	ret = 1;
2298c2ecf20Sopenharmony_cibail:
2308c2ecf20Sopenharmony_ci	return ret;
2318c2ecf20Sopenharmony_ci}
2328c2ecf20Sopenharmony_ci
2338c2ecf20Sopenharmony_ci/*
2348c2ecf20Sopenharmony_ci * initialize the new inode, but don't do anything that would cause
2358c2ecf20Sopenharmony_ci * us to sleep.
2368c2ecf20Sopenharmony_ci * return 0 on success, 1 on failure
2378c2ecf20Sopenharmony_ci */
2388c2ecf20Sopenharmony_cistatic int ocfs2_init_locked_inode(struct inode *inode, void *opaque)
2398c2ecf20Sopenharmony_ci{
2408c2ecf20Sopenharmony_ci	struct ocfs2_find_inode_args *args = opaque;
2418c2ecf20Sopenharmony_ci	static struct lock_class_key ocfs2_quota_ip_alloc_sem_key,
2428c2ecf20Sopenharmony_ci				     ocfs2_file_ip_alloc_sem_key;
2438c2ecf20Sopenharmony_ci
2448c2ecf20Sopenharmony_ci	inode->i_ino = args->fi_ino;
2458c2ecf20Sopenharmony_ci	OCFS2_I(inode)->ip_blkno = args->fi_blkno;
2468c2ecf20Sopenharmony_ci	if (args->fi_sysfile_type != 0)
2478c2ecf20Sopenharmony_ci		lockdep_set_class(&inode->i_rwsem,
2488c2ecf20Sopenharmony_ci			&ocfs2_sysfile_lock_key[args->fi_sysfile_type]);
2498c2ecf20Sopenharmony_ci	if (args->fi_sysfile_type == USER_QUOTA_SYSTEM_INODE ||
2508c2ecf20Sopenharmony_ci	    args->fi_sysfile_type == GROUP_QUOTA_SYSTEM_INODE ||
2518c2ecf20Sopenharmony_ci	    args->fi_sysfile_type == LOCAL_USER_QUOTA_SYSTEM_INODE ||
2528c2ecf20Sopenharmony_ci	    args->fi_sysfile_type == LOCAL_GROUP_QUOTA_SYSTEM_INODE)
2538c2ecf20Sopenharmony_ci		lockdep_set_class(&OCFS2_I(inode)->ip_alloc_sem,
2548c2ecf20Sopenharmony_ci				  &ocfs2_quota_ip_alloc_sem_key);
2558c2ecf20Sopenharmony_ci	else
2568c2ecf20Sopenharmony_ci		lockdep_set_class(&OCFS2_I(inode)->ip_alloc_sem,
2578c2ecf20Sopenharmony_ci				  &ocfs2_file_ip_alloc_sem_key);
2588c2ecf20Sopenharmony_ci
2598c2ecf20Sopenharmony_ci	return 0;
2608c2ecf20Sopenharmony_ci}
2618c2ecf20Sopenharmony_ci
2628c2ecf20Sopenharmony_civoid ocfs2_populate_inode(struct inode *inode, struct ocfs2_dinode *fe,
2638c2ecf20Sopenharmony_ci			  int create_ino)
2648c2ecf20Sopenharmony_ci{
2658c2ecf20Sopenharmony_ci	struct super_block *sb;
2668c2ecf20Sopenharmony_ci	struct ocfs2_super *osb;
2678c2ecf20Sopenharmony_ci	int use_plocks = 1;
2688c2ecf20Sopenharmony_ci
2698c2ecf20Sopenharmony_ci	sb = inode->i_sb;
2708c2ecf20Sopenharmony_ci	osb = OCFS2_SB(sb);
2718c2ecf20Sopenharmony_ci
2728c2ecf20Sopenharmony_ci	if ((osb->s_mount_opt & OCFS2_MOUNT_LOCALFLOCKS) ||
2738c2ecf20Sopenharmony_ci	    ocfs2_mount_local(osb) || !ocfs2_stack_supports_plocks())
2748c2ecf20Sopenharmony_ci		use_plocks = 0;
2758c2ecf20Sopenharmony_ci
2768c2ecf20Sopenharmony_ci	/*
2778c2ecf20Sopenharmony_ci	 * These have all been checked by ocfs2_read_inode_block() or set
2788c2ecf20Sopenharmony_ci	 * by ocfs2_mknod_locked(), so a failure is a code bug.
2798c2ecf20Sopenharmony_ci	 */
2808c2ecf20Sopenharmony_ci	BUG_ON(!OCFS2_IS_VALID_DINODE(fe));  /* This means that read_inode
2818c2ecf20Sopenharmony_ci						cannot create a superblock
2828c2ecf20Sopenharmony_ci						inode today.  change if
2838c2ecf20Sopenharmony_ci						that is needed. */
2848c2ecf20Sopenharmony_ci	BUG_ON(!(fe->i_flags & cpu_to_le32(OCFS2_VALID_FL)));
2858c2ecf20Sopenharmony_ci	BUG_ON(le32_to_cpu(fe->i_fs_generation) != osb->fs_generation);
2868c2ecf20Sopenharmony_ci
2878c2ecf20Sopenharmony_ci
2888c2ecf20Sopenharmony_ci	OCFS2_I(inode)->ip_clusters = le32_to_cpu(fe->i_clusters);
2898c2ecf20Sopenharmony_ci	OCFS2_I(inode)->ip_attr = le32_to_cpu(fe->i_attr);
2908c2ecf20Sopenharmony_ci	OCFS2_I(inode)->ip_dyn_features = le16_to_cpu(fe->i_dyn_features);
2918c2ecf20Sopenharmony_ci
2928c2ecf20Sopenharmony_ci	inode_set_iversion(inode, 1);
2938c2ecf20Sopenharmony_ci	inode->i_generation = le32_to_cpu(fe->i_generation);
2948c2ecf20Sopenharmony_ci	inode->i_rdev = huge_decode_dev(le64_to_cpu(fe->id1.dev1.i_rdev));
2958c2ecf20Sopenharmony_ci	inode->i_mode = le16_to_cpu(fe->i_mode);
2968c2ecf20Sopenharmony_ci	i_uid_write(inode, le32_to_cpu(fe->i_uid));
2978c2ecf20Sopenharmony_ci	i_gid_write(inode, le32_to_cpu(fe->i_gid));
2988c2ecf20Sopenharmony_ci
2998c2ecf20Sopenharmony_ci	/* Fast symlinks will have i_size but no allocated clusters. */
3008c2ecf20Sopenharmony_ci	if (S_ISLNK(inode->i_mode) && !fe->i_clusters) {
3018c2ecf20Sopenharmony_ci		inode->i_blocks = 0;
3028c2ecf20Sopenharmony_ci		inode->i_mapping->a_ops = &ocfs2_fast_symlink_aops;
3038c2ecf20Sopenharmony_ci	} else {
3048c2ecf20Sopenharmony_ci		inode->i_blocks = ocfs2_inode_sector_count(inode);
3058c2ecf20Sopenharmony_ci		inode->i_mapping->a_ops = &ocfs2_aops;
3068c2ecf20Sopenharmony_ci	}
3078c2ecf20Sopenharmony_ci	inode->i_atime.tv_sec = le64_to_cpu(fe->i_atime);
3088c2ecf20Sopenharmony_ci	inode->i_atime.tv_nsec = le32_to_cpu(fe->i_atime_nsec);
3098c2ecf20Sopenharmony_ci	inode->i_mtime.tv_sec = le64_to_cpu(fe->i_mtime);
3108c2ecf20Sopenharmony_ci	inode->i_mtime.tv_nsec = le32_to_cpu(fe->i_mtime_nsec);
3118c2ecf20Sopenharmony_ci	inode->i_ctime.tv_sec = le64_to_cpu(fe->i_ctime);
3128c2ecf20Sopenharmony_ci	inode->i_ctime.tv_nsec = le32_to_cpu(fe->i_ctime_nsec);
3138c2ecf20Sopenharmony_ci
3148c2ecf20Sopenharmony_ci	if (OCFS2_I(inode)->ip_blkno != le64_to_cpu(fe->i_blkno))
3158c2ecf20Sopenharmony_ci		mlog(ML_ERROR,
3168c2ecf20Sopenharmony_ci		     "ip_blkno %llu != i_blkno %llu!\n",
3178c2ecf20Sopenharmony_ci		     (unsigned long long)OCFS2_I(inode)->ip_blkno,
3188c2ecf20Sopenharmony_ci		     (unsigned long long)le64_to_cpu(fe->i_blkno));
3198c2ecf20Sopenharmony_ci
3208c2ecf20Sopenharmony_ci	set_nlink(inode, ocfs2_read_links_count(fe));
3218c2ecf20Sopenharmony_ci
3228c2ecf20Sopenharmony_ci	trace_ocfs2_populate_inode(OCFS2_I(inode)->ip_blkno,
3238c2ecf20Sopenharmony_ci				   le32_to_cpu(fe->i_flags));
3248c2ecf20Sopenharmony_ci	if (fe->i_flags & cpu_to_le32(OCFS2_SYSTEM_FL)) {
3258c2ecf20Sopenharmony_ci		OCFS2_I(inode)->ip_flags |= OCFS2_INODE_SYSTEM_FILE;
3268c2ecf20Sopenharmony_ci		inode->i_flags |= S_NOQUOTA;
3278c2ecf20Sopenharmony_ci	}
3288c2ecf20Sopenharmony_ci
3298c2ecf20Sopenharmony_ci	if (fe->i_flags & cpu_to_le32(OCFS2_LOCAL_ALLOC_FL)) {
3308c2ecf20Sopenharmony_ci		OCFS2_I(inode)->ip_flags |= OCFS2_INODE_BITMAP;
3318c2ecf20Sopenharmony_ci	} else if (fe->i_flags & cpu_to_le32(OCFS2_BITMAP_FL)) {
3328c2ecf20Sopenharmony_ci		OCFS2_I(inode)->ip_flags |= OCFS2_INODE_BITMAP;
3338c2ecf20Sopenharmony_ci	} else if (fe->i_flags & cpu_to_le32(OCFS2_QUOTA_FL)) {
3348c2ecf20Sopenharmony_ci		inode->i_flags |= S_NOQUOTA;
3358c2ecf20Sopenharmony_ci	} else if (fe->i_flags & cpu_to_le32(OCFS2_SUPER_BLOCK_FL)) {
3368c2ecf20Sopenharmony_ci		/* we can't actually hit this as read_inode can't
3378c2ecf20Sopenharmony_ci		 * handle superblocks today ;-) */
3388c2ecf20Sopenharmony_ci		BUG();
3398c2ecf20Sopenharmony_ci	}
3408c2ecf20Sopenharmony_ci
3418c2ecf20Sopenharmony_ci	switch (inode->i_mode & S_IFMT) {
3428c2ecf20Sopenharmony_ci	    case S_IFREG:
3438c2ecf20Sopenharmony_ci		    if (use_plocks)
3448c2ecf20Sopenharmony_ci			    inode->i_fop = &ocfs2_fops;
3458c2ecf20Sopenharmony_ci		    else
3468c2ecf20Sopenharmony_ci			    inode->i_fop = &ocfs2_fops_no_plocks;
3478c2ecf20Sopenharmony_ci		    inode->i_op = &ocfs2_file_iops;
3488c2ecf20Sopenharmony_ci		    i_size_write(inode, le64_to_cpu(fe->i_size));
3498c2ecf20Sopenharmony_ci		    break;
3508c2ecf20Sopenharmony_ci	    case S_IFDIR:
3518c2ecf20Sopenharmony_ci		    inode->i_op = &ocfs2_dir_iops;
3528c2ecf20Sopenharmony_ci		    if (use_plocks)
3538c2ecf20Sopenharmony_ci			    inode->i_fop = &ocfs2_dops;
3548c2ecf20Sopenharmony_ci		    else
3558c2ecf20Sopenharmony_ci			    inode->i_fop = &ocfs2_dops_no_plocks;
3568c2ecf20Sopenharmony_ci		    i_size_write(inode, le64_to_cpu(fe->i_size));
3578c2ecf20Sopenharmony_ci		    OCFS2_I(inode)->ip_dir_lock_gen = 1;
3588c2ecf20Sopenharmony_ci		    break;
3598c2ecf20Sopenharmony_ci	    case S_IFLNK:
3608c2ecf20Sopenharmony_ci		    inode->i_op = &ocfs2_symlink_inode_operations;
3618c2ecf20Sopenharmony_ci		    inode_nohighmem(inode);
3628c2ecf20Sopenharmony_ci		    i_size_write(inode, le64_to_cpu(fe->i_size));
3638c2ecf20Sopenharmony_ci		    break;
3648c2ecf20Sopenharmony_ci	    default:
3658c2ecf20Sopenharmony_ci		    inode->i_op = &ocfs2_special_file_iops;
3668c2ecf20Sopenharmony_ci		    init_special_inode(inode, inode->i_mode,
3678c2ecf20Sopenharmony_ci				       inode->i_rdev);
3688c2ecf20Sopenharmony_ci		    break;
3698c2ecf20Sopenharmony_ci	}
3708c2ecf20Sopenharmony_ci
3718c2ecf20Sopenharmony_ci	if (create_ino) {
3728c2ecf20Sopenharmony_ci		inode->i_ino = ino_from_blkno(inode->i_sb,
3738c2ecf20Sopenharmony_ci			       le64_to_cpu(fe->i_blkno));
3748c2ecf20Sopenharmony_ci
3758c2ecf20Sopenharmony_ci		/*
3768c2ecf20Sopenharmony_ci		 * If we ever want to create system files from kernel,
3778c2ecf20Sopenharmony_ci		 * the generation argument to
3788c2ecf20Sopenharmony_ci		 * ocfs2_inode_lock_res_init() will have to change.
3798c2ecf20Sopenharmony_ci		 */
3808c2ecf20Sopenharmony_ci		BUG_ON(le32_to_cpu(fe->i_flags) & OCFS2_SYSTEM_FL);
3818c2ecf20Sopenharmony_ci
3828c2ecf20Sopenharmony_ci		ocfs2_inode_lock_res_init(&OCFS2_I(inode)->ip_inode_lockres,
3838c2ecf20Sopenharmony_ci					  OCFS2_LOCK_TYPE_META, 0, inode);
3848c2ecf20Sopenharmony_ci
3858c2ecf20Sopenharmony_ci		ocfs2_inode_lock_res_init(&OCFS2_I(inode)->ip_open_lockres,
3868c2ecf20Sopenharmony_ci					  OCFS2_LOCK_TYPE_OPEN, 0, inode);
3878c2ecf20Sopenharmony_ci	}
3888c2ecf20Sopenharmony_ci
3898c2ecf20Sopenharmony_ci	ocfs2_inode_lock_res_init(&OCFS2_I(inode)->ip_rw_lockres,
3908c2ecf20Sopenharmony_ci				  OCFS2_LOCK_TYPE_RW, inode->i_generation,
3918c2ecf20Sopenharmony_ci				  inode);
3928c2ecf20Sopenharmony_ci
3938c2ecf20Sopenharmony_ci	ocfs2_set_inode_flags(inode);
3948c2ecf20Sopenharmony_ci
3958c2ecf20Sopenharmony_ci	OCFS2_I(inode)->ip_last_used_slot = 0;
3968c2ecf20Sopenharmony_ci	OCFS2_I(inode)->ip_last_used_group = 0;
3978c2ecf20Sopenharmony_ci
3988c2ecf20Sopenharmony_ci	if (S_ISDIR(inode->i_mode))
3998c2ecf20Sopenharmony_ci		ocfs2_resv_set_type(&OCFS2_I(inode)->ip_la_data_resv,
4008c2ecf20Sopenharmony_ci				    OCFS2_RESV_FLAG_DIR);
4018c2ecf20Sopenharmony_ci}
4028c2ecf20Sopenharmony_ci
4038c2ecf20Sopenharmony_cistatic int ocfs2_read_locked_inode(struct inode *inode,
4048c2ecf20Sopenharmony_ci				   struct ocfs2_find_inode_args *args)
4058c2ecf20Sopenharmony_ci{
4068c2ecf20Sopenharmony_ci	struct super_block *sb;
4078c2ecf20Sopenharmony_ci	struct ocfs2_super *osb;
4088c2ecf20Sopenharmony_ci	struct ocfs2_dinode *fe;
4098c2ecf20Sopenharmony_ci	struct buffer_head *bh = NULL;
4108c2ecf20Sopenharmony_ci	int status, can_lock, lock_level = 0;
4118c2ecf20Sopenharmony_ci	u32 generation = 0;
4128c2ecf20Sopenharmony_ci
4138c2ecf20Sopenharmony_ci	status = -EINVAL;
4148c2ecf20Sopenharmony_ci	sb = inode->i_sb;
4158c2ecf20Sopenharmony_ci	osb = OCFS2_SB(sb);
4168c2ecf20Sopenharmony_ci
4178c2ecf20Sopenharmony_ci	/*
4188c2ecf20Sopenharmony_ci	 * To improve performance of cold-cache inode stats, we take
4198c2ecf20Sopenharmony_ci	 * the cluster lock here if possible.
4208c2ecf20Sopenharmony_ci	 *
4218c2ecf20Sopenharmony_ci	 * Generally, OCFS2 never trusts the contents of an inode
4228c2ecf20Sopenharmony_ci	 * unless it's holding a cluster lock, so taking it here isn't
4238c2ecf20Sopenharmony_ci	 * a correctness issue as much as it is a performance
4248c2ecf20Sopenharmony_ci	 * improvement.
4258c2ecf20Sopenharmony_ci	 *
4268c2ecf20Sopenharmony_ci	 * There are three times when taking the lock is not a good idea:
4278c2ecf20Sopenharmony_ci	 *
4288c2ecf20Sopenharmony_ci	 * 1) During startup, before we have initialized the DLM.
4298c2ecf20Sopenharmony_ci	 *
4308c2ecf20Sopenharmony_ci	 * 2) If we are reading certain system files which never get
4318c2ecf20Sopenharmony_ci	 *    cluster locks (local alloc, truncate log).
4328c2ecf20Sopenharmony_ci	 *
4338c2ecf20Sopenharmony_ci	 * 3) If the process doing the iget() is responsible for
4348c2ecf20Sopenharmony_ci	 *    orphan dir recovery. We're holding the orphan dir lock and
4358c2ecf20Sopenharmony_ci	 *    can get into a deadlock with another process on another
4368c2ecf20Sopenharmony_ci	 *    node in ->delete_inode().
4378c2ecf20Sopenharmony_ci	 *
4388c2ecf20Sopenharmony_ci	 * #1 and #2 can be simply solved by never taking the lock
4398c2ecf20Sopenharmony_ci	 * here for system files (which are the only type we read
4408c2ecf20Sopenharmony_ci	 * during mount). It's a heavier approach, but our main
4418c2ecf20Sopenharmony_ci	 * concern is user-accessible files anyway.
4428c2ecf20Sopenharmony_ci	 *
4438c2ecf20Sopenharmony_ci	 * #3 works itself out because we'll eventually take the
4448c2ecf20Sopenharmony_ci	 * cluster lock before trusting anything anyway.
4458c2ecf20Sopenharmony_ci	 */
4468c2ecf20Sopenharmony_ci	can_lock = !(args->fi_flags & OCFS2_FI_FLAG_SYSFILE)
4478c2ecf20Sopenharmony_ci		&& !(args->fi_flags & OCFS2_FI_FLAG_ORPHAN_RECOVERY)
4488c2ecf20Sopenharmony_ci		&& !ocfs2_mount_local(osb);
4498c2ecf20Sopenharmony_ci
4508c2ecf20Sopenharmony_ci	trace_ocfs2_read_locked_inode(
4518c2ecf20Sopenharmony_ci		(unsigned long long)OCFS2_I(inode)->ip_blkno, can_lock);
4528c2ecf20Sopenharmony_ci
4538c2ecf20Sopenharmony_ci	/*
4548c2ecf20Sopenharmony_ci	 * To maintain backwards compatibility with older versions of
4558c2ecf20Sopenharmony_ci	 * ocfs2-tools, we still store the generation value for system
4568c2ecf20Sopenharmony_ci	 * files. The only ones that actually matter to userspace are
4578c2ecf20Sopenharmony_ci	 * the journals, but it's easier and inexpensive to just flag
4588c2ecf20Sopenharmony_ci	 * all system files similarly.
4598c2ecf20Sopenharmony_ci	 */
4608c2ecf20Sopenharmony_ci	if (args->fi_flags & OCFS2_FI_FLAG_SYSFILE)
4618c2ecf20Sopenharmony_ci		generation = osb->fs_generation;
4628c2ecf20Sopenharmony_ci
4638c2ecf20Sopenharmony_ci	ocfs2_inode_lock_res_init(&OCFS2_I(inode)->ip_inode_lockres,
4648c2ecf20Sopenharmony_ci				  OCFS2_LOCK_TYPE_META,
4658c2ecf20Sopenharmony_ci				  generation, inode);
4668c2ecf20Sopenharmony_ci
4678c2ecf20Sopenharmony_ci	ocfs2_inode_lock_res_init(&OCFS2_I(inode)->ip_open_lockres,
4688c2ecf20Sopenharmony_ci				  OCFS2_LOCK_TYPE_OPEN,
4698c2ecf20Sopenharmony_ci				  0, inode);
4708c2ecf20Sopenharmony_ci
4718c2ecf20Sopenharmony_ci	if (can_lock) {
4728c2ecf20Sopenharmony_ci		status = ocfs2_open_lock(inode);
4738c2ecf20Sopenharmony_ci		if (status) {
4748c2ecf20Sopenharmony_ci			make_bad_inode(inode);
4758c2ecf20Sopenharmony_ci			mlog_errno(status);
4768c2ecf20Sopenharmony_ci			return status;
4778c2ecf20Sopenharmony_ci		}
4788c2ecf20Sopenharmony_ci		status = ocfs2_inode_lock(inode, NULL, lock_level);
4798c2ecf20Sopenharmony_ci		if (status) {
4808c2ecf20Sopenharmony_ci			make_bad_inode(inode);
4818c2ecf20Sopenharmony_ci			mlog_errno(status);
4828c2ecf20Sopenharmony_ci			return status;
4838c2ecf20Sopenharmony_ci		}
4848c2ecf20Sopenharmony_ci	}
4858c2ecf20Sopenharmony_ci
4868c2ecf20Sopenharmony_ci	if (args->fi_flags & OCFS2_FI_FLAG_ORPHAN_RECOVERY) {
4878c2ecf20Sopenharmony_ci		status = ocfs2_try_open_lock(inode, 0);
4888c2ecf20Sopenharmony_ci		if (status) {
4898c2ecf20Sopenharmony_ci			make_bad_inode(inode);
4908c2ecf20Sopenharmony_ci			return status;
4918c2ecf20Sopenharmony_ci		}
4928c2ecf20Sopenharmony_ci	}
4938c2ecf20Sopenharmony_ci
4948c2ecf20Sopenharmony_ci	if (can_lock) {
4958c2ecf20Sopenharmony_ci		if (args->fi_flags & OCFS2_FI_FLAG_FILECHECK_CHK)
4968c2ecf20Sopenharmony_ci			status = ocfs2_filecheck_read_inode_block_full(inode,
4978c2ecf20Sopenharmony_ci						&bh, OCFS2_BH_IGNORE_CACHE, 0);
4988c2ecf20Sopenharmony_ci		else if (args->fi_flags & OCFS2_FI_FLAG_FILECHECK_FIX)
4998c2ecf20Sopenharmony_ci			status = ocfs2_filecheck_read_inode_block_full(inode,
5008c2ecf20Sopenharmony_ci						&bh, OCFS2_BH_IGNORE_CACHE, 1);
5018c2ecf20Sopenharmony_ci		else
5028c2ecf20Sopenharmony_ci			status = ocfs2_read_inode_block_full(inode,
5038c2ecf20Sopenharmony_ci						&bh, OCFS2_BH_IGNORE_CACHE);
5048c2ecf20Sopenharmony_ci	} else {
5058c2ecf20Sopenharmony_ci		status = ocfs2_read_blocks_sync(osb, args->fi_blkno, 1, &bh);
5068c2ecf20Sopenharmony_ci		/*
5078c2ecf20Sopenharmony_ci		 * If buffer is in jbd, then its checksum may not have been
5088c2ecf20Sopenharmony_ci		 * computed as yet.
5098c2ecf20Sopenharmony_ci		 */
5108c2ecf20Sopenharmony_ci		if (!status && !buffer_jbd(bh)) {
5118c2ecf20Sopenharmony_ci			if (args->fi_flags & OCFS2_FI_FLAG_FILECHECK_CHK)
5128c2ecf20Sopenharmony_ci				status = ocfs2_filecheck_validate_inode_block(
5138c2ecf20Sopenharmony_ci								osb->sb, bh);
5148c2ecf20Sopenharmony_ci			else if (args->fi_flags & OCFS2_FI_FLAG_FILECHECK_FIX)
5158c2ecf20Sopenharmony_ci				status = ocfs2_filecheck_repair_inode_block(
5168c2ecf20Sopenharmony_ci								osb->sb, bh);
5178c2ecf20Sopenharmony_ci			else
5188c2ecf20Sopenharmony_ci				status = ocfs2_validate_inode_block(
5198c2ecf20Sopenharmony_ci								osb->sb, bh);
5208c2ecf20Sopenharmony_ci		}
5218c2ecf20Sopenharmony_ci	}
5228c2ecf20Sopenharmony_ci	if (status < 0) {
5238c2ecf20Sopenharmony_ci		mlog_errno(status);
5248c2ecf20Sopenharmony_ci		goto bail;
5258c2ecf20Sopenharmony_ci	}
5268c2ecf20Sopenharmony_ci
5278c2ecf20Sopenharmony_ci	status = -EINVAL;
5288c2ecf20Sopenharmony_ci	fe = (struct ocfs2_dinode *) bh->b_data;
5298c2ecf20Sopenharmony_ci
5308c2ecf20Sopenharmony_ci	/*
5318c2ecf20Sopenharmony_ci	 * This is a code bug. Right now the caller needs to
5328c2ecf20Sopenharmony_ci	 * understand whether it is asking for a system file inode or
5338c2ecf20Sopenharmony_ci	 * not so the proper lock names can be built.
5348c2ecf20Sopenharmony_ci	 */
5358c2ecf20Sopenharmony_ci	mlog_bug_on_msg(!!(fe->i_flags & cpu_to_le32(OCFS2_SYSTEM_FL)) !=
5368c2ecf20Sopenharmony_ci			!!(args->fi_flags & OCFS2_FI_FLAG_SYSFILE),
5378c2ecf20Sopenharmony_ci			"Inode %llu: system file state is ambiguous\n",
5388c2ecf20Sopenharmony_ci			(unsigned long long)args->fi_blkno);
5398c2ecf20Sopenharmony_ci
5408c2ecf20Sopenharmony_ci	if (S_ISCHR(le16_to_cpu(fe->i_mode)) ||
5418c2ecf20Sopenharmony_ci	    S_ISBLK(le16_to_cpu(fe->i_mode)))
5428c2ecf20Sopenharmony_ci		inode->i_rdev = huge_decode_dev(le64_to_cpu(fe->id1.dev1.i_rdev));
5438c2ecf20Sopenharmony_ci
5448c2ecf20Sopenharmony_ci	ocfs2_populate_inode(inode, fe, 0);
5458c2ecf20Sopenharmony_ci
5468c2ecf20Sopenharmony_ci	BUG_ON(args->fi_blkno != le64_to_cpu(fe->i_blkno));
5478c2ecf20Sopenharmony_ci
5488c2ecf20Sopenharmony_ci	if (buffer_dirty(bh) && !buffer_jbd(bh)) {
5498c2ecf20Sopenharmony_ci		if (can_lock) {
5508c2ecf20Sopenharmony_ci			ocfs2_inode_unlock(inode, lock_level);
5518c2ecf20Sopenharmony_ci			lock_level = 1;
5528c2ecf20Sopenharmony_ci			ocfs2_inode_lock(inode, NULL, lock_level);
5538c2ecf20Sopenharmony_ci		}
5548c2ecf20Sopenharmony_ci		status = ocfs2_write_block(osb, bh, INODE_CACHE(inode));
5558c2ecf20Sopenharmony_ci		if (status < 0) {
5568c2ecf20Sopenharmony_ci			mlog_errno(status);
5578c2ecf20Sopenharmony_ci			goto bail;
5588c2ecf20Sopenharmony_ci		}
5598c2ecf20Sopenharmony_ci	}
5608c2ecf20Sopenharmony_ci
5618c2ecf20Sopenharmony_ci	status = 0;
5628c2ecf20Sopenharmony_ci
5638c2ecf20Sopenharmony_cibail:
5648c2ecf20Sopenharmony_ci	if (can_lock)
5658c2ecf20Sopenharmony_ci		ocfs2_inode_unlock(inode, lock_level);
5668c2ecf20Sopenharmony_ci
5678c2ecf20Sopenharmony_ci	if (status < 0)
5688c2ecf20Sopenharmony_ci		make_bad_inode(inode);
5698c2ecf20Sopenharmony_ci
5708c2ecf20Sopenharmony_ci	brelse(bh);
5718c2ecf20Sopenharmony_ci
5728c2ecf20Sopenharmony_ci	return status;
5738c2ecf20Sopenharmony_ci}
5748c2ecf20Sopenharmony_ci
5758c2ecf20Sopenharmony_civoid ocfs2_sync_blockdev(struct super_block *sb)
5768c2ecf20Sopenharmony_ci{
5778c2ecf20Sopenharmony_ci	sync_blockdev(sb->s_bdev);
5788c2ecf20Sopenharmony_ci}
5798c2ecf20Sopenharmony_ci
5808c2ecf20Sopenharmony_cistatic int ocfs2_truncate_for_delete(struct ocfs2_super *osb,
5818c2ecf20Sopenharmony_ci				     struct inode *inode,
5828c2ecf20Sopenharmony_ci				     struct buffer_head *fe_bh)
5838c2ecf20Sopenharmony_ci{
5848c2ecf20Sopenharmony_ci	int status = 0;
5858c2ecf20Sopenharmony_ci	struct ocfs2_dinode *fe;
5868c2ecf20Sopenharmony_ci	handle_t *handle = NULL;
5878c2ecf20Sopenharmony_ci
5888c2ecf20Sopenharmony_ci	fe = (struct ocfs2_dinode *) fe_bh->b_data;
5898c2ecf20Sopenharmony_ci
5908c2ecf20Sopenharmony_ci	/*
5918c2ecf20Sopenharmony_ci	 * This check will also skip truncate of inodes with inline
5928c2ecf20Sopenharmony_ci	 * data and fast symlinks.
5938c2ecf20Sopenharmony_ci	 */
5948c2ecf20Sopenharmony_ci	if (fe->i_clusters) {
5958c2ecf20Sopenharmony_ci		if (ocfs2_should_order_data(inode))
5968c2ecf20Sopenharmony_ci			ocfs2_begin_ordered_truncate(inode, 0);
5978c2ecf20Sopenharmony_ci
5988c2ecf20Sopenharmony_ci		handle = ocfs2_start_trans(osb, OCFS2_INODE_UPDATE_CREDITS);
5998c2ecf20Sopenharmony_ci		if (IS_ERR(handle)) {
6008c2ecf20Sopenharmony_ci			status = PTR_ERR(handle);
6018c2ecf20Sopenharmony_ci			handle = NULL;
6028c2ecf20Sopenharmony_ci			mlog_errno(status);
6038c2ecf20Sopenharmony_ci			goto out;
6048c2ecf20Sopenharmony_ci		}
6058c2ecf20Sopenharmony_ci
6068c2ecf20Sopenharmony_ci		status = ocfs2_journal_access_di(handle, INODE_CACHE(inode),
6078c2ecf20Sopenharmony_ci						 fe_bh,
6088c2ecf20Sopenharmony_ci						 OCFS2_JOURNAL_ACCESS_WRITE);
6098c2ecf20Sopenharmony_ci		if (status < 0) {
6108c2ecf20Sopenharmony_ci			mlog_errno(status);
6118c2ecf20Sopenharmony_ci			goto out;
6128c2ecf20Sopenharmony_ci		}
6138c2ecf20Sopenharmony_ci
6148c2ecf20Sopenharmony_ci		i_size_write(inode, 0);
6158c2ecf20Sopenharmony_ci
6168c2ecf20Sopenharmony_ci		status = ocfs2_mark_inode_dirty(handle, inode, fe_bh);
6178c2ecf20Sopenharmony_ci		if (status < 0) {
6188c2ecf20Sopenharmony_ci			mlog_errno(status);
6198c2ecf20Sopenharmony_ci			goto out;
6208c2ecf20Sopenharmony_ci		}
6218c2ecf20Sopenharmony_ci
6228c2ecf20Sopenharmony_ci		ocfs2_commit_trans(osb, handle);
6238c2ecf20Sopenharmony_ci		handle = NULL;
6248c2ecf20Sopenharmony_ci
6258c2ecf20Sopenharmony_ci		status = ocfs2_commit_truncate(osb, inode, fe_bh);
6268c2ecf20Sopenharmony_ci		if (status < 0)
6278c2ecf20Sopenharmony_ci			mlog_errno(status);
6288c2ecf20Sopenharmony_ci	}
6298c2ecf20Sopenharmony_ci
6308c2ecf20Sopenharmony_ciout:
6318c2ecf20Sopenharmony_ci	if (handle)
6328c2ecf20Sopenharmony_ci		ocfs2_commit_trans(osb, handle);
6338c2ecf20Sopenharmony_ci	return status;
6348c2ecf20Sopenharmony_ci}
6358c2ecf20Sopenharmony_ci
6368c2ecf20Sopenharmony_cistatic int ocfs2_remove_inode(struct inode *inode,
6378c2ecf20Sopenharmony_ci			      struct buffer_head *di_bh,
6388c2ecf20Sopenharmony_ci			      struct inode *orphan_dir_inode,
6398c2ecf20Sopenharmony_ci			      struct buffer_head *orphan_dir_bh)
6408c2ecf20Sopenharmony_ci{
6418c2ecf20Sopenharmony_ci	int status;
6428c2ecf20Sopenharmony_ci	struct inode *inode_alloc_inode = NULL;
6438c2ecf20Sopenharmony_ci	struct buffer_head *inode_alloc_bh = NULL;
6448c2ecf20Sopenharmony_ci	handle_t *handle;
6458c2ecf20Sopenharmony_ci	struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
6468c2ecf20Sopenharmony_ci	struct ocfs2_dinode *di = (struct ocfs2_dinode *) di_bh->b_data;
6478c2ecf20Sopenharmony_ci
6488c2ecf20Sopenharmony_ci	inode_alloc_inode =
6498c2ecf20Sopenharmony_ci		ocfs2_get_system_file_inode(osb, INODE_ALLOC_SYSTEM_INODE,
6508c2ecf20Sopenharmony_ci					    le16_to_cpu(di->i_suballoc_slot));
6518c2ecf20Sopenharmony_ci	if (!inode_alloc_inode) {
6528c2ecf20Sopenharmony_ci		status = -ENOENT;
6538c2ecf20Sopenharmony_ci		mlog_errno(status);
6548c2ecf20Sopenharmony_ci		goto bail;
6558c2ecf20Sopenharmony_ci	}
6568c2ecf20Sopenharmony_ci
6578c2ecf20Sopenharmony_ci	inode_lock(inode_alloc_inode);
6588c2ecf20Sopenharmony_ci	status = ocfs2_inode_lock(inode_alloc_inode, &inode_alloc_bh, 1);
6598c2ecf20Sopenharmony_ci	if (status < 0) {
6608c2ecf20Sopenharmony_ci		inode_unlock(inode_alloc_inode);
6618c2ecf20Sopenharmony_ci
6628c2ecf20Sopenharmony_ci		mlog_errno(status);
6638c2ecf20Sopenharmony_ci		goto bail;
6648c2ecf20Sopenharmony_ci	}
6658c2ecf20Sopenharmony_ci
6668c2ecf20Sopenharmony_ci	handle = ocfs2_start_trans(osb, OCFS2_DELETE_INODE_CREDITS +
6678c2ecf20Sopenharmony_ci				   ocfs2_quota_trans_credits(inode->i_sb));
6688c2ecf20Sopenharmony_ci	if (IS_ERR(handle)) {
6698c2ecf20Sopenharmony_ci		status = PTR_ERR(handle);
6708c2ecf20Sopenharmony_ci		mlog_errno(status);
6718c2ecf20Sopenharmony_ci		goto bail_unlock;
6728c2ecf20Sopenharmony_ci	}
6738c2ecf20Sopenharmony_ci
6748c2ecf20Sopenharmony_ci	if (!(OCFS2_I(inode)->ip_flags & OCFS2_INODE_SKIP_ORPHAN_DIR)) {
6758c2ecf20Sopenharmony_ci		status = ocfs2_orphan_del(osb, handle, orphan_dir_inode, inode,
6768c2ecf20Sopenharmony_ci					  orphan_dir_bh, false);
6778c2ecf20Sopenharmony_ci		if (status < 0) {
6788c2ecf20Sopenharmony_ci			mlog_errno(status);
6798c2ecf20Sopenharmony_ci			goto bail_commit;
6808c2ecf20Sopenharmony_ci		}
6818c2ecf20Sopenharmony_ci	}
6828c2ecf20Sopenharmony_ci
6838c2ecf20Sopenharmony_ci	/* set the inodes dtime */
6848c2ecf20Sopenharmony_ci	status = ocfs2_journal_access_di(handle, INODE_CACHE(inode), di_bh,
6858c2ecf20Sopenharmony_ci					 OCFS2_JOURNAL_ACCESS_WRITE);
6868c2ecf20Sopenharmony_ci	if (status < 0) {
6878c2ecf20Sopenharmony_ci		mlog_errno(status);
6888c2ecf20Sopenharmony_ci		goto bail_commit;
6898c2ecf20Sopenharmony_ci	}
6908c2ecf20Sopenharmony_ci
6918c2ecf20Sopenharmony_ci	di->i_dtime = cpu_to_le64(ktime_get_real_seconds());
6928c2ecf20Sopenharmony_ci	di->i_flags &= cpu_to_le32(~(OCFS2_VALID_FL | OCFS2_ORPHANED_FL));
6938c2ecf20Sopenharmony_ci	ocfs2_journal_dirty(handle, di_bh);
6948c2ecf20Sopenharmony_ci
6958c2ecf20Sopenharmony_ci	ocfs2_remove_from_cache(INODE_CACHE(inode), di_bh);
6968c2ecf20Sopenharmony_ci	dquot_free_inode(inode);
6978c2ecf20Sopenharmony_ci
6988c2ecf20Sopenharmony_ci	status = ocfs2_free_dinode(handle, inode_alloc_inode,
6998c2ecf20Sopenharmony_ci				   inode_alloc_bh, di);
7008c2ecf20Sopenharmony_ci	if (status < 0)
7018c2ecf20Sopenharmony_ci		mlog_errno(status);
7028c2ecf20Sopenharmony_ci
7038c2ecf20Sopenharmony_cibail_commit:
7048c2ecf20Sopenharmony_ci	ocfs2_commit_trans(osb, handle);
7058c2ecf20Sopenharmony_cibail_unlock:
7068c2ecf20Sopenharmony_ci	ocfs2_inode_unlock(inode_alloc_inode, 1);
7078c2ecf20Sopenharmony_ci	inode_unlock(inode_alloc_inode);
7088c2ecf20Sopenharmony_ci	brelse(inode_alloc_bh);
7098c2ecf20Sopenharmony_cibail:
7108c2ecf20Sopenharmony_ci	iput(inode_alloc_inode);
7118c2ecf20Sopenharmony_ci
7128c2ecf20Sopenharmony_ci	return status;
7138c2ecf20Sopenharmony_ci}
7148c2ecf20Sopenharmony_ci
7158c2ecf20Sopenharmony_ci/*
7168c2ecf20Sopenharmony_ci * Serialize with orphan dir recovery. If the process doing
7178c2ecf20Sopenharmony_ci * recovery on this orphan dir does an iget() with the dir
7188c2ecf20Sopenharmony_ci * i_mutex held, we'll deadlock here. Instead we detect this
7198c2ecf20Sopenharmony_ci * and exit early - recovery will wipe this inode for us.
7208c2ecf20Sopenharmony_ci */
7218c2ecf20Sopenharmony_cistatic int ocfs2_check_orphan_recovery_state(struct ocfs2_super *osb,
7228c2ecf20Sopenharmony_ci					     int slot)
7238c2ecf20Sopenharmony_ci{
7248c2ecf20Sopenharmony_ci	int ret = 0;
7258c2ecf20Sopenharmony_ci
7268c2ecf20Sopenharmony_ci	spin_lock(&osb->osb_lock);
7278c2ecf20Sopenharmony_ci	if (ocfs2_node_map_test_bit(osb, &osb->osb_recovering_orphan_dirs, slot)) {
7288c2ecf20Sopenharmony_ci		ret = -EDEADLK;
7298c2ecf20Sopenharmony_ci		goto out;
7308c2ecf20Sopenharmony_ci	}
7318c2ecf20Sopenharmony_ci	/* This signals to the orphan recovery process that it should
7328c2ecf20Sopenharmony_ci	 * wait for us to handle the wipe. */
7338c2ecf20Sopenharmony_ci	osb->osb_orphan_wipes[slot]++;
7348c2ecf20Sopenharmony_ciout:
7358c2ecf20Sopenharmony_ci	spin_unlock(&osb->osb_lock);
7368c2ecf20Sopenharmony_ci	trace_ocfs2_check_orphan_recovery_state(slot, ret);
7378c2ecf20Sopenharmony_ci	return ret;
7388c2ecf20Sopenharmony_ci}
7398c2ecf20Sopenharmony_ci
7408c2ecf20Sopenharmony_cistatic void ocfs2_signal_wipe_completion(struct ocfs2_super *osb,
7418c2ecf20Sopenharmony_ci					 int slot)
7428c2ecf20Sopenharmony_ci{
7438c2ecf20Sopenharmony_ci	spin_lock(&osb->osb_lock);
7448c2ecf20Sopenharmony_ci	osb->osb_orphan_wipes[slot]--;
7458c2ecf20Sopenharmony_ci	spin_unlock(&osb->osb_lock);
7468c2ecf20Sopenharmony_ci
7478c2ecf20Sopenharmony_ci	wake_up(&osb->osb_wipe_event);
7488c2ecf20Sopenharmony_ci}
7498c2ecf20Sopenharmony_ci
7508c2ecf20Sopenharmony_cistatic int ocfs2_wipe_inode(struct inode *inode,
7518c2ecf20Sopenharmony_ci			    struct buffer_head *di_bh)
7528c2ecf20Sopenharmony_ci{
7538c2ecf20Sopenharmony_ci	int status, orphaned_slot = -1;
7548c2ecf20Sopenharmony_ci	struct inode *orphan_dir_inode = NULL;
7558c2ecf20Sopenharmony_ci	struct buffer_head *orphan_dir_bh = NULL;
7568c2ecf20Sopenharmony_ci	struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
7578c2ecf20Sopenharmony_ci	struct ocfs2_dinode *di = (struct ocfs2_dinode *) di_bh->b_data;
7588c2ecf20Sopenharmony_ci
7598c2ecf20Sopenharmony_ci	if (!(OCFS2_I(inode)->ip_flags & OCFS2_INODE_SKIP_ORPHAN_DIR)) {
7608c2ecf20Sopenharmony_ci		orphaned_slot = le16_to_cpu(di->i_orphaned_slot);
7618c2ecf20Sopenharmony_ci
7628c2ecf20Sopenharmony_ci		status = ocfs2_check_orphan_recovery_state(osb, orphaned_slot);
7638c2ecf20Sopenharmony_ci		if (status)
7648c2ecf20Sopenharmony_ci			return status;
7658c2ecf20Sopenharmony_ci
7668c2ecf20Sopenharmony_ci		orphan_dir_inode = ocfs2_get_system_file_inode(osb,
7678c2ecf20Sopenharmony_ci							       ORPHAN_DIR_SYSTEM_INODE,
7688c2ecf20Sopenharmony_ci							       orphaned_slot);
7698c2ecf20Sopenharmony_ci		if (!orphan_dir_inode) {
7708c2ecf20Sopenharmony_ci			status = -ENOENT;
7718c2ecf20Sopenharmony_ci			mlog_errno(status);
7728c2ecf20Sopenharmony_ci			goto bail;
7738c2ecf20Sopenharmony_ci		}
7748c2ecf20Sopenharmony_ci
7758c2ecf20Sopenharmony_ci		/* Lock the orphan dir. The lock will be held for the entire
7768c2ecf20Sopenharmony_ci		 * delete_inode operation. We do this now to avoid races with
7778c2ecf20Sopenharmony_ci		 * recovery completion on other nodes. */
7788c2ecf20Sopenharmony_ci		inode_lock(orphan_dir_inode);
7798c2ecf20Sopenharmony_ci		status = ocfs2_inode_lock(orphan_dir_inode, &orphan_dir_bh, 1);
7808c2ecf20Sopenharmony_ci		if (status < 0) {
7818c2ecf20Sopenharmony_ci			inode_unlock(orphan_dir_inode);
7828c2ecf20Sopenharmony_ci
7838c2ecf20Sopenharmony_ci			mlog_errno(status);
7848c2ecf20Sopenharmony_ci			goto bail;
7858c2ecf20Sopenharmony_ci		}
7868c2ecf20Sopenharmony_ci	}
7878c2ecf20Sopenharmony_ci
7888c2ecf20Sopenharmony_ci	/* we do this while holding the orphan dir lock because we
7898c2ecf20Sopenharmony_ci	 * don't want recovery being run from another node to try an
7908c2ecf20Sopenharmony_ci	 * inode delete underneath us -- this will result in two nodes
7918c2ecf20Sopenharmony_ci	 * truncating the same file! */
7928c2ecf20Sopenharmony_ci	status = ocfs2_truncate_for_delete(osb, inode, di_bh);
7938c2ecf20Sopenharmony_ci	if (status < 0) {
7948c2ecf20Sopenharmony_ci		mlog_errno(status);
7958c2ecf20Sopenharmony_ci		goto bail_unlock_dir;
7968c2ecf20Sopenharmony_ci	}
7978c2ecf20Sopenharmony_ci
7988c2ecf20Sopenharmony_ci	/* Remove any dir index tree */
7998c2ecf20Sopenharmony_ci	if (S_ISDIR(inode->i_mode)) {
8008c2ecf20Sopenharmony_ci		status = ocfs2_dx_dir_truncate(inode, di_bh);
8018c2ecf20Sopenharmony_ci		if (status) {
8028c2ecf20Sopenharmony_ci			mlog_errno(status);
8038c2ecf20Sopenharmony_ci			goto bail_unlock_dir;
8048c2ecf20Sopenharmony_ci		}
8058c2ecf20Sopenharmony_ci	}
8068c2ecf20Sopenharmony_ci
8078c2ecf20Sopenharmony_ci	/*Free extended attribute resources associated with this inode.*/
8088c2ecf20Sopenharmony_ci	status = ocfs2_xattr_remove(inode, di_bh);
8098c2ecf20Sopenharmony_ci	if (status < 0) {
8108c2ecf20Sopenharmony_ci		mlog_errno(status);
8118c2ecf20Sopenharmony_ci		goto bail_unlock_dir;
8128c2ecf20Sopenharmony_ci	}
8138c2ecf20Sopenharmony_ci
8148c2ecf20Sopenharmony_ci	status = ocfs2_remove_refcount_tree(inode, di_bh);
8158c2ecf20Sopenharmony_ci	if (status < 0) {
8168c2ecf20Sopenharmony_ci		mlog_errno(status);
8178c2ecf20Sopenharmony_ci		goto bail_unlock_dir;
8188c2ecf20Sopenharmony_ci	}
8198c2ecf20Sopenharmony_ci
8208c2ecf20Sopenharmony_ci	status = ocfs2_remove_inode(inode, di_bh, orphan_dir_inode,
8218c2ecf20Sopenharmony_ci				    orphan_dir_bh);
8228c2ecf20Sopenharmony_ci	if (status < 0)
8238c2ecf20Sopenharmony_ci		mlog_errno(status);
8248c2ecf20Sopenharmony_ci
8258c2ecf20Sopenharmony_cibail_unlock_dir:
8268c2ecf20Sopenharmony_ci	if (OCFS2_I(inode)->ip_flags & OCFS2_INODE_SKIP_ORPHAN_DIR)
8278c2ecf20Sopenharmony_ci		return status;
8288c2ecf20Sopenharmony_ci
8298c2ecf20Sopenharmony_ci	ocfs2_inode_unlock(orphan_dir_inode, 1);
8308c2ecf20Sopenharmony_ci	inode_unlock(orphan_dir_inode);
8318c2ecf20Sopenharmony_ci	brelse(orphan_dir_bh);
8328c2ecf20Sopenharmony_cibail:
8338c2ecf20Sopenharmony_ci	iput(orphan_dir_inode);
8348c2ecf20Sopenharmony_ci	ocfs2_signal_wipe_completion(osb, orphaned_slot);
8358c2ecf20Sopenharmony_ci
8368c2ecf20Sopenharmony_ci	return status;
8378c2ecf20Sopenharmony_ci}
8388c2ecf20Sopenharmony_ci
8398c2ecf20Sopenharmony_ci/* There is a series of simple checks that should be done before a
8408c2ecf20Sopenharmony_ci * trylock is even considered. Encapsulate those in this function. */
8418c2ecf20Sopenharmony_cistatic int ocfs2_inode_is_valid_to_delete(struct inode *inode)
8428c2ecf20Sopenharmony_ci{
8438c2ecf20Sopenharmony_ci	int ret = 0;
8448c2ecf20Sopenharmony_ci	struct ocfs2_inode_info *oi = OCFS2_I(inode);
8458c2ecf20Sopenharmony_ci	struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
8468c2ecf20Sopenharmony_ci
8478c2ecf20Sopenharmony_ci	trace_ocfs2_inode_is_valid_to_delete(current, osb->dc_task,
8488c2ecf20Sopenharmony_ci					     (unsigned long long)oi->ip_blkno,
8498c2ecf20Sopenharmony_ci					     oi->ip_flags);
8508c2ecf20Sopenharmony_ci
8518c2ecf20Sopenharmony_ci	/* We shouldn't be getting here for the root directory
8528c2ecf20Sopenharmony_ci	 * inode.. */
8538c2ecf20Sopenharmony_ci	if (inode == osb->root_inode) {
8548c2ecf20Sopenharmony_ci		mlog(ML_ERROR, "Skipping delete of root inode.\n");
8558c2ecf20Sopenharmony_ci		goto bail;
8568c2ecf20Sopenharmony_ci	}
8578c2ecf20Sopenharmony_ci
8588c2ecf20Sopenharmony_ci	/*
8598c2ecf20Sopenharmony_ci	 * If we're coming from downconvert_thread we can't go into our own
8608c2ecf20Sopenharmony_ci	 * voting [hello, deadlock city!] so we cannot delete the inode. But
8618c2ecf20Sopenharmony_ci	 * since we dropped last inode ref when downconverting dentry lock,
8628c2ecf20Sopenharmony_ci	 * we cannot have the file open and thus the node doing unlink will
8638c2ecf20Sopenharmony_ci	 * take care of deleting the inode.
8648c2ecf20Sopenharmony_ci	 */
8658c2ecf20Sopenharmony_ci	if (current == osb->dc_task)
8668c2ecf20Sopenharmony_ci		goto bail;
8678c2ecf20Sopenharmony_ci
8688c2ecf20Sopenharmony_ci	spin_lock(&oi->ip_lock);
8698c2ecf20Sopenharmony_ci	/* OCFS2 *never* deletes system files. This should technically
8708c2ecf20Sopenharmony_ci	 * never get here as system file inodes should always have a
8718c2ecf20Sopenharmony_ci	 * positive link count. */
8728c2ecf20Sopenharmony_ci	if (oi->ip_flags & OCFS2_INODE_SYSTEM_FILE) {
8738c2ecf20Sopenharmony_ci		mlog(ML_ERROR, "Skipping delete of system file %llu\n",
8748c2ecf20Sopenharmony_ci		     (unsigned long long)oi->ip_blkno);
8758c2ecf20Sopenharmony_ci		goto bail_unlock;
8768c2ecf20Sopenharmony_ci	}
8778c2ecf20Sopenharmony_ci
8788c2ecf20Sopenharmony_ci	ret = 1;
8798c2ecf20Sopenharmony_cibail_unlock:
8808c2ecf20Sopenharmony_ci	spin_unlock(&oi->ip_lock);
8818c2ecf20Sopenharmony_cibail:
8828c2ecf20Sopenharmony_ci	return ret;
8838c2ecf20Sopenharmony_ci}
8848c2ecf20Sopenharmony_ci
8858c2ecf20Sopenharmony_ci/* Query the cluster to determine whether we should wipe an inode from
8868c2ecf20Sopenharmony_ci * disk or not.
8878c2ecf20Sopenharmony_ci *
8888c2ecf20Sopenharmony_ci * Requires the inode to have the cluster lock. */
8898c2ecf20Sopenharmony_cistatic int ocfs2_query_inode_wipe(struct inode *inode,
8908c2ecf20Sopenharmony_ci				  struct buffer_head *di_bh,
8918c2ecf20Sopenharmony_ci				  int *wipe)
8928c2ecf20Sopenharmony_ci{
8938c2ecf20Sopenharmony_ci	int status = 0, reason = 0;
8948c2ecf20Sopenharmony_ci	struct ocfs2_inode_info *oi = OCFS2_I(inode);
8958c2ecf20Sopenharmony_ci	struct ocfs2_dinode *di;
8968c2ecf20Sopenharmony_ci
8978c2ecf20Sopenharmony_ci	*wipe = 0;
8988c2ecf20Sopenharmony_ci
8998c2ecf20Sopenharmony_ci	trace_ocfs2_query_inode_wipe_begin((unsigned long long)oi->ip_blkno,
9008c2ecf20Sopenharmony_ci					   inode->i_nlink);
9018c2ecf20Sopenharmony_ci
9028c2ecf20Sopenharmony_ci	/* While we were waiting for the cluster lock in
9038c2ecf20Sopenharmony_ci	 * ocfs2_delete_inode, another node might have asked to delete
9048c2ecf20Sopenharmony_ci	 * the inode. Recheck our flags to catch this. */
9058c2ecf20Sopenharmony_ci	if (!ocfs2_inode_is_valid_to_delete(inode)) {
9068c2ecf20Sopenharmony_ci		reason = 1;
9078c2ecf20Sopenharmony_ci		goto bail;
9088c2ecf20Sopenharmony_ci	}
9098c2ecf20Sopenharmony_ci
9108c2ecf20Sopenharmony_ci	/* Now that we have an up to date inode, we can double check
9118c2ecf20Sopenharmony_ci	 * the link count. */
9128c2ecf20Sopenharmony_ci	if (inode->i_nlink)
9138c2ecf20Sopenharmony_ci		goto bail;
9148c2ecf20Sopenharmony_ci
9158c2ecf20Sopenharmony_ci	/* Do some basic inode verification... */
9168c2ecf20Sopenharmony_ci	di = (struct ocfs2_dinode *) di_bh->b_data;
9178c2ecf20Sopenharmony_ci	if (!(di->i_flags & cpu_to_le32(OCFS2_ORPHANED_FL)) &&
9188c2ecf20Sopenharmony_ci	    !(oi->ip_flags & OCFS2_INODE_SKIP_ORPHAN_DIR)) {
9198c2ecf20Sopenharmony_ci		/*
9208c2ecf20Sopenharmony_ci		 * Inodes in the orphan dir must have ORPHANED_FL.  The only
9218c2ecf20Sopenharmony_ci		 * inodes that come back out of the orphan dir are reflink
9228c2ecf20Sopenharmony_ci		 * targets. A reflink target may be moved out of the orphan
9238c2ecf20Sopenharmony_ci		 * dir between the time we scan the directory and the time we
9248c2ecf20Sopenharmony_ci		 * process it. This would lead to HAS_REFCOUNT_FL being set but
9258c2ecf20Sopenharmony_ci		 * ORPHANED_FL not.
9268c2ecf20Sopenharmony_ci		 */
9278c2ecf20Sopenharmony_ci		if (di->i_dyn_features & cpu_to_le16(OCFS2_HAS_REFCOUNT_FL)) {
9288c2ecf20Sopenharmony_ci			reason = 2;
9298c2ecf20Sopenharmony_ci			goto bail;
9308c2ecf20Sopenharmony_ci		}
9318c2ecf20Sopenharmony_ci
9328c2ecf20Sopenharmony_ci		/* for lack of a better error? */
9338c2ecf20Sopenharmony_ci		status = -EEXIST;
9348c2ecf20Sopenharmony_ci		mlog(ML_ERROR,
9358c2ecf20Sopenharmony_ci		     "Inode %llu (on-disk %llu) not orphaned! "
9368c2ecf20Sopenharmony_ci		     "Disk flags  0x%x, inode flags 0x%x\n",
9378c2ecf20Sopenharmony_ci		     (unsigned long long)oi->ip_blkno,
9388c2ecf20Sopenharmony_ci		     (unsigned long long)le64_to_cpu(di->i_blkno),
9398c2ecf20Sopenharmony_ci		     le32_to_cpu(di->i_flags), oi->ip_flags);
9408c2ecf20Sopenharmony_ci		goto bail;
9418c2ecf20Sopenharmony_ci	}
9428c2ecf20Sopenharmony_ci
9438c2ecf20Sopenharmony_ci	/* has someone already deleted us?! baaad... */
9448c2ecf20Sopenharmony_ci	if (di->i_dtime) {
9458c2ecf20Sopenharmony_ci		status = -EEXIST;
9468c2ecf20Sopenharmony_ci		mlog_errno(status);
9478c2ecf20Sopenharmony_ci		goto bail;
9488c2ecf20Sopenharmony_ci	}
9498c2ecf20Sopenharmony_ci
9508c2ecf20Sopenharmony_ci	/*
9518c2ecf20Sopenharmony_ci	 * This is how ocfs2 determines whether an inode is still live
9528c2ecf20Sopenharmony_ci	 * within the cluster. Every node takes a shared read lock on
9538c2ecf20Sopenharmony_ci	 * the inode open lock in ocfs2_read_locked_inode(). When we
9548c2ecf20Sopenharmony_ci	 * get to ->delete_inode(), each node tries to convert it's
9558c2ecf20Sopenharmony_ci	 * lock to an exclusive. Trylocks are serialized by the inode
9568c2ecf20Sopenharmony_ci	 * meta data lock. If the upconvert succeeds, we know the inode
9578c2ecf20Sopenharmony_ci	 * is no longer live and can be deleted.
9588c2ecf20Sopenharmony_ci	 *
9598c2ecf20Sopenharmony_ci	 * Though we call this with the meta data lock held, the
9608c2ecf20Sopenharmony_ci	 * trylock keeps us from ABBA deadlock.
9618c2ecf20Sopenharmony_ci	 */
9628c2ecf20Sopenharmony_ci	status = ocfs2_try_open_lock(inode, 1);
9638c2ecf20Sopenharmony_ci	if (status == -EAGAIN) {
9648c2ecf20Sopenharmony_ci		status = 0;
9658c2ecf20Sopenharmony_ci		reason = 3;
9668c2ecf20Sopenharmony_ci		goto bail;
9678c2ecf20Sopenharmony_ci	}
9688c2ecf20Sopenharmony_ci	if (status < 0) {
9698c2ecf20Sopenharmony_ci		mlog_errno(status);
9708c2ecf20Sopenharmony_ci		goto bail;
9718c2ecf20Sopenharmony_ci	}
9728c2ecf20Sopenharmony_ci
9738c2ecf20Sopenharmony_ci	*wipe = 1;
9748c2ecf20Sopenharmony_ci	trace_ocfs2_query_inode_wipe_succ(le16_to_cpu(di->i_orphaned_slot));
9758c2ecf20Sopenharmony_ci
9768c2ecf20Sopenharmony_cibail:
9778c2ecf20Sopenharmony_ci	trace_ocfs2_query_inode_wipe_end(status, reason);
9788c2ecf20Sopenharmony_ci	return status;
9798c2ecf20Sopenharmony_ci}
9808c2ecf20Sopenharmony_ci
9818c2ecf20Sopenharmony_ci/* Support function for ocfs2_delete_inode. Will help us keep the
9828c2ecf20Sopenharmony_ci * inode data in a consistent state for clear_inode. Always truncates
9838c2ecf20Sopenharmony_ci * pages, optionally sync's them first. */
9848c2ecf20Sopenharmony_cistatic void ocfs2_cleanup_delete_inode(struct inode *inode,
9858c2ecf20Sopenharmony_ci				       int sync_data)
9868c2ecf20Sopenharmony_ci{
9878c2ecf20Sopenharmony_ci	trace_ocfs2_cleanup_delete_inode(
9888c2ecf20Sopenharmony_ci		(unsigned long long)OCFS2_I(inode)->ip_blkno, sync_data);
9898c2ecf20Sopenharmony_ci	if (sync_data)
9908c2ecf20Sopenharmony_ci		filemap_write_and_wait(inode->i_mapping);
9918c2ecf20Sopenharmony_ci	truncate_inode_pages_final(&inode->i_data);
9928c2ecf20Sopenharmony_ci}
9938c2ecf20Sopenharmony_ci
9948c2ecf20Sopenharmony_cistatic void ocfs2_delete_inode(struct inode *inode)
9958c2ecf20Sopenharmony_ci{
9968c2ecf20Sopenharmony_ci	int wipe, status;
9978c2ecf20Sopenharmony_ci	sigset_t oldset;
9988c2ecf20Sopenharmony_ci	struct buffer_head *di_bh = NULL;
9998c2ecf20Sopenharmony_ci	struct ocfs2_dinode *di = NULL;
10008c2ecf20Sopenharmony_ci
10018c2ecf20Sopenharmony_ci	trace_ocfs2_delete_inode(inode->i_ino,
10028c2ecf20Sopenharmony_ci				 (unsigned long long)OCFS2_I(inode)->ip_blkno,
10038c2ecf20Sopenharmony_ci				 is_bad_inode(inode));
10048c2ecf20Sopenharmony_ci
10058c2ecf20Sopenharmony_ci	/* When we fail in read_inode() we mark inode as bad. The second test
10068c2ecf20Sopenharmony_ci	 * catches the case when inode allocation fails before allocating
10078c2ecf20Sopenharmony_ci	 * a block for inode. */
10088c2ecf20Sopenharmony_ci	if (is_bad_inode(inode) || !OCFS2_I(inode)->ip_blkno)
10098c2ecf20Sopenharmony_ci		goto bail;
10108c2ecf20Sopenharmony_ci
10118c2ecf20Sopenharmony_ci	if (!ocfs2_inode_is_valid_to_delete(inode)) {
10128c2ecf20Sopenharmony_ci		/* It's probably not necessary to truncate_inode_pages
10138c2ecf20Sopenharmony_ci		 * here but we do it for safety anyway (it will most
10148c2ecf20Sopenharmony_ci		 * likely be a no-op anyway) */
10158c2ecf20Sopenharmony_ci		ocfs2_cleanup_delete_inode(inode, 0);
10168c2ecf20Sopenharmony_ci		goto bail;
10178c2ecf20Sopenharmony_ci	}
10188c2ecf20Sopenharmony_ci
10198c2ecf20Sopenharmony_ci	dquot_initialize(inode);
10208c2ecf20Sopenharmony_ci
10218c2ecf20Sopenharmony_ci	/* We want to block signals in delete_inode as the lock and
10228c2ecf20Sopenharmony_ci	 * messaging paths may return us -ERESTARTSYS. Which would
10238c2ecf20Sopenharmony_ci	 * cause us to exit early, resulting in inodes being orphaned
10248c2ecf20Sopenharmony_ci	 * forever. */
10258c2ecf20Sopenharmony_ci	ocfs2_block_signals(&oldset);
10268c2ecf20Sopenharmony_ci
10278c2ecf20Sopenharmony_ci	/*
10288c2ecf20Sopenharmony_ci	 * Synchronize us against ocfs2_get_dentry. We take this in
10298c2ecf20Sopenharmony_ci	 * shared mode so that all nodes can still concurrently
10308c2ecf20Sopenharmony_ci	 * process deletes.
10318c2ecf20Sopenharmony_ci	 */
10328c2ecf20Sopenharmony_ci	status = ocfs2_nfs_sync_lock(OCFS2_SB(inode->i_sb), 0);
10338c2ecf20Sopenharmony_ci	if (status < 0) {
10348c2ecf20Sopenharmony_ci		mlog(ML_ERROR, "getting nfs sync lock(PR) failed %d\n", status);
10358c2ecf20Sopenharmony_ci		ocfs2_cleanup_delete_inode(inode, 0);
10368c2ecf20Sopenharmony_ci		goto bail_unblock;
10378c2ecf20Sopenharmony_ci	}
10388c2ecf20Sopenharmony_ci	/* Lock down the inode. This gives us an up to date view of
10398c2ecf20Sopenharmony_ci	 * it's metadata (for verification), and allows us to
10408c2ecf20Sopenharmony_ci	 * serialize delete_inode on multiple nodes.
10418c2ecf20Sopenharmony_ci	 *
10428c2ecf20Sopenharmony_ci	 * Even though we might be doing a truncate, we don't take the
10438c2ecf20Sopenharmony_ci	 * allocation lock here as it won't be needed - nobody will
10448c2ecf20Sopenharmony_ci	 * have the file open.
10458c2ecf20Sopenharmony_ci	 */
10468c2ecf20Sopenharmony_ci	status = ocfs2_inode_lock(inode, &di_bh, 1);
10478c2ecf20Sopenharmony_ci	if (status < 0) {
10488c2ecf20Sopenharmony_ci		if (status != -ENOENT)
10498c2ecf20Sopenharmony_ci			mlog_errno(status);
10508c2ecf20Sopenharmony_ci		ocfs2_cleanup_delete_inode(inode, 0);
10518c2ecf20Sopenharmony_ci		goto bail_unlock_nfs_sync;
10528c2ecf20Sopenharmony_ci	}
10538c2ecf20Sopenharmony_ci
10548c2ecf20Sopenharmony_ci	di = (struct ocfs2_dinode *)di_bh->b_data;
10558c2ecf20Sopenharmony_ci	/* Skip inode deletion and wait for dio orphan entry recovered
10568c2ecf20Sopenharmony_ci	 * first */
10578c2ecf20Sopenharmony_ci	if (unlikely(di->i_flags & cpu_to_le32(OCFS2_DIO_ORPHANED_FL))) {
10588c2ecf20Sopenharmony_ci		ocfs2_cleanup_delete_inode(inode, 0);
10598c2ecf20Sopenharmony_ci		goto bail_unlock_inode;
10608c2ecf20Sopenharmony_ci	}
10618c2ecf20Sopenharmony_ci
10628c2ecf20Sopenharmony_ci	/* Query the cluster. This will be the final decision made
10638c2ecf20Sopenharmony_ci	 * before we go ahead and wipe the inode. */
10648c2ecf20Sopenharmony_ci	status = ocfs2_query_inode_wipe(inode, di_bh, &wipe);
10658c2ecf20Sopenharmony_ci	if (!wipe || status < 0) {
10668c2ecf20Sopenharmony_ci		/* Error and remote inode busy both mean we won't be
10678c2ecf20Sopenharmony_ci		 * removing the inode, so they take almost the same
10688c2ecf20Sopenharmony_ci		 * path. */
10698c2ecf20Sopenharmony_ci		if (status < 0)
10708c2ecf20Sopenharmony_ci			mlog_errno(status);
10718c2ecf20Sopenharmony_ci
10728c2ecf20Sopenharmony_ci		/* Someone in the cluster has disallowed a wipe of
10738c2ecf20Sopenharmony_ci		 * this inode, or it was never completely
10748c2ecf20Sopenharmony_ci		 * orphaned. Write out the pages and exit now. */
10758c2ecf20Sopenharmony_ci		ocfs2_cleanup_delete_inode(inode, 1);
10768c2ecf20Sopenharmony_ci		goto bail_unlock_inode;
10778c2ecf20Sopenharmony_ci	}
10788c2ecf20Sopenharmony_ci
10798c2ecf20Sopenharmony_ci	ocfs2_cleanup_delete_inode(inode, 0);
10808c2ecf20Sopenharmony_ci
10818c2ecf20Sopenharmony_ci	status = ocfs2_wipe_inode(inode, di_bh);
10828c2ecf20Sopenharmony_ci	if (status < 0) {
10838c2ecf20Sopenharmony_ci		if (status != -EDEADLK)
10848c2ecf20Sopenharmony_ci			mlog_errno(status);
10858c2ecf20Sopenharmony_ci		goto bail_unlock_inode;
10868c2ecf20Sopenharmony_ci	}
10878c2ecf20Sopenharmony_ci
10888c2ecf20Sopenharmony_ci	/*
10898c2ecf20Sopenharmony_ci	 * Mark the inode as successfully deleted.
10908c2ecf20Sopenharmony_ci	 *
10918c2ecf20Sopenharmony_ci	 * This is important for ocfs2_clear_inode() as it will check
10928c2ecf20Sopenharmony_ci	 * this flag and skip any checkpointing work
10938c2ecf20Sopenharmony_ci	 *
10948c2ecf20Sopenharmony_ci	 * ocfs2_stuff_meta_lvb() also uses this flag to invalidate
10958c2ecf20Sopenharmony_ci	 * the LVB for other nodes.
10968c2ecf20Sopenharmony_ci	 */
10978c2ecf20Sopenharmony_ci	OCFS2_I(inode)->ip_flags |= OCFS2_INODE_DELETED;
10988c2ecf20Sopenharmony_ci
10998c2ecf20Sopenharmony_cibail_unlock_inode:
11008c2ecf20Sopenharmony_ci	ocfs2_inode_unlock(inode, 1);
11018c2ecf20Sopenharmony_ci	brelse(di_bh);
11028c2ecf20Sopenharmony_ci
11038c2ecf20Sopenharmony_cibail_unlock_nfs_sync:
11048c2ecf20Sopenharmony_ci	ocfs2_nfs_sync_unlock(OCFS2_SB(inode->i_sb), 0);
11058c2ecf20Sopenharmony_ci
11068c2ecf20Sopenharmony_cibail_unblock:
11078c2ecf20Sopenharmony_ci	ocfs2_unblock_signals(&oldset);
11088c2ecf20Sopenharmony_cibail:
11098c2ecf20Sopenharmony_ci	return;
11108c2ecf20Sopenharmony_ci}
11118c2ecf20Sopenharmony_ci
11128c2ecf20Sopenharmony_cistatic void ocfs2_clear_inode(struct inode *inode)
11138c2ecf20Sopenharmony_ci{
11148c2ecf20Sopenharmony_ci	int status;
11158c2ecf20Sopenharmony_ci	struct ocfs2_inode_info *oi = OCFS2_I(inode);
11168c2ecf20Sopenharmony_ci	struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
11178c2ecf20Sopenharmony_ci
11188c2ecf20Sopenharmony_ci	clear_inode(inode);
11198c2ecf20Sopenharmony_ci	trace_ocfs2_clear_inode((unsigned long long)oi->ip_blkno,
11208c2ecf20Sopenharmony_ci				inode->i_nlink);
11218c2ecf20Sopenharmony_ci
11228c2ecf20Sopenharmony_ci	mlog_bug_on_msg(osb == NULL,
11238c2ecf20Sopenharmony_ci			"Inode=%lu\n", inode->i_ino);
11248c2ecf20Sopenharmony_ci
11258c2ecf20Sopenharmony_ci	dquot_drop(inode);
11268c2ecf20Sopenharmony_ci
11278c2ecf20Sopenharmony_ci	/* To preven remote deletes we hold open lock before, now it
11288c2ecf20Sopenharmony_ci	 * is time to unlock PR and EX open locks. */
11298c2ecf20Sopenharmony_ci	ocfs2_open_unlock(inode);
11308c2ecf20Sopenharmony_ci
11318c2ecf20Sopenharmony_ci	/* Do these before all the other work so that we don't bounce
11328c2ecf20Sopenharmony_ci	 * the downconvert thread while waiting to destroy the locks. */
11338c2ecf20Sopenharmony_ci	ocfs2_mark_lockres_freeing(osb, &oi->ip_rw_lockres);
11348c2ecf20Sopenharmony_ci	ocfs2_mark_lockres_freeing(osb, &oi->ip_inode_lockres);
11358c2ecf20Sopenharmony_ci	ocfs2_mark_lockres_freeing(osb, &oi->ip_open_lockres);
11368c2ecf20Sopenharmony_ci
11378c2ecf20Sopenharmony_ci	ocfs2_resv_discard(&osb->osb_la_resmap,
11388c2ecf20Sopenharmony_ci			   &oi->ip_la_data_resv);
11398c2ecf20Sopenharmony_ci	ocfs2_resv_init_once(&oi->ip_la_data_resv);
11408c2ecf20Sopenharmony_ci
11418c2ecf20Sopenharmony_ci	/* We very well may get a clear_inode before all an inodes
11428c2ecf20Sopenharmony_ci	 * metadata has hit disk. Of course, we can't drop any cluster
11438c2ecf20Sopenharmony_ci	 * locks until the journal has finished with it. The only
11448c2ecf20Sopenharmony_ci	 * exception here are successfully wiped inodes - their
11458c2ecf20Sopenharmony_ci	 * metadata can now be considered to be part of the system
11468c2ecf20Sopenharmony_ci	 * inodes from which it came. */
11478c2ecf20Sopenharmony_ci	if (!(oi->ip_flags & OCFS2_INODE_DELETED))
11488c2ecf20Sopenharmony_ci		ocfs2_checkpoint_inode(inode);
11498c2ecf20Sopenharmony_ci
11508c2ecf20Sopenharmony_ci	mlog_bug_on_msg(!list_empty(&oi->ip_io_markers),
11518c2ecf20Sopenharmony_ci			"Clear inode of %llu, inode has io markers\n",
11528c2ecf20Sopenharmony_ci			(unsigned long long)oi->ip_blkno);
11538c2ecf20Sopenharmony_ci	mlog_bug_on_msg(!list_empty(&oi->ip_unwritten_list),
11548c2ecf20Sopenharmony_ci			"Clear inode of %llu, inode has unwritten extents\n",
11558c2ecf20Sopenharmony_ci			(unsigned long long)oi->ip_blkno);
11568c2ecf20Sopenharmony_ci
11578c2ecf20Sopenharmony_ci	ocfs2_extent_map_trunc(inode, 0);
11588c2ecf20Sopenharmony_ci
11598c2ecf20Sopenharmony_ci	status = ocfs2_drop_inode_locks(inode);
11608c2ecf20Sopenharmony_ci	if (status < 0)
11618c2ecf20Sopenharmony_ci		mlog_errno(status);
11628c2ecf20Sopenharmony_ci
11638c2ecf20Sopenharmony_ci	ocfs2_lock_res_free(&oi->ip_rw_lockres);
11648c2ecf20Sopenharmony_ci	ocfs2_lock_res_free(&oi->ip_inode_lockres);
11658c2ecf20Sopenharmony_ci	ocfs2_lock_res_free(&oi->ip_open_lockres);
11668c2ecf20Sopenharmony_ci
11678c2ecf20Sopenharmony_ci	ocfs2_metadata_cache_exit(INODE_CACHE(inode));
11688c2ecf20Sopenharmony_ci
11698c2ecf20Sopenharmony_ci	mlog_bug_on_msg(INODE_CACHE(inode)->ci_num_cached,
11708c2ecf20Sopenharmony_ci			"Clear inode of %llu, inode has %u cache items\n",
11718c2ecf20Sopenharmony_ci			(unsigned long long)oi->ip_blkno,
11728c2ecf20Sopenharmony_ci			INODE_CACHE(inode)->ci_num_cached);
11738c2ecf20Sopenharmony_ci
11748c2ecf20Sopenharmony_ci	mlog_bug_on_msg(!(INODE_CACHE(inode)->ci_flags & OCFS2_CACHE_FL_INLINE),
11758c2ecf20Sopenharmony_ci			"Clear inode of %llu, inode has a bad flag\n",
11768c2ecf20Sopenharmony_ci			(unsigned long long)oi->ip_blkno);
11778c2ecf20Sopenharmony_ci
11788c2ecf20Sopenharmony_ci	mlog_bug_on_msg(spin_is_locked(&oi->ip_lock),
11798c2ecf20Sopenharmony_ci			"Clear inode of %llu, inode is locked\n",
11808c2ecf20Sopenharmony_ci			(unsigned long long)oi->ip_blkno);
11818c2ecf20Sopenharmony_ci
11828c2ecf20Sopenharmony_ci	mlog_bug_on_msg(!mutex_trylock(&oi->ip_io_mutex),
11838c2ecf20Sopenharmony_ci			"Clear inode of %llu, io_mutex is locked\n",
11848c2ecf20Sopenharmony_ci			(unsigned long long)oi->ip_blkno);
11858c2ecf20Sopenharmony_ci	mutex_unlock(&oi->ip_io_mutex);
11868c2ecf20Sopenharmony_ci
11878c2ecf20Sopenharmony_ci	/*
11888c2ecf20Sopenharmony_ci	 * down_trylock() returns 0, down_write_trylock() returns 1
11898c2ecf20Sopenharmony_ci	 * kernel 1, world 0
11908c2ecf20Sopenharmony_ci	 */
11918c2ecf20Sopenharmony_ci	mlog_bug_on_msg(!down_write_trylock(&oi->ip_alloc_sem),
11928c2ecf20Sopenharmony_ci			"Clear inode of %llu, alloc_sem is locked\n",
11938c2ecf20Sopenharmony_ci			(unsigned long long)oi->ip_blkno);
11948c2ecf20Sopenharmony_ci	up_write(&oi->ip_alloc_sem);
11958c2ecf20Sopenharmony_ci
11968c2ecf20Sopenharmony_ci	mlog_bug_on_msg(oi->ip_open_count,
11978c2ecf20Sopenharmony_ci			"Clear inode of %llu has open count %d\n",
11988c2ecf20Sopenharmony_ci			(unsigned long long)oi->ip_blkno, oi->ip_open_count);
11998c2ecf20Sopenharmony_ci
12008c2ecf20Sopenharmony_ci	/* Clear all other flags. */
12018c2ecf20Sopenharmony_ci	oi->ip_flags = 0;
12028c2ecf20Sopenharmony_ci	oi->ip_dir_start_lookup = 0;
12038c2ecf20Sopenharmony_ci	oi->ip_blkno = 0ULL;
12048c2ecf20Sopenharmony_ci
12058c2ecf20Sopenharmony_ci	/*
12068c2ecf20Sopenharmony_ci	 * ip_jinode is used to track txns against this inode. We ensure that
12078c2ecf20Sopenharmony_ci	 * the journal is flushed before journal shutdown. Thus it is safe to
12088c2ecf20Sopenharmony_ci	 * have inodes get cleaned up after journal shutdown.
12098c2ecf20Sopenharmony_ci	 */
12108c2ecf20Sopenharmony_ci	jbd2_journal_release_jbd_inode(osb->journal->j_journal,
12118c2ecf20Sopenharmony_ci				       &oi->ip_jinode);
12128c2ecf20Sopenharmony_ci}
12138c2ecf20Sopenharmony_ci
12148c2ecf20Sopenharmony_civoid ocfs2_evict_inode(struct inode *inode)
12158c2ecf20Sopenharmony_ci{
12168c2ecf20Sopenharmony_ci	if (!inode->i_nlink ||
12178c2ecf20Sopenharmony_ci	    (OCFS2_I(inode)->ip_flags & OCFS2_INODE_MAYBE_ORPHANED)) {
12188c2ecf20Sopenharmony_ci		ocfs2_delete_inode(inode);
12198c2ecf20Sopenharmony_ci	} else {
12208c2ecf20Sopenharmony_ci		truncate_inode_pages_final(&inode->i_data);
12218c2ecf20Sopenharmony_ci	}
12228c2ecf20Sopenharmony_ci	ocfs2_clear_inode(inode);
12238c2ecf20Sopenharmony_ci}
12248c2ecf20Sopenharmony_ci
12258c2ecf20Sopenharmony_ci/* Called under inode_lock, with no more references on the
12268c2ecf20Sopenharmony_ci * struct inode, so it's safe here to check the flags field
12278c2ecf20Sopenharmony_ci * and to manipulate i_nlink without any other locks. */
12288c2ecf20Sopenharmony_ciint ocfs2_drop_inode(struct inode *inode)
12298c2ecf20Sopenharmony_ci{
12308c2ecf20Sopenharmony_ci	struct ocfs2_inode_info *oi = OCFS2_I(inode);
12318c2ecf20Sopenharmony_ci
12328c2ecf20Sopenharmony_ci	trace_ocfs2_drop_inode((unsigned long long)oi->ip_blkno,
12338c2ecf20Sopenharmony_ci				inode->i_nlink, oi->ip_flags);
12348c2ecf20Sopenharmony_ci
12358c2ecf20Sopenharmony_ci	assert_spin_locked(&inode->i_lock);
12368c2ecf20Sopenharmony_ci	inode->i_state |= I_WILL_FREE;
12378c2ecf20Sopenharmony_ci	spin_unlock(&inode->i_lock);
12388c2ecf20Sopenharmony_ci	write_inode_now(inode, 1);
12398c2ecf20Sopenharmony_ci	spin_lock(&inode->i_lock);
12408c2ecf20Sopenharmony_ci	WARN_ON(inode->i_state & I_NEW);
12418c2ecf20Sopenharmony_ci	inode->i_state &= ~I_WILL_FREE;
12428c2ecf20Sopenharmony_ci
12438c2ecf20Sopenharmony_ci	return 1;
12448c2ecf20Sopenharmony_ci}
12458c2ecf20Sopenharmony_ci
12468c2ecf20Sopenharmony_ci/*
12478c2ecf20Sopenharmony_ci * This is called from our getattr.
12488c2ecf20Sopenharmony_ci */
12498c2ecf20Sopenharmony_ciint ocfs2_inode_revalidate(struct dentry *dentry)
12508c2ecf20Sopenharmony_ci{
12518c2ecf20Sopenharmony_ci	struct inode *inode = d_inode(dentry);
12528c2ecf20Sopenharmony_ci	int status = 0;
12538c2ecf20Sopenharmony_ci
12548c2ecf20Sopenharmony_ci	trace_ocfs2_inode_revalidate(inode,
12558c2ecf20Sopenharmony_ci		inode ? (unsigned long long)OCFS2_I(inode)->ip_blkno : 0ULL,
12568c2ecf20Sopenharmony_ci		inode ? (unsigned long long)OCFS2_I(inode)->ip_flags : 0);
12578c2ecf20Sopenharmony_ci
12588c2ecf20Sopenharmony_ci	if (!inode) {
12598c2ecf20Sopenharmony_ci		status = -ENOENT;
12608c2ecf20Sopenharmony_ci		goto bail;
12618c2ecf20Sopenharmony_ci	}
12628c2ecf20Sopenharmony_ci
12638c2ecf20Sopenharmony_ci	spin_lock(&OCFS2_I(inode)->ip_lock);
12648c2ecf20Sopenharmony_ci	if (OCFS2_I(inode)->ip_flags & OCFS2_INODE_DELETED) {
12658c2ecf20Sopenharmony_ci		spin_unlock(&OCFS2_I(inode)->ip_lock);
12668c2ecf20Sopenharmony_ci		status = -ENOENT;
12678c2ecf20Sopenharmony_ci		goto bail;
12688c2ecf20Sopenharmony_ci	}
12698c2ecf20Sopenharmony_ci	spin_unlock(&OCFS2_I(inode)->ip_lock);
12708c2ecf20Sopenharmony_ci
12718c2ecf20Sopenharmony_ci	/* Let ocfs2_inode_lock do the work of updating our struct
12728c2ecf20Sopenharmony_ci	 * inode for us. */
12738c2ecf20Sopenharmony_ci	status = ocfs2_inode_lock(inode, NULL, 0);
12748c2ecf20Sopenharmony_ci	if (status < 0) {
12758c2ecf20Sopenharmony_ci		if (status != -ENOENT)
12768c2ecf20Sopenharmony_ci			mlog_errno(status);
12778c2ecf20Sopenharmony_ci		goto bail;
12788c2ecf20Sopenharmony_ci	}
12798c2ecf20Sopenharmony_ci	ocfs2_inode_unlock(inode, 0);
12808c2ecf20Sopenharmony_cibail:
12818c2ecf20Sopenharmony_ci	return status;
12828c2ecf20Sopenharmony_ci}
12838c2ecf20Sopenharmony_ci
12848c2ecf20Sopenharmony_ci/*
12858c2ecf20Sopenharmony_ci * Updates a disk inode from a
12868c2ecf20Sopenharmony_ci * struct inode.
12878c2ecf20Sopenharmony_ci * Only takes ip_lock.
12888c2ecf20Sopenharmony_ci */
12898c2ecf20Sopenharmony_ciint ocfs2_mark_inode_dirty(handle_t *handle,
12908c2ecf20Sopenharmony_ci			   struct inode *inode,
12918c2ecf20Sopenharmony_ci			   struct buffer_head *bh)
12928c2ecf20Sopenharmony_ci{
12938c2ecf20Sopenharmony_ci	int status;
12948c2ecf20Sopenharmony_ci	struct ocfs2_dinode *fe = (struct ocfs2_dinode *) bh->b_data;
12958c2ecf20Sopenharmony_ci
12968c2ecf20Sopenharmony_ci	trace_ocfs2_mark_inode_dirty((unsigned long long)OCFS2_I(inode)->ip_blkno);
12978c2ecf20Sopenharmony_ci
12988c2ecf20Sopenharmony_ci	status = ocfs2_journal_access_di(handle, INODE_CACHE(inode), bh,
12998c2ecf20Sopenharmony_ci					 OCFS2_JOURNAL_ACCESS_WRITE);
13008c2ecf20Sopenharmony_ci	if (status < 0) {
13018c2ecf20Sopenharmony_ci		mlog_errno(status);
13028c2ecf20Sopenharmony_ci		goto leave;
13038c2ecf20Sopenharmony_ci	}
13048c2ecf20Sopenharmony_ci
13058c2ecf20Sopenharmony_ci	spin_lock(&OCFS2_I(inode)->ip_lock);
13068c2ecf20Sopenharmony_ci	fe->i_clusters = cpu_to_le32(OCFS2_I(inode)->ip_clusters);
13078c2ecf20Sopenharmony_ci	ocfs2_get_inode_flags(OCFS2_I(inode));
13088c2ecf20Sopenharmony_ci	fe->i_attr = cpu_to_le32(OCFS2_I(inode)->ip_attr);
13098c2ecf20Sopenharmony_ci	fe->i_dyn_features = cpu_to_le16(OCFS2_I(inode)->ip_dyn_features);
13108c2ecf20Sopenharmony_ci	spin_unlock(&OCFS2_I(inode)->ip_lock);
13118c2ecf20Sopenharmony_ci
13128c2ecf20Sopenharmony_ci	fe->i_size = cpu_to_le64(i_size_read(inode));
13138c2ecf20Sopenharmony_ci	ocfs2_set_links_count(fe, inode->i_nlink);
13148c2ecf20Sopenharmony_ci	fe->i_uid = cpu_to_le32(i_uid_read(inode));
13158c2ecf20Sopenharmony_ci	fe->i_gid = cpu_to_le32(i_gid_read(inode));
13168c2ecf20Sopenharmony_ci	fe->i_mode = cpu_to_le16(inode->i_mode);
13178c2ecf20Sopenharmony_ci	fe->i_atime = cpu_to_le64(inode->i_atime.tv_sec);
13188c2ecf20Sopenharmony_ci	fe->i_atime_nsec = cpu_to_le32(inode->i_atime.tv_nsec);
13198c2ecf20Sopenharmony_ci	fe->i_ctime = cpu_to_le64(inode->i_ctime.tv_sec);
13208c2ecf20Sopenharmony_ci	fe->i_ctime_nsec = cpu_to_le32(inode->i_ctime.tv_nsec);
13218c2ecf20Sopenharmony_ci	fe->i_mtime = cpu_to_le64(inode->i_mtime.tv_sec);
13228c2ecf20Sopenharmony_ci	fe->i_mtime_nsec = cpu_to_le32(inode->i_mtime.tv_nsec);
13238c2ecf20Sopenharmony_ci
13248c2ecf20Sopenharmony_ci	ocfs2_journal_dirty(handle, bh);
13258c2ecf20Sopenharmony_ci	ocfs2_update_inode_fsync_trans(handle, inode, 1);
13268c2ecf20Sopenharmony_cileave:
13278c2ecf20Sopenharmony_ci	return status;
13288c2ecf20Sopenharmony_ci}
13298c2ecf20Sopenharmony_ci
13308c2ecf20Sopenharmony_ci/*
13318c2ecf20Sopenharmony_ci *
13328c2ecf20Sopenharmony_ci * Updates a struct inode from a disk inode.
13338c2ecf20Sopenharmony_ci * does no i/o, only takes ip_lock.
13348c2ecf20Sopenharmony_ci */
13358c2ecf20Sopenharmony_civoid ocfs2_refresh_inode(struct inode *inode,
13368c2ecf20Sopenharmony_ci			 struct ocfs2_dinode *fe)
13378c2ecf20Sopenharmony_ci{
13388c2ecf20Sopenharmony_ci	spin_lock(&OCFS2_I(inode)->ip_lock);
13398c2ecf20Sopenharmony_ci
13408c2ecf20Sopenharmony_ci	OCFS2_I(inode)->ip_clusters = le32_to_cpu(fe->i_clusters);
13418c2ecf20Sopenharmony_ci	OCFS2_I(inode)->ip_attr = le32_to_cpu(fe->i_attr);
13428c2ecf20Sopenharmony_ci	OCFS2_I(inode)->ip_dyn_features = le16_to_cpu(fe->i_dyn_features);
13438c2ecf20Sopenharmony_ci	ocfs2_set_inode_flags(inode);
13448c2ecf20Sopenharmony_ci	i_size_write(inode, le64_to_cpu(fe->i_size));
13458c2ecf20Sopenharmony_ci	set_nlink(inode, ocfs2_read_links_count(fe));
13468c2ecf20Sopenharmony_ci	i_uid_write(inode, le32_to_cpu(fe->i_uid));
13478c2ecf20Sopenharmony_ci	i_gid_write(inode, le32_to_cpu(fe->i_gid));
13488c2ecf20Sopenharmony_ci	inode->i_mode = le16_to_cpu(fe->i_mode);
13498c2ecf20Sopenharmony_ci	if (S_ISLNK(inode->i_mode) && le32_to_cpu(fe->i_clusters) == 0)
13508c2ecf20Sopenharmony_ci		inode->i_blocks = 0;
13518c2ecf20Sopenharmony_ci	else
13528c2ecf20Sopenharmony_ci		inode->i_blocks = ocfs2_inode_sector_count(inode);
13538c2ecf20Sopenharmony_ci	inode->i_atime.tv_sec = le64_to_cpu(fe->i_atime);
13548c2ecf20Sopenharmony_ci	inode->i_atime.tv_nsec = le32_to_cpu(fe->i_atime_nsec);
13558c2ecf20Sopenharmony_ci	inode->i_mtime.tv_sec = le64_to_cpu(fe->i_mtime);
13568c2ecf20Sopenharmony_ci	inode->i_mtime.tv_nsec = le32_to_cpu(fe->i_mtime_nsec);
13578c2ecf20Sopenharmony_ci	inode->i_ctime.tv_sec = le64_to_cpu(fe->i_ctime);
13588c2ecf20Sopenharmony_ci	inode->i_ctime.tv_nsec = le32_to_cpu(fe->i_ctime_nsec);
13598c2ecf20Sopenharmony_ci
13608c2ecf20Sopenharmony_ci	spin_unlock(&OCFS2_I(inode)->ip_lock);
13618c2ecf20Sopenharmony_ci}
13628c2ecf20Sopenharmony_ci
13638c2ecf20Sopenharmony_ciint ocfs2_validate_inode_block(struct super_block *sb,
13648c2ecf20Sopenharmony_ci			       struct buffer_head *bh)
13658c2ecf20Sopenharmony_ci{
13668c2ecf20Sopenharmony_ci	int rc;
13678c2ecf20Sopenharmony_ci	struct ocfs2_dinode *di = (struct ocfs2_dinode *)bh->b_data;
13688c2ecf20Sopenharmony_ci
13698c2ecf20Sopenharmony_ci	trace_ocfs2_validate_inode_block((unsigned long long)bh->b_blocknr);
13708c2ecf20Sopenharmony_ci
13718c2ecf20Sopenharmony_ci	BUG_ON(!buffer_uptodate(bh));
13728c2ecf20Sopenharmony_ci
13738c2ecf20Sopenharmony_ci	/*
13748c2ecf20Sopenharmony_ci	 * If the ecc fails, we return the error but otherwise
13758c2ecf20Sopenharmony_ci	 * leave the filesystem running.  We know any error is
13768c2ecf20Sopenharmony_ci	 * local to this block.
13778c2ecf20Sopenharmony_ci	 */
13788c2ecf20Sopenharmony_ci	rc = ocfs2_validate_meta_ecc(sb, bh->b_data, &di->i_check);
13798c2ecf20Sopenharmony_ci	if (rc) {
13808c2ecf20Sopenharmony_ci		mlog(ML_ERROR, "Checksum failed for dinode %llu\n",
13818c2ecf20Sopenharmony_ci		     (unsigned long long)bh->b_blocknr);
13828c2ecf20Sopenharmony_ci		goto bail;
13838c2ecf20Sopenharmony_ci	}
13848c2ecf20Sopenharmony_ci
13858c2ecf20Sopenharmony_ci	/*
13868c2ecf20Sopenharmony_ci	 * Errors after here are fatal.
13878c2ecf20Sopenharmony_ci	 */
13888c2ecf20Sopenharmony_ci
13898c2ecf20Sopenharmony_ci	rc = -EINVAL;
13908c2ecf20Sopenharmony_ci
13918c2ecf20Sopenharmony_ci	if (!OCFS2_IS_VALID_DINODE(di)) {
13928c2ecf20Sopenharmony_ci		rc = ocfs2_error(sb, "Invalid dinode #%llu: signature = %.*s\n",
13938c2ecf20Sopenharmony_ci				 (unsigned long long)bh->b_blocknr, 7,
13948c2ecf20Sopenharmony_ci				 di->i_signature);
13958c2ecf20Sopenharmony_ci		goto bail;
13968c2ecf20Sopenharmony_ci	}
13978c2ecf20Sopenharmony_ci
13988c2ecf20Sopenharmony_ci	if (le64_to_cpu(di->i_blkno) != bh->b_blocknr) {
13998c2ecf20Sopenharmony_ci		rc = ocfs2_error(sb, "Invalid dinode #%llu: i_blkno is %llu\n",
14008c2ecf20Sopenharmony_ci				 (unsigned long long)bh->b_blocknr,
14018c2ecf20Sopenharmony_ci				 (unsigned long long)le64_to_cpu(di->i_blkno));
14028c2ecf20Sopenharmony_ci		goto bail;
14038c2ecf20Sopenharmony_ci	}
14048c2ecf20Sopenharmony_ci
14058c2ecf20Sopenharmony_ci	if (!(di->i_flags & cpu_to_le32(OCFS2_VALID_FL))) {
14068c2ecf20Sopenharmony_ci		rc = ocfs2_error(sb,
14078c2ecf20Sopenharmony_ci				 "Invalid dinode #%llu: OCFS2_VALID_FL not set\n",
14088c2ecf20Sopenharmony_ci				 (unsigned long long)bh->b_blocknr);
14098c2ecf20Sopenharmony_ci		goto bail;
14108c2ecf20Sopenharmony_ci	}
14118c2ecf20Sopenharmony_ci
14128c2ecf20Sopenharmony_ci	if (le32_to_cpu(di->i_fs_generation) !=
14138c2ecf20Sopenharmony_ci	    OCFS2_SB(sb)->fs_generation) {
14148c2ecf20Sopenharmony_ci		rc = ocfs2_error(sb,
14158c2ecf20Sopenharmony_ci				 "Invalid dinode #%llu: fs_generation is %u\n",
14168c2ecf20Sopenharmony_ci				 (unsigned long long)bh->b_blocknr,
14178c2ecf20Sopenharmony_ci				 le32_to_cpu(di->i_fs_generation));
14188c2ecf20Sopenharmony_ci		goto bail;
14198c2ecf20Sopenharmony_ci	}
14208c2ecf20Sopenharmony_ci
14218c2ecf20Sopenharmony_ci	rc = 0;
14228c2ecf20Sopenharmony_ci
14238c2ecf20Sopenharmony_cibail:
14248c2ecf20Sopenharmony_ci	return rc;
14258c2ecf20Sopenharmony_ci}
14268c2ecf20Sopenharmony_ci
14278c2ecf20Sopenharmony_cistatic int ocfs2_filecheck_validate_inode_block(struct super_block *sb,
14288c2ecf20Sopenharmony_ci						struct buffer_head *bh)
14298c2ecf20Sopenharmony_ci{
14308c2ecf20Sopenharmony_ci	int rc = 0;
14318c2ecf20Sopenharmony_ci	struct ocfs2_dinode *di = (struct ocfs2_dinode *)bh->b_data;
14328c2ecf20Sopenharmony_ci
14338c2ecf20Sopenharmony_ci	trace_ocfs2_filecheck_validate_inode_block(
14348c2ecf20Sopenharmony_ci		(unsigned long long)bh->b_blocknr);
14358c2ecf20Sopenharmony_ci
14368c2ecf20Sopenharmony_ci	BUG_ON(!buffer_uptodate(bh));
14378c2ecf20Sopenharmony_ci
14388c2ecf20Sopenharmony_ci	/*
14398c2ecf20Sopenharmony_ci	 * Call ocfs2_validate_meta_ecc() first since it has ecc repair
14408c2ecf20Sopenharmony_ci	 * function, but we should not return error immediately when ecc
14418c2ecf20Sopenharmony_ci	 * validation fails, because the reason is quite likely the invalid
14428c2ecf20Sopenharmony_ci	 * inode number inputed.
14438c2ecf20Sopenharmony_ci	 */
14448c2ecf20Sopenharmony_ci	rc = ocfs2_validate_meta_ecc(sb, bh->b_data, &di->i_check);
14458c2ecf20Sopenharmony_ci	if (rc) {
14468c2ecf20Sopenharmony_ci		mlog(ML_ERROR,
14478c2ecf20Sopenharmony_ci		     "Filecheck: checksum failed for dinode %llu\n",
14488c2ecf20Sopenharmony_ci		     (unsigned long long)bh->b_blocknr);
14498c2ecf20Sopenharmony_ci		rc = -OCFS2_FILECHECK_ERR_BLOCKECC;
14508c2ecf20Sopenharmony_ci	}
14518c2ecf20Sopenharmony_ci
14528c2ecf20Sopenharmony_ci	if (!OCFS2_IS_VALID_DINODE(di)) {
14538c2ecf20Sopenharmony_ci		mlog(ML_ERROR,
14548c2ecf20Sopenharmony_ci		     "Filecheck: invalid dinode #%llu: signature = %.*s\n",
14558c2ecf20Sopenharmony_ci		     (unsigned long long)bh->b_blocknr, 7, di->i_signature);
14568c2ecf20Sopenharmony_ci		rc = -OCFS2_FILECHECK_ERR_INVALIDINO;
14578c2ecf20Sopenharmony_ci		goto bail;
14588c2ecf20Sopenharmony_ci	} else if (rc)
14598c2ecf20Sopenharmony_ci		goto bail;
14608c2ecf20Sopenharmony_ci
14618c2ecf20Sopenharmony_ci	if (le64_to_cpu(di->i_blkno) != bh->b_blocknr) {
14628c2ecf20Sopenharmony_ci		mlog(ML_ERROR,
14638c2ecf20Sopenharmony_ci		     "Filecheck: invalid dinode #%llu: i_blkno is %llu\n",
14648c2ecf20Sopenharmony_ci		     (unsigned long long)bh->b_blocknr,
14658c2ecf20Sopenharmony_ci		     (unsigned long long)le64_to_cpu(di->i_blkno));
14668c2ecf20Sopenharmony_ci		rc = -OCFS2_FILECHECK_ERR_BLOCKNO;
14678c2ecf20Sopenharmony_ci		goto bail;
14688c2ecf20Sopenharmony_ci	}
14698c2ecf20Sopenharmony_ci
14708c2ecf20Sopenharmony_ci	if (!(di->i_flags & cpu_to_le32(OCFS2_VALID_FL))) {
14718c2ecf20Sopenharmony_ci		mlog(ML_ERROR,
14728c2ecf20Sopenharmony_ci		     "Filecheck: invalid dinode #%llu: OCFS2_VALID_FL "
14738c2ecf20Sopenharmony_ci		     "not set\n",
14748c2ecf20Sopenharmony_ci		     (unsigned long long)bh->b_blocknr);
14758c2ecf20Sopenharmony_ci		rc = -OCFS2_FILECHECK_ERR_VALIDFLAG;
14768c2ecf20Sopenharmony_ci		goto bail;
14778c2ecf20Sopenharmony_ci	}
14788c2ecf20Sopenharmony_ci
14798c2ecf20Sopenharmony_ci	if (le32_to_cpu(di->i_fs_generation) !=
14808c2ecf20Sopenharmony_ci	    OCFS2_SB(sb)->fs_generation) {
14818c2ecf20Sopenharmony_ci		mlog(ML_ERROR,
14828c2ecf20Sopenharmony_ci		     "Filecheck: invalid dinode #%llu: fs_generation is %u\n",
14838c2ecf20Sopenharmony_ci		     (unsigned long long)bh->b_blocknr,
14848c2ecf20Sopenharmony_ci		     le32_to_cpu(di->i_fs_generation));
14858c2ecf20Sopenharmony_ci		rc = -OCFS2_FILECHECK_ERR_GENERATION;
14868c2ecf20Sopenharmony_ci	}
14878c2ecf20Sopenharmony_ci
14888c2ecf20Sopenharmony_cibail:
14898c2ecf20Sopenharmony_ci	return rc;
14908c2ecf20Sopenharmony_ci}
14918c2ecf20Sopenharmony_ci
14928c2ecf20Sopenharmony_cistatic int ocfs2_filecheck_repair_inode_block(struct super_block *sb,
14938c2ecf20Sopenharmony_ci					      struct buffer_head *bh)
14948c2ecf20Sopenharmony_ci{
14958c2ecf20Sopenharmony_ci	int changed = 0;
14968c2ecf20Sopenharmony_ci	struct ocfs2_dinode *di = (struct ocfs2_dinode *)bh->b_data;
14978c2ecf20Sopenharmony_ci
14988c2ecf20Sopenharmony_ci	if (!ocfs2_filecheck_validate_inode_block(sb, bh))
14998c2ecf20Sopenharmony_ci		return 0;
15008c2ecf20Sopenharmony_ci
15018c2ecf20Sopenharmony_ci	trace_ocfs2_filecheck_repair_inode_block(
15028c2ecf20Sopenharmony_ci		(unsigned long long)bh->b_blocknr);
15038c2ecf20Sopenharmony_ci
15048c2ecf20Sopenharmony_ci	if (ocfs2_is_hard_readonly(OCFS2_SB(sb)) ||
15058c2ecf20Sopenharmony_ci	    ocfs2_is_soft_readonly(OCFS2_SB(sb))) {
15068c2ecf20Sopenharmony_ci		mlog(ML_ERROR,
15078c2ecf20Sopenharmony_ci		     "Filecheck: cannot repair dinode #%llu "
15088c2ecf20Sopenharmony_ci		     "on readonly filesystem\n",
15098c2ecf20Sopenharmony_ci		     (unsigned long long)bh->b_blocknr);
15108c2ecf20Sopenharmony_ci		return -OCFS2_FILECHECK_ERR_READONLY;
15118c2ecf20Sopenharmony_ci	}
15128c2ecf20Sopenharmony_ci
15138c2ecf20Sopenharmony_ci	if (buffer_jbd(bh)) {
15148c2ecf20Sopenharmony_ci		mlog(ML_ERROR,
15158c2ecf20Sopenharmony_ci		     "Filecheck: cannot repair dinode #%llu, "
15168c2ecf20Sopenharmony_ci		     "its buffer is in jbd\n",
15178c2ecf20Sopenharmony_ci		     (unsigned long long)bh->b_blocknr);
15188c2ecf20Sopenharmony_ci		return -OCFS2_FILECHECK_ERR_INJBD;
15198c2ecf20Sopenharmony_ci	}
15208c2ecf20Sopenharmony_ci
15218c2ecf20Sopenharmony_ci	if (!OCFS2_IS_VALID_DINODE(di)) {
15228c2ecf20Sopenharmony_ci		/* Cannot fix invalid inode block */
15238c2ecf20Sopenharmony_ci		return -OCFS2_FILECHECK_ERR_INVALIDINO;
15248c2ecf20Sopenharmony_ci	}
15258c2ecf20Sopenharmony_ci
15268c2ecf20Sopenharmony_ci	if (!(di->i_flags & cpu_to_le32(OCFS2_VALID_FL))) {
15278c2ecf20Sopenharmony_ci		/* Cannot just add VALID_FL flag back as a fix,
15288c2ecf20Sopenharmony_ci		 * need more things to check here.
15298c2ecf20Sopenharmony_ci		 */
15308c2ecf20Sopenharmony_ci		return -OCFS2_FILECHECK_ERR_VALIDFLAG;
15318c2ecf20Sopenharmony_ci	}
15328c2ecf20Sopenharmony_ci
15338c2ecf20Sopenharmony_ci	if (le64_to_cpu(di->i_blkno) != bh->b_blocknr) {
15348c2ecf20Sopenharmony_ci		di->i_blkno = cpu_to_le64(bh->b_blocknr);
15358c2ecf20Sopenharmony_ci		changed = 1;
15368c2ecf20Sopenharmony_ci		mlog(ML_ERROR,
15378c2ecf20Sopenharmony_ci		     "Filecheck: reset dinode #%llu: i_blkno to %llu\n",
15388c2ecf20Sopenharmony_ci		     (unsigned long long)bh->b_blocknr,
15398c2ecf20Sopenharmony_ci		     (unsigned long long)le64_to_cpu(di->i_blkno));
15408c2ecf20Sopenharmony_ci	}
15418c2ecf20Sopenharmony_ci
15428c2ecf20Sopenharmony_ci	if (le32_to_cpu(di->i_fs_generation) !=
15438c2ecf20Sopenharmony_ci	    OCFS2_SB(sb)->fs_generation) {
15448c2ecf20Sopenharmony_ci		di->i_fs_generation = cpu_to_le32(OCFS2_SB(sb)->fs_generation);
15458c2ecf20Sopenharmony_ci		changed = 1;
15468c2ecf20Sopenharmony_ci		mlog(ML_ERROR,
15478c2ecf20Sopenharmony_ci		     "Filecheck: reset dinode #%llu: fs_generation to %u\n",
15488c2ecf20Sopenharmony_ci		     (unsigned long long)bh->b_blocknr,
15498c2ecf20Sopenharmony_ci		     le32_to_cpu(di->i_fs_generation));
15508c2ecf20Sopenharmony_ci	}
15518c2ecf20Sopenharmony_ci
15528c2ecf20Sopenharmony_ci	if (changed || ocfs2_validate_meta_ecc(sb, bh->b_data, &di->i_check)) {
15538c2ecf20Sopenharmony_ci		ocfs2_compute_meta_ecc(sb, bh->b_data, &di->i_check);
15548c2ecf20Sopenharmony_ci		mark_buffer_dirty(bh);
15558c2ecf20Sopenharmony_ci		mlog(ML_ERROR,
15568c2ecf20Sopenharmony_ci		     "Filecheck: reset dinode #%llu: compute meta ecc\n",
15578c2ecf20Sopenharmony_ci		     (unsigned long long)bh->b_blocknr);
15588c2ecf20Sopenharmony_ci	}
15598c2ecf20Sopenharmony_ci
15608c2ecf20Sopenharmony_ci	return 0;
15618c2ecf20Sopenharmony_ci}
15628c2ecf20Sopenharmony_ci
15638c2ecf20Sopenharmony_cistatic int
15648c2ecf20Sopenharmony_ciocfs2_filecheck_read_inode_block_full(struct inode *inode,
15658c2ecf20Sopenharmony_ci				      struct buffer_head **bh,
15668c2ecf20Sopenharmony_ci				      int flags, int type)
15678c2ecf20Sopenharmony_ci{
15688c2ecf20Sopenharmony_ci	int rc;
15698c2ecf20Sopenharmony_ci	struct buffer_head *tmp = *bh;
15708c2ecf20Sopenharmony_ci
15718c2ecf20Sopenharmony_ci	if (!type) /* Check inode block */
15728c2ecf20Sopenharmony_ci		rc = ocfs2_read_blocks(INODE_CACHE(inode),
15738c2ecf20Sopenharmony_ci				OCFS2_I(inode)->ip_blkno,
15748c2ecf20Sopenharmony_ci				1, &tmp, flags,
15758c2ecf20Sopenharmony_ci				ocfs2_filecheck_validate_inode_block);
15768c2ecf20Sopenharmony_ci	else /* Repair inode block */
15778c2ecf20Sopenharmony_ci		rc = ocfs2_read_blocks(INODE_CACHE(inode),
15788c2ecf20Sopenharmony_ci				OCFS2_I(inode)->ip_blkno,
15798c2ecf20Sopenharmony_ci				1, &tmp, flags,
15808c2ecf20Sopenharmony_ci				ocfs2_filecheck_repair_inode_block);
15818c2ecf20Sopenharmony_ci
15828c2ecf20Sopenharmony_ci	/* If ocfs2_read_blocks() got us a new bh, pass it up. */
15838c2ecf20Sopenharmony_ci	if (!rc && !*bh)
15848c2ecf20Sopenharmony_ci		*bh = tmp;
15858c2ecf20Sopenharmony_ci
15868c2ecf20Sopenharmony_ci	return rc;
15878c2ecf20Sopenharmony_ci}
15888c2ecf20Sopenharmony_ci
15898c2ecf20Sopenharmony_ciint ocfs2_read_inode_block_full(struct inode *inode, struct buffer_head **bh,
15908c2ecf20Sopenharmony_ci				int flags)
15918c2ecf20Sopenharmony_ci{
15928c2ecf20Sopenharmony_ci	int rc;
15938c2ecf20Sopenharmony_ci	struct buffer_head *tmp = *bh;
15948c2ecf20Sopenharmony_ci
15958c2ecf20Sopenharmony_ci	rc = ocfs2_read_blocks(INODE_CACHE(inode), OCFS2_I(inode)->ip_blkno,
15968c2ecf20Sopenharmony_ci			       1, &tmp, flags, ocfs2_validate_inode_block);
15978c2ecf20Sopenharmony_ci
15988c2ecf20Sopenharmony_ci	/* If ocfs2_read_blocks() got us a new bh, pass it up. */
15998c2ecf20Sopenharmony_ci	if (!rc && !*bh)
16008c2ecf20Sopenharmony_ci		*bh = tmp;
16018c2ecf20Sopenharmony_ci
16028c2ecf20Sopenharmony_ci	return rc;
16038c2ecf20Sopenharmony_ci}
16048c2ecf20Sopenharmony_ci
16058c2ecf20Sopenharmony_ciint ocfs2_read_inode_block(struct inode *inode, struct buffer_head **bh)
16068c2ecf20Sopenharmony_ci{
16078c2ecf20Sopenharmony_ci	return ocfs2_read_inode_block_full(inode, bh, 0);
16088c2ecf20Sopenharmony_ci}
16098c2ecf20Sopenharmony_ci
16108c2ecf20Sopenharmony_ci
16118c2ecf20Sopenharmony_cistatic u64 ocfs2_inode_cache_owner(struct ocfs2_caching_info *ci)
16128c2ecf20Sopenharmony_ci{
16138c2ecf20Sopenharmony_ci	struct ocfs2_inode_info *oi = cache_info_to_inode(ci);
16148c2ecf20Sopenharmony_ci
16158c2ecf20Sopenharmony_ci	return oi->ip_blkno;
16168c2ecf20Sopenharmony_ci}
16178c2ecf20Sopenharmony_ci
16188c2ecf20Sopenharmony_cistatic struct super_block *ocfs2_inode_cache_get_super(struct ocfs2_caching_info *ci)
16198c2ecf20Sopenharmony_ci{
16208c2ecf20Sopenharmony_ci	struct ocfs2_inode_info *oi = cache_info_to_inode(ci);
16218c2ecf20Sopenharmony_ci
16228c2ecf20Sopenharmony_ci	return oi->vfs_inode.i_sb;
16238c2ecf20Sopenharmony_ci}
16248c2ecf20Sopenharmony_ci
16258c2ecf20Sopenharmony_cistatic void ocfs2_inode_cache_lock(struct ocfs2_caching_info *ci)
16268c2ecf20Sopenharmony_ci{
16278c2ecf20Sopenharmony_ci	struct ocfs2_inode_info *oi = cache_info_to_inode(ci);
16288c2ecf20Sopenharmony_ci
16298c2ecf20Sopenharmony_ci	spin_lock(&oi->ip_lock);
16308c2ecf20Sopenharmony_ci}
16318c2ecf20Sopenharmony_ci
16328c2ecf20Sopenharmony_cistatic void ocfs2_inode_cache_unlock(struct ocfs2_caching_info *ci)
16338c2ecf20Sopenharmony_ci{
16348c2ecf20Sopenharmony_ci	struct ocfs2_inode_info *oi = cache_info_to_inode(ci);
16358c2ecf20Sopenharmony_ci
16368c2ecf20Sopenharmony_ci	spin_unlock(&oi->ip_lock);
16378c2ecf20Sopenharmony_ci}
16388c2ecf20Sopenharmony_ci
16398c2ecf20Sopenharmony_cistatic void ocfs2_inode_cache_io_lock(struct ocfs2_caching_info *ci)
16408c2ecf20Sopenharmony_ci{
16418c2ecf20Sopenharmony_ci	struct ocfs2_inode_info *oi = cache_info_to_inode(ci);
16428c2ecf20Sopenharmony_ci
16438c2ecf20Sopenharmony_ci	mutex_lock(&oi->ip_io_mutex);
16448c2ecf20Sopenharmony_ci}
16458c2ecf20Sopenharmony_ci
16468c2ecf20Sopenharmony_cistatic void ocfs2_inode_cache_io_unlock(struct ocfs2_caching_info *ci)
16478c2ecf20Sopenharmony_ci{
16488c2ecf20Sopenharmony_ci	struct ocfs2_inode_info *oi = cache_info_to_inode(ci);
16498c2ecf20Sopenharmony_ci
16508c2ecf20Sopenharmony_ci	mutex_unlock(&oi->ip_io_mutex);
16518c2ecf20Sopenharmony_ci}
16528c2ecf20Sopenharmony_ci
16538c2ecf20Sopenharmony_ciconst struct ocfs2_caching_operations ocfs2_inode_caching_ops = {
16548c2ecf20Sopenharmony_ci	.co_owner		= ocfs2_inode_cache_owner,
16558c2ecf20Sopenharmony_ci	.co_get_super		= ocfs2_inode_cache_get_super,
16568c2ecf20Sopenharmony_ci	.co_cache_lock		= ocfs2_inode_cache_lock,
16578c2ecf20Sopenharmony_ci	.co_cache_unlock	= ocfs2_inode_cache_unlock,
16588c2ecf20Sopenharmony_ci	.co_io_lock		= ocfs2_inode_cache_io_lock,
16598c2ecf20Sopenharmony_ci	.co_io_unlock		= ocfs2_inode_cache_io_unlock,
16608c2ecf20Sopenharmony_ci};
16618c2ecf20Sopenharmony_ci
1662