0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #include <linux/pagemap.h>
0012
0013 #include "hfs_fs.h"
0014 #include "btree.h"
0015
0016
0017
0018
0019
0020
0021 static void hfs_ext_build_key(hfs_btree_key *key, u32 cnid, u16 block, u8 type)
0022 {
0023 key->key_len = 7;
0024 key->ext.FkType = type;
0025 key->ext.FNum = cpu_to_be32(cnid);
0026 key->ext.FABN = cpu_to_be16(block);
0027 }
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050 int hfs_ext_keycmp(const btree_key *key1, const btree_key *key2)
0051 {
0052 __be32 fnum1, fnum2;
0053 __be16 block1, block2;
0054
0055 fnum1 = key1->ext.FNum;
0056 fnum2 = key2->ext.FNum;
0057 if (fnum1 != fnum2)
0058 return be32_to_cpu(fnum1) < be32_to_cpu(fnum2) ? -1 : 1;
0059 if (key1->ext.FkType != key2->ext.FkType)
0060 return key1->ext.FkType < key2->ext.FkType ? -1 : 1;
0061
0062 block1 = key1->ext.FABN;
0063 block2 = key2->ext.FABN;
0064 if (block1 == block2)
0065 return 0;
0066 return be16_to_cpu(block1) < be16_to_cpu(block2) ? -1 : 1;
0067 }
0068
0069
0070
0071
0072
0073
0074 static u16 hfs_ext_find_block(struct hfs_extent *ext, u16 off)
0075 {
0076 int i;
0077 u16 count;
0078
0079 for (i = 0; i < 3; ext++, i++) {
0080 count = be16_to_cpu(ext->count);
0081 if (off < count)
0082 return be16_to_cpu(ext->block) + off;
0083 off -= count;
0084 }
0085
0086 return 0;
0087 }
0088
0089 static int hfs_ext_block_count(struct hfs_extent *ext)
0090 {
0091 int i;
0092 u16 count = 0;
0093
0094 for (i = 0; i < 3; ext++, i++)
0095 count += be16_to_cpu(ext->count);
0096 return count;
0097 }
0098
0099 static u16 hfs_ext_lastblock(struct hfs_extent *ext)
0100 {
0101 int i;
0102
0103 ext += 2;
0104 for (i = 0; i < 2; ext--, i++)
0105 if (ext->count)
0106 break;
0107 return be16_to_cpu(ext->block) + be16_to_cpu(ext->count);
0108 }
0109
0110 static int __hfs_ext_write_extent(struct inode *inode, struct hfs_find_data *fd)
0111 {
0112 int res;
0113
0114 hfs_ext_build_key(fd->search_key, inode->i_ino, HFS_I(inode)->cached_start,
0115 HFS_IS_RSRC(inode) ? HFS_FK_RSRC : HFS_FK_DATA);
0116 res = hfs_brec_find(fd);
0117 if (HFS_I(inode)->flags & HFS_FLG_EXT_NEW) {
0118 if (res != -ENOENT)
0119 return res;
0120
0121 res = hfs_bmap_reserve(fd->tree, fd->tree->depth + 1);
0122 if (res)
0123 return res;
0124 hfs_brec_insert(fd, HFS_I(inode)->cached_extents, sizeof(hfs_extent_rec));
0125 HFS_I(inode)->flags &= ~(HFS_FLG_EXT_DIRTY|HFS_FLG_EXT_NEW);
0126 } else {
0127 if (res)
0128 return res;
0129 hfs_bnode_write(fd->bnode, HFS_I(inode)->cached_extents, fd->entryoffset, fd->entrylength);
0130 HFS_I(inode)->flags &= ~HFS_FLG_EXT_DIRTY;
0131 }
0132 return 0;
0133 }
0134
0135 int hfs_ext_write_extent(struct inode *inode)
0136 {
0137 struct hfs_find_data fd;
0138 int res = 0;
0139
0140 if (HFS_I(inode)->flags & HFS_FLG_EXT_DIRTY) {
0141 res = hfs_find_init(HFS_SB(inode->i_sb)->ext_tree, &fd);
0142 if (res)
0143 return res;
0144 res = __hfs_ext_write_extent(inode, &fd);
0145 hfs_find_exit(&fd);
0146 }
0147 return res;
0148 }
0149
0150 static inline int __hfs_ext_read_extent(struct hfs_find_data *fd, struct hfs_extent *extent,
0151 u32 cnid, u32 block, u8 type)
0152 {
0153 int res;
0154
0155 hfs_ext_build_key(fd->search_key, cnid, block, type);
0156 fd->key->ext.FNum = 0;
0157 res = hfs_brec_find(fd);
0158 if (res && res != -ENOENT)
0159 return res;
0160 if (fd->key->ext.FNum != fd->search_key->ext.FNum ||
0161 fd->key->ext.FkType != fd->search_key->ext.FkType)
0162 return -ENOENT;
0163 if (fd->entrylength != sizeof(hfs_extent_rec))
0164 return -EIO;
0165 hfs_bnode_read(fd->bnode, extent, fd->entryoffset, sizeof(hfs_extent_rec));
0166 return 0;
0167 }
0168
0169 static inline int __hfs_ext_cache_extent(struct hfs_find_data *fd, struct inode *inode, u32 block)
0170 {
0171 int res;
0172
0173 if (HFS_I(inode)->flags & HFS_FLG_EXT_DIRTY) {
0174 res = __hfs_ext_write_extent(inode, fd);
0175 if (res)
0176 return res;
0177 }
0178
0179 res = __hfs_ext_read_extent(fd, HFS_I(inode)->cached_extents, inode->i_ino,
0180 block, HFS_IS_RSRC(inode) ? HFS_FK_RSRC : HFS_FK_DATA);
0181 if (!res) {
0182 HFS_I(inode)->cached_start = be16_to_cpu(fd->key->ext.FABN);
0183 HFS_I(inode)->cached_blocks = hfs_ext_block_count(HFS_I(inode)->cached_extents);
0184 } else {
0185 HFS_I(inode)->cached_start = HFS_I(inode)->cached_blocks = 0;
0186 HFS_I(inode)->flags &= ~(HFS_FLG_EXT_DIRTY|HFS_FLG_EXT_NEW);
0187 }
0188 return res;
0189 }
0190
0191 static int hfs_ext_read_extent(struct inode *inode, u16 block)
0192 {
0193 struct hfs_find_data fd;
0194 int res;
0195
0196 if (block >= HFS_I(inode)->cached_start &&
0197 block < HFS_I(inode)->cached_start + HFS_I(inode)->cached_blocks)
0198 return 0;
0199
0200 res = hfs_find_init(HFS_SB(inode->i_sb)->ext_tree, &fd);
0201 if (!res) {
0202 res = __hfs_ext_cache_extent(&fd, inode, block);
0203 hfs_find_exit(&fd);
0204 }
0205 return res;
0206 }
0207
0208 static void hfs_dump_extent(struct hfs_extent *extent)
0209 {
0210 int i;
0211
0212 hfs_dbg(EXTENT, " ");
0213 for (i = 0; i < 3; i++)
0214 hfs_dbg_cont(EXTENT, " %u:%u",
0215 be16_to_cpu(extent[i].block),
0216 be16_to_cpu(extent[i].count));
0217 hfs_dbg_cont(EXTENT, "\n");
0218 }
0219
0220 static int hfs_add_extent(struct hfs_extent *extent, u16 offset,
0221 u16 alloc_block, u16 block_count)
0222 {
0223 u16 count, start;
0224 int i;
0225
0226 hfs_dump_extent(extent);
0227 for (i = 0; i < 3; extent++, i++) {
0228 count = be16_to_cpu(extent->count);
0229 if (offset == count) {
0230 start = be16_to_cpu(extent->block);
0231 if (alloc_block != start + count) {
0232 if (++i >= 3)
0233 return -ENOSPC;
0234 extent++;
0235 extent->block = cpu_to_be16(alloc_block);
0236 } else
0237 block_count += count;
0238 extent->count = cpu_to_be16(block_count);
0239 return 0;
0240 } else if (offset < count)
0241 break;
0242 offset -= count;
0243 }
0244
0245 return -EIO;
0246 }
0247
0248 static int hfs_free_extents(struct super_block *sb, struct hfs_extent *extent,
0249 u16 offset, u16 block_nr)
0250 {
0251 u16 count, start;
0252 int i;
0253
0254 hfs_dump_extent(extent);
0255 for (i = 0; i < 3; extent++, i++) {
0256 count = be16_to_cpu(extent->count);
0257 if (offset == count)
0258 goto found;
0259 else if (offset < count)
0260 break;
0261 offset -= count;
0262 }
0263
0264 return -EIO;
0265 found:
0266 for (;;) {
0267 start = be16_to_cpu(extent->block);
0268 if (count <= block_nr) {
0269 hfs_clear_vbm_bits(sb, start, count);
0270 extent->block = 0;
0271 extent->count = 0;
0272 block_nr -= count;
0273 } else {
0274 count -= block_nr;
0275 hfs_clear_vbm_bits(sb, start + count, block_nr);
0276 extent->count = cpu_to_be16(count);
0277 block_nr = 0;
0278 }
0279 if (!block_nr || !i)
0280 return 0;
0281 i--;
0282 extent--;
0283 count = be16_to_cpu(extent->count);
0284 }
0285 }
0286
0287 int hfs_free_fork(struct super_block *sb, struct hfs_cat_file *file, int type)
0288 {
0289 struct hfs_find_data fd;
0290 u32 total_blocks, blocks, start;
0291 u32 cnid = be32_to_cpu(file->FlNum);
0292 struct hfs_extent *extent;
0293 int res, i;
0294
0295 if (type == HFS_FK_DATA) {
0296 total_blocks = be32_to_cpu(file->PyLen);
0297 extent = file->ExtRec;
0298 } else {
0299 total_blocks = be32_to_cpu(file->RPyLen);
0300 extent = file->RExtRec;
0301 }
0302 total_blocks /= HFS_SB(sb)->alloc_blksz;
0303 if (!total_blocks)
0304 return 0;
0305
0306 blocks = 0;
0307 for (i = 0; i < 3; i++)
0308 blocks += be16_to_cpu(extent[i].count);
0309
0310 res = hfs_free_extents(sb, extent, blocks, blocks);
0311 if (res)
0312 return res;
0313 if (total_blocks == blocks)
0314 return 0;
0315
0316 res = hfs_find_init(HFS_SB(sb)->ext_tree, &fd);
0317 if (res)
0318 return res;
0319 do {
0320 res = __hfs_ext_read_extent(&fd, extent, cnid, total_blocks, type);
0321 if (res)
0322 break;
0323 start = be16_to_cpu(fd.key->ext.FABN);
0324 hfs_free_extents(sb, extent, total_blocks - start, total_blocks);
0325 hfs_brec_remove(&fd);
0326 total_blocks = start;
0327 } while (total_blocks > blocks);
0328 hfs_find_exit(&fd);
0329
0330 return res;
0331 }
0332
0333
0334
0335
0336 int hfs_get_block(struct inode *inode, sector_t block,
0337 struct buffer_head *bh_result, int create)
0338 {
0339 struct super_block *sb;
0340 u16 dblock, ablock;
0341 int res;
0342
0343 sb = inode->i_sb;
0344
0345 ablock = (u32)block / HFS_SB(sb)->fs_div;
0346
0347 if (block >= HFS_I(inode)->fs_blocks) {
0348 if (!create)
0349 return 0;
0350 if (block > HFS_I(inode)->fs_blocks)
0351 return -EIO;
0352 if (ablock >= HFS_I(inode)->alloc_blocks) {
0353 res = hfs_extend_file(inode);
0354 if (res)
0355 return res;
0356 }
0357 } else
0358 create = 0;
0359
0360 if (ablock < HFS_I(inode)->first_blocks) {
0361 dblock = hfs_ext_find_block(HFS_I(inode)->first_extents, ablock);
0362 goto done;
0363 }
0364
0365 mutex_lock(&HFS_I(inode)->extents_lock);
0366 res = hfs_ext_read_extent(inode, ablock);
0367 if (!res)
0368 dblock = hfs_ext_find_block(HFS_I(inode)->cached_extents,
0369 ablock - HFS_I(inode)->cached_start);
0370 else {
0371 mutex_unlock(&HFS_I(inode)->extents_lock);
0372 return -EIO;
0373 }
0374 mutex_unlock(&HFS_I(inode)->extents_lock);
0375
0376 done:
0377 map_bh(bh_result, sb, HFS_SB(sb)->fs_start +
0378 dblock * HFS_SB(sb)->fs_div +
0379 (u32)block % HFS_SB(sb)->fs_div);
0380
0381 if (create) {
0382 set_buffer_new(bh_result);
0383 HFS_I(inode)->phys_size += sb->s_blocksize;
0384 HFS_I(inode)->fs_blocks++;
0385 inode_add_bytes(inode, sb->s_blocksize);
0386 mark_inode_dirty(inode);
0387 }
0388 return 0;
0389 }
0390
0391 int hfs_extend_file(struct inode *inode)
0392 {
0393 struct super_block *sb = inode->i_sb;
0394 u32 start, len, goal;
0395 int res;
0396
0397 mutex_lock(&HFS_I(inode)->extents_lock);
0398 if (HFS_I(inode)->alloc_blocks == HFS_I(inode)->first_blocks)
0399 goal = hfs_ext_lastblock(HFS_I(inode)->first_extents);
0400 else {
0401 res = hfs_ext_read_extent(inode, HFS_I(inode)->alloc_blocks);
0402 if (res)
0403 goto out;
0404 goal = hfs_ext_lastblock(HFS_I(inode)->cached_extents);
0405 }
0406
0407 len = HFS_I(inode)->clump_blocks;
0408 start = hfs_vbm_search_free(sb, goal, &len);
0409 if (!len) {
0410 res = -ENOSPC;
0411 goto out;
0412 }
0413
0414 hfs_dbg(EXTENT, "extend %lu: %u,%u\n", inode->i_ino, start, len);
0415 if (HFS_I(inode)->alloc_blocks == HFS_I(inode)->first_blocks) {
0416 if (!HFS_I(inode)->first_blocks) {
0417 hfs_dbg(EXTENT, "first extents\n");
0418
0419 HFS_I(inode)->first_extents[0].block = cpu_to_be16(start);
0420 HFS_I(inode)->first_extents[0].count = cpu_to_be16(len);
0421 res = 0;
0422 } else {
0423
0424 res = hfs_add_extent(HFS_I(inode)->first_extents,
0425 HFS_I(inode)->alloc_blocks,
0426 start, len);
0427 if (res == -ENOSPC)
0428 goto insert_extent;
0429 }
0430 if (!res) {
0431 hfs_dump_extent(HFS_I(inode)->first_extents);
0432 HFS_I(inode)->first_blocks += len;
0433 }
0434 } else {
0435 res = hfs_add_extent(HFS_I(inode)->cached_extents,
0436 HFS_I(inode)->alloc_blocks -
0437 HFS_I(inode)->cached_start,
0438 start, len);
0439 if (!res) {
0440 hfs_dump_extent(HFS_I(inode)->cached_extents);
0441 HFS_I(inode)->flags |= HFS_FLG_EXT_DIRTY;
0442 HFS_I(inode)->cached_blocks += len;
0443 } else if (res == -ENOSPC)
0444 goto insert_extent;
0445 }
0446 out:
0447 mutex_unlock(&HFS_I(inode)->extents_lock);
0448 if (!res) {
0449 HFS_I(inode)->alloc_blocks += len;
0450 mark_inode_dirty(inode);
0451 if (inode->i_ino < HFS_FIRSTUSER_CNID)
0452 set_bit(HFS_FLG_ALT_MDB_DIRTY, &HFS_SB(sb)->flags);
0453 set_bit(HFS_FLG_MDB_DIRTY, &HFS_SB(sb)->flags);
0454 hfs_mark_mdb_dirty(sb);
0455 }
0456 return res;
0457
0458 insert_extent:
0459 hfs_dbg(EXTENT, "insert new extent\n");
0460 res = hfs_ext_write_extent(inode);
0461 if (res)
0462 goto out;
0463
0464 memset(HFS_I(inode)->cached_extents, 0, sizeof(hfs_extent_rec));
0465 HFS_I(inode)->cached_extents[0].block = cpu_to_be16(start);
0466 HFS_I(inode)->cached_extents[0].count = cpu_to_be16(len);
0467 hfs_dump_extent(HFS_I(inode)->cached_extents);
0468 HFS_I(inode)->flags |= HFS_FLG_EXT_DIRTY|HFS_FLG_EXT_NEW;
0469 HFS_I(inode)->cached_start = HFS_I(inode)->alloc_blocks;
0470 HFS_I(inode)->cached_blocks = len;
0471
0472 res = 0;
0473 goto out;
0474 }
0475
0476 void hfs_file_truncate(struct inode *inode)
0477 {
0478 struct super_block *sb = inode->i_sb;
0479 struct hfs_find_data fd;
0480 u16 blk_cnt, alloc_cnt, start;
0481 u32 size;
0482 int res;
0483
0484 hfs_dbg(INODE, "truncate: %lu, %Lu -> %Lu\n",
0485 inode->i_ino, (long long)HFS_I(inode)->phys_size,
0486 inode->i_size);
0487 if (inode->i_size > HFS_I(inode)->phys_size) {
0488 struct address_space *mapping = inode->i_mapping;
0489 void *fsdata;
0490 struct page *page;
0491
0492
0493 size = inode->i_size - 1;
0494 res = hfs_write_begin(NULL, mapping, size + 1, 0, &page,
0495 &fsdata);
0496 if (!res) {
0497 res = generic_write_end(NULL, mapping, size + 1, 0, 0,
0498 page, fsdata);
0499 }
0500 if (res)
0501 inode->i_size = HFS_I(inode)->phys_size;
0502 return;
0503 } else if (inode->i_size == HFS_I(inode)->phys_size)
0504 return;
0505 size = inode->i_size + HFS_SB(sb)->alloc_blksz - 1;
0506 blk_cnt = size / HFS_SB(sb)->alloc_blksz;
0507 alloc_cnt = HFS_I(inode)->alloc_blocks;
0508 if (blk_cnt == alloc_cnt)
0509 goto out;
0510
0511 mutex_lock(&HFS_I(inode)->extents_lock);
0512 res = hfs_find_init(HFS_SB(sb)->ext_tree, &fd);
0513 if (res) {
0514 mutex_unlock(&HFS_I(inode)->extents_lock);
0515
0516 return;
0517 }
0518 while (1) {
0519 if (alloc_cnt == HFS_I(inode)->first_blocks) {
0520 hfs_free_extents(sb, HFS_I(inode)->first_extents,
0521 alloc_cnt, alloc_cnt - blk_cnt);
0522 hfs_dump_extent(HFS_I(inode)->first_extents);
0523 HFS_I(inode)->first_blocks = blk_cnt;
0524 break;
0525 }
0526 res = __hfs_ext_cache_extent(&fd, inode, alloc_cnt);
0527 if (res)
0528 break;
0529 start = HFS_I(inode)->cached_start;
0530 hfs_free_extents(sb, HFS_I(inode)->cached_extents,
0531 alloc_cnt - start, alloc_cnt - blk_cnt);
0532 hfs_dump_extent(HFS_I(inode)->cached_extents);
0533 if (blk_cnt > start) {
0534 HFS_I(inode)->flags |= HFS_FLG_EXT_DIRTY;
0535 break;
0536 }
0537 alloc_cnt = start;
0538 HFS_I(inode)->cached_start = HFS_I(inode)->cached_blocks = 0;
0539 HFS_I(inode)->flags &= ~(HFS_FLG_EXT_DIRTY|HFS_FLG_EXT_NEW);
0540 hfs_brec_remove(&fd);
0541 }
0542 hfs_find_exit(&fd);
0543 mutex_unlock(&HFS_I(inode)->extents_lock);
0544
0545 HFS_I(inode)->alloc_blocks = blk_cnt;
0546 out:
0547 HFS_I(inode)->phys_size = inode->i_size;
0548 HFS_I(inode)->fs_blocks = (inode->i_size + sb->s_blocksize - 1) >> sb->s_blocksize_bits;
0549 inode_set_bytes(inode, HFS_I(inode)->fs_blocks << sb->s_blocksize_bits);
0550 mark_inode_dirty(inode);
0551 }