2 * COPYRIGHT: See COPYRIGHT.TXT
3 * PROJECT: Ext2 File System Driver for WinNT/2K/XP
5 * PROGRAMMER: Matt Wu <mattwu@163.com>
6 * HOMEPAGE: http://www.ext2fsd.com
10 /* INCLUDES *****************************************************************/
14 /* GLOBALS *****************************************************************/
16 extern PEXT2_GLOBAL Ext2Global
;
18 /* DEFINITIONS *************************************************************/
26 IN PEXT2_IRP_CONTEXT IrpContext
,
35 EXT4_EXTENT_HEADER
*eh
;
36 struct buffer_head bh_got
;
40 memset(&bh_got
, 0, sizeof(struct buffer_head
));
41 eh
= get_ext4_header(&Mcb
->Inode
);
43 if (eh
->eh_magic
!= EXT4_EXT_MAGIC
) {
45 /* now initialize inode extent root node */
46 ext4_ext_tree_init(IrpContext
, NULL
, &Mcb
->Inode
);
48 /* return empty-mapping when inode extent isn't initialized */
52 LONGLONG _len
= _len
= Mcb
->Inode
.i_size
;
54 _len
= Mcb
->Fcb
->Header
.AllocationSize
.QuadPart
;
55 *Number
= (ULONG
)((_len
+ BLOCK_SIZE
- 1) >> BLOCK_BITS
);
57 return STATUS_SUCCESS
;
61 /* IrpContext is NULL when called during journal initialization */
62 if (IsMcbDirectory(Mcb
) || IrpContext
== NULL
||
63 IrpContext
->MajorFunction
== IRP_MJ_WRITE
|| !Alloc
){
64 flags
= EXT4_GET_BLOCKS_IO_CONVERT_EXT
;
65 max_blocks
= EXT_INIT_MAX_LEN
;
67 flags
= EXT4_GET_BLOCKS_IO_CREATE_EXT
;
68 max_blocks
= EXT_UNWRITTEN_MAX_LEN
;
71 if ((rc
= ext4_ext_get_blocks(
80 DEBUG(DL_ERR
, ("Block insufficient resources, err: %d\n", rc
));
81 return Ext2WinntError(rc
);
84 Ext2SaveInode(IrpContext
, Vcb
, &Mcb
->Inode
);
86 *Number
= rc
? rc
: 1;
88 *Block
= (ULONG
)bh_got
.b_blocknr
;
90 return STATUS_SUCCESS
;
96 IN PEXT2_IRP_CONTEXT IrpContext
,
104 EXT4_EXTENT_HEADER
*eh
;
105 struct buffer_head bh_got
;
108 if (IsMcbDirectory(Mcb
) || IrpContext
->MajorFunction
== IRP_MJ_WRITE
) {
109 flags
= EXT4_GET_BLOCKS_IO_CONVERT_EXT
;
111 flags
= EXT4_GET_BLOCKS_IO_CREATE_EXT
;
114 memset(&bh_got
, 0, sizeof(struct buffer_head
));
115 eh
= get_ext4_header(&Mcb
->Inode
);
117 if (eh
->eh_magic
!= EXT4_EXT_MAGIC
) {
118 ext4_ext_tree_init(IrpContext
, NULL
, &Mcb
->Inode
);
121 if ((rc
= ext4_ext_get_blocks( IrpContext
, NULL
, &Mcb
->Inode
, Index
,
122 *Number
, &bh_got
, 1, flags
)) < 0) {
123 DEBUG(DL_ERR
, ("Expand Block insufficient resources, Number: %u,"
124 " err: %d\n", *Number
, rc
));
126 return Ext2WinntError(rc
);
130 *Number
= rc
? rc
: 1;
132 *Block
= (ULONG
)bh_got
.b_blocknr
;
134 Ext2SaveInode(IrpContext
, Vcb
, &Mcb
->Inode
);
136 return STATUS_SUCCESS
;
142 PEXT2_IRP_CONTEXT IrpContext
,
150 ULONG Count
= 0, Number
= 0, Block
= 0;
151 NTSTATUS Status
= STATUS_SUCCESS
;
156 while (End
> Start
+ Count
) {
158 Number
= End
- Start
- Count
;
159 Status
= Ext2DoExtentExpand(IrpContext
, Vcb
, Mcb
, Start
+ Count
,
161 if (!NT_SUCCESS(Status
)) {
162 Status
= STATUS_INSUFFICIENT_RESOURCES
;
166 Status
= STATUS_INSUFFICIENT_RESOURCES
;
170 if (Block
&& IsZoneInited(Mcb
)) {
171 if (!Ext2AddBlockExtent(Vcb
, Mcb
, Start
+ Count
, Block
, Number
)) {
173 ClearFlag(Mcb
->Flags
, MCB_ZONE_INITED
);
174 Ext2ClearAllExtents(&Mcb
->Extents
);
180 Size
->QuadPart
= ((LONGLONG
)(Start
+ Count
)) << BLOCK_BITS
;
182 /* save inode whatever it succeeds to expand or not */
183 Ext2SaveInode(IrpContext
, Vcb
, &Mcb
->Inode
);
191 PEXT2_IRP_CONTEXT IrpContext
,
197 NTSTATUS Status
= STATUS_SUCCESS
;
205 /* translate file size to block */
206 End
= Vcb
->max_data_blocks
;
207 Wanted
= (ULONG
)((Size
->QuadPart
+ BLOCK_SIZE
- 1) >> BLOCK_BITS
);
209 /* calculate blocks to be freed */
210 Extra
= End
- Wanted
;
212 err
= ext4_ext_remove_space(IrpContext
, &Mcb
->Inode
, Wanted
);
214 if (!Ext2RemoveBlockExtent(Vcb
, Mcb
, Wanted
, Extra
)) {
215 ClearFlag(Mcb
->Flags
, MCB_ZONE_INITED
);
216 Ext2ClearAllExtents(&Mcb
->Extents
);
220 Status
= STATUS_INSUFFICIENT_RESOURCES
;
223 if (!NT_SUCCESS(Status
)) {
224 Size
->QuadPart
+= ((ULONGLONG
)Extra
<< BLOCK_BITS
);
228 if (Mcb
->Inode
.i_size
> (loff_t
)(Size
->QuadPart
))
229 Mcb
->Inode
.i_size
= (loff_t
)(Size
->QuadPart
);
230 Ext2SaveInode(IrpContext
, Vcb
, &Mcb
->Inode
);