tty: gigaset: really fix chars_in_buffer
[safe/jmp/linux-2.6] / fs / ocfs2 / namei.c
index e5fc934..8601f93 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 "sysfile.h"
 #include "uptodate.h"
 #include "xattr.h"
+#include "acl.h"
 
 #include "buffer_head_io.h"
 
 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_prepare_orphan_dir(struct ocfs2_super *osb,
                                    struct inode **ret_orphan_dir,
                                    struct inode *inode,
                                    char *name,
-                                   struct buffer_head **de_bh);
+                                   struct ocfs2_dir_lookup_result *lookup);
 
 static int ocfs2_orphan_add(struct ocfs2_super *osb,
                            handle_t *handle,
                            struct inode *inode,
                            struct ocfs2_dinode *fe,
                            char *name,
-                           struct buffer_head *de_bh,
+                           struct ocfs2_dir_lookup_result *lookup,
                            struct inode *orphan_dir_inode);
 
 static int ocfs2_create_symlink_data(struct ocfs2_super *osb,
@@ -116,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_inode_lock(dir, NULL, 0);
+       status = ocfs2_inode_lock_nested(dir, NULL, 0, OI_LS_PARENT);
        if (status < 0) {
                if (status != -ENOENT)
                        mlog_errno(status);
@@ -186,6 +188,35 @@ bail:
        return ret;
 }
 
+static struct inode *ocfs2_get_init_inode(struct inode *dir, int mode)
+{
+       struct inode *inode;
+
+       inode = new_inode(dir->i_sb);
+       if (!inode) {
+               mlog(ML_ERROR, "new_inode failed!\n");
+               return NULL;
+       }
+
+       /* 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,
                       struct dentry *dentry,
                       int mode,
@@ -197,10 +228,18 @@ static int ocfs2_mknod(struct inode *dir,
        struct ocfs2_super *osb;
        struct ocfs2_dinode *dirfe;
        struct buffer_head *new_fe_bh = NULL;
-       struct buffer_head *de_bh = NULL;
        struct inode *inode = NULL;
        struct ocfs2_alloc_context *inode_ac = NULL;
        struct ocfs2_alloc_context *data_ac = NULL;
+       struct ocfs2_alloc_context *meta_ac = NULL;
+       int want_clusters = 0;
+       int want_meta = 0;
+       int xattr_credits = 0;
+       struct ocfs2_security_xattr_info si = {
+               .enable = 1,
+       };
+       int did_quota_inode = 0;
+       struct ocfs2_dir_lookup_result lookup = { NULL, };
 
        mlog_entry("(0x%p, 0x%p, %d, %lu, '%.*s')\n", dir, dentry, mode,
                   (unsigned long)dev, dentry->d_name.len,
@@ -216,13 +255,13 @@ static int ocfs2_mknod(struct inode *dir,
                return status;
        }
 
-       if (S_ISDIR(mode) && (dir->i_nlink >= OCFS2_LINK_MAX)) {
+       if (S_ISDIR(mode) && (dir->i_nlink >= ocfs2_link_max(osb))) {
                status = -EMLINK;
                goto leave;
        }
 
        dirfe = (struct ocfs2_dinode *) parent_fe_bh->b_data;
-       if (!dirfe->i_links_count) {
+       if (!ocfs2_read_links_count(dirfe)) {
                /* can't make a file in a deleted directory. */
                status = -ENOENT;
                goto leave;
@@ -236,7 +275,7 @@ static int ocfs2_mknod(struct inode *dir,
        /* get a spot inside the dir. */
        status = ocfs2_prepare_dir_for_insert(osb, dir, parent_fe_bh,
                                              dentry->d_name.name,
-                                             dentry->d_name.len, &de_bh);
+                                             dentry->d_name.len, &lookup);
        if (status < 0) {
                mlog_errno(status);
                goto leave;
@@ -250,17 +289,59 @@ static int ocfs2_mknod(struct inode *dir,
                goto leave;
        }
 
-       /* Reserve a cluster if creating an extent based directory. */
-       if (S_ISDIR(mode) && !ocfs2_supports_inline_data(osb)) {
-               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, &want_meta);
+       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;
+
+               /* Dir indexing requires extra space as well */
+               if (ocfs2_supports_indexed_dirs(osb))
+                       want_meta++;
+       }
+
+       status = ocfs2_reserve_new_metadata_blocks(osb, want_meta, &meta_ac);
+       if (status < 0) {
+               if (status != -ENOSPC)
+                       mlog_errno(status);
+               goto leave;
+       }
+
+       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,
+                                                           S_ISDIR(mode),
+                                                           xattr_credits));
        if (IS_ERR(handle)) {
                status = PTR_ERR(handle);
                handle = NULL;
@@ -268,10 +349,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;
@@ -279,19 +369,19 @@ static int ocfs2_mknod(struct inode *dir,
 
        if (S_ISDIR(mode)) {
                status = ocfs2_fill_new_dir(osb, handle, dir, inode,
-                                           new_fe_bh, data_ac);
+                                           new_fe_bh, data_ac, meta_ac);
                if (status < 0) {
                        mlog_errno(status);
                        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;
                }
-               le16_add_cpu(&dirfe->i_links_count, 1);
+               ocfs2_add_links_count(dirfe, 1);
                status = ocfs2_journal_dirty(handle, parent_fe_bh);
                if (status < 0) {
                        mlog_errno(status);
@@ -300,9 +390,25 @@ static int ocfs2_mknod(struct inode *dir,
                inc_nlink(dir);
        }
 
+       status = ocfs2_init_acl(handle, inode, dir, new_fe_bh, parent_fe_bh,
+                               meta_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,
+                                                meta_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);
+                                &lookup);
        if (status < 0) {
                mlog_errno(status);
                goto leave;
@@ -320,6 +426,8 @@ 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);
 
@@ -329,11 +437,16 @@ leave:
                mlog(0, "Disk is full\n");
 
        brelse(new_fe_bh);
-       brelse(de_bh);
        brelse(parent_fe_bh);
+       kfree(si.name);
+       kfree(si.value);
 
-       if ((status < 0) && inode)
+       ocfs2_free_dir_lookup_result(&lookup);
+
+       if ((status < 0) && inode) {
+               clear_nlink(inode);
                iput(inode);
+       }
 
        if (inode_ac)
                ocfs2_free_alloc_context(inode_ac);
@@ -341,6 +454,9 @@ leave:
        if (data_ac)
                ocfs2_free_alloc_context(data_ac);
 
+       if (meta_ac)
+               ocfs2_free_alloc_context(meta_ac);
+
        mlog_exit(status);
 
        return status;
@@ -348,12 +464,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;
@@ -361,39 +477,26 @@ 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;
+       u16 feat;
 
-       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);
+       status = ocfs2_claim_new_inode(osb, handle, dir, parent_fe_bh,
+                                      inode_ac, &suballoc_bit, &fe_blkno);
        if (status < 0) {
                mlog_errno(status);
                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);
@@ -406,8 +509,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;
@@ -421,18 +524,13 @@ static int ocfs2_mknod_locked(struct ocfs2_super *osb,
        fe->i_blkno = cpu_to_le64(fe_blkno);
        fe->i_suballoc_bit = cpu_to_le16(suballoc_bit);
        fe->i_suballoc_slot = cpu_to_le16(inode_ac->ac_alloc_slot);
-       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_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);
+       ocfs2_set_links_count(fe, inode->i_nlink);
 
        fe->i_last_eb_blk = 0;
        strcpy(fe->i_signature, OCFS2_INODE_SIGNATURE);
@@ -444,14 +542,15 @@ static int ocfs2_mknod_locked(struct ocfs2_super *osb,
        fe->i_dtime = 0;
 
        /*
-        * If supported, directories start with inline data.
+        * If supported, directories start with inline data. If inline
+        * isn't supported, but indexing is, we start them as indexed.
         */
-       if (S_ISDIR(mode) && ocfs2_supports_inline_data(osb)) {
-               u16 feat = le16_to_cpu(fe->i_dyn_features);
-
+       feat = le16_to_cpu(fe->i_dyn_features);
+       if (S_ISDIR(inode->i_mode) && ocfs2_supports_inline_data(osb)) {
                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));
+               fe->id2.i_data.id_count = cpu_to_le16(
+                               ocfs2_max_inline_data_with_xattr(osb->sb, fe));
        } else {
                fel = &fe->id2.i_list;
                fel->l_tree_depth = 0;
@@ -465,15 +564,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);
@@ -484,15 +575,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);
@@ -537,9 +625,9 @@ static int ocfs2_link(struct dentry *old_dentry,
        int err;
        struct buffer_head *fe_bh = NULL;
        struct buffer_head *parent_fe_bh = NULL;
-       struct buffer_head *de_bh = NULL;
        struct ocfs2_dinode *fe = NULL;
        struct ocfs2_super *osb = OCFS2_SB(dir->i_sb);
+       struct ocfs2_dir_lookup_result lookup = { NULL, };
 
        mlog_entry("(inode=%lu, old='%.*s' new='%.*s')\n", inode->i_ino,
                   old_dentry->d_name.len, old_dentry->d_name.name,
@@ -548,7 +636,7 @@ static int ocfs2_link(struct dentry *old_dentry,
        if (S_ISDIR(inode->i_mode))
                return -EPERM;
 
-       err = ocfs2_inode_lock(dir, &parent_fe_bh, 1);
+       err = ocfs2_inode_lock_nested(dir, &parent_fe_bh, 1, OI_LS_PARENT);
        if (err < 0) {
                if (err != -ENOENT)
                        mlog_errno(err);
@@ -567,7 +655,7 @@ static int ocfs2_link(struct dentry *old_dentry,
 
        err = ocfs2_prepare_dir_for_insert(osb, dir, parent_fe_bh,
                                           dentry->d_name.name,
-                                          dentry->d_name.len, &de_bh);
+                                          dentry->d_name.len, &lookup);
        if (err < 0) {
                mlog_errno(err);
                goto out;
@@ -581,12 +669,12 @@ static int ocfs2_link(struct dentry *old_dentry,
        }
 
        fe = (struct ocfs2_dinode *) fe_bh->b_data;
-       if (le16_to_cpu(fe->i_links_count) >= OCFS2_LINK_MAX) {
+       if (ocfs2_read_links_count(fe) >= ocfs2_link_max(osb)) {
                err = -EMLINK;
                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;
@@ -594,8 +682,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;
@@ -603,13 +691,13 @@ static int ocfs2_link(struct dentry *old_dentry,
 
        inc_nlink(inode);
        inode->i_ctime = CURRENT_TIME;
-       fe->i_links_count = cpu_to_le16(inode->i_nlink);
+       ocfs2_set_links_count(fe, inode->i_nlink);
        fe->i_ctime = cpu_to_le64(inode->i_ctime.tv_sec);
        fe->i_ctime_nsec = cpu_to_le32(inode->i_ctime.tv_nsec);
 
        err = ocfs2_journal_dirty(handle, fe_bh);
        if (err < 0) {
-               le16_add_cpu(&fe->i_links_count, -1);
+               ocfs2_add_links_count(fe, -1);
                drop_nlink(inode);
                mlog_errno(err);
                goto out_commit;
@@ -617,9 +705,9 @@ static int ocfs2_link(struct dentry *old_dentry,
 
        err = ocfs2_add_entry(handle, dentry, inode,
                              OCFS2_I(inode)->ip_blkno,
-                             parent_fe_bh, de_bh);
+                             parent_fe_bh, &lookup);
        if (err) {
-               le16_add_cpu(&fe->i_links_count, -1);
+               ocfs2_add_links_count(fe, -1);
                drop_nlink(inode);
                mlog_errno(err);
                goto out_commit;
@@ -643,10 +731,11 @@ out_unlock_inode:
 out:
        ocfs2_inode_unlock(dir, 1);
 
-       brelse(de_bh);
        brelse(fe_bh);
        brelse(parent_fe_bh);
 
+       ocfs2_free_dir_lookup_result(&lookup);
+
        mlog_exit(err);
 
        return err;
@@ -695,10 +784,9 @@ static int ocfs2_unlink(struct inode *dir,
        struct buffer_head *fe_bh = NULL;
        struct buffer_head *parent_node_bh = NULL;
        handle_t *handle = NULL;
-       struct ocfs2_dir_entry *dirent = NULL;
-       struct buffer_head *dirent_bh = NULL;
        char orphan_name[OCFS2_ORPHAN_NAMELEN + 1];
-       struct buffer_head *orphan_entry_bh = NULL;
+       struct ocfs2_dir_lookup_result lookup = { NULL, };
+       struct ocfs2_dir_lookup_result orphan_insert = { NULL, };
 
        mlog_entry("(0x%p, 0x%p, '%.*s')\n", dir, dentry,
                   dentry->d_name.len, dentry->d_name.name);
@@ -712,7 +800,8 @@ static int ocfs2_unlink(struct inode *dir,
                return -EPERM;
        }
 
-       status = ocfs2_inode_lock(dir, &parent_node_bh, 1);
+       status = ocfs2_inode_lock_nested(dir, &parent_node_bh, 1,
+                                        OI_LS_PARENT);
        if (status < 0) {
                if (status != -ENOENT)
                        mlog_errno(status);
@@ -720,8 +809,8 @@ static int ocfs2_unlink(struct inode *dir,
        }
 
        status = ocfs2_find_files_on_disk(dentry->d_name.name,
-                                         dentry->d_name.len, &blkno,
-                                         dir, &dirent_bh, &dirent);
+                                         dentry->d_name.len, &blkno, dir,
+                                         &lookup);
        if (status < 0) {
                if (status != -ENOENT)
                        mlog_errno(status);
@@ -746,10 +835,7 @@ static int ocfs2_unlink(struct inode *dir,
        child_locked = 1;
 
        if (S_ISDIR(inode->i_mode)) {
-               if (!ocfs2_empty_dir(inode)) {
-                       status = -ENOTEMPTY;
-                       goto leave;
-               } else if (inode->i_nlink != 2) {
+               if (inode->i_nlink != 2 || !ocfs2_empty_dir(inode)) {
                        status = -ENOTEMPTY;
                        goto leave;
                }
@@ -765,15 +851,14 @@ static int ocfs2_unlink(struct inode *dir,
 
        if (inode_is_unlinkable(inode)) {
                status = ocfs2_prepare_orphan_dir(osb, &orphan_dir, inode,
-                                                 orphan_name,
-                                                 &orphan_entry_bh);
+                                                 orphan_name, &orphan_insert);
                if (status < 0) {
                        mlog_errno(status);
                        goto leave;
                }
        }
 
-       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;
@@ -781,8 +866,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;
@@ -792,7 +877,7 @@ static int ocfs2_unlink(struct inode *dir,
 
        if (inode_is_unlinkable(inode)) {
                status = ocfs2_orphan_add(osb, handle, inode, fe, orphan_name,
-                                         orphan_entry_bh, orphan_dir);
+                                         &orphan_insert, orphan_dir);
                if (status < 0) {
                        mlog_errno(status);
                        goto leave;
@@ -800,7 +885,7 @@ static int ocfs2_unlink(struct inode *dir,
        }
 
        /* delete the name from the parent dir */
-       status = ocfs2_delete_entry(handle, dir, dirent, dirent_bh);
+       status = ocfs2_delete_entry(handle, dir, &lookup);
        if (status < 0) {
                mlog_errno(status);
                goto leave;
@@ -809,7 +894,7 @@ static int ocfs2_unlink(struct inode *dir,
        if (S_ISDIR(inode->i_mode))
                drop_nlink(inode);
        drop_nlink(inode);
-       fe->i_links_count = cpu_to_le16(inode->i_nlink);
+       ocfs2_set_links_count(fe, inode->i_nlink);
 
        status = ocfs2_journal_dirty(handle, fe_bh);
        if (status < 0) {
@@ -845,9 +930,10 @@ leave:
        }
 
        brelse(fe_bh);
-       brelse(dirent_bh);
        brelse(parent_node_bh);
-       brelse(orphan_entry_bh);
+
+       ocfs2_free_dir_lookup_result(&orphan_insert);
+       ocfs2_free_dir_lookup_result(&lookup);
 
        mlog_exit(status);
 
@@ -893,7 +979,8 @@ static int ocfs2_double_lock(struct ocfs2_super *osb,
                        inode1 = tmpinode;
                }
                /* lock id2 */
-               status = ocfs2_inode_lock(inode2, bh2, 1);
+               status = ocfs2_inode_lock_nested(inode2, bh2, 1,
+                                                OI_LS_RENAME1);
                if (status < 0) {
                        if (status != -ENOENT)
                                mlog_errno(status);
@@ -902,7 +989,7 @@ static int ocfs2_double_lock(struct ocfs2_super *osb,
        }
 
        /* lock id1 */
-       status = ocfs2_inode_lock(inode1, bh1, 1);
+       status = ocfs2_inode_lock_nested(inode1, bh1, 1, OI_LS_RENAME2);
        if (status < 0) {
                /*
                 * An error return must mean that no cluster locks
@@ -933,29 +1020,27 @@ static int ocfs2_rename(struct inode *old_dir,
                        struct inode *new_dir,
                        struct dentry *new_dentry)
 {
-       int status = 0, rename_lock = 0, parents_locked = 0;
-       int old_child_locked = 0, new_child_locked = 0;
+       int status = 0, rename_lock = 0, parents_locked = 0, target_exists = 0;
+       int old_child_locked = 0, new_child_locked = 0, update_dot_dot = 0;
        struct inode *old_inode = old_dentry->d_inode;
        struct inode *new_inode = new_dentry->d_inode;
        struct inode *orphan_dir = NULL;
        struct ocfs2_dinode *newfe = NULL;
        char orphan_name[OCFS2_ORPHAN_NAMELEN + 1];
-       struct buffer_head *orphan_entry_bh = NULL;
        struct buffer_head *newfe_bh = NULL;
        struct buffer_head *old_inode_bh = NULL;
-       struct buffer_head *insert_entry_bh = NULL;
        struct ocfs2_super *osb = NULL;
        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_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
        nlink_t old_dir_nlink = old_dir->i_nlink;
        struct ocfs2_dinode *old_di;
+       struct ocfs2_dir_lookup_result old_inode_dot_dot_res = { NULL, };
+       struct ocfs2_dir_lookup_result target_lookup_res = { NULL, };
+       struct ocfs2_dir_lookup_result old_entry_lookup = { NULL, };
+       struct ocfs2_dir_lookup_result orphan_insert = { NULL, };
+       struct ocfs2_dir_lookup_result target_insert = { NULL, };
 
        /* At some point it might be nice to break this function up a
         * bit. */
@@ -1020,7 +1105,8 @@ static int ocfs2_rename(struct inode *old_dir,
         * won't have to concurrently downconvert the inode and the
         * dentry locks.
         */
-       status = ocfs2_inode_lock(old_inode, &old_inode_bh, 1);
+       status = ocfs2_inode_lock_nested(old_inode, &old_inode_bh, 1,
+                                        OI_LS_PARENT);
        if (status < 0) {
                if (status != -ENOENT)
                        mlog_errno(status);
@@ -1037,9 +1123,10 @@ static int ocfs2_rename(struct inode *old_dir,
        if (S_ISDIR(old_inode->i_mode)) {
                u64 old_inode_parent;
 
+               update_dot_dot = 1;
                status = ocfs2_find_files_on_disk("..", 2, &old_inode_parent,
-                                                 old_inode, &old_inode_de_bh,
-                                                 &old_inode_dot_dot_de);
+                                                 old_inode,
+                                                 &old_inode_dot_dot_res);
                if (status) {
                        status = -EIO;
                        goto bail;
@@ -1051,7 +1138,7 @@ static int ocfs2_rename(struct inode *old_dir,
                }
 
                if (!new_inode && new_dir != old_dir &&
-                   new_dir->i_nlink >= OCFS2_LINK_MAX) {
+                   new_dir->i_nlink >= ocfs2_link_max(osb)) {
                        status = -EMLINK;
                        goto bail;
                }
@@ -1080,8 +1167,8 @@ static int ocfs2_rename(struct inode *old_dir,
         * to delete it */
        status = ocfs2_find_files_on_disk(new_dentry->d_name.name,
                                          new_dentry->d_name.len,
-                                         &newfe_blkno, new_dir, &new_de_bh,
-                                         &new_de);
+                                         &newfe_blkno, new_dir,
+                                         &target_lookup_res);
        /* The only error we allow here is -ENOENT because the new
         * file not existing is perfectly valid. */
        if ((status < 0) && (status != -ENOENT)) {
@@ -1090,8 +1177,10 @@ static int ocfs2_rename(struct inode *old_dir,
                mlog_errno(status);
                goto bail;
        }
+       if (status == 0)
+               target_exists = 1;
 
-       if (!new_de && new_inode) {
+       if (!target_exists && new_inode) {
                /*
                 * Target was unlinked by another node while we were
                 * waiting to get to ocfs2_rename(). There isn't
@@ -1104,7 +1193,7 @@ static int ocfs2_rename(struct inode *old_dir,
 
        /* In case we need to overwrite an existing file, we blow it
         * away first */
-       if (new_de) {
+       if (target_exists) {
                /* VFS didn't think there existed an inode here, but
                 * someone else in the cluster must have raced our
                 * rename to create one. Today we error cleanly, in
@@ -1145,8 +1234,8 @@ static int ocfs2_rename(struct inode *old_dir,
 
                newfe = (struct ocfs2_dinode *) newfe_bh->b_data;
 
-               mlog(0, "aha rename over existing... new_de=%p new_blkno=%llu "
-                    "newfebh=%p bhblocknr=%llu\n", new_de,
+               mlog(0, "aha rename over existing... new_blkno=%llu "
+                    "newfebh=%p bhblocknr=%llu\n",
                     (unsigned long long)newfe_blkno, newfe_bh, newfe_bh ?
                     (unsigned long long)newfe_bh->b_blocknr : 0ULL);
 
@@ -1154,7 +1243,7 @@ static int ocfs2_rename(struct inode *old_dir,
                        status = ocfs2_prepare_orphan_dir(osb, &orphan_dir,
                                                          new_inode,
                                                          orphan_name,
-                                                         &orphan_entry_bh);
+                                                         &orphan_insert);
                        if (status < 0) {
                                mlog_errno(status);
                                goto bail;
@@ -1172,14 +1261,14 @@ static int ocfs2_rename(struct inode *old_dir,
                status = ocfs2_prepare_dir_for_insert(osb, new_dir, new_dir_bh,
                                                      new_dentry->d_name.name,
                                                      new_dentry->d_name.len,
-                                                     &insert_entry_bh);
+                                                     &target_insert);
                if (status < 0) {
                        mlog_errno(status);
                        goto bail;
                }
        }
 
-       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;
@@ -1187,26 +1276,26 @@ static int ocfs2_rename(struct inode *old_dir,
                goto bail;
        }
 
-       if (new_de) {
+       if (target_exists) {
                if (S_ISDIR(new_inode->i_mode)) {
-                       if (!ocfs2_empty_dir(new_inode) ||
-                           new_inode->i_nlink != 2) {
+                       if (new_inode->i_nlink != 2 ||
+                           !ocfs2_empty_dir(new_inode)) {
                                status = -ENOTEMPTY;
                                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;
                }
 
                if (S_ISDIR(new_inode->i_mode) ||
-                   (newfe->i_links_count == cpu_to_le16(1))){
+                   (ocfs2_read_links_count(newfe) == 1)) {
                        status = ocfs2_orphan_add(osb, handle, new_inode,
                                                  newfe, orphan_name,
-                                                 orphan_entry_bh, orphan_dir);
+                                                 &orphan_insert, orphan_dir);
                        if (status < 0) {
                                mlog_errno(status);
                                goto bail;
@@ -1214,8 +1303,8 @@ static int ocfs2_rename(struct inode *old_dir,
                }
 
                /* change the dirent to point to the correct inode */
-               status = ocfs2_update_entry(new_dir, handle, new_de_bh,
-                                           new_de, old_inode);
+               status = ocfs2_update_entry(new_dir, handle, &target_lookup_res,
+                                           old_inode);
                if (status < 0) {
                        mlog_errno(status);
                        goto bail;
@@ -1223,9 +1312,9 @@ static int ocfs2_rename(struct inode *old_dir,
                new_dir->i_version++;
 
                if (S_ISDIR(new_inode->i_mode))
-                       newfe->i_links_count = 0;
+                       ocfs2_set_links_count(newfe, 0);
                else
-                       le16_add_cpu(&newfe->i_links_count, -1);
+                       ocfs2_add_links_count(newfe, -1);
 
                status = ocfs2_journal_dirty(handle, newfe_bh);
                if (status < 0) {
@@ -1236,14 +1325,14 @@ static int ocfs2_rename(struct inode *old_dir,
                /* if the name was not found in new_dir, add it now */
                status = ocfs2_add_entry(handle, new_dentry, old_inode,
                                         OCFS2_I(old_inode)->ip_blkno,
-                                        new_dir_bh, insert_entry_bh);
+                                        new_dir_bh, &target_insert);
        }
 
        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;
 
@@ -1263,15 +1352,13 @@ static int ocfs2_rename(struct inode *old_dir,
         * 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;
+       status = ocfs2_find_entry(old_dentry->d_name.name,
+                                 old_dentry->d_name.len, old_dir,
+                                 &old_entry_lookup);
+       if (status)
                goto bail;
-       }
 
-       status = ocfs2_delete_entry(handle, old_dir, old_de, old_de_bh);
+       status = ocfs2_delete_entry(handle, old_dir, &old_entry_lookup);
        if (status < 0) {
                mlog_errno(status);
                goto bail;
@@ -1282,9 +1369,10 @@ static int ocfs2_rename(struct inode *old_dir,
                new_inode->i_ctime = CURRENT_TIME;
        }
        old_dir->i_ctime = old_dir->i_mtime = CURRENT_TIME;
-       if (old_inode_de_bh) {
-               status = ocfs2_update_entry(old_inode, handle, old_inode_de_bh,
-                                           old_inode_dot_dot_de, new_dir);
+
+       if (update_dot_dot) {
+               status = ocfs2_update_entry(old_inode, handle,
+                                           &old_inode_dot_dot_res, new_dir);
                old_dir->i_nlink--;
                if (new_inode) {
                        new_inode->i_nlink--;
@@ -1319,15 +1407,14 @@ 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,
+                       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);
+                       ocfs2_set_links_count(fe, old_dir->i_nlink);
                        status = ocfs2_journal_dirty(handle, old_dir_bh);
                }
        }
-
        ocfs2_dentry_move(old_dentry, new_dentry, old_dir, new_dir);
        status = 0;
 bail:
@@ -1358,15 +1445,17 @@ bail:
 
        if (new_inode)
                iput(new_inode);
+
+       ocfs2_free_dir_lookup_result(&target_lookup_res);
+       ocfs2_free_dir_lookup_result(&old_entry_lookup);
+       ocfs2_free_dir_lookup_result(&old_inode_dot_dot_res);
+       ocfs2_free_dir_lookup_result(&orphan_insert);
+       ocfs2_free_dir_lookup_result(&target_insert);
+
        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);
 
@@ -1487,13 +1576,20 @@ static int ocfs2_symlink(struct inode *dir,
        struct inode *inode = NULL;
        struct super_block *sb;
        struct buffer_head *new_fe_bh = NULL;
-       struct buffer_head *de_bh = NULL;
        struct buffer_head *parent_fe_bh = NULL;
        struct ocfs2_dinode *fe = NULL;
        struct ocfs2_dinode *dirfe;
        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;
+       struct ocfs2_dir_lookup_result lookup = { NULL, };
 
        mlog_entry("(0x%p, 0x%p, symname='%s' actual='%.*s')\n", dir,
                   dentry, symname, dentry->d_name.len, dentry->d_name.name);
@@ -1514,7 +1610,7 @@ static int ocfs2_symlink(struct inode *dir,
        }
 
        dirfe = (struct ocfs2_dinode *) parent_fe_bh->b_data;
-       if (!dirfe->i_links_count) {
+       if (!ocfs2_read_links_count(dirfe)) {
                /* can't make a file in a deleted directory. */
                status = -ENOENT;
                goto bail;
@@ -1527,7 +1623,7 @@ static int ocfs2_symlink(struct inode *dir,
 
        status = ocfs2_prepare_dir_for_insert(osb, dir, parent_fe_bh,
                                              dentry->d_name.name,
-                                             dentry->d_name.len, &de_bh);
+                                             dentry->d_name.len, &lookup);
        if (status < 0) {
                mlog_errno(status);
                goto bail;
@@ -1540,17 +1636,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;
@@ -1558,10 +1683,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;
@@ -1574,6 +1707,12 @@ static int ocfs2_symlink(struct inode *dir,
                u32 offset = 0;
 
                inode->i_op = &ocfs2_symlink_inode_operations;
+               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,
@@ -1612,9 +1751,18 @@ 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);
+                                &lookup);
        if (status < 0) {
                mlog_errno(status);
                goto bail;
@@ -1630,6 +1778,11 @@ 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);
 
@@ -1637,13 +1790,19 @@ bail:
 
        brelse(new_fe_bh);
        brelse(parent_fe_bh);
-       brelse(de_bh);
+       kfree(si.name);
+       kfree(si.value);
+       ocfs2_free_dir_lookup_result(&lookup);
        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);
 
@@ -1685,7 +1844,7 @@ static int ocfs2_prepare_orphan_dir(struct ocfs2_super *osb,
                                    struct inode **ret_orphan_dir,
                                    struct inode *inode,
                                    char *name,
-                                   struct buffer_head **de_bh)
+                                   struct ocfs2_dir_lookup_result *lookup)
 {
        struct inode *orphan_dir_inode;
        struct buffer_head *orphan_dir_bh = NULL;
@@ -1716,7 +1875,7 @@ static int ocfs2_prepare_orphan_dir(struct ocfs2_super *osb,
 
        status = ocfs2_prepare_dir_for_insert(osb, orphan_dir_inode,
                                              orphan_dir_bh, name,
-                                             OCFS2_ORPHAN_NAMELEN, de_bh);
+                                             OCFS2_ORPHAN_NAMELEN, lookup);
        if (status < 0) {
                ocfs2_inode_unlock(orphan_dir_inode, 1);
 
@@ -1743,7 +1902,7 @@ static int ocfs2_orphan_add(struct ocfs2_super *osb,
                            struct inode *inode,
                            struct ocfs2_dinode *fe,
                            char *name,
-                           struct buffer_head *de_bh,
+                           struct ocfs2_dir_lookup_result *lookup,
                            struct inode *orphan_dir_inode)
 {
        struct buffer_head *orphan_dir_bh = NULL;
@@ -1752,16 +1911,14 @@ static int ocfs2_orphan_add(struct ocfs2_super *osb,
 
        mlog_entry("(inode->i_ino = %lu)\n", inode->i_ino);
 
-       status = ocfs2_read_block(orphan_dir_inode,
-                                 OCFS2_I(orphan_dir_inode)->ip_blkno,
-                                 &orphan_dir_bh, OCFS2_BH_CACHED);
+       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;
@@ -1771,8 +1928,8 @@ static int ocfs2_orphan_add(struct ocfs2_super *osb,
         * underneath us... */
        orphan_fe = (struct ocfs2_dinode *) orphan_dir_bh->b_data;
        if (S_ISDIR(inode->i_mode))
-               le16_add_cpu(&orphan_fe->i_links_count, 1);
-       orphan_dir_inode->i_nlink = le16_to_cpu(orphan_fe->i_links_count);
+               ocfs2_add_links_count(orphan_fe, 1);
+       orphan_dir_inode->i_nlink = ocfs2_read_links_count(orphan_fe);
 
        status = ocfs2_journal_dirty(handle, orphan_dir_bh);
        if (status < 0) {
@@ -1783,7 +1940,7 @@ static int ocfs2_orphan_add(struct ocfs2_super *osb,
        status = __ocfs2_add_entry(handle, orphan_dir_inode, name,
                                   OCFS2_ORPHAN_NAMELEN, inode,
                                   OCFS2_I(inode)->ip_blkno,
-                                  orphan_dir_bh, de_bh);
+                                  orphan_dir_bh, lookup);
        if (status < 0) {
                mlog_errno(status);
                goto leave;
@@ -1816,8 +1973,7 @@ int ocfs2_orphan_del(struct ocfs2_super *osb,
        char name[OCFS2_ORPHAN_NAMELEN + 1];
        struct ocfs2_dinode *orphan_fe;
        int status = 0;
-       struct buffer_head *target_de_bh = NULL;
-       struct ocfs2_dir_entry *target_de = NULL;
+       struct ocfs2_dir_lookup_result lookup = { NULL, };
 
        mlog_entry_void();
 
@@ -1832,24 +1988,22 @@ int ocfs2_orphan_del(struct ocfs2_super *osb,
             OCFS2_ORPHAN_NAMELEN);
 
        /* find it's spot in the orphan directory */
-       target_de_bh = ocfs2_find_entry(name, OCFS2_ORPHAN_NAMELEN,
-                                       orphan_dir_inode, &target_de);
-       if (!target_de_bh) {
-               status = -ENOENT;
+       status = ocfs2_find_entry(name, OCFS2_ORPHAN_NAMELEN, orphan_dir_inode,
+                                 &lookup);
+       if (status) {
                mlog_errno(status);
                goto leave;
        }
 
        /* remove it from the orphan directory */
-       status = ocfs2_delete_entry(handle, orphan_dir_inode, target_de,
-                                   target_de_bh);
+       status = ocfs2_delete_entry(handle, orphan_dir_inode, &lookup);
        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;
@@ -1858,8 +2012,8 @@ int ocfs2_orphan_del(struct ocfs2_super *osb,
        /* do the i_nlink dance! :) */
        orphan_fe = (struct ocfs2_dinode *) orphan_dir_bh->b_data;
        if (S_ISDIR(inode->i_mode))
-               le16_add_cpu(&orphan_fe->i_links_count, -1);
-       orphan_dir_inode->i_nlink = le16_to_cpu(orphan_fe->i_links_count);
+               ocfs2_add_links_count(orphan_fe, -1);
+       orphan_dir_inode->i_nlink = ocfs2_read_links_count(orphan_fe);
 
        status = ocfs2_journal_dirty(handle, orphan_dir_bh);
        if (status < 0) {
@@ -1868,7 +2022,7 @@ int ocfs2_orphan_del(struct ocfs2_super *osb,
        }
 
 leave:
-       brelse(target_de_bh);
+       ocfs2_free_dir_lookup_result(&lookup);
 
        mlog_exit(status);
        return status;