hc
2024-02-20 102a0743326a03cd1a1202ceda21e175b7d3575c
kernel/fs/ubifs/tnc.c
....@@ -44,6 +44,33 @@
4444 NOT_ON_MEDIA = 3,
4545 };
4646
47
+static void do_insert_old_idx(struct ubifs_info *c,
48
+ struct ubifs_old_idx *old_idx)
49
+{
50
+ struct ubifs_old_idx *o;
51
+ struct rb_node **p, *parent = NULL;
52
+
53
+ p = &c->old_idx.rb_node;
54
+ while (*p) {
55
+ parent = *p;
56
+ o = rb_entry(parent, struct ubifs_old_idx, rb);
57
+ if (old_idx->lnum < o->lnum)
58
+ p = &(*p)->rb_left;
59
+ else if (old_idx->lnum > o->lnum)
60
+ p = &(*p)->rb_right;
61
+ else if (old_idx->offs < o->offs)
62
+ p = &(*p)->rb_left;
63
+ else if (old_idx->offs > o->offs)
64
+ p = &(*p)->rb_right;
65
+ else {
66
+ ubifs_err(c, "old idx added twice!");
67
+ kfree(old_idx);
68
+ }
69
+ }
70
+ rb_link_node(&old_idx->rb, parent, p);
71
+ rb_insert_color(&old_idx->rb, &c->old_idx);
72
+}
73
+
4774 /**
4875 * insert_old_idx - record an index node obsoleted since the last commit start.
4976 * @c: UBIFS file-system description object
....@@ -69,35 +96,15 @@
6996 */
7097 static int insert_old_idx(struct ubifs_info *c, int lnum, int offs)
7198 {
72
- struct ubifs_old_idx *old_idx, *o;
73
- struct rb_node **p, *parent = NULL;
99
+ struct ubifs_old_idx *old_idx;
74100
75101 old_idx = kmalloc(sizeof(struct ubifs_old_idx), GFP_NOFS);
76102 if (unlikely(!old_idx))
77103 return -ENOMEM;
78104 old_idx->lnum = lnum;
79105 old_idx->offs = offs;
106
+ do_insert_old_idx(c, old_idx);
80107
81
- p = &c->old_idx.rb_node;
82
- while (*p) {
83
- parent = *p;
84
- o = rb_entry(parent, struct ubifs_old_idx, rb);
85
- if (lnum < o->lnum)
86
- p = &(*p)->rb_left;
87
- else if (lnum > o->lnum)
88
- p = &(*p)->rb_right;
89
- else if (offs < o->offs)
90
- p = &(*p)->rb_left;
91
- else if (offs > o->offs)
92
- p = &(*p)->rb_right;
93
- else {
94
- ubifs_err(c, "old idx added twice!");
95
- kfree(old_idx);
96
- return 0;
97
- }
98
- }
99
- rb_link_node(&old_idx->rb, parent, p);
100
- rb_insert_color(&old_idx->rb, &c->old_idx);
101108 return 0;
102109 }
103110
....@@ -199,23 +206,6 @@
199206 __set_bit(DIRTY_ZNODE, &zn->flags);
200207 __clear_bit(COW_ZNODE, &zn->flags);
201208
202
- ubifs_assert(c, !ubifs_zn_obsolete(znode));
203
- __set_bit(OBSOLETE_ZNODE, &znode->flags);
204
-
205
- if (znode->level != 0) {
206
- int i;
207
- const int n = zn->child_cnt;
208
-
209
- /* The children now have new parent */
210
- for (i = 0; i < n; i++) {
211
- struct ubifs_zbranch *zbr = &zn->zbranch[i];
212
-
213
- if (zbr->znode)
214
- zbr->znode->parent = zn;
215
- }
216
- }
217
-
218
- atomic_long_inc(&c->dirty_zn_cnt);
219209 return zn;
220210 }
221211
....@@ -231,6 +221,42 @@
231221 {
232222 c->calc_idx_sz -= ALIGN(dirt, 8);
233223 return ubifs_add_dirt(c, lnum, dirt);
224
+}
225
+
226
+/**
227
+ * replace_znode - replace old znode with new znode.
228
+ * @c: UBIFS file-system description object
229
+ * @new_zn: new znode
230
+ * @old_zn: old znode
231
+ * @zbr: the branch of parent znode
232
+ *
233
+ * Replace old znode with new znode in TNC.
234
+ */
235
+static void replace_znode(struct ubifs_info *c, struct ubifs_znode *new_zn,
236
+ struct ubifs_znode *old_zn, struct ubifs_zbranch *zbr)
237
+{
238
+ ubifs_assert(c, !ubifs_zn_obsolete(old_zn));
239
+ __set_bit(OBSOLETE_ZNODE, &old_zn->flags);
240
+
241
+ if (old_zn->level != 0) {
242
+ int i;
243
+ const int n = new_zn->child_cnt;
244
+
245
+ /* The children now have new parent */
246
+ for (i = 0; i < n; i++) {
247
+ struct ubifs_zbranch *child = &new_zn->zbranch[i];
248
+
249
+ if (child->znode)
250
+ child->znode->parent = new_zn;
251
+ }
252
+ }
253
+
254
+ zbr->znode = new_zn;
255
+ zbr->lnum = 0;
256
+ zbr->offs = 0;
257
+ zbr->len = 0;
258
+
259
+ atomic_long_inc(&c->dirty_zn_cnt);
234260 }
235261
236262 /**
....@@ -265,21 +291,32 @@
265291 return zn;
266292
267293 if (zbr->len) {
268
- err = insert_old_idx(c, zbr->lnum, zbr->offs);
269
- if (unlikely(err))
270
- return ERR_PTR(err);
294
+ struct ubifs_old_idx *old_idx;
295
+
296
+ old_idx = kmalloc(sizeof(struct ubifs_old_idx), GFP_NOFS);
297
+ if (unlikely(!old_idx)) {
298
+ err = -ENOMEM;
299
+ goto out;
300
+ }
301
+ old_idx->lnum = zbr->lnum;
302
+ old_idx->offs = zbr->offs;
303
+
271304 err = add_idx_dirt(c, zbr->lnum, zbr->len);
272
- } else
273
- err = 0;
305
+ if (err) {
306
+ kfree(old_idx);
307
+ goto out;
308
+ }
274309
275
- zbr->znode = zn;
276
- zbr->lnum = 0;
277
- zbr->offs = 0;
278
- zbr->len = 0;
310
+ do_insert_old_idx(c, old_idx);
311
+ }
279312
280
- if (unlikely(err))
281
- return ERR_PTR(err);
313
+ replace_znode(c, zn, znode, zbr);
314
+
282315 return zn;
316
+
317
+out:
318
+ kfree(zn);
319
+ return ERR_PTR(err);
283320 }
284321
285322 /**
....@@ -3053,6 +3090,21 @@
30533090 cnext = cnext->cnext;
30543091 if (ubifs_zn_obsolete(znode))
30553092 kfree(znode);
3093
+ else if (!ubifs_zn_cow(znode)) {
3094
+ /*
3095
+ * Don't forget to update clean znode count after
3096
+ * committing failed, because ubifs will check this
3097
+ * count while closing tnc. Non-obsolete znode could
3098
+ * be re-dirtied during committing process, so dirty
3099
+ * flag is untrustable. The flag 'COW_ZNODE' is set
3100
+ * for each dirty znode before committing, and it is
3101
+ * cleared as long as the znode become clean, so we
3102
+ * can statistic clean znode count according to this
3103
+ * flag.
3104
+ */
3105
+ atomic_long_inc(&c->clean_zn_cnt);
3106
+ atomic_long_inc(&ubifs_clean_zn_cnt);
3107
+ }
30563108 } while (cnext && cnext != c->cnext);
30573109 }
30583110