Merge branch 'for-linus' of git://oss.sgi.com:8090/xfs/xfs-2.6
authorLinus Torvalds <torvalds@woody.linux-foundation.org>
Wed, 17 Oct 2007 16:04:11 +0000 (09:04 -0700)
committerLinus Torvalds <torvalds@woody.linux-foundation.org>
Wed, 17 Oct 2007 16:04:11 +0000 (09:04 -0700)
* 'for-linus' of git://oss.sgi.com:8090/xfs/xfs-2.6: (59 commits)
  [XFS] eagerly remove vmap mappings to avoid upsetting Xen
  [XFS] simplify validata_fields
  [XFS] no longer using io_vnode, as was remaining from 23 cherrypick
  [XFS] Remove STATIC which was missing from prior manual merge
  [XFS] Put back the QUEUE_ORDERED_NONE test in the barrier check.
  [XFS] Turn off XBF_ASYNC flag before re-reading superblock.
  [XFS] avoid race in sync_inodes() that can fail to write out all dirty data
  [XFS] This fix prevents bulkstat from spinning in an infinite loop.
  [XFS] simplify xfs_create/mknod/symlink prototype
  [XFS] avoid xfs_getattr in XFS_IOC_FSGETXATTR ioctl
  [XFS] get_bulkall() could return incorrect inode state
  [XFS] Kill unused IOMAP_EOF flag
  [XFS] fix when DMAPI mount option processing happens
  [XFS] ensure file size is logged on synchronous writes
  [XFS] growlock should be a mutex
  [XFS] replace some large xfs_log_priv.h macros by proper functions
  [XFS] kill struct bhv_vfs
  [XFS] move syncing related members from struct bhv_vfs to struct xfs_mount
  [XFS] kill the vfs_flags member in struct bhv_vfs
  [XFS] kill the vfs_fsid and vfs_altfsid members in struct bhv_vfs
  ...

1  2 
fs/xfs/linux-2.6/xfs_aops.c
fs/xfs/linux-2.6/xfs_buf.c
fs/xfs/linux-2.6/xfs_iops.c
fs/xfs/linux-2.6/xfs_lrw.c
fs/xfs/linux-2.6/xfs_super.c

@@@ -37,6 -37,7 +37,7 @@@
  #include "xfs_error.h"
  #include "xfs_rw.h"
  #include "xfs_iomap.h"
+ #include "xfs_vnodeops.h"
  #include <linux/mpage.h>
  #include <linux/pagevec.h>
  #include <linux/writeback.h>
@@@ -139,9 -140,11 +140,11 @@@ xfs_destroy_ioend
                next = bh->b_private;
                bh->b_end_io(bh, !ioend->io_error);
        }
-       if (unlikely(ioend->io_error))
-               vn_ioerror(ioend->io_vnode, ioend->io_error, __FILE__,__LINE__);
-       vn_iowake(ioend->io_vnode);
+       if (unlikely(ioend->io_error)) {
+               vn_ioerror(XFS_I(ioend->io_inode), ioend->io_error,
+                               __FILE__,__LINE__);
+       }
+       vn_iowake(XFS_I(ioend->io_inode));
        mempool_free(ioend, xfs_ioend_pool);
  }
  
@@@ -156,14 -159,10 +159,10 @@@ STATIC voi
  xfs_setfilesize(
        xfs_ioend_t             *ioend)
  {
-       xfs_inode_t             *ip;
+       xfs_inode_t             *ip = XFS_I(ioend->io_inode);
        xfs_fsize_t             isize;
        xfs_fsize_t             bsize;
  
-       ip = xfs_vtoi(ioend->io_vnode);
-       if (!ip)
-               return;
        ASSERT((ip->i_d.di_mode & S_IFMT) == S_IFREG);
        ASSERT(ioend->io_type != IOMAP_READ);
  
                ip->i_d.di_size = isize;
                ip->i_update_core = 1;
                ip->i_update_size = 1;
-               mark_inode_dirty_sync(vn_to_inode(ioend->io_vnode));
+               mark_inode_dirty_sync(ioend->io_inode);
        }
  
        xfs_iunlock(ip, XFS_ILOCK_EXCL);
@@@ -227,12 -226,12 +226,12 @@@ xfs_end_bio_unwritten
  {
        xfs_ioend_t             *ioend =
                container_of(work, xfs_ioend_t, io_work);
-       bhv_vnode_t             *vp = ioend->io_vnode;
        xfs_off_t               offset = ioend->io_offset;
        size_t                  size = ioend->io_size;
  
        if (likely(!ioend->io_error)) {
-               bhv_vop_bmap(vp, offset, size, BMAPI_UNWRITTEN, NULL, NULL);
+               xfs_bmap(XFS_I(ioend->io_inode), offset, size,
+                               BMAPI_UNWRITTEN, NULL, NULL);
                xfs_setfilesize(ioend);
        }
        xfs_destroy_ioend(ioend);
@@@ -275,10 -274,10 +274,10 @@@ xfs_alloc_ioend
        ioend->io_error = 0;
        ioend->io_list = NULL;
        ioend->io_type = type;
-       ioend->io_vnode = vn_from_inode(inode);
+       ioend->io_inode = inode;
        ioend->io_buffer_head = NULL;
        ioend->io_buffer_tail = NULL;
-       atomic_inc(&ioend->io_vnode->v_iocount);
+       atomic_inc(&XFS_I(ioend->io_inode)->i_iocount);
        ioend->io_offset = 0;
        ioend->io_size = 0;
  
@@@ -302,12 -301,13 +301,13 @@@ xfs_map_blocks
        xfs_iomap_t             *mapp,
        int                     flags)
  {
-       bhv_vnode_t             *vp = vn_from_inode(inode);
+       xfs_inode_t             *ip = XFS_I(inode);
        int                     error, nmaps = 1;
  
-       error = bhv_vop_bmap(vp, offset, count, flags, mapp, &nmaps);
+       error = xfs_bmap(ip, offset, count,
+                               flags, mapp, &nmaps);
        if (!error && (flags & (BMAPI_WRITE|BMAPI_ALLOCATE)))
-               VMODIFY(vp);
+               xfs_iflags_set(ip, XFS_IMODIFIED);
        return -error;
  }
  
@@@ -323,13 -323,17 +323,13 @@@ xfs_iomap_valid
  /*
   * BIO completion handler for buffered IO.
   */
 -STATIC int
 +STATIC void
  xfs_end_bio(
        struct bio              *bio,
 -      unsigned int            bytes_done,
        int                     error)
  {
        xfs_ioend_t             *ioend = bio->bi_private;
  
 -      if (bio->bi_size)
 -              return 1;
 -
        ASSERT(atomic_read(&bio->bi_cnt) >= 1);
        ioend->io_error = test_bit(BIO_UPTODATE, &bio->bi_flags) ? 0 : error;
  
        bio_put(bio);
  
        xfs_finish_ioend(ioend, 0);
 -      return 0;
  }
  
  STATIC void
@@@ -402,9 -407,10 +402,9 @@@ xfs_start_page_writeback
                clear_page_dirty_for_io(page);
        set_page_writeback(page);
        unlock_page(page);
 -      if (!buffers) {
 +      /* If no buffers on the page are to be written, finish it here */
 +      if (!buffers)
                end_page_writeback(page);
 -              wbc->pages_skipped++;   /* We didn't write this page */
 -      }
  }
  
  static inline int bio_add_buffer(struct bio *bio, struct buffer_head *bh)
@@@ -497,7 -503,7 +497,7 @@@ xfs_cancel_ioend
                        unlock_buffer(bh);
                } while ((bh = next_bh) != NULL);
  
-               vn_iowake(ioend->io_vnode);
+               vn_iowake(XFS_I(ioend->io_inode));
                mempool_free(ioend, xfs_ioend_pool);
        } while ((ioend = next) != NULL);
  }
@@@ -1237,10 -1243,7 +1237,7 @@@ xfs_vm_writepages
        struct address_space    *mapping,
        struct writeback_control *wbc)
  {
-       struct bhv_vnode        *vp = vn_from_inode(mapping->host);
-       if (VN_TRUNC(vp))
-               VUNTRUNCATE(vp);
+       xfs_iflags_clear(XFS_I(mapping->host), XFS_ITRUNCATED);
        return generic_writepages(mapping, wbc);
  }
  
