Commit 24f211ba authored by Christoph Hellwig's avatar Christoph Hellwig Committed by Niv Sardi

[XFS] move inode allocation out xfs_iread

Allocate the inode in xfs_iget_cache_miss and pass it into xfs_iread.  This
simplifies the error handling and allows xfs_iread to be shared with userspace
which already uses these semantics.
Signed-off-by: default avatarChristoph Hellwig <hch@lst.de>
Reviewed-by: default avatarDave Chinner <david@fromorbit.com>
Signed-off-by: default avatarNiv Sardi <xaiki@sgi.com>
parent b48d8d64
...@@ -40,6 +40,82 @@ ...@@ -40,6 +40,82 @@
#include "xfs_utils.h" #include "xfs_utils.h"
#include "xfs_trans_priv.h" #include "xfs_trans_priv.h"
#include "xfs_inode_item.h" #include "xfs_inode_item.h"
#include "xfs_bmap.h"
#include "xfs_btree_trace.h"
#include "xfs_dir2_trace.h"
/*
* Allocate and initialise an xfs_inode.
*/
STATIC struct xfs_inode *
xfs_inode_alloc(
struct xfs_mount *mp,
xfs_ino_t ino)
{
struct xfs_inode *ip;
/*
* if this didn't occur in transactions, we could use
* KM_MAYFAIL and return NULL here on ENOMEM. Set the
* code up to do this anyway.
*/
ip = kmem_zone_alloc(xfs_inode_zone, KM_SLEEP);
if (!ip)
return NULL;
ASSERT(atomic_read(&ip->i_iocount) == 0);
ASSERT(atomic_read(&ip->i_pincount) == 0);
ASSERT(!spin_is_locked(&ip->i_flags_lock));
ASSERT(completion_done(&ip->i_flush));
/*
* initialise the VFS inode here to get failures
* out of the way early.
*/
if (!inode_init_always(mp->m_super, VFS_I(ip))) {
kmem_zone_free(xfs_inode_zone, ip);
return NULL;
}
/* initialise the xfs inode */
ip->i_ino = ino;
ip->i_mount = mp;
memset(&ip->i_imap, 0, sizeof(struct xfs_imap));
ip->i_afp = NULL;
memset(&ip->i_df, 0, sizeof(xfs_ifork_t));
ip->i_flags = 0;
ip->i_update_core = 0;
ip->i_update_size = 0;
ip->i_delayed_blks = 0;
memset(&ip->i_d, 0, sizeof(xfs_icdinode_t));
ip->i_size = 0;
ip->i_new_size = 0;
/*
* Initialize inode's trace buffers.
*/
#ifdef XFS_INODE_TRACE
ip->i_trace = ktrace_alloc(INODE_TRACE_SIZE, KM_NOFS);
#endif
#ifdef XFS_BMAP_TRACE
ip->i_xtrace = ktrace_alloc(XFS_BMAP_KTRACE_SIZE, KM_NOFS);
#endif
#ifdef XFS_BTREE_TRACE
ip->i_btrace = ktrace_alloc(XFS_BMBT_KTRACE_SIZE, KM_NOFS);
#endif
#ifdef XFS_RW_TRACE
ip->i_rwtrace = ktrace_alloc(XFS_RW_KTRACE_SIZE, KM_NOFS);
#endif
#ifdef XFS_ILOCK_TRACE
ip->i_lock_trace = ktrace_alloc(XFS_ILOCK_KTRACE_SIZE, KM_NOFS);
#endif
#ifdef XFS_DIR2_TRACE
ip->i_dir_trace = ktrace_alloc(XFS_DIR2_KTRACE_SIZE, KM_NOFS);
#endif
return ip;
}
/* /*
* Check the validity of the inode we just found it the cache * Check the validity of the inode we just found it the cache
...@@ -155,13 +231,13 @@ xfs_iget_cache_miss( ...@@ -155,13 +231,13 @@ xfs_iget_cache_miss(
unsigned long first_index, mask; unsigned long first_index, mask;
xfs_agino_t agino = XFS_INO_TO_AGINO(mp, ino); xfs_agino_t agino = XFS_INO_TO_AGINO(mp, ino);
/* ip = xfs_inode_alloc(mp, ino);
* Read the disk inode attributes into a new inode structure and get if (!ip)
* a new vnode for it. This should also initialize i_ino and i_mount. return ENOMEM;
*/
error = xfs_iread(mp, tp, ino, &ip, bno, flags); error = xfs_iread(mp, tp, ip, bno, flags);
if (error) if (error)
return error; goto out_destroy;
xfs_itrace_exit_tag(ip, "xfs_iget.alloc"); xfs_itrace_exit_tag(ip, "xfs_iget.alloc");
......
...@@ -758,119 +758,36 @@ xfs_dic2xflags( ...@@ -758,119 +758,36 @@ xfs_dic2xflags(
} }
/* /*
* Allocate and initialise an xfs_inode. * Read the disk inode attributes into the in-core inode structure.
*/
STATIC struct xfs_inode *
xfs_inode_alloc(
struct xfs_mount *mp,
xfs_ino_t ino)
{
struct xfs_inode *ip;
/*
* if this didn't occur in transactions, we could use
* KM_MAYFAIL and return NULL here on ENOMEM. Set the
* code up to do this anyway.
*/
ip = kmem_zone_alloc(xfs_inode_zone, KM_SLEEP);
if (!ip)
return NULL;
ASSERT(atomic_read(&ip->i_iocount) == 0);
ASSERT(atomic_read(&ip->i_pincount) == 0);
ASSERT(!spin_is_locked(&ip->i_flags_lock));
ASSERT(completion_done(&ip->i_flush));
/*
* initialise the VFS inode here to get failures
* out of the way early.
*/
if (!inode_init_always(mp->m_super, VFS_I(ip))) {
kmem_zone_free(xfs_inode_zone, ip);
return NULL;
}
/* initialise the xfs inode */
ip->i_ino = ino;
ip->i_mount = mp;
memset(&ip->i_imap, 0, sizeof(struct xfs_imap));
ip->i_afp = NULL;
memset(&ip->i_df, 0, sizeof(xfs_ifork_t));
ip->i_flags = 0;
ip->i_update_core = 0;
ip->i_update_size = 0;
ip->i_delayed_blks = 0;
memset(&ip->i_d, 0, sizeof(xfs_icdinode_t));
ip->i_size = 0;
ip->i_new_size = 0;
/*
* Initialize inode's trace buffers.
*/
#ifdef XFS_INODE_TRACE
ip->i_trace = ktrace_alloc(INODE_TRACE_SIZE, KM_NOFS);
#endif
#ifdef XFS_BMAP_TRACE
ip->i_xtrace = ktrace_alloc(XFS_BMAP_KTRACE_SIZE, KM_NOFS);
#endif
#ifdef XFS_BTREE_TRACE
ip->i_btrace = ktrace_alloc(XFS_BMBT_KTRACE_SIZE, KM_NOFS);
#endif
#ifdef XFS_RW_TRACE
ip->i_rwtrace = ktrace_alloc(XFS_RW_KTRACE_SIZE, KM_NOFS);
#endif
#ifdef XFS_ILOCK_TRACE
ip->i_lock_trace = ktrace_alloc(XFS_ILOCK_KTRACE_SIZE, KM_NOFS);
#endif
#ifdef XFS_DIR2_TRACE
ip->i_dir_trace = ktrace_alloc(XFS_DIR2_KTRACE_SIZE, KM_NOFS);
#endif
return ip;
}
/*
* Given a mount structure and an inode number, return a pointer
* to a newly allocated in-core inode corresponding to the given
* inode number.
*
* Initialize the inode's attributes and extent pointers if it
* already has them (it will not if the inode has no links).
*/ */
int int
xfs_iread( xfs_iread(
xfs_mount_t *mp, xfs_mount_t *mp,
xfs_trans_t *tp, xfs_trans_t *tp,
xfs_ino_t ino, xfs_inode_t *ip,
xfs_inode_t **ipp,
xfs_daddr_t bno, xfs_daddr_t bno,
uint imap_flags) uint iget_flags)
{ {
xfs_buf_t *bp; xfs_buf_t *bp;
xfs_dinode_t *dip; xfs_dinode_t *dip;
xfs_inode_t *ip;
int error; int error;
ip = xfs_inode_alloc(mp, ino);
if (!ip)
return ENOMEM;
/* /*
* Fill in the location information in the in-core inode. * Fill in the location information in the in-core inode.
*/ */
ip->i_imap.im_blkno = bno; ip->i_imap.im_blkno = bno;
error = xfs_imap(mp, tp, ip->i_ino, &ip->i_imap, imap_flags); error = xfs_imap(mp, tp, ip->i_ino, &ip->i_imap, iget_flags);
if (error) if (error)
goto out_destroy_inode; return error;
ASSERT(bno == 0 || bno == ip->i_imap.im_blkno); ASSERT(bno == 0 || bno == ip->i_imap.im_blkno);
/* /*
* Get pointers to the on-disk inode and the buffer containing it. * Get pointers to the on-disk inode and the buffer containing it.
*/ */
error = xfs_imap_to_bp(mp, tp, &ip->i_imap, &bp, error = xfs_imap_to_bp(mp, tp, &ip->i_imap, &bp,
XFS_BUF_LOCK, imap_flags); XFS_BUF_LOCK, iget_flags);
if (error) if (error)
goto out_destroy_inode; return error;
dip = (xfs_dinode_t *)xfs_buf_offset(bp, ip->i_imap.im_boffset); dip = (xfs_dinode_t *)xfs_buf_offset(bp, ip->i_imap.im_boffset);
/* /*
...@@ -968,14 +885,8 @@ xfs_iread( ...@@ -968,14 +885,8 @@ xfs_iread(
* to worry about the inode being changed just because we released * to worry about the inode being changed just because we released
* the buffer. * the buffer.
*/ */
xfs_trans_brelse(tp, bp);
*ipp = ip;
return 0;
out_brelse: out_brelse:
xfs_trans_brelse(tp, bp); xfs_trans_brelse(tp, bp);
out_destroy_inode:
xfs_destroy_inode(ip);
return error; return error;
} }
......
...@@ -516,8 +516,8 @@ void xfs_ireclaim(xfs_inode_t *); ...@@ -516,8 +516,8 @@ void xfs_ireclaim(xfs_inode_t *);
/* /*
* xfs_inode.c prototypes. * xfs_inode.c prototypes.
*/ */
int xfs_iread(struct xfs_mount *, struct xfs_trans *, xfs_ino_t, int xfs_iread(struct xfs_mount *, struct xfs_trans *,
xfs_inode_t **, xfs_daddr_t, uint); struct xfs_inode *, xfs_daddr_t, uint);
int xfs_ialloc(struct xfs_trans *, xfs_inode_t *, mode_t, int xfs_ialloc(struct xfs_trans *, xfs_inode_t *, mode_t,
xfs_nlink_t, xfs_dev_t, struct cred *, xfs_prid_t, xfs_nlink_t, xfs_dev_t, struct cred *, xfs_prid_t,
int, struct xfs_buf **, boolean_t *, xfs_inode_t **); int, struct xfs_buf **, boolean_t *, xfs_inode_t **);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment