aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mtd/ubi/upd.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mtd/ubi/upd.c')
-rw-r--r--drivers/mtd/ubi/upd.c176
1 files changed, 131 insertions, 45 deletions
diff --git a/drivers/mtd/ubi/upd.c b/drivers/mtd/ubi/upd.c
index e32b04d2e04..ddaa1a56cc6 100644
--- a/drivers/mtd/ubi/upd.c
+++ b/drivers/mtd/ubi/upd.c
@@ -22,7 +22,8 @@
22 */ 22 */
23 23
24/* 24/*
25 * This file contains implementation of the volume update functionality. 25 * This file contains implementation of the volume update and atomic LEB change
26 * functionality.
26 * 27 *
27 * The update operation is based on the per-volume update marker which is 28 * The update operation is based on the per-volume update marker which is
28 * stored in the volume table. The update marker is set before the update 29 * stored in the volume table. The update marker is set before the update
@@ -45,30 +46,30 @@
45/** 46/**
46 * set_update_marker - set update marker. 47 * set_update_marker - set update marker.
47 * @ubi: UBI device description object 48 * @ubi: UBI device description object
48 * @vol_id: volume ID 49 * @vol: volume description object
49 * 50 *
50 * This function sets the update marker flag for volume @vol_id. Returns zero 51 * This function sets the update marker flag for volume @vol. Returns zero
51 * in case of success and a negative error code in case of failure. 52 * in case of success and a negative error code in case of failure.
52 */ 53 */
53static int set_update_marker(struct ubi_device *ubi, int vol_id) 54static int set_update_marker(struct ubi_device *ubi, struct ubi_volume *vol)
54{ 55{
55 int err; 56 int err;
56 struct ubi_vtbl_record vtbl_rec; 57 struct ubi_vtbl_record vtbl_rec;
57 struct ubi_volume *vol = ubi->volumes[vol_id];
58 58
59 dbg_msg("set update marker for volume %d", vol_id); 59 dbg_msg("set update marker for volume %d", vol->vol_id);
60 60
61 if (vol->upd_marker) { 61 if (vol->upd_marker) {
62 ubi_assert(ubi->vtbl[vol_id].upd_marker); 62 ubi_assert(ubi->vtbl[vol->vol_id].upd_marker);
63 dbg_msg("already set"); 63 dbg_msg("already set");
64 return 0; 64 return 0;
65 } 65 }
66 66
67 memcpy(&vtbl_rec, &ubi->vtbl[vol_id], sizeof(struct ubi_vtbl_record)); 67 memcpy(&vtbl_rec, &ubi->vtbl[vol->vol_id],
68 sizeof(struct ubi_vtbl_record));
68 vtbl_rec.upd_marker = 1; 69 vtbl_rec.upd_marker = 1;
69 70
70 mutex_lock(&ubi->volumes_mutex); 71 mutex_lock(&ubi->volumes_mutex);
71 err = ubi_change_vtbl_record(ubi, vol_id, &vtbl_rec); 72 err = ubi_change_vtbl_record(ubi, vol->vol_id, &vtbl_rec);
72 mutex_unlock(&ubi->volumes_mutex); 73 mutex_unlock(&ubi->volumes_mutex);
73 vol->upd_marker = 1; 74 vol->upd_marker = 1;
74 return err; 75 return err;
@@ -77,23 +78,24 @@ static int set_update_marker(struct ubi_device *ubi, int vol_id)
77/** 78/**
78 * clear_update_marker - clear update marker. 79 * clear_update_marker - clear update marker.
79 * @ubi: UBI device description object 80 * @ubi: UBI device description object
80 * @vol_id: volume ID 81 * @vol: volume description object
81 * @bytes: new data size in bytes 82 * @bytes: new data size in bytes
82 * 83 *
83 * This function clears the update marker for volume @vol_id, sets new volume 84 * This function clears the update marker for volume @vol, sets new volume
84 * data size and clears the "corrupted" flag (static volumes only). Returns 85 * data size and clears the "corrupted" flag (static volumes only). Returns
85 * zero in case of success and a negative error code in case of failure. 86 * zero in case of success and a negative error code in case of failure.
86 */ 87 */
87static int clear_update_marker(struct ubi_device *ubi, int vol_id, long long bytes) 88static int clear_update_marker(struct ubi_device *ubi, struct ubi_volume *vol,
89 long long bytes)
88{ 90{
89 int err; 91 int err;
90 uint64_t tmp; 92 uint64_t tmp;
91 struct ubi_vtbl_record vtbl_rec; 93 struct ubi_vtbl_record vtbl_rec;
92 struct ubi_volume *vol = ubi->volumes[vol_id];
93 94
94 dbg_msg("clear update marker for volume %d", vol_id); 95 dbg_msg("clear update marker for volume %d", vol->vol_id);
95 96
96 memcpy(&vtbl_rec, &ubi->vtbl[vol_id], sizeof(struct ubi_vtbl_record)); 97 memcpy(&vtbl_rec, &ubi->vtbl[vol->vol_id],
98 sizeof(struct ubi_vtbl_record));
97 ubi_assert(vol->upd_marker && vtbl_rec.upd_marker); 99 ubi_assert(vol->upd_marker && vtbl_rec.upd_marker);
98 vtbl_rec.upd_marker = 0; 100 vtbl_rec.upd_marker = 0;
99 101
@@ -109,7 +111,7 @@ static int clear_update_marker(struct ubi_device *ubi, int vol_id, long long byt
109 } 111 }
110 112
111 mutex_lock(&ubi->volumes_mutex); 113 mutex_lock(&ubi->volumes_mutex);
112 err = ubi_change_vtbl_record(ubi, vol_id, &vtbl_rec); 114 err = ubi_change_vtbl_record(ubi, vol->vol_id, &vtbl_rec);
113 mutex_unlock(&ubi->volumes_mutex); 115 mutex_unlock(&ubi->volumes_mutex);
114 vol->upd_marker = 0; 116 vol->upd_marker = 0;
115 return err; 117 return err;
@@ -118,23 +120,24 @@ static int clear_update_marker(struct ubi_device *ubi, int vol_id, long long byt
118/** 120/**
119 * ubi_start_update - start volume update. 121 * ubi_start_update - start volume update.
120 * @ubi: UBI device description object 122 * @ubi: UBI device description object
121 * @vol_id: volume ID 123 * @vol: volume description object
122 * @bytes: update bytes 124 * @bytes: update bytes
123 * 125 *
124 * This function starts volume update operation. If @bytes is zero, the volume 126 * This function starts volume update operation. If @bytes is zero, the volume
125 * is just wiped out. Returns zero in case of success and a negative error code 127 * is just wiped out. Returns zero in case of success and a negative error code
126 * in case of failure. 128 * in case of failure.
127 */ 129 */
128int ubi_start_update(struct ubi_device *ubi, int vol_id, long long bytes) 130int ubi_start_update(struct ubi_device *ubi, struct ubi_volume *vol,
131 long long bytes)
129{ 132{
130 int i, err; 133 int i, err;
131 uint64_t tmp; 134 uint64_t tmp;
132 struct ubi_volume *vol = ubi->volumes[vol_id];
133 135
134 dbg_msg("start update of volume %d, %llu bytes", vol_id, bytes); 136 dbg_msg("start update of volume %d, %llu bytes", vol->vol_id, bytes);
137 ubi_assert(!vol->updating && !vol->changing_leb);
135 vol->updating = 1; 138 vol->updating = 1;
136 139
137 err = set_update_marker(ubi, vol_id); 140 err = set_update_marker(ubi, vol);
138 if (err) 141 if (err)
139 return err; 142 return err;
140 143
@@ -146,7 +149,7 @@ int ubi_start_update(struct ubi_device *ubi, int vol_id, long long bytes)
146 } 149 }
147 150
148 if (bytes == 0) { 151 if (bytes == 0) {
149 err = clear_update_marker(ubi, vol_id, 0); 152 err = clear_update_marker(ubi, vol, 0);
150 if (err) 153 if (err)
151 return err; 154 return err;
152 err = ubi_wl_flush(ubi); 155 err = ubi_wl_flush(ubi);
@@ -167,9 +170,42 @@ int ubi_start_update(struct ubi_device *ubi, int vol_id, long long bytes)
167} 170}
168 171
169/** 172/**
173 * ubi_start_leb_change - start atomic LEB change.
174 * @ubi: UBI device description object
175 * @vol: volume description object
176 * @req: operation request
177 *
178 * This function starts atomic LEB change operation. Returns zero in case of
179 * success and a negative error code in case of failure.
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_msg("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 req->dtype);
191
192 vol->upd_bytes = req->bytes;
193 vol->upd_received = 0;
194 vol->changing_leb = 1;
195 vol->ch_lnum = req->lnum;
196 vol->ch_dtype = req->dtype;
197
198 vol->upd_buf = vmalloc(req->bytes);
199 if (!vol->upd_buf)
200 return -ENOMEM;
201
202 return 0;
203}
204
205/**
170 * write_leb - write update data. 206 * write_leb - write update data.
171 * @ubi: UBI device description object 207 * @ubi: UBI device description object
172 * @vol_id: volume ID 208 * @vol: volume description object
173 * @lnum: logical eraseblock number 209 * @lnum: logical eraseblock number
174 * @buf: data to write 210 * @buf: data to write
175 * @len: data size 211 * @len: data size
@@ -195,25 +231,22 @@ int ubi_start_update(struct ubi_device *ubi, int vol_id, long long bytes)
195 * This function returns zero in case of success and a negative error code in 231 * This function returns zero in case of success and a negative error code in
196 * case of failure. 232 * case of failure.
197 */ 233 */
198static int write_leb(struct ubi_device *ubi, int vol_id, int lnum, void *buf, 234static int write_leb(struct ubi_device *ubi, struct ubi_volume *vol, int lnum,
199 int len, int used_ebs) 235 void *buf, int len, int used_ebs)
200{ 236{
201 int err, l; 237 int err;
202 struct ubi_volume *vol = ubi->volumes[vol_id];
203 238
204 if (vol->vol_type == UBI_DYNAMIC_VOLUME) { 239 if (vol->vol_type == UBI_DYNAMIC_VOLUME) {
205 l = ALIGN(len, ubi->min_io_size); 240 len = ALIGN(len, ubi->min_io_size);
206 memset(buf + len, 0xFF, l - len); 241 memset(buf + len, 0xFF, len - len);
207 242
208 l = ubi_calc_data_len(ubi, buf, l); 243 len = ubi_calc_data_len(ubi, buf, len);
209 if (l == 0) { 244 if (len == 0) {
210 dbg_msg("all %d bytes contain 0xFF - skip", len); 245 dbg_msg("all %d bytes contain 0xFF - skip", len);
211 return 0; 246 return 0;
212 } 247 }
213 if (len != l)
214 dbg_msg("skip last %d bytes (0xFF)", len - l);
215 248
216 err = ubi_eba_write_leb(ubi, vol, lnum, buf, 0, l, UBI_UNKNOWN); 249 err = ubi_eba_write_leb(ubi, vol, lnum, buf, 0, len, UBI_UNKNOWN);
217 } else { 250 } else {
218 /* 251 /*
219 * When writing static volume, and this is the last logical 252 * When writing static volume, and this is the last logical
@@ -239,16 +272,15 @@ static int write_leb(struct ubi_device *ubi, int vol_id, int lnum, void *buf,
239 * @count: how much bytes to write 272 * @count: how much bytes to write
240 * 273 *
241 * This function writes more data to the volume which is being updated. It may 274 * This function writes more data to the volume which is being updated. It may
242 * be called arbitrary number of times until all of the update data arrive. 275 * be called arbitrary number of times until all the update data arriveis. This
243 * This function returns %0 in case of success, number of bytes written during 276 * function returns %0 in case of success, number of bytes written during the
244 * the last call if the whole volume update was successfully finished, and a 277 * last call if the whole volume update has been successfully finished, and a
245 * negative error code in case of failure. 278 * negative error code in case of failure.
246 */ 279 */
247int ubi_more_update_data(struct ubi_device *ubi, int vol_id, 280int ubi_more_update_data(struct ubi_device *ubi, struct ubi_volume *vol,
248 const void __user *buf, int count) 281 const void __user *buf, int count)
249{ 282{
250 uint64_t tmp; 283 uint64_t tmp;
251 struct ubi_volume *vol = ubi->volumes[vol_id];
252 int lnum, offs, err = 0, len, to_write = count; 284 int lnum, offs, err = 0, len, to_write = count;
253 285
254 dbg_msg("write %d of %lld bytes, %lld already passed", 286 dbg_msg("write %d of %lld bytes, %lld already passed",
@@ -293,8 +325,8 @@ int ubi_more_update_data(struct ubi_device *ubi, int vol_id,
293 * is the last chunk, it's time to flush the buffer. 325 * is the last chunk, it's time to flush the buffer.
294 */ 326 */
295 ubi_assert(flush_len <= vol->usable_leb_size); 327 ubi_assert(flush_len <= vol->usable_leb_size);
296 err = write_leb(ubi, vol_id, lnum, vol->upd_buf, 328 err = write_leb(ubi, vol, lnum, vol->upd_buf, flush_len,
297 flush_len, vol->upd_ebs); 329 vol->upd_ebs);
298 if (err) 330 if (err)
299 return err; 331 return err;
300 } 332 }
@@ -321,8 +353,8 @@ int ubi_more_update_data(struct ubi_device *ubi, int vol_id,
321 353
322 if (len == vol->usable_leb_size || 354 if (len == vol->usable_leb_size ||
323 vol->upd_received + len == vol->upd_bytes) { 355 vol->upd_received + len == vol->upd_bytes) {
324 err = write_leb(ubi, vol_id, lnum, vol->upd_buf, len, 356 err = write_leb(ubi, vol, lnum, vol->upd_buf,
325 vol->upd_ebs); 357 len, vol->upd_ebs);
326 if (err) 358 if (err)
327 break; 359 break;
328 } 360 }
@@ -336,16 +368,70 @@ int ubi_more_update_data(struct ubi_device *ubi, int vol_id,
336 ubi_assert(vol->upd_received <= vol->upd_bytes); 368 ubi_assert(vol->upd_received <= vol->upd_bytes);
337 if (vol->upd_received == vol->upd_bytes) { 369 if (vol->upd_received == vol->upd_bytes) {
338 /* The update is finished, clear the update marker */ 370 /* The update is finished, clear the update marker */
339 err = clear_update_marker(ubi, vol_id, vol->upd_bytes); 371 err = clear_update_marker(ubi, vol, vol->upd_bytes);
340 if (err) 372 if (err)
341 return err; 373 return err;
342 err = ubi_wl_flush(ubi); 374 err = ubi_wl_flush(ubi);
343 if (err == 0) { 375 if (err == 0) {
376 vol->updating = 0;
344 err = to_write; 377 err = to_write;
345 vfree(vol->upd_buf); 378 vfree(vol->upd_buf);
346 vol->updating = 0;
347 } 379 }
348 } 380 }
349 381
350 return err; 382 return err;
351} 383}
384
385/**
386 * ubi_more_leb_change_data - accept more data for atomic LEB change.
387 * @vol: volume description object
388 * @buf: write data (user-space memory buffer)
389 * @count: how much bytes to write
390 *
391 * This function accepts more data to the volume which is being under the
392 * "atomic LEB change" operation. It may be called arbitrary number of times
393 * until all data arrives. This function returns %0 in case of success, number
394 * of bytes written during the last call if the whole "atomic LEB change"
395 * operation has been successfully finished, and a negative error code in case
396 * of failure.
397 */
398int ubi_more_leb_change_data(struct ubi_device *ubi, struct ubi_volume *vol,
399 const void __user *buf, int count)
400{
401 int err;
402
403 dbg_msg("write %d of %lld bytes, %lld already passed",
404 count, vol->upd_bytes, vol->upd_received);
405
406 if (ubi->ro_mode)
407 return -EROFS;
408
409 if (vol->upd_received + count > vol->upd_bytes)
410 count = vol->upd_bytes - vol->upd_received;
411
412 err = copy_from_user(vol->upd_buf + vol->upd_received, buf, count);
413 if (err)
414 return -EFAULT;
415
416 vol->upd_received += count;
417
418 if (vol->upd_received == vol->upd_bytes) {
419 int len = ALIGN((int)vol->upd_bytes, ubi->min_io_size);
420
421 memset(vol->upd_buf + vol->upd_bytes, 0xFF, len - vol->upd_bytes);
422 len = ubi_calc_data_len(ubi, vol->upd_buf, len);
423 err = ubi_eba_atomic_leb_change(ubi, vol, vol->ch_lnum,
424 vol->upd_buf, len, UBI_UNKNOWN);
425 if (err)
426 return err;
427 }
428
429 ubi_assert(vol->upd_received <= vol->upd_bytes);
430 if (vol->upd_received == vol->upd_bytes) {
431 vol->changing_leb = 0;
432 err = count;
433 vfree(vol->upd_buf);
434 }
435
436 return err;
437}