SUNRPC: xprt_connect() don't abort the task if the transport isn't bound
[safe/jmp/linux-2.6] / fs / ocfs2 / namei.c
index 701e6d0..084aba8 100644 (file)
@@ -40,6 +40,7 @@
 #include <linux/types.h>
 #include <linux/slab.h>
 #include <linux/highmem.h>
+#include <linux/quotaops.h>
 
 #define MLOG_MASK_PREFIX ML_NAMEI
 #include <cluster/masklog.h>
 #include "symlink.h"
 #include "sysfile.h"
 #include "uptodate.h"
-#include "vote.h"
+#include "xattr.h"
+#include "acl.h"
 
 #include "buffer_head_io.h"
 
-#define NAMEI_RA_CHUNKS  2
-#define NAMEI_RA_BLOCKS  4
-#define NAMEI_RA_SIZE        (NAMEI_RA_CHUNKS * NAMEI_RA_BLOCKS)
-#define NAMEI_RA_INDEX(c,b)  (((c) * NAMEI_RA_BLOCKS) + (b))
-
-static int inline ocfs2_search_dirblock(struct buffer_head *bh,
-                                       struct inode *dir,
-                                       const char *name, int namelen,
-                                       unsigned long offset,
-                                       struct ocfs2_dir_entry **res_dir);
-
-static int ocfs2_delete_entry(handle_t *handle,
-                             struct inode *dir,
-                             struct ocfs2_dir_entry *de_del,
-                             struct buffer_head *bh);
-
-static int __ocfs2_add_entry(handle_t *handle,
-                            struct inode *dir,
-                            const char *name, int namelen,
-                            struct inode *inode, u64 blkno,
-                            struct buffer_head *parent_fe_bh,
-                            struct buffer_head *insert_bh);
-
 static int ocfs2_mknod_locked(struct ocfs2_super *osb,
                              struct inode *dir,
-                             struct dentry *dentry, int mode,
+                             struct inode *inode,
+                             struct dentry *dentry,
                              dev_t dev,
                              struct buffer_head **new_fe_bh,
                              struct buffer_head *parent_fe_bh,
                              handle_t *handle,
-                             struct inode **ret_inode,
                              struct ocfs2_alloc_context *inode_ac);
 
