VisionFive2 Linux kernel

StarFive Tech Linux Kernel for VisionFive (JH7110) boards (mirror)

More than 9999 Commits   32 Branches   54 Tags
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/affs/file.c
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700    4)  *
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700    5)  *  (c) 1996  Hans-Joachim Widmaier - Rewritten
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700    6)  *
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700    7)  *  (C) 1993  Ray Burr - Modified for Amiga FFS filesystem.
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700    8)  *
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700    9)  *  (C) 1992  Eric Youngdale Modified for ISO 9660 filesystem.
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   10)  *
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   11)  *  (C) 1991  Linus Torvalds - minix filesystem
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   12)  *
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   13)  *  affs regular file handling primitives
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   14)  */
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   15) 
e2e40f2c1ed43 (Christoph Hellwig  2015-02-22 08:58:50 -0800   16) #include <linux/uio.h>
3f1266f1f82d7 (Christoph Hellwig  2020-06-20 09:16:41 +0200   17) #include <linux/blkdev.h>
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   18) #include "affs.h"
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   19) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   20) static struct buffer_head *affs_get_extblock_slow(struct inode *inode, u32 ext);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   21) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   22) static int
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   23) affs_file_open(struct inode *inode, struct file *filp)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   24) {
9606d9aa858ae (Fabian Frederick   2014-06-06 14:37:25 -0700   25) 	pr_debug("open(%lu,%d)\n",
dca3c33652e43 (Roman Zippel       2008-04-29 17:02:20 +0200   26) 		 inode->i_ino, atomic_read(&AFFS_I(inode)->i_opencnt));
dca3c33652e43 (Roman Zippel       2008-04-29 17:02:20 +0200   27) 	atomic_inc(&AFFS_I(inode)->i_opencnt);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   28) 	return 0;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   29) }
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   30) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   31) static int
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   32) affs_file_release(struct inode *inode, struct file *filp)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   33) {
9606d9aa858ae (Fabian Frederick   2014-06-06 14:37:25 -0700   34) 	pr_debug("release(%lu, %d)\n",
dca3c33652e43 (Roman Zippel       2008-04-29 17:02:20 +0200   35) 		 inode->i_ino, atomic_read(&AFFS_I(inode)->i_opencnt));
dca3c33652e43 (Roman Zippel       2008-04-29 17:02:20 +0200   36) 
dca3c33652e43 (Roman Zippel       2008-04-29 17:02:20 +0200   37) 	if (atomic_dec_and_test(&AFFS_I(inode)->i_opencnt)) {
5955102c9984f (Al Viro            2016-01-22 15:40:57 -0500   38) 		inode_lock(inode);
dca3c33652e43 (Roman Zippel       2008-04-29 17:02:20 +0200   39) 		if (inode->i_size != AFFS_I(inode)->mmu_private)
dca3c33652e43 (Roman Zippel       2008-04-29 17:02:20 +0200   40) 			affs_truncate(inode);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   41) 		affs_free_prealloc(inode);
5955102c9984f (Al Viro            2016-01-22 15:40:57 -0500   42) 		inode_unlock(inode);
dca3c33652e43 (Roman Zippel       2008-04-29 17:02:20 +0200   43) 	}
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   44) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   45) 	return 0;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   46) }
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   47) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   48) static int
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   49) affs_grow_extcache(struct inode *inode, u32 lc_idx)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   50) {
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   51) 	struct super_block	*sb = inode->i_sb;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   52) 	struct buffer_head	*bh;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   53) 	u32 lc_max;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   54) 	int i, j, key;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   55) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   56) 	if (!AFFS_I(inode)->i_lc) {
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   57) 		char *ptr = (char *)get_zeroed_page(GFP_NOFS);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   58) 		if (!ptr)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   59) 			return -ENOMEM;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   60) 		AFFS_I(inode)->i_lc = (u32 *)ptr;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   61) 		AFFS_I(inode)->i_ac = (struct affs_ext_key *)(ptr + AFFS_CACHE_SIZE / 2);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   62) 	}
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   63) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   64) 	lc_max = AFFS_LC_SIZE << AFFS_I(inode)->i_lc_shift;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   65) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   66) 	if (AFFS_I(inode)->i_extcnt > lc_max) {
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   67) 		u32 lc_shift, lc_mask, tmp, off;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   68) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   69) 		/* need to recalculate linear cache, start from old size */
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   70) 		lc_shift = AFFS_I(inode)->i_lc_shift;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   71) 		tmp = (AFFS_I(inode)->i_extcnt / AFFS_LC_SIZE) >> lc_shift;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   72) 		for (; tmp; tmp >>= 1)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   73) 			lc_shift++;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   74) 		lc_mask = (1 << lc_shift) - 1;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   75) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   76) 		/* fix idx and old size to new shift */
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   77) 		lc_idx >>= (lc_shift - AFFS_I(inode)->i_lc_shift);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   78) 		AFFS_I(inode)->i_lc_size >>= (lc_shift - AFFS_I(inode)->i_lc_shift);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   79) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   80) 		/* first shrink old cache to make more space */
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   81) 		off = 1 << (lc_shift - AFFS_I(inode)->i_lc_shift);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   82) 		for (i = 1, j = off; j < AFFS_LC_SIZE; i++, j += off)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   83) 			AFFS_I(inode)->i_ac[i] = AFFS_I(inode)->i_ac[j];
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   84) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   85) 		AFFS_I(inode)->i_lc_shift = lc_shift;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   86) 		AFFS_I(inode)->i_lc_mask = lc_mask;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   87) 	}
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   88) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   89) 	/* fill cache to the needed index */
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   90) 	i = AFFS_I(inode)->i_lc_size;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   91) 	AFFS_I(inode)->i_lc_size = lc_idx + 1;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   92) 	for (; i <= lc_idx; i++) {
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   93) 		if (!i) {
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   94) 			AFFS_I(inode)->i_lc[0] = inode->i_ino;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   95) 			continue;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   96) 		}
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   97) 		key = AFFS_I(inode)->i_lc[i - 1];
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   98) 		j = AFFS_I(inode)->i_lc_mask + 1;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   99) 		// unlock cache
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  100) 		for (; j > 0; j--) {
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  101) 			bh = affs_bread(sb, key);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  102) 			if (!bh)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  103) 				goto err;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  104) 			key = be32_to_cpu(AFFS_TAIL(sb, bh)->extension);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  105) 			affs_brelse(bh);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  106) 		}
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  107) 		// lock cache
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  108) 		AFFS_I(inode)->i_lc[i] = key;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  109) 	}
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  110) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  111) 	return 0;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  112) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  113) err:
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  114) 	// lock cache
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  115) 	return -EIO;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  116) }
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  117) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  118) static struct buffer_head *
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  119) affs_alloc_extblock(struct inode *inode, struct buffer_head *bh, u32 ext)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  120) {
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  121) 	struct super_block *sb = inode->i_sb;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  122) 	struct buffer_head *new_bh;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  123) 	u32 blocknr, tmp;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  124) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  125) 	blocknr = affs_alloc_block(inode, bh->b_blocknr);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  126) 	if (!blocknr)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  127) 		return ERR_PTR(-ENOSPC);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  128) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  129) 	new_bh = affs_getzeroblk(sb, blocknr);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  130) 	if (!new_bh) {
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  131) 		affs_free_block(sb, blocknr);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  132) 		return ERR_PTR(-EIO);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  133) 	}
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  134) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  135) 	AFFS_HEAD(new_bh)->ptype = cpu_to_be32(T_LIST);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  136) 	AFFS_HEAD(new_bh)->key = cpu_to_be32(blocknr);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  137) 	AFFS_TAIL(sb, new_bh)->stype = cpu_to_be32(ST_FILE);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  138) 	AFFS_TAIL(sb, new_bh)->parent = cpu_to_be32(inode->i_ino);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  139) 	affs_fix_checksum(sb, new_bh);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  140) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  141) 	mark_buffer_dirty_inode(new_bh, inode);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  142) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  143) 	tmp = be32_to_cpu(AFFS_TAIL(sb, bh)->extension);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  144) 	if (tmp)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  145) 		affs_warning(sb, "alloc_ext", "previous extension set (%x)", tmp);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  146) 	AFFS_TAIL(sb, bh)->extension = cpu_to_be32(blocknr);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  147) 	affs_adjust_checksum(bh, blocknr - tmp);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  148) 	mark_buffer_dirty_inode(bh, inode);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  149) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  150) 	AFFS_I(inode)->i_extcnt++;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  151) 	mark_inode_dirty(inode);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  152) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  153) 	return new_bh;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  154) }
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  155) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  156) static inline struct buffer_head *
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  157) affs_get_extblock(struct inode *inode, u32 ext)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  158) {
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  159) 	/* inline the simplest case: same extended block as last time */
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  160) 	struct buffer_head *bh = AFFS_I(inode)->i_ext_bh;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  161) 	if (ext == AFFS_I(inode)->i_ext_last)
dca3c33652e43 (Roman Zippel       2008-04-29 17:02:20 +0200  162) 		get_bh(bh);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  163) 	else
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  164) 		/* we have to do more (not inlined) */
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  165) 		bh = affs_get_extblock_slow(inode, ext);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  166) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  167) 	return bh;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  168) }
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  169) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  170) static struct buffer_head *
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  171) affs_get_extblock_slow(struct inode *inode, u32 ext)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  172) {
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  173) 	struct super_block *sb = inode->i_sb;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  174) 	struct buffer_head *bh;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  175) 	u32 ext_key;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  176) 	u32 lc_idx, lc_off, ac_idx;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  177) 	u32 tmp, idx;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  178) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  179) 	if (ext == AFFS_I(inode)->i_ext_last + 1) {
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  180) 		/* read the next extended block from the current one */
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  181) 		bh = AFFS_I(inode)->i_ext_bh;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  182) 		ext_key = be32_to_cpu(AFFS_TAIL(sb, bh)->extension);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  183) 		if (ext < AFFS_I(inode)->i_extcnt)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  184) 			goto read_ext;
afe305dcc96ed (Fabian Frederick   2015-02-17 13:46:12 -0800  185) 		BUG_ON(ext > AFFS_I(inode)->i_extcnt);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  186) 		bh = affs_alloc_extblock(inode, bh, ext);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  187) 		if (IS_ERR(bh))
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  188) 			return bh;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  189) 		goto store_ext;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  190) 	}
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  191) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  192) 	if (ext == 0) {
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  193) 		/* we seek back to the file header block */
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  194) 		ext_key = inode->i_ino;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  195) 		goto read_ext;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  196) 	}
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  197) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  198) 	if (ext >= AFFS_I(inode)->i_extcnt) {
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  199) 		struct buffer_head *prev_bh;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  200) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  201) 		/* allocate a new extended block */
afe305dcc96ed (Fabian Frederick   2015-02-17 13:46:12 -0800  202) 		BUG_ON(ext > AFFS_I(inode)->i_extcnt);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  203) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  204) 		/* get previous extended block */
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  205) 		prev_bh = affs_get_extblock(inode, ext - 1);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  206) 		if (IS_ERR(prev_bh))
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  207) 			return prev_bh;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  208) 		bh = affs_alloc_extblock(inode, prev_bh, ext);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  209) 		affs_brelse(prev_bh);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  210) 		if (IS_ERR(bh))
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  211) 			return bh;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  212) 		goto store_ext;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  213) 	}
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  214) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  215) again:
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  216) 	/* check if there is an extended cache and whether it's large enough */
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  217) 	lc_idx = ext >> AFFS_I(inode)->i_lc_shift;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  218) 	lc_off = ext & AFFS_I(inode)->i_lc_mask;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  219) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  220) 	if (lc_idx >= AFFS_I(inode)->i_lc_size) {
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  221) 		int err;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  222) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  223) 		err = affs_grow_extcache(inode, lc_idx);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  224) 		if (err)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  225) 			return ERR_PTR(err);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  226) 		goto again;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  227) 	}
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  228) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  229) 	/* every n'th key we find in the linear cache */
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  230) 	if (!lc_off) {
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  231) 		ext_key = AFFS_I(inode)->i_lc[lc_idx];
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  232) 		goto read_ext;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  233) 	}
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  234) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  235) 	/* maybe it's still in the associative cache */
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  236) 	ac_idx = (ext - lc_idx - 1) & AFFS_AC_MASK;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  237) 	if (AFFS_I(inode)->i_ac[ac_idx].ext == ext) {
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  238) 		ext_key = AFFS_I(inode)->i_ac[ac_idx].key;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  239) 		goto read_ext;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  240) 	}
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  241) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  242) 	/* try to find one of the previous extended blocks */
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  243) 	tmp = ext;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  244) 	idx = ac_idx;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  245) 	while (--tmp, --lc_off > 0) {
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  246) 		idx = (idx - 1) & AFFS_AC_MASK;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  247) 		if (AFFS_I(inode)->i_ac[idx].ext == tmp) {
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  248) 			ext_key = AFFS_I(inode)->i_ac[idx].key;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  249) 			goto find_ext;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  250) 		}
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  251) 	}
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  252) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  253) 	/* fall back to the linear cache */
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  254) 	ext_key = AFFS_I(inode)->i_lc[lc_idx];
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  255) find_ext:
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  256) 	/* read all extended blocks until we find the one we need */
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  257) 	//unlock cache
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  258) 	do {
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  259) 		bh = affs_bread(sb, ext_key);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  260) 		if (!bh)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  261) 			goto err_bread;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  262) 		ext_key = be32_to_cpu(AFFS_TAIL(sb, bh)->extension);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  263) 		affs_brelse(bh);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  264) 		tmp++;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  265) 	} while (tmp < ext);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  266) 	//lock cache
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  267) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  268) 	/* store it in the associative cache */
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  269) 	// recalculate ac_idx?
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  270) 	AFFS_I(inode)->i_ac[ac_idx].ext = ext;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  271) 	AFFS_I(inode)->i_ac[ac_idx].key = ext_key;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  272) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  273) read_ext:
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  274) 	/* finally read the right extended block */
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  275) 	//unlock cache
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  276) 	bh = affs_bread(sb, ext_key);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  277) 	if (!bh)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  278) 		goto err_bread;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  279) 	//lock cache
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  280) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  281) store_ext:
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  282) 	/* release old cached extended block and store the new one */
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  283) 	affs_brelse(AFFS_I(inode)->i_ext_bh);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  284) 	AFFS_I(inode)->i_ext_last = ext;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  285) 	AFFS_I(inode)->i_ext_bh = bh;
dca3c33652e43 (Roman Zippel       2008-04-29 17:02:20 +0200  286) 	get_bh(bh);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  287) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  288) 	return bh;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  289) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  290) err_bread:
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  291) 	affs_brelse(bh);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  292) 	return ERR_PTR(-EIO);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  293) }
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  294) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  295) static int
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  296) affs_get_block(struct inode *inode, sector_t block, struct buffer_head *bh_result, int create)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  297) {
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  298) 	struct super_block	*sb = inode->i_sb;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  299) 	struct buffer_head	*ext_bh;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  300) 	u32			 ext;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  301) 
08fe100d91bc0 (Geert Uytterhoeven 2015-02-17 13:46:10 -0800  302) 	pr_debug("%s(%lu, %llu)\n", __func__, inode->i_ino,
08fe100d91bc0 (Geert Uytterhoeven 2015-02-17 13:46:10 -0800  303) 		 (unsigned long long)block);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  304) 
8d4b69002e56e (Julia Lawall       2008-04-29 00:59:12 -0700  305) 	BUG_ON(block > (sector_t)0x7fffffffUL);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  306) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  307) 	if (block >= AFFS_I(inode)->i_blkcnt) {
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  308) 		if (block > AFFS_I(inode)->i_blkcnt || !create)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  309) 			goto err_big;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  310) 	} else
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  311) 		create = 0;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  312) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  313) 	//lock cache
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  314) 	affs_lock_ext(inode);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  315) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  316) 	ext = (u32)block / AFFS_SB(sb)->s_hashsize;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  317) 	block -= ext * AFFS_SB(sb)->s_hashsize;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  318) 	ext_bh = affs_get_extblock(inode, ext);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  319) 	if (IS_ERR(ext_bh))
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  320) 		goto err_ext;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  321) 	map_bh(bh_result, sb, (sector_t)be32_to_cpu(AFFS_BLOCK(sb, ext_bh, block)));
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  322) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  323) 	if (create) {
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  324) 		u32 blocknr = affs_alloc_block(inode, ext_bh->b_blocknr);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  325) 		if (!blocknr)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  326) 			goto err_alloc;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  327) 		set_buffer_new(bh_result);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  328) 		AFFS_I(inode)->mmu_private += AFFS_SB(sb)->s_data_blksize;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  329) 		AFFS_I(inode)->i_blkcnt++;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  330) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  331) 		/* store new block */
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  332) 		if (bh_result->b_blocknr)
08fe100d91bc0 (Geert Uytterhoeven 2015-02-17 13:46:10 -0800  333) 			affs_warning(sb, "get_block",
08fe100d91bc0 (Geert Uytterhoeven 2015-02-17 13:46:10 -0800  334) 				     "block already set (%llx)",
08fe100d91bc0 (Geert Uytterhoeven 2015-02-17 13:46:10 -0800  335) 				     (unsigned long long)bh_result->b_blocknr);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  336) 		AFFS_BLOCK(sb, ext_bh, block) = cpu_to_be32(blocknr);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  337) 		AFFS_HEAD(ext_bh)->block_count = cpu_to_be32(block + 1);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  338) 		affs_adjust_checksum(ext_bh, blocknr - bh_result->b_blocknr + 1);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  339) 		bh_result->b_blocknr = blocknr;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  340) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  341) 		if (!block) {
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  342) 			/* insert first block into header block */
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  343) 			u32 tmp = be32_to_cpu(AFFS_HEAD(ext_bh)->first_data);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  344) 			if (tmp)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  345) 				affs_warning(sb, "get_block", "first block already set (%d)", tmp);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  346) 			AFFS_HEAD(ext_bh)->first_data = cpu_to_be32(blocknr);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  347) 			affs_adjust_checksum(ext_bh, blocknr - tmp);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  348) 		}
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  349) 	}
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  350) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  351) 	affs_brelse(ext_bh);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  352) 	//unlock cache
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  353) 	affs_unlock_ext(inode);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  354) 	return 0;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  355) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  356) err_big:
08fe100d91bc0 (Geert Uytterhoeven 2015-02-17 13:46:10 -0800  357) 	affs_error(inode->i_sb, "get_block", "strange block request %llu",
08fe100d91bc0 (Geert Uytterhoeven 2015-02-17 13:46:10 -0800  358) 		   (unsigned long long)block);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  359) 	return -EIO;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  360) err_ext:
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  361) 	// unlock cache
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  362) 	affs_unlock_ext(inode);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  363) 	return PTR_ERR(ext_bh);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  364) err_alloc:
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  365) 	brelse(ext_bh);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  366) 	clear_buffer_mapped(bh_result);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  367) 	bh_result->b_bdev = NULL;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  368) 	// unlock cache
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  369) 	affs_unlock_ext(inode);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  370) 	return -ENOSPC;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  371) }
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  372) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  373) static int affs_writepage(struct page *page, struct writeback_control *wbc)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  374) {
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  375) 	return block_write_full_page(page, affs_get_block, wbc);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  376) }
f2b6a16eb8f5b (Nicholas Piggin    2007-10-16 01:25:24 -0700  377) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  378) static int affs_readpage(struct file *file, struct page *page)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  379) {
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  380) 	return block_read_full_page(page, affs_get_block);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  381) }
f2b6a16eb8f5b (Nicholas Piggin    2007-10-16 01:25:24 -0700  382) 
1dc1834f42926 (Marco Stornelli    2012-12-15 11:51:53 +0100  383) static void affs_write_failed(struct address_space *mapping, loff_t to)
1dc1834f42926 (Marco Stornelli    2012-12-15 11:51:53 +0100  384) {
1dc1834f42926 (Marco Stornelli    2012-12-15 11:51:53 +0100  385) 	struct inode *inode = mapping->host;
1dc1834f42926 (Marco Stornelli    2012-12-15 11:51:53 +0100  386) 
1dc1834f42926 (Marco Stornelli    2012-12-15 11:51:53 +0100  387) 	if (to > inode->i_size) {
7caef26767c17 (Kirill A. Shutemov 2013-09-12 15:13:56 -0700  388) 		truncate_pagecache(inode, inode->i_size);
1dc1834f42926 (Marco Stornelli    2012-12-15 11:51:53 +0100  389) 		affs_truncate(inode);
1dc1834f42926 (Marco Stornelli    2012-12-15 11:51:53 +0100  390) 	}
1dc1834f42926 (Marco Stornelli    2012-12-15 11:51:53 +0100  391) }
1dc1834f42926 (Marco Stornelli    2012-12-15 11:51:53 +0100  392) 
9abb408307008 (Fabian Frederick   2014-12-12 16:57:52 -0800  393) static ssize_t
c8b8e32d700fe (Christoph Hellwig  2016-04-07 08:51:58 -0700  394) affs_direct_IO(struct kiocb *iocb, struct iov_iter *iter)
9abb408307008 (Fabian Frederick   2014-12-12 16:57:52 -0800  395) {
9abb408307008 (Fabian Frederick   2014-12-12 16:57:52 -0800  396) 	struct file *file = iocb->ki_filp;
9abb408307008 (Fabian Frederick   2014-12-12 16:57:52 -0800  397) 	struct address_space *mapping = file->f_mapping;
9abb408307008 (Fabian Frederick   2014-12-12 16:57:52 -0800  398) 	struct inode *inode = mapping->host;
9abb408307008 (Fabian Frederick   2014-12-12 16:57:52 -0800  399) 	size_t count = iov_iter_count(iter);
c8b8e32d700fe (Christoph Hellwig  2016-04-07 08:51:58 -0700  400) 	loff_t offset = iocb->ki_pos;
9abb408307008 (Fabian Frederick   2014-12-12 16:57:52 -0800  401) 	ssize_t ret;
9abb408307008 (Fabian Frederick   2014-12-12 16:57:52 -0800  402) 
6f67376318abe (Omar Sandoval      2015-03-16 04:33:52 -0700  403) 	if (iov_iter_rw(iter) == WRITE) {
92b20708f9f0c (Fabian Frederick   2015-02-17 13:46:15 -0800  404) 		loff_t size = offset + count;
92b20708f9f0c (Fabian Frederick   2015-02-17 13:46:15 -0800  405) 
92b20708f9f0c (Fabian Frederick   2015-02-17 13:46:15 -0800  406) 		if (AFFS_I(inode)->mmu_private < size)
92b20708f9f0c (Fabian Frederick   2015-02-17 13:46:15 -0800  407) 			return 0;
92b20708f9f0c (Fabian Frederick   2015-02-17 13:46:15 -0800  408) 	}
92b20708f9f0c (Fabian Frederick   2015-02-17 13:46:15 -0800  409) 
c8b8e32d700fe (Christoph Hellwig  2016-04-07 08:51:58 -0700  410) 	ret = blockdev_direct_IO(iocb, inode, iter, affs_get_block);
6f67376318abe (Omar Sandoval      2015-03-16 04:33:52 -0700  411) 	if (ret < 0 && iov_iter_rw(iter) == WRITE)
9abb408307008 (Fabian Frederick   2014-12-12 16:57:52 -0800  412) 		affs_write_failed(mapping, offset + count);
9abb408307008 (Fabian Frederick   2014-12-12 16:57:52 -0800  413) 	return ret;
9abb408307008 (Fabian Frederick   2014-12-12 16:57:52 -0800  414) }
9abb408307008 (Fabian Frederick   2014-12-12 16:57:52 -0800  415) 
f2b6a16eb8f5b (Nicholas Piggin    2007-10-16 01:25:24 -0700  416) static int affs_write_begin(struct file *file, struct address_space *mapping,
f2b6a16eb8f5b (Nicholas Piggin    2007-10-16 01:25:24 -0700  417) 			loff_t pos, unsigned len, unsigned flags,
f2b6a16eb8f5b (Nicholas Piggin    2007-10-16 01:25:24 -0700  418) 			struct page **pagep, void **fsdata)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  419) {
282dc17884988 (Christoph Hellwig  2010-06-04 11:29:55 +0200  420) 	int ret;
282dc17884988 (Christoph Hellwig  2010-06-04 11:29:55 +0200  421) 
f2b6a16eb8f5b (Nicholas Piggin    2007-10-16 01:25:24 -0700  422) 	*pagep = NULL;
282dc17884988 (Christoph Hellwig  2010-06-04 11:29:55 +0200  423) 	ret = cont_write_begin(file, mapping, pos, len, flags, pagep, fsdata,
f2b6a16eb8f5b (Nicholas Piggin    2007-10-16 01:25:24 -0700  424) 				affs_get_block,
f2b6a16eb8f5b (Nicholas Piggin    2007-10-16 01:25:24 -0700  425) 				&AFFS_I(mapping->host)->mmu_private);
1dc1834f42926 (Marco Stornelli    2012-12-15 11:51:53 +0100  426) 	if (unlikely(ret))
1dc1834f42926 (Marco Stornelli    2012-12-15 11:51:53 +0100  427) 		affs_write_failed(mapping, pos + len);
282dc17884988 (Christoph Hellwig  2010-06-04 11:29:55 +0200  428) 
282dc17884988 (Christoph Hellwig  2010-06-04 11:29:55 +0200  429) 	return ret;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  430) }
f2b6a16eb8f5b (Nicholas Piggin    2007-10-16 01:25:24 -0700  431) 
d3a84a8d0dde4 (Max Staudt         2020-08-27 17:49:00 +0200  432) static int affs_write_end(struct file *file, struct address_space *mapping,
d3a84a8d0dde4 (Max Staudt         2020-08-27 17:49:00 +0200  433) 			  loff_t pos, unsigned int len, unsigned int copied,
d3a84a8d0dde4 (Max Staudt         2020-08-27 17:49:00 +0200  434) 			  struct page *page, void *fsdata)
d3a84a8d0dde4 (Max Staudt         2020-08-27 17:49:00 +0200  435) {
d3a84a8d0dde4 (Max Staudt         2020-08-27 17:49:00 +0200  436) 	struct inode *inode = mapping->host;
d3a84a8d0dde4 (Max Staudt         2020-08-27 17:49:00 +0200  437) 	int ret;
d3a84a8d0dde4 (Max Staudt         2020-08-27 17:49:00 +0200  438) 
d3a84a8d0dde4 (Max Staudt         2020-08-27 17:49:00 +0200  439) 	ret = generic_write_end(file, mapping, pos, len, copied, page, fsdata);
d3a84a8d0dde4 (Max Staudt         2020-08-27 17:49:00 +0200  440) 
d3a84a8d0dde4 (Max Staudt         2020-08-27 17:49:00 +0200  441) 	/* Clear Archived bit on file writes, as AmigaOS would do */
d3a84a8d0dde4 (Max Staudt         2020-08-27 17:49:00 +0200  442) 	if (AFFS_I(inode)->i_protect & FIBF_ARCHIVED) {
d3a84a8d0dde4 (Max Staudt         2020-08-27 17:49:00 +0200  443) 		AFFS_I(inode)->i_protect &= ~FIBF_ARCHIVED;
d3a84a8d0dde4 (Max Staudt         2020-08-27 17:49:00 +0200  444) 		mark_inode_dirty(inode);
d3a84a8d0dde4 (Max Staudt         2020-08-27 17:49:00 +0200  445) 	}
d3a84a8d0dde4 (Max Staudt         2020-08-27 17:49:00 +0200  446) 
d3a84a8d0dde4 (Max Staudt         2020-08-27 17:49:00 +0200  447) 	return ret;
d3a84a8d0dde4 (Max Staudt         2020-08-27 17:49:00 +0200  448) }
d3a84a8d0dde4 (Max Staudt         2020-08-27 17:49:00 +0200  449) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  450) static sector_t _affs_bmap(struct address_space *mapping, sector_t block)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  451) {
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  452) 	return generic_block_bmap(mapping,block,affs_get_block);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  453) }
f2b6a16eb8f5b (Nicholas Piggin    2007-10-16 01:25:24 -0700  454) 
f5e54d6e53a20 (Christoph Hellwig  2006-06-28 04:26:44 -0700  455) const struct address_space_operations affs_aops = {
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  456) 	.readpage = affs_readpage,
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  457) 	.writepage = affs_writepage,
f2b6a16eb8f5b (Nicholas Piggin    2007-10-16 01:25:24 -0700  458) 	.write_begin = affs_write_begin,
d3a84a8d0dde4 (Max Staudt         2020-08-27 17:49:00 +0200  459) 	.write_end = affs_write_end,
9abb408307008 (Fabian Frederick   2014-12-12 16:57:52 -0800  460) 	.direct_IO = affs_direct_IO,
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  461) 	.bmap = _affs_bmap
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  462) };
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  463) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  464) static inline struct buffer_head *
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  465) affs_bread_ino(struct inode *inode, int block, int create)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  466) {
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  467) 	struct buffer_head *bh, tmp_bh;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  468) 	int err;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  469) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  470) 	tmp_bh.b_state = 0;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  471) 	err = affs_get_block(inode, block, &tmp_bh, create);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  472) 	if (!err) {
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  473) 		bh = affs_bread(inode->i_sb, tmp_bh.b_blocknr);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  474) 		if (bh) {
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  475) 			bh->b_state |= tmp_bh.b_state;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  476) 			return bh;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  477) 		}
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  478) 		err = -EIO;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  479) 	}
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  480) 	return ERR_PTR(err);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  481) }
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  482) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  483) static inline struct buffer_head *
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  484) affs_getzeroblk_ino(struct inode *inode, int block)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  485) {
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  486) 	struct buffer_head *bh, tmp_bh;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  487) 	int err;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  488) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  489) 	tmp_bh.b_state = 0;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  490) 	err = affs_get_block(inode, block, &tmp_bh, 1);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  491) 	if (!err) {
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  492) 		bh = affs_getzeroblk(inode->i_sb, tmp_bh.b_blocknr);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  493) 		if (bh) {
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  494) 			bh->b_state |= tmp_bh.b_state;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  495) 			return bh;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  496) 		}
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  497) 		err = -EIO;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  498) 	}
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  499) 	return ERR_PTR(err);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  500) }
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  501) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  502) static inline struct buffer_head *
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  503) affs_getemptyblk_ino(struct inode *inode, int block)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  504) {
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  505) 	struct buffer_head *bh, tmp_bh;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  506) 	int err;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  507) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  508) 	tmp_bh.b_state = 0;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  509) 	err = affs_get_block(inode, block, &tmp_bh, 1);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  510) 	if (!err) {
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  511) 		bh = affs_getemptyblk(inode->i_sb, tmp_bh.b_blocknr);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  512) 		if (bh) {
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  513) 			bh->b_state |= tmp_bh.b_state;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  514) 			return bh;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  515) 		}
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  516) 		err = -EIO;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  517) 	}
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  518) 	return ERR_PTR(err);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  519) }
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  520) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  521) static int
077e073e8f9eb (Fabian Frederick   2017-04-24 22:12:57 +0200  522) affs_do_readpage_ofs(struct page *page, unsigned to, int create)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  523) {
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  524) 	struct inode *inode = page->mapping->host;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  525) 	struct super_block *sb = inode->i_sb;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  526) 	struct buffer_head *bh;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  527) 	char *data;
0c89d67016081 (Fabian Frederick   2014-06-06 14:37:23 -0700  528) 	unsigned pos = 0;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  529) 	u32 bidx, boff, bsize;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  530) 	u32 tmp;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  531) 
08fe100d91bc0 (Geert Uytterhoeven 2015-02-17 13:46:10 -0800  532) 	pr_debug("%s(%lu, %ld, 0, %d)\n", __func__, inode->i_ino,
0c89d67016081 (Fabian Frederick   2014-06-06 14:37:23 -0700  533) 		 page->index, to);
09cbfeaf1a5a6 (Kirill A. Shutemov 2016-04-01 15:29:47 +0300  534) 	BUG_ON(to > PAGE_SIZE);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  535) 	bsize = AFFS_SB(sb)->s_data_blksize;
09cbfeaf1a5a6 (Kirill A. Shutemov 2016-04-01 15:29:47 +0300  536) 	tmp = page->index << PAGE_SHIFT;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  537) 	bidx = tmp / bsize;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  538) 	boff = tmp % bsize;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  539) 
0c89d67016081 (Fabian Frederick   2014-06-06 14:37:23 -0700  540) 	while (pos < to) {
077e073e8f9eb (Fabian Frederick   2017-04-24 22:12:57 +0200  541) 		bh = affs_bread_ino(inode, bidx, create);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  542) 		if (IS_ERR(bh))
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  543) 			return PTR_ERR(bh);
0c89d67016081 (Fabian Frederick   2014-06-06 14:37:23 -0700  544) 		tmp = min(bsize - boff, to - pos);
0c89d67016081 (Fabian Frederick   2014-06-06 14:37:23 -0700  545) 		BUG_ON(pos + tmp > to || tmp > bsize);
0bacbe528e264 (Al Viro            2016-02-02 02:28:05 +0000  546) 		data = kmap_atomic(page);
0c89d67016081 (Fabian Frederick   2014-06-06 14:37:23 -0700  547) 		memcpy(data + pos, AFFS_DATA(bh) + boff, tmp);
0bacbe528e264 (Al Viro            2016-02-02 02:28:05 +0000  548) 		kunmap_atomic(data);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  549) 		affs_brelse(bh);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  550) 		bidx++;
0c89d67016081 (Fabian Frederick   2014-06-06 14:37:23 -0700  551) 		pos += tmp;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  552) 		boff = 0;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  553) 	}
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  554) 	flush_dcache_page(page);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  555) 	return 0;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  556) }
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  557) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  558) static int
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  559) affs_extent_file_ofs(struct inode *inode, u32 newsize)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  560) {
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  561) 	struct super_block *sb = inode->i_sb;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  562) 	struct buffer_head *bh, *prev_bh;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  563) 	u32 bidx, boff;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  564) 	u32 size, bsize;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  565) 	u32 tmp;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  566) 
08fe100d91bc0 (Geert Uytterhoeven 2015-02-17 13:46:10 -0800  567) 	pr_debug("%s(%lu, %d)\n", __func__, inode->i_ino, newsize);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  568) 	bsize = AFFS_SB(sb)->s_data_blksize;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  569) 	bh = NULL;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  570) 	size = AFFS_I(inode)->mmu_private;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  571) 	bidx = size / bsize;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  572) 	boff = size % bsize;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  573) 	if (boff) {
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  574) 		bh = affs_bread_ino(inode, bidx, 0);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  575) 		if (IS_ERR(bh))
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  576) 			return PTR_ERR(bh);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  577) 		tmp = min(bsize - boff, newsize - size);
8d4b69002e56e (Julia Lawall       2008-04-29 00:59:12 -0700  578) 		BUG_ON(boff + tmp > bsize || tmp > bsize);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  579) 		memset(AFFS_DATA(bh) + boff, 0, tmp);
6369a4abb4866 (Marcin Slusarz     2008-04-30 00:54:47 -0700  580) 		be32_add_cpu(&AFFS_DATA_HEAD(bh)->size, tmp);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  581) 		affs_fix_checksum(sb, bh);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  582) 		mark_buffer_dirty_inode(bh, inode);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  583) 		size += tmp;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  584) 		bidx++;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  585) 	} else if (bidx) {
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  586) 		bh = affs_bread_ino(inode, bidx - 1, 0);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  587) 		if (IS_ERR(bh))
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  588) 			return PTR_ERR(bh);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  589) 	}
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  590) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  591) 	while (size < newsize) {
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  592) 		prev_bh = bh;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  593) 		bh = affs_getzeroblk_ino(inode, bidx);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  594) 		if (IS_ERR(bh))
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  595) 			goto out;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  596) 		tmp = min(bsize, newsize - size);
8d4b69002e56e (Julia Lawall       2008-04-29 00:59:12 -0700  597) 		BUG_ON(tmp > bsize);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  598) 		AFFS_DATA_HEAD(bh)->ptype = cpu_to_be32(T_DATA);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  599) 		AFFS_DATA_HEAD(bh)->key = cpu_to_be32(inode->i_ino);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  600) 		AFFS_DATA_HEAD(bh)->sequence = cpu_to_be32(bidx);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  601) 		AFFS_DATA_HEAD(bh)->size = cpu_to_be32(tmp);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  602) 		affs_fix_checksum(sb, bh);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  603) 		bh->b_state &= ~(1UL << BH_New);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  604) 		mark_buffer_dirty_inode(bh, inode);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  605) 		if (prev_bh) {
73516ace940a7 (Fabian Frederick   2014-10-13 15:53:54 -0700  606) 			u32 tmp_next = be32_to_cpu(AFFS_DATA_HEAD(prev_bh)->next);
73516ace940a7 (Fabian Frederick   2014-10-13 15:53:54 -0700  607) 
73516ace940a7 (Fabian Frederick   2014-10-13 15:53:54 -0700  608) 			if (tmp_next)
73516ace940a7 (Fabian Frederick   2014-10-13 15:53:54 -0700  609) 				affs_warning(sb, "extent_file_ofs",
73516ace940a7 (Fabian Frederick   2014-10-13 15:53:54 -0700  610) 					     "next block already set for %d (%d)",
73516ace940a7 (Fabian Frederick   2014-10-13 15:53:54 -0700  611) 					     bidx, tmp_next);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  612) 			AFFS_DATA_HEAD(prev_bh)->next = cpu_to_be32(bh->b_blocknr);
73516ace940a7 (Fabian Frederick   2014-10-13 15:53:54 -0700  613) 			affs_adjust_checksum(prev_bh, bh->b_blocknr - tmp_next);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  614) 			mark_buffer_dirty_inode(prev_bh, inode);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  615) 			affs_brelse(prev_bh);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  616) 		}
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  617) 		size += bsize;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  618) 		bidx++;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  619) 	}
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  620) 	affs_brelse(bh);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  621) 	inode->i_size = AFFS_I(inode)->mmu_private = newsize;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  622) 	return 0;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  623) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  624) out:
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  625) 	inode->i_size = AFFS_I(inode)->mmu_private = newsize;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  626) 	return PTR_ERR(bh);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  627) }
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  628) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  629) static int
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  630) affs_readpage_ofs(struct file *file, struct page *page)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  631) {
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  632) 	struct inode *inode = page->mapping->host;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  633) 	u32 to;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  634) 	int err;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  635) 
08fe100d91bc0 (Geert Uytterhoeven 2015-02-17 13:46:10 -0800  636) 	pr_debug("%s(%lu, %ld)\n", __func__, inode->i_ino, page->index);
09cbfeaf1a5a6 (Kirill A. Shutemov 2016-04-01 15:29:47 +0300  637) 	to = PAGE_SIZE;
09cbfeaf1a5a6 (Kirill A. Shutemov 2016-04-01 15:29:47 +0300  638) 	if (((page->index + 1) << PAGE_SHIFT) > inode->i_size) {
09cbfeaf1a5a6 (Kirill A. Shutemov 2016-04-01 15:29:47 +0300  639) 		to = inode->i_size & ~PAGE_MASK;
09cbfeaf1a5a6 (Kirill A. Shutemov 2016-04-01 15:29:47 +0300  640) 		memset(page_address(page) + to, 0, PAGE_SIZE - to);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  641) 	}
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  642) 
077e073e8f9eb (Fabian Frederick   2017-04-24 22:12:57 +0200  643) 	err = affs_do_readpage_ofs(page, to, 0);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  644) 	if (!err)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  645) 		SetPageUptodate(page);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  646) 	unlock_page(page);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  647) 	return err;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  648) }
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  649) 
f2b6a16eb8f5b (Nicholas Piggin    2007-10-16 01:25:24 -0700  650) static int affs_write_begin_ofs(struct file *file, struct address_space *mapping,
f2b6a16eb8f5b (Nicholas Piggin    2007-10-16 01:25:24 -0700  651) 				loff_t pos, unsigned len, unsigned flags,
f2b6a16eb8f5b (Nicholas Piggin    2007-10-16 01:25:24 -0700  652) 				struct page **pagep, void **fsdata)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  653) {
f2b6a16eb8f5b (Nicholas Piggin    2007-10-16 01:25:24 -0700  654) 	struct inode *inode = mapping->host;
f2b6a16eb8f5b (Nicholas Piggin    2007-10-16 01:25:24 -0700  655) 	struct page *page;
f2b6a16eb8f5b (Nicholas Piggin    2007-10-16 01:25:24 -0700  656) 	pgoff_t index;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  657) 	int err = 0;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  658) 
08fe100d91bc0 (Geert Uytterhoeven 2015-02-17 13:46:10 -0800  659) 	pr_debug("%s(%lu, %llu, %llu)\n", __func__, inode->i_ino, pos,
08fe100d91bc0 (Geert Uytterhoeven 2015-02-17 13:46:10 -0800  660) 		 pos + len);
f2b6a16eb8f5b (Nicholas Piggin    2007-10-16 01:25:24 -0700  661) 	if (pos > AFFS_I(inode)->mmu_private) {
f2b6a16eb8f5b (Nicholas Piggin    2007-10-16 01:25:24 -0700  662) 		/* XXX: this probably leaves a too-big i_size in case of
f2b6a16eb8f5b (Nicholas Piggin    2007-10-16 01:25:24 -0700  663) 		 * failure. Should really be updating i_size at write_end time
f2b6a16eb8f5b (Nicholas Piggin    2007-10-16 01:25:24 -0700  664) 		 */
f2b6a16eb8f5b (Nicholas Piggin    2007-10-16 01:25:24 -0700  665) 		err = affs_extent_file_ofs(inode, pos);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  666) 		if (err)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  667) 			return err;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  668) 	}
f2b6a16eb8f5b (Nicholas Piggin    2007-10-16 01:25:24 -0700  669) 
09cbfeaf1a5a6 (Kirill A. Shutemov 2016-04-01 15:29:47 +0300  670) 	index = pos >> PAGE_SHIFT;
54566b2c1594c (Nicholas Piggin    2009-01-04 12:00:53 -0800  671) 	page = grab_cache_page_write_begin(mapping, index, flags);
f2b6a16eb8f5b (Nicholas Piggin    2007-10-16 01:25:24 -0700  672) 	if (!page)
f2b6a16eb8f5b (Nicholas Piggin    2007-10-16 01:25:24 -0700  673) 		return -ENOMEM;
f2b6a16eb8f5b (Nicholas Piggin    2007-10-16 01:25:24 -0700  674) 	*pagep = page;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  675) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  676) 	if (PageUptodate(page))
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  677) 		return 0;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  678) 
f2b6a16eb8f5b (Nicholas Piggin    2007-10-16 01:25:24 -0700  679) 	/* XXX: inefficient but safe in the face of short writes */
077e073e8f9eb (Fabian Frederick   2017-04-24 22:12:57 +0200  680) 	err = affs_do_readpage_ofs(page, PAGE_SIZE, 1);
f2b6a16eb8f5b (Nicholas Piggin    2007-10-16 01:25:24 -0700  681) 	if (err) {
f2b6a16eb8f5b (Nicholas Piggin    2007-10-16 01:25:24 -0700  682) 		unlock_page(page);
09cbfeaf1a5a6 (Kirill A. Shutemov 2016-04-01 15:29:47 +0300  683) 		put_page(page);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  684) 	}
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  685) 	return err;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  686) }
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  687) 
f2b6a16eb8f5b (Nicholas Piggin    2007-10-16 01:25:24 -0700  688) static int affs_write_end_ofs(struct file *file, struct address_space *mapping,
f2b6a16eb8f5b (Nicholas Piggin    2007-10-16 01:25:24 -0700  689) 				loff_t pos, unsigned len, unsigned copied,
f2b6a16eb8f5b (Nicholas Piggin    2007-10-16 01:25:24 -0700  690) 				struct page *page, void *fsdata)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  691) {
f2b6a16eb8f5b (Nicholas Piggin    2007-10-16 01:25:24 -0700  692) 	struct inode *inode = mapping->host;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  693) 	struct super_block *sb = inode->i_sb;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  694) 	struct buffer_head *bh, *prev_bh;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  695) 	char *data;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  696) 	u32 bidx, boff, bsize;
f2b6a16eb8f5b (Nicholas Piggin    2007-10-16 01:25:24 -0700  697) 	unsigned from, to;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  698) 	u32 tmp;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  699) 	int written;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  700) 
09cbfeaf1a5a6 (Kirill A. Shutemov 2016-04-01 15:29:47 +0300  701) 	from = pos & (PAGE_SIZE - 1);
a80f2d2224544 (Fabian Frederick   2017-04-24 22:13:10 +0200  702) 	to = from + len;
f2b6a16eb8f5b (Nicholas Piggin    2007-10-16 01:25:24 -0700  703) 	/*
f2b6a16eb8f5b (Nicholas Piggin    2007-10-16 01:25:24 -0700  704) 	 * XXX: not sure if this can handle short copies (len < copied), but
f2b6a16eb8f5b (Nicholas Piggin    2007-10-16 01:25:24 -0700  705) 	 * we don't have to, because the page should always be uptodate here,
f2b6a16eb8f5b (Nicholas Piggin    2007-10-16 01:25:24 -0700  706) 	 * due to write_begin.
f2b6a16eb8f5b (Nicholas Piggin    2007-10-16 01:25:24 -0700  707) 	 */
f2b6a16eb8f5b (Nicholas Piggin    2007-10-16 01:25:24 -0700  708) 
08fe100d91bc0 (Geert Uytterhoeven 2015-02-17 13:46:10 -0800  709) 	pr_debug("%s(%lu, %llu, %llu)\n", __func__, inode->i_ino, pos,
08fe100d91bc0 (Geert Uytterhoeven 2015-02-17 13:46:10 -0800  710) 		 pos + len);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  711) 	bsize = AFFS_SB(sb)->s_data_blksize;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  712) 	data = page_address(page);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  713) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  714) 	bh = NULL;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  715) 	written = 0;
09cbfeaf1a5a6 (Kirill A. Shutemov 2016-04-01 15:29:47 +0300  716) 	tmp = (page->index << PAGE_SHIFT) + from;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  717) 	bidx = tmp / bsize;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  718) 	boff = tmp % bsize;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  719) 	if (boff) {
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  720) 		bh = affs_bread_ino(inode, bidx, 0);
3d5d472cf55d1 (Taesoo Kim         2015-03-25 15:55:29 -0700  721) 		if (IS_ERR(bh)) {
3d5d472cf55d1 (Taesoo Kim         2015-03-25 15:55:29 -0700  722) 			written = PTR_ERR(bh);
3d5d472cf55d1 (Taesoo Kim         2015-03-25 15:55:29 -0700  723) 			goto err_first_bh;
3d5d472cf55d1 (Taesoo Kim         2015-03-25 15:55:29 -0700  724) 		}
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  725) 		tmp = min(bsize - boff, to - from);
8d4b69002e56e (Julia Lawall       2008-04-29 00:59:12 -0700  726) 		BUG_ON(boff + tmp > bsize || tmp > bsize);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  727) 		memcpy(AFFS_DATA(bh) + boff, data + from, tmp);
6369a4abb4866 (Marcin Slusarz     2008-04-30 00:54:47 -0700  728) 		be32_add_cpu(&AFFS_DATA_HEAD(bh)->size, tmp);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  729) 		affs_fix_checksum(sb, bh);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  730) 		mark_buffer_dirty_inode(bh, inode);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  731) 		written += tmp;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  732) 		from += tmp;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  733) 		bidx++;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  734) 	} else if (bidx) {
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  735) 		bh = affs_bread_ino(inode, bidx - 1, 0);
3d5d472cf55d1 (Taesoo Kim         2015-03-25 15:55:29 -0700  736) 		if (IS_ERR(bh)) {
3d5d472cf55d1 (Taesoo Kim         2015-03-25 15:55:29 -0700  737) 			written = PTR_ERR(bh);
3d5d472cf55d1 (Taesoo Kim         2015-03-25 15:55:29 -0700  738) 			goto err_first_bh;
3d5d472cf55d1 (Taesoo Kim         2015-03-25 15:55:29 -0700  739) 		}
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  740) 	}
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  741) 	while (from + bsize <= to) {
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  742) 		prev_bh = bh;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  743) 		bh = affs_getemptyblk_ino(inode, bidx);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  744) 		if (IS_ERR(bh))
3d5d472cf55d1 (Taesoo Kim         2015-03-25 15:55:29 -0700  745) 			goto err_bh;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  746) 		memcpy(AFFS_DATA(bh), data + from, bsize);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  747) 		if (buffer_new(bh)) {
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  748) 			AFFS_DATA_HEAD(bh)->ptype = cpu_to_be32(T_DATA);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  749) 			AFFS_DATA_HEAD(bh)->key = cpu_to_be32(inode->i_ino);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  750) 			AFFS_DATA_HEAD(bh)->sequence = cpu_to_be32(bidx);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  751) 			AFFS_DATA_HEAD(bh)->size = cpu_to_be32(bsize);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  752) 			AFFS_DATA_HEAD(bh)->next = 0;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  753) 			bh->b_state &= ~(1UL << BH_New);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  754) 			if (prev_bh) {
73516ace940a7 (Fabian Frederick   2014-10-13 15:53:54 -0700  755) 				u32 tmp_next = be32_to_cpu(AFFS_DATA_HEAD(prev_bh)->next);
73516ace940a7 (Fabian Frederick   2014-10-13 15:53:54 -0700  756) 
73516ace940a7 (Fabian Frederick   2014-10-13 15:53:54 -0700  757) 				if (tmp_next)
73516ace940a7 (Fabian Frederick   2014-10-13 15:53:54 -0700  758) 					affs_warning(sb, "commit_write_ofs",
73516ace940a7 (Fabian Frederick   2014-10-13 15:53:54 -0700  759) 						     "next block already set for %d (%d)",
73516ace940a7 (Fabian Frederick   2014-10-13 15:53:54 -0700  760) 						     bidx, tmp_next);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  761) 				AFFS_DATA_HEAD(prev_bh)->next = cpu_to_be32(bh->b_blocknr);
73516ace940a7 (Fabian Frederick   2014-10-13 15:53:54 -0700  762) 				affs_adjust_checksum(prev_bh, bh->b_blocknr - tmp_next);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  763) 				mark_buffer_dirty_inode(prev_bh, inode);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  764) 			}
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  765) 		}
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  766) 		affs_brelse(prev_bh);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  767) 		affs_fix_checksum(sb, bh);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  768) 		mark_buffer_dirty_inode(bh, inode);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  769) 		written += bsize;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  770) 		from += bsize;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  771) 		bidx++;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  772) 	}
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  773) 	if (from < to) {
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  774) 		prev_bh = bh;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  775) 		bh = affs_bread_ino(inode, bidx, 1);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  776) 		if (IS_ERR(bh))
3d5d472cf55d1 (Taesoo Kim         2015-03-25 15:55:29 -0700  777) 			goto err_bh;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  778) 		tmp = min(bsize, to - from);
8d4b69002e56e (Julia Lawall       2008-04-29 00:59:12 -0700  779) 		BUG_ON(tmp > bsize);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  780) 		memcpy(AFFS_DATA(bh), data + from, tmp);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  781) 		if (buffer_new(bh)) {
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  782) 			AFFS_DATA_HEAD(bh)->ptype = cpu_to_be32(T_DATA);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  783) 			AFFS_DATA_HEAD(bh)->key = cpu_to_be32(inode->i_ino);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  784) 			AFFS_DATA_HEAD(bh)->sequence = cpu_to_be32(bidx);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  785) 			AFFS_DATA_HEAD(bh)->size = cpu_to_be32(tmp);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  786) 			AFFS_DATA_HEAD(bh)->next = 0;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  787) 			bh->b_state &= ~(1UL << BH_New);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  788) 			if (prev_bh) {
73516ace940a7 (Fabian Frederick   2014-10-13 15:53:54 -0700  789) 				u32 tmp_next = be32_to_cpu(AFFS_DATA_HEAD(prev_bh)->next);
73516ace940a7 (Fabian Frederick   2014-10-13 15:53:54 -0700  790) 
73516ace940a7 (Fabian Frederick   2014-10-13 15:53:54 -0700  791) 				if (tmp_next)
73516ace940a7 (Fabian Frederick   2014-10-13 15:53:54 -0700  792) 					affs_warning(sb, "commit_write_ofs",
73516ace940a7 (Fabian Frederick   2014-10-13 15:53:54 -0700  793) 						     "next block already set for %d (%d)",
73516ace940a7 (Fabian Frederick   2014-10-13 15:53:54 -0700  794) 						     bidx, tmp_next);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  795) 				AFFS_DATA_HEAD(prev_bh)->next = cpu_to_be32(bh->b_blocknr);
73516ace940a7 (Fabian Frederick   2014-10-13 15:53:54 -0700  796) 				affs_adjust_checksum(prev_bh, bh->b_blocknr - tmp_next);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  797) 				mark_buffer_dirty_inode(prev_bh, inode);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  798) 			}
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  799) 		} else if (be32_to_cpu(AFFS_DATA_HEAD(bh)->size) < tmp)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  800) 			AFFS_DATA_HEAD(bh)->size = cpu_to_be32(tmp);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  801) 		affs_brelse(prev_bh);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  802) 		affs_fix_checksum(sb, bh);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  803) 		mark_buffer_dirty_inode(bh, inode);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  804) 		written += tmp;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  805) 		from += tmp;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  806) 		bidx++;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  807) 	}
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  808) 	SetPageUptodate(page);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  809) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  810) done:
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  811) 	affs_brelse(bh);
09cbfeaf1a5a6 (Kirill A. Shutemov 2016-04-01 15:29:47 +0300  812) 	tmp = (page->index << PAGE_SHIFT) + from;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  813) 	if (tmp > inode->i_size)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  814) 		inode->i_size = AFFS_I(inode)->mmu_private = tmp;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  815) 
d3a84a8d0dde4 (Max Staudt         2020-08-27 17:49:00 +0200  816) 	/* Clear Archived bit on file writes, as AmigaOS would do */
d3a84a8d0dde4 (Max Staudt         2020-08-27 17:49:00 +0200  817) 	if (AFFS_I(inode)->i_protect & FIBF_ARCHIVED) {
d3a84a8d0dde4 (Max Staudt         2020-08-27 17:49:00 +0200  818) 		AFFS_I(inode)->i_protect &= ~FIBF_ARCHIVED;
d3a84a8d0dde4 (Max Staudt         2020-08-27 17:49:00 +0200  819) 		mark_inode_dirty(inode);
d3a84a8d0dde4 (Max Staudt         2020-08-27 17:49:00 +0200  820) 	}
d3a84a8d0dde4 (Max Staudt         2020-08-27 17:49:00 +0200  821) 
3d5d472cf55d1 (Taesoo Kim         2015-03-25 15:55:29 -0700  822) err_first_bh:
f2b6a16eb8f5b (Nicholas Piggin    2007-10-16 01:25:24 -0700  823) 	unlock_page(page);
09cbfeaf1a5a6 (Kirill A. Shutemov 2016-04-01 15:29:47 +0300  824) 	put_page(page);
f2b6a16eb8f5b (Nicholas Piggin    2007-10-16 01:25:24 -0700  825) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  826) 	return written;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  827) 
3d5d472cf55d1 (Taesoo Kim         2015-03-25 15:55:29 -0700  828) err_bh:
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  829) 	bh = prev_bh;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  830) 	if (!written)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  831) 		written = PTR_ERR(bh);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  832) 	goto done;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  833) }
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  834) 
f5e54d6e53a20 (Christoph Hellwig  2006-06-28 04:26:44 -0700  835) const struct address_space_operations affs_aops_ofs = {
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  836) 	.readpage = affs_readpage_ofs,
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  837) 	//.writepage = affs_writepage_ofs,
f2b6a16eb8f5b (Nicholas Piggin    2007-10-16 01:25:24 -0700  838) 	.write_begin = affs_write_begin_ofs,
f2b6a16eb8f5b (Nicholas Piggin    2007-10-16 01:25:24 -0700  839) 	.write_end = affs_write_end_ofs
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  840) };
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  841) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  842) /* Free any preallocated blocks. */
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  843) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  844) void
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  845) affs_free_prealloc(struct inode *inode)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  846) {
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  847) 	struct super_block *sb = inode->i_sb;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  848) 
9606d9aa858ae (Fabian Frederick   2014-06-06 14:37:25 -0700  849) 	pr_debug("free_prealloc(ino=%lu)\n", inode->i_ino);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  850) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  851) 	while (AFFS_I(inode)->i_pa_cnt) {
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  852) 		AFFS_I(inode)->i_pa_cnt--;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  853) 		affs_free_block(sb, ++AFFS_I(inode)->i_lastalloc);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  854) 	}
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  855) }
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  856) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  857) /* Truncate (or enlarge) a file to the requested size. */
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  858) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  859) void
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  860) affs_truncate(struct inode *inode)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  861) {
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  862) 	struct super_block *sb = inode->i_sb;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  863) 	u32 ext, ext_key;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  864) 	u32 last_blk, blkcnt, blk;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  865) 	u32 size;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  866) 	struct buffer_head *ext_bh;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  867) 	int i;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  868) 
08fe100d91bc0 (Geert Uytterhoeven 2015-02-17 13:46:10 -0800  869) 	pr_debug("truncate(inode=%lu, oldsize=%llu, newsize=%llu)\n",
08fe100d91bc0 (Geert Uytterhoeven 2015-02-17 13:46:10 -0800  870) 		 inode->i_ino, AFFS_I(inode)->mmu_private, inode->i_size);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  871) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  872) 	last_blk = 0;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  873) 	ext = 0;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  874) 	if (inode->i_size) {
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  875) 		last_blk = ((u32)inode->i_size - 1) / AFFS_SB(sb)->s_data_blksize;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  876) 		ext = last_blk / AFFS_SB(sb)->s_hashsize;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  877) 	}
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  878) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  879) 	if (inode->i_size > AFFS_I(inode)->mmu_private) {
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  880) 		struct address_space *mapping = inode->i_mapping;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  881) 		struct page *page;
f2b6a16eb8f5b (Nicholas Piggin    2007-10-16 01:25:24 -0700  882) 		void *fsdata;
73516ace940a7 (Fabian Frederick   2014-10-13 15:53:54 -0700  883) 		loff_t isize = inode->i_size;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  884) 		int res;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  885) 
73516ace940a7 (Fabian Frederick   2014-10-13 15:53:54 -0700  886) 		res = mapping->a_ops->write_begin(NULL, mapping, isize, 0, 0, &page, &fsdata);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  887) 		if (!res)
73516ace940a7 (Fabian Frederick   2014-10-13 15:53:54 -0700  888) 			res = mapping->a_ops->write_end(NULL, mapping, isize, 0, 0, page, fsdata);
dca3c33652e43 (Roman Zippel       2008-04-29 17:02:20 +0200  889) 		else
dca3c33652e43 (Roman Zippel       2008-04-29 17:02:20 +0200  890) 			inode->i_size = AFFS_I(inode)->mmu_private;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  891) 		mark_inode_dirty(inode);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  892) 		return;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  893) 	} else if (inode->i_size == AFFS_I(inode)->mmu_private)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  894) 		return;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  895) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  896) 	// lock cache
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  897) 	ext_bh = affs_get_extblock(inode, ext);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  898) 	if (IS_ERR(ext_bh)) {
1ee54b099acec (Fabian Frederick   2014-12-12 16:57:49 -0800  899) 		affs_warning(sb, "truncate",
1ee54b099acec (Fabian Frederick   2014-12-12 16:57:49 -0800  900) 			     "unexpected read error for ext block %u (%ld)",
08fe100d91bc0 (Geert Uytterhoeven 2015-02-17 13:46:10 -0800  901) 			     ext, PTR_ERR(ext_bh));
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  902) 		return;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  903) 	}
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  904) 	if (AFFS_I(inode)->i_lc) {
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  905) 		/* clear linear cache */
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  906) 		i = (ext + 1) >> AFFS_I(inode)->i_lc_shift;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  907) 		if (AFFS_I(inode)->i_lc_size > i) {
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  908) 			AFFS_I(inode)->i_lc_size = i;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  909) 			for (; i < AFFS_LC_SIZE; i++)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  910) 				AFFS_I(inode)->i_lc[i] = 0;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  911) 		}
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  912) 		/* clear associative cache */
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  913) 		for (i = 0; i < AFFS_AC_SIZE; i++)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  914) 			if (AFFS_I(inode)->i_ac[i].ext >= ext)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  915) 				AFFS_I(inode)->i_ac[i].ext = 0;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  916) 	}
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  917) 	ext_key = be32_to_cpu(AFFS_TAIL(sb, ext_bh)->extension);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  918) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  919) 	blkcnt = AFFS_I(inode)->i_blkcnt;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  920) 	i = 0;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  921) 	blk = last_blk;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  922) 	if (inode->i_size) {
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  923) 		i = last_blk % AFFS_SB(sb)->s_hashsize + 1;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  924) 		blk++;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  925) 	} else
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  926) 		AFFS_HEAD(ext_bh)->first_data = 0;
dca3c33652e43 (Roman Zippel       2008-04-29 17:02:20 +0200  927) 	AFFS_HEAD(ext_bh)->block_count = cpu_to_be32(i);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  928) 	size = AFFS_SB(sb)->s_hashsize;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  929) 	if (size > blkcnt - blk + i)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  930) 		size = blkcnt - blk + i;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  931) 	for (; i < size; i++, blk++) {
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  932) 		affs_free_block(sb, be32_to_cpu(AFFS_BLOCK(sb, ext_bh, i)));
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  933) 		AFFS_BLOCK(sb, ext_bh, i) = 0;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  934) 	}
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  935) 	AFFS_TAIL(sb, ext_bh)->extension = 0;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  936) 	affs_fix_checksum(sb, ext_bh);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  937) 	mark_buffer_dirty_inode(ext_bh, inode);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  938) 	affs_brelse(ext_bh);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  939) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  940) 	if (inode->i_size) {
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  941) 		AFFS_I(inode)->i_blkcnt = last_blk + 1;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  942) 		AFFS_I(inode)->i_extcnt = ext + 1;
79bda4d510f80 (Fabian Frederick   2015-04-16 12:48:24 -0700  943) 		if (affs_test_opt(AFFS_SB(sb)->s_flags, SF_OFS)) {
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  944) 			struct buffer_head *bh = affs_bread_ino(inode, last_blk, 0);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  945) 			u32 tmp;
0e45b67d5aeb3 (Dan Carpenter      2010-08-25 09:05:27 +0200  946) 			if (IS_ERR(bh)) {
1ee54b099acec (Fabian Frederick   2014-12-12 16:57:49 -0800  947) 				affs_warning(sb, "truncate",
1ee54b099acec (Fabian Frederick   2014-12-12 16:57:49 -0800  948) 					     "unexpected read error for last block %u (%ld)",
08fe100d91bc0 (Geert Uytterhoeven 2015-02-17 13:46:10 -0800  949) 					     ext, PTR_ERR(bh));
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  950) 				return;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  951) 			}
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  952) 			tmp = be32_to_cpu(AFFS_DATA_HEAD(bh)->next);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  953) 			AFFS_DATA_HEAD(bh)->next = 0;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  954) 			affs_adjust_checksum(bh, -tmp);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  955) 			affs_brelse(bh);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  956) 		}
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  957) 	} else {
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  958) 		AFFS_I(inode)->i_blkcnt = 0;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  959) 		AFFS_I(inode)->i_extcnt = 1;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  960) 	}
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  961) 	AFFS_I(inode)->mmu_private = inode->i_size;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  962) 	// unlock cache
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  963) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  964) 	while (ext_key) {
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  965) 		ext_bh = affs_bread(sb, ext_key);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  966) 		size = AFFS_SB(sb)->s_hashsize;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  967) 		if (size > blkcnt - blk)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  968) 			size = blkcnt - blk;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  969) 		for (i = 0; i < size; i++, blk++)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  970) 			affs_free_block(sb, be32_to_cpu(AFFS_BLOCK(sb, ext_bh, i)));
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  971) 		affs_free_block(sb, ext_key);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  972) 		ext_key = be32_to_cpu(AFFS_TAIL(sb, ext_bh)->extension);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  973) 		affs_brelse(ext_bh);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  974) 	}
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  975) 	affs_free_prealloc(inode);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  976) }
c475879556a86 (Al Viro            2009-06-08 01:22:00 -0400  977) 
02c24a82187d5 (Josef Bacik        2011-07-16 20:44:56 -0400  978) int affs_file_fsync(struct file *filp, loff_t start, loff_t end, int datasync)
c475879556a86 (Al Viro            2009-06-08 01:22:00 -0400  979) {
7ea8085910ef3 (Christoph Hellwig  2010-05-26 17:53:25 +0200  980) 	struct inode *inode = filp->f_mapping->host;
c475879556a86 (Al Viro            2009-06-08 01:22:00 -0400  981) 	int ret, err;
c475879556a86 (Al Viro            2009-06-08 01:22:00 -0400  982) 
3b49c9a1e984b (Jeff Layton        2017-07-07 15:20:52 -0400  983) 	err = file_write_and_wait_range(filp, start, end);
02c24a82187d5 (Josef Bacik        2011-07-16 20:44:56 -0400  984) 	if (err)
02c24a82187d5 (Josef Bacik        2011-07-16 20:44:56 -0400  985) 		return err;
02c24a82187d5 (Josef Bacik        2011-07-16 20:44:56 -0400  986) 
5955102c9984f (Al Viro            2016-01-22 15:40:57 -0500  987) 	inode_lock(inode);
c475879556a86 (Al Viro            2009-06-08 01:22:00 -0400  988) 	ret = write_inode_now(inode, 0);
c475879556a86 (Al Viro            2009-06-08 01:22:00 -0400  989) 	err = sync_blockdev(inode->i_sb->s_bdev);
c475879556a86 (Al Viro            2009-06-08 01:22:00 -0400  990) 	if (!ret)
c475879556a86 (Al Viro            2009-06-08 01:22:00 -0400  991) 		ret = err;
5955102c9984f (Al Viro            2016-01-22 15:40:57 -0500  992) 	inode_unlock(inode);
c475879556a86 (Al Viro            2009-06-08 01:22:00 -0400  993) 	return ret;
c475879556a86 (Al Viro            2009-06-08 01:22:00 -0400  994) }
7633978b43ebe (Fabian Frederick   2014-12-12 16:57:47 -0800  995) const struct file_operations affs_file_operations = {
7633978b43ebe (Fabian Frederick   2014-12-12 16:57:47 -0800  996) 	.llseek		= generic_file_llseek,
7633978b43ebe (Fabian Frederick   2014-12-12 16:57:47 -0800  997) 	.read_iter	= generic_file_read_iter,
7633978b43ebe (Fabian Frederick   2014-12-12 16:57:47 -0800  998) 	.write_iter	= generic_file_write_iter,
7633978b43ebe (Fabian Frederick   2014-12-12 16:57:47 -0800  999) 	.mmap		= generic_file_mmap,
7633978b43ebe (Fabian Frederick   2014-12-12 16:57:47 -0800 1000) 	.open		= affs_file_open,
7633978b43ebe (Fabian Frederick   2014-12-12 16:57:47 -0800 1001) 	.release	= affs_file_release,
7633978b43ebe (Fabian Frederick   2014-12-12 16:57:47 -0800 1002) 	.fsync		= affs_file_fsync,
7633978b43ebe (Fabian Frederick   2014-12-12 16:57:47 -0800 1003) 	.splice_read	= generic_file_splice_read,
7633978b43ebe (Fabian Frederick   2014-12-12 16:57:47 -0800 1004) };
7633978b43ebe (Fabian Frederick   2014-12-12 16:57:47 -0800 1005) 
7633978b43ebe (Fabian Frederick   2014-12-12 16:57:47 -0800 1006) const struct inode_operations affs_file_inode_operations = {
7633978b43ebe (Fabian Frederick   2014-12-12 16:57:47 -0800 1007) 	.setattr	= affs_notify_change,
7633978b43ebe (Fabian Frederick   2014-12-12 16:57:47 -0800 1008) };