Commit f892436e authored by Chris Mason's avatar Chris Mason

Merge branch 'lzo-support' of git://repo.or.cz/linux-btrfs-devel into btrfs-38

parents 26c79f6b 3a39c18d
...@@ -4,6 +4,8 @@ config BTRFS_FS ...@@ -4,6 +4,8 @@ config BTRFS_FS
select LIBCRC32C select LIBCRC32C
select ZLIB_INFLATE select ZLIB_INFLATE
select ZLIB_DEFLATE select ZLIB_DEFLATE
select LZO_COMPRESS
select LZO_DECOMPRESS
help help
Btrfs is a new filesystem with extents, writable snapshotting, Btrfs is a new filesystem with extents, writable snapshotting,
support for multiple devices and many more features. support for multiple devices and many more features.
......
...@@ -6,5 +6,5 @@ btrfs-y += super.o ctree.o extent-tree.o print-tree.o root-tree.o dir-item.o \ ...@@ -6,5 +6,5 @@ btrfs-y += super.o ctree.o extent-tree.o print-tree.o root-tree.o dir-item.o \
transaction.o inode.o file.o tree-defrag.o \ transaction.o inode.o file.o tree-defrag.o \
extent_map.o sysfs.o struct-funcs.o xattr.o ordered-data.o \ extent_map.o sysfs.o struct-funcs.o xattr.o ordered-data.o \
extent_io.o volumes.o async-thread.o ioctl.o locking.o orphan.o \ extent_io.o volumes.o async-thread.o ioctl.o locking.o orphan.o \
export.o tree-log.o acl.o free-space-cache.o zlib.o \ export.o tree-log.o acl.o free-space-cache.o zlib.o lzo.o \
compression.o delayed-ref.o relocation.o compression.o delayed-ref.o relocation.o
...@@ -157,7 +157,7 @@ struct btrfs_inode { ...@@ -157,7 +157,7 @@ struct btrfs_inode {
/* /*
* always compress this one file * always compress this one file
*/ */
unsigned force_compress:1; unsigned force_compress:4;
struct inode vfs_inode; struct inode vfs_inode;
}; };
......
This diff is collapsed.
...@@ -19,24 +19,27 @@ ...@@ -19,24 +19,27 @@
#ifndef __BTRFS_COMPRESSION_ #ifndef __BTRFS_COMPRESSION_
#define __BTRFS_COMPRESSION_ #define __BTRFS_COMPRESSION_
int btrfs_zlib_decompress(unsigned char *data_in, int btrfs_init_compress(void);
struct page *dest_page, void btrfs_exit_compress(void);
unsigned long start_byte,
size_t srclen, size_t destlen); int btrfs_compress_pages(int type, struct address_space *mapping,
int btrfs_zlib_compress_pages(struct address_space *mapping, u64 start, unsigned long len,
u64 start, unsigned long len, struct page **pages,
struct page **pages, unsigned long nr_dest_pages,
unsigned long nr_dest_pages, unsigned long *out_pages,
unsigned long *out_pages, unsigned long *total_in,
unsigned long *total_in, unsigned long *total_out,
unsigned long *total_out, unsigned long max_out);
unsigned long max_out); int btrfs_decompress_biovec(int type, struct page **pages_in, u64 disk_start,
int btrfs_zlib_decompress_biovec(struct page **pages_in, struct bio_vec *bvec, int vcnt, size_t srclen);
u64 disk_start, int btrfs_decompress(int type, unsigned char *data_in, struct page *dest_page,
struct bio_vec *bvec, unsigned long start_byte, size_t srclen, size_t destlen);
int vcnt, int btrfs_decompress_buf2page(char *buf, unsigned long buf_start,
size_t srclen); unsigned long total_out, u64 disk_start,
void btrfs_zlib_exit(void); struct bio_vec *bvec, int vcnt,
unsigned long *page_index,
unsigned long *pg_offset);
int btrfs_submit_compressed_write(struct inode *inode, u64 start, int btrfs_submit_compressed_write(struct inode *inode, u64 start,
unsigned long len, u64 disk_start, unsigned long len, u64 disk_start,
unsigned long compressed_len, unsigned long compressed_len,
...@@ -44,4 +47,37 @@ int btrfs_submit_compressed_write(struct inode *inode, u64 start, ...@@ -44,4 +47,37 @@ int btrfs_submit_compressed_write(struct inode *inode, u64 start,
unsigned long nr_pages); unsigned long nr_pages);
int btrfs_submit_compressed_read(struct inode *inode, struct bio *bio, int btrfs_submit_compressed_read(struct inode *inode, struct bio *bio,
int mirror_num, unsigned long bio_flags); int mirror_num, unsigned long bio_flags);
struct btrfs_compress_op {
struct list_head *(*alloc_workspace)(void);
void (*free_workspace)(struct list_head *workspace);
int (*compress_pages)(struct list_head *workspace,
struct address_space *mapping,
u64 start, unsigned long len,
struct page **pages,
unsigned long nr_dest_pages,
unsigned long *out_pages,
unsigned long *total_in,
unsigned long *total_out,
unsigned long max_out);
int (*decompress_biovec)(struct list_head *workspace,
struct page **pages_in,
u64 disk_start,
struct bio_vec *bvec,
int vcnt,
size_t srclen);
int (*decompress)(struct list_head *workspace,
unsigned char *data_in,
struct page *dest_page,
unsigned long start_byte,
size_t srclen, size_t destlen);
};
extern struct btrfs_compress_op btrfs_zlib_compress;
extern struct btrfs_compress_op btrfs_lzo_compress;
#endif #endif
...@@ -398,13 +398,15 @@ struct btrfs_super_block { ...@@ -398,13 +398,15 @@ struct btrfs_super_block {
#define BTRFS_FEATURE_INCOMPAT_MIXED_BACKREF (1ULL << 0) #define BTRFS_FEATURE_INCOMPAT_MIXED_BACKREF (1ULL << 0)
#define BTRFS_FEATURE_INCOMPAT_DEFAULT_SUBVOL (1ULL << 1) #define BTRFS_FEATURE_INCOMPAT_DEFAULT_SUBVOL (1ULL << 1)
#define BTRFS_FEATURE_INCOMPAT_MIXED_GROUPS (1ULL << 2) #define BTRFS_FEATURE_INCOMPAT_MIXED_GROUPS (1ULL << 2)
#define BTRFS_FEATURE_INCOMPAT_COMPRESS_LZO (1ULL << 3)
#define BTRFS_FEATURE_COMPAT_SUPP 0ULL #define BTRFS_FEATURE_COMPAT_SUPP 0ULL
#define BTRFS_FEATURE_COMPAT_RO_SUPP 0ULL #define BTRFS_FEATURE_COMPAT_RO_SUPP 0ULL
#define BTRFS_FEATURE_INCOMPAT_SUPP \ #define BTRFS_FEATURE_INCOMPAT_SUPP \
(BTRFS_FEATURE_INCOMPAT_MIXED_BACKREF | \ (BTRFS_FEATURE_INCOMPAT_MIXED_BACKREF | \
BTRFS_FEATURE_INCOMPAT_DEFAULT_SUBVOL | \ BTRFS_FEATURE_INCOMPAT_DEFAULT_SUBVOL | \
BTRFS_FEATURE_INCOMPAT_MIXED_GROUPS) BTRFS_FEATURE_INCOMPAT_MIXED_GROUPS | \
BTRFS_FEATURE_INCOMPAT_COMPRESS_LZO)
/* /*
* A leaf is full of items. offset and size tell us where to find * A leaf is full of items. offset and size tell us where to find
...@@ -551,9 +553,11 @@ struct btrfs_timespec { ...@@ -551,9 +553,11 @@ struct btrfs_timespec {
} __attribute__ ((__packed__)); } __attribute__ ((__packed__));
enum btrfs_compression_type { enum btrfs_compression_type {
BTRFS_COMPRESS_NONE = 0, BTRFS_COMPRESS_NONE = 0,
BTRFS_COMPRESS_ZLIB = 1, BTRFS_COMPRESS_ZLIB = 1,
BTRFS_COMPRESS_LAST = 2, BTRFS_COMPRESS_LZO = 2,
BTRFS_COMPRESS_TYPES = 2,
BTRFS_COMPRESS_LAST = 3,
}; };
struct btrfs_inode_item { struct btrfs_inode_item {
...@@ -897,7 +901,8 @@ struct btrfs_fs_info { ...@@ -897,7 +901,8 @@ struct btrfs_fs_info {
*/ */
u64 last_trans_log_full_commit; u64 last_trans_log_full_commit;
u64 open_ioctl_trans; u64 open_ioctl_trans;
unsigned long mount_opt; unsigned long mount_opt:20;
unsigned long compress_type:4;
u64 max_inline; u64 max_inline;
u64 alloc_start; u64 alloc_start;
struct btrfs_transaction *running_transaction; struct btrfs_transaction *running_transaction;
......
...@@ -1744,10 +1744,10 @@ struct btrfs_root *open_ctree(struct super_block *sb, ...@@ -1744,10 +1744,10 @@ struct btrfs_root *open_ctree(struct super_block *sb,
} }
features = btrfs_super_incompat_flags(disk_super); features = btrfs_super_incompat_flags(disk_super);
if (!(features & BTRFS_FEATURE_INCOMPAT_MIXED_BACKREF)) { features |= BTRFS_FEATURE_INCOMPAT_MIXED_BACKREF;
features |= BTRFS_FEATURE_INCOMPAT_MIXED_BACKREF; if (tree_root->fs_info->compress_type & BTRFS_COMPRESS_LZO)
btrfs_set_super_incompat_flags(disk_super, features); features |= BTRFS_FEATURE_INCOMPAT_COMPRESS_LZO;
} btrfs_set_super_incompat_flags(disk_super, features);
features = btrfs_super_compat_ro_flags(disk_super) & features = btrfs_super_compat_ro_flags(disk_super) &
~BTRFS_FEATURE_COMPAT_RO_SUPP; ~BTRFS_FEATURE_COMPAT_RO_SUPP;
......
...@@ -2028,8 +2028,11 @@ static int __extent_read_full_page(struct extent_io_tree *tree, ...@@ -2028,8 +2028,11 @@ static int __extent_read_full_page(struct extent_io_tree *tree,
BUG_ON(extent_map_end(em) <= cur); BUG_ON(extent_map_end(em) <= cur);
BUG_ON(end < cur); BUG_ON(end < cur);
if (test_bit(EXTENT_FLAG_COMPRESSED, &em->flags)) if (test_bit(EXTENT_FLAG_COMPRESSED, &em->flags)) {
this_bio_flag = EXTENT_BIO_COMPRESSED; this_bio_flag = EXTENT_BIO_COMPRESSED;
extent_set_compress_type(&this_bio_flag,
em->compress_type);
}
iosize = min(extent_map_end(em) - cur, end - cur + 1); iosize = min(extent_map_end(em) - cur, end - cur + 1);
cur_end = min(extent_map_end(em) - 1, end); cur_end = min(extent_map_end(em) - 1, end);
......
...@@ -20,8 +20,12 @@ ...@@ -20,8 +20,12 @@
#define EXTENT_IOBITS (EXTENT_LOCKED | EXTENT_WRITEBACK) #define EXTENT_IOBITS (EXTENT_LOCKED | EXTENT_WRITEBACK)
#define EXTENT_CTLBITS (EXTENT_DO_ACCOUNTING | EXTENT_FIRST_DELALLOC) #define EXTENT_CTLBITS (EXTENT_DO_ACCOUNTING | EXTENT_FIRST_DELALLOC)
/* flags for bio submission */ /*
* flags for bio submission. The high bits indicate the compression
* type for this bio
*/
#define EXTENT_BIO_COMPRESSED 1 #define EXTENT_BIO_COMPRESSED 1
#define EXTENT_BIO_FLAG_SHIFT 16
/* these are bit numbers for test/set bit */ /* these are bit numbers for test/set bit */
#define EXTENT_BUFFER_UPTODATE 0 #define EXTENT_BUFFER_UPTODATE 0
...@@ -135,6 +139,17 @@ struct extent_buffer { ...@@ -135,6 +139,17 @@ struct extent_buffer {
wait_queue_head_t lock_wq; wait_queue_head_t lock_wq;
}; };
static inline void extent_set_compress_type(unsigned long *bio_flags,
int compress_type)
{
*bio_flags |= compress_type << EXTENT_BIO_FLAG_SHIFT;
}
static inline int extent_compress_type(unsigned long bio_flags)
{
return bio_flags >> EXTENT_BIO_FLAG_SHIFT;
}
struct extent_map_tree; struct extent_map_tree;
static inline struct extent_state *extent_state_next(struct extent_state *state) static inline struct extent_state *extent_state_next(struct extent_state *state)
......
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <linux/hardirq.h> #include <linux/hardirq.h>
#include "ctree.h"
#include "extent_map.h" #include "extent_map.h"
...@@ -54,6 +55,7 @@ struct extent_map *alloc_extent_map(gfp_t mask) ...@@ -54,6 +55,7 @@ struct extent_map *alloc_extent_map(gfp_t mask)
return em; return em;
em->in_tree = 0; em->in_tree = 0;
em->flags = 0; em->flags = 0;
em->compress_type = BTRFS_COMPRESS_NONE;
atomic_set(&em->refs, 1); atomic_set(&em->refs, 1);
return em; return em;
} }
......
...@@ -26,7 +26,8 @@ struct extent_map { ...@@ -26,7 +26,8 @@ struct extent_map {
unsigned long flags; unsigned long flags;
struct block_device *bdev; struct block_device *bdev;
atomic_t refs; atomic_t refs;
int in_tree; unsigned int in_tree:1;
unsigned int compress_type:4;
}; };
struct extent_map_tree { struct extent_map_tree {
......
...@@ -224,6 +224,7 @@ int btrfs_drop_extent_cache(struct inode *inode, u64 start, u64 end, ...@@ -224,6 +224,7 @@ int btrfs_drop_extent_cache(struct inode *inode, u64 start, u64 end,
split->bdev = em->bdev; split->bdev = em->bdev;
split->flags = flags; split->flags = flags;
split->compress_type = em->compress_type;
ret = add_extent_mapping(em_tree, split); ret = add_extent_mapping(em_tree, split);
BUG_ON(ret); BUG_ON(ret);
free_extent_map(split); free_extent_map(split);
...@@ -238,6 +239,7 @@ int btrfs_drop_extent_cache(struct inode *inode, u64 start, u64 end, ...@@ -238,6 +239,7 @@ int btrfs_drop_extent_cache(struct inode *inode, u64 start, u64 end,
split->len = em->start + em->len - (start + len); split->len = em->start + em->len - (start + len);
split->bdev = em->bdev; split->bdev = em->bdev;
split->flags = flags; split->flags = flags;
split->compress_type = em->compress_type;
if (compressed) { if (compressed) {
split->block_len = em->block_len; split->block_len = em->block_len;
......
...@@ -122,10 +122,10 @@ static noinline int insert_inline_extent(struct btrfs_trans_handle *trans, ...@@ -122,10 +122,10 @@ static noinline int insert_inline_extent(struct btrfs_trans_handle *trans,
size_t cur_size = size; size_t cur_size = size;
size_t datasize; size_t datasize;
unsigned long offset; unsigned long offset;
int use_compress = 0; int compress_type = BTRFS_COMPRESS_NONE;
if (compressed_size && compressed_pages) { if (compressed_size && compressed_pages) {
use_compress = 1; compress_type = root->fs_info->compress_type;
cur_size = compressed_size; cur_size = compressed_size;
} }
...@@ -159,7 +159,7 @@ static noinline int insert_inline_extent(struct btrfs_trans_handle *trans, ...@@ -159,7 +159,7 @@ static noinline int insert_inline_extent(struct btrfs_trans_handle *trans,
btrfs_set_file_extent_ram_bytes(leaf, ei, size); btrfs_set_file_extent_ram_bytes(leaf, ei, size);
ptr = btrfs_file_extent_inline_start(ei); ptr = btrfs_file_extent_inline_start(ei);
if (use_compress) { if (compress_type != BTRFS_COMPRESS_NONE) {
struct page *cpage; struct page *cpage;
int i = 0; int i = 0;
while (compressed_size > 0) { while (compressed_size > 0) {
...@@ -176,7 +176,7 @@ static noinline int insert_inline_extent(struct btrfs_trans_handle *trans, ...@@ -176,7 +176,7 @@ static noinline int insert_inline_extent(struct btrfs_trans_handle *trans,
compressed_size -= cur_size; compressed_size -= cur_size;
} }
btrfs_set_file_extent_compression(leaf, ei, btrfs_set_file_extent_compression(leaf, ei,
BTRFS_COMPRESS_ZLIB); compress_type);
} else { } else {
page = find_get_page(inode->i_mapping, page = find_get_page(inode->i_mapping,
start >> PAGE_CACHE_SHIFT); start >> PAGE_CACHE_SHIFT);
...@@ -263,6 +263,7 @@ struct async_extent { ...@@ -263,6 +263,7 @@ struct async_extent {
u64 compressed_size; u64 compressed_size;
struct page **pages; struct page **pages;
unsigned long nr_pages; unsigned long nr_pages;
int compress_type;
struct list_head list; struct list_head list;
}; };
...@@ -280,7 +281,8 @@ static noinline int add_async_extent(struct async_cow *cow, ...@@ -280,7 +281,8 @@ static noinline int add_async_extent(struct async_cow *cow,
u64 start, u64 ram_size, u64 start, u64 ram_size,
u64 compressed_size, u64 compressed_size,
struct page **pages, struct page **pages,
unsigned long nr_pages) unsigned long nr_pages,
int compress_type)
{ {
struct async_extent *async_extent; struct async_extent *async_extent;
...@@ -290,6 +292,7 @@ static noinline int add_async_extent(struct async_cow *cow, ...@@ -290,6 +292,7 @@ static noinline int add_async_extent(struct async_cow *cow,
async_extent->compressed_size = compressed_size; async_extent->compressed_size = compressed_size;
async_extent->pages = pages; async_extent->pages = pages;
async_extent->nr_pages = nr_pages; async_extent->nr_pages = nr_pages;
async_extent->compress_type = compress_type;
list_add_tail(&async_extent->list, &cow->extents); list_add_tail(&async_extent->list, &cow->extents);
return 0; return 0;
} }
...@@ -332,6 +335,7 @@ static noinline int compress_file_range(struct inode *inode, ...@@ -332,6 +335,7 @@ static noinline int compress_file_range(struct inode *inode,
unsigned long max_uncompressed = 128 * 1024; unsigned long max_uncompressed = 128 * 1024;
int i; int i;
int will_compress; int will_compress;
int compress_type = root->fs_info->compress_type;
actual_end = min_t(u64, isize, end + 1); actual_end = min_t(u64, isize, end + 1);
again: again:
...@@ -381,12 +385,16 @@ static noinline int compress_file_range(struct inode *inode, ...@@ -381,12 +385,16 @@ static noinline int compress_file_range(struct inode *inode,
WARN_ON(pages); WARN_ON(pages);
pages = kzalloc(sizeof(struct page *) * nr_pages, GFP_NOFS); pages = kzalloc(sizeof(struct page *) * nr_pages, GFP_NOFS);
ret = btrfs_zlib_compress_pages(inode->i_mapping, start, if (BTRFS_I(inode)->force_compress)
total_compressed, pages, compress_type = BTRFS_I(inode)->force_compress;
nr_pages, &nr_pages_ret,
&total_in, ret = btrfs_compress_pages(compress_type,
&total_compressed, inode->i_mapping, start,
max_compressed); total_compressed, pages,
nr_pages, &nr_pages_ret,
&total_in,
&total_compressed,
max_compressed);
if (!ret) { if (!ret) {
unsigned long offset = total_compressed & unsigned long offset = total_compressed &
...@@ -493,7 +501,8 @@ static noinline int compress_file_range(struct inode *inode, ...@@ -493,7 +501,8 @@ static noinline int compress_file_range(struct inode *inode,
* and will submit them to the elevator. * and will submit them to the elevator.
*/ */
add_async_extent(async_cow, start, num_bytes, add_async_extent(async_cow, start, num_bytes,
total_compressed, pages, nr_pages_ret); total_compressed, pages, nr_pages_ret,
compress_type);
if (start + num_bytes < end) { if (start + num_bytes < end) {
start += num_bytes; start += num_bytes;
...@@ -515,7 +524,8 @@ static noinline int compress_file_range(struct inode *inode, ...@@ -515,7 +524,8 @@ static noinline int compress_file_range(struct inode *inode,
__set_page_dirty_nobuffers(locked_page); __set_page_dirty_nobuffers(locked_page);
/* unlocked later on in the async handlers */ /* unlocked later on in the async handlers */
} }
add_async_extent(async_cow, start, end - start + 1, 0, NULL, 0); add_async_extent(async_cow, start, end - start + 1,
0, NULL, 0, BTRFS_COMPRESS_NONE);
*num_added += 1; *num_added += 1;
} }
...@@ -640,6 +650,7 @@ static noinline int submit_compressed_extents(struct inode *inode, ...@@ -640,6 +650,7 @@ static noinline int submit_compressed_extents(struct inode *inode,
em->block_start = ins.objectid; em->block_start = ins.objectid;
em->block_len = ins.offset; em->block_len = ins.offset;
em->bdev = root->fs_info->fs_devices->latest_bdev; em->bdev = root->fs_info->fs_devices->latest_bdev;
em->compress_type = async_extent->compress_type;
set_bit(EXTENT_FLAG_PINNED, &em->flags); set_bit(EXTENT_FLAG_PINNED, &em->flags);
set_bit(EXTENT_FLAG_COMPRESSED, &em->flags); set_bit(EXTENT_FLAG_COMPRESSED, &em->flags);
...@@ -656,11 +667,13 @@ static noinline int submit_compressed_extents(struct inode *inode, ...@@ -656,11 +667,13 @@ static noinline int submit_compressed_extents(struct inode *inode,
async_extent->ram_size - 1, 0); async_extent->ram_size - 1, 0);
} }
ret = btrfs_add_ordered_extent(inode, async_extent->start, ret = btrfs_add_ordered_extent_compress(inode,
ins.objectid, async_extent->start,
async_extent->ram_size, ins.objectid,
ins.offset, async_extent->ram_size,
BTRFS_ORDERED_COMPRESSED); ins.offset,
BTRFS_ORDERED_COMPRESSED,
async_extent->compress_type);
BUG_ON(ret); BUG_ON(ret);
/* /*
...@@ -1670,7 +1683,7 @@ static int btrfs_finish_ordered_io(struct inode *inode, u64 start, u64 end) ...@@ -1670,7 +1683,7 @@ static int btrfs_finish_ordered_io(struct inode *inode, u64 start, u64 end)
struct btrfs_ordered_extent *ordered_extent = NULL; struct btrfs_ordered_extent *ordered_extent = NULL;
struct extent_io_tree *io_tree = &BTRFS_I(inode)->io_tree; struct extent_io_tree *io_tree = &BTRFS_I(inode)->io_tree;
struct extent_state *cached_state = NULL; struct extent_state *cached_state = NULL;
int compressed = 0; int compress_type = 0;
int ret; int ret;
bool nolock = false; bool nolock = false;
...@@ -1711,9 +1724,9 @@ static int btrfs_finish_ordered_io(struct inode *inode, u64 start, u64 end) ...@@ -1711,9 +1724,9 @@ static int btrfs_finish_ordered_io(struct inode *inode, u64 start, u64 end)
trans->block_rsv = &root->fs_info->delalloc_block_rsv; trans->block_rsv = &root->fs_info->delalloc_block_rsv;
if (test_bit(BTRFS_ORDERED_COMPRESSED, &ordered_extent->flags)) if (test_bit(BTRFS_ORDERED_COMPRESSED, &ordered_extent->flags))
compressed = 1; compress_type = ordered_extent->compress_type;
if (test_bit(BTRFS_ORDERED_PREALLOC, &ordered_extent->flags)) { if (test_bit(BTRFS_ORDERED_PREALLOC, &ordered_extent->flags)) {
BUG_ON(compressed); BUG_ON(compress_type);
ret = btrfs_mark_extent_written(trans, inode, ret = btrfs_mark_extent_written(trans, inode,
ordered_extent->file_offset, ordered_extent->file_offset,
ordered_extent->file_offset + ordered_extent->file_offset +
...@@ -1727,7 +1740,7 @@ static int btrfs_finish_ordered_io(struct inode *inode, u64 start, u64 end) ...@@ -1727,7 +1740,7 @@ static int btrfs_finish_ordered_io(struct inode *inode, u64 start, u64 end)
ordered_extent->disk_len, ordered_extent->disk_len,
ordered_extent->len, ordered_extent->len,
ordered_extent->len, ordered_extent->len,
compressed, 0, 0, compress_type, 0, 0,
BTRFS_FILE_EXTENT_REG); BTRFS_FILE_EXTENT_REG);
unpin_extent_cache(&BTRFS_I(inode)->extent_tree, unpin_extent_cache(&BTRFS_I(inode)->extent_tree,
ordered_extent->file_offset, ordered_extent->file_offset,
...@@ -1829,6 +1842,8 @@ static int btrfs_io_failed_hook(struct bio *failed_bio, ...@@ -1829,6 +1842,8 @@ static int btrfs_io_failed_hook(struct bio *failed_bio,
if (test_bit(EXTENT_FLAG_COMPRESSED, &em->flags)) { if (test_bit(EXTENT_FLAG_COMPRESSED, &em->flags)) {
logical = em->block_start; logical = em->block_start;
failrec->bio_flags = EXTENT_BIO_COMPRESSED; failrec->bio_flags = EXTENT_BIO_COMPRESSED;
extent_set_compress_type(&failrec->bio_flags,
em->compress_type);
} }
failrec->logical = logical; failrec->logical = logical;
free_extent_map(em); free_extent_map(em);
...@@ -4934,8 +4949,10 @@ static noinline int uncompress_inline(struct btrfs_path *path, ...@@ -4934,8 +4949,10 @@ static noinline int uncompress_inline(struct btrfs_path *path,
size_t max_size; size_t max_size;
unsigned long inline_size; unsigned long inline_size;
unsigned long ptr; unsigned long ptr;
int compress_type;
WARN_ON(pg_offset != 0); WARN_ON(pg_offset != 0);
compress_type = btrfs_file_extent_compression(leaf, item);
max_size = btrfs_file_extent_ram_bytes(leaf, item); max_size = btrfs_file_extent_ram_bytes(leaf, item);
inline_size = btrfs_file_extent_inline_item_len(leaf, inline_size = btrfs_file_extent_inline_item_len(leaf,
btrfs_item_nr(leaf, path->slots[0])); btrfs_item_nr(leaf, path->slots[0]));
...@@ -4945,8 +4962,8 @@ static noinline int uncompress_inline(struct btrfs_path *path, ...@@ -4945,8 +4962,8 @@ static noinline int uncompress_inline(struct btrfs_path *path,
read_extent_buffer(leaf, tmp, ptr, inline_size); read_extent_buffer(leaf, tmp, ptr, inline_size);
max_size = min_t(unsigned long, PAGE_CACHE_SIZE, max_size); max_size = min_t(unsigned long, PAGE_CACHE_SIZE, max_size);
ret = btrfs_zlib_decompress(tmp, page, extent_offset, ret = btrfs_decompress(compress_type, tmp, page,
inline_size, max_size); extent_offset, inline_size, max_size);
if (ret) { if (ret) {
char *kaddr = kmap_atomic(page, KM_USER0); char *kaddr = kmap_atomic(page, KM_USER0);
unsigned long copy_size = min_t(u64, unsigned long copy_size = min_t(u64,
...@@ -4988,7 +5005,7 @@ struct extent_map *btrfs_get_extent(struct inode *inode, struct page *page, ...@@ -4988,7 +5005,7 @@ struct extent_map *btrfs_get_extent(struct inode *inode, struct page *page,
struct extent_map_tree *em_tree = &BTRFS_I(inode)->extent_tree; struct extent_map_tree *em_tree = &BTRFS_I(inode)->extent_tree;
struct extent_io_tree *io_tree = &BTRFS_I(inode)->io_tree; struct extent_io_tree *io_tree = &BTRFS_I(inode)->io_tree;
struct btrfs_trans_handle *trans = NULL; struct btrfs_trans_handle *trans = NULL;
int compressed; int compress_type;
again: again:
read_lock(&em_tree->lock); read_lock(&em_tree->lock);
...@@ -5047,7 +5064,7 @@ struct extent_map *btrfs_get_extent(struct inode *inode, struct page *page, ...@@ -5047,7 +5064,7 @@ struct extent_map *btrfs_get_extent(struct inode *inode, struct page *page,
found_type = btrfs_file_extent_type(leaf, item); found_type = btrfs_file_extent_type(leaf, item);
extent_start = found_key.offset; extent_start = found_key.offset;
compressed = btrfs_file_extent_compression(leaf, item); compress_type = btrfs_file_extent_compression(leaf, item);
if (found_type == BTRFS_FILE_EXTENT_REG || if (found_type == BTRFS_FILE_EXTENT_REG ||
found_type == BTRFS_FILE_EXTENT_PREALLOC) { found_type == BTRFS_FILE_EXTENT_PREALLOC) {
extent_end = extent_start + extent_end = extent_start +
...@@ -5093,8 +5110,9 @@ struct extent_map *btrfs_get_extent(struct inode *inode, struct page *page, ...@@ -5093,8 +5110,9 @@ struct extent_map *btrfs_get_extent(struct inode *inode, struct page *page,
em->block_start = EXTENT_MAP_HOLE; em->block_start = EXTENT_MAP_HOLE;
goto insert; goto insert;
} }
if (compressed) { if (compress_type != BTRFS_COMPRESS_NONE) {
set_bit(EXTENT_FLAG_COMPRESSED, &em->flags); set_bit(EXTENT_FLAG_COMPRESSED, &em->flags);
em->compress_type = compress_type;
em->block_start = bytenr; em->block_start = bytenr;
em->block_len = btrfs_file_extent_disk_num_bytes(leaf, em->block_len = btrfs_file_extent_disk_num_bytes(leaf,
item); item);
...@@ -5128,12 +5146,14 @@ struct extent_map *btrfs_get_extent(struct inode *inode, struct page *page, ...@@ -5128,12 +5146,14 @@ struct extent_map *btrfs_get_extent(struct inode *inode, struct page *page,
em->len = (copy_size + root->sectorsize - 1) & em->len = (copy_size + root->sectorsize - 1) &
~((u64)root->sectorsize - 1); ~((u64)root->sectorsize - 1);
em->orig_start = EXTENT_MAP_INLINE; em->orig_start = EXTENT_MAP_INLINE;
if (compressed) if (compress_type) {
set_bit(EXTENT_FLAG_COMPRESSED, &em->flags); set_bit(EXTENT_FLAG_COMPRESSED, &em->flags);
em->compress_type = compress_type;
}
ptr = btrfs_file_extent_inline_start(item) + extent_offset; ptr = btrfs_file_extent_inline_start(item) + extent_offset;
if (create == 0 && !PageUptodate(page)) { if (create == 0 && !PageUptodate(page)) {
if (btrfs_file_extent_compression(leaf, item) == if (btrfs_file_extent_compression(leaf, item) !=
BTRFS_COMPRESS_ZLIB) { BTRFS_COMPRESS_NONE) {
ret = uncompress_inline(path, inode, page, ret = uncompress_inline(path, inode, page,
pg_offset, pg_offset,
extent_offset, item); extent_offset, item);
...@@ -6483,7 +6503,7 @@ struct inode *btrfs_alloc_inode(struct super_block *sb) ...@@ -6483,7 +6503,7 @@ struct inode *btrfs_alloc_inode(struct super_block *sb)
ei->ordered_data_close = 0; ei->ordered_data_close = 0;
ei->orphan_meta_reserved = 0; ei->orphan_meta_reserved = 0;
ei->dummy_inode = 0; ei->dummy_inode = 0;
ei->force_compress = 0; ei->force_compress = BTRFS_COMPRESS_NONE;
inode = &ei->vfs_inode; inode = &ei->vfs_inode;
extent_map_tree_init(&ei->extent_tree, GFP_NOFS); extent_map_tree_init(&ei->extent_tree, GFP_NOFS);
......
...@@ -643,9 +643,11 @@ static int btrfs_defrag_file(struct file *file, ...@@ -643,9 +643,11 @@ static int btrfs_defrag_file(struct file *file,
struct extent_io_tree *io_tree = &BTRFS_I(inode)->io_tree; struct extent_io_tree *io_tree = &BTRFS_I(inode)->io_tree;
struct btrfs_ordered_extent *ordered; struct btrfs_ordered_extent *ordered;
struct page *page; struct page *page;
struct btrfs_super_block *disk_super;
unsigned long last_index; unsigned long last_index;
unsigned long ra_pages = root->fs_info->bdi.ra_pages; unsigned long ra_pages = root->fs_info->bdi.ra_pages;
unsigned long total_read = 0; unsigned long total_read = 0;
u64 features;
u64 page_start; u64 page_start;
u64 page_end; u64 page_end;
u64 last_len = 0; u64 last_len = 0;
...@@ -653,6 +655,14 @@ static int btrfs_defrag_file(struct file *file, ...@@ -653,6 +655,14 @@ static int btrfs_defrag_file(struct file *file,
u64 defrag_end = 0; u64 defrag_end = 0;
unsigned long i; unsigned long i;
int ret; int ret;
int compress_type = BTRFS_COMPRESS_ZLIB;
if (range->flags & BTRFS_DEFRAG_RANGE_COMPRESS) {
if (range->compress_type > BTRFS_COMPRESS_TYPES)
return -EINVAL;
if (range->compress_type)
compress_type = range->compress_type;
}
if (inode->i_size == 0) if (inode->i_size == 0)
return 0; return 0;
...@@ -688,7 +698,7 @@ static int btrfs_defrag_file(struct file *file, ...@@ -688,7 +698,7 @@ static int btrfs_defrag_file(struct file *file,
total_read++; total_read++;
mutex_lock(&inode->i_mutex); mutex_lock(&inode->i_mutex);
if (range->flags & BTRFS_DEFRAG_RANGE_COMPRESS) if (range->flags & BTRFS_DEFRAG_RANGE_COMPRESS)
BTRFS_I(inode)->force_compress = 1; BTRFS_I(inode)->force_compress = compress_type;
ret = btrfs_delalloc_reserve_space(inode, PAGE_CACHE_SIZE); ret = btrfs_delalloc_reserve_space(inode, PAGE_CACHE_SIZE);
if (ret) if (ret)
...@@ -786,10 +796,17 @@ static int btrfs_defrag_file(struct file *file, ...@@ -786,10 +796,17 @@ static int btrfs_defrag_file(struct file *file,
atomic_dec(&root->fs_info->async_submit_draining); atomic_dec(&root->fs_info->async_submit_draining);
mutex_lock(&inode->i_mutex); mutex_lock(&inode->i_mutex);
BTRFS_I(inode)->force_compress = 0; BTRFS_I(inode)->force_compress = BTRFS_COMPRESS_NONE;
mutex_unlock(&inode->i_mutex); mutex_unlock(&inode->i_mutex);
} }
disk_super = &root->fs_info->super_copy;
features = btrfs_super_incompat_flags(disk_super);
if (range->compress_type == BTRFS_COMPRESS_LZO) {
features |= BTRFS_FEATURE_INCOMPAT_COMPRESS_LZO;
btrfs_set_super_incompat_flags(disk_super, features);
}
return 0; return 0;
err_reservations: err_reservations:
......
...@@ -134,8 +134,15 @@ struct btrfs_ioctl_defrag_range_args { ...@@ -134,8 +134,15 @@ struct btrfs_ioctl_defrag_range_args {
*/ */
__u32 extent_thresh; __u32 extent_thresh;
/*
* which compression method to use if turning on compression
* for this defrag operation. If unspecified, zlib will
* be used
*/
__u32 compress_type;
/* spare for later */ /* spare for later */
__u32 unused[5]; __u32 unused[4];
}; };
struct btrfs_ioctl_space_info { struct btrfs_ioctl_space_info {
......
This diff is collapsed.
...@@ -172,7 +172,7 @@ static inline struct rb_node *tree_search(struct btrfs_ordered_inode_tree *tree, ...@@ -172,7 +172,7 @@ static inline struct rb_node *tree_search(struct btrfs_ordered_inode_tree *tree,
*/ */
static int __btrfs_add_ordered_extent(struct inode *inode, u64 file_offset, static int __btrfs_add_ordered_extent(struct inode *inode, u64 file_offset,
u64 start, u64 len, u64 disk_len, u64 start, u64 len, u64 disk_len,
int type, int dio) int type, int dio, int compress_type)
{ {
struct btrfs_ordered_inode_tree *tree; struct btrfs_ordered_inode_tree *tree;
struct rb_node *node; struct rb_node *node;
...@@ -189,6 +189,7 @@ static int __btrfs_add_ordered_extent(struct inode *inode, u64 file_offset, ...@@ -189,6 +189,7 @@ static int __btrfs_add_ordered_extent(struct inode *inode, u64 file_offset,
entry->disk_len = disk_len; entry->disk_len = disk_len;
entry->bytes_left = len; entry->bytes_left = len;
entry->inode = inode; entry->inode = inode;
entry->compress_type = compress_type;
if (type != BTRFS_ORDERED_IO_DONE && type != BTRFS_ORDERED_COMPLETE) if (type != BTRFS_ORDERED_IO_DONE && type != BTRFS_ORDERED_COMPLETE)
set_bit(type, &entry->flags); set_bit(type, &entry->flags);
...@@ -220,14 +221,25 @@ int btrfs_add_ordered_extent(struct inode *inode, u64 file_offset, ...@@ -220,14 +221,25 @@ int btrfs_add_ordered_extent(struct inode *inode, u64 file_offset,
u64 start, u64 len, u64 disk_len, int type) u64 start, u64 len, u64 disk_len, int type)
{ {
return __btrfs_add_ordered_extent(inode, file_offset, start, len, return __btrfs_add_ordered_extent(inode, file_offset, start, len,
disk_len, type, 0); disk_len, type, 0,
BTRFS_COMPRESS_NONE);
} }
int btrfs_add_ordered_extent_dio(struct inode *inode, u64 file_offset, int btrfs_add_ordered_extent_dio(struct inode *inode, u64 file_offset,
u64 start, u64 len, u64 disk_len, int type) u64 start, u64 len, u64 disk_len, int type)
{ {
return __btrfs_add_ordered_extent(inode, file_offset, start, len, return __btrfs_add_ordered_extent(inode, file_offset, start, len,
disk_len, type, 1); disk_len, type, 1,
BTRFS_COMPRESS_NONE);
}
int btrfs_add_ordered_extent_compress(struct inode *inode, u64 file_offset,
u64 start, u64 len, u64 disk_len,
int type, int compress_type)
{
return __btrfs_add_ordered_extent(inode, file_offset, start, len,
disk_len, type, 0,
compress_type);
} }
/* /*
......
...@@ -68,7 +68,7 @@ struct btrfs_ordered_sum { ...@@ -68,7 +68,7 @@ struct btrfs_ordered_sum {
#define BTRFS_ORDERED_NOCOW 2 /* set when we want to write in place */ #define BTRFS_ORDERED_NOCOW 2 /* set when we want to write in place */
#define BTRFS_ORDERED_COMPRESSED 3 /* writing a compressed extent */ #define BTRFS_ORDERED_COMPRESSED 3 /* writing a zlib compressed extent */
#define BTRFS_ORDERED_PREALLOC 4 /* set when writing to prealloced extent */ #define BTRFS_ORDERED_PREALLOC 4 /* set when writing to prealloced extent */
...@@ -93,6 +93,9 @@ struct btrfs_ordered_extent { ...@@ -93,6 +93,9 @@ struct btrfs_ordered_extent {
/* flags (described above) */ /* flags (described above) */
unsigned long flags; unsigned long flags;
/* compression algorithm */
int compress_type;
/* reference count */ /* reference count */
atomic_t refs; atomic_t refs;
...@@ -148,6 +151,9 @@ int btrfs_add_ordered_extent(struct inode *inode, u64 file_offset, ...@@ -148,6 +151,9 @@ int btrfs_add_ordered_extent(struct inode *inode, u64 file_offset,
u64 start, u64 len, u64 disk_len, int type); u64 start, u64 len, u64 disk_len, int type);
int btrfs_add_ordered_extent_dio(struct inode *inode, u64 file_offset, int btrfs_add_ordered_extent_dio(struct inode *inode, u64 file_offset,
u64 start, u64 len, u64 disk_len, int type); u64 start, u64 len, u64 disk_len, int type);
int btrfs_add_ordered_extent_compress(struct inode *inode, u64 file_offset,
u64 start, u64 len, u64 disk_len,
int type, int compress_type);
int btrfs_add_ordered_sum(struct inode *inode, int btrfs_add_ordered_sum(struct inode *inode,
struct btrfs_ordered_extent *entry, struct btrfs_ordered_extent *entry,
struct btrfs_ordered_sum *sum); struct btrfs_ordered_sum *sum);
......
...@@ -69,9 +69,9 @@ enum { ...@@ -69,9 +69,9 @@ enum {
Opt_degraded, Opt_subvol, Opt_subvolid, Opt_device, Opt_nodatasum, Opt_degraded, Opt_subvol, Opt_subvolid, Opt_device, Opt_nodatasum,
Opt_nodatacow, Opt_max_inline, Opt_alloc_start, Opt_nobarrier, Opt_ssd, Opt_nodatacow, Opt_max_inline, Opt_alloc_start, Opt_nobarrier, Opt_ssd,
Opt_nossd, Opt_ssd_spread, Opt_thread_pool, Opt_noacl, Opt_compress, Opt_nossd, Opt_ssd_spread, Opt_thread_pool, Opt_noacl, Opt_compress,
Opt_compress_force, Opt_notreelog, Opt_ratio, Opt_flushoncommit, Opt_compress_type, Opt_compress_force, Opt_compress_force_type,
Opt_discard, Opt_space_cache, Opt_clear_cache, Opt_err, Opt_notreelog, Opt_ratio, Opt_flushoncommit, Opt_discard,
Opt_user_subvol_rm_allowed, Opt_space_cache, Opt_clear_cache, Opt_user_subvol_rm_allowed, Opt_err,
}; };
static match_table_t tokens = { static match_table_t tokens = {
...@@ -86,7 +86,9 @@ static match_table_t tokens = { ...@@ -86,7 +86,9 @@ static match_table_t tokens = {
{Opt_alloc_start, "alloc_start=%s"}, {Opt_alloc_start, "alloc_start=%s"},
{Opt_thread_pool, "thread_pool=%d"}, {Opt_thread_pool, "thread_pool=%d"},
{Opt_compress, "compress"}, {Opt_compress, "compress"},
{Opt_compress_type, "compress=%s"},
{Opt_compress_force, "compress-force"}, {Opt_compress_force, "compress-force"},
{Opt_compress_force_type, "compress-force=%s"},
{Opt_ssd, "ssd"}, {Opt_ssd, "ssd"},
{Opt_ssd_spread, "ssd_spread"}, {Opt_ssd_spread, "ssd_spread"},
{Opt_nossd, "nossd"}, {Opt_nossd, "nossd"},
...@@ -112,6 +114,8 @@ int btrfs_parse_options(struct btrfs_root *root, char *options) ...@@ -112,6 +114,8 @@ int btrfs_parse_options(struct btrfs_root *root, char *options)
char *p, *num, *orig; char *p, *num, *orig;
int intarg; int intarg;
int ret = 0; int ret = 0;
char *compress_type;
bool compress_force = false;
if (!options) if (!options)
return 0; return 0;
...@@ -154,14 +158,32 @@ int btrfs_parse_options(struct btrfs_root *root, char *options) ...@@ -154,14 +158,32 @@ int btrfs_parse_options(struct btrfs_root *root, char *options)
btrfs_set_opt(info->mount_opt, NODATACOW); btrfs_set_opt(info->mount_opt, NODATACOW);
btrfs_set_opt(info->mount_opt, NODATASUM); btrfs_set_opt(info->mount_opt, NODATASUM);
break; break;
case Opt_compress:
printk(KERN_INFO "btrfs: use compression\n");
btrfs_set_opt(info->mount_opt, COMPRESS);
break;
case Opt_compress_force: case Opt_compress_force:
printk(KERN_INFO "btrfs: forcing compression\n"); case Opt_compress_force_type:
btrfs_set_opt(info->mount_opt, FORCE_COMPRESS); compress_force = true;
case Opt_compress:
case Opt_compress_type:
if (token == Opt_compress ||
token == Opt_compress_force ||
strcmp(args[0].from, "zlib") == 0) {
compress_type = "zlib";
info->compress_type = BTRFS_COMPRESS_ZLIB;
} else if (strcmp(args[0].from, "lzo") == 0) {
compress_type = "lzo";
info->compress_type = BTRFS_COMPRESS_LZO;
} else {
ret = -EINVAL;
goto out;
}
btrfs_set_opt(info->mount_opt, COMPRESS); btrfs_set_opt(info->mount_opt, COMPRESS);
if (compress_force) {
btrfs_set_opt(info->mount_opt, FORCE_COMPRESS);
pr_info("btrfs: force %s compression\n",
compress_type);
} else
pr_info("btrfs: use %s compression\n",
compress_type);
break; break;
case Opt_ssd: case Opt_ssd:
printk(KERN_INFO "btrfs: use ssd allocation scheme\n"); printk(KERN_INFO "btrfs: use ssd allocation scheme\n");
...@@ -898,10 +920,14 @@ static int __init init_btrfs_fs(void) ...@@ -898,10 +920,14 @@ static int __init init_btrfs_fs(void)
if (err) if (err)
return err; return err;
err = btrfs_init_cachep(); err = btrfs_init_compress();
if (err) if (err)
goto free_sysfs; goto free_sysfs;
err = btrfs_init_cachep();
if (err)
goto free_compress;
err = extent_io_init(); err = extent_io_init();
if (err) if (err)
goto free_cachep; goto free_cachep;
...@@ -929,6 +955,8 @@ static int __init init_btrfs_fs(void) ...@@ -929,6 +955,8 @@ static int __init init_btrfs_fs(void)
extent_io_exit(); extent_io_exit();
free_cachep: free_cachep:
btrfs_destroy_cachep(); btrfs_destroy_cachep();
free_compress:
btrfs_exit_compress();
free_sysfs: free_sysfs:
btrfs_exit_sysfs(); btrfs_exit_sysfs();
return err; return err;
...@@ -943,7 +971,7 @@ static void __exit exit_btrfs_fs(void) ...@@ -943,7 +971,7 @@ static void __exit exit_btrfs_fs(void)
unregister_filesystem(&btrfs_fs_type); unregister_filesystem(&btrfs_fs_type);
btrfs_exit_sysfs(); btrfs_exit_sysfs();
btrfs_cleanup_fs_uuids(); btrfs_cleanup_fs_uuids();
btrfs_zlib_exit(); btrfs_exit_compress();
} }
module_init(init_btrfs_fs) module_init(init_btrfs_fs)
......
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment