STATIC int xfs_reclaim_inode_grab( struct xfs_inode *ip, int flags) { ASSERT(rcu_read_lock_held()); if (!ip->i_ino) return 1; if ((flags & SYNC_TRYLOCK) && __xfs_iflags_test(ip, XFS_IFLOCK | XFS_IRECLAIM)) return 1; spin_lock(&ip->i_flags_lock); if (!__xfs_iflags_test(ip, XFS_IRECLAIMABLE) || __xfs_iflags_test(ip, XFS_IRECLAIM)) { spin_unlock(&ip->i_flags_lock); return 1; } __xfs_iflags_set(ip, XFS_IRECLAIM); spin_unlock(&ip->i_flags_lock); return 0; }
void xfs_inode_set_reclaim_tag( xfs_inode_t *ip) { struct xfs_mount *mp = ip->i_mount; struct xfs_perag *pag; pag = xfs_perag_get(mp, XFS_INO_TO_AGNO(mp, ip->i_ino)); spin_lock(&pag->pag_ici_lock); spin_lock(&ip->i_flags_lock); __xfs_inode_set_reclaim_tag(pag, ip); __xfs_iflags_set(ip, XFS_IRECLAIMABLE); spin_unlock(&ip->i_flags_lock); spin_unlock(&pag->pag_ici_lock); xfs_perag_put(pag); }
/* * Grab the inode for reclaim exclusively. * Return 0 if we grabbed it, non-zero otherwise. */ STATIC int xfs_reclaim_inode_grab( struct xfs_inode *ip, int flags) { ASSERT(rcu_read_lock_held()); /* quick check for stale RCU freed inode */ if (!ip->i_ino) return 1; /* * do some unlocked checks first to avoid unnecessary lock traffic. * The first is a flush lock check, the second is a already in reclaim * check. Only do these checks if we are not going to block on locks. */ if ((flags & SYNC_TRYLOCK) && (!ip->i_flush.done || __xfs_iflags_test(ip, XFS_IRECLAIM))) { return 1; } /* * The radix tree lock here protects a thread in xfs_iget from racing * with us starting reclaim on the inode. Once we have the * XFS_IRECLAIM flag set it will not touch us. * * Due to RCU lookup, we may find inodes that have been freed and only * have XFS_IRECLAIM set. Indeed, we may see reallocated inodes that * aren't candidates for reclaim at all, so we must check the * XFS_IRECLAIMABLE is set first before proceeding to reclaim. */ spin_lock(&ip->i_flags_lock); if (!__xfs_iflags_test(ip, XFS_IRECLAIMABLE) || __xfs_iflags_test(ip, XFS_IRECLAIM)) { /* not a reclaim candidate. */ spin_unlock(&ip->i_flags_lock); return 1; } __xfs_iflags_set(ip, XFS_IRECLAIM); spin_unlock(&ip->i_flags_lock); return 0; }
/* * We set the inode flag atomically with the radix tree tag. * Once we get tag lookups on the radix tree, this inode flag * can go away. */ void xfs_inode_set_reclaim_tag( struct xfs_inode *ip) { struct xfs_mount *mp = ip->i_mount; struct xfs_perag *pag; pag = xfs_perag_get(mp, XFS_INO_TO_AGNO(mp, ip->i_ino)); spin_lock(&pag->pag_ici_lock); spin_lock(&ip->i_flags_lock); radix_tree_tag_set(&pag->pag_ici_root, XFS_INO_TO_AGINO(mp, ip->i_ino), XFS_ICI_RECLAIM_TAG); xfs_perag_set_reclaim_tag(pag); __xfs_iflags_set(ip, XFS_IRECLAIMABLE); spin_unlock(&ip->i_flags_lock); spin_unlock(&pag->pag_ici_lock); xfs_perag_put(pag); }
/* * Grab the inode for reclaim exclusively. * Return 0 if we grabbed it, non-zero otherwise. */ STATIC int xfs_reclaim_inode_grab( struct xfs_inode *ip, int flags) { ASSERT(rcu_read_lock_held()); /* quick check for stale RCU freed inode */ if (!ip->i_ino) return 1; /* * If we are asked for non-blocking operation, do unlocked checks to * see if the inode already is being flushed or in reclaim to avoid * lock traffic. */ if ((flags & SYNC_TRYLOCK) && __xfs_iflags_test(ip, XFS_IFLOCK | XFS_IRECLAIM)) return 1; /* * The radix tree lock here protects a thread in xfs_iget from racing * with us starting reclaim on the inode. Once we have the * XFS_IRECLAIM flag set it will not touch us. * * Due to RCU lookup, we may find inodes that have been freed and only * have XFS_IRECLAIM set. Indeed, we may see reallocated inodes that * aren't candidates for reclaim at all, so we must check the * XFS_IRECLAIMABLE is set first before proceeding to reclaim. */ spin_lock(&ip->i_flags_lock); if (!__xfs_iflags_test(ip, XFS_IRECLAIMABLE) || __xfs_iflags_test(ip, XFS_IRECLAIM)) { /* not a reclaim candidate. */ spin_unlock(&ip->i_flags_lock); return 1; } __xfs_iflags_set(ip, XFS_IRECLAIM); spin_unlock(&ip->i_flags_lock); return 0; }