[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: Christoph Hellwig <hch@lst.de> Reviewed-by: Dave Chinner <david@fromorbit.com> Signed-off-by: Niv Sardi <xaiki@sgi.com>
This commit is contained in:
parent
b48d8d6437
commit
24f211bad0
@ -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(
|
|||||||
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(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* 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(
|
|||||||
* 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 *);
|
|||||||
/*
|
/*
|
||||||
* 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 **);
|
||||||
|
Loading…
Reference in New Issue
Block a user