#include "xfs_bit.h"
#include "xfs_log.h"
#include "xfs_inum.h"
-#include "xfs_imap.h"
#include "xfs_trans.h"
#include "xfs_trans_priv.h"
#include "xfs_sb.h"
xfs_imap_to_bp(
xfs_mount_t *mp,
xfs_trans_t *tp,
- xfs_imap_t *imap,
+ struct xfs_imap *imap,
xfs_buf_t **bpp,
uint buf_flags,
- uint imap_flags)
+ uint iget_flags)
{
int error;
int i;
if (unlikely(XFS_TEST_ERROR(!di_ok, mp,
XFS_ERRTAG_ITOBP_INOTOBP,
XFS_RANDOM_ITOBP_INOTOBP))) {
- if (imap_flags & XFS_IMAP_BULKSTAT) {
+ if (iget_flags & XFS_IGET_BULKSTAT) {
xfs_trans_brelse(tp, bp);
return XFS_ERROR(EINVAL);
}
int *offset,
uint imap_flags)
{
- xfs_imap_t imap;
+ struct xfs_imap imap;
xfs_buf_t *bp;
int error;
* in once, thus we can use the mapping information stored in the inode
* rather than calling xfs_imap(). This allows us to avoid the overhead
* of looking at the inode btree for small block file systems
- * (see xfs_dilocate()).
+ * (see xfs_imap()).
*/
int
xfs_itobp(
xfs_buf_t **bpp,
uint buf_flags)
{
- xfs_imap_t imap;
xfs_buf_t *bp;
int error;
- ASSERT(ip->i_blkno != 0);
-
- imap.im_blkno = ip->i_blkno;
- imap.im_len = ip->i_len;
- imap.im_boffset = ip->i_boffset;
+ ASSERT(ip->i_imap.im_blkno != 0);
- error = xfs_imap_to_bp(mp, tp, &imap, &bp, buf_flags, 0);
+ error = xfs_imap_to_bp(mp, tp, &ip->i_imap, &bp, buf_flags, 0);
if (error)
return error;
return EAGAIN;
}
- *dipp = (xfs_dinode_t *)xfs_buf_offset(bp, imap.im_boffset);
+ *dipp = (xfs_dinode_t *)xfs_buf_offset(bp, ip->i_imap.im_boffset);
*bpp = bp;
return 0;
}
}
/*
- * 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;
- ip->i_blkno = 0;
- ip->i_len = 0;
- ip->i_boffset =0;
- 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).
+ * Read the disk inode attributes into the in-core inode structure.
*/
int
xfs_iread(
xfs_mount_t *mp,
xfs_trans_t *tp,
- xfs_ino_t ino,
- xfs_inode_t **ipp,
+ xfs_inode_t *ip,
xfs_daddr_t bno,
- uint imap_flags)
+ uint iget_flags)
{
xfs_buf_t *bp;
xfs_dinode_t *dip;
- xfs_inode_t *ip;
- xfs_imap_t imap;
int error;
- ip = xfs_inode_alloc(mp, ino);
- if (!ip)
- return ENOMEM;
-
/*
- * Get pointers to the on-disk inode and the buffer containing it.
+ * Fill in the location information in the in-core inode.
*/
- imap.im_blkno = bno;
- error = xfs_imap(mp, tp, ip->i_ino, &imap, imap_flags);
+ ip->i_imap.im_blkno = bno;
+ error = xfs_imap(mp, tp, ip->i_ino, &ip->i_imap, iget_flags);
if (error)
- goto out_destroy_inode;
+ return error;
+ ASSERT(bno == 0 || bno == ip->i_imap.im_blkno);
/*
- * Fill in the fields in the inode that will be used to
- * map the inode to its buffer from now on.
+ * Get pointers to the on-disk inode and the buffer containing it.
*/
- ip->i_blkno = imap.im_blkno;
- ip->i_len = imap.im_len;
- ip->i_boffset = imap.im_boffset;
- ASSERT(bno == 0 || bno == imap.im_blkno);
-
- error = xfs_imap_to_bp(mp, tp, &imap, &bp, XFS_BUF_LOCK, imap_flags);
+ error = xfs_imap_to_bp(mp, tp, &ip->i_imap, &bp,
+ XFS_BUF_LOCK, iget_flags);
if (error)
- goto out_destroy_inode;
- dip = (xfs_dinode_t *)xfs_buf_offset(bp, imap.im_boffset);
+ return error;
+ dip = (xfs_dinode_t *)xfs_buf_offset(bp, ip->i_imap.im_boffset);
/*
* If we got something that isn't an inode it means someone
* around for a while. This helps to keep recently accessed
* meta-data in-core longer.
*/
- XFS_BUF_SET_REF(bp, XFS_INO_REF);
+ XFS_BUF_SET_REF(bp, XFS_INO_REF);
/*
* Use xfs_trans_brelse() to release the buffer containing the
* to worry about the inode being changed just because we released
* the buffer.
*/
- xfs_trans_brelse(tp, bp);
- *ipp = ip;
- return 0;
-
out_brelse:
xfs_trans_brelse(tp, bp);
- out_destroy_inode:
- xfs_destroy_inode(ip);
return error;
}
* direct I/O with the truncate operation. Also, because we hold
* the IOLOCK in exclusive mode, we prevent new direct I/Os from being
* started until the truncate completes and drops the lock. Essentially,
- * the vn_iowait() call forms an I/O barrier that provides strict ordering
- * between direct I/Os and the truncate operation.
+ * the xfs_ioend_wait() call forms an I/O barrier that provides strict
+ * ordering between direct I/Os and the truncate operation.
*
* The flags parameter can have either the value XFS_ITRUNC_DEFINITE
* or XFS_ITRUNC_MAYBE. The XFS_ITRUNC_MAYBE value should be used
/* wait for the completion of any pending DIOs */
if (new_size == 0 || new_size < ip->i_size)
- vn_iowait(ip);
+ xfs_ioend_wait(ip);
/*
* Call toss_pages or flushinval_pages to get rid of pages
ASSERT(be32_to_cpu(dip->di_next_unlinked) == NULLAGINO);
/* both on-disk, don't endian flip twice */
dip->di_next_unlinked = agi->agi_unlinked[bucket_index];
- offset = ip->i_boffset +
+ offset = ip->i_imap.im_boffset +
offsetof(xfs_dinode_t, di_next_unlinked);
xfs_trans_inode_buf(tp, ibp);
xfs_trans_log_buf(tp, ibp, offset,
ASSERT(next_agino != 0);
if (next_agino != NULLAGINO) {
dip->di_next_unlinked = cpu_to_be32(NULLAGINO);
- offset = ip->i_boffset +
+ offset = ip->i_imap.im_boffset +
offsetof(xfs_dinode_t, di_next_unlinked);
xfs_trans_inode_buf(tp, ibp);
xfs_trans_log_buf(tp, ibp, offset,
ASSERT(next_agino != agino);
if (next_agino != NULLAGINO) {
dip->di_next_unlinked = cpu_to_be32(NULLAGINO);
- offset = ip->i_boffset +
+ offset = ip->i_imap.im_boffset +
offsetof(xfs_dinode_t, di_next_unlinked);
xfs_trans_inode_buf(tp, ibp);
xfs_trans_log_buf(tp, ibp, offset,
ASSERT(ifp->if_bytes <= XFS_IFORK_SIZE(ip, whichfork));
}
-
-
-
-/*
- * Map inode to disk block and offset.
- *
- * mp -- the mount point structure for the current file system
- * tp -- the current transaction
- * ino -- the inode number of the inode to be located
- * imap -- this structure is filled in with the information necessary
- * to retrieve the given inode from disk
- * flags -- flags to pass to xfs_dilocate indicating whether or not
- * lookups in the inode btree were OK or not
- */
-int
-xfs_imap(
- xfs_mount_t *mp,
- xfs_trans_t *tp,
- xfs_ino_t ino,
- xfs_imap_t *imap,
- uint flags)
-{
- xfs_fsblock_t fsbno;
- int len;
- int off;
- int error;
-
- fsbno = imap->im_blkno ?
- XFS_DADDR_TO_FSB(mp, imap->im_blkno) : NULLFSBLOCK;
- error = xfs_dilocate(mp, tp, ino, &fsbno, &len, &off, flags);
- if (error)
- return error;
-
- imap->im_blkno = XFS_FSB_TO_DADDR(mp, fsbno);
- imap->im_len = XFS_FSB_TO_BB(mp, len);
- imap->im_agblkno = XFS_FSB_TO_AGBNO(mp, fsbno);
- imap->im_ioffset = (ushort)off;
- imap->im_boffset = (ushort)(off << mp->m_sb.sb_inodelog);
-
- /*
- * If the inode number maps to a block outside the bounds
- * of the file system then return NULL rather than calling
- * read_buf and panicing when we get an error from the
- * driver.
- */
- if ((imap->im_blkno + imap->im_len) >
- XFS_FSB_TO_BB(mp, mp->m_sb.sb_dblocks)) {
- xfs_fs_cmn_err(CE_ALERT, mp, "xfs_imap: "
- "(imap->im_blkno (0x%llx) + imap->im_len (0x%llx)) > "
- " XFS_FSB_TO_BB(mp, mp->m_sb.sb_dblocks) (0x%llx)",
- (unsigned long long) imap->im_blkno,
- (unsigned long long) imap->im_len,
- XFS_FSB_TO_BB(mp, mp->m_sb.sb_dblocks));
- return EINVAL;
- }
- return 0;
-}
-
void
xfs_idestroy_fork(
xfs_inode_t *ip,
}
}
-/*
- * This is called free all the memory associated with an inode.
- * It must free the inode itself and any buffers allocated for
- * if_extents/if_data and if_broot. It must also free the lock
- * associated with the inode.
- *
- * Note: because we don't initialise everything on reallocation out
- * of the zone, we must ensure we nullify everything correctly before
- * freeing the structure.
- */
-void
-xfs_idestroy(
- xfs_inode_t *ip)
-{
- switch (ip->i_d.di_mode & S_IFMT) {
- case S_IFREG:
- case S_IFDIR:
- case S_IFLNK:
- xfs_idestroy_fork(ip, XFS_DATA_FORK);
- break;
- }
- if (ip->i_afp)
- xfs_idestroy_fork(ip, XFS_ATTR_FORK);
-
-#ifdef XFS_INODE_TRACE
- ktrace_free(ip->i_trace);
-#endif
-#ifdef XFS_BMAP_TRACE
- ktrace_free(ip->i_xtrace);
-#endif
-#ifdef XFS_BTREE_TRACE
- ktrace_free(ip->i_btrace);
-#endif
-#ifdef XFS_RW_TRACE
- ktrace_free(ip->i_rwtrace);
-#endif
-#ifdef XFS_ILOCK_TRACE
- ktrace_free(ip->i_lock_trace);
-#endif
-#ifdef XFS_DIR2_TRACE
- ktrace_free(ip->i_dir_trace);
-#endif
- if (ip->i_itemp) {
- /*
- * Only if we are shutting down the fs will we see an
- * inode still in the AIL. If it is there, we should remove
- * it to prevent a use-after-free from occurring.
- */
- xfs_log_item_t *lip = &ip->i_itemp->ili_item;
- struct xfs_ail *ailp = lip->li_ailp;
-
- ASSERT(((lip->li_flags & XFS_LI_IN_AIL) == 0) ||
- XFS_FORCED_SHUTDOWN(ip->i_mount));
- if (lip->li_flags & XFS_LI_IN_AIL) {
- spin_lock(&ailp->xa_lock);
- if (lip->li_flags & XFS_LI_IN_AIL)
- xfs_trans_ail_delete(ailp, lip);
- else
- spin_unlock(&ailp->xa_lock);
- }
- xfs_inode_item_destroy(ip);
- ip->i_itemp = NULL;
- }
- /* asserts to verify all state is correct here */
- 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));
- kmem_zone_free(xfs_inode_zone, ip);
-}
-
-
/*
* Increment the pin count of the given buffer.
* This value is protected by ipinlock spinlock in the mount structure.
XFS_BUF_CLR_BDSTRAT_FUNC(bp);
XFS_BUF_UNDONE(bp);
XFS_BUF_STALE(bp);
- XFS_BUF_SHUT(bp);
XFS_BUF_ERROR(bp,EIO);
xfs_biodone(bp);
} else {
}
/* set *dip = inode's place in the buffer */
- dip = (xfs_dinode_t *)xfs_buf_offset(bp, ip->i_boffset);
+ dip = (xfs_dinode_t *)xfs_buf_offset(bp, ip->i_imap.im_boffset);
/*
* Clear i_update_core before copying out the data.
#ifdef XFS_ILOCK_TRACE
-ktrace_t *xfs_ilock_trace_buf;
-
void
xfs_ilock_trace(xfs_inode_t *ip, int lock, unsigned int lockflags, inst_t *ra)
{