Skip to content

Commit de4c455

Browse files
Boris Brezillonrichardweinberger
authored andcommitted
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>
1 parent 5f09aaa commit de4c455

File tree

3 files changed

+112
-67
lines changed

3 files changed

+112
-67
lines changed

drivers/mtd/ubi/attach.c

Lines changed: 108 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,92 @@ static int self_check_ai(struct ubi_device *ubi, struct ubi_attach_info *ai);
9595
static struct ubi_ec_hdr *ech;
9696
static struct ubi_vid_hdr *vidh;
9797

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+
98184
/**
99185
* add_to_list - add physical eraseblock to a list.
100186
* @ai: attaching information
@@ -294,44 +380,20 @@ static struct ubi_ainf_volume *add_volume(struct ubi_attach_info *ai,
294380
const struct ubi_vid_hdr *vid_hdr)
295381
{
296382
struct ubi_ainf_volume *av;
297-
struct rb_node **p = &ai->volumes.rb_node, *parent = NULL;
383+
bool created;
298384

299385
ubi_assert(vol_id == be32_to_cpu(vid_hdr->vol_id));
300386

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;
308390

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;
323391
av->used_ebs = be32_to_cpu(vid_hdr->used_ebs);
324392
av->data_pad = be32_to_cpu(vid_hdr->data_pad);
325393
av->compat = vid_hdr->compat;
326394
av->vol_type = vid_hdr->vol_type == UBI_VID_DYNAMIC ? UBI_DYNAMIC_VOLUME
327395
: UBI_STATIC_VOLUME;
328-
if (vol_id > ai->highest_vol_id)
329-
ai->highest_vol_id = vol_id;
330396

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);
335397
return av;
336398
}
337399

@@ -628,6 +690,21 @@ int ubi_add_to_av(struct ubi_device *ubi, struct ubi_attach_info *ai, int pnum,
628690
return 0;
629691
}
630692

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+
631708
/**
632709
* ubi_find_av - find volume in the attaching information.
633710
* @ai: attaching information
@@ -639,22 +716,10 @@ int ubi_add_to_av(struct ubi_device *ubi, struct ubi_attach_info *ai, int pnum,
639716
struct ubi_ainf_volume *ubi_find_av(const struct ubi_attach_info *ai,
640717
int vol_id)
641718
{
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;
656720

657-
return NULL;
721+
return find_or_add_av((struct ubi_attach_info *)ai, vol_id, AV_FIND,
722+
&created);
658723
}
659724

660725
/**

drivers/mtd/ubi/fastmap.c

Lines changed: 3 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -186,40 +186,19 @@ static struct ubi_ainf_volume *add_vol(struct ubi_attach_info *ai, int vol_id,
186186
int last_eb_bytes)
187187
{
188188
struct ubi_ainf_volume *av;
189-
struct rb_node **p = &ai->volumes.rb_node, *parent = NULL;
190189

191-
while (*p) {
192-
parent = *p;
193-
av = rb_entry(parent, struct ubi_ainf_volume, rb);
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-
}
190+
av = ubi_add_av(ai, vol_id);
191+
if (IS_ERR(av))
192+
return av;
202193

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;
209194
av->data_pad = data_pad;
210195
av->last_data_size = last_eb_bytes;
211196
av->compat = 0;
212197
av->vol_type = vol_type;
213-
av->root = RB_ROOT;
214198
if (av->vol_type == UBI_STATIC_VOLUME)
215199
av->used_ebs = used_ebs;
216200

217201
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:
223202
return av;
224203
}
225204

drivers/mtd/ubi/ubi.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -794,6 +794,7 @@ extern struct blocking_notifier_head ubi_notifiers;
794794
/* attach.c */
795795
int ubi_add_to_av(struct ubi_device *ubi, struct ubi_attach_info *ai, int pnum,
796796
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);
797798
struct ubi_ainf_volume *ubi_find_av(const struct ubi_attach_info *ai,
798799
int vol_id);
799800
void ubi_remove_av(struct ubi_attach_info *ai, struct ubi_ainf_volume *av);

0 commit comments

Comments
 (0)