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