~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/fs/squashfs/page_actor.c

Version: ~ [ linux-6.11-rc3 ] ~ [ linux-6.10.4 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.45 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.104 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.164 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.223 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.281 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.319 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 // SPDX-License-Identifier: GPL-2.0-only
  2 /*
  3  * Copyright (c) 2013
  4  * Phillip Lougher <phillip@squashfs.org.uk>
  5  */
  6 
  7 #include <linux/kernel.h>
  8 #include <linux/slab.h>
  9 #include <linux/pagemap.h>
 10 #include "squashfs_fs_sb.h"
 11 #include "decompressor.h"
 12 #include "page_actor.h"
 13 
 14 /*
 15  * This file contains implementations of page_actor for decompressing into
 16  * an intermediate buffer, and for decompressing directly into the
 17  * page cache.
 18  *
 19  * Calling code should avoid sleeping between calls to squashfs_first_page()
 20  * and squashfs_finish_page().
 21  */
 22 
 23 /* Implementation of page_actor for decompressing into intermediate buffer */
 24 static void *cache_first_page(struct squashfs_page_actor *actor)
 25 {
 26         actor->next_page = 1;
 27         return actor->buffer[0];
 28 }
 29 
 30 static void *cache_next_page(struct squashfs_page_actor *actor)
 31 {
 32         if (actor->next_page == actor->pages)
 33                 return NULL;
 34 
 35         return actor->buffer[actor->next_page++];
 36 }
 37 
 38 static void cache_finish_page(struct squashfs_page_actor *actor)
 39 {
 40         /* empty */
 41 }
 42 
 43 struct squashfs_page_actor *squashfs_page_actor_init(void **buffer,
 44         int pages, int length)
 45 {
 46         struct squashfs_page_actor *actor = kmalloc(sizeof(*actor), GFP_KERNEL);
 47 
 48         if (actor == NULL)
 49                 return NULL;
 50 
 51         actor->length = length ? : pages * PAGE_SIZE;
 52         actor->buffer = buffer;
 53         actor->pages = pages;
 54         actor->next_page = 0;
 55         actor->tmp_buffer = NULL;
 56         actor->squashfs_first_page = cache_first_page;
 57         actor->squashfs_next_page = cache_next_page;
 58         actor->squashfs_finish_page = cache_finish_page;
 59         return actor;
 60 }
 61 
 62 /* Implementation of page_actor for decompressing directly into page cache. */
 63 static void *handle_next_page(struct squashfs_page_actor *actor)
 64 {
 65         int max_pages = (actor->length + PAGE_SIZE - 1) >> PAGE_SHIFT;
 66 
 67         if (actor->returned_pages == max_pages)
 68                 return NULL;
 69 
 70         if ((actor->next_page == actor->pages) ||
 71                         (actor->next_index != actor->page[actor->next_page]->index)) {
 72                 actor->next_index++;
 73                 actor->returned_pages++;
 74                 actor->last_page = NULL;
 75                 return actor->alloc_buffer ? actor->tmp_buffer : ERR_PTR(-ENOMEM);
 76         }
 77 
 78         actor->next_index++;
 79         actor->returned_pages++;
 80         actor->last_page = actor->page[actor->next_page];
 81         return actor->pageaddr = kmap_local_page(actor->page[actor->next_page++]);
 82 }
 83 
 84 static void *direct_first_page(struct squashfs_page_actor *actor)
 85 {
 86         return handle_next_page(actor);
 87 }
 88 
 89 static void *direct_next_page(struct squashfs_page_actor *actor)
 90 {
 91         if (actor->pageaddr) {
 92                 kunmap_local(actor->pageaddr);
 93                 actor->pageaddr = NULL;
 94         }
 95 
 96         return handle_next_page(actor);
 97 }
 98 
 99 static void direct_finish_page(struct squashfs_page_actor *actor)
100 {
101         if (actor->pageaddr)
102                 kunmap_local(actor->pageaddr);
103 }
104 
105 struct squashfs_page_actor *squashfs_page_actor_init_special(struct squashfs_sb_info *msblk,
106         struct page **page, int pages, int length)
107 {
108         struct squashfs_page_actor *actor = kmalloc(sizeof(*actor), GFP_KERNEL);
109 
110         if (actor == NULL)
111                 return NULL;
112 
113         if (msblk->decompressor->alloc_buffer) {
114                 actor->tmp_buffer = kmalloc(PAGE_SIZE, GFP_KERNEL);
115 
116                 if (actor->tmp_buffer == NULL) {
117                         kfree(actor);
118                         return NULL;
119                 }
120         } else
121                 actor->tmp_buffer = NULL;
122 
123         actor->length = length ? : pages * PAGE_SIZE;
124         actor->page = page;
125         actor->pages = pages;
126         actor->next_page = 0;
127         actor->returned_pages = 0;
128         actor->next_index = page[0]->index & ~((1 << (msblk->block_log - PAGE_SHIFT)) - 1);
129         actor->pageaddr = NULL;
130         actor->last_page = NULL;
131         actor->alloc_buffer = msblk->decompressor->alloc_buffer;
132         actor->squashfs_first_page = direct_first_page;
133         actor->squashfs_next_page = direct_next_page;
134         actor->squashfs_finish_page = direct_finish_page;
135         return actor;
136 }
137 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php