aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mtd/ubi
diff options
context:
space:
mode:
authorArtem Bityutskiy <Artem.Bityutskiy@nokia.com>2008-12-04 13:52:44 -0500
committerArtem Bityutskiy <Artem.Bityutskiy@nokia.com>2008-12-05 06:46:49 -0500
commit4df581f3dc6a91a63b9965ac8bdb47d8db294e37 (patch)
treeddd44e9b424c999b615185c6c6d34c1d2983f6f4 /drivers/mtd/ubi
parented45819f315b5a8844b5bfce881a18e9f3a055e7 (diff)
UBI: fix deadlock
We cannot call 'ubi_wl_get_peb()' with @ubi->buf_mutex locked, because 'ubi_wl_get_peb()' may force erasure, which, in turn, may call 'torture_peb()' which also locks the @ubi->buf_mutex and deadlocks. Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy@nokia.com>
Diffstat (limited to 'drivers/mtd/ubi')
-rw-r--r--drivers/mtd/ubi/eba.c14
1 files changed, 7 insertions, 7 deletions
diff --git a/drivers/mtd/ubi/eba.c b/drivers/mtd/ubi/eba.c
index d8966bae0e0b..2e4d6bf94582 100644
--- a/drivers/mtd/ubi/eba.c
+++ b/drivers/mtd/ubi/eba.c
@@ -504,12 +504,9 @@ static int recover_peb(struct ubi_device *ubi, int pnum, int vol_id, int lnum,
504 if (!vid_hdr) 504 if (!vid_hdr)
505 return -ENOMEM; 505 return -ENOMEM;
506 506
507 mutex_lock(&ubi->buf_mutex);
508
509retry: 507retry:
510 new_pnum = ubi_wl_get_peb(ubi, UBI_UNKNOWN); 508 new_pnum = ubi_wl_get_peb(ubi, UBI_UNKNOWN);
511 if (new_pnum < 0) { 509 if (new_pnum < 0) {
512 mutex_unlock(&ubi->buf_mutex);
513 ubi_free_vid_hdr(ubi, vid_hdr); 510 ubi_free_vid_hdr(ubi, vid_hdr);
514 return new_pnum; 511 return new_pnum;
515 } 512 }
@@ -529,20 +526,23 @@ retry:
529 goto write_error; 526 goto write_error;
530 527
531 data_size = offset + len; 528 data_size = offset + len;
529 mutex_lock(&ubi->buf_mutex);
532 memset(ubi->peb_buf1 + offset, 0xFF, len); 530 memset(ubi->peb_buf1 + offset, 0xFF, len);
533 531
534 /* Read everything before the area where the write failure happened */ 532 /* Read everything before the area where the write failure happened */
535 if (offset > 0) { 533 if (offset > 0) {
536 err = ubi_io_read_data(ubi, ubi->peb_buf1, pnum, 0, offset); 534 err = ubi_io_read_data(ubi, ubi->peb_buf1, pnum, 0, offset);
537 if (err && err != UBI_IO_BITFLIPS) 535 if (err && err != UBI_IO_BITFLIPS)
538 goto out_put; 536 goto out_unlock;
539 } 537 }
540 538
541 memcpy(ubi->peb_buf1 + offset, buf, len); 539 memcpy(ubi->peb_buf1 + offset, buf, len);
542 540
543 err = ubi_io_write_data(ubi, ubi->peb_buf1, new_pnum, 0, data_size); 541 err = ubi_io_write_data(ubi, ubi->peb_buf1, new_pnum, 0, data_size);
544 if (err) 542 if (err) {
543 mutex_unlock(&ubi->buf_mutex);
545 goto write_error; 544 goto write_error;
545 }
546 546
547 mutex_unlock(&ubi->buf_mutex); 547 mutex_unlock(&ubi->buf_mutex);
548 ubi_free_vid_hdr(ubi, vid_hdr); 548 ubi_free_vid_hdr(ubi, vid_hdr);
@@ -553,8 +553,9 @@ retry:
553 ubi_msg("data was successfully recovered"); 553 ubi_msg("data was successfully recovered");
554 return 0; 554 return 0;
555 555
556out_put: 556out_unlock:
557 mutex_unlock(&ubi->buf_mutex); 557 mutex_unlock(&ubi->buf_mutex);
558out_put:
558 ubi_wl_put_peb(ubi, new_pnum, 1); 559 ubi_wl_put_peb(ubi, new_pnum, 1);
559 ubi_free_vid_hdr(ubi, vid_hdr); 560 ubi_free_vid_hdr(ubi, vid_hdr);
560 return err; 561 return err;
@@ -567,7 +568,6 @@ write_error:
567 ubi_warn("failed to write to PEB %d", new_pnum); 568 ubi_warn("failed to write to PEB %d", new_pnum);
568 ubi_wl_put_peb(ubi, new_pnum, 1); 569 ubi_wl_put_peb(ubi, new_pnum, 1);
569 if (++tries > UBI_IO_RETRIES) { 570 if (++tries > UBI_IO_RETRIES) {
570 mutex_unlock(&ubi->buf_mutex);
571 ubi_free_vid_hdr(ubi, vid_hdr); 571 ubi_free_vid_hdr(ubi, vid_hdr);
572 return err; 572 return err;
573 } 573 }