Loading fs/ubifs/recovery.c +26 −0 Original line number Diff line number Diff line Loading @@ -317,6 +317,32 @@ int ubifs_recover_master_node(struct ubifs_info *c) goto out_free; } memcpy(c->rcvrd_mst_node, c->mst_node, UBIFS_MST_NODE_SZ); /* * We had to recover the master node, which means there was an * unclean reboot. However, it is possible that the master node * is clean at this point, i.e., %UBIFS_MST_DIRTY is not set. * E.g., consider the following chain of events: * * 1. UBIFS was cleanly unmounted, so the master node is clean * 2. UBIFS is being mounted R/W and starts changing the master * node in the first (%UBIFS_MST_LNUM). A power cut happens, * so this LEB ends up with some amount of garbage at the * end. * 3. UBIFS is being mounted R/O. We reach this place and * recover the master node from the second LEB * (%UBIFS_MST_LNUM + 1). But we cannot update the media * because we are being mounted R/O. We have to defer the * operation. * 4. However, this master node (@c->mst_node) is marked as * clean (since the step 1). And if we just return, the * mount code will be confused and won't recover the master * node when it is re-mounter R/W later. * * Thus, to force the recovery by marking the master node as * dirty. */ c->mst_node->flags |= cpu_to_le32(UBIFS_MST_DIRTY); } else { /* Write the recovered master node */ c->max_sqnum = le64_to_cpu(mst->ch.sqnum) - 1; Loading fs/ubifs/super.c +21 −8 Original line number Diff line number Diff line Loading @@ -1671,14 +1671,25 @@ static int ubifs_remount_rw(struct ubifs_info *c) if (err) goto out; dbg_gen("re-mounted read-write"); c->remounting_rw = 0; if (c->need_recovery) { c->need_recovery = 0; ubifs_msg("deferred recovery completed"); } dbg_gen("re-mounted read-write"); c->remounting_rw = 0; } else { /* * Do not run the debugging space check if the were doing * recovery, because when we saved the information we had the * file-system in a state where the TNC and lprops has been * modified in memory, but all the I/O operations (including a * commit) were deferred. So the file-system was in * "non-committed" state. Now the file-system is in committed * state, and of course the amount of free space will change * because, for example, the old index size was imprecise. */ err = dbg_check_space_info(c); } mutex_unlock(&c->umount_mutex); return err; Loading Loading @@ -1761,10 +1772,12 @@ static void ubifs_put_super(struct super_block *sb) * of the media. For example, there will be dirty inodes if we failed * to write them back because of I/O errors. */ if (!c->ro_error) { ubifs_assert(atomic_long_read(&c->dirty_pg_cnt) == 0); ubifs_assert(c->budg_idx_growth == 0); ubifs_assert(c->budg_dd_growth == 0); ubifs_assert(c->budg_data_growth == 0); } /* * The 'c->umount_lock' prevents races between UBIFS memory shrinker Loading Loading
fs/ubifs/recovery.c +26 −0 Original line number Diff line number Diff line Loading @@ -317,6 +317,32 @@ int ubifs_recover_master_node(struct ubifs_info *c) goto out_free; } memcpy(c->rcvrd_mst_node, c->mst_node, UBIFS_MST_NODE_SZ); /* * We had to recover the master node, which means there was an * unclean reboot. However, it is possible that the master node * is clean at this point, i.e., %UBIFS_MST_DIRTY is not set. * E.g., consider the following chain of events: * * 1. UBIFS was cleanly unmounted, so the master node is clean * 2. UBIFS is being mounted R/W and starts changing the master * node in the first (%UBIFS_MST_LNUM). A power cut happens, * so this LEB ends up with some amount of garbage at the * end. * 3. UBIFS is being mounted R/O. We reach this place and * recover the master node from the second LEB * (%UBIFS_MST_LNUM + 1). But we cannot update the media * because we are being mounted R/O. We have to defer the * operation. * 4. However, this master node (@c->mst_node) is marked as * clean (since the step 1). And if we just return, the * mount code will be confused and won't recover the master * node when it is re-mounter R/W later. * * Thus, to force the recovery by marking the master node as * dirty. */ c->mst_node->flags |= cpu_to_le32(UBIFS_MST_DIRTY); } else { /* Write the recovered master node */ c->max_sqnum = le64_to_cpu(mst->ch.sqnum) - 1; Loading
fs/ubifs/super.c +21 −8 Original line number Diff line number Diff line Loading @@ -1671,14 +1671,25 @@ static int ubifs_remount_rw(struct ubifs_info *c) if (err) goto out; dbg_gen("re-mounted read-write"); c->remounting_rw = 0; if (c->need_recovery) { c->need_recovery = 0; ubifs_msg("deferred recovery completed"); } dbg_gen("re-mounted read-write"); c->remounting_rw = 0; } else { /* * Do not run the debugging space check if the were doing * recovery, because when we saved the information we had the * file-system in a state where the TNC and lprops has been * modified in memory, but all the I/O operations (including a * commit) were deferred. So the file-system was in * "non-committed" state. Now the file-system is in committed * state, and of course the amount of free space will change * because, for example, the old index size was imprecise. */ err = dbg_check_space_info(c); } mutex_unlock(&c->umount_mutex); return err; Loading Loading @@ -1761,10 +1772,12 @@ static void ubifs_put_super(struct super_block *sb) * of the media. For example, there will be dirty inodes if we failed * to write them back because of I/O errors. */ if (!c->ro_error) { ubifs_assert(atomic_long_read(&c->dirty_pg_cnt) == 0); ubifs_assert(c->budg_idx_growth == 0); ubifs_assert(c->budg_dd_growth == 0); ubifs_assert(c->budg_data_growth == 0); } /* * The 'c->umount_lock' prevents races between UBIFS memory shrinker Loading