@@@ -1317,7 -1320,6 +1314,6 @@@ __xfs_get_blocks
        int                     direct,
        bmapi_flags_t           flags)
  {
-       bhv_vnode_t             *vp = vn_from_inode(inode);
        xfs_iomap_t             iomap;
        xfs_off_t               offset;
        ssize_t                 size;
        offset = (xfs_off_t)iblock << inode->i_blkbits;
        ASSERT(bh_result->b_size >= (1 << inode->i_blkbits));
        size = bh_result->b_size;
-       error = bhv_vop_bmap(vp, offset, size,
+       error = xfs_bmap(XFS_I(inode), offset, size,
                             create ? flags : BMAPI_READ, &iomap, &niomap);
        if (error)
                return -error;
@@@ -1475,13 -1477,13 +1471,13 @@@ xfs_vm_direct_IO
  {
        struct file     *file = iocb->ki_filp;
        struct inode    *inode = file->f_mapping->host;
-       bhv_vnode_t     *vp = vn_from_inode(inode);
        xfs_iomap_t     iomap;
        int             maps = 1;
        int             error;
        ssize_t         ret;
  
-       error = bhv_vop_bmap(vp, offset, 0, BMAPI_DEVICE, &iomap, &maps);
+       error = xfs_bmap(XFS_I(inode), offset, 0,
+                               BMAPI_DEVICE, &iomap, &maps);
        if (error)
                return -error;
  
  }
  
  STATIC int
 -xfs_vm_prepare_write(
 +xfs_vm_write_begin(
        struct file             *file,
 -      struct page             *page,
 -      unsigned int            from,
 -      unsigned int            to)
 +      struct address_space    *mapping,
 +      loff_t                  pos,
 +      unsigned                len,
 +      unsigned                flags,
 +      struct page             **pagep,
 +      void                    **fsdata)
  {
 -      return block_prepare_write(page, from, to, xfs_get_blocks);
 +      *pagep = NULL;
 +      return block_write_begin(file, mapping, pos, len, flags, pagep, fsdata,
 +                                                              xfs_get_blocks);
  }
  
  STATIC sector_t
@@@ -1527,12 -1524,13 +1523,13 @@@ xfs_vm_bmap
        sector_t                block)
  {
        struct inode            *inode = (struct inode *)mapping->host;
-       bhv_vnode_t             *vp = vn_from_inode(inode);
+       struct xfs_inode        *ip = XFS_I(inode);
  
-       vn_trace_entry(vp, __FUNCTION__, (inst_t *)__return_address);
-       bhv_vop_rwlock(vp, VRWLOCK_READ);
-       bhv_vop_flush_pages(vp, (xfs_off_t)0, -1, 0, FI_REMAPF);
-       bhv_vop_rwunlock(vp, VRWLOCK_READ);
+       vn_trace_entry(XFS_I(inode), __FUNCTION__,
+                       (inst_t *)__return_address);
+       xfs_rwlock(ip, VRWLOCK_READ);
+       xfs_flush_pages(ip, (xfs_off_t)0, -1, 0, FI_REMAPF);
+       xfs_rwunlock(ip, VRWLOCK_READ);
        return generic_block_bmap(mapping, block, xfs_get_blocks);
  }
  
@@@ -1572,8 -1570,8 +1569,8 @@@ const struct address_space_operations x
        .sync_page              = block_sync_page,
        .releasepage            = xfs_vm_releasepage,
        .invalidatepage         = xfs_vm_invalidatepage,
 -      .prepare_write          = xfs_vm_prepare_write,
 -      .commit_write           = generic_commit_write,
 +      .write_begin            = xfs_vm_write_begin,
 +      .write_end              = generic_write_end,
        .bmap                   = xfs_vm_bmap,
        .direct_IO              = xfs_vm_direct_IO,
        .migratepage            = buffer_migrate_page,
@@@ -187,6 -187,19 +187,19 @@@ free_address
  {
        a_list_t        *aentry;
  
+ #ifdef CONFIG_XEN
+       /*
+        * Xen needs to be able to make sure it can get an exclusive
+        * RO mapping of pages it wants to turn into a pagetable.  If
+        * a newly allocated page is also still being vmap()ed by xfs,
+        * it will cause pagetable construction to fail.  This is a
+        * quick workaround to always eagerly unmap pages so that Xen
+        * is happy.
+        */
+       vunmap(addr);
+       return;
+ #endif
        aentry = kmalloc(sizeof(a_list_t), GFP_NOWAIT);
        if (likely(aentry)) {
                spin_lock(&as_lock);
@@@ -997,7 -1010,18 +1010,18 @@@ xfs_buf_iodone_work
        xfs_buf_t               *bp =
                container_of(work, xfs_buf_t, b_iodone_work);
  
-       if (bp->b_iodone)
+       /*
+        * We can get an EOPNOTSUPP to ordered writes.  Here we clear the
+        * ordered flag and reissue them.  Because we can't tell the higher
+        * layers directly that they should not issue ordered I/O anymore, they
+        * need to check if the ordered flag was cleared during I/O completion.
+        */
+       if ((bp->b_error == EOPNOTSUPP) &&
+           (bp->b_flags & (XBF_ORDERED|XBF_ASYNC)) == (XBF_ORDERED|XBF_ASYNC)) {
+               XB_TRACE(bp, "ordered_retry", bp->b_iodone);
+               bp->b_flags &= ~XBF_ORDERED;
+               xfs_buf_iorequest(bp);
+       } else if (bp->b_iodone)
                (*(bp->b_iodone))(bp);
        else if (bp->b_flags & XBF_ASYNC)
                xfs_buf_relse(bp);
@@@ -1103,15 -1127,19 +1127,15 @@@ _xfs_buf_ioend
        }
  }
  
 -STATIC int
 +STATIC void
  xfs_buf_bio_end_io(
        struct bio              *bio,
 -      unsigned int            bytes_done,
        int                     error)
  {
        xfs_buf_t               *bp = (xfs_buf_t *)bio->bi_private;
        unsigned int            blocksize = bp->b_target->bt_bsize;
        struct bio_vec          *bvec = bio->bi_io_vec + bio->bi_vcnt - 1;
  
 -      if (bio->bi_size)
 -              return 1;
 -
        if (!test_bit(BIO_UPTODATE, &bio->bi_flags))
                bp->b_error = EIO;
  
  
        _xfs_buf_ioend(bp, 1);
        bio_put(bio);
 -      return 0;
  }
  
  STATIC void
@@@ -46,6 -46,7 +46,7 @@@
  #include "xfs_attr.h"
  #include "xfs_buf_item.h"
  #include "xfs_utils.h"
+ #include "xfs_vnodeops.h"
  
  #include <linux/capability.h>
  #include <linux/xattr.h>
  #include <linux/security.h>
  
  /*
-  * Get a XFS inode from a given vnode.
-  */
- xfs_inode_t *
- xfs_vtoi(
-       bhv_vnode_t     *vp)
- {
-       bhv_desc_t      *bdp;
-       bdp = bhv_lookup_range(VN_BHV_HEAD(vp),
-                       VNODE_POSITION_XFS, VNODE_POSITION_XFS);
-       if (unlikely(bdp == NULL))
-               return NULL;
-       return XFS_BHVTOI(bdp);
- }
- /*
   * Bring the atime in the XFS inode uptodate.
   * Used before logging the inode to disk or when the Linux inode goes away.
   */
@@@ -80,9 -65,8 +65,8 @@@ xfs_synchronize_atime
  
        vp = XFS_ITOV_NULL(ip);
        if (vp) {
-               struct inode *inode = &vp->v_inode;
-               ip->i_d.di_atime.t_sec = (__int32_t)inode->i_atime.tv_sec;
-               ip->i_d.di_atime.t_nsec = (__int32_t)inode->i_atime.tv_nsec;
+               ip->i_d.di_atime.t_sec = (__int32_t)vp->i_atime.tv_sec;
+               ip->i_d.di_atime.t_nsec = (__int32_t)vp->i_atime.tv_nsec;
        }
  }
  
@@@ -133,7 -117,7 +117,7 @@@ xfs_ichgtime
         */
        SYNCHRONIZE();
        ip->i_update_core = 1;
 -      if (!(inode->i_state & I_LOCK))
 +      if (!(inode->i_state & I_SYNC))
                mark_inode_dirty_sync(inode);
  }
  
