mempool_free(ioend, xfs_ioend_pool);
 }
 
+/*
+ * Update on-disk file size now that data has been written to disk.
+ * The current in-memory file size is i_size.  If a write is beyond
+ * eof io_new_size will be the intended file size until i_size is
+ * updated.  If this write does not extend all the way to the valid
+ * file size then restrict this update to the end of the write.
+ */
+STATIC void
+xfs_setfilesize(
+       xfs_ioend_t             *ioend)
+{
+       xfs_inode_t             *ip;
+       xfs_fsize_t             isize;
+       xfs_fsize_t             bsize;
+
+       ip = xfs_vtoi(ioend->io_vnode);
+
+       ASSERT((ip->i_d.di_mode & S_IFMT) == S_IFREG);
+       ASSERT(ioend->io_type != IOMAP_READ);
+
+       if (unlikely(ioend->io_error))
+               return;
+
+       bsize = ioend->io_offset + ioend->io_size;
+
+       xfs_ilock(ip, XFS_ILOCK_EXCL);
+
+       isize = MAX(ip->i_size, ip->i_iocore.io_new_size);
+       isize = MIN(isize, bsize);
+
+       if (ip->i_d.di_size < isize) {
+               ip->i_d.di_size = isize;
+               ip->i_update_core = 1;
+               ip->i_update_size = 1;
+       }
+
+       xfs_iunlock(ip, XFS_ILOCK_EXCL);
+}
+
 /*
  * Buffered IO write completion for delayed allocate extents.
- * TODO: Update ondisk isize now that we know the file data
- * has been flushed (i.e. the notorious "NULL file" problem).
  */
 STATIC void
 xfs_end_bio_delalloc(
        xfs_ioend_t             *ioend =
                container_of(work, xfs_ioend_t, io_work);
 
+       xfs_setfilesize(ioend);
        xfs_destroy_ioend(ioend);
 }
 
        xfs_ioend_t             *ioend =
                container_of(work, xfs_ioend_t, io_work);
 
+       xfs_setfilesize(ioend);
        xfs_destroy_ioend(ioend);
 }
 
        xfs_off_t               offset = ioend->io_offset;
        size_t                  size = ioend->io_size;
 
-       if (likely(!ioend->io_error))
+       if (likely(!ioend->io_error)) {
                bhv_vop_bmap(vp, offset, size, BMAPI_UNWRITTEN, NULL, NULL);
+               xfs_setfilesize(ioend);
+       }
+       xfs_destroy_ioend(ioend);
+}
+
+/*
+ * IO read completion for regular, written extents.
+ */
+STATIC void
+xfs_end_bio_read(
+       struct work_struct      *work)
+{
+       xfs_ioend_t             *ioend =
+               container_of(work, xfs_ioend_t, io_work);
+
        xfs_destroy_ioend(ioend);
 }
 
                INIT_WORK(&ioend->io_work, xfs_end_bio_unwritten);
        else if (type == IOMAP_DELAY)
                INIT_WORK(&ioend->io_work, xfs_end_bio_delalloc);
+       else if (type == IOMAP_READ)
+               INIT_WORK(&ioend->io_work, xfs_end_bio_read);
        else
                INIT_WORK(&ioend->io_work, xfs_end_bio_written);
 
        bh = head = page_buffers(page);
        offset = page_offset(page);
        flags = -1;
-       type = 0;
+       type = IOMAP_READ;
 
        /* TODO: cleanup count and page_dirty */
 
                         * That means it must already have extents allocated
                         * underneath it. Map the extent by reading it.
                         */
