aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBoris Brezillon <boris.brezillon@free-electrons.com>2016-09-16 10:59:14 -0400
committerRichard Weinberger <richard@nod.at>2016-10-02 16:48:14 -0400
commitde4c455b3e9f6306ce7f4245d1ae09d4f1209bb4 (patch)
treefcd764fb80555312cf6d1aa67218cd302af08c5c
parent5f09aaa9b30c91e6f72790bfb975240e8116d6db (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.c151
-rw-r--r--drivers/mtd/ubi/fastmap.c27
-rw-r--r--drivers/mtd/ubi/ubi.h1
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);
95static struct ubi_ec_hdr *ech; 95static struct ubi_ec_hdr *ech;
96static struct ubi_vid_hdr *vidh; 96static 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 */
120static 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 */
178static 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 */
701struct 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,
639struct ubi_ainf_volume *ubi_find_av(const struct ubi_attach_info *ai, 716struct 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
222out:
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 */
795int ubi_add_to_av(struct ubi_device *ubi, struct ubi_attach_info *ai, int pnum, 795int 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);
797struct ubi_ainf_volume *ubi_add_av(struct ubi_attach_info *ai, int vol_id);
797struct ubi_ainf_volume *ubi_find_av(const struct ubi_attach_info *ai, 798struct ubi_ainf_volume *ubi_find_av(const struct ubi_attach_info *ai,
798 int vol_id); 799 int vol_id);
799void ubi_remove_av(struct ubi_attach_info *ai, struct ubi_ainf_volume *av); 800void ubi_remove_av(struct ubi_attach_info *ai, struct ubi_ainf_volume *av);