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

Commit d3d1faf6 authored by Curt Wohlgemuth's avatar Curt Wohlgemuth Committed by Theodore Ts'o
Browse files

ext4: Handle nested ext4_journal_start/stop calls without a journal



This patch fixes a problem with handling nested calls to
ext4_journal_start/ext4_journal_stop, when there is no journal present.

Signed-off-by: default avatarCurt Wohlgemuth <curtw@google.com>
Signed-off-by: default avatar"Theodore Ts'o" <tytso@mit.edu>
parent f3dc272f
Loading
Loading
Loading
Loading
+4 −2
Original line number Original line Diff line number Diff line
@@ -161,11 +161,13 @@ int __ext4_handle_dirty_metadata(const char *where, handle_t *handle,
handle_t *ext4_journal_start_sb(struct super_block *sb, int nblocks);
handle_t *ext4_journal_start_sb(struct super_block *sb, int nblocks);
int __ext4_journal_stop(const char *where, handle_t *handle);
int __ext4_journal_stop(const char *where, handle_t *handle);


#define EXT4_NOJOURNAL_HANDLE	((handle_t *) 0x1)
#define EXT4_NOJOURNAL_MAX_REF_COUNT ((unsigned long) 4096)


/* Note:  Do not use this for NULL handles.  This is only to determine if
 * a properly allocated handle is using a journal or not. */
static inline int ext4_handle_valid(handle_t *handle)
static inline int ext4_handle_valid(handle_t *handle)
{
{
	if (handle == EXT4_NOJOURNAL_HANDLE)
	if ((unsigned long)handle < EXT4_NOJOURNAL_MAX_REF_COUNT)
		return 0;
		return 0;
	return 1;
	return 1;
}
}
+2 −1
Original line number Original line Diff line number Diff line
@@ -2076,7 +2076,8 @@ int ext4_orphan_del(handle_t *handle, struct inode *inode)
	struct ext4_iloc iloc;
	struct ext4_iloc iloc;
	int err = 0;
	int err = 0;


	if (!ext4_handle_valid(handle))
	/* ext4_handle_valid() assumes a valid handle_t pointer */
	if (handle && !ext4_handle_valid(handle))
		return 0;
		return 0;


	mutex_lock(&EXT4_SB(inode->i_sb)->s_orphan_lock);
	mutex_lock(&EXT4_SB(inode->i_sb)->s_orphan_lock);
+32 −10
Original line number Original line Diff line number Diff line
@@ -189,6 +189,36 @@ void ext4_itable_unused_set(struct super_block *sb,
		bg->bg_itable_unused_hi = cpu_to_le16(count >> 16);
		bg->bg_itable_unused_hi = cpu_to_le16(count >> 16);
}
}



/* Just increment the non-pointer handle value */
static handle_t *ext4_get_nojournal(void)
{
	handle_t *handle = current->journal_info;
	unsigned long ref_cnt = (unsigned long)handle;

	BUG_ON(ref_cnt >= EXT4_NOJOURNAL_MAX_REF_COUNT);

	ref_cnt++;
	handle = (handle_t *)ref_cnt;

	current->journal_info = handle;
	return handle;
}


/* Decrement the non-pointer handle value */
static void ext4_put_nojournal(handle_t *handle)
{
	unsigned long ref_cnt = (unsigned long)handle;

	BUG_ON(ref_cnt == 0);

	ref_cnt--;
	handle = (handle_t *)ref_cnt;

	current->journal_info = handle;
}

/*
/*
 * Wrappers for jbd2_journal_start/end.
 * Wrappers for jbd2_journal_start/end.
 *
 *
@@ -215,11 +245,7 @@ handle_t *ext4_journal_start_sb(struct super_block *sb, int nblocks)
		}
		}
		return jbd2_journal_start(journal, nblocks);
		return jbd2_journal_start(journal, nblocks);
	}
	}
	/*
	return ext4_get_nojournal();
	 * We're not journaling, return the appropriate indication.
	 */
	current->journal_info = EXT4_NOJOURNAL_HANDLE;
	return current->journal_info;
}
}


/*
/*
@@ -235,11 +261,7 @@ int __ext4_journal_stop(const char *where, handle_t *handle)
	int rc;
	int rc;


	if (!ext4_handle_valid(handle)) {
	if (!ext4_handle_valid(handle)) {
		/*
		ext4_put_nojournal(handle);
		 * Do this here since we don't call jbd2_journal_stop() in
		 * no-journal mode.
		 */
		current->journal_info = NULL;
		return 0;
		return 0;
	}
	}
	sb = handle->h_transaction->t_journal->j_private;
	sb = handle->h_transaction->t_journal->j_private;