android_kernel_oneplus_msm8998/fs/squashfs/page_actor.h
Adrien Schildknecht 417aca479b Squashfs: refactor page_actor
This patch essentially does 3 things:
  1/ Always use an array of page to store the data instead of a mix of
     buffers and pages.
  2/ It is now possible to have 'holes' in a page actor, i.e. NULL
     pages in the array.
     When reading a block (default 128K), squashfs tries to grab all
     the pages covering this block. If a single page is up-to-date or
     locked, it falls back to using an intermediate buffer to do the
     read and then copy the pages in the actor. Allowing holes in the
     page actor remove the need for this intermediate buffer.
  3/ Refactor the wrappers to share code that deals with page actors.

Signed-off-by: Adrien Schildknecht <adriens@google.com>
Change-Id: I98128bed5d518cf31b67e788a85b275e9a323bec
2017-02-09 04:03:50 +00:00

65 lines
1.9 KiB
C

#ifndef PAGE_ACTOR_H
#define PAGE_ACTOR_H
/*
* Copyright (c) 2013
* Phillip Lougher <phillip@squashfs.org.uk>
*
* This work is licensed under the terms of the GNU GPL, version 2. See
* the COPYING file in the top-level squashfsory.
*/
struct squashfs_page_actor {
struct page **page;
void *pageaddr;
int pages;
int length;
int next_page;
void (*release_pages)(struct page **, int, int);
};
extern struct squashfs_page_actor *squashfs_page_actor_init(struct page **,
int, int, void (*)(struct page **, int, int));
extern void squashfs_page_actor_free(struct squashfs_page_actor *, int);
extern void squashfs_actor_to_buf(struct squashfs_page_actor *, void *, int);
extern void squashfs_buf_to_actor(void *, struct squashfs_page_actor *, int);
extern void squashfs_bh_to_actor(struct buffer_head **, int,
struct squashfs_page_actor *, int, int, int);
extern void squashfs_bh_to_buf(struct buffer_head **, int, void *, int, int,
int);
/*
* Calling code should avoid sleeping between calls to squashfs_first_page()
* and squashfs_finish_page().
*/
static inline void *squashfs_first_page(struct squashfs_page_actor *actor)
{
actor->next_page = 1;
return actor->pageaddr = actor->page[0] ? kmap_atomic(actor->page[0])
: NULL;
}
static inline void *squashfs_next_page(struct squashfs_page_actor *actor)
{
if (!IS_ERR_OR_NULL(actor->pageaddr))
kunmap_atomic(actor->pageaddr);
if (actor->next_page == actor->pages)
return actor->pageaddr = ERR_PTR(-ENODATA);
actor->pageaddr = actor->page[actor->next_page] ?
kmap_atomic(actor->page[actor->next_page]) : NULL;
++actor->next_page;
return actor->pageaddr;
}
static inline void squashfs_finish_page(struct squashfs_page_actor *actor)
{
if (!IS_ERR_OR_NULL(actor->pageaddr))
kunmap_atomic(actor->pageaddr);
}
extern struct page **alloc_page_array(int, int);
extern void free_page_array(struct page **, int);
#endif