···9595 struct xfs_perag *pag, int flags),9696 int flags,9797 int tag,9898- int exclusive)9898+ int exclusive,9999+ int *nr_to_scan)99100{100101 uint32_t first_index;101102 int last_error = 0;···135134 if (error == EFSCORRUPTED)136135 break;137136138138- } while (1);137137+ } while ((*nr_to_scan)--);139138140139 if (skipped) {141140 delay(1);···151150 struct xfs_perag *pag, int flags),152151 int flags,153152 int tag,154154- int exclusive)153153+ int exclusive,154154+ int *nr_to_scan)155155{156156 int error = 0;157157 int last_error = 0;158158 xfs_agnumber_t ag;159159+ int nr;159160161161+ nr = nr_to_scan ? *nr_to_scan : INT_MAX;160162 for (ag = 0; ag < mp->m_sb.sb_agcount; ag++) {161163 struct xfs_perag *pag;162164···169165 continue;170166 }171167 error = xfs_inode_ag_walk(mp, pag, execute, flags, tag,172172- exclusive);168168+ exclusive, &nr);173169 xfs_perag_put(pag);174170 if (error) {175171 last_error = error;176172 if (error == EFSCORRUPTED)177173 break;178174 }175175+ if (nr <= 0)176176+ break;179177 }178178+ if (nr_to_scan)179179+ *nr_to_scan = nr;180180 return XFS_ERROR(last_error);181181}182182···299291 ASSERT((flags & ~(SYNC_TRYLOCK|SYNC_WAIT)) == 0);300292301293 error = xfs_inode_ag_iterator(mp, xfs_sync_inode_data, flags,302302- XFS_ICI_NO_TAG, 0);294294+ XFS_ICI_NO_TAG, 0, NULL);303295 if (error)304296 return XFS_ERROR(error);305297···318310 ASSERT((flags & ~SYNC_WAIT) == 0);319311320312 return xfs_inode_ag_iterator(mp, xfs_sync_inode_attr, flags,321321- XFS_ICI_NO_TAG, 0);313313+ XFS_ICI_NO_TAG, 0, NULL);322314}323315324316STATIC int···681673 radix_tree_tag_set(&pag->pag_ici_root,682674 XFS_INO_TO_AGINO(ip->i_mount, ip->i_ino),683675 XFS_ICI_RECLAIM_TAG);676676+ pag->pag_ici_reclaimable++;684677}685678686679/*···714705{715706 radix_tree_tag_clear(&pag->pag_ici_root,716707 XFS_INO_TO_AGINO(mp, ip->i_ino), XFS_ICI_RECLAIM_TAG);708708+ pag->pag_ici_reclaimable--;717709}718710719711/*···864854 int mode)865855{866856 return xfs_inode_ag_iterator(mp, xfs_reclaim_inode, mode,867867- XFS_ICI_RECLAIM_TAG, 1);857857+ XFS_ICI_RECLAIM_TAG, 1, NULL);858858+}859859+860860+/*861861+ * Shrinker infrastructure.862862+ *863863+ * This is all far more complex than it needs to be. It adds a global list of864864+ * mounts because the shrinkers can only call a global context. We need to make865865+ * the shrinkers pass a context to avoid the need for global state.866866+ */867867+static LIST_HEAD(xfs_mount_list);868868+static struct rw_semaphore xfs_mount_list_lock;869869+870870+static int871871+xfs_reclaim_inode_shrink(872872+ int nr_to_scan,873873+ gfp_t gfp_mask)874874+{875875+ struct xfs_mount *mp;876876+ struct xfs_perag *pag;877877+ xfs_agnumber_t ag;878878+ int reclaimable = 0;879879+880880+ if (nr_to_scan) {881881+ if (!(gfp_mask & __GFP_FS))882882+ return -1;883883+884884+ down_read(&xfs_mount_list_lock);885885+ list_for_each_entry(mp, &xfs_mount_list, m_mplist) {886886+ xfs_inode_ag_iterator(mp, xfs_reclaim_inode, 0,887887+ XFS_ICI_RECLAIM_TAG, 1, &nr_to_scan);888888+ if (nr_to_scan <= 0)889889+ break;890890+ }891891+ up_read(&xfs_mount_list_lock);892892+ }893893+894894+ down_read(&xfs_mount_list_lock);895895+ list_for_each_entry(mp, &xfs_mount_list, m_mplist) {896896+ for (ag = 0; ag < mp->m_sb.sb_agcount; ag++) {897897+898898+ pag = xfs_perag_get(mp, ag);899899+ if (!pag->pag_ici_init) {900900+ xfs_perag_put(pag);901901+ continue;902902+ }903903+ reclaimable += pag->pag_ici_reclaimable;904904+ xfs_perag_put(pag);905905+ }906906+ }907907+ up_read(&xfs_mount_list_lock);908908+ return reclaimable;909909+}910910+911911+static struct shrinker xfs_inode_shrinker = {912912+ .shrink = xfs_reclaim_inode_shrink,913913+ .seeks = DEFAULT_SEEKS,914914+};915915+916916+void __init917917+xfs_inode_shrinker_init(void)918918+{919919+ init_rwsem(&xfs_mount_list_lock);920920+ register_shrinker(&xfs_inode_shrinker);921921+}922922+923923+void924924+xfs_inode_shrinker_destroy(void)925925+{926926+ ASSERT(list_empty(&xfs_mount_list));927927+ unregister_shrinker(&xfs_inode_shrinker);928928+}929929+930930+void931931+xfs_inode_shrinker_register(932932+ struct xfs_mount *mp)933933+{934934+ down_write(&xfs_mount_list_lock);935935+ list_add_tail(&mp->m_mplist, &xfs_mount_list);936936+ up_write(&xfs_mount_list_lock);937937+}938938+939939+void940940+xfs_inode_shrinker_unregister(941941+ struct xfs_mount *mp)942942+{943943+ down_write(&xfs_mount_list_lock);944944+ list_del(&mp->m_mplist);945945+ up_write(&xfs_mount_list_lock);868946}
+6-1
fs/xfs/linux-2.6/xfs_sync.h
···5353int xfs_sync_inode_valid(struct xfs_inode *ip, struct xfs_perag *pag);5454int xfs_inode_ag_iterator(struct xfs_mount *mp,5555 int (*execute)(struct xfs_inode *ip, struct xfs_perag *pag, int flags),5656- int flags, int tag, int write_lock);5656+ int flags, int tag, int write_lock, int *nr_to_scan);5757+5858+void xfs_inode_shrinker_init(void);5959+void xfs_inode_shrinker_destroy(void);6060+void xfs_inode_shrinker_register(struct xfs_mount *mp);6161+void xfs_inode_shrinker_unregister(struct xfs_mount *mp);57625863#endif
···223223 int pag_ici_init; /* incore inode cache initialised */224224 rwlock_t pag_ici_lock; /* incore inode lock */225225 struct radix_tree_root pag_ici_root; /* incore inode cache root */226226+ int pag_ici_reclaimable; /* reclaimable inodes */226227#endif227228 int pagb_count; /* pagb slots in use */228229 xfs_perag_busy_t pagb_list[XFS_PAGB_NUM_SLOTS]; /* unstable blocks */
+1
fs/xfs/xfs_mount.h
···259259 wait_queue_head_t m_wait_single_sync_task;260260 __int64_t m_update_flags; /* sb flags we need to update261261 on the next remount,rw */262262+ struct list_head m_mplist; /* inode shrinker mount list */262263} xfs_mount_t;263264264265/*