162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * linux/fs/ext2/inode.c 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (C) 1992, 1993, 1994, 1995 662306a36Sopenharmony_ci * Remy Card (card@masi.ibp.fr) 762306a36Sopenharmony_ci * Laboratoire MASI - Institut Blaise Pascal 862306a36Sopenharmony_ci * Universite Pierre et Marie Curie (Paris VI) 962306a36Sopenharmony_ci * 1062306a36Sopenharmony_ci * from 1162306a36Sopenharmony_ci * 1262306a36Sopenharmony_ci * linux/fs/minix/inode.c 1362306a36Sopenharmony_ci * 1462306a36Sopenharmony_ci * Copyright (C) 1991, 1992 Linus Torvalds 1562306a36Sopenharmony_ci * 1662306a36Sopenharmony_ci * Goal-directed block allocation by Stephen Tweedie 1762306a36Sopenharmony_ci * (sct@dcs.ed.ac.uk), 1993, 1998 1862306a36Sopenharmony_ci * Big-endian to little-endian byte-swapping/bitmaps by 1962306a36Sopenharmony_ci * David S. Miller (davem@caip.rutgers.edu), 1995 2062306a36Sopenharmony_ci * 64-bit file support on 64-bit platforms by Jakub Jelinek 2162306a36Sopenharmony_ci * (jj@sunsite.ms.mff.cuni.cz) 2262306a36Sopenharmony_ci * 2362306a36Sopenharmony_ci * Assorted race fixes, rewrite of ext2_get_block() by Al Viro, 2000 2462306a36Sopenharmony_ci */ 2562306a36Sopenharmony_ci 2662306a36Sopenharmony_ci#include <linux/time.h> 2762306a36Sopenharmony_ci#include <linux/highuid.h> 2862306a36Sopenharmony_ci#include <linux/pagemap.h> 2962306a36Sopenharmony_ci#include <linux/dax.h> 3062306a36Sopenharmony_ci#include <linux/blkdev.h> 3162306a36Sopenharmony_ci#include <linux/quotaops.h> 3262306a36Sopenharmony_ci#include <linux/writeback.h> 3362306a36Sopenharmony_ci#include <linux/buffer_head.h> 3462306a36Sopenharmony_ci#include <linux/mpage.h> 3562306a36Sopenharmony_ci#include <linux/fiemap.h> 3662306a36Sopenharmony_ci#include <linux/iomap.h> 3762306a36Sopenharmony_ci#include <linux/namei.h> 3862306a36Sopenharmony_ci#include <linux/uio.h> 3962306a36Sopenharmony_ci#include "ext2.h" 4062306a36Sopenharmony_ci#include "acl.h" 4162306a36Sopenharmony_ci#include "xattr.h" 4262306a36Sopenharmony_ci 4362306a36Sopenharmony_cistatic int __ext2_write_inode(struct inode *inode, int do_sync); 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_ci/* 4662306a36Sopenharmony_ci * Test whether an inode is a fast symlink. 4762306a36Sopenharmony_ci */ 4862306a36Sopenharmony_cistatic inline int ext2_inode_is_fast_symlink(struct inode *inode) 4962306a36Sopenharmony_ci{ 5062306a36Sopenharmony_ci int ea_blocks = EXT2_I(inode)->i_file_acl ? 5162306a36Sopenharmony_ci (inode->i_sb->s_blocksize >> 9) : 0; 5262306a36Sopenharmony_ci 5362306a36Sopenharmony_ci return (S_ISLNK(inode->i_mode) && 5462306a36Sopenharmony_ci inode->i_blocks - ea_blocks == 0); 5562306a36Sopenharmony_ci} 5662306a36Sopenharmony_ci 5762306a36Sopenharmony_cistatic void ext2_truncate_blocks(struct inode *inode, loff_t offset); 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_civoid ext2_write_failed(struct address_space *mapping, loff_t to) 6062306a36Sopenharmony_ci{ 6162306a36Sopenharmony_ci struct inode *inode = mapping->host; 6262306a36Sopenharmony_ci 6362306a36Sopenharmony_ci if (to > inode->i_size) { 6462306a36Sopenharmony_ci truncate_pagecache(inode, inode->i_size); 6562306a36Sopenharmony_ci ext2_truncate_blocks(inode, inode->i_size); 6662306a36Sopenharmony_ci } 6762306a36Sopenharmony_ci} 6862306a36Sopenharmony_ci 6962306a36Sopenharmony_ci/* 7062306a36Sopenharmony_ci * Called at the last iput() if i_nlink is zero. 7162306a36Sopenharmony_ci */ 7262306a36Sopenharmony_civoid ext2_evict_inode(struct inode * inode) 7362306a36Sopenharmony_ci{ 7462306a36Sopenharmony_ci struct ext2_block_alloc_info *rsv; 7562306a36Sopenharmony_ci int want_delete = 0; 7662306a36Sopenharmony_ci 7762306a36Sopenharmony_ci if (!inode->i_nlink && !is_bad_inode(inode)) { 7862306a36Sopenharmony_ci want_delete = 1; 7962306a36Sopenharmony_ci dquot_initialize(inode); 8062306a36Sopenharmony_ci } else { 8162306a36Sopenharmony_ci dquot_drop(inode); 8262306a36Sopenharmony_ci } 8362306a36Sopenharmony_ci 8462306a36Sopenharmony_ci truncate_inode_pages_final(&inode->i_data); 8562306a36Sopenharmony_ci 8662306a36Sopenharmony_ci if (want_delete) { 8762306a36Sopenharmony_ci sb_start_intwrite(inode->i_sb); 8862306a36Sopenharmony_ci /* set dtime */ 8962306a36Sopenharmony_ci EXT2_I(inode)->i_dtime = ktime_get_real_seconds(); 9062306a36Sopenharmony_ci mark_inode_dirty(inode); 9162306a36Sopenharmony_ci __ext2_write_inode(inode, inode_needs_sync(inode)); 9262306a36Sopenharmony_ci /* truncate to 0 */ 9362306a36Sopenharmony_ci inode->i_size = 0; 9462306a36Sopenharmony_ci if (inode->i_blocks) 9562306a36Sopenharmony_ci ext2_truncate_blocks(inode, 0); 9662306a36Sopenharmony_ci ext2_xattr_delete_inode(inode); 9762306a36Sopenharmony_ci } 9862306a36Sopenharmony_ci 9962306a36Sopenharmony_ci invalidate_inode_buffers(inode); 10062306a36Sopenharmony_ci clear_inode(inode); 10162306a36Sopenharmony_ci 10262306a36Sopenharmony_ci ext2_discard_reservation(inode); 10362306a36Sopenharmony_ci rsv = EXT2_I(inode)->i_block_alloc_info; 10462306a36Sopenharmony_ci EXT2_I(inode)->i_block_alloc_info = NULL; 10562306a36Sopenharmony_ci if (unlikely(rsv)) 10662306a36Sopenharmony_ci kfree(rsv); 10762306a36Sopenharmony_ci 10862306a36Sopenharmony_ci if (want_delete) { 10962306a36Sopenharmony_ci ext2_free_inode(inode); 11062306a36Sopenharmony_ci sb_end_intwrite(inode->i_sb); 11162306a36Sopenharmony_ci } 11262306a36Sopenharmony_ci} 11362306a36Sopenharmony_ci 11462306a36Sopenharmony_citypedef struct { 11562306a36Sopenharmony_ci __le32 *p; 11662306a36Sopenharmony_ci __le32 key; 11762306a36Sopenharmony_ci struct buffer_head *bh; 11862306a36Sopenharmony_ci} Indirect; 11962306a36Sopenharmony_ci 12062306a36Sopenharmony_cistatic inline void add_chain(Indirect *p, struct buffer_head *bh, __le32 *v) 12162306a36Sopenharmony_ci{ 12262306a36Sopenharmony_ci p->key = *(p->p = v); 12362306a36Sopenharmony_ci p->bh = bh; 12462306a36Sopenharmony_ci} 12562306a36Sopenharmony_ci 12662306a36Sopenharmony_cistatic inline int verify_chain(Indirect *from, Indirect *to) 12762306a36Sopenharmony_ci{ 12862306a36Sopenharmony_ci while (from <= to && from->key == *from->p) 12962306a36Sopenharmony_ci from++; 13062306a36Sopenharmony_ci return (from > to); 13162306a36Sopenharmony_ci} 13262306a36Sopenharmony_ci 13362306a36Sopenharmony_ci/** 13462306a36Sopenharmony_ci * ext2_block_to_path - parse the block number into array of offsets 13562306a36Sopenharmony_ci * @inode: inode in question (we are only interested in its superblock) 13662306a36Sopenharmony_ci * @i_block: block number to be parsed 13762306a36Sopenharmony_ci * @offsets: array to store the offsets in 13862306a36Sopenharmony_ci * @boundary: set this non-zero if the referred-to block is likely to be 13962306a36Sopenharmony_ci * followed (on disk) by an indirect block. 14062306a36Sopenharmony_ci * To store the locations of file's data ext2 uses a data structure common 14162306a36Sopenharmony_ci * for UNIX filesystems - tree of pointers anchored in the inode, with 14262306a36Sopenharmony_ci * data blocks at leaves and indirect blocks in intermediate nodes. 14362306a36Sopenharmony_ci * This function translates the block number into path in that tree - 14462306a36Sopenharmony_ci * return value is the path length and @offsets[n] is the offset of 14562306a36Sopenharmony_ci * pointer to (n+1)th node in the nth one. If @block is out of range 14662306a36Sopenharmony_ci * (negative or too large) warning is printed and zero returned. 14762306a36Sopenharmony_ci * 14862306a36Sopenharmony_ci * Note: function doesn't find node addresses, so no IO is needed. All 14962306a36Sopenharmony_ci * we need to know is the capacity of indirect blocks (taken from the 15062306a36Sopenharmony_ci * inode->i_sb). 15162306a36Sopenharmony_ci */ 15262306a36Sopenharmony_ci 15362306a36Sopenharmony_ci/* 15462306a36Sopenharmony_ci * Portability note: the last comparison (check that we fit into triple 15562306a36Sopenharmony_ci * indirect block) is spelled differently, because otherwise on an 15662306a36Sopenharmony_ci * architecture with 32-bit longs and 8Kb pages we might get into trouble 15762306a36Sopenharmony_ci * if our filesystem had 8Kb blocks. We might use long long, but that would 15862306a36Sopenharmony_ci * kill us on x86. Oh, well, at least the sign propagation does not matter - 15962306a36Sopenharmony_ci * i_block would have to be negative in the very beginning, so we would not 16062306a36Sopenharmony_ci * get there at all. 16162306a36Sopenharmony_ci */ 16262306a36Sopenharmony_ci 16362306a36Sopenharmony_cistatic int ext2_block_to_path(struct inode *inode, 16462306a36Sopenharmony_ci long i_block, int offsets[4], int *boundary) 16562306a36Sopenharmony_ci{ 16662306a36Sopenharmony_ci int ptrs = EXT2_ADDR_PER_BLOCK(inode->i_sb); 16762306a36Sopenharmony_ci int ptrs_bits = EXT2_ADDR_PER_BLOCK_BITS(inode->i_sb); 16862306a36Sopenharmony_ci const long direct_blocks = EXT2_NDIR_BLOCKS, 16962306a36Sopenharmony_ci indirect_blocks = ptrs, 17062306a36Sopenharmony_ci double_blocks = (1 << (ptrs_bits * 2)); 17162306a36Sopenharmony_ci int n = 0; 17262306a36Sopenharmony_ci int final = 0; 17362306a36Sopenharmony_ci 17462306a36Sopenharmony_ci if (i_block < 0) { 17562306a36Sopenharmony_ci ext2_msg(inode->i_sb, KERN_WARNING, 17662306a36Sopenharmony_ci "warning: %s: block < 0", __func__); 17762306a36Sopenharmony_ci } else if (i_block < direct_blocks) { 17862306a36Sopenharmony_ci offsets[n++] = i_block; 17962306a36Sopenharmony_ci final = direct_blocks; 18062306a36Sopenharmony_ci } else if ( (i_block -= direct_blocks) < indirect_blocks) { 18162306a36Sopenharmony_ci offsets[n++] = EXT2_IND_BLOCK; 18262306a36Sopenharmony_ci offsets[n++] = i_block; 18362306a36Sopenharmony_ci final = ptrs; 18462306a36Sopenharmony_ci } else if ((i_block -= indirect_blocks) < double_blocks) { 18562306a36Sopenharmony_ci offsets[n++] = EXT2_DIND_BLOCK; 18662306a36Sopenharmony_ci offsets[n++] = i_block >> ptrs_bits; 18762306a36Sopenharmony_ci offsets[n++] = i_block & (ptrs - 1); 18862306a36Sopenharmony_ci final = ptrs; 18962306a36Sopenharmony_ci } else if (((i_block -= double_blocks) >> (ptrs_bits * 2)) < ptrs) { 19062306a36Sopenharmony_ci offsets[n++] = EXT2_TIND_BLOCK; 19162306a36Sopenharmony_ci offsets[n++] = i_block >> (ptrs_bits * 2); 19262306a36Sopenharmony_ci offsets[n++] = (i_block >> ptrs_bits) & (ptrs - 1); 19362306a36Sopenharmony_ci offsets[n++] = i_block & (ptrs - 1); 19462306a36Sopenharmony_ci final = ptrs; 19562306a36Sopenharmony_ci } else { 19662306a36Sopenharmony_ci ext2_msg(inode->i_sb, KERN_WARNING, 19762306a36Sopenharmony_ci "warning: %s: block is too big", __func__); 19862306a36Sopenharmony_ci } 19962306a36Sopenharmony_ci if (boundary) 20062306a36Sopenharmony_ci *boundary = final - 1 - (i_block & (ptrs - 1)); 20162306a36Sopenharmony_ci 20262306a36Sopenharmony_ci return n; 20362306a36Sopenharmony_ci} 20462306a36Sopenharmony_ci 20562306a36Sopenharmony_ci/** 20662306a36Sopenharmony_ci * ext2_get_branch - read the chain of indirect blocks leading to data 20762306a36Sopenharmony_ci * @inode: inode in question 20862306a36Sopenharmony_ci * @depth: depth of the chain (1 - direct pointer, etc.) 20962306a36Sopenharmony_ci * @offsets: offsets of pointers in inode/indirect blocks 21062306a36Sopenharmony_ci * @chain: place to store the result 21162306a36Sopenharmony_ci * @err: here we store the error value 21262306a36Sopenharmony_ci * 21362306a36Sopenharmony_ci * Function fills the array of triples <key, p, bh> and returns %NULL 21462306a36Sopenharmony_ci * if everything went OK or the pointer to the last filled triple 21562306a36Sopenharmony_ci * (incomplete one) otherwise. Upon the return chain[i].key contains 21662306a36Sopenharmony_ci * the number of (i+1)-th block in the chain (as it is stored in memory, 21762306a36Sopenharmony_ci * i.e. little-endian 32-bit), chain[i].p contains the address of that 21862306a36Sopenharmony_ci * number (it points into struct inode for i==0 and into the bh->b_data 21962306a36Sopenharmony_ci * for i>0) and chain[i].bh points to the buffer_head of i-th indirect 22062306a36Sopenharmony_ci * block for i>0 and NULL for i==0. In other words, it holds the block 22162306a36Sopenharmony_ci * numbers of the chain, addresses they were taken from (and where we can 22262306a36Sopenharmony_ci * verify that chain did not change) and buffer_heads hosting these 22362306a36Sopenharmony_ci * numbers. 22462306a36Sopenharmony_ci * 22562306a36Sopenharmony_ci * Function stops when it stumbles upon zero pointer (absent block) 22662306a36Sopenharmony_ci * (pointer to last triple returned, *@err == 0) 22762306a36Sopenharmony_ci * or when it gets an IO error reading an indirect block 22862306a36Sopenharmony_ci * (ditto, *@err == -EIO) 22962306a36Sopenharmony_ci * or when it notices that chain had been changed while it was reading 23062306a36Sopenharmony_ci * (ditto, *@err == -EAGAIN) 23162306a36Sopenharmony_ci * or when it reads all @depth-1 indirect blocks successfully and finds 23262306a36Sopenharmony_ci * the whole chain, all way to the data (returns %NULL, *err == 0). 23362306a36Sopenharmony_ci */ 23462306a36Sopenharmony_cistatic Indirect *ext2_get_branch(struct inode *inode, 23562306a36Sopenharmony_ci int depth, 23662306a36Sopenharmony_ci int *offsets, 23762306a36Sopenharmony_ci Indirect chain[4], 23862306a36Sopenharmony_ci int *err) 23962306a36Sopenharmony_ci{ 24062306a36Sopenharmony_ci struct super_block *sb = inode->i_sb; 24162306a36Sopenharmony_ci Indirect *p = chain; 24262306a36Sopenharmony_ci struct buffer_head *bh; 24362306a36Sopenharmony_ci 24462306a36Sopenharmony_ci *err = 0; 24562306a36Sopenharmony_ci /* i_data is not going away, no lock needed */ 24662306a36Sopenharmony_ci add_chain (chain, NULL, EXT2_I(inode)->i_data + *offsets); 24762306a36Sopenharmony_ci if (!p->key) 24862306a36Sopenharmony_ci goto no_block; 24962306a36Sopenharmony_ci while (--depth) { 25062306a36Sopenharmony_ci bh = sb_bread(sb, le32_to_cpu(p->key)); 25162306a36Sopenharmony_ci if (!bh) 25262306a36Sopenharmony_ci goto failure; 25362306a36Sopenharmony_ci read_lock(&EXT2_I(inode)->i_meta_lock); 25462306a36Sopenharmony_ci if (!verify_chain(chain, p)) 25562306a36Sopenharmony_ci goto changed; 25662306a36Sopenharmony_ci add_chain(++p, bh, (__le32*)bh->b_data + *++offsets); 25762306a36Sopenharmony_ci read_unlock(&EXT2_I(inode)->i_meta_lock); 25862306a36Sopenharmony_ci if (!p->key) 25962306a36Sopenharmony_ci goto no_block; 26062306a36Sopenharmony_ci } 26162306a36Sopenharmony_ci return NULL; 26262306a36Sopenharmony_ci 26362306a36Sopenharmony_cichanged: 26462306a36Sopenharmony_ci read_unlock(&EXT2_I(inode)->i_meta_lock); 26562306a36Sopenharmony_ci brelse(bh); 26662306a36Sopenharmony_ci *err = -EAGAIN; 26762306a36Sopenharmony_ci goto no_block; 26862306a36Sopenharmony_cifailure: 26962306a36Sopenharmony_ci *err = -EIO; 27062306a36Sopenharmony_cino_block: 27162306a36Sopenharmony_ci return p; 27262306a36Sopenharmony_ci} 27362306a36Sopenharmony_ci 27462306a36Sopenharmony_ci/** 27562306a36Sopenharmony_ci * ext2_find_near - find a place for allocation with sufficient locality 27662306a36Sopenharmony_ci * @inode: owner 27762306a36Sopenharmony_ci * @ind: descriptor of indirect block. 27862306a36Sopenharmony_ci * 27962306a36Sopenharmony_ci * This function returns the preferred place for block allocation. 28062306a36Sopenharmony_ci * It is used when heuristic for sequential allocation fails. 28162306a36Sopenharmony_ci * Rules are: 28262306a36Sopenharmony_ci * + if there is a block to the left of our position - allocate near it. 28362306a36Sopenharmony_ci * + if pointer will live in indirect block - allocate near that block. 28462306a36Sopenharmony_ci * + if pointer will live in inode - allocate in the same cylinder group. 28562306a36Sopenharmony_ci * 28662306a36Sopenharmony_ci * In the latter case we colour the starting block by the callers PID to 28762306a36Sopenharmony_ci * prevent it from clashing with concurrent allocations for a different inode 28862306a36Sopenharmony_ci * in the same block group. The PID is used here so that functionally related 28962306a36Sopenharmony_ci * files will be close-by on-disk. 29062306a36Sopenharmony_ci * 29162306a36Sopenharmony_ci * Caller must make sure that @ind is valid and will stay that way. 29262306a36Sopenharmony_ci */ 29362306a36Sopenharmony_ci 29462306a36Sopenharmony_cistatic ext2_fsblk_t ext2_find_near(struct inode *inode, Indirect *ind) 29562306a36Sopenharmony_ci{ 29662306a36Sopenharmony_ci struct ext2_inode_info *ei = EXT2_I(inode); 29762306a36Sopenharmony_ci __le32 *start = ind->bh ? (__le32 *) ind->bh->b_data : ei->i_data; 29862306a36Sopenharmony_ci __le32 *p; 29962306a36Sopenharmony_ci ext2_fsblk_t bg_start; 30062306a36Sopenharmony_ci ext2_fsblk_t colour; 30162306a36Sopenharmony_ci 30262306a36Sopenharmony_ci /* Try to find previous block */ 30362306a36Sopenharmony_ci for (p = ind->p - 1; p >= start; p--) 30462306a36Sopenharmony_ci if (*p) 30562306a36Sopenharmony_ci return le32_to_cpu(*p); 30662306a36Sopenharmony_ci 30762306a36Sopenharmony_ci /* No such thing, so let's try location of indirect block */ 30862306a36Sopenharmony_ci if (ind->bh) 30962306a36Sopenharmony_ci return ind->bh->b_blocknr; 31062306a36Sopenharmony_ci 31162306a36Sopenharmony_ci /* 31262306a36Sopenharmony_ci * It is going to be referred from inode itself? OK, just put it into 31362306a36Sopenharmony_ci * the same cylinder group then. 31462306a36Sopenharmony_ci */ 31562306a36Sopenharmony_ci bg_start = ext2_group_first_block_no(inode->i_sb, ei->i_block_group); 31662306a36Sopenharmony_ci colour = (current->pid % 16) * 31762306a36Sopenharmony_ci (EXT2_BLOCKS_PER_GROUP(inode->i_sb) / 16); 31862306a36Sopenharmony_ci return bg_start + colour; 31962306a36Sopenharmony_ci} 32062306a36Sopenharmony_ci 32162306a36Sopenharmony_ci/** 32262306a36Sopenharmony_ci * ext2_find_goal - find a preferred place for allocation. 32362306a36Sopenharmony_ci * @inode: owner 32462306a36Sopenharmony_ci * @block: block we want 32562306a36Sopenharmony_ci * @partial: pointer to the last triple within a chain 32662306a36Sopenharmony_ci * 32762306a36Sopenharmony_ci * Returns preferred place for a block (the goal). 32862306a36Sopenharmony_ci */ 32962306a36Sopenharmony_ci 33062306a36Sopenharmony_cistatic inline ext2_fsblk_t ext2_find_goal(struct inode *inode, long block, 33162306a36Sopenharmony_ci Indirect *partial) 33262306a36Sopenharmony_ci{ 33362306a36Sopenharmony_ci struct ext2_block_alloc_info *block_i; 33462306a36Sopenharmony_ci 33562306a36Sopenharmony_ci block_i = EXT2_I(inode)->i_block_alloc_info; 33662306a36Sopenharmony_ci 33762306a36Sopenharmony_ci /* 33862306a36Sopenharmony_ci * try the heuristic for sequential allocation, 33962306a36Sopenharmony_ci * failing that at least try to get decent locality. 34062306a36Sopenharmony_ci */ 34162306a36Sopenharmony_ci if (block_i && (block == block_i->last_alloc_logical_block + 1) 34262306a36Sopenharmony_ci && (block_i->last_alloc_physical_block != 0)) { 34362306a36Sopenharmony_ci return block_i->last_alloc_physical_block + 1; 34462306a36Sopenharmony_ci } 34562306a36Sopenharmony_ci 34662306a36Sopenharmony_ci return ext2_find_near(inode, partial); 34762306a36Sopenharmony_ci} 34862306a36Sopenharmony_ci 34962306a36Sopenharmony_ci/** 35062306a36Sopenharmony_ci * ext2_blks_to_allocate: Look up the block map and count the number 35162306a36Sopenharmony_ci * of direct blocks need to be allocated for the given branch. 35262306a36Sopenharmony_ci * 35362306a36Sopenharmony_ci * @branch: chain of indirect blocks 35462306a36Sopenharmony_ci * @k: number of blocks need for indirect blocks 35562306a36Sopenharmony_ci * @blks: number of data blocks to be mapped. 35662306a36Sopenharmony_ci * @blocks_to_boundary: the offset in the indirect block 35762306a36Sopenharmony_ci * 35862306a36Sopenharmony_ci * return the number of direct blocks to allocate. 35962306a36Sopenharmony_ci */ 36062306a36Sopenharmony_cistatic int 36162306a36Sopenharmony_ciext2_blks_to_allocate(Indirect * branch, int k, unsigned long blks, 36262306a36Sopenharmony_ci int blocks_to_boundary) 36362306a36Sopenharmony_ci{ 36462306a36Sopenharmony_ci unsigned long count = 0; 36562306a36Sopenharmony_ci 36662306a36Sopenharmony_ci /* 36762306a36Sopenharmony_ci * Simple case, [t,d]Indirect block(s) has not allocated yet 36862306a36Sopenharmony_ci * then it's clear blocks on that path have not allocated 36962306a36Sopenharmony_ci */ 37062306a36Sopenharmony_ci if (k > 0) { 37162306a36Sopenharmony_ci /* right now don't hanel cross boundary allocation */ 37262306a36Sopenharmony_ci if (blks < blocks_to_boundary + 1) 37362306a36Sopenharmony_ci count += blks; 37462306a36Sopenharmony_ci else 37562306a36Sopenharmony_ci count += blocks_to_boundary + 1; 37662306a36Sopenharmony_ci return count; 37762306a36Sopenharmony_ci } 37862306a36Sopenharmony_ci 37962306a36Sopenharmony_ci count++; 38062306a36Sopenharmony_ci while (count < blks && count <= blocks_to_boundary 38162306a36Sopenharmony_ci && le32_to_cpu(*(branch[0].p + count)) == 0) { 38262306a36Sopenharmony_ci count++; 38362306a36Sopenharmony_ci } 38462306a36Sopenharmony_ci return count; 38562306a36Sopenharmony_ci} 38662306a36Sopenharmony_ci 38762306a36Sopenharmony_ci/** 38862306a36Sopenharmony_ci * ext2_alloc_blocks: Allocate multiple blocks needed for a branch. 38962306a36Sopenharmony_ci * @inode: Owner. 39062306a36Sopenharmony_ci * @goal: Preferred place for allocation. 39162306a36Sopenharmony_ci * @indirect_blks: The number of blocks needed to allocate for indirect blocks. 39262306a36Sopenharmony_ci * @blks: The number of blocks need to allocate for direct blocks. 39362306a36Sopenharmony_ci * @new_blocks: On return it will store the new block numbers for 39462306a36Sopenharmony_ci * the indirect blocks(if needed) and the first direct block. 39562306a36Sopenharmony_ci * @err: Error pointer. 39662306a36Sopenharmony_ci * 39762306a36Sopenharmony_ci * Return: Number of blocks allocated. 39862306a36Sopenharmony_ci */ 39962306a36Sopenharmony_cistatic int ext2_alloc_blocks(struct inode *inode, 40062306a36Sopenharmony_ci ext2_fsblk_t goal, int indirect_blks, int blks, 40162306a36Sopenharmony_ci ext2_fsblk_t new_blocks[4], int *err) 40262306a36Sopenharmony_ci{ 40362306a36Sopenharmony_ci int target, i; 40462306a36Sopenharmony_ci unsigned long count = 0; 40562306a36Sopenharmony_ci int index = 0; 40662306a36Sopenharmony_ci ext2_fsblk_t current_block = 0; 40762306a36Sopenharmony_ci int ret = 0; 40862306a36Sopenharmony_ci 40962306a36Sopenharmony_ci /* 41062306a36Sopenharmony_ci * Here we try to allocate the requested multiple blocks at once, 41162306a36Sopenharmony_ci * on a best-effort basis. 41262306a36Sopenharmony_ci * To build a branch, we should allocate blocks for 41362306a36Sopenharmony_ci * the indirect blocks(if not allocated yet), and at least 41462306a36Sopenharmony_ci * the first direct block of this branch. That's the 41562306a36Sopenharmony_ci * minimum number of blocks need to allocate(required) 41662306a36Sopenharmony_ci */ 41762306a36Sopenharmony_ci target = blks + indirect_blks; 41862306a36Sopenharmony_ci 41962306a36Sopenharmony_ci while (1) { 42062306a36Sopenharmony_ci count = target; 42162306a36Sopenharmony_ci /* allocating blocks for indirect blocks and direct blocks */ 42262306a36Sopenharmony_ci current_block = ext2_new_blocks(inode, goal, &count, err, 0); 42362306a36Sopenharmony_ci if (*err) 42462306a36Sopenharmony_ci goto failed_out; 42562306a36Sopenharmony_ci 42662306a36Sopenharmony_ci target -= count; 42762306a36Sopenharmony_ci /* allocate blocks for indirect blocks */ 42862306a36Sopenharmony_ci while (index < indirect_blks && count) { 42962306a36Sopenharmony_ci new_blocks[index++] = current_block++; 43062306a36Sopenharmony_ci count--; 43162306a36Sopenharmony_ci } 43262306a36Sopenharmony_ci 43362306a36Sopenharmony_ci if (count > 0) 43462306a36Sopenharmony_ci break; 43562306a36Sopenharmony_ci } 43662306a36Sopenharmony_ci 43762306a36Sopenharmony_ci /* save the new block number for the first direct block */ 43862306a36Sopenharmony_ci new_blocks[index] = current_block; 43962306a36Sopenharmony_ci 44062306a36Sopenharmony_ci /* total number of blocks allocated for direct blocks */ 44162306a36Sopenharmony_ci ret = count; 44262306a36Sopenharmony_ci *err = 0; 44362306a36Sopenharmony_ci return ret; 44462306a36Sopenharmony_cifailed_out: 44562306a36Sopenharmony_ci for (i = 0; i <index; i++) 44662306a36Sopenharmony_ci ext2_free_blocks(inode, new_blocks[i], 1); 44762306a36Sopenharmony_ci if (index) 44862306a36Sopenharmony_ci mark_inode_dirty(inode); 44962306a36Sopenharmony_ci return ret; 45062306a36Sopenharmony_ci} 45162306a36Sopenharmony_ci 45262306a36Sopenharmony_ci/** 45362306a36Sopenharmony_ci * ext2_alloc_branch - allocate and set up a chain of blocks. 45462306a36Sopenharmony_ci * @inode: owner 45562306a36Sopenharmony_ci * @indirect_blks: depth of the chain (number of blocks to allocate) 45662306a36Sopenharmony_ci * @blks: number of allocated direct blocks 45762306a36Sopenharmony_ci * @goal: preferred place for allocation 45862306a36Sopenharmony_ci * @offsets: offsets (in the blocks) to store the pointers to next. 45962306a36Sopenharmony_ci * @branch: place to store the chain in. 46062306a36Sopenharmony_ci * 46162306a36Sopenharmony_ci * This function allocates @num blocks, zeroes out all but the last one, 46262306a36Sopenharmony_ci * links them into chain and (if we are synchronous) writes them to disk. 46362306a36Sopenharmony_ci * In other words, it prepares a branch that can be spliced onto the 46462306a36Sopenharmony_ci * inode. It stores the information about that chain in the branch[], in 46562306a36Sopenharmony_ci * the same format as ext2_get_branch() would do. We are calling it after 46662306a36Sopenharmony_ci * we had read the existing part of chain and partial points to the last 46762306a36Sopenharmony_ci * triple of that (one with zero ->key). Upon the exit we have the same 46862306a36Sopenharmony_ci * picture as after the successful ext2_get_block(), except that in one 46962306a36Sopenharmony_ci * place chain is disconnected - *branch->p is still zero (we did not 47062306a36Sopenharmony_ci * set the last link), but branch->key contains the number that should 47162306a36Sopenharmony_ci * be placed into *branch->p to fill that gap. 47262306a36Sopenharmony_ci * 47362306a36Sopenharmony_ci * If allocation fails we free all blocks we've allocated (and forget 47462306a36Sopenharmony_ci * their buffer_heads) and return the error value the from failed 47562306a36Sopenharmony_ci * ext2_alloc_block() (normally -ENOSPC). Otherwise we set the chain 47662306a36Sopenharmony_ci * as described above and return 0. 47762306a36Sopenharmony_ci */ 47862306a36Sopenharmony_ci 47962306a36Sopenharmony_cistatic int ext2_alloc_branch(struct inode *inode, 48062306a36Sopenharmony_ci int indirect_blks, int *blks, ext2_fsblk_t goal, 48162306a36Sopenharmony_ci int *offsets, Indirect *branch) 48262306a36Sopenharmony_ci{ 48362306a36Sopenharmony_ci int blocksize = inode->i_sb->s_blocksize; 48462306a36Sopenharmony_ci int i, n = 0; 48562306a36Sopenharmony_ci int err = 0; 48662306a36Sopenharmony_ci struct buffer_head *bh; 48762306a36Sopenharmony_ci int num; 48862306a36Sopenharmony_ci ext2_fsblk_t new_blocks[4]; 48962306a36Sopenharmony_ci ext2_fsblk_t current_block; 49062306a36Sopenharmony_ci 49162306a36Sopenharmony_ci num = ext2_alloc_blocks(inode, goal, indirect_blks, 49262306a36Sopenharmony_ci *blks, new_blocks, &err); 49362306a36Sopenharmony_ci if (err) 49462306a36Sopenharmony_ci return err; 49562306a36Sopenharmony_ci 49662306a36Sopenharmony_ci branch[0].key = cpu_to_le32(new_blocks[0]); 49762306a36Sopenharmony_ci /* 49862306a36Sopenharmony_ci * metadata blocks and data blocks are allocated. 49962306a36Sopenharmony_ci */ 50062306a36Sopenharmony_ci for (n = 1; n <= indirect_blks; n++) { 50162306a36Sopenharmony_ci /* 50262306a36Sopenharmony_ci * Get buffer_head for parent block, zero it out 50362306a36Sopenharmony_ci * and set the pointer to new one, then send 50462306a36Sopenharmony_ci * parent to disk. 50562306a36Sopenharmony_ci */ 50662306a36Sopenharmony_ci bh = sb_getblk(inode->i_sb, new_blocks[n-1]); 50762306a36Sopenharmony_ci if (unlikely(!bh)) { 50862306a36Sopenharmony_ci err = -ENOMEM; 50962306a36Sopenharmony_ci goto failed; 51062306a36Sopenharmony_ci } 51162306a36Sopenharmony_ci branch[n].bh = bh; 51262306a36Sopenharmony_ci lock_buffer(bh); 51362306a36Sopenharmony_ci memset(bh->b_data, 0, blocksize); 51462306a36Sopenharmony_ci branch[n].p = (__le32 *) bh->b_data + offsets[n]; 51562306a36Sopenharmony_ci branch[n].key = cpu_to_le32(new_blocks[n]); 51662306a36Sopenharmony_ci *branch[n].p = branch[n].key; 51762306a36Sopenharmony_ci if ( n == indirect_blks) { 51862306a36Sopenharmony_ci current_block = new_blocks[n]; 51962306a36Sopenharmony_ci /* 52062306a36Sopenharmony_ci * End of chain, update the last new metablock of 52162306a36Sopenharmony_ci * the chain to point to the new allocated 52262306a36Sopenharmony_ci * data blocks numbers 52362306a36Sopenharmony_ci */ 52462306a36Sopenharmony_ci for (i=1; i < num; i++) 52562306a36Sopenharmony_ci *(branch[n].p + i) = cpu_to_le32(++current_block); 52662306a36Sopenharmony_ci } 52762306a36Sopenharmony_ci set_buffer_uptodate(bh); 52862306a36Sopenharmony_ci unlock_buffer(bh); 52962306a36Sopenharmony_ci mark_buffer_dirty_inode(bh, inode); 53062306a36Sopenharmony_ci /* We used to sync bh here if IS_SYNC(inode). 53162306a36Sopenharmony_ci * But we now rely upon generic_write_sync() 53262306a36Sopenharmony_ci * and b_inode_buffers. But not for directories. 53362306a36Sopenharmony_ci */ 53462306a36Sopenharmony_ci if (S_ISDIR(inode->i_mode) && IS_DIRSYNC(inode)) 53562306a36Sopenharmony_ci sync_dirty_buffer(bh); 53662306a36Sopenharmony_ci } 53762306a36Sopenharmony_ci *blks = num; 53862306a36Sopenharmony_ci return err; 53962306a36Sopenharmony_ci 54062306a36Sopenharmony_cifailed: 54162306a36Sopenharmony_ci for (i = 1; i < n; i++) 54262306a36Sopenharmony_ci bforget(branch[i].bh); 54362306a36Sopenharmony_ci for (i = 0; i < indirect_blks; i++) 54462306a36Sopenharmony_ci ext2_free_blocks(inode, new_blocks[i], 1); 54562306a36Sopenharmony_ci ext2_free_blocks(inode, new_blocks[i], num); 54662306a36Sopenharmony_ci return err; 54762306a36Sopenharmony_ci} 54862306a36Sopenharmony_ci 54962306a36Sopenharmony_ci/** 55062306a36Sopenharmony_ci * ext2_splice_branch - splice the allocated branch onto inode. 55162306a36Sopenharmony_ci * @inode: owner 55262306a36Sopenharmony_ci * @block: (logical) number of block we are adding 55362306a36Sopenharmony_ci * @where: location of missing link 55462306a36Sopenharmony_ci * @num: number of indirect blocks we are adding 55562306a36Sopenharmony_ci * @blks: number of direct blocks we are adding 55662306a36Sopenharmony_ci * 55762306a36Sopenharmony_ci * This function fills the missing link and does all housekeeping needed in 55862306a36Sopenharmony_ci * inode (->i_blocks, etc.). In case of success we end up with the full 55962306a36Sopenharmony_ci * chain to new block and return 0. 56062306a36Sopenharmony_ci */ 56162306a36Sopenharmony_cistatic void ext2_splice_branch(struct inode *inode, 56262306a36Sopenharmony_ci long block, Indirect *where, int num, int blks) 56362306a36Sopenharmony_ci{ 56462306a36Sopenharmony_ci int i; 56562306a36Sopenharmony_ci struct ext2_block_alloc_info *block_i; 56662306a36Sopenharmony_ci ext2_fsblk_t current_block; 56762306a36Sopenharmony_ci 56862306a36Sopenharmony_ci block_i = EXT2_I(inode)->i_block_alloc_info; 56962306a36Sopenharmony_ci 57062306a36Sopenharmony_ci /* XXX LOCKING probably should have i_meta_lock ?*/ 57162306a36Sopenharmony_ci /* That's it */ 57262306a36Sopenharmony_ci 57362306a36Sopenharmony_ci *where->p = where->key; 57462306a36Sopenharmony_ci 57562306a36Sopenharmony_ci /* 57662306a36Sopenharmony_ci * Update the host buffer_head or inode to point to more just allocated 57762306a36Sopenharmony_ci * direct blocks blocks 57862306a36Sopenharmony_ci */ 57962306a36Sopenharmony_ci if (num == 0 && blks > 1) { 58062306a36Sopenharmony_ci current_block = le32_to_cpu(where->key) + 1; 58162306a36Sopenharmony_ci for (i = 1; i < blks; i++) 58262306a36Sopenharmony_ci *(where->p + i ) = cpu_to_le32(current_block++); 58362306a36Sopenharmony_ci } 58462306a36Sopenharmony_ci 58562306a36Sopenharmony_ci /* 58662306a36Sopenharmony_ci * update the most recently allocated logical & physical block 58762306a36Sopenharmony_ci * in i_block_alloc_info, to assist find the proper goal block for next 58862306a36Sopenharmony_ci * allocation 58962306a36Sopenharmony_ci */ 59062306a36Sopenharmony_ci if (block_i) { 59162306a36Sopenharmony_ci block_i->last_alloc_logical_block = block + blks - 1; 59262306a36Sopenharmony_ci block_i->last_alloc_physical_block = 59362306a36Sopenharmony_ci le32_to_cpu(where[num].key) + blks - 1; 59462306a36Sopenharmony_ci } 59562306a36Sopenharmony_ci 59662306a36Sopenharmony_ci /* We are done with atomic stuff, now do the rest of housekeeping */ 59762306a36Sopenharmony_ci 59862306a36Sopenharmony_ci /* had we spliced it onto indirect block? */ 59962306a36Sopenharmony_ci if (where->bh) 60062306a36Sopenharmony_ci mark_buffer_dirty_inode(where->bh, inode); 60162306a36Sopenharmony_ci 60262306a36Sopenharmony_ci inode_set_ctime_current(inode); 60362306a36Sopenharmony_ci mark_inode_dirty(inode); 60462306a36Sopenharmony_ci} 60562306a36Sopenharmony_ci 60662306a36Sopenharmony_ci/* 60762306a36Sopenharmony_ci * Allocation strategy is simple: if we have to allocate something, we will 60862306a36Sopenharmony_ci * have to go the whole way to leaf. So let's do it before attaching anything 60962306a36Sopenharmony_ci * to tree, set linkage between the newborn blocks, write them if sync is 61062306a36Sopenharmony_ci * required, recheck the path, free and repeat if check fails, otherwise 61162306a36Sopenharmony_ci * set the last missing link (that will protect us from any truncate-generated 61262306a36Sopenharmony_ci * removals - all blocks on the path are immune now) and possibly force the 61362306a36Sopenharmony_ci * write on the parent block. 61462306a36Sopenharmony_ci * That has a nice additional property: no special recovery from the failed 61562306a36Sopenharmony_ci * allocations is needed - we simply release blocks and do not touch anything 61662306a36Sopenharmony_ci * reachable from inode. 61762306a36Sopenharmony_ci * 61862306a36Sopenharmony_ci * `handle' can be NULL if create == 0. 61962306a36Sopenharmony_ci * 62062306a36Sopenharmony_ci * return > 0, # of blocks mapped or allocated. 62162306a36Sopenharmony_ci * return = 0, if plain lookup failed. 62262306a36Sopenharmony_ci * return < 0, error case. 62362306a36Sopenharmony_ci */ 62462306a36Sopenharmony_cistatic int ext2_get_blocks(struct inode *inode, 62562306a36Sopenharmony_ci sector_t iblock, unsigned long maxblocks, 62662306a36Sopenharmony_ci u32 *bno, bool *new, bool *boundary, 62762306a36Sopenharmony_ci int create) 62862306a36Sopenharmony_ci{ 62962306a36Sopenharmony_ci int err; 63062306a36Sopenharmony_ci int offsets[4]; 63162306a36Sopenharmony_ci Indirect chain[4]; 63262306a36Sopenharmony_ci Indirect *partial; 63362306a36Sopenharmony_ci ext2_fsblk_t goal; 63462306a36Sopenharmony_ci int indirect_blks; 63562306a36Sopenharmony_ci int blocks_to_boundary = 0; 63662306a36Sopenharmony_ci int depth; 63762306a36Sopenharmony_ci struct ext2_inode_info *ei = EXT2_I(inode); 63862306a36Sopenharmony_ci int count = 0; 63962306a36Sopenharmony_ci ext2_fsblk_t first_block = 0; 64062306a36Sopenharmony_ci 64162306a36Sopenharmony_ci BUG_ON(maxblocks == 0); 64262306a36Sopenharmony_ci 64362306a36Sopenharmony_ci depth = ext2_block_to_path(inode,iblock,offsets,&blocks_to_boundary); 64462306a36Sopenharmony_ci 64562306a36Sopenharmony_ci if (depth == 0) 64662306a36Sopenharmony_ci return -EIO; 64762306a36Sopenharmony_ci 64862306a36Sopenharmony_ci partial = ext2_get_branch(inode, depth, offsets, chain, &err); 64962306a36Sopenharmony_ci /* Simplest case - block found, no allocation needed */ 65062306a36Sopenharmony_ci if (!partial) { 65162306a36Sopenharmony_ci first_block = le32_to_cpu(chain[depth - 1].key); 65262306a36Sopenharmony_ci count++; 65362306a36Sopenharmony_ci /*map more blocks*/ 65462306a36Sopenharmony_ci while (count < maxblocks && count <= blocks_to_boundary) { 65562306a36Sopenharmony_ci ext2_fsblk_t blk; 65662306a36Sopenharmony_ci 65762306a36Sopenharmony_ci if (!verify_chain(chain, chain + depth - 1)) { 65862306a36Sopenharmony_ci /* 65962306a36Sopenharmony_ci * Indirect block might be removed by 66062306a36Sopenharmony_ci * truncate while we were reading it. 66162306a36Sopenharmony_ci * Handling of that case: forget what we've 66262306a36Sopenharmony_ci * got now, go to reread. 66362306a36Sopenharmony_ci */ 66462306a36Sopenharmony_ci err = -EAGAIN; 66562306a36Sopenharmony_ci count = 0; 66662306a36Sopenharmony_ci partial = chain + depth - 1; 66762306a36Sopenharmony_ci break; 66862306a36Sopenharmony_ci } 66962306a36Sopenharmony_ci blk = le32_to_cpu(*(chain[depth-1].p + count)); 67062306a36Sopenharmony_ci if (blk == first_block + count) 67162306a36Sopenharmony_ci count++; 67262306a36Sopenharmony_ci else 67362306a36Sopenharmony_ci break; 67462306a36Sopenharmony_ci } 67562306a36Sopenharmony_ci if (err != -EAGAIN) 67662306a36Sopenharmony_ci goto got_it; 67762306a36Sopenharmony_ci } 67862306a36Sopenharmony_ci 67962306a36Sopenharmony_ci /* Next simple case - plain lookup or failed read of indirect block */ 68062306a36Sopenharmony_ci if (!create || err == -EIO) 68162306a36Sopenharmony_ci goto cleanup; 68262306a36Sopenharmony_ci 68362306a36Sopenharmony_ci mutex_lock(&ei->truncate_mutex); 68462306a36Sopenharmony_ci /* 68562306a36Sopenharmony_ci * If the indirect block is missing while we are reading 68662306a36Sopenharmony_ci * the chain(ext2_get_branch() returns -EAGAIN err), or 68762306a36Sopenharmony_ci * if the chain has been changed after we grab the semaphore, 68862306a36Sopenharmony_ci * (either because another process truncated this branch, or 68962306a36Sopenharmony_ci * another get_block allocated this branch) re-grab the chain to see if 69062306a36Sopenharmony_ci * the request block has been allocated or not. 69162306a36Sopenharmony_ci * 69262306a36Sopenharmony_ci * Since we already block the truncate/other get_block 69362306a36Sopenharmony_ci * at this point, we will have the current copy of the chain when we 69462306a36Sopenharmony_ci * splice the branch into the tree. 69562306a36Sopenharmony_ci */ 69662306a36Sopenharmony_ci if (err == -EAGAIN || !verify_chain(chain, partial)) { 69762306a36Sopenharmony_ci while (partial > chain) { 69862306a36Sopenharmony_ci brelse(partial->bh); 69962306a36Sopenharmony_ci partial--; 70062306a36Sopenharmony_ci } 70162306a36Sopenharmony_ci partial = ext2_get_branch(inode, depth, offsets, chain, &err); 70262306a36Sopenharmony_ci if (!partial) { 70362306a36Sopenharmony_ci count++; 70462306a36Sopenharmony_ci mutex_unlock(&ei->truncate_mutex); 70562306a36Sopenharmony_ci goto got_it; 70662306a36Sopenharmony_ci } 70762306a36Sopenharmony_ci 70862306a36Sopenharmony_ci if (err) { 70962306a36Sopenharmony_ci mutex_unlock(&ei->truncate_mutex); 71062306a36Sopenharmony_ci goto cleanup; 71162306a36Sopenharmony_ci } 71262306a36Sopenharmony_ci } 71362306a36Sopenharmony_ci 71462306a36Sopenharmony_ci /* 71562306a36Sopenharmony_ci * Okay, we need to do block allocation. Lazily initialize the block 71662306a36Sopenharmony_ci * allocation info here if necessary 71762306a36Sopenharmony_ci */ 71862306a36Sopenharmony_ci if (S_ISREG(inode->i_mode) && (!ei->i_block_alloc_info)) 71962306a36Sopenharmony_ci ext2_init_block_alloc_info(inode); 72062306a36Sopenharmony_ci 72162306a36Sopenharmony_ci goal = ext2_find_goal(inode, iblock, partial); 72262306a36Sopenharmony_ci 72362306a36Sopenharmony_ci /* the number of blocks need to allocate for [d,t]indirect blocks */ 72462306a36Sopenharmony_ci indirect_blks = (chain + depth) - partial - 1; 72562306a36Sopenharmony_ci /* 72662306a36Sopenharmony_ci * Next look up the indirect map to count the total number of 72762306a36Sopenharmony_ci * direct blocks to allocate for this branch. 72862306a36Sopenharmony_ci */ 72962306a36Sopenharmony_ci count = ext2_blks_to_allocate(partial, indirect_blks, 73062306a36Sopenharmony_ci maxblocks, blocks_to_boundary); 73162306a36Sopenharmony_ci /* 73262306a36Sopenharmony_ci * XXX ???? Block out ext2_truncate while we alter the tree 73362306a36Sopenharmony_ci */ 73462306a36Sopenharmony_ci err = ext2_alloc_branch(inode, indirect_blks, &count, goal, 73562306a36Sopenharmony_ci offsets + (partial - chain), partial); 73662306a36Sopenharmony_ci 73762306a36Sopenharmony_ci if (err) { 73862306a36Sopenharmony_ci mutex_unlock(&ei->truncate_mutex); 73962306a36Sopenharmony_ci goto cleanup; 74062306a36Sopenharmony_ci } 74162306a36Sopenharmony_ci 74262306a36Sopenharmony_ci if (IS_DAX(inode)) { 74362306a36Sopenharmony_ci /* 74462306a36Sopenharmony_ci * We must unmap blocks before zeroing so that writeback cannot 74562306a36Sopenharmony_ci * overwrite zeros with stale data from block device page cache. 74662306a36Sopenharmony_ci */ 74762306a36Sopenharmony_ci clean_bdev_aliases(inode->i_sb->s_bdev, 74862306a36Sopenharmony_ci le32_to_cpu(chain[depth-1].key), 74962306a36Sopenharmony_ci count); 75062306a36Sopenharmony_ci /* 75162306a36Sopenharmony_ci * block must be initialised before we put it in the tree 75262306a36Sopenharmony_ci * so that it's not found by another thread before it's 75362306a36Sopenharmony_ci * initialised 75462306a36Sopenharmony_ci */ 75562306a36Sopenharmony_ci err = sb_issue_zeroout(inode->i_sb, 75662306a36Sopenharmony_ci le32_to_cpu(chain[depth-1].key), count, 75762306a36Sopenharmony_ci GFP_NOFS); 75862306a36Sopenharmony_ci if (err) { 75962306a36Sopenharmony_ci mutex_unlock(&ei->truncate_mutex); 76062306a36Sopenharmony_ci goto cleanup; 76162306a36Sopenharmony_ci } 76262306a36Sopenharmony_ci } 76362306a36Sopenharmony_ci *new = true; 76462306a36Sopenharmony_ci 76562306a36Sopenharmony_ci ext2_splice_branch(inode, iblock, partial, indirect_blks, count); 76662306a36Sopenharmony_ci mutex_unlock(&ei->truncate_mutex); 76762306a36Sopenharmony_cigot_it: 76862306a36Sopenharmony_ci if (count > blocks_to_boundary) 76962306a36Sopenharmony_ci *boundary = true; 77062306a36Sopenharmony_ci err = count; 77162306a36Sopenharmony_ci /* Clean up and exit */ 77262306a36Sopenharmony_ci partial = chain + depth - 1; /* the whole chain */ 77362306a36Sopenharmony_cicleanup: 77462306a36Sopenharmony_ci while (partial > chain) { 77562306a36Sopenharmony_ci brelse(partial->bh); 77662306a36Sopenharmony_ci partial--; 77762306a36Sopenharmony_ci } 77862306a36Sopenharmony_ci if (err > 0) 77962306a36Sopenharmony_ci *bno = le32_to_cpu(chain[depth-1].key); 78062306a36Sopenharmony_ci return err; 78162306a36Sopenharmony_ci} 78262306a36Sopenharmony_ci 78362306a36Sopenharmony_ciint ext2_get_block(struct inode *inode, sector_t iblock, 78462306a36Sopenharmony_ci struct buffer_head *bh_result, int create) 78562306a36Sopenharmony_ci{ 78662306a36Sopenharmony_ci unsigned max_blocks = bh_result->b_size >> inode->i_blkbits; 78762306a36Sopenharmony_ci bool new = false, boundary = false; 78862306a36Sopenharmony_ci u32 bno; 78962306a36Sopenharmony_ci int ret; 79062306a36Sopenharmony_ci 79162306a36Sopenharmony_ci ret = ext2_get_blocks(inode, iblock, max_blocks, &bno, &new, &boundary, 79262306a36Sopenharmony_ci create); 79362306a36Sopenharmony_ci if (ret <= 0) 79462306a36Sopenharmony_ci return ret; 79562306a36Sopenharmony_ci 79662306a36Sopenharmony_ci map_bh(bh_result, inode->i_sb, bno); 79762306a36Sopenharmony_ci bh_result->b_size = (ret << inode->i_blkbits); 79862306a36Sopenharmony_ci if (new) 79962306a36Sopenharmony_ci set_buffer_new(bh_result); 80062306a36Sopenharmony_ci if (boundary) 80162306a36Sopenharmony_ci set_buffer_boundary(bh_result); 80262306a36Sopenharmony_ci return 0; 80362306a36Sopenharmony_ci 80462306a36Sopenharmony_ci} 80562306a36Sopenharmony_ci 80662306a36Sopenharmony_cistatic int ext2_iomap_begin(struct inode *inode, loff_t offset, loff_t length, 80762306a36Sopenharmony_ci unsigned flags, struct iomap *iomap, struct iomap *srcmap) 80862306a36Sopenharmony_ci{ 80962306a36Sopenharmony_ci unsigned int blkbits = inode->i_blkbits; 81062306a36Sopenharmony_ci unsigned long first_block = offset >> blkbits; 81162306a36Sopenharmony_ci unsigned long max_blocks = (length + (1 << blkbits) - 1) >> blkbits; 81262306a36Sopenharmony_ci struct ext2_sb_info *sbi = EXT2_SB(inode->i_sb); 81362306a36Sopenharmony_ci bool new = false, boundary = false; 81462306a36Sopenharmony_ci u32 bno; 81562306a36Sopenharmony_ci int ret; 81662306a36Sopenharmony_ci bool create = flags & IOMAP_WRITE; 81762306a36Sopenharmony_ci 81862306a36Sopenharmony_ci /* 81962306a36Sopenharmony_ci * For writes that could fill holes inside i_size on a 82062306a36Sopenharmony_ci * DIO_SKIP_HOLES filesystem we forbid block creations: only 82162306a36Sopenharmony_ci * overwrites are permitted. 82262306a36Sopenharmony_ci */ 82362306a36Sopenharmony_ci if ((flags & IOMAP_DIRECT) && 82462306a36Sopenharmony_ci (first_block << blkbits) < i_size_read(inode)) 82562306a36Sopenharmony_ci create = 0; 82662306a36Sopenharmony_ci 82762306a36Sopenharmony_ci /* 82862306a36Sopenharmony_ci * Writes that span EOF might trigger an IO size update on completion, 82962306a36Sopenharmony_ci * so consider them to be dirty for the purposes of O_DSYNC even if 83062306a36Sopenharmony_ci * there is no other metadata changes pending or have been made here. 83162306a36Sopenharmony_ci */ 83262306a36Sopenharmony_ci if ((flags & IOMAP_WRITE) && offset + length > i_size_read(inode)) 83362306a36Sopenharmony_ci iomap->flags |= IOMAP_F_DIRTY; 83462306a36Sopenharmony_ci 83562306a36Sopenharmony_ci ret = ext2_get_blocks(inode, first_block, max_blocks, 83662306a36Sopenharmony_ci &bno, &new, &boundary, create); 83762306a36Sopenharmony_ci if (ret < 0) 83862306a36Sopenharmony_ci return ret; 83962306a36Sopenharmony_ci 84062306a36Sopenharmony_ci iomap->flags = 0; 84162306a36Sopenharmony_ci iomap->offset = (u64)first_block << blkbits; 84262306a36Sopenharmony_ci if (flags & IOMAP_DAX) 84362306a36Sopenharmony_ci iomap->dax_dev = sbi->s_daxdev; 84462306a36Sopenharmony_ci else 84562306a36Sopenharmony_ci iomap->bdev = inode->i_sb->s_bdev; 84662306a36Sopenharmony_ci 84762306a36Sopenharmony_ci if (ret == 0) { 84862306a36Sopenharmony_ci /* 84962306a36Sopenharmony_ci * Switch to buffered-io for writing to holes in a non-extent 85062306a36Sopenharmony_ci * based filesystem to avoid stale data exposure problem. 85162306a36Sopenharmony_ci */ 85262306a36Sopenharmony_ci if (!create && (flags & IOMAP_WRITE) && (flags & IOMAP_DIRECT)) 85362306a36Sopenharmony_ci return -ENOTBLK; 85462306a36Sopenharmony_ci iomap->type = IOMAP_HOLE; 85562306a36Sopenharmony_ci iomap->addr = IOMAP_NULL_ADDR; 85662306a36Sopenharmony_ci iomap->length = 1 << blkbits; 85762306a36Sopenharmony_ci } else { 85862306a36Sopenharmony_ci iomap->type = IOMAP_MAPPED; 85962306a36Sopenharmony_ci iomap->addr = (u64)bno << blkbits; 86062306a36Sopenharmony_ci if (flags & IOMAP_DAX) 86162306a36Sopenharmony_ci iomap->addr += sbi->s_dax_part_off; 86262306a36Sopenharmony_ci iomap->length = (u64)ret << blkbits; 86362306a36Sopenharmony_ci iomap->flags |= IOMAP_F_MERGED; 86462306a36Sopenharmony_ci } 86562306a36Sopenharmony_ci 86662306a36Sopenharmony_ci if (new) 86762306a36Sopenharmony_ci iomap->flags |= IOMAP_F_NEW; 86862306a36Sopenharmony_ci return 0; 86962306a36Sopenharmony_ci} 87062306a36Sopenharmony_ci 87162306a36Sopenharmony_cistatic int 87262306a36Sopenharmony_ciext2_iomap_end(struct inode *inode, loff_t offset, loff_t length, 87362306a36Sopenharmony_ci ssize_t written, unsigned flags, struct iomap *iomap) 87462306a36Sopenharmony_ci{ 87562306a36Sopenharmony_ci /* 87662306a36Sopenharmony_ci * Switch to buffered-io in case of any error. 87762306a36Sopenharmony_ci * Blocks allocated can be used by the buffered-io path. 87862306a36Sopenharmony_ci */ 87962306a36Sopenharmony_ci if ((flags & IOMAP_DIRECT) && (flags & IOMAP_WRITE) && written == 0) 88062306a36Sopenharmony_ci return -ENOTBLK; 88162306a36Sopenharmony_ci 88262306a36Sopenharmony_ci if (iomap->type == IOMAP_MAPPED && 88362306a36Sopenharmony_ci written < length && 88462306a36Sopenharmony_ci (flags & IOMAP_WRITE)) 88562306a36Sopenharmony_ci ext2_write_failed(inode->i_mapping, offset + length); 88662306a36Sopenharmony_ci return 0; 88762306a36Sopenharmony_ci} 88862306a36Sopenharmony_ci 88962306a36Sopenharmony_ciconst struct iomap_ops ext2_iomap_ops = { 89062306a36Sopenharmony_ci .iomap_begin = ext2_iomap_begin, 89162306a36Sopenharmony_ci .iomap_end = ext2_iomap_end, 89262306a36Sopenharmony_ci}; 89362306a36Sopenharmony_ci 89462306a36Sopenharmony_ciint ext2_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, 89562306a36Sopenharmony_ci u64 start, u64 len) 89662306a36Sopenharmony_ci{ 89762306a36Sopenharmony_ci int ret; 89862306a36Sopenharmony_ci 89962306a36Sopenharmony_ci inode_lock(inode); 90062306a36Sopenharmony_ci len = min_t(u64, len, i_size_read(inode)); 90162306a36Sopenharmony_ci ret = iomap_fiemap(inode, fieinfo, start, len, &ext2_iomap_ops); 90262306a36Sopenharmony_ci inode_unlock(inode); 90362306a36Sopenharmony_ci 90462306a36Sopenharmony_ci return ret; 90562306a36Sopenharmony_ci} 90662306a36Sopenharmony_ci 90762306a36Sopenharmony_cistatic int ext2_read_folio(struct file *file, struct folio *folio) 90862306a36Sopenharmony_ci{ 90962306a36Sopenharmony_ci return mpage_read_folio(folio, ext2_get_block); 91062306a36Sopenharmony_ci} 91162306a36Sopenharmony_ci 91262306a36Sopenharmony_cistatic void ext2_readahead(struct readahead_control *rac) 91362306a36Sopenharmony_ci{ 91462306a36Sopenharmony_ci mpage_readahead(rac, ext2_get_block); 91562306a36Sopenharmony_ci} 91662306a36Sopenharmony_ci 91762306a36Sopenharmony_cistatic int 91862306a36Sopenharmony_ciext2_write_begin(struct file *file, struct address_space *mapping, 91962306a36Sopenharmony_ci loff_t pos, unsigned len, struct page **pagep, void **fsdata) 92062306a36Sopenharmony_ci{ 92162306a36Sopenharmony_ci int ret; 92262306a36Sopenharmony_ci 92362306a36Sopenharmony_ci ret = block_write_begin(mapping, pos, len, pagep, ext2_get_block); 92462306a36Sopenharmony_ci if (ret < 0) 92562306a36Sopenharmony_ci ext2_write_failed(mapping, pos + len); 92662306a36Sopenharmony_ci return ret; 92762306a36Sopenharmony_ci} 92862306a36Sopenharmony_ci 92962306a36Sopenharmony_cistatic int ext2_write_end(struct file *file, struct address_space *mapping, 93062306a36Sopenharmony_ci loff_t pos, unsigned len, unsigned copied, 93162306a36Sopenharmony_ci struct page *page, void *fsdata) 93262306a36Sopenharmony_ci{ 93362306a36Sopenharmony_ci int ret; 93462306a36Sopenharmony_ci 93562306a36Sopenharmony_ci ret = generic_write_end(file, mapping, pos, len, copied, page, fsdata); 93662306a36Sopenharmony_ci if (ret < len) 93762306a36Sopenharmony_ci ext2_write_failed(mapping, pos + len); 93862306a36Sopenharmony_ci return ret; 93962306a36Sopenharmony_ci} 94062306a36Sopenharmony_ci 94162306a36Sopenharmony_cistatic sector_t ext2_bmap(struct address_space *mapping, sector_t block) 94262306a36Sopenharmony_ci{ 94362306a36Sopenharmony_ci return generic_block_bmap(mapping,block,ext2_get_block); 94462306a36Sopenharmony_ci} 94562306a36Sopenharmony_ci 94662306a36Sopenharmony_cistatic int 94762306a36Sopenharmony_ciext2_writepages(struct address_space *mapping, struct writeback_control *wbc) 94862306a36Sopenharmony_ci{ 94962306a36Sopenharmony_ci return mpage_writepages(mapping, wbc, ext2_get_block); 95062306a36Sopenharmony_ci} 95162306a36Sopenharmony_ci 95262306a36Sopenharmony_cistatic int 95362306a36Sopenharmony_ciext2_dax_writepages(struct address_space *mapping, struct writeback_control *wbc) 95462306a36Sopenharmony_ci{ 95562306a36Sopenharmony_ci struct ext2_sb_info *sbi = EXT2_SB(mapping->host->i_sb); 95662306a36Sopenharmony_ci 95762306a36Sopenharmony_ci return dax_writeback_mapping_range(mapping, sbi->s_daxdev, wbc); 95862306a36Sopenharmony_ci} 95962306a36Sopenharmony_ci 96062306a36Sopenharmony_ciconst struct address_space_operations ext2_aops = { 96162306a36Sopenharmony_ci .dirty_folio = block_dirty_folio, 96262306a36Sopenharmony_ci .invalidate_folio = block_invalidate_folio, 96362306a36Sopenharmony_ci .read_folio = ext2_read_folio, 96462306a36Sopenharmony_ci .readahead = ext2_readahead, 96562306a36Sopenharmony_ci .write_begin = ext2_write_begin, 96662306a36Sopenharmony_ci .write_end = ext2_write_end, 96762306a36Sopenharmony_ci .bmap = ext2_bmap, 96862306a36Sopenharmony_ci .direct_IO = noop_direct_IO, 96962306a36Sopenharmony_ci .writepages = ext2_writepages, 97062306a36Sopenharmony_ci .migrate_folio = buffer_migrate_folio, 97162306a36Sopenharmony_ci .is_partially_uptodate = block_is_partially_uptodate, 97262306a36Sopenharmony_ci .error_remove_page = generic_error_remove_page, 97362306a36Sopenharmony_ci}; 97462306a36Sopenharmony_ci 97562306a36Sopenharmony_cistatic const struct address_space_operations ext2_dax_aops = { 97662306a36Sopenharmony_ci .writepages = ext2_dax_writepages, 97762306a36Sopenharmony_ci .direct_IO = noop_direct_IO, 97862306a36Sopenharmony_ci .dirty_folio = noop_dirty_folio, 97962306a36Sopenharmony_ci}; 98062306a36Sopenharmony_ci 98162306a36Sopenharmony_ci/* 98262306a36Sopenharmony_ci * Probably it should be a library function... search for first non-zero word 98362306a36Sopenharmony_ci * or memcmp with zero_page, whatever is better for particular architecture. 98462306a36Sopenharmony_ci * Linus? 98562306a36Sopenharmony_ci */ 98662306a36Sopenharmony_cistatic inline int all_zeroes(__le32 *p, __le32 *q) 98762306a36Sopenharmony_ci{ 98862306a36Sopenharmony_ci while (p < q) 98962306a36Sopenharmony_ci if (*p++) 99062306a36Sopenharmony_ci return 0; 99162306a36Sopenharmony_ci return 1; 99262306a36Sopenharmony_ci} 99362306a36Sopenharmony_ci 99462306a36Sopenharmony_ci/** 99562306a36Sopenharmony_ci * ext2_find_shared - find the indirect blocks for partial truncation. 99662306a36Sopenharmony_ci * @inode: inode in question 99762306a36Sopenharmony_ci * @depth: depth of the affected branch 99862306a36Sopenharmony_ci * @offsets: offsets of pointers in that branch (see ext2_block_to_path) 99962306a36Sopenharmony_ci * @chain: place to store the pointers to partial indirect blocks 100062306a36Sopenharmony_ci * @top: place to the (detached) top of branch 100162306a36Sopenharmony_ci * 100262306a36Sopenharmony_ci * This is a helper function used by ext2_truncate(). 100362306a36Sopenharmony_ci * 100462306a36Sopenharmony_ci * When we do truncate() we may have to clean the ends of several indirect 100562306a36Sopenharmony_ci * blocks but leave the blocks themselves alive. Block is partially 100662306a36Sopenharmony_ci * truncated if some data below the new i_size is referred from it (and 100762306a36Sopenharmony_ci * it is on the path to the first completely truncated data block, indeed). 100862306a36Sopenharmony_ci * We have to free the top of that path along with everything to the right 100962306a36Sopenharmony_ci * of the path. Since no allocation past the truncation point is possible 101062306a36Sopenharmony_ci * until ext2_truncate() finishes, we may safely do the latter, but top 101162306a36Sopenharmony_ci * of branch may require special attention - pageout below the truncation 101262306a36Sopenharmony_ci * point might try to populate it. 101362306a36Sopenharmony_ci * 101462306a36Sopenharmony_ci * We atomically detach the top of branch from the tree, store the block 101562306a36Sopenharmony_ci * number of its root in *@top, pointers to buffer_heads of partially 101662306a36Sopenharmony_ci * truncated blocks - in @chain[].bh and pointers to their last elements 101762306a36Sopenharmony_ci * that should not be removed - in @chain[].p. Return value is the pointer 101862306a36Sopenharmony_ci * to last filled element of @chain. 101962306a36Sopenharmony_ci * 102062306a36Sopenharmony_ci * The work left to caller to do the actual freeing of subtrees: 102162306a36Sopenharmony_ci * a) free the subtree starting from *@top 102262306a36Sopenharmony_ci * b) free the subtrees whose roots are stored in 102362306a36Sopenharmony_ci * (@chain[i].p+1 .. end of @chain[i].bh->b_data) 102462306a36Sopenharmony_ci * c) free the subtrees growing from the inode past the @chain[0].p 102562306a36Sopenharmony_ci * (no partially truncated stuff there). 102662306a36Sopenharmony_ci */ 102762306a36Sopenharmony_ci 102862306a36Sopenharmony_cistatic Indirect *ext2_find_shared(struct inode *inode, 102962306a36Sopenharmony_ci int depth, 103062306a36Sopenharmony_ci int offsets[4], 103162306a36Sopenharmony_ci Indirect chain[4], 103262306a36Sopenharmony_ci __le32 *top) 103362306a36Sopenharmony_ci{ 103462306a36Sopenharmony_ci Indirect *partial, *p; 103562306a36Sopenharmony_ci int k, err; 103662306a36Sopenharmony_ci 103762306a36Sopenharmony_ci *top = 0; 103862306a36Sopenharmony_ci for (k = depth; k > 1 && !offsets[k-1]; k--) 103962306a36Sopenharmony_ci ; 104062306a36Sopenharmony_ci partial = ext2_get_branch(inode, k, offsets, chain, &err); 104162306a36Sopenharmony_ci if (!partial) 104262306a36Sopenharmony_ci partial = chain + k-1; 104362306a36Sopenharmony_ci /* 104462306a36Sopenharmony_ci * If the branch acquired continuation since we've looked at it - 104562306a36Sopenharmony_ci * fine, it should all survive and (new) top doesn't belong to us. 104662306a36Sopenharmony_ci */ 104762306a36Sopenharmony_ci write_lock(&EXT2_I(inode)->i_meta_lock); 104862306a36Sopenharmony_ci if (!partial->key && *partial->p) { 104962306a36Sopenharmony_ci write_unlock(&EXT2_I(inode)->i_meta_lock); 105062306a36Sopenharmony_ci goto no_top; 105162306a36Sopenharmony_ci } 105262306a36Sopenharmony_ci for (p=partial; p>chain && all_zeroes((__le32*)p->bh->b_data,p->p); p--) 105362306a36Sopenharmony_ci ; 105462306a36Sopenharmony_ci /* 105562306a36Sopenharmony_ci * OK, we've found the last block that must survive. The rest of our 105662306a36Sopenharmony_ci * branch should be detached before unlocking. However, if that rest 105762306a36Sopenharmony_ci * of branch is all ours and does not grow immediately from the inode 105862306a36Sopenharmony_ci * it's easier to cheat and just decrement partial->p. 105962306a36Sopenharmony_ci */ 106062306a36Sopenharmony_ci if (p == chain + k - 1 && p > chain) { 106162306a36Sopenharmony_ci p->p--; 106262306a36Sopenharmony_ci } else { 106362306a36Sopenharmony_ci *top = *p->p; 106462306a36Sopenharmony_ci *p->p = 0; 106562306a36Sopenharmony_ci } 106662306a36Sopenharmony_ci write_unlock(&EXT2_I(inode)->i_meta_lock); 106762306a36Sopenharmony_ci 106862306a36Sopenharmony_ci while(partial > p) 106962306a36Sopenharmony_ci { 107062306a36Sopenharmony_ci brelse(partial->bh); 107162306a36Sopenharmony_ci partial--; 107262306a36Sopenharmony_ci } 107362306a36Sopenharmony_cino_top: 107462306a36Sopenharmony_ci return partial; 107562306a36Sopenharmony_ci} 107662306a36Sopenharmony_ci 107762306a36Sopenharmony_ci/** 107862306a36Sopenharmony_ci * ext2_free_data - free a list of data blocks 107962306a36Sopenharmony_ci * @inode: inode we are dealing with 108062306a36Sopenharmony_ci * @p: array of block numbers 108162306a36Sopenharmony_ci * @q: points immediately past the end of array 108262306a36Sopenharmony_ci * 108362306a36Sopenharmony_ci * We are freeing all blocks referred from that array (numbers are 108462306a36Sopenharmony_ci * stored as little-endian 32-bit) and updating @inode->i_blocks 108562306a36Sopenharmony_ci * appropriately. 108662306a36Sopenharmony_ci */ 108762306a36Sopenharmony_cistatic inline void ext2_free_data(struct inode *inode, __le32 *p, __le32 *q) 108862306a36Sopenharmony_ci{ 108962306a36Sopenharmony_ci ext2_fsblk_t block_to_free = 0, count = 0; 109062306a36Sopenharmony_ci ext2_fsblk_t nr; 109162306a36Sopenharmony_ci 109262306a36Sopenharmony_ci for ( ; p < q ; p++) { 109362306a36Sopenharmony_ci nr = le32_to_cpu(*p); 109462306a36Sopenharmony_ci if (nr) { 109562306a36Sopenharmony_ci *p = 0; 109662306a36Sopenharmony_ci /* accumulate blocks to free if they're contiguous */ 109762306a36Sopenharmony_ci if (count == 0) 109862306a36Sopenharmony_ci goto free_this; 109962306a36Sopenharmony_ci else if (block_to_free == nr - count) 110062306a36Sopenharmony_ci count++; 110162306a36Sopenharmony_ci else { 110262306a36Sopenharmony_ci ext2_free_blocks (inode, block_to_free, count); 110362306a36Sopenharmony_ci mark_inode_dirty(inode); 110462306a36Sopenharmony_ci free_this: 110562306a36Sopenharmony_ci block_to_free = nr; 110662306a36Sopenharmony_ci count = 1; 110762306a36Sopenharmony_ci } 110862306a36Sopenharmony_ci } 110962306a36Sopenharmony_ci } 111062306a36Sopenharmony_ci if (count > 0) { 111162306a36Sopenharmony_ci ext2_free_blocks (inode, block_to_free, count); 111262306a36Sopenharmony_ci mark_inode_dirty(inode); 111362306a36Sopenharmony_ci } 111462306a36Sopenharmony_ci} 111562306a36Sopenharmony_ci 111662306a36Sopenharmony_ci/** 111762306a36Sopenharmony_ci * ext2_free_branches - free an array of branches 111862306a36Sopenharmony_ci * @inode: inode we are dealing with 111962306a36Sopenharmony_ci * @p: array of block numbers 112062306a36Sopenharmony_ci * @q: pointer immediately past the end of array 112162306a36Sopenharmony_ci * @depth: depth of the branches to free 112262306a36Sopenharmony_ci * 112362306a36Sopenharmony_ci * We are freeing all blocks referred from these branches (numbers are 112462306a36Sopenharmony_ci * stored as little-endian 32-bit) and updating @inode->i_blocks 112562306a36Sopenharmony_ci * appropriately. 112662306a36Sopenharmony_ci */ 112762306a36Sopenharmony_cistatic void ext2_free_branches(struct inode *inode, __le32 *p, __le32 *q, int depth) 112862306a36Sopenharmony_ci{ 112962306a36Sopenharmony_ci struct buffer_head * bh; 113062306a36Sopenharmony_ci ext2_fsblk_t nr; 113162306a36Sopenharmony_ci 113262306a36Sopenharmony_ci if (depth--) { 113362306a36Sopenharmony_ci int addr_per_block = EXT2_ADDR_PER_BLOCK(inode->i_sb); 113462306a36Sopenharmony_ci for ( ; p < q ; p++) { 113562306a36Sopenharmony_ci nr = le32_to_cpu(*p); 113662306a36Sopenharmony_ci if (!nr) 113762306a36Sopenharmony_ci continue; 113862306a36Sopenharmony_ci *p = 0; 113962306a36Sopenharmony_ci bh = sb_bread(inode->i_sb, nr); 114062306a36Sopenharmony_ci /* 114162306a36Sopenharmony_ci * A read failure? Report error and clear slot 114262306a36Sopenharmony_ci * (should be rare). 114362306a36Sopenharmony_ci */ 114462306a36Sopenharmony_ci if (!bh) { 114562306a36Sopenharmony_ci ext2_error(inode->i_sb, "ext2_free_branches", 114662306a36Sopenharmony_ci "Read failure, inode=%ld, block=%ld", 114762306a36Sopenharmony_ci inode->i_ino, nr); 114862306a36Sopenharmony_ci continue; 114962306a36Sopenharmony_ci } 115062306a36Sopenharmony_ci ext2_free_branches(inode, 115162306a36Sopenharmony_ci (__le32*)bh->b_data, 115262306a36Sopenharmony_ci (__le32*)bh->b_data + addr_per_block, 115362306a36Sopenharmony_ci depth); 115462306a36Sopenharmony_ci bforget(bh); 115562306a36Sopenharmony_ci ext2_free_blocks(inode, nr, 1); 115662306a36Sopenharmony_ci mark_inode_dirty(inode); 115762306a36Sopenharmony_ci } 115862306a36Sopenharmony_ci } else 115962306a36Sopenharmony_ci ext2_free_data(inode, p, q); 116062306a36Sopenharmony_ci} 116162306a36Sopenharmony_ci 116262306a36Sopenharmony_ci/* mapping->invalidate_lock must be held when calling this function */ 116362306a36Sopenharmony_cistatic void __ext2_truncate_blocks(struct inode *inode, loff_t offset) 116462306a36Sopenharmony_ci{ 116562306a36Sopenharmony_ci __le32 *i_data = EXT2_I(inode)->i_data; 116662306a36Sopenharmony_ci struct ext2_inode_info *ei = EXT2_I(inode); 116762306a36Sopenharmony_ci int addr_per_block = EXT2_ADDR_PER_BLOCK(inode->i_sb); 116862306a36Sopenharmony_ci int offsets[4]; 116962306a36Sopenharmony_ci Indirect chain[4]; 117062306a36Sopenharmony_ci Indirect *partial; 117162306a36Sopenharmony_ci __le32 nr = 0; 117262306a36Sopenharmony_ci int n; 117362306a36Sopenharmony_ci long iblock; 117462306a36Sopenharmony_ci unsigned blocksize; 117562306a36Sopenharmony_ci blocksize = inode->i_sb->s_blocksize; 117662306a36Sopenharmony_ci iblock = (offset + blocksize-1) >> EXT2_BLOCK_SIZE_BITS(inode->i_sb); 117762306a36Sopenharmony_ci 117862306a36Sopenharmony_ci#ifdef CONFIG_FS_DAX 117962306a36Sopenharmony_ci WARN_ON(!rwsem_is_locked(&inode->i_mapping->invalidate_lock)); 118062306a36Sopenharmony_ci#endif 118162306a36Sopenharmony_ci 118262306a36Sopenharmony_ci n = ext2_block_to_path(inode, iblock, offsets, NULL); 118362306a36Sopenharmony_ci if (n == 0) 118462306a36Sopenharmony_ci return; 118562306a36Sopenharmony_ci 118662306a36Sopenharmony_ci /* 118762306a36Sopenharmony_ci * From here we block out all ext2_get_block() callers who want to 118862306a36Sopenharmony_ci * modify the block allocation tree. 118962306a36Sopenharmony_ci */ 119062306a36Sopenharmony_ci mutex_lock(&ei->truncate_mutex); 119162306a36Sopenharmony_ci 119262306a36Sopenharmony_ci if (n == 1) { 119362306a36Sopenharmony_ci ext2_free_data(inode, i_data+offsets[0], 119462306a36Sopenharmony_ci i_data + EXT2_NDIR_BLOCKS); 119562306a36Sopenharmony_ci goto do_indirects; 119662306a36Sopenharmony_ci } 119762306a36Sopenharmony_ci 119862306a36Sopenharmony_ci partial = ext2_find_shared(inode, n, offsets, chain, &nr); 119962306a36Sopenharmony_ci /* Kill the top of shared branch (already detached) */ 120062306a36Sopenharmony_ci if (nr) { 120162306a36Sopenharmony_ci if (partial == chain) 120262306a36Sopenharmony_ci mark_inode_dirty(inode); 120362306a36Sopenharmony_ci else 120462306a36Sopenharmony_ci mark_buffer_dirty_inode(partial->bh, inode); 120562306a36Sopenharmony_ci ext2_free_branches(inode, &nr, &nr+1, (chain+n-1) - partial); 120662306a36Sopenharmony_ci } 120762306a36Sopenharmony_ci /* Clear the ends of indirect blocks on the shared branch */ 120862306a36Sopenharmony_ci while (partial > chain) { 120962306a36Sopenharmony_ci ext2_free_branches(inode, 121062306a36Sopenharmony_ci partial->p + 1, 121162306a36Sopenharmony_ci (__le32*)partial->bh->b_data+addr_per_block, 121262306a36Sopenharmony_ci (chain+n-1) - partial); 121362306a36Sopenharmony_ci mark_buffer_dirty_inode(partial->bh, inode); 121462306a36Sopenharmony_ci brelse (partial->bh); 121562306a36Sopenharmony_ci partial--; 121662306a36Sopenharmony_ci } 121762306a36Sopenharmony_cido_indirects: 121862306a36Sopenharmony_ci /* Kill the remaining (whole) subtrees */ 121962306a36Sopenharmony_ci switch (offsets[0]) { 122062306a36Sopenharmony_ci default: 122162306a36Sopenharmony_ci nr = i_data[EXT2_IND_BLOCK]; 122262306a36Sopenharmony_ci if (nr) { 122362306a36Sopenharmony_ci i_data[EXT2_IND_BLOCK] = 0; 122462306a36Sopenharmony_ci mark_inode_dirty(inode); 122562306a36Sopenharmony_ci ext2_free_branches(inode, &nr, &nr+1, 1); 122662306a36Sopenharmony_ci } 122762306a36Sopenharmony_ci fallthrough; 122862306a36Sopenharmony_ci case EXT2_IND_BLOCK: 122962306a36Sopenharmony_ci nr = i_data[EXT2_DIND_BLOCK]; 123062306a36Sopenharmony_ci if (nr) { 123162306a36Sopenharmony_ci i_data[EXT2_DIND_BLOCK] = 0; 123262306a36Sopenharmony_ci mark_inode_dirty(inode); 123362306a36Sopenharmony_ci ext2_free_branches(inode, &nr, &nr+1, 2); 123462306a36Sopenharmony_ci } 123562306a36Sopenharmony_ci fallthrough; 123662306a36Sopenharmony_ci case EXT2_DIND_BLOCK: 123762306a36Sopenharmony_ci nr = i_data[EXT2_TIND_BLOCK]; 123862306a36Sopenharmony_ci if (nr) { 123962306a36Sopenharmony_ci i_data[EXT2_TIND_BLOCK] = 0; 124062306a36Sopenharmony_ci mark_inode_dirty(inode); 124162306a36Sopenharmony_ci ext2_free_branches(inode, &nr, &nr+1, 3); 124262306a36Sopenharmony_ci } 124362306a36Sopenharmony_ci break; 124462306a36Sopenharmony_ci case EXT2_TIND_BLOCK: 124562306a36Sopenharmony_ci ; 124662306a36Sopenharmony_ci } 124762306a36Sopenharmony_ci 124862306a36Sopenharmony_ci ext2_discard_reservation(inode); 124962306a36Sopenharmony_ci 125062306a36Sopenharmony_ci mutex_unlock(&ei->truncate_mutex); 125162306a36Sopenharmony_ci} 125262306a36Sopenharmony_ci 125362306a36Sopenharmony_cistatic void ext2_truncate_blocks(struct inode *inode, loff_t offset) 125462306a36Sopenharmony_ci{ 125562306a36Sopenharmony_ci if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) || 125662306a36Sopenharmony_ci S_ISLNK(inode->i_mode))) 125762306a36Sopenharmony_ci return; 125862306a36Sopenharmony_ci if (ext2_inode_is_fast_symlink(inode)) 125962306a36Sopenharmony_ci return; 126062306a36Sopenharmony_ci 126162306a36Sopenharmony_ci filemap_invalidate_lock(inode->i_mapping); 126262306a36Sopenharmony_ci __ext2_truncate_blocks(inode, offset); 126362306a36Sopenharmony_ci filemap_invalidate_unlock(inode->i_mapping); 126462306a36Sopenharmony_ci} 126562306a36Sopenharmony_ci 126662306a36Sopenharmony_cistatic int ext2_setsize(struct inode *inode, loff_t newsize) 126762306a36Sopenharmony_ci{ 126862306a36Sopenharmony_ci int error; 126962306a36Sopenharmony_ci 127062306a36Sopenharmony_ci if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) || 127162306a36Sopenharmony_ci S_ISLNK(inode->i_mode))) 127262306a36Sopenharmony_ci return -EINVAL; 127362306a36Sopenharmony_ci if (ext2_inode_is_fast_symlink(inode)) 127462306a36Sopenharmony_ci return -EINVAL; 127562306a36Sopenharmony_ci if (IS_APPEND(inode) || IS_IMMUTABLE(inode)) 127662306a36Sopenharmony_ci return -EPERM; 127762306a36Sopenharmony_ci 127862306a36Sopenharmony_ci inode_dio_wait(inode); 127962306a36Sopenharmony_ci 128062306a36Sopenharmony_ci if (IS_DAX(inode)) 128162306a36Sopenharmony_ci error = dax_truncate_page(inode, newsize, NULL, 128262306a36Sopenharmony_ci &ext2_iomap_ops); 128362306a36Sopenharmony_ci else 128462306a36Sopenharmony_ci error = block_truncate_page(inode->i_mapping, 128562306a36Sopenharmony_ci newsize, ext2_get_block); 128662306a36Sopenharmony_ci if (error) 128762306a36Sopenharmony_ci return error; 128862306a36Sopenharmony_ci 128962306a36Sopenharmony_ci filemap_invalidate_lock(inode->i_mapping); 129062306a36Sopenharmony_ci truncate_setsize(inode, newsize); 129162306a36Sopenharmony_ci __ext2_truncate_blocks(inode, newsize); 129262306a36Sopenharmony_ci filemap_invalidate_unlock(inode->i_mapping); 129362306a36Sopenharmony_ci 129462306a36Sopenharmony_ci inode->i_mtime = inode_set_ctime_current(inode); 129562306a36Sopenharmony_ci if (inode_needs_sync(inode)) { 129662306a36Sopenharmony_ci sync_mapping_buffers(inode->i_mapping); 129762306a36Sopenharmony_ci sync_inode_metadata(inode, 1); 129862306a36Sopenharmony_ci } else { 129962306a36Sopenharmony_ci mark_inode_dirty(inode); 130062306a36Sopenharmony_ci } 130162306a36Sopenharmony_ci 130262306a36Sopenharmony_ci return 0; 130362306a36Sopenharmony_ci} 130462306a36Sopenharmony_ci 130562306a36Sopenharmony_cistatic struct ext2_inode *ext2_get_inode(struct super_block *sb, ino_t ino, 130662306a36Sopenharmony_ci struct buffer_head **p) 130762306a36Sopenharmony_ci{ 130862306a36Sopenharmony_ci struct buffer_head * bh; 130962306a36Sopenharmony_ci unsigned long block_group; 131062306a36Sopenharmony_ci unsigned long block; 131162306a36Sopenharmony_ci unsigned long offset; 131262306a36Sopenharmony_ci struct ext2_group_desc * gdp; 131362306a36Sopenharmony_ci 131462306a36Sopenharmony_ci *p = NULL; 131562306a36Sopenharmony_ci if ((ino != EXT2_ROOT_INO && ino < EXT2_FIRST_INO(sb)) || 131662306a36Sopenharmony_ci ino > le32_to_cpu(EXT2_SB(sb)->s_es->s_inodes_count)) 131762306a36Sopenharmony_ci goto Einval; 131862306a36Sopenharmony_ci 131962306a36Sopenharmony_ci block_group = (ino - 1) / EXT2_INODES_PER_GROUP(sb); 132062306a36Sopenharmony_ci gdp = ext2_get_group_desc(sb, block_group, NULL); 132162306a36Sopenharmony_ci if (!gdp) 132262306a36Sopenharmony_ci goto Egdp; 132362306a36Sopenharmony_ci /* 132462306a36Sopenharmony_ci * Figure out the offset within the block group inode table 132562306a36Sopenharmony_ci */ 132662306a36Sopenharmony_ci offset = ((ino - 1) % EXT2_INODES_PER_GROUP(sb)) * EXT2_INODE_SIZE(sb); 132762306a36Sopenharmony_ci block = le32_to_cpu(gdp->bg_inode_table) + 132862306a36Sopenharmony_ci (offset >> EXT2_BLOCK_SIZE_BITS(sb)); 132962306a36Sopenharmony_ci if (!(bh = sb_bread(sb, block))) 133062306a36Sopenharmony_ci goto Eio; 133162306a36Sopenharmony_ci 133262306a36Sopenharmony_ci *p = bh; 133362306a36Sopenharmony_ci offset &= (EXT2_BLOCK_SIZE(sb) - 1); 133462306a36Sopenharmony_ci return (struct ext2_inode *) (bh->b_data + offset); 133562306a36Sopenharmony_ci 133662306a36Sopenharmony_ciEinval: 133762306a36Sopenharmony_ci ext2_error(sb, "ext2_get_inode", "bad inode number: %lu", 133862306a36Sopenharmony_ci (unsigned long) ino); 133962306a36Sopenharmony_ci return ERR_PTR(-EINVAL); 134062306a36Sopenharmony_ciEio: 134162306a36Sopenharmony_ci ext2_error(sb, "ext2_get_inode", 134262306a36Sopenharmony_ci "unable to read inode block - inode=%lu, block=%lu", 134362306a36Sopenharmony_ci (unsigned long) ino, block); 134462306a36Sopenharmony_ciEgdp: 134562306a36Sopenharmony_ci return ERR_PTR(-EIO); 134662306a36Sopenharmony_ci} 134762306a36Sopenharmony_ci 134862306a36Sopenharmony_civoid ext2_set_inode_flags(struct inode *inode) 134962306a36Sopenharmony_ci{ 135062306a36Sopenharmony_ci unsigned int flags = EXT2_I(inode)->i_flags; 135162306a36Sopenharmony_ci 135262306a36Sopenharmony_ci inode->i_flags &= ~(S_SYNC | S_APPEND | S_IMMUTABLE | S_NOATIME | 135362306a36Sopenharmony_ci S_DIRSYNC | S_DAX); 135462306a36Sopenharmony_ci if (flags & EXT2_SYNC_FL) 135562306a36Sopenharmony_ci inode->i_flags |= S_SYNC; 135662306a36Sopenharmony_ci if (flags & EXT2_APPEND_FL) 135762306a36Sopenharmony_ci inode->i_flags |= S_APPEND; 135862306a36Sopenharmony_ci if (flags & EXT2_IMMUTABLE_FL) 135962306a36Sopenharmony_ci inode->i_flags |= S_IMMUTABLE; 136062306a36Sopenharmony_ci if (flags & EXT2_NOATIME_FL) 136162306a36Sopenharmony_ci inode->i_flags |= S_NOATIME; 136262306a36Sopenharmony_ci if (flags & EXT2_DIRSYNC_FL) 136362306a36Sopenharmony_ci inode->i_flags |= S_DIRSYNC; 136462306a36Sopenharmony_ci if (test_opt(inode->i_sb, DAX) && S_ISREG(inode->i_mode)) 136562306a36Sopenharmony_ci inode->i_flags |= S_DAX; 136662306a36Sopenharmony_ci} 136762306a36Sopenharmony_ci 136862306a36Sopenharmony_civoid ext2_set_file_ops(struct inode *inode) 136962306a36Sopenharmony_ci{ 137062306a36Sopenharmony_ci inode->i_op = &ext2_file_inode_operations; 137162306a36Sopenharmony_ci inode->i_fop = &ext2_file_operations; 137262306a36Sopenharmony_ci if (IS_DAX(inode)) 137362306a36Sopenharmony_ci inode->i_mapping->a_ops = &ext2_dax_aops; 137462306a36Sopenharmony_ci else 137562306a36Sopenharmony_ci inode->i_mapping->a_ops = &ext2_aops; 137662306a36Sopenharmony_ci} 137762306a36Sopenharmony_ci 137862306a36Sopenharmony_cistruct inode *ext2_iget (struct super_block *sb, unsigned long ino) 137962306a36Sopenharmony_ci{ 138062306a36Sopenharmony_ci struct ext2_inode_info *ei; 138162306a36Sopenharmony_ci struct buffer_head * bh = NULL; 138262306a36Sopenharmony_ci struct ext2_inode *raw_inode; 138362306a36Sopenharmony_ci struct inode *inode; 138462306a36Sopenharmony_ci long ret = -EIO; 138562306a36Sopenharmony_ci int n; 138662306a36Sopenharmony_ci uid_t i_uid; 138762306a36Sopenharmony_ci gid_t i_gid; 138862306a36Sopenharmony_ci 138962306a36Sopenharmony_ci inode = iget_locked(sb, ino); 139062306a36Sopenharmony_ci if (!inode) 139162306a36Sopenharmony_ci return ERR_PTR(-ENOMEM); 139262306a36Sopenharmony_ci if (!(inode->i_state & I_NEW)) 139362306a36Sopenharmony_ci return inode; 139462306a36Sopenharmony_ci 139562306a36Sopenharmony_ci ei = EXT2_I(inode); 139662306a36Sopenharmony_ci ei->i_block_alloc_info = NULL; 139762306a36Sopenharmony_ci 139862306a36Sopenharmony_ci raw_inode = ext2_get_inode(inode->i_sb, ino, &bh); 139962306a36Sopenharmony_ci if (IS_ERR(raw_inode)) { 140062306a36Sopenharmony_ci ret = PTR_ERR(raw_inode); 140162306a36Sopenharmony_ci goto bad_inode; 140262306a36Sopenharmony_ci } 140362306a36Sopenharmony_ci 140462306a36Sopenharmony_ci inode->i_mode = le16_to_cpu(raw_inode->i_mode); 140562306a36Sopenharmony_ci i_uid = (uid_t)le16_to_cpu(raw_inode->i_uid_low); 140662306a36Sopenharmony_ci i_gid = (gid_t)le16_to_cpu(raw_inode->i_gid_low); 140762306a36Sopenharmony_ci if (!(test_opt (inode->i_sb, NO_UID32))) { 140862306a36Sopenharmony_ci i_uid |= le16_to_cpu(raw_inode->i_uid_high) << 16; 140962306a36Sopenharmony_ci i_gid |= le16_to_cpu(raw_inode->i_gid_high) << 16; 141062306a36Sopenharmony_ci } 141162306a36Sopenharmony_ci i_uid_write(inode, i_uid); 141262306a36Sopenharmony_ci i_gid_write(inode, i_gid); 141362306a36Sopenharmony_ci set_nlink(inode, le16_to_cpu(raw_inode->i_links_count)); 141462306a36Sopenharmony_ci inode->i_size = le32_to_cpu(raw_inode->i_size); 141562306a36Sopenharmony_ci inode->i_atime.tv_sec = (signed)le32_to_cpu(raw_inode->i_atime); 141662306a36Sopenharmony_ci inode_set_ctime(inode, (signed)le32_to_cpu(raw_inode->i_ctime), 0); 141762306a36Sopenharmony_ci inode->i_mtime.tv_sec = (signed)le32_to_cpu(raw_inode->i_mtime); 141862306a36Sopenharmony_ci inode->i_atime.tv_nsec = inode->i_mtime.tv_nsec = 0; 141962306a36Sopenharmony_ci ei->i_dtime = le32_to_cpu(raw_inode->i_dtime); 142062306a36Sopenharmony_ci /* We now have enough fields to check if the inode was active or not. 142162306a36Sopenharmony_ci * This is needed because nfsd might try to access dead inodes 142262306a36Sopenharmony_ci * the test is that same one that e2fsck uses 142362306a36Sopenharmony_ci * NeilBrown 1999oct15 142462306a36Sopenharmony_ci */ 142562306a36Sopenharmony_ci if (inode->i_nlink == 0 && (inode->i_mode == 0 || ei->i_dtime)) { 142662306a36Sopenharmony_ci /* this inode is deleted */ 142762306a36Sopenharmony_ci ret = -ESTALE; 142862306a36Sopenharmony_ci goto bad_inode; 142962306a36Sopenharmony_ci } 143062306a36Sopenharmony_ci inode->i_blocks = le32_to_cpu(raw_inode->i_blocks); 143162306a36Sopenharmony_ci ei->i_flags = le32_to_cpu(raw_inode->i_flags); 143262306a36Sopenharmony_ci ext2_set_inode_flags(inode); 143362306a36Sopenharmony_ci ei->i_faddr = le32_to_cpu(raw_inode->i_faddr); 143462306a36Sopenharmony_ci ei->i_frag_no = raw_inode->i_frag; 143562306a36Sopenharmony_ci ei->i_frag_size = raw_inode->i_fsize; 143662306a36Sopenharmony_ci ei->i_file_acl = le32_to_cpu(raw_inode->i_file_acl); 143762306a36Sopenharmony_ci ei->i_dir_acl = 0; 143862306a36Sopenharmony_ci 143962306a36Sopenharmony_ci if (ei->i_file_acl && 144062306a36Sopenharmony_ci !ext2_data_block_valid(EXT2_SB(sb), ei->i_file_acl, 1)) { 144162306a36Sopenharmony_ci ext2_error(sb, "ext2_iget", "bad extended attribute block %u", 144262306a36Sopenharmony_ci ei->i_file_acl); 144362306a36Sopenharmony_ci ret = -EFSCORRUPTED; 144462306a36Sopenharmony_ci goto bad_inode; 144562306a36Sopenharmony_ci } 144662306a36Sopenharmony_ci 144762306a36Sopenharmony_ci if (S_ISREG(inode->i_mode)) 144862306a36Sopenharmony_ci inode->i_size |= ((__u64)le32_to_cpu(raw_inode->i_size_high)) << 32; 144962306a36Sopenharmony_ci else 145062306a36Sopenharmony_ci ei->i_dir_acl = le32_to_cpu(raw_inode->i_dir_acl); 145162306a36Sopenharmony_ci if (i_size_read(inode) < 0) { 145262306a36Sopenharmony_ci ret = -EFSCORRUPTED; 145362306a36Sopenharmony_ci goto bad_inode; 145462306a36Sopenharmony_ci } 145562306a36Sopenharmony_ci ei->i_dtime = 0; 145662306a36Sopenharmony_ci inode->i_generation = le32_to_cpu(raw_inode->i_generation); 145762306a36Sopenharmony_ci ei->i_state = 0; 145862306a36Sopenharmony_ci ei->i_block_group = (ino - 1) / EXT2_INODES_PER_GROUP(inode->i_sb); 145962306a36Sopenharmony_ci ei->i_dir_start_lookup = 0; 146062306a36Sopenharmony_ci 146162306a36Sopenharmony_ci /* 146262306a36Sopenharmony_ci * NOTE! The in-memory inode i_data array is in little-endian order 146362306a36Sopenharmony_ci * even on big-endian machines: we do NOT byteswap the block numbers! 146462306a36Sopenharmony_ci */ 146562306a36Sopenharmony_ci for (n = 0; n < EXT2_N_BLOCKS; n++) 146662306a36Sopenharmony_ci ei->i_data[n] = raw_inode->i_block[n]; 146762306a36Sopenharmony_ci 146862306a36Sopenharmony_ci if (S_ISREG(inode->i_mode)) { 146962306a36Sopenharmony_ci ext2_set_file_ops(inode); 147062306a36Sopenharmony_ci } else if (S_ISDIR(inode->i_mode)) { 147162306a36Sopenharmony_ci inode->i_op = &ext2_dir_inode_operations; 147262306a36Sopenharmony_ci inode->i_fop = &ext2_dir_operations; 147362306a36Sopenharmony_ci inode->i_mapping->a_ops = &ext2_aops; 147462306a36Sopenharmony_ci } else if (S_ISLNK(inode->i_mode)) { 147562306a36Sopenharmony_ci if (ext2_inode_is_fast_symlink(inode)) { 147662306a36Sopenharmony_ci inode->i_link = (char *)ei->i_data; 147762306a36Sopenharmony_ci inode->i_op = &ext2_fast_symlink_inode_operations; 147862306a36Sopenharmony_ci nd_terminate_link(ei->i_data, inode->i_size, 147962306a36Sopenharmony_ci sizeof(ei->i_data) - 1); 148062306a36Sopenharmony_ci } else { 148162306a36Sopenharmony_ci inode->i_op = &ext2_symlink_inode_operations; 148262306a36Sopenharmony_ci inode_nohighmem(inode); 148362306a36Sopenharmony_ci inode->i_mapping->a_ops = &ext2_aops; 148462306a36Sopenharmony_ci } 148562306a36Sopenharmony_ci } else { 148662306a36Sopenharmony_ci inode->i_op = &ext2_special_inode_operations; 148762306a36Sopenharmony_ci if (raw_inode->i_block[0]) 148862306a36Sopenharmony_ci init_special_inode(inode, inode->i_mode, 148962306a36Sopenharmony_ci old_decode_dev(le32_to_cpu(raw_inode->i_block[0]))); 149062306a36Sopenharmony_ci else 149162306a36Sopenharmony_ci init_special_inode(inode, inode->i_mode, 149262306a36Sopenharmony_ci new_decode_dev(le32_to_cpu(raw_inode->i_block[1]))); 149362306a36Sopenharmony_ci } 149462306a36Sopenharmony_ci brelse (bh); 149562306a36Sopenharmony_ci unlock_new_inode(inode); 149662306a36Sopenharmony_ci return inode; 149762306a36Sopenharmony_ci 149862306a36Sopenharmony_cibad_inode: 149962306a36Sopenharmony_ci brelse(bh); 150062306a36Sopenharmony_ci iget_failed(inode); 150162306a36Sopenharmony_ci return ERR_PTR(ret); 150262306a36Sopenharmony_ci} 150362306a36Sopenharmony_ci 150462306a36Sopenharmony_cistatic int __ext2_write_inode(struct inode *inode, int do_sync) 150562306a36Sopenharmony_ci{ 150662306a36Sopenharmony_ci struct ext2_inode_info *ei = EXT2_I(inode); 150762306a36Sopenharmony_ci struct super_block *sb = inode->i_sb; 150862306a36Sopenharmony_ci ino_t ino = inode->i_ino; 150962306a36Sopenharmony_ci uid_t uid = i_uid_read(inode); 151062306a36Sopenharmony_ci gid_t gid = i_gid_read(inode); 151162306a36Sopenharmony_ci struct buffer_head * bh; 151262306a36Sopenharmony_ci struct ext2_inode * raw_inode = ext2_get_inode(sb, ino, &bh); 151362306a36Sopenharmony_ci int n; 151462306a36Sopenharmony_ci int err = 0; 151562306a36Sopenharmony_ci 151662306a36Sopenharmony_ci if (IS_ERR(raw_inode)) 151762306a36Sopenharmony_ci return -EIO; 151862306a36Sopenharmony_ci 151962306a36Sopenharmony_ci /* For fields not tracking in the in-memory inode, 152062306a36Sopenharmony_ci * initialise them to zero for new inodes. */ 152162306a36Sopenharmony_ci if (ei->i_state & EXT2_STATE_NEW) 152262306a36Sopenharmony_ci memset(raw_inode, 0, EXT2_SB(sb)->s_inode_size); 152362306a36Sopenharmony_ci 152462306a36Sopenharmony_ci raw_inode->i_mode = cpu_to_le16(inode->i_mode); 152562306a36Sopenharmony_ci if (!(test_opt(sb, NO_UID32))) { 152662306a36Sopenharmony_ci raw_inode->i_uid_low = cpu_to_le16(low_16_bits(uid)); 152762306a36Sopenharmony_ci raw_inode->i_gid_low = cpu_to_le16(low_16_bits(gid)); 152862306a36Sopenharmony_ci/* 152962306a36Sopenharmony_ci * Fix up interoperability with old kernels. Otherwise, old inodes get 153062306a36Sopenharmony_ci * re-used with the upper 16 bits of the uid/gid intact 153162306a36Sopenharmony_ci */ 153262306a36Sopenharmony_ci if (!ei->i_dtime) { 153362306a36Sopenharmony_ci raw_inode->i_uid_high = cpu_to_le16(high_16_bits(uid)); 153462306a36Sopenharmony_ci raw_inode->i_gid_high = cpu_to_le16(high_16_bits(gid)); 153562306a36Sopenharmony_ci } else { 153662306a36Sopenharmony_ci raw_inode->i_uid_high = 0; 153762306a36Sopenharmony_ci raw_inode->i_gid_high = 0; 153862306a36Sopenharmony_ci } 153962306a36Sopenharmony_ci } else { 154062306a36Sopenharmony_ci raw_inode->i_uid_low = cpu_to_le16(fs_high2lowuid(uid)); 154162306a36Sopenharmony_ci raw_inode->i_gid_low = cpu_to_le16(fs_high2lowgid(gid)); 154262306a36Sopenharmony_ci raw_inode->i_uid_high = 0; 154362306a36Sopenharmony_ci raw_inode->i_gid_high = 0; 154462306a36Sopenharmony_ci } 154562306a36Sopenharmony_ci raw_inode->i_links_count = cpu_to_le16(inode->i_nlink); 154662306a36Sopenharmony_ci raw_inode->i_size = cpu_to_le32(inode->i_size); 154762306a36Sopenharmony_ci raw_inode->i_atime = cpu_to_le32(inode->i_atime.tv_sec); 154862306a36Sopenharmony_ci raw_inode->i_ctime = cpu_to_le32(inode_get_ctime(inode).tv_sec); 154962306a36Sopenharmony_ci raw_inode->i_mtime = cpu_to_le32(inode->i_mtime.tv_sec); 155062306a36Sopenharmony_ci 155162306a36Sopenharmony_ci raw_inode->i_blocks = cpu_to_le32(inode->i_blocks); 155262306a36Sopenharmony_ci raw_inode->i_dtime = cpu_to_le32(ei->i_dtime); 155362306a36Sopenharmony_ci raw_inode->i_flags = cpu_to_le32(ei->i_flags); 155462306a36Sopenharmony_ci raw_inode->i_faddr = cpu_to_le32(ei->i_faddr); 155562306a36Sopenharmony_ci raw_inode->i_frag = ei->i_frag_no; 155662306a36Sopenharmony_ci raw_inode->i_fsize = ei->i_frag_size; 155762306a36Sopenharmony_ci raw_inode->i_file_acl = cpu_to_le32(ei->i_file_acl); 155862306a36Sopenharmony_ci if (!S_ISREG(inode->i_mode)) 155962306a36Sopenharmony_ci raw_inode->i_dir_acl = cpu_to_le32(ei->i_dir_acl); 156062306a36Sopenharmony_ci else { 156162306a36Sopenharmony_ci raw_inode->i_size_high = cpu_to_le32(inode->i_size >> 32); 156262306a36Sopenharmony_ci if (inode->i_size > 0x7fffffffULL) { 156362306a36Sopenharmony_ci if (!EXT2_HAS_RO_COMPAT_FEATURE(sb, 156462306a36Sopenharmony_ci EXT2_FEATURE_RO_COMPAT_LARGE_FILE) || 156562306a36Sopenharmony_ci EXT2_SB(sb)->s_es->s_rev_level == 156662306a36Sopenharmony_ci cpu_to_le32(EXT2_GOOD_OLD_REV)) { 156762306a36Sopenharmony_ci /* If this is the first large file 156862306a36Sopenharmony_ci * created, add a flag to the superblock. 156962306a36Sopenharmony_ci */ 157062306a36Sopenharmony_ci spin_lock(&EXT2_SB(sb)->s_lock); 157162306a36Sopenharmony_ci ext2_update_dynamic_rev(sb); 157262306a36Sopenharmony_ci EXT2_SET_RO_COMPAT_FEATURE(sb, 157362306a36Sopenharmony_ci EXT2_FEATURE_RO_COMPAT_LARGE_FILE); 157462306a36Sopenharmony_ci spin_unlock(&EXT2_SB(sb)->s_lock); 157562306a36Sopenharmony_ci ext2_sync_super(sb, EXT2_SB(sb)->s_es, 1); 157662306a36Sopenharmony_ci } 157762306a36Sopenharmony_ci } 157862306a36Sopenharmony_ci } 157962306a36Sopenharmony_ci 158062306a36Sopenharmony_ci raw_inode->i_generation = cpu_to_le32(inode->i_generation); 158162306a36Sopenharmony_ci if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) { 158262306a36Sopenharmony_ci if (old_valid_dev(inode->i_rdev)) { 158362306a36Sopenharmony_ci raw_inode->i_block[0] = 158462306a36Sopenharmony_ci cpu_to_le32(old_encode_dev(inode->i_rdev)); 158562306a36Sopenharmony_ci raw_inode->i_block[1] = 0; 158662306a36Sopenharmony_ci } else { 158762306a36Sopenharmony_ci raw_inode->i_block[0] = 0; 158862306a36Sopenharmony_ci raw_inode->i_block[1] = 158962306a36Sopenharmony_ci cpu_to_le32(new_encode_dev(inode->i_rdev)); 159062306a36Sopenharmony_ci raw_inode->i_block[2] = 0; 159162306a36Sopenharmony_ci } 159262306a36Sopenharmony_ci } else for (n = 0; n < EXT2_N_BLOCKS; n++) 159362306a36Sopenharmony_ci raw_inode->i_block[n] = ei->i_data[n]; 159462306a36Sopenharmony_ci mark_buffer_dirty(bh); 159562306a36Sopenharmony_ci if (do_sync) { 159662306a36Sopenharmony_ci sync_dirty_buffer(bh); 159762306a36Sopenharmony_ci if (buffer_req(bh) && !buffer_uptodate(bh)) { 159862306a36Sopenharmony_ci printk ("IO error syncing ext2 inode [%s:%08lx]\n", 159962306a36Sopenharmony_ci sb->s_id, (unsigned long) ino); 160062306a36Sopenharmony_ci err = -EIO; 160162306a36Sopenharmony_ci } 160262306a36Sopenharmony_ci } 160362306a36Sopenharmony_ci ei->i_state &= ~EXT2_STATE_NEW; 160462306a36Sopenharmony_ci brelse (bh); 160562306a36Sopenharmony_ci return err; 160662306a36Sopenharmony_ci} 160762306a36Sopenharmony_ci 160862306a36Sopenharmony_ciint ext2_write_inode(struct inode *inode, struct writeback_control *wbc) 160962306a36Sopenharmony_ci{ 161062306a36Sopenharmony_ci return __ext2_write_inode(inode, wbc->sync_mode == WB_SYNC_ALL); 161162306a36Sopenharmony_ci} 161262306a36Sopenharmony_ci 161362306a36Sopenharmony_ciint ext2_getattr(struct mnt_idmap *idmap, const struct path *path, 161462306a36Sopenharmony_ci struct kstat *stat, u32 request_mask, unsigned int query_flags) 161562306a36Sopenharmony_ci{ 161662306a36Sopenharmony_ci struct inode *inode = d_inode(path->dentry); 161762306a36Sopenharmony_ci struct ext2_inode_info *ei = EXT2_I(inode); 161862306a36Sopenharmony_ci unsigned int flags; 161962306a36Sopenharmony_ci 162062306a36Sopenharmony_ci flags = ei->i_flags & EXT2_FL_USER_VISIBLE; 162162306a36Sopenharmony_ci if (flags & EXT2_APPEND_FL) 162262306a36Sopenharmony_ci stat->attributes |= STATX_ATTR_APPEND; 162362306a36Sopenharmony_ci if (flags & EXT2_COMPR_FL) 162462306a36Sopenharmony_ci stat->attributes |= STATX_ATTR_COMPRESSED; 162562306a36Sopenharmony_ci if (flags & EXT2_IMMUTABLE_FL) 162662306a36Sopenharmony_ci stat->attributes |= STATX_ATTR_IMMUTABLE; 162762306a36Sopenharmony_ci if (flags & EXT2_NODUMP_FL) 162862306a36Sopenharmony_ci stat->attributes |= STATX_ATTR_NODUMP; 162962306a36Sopenharmony_ci stat->attributes_mask |= (STATX_ATTR_APPEND | 163062306a36Sopenharmony_ci STATX_ATTR_COMPRESSED | 163162306a36Sopenharmony_ci STATX_ATTR_ENCRYPTED | 163262306a36Sopenharmony_ci STATX_ATTR_IMMUTABLE | 163362306a36Sopenharmony_ci STATX_ATTR_NODUMP); 163462306a36Sopenharmony_ci 163562306a36Sopenharmony_ci generic_fillattr(&nop_mnt_idmap, request_mask, inode, stat); 163662306a36Sopenharmony_ci return 0; 163762306a36Sopenharmony_ci} 163862306a36Sopenharmony_ci 163962306a36Sopenharmony_ciint ext2_setattr(struct mnt_idmap *idmap, struct dentry *dentry, 164062306a36Sopenharmony_ci struct iattr *iattr) 164162306a36Sopenharmony_ci{ 164262306a36Sopenharmony_ci struct inode *inode = d_inode(dentry); 164362306a36Sopenharmony_ci int error; 164462306a36Sopenharmony_ci 164562306a36Sopenharmony_ci error = setattr_prepare(&nop_mnt_idmap, dentry, iattr); 164662306a36Sopenharmony_ci if (error) 164762306a36Sopenharmony_ci return error; 164862306a36Sopenharmony_ci 164962306a36Sopenharmony_ci if (is_quota_modification(&nop_mnt_idmap, inode, iattr)) { 165062306a36Sopenharmony_ci error = dquot_initialize(inode); 165162306a36Sopenharmony_ci if (error) 165262306a36Sopenharmony_ci return error; 165362306a36Sopenharmony_ci } 165462306a36Sopenharmony_ci if (i_uid_needs_update(&nop_mnt_idmap, iattr, inode) || 165562306a36Sopenharmony_ci i_gid_needs_update(&nop_mnt_idmap, iattr, inode)) { 165662306a36Sopenharmony_ci error = dquot_transfer(&nop_mnt_idmap, inode, iattr); 165762306a36Sopenharmony_ci if (error) 165862306a36Sopenharmony_ci return error; 165962306a36Sopenharmony_ci } 166062306a36Sopenharmony_ci if (iattr->ia_valid & ATTR_SIZE && iattr->ia_size != inode->i_size) { 166162306a36Sopenharmony_ci error = ext2_setsize(inode, iattr->ia_size); 166262306a36Sopenharmony_ci if (error) 166362306a36Sopenharmony_ci return error; 166462306a36Sopenharmony_ci } 166562306a36Sopenharmony_ci setattr_copy(&nop_mnt_idmap, inode, iattr); 166662306a36Sopenharmony_ci if (iattr->ia_valid & ATTR_MODE) 166762306a36Sopenharmony_ci error = posix_acl_chmod(&nop_mnt_idmap, dentry, inode->i_mode); 166862306a36Sopenharmony_ci mark_inode_dirty(inode); 166962306a36Sopenharmony_ci 167062306a36Sopenharmony_ci return error; 167162306a36Sopenharmony_ci} 1672