if (inode->i_state & I_NEW) {
                struct gfs2_sbd *sdp = GFS2_SB(inode);
-               umode_t mode = DT2IF(type);
+               umode_t mode;
                inode->i_private = ip;
-               inode->i_mode = mode;
-
-               if (S_ISREG(mode)) {
-                       inode->i_op = &gfs2_file_iops;
-                       inode->i_fop = &gfs2_file_fops;
-                       inode->i_mapping->a_ops = &gfs2_file_aops;
-               } else if (S_ISDIR(mode)) {
-                       inode->i_op = &gfs2_dir_iops;
-                       inode->i_fop = &gfs2_dir_fops;
-               } else if (S_ISLNK(mode)) {
-                       inode->i_op = &gfs2_symlink_iops;
-               } else {
-                       inode->i_op = &gfs2_dev_iops;
-               }
 
                error = gfs2_glock_get(sdp, no_addr, &gfs2_inode_glops, CREATE, &ip->i_gl);
                if (unlikely(error))
                        goto fail_iopen;
 
                gfs2_glock_put(io_gl);
+
+               /*
+                * We must read the inode in order to work out its type in
+                * this case. Note that this doesn't happen often as we normally
+                * know the type beforehand. This code path only occurs during
+                * unlinked inode recovery (where it is safe to do this glock,
+                * which is not true in the general case).
+                */
+               inode->i_mode = mode = DT2IF(type);
+               if (type == DT_UNKNOWN) {
+                       struct gfs2_holder gh;
+                       error = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &gh);
+                       if (unlikely(error))
+                               goto fail_glock;
+                       /* Inode is now uptodate */
+                       mode = inode->i_mode;
+                       gfs2_glock_dq_uninit(&gh);
+               }
+
+               if (S_ISREG(mode)) {
+                       inode->i_op = &gfs2_file_iops;
+                       inode->i_fop = &gfs2_file_fops;
+                       inode->i_mapping->a_ops = &gfs2_file_aops;
+               } else if (S_ISDIR(mode)) {
+                       inode->i_op = &gfs2_dir_iops;
+                       inode->i_fop = &gfs2_dir_fops;
+               } else if (S_ISLNK(mode)) {
+                       inode->i_op = &gfs2_symlink_iops;
+               } else {
+                       inode->i_op = &gfs2_dev_iops;
+               }
+
                unlock_new_inode(inode);
        }
 
        return inode;
+fail_glock:
+       gfs2_glock_dq(&ip->i_iopen_gh);
 fail_iopen:
        gfs2_glock_put(io_gl);
 fail_put:
 
 #include "ops_file.h"
 #include "util.h"
 #include "log.h"
+#include "inode.h"
 
 #define BFITNOENT ((u32)~0)
 
                1, 0, 0, 0
 };
 
+static u32 rgblk_search(struct gfs2_rgrpd *rgd, u32 goal,
+                        unsigned char old_state, unsigned char new_state);
+
 /**
  * gfs2_setbit - Set a bit in the bitmaps
  * @buffer: the buffer that holds the bitmaps
 
        rgd->rd_gl->gl_object = rgd;
        rgd->rd_rg_vn = rgd->rd_gl->gl_vn - 1;
+       rgd->rd_flags |= GFS2_RDF_CHECK;
        return error;
 }
 
        return ret;
 }
 
+/**
+ * try_rgrp_unlink - Look for any unlinked, allocated, but unused inodes
+ * @rgd: The rgrp
+ *
+ * Returns: The inode, if one has been found
+ */
+
+static struct inode *try_rgrp_unlink(struct gfs2_rgrpd *rgd, u64 *last_unlinked)
+{
+       struct inode *inode;
+       u32 goal = 0;
+       u64 ino;
+
+       for(;;) {
+               goal = rgblk_search(rgd, goal, GFS2_BLKST_UNLINKED,
+                                   GFS2_BLKST_UNLINKED);
+               if (goal == 0)
+                       return 0;
+               ino = goal + rgd->rd_data0;
+               if (ino <= *last_unlinked)
+                       continue;
+               *last_unlinked = ino;
+               inode = gfs2_inode_lookup(rgd->rd_sbd->sd_vfs, ino, DT_UNKNOWN);
+               if (!IS_ERR(inode))
+                       return inode;
+       }
+
+       rgd->rd_flags &= ~GFS2_RDF_CHECK;
+       return NULL;
+}
+
 /**
  * recent_rgrp_first - get first RG from "recent" list
  * @sdp: The GFS2 superblock
  * Returns: errno
  */
 
