diff options
author | Boris Brezillon <boris.brezillon@free-electrons.com> | 2016-09-16 10:59:14 -0400 |
---|---|---|
committer | Richard Weinberger <richard@nod.at> | 2016-10-02 16:48:14 -0400 |
commit | de4c455b3e9f6306ce7f4245d1ae09d4f1209bb4 (patch) | |
tree | fcd764fb80555312cf6d1aa67218cd302af08c5c | |
parent | 5f09aaa9b30c91e6f72790bfb975240e8116d6db (diff) |
UBI: factorize code used to manipulate volumes at attach time
Volume creation/search code is duplicated in a few places (fastmap and
non fastmap code). Create some helpers to factorize the code.
Signed-off-by: Boris Brezillon <boris.brezillon@free-electrons.com>
Signed-off-by: Richard Weinberger <richard@nod.at>
-rw-r--r-- | drivers/mtd/ubi/attach.c | 151 | ||||
-rw-r--r-- | drivers/mtd/ubi/fastmap.c | 27 | ||||
-rw-r--r-- | drivers/mtd/ubi/ubi.h | 1 |
3 files changed, 112 insertions, 67 deletions
diff --git a/drivers/mtd/ubi/attach.c b/drivers/mtd/ubi/attach.c index 95138ae2062f..6d34cd7b0263 100644 --- a/drivers/mtd/ubi/attach.c +++ b/drivers/mtd/ubi/attach.c | |||
@@ -95,6 +95,92 @@ static int self_check_ai(struct ubi_device *ubi, struct ubi_attach_info *ai); | |||
95 | static struct ubi_ec_hdr *ech; | 95 | static struct ubi_ec_hdr *ech; |
96 | static struct ubi_vid_hdr *vidh; | 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 | * add_to_list - add physical eraseblock to a list. | 185 | * add_to_list - add physical eraseblock to a list. |
100 | * @ai: attaching information | 186 | * @ai: attaching information |
@@ -294,44 +380,20 @@ static struct ubi_ainf_volume *add_volume(struct ubi_attach_info *ai, | |||
294 | const struct ubi_vid_hdr *vid_hdr) | 380 | const struct ubi_vid_hdr *vid_hdr) |
295 | { | 381 | { |
296 | struct ubi_ainf_volume *av; | 382 | struct ubi_ainf_volume *av; |
297 | struct rb_node **p = &ai->volumes.rb_node, *parent = NULL; | 383 | bool created; |
298 | 384 | ||
299 | ubi_assert(vol_id == be32_to_cpu(vid_hdr->vol_id)); | 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 */ | 387 | av = ubi_find_or_add_av(ai, vol_id, &created); |
302 | while (*p) { | 388 | if (IS_ERR(av) || !created) |
303 | parent = *p; | 389 | return av; |
304 | av = rb_entry(parent, struct ubi_ainf_volume, rb); | ||
305 | |||
306 | if (vol_id == av->vol_id) | ||
307 | 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 | av->used_ebs = be32_to_cpu(vid_hdr->used_ebs); | 391 | av->used_ebs = be32_to_cpu(vid_hdr->used_ebs); |
324 | av->data_pad = be32_to_cpu(vid_hdr->data_pad); | 392 | av->data_pad = be32_to_cpu(vid_hdr->data_pad); |
325 | av->compat = vid_hdr->compat; | 393 | av->compat = vid_hdr->compat; |
326 | av->vol_type = vid_hdr->vol_type == UBI_VID_DYNAMIC ? UBI_DYNAMIC_VOLUME | 394 | av->vol_type = vid_hdr->vol_type == UBI_VID_DYNAMIC ? UBI_DYNAMIC_VOLUME |
327 | : UBI_STATIC_VOLUME; | 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 | return av; | 397 | return av; |
336 | } | 398 | } |
337 | 399 | ||
@@ -629,6 +691,21 @@ int ubi_add_to_av(struct ubi_device *ubi, struct ubi_attach_info *ai, int pnum, | |||
629 | } | 691 | } |
630 | 692 | ||
631 | /** | 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 | |||
708 | /** | ||
632 | * ubi_find_av - find volume in the attaching information. | 709 | * ubi_find_av - find volume in the attaching information. |
633 | * @ai: attaching information | 710 | * @ai: attaching information |
634 | * @vol_id: the requested volume ID | 711 | * @vol_id: the requested volume ID |
@@ -639,22 +716,10 @@ int ubi_add_to_av(struct ubi_device *ubi, struct ubi_attach_info *ai, int pnum, | |||
639 | struct ubi_ainf_volume *ubi_find_av(const struct ubi_attach_info *ai, | 716 | struct ubi_ainf_volume *ubi_find_av(const struct ubi_attach_info *ai, |
640 | int vol_id) | 717 | int vol_id) |
641 | { | 718 | { |
642 | struct ubi_ainf_volume *av; | 719 | bool created; |
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 | } | ||
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 | /** |
diff --git a/drivers/mtd/ubi/fastmap.c b/drivers/mtd/ubi/fastmap.c index a6ed78d14055..bae80699c2f2 100644 --- a/drivers/mtd/ubi/fastmap.c +++ b/drivers/mtd/ubi/fastmap.c | |||
@@ -186,40 +186,19 @@ static struct ubi_ainf_volume *add_vol(struct ubi_attach_info *ai, int vol_id, | |||
186 | int last_eb_bytes) | 186 | int last_eb_bytes) |
187 | { | 187 | { |
188 | struct ubi_ainf_volume *av; | 188 | struct ubi_ainf_volume *av; |
189 | struct rb_node **p = &ai->volumes.rb_node, *parent = NULL; | ||
190 | 189 | ||
191 | while (*p) { | 190 | av = ubi_add_av(ai, vol_id); |
192 | parent = *p; | 191 | if (IS_ERR(av)) |
193 | av = rb_entry(parent, struct ubi_ainf_volume, rb); | 192 | return av; |
194 | |||
195 | if (vol_id > av->vol_id) | ||
196 | p = &(*p)->rb_left; | ||
197 | else if (vol_id < av->vol_id) | ||
198 | p = &(*p)->rb_right; | ||
199 | else | ||
200 | return ERR_PTR(-EINVAL); | ||
201 | } | ||
202 | 193 | ||
203 | av = kmalloc(sizeof(struct ubi_ainf_volume), GFP_KERNEL); | ||
204 | if (!av) | ||
205 | goto out; | ||
206 | |||
207 | av->highest_lnum = av->leb_count = av->used_ebs = 0; | ||
208 | av->vol_id = vol_id; | ||
209 | av->data_pad = data_pad; | 194 | av->data_pad = data_pad; |
210 | av->last_data_size = last_eb_bytes; | 195 | av->last_data_size = last_eb_bytes; |
211 | av->compat = 0; | 196 | av->compat = 0; |
212 | av->vol_type = vol_type; | 197 | av->vol_type = vol_type; |
213 | av->root = RB_ROOT; | ||
214 | if (av->vol_type == UBI_STATIC_VOLUME) | 198 | if (av->vol_type == UBI_STATIC_VOLUME) |
215 | av->used_ebs = used_ebs; | 199 | av->used_ebs = used_ebs; |
216 | 200 | ||
217 | dbg_bld("found volume (ID %i)", vol_id); | 201 | dbg_bld("found volume (ID %i)", vol_id); |
218 | |||
219 | rb_link_node(&av->rb, parent, p); | ||
220 | rb_insert_color(&av->rb, &ai->volumes); | ||
221 | |||
222 | out: | ||
223 | return av; | 202 | return av; |
224 | } | 203 | } |
225 | 204 | ||
diff --git a/drivers/mtd/ubi/ubi.h b/drivers/mtd/ubi/ubi.h index b616a115c9d3..fce142666bf3 100644 --- a/drivers/mtd/ubi/ubi.h +++ b/drivers/mtd/ubi/ubi.h | |||
@@ -794,6 +794,7 @@ extern struct blocking_notifier_head ubi_notifiers; | |||
794 | /* attach.c */ | 794 | /* attach.c */ |
795 | int ubi_add_to_av(struct ubi_device *ubi, struct ubi_attach_info *ai, int pnum, | 795 | int ubi_add_to_av(struct ubi_device *ubi, struct ubi_attach_info *ai, int pnum, |
796 | int ec, const struct ubi_vid_hdr *vid_hdr, int bitflips); | 796 | int ec, const struct ubi_vid_hdr *vid_hdr, int bitflips); |
797 | struct ubi_ainf_volume *ubi_add_av(struct ubi_attach_info *ai, int vol_id); | ||
797 | struct ubi_ainf_volume *ubi_find_av(const struct ubi_attach_info *ai, | 798 | struct ubi_ainf_volume *ubi_find_av(const struct ubi_attach_info *ai, |
798 | int vol_id); | 799 | int vol_id); |
799 | void ubi_remove_av(struct ubi_attach_info *ai, struct ubi_ainf_volume *av); | 800 | void ubi_remove_av(struct ubi_attach_info *ai, struct ubi_ainf_volume *av); |