b24413180f560 (Greg Kroah-Hartman 2017-11-01 15:07:57 +0100 1) // SPDX-License-Identifier: GPL-2.0
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 2) /*
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 3) * linux/fs/ext2/inode.c
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 4) *
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 5) * Copyright (C) 1992, 1993, 1994, 1995
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 6) * Remy Card (card@masi.ibp.fr)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 7) * Laboratoire MASI - Institut Blaise Pascal
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 8) * Universite Pierre et Marie Curie (Paris VI)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 9) *
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 10) * from
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 11) *
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 12) * linux/fs/minix/inode.c
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 13) *
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 14) * Copyright (C) 1991, 1992 Linus Torvalds
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 15) *
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 16) * Goal-directed block allocation by Stephen Tweedie
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 17) * (sct@dcs.ed.ac.uk), 1993, 1998
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 18) * Big-endian to little-endian byte-swapping/bitmaps by
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 19) * David S. Miller (davem@caip.rutgers.edu), 1995
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 20) * 64-bit file support on 64-bit platforms by Jakub Jelinek
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 21) * (jj@sunsite.ms.mff.cuni.cz)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 22) *
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 23) * Assorted race fixes, rewrite of ext2_get_block() by Al Viro, 2000
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 24) */
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 25)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 26) #include <linux/time.h>
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 27) #include <linux/highuid.h>
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 28) #include <linux/pagemap.h>
c94c2acf84dc1 (Matthew Wilcox 2015-09-08 14:58:40 -0700 29) #include <linux/dax.h>
3dc29161070ab (Matthew Wilcox 2016-03-15 11:20:41 -0600 30) #include <linux/blkdev.h>
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 31) #include <linux/quotaops.h>
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 32) #include <linux/writeback.h>
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 33) #include <linux/buffer_head.h>
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 34) #include <linux/mpage.h>
68c9d702bb72f (Josef Bacik 2008-10-03 17:32:43 -0400 35) #include <linux/fiemap.h>
25f4e70291a30 (Christoph Hellwig 2016-09-19 11:30:29 +1000 36) #include <linux/iomap.h>
8d6d0c4da2dbb (Duane Griffin 2008-12-19 20:47:13 +0000 37) #include <linux/namei.h>
e2e40f2c1ed43 (Christoph Hellwig 2015-02-22 08:58:50 -0800 38) #include <linux/uio.h>
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 39) #include "ext2.h"
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 40) #include "acl.h"
c288d2969627b (Jan Kara 2013-03-13 12:57:08 +0100 41) #include "xattr.h"
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 42)
a9185b41a4f84 (Christoph Hellwig 2010-03-05 09:21:37 +0100 43) static int __ext2_write_inode(struct inode *inode, int do_sync);
a9185b41a4f84 (Christoph Hellwig 2010-03-05 09:21:37 +0100 44)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 45) /*
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 46) * Test whether an inode is a fast symlink.
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 47) */
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 48) static inline int ext2_inode_is_fast_symlink(struct inode *inode)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 49) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 50) int ea_blocks = EXT2_I(inode)->i_file_acl ?
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 51) (inode->i_sb->s_blocksize >> 9) : 0;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 52)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 53) return (S_ISLNK(inode->i_mode) &&
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 54) inode->i_blocks - ea_blocks == 0);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 55) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 56)
737f2e93b9724 (Nicholas Piggin 2010-05-27 01:05:37 +1000 57) static void ext2_truncate_blocks(struct inode *inode, loff_t offset);
737f2e93b9724 (Nicholas Piggin 2010-05-27 01:05:37 +1000 58)
737f2e93b9724 (Nicholas Piggin 2010-05-27 01:05:37 +1000 59) static void ext2_write_failed(struct address_space *mapping, loff_t to)
737f2e93b9724 (Nicholas Piggin 2010-05-27 01:05:37 +1000 60) {
737f2e93b9724 (Nicholas Piggin 2010-05-27 01:05:37 +1000 61) struct inode *inode = mapping->host;
737f2e93b9724 (Nicholas Piggin 2010-05-27 01:05:37 +1000 62)
737f2e93b9724 (Nicholas Piggin 2010-05-27 01:05:37 +1000 63) if (to > inode->i_size) {
7caef26767c17 (Kirill A. Shutemov 2013-09-12 15:13:56 -0700 64) truncate_pagecache(inode, inode->i_size);
737f2e93b9724 (Nicholas Piggin 2010-05-27 01:05:37 +1000 65) ext2_truncate_blocks(inode, inode->i_size);
737f2e93b9724 (Nicholas Piggin 2010-05-27 01:05:37 +1000 66) }
737f2e93b9724 (Nicholas Piggin 2010-05-27 01:05:37 +1000 67) }
737f2e93b9724 (Nicholas Piggin 2010-05-27 01:05:37 +1000 68)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 69) /*
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 70) * Called at the last iput() if i_nlink is zero.
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 71) */
72edc4d0873ba (Al Viro 2010-06-04 23:32:28 -0400 72) void ext2_evict_inode(struct inode * inode)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 73) {
72edc4d0873ba (Al Viro 2010-06-04 23:32:28 -0400 74) struct ext2_block_alloc_info *rsv;
72edc4d0873ba (Al Viro 2010-06-04 23:32:28 -0400 75) int want_delete = 0;
72edc4d0873ba (Al Viro 2010-06-04 23:32:28 -0400 76)
72edc4d0873ba (Al Viro 2010-06-04 23:32:28 -0400 77) if (!inode->i_nlink && !is_bad_inode(inode)) {
72edc4d0873ba (Al Viro 2010-06-04 23:32:28 -0400 78) want_delete = 1;
871a293155a24 (Christoph Hellwig 2010-03-03 09:05:07 -0500 79) dquot_initialize(inode);
72edc4d0873ba (Al Viro 2010-06-04 23:32:28 -0400 80) } else {
72edc4d0873ba (Al Viro 2010-06-04 23:32:28 -0400 81) dquot_drop(inode);
72edc4d0873ba (Al Viro 2010-06-04 23:32:28 -0400 82) }
72edc4d0873ba (Al Viro 2010-06-04 23:32:28 -0400 83)
91b0abe36a7b2 (Johannes Weiner 2014-04-03 14:47:49 -0700 84) truncate_inode_pages_final(&inode->i_data);
fef266580e5cf (Mark Fasheh 2005-09-09 13:01:31 -0700 85)
72edc4d0873ba (Al Viro 2010-06-04 23:32:28 -0400 86) if (want_delete) {
1e8b212fe5dce (Jan Kara 2012-06-12 16:20:46 +0200 87) sb_start_intwrite(inode->i_sb);
72edc4d0873ba (Al Viro 2010-06-04 23:32:28 -0400 88) /* set dtime */
fe2c32545bfc2 (Arnd Bergmann 2018-06-20 16:31:40 +0200 89) EXT2_I(inode)->i_dtime = ktime_get_real_seconds();
72edc4d0873ba (Al Viro 2010-06-04 23:32:28 -0400 90) mark_inode_dirty(inode);
72edc4d0873ba (Al Viro 2010-06-04 23:32:28 -0400 91) __ext2_write_inode(inode, inode_needs_sync(inode));
72edc4d0873ba (Al Viro 2010-06-04 23:32:28 -0400 92) /* truncate to 0 */
72edc4d0873ba (Al Viro 2010-06-04 23:32:28 -0400 93) inode->i_size = 0;
72edc4d0873ba (Al Viro 2010-06-04 23:32:28 -0400 94) if (inode->i_blocks)
72edc4d0873ba (Al Viro 2010-06-04 23:32:28 -0400 95) ext2_truncate_blocks(inode, 0);
c288d2969627b (Jan Kara 2013-03-13 12:57:08 +0100 96) ext2_xattr_delete_inode(inode);
72edc4d0873ba (Al Viro 2010-06-04 23:32:28 -0400 97) }
72edc4d0873ba (Al Viro 2010-06-04 23:32:28 -0400 98)
72edc4d0873ba (Al Viro 2010-06-04 23:32:28 -0400 99) invalidate_inode_buffers(inode);
dbd5768f87ff6 (Jan Kara 2012-05-03 14:48:02 +0200 100) clear_inode(inode);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 101)
72edc4d0873ba (Al Viro 2010-06-04 23:32:28 -0400 102) ext2_discard_reservation(inode);
72edc4d0873ba (Al Viro 2010-06-04 23:32:28 -0400 103) rsv = EXT2_I(inode)->i_block_alloc_info;
72edc4d0873ba (Al Viro 2010-06-04 23:32:28 -0400 104) EXT2_I(inode)->i_block_alloc_info = NULL;
72edc4d0873ba (Al Viro 2010-06-04 23:32:28 -0400 105) if (unlikely(rsv))
72edc4d0873ba (Al Viro 2010-06-04 23:32:28 -0400 106) kfree(rsv);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 107)
1e8b212fe5dce (Jan Kara 2012-06-12 16:20:46 +0200 108) if (want_delete) {
72edc4d0873ba (Al Viro 2010-06-04 23:32:28 -0400 109) ext2_free_inode(inode);
1e8b212fe5dce (Jan Kara 2012-06-12 16:20:46 +0200 110) sb_end_intwrite(inode->i_sb);
1e8b212fe5dce (Jan Kara 2012-06-12 16:20:46 +0200 111) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 112) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 113)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 114) typedef struct {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 115) __le32 *p;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 116) __le32 key;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 117) struct buffer_head *bh;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 118) } Indirect;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 119)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 120) static inline void add_chain(Indirect *p, struct buffer_head *bh, __le32 *v)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 121) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 122) p->key = *(p->p = v);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 123) p->bh = bh;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 124) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 125)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 126) static inline int verify_chain(Indirect *from, Indirect *to)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 127) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 128) while (from <= to && from->key == *from->p)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 129) from++;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 130) return (from > to);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 131) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 132)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 133) /**
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 134) * ext2_block_to_path - parse the block number into array of offsets
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 135) * @inode: inode in question (we are only interested in its superblock)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 136) * @i_block: block number to be parsed
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 137) * @offsets: array to store the offsets in
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 138) * @boundary: set this non-zero if the referred-to block is likely to be
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 139) * followed (on disk) by an indirect block.
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 140) * To store the locations of file's data ext2 uses a data structure common
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 141) * for UNIX filesystems - tree of pointers anchored in the inode, with
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 142) * data blocks at leaves and indirect blocks in intermediate nodes.
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 143) * This function translates the block number into path in that tree -
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 144) * return value is the path length and @offsets[n] is the offset of
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 145) * pointer to (n+1)th node in the nth one. If @block is out of range
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 146) * (negative or too large) warning is printed and zero returned.
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 147) *
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 148) * Note: function doesn't find node addresses, so no IO is needed. All
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 149) * we need to know is the capacity of indirect blocks (taken from the
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 150) * inode->i_sb).
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 151) */
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 152)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 153) /*
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 154) * Portability note: the last comparison (check that we fit into triple
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 155) * indirect block) is spelled differently, because otherwise on an
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 156) * architecture with 32-bit longs and 8Kb pages we might get into trouble
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 157) * if our filesystem had 8Kb blocks. We might use long long, but that would
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 158) * kill us on x86. Oh, well, at least the sign propagation does not matter -
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 159) * i_block would have to be negative in the very beginning, so we would not
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 160) * get there at all.
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 161) */
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 162)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 163) static int ext2_block_to_path(struct inode *inode,
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 164) long i_block, int offsets[4], int *boundary)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 165) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 166) int ptrs = EXT2_ADDR_PER_BLOCK(inode->i_sb);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 167) int ptrs_bits = EXT2_ADDR_PER_BLOCK_BITS(inode->i_sb);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 168) const long direct_blocks = EXT2_NDIR_BLOCKS,
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 169) indirect_blocks = ptrs,
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 170) double_blocks = (1 << (ptrs_bits * 2));
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 171) int n = 0;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 172) int final = 0;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 173)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 174) if (i_block < 0) {
2314b07cb47ef (Oleksij Rempel 2009-11-19 19:12:51 +0100 175) ext2_msg(inode->i_sb, KERN_WARNING,
2314b07cb47ef (Oleksij Rempel 2009-11-19 19:12:51 +0100 176) "warning: %s: block < 0", __func__);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 177) } else if (i_block < direct_blocks) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 178) offsets[n++] = i_block;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 179) final = direct_blocks;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 180) } else if ( (i_block -= direct_blocks) < indirect_blocks) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 181) offsets[n++] = EXT2_IND_BLOCK;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 182) offsets[n++] = i_block;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 183) final = ptrs;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 184) } else if ((i_block -= indirect_blocks) < double_blocks) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 185) offsets[n++] = EXT2_DIND_BLOCK;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 186) offsets[n++] = i_block >> ptrs_bits;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 187) offsets[n++] = i_block & (ptrs - 1);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 188) final = ptrs;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 189) } else if (((i_block -= double_blocks) >> (ptrs_bits * 2)) < ptrs) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 190) offsets[n++] = EXT2_TIND_BLOCK;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 191) offsets[n++] = i_block >> (ptrs_bits * 2);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 192) offsets[n++] = (i_block >> ptrs_bits) & (ptrs - 1);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 193) offsets[n++] = i_block & (ptrs - 1);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 194) final = ptrs;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 195) } else {
2314b07cb47ef (Oleksij Rempel 2009-11-19 19:12:51 +0100 196) ext2_msg(inode->i_sb, KERN_WARNING,
2314b07cb47ef (Oleksij Rempel 2009-11-19 19:12:51 +0100 197) "warning: %s: block is too big", __func__);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 198) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 199) if (boundary)
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 200) *boundary = final - 1 - (i_block & (ptrs - 1));
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 201)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 202) return n;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 203) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 204)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 205) /**
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 206) * ext2_get_branch - read the chain of indirect blocks leading to data
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 207) * @inode: inode in question
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 208) * @depth: depth of the chain (1 - direct pointer, etc.)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 209) * @offsets: offsets of pointers in inode/indirect blocks
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 210) * @chain: place to store the result
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 211) * @err: here we store the error value
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 212) *
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 213) * Function fills the array of triples <key, p, bh> and returns %NULL
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 214) * if everything went OK or the pointer to the last filled triple
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 215) * (incomplete one) otherwise. Upon the return chain[i].key contains
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 216) * the number of (i+1)-th block in the chain (as it is stored in memory,
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 217) * i.e. little-endian 32-bit), chain[i].p contains the address of that
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 218) * number (it points into struct inode for i==0 and into the bh->b_data
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 219) * for i>0) and chain[i].bh points to the buffer_head of i-th indirect
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 220) * block for i>0 and NULL for i==0. In other words, it holds the block
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 221) * numbers of the chain, addresses they were taken from (and where we can
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 222) * verify that chain did not change) and buffer_heads hosting these
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 223) * numbers.
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 224) *
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 225) * Function stops when it stumbles upon zero pointer (absent block)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 226) * (pointer to last triple returned, *@err == 0)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 227) * or when it gets an IO error reading an indirect block
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 228) * (ditto, *@err == -EIO)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 229) * or when it notices that chain had been changed while it was reading
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 230) * (ditto, *@err == -EAGAIN)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 231) * or when it reads all @depth-1 indirect blocks successfully and finds
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 232) * the whole chain, all way to the data (returns %NULL, *err == 0).
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 233) */
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 234) static Indirect *ext2_get_branch(struct inode *inode,
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 235) int depth,
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 236) int *offsets,
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 237) Indirect chain[4],
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 238) int *err)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 239) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 240) struct super_block *sb = inode->i_sb;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 241) Indirect *p = chain;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 242) struct buffer_head *bh;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 243)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 244) *err = 0;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 245) /* i_data is not going away, no lock needed */
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 246) add_chain (chain, NULL, EXT2_I(inode)->i_data + *offsets);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 247) if (!p->key)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 248) goto no_block;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 249) while (--depth) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 250) bh = sb_bread(sb, le32_to_cpu(p->key));
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 251) if (!bh)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 252) goto failure;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 253) read_lock(&EXT2_I(inode)->i_meta_lock);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 254) if (!verify_chain(chain, p))
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 255) goto changed;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 256) add_chain(++p, bh, (__le32*)bh->b_data + *++offsets);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 257) read_unlock(&EXT2_I(inode)->i_meta_lock);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 258) if (!p->key)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 259) goto no_block;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 260) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 261) return NULL;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 262)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 263) changed:
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 264) read_unlock(&EXT2_I(inode)->i_meta_lock);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 265) brelse(bh);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 266) *err = -EAGAIN;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 267) goto no_block;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 268) failure:
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 269) *err = -EIO;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 270) no_block:
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 271) return p;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 272) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 273)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 274) /**
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 275) * ext2_find_near - find a place for allocation with sufficient locality
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 276) * @inode: owner
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 277) * @ind: descriptor of indirect block.
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 278) *
1cc8dcf569a3f (Benoit Boissinot 2008-04-21 22:45:55 +0000 279) * This function returns the preferred place for block allocation.
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 280) * It is used when heuristic for sequential allocation fails.
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 281) * Rules are:
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 282) * + if there is a block to the left of our position - allocate near it.
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 283) * + if pointer will live in indirect block - allocate near that block.
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 284) * + if pointer will live in inode - allocate in the same cylinder group.
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 285) *
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 286) * In the latter case we colour the starting block by the callers PID to
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 287) * prevent it from clashing with concurrent allocations for a different inode
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 288) * in the same block group. The PID is used here so that functionally related
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 289) * files will be close-by on-disk.
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 290) *
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 291) * Caller must make sure that @ind is valid and will stay that way.
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 292) */
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 293)
4c8b3125f8dce (Akinobu Mita 2008-04-28 02:16:02 -0700 294) static ext2_fsblk_t ext2_find_near(struct inode *inode, Indirect *ind)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 295) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 296) struct ext2_inode_info *ei = EXT2_I(inode);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 297) __le32 *start = ind->bh ? (__le32 *) ind->bh->b_data : ei->i_data;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 298) __le32 *p;
4c8b3125f8dce (Akinobu Mita 2008-04-28 02:16:02 -0700 299) ext2_fsblk_t bg_start;
4c8b3125f8dce (Akinobu Mita 2008-04-28 02:16:02 -0700 300) ext2_fsblk_t colour;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 301)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 302) /* Try to find previous block */
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 303) for (p = ind->p - 1; p >= start; p--)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 304) if (*p)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 305) return le32_to_cpu(*p);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 306)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 307) /* No such thing, so let's try location of indirect block */
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 308) if (ind->bh)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 309) return ind->bh->b_blocknr;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 310)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 311) /*
25985edcedea6 (Lucas De Marchi 2011-03-30 22:57:33 -0300 312) * It is going to be referred from inode itself? OK, just put it into
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 313) * the same cylinder group then.
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 314) */
24097d12efbb9 (Akinobu Mita 2008-04-28 02:16:01 -0700 315) bg_start = ext2_group_first_block_no(inode->i_sb, ei->i_block_group);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 316) colour = (current->pid % 16) *
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 317) (EXT2_BLOCKS_PER_GROUP(inode->i_sb) / 16);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 318) return bg_start + colour;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 319) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 320)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 321) /**
1cc8dcf569a3f (Benoit Boissinot 2008-04-21 22:45:55 +0000 322) * ext2_find_goal - find a preferred place for allocation.
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 323) * @inode: owner
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 324) * @block: block we want
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 325) * @partial: pointer to the last triple within a chain
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 326) *
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 327) * Returns preferred place for a block (the goal).
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 328) */
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 329)
4c8b3125f8dce (Akinobu Mita 2008-04-28 02:16:02 -0700 330) static inline ext2_fsblk_t ext2_find_goal(struct inode *inode, long block,
4c8b3125f8dce (Akinobu Mita 2008-04-28 02:16:02 -0700 331) Indirect *partial)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 332) {
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 333) struct ext2_block_alloc_info *block_i;
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 334)
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 335) block_i = EXT2_I(inode)->i_block_alloc_info;
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 336)
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 337) /*
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 338) * try the heuristic for sequential allocation,
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 339) * failing that at least try to get decent locality.
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 340) */
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 341) if (block_i && (block == block_i->last_alloc_logical_block + 1)
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 342) && (block_i->last_alloc_physical_block != 0)) {
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 343) return block_i->last_alloc_physical_block + 1;
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 344) }
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 345)
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 346) return ext2_find_near(inode, partial);
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 347) }
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 348)
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 349) /**
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 350) * ext2_blks_to_allocate: Look up the block map and count the number
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 351) * of direct blocks need to be allocated for the given branch.
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 352) *
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 353) * @branch: chain of indirect blocks
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 354) * @k: number of blocks need for indirect blocks
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 355) * @blks: number of data blocks to be mapped.
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 356) * @blocks_to_boundary: the offset in the indirect block
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 357) *
cf1013f441eb9 (Chengguang Xu 2020-07-03 20:44:11 +0800 358) * return the number of direct blocks to allocate.
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 359) */
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 360) static int
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 361) ext2_blks_to_allocate(Indirect * branch, int k, unsigned long blks,
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 362) int blocks_to_boundary)
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 363) {
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 364) unsigned long count = 0;
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 365)
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 366) /*
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 367) * Simple case, [t,d]Indirect block(s) has not allocated yet
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 368) * then it's clear blocks on that path have not allocated
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 369) */
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 370) if (k > 0) {
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 371) /* right now don't hanel cross boundary allocation */
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 372) if (blks < blocks_to_boundary + 1)
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 373) count += blks;
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 374) else
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 375) count += blocks_to_boundary + 1;
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 376) return count;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 377) }
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 378)
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 379) count++;
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 380) while (count < blks && count <= blocks_to_boundary
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 381) && le32_to_cpu(*(branch[0].p + count)) == 0) {
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 382) count++;
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 383) }
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 384) return count;
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 385) }
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 386)
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 387) /**
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 388) * ext2_alloc_blocks: multiple allocate blocks needed for a branch
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 389) * @indirect_blks: the number of blocks need to allocate for indirect
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 390) * blocks
cf1013f441eb9 (Chengguang Xu 2020-07-03 20:44:11 +0800 391) * @blks: the number of blocks need to allocate for direct blocks
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 392) * @new_blocks: on return it will store the new block numbers for
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 393) * the indirect blocks(if needed) and the first direct block,
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 394) */
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 395) static int ext2_alloc_blocks(struct inode *inode,
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 396) ext2_fsblk_t goal, int indirect_blks, int blks,
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 397) ext2_fsblk_t new_blocks[4], int *err)
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 398) {
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 399) int target, i;
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 400) unsigned long count = 0;
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 401) int index = 0;
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 402) ext2_fsblk_t current_block = 0;
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 403) int ret = 0;
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 404)
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 405) /*
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 406) * Here we try to allocate the requested multiple blocks at once,
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 407) * on a best-effort basis.
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 408) * To build a branch, we should allocate blocks for
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 409) * the indirect blocks(if not allocated yet), and at least
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 410) * the first direct block of this branch. That's the
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 411) * minimum number of blocks need to allocate(required)
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 412) */
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 413) target = blks + indirect_blks;
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 414)
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 415) while (1) {
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 416) count = target;
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 417) /* allocating blocks for indirect blocks and direct blocks */
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 418) current_block = ext2_new_blocks(inode,goal,&count,err);
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 419) if (*err)
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 420) goto failed_out;
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 421)
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 422) target -= count;
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 423) /* allocate blocks for indirect blocks */
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 424) while (index < indirect_blks && count) {
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 425) new_blocks[index++] = current_block++;
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 426) count--;
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 427) }
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 428)
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 429) if (count > 0)
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 430) break;
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 431) }
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 432)
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 433) /* save the new block number for the first direct block */
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 434) new_blocks[index] = current_block;
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 435)
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 436) /* total number of blocks allocated for direct blocks */
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 437) ret = count;
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 438) *err = 0;
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 439) return ret;
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 440) failed_out:
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 441) for (i = 0; i <index; i++)
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 442) ext2_free_blocks(inode, new_blocks[i], 1);
addacc7d6f0f0 (Al Viro 2010-07-22 01:19:42 +0400 443) if (index)
addacc7d6f0f0 (Al Viro 2010-07-22 01:19:42 +0400 444) mark_inode_dirty(inode);
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 445) return ret;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 446) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 447)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 448) /**
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 449) * ext2_alloc_branch - allocate and set up a chain of blocks.
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 450) * @inode: owner
1206d028b2c8f (Shuning Zhang 2019-03-06 09:47:35 +0800 451) * @indirect_blks: depth of the chain (number of blocks to allocate)
1206d028b2c8f (Shuning Zhang 2019-03-06 09:47:35 +0800 452) * @blks: number of allocated direct blocks
1206d028b2c8f (Shuning Zhang 2019-03-06 09:47:35 +0800 453) * @goal: preferred place for allocation
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 454) * @offsets: offsets (in the blocks) to store the pointers to next.
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 455) * @branch: place to store the chain in.
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 456) *
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 457) * This function allocates @num blocks, zeroes out all but the last one,
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 458) * links them into chain and (if we are synchronous) writes them to disk.
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 459) * In other words, it prepares a branch that can be spliced onto the
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 460) * inode. It stores the information about that chain in the branch[], in
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 461) * the same format as ext2_get_branch() would do. We are calling it after
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 462) * we had read the existing part of chain and partial points to the last
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 463) * triple of that (one with zero ->key). Upon the exit we have the same
72b43570f3046 (Namhyung Kim 2010-09-15 21:46:02 +0900 464) * picture as after the successful ext2_get_block(), except that in one
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 465) * place chain is disconnected - *branch->p is still zero (we did not
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 466) * set the last link), but branch->key contains the number that should
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 467) * be placed into *branch->p to fill that gap.
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 468) *
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 469) * If allocation fails we free all blocks we've allocated (and forget
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 470) * their buffer_heads) and return the error value the from failed
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 471) * ext2_alloc_block() (normally -ENOSPC). Otherwise we set the chain
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 472) * as described above and return 0.
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 473) */
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 474)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 475) static int ext2_alloc_branch(struct inode *inode,
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 476) int indirect_blks, int *blks, ext2_fsblk_t goal,
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 477) int *offsets, Indirect *branch)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 478) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 479) int blocksize = inode->i_sb->s_blocksize;
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 480) int i, n = 0;
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 481) int err = 0;
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 482) struct buffer_head *bh;
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 483) int num;
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 484) ext2_fsblk_t new_blocks[4];
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 485) ext2_fsblk_t current_block;
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 486)
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 487) num = ext2_alloc_blocks(inode, goal, indirect_blks,
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 488) *blks, new_blocks, &err);
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 489) if (err)
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 490) return err;
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 491)
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 492) branch[0].key = cpu_to_le32(new_blocks[0]);
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 493) /*
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 494) * metadata blocks and data blocks are allocated.
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 495) */
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 496) for (n = 1; n <= indirect_blks; n++) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 497) /*
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 498) * Get buffer_head for parent block, zero it out
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 499) * and set the pointer to new one, then send
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 500) * parent to disk.
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 501) */
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 502) bh = sb_getblk(inode->i_sb, new_blocks[n-1]);
8d8759eb488f9 (Wang Shilong 2013-01-12 01:19:32 -0800 503) if (unlikely(!bh)) {
8d8759eb488f9 (Wang Shilong 2013-01-12 01:19:32 -0800 504) err = -ENOMEM;
8d8759eb488f9 (Wang Shilong 2013-01-12 01:19:32 -0800 505) goto failed;
8d8759eb488f9 (Wang Shilong 2013-01-12 01:19:32 -0800 506) }
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 507) branch[n].bh = bh;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 508) lock_buffer(bh);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 509) memset(bh->b_data, 0, blocksize);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 510) branch[n].p = (__le32 *) bh->b_data + offsets[n];
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 511) branch[n].key = cpu_to_le32(new_blocks[n]);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 512) *branch[n].p = branch[n].key;
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 513) if ( n == indirect_blks) {
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 514) current_block = new_blocks[n];
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 515) /*
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 516) * End of chain, update the last new metablock of
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 517) * the chain to point to the new allocated
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 518) * data blocks numbers
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 519) */
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 520) for (i=1; i < num; i++)
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 521) *(branch[n].p + i) = cpu_to_le32(++current_block);
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 522) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 523) set_buffer_uptodate(bh);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 524) unlock_buffer(bh);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 525) mark_buffer_dirty_inode(bh, inode);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 526) /* We used to sync bh here if IS_SYNC(inode).
a2a735ad666a0 (Jan Kara 2009-08-18 17:54:11 +0200 527) * But we now rely upon generic_write_sync()
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 528) * and b_inode_buffers. But not for directories.
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 529) */
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 530) if (S_ISDIR(inode->i_mode) && IS_DIRSYNC(inode))
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 531) sync_dirty_buffer(bh);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 532) }
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 533) *blks = num;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 534) return err;
8d8759eb488f9 (Wang Shilong 2013-01-12 01:19:32 -0800 535)
8d8759eb488f9 (Wang Shilong 2013-01-12 01:19:32 -0800 536) failed:
8d8759eb488f9 (Wang Shilong 2013-01-12 01:19:32 -0800 537) for (i = 1; i < n; i++)
8d8759eb488f9 (Wang Shilong 2013-01-12 01:19:32 -0800 538) bforget(branch[i].bh);
8d8759eb488f9 (Wang Shilong 2013-01-12 01:19:32 -0800 539) for (i = 0; i < indirect_blks; i++)
8d8759eb488f9 (Wang Shilong 2013-01-12 01:19:32 -0800 540) ext2_free_blocks(inode, new_blocks[i], 1);
8d8759eb488f9 (Wang Shilong 2013-01-12 01:19:32 -0800 541) ext2_free_blocks(inode, new_blocks[i], num);
8d8759eb488f9 (Wang Shilong 2013-01-12 01:19:32 -0800 542) return err;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 543) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 544)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 545) /**
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 546) * ext2_splice_branch - splice the allocated branch onto inode.
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 547) * @inode: owner
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 548) * @block: (logical) number of block we are adding
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 549) * @where: location of missing link
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 550) * @num: number of indirect blocks we are adding
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 551) * @blks: number of direct blocks we are adding
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 552) *
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 553) * This function fills the missing link and does all housekeeping needed in
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 554) * inode (->i_blocks, etc.). In case of success we end up with the full
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 555) * chain to new block and return 0.
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 556) */
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 557) static void ext2_splice_branch(struct inode *inode,
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 558) long block, Indirect *where, int num, int blks)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 559) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 560) int i;
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 561) struct ext2_block_alloc_info *block_i;
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 562) ext2_fsblk_t current_block;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 563)
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 564) block_i = EXT2_I(inode)->i_block_alloc_info;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 565)
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 566) /* XXX LOCKING probably should have i_meta_lock ?*/
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 567) /* That's it */
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 568)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 569) *where->p = where->key;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 570)
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 571) /*
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 572) * Update the host buffer_head or inode to point to more just allocated
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 573) * direct blocks blocks
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 574) */
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 575) if (num == 0 && blks > 1) {
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 576) current_block = le32_to_cpu(where->key) + 1;
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 577) for (i = 1; i < blks; i++)
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 578) *(where->p + i ) = cpu_to_le32(current_block++);
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 579) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 580)
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 581) /*
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 582) * update the most recently allocated logical & physical block
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 583) * in i_block_alloc_info, to assist find the proper goal block for next
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 584) * allocation
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 585) */
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 586) if (block_i) {
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 587) block_i->last_alloc_logical_block = block + blks - 1;
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 588) block_i->last_alloc_physical_block =
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 589) le32_to_cpu(where[num].key) + blks - 1;
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 590) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 591)
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 592) /* We are done with atomic stuff, now do the rest of housekeeping */
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 593)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 594) /* had we spliced it onto indirect block? */
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 595) if (where->bh)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 596) mark_buffer_dirty_inode(where->bh, inode);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 597)
02027d42c3f74 (Deepa Dinamani 2016-09-14 07:48:05 -0700 598) inode->i_ctime = current_time(inode);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 599) mark_inode_dirty(inode);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 600) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 601)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 602) /*
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 603) * Allocation strategy is simple: if we have to allocate something, we will
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 604) * have to go the whole way to leaf. So let's do it before attaching anything
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 605) * to tree, set linkage between the newborn blocks, write them if sync is
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 606) * required, recheck the path, free and repeat if check fails, otherwise
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 607) * set the last missing link (that will protect us from any truncate-generated
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 608) * removals - all blocks on the path are immune now) and possibly force the
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 609) * write on the parent block.
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 610) * That has a nice additional property: no special recovery from the failed
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 611) * allocations is needed - we simply release blocks and do not touch anything
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 612) * reachable from inode.
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 613) *
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 614) * `handle' can be NULL if create == 0.
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 615) *
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 616) * return > 0, # of blocks mapped or allocated.
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 617) * return = 0, if plain lookup failed.
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 618) * return < 0, error case.
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 619) */
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 620) static int ext2_get_blocks(struct inode *inode,
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 621) sector_t iblock, unsigned long maxblocks,
6750ad71986d2 (Christoph Hellwig 2016-09-19 11:28:39 +1000 622) u32 *bno, bool *new, bool *boundary,
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 623) int create)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 624) {
e952813e210b3 (Arnd Bergmann 2016-10-18 00:05:34 +0200 625) int err;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 626) int offsets[4];
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 627) Indirect chain[4];
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 628) Indirect *partial;
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 629) ext2_fsblk_t goal;
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 630) int indirect_blks;
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 631) int blocks_to_boundary = 0;
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 632) int depth;
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 633) struct ext2_inode_info *ei = EXT2_I(inode);
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 634) int count = 0;
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 635) ext2_fsblk_t first_block = 0;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 636)
7ba3ec5749ddb (Jan Kara 2013-11-05 01:15:38 +0100 637) BUG_ON(maxblocks == 0);
7ba3ec5749ddb (Jan Kara 2013-11-05 01:15:38 +0100 638)
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 639) depth = ext2_block_to_path(inode,iblock,offsets,&blocks_to_boundary);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 640)
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 641) if (depth == 0)
e952813e210b3 (Arnd Bergmann 2016-10-18 00:05:34 +0200 642) return -EIO;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 643)
316cb4ef3eb2a (Jan Kara 2009-04-13 14:40:14 -0700 644) partial = ext2_get_branch(inode, depth, offsets, chain, &err);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 645) /* Simplest case - block found, no allocation needed */
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 646) if (!partial) {
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 647) first_block = le32_to_cpu(chain[depth - 1].key);
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 648) count++;
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 649) /*map more blocks*/
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 650) while (count < maxblocks && count <= blocks_to_boundary) {
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 651) ext2_fsblk_t blk;
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 652)
316cb4ef3eb2a (Jan Kara 2009-04-13 14:40:14 -0700 653) if (!verify_chain(chain, chain + depth - 1)) {
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 654) /*
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 655) * Indirect block might be removed by
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 656) * truncate while we were reading it.
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 657) * Handling of that case: forget what we've
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 658) * got now, go to reread.
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 659) */
316cb4ef3eb2a (Jan Kara 2009-04-13 14:40:14 -0700 660) err = -EAGAIN;
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 661) count = 0;
4d9bcaddacf23 (Ernesto A. Fernández 2017-06-23 21:37:21 -0300 662) partial = chain + depth - 1;
316cb4ef3eb2a (Jan Kara 2009-04-13 14:40:14 -0700 663) break;
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 664) }
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 665) blk = le32_to_cpu(*(chain[depth-1].p + count));
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 666) if (blk == first_block + count)
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 667) count++;
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 668) else
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 669) break;
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 670) }
316cb4ef3eb2a (Jan Kara 2009-04-13 14:40:14 -0700 671) if (err != -EAGAIN)
316cb4ef3eb2a (Jan Kara 2009-04-13 14:40:14 -0700 672) goto got_it;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 673) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 674)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 675) /* Next simple case - plain lookup or failed read of indirect block */
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 676) if (!create || err == -EIO)
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 677) goto cleanup;
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 678)
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 679) mutex_lock(&ei->truncate_mutex);
316cb4ef3eb2a (Jan Kara 2009-04-13 14:40:14 -0700 680) /*
316cb4ef3eb2a (Jan Kara 2009-04-13 14:40:14 -0700 681) * If the indirect block is missing while we are reading
72b43570f3046 (Namhyung Kim 2010-09-15 21:46:02 +0900 682) * the chain(ext2_get_branch() returns -EAGAIN err), or
316cb4ef3eb2a (Jan Kara 2009-04-13 14:40:14 -0700 683) * if the chain has been changed after we grab the semaphore,
316cb4ef3eb2a (Jan Kara 2009-04-13 14:40:14 -0700 684) * (either because another process truncated this branch, or
316cb4ef3eb2a (Jan Kara 2009-04-13 14:40:14 -0700 685) * another get_block allocated this branch) re-grab the chain to see if
316cb4ef3eb2a (Jan Kara 2009-04-13 14:40:14 -0700 686) * the request block has been allocated or not.
316cb4ef3eb2a (Jan Kara 2009-04-13 14:40:14 -0700 687) *
316cb4ef3eb2a (Jan Kara 2009-04-13 14:40:14 -0700 688) * Since we already block the truncate/other get_block
316cb4ef3eb2a (Jan Kara 2009-04-13 14:40:14 -0700 689) * at this point, we will have the current copy of the chain when we
316cb4ef3eb2a (Jan Kara 2009-04-13 14:40:14 -0700 690) * splice the branch into the tree.
316cb4ef3eb2a (Jan Kara 2009-04-13 14:40:14 -0700 691) */
316cb4ef3eb2a (Jan Kara 2009-04-13 14:40:14 -0700 692) if (err == -EAGAIN || !verify_chain(chain, partial)) {
316cb4ef3eb2a (Jan Kara 2009-04-13 14:40:14 -0700 693) while (partial > chain) {
316cb4ef3eb2a (Jan Kara 2009-04-13 14:40:14 -0700 694) brelse(partial->bh);
316cb4ef3eb2a (Jan Kara 2009-04-13 14:40:14 -0700 695) partial--;
316cb4ef3eb2a (Jan Kara 2009-04-13 14:40:14 -0700 696) }
316cb4ef3eb2a (Jan Kara 2009-04-13 14:40:14 -0700 697) partial = ext2_get_branch(inode, depth, offsets, chain, &err);
316cb4ef3eb2a (Jan Kara 2009-04-13 14:40:14 -0700 698) if (!partial) {
316cb4ef3eb2a (Jan Kara 2009-04-13 14:40:14 -0700 699) count++;
316cb4ef3eb2a (Jan Kara 2009-04-13 14:40:14 -0700 700) mutex_unlock(&ei->truncate_mutex);
316cb4ef3eb2a (Jan Kara 2009-04-13 14:40:14 -0700 701) goto got_it;
316cb4ef3eb2a (Jan Kara 2009-04-13 14:40:14 -0700 702) }
e705f4b8aa27a (Chengguang Xu 2019-11-05 12:51:00 +0800 703)
e705f4b8aa27a (Chengguang Xu 2019-11-05 12:51:00 +0800 704) if (err) {
e705f4b8aa27a (Chengguang Xu 2019-11-05 12:51:00 +0800 705) mutex_unlock(&ei->truncate_mutex);
e705f4b8aa27a (Chengguang Xu 2019-11-05 12:51:00 +0800 706) goto cleanup;
e705f4b8aa27a (Chengguang Xu 2019-11-05 12:51:00 +0800 707) }
316cb4ef3eb2a (Jan Kara 2009-04-13 14:40:14 -0700 708) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 709)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 710) /*
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 711) * Okay, we need to do block allocation. Lazily initialize the block
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 712) * allocation info here if necessary
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 713) */
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 714) if (S_ISREG(inode->i_mode) && (!ei->i_block_alloc_info))
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 715) ext2_init_block_alloc_info(inode);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 716)
fb01bfdac733f (Akinobu Mita 2008-02-06 01:40:16 -0800 717) goal = ext2_find_goal(inode, iblock, partial);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 718)
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 719) /* the number of blocks need to allocate for [d,t]indirect blocks */
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 720) indirect_blks = (chain + depth) - partial - 1;
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 721) /*
4bc74ba1c7320 (Liu Xiang 2019-01-29 20:39:49 +0800 722) * Next look up the indirect map to count the total number of
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 723) * direct blocks to allocate for this branch.
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 724) */
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 725) count = ext2_blks_to_allocate(partial, indirect_blks,
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 726) maxblocks, blocks_to_boundary);
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 727) /*
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 728) * XXX ???? Block out ext2_truncate while we alter the tree
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 729) */
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 730) err = ext2_alloc_branch(inode, indirect_blks, &count, goal,
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 731) offsets + (partial - chain), partial);
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 732)
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 733) if (err) {
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 734) mutex_unlock(&ei->truncate_mutex);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 735) goto cleanup;
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 736) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 737)
fbbbad4bc2101 (Matthew Wilcox 2015-02-16 15:58:53 -0800 738) if (IS_DAX(inode)) {
225c5161b1183 (Jan Kara 2016-09-27 16:35:45 +0200 739) /*
225c5161b1183 (Jan Kara 2016-09-27 16:35:45 +0200 740) * We must unmap blocks before zeroing so that writeback cannot
225c5161b1183 (Jan Kara 2016-09-27 16:35:45 +0200 741) * overwrite zeros with stale data from block device page cache.
225c5161b1183 (Jan Kara 2016-09-27 16:35:45 +0200 742) */
69a9bea146b18 (Jan Kara 2016-11-04 18:08:14 +0100 743) clean_bdev_aliases(inode->i_sb->s_bdev,
69a9bea146b18 (Jan Kara 2016-11-04 18:08:14 +0100 744) le32_to_cpu(chain[depth-1].key),
69a9bea146b18 (Jan Kara 2016-11-04 18:08:14 +0100 745) count);
6d79125bba55e (Carsten Otte 2005-06-23 22:05:26 -0700 746) /*
289c6aedac981 (Matthew Wilcox 2015-02-16 15:58:59 -0800 747) * block must be initialised before we put it in the tree
289c6aedac981 (Matthew Wilcox 2015-02-16 15:58:59 -0800 748) * so that it's not found by another thread before it's
289c6aedac981 (Matthew Wilcox 2015-02-16 15:58:59 -0800 749) * initialised
6d79125bba55e (Carsten Otte 2005-06-23 22:05:26 -0700 750) */
3dc29161070ab (Matthew Wilcox 2016-03-15 11:20:41 -0600 751) err = sb_issue_zeroout(inode->i_sb,
3dc29161070ab (Matthew Wilcox 2016-03-15 11:20:41 -0600 752) le32_to_cpu(chain[depth-1].key), count,
3dc29161070ab (Matthew Wilcox 2016-03-15 11:20:41 -0600 753) GFP_NOFS);
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 754) if (err) {
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 755) mutex_unlock(&ei->truncate_mutex);
6d79125bba55e (Carsten Otte 2005-06-23 22:05:26 -0700 756) goto cleanup;
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 757) }
6750ad71986d2 (Christoph Hellwig 2016-09-19 11:28:39 +1000 758) }
e568df6b84ff0 (Jan Kara 2016-08-10 16:42:53 +0200 759) *new = true;
6d79125bba55e (Carsten Otte 2005-06-23 22:05:26 -0700 760)
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 761) ext2_splice_branch(inode, iblock, partial, indirect_blks, count);
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 762) mutex_unlock(&ei->truncate_mutex);
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 763) got_it:
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 764) if (count > blocks_to_boundary)
6750ad71986d2 (Christoph Hellwig 2016-09-19 11:28:39 +1000 765) *boundary = true;
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 766) err = count;
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 767) /* Clean up and exit */
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 768) partial = chain + depth - 1; /* the whole chain */
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 769) cleanup:
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 770) while (partial > chain) {
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 771) brelse(partial->bh);
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 772) partial--;
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 773) }
e952813e210b3 (Arnd Bergmann 2016-10-18 00:05:34 +0200 774) if (err > 0)
e952813e210b3 (Arnd Bergmann 2016-10-18 00:05:34 +0200 775) *bno = le32_to_cpu(chain[depth-1].key);
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 776) return err;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 777) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 778)
6750ad71986d2 (Christoph Hellwig 2016-09-19 11:28:39 +1000 779) int ext2_get_block(struct inode *inode, sector_t iblock,
6750ad71986d2 (Christoph Hellwig 2016-09-19 11:28:39 +1000 780) struct buffer_head *bh_result, int create)
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 781) {
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 782) unsigned max_blocks = bh_result->b_size >> inode->i_blkbits;
6750ad71986d2 (Christoph Hellwig 2016-09-19 11:28:39 +1000 783) bool new = false, boundary = false;
6750ad71986d2 (Christoph Hellwig 2016-09-19 11:28:39 +1000 784) u32 bno;
6750ad71986d2 (Christoph Hellwig 2016-09-19 11:28:39 +1000 785) int ret;
6750ad71986d2 (Christoph Hellwig 2016-09-19 11:28:39 +1000 786)
6750ad71986d2 (Christoph Hellwig 2016-09-19 11:28:39 +1000 787) ret = ext2_get_blocks(inode, iblock, max_blocks, &bno, &new, &boundary,
6750ad71986d2 (Christoph Hellwig 2016-09-19 11:28:39 +1000 788) create);
6750ad71986d2 (Christoph Hellwig 2016-09-19 11:28:39 +1000 789) if (ret <= 0)
6750ad71986d2 (Christoph Hellwig 2016-09-19 11:28:39 +1000 790) return ret;
6750ad71986d2 (Christoph Hellwig 2016-09-19 11:28:39 +1000 791)
6750ad71986d2 (Christoph Hellwig 2016-09-19 11:28:39 +1000 792) map_bh(bh_result, inode->i_sb, bno);
6750ad71986d2 (Christoph Hellwig 2016-09-19 11:28:39 +1000 793) bh_result->b_size = (ret << inode->i_blkbits);
6750ad71986d2 (Christoph Hellwig 2016-09-19 11:28:39 +1000 794) if (new)
6750ad71986d2 (Christoph Hellwig 2016-09-19 11:28:39 +1000 795) set_buffer_new(bh_result);
6750ad71986d2 (Christoph Hellwig 2016-09-19 11:28:39 +1000 796) if (boundary)
6750ad71986d2 (Christoph Hellwig 2016-09-19 11:28:39 +1000 797) set_buffer_boundary(bh_result);
6750ad71986d2 (Christoph Hellwig 2016-09-19 11:28:39 +1000 798) return 0;
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 799)
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 800) }
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 801)
25f4e70291a30 (Christoph Hellwig 2016-09-19 11:30:29 +1000 802) #ifdef CONFIG_FS_DAX
25f4e70291a30 (Christoph Hellwig 2016-09-19 11:30:29 +1000 803) static int ext2_iomap_begin(struct inode *inode, loff_t offset, loff_t length,
c039b99792726 (Goldwyn Rodrigues 2019-10-18 16:44:10 -0700 804) unsigned flags, struct iomap *iomap, struct iomap *srcmap)
25f4e70291a30 (Christoph Hellwig 2016-09-19 11:30:29 +1000 805) {
25f4e70291a30 (Christoph Hellwig 2016-09-19 11:30:29 +1000 806) unsigned int blkbits = inode->i_blkbits;
25f4e70291a30 (Christoph Hellwig 2016-09-19 11:30:29 +1000 807) unsigned long first_block = offset >> blkbits;
25f4e70291a30 (Christoph Hellwig 2016-09-19 11:30:29 +1000 808) unsigned long max_blocks = (length + (1 << blkbits) - 1) >> blkbits;
8cf037a8b22f7 (Dan Williams 2017-08-30 09:43:34 -0700 809) struct ext2_sb_info *sbi = EXT2_SB(inode->i_sb);
25f4e70291a30 (Christoph Hellwig 2016-09-19 11:30:29 +1000 810) bool new = false, boundary = false;
25f4e70291a30 (Christoph Hellwig 2016-09-19 11:30:29 +1000 811) u32 bno;
25f4e70291a30 (Christoph Hellwig 2016-09-19 11:30:29 +1000 812) int ret;
25f4e70291a30 (Christoph Hellwig 2016-09-19 11:30:29 +1000 813)
25f4e70291a30 (Christoph Hellwig 2016-09-19 11:30:29 +1000 814) ret = ext2_get_blocks(inode, first_block, max_blocks,
25f4e70291a30 (Christoph Hellwig 2016-09-19 11:30:29 +1000 815) &bno, &new, &boundary, flags & IOMAP_WRITE);
25f4e70291a30 (Christoph Hellwig 2016-09-19 11:30:29 +1000 816) if (ret < 0)
25f4e70291a30 (Christoph Hellwig 2016-09-19 11:30:29 +1000 817) return ret;
25f4e70291a30 (Christoph Hellwig 2016-09-19 11:30:29 +1000 818)
25f4e70291a30 (Christoph Hellwig 2016-09-19 11:30:29 +1000 819) iomap->flags = 0;
8cf037a8b22f7 (Dan Williams 2017-08-30 09:43:34 -0700 820) iomap->bdev = inode->i_sb->s_bdev;
d5bfccdf38d09 (Christoph Hellwig 2016-10-03 09:46:04 +1100 821) iomap->offset = (u64)first_block << blkbits;
8cf037a8b22f7 (Dan Williams 2017-08-30 09:43:34 -0700 822) iomap->dax_dev = sbi->s_daxdev;
25f4e70291a30 (Christoph Hellwig 2016-09-19 11:30:29 +1000 823)
25f4e70291a30 (Christoph Hellwig 2016-09-19 11:30:29 +1000 824) if (ret == 0) {
25f4e70291a30 (Christoph Hellwig 2016-09-19 11:30:29 +1000 825) iomap->type = IOMAP_HOLE;
19fe5f643f89f (Andreas Gruenbacher 2017-10-01 17:55:54 -0400 826) iomap->addr = IOMAP_NULL_ADDR;
25f4e70291a30 (Christoph Hellwig 2016-09-19 11:30:29 +1000 827) iomap->length = 1 << blkbits;
25f4e70291a30 (Christoph Hellwig 2016-09-19 11:30:29 +1000 828) } else {
25f4e70291a30 (Christoph Hellwig 2016-09-19 11:30:29 +1000 829) iomap->type = IOMAP_MAPPED;
19fe5f643f89f (Andreas Gruenbacher 2017-10-01 17:55:54 -0400 830) iomap->addr = (u64)bno << blkbits;
25f4e70291a30 (Christoph Hellwig 2016-09-19 11:30:29 +1000 831) iomap->length = (u64)ret << blkbits;
25f4e70291a30 (Christoph Hellwig 2016-09-19 11:30:29 +1000 832) iomap->flags |= IOMAP_F_MERGED;
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 833) }
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 834)
25f4e70291a30 (Christoph Hellwig 2016-09-19 11:30:29 +1000 835) if (new)
25f4e70291a30 (Christoph Hellwig 2016-09-19 11:30:29 +1000 836) iomap->flags |= IOMAP_F_NEW;
25f4e70291a30 (Christoph Hellwig 2016-09-19 11:30:29 +1000 837) return 0;
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 838) }
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 839)
25f4e70291a30 (Christoph Hellwig 2016-09-19 11:30:29 +1000 840) static int
25f4e70291a30 (Christoph Hellwig 2016-09-19 11:30:29 +1000 841) ext2_iomap_end(struct inode *inode, loff_t offset, loff_t length,
25f4e70291a30 (Christoph Hellwig 2016-09-19 11:30:29 +1000 842) ssize_t written, unsigned flags, struct iomap *iomap)
25f4e70291a30 (Christoph Hellwig 2016-09-19 11:30:29 +1000 843) {
25f4e70291a30 (Christoph Hellwig 2016-09-19 11:30:29 +1000 844) if (iomap->type == IOMAP_MAPPED &&
25f4e70291a30 (Christoph Hellwig 2016-09-19 11:30:29 +1000 845) written < length &&
25f4e70291a30 (Christoph Hellwig 2016-09-19 11:30:29 +1000 846) (flags & IOMAP_WRITE))
25f4e70291a30 (Christoph Hellwig 2016-09-19 11:30:29 +1000 847) ext2_write_failed(inode->i_mapping, offset + length);
25f4e70291a30 (Christoph Hellwig 2016-09-19 11:30:29 +1000 848) return 0;
25f4e70291a30 (Christoph Hellwig 2016-09-19 11:30:29 +1000 849) }
25f4e70291a30 (Christoph Hellwig 2016-09-19 11:30:29 +1000 850)
8ff6daa17b6a6 (Christoph Hellwig 2017-01-27 23:20:26 -0800 851) const struct iomap_ops ext2_iomap_ops = {
25f4e70291a30 (Christoph Hellwig 2016-09-19 11:30:29 +1000 852) .iomap_begin = ext2_iomap_begin,
25f4e70291a30 (Christoph Hellwig 2016-09-19 11:30:29 +1000 853) .iomap_end = ext2_iomap_end,
25f4e70291a30 (Christoph Hellwig 2016-09-19 11:30:29 +1000 854) };
00697eed386d5 (Jan Kara 2016-11-20 20:47:07 -0500 855) #else
00697eed386d5 (Jan Kara 2016-11-20 20:47:07 -0500 856) /* Define empty ops for !CONFIG_FS_DAX case to avoid ugly ifdefs */
8ff6daa17b6a6 (Christoph Hellwig 2017-01-27 23:20:26 -0800 857) const struct iomap_ops ext2_iomap_ops;
25f4e70291a30 (Christoph Hellwig 2016-09-19 11:30:29 +1000 858) #endif /* CONFIG_FS_DAX */
25f4e70291a30 (Christoph Hellwig 2016-09-19 11:30:29 +1000 859)
68c9d702bb72f (Josef Bacik 2008-10-03 17:32:43 -0400 860) int ext2_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
68c9d702bb72f (Josef Bacik 2008-10-03 17:32:43 -0400 861) u64 start, u64 len)
68c9d702bb72f (Josef Bacik 2008-10-03 17:32:43 -0400 862) {
68c9d702bb72f (Josef Bacik 2008-10-03 17:32:43 -0400 863) return generic_block_fiemap(inode, fieinfo, start, len,
68c9d702bb72f (Josef Bacik 2008-10-03 17:32:43 -0400 864) ext2_get_block);
68c9d702bb72f (Josef Bacik 2008-10-03 17:32:43 -0400 865) }
68c9d702bb72f (Josef Bacik 2008-10-03 17:32:43 -0400 866)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 867) static int ext2_writepage(struct page *page, struct writeback_control *wbc)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 868) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 869) return block_write_full_page(page, ext2_get_block, wbc);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 870) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 871)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 872) static int ext2_readpage(struct file *file, struct page *page)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 873) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 874) return mpage_readpage(page, ext2_get_block);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 875) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 876)
d4388340ae0bc (Matthew Wilcox (Oracle) 2020-06-01 21:47:02 -0700 877) static void ext2_readahead(struct readahead_control *rac)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 878) {
d4388340ae0bc (Matthew Wilcox (Oracle) 2020-06-01 21:47:02 -0700 879) mpage_readahead(rac, ext2_get_block);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 880) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 881)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 882) static int
f34fb6eccc962 (Nicholas Piggin 2007-10-16 01:25:04 -0700 883) ext2_write_begin(struct file *file, struct address_space *mapping,
f34fb6eccc962 (Nicholas Piggin 2007-10-16 01:25:04 -0700 884) loff_t pos, unsigned len, unsigned flags,
f34fb6eccc962 (Nicholas Piggin 2007-10-16 01:25:04 -0700 885) struct page **pagep, void **fsdata)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 886) {
737f2e93b9724 (Nicholas Piggin 2010-05-27 01:05:37 +1000 887) int ret;
737f2e93b9724 (Nicholas Piggin 2010-05-27 01:05:37 +1000 888)
155130a4f7848 (Christoph Hellwig 2010-06-04 11:29:58 +0200 889) ret = block_write_begin(mapping, pos, len, flags, pagep,
155130a4f7848 (Christoph Hellwig 2010-06-04 11:29:58 +0200 890) ext2_get_block);
737f2e93b9724 (Nicholas Piggin 2010-05-27 01:05:37 +1000 891) if (ret < 0)
737f2e93b9724 (Nicholas Piggin 2010-05-27 01:05:37 +1000 892) ext2_write_failed(mapping, pos + len);
737f2e93b9724 (Nicholas Piggin 2010-05-27 01:05:37 +1000 893) return ret;
737f2e93b9724 (Nicholas Piggin 2010-05-27 01:05:37 +1000 894) }
737f2e93b9724 (Nicholas Piggin 2010-05-27 01:05:37 +1000 895)
737f2e93b9724 (Nicholas Piggin 2010-05-27 01:05:37 +1000 896) static int ext2_write_end(struct file *file, struct address_space *mapping,
737f2e93b9724 (Nicholas Piggin 2010-05-27 01:05:37 +1000 897) loff_t pos, unsigned len, unsigned copied,
737f2e93b9724 (Nicholas Piggin 2010-05-27 01:05:37 +1000 898) struct page *page, void *fsdata)
737f2e93b9724 (Nicholas Piggin 2010-05-27 01:05:37 +1000 899) {
737f2e93b9724 (Nicholas Piggin 2010-05-27 01:05:37 +1000 900) int ret;
737f2e93b9724 (Nicholas Piggin 2010-05-27 01:05:37 +1000 901)
737f2e93b9724 (Nicholas Piggin 2010-05-27 01:05:37 +1000 902) ret = generic_write_end(file, mapping, pos, len, copied, page, fsdata);
737f2e93b9724 (Nicholas Piggin 2010-05-27 01:05:37 +1000 903) if (ret < len)
737f2e93b9724 (Nicholas Piggin 2010-05-27 01:05:37 +1000 904) ext2_write_failed(mapping, pos + len);
737f2e93b9724 (Nicholas Piggin 2010-05-27 01:05:37 +1000 905) return ret;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 906) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 907)
03158cd7eb337 (Nicholas Piggin 2007-10-16 01:25:25 -0700 908) static int
03158cd7eb337 (Nicholas Piggin 2007-10-16 01:25:25 -0700 909) ext2_nobh_write_begin(struct file *file, struct address_space *mapping,
03158cd7eb337 (Nicholas Piggin 2007-10-16 01:25:25 -0700 910) loff_t pos, unsigned len, unsigned flags,
03158cd7eb337 (Nicholas Piggin 2007-10-16 01:25:25 -0700 911) struct page **pagep, void **fsdata)
03158cd7eb337 (Nicholas Piggin 2007-10-16 01:25:25 -0700 912) {
737f2e93b9724 (Nicholas Piggin 2010-05-27 01:05:37 +1000 913) int ret;
737f2e93b9724 (Nicholas Piggin 2010-05-27 01:05:37 +1000 914)
ea0f04e59543b (Christoph Hellwig 2010-06-04 11:29:54 +0200 915) ret = nobh_write_begin(mapping, pos, len, flags, pagep, fsdata,
ea0f04e59543b (Christoph Hellwig 2010-06-04 11:29:54 +0200 916) ext2_get_block);
737f2e93b9724 (Nicholas Piggin 2010-05-27 01:05:37 +1000 917) if (ret < 0)
737f2e93b9724 (Nicholas Piggin 2010-05-27 01:05:37 +1000 918) ext2_write_failed(mapping, pos + len);
737f2e93b9724 (Nicholas Piggin 2010-05-27 01:05:37 +1000 919) return ret;
03158cd7eb337 (Nicholas Piggin 2007-10-16 01:25:25 -0700 920) }
03158cd7eb337 (Nicholas Piggin 2007-10-16 01:25:25 -0700 921)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 922) static int ext2_nobh_writepage(struct page *page,
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 923) struct writeback_control *wbc)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 924) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 925) return nobh_writepage(page, ext2_get_block, wbc);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 926) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 927)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 928) static sector_t ext2_bmap(struct address_space *mapping, sector_t block)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 929) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 930) return generic_block_bmap(mapping,block,ext2_get_block);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 931) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 932)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 933) static ssize_t
c8b8e32d700fe (Christoph Hellwig 2016-04-07 08:51:58 -0700 934) ext2_direct_IO(struct kiocb *iocb, struct iov_iter *iter)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 935) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 936) struct file *file = iocb->ki_filp;
737f2e93b9724 (Nicholas Piggin 2010-05-27 01:05:37 +1000 937) struct address_space *mapping = file->f_mapping;
737f2e93b9724 (Nicholas Piggin 2010-05-27 01:05:37 +1000 938) struct inode *inode = mapping->host;
a6cbcd4a4a85e (Al Viro 2014-03-04 22:38:00 -0500 939) size_t count = iov_iter_count(iter);
c8b8e32d700fe (Christoph Hellwig 2016-04-07 08:51:58 -0700 940) loff_t offset = iocb->ki_pos;
737f2e93b9724 (Nicholas Piggin 2010-05-27 01:05:37 +1000 941) ssize_t ret;
737f2e93b9724 (Nicholas Piggin 2010-05-27 01:05:37 +1000 942)
25f4e70291a30 (Christoph Hellwig 2016-09-19 11:30:29 +1000 943) ret = blockdev_direct_IO(iocb, inode, iter, ext2_get_block);
6f67376318abe (Omar Sandoval 2015-03-16 04:33:52 -0700 944) if (ret < 0 && iov_iter_rw(iter) == WRITE)
a6cbcd4a4a85e (Al Viro 2014-03-04 22:38:00 -0500 945) ext2_write_failed(mapping, offset + count);
737f2e93b9724 (Nicholas Piggin 2010-05-27 01:05:37 +1000 946) return ret;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 947) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 948)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 949) static int
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 950) ext2_writepages(struct address_space *mapping, struct writeback_control *wbc)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 951) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 952) return mpage_writepages(mapping, wbc, ext2_get_block);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 953) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 954)
fb094c90748fb (Dan Williams 2017-12-21 12:25:11 -0800 955) static int
fb094c90748fb (Dan Williams 2017-12-21 12:25:11 -0800 956) ext2_dax_writepages(struct address_space *mapping, struct writeback_control *wbc)
fb094c90748fb (Dan Williams 2017-12-21 12:25:11 -0800 957) {
3f666c56c6b8c (Vivek Goyal 2020-01-03 13:33:07 -0500 958) struct ext2_sb_info *sbi = EXT2_SB(mapping->host->i_sb);
3f666c56c6b8c (Vivek Goyal 2020-01-03 13:33:07 -0500 959)
3f666c56c6b8c (Vivek Goyal 2020-01-03 13:33:07 -0500 960) return dax_writeback_mapping_range(mapping, sbi->s_daxdev, wbc);
fb094c90748fb (Dan Williams 2017-12-21 12:25:11 -0800 961) }
fb094c90748fb (Dan Williams 2017-12-21 12:25:11 -0800 962)
f5e54d6e53a20 (Christoph Hellwig 2006-06-28 04:26:44 -0700 963) const struct address_space_operations ext2_aops = {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 964) .readpage = ext2_readpage,
d4388340ae0bc (Matthew Wilcox (Oracle) 2020-06-01 21:47:02 -0700 965) .readahead = ext2_readahead,
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 966) .writepage = ext2_writepage,
f34fb6eccc962 (Nicholas Piggin 2007-10-16 01:25:04 -0700 967) .write_begin = ext2_write_begin,
737f2e93b9724 (Nicholas Piggin 2010-05-27 01:05:37 +1000 968) .write_end = ext2_write_end,
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 969) .bmap = ext2_bmap,
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 970) .direct_IO = ext2_direct_IO,
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 971) .writepages = ext2_writepages,
e965f9630c651 (Christoph Lameter 2006-02-01 03:05:41 -0800 972) .migratepage = buffer_migrate_page,
8ab22b9abb5c5 (Hisashi Hifumi 2008-07-28 15:46:36 -0700 973) .is_partially_uptodate = block_is_partially_uptodate,
aa261f549d765 (Andi Kleen 2009-09-16 11:50:16 +0200 974) .error_remove_page = generic_error_remove_page,
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 975) };
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 976)
f5e54d6e53a20 (Christoph Hellwig 2006-06-28 04:26:44 -0700 977) const struct address_space_operations ext2_nobh_aops = {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 978) .readpage = ext2_readpage,
d4388340ae0bc (Matthew Wilcox (Oracle) 2020-06-01 21:47:02 -0700 979) .readahead = ext2_readahead,
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 980) .writepage = ext2_nobh_writepage,
03158cd7eb337 (Nicholas Piggin 2007-10-16 01:25:25 -0700 981) .write_begin = ext2_nobh_write_begin,
03158cd7eb337 (Nicholas Piggin 2007-10-16 01:25:25 -0700 982) .write_end = nobh_write_end,
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 983) .bmap = ext2_bmap,
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 984) .direct_IO = ext2_direct_IO,
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 985) .writepages = ext2_writepages,
e965f9630c651 (Christoph Lameter 2006-02-01 03:05:41 -0800 986) .migratepage = buffer_migrate_page,
aa261f549d765 (Andi Kleen 2009-09-16 11:50:16 +0200 987) .error_remove_page = generic_error_remove_page,
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 988) };
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 989)
fb094c90748fb (Dan Williams 2017-12-21 12:25:11 -0800 990) static const struct address_space_operations ext2_dax_aops = {
fb094c90748fb (Dan Williams 2017-12-21 12:25:11 -0800 991) .writepages = ext2_dax_writepages,
fb094c90748fb (Dan Williams 2017-12-21 12:25:11 -0800 992) .direct_IO = noop_direct_IO,
fb094c90748fb (Dan Williams 2017-12-21 12:25:11 -0800 993) .set_page_dirty = noop_set_page_dirty,
fb094c90748fb (Dan Williams 2017-12-21 12:25:11 -0800 994) .invalidatepage = noop_invalidatepage,
fb094c90748fb (Dan Williams 2017-12-21 12:25:11 -0800 995) };
fb094c90748fb (Dan Williams 2017-12-21 12:25:11 -0800 996)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 997) /*
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 998) * Probably it should be a library function... search for first non-zero word
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 999) * or memcmp with zero_page, whatever is better for particular architecture.
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1000) * Linus?
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1001) */
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1002) static inline int all_zeroes(__le32 *p, __le32 *q)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1003) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1004) while (p < q)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1005) if (*p++)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1006) return 0;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1007) return 1;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1008) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1009)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1010) /**
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1011) * ext2_find_shared - find the indirect blocks for partial truncation.
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1012) * @inode: inode in question
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1013) * @depth: depth of the affected branch
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1014) * @offsets: offsets of pointers in that branch (see ext2_block_to_path)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1015) * @chain: place to store the pointers to partial indirect blocks
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1016) * @top: place to the (detached) top of branch
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1017) *
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1018) * This is a helper function used by ext2_truncate().
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1019) *
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1020) * When we do truncate() we may have to clean the ends of several indirect
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1021) * blocks but leave the blocks themselves alive. Block is partially
25985edcedea6 (Lucas De Marchi 2011-03-30 22:57:33 -0300 1022) * truncated if some data below the new i_size is referred from it (and
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1023) * it is on the path to the first completely truncated data block, indeed).
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1024) * We have to free the top of that path along with everything to the right
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1025) * of the path. Since no allocation past the truncation point is possible
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1026) * until ext2_truncate() finishes, we may safely do the latter, but top
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1027) * of branch may require special attention - pageout below the truncation
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1028) * point might try to populate it.
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1029) *
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1030) * We atomically detach the top of branch from the tree, store the block
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1031) * number of its root in *@top, pointers to buffer_heads of partially
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1032) * truncated blocks - in @chain[].bh and pointers to their last elements
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1033) * that should not be removed - in @chain[].p. Return value is the pointer
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1034) * to last filled element of @chain.
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1035) *
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1036) * The work left to caller to do the actual freeing of subtrees:
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1037) * a) free the subtree starting from *@top
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1038) * b) free the subtrees whose roots are stored in
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1039) * (@chain[i].p+1 .. end of @chain[i].bh->b_data)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1040) * c) free the subtrees growing from the inode past the @chain[0].p
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1041) * (no partially truncated stuff there).
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1042) */
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1043)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1044) static Indirect *ext2_find_shared(struct inode *inode,
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1045) int depth,
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1046) int offsets[4],
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1047) Indirect chain[4],
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1048) __le32 *top)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1049) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1050) Indirect *partial, *p;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1051) int k, err;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1052)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1053) *top = 0;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1054) for (k = depth; k > 1 && !offsets[k-1]; k--)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1055) ;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1056) partial = ext2_get_branch(inode, k, offsets, chain, &err);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1057) if (!partial)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1058) partial = chain + k-1;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1059) /*
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1060) * If the branch acquired continuation since we've looked at it -
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1061) * fine, it should all survive and (new) top doesn't belong to us.
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1062) */
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1063) write_lock(&EXT2_I(inode)->i_meta_lock);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1064) if (!partial->key && *partial->p) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1065) write_unlock(&EXT2_I(inode)->i_meta_lock);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1066) goto no_top;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1067) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1068) for (p=partial; p>chain && all_zeroes((__le32*)p->bh->b_data,p->p); p--)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1069) ;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1070) /*
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1071) * OK, we've found the last block that must survive. The rest of our
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1072) * branch should be detached before unlocking. However, if that rest
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1073) * of branch is all ours and does not grow immediately from the inode
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1074) * it's easier to cheat and just decrement partial->p.
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1075) */
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1076) if (p == chain + k - 1 && p > chain) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1077) p->p--;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1078) } else {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1079) *top = *p->p;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1080) *p->p = 0;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1081) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1082) write_unlock(&EXT2_I(inode)->i_meta_lock);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1083)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1084) while(partial > p)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1085) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1086) brelse(partial->bh);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1087) partial--;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1088) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1089) no_top:
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1090) return partial;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1091) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1092)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1093) /**
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1094) * ext2_free_data - free a list of data blocks
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1095) * @inode: inode we are dealing with
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1096) * @p: array of block numbers
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1097) * @q: points immediately past the end of array
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1098) *
25985edcedea6 (Lucas De Marchi 2011-03-30 22:57:33 -0300 1099) * We are freeing all blocks referred from that array (numbers are
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1100) * stored as little-endian 32-bit) and updating @inode->i_blocks
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1101) * appropriately.
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1102) */
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1103) static inline void ext2_free_data(struct inode *inode, __le32 *p, __le32 *q)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1104) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1105) unsigned long block_to_free = 0, count = 0;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1106) unsigned long nr;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1107)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1108) for ( ; p < q ; p++) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1109) nr = le32_to_cpu(*p);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1110) if (nr) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1111) *p = 0;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1112) /* accumulate blocks to free if they're contiguous */
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1113) if (count == 0)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1114) goto free_this;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1115) else if (block_to_free == nr - count)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1116) count++;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1117) else {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1118) ext2_free_blocks (inode, block_to_free, count);
addacc7d6f0f0 (Al Viro 2010-07-22 01:19:42 +0400 1119) mark_inode_dirty(inode);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1120) free_this:
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1121) block_to_free = nr;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1122) count = 1;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1123) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1124) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1125) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1126) if (count > 0) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1127) ext2_free_blocks (inode, block_to_free, count);
addacc7d6f0f0 (Al Viro 2010-07-22 01:19:42 +0400 1128) mark_inode_dirty(inode);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1129) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1130) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1131)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1132) /**
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1133) * ext2_free_branches - free an array of branches
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1134) * @inode: inode we are dealing with
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1135) * @p: array of block numbers
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1136) * @q: pointer immediately past the end of array
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1137) * @depth: depth of the branches to free
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1138) *
25985edcedea6 (Lucas De Marchi 2011-03-30 22:57:33 -0300 1139) * We are freeing all blocks referred from these branches (numbers are
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1140) * stored as little-endian 32-bit) and updating @inode->i_blocks
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1141) * appropriately.
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1142) */
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1143) static void ext2_free_branches(struct inode *inode, __le32 *p, __le32 *q, int depth)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1144) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1145) struct buffer_head * bh;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1146) unsigned long nr;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1147)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1148) if (depth--) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1149) int addr_per_block = EXT2_ADDR_PER_BLOCK(inode->i_sb);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1150) for ( ; p < q ; p++) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1151) nr = le32_to_cpu(*p);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1152) if (!nr)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1153) continue;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1154) *p = 0;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1155) bh = sb_bread(inode->i_sb, nr);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1156) /*
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1157) * A read failure? Report error and clear slot
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1158) * (should be rare).
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1159) */
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1160) if (!bh) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1161) ext2_error(inode->i_sb, "ext2_free_branches",
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1162) "Read failure, inode=%ld, block=%ld",
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1163) inode->i_ino, nr);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1164) continue;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1165) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1166) ext2_free_branches(inode,
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1167) (__le32*)bh->b_data,
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1168) (__le32*)bh->b_data + addr_per_block,
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1169) depth);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1170) bforget(bh);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1171) ext2_free_blocks(inode, nr, 1);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1172) mark_inode_dirty(inode);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1173) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1174) } else
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1175) ext2_free_data(inode, p, q);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1176) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1177)
5726b27b09cc9 (Ross Zwisler 2015-10-13 16:25:37 -0600 1178) /* dax_sem must be held when calling this function */
737f2e93b9724 (Nicholas Piggin 2010-05-27 01:05:37 +1000 1179) static void __ext2_truncate_blocks(struct inode *inode, loff_t offset)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1180) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1181) __le32 *i_data = EXT2_I(inode)->i_data;
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 1182) struct ext2_inode_info *ei = EXT2_I(inode);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1183) int addr_per_block = EXT2_ADDR_PER_BLOCK(inode->i_sb);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1184) int offsets[4];
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1185) Indirect chain[4];
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1186) Indirect *partial;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1187) __le32 nr = 0;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1188) int n;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1189) long iblock;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1190) unsigned blocksize;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1191) blocksize = inode->i_sb->s_blocksize;
737f2e93b9724 (Nicholas Piggin 2010-05-27 01:05:37 +1000 1192) iblock = (offset + blocksize-1) >> EXT2_BLOCK_SIZE_BITS(inode->i_sb);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1193)
5726b27b09cc9 (Ross Zwisler 2015-10-13 16:25:37 -0600 1194) #ifdef CONFIG_FS_DAX
5726b27b09cc9 (Ross Zwisler 2015-10-13 16:25:37 -0600 1195) WARN_ON(!rwsem_is_locked(&ei->dax_sem));
5726b27b09cc9 (Ross Zwisler 2015-10-13 16:25:37 -0600 1196) #endif
5726b27b09cc9 (Ross Zwisler 2015-10-13 16:25:37 -0600 1197)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1198) n = ext2_block_to_path(inode, iblock, offsets, NULL);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1199) if (n == 0)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1200) return;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1201)
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 1202) /*
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 1203) * From here we block out all ext2_get_block() callers who want to
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 1204) * modify the block allocation tree.
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 1205) */
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 1206) mutex_lock(&ei->truncate_mutex);
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 1207)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1208) if (n == 1) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1209) ext2_free_data(inode, i_data+offsets[0],
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1210) i_data + EXT2_NDIR_BLOCKS);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1211) goto do_indirects;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1212) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1213)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1214) partial = ext2_find_shared(inode, n, offsets, chain, &nr);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1215) /* Kill the top of shared branch (already detached) */
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1216) if (nr) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1217) if (partial == chain)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1218) mark_inode_dirty(inode);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1219) else
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1220) mark_buffer_dirty_inode(partial->bh, inode);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1221) ext2_free_branches(inode, &nr, &nr+1, (chain+n-1) - partial);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1222) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1223) /* Clear the ends of indirect blocks on the shared branch */
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1224) while (partial > chain) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1225) ext2_free_branches(inode,
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1226) partial->p + 1,
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1227) (__le32*)partial->bh->b_data+addr_per_block,
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1228) (chain+n-1) - partial);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1229) mark_buffer_dirty_inode(partial->bh, inode);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1230) brelse (partial->bh);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1231) partial--;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1232) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1233) do_indirects:
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1234) /* Kill the remaining (whole) subtrees */
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1235) switch (offsets[0]) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1236) default:
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1237) nr = i_data[EXT2_IND_BLOCK];
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1238) if (nr) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1239) i_data[EXT2_IND_BLOCK] = 0;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1240) mark_inode_dirty(inode);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1241) ext2_free_branches(inode, &nr, &nr+1, 1);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1242) }
df561f6688fef (Gustavo A. R. Silva 2020-08-23 17:36:59 -0500 1243) fallthrough;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1244) case EXT2_IND_BLOCK:
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1245) nr = i_data[EXT2_DIND_BLOCK];
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1246) if (nr) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1247) i_data[EXT2_DIND_BLOCK] = 0;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1248) mark_inode_dirty(inode);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1249) ext2_free_branches(inode, &nr, &nr+1, 2);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1250) }
df561f6688fef (Gustavo A. R. Silva 2020-08-23 17:36:59 -0500 1251) fallthrough;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1252) case EXT2_DIND_BLOCK:
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1253) nr = i_data[EXT2_TIND_BLOCK];
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1254) if (nr) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1255) i_data[EXT2_TIND_BLOCK] = 0;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1256) mark_inode_dirty(inode);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1257) ext2_free_branches(inode, &nr, &nr+1, 3);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1258) }
8fca3c8a34515 (Gustavo A. R. Silva 2020-11-20 12:28:25 -0600 1259) break;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1260) case EXT2_TIND_BLOCK:
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1261) ;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1262) }
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 1263)
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 1264) ext2_discard_reservation(inode);
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 1265)
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 1266) mutex_unlock(&ei->truncate_mutex);
737f2e93b9724 (Nicholas Piggin 2010-05-27 01:05:37 +1000 1267) }
737f2e93b9724 (Nicholas Piggin 2010-05-27 01:05:37 +1000 1268)
737f2e93b9724 (Nicholas Piggin 2010-05-27 01:05:37 +1000 1269) static void ext2_truncate_blocks(struct inode *inode, loff_t offset)
737f2e93b9724 (Nicholas Piggin 2010-05-27 01:05:37 +1000 1270) {
737f2e93b9724 (Nicholas Piggin 2010-05-27 01:05:37 +1000 1271) if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
737f2e93b9724 (Nicholas Piggin 2010-05-27 01:05:37 +1000 1272) S_ISLNK(inode->i_mode)))
737f2e93b9724 (Nicholas Piggin 2010-05-27 01:05:37 +1000 1273) return;
737f2e93b9724 (Nicholas Piggin 2010-05-27 01:05:37 +1000 1274) if (ext2_inode_is_fast_symlink(inode))
737f2e93b9724 (Nicholas Piggin 2010-05-27 01:05:37 +1000 1275) return;
5726b27b09cc9 (Ross Zwisler 2015-10-13 16:25:37 -0600 1276)
5726b27b09cc9 (Ross Zwisler 2015-10-13 16:25:37 -0600 1277) dax_sem_down_write(EXT2_I(inode));
737f2e93b9724 (Nicholas Piggin 2010-05-27 01:05:37 +1000 1278) __ext2_truncate_blocks(inode, offset);
5726b27b09cc9 (Ross Zwisler 2015-10-13 16:25:37 -0600 1279) dax_sem_up_write(EXT2_I(inode));
737f2e93b9724 (Nicholas Piggin 2010-05-27 01:05:37 +1000 1280) }
737f2e93b9724 (Nicholas Piggin 2010-05-27 01:05:37 +1000 1281)
2c27c65ed0696 (Christoph Hellwig 2010-06-04 11:30:04 +0200 1282) static int ext2_setsize(struct inode *inode, loff_t newsize)
737f2e93b9724 (Nicholas Piggin 2010-05-27 01:05:37 +1000 1283) {
737f2e93b9724 (Nicholas Piggin 2010-05-27 01:05:37 +1000 1284) int error;
737f2e93b9724 (Nicholas Piggin 2010-05-27 01:05:37 +1000 1285)
737f2e93b9724 (Nicholas Piggin 2010-05-27 01:05:37 +1000 1286) if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
737f2e93b9724 (Nicholas Piggin 2010-05-27 01:05:37 +1000 1287) S_ISLNK(inode->i_mode)))
737f2e93b9724 (Nicholas Piggin 2010-05-27 01:05:37 +1000 1288) return -EINVAL;
737f2e93b9724 (Nicholas Piggin 2010-05-27 01:05:37 +1000 1289) if (ext2_inode_is_fast_symlink(inode))
737f2e93b9724 (Nicholas Piggin 2010-05-27 01:05:37 +1000 1290) return -EINVAL;
737f2e93b9724 (Nicholas Piggin 2010-05-27 01:05:37 +1000 1291) if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
737f2e93b9724 (Nicholas Piggin 2010-05-27 01:05:37 +1000 1292) return -EPERM;
737f2e93b9724 (Nicholas Piggin 2010-05-27 01:05:37 +1000 1293)
562c72aa57c36 (Christoph Hellwig 2011-06-24 14:29:45 -0400 1294) inode_dio_wait(inode);
562c72aa57c36 (Christoph Hellwig 2011-06-24 14:29:45 -0400 1295)
00697eed386d5 (Jan Kara 2016-11-20 20:47:07 -0500 1296) if (IS_DAX(inode)) {
00697eed386d5 (Jan Kara 2016-11-20 20:47:07 -0500 1297) error = iomap_zero_range(inode, newsize,
00697eed386d5 (Jan Kara 2016-11-20 20:47:07 -0500 1298) PAGE_ALIGN(newsize) - newsize, NULL,
00697eed386d5 (Jan Kara 2016-11-20 20:47:07 -0500 1299) &ext2_iomap_ops);
00697eed386d5 (Jan Kara 2016-11-20 20:47:07 -0500 1300) } else if (test_opt(inode->i_sb, NOBH))
737f2e93b9724 (Nicholas Piggin 2010-05-27 01:05:37 +1000 1301) error = nobh_truncate_page(inode->i_mapping,
737f2e93b9724 (Nicholas Piggin 2010-05-27 01:05:37 +1000 1302) newsize, ext2_get_block);
737f2e93b9724 (Nicholas Piggin 2010-05-27 01:05:37 +1000 1303) else
737f2e93b9724 (Nicholas Piggin 2010-05-27 01:05:37 +1000 1304) error = block_truncate_page(inode->i_mapping,
737f2e93b9724 (Nicholas Piggin 2010-05-27 01:05:37 +1000 1305) newsize, ext2_get_block);
737f2e93b9724 (Nicholas Piggin 2010-05-27 01:05:37 +1000 1306) if (error)
737f2e93b9724 (Nicholas Piggin 2010-05-27 01:05:37 +1000 1307) return error;
737f2e93b9724 (Nicholas Piggin 2010-05-27 01:05:37 +1000 1308)
5726b27b09cc9 (Ross Zwisler 2015-10-13 16:25:37 -0600 1309) dax_sem_down_write(EXT2_I(inode));
2c27c65ed0696 (Christoph Hellwig 2010-06-04 11:30:04 +0200 1310) truncate_setsize(inode, newsize);
737f2e93b9724 (Nicholas Piggin 2010-05-27 01:05:37 +1000 1311) __ext2_truncate_blocks(inode, newsize);
5726b27b09cc9 (Ross Zwisler 2015-10-13 16:25:37 -0600 1312) dax_sem_up_write(EXT2_I(inode));
737f2e93b9724 (Nicholas Piggin 2010-05-27 01:05:37 +1000 1313)
02027d42c3f74 (Deepa Dinamani 2016-09-14 07:48:05 -0700 1314) inode->i_mtime = inode->i_ctime = current_time(inode);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1315) if (inode_needs_sync(inode)) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1316) sync_mapping_buffers(inode->i_mapping);
c37650161a53c (Christoph Hellwig 2010-10-06 10:48:20 +0200 1317) sync_inode_metadata(inode, 1);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1318) } else {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1319) mark_inode_dirty(inode);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1320) }
737f2e93b9724 (Nicholas Piggin 2010-05-27 01:05:37 +1000 1321)
737f2e93b9724 (Nicholas Piggin 2010-05-27 01:05:37 +1000 1322) return 0;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1323) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1324)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1325) static struct ext2_inode *ext2_get_inode(struct super_block *sb, ino_t ino,
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1326) struct buffer_head **p)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1327) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1328) struct buffer_head * bh;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1329) unsigned long block_group;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1330) unsigned long block;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1331) unsigned long offset;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1332) struct ext2_group_desc * gdp;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1333)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1334) *p = NULL;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1335) if ((ino != EXT2_ROOT_INO && ino < EXT2_FIRST_INO(sb)) ||
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1336) ino > le32_to_cpu(EXT2_SB(sb)->s_es->s_inodes_count))
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1337) goto Einval;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1338)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1339) block_group = (ino - 1) / EXT2_INODES_PER_GROUP(sb);
ef2fb67989d30 (Eric Sandeen 2007-10-16 23:26:30 -0700 1340) gdp = ext2_get_group_desc(sb, block_group, NULL);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1341) if (!gdp)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1342) goto Egdp;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1343) /*
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1344) * Figure out the offset within the block group inode table
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1345) */
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1346) offset = ((ino - 1) % EXT2_INODES_PER_GROUP(sb)) * EXT2_INODE_SIZE(sb);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1347) block = le32_to_cpu(gdp->bg_inode_table) +
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1348) (offset >> EXT2_BLOCK_SIZE_BITS(sb));
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1349) if (!(bh = sb_bread(sb, block)))
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1350) goto Eio;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1351)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1352) *p = bh;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1353) offset &= (EXT2_BLOCK_SIZE(sb) - 1);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1354) return (struct ext2_inode *) (bh->b_data + offset);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1355)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1356) Einval:
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1357) ext2_error(sb, "ext2_get_inode", "bad inode number: %lu",
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1358) (unsigned long) ino);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1359) return ERR_PTR(-EINVAL);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1360) Eio:
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1361) ext2_error(sb, "ext2_get_inode",
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1362) "unable to read inode block - inode=%lu, block=%lu",
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1363) (unsigned long) ino, block);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1364) Egdp:
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1365) return ERR_PTR(-EIO);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1366) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1367)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1368) void ext2_set_inode_flags(struct inode *inode)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1369) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1370) unsigned int flags = EXT2_I(inode)->i_flags;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1371)
fbbbad4bc2101 (Matthew Wilcox 2015-02-16 15:58:53 -0800 1372) inode->i_flags &= ~(S_SYNC | S_APPEND | S_IMMUTABLE | S_NOATIME |
fbbbad4bc2101 (Matthew Wilcox 2015-02-16 15:58:53 -0800 1373) S_DIRSYNC | S_DAX);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1374) if (flags & EXT2_SYNC_FL)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1375) inode->i_flags |= S_SYNC;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1376) if (flags & EXT2_APPEND_FL)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1377) inode->i_flags |= S_APPEND;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1378) if (flags & EXT2_IMMUTABLE_FL)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1379) inode->i_flags |= S_IMMUTABLE;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1380) if (flags & EXT2_NOATIME_FL)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1381) inode->i_flags |= S_NOATIME;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1382) if (flags & EXT2_DIRSYNC_FL)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1383) inode->i_flags |= S_DIRSYNC;
0a6cf9137ded4 (Ross Zwisler 2016-02-26 15:19:46 -0800 1384) if (test_opt(inode->i_sb, DAX) && S_ISREG(inode->i_mode))
fbbbad4bc2101 (Matthew Wilcox 2015-02-16 15:58:53 -0800 1385) inode->i_flags |= S_DAX;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1386) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1387)
fb094c90748fb (Dan Williams 2017-12-21 12:25:11 -0800 1388) void ext2_set_file_ops(struct inode *inode)
fb094c90748fb (Dan Williams 2017-12-21 12:25:11 -0800 1389) {
fb094c90748fb (Dan Williams 2017-12-21 12:25:11 -0800 1390) inode->i_op = &ext2_file_inode_operations;
fb094c90748fb (Dan Williams 2017-12-21 12:25:11 -0800 1391) inode->i_fop = &ext2_file_operations;
fb094c90748fb (Dan Williams 2017-12-21 12:25:11 -0800 1392) if (IS_DAX(inode))
fb094c90748fb (Dan Williams 2017-12-21 12:25:11 -0800 1393) inode->i_mapping->a_ops = &ext2_dax_aops;
fb094c90748fb (Dan Williams 2017-12-21 12:25:11 -0800 1394) else if (test_opt(inode->i_sb, NOBH))
fb094c90748fb (Dan Williams 2017-12-21 12:25:11 -0800 1395) inode->i_mapping->a_ops = &ext2_nobh_aops;
fb094c90748fb (Dan Williams 2017-12-21 12:25:11 -0800 1396) else
fb094c90748fb (Dan Williams 2017-12-21 12:25:11 -0800 1397) inode->i_mapping->a_ops = &ext2_aops;
fb094c90748fb (Dan Williams 2017-12-21 12:25:11 -0800 1398) }
fb094c90748fb (Dan Williams 2017-12-21 12:25:11 -0800 1399)
52fcf7032935b (David Howells 2008-02-07 00:15:35 -0800 1400) struct inode *ext2_iget (struct super_block *sb, unsigned long ino)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1401) {
52fcf7032935b (David Howells 2008-02-07 00:15:35 -0800 1402) struct ext2_inode_info *ei;
936bbf3aea846 (Jan Kara 2019-06-19 18:29:45 +0200 1403) struct buffer_head * bh = NULL;
52fcf7032935b (David Howells 2008-02-07 00:15:35 -0800 1404) struct ext2_inode *raw_inode;
52fcf7032935b (David Howells 2008-02-07 00:15:35 -0800 1405) struct inode *inode;
52fcf7032935b (David Howells 2008-02-07 00:15:35 -0800 1406) long ret = -EIO;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1407) int n;
b8a9f9e183229 (Eric W. Biederman 2012-02-07 15:39:12 -0800 1408) uid_t i_uid;
b8a9f9e183229 (Eric W. Biederman 2012-02-07 15:39:12 -0800 1409) gid_t i_gid;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1410)
52fcf7032935b (David Howells 2008-02-07 00:15:35 -0800 1411) inode = iget_locked(sb, ino);
52fcf7032935b (David Howells 2008-02-07 00:15:35 -0800 1412) if (!inode)
52fcf7032935b (David Howells 2008-02-07 00:15:35 -0800 1413) return ERR_PTR(-ENOMEM);
52fcf7032935b (David Howells 2008-02-07 00:15:35 -0800 1414) if (!(inode->i_state & I_NEW))
52fcf7032935b (David Howells 2008-02-07 00:15:35 -0800 1415) return inode;
52fcf7032935b (David Howells 2008-02-07 00:15:35 -0800 1416)
52fcf7032935b (David Howells 2008-02-07 00:15:35 -0800 1417) ei = EXT2_I(inode);
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 1418) ei->i_block_alloc_info = NULL;
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 1419)
52fcf7032935b (David Howells 2008-02-07 00:15:35 -0800 1420) raw_inode = ext2_get_inode(inode->i_sb, ino, &bh);
52fcf7032935b (David Howells 2008-02-07 00:15:35 -0800 1421) if (IS_ERR(raw_inode)) {
52fcf7032935b (David Howells 2008-02-07 00:15:35 -0800 1422) ret = PTR_ERR(raw_inode);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1423) goto bad_inode;
52fcf7032935b (David Howells 2008-02-07 00:15:35 -0800 1424) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1425)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1426) inode->i_mode = le16_to_cpu(raw_inode->i_mode);
b8a9f9e183229 (Eric W. Biederman 2012-02-07 15:39:12 -0800 1427) i_uid = (uid_t)le16_to_cpu(raw_inode->i_uid_low);
b8a9f9e183229 (Eric W. Biederman 2012-02-07 15:39:12 -0800 1428) i_gid = (gid_t)le16_to_cpu(raw_inode->i_gid_low);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1429) if (!(test_opt (inode->i_sb, NO_UID32))) {
b8a9f9e183229 (Eric W. Biederman 2012-02-07 15:39:12 -0800 1430) i_uid |= le16_to_cpu(raw_inode->i_uid_high) << 16;
b8a9f9e183229 (Eric W. Biederman 2012-02-07 15:39:12 -0800 1431) i_gid |= le16_to_cpu(raw_inode->i_gid_high) << 16;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1432) }
b8a9f9e183229 (Eric W. Biederman 2012-02-07 15:39:12 -0800 1433) i_uid_write(inode, i_uid);
b8a9f9e183229 (Eric W. Biederman 2012-02-07 15:39:12 -0800 1434) i_gid_write(inode, i_gid);
bfe8684869601 (Miklos Szeredi 2011-10-28 14:13:29 +0200 1435) set_nlink(inode, le16_to_cpu(raw_inode->i_links_count));
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1436) inode->i_size = le32_to_cpu(raw_inode->i_size);
4d7bf11d649c7 (Markus Rechberger 2007-05-08 00:23:39 -0700 1437) inode->i_atime.tv_sec = (signed)le32_to_cpu(raw_inode->i_atime);
4d7bf11d649c7 (Markus Rechberger 2007-05-08 00:23:39 -0700 1438) inode->i_ctime.tv_sec = (signed)le32_to_cpu(raw_inode->i_ctime);
4d7bf11d649c7 (Markus Rechberger 2007-05-08 00:23:39 -0700 1439) inode->i_mtime.tv_sec = (signed)le32_to_cpu(raw_inode->i_mtime);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1440) inode->i_atime.tv_nsec = inode->i_mtime.tv_nsec = inode->i_ctime.tv_nsec = 0;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1441) ei->i_dtime = le32_to_cpu(raw_inode->i_dtime);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1442) /* We now have enough fields to check if the inode was active or not.
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1443) * This is needed because nfsd might try to access dead inodes
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1444) * the test is that same one that e2fsck uses
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1445) * NeilBrown 1999oct15
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1446) */
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1447) if (inode->i_nlink == 0 && (inode->i_mode == 0 || ei->i_dtime)) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1448) /* this inode is deleted */
52fcf7032935b (David Howells 2008-02-07 00:15:35 -0800 1449) ret = -ESTALE;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1450) goto bad_inode;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1451) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1452) inode->i_blocks = le32_to_cpu(raw_inode->i_blocks);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1453) ei->i_flags = le32_to_cpu(raw_inode->i_flags);
9e796c9db93b4 (Toshi Kani 2018-09-14 08:51:14 -0600 1454) ext2_set_inode_flags(inode);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1455) ei->i_faddr = le32_to_cpu(raw_inode->i_faddr);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1456) ei->i_frag_no = raw_inode->i_frag;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1457) ei->i_frag_size = raw_inode->i_fsize;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1458) ei->i_file_acl = le32_to_cpu(raw_inode->i_file_acl);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1459) ei->i_dir_acl = 0;
ff0031d848a0c (Carlos Maiolino 2016-07-05 22:02:41 -0400 1460)
ff0031d848a0c (Carlos Maiolino 2016-07-05 22:02:41 -0400 1461) if (ei->i_file_acl &&
ff0031d848a0c (Carlos Maiolino 2016-07-05 22:02:41 -0400 1462) !ext2_data_block_valid(EXT2_SB(sb), ei->i_file_acl, 1)) {
ff0031d848a0c (Carlos Maiolino 2016-07-05 22:02:41 -0400 1463) ext2_error(sb, "ext2_iget", "bad extended attribute block %u",
ff0031d848a0c (Carlos Maiolino 2016-07-05 22:02:41 -0400 1464) ei->i_file_acl);
ff0031d848a0c (Carlos Maiolino 2016-07-05 22:02:41 -0400 1465) ret = -EFSCORRUPTED;
ff0031d848a0c (Carlos Maiolino 2016-07-05 22:02:41 -0400 1466) goto bad_inode;
ff0031d848a0c (Carlos Maiolino 2016-07-05 22:02:41 -0400 1467) }
ff0031d848a0c (Carlos Maiolino 2016-07-05 22:02:41 -0400 1468)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1469) if (S_ISREG(inode->i_mode))
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1470) inode->i_size |= ((__u64)le32_to_cpu(raw_inode->i_size_high)) << 32;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1471) else
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1472) ei->i_dir_acl = le32_to_cpu(raw_inode->i_dir_acl);
b46dc033818d3 (Darrick J. Wong 2016-12-06 15:59:01 -0800 1473) if (i_size_read(inode) < 0) {
b46dc033818d3 (Darrick J. Wong 2016-12-06 15:59:01 -0800 1474) ret = -EFSCORRUPTED;
b46dc033818d3 (Darrick J. Wong 2016-12-06 15:59:01 -0800 1475) goto bad_inode;
b46dc033818d3 (Darrick J. Wong 2016-12-06 15:59:01 -0800 1476) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1477) ei->i_dtime = 0;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1478) inode->i_generation = le32_to_cpu(raw_inode->i_generation);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1479) ei->i_state = 0;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1480) ei->i_block_group = (ino - 1) / EXT2_INODES_PER_GROUP(inode->i_sb);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1481) ei->i_dir_start_lookup = 0;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1482)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1483) /*
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1484) * NOTE! The in-memory inode i_data array is in little-endian order
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1485) * even on big-endian machines: we do NOT byteswap the block numbers!
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1486) */
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1487) for (n = 0; n < EXT2_N_BLOCKS; n++)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1488) ei->i_data[n] = raw_inode->i_block[n];
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1489)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1490) if (S_ISREG(inode->i_mode)) {
fb094c90748fb (Dan Williams 2017-12-21 12:25:11 -0800 1491) ext2_set_file_ops(inode);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1492) } else if (S_ISDIR(inode->i_mode)) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1493) inode->i_op = &ext2_dir_inode_operations;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1494) inode->i_fop = &ext2_dir_operations;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1495) if (test_opt(inode->i_sb, NOBH))
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1496) inode->i_mapping->a_ops = &ext2_nobh_aops;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1497) else
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1498) inode->i_mapping->a_ops = &ext2_aops;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1499) } else if (S_ISLNK(inode->i_mode)) {
8d6d0c4da2dbb (Duane Griffin 2008-12-19 20:47:13 +0000 1500) if (ext2_inode_is_fast_symlink(inode)) {
cbe0fa3858cd6 (Al Viro 2015-05-02 10:02:46 -0400 1501) inode->i_link = (char *)ei->i_data;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1502) inode->i_op = &ext2_fast_symlink_inode_operations;
8d6d0c4da2dbb (Duane Griffin 2008-12-19 20:47:13 +0000 1503) nd_terminate_link(ei->i_data, inode->i_size,
8d6d0c4da2dbb (Duane Griffin 2008-12-19 20:47:13 +0000 1504) sizeof(ei->i_data) - 1);
8d6d0c4da2dbb (Duane Griffin 2008-12-19 20:47:13 +0000 1505) } else {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1506) inode->i_op = &ext2_symlink_inode_operations;
21fc61c73c390 (Al Viro 2015-11-17 01:07:57 -0500 1507) inode_nohighmem(inode);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1508) if (test_opt(inode->i_sb, NOBH))
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1509) inode->i_mapping->a_ops = &ext2_nobh_aops;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1510) else
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1511) inode->i_mapping->a_ops = &ext2_aops;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1512) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1513) } else {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1514) inode->i_op = &ext2_special_inode_operations;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1515) if (raw_inode->i_block[0])
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1516) init_special_inode(inode, inode->i_mode,
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1517) old_decode_dev(le32_to_cpu(raw_inode->i_block[0])));
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1518) else
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1519) init_special_inode(inode, inode->i_mode,
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1520) new_decode_dev(le32_to_cpu(raw_inode->i_block[1])));
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1521) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1522) brelse (bh);
52fcf7032935b (David Howells 2008-02-07 00:15:35 -0800 1523) unlock_new_inode(inode);
52fcf7032935b (David Howells 2008-02-07 00:15:35 -0800 1524) return inode;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1525)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1526) bad_inode:
936bbf3aea846 (Jan Kara 2019-06-19 18:29:45 +0200 1527) brelse(bh);
52fcf7032935b (David Howells 2008-02-07 00:15:35 -0800 1528) iget_failed(inode);
52fcf7032935b (David Howells 2008-02-07 00:15:35 -0800 1529) return ERR_PTR(ret);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1530) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1531)
a9185b41a4f84 (Christoph Hellwig 2010-03-05 09:21:37 +0100 1532) static int __ext2_write_inode(struct inode *inode, int do_sync)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1533) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1534) struct ext2_inode_info *ei = EXT2_I(inode);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1535) struct super_block *sb = inode->i_sb;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1536) ino_t ino = inode->i_ino;
b8a9f9e183229 (Eric W. Biederman 2012-02-07 15:39:12 -0800 1537) uid_t uid = i_uid_read(inode);
b8a9f9e183229 (Eric W. Biederman 2012-02-07 15:39:12 -0800 1538) gid_t gid = i_gid_read(inode);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1539) struct buffer_head * bh;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1540) struct ext2_inode * raw_inode = ext2_get_inode(sb, ino, &bh);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1541) int n;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1542) int err = 0;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1543)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1544) if (IS_ERR(raw_inode))
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1545) return -EIO;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1546)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1547) /* For fields not not tracking in the in-memory inode,
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1548) * initialise them to zero for new inodes. */
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1549) if (ei->i_state & EXT2_STATE_NEW)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1550) memset(raw_inode, 0, EXT2_SB(sb)->s_inode_size);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1551)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1552) raw_inode->i_mode = cpu_to_le16(inode->i_mode);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1553) if (!(test_opt(sb, NO_UID32))) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1554) raw_inode->i_uid_low = cpu_to_le16(low_16_bits(uid));
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1555) raw_inode->i_gid_low = cpu_to_le16(low_16_bits(gid));
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1556) /*
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1557) * Fix up interoperability with old kernels. Otherwise, old inodes get
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1558) * re-used with the upper 16 bits of the uid/gid intact
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1559) */
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1560) if (!ei->i_dtime) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1561) raw_inode->i_uid_high = cpu_to_le16(high_16_bits(uid));
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1562) raw_inode->i_gid_high = cpu_to_le16(high_16_bits(gid));
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1563) } else {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1564) raw_inode->i_uid_high = 0;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1565) raw_inode->i_gid_high = 0;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1566) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1567) } else {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1568) raw_inode->i_uid_low = cpu_to_le16(fs_high2lowuid(uid));
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1569) raw_inode->i_gid_low = cpu_to_le16(fs_high2lowgid(gid));
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1570) raw_inode->i_uid_high = 0;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1571) raw_inode->i_gid_high = 0;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1572) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1573) raw_inode->i_links_count = cpu_to_le16(inode->i_nlink);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1574) raw_inode->i_size = cpu_to_le32(inode->i_size);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1575) raw_inode->i_atime = cpu_to_le32(inode->i_atime.tv_sec);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1576) raw_inode->i_ctime = cpu_to_le32(inode->i_ctime.tv_sec);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1577) raw_inode->i_mtime = cpu_to_le32(inode->i_mtime.tv_sec);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1578)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1579) raw_inode->i_blocks = cpu_to_le32(inode->i_blocks);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1580) raw_inode->i_dtime = cpu_to_le32(ei->i_dtime);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1581) raw_inode->i_flags = cpu_to_le32(ei->i_flags);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1582) raw_inode->i_faddr = cpu_to_le32(ei->i_faddr);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1583) raw_inode->i_frag = ei->i_frag_no;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1584) raw_inode->i_fsize = ei->i_frag_size;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1585) raw_inode->i_file_acl = cpu_to_le32(ei->i_file_acl);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1586) if (!S_ISREG(inode->i_mode))
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1587) raw_inode->i_dir_acl = cpu_to_le32(ei->i_dir_acl);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1588) else {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1589) raw_inode->i_size_high = cpu_to_le32(inode->i_size >> 32);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1590) if (inode->i_size > 0x7fffffffULL) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1591) if (!EXT2_HAS_RO_COMPAT_FEATURE(sb,
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1592) EXT2_FEATURE_RO_COMPAT_LARGE_FILE) ||
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1593) EXT2_SB(sb)->s_es->s_rev_level ==
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1594) cpu_to_le32(EXT2_GOOD_OLD_REV)) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1595) /* If this is the first large file
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1596) * created, add a flag to the superblock.
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1597) */
c15271f4e74cd (Jan Blunck 2010-04-14 14:38:38 +0200 1598) spin_lock(&EXT2_SB(sb)->s_lock);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1599) ext2_update_dynamic_rev(sb);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1600) EXT2_SET_RO_COMPAT_FEATURE(sb,
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1601) EXT2_FEATURE_RO_COMPAT_LARGE_FILE);
c15271f4e74cd (Jan Blunck 2010-04-14 14:38:38 +0200 1602) spin_unlock(&EXT2_SB(sb)->s_lock);
6554766150088 (Jan Kara 2017-04-05 13:32:52 +0200 1603) ext2_sync_super(sb, EXT2_SB(sb)->s_es, 1);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1604) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1605) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1606) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1607)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1608) raw_inode->i_generation = cpu_to_le32(inode->i_generation);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1609) if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1610) if (old_valid_dev(inode->i_rdev)) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1611) raw_inode->i_block[0] =
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1612) cpu_to_le32(old_encode_dev(inode->i_rdev));
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1613) raw_inode->i_block[1] = 0;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1614) } else {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1615) raw_inode->i_block[0] = 0;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1616) raw_inode->i_block[1] =
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1617) cpu_to_le32(new_encode_dev(inode->i_rdev));
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1618) raw_inode->i_block[2] = 0;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1619) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1620) } else for (n = 0; n < EXT2_N_BLOCKS; n++)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1621) raw_inode->i_block[n] = ei->i_data[n];
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1622) mark_buffer_dirty(bh);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1623) if (do_sync) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1624) sync_dirty_buffer(bh);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1625) if (buffer_req(bh) && !buffer_uptodate(bh)) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1626) printk ("IO error syncing ext2 inode [%s:%08lx]\n",
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1627) sb->s_id, (unsigned long) ino);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1628) err = -EIO;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1629) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1630) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1631) ei->i_state &= ~EXT2_STATE_NEW;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1632) brelse (bh);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1633) return err;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1634) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1635)
a9185b41a4f84 (Christoph Hellwig 2010-03-05 09:21:37 +0100 1636) int ext2_write_inode(struct inode *inode, struct writeback_control *wbc)
a9185b41a4f84 (Christoph Hellwig 2010-03-05 09:21:37 +0100 1637) {
a9185b41a4f84 (Christoph Hellwig 2010-03-05 09:21:37 +0100 1638) return __ext2_write_inode(inode, wbc->sync_mode == WB_SYNC_ALL);
a9185b41a4f84 (Christoph Hellwig 2010-03-05 09:21:37 +0100 1639) }
a9185b41a4f84 (Christoph Hellwig 2010-03-05 09:21:37 +0100 1640)
549c7297717c3 (Christian Brauner 2021-01-21 14:19:43 +0100 1641) int ext2_getattr(struct user_namespace *mnt_userns, const struct path *path,
549c7297717c3 (Christian Brauner 2021-01-21 14:19:43 +0100 1642) struct kstat *stat, u32 request_mask, unsigned int query_flags)
93bc420ed41df (yangerkun 2019-02-18 09:07:02 +0800 1643) {
93bc420ed41df (yangerkun 2019-02-18 09:07:02 +0800 1644) struct inode *inode = d_inode(path->dentry);
93bc420ed41df (yangerkun 2019-02-18 09:07:02 +0800 1645) struct ext2_inode_info *ei = EXT2_I(inode);
93bc420ed41df (yangerkun 2019-02-18 09:07:02 +0800 1646) unsigned int flags;
93bc420ed41df (yangerkun 2019-02-18 09:07:02 +0800 1647)
93bc420ed41df (yangerkun 2019-02-18 09:07:02 +0800 1648) flags = ei->i_flags & EXT2_FL_USER_VISIBLE;
93bc420ed41df (yangerkun 2019-02-18 09:07:02 +0800 1649) if (flags & EXT2_APPEND_FL)
93bc420ed41df (yangerkun 2019-02-18 09:07:02 +0800 1650) stat->attributes |= STATX_ATTR_APPEND;
93bc420ed41df (yangerkun 2019-02-18 09:07:02 +0800 1651) if (flags & EXT2_COMPR_FL)
93bc420ed41df (yangerkun 2019-02-18 09:07:02 +0800 1652) stat->attributes |= STATX_ATTR_COMPRESSED;
93bc420ed41df (yangerkun 2019-02-18 09:07:02 +0800 1653) if (flags & EXT2_IMMUTABLE_FL)
93bc420ed41df (yangerkun 2019-02-18 09:07:02 +0800 1654) stat->attributes |= STATX_ATTR_IMMUTABLE;
93bc420ed41df (yangerkun 2019-02-18 09:07:02 +0800 1655) if (flags & EXT2_NODUMP_FL)
93bc420ed41df (yangerkun 2019-02-18 09:07:02 +0800 1656) stat->attributes |= STATX_ATTR_NODUMP;
93bc420ed41df (yangerkun 2019-02-18 09:07:02 +0800 1657) stat->attributes_mask |= (STATX_ATTR_APPEND |
93bc420ed41df (yangerkun 2019-02-18 09:07:02 +0800 1658) STATX_ATTR_COMPRESSED |
93bc420ed41df (yangerkun 2019-02-18 09:07:02 +0800 1659) STATX_ATTR_ENCRYPTED |
93bc420ed41df (yangerkun 2019-02-18 09:07:02 +0800 1660) STATX_ATTR_IMMUTABLE |
93bc420ed41df (yangerkun 2019-02-18 09:07:02 +0800 1661) STATX_ATTR_NODUMP);
93bc420ed41df (yangerkun 2019-02-18 09:07:02 +0800 1662)
0d56a4518d5ea (Christian Brauner 2021-01-21 14:19:30 +0100 1663) generic_fillattr(&init_user_ns, inode, stat);
93bc420ed41df (yangerkun 2019-02-18 09:07:02 +0800 1664) return 0;
93bc420ed41df (yangerkun 2019-02-18 09:07:02 +0800 1665) }
93bc420ed41df (yangerkun 2019-02-18 09:07:02 +0800 1666)
549c7297717c3 (Christian Brauner 2021-01-21 14:19:43 +0100 1667) int ext2_setattr(struct user_namespace *mnt_userns, struct dentry *dentry,
549c7297717c3 (Christian Brauner 2021-01-21 14:19:43 +0100 1668) struct iattr *iattr)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1669) {
2b0143b5c986b (David Howells 2015-03-17 22:25:59 +0000 1670) struct inode *inode = d_inode(dentry);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1671) int error;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1672)
2f221d6f7b881 (Christian Brauner 2021-01-21 14:19:26 +0100 1673) error = setattr_prepare(&init_user_ns, dentry, iattr);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1674) if (error)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1675) return error;
907f4554e2521 (Christoph Hellwig 2010-03-03 09:05:06 -0500 1676)
c2edb305d6846 (Jan Kara 2015-06-29 16:08:45 +0200 1677) if (is_quota_modification(inode, iattr)) {
c2edb305d6846 (Jan Kara 2015-06-29 16:08:45 +0200 1678) error = dquot_initialize(inode);
c2edb305d6846 (Jan Kara 2015-06-29 16:08:45 +0200 1679) if (error)
c2edb305d6846 (Jan Kara 2015-06-29 16:08:45 +0200 1680) return error;
c2edb305d6846 (Jan Kara 2015-06-29 16:08:45 +0200 1681) }
b8a9f9e183229 (Eric W. Biederman 2012-02-07 15:39:12 -0800 1682) if ((iattr->ia_valid & ATTR_UID && !uid_eq(iattr->ia_uid, inode->i_uid)) ||
b8a9f9e183229 (Eric W. Biederman 2012-02-07 15:39:12 -0800 1683) (iattr->ia_valid & ATTR_GID && !gid_eq(iattr->ia_gid, inode->i_gid))) {
b43fa8284d779 (Christoph Hellwig 2010-03-03 09:05:03 -0500 1684) error = dquot_transfer(inode, iattr);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1685) if (error)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1686) return error;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1687) }
af5a30d8cfcfc (Nicholas Piggin 2010-06-03 22:01:46 +1000 1688) if (iattr->ia_valid & ATTR_SIZE && iattr->ia_size != inode->i_size) {
737f2e93b9724 (Nicholas Piggin 2010-05-27 01:05:37 +1000 1689) error = ext2_setsize(inode, iattr->ia_size);
737f2e93b9724 (Nicholas Piggin 2010-05-27 01:05:37 +1000 1690) if (error)
737f2e93b9724 (Nicholas Piggin 2010-05-27 01:05:37 +1000 1691) return error;
737f2e93b9724 (Nicholas Piggin 2010-05-27 01:05:37 +1000 1692) }
2f221d6f7b881 (Christian Brauner 2021-01-21 14:19:26 +0100 1693) setattr_copy(&init_user_ns, inode, iattr);
737f2e93b9724 (Nicholas Piggin 2010-05-27 01:05:37 +1000 1694) if (iattr->ia_valid & ATTR_MODE)
e65ce2a50cf6a (Christian Brauner 2021-01-21 14:19:27 +0100 1695) error = posix_acl_chmod(&init_user_ns, inode, inode->i_mode);
737f2e93b9724 (Nicholas Piggin 2010-05-27 01:05:37 +1000 1696) mark_inode_dirty(inode);
737f2e93b9724 (Nicholas Piggin 2010-05-27 01:05:37 +1000 1697)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1698) return error;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1699) }