Merge branch 'linux-linaro-lsk-v4.4' into linux-linaro-lsk-v4.4-android
[firefly-linux-kernel-4.4.55.git] / fs / squashfs / file_direct.c
1 /*
2  * Copyright (c) 2013
3  * Phillip Lougher <phillip@squashfs.org.uk>
4  *
5  * This work is licensed under the terms of the GNU GPL, version 2. See
6  * the COPYING file in the top-level directory.
7  */
8
9 #include <linux/fs.h>
10 #include <linux/vfs.h>
11 #include <linux/kernel.h>
12 #include <linux/slab.h>
13 #include <linux/string.h>
14 #include <linux/pagemap.h>
15 #include <linux/mutex.h>
16 #include <linux/mm_inline.h>
17
18 #include "squashfs_fs.h"
19 #include "squashfs_fs_sb.h"
20 #include "squashfs_fs_i.h"
21 #include "squashfs.h"
22 #include "page_actor.h"
23
24 // Backported from 4.5
25 #define lru_to_page(head) (list_entry((head)->prev, struct page, lru))
26
27 static void release_actor_pages(struct page **page, int pages, int error)
28 {
29         int i;
30
31         for (i = 0; i < pages; i++) {
32                 if (!page[i])
33                         continue;
34                 flush_dcache_page(page[i]);
35                 if (!error)
36                         SetPageUptodate(page[i]);
37                 else {
38                         SetPageError(page[i]);
39                         zero_user_segment(page[i], 0, PAGE_CACHE_SIZE);
40                 }
41                 unlock_page(page[i]);
42                 put_page(page[i]);
43         }
44         kfree(page);
45 }
46
47 /*
48  * Create a "page actor" which will kmap and kunmap the
49  * page cache pages appropriately within the decompressor
50  */
51 static struct squashfs_page_actor *actor_from_page_cache(
52         unsigned int actor_pages, struct page *target_page,
53         struct list_head *rpages, unsigned int *nr_pages, int start_index,
54         struct address_space *mapping)
55 {
56         struct page **page;
57         struct squashfs_page_actor *actor;
58         int i, n;
59         gfp_t gfp = mapping_gfp_constraint(mapping, GFP_KERNEL);
60
61         page = kmalloc_array(actor_pages, sizeof(void *), GFP_KERNEL);
62         if (!page)
63                 return NULL;
64
65         for (i = 0, n = start_index; i < actor_pages; i++, n++) {
66                 if (target_page == NULL && rpages && !list_empty(rpages)) {
67                         struct page *cur_page = lru_to_page(rpages);
68
69                         if (cur_page->index < start_index + actor_pages) {
70                                 list_del(&cur_page->lru);
71                                 --(*nr_pages);
72                                 if (add_to_page_cache_lru(cur_page, mapping,
73                                                           cur_page->index, gfp))
74                                         put_page(cur_page);
75                                 else
76                                         target_page = cur_page;
77                         } else
78                                 rpages = NULL;
79                 }
80
81                 if (target_page && target_page->index == n) {
82                         page[i] = target_page;
83                         target_page = NULL;
84                 } else {
85                         page[i] = grab_cache_page_nowait(mapping, n);
86                         if (page[i] == NULL)
87                                 continue;
88                 }
89
90                 if (PageUptodate(page[i])) {
91                         unlock_page(page[i]);
92                         put_page(page[i]);
93                         page[i] = NULL;
94                 }
95         }
96
97         actor = squashfs_page_actor_init(page, actor_pages, 0,
98                         release_actor_pages);
99         if (!actor) {
100                 release_actor_pages(page, actor_pages, -ENOMEM);
101                 kfree(page);
102                 return NULL;
103         }
104         return actor;
105 }
106
107 int squashfs_readpages_block(struct page *target_page,
108                              struct list_head *readahead_pages,
109                              unsigned int *nr_pages,
110                              struct address_space *mapping,
111                              int page_index, u64 block, int bsize)
112
113 {
114         struct squashfs_page_actor *actor;
115         struct inode *inode = mapping->host;
116         struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info;
117         int start_index, end_index, file_end, actor_pages, res;
118         int mask = (1 << (msblk->block_log - PAGE_CACHE_SHIFT)) - 1;
119
120         /*
121          * If readpage() is called on an uncompressed datablock, we can just
122          * read the pages instead of fetching the whole block.
123          * This greatly improves the performance when a process keep doing
124          * random reads because we only fetch the necessary data.
125          * The readahead algorithm will take care of doing speculative reads
126          * if necessary.
127          * We can't read more than 1 block even if readahead provides use more
128          * pages because we don't know yet if the next block is compressed or
129          * not.
130          */
131         if (bsize && !SQUASHFS_COMPRESSED_BLOCK(bsize)) {
132                 u64 block_end = block + msblk->block_size;
133
134                 block += (page_index & mask) * PAGE_CACHE_SIZE;
135                 actor_pages = (block_end - block) / PAGE_CACHE_SIZE;
136                 if (*nr_pages < actor_pages)
137                         actor_pages = *nr_pages;
138                 start_index = page_index;
139                 bsize = min_t(int, bsize, (PAGE_CACHE_SIZE * actor_pages)
140                                           | SQUASHFS_COMPRESSED_BIT_BLOCK);
141         } else {
142                 file_end = (i_size_read(inode) - 1) >> PAGE_CACHE_SHIFT;
143                 start_index = page_index & ~mask;
144                 end_index = start_index | mask;
145                 if (end_index > file_end)
146                         end_index = file_end;
147                 actor_pages = end_index - start_index + 1;
148         }
149
150         actor = actor_from_page_cache(actor_pages, target_page,
151                                       readahead_pages, nr_pages, start_index,
152                                       mapping);
153         if (!actor)
154                 return -ENOMEM;
155
156         res = squashfs_read_data_async(inode->i_sb, block, bsize, NULL,
157                                        actor);
158         return res < 0 ? res : 0;
159 }