aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArtem Bityutskiy <Artem.Bityutskiy@nokia.com>2011-04-27 07:52:35 -0400
committerArtem Bityutskiy <Artem.Bityutskiy@nokia.com>2011-05-13 12:23:56 -0400
commit447442139c764fd75cf892905d0feb08a9b983ed (patch)
tree2a3f547c28d5e28b25ce54980539e09eff6d6375
parentec0681426526b23d3e12cf247d64676806c30b7f (diff)
UBIFS: split ubifs_rcvry_gc_commit
Split the 'ubifs_rcvry_gc_commit()' function and introduce a 'grab_empty_leb()' heler. This cleans 'ubifs_rcvry_gc_commit()' a little and makes it a bit less of spagetti. Also, add a commentary which explains why it is crucial to first search for an empty LEB and then run commit. Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy@nokia.com>
-rw-r--r--fs/ubifs/recovery.c77
1 files changed, 50 insertions, 27 deletions
diff --git a/fs/ubifs/recovery.c b/fs/ubifs/recovery.c
index 3d2598deaa58..11776ae8caf6 100644
--- a/fs/ubifs/recovery.c
+++ b/fs/ubifs/recovery.c
@@ -1070,6 +1070,53 @@ int ubifs_clean_lebs(const struct ubifs_info *c, void *sbuf)
1070} 1070}
1071 1071
1072/** 1072/**
1073 * grab_empty_leb - grab an empty LEB to use as GC LEB and run commit.
1074 * @c: UBIFS file-system description object
1075 *
1076 * This is a helper function for 'ubifs_rcvry_gc_commit()' which grabs an empty
1077 * LEB to be used as GC LEB (@c->gc_lnum), and then runs the commit. Returns
1078 * zero in case of success and a negative error code in case of failure.
1079 */
1080static int grab_empty_leb(struct ubifs_info *c)
1081{
1082 int lnum, err;
1083
1084 /*
1085 * Note, it is very important to first search for an empty LEB and then
1086 * run the commit, not vice-versa. The reason is that there might be
1087 * only one empty LEB at the moment, the one which has been the
1088 * @c->gc_lnum just before the power cut happened. During the regular
1089 * UBIFS operation (not now) @c->gc_lnum is marked as "taken", so no
1090 * one but GC can grab it. But at this moment this single empty LEB is
1091 * not marked as taken, so if we run commit - what happens? Right, the
1092 * commit will grab it and write the index there. Remember that the
1093 * index always expands as long as there is free space, and it only
1094 * starts consolidating when we run out of space.
1095 *
1096 * IOW, if we run commit now, we might not be able to find a free LEB
1097 * after this.
1098 */
1099 lnum = ubifs_find_free_leb_for_idx(c);
1100 if (lnum < 0) {
1101 dbg_err("could not find an empty LEB");
1102 dbg_dump_lprops(c);
1103 dbg_dump_budg(c, &c->bi);
1104 return lnum;
1105 }
1106
1107 /* Reset the index flag */
1108 err = ubifs_change_one_lp(c, lnum, LPROPS_NC, LPROPS_NC, 0,
1109 LPROPS_INDEX, 0);
1110 if (err)
1111 return err;
1112
1113 c->gc_lnum = lnum;
1114 dbg_rcvry("found empty LEB %d, run commit", lnum);
1115
1116 return ubifs_run_commit(c);
1117}
1118
1119/**
1073 * ubifs_rcvry_gc_commit - recover the GC LEB number and run the commit. 1120 * ubifs_rcvry_gc_commit - recover the GC LEB number and run the commit.
1074 * @c: UBIFS file-system description object 1121 * @c: UBIFS file-system description object
1075 * 1122 *
@@ -1096,7 +1143,7 @@ int ubifs_rcvry_gc_commit(struct ubifs_info *c)
1096 c->gc_lnum = -1; 1143 c->gc_lnum = -1;
1097 if (wbuf->lnum == -1) { 1144 if (wbuf->lnum == -1) {
1098 dbg_rcvry("no GC head LEB"); 1145 dbg_rcvry("no GC head LEB");
1099 goto find_free; 1146 return grab_empty_leb(c);
1100 } 1147 }
1101 /* 1148 /*
1102 * See whether the used space in the dirtiest LEB fits in the GC head 1149 * See whether the used space in the dirtiest LEB fits in the GC head
@@ -1104,7 +1151,7 @@ int ubifs_rcvry_gc_commit(struct ubifs_info *c)
1104 */ 1151 */
1105 if (wbuf->offs == c->leb_size) { 1152 if (wbuf->offs == c->leb_size) {
1106 dbg_rcvry("no room in GC head LEB"); 1153 dbg_rcvry("no room in GC head LEB");
1107 goto find_free; 1154 return grab_empty_leb(c);
1108 } 1155 }
1109 err = ubifs_find_dirty_leb(c, &lp, wbuf->offs, 2); 1156 err = ubifs_find_dirty_leb(c, &lp, wbuf->offs, 2);
1110 if (err) { 1157 if (err) {
@@ -1121,7 +1168,7 @@ int ubifs_rcvry_gc_commit(struct ubifs_info *c)
1121 */ 1168 */
1122 if (err == -ENOSPC) { 1169 if (err == -ENOSPC) {
1123 dbg_rcvry("could not find a dirty LEB"); 1170 dbg_rcvry("could not find a dirty LEB");
1124 goto find_free; 1171 return grab_empty_leb(c);
1125 } 1172 }
1126 return err; 1173 return err;
1127 } 1174 }
@@ -1167,30 +1214,6 @@ int ubifs_rcvry_gc_commit(struct ubifs_info *c)
1167 return err; 1214 return err;
1168 dbg_rcvry("allocated LEB %d for GC", lnum); 1215 dbg_rcvry("allocated LEB %d for GC", lnum);
1169 return 0; 1216 return 0;
1170
1171find_free:
1172 /*
1173 * There is no GC head LEB or the free space in the GC head LEB is too
1174 * small, or there are not dirty LEBs. Allocate gc_lnum by calling
1175 * 'ubifs_find_free_leb_for_idx()' so GC is not run.
1176 */
1177 lnum = ubifs_find_free_leb_for_idx(c);
1178 if (lnum < 0) {
1179 dbg_err("could not find an empty LEB");
1180 dbg_dump_lprops(c);
1181 dbg_dump_budg(c, &c->bi);
1182 return lnum;
1183 }
1184 /* And reset the index flag */
1185 err = ubifs_change_one_lp(c, lnum, LPROPS_NC, LPROPS_NC, 0,
1186 LPROPS_INDEX, 0);
1187 if (err)
1188 return err;
1189 c->gc_lnum = lnum;
1190 dbg_rcvry("allocated LEB %d for GC", lnum);
1191 /* Run the commit */
1192 dbg_rcvry("committing");
1193 return ubifs_run_commit(c);
1194} 1217}
1195 1218
1196/** 1219/**