#include "util.h"
 
 /**
- * inode_attr_in - Copy attributes from the dinode into the VFS inode
+ * gfs2_inode_attr_in - Copy attributes from the dinode into the VFS inode
  * @ip: The GFS2 inode (with embedded disk inode data)
  * @inode:  The Linux VFS inode
  *
  */
 
-static void inode_attr_in(struct gfs2_inode *ip, struct inode *inode)
+void gfs2_inode_attr_in(struct gfs2_inode *ip)
 {
-       inode->i_ino = ip->i_num.no_formal_ino;
+       struct inode *inode = &ip->i_inode;
+
+       inode->i_ino = ip->i_num.no_addr;
 
        switch (ip->i_di.di_mode & S_IFMT) {
        case S_IFBLK:
                inode->i_flags &= ~S_APPEND;
 }
 
-/**
- * gfs2_inode_attr_in - Copy attributes from the dinode into the VFS inode
- * @ip: The GFS2 inode (with embedded disk inode data)
- *
- */
-
-void gfs2_inode_attr_in(struct gfs2_inode *ip)
-{
-       struct inode *inode = &ip->i_inode;
-       inode_attr_in(ip, inode);
-}
-
 /**
  * gfs2_inode_attr_out - Copy attributes from VFS inode into the dinode
  * @ip: The GFS2 inode
                *gid = current->fsgid;
 }
 
-static int alloc_dinode(struct gfs2_inode *dip, struct gfs2_inum *inum)
+static int alloc_dinode(struct gfs2_inode *dip, struct gfs2_inum *inum,
+                       u64 *generation)
 {
        struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode);
        int error;
        if (error)
                goto out_ipreserv;
 
-       inum->no_addr = gfs2_alloc_di(dip);
+       inum->no_addr = gfs2_alloc_di(dip, generation);
 
        gfs2_trans_end(sdp);
 
- out_ipreserv:
+out_ipreserv:
        gfs2_inplace_release(dip);
 
- out:
+out:
        gfs2_alloc_put(dip);
 
        return error;
  */
 
 static void init_dinode(struct gfs2_inode *dip, struct gfs2_glock *gl,
-                       struct gfs2_inum *inum, unsigned int mode,
-                       unsigned int uid, unsigned int gid)
+                       const struct gfs2_inum *inum, unsigned int mode,
+                       unsigned int uid, unsigned int gid,
+                       const u64 *generation)
 {
        struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode);
        struct gfs2_dinode *di;
        di->di_atime = di->di_mtime = di->di_ctime = cpu_to_be64(get_seconds());
        di->di_major = di->di_minor = cpu_to_be32(0);
        di->di_goal_meta = di->di_goal_data = cpu_to_be64(inum->no_addr);
-       di->__pad[0] = di->__pad[1] = 0;
+       di->di_generation = cpu_to_be64(*generation);
        di->di_flags = cpu_to_be32(0);
 
        if (S_ISREG(mode)) {
 }
 
 static int make_dinode(struct gfs2_inode *dip, struct gfs2_glock *gl,
-                      unsigned int mode, struct gfs2_inum *inum)
+                      unsigned int mode, const struct gfs2_inum *inum,
+                      const u64 *generation)
 {
        struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode);
        unsigned int uid, gid;
        if (error)
                goto out_quota;
 
-       init_dinode(dip, gl, inum, mode, uid, gid);
+       init_dinode(dip, gl, inum, mode, uid, gid, generation);
        gfs2_quota_change(dip, +1, uid, gid);
        gfs2_trans_end(sdp);
 
        struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode);
        struct gfs2_inum inum;
        int error;
+       u64 generation;
 
        if (!name->len || name->len > GFS2_FNAMESIZE)
                return ERR_PTR(-ENAMETOOLONG);
        if (error)
                goto fail_gunlock;
 
-       error = alloc_dinode(dip, &inum);
+       error = alloc_dinode(dip, &inum, &generation);
        if (error)
                goto fail_gunlock;
 
                        goto fail_gunlock;
        }
 
-       error = make_dinode(dip, ghs[1].gh_gl, mode, &inum);
+       error = make_dinode(dip, ghs[1].gh_gl, mode, &inum, &generation);
        if (error)
                goto fail_gunlock2;
 
 
 #include "rgrp.h"
 #include "trans.h"
 #include "util.h"
+#include "ops_address.h"
 
 #define buffer_busy(bh) \
 ((bh)->b_state & ((1ul << BH_Dirty) | (1ul << BH_Lock) | (1ul << BH_Pinned)))
        return block_write_full_page(page, aspace_get_block, wbc);
 }
 
