aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mtd/ubi/cdev.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mtd/ubi/cdev.c')
-rw-r--r--drivers/mtd/ubi/cdev.c82
1 files changed, 64 insertions, 18 deletions
diff --git a/drivers/mtd/ubi/cdev.c b/drivers/mtd/ubi/cdev.c
index 5ec13dc4705b..9d6aae5449b6 100644
--- a/drivers/mtd/ubi/cdev.c
+++ b/drivers/mtd/ubi/cdev.c
@@ -132,8 +132,15 @@ static int vol_cdev_release(struct inode *inode, struct file *file)
132 if (vol->updating) { 132 if (vol->updating) {
133 ubi_warn("update of volume %d not finished, volume is damaged", 133 ubi_warn("update of volume %d not finished, volume is damaged",
134 vol->vol_id); 134 vol->vol_id);
135 ubi_assert(!vol->changing_leb);
135 vol->updating = 0; 136 vol->updating = 0;
136 vfree(vol->upd_buf); 137 vfree(vol->upd_buf);
138 } else if (vol->changing_leb) {
139 dbg_msg("only %lld of %lld bytes received for atomic LEB change"
140 " for volume %d:%d, cancel", vol->upd_received,
141 vol->upd_bytes, vol->ubi->ubi_num, vol->vol_id);
142 vol->changing_leb = 0;
143 vfree(vol->upd_buf);
137 } 144 }
138 145
139 ubi_close_volume(desc); 146 ubi_close_volume(desc);
@@ -184,13 +191,13 @@ static ssize_t vol_cdev_read(struct file *file, __user char *buf, size_t count,
184 struct ubi_volume_desc *desc = file->private_data; 191 struct ubi_volume_desc *desc = file->private_data;
185 struct ubi_volume *vol = desc->vol; 192 struct ubi_volume *vol = desc->vol;
186 struct ubi_device *ubi = vol->ubi; 193 struct ubi_device *ubi = vol->ubi;
187 int err, lnum, off, len, vol_id = desc->vol->vol_id, tbuf_size; 194 int err, lnum, off, len, tbuf_size;
188 size_t count_save = count; 195 size_t count_save = count;
189 void *tbuf; 196 void *tbuf;
190 uint64_t tmp; 197 uint64_t tmp;
191 198
192 dbg_msg("read %zd bytes from offset %lld of volume %d", 199 dbg_msg("read %zd bytes from offset %lld of volume %d",
193 count, *offp, vol_id); 200 count, *offp, vol->vol_id);
194 201
195 if (vol->updating) { 202 if (vol->updating) {
196 dbg_err("updating"); 203 dbg_err("updating");
@@ -204,7 +211,7 @@ static ssize_t vol_cdev_read(struct file *file, __user char *buf, size_t count,
204 return 0; 211 return 0;
205 212
206 if (vol->corrupted) 213 if (vol->corrupted)
207 dbg_msg("read from corrupted volume %d", vol_id); 214 dbg_msg("read from corrupted volume %d", vol->vol_id);
208 215
209 if (*offp + count > vol->used_bytes) 216 if (*offp + count > vol->used_bytes)
210 count_save = count = vol->used_bytes - *offp; 217 count_save = count = vol->used_bytes - *offp;
@@ -274,7 +281,7 @@ static ssize_t vol_cdev_direct_write(struct file *file, const char __user *buf,
274 uint64_t tmp; 281 uint64_t tmp;
275 282
276 dbg_msg("requested: write %zd bytes to offset %lld of volume %u", 283 dbg_msg("requested: write %zd bytes to offset %lld of volume %u",
277 count, *offp, desc->vol->vol_id); 284 count, *offp, vol->vol_id);
278 285
279 if (vol->vol_type == UBI_STATIC_VOLUME) 286 if (vol->vol_type == UBI_STATIC_VOLUME)
280 return -EROFS; 287 return -EROFS;
@@ -351,23 +358,32 @@ static ssize_t vol_cdev_write(struct file *file, const char __user *buf,
351 struct ubi_volume *vol = desc->vol; 358 struct ubi_volume *vol = desc->vol;
352 struct ubi_device *ubi = vol->ubi; 359 struct ubi_device *ubi = vol->ubi;
353 360
354 if (!vol->updating) 361 if (!vol->updating && !vol->changing_leb)
355 return vol_cdev_direct_write(file, buf, count, offp); 362 return vol_cdev_direct_write(file, buf, count, offp);
356 363
357 err = ubi_more_update_data(ubi, vol->vol_id, buf, count); 364 if (vol->updating)
365 err = ubi_more_update_data(ubi, vol, buf, count);
366 else
367 err = ubi_more_leb_change_data(ubi, vol, buf, count);
368
358 if (err < 0) { 369 if (err < 0) {
359 ubi_err("cannot write %zd bytes of update data, error %d", 370 ubi_err("cannot accept more %zd bytes of data, error %d",
360 count, err); 371 count, err);
361 return err; 372 return err;
362 } 373 }
363 374
364 if (err) { 375 if (err) {
365 /* 376 /*
366 * Update is finished, @err contains number of actually written 377 * The operation is finished, @err contains number of actually
367 * bytes now. 378 * written bytes.
368 */ 379 */
369 count = err; 380 count = err;
370 381
382 if (vol->changing_leb) {
383 revoke_exclusive(desc, UBI_READWRITE);
384 return count;
385 }
386
371 err = ubi_check_volume(ubi, vol->vol_id); 387 err = ubi_check_volume(ubi, vol->vol_id);
372 if (err < 0) 388 if (err < 0)
373 return err; 389 return err;
@@ -382,7 +398,6 @@ static ssize_t vol_cdev_write(struct file *file, const char __user *buf,
382 revoke_exclusive(desc, UBI_READWRITE); 398 revoke_exclusive(desc, UBI_READWRITE);
383 } 399 }
384 400
385 *offp += count;
386 return count; 401 return count;
387} 402}
388 403
@@ -427,11 +442,46 @@ static int vol_cdev_ioctl(struct inode *inode, struct file *file,
427 if (err < 0) 442 if (err < 0)
428 break; 443 break;
429 444
430 err = ubi_start_update(ubi, vol->vol_id, bytes); 445 err = ubi_start_update(ubi, vol, bytes);
431 if (bytes == 0) 446 if (bytes == 0)
432 revoke_exclusive(desc, UBI_READWRITE); 447 revoke_exclusive(desc, UBI_READWRITE);
448 break;
449 }
450
451 /* Atomic logical eraseblock change command */
452 case UBI_IOCEBCH:
453 {
454 struct ubi_leb_change_req req;
455
456 err = copy_from_user(&req, argp,
457 sizeof(struct ubi_leb_change_req));
458 if (err) {
459 err = -EFAULT;
460 break;
461 }
462
463 if (desc->mode == UBI_READONLY ||
464 vol->vol_type == UBI_STATIC_VOLUME) {
465 err = -EROFS;
466 break;
467 }
468
469 /* Validate the request */
470 err = -EINVAL;
471 if (req.lnum < 0 || req.lnum >= vol->reserved_pebs ||
472 req.bytes < 0 || req.lnum >= vol->usable_leb_size)
473 break;
474 if (req.dtype != UBI_LONGTERM && req.dtype != UBI_SHORTTERM &&
475 req.dtype != UBI_UNKNOWN)
476 break;
477
478 err = get_exclusive(desc);
479 if (err < 0)
480 break;
433 481
434 file->f_pos = 0; 482 err = ubi_start_leb_change(ubi, vol, &req);
483 if (req.bytes == 0)
484 revoke_exclusive(desc, UBI_READWRITE);
435 break; 485 break;
436 } 486 }
437 487
@@ -447,7 +497,8 @@ static int vol_cdev_ioctl(struct inode *inode, struct file *file,
447 break; 497 break;
448 } 498 }
449 499
450 if (desc->mode == UBI_READONLY) { 500 if (desc->mode == UBI_READONLY ||
501 vol->vol_type == UBI_STATIC_VOLUME) {
451 err = -EROFS; 502 err = -EROFS;
452 break; 503 break;
453 } 504 }
@@ -457,11 +508,6 @@ static int vol_cdev_ioctl(struct inode *inode, struct file *file,
457 break; 508 break;
458 } 509 }
459 510
460 if (vol->vol_type != UBI_DYNAMIC_VOLUME) {
461 err = -EROFS;
462 break;
463 }
464
465 dbg_msg("erase LEB %d:%d", vol->vol_id, lnum); 511 dbg_msg("erase LEB %d:%d", vol->vol_id, lnum);
466 err = ubi_eba_unmap_leb(ubi, vol, lnum); 512 err = ubi_eba_unmap_leb(ubi, vol, lnum);
467 if (err) 513 if (err)