int hfsplus_journaled_get_block(struct page *page) { struct inode * const inode = page->mapping->host; struct super_block * const sb = inode->i_sb; struct hfsplus_inode_info *hip = HFSPLUS_I(inode); u32 ablock, res; sector_t iblock; s32 block_num = -1; iblock = page->index << (PAGE_CACHE_SHIFT - inode->i_blkbits); ablock = iblock >> HFSPLUS_SB(sb)->fs_shift; if (ablock < hip->first_blocks) { block_num = hfsplus_ext_find_block(hip->first_extents, ablock); } else { mutex_lock(&hip->extents_lock); res = hfsplus_ext_read_extent(inode, ablock); if (!res) { mutex_lock(&hip->extents_lock); block_num = hfsplus_ext_find_block(hip->cached_extents, ablock - hip->cached_start); mutex_unlock(&hip->extents_lock); } else { mutex_unlock(&hip->extents_lock); } mutex_unlock(&hip->extents_lock); } return block_num; }
/* Get a block at iblock for inode, possibly allocating if create */ int hfsplus_get_block(struct inode *inode, sector_t iblock, struct buffer_head *bh_result, int create) { struct super_block *sb; int res = -EIO; u32 ablock, dblock, mask; int shift; sb = inode->i_sb; /* Convert inode block to disk allocation block */ shift = HFSPLUS_SB(sb).alloc_blksz_shift - sb->s_blocksize_bits; ablock = iblock >> HFSPLUS_SB(sb).fs_shift; if (iblock >= inode->i_blocks) { if (iblock > inode->i_blocks || !create) return -EIO; if (ablock >= HFSPLUS_I(inode).alloc_blocks) { res = hfsplus_file_extend(inode); if (res) return res; } } else create = 0; if (ablock < HFSPLUS_I(inode).first_blocks) { dblock = hfsplus_ext_find_block(HFSPLUS_I(inode).first_extents, ablock); goto done; } down(&HFSPLUS_I(inode).extents_lock); res = hfsplus_ext_read_extent(inode, ablock); if (!res) { dblock = hfsplus_ext_find_block(HFSPLUS_I(inode).cached_extents, ablock - HFSPLUS_I(inode).cached_start); } else { up(&HFSPLUS_I(inode).extents_lock); return -EIO; } up(&HFSPLUS_I(inode).extents_lock); done: dprint(DBG_EXTENT, "get_block(%lu): %llu - %u\n", inode->i_ino, (long long)iblock, dblock); mask = (1 << HFSPLUS_SB(sb).fs_shift) - 1; map_bh(bh_result, sb, (dblock << HFSPLUS_SB(sb).fs_shift) + HFSPLUS_SB(sb).blockoffset + (iblock & mask)); if (create) { set_buffer_new(bh_result); HFSPLUS_I(inode).phys_size += sb->s_blocksize; inode->i_blocks++; mark_inode_dirty(inode); } return 0; }
/* Get a block at iblock for inode, possibly allocating if create */ int hfsplus_get_block(struct inode *inode, sector_t iblock, struct buffer_head *bh_result, int create) { struct super_block *sb = inode->i_sb; struct hfsplus_sb_info *sbi = HFSPLUS_SB(sb); struct hfsplus_inode_info *hip = HFSPLUS_I(inode); int res = -EIO; u32 ablock, dblock, mask; sector_t sector; int was_dirty = 0; /* Convert inode block to disk allocation block */ ablock = iblock >> sbi->fs_shift; if (iblock >= hip->fs_blocks) { if (iblock > hip->fs_blocks || !create) return -EIO; if (ablock >= hip->alloc_blocks) { res = hfsplus_file_extend(inode, false); if (res) return res; } } else create = 0; if (ablock < hip->first_blocks) { dblock = hfsplus_ext_find_block(hip->first_extents, ablock); goto done; } if (inode->i_ino == HFSPLUS_EXT_CNID) return -EIO; mutex_lock(&hip->extents_lock); /* * hfsplus_ext_read_extent will write out a cached extent into * the extents btree. In that case we may have to mark the inode * dirty even for a pure read of an extent here. */ was_dirty = (hip->extent_state & HFSPLUS_EXT_DIRTY); res = hfsplus_ext_read_extent(inode, ablock); if (res) { mutex_unlock(&hip->extents_lock); return -EIO; } dblock = hfsplus_ext_find_block(hip->cached_extents, ablock - hip->cached_start); mutex_unlock(&hip->extents_lock); done: hfs_dbg(EXTENT, "get_block(%lu): %llu - %u\n", inode->i_ino, (long long)iblock, dblock); mask = (1 << sbi->fs_shift) - 1; sector = ((sector_t)dblock << sbi->fs_shift) + sbi->blockoffset + (iblock & mask); map_bh(bh_result, sb, sector); if (create) { set_buffer_new(bh_result); hip->phys_size += sb->s_blocksize; hip->fs_blocks++; inode_add_bytes(inode, sb->s_blocksize); } if (create || was_dirty) mark_inode_dirty(inode); return 0; }
/* Get a block at iblock for inode, possibly allocating if create */ int hfsplus_get_block(struct inode *inode, sector_t iblock, struct buffer_head *bh_result, int create) { struct super_block *sb; int res = -EIO; u32 ablock, dblock, mask; int shift; hfsplus_handle_t *hfsplus_handle, tmp_hfsplus_handle; tmp_hfsplus_handle.journaled = !HFSPLUS_JOURNAL_PRESENT; tmp_hfsplus_handle.handle = NULL; sb = inode->i_sb; /* Journal device */ if (HFSPLUS_SB(sb).jnl.journaled == HFSPLUS_JOURNAL_PRESENT) { /* Write Metadata */ if (((inode->i_mapping->a_ops == &hfsplus_journalled_btree_aops) || (inode->i_mapping->a_ops == &hfsplus_journalled_aops)) && create) { hfsplus_handle = hfsplus_jbd_current_handle(); if (hfsplus_handle == NULL) { printk("hfsplus_handle is NULL\n"); hfsplus_handle = &tmp_hfsplus_handle; } } else { hfsplus_handle = &tmp_hfsplus_handle; } } /* Non-journal device */ else { hfsplus_handle = &tmp_hfsplus_handle; } /* Convert inode block to disk allocation block */ shift = HFSPLUS_SB(sb).alloc_blksz_shift - sb->s_blocksize_bits; ablock = iblock >> HFSPLUS_SB(sb).fs_shift; if (iblock >= HFSPLUS_I(inode).fs_blocks) { if (iblock > HFSPLUS_I(inode).fs_blocks || !create) { return -EIO; } if (ablock >= HFSPLUS_I(inode).alloc_blocks) { res = hfsplus_file_extend(hfsplus_handle, inode); if (res) { return res; } } } else create = 0; if (ablock < HFSPLUS_I(inode).first_blocks) { dblock = hfsplus_ext_find_block(HFSPLUS_I(inode).first_extents, ablock); goto done; } mutex_lock(&HFSPLUS_I(inode).extents_lock); res = hfsplus_ext_read_extent(hfsplus_handle, inode, ablock); if (!res) { dblock = hfsplus_ext_find_block(HFSPLUS_I(inode).cached_extents, ablock - HFSPLUS_I(inode).cached_start); } else { mutex_unlock(&HFSPLUS_I(inode).extents_lock); return -EIO; } mutex_unlock(&HFSPLUS_I(inode).extents_lock); done: dprint(DBG_EXTENT, "get_block(%lu): %llu - %u\n", inode->i_ino, (long long)iblock, dblock); mask = (1 << HFSPLUS_SB(sb).fs_shift) - 1; map_bh(bh_result, sb, (dblock << HFSPLUS_SB(sb).fs_shift) + HFSPLUS_SB(sb).blockoffset + (iblock & mask)); if (create) { set_buffer_new(bh_result); HFSPLUS_I(inode).phys_size += sb->s_blocksize; HFSPLUS_I(inode).fs_blocks++; inode_add_bytes(inode, sb->s_blocksize); if (hfsplus_journalled_mark_inode_dirty(__FUNCTION__, hfsplus_handle, inode)) { printk("HFS+-fs: Error in %s()\n", __FUNCTION__); return -1; } } return 0; }