[XFS] Remove unused ilen variable and references.
[safe/jmp/linux-2.6] / fs / xfs / xfs_vnodeops.c
index 8221b11..e2c9bbc 100644 (file)
 /*
- * Copyright (c) 2000-2005 Silicon Graphics, Inc.  All Rights Reserved.
+ * Copyright (c) 2000-2006 Silicon Graphics, Inc.
+ * All Rights Reserved.
  *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of version 2 of the GNU General Public License as
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
  * published by the Free Software Foundation.
  *
- * This program is distributed in the hope that it would be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * This program is distributed in the hope that it would be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
  *
- * Further, this software is distributed without any warranty that it is
- * free of the rightful claim of any third person regarding infringement
- * or the like.  Any license provided herein, whether implied or
- * otherwise, applies only to this software file.  Patent licenses, if
- * any, provided herein do not apply to combinations of this program with
- * other software, or any other product whatsoever.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write the Free Software Foundation, Inc., 59
- * Temple Place - Suite 330, Boston MA 02111-1307, USA.
- *
- * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
- * Mountain View, CA  94043, or:
- *
- * http://www.sgi.com
- *
- * For further information regarding this notice, see:
- *
- * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write the Free Software Foundation,
+ * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  */
 
 #include "xfs.h"
-#include "xfs_macros.h"
+#include "xfs_fs.h"
 #include "xfs_types.h"
-#include "xfs_inum.h"
+#include "xfs_bit.h"
 #include "xfs_log.h"
+#include "xfs_inum.h"
 #include "xfs_trans.h"
 #include "xfs_sb.h"
 #include "xfs_ag.h"
-#include "xfs_dir.h"
 #include "xfs_dir2.h"
 #include "xfs_dmapi.h"
 #include "xfs_mount.h"
-#include "xfs_alloc_btree.h"
+#include "xfs_da_btree.h"
 #include "xfs_bmap_btree.h"
+#include "xfs_alloc_btree.h"
 #include "xfs_ialloc_btree.h"
+#include "xfs_dir2_sf.h"
+#include "xfs_attr_sf.h"
+#include "xfs_dinode.h"
+#include "xfs_inode.h"
+#include "xfs_inode_item.h"
 #include "xfs_itable.h"
 #include "xfs_btree.h"
 #include "xfs_ialloc.h"
 #include "xfs_alloc.h"
-#include "xfs_attr_sf.h"
-#include "xfs_dir_sf.h"
-#include "xfs_dir2_sf.h"
-#include "xfs_dinode.h"
-#include "xfs_inode_item.h"
-#include "xfs_inode.h"
 #include "xfs_bmap.h"
-#include "xfs_da_btree.h"
 #include "xfs_attr.h"
 #include "xfs_rw.h"
-#include "xfs_refcache.h"
 #include "xfs_error.h"
-#include "xfs_bit.h"
-#include "xfs_rtalloc.h"
 #include "xfs_quota.h"
 #include "xfs_utils.h"
+#include "xfs_rtalloc.h"
+#include "xfs_refcache.h"
 #include "xfs_trans_space.h"
-#include "xfs_dir_leaf.h"
-#include "xfs_mac.h"
 #include "xfs_log_priv.h"
 