@@@ -185,7 -169,7 +169,7 @@@ xfs_ichgtime_fast
         */
        SYNCHRONIZE();
        ip->i_update_core = 1;
 -      if (!(inode->i_state & I_LOCK))
 +      if (!(inode->i_state & I_SYNC))
                mark_inode_dirty_sync(inode);
  }
  
   */
  STATIC void
  xfs_validate_fields(
-       struct inode    *ip,
-       bhv_vattr_t     *vattr)
+       struct inode            *inode)
  {
-       vattr->va_mask = XFS_AT_NLINK|XFS_AT_SIZE|XFS_AT_NBLOCKS;
-       if (!bhv_vop_getattr(vn_from_inode(ip), vattr, ATTR_LAZY, NULL)) {
-               ip->i_nlink = vattr->va_nlink;
-               ip->i_blocks = vattr->va_nblocks;
-               /* we're under i_sem so i_size can't change under us */
-               if (i_size_read(ip) != vattr->va_size)
-                       i_size_write(ip, vattr->va_size);
-       }
+       struct xfs_inode        *ip = XFS_I(inode);
+       loff_t size;
+       inode->i_nlink = ip->i_d.di_nlink;
+       inode->i_blocks =
+               XFS_FSB_TO_BB(ip->i_mount, ip->i_d.di_nblocks +
+                                          ip->i_delayed_blks);
+       /* we're under i_sem so i_size can't change under us */
+       size = XFS_ISIZE(ip);
+       if (i_size_read(inode) != size)
+               i_size_write(inode, size);
  }
  
  /*
@@@ -233,9 -218,10 +218,10 @@@ xfs_init_security
                return -error;
        }
  
-       error = bhv_vop_attr_set(vp, name, value, length, ATTR_SECURE, NULL);
+       error = xfs_attr_set(XFS_I(ip), name, value,
+                       length, ATTR_SECURE);
        if (!error)
-               VMODIFY(vp);
+               xfs_iflags_set(XFS_I(ip), XFS_IMODIFIED);
  
        kfree(name);
        kfree(value);
@@@ -256,7 -242,7 +242,7 @@@ xfs_has_fs_struct(struct task_struct *t
  
  STATIC void
  xfs_cleanup_inode(
-       bhv_vnode_t     *dvp,
+       struct inode    *dir,
        bhv_vnode_t     *vp,
        struct dentry   *dentry,
        int             mode)
        teardown.d_name = dentry->d_name;
  
        if (S_ISDIR(mode))
-               bhv_vop_rmdir(dvp, &teardown, NULL);
+               xfs_rmdir(XFS_I(dir), &teardown);
        else
-               bhv_vop_remove(dvp, &teardown, NULL);
+               xfs_remove(XFS_I(dir), &teardown);
        VN_RELE(vp);
  }
  
@@@ -286,7 -272,6 +272,6 @@@ xfs_vn_mknod
        dev_t           rdev)
  {
        struct inode    *ip;
-       bhv_vattr_t     vattr = { 0 };
        bhv_vnode_t     *vp = NULL, *dvp = vn_from_inode(dir);
        xfs_acl_t       *default_acl = NULL;
        attrexists_t    test_default_acl = _ACL_DEFAULT_EXISTS;
        if (IS_POSIXACL(dir) && !default_acl && xfs_has_fs_struct(current))
                mode &= ~current->fs->umask;
  
-       vattr.va_mask = XFS_AT_TYPE|XFS_AT_MODE;
-       vattr.va_mode = mode;
        switch (mode & S_IFMT) {
        case S_IFCHR: case S_IFBLK: case S_IFIFO: case S_IFSOCK:
-               vattr.va_rdev = sysv_encode_dev(rdev);
-               vattr.va_mask |= XFS_AT_RDEV;
-               /*FALLTHROUGH*/
+               rdev = sysv_encode_dev(rdev);
        case S_IFREG:
-               error = bhv_vop_create(dvp, dentry, &vattr, &vp, NULL);
+               error = xfs_create(XFS_I(dir), dentry, mode, rdev, &vp, NULL);
                break;
        case S_IFDIR:
-               error = bhv_vop_mkdir(dvp, dentry, &vattr, &vp, NULL);
+               error = xfs_mkdir(XFS_I(dir), dentry, mode, &vp, NULL);
                break;
        default:
                error = EINVAL;
        if (unlikely(!error)) {
                error = xfs_init_security(vp, dir);
                if (error)
-                       xfs_cleanup_inode(dvp, vp, dentry, mode);
+                       xfs_cleanup_inode(dir, vp, dentry, mode);
        }
  
        if (unlikely(default_acl)) {
                if (!error) {
-                       error = _ACL_INHERIT(vp, &vattr, default_acl);
+                       error = _ACL_INHERIT(vp, mode, default_acl);
                        if (!error)
-                               VMODIFY(vp);
+                               xfs_iflags_set(XFS_I(vp), XFS_IMODIFIED);
                        else
-                               xfs_cleanup_inode(dvp, vp, dentry, mode);
+                               xfs_cleanup_inode(dir, vp, dentry, mode);
                }
                _ACL_FREE(default_acl);
        }
                if (S_ISCHR(mode) || S_ISBLK(mode))
                        ip->i_rdev = rdev;
                else if (S_ISDIR(mode))
-                       xfs_validate_fields(ip, &vattr);
+                       xfs_validate_fields(ip);
                d_instantiate(dentry, ip);
-               xfs_validate_fields(dir, &vattr);
+               xfs_validate_fields(dir);
        }
        return -error;
  }
@@@ -387,13 -367,13 +367,13 @@@ xfs_vn_lookup
        struct dentry   *dentry,
        struct nameidata *nd)
  {
-       bhv_vnode_t     *vp = vn_from_inode(dir), *cvp;
+       bhv_vnode_t     *cvp;
        int             error;
  
        if (dentry->d_name.len >= MAXNAMELEN)
                return ERR_PTR(-ENAMETOOLONG);
  
-       error = bhv_vop_lookup(vp, dentry, &cvp, 0, NULL, NULL);
+       error = xfs_lookup(XFS_I(dir), dentry, &cvp);
        if (unlikely(error)) {
                if (unlikely(error != ENOENT))
                        return ERR_PTR(-error);
@@@ -411,22 -391,19 +391,19 @@@ xfs_vn_link
        struct dentry   *dentry)
  {
        struct inode    *ip;    /* inode of guy being linked to */
-       bhv_vnode_t     *tdvp;  /* target directory for new name/link */
        bhv_vnode_t     *vp;    /* vp of name being linked */
-       bhv_vattr_t     vattr;
        int             error;
  
        ip = old_dentry->d_inode;       /* inode being linked to */
-       tdvp = vn_from_inode(dir);
        vp = vn_from_inode(ip);
  
        VN_HOLD(vp);
-       error = bhv_vop_link(tdvp, vp, dentry, NULL);
+       error = xfs_link(XFS_I(dir), vp, dentry);
        if (unlikely(error)) {
                VN_RELE(vp);
        } else {
-               VMODIFY(tdvp);
-               xfs_validate_fields(ip, &vattr);
+               xfs_iflags_set(XFS_I(dir), XFS_IMODIFIED);
+               xfs_validate_fields(ip);
                d_instantiate(dentry, ip);
        }
        return -error;
@@@ -438,17 -415,14 +415,14 @@@ xfs_vn_unlink
        struct dentry   *dentry)
  {
        struct inode    *inode;
-       bhv_vnode_t     *dvp;   /* directory containing name to remove */
-       bhv_vattr_t     vattr;
        int             error;
  
        inode = dentry->d_inode;
-       dvp = vn_from_inode(dir);
  
-       error = bhv_vop_remove(dvp, dentry, NULL);
+       error = xfs_remove(XFS_I(dir), dentry);
        if (likely(!error)) {
-               xfs_validate_fields(dir, &vattr);       /* size needs update */
-               xfs_validate_fields(inode, &vattr);
+               xfs_validate_fields(dir);       /* size needs update */
+               xfs_validate_fields(inode);
        }
        return -error;
  }
@@@ -460,28 -434,26 +434,26 @@@ xfs_vn_symlink
        const char      *symname)
  {
        struct inode    *ip;
-       bhv_vattr_t     va = { 0 };
-       bhv_vnode_t     *dvp;   /* directory containing name of symlink */
        bhv_vnode_t     *cvp;   /* used to lookup symlink to put in dentry */
        int             error;
+       mode_t          mode;
  
-       dvp = vn_from_inode(dir);
        cvp = NULL;
  
-       va.va_mode = S_IFLNK |
+       mode = S_IFLNK |
                (irix_symlink_mode ? 0777 & ~current->fs->umask : S_IRWXUGO);
-       va.va_mask = XFS_AT_TYPE|XFS_AT_MODE;
  
-       error = bhv_vop_symlink(dvp, dentry, &va, (char *)symname, &cvp, NULL);
+       error = xfs_symlink(XFS_I(dir), dentry, (char *)symname, mode,
+                           &cvp, NULL);
        if (likely(!error && cvp)) {
                error = xfs_init_security(cvp, dir);
                if (likely(!error)) {
                        ip = vn_to_inode(cvp);
                        d_instantiate(dentry, ip);
-                       xfs_validate_fields(dir, &va);
-                       xfs_validate_fields(ip, &va);
+                       xfs_validate_fields(dir);
+                       xfs_validate_fields(ip);
                } else {
-                       xfs_cleanup_inode(dvp, cvp, dentry, 0);
+                       xfs_cleanup_inode(dir, cvp, dentry, 0);
                }
        }
        return -error;
@@@ -493,14 -465,12 +465,12 @@@ xfs_vn_rmdir
        struct dentry   *dentry)
  {
        struct inode    *inode = dentry->d_inode;
-       bhv_vnode_t     *dvp = vn_from_inode(dir);
-       bhv_vattr_t     vattr;
        int             error;
  
-       error = bhv_vop_rmdir(dvp, dentry, NULL);
+       error = xfs_rmdir(XFS_I(dir), dentry);
        if (likely(!error)) {
-               xfs_validate_fields(inode, &vattr);
-               xfs_validate_fields(dir, &vattr);
+               xfs_validate_fields(inode);
+               xfs_validate_fields(dir);
        }
        return -error;
  }
