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