goto out_inserted_sd;
        }
 
-       /* XXX CHECK THIS */
        if (reiserfs_posixacl(inode->i_sb)) {
-               retval = reiserfs_inherit_default_acl(dir, dentry, inode);
+               retval = reiserfs_inherit_default_acl(th, dir, dentry, inode);
                if (retval) {
                        err = retval;
                        reiserfs_check_path(&path_to_key);
 
            2 * (REISERFS_QUOTA_INIT_BLOCKS(dir->i_sb) +
                 REISERFS_QUOTA_TRANS_BLOCKS(dir->i_sb));
        struct reiserfs_transaction_handle th;
-       int locked;
 
        if (!(inode = new_inode(dir->i_sb))) {
                return -ENOMEM;
        }
        new_inode_init(inode, dir, mode);
 
-       locked = reiserfs_cache_default_acl(dir);
-
+       jbegin_count += reiserfs_cache_default_acl(dir);
        reiserfs_write_lock(dir->i_sb);
 
        retval = journal_begin(&th, dir->i_sb, jbegin_count);
            JOURNAL_PER_BALANCE_CNT * 3 +
            2 * (REISERFS_QUOTA_INIT_BLOCKS(dir->i_sb) +
                 REISERFS_QUOTA_TRANS_BLOCKS(dir->i_sb));
-       int locked;
 
        if (!new_valid_dev(rdev))
                return -EINVAL;
        }
        new_inode_init(inode, dir, mode);
 
-       locked = reiserfs_cache_default_acl(dir);
-
+       jbegin_count += reiserfs_cache_default_acl(dir);
        reiserfs_write_lock(dir->i_sb);
 
        retval = journal_begin(&th, dir->i_sb, jbegin_count);
            JOURNAL_PER_BALANCE_CNT * 3 +
            2 * (REISERFS_QUOTA_INIT_BLOCKS(dir->i_sb) +
                 REISERFS_QUOTA_TRANS_BLOCKS(dir->i_sb));
-       int locked;
 
 #ifdef DISPLACE_NEW_PACKING_LOCALITIES
        /* set flag that new packing locality created and new blocks for the content     * of that directory are not displaced yet */
        }
        new_inode_init(inode, dir, mode);
 
-       locked = reiserfs_cache_default_acl(dir);
-
+       jbegin_count += reiserfs_cache_default_acl(dir);
        reiserfs_write_lock(dir->i_sb);
 
        retval = journal_begin(&th, dir->i_sb, jbegin_count);
        memcpy(name, symname, strlen(symname));
        padd_item(name, item_len, strlen(symname));
 
