aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/lzo.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/btrfs/lzo.c')
-rw-r--r--fs/btrfs/lzo.c44
1 files changed, 33 insertions, 11 deletions
diff --git a/fs/btrfs/lzo.c b/fs/btrfs/lzo.c
index e61f00a192db..0fb90cbe7669 100644
--- a/fs/btrfs/lzo.c
+++ b/fs/btrfs/lzo.c
@@ -132,6 +132,7 @@ static int copy_compressed_data_to_page(char *compressed_data,
u32 sector_bytes_left;
u32 orig_out;
struct page *cur_page;
+ char *kaddr;
if ((*cur_out / PAGE_SIZE) >= max_nr_page)
return -E2BIG;
@@ -151,7 +152,8 @@ static int copy_compressed_data_to_page(char *compressed_data,
out_pages[*cur_out / PAGE_SIZE] = cur_page;
}
- write_compress_length(page_address(cur_page) + offset_in_page(*cur_out),
+ kaddr = kmap(cur_page);
+ write_compress_length(kaddr + offset_in_page(*cur_out),
compressed_size);
*cur_out += LZO_LEN;
@@ -162,6 +164,8 @@ static int copy_compressed_data_to_page(char *compressed_data,
u32 copy_len = min_t(u32, sectorsize - *cur_out % sectorsize,
orig_out + compressed_size - *cur_out);
+ kunmap(cur_page);
+
if ((*cur_out / PAGE_SIZE) >= max_nr_page)
return -E2BIG;
@@ -173,8 +177,9 @@ static int copy_compressed_data_to_page(char *compressed_data,
return -ENOMEM;
out_pages[*cur_out / PAGE_SIZE] = cur_page;
}
+ kaddr = kmap(cur_page);
- memcpy(page_address(cur_page) + offset_in_page(*cur_out),
+ memcpy(kaddr + offset_in_page(*cur_out),
compressed_data + *cur_out - orig_out, copy_len);
*cur_out += copy_len;
@@ -186,12 +191,15 @@ static int copy_compressed_data_to_page(char *compressed_data,
*/
sector_bytes_left = round_up(*cur_out, sectorsize) - *cur_out;
if (sector_bytes_left >= LZO_LEN || sector_bytes_left == 0)
- return 0;
+ goto out;
/* The remaining size is not enough, pad it with zeros */
- memset(page_address(cur_page) + offset_in_page(*cur_out), 0,
+ memset(kaddr + offset_in_page(*cur_out), 0,
sector_bytes_left);
*cur_out += sector_bytes_left;
+
+out:
+ kunmap(cur_page);
return 0;
}
@@ -202,6 +210,7 @@ int lzo_compress_pages(struct list_head *ws, struct address_space *mapping,
struct workspace *workspace = list_entry(ws, struct workspace, list);
const u32 sectorsize = btrfs_sb(mapping->host->i_sb)->sectorsize;
struct page *page_in = NULL;
+ char *sizes_ptr;
const unsigned long max_nr_page = *out_pages;
int ret = 0;
/* Points to the file offset of input data */
@@ -221,6 +230,7 @@ int lzo_compress_pages(struct list_head *ws, struct address_space *mapping,
*/
cur_out += LZO_LEN;
while (cur_in < start + len) {
+ char *data_in;
const u32 sectorsize_mask = sectorsize - 1;
u32 sector_off = (cur_in - start) & sectorsize_mask;
u32 in_len;
@@ -235,10 +245,12 @@ int lzo_compress_pages(struct list_head *ws, struct address_space *mapping,
/* Compress at most one sector of data each time */
in_len = min_t(u32, start + len - cur_in, sectorsize - sector_off);
ASSERT(in_len);
- ret = lzo1x_1_compress(page_address(page_in) +
+ data_in = kmap(page_in);
+ ret = lzo1x_1_compress(data_in +
offset_in_page(cur_in), in_len,
workspace->cbuf, &out_len,
workspace->mem);
+ kunmap(page_in);
if (ret < 0) {
pr_debug("BTRFS: lzo in loop returned %d\n", ret);
ret = -EIO;
@@ -270,7 +282,9 @@ int lzo_compress_pages(struct list_head *ws, struct address_space *mapping,
}
/* Store the size of all chunks of compressed data */
- write_compress_length(page_address(pages[0]), cur_out);
+ sizes_ptr = kmap_local_page(pages[0]);
+ write_compress_length(sizes_ptr, cur_out);
+ kunmap_local(sizes_ptr);
ret = 0;
*total_out = cur_out;
@@ -293,6 +307,7 @@ static void copy_compressed_segment(struct compressed_bio *cb,
u32 orig_in = *cur_in;
while (*cur_in < orig_in + len) {
+ char *kaddr;
struct page *cur_page;
u32 copy_len = min_t(u32, PAGE_SIZE - offset_in_page(*cur_in),
orig_in + len - *cur_in);
@@ -300,9 +315,11 @@ static void copy_compressed_segment(struct compressed_bio *cb,
ASSERT(copy_len);
cur_page = cb->compressed_pages[*cur_in / PAGE_SIZE];
+ kaddr = kmap(cur_page);
memcpy(dest + *cur_in - orig_in,
- page_address(cur_page) + offset_in_page(*cur_in),
+ kaddr + offset_in_page(*cur_in),
copy_len);
+ kunmap(cur_page);
*cur_in += copy_len;
}
@@ -313,6 +330,7 @@ int lzo_decompress_bio(struct list_head *ws, struct compressed_bio *cb)
struct workspace *workspace = list_entry(ws, struct workspace, list);
const struct btrfs_fs_info *fs_info = btrfs_sb(cb->inode->i_sb);
const u32 sectorsize = fs_info->sectorsize;
+ char *kaddr;
int ret;
/* Compressed data length, can be unaligned */
u32 len_in;
@@ -321,7 +339,9 @@ int lzo_decompress_bio(struct list_head *ws, struct compressed_bio *cb)
/* Bytes decompressed so far */
u32 cur_out = 0;
- len_in = read_compress_length(page_address(cb->compressed_pages[0]));
+ kaddr = kmap(cb->compressed_pages[0]);
+ len_in = read_compress_length(kaddr);
+ kunmap(cb->compressed_pages[0]);
cur_in += LZO_LEN;
/*
@@ -355,8 +375,9 @@ int lzo_decompress_bio(struct list_head *ws, struct compressed_bio *cb)
(cur_in + LZO_LEN - 1) / sectorsize);
cur_page = cb->compressed_pages[cur_in / PAGE_SIZE];
ASSERT(cur_page);
- seg_len = read_compress_length(page_address(cur_page) +
- offset_in_page(cur_in));
+ kaddr = kmap(cur_page);
+ seg_len = read_compress_length(kaddr + offset_in_page(cur_in));
+ kunmap(cur_page);
cur_in += LZO_LEN;
/* Copy the compressed segment payload into workspace */
@@ -441,7 +462,7 @@ int lzo_decompress(struct list_head *ws, unsigned char *data_in,
destlen = min_t(unsigned long, destlen, PAGE_SIZE);
bytes = min_t(unsigned long, destlen, out_len - start_byte);
- kaddr = page_address(dest_page);
+ kaddr = kmap_local_page(dest_page);
memcpy(kaddr, workspace->buf + start_byte, bytes);
/*
@@ -451,6 +472,7 @@ int lzo_decompress(struct list_head *ws, unsigned char *data_in,
*/
if (bytes < destlen)
memset(kaddr+bytes, 0, destlen-bytes);
+ kunmap_local(kaddr);
out:
return ret;
}