-
-/*
- * The maximum pathlen is 1024 bytes. Since the minimum file system
- * blocksize is 512 bytes, we can get a max of 2 extents back from
- * bmapi.
- */
-#define SYMLINK_MAPS 2
-
-/*
- * For xfs, we check that the file isn't too big to be opened by this kernel.
- * No other open action is required for regular files.  Devices are handled
- * through the specfs file system, pipes through fifofs.  Device and
- * fifo vnodes are "wrapped" by specfs and fifofs vnodes, respectively,
- * when a new vnode is first looked up or created.
- */
 STATIC int
 xfs_open(
        bhv_desc_t      *bdp,
        cred_t          *credp)
 {
        int             mode;
-       vnode_t         *vp;
-       xfs_inode_t     *ip;
-
-       vp = BHV_TO_VNODE(bdp);
-       ip = XFS_BHVTOI(bdp);
+       bhv_vnode_t     *vp = BHV_TO_VNODE(bdp);
+       xfs_inode_t     *ip = XFS_BHVTOI(bdp);
 
        if (XFS_FORCED_SHUTDOWN(ip->i_mount))
                return XFS_ERROR(EIO);
@@ -113,6 +77,35 @@ xfs_open(
        return 0;
 }
 
+STATIC int
+xfs_close(
+       bhv_desc_t      *bdp,
+       int             flags,
+       lastclose_t     lastclose,
+       cred_t          *credp)
+{
+       bhv_vnode_t     *vp = BHV_TO_VNODE(bdp);
+       xfs_inode_t     *ip = XFS_BHVTOI(bdp);
+
+       if (XFS_FORCED_SHUTDOWN(ip->i_mount))
+               return XFS_ERROR(EIO);
+
+       if (lastclose != L_TRUE || !VN_ISREG(vp))
+               return 0;
+
+       /*
+        * If we previously truncated this file and removed old data in
+        * the process, we want to initiate "early" writeout on the last
+        * close.  This is an attempt to combat the notorious NULL files
+        * problem which is particularly noticable from a truncate down,
+        * buffered (re-)write (delalloc), followed by a crash.  What we
+        * are effectively doing here is significantly reducing the time
+        * window where we'd otherwise be exposed to that problem.
+        */
+       if (VUNTRUNCATE(vp) && VN_DIRTY(vp) && ip->i_delayed_blks > 0)
+               return bhv_vop_flush_pages(vp, 0, -1, XFS_B_ASYNC, FI_NONE);
+       return 0;
+}
 
 /*
  * xfs_getattr
@@ -120,13 +113,13 @@ xfs_open(
 STATIC int
 xfs_getattr(
        bhv_desc_t      *bdp,
-       vattr_t         *vap,
+       bhv_vattr_t     *vap,
        int             flags,
        cred_t          *credp)
 {
        xfs_inode_t     *ip;
        xfs_mount_t     *mp;
-       vnode_t         *vp;
+       bhv_vnode_t     *vp;
 
        vp  = BHV_TO_VNODE(bdp);
        vn_trace_entry(vp, __FUNCTION__, (inst_t *)__return_address);
@@ -140,7 +133,7 @@ xfs_getattr(
        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;
 
@@ -197,8 +190,7 @@ xfs_getattr(
                break;
        }
 
-       vap->va_atime.tv_sec = ip->i_d.di_atime.t_sec;
-       vap->va_atime.tv_nsec = ip->i_d.di_atime.t_nsec;
+       vn_atime_to_timespec(vp, &vap->va_atime);
        vap->va_mtime.tv_sec = ip->i_d.di_mtime.t_sec;
        vap->va_mtime.tv_nsec = ip->i_d.di_mtime.t_nsec;
        vap->va_ctime.tv_sec = ip->i_d.di_ctime.t_sec;
@@ -254,7 +246,7 @@ xfs_getattr(
 int
 xfs_setattr(
        bhv_desc_t              *bdp,
-       vattr_t                 *vap,
+       bhv_vattr_t             *vap,
        int                     flags,
        cred_t                  *credp)
 {
@@ -268,7 +260,7 @@ xfs_setattr(
        uid_t                   uid=0, iuid=0;
        gid_t                   gid=0, igid=0;
        int                     timeflags = 0;
-       vnode_t                 *vp;
+       bhv_vnode_t             *vp;
        xfs_prid_t              projid=0, iprojid=0;
        int                     mandlock_before, mandlock_after;
        struct xfs_dquot        *udqp, *gdqp, *olddquot1, *olddquot2;
@@ -351,7 +343,7 @@ xfs_setattr(
                code = XFS_QM_DQVOPALLOC(mp, ip, uid, gid, projid, qflags,
                                         &udqp, &gdqp);
                if (code)
-                       return (code);
+                       return code;
        }
 
        /*
@@ -360,7 +352,6 @@ xfs_setattr(
         */
        tp = NULL;
        lock_flags = XFS_ILOCK_EXCL;
-       ASSERT(flags & ATTR_NOLOCK ? flags & ATTR_DMI : 1);
        if (flags & ATTR_NOLOCK)
                need_iolock = 0;
        if (!(mask & XFS_AT_SIZE)) {
@@ -505,7 +496,7 @@ xfs_setattr(
        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)
@@ -548,8 +539,7 @@ xfs_setattr(
                /*
                 * Can't change extent size if any extents are allocated.
                 */
-               if ((ip->i_d.di_nextents || ip->i_delayed_blks) &&
-                   (mask & XFS_AT_EXTSIZE) &&
+               if (ip->i_d.di_nextents && (mask & XFS_AT_EXTSIZE) &&
                    ((ip->i_d.di_extsize << mp->m_sb.sb_blocklog) !=
                     vap->va_extsize) ) {
                        code = XFS_ERROR(EINVAL);       /* EFBIG? */
@@ -557,27 +547,10 @@ xfs_setattr(
                }
 
                /*
-                * Can't set extent size unless the file is marked, or
-                * about to be marked as a realtime file.
-                *
-                * This check will be removed when fixed size extents
-                * with buffered data writes is implemented.
-                *
-                */
-               if ((mask & XFS_AT_EXTSIZE)                     &&
-                   ((ip->i_d.di_extsize << mp->m_sb.sb_blocklog) !=
-                    vap->va_extsize) &&
-                   (!((ip->i_d.di_flags & XFS_DIFLAG_REALTIME) ||
-                      ((mask & XFS_AT_XFLAGS) &&
-                       (vap->va_xflags & XFS_XFLAG_REALTIME))))) {
-                       code = XFS_ERROR(EINVAL);
-                       goto error_return;
-               }
-
-               /*
                 * Can't change realtime flag if any extents are allocated.
                 */
-               if (ip->i_d.di_nextents && (mask & XFS_AT_XFLAGS) &&
+               if ((ip->i_d.di_nextents || ip->i_delayed_blks) &&
+                   (mask & XFS_AT_XFLAGS) &&
                    (ip->i_d.di_flags & XFS_DIFLAG_REALTIME) !=
                    (vap->va_xflags & XFS_XFLAG_REALTIME)) {
                        code = XFS_ERROR(EINVAL);       /* EFBIG? */
@@ -641,9 +614,12 @@ xfs_setattr(
         */
        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);
+               }
                xfs_iunlock(ip, XFS_ILOCK_EXCL);
+               vn_iowait(vp); /* wait for the completion of any pending DIOs */
                if (!code)
                        code = xfs_itruncate_data(ip, vap->va_size);
                if (code) {
@@ -678,10 +654,10 @@ xfs_setattr(
         * 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
@@ -694,9 +670,17 @@ xfs_setattr(
                                            ((ip->i_d.di_nlink != 0 ||
                                              !(mp->m_flags & XFS_MOUNT_WSYNC))
                                             ? 1 : 0));
-                       if (code) {
+                       if (code)
                                goto abort_return;
-                       }
+                       /*
+                        * Truncated "down", so we're removing references
+                        * to old data here - if we now delay flushing for
+                        * a long time, we expose ourselves unduly to the
+                        * notorious NULL files problem.  So, we mark this
+                        * vnode and flush it when the file is closed, and
+                        * do not wait the usual (long) time for writeout.
+                        */
+                       VTRUNCATE(vp);
                }
                /*
                 * Have to do this even if the file's size doesn't change.
@@ -828,18 +812,24 @@ xfs_setattr(
                                di_flags |= XFS_DIFLAG_NODUMP;
                        if (vap->va_xflags & XFS_XFLAG_PROJINHERIT)
                                di_flags |= XFS_DIFLAG_PROJINHERIT;
+                       if (vap->va_xflags & XFS_XFLAG_NODEFRAG)
+                               di_flags |= XFS_DIFLAG_NODEFRAG;
                        if ((ip->i_d.di_mode & S_IFMT) == S_IFDIR) {
                                if (vap->va_xflags & XFS_XFLAG_RTINHERIT)
                                        di_flags |= XFS_DIFLAG_RTINHERIT;
                                if (vap->va_xflags & XFS_XFLAG_NOSYMLINKS)
                                        di_flags |= XFS_DIFLAG_NOSYMLINKS;
-                       } else {
+                               if (vap->va_xflags & XFS_XFLAG_EXTSZINHERIT)
+                                       di_flags |= XFS_DIFLAG_EXTSZINHERIT;
+                       } else if ((ip->i_d.di_mode & S_IFMT) == S_IFREG) {
                                if (vap->va_xflags & XFS_XFLAG_REALTIME) {
                                        di_flags |= XFS_DIFLAG_REALTIME;
                                        ip->i_iocore.io_flags |= XFS_IOCORE_RT;
                                } else {
                                        ip->i_iocore.io_flags &= ~XFS_IOCORE_RT;
                                }
+                               if (vap->va_xflags & XFS_XFLAG_EXTSIZE)
+                                       di_flags |= XFS_DIFLAG_EXTSIZE;
                        }
                        ip->i_d.di_flags = di_flags;
                }
@@ -872,7 +862,7 @@ xfs_setattr(
         * If this is a synchronous mount, make sure that the
         * transaction goes to disk before returning to the user.
         * This is slightly sub-optimal in that truncates require
-        * two sync transactions instead of one for wsync filesytems.
+        * two sync transactions instead of one for wsync filesystems.
         * One for the truncate and one for the timestamps since we
         * don't want to change the timestamps unless we're sure the
         * truncate worked.  Truncates are less than 1% of the laddis
@@ -883,7 +873,7 @@ xfs_setattr(
                if (mp->m_flags & XFS_MOUNT_WSYNC)
                        xfs_trans_set_sync(tp);
 
-               code = xfs_trans_commit(tp, commit_flags, NULL);
+               code = xfs_trans_commit(tp, commit_flags);
        }
 
        /*
@@ -893,7 +883,7 @@ xfs_setattr(
         */
        mandlock_after = MANDLOCK(vp, ip->i_d.di_mode);
        if (mandlock_before != mandlock_after) {
-               VOP_VNODE_CHANGE(vp, VCHANGE_FLAGS_ENF_LOCKING,
+               bhv_vop_vnode_change(vp, VCHANGE_FLAGS_ENF_LOCKING,
                                 mandlock_after);
        }
 
@@ -960,6 +950,13 @@ xfs_access(
 
 
 /*
+ * The maximum pathlen is 1024 bytes. Since the minimum file system
+ * blocksize is 512 bytes, we can get a max of 2 extents back from
+ * bmapi.
+ */
+#define SYMLINK_MAPS 2
+
+/*
  * xfs_readlink
  *
  */
@@ -974,7 +971,7 @@ xfs_readlink(
        int             count;
        xfs_off_t       offset;
        int             pathlen;
-       vnode_t         *vp;
+       bhv_vnode_t     *vp;
        int             error = 0;
        xfs_mount_t     *mp;
        int             nmaps;
@@ -1009,17 +1006,13 @@ xfs_readlink(
                goto error_return;
        }
 
-       if (!(ioflags & IO_INVIS)) {
-               xfs_ichgtime(ip, XFS_ICHGTIME_ACC);
-       }
-
        /*
         * See if the symlink is stored inline.
         */
        pathlen = (int)ip->i_d.di_size;
 
        if (ip->i_df.if_flags & XFS_IFINLINE) {
-               error = uio_read(ip->i_df.if_u1.if_data, pathlen, uiop);
+               error = xfs_uio_read(ip->i_df.if_u1.if_data, pathlen, uiop);
        }
        else {
                /*
@@ -1028,7 +1021,7 @@ xfs_readlink(
                nmaps = SYMLINK_MAPS;
 
                error = xfs_bmapi(NULL, ip, 0, XFS_B_TO_FSB(mp, pathlen),
-                                 0, NULL, 0, mval, &nmaps, NULL);
+                                 0, NULL, 0, mval, &nmaps, NULL, NULL);
 
                if (error) {
                        goto error_return;
@@ -1050,17 +1043,14 @@ xfs_readlink(
                                byte_cnt = pathlen;
                        pathlen -= byte_cnt;
 
-                       error = uio_read(XFS_BUF_PTR(bp), byte_cnt, uiop);
+                       error = xfs_uio_read(XFS_BUF_PTR(bp), byte_cnt, uiop);
                        xfs_buf_relse (bp);
                }
 
        }
 
-
 error_return:
-
        xfs_iunlock(ip, XFS_ILOCK_SHARED);
-
        return error;
 }
 
@@ -1186,7 +1176,7 @@ xfs_fsync(
                xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
                if (flag & FSYNC_WAIT)
                        xfs_trans_set_sync(tp);
-               error = _xfs_trans_commit(tp, 0, NULL, &log_flushed);
+               error = _xfs_trans_commit(tp, 0, &log_flushed);
 
                xfs_iunlock(ip, XFS_ILOCK_EXCL);
        }
@@ -1201,7 +1191,7 @@ xfs_fsync(
 
                /*
                 * If this inode is on the RT dev we need to flush that
-                * cache aswell.
+                * cache as well.
                 */
                if (ip->i_d.di_flags & XFS_DIFLAG_REALTIME)
                        xfs_blkdev_issue_flush(ip->i_mount->m_rtdev_targp);
@@ -1231,25 +1221,26 @@ xfs_inactive_free_eofblocks(
         * 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)
-               return (0);
+               return 0;
 
        nimaps = 1;
        xfs_ilock(ip, XFS_ILOCK_SHARED);
-       error = xfs_bmapi(NULL, ip, end_fsb, map_len, 0,
-                         NULL, 0, &imap, &nimaps, NULL);
+       error = XFS_BMAPI(mp, NULL, &ip->i_iocore, end_fsb, map_len, 0,
+                         NULL, 0, &imap, &nimaps, NULL, NULL);
        xfs_iunlock(ip, XFS_ILOCK_SHARED);
 
        if (!error && (nimaps != 0) &&
-           (imap.br_startblock != HOLESTARTBLOCK)) {
+           (imap.br_startblock != HOLESTARTBLOCK ||
+            ip->i_delayed_blks)) {
                /*
                 * Attach the dquots to the inode up front.
                 */
                if ((error = XFS_QM_DQATTACH(mp, ip, 0)))
-                       return (error);
+                       return error;
 
                /*
                 * There are blocks after the end of file.
@@ -1266,8 +1257,12 @@ xfs_inactive_free_eofblocks(
                 * do that within a transaction.
                 */
                xfs_ilock(ip, XFS_IOLOCK_EXCL);
-               xfs_itruncate_start(ip, XFS_ITRUNC_DEFINITE,
-                                   ip->i_d.di_size);
+               error = xfs_itruncate_start(ip, XFS_ITRUNC_DEFINITE,
+                                   ip->i_size);
+               if (error) {
+                       xfs_iunlock(ip, XFS_IOLOCK_EXCL);
+                       return error;
+               }
 
                error = xfs_trans_reserve(tp, 0,
                                          XFS_ITRUNCATE_LOG_RES(mp),
@@ -1277,7 +1272,7 @@ xfs_inactive_free_eofblocks(
                        ASSERT(XFS_FORCED_SHUTDOWN(mp));
                        xfs_trans_cancel(tp, 0);
                        xfs_iunlock(ip, XFS_IOLOCK_EXCL);
-                       return (error);
+                       return error;
                }
 
                xfs_ilock(ip, XFS_ILOCK_EXCL);
@@ -1287,7 +1282,7 @@ xfs_inactive_free_eofblocks(
                xfs_trans_ihold(tp, ip);
 
                error = xfs_itruncate_finish(&tp, ip,
-                                            ip->i_d.di_size,
+                                            ip->i_size,
                                             XFS_DATA_FORK,
                                             0);
                /*
@@ -1300,12 +1295,11 @@ xfs_inactive_free_eofblocks(
                                          XFS_TRANS_ABORT));
                } else {
                        error = xfs_trans_commit(tp,
-                                               XFS_TRANS_RELEASE_LOG_RES,
-                                               NULL);
+                                               XFS_TRANS_RELEASE_LOG_RES);
                }
                xfs_iunlock(ip, XFS_IOLOCK_EXCL | XFS_ILOCK_EXCL);
        }
-       return (error);
+       return error;
 }
 
 /*
@@ -1365,10 +1359,10 @@ xfs_inactive_symlink_rmt(
         */
        done = 0;
        XFS_BMAP_INIT(&free_list, &first_block);
-       nmaps = sizeof(mval) / sizeof(mval[0]);
+       nmaps = ARRAY_SIZE(mval);
        if ((error = xfs_bmapi(tp, ip, 0, XFS_B_TO_FSB(mp, size),
                        XFS_BMAPI_METADATA, &first_block, 0, mval, &nmaps,
-                       &free_list)))
+                       &free_list, NULL)))
                goto error0;
        /*
         * Invalidate the block(s).
@@ -1383,13 +1377,13 @@ xfs_inactive_symlink_rmt(
         * Unmap the dead block(s) to the free_list.
         */
        if ((error = xfs_bunmapi(tp, ip, 0, size, XFS_BMAPI_METADATA, nmaps,
-                       &first_block, &free_list, &done)))
+                       &first_block, &free_list, NULL, &done)))
                goto error1;
        ASSERT(done);
        /*
         * Commit the first transaction.  This logs the EFI and the inode.
         */
-       if ((error = xfs_bmap_finish(&tp, &free_list, first_block, &committed)))
+       if ((error = xfs_bmap_finish(&tp, &free_list, &committed)))
                goto error1;
        /*
         * The transaction must have been committed, since there were
@@ -1410,12 +1404,12 @@ xfs_inactive_symlink_rmt(
         */
        ntp = xfs_trans_dup(tp);
        /*
-        * Commit the transaction containing extent freeing and EFD's.
+        * Commit the transaction containing extent freeing and EFDs.
         * If we get an error on the commit here or on the reserve below,
         * we need to unlock the inode since the new transaction doesn't
         * have the inode attached.
         */
-       error = xfs_trans_commit(tp, 0, NULL);
+       error = xfs_trans_commit(tp, 0);
        tp = ntp;
        if (error) {
                ASSERT(XFS_FORCED_SHUTDOWN(mp));
@@ -1483,7 +1477,7 @@ xfs_inactive_symlink_local(
        if (error) {
                xfs_trans_cancel(*tpp, 0);
                *tpp = NULL;
-               return (error);
+               return error;
        }
        xfs_ilock(ip, XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL);
 
@@ -1496,12 +1490,9 @@ xfs_inactive_symlink_local(
                                  XFS_DATA_FORK);
                ASSERT(ip->i_df.if_bytes == 0);
        }
-       return (0);
+       return 0;
 }
 
-/*
- *
- */
 STATIC int
 xfs_inactive_attrs(
        xfs_inode_t     *ip,
@@ -1515,14 +1506,14 @@ xfs_inactive_attrs(
        tp = *tpp;
        mp = ip->i_mount;
        ASSERT(ip->i_d.di_forkoff != 0);
-       xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES, NULL);
+       xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES);
        xfs_iunlock(ip, XFS_ILOCK_EXCL);
 
        error = xfs_attr_inactive(ip);
        if (error) {
                *tpp = NULL;
                xfs_iunlock(ip, XFS_IOLOCK_EXCL);
-               return (error); /* goto out*/
+               return error; /* goto out */
        }
 
        tp = xfs_trans_alloc(mp, XFS_TRANS_INACTIVE);
@@ -1535,7 +1526,7 @@ xfs_inactive_attrs(
                xfs_trans_cancel(tp, 0);
                *tpp = NULL;
                xfs_iunlock(ip, XFS_IOLOCK_EXCL);
-               return (error);
+               return error;
        }
 
        xfs_ilock(ip, XFS_ILOCK_EXCL);
@@ -1546,7 +1537,7 @@ xfs_inactive_attrs(
        ASSERT(ip->i_d.di_anextents == 0);
 
        *tpp = tp;
-       return (0);
+       return 0;
 }
 
 STATIC int
@@ -1554,16 +1545,16 @@ xfs_release(
        bhv_desc_t      *bdp)
 {
        xfs_inode_t     *ip;
-       vnode_t         *vp;
+       bhv_vnode_t     *vp;
        xfs_mount_t     *mp;
        int             error;
 
        vp = BHV_TO_VNODE(bdp);
        ip = XFS_BHVTOI(bdp);
+       mp = ip->i_mount;
 
-       if (!VN_ISREG(vp) || (ip->i_d.di_mode == 0)) {
+       if (!VN_ISREG(vp) || (ip->i_d.di_mode == 0))
                return 0;
-       }
 
        /* If this is a read-only mount, don't do this (would generate I/O) */
        if (vp->v_vfsp->vfs_flag & VFS_RDONLY)
@@ -1575,17 +1566,17 @@ xfs_release(
                return 0;
 #endif
 
-       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 & (XFS_DIFLAG_PREALLOC|XFS_DIFLAG_APPEND)))) {
+                   (!(ip->i_d.di_flags &
+                               (XFS_DIFLAG_PREALLOC | XFS_DIFLAG_APPEND)))) {
                        if ((error = xfs_inactive_free_eofblocks(mp, ip)))
-                               return (error);
+                               return error;
                        /* Update linux inode block count after free above */
-                       LINVFS_GET_IP(vp)->i_blocks = XFS_FSB_TO_BB(mp,
+                       vn_to_inode(vp)->i_blocks = XFS_FSB_TO_BB(mp,
                                ip->i_d.di_nblocks + ip->i_delayed_blks);
                }
        }
@@ -1607,8 +1598,8 @@ xfs_inactive(
        cred_t          *credp)
 {
        xfs_inode_t     *ip;
-       vnode_t         *vp;
-       xfs_bmap_free_t free_list; 
+       bhv_vnode_t     *vp;
+       xfs_bmap_free_t free_list;
        xfs_fsblock_t   first_block;
        int             committed;
        xfs_trans_t     *tp;
@@ -1638,7 +1629,8 @@ xfs_inactive(
         * 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_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;
@@ -1656,14 +1648,16 @@ xfs_inactive(
 
        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_df.if_flags & XFS_IFEXTENTS))  &&
-                   (!(ip->i_d.di_flags & (XFS_DIFLAG_PREALLOC|XFS_DIFLAG_APPEND)) ||
-                    (ip->i_delayed_blks != 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 &
+                               (XFS_DIFLAG_PREALLOC | XFS_DIFLAG_APPEND)) ||
+                     (ip->i_delayed_blks != 0)))) {
                        if ((error = xfs_inactive_free_eofblocks(mp, ip)))
-                               return (VN_INACTIVE_CACHE);
+                               return VN_INACTIVE_CACHE;
                        /* Update linux inode block count after free above */
-                       LINVFS_GET_IP(vp)->i_blocks = XFS_FSB_TO_BB(mp,
+                       vn_to_inode(vp)->i_blocks = XFS_FSB_TO_BB(mp,
                                ip->i_d.di_nblocks + ip->i_delayed_blks);
                }
                goto out;
@@ -1672,7 +1666,7 @@ xfs_inactive(
        ASSERT(ip->i_d.di_nlink == 0);
 
        if ((error = XFS_QM_DQATTACH(mp, ip, 0)))
-               return (VN_INACTIVE_CACHE);
+               return VN_INACTIVE_CACHE;
 
        tp = xfs_trans_alloc(mp, XFS_TRANS_INACTIVE);
        if (truncate) {
@@ -1684,7 +1678,11 @@ xfs_inactive(
                 */
                xfs_ilock(ip, XFS_IOLOCK_EXCL);
 
-               xfs_itruncate_start(ip, XFS_ITRUNC_DEFINITE, 0);
+               error = xfs_itruncate_start(ip, XFS_ITRUNC_DEFINITE, 0);
+               if (error) {
+                       xfs_iunlock(ip, XFS_IOLOCK_EXCL);
+                       return VN_INACTIVE_CACHE;
+               }
 
                error = xfs_trans_reserve(tp, 0,
                                          XFS_ITRUNCATE_LOG_RES(mp),
@@ -1695,7 +1693,7 @@ xfs_inactive(
                        ASSERT(XFS_FORCED_SHUTDOWN(mp));
                        xfs_trans_cancel(tp, 0);
                        xfs_iunlock(ip, XFS_IOLOCK_EXCL);
-                       return (VN_INACTIVE_CACHE);
+                       return VN_INACTIVE_CACHE;
                }
 
                xfs_ilock(ip, XFS_ILOCK_EXCL);
@@ -1716,7 +1714,7 @@ xfs_inactive(
                        xfs_trans_cancel(tp,
                                XFS_TRANS_RELEASE_LOG_RES | XFS_TRANS_ABORT);
                        xfs_iunlock(ip, XFS_IOLOCK_EXCL | XFS_ILOCK_EXCL);
-                       return (VN_INACTIVE_CACHE);
+                       return VN_INACTIVE_CACHE;
                }
        } else if ((ip->i_d.di_mode & S_IFMT) == S_IFLNK) {
 
@@ -1730,7 +1728,7 @@ xfs_inactive(
 
                if (error) {
                        ASSERT(tp == NULL);
-                       return (VN_INACTIVE_CACHE);
+                       return VN_INACTIVE_CACHE;
                }
 
                xfs_trans_ijoin(tp, ip, XFS_IOLOCK_EXCL | XFS_ILOCK_EXCL);
@@ -1743,7 +1741,7 @@ xfs_inactive(
                if (error) {
                        ASSERT(XFS_FORCED_SHUTDOWN(mp));
                        xfs_trans_cancel(tp, 0);
-                       return (VN_INACTIVE_CACHE);
+                       return VN_INACTIVE_CACHE;
                }
 
                xfs_ilock(ip, XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL);
@@ -1765,7 +1763,7 @@ xfs_inactive(
                 * cancelled, and the inode is unlocked. Just get out.
                 */
                 if (error)
-                        return (VN_INACTIVE_CACHE);
+                        return VN_INACTIVE_CACHE;
        } else if (ip->i_afp) {
                xfs_idestroy_fork(ip, XFS_ATTR_FORK);
        }
@@ -1785,7 +1783,7 @@ xfs_inactive(
                        cmn_err(CE_NOTE,
                "xfs_inactive:  xfs_ifree() returned an error = %d on %s",
                                error, mp->m_fsname);
-                       xfs_force_shutdown(mp, XFS_METADATA_IO_ERROR);
+                       xfs_force_shutdown(mp, SHUTDOWN_META_IO_ERROR);
                }
                xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES|XFS_TRANS_ABORT);
        } else {
@@ -1798,9 +1796,8 @@ xfs_inactive(
                 * Just ignore errors at this point.  There is
                 * nothing we can do except to try to keep going.
                 */
-               (void) xfs_bmap_finish(&tp,  &free_list, first_block,
-                                      &committed);
-               (void) xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES, NULL);
+               (void) xfs_bmap_finish(&tp,  &free_list, &committed);
+               (void) xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES);
        }
        /*
         * Release the dquots held by inode, if any.
@@ -1820,17 +1817,17 @@ xfs_inactive(
 STATIC int
 xfs_lookup(
        bhv_desc_t              *dir_bdp,
-       vname_t                 *dentry,
-       vnode_t                 **vpp,
+       bhv_vname_t             *dentry,
+       bhv_vnode_t             **vpp,
        int                     flags,
-       vnode_t                 *rdir,
+       bhv_vnode_t             *rdir,
        cred_t                  *credp)
 {
        xfs_inode_t             *dp, *ip;
        xfs_ino_t               e_inum;
        int                     error;
        uint                    lock_mode;
-       vnode_t                 *dir_vp;
+       bhv_vnode_t             *dir_vp;
 
        dir_vp = BHV_TO_VNODE(dir_bdp);
        vn_trace_entry(dir_vp, __FUNCTION__, (inst_t *)__return_address);
@@ -1857,15 +1854,15 @@ xfs_lookup(
 STATIC int
 xfs_create(
        bhv_desc_t              *dir_bdp,
-       vname_t                 *dentry,
-       vattr_t                 *vap,
-       vnode_t                 **vpp,
+       bhv_vname_t             *dentry,
+       bhv_vattr_t             *vap,
+       bhv_vnode_t             **vpp,
        cred_t                  *credp)
 {
        char                    *name = VNAME(dentry);
-       vnode_t                 *dir_vp;
+       bhv_vnode_t             *dir_vp;
        xfs_inode_t             *dp, *ip;
-       vnode_t                 *vp=NULL;
+       bhv_vnode_t             *vp = NULL;
        xfs_trans_t             *tp;
        xfs_mount_t             *mp;
        xfs_dev_t               rdev;
@@ -1963,8 +1960,7 @@ xfs_create(
        if (error)
                goto error_return;
 
-       if (resblks == 0 &&
-           (error = XFS_DIR_CANENTER(mp, tp, dp, name, namelen)))
+       if (resblks == 0 && (error = xfs_dir_canenter(tp, dp, name, namelen)))
                goto error_return;
        rdev = (vap->va_mask & XFS_AT_RDEV) ? vap->va_rdev : 0;
        error = xfs_dir_ialloc(&tp, dp, vap->va_mode, 1,
@@ -1995,9 +1991,9 @@ xfs_create(
        xfs_trans_ijoin(tp, dp, XFS_ILOCK_EXCL);
        dp_joined_to_trans = B_TRUE;
 
-       error = XFS_DIR_CREATENAME(mp, tp, dp, name, namelen, ip->i_ino,
-               &first_block, &free_list,
-               resblks ? resblks - XFS_IALLOC_SPACE_RES(mp) : 0);
+       error = xfs_dir_createname(tp, dp, name, namelen, ip->i_ino,
+                                       &first_block, &free_list, resblks ?
+                                       resblks - XFS_IALLOC_SPACE_RES(mp) : 0);
        if (error) {
                ASSERT(error != ENOSPC);
                goto abort_return;
@@ -2031,13 +2027,13 @@ xfs_create(
        IHOLD(ip);
        vp = XFS_ITOV(ip);
 
-       error = xfs_bmap_finish(&tp, &free_list, first_block, &committed);
+       error = xfs_bmap_finish(&tp, &free_list, &committed);
        if (error) {
                xfs_bmap_cancel(&free_list);
                goto abort_rele;
        }
 
-       error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES, NULL);
+       error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES);
        if (error) {
                IRELE(ip);
                tp = NULL;
@@ -2048,10 +2044,10 @@ xfs_create(
        XFS_QM_DQRELE(mp, gdqp);
 
        /*
-        * Propogate the fact that the vnode changed after the
+        * Propagate the fact that the vnode changed after the
         * xfs_inode locks have been released.
         */
-       VOP_VNODE_CHANGE(vp, VCHANGE_FLAGS_TRUNCATED, 3);
+       bhv_vop_vnode_change(vp, VCHANGE_FLAGS_TRUNCATED, 3);
 
        *vpp = vp;
 
@@ -2072,8 +2068,8 @@ std_return:
  abort_return:
        cancel_flags |= XFS_TRANS_ABORT;
        /* FALLTHROUGH */
- error_return:
 
+ error_return:
        if (tp != NULL)
                xfs_trans_cancel(tp, cancel_flags);
 
@@ -2132,7 +2128,6 @@ int xfs_rm_attempts;
 STATIC int
 xfs_lock_dir_and_entry(
        xfs_inode_t     *dp,
-       vname_t         *dentry,
        xfs_inode_t     *ip)    /* inode of entry 'name' */
 {
        int             attempts;
@@ -2346,10 +2341,10 @@ int remove_which_error_return = 0;
 STATIC int
 xfs_remove(
        bhv_desc_t              *dir_bdp,
-       vname_t                 *dentry,
+       bhv_vname_t             *dentry,
        cred_t                  *credp)
 {
-       vnode_t                 *dir_vp;
+       bhv_vnode_t             *dir_vp;
        char                    *name = VNAME(dentry);
        xfs_inode_t             *dp, *ip;
        xfs_trans_t             *tp = NULL;
@@ -2375,10 +2370,15 @@ xfs_remove(
 
        namelen = VNAMELEN(dentry);
 
+       if (!xfs_get_dir_entry(dentry, &ip)) {
+               dm_di_mode = ip->i_d.di_mode;
+               IRELE(ip);
+       }
+
        if (DM_EVENT_ENABLED(dir_vp->v_vfsp, dp, DM_EVENT_REMOVE)) {
                error = XFS_SEND_NAMESP(mp, DM_EVENT_REMOVE, dir_vp,
                                        DM_RIGHT_NULL, NULL, DM_RIGHT_NULL,
-                                       name, NULL, 0, 0, 0);
+                                       name, NULL, dm_di_mode, 0, 0);
                if (error)
                        return error;
        }
@@ -2395,7 +2395,7 @@ xfs_remove(
         * for a log reservation. Since we'll have to wait for the
         * inactive code to complete before returning from xfs_iget,
         * we need to make sure that we don't have log space reserved
-        * when we call xfs_iget.  Instead we get an unlocked referece
+        * when we call xfs_iget.  Instead we get an unlocked reference
         * to the inode before getting our log reservation.
         */
        error = xfs_get_dir_entry(dentry, &ip);
@@ -2446,7 +2446,7 @@ xfs_remove(
                return error;
        }
 
-       error = xfs_lock_dir_and_entry(dp, dentry, ip);
+       error = xfs_lock_dir_and_entry(dp, ip);
        if (error) {
                REMOVE_DEBUG_TRACE(__LINE__);
                xfs_trans_cancel(tp, cancel_flags);
@@ -2473,8 +2473,8 @@ xfs_remove(
         * Entry must exist since we did a lookup in xfs_lock_dir_and_entry.
         */
        XFS_BMAP_INIT(&free_list, &first_block);
-       error = XFS_DIR_REMOVENAME(mp, tp, dp, name, namelen, ip->i_ino,
-               &first_block, &free_list, 0);
+       error = xfs_dir_removename(tp, dp, name, namelen, ip->i_ino,
+                                       &first_block, &free_list, 0);
        if (error) {
                ASSERT(error != ENOENT);
                REMOVE_DEBUG_TRACE(__LINE__);
@@ -2511,13 +2511,13 @@ xfs_remove(
                xfs_trans_set_sync(tp);
        }
 
-       error = xfs_bmap_finish(&tp, &free_list, first_block, &committed);
+       error = xfs_bmap_finish(&tp, &free_list, &committed);
        if (error) {
                REMOVE_DEBUG_TRACE(__LINE__);
                goto error_rele;
        }
 
-       error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES, NULL);
+       error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES);
        if (error) {
                IRELE(ip);
                goto std_return;
@@ -2536,7 +2536,7 @@ xfs_remove(
        /*
         * Let interposed file systems know about removed links.
         */
-       VOP_LINK_REMOVED(XFS_ITOV(ip), dir_vp, link_zero);
+       bhv_vop_link_removed(XFS_ITOV(ip), dir_vp, link_zero);
 
        IRELE(ip);
 
@@ -2589,8 +2589,8 @@ xfs_remove(
 STATIC int
 xfs_link(
        bhv_desc_t              *target_dir_bdp,
-       vnode_t                 *src_vp,
-       vname_t                 *dentry,
+       bhv_vnode_t             *src_vp,
+       bhv_vname_t             *dentry,
        cred_t                  *credp)
 {
        xfs_inode_t             *tdp, *sip;
@@ -2602,8 +2602,7 @@ xfs_link(
        xfs_fsblock_t           first_block;
        int                     cancel_flags;
        int                     committed;
-       vnode_t                 *target_dir_vp;
-       bhv_desc_t              *src_bdp;
+       bhv_vnode_t             *target_dir_vp;
        int                     resblks;
        char                    *target_name = VNAME(dentry);
        int                     target_namelen;
@@ -2613,11 +2612,9 @@ xfs_link(
        vn_trace_entry(src_vp, __FUNCTION__, (inst_t *)__return_address);
 
        target_namelen = VNAMELEN(dentry);
-       if (VN_ISDIR(src_vp))
-               return XFS_ERROR(EPERM);
+       ASSERT(!VN_ISDIR(src_vp));
 
-       src_bdp = vn_bhv_lookup_unlocked(VN_BHV_HEAD(src_vp), &xfs_vnodeops);
-       sip = XFS_BHVTOI(src_bdp);
+       sip = xfs_vtoi(src_vp);
        tdp = XFS_BHVTOI(target_dir_bdp);
        mp = tdp->i_mount;
        if (XFS_FORCED_SHUTDOWN(mp))
@@ -2690,18 +2687,17 @@ xfs_link(
         */
        if (unlikely((tdp->i_d.di_flags & XFS_DIFLAG_PROJINHERIT) &&
                     (tdp->i_d.di_projid != sip->i_d.di_projid))) {
-               error = XFS_ERROR(EPERM);
+               error = XFS_ERROR(EXDEV);
                goto error_return;
        }
 
        if (resblks == 0 &&
-           (error = XFS_DIR_CANENTER(mp, tp, tdp, target_name,
-                       target_namelen)))
+           (error = xfs_dir_canenter(tp, tdp, target_name, target_namelen)))
                goto error_return;
 
        XFS_BMAP_INIT(&free_list, &first_block);
 
-       error = XFS_DIR_CREATENAME(mp, tp, tdp, target_name, target_namelen,
+       error = xfs_dir_createname(tp, tdp, target_name, target_namelen,
                                   sip->i_ino, &first_block, &free_list,
                                   resblks);
        if (error)
@@ -2711,9 +2707,8 @@ xfs_link(
        xfs_trans_log_inode(tp, tdp, XFS_ILOG_CORE);
 
        error = xfs_bumplink(tp, sip);
-       if (error) {
+       if (error)
                goto abort_return;
-       }
 
        /*
         * If this is a synchronous mount, make sure that the
@@ -2724,16 +2719,15 @@ xfs_link(
                xfs_trans_set_sync(tp);
        }
 
-       error = xfs_bmap_finish (&tp, &free_list, first_block, &committed);
+       error = xfs_bmap_finish (&tp, &free_list, &committed);
        if (error) {
                xfs_bmap_cancel(&free_list);
                goto abort_return;
        }
 
-       error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES, NULL);
-       if (error) {
+       error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES);
+       if (error)
                goto std_return;
-       }
 
        /* Fall through to std_return with error = 0. */
 std_return:
@@ -2749,11 +2743,13 @@ std_return:
  abort_return:
        cancel_flags |= XFS_TRANS_ABORT;
        /* FALLTHROUGH */
+
  error_return:
        xfs_trans_cancel(tp, cancel_flags);
-
        goto std_return;
 }
+
+
 /*
  * xfs_mkdir
  *
@@ -2761,15 +2757,15 @@ std_return:
 STATIC int
 xfs_mkdir(
        bhv_desc_t              *dir_bdp,
-       vname_t                 *dentry,
-       vattr_t                 *vap,
-       vnode_t                 **vpp,
+       bhv_vname_t             *dentry,
+       bhv_vattr_t             *vap,
+       bhv_vnode_t             **vpp,
        cred_t                  *credp)
 {
        char                    *dir_name = VNAME(dentry);
        xfs_inode_t             *dp;
        xfs_inode_t             *cdp;   /* inode of created dir */
-       vnode_t                 *cvp;   /* vnode of created dir */
+       bhv_vnode_t             *cvp;   /* vnode of created dir */
        xfs_trans_t             *tp;
        xfs_mount_t             *mp;
        int                     cancel_flags;
@@ -2777,7 +2773,7 @@ xfs_mkdir(
        int                     committed;
        xfs_bmap_free_t         free_list;
        xfs_fsblock_t           first_block;
-       vnode_t                 *dir_vp;
+       bhv_vnode_t             *dir_vp;
        boolean_t               dp_joined_to_trans;
        boolean_t               created = B_FALSE;
        int                     dm_event_sent = 0;
@@ -2867,7 +2863,7 @@ xfs_mkdir(
                goto error_return;
 
        if (resblks == 0 &&
-           (error = XFS_DIR_CANENTER(mp, tp, dp, dir_name, dir_namelen)))
+           (error = xfs_dir_canenter(tp, dp, dir_name, dir_namelen)))
                goto error_return;
        /*
         * create the directory inode.
@@ -2894,9 +2890,9 @@ xfs_mkdir(
 
        XFS_BMAP_INIT(&free_list, &first_block);
 
-       error = XFS_DIR_CREATENAME(mp, tp, dp, dir_name, dir_namelen,
-                       cdp->i_ino, &first_block, &free_list,
-                       resblks ? resblks - XFS_IALLOC_SPACE_RES(mp) : 0);
+       error = xfs_dir_createname(tp, dp, dir_name, dir_namelen, cdp->i_ino,
+                                  &first_block, &free_list, resblks ?
+                                  resblks - XFS_IALLOC_SPACE_RES(mp) : 0);
        if (error) {
                ASSERT(error != ENOSPC);
                goto error1;
@@ -2910,16 +2906,14 @@ xfs_mkdir(
         */
        dp->i_gen++;
 
-       error = XFS_DIR_INIT(mp, tp, cdp, dp);
-       if (error) {
+       error = xfs_dir_init(tp, cdp, dp);
+       if (error)
                goto error2;
-       }
 
        cdp->i_gen = 1;
        error = xfs_bumplink(tp, dp);
-       if (error) {
+       if (error)
                goto error2;
-       }
 
        cvp = XFS_ITOV(cdp);
 
@@ -2942,13 +2936,13 @@ xfs_mkdir(
                xfs_trans_set_sync(tp);
        }
 
-       error = xfs_bmap_finish(&tp, &free_list, first_block, &committed);
+       error = xfs_bmap_finish(&tp, &free_list, &committed);
        if (error) {
                IRELE(cdp);
                goto error2;
        }
 
-       error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES, NULL);
+       error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES);
        XFS_QM_DQRELE(mp, udqp);
        XFS_QM_DQRELE(mp, gdqp);
        if (error) {
@@ -2996,7 +2990,7 @@ std_return:
 STATIC int
 xfs_rmdir(
        bhv_desc_t              *dir_bdp,
-       vname_t                 *dentry,
+       bhv_vname_t             *dentry,
        cred_t                  *credp)
 {
        char                    *name = VNAME(dentry);
@@ -3009,8 +3003,8 @@ xfs_rmdir(
        xfs_fsblock_t           first_block;
        int                     cancel_flags;
        int                     committed;
-       vnode_t                 *dir_vp;
-       int                     dm_di_mode = 0;
+       bhv_vnode_t             *dir_vp;
+       int                     dm_di_mode = S_IFDIR;
        int                     last_cdp_link;
        int                     namelen;
        uint                    resblks;
@@ -3025,11 +3019,16 @@ xfs_rmdir(
                return XFS_ERROR(EIO);
        namelen = VNAMELEN(dentry);
 
+       if (!xfs_get_dir_entry(dentry, &cdp)) {
+               dm_di_mode = cdp->i_d.di_mode;
+               IRELE(cdp);
+       }
+
        if (DM_EVENT_ENABLED(dir_vp->v_vfsp, dp, DM_EVENT_REMOVE)) {
                error = XFS_SEND_NAMESP(mp, DM_EVENT_REMOVE,
                                        dir_vp, DM_RIGHT_NULL,
                                        NULL, DM_RIGHT_NULL,
-                                       name, NULL, 0, 0, 0);
+                                       name, NULL, dm_di_mode, 0, 0);
                if (error)
                        return XFS_ERROR(error);
        }
@@ -3047,7 +3046,7 @@ xfs_rmdir(
         * for a log reservation.  Since we'll have to wait for the
         * inactive code to complete before returning from xfs_iget,
         * we need to make sure that we don't have log space reserved
-        * when we call xfs_iget.  Instead we get an unlocked referece
+        * when we call xfs_iget.  Instead we get an unlocked reference
         * to the inode before getting our log reservation.
         */
        error = xfs_get_dir_entry(dentry, &cdp);
@@ -3103,7 +3102,7 @@ xfs_rmdir(
         * that the directory entry for the child directory inode has
         * not changed while we were obtaining a log reservation.
         */
-       error = xfs_lock_dir_and_entry(dp, dentry, cdp);
+       error = xfs_lock_dir_and_entry(dp, cdp);
        if (error) {
                xfs_trans_cancel(tp, cancel_flags);
                IRELE(cdp);
@@ -3128,16 +3127,15 @@ xfs_rmdir(
                error = XFS_ERROR(ENOTEMPTY);
                goto error_return;
        }
-       if (!XFS_DIR_ISEMPTY(mp, cdp)) {
+       if (!xfs_dir_isempty(cdp)) {
                error = XFS_ERROR(ENOTEMPTY);
                goto error_return;
        }
 
-       error = XFS_DIR_REMOVENAME(mp, tp, dp, name, namelen, cdp->i_ino,
-               &first_block, &free_list, resblks);
-       if (error) {
+       error = xfs_dir_removename(tp, dp, name, namelen, cdp->i_ino,
+                                       &first_block, &free_list, resblks);
+       if (error)
                goto error1;
-       }
 
        xfs_ichgtime(dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
 
@@ -3189,7 +3187,7 @@ xfs_rmdir(
                xfs_trans_set_sync(tp);
        }
 
-       error = xfs_bmap_finish (&tp, &free_list, first_block, &committed);
+       error = xfs_bmap_finish (&tp, &free_list, &committed);
        if (error) {
                xfs_bmap_cancel(&free_list);
                xfs_trans_cancel(tp, (XFS_TRANS_RELEASE_LOG_RES |
@@ -3198,7 +3196,7 @@ xfs_rmdir(
                goto std_return;
        }
 
-       error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES, NULL);
+       error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES);
        if (error) {
                IRELE(cdp);
                goto std_return;
@@ -3208,13 +3206,13 @@ xfs_rmdir(
        /*
         * Let interposed file systems know about removed links.
         */
-       VOP_LINK_REMOVED(XFS_ITOV(cdp), dir_vp, last_cdp_link);
+       bhv_vop_link_removed(XFS_ITOV(cdp), dir_vp, last_cdp_link);
 
        IRELE(cdp);
 
        /* Fall through to std_return with error = 0 or the errno
         * from xfs_trans_commit. */
-std_return:
+ std_return:
        if (DM_EVENT_ENABLED(dir_vp->v_vfsp, dp, DM_EVENT_POSTREMOVE)) {
                (void) XFS_SEND_NAMESP(mp, DM_EVENT_POSTREMOVE,
                                        dir_vp, DM_RIGHT_NULL,
@@ -3227,6 +3225,8 @@ std_return:
  error1:
        xfs_bmap_cancel(&free_list);
        cancel_flags |= XFS_TRANS_ABORT;
+       /* FALLTHROUGH */
+
  error_return:
        xfs_trans_cancel(tp, cancel_flags);
        goto std_return;
@@ -3234,8 +3234,6 @@ std_return:
 
 
 /*
- * xfs_readdir
- *
  * Read dp's entries starting at uiop->uio_offset and translate them into
  * bufsize bytes worth of struct dirents starting at bufbase.
  */
@@ -3250,38 +3248,28 @@ xfs_readdir(
        xfs_trans_t     *tp = NULL;
        int             error = 0;
        uint            lock_mode;
-       xfs_off_t       start_offset;
 
        vn_trace_entry(BHV_TO_VNODE(dir_bdp), __FUNCTION__,
                                               (inst_t *)__return_address);
        dp = XFS_BHVTOI(dir_bdp);
 
-       if (XFS_FORCED_SHUTDOWN(dp->i_mount)) {
+       if (XFS_FORCED_SHUTDOWN(dp->i_mount))
                return XFS_ERROR(EIO);
-       }
 
        lock_mode = xfs_ilock_map_shared(dp);
-       start_offset = uiop->uio_offset;
-       error = XFS_DIR_GETDENTS(dp->i_mount, tp, dp, uiop, eofp);
-       if (start_offset != uiop->uio_offset) {
-               xfs_ichgtime(dp, XFS_ICHGTIME_ACC);
-       }
+       error = xfs_dir_getdents(tp, dp, uiop, eofp);
        xfs_iunlock_map_shared(dp, lock_mode);
        return error;
 }
 
 
-/*
- * xfs_symlink
- *
- */
 STATIC int
 xfs_symlink(
        bhv_desc_t              *dir_bdp,
-       vname_t                 *dentry,
-       vattr_t                 *vap,
+       bhv_vname_t             *dentry,
+       bhv_vattr_t             *vap,
        char                    *target_path,
-       vnode_t                 **vpp,
+       bhv_vnode_t             **vpp,
        cred_t                  *credp)
 {
        xfs_trans_t             *tp;
@@ -3293,7 +3281,7 @@ xfs_symlink(
        xfs_bmap_free_t         free_list;
        xfs_fsblock_t           first_block;
        boolean_t               dp_joined_to_trans;
-       vnode_t                 *dir_vp;
+       bhv_vnode_t             *dir_vp;
        uint                    cancel_flags;
        int                     committed;
        xfs_fileoff_t           first_fsb;
@@ -3338,7 +3326,7 @@ xfs_symlink(
                int len, total;
                char *path;
 
-               for(total = 0, path = target_path; total < pathlen;) {
+               for (total = 0, path = target_path; total < pathlen;) {
                        /*
                         * Skip any slashes.
                         */
@@ -3432,7 +3420,7 @@ xfs_symlink(
         * Check for ability to enter directory entry, if no space reserved.
         */
        if (resblks == 0 &&
-           (error = XFS_DIR_CANENTER(mp, tp, dp, link_name, link_namelen)))
+           (error = xfs_dir_canenter(tp, dp, link_name, link_namelen)))
                goto error_return;
        /*
         * Initialize the bmap freelist prior to calling either
@@ -3487,7 +3475,7 @@ xfs_symlink(
                error = xfs_bmapi(tp, ip, first_fsb, fs_blocks,
                                  XFS_BMAPI_WRITE | XFS_BMAPI_METADATA,
                                  &first_block, resblks, mval, &nmaps,
-                                 &free_list);
+                                 &free_list, NULL);
                if (error) {
                        goto error1;
                }
@@ -3519,11 +3507,10 @@ xfs_symlink(
        /*
         * Create the directory entry for the symlink.
         */
-       error = XFS_DIR_CREATENAME(mp, tp, dp, link_name, link_namelen,
-                       ip->i_ino, &first_block, &free_list, resblks);
-       if (error) {
+       error = xfs_dir_createname(tp, dp, link_name, link_namelen, ip->i_ino,
+                                  &first_block, &free_list, resblks);
+       if (error)
                goto error1;
-       }
        xfs_ichgtime(dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
        xfs_trans_log_inode(tp, dp, XFS_ILOG_CORE);
 
@@ -3550,11 +3537,11 @@ xfs_symlink(
         */
        IHOLD(ip);
 
-       error = xfs_bmap_finish(&tp, &free_list, first_block, &committed);
+       error = xfs_bmap_finish(&tp, &free_list, &committed);
        if (error) {
                goto error2;
        }
-       error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES, NULL);
+       error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES);
        XFS_QM_DQRELE(mp, udqp);
        XFS_QM_DQRELE(mp, gdqp);
 
@@ -3571,7 +3558,7 @@ std_return:
        }
 
        if (!error) {
-               vnode_t *vp;
+               bhv_vnode_t *vp;
 
                ASSERT(ip);
                vp = XFS_ITOV(ip);
@@ -3636,10 +3623,10 @@ xfs_fid2(
 int
 xfs_rwlock(
        bhv_desc_t      *bdp,
-       vrwlock_t       locktype)
+       bhv_vrwlock_t   locktype)
 {
        xfs_inode_t     *ip;
-       vnode_t         *vp;
+       bhv_vnode_t     *vp;
 
        vp = BHV_TO_VNODE(bdp);
        if (VN_ISDIR(vp))
@@ -3648,9 +3635,9 @@ xfs_rwlock(
        if (locktype == VRWLOCK_WRITE) {
                xfs_ilock(ip, XFS_IOLOCK_EXCL);
        } else if (locktype == VRWLOCK_TRY_READ) {
-               return (xfs_ilock_nowait(ip, XFS_IOLOCK_SHARED));
+               return xfs_ilock_nowait(ip, XFS_IOLOCK_SHARED);
        } else if (locktype == VRWLOCK_TRY_WRITE) {
-               return (xfs_ilock_nowait(ip, XFS_IOLOCK_EXCL));
+               return xfs_ilock_nowait(ip, XFS_IOLOCK_EXCL);
        } else {
                ASSERT((locktype == VRWLOCK_READ) ||
                       (locktype == VRWLOCK_WRITE_DIRECT));
@@ -3667,10 +3654,10 @@ xfs_rwlock(
 void
 xfs_rwunlock(
        bhv_desc_t      *bdp,
-       vrwlock_t       locktype)
+       bhv_vrwlock_t   locktype)
 {
        xfs_inode_t     *ip;
-       vnode_t         *vp;
+       bhv_vnode_t     *vp;
 
        vp = BHV_TO_VNODE(bdp);
        if (VN_ISDIR(vp))
@@ -3774,7 +3761,6 @@ xfs_inode_flush(
        return error;
 }
 
-
 int
 xfs_set_dmattrs (
        bhv_desc_t      *bdp,
@@ -3810,21 +3796,17 @@ xfs_set_dmattrs (
 
        xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
        IHOLD(ip);
-       error = xfs_trans_commit(tp, 0, NULL);
+       error = xfs_trans_commit(tp, 0);
 
        return error;
 }
 
-
-/*
- * xfs_reclaim
- */
 STATIC int
 xfs_reclaim(
        bhv_desc_t      *bdp)
 {
        xfs_inode_t     *ip;
-       vnode_t         *vp;
+       bhv_vnode_t     *vp;
 
        vp = BHV_TO_VNODE(bdp);
        ip = XFS_BHVTOI(bdp);
@@ -3842,13 +3824,23 @@ xfs_reclaim(
        vn_iowait(vp);
 
        ASSERT(XFS_FORCED_SHUTDOWN(ip->i_mount) || ip->i_delayed_blks == 0);
-       ASSERT(VN_CACHED(vp) == 0);
 
-       /* If we have nothing to flush with this inode then complete the
-        * teardown now, otherwise break the link between the xfs inode
-        * and the linux inode and clean up the xfs inode later. This
-        * avoids flushing the inode to disk during the delete operation
-        * itself.
+       /*
+        * Make sure the atime in the XFS inode is correct before freeing the
+        * Linux inode.
+        */
+       xfs_synchronize_atime(ip);
+
+       /*
+        * If we have nothing to flush with this inode then complete the
+        * teardown now, otherwise break the link between the xfs inode and the
+        * linux inode and clean up the xfs inode later. This avoids flushing
+        * the inode to disk during the delete operation itself.
+        *
+        * When breaking the link, we need to set the XFS_IRECLAIMABLE flag
+        * first to ensure that xfs_iunpin() will never see an xfs inode
+        * that has a linux inode being reclaimed. Synchronisation is provided
+        * by the i_flags_lock.
         */
        if (!ip->i_update_core && (ip->i_itemp == NULL)) {
                xfs_ilock(ip, XFS_ILOCK_EXCL);
@@ -3857,11 +3849,13 @@ xfs_reclaim(
        } else {
                xfs_mount_t     *mp = ip->i_mount;
 
-               /* Protect sync from us */
+               /* Protect sync and unpin from us */
                XFS_MOUNT_ILOCK(mp);
+               spin_lock(&ip->i_flags_lock);
+               __xfs_iflags_set(ip, XFS_IRECLAIMABLE);
                vn_bhv_remove(VN_BHV_HEAD(vp), XFS_ITOBHV(ip));
+               spin_unlock(&ip->i_flags_lock);
                list_add_tail(&ip->i_reclaim, &mp->m_del_inodes);
-               ip->i_flags |= XFS_IRECLAIMABLE;
                XFS_MOUNT_IUNLOCK(mp);
        }
        return 0;
@@ -3874,7 +3868,7 @@ xfs_finish_reclaim(
        int             sync_mode)
 {
        xfs_ihash_t     *ih = ip->i_hash;
-       vnode_t         *vp = XFS_ITOV_NULL(ip);
+       bhv_vnode_t     *vp = XFS_ITOV_NULL(ip);
        int             error;
 
        if (vp && VN_BAD(vp))
@@ -3886,16 +3880,19 @@ xfs_finish_reclaim(
         * us.
         */
        write_lock(&ih->ih_lock);
-       if ((ip->i_flags & XFS_IRECLAIM) ||
-           (!(ip->i_flags & XFS_IRECLAIMABLE) && vp == NULL)) {
+       spin_lock(&ip->i_flags_lock);
+       if (__xfs_iflags_test(ip, XFS_IRECLAIM) ||
+           (!__xfs_iflags_test(ip, XFS_IRECLAIMABLE) && vp == NULL)) {
+               spin_unlock(&ip->i_flags_lock);
                write_unlock(&ih->ih_lock);
                if (locked) {
                        xfs_ifunlock(ip);
                        xfs_iunlock(ip, XFS_ILOCK_EXCL);
                }
-               return(1);
+               return 1;
        }
-       ip->i_flags |= XFS_IRECLAIM;
+       __xfs_iflags_set(ip, XFS_IRECLAIM);
+       spin_unlock(&ip->i_flags_lock);
        write_unlock(&ih->ih_lock);
 
        /*
@@ -3971,8 +3968,9 @@ xfs_finish_reclaim_all(xfs_mount_t *mp, int noblock)
                                }
                        }
                        XFS_MOUNT_IUNLOCK(mp);
-                       xfs_finish_reclaim(ip, noblock,
-                               XFS_IFLUSH_DELWRI_ELSE_ASYNC);
+                       if (xfs_finish_reclaim(ip, noblock,
+                                       XFS_IFLUSH_DELWRI_ELSE_ASYNC))
+                               delay(1);
                        purged = 1;
                        break;
                }
@@ -4011,42 +4009,36 @@ xfs_alloc_file_space(
        int                     alloc_type,
        int                     attr_flags)
 {
+       xfs_mount_t             *mp = ip->i_mount;
+       xfs_off_t               count;
        xfs_filblks_t           allocated_fsb;
        xfs_filblks_t           allocatesize_fsb;
-       int                     committed;
-       xfs_off_t               count;
-       xfs_filblks_t           datablocks;
-       int                     error;
+       xfs_extlen_t            extsz, temp;
+       xfs_fileoff_t           startoffset_fsb;
        xfs_fsblock_t           firstfsb;
-       xfs_bmap_free_t         free_list;
-       xfs_bmbt_irec_t         *imapp;
-       xfs_bmbt_irec_t         imaps[1];
-       xfs_mount_t             *mp;
-       int                     numrtextents;
-       int                     reccount;
-       uint                    resblks;
+       int                     nimaps;
+       int                     bmapi_flag;
+       int                     quota_flag;
        int                     rt;
-       int                     rtextsize;
-       xfs_fileoff_t           startoffset_fsb;
        xfs_trans_t             *tp;
-       int                     xfs_bmapi_flags;
+       xfs_bmbt_irec_t         imaps[1], *imapp;
+       xfs_bmap_free_t         free_list;
+       uint                    qblocks, resblks, resrtextents;
+       int                     committed;
+       int                     error;
 
        vn_trace_entry(XFS_ITOV(ip), __FUNCTION__, (inst_t *)__return_address);
-       mp = ip->i_mount;
 
        if (XFS_FORCED_SHUTDOWN(mp))
                return XFS_ERROR(EIO);
 
-       /*
-        * determine if this is a realtime file
-        */
-       if ((rt = XFS_IS_REALTIME_INODE(ip)) != 0) {
-               if (ip->i_d.di_extsize)
-                       rtextsize = ip->i_d.di_extsize;
-               else
-                       rtextsize = mp->m_sb.sb_rextsize;
-       } else
-               rtextsize = 0;
+       rt = XFS_IS_REALTIME_INODE(ip);
+       if (unlikely(rt)) {
+               if (!(extsz = ip->i_d.di_extsize))
+                       extsz = mp->m_sb.sb_rextsize;
+       } else {
+               extsz = ip->i_d.di_extsize;
+       }
 
        if ((error = XFS_QM_DQATTACH(mp, ip, 0)))
                return error;
@@ -4057,65 +4049,73 @@ xfs_alloc_file_space(
        count = len;
        error = 0;
        imapp = &imaps[0];
-       reccount = 1;
-       xfs_bmapi_flags = XFS_BMAPI_WRITE | (alloc_type ? XFS_BMAPI_PREALLOC : 0);
+       nimaps = 1;
+       bmapi_flag = XFS_BMAPI_WRITE | (alloc_type ? XFS_BMAPI_PREALLOC : 0);
        startoffset_fsb = XFS_B_TO_FSBT(mp, offset);
        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);
                if (error)
-                       return(error);
+                       return error;
        }
 
        /*
-        * allocate file space until done or until there is an error
+        * Allocate file space until done or until there is an error
         */
 retry:
        while (allocatesize_fsb && !error) {
+               xfs_fileoff_t   s, e;
+
                /*
-                * determine if reserving space on
-                * the data or realtime partition.
+                * Determine space reservations for data/realtime.
                 */
-               if (rt) {
-                       xfs_fileoff_t s, e;
-
+               if (unlikely(extsz)) {
                        s = startoffset_fsb;
-                       do_div(s, rtextsize);
-                       s *= rtextsize;
-                       e = roundup_64(startoffset_fsb + allocatesize_fsb,
-                               rtextsize);
-                       numrtextents = (int)(e - s) / mp->m_sb.sb_rextsize;
-                       datablocks = 0;
+                       do_div(s, extsz);
+                       s *= extsz;
+                       e = startoffset_fsb + allocatesize_fsb;
+                       if ((temp = do_mod(startoffset_fsb, extsz)))
+                               e += temp;
+                       if ((temp = do_mod(e, extsz)))
+                               e += extsz - temp;
                } else {
-                       datablocks = allocatesize_fsb;
-                       numrtextents = 0;
+                       s = 0;
+                       e = allocatesize_fsb;
+               }
+
+               if (unlikely(rt)) {
+                       resrtextents = qblocks = (uint)(e - s);
+                       resrtextents /= mp->m_sb.sb_rextsize;
+                       resblks = XFS_DIOSTRAT_SPACE_RES(mp, 0);
+                       quota_flag = XFS_QMOPT_RES_RTBLKS;
+               } else {
+                       resrtextents = 0;
+                       resblks = qblocks = \
+                               XFS_DIOSTRAT_SPACE_RES(mp, (uint)(e - s));
+                       quota_flag = XFS_QMOPT_RES_REGBLKS;
                }
 
                /*
-                * allocate and setup the transaction
+                * Allocate and setup the transaction.
                 */
                tp = xfs_trans_alloc(mp, XFS_TRANS_DIOSTRAT);
-               resblks = XFS_DIOSTRAT_SPACE_RES(mp, datablocks);
-               error = xfs_trans_reserve(tp,
-                                         resblks,
-                                         XFS_WRITE_LOG_RES(mp),
-                                         numrtextents,
+               error = xfs_trans_reserve(tp, resblks,
+                                         XFS_WRITE_LOG_RES(mp), resrtextents,
                                          XFS_TRANS_PERM_LOG_RES,
                                          XFS_WRITE_LOG_COUNT);
-
                /*
-                * check for running out of space
+                * Check for running out of space
                 */
                if (error) {
                        /*
@@ -4126,8 +4126,8 @@ retry:
                        break;
                }
                xfs_ilock(ip, XFS_ILOCK_EXCL);
-               error = XFS_TRANS_RESERVE_QUOTA(mp, tp,
-                               ip->i_udquot, ip->i_gdquot, resblks, 0, 0);
+               error = XFS_TRANS_RESERVE_QUOTA_NBLKS(mp, tp, ip,
+                                                     qblocks, 0, quota_flag);
                if (error)
                        goto error1;
 
@@ -4135,26 +4135,26 @@ retry:
                xfs_trans_ihold(tp, ip);
 
                /*
-                * issue the bmapi() call to allocate the blocks
+                * Issue the xfs_bmapi() call to allocate the blocks
                 */
                XFS_BMAP_INIT(&free_list, &firstfsb);
-               error = xfs_bmapi(tp, ip, startoffset_fsb,
-                                 allocatesize_fsb, xfs_bmapi_flags,
-                                 &firstfsb, 0, imapp, &reccount,
-                                 &free_list);
+               error = XFS_BMAPI(mp, tp, &ip->i_iocore, startoffset_fsb,
+                                 allocatesize_fsb, bmapi_flag,
+                                 &firstfsb, 0, imapp, &nimaps,
+                                 &free_list, NULL);
                if (error) {
                        goto error0;
                }
 
                /*
-                * complete the transaction
+                * Complete the transaction
                 */
-               error = xfs_bmap_finish(&tp, &free_list, firstfsb, &committed);
+               error = xfs_bmap_finish(&tp, &free_list, &committed);
                if (error) {
                        goto error0;
                }
 
-               error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES, NULL);
+               error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES);
                xfs_iunlock(ip, XFS_ILOCK_EXCL);
                if (error) {
                        break;
@@ -4162,7 +4162,7 @@ retry:
 
                allocated_fsb = imapp->br_blockcount;
 
-               if (reccount == 0) {
+               if (nimaps == 0) {
                        error = XFS_ERROR(ENOSPC);
                        break;
                }
@@ -4185,9 +4185,11 @@ dmapi_enospc_check:
 
        return error;
 
- error0:
+error0:        /* Cancel bmap, unlock inode, unreserve quota blocks, cancel trans */
        xfs_bmap_cancel(&free_list);
- error1:
+       XFS_TRANS_UNRESERVE_QUOTA_NBLKS(mp, tp, ip, qblocks, 0, quota_flag);
+
+error1:        /* Just cancel transaction */
        xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES | XFS_TRANS_ABORT);
        xfs_iunlock(ip, XFS_ILOCK_EXCL);
        goto dmapi_enospc_check;
@@ -4219,8 +4221,8 @@ xfs_zero_remaining_bytes(
        for (offset = startoff; offset <= endoff; offset = lastoffset + 1) {
                offset_fsb = XFS_B_TO_FSBT(mp, offset);
                nimap = 1;
-               error = xfs_bmapi(NULL, ip, offset_fsb, 1, 0, NULL, 0, &imap,
-                       &nimap, NULL);
+               error = XFS_BMAPI(mp, NULL, &ip->i_iocore, offset_fsb, 1, 0,
+                       NULL, 0, &imap, &nimap, NULL, NULL);
                if (error || nimap < 1)
                        break;
                ASSERT(imap.br_blockcount >= 1);
@@ -4279,7 +4281,7 @@ xfs_free_file_space(
        xfs_off_t               len,
        int                     attr_flags)
 {
-       vnode_t                 *vp;
+       bhv_vnode_t             *vp;
        int                     committed;
        int                     done;
        xfs_off_t               end_dmi_offset;
@@ -4287,14 +4289,13 @@ xfs_free_file_space(
        int                     error;
        xfs_fsblock_t           firstfsb;
        xfs_bmap_free_t         free_list;
-       xfs_off_t               ilen;
        xfs_bmbt_irec_t         imap;
        xfs_off_t               ioffset;
        xfs_extlen_t            mod=0;
        xfs_mount_t             *mp;
        int                     nimap;
        uint                    resblks;
-       int                     rounding;
+       uint                    rounding;
        int                     rt;
        xfs_fileoff_t           startoffset_fsb;
        xfs_trans_t             *tp;
@@ -4316,36 +4317,35 @@ xfs_free_file_space(
        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);
                if (error)
-                       return(error);
+                       return error;
        }
 
-       ASSERT(attr_flags & ATTR_NOLOCK ? attr_flags & ATTR_DMI : 1);
        if (attr_flags & ATTR_NOLOCK)
                need_iolock = 0;
-       if (need_iolock)
+       if (need_iolock) {
                xfs_ilock(ip, XFS_IOLOCK_EXCL);
+               vn_iowait(vp);  /* wait for the completion of any pending DIOs */
+       }
 
-       rounding = MAX((__uint8_t)(1 << mp->m_sb.sb_blocklog),
-                       (__uint8_t)NBPP);
-       ilen = len + (offset & (rounding - 1));
+       rounding = max_t(uint, 1 << mp->m_sb.sb_blocklog, NBPP);
        ioffset = offset & ~(rounding - 1);
-       if (ilen & (rounding - 1))
-               ilen = (ilen + rounding) & ~(rounding - 1);
 
        if (VN_CACHED(vp) != 0) {
                xfs_inval_cached_trace(&ip->i_iocore, ioffset, -1,
                                ctooff(offtoct(ioffset)), -1);
-               VOP_FLUSHINVAL_PAGES(vp, ctooff(offtoct(ioffset)),
+               error = bhv_vop_flushinval_pages(vp, ctooff(offtoct(ioffset)),
                                -1, FI_REMAPF_LOCKED);
+               if (error)
+                       goto out_unlock_iolock;
        }
 
        /*
@@ -4356,8 +4356,8 @@ xfs_free_file_space(
         */
        if (rt && !XFS_SB_VERSION_HASEXTFLGBIT(&mp->m_sb)) {
                nimap = 1;
-               error = xfs_bmapi(NULL, ip, startoffset_fsb, 1, 0, NULL, 0,
-                       &imap, &nimap, NULL);
+               error = XFS_BMAPI(mp, NULL, &ip->i_iocore, startoffset_fsb,
+                       1, 0, NULL, 0, &imap, &nimap, NULL, NULL);
                if (error)
                        goto out_unlock_iolock;
                ASSERT(nimap == 0 || nimap == 1);
@@ -4371,8 +4371,8 @@ xfs_free_file_space(
                                startoffset_fsb += mp->m_sb.sb_rextsize - mod;
                }
                nimap = 1;
-               error = xfs_bmapi(NULL, ip, endoffset_fsb - 1, 1, 0, NULL, 0,
-                       &imap, &nimap, NULL);
+               error = XFS_BMAPI(mp, NULL, &ip->i_iocore, endoffset_fsb - 1,
+                       1, 0, NULL, 0, &imap, &nimap, NULL, NULL);
                if (error)
                        goto out_unlock_iolock;
                ASSERT(nimap == 0 || nimap == 1);
@@ -4432,8 +4432,8 @@ xfs_free_file_space(
                }
                xfs_ilock(ip, XFS_ILOCK_EXCL);
                error = XFS_TRANS_RESERVE_QUOTA(mp, tp,
-                               ip->i_udquot, ip->i_gdquot, resblks, 0, rt ?
-                               XFS_QMOPT_RES_RTBLKS : XFS_QMOPT_RES_REGBLKS);
+                               ip->i_udquot, ip->i_gdquot, resblks, 0,
+                               XFS_QMOPT_RES_REGBLKS);
                if (error)
                        goto error1;
 
@@ -4444,9 +4444,9 @@ xfs_free_file_space(
                 * issue the bunmapi() call to free the blocks
                 */
                XFS_BMAP_INIT(&free_list, &firstfsb);
-               error = xfs_bunmapi(tp, ip, startoffset_fsb,
+               error = XFS_BUNMAPI(mp, tp, &ip->i_iocore, startoffset_fsb,
                                  endoffset_fsb - startoffset_fsb,
-                                 0, 2, &firstfsb, &free_list, &done);
+                                 0, 2, &firstfsb, &free_list, NULL, &done);
                if (error) {
                        goto error0;
                }
@@ -4454,12 +4454,12 @@ xfs_free_file_space(
                /*
                 * complete the transaction
                 */
-               error = xfs_bmap_finish(&tp, &free_list, firstfsb, &committed);
+               error = xfs_bmap_finish(&tp, &free_list, &committed);
                if (error) {
                        goto error0;
                }
 
-               error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES, NULL);
+               error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES);
                xfs_iunlock(ip, XFS_ILOCK_EXCL);
        }
 
@@ -4506,8 +4506,8 @@ xfs_change_file_space(
        xfs_off_t       startoffset;
        xfs_off_t       llen;
        xfs_trans_t     *tp;
-       vattr_t         va;
-       vnode_t         *vp;
+       bhv_vattr_t     va;
+       bhv_vnode_t     *vp;
 
        vp = BHV_TO_VNODE(bdp);
        vn_trace_entry(vp, __FUNCTION__, (inst_t *)__return_address);
@@ -4537,7 +4537,7 @@ xfs_change_file_space(
                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);
@@ -4554,7 +4554,7 @@ xfs_change_file_space(
        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
@@ -4653,20 +4653,25 @@ xfs_change_file_space(
        xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
        xfs_trans_set_sync(tp);
 
-       error = xfs_trans_commit(tp, 0, NULL);
+       error = xfs_trans_commit(tp, 0);
 
        xfs_iunlock(ip, XFS_ILOCK_EXCL);
 
        return error;
 }
 
-vnodeops_t xfs_vnodeops = {
+bhv_vnodeops_t xfs_vnodeops = {
        BHV_IDENTITY_INIT(VN_BHV_XFS,VNODE_POSITION_XFS),
        .vop_open               = xfs_open,
+       .vop_close              = xfs_close,
        .vop_read               = xfs_read,
 #ifdef HAVE_SENDFILE
        .vop_sendfile           = xfs_sendfile,
 #endif
+#ifdef HAVE_SPLICE
+       .vop_splice_read        = xfs_splice_read,
+       .vop_splice_write       = xfs_splice_write,
+#endif
        .vop_write              = xfs_write,
        .vop_ioctl              = xfs_ioctl,
        .vop_getattr            = xfs_getattr,