diff options
author | Steven Whitehouse <swhiteho@redhat.com> | 2008-07-10 10:54:12 -0400 |
---|---|---|
committer | Steven Whitehouse <swhiteho@redhat.com> | 2008-07-10 10:54:12 -0400 |
commit | 9cabcdbd4638cf884839ee4cd15780800c223b90 (patch) | |
tree | 7f5c4aa81a919fde33e33e5d8df04e053f99b93b /fs/gfs2 | |
parent | 209806aba9d540dde3db0a5ce72307f85f33468f (diff) |
[GFS2] Replace rgrp "recent list" with mru list
This patch removes the "recent list" which is used during allocation
and replaces it with the (already existing) mru list used during
deletion. The "recent list" was not a true mru list leading to a number
of inefficiencies including a "next" function which made scanning the
list an order N^2 operation wrt to the number of list elements.
This should increase allocation performance with large numbers of rgrps.
Its also a useful preparation and cleanup before some further changes
which are planned in this area.
Signed-off-by: Steven Whitehouse <swhiteho@redhat.com>
Diffstat (limited to 'fs/gfs2')
-rw-r--r-- | fs/gfs2/incore.h | 2 | ||||
-rw-r--r-- | fs/gfs2/ops_fstype.c | 1 | ||||
-rw-r--r-- | fs/gfs2/rgrp.c | 108 |
3 files changed, 12 insertions, 99 deletions
diff --git a/fs/gfs2/incore.h b/fs/gfs2/incore.h index 4b734c6e34f0..4ab3c3a4a96f 100644 --- a/fs/gfs2/incore.h +++ b/fs/gfs2/incore.h | |||
@@ -77,7 +77,6 @@ struct gfs2_rgrp_host { | |||
77 | struct gfs2_rgrpd { | 77 | struct gfs2_rgrpd { |
78 | struct list_head rd_list; /* Link with superblock */ | 78 | struct list_head rd_list; /* Link with superblock */ |
79 | struct list_head rd_list_mru; | 79 | struct list_head rd_list_mru; |
80 | struct list_head rd_recent; /* Recently used rgrps */ | ||
81 | struct gfs2_glock *rd_gl; /* Glock for this rgrp */ | 80 | struct gfs2_glock *rd_gl; /* Glock for this rgrp */ |
82 | u64 rd_addr; /* grp block disk address */ | 81 | u64 rd_addr; /* grp block disk address */ |
83 | u64 rd_data0; /* first data location */ | 82 | u64 rd_data0; /* first data location */ |
@@ -529,7 +528,6 @@ struct gfs2_sbd { | |||
529 | struct mutex sd_rindex_mutex; | 528 | struct mutex sd_rindex_mutex; |
530 | struct list_head sd_rindex_list; | 529 | struct list_head sd_rindex_list; |
531 | struct list_head sd_rindex_mru_list; | 530 | struct list_head sd_rindex_mru_list; |
532 | struct list_head sd_rindex_recent_list; | ||
533 | struct gfs2_rgrpd *sd_rindex_forward; | 531 | struct gfs2_rgrpd *sd_rindex_forward; |
534 | unsigned int sd_rgrps; | 532 | unsigned int sd_rgrps; |
535 | 533 | ||
diff --git a/fs/gfs2/ops_fstype.c b/fs/gfs2/ops_fstype.c index 6ba69dd1a729..b4d1d6490633 100644 --- a/fs/gfs2/ops_fstype.c +++ b/fs/gfs2/ops_fstype.c | |||
@@ -64,7 +64,6 @@ static struct gfs2_sbd *init_sbd(struct super_block *sb) | |||
64 | mutex_init(&sdp->sd_rindex_mutex); | 64 | mutex_init(&sdp->sd_rindex_mutex); |
65 | INIT_LIST_HEAD(&sdp->sd_rindex_list); | 65 | INIT_LIST_HEAD(&sdp->sd_rindex_list); |
66 | INIT_LIST_HEAD(&sdp->sd_rindex_mru_list); | 66 | INIT_LIST_HEAD(&sdp->sd_rindex_mru_list); |
67 | INIT_LIST_HEAD(&sdp->sd_rindex_recent_list); | ||
68 | 67 | ||
69 | INIT_LIST_HEAD(&sdp->sd_jindex_list); | 68 | INIT_LIST_HEAD(&sdp->sd_jindex_list); |
70 | spin_lock_init(&sdp->sd_jindex_spin); | 69 | spin_lock_init(&sdp->sd_jindex_spin); |
diff --git a/fs/gfs2/rgrp.c b/fs/gfs2/rgrp.c index 3401628d742b..2d90fb253505 100644 --- a/fs/gfs2/rgrp.c +++ b/fs/gfs2/rgrp.c | |||
@@ -371,11 +371,6 @@ static void clear_rgrpdi(struct gfs2_sbd *sdp) | |||
371 | 371 | ||
372 | spin_lock(&sdp->sd_rindex_spin); | 372 | spin_lock(&sdp->sd_rindex_spin); |
373 | sdp->sd_rindex_forward = NULL; | 373 | sdp->sd_rindex_forward = NULL; |
374 | head = &sdp->sd_rindex_recent_list; | ||
375 | while (!list_empty(head)) { | ||
376 | rgd = list_entry(head->next, struct gfs2_rgrpd, rd_recent); | ||
377 | list_del(&rgd->rd_recent); | ||
378 | } | ||
379 | spin_unlock(&sdp->sd_rindex_spin); | 374 | spin_unlock(&sdp->sd_rindex_spin); |
380 | 375 | ||
381 | head = &sdp->sd_rindex_list; | 376 | head = &sdp->sd_rindex_list; |
@@ -945,107 +940,30 @@ static struct inode *try_rgrp_unlink(struct gfs2_rgrpd *rgd, u64 *last_unlinked) | |||
945 | } | 940 | } |
946 | 941 | ||
947 | /** | 942 | /** |
948 | * recent_rgrp_first - get first RG from "recent" list | ||
949 | * @sdp: The GFS2 superblock | ||
950 | * @rglast: address of the rgrp used last | ||
951 | * | ||
952 | * Returns: The first rgrp in the recent list | ||
953 | */ | ||
954 | |||
955 | static struct gfs2_rgrpd *recent_rgrp_first(struct gfs2_sbd *sdp, | ||
956 | u64 rglast) | ||
957 | { | ||
958 | struct gfs2_rgrpd *rgd; | ||
959 | |||
960 | spin_lock(&sdp->sd_rindex_spin); | ||
961 | |||
962 | if (rglast) { | ||
963 | list_for_each_entry(rgd, &sdp->sd_rindex_recent_list, rd_recent) { | ||
964 | if (rgrp_contains_block(rgd, rglast)) | ||
965 | goto out; | ||
966 | } | ||
967 | } | ||
968 | rgd = NULL; | ||
969 | if (!list_empty(&sdp->sd_rindex_recent_list)) | ||
970 | rgd = list_entry(sdp->sd_rindex_recent_list.next, | ||
971 | struct gfs2_rgrpd, rd_recent); | ||
972 | out: | ||
973 | spin_unlock(&sdp->sd_rindex_spin); | ||
974 | return rgd; | ||
975 | } | ||
976 | |||
977 | /** | ||
978 | * recent_rgrp_next - get next RG from "recent" list | 943 | * recent_rgrp_next - get next RG from "recent" list |
979 | * @cur_rgd: current rgrp | 944 | * @cur_rgd: current rgrp |
980 | * @remove: | ||
981 | * | 945 | * |
982 | * Returns: The next rgrp in the recent list | 946 | * Returns: The next rgrp in the recent list |
983 | */ | 947 | */ |
984 | 948 | ||
985 | static struct gfs2_rgrpd *recent_rgrp_next(struct gfs2_rgrpd *cur_rgd, | 949 | static struct gfs2_rgrpd *recent_rgrp_next(struct gfs2_rgrpd *cur_rgd) |
986 | int remove) | ||
987 | { | 950 | { |
988 | struct gfs2_sbd *sdp = cur_rgd->rd_sbd; | 951 | struct gfs2_sbd *sdp = cur_rgd->rd_sbd; |
989 | struct list_head *head; | 952 | struct list_head *head; |
990 | struct gfs2_rgrpd *rgd; | 953 | struct gfs2_rgrpd *rgd; |
991 | 954 | ||
992 | spin_lock(&sdp->sd_rindex_spin); | 955 | spin_lock(&sdp->sd_rindex_spin); |
993 | 956 | head = &sdp->sd_rindex_mru_list; | |
994 | head = &sdp->sd_rindex_recent_list; | 957 | if (unlikely(cur_rgd->rd_list_mru.next == head)) { |
995 | 958 | spin_unlock(&sdp->sd_rindex_spin); | |
996 | list_for_each_entry(rgd, head, rd_recent) { | 959 | return NULL; |
997 | if (rgd == cur_rgd) { | ||
998 | if (cur_rgd->rd_recent.next != head) | ||
999 | rgd = list_entry(cur_rgd->rd_recent.next, | ||
1000 | struct gfs2_rgrpd, rd_recent); | ||
1001 | else | ||
1002 | rgd = NULL; | ||
1003 | |||
1004 | if (remove) | ||
1005 | list_del(&cur_rgd->rd_recent); | ||
1006 | |||
1007 | goto out; | ||
1008 | } | ||
1009 | } | 960 | } |
1010 | 961 | rgd = list_entry(cur_rgd->rd_list_mru.next, struct gfs2_rgrpd, rd_list_mru); | |
1011 | rgd = NULL; | ||
1012 | if (!list_empty(head)) | ||
1013 | rgd = list_entry(head->next, struct gfs2_rgrpd, rd_recent); | ||
1014 | |||
1015 | out: | ||
1016 | spin_unlock(&sdp->sd_rindex_spin); | 962 | spin_unlock(&sdp->sd_rindex_spin); |
1017 | return rgd; | 963 | return rgd; |
1018 | } | 964 | } |
1019 | 965 | ||
1020 | /** | 966 | /** |
1021 | * recent_rgrp_add - add an RG to tail of "recent" list | ||
1022 | * @new_rgd: The rgrp to add | ||
1023 | * | ||
1024 | */ | ||
1025 | |||
1026 | static void recent_rgrp_add(struct gfs2_rgrpd *new_rgd) | ||
1027 | { | ||
1028 | struct gfs2_sbd *sdp = new_rgd->rd_sbd; | ||
1029 | struct gfs2_rgrpd *rgd; | ||
1030 | unsigned int count = 0; | ||
1031 | unsigned int max = sdp->sd_rgrps / gfs2_jindex_size(sdp); | ||
1032 | |||
1033 | spin_lock(&sdp->sd_rindex_spin); | ||
1034 | |||
1035 | list_for_each_entry(rgd, &sdp->sd_rindex_recent_list, rd_recent) { | ||
1036 | if (rgd == new_rgd) | ||
1037 | goto out; | ||
1038 | |||
1039 | if (++count >= max) | ||
1040 | goto out; | ||
1041 | } | ||
1042 | list_add_tail(&new_rgd->rd_recent, &sdp->sd_rindex_recent_list); | ||
1043 | |||
1044 | out: | ||
1045 | spin_unlock(&sdp->sd_rindex_spin); | ||
1046 | } | ||
1047 | |||
1048 | /** | ||
1049 | * forward_rgrp_get - get an rgrp to try next from full list | 967 | * forward_rgrp_get - get an rgrp to try next from full list |
1050 | * @sdp: The GFS2 superblock | 968 | * @sdp: The GFS2 superblock |
1051 | * | 969 | * |
@@ -1112,9 +1030,7 @@ static struct inode *get_local_rgrp(struct gfs2_inode *ip, u64 *last_unlinked) | |||
1112 | int loops = 0; | 1030 | int loops = 0; |
1113 | int error, rg_locked; | 1031 | int error, rg_locked; |
1114 | 1032 | ||
1115 | /* Try recently successful rgrps */ | 1033 | rgd = gfs2_blk2rgrpd(sdp, ip->i_goal); |
1116 | |||
1117 | rgd = recent_rgrp_first(sdp, ip->i_goal); | ||
1118 | 1034 | ||
1119 | while (rgd) { | 1035 | while (rgd) { |
1120 | rg_locked = 0; | 1036 | rg_locked = 0; |
@@ -1136,11 +1052,9 @@ static struct inode *get_local_rgrp(struct gfs2_inode *ip, u64 *last_unlinked) | |||
1136 | gfs2_glock_dq_uninit(&al->al_rgd_gh); | 1052 | gfs2_glock_dq_uninit(&al->al_rgd_gh); |
1137 | if (inode) | 1053 | if (inode) |
1138 | return inode; | 1054 | return inode; |
1139 | rgd = recent_rgrp_next(rgd, 1); | 1055 | /* fall through */ |
1140 | break; | ||
1141 | |||
1142 | case GLR_TRYFAILED: | 1056 | case GLR_TRYFAILED: |
1143 | rgd = recent_rgrp_next(rgd, 0); | 1057 | rgd = recent_rgrp_next(rgd); |
1144 | break; | 1058 | break; |
1145 | 1059 | ||
1146 | default: | 1060 | default: |
@@ -1199,7 +1113,9 @@ static struct inode *get_local_rgrp(struct gfs2_inode *ip, u64 *last_unlinked) | |||
1199 | 1113 | ||
1200 | out: | 1114 | out: |
1201 | if (begin) { | 1115 | if (begin) { |
1202 | recent_rgrp_add(rgd); | 1116 | spin_lock(&sdp->sd_rindex_spin); |
1117 | list_move(&rgd->rd_list_mru, &sdp->sd_rindex_mru_list); | ||
1118 | spin_unlock(&sdp->sd_rindex_spin); | ||
1203 | rgd = gfs2_rgrpd_get_next(rgd); | 1119 | rgd = gfs2_rgrpd_get_next(rgd); |
1204 | if (!rgd) | 1120 | if (!rgd) |
1205 | rgd = gfs2_rgrpd_get_first(sdp); | 1121 | rgd = gfs2_rgrpd_get_first(sdp); |