| .. | .. | 
|---|
| 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 |   | 
|---|