// SPDX-License-Identifier: GPL-2.0 /* * Copyright (c) 2000-2006 Silicon Graphics, Inc. * All Rights Reserved. */ #include "xfs.h" #include "xfs_fs.h" #include "xfs_shared.h" #include "xfs_format.h" #include "xfs_log_format.h" #include "xfs_trans_resv.h" #include "xfs_mount.h" #include "xfs_inode.h" #include "xfs_trans.h" #include "xfs_inode_item.h" #include "xfs_trace.h" #include "xfs_trans_priv.h" #include "xfs_buf_item.h" #include "xfs_log.h" #include "xfs_error.h" #include "xfs_log_priv.h" #include "xfs_log_recover.h" #include "xfs_icache.h" #include "xfs_bmap_btree.h" STATIC void xlog_recover_inode_ra_pass2( struct xlog *log, struct xlog_recover_item *item) { … } /* * Inode fork owner changes * * If we have been told that we have to reparent the inode fork, it's because an * extent swap operation on a CRC enabled filesystem has been done and we are * replaying it. We need to walk the BMBT of the appropriate fork and change the * owners of it. * * The complexity here is that we don't have an inode context to work with, so * after we've replayed the inode we need to instantiate one. This is where the * fun begins. * * We are in the middle of log recovery, so we can't run transactions. That * means we cannot use cache coherent inode instantiation via xfs_iget(), as * that will result in the corresponding iput() running the inode through * xfs_inactive(). If we've just replayed an inode core that changes the link * count to zero (i.e. it's been unlinked), then xfs_inactive() will run * transactions (bad!). * * So, to avoid this, we instantiate an inode directly from the inode core we've * just recovered. We have the buffer still locked, and all we really need to * instantiate is the inode core and the forks being modified. We can do this * manually, then run the inode btree owner change, and then tear down the * xfs_inode without having to run any transactions at all. * * Also, because we don't have a transaction context available here but need to * gather all the buffers we modify for writeback so we pass the buffer_list * instead for the operation to use. */ STATIC int xfs_recover_inode_owner_change( struct xfs_mount *mp, struct xfs_dinode *dip, struct xfs_inode_log_format *in_f, struct list_head *buffer_list) { … } static inline bool xfs_log_dinode_has_bigtime(const struct xfs_log_dinode *ld) { … } /* Convert a log timestamp to an ondisk timestamp. */ static inline xfs_timestamp_t xfs_log_dinode_to_disk_ts( struct xfs_log_dinode *from, const xfs_log_timestamp_t its) { … } static inline bool xfs_log_dinode_has_large_extent_counts( const struct xfs_log_dinode *ld) { … } static inline void xfs_log_dinode_to_disk_iext_counters( struct xfs_log_dinode *from, struct xfs_dinode *to) { … } STATIC void xfs_log_dinode_to_disk( struct xfs_log_dinode *from, struct xfs_dinode *to, xfs_lsn_t lsn) { … } STATIC int xlog_dinode_verify_extent_counts( struct xfs_mount *mp, struct xfs_log_dinode *ldip) { … } STATIC int xlog_recover_inode_commit_pass2( struct xlog *log, struct list_head *buffer_list, struct xlog_recover_item *item, xfs_lsn_t current_lsn) { … } const struct xlog_recover_item_ops xlog_inode_item_ops = …;