^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) * linux/fs/hfs/extent.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Copyright (C) 1995-1997 Paul H. Hargrove
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * (C) 2003 Ardis Technologies <roman@ardistech.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * This file may be distributed under the terms of the GNU General Public License.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * This file contains the functions related to the extents B-tree.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/pagemap.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include "hfs_fs.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include "btree.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) /*================ File-local functions ================*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) * build_key
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) static void hfs_ext_build_key(hfs_btree_key *key, u32 cnid, u16 block, u8 type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) key->key_len = 7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) key->ext.FkType = type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) key->ext.FNum = cpu_to_be32(cnid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) key->ext.FABN = cpu_to_be16(block);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) * hfs_ext_compare()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) * Description:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) * This is the comparison function used for the extents B-tree. In
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) * comparing extent B-tree entries, the file id is the most
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) * significant field (compared as unsigned ints); the fork type is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) * the second most significant field (compared as unsigned chars);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) * and the allocation block number field is the least significant
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) * (compared as unsigned ints).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) * Input Variable(s):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) * struct hfs_ext_key *key1: pointer to the first key to compare
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) * struct hfs_ext_key *key2: pointer to the second key to compare
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) * Output Variable(s):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) * NONE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) * Returns:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) * int: negative if key1<key2, positive if key1>key2, and 0 if key1==key2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) * Preconditions:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) * key1 and key2 point to "valid" (struct hfs_ext_key)s.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) * Postconditions:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) * This function has no side-effects */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) int hfs_ext_keycmp(const btree_key *key1, const btree_key *key2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) __be32 fnum1, fnum2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) __be16 block1, block2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) fnum1 = key1->ext.FNum;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) fnum2 = key2->ext.FNum;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) if (fnum1 != fnum2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) return be32_to_cpu(fnum1) < be32_to_cpu(fnum2) ? -1 : 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) if (key1->ext.FkType != key2->ext.FkType)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) return key1->ext.FkType < key2->ext.FkType ? -1 : 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) block1 = key1->ext.FABN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) block2 = key2->ext.FABN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) if (block1 == block2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) return be16_to_cpu(block1) < be16_to_cpu(block2) ? -1 : 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) * hfs_ext_find_block
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) * Find a block within an extent record
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) static u16 hfs_ext_find_block(struct hfs_extent *ext, u16 off)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) u16 count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) for (i = 0; i < 3; ext++, i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) count = be16_to_cpu(ext->count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) if (off < count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) return be16_to_cpu(ext->block) + off;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) off -= count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) /* panic? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) static int hfs_ext_block_count(struct hfs_extent *ext)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) u16 count = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) for (i = 0; i < 3; ext++, i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) count += be16_to_cpu(ext->count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) return count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) static u16 hfs_ext_lastblock(struct hfs_extent *ext)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) ext += 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) for (i = 0; i < 2; ext--, i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) if (ext->count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) return be16_to_cpu(ext->block) + be16_to_cpu(ext->count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) static int __hfs_ext_write_extent(struct inode *inode, struct hfs_find_data *fd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) int res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) hfs_ext_build_key(fd->search_key, inode->i_ino, HFS_I(inode)->cached_start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) HFS_IS_RSRC(inode) ? HFS_FK_RSRC : HFS_FK_DATA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) res = hfs_brec_find(fd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) if (HFS_I(inode)->flags & HFS_FLG_EXT_NEW) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) if (res != -ENOENT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) /* Fail early and avoid ENOSPC during the btree operation */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) res = hfs_bmap_reserve(fd->tree, fd->tree->depth + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) if (res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) hfs_brec_insert(fd, HFS_I(inode)->cached_extents, sizeof(hfs_extent_rec));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) HFS_I(inode)->flags &= ~(HFS_FLG_EXT_DIRTY|HFS_FLG_EXT_NEW);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) if (res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) hfs_bnode_write(fd->bnode, HFS_I(inode)->cached_extents, fd->entryoffset, fd->entrylength);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) HFS_I(inode)->flags &= ~HFS_FLG_EXT_DIRTY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) int hfs_ext_write_extent(struct inode *inode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) struct hfs_find_data fd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) int res = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) if (HFS_I(inode)->flags & HFS_FLG_EXT_DIRTY) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) res = hfs_find_init(HFS_SB(inode->i_sb)->ext_tree, &fd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) if (res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) res = __hfs_ext_write_extent(inode, &fd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) hfs_find_exit(&fd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) static inline int __hfs_ext_read_extent(struct hfs_find_data *fd, struct hfs_extent *extent,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) u32 cnid, u32 block, u8 type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) int res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) hfs_ext_build_key(fd->search_key, cnid, block, type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) fd->key->ext.FNum = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) res = hfs_brec_find(fd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) if (res && res != -ENOENT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) if (fd->key->ext.FNum != fd->search_key->ext.FNum ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) fd->key->ext.FkType != fd->search_key->ext.FkType)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) return -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) if (fd->entrylength != sizeof(hfs_extent_rec))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) hfs_bnode_read(fd->bnode, extent, fd->entryoffset, sizeof(hfs_extent_rec));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) static inline int __hfs_ext_cache_extent(struct hfs_find_data *fd, struct inode *inode, u32 block)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) int res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) if (HFS_I(inode)->flags & HFS_FLG_EXT_DIRTY) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) res = __hfs_ext_write_extent(inode, fd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) if (res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) res = __hfs_ext_read_extent(fd, HFS_I(inode)->cached_extents, inode->i_ino,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) block, HFS_IS_RSRC(inode) ? HFS_FK_RSRC : HFS_FK_DATA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) if (!res) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) HFS_I(inode)->cached_start = be16_to_cpu(fd->key->ext.FABN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) HFS_I(inode)->cached_blocks = hfs_ext_block_count(HFS_I(inode)->cached_extents);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) HFS_I(inode)->cached_start = HFS_I(inode)->cached_blocks = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) HFS_I(inode)->flags &= ~(HFS_FLG_EXT_DIRTY|HFS_FLG_EXT_NEW);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) static int hfs_ext_read_extent(struct inode *inode, u16 block)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) struct hfs_find_data fd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) int res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) if (block >= HFS_I(inode)->cached_start &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) block < HFS_I(inode)->cached_start + HFS_I(inode)->cached_blocks)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) res = hfs_find_init(HFS_SB(inode->i_sb)->ext_tree, &fd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) if (!res) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) res = __hfs_ext_cache_extent(&fd, inode, block);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) hfs_find_exit(&fd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) static void hfs_dump_extent(struct hfs_extent *extent)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) hfs_dbg(EXTENT, " ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) for (i = 0; i < 3; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) hfs_dbg_cont(EXTENT, " %u:%u",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) be16_to_cpu(extent[i].block),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) be16_to_cpu(extent[i].count));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) hfs_dbg_cont(EXTENT, "\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) static int hfs_add_extent(struct hfs_extent *extent, u16 offset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) u16 alloc_block, u16 block_count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) u16 count, start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) hfs_dump_extent(extent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) for (i = 0; i < 3; extent++, i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) count = be16_to_cpu(extent->count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) if (offset == count) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) start = be16_to_cpu(extent->block);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) if (alloc_block != start + count) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) if (++i >= 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) return -ENOSPC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) extent++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) extent->block = cpu_to_be16(alloc_block);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) block_count += count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) extent->count = cpu_to_be16(block_count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) } else if (offset < count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) offset -= count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) /* panic? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) static int hfs_free_extents(struct super_block *sb, struct hfs_extent *extent,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) u16 offset, u16 block_nr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) u16 count, start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) hfs_dump_extent(extent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) for (i = 0; i < 3; extent++, i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) count = be16_to_cpu(extent->count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) if (offset == count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) goto found;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) else if (offset < count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) offset -= count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) /* panic? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) found:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) for (;;) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) start = be16_to_cpu(extent->block);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) if (count <= block_nr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) hfs_clear_vbm_bits(sb, start, count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) extent->block = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) extent->count = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) block_nr -= count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) count -= block_nr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) hfs_clear_vbm_bits(sb, start + count, block_nr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) extent->count = cpu_to_be16(count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) block_nr = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) if (!block_nr || !i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) i--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) extent--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) count = be16_to_cpu(extent->count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) int hfs_free_fork(struct super_block *sb, struct hfs_cat_file *file, int type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) struct hfs_find_data fd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) u32 total_blocks, blocks, start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) u32 cnid = be32_to_cpu(file->FlNum);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) struct hfs_extent *extent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) int res, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) if (type == HFS_FK_DATA) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) total_blocks = be32_to_cpu(file->PyLen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) extent = file->ExtRec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) total_blocks = be32_to_cpu(file->RPyLen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) extent = file->RExtRec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) total_blocks /= HFS_SB(sb)->alloc_blksz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) if (!total_blocks)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) blocks = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) for (i = 0; i < 3; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) blocks += be16_to_cpu(extent[i].count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) res = hfs_free_extents(sb, extent, blocks, blocks);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) if (res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) if (total_blocks == blocks)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) res = hfs_find_init(HFS_SB(sb)->ext_tree, &fd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) if (res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) res = __hfs_ext_read_extent(&fd, extent, cnid, total_blocks, type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) if (res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) start = be16_to_cpu(fd.key->ext.FABN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) hfs_free_extents(sb, extent, total_blocks - start, total_blocks);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) hfs_brec_remove(&fd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) total_blocks = start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) } while (total_blocks > blocks);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) hfs_find_exit(&fd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) * hfs_get_block
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) int hfs_get_block(struct inode *inode, sector_t block,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) struct buffer_head *bh_result, int create)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) struct super_block *sb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) u16 dblock, ablock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) int res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) sb = inode->i_sb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) /* Convert inode block to disk allocation block */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) ablock = (u32)block / HFS_SB(sb)->fs_div;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) if (block >= HFS_I(inode)->fs_blocks) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) if (!create)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) if (block > HFS_I(inode)->fs_blocks)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) if (ablock >= HFS_I(inode)->alloc_blocks) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) res = hfs_extend_file(inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) if (res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) create = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) if (ablock < HFS_I(inode)->first_blocks) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) dblock = hfs_ext_find_block(HFS_I(inode)->first_extents, ablock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) mutex_lock(&HFS_I(inode)->extents_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) res = hfs_ext_read_extent(inode, ablock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) if (!res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) dblock = hfs_ext_find_block(HFS_I(inode)->cached_extents,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) ablock - HFS_I(inode)->cached_start);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) mutex_unlock(&HFS_I(inode)->extents_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) mutex_unlock(&HFS_I(inode)->extents_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) done:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) map_bh(bh_result, sb, HFS_SB(sb)->fs_start +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) dblock * HFS_SB(sb)->fs_div +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) (u32)block % HFS_SB(sb)->fs_div);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) if (create) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) set_buffer_new(bh_result);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) HFS_I(inode)->phys_size += sb->s_blocksize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) HFS_I(inode)->fs_blocks++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) inode_add_bytes(inode, sb->s_blocksize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) mark_inode_dirty(inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) int hfs_extend_file(struct inode *inode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) struct super_block *sb = inode->i_sb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) u32 start, len, goal;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) int res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) mutex_lock(&HFS_I(inode)->extents_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) if (HFS_I(inode)->alloc_blocks == HFS_I(inode)->first_blocks)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) goal = hfs_ext_lastblock(HFS_I(inode)->first_extents);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) res = hfs_ext_read_extent(inode, HFS_I(inode)->alloc_blocks);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) if (res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) goal = hfs_ext_lastblock(HFS_I(inode)->cached_extents);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) len = HFS_I(inode)->clump_blocks;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) start = hfs_vbm_search_free(sb, goal, &len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) if (!len) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) res = -ENOSPC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) hfs_dbg(EXTENT, "extend %lu: %u,%u\n", inode->i_ino, start, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) if (HFS_I(inode)->alloc_blocks == HFS_I(inode)->first_blocks) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) if (!HFS_I(inode)->first_blocks) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) hfs_dbg(EXTENT, "first extents\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) /* no extents yet */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) HFS_I(inode)->first_extents[0].block = cpu_to_be16(start);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) HFS_I(inode)->first_extents[0].count = cpu_to_be16(len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) res = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) /* try to append to extents in inode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) res = hfs_add_extent(HFS_I(inode)->first_extents,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) HFS_I(inode)->alloc_blocks,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) start, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) if (res == -ENOSPC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) goto insert_extent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) if (!res) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) hfs_dump_extent(HFS_I(inode)->first_extents);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) HFS_I(inode)->first_blocks += len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) res = hfs_add_extent(HFS_I(inode)->cached_extents,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) HFS_I(inode)->alloc_blocks -
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) HFS_I(inode)->cached_start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) start, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) if (!res) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) hfs_dump_extent(HFS_I(inode)->cached_extents);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) HFS_I(inode)->flags |= HFS_FLG_EXT_DIRTY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) HFS_I(inode)->cached_blocks += len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) } else if (res == -ENOSPC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) goto insert_extent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) mutex_unlock(&HFS_I(inode)->extents_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) if (!res) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) HFS_I(inode)->alloc_blocks += len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) mark_inode_dirty(inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) if (inode->i_ino < HFS_FIRSTUSER_CNID)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) set_bit(HFS_FLG_ALT_MDB_DIRTY, &HFS_SB(sb)->flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) set_bit(HFS_FLG_MDB_DIRTY, &HFS_SB(sb)->flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) hfs_mark_mdb_dirty(sb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) insert_extent:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) hfs_dbg(EXTENT, "insert new extent\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) res = hfs_ext_write_extent(inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) if (res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) memset(HFS_I(inode)->cached_extents, 0, sizeof(hfs_extent_rec));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) HFS_I(inode)->cached_extents[0].block = cpu_to_be16(start);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) HFS_I(inode)->cached_extents[0].count = cpu_to_be16(len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) hfs_dump_extent(HFS_I(inode)->cached_extents);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) HFS_I(inode)->flags |= HFS_FLG_EXT_DIRTY|HFS_FLG_EXT_NEW;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) HFS_I(inode)->cached_start = HFS_I(inode)->alloc_blocks;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) HFS_I(inode)->cached_blocks = len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) res = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) void hfs_file_truncate(struct inode *inode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) struct super_block *sb = inode->i_sb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) struct hfs_find_data fd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) u16 blk_cnt, alloc_cnt, start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) u32 size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) int res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) hfs_dbg(INODE, "truncate: %lu, %Lu -> %Lu\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) inode->i_ino, (long long)HFS_I(inode)->phys_size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) inode->i_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) if (inode->i_size > HFS_I(inode)->phys_size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) struct address_space *mapping = inode->i_mapping;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) void *fsdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) struct page *page;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) /* XXX: Can use generic_cont_expand? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) size = inode->i_size - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) res = pagecache_write_begin(NULL, mapping, size+1, 0, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) &page, &fsdata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) if (!res) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) res = pagecache_write_end(NULL, mapping, size+1, 0, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) page, fsdata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) if (res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) inode->i_size = HFS_I(inode)->phys_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) } else if (inode->i_size == HFS_I(inode)->phys_size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) size = inode->i_size + HFS_SB(sb)->alloc_blksz - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) blk_cnt = size / HFS_SB(sb)->alloc_blksz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) alloc_cnt = HFS_I(inode)->alloc_blocks;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) if (blk_cnt == alloc_cnt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) mutex_lock(&HFS_I(inode)->extents_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) res = hfs_find_init(HFS_SB(sb)->ext_tree, &fd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) if (res) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) mutex_unlock(&HFS_I(inode)->extents_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) /* XXX: We lack error handling of hfs_file_truncate() */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) while (1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) if (alloc_cnt == HFS_I(inode)->first_blocks) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) hfs_free_extents(sb, HFS_I(inode)->first_extents,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) alloc_cnt, alloc_cnt - blk_cnt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) hfs_dump_extent(HFS_I(inode)->first_extents);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) HFS_I(inode)->first_blocks = blk_cnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) res = __hfs_ext_cache_extent(&fd, inode, alloc_cnt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) if (res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) start = HFS_I(inode)->cached_start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) hfs_free_extents(sb, HFS_I(inode)->cached_extents,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) alloc_cnt - start, alloc_cnt - blk_cnt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) hfs_dump_extent(HFS_I(inode)->cached_extents);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) if (blk_cnt > start) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) HFS_I(inode)->flags |= HFS_FLG_EXT_DIRTY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) alloc_cnt = start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) HFS_I(inode)->cached_start = HFS_I(inode)->cached_blocks = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) HFS_I(inode)->flags &= ~(HFS_FLG_EXT_DIRTY|HFS_FLG_EXT_NEW);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) hfs_brec_remove(&fd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) hfs_find_exit(&fd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) mutex_unlock(&HFS_I(inode)->extents_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) HFS_I(inode)->alloc_blocks = blk_cnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) HFS_I(inode)->phys_size = inode->i_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) HFS_I(inode)->fs_blocks = (inode->i_size + sb->s_blocksize - 1) >> sb->s_blocksize_bits;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) inode_set_bytes(inode, HFS_I(inode)->fs_blocks << sb->s_blocksize_bits);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) mark_inode_dirty(inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) }