Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions libvmfs/vmfs_file.c
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,11 @@ ssize_t vmfs_file_pread(vmfs_file_t *f,u_char *buf,size_t len,off_t pos)
break;
}

/* Pointer-Block, if we get here we failed to resolve pointer */
case VMFS_BLK_TYPE_PB:
fprintf(stderr, "VMFS: Pointer block at id 0x%8.8x\n", blk_id);
return(-EINVAL);

/* Inline in the inode */
case VMFS_BLK_TYPE_FD:
if (blk_id == f->inode->id) {
Expand Down
118 changes: 90 additions & 28 deletions libvmfs/vmfs_inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -311,36 +311,20 @@ int vmfs_inode_get_block(const vmfs_inode_t *inode,off_t pos,uint32_t *blk_id)

case VMFS_BLK_TYPE_PB:
{
DECL_ALIGNED_BUFFER_WOL(buf,fs->pbc->bmh.data_size);
uint32_t pb_blk_id;
uint32_t blk_per_pb;
u_int pb_index;
u_int sub_index;

blk_per_pb = fs->pbc->bmh.data_size / sizeof(uint32_t);
blk_index = pos / inode->blk_size;

pb_index = blk_index / blk_per_pb;
sub_index = blk_index % blk_per_pb;

if (pb_index >= VMFS_INODE_BLK_COUNT)
return(-EINVAL);

pb_blk_id = inode->blocks[pb_index];

if (!pb_blk_id)
break;

if (!vmfs_bitmap_get_item(fs->pbc,
VMFS_BLK_PB_ENTRY(pb_blk_id),
VMFS_BLK_PB_ITEM(pb_blk_id),
buf))
return(-EIO);

*blk_id = read_le32(buf,sub_index*sizeof(uint32_t));
int pointer_result = -EINVAL;
if (inode->blk_size == VMFS_DP_BLOCK_SZ &&
inode->size > VMFS_SP_MAX_SZ) {
pointer_result = vmfs_dp_get_block(fs, inode, pos, blk_id);
} else {
pointer_result = vmfs_sp_get_block(fs, inode, pos, blk_id);
}
if (pointer_result) {
fprintf(stderr, "Error in resolving pointer block: %d\n",
pointer_result);
return(pointer_result);
}
break;
}

case VMFS_BLK_TYPE_FD:
if (vmfs5_extension) {
*blk_id = inode->id;
Expand All @@ -354,6 +338,84 @@ int vmfs_inode_get_block(const vmfs_inode_t *inode,off_t pos,uint32_t *blk_id)
return(0);
}

/* read pointer to get block id */
int vmfs_sp_get_block(const vmfs_fs_t *fs, const vmfs_inode_t *inode, off_t pos,
uint32_t *blk_id) {
DECL_ALIGNED_BUFFER_WOL(buf,fs->pbc->bmh.data_size);
uint32_t pb_blk_id;
uint32_t blk_per_pb;
u_int pb_index;
u_int sub_index;
u_int blk_index;

blk_per_pb = fs->pbc->bmh.data_size / sizeof(uint32_t);
blk_index = pos / inode->blk_size;

pb_index = blk_index / blk_per_pb;
sub_index = blk_index % blk_per_pb;

if (pb_index >= VMFS_INODE_BLK_COUNT)
return(-EINVAL);

pb_blk_id = inode->blocks[pb_index];

if (!pb_blk_id) {
return(0);
}

if (!vmfs_bitmap_get_item(fs->pbc,
VMFS_BLK_PB_ENTRY(pb_blk_id),
VMFS_BLK_PB_ITEM(pb_blk_id),
buf)) {
return(-EIO);
}

*blk_id = read_le32(buf,sub_index*sizeof(uint32_t));

return(0);
}

/* read double pointer to get block */
int vmfs_dp_get_block(const vmfs_fs_t *fs, const vmfs_inode_t *inode, off_t pos,
uint32_t *blk_id) {
DECL_ALIGNED_BUFFER_WOL(buf,fs->pbc->bmh.data_size);
uint32_t pb_blk_id;
uint32_t di_blk_id;
uint32_t blk_per_pb;
u_int pb_index;
u_int sub_index;
u_int blk_index;
u_int di_pb_index;

blk_per_pb = fs->pbc->bmh.data_size / sizeof(uint32_t);
blk_index = pos / inode->blk_size;
pb_index = blk_index / (blk_per_pb * blk_per_pb);
di_pb_index = (blk_index / blk_per_pb) % blk_per_pb;
sub_index = blk_index % blk_per_pb;
pb_blk_id = inode->blocks[pb_index];

if (!pb_blk_id) {
return(0);
}
// read first pointer block
if (!vmfs_bitmap_get_item(fs->pbc,
VMFS_BLK_PB_ENTRY(pb_blk_id),
VMFS_BLK_PB_ITEM(pb_blk_id),
buf)) {
return(-EIO);
}
di_blk_id = read_le32(buf,di_pb_index*sizeof(uint32_t));
// read second pointer block
if (!vmfs_bitmap_get_item(fs->pbc,
VMFS_BLK_PB_ENTRY(di_blk_id),
VMFS_BLK_PB_ITEM(di_blk_id),
buf)) {
return(-EIO);
}
*blk_id = read_le32(buf, sub_index*sizeof(uint32_t));
return(0);
}

/* Aggregate a sub-block to a file block */
static int vmfs_inode_aggregate_fb(vmfs_inode_t *inode)
{
Expand Down
9 changes: 9 additions & 0 deletions libvmfs/vmfs_inode.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@

#define VMFS_INODE_MAGIC 0x10c00001

#define VMFS_DP_BLOCK_SZ 0x100000
#define VMFS_SP_MAX_SZ 0x4000000000

struct vmfs_inode_raw {
struct vmfs_metadata_hdr_raw mdh;
uint32_t id;
Expand Down Expand Up @@ -136,6 +139,12 @@ int vmfs_inode_alloc(vmfs_fs_t *fs,u_int type,mode_t mode,vmfs_inode_t **inode);
*/
int vmfs_inode_get_block(const vmfs_inode_t *inode,off_t pos,uint32_t *blk_id);

/* Get block id from pointer block */
int vmfs_sp_get_block(const vmfs_fs_t *fs, const vmfs_inode_t *inode, off_t pos, uint32_t *blk_id);

/* Get block id from double indirect pointer block */
int vmfs_dp_get_block(const vmfs_fs_t *fs, const vmfs_inode_t *inode, off_t pos, uint32_t *blk_id);

/* Get a block for writing corresponding to the specified position */
int vmfs_inode_get_wrblock(vmfs_inode_t *inode,off_t pos,uint32_t *blk_id);

Expand Down