/* Get pblock for a given inode and lblock. If extent is not NULL, it will * store the length of extent, that is, the number of consecutive pblocks * that are also consecutive lblocks (not counting the requested one). */ uint64_t inode_get_data_pblock(struct ext4_inode *inode, uint32_t lblock, uint32_t *extent_len) { if (extent_len) *extent_len = 1; if (inode->i_flags & EXT4_EXTENTS_FL) { return extent_get_pblock(&inode->i_block, lblock, extent_len); } else { ASSERT(lblock <= BYTES2BLOCKS(inode_get_size(inode))); if (lblock < EXT4_NDIR_BLOCKS) { return inode->i_block[lblock]; } else if (lblock < MAX_IND_BLOCK) { uint32_t index_block = inode->i_block[EXT4_IND_BLOCK]; return __inode_get_data_pblock_ind(lblock - EXT4_NDIR_BLOCKS, index_block); } else if (lblock < MAX_DIND_BLOCK) { uint32_t dindex_block = inode->i_block[EXT4_DIND_BLOCK]; return __inode_get_data_pblock_dind(lblock - MAX_IND_BLOCK, dindex_block); } else if (lblock < MAX_TIND_BLOCK) { uint32_t tindex_block = inode->i_block[EXT4_TIND_BLOCK]; return __inode_get_data_pblock_tind(lblock - MAX_DIND_BLOCK, tindex_block); } else { /* File-system corruption? */ ASSERT(0); } } /* Should never reach here */ ASSERT(0); return 0; }
/* * _sdsset sets all bytes in an SDS data segment to a specified value. * * Both byte_offset and nbytes must be 512-word block multiples. * * Returns byte_offset on normal return. If an error is encountered -1 is * returned with the error code in errno. */ _sdsset( int byte_offset, /* Byte offset into SDS area */ int value, /* Value to which all bytes should be set */ int nbytes) /* Number of bytes to set */ { #define _BUFFER_BLOCKS 10 char bytebuf[_BUFFER_BLOCKS * BYTPBLOCK]; /* must be word-aligned */ int nblocks; int blk_offset; int ret; int this_chunk; int left; /* check that byte_offset and nbytes are on block boundaries */ if ((byte_offset | nbytes) & (BYTPBLOCK - 1)) { errno = FDC_ERR_GRAN; return -1; } nblocks = BYTES2BLOCKS(nbytes); blk_offset = BYTES2BLOCKS(byte_offset); (void)memset(bytebuf, value, MIN(nblocks, _BUFFER_BLOCKS) * BYTPBLOCK); left = nblocks; while (left > 0) { this_chunk = MIN(left, _BUFFER_BLOCKS); ret = sswrite((long)bytebuf, blk_offset, this_chunk); if (ret == -1) { errno = FDC_ERR_SDSIO; return -1; } left -= this_chunk; blk_offset += this_chunk; } return byte_offset; }
_sdsset_any( int byte_offset, /* Byte offset into SDS area */ int value, /* Value to which all bytes should be set */ int nbytes) /* Number of bytes to set */ { #define _BUFFER_BLOCKS 10 char bytebuf[_BUFFER_BLOCKS * BYTPBLOCK]; /* must be word-aligned */ int nblocks; int blk_offset; int ret; int this_chunk; int left; int lblk_offset; int headbytes,tailbytes; int orig_byte_offset; orig_byte_offset = byte_offset; nblocks = BYTES2BLOCKS(nbytes); blk_offset = BYTES2BLOCKS(byte_offset); /* if byte_offset is not on a block boundary */ if ((byte_offset) & (BYTPBLOCK - 1)) { headbytes = BYTPBLOCK - (byte_offset & (BYTPBLOCK -1 )); if (headbytes > nbytes) headbytes = nbytes; ret = ssread(bytebuf, blk_offset, 1); if (ret == -1) { errno = FDC_ERR_SDSIO; return -1; } memset(bytebuf + (byte_offset & (BYTPBLOCK-1)), value, headbytes); ret = sswrite(bytebuf, blk_offset, 1); if (ret == -1) { errno = FDC_ERR_SDSIO; return -1; } nbytes -= headbytes; nblocks = BYTES2BLOCKS(nbytes); byte_offset += headbytes; blk_offset = BYTES2BLOCKS(byte_offset); } if (nbytes & (BYTPBLOCK - 1)){ /* these will be the bytes left over at the end */ tailbytes = nbytes & (BYTPBLOCK - 1); lblk_offset = BYTES2BLOCKS(byte_offset + nbytes -1); ret = ssread(bytebuf, lblk_offset, 1); if (ret == -1) { errno = FDC_ERR_SDSIO; return -1; } memset(bytebuf, value, tailbytes); ret = sswrite(bytebuf, lblk_offset, 1); if (ret == -1) { errno = FDC_ERR_SDSIO; return -1; } nbytes -= tailbytes; } if (nbytes & (BYTPBLOCK -1 )){ abort(); } (void)memset(bytebuf, value, MIN(nblocks, _BUFFER_BLOCKS) * BYTPBLOCK); left = nblocks; while (left > 0) { this_chunk = MIN(left, _BUFFER_BLOCKS); ret = sswrite((long)bytebuf, blk_offset, this_chunk); if (ret == -1) { errno = FDC_ERR_SDSIO; return -1; } left -= this_chunk; blk_offset += this_chunk; } return orig_byte_offset; }