ocfs2: Access and dirty the buffer_head in mark_written.
[safe/jmp/linux-2.6] / fs / ocfs2 / alloc.c
index 69d67ab..3a9e5de 100644 (file)
@@ -28,6 +28,7 @@
 #include <linux/slab.h>
 #include <linux/highmem.h>
 #include <linux/swap.h>
+#include <linux/quotaops.h>
 
 #define MLOG_MASK_PREFIX ML_DISK_ALLOC
 #include <cluster/masklog.h>
@@ -36,6 +37,7 @@
 
 #include "alloc.h"
 #include "aops.h"
+#include "blockcheck.h"
 #include "dlmglue.h"
 #include "extent_map.h"
 #include "inode.h"
@@ -46,6 +48,7 @@
 #include "file.h"
 #include "super.h"
 #include "uptodate.h"
+#include "xattr.h"
 
 #include "buffer_head_io.h"
 
@@ -205,36 +208,33 @@ static void ocfs2_dinode_fill_root_el(struct ocfs2_extent_tree *et)
 
 static void ocfs2_xattr_value_fill_root_el(struct ocfs2_extent_tree *et)
 {
-       struct ocfs2_xattr_value_root *xv = et->et_object;
+       struct ocfs2_xattr_value_buf *vb = et->et_object;
 
-       et->et_root_el = &xv->xr_list;
+       et->et_root_el = &vb->vb_xv->xr_list;
 }
 
 static void ocfs2_xattr_value_set_last_eb_blk(struct ocfs2_extent_tree *et,
                                              u64 blkno)
 {
-       struct ocfs2_xattr_value_root *xv =
-               (struct ocfs2_xattr_value_root *)et->et_object;
+       struct ocfs2_xattr_value_buf *vb = et->et_object;
 
-       xv->xr_last_eb_blk = cpu_to_le64(blkno);
+       vb->vb_xv->xr_last_eb_blk = cpu_to_le64(blkno);
 }
 
 static u64 ocfs2_xattr_value_get_last_eb_blk(struct ocfs2_extent_tree *et)
 {
-       struct ocfs2_xattr_value_root *xv =
-               (struct ocfs2_xattr_value_root *) et->et_object;
+       struct ocfs2_xattr_value_buf *vb = et->et_object;
 
-       return le64_to_cpu(xv->xr_last_eb_blk);
+       return le64_to_cpu(vb->vb_xv->xr_last_eb_blk);
 }
 
 static void ocfs2_xattr_value_update_clusters(struct inode *inode,
                                              struct ocfs2_extent_tree *et,
                                              u32 clusters)
 {
-       struct ocfs2_xattr_value_root *xv =
-               (struct ocfs2_xattr_value_root *)et->et_object;
+       struct ocfs2_xattr_value_buf *vb = et->et_object;
 
-       le32_add_cpu(&xv->xr_clusters, clusters);
+       le32_add_cpu(&vb->vb_xv->xr_clusters, clusters);
 }
 
 static struct ocfs2_extent_tree_operations ocfs2_xattr_value_et_ops = {
@@ -296,11 +296,13 @@ static struct ocfs2_extent_tree_operations ocfs2_xattr_tree_et_ops = {
 static void __ocfs2_init_extent_tree(struct ocfs2_extent_tree *et,
                                     struct inode *inode,
                                     struct buffer_head *bh,
+                                    ocfs2_journal_access_func access,
                                     void *obj,
                                     struct ocfs2_extent_tree_operations *ops)
 {
        et->et_ops = ops;
        et->et_root_bh = bh;
+       et->et_root_journal_access = access;
        if (!obj)
                obj = (void *)bh->b_data;
        et->et_object = obj;
@@ -316,23 +318,23 @@ void ocfs2_init_dinode_extent_tree(struct ocfs2_extent_tree *et,
                                   struct inode *inode,
                                   struct buffer_head *bh)
 {
-       __ocfs2_init_extent_tree(et, inode, bh, NULL, &ocfs2_dinode_et_ops);
+       __ocfs2_init_extent_tree(et, inode, bh, ocfs2_journal_access_di,
+                                NULL, &ocfs2_dinode_et_ops);
 }
 
 void ocfs2_init_xattr_tree_extent_tree(struct ocfs2_extent_tree *et,
                                       struct inode *inode,
                                       struct buffer_head *bh)
 {
-       __ocfs2_init_extent_tree(et, inode, bh, NULL,
-                                &ocfs2_xattr_tree_et_ops);
+       __ocfs2_init_extent_tree(et, inode, bh, ocfs2_journal_access_xb,
+                                NULL, &ocfs2_xattr_tree_et_ops);
 }
 
 void ocfs2_init_xattr_value_extent_tree(struct ocfs2_extent_tree *et,
                                        struct inode *inode,
-                                       struct buffer_head *bh,
-                                       struct ocfs2_xattr_value_root *xv)
+                                       struct ocfs2_xattr_value_buf *vb)
 {
-       __ocfs2_init_extent_tree(et, inode, bh, xv,
+       __ocfs2_init_extent_tree(et, inode, vb->vb_bh, vb->vb_access, vb,
                                 &ocfs2_xattr_value_et_ops);
 }
 
@@ -354,6 +356,15 @@ static inline void ocfs2_et_update_clusters(struct inode *inode,
        et->et_ops->eo_update_clusters(inode, et, clusters);
 }
 
+static inline int ocfs2_et_root_journal_access(handle_t *handle,
+                                              struct inode *inode,
+                                              struct ocfs2_extent_tree *et,
+                                              int type)
+{
+       return et->et_root_journal_access(handle, inode, et->et_root_bh,
+                                         type);
+}
+
 static inline int ocfs2_et_insert_check(struct inode *inode,
                                        struct ocfs2_extent_tree *et,
                                        struct ocfs2_extent_rec *rec)
@@ -394,12 +405,14 @@ struct ocfs2_path_item {
 #define OCFS2_MAX_PATH_DEPTH   5
 
 struct ocfs2_path {
-       int                     p_tree_depth;
-       struct ocfs2_path_item  p_node[OCFS2_MAX_PATH_DEPTH];
+       int                             p_tree_depth;
+       ocfs2_journal_access_func       p_root_access;
+       struct ocfs2_path_item          p_node[OCFS2_MAX_PATH_DEPTH];
 };
 
 #define path_root_bh(_path) ((_path)->p_node[0].bh)
 #define path_root_el(_path) ((_path)->p_node[0].el)
+#define path_root_access(_path)((_path)->p_root_access)
 #define path_leaf_bh(_path) ((_path)->p_node[(_path)->p_tree_depth].bh)
 #define path_leaf_el(_path) ((_path)->p_node[(_path)->p_tree_depth].el)
 #define path_num_items(_path) ((_path)->p_tree_depth + 1)
@@ -432,6 +445,8 @@ static void ocfs2_reinit_path(struct ocfs2_path *path, int keep_root)
         */
        if (keep_root)
                depth = le16_to_cpu(path_root_el(path)->l_tree_depth);
+       else
+               path_root_access(path) = NULL;
 
        path->p_tree_depth = depth;
 }
@@ -457,6 +472,7 @@ static void ocfs2_cp_path(struct ocfs2_path *dest, struct ocfs2_path *src)
 
        BUG_ON(path_root_bh(dest) != path_root_bh(src));
        BUG_ON(path_root_el(dest) != path_root_el(src));
+       BUG_ON(path_root_access(dest) != path_root_access(src));
 
        ocfs2_reinit_path(dest, 1);
 
@@ -478,6 +494,7 @@ static void ocfs2_mv_path(struct ocfs2_path *dest, struct ocfs2_path *src)
        int i;
 
        BUG_ON(path_root_bh(dest) != path_root_bh(src));
+       BUG_ON(path_root_access(dest) != path_root_access(src));
 
        for(i = 1; i < OCFS2_MAX_PATH_DEPTH; i++) {
                brelse(dest->p_node[i].bh);
@@ -513,7 +530,8 @@ static inline void ocfs2_path_insert_eb(struct ocfs2_path *path, int index,
 }
 
 static struct ocfs2_path *ocfs2_new_path(struct buffer_head *root_bh,
-                                        struct ocfs2_extent_list *root_el)
+                                        struct ocfs2_extent_list *root_el,
+                                        ocfs2_journal_access_func access)
 {
        struct ocfs2_path *path;
 
@@ -525,11 +543,48 @@ static struct ocfs2_path *ocfs2_new_path(struct buffer_head *root_bh,
                get_bh(root_bh);
                path_root_bh(path) = root_bh;
                path_root_el(path) = root_el;
+               path_root_access(path) = access;
        }
 
        return path;
 }
 
+static struct ocfs2_path *ocfs2_new_path_from_path(struct ocfs2_path *path)
+{
+       return ocfs2_new_path(path_root_bh(path), path_root_el(path),
+                             path_root_access(path));
+}
+
+static struct ocfs2_path *ocfs2_new_path_from_et(struct ocfs2_extent_tree *et)
+{
+       return ocfs2_new_path(et->et_root_bh, et->et_root_el,
+                             et->et_root_journal_access);
+}
+
+/*
+ * Journal the buffer at depth idx.  All idx>0 are extent_blocks,
+ * otherwise it's the root_access function.
+ *
+ * I don't like the way this function's name looks next to
+ * ocfs2_journal_access_path(), but I don't have a better one.
+ */
+static int ocfs2_path_bh_journal_access(handle_t *handle,
+                                       struct inode *inode,
+                                       struct ocfs2_path *path,
+                                       int idx)
+{
+       ocfs2_journal_access_func access = path_root_access(path);
+
+       if (!access)
+               access = ocfs2_journal_access;
+
+       if (idx)
+               access = ocfs2_journal_access_eb;
+
+       return access(handle, inode, path->p_node[idx].bh,
+                     OCFS2_JOURNAL_ACCESS_WRITE);
+}
+
 /*
  * Convenience function to journal all components in a path.
  */
@@ -542,8 +597,7 @@ static int ocfs2_journal_access_path(struct inode *inode, handle_t *handle,
                goto out;
 
        for(i = 0; i < path_num_items(path); i++) {
-               ret = ocfs2_journal_access(handle, inode, path->p_node[i].bh,
-                                          OCFS2_JOURNAL_ACCESS_WRITE);
+               ret = ocfs2_path_bh_journal_access(handle, inode, path, i);
                if (ret < 0) {
                        mlog_errno(ret);
                        goto out;
@@ -681,12 +735,31 @@ struct ocfs2_merge_ctxt {
 static int ocfs2_validate_extent_block(struct super_block *sb,
                                       struct buffer_head *bh)
 {
+       int rc;
        struct ocfs2_extent_block *eb =
                (struct ocfs2_extent_block *)bh->b_data;
 
        mlog(0, "Validating extent block %llu\n",
             (unsigned long long)bh->b_blocknr);
 
+       BUG_ON(!buffer_uptodate(bh));
+
+       /*
+        * If the ecc fails, we return the error but otherwise
+        * leave the filesystem running.  We know any error is
+        * local to this block.
+        */
+       rc = ocfs2_validate_meta_ecc(sb, bh->b_data, &eb->h_check);
+       if (rc) {
+               mlog(ML_ERROR, "Checksum failed for extent block %llu\n",
+                    (unsigned long long)bh->b_blocknr);
+               return rc;
+       }
+
+       /*
+        * Errors after here are fatal.
+        */
+
        if (!OCFS2_IS_VALID_EXTENT_BLOCK(eb)) {
                ocfs2_error(sb,
                            "Extent block #%llu has bad signature %.*s",
@@ -814,8 +887,8 @@ static int ocfs2_create_new_meta_bhs(struct ocfs2_super *osb,
                        }
                        ocfs2_set_new_buffer_uptodate(inode, bhs[i]);
 
-                       status = ocfs2_journal_access(handle, inode, bhs[i],
-                                                     OCFS2_JOURNAL_ACCESS_CREATE);
+                       status = ocfs2_journal_access_eb(handle, inode, bhs[i],
+                                                        OCFS2_JOURNAL_ACCESS_CREATE);
                        if (status < 0) {
                                mlog_errno(status);
                                goto bail;
@@ -958,8 +1031,8 @@ static int ocfs2_add_branch(struct ocfs2_super *osb,
                BUG_ON(!OCFS2_IS_VALID_EXTENT_BLOCK(eb));
                eb_el = &eb->h_list;
 
-               status = ocfs2_journal_access(handle, inode, bh,
-                                             OCFS2_JOURNAL_ACCESS_CREATE);
+               status = ocfs2_journal_access_eb(handle, inode, bh,
+                                                OCFS2_JOURNAL_ACCESS_CREATE);
                if (status < 0) {
                        mlog_errno(status);
                        goto bail;
@@ -998,21 +1071,21 @@ static int ocfs2_add_branch(struct ocfs2_super *osb,
         * journal_dirty erroring as it won't unless we've aborted the
         * handle (in which case we would never be here) so reserving
         * the write with journal_access is all we need to do. */
-       status = ocfs2_journal_access(handle, inode, *last_eb_bh,
-                                     OCFS2_JOURNAL_ACCESS_WRITE);
+       status = ocfs2_journal_access_eb(handle, inode, *last_eb_bh,
+                                        OCFS2_JOURNAL_ACCESS_WRITE);
        if (status < 0) {
                mlog_errno(status);
                goto bail;
        }
-       status = ocfs2_journal_access(handle, inode, et->et_root_bh,
-                                     OCFS2_JOURNAL_ACCESS_WRITE);
+       status = ocfs2_et_root_journal_access(handle, inode, et,
+                                             OCFS2_JOURNAL_ACCESS_WRITE);
        if (status < 0) {
                mlog_errno(status);
                goto bail;
        }
        if (eb_bh) {
-               status = ocfs2_journal_access(handle, inode, eb_bh,
-                                             OCFS2_JOURNAL_ACCESS_WRITE);
+               status = ocfs2_journal_access_eb(handle, inode, eb_bh,
+                                                OCFS2_JOURNAL_ACCESS_WRITE);
                if (status < 0) {
                        mlog_errno(status);
                        goto bail;
@@ -1101,8 +1174,8 @@ static int ocfs2_shift_tree_depth(struct ocfs2_super *osb,
        eb_el = &eb->h_list;
        root_el = et->et_root_el;
 
-       status = ocfs2_journal_access(handle, inode, new_eb_bh,
-                                     OCFS2_JOURNAL_ACCESS_CREATE);
+       status = ocfs2_journal_access_eb(handle, inode, new_eb_bh,
+                                        OCFS2_JOURNAL_ACCESS_CREATE);
        if (status < 0) {
                mlog_errno(status);
                goto bail;
@@ -1120,8 +1193,8 @@ static int ocfs2_shift_tree_depth(struct ocfs2_super *osb,
                goto bail;
        }
 
-       status = ocfs2_journal_access(handle, inode, et->et_root_bh,
-                                     OCFS2_JOURNAL_ACCESS_WRITE);
+       status = ocfs2_et_root_journal_access(handle, inode, et,
+                                             OCFS2_JOURNAL_ACCESS_WRITE);
        if (status < 0) {
                mlog_errno(status);
                goto bail;
@@ -1890,25 +1963,23 @@ static int ocfs2_rotate_subtree_right(struct inode *inode,
        root_bh = left_path->p_node[subtree_index].bh;
        BUG_ON(root_bh != right_path->p_node[subtree_index].bh);
 
-       ret = ocfs2_journal_access(handle, inode, root_bh,
-                                  OCFS2_JOURNAL_ACCESS_WRITE);
+       ret = ocfs2_path_bh_journal_access(handle, inode, right_path,
+                                          subtree_index);
        if (ret) {
                mlog_errno(ret);
                goto out;
        }
 
        for(i = subtree_index + 1; i < path_num_items(right_path); i++) {
-               ret = ocfs2_journal_access(handle, inode,
-                                          right_path->p_node[i].bh,
-                                          OCFS2_JOURNAL_ACCESS_WRITE);
+               ret = ocfs2_path_bh_journal_access(handle, inode,
+                                                  right_path, i);
                if (ret) {
                        mlog_errno(ret);
                        goto out;
                }
 
-               ret = ocfs2_journal_access(handle, inode,
-                                          left_path->p_node[i].bh,
-                                          OCFS2_JOURNAL_ACCESS_WRITE);
+               ret = ocfs2_path_bh_journal_access(handle, inode,
+                                                  left_path, i);
                if (ret) {
                        mlog_errno(ret);
                        goto out;
@@ -2132,8 +2203,7 @@ static int ocfs2_rotate_tree_right(struct inode *inode,
 
        *ret_left_path = NULL;
 
-       left_path = ocfs2_new_path(path_root_bh(right_path),
-                                  path_root_el(right_path));
+       left_path = ocfs2_new_path_from_path(right_path);
        if (!left_path) {
                ret = -ENOMEM;
                mlog_errno(ret);
@@ -2428,9 +2498,9 @@ static int ocfs2_rotate_subtree_left(struct inode *inode, handle_t *handle,
                        return -EAGAIN;
 
                if (le16_to_cpu(right_leaf_el->l_next_free_rec) > 1) {
-                       ret = ocfs2_journal_access(handle, inode,
-                                                  path_leaf_bh(right_path),
-                                                  OCFS2_JOURNAL_ACCESS_WRITE);
+                       ret = ocfs2_journal_access_eb(handle, inode,
+                                                     path_leaf_bh(right_path),
+                                                     OCFS2_JOURNAL_ACCESS_WRITE);
                        if (ret) {
                                mlog_errno(ret);
                                goto out;
@@ -2447,8 +2517,8 @@ static int ocfs2_rotate_subtree_left(struct inode *inode, handle_t *handle,
                 * We have to update i_last_eb_blk during the meta
                 * data delete.
                 */
-               ret = ocfs2_journal_access(handle, inode, et_root_bh,
-                                          OCFS2_JOURNAL_ACCESS_WRITE);
+               ret = ocfs2_et_root_journal_access(handle, inode, et,
+                                                  OCFS2_JOURNAL_ACCESS_WRITE);
                if (ret) {
                        mlog_errno(ret);
                        goto out;
@@ -2463,25 +2533,23 @@ static int ocfs2_rotate_subtree_left(struct inode *inode, handle_t *handle,
         */
        BUG_ON(right_has_empty && !del_right_subtree);
 
-       ret = ocfs2_journal_access(handle, inode, root_bh,
-                                  OCFS2_JOURNAL_ACCESS_WRITE);
+       ret = ocfs2_path_bh_journal_access(handle, inode, right_path,
+                                          subtree_index);
        if (ret) {
                mlog_errno(ret);
                goto out;
        }
 
        for(i = subtree_index + 1; i < path_num_items(right_path); i++) {
-               ret = ocfs2_journal_access(handle, inode,
-                                          right_path->p_node[i].bh,
-                                          OCFS2_JOURNAL_ACCESS_WRITE);
+               ret = ocfs2_path_bh_journal_access(handle, inode,
+                                                  right_path, i);
                if (ret) {
                        mlog_errno(ret);
                        goto out;
                }
 
-               ret = ocfs2_journal_access(handle, inode,
-                                          left_path->p_node[i].bh,
-                                          OCFS2_JOURNAL_ACCESS_WRITE);
+               ret = ocfs2_path_bh_journal_access(handle, inode,
+                                                  left_path, i);
                if (ret) {
                        mlog_errno(ret);
                        goto out;
@@ -2626,16 +2694,17 @@ out:
 
 static int ocfs2_rotate_rightmost_leaf_left(struct inode *inode,
                                            handle_t *handle,
-                                           struct buffer_head *bh,
-                                           struct ocfs2_extent_list *el)
+                                           struct ocfs2_path *path)
 {
        int ret;
+       struct buffer_head *bh = path_leaf_bh(path);
+       struct ocfs2_extent_list *el = path_leaf_el(path);
 
        if (!ocfs2_is_empty_extent(&el->l_recs[0]))
                return 0;
 
-       ret = ocfs2_journal_access(handle, inode, bh,
-                                  OCFS2_JOURNAL_ACCESS_WRITE);
+       ret = ocfs2_path_bh_journal_access(handle, inode, path,
+                                          path_num_items(path) - 1);
        if (ret) {
                mlog_errno(ret);
                goto out;
@@ -2674,8 +2743,7 @@ static int __ocfs2_rotate_tree_left(struct inode *inode,
                goto out;
        }
 
-       left_path = ocfs2_new_path(path_root_bh(path),
-                                  path_root_el(path));
+       left_path = ocfs2_new_path_from_path(path);
        if (!left_path) {
                ret = -ENOMEM;
                mlog_errno(ret);
@@ -2684,8 +2752,7 @@ static int __ocfs2_rotate_tree_left(struct inode *inode,
 
        ocfs2_cp_path(left_path, path);
 
-       right_path = ocfs2_new_path(path_root_bh(path),
-                                   path_root_el(path));
+       right_path = ocfs2_new_path_from_path(path);
        if (!right_path) {
                ret = -ENOMEM;
                mlog_errno(ret);
@@ -2719,9 +2786,8 @@ static int __ocfs2_rotate_tree_left(struct inode *inode,
                 * Caller might still want to make changes to the
                 * tree root, so re-add it to the journal here.
                 */
-               ret = ocfs2_journal_access(handle, inode,
-                                          path_root_bh(left_path),
-                                          OCFS2_JOURNAL_ACCESS_WRITE);
+               ret = ocfs2_path_bh_journal_access(handle, inode,
+                                                  left_path, 0);
                if (ret) {
                        mlog_errno(ret);
                        goto out;
@@ -2815,8 +2881,7 @@ static int ocfs2_remove_rightmost_path(struct inode *inode, handle_t *handle,
                 * We have a path to the left of this one - it needs
                 * an update too.
                 */
-               left_path = ocfs2_new_path(path_root_bh(path),
-                                          path_root_el(path));
+               left_path = ocfs2_new_path_from_path(path);
                if (!left_path) {
                        ret = -ENOMEM;
                        mlog_errno(ret);
@@ -2905,8 +2970,7 @@ rightmost_no_delete:
                 * it up front.
                 */
                ret = ocfs2_rotate_rightmost_leaf_left(inode, handle,
-                                                      path_leaf_bh(path),
-                                                      path_leaf_el(path));
+                                                      path);
                if (ret)
                        mlog_errno(ret);
                goto out;
@@ -3057,8 +3121,7 @@ static int ocfs2_get_right_path(struct inode *inode,
        /* This function shouldn't be called for the rightmost leaf. */
        BUG_ON(right_cpos == 0);
 
-       right_path = ocfs2_new_path(path_root_bh(left_path),
-                                   path_root_el(left_path));
+       right_path = ocfs2_new_path_from_path(left_path);
        if (!right_path) {
                ret = -ENOMEM;
                mlog_errno(ret);
@@ -3141,8 +3204,8 @@ static int ocfs2_merge_rec_right(struct inode *inode,
                root_bh = left_path->p_node[subtree_index].bh;
                BUG_ON(root_bh != right_path->p_node[subtree_index].bh);
 
-               ret = ocfs2_journal_access(handle, inode, root_bh,
-                                          OCFS2_JOURNAL_ACCESS_WRITE);
+               ret = ocfs2_path_bh_journal_access(handle, inode, right_path,
+                                                  subtree_index);
                if (ret) {
                        mlog_errno(ret);
                        goto out;
@@ -3150,17 +3213,15 @@ static int ocfs2_merge_rec_right(struct inode *inode,
 
                for (i = subtree_index + 1;
                     i < path_num_items(right_path); i++) {
-                       ret = ocfs2_journal_access(handle, inode,
-                                                  right_path->p_node[i].bh,
-                                                  OCFS2_JOURNAL_ACCESS_WRITE);
+                       ret = ocfs2_path_bh_journal_access(handle, inode,
+                                                          right_path, i);
                        if (ret) {
                                mlog_errno(ret);
                                goto out;
                        }
 
-                       ret = ocfs2_journal_access(handle, inode,
-                                                  left_path->p_node[i].bh,
-                                                  OCFS2_JOURNAL_ACCESS_WRITE);
+                       ret = ocfs2_path_bh_journal_access(handle, inode,
+                                                          left_path, i);
                        if (ret) {
                                mlog_errno(ret);
                                goto out;
@@ -3172,8 +3233,8 @@ static int ocfs2_merge_rec_right(struct inode *inode,
                right_rec = &el->l_recs[index + 1];
        }
 
-       ret = ocfs2_journal_access(handle, inode, bh,
-                                  OCFS2_JOURNAL_ACCESS_WRITE);
+       ret = ocfs2_path_bh_journal_access(handle, inode, left_path,
+                                          path_num_items(left_path) - 1);
        if (ret) {
                mlog_errno(ret);
                goto out;
@@ -3229,8 +3290,7 @@ static int ocfs2_get_left_path(struct inode *inode,
        /* This function shouldn't be called for the leftmost leaf. */
        BUG_ON(left_cpos == 0);
 
-       left_path = ocfs2_new_path(path_root_bh(right_path),
-                                  path_root_el(right_path));
+       left_path = ocfs2_new_path_from_path(right_path);
        if (!left_path) {
                ret = -ENOMEM;
                mlog_errno(ret);
@@ -3313,8 +3373,8 @@ static int ocfs2_merge_rec_left(struct inode *inode,
                root_bh = left_path->p_node[subtree_index].bh;
                BUG_ON(root_bh != right_path->p_node[subtree_index].bh);
 
-               ret = ocfs2_journal_access(handle, inode, root_bh,
-                                          OCFS2_JOURNAL_ACCESS_WRITE);
+               ret = ocfs2_path_bh_journal_access(handle, inode, right_path,
+                                                  subtree_index);
                if (ret) {
                        mlog_errno(ret);
                        goto out;
@@ -3322,17 +3382,15 @@ static int ocfs2_merge_rec_left(struct inode *inode,
 
                for (i = subtree_index + 1;
                     i < path_num_items(right_path); i++) {
-                       ret = ocfs2_journal_access(handle, inode,
-                                                  right_path->p_node[i].bh,
-                                                  OCFS2_JOURNAL_ACCESS_WRITE);
+                       ret = ocfs2_path_bh_journal_access(handle, inode,
+                                                          right_path, i);
                        if (ret) {
                                mlog_errno(ret);
                                goto out;
                        }
 
-                       ret = ocfs2_journal_access(handle, inode,
-                                                  left_path->p_node[i].bh,
-                                                  OCFS2_JOURNAL_ACCESS_WRITE);
+                       ret = ocfs2_path_bh_journal_access(handle, inode,
+                                                          left_path, i);
                        if (ret) {
                                mlog_errno(ret);
                                goto out;
@@ -3344,8 +3402,8 @@ static int ocfs2_merge_rec_left(struct inode *inode,
                        has_empty_extent = 1;
        }
 
-       ret = ocfs2_journal_access(handle, inode, bh,
-                                  OCFS2_JOURNAL_ACCESS_WRITE);
+       ret = ocfs2_path_bh_journal_access(handle, inode, right_path,
+                                          path_num_items(right_path) - 1);
        if (ret) {
                mlog_errno(ret);
                goto out;
@@ -3762,8 +3820,7 @@ static int ocfs2_append_rec_to_path(struct inode *inode, handle_t *handle,
                 * leftmost leaf.
                 */
                if (left_cpos) {
-                       left_path = ocfs2_new_path(path_root_bh(right_path),
-                                                  path_root_el(right_path));
+                       left_path = ocfs2_new_path_from_path(right_path);
                        if (!left_path) {
                                ret = -ENOMEM;
                                mlog_errno(ret);
@@ -3811,7 +3868,7 @@ static void ocfs2_split_record(struct inode *inode,
        struct ocfs2_extent_list *left_el = NULL, *right_el, *insert_el, *el;
        struct ocfs2_extent_rec *rec, *tmprec;
 
-       right_el = path_leaf_el(right_path);;
+       right_el = path_leaf_el(right_path);
        if (left_path)
                left_el = path_leaf_el(left_path);
 
@@ -3988,8 +4045,8 @@ static int ocfs2_do_insert_extent(struct inode *inode,
 
        el = et->et_root_el;
 
-       ret = ocfs2_journal_access(handle, inode, et->et_root_bh,
-                                  OCFS2_JOURNAL_ACCESS_WRITE);
+       ret = ocfs2_et_root_journal_access(handle, inode, et,
+                                          OCFS2_JOURNAL_ACCESS_WRITE);
        if (ret) {
                mlog_errno(ret);
                goto out;
@@ -4000,7 +4057,7 @@ static int ocfs2_do_insert_extent(struct inode *inode,
                goto out_update_clusters;
        }
 
-       right_path = ocfs2_new_path(et->et_root_bh, et->et_root_el);
+       right_path = ocfs2_new_path_from_et(et);
        if (!right_path) {
                ret = -ENOMEM;
                mlog_errno(ret);
@@ -4050,8 +4107,8 @@ static int ocfs2_do_insert_extent(struct inode *inode,
                 * ocfs2_rotate_tree_right() might have extended the
                 * transaction without re-journaling our tree root.
                 */
-               ret = ocfs2_journal_access(handle, inode, et->et_root_bh,
-                                          OCFS2_JOURNAL_ACCESS_WRITE);
+               ret = ocfs2_et_root_journal_access(handle, inode, et,
+                                                  OCFS2_JOURNAL_ACCESS_WRITE);
                if (ret) {
                        mlog_errno(ret);
                        goto out;
@@ -4112,8 +4169,7 @@ ocfs2_figure_merge_contig_type(struct inode *inode, struct ocfs2_path *path,
                        goto out;
 
                if (left_cpos != 0) {
-                       left_path = ocfs2_new_path(path_root_bh(path),
-                                                  path_root_el(path));
+                       left_path = ocfs2_new_path_from_path(path);
                        if (!left_path)
                                goto out;
 
@@ -4169,8 +4225,7 @@ ocfs2_figure_merge_contig_type(struct inode *inode, struct ocfs2_path *path,
                if (right_cpos == 0)
                        goto out;
 
-               right_path = ocfs2_new_path(path_root_bh(path),
-                                           path_root_el(path));
+               right_path = ocfs2_new_path_from_path(path);
                if (!right_path)
                        goto out;
 
@@ -4363,7 +4418,7 @@ static int ocfs2_figure_insert_type(struct inode *inode,
                return 0;
        }
 
-       path = ocfs2_new_path(et->et_root_bh, et->et_root_el);
+       path = ocfs2_new_path_from_et(et);
        if (!path) {
                ret = -ENOMEM;
                mlog_errno(ret);
@@ -4574,9 +4629,9 @@ int ocfs2_add_clusters_in_btree(struct ocfs2_super *osb,
 
        BUG_ON(num_bits > clusters_to_add);
 
-       /* reserve our write early -- insert_extent may update the inode */
-       status = ocfs2_journal_access(handle, inode, et->et_root_bh,
-                                     OCFS2_JOURNAL_ACCESS_WRITE);
+       /* reserve our write early -- insert_extent may update the tree root */
+       status = ocfs2_et_root_journal_access(handle, inode, et,
+                                             OCFS2_JOURNAL_ACCESS_WRITE);
        if (status < 0) {
                mlog_errno(status);
                goto leave;
@@ -4741,6 +4796,29 @@ out:
        return ret;
 }
 
+static int ocfs2_replace_extent_rec(struct inode *inode,
+                                   handle_t *handle,
+                                   struct ocfs2_path *path,
+                                   struct ocfs2_extent_list *el,
+                                   int split_index,
+                                   struct ocfs2_extent_rec *split_rec)
+{
+       int ret;
+
+       ret = ocfs2_path_bh_journal_access(handle, inode, path,
+                                          path_num_items(path) - 1);
+       if (ret) {
+               mlog_errno(ret);
+               goto out;
+       }
+
+       el->l_recs[split_index] = *split_rec;
+
+       ocfs2_journal_dirty(handle, path_leaf_bh(path));
+out:
+       return ret;
+}
+
 /*
  * Mark part or all of the extent record at split_index in the leaf
  * pointed to by path as written. This removes the unwritten
@@ -4830,7 +4908,9 @@ static int __ocfs2_mark_extent_written(struct inode *inode,
 
        if (ctxt.c_contig_type == CONTIG_NONE) {
                if (ctxt.c_split_covers_rec)
-                       el->l_recs[split_index] = *split_rec;
+                       ret = ocfs2_replace_extent_rec(inode, handle,
+                                                      path, el,
+                                                      split_index, split_rec);
                else
                        ret = ocfs2_split_and_insert(inode, handle, path, et,
                                                     &last_eb_bh, split_index,
@@ -4892,7 +4972,7 @@ int ocfs2_mark_extent_written(struct inode *inode,
        if (et->et_ops == &ocfs2_dinode_et_ops)
                ocfs2_extent_map_trunc(inode, 0);
 
-       left_path = ocfs2_new_path(et->et_root_bh, et->et_root_el);
+       left_path = ocfs2_new_path_from_et(et);
        if (!left_path) {
                ret = -ENOMEM;
                mlog_errno(ret);
@@ -5064,8 +5144,7 @@ static int ocfs2_truncate_rec(struct inode *inode, handle_t *handle,
                }
 
                if (left_cpos && le16_to_cpu(el->l_next_free_rec) > 1) {
-                       left_path = ocfs2_new_path(path_root_bh(path),
-                                                  path_root_el(path));
+                       left_path = ocfs2_new_path_from_path(path);
                        if (!left_path) {
                                ret = -ENOMEM;
                                mlog_errno(ret);
@@ -5174,7 +5253,7 @@ int ocfs2_remove_extent(struct inode *inode,
 
        ocfs2_extent_map_trunc(inode, 0);
 
-       path = ocfs2_new_path(et->et_root_bh, et->et_root_el);
+       path = ocfs2_new_path_from_et(et);
        if (!path) {
                ret = -ENOMEM;
                mlog_errno(ret);
@@ -5322,20 +5401,23 @@ int ocfs2_remove_btree_range(struct inode *inode,
                }
        }
 
-       handle = ocfs2_start_trans(osb, OCFS2_REMOVE_EXTENT_CREDITS);
+       handle = ocfs2_start_trans(osb, ocfs2_remove_extent_credits(osb->sb));
        if (IS_ERR(handle)) {
                ret = PTR_ERR(handle);
                mlog_errno(ret);
                goto out;
        }
 
-       ret = ocfs2_journal_access(handle, inode, et->et_root_bh,
-                                  OCFS2_JOURNAL_ACCESS_WRITE);
+       ret = ocfs2_et_root_journal_access(handle, inode, et,
+                                          OCFS2_JOURNAL_ACCESS_WRITE);
        if (ret) {
                mlog_errno(ret);
                goto out;
        }
 
+       vfs_dq_free_space_nodirty(inode,
+                                 ocfs2_clusters_to_bytes(inode->i_sb, len));
+
        ret = ocfs2_remove_extent(inode, et, cpos, len, handle, meta_ac,
                                  dealloc);
        if (ret) {
@@ -5443,8 +5525,8 @@ int ocfs2_truncate_log_append(struct ocfs2_super *osb,
                goto bail;
        }
 
-       status = ocfs2_journal_access(handle, tl_inode, tl_bh,
-                                     OCFS2_JOURNAL_ACCESS_WRITE);
+       status = ocfs2_journal_access_di(handle, tl_inode, tl_bh,
+                                        OCFS2_JOURNAL_ACCESS_WRITE);
        if (status < 0) {
                mlog_errno(status);
                goto bail;
@@ -5505,8 +5587,8 @@ static int ocfs2_replay_truncate_records(struct ocfs2_super *osb,
        while (i >= 0) {
                /* Caller has given us at least enough credits to
                 * update the truncate log dinode */
-               status = ocfs2_journal_access(handle, tl_inode, tl_bh,
-                                             OCFS2_JOURNAL_ACCESS_WRITE);
+               status = ocfs2_journal_access_di(handle, tl_inode, tl_bh,
+                                                OCFS2_JOURNAL_ACCESS_WRITE);
                if (status < 0) {
                        mlog_errno(status);
                        goto bail;
@@ -5762,6 +5844,7 @@ int ocfs2_begin_truncate_log_recovery(struct ocfs2_super *osb,
                 * tl_used. */
                tl->tl_used = 0;
 
+               ocfs2_compute_meta_ecc(osb->sb, tl_bh->b_data, &di->i_check);
                status = ocfs2_write_block(osb, tl_bh, tl_inode);
                if (status < 0) {
                        mlog_errno(status);
@@ -6528,8 +6611,8 @@ static int ocfs2_do_truncate(struct ocfs2_super *osb,
        }
 
        if (last_eb_bh) {
-               status = ocfs2_journal_access(handle, inode, last_eb_bh,
-                                             OCFS2_JOURNAL_ACCESS_WRITE);
+               status = ocfs2_journal_access_eb(handle, inode, last_eb_bh,
+                                                OCFS2_JOURNAL_ACCESS_WRITE);
                if (status < 0) {
                        mlog_errno(status);
                        goto bail;
@@ -6552,6 +6635,8 @@ static int ocfs2_do_truncate(struct ocfs2_super *osb,
                goto bail;
        }
 
+       vfs_dq_free_space_nodirty(inode,
+                       ocfs2_clusters_to_bytes(osb->sb, clusters_to_del));
        spin_lock(&OCFS2_I(inode)->ip_lock);
        OCFS2_I(inode)->ip_clusters = le32_to_cpu(fe->i_clusters) -
                                      clusters_to_del;
@@ -6860,6 +6945,7 @@ int ocfs2_convert_inline_data_to_extents(struct inode *inode,
        struct page **pages = NULL;
        loff_t end = osb->s_clustersize;
        struct ocfs2_extent_tree et;
+       int did_quota = 0;
 
        has_data = i_size_read(inode) ? 1 : 0;
 
@@ -6879,15 +6965,16 @@ int ocfs2_convert_inline_data_to_extents(struct inode *inode,
                }
        }
 
-       handle = ocfs2_start_trans(osb, OCFS2_INLINE_TO_EXTENTS_CREDITS);
+       handle = ocfs2_start_trans(osb,
+                                  ocfs2_inline_to_extents_credits(osb->sb));
        if (IS_ERR(handle)) {
                ret = PTR_ERR(handle);
                mlog_errno(ret);
                goto out_unlock;
        }
 
-       ret = ocfs2_journal_access(handle, inode, di_bh,
-                                  OCFS2_JOURNAL_ACCESS_WRITE);
+       ret = ocfs2_journal_access_di(handle, inode, di_bh,
+                                     OCFS2_JOURNAL_ACCESS_WRITE);
        if (ret) {
                mlog_errno(ret);
                goto out_commit;
@@ -6898,6 +6985,13 @@ int ocfs2_convert_inline_data_to_extents(struct inode *inode,
                unsigned int page_end;
                u64 phys;
 
+               if (vfs_dq_alloc_space_nodirty(inode,
+                                      ocfs2_clusters_to_bytes(osb->sb, 1))) {
+                       ret = -EDQUOT;
+                       goto out_commit;
+               }
+               did_quota = 1;
+
                ret = ocfs2_claim_clusters(osb, handle, data_ac, 1, &bit_off,
                                           &num);
                if (ret) {
@@ -6971,6 +7065,10 @@ int ocfs2_convert_inline_data_to_extents(struct inode *inode,
        }
 
 out_commit:
+       if (ret < 0 && did_quota)
+               vfs_dq_free_space_nodirty(inode,
+                                         ocfs2_clusters_to_bytes(osb->sb, 1));
+
        ocfs2_commit_trans(osb, handle);
 
 out_unlock:
@@ -7010,7 +7108,8 @@ int ocfs2_commit_truncate(struct ocfs2_super *osb,
        new_highest_cpos = ocfs2_clusters_for_bytes(osb->sb,
                                                     i_size_read(inode));
 
-       path = ocfs2_new_path(fe_bh, &di->id2.i_list);
+       path = ocfs2_new_path(fe_bh, &di->id2.i_list,
+                             ocfs2_journal_access_di);
        if (!path) {
                status = -ENOMEM;
                mlog_errno(status);
@@ -7243,8 +7342,8 @@ int ocfs2_truncate_inline(struct inode *inode, struct buffer_head *di_bh,
                goto out;
        }
 
-       ret = ocfs2_journal_access(handle, inode, di_bh,
-                                  OCFS2_JOURNAL_ACCESS_WRITE);
+       ret = ocfs2_journal_access_di(handle, inode, di_bh,
+                                     OCFS2_JOURNAL_ACCESS_WRITE);
        if (ret) {
                mlog_errno(ret);
                goto out_commit;