*/
teardown.d_inode = ip = LINVFS_GET_IP(vp);
teardown.d_name = dentry->d_name;
- remove_inode_hash(ip);
- make_bad_inode(ip);
+
+ vn_mark_bad(vp);
+
if (S_ISDIR(mode))
VOP_RMDIR(dvp, &teardown, NULL, err2);
else
vnode_t *vp = LINVFS_GET_VP(inode);
if (vp->v_type == VNON) {
- make_bad_inode(inode);
+ vn_mark_bad(vp);
} else if (S_ISREG(inode->i_mode)) {
inode->i_op = &linvfs_file_inode_operations;
inode->i_fop = &linvfs_file_operations;
bhv_insert(VN_BHV_HEAD(vp), inode_bhv);
}
- vp->v_type = IFTOVT(ip->i_d.di_mode);
-
- /* Have we been called during the new inode create process,
- * in which case we are too early to fill in the Linux inode.
- */
- if (vp->v_type == VNON)
- return;
-
- xfs_revalidate_inode(XFS_BHVTOM(bdp), vp, ip);
-
- /* For new inodes we need to set the ops vectors,
- * and unlock the inode.
+ /*
+ * We need to set the ops vectors, and unlock the inode, but if
+ * we have been called during the new inode create process, it is
+ * too early to fill in the Linux inode. We will get called a
+ * second time once the inode is properly set up, and then we can
+ * finish our work.
*/
- if (unlock && (inode->i_state & I_NEW)) {
+ if (ip->i_d.di_mode != 0 && unlock && (inode->i_state & I_NEW)) {
+ vp->v_type = IFTOVT(ip->i_d.di_mode);
+ xfs_revalidate_inode(XFS_BHVTOM(bdp), vp, ip);
xfs_set_inodeops(inode);
unlock_new_inode(inode);
}
#define VN_ATIMESET(vp, tvp) (LINVFS_GET_IP(vp)->i_atime = *(tvp))
#define VN_CTIMESET(vp, tvp) (LINVFS_GET_IP(vp)->i_ctime = *(tvp))
+/*
+ * Dealing with bad inodes
+ */
+static inline void vn_mark_bad(struct vnode *vp)
+{
+ make_bad_inode(LINVFS_GET_IP(vp));
+}
+
+static inline int VN_BAD(struct vnode *vp)
+{
+ return is_bad_inode(LINVFS_GET_IP(vp));
+}
+
/*
* Some useful predicates.
*/
error = xfs_iget_core(vp, mp, tp, ino,
lock_flags, ipp, bno);
if (error) {
- make_bad_inode(inode);
+ vn_mark_bad(vp);
if (inode->i_state & I_NEW)
unlock_new_inode(inode);
iput(inode);
vn_trace_entry(vp, "xfs_iput_new", (inst_t *)__return_address);
- /* We shouldn't get here without this being true, but just in case */
- if (inode->i_state & I_NEW) {
- make_bad_inode(inode);
+ if (inode->i_state & I_NEW)
unlock_new_inode(inode);
- }
if (lock_flags)
xfs_iunlock(ip, lock_flags);
VN_RELE(vp);
continue;
}
+ if (VN_BAD(vp)) {
+ ip = ip->i_mnext;
+ continue;
+ }
+
if (XFS_FORCED_SHUTDOWN(mp) && !(flags & SYNC_CLOSE)) {
XFS_MOUNT_IUNLOCK(mp);
kmem_free(ipointer, sizeof(xfs_iptr_t));
* If the inode is already free, then there can be nothing
* to clean up here.
*/
- if (ip->i_d.di_mode == 0) {
+ if (ip->i_d.di_mode == 0 || VN_BAD(vp)) {
ASSERT(ip->i_df.if_real_bytes == 0);
ASSERT(ip->i_df.if_broot_bytes == 0);
return VN_INACTIVE_CACHE;
vnode_t *vp;
vp = BHV_TO_VNODE(bdp);
+ ip = XFS_BHVTOI(bdp);
vn_trace_entry(vp, __FUNCTION__, (inst_t *)__return_address);
ASSERT(!VN_MAPPED(vp));
- ip = XFS_BHVTOI(bdp);
+
+ /* bad inode, get out here ASAP */
+ if (VN_BAD(vp)) {
+ xfs_ireclaim(ip);
+ return 0;
+ }
if ((ip->i_d.di_mode & S_IFMT) == S_IFREG) {
if (ip->i_d.di_size > 0) {
int sync_mode)
{
xfs_ihash_t *ih = ip->i_hash;
+ vnode_t *vp = XFS_ITOV_NULL(ip);
int error;
+ if (vp && VN_BAD(vp))
+ return 0;
+
/* The hash lock here protects a thread in xfs_iget_core from
* racing with us on linking the inode back with a vnode.
* Once we have the XFS_IRECLAIM flag set it will not touch
*/
write_lock(&ih->ih_lock);
if ((ip->i_flags & XFS_IRECLAIM) ||
- (!(ip->i_flags & XFS_IRECLAIMABLE) &&
- (XFS_ITOV_NULL(ip) == NULL))) {
+ (!(ip->i_flags & XFS_IRECLAIMABLE) && vp == NULL)) {
write_unlock(&ih->ih_lock);
if (locked) {
xfs_ifunlock(ip);