-/**
- * stuck_releasepage - We're stuck in gfs2_releasepage().  Print stuff out.
- * @bh: the buffer we're stuck on
- *
- */
-
-static void stuck_releasepage(struct buffer_head *bh)
-{
-       struct inode *inode = bh->b_page->mapping->host;
-       struct gfs2_sbd *sdp = inode->i_sb->s_fs_info;
-       struct gfs2_bufdata *bd = bh->b_private;
-       struct gfs2_glock *gl;
-
-       fs_warn(sdp, "stuck in gfs2_releasepage() %p\n", inode);
-       fs_warn(sdp, "blkno = %llu, bh->b_count = %d\n",
-               (unsigned long long)bh->b_blocknr, atomic_read(&bh->b_count));
-       fs_warn(sdp, "pinned = %u\n", buffer_pinned(bh));
-       fs_warn(sdp, "bh->b_private = %s\n", (bd) ? "!NULL" : "NULL");
-
-       if (!bd)
-               return;
-
-       gl = bd->bd_gl;
-
-       fs_warn(sdp, "gl = (%u, %llu)\n", 
-               gl->gl_name.ln_type, (unsigned long long)gl->gl_name.ln_number);
-
-       fs_warn(sdp, "bd_list_tr = %s, bd_le.le_list = %s\n",
-               (list_empty(&bd->bd_list_tr)) ? "no" : "yes",
-               (list_empty(&bd->bd_le.le_list)) ? "no" : "yes");
-
-       if (gl->gl_ops == &gfs2_inode_glops) {
-               struct gfs2_inode *ip = gl->gl_object;
-               unsigned int x;
-
-               if (!ip)
-                       return;
-
-               fs_warn(sdp, "ip = %llu %llu\n",
-                       (unsigned long long)ip->i_num.no_formal_ino,
-                       (unsigned long long)ip->i_num.no_addr);
-
-               for (x = 0; x < GFS2_MAX_META_HEIGHT; x++)
-                       fs_warn(sdp, "ip->i_cache[%u] = %s\n",
-                               x, (ip->i_cache[x]) ? "!NULL" : "NULL");
-       }
-}
-
-/**
- * gfs2_aspace_releasepage - free the metadata associated with a page
- * @page: the page that's being released
- * @gfp_mask: passed from Linux VFS, ignored by us
- *
- * Call try_to_free_buffers() if the buffers in this page can be
- * released.
- *
- * Returns: 0
- */
-
-static int gfs2_aspace_releasepage(struct page *page, gfp_t gfp_mask)
-{
-       struct inode *aspace = page->mapping->host;
-       struct gfs2_sbd *sdp = aspace->i_sb->s_fs_info;
-       struct buffer_head *bh, *head;
-       struct gfs2_bufdata *bd;
-       unsigned long t;
-
-       if (!page_has_buffers(page))
-               goto out;
-
-       head = bh = page_buffers(page);
-       do {
-               t = jiffies;
-
-               while (atomic_read(&bh->b_count)) {
-                       if (atomic_read(&aspace->i_writecount)) {
-                               if (time_after_eq(jiffies, t +
-                                   gfs2_tune_get(sdp, gt_stall_secs) * HZ)) {
-                                       stuck_releasepage(bh);
-                                       t = jiffies;
-                               }
-
-                               yield();
-                               continue;
-                       }
-
-                       return 0;
-               }
-
-               gfs2_assert_warn(sdp, !buffer_pinned(bh));
-
-               bd = bh->b_private;
-               if (bd) {
-                       gfs2_assert_warn(sdp, bd->bd_bh == bh);
-                       gfs2_assert_warn(sdp, list_empty(&bd->bd_list_tr));
-                       gfs2_assert_warn(sdp, list_empty(&bd->bd_le.le_list));
-                       gfs2_assert_warn(sdp, !bd->bd_ail);
-                       kmem_cache_free(gfs2_bufdata_cachep, bd);
-                       bh->b_private = NULL;
-               }
-
-               bh = bh->b_this_page;
-       }
-       while (bh != head);
-
- out:
-       return try_to_free_buffers(page);
-}
-
 static const struct address_space_operations aspace_aops = {
        .writepage = gfs2_aspace_writepage,
-       .releasepage = gfs2_aspace_releasepage,
+       .releasepage = gfs2_releasepage,
 };
 
 /**
 
        rg->rg_flags = be32_to_cpu(str->rg_flags);
        rg->rg_free = be32_to_cpu(str->rg_free);
        rg->rg_dinodes = be32_to_cpu(str->rg_dinodes);
+       rg->rg_igeneration = be64_to_cpu(str->rg_igeneration);
 }
 
 void gfs2_rgrp_out(struct gfs2_rgrp *rg, char *buf)
        str->rg_flags = cpu_to_be32(rg->rg_flags);
        str->rg_free = cpu_to_be32(rg->rg_free);
        str->rg_dinodes = cpu_to_be32(rg->rg_dinodes);
-
+       str->__pad = cpu_to_be32(0);
+       str->rg_igeneration = cpu_to_be64(rg->rg_igeneration);
        memset(&str->rg_reserved, 0, sizeof(str->rg_reserved));
 }
 
 
        di->di_goal_meta = be64_to_cpu(str->di_goal_meta);
        di->di_goal_data = be64_to_cpu(str->di_goal_data);
+       di->di_generation = be64_to_cpu(str->di_generation);
 
        di->di_flags = be32_to_cpu(str->di_flags);
        di->di_payload_format = be32_to_cpu(str->di_payload_format);
 
        str->di_goal_meta = cpu_to_be64(di->di_goal_meta);
        str->di_goal_data = cpu_to_be64(di->di_goal_data);
+       str->di_generation = cpu_to_be64(di->di_generation);
 
        str->di_flags = cpu_to_be32(di->di_flags);
        str->di_payload_format = cpu_to_be32(di->di_payload_format);
 
 #include "rgrp.h"
 #include "ops_file.h"
 #include "util.h"
+#include "glops.h"
 
 /**
  * gfs2_get_block - Fills in a buffer head with details about a block
        return ret;
 }
 
+/**
+ * stuck_releasepage - We're stuck in gfs2_releasepage().  Print stuff out.
+ * @bh: the buffer we're stuck on
+ *
+ */
+
+static void stuck_releasepage(struct buffer_head *bh)
+{
+       struct inode *inode = bh->b_page->mapping->host;
+       struct gfs2_sbd *sdp = inode->i_sb->s_fs_info;
+       struct gfs2_bufdata *bd = bh->b_private;
+       struct gfs2_glock *gl;
+
+       fs_warn(sdp, "stuck in gfs2_releasepage() %p\n", inode);
+       fs_warn(sdp, "blkno = %llu, bh->b_count = %d\n",
+               (unsigned long long)bh->b_blocknr, atomic_read(&bh->b_count));
+       fs_warn(sdp, "pinned = %u\n", buffer_pinned(bh));
+       fs_warn(sdp, "bh->b_private = %s\n", (bd) ? "!NULL" : "NULL");
+
+       if (!bd)
+               return;
+
+       gl = bd->bd_gl;
+
+       fs_warn(sdp, "gl = (%u, %llu)\n", 
+               gl->gl_name.ln_type, (unsigned long long)gl->gl_name.ln_number);
+
+       fs_warn(sdp, "bd_list_tr = %s, bd_le.le_list = %s\n",
+               (list_empty(&bd->bd_list_tr)) ? "no" : "yes",
+               (list_empty(&bd->bd_le.le_list)) ? "no" : "yes");
+
+       if (gl->gl_ops == &gfs2_inode_glops) {
+               struct gfs2_inode *ip = gl->gl_object;
+               unsigned int x;
+
+               if (!ip)
+                       return;
+
+               fs_warn(sdp, "ip = %llu %llu\n",
+                       (unsigned long long)ip->i_num.no_formal_ino,
+                       (unsigned long long)ip->i_num.no_addr);
+
+               for (x = 0; x < GFS2_MAX_META_HEIGHT; x++)
+                       fs_warn(sdp, "ip->i_cache[%u] = %s\n",
+                               x, (ip->i_cache[x]) ? "!NULL" : "NULL");
+       }
+}
+
+/**
+ * gfs2_aspace_releasepage - free the metadata associated with a page
+ * @page: the page that's being released
+ * @gfp_mask: passed from Linux VFS, ignored by us
+ *
+ * Call try_to_free_buffers() if the buffers in this page can be
+ * released.
+ *
+ * Returns: 0
+ */
+
+int gfs2_releasepage(struct page *page, gfp_t gfp_mask)
+{
+       struct inode *aspace = page->mapping->host;
+       struct gfs2_sbd *sdp = aspace->i_sb->s_fs_info;
+       struct buffer_head *bh, *head;
+       struct gfs2_bufdata *bd;
+       unsigned long t;
+
+       if (!page_has_buffers(page))
+               goto out;
+
+       head = bh = page_buffers(page);
+       do {
+               t = jiffies;
+
+               while (atomic_read(&bh->b_count)) {
+                       if (atomic_read(&aspace->i_writecount)) {
+                               if (time_after_eq(jiffies, t +
+                                   gfs2_tune_get(sdp, gt_stall_secs) * HZ)) {
+                                       stuck_releasepage(bh);
+                                       t = jiffies;
+                               }
+
+                               yield();
+                               continue;
+                       }
+
+                       return 0;
+               }
+
+               gfs2_assert_warn(sdp, !buffer_pinned(bh));
+
+               bd = bh->b_private;
+               if (bd) {
+                       gfs2_assert_warn(sdp, bd->bd_bh == bh);
+                       gfs2_assert_warn(sdp, list_empty(&bd->bd_list_tr));
+                       gfs2_assert_warn(sdp, list_empty(&bd->bd_le.le_list));
+                       gfs2_assert_warn(sdp, !bd->bd_ail);
+                       kmem_cache_free(gfs2_bufdata_cachep, bd);
+                       bh->b_private = NULL;
+               }
+
+               bh = bh->b_this_page;
+       }
+       while (bh != head);
+
+ out:
+       return try_to_free_buffers(page);
+}
+
 const struct address_space_operations gfs2_file_aops = {
        .writepage = gfs2_writepage,
        .readpage = gfs2_readpage,
        .commit_write = gfs2_commit_write,
        .bmap = gfs2_bmap,
        .invalidatepage = gfs2_invalidatepage,
+       .releasepage = gfs2_releasepage,
        .direct_IO = gfs2_direct_IO,
 };
 
 
 extern const struct address_space_operations gfs2_file_aops;
 extern int gfs2_get_block(struct inode *inode, sector_t lblock,
                          struct buffer_head *bh_result, int create);
