diff options
Diffstat (limited to 'fs/btrfs/lzo.c')
-rw-r--r-- | fs/btrfs/lzo.c | 44 |
1 files changed, 33 insertions, 11 deletions
diff --git a/fs/btrfs/lzo.c b/fs/btrfs/lzo.c index f410ceabcdbd..9febb8025825 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; @@ -291,6 +305,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); @@ -298,9 +313,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; } @@ -311,6 +328,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; @@ -319,7 +337,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; /* @@ -353,8 +373,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 */ @@ -439,7 +460,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); /* @@ -449,6 +470,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; } |