struct gfs2_dinode_host *di = &ip->i_di;
 
        inode->i_ino = ip->i_num.no_addr;
-       inode->i_nlink = di->di_nlink;
        i_size_write(inode, di->di_size);
        inode->i_atime.tv_sec = di->di_atime;
        inode->i_mtime.tv_sec = di->di_mtime;
 
        ip->i_inode.i_uid = be32_to_cpu(str->di_uid);
        ip->i_inode.i_gid = be32_to_cpu(str->di_gid);
-       di->di_nlink = be32_to_cpu(str->di_nlink);
+       /*
+        * We will need to review setting the nlink count here in the
+        * light of the forthcoming ro bind mount work. This is a reminder
+        * to do that.
+        */
+       ip->i_inode.i_nlink = be32_to_cpu(str->di_nlink);
        di->di_size = be64_to_cpu(str->di_size);
        di->di_blocks = be64_to_cpu(str->di_blocks);
        di->di_atime = be64_to_cpu(str->di_atime);
        u32 nlink;
        int error;
 
-       BUG_ON(ip->i_di.di_nlink != ip->i_inode.i_nlink);
-       nlink = ip->i_di.di_nlink + diff;
+       BUG_ON(diff != 1 && diff != -1);
+       nlink = ip->i_inode.i_nlink + diff;
 
        /* If we are reducing the nlink count, but the new value ends up being
           bigger than the old one, we must have underflowed. */
-       if (diff < 0 && nlink > ip->i_di.di_nlink) {
+       if (diff < 0 && nlink > ip->i_inode.i_nlink) {
                if (gfs2_consist_inode(ip))
                        gfs2_dinode_print(ip);
                return -EIO;
        if (error)
                return error;
 
-       ip->i_di.di_nlink = nlink;
+       if (diff > 0)
+               inc_nlink(&ip->i_inode);
+       else
+               drop_nlink(&ip->i_inode);
+
        ip->i_di.di_ctime = get_seconds();
-       ip->i_inode.i_nlink = nlink;
 
        gfs2_trans_add_bh(ip->i_gl, dibh, 1);
        gfs2_dinode_out(ip, dibh->b_data);
        brelse(dibh);
        mark_inode_dirty(&ip->i_inode);
 
-       if (ip->i_di.di_nlink == 0) {
+       if (ip->i_inode.i_nlink == 0) {
                struct gfs2_rgrpd *rgd;
                struct gfs2_holder ri_gh, rg_gh;
 
                if (error)
                        goto out_norgrp;
 
-               clear_nlink(&ip->i_inode);
                gfs2_unlink_di(&ip->i_inode); /* mark inode unlinked */
                gfs2_glock_dq_uninit(&rg_gh);
 out_norgrp:
                return error;
 
        /*  Don't create entries in an unlinked directory  */
-       if (!dip->i_di.di_nlink)
+       if (!dip->i_inode.i_nlink)
                return -EPERM;
 
        error = gfs2_dir_search(&dip->i_inode, name, NULL, NULL);
 
        if (dip->i_di.di_entries == (u32)-1)
                return -EFBIG;
-       if (S_ISDIR(mode) && dip->i_di.di_nlink == (u32)-1)
+       if (S_ISDIR(mode) && dip->i_inode.i_nlink == (u32)-1)
                return -EMLINK;
 
        return 0;
        error = gfs2_meta_inode_buffer(ip, &dibh);
        if (error)
                goto fail_end_trans;
-       ip->i_di.di_nlink = 1;
+       ip->i_inode.i_nlink = 1;
        gfs2_trans_add_bh(ip->i_gl, dibh, 1);
        gfs2_dinode_out(ip, dibh->b_data);
        brelse(dibh);
        if (error)
                return error;
 
-       error = gfs2_change_nlink(ip, -2);
+       /* It looks odd, but it really should be done twice */
+       error = gfs2_change_nlink(ip, -1);
+       if (error)
+               return error;
+
+       error = gfs2_change_nlink(ip, -1);
        if (error)
                return error;
 
 
        str->di_mode = cpu_to_be32(ip->i_inode.i_mode);
        str->di_uid = cpu_to_be32(ip->i_inode.i_uid);
        str->di_gid = cpu_to_be32(ip->i_inode.i_gid);
-       str->di_nlink = cpu_to_be32(di->di_nlink);
+       str->di_nlink = cpu_to_be32(ip->i_inode.i_nlink);
        str->di_size = cpu_to_be64(di->di_size);
        str->di_blocks = cpu_to_be64(di->di_blocks);
        str->di_atime = cpu_to_be64(di->di_atime);
 
        gfs2_inum_print(&ip->i_num);
 
-       pv(di, di_nlink, "%u");
        printk(KERN_INFO "  di_size = %llu\n", (unsigned long long)di->di_size);
        printk(KERN_INFO "  di_blocks = %llu\n", (unsigned long long)di->di_blocks);
        printk(KERN_INFO "  di_atime = %lld\n", (long long)di->di_atime);
 
        }
 
        error = -EINVAL;
-       if (!dip->i_di.di_nlink)
+       if (!dip->i_inode.i_nlink)
                goto out_gunlock;
        error = -EFBIG;
        if (dip->i_di.di_entries == (u32)-1)
        if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
                goto out_gunlock;
        error = -EINVAL;
-       if (!ip->i_di.di_nlink)
+       if (!ip->i_inode.i_nlink)
                goto out_gunlock;
        error = -EMLINK;
-       if (ip->i_di.di_nlink == (u32)-1)
+       if (ip->i_inode.i_nlink == (u32)-1)
                goto out_gunlock;
 
        alloc_required = error = gfs2_diradd_alloc_required(dir, &dentry->d_name);
 
        ip = ghs[1].gh_gl->gl_object;
 
-       ip->i_di.di_nlink = 2;
+       ip->i_inode.i_nlink = 2;
        ip->i_di.di_size = sdp->sd_sb.sb_bsize - sizeof(struct gfs2_dinode);
        ip->i_di.di_flags |= GFS2_DIF_JDATA;
        ip->i_di.di_payload_format = GFS2_FORMAT_DE;
                };
 
                if (odip != ndip) {
-                       if (!ndip->i_di.di_nlink) {
+                       if (!ndip->i_inode.i_nlink) {
                                error = -EINVAL;
                                goto out_gunlock;
                        }
                                goto out_gunlock;
                        }
                        if (S_ISDIR(ip->i_inode.i_mode) &&
-                           ndip->i_di.di_nlink == (u32)-1) {
+                           ndip->i_inode.i_nlink == (u32)-1) {
                                error = -EMLINK;
                                goto out_gunlock;
                        }