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 vol->upd_buf = vmalloc(ubi->leb_size);
137 if (!vol->upd_buf)
138 return -ENOMEM;
139
140 err = set_update_marker(ubi, vol);
141 if (err)
142 return err;
143
144
145 for (i = 0; i < vol->reserved_pebs; i++) {
146 err = ubi_eba_unmap_leb(ubi, vol, i);
147 if (err)
148 return err;
149 }
150
151 err = ubi_wl_flush(ubi, UBI_ALL, UBI_ALL);
152 if (err)
153 return err;
154
155 if (bytes == 0) {
156 err = clear_update_marker(ubi, vol, 0);
157 if (err)
158 return err;
159
160 vfree(vol->upd_buf);
161 vol->updating = 0;
162 return 0;
163 }
164
165 vol->upd_ebs = div_u64(bytes + vol->usable_leb_size - 1,
166 vol->usable_leb_size);
167 vol->upd_bytes = bytes;
168 vol->upd_received = 0;
169 return 0;
170}
171
172
173
174
175
176
177
178
179
180
181int ubi_start_leb_change(struct ubi_device *ubi, struct ubi_volume *vol,
182 const struct ubi_leb_change_req *req)
183{
184 ubi_assert(!vol->updating && !vol->changing_leb);
185
186 dbg_gen("start changing LEB %d:%d, %u bytes",
187 vol->vol_id, req->lnum, req->bytes);
188 if (req->bytes == 0)
189 return ubi_eba_atomic_leb_change(ubi, vol, req->lnum, NULL, 0);
190
191 vol->upd_bytes = req->bytes;
192 vol->upd_received = 0;
193 vol->changing_leb = 1;
194 vol->ch_lnum = req->lnum;
195
196 vol->upd_buf = vmalloc(ALIGN((int)req->bytes, ubi->min_io_size));
197 if (!vol->upd_buf)
198 return -ENOMEM;
199
200 return 0;
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
230
231
232static int write_leb(struct ubi_device *ubi, struct ubi_volume *vol, int lnum,
233 void *buf, int len, int used_ebs)
234{
235 int err;
236
237 if (vol->vol_type == UBI_DYNAMIC_VOLUME) {
238 int l = ALIGN(len, ubi->min_io_size);
239
240 memset(buf + len, 0xFF, l - len);
241 len = ubi_calc_data_len(ubi, buf, l);
242 if (len == 0) {
243 dbg_gen("all %d bytes contain 0xFF - skip", len);
244 return 0;
245 }
246
247 err = ubi_eba_write_leb(ubi, vol, lnum, buf, 0, len);
248 } else {
249
250
251
252
253
254
255
256
257
258 memset(buf + len, 0, vol->usable_leb_size - len);
259 err = ubi_eba_write_leb_st(ubi, vol, lnum, buf, len, used_ebs);
260 }
261
262 return err;
263}
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278int ubi_more_update_data(struct ubi_device *ubi, struct ubi_volume *vol,
279 const void __user *buf, int count)
280{
281 int lnum, offs, err = 0, len, to_write = count;
282
283 dbg_gen("write %d of %lld bytes, %lld already passed",
284 count, vol->upd_bytes, vol->upd_received);
285
286 if (ubi->ro_mode)
287 return -EROFS;
288
289 lnum = div_u64_rem(vol->upd_received, vol->usable_leb_size, &offs);
290 if (vol->upd_received + count > vol->upd_bytes)
291 to_write = count = vol->upd_bytes - vol->upd_received;
292
293
294
295
296
297 if (offs != 0) {
298
299
300
301
302
303
304
305 len = vol->usable_leb_size - offs;
306 if (len > count)
307 len = count;
308
309 err = copy_from_user(vol->upd_buf + offs, buf, len);
310 if (err)
311 return -EFAULT;
312
313 if (offs + len == vol->usable_leb_size ||
314 vol->upd_received + len == vol->upd_bytes) {
315 int flush_len = offs + len;
316
317
318
319
320
321 ubi_assert(flush_len <= vol->usable_leb_size);
322 err = write_leb(ubi, vol, lnum, vol->upd_buf, flush_len,
323 vol->upd_ebs);
324 if (err)
325 return err;
326 }
327
328 vol->upd_received += len;
329 count -= len;
330 buf += len;
331 lnum += 1;
332 }
333
334
335
336
337
338 while (count) {
339 if (count > vol->usable_leb_size)
340 len = vol->usable_leb_size;
341 else
342 len = count;
343
344 err = copy_from_user(vol->upd_buf, buf, len);
345 if (err)
346 return -EFAULT;
347
348 if (len == vol->usable_leb_size ||
349 vol->upd_received + len == vol->upd_bytes) {
350 err = write_leb(ubi, vol, lnum, vol->upd_buf,
351 len, vol->upd_ebs);
352 if (err)
353 break;
354 }
355
356 vol->upd_received += len;
357 count -= len;
358 lnum += 1;
359 buf += len;
360 }
361
362 ubi_assert(vol->upd_received <= vol->upd_bytes);
363 if (vol->upd_received == vol->upd_bytes) {
364 err = ubi_wl_flush(ubi, UBI_ALL, UBI_ALL);
365 if (err)
366 return err;
367
368 err = clear_update_marker(ubi, vol, vol->upd_bytes);
369 if (err)
370 return err;
371 vol->updating = 0;
372 err = to_write;
373 vfree(vol->upd_buf);
374 }
375
376 return err;
377}
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393int ubi_more_leb_change_data(struct ubi_device *ubi, struct ubi_volume *vol,
394 const void __user *buf, int count)
395{
396 int err;
397
398 dbg_gen("write %d of %lld bytes, %lld already passed",
399 count, vol->upd_bytes, vol->upd_received);
400
401 if (ubi->ro_mode)
402 return -EROFS;
403
404 if (vol->upd_received + count > vol->upd_bytes)
405 count = vol->upd_bytes - vol->upd_received;
406
407 err = copy_from_user(vol->upd_buf + vol->upd_received, buf, count);
408 if (err)
409 return -EFAULT;
410
411 vol->upd_received += count;
412
413 if (vol->upd_received == vol->upd_bytes) {
414 int len = ALIGN((int)vol->upd_bytes, ubi->min_io_size);
415
416 memset(vol->upd_buf + vol->upd_bytes, 0xFF,
417 len - vol->upd_bytes);
418 len = ubi_calc_data_len(ubi, vol->upd_buf, len);
419 err = ubi_eba_atomic_leb_change(ubi, vol, vol->ch_lnum,
420 vol->upd_buf, len);
421 if (err)
422 return err;
423 }
424
425 ubi_assert(vol->upd_received <= vol->upd_bytes);
426 if (vol->upd_received == vol->upd_bytes) {
427 vol->changing_leb = 0;
428 err = count;
429 vfree(vol->upd_buf);
430 }
431
432 return err;
433}
434