NTSTATUS Ext2DoExtentExpand( IN PEXT2_IRP_CONTEXT IrpContext, IN PEXT2_VCB Vcb, IN PEXT2_MCB Mcb, IN ULONG Index, IN OUT PULONG Block, IN OUT PULONG Number ) { EXT4_EXTENT_HEADER *eh; struct buffer_head bh_got; int rc, flags; if (IsMcbDirectory(Mcb) || IrpContext->MajorFunction == IRP_MJ_WRITE) { flags = EXT4_GET_BLOCKS_IO_CONVERT_EXT; } else { flags = EXT4_GET_BLOCKS_IO_CREATE_EXT; } memset(&bh_got, 0, sizeof(struct buffer_head)); eh = get_ext4_header(&Mcb->Inode); if (eh->eh_magic != EXT4_EXT_MAGIC) { ext4_ext_tree_init(IrpContext, NULL, &Mcb->Inode); } if ((rc = ext4_ext_get_blocks( IrpContext, NULL, &Mcb->Inode, Index, *Number, &bh_got, 1, flags)) < 0) { DEBUG(DL_ERR, ("Expand Block insufficient resources, Number: %u," " err: %d\n", *Number, rc)); DbgBreak(); return Ext2WinntError(rc); } if (Number) *Number = rc ? rc : 1; if (Block) *Block = (ULONG)bh_got.b_blocknr; Ext2SaveInode(IrpContext, Vcb, &Mcb->Inode); return STATUS_SUCCESS; }
NTSTATUS Ext2MapExtent( IN PEXT2_IRP_CONTEXT IrpContext, IN PEXT2_VCB Vcb, IN PEXT2_MCB Mcb, IN ULONG Index, IN BOOLEAN Alloc, OUT PULONG Block, OUT PULONG Number ) { EXT4_EXTENT_HEADER *eh; struct buffer_head bh_got; int flags, rc; ULONG max_blocks = 0; memset(&bh_got, 0, sizeof(struct buffer_head)); eh = get_ext4_header(&Mcb->Inode); if (eh->eh_magic != EXT4_EXT_MAGIC) { if (Alloc) { /* now initialize inode extent root node */ ext4_ext_tree_init(IrpContext, NULL, &Mcb->Inode); } else { /* return empty-mapping when inode extent isn't initialized */ if (Block) *Block = 0; if (Number) { LONGLONG _len = _len = Mcb->Inode.i_size; if (Mcb->Fcb) _len = Mcb->Fcb->Header.AllocationSize.QuadPart; *Number = (ULONG)((_len + BLOCK_SIZE - 1) >> BLOCK_BITS); } return STATUS_SUCCESS; } } /* IrpContext is NULL when called during journal initialization */ if (IsMcbDirectory(Mcb) || IrpContext == NULL || IrpContext->MajorFunction == IRP_MJ_WRITE || !Alloc){ flags = EXT4_GET_BLOCKS_IO_CONVERT_EXT; max_blocks = EXT_INIT_MAX_LEN; } else { flags = EXT4_GET_BLOCKS_IO_CREATE_EXT; max_blocks = EXT_UNWRITTEN_MAX_LEN; } if ((rc = ext4_ext_get_blocks( IrpContext, NULL, &Mcb->Inode, Index, max_blocks, &bh_got, Alloc, flags)) < 0) { DEBUG(DL_ERR, ("Block insufficient resources, err: %d\n", rc)); return Ext2WinntError(rc); } if (Alloc) Ext2SaveInode(IrpContext, Vcb, &Mcb->Inode); if (Number) *Number = rc ? rc : 1; if (Block) *Block = (ULONG)bh_got.b_blocknr; return STATUS_SUCCESS; }
static int ext2_ext_balloc(struct inode *ip, uint32_t lbn, int size, struct ucred *cred, struct buf **bpp, int flags) { struct m_ext2fs *fs; struct buf *bp = NULL; struct vnode *vp = ITOV(ip); daddr_t newblk; int osize, nsize, blks, error, allocated; fs = ip->i_e2fs; blks = howmany(size, fs->e2fs_bsize); error = ext4_ext_get_blocks(ip, lbn, blks, cred, NULL, &allocated, &newblk); if (error) return (error); if (allocated) { if (ip->i_size < (lbn + 1) * fs->e2fs_bsize) nsize = fragroundup(fs, size); else nsize = fs->e2fs_bsize; bp = getblk(vp, lbn, nsize, 0, 0, 0); if(!bp) return (EIO); bp->b_blkno = fsbtodb(fs, newblk); if (flags & BA_CLRBUF) vfs_bio_clrbuf(bp); } else { if (ip->i_size >= (lbn + 1) * fs->e2fs_bsize) { error = bread(vp, lbn, fs->e2fs_bsize, NOCRED, &bp); if (error) { brelse(bp); return (error); } bp->b_blkno = fsbtodb(fs, newblk); *bpp = bp; return (0); } /* * Consider need to reallocate a fragment. */ osize = fragroundup(fs, blkoff(fs, ip->i_size)); nsize = fragroundup(fs, size); if (nsize <= osize) error = bread(vp, lbn, osize, NOCRED, &bp); else error = bread(vp, lbn, fs->e2fs_bsize, NOCRED, &bp); if (error) { brelse(bp); return (error); } bp->b_blkno = fsbtodb(fs, newblk); } *bpp = bp; return (error); }