Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge branch 'for-linus' of git://oss.sgi.com/xfs/xfs

* 'for-linus' of git://oss.sgi.com/xfs/xfs:
xfs: add a shrinker to background inode reclaim

+120 -9
+5
fs/xfs/linux-2.6/xfs_super.c
··· 1209 1209 1210 1210 xfs_unmountfs(mp); 1211 1211 xfs_freesb(mp); 1212 + xfs_inode_shrinker_unregister(mp); 1212 1213 xfs_icsb_destroy_counters(mp); 1213 1214 xfs_close_devices(mp); 1214 1215 xfs_dmops_put(mp); ··· 1623 1622 if (error) 1624 1623 goto fail_vnrele; 1625 1624 1625 + xfs_inode_shrinker_register(mp); 1626 + 1626 1627 kfree(mtpt); 1627 1628 return 0; 1628 1629 ··· 1870 1867 goto out_cleanup_procfs; 1871 1868 1872 1869 vfs_initquota(); 1870 + xfs_inode_shrinker_init(); 1873 1871 1874 1872 error = register_filesystem(&xfs_fs_type); 1875 1873 if (error) ··· 1898 1894 { 1899 1895 vfs_exitquota(); 1900 1896 unregister_filesystem(&xfs_fs_type); 1897 + xfs_inode_shrinker_destroy(); 1901 1898 xfs_sysctl_unregister(); 1902 1899 xfs_cleanup_procfs(); 1903 1900 xfs_buf_terminate();
+105 -7
fs/xfs/linux-2.6/xfs_sync.c
··· 95 95 struct xfs_perag *pag, int flags), 96 96 int flags, 97 97 int tag, 98 - int exclusive) 98 + int exclusive, 99 + int *nr_to_scan) 99 100 { 100 101 uint32_t first_index; 101 102 int last_error = 0; ··· 135 134 if (error == EFSCORRUPTED) 136 135 break; 137 136 138 - } while (1); 137 + } while ((*nr_to_scan)--); 139 138 140 139 if (skipped) { 141 140 delay(1); ··· 151 150 struct xfs_perag *pag, int flags), 152 151 int flags, 153 152 int tag, 154 - int exclusive) 153 + int exclusive, 154 + int *nr_to_scan) 155 155 { 156 156 int error = 0; 157 157 int last_error = 0; 158 158 xfs_agnumber_t ag; 159 + int nr; 159 160 161 + nr = nr_to_scan ? *nr_to_scan : INT_MAX; 160 162 for (ag = 0; ag < mp->m_sb.sb_agcount; ag++) { 161 163 struct xfs_perag *pag; 162 164 ··· 169 165 continue; 170 166 } 171 167 error = xfs_inode_ag_walk(mp, pag, execute, flags, tag, 172 - exclusive); 168 + exclusive, &nr); 173 169 xfs_perag_put(pag); 174 170 if (error) { 175 171 last_error = error; 176 172 if (error == EFSCORRUPTED) 177 173 break; 178 174 } 175 + if (nr <= 0) 176 + break; 179 177 } 178 + if (nr_to_scan) 179 + *nr_to_scan = nr; 180 180 return XFS_ERROR(last_error); 181 181 } 182 182 ··· 299 291 ASSERT((flags & ~(SYNC_TRYLOCK|SYNC_WAIT)) == 0); 300 292 301 293 error = xfs_inode_ag_iterator(mp, xfs_sync_inode_data, flags, 302 - XFS_ICI_NO_TAG, 0); 294 + XFS_ICI_NO_TAG, 0, NULL); 303 295 if (error) 304 296 return XFS_ERROR(error); 305 297 ··· 318 310 ASSERT((flags & ~SYNC_WAIT) == 0); 319 311 320 312 return xfs_inode_ag_iterator(mp, xfs_sync_inode_attr, flags, 321 - XFS_ICI_NO_TAG, 0); 313 + XFS_ICI_NO_TAG, 0, NULL); 322 314 } 323 315 324 316 STATIC int ··· 681 673 radix_tree_tag_set(&pag->pag_ici_root, 682 674 XFS_INO_TO_AGINO(ip->i_mount, ip->i_ino), 683 675 XFS_ICI_RECLAIM_TAG); 676 + pag->pag_ici_reclaimable++; 684 677 } 685 678 686 679 /* ··· 714 705 { 715 706 radix_tree_tag_clear(&pag->pag_ici_root, 716 707 XFS_INO_TO_AGINO(mp, ip->i_ino), XFS_ICI_RECLAIM_TAG); 708 + pag->pag_ici_reclaimable--; 717 709 } 718 710 719 711 /* ··· 864 854 int mode) 865 855 { 866 856 return xfs_inode_ag_iterator(mp, xfs_reclaim_inode, mode, 867 - XFS_ICI_RECLAIM_TAG, 1); 857 + XFS_ICI_RECLAIM_TAG, 1, NULL); 858 + } 859 + 860 + /* 861 + * Shrinker infrastructure. 862 + * 863 + * This is all far more complex than it needs to be. It adds a global list of 864 + * mounts because the shrinkers can only call a global context. We need to make 865 + * the shrinkers pass a context to avoid the need for global state. 866 + */ 867 + static LIST_HEAD(xfs_mount_list); 868 + static struct rw_semaphore xfs_mount_list_lock; 869 + 870 + static int 871 + xfs_reclaim_inode_shrink( 872 + int nr_to_scan, 873 + gfp_t gfp_mask) 874 + { 875 + struct xfs_mount *mp; 876 + struct xfs_perag *pag; 877 + xfs_agnumber_t ag; 878 + int reclaimable = 0; 879 + 880 + if (nr_to_scan) { 881 + if (!(gfp_mask & __GFP_FS)) 882 + return -1; 883 + 884 + down_read(&xfs_mount_list_lock); 885 + list_for_each_entry(mp, &xfs_mount_list, m_mplist) { 886 + xfs_inode_ag_iterator(mp, xfs_reclaim_inode, 0, 887 + XFS_ICI_RECLAIM_TAG, 1, &nr_to_scan); 888 + if (nr_to_scan <= 0) 889 + break; 890 + } 891 + up_read(&xfs_mount_list_lock); 892 + } 893 + 894 + down_read(&xfs_mount_list_lock); 895 + list_for_each_entry(mp, &xfs_mount_list, m_mplist) { 896 + for (ag = 0; ag < mp->m_sb.sb_agcount; ag++) { 897 + 898 + pag = xfs_perag_get(mp, ag); 899 + if (!pag->pag_ici_init) { 900 + xfs_perag_put(pag); 901 + continue; 902 + } 903 + reclaimable += pag->pag_ici_reclaimable; 904 + xfs_perag_put(pag); 905 + } 906 + } 907 + up_read(&xfs_mount_list_lock); 908 + return reclaimable; 909 + } 910 + 911 + static struct shrinker xfs_inode_shrinker = { 912 + .shrink = xfs_reclaim_inode_shrink, 913 + .seeks = DEFAULT_SEEKS, 914 + }; 915 + 916 + void __init 917 + xfs_inode_shrinker_init(void) 918 + { 919 + init_rwsem(&xfs_mount_list_lock); 920 + register_shrinker(&xfs_inode_shrinker); 921 + } 922 + 923 + void 924 + xfs_inode_shrinker_destroy(void) 925 + { 926 + ASSERT(list_empty(&xfs_mount_list)); 927 + unregister_shrinker(&xfs_inode_shrinker); 928 + } 929 + 930 + void 931 + xfs_inode_shrinker_register( 932 + struct xfs_mount *mp) 933 + { 934 + down_write(&xfs_mount_list_lock); 935 + list_add_tail(&mp->m_mplist, &xfs_mount_list); 936 + up_write(&xfs_mount_list_lock); 937 + } 938 + 939 + void 940 + xfs_inode_shrinker_unregister( 941 + struct xfs_mount *mp) 942 + { 943 + down_write(&xfs_mount_list_lock); 944 + list_del(&mp->m_mplist); 945 + up_write(&xfs_mount_list_lock); 868 946 }
+6 -1
fs/xfs/linux-2.6/xfs_sync.h
··· 53 53 int xfs_sync_inode_valid(struct xfs_inode *ip, struct xfs_perag *pag); 54 54 int xfs_inode_ag_iterator(struct xfs_mount *mp, 55 55 int (*execute)(struct xfs_inode *ip, struct xfs_perag *pag, int flags), 56 - int flags, int tag, int write_lock); 56 + int flags, int tag, int write_lock, int *nr_to_scan); 57 + 58 + void xfs_inode_shrinker_init(void); 59 + void xfs_inode_shrinker_destroy(void); 60 + void xfs_inode_shrinker_register(struct xfs_mount *mp); 61 + void xfs_inode_shrinker_unregister(struct xfs_mount *mp); 57 62 58 63 #endif
+2 -1
fs/xfs/quota/xfs_qm_syscalls.c
··· 891 891 uint flags) 892 892 { 893 893 ASSERT(mp->m_quotainfo); 894 - xfs_inode_ag_iterator(mp, xfs_dqrele_inode, flags, XFS_ICI_NO_TAG, 0); 894 + xfs_inode_ag_iterator(mp, xfs_dqrele_inode, flags, 895 + XFS_ICI_NO_TAG, 0, NULL); 895 896 } 896 897 897 898 /*------------------------------------------------------------------------*/
+1
fs/xfs/xfs_ag.h
··· 223 223 int pag_ici_init; /* incore inode cache initialised */ 224 224 rwlock_t pag_ici_lock; /* incore inode lock */ 225 225 struct radix_tree_root pag_ici_root; /* incore inode cache root */ 226 + int pag_ici_reclaimable; /* reclaimable inodes */ 226 227 #endif 227 228 int pagb_count; /* pagb slots in use */ 228 229 xfs_perag_busy_t pagb_list[XFS_PAGB_NUM_SLOTS]; /* unstable blocks */
+1
fs/xfs/xfs_mount.h
··· 259 259 wait_queue_head_t m_wait_single_sync_task; 260 260 __int64_t m_update_flags; /* sb flags we need to update 261 261 on the next remount,rw */ 262 + struct list_head m_mplist; /* inode shrinker mount list */ 262 263 } xfs_mount_t; 263 264 264 265 /*