Select Git revision
file.c 15.71 KiB
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Squashfs - a compressed read only filesystem for Linux
*
* Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008
* Phillip Lougher <phillip@squashfs.org.uk>
*
* file.c
*/
/*
* This file contains code for handling regular files. A regular file
* consists of a sequence of contiguous compressed blocks, and/or a
* compressed fragment block (tail-end packed block). The compressed size
* of each datablock is stored in a block list contained within the
* file inode (itself stored in one or more compressed metadata blocks).
*
* To speed up access to datablocks when reading 'large' files (256 Mbytes or
* larger), the code implements an index cache that caches the mapping from
* block index to datablock location on disk.
*
* The index cache allows Squashfs to handle large files (up to 1.75 TiB) while
* retaining a simple and space-efficient block list on disk. The cache
* is split into slots, caching up to eight 224 GiB files (128 KiB blocks).
* Larger files use multiple slots, with 1.75 TiB files using all 8 slots.
* The index cache is designed to be memory efficient, and by default uses
* 16 KiB.
*/
#include <linux/fs.h>
#include <linux/vfs.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/pagemap.h>
#include <linux/mutex.h>
#include "squashfs_fs.h"
#include "squashfs_fs_sb.h"
#include "squashfs_fs_i.h"
#include "squashfs.h"
#include "page_actor.h"
/*
* Locate cache slot in range [offset, index] for specified inode. If
* there's more than one return the slot closest to index.
*/
static struct meta_index *locate_meta_index(struct inode *inode, int offset,
int index)
{
struct meta_index *meta = NULL;
struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info;
int i;
mutex_lock(&msblk->meta_index_mutex);
TRACE("locate_meta_index: index %d, offset %d\n", index, offset);
if (msblk->meta_index == NULL)
goto not_allocated;
for (i = 0; i < SQUASHFS_META_SLOTS; i++) {
if (msblk->meta_index[i].inode_number == inode->i_ino &&
msblk->meta_index[i].offset >= offset &&
msblk->meta_index[i].offset <= index &&
msblk->meta_index[i].locked == 0) {
TRACE("locate_meta_index: entry %d, offset %d\n", i,
msblk->meta_index[i].offset);
meta = &msblk->meta_index[i];
offset = meta->offset;