]> git.hungrycats.org Git - linux/commitdiff
[XFS] fix handling of bad inodes
authorChristoph Hellwig <hch@sgi.com>
Wed, 29 Sep 2004 00:01:43 +0000 (10:01 +1000)
committerNathan Scott <nathans@sgi.com>
Wed, 29 Sep 2004 00:01:43 +0000 (10:01 +1000)
SGI Modid: xfs-linux:xfs-kern:179634a
Signed-off-by: Nathan Scott <nathans@sgi.com>
fs/xfs/linux-2.6/xfs_iops.c
fs/xfs/linux-2.6/xfs_super.c
fs/xfs/linux-2.6/xfs_vnode.h
fs/xfs/xfs_iget.c
fs/xfs/xfs_vfsops.c
fs/xfs/xfs_vnodeops.c

index d4ac35562869204e801bfa8beeebcefe58d5a5db..0cd5674cb3c559084423d381ae4da6625265ef3f 100644 (file)
@@ -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
index 0879377bbddbe86f3dfb1596417209abeacd3ea6..81dd6f593c7709d8c741d08bfa3e772f7386491c 100644 (file)
@@ -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.
-        */
-       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);
        }
index c274b7f589e4646029f240b16d49904d85d4bb74..3466465fa8d5ca5aa6ef923a3e442e0a2d82b9f7 100644 (file)
@@ -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.
  */
index d3a53b67b73c8ffc9a399bd62a4e7ed0f3f3643c..07641fc90d61350d834ce2b081382ddbaec32c8e 100644 (file)
@@ -457,7 +457,7 @@ inode_allocate:
                        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);
index 822bdf179e69dc342e987f08b451052569a7ad8f..dc6037a467a847d4af4987422f6641c493695bbc 100644 (file)
@@ -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));
index d662846dda39cc236077e529857f333e2e048e0f..4f568b5a4b5d9d313302d674f5854812741d4958 100644 (file)
@@ -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);