ReactOS  0.4.13-dev-101-g0ca4b50
extents.c
Go to the documentation of this file.
1 /*
2  * COPYRIGHT: See COPYRIGHT.TXT
3  * PROJECT: Ext2 File System Driver for WinNT/2K/XP
4  * FILE: extents.c
5  * PROGRAMMER: Matt Wu <mattwu@163.com>
6  * HOMEPAGE: http://www.ext2fsd.com
7  * UPDATE HISTORY:
8  */
9 
10 /* INCLUDES *****************************************************************/
11 
12 #include "ext2fs.h"
13 
14 /* GLOBALS *****************************************************************/
15 
17 
18 /* DEFINITIONS *************************************************************/
19 
20 #ifdef ALLOC_PRAGMA
21 #endif
22 
23 
26  IN PEXT2_IRP_CONTEXT IrpContext,
29  IN ULONG Index,
31  OUT PULONG Block,
33 )
34 {
35  EXT4_EXTENT_HEADER *eh;
36  struct buffer_head bh_got = {0};
37  int flags, rc;
38  ULONG max_blocks = 0;
39 
40  memset(&bh_got, 0, sizeof(struct buffer_head));
41  eh = get_ext4_header(&Mcb->Inode);
42 
43  if (eh->eh_magic != EXT4_EXT_MAGIC) {
44  if (Alloc) {
45  /* now initialize inode extent root node */
46  ext4_ext_tree_init(IrpContext, NULL, &Mcb->Inode);
47  } else {
48  /* return empty-mapping when inode extent isn't initialized */
49  if (Block)
50  *Block = 0;
51  if (Number) {
52  LONGLONG _len = _len = Mcb->Inode.i_size;
53  if (Mcb->Fcb)
54  _len = Mcb->Fcb->Header.AllocationSize.QuadPart;
55  *Number = (ULONG)((_len + BLOCK_SIZE - 1) >> BLOCK_BITS);
56  }
57  return STATUS_SUCCESS;
58  }
59  }
60 
61  /* IrpContext is NULL when called during journal initialization */
62  if (IsMcbDirectory(Mcb) || IrpContext == NULL ||
63  IrpContext->MajorFunction == IRP_MJ_WRITE || !Alloc){
65  max_blocks = EXT_INIT_MAX_LEN;
66  } else {
68  max_blocks = EXT_UNWRITTEN_MAX_LEN;
69  }
70 
71  if (Alloc) {
72  if (Number && !*Number) {
73  if (max_blocks > *Number) {
74  max_blocks = *Number;
75  }
76  } else {
77  max_blocks = 1;
78  }
79  }
80 
81  if ((rc = ext4_ext_get_blocks(
82  IrpContext,
83  NULL,
84  &Mcb->Inode,
85  Index,
86  max_blocks,
87  &bh_got,
88  Alloc,
89  flags)) < 0) {
90  DEBUG(DL_ERR, ("Block insufficient resources, err: %d\n", rc));
91  return Ext2WinntError(rc);
92  }
93  if (Alloc)
94  Ext2SaveInode(IrpContext, Vcb, &Mcb->Inode);
95  if (Number)
96  *Number = rc ? rc : 1;
97  if (Block)
98  *Block = (ULONG)bh_got.b_blocknr;
99 
100  return STATUS_SUCCESS;
101 }
102 
103 
104 NTSTATUS
106  IN PEXT2_IRP_CONTEXT IrpContext,
107  IN PEXT2_VCB Vcb,
108  IN PEXT2_MCB Mcb,
109  IN ULONG Index,
110  IN OUT PULONG Block,
112 )
113 {
114  EXT4_EXTENT_HEADER *eh;
115  struct buffer_head bh_got;
116  int rc, flags;
117 
118  if (IsMcbDirectory(Mcb) || IrpContext->MajorFunction == IRP_MJ_WRITE) {
120  } else {
122  }
123 
124  memset(&bh_got, 0, sizeof(struct buffer_head));
125  eh = get_ext4_header(&Mcb->Inode);
126 
127  if (eh->eh_magic != EXT4_EXT_MAGIC) {
128  ext4_ext_tree_init(IrpContext, NULL, &Mcb->Inode);
129  }
130 
131  if ((rc = ext4_ext_get_blocks( IrpContext, NULL, &Mcb->Inode, Index,
132  *Number, &bh_got, 1, flags)) < 0) {
133  DEBUG(DL_ERR, ("Expand Block insufficient resources, Number: %u,"
134  " err: %d\n", *Number, rc));
135  DbgBreak();
136  return Ext2WinntError(rc);
137  }
138 
139  if (Number)
140  *Number = rc ? rc : 1;
141  if (Block)
142  *Block = (ULONG)bh_got.b_blocknr;
143 
144  Ext2SaveInode(IrpContext, Vcb, &Mcb->Inode);
145 
146  return STATUS_SUCCESS;
147 }
148 
149 
150 NTSTATUS
152  PEXT2_IRP_CONTEXT IrpContext,
153  PEXT2_VCB Vcb,
154  PEXT2_MCB Mcb,
155  ULONG Start,
156  ULONG End,
158  )
159 {
160  ULONG Count = 0, Number = 0, Block = 0;
162 
163  if (End <= Start)
164  return Status;
165 
166  while (End > Start + Count) {
167 
168  Number = End - Start - Count;
169  Status = Ext2DoExtentExpand(IrpContext, Vcb, Mcb, Start + Count,
170  &Block, &Number);
171  if (!NT_SUCCESS(Status)) {
173  break;
174  }
175  if (Number == 0) {
177  break;
178  }
179 
180  if (Block && IsZoneInited(Mcb)) {
181  if (!Ext2AddBlockExtent(Vcb, Mcb, Start + Count, Block, Number)) {
182  DbgBreak();
183  ClearFlag(Mcb->Flags, MCB_ZONE_INITED);
184  Ext2ClearAllExtents(&Mcb->Extents);
185  }
186  }
187  Count += Number;
188  }
189 
190  Size->QuadPart = ((LONGLONG)(Start + Count)) << BLOCK_BITS;
191 
192  /* save inode whatever it succeeds to expand or not */
193  Ext2SaveInode(IrpContext, Vcb, &Mcb->Inode);
194 
195  return Status;
196 }
197 
198 
199 NTSTATUS
201  PEXT2_IRP_CONTEXT IrpContext,
202  PEXT2_VCB Vcb,
203  PEXT2_MCB Mcb,
205  )
206 {
208 
209  ULONG Extra = 0;
210  ULONG Wanted = 0;
211  ULONG End;
212  ULONG Removed;
213  int err;
214 
215  /* translate file size to block */
216  End = Vcb->max_data_blocks;
217  Wanted = (ULONG)((Size->QuadPart + BLOCK_SIZE - 1) >> BLOCK_BITS);
218 
219  /* calculate blocks to be freed */
220  Extra = End - Wanted;
221 
222  err = ext4_ext_truncate(IrpContext, &Mcb->Inode, Wanted);
223  if (err == 0) {
224  if (!Ext2RemoveBlockExtent(Vcb, Mcb, Wanted, Extra)) {
225  ClearFlag(Mcb->Flags, MCB_ZONE_INITED);
226  Ext2ClearAllExtents(&Mcb->Extents);
227  }
228  Extra = 0;
229  } else {
231  }
232 
233  if (!NT_SUCCESS(Status)) {
234  Size->QuadPart += ((ULONGLONG)Extra << BLOCK_BITS);
235  }
236 
237  if (Mcb->Inode.i_size > (loff_t)(Size->QuadPart))
238  Mcb->Inode.i_size = (loff_t)(Size->QuadPart);
239 
240  /* Save modifications on i_blocks field and i_size field of the inode. */
241  Ext2SaveInode(IrpContext, Vcb, &Mcb->Inode);
242 
243  return Status;
244 }
#define EXT4_EXT_MAGIC
Definition: ext4_ext.h:50
NTSTATUS Ext2WinntError(int rc)
Definition: misc.c:410
#define IN
Definition: typedefs.h:38
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
#define IsMcbDirectory(Mcb)
Definition: ext2fs.h:958
VOID Ext2ClearAllExtents(PLARGE_MCB Zone)
Definition: memory.c:637
LONG NTSTATUS
Definition: precomp.h:26
_Inout_ __drv_aliasesMem PSLIST_ENTRY _Inout_ PSLIST_ENTRY _In_ ULONG Count
Definition: exfuncs.h:1015
int ext4_ext_get_blocks(void *icb, handle_t *handle, struct inode *inode, ext4_fsblk_t iblock, unsigned long max_blocks, struct buffer_head *bh_result, int create, int flags)
int ext4_ext_tree_init(void *icb, handle_t *handle, struct inode *inode)
unsigned char BOOLEAN
#define BLOCK_BITS
Definition: stream.h:22
smooth NULL
Definition: ftsmooth.c:416
#define EXT4_GET_BLOCKS_IO_CREATE_EXT
Definition: ext4.h:33
#define EXT_UNWRITTEN_MAX_LEN
Definition: ext4_ext.h:102
BOOLEAN Ext2RemoveBlockExtent(IN PEXT2_VCB Vcb, IN PEXT2_MCB Mcb, IN ULONG Start, IN ULONG Number)
Definition: memory.c:1097
int64_t LONGLONG
Definition: typedefs.h:66
#define BLOCK_SIZE
Definition: dlist.c:220
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
uint64_t ULONGLONG
Definition: typedefs.h:65
NTSTATUS Ext2TruncateExtent(PEXT2_IRP_CONTEXT IrpContext, PEXT2_VCB Vcb, PEXT2_MCB Mcb, PLARGE_INTEGER Size)
Definition: extents.c:200
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)
Definition: extents.c:25
#define Vcb
Definition: cdprocs.h:1425
static const UCHAR Index[8]
Definition: usbohci.c:18
PVOID Alloc(IN DWORD dwFlags, IN SIZE_T dwBytes)
Definition: main.c:63
blkcnt_t b_blocknr
Definition: module.h:723
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)
Definition: extents.c:105
Definition: partlist.h:33
GLbitfield flags
Definition: glext.h:7161
int ext4_ext_truncate(void *icb, struct inode *inode, unsigned long start)
unsigned __int64 loff_t
Definition: types.h:80
NTSTATUS Ext2ExpandExtent(PEXT2_IRP_CONTEXT IrpContext, PEXT2_VCB Vcb, PEXT2_MCB Mcb, ULONG Start, ULONG End, PLARGE_INTEGER Size)
Definition: extents.c:151
#define get_ext4_header(i)
Definition: ext4_ext.h:51
#define err(...)
IN PVOID IN PVOID IN USHORT IN USHORT Size
Definition: pci.h:359
_In_opt_ PENTER_STATE_SYSTEM_HANDLER _In_opt_ PVOID _In_ LONG _In_opt_ LONG volatile * Number
Definition: ntpoapi.h:204
PEXT2_GLOBAL Ext2Global
Definition: init.c:16
#define EXT4_GET_BLOCKS_IO_CONVERT_EXT
Definition: ext4.h:36
ClearFlag(Dirent->Flags, DIRENT_FLAG_NOT_PERSISTENT)
Status
Definition: gdiplustypes.h:24
#define DL_ERR
Definition: ext2fs.h:1397
#define MCB_ZONE_INITED
Definition: ext2fs.h:948
IN PVCB IN ULONG IN OUT PULONG IN BOOLEAN OUT PLARGE_MCB Mcb
Definition: fatprocs.h:334
unsigned int * PULONG
Definition: retypes.h:1
#define OUT
Definition: typedefs.h:39
unsigned int ULONG
Definition: retypes.h:1
#define DbgBreak()
Definition: ext2fs.h:46
#define IRP_MJ_WRITE
Definition: rdpdr.c:47
#define DEBUG(args)
Definition: rdesktop.h:129
Definition: fbtusb.h:86
#define EXT_INIT_MAX_LEN
Definition: ext4_ext.h:101
return STATUS_SUCCESS
Definition: btrfs.c:2725
#define memset(x, y, z)
Definition: compat.h:39
BOOLEAN Ext2SaveInode(IN PEXT2_IRP_CONTEXT IrpContext, IN PEXT2_VCB Vcb, IN struct inode *Inode)
Definition: generic.c:548
BOOLEAN Ext2AddBlockExtent(IN PEXT2_VCB Vcb, IN PEXT2_MCB Mcb, IN ULONG Start, IN ULONG Block, IN ULONG Number)
Definition: memory.c:1027
#define IsZoneInited(Mcb)
Definition: ext2fs.h:954