-                       if (!iomap_valid || type != 0) {
+                       if (!iomap_valid || type != IOMAP_READ) {
                                flags = BMAPI_READ;
                                size = xfs_probe_cluster(inode, page, bh,
                                                                head, 1);
                                iomap_valid = xfs_iomap_valid(&iomap, offset);
                        }
 
-                       type = 0;
+                       type = IOMAP_READ;
                        if (!test_and_set_bit(BH_Lock, &bh->b_state)) {
                                ASSERT(buffer_mapped(bh));
                                if (iomap_valid)
         * completion handler in the future, in which case all this can
         * go away.
         */
-       if (private && size > 0) {
-               ioend->io_offset = offset;
-               ioend->io_size = size;
+       ioend->io_offset = offset;
+       ioend->io_size = size;
+       if (ioend->io_type == IOMAP_READ) {
+               xfs_finish_ioend(ioend);
+       } else if (private && size > 0) {
                xfs_finish_ioend(ioend);
        } else {
-               xfs_destroy_ioend(ioend);
+               /*
+                * A direct I/O write ioend starts it's life in unwritten
+                * state in case they map an unwritten extent.  This write
+                * didn't map an unwritten extent so switch it's completion
+                * handler.
+                */
+               INIT_WORK(&ioend->io_work, xfs_end_bio_written);
+               xfs_finish_ioend(ioend);
        }
 
        /*
        if (error)
                return -error;
 
-       iocb->private = xfs_alloc_ioend(inode, IOMAP_UNWRITTEN);
-
        if (rw == WRITE) {
+               iocb->private = xfs_alloc_ioend(inode, IOMAP_UNWRITTEN);
                ret = blockdev_direct_IO_own_locking(rw, iocb, inode,
                        iomap.iomap_target->bt_bdev,
                        iov, offset, nr_segs,
                        xfs_get_blocks_direct,
                        xfs_end_io_direct);
        } else {
+               iocb->private = xfs_alloc_ioend(inode, IOMAP_READ);
                ret = blockdev_direct_IO_no_locking(rw, iocb, inode,
                        iomap.iomap_target->bt_bdev,
                        iov, offset, nr_segs,
 
                                mp->m_rtdev_targp : mp->m_ddev_targp;
                if ((*offset & target->bt_smask) ||
                    (size & target->bt_smask)) {
-                       if (*offset == ip->i_d.di_size) {
+                       if (*offset == ip->i_size) {
                                return (0);
                        }
                        return -XFS_ERROR(EINVAL);
 {
        xfs_inode_t             *ip = XFS_BHVTOI(bdp);
        xfs_mount_t             *mp = ip->i_mount;
+       xfs_iocore_t            *io = &ip->i_iocore;
        ssize_t                 ret;
        struct inode            *inode = outfilp->f_mapping->host;
-       xfs_fsize_t             isize;
+       xfs_fsize_t             isize, new_size;
 
        XFS_STATS_INC(xs_write_calls);
        if (XFS_FORCED_SHUTDOWN(ip->i_mount))
                        return -error;
                }
        }
+
+       new_size = *ppos + count;
+
+       xfs_ilock(ip, XFS_ILOCK_EXCL);
+       if (new_size > ip->i_size)
+               io->io_new_size = new_size;
+       xfs_iunlock(ip, XFS_ILOCK_EXCL);
+
        xfs_rw_enter_trace(XFS_SPLICE_WRITE_ENTER, &ip->i_iocore,
                           pipe, count, *ppos, ioflags);
        ret = generic_file_splice_write(pipe, outfilp, ppos, count, flags);
        if (unlikely(ret < 0 && ret != -EFAULT && *ppos > isize))
                *ppos = isize;
 
-       if (*ppos > ip->i_d.di_size) {
+       if (*ppos > ip->i_size) {
                xfs_ilock(ip, XFS_ILOCK_EXCL);
-               if (*ppos > ip->i_d.di_size) {
-                       ip->i_d.di_size = *ppos;
-                       i_size_write(inode, *ppos);
-                       ip->i_update_core = 1;
-                       ip->i_update_size = 1;
-               }
+               if (*ppos > ip->i_size)
+                       ip->i_size = *ppos;
+               xfs_iunlock(ip, XFS_ILOCK_EXCL);
+       }
+
+       if (io->io_new_size) {
+               xfs_ilock(ip, XFS_ILOCK_EXCL);
+               io->io_new_size = 0;
+               if (ip->i_d.di_size > ip->i_size)
+                       ip->i_d.di_size = ip->i_size;
                xfs_iunlock(ip, XFS_ILOCK_EXCL);
        }
        xfs_iunlock(ip, XFS_IOLOCK_EXCL);
                goto out_unlock_mutex;
        }
 
-       isize = i_size_read(inode);
-
        if (ioflags & IO_ISDIRECT) {
                xfs_buftarg_t   *target =
                        (xip->i_d.di_flags & XFS_DIFLAG_REALTIME) ?
                        return XFS_ERROR(-EINVAL);
                }
 
-               if (!need_i_mutex && (VN_CACHED(vp) || pos > isize)) {
+               if (!need_i_mutex && (VN_CACHED(vp) || pos > xip->i_size)) {
                        xfs_iunlock(xip, XFS_ILOCK_EXCL|iolock);
                        iolock = XFS_IOLOCK_EXCL;
                        locktype = VRWLOCK_WRITE;
        }
 
        new_size = pos + count;
-       if (new_size > isize)
+       if (new_size > xip->i_size)
                io->io_new_size = new_size;
 
        if ((DM_EVENT_ENABLED(vp->v_vfsp, xip, DM_EVENT_WRITE) &&
                                      pos, count,
                                      dmflags, &locktype);
                if (error) {
-                       xfs_iunlock(xip, iolock);
-                       goto out_unlock_mutex;
+                       goto out_unlock_internal;
                }
                xfs_ilock(xip, XFS_ILOCK_EXCL);
                eventsent = 1;
                 * event prevents another call to XFS_SEND_DATA, which is
                 * what allows the size to change in the first place.
                 */
-               if ((file->f_flags & O_APPEND) && savedsize != isize) {
+               if ((file->f_flags & O_APPEND) && savedsize != xip->i_size)
                        goto start;
-               }
        }
 
        if (likely(!(ioflags & IO_INVIS))) {
         * to zero it out up to the new size.
         */
 
-       if (pos > isize) {
-               error = xfs_zero_eof(BHV_TO_VNODE(bdp), io, pos, isize);
+       if (pos > xip->i_size) {
+               error = xfs_zero_eof(BHV_TO_VNODE(bdp), io, pos, xip->i_size);
                if (error) {
-                       xfs_iunlock(xip, XFS_ILOCK_EXCL|iolock);
-                       goto out_unlock_mutex;
+                       xfs_iunlock(xip, XFS_ILOCK_EXCL);
+                       goto out_unlock_internal;
                }
        }
        xfs_iunlock(xip, XFS_ILOCK_EXCL);
                if (likely(!error))
                        error = -remove_suid(file->f_path.dentry);
                if (unlikely(error)) {
-                       xfs_iunlock(xip, iolock);
-                       goto out_unlock_mutex;
+                       goto out_unlock_internal;
                }
        }
 
                error = XFS_SEND_NAMESP(xip->i_mount, DM_EVENT_NOSPACE, vp,
                                DM_RIGHT_NULL, vp, DM_RIGHT_NULL, NULL, NULL,
                                0, 0, 0); /* Delay flag intentionally  unused */
-               if (error)
-                       goto out_nounlocks;
                if (need_i_mutex)
                        mutex_lock(&inode->i_mutex);
                xfs_rwlock(bdp, locktype);
-               pos = xip->i_d.di_size;
+               if (error)
+                       goto out_unlock_internal;
+               pos = xip->i_size;
                ret = 0;
                goto retry;
        }
        if (unlikely(ret < 0 && ret != -EFAULT && *offset > isize))
                *offset = isize;
 
-       if (*offset > xip->i_d.di_size) {
+       if (*offset > xip->i_size) {
                xfs_ilock(xip, XFS_ILOCK_EXCL);
-               if (*offset > xip->i_d.di_size) {
-                       xip->i_d.di_size = *offset;
-                       i_size_write(inode, *offset);
-                       xip->i_update_core = 1;
-                       xip->i_update_size = 1;
-               }
+               if (*offset > xip->i_size)
+                       xip->i_size = *offset;
                xfs_iunlock(xip, XFS_ILOCK_EXCL);
        }
 
 
                error = sync_page_range(inode, mapping, pos, ret);
                if (!error)
-                       error = ret;
-               return error;
+                       error = -ret;
+               if (need_i_mutex)
+                       mutex_lock(&inode->i_mutex);
+               xfs_rwlock(bdp, locktype);
        }
 
  out_unlock_internal:
+       if (io->io_new_size) {
+               xfs_ilock(xip, XFS_ILOCK_EXCL);
+               io->io_new_size = 0;
+               /*
+                * If this was a direct or synchronous I/O that failed (such
+                * as ENOSPC) then part of the I/O may have been written to
+                * disk before the error occured.  In this case the on-disk
+                * file size may have been adjusted beyond the in-memory file
+                * size and now needs to be truncated back.
+                */
+               if (xip->i_d.di_size > xip->i_size)
+                       xip->i_d.di_size = xip->i_size;
+               xfs_iunlock(xip, XFS_ILOCK_EXCL);
+       }
        xfs_rwunlock(bdp, locktype);
  out_unlock_mutex:
        if (need_i_mutex)
                mutex_unlock(&inode->i_mutex);
- out_nounlocks:
        return -error;
 }
 
 
        xfs_bmbt_irec_t s;              /* internal version of extent */
 
 #ifndef DEBUG
-       if (whichfork == XFS_DATA_FORK)
-               return ip->i_d.di_size == ip->i_mount->m_sb.sb_blocksize;
+       if (whichfork == XFS_DATA_FORK) {
+               return ((ip->i_d.di_mode & S_IFMT) == S_IFREG) ?
+                       (ip->i_size == ip->i_mount->m_sb.sb_blocksize) :
+                       (ip->i_d.di_size == ip->i_mount->m_sb.sb_blocksize);
+       }
 #endif /* !DEBUG */
        if (XFS_IFORK_NEXTENTS(ip, whichfork) != 1)
                return 0;
        xfs_bmbt_get_all(ep, &s);
        rval = s.br_startoff == 0 && s.br_blockcount == 1;
        if (rval && whichfork == XFS_DATA_FORK)
-               ASSERT(ip->i_d.di_size == ip->i_mount->m_sb.sb_blocksize);
+               ASSERT(ip->i_size == ip->i_mount->m_sb.sb_blocksize);
        return rval;
 }
 
                        fixlen = XFS_MAXIOFFSET(mp);
                } else {
                        prealloced = 0;
-                       fixlen = ip->i_d.di_size;
+                       fixlen = ip->i_size;
                }
        } else {
                prealloced = 0;
 
        xfs_ilock(ip, XFS_IOLOCK_SHARED);
 
-       if (whichfork == XFS_DATA_FORK && ip->i_delayed_blks) {
+       if (whichfork == XFS_DATA_FORK &&
+               (ip->i_delayed_blks || ip->i_size > ip->i_d.di_size)) {
                /* xfs_fsize_t last_byte = xfs_file_last_byte(ip); */
                error = bhv_vop_flush_pages(vp, (xfs_off_t)0, -1, 0, FI_REMAPF);
        }
 
                        return XFS_ERROR(EFSCORRUPTED);
                }
                ip->i_d.di_size = 0;
+               ip->i_size = 0;
                ip->i_df.if_u2.if_rdev = INT_GET(dip->di_u.di_dev, ARCH_CONVERT);
                break;
 
        }
 
        ip->i_delayed_blks = 0;
