|
@@ -116,6 +116,71 @@ xfs_inode_alloc(
|
|
|
return ip;
|
|
|
}
|
|
|
|
|
|
+STATIC void
|
|
|
+xfs_inode_free(
|
|
|
+ struct xfs_inode *ip)
|
|
|
+{
|
|
|
+ switch (ip->i_d.di_mode & S_IFMT) {
|
|
|
+ case S_IFREG:
|
|
|
+ case S_IFDIR:
|
|
|
+ case S_IFLNK:
|
|
|
+ xfs_idestroy_fork(ip, XFS_DATA_FORK);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (ip->i_afp)
|
|
|
+ xfs_idestroy_fork(ip, XFS_ATTR_FORK);
|
|
|
+
|
|
|
+#ifdef XFS_INODE_TRACE
|
|
|
+ ktrace_free(ip->i_trace);
|
|
|
+#endif
|
|
|
+#ifdef XFS_BMAP_TRACE
|
|
|
+ ktrace_free(ip->i_xtrace);
|
|
|
+#endif
|
|
|
+#ifdef XFS_BTREE_TRACE
|
|
|
+ ktrace_free(ip->i_btrace);
|
|
|
+#endif
|
|
|
+#ifdef XFS_RW_TRACE
|
|
|
+ ktrace_free(ip->i_rwtrace);
|
|
|
+#endif
|
|
|
+#ifdef XFS_ILOCK_TRACE
|
|
|
+ ktrace_free(ip->i_lock_trace);
|
|
|
+#endif
|
|
|
+#ifdef XFS_DIR2_TRACE
|
|
|
+ ktrace_free(ip->i_dir_trace);
|
|
|
+#endif
|
|
|
+
|
|
|
+ if (ip->i_itemp) {
|
|
|
+ /*
|
|
|
+ * Only if we are shutting down the fs will we see an
|
|
|
+ * inode still in the AIL. If it is there, we should remove
|
|
|
+ * it to prevent a use-after-free from occurring.
|
|
|
+ */
|
|
|
+ xfs_log_item_t *lip = &ip->i_itemp->ili_item;
|
|
|
+ struct xfs_ail *ailp = lip->li_ailp;
|
|
|
+
|
|
|
+ ASSERT(((lip->li_flags & XFS_LI_IN_AIL) == 0) ||
|
|
|
+ XFS_FORCED_SHUTDOWN(ip->i_mount));
|
|
|
+ if (lip->li_flags & XFS_LI_IN_AIL) {
|
|
|
+ spin_lock(&ailp->xa_lock);
|
|
|
+ if (lip->li_flags & XFS_LI_IN_AIL)
|
|
|
+ xfs_trans_ail_delete(ailp, lip);
|
|
|
+ else
|
|
|
+ spin_unlock(&ailp->xa_lock);
|
|
|
+ }
|
|
|
+ xfs_inode_item_destroy(ip);
|
|
|
+ ip->i_itemp = NULL;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* asserts to verify all state is correct here */
|
|
|
+ ASSERT(atomic_read(&ip->i_iocount) == 0);
|
|
|
+ ASSERT(atomic_read(&ip->i_pincount) == 0);
|
|
|
+ ASSERT(!spin_is_locked(&ip->i_flags_lock));
|
|
|
+ ASSERT(completion_done(&ip->i_flush));
|
|
|
+
|
|
|
+ kmem_zone_free(xfs_inode_zone, ip);
|
|
|
+}
|
|
|
+
|
|
|
/*
|
|
|
* Check the validity of the inode we just found it the cache
|
|
|
*/
|
|
@@ -292,7 +357,8 @@ out_preload_end:
|
|
|
if (lock_flags)
|
|
|
xfs_iunlock(ip, lock_flags);
|
|
|
out_destroy:
|
|
|
- xfs_destroy_inode(ip);
|
|
|
+ __destroy_inode(VFS_I(ip));
|
|
|
+ xfs_inode_free(ip);
|
|
|
return error;
|
|
|
}
|
|
|
|
|
@@ -497,62 +563,7 @@ xfs_ireclaim(
|
|
|
xfs_qm_dqdetach(ip);
|
|
|
xfs_iunlock(ip, XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL);
|
|
|
|
|
|
- switch (ip->i_d.di_mode & S_IFMT) {
|
|
|
- case S_IFREG:
|
|
|
- case S_IFDIR:
|
|
|
- case S_IFLNK:
|
|
|
- xfs_idestroy_fork(ip, XFS_DATA_FORK);
|
|
|
- break;
|
|
|
- }
|
|
|
-
|
|
|
- if (ip->i_afp)
|
|
|
- xfs_idestroy_fork(ip, XFS_ATTR_FORK);
|
|
|
-
|
|
|
-#ifdef XFS_INODE_TRACE
|
|
|
- ktrace_free(ip->i_trace);
|
|
|
-#endif
|
|
|
-#ifdef XFS_BMAP_TRACE
|
|
|
- ktrace_free(ip->i_xtrace);
|
|
|
-#endif
|
|
|
-#ifdef XFS_BTREE_TRACE
|
|
|
- ktrace_free(ip->i_btrace);
|
|
|
-#endif
|
|
|
-#ifdef XFS_RW_TRACE
|
|
|
- ktrace_free(ip->i_rwtrace);
|
|
|
-#endif
|
|
|
-#ifdef XFS_ILOCK_TRACE
|
|
|
- ktrace_free(ip->i_lock_trace);
|
|
|
-#endif
|
|
|
-#ifdef XFS_DIR2_TRACE
|
|
|
- ktrace_free(ip->i_dir_trace);
|
|
|
-#endif
|
|
|
- if (ip->i_itemp) {
|
|
|
- /*
|
|
|
- * Only if we are shutting down the fs will we see an
|
|
|
- * inode still in the AIL. If it is there, we should remove
|
|
|
- * it to prevent a use-after-free from occurring.
|
|
|
- */
|
|
|
- xfs_log_item_t *lip = &ip->i_itemp->ili_item;
|
|
|
- struct xfs_ail *ailp = lip->li_ailp;
|
|
|
-
|
|
|
- ASSERT(((lip->li_flags & XFS_LI_IN_AIL) == 0) ||
|
|
|
- XFS_FORCED_SHUTDOWN(ip->i_mount));
|
|
|
- if (lip->li_flags & XFS_LI_IN_AIL) {
|
|
|
- spin_lock(&ailp->xa_lock);
|
|
|
- if (lip->li_flags & XFS_LI_IN_AIL)
|
|
|
- xfs_trans_ail_delete(ailp, lip);
|
|
|
- else
|
|
|
- spin_unlock(&ailp->xa_lock);
|
|
|
- }
|
|
|
- xfs_inode_item_destroy(ip);
|
|
|
- ip->i_itemp = NULL;
|
|
|
- }
|
|
|
- /* asserts to verify all state is correct here */
|
|
|
- ASSERT(atomic_read(&ip->i_iocount) == 0);
|
|
|
- ASSERT(atomic_read(&ip->i_pincount) == 0);
|
|
|
- ASSERT(!spin_is_locked(&ip->i_flags_lock));
|
|
|
- ASSERT(completion_done(&ip->i_flush));
|
|
|
- kmem_zone_free(xfs_inode_zone, ip);
|
|
|
+ xfs_inode_free(ip);
|
|
|
}
|
|
|
|
|
|
/*
|