Btrfs: Add mount -o nodatasum to turn of file data checksumming
authorChris Mason <chris.mason@oracle.com>
Fri, 14 Dec 2007 20:30:32 +0000 (15:30 -0500)
committerChris Mason <chris.mason@oracle.com>
Thu, 25 Sep 2008 15:03:58 +0000 (11:03 -0400)
Signed-off-by: Chris Mason <chris.mason@oracle.com>
fs/btrfs/ctree.h
fs/btrfs/disk-io.c
fs/btrfs/inode.c
fs/btrfs/super.c

index 052555c..5e255ca 100644 (file)
@@ -321,6 +321,7 @@ struct btrfs_fs_info {
 
        u64 generation;
        u64 last_trans_committed;
+       unsigned long mount_opt;
        struct btrfs_transaction *running_transaction;
        struct btrfs_super_block super_copy;
        struct extent_buffer *sb_buffer;
@@ -429,6 +430,13 @@ struct btrfs_root {
  */
 #define BTRFS_STRING_ITEM_KEY  253
 
+#define BTRFS_MOUNT_NODATASUM          0x1
+
+#define btrfs_clear_opt(o, opt)                ((o) &= ~BTRFS_MOUNT_##opt)
+#define btrfs_set_opt(o, opt)          ((o) |= BTRFS_MOUNT_##opt)
+#define btrfs_test_opt(root, opt)      ((root)->fs_info->mount_opt & \
+                                        BTRFS_MOUNT_##opt)
+
 /* some macros to generate set/get funcs for the struct fields.  This
  * assumes there is a lefoo_to_cpu for every type, so lets make a simple
  * one for u8:
@@ -906,12 +914,6 @@ static inline u32 btrfs_level_size(struct btrfs_root *root, int level) {
        ((unsigned long)(btrfs_leaf_data(leaf) + \
        btrfs_item_offset_nr(leaf, slot)))
 
-/* mount option defines and helpers */
-#define BTRFS_MOUNT_SUBVOL             0x000001
-#define btrfs_clear_opt(o, opt)                o &= ~BTRFS_MOUNT_##opt
-#define btrfs_set_opt(o, opt)          o |= BTRFS_MOUNT_##opt
-#define btrfs_test_opt(sb, opt)                (BTRFS_SB(sb)->s_mount_opt & \
-                                        BTRFS_MOUNT_##opt)
 /* extent-tree.c */
 int btrfs_extent_post_op(struct btrfs_trans_handle *trans,
                         struct btrfs_root *root);
index 60a30da..4338b00 100644 (file)
@@ -568,6 +568,7 @@ struct btrfs_root *open_ctree(struct super_block *sb)
        fs_info->tree_root = tree_root;
        fs_info->extent_root = extent_root;
        fs_info->sb = sb;
+       fs_info->mount_opt = 0;
        fs_info->btree_inode = new_inode(sb);
        fs_info->btree_inode->i_ino = 1;
        fs_info->btree_inode->i_nlink = 1;
index e535c50..11885cb 100644 (file)
@@ -116,10 +116,13 @@ int btrfs_writepage_io_hook(struct page *page, u64 start, u64 end)
        struct btrfs_root *root = BTRFS_I(inode)->root;
        struct btrfs_trans_handle *trans;
        char *kaddr;
-       int ret;
+       int ret = 0;
        u64 page_start = (u64)page->index << PAGE_CACHE_SHIFT;
        size_t offset = start - page_start;
 
+       if (btrfs_test_opt(root, NODATASUM))
+               return 0;
+
        mutex_lock(&root->fs_info->fs_mutex);
        trans = btrfs_start_transaction(root, 1);
        btrfs_set_trans_block_group(trans, inode);
@@ -143,6 +146,9 @@ int btrfs_readpage_io_hook(struct page *page, u64 start, u64 end)
        struct btrfs_path *path = NULL;
        u32 csum;
 
+       if (btrfs_test_opt(root, NODATASUM))
+               return 0;
+
        mutex_lock(&root->fs_info->fs_mutex);
        path = btrfs_alloc_path();
        item = btrfs_lookup_csum(NULL, root, path, inode->i_ino, start, 0);
@@ -176,6 +182,9 @@ int btrfs_readpage_end_io_hook(struct page *page, u64 start, u64 end)
        u32 csum = ~(u32)0;
        unsigned long flags;
 
+       if (btrfs_test_opt(root, NODATASUM))
+               return 0;
+
        ret = get_state_private(em_tree, start, &private);
        local_irq_save(flags);
        kaddr = kmap_atomic(page, KM_IRQ0);
index ffa0287..ad4f280 100644 (file)
@@ -61,11 +61,12 @@ static void btrfs_put_super (struct super_block * sb)
 }
 
 enum {
-       Opt_subvol, Opt_err,
+       Opt_subvol, Opt_nodatasum, Opt_err,
 };
 
 static match_table_t tokens = {
        {Opt_subvol, "subvol=%s"},
+       {Opt_nodatasum, "nodatasum"},
        {Opt_err, NULL}
 };
 
@@ -74,7 +75,12 @@ static int parse_options (char * options,
                          char **subvol_name)
 {
        char * p;
+       struct btrfs_fs_info *info = NULL;
        substring_t args[MAX_OPT_ARGS];
+
+       if (root)
+               info = root->fs_info;
+
        if (!options)
                return 1;
 
@@ -86,7 +92,12 @@ static int parse_options (char * options,
                token = match_token(p, tokens, args);
                switch (token) {
                case Opt_subvol:
-                       *subvol_name = match_strdup(&args[0]);
+                       if (subvol_name)
+                               *subvol_name = match_strdup(&args[0]);
+                       break;
+               case Opt_nodatasum:
+                       if (root)
+                               btrfs_set_opt(info->mount_opt, NODATASUM);
                        break;
                default:
                        return 0;
@@ -143,6 +154,8 @@ static int btrfs_fill_super(struct super_block * sb, void * data, int silent)
                goto fail_close;
        }
 
+       parse_options((char *)data, tree_root, NULL);
+
        /* this does the super kobj at the same time */
        err = btrfs_sysfs_add_super(tree_root->fs_info);
        if (err)