+extern int gfs2_releasepage(struct page *page, gfp_t gfp_mask);
 
 #endif /* __OPS_ADDRESS_DOT_H__ */
 
        int error;
 
        error = fdr->fdr_filldir(fdr->fdr_opaque, name, length, offset,
-                                inum->no_formal_ino, type);
+                                inum->no_addr, type);
        if (error)
                return 1;
 
 
  * Returns: the allocated block
  */
 
-uint64_t gfs2_alloc_data(struct gfs2_inode *ip)
+u64 gfs2_alloc_data(struct gfs2_inode *ip)
 {
        struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
        struct gfs2_alloc *al = &ip->i_alloc;
  * Returns: the allocated block
  */
 
-uint64_t gfs2_alloc_meta(struct gfs2_inode *ip)
+u64 gfs2_alloc_meta(struct gfs2_inode *ip)
 {
        struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
        struct gfs2_alloc *al = &ip->i_alloc;
  * Returns: the block allocated
  */
 
-uint64_t gfs2_alloc_di(struct gfs2_inode *dip)
+u64 gfs2_alloc_di(struct gfs2_inode *dip, u64 *generation)
 {
        struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode);
        struct gfs2_alloc *al = &dip->i_alloc;
        struct gfs2_rgrpd *rgd = al->al_rgd;
-       uint32_t blk;
-       uint64_t block;
+       u32 blk;
+       u64 block;
 
        blk = rgblk_search(rgd, rgd->rd_last_alloc_meta,
                           GFS2_BLKST_FREE, GFS2_BLKST_DINODE);
        gfs2_assert_withdraw(sdp, rgd->rd_rg.rg_free);
        rgd->rd_rg.rg_free--;
        rgd->rd_rg.rg_dinodes++;
-
+       *generation = rgd->rd_rg.rg_igeneration++;
        gfs2_trans_add_bh(rgd->rd_gl, rgd->rd_bits[0].bi_bh, 1);
        gfs2_rgrp_out(&rgd->rd_rg, rgd->rd_bits[0].bi_bh->b_data);
 
 
 
 unsigned char gfs2_get_block_type(struct gfs2_rgrpd *rgd, uint64_t block);
 
-uint64_t gfs2_alloc_data(struct gfs2_inode *ip);
-uint64_t gfs2_alloc_meta(struct gfs2_inode *ip);
-uint64_t gfs2_alloc_di(struct gfs2_inode *ip);
+u64 gfs2_alloc_data(struct gfs2_inode *ip);
+u64 gfs2_alloc_meta(struct gfs2_inode *ip);
+u64 gfs2_alloc_di(struct gfs2_inode *ip, u64 *generation);
 
 void gfs2_free_data(struct gfs2_inode *ip, uint64_t bstart, uint32_t blen);
 void gfs2_free_meta(struct gfs2_inode *ip, uint64_t bstart, uint32_t blen);
 
        __be32 rg_flags;
        __be32 rg_free;
        __be32 rg_dinodes;
+       __be32 __pad;
+       __be64 rg_igeneration;
 
-       __u8 rg_reserved[92]; /* Several fields from gfs1 now reserved */
+       __u8 rg_reserved[80]; /* Several fields from gfs1 now reserved */
 };
 
 /*
         */
        __be64 di_goal_meta;    /* rgrp to alloc from next */
        __be64 di_goal_data;    /* data block goal */
-       __u32 __pad[2];
+       __be64 di_generation;   /* generation number for NFS */
 
        __be32 di_flags;        /* GFS2_DIF_... */
        __be32 di_payload_format;  /* GFS2_FORMAT_... */