-static int ocfs2_fill_new_dir(struct ocfs2_super *osb,
-                             handle_t *handle,
-                             struct inode *parent,
-                             struct inode *inode,
-                             struct buffer_head *fe_bh,
-                             struct ocfs2_alloc_context *data_ac);
-
 static int ocfs2_prepare_orphan_dir(struct ocfs2_super *osb,
                                    struct inode **ret_orphan_dir,
                                    struct inode *inode,
@@ -123,17 +95,6 @@ static int ocfs2_create_symlink_data(struct ocfs2_super *osb,
                                     struct inode *inode,
                                     const char *symname);
 
-static inline int ocfs2_add_entry(handle_t *handle,
-                                 struct dentry *dentry,
-                                 struct inode *inode, u64 blkno,
-                                 struct buffer_head *parent_fe_bh,
-                                 struct buffer_head *insert_bh)
-{
-       return __ocfs2_add_entry(handle, dentry->d_parent->d_inode,
-                                dentry->d_name.name, dentry->d_name.len,
-                                inode, blkno, parent_fe_bh, insert_bh);
-}
-
 /* An orphan dir name is an 8 byte value, printed as a hex string */
 #define OCFS2_ORPHAN_NAMELEN ((int)(2 * sizeof(u64)))
 
@@ -142,10 +103,8 @@ static struct dentry *ocfs2_lookup(struct inode *dir, struct dentry *dentry,
 {
        int status;
        u64 blkno;
-       struct buffer_head *dirent_bh = NULL;
        struct inode *inode = NULL;
        struct dentry *ret;
-       struct ocfs2_dir_entry *dirent;
        struct ocfs2_inode_info *oi;
 
        mlog_entry("(0x%p, 0x%p, '%.*s')\n", dir, dentry,
@@ -159,7 +118,7 @@ static struct dentry *ocfs2_lookup(struct inode *dir, struct dentry *dentry,
        mlog(0, "find name %.*s in directory %llu\n", dentry->d_name.len,
             dentry->d_name.name, (unsigned long long)OCFS2_I(dir)->ip_blkno);
 
-       status = ocfs2_meta_lock(dir, NULL, 0);
+       status = ocfs2_inode_lock(dir, NULL, 0);
        if (status < 0) {
                if (status != -ENOENT)
                        mlog_errno(status);
@@ -167,13 +126,12 @@ static struct dentry *ocfs2_lookup(struct inode *dir, struct dentry *dentry,
                goto bail;
        }
 
-       status = ocfs2_find_files_on_disk(dentry->d_name.name,
-                                         dentry->d_name.len, &blkno,
-                                         dir, &dirent_bh, &dirent);
+       status = ocfs2_lookup_ino_from_name(dir, dentry->d_name.name,
+                                           dentry->d_name.len, &blkno);
        if (status < 0)
                goto bail_add;
 
-       inode = ocfs2_iget(OCFS2_SB(dir->i_sb), blkno, 0);
+       inode = ocfs2_iget(OCFS2_SB(dir->i_sb), blkno, 0, 0);
        if (IS_ERR(inode)) {
                ret = ERR_PTR(-EACCES);
                goto bail_unlock;
@@ -220,85 +178,43 @@ bail_unlock:
        /* Don't drop the cluster lock until *after* the d_add --
         * unlink on another node will message us to remove that
         * dentry under this lock so otherwise we can race this with
-        * the vote thread and have a stale dentry. */
-       ocfs2_meta_unlock(dir, 0);
+        * the downconvert thread and have a stale dentry. */
+       ocfs2_inode_unlock(dir, 0);
 
 bail:
-       if (dirent_bh)
-               brelse(dirent_bh);
 
        mlog_exit_ptr(ret);
 
        return ret;
 }
 
-static int ocfs2_fill_new_dir(struct ocfs2_super *osb,
-                             handle_t *handle,
-                             struct inode *parent,
-                             struct inode *inode,
-                             struct buffer_head *fe_bh,
-                             struct ocfs2_alloc_context *data_ac)
+static struct inode *ocfs2_get_init_inode(struct inode *dir, int mode)
 {
-       int status;
-       struct buffer_head *new_bh = NULL;
-       struct ocfs2_dir_entry *de = NULL;
+       struct inode *inode;
 
-       mlog_entry_void();
-
-       status = ocfs2_do_extend_dir(osb->sb, handle, inode, fe_bh,
-                                    data_ac, NULL, &new_bh);
-       if (status < 0) {
-               mlog_errno(status);
-               goto bail;
-       }
-
-       ocfs2_set_new_buffer_uptodate(inode, new_bh);
-
-       status = ocfs2_journal_access(handle, inode, new_bh,
-                                     OCFS2_JOURNAL_ACCESS_CREATE);
-       if (status < 0) {
-               mlog_errno(status);
-               goto bail;
-       }
-       memset(new_bh->b_data, 0, osb->sb->s_blocksize);
-
-       de = (struct ocfs2_dir_entry *) new_bh->b_data;
-       de->inode = cpu_to_le64(OCFS2_I(inode)->ip_blkno);
-       de->name_len = 1;
-       de->rec_len =
-               cpu_to_le16(OCFS2_DIR_REC_LEN(de->name_len));
-       strcpy(de->name, ".");
-       ocfs2_set_de_type(de, S_IFDIR);
-       de = (struct ocfs2_dir_entry *) ((char *)de + le16_to_cpu(de->rec_len));
-       de->inode = cpu_to_le64(OCFS2_I(parent)->ip_blkno);
-       de->rec_len = cpu_to_le16(inode->i_sb->s_blocksize -
-                                 OCFS2_DIR_REC_LEN(1));
-       de->name_len = 2;
-       strcpy(de->name, "..");
-       ocfs2_set_de_type(de, S_IFDIR);
-
-       status = ocfs2_journal_dirty(handle, new_bh);
-       if (status < 0) {
-               mlog_errno(status);
-               goto bail;
-       }
-
-       i_size_write(inode, inode->i_sb->s_blocksize);
-       inode->i_nlink = 2;
-       inode->i_blocks = ocfs2_inode_sector_count(inode);
-       status = ocfs2_mark_inode_dirty(handle, inode, fe_bh);
-       if (status < 0) {
-               mlog_errno(status);
-               goto bail;
+       inode = new_inode(dir->i_sb);
+       if (!inode) {
+               mlog(ML_ERROR, "new_inode failed!\n");
+               return NULL;
        }
 
-       status = 0;
-bail:
-       if (new_bh)
-               brelse(new_bh);
-
-       mlog_exit(status);
-       return status;
+       /* populate as many fields early on as possible - many of
+        * these are used by the support functions here and in
+        * callers. */
+       if (S_ISDIR(mode))
+               inode->i_nlink = 2;
+       else
+               inode->i_nlink = 1;
+       inode->i_uid = current_fsuid();
+       if (dir->i_mode & S_ISGID) {
+               inode->i_gid = dir->i_gid;
+               if (S_ISDIR(mode))
+                       mode |= S_ISGID;
+       } else
+               inode->i_gid = current_fsgid();
+       inode->i_mode = mode;
+       vfs_dq_init(inode);
+       return inode;
 }
 
 static int ocfs2_mknod(struct inode *dir,
@@ -316,6 +232,13 @@ static int ocfs2_mknod(struct inode *dir,
        struct inode *inode = NULL;
        struct ocfs2_alloc_context *inode_ac = NULL;
        struct ocfs2_alloc_context *data_ac = NULL;
+       struct ocfs2_alloc_context *xattr_ac = NULL;
+       int want_clusters = 0;
+       int xattr_credits = 0;
+       struct ocfs2_security_xattr_info si = {
+               .enable = 1,
+       };
+       int did_quota_inode = 0;
 
        mlog_entry("(0x%p, 0x%p, %d, %lu, '%.*s')\n", dir, dentry, mode,
                   (unsigned long)dev, dentry->d_name.len,
@@ -324,7 +247,7 @@ static int ocfs2_mknod(struct inode *dir,
        /* get our super block */
        osb = OCFS2_SB(dir->i_sb);
 
-       status = ocfs2_meta_lock(dir, &parent_fe_bh, 1);
+       status = ocfs2_inode_lock(dir, &parent_fe_bh, 1);
        if (status < 0) {
                if (status != -ENOENT)
                        mlog_errno(status);
@@ -365,18 +288,46 @@ static int ocfs2_mknod(struct inode *dir,
                goto leave;
        }
 
-       /* are we making a directory? If so, reserve a cluster for his
-        * 1st extent. */
-       if (S_ISDIR(mode)) {
-               status = ocfs2_reserve_clusters(osb, 1, &data_ac);
-               if (status < 0) {
-                       if (status != -ENOSPC)
-                               mlog_errno(status);
+       inode = ocfs2_get_init_inode(dir, mode);
+       if (!inode) {
+               status = -ENOMEM;
+               mlog_errno(status);
+               goto leave;
+       }
+
+       /* get security xattr */
+       status = ocfs2_init_security_get(inode, dir, &si);
+       if (status) {
+               if (status == -EOPNOTSUPP)
+                       si.enable = 0;
+               else {
+                       mlog_errno(status);
                        goto leave;
                }
        }
 
-       handle = ocfs2_start_trans(osb, OCFS2_MKNOD_CREDITS);
+       /* calculate meta data/clusters for setting security and acl xattr */
+       status = ocfs2_calc_xattr_init(dir, parent_fe_bh, mode,
+                                       &si, &want_clusters,
+                                       &xattr_credits, &xattr_ac);
+       if (status < 0) {
+               mlog_errno(status);
+               goto leave;
+       }
+
+       /* Reserve a cluster if creating an extent based directory. */
+       if (S_ISDIR(mode) && !ocfs2_supports_inline_data(osb))
+               want_clusters += 1;
+
+       status = ocfs2_reserve_clusters(osb, want_clusters, &data_ac);
+       if (status < 0) {
+               if (status != -ENOSPC)
+                       mlog_errno(status);
+               goto leave;
+       }
+
+       handle = ocfs2_start_trans(osb, ocfs2_mknod_credits(osb->sb) +
+                                  xattr_credits);
        if (IS_ERR(handle)) {
                status = PTR_ERR(handle);
                handle = NULL;
@@ -384,10 +335,19 @@ static int ocfs2_mknod(struct inode *dir,
                goto leave;
        }
 
+       /* We don't use standard VFS wrapper because we don't want vfs_dq_init
+        * to be called. */
+       if (sb_any_quota_active(osb->sb) &&
+           osb->sb->dq_op->alloc_inode(inode, 1) == NO_QUOTA) {
+               status = -EDQUOT;
+               goto leave;
+       }
+       did_quota_inode = 1;
+
        /* do the real work now. */
-       status = ocfs2_mknod_locked(osb, dir, dentry, mode, dev,
+       status = ocfs2_mknod_locked(osb, dir, inode, dentry, dev,
                                    &new_fe_bh, parent_fe_bh, handle,
-                                   &inode, inode_ac);
+                                   inode_ac);
        if (status < 0) {
                mlog_errno(status);
                goto leave;
@@ -401,8 +361,8 @@ static int ocfs2_mknod(struct inode *dir,
                        goto leave;
                }
 
-               status = ocfs2_journal_access(handle, dir, parent_fe_bh,
-                                             OCFS2_JOURNAL_ACCESS_WRITE);
+               status = ocfs2_journal_access_di(handle, dir, parent_fe_bh,
+                                                OCFS2_JOURNAL_ACCESS_WRITE);
                if (status < 0) {
                        mlog_errno(status);
                        goto leave;
@@ -416,6 +376,22 @@ static int ocfs2_mknod(struct inode *dir,
                inc_nlink(dir);
        }
 
+       status = ocfs2_init_acl(handle, inode, dir, new_fe_bh, parent_fe_bh,
+                               xattr_ac, data_ac);
+       if (status < 0) {
+               mlog_errno(status);
+               goto leave;
+       }
+
+       if (si.enable) {
+               status = ocfs2_init_security_set(handle, inode, new_fe_bh, &si,
+                                                xattr_ac, data_ac);
+               if (status < 0) {
+                       mlog_errno(status);
+                       goto leave;
+               }
+       }
+
        status = ocfs2_add_entry(handle, dentry, inode,
                                 OCFS2_I(inode)->ip_blkno, parent_fe_bh,
                                 de_bh);
@@ -436,25 +412,26 @@ static int ocfs2_mknod(struct inode *dir,
        d_instantiate(dentry, inode);
        status = 0;
 leave:
+       if (status < 0 && did_quota_inode)
+               vfs_dq_free_inode(inode);
        if (handle)
                ocfs2_commit_trans(osb, handle);
 
-       ocfs2_meta_unlock(dir, 1);
+       ocfs2_inode_unlock(dir, 1);
 
        if (status == -ENOSPC)
                mlog(0, "Disk is full\n");
 
-       if (new_fe_bh)
-               brelse(new_fe_bh);
-
-       if (de_bh)
-               brelse(de_bh);
-
-       if (parent_fe_bh)
-               brelse(parent_fe_bh);
+       brelse(new_fe_bh);
+       brelse(de_bh);
+       brelse(parent_fe_bh);
+       kfree(si.name);
+       kfree(si.value);
 
-       if ((status < 0) && inode)
+       if ((status < 0) && inode) {
+               clear_nlink(inode);
                iput(inode);
+       }
 
        if (inode_ac)
                ocfs2_free_alloc_context(inode_ac);
@@ -462,6 +439,9 @@ leave:
        if (data_ac)
                ocfs2_free_alloc_context(data_ac);
 
+       if (xattr_ac)
+               ocfs2_free_alloc_context(xattr_ac);
+
        mlog_exit(status);
 
        return status;
@@ -469,12 +449,12 @@ leave:
 
 static int ocfs2_mknod_locked(struct ocfs2_super *osb,
                              struct inode *dir,
-                             struct dentry *dentry, int mode,
+                             struct inode *inode,
+                             struct dentry *dentry,
                              dev_t dev,
                              struct buffer_head **new_fe_bh,
                              struct buffer_head *parent_fe_bh,
                              handle_t *handle,
-                             struct inode **ret_inode,
                              struct ocfs2_alloc_context *inode_ac)
 {
        int status = 0;
@@ -482,14 +462,12 @@ static int ocfs2_mknod_locked(struct ocfs2_super *osb,
        struct ocfs2_extent_list *fel;
        u64 fe_blkno = 0;
        u16 suballoc_bit;
-       struct inode *inode = NULL;
 
-       mlog_entry("(0x%p, 0x%p, %d, %lu, '%.*s')\n", dir, dentry, mode,
-                  (unsigned long)dev, dentry->d_name.len,
+       mlog_entry("(0x%p, 0x%p, %d, %lu, '%.*s')\n", dir, dentry,
+                  inode->i_mode, (unsigned long)dev, dentry->d_name.len,
                   dentry->d_name.name);
 
        *new_fe_bh = NULL;
-       *ret_inode = NULL;
 
        status = ocfs2_claim_new_inode(osb, handle, inode_ac, &suballoc_bit,
                                       &fe_blkno);
@@ -498,23 +476,11 @@ static int ocfs2_mknod_locked(struct ocfs2_super *osb,
                goto leave;
        }
 
-       inode = new_inode(dir->i_sb);
-       if (IS_ERR(inode)) {
-               status = PTR_ERR(inode);
-               mlog(ML_ERROR, "new_inode failed!\n");
-               goto leave;
-       }
-
        /* populate as many fields early on as possible - many of
         * these are used by the support functions here and in
         * callers. */
        inode->i_ino = ino_from_blkno(osb->sb, fe_blkno);
        OCFS2_I(inode)->ip_blkno = fe_blkno;
-       if (S_ISDIR(mode))
-               inode->i_nlink = 2;
-       else
-               inode->i_nlink = 1;
-       inode->i_mode = mode;
        spin_lock(&osb->osb_lock);
        inode->i_generation = osb->s_next_generation++;
        spin_unlock(&osb->osb_lock);
@@ -527,8 +493,8 @@ static int ocfs2_mknod_locked(struct ocfs2_super *osb,
        }
        ocfs2_set_new_buffer_uptodate(inode, *new_fe_bh);
 
-       status = ocfs2_journal_access(handle, inode, *new_fe_bh,
-                                     OCFS2_JOURNAL_ACCESS_CREATE);
+       status = ocfs2_journal_access_di(handle, inode, *new_fe_bh,
+                                        OCFS2_JOURNAL_ACCESS_CREATE);
        if (status < 0) {
                mlog_errno(status);
                goto leave;
@@ -541,18 +507,12 @@ static int ocfs2_mknod_locked(struct ocfs2_super *osb,
        fe->i_fs_generation = cpu_to_le32(osb->fs_generation);
        fe->i_blkno = cpu_to_le64(fe_blkno);
        fe->i_suballoc_bit = cpu_to_le16(suballoc_bit);
-       fe->i_suballoc_slot = cpu_to_le16(osb->slot_num);
-       fe->i_uid = cpu_to_le32(current->fsuid);
-       if (dir->i_mode & S_ISGID) {
-               fe->i_gid = cpu_to_le32(dir->i_gid);
-               if (S_ISDIR(mode))
-                       mode |= S_ISGID;
-       } else
-               fe->i_gid = cpu_to_le32(current->fsgid);
-       fe->i_mode = cpu_to_le16(mode);
-       if (S_ISCHR(mode) || S_ISBLK(mode))
+       fe->i_suballoc_slot = cpu_to_le16(inode_ac->ac_alloc_slot);
+       fe->i_uid = cpu_to_le32(inode->i_uid);
+       fe->i_gid = cpu_to_le32(inode->i_gid);
+       fe->i_mode = cpu_to_le16(inode->i_mode);
+       if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode))
                fe->id1.dev1.i_rdev = cpu_to_le64(huge_encode_dev(dev));
-
        fe->i_links_count = cpu_to_le16(inode->i_nlink);
 
        fe->i_last_eb_blk = 0;
@@ -564,10 +524,21 @@ static int ocfs2_mknod_locked(struct ocfs2_super *osb,
                cpu_to_le32(CURRENT_TIME.tv_nsec);
        fe->i_dtime = 0;
 
-       fel = &fe->id2.i_list;
-       fel->l_tree_depth = 0;
-       fel->l_next_free_rec = 0;
-       fel->l_count = cpu_to_le16(ocfs2_extent_recs_per_inode(osb->sb));
+       /*
+        * If supported, directories start with inline data.
+        */
+       if (S_ISDIR(inode->i_mode) && ocfs2_supports_inline_data(osb)) {
+               u16 feat = le16_to_cpu(fe->i_dyn_features);
+
+               fe->i_dyn_features = cpu_to_le16(feat | OCFS2_INLINE_DATA_FL);
+
+               fe->id2.i_data.id_count = cpu_to_le16(ocfs2_max_inline_data(osb->sb));
+       } else {
+               fel = &fe->id2.i_list;
+               fel->l_tree_depth = 0;
+               fel->l_next_free_rec = 0;
+               fel->l_count = cpu_to_le16(ocfs2_extent_recs_per_inode(osb->sb));
+       }
 
        status = ocfs2_journal_dirty(handle, *new_fe_bh);
        if (status < 0) {
@@ -575,15 +546,7 @@ static int ocfs2_mknod_locked(struct ocfs2_super *osb,
                goto leave;
        }
 
-       if (ocfs2_populate_inode(inode, fe, 1) < 0) {
-               mlog(ML_ERROR, "populate inode failed! bh->b_blocknr=%llu, "
-                    "i_blkno=%llu, i_ino=%lu\n",
-                    (unsigned long long)(*new_fe_bh)->b_blocknr,
-                    (unsigned long long)le64_to_cpu(fe->i_blkno),
-                    inode->i_ino);
-               BUG();
-       }
-
+       ocfs2_populate_inode(inode, fe, 1);
        ocfs2_inode_set_new(osb, inode);
        if (!ocfs2_mount_local(osb)) {
                status = ocfs2_create_new_inode_locks(inode);
@@ -594,15 +557,12 @@ static int ocfs2_mknod_locked(struct ocfs2_super *osb,
        status = 0; /* error in ocfs2_create_new_inode_locks is not
                     * critical */
 
-       *ret_inode = inode;
 leave:
        if (status < 0) {
                if (*new_fe_bh) {
                        brelse(*new_fe_bh);
                        *new_fe_bh = NULL;
                }
-               if (inode)
-                       iput(inode);
        }
 
        mlog_exit(status);
@@ -658,7 +618,7 @@ static int ocfs2_link(struct dentry *old_dentry,
        if (S_ISDIR(inode->i_mode))
                return -EPERM;
 
-       err = ocfs2_meta_lock(dir, &parent_fe_bh, 1);
+       err = ocfs2_inode_lock(dir, &parent_fe_bh, 1);
        if (err < 0) {
                if (err != -ENOENT)
                        mlog_errno(err);
@@ -683,7 +643,7 @@ static int ocfs2_link(struct dentry *old_dentry,
                goto out;
        }
 
-       err = ocfs2_meta_lock(inode, &fe_bh, 1);
+       err = ocfs2_inode_lock(inode, &fe_bh, 1);
        if (err < 0) {
                if (err != -ENOENT)
                        mlog_errno(err);
@@ -696,7 +656,7 @@ static int ocfs2_link(struct dentry *old_dentry,
                goto out_unlock_inode;
        }
 
-       handle = ocfs2_start_trans(osb, OCFS2_LINK_CREDITS);
+       handle = ocfs2_start_trans(osb, ocfs2_link_credits(osb->sb));
        if (IS_ERR(handle)) {
                err = PTR_ERR(handle);
                handle = NULL;
@@ -704,8 +664,8 @@ static int ocfs2_link(struct dentry *old_dentry,
                goto out_unlock_inode;
        }
 
-       err = ocfs2_journal_access(handle, inode, fe_bh,
-                                  OCFS2_JOURNAL_ACCESS_WRITE);
+       err = ocfs2_journal_access_di(handle, inode, fe_bh,
+                                     OCFS2_JOURNAL_ACCESS_WRITE);
        if (err < 0) {
                mlog_errno(err);
                goto out_commit;
@@ -748,17 +708,14 @@ static int ocfs2_link(struct dentry *old_dentry,
 out_commit:
        ocfs2_commit_trans(osb, handle);
 out_unlock_inode:
-       ocfs2_meta_unlock(inode, 1);
+       ocfs2_inode_unlock(inode, 1);
 
 out:
-       ocfs2_meta_unlock(dir, 1);
+       ocfs2_inode_unlock(dir, 1);
 
-       if (de_bh)
-               brelse(de_bh);
-       if (fe_bh)
-               brelse(fe_bh);
-       if (parent_fe_bh)
-               brelse(parent_fe_bh);
+       brelse(de_bh);
+       brelse(fe_bh);
+       brelse(parent_fe_bh);
 
        mlog_exit(err);
 
@@ -825,7 +782,7 @@ static int ocfs2_unlink(struct inode *dir,
                return -EPERM;
        }
 
-       status = ocfs2_meta_lock(dir, &parent_node_bh, 1);
+       status = ocfs2_inode_lock(dir, &parent_node_bh, 1);
        if (status < 0) {
                if (status != -ENOENT)
                        mlog_errno(status);
@@ -850,7 +807,7 @@ static int ocfs2_unlink(struct inode *dir,
                goto leave;
        }
 
-       status = ocfs2_meta_lock(inode, &fe_bh, 1);
+       status = ocfs2_inode_lock(inode, &fe_bh, 1);
        if (status < 0) {
                if (status != -ENOENT)
                        mlog_errno(status);
@@ -870,7 +827,7 @@ static int ocfs2_unlink(struct inode *dir,
 
        status = ocfs2_remote_dentry_delete(dentry);
        if (status < 0) {
-               /* This vote should succeed under all normal
+               /* This remote delete should succeed under all normal
                 * circumstances. */
                mlog_errno(status);
                goto leave;
@@ -886,7 +843,7 @@ static int ocfs2_unlink(struct inode *dir,
                }
        }
 
-       handle = ocfs2_start_trans(osb, OCFS2_UNLINK_CREDITS);
+       handle = ocfs2_start_trans(osb, ocfs2_unlink_credits(osb->sb));
        if (IS_ERR(handle)) {
                status = PTR_ERR(handle);
                handle = NULL;
@@ -894,8 +851,8 @@ static int ocfs2_unlink(struct inode *dir,
                goto leave;
        }
 
-       status = ocfs2_journal_access(handle, inode, fe_bh,
-                                     OCFS2_JOURNAL_ACCESS_WRITE);
+       status = ocfs2_journal_access_di(handle, inode, fe_bh,
+                                        OCFS2_JOURNAL_ACCESS_WRITE);
        if (status < 0) {
                mlog_errno(status);
                goto leave;
@@ -946,28 +903,21 @@ leave:
                ocfs2_commit_trans(osb, handle);
 
        if (child_locked)
-               ocfs2_meta_unlock(inode, 1);
+               ocfs2_inode_unlock(inode, 1);
 
-       ocfs2_meta_unlock(dir, 1);
+       ocfs2_inode_unlock(dir, 1);
 
        if (orphan_dir) {
                /* This was locked for us in ocfs2_prepare_orphan_dir() */
-               ocfs2_meta_unlock(orphan_dir, 1);
+               ocfs2_inode_unlock(orphan_dir, 1);
                mutex_unlock(&orphan_dir->i_mutex);
                iput(orphan_dir);
        }
 
-       if (fe_bh)
-               brelse(fe_bh);
-
-       if (dirent_bh)
-               brelse(dirent_bh);
-
-       if (parent_node_bh)
-               brelse(parent_node_bh);
-
-       if (orphan_entry_bh)
-               brelse(orphan_entry_bh);
+       brelse(fe_bh);
+       brelse(dirent_bh);
+       brelse(parent_node_bh);
+       brelse(orphan_entry_bh);
 
        mlog_exit(status);
 
@@ -1013,7 +963,7 @@ static int ocfs2_double_lock(struct ocfs2_super *osb,
                        inode1 = tmpinode;
                }
                /* lock id2 */
-               status = ocfs2_meta_lock(inode2, bh2, 1);
+               status = ocfs2_inode_lock(inode2, bh2, 1);
                if (status < 0) {
                        if (status != -ENOENT)
                                mlog_errno(status);
@@ -1022,14 +972,14 @@ static int ocfs2_double_lock(struct ocfs2_super *osb,
        }
 
        /* lock id1 */
-       status = ocfs2_meta_lock(inode1, bh1, 1);
+       status = ocfs2_inode_lock(inode1, bh1, 1);
        if (status < 0) {
                /*
                 * An error return must mean that no cluster locks
                 * were held on function exit.
                 */
                if (oi1->ip_blkno != oi2->ip_blkno)
-                       ocfs2_meta_unlock(inode2, 1);
+                       ocfs2_inode_unlock(inode2, 1);
 
                if (status != -ENOENT)
                        mlog_errno(status);
@@ -1042,17 +992,12 @@ bail:
 
 static void ocfs2_double_unlock(struct inode *inode1, struct inode *inode2)
 {
-       ocfs2_meta_unlock(inode1, 1);
+       ocfs2_inode_unlock(inode1, 1);
 
        if (inode1 != inode2)
-               ocfs2_meta_unlock(inode2, 1);
+               ocfs2_inode_unlock(inode2, 1);
 }
 
-#define PARENT_INO(buffer) \
-       ((struct ocfs2_dir_entry *) \
-        ((char *)buffer + \
-         le16_to_cpu(((struct ocfs2_dir_entry *)buffer)->rec_len)))->inode
-
 static int ocfs2_rename(struct inode *old_dir,
                        struct dentry *old_dentry,
                        struct inode *new_dir,
@@ -1070,12 +1015,12 @@ static int ocfs2_rename(struct inode *old_dir,
        struct buffer_head *old_inode_bh = NULL;
        struct buffer_head *insert_entry_bh = NULL;
        struct ocfs2_super *osb = NULL;
-       u64 newfe_blkno;
+       u64 newfe_blkno, old_de_ino;
        handle_t *handle = NULL;
        struct buffer_head *old_dir_bh = NULL;
        struct buffer_head *new_dir_bh = NULL;
-       struct ocfs2_dir_entry *old_de = NULL, *new_de = NULL; // dirent for old_dentry
-                                                              // and new_dentry
+       struct ocfs2_dir_entry *old_inode_dot_dot_de = NULL, *old_de = NULL,
+               *new_de = NULL;
        struct buffer_head *new_de_bh = NULL, *old_de_bh = NULL; // bhs for above
        struct buffer_head *old_inode_de_bh = NULL; // if old_dentry is a dir,
                                                    // this is the 1st dirent bh
@@ -1108,7 +1053,7 @@ static int ocfs2_rename(struct inode *old_dir,
         *
         * And that's why, just like the VFS, we need a file system
         * rename lock. */
-       if (old_dentry != new_dentry) {
+       if (old_dir != new_dir && S_ISDIR(old_inode->i_mode)) {
                status = ocfs2_rename_lock(osb);
                if (status < 0) {
                        mlog_errno(status);
@@ -1141,10 +1086,11 @@ static int ocfs2_rename(struct inode *old_dir,
 
        /*
         * Aside from allowing a meta data update, the locking here
-        * also ensures that the vote thread on other nodes won't have
-        * to concurrently downconvert the inode and the dentry locks.
+        * also ensures that the downconvert thread on other nodes
+        * won't have to concurrently downconvert the inode and the
+        * dentry locks.
         */
-       status = ocfs2_meta_lock(old_inode, &old_inode_bh, 1);
+       status = ocfs2_inode_lock(old_inode, &old_inode_bh, 1);
        if (status < 0) {
                if (status != -ENOENT)
                        mlog_errno(status);
@@ -1159,27 +1105,35 @@ static int ocfs2_rename(struct inode *old_dir,
        }
 
        if (S_ISDIR(old_inode->i_mode)) {
-               status = -EIO;
-               old_inode_de_bh = ocfs2_bread(old_inode, 0, &status, 0);
-               if (!old_inode_de_bh)
+               u64 old_inode_parent;
+
+               status = ocfs2_find_files_on_disk("..", 2, &old_inode_parent,
+                                                 old_inode, &old_inode_de_bh,
+                                                 &old_inode_dot_dot_de);
+               if (status) {
+                       status = -EIO;
                        goto bail;
+               }
 
-               status = -EIO;
-               if (le64_to_cpu(PARENT_INO(old_inode_de_bh->b_data)) !=
-                   OCFS2_I(old_dir)->ip_blkno)
+               if (old_inode_parent != OCFS2_I(old_dir)->ip_blkno) {
+                       status = -EIO;
                        goto bail;
-               status = -EMLINK;
-               if (!new_inode && new_dir!=old_dir &&
-                   new_dir->i_nlink >= OCFS2_LINK_MAX)
+               }
+
+               if (!new_inode && new_dir != old_dir &&
+                   new_dir->i_nlink >= OCFS2_LINK_MAX) {
+                       status = -EMLINK;
                        goto bail;
+               }
        }
 
-       status = -ENOENT;
-       old_de_bh = ocfs2_find_entry(old_dentry->d_name.name,
-                                    old_dentry->d_name.len,
-                                    old_dir, &old_de);
-       if (!old_de_bh)
+       status = ocfs2_lookup_ino_from_name(old_dir, old_dentry->d_name.name,
+                                           old_dentry->d_name.len,
+                                           &old_de_ino);
+       if (status) {
+               status = -ENOENT;
                goto bail;
+       }
 
        /*
         *  Check for inode number is _not_ due to possible IO errors.
@@ -1187,8 +1141,10 @@ static int ocfs2_rename(struct inode *old_dir,
         *  and merrily kill the link to whatever was created under the
         *  same name. Goodbye sticky bit ;-<
         */
-       if (le64_to_cpu(old_de->inode) != OCFS2_I(old_inode)->ip_blkno)
+       if (old_de_ino != OCFS2_I(old_inode)->ip_blkno) {
+               status = -ENOENT;
                goto bail;
+       }
 
        /* check if the target already exists (in which case we need
         * to delete it */
@@ -1205,9 +1161,16 @@ static int ocfs2_rename(struct inode *old_dir,
                goto bail;
        }
 
-       if (!new_de && new_inode)
-               mlog(ML_ERROR, "inode %lu does not exist in it's parent "
-                    "directory!", new_inode->i_ino);
+       if (!new_de && new_inode) {
+               /*
+                * Target was unlinked by another node while we were
+                * waiting to get to ocfs2_rename(). There isn't
+                * anything we can do here to help the situation, so
+                * bubble up the appropriate error.
+                */
+               status = -ENOENT;
+               goto bail;
+       }
 
        /* In case we need to overwrite an existing file, we blow it
         * away first */
@@ -1236,7 +1199,7 @@ static int ocfs2_rename(struct inode *old_dir,
                        goto bail;
                }
 
-               status = ocfs2_meta_lock(new_inode, &newfe_bh, 1);
+               status = ocfs2_inode_lock(new_inode, &newfe_bh, 1);
                if (status < 0) {
                        if (status != -ENOENT)
                                mlog_errno(status);
@@ -1286,7 +1249,7 @@ static int ocfs2_rename(struct inode *old_dir,
                }
        }
 
-       handle = ocfs2_start_trans(osb, OCFS2_RENAME_CREDITS);
+       handle = ocfs2_start_trans(osb, ocfs2_rename_credits(osb->sb));
        if (IS_ERR(handle)) {
                status = PTR_ERR(handle);
                handle = NULL;
@@ -1302,8 +1265,8 @@ static int ocfs2_rename(struct inode *old_dir,
                                goto bail;
                        }
                }
-               status = ocfs2_journal_access(handle, new_inode, newfe_bh,
-                                             OCFS2_JOURNAL_ACCESS_WRITE);
+               status = ocfs2_journal_access_di(handle, new_inode, newfe_bh,
+                                                OCFS2_JOURNAL_ACCESS_WRITE);
                if (status < 0) {
                        mlog_errno(status);
                        goto bail;
@@ -1321,20 +1284,13 @@ static int ocfs2_rename(struct inode *old_dir,
                }
 
                /* change the dirent to point to the correct inode */
-               status = ocfs2_journal_access(handle, new_dir, new_de_bh,
-                                             OCFS2_JOURNAL_ACCESS_WRITE);
+               status = ocfs2_update_entry(new_dir, handle, new_de_bh,
+                                           new_de, old_inode);
                if (status < 0) {
                        mlog_errno(status);
                        goto bail;
                }
-               new_de->inode = cpu_to_le64(OCFS2_I(old_inode)->ip_blkno);
-               new_de->file_type = old_de->file_type;
                new_dir->i_version++;
-               status = ocfs2_journal_dirty(handle, new_de_bh);
-               if (status < 0) {
-                       mlog_errno(status);
-                       goto bail;
-               }
 
                if (S_ISDIR(new_inode->i_mode))
                        newfe->i_links_count = 0;
@@ -1356,8 +1312,8 @@ static int ocfs2_rename(struct inode *old_dir,
        old_inode->i_ctime = CURRENT_TIME;
        mark_inode_dirty(old_inode);
 
-       status = ocfs2_journal_access(handle, old_inode, old_inode_bh,
-                                     OCFS2_JOURNAL_ACCESS_WRITE);
+       status = ocfs2_journal_access_di(handle, old_inode, old_inode_bh,
+                                        OCFS2_JOURNAL_ACCESS_WRITE);
        if (status >= 0) {
                old_di = (struct ocfs2_dinode *) old_inode_bh->b_data;
 
@@ -1370,7 +1326,21 @@ static int ocfs2_rename(struct inode *old_dir,
        } else
                mlog_errno(status);
 
-       /* now that the name has been added to new_dir, remove the old name */
+       /*
+        * Now that the name has been added to new_dir, remove the old name.
+        *
+        * We don't keep any directory entry context around until now
+        * because the insert might have changed the type of directory
+        * we're dealing with.
+        */
+       old_de_bh = ocfs2_find_entry(old_dentry->d_name.name,
+                                    old_dentry->d_name.len,
+                                    old_dir, &old_de);
+       if (!old_de_bh) {
+               status = -EIO;
+               goto bail;
+       }
+
        status = ocfs2_delete_entry(handle, old_dir, old_de, old_de_bh);
        if (status < 0) {
                mlog_errno(status);
@@ -1383,12 +1353,8 @@ static int ocfs2_rename(struct inode *old_dir,
        }
        old_dir->i_ctime = old_dir->i_mtime = CURRENT_TIME;
        if (old_inode_de_bh) {
-               status = ocfs2_journal_access(handle, old_inode,
-                                            old_inode_de_bh,
-                                            OCFS2_JOURNAL_ACCESS_WRITE);
-               PARENT_INO(old_inode_de_bh->b_data) =
-                       cpu_to_le64(OCFS2_I(new_dir)->ip_blkno);
-               status = ocfs2_journal_dirty(handle, old_inode_de_bh);
+               status = ocfs2_update_entry(old_inode, handle, old_inode_de_bh,
+                                           old_inode_dot_dot_de, new_dir);
                old_dir->i_nlink--;
                if (new_inode) {
                        new_inode->i_nlink--;
@@ -1423,9 +1389,9 @@ static int ocfs2_rename(struct inode *old_dir,
                             (int)old_dir_nlink, old_dir->i_nlink);
                } else {
                        struct ocfs2_dinode *fe;
-                       status = ocfs2_journal_access(handle, old_dir,
-                                                     old_dir_bh,
-                                                     OCFS2_JOURNAL_ACCESS_WRITE);
+                       status = ocfs2_journal_access_di(handle, old_dir,
+                                                        old_dir_bh,
+                                                        OCFS2_JOURNAL_ACCESS_WRITE);
                        fe = (struct ocfs2_dinode *) old_dir_bh->b_data;
                        fe->i_links_count = cpu_to_le16(old_dir->i_nlink);
                        status = ocfs2_journal_dirty(handle, old_dir_bh);
@@ -1445,14 +1411,14 @@ bail:
                ocfs2_double_unlock(old_dir, new_dir);
 
        if (old_child_locked)
-               ocfs2_meta_unlock(old_inode, 1);
+               ocfs2_inode_unlock(old_inode, 1);
 
        if (new_child_locked)
-               ocfs2_meta_unlock(new_inode, 1);
+               ocfs2_inode_unlock(new_inode, 1);
 
        if (orphan_dir) {
                /* This was locked for us in ocfs2_prepare_orphan_dir() */
-               ocfs2_meta_unlock(orphan_dir, 1);
+               ocfs2_inode_unlock(orphan_dir, 1);
                mutex_unlock(&orphan_dir->i_mutex);
                iput(orphan_dir);
        }
@@ -1462,24 +1428,15 @@ bail:
 
        if (new_inode)
                iput(new_inode);
-       if (newfe_bh)
-               brelse(newfe_bh);
-       if (old_inode_bh)
-               brelse(old_inode_bh);
-       if (old_dir_bh)
-               brelse(old_dir_bh);
-       if (new_dir_bh)
-               brelse(new_dir_bh);
-       if (new_de_bh)
-               brelse(new_de_bh);
-       if (old_de_bh)
-               brelse(old_de_bh);
-       if (old_inode_de_bh)
-               brelse(old_inode_de_bh);
-       if (orphan_entry_bh)
-               brelse(orphan_entry_bh);
-       if (insert_entry_bh)
-               brelse(insert_entry_bh);
+       brelse(newfe_bh);
+       brelse(old_inode_bh);
+       brelse(old_dir_bh);
+       brelse(new_dir_bh);
+       brelse(new_de_bh);
+       brelse(old_de_bh);
+       brelse(old_inode_de_bh);
+       brelse(orphan_entry_bh);
+       brelse(insert_entry_bh);
 
        mlog_exit(status);
 
@@ -1582,8 +1539,7 @@ bail:
 
        if (bhs) {
                for(i = 0; i < blocks; i++)
-                       if (bhs[i])
-                               brelse(bhs[i]);
+                       brelse(bhs[i]);
                kfree(bhs);
        }
 
@@ -1608,6 +1564,13 @@ static int ocfs2_symlink(struct inode *dir,
        handle_t *handle = NULL;
        struct ocfs2_alloc_context *inode_ac = NULL;
        struct ocfs2_alloc_context *data_ac = NULL;
+       struct ocfs2_alloc_context *xattr_ac = NULL;
+       int want_clusters = 0;
+       int xattr_credits = 0;
+       struct ocfs2_security_xattr_info si = {
+               .enable = 1,
+       };
+       int did_quota = 0, did_quota_inode = 0;
 
        mlog_entry("(0x%p, 0x%p, symname='%s' actual='%.*s')\n", dir,
                   dentry, symname, dentry->d_name.len, dentry->d_name.name);
@@ -1620,7 +1583,7 @@ static int ocfs2_symlink(struct inode *dir,
        credits = ocfs2_calc_symlink_credits(sb);
 
        /* lock the parent directory */
-       status = ocfs2_meta_lock(dir, &parent_fe_bh, 1);
+       status = ocfs2_inode_lock(dir, &parent_fe_bh, 1);
        if (status < 0) {
                if (status != -ENOENT)
                        mlog_errno(status);
@@ -1654,17 +1617,46 @@ static int ocfs2_symlink(struct inode *dir,
                goto bail;
        }
 
-       /* don't reserve bitmap space for fast symlinks. */
-       if (l > ocfs2_fast_symlink_chars(sb)) {
-               status = ocfs2_reserve_clusters(osb, 1, &data_ac);
+       inode = ocfs2_get_init_inode(dir, S_IFLNK | S_IRWXUGO);
+       if (!inode) {
+               status = -ENOMEM;
+               mlog_errno(status);
+               goto bail;
+       }
+
+       /* get security xattr */
+       status = ocfs2_init_security_get(inode, dir, &si);
+       if (status) {
+               if (status == -EOPNOTSUPP)
+                       si.enable = 0;
+               else {
+                       mlog_errno(status);
+                       goto bail;
+               }
+       }
+
+       /* calculate meta data/clusters for setting security xattr */
+       if (si.enable) {
+               status = ocfs2_calc_security_init(dir, &si, &want_clusters,
+                                                 &xattr_credits, &xattr_ac);
                if (status < 0) {
-                       if (status != -ENOSPC)
-                               mlog_errno(status);
+                       mlog_errno(status);
                        goto bail;
                }
        }
 
-       handle = ocfs2_start_trans(osb, credits);
+       /* don't reserve bitmap space for fast symlinks. */
+       if (l > ocfs2_fast_symlink_chars(sb))
+               want_clusters += 1;
+
+       status = ocfs2_reserve_clusters(osb, want_clusters, &data_ac);
+       if (status < 0) {
+               if (status != -ENOSPC)
+                       mlog_errno(status);
+               goto bail;
+       }
+
+       handle = ocfs2_start_trans(osb, credits + xattr_credits);
        if (IS_ERR(handle)) {
                status = PTR_ERR(handle);
                handle = NULL;
@@ -1672,10 +1664,18 @@ static int ocfs2_symlink(struct inode *dir,
                goto bail;
        }
 
-       status = ocfs2_mknod_locked(osb, dir, dentry,
-                                   S_IFLNK | S_IRWXUGO, 0,
-                                   &new_fe_bh, parent_fe_bh, handle,
-                                   &inode, inode_ac);
+       /* We don't use standard VFS wrapper because we don't want vfs_dq_init
+        * to be called. */
+       if (sb_any_quota_active(osb->sb) &&
+           osb->sb->dq_op->alloc_inode(inode, 1) == NO_QUOTA) {
+               status = -EDQUOT;
+               goto bail;
+       }
+       did_quota_inode = 1;
+
+       status = ocfs2_mknod_locked(osb, dir, inode, dentry,
+                                   0, &new_fe_bh, parent_fe_bh, handle,
+                                   inode_ac);
        if (status < 0) {
                mlog_errno(status);
                goto bail;
@@ -1688,10 +1688,16 @@ static int ocfs2_symlink(struct inode *dir,
                u32 offset = 0;
 
                inode->i_op = &ocfs2_symlink_inode_operations;
-               status = ocfs2_do_extend_allocation(osb, inode, &offset, 1, 0,
-                                                   new_fe_bh,
-                                                   handle, data_ac, NULL,
-                                                   NULL);
+               if (vfs_dq_alloc_space_nodirty(inode,
+                   ocfs2_clusters_to_bytes(osb->sb, 1))) {
+                       status = -EDQUOT;
+                       goto bail;
+               }
+               did_quota = 1;
+               status = ocfs2_add_inode_data(osb, inode, &offset, 1, 0,
+                                             new_fe_bh,
+                                             handle, data_ac, NULL,
+                                             NULL);
                if (status < 0) {
                        if (status != -ENOSPC && status != -EINTR) {
                                mlog(ML_ERROR,
@@ -1726,6 +1732,15 @@ static int ocfs2_symlink(struct inode *dir,
                }
        }
 
+       if (si.enable) {
+               status = ocfs2_init_security_set(handle, inode, new_fe_bh, &si,
+                                                xattr_ac, data_ac);
+               if (status < 0) {
+                       mlog_errno(status);
+                       goto bail;
+               }
+       }
+
        status = ocfs2_add_entry(handle, dentry, inode,
                                 le64_to_cpu(fe->i_blkno), parent_fe_bh,
                                 de_bh);
@@ -1744,350 +1759,35 @@ static int ocfs2_symlink(struct inode *dir,
        dentry->d_op = &ocfs2_dentry_ops;
        d_instantiate(dentry, inode);
 bail:
+       if (status < 0 && did_quota)
+               vfs_dq_free_space_nodirty(inode,
+                                       ocfs2_clusters_to_bytes(osb->sb, 1));
+       if (status < 0 && did_quota_inode)
+               vfs_dq_free_inode(inode);
        if (handle)
                ocfs2_commit_trans(osb, handle);
 
-       ocfs2_meta_unlock(dir, 1);
+       ocfs2_inode_unlock(dir, 1);
 
-       if (new_fe_bh)
-               brelse(new_fe_bh);
-       if (parent_fe_bh)
-               brelse(parent_fe_bh);
-       if (de_bh)
-               brelse(de_bh);
+       brelse(new_fe_bh);
+       brelse(parent_fe_bh);
+       brelse(de_bh);
+       kfree(si.name);
+       kfree(si.value);
        if (inode_ac)
                ocfs2_free_alloc_context(inode_ac);
        if (data_ac)
                ocfs2_free_alloc_context(data_ac);
-       if ((status < 0) && inode)
+       if (xattr_ac)
+               ocfs2_free_alloc_context(xattr_ac);
+       if ((status < 0) && inode) {
+               clear_nlink(inode);
                iput(inode);
-
-       mlog_exit(status);
-
-       return status;
-}
-
-int ocfs2_check_dir_entry(struct inode * dir,
-                         struct ocfs2_dir_entry * de,
-                         struct buffer_head * bh,
-                         unsigned long offset)
-{
-       const char *error_msg = NULL;
-       const int rlen = le16_to_cpu(de->rec_len);
-
-       if (rlen < OCFS2_DIR_REC_LEN(1))
-               error_msg = "rec_len is smaller than minimal";
-       else if (rlen % 4 != 0)
-               error_msg = "rec_len % 4 != 0";
-       else if (rlen < OCFS2_DIR_REC_LEN(de->name_len))
-               error_msg = "rec_len is too small for name_len";
-       else if (((char *) de - bh->b_data) + rlen > dir->i_sb->s_blocksize)
-               error_msg = "directory entry across blocks";
-
-       if (error_msg != NULL)
-               mlog(ML_ERROR, "bad entry in directory #%llu: %s - "
-                    "offset=%lu, inode=%llu, rec_len=%d, name_len=%d\n",
-                    (unsigned long long)OCFS2_I(dir)->ip_blkno, error_msg,
-                    offset, (unsigned long long)le64_to_cpu(de->inode), rlen,
-                    de->name_len);
-       return error_msg == NULL ? 1 : 0;
-}
-
-/* we don't always have a dentry for what we want to add, so people
- * like orphan dir can call this instead.
- *
- * If you pass me insert_bh, I'll skip the search of the other dir
- * blocks and put the record in there.
- */
-static int __ocfs2_add_entry(handle_t *handle,
-                            struct inode *dir,
-                            const char *name, int namelen,
-                            struct inode *inode, u64 blkno,
-                            struct buffer_head *parent_fe_bh,
-                            struct buffer_head *insert_bh)
-{
-       unsigned long offset;
-       unsigned short rec_len;
-       struct ocfs2_dir_entry *de, *de1;
-       struct super_block *sb;
-       int retval, status;
-
-       mlog_entry_void();
-
-       sb = dir->i_sb;
-
-       if (!namelen)
-               return -EINVAL;
-
-       rec_len = OCFS2_DIR_REC_LEN(namelen);
-       offset = 0;
-       de = (struct ocfs2_dir_entry *) insert_bh->b_data;
-       while (1) {
-               BUG_ON((char *)de >= sb->s_blocksize + insert_bh->b_data);
-               /* These checks should've already been passed by the
-                * prepare function, but I guess we can leave them
-                * here anyway. */
-               if (!ocfs2_check_dir_entry(dir, de, insert_bh, offset)) {
-                       retval = -ENOENT;
-                       goto bail;
-               }
-               if (ocfs2_match(namelen, name, de)) {
-                       retval = -EEXIST;
-                       goto bail;
-               }
-               if (((le64_to_cpu(de->inode) == 0) &&
-                    (le16_to_cpu(de->rec_len) >= rec_len)) ||
-                   (le16_to_cpu(de->rec_len) >=
-                    (OCFS2_DIR_REC_LEN(de->name_len) + rec_len))) {
-                       dir->i_mtime = dir->i_ctime = CURRENT_TIME;
-                       retval = ocfs2_mark_inode_dirty(handle, dir, parent_fe_bh);
-                       if (retval < 0) {
-                               mlog_errno(retval);
-                               goto bail;
-                       }
-
-                       status = ocfs2_journal_access(handle, dir, insert_bh,
-                                                     OCFS2_JOURNAL_ACCESS_WRITE);
-                       /* By now the buffer is marked for journaling */
-                       offset += le16_to_cpu(de->rec_len);
-                       if (le64_to_cpu(de->inode)) {
-                               de1 = (struct ocfs2_dir_entry *)((char *) de +
-                                       OCFS2_DIR_REC_LEN(de->name_len));
-                               de1->rec_len =
-                                       cpu_to_le16(le16_to_cpu(de->rec_len) -
-                                       OCFS2_DIR_REC_LEN(de->name_len));
-                               de->rec_len = cpu_to_le16(OCFS2_DIR_REC_LEN(de->name_len));
-                               de = de1;
-                       }
-                       de->file_type = OCFS2_FT_UNKNOWN;
-                       if (blkno) {
-                               de->inode = cpu_to_le64(blkno);
-                               ocfs2_set_de_type(de, inode->i_mode);
-                       } else
-                               de->inode = 0;
-                       de->name_len = namelen;
-                       memcpy(de->name, name, namelen);
-
-                       dir->i_version++;
-                       status = ocfs2_journal_dirty(handle, insert_bh);
-                       retval = 0;
-                       goto bail;
-               }
-               offset += le16_to_cpu(de->rec_len);
-               de = (struct ocfs2_dir_entry *) ((char *) de + le16_to_cpu(de->rec_len));
        }
 
-       /* when you think about it, the assert above should prevent us
-        * from ever getting here. */
-       retval = -ENOSPC;
-bail:
-
-       mlog_exit(retval);
-       return retval;
-}
-
-
-/*
- * ocfs2_delete_entry deletes a directory entry by merging it with the
- * previous entry
- */
-static int ocfs2_delete_entry(handle_t *handle,
-                             struct inode *dir,
-                             struct ocfs2_dir_entry *de_del,
-                             struct buffer_head *bh)
-{
-       struct ocfs2_dir_entry *de, *pde;
-       int i, status = -ENOENT;
-
-       mlog_entry("(0x%p, 0x%p, 0x%p, 0x%p)\n", handle, dir, de_del, bh);
-
-       i = 0;
-       pde = NULL;
-       de = (struct ocfs2_dir_entry *) bh->b_data;
-       while (i < bh->b_size) {
-               if (!ocfs2_check_dir_entry(dir, de, bh, i)) {
-                       status = -EIO;
-                       mlog_errno(status);
-                       goto bail;
-               }
-               if (de == de_del)  {
-                       status = ocfs2_journal_access(handle, dir, bh,
-                                                     OCFS2_JOURNAL_ACCESS_WRITE);
-                       if (status < 0) {
-                               status = -EIO;
-                               mlog_errno(status);
-                               goto bail;
-                       }
-                       if (pde)
-                               pde->rec_len =
-                                       cpu_to_le16(le16_to_cpu(pde->rec_len) +
-                                                   le16_to_cpu(de->rec_len));
-                       else
-                               de->inode = 0;
-                       dir->i_version++;
-                       status = ocfs2_journal_dirty(handle, bh);
-                       goto bail;
-               }
-               i += le16_to_cpu(de->rec_len);
-               pde = de;
-               de = (struct ocfs2_dir_entry *)((char *)de + le16_to_cpu(de->rec_len));
-       }
-bail:
        mlog_exit(status);
-       return status;
-}
 
-/*
- * Returns 0 if not found, -1 on failure, and 1 on success
- */
-static int inline ocfs2_search_dirblock(struct buffer_head *bh,
-                                       struct inode *dir,
-                                       const char *name, int namelen,
-                                       unsigned long offset,
-                                       struct ocfs2_dir_entry **res_dir)
-{
-       struct ocfs2_dir_entry *de;
-       char *dlimit, *de_buf;
-       int de_len;
-       int ret = 0;
-
-       mlog_entry_void();
-
-       de_buf = bh->b_data;
-       dlimit = de_buf + dir->i_sb->s_blocksize;
-
-       while (de_buf < dlimit) {
-               /* this code is executed quadratically often */
-               /* do minimal checking `by hand' */
-
-               de = (struct ocfs2_dir_entry *) de_buf;
-
-               if (de_buf + namelen <= dlimit &&
-                   ocfs2_match(namelen, name, de)) {
-                       /* found a match - just to be sure, do a full check */
-                       if (!ocfs2_check_dir_entry(dir, de, bh, offset)) {
-                               ret = -1;
-                               goto bail;
-                       }
-                       *res_dir = de;
-                       ret = 1;
-                       goto bail;
-               }
-
-               /* prevent looping on a bad block */
-               de_len = le16_to_cpu(de->rec_len);
-               if (de_len <= 0) {
-                       ret = -1;
-                       goto bail;
-               }
-
-               de_buf += de_len;
-               offset += de_len;
-       }
-
-bail:
-       mlog_exit(ret);
-       return ret;
-}
-
-struct buffer_head *ocfs2_find_entry(const char *name, int namelen,
-                                    struct inode *dir,
-                                    struct ocfs2_dir_entry **res_dir)
-{
-       struct super_block *sb;
-       struct buffer_head *bh_use[NAMEI_RA_SIZE];
-       struct buffer_head *bh, *ret = NULL;
-       unsigned long start, block, b;
-       int ra_max = 0;         /* Number of bh's in the readahead
-                                  buffer, bh_use[] */
-       int ra_ptr = 0;         /* Current index into readahead
-                                  buffer */
-       int num = 0;
-       int nblocks, i, err;
-
-       mlog_entry_void();
-
-       *res_dir = NULL;
-       sb = dir->i_sb;
-
-       nblocks = i_size_read(dir) >> sb->s_blocksize_bits;
-       start = OCFS2_I(dir)->ip_dir_start_lookup;
-       if (start >= nblocks)
-               start = 0;
-       block = start;
-
-restart:
-       do {
-               /*
-                * We deal with the read-ahead logic here.
-                */
-               if (ra_ptr >= ra_max) {
-                       /* Refill the readahead buffer */
-                       ra_ptr = 0;
-                       b = block;
-                       for (ra_max = 0; ra_max < NAMEI_RA_SIZE; ra_max++) {
-                               /*
-                                * Terminate if we reach the end of the
-                                * directory and must wrap, or if our
-                                * search has finished at this block.
-                                */
-                               if (b >= nblocks || (num && block == start)) {
-                                       bh_use[ra_max] = NULL;
-                                       break;
-                               }
-                               num++;
-
-                               bh = ocfs2_bread(dir, b++, &err, 1);
-                               bh_use[ra_max] = bh;
-                       }
-               }
-               if ((bh = bh_use[ra_ptr++]) == NULL)
-                       goto next;
-               wait_on_buffer(bh);
-               if (!buffer_uptodate(bh)) {
-                       /* read error, skip block & hope for the best */
-                       ocfs2_error(dir->i_sb, "reading directory %llu, "
-                                   "offset %lu\n",
-                                   (unsigned long long)OCFS2_I(dir)->ip_blkno,
-                                   block);
-                       brelse(bh);
-                       goto next;
-               }
-               i = ocfs2_search_dirblock(bh, dir, name, namelen,
-                                         block << sb->s_blocksize_bits,
-                                         res_dir);
-               if (i == 1) {
-                       OCFS2_I(dir)->ip_dir_start_lookup = block;
-                       ret = bh;
-                       goto cleanup_and_exit;
-               } else {
-                       brelse(bh);
-                       if (i < 0)
-                               goto cleanup_and_exit;
-               }
-       next:
-               if (++block >= nblocks)
-                       block = 0;
-       } while (block != start);
-
-       /*
-        * If the directory has grown while we were searching, then
-        * search the last part of the directory before giving up.
-        */
-       block = nblocks;
-       nblocks = i_size_read(dir) >> sb->s_blocksize_bits;
-       if (block < nblocks) {
-               start = 0;
-               goto restart;
-       }
-
-cleanup_and_exit:
-       /* Clean up the read-ahead blocks */
-       for (; ra_ptr < ra_max; ra_ptr++)
-               brelse(bh_use[ra_ptr]);
-
-       mlog_exit_ptr(ret);
-       return ret;
+       return status;
 }
 
 static int ocfs2_blkno_stringify(u64 blkno, char *name)
@@ -2148,7 +1848,7 @@ static int ocfs2_prepare_orphan_dir(struct ocfs2_super *osb,
 
        mutex_lock(&orphan_dir_inode->i_mutex);
 
-       status = ocfs2_meta_lock(orphan_dir_inode, &orphan_dir_bh, 1);
+       status = ocfs2_inode_lock(orphan_dir_inode, &orphan_dir_bh, 1);
        if (status < 0) {
                mlog_errno(status);
                goto leave;
@@ -2158,7 +1858,7 @@ static int ocfs2_prepare_orphan_dir(struct ocfs2_super *osb,
                                              orphan_dir_bh, name,
                                              OCFS2_ORPHAN_NAMELEN, de_bh);
        if (status < 0) {
-               ocfs2_meta_unlock(orphan_dir_inode, 1);
+               ocfs2_inode_unlock(orphan_dir_inode, 1);
 
                mlog_errno(status);
                goto leave;
@@ -2172,8 +1872,7 @@ leave:
                iput(orphan_dir_inode);
        }
 
-       if (orphan_dir_bh)
-               brelse(orphan_dir_bh);
+       brelse(orphan_dir_bh);
 
        mlog_exit(status);
        return status;
@@ -2193,17 +1892,14 @@ static int ocfs2_orphan_add(struct ocfs2_super *osb,
 
        mlog_entry("(inode->i_ino = %lu)\n", inode->i_ino);
 
-       status = ocfs2_read_block(osb,
-                                 OCFS2_I(orphan_dir_inode)->ip_blkno,
-                                 &orphan_dir_bh, OCFS2_BH_CACHED,
-                                 orphan_dir_inode);
+       status = ocfs2_read_inode_block(orphan_dir_inode, &orphan_dir_bh);
        if (status < 0) {
                mlog_errno(status);
                goto leave;
        }
 
-       status = ocfs2_journal_access(handle, orphan_dir_inode, orphan_dir_bh,
-                                     OCFS2_JOURNAL_ACCESS_WRITE);
+       status = ocfs2_journal_access_di(handle, orphan_dir_inode, orphan_dir_bh,
+                                        OCFS2_JOURNAL_ACCESS_WRITE);
        if (status < 0) {
                mlog_errno(status);
                goto leave;
@@ -2242,8 +1938,7 @@ static int ocfs2_orphan_add(struct ocfs2_super *osb,
             (unsigned long long)OCFS2_I(inode)->ip_blkno, osb->slot_num);
 
 leave:
-       if (orphan_dir_bh)
-               brelse(orphan_dir_bh);
+       brelse(orphan_dir_bh);
 
        mlog_exit(status);
        return status;
@@ -2291,8 +1986,8 @@ int ocfs2_orphan_del(struct ocfs2_super *osb,
                goto leave;
        }
 
-       status = ocfs2_journal_access(handle,orphan_dir_inode,  orphan_dir_bh,
-                                     OCFS2_JOURNAL_ACCESS_WRITE);
+       status = ocfs2_journal_access_di(handle,orphan_dir_inode,  orphan_dir_bh,
+                                        OCFS2_JOURNAL_ACCESS_WRITE);
        if (status < 0) {
                mlog_errno(status);
                goto leave;
@@ -2311,8 +2006,7 @@ int ocfs2_orphan_del(struct ocfs2_super *osb,
        }
 
 leave:
-       if (target_de_bh)
-               brelse(target_de_bh);
+       brelse(target_de_bh);
 
        mlog_exit(status);
        return status;
@@ -2331,4 +2025,8 @@ const struct inode_operations ocfs2_dir_iops = {
        .setattr        = ocfs2_setattr,
        .getattr        = ocfs2_getattr,
        .permission     = ocfs2_permission,
+       .setxattr       = generic_setxattr,
+       .getxattr       = generic_getxattr,
+       .listxattr      = ocfs2_listxattr,
+       .removexattr    = generic_removexattr,
 };