This source file includes following definitions.
- set_update_marker
- clear_update_marker
- ubi_start_update
- ubi_start_leb_change
- write_leb
- ubi_more_update_data
- ubi_more_leb_change_data
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28 #include <linux/err.h>
29 #include <linux/uaccess.h>
30 #include <linux/math64.h>
31 #include "ubi.h"
32
33
34
35
36
37
38
39
40
41 static int set_update_marker(struct ubi_device *ubi, struct ubi_volume *vol)
42 {
43 int err;
44 struct ubi_vtbl_record vtbl_rec;
45
46 dbg_gen("set update marker for volume %d", vol->vol_id);
47
48 if (vol->upd_marker) {
49 ubi_assert(ubi->vtbl[vol->vol_id].upd_marker);
50 dbg_gen("already set");
51 return 0;
52 }
53
54 vtbl_rec = ubi->vtbl[vol->vol_id];
55 vtbl_rec.upd_marker = 1;
56
57 mutex_lock(&ubi->device_mutex);
58 err = ubi_change_vtbl_record(ubi, vol->vol_id, &vtbl_rec);
59 vol->upd_marker = 1;
60 mutex_unlock(&ubi->device_mutex);
61 return err;
62 }
63
64
65
66
67
68
69
70
71
72
73
74 static int clear_update_marker(struct ubi_device *ubi, struct ubi_volume *vol,
75 long long bytes)
76 {
77 int err;
78 struct ubi_vtbl_record vtbl_rec;
79
80 dbg_gen("clear update marker for volume %d", vol->vol_id);
81
82 vtbl_rec = ubi->vtbl[vol->vol_id];
83 ubi_assert(vol->upd_marker && vtbl_rec.upd_marker);
84 vtbl_rec.upd_marker = 0;
85
86 if (vol->vol_type == UBI_STATIC_VOLUME) {
87 vol->corrupted = 0;
88 vol->used_bytes = bytes;
89 vol->used_ebs = div_u64_rem(bytes, vol->usable_leb_size,
90 &vol->last_eb_bytes);
91 if (vol->last_eb_bytes)
92 vol->used_ebs += 1;
93 else
94 vol->last_eb_bytes = vol->usable_leb_size;
95 }
96
97 mutex_lock(&ubi->device_mutex);
98 err = ubi_change_vtbl_record(ubi, vol->vol_id, &vtbl_rec);
99 vol->upd_marker = 0;
100 mutex_unlock(&ubi->device_mutex);
101 return err;
102 }
103
104
105
106
107
108
109
110
111
112
113
114 int ubi_start_update(struct ubi_device *ubi, struct ubi_volume *vol,
115 long long bytes)
116 {
117 int i, err;
118
119 dbg_gen("start update of volume %d, %llu bytes", vol->vol_id, bytes);
120 ubi_assert(!vol->updating && !vol->changing_leb);
121 vol->updating = 1;
122
123 vol->upd_buf = vmalloc(ubi->leb_size);
124 if (!vol->upd_buf)
125 return -ENOMEM;
126
127 err = set_update_marker(ubi, vol);
128 if (err)
129 return err;
130
131
132 for (i = 0; i < vol->reserved_pebs; i++) {
133 err = ubi_eba_unmap_leb(ubi, vol, i);
134 if (err)
135 return err;
136 }
137
138 err = ubi_wl_flush(ubi, UBI_ALL, UBI_ALL);
139 if (err)
140 return err;
141
142 if (bytes == 0) {
143 err = clear_update_marker(ubi, vol, 0);
144 if (err)
145 return err;
146
147 vfree(vol->upd_buf);
148 vol->updating = 0;
149 return 0;
150 }
151
152 vol->upd_ebs = div_u64(bytes + vol->usable_leb_size - 1,
153 vol->usable_leb_size);
154 vol->upd_bytes = bytes;
155 vol->upd_received = 0;
156 return 0;
157 }
158
159
160
161
162
163
164
165
166
167
168 int ubi_start_leb_change(struct ubi_device *ubi, struct ubi_volume *vol,
169 const struct ubi_leb_change_req *req)
170 {
171 ubi_assert(!vol->updating && !vol->changing_leb);
172
173 dbg_gen("start changing LEB %d:%d, %u bytes",
174 vol->vol_id, req->lnum, req->bytes);
175 if (req->bytes == 0)
176 return ubi_eba_atomic_leb_change(ubi, vol, req->lnum, NULL, 0);
177
178 vol->upd_bytes = req->bytes;
179 vol->upd_received = 0;
180 vol->changing_leb = 1;
181 vol->ch_lnum = req->lnum;
182
183 vol->upd_buf = vmalloc(ALIGN((int)req->bytes, ubi->min_io_size));
184 if (!vol->upd_buf)
185 return -ENOMEM;
186
187 return 0;
188 }
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219 static int write_leb(struct ubi_device *ubi, struct ubi_volume *vol, int lnum,
220 void *buf, int len, int used_ebs)
221 {
222 int err;
223
224 if (vol->vol_type == UBI_DYNAMIC_VOLUME) {
225 int l = ALIGN(len, ubi->min_io_size);
226
227 memset(buf + len, 0xFF, l - len);
228 len = ubi_calc_data_len(ubi, buf, l);
229 if (len == 0) {
230 dbg_gen("all %d bytes contain 0xFF - skip", len);
231 return 0;
232 }
233
234 err = ubi_eba_write_leb(ubi, vol, lnum, buf, 0, len);
235 } else {
236
237
238
239
240
241
242
243
244
245 memset(buf + len, 0, vol->usable_leb_size - len);
246 err = ubi_eba_write_leb_st(ubi, vol, lnum, buf, len, used_ebs);
247 }
248
249 return err;
250 }
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265 int ubi_more_update_data(struct ubi_device *ubi, struct ubi_volume *vol,
266 const void __user *buf, int count)
267 {
268 int lnum, offs, err = 0, len, to_write = count;
269
270 dbg_gen("write %d of %lld bytes, %lld already passed",
271 count, vol->upd_bytes, vol->upd_received);
272
273 if (ubi->ro_mode)
274 return -EROFS;
275
276 lnum = div_u64_rem(vol->upd_received, vol->usable_leb_size, &offs);
277 if (vol->upd_received + count > vol->upd_bytes)
278 to_write = count = vol->upd_bytes - vol->upd_received;
279
280
281
282
283
284 if (offs != 0) {
285
286
287
288
289
290
291
292 len = vol->usable_leb_size - offs;
293 if (len > count)
294 len = count;
295
296 err = copy_from_user(vol->upd_buf + offs, buf, len);
297 if (err)
298 return -EFAULT;
299
300 if (offs + len == vol->usable_leb_size ||
301 vol->upd_received + len == vol->upd_bytes) {
302 int flush_len = offs + len;
303
304
305
306
307
308 ubi_assert(flush_len <= vol->usable_leb_size);
309 err = write_leb(ubi, vol, lnum, vol->upd_buf, flush_len,
310 vol->upd_ebs);
311 if (err)
312 return err;
313 }
314
315 vol->upd_received += len;
316 count -= len;
317 buf += len;
318 lnum += 1;
319 }
320
321
322
323
324
325 while (count) {
326 if (count > vol->usable_leb_size)
327 len = vol->usable_leb_size;
328 else
329 len = count;
330
331 err = copy_from_user(vol->upd_buf, buf, len);
332 if (err)
333 return -EFAULT;
334
335 if (len == vol->usable_leb_size ||
336 vol->upd_received + len == vol->upd_bytes) {
337 err = write_leb(ubi, vol, lnum, vol->upd_buf,
338 len, vol->upd_ebs);
339 if (err)
340 break;
341 }
342
343 vol->upd_received += len;
344 count -= len;
345 lnum += 1;
346 buf += len;
347 }
348
349 ubi_assert(vol->upd_received <= vol->upd_bytes);
350 if (vol->upd_received == vol->upd_bytes) {
351 err = ubi_wl_flush(ubi, UBI_ALL, UBI_ALL);
352 if (err)
353 return err;
354
355 err = clear_update_marker(ubi, vol, vol->upd_bytes);
356 if (err)
357 return err;
358 vol->updating = 0;
359 err = to_write;
360 vfree(vol->upd_buf);
361 }
362
363 return err;
364 }
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380 int ubi_more_leb_change_data(struct ubi_device *ubi, struct ubi_volume *vol,
381 const void __user *buf, int count)
382 {
383 int err;
384
385 dbg_gen("write %d of %lld bytes, %lld already passed",
386 count, vol->upd_bytes, vol->upd_received);
387
388 if (ubi->ro_mode)
389 return -EROFS;
390
391 if (vol->upd_received + count > vol->upd_bytes)
392 count = vol->upd_bytes - vol->upd_received;
393
394 err = copy_from_user(vol->upd_buf + vol->upd_received, buf, count);
395 if (err)
396 return -EFAULT;
397
398 vol->upd_received += count;
399
400 if (vol->upd_received == vol->upd_bytes) {
401 int len = ALIGN((int)vol->upd_bytes, ubi->min_io_size);
402
403 memset(vol->upd_buf + vol->upd_bytes, 0xFF,
404 len - vol->upd_bytes);
405 len = ubi_calc_data_len(ubi, vol->upd_buf, len);
406 err = ubi_eba_atomic_leb_change(ubi, vol, vol->ch_lnum,
407 vol->upd_buf, len);
408 if (err)
409 return err;
410 }
411
412 ubi_assert(vol->upd_received <= vol->upd_bytes);
413 if (vol->upd_received == vol->upd_bytes) {
414 vol->changing_leb = 0;
415 err = count;
416 vfree(vol->upd_buf);
417 }
418
419 return err;
420 }