/*
* This file is part of UBIFS.
*
* Copyright (C) 2006-2008 Nokia Corporation.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published by
* the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc., 51
* Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
* Authors: Artem Bityutskiy (Битюцкий Артём)
* Adrian Hunter
*/
/*
* This file implements VFS file and inode operations of regular files, device
* nodes and symlinks as well as address space operations.
*
* UBIFS uses 2 page flags: PG_private and PG_checked. PG_private is set if the
* page is dirty and is used for budgeting purposes - dirty pages should not be
* budgeted. The PG_checked flag is set if full budgeting is required for the
* page e.g., when it corresponds to a file hole or it is just beyond the file
* size. The budgeting is done in 'ubifs_write_begin()', because it is OK to
* fail in this function, and the budget is released in 'ubifs_write_end()'. So
* the PG_private and PG_checked flags carry the information about how the page
* was budgeted, to make it possible to release the budget properly.
*
* A thing to keep in mind: inode's 'i_mutex' is locked in most VFS operations
* we implement. However, this is not true for '->writepage()', which might be
* called with 'i_mutex' unlocked. For example, when pdflush is performing
* write-back, it calls 'writepage()' with unlocked 'i_mutex', although the
* inode has 'I_LOCK' flag in this case. At "normal" work-paths 'i_mutex' is
* locked in '->writepage', e.g. in "sys_write -> alloc_pages -> direct reclaim
* path'. So, in '->writepage()' we are only guaranteed that the page is
* locked.
*
* Similarly, 'i_mutex' does not have to be locked in readpage(), e.g.,
* readahead path does not have it locked ("sys_read -> generic_file_aio_read
* -> ondemand_readahead -> readpage"). In case of readahead, 'I_LOCK' flag is
* not set as well. However, UBIFS disables readahead.
*
* This, for example means that there might be 2 concurrent '->writepage()'
* calls for the same inode, but different inode dirty pages.
*/
#include "ubifs.h"
#include <linux/mount.h>
#include <linux/namei.h>
static int read_block(struct inode *inode, void *addr, unsigned int block,
struct ubifs_data_node *dn)
{
struct ubifs_info *c = inode->i_sb->s_fs_info;
int err, len, out_len;
union ubifs_key key;
unsigned int dlen;
data_key_init(c, &key, inode->i_ino, block);
err = ubifs_tnc_lookup(c, &key, dn);
if (err) {
if (err == -ENOENT)
/* Not found, so it must be a hole */
memset(addr, 0, UBIFS_BLOCK_SIZE);
return err;
}
ubifs_assert(dn->ch.sqnum > ubifs_inode(inode)->creat_sqnum);
len = le32_to_cpu(dn->size);
if (len <= 0 || len > UBIFS_BLOCK_SIZE)
goto dump;
dlen = le32_to_cpu(dn->ch.len) - UBIFS_DATA_NODE_SZ;
out_len = UBIFS_BLOCK_SIZE;
err = ubifs_decompress(&dn->data, dlen, addr, &out_len,
le16_to_cpu(dn->compr_type));
if (err || len != out_len)
goto dump;
/*
* Data length can be less than a full block, even for blocks that are
* not the last in the file (e.g., as a result of making a hole and
* appending data). Ensure that the remainder is zeroed out.
*/
if (len < UBIFS_BLOCK_SIZE)
memset(addr + len, 0, UBIFS_BLOCK_SIZE