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(
*/
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
......
......@@ -141,7 +141,7 @@ xfs_set_inodeops(
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;
......@@ -223,20 +223,16 @@ xfs_initialize_vnode(
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.
/*
* 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 (vp->v_type == VNON)
return;
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);
/* For new inodes we need to set the ops vectors,
* and unlock the inode.
*/
if (unlock && (inode->i_state & I_NEW)) {
xfs_set_inodeops(inode);
unlock_new_inode(inode);
}
......
......@@ -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_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.
*/
......
......@@ -457,7 +457,7 @@ xfs_iget(
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);
......@@ -576,11 +576,8 @@ xfs_iput_new(xfs_inode_t *ip,
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);
......
......@@ -1055,6 +1055,11 @@ xfs_sync_inodes(
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));
......
......@@ -1611,7 +1611,7 @@ xfs_inactive(
* 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;
......@@ -3808,11 +3808,17 @@ xfs_reclaim(
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) {
......@@ -3890,8 +3896,12 @@ xfs_finish_reclaim(
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
......@@ -3899,8 +3909,7 @@ xfs_finish_reclaim(
*/
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);
......
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