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) };