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

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

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ 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/fs.h>
  8 #include <linux/vfs.h>
  9 #include <linux/kernel.h>
 10 #include <linux/slab.h>
 11 #include <linux/string.h>
 12 #include <linux/pagemap.h>
 13 #include <linux/mutex.h>
 14 
 15 #include "squashfs_fs.h"
 16 #include "squashfs_fs_sb.h"
 17 #include "squashfs_fs_i.h"
 18 #include "squashfs.h"
 19 #include "page_actor.h"
 20 
 21 /* Read separately compressed datablock directly into page cache */
 22 int squashfs_readpage_block(struct page *target_page, u64 block, int bsize,
 23         int expected)
 24 
 25 {
 26         struct inode *inode = target_page->mapping->host;
 27         struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info;
 28 
 29         loff_t file_end = (i_size_read(inode) - 1) >> PAGE_SHIFT;
 30         int mask = (1 << (msblk->block_log - PAGE_SHIFT)) - 1;
 31         loff_t start_index = target_page->index & ~mask;
 32         loff_t end_index = start_index | mask;
 33         int i, n, pages, bytes, res = -ENOMEM;
 34         struct page **page;
 35         struct squashfs_page_actor *actor;
 36         void *pageaddr;
 37 
 38         if (end_index > file_end)
 39                 end_index = file_end;
 40 
 41         pages = end_index - start_index + 1;
 42 
 43         page = kmalloc_array(pages, sizeof(void *), GFP_KERNEL);
 44         if (page == NULL)
 45                 return res;
 46 
 47         /* Try to grab all the pages covered by the Squashfs block */
 48         for (i = 0, n = start_index; n <= end_index; n++) {
 49                 page[i] = (n == target_page->index) ? target_page :
 50                         grab_cache_page_nowait(target_page->mapping, n);
 51 
 52                 if (page[i] == NULL)
 53                         continue;
 54 
 55                 if (PageUptodate(page[i])) {
 56                         unlock_page(page[i]);
 57                         put_page(page[i]);
 58                         continue;
 59                 }
 60 
 61                 i++;
 62         }
 63 
 64         pages = i;
 65 
 66         /*
 67          * Create a "page actor" which will kmap and kunmap the
 68          * page cache pages appropriately within the decompressor
 69          */
 70         actor = squashfs_page_actor_init_special(msblk, page, pages, expected);
 71         if (actor == NULL)
 72                 goto out;
 73 
 74         /* Decompress directly into the page cache buffers */
 75         res = squashfs_read_data(inode->i_sb, block, bsize, NULL, actor);
 76 
 77         squashfs_page_actor_free(actor);
 78 
 79         if (res < 0)
 80                 goto mark_errored;
 81 
 82         if (res != expected) {
 83                 res = -EIO;
 84                 goto mark_errored;
 85         }
 86 
 87         /* Last page (if present) may have trailing bytes not filled */
 88         bytes = res % PAGE_SIZE;
 89         if (page[pages - 1]->index == end_index && bytes) {
 90                 pageaddr = kmap_local_page(page[pages - 1]);
 91                 memset(pageaddr + bytes, 0, PAGE_SIZE - bytes);
 92                 kunmap_local(pageaddr);
 93         }
 94 
 95         /* Mark pages as uptodate, unlock and release */
 96         for (i = 0; i < pages; i++) {
 97                 flush_dcache_page(page[i]);
 98                 SetPageUptodate(page[i]);
 99                 unlock_page(page[i]);
100                 if (page[i] != target_page)
101                         put_page(page[i]);
102         }
103 
104         kfree(page);
105 
106         return 0;
107 
108 mark_errored:
109         /* Decompression failed.  Target_page is
110          * dealt with by the caller
111          */
112         for (i = 0; i < pages; i++) {
113                 if (page[i] == NULL || page[i] == target_page)
114                         continue;
115                 flush_dcache_page(page[i]);
116                 unlock_page(page[i]);
117                 put_page(page[i]);
118         }
119 
120 out:
121         kfree(page);
122         return res;
123 }
124 

~ [ 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