Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1f91f48b authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge branch 'for-linus' of git://git.infradead.org/ubifs-2.6

* 'for-linus' of git://git.infradead.org/ubifs-2.6:
  UBIFS: fix master node recovery
  UBIFS: fix false assertion warning in case of I/O failures
  UBIFS: fix false space checking failure
parents 3ba41621 6e0d9fd3
Loading
Loading
Loading
Loading
+26 −0
Original line number Diff line number Diff line
@@ -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;
+21 −8
Original line number Diff line number Diff line
@@ -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;

@@ -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