+       ip->i_size = ip->i_d.di_size;
 
        /*
         * Mark the buffer containing the inode as something to keep
        }
 
        ip->i_d.di_size = 0;
+       ip->i_size = 0;
        ip->i_d.di_nextents = 0;
        ASSERT(ip->i_d.di_nblocks == 0);
        xfs_ichgtime(ip, XFS_ICHGTIME_CHG|XFS_ICHGTIME_ACC|XFS_ICHGTIME_MOD);
        } else {
                last_block = 0;
        }
-       size_last_block = XFS_B_TO_FSB(mp, (xfs_ufsize_t)ip->i_d.di_size);
+       size_last_block = XFS_B_TO_FSB(mp, (xfs_ufsize_t)ip->i_size);
        last_block = XFS_FILEOFF_MAX(last_block, size_last_block);
 
        last_byte = XFS_FSB_TO_B(mp, last_block);
        int             error = 0;
 
        ASSERT(ismrlocked(&ip->i_iolock, MR_UPDATE) != 0);
-       ASSERT((new_size == 0) || (new_size <= ip->i_d.di_size));
+       ASSERT((new_size == 0) || (new_size <= ip->i_size));
        ASSERT((flags == XFS_ITRUNC_DEFINITE) ||
               (flags == XFS_ITRUNC_MAYBE));
 
 
        ASSERT(ismrlocked(&ip->i_iolock, MR_UPDATE) != 0);
        ASSERT(ismrlocked(&ip->i_lock, MR_UPDATE) != 0);
-       ASSERT((new_size == 0) || (new_size <= ip->i_d.di_size));
+       ASSERT((new_size == 0) || (new_size <= ip->i_size));
        ASSERT(*tp != NULL);
        ASSERT((*tp)->t_flags & XFS_TRANS_PERM_LOG_RES);
        ASSERT(ip->i_transp == *tp);
         */
        if (fork == XFS_DATA_FORK) {
                if (ip->i_d.di_nextents > 0) {
-                       ip->i_d.di_size = new_size;
-                       xfs_trans_log_inode(ntp, ip, XFS_ILOG_CORE);
+                       /*
+                        * If we are not changing the file size then do
+                        * not update the on-disk file size - we may be
+                        * called from xfs_inactive_free_eofblocks().  If we
+                        * update the on-disk file size and then the system
+                        * crashes before the contents of the file are
+                        * flushed to disk then the files may be full of
+                        * holes (ie NULL files bug).
+                        */
+                       if (ip->i_size != new_size) {
+                               ip->i_d.di_size = new_size;
+                               ip->i_size = new_size;
+                               xfs_trans_log_inode(ntp, ip, XFS_ILOG_CORE);
+                       }
                }
        } else if (sync) {
                ASSERT(!(mp->m_flags & XFS_MOUNT_WSYNC));
         */
        if (fork == XFS_DATA_FORK) {
                xfs_isize_check(mp, ip, new_size);
-               ip->i_d.di_size = new_size;
+               /*
+                * If we are not changing the file size then do
+                * not update the on-disk file size - we may be
+                * called from xfs_inactive_free_eofblocks().  If we
+                * update the on-disk file size and then the system
+                * crashes before the contents of the file are
+                * flushed to disk then the files may be full of
+                * holes (ie NULL files bug).
+                */
+               if (ip->i_size != new_size) {
+                       ip->i_d.di_size = new_size;
+                       ip->i_size = new_size;
+               }
        }
        xfs_trans_log_inode(ntp, ip, XFS_ILOG_CORE);
        ASSERT((new_size != 0) ||
 
        ASSERT(ismrlocked(&(ip->i_lock), MR_UPDATE) != 0);
        ASSERT(ismrlocked(&(ip->i_iolock), MR_UPDATE) != 0);
-       ASSERT(new_size > ip->i_d.di_size);
+       ASSERT(new_size > ip->i_size);
 
        /*
         * Zero any pages that may have been created by
         * and any blocks between the old and new file sizes.
         */
        error = xfs_zero_eof(XFS_ITOV(ip), &ip->i_iocore, new_size,
-                            ip->i_d.di_size);
+                            ip->i_size);
        return error;
 }
 
        ASSERT(ismrlocked(&(ip->i_lock), MR_UPDATE) != 0);
        ASSERT(ismrlocked(&(ip->i_iolock), MR_UPDATE) != 0);
        ASSERT(ip->i_transp == tp);