-       /* We would inherit the default ACL here, but symlinks don't get ACLs */
-
        retval = journal_begin(&th, parent_dir->i_sb, jbegin_count);
        if (retval) {
                drop_new_inode(inode);
 
  * inode->i_mutex: down
  */
 int
-__reiserfs_xattr_set(struct inode *inode, const char *name, const void *buffer,
-                    size_t buffer_size, int flags)
+reiserfs_xattr_set_handle(struct reiserfs_transaction_handle *th,
+                         struct inode *inode, const char *name,
+                         const void *buffer, size_t buffer_size, int flags)
 {
        int err = 0;
        struct dentry *dentry;
        return err;
 }
 
-int
-reiserfs_xattr_set(struct inode *inode, const char *name, const void *buffer,
-                    size_t buffer_size, int flags)
+/* We need to start a transaction to maintain lock ordering */
+int reiserfs_xattr_set(struct inode *inode, const char *name,
+                      const void *buffer, size_t buffer_size, int flags)
 {
-       int err = __reiserfs_xattr_set(inode, name, buffer, buffer_size, flags);
-       if (err == -ENODATA)
-               err = 0;
-       return err;
+
+       struct reiserfs_transaction_handle th;
+       int error, error2;
+       size_t jbegin_count = reiserfs_xattr_nblocks(inode, buffer_size);
+
+       if (!(flags & XATTR_REPLACE))
+               jbegin_count += reiserfs_xattr_jcreate_nblocks(inode);
+
+       reiserfs_write_lock(inode->i_sb);
+       error = journal_begin(&th, inode->i_sb, jbegin_count);
+       if (error) {
+               reiserfs_write_unlock(inode->i_sb);
+               return error;
+       }
+
+       error = reiserfs_xattr_set_handle(&th, inode, name,
+                                         buffer, buffer_size, flags);
+
+       error2 = journal_end(&th, inode->i_sb, jbegin_count);
+       if (error == 0)
+               error = error2;
+       reiserfs_write_unlock(inode->i_sb);
+
+       return error;
 }
 
 /*
 
 #include <linux/reiserfs_acl.h>
 #include <asm/uaccess.h>
 
-static int reiserfs_set_acl(struct inode *inode, int type,
+static int reiserfs_set_acl(struct reiserfs_transaction_handle *th,
+                           struct inode *inode, int type,
                            struct posix_acl *acl);
 
 static int
 xattr_set_acl(struct inode *inode, int type, const void *value, size_t size)
 {
        struct posix_acl *acl;
-       int error;
-
+       int error, error2;
+       struct reiserfs_transaction_handle th;
+       size_t jcreate_blocks;
        if (!reiserfs_posixacl(inode->i_sb))
                return -EOPNOTSUPP;
        if (!is_owner_or_cap(inode))
        } else
                acl = NULL;
 
-       error = reiserfs_set_acl(inode, type, acl);
+       /* Pessimism: We can't assume that anything from the xattr root up
+        * has been created. */
+
+       jcreate_blocks = reiserfs_xattr_jcreate_nblocks(inode) +
+                        reiserfs_xattr_nblocks(inode, size) * 2;
+
+       reiserfs_write_lock(inode->i_sb);
+       error = journal_begin(&th, inode->i_sb, jcreate_blocks);
+       if (error == 0) {
+               error = reiserfs_set_acl(&th, inode, type, acl);
+               error2 = journal_end(&th, inode->i_sb, jcreate_blocks);
+               if (error2)
+                       error = error2;
+       }
+       reiserfs_write_unlock(inode->i_sb);
 
       release_and_out:
        posix_acl_release(acl);
  * BKL held [before 2.5.x]
  */
 static int
-reiserfs_set_acl(struct inode *inode, int type, struct posix_acl *acl)
+reiserfs_set_acl(struct reiserfs_transaction_handle *th, struct inode *inode,
+                int type, struct posix_acl *acl)
 {
        char *name;
        void *value = NULL;
                        return (int)PTR_ERR(value);
        }
 
-       error = __reiserfs_xattr_set(inode, name, value, size, 0);
+       error = reiserfs_xattr_set_handle(th, inode, name, value, size, 0);
 
        /*
         * Ensure that the inode gets dirtied if we're only using
 /* dir->i_mutex: locked,
  * inode is new and not released into the wild yet */
 int
-reiserfs_inherit_default_acl(struct inode *dir, struct dentry *dentry,
+reiserfs_inherit_default_acl(struct reiserfs_transaction_handle *th,
+                            struct inode *dir, struct dentry *dentry,
                             struct inode *inode)
 {
        struct posix_acl *acl;
 
                /* Copy the default ACL to the default ACL of a new directory */
                if (S_ISDIR(inode->i_mode)) {
-                       err = reiserfs_set_acl(inode, ACL_TYPE_DEFAULT, acl);
+                       err = reiserfs_set_acl(th, inode, ACL_TYPE_DEFAULT,
+                                              acl);
                        if (err)
                                goto cleanup;
                }
 
                        /* If we need an ACL.. */
                        if (need_acl > 0) {
-                               err =
-                                   reiserfs_set_acl(inode, ACL_TYPE_ACCESS,
-                                                    acl_copy);
+                               err = reiserfs_set_acl(th, inode,
+                                                      ACL_TYPE_ACCESS,
+                                                      acl_copy);
                                if (err)
                                        goto cleanup_copy;
                        }
        return err;
 }
 
-/* Looks up and caches the result of the default ACL.
- * We do this so that we don't need to carry the xattr_sem into
- * reiserfs_new_inode if we don't need to */
+/* This is used to cache the default acl before a new object is created.
+ * The biggest reason for this is to get an idea of how many blocks will
+ * actually be required for the create operation if we must inherit an ACL.
+ * An ACL write can add up to 3 object creations and an additional file write
+ * so we'd prefer not to reserve that many blocks in the journal if we can.
+ * It also has the advantage of not loading the ACL with a transaction open,
+ * this may seem silly, but if the owner of the directory is doing the
+ * creation, the ACL may not be loaded since the permissions wouldn't require
+ * it.
+ * We return the number of blocks required for the transaction.
+ */
 int reiserfs_cache_default_acl(struct inode *inode)
 {
-       int ret = 0;
-       if (reiserfs_posixacl(inode->i_sb) && !IS_PRIVATE(inode)) {
-               struct posix_acl *acl;
-               acl = reiserfs_get_acl(inode, ACL_TYPE_DEFAULT);
-               ret = (acl && !IS_ERR(acl));
-               if (ret)
-                       posix_acl_release(acl);
+       struct posix_acl *acl;
+       int nblocks = 0;
+
+       if (IS_PRIVATE(inode))
+               return 0;
+
+       acl = reiserfs_get_acl(inode, ACL_TYPE_DEFAULT);
+
+       if (acl && !IS_ERR(acl)) {
+               int size = reiserfs_acl_size(acl->a_count);
+
+               /* Other xattrs can be created during inode creation. We don't
+                * want to claim too many blocks, so we check to see if we
+                * we need to create the tree to the xattrs, and then we
+                * just want two files. */
+               nblocks = reiserfs_xattr_jcreate_nblocks(inode);
+               nblocks += JOURNAL_BLOCKS_PER_OBJECT(inode->i_sb);
+
+               REISERFS_I(inode)->i_flags |= i_has_xattr_dir;
+
+               /* We need to account for writes + bitmaps for two files */
+               nblocks += reiserfs_xattr_nblocks(inode, size) * 4;
+               posix_acl_release(acl);
        }
 
-       return ret;
+       return nblocks;
 }
 
 int reiserfs_acl_chmod(struct inode *inode)
        if (!clone)
                return -ENOMEM;
        error = posix_acl_chmod_masq(clone, inode->i_mode);
-       if (!error)
-               error = reiserfs_set_acl(inode, ACL_TYPE_ACCESS, clone);
+       if (!error) {
+               struct reiserfs_transaction_handle th;
+               size_t size = reiserfs_xattr_nblocks(inode,
+                                            reiserfs_acl_size(clone->a_count));
+               reiserfs_write_lock(inode->i_sb);
+               error = journal_begin(&th, inode->i_sb, size * 2);
+               if (!error) {
+                       int error2;
+                       error = reiserfs_set_acl(&th, inode, ACL_TYPE_ACCESS,
+                                                clone);
+                       error2 = journal_end(&th, inode->i_sb, size * 2);
+                       if (error2)
+                               error = error2;
+               }
+               reiserfs_write_unlock(inode->i_sb);
+       }
        posix_acl_release(clone);
        return error;
 }
 
 #ifdef CONFIG_REISERFS_FS_POSIX_ACL
 struct posix_acl *reiserfs_get_acl(struct inode *inode, int type);
 int reiserfs_acl_chmod(struct inode *inode);
-int reiserfs_inherit_default_acl(struct inode *dir, struct dentry *dentry,
+int reiserfs_inherit_default_acl(struct reiserfs_transaction_handle *th,
+                                struct inode *dir, struct dentry *dentry,
                                 struct inode *inode);
 int reiserfs_cache_default_acl(struct inode *dir);
 extern struct xattr_handler reiserfs_posix_acl_default_handler;
 
 #define JOURNAL_MAX_COMMIT_AGE 30
 #define JOURNAL_MAX_TRANS_AGE 30
 #define JOURNAL_PER_BALANCE_CNT (3 * (MAX_HEIGHT-2) + 9)
+#define JOURNAL_BLOCKS_PER_OBJECT(sb)  (JOURNAL_PER_BALANCE_CNT * 3 + \
+                                        2 * (REISERFS_QUOTA_INIT_BLOCKS(sb) + \
+                                             REISERFS_QUOTA_TRANS_BLOCKS(sb)))
+
 #ifdef CONFIG_QUOTA
 /* We need to update data and inode (atime) */
 #define REISERFS_QUOTA_TRANS_BLOCKS(s) (REISERFS_SB(s)->s_mount_opt & (1<<REISERFS_QUOTA) ? 2 : 0)
 
 int reiserfs_permission(struct inode *inode, int mask);
 
 int reiserfs_xattr_get(struct inode *, const char *, void *, size_t);
-int __reiserfs_xattr_set(struct inode *, const char *, const void *,
-                        size_t, int);
 int reiserfs_xattr_set(struct inode *, const char *, const void *, size_t, int);
+int reiserfs_xattr_set_handle(struct reiserfs_transaction_handle *,
+                             struct inode *, const char *, const void *,
+                             size_t, int);
 
 extern struct xattr_handler reiserfs_xattr_user_handler;
 extern struct xattr_handler reiserfs_xattr_trusted_handler;
 extern struct xattr_handler reiserfs_xattr_security_handler;
 
+#define xattr_size(size) ((size) + sizeof(struct reiserfs_xattr_header))
+static inline loff_t reiserfs_xattr_nblocks(struct inode *inode, loff_t size)
+{
+       loff_t ret = 0;
+       if (reiserfs_file_data_log(inode)) {
+               ret = _ROUND_UP(xattr_size(size), inode->i_sb->s_blocksize);
+               ret >>= inode->i_sb->s_blocksize_bits;
+       }
+       return ret;
+}
+
+/* We may have to create up to 3 objects: xattr root, xattr dir, xattr file.
+ * Let's try to be smart about it.
+ * xattr root: We cache it. If it's not cached, we may need to create it.
+ * xattr dir: If anything has been loaded for this inode, we can set a flag
+ *            saying so.
+ * xattr file: Since we don't cache xattrs, we can't tell. We always include
+ *             blocks for it.
+ *
+ * However, since root and dir can be created between calls - YOU MUST SAVE
+ * THIS VALUE.
+ */
+static inline size_t reiserfs_xattr_jcreate_nblocks(struct inode *inode)
+{
+       size_t nblocks = JOURNAL_BLOCKS_PER_OBJECT(inode->i_sb);
+
+       if ((REISERFS_I(inode)->i_flags & i_has_xattr_dir) == 0) {
+               nblocks += JOURNAL_BLOCKS_PER_OBJECT(inode->i_sb);
+               if (REISERFS_SB(inode->i_sb)->xattr_root == NULL)
+                       nblocks += JOURNAL_BLOCKS_PER_OBJECT(inode->i_sb);
+       }
+
+       return nblocks;
+}
+
 static inline void reiserfs_init_xattr_rwsem(struct inode *inode)
 {
        init_rwsem(&REISERFS_I(inode)->i_xattr_sem);