/*
* Get the XFS inode, building a vnode to go with it.
*/
- error = xfs_iget(mp, NULL, ino, XFS_ILOCK_SHARED, &ip, 0);
+ error = xfs_iget(mp, NULL, ino, 0, XFS_ILOCK_SHARED, &ip, 0);
if (error)
return error;
if (ip == NULL)
vp->v_type = IFTOVT(ip->i_d.di_mode);
xfs_revalidate_inode(XFS_BHVTOM(bdp), vp, ip);
xfs_set_inodeops(inode);
+
+ ip->i_flags &= ~XFS_INEW;
+ barrier();
+
unlock_new_inode(inode);
}
}
* the case in all other instances. It's OK that we do this because
* quotacheck is done only at mount time.
*/
- if ((error = xfs_iget(mp, NULL, ino, XFS_ILOCK_EXCL, &ip, bno))) {
+ if ((error = xfs_iget(mp, NULL, ino, 0, XFS_ILOCK_EXCL, &ip, bno))) {
*res = BULKSTAT_RV_NOTHING;
return (error);
}
mp->m_sb.sb_uquotino != NULLFSINO) {
ASSERT(mp->m_sb.sb_uquotino > 0);
if ((error = xfs_iget(mp, NULL, mp->m_sb.sb_uquotino,
- 0, &uip, 0)))
+ 0, 0, &uip, 0)))
return XFS_ERROR(error);
}
if (XFS_IS_GQUOTA_ON(mp) &&
mp->m_sb.sb_gquotino != NULLFSINO) {
ASSERT(mp->m_sb.sb_gquotino > 0);
if ((error = xfs_iget(mp, NULL, mp->m_sb.sb_gquotino,
- 0, &gip, 0))) {
+ 0, 0, &gip, 0))) {
if (uip)
VN_RELE(XFS_ITOV(uip));
return XFS_ERROR(error);
}
if ((flags & XFS_DQ_USER) && mp->m_sb.sb_uquotino != NULLFSINO) {
- error = xfs_iget(mp, NULL, mp->m_sb.sb_uquotino, 0, &qip, 0);
+ error = xfs_iget(mp, NULL, mp->m_sb.sb_uquotino, 0, 0, &qip, 0);
if (! error) {
(void) xfs_truncate_file(mp, qip);
VN_RELE(XFS_ITOV(qip));
}
if ((flags & XFS_DQ_GROUP) && mp->m_sb.sb_gquotino != NULLFSINO) {
- error = xfs_iget(mp, NULL, mp->m_sb.sb_gquotino, 0, &qip, 0);
+ error = xfs_iget(mp, NULL, mp->m_sb.sb_gquotino, 0, 0, &qip, 0);
if (! error) {
(void) xfs_truncate_file(mp, qip);
VN_RELE(XFS_ITOV(qip));
gip = mp->m_quotainfo->qi_gquotaip;
}
if (!uip && mp->m_sb.sb_uquotino != NULLFSINO) {
- if (xfs_iget(mp, NULL, mp->m_sb.sb_uquotino, 0, &uip, 0) == 0)
+ if (xfs_iget(mp, NULL, mp->m_sb.sb_uquotino,
+ 0, 0, &uip, 0) == 0)
tempuqip = B_TRUE;
}
if (!gip && mp->m_sb.sb_gquotino != NULLFSINO) {
- if (xfs_iget(mp, NULL, mp->m_sb.sb_gquotino, 0, &gip, 0) == 0)
+ if (xfs_iget(mp, NULL, mp->m_sb.sb_gquotino,
+ 0, 0, &gip, 0) == 0)
tempgqip = B_TRUE;
}
if (uip) {
ipreleased = B_FALSE;
again:
lock_flags = XFS_ILOCK_SHARED;
- if ((error = xfs_iget(mp, NULL, ino, lock_flags, &ip, bno))) {
+ if ((error = xfs_iget(mp, NULL, ino, 0, lock_flags, &ip, bno))) {
*res = BULKSTAT_RV_NOTHING;
return (error);
}
xfs_mount_t *mp,
xfs_trans_t *tp,
xfs_ino_t ino,
+ uint flags,
uint lock_flags,
xfs_inode_t **ipp,
xfs_daddr_t bno)
ulong version;
int error;
/* REFERENCED */
- int newnode;
xfs_chash_t *ch;
xfs_chashlist_t *chl, *chlnew;
SPLDECL(s);
for (ip = ih->ih_next; ip != NULL; ip = ip->i_next) {
if (ip->i_ino == ino) {
+ /*
+ * If INEW is set this inode is being set up
+ * we need to pause and try again.
+ */
+ if (ip->i_flags & XFS_INEW) {
+ read_unlock(&ih->ih_lock);
+ delay(1);
+ XFS_STATS_INC(xs_ig_frecycle);
- inode_vp = XFS_ITOV_NULL(ip);
+ goto again;
+ }
+ inode_vp = XFS_ITOV_NULL(ip);
if (inode_vp == NULL) {
- /* If IRECLAIM is set this inode is
+ /*
+ * If IRECLAIM is set this inode is
* on its way out of the system,
* we need to pause and try again.
*/
XFS_STATS_INC(xs_ig_found);
finish_inode:
- if (lock_flags != 0) {
- xfs_ilock(ip, lock_flags);
- }
-
- newnode = (ip->i_d.di_mode == 0);
- if (newnode) {
+ if (ip->i_d.di_mode == 0) {
+ if (!(flags & IGET_CREATE))
+ return ENOENT;
xfs_iocore_inode_reinit(ip);
}
+
+ if (lock_flags != 0)
+ xfs_ilock(ip, lock_flags);
+
ip->i_flags &= ~XFS_ISTALE;
vn_trace_exit(vp, "xfs_iget.found",
if (lock_flags != 0) {
xfs_ilock(ip, lock_flags);
}
+
+ if ((ip->i_d.di_mode == 0) && !(flags & IGET_CREATE)) {
+ xfs_idestroy(ip);
+ return ENOENT;
+ }
/*
* Put ip on its hash chain, unless someone else hashed a duplicate
ih->ih_next = ip;
ip->i_udquot = ip->i_gdquot = NULL;
ih->ih_version++;
+ ip->i_flags |= XFS_INEW;
write_unlock(&ih->ih_lock);
XFS_MOUNT_IUNLOCK(mp);
- newnode = 1;
-
return_ip:
ASSERT(ip->i_df.if_ext_max ==
XFS_IFORK_DSIZE(ip) / sizeof(xfs_bmbt_rec_t));
xfs_mount_t *mp,
xfs_trans_t *tp,
xfs_ino_t ino,
+ uint flags,
uint lock_flags,
xfs_inode_t **ipp,
xfs_daddr_t bno)
if (inode->i_state & I_NEW) {
inode_allocate:
vn_initialize(inode);
- error = xfs_iget_core(vp, mp, tp, ino,
- lock_flags, ipp, bno);
+ error = xfs_iget_core(vp, mp, tp, ino, flags,
+ lock_flags, ipp, bno);
if (error) {
vn_mark_bad(vp);
if (inode->i_state & I_NEW)
vn_trace_entry(vp, "xfs_iput_new", (inst_t *)__return_address);
+ if ((ip->i_d.di_mode == 0)) {
+ ASSERT(!(ip->i_flags & XFS_IRECLAIMABLE));
+ vn_mark_bad(vp);
+ }
if (inode->i_state & I_NEW)
unlock_new_inode(inode);
if (lock_flags)
* This is because we're setting fields here we need
* to prevent others from looking at until we're done.
*/
- error = xfs_trans_iget(tp->t_mountp, tp, ino, XFS_ILOCK_EXCL, &ip);
+ error = xfs_trans_iget(tp->t_mountp, tp, ino,
+ IGET_CREATE, XFS_ILOCK_EXCL, &ip);
if (error != 0) {
return error;
}
#define XFS_IRECLAIM 0x0008 /* we have started reclaiming this inode */
#define XFS_ISTALE 0x0010 /* inode has been staled */
#define XFS_IRECLAIMABLE 0x0020 /* inode can be reclaimed */
+#define XFS_INEW 0x0040
/*
* Flags for inode locking.
/*
* xfs_iget.c prototypes.
*/
+
+#define IGET_CREATE 1
+
void xfs_ihash_init(struct xfs_mount *);
void xfs_ihash_free(struct xfs_mount *);
void xfs_chash_init(struct xfs_mount *);
struct xfs_trans *);
void xfs_inode_lock_init(xfs_inode_t *, struct vnode *);
int xfs_iget(struct xfs_mount *, struct xfs_trans *, xfs_ino_t,
- uint, xfs_inode_t **, xfs_daddr_t);
+ uint, uint, xfs_inode_t **, xfs_daddr_t);
void xfs_iput(xfs_inode_t *, uint);
void xfs_iput_new(xfs_inode_t *, uint);
void xfs_ilock(xfs_inode_t *, uint);
/* We're not being passed a pointer to a dinode. This happens
* if BULKSTAT_FG_IGET is selected. Do the iget.
*/
- error = xfs_iget(mp, NULL, ino, XFS_ILOCK_SHARED, &ip, bno);
+ error = xfs_iget(mp, NULL, ino, 0, XFS_ILOCK_SHARED, &ip, bno);
if (error) {
*stat = BULKSTAT_RV_NOTHING;
return error;
xfs_buf_relse(agibp);
ino = XFS_AGINO_TO_INO(mp, agno, agino);
- error = xfs_iget(mp, NULL, ino, 0, &ip, 0);
+ error = xfs_iget(mp, NULL, ino, 0, 0, &ip, 0);
ASSERT(error || (ip != NULL));
if (!error) {
* Get and sanity-check the root inode.
* Save the pointer to it in the mount structure.
*/
- error = xfs_iget(mp, NULL, sbp->sb_rootino, XFS_ILOCK_EXCL, &rip, 0);
+ error = xfs_iget(mp, NULL, sbp->sb_rootino, 0, XFS_ILOCK_EXCL, &rip, 0);
if (error) {
cmn_err(CE_WARN, "XFS: failed to read root inode");
goto error3;
/*
* Lock the inode.
*/
- if ((error = xfs_trans_iget(mp, tp, ino, XFS_ILOCK_EXCL, &ip)))
+ if ((error = xfs_trans_iget(mp, tp, ino, 0, XFS_ILOCK_EXCL, &ip)))
goto error_exit;
XFS_BMAP_INIT(&flist, &firstblock);
/*
/*
* Lock the bitmap inode.
*/
- if ((error = xfs_trans_iget(mp, tp, ino, XFS_ILOCK_EXCL,
+ if ((error = xfs_trans_iget(mp, tp, ino, 0, XFS_ILOCK_EXCL,
&ip)))
goto error_exit;
/*
/*
* Lock out other callers by grabbing the bitmap inode lock.
*/
- if ((error = xfs_trans_iget(mp, tp, mp->m_sb.sb_rbmino,
+ if ((error = xfs_trans_iget(mp, tp, 0, mp->m_sb.sb_rbmino,
XFS_ILOCK_EXCL, &ip)))
goto error_exit;
ASSERT(ip == mp->m_rbmip);
* Get the summary inode into the transaction.
*/
if ((error = xfs_trans_iget(mp, tp, mp->m_sb.sb_rsumino,
- XFS_ILOCK_EXCL, &ip)))
+ 0, XFS_ILOCK_EXCL, &ip)))
goto error_exit;
ASSERT(ip == mp->m_rsumip);
/*
/*
* Lock out other callers by grabbing the bitmap inode lock.
*/
- error = xfs_trans_iget(mp, tp, mp->m_sb.sb_rbmino, XFS_ILOCK_EXCL, &ip);
+ error = xfs_trans_iget(mp, tp, mp->m_sb.sb_rbmino, 0, XFS_ILOCK_EXCL, &ip);
if (error) {
return error;
}
/*
* Synchronize by locking the bitmap inode.
*/
- error = xfs_trans_iget(mp, tp, mp->m_sb.sb_rbmino, XFS_ILOCK_EXCL, &ip);
+ error = xfs_trans_iget(mp, tp, mp->m_sb.sb_rbmino, 0, XFS_ILOCK_EXCL, &ip);
if (error) {
return error;
}
sbp = &mp->m_sb;
if (sbp->sb_rbmino == NULLFSINO)
return 0;
- error = xfs_iget(mp, NULL, sbp->sb_rbmino, 0, &mp->m_rbmip, 0);
+ error = xfs_iget(mp, NULL, sbp->sb_rbmino, 0, 0, &mp->m_rbmip, 0);
if (error)
return error;
ASSERT(mp->m_rbmip != NULL);
ASSERT(sbp->sb_rsumino != NULLFSINO);
- error = xfs_iget(mp, NULL, sbp->sb_rsumino, 0, &mp->m_rsumip, 0);
+ error = xfs_iget(mp, NULL, sbp->sb_rsumino, 0, 0, &mp->m_rsumip, 0);
if (error) {
VN_RELE(XFS_ITOV(mp->m_rbmip));
return error;
__uint64_t seq; /* sequence number of file creation */
__uint64_t *seqp; /* pointer to seqno in inode */
- error = xfs_trans_iget(mp, tp, mp->m_sb.sb_rbmino, XFS_ILOCK_EXCL, &ip);
+ error = xfs_trans_iget(mp, tp, mp->m_sb.sb_rbmino, 0, XFS_ILOCK_EXCL, &ip);
if (error)
return error;
ASSERT(ip == mp->m_rbmip);
void xfs_trans_dquot_buf(xfs_trans_t *, struct xfs_buf *, uint);
void xfs_trans_inode_alloc_buf(xfs_trans_t *, struct xfs_buf *);
int xfs_trans_iget(struct xfs_mount *, xfs_trans_t *,
- xfs_ino_t , uint, struct xfs_inode **);
+ xfs_ino_t , uint, uint, struct xfs_inode **);
void xfs_trans_ijoin(xfs_trans_t *, struct xfs_inode *, uint);
void xfs_trans_ihold(xfs_trans_t *, struct xfs_inode *);
void xfs_trans_ihold_release(xfs_trans_t *, struct xfs_inode *);
xfs_mount_t *mp,
xfs_trans_t *tp,
xfs_ino_t ino,
+ uint flags,
uint lock_flags,
xfs_inode_t **ipp)
{
* If the transaction pointer is NULL, just call the normal
* xfs_iget().
*/
- if (tp == NULL) {
- return (xfs_iget(mp, NULL, ino, lock_flags, ipp, 0));
- }
+ if (tp == NULL)
+ return xfs_iget(mp, NULL, ino, flags, lock_flags, ipp, 0);
/*
* If we find the inode in core with this transaction
}
ASSERT(lock_flags & XFS_ILOCK_EXCL);
- error = xfs_iget(tp->t_mountp, tp, ino, lock_flags, &ip, 0);
+ error = xfs_iget(tp->t_mountp, tp, ino, flags, lock_flags, &ip, 0);
if (error) {
return error;
}
return 0;
}
-
/*
* Add the locked inode to the transaction.
* The inode must be locked, and it cannot be associated with any
* reservation in the inactive routine.
*/
xfs_iunlock(dp, lock_mode);
- error = xfs_iget(dp->i_mount, NULL, *inum, 0, ipp, 0);
+ error = xfs_iget(dp->i_mount, NULL, *inum, 0, 0, ipp, 0);
xfs_ilock(dp, lock_mode);
if (error) {
if (ino == 0)
return XFS_ERROR(ESTALE);
- error = xfs_iget(mp, NULL, ino, XFS_ILOCK_SHARED, &ip, 0);
+ error = xfs_iget(mp, NULL, ino, 0, XFS_ILOCK_SHARED, &ip, 0);
if (error) {
*vpp = NULL;
return error;