[Ocfs2-devel] [PATCH 1/1] ocfs2: Release jbd inode for system inodes before journal shutdown

Joel Becker Joel.Becker at oracle.com
Wed Oct 15 16:07:45 PDT 2008


On Wed, Oct 15, 2008 at 03:14:56PM -0700, Sunil Mushran wrote:
> JBD2 expects clear inode to also release the corresponding jbd inode.
> OCFS2 has a set of system inodes that includes the journal inode that
> are cleared after the journal is shutdown. This is problematic as the
> jbd inode needs to be released while the journal is still up.
> 
> This patch fixes this issue by making the fs explicitly release the jbd
> inode for all system inodes before the journal shutdown.
> 
> Signed-off-by: Sunil Mushran <sunil.mushran at oracle.com>
> ---
>  fs/ocfs2/inode.c |    7 +++++--
>  fs/ocfs2/super.c |   33 +++++++++++++++++++++++++++++++++
>  2 files changed, 38 insertions(+), 2 deletions(-)
> 
> diff --git a/fs/ocfs2/inode.c b/fs/ocfs2/inode.c
> index 4903688..20f93fd 100644
> --- a/fs/ocfs2/inode.c
> +++ b/fs/ocfs2/inode.c
> @@ -1023,6 +1023,7 @@ void ocfs2_clear_inode(struct inode *inode)
>  {
>  	int status;
>  	struct ocfs2_inode_info *oi = OCFS2_I(inode);
> +	struct ocfs2_journal *journal;
>  
>  	mlog_entry_void();
>  
> @@ -1106,8 +1107,10 @@ void ocfs2_clear_inode(struct inode *inode)
>  	oi->ip_last_trans = 0;
>  	oi->ip_dir_start_lookup = 0;
>  	oi->ip_blkno = 0ULL;
> -	jbd2_journal_release_jbd_inode(OCFS2_SB(inode->i_sb)->journal->j_journal,
> -				       &oi->ip_jinode);
> +
> +	journal = OCFS2_SB(inode->i_sb)->journal;
> +	BUG_ON(journal->j_state != OCFS2_JOURNAL_LOADED);
> +	jbd2_journal_release_jbd_inode(journal->j_journal, &oi->ip_jinode);

	This can't be right - clear_inode() will be called by
release_system_inodes() just as before, and journal->j_state will be
JOURNAL_FREE.  The BUG_ON() will always trigger.
	Shouldn't this be more like:

	if (!(op->ip_flags & OCFS2_INODE_SYSTEM_FILE) ||
	    (journal->j_state != OCFS2_JOURNAL_FREE)
		jbd2_journal_release_jbd_inode(journal->j_journal, &oi->ip_jinode);

	The problem with this is, what about cleaning up mount errors?
System files are allocated *before* we start the journal, and we need to
clean that up too.  In the error paths of init_*_system_inodes(), you
need to call your ocfs2_release_system_inodes_jbd_inode() function right
before calling ocfs2_release_system_inodes().  And that call has to do
the right thing.
	Come to that, we can't clean that up safely, because we don't
have a journal yet.
	Ok, let's ignore allocation.  We were worried about releasing
any allocation done by init_jbd_inode(), but we can't handle that
safely.  It doesn't do it today, and if they ever add it, we can yell at
them.
	So, don't call ocfs2_release_system_inodes_jbd_inode() in the
error paths of init_*_system_inodes().  Leave that out.  Change
clean_inode() to:

	if (op->ip_flags & OCFS2_INODE_SYSTEM_FILE) {
		if (journal->j_state != OCFS2_JOURNAL_FREE)
			jbd2_journal_release_jbd_inode(journal->j_journal,
						       &oi->ip_jinode);
	} else {
		BUG_ON(journa->j_state == OCFS2_JOURNAL_FREE);
		jbd2_journal_release_jbd_inode(journal->j_journal,
					       &oi->ip_jinode);
	}

Joel

>  
>  bail:
>  	mlog_exit_void();
> diff --git a/fs/ocfs2/super.c b/fs/ocfs2/super.c
> index 304b63a..5f40d7c 100644
> --- a/fs/ocfs2/super.c
> +++ b/fs/ocfs2/super.c
> @@ -324,6 +324,36 @@ static void ocfs2_release_system_inodes(struct ocfs2_super *osb)
>  	mlog_exit(0);
>  }
>  
> +static void ocfs2_release_system_inodes_jbd_inode(struct ocfs2_super *osb)
> +{
> +	int i;
> +	struct inode *inode;
> +	struct ocfs2_journal *journal;
> +
> +	for (i = 0; i < NUM_SYSTEM_INODES; i++) {
> +		inode = osb->system_inodes[i];
> +		if (!inode)
> +			continue;
> +		journal = OCFS2_SB(inode->i_sb)->journal;
> +		jbd2_journal_release_jbd_inode(journal->j_journal,
> +					       OCFS2_I(inode)->ip_jinode);
> +	}
> +
> +	inode = osb->sys_root_inode;
> +	if (inode) {
> +		journal = OCFS2_SB(inode->i_sb)->journal;
> +		jbd2_journal_release_jbd_inode(journal->j_journal,
> +					       OCFS2_I(inode)->ip_jinode);
> +	}
> +
> +	inode = osb->root_inode;
> +	if (inode) {
> +		journal = OCFS2_SB(inode->i_sb)->journal;
> +		jbd2_journal_release_jbd_inode(journal->j_journal,
> +					       OCFS2_I(inode)->ip_jinode);
> +	}
> +}
> +
>  /* We're allocating fs objects, use GFP_NOFS */
>  static struct inode *ocfs2_alloc_inode(struct super_block *sb)
>  {
> @@ -1310,6 +1340,9 @@ static void ocfs2_dismount_volume(struct super_block *sb, int mnt_err)
>  	/* This will disable recovery and flush any recovery work. */
>  	ocfs2_recovery_exit(osb);
>  
> +	/* Release jbd inode for system inodes before journal shutdown */
> +	ocfs2_release_system_inodes_jbd_inode(osb);
> +
>  	ocfs2_journal_shutdown(osb);
>  
>  	ocfs2_sync_blockdev(sb);
> -- 
> 1.5.6.3
> 
> 
> _______________________________________________
> Ocfs2-devel mailing list
> Ocfs2-devel at oss.oracle.com
> http://oss.oracle.com/mailman/listinfo/ocfs2-devel

-- 

"Glory is fleeting, but obscurity is forever."  
         - Napoleon Bonaparte

Joel Becker
Principal Software Developer
Oracle
E-mail: joel.becker at oracle.com
Phone: (650) 506-8127



More information about the Ocfs2-devel mailing list