-       ASSERT(new_size > ip->i_d.di_size);
+       ASSERT(new_size > ip->i_size);
 
        /*
         * Update the file size.  Update the inode change timestamp
         * if change_flag set.
         */
        ip->i_d.di_size = new_size;
+       ip->i_size = new_size;
        if (change_flag)
                xfs_ichgtime(ip, XFS_ICHGTIME_CHG);
        xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
        ASSERT(ip->i_d.di_nlink == 0);
        ASSERT(ip->i_d.di_nextents == 0);
        ASSERT(ip->i_d.di_anextents == 0);
-       ASSERT((ip->i_d.di_size == 0) ||
+       ASSERT((ip->i_d.di_size == 0 && ip->i_size == 0) ||
               ((ip->i_d.di_mode & S_IFMT) != S_IFREG));
        ASSERT(ip->i_d.di_nblocks == 0);
 
 
        struct xfs_inode        *i_cnext;       /* cluster hash link forward */
        struct xfs_inode        *i_cprev;       /* cluster hash link backward */
 
+       xfs_fsize_t             i_size;         /* in-memory size */
        /* Trace buffers per inode. */
 #ifdef XFS_BMAP_TRACE
        struct ktrace           *i_xtrace;      /* inode extent list trace */
 #endif
 } xfs_inode_t;
 
