@@ -95,6 +95,92 @@ static int self_check_ai(struct ubi_device *ubi, struct ubi_attach_info *ai);
95
95
static struct ubi_ec_hdr * ech ;
96
96
static struct ubi_vid_hdr * vidh ;
97
97
98
+ #define AV_FIND BIT(0)
99
+ #define AV_ADD BIT(1)
100
+ #define AV_FIND_OR_ADD (AV_FIND | AV_ADD)
101
+
102
+ /**
103
+ * find_or_add_av - internal function to find a volume, add a volume or do
104
+ * both (find and add if missing).
105
+ * @ai: attaching information
106
+ * @vol_id: the requested volume ID
107
+ * @flags: a combination of the %AV_FIND and %AV_ADD flags describing the
108
+ * expected operation. If only %AV_ADD is set, -EEXIST is returned
109
+ * if the volume already exists. If only %AV_FIND is set, NULL is
110
+ * returned if the volume does not exist. And if both flags are
111
+ * set, the helper first tries to find an existing volume, and if
112
+ * it does not exist it creates a new one.
113
+ * @created: in value used to inform the caller whether it"s a newly created
114
+ * volume or not.
115
+ *
116
+ * This function returns a pointer to a volume description or an ERR_PTR if
117
+ * the operation failed. It can also return NULL if only %AV_FIND is set and
118
+ * the volume does not exist.
119
+ */
120
+ static struct ubi_ainf_volume * find_or_add_av (struct ubi_attach_info * ai ,
121
+ int vol_id , unsigned int flags ,
122
+ bool * created )
123
+ {
124
+ struct ubi_ainf_volume * av ;
125
+ struct rb_node * * p = & ai -> volumes .rb_node , * parent = NULL ;
126
+
127
+ /* Walk the volume RB-tree to look if this volume is already present */
128
+ while (* p ) {
129
+ parent = * p ;
130
+ av = rb_entry (parent , struct ubi_ainf_volume , rb );
131
+
132
+ if (vol_id == av -> vol_id ) {
133
+ * created = false;
134
+
135
+ if (!(flags & AV_FIND ))
136
+ return ERR_PTR (- EEXIST );
137
+
138
+ return av ;
139
+ }
140
+
141
+ if (vol_id > av -> vol_id )
142
+ p = & (* p )-> rb_left ;
143
+ else
144
+ p = & (* p )-> rb_right ;
145
+ }
146
+
147
+ if (!(flags & AV_ADD ))
148
+ return NULL ;
149
+
150
+ /* The volume is absent - add it */
151
+ av = kzalloc (sizeof (* av ), GFP_KERNEL );
152
+ if (!av )
153
+ return ERR_PTR (- ENOMEM );
154
+
155
+ av -> vol_id = vol_id ;
156
+
157
+ if (vol_id > ai -> highest_vol_id )
158
+ ai -> highest_vol_id = vol_id ;
159
+
160
+ rb_link_node (& av -> rb , parent , p );
161
+ rb_insert_color (& av -> rb , & ai -> volumes );
162
+ ai -> vols_found += 1 ;
163
+ * created = true;
164
+ dbg_bld ("added volume %d" , vol_id );
165
+ return av ;
166
+ }
167
+
168
+ /**
169
+ * ubi_find_or_add_av - search for a volume in the attaching information and
170
+ * add one if it does not exist.
171
+ * @ai: attaching information
172
+ * @vol_id: the requested volume ID
173
+ * @created: whether the volume has been created or not
174
+ *
175
+ * This function returns a pointer to the new volume description or an
176
+ * ERR_PTR if the operation failed.
177
+ */
178
+ static struct ubi_ainf_volume * ubi_find_or_add_av (struct ubi_attach_info * ai ,
179
+ int vol_id , bool * created )
180
+ {
181
+ return find_or_add_av (ai , vol_id , AV_FIND_OR_ADD , created );
182
+ }
183
+
98
184
/**
99
185
* add_to_list - add physical eraseblock to a list.
100
186
* @ai: attaching information
@@ -294,44 +380,20 @@ static struct ubi_ainf_volume *add_volume(struct ubi_attach_info *ai,
294
380
const struct ubi_vid_hdr * vid_hdr )
295
381
{
296
382
struct ubi_ainf_volume * av ;
297
- struct rb_node * * p = & ai -> volumes . rb_node , * parent = NULL ;
383
+ bool created ;
298
384
299
385
ubi_assert (vol_id == be32_to_cpu (vid_hdr -> vol_id ));
300
386
301
- /* Walk the volume RB-tree to look if this volume is already present */
302
- while (* p ) {
303
- parent = * p ;
304
- av = rb_entry (parent , struct ubi_ainf_volume , rb );
305
-
306
- if (vol_id == av -> vol_id )
307
- return av ;
387
+ av = ubi_find_or_add_av (ai , vol_id , & created );
388
+ if (IS_ERR (av ) || !created )
389
+ return av ;
308
390
309
- if (vol_id > av -> vol_id )
310
- p = & (* p )-> rb_left ;
311
- else
312
- p = & (* p )-> rb_right ;
313
- }
314
-
315
- /* The volume is absent - add it */
316
- av = kmalloc (sizeof (struct ubi_ainf_volume ), GFP_KERNEL );
317
- if (!av )
318
- return ERR_PTR (- ENOMEM );
319
-
320
- av -> highest_lnum = av -> leb_count = 0 ;
321
- av -> vol_id = vol_id ;
322
- av -> root = RB_ROOT ;
323
391
av -> used_ebs = be32_to_cpu (vid_hdr -> used_ebs );
324
392
av -> data_pad = be32_to_cpu (vid_hdr -> data_pad );
325
393
av -> compat = vid_hdr -> compat ;
326
394
av -> vol_type = vid_hdr -> vol_type == UBI_VID_DYNAMIC ? UBI_DYNAMIC_VOLUME
327
395
: UBI_STATIC_VOLUME ;
328
- if (vol_id > ai -> highest_vol_id )
329
- ai -> highest_vol_id = vol_id ;
330
396
331
- rb_link_node (& av -> rb , parent , p );
332
- rb_insert_color (& av -> rb , & ai -> volumes );
333
- ai -> vols_found += 1 ;
334
- dbg_bld ("added volume %d" , vol_id );
335
397
return av ;
336
398
}
337
399
@@ -628,6 +690,21 @@ int ubi_add_to_av(struct ubi_device *ubi, struct ubi_attach_info *ai, int pnum,
628
690
return 0 ;
629
691
}
630
692
693
+ /**
694
+ * ubi_add_av - add volume to the attaching information.
695
+ * @ai: attaching information
696
+ * @vol_id: the requested volume ID
697
+ *
698
+ * This function returns a pointer to the new volume description or an
699
+ * ERR_PTR if the operation failed.
700
+ */
701
+ struct ubi_ainf_volume * ubi_add_av (struct ubi_attach_info * ai , int vol_id )
702
+ {
703
+ bool created ;
704
+
705
+ return find_or_add_av (ai , vol_id , AV_ADD , & created );
706
+ }
707
+
631
708
/**
632
709
* ubi_find_av - find volume in the attaching information.
633
710
* @ai: attaching information
@@ -639,22 +716,10 @@ int ubi_add_to_av(struct ubi_device *ubi, struct ubi_attach_info *ai, int pnum,
639
716
struct ubi_ainf_volume * ubi_find_av (const struct ubi_attach_info * ai ,
640
717
int vol_id )
641
718
{
642
- struct ubi_ainf_volume * av ;
643
- struct rb_node * p = ai -> volumes .rb_node ;
644
-
645
- while (p ) {
646
- av = rb_entry (p , struct ubi_ainf_volume , rb );
647
-
648
- if (vol_id == av -> vol_id )
649
- return av ;
650
-
651
- if (vol_id > av -> vol_id )
652
- p = p -> rb_left ;
653
- else
654
- p = p -> rb_right ;
655
- }
719
+ bool created ;
656
720
657
- return NULL ;
721
+ return find_or_add_av ((struct ubi_attach_info * )ai , vol_id , AV_FIND ,
722
+ & created );
658
723
}
659
724
660
725
/**
0 commit comments