2 * linux/fs/hfs/extent.c
4 * Copyright (C) 1995-1997 Paul H. Hargrove
5 * (C) 2003 Ardis Technologies <roman@ardistech.com>
6 * This file may be distributed under the terms of the GNU General Public License.
8 * This file contains the functions related to the extents B-tree.
11 #include <linux/pagemap.h>
16 /*================ File-local functions ================*/
21 static void hfs_ext_build_key(hfs_btree_key
*key
, u32 cnid
, u16 block
, u8 type
)
24 key
->ext
.FkType
= type
;
25 key
->ext
.FNum
= cpu_to_be32(cnid
);
26 key
->ext
.FABN
= cpu_to_be16(block
);
33 * This is the comparison function used for the extents B-tree. In
34 * comparing extent B-tree entries, the file id is the most
35 * significant field (compared as unsigned ints); the fork type is
36 * the second most significant field (compared as unsigned chars);
37 * and the allocation block number field is the least significant
38 * (compared as unsigned ints).
40 * struct hfs_ext_key *key1: pointer to the first key to compare
41 * struct hfs_ext_key *key2: pointer to the second key to compare
45 * int: negative if key1<key2, positive if key1>key2, and 0 if key1==key2
47 * key1 and key2 point to "valid" (struct hfs_ext_key)s.
49 * This function has no side-effects */
50 int hfs_ext_keycmp(const btree_key
*key1
, const btree_key
*key2
)
53 __be16 block1
, block2
;
55 fnum1
= key1
->ext
.FNum
;
56 fnum2
= key2
->ext
.FNum
;
58 return be32_to_cpu(fnum1
) < be32_to_cpu(fnum2
) ? -1 : 1;
59 if (key1
->ext
.FkType
!= key2
->ext
.FkType
)
60 return key1
->ext
.FkType
< key2
->ext
.FkType
? -1 : 1;
62 block1
= key1
->ext
.FABN
;
63 block2
= key2
->ext
.FABN
;
66 return be16_to_cpu(block1
) < be16_to_cpu(block2
) ? -1 : 1;
72 * Find a block within an extent record
74 static u16
hfs_ext_find_block(struct hfs_extent
*ext
, u16 off
)
79 for (i
= 0; i
< 3; ext
++, i
++) {
80 count
= be16_to_cpu(ext
->count
);
82 return be16_to_cpu(ext
->block
) + off
;
89 static int hfs_ext_block_count(struct hfs_extent
*ext
)
94 for (i
= 0; i
< 3; ext
++, i
++)
95 count
+= be16_to_cpu(ext
->count
);
99 static u16
hfs_ext_lastblock(struct hfs_extent
*ext
)
104 for (i
= 0; i
< 2; ext
--, i
++)
107 return be16_to_cpu(ext
->block
) + be16_to_cpu(ext
->count
);
110 static int __hfs_ext_write_extent(struct inode
*inode
, struct hfs_find_data
*fd
)
114 hfs_ext_build_key(fd
->search_key
, inode
->i_ino
, HFS_I(inode
)->cached_start
,
115 HFS_IS_RSRC(inode
) ? HFS_FK_RSRC
: HFS_FK_DATA
);
116 res
= hfs_brec_find(fd
);
117 if (HFS_I(inode
)->flags
& HFS_FLG_EXT_NEW
) {
120 /* Fail early and avoid ENOSPC during the btree operation */
121 res
= hfs_bmap_reserve(fd
->tree
, fd
->tree
->depth
+ 1);
124 hfs_brec_insert(fd
, HFS_I(inode
)->cached_extents
, sizeof(hfs_extent_rec
));
125 HFS_I(inode
)->flags
&= ~(HFS_FLG_EXT_DIRTY
|HFS_FLG_EXT_NEW
);
129 hfs_bnode_write(fd
->bnode
, HFS_I(inode
)->cached_extents
, fd
->entryoffset
, fd
->entrylength
);
130 HFS_I(inode
)->flags
&= ~HFS_FLG_EXT_DIRTY
;
135 int hfs_ext_write_extent(struct inode
*inode
)
137 struct hfs_find_data fd
;
140 if (HFS_I(inode
)->flags
& HFS_FLG_EXT_DIRTY
) {
141 res
= hfs_find_init(HFS_SB(inode
->i_sb
)->ext_tree
, &fd
);
144 res
= __hfs_ext_write_extent(inode
, &fd
);
150 static inline int __hfs_ext_read_extent(struct hfs_find_data
*fd
, struct hfs_extent
*extent
,
151 u32 cnid
, u32 block
, u8 type
)
155 hfs_ext_build_key(fd
->search_key
, cnid
, block
, type
);
156 fd
->key
->ext
.FNum
= 0;
157 res
= hfs_brec_find(fd
);
158 if (res
&& res
!= -ENOENT
)
160 if (fd
->key
->ext
.FNum
!= fd
->search_key
->ext
.FNum
||
161 fd
->key
->ext
.FkType
!= fd
->search_key
->ext
.FkType
)
163 if (fd
->entrylength
!= sizeof(hfs_extent_rec
))
165 hfs_bnode_read(fd
->bnode
, extent
, fd
->entryoffset
, sizeof(hfs_extent_rec
));
169 static inline int __hfs_ext_cache_extent(struct hfs_find_data
*fd
, struct inode
*inode
, u32 block
)
173 if (HFS_I(inode
)->flags
& HFS_FLG_EXT_DIRTY
) {
174 res
= __hfs_ext_write_extent(inode
, fd
);
179 res
= __hfs_ext_read_extent(fd
, HFS_I(inode
)->cached_extents
, inode
->i_ino
,
180 block
, HFS_IS_RSRC(inode
) ? HFS_FK_RSRC
: HFS_FK_DATA
);
182 HFS_I(inode
)->cached_start
= be16_to_cpu(fd
->key
->ext
.FABN
);
183 HFS_I(inode
)->cached_blocks
= hfs_ext_block_count(HFS_I(inode
)->cached_extents
);
185 HFS_I(inode
)->cached_start
= HFS_I(inode
)->cached_blocks
= 0;
186 HFS_I(inode
)->flags
&= ~(HFS_FLG_EXT_DIRTY
|HFS_FLG_EXT_NEW
);
191 static int hfs_ext_read_extent(struct inode
*inode
, u16 block
)
193 struct hfs_find_data fd
;
196 if (block
>= HFS_I(inode
)->cached_start
&&
197 block
< HFS_I(inode
)->cached_start
+ HFS_I(inode
)->cached_blocks
)
200 res
= hfs_find_init(HFS_SB(inode
->i_sb
)->ext_tree
, &fd
);
202 res
= __hfs_ext_cache_extent(&fd
, inode
, block
);
208 static void hfs_dump_extent(struct hfs_extent
*extent
)
212 hfs_dbg(EXTENT
, " ");
213 for (i
= 0; i
< 3; i
++)
214 hfs_dbg_cont(EXTENT
, " %u:%u",
215 be16_to_cpu(extent
[i
].block
),
216 be16_to_cpu(extent
[i
].count
));
217 hfs_dbg_cont(EXTENT
, "\n");
220 static int hfs_add_extent(struct hfs_extent
*extent
, u16 offset
,
221 u16 alloc_block
, u16 block_count
)
226 hfs_dump_extent(extent
);
227 for (i
= 0; i
< 3; extent
++, i
++) {
228 count
= be16_to_cpu(extent
->count
);
229 if (offset
== count
) {
230 start
= be16_to_cpu(extent
->block
);
231 if (alloc_block
!= start
+ count
) {
235 extent
->block
= cpu_to_be16(alloc_block
);
237 block_count
+= count
;
238 extent
->count
= cpu_to_be16(block_count
);
240 } else if (offset
< count
)
248 static int hfs_free_extents(struct super_block
*sb
, struct hfs_extent
*extent
,
249 u16 offset
, u16 block_nr
)
254 hfs_dump_extent(extent
);
255 for (i
= 0; i
< 3; extent
++, i
++) {
256 count
= be16_to_cpu(extent
->count
);
259 else if (offset
< count
)
267 start
= be16_to_cpu(extent
->block
);
268 if (count
<= block_nr
) {
269 hfs_clear_vbm_bits(sb
, start
, count
);
275 hfs_clear_vbm_bits(sb
, start
+ count
, block_nr
);
276 extent
->count
= cpu_to_be16(count
);
283 count
= be16_to_cpu(extent
->count
);
287 int hfs_free_fork(struct super_block
*sb
, struct hfs_cat_file
*file
, int type
)
289 struct hfs_find_data fd
;
290 u32 total_blocks
, blocks
, start
;
291 u32 cnid
= be32_to_cpu(file
->FlNum
);
292 struct hfs_extent
*extent
;
295 if (type
== HFS_FK_DATA
) {
296 total_blocks
= be32_to_cpu(file
->PyLen
);
297 extent
= file
->ExtRec
;
299 total_blocks
= be32_to_cpu(file
->RPyLen
);
300 extent
= file
->RExtRec
;
302 total_blocks
/= HFS_SB(sb
)->alloc_blksz
;
307 for (i
= 0; i
< 3; i
++)
308 blocks
+= be16_to_cpu(extent
[i
].count
);
310 res
= hfs_free_extents(sb
, extent
, blocks
, blocks
);
313 if (total_blocks
== blocks
)
316 res
= hfs_find_init(HFS_SB(sb
)->ext_tree
, &fd
);
320 res
= __hfs_ext_read_extent(&fd
, extent
, cnid
, total_blocks
, type
);
323 start
= be16_to_cpu(fd
.key
->ext
.FABN
);
324 hfs_free_extents(sb
, extent
, total_blocks
- start
, total_blocks
);
325 hfs_brec_remove(&fd
);
326 total_blocks
= start
;
327 } while (total_blocks
> blocks
);
336 int hfs_get_block(struct inode
*inode
, sector_t block
,
337 struct buffer_head
*bh_result
, int create
)
339 struct super_block
*sb
;
344 /* Convert inode block to disk allocation block */
345 ablock
= (u32
)block
/ HFS_SB(sb
)->fs_div
;
347 if (block
>= HFS_I(inode
)->fs_blocks
) {
350 if (block
> HFS_I(inode
)->fs_blocks
)
352 if (ablock
>= HFS_I(inode
)->alloc_blocks
) {
353 res
= hfs_extend_file(inode
);
360 if (ablock
< HFS_I(inode
)->first_blocks
) {
361 dblock
= hfs_ext_find_block(HFS_I(inode
)->first_extents
, ablock
);
365 mutex_lock(&HFS_I(inode
)->extents_lock
);
366 res
= hfs_ext_read_extent(inode
, ablock
);
368 dblock
= hfs_ext_find_block(HFS_I(inode
)->cached_extents
,
369 ablock
- HFS_I(inode
)->cached_start
);
371 mutex_unlock(&HFS_I(inode
)->extents_lock
);
374 mutex_unlock(&HFS_I(inode
)->extents_lock
);
377 map_bh(bh_result
, sb
, HFS_SB(sb
)->fs_start
+
378 dblock
* HFS_SB(sb
)->fs_div
+
379 (u32
)block
% HFS_SB(sb
)->fs_div
);
382 set_buffer_new(bh_result
);
383 HFS_I(inode
)->phys_size
+= sb
->s_blocksize
;
384 HFS_I(inode
)->fs_blocks
++;
385 inode_add_bytes(inode
, sb
->s_blocksize
);
386 mark_inode_dirty(inode
);
391 int hfs_extend_file(struct inode
*inode
)
393 struct super_block
*sb
= inode
->i_sb
;
394 u32 start
, len
, goal
;
397 mutex_lock(&HFS_I(inode
)->extents_lock
);
398 if (HFS_I(inode
)->alloc_blocks
== HFS_I(inode
)->first_blocks
)
399 goal
= hfs_ext_lastblock(HFS_I(inode
)->first_extents
);
401 res
= hfs_ext_read_extent(inode
, HFS_I(inode
)->alloc_blocks
);
404 goal
= hfs_ext_lastblock(HFS_I(inode
)->cached_extents
);
407 len
= HFS_I(inode
)->clump_blocks
;
408 start
= hfs_vbm_search_free(sb
, goal
, &len
);
414 hfs_dbg(EXTENT
, "extend %lu: %u,%u\n", inode
->i_ino
, start
, len
);
415 if (HFS_I(inode
)->alloc_blocks
== HFS_I(inode
)->first_blocks
) {
416 if (!HFS_I(inode
)->first_blocks
) {
417 hfs_dbg(EXTENT
, "first extents\n");
419 HFS_I(inode
)->first_extents
[0].block
= cpu_to_be16(start
);
420 HFS_I(inode
)->first_extents
[0].count
= cpu_to_be16(len
);
423 /* try to append to extents in inode */
424 res
= hfs_add_extent(HFS_I(inode
)->first_extents
,
425 HFS_I(inode
)->alloc_blocks
,
431 hfs_dump_extent(HFS_I(inode
)->first_extents
);
432 HFS_I(inode
)->first_blocks
+= len
;
435 res
= hfs_add_extent(HFS_I(inode
)->cached_extents
,
436 HFS_I(inode
)->alloc_blocks
-
437 HFS_I(inode
)->cached_start
,
440 hfs_dump_extent(HFS_I(inode
)->cached_extents
);
441 HFS_I(inode
)->flags
|= HFS_FLG_EXT_DIRTY
;
442 HFS_I(inode
)->cached_blocks
+= len
;
443 } else if (res
== -ENOSPC
)
447 mutex_unlock(&HFS_I(inode
)->extents_lock
);
449 HFS_I(inode
)->alloc_blocks
+= len
;
450 mark_inode_dirty(inode
);
451 if (inode
->i_ino
< HFS_FIRSTUSER_CNID
)
452 set_bit(HFS_FLG_ALT_MDB_DIRTY
, &HFS_SB(sb
)->flags
);
453 set_bit(HFS_FLG_MDB_DIRTY
, &HFS_SB(sb
)->flags
);
454 hfs_mark_mdb_dirty(sb
);
459 hfs_dbg(EXTENT
, "insert new extent\n");
460 res
= hfs_ext_write_extent(inode
);
464 memset(HFS_I(inode
)->cached_extents
, 0, sizeof(hfs_extent_rec
));
465 HFS_I(inode
)->cached_extents
[0].block
= cpu_to_be16(start
);
466 HFS_I(inode
)->cached_extents
[0].count
= cpu_to_be16(len
);
467 hfs_dump_extent(HFS_I(inode
)->cached_extents
);
468 HFS_I(inode
)->flags
|= HFS_FLG_EXT_DIRTY
|HFS_FLG_EXT_NEW
;
469 HFS_I(inode
)->cached_start
= HFS_I(inode
)->alloc_blocks
;
470 HFS_I(inode
)->cached_blocks
= len
;
476 void hfs_file_truncate(struct inode
*inode
)
478 struct super_block
*sb
= inode
->i_sb
;
479 struct hfs_find_data fd
;
480 u16 blk_cnt
, alloc_cnt
, start
;
484 hfs_dbg(INODE
, "truncate: %lu, %Lu -> %Lu\n",
485 inode
->i_ino
, (long long)HFS_I(inode
)->phys_size
,
487 if (inode
->i_size
> HFS_I(inode
)->phys_size
) {
488 struct address_space
*mapping
= inode
->i_mapping
;
492 /* XXX: Can use generic_cont_expand? */
493 size
= inode
->i_size
- 1;
494 res
= pagecache_write_begin(NULL
, mapping
, size
+1, 0, 0,
497 res
= pagecache_write_end(NULL
, mapping
, size
+1, 0, 0,
501 inode
->i_size
= HFS_I(inode
)->phys_size
;
503 } else if (inode
->i_size
== HFS_I(inode
)->phys_size
)
505 size
= inode
->i_size
+ HFS_SB(sb
)->alloc_blksz
- 1;
506 blk_cnt
= size
/ HFS_SB(sb
)->alloc_blksz
;
507 alloc_cnt
= HFS_I(inode
)->alloc_blocks
;
508 if (blk_cnt
== alloc_cnt
)
511 mutex_lock(&HFS_I(inode
)->extents_lock
);
512 res
= hfs_find_init(HFS_SB(sb
)->ext_tree
, &fd
);
514 mutex_unlock(&HFS_I(inode
)->extents_lock
);
515 /* XXX: We lack error handling of hfs_file_truncate() */
519 if (alloc_cnt
== HFS_I(inode
)->first_blocks
) {
520 hfs_free_extents(sb
, HFS_I(inode
)->first_extents
,
521 alloc_cnt
, alloc_cnt
- blk_cnt
);
522 hfs_dump_extent(HFS_I(inode
)->first_extents
);
523 HFS_I(inode
)->first_blocks
= blk_cnt
;
526 res
= __hfs_ext_cache_extent(&fd
, inode
, alloc_cnt
);
529 start
= HFS_I(inode
)->cached_start
;
530 hfs_free_extents(sb
, HFS_I(inode
)->cached_extents
,
531 alloc_cnt
- start
, alloc_cnt
- blk_cnt
);
532 hfs_dump_extent(HFS_I(inode
)->cached_extents
);
533 if (blk_cnt
> start
) {
534 HFS_I(inode
)->flags
|= HFS_FLG_EXT_DIRTY
;
538 HFS_I(inode
)->cached_start
= HFS_I(inode
)->cached_blocks
= 0;
539 HFS_I(inode
)->flags
&= ~(HFS_FLG_EXT_DIRTY
|HFS_FLG_EXT_NEW
);
540 hfs_brec_remove(&fd
);
543 mutex_unlock(&HFS_I(inode
)->extents_lock
);
545 HFS_I(inode
)->alloc_blocks
= blk_cnt
;
547 HFS_I(inode
)->phys_size
= inode
->i_size
;
548 HFS_I(inode
)->fs_blocks
= (inode
->i_size
+ sb
->s_blocksize
- 1) >> sb
->s_blocksize_bits
;
549 inode_set_bytes(inode
, HFS_I(inode
)->fs_blocks
<< sb
->s_blocksize_bits
);
550 mark_inode_dirty(inode
);