+#define XFS_ISIZE(ip)  (((ip)->i_d.di_mode & S_IFMT) == S_IFREG) ? \
+                               (ip)->i_size : (ip)->i_d.di_size;
 
 /*
  * i_flags helper functions
 
 xfs_size_fn(
        xfs_inode_t             *ip)
 {
-       return (ip->i_d.di_size);
+       return XFS_ISIZE(ip);
 }
 
 STATIC int
 
                extsz = ip->i_d.di_extsize;
        }
 
-       isize = ip->i_d.di_size;
+       isize = ip->i_size;
        if (io->io_new_size > isize)
                isize = io->io_new_size;
 
        xfs_trans_ihold(tp, ip);
 
        bmapi_flag = XFS_BMAPI_WRITE;
-       if ((flags & BMAPI_DIRECT) && (offset < ip->i_d.di_size || extsz))
+       if ((flags & BMAPI_DIRECT) && (offset < ip->i_size || extsz))
                bmapi_flag |= XFS_BMAPI_PREALLOC;
 
        /*
        offset_fsb = XFS_B_TO_FSBT(mp, offset);
 
 retry:
-       isize = ip->i_d.di_size;
+       isize = ip->i_size;
        if (io->io_new_size > isize)
                isize = io->io_new_size;
 
                         * we dropped the ilock in the interim.
                         */
 