-static int get_local_rgrp(struct gfs2_inode *ip)
+static struct inode *get_local_rgrp(struct gfs2_inode *ip, u64 *last_unlinked)
 {
+       struct inode *inode = NULL;
        struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
        struct gfs2_rgrpd *rgd, *begin = NULL;
        struct gfs2_alloc *al = &ip->i_alloc;
                case 0:
                        if (try_rgrp_fit(rgd, al))
                                goto out;
+                       if (rgd->rd_flags & GFS2_RDF_CHECK)
+                               inode = try_rgrp_unlink(rgd, last_unlinked);
                        gfs2_glock_dq_uninit(&al->al_rgd_gh);
+                       if (inode)
+                               return inode;
                        rgd = recent_rgrp_next(rgd, 1);
                        break;
 
                        break;
 
                default:
-                       return error;
+                       return ERR_PTR(error);
                }
        }
 
                case 0:
                        if (try_rgrp_fit(rgd, al))
                                goto out;
+                       if (rgd->rd_flags & GFS2_RDF_CHECK)
+                               inode = try_rgrp_unlink(rgd, last_unlinked);
                        gfs2_glock_dq_uninit(&al->al_rgd_gh);
+                       if (inode)
+                               return inode;
                        break;
 
                case GLR_TRYFAILED:
                        break;
 
                default:
-                       return error;
+                       return ERR_PTR(error);
                }
 
                rgd = gfs2_rgrpd_get_next(rgd);
 
                if (rgd == begin) {
                        if (++loops >= 3)
-                               return -ENOSPC;
+                               return ERR_PTR(-ENOSPC);
                        if (!skipped)
                                loops++;
                        flags = 0;
                forward_rgrp_set(sdp, rgd);
        }
 
-       return 0;
+       return NULL;
 }
 
 /**
 {
        struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
        struct gfs2_alloc *al = &ip->i_alloc;
+       struct inode *inode;
        int error = 0;
+       u64 last_unlinked = 0;
 
        if (gfs2_assert_warn(sdp, al->al_requested))
                return -EINVAL;
 
+try_again:
        /* We need to hold the rindex unless the inode we're using is
           the rindex itself, in which case it's already held. */
        if (ip != GFS2_I(sdp->sd_rindex))
        if (error)
                return error;
 
-       error = get_local_rgrp(ip);
-       if (error) {
+       inode = get_local_rgrp(ip, &last_unlinked);
+       if (inode) {
                if (ip != GFS2_I(sdp->sd_rindex))
                        gfs2_glock_dq_uninit(&al->al_ri_gh);
-               return error;
+               if (IS_ERR(inode))
+                       return PTR_ERR(inode);
+               iput(inode);
+               gfs2_log_flush(sdp, NULL);
+               goto try_again;
        }
 
        al->al_file = file;
  */
 
 static u32 rgblk_search(struct gfs2_rgrpd *rgd, u32 goal,
-                            unsigned char old_state, unsigned char new_state)
+                       unsigned char old_state, unsigned char new_state)
 {
        struct gfs2_bitmap *bi = NULL;
        u32 length = rgd->rd_length;
                goal = 0;
        }
 
-       if (gfs2_assert_withdraw(rgd->rd_sbd, x <= length))
-               blk = 0;
+       if (old_state != new_state) {
+               gfs2_assert_withdraw(rgd->rd_sbd, blk != BFITNOENT);
 
-       gfs2_trans_add_bh(rgd->rd_gl, bi->bi_bh, 1);
-       gfs2_setbit(rgd, bi->bi_bh->b_data + bi->bi_offset,
-                   bi->bi_len, blk, new_state);
-       if (bi->bi_clone)
-               gfs2_setbit(rgd, bi->bi_clone + bi->bi_offset,
+               gfs2_trans_add_bh(rgd->rd_gl, bi->bi_bh, 1);
+               gfs2_setbit(rgd, bi->bi_bh->b_data + bi->bi_offset,
                            bi->bi_len, blk, new_state);
+               if (bi->bi_clone)
+                       gfs2_setbit(rgd, bi->bi_clone + bi->bi_offset,
+                                   bi->bi_len, blk, new_state);
+       }
 
-       return bi->bi_start * GFS2_NBBY + blk;
+       return (blk == BFITNOENT) ? 0 : (bi->bi_start * GFS2_NBBY) + blk;
 }
 
 /**