@@ -44,6 +44,33 @@ enum {
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 @@ enum {
6996 */
7097static 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 @@ static struct ubifs_znode *copy_znode(struct ubifs_info *c,
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
@@ -233,6 +223,42 @@ static int add_idx_dirt(struct ubifs_info *c, int lnum, int dirt)
233223 return ubifs_add_dirt (c , lnum , dirt );
234224}
235225
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 );
260+ }
261+
236262/**
237263 * dirty_cow_znode - ensure a znode is not being committed.
238264 * @c: UBIFS file-system description object
@@ -265,21 +291,32 @@ static struct ubifs_znode *dirty_cow_znode(struct ubifs_info *c,
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+ }
312+
313+ replace_znode ( c , zn , znode , zbr ) ;
279314
280- if (unlikely (err ))
281- return ERR_PTR (err );
282315 return zn ;
316+
317+ out :
318+ kfree (zn );
319+ return ERR_PTR (err );
283320}
284321
285322/**
0 commit comments