-                       end_fsb = XFS_B_TO_FSB(mp, ip->i_d.di_size);
+                       end_fsb = XFS_B_TO_FSB(mp, ip->i_size);
                        xfs_bmap_last_offset(NULL, ip, &last_block,
                                XFS_DATA_FORK);
                        last_block = XFS_FILEOFF_MAX(last_block, end_fsb);
 
 
 
 typedef enum {                         /* iomap_flags values */
+       IOMAP_READ =            0,      /* mapping for a read */
        IOMAP_EOF =             0x01,   /* mapping contains EOF   */
        IOMAP_HOLE =            0x02,   /* mapping covers a hole  */
        IOMAP_DELAY =           0x04,   /* mapping covers delalloc region  */
 
        if (!(flags & ATTR_LAZY))
                xfs_ilock(ip, XFS_ILOCK_SHARED);
 
-       vap->va_size = ip->i_d.di_size;
+       vap->va_size = XFS_ISIZE(ip);
        if (vap->va_mask == XFS_AT_SIZE)
                goto all_done;
 
        if (mask & XFS_AT_SIZE) {
                /* Short circuit the truncate case for zero length files */
                if ((vap->va_size == 0) &&
-                  (ip->i_d.di_size == 0) && (ip->i_d.di_nextents == 0)) {
+                  (ip->i_size == 0) && (ip->i_d.di_nextents == 0)) {
                        xfs_iunlock(ip, XFS_ILOCK_EXCL);
                        lock_flags &= ~XFS_ILOCK_EXCL;
                        if (mask & XFS_AT_CTIME)
         */
        if (mask & XFS_AT_SIZE) {
                code = 0;
-               if ((vap->va_size > ip->i_d.di_size) && 
+               if ((vap->va_size > ip->i_size) &&
                    (flags & ATTR_NOSIZETOK) == 0) {
                        code = xfs_igrow_start(ip, vap->va_size, credp);
                }
         * Truncate file.  Must have write permission and not be a directory.
         */
        if (mask & XFS_AT_SIZE) {
-               if (vap->va_size > ip->i_d.di_size) {
+               if (vap->va_size > ip->i_size) {
                        xfs_igrow_finish(tp, ip, vap->va_size,
                            !(flags & ATTR_DMI));
-               } else if ((vap->va_size <= ip->i_d.di_size) ||
+               } else if ((vap->va_size <= ip->i_size) ||
                           ((vap->va_size == 0) && ip->i_d.di_nextents)) {
                        /*
                         * signal a sync transaction unless
         * Figure out if there are any blocks beyond the end
         * of the file.  If not, then there is nothing to do.
         */
-       end_fsb = XFS_B_TO_FSB(mp, ((xfs_ufsize_t)ip->i_d.di_size));
+       end_fsb = XFS_B_TO_FSB(mp, ((xfs_ufsize_t)ip->i_size));
        last_fsb = XFS_B_TO_FSB(mp, (xfs_ufsize_t)XFS_MAXIOFFSET(mp));
        map_len = last_fsb - end_fsb;
        if (map_len <= 0)
                 */
                xfs_ilock(ip, XFS_IOLOCK_EXCL);
                error = xfs_itruncate_start(ip, XFS_ITRUNC_DEFINITE,
-                                   ip->i_d.di_size);
+                                   ip->i_size);
                if (error) {
                        xfs_iunlock(ip, XFS_IOLOCK_EXCL);
                        return error;
                xfs_trans_ihold(tp, ip);
 
                error = xfs_itruncate_finish(&tp, ip,
-                                            ip->i_d.di_size,
+                                            ip->i_size,
                                             XFS_DATA_FORK,
                                             0);
                /*
 
        if (ip->i_d.di_nlink != 0) {
                if ((((ip->i_d.di_mode & S_IFMT) == S_IFREG) &&
-                    ((ip->i_d.di_size > 0) || (VN_CACHED(vp) > 0 ||
+                    ((ip->i_size > 0) || (VN_CACHED(vp) > 0 ||
                       ip->i_delayed_blks > 0)) &&
                     (ip->i_df.if_flags & XFS_IFEXTENTS))  &&
                    (!(ip->i_d.di_flags &
         * only one with a reference to the inode.
         */
        truncate = ((ip->i_d.di_nlink == 0) &&
-            ((ip->i_d.di_size != 0) || (ip->i_d.di_nextents > 0) ||
-             (ip->i_delayed_blks > 0)) &&
+           ((ip->i_d.di_size != 0) || (ip->i_size != 0) ||
+            (ip->i_d.di_nextents > 0) || (ip->i_delayed_blks > 0)) &&
            ((ip->i_d.di_mode & S_IFMT) == S_IFREG));
 
        mp = ip->i_mount;
 
        if (ip->i_d.di_nlink != 0) {
                if ((((ip->i_d.di_mode & S_IFMT) == S_IFREG) &&
-                     ((ip->i_d.di_size > 0) || (VN_CACHED(vp) > 0 ||
+                     ((ip->i_size > 0) || (VN_CACHED(vp) > 0 ||
                        ip->i_delayed_blks > 0)) &&
                      (ip->i_df.if_flags & XFS_IFEXTENTS) &&
                     (!(ip->i_d.di_flags &
        allocatesize_fsb = XFS_B_TO_FSB(mp, count);
 
        /*      Generate a DMAPI event if needed.       */
-       if (alloc_type != 0 && offset < ip->i_d.di_size &&
+       if (alloc_type != 0 && offset < ip->i_size &&
                        (attr_flags&ATTR_DMI) == 0  &&
                        DM_EVENT_ENABLED(XFS_MTOVFS(mp), ip, DM_EVENT_WRITE)) {
                xfs_off_t           end_dmi_offset;
 
                end_dmi_offset = offset+len;
-               if (end_dmi_offset > ip->i_d.di_size)
-                       end_dmi_offset = ip->i_d.di_size;
+               if (end_dmi_offset > ip->i_size)
+                       end_dmi_offset = ip->i_size;
                error = XFS_SEND_DATA(mp, DM_EVENT_WRITE, XFS_ITOV(ip),
                        offset, end_dmi_offset - offset,
                        0, NULL);
        end_dmi_offset = offset + len;
        endoffset_fsb = XFS_B_TO_FSBT(mp, end_dmi_offset);
 
-       if (offset < ip->i_d.di_size &&
+       if (offset < ip->i_size &&
            (attr_flags & ATTR_DMI) == 0 &&
            DM_EVENT_ENABLED(XFS_MTOVFS(mp), ip, DM_EVENT_WRITE)) {
-               if (end_dmi_offset > ip->i_d.di_size)
-                       end_dmi_offset = ip->i_d.di_size;
+               if (end_dmi_offset > ip->i_size)
+                       end_dmi_offset = ip->i_size;
                error = XFS_SEND_DATA(mp, DM_EVENT_WRITE, vp,
                                offset, end_dmi_offset - offset,
                                AT_DELAY_FLAG(attr_flags), NULL);
                bf->l_start += offset;
                break;
        case 2: /*SEEK_END*/
-               bf->l_start += ip->i_d.di_size;
+               bf->l_start += ip->i_size;
                break;
        default:
                return XFS_ERROR(EINVAL);
        bf->l_whence = 0;
 
        startoffset = bf->l_start;
-       fsize = ip->i_d.di_size;
+       fsize = ip->i_size;
 
        /*
         * XFS_IOC_RESVSP and XFS_IOC_UNRESVSP will reserve or unreserve