[XFS] Use the incore inode size in xfs_file_readdir()
[safe/jmp/linux-2.6] / fs / xfs / xfs_inode.h
index 3b544db..f0e4d79 100644 (file)
@@ -18,6 +18,9 @@
 #ifndef        __XFS_INODE_H__
 #define        __XFS_INODE_H__
 
+struct xfs_dinode;
+struct xfs_inode;
+
 /*
  * Fork identifiers.
  */
@@ -44,7 +47,7 @@
  * it is possible that a third level of indirection may be required.
  */
 typedef struct xfs_ext_irec {
-       xfs_bmbt_rec_t  *er_extbuf;     /* block of extent records */
+       xfs_bmbt_rec_host_t *er_extbuf; /* block of extent records */
        xfs_extnum_t    er_extoff;      /* extent offset in file */
        xfs_extnum_t    er_extcount;    /* number of extents in page/block */
 } xfs_ext_irec_t;
@@ -59,18 +62,18 @@ typedef struct xfs_ext_irec {
 typedef struct xfs_ifork {
        int                     if_bytes;       /* bytes in if_u1 */
        int                     if_real_bytes;  /* bytes allocated in if_u1 */
-       xfs_bmbt_block_t        *if_broot;      /* file's incore btree root */
+       struct xfs_btree_block  *if_broot;      /* file's incore btree root */
        short                   if_broot_bytes; /* bytes allocated for root */
        unsigned char           if_flags;       /* per-fork flags */
        unsigned char           if_ext_max;     /* max # of extent records */
        xfs_extnum_t            if_lastex;      /* last if_extents used */
        union {
-               xfs_bmbt_rec_t  *if_extents;    /* linear map file exts */
+               xfs_bmbt_rec_host_t *if_extents;/* linear map file exts */
                xfs_ext_irec_t  *if_ext_irec;   /* irec map file exts */
                char            *if_data;       /* inline file data */
        } if_u1;
        union {
-               xfs_bmbt_rec_ if_inline_ext[XFS_INLINE_EXTS];
+               xfs_bmbt_rec_host_t if_inline_ext[XFS_INLINE_EXTS];
                                                /* very small file extents */
                char            if_inline_data[XFS_INLINE_DATA];
                                                /* very small file data */
@@ -80,11 +83,80 @@ typedef struct xfs_ifork {
 } xfs_ifork_t;
 
 /*
+ * Inode location information.  Stored in the inode and passed to
+ * xfs_imap_to_bp() to get a buffer and dinode for a given inode.
+ */
+struct xfs_imap {
+       xfs_daddr_t     im_blkno;       /* starting BB of inode chunk */
+       ushort          im_len;         /* length in BBs of inode chunk */
+       ushort          im_boffset;     /* inode offset in block in bytes */
+};
+
+/*
+ * This is the xfs in-core inode structure.
+ * Most of the on-disk inode is embedded in the i_d field.
+ *
+ * The extent pointers/inline file space, however, are managed
+ * separately.  The memory for this information is pointed to by
+ * the if_u1 unions depending on the type of the data.
+ * This is used to linearize the array of extents for fast in-core
+ * access.  This is used until the file's number of extents
+ * surpasses XFS_MAX_INCORE_EXTENTS, at which point all extent pointers
+ * are accessed through the buffer cache.
+ *
+ * Other state kept in the in-core inode is used for identification,
+ * locking, transactional updating, etc of the inode.
+ *
+ * Generally, we do not want to hold the i_rlock while holding the
+ * i_ilock. Hierarchy is i_iolock followed by i_rlock.
+ *
+ * xfs_iptr_t contains all the inode fields upto and including the
+ * i_mnext and i_mprev fields, it is used as a marker in the inode
+ * chain off the mount structure by xfs_sync calls.
+ */
+
+typedef struct xfs_ictimestamp {
+       __int32_t       t_sec;          /* timestamp seconds */
+       __int32_t       t_nsec;         /* timestamp nanoseconds */
+} xfs_ictimestamp_t;
+
+/*
+ * NOTE:  This structure must be kept identical to struct xfs_dinode
+ *       in xfs_dinode.h except for the endianess annotations.
+ */
+typedef struct xfs_icdinode {
+       __uint16_t      di_magic;       /* inode magic # = XFS_DINODE_MAGIC */
+       __uint16_t      di_mode;        /* mode and type of file */
+       __int8_t        di_version;     /* inode version */
+       __int8_t        di_format;      /* format of di_c data */
+       __uint16_t      di_onlink;      /* old number of links to file */
+       __uint32_t      di_uid;         /* owner's user id */
+       __uint32_t      di_gid;         /* owner's group id */
+       __uint32_t      di_nlink;       /* number of links to file */
+       __uint16_t      di_projid;      /* owner's project id */
+       __uint8_t       di_pad[8];      /* unused, zeroed space */
+       __uint16_t      di_flushiter;   /* incremented on flush */
+       xfs_ictimestamp_t di_atime;     /* time last accessed */
+       xfs_ictimestamp_t di_mtime;     /* time last modified */
+       xfs_ictimestamp_t di_ctime;     /* time created/inode modified */
+       xfs_fsize_t     di_size;        /* number of bytes in file */
+       xfs_drfsbno_t   di_nblocks;     /* # of direct & btree blocks used */
+       xfs_extlen_t    di_extsize;     /* basic/minimum extent size for file */
+       xfs_extnum_t    di_nextents;    /* number of extents in data fork */
+       xfs_aextnum_t   di_anextents;   /* number of extents in attribute fork*/
+       __uint8_t       di_forkoff;     /* attr fork offs, <<3 for 64b align */
+       __int8_t        di_aformat;     /* format of attr fork's data */
+       __uint32_t      di_dmevmask;    /* DMIG event mask */
+       __uint16_t      di_dmstate;     /* DMIG state info */
+       __uint16_t      di_flags;       /* random flags, XFS_DIFLAG_... */
+       __uint32_t      di_gen;         /* generation number */
+} xfs_icdinode_t;
+
+/*
  * Flags for xfs_ichgtime().
  */
 #define        XFS_ICHGTIME_MOD        0x1     /* data fork modification timestamp */
-#define        XFS_ICHGTIME_ACC        0x2     /* data fork access timestamp */
-#define        XFS_ICHGTIME_CHG        0x4     /* inode field change timestamp */
+#define        XFS_ICHGTIME_CHG        0x2     /* inode field change timestamp */
 
 /*
  * Per-fork incore inode flags.
@@ -95,21 +167,55 @@ typedef struct xfs_ifork {
 #define        XFS_IFEXTIREC   0x08    /* Indirection array of extent blocks */
 
 /*
- * Flags for xfs_itobp(), xfs_imap() and xfs_dilocate().
+ * Fork handling.
  */
-#define XFS_IMAP_LOOKUP                0x1
-#define XFS_IMAP_BULKSTAT      0x2
+
+#define XFS_IFORK_Q(ip)                        ((ip)->i_d.di_forkoff != 0)
+#define XFS_IFORK_BOFF(ip)             ((int)((ip)->i_d.di_forkoff << 3))
+
+#define XFS_IFORK_PTR(ip,w)            \
+       ((w) == XFS_DATA_FORK ? \
+               &(ip)->i_df : \
+               (ip)->i_afp)
+#define XFS_IFORK_DSIZE(ip) \
+       (XFS_IFORK_Q(ip) ? \
+               XFS_IFORK_BOFF(ip) : \
+               XFS_LITINO((ip)->i_mount))
+#define XFS_IFORK_ASIZE(ip) \
+       (XFS_IFORK_Q(ip) ? \
+               XFS_LITINO((ip)->i_mount) - XFS_IFORK_BOFF(ip) : \
+               0)
+#define XFS_IFORK_SIZE(ip,w) \
+       ((w) == XFS_DATA_FORK ? \
+               XFS_IFORK_DSIZE(ip) : \
+               XFS_IFORK_ASIZE(ip))
+#define XFS_IFORK_FORMAT(ip,w) \
+       ((w) == XFS_DATA_FORK ? \
+               (ip)->i_d.di_format : \
+               (ip)->i_d.di_aformat)
+#define XFS_IFORK_FMT_SET(ip,w,n) \
+       ((w) == XFS_DATA_FORK ? \
+               ((ip)->i_d.di_format = (n)) : \
+               ((ip)->i_d.di_aformat = (n)))
+#define XFS_IFORK_NEXTENTS(ip,w) \
+       ((w) == XFS_DATA_FORK ? \
+               (ip)->i_d.di_nextents : \
+               (ip)->i_d.di_anextents)
+#define XFS_IFORK_NEXT_SET(ip,w,n) \
+       ((w) == XFS_DATA_FORK ? \
+               ((ip)->i_d.di_nextents = (n)) : \
+               ((ip)->i_d.di_anextents = (n)))
+
+
 
 #ifdef __KERNEL__
+
 struct bhv_desc;
 struct cred;
 struct ktrace;
-struct vnode;
 struct xfs_buf;
 struct xfs_bmap_free;
 struct xfs_bmbt_irec;
-struct xfs_bmbt_block;
-struct xfs_inode;
 struct xfs_inode_log_item;
 struct xfs_mount;
 struct xfs_trans;
@@ -117,7 +223,6 @@ struct xfs_dquot;
 
 #if defined(XFS_ILOCK_TRACE)
 #define XFS_ILOCK_KTRACE_SIZE  32
-extern ktrace_t *xfs_ilock_trace_buf;
 extern void xfs_ilock_trace(struct xfs_inode *, int, unsigned int, inst_t *);
 #else
 #define        xfs_ilock_trace(i,n,f,ra)
@@ -129,131 +234,15 @@ typedef struct dm_attrs_s {
        __uint16_t      da_pad;         /* DMIG extra padding */
 } dm_attrs_t;
 
-typedef struct xfs_iocore {
-       void                    *io_obj;        /* pointer to container
-                                                * inode or dcxvn structure */
-       struct xfs_mount        *io_mount;      /* fs mount struct ptr */
-#ifdef DEBUG
-       mrlock_t                *io_lock;       /* inode IO lock */
-       mrlock_t                *io_iolock;     /* inode IO lock */
-#endif
-
-       /* I/O state */
-       xfs_fsize_t             io_new_size;    /* sz when write completes */
-
-       /* Miscellaneous state. */
-       unsigned int            io_flags;       /* IO related flags */
-
-       /* DMAPI state */
-       dm_attrs_t              io_dmattrs;
-
-} xfs_iocore_t;
-
-#define        io_dmevmask     io_dmattrs.da_dmevmask
-#define        io_dmstate      io_dmattrs.da_dmstate
-
-#define XFS_IO_INODE(io)       ((xfs_inode_t *) ((io)->io_obj))
-#define XFS_IO_DCXVN(io)       ((dcxvn_t *) ((io)->io_obj))
-
-/*
- * Flags in the flags field
- */
-
-#define XFS_IOCORE_RT          0x1
-
-/*
- * xfs_iocore prototypes
- */
-
-extern void xfs_iocore_inode_init(struct xfs_inode *);
-extern void xfs_iocore_inode_reinit(struct xfs_inode *);
-
-
-/*
- * This is the type used in the xfs inode hash table.
- * An array of these is allocated for each mounted
- * file system to hash the inodes for that file system.
- */
-typedef struct xfs_ihash {
-       struct xfs_inode        *ih_next;
-       rwlock_t                ih_lock;
-       uint                    ih_version;
-} xfs_ihash_t;
-
-#define XFS_IHASH(mp,ino) ((mp)->m_ihash + (((uint)(ino)) % (mp)->m_ihsize))
-
-/*
- * This is the xfs inode cluster hash.  This hash is used by xfs_iflush to
- * find inodes that share a cluster and can be flushed to disk at the same
- * time.
- */
-typedef struct xfs_chashlist {
-       struct xfs_chashlist    *chl_next;
-       struct xfs_chashlist    *chl_prev;
-       struct xfs_inode        *chl_ip;
-       xfs_daddr_t             chl_blkno;      /* starting block number of
-                                                * the cluster */
-       struct xfs_buf          *chl_buf;       /* the inode buffer */
-} xfs_chashlist_t;
-
-typedef struct xfs_chash {
-       xfs_chashlist_t         *ch_list;
-       lock_t                  ch_lock;
-} xfs_chash_t;
-
-#define XFS_CHASH(mp,blk) ((mp)->m_chash + (((uint)blk) % (mp)->m_chsize))
-
-
-/*
- * This is the xfs in-core inode structure.
- * Most of the on-disk inode is embedded in the i_d field.
- *
- * The extent pointers/inline file space, however, are managed
- * separately.  The memory for this information is pointed to by
- * the if_u1 unions depending on the type of the data.
- * This is used to linearize the array of extents for fast in-core
- * access.  This is used until the file's number of extents
- * surpasses XFS_MAX_INCORE_EXTENTS, at which point all extent pointers
- * are accessed through the buffer cache.
- *
- * Other state kept in the in-core inode is used for identification,
- * locking, transactional updating, etc of the inode.
- *
- * Generally, we do not want to hold the i_rlock while holding the
- * i_ilock. Hierarchy is i_iolock followed by i_rlock.
- *
- * xfs_iptr_t contains all the inode fields upto and including the
- * i_mnext and i_mprev fields, it is used as a marker in the inode
- * chain off the mount structure by xfs_sync calls.
- */
-
-typedef struct {
-       struct xfs_ihash        *ip_hash;       /* pointer to hash header */
-       struct xfs_inode        *ip_next;       /* inode hash link forw */
-       struct xfs_inode        *ip_mnext;      /* next inode in mount list */
-       struct xfs_inode        *ip_mprev;      /* ptr to prev inode */
-       struct xfs_inode        **ip_prevp;     /* ptr to prev i_next */
-       struct xfs_mount        *ip_mount;      /* fs mount struct ptr */
-} xfs_iptr_t;
-
 typedef struct xfs_inode {
        /* Inode linking and identification information. */
-       struct xfs_ihash        *i_hash;        /* pointer to hash header */
-       struct xfs_inode        *i_next;        /* inode hash link forw */
-       struct xfs_inode        *i_mnext;       /* next inode in mount list */
-       struct xfs_inode        *i_mprev;       /* ptr to prev inode */
-       struct xfs_inode        **i_prevp;      /* ptr to prev i_next */
        struct xfs_mount        *i_mount;       /* fs mount struct ptr */
-       struct list_head        i_reclaim;      /* reclaim list */
-       struct bhv_desc         i_bhv_desc;     /* inode behavior descriptor*/
        struct xfs_dquot        *i_udquot;      /* user dquot */
        struct xfs_dquot        *i_gdquot;      /* group dquot */
 
        /* Inode location stuff */
        xfs_ino_t               i_ino;          /* inode number (agno/agino)*/
-       xfs_daddr_t             i_blkno;        /* blkno of inode buffer */
-       ushort                  i_len;          /* len of inode buffer */
-       ushort                  i_boffset;      /* off of inode in buffer */
+       struct xfs_imap         i_imap;         /* location for xfs_imap() */
 
        /* Extent information. */
        xfs_ifork_t             *i_afp;         /* attribute fork pointer */
@@ -264,33 +253,33 @@ typedef struct xfs_inode {
        struct xfs_inode_log_item *i_itemp;     /* logging information */
        mrlock_t                i_lock;         /* inode lock */
        mrlock_t                i_iolock;       /* inode IO lock */
-       sema_t                  i_flock;        /* inode flush lock */
+       struct completion       i_flush;        /* inode flush completion q */
        atomic_t                i_pincount;     /* inode pin count */
        wait_queue_head_t       i_ipin_wait;    /* inode pinning wait queue */
-#ifdef HAVE_REFCACHE
-       struct xfs_inode        **i_refcache;   /* ptr to entry in ref cache */
-       struct xfs_inode        *i_release;     /* inode to unref */
-#endif
-       /* I/O state */
-       xfs_iocore_t            i_iocore;       /* I/O core */
-
+       spinlock_t              i_flags_lock;   /* inode i_flags lock */
        /* Miscellaneous state. */
        unsigned short          i_flags;        /* see defined flags below */
        unsigned char           i_update_core;  /* timestamps/size is dirty */
        unsigned char           i_update_size;  /* di_size field is dirty */
-       unsigned int            i_gen;          /* generation count */
        unsigned int            i_delayed_blks; /* count of delay alloc blks */
 
-       xfs_dinode_core_t       i_d;            /* most of ondisk inode */
-       xfs_chashlist_t         *i_chash;       /* cluster hash list header */
-       struct xfs_inode        *i_cnext;       /* cluster hash link forward */
-       struct xfs_inode        *i_cprev;       /* cluster hash link backward */
+       xfs_icdinode_t          i_d;            /* most of ondisk inode */
+
+       xfs_fsize_t             i_size;         /* in-memory size */
+       xfs_fsize_t             i_new_size;     /* size when write completes */
+       atomic_t                i_iocount;      /* outstanding I/O count */
+
+       /* VFS inode */
+       struct inode            i_vnode;        /* embedded VFS inode */
 
        /* Trace buffers per inode. */
+#ifdef XFS_INODE_TRACE
+       struct ktrace           *i_trace;       /* general inode trace */
+#endif
 #ifdef XFS_BMAP_TRACE
        struct ktrace           *i_xtrace;      /* inode extent list trace */
 #endif
-#ifdef XFS_BMBT_TRACE
+#ifdef XFS_BTREE_TRACE
        struct ktrace           *i_btrace;      /* inode bmap btree trace */
 #endif
 #ifdef XFS_RW_TRACE
@@ -304,59 +293,168 @@ typedef struct xfs_inode {
 #endif
 } xfs_inode_t;
 
-#endif /* __KERNEL__ */
+#define XFS_ISIZE(ip)  (((ip)->i_d.di_mode & S_IFMT) == S_IFREG) ? \
+                               (ip)->i_size : (ip)->i_d.di_size;
 
+/* Convert from vfs inode to xfs inode */
+static inline struct xfs_inode *XFS_I(struct inode *inode)
+{
+       return container_of(inode, struct xfs_inode, i_vnode);
+}
+
+/* convert from xfs inode to vfs inode */
+static inline struct inode *VFS_I(struct xfs_inode *ip)
+{
+       return &ip->i_vnode;
+}
 
 /*
- * Fork handling.
+ * Get rid of a partially initialized inode.
+ *
+ * We have to go through destroy_inode to make sure allocations
+ * from init_inode_always like the security data are undone.
+ *
+ * We mark the inode bad so that it takes the short cut in
+ * the reclaim path instead of going through the flush path
+ * which doesn't make sense for an inode that has never seen the
+ * light of day.
  */
-#define        XFS_IFORK_PTR(ip,w)             \
-       ((w) == XFS_DATA_FORK ? &(ip)->i_df : (ip)->i_afp)
-#define        XFS_IFORK_Q(ip)                 XFS_CFORK_Q(&(ip)->i_d)
-#define        XFS_IFORK_DSIZE(ip)             XFS_CFORK_DSIZE(&ip->i_d, ip->i_mount)
-#define        XFS_IFORK_ASIZE(ip)             XFS_CFORK_ASIZE(&ip->i_d, ip->i_mount)
-#define        XFS_IFORK_SIZE(ip,w)            XFS_CFORK_SIZE(&ip->i_d, ip->i_mount, w)
-#define        XFS_IFORK_FORMAT(ip,w)          XFS_CFORK_FORMAT(&ip->i_d, w)
-#define        XFS_IFORK_FMT_SET(ip,w,n)       XFS_CFORK_FMT_SET(&ip->i_d, w, n)
-#define        XFS_IFORK_NEXTENTS(ip,w)        XFS_CFORK_NEXTENTS(&ip->i_d, w)
-#define        XFS_IFORK_NEXT_SET(ip,w,n)      XFS_CFORK_NEXT_SET(&ip->i_d, w, n)
+static inline void xfs_destroy_inode(struct xfs_inode *ip)
+{
+       make_bad_inode(VFS_I(ip));
+       return destroy_inode(VFS_I(ip));
+}
 
+/*
+ * i_flags helper functions
+ */
+static inline void
+__xfs_iflags_set(xfs_inode_t *ip, unsigned short flags)
+{
+       ip->i_flags |= flags;
+}
+
+static inline void
+xfs_iflags_set(xfs_inode_t *ip, unsigned short flags)
+{
+       spin_lock(&ip->i_flags_lock);
+       __xfs_iflags_set(ip, flags);
+       spin_unlock(&ip->i_flags_lock);
+}
+
+static inline void
+xfs_iflags_clear(xfs_inode_t *ip, unsigned short flags)
+{
+       spin_lock(&ip->i_flags_lock);
+       ip->i_flags &= ~flags;
+       spin_unlock(&ip->i_flags_lock);
+}
+
+static inline int
+__xfs_iflags_test(xfs_inode_t *ip, unsigned short flags)
+{
+       return (ip->i_flags & flags);
+}
+
+static inline int
+xfs_iflags_test(xfs_inode_t *ip, unsigned short flags)
+{
+       int ret;
+       spin_lock(&ip->i_flags_lock);
+       ret = __xfs_iflags_test(ip, flags);
+       spin_unlock(&ip->i_flags_lock);
+       return ret;
+}
+
+static inline int
+xfs_iflags_test_and_clear(xfs_inode_t *ip, unsigned short flags)
+{
+       int ret;
+
+       spin_lock(&ip->i_flags_lock);
+       ret = ip->i_flags & flags;
+       if (ret)
+               ip->i_flags &= ~flags;
+       spin_unlock(&ip->i_flags_lock);
+       return ret;
+}
 
-#ifdef __KERNEL__
+/*
+ * Manage the i_flush queue embedded in the inode.  This completion
+ * queue synchronizes processes attempting to flush the in-core
+ * inode back to disk.
+ */
+static inline void xfs_iflock(xfs_inode_t *ip)
+{
+       wait_for_completion(&ip->i_flush);
+}
+
+static inline int xfs_iflock_nowait(xfs_inode_t *ip)
+{
+       return try_wait_for_completion(&ip->i_flush);
+}
+
+static inline void xfs_ifunlock(xfs_inode_t *ip)
+{
+       complete(&ip->i_flush);
+}
 
 /*
  * In-core inode flags.
  */
-#define XFS_IGRIO      0x0001  /* inode used for guaranteed rate i/o */
-#define XFS_IUIOSZ     0x0002  /* inode i/o sizes have been explicitly set */
-#define XFS_IQUIESCE    0x0004  /* we have started quiescing for this inode */
-#define XFS_IRECLAIM    0x0008  /* we have started reclaiming this inode    */
-#define XFS_ISTALE     0x0010  /* inode has been staled */
-#define XFS_IRECLAIMABLE 0x0020 /* inode can be reclaimed */
-#define XFS_INEW       0x0040
+#define XFS_IRECLAIM    0x0001  /* we have started reclaiming this inode    */
+#define XFS_ISTALE     0x0002  /* inode has been staled */
+#define XFS_IRECLAIMABLE 0x0004 /* inode can be reclaimed */
+#define XFS_INEW       0x0008  /* inode has just been allocated */
+#define XFS_IFILESTREAM        0x0010  /* inode is in a filestream directory */
+#define XFS_ITRUNCATED 0x0020  /* truncated down so flush-on-close */
 
 /*
  * Flags for inode locking.
+ * Bit ranges: 1<<1  - 1<<16-1 -- iolock/ilock modes (bitfield)
+ *             1<<16 - 1<<32-1 -- lockdep annotation (integers)
  */
-#define        XFS_IOLOCK_EXCL         0x001
-#define        XFS_IOLOCK_SHARED       0x002
-#define        XFS_ILOCK_EXCL          0x004
-#define        XFS_ILOCK_SHARED        0x008
-#define        XFS_IUNLOCK_NONOTIFY    0x010
-/*     XFS_IOLOCK_NESTED       0x020 */
-#define XFS_EXTENT_TOKEN_RD    0x040
-#define XFS_SIZE_TOKEN_RD      0x080
-#define XFS_EXTSIZE_RD         (XFS_EXTENT_TOKEN_RD|XFS_SIZE_TOKEN_RD)
-#define XFS_WILLLEND           0x100   /* Always acquire tokens for lending */
-#define XFS_EXTENT_TOKEN_WR    (XFS_EXTENT_TOKEN_RD | XFS_WILLLEND)
-#define XFS_SIZE_TOKEN_WR       (XFS_SIZE_TOKEN_RD | XFS_WILLLEND)
-#define XFS_EXTSIZE_WR         (XFS_EXTSIZE_RD | XFS_WILLLEND)
-/*     XFS_SIZE_TOKEN_WANT     0x200 */
-
-#define XFS_LOCK_MASK  \
-       (XFS_IOLOCK_EXCL | XFS_IOLOCK_SHARED | XFS_ILOCK_EXCL | \
-        XFS_ILOCK_SHARED | XFS_EXTENT_TOKEN_RD | XFS_SIZE_TOKEN_RD | \
-        XFS_WILLLEND)
+#define        XFS_IOLOCK_EXCL         (1<<0)
+#define        XFS_IOLOCK_SHARED       (1<<1)
+#define        XFS_ILOCK_EXCL          (1<<2)
+#define        XFS_ILOCK_SHARED        (1<<3)
+#define        XFS_IUNLOCK_NONOTIFY    (1<<4)
+
+#define XFS_LOCK_MASK          (XFS_IOLOCK_EXCL | XFS_IOLOCK_SHARED \
+                               | XFS_ILOCK_EXCL | XFS_ILOCK_SHARED)
+
+/*
+ * Flags for lockdep annotations.
+ *
+ * XFS_I[O]LOCK_PARENT - for operations that require locking two inodes
+ * (ie directory operations that require locking a directory inode and
+ * an entry inode).  The first inode gets locked with this flag so it
+ * gets a lockdep subclass of 1 and the second lock will have a lockdep
+ * subclass of 0.
+ *
+ * XFS_LOCK_INUMORDER - for locking several inodes at the some time
+ * with xfs_lock_inodes().  This flag is used as the starting subclass
+ * and each subsequent lock acquired will increment the subclass by one.
+ * So the first lock acquired will have a lockdep subclass of 2, the
+ * second lock will have a lockdep subclass of 3, and so on. It is
+ * the responsibility of the class builder to shift this to the correct
+ * portion of the lock_mode lockdep mask.
+ */
+#define XFS_LOCK_PARENT                1
+#define XFS_LOCK_INUMORDER     2
+
+#define XFS_IOLOCK_SHIFT       16
+#define        XFS_IOLOCK_PARENT       (XFS_LOCK_PARENT << XFS_IOLOCK_SHIFT)
+
+#define XFS_ILOCK_SHIFT                24
+#define        XFS_ILOCK_PARENT        (XFS_LOCK_PARENT << XFS_ILOCK_SHIFT)
+
+#define XFS_IOLOCK_DEP_MASK    0x00ff0000
+#define XFS_ILOCK_DEP_MASK     0xff000000
+#define XFS_LOCK_DEP_MASK      (XFS_IOLOCK_DEP_MASK | XFS_ILOCK_DEP_MASK)
+
+#define XFS_IOLOCK_DEP(flags)  (((flags) & XFS_IOLOCK_DEP_MASK) >> XFS_IOLOCK_SHIFT)
+#define XFS_ILOCK_DEP(flags)   (((flags) & XFS_ILOCK_DEP_MASK) >> XFS_ILOCK_SHIFT)
 
 /*
  * Flags for xfs_iflush()
@@ -366,6 +464,7 @@ typedef struct xfs_inode {
 #define        XFS_IFLUSH_SYNC                 3
 #define        XFS_IFLUSH_ASYNC                4
 #define        XFS_IFLUSH_DELWRI               5
+#define        XFS_IFLUSH_ASYNC_NOBLOCK        6
 
 /*
  * Flags for xfs_itruncate_start().
@@ -373,34 +472,20 @@ typedef struct xfs_inode {
 #define        XFS_ITRUNC_DEFINITE     0x1
 #define        XFS_ITRUNC_MAYBE        0x2
 
-#define        XFS_ITOV(ip)            BHV_TO_VNODE(XFS_ITOBHV(ip))
-#define        XFS_ITOV_NULL(ip)       BHV_TO_VNODE_NULL(XFS_ITOBHV(ip))
-#define        XFS_ITOBHV(ip)          ((struct bhv_desc *)(&((ip)->i_bhv_desc)))
-#define        XFS_BHVTOI(bhvp)        ((xfs_inode_t *)((char *)(bhvp) - \
-                               (char *)&(((xfs_inode_t *)0)->i_bhv_desc)))
-#define BHV_IS_XFS(bdp)                (BHV_OPS(bdp) == &xfs_vnodeops)
-
 /*
  * For multiple groups support: if S_ISGID bit is set in the parent
  * directory, group of new file is set to that of the parent, and
  * new subdirectory gets S_ISGID bit from parent.
  */
-#define XFS_INHERIT_GID(pip, vfsp)     \
-       (((vfsp)->vfs_flag & VFS_GRPID) || ((pip)->i_d.di_mode & S_ISGID))
+#define XFS_INHERIT_GID(pip)   \
+       (((pip)->i_mount->m_flags & XFS_MOUNT_GRPID) || \
+        ((pip)->i_d.di_mode & S_ISGID))
 
 /*
  * xfs_iget.c prototypes.
  */
-
-#define IGET_CREATE    1
-
-void           xfs_ihash_init(struct xfs_mount *);
-void           xfs_ihash_free(struct xfs_mount *);
-void           xfs_chash_init(struct xfs_mount *);
-void           xfs_chash_free(struct xfs_mount *);
 xfs_inode_t    *xfs_inode_incore(struct xfs_mount *, xfs_ino_t,
                                  struct xfs_trans *);
-void            xfs_inode_lock_init(xfs_inode_t *, struct vnode *);
 int            xfs_iget(struct xfs_mount *, struct xfs_trans *, xfs_ino_t,
                         uint, uint, xfs_inode_t **, xfs_daddr_t);
 void           xfs_iput(xfs_inode_t *, uint);
@@ -409,63 +494,111 @@ void             xfs_ilock(xfs_inode_t *, uint);
 int            xfs_ilock_nowait(xfs_inode_t *, uint);
 void           xfs_iunlock(xfs_inode_t *, uint);
 void           xfs_ilock_demote(xfs_inode_t *, uint);
-void           xfs_iflock(xfs_inode_t *);
-int            xfs_iflock_nowait(xfs_inode_t *);
+int            xfs_isilocked(xfs_inode_t *, uint);
 uint           xfs_ilock_map_shared(xfs_inode_t *);
 void           xfs_iunlock_map_shared(xfs_inode_t *, uint);
-void           xfs_ifunlock(xfs_inode_t *);
 void           xfs_ireclaim(xfs_inode_t *);
-int            xfs_finish_reclaim(xfs_inode_t *, int, int);
-int            xfs_finish_reclaim_all(struct xfs_mount *, int);
 
 /*
  * xfs_inode.c prototypes.
  */
-int            xfs_itobp(struct xfs_mount *, struct xfs_trans *,
-                         xfs_inode_t *, xfs_dinode_t **, struct xfs_buf **,
-                         xfs_daddr_t, uint);
-int            xfs_iread(struct xfs_mount *, struct xfs_trans *, xfs_ino_t,
-                         xfs_inode_t **, xfs_daddr_t);
-int            xfs_iread_extents(struct xfs_trans *, xfs_inode_t *, int);
 int            xfs_ialloc(struct xfs_trans *, xfs_inode_t *, mode_t,
                           xfs_nlink_t, xfs_dev_t, struct cred *, xfs_prid_t,
                           int, struct xfs_buf **, boolean_t *, xfs_inode_t **);
-void           xfs_xlate_dinode_core(xfs_caddr_t, struct xfs_dinode_core *,
-                                       int);
+
 uint           xfs_ip2xflags(struct xfs_inode *);
-uint           xfs_dic2xflags(struct xfs_dinode_core *);
+uint           xfs_dic2xflags(struct xfs_dinode *);
 int            xfs_ifree(struct xfs_trans *, xfs_inode_t *,
                           struct xfs_bmap_free *);
-void           xfs_itruncate_start(xfs_inode_t *, uint, xfs_fsize_t);
+int            xfs_itruncate_start(xfs_inode_t *, uint, xfs_fsize_t);
 int            xfs_itruncate_finish(struct xfs_trans **, xfs_inode_t *,
                                     xfs_fsize_t, int, int);
 int            xfs_iunlink(struct xfs_trans *, xfs_inode_t *);
-int            xfs_igrow_start(xfs_inode_t *, xfs_fsize_t, struct cred *);
-void           xfs_igrow_finish(struct xfs_trans *, xfs_inode_t *,
-                                xfs_fsize_t, int);
-
-void           xfs_idestroy_fork(xfs_inode_t *, int);
-void           xfs_idestroy(xfs_inode_t *);
-void           xfs_idata_realloc(xfs_inode_t *, int, int);
-void           xfs_iextract(xfs_inode_t *);
+
 void           xfs_iext_realloc(xfs_inode_t *, int, int);
-void           xfs_iroot_realloc(xfs_inode_t *, int, int);
 void           xfs_ipin(xfs_inode_t *);
 void           xfs_iunpin(xfs_inode_t *);
-int            xfs_iextents_copy(xfs_inode_t *, xfs_bmbt_rec_t *, int);
 int            xfs_iflush(xfs_inode_t *, uint);
-void           xfs_iflush_all(struct xfs_mount *);
-int            xfs_iaccess(xfs_inode_t *, mode_t, cred_t *);
-uint           xfs_iroundup(uint);
 void           xfs_ichgtime(xfs_inode_t *, int);
 xfs_fsize_t    xfs_file_last_byte(xfs_inode_t *);
-void           xfs_lock_inodes(xfs_inode_t **, int, int, uint);
-
-xfs_inode_t    *xfs_vtoi(struct vnode *vp);
+void           xfs_lock_inodes(xfs_inode_t **, int, uint);
+void           xfs_lock_two_inodes(xfs_inode_t *, xfs_inode_t *, uint);
 
 void           xfs_synchronize_atime(xfs_inode_t *);
+void           xfs_mark_inode_dirty_sync(xfs_inode_t *);
+
+#if defined(XFS_INODE_TRACE)
+
+#define        INODE_TRACE_SIZE        16              /* number of trace entries */
+#define        INODE_KTRACE_ENTRY      1
+#define        INODE_KTRACE_EXIT       2
+#define        INODE_KTRACE_HOLD       3
+#define        INODE_KTRACE_REF        4
+#define        INODE_KTRACE_RELE       5
+
+extern void _xfs_itrace_entry(struct xfs_inode *, const char *, inst_t *);
+extern void _xfs_itrace_exit(struct xfs_inode *, const char *, inst_t *);
+extern void xfs_itrace_hold(struct xfs_inode *, char *, int, inst_t *);
+extern void _xfs_itrace_ref(struct xfs_inode *, char *, int, inst_t *);
+extern void xfs_itrace_rele(struct xfs_inode *, char *, int, inst_t *);
+#define xfs_itrace_entry(ip)   \
+       _xfs_itrace_entry(ip, __func__, (inst_t *)__return_address)
+#define xfs_itrace_exit(ip)    \
+       _xfs_itrace_exit(ip, __func__, (inst_t *)__return_address)
+#define xfs_itrace_exit_tag(ip, tag)   \
+       _xfs_itrace_exit(ip, tag, (inst_t *)__return_address)
+#define xfs_itrace_ref(ip)     \
+       _xfs_itrace_ref(ip, __FILE__, __LINE__, (inst_t *)__return_address)
+
+#else
+#define        xfs_itrace_entry(a)
+#define        xfs_itrace_exit(a)
+#define        xfs_itrace_exit_tag(a, b)
+#define        xfs_itrace_hold(a, b, c, d)
+#define        xfs_itrace_ref(a)
+#define        xfs_itrace_rele(a, b, c, d)
+#endif
 
-xfs_bmbt_rec_t *xfs_iext_get_ext(xfs_ifork_t *, xfs_extnum_t);
+#define IHOLD(ip) \
+do { \
+       ASSERT(atomic_read(&VFS_I(ip)->i_count) > 0) ; \
+       atomic_inc(&(VFS_I(ip)->i_count)); \
+       xfs_itrace_hold((ip), __FILE__, __LINE__, (inst_t *)__return_address); \
+} while (0)
+
+#define IRELE(ip) \
+do { \
+       xfs_itrace_rele((ip), __FILE__, __LINE__, (inst_t *)__return_address); \
+       iput(VFS_I(ip)); \
+} while (0)
+
+#endif /* __KERNEL__ */
+
+/*
+ * Flags for xfs_iget()
+ */
+#define XFS_IGET_CREATE                0x1
+#define XFS_IGET_BULKSTAT      0x2
+
+int            xfs_inotobp(struct xfs_mount *, struct xfs_trans *,
+                           xfs_ino_t, struct xfs_dinode **,
+                           struct xfs_buf **, int *, uint);
+int            xfs_itobp(struct xfs_mount *, struct xfs_trans *,
+                         struct xfs_inode *, struct xfs_dinode **,
+                         struct xfs_buf **, uint);
+int            xfs_iread(struct xfs_mount *, struct xfs_trans *,
+                         struct xfs_inode *, xfs_daddr_t, uint);
+void           xfs_dinode_from_disk(struct xfs_icdinode *,
+                                    struct xfs_dinode *);
+void           xfs_dinode_to_disk(struct xfs_dinode *,
+                                  struct xfs_icdinode *);
+void           xfs_idestroy_fork(struct xfs_inode *, int);
+void           xfs_idata_realloc(struct xfs_inode *, int, int);
+void           xfs_iroot_realloc(struct xfs_inode *, int, int);
+int            xfs_iread_extents(struct xfs_trans *, struct xfs_inode *, int);
+int            xfs_iextents_copy(struct xfs_inode *, xfs_bmbt_rec_t *, int);
+
+xfs_bmbt_rec_host_t *xfs_iext_get_ext(xfs_ifork_t *, xfs_extnum_t);
 void           xfs_iext_insert(xfs_ifork_t *, xfs_extnum_t, xfs_extnum_t,
                                xfs_bmbt_irec_t *);
 void           xfs_iext_add(xfs_ifork_t *, xfs_extnum_t, int);
@@ -480,7 +613,7 @@ void                xfs_iext_indirect_to_direct(xfs_ifork_t *);
 void           xfs_iext_direct_to_inline(xfs_ifork_t *, xfs_extnum_t);
 void           xfs_iext_inline_to_direct(xfs_ifork_t *, int);
 void           xfs_iext_destroy(xfs_ifork_t *);
-xfs_bmbt_rec_t *xfs_iext_bno_to_ext(xfs_ifork_t *, xfs_fileoff_t, int *);
+xfs_bmbt_rec_host_t *xfs_iext_bno_to_ext(xfs_ifork_t *, xfs_fileoff_t, int *);
 xfs_ext_irec_t *xfs_iext_bno_to_irec(xfs_ifork_t *, xfs_fileoff_t, int *);
 xfs_ext_irec_t *xfs_iext_idx_to_irec(xfs_ifork_t *, xfs_extnum_t *, int *, int);
 void           xfs_iext_irec_init(xfs_ifork_t *);
@@ -494,7 +627,8 @@ void                xfs_iext_irec_update_extoffs(xfs_ifork_t *, int, int);
 #define xfs_ipincount(ip)      ((unsigned int) atomic_read(&ip->i_pincount))
 
 #ifdef DEBUG
-void           xfs_isize_check(struct xfs_mount *, xfs_inode_t *, xfs_fsize_t);
+void           xfs_isize_check(struct xfs_mount *, struct xfs_inode *,
+                               xfs_fsize_t);
 #else  /* DEBUG */
 #define xfs_isize_check(mp, ip, isize)
 #endif /* DEBUG */
@@ -505,12 +639,8 @@ void               xfs_inobp_check(struct xfs_mount *, struct xfs_buf *);
 #define        xfs_inobp_check(mp, bp)
 #endif /* DEBUG */
 
-extern struct kmem_zone        *xfs_chashlist_zone;
 extern struct kmem_zone        *xfs_ifork_zone;
 extern struct kmem_zone        *xfs_inode_zone;
 extern struct kmem_zone        *xfs_ili_zone;
-extern struct vnodeops xfs_vnodeops;
-
-#endif /* __KERNEL__ */
 
 #endif /* __XFS_INODE_H__ */