void btrfs_destroy_inode(struct inode *inode);
 int btrfs_init_cachep(void);
 void btrfs_destroy_cachep(void);
+long btrfs_ioctl_trans_end(struct file *file);
 long btrfs_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
 struct inode *btrfs_iget_locked(struct super_block *s, u64 objectid,
                                struct btrfs_root *root);
 int btrfs_drop_extents(struct btrfs_trans_handle *trans,
                       struct btrfs_root *root, struct inode *inode,
                       u64 start, u64 end, u64 inline_limit, u64 *hint_block);
+int btrfs_release_file(struct inode *inode, struct file *file);
+
 /* tree-defrag.c */
 int btrfs_defrag_leaves(struct btrfs_trans_handle *trans,
                        struct btrfs_root *root, int cache_only);
 u64 btrfs_parse_size(char *str);
 int btrfs_parse_options(char *options, struct btrfs_root *root,
                        char **subvol_name);
+int btrfs_sync_fs(struct super_block *sb, int wait);
 #endif
 
        return num_written ? num_written : err;
 }
 
-static int btrfs_release_file (struct inode * inode, struct file * filp)
+int btrfs_release_file(struct inode * inode, struct file * filp)
 {
        btrfs_del_ordered_inode(inode);
+       if (filp->private_data)
+               btrfs_ioctl_trans_end(filp);
        return 0;
 }
 
        /*
         * ok we haven't committed the transaction yet, lets do a commit
         */
+       if (file->private_data)
+               btrfs_ioctl_trans_end(file);
+
        trans = btrfs_start_transaction(root, 1);
        if (!trans) {
                ret = -ENOMEM;
 
        return ret;
 }
 
+/*
+ * there are many ways the trans_start and trans_end ioctls can lead
+ * to deadlocks.  They should only be used by applications that
+ * basically own the machine, and have a very in depth understanding
+ * of all the possible deadlocks and enospc problems.
+ */
+long btrfs_ioctl_trans_start(struct file *file)
+{
+       struct inode *inode = fdentry(file)->d_inode;
+       struct btrfs_root *root = BTRFS_I(inode)->root;
+       struct btrfs_trans_handle *trans;
+       int ret = 0;
+
+       mutex_lock(&root->fs_info->fs_mutex);
+       if (file->private_data) {
+               ret = -EINPROGRESS;
+               goto out;
+       }
+       trans = btrfs_start_transaction(root, 0);
+       if (trans)
+               file->private_data = trans;
+       else
+               ret = -ENOMEM;
+       /*printk(KERN_INFO "btrfs_ioctl_trans_start on %p\n", file);*/
+out:
+       mutex_unlock(&root->fs_info->fs_mutex);
+       return ret;
+}
+
+/*
+ * there are many ways the trans_start and trans_end ioctls can lead
+ * to deadlocks.  They should only be used by applications that
+ * basically own the machine, and have a very in depth understanding
+ * of all the possible deadlocks and enospc problems.
+ */
+long btrfs_ioctl_trans_end(struct file *file)
+{
+       struct inode *inode = fdentry(file)->d_inode;
+       struct btrfs_root *root = BTRFS_I(inode)->root;
+       struct btrfs_trans_handle *trans;
+       int ret = 0;
+
+       mutex_lock(&root->fs_info->fs_mutex);
+       trans = file->private_data;
+       if (!trans) {
+               ret = -EINVAL;
+               goto out;
+       }
+       btrfs_end_transaction(trans, root);
+       file->private_data = 0;
+out:
+       mutex_unlock(&root->fs_info->fs_mutex);
+       return ret;
+}
+
 long btrfs_ioctl(struct file *file, unsigned int
                cmd, unsigned long arg)
 {
                return btrfs_balance(root->fs_info->dev_root);
        case BTRFS_IOC_CLONE:
                return btrfs_ioctl_clone(file, arg);
+       case BTRFS_IOC_TRANS_START:
+               return btrfs_ioctl_trans_start(file);
+       case BTRFS_IOC_TRANS_END:
+               return btrfs_ioctl_trans_end(file);
+       case BTRFS_IOC_SYNC:
+               btrfs_sync_fs(file->f_dentry->d_sb, 1);
+               return 0;
        }
 
        return -ENOTTY;
 #ifdef CONFIG_COMPAT
        .compat_ioctl   = btrfs_ioctl,
 #endif
+       .release        = btrfs_release_file,
 };
 
 static struct extent_io_ops btrfs_extent_io_ops = {
 
                                   struct btrfs_ioctl_vol_args)
 #define BTRFS_IOC_SCAN_DEV _IOW(BTRFS_IOCTL_MAGIC, 4, \
                                   struct btrfs_ioctl_vol_args)
+/* trans start and trans end are dangerous, and only for
+ * use by applications that know how to avoid the
+ * resulting deadlocks
+ */
+#define BTRFS_IOC_TRANS_START  _IO(BTRFS_IOCTL_MAGIC, 6)
+#define BTRFS_IOC_TRANS_END    _IO(BTRFS_IOCTL_MAGIC, 7)
+#define BTRFS_IOC_SYNC         _IO(BTRFS_IOCTL_MAGIC, 8)
+
 #define BTRFS_IOC_CLONE        _IOW(BTRFS_IOCTL_MAGIC, 9, int)
 #define BTRFS_IOC_ADD_DEV _IOW(BTRFS_IOCTL_MAGIC, 10, \
                                   struct btrfs_ioctl_vol_args)
                                   struct btrfs_ioctl_vol_args)
 #define BTRFS_IOC_BALANCE _IOW(BTRFS_IOCTL_MAGIC, 12, \
                                   struct btrfs_ioctl_vol_args)
+
 #endif
 
        return err;
 }
 
-static int btrfs_sync_fs(struct super_block *sb, int wait)
+int btrfs_sync_fs(struct super_block *sb, int wait)
 {
        struct btrfs_trans_handle *trans;
        struct btrfs_root *root;