0001
0002
0003
0004
0005
0006
0007 #include <linux/kernel.h>
0008 #include <linux/slab.h>
0009 #include <linux/pagemap.h>
0010 #include "squashfs_fs_sb.h"
0011 #include "decompressor.h"
0012 #include "page_actor.h"
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024 static void *cache_first_page(struct squashfs_page_actor *actor)
0025 {
0026 actor->next_page = 1;
0027 return actor->buffer[0];
0028 }
0029
0030 static void *cache_next_page(struct squashfs_page_actor *actor)
0031 {
0032 if (actor->next_page == actor->pages)
0033 return NULL;
0034
0035 return actor->buffer[actor->next_page++];
0036 }
0037
0038 static void cache_finish_page(struct squashfs_page_actor *actor)
0039 {
0040
0041 }
0042
0043 struct squashfs_page_actor *squashfs_page_actor_init(void **buffer,
0044 int pages, int length)
0045 {
0046 struct squashfs_page_actor *actor = kmalloc(sizeof(*actor), GFP_KERNEL);
0047
0048 if (actor == NULL)
0049 return NULL;
0050
0051 actor->length = length ? : pages * PAGE_SIZE;
0052 actor->buffer = buffer;
0053 actor->pages = pages;
0054 actor->next_page = 0;
0055 actor->tmp_buffer = NULL;
0056 actor->squashfs_first_page = cache_first_page;
0057 actor->squashfs_next_page = cache_next_page;
0058 actor->squashfs_finish_page = cache_finish_page;
0059 return actor;
0060 }
0061
0062
0063 static void *handle_next_page(struct squashfs_page_actor *actor)
0064 {
0065 int max_pages = (actor->length + PAGE_SIZE - 1) >> PAGE_SHIFT;
0066
0067 if (actor->returned_pages == max_pages)
0068 return NULL;
0069
0070 if ((actor->next_page == actor->pages) ||
0071 (actor->next_index != actor->page[actor->next_page]->index)) {
0072 actor->next_index++;
0073 actor->returned_pages++;
0074 return actor->alloc_buffer ? actor->tmp_buffer : ERR_PTR(-ENOMEM);
0075 }
0076
0077 actor->next_index++;
0078 actor->returned_pages++;
0079 return actor->pageaddr = kmap_local_page(actor->page[actor->next_page++]);
0080 }
0081
0082 static void *direct_first_page(struct squashfs_page_actor *actor)
0083 {
0084 return handle_next_page(actor);
0085 }
0086
0087 static void *direct_next_page(struct squashfs_page_actor *actor)
0088 {
0089 if (actor->pageaddr) {
0090 kunmap_local(actor->pageaddr);
0091 actor->pageaddr = NULL;
0092 }
0093
0094 return handle_next_page(actor);
0095 }
0096
0097 static void direct_finish_page(struct squashfs_page_actor *actor)
0098 {
0099 if (actor->pageaddr)
0100 kunmap_local(actor->pageaddr);
0101 }
0102
0103 struct squashfs_page_actor *squashfs_page_actor_init_special(struct squashfs_sb_info *msblk,
0104 struct page **page, int pages, int length)
0105 {
0106 struct squashfs_page_actor *actor = kmalloc(sizeof(*actor), GFP_KERNEL);
0107
0108 if (actor == NULL)
0109 return NULL;
0110
0111 if (msblk->decompressor->alloc_buffer) {
0112 actor->tmp_buffer = kmalloc(PAGE_SIZE, GFP_KERNEL);
0113
0114 if (actor->tmp_buffer == NULL) {
0115 kfree(actor);
0116 return NULL;
0117 }
0118 } else
0119 actor->tmp_buffer = NULL;
0120
0121 actor->length = length ? : pages * PAGE_SIZE;
0122 actor->page = page;
0123 actor->pages = pages;
0124 actor->next_page = 0;
0125 actor->returned_pages = 0;
0126 actor->next_index = page[0]->index & ~((1 << (msblk->block_log - PAGE_SHIFT)) - 1);
0127 actor->pageaddr = NULL;
0128 actor->alloc_buffer = msblk->decompressor->alloc_buffer;
0129 actor->squashfs_first_page = direct_first_page;
0130 actor->squashfs_next_page = direct_next_page;
0131 actor->squashfs_finish_page = direct_finish_page;
0132 return actor;
0133 }