static void init_dinode(struct gfs2_inode *dip, struct gfs2_glock *gl,
                        const struct gfs2_inum_host *inum, unsigned int mode,
                        unsigned int uid, unsigned int gid,
-                       const u64 *generation, dev_t dev, struct buffer_head **bhp)
+                       const u64 *generation, dev_t dev, const char *symname,
+                       unsigned size, struct buffer_head **bhp)
 {
        struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode);
        struct gfs2_dinode *di;
        di->di_uid = cpu_to_be32(uid);
        di->di_gid = cpu_to_be32(gid);
        di->di_nlink = 0;
-       di->di_size = 0;
+       di->di_size = cpu_to_be64(size);
        di->di_blocks = cpu_to_be64(1);
        di->di_atime = di->di_mtime = di->di_ctime = cpu_to_be64(tv.tv_sec);
        di->di_major = cpu_to_be32(MAJOR(dev));
        di->di_mtime_nsec = cpu_to_be32(tv.tv_nsec);
        di->di_ctime_nsec = cpu_to_be32(tv.tv_nsec);
        memset(&di->di_reserved, 0, sizeof(di->di_reserved));
-       
-       if (S_ISREG(mode)) {
+
+       switch(mode & S_IFMT) { 
+       case S_IFREG:
                if ((dip->i_diskflags & GFS2_DIF_INHERIT_JDATA) ||
                    gfs2_tune_get(sdp, gt_new_files_jdata))
                        di->di_flags |= cpu_to_be32(GFS2_DIF_JDATA);
-       } else if (S_ISDIR(mode)) {
+               break;
+       case S_IFDIR:
                di->di_flags |= cpu_to_be32(dip->i_diskflags &
                                            GFS2_DIF_INHERIT_JDATA);
                di->di_flags |= cpu_to_be32(GFS2_DIF_JDATA);
                di->di_size = cpu_to_be64(sdp->sd_sb.sb_bsize - sizeof(struct gfs2_dinode));
                di->di_entries = cpu_to_be32(2);
                gfs2_init_dir(dibh, dip);
+               break;
+       case S_IFLNK:
+               memcpy(dibh->b_data + sizeof(struct gfs2_dinode), symname, size);
+               break;
        }
 
        set_buffer_uptodate(dibh);
 
 static int make_dinode(struct gfs2_inode *dip, struct gfs2_glock *gl,
                       unsigned int mode, const struct gfs2_inum_host *inum,
-                      const u64 *generation, dev_t dev, struct buffer_head **bhp)
+                      const u64 *generation, dev_t dev, const char *symname,
+                      unsigned int size, struct buffer_head **bhp)
 {
        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, generation, dev, bhp);
+       init_dinode(dip, gl, inum, mode, uid, gid, generation, dev, symname, size, bhp);
        gfs2_quota_change(dip, +1, uid, gid);
        gfs2_trans_end(sdp);
 
  * Returns: An inode
  */
 
-struct inode *gfs2_createi(struct gfs2_holder *ghs, const struct qstr *name,
-                          unsigned int mode, dev_t dev)
+static struct inode *gfs2_createi(struct gfs2_holder *ghs,
+                                 const struct qstr *name, unsigned int mode,
+                                 dev_t dev, const char *symname,
+                                 unsigned int size)
 {
        struct inode *inode = NULL;
        struct gfs2_inode *dip = ghs->gh_gl->gl_object;
        if (error)
                goto fail_gunlock;
 
-       error = make_dinode(dip, ghs[1].gh_gl, mode, &inum, &generation, dev, &bh);
+       error = make_dinode(dip, ghs[1].gh_gl, mode, &inum, &generation, dev, symname, size, &bh);
        if (error)
                goto fail_gunlock2;
 
        gfs2_holder_init(dip->i_gl, 0, 0, ghs);
 
        for (;;) {
-               inode = gfs2_createi(ghs, &dentry->d_name, S_IFREG | mode, 0);
+               inode = gfs2_createi(ghs, &dentry->d_name, S_IFREG | mode, 0, NULL, 0);
                if (!IS_ERR(inode)) {
                        gfs2_trans_end(sdp);
                        if (dip->i_alloc->al_rgd)
 static int gfs2_symlink(struct inode *dir, struct dentry *dentry,
                        const char *symname)
 {
-       struct gfs2_inode *dip = GFS2_I(dir), *ip;
+       struct gfs2_inode *dip = GFS2_I(dir);
        struct gfs2_sbd *sdp = GFS2_SB(dir);
        struct gfs2_holder ghs[2];
        struct inode *inode;
-       struct buffer_head *dibh;
-       int size;
-       int error;
+       unsigned int size;
 
-       /* Must be stuffed with a null terminator for gfs2_follow_link() */
        size = strlen(symname);
        if (size > sdp->sd_sb.sb_bsize - sizeof(struct gfs2_dinode) - 1)
                return -ENAMETOOLONG;
 
        gfs2_holder_init(dip->i_gl, 0, 0, ghs);
 
-       inode = gfs2_createi(ghs, &dentry->d_name, S_IFLNK | S_IRWXUGO, 0);
+       inode = gfs2_createi(ghs, &dentry->d_name, S_IFLNK | S_IRWXUGO, 0, symname, size);
        if (IS_ERR(inode)) {
                gfs2_holder_uninit(ghs);
                return PTR_ERR(inode);
        }
 
-       ip = ghs[1].gh_gl->gl_object;
-
-       i_size_write(inode, size);
-
-       error = gfs2_meta_inode_buffer(ip, &dibh);
-
-       if (!gfs2_assert_withdraw(sdp, !error)) {
-               gfs2_dinode_out(ip, dibh->b_data);
-               memcpy(dibh->b_data + sizeof(struct gfs2_dinode), symname,
-                      size);
-               brelse(dibh);
-       }
-
        gfs2_trans_end(sdp);
        if (dip->i_alloc->al_rgd)
                gfs2_inplace_release(dip);
 
        gfs2_holder_init(dip->i_gl, 0, 0, ghs);
 
-       inode = gfs2_createi(ghs, &dentry->d_name, S_IFDIR | mode, 0);
+       inode = gfs2_createi(ghs, &dentry->d_name, S_IFDIR | mode, 0, NULL, 0);
        if (IS_ERR(inode)) {
                gfs2_holder_uninit(ghs);
                return PTR_ERR(inode);
 
        gfs2_holder_init(dip->i_gl, 0, 0, ghs);
 
-       inode = gfs2_createi(ghs, &dentry->d_name, mode, dev);
+       inode = gfs2_createi(ghs, &dentry->d_name, mode, dev, NULL, 0);
        if (IS_ERR(inode)) {
                gfs2_holder_uninit(ghs);
                return PTR_ERR(inode);
        struct gfs2_inode *ip = GFS2_I(dentry->d_inode);
        struct gfs2_holder i_gh;
        struct buffer_head *dibh;
-       unsigned int x, size;
+       unsigned int size;
        char *buf;
        int error;
 
                goto out;
        }
 
-       x = size + 1;
-       buf = kmalloc(x, GFP_NOFS);
+       buf = kzalloc(size + 1, GFP_NOFS);
        if (!buf)
                buf = ERR_PTR(-ENOMEM);
        else
-               memcpy(buf, dibh->b_data + sizeof(struct gfs2_dinode), x);
+               memcpy(buf, dibh->b_data + sizeof(struct gfs2_dinode), size);
        brelse(dibh);
 out:
        gfs2_glock_dq_uninit(&i_gh);