aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ubifs
diff options
context:
space:
mode:
authorArtem Bityutskiy <Artem.Bityutskiy@nokia.com>2009-01-23 07:17:36 -0500
committerArtem Bityutskiy <Artem.Bityutskiy@nokia.com>2009-01-26 05:54:11 -0500
commite4d9b6cbfc98d696a28d2c24a3d49768695811ee (patch)
tree5d76848d68add2830efa29b16425e2f07b4f1967 /fs/ubifs
parent82c1593cad3dfc97661764c8bc62aa1a416e9ea8 (diff)
UBIFS: fix LEB list freeing
When freeing the c->idx_lebs list, we have to release the LEBs as well, because we might be called from mount to read-only mode code. Otherwise the LEBs stay taken forever, which may cause problems when we re-mount back ro RW mode. Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy@nokia.com>
Diffstat (limited to 'fs/ubifs')
-rw-r--r--fs/ubifs/gc.c16
-rw-r--r--fs/ubifs/lprops.c8
-rw-r--r--fs/ubifs/super.c42
-rw-r--r--fs/ubifs/ubifs.h2
4 files changed, 48 insertions, 20 deletions
diff --git a/fs/ubifs/gc.c b/fs/ubifs/gc.c
index b2e5f1133377..9760154d874b 100644
--- a/fs/ubifs/gc.c
+++ b/fs/ubifs/gc.c
@@ -830,21 +830,29 @@ out:
830 * ubifs_destroy_idx_gc - destroy idx_gc list. 830 * ubifs_destroy_idx_gc - destroy idx_gc list.
831 * @c: UBIFS file-system description object 831 * @c: UBIFS file-system description object
832 * 832 *
833 * This function destroys the idx_gc list. It is called when unmounting or 833 * This function destroys the @c->idx_gc list. It is called when unmounting or
834 * remounting read-only so locks are not needed. 834 * remounting read-only so locks are not needed. Returns zero in case of
835 * success and a negative error code in case of failure.
835 */ 836 */
836void ubifs_destroy_idx_gc(struct ubifs_info *c) 837int ubifs_destroy_idx_gc(struct ubifs_info *c)
837{ 838{
839 int ret = 0;
840
838 while (!list_empty(&c->idx_gc)) { 841 while (!list_empty(&c->idx_gc)) {
842 int err;
839 struct ubifs_gced_idx_leb *idx_gc; 843 struct ubifs_gced_idx_leb *idx_gc;
840 844
841 idx_gc = list_entry(c->idx_gc.next, struct ubifs_gced_idx_leb, 845 idx_gc = list_entry(c->idx_gc.next, struct ubifs_gced_idx_leb,
842 list); 846 list);
843 c->idx_gc_cnt -= 1; 847 err = ubifs_change_one_lp(c, idx_gc->lnum, LPROPS_NC,
848 LPROPS_NC, 0, LPROPS_TAKEN, -1);
849 if (err && !ret)
850 ret = err;
844 list_del(&idx_gc->list); 851 list_del(&idx_gc->list);
845 kfree(idx_gc); 852 kfree(idx_gc);
846 } 853 }
847 854
855 return ret;
848} 856}
849 857
850/** 858/**
diff --git a/fs/ubifs/lprops.c b/fs/ubifs/lprops.c
index dfd2bcece27a..68328c59762b 100644
--- a/fs/ubifs/lprops.c
+++ b/fs/ubifs/lprops.c
@@ -678,6 +678,9 @@ int ubifs_change_one_lp(struct ubifs_info *c, int lnum, int free, int dirty,
678 678
679out: 679out:
680 ubifs_release_lprops(c); 680 ubifs_release_lprops(c);
681 if (err)
682 ubifs_err("cannot change properties of LEB %d, error %d",
683 lnum, err);
681 return err; 684 return err;
682} 685}
683 686
@@ -714,6 +717,9 @@ int ubifs_update_one_lp(struct ubifs_info *c, int lnum, int free, int dirty,
714 717
715out: 718out:
716 ubifs_release_lprops(c); 719 ubifs_release_lprops(c);
720 if (err)
721 ubifs_err("cannot update properties of LEB %d, error %d",
722 lnum, err);
717 return err; 723 return err;
718} 724}
719 725
@@ -737,6 +743,8 @@ int ubifs_read_one_lp(struct ubifs_info *c, int lnum, struct ubifs_lprops *lp)
737 lpp = ubifs_lpt_lookup(c, lnum); 743 lpp = ubifs_lpt_lookup(c, lnum);
738 if (IS_ERR(lpp)) { 744 if (IS_ERR(lpp)) {
739 err = PTR_ERR(lpp); 745 err = PTR_ERR(lpp);
746 ubifs_err("cannot read properties of LEB %d, error %d",
747 lnum, err);
740 goto out; 748 goto out;
741 } 749 }
742 750
diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c
index da99da098efd..807bbd3c8b4b 100644
--- a/fs/ubifs/super.c
+++ b/fs/ubifs/super.c
@@ -1469,9 +1469,6 @@ static int ubifs_remount_rw(struct ubifs_info *c)
1469{ 1469{
1470 int err, lnum; 1470 int err, lnum;
1471 1471
1472 if (c->ro_media)
1473 return -EINVAL;
1474
1475 mutex_lock(&c->umount_mutex); 1472 mutex_lock(&c->umount_mutex);
1476 c->remounting_rw = 1; 1473 c->remounting_rw = 1;
1477 c->always_chk_crc = 1; 1474 c->always_chk_crc = 1;
@@ -1605,9 +1602,13 @@ out:
1605 */ 1602 */
1606static void commit_on_unmount(struct ubifs_info *c) 1603static void commit_on_unmount(struct ubifs_info *c)
1607{ 1604{
1608 struct super_block *sb = c->vfs_sb;
1609 long long bud_bytes; 1605 long long bud_bytes;
1610 1606
1607 if (!c->fast_unmount) {
1608 dbg_gen("skip committing - fast unmount enabled");
1609 return;
1610 }
1611
1611 /* 1612 /*
1612 * This function is called before the background thread is stopped, so 1613 * This function is called before the background thread is stopped, so
1613 * we may race with ongoing commit, which means we have to take 1614 * we may race with ongoing commit, which means we have to take
@@ -1617,8 +1618,11 @@ static void commit_on_unmount(struct ubifs_info *c)
1617 bud_bytes = c->bud_bytes; 1618 bud_bytes = c->bud_bytes;
1618 spin_unlock(&c->buds_lock); 1619 spin_unlock(&c->buds_lock);
1619 1620
1620 if (!c->fast_unmount && !(sb->s_flags & MS_RDONLY) && bud_bytes) 1621 if (bud_bytes) {
1622 dbg_gen("run commit");
1621 ubifs_run_commit(c); 1623 ubifs_run_commit(c);
1624 } else
1625 dbg_gen("journal is empty, do not run commit");
1622} 1626}
1623 1627
1624/** 1628/**
@@ -1633,6 +1637,8 @@ static void ubifs_remount_ro(struct ubifs_info *c)
1633 int i, err; 1637 int i, err;
1634 1638
1635 ubifs_assert(!c->need_recovery); 1639 ubifs_assert(!c->need_recovery);
1640 ubifs_assert(!c->ro_media);
1641
1636 commit_on_unmount(c); 1642 commit_on_unmount(c);
1637 1643
1638 mutex_lock(&c->umount_mutex); 1644 mutex_lock(&c->umount_mutex);
@@ -1646,16 +1652,17 @@ static void ubifs_remount_ro(struct ubifs_info *c)
1646 del_timer_sync(&c->jheads[i].wbuf.timer); 1652 del_timer_sync(&c->jheads[i].wbuf.timer);
1647 } 1653 }
1648 1654
1649 if (!c->ro_media) { 1655 c->mst_node->flags &= ~cpu_to_le32(UBIFS_MST_DIRTY);
1650 c->mst_node->flags &= ~cpu_to_le32(UBIFS_MST_DIRTY); 1656 c->mst_node->flags |= cpu_to_le32(UBIFS_MST_NO_ORPHS);
1651 c->mst_node->flags |= cpu_to_le32(UBIFS_MST_NO_ORPHS); 1657 c->mst_node->gc_lnum = cpu_to_le32(c->gc_lnum);
1652 c->mst_node->gc_lnum = cpu_to_le32(c->gc_lnum); 1658 err = ubifs_write_master(c);
1653 err = ubifs_write_master(c); 1659 if (err)
1654 if (err) 1660 ubifs_ro_mode(c, err);
1655 ubifs_ro_mode(c, err); 1661
1656 } 1662 err = ubifs_destroy_idx_gc(c);
1663 if (err)
1664 ubifs_ro_mode(c, err);
1657 1665
1658 ubifs_destroy_idx_gc(c);
1659 free_wbufs(c); 1666 free_wbufs(c);
1660 vfree(c->orph_buf); 1667 vfree(c->orph_buf);
1661 c->orph_buf = NULL; 1668 c->orph_buf = NULL;
@@ -1754,6 +1761,11 @@ static int ubifs_remount_fs(struct super_block *sb, int *flags, char *data)
1754 } 1761 }
1755 1762
1756 if ((sb->s_flags & MS_RDONLY) && !(*flags & MS_RDONLY)) { 1763 if ((sb->s_flags & MS_RDONLY) && !(*flags & MS_RDONLY)) {
1764 if (c->ro_media) {
1765 ubifs_msg("cannot re-mount R/W, UBIFS is working in "
1766 "R/O mode");
1767 return -EINVAL;
1768 }
1757 err = ubifs_remount_rw(c); 1769 err = ubifs_remount_rw(c);
1758 if (err) 1770 if (err)
1759 return err; 1771 return err;
@@ -2044,7 +2056,7 @@ static void ubifs_kill_sb(struct super_block *sb)
2044 * We do 'commit_on_unmount()' here instead of 'ubifs_put_super()' 2056 * We do 'commit_on_unmount()' here instead of 'ubifs_put_super()'
2045 * in order to be outside BKL. 2057 * in order to be outside BKL.
2046 */ 2058 */
2047 if (sb->s_root) 2059 if (sb->s_root && !(sb->s_flags & MS_RDONLY))
2048 commit_on_unmount(c); 2060 commit_on_unmount(c);
2049 /* The un-mount routine is actually done in put_super() */ 2061 /* The un-mount routine is actually done in put_super() */
2050 generic_shutdown_super(sb); 2062 generic_shutdown_super(sb);
diff --git a/fs/ubifs/ubifs.h b/fs/ubifs/ubifs.h
index 2e78d6ac007e..ee9517a7b024 100644
--- a/fs/ubifs/ubifs.h
+++ b/fs/ubifs/ubifs.h
@@ -1593,7 +1593,7 @@ int ubifs_replay_journal(struct ubifs_info *c);
1593int ubifs_garbage_collect(struct ubifs_info *c, int anyway); 1593int ubifs_garbage_collect(struct ubifs_info *c, int anyway);
1594int ubifs_gc_start_commit(struct ubifs_info *c); 1594int ubifs_gc_start_commit(struct ubifs_info *c);
1595int ubifs_gc_end_commit(struct ubifs_info *c); 1595int ubifs_gc_end_commit(struct ubifs_info *c);
1596void ubifs_destroy_idx_gc(struct ubifs_info *c); 1596int ubifs_destroy_idx_gc(struct ubifs_info *c);
1597int ubifs_get_idx_gc_leb(struct ubifs_info *c); 1597int ubifs_get_idx_gc_leb(struct ubifs_info *c);
1598int ubifs_garbage_collect_leb(struct ubifs_info *c, struct ubifs_lprops *lp); 1598int ubifs_garbage_collect_leb(struct ubifs_info *c, struct ubifs_lprops *lp);
1599 1599