@@@ -513,21 -483,18 +483,18 @@@ xfs_vn_rename
        struct dentry   *ndentry)
  {
        struct inode    *new_inode = ndentry->d_inode;
-       bhv_vnode_t     *fvp;   /* from directory */
        bhv_vnode_t     *tvp;   /* target directory */
-       bhv_vattr_t     vattr;
        int             error;
  
-       fvp = vn_from_inode(odir);
        tvp = vn_from_inode(ndir);
  
-       error = bhv_vop_rename(fvp, odentry, tvp, ndentry, NULL);
+       error = xfs_rename(XFS_I(odir), odentry, tvp, ndentry);
        if (likely(!error)) {
                if (new_inode)
-                       xfs_validate_fields(new_inode, &vattr);
-               xfs_validate_fields(odir, &vattr);
+                       xfs_validate_fields(new_inode);
+               xfs_validate_fields(odir);
                if (ndir != odir)
-                       xfs_validate_fields(ndir, &vattr);
+                       xfs_validate_fields(ndir);
        }
        return -error;
  }
@@@ -542,50 -509,25 +509,25 @@@ xfs_vn_follow_link
        struct dentry           *dentry,
        struct nameidata        *nd)
  {
-       bhv_vnode_t             *vp;
-       uio_t                   *uio;
-       iovec_t                 iov;
-       int                     error;
        char                    *link;
-       ASSERT(dentry);
-       ASSERT(nd);
+       int                     error = -ENOMEM;
  
        link = kmalloc(MAXPATHLEN+1, GFP_KERNEL);
-       if (!link) {
-               nd_set_link(nd, ERR_PTR(-ENOMEM));
-               return NULL;
-       }
-       uio = kmalloc(sizeof(uio_t), GFP_KERNEL);
-       if (!uio) {
-               kfree(link);
-               nd_set_link(nd, ERR_PTR(-ENOMEM));
-               return NULL;
-       }
-       vp = vn_from_inode(dentry->d_inode);
-       iov.iov_base = link;
-       iov.iov_len = MAXPATHLEN;
+       if (!link)
+               goto out_err;
  
-       uio->uio_iov = &iov;
-       uio->uio_offset = 0;
-       uio->uio_segflg = UIO_SYSSPACE;
-       uio->uio_resid = MAXPATHLEN;
-       uio->uio_iovcnt = 1;
-       error = bhv_vop_readlink(vp, uio, 0, NULL);
-       if (unlikely(error)) {
-               kfree(link);
-               link = ERR_PTR(-error);
-       } else {
-               link[MAXPATHLEN - uio->uio_resid] = '\0';
-       }
-       kfree(uio);
+       error = -xfs_readlink(XFS_I(dentry->d_inode), link);
+       if (unlikely(error))
+               goto out_kfree;
  
        nd_set_link(nd, link);
        return NULL;
+  out_kfree:
+       kfree(link);
+  out_err:
+       nd_set_link(nd, ERR_PTR(error));
+       return NULL;
  }
  
  STATIC void
@@@ -607,7 -549,7 +549,7 @@@ xfs_vn_permission
        int             mode,
        struct nameidata *nd)
  {
-       return -bhv_vop_access(vn_from_inode(inode), mode << 6, NULL);
+       return -xfs_access(XFS_I(inode), mode << 6, NULL);
  }
  #else
  #define xfs_vn_permission NULL
@@@ -620,11 -562,10 +562,10 @@@ xfs_vn_getattr
        struct kstat    *stat)
  {
        struct inode    *inode = dentry->d_inode;
-       bhv_vnode_t     *vp = vn_from_inode(inode);
        bhv_vattr_t     vattr = { .va_mask = XFS_AT_STAT };
        int             error;
  
-       error = bhv_vop_getattr(vp, &vattr, ATTR_LAZY, NULL);
+       error = xfs_getattr(XFS_I(inode), &vattr, ATTR_LAZY);
        if (likely(!error)) {
                stat->size = i_size_read(inode);
                stat->dev = inode->i_sb->s_dev;
@@@ -652,7 -593,6 +593,6 @@@ xfs_vn_setattr
  {
        struct inode    *inode = dentry->d_inode;
        unsigned int    ia_valid = attr->ia_valid;
-       bhv_vnode_t     *vp = vn_from_inode(inode);
        bhv_vattr_t     vattr = { 0 };
        int             flags = 0;
        int             error;
                flags |= ATTR_NONBLOCK;
  #endif
  
-       error = bhv_vop_setattr(vp, &vattr, flags, NULL);
+       error = xfs_setattr(XFS_I(inode), &vattr, flags, NULL);
        if (likely(!error))
-               __vn_revalidate(vp, &vattr);
+               __vn_revalidate(vn_from_inode(inode), &vattr);
        return -error;
  }
  
@@@ -48,6 -48,7 +48,7 @@@
  #include "xfs_buf_item.h"
  #include "xfs_utils.h"
  #include "xfs_iomap.h"
+ #include "xfs_vnodeops.h"
  
  #include <linux/capability.h>
  #include <linux/writeback.h>
@@@ -134,34 -135,45 +135,34 @@@ xfs_iozero
        loff_t                  pos,    /* offset in file               */
        size_t                  count)  /* size of data to zero         */
  {
 -      unsigned                bytes;
        struct page             *page;
        struct address_space    *mapping;
        int                     status;
  
        mapping = ip->i_mapping;
        do {
 -              unsigned long index, offset;
 +              unsigned offset, bytes;
 +              void *fsdata;
  
                offset = (pos & (PAGE_CACHE_SIZE -1)); /* Within page */
 -              index = pos >> PAGE_CACHE_SHIFT;
                bytes = PAGE_CACHE_SIZE - offset;
                if (bytes > count)
                        bytes = count;
  
 -              status = -ENOMEM;
 -              page = grab_cache_page(mapping, index);
 -              if (!page)
 -                      break;
 -
 -              status = mapping->a_ops->prepare_write(NULL, page, offset,
 -                                                      offset + bytes);
 +              status = pagecache_write_begin(NULL, mapping, pos, bytes,
 +                                      AOP_FLAG_UNINTERRUPTIBLE,
 +                                      &page, &fsdata);
                if (status)
 -                      goto unlock;
 +                      break;
  
                zero_user_page(page, offset, bytes, KM_USER0);
  
 -              status = mapping->a_ops->commit_write(NULL, page, offset,
 -                                                      offset + bytes);
 -              if (!status) {
 -                      pos += bytes;
 -                      count -= bytes;
 -              }
 -
 -unlock:
 -              unlock_page(page);
 -              page_cache_release(page);
 -              if (status)
 -                      break;
 +              status = pagecache_write_end(NULL, mapping, pos, bytes, bytes,
 +                                      page, fsdata);
 +              WARN_ON(status <= 0); /* can't return less than zero! */
 +              pos += bytes;
 +              count -= bytes;
 +              status = 0;
        } while (count);
  
        return (-status);
  
  ssize_t                       /* bytes read, or (-)  error */
  xfs_read(
-       bhv_desc_t              *bdp,
+       xfs_inode_t             *ip,
        struct kiocb            *iocb,
        const struct iovec      *iovp,
        unsigned int            segs,
        loff_t                  *offset,
-       int                     ioflags,
-       cred_t                  *credp)
+       int                     ioflags)
  {
        struct file             *file = iocb->ki_filp;
        struct inode            *inode = file->f_mapping->host;
+       bhv_vnode_t             *vp = XFS_ITOV(ip);
+       xfs_mount_t             *mp = ip->i_mount;
        size_t                  size = 0;
        ssize_t                 ret = 0;
        xfs_fsize_t             n;
-       xfs_inode_t             *ip;
-       xfs_mount_t             *mp;
-       bhv_vnode_t             *vp;
        unsigned long           seg;
  
-       ip = XFS_BHVTOI(bdp);
-       vp = BHV_TO_VNODE(bdp);
-       mp = ip->i_mount;
  
        XFS_STATS_INC(xs_read_calls);
  
                mutex_lock(&inode->i_mutex);
        xfs_ilock(ip, XFS_IOLOCK_SHARED);
  
-       if (DM_EVENT_ENABLED(vp->v_vfsp, ip, DM_EVENT_READ) &&
-           !(ioflags & IO_INVIS)) {
+       if (DM_EVENT_ENABLED(ip, DM_EVENT_READ) && !(ioflags & IO_INVIS)) {
                bhv_vrwlock_t locktype = VRWLOCK_READ;
                int dmflags = FILP_DELAY_FLAG(file) | DM_SEM_FLAG_RD(ioflags);
  
-               ret = -XFS_SEND_DATA(mp, DM_EVENT_READ,
-                                       BHV_TO_VNODE(bdp), *offset, size,
+               ret = -XFS_SEND_DATA(mp, DM_EVENT_READ, vp, *offset, size,
                                        dmflags, &locktype);
                if (ret) {
                        xfs_iunlock(ip, XFS_IOLOCK_SHARED);
  
        if (unlikely(ioflags & IO_ISDIRECT)) {
                if (VN_CACHED(vp))
-                       ret = bhv_vop_flushinval_pages(vp, ctooff(offtoct(*offset)),
-                                                -1, FI_REMAPF_LOCKED);
+                       ret = xfs_flushinval_pages(ip,
+                                       ctooff(offtoct(*offset)),
+                                       -1, FI_REMAPF_LOCKED);
                mutex_unlock(&inode->i_mutex);
                if (ret) {
                        xfs_iunlock(ip, XFS_IOLOCK_SHARED);
  
  ssize_t
  xfs_splice_read(
-       bhv_desc_t              *bdp,
+       xfs_inode_t             *ip,
        struct file             *infilp,
        loff_t                  *ppos,
        struct pipe_inode_info  *pipe,
        size_t                  count,
        int                     flags,
-       int                     ioflags,
-       cred_t                  *credp)
+       int                     ioflags)
  {
-       xfs_inode_t             *ip = XFS_BHVTOI(bdp);
+       bhv_vnode_t             *vp = XFS_ITOV(ip);
        xfs_mount_t             *mp = ip->i_mount;
        ssize_t                 ret;
  
  
        xfs_ilock(ip, XFS_IOLOCK_SHARED);
  
-       if (DM_EVENT_ENABLED(BHV_TO_VNODE(bdp)->v_vfsp, ip, DM_EVENT_READ) &&
-           (!(ioflags & IO_INVIS))) {
+       if (DM_EVENT_ENABLED(ip, DM_EVENT_READ) && !(ioflags & IO_INVIS)) {
                bhv_vrwlock_t locktype = VRWLOCK_READ;
                int error;
  
-               error = XFS_SEND_DATA(mp, DM_EVENT_READ, BHV_TO_VNODE(bdp),
-                                       *ppos, count,
+               error = XFS_SEND_DATA(mp, DM_EVENT_READ, vp, *ppos, count,
                                        FILP_DELAY_FLAG(infilp), &locktype);
                if (error) {
                        xfs_iunlock(ip, XFS_IOLOCK_SHARED);
  
  ssize_t
  xfs_splice_write(
-       bhv_desc_t              *bdp,
+       xfs_inode_t             *ip,
        struct pipe_inode_info  *pipe,
        struct file             *outfilp,
        loff_t                  *ppos,
        size_t                  count,
        int                     flags,
-       int                     ioflags,
-       cred_t                  *credp)
+       int                     ioflags)
  {
-       xfs_inode_t             *ip = XFS_BHVTOI(bdp);
+       bhv_vnode_t             *vp = XFS_ITOV(ip);
        xfs_mount_t             *mp = ip->i_mount;
        xfs_iocore_t            *io = &ip->i_iocore;
        ssize_t                 ret;
  
        xfs_ilock(ip, XFS_IOLOCK_EXCL);
  
-       if (DM_EVENT_ENABLED(BHV_TO_VNODE(bdp)->v_vfsp, ip, DM_EVENT_WRITE) &&
-           (!(ioflags & IO_INVIS))) {
+       if (DM_EVENT_ENABLED(ip, DM_EVENT_WRITE) && !(ioflags & IO_INVIS)) {
                bhv_vrwlock_t locktype = VRWLOCK_WRITE;
                int error;
  
-               error = XFS_SEND_DATA(mp, DM_EVENT_WRITE, BHV_TO_VNODE(bdp),
-                                       *ppos, count,
+               error = XFS_SEND_DATA(mp, DM_EVENT_WRITE, vp, *ppos, count,
                                        FILP_DELAY_FLAG(outfilp), &locktype);
                if (error) {
                        xfs_iunlock(ip, XFS_IOLOCK_EXCL);
@@@ -583,24 -583,22 +572,22 @@@ out_lock
  
  ssize_t                               /* bytes written, or (-) error */
  xfs_write(
-       bhv_desc_t              *bdp,
+       struct xfs_inode        *xip,
        struct kiocb            *iocb,
        const struct iovec      *iovp,
        unsigned int            nsegs,
        loff_t                  *offset,
-       int                     ioflags,
-       cred_t                  *credp)
+       int                     ioflags)
  {
        struct file             *file = iocb->ki_filp;
        struct address_space    *mapping = file->f_mapping;
        struct inode            *inode = mapping->host;
+       bhv_vnode_t             *vp = XFS_ITOV(xip);
        unsigned long           segs = nsegs;
-       xfs_inode_t             *xip;
        xfs_mount_t             *mp;
        ssize_t                 ret = 0, error = 0;
        xfs_fsize_t             isize, new_size;
        xfs_iocore_t            *io;
-       bhv_vnode_t             *vp;
        int                     iolock;
        int                     eventsent = 0;
        bhv_vrwlock_t           locktype;
  
        XFS_STATS_INC(xs_write_calls);
  
-       vp = BHV_TO_VNODE(bdp);
-       xip = XFS_BHVTOI(bdp);
        error = generic_segment_checks(iovp, &segs, &ocount, VERIFY_READ);
        if (error)
                return error;
        io = &xip->i_iocore;
        mp = io->io_mount;
  
-       vfs_wait_for_freeze(vp->v_vfsp, SB_FREEZE_WRITE);
+       xfs_wait_for_freeze(mp, SB_FREEZE_WRITE);
  
        if (XFS_FORCED_SHUTDOWN(mp))
                return -EIO;
@@@ -653,7 -648,7 +637,7 @@@ start
                goto out_unlock_mutex;
        }
  
-       if ((DM_EVENT_ENABLED(vp->v_vfsp, xip, DM_EVENT_WRITE) &&
+       if ((DM_EVENT_ENABLED(xip, DM_EVENT_WRITE) &&
            !(ioflags & IO_INVIS) && !eventsent)) {
                int             dmflags = FILP_DELAY_FLAG(file);
  
         */
  
        if (pos > xip->i_size) {
-               error = xfs_zero_eof(BHV_TO_VNODE(bdp), io, pos, xip->i_size);
+               error = xfs_zero_eof(vp, io, pos, xip->i_size);
                if (error) {
                        xfs_iunlock(xip, XFS_ILOCK_EXCL);
                        goto out_unlock_internal;
@@@ -758,7 -753,8 +742,8 @@@ retry
                        WARN_ON(need_i_mutex == 0);
                        xfs_inval_cached_trace(io, pos, -1,
                                        ctooff(offtoct(pos)), -1);
-                       error = bhv_vop_flushinval_pages(vp, ctooff(offtoct(pos)),
+                       error = xfs_flushinval_pages(xip,
+                                       ctooff(offtoct(pos)),
                                        -1, FI_REMAPF_LOCKED);
                        if (error)
                                goto out_unlock_internal;
        if (ret == -EIOCBQUEUED && !(ioflags & IO_ISAIO))
                ret = wait_on_sync_kiocb(iocb);
  
-       if ((ret == -ENOSPC) &&
-           DM_EVENT_ENABLED(vp->v_vfsp, xip, DM_EVENT_NOSPACE) &&
-           !(ioflags & IO_INVIS)) {
-               xfs_rwunlock(bdp, locktype);
+       if (ret == -ENOSPC &&
+           DM_EVENT_ENABLED(xip, DM_EVENT_NOSPACE) && !(ioflags & IO_INVIS)) {
+               xfs_rwunlock(xip, locktype);
                if (need_i_mutex)
                        mutex_unlock(&inode->i_mutex);
                error = XFS_SEND_NAMESP(xip->i_mount, DM_EVENT_NOSPACE, vp,
                                0, 0, 0); /* Delay flag intentionally  unused */
                if (need_i_mutex)
                        mutex_lock(&inode->i_mutex);
-               xfs_rwlock(bdp, locktype);
+               xfs_rwlock(xip, locktype);
                if (error)
                        goto out_unlock_internal;
                pos = xip->i_size;
  
        /* Handle various SYNC-type writes */
        if ((file->f_flags & O_SYNC) || IS_SYNC(inode)) {
-               error = xfs_write_sync_logforce(mp, xip);
-               if (error)
-                       goto out_unlock_internal;
-               xfs_rwunlock(bdp, locktype);
+               int error2;
+               xfs_rwunlock(xip, locktype);
                if (need_i_mutex)
                        mutex_unlock(&inode->i_mutex);
-               error = sync_page_range(inode, mapping, pos, ret);
+               error2 = sync_page_range(inode, mapping, pos, ret);
                if (!error)
-                       error = -ret;
+                       error = error2;
                if (need_i_mutex)
                        mutex_lock(&inode->i_mutex);
-               xfs_rwlock(bdp, locktype);
+               xfs_rwlock(xip, locktype);
+               error2 = xfs_write_sync_logforce(mp, xip);
+               if (!error)
+                       error = error2;
        }
  
   out_unlock_internal:
                        xip->i_d.di_size = xip->i_size;
                xfs_iunlock(xip, XFS_ILOCK_EXCL);
        }
-       xfs_rwunlock(bdp, locktype);
+       xfs_rwunlock(xip, locktype);
   out_unlock_mutex:
        if (need_i_mutex)
                mutex_unlock(&inode->i_mutex);
@@@ -914,14 -907,14 +896,14 @@@ xfs_bdstrat_cb(struct xfs_buf *bp
  
  
  int
- xfs_bmap(bhv_desc_t   *bdp,
+ xfs_bmap(
+       xfs_inode_t     *ip,
        xfs_off_t       offset,
        ssize_t         count,
        int             flags,
        xfs_iomap_t     *iomapp,
        int             *niomaps)
  {
-       xfs_inode_t     *ip = XFS_BHVTOI(bdp);
        xfs_iocore_t    *io = &ip->i_iocore;
  
        ASSERT((ip->i_d.di_mode & S_IFMT) == S_IFREG);
@@@ -46,6 -46,8 +46,8 @@@
  #include "xfs_attr.h"
  #include "xfs_buf_item.h"
  #include "xfs_utils.h"
+ #include "xfs_vnodeops.h"
+ #include "xfs_vfsops.h"
  #include "xfs_version.h"
  
  #include <linux/namei.h>
@@@ -196,23 -198,20 +198,20 @@@ xfs_revalidate_inode
                inode->i_flags |= S_NOATIME;
        else
                inode->i_flags &= ~S_NOATIME;
-       vp->v_flag &= ~VMODIFIED;
+       xfs_iflags_clear(ip, XFS_IMODIFIED);
  }
  
  void
  xfs_initialize_vnode(
-       bhv_desc_t              *bdp,
+       struct xfs_mount        *mp,
        bhv_vnode_t             *vp,
-       bhv_desc_t              *inode_bhv,
-       int                     unlock)
+       struct xfs_inode        *ip)
  {
-       xfs_inode_t             *ip = XFS_BHVTOI(inode_bhv);
        struct inode            *inode = vn_to_inode(vp);
  
-       if (!inode_bhv->bd_vobj) {
-               vp->v_vfsp = bhvtovfs(bdp);
-               bhv_desc_init(inode_bhv, ip, vp, &xfs_vnodeops);
-               bhv_insert(VN_BHV_HEAD(vp), inode_bhv);
+       if (!ip->i_vnode) {
+               ip->i_vnode = vp;
+               inode->i_private = ip;
        }
  
        /*
         * second time once the inode is properly set up, and then we can
         * finish our work.
         */
-       if (ip->i_d.di_mode != 0 && unlock && (inode->i_state & I_NEW)) {
-               xfs_revalidate_inode(XFS_BHVTOM(bdp), vp, ip);
+       if (ip->i_d.di_mode != 0 && (inode->i_state & I_NEW)) {
+               xfs_revalidate_inode(mp, vp, ip);
                xfs_set_inodeops(inode);
  
                xfs_iflags_clear(ip, XFS_INEW);
@@@ -356,8 -355,9 +355,8 @@@ xfs_fs_destroy_inode
  
  STATIC void
  xfs_fs_inode_init_once(
 -      void                    *vnode,
        kmem_zone_t             *zonep,
 -      unsigned long           flags)
 +      void                    *vnode)
  {
        inode_init_once(vn_to_inode((bhv_vnode_t *)vnode));
  }
@@@ -409,19 -409,22 +408,22 @@@ xfs_fs_write_inode
        struct inode            *inode,
        int                     sync)
  {
-       bhv_vnode_t             *vp = vn_from_inode(inode);
        int                     error = 0, flags = FLUSH_INODE;
  
-       if (vp) {
-               vn_trace_entry(vp, __FUNCTION__, (inst_t *)__return_address);
-               if (sync) {
-                       filemap_fdatawait(inode->i_mapping);
-                       flags |= FLUSH_SYNC;
-               }
-               error = bhv_vop_iflush(vp, flags);
-               if (error == EAGAIN)
-                       error = sync? bhv_vop_iflush(vp, flags | FLUSH_LOG) : 0;
+       vn_trace_entry(XFS_I(inode), __FUNCTION__,
+                       (inst_t *)__return_address);
+       if (sync) {
+               filemap_fdatawait(inode->i_mapping);
+               flags |= FLUSH_SYNC;
        }
+       error = xfs_inode_flush(XFS_I(inode), flags);
+       /*
+        * if we failed to write out the inode then mark
+        * it dirty again so we'll try again later.
+        */
+       if (error)
+               mark_inode_dirty_sync(inode);
        return -error;
  }
  
@@@ -429,35 -432,27 +431,27 @@@ STATIC voi
  xfs_fs_clear_inode(
        struct inode            *inode)
  {
-       bhv_vnode_t             *vp = vn_from_inode(inode);
-       vn_trace_entry(vp, __FUNCTION__, (inst_t *)__return_address);
-       XFS_STATS_INC(vn_rele);
-       XFS_STATS_INC(vn_remove);
-       XFS_STATS_INC(vn_reclaim);
-       XFS_STATS_DEC(vn_active);
+       xfs_inode_t             *ip = XFS_I(inode);
  
        /*
-        * This can happen because xfs_iget_core calls xfs_idestroy if we
+        * ip can be null when xfs_iget_core calls xfs_idestroy if we
         * find an inode with di_mode == 0 but without IGET_CREATE set.
         */
-       if (VNHEAD(vp))
-               bhv_vop_inactive(vp, NULL);
-       VN_LOCK(vp);
-       vp->v_flag &= ~VMODIFIED;
-       VN_UNLOCK(vp, 0);
-       if (VNHEAD(vp))
-               if (bhv_vop_reclaim(vp))
-                       panic("%s: cannot reclaim 0x%p\n", __FUNCTION__, vp);
-       ASSERT(VNHEAD(vp) == NULL);
+       if (ip) {
+               vn_trace_entry(ip, __FUNCTION__, (inst_t *)__return_address);
+               XFS_STATS_INC(vn_rele);
+               XFS_STATS_INC(vn_remove);
+               XFS_STATS_INC(vn_reclaim);
+               XFS_STATS_DEC(vn_active);
+               xfs_inactive(ip);
+               xfs_iflags_clear(ip, XFS_IMODIFIED);
+               if (xfs_reclaim(ip))
+                       panic("%s: cannot reclaim 0x%p\n", __FUNCTION__, inode);
+       }
  
- #ifdef XFS_VNODE_TRACE
-       ktrace_free(vp->v_trace);
- #endif
+       ASSERT(XFS_I(inode) == NULL);
  }
  
  /*
   */
  STATIC void
  xfs_syncd_queue_work(
-       struct bhv_vfs  *vfs,
+       struct xfs_mount *mp,
        void            *data,
-       void            (*syncer)(bhv_vfs_t *, void *))
+       void            (*syncer)(struct xfs_mount *, void *))
  {
        struct bhv_vfs_sync_work *work;
  
        INIT_LIST_HEAD(&work->w_list);
        work->w_syncer = syncer;
        work->w_data = data;
-       work->w_vfs = vfs;
-       spin_lock(&vfs->vfs_sync_lock);
-       list_add_tail(&work->w_list, &vfs->vfs_sync_list);
-       spin_unlock(&vfs->vfs_sync_lock);
-       wake_up_process(vfs->vfs_sync_task);
+       work->w_mount = mp;
+       spin_lock(&mp->m_sync_lock);
+       list_add_tail(&work->w_list, &mp->m_sync_list);
+       spin_unlock(&mp->m_sync_lock);
+       wake_up_process(mp->m_sync_task);
  }
  
  /*
   */
  STATIC void
  xfs_flush_inode_work(
-       bhv_vfs_t       *vfs,
-       void            *inode)
+       struct xfs_mount *mp,
+       void            *arg)
  {
-       filemap_flush(((struct inode *)inode)->i_mapping);
-       iput((struct inode *)inode);
+       struct inode    *inode = arg;
+       filemap_flush(inode->i_mapping);
+       iput(inode);
  }
  
  void
  xfs_flush_inode(
        xfs_inode_t     *ip)
  {
-       struct inode    *inode = vn_to_inode(XFS_ITOV(ip));
-       struct bhv_vfs  *vfs = XFS_MTOVFS(ip->i_mount);
+       struct inode    *inode = ip->i_vnode;
  
        igrab(inode);
-       xfs_syncd_queue_work(vfs, inode, xfs_flush_inode_work);
+       xfs_syncd_queue_work(ip->i_mount, inode, xfs_flush_inode_work);
        delay(msecs_to_jiffies(500));
  }
  
   */
  STATIC void
  xfs_flush_device_work(
-       bhv_vfs_t       *vfs,
-       void            *inode)
+       struct xfs_mount *mp,
+       void            *arg)
  {
-       sync_blockdev(vfs->vfs_super->s_bdev);
-       iput((struct inode *)inode);
+       struct inode    *inode = arg;
+       sync_blockdev(mp->m_super->s_bdev);
+       iput(inode);
  }
  
  void
@@@ -531,35 -527,33 +526,33 @@@ xfs_flush_device
        xfs_inode_t     *ip)
  {
        struct inode    *inode = vn_to_inode(XFS_ITOV(ip));
-       struct bhv_vfs  *vfs = XFS_MTOVFS(ip->i_mount);
  
        igrab(inode);
-       xfs_syncd_queue_work(vfs, inode, xfs_flush_device_work);
+       xfs_syncd_queue_work(ip->i_mount, inode, xfs_flush_device_work);
        delay(msecs_to_jiffies(500));
        xfs_log_force(ip->i_mount, (xfs_lsn_t)0, XFS_LOG_FORCE|XFS_LOG_SYNC);
  }
  
  STATIC void
vfs_sync_worker(
-       bhv_vfs_t       *vfsp,
xfs_sync_worker(
+       struct xfs_mount *mp,
        void            *unused)
  {
        int             error;
  
-       if (!(vfsp->vfs_flag & VFS_RDONLY))
-               error = bhv_vfs_sync(vfsp, SYNC_FSDATA | SYNC_BDFLUSH | \
-                                       SYNC_ATTR | SYNC_REFCACHE | SYNC_SUPER,
-                                       NULL);
-       vfsp->vfs_sync_seq++;
-       wake_up(&vfsp->vfs_wait_single_sync_task);
+       if (!(mp->m_flags & XFS_MOUNT_RDONLY))
+               error = xfs_sync(mp, SYNC_FSDATA | SYNC_BDFLUSH | SYNC_ATTR |
+                                    SYNC_REFCACHE | SYNC_SUPER);
+       mp->m_sync_seq++;
+       wake_up(&mp->m_wait_single_sync_task);
  }
  
  STATIC int
  xfssyncd(
        void                    *arg)
  {
+       struct xfs_mount        *mp = arg;
        long                    timeleft;
-       bhv_vfs_t               *vfsp = (bhv_vfs_t *) arg;
        bhv_vfs_sync_work_t     *work, *n;
        LIST_HEAD               (tmp);
  
                timeleft = schedule_timeout_interruptible(timeleft);
                /* swsusp */
                try_to_freeze();
-               if (kthread_should_stop() && list_empty(&vfsp->vfs_sync_list))
+               if (kthread_should_stop() && list_empty(&mp->m_sync_list))
                        break;
  
-               spin_lock(&vfsp->vfs_sync_lock);
+               spin_lock(&mp->m_sync_lock);
                /*
                 * We can get woken by laptop mode, to do a sync -
                 * that's the (only!) case where the list would be
                 * empty with time remaining.
                 */
-               if (!timeleft || list_empty(&vfsp->vfs_sync_list)) {
+               if (!timeleft || list_empty(&mp->m_sync_list)) {
                        if (!timeleft)
                                timeleft = xfs_syncd_centisecs *
                                                        msecs_to_jiffies(10);
-                       INIT_LIST_HEAD(&vfsp->vfs_sync_work.w_list);
-                       list_add_tail(&vfsp->vfs_sync_work.w_list,
-                                       &vfsp->vfs_sync_list);
+                       INIT_LIST_HEAD(&mp->m_sync_work.w_list);
+                       list_add_tail(&mp->m_sync_work.w_list,
+                                       &mp->m_sync_list);
                }
-               list_for_each_entry_safe(work, n, &vfsp->vfs_sync_list, w_list)
+               list_for_each_entry_safe(work, n, &mp->m_sync_list, w_list)
                        list_move(&work->w_list, &tmp);
-               spin_unlock(&vfsp->vfs_sync_lock);
+               spin_unlock(&mp->m_sync_lock);
  
                list_for_each_entry_safe(work, n, &tmp, w_list) {
-                       (*work->w_syncer)(vfsp, work->w_data);
+                       (*work->w_syncer)(mp, work->w_data);
                        list_del(&work->w_list);
-                       if (work == &vfsp->vfs_sync_work)
+                       if (work == &mp->m_sync_work)
                                continue;
                        kmem_free(work, sizeof(struct bhv_vfs_sync_work));
                }
        return 0;
  }
  
- STATIC int
- xfs_fs_start_syncd(
-       bhv_vfs_t               *vfsp)
- {
-       vfsp->vfs_sync_work.w_syncer = vfs_sync_worker;
-       vfsp->vfs_sync_work.w_vfs = vfsp;
-       vfsp->vfs_sync_task = kthread_run(xfssyncd, vfsp, "xfssyncd");
-       if (IS_ERR(vfsp->vfs_sync_task))
-               return -PTR_ERR(vfsp->vfs_sync_task);
-       return 0;
- }
- STATIC void
- xfs_fs_stop_syncd(
-       bhv_vfs_t               *vfsp)
- {
-       kthread_stop(vfsp->vfs_sync_task);
- }
  STATIC void
  xfs_fs_put_super(
        struct super_block      *sb)
  {
-       bhv_vfs_t               *vfsp = vfs_from_sb(sb);
+       struct xfs_mount        *mp = XFS_M(sb);
        int                     error;
  
-       xfs_fs_stop_syncd(vfsp);
-       bhv_vfs_sync(vfsp, SYNC_ATTR | SYNC_DELWRI, NULL);
-       error = bhv_vfs_unmount(vfsp, 0, NULL);
-       if (error) {
+       kthread_stop(mp->m_sync_task);
+       xfs_sync(mp, SYNC_ATTR | SYNC_DELWRI);
+       error = xfs_unmount(mp, 0, NULL);
+       if (error)
                printk("XFS: unmount got error=%d\n", error);
-               printk("%s: vfs=0x%p left dangling!\n", __FUNCTION__, vfsp);
-       } else {
-               vfs_deallocate(vfsp);
-       }
  }
  
  STATIC void
@@@ -644,7 -616,7 +615,7 @@@ xfs_fs_write_super
        struct super_block      *sb)
  {
        if (!(sb->s_flags & MS_RDONLY))
-               bhv_vfs_sync(vfs_from_sb(sb), SYNC_FSDATA, NULL);
+               xfs_sync(XFS_M(sb), SYNC_FSDATA);
        sb->s_dirt = 0;
  }
  
@@@ -653,11 -625,23 +624,23 @@@ xfs_fs_sync_super
        struct super_block      *sb,
        int                     wait)
  {
-       bhv_vfs_t               *vfsp = vfs_from_sb(sb);
+       struct xfs_mount        *mp = XFS_M(sb);
        int                     error;
        int                     flags;
  
-       if (unlikely(sb->s_frozen == SB_FREEZE_WRITE)) {
+       /*
+        * Treat a sync operation like a freeze.  This is to work
+        * around a race in sync_inodes() which works in two phases
+        * - an asynchronous flush, which can write out an inode
+        * without waiting for file size updates to complete, and a
+        * synchronous flush, which wont do anything because the
+        * async flush removed the inode's dirty flag.  Also
+        * sync_inodes() will not see any files that just have
+        * outstanding transactions to be flushed because we don't
+        * dirty the Linux inode until after the transaction I/O
+        * completes.
+        */
+       if (wait || unlikely(sb->s_frozen == SB_FREEZE_WRITE)) {
                /*
                 * First stage of freeze - no more writers will make progress
                 * now we are here, so we flush delwri and delalloc buffers
                 */
                flags = SYNC_DATA_QUIESCE;
        } else
-               flags = SYNC_FSDATA | (wait ? SYNC_WAIT : 0);
+               flags = SYNC_FSDATA;
  
-       error = bhv_vfs_sync(vfsp, flags, NULL);
+       error = xfs_sync(mp, flags);
        sb->s_dirt = 0;
  
        if (unlikely(laptop_mode)) {
-               int     prev_sync_seq = vfsp->vfs_sync_seq;
+               int     prev_sync_seq = mp->m_sync_seq;
  
                /*
                 * The disk must be active because we're syncing.
                 * We schedule xfssyncd now (now that the disk is
                 * active) instead of later (when it might not be).
                 */
-               wake_up_process(vfsp->vfs_sync_task);
+               wake_up_process(mp->m_sync_task);
                /*
                 * We have to wait for the sync iteration to complete.
                 * If we don't, the disk activity caused by the sync
                 * will come after the sync is completed, and that
                 * triggers another sync from laptop mode.
                 */
-               wait_event(vfsp->vfs_wait_single_sync_task,
-                               vfsp->vfs_sync_seq != prev_sync_seq);
+               wait_event(mp->m_wait_single_sync_task,
+                               mp->m_sync_seq != prev_sync_seq);
        }
  
        return -error;
@@@ -700,7 -684,7 +683,7 @@@ xfs_fs_statfs
        struct dentry           *dentry,
        struct kstatfs          *statp)
  {
-       return -bhv_vfs_statvfs(vfs_from_sb(dentry->d_sb), statp,
+       return -xfs_statvfs(XFS_M(dentry->d_sb), statp,
                                vn_from_inode(dentry->d_inode));
  }
  
@@@ -710,13 -694,13 +693,13 @@@ xfs_fs_remount
        int                     *flags,
        char                    *options)
  {
-       bhv_vfs_t               *vfsp = vfs_from_sb(sb);
+       struct xfs_mount        *mp = XFS_M(sb);
        struct xfs_mount_args   *args = xfs_args_allocate(sb, 0);
        int                     error;
  
-       error = bhv_vfs_parseargs(vfsp, options, args, 1);
+       error = xfs_parseargs(mp, options, args, 1);
        if (!error)
-               error = bhv_vfs_mntupdate(vfsp, flags, args);
+               error = xfs_mntupdate(mp, flags, args);
        kmem_free(args, sizeof(*args));
        return -error;
  }
@@@ -725,7 -709,7 +708,7 @@@ STATIC voi
  xfs_fs_lockfs(
        struct super_block      *sb)
  {
-       bhv_vfs_freeze(vfs_from_sb(sb));
+       xfs_freeze(XFS_M(sb));
  }
  
  STATIC int
@@@ -733,7 -717,7 +716,7 @@@ xfs_fs_show_options
        struct seq_file         *m,
        struct vfsmount         *mnt)
  {
-       return -bhv_vfs_showargs(vfs_from_sb(mnt->mnt_sb), m);
+       return -xfs_showargs(XFS_M(mnt->mnt_sb), m);
  }
  
  STATIC int
@@@ -741,7 -725,7 +724,7 @@@ xfs_fs_quotasync
        struct super_block      *sb,
        int                     type)
  {
-       return -bhv_vfs_quotactl(vfs_from_sb(sb), Q_XQUOTASYNC, 0, NULL);
+       return -XFS_QM_QUOTACTL(XFS_M(sb), Q_XQUOTASYNC, 0, NULL);
  }
  
  STATIC int
@@@ -749,7 -733,7 +732,7 @@@ xfs_fs_getxstate
        struct super_block      *sb,
        struct fs_quota_stat    *fqs)
  {
-       return -bhv_vfs_quotactl(vfs_from_sb(sb), Q_XGETQSTAT, 0, (caddr_t)fqs);
+       return -XFS_QM_QUOTACTL(XFS_M(sb), Q_XGETQSTAT, 0, (caddr_t)fqs);
  }
  
  STATIC int
@@@ -758,7 -742,7 +741,7 @@@ xfs_fs_setxstate
        unsigned int            flags,
        int                     op)
  {
-       return -bhv_vfs_quotactl(vfs_from_sb(sb), op, 0, (caddr_t)&flags);
+       return -XFS_QM_QUOTACTL(XFS_M(sb), op, 0, (caddr_t)&flags);
  }
  
  STATIC int
@@@ -768,7 -752,7 +751,7 @@@ xfs_fs_getxquota
        qid_t                   id,
        struct fs_disk_quota    *fdq)
  {
-       return -bhv_vfs_quotactl(vfs_from_sb(sb),
+       return -XFS_QM_QUOTACTL(XFS_M(sb),
                                 (type == USRQUOTA) ? Q_XGETQUOTA :
                                  ((type == GRPQUOTA) ? Q_XGETGQUOTA :
                                   Q_XGETPQUOTA), id, (caddr_t)fdq);
@@@ -781,7 -765,7 +764,7 @@@ xfs_fs_setxquota
        qid_t                   id,
        struct fs_disk_quota    *fdq)
  {
-       return -bhv_vfs_quotactl(vfs_from_sb(sb),
+       return -XFS_QM_QUOTACTL(XFS_M(sb),
                                 (type == USRQUOTA) ? Q_XSETQLIM :
                                  ((type == GRPQUOTA) ? Q_XSETGQLIM :
                                   Q_XSETPQLIM), id, (caddr_t)fdq);
@@@ -793,32 -777,38 +776,38 @@@ xfs_fs_fill_super
        void                    *data,
        int                     silent)
  {
-       struct bhv_vnode        *rootvp;
-       struct bhv_vfs          *vfsp = vfs_allocate(sb);
+       struct inode            *rootvp;
+       struct xfs_mount        *mp = NULL;
        struct xfs_mount_args   *args = xfs_args_allocate(sb, silent);
        struct kstatfs          statvfs;
        int                     error;
  
-       bhv_insert_all_vfsops(vfsp);
+       mp = xfs_mount_init();
  
-       error = bhv_vfs_parseargs(vfsp, (char *)data, args, 0);
-       if (error) {
-               bhv_remove_all_vfsops(vfsp, 1);
+       INIT_LIST_HEAD(&mp->m_sync_list);
+       spin_lock_init(&mp->m_sync_lock);
+       init_waitqueue_head(&mp->m_wait_single_sync_task);
+       mp->m_super = sb;
+       sb->s_fs_info = mp;
+       if (sb->s_flags & MS_RDONLY)
+               mp->m_flags |= XFS_MOUNT_RDONLY;
+       error = xfs_parseargs(mp, (char *)data, args, 0);
+       if (error)
                goto fail_vfsop;
-       }
  
        sb_min_blocksize(sb, BBSIZE);
        sb->s_export_op = &xfs_export_operations;
        sb->s_qcop = &xfs_quotactl_operations;
        sb->s_op = &xfs_super_operations;
  
-       error = bhv_vfs_mount(vfsp, args, NULL);
-       if (error) {
-               bhv_remove_all_vfsops(vfsp, 1);
+       error = xfs_mount(mp, args, NULL);
+       if (error)
                goto fail_vfsop;
-       }
  
-       error = bhv_vfs_statvfs(vfsp, &statvfs, NULL);
+       error = xfs_statvfs(mp, &statvfs, NULL);
        if (error)
                goto fail_unmount;
  
        sb->s_time_gran = 1;
        set_posix_acl_flag(sb);
  
-       error = bhv_vfs_root(vfsp, &rootvp);
+       error = xfs_root(mp, &rootvp);
        if (error)
                goto fail_unmount;
  
                error = EINVAL;
                goto fail_vnrele;
        }
-       if ((error = xfs_fs_start_syncd(vfsp)))
+       mp->m_sync_work.w_syncer = xfs_sync_worker;
+       mp->m_sync_work.w_mount = mp;
+       mp->m_sync_task = kthread_run(xfssyncd, mp, "xfssyncd");
+       if (IS_ERR(mp->m_sync_task)) {
+               error = -PTR_ERR(mp->m_sync_task);
                goto fail_vnrele;
-       vn_trace_exit(rootvp, __FUNCTION__, (inst_t *)__return_address);
+       }
+       vn_trace_exit(XFS_I(sb->s_root->d_inode), __FUNCTION__,
+                       (inst_t *)__return_address);
  
        kmem_free(args, sizeof(*args));
        return 0;
@@@ -859,10 -857,9 +856,9 @@@ fail_vnrele
        }
  
  fail_unmount:
-       bhv_vfs_unmount(vfsp, 0, NULL);
+       xfs_unmount(mp, 0, NULL);
  
  fail_vfsop:
-       vfs_deallocate(vfsp);
        kmem_free(args, sizeof(*args));
        return -error;
  }
@@@ -914,15 -911,11 +910,11 @@@ STATIC int __ini
  init_xfs_fs( void )
  {
        int                     error;
-       struct sysinfo          si;
        static char             message[] __initdata = KERN_INFO \
                XFS_VERSION_STRING " with " XFS_BUILD_OPTIONS " enabled\n";
  
        printk(message);
  
-       si_meminfo(&si);
-       xfs_physmem = si.totalram;
        ktrace_init(64);
  
        error = xfs_init_zones();