public inbox for linux-xfs@vger.kernel.org
 help / color / mirror / Atom feed
From: Timothy Shimmin <tes@sgi.com>
To: Dave Chinner <david@fromorbit.com>
Cc: xfs@oss.sgi.com
Subject: Re: [PATCH] XFS: handle memory allocation failures during log initialisation
Date: Fri, 31 Oct 2008 15:33:49 +1100	[thread overview]
Message-ID: <490A8AAD.50207@sgi.com> (raw)
In-Reply-To: <1225416366-3116-1-git-send-email-david@fromorbit.com>

Hi Dave,

Dave Chinner wrote:
> When there is no memory left in the system, xfs_buf_get_noaddr()
> can fail. If this happens at mount time during xlog_alloc_log()
> we fail to catch the error and oops.
> 
> Catch the error from xfs_buf_get_noaddr(), and allow other memory
> allocations to fail and catch those errors too. Report the error
> to the console and fail the mount with ENOMEM.
> 
> Tested by manually injecting errors into xfs_buf_get_noaddr() and
> xlog_alloc_log().
> 
> Version 2:
> o remove unnecessary casts of the returned pointer from kmem_zalloc()
> 
> Signed-off-by: Dave Chinner <david@fromorbit.com>
> ---
>  fs/xfs/xfs_log.c |   39 ++++++++++++++++++++++++++++++++++++---
>  1 files changed, 36 insertions(+), 3 deletions(-)
> 
> diff --git a/fs/xfs/xfs_log.c b/fs/xfs/xfs_log.c
> index 5184017..92c20a8 100644
> --- a/fs/xfs/xfs_log.c
> +++ b/fs/xfs/xfs_log.c
> @@ -563,6 +563,11 @@ xfs_log_mount(
>  	}
>  
>  	mp->m_log = xlog_alloc_log(mp, log_target, blk_offset, num_bblks);
> +	if (!mp->m_log) {
> +		cmn_err(CE_WARN, "XFS: Log allocation failed: No memory!");
> +		error = ENOMEM;
> +		goto out;
> +	}
>  
>  	/*
>  	 * Initialize the AIL now we have a log.
> @@ -601,6 +606,7 @@ xfs_log_mount(
>  	return 0;
>  error:
>  	xfs_log_unmount_dealloc(mp);
> +out:
>  	return error;
>  }	/* xfs_log_mount */
>  
> @@ -1217,7 +1223,9 @@ xlog_alloc_log(xfs_mount_t	*mp,
>  	int			i;
>  	int			iclogsize;
>  
> -	log = (xlog_t *)kmem_zalloc(sizeof(xlog_t), KM_SLEEP);
> +	log = kmem_zalloc(sizeof(xlog_t), KM_MAYFAIL);
> +	if (!log)
> +		return NULL;
>  
>  	log->l_mp	   = mp;
>  	log->l_targ	   = log_target;
> @@ -1249,6 +1257,8 @@ xlog_alloc_log(xfs_mount_t	*mp,
>  	xlog_get_iclog_buffer_size(mp, log);
>  
>  	bp = xfs_buf_get_empty(log->l_iclog_size, mp->m_logdev_targp);
> +	if (!bp)
> +		goto out_free_log;
>  	XFS_BUF_SET_IODONE_FUNC(bp, xlog_iodone);
>  	XFS_BUF_SET_BDSTRAT_FUNC(bp, xlog_bdstrat_cb);
>  	XFS_BUF_SET_FSPRIVATE2(bp, (unsigned long)1);
> @@ -1275,13 +1285,17 @@ xlog_alloc_log(xfs_mount_t	*mp,
>  	iclogsize = log->l_iclog_size;
>  	ASSERT(log->l_iclog_size >= 4096);
>  	for (i=0; i < log->l_iclog_bufs; i++) {
> -		*iclogp = (xlog_in_core_t *)
> -			  kmem_zalloc(sizeof(xlog_in_core_t), KM_SLEEP);
> +		*iclogp = kmem_zalloc(sizeof(xlog_in_core_t), KM_MAYFAIL);
> +		if (!*iclogp)
> +			goto out_free_iclog;
> +
>  		iclog = *iclogp;
>  		iclog->ic_prev = prev_iclog;
>  		prev_iclog = iclog;
>  
>  		bp = xfs_buf_get_noaddr(log->l_iclog_size, mp->m_logdev_targp);
> +		if (!bp)
> +			goto out_free_iclog;
>  		if (!XFS_BUF_CPSEMA(bp))
>  			ASSERT(0);
>  		XFS_BUF_SET_IODONE_FUNC(bp, xlog_iodone);
> @@ -1323,6 +1337,25 @@ xlog_alloc_log(xfs_mount_t	*mp,
>  	log->l_iclog->ic_prev = prev_iclog;	/* re-write 1st prev ptr */
>  
>  	return log;
> +
> +out_free_iclog:
> +	for (iclog = log->l_iclog; iclog; iclog = prev_iclog) {
> +		prev_iclog = iclog->ic_next;
> +		if (iclog->ic_bp) {
> +			sv_destroy(&iclog->ic_force_wait);
> +			sv_destroy(&iclog->ic_write_wait);
> +			xfs_buf_free(iclog->ic_bp);
> +			xlog_trace_iclog_dealloc(iclog);
> +		}
> +		kmem_free(iclog);
> +	}
> +	spinlock_destroy(&log->l_icloglock);
> +	spinlock_destroy(&log->l_grant_lock);
> +	xlog_trace_loggrant_dealloc(log);
> +	xfs_buf_free(log->l_xbuf);
> +out_free_log:
> +	kmem_free(log);
> +	return NULL;
>  }	/* xlog_alloc_log */
>  
>  

I would have done s/prev_iclog/next_iclog/
as I'm not sure why you look at it as previous.

However, I think it would be nicer to modify xlog_dealloc_log()
to handle less than l_iclog_bufs.
i.e put the code you have here into xlog_dealloc_log()
and do the deallocation in one place.

--Tim

  reply	other threads:[~2008-10-31  4:34 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-10-31  1:26 [PATCH] XFS: handle memory allocation failures during log initialisation Dave Chinner
2008-10-31  4:33 ` Timothy Shimmin [this message]
2008-11-02 23:10   ` Dave Chinner
2008-11-05  0:24     ` Timothy Shimmin

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=490A8AAD.50207@sgi.com \
    --to=tes@sgi.com \
    --cc=david@fromorbit.com \
    --cc=xfs@oss.sgi.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox