|
@@ -368,6 +368,11 @@ xfs_iget_cache_hit(
|
|
|
if (ip->i_flags & XFS_IRECLAIMABLE) {
|
|
|
trace_xfs_iget_reclaim(ip);
|
|
|
|
|
|
+ if (flags & XFS_IGET_INCORE) {
|
|
|
+ error = -EAGAIN;
|
|
|
+ goto out_error;
|
|
|
+ }
|
|
|
+
|
|
|
/*
|
|
|
* We need to set XFS_IRECLAIM to prevent xfs_reclaim_inode
|
|
|
* from stomping over us while we recycle the inode. We can't
|
|
@@ -432,7 +437,8 @@ xfs_iget_cache_hit(
|
|
|
if (lock_flags != 0)
|
|
|
xfs_ilock(ip, lock_flags);
|
|
|
|
|
|
- xfs_iflags_clear(ip, XFS_ISTALE | XFS_IDONTCACHE);
|
|
|
+ if (!(flags & XFS_IGET_INCORE))
|
|
|
+ xfs_iflags_clear(ip, XFS_ISTALE | XFS_IDONTCACHE);
|
|
|
XFS_STATS_INC(mp, xs_ig_found);
|
|
|
|
|
|
return 0;
|
|
@@ -603,6 +609,10 @@ again:
|
|
|
goto out_error_or_again;
|
|
|
} else {
|
|
|
rcu_read_unlock();
|
|
|
+ if (flags & XFS_IGET_INCORE) {
|
|
|
+ error = -ENOENT;
|
|
|
+ goto out_error_or_again;
|
|
|
+ }
|
|
|
XFS_STATS_INC(mp, xs_ig_missed);
|
|
|
|
|
|
error = xfs_iget_cache_miss(mp, pag, tp, ino, &ip,
|
|
@@ -623,7 +633,7 @@ again:
|
|
|
return 0;
|
|
|
|
|
|
out_error_or_again:
|
|
|
- if (error == -EAGAIN) {
|
|
|
+ if (!(flags & XFS_IGET_INCORE) && error == -EAGAIN) {
|
|
|
delay(1);
|
|
|
goto again;
|
|
|
}
|
|
@@ -631,6 +641,44 @@ out_error_or_again:
|
|
|
return error;
|
|
|
}
|
|
|
|
|
|
+/*
|
|
|
+ * "Is this a cached inode that's also allocated?"
|
|
|
+ *
|
|
|
+ * Look up an inode by number in the given file system. If the inode is
|
|
|
+ * in cache and isn't in purgatory, return 1 if the inode is allocated
|
|
|
+ * and 0 if it is not. For all other cases (not in cache, being torn
|
|
|
+ * down, etc.), return a negative error code.
|
|
|
+ *
|
|
|
+ * The caller has to prevent inode allocation and freeing activity,
|
|
|
+ * presumably by locking the AGI buffer. This is to ensure that an
|
|
|
+ * inode cannot transition from allocated to freed until the caller is
|
|
|
+ * ready to allow that. If the inode is in an intermediate state (new,
|
|
|
+ * reclaimable, or being reclaimed), -EAGAIN will be returned; if the
|
|
|
+ * inode is not in the cache, -ENOENT will be returned. The caller must
|
|
|
+ * deal with these scenarios appropriately.
|
|
|
+ *
|
|
|
+ * This is a specialized use case for the online scrubber; if you're
|
|
|
+ * reading this, you probably want xfs_iget.
|
|
|
+ */
|
|
|
+int
|
|
|
+xfs_icache_inode_is_allocated(
|
|
|
+ struct xfs_mount *mp,
|
|
|
+ struct xfs_trans *tp,
|
|
|
+ xfs_ino_t ino,
|
|
|
+ bool *inuse)
|
|
|
+{
|
|
|
+ struct xfs_inode *ip;
|
|
|
+ int error;
|
|
|
+
|
|
|
+ error = xfs_iget(mp, tp, ino, XFS_IGET_INCORE, 0, &ip);
|
|
|
+ if (error)
|
|
|
+ return error;
|
|
|
+
|
|
|
+ *inuse = !!(VFS_I(ip)->i_mode);
|
|
|
+ IRELE(ip);
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
/*
|
|
|
* The inode lookup is done in batches to keep the amount of lock traffic and
|
|
|
* radix tree lookups to a minimum. The batch size is a trade off between
|