Commit 6546e97b authored by Christoph Hellwig's avatar Christoph Hellwig Committed by Nathan Scott

[XFS] fix handling of bad inodes

SGI Modid: xfs-linux:xfs-kern:179634a
Signed-off-by: default avatarNathan Scott <nathans@sgi.com>
parent f688b1b8
...@@ -174,8 +174,9 @@ linvfs_mknod( ...@@ -174,8 +174,9 @@ linvfs_mknod(
*/ */
teardown.d_inode = ip = LINVFS_GET_IP(vp); teardown.d_inode = ip = LINVFS_GET_IP(vp);
teardown.d_name = dentry->d_name; teardown.d_name = dentry->d_name;
remove_inode_hash(ip);
make_bad_inode(ip); vn_mark_bad(vp);
if (S_ISDIR(mode)) if (S_ISDIR(mode))
VOP_RMDIR(dvp, &teardown, NULL, err2); VOP_RMDIR(dvp, &teardown, NULL, err2);
else else
......
...@@ -141,7 +141,7 @@ xfs_set_inodeops( ...@@ -141,7 +141,7 @@ xfs_set_inodeops(
vnode_t *vp = LINVFS_GET_VP(inode); vnode_t *vp = LINVFS_GET_VP(inode);
if (vp->v_type == VNON) { if (vp->v_type == VNON) {
make_bad_inode(inode); vn_mark_bad(vp);
} else if (S_ISREG(inode->i_mode)) { } else if (S_ISREG(inode->i_mode)) {
inode->i_op = &linvfs_file_inode_operations; inode->i_op = &linvfs_file_inode_operations;
inode->i_fop = &linvfs_file_operations; inode->i_fop = &linvfs_file_operations;
...@@ -223,20 +223,16 @@ xfs_initialize_vnode( ...@@ -223,20 +223,16 @@ xfs_initialize_vnode(
bhv_insert(VN_BHV_HEAD(vp), inode_bhv); bhv_insert(VN_BHV_HEAD(vp), inode_bhv);
} }
vp->v_type = IFTOVT(ip->i_d.di_mode); /*
* We need to set the ops vectors, and unlock the inode, but if
/* Have we been called during the new inode create process, * we have been called during the new inode create process, it is
* in which case we are too early to fill in the Linux inode. * 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
if (vp->v_type == VNON) * finish our work.
return;
xfs_revalidate_inode(XFS_BHVTOM(bdp), vp, ip);
/* For new inodes we need to set the ops vectors,
* and unlock the inode.
*/ */
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); xfs_set_inodeops(inode);
unlock_new_inode(inode); unlock_new_inode(inode);
} }
......
...@@ -594,6 +594,19 @@ static __inline__ void vn_flagclr(struct vnode *vp, uint flag) ...@@ -594,6 +594,19 @@ static __inline__ void vn_flagclr(struct vnode *vp, uint flag)
#define VN_ATIMESET(vp, tvp) (LINVFS_GET_IP(vp)->i_atime = *(tvp)) #define VN_ATIMESET(vp, tvp) (LINVFS_GET_IP(vp)->i_atime = *(tvp))
#define VN_CTIMESET(vp, tvp) (LINVFS_GET_IP(vp)->i_ctime = *(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. * Some useful predicates.
*/ */
......
...@@ -457,7 +457,7 @@ xfs_iget( ...@@ -457,7 +457,7 @@ xfs_iget(
error = xfs_iget_core(vp, mp, tp, ino, error = xfs_iget_core(vp, mp, tp, ino,
lock_flags, ipp, bno); lock_flags, ipp, bno);
if (error) { if (error) {
make_bad_inode(inode); vn_mark_bad(vp);
if (inode->i_state & I_NEW) if (inode->i_state & I_NEW)
unlock_new_inode(inode); unlock_new_inode(inode);
iput(inode); iput(inode);
...@@ -576,11 +576,8 @@ xfs_iput_new(xfs_inode_t *ip, ...@@ -576,11 +576,8 @@ xfs_iput_new(xfs_inode_t *ip,
vn_trace_entry(vp, "xfs_iput_new", (inst_t *)__return_address); 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)
if (inode->i_state & I_NEW) {
make_bad_inode(inode);
unlock_new_inode(inode); unlock_new_inode(inode);
}
if (lock_flags) if (lock_flags)
xfs_iunlock(ip, lock_flags); xfs_iunlock(ip, lock_flags);
VN_RELE(vp); VN_RELE(vp);
......
...@@ -1055,6 +1055,11 @@ xfs_sync_inodes( ...@@ -1055,6 +1055,11 @@ xfs_sync_inodes(
continue; continue;
} }
if (VN_BAD(vp)) {
ip = ip->i_mnext;
continue;
}
if (XFS_FORCED_SHUTDOWN(mp) && !(flags & SYNC_CLOSE)) { if (XFS_FORCED_SHUTDOWN(mp) && !(flags & SYNC_CLOSE)) {
XFS_MOUNT_IUNLOCK(mp); XFS_MOUNT_IUNLOCK(mp);
kmem_free(ipointer, sizeof(xfs_iptr_t)); kmem_free(ipointer, sizeof(xfs_iptr_t));
......
...@@ -1611,7 +1611,7 @@ xfs_inactive( ...@@ -1611,7 +1611,7 @@ xfs_inactive(
* If the inode is already free, then there can be nothing * If the inode is already free, then there can be nothing
* to clean up here. * 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_real_bytes == 0);
ASSERT(ip->i_df.if_broot_bytes == 0); ASSERT(ip->i_df.if_broot_bytes == 0);
return VN_INACTIVE_CACHE; return VN_INACTIVE_CACHE;
...@@ -3808,11 +3808,17 @@ xfs_reclaim( ...@@ -3808,11 +3808,17 @@ xfs_reclaim(
vnode_t *vp; vnode_t *vp;
vp = BHV_TO_VNODE(bdp); vp = BHV_TO_VNODE(bdp);
ip = XFS_BHVTOI(bdp);
vn_trace_entry(vp, __FUNCTION__, (inst_t *)__return_address); vn_trace_entry(vp, __FUNCTION__, (inst_t *)__return_address);
ASSERT(!VN_MAPPED(vp)); 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_mode & S_IFMT) == S_IFREG) {
if (ip->i_d.di_size > 0) { if (ip->i_d.di_size > 0) {
...@@ -3890,8 +3896,12 @@ xfs_finish_reclaim( ...@@ -3890,8 +3896,12 @@ xfs_finish_reclaim(
int sync_mode) int sync_mode)
{ {
xfs_ihash_t *ih = ip->i_hash; xfs_ihash_t *ih = ip->i_hash;
vnode_t *vp = XFS_ITOV_NULL(ip);
int error; int error;
if (vp && VN_BAD(vp))
return 0;
/* The hash lock here protects a thread in xfs_iget_core from /* The hash lock here protects a thread in xfs_iget_core from
* racing with us on linking the inode back with a vnode. * racing with us on linking the inode back with a vnode.
* Once we have the XFS_IRECLAIM flag set it will not touch * Once we have the XFS_IRECLAIM flag set it will not touch
...@@ -3899,8 +3909,7 @@ xfs_finish_reclaim( ...@@ -3899,8 +3909,7 @@ xfs_finish_reclaim(
*/ */
write_lock(&ih->ih_lock); write_lock(&ih->ih_lock);
if ((ip->i_flags & XFS_IRECLAIM) || if ((ip->i_flags & XFS_IRECLAIM) ||
(!(ip->i_flags & XFS_IRECLAIMABLE) && (!(ip->i_flags & XFS_IRECLAIMABLE) && vp == NULL)) {
(XFS_ITOV_NULL(ip) == NULL))) {
write_unlock(&ih->ih_lock); write_unlock(&ih->ih_lock);
if (locked) { if (locked) {
xfs_ifunlock(ip); xfs_ifunlock(ip);
......
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