.. | .. |
---|
44 | 44 | NOT_ON_MEDIA = 3, |
---|
45 | 45 | }; |
---|
46 | 46 | |
---|
| 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 | + |
---|
47 | 74 | /** |
---|
48 | 75 | * insert_old_idx - record an index node obsoleted since the last commit start. |
---|
49 | 76 | * @c: UBIFS file-system description object |
---|
.. | .. |
---|
69 | 96 | */ |
---|
70 | 97 | static int insert_old_idx(struct ubifs_info *c, int lnum, int offs) |
---|
71 | 98 | { |
---|
72 | | - struct ubifs_old_idx *old_idx, *o; |
---|
73 | | - struct rb_node **p, *parent = NULL; |
---|
| 99 | + struct ubifs_old_idx *old_idx; |
---|
74 | 100 | |
---|
75 | 101 | old_idx = kmalloc(sizeof(struct ubifs_old_idx), GFP_NOFS); |
---|
76 | 102 | if (unlikely(!old_idx)) |
---|
77 | 103 | return -ENOMEM; |
---|
78 | 104 | old_idx->lnum = lnum; |
---|
79 | 105 | old_idx->offs = offs; |
---|
| 106 | + do_insert_old_idx(c, old_idx); |
---|
80 | 107 | |
---|
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); |
---|
101 | 108 | return 0; |
---|
102 | 109 | } |
---|
103 | 110 | |
---|
.. | .. |
---|
199 | 206 | __set_bit(DIRTY_ZNODE, &zn->flags); |
---|
200 | 207 | __clear_bit(COW_ZNODE, &zn->flags); |
---|
201 | 208 | |
---|
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); |
---|
219 | 209 | return zn; |
---|
220 | 210 | } |
---|
221 | 211 | |
---|
.. | .. |
---|
231 | 221 | { |
---|
232 | 222 | c->calc_idx_sz -= ALIGN(dirt, 8); |
---|
233 | 223 | 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); |
---|
234 | 260 | } |
---|
235 | 261 | |
---|
236 | 262 | /** |
---|
.. | .. |
---|
265 | 291 | return zn; |
---|
266 | 292 | |
---|
267 | 293 | 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 | + |
---|
271 | 304 | 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 | + } |
---|
274 | 309 | |
---|
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 | + } |
---|
279 | 312 | |
---|
280 | | - if (unlikely(err)) |
---|
281 | | - return ERR_PTR(err); |
---|
| 313 | + replace_znode(c, zn, znode, zbr); |
---|
| 314 | + |
---|
282 | 315 | return zn; |
---|
| 316 | + |
---|
| 317 | +out: |
---|
| 318 | + kfree(zn); |
---|
| 319 | + return ERR_PTR(err); |
---|
283 | 320 | } |
---|
284 | 321 | |
---|
285 | 322 | /** |
---|
.. | .. |
---|
3053 | 3090 | cnext = cnext->cnext; |
---|
3054 | 3091 | if (ubifs_zn_obsolete(znode)) |
---|
3055 | 3092 | 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 | + } |
---|
3056 | 3108 | } while (cnext && cnext != c->cnext); |
---|
3057 | 3109 | } |
---|
3058 | 3110 | |
---|