ReactOS 0.4.15-dev-7704-gc07eb9f
write.c File Reference
#include "btrfs_drv.h"
Include dependency graph for write.c:

Go to the source code of this file.

Classes

struct  write_stripe
 
struct  stripe
 
struct  log_stripe
 

Functions

 _Function_class_ (IO_COMPLETION_ROUTINE)
 
 __attribute__ ((nonnull(1)))
 
 __attribute__ ((nonnull(1, 2)))
 
 __attribute__ ((nonnull(1, 3)))
 
 __attribute__ ((nonnull(1, 3, 5, 8)))
 
 __attribute__ ((nonnull(1, 2, 5)))
 
 __attribute__ ((nonnull(1, 2, 4, 6, 10)))
 
 __attribute__ ((nonnull(1, 3, 5)))
 
 __attribute__ ((nonnull(1, 4, 5)))
 
 __attribute__ ((nonnull(2, 3)))
 
 __attribute__ ((nonnull(1, 2, 3)))
 
 __attribute__ ((nonnull(1, 2, 6)))
 
 __attribute__ ((nonnull(1, 3, 7)))
 
 _Requires_lock_held_ (c->lock) _When_(return !=0
 
 _Releases_lock_ (c->lock)) __attribute__((nonnull(1
 
bool insert_extent_chunk (_In_ device_extension *Vcb, _In_ fcb *fcb, _In_ chunk *c, _In_ uint64_t start_data, _In_ uint64_t length, _In_ bool prealloc, _In_opt_ void *data, _In_opt_ PIRP Irp, _In_ LIST_ENTRY *rollback, _In_ uint8_t compression, _In_ uint64_t decoded_size, _In_ bool file_write, _In_ uint64_t irp_offset)
 
 __attribute__ ((nonnull(1, 2, 5, 7, 10)))
 
 __attribute__ ((nonnull(1, 4)))
 
 __attribute__ ((nonnull(1, 2, 5, 9)))
 
 __attribute__ ((nonnull(1, 6)))
 
 __attribute__ ((nonnull(1, 2, 5, 6, 11)))
 
 __attribute__ ((nonnull(1, 2, 4, 5, 11)))
 
 _Dispatch_type_ (IRP_MJ_WRITE)
 

Function Documentation

◆ __attribute__() [1/18]

__attribute__ ( (nonnull(1))  )

Definition at line 90 of file write.c.

91 {
92 LIST_ENTRY* le2;
93
94 ExAcquireResourceSharedLite(&Vcb->chunk_lock, true);
95
96 le2 = Vcb->chunks.Flink;
97 while (le2 != &Vcb->chunks) {
99
100 if (address >= c->offset && address < c->offset + c->chunk_item->size) {
101 ExReleaseResourceLite(&Vcb->chunk_lock);
102 return c;
103 }
104
105 le2 = le2->Flink;
106 }
107
108 ExReleaseResourceLite(&Vcb->chunk_lock);
109
110 return NULL;
111}
#define NULL
Definition: types.h:112
#define ExAcquireResourceSharedLite(res, wait)
Definition: env_spec_w32.h:621
GLuint address
Definition: glext.h:9393
const GLubyte * c
Definition: glext.h:8905
GLintptr offset
Definition: glext.h:5920
#define c
Definition: ke_i.h:80
VOID FASTCALL ExReleaseResourceLite(IN PERESOURCE Resource)
Definition: resource.c:1822
#define Vcb
Definition: cdprocs.h:1415
Definition: typedefs.h:120
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
Definition: list.h:27
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260

◆ __attribute__() [2/18]

__attribute__ ( (nonnull(1, 2))  )

Definition at line 140 of file write.c.

141 {
142 uint64_t devusage = 0xffffffffffffffff;
143 space *devdh1 = NULL, *devdh2 = NULL;
144 LIST_ENTRY* le;
145 device* dev2 = NULL;
146
147 le = Vcb->devices.Flink;
148
149 while (le != &Vcb->devices) {
151
152 if (!dev->readonly && !dev->reloc && dev->devobj) {
153 uint64_t usage = (dev->devitem.bytes_used * 4096) / dev->devitem.num_bytes;
154
155 // favour devices which have been used the least
156 if (usage < devusage) {
157 if (!IsListEmpty(&dev->space)) {
158 LIST_ENTRY* le2;
159 space *dh1 = NULL, *dh2 = NULL;
160
161 le2 = dev->space.Flink;
162 while (le2 != &dev->space) {
164
165 if (dh->size >= max_stripe_size && (!dh1 || !dh2 || dh->size < dh1->size)) {
166 dh2 = dh1;
167 dh1 = dh;
168 }
169
170 le2 = le2->Flink;
171 }
172
173 if (dh1 && (dh2 || dh1->size >= 2 * max_stripe_size)) {
174 dev2 = dev;
175 devusage = usage;
176 devdh1 = dh1;
177 devdh2 = dh2 ? dh2 : dh1;
178 }
179 }
180 }
181 }
182
183 le = le->Flink;
184 }
185
186 if (!devdh1) {
187 uint64_t size = 0;
188
189 // Can't find hole of at least max_stripe_size; look for the largest one we can find
190
191 if (full_size)
192 return false;
193
194 le = Vcb->devices.Flink;
195 while (le != &Vcb->devices) {
197
198 if (!dev->readonly && !dev->reloc) {
199 if (!IsListEmpty(&dev->space)) {
200 LIST_ENTRY* le2;
201 space *dh1 = NULL, *dh2 = NULL;
202
203 le2 = dev->space.Flink;
204 while (le2 != &dev->space) {
206
207 if (!dh1 || !dh2 || dh->size < dh1->size) {
208 dh2 = dh1;
209 dh1 = dh;
210 }
211
212 le2 = le2->Flink;
213 }
214
215 if (dh1) {
216 uint64_t devsize;
217
218 if (dh2)
219 devsize = max(dh1->size / 2, min(dh1->size, dh2->size));
220 else
221 devsize = dh1->size / 2;
222
223 if (devsize > size) {
224 dev2 = dev;
225 devdh1 = dh1;
226
227 if (dh2 && min(dh1->size, dh2->size) > dh1->size / 2)
228 devdh2 = dh2;
229 else
230 devdh2 = dh1;
231
232 size = devsize;
233 }
234 }
235 }
236 }
237
238 le = le->Flink;
239 }
240
241 if (!devdh1)
242 return false;
243 }
244
245 stripes[0].device = stripes[1].device = dev2;
246 stripes[0].dh = devdh1;
247 stripes[1].dh = devdh2;
248
249 return true;
250}
UINT64 uint64_t
Definition: types.h:77
#define IsListEmpty(ListHead)
Definition: env_spec_w32.h:954
GLsizeiptr size
Definition: glext.h:5919
GLsizeiptr const GLvoid GLenum usage
Definition: glext.h:5919
if(dx< 0)
Definition: linetemp.h:194
#define min(a, b)
Definition: monoChain.cc:55
Definition: devices.h:37
uint64_t size
Definition: btrfs_drv.h:519
#define max(a, b)
Definition: svc.c:63

◆ __attribute__() [3/18]

__attribute__ ( (nonnull(1, 2, 3))  )

Definition at line 2383 of file write.c.

2384 {
2385 LIST_ENTRY* le = prevextle->Flink;
2386
2387 while (le != &fcb->extents) {
2389
2390 if (ext->offset >= newext->offset) {
2391 InsertHeadList(ext->list_entry.Blink, &newext->list_entry);
2392 return;
2393 }
2394
2395 le = le->Flink;
2396 }
2397
2398 InsertTailList(&fcb->extents, &newext->list_entry);
2399}
static const WCHAR *const ext[]
Definition: module.c:53
#define InsertTailList(ListHead, Entry)
#define InsertHeadList(ListHead, Entry)
LIST_ENTRY extents
Definition: btrfs_drv.h:300

◆ __attribute__() [4/18]

__attribute__ ( (nonnull(1, 2, 4, 5, 11))  )

Definition at line 4098 of file write.c.

4100 {
4103 EXTENT_DATA* ed2;
4104 uint64_t off64, newlength, start_data, end_data;
4105 uint32_t bufhead;
4106 bool make_inline;
4107 INODE_ITEM* origii;
4108 bool changed_length = false;
4112 fcb* fcb;
4113 ccb* ccb;
4114 file_ref* fileref;
4115 bool paging_lock = false, acquired_fcb_lock = false, acquired_tree_lock = false, pagefile;
4116 ULONG filter = 0;
4117
4118 TRACE("(%p, %p, %I64x, %p, %lx, %u, %u)\n", Vcb, FileObject, offset.QuadPart, buf, *length, paging_io, no_cache);
4119
4120 if (*length == 0) {
4121 TRACE("returning success for zero-length write\n");
4122 return STATUS_SUCCESS;
4123 }
4124
4125 if (!FileObject) {
4126 ERR("error - FileObject was NULL\n");
4127 return STATUS_ACCESS_DENIED;
4128 }
4129
4130 fcb = FileObject->FsContext;
4131 ccb = FileObject->FsContext2;
4132 fileref = ccb ? ccb->fileref : NULL;
4133
4134 if (!fcb->ads && fcb->type != BTRFS_TYPE_FILE && fcb->type != BTRFS_TYPE_SYMLINK) {
4135 WARN("tried to write to something other than a file or symlink (inode %I64x, type %u, %p, %p)\n", fcb->inode, fcb->type, &fcb->type, fcb);
4137 }
4138
4139 if (offset.LowPart == FILE_WRITE_TO_END_OF_FILE && offset.HighPart == -1)
4140 offset = fcb->Header.FileSize;
4141
4142 off64 = offset.QuadPart;
4143
4144 TRACE("fcb->Header.Flags = %x\n", fcb->Header.Flags);
4145
4146 if (!no_cache && !CcCanIWrite(FileObject, *length, wait, deferred_write))
4147 return STATUS_PENDING;
4148
4149 if (!wait && no_cache)
4150 return STATUS_PENDING;
4151
4152 if (no_cache && !paging_io && FileObject->SectionObjectPointer->DataSectionObject) {
4154
4155 ExAcquireResourceExclusiveLite(fcb->Header.PagingIoResource, true);
4156
4157 CcFlushCache(FileObject->SectionObjectPointer, &offset, *length, &iosb);
4158
4159 if (!NT_SUCCESS(iosb.Status)) {
4160 ExReleaseResourceLite(fcb->Header.PagingIoResource);
4161 ERR("CcFlushCache returned %08lx\n", iosb.Status);
4162 return iosb.Status;
4163 }
4164
4165 paging_lock = true;
4166
4167 CcPurgeCacheSection(FileObject->SectionObjectPointer, &offset, *length, false);
4168 }
4169
4170 if (paging_io) {
4171 if (!ExAcquireResourceSharedLite(fcb->Header.PagingIoResource, wait)) {
4173 goto end;
4174 } else
4175 paging_lock = true;
4176 }
4177
4178 pagefile = fcb->Header.Flags2 & FSRTL_FLAG2_IS_PAGING_FILE && paging_io;
4179
4180 if (!pagefile && !ExIsResourceAcquiredExclusiveLite(&Vcb->tree_lock)) {
4181 if (!ExAcquireResourceSharedLite(&Vcb->tree_lock, wait)) {
4183 goto end;
4184 } else
4185 acquired_tree_lock = true;
4186 }
4187
4188 if (pagefile) {
4189 if (!ExAcquireResourceSharedLite(fcb->Header.Resource, wait)) {
4191 goto end;
4192 } else
4193 acquired_fcb_lock = true;
4194 } else if (!ExIsResourceAcquiredExclusiveLite(fcb->Header.Resource)) {
4195 if (!ExAcquireResourceExclusiveLite(fcb->Header.Resource, wait)) {
4197 goto end;
4198 } else
4199 acquired_fcb_lock = true;
4200 }
4201
4202 newlength = fcb->ads ? fcb->adsdata.Length : fcb->inode_item.st_size;
4203
4204 if (fcb->deleted)
4205 newlength = 0;
4206
4207 TRACE("newlength = %I64x\n", newlength);
4208
4209 if (off64 + *length > newlength) {
4210 if (paging_io) {
4211 if (off64 >= newlength) {
4212 TRACE("paging IO tried to write beyond end of file (file size = %I64x, offset = %I64x, length = %lx)\n", newlength, off64, *length);
4213 TRACE("FileObject: AllocationSize = %I64x, FileSize = %I64x, ValidDataLength = %I64x\n",
4214 fcb->Header.AllocationSize.QuadPart, fcb->Header.FileSize.QuadPart, fcb->Header.ValidDataLength.QuadPart);
4215 Irp->IoStatus.Information = 0;
4217 goto end;
4218 }
4219
4220 *length = (ULONG)(newlength - off64);
4221 } else {
4222 newlength = off64 + *length;
4223 changed_length = true;
4224
4225 TRACE("extending length to %I64x\n", newlength);
4226 }
4227 }
4228
4229 if (fcb->ads)
4230 make_inline = false;
4231 else
4232 make_inline = newlength <= fcb->Vcb->options.max_inline;
4233
4234 if (changed_length) {
4235 if (newlength > (uint64_t)fcb->Header.AllocationSize.QuadPart) {
4236 if (!acquired_tree_lock) {
4237 // We need to acquire the tree lock if we don't have it already -
4238 // we can't give an inline file proper extents at the same time as we're
4239 // doing a flush.
4240 if (!ExAcquireResourceSharedLite(&Vcb->tree_lock, wait)) {
4242 goto end;
4243 } else
4244 acquired_tree_lock = true;
4245 }
4246
4247 Status = extend_file(fcb, fileref, newlength, false, Irp, rollback);
4248 if (!NT_SUCCESS(Status)) {
4249 ERR("extend_file returned %08lx\n", Status);
4250 goto end;
4251 }
4252 } else if (!fcb->ads)
4253 fcb->inode_item.st_size = newlength;
4254
4255 fcb->Header.FileSize.QuadPart = newlength;
4256 fcb->Header.ValidDataLength.QuadPart = newlength;
4257
4258 TRACE("AllocationSize = %I64x\n", fcb->Header.AllocationSize.QuadPart);
4259 TRACE("FileSize = %I64x\n", fcb->Header.FileSize.QuadPart);
4260 TRACE("ValidDataLength = %I64x\n", fcb->Header.ValidDataLength.QuadPart);
4261 }
4262
4263 if (!no_cache) {
4265
4266 _SEH2_TRY {
4267 if (!FileObject->PrivateCacheMap || changed_length) {
4268 CC_FILE_SIZES ccfs;
4269
4270 ccfs.AllocationSize = fcb->Header.AllocationSize;
4271 ccfs.FileSize = fcb->Header.FileSize;
4272 ccfs.ValidDataLength = fcb->Header.ValidDataLength;
4273
4274 if (!FileObject->PrivateCacheMap)
4276
4277 CcSetFileSizes(FileObject, &ccfs);
4278 }
4279
4281 CcPrepareMdlWrite(FileObject, &offset, *length, &Irp->MdlAddress, &Irp->IoStatus);
4282
4283 Status = Irp->IoStatus.Status;
4284 goto end;
4285 } else {
4286 /* We have to wait in CcCopyWrite - if we return STATUS_PENDING and add this to the work queue,
4287 * it can result in CcFlushCache being called before the job has run. See ifstest ReadWriteTest. */
4288
4289 if (fCcCopyWriteEx) {
4290 TRACE("CcCopyWriteEx(%p, %I64x, %lx, %u, %p, %p)\n", FileObject, off64, *length, true, buf, Irp->Tail.Overlay.Thread);
4291 if (!fCcCopyWriteEx(FileObject, &offset, *length, true, buf, Irp->Tail.Overlay.Thread)) {
4293 goto end;
4294 }
4295 TRACE("CcCopyWriteEx finished\n");
4296 } else {
4297 TRACE("CcCopyWrite(%p, %I64x, %lx, %u, %p)\n", FileObject, off64, *length, true, buf);
4298 if (!CcCopyWrite(FileObject, &offset, *length, true, buf)) {
4300 goto end;
4301 }
4302 TRACE("CcCopyWrite finished\n");
4303 }
4304
4305 Irp->IoStatus.Information = *length;
4306 }
4309 } _SEH2_END;
4310
4311 if (changed_length) {
4313 fcb->ads ? FILE_ACTION_MODIFIED_STREAM : FILE_ACTION_MODIFIED, fcb->ads && fileref->dc ? &fileref->dc->name : NULL);
4314 }
4315
4316 goto end;
4317 }
4318
4319 if (fcb->ads) {
4320 if (changed_length) {
4321 char* data2;
4322
4323 if (newlength > fcb->adsmaxlen) {
4324 ERR("error - xattr too long (%I64u > %lu)\n", newlength, fcb->adsmaxlen);
4326 goto end;
4327 }
4328
4330 if (!data2) {
4331 ERR("out of memory\n");
4333 goto end;
4334 }
4335
4336 if (fcb->adsdata.Buffer) {
4339 }
4340
4341 if (newlength > fcb->adsdata.Length)
4343
4344
4346 fcb->adsdata.Length = fcb->adsdata.MaximumLength = (USHORT)newlength;
4347
4348 fcb->Header.AllocationSize.QuadPart = newlength;
4349 fcb->Header.FileSize.QuadPart = newlength;
4350 fcb->Header.ValidDataLength.QuadPart = newlength;
4351 }
4352
4353 if (*length > 0)
4355
4356 fcb->Header.ValidDataLength.QuadPart = newlength;
4357
4359
4360 if (fileref)
4361 mark_fileref_dirty(fileref);
4362 } else {
4363 bool compress = write_fcb_compressed(fcb), no_buf = false;
4364 uint8_t* data;
4365
4366 if (make_inline) {
4367 start_data = 0;
4368 end_data = sector_align(newlength, fcb->Vcb->superblock.sector_size);
4369 bufhead = sizeof(EXTENT_DATA) - 1;
4370 } else if (compress) {
4371 start_data = off64 & ~(uint64_t)(COMPRESSED_EXTENT_SIZE - 1);
4372 end_data = min(sector_align(off64 + *length, COMPRESSED_EXTENT_SIZE),
4373 sector_align(newlength, fcb->Vcb->superblock.sector_size));
4374 bufhead = 0;
4375 } else {
4376 start_data = off64 & ~(uint64_t)(fcb->Vcb->superblock.sector_size - 1);
4377 end_data = sector_align(off64 + *length, fcb->Vcb->superblock.sector_size);
4378 bufhead = 0;
4379 }
4380
4381 if (fcb_is_inline(fcb))
4382 end_data = max(end_data, sector_align(fcb->inode_item.st_size, Vcb->superblock.sector_size));
4383
4384 fcb->Header.ValidDataLength.QuadPart = newlength;
4385 TRACE("fcb %p FileSize = %I64x\n", fcb, fcb->Header.FileSize.QuadPart);
4386
4387 if (!make_inline && !compress && off64 == start_data && off64 + *length == end_data) {
4388 data = buf;
4389 no_buf = true;
4390 } else {
4391 data = ExAllocatePoolWithTag(PagedPool, (ULONG)(end_data - start_data + bufhead), ALLOC_TAG);
4392 if (!data) {
4393 ERR("out of memory\n");
4395 goto end;
4396 }
4397
4398 RtlZeroMemory(data + bufhead, (ULONG)(end_data - start_data));
4399
4400 TRACE("start_data = %I64x\n", start_data);
4401 TRACE("end_data = %I64x\n", end_data);
4402
4403 if (off64 > start_data || off64 + *length < end_data) {
4404 if (changed_length) {
4407 else
4409 } else
4410 Status = read_file(fcb, data + bufhead, start_data, end_data - start_data, NULL, Irp);
4411
4412 if (!NT_SUCCESS(Status)) {
4413 ERR("read_file returned %08lx\n", Status);
4415 goto end;
4416 }
4417 }
4418
4419 RtlCopyMemory(data + bufhead + off64 - start_data, buf, *length);
4420 }
4421
4422 if (make_inline) {
4424 if (!NT_SUCCESS(Status)) {
4425 ERR("error - excise_extents returned %08lx\n", Status);
4427 goto end;
4428 }
4429
4430 ed2 = (EXTENT_DATA*)data;
4431 ed2->generation = fcb->Vcb->superblock.generation;
4432 ed2->decoded_size = newlength;
4436 ed2->type = EXTENT_TYPE_INLINE;
4437
4438 Status = add_extent_to_fcb(fcb, 0, ed2, (uint16_t)(offsetof(EXTENT_DATA, data[0]) + newlength), false, NULL, rollback);
4439 if (!NT_SUCCESS(Status)) {
4440 ERR("add_extent_to_fcb returned %08lx\n", Status);
4442 goto end;
4443 }
4444
4445 fcb->inode_item.st_blocks += newlength;
4446 } else if (compress) {
4448
4449 if (!NT_SUCCESS(Status)) {
4450 ERR("write_compressed returned %08lx\n", Status);
4452 goto end;
4453 }
4454 } else {
4455 if (write_irp && Irp->MdlAddress && no_buf) {
4456 bool locked = Irp->MdlAddress->MdlFlags & (MDL_PAGES_LOCKED | MDL_PARTIAL);
4457
4458 if (!locked) {
4460
4461 _SEH2_TRY {
4465 } _SEH2_END;
4466
4467 if (!NT_SUCCESS(Status)) {
4468 ERR("MmProbeAndLockPages threw exception %08lx\n", Status);
4469 goto end;
4470 }
4471 }
4472
4473 _SEH2_TRY {
4474 Status = do_write_file(fcb, start_data, end_data, data, Irp, true, 0, rollback);
4477 } _SEH2_END;
4478
4479 if (!locked)
4480 MmUnlockPages(Irp->MdlAddress);
4481 } else {
4482 _SEH2_TRY {
4483 Status = do_write_file(fcb, start_data, end_data, data, Irp, false, 0, rollback);
4486 } _SEH2_END;
4487 }
4488
4489 if (!NT_SUCCESS(Status)) {
4490 ERR("do_write_file returned %08lx\n", Status);
4491 if (!no_buf) ExFreePool(data);
4492 goto end;
4493 }
4494 }
4495
4496 if (!no_buf)
4498 }
4499
4502
4503 if (!pagefile) {
4504 if (fcb->ads) {
4505 if (fileref && fileref->parent)
4506 origii = &fileref->parent->fcb->inode_item;
4507 else {
4508 ERR("no parent fcb found for stream\n");
4510 goto end;
4511 }
4512 } else
4513 origii = &fcb->inode_item;
4514
4515 origii->transid = Vcb->superblock.generation;
4516 origii->sequence++;
4517
4519 origii->st_ctime = now;
4520
4521 if (!fcb->ads) {
4522 if (changed_length) {
4523 TRACE("setting st_size to %I64x\n", newlength);
4524 origii->st_size = newlength;
4526 }
4527
4528 fcb->inode_item_changed = true;
4529 } else {
4530 fileref->parent->fcb->inode_item_changed = true;
4531
4532 if (changed_length)
4534
4536 }
4537
4538 if (!ccb->user_set_write_time) {
4539 origii->st_mtime = now;
4541 }
4542
4543 mark_fcb_dirty(fcb->ads ? fileref->parent->fcb : fcb);
4544 }
4545
4546 if (changed_length) {
4547 CC_FILE_SIZES ccfs;
4548
4549 ccfs.AllocationSize = fcb->Header.AllocationSize;
4550 ccfs.FileSize = fcb->Header.FileSize;
4551 ccfs.ValidDataLength = fcb->Header.ValidDataLength;
4552
4553 _SEH2_TRY {
4554 CcSetFileSizes(FileObject, &ccfs);
4557 goto end;
4558 } _SEH2_END;
4559 }
4560
4561 fcb->subvol->root_item.ctransid = Vcb->superblock.generation;
4562 fcb->subvol->root_item.ctime = now;
4563
4565 Irp->IoStatus.Information = *length;
4566
4567 if (filter != 0)
4569 fcb->ads && fileref->dc ? &fileref->dc->name : NULL);
4570
4571end:
4572 if (NT_SUCCESS(Status) && FileObject->Flags & FO_SYNCHRONOUS_IO && !paging_io) {
4573 TRACE("CurrentByteOffset was: %I64x\n", FileObject->CurrentByteOffset.QuadPart);
4574 FileObject->CurrentByteOffset.QuadPart = offset.QuadPart + (NT_SUCCESS(Status) ? *length : 0);
4575 TRACE("CurrentByteOffset now: %I64x\n", FileObject->CurrentByteOffset.QuadPart);
4576 }
4577
4578 if (acquired_fcb_lock)
4579 ExReleaseResourceLite(fcb->Header.Resource);
4580
4581 if (acquired_tree_lock)
4582 ExReleaseResourceLite(&Vcb->tree_lock);
4583
4584 if (paging_lock)
4585 ExReleaseResourceLite(fcb->Header.PagingIoResource);
4586
4587 return Status;
4588}
unsigned short int uint16_t
Definition: acefiex.h:54
LONG NTSTATUS
Definition: precomp.h:26
#define WARN(fmt,...)
Definition: debug.h:112
#define ERR(fmt,...)
Definition: debug.h:110
NTSTATUS read_file(fcb *fcb, uint8_t *data, uint64_t start, uint64_t length, ULONG *pbr, PIRP Irp) __attribute__((nonnull(1
_In_ fcb _In_ chunk _In_ uint64_t _In_ uint64_t _In_ bool _In_opt_ void _In_opt_ PIRP _In_ LIST_ENTRY * rollback
Definition: btrfs_drv.h:1365
NTSTATUS NTSTATUS NTSTATUS NTSTATUS NTSTATUS excise_extents(device_extension *Vcb, fcb *fcb, uint64_t start_data, uint64_t end_data, PIRP Irp, LIST_ENTRY *rollback) __attribute__((nonnull(1
static __inline void win_time_to_unix(LARGE_INTEGER t, BTRFS_TIME *out)
Definition: btrfs_drv.h:989
struct _fcb fcb
Definition: btrfs_drv.h:1364
NTSTATUS do_write_file(fcb *fcb, uint64_t start_data, uint64_t end_data, void *data, PIRP Irp, bool file_write, uint32_t irp_offset, LIST_ENTRY *rollback) __attribute__((nonnull(1
#define ALLOC_TAG
Definition: btrfs_drv.h:87
_In_ fcb _In_ chunk _In_ uint64_t start_data
Definition: btrfs_drv.h:1364
#define COMPRESSED_EXTENT_SIZE
Definition: btrfs_drv.h:112
NTSTATUS NTSTATUS NTSTATUS NTSTATUS extend_file(fcb *fcb, file_ref *fileref, uint64_t end, bool prealloc, PIRP Irp, LIST_ENTRY *rollback) __attribute__((nonnull(1
NTSTATUS write_compressed(fcb *fcb, uint64_t start_data, uint64_t end_data, void *data, PIRP Irp, LIST_ENTRY *rollback)
Definition: compress.c:875
NTSTATUS bool void NTSTATUS add_extent_to_fcb(_In_ fcb *fcb, _In_ uint64_t offset, _In_reads_bytes_(edsize) EXTENT_DATA *ed, _In_ uint16_t edsize, _In_ bool unique, _In_opt_ _When_(return >=0, __drv_aliasesMem) void *csum, _In_ LIST_ENTRY *rollback) __attribute__((nonnull(1
struct _ccb ccb
bool fcb_is_inline(fcb *fcb)
Definition: fsctl.c:3246
static __inline bool write_fcb_compressed(fcb *fcb)
Definition: btrfs_drv.h:1706
VOID NTAPI CcPrepareMdlWrite(IN PFILE_OBJECT FileObject, IN PLARGE_INTEGER FileOffset, IN ULONG Length, OUT PMDL *MdlChain, OUT PIO_STATUS_BLOCK IoStatus)
Definition: mdlsup.c:91
VOID NTAPI CcFlushCache(IN PSECTION_OBJECT_POINTERS SectionObjectPointer, IN OPTIONAL PLARGE_INTEGER FileOffset, IN ULONG Length, OUT OPTIONAL PIO_STATUS_BLOCK IoStatus)
Definition: cachesub.c:222
static uint64_t __inline sector_align(uint64_t n, uint64_t a)
_In_ PIRP Irp
Definition: csq.h:116
UINT32 uint32_t
Definition: types.h:75
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
void mark_fcb_dirty(_In_ fcb *fcb)
Definition: btrfs.c:1695
tCcCopyWriteEx fCcCopyWriteEx
Definition: btrfs.c:92
void mark_fileref_dirty(_In_ file_ref *fileref)
Definition: btrfs.c:1717
void queue_notification_fcb(_In_ file_ref *fileref, _In_ ULONG filter_match, _In_ ULONG action, _In_opt_ PUNICODE_STRING stream)
Definition: btrfs.c:1667
void init_file_cache(_In_ PFILE_OBJECT FileObject, _In_ CC_FILE_SIZES *ccfs)
Definition: btrfs.c:4069
#define BTRFS_ENCODING_NONE
Definition: btrfs.h:72
#define EXTENT_TYPE_INLINE
Definition: btrfs.h:74
#define BTRFS_COMPRESSION_NONE
Definition: btrfs.h:65
#define BTRFS_ENCRYPTION_NONE
Definition: btrfs.h:70
_In_ PIO_STACK_LOCATION IrpSp
Definition: create.c:4137
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define KeQuerySystemTime(t)
Definition: env_spec_w32.h:570
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
#define ExAcquireResourceExclusiveLite(res, wait)
Definition: env_spec_w32.h:615
#define PagedPool
Definition: env_spec_w32.h:308
#define FILE_WRITE_TO_END_OF_FILE
Definition: ext2fs.h:278
#define _SEH2_END
Definition: filesup.c:22
#define _SEH2_TRY
Definition: filesup.c:19
time_t now
Definition: finger.c:65
#define FSRTL_FLAG2_IS_PAGING_FILE
Definition: fsrtltypes.h:57
VOID NTAPI CcSetFileSizes(IN PFILE_OBJECT FileObject, IN PCC_FILE_SIZES FileSizes)
Definition: fssup.c:356
BOOLEAN NTAPI CcPurgeCacheSection(IN PSECTION_OBJECT_POINTERS SectionObjectPointer, IN OPTIONAL PLARGE_INTEGER FileOffset, IN ULONG Length, IN BOOLEAN UninitializeCacheMaps)
Definition: fssup.c:386
Status
Definition: gdiplustypes.h:25
GLuint GLuint end
Definition: gl.h:1545
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
GLint GLint GLint GLint GLint GLint GLint GLbitfield GLenum filter
Definition: glext.h:7005
GLuint GLsizei GLsizei * length
Definition: glext.h:6040
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
__u16 time
Definition: mkdosfs.c:8
VOID NTAPI MmProbeAndLockPages(IN PMDL Mdl, IN KPROCESSOR_MODE AccessMode, IN LOCK_OPERATION Operation)
Definition: mdlsup.c:931
VOID NTAPI MmUnlockPages(IN PMDL Mdl)
Definition: mdlsup.c:1435
static PIO_STATUS_BLOCK iosb
Definition: file.c:98
BYTE uint8_t
Definition: msvideo1.c:66
#define KernelMode
Definition: asm.h:34
#define uint64_t
Definition: nsiface.idl:62
BOOLEAN NTAPI CcCopyWrite(IN PFILE_OBJECT FileObject, IN PLARGE_INTEGER FileOffset, IN ULONG Length, IN BOOLEAN Wait, IN PVOID Buffer)
Definition: copysup.c:129
BOOLEAN NTAPI CcCanIWrite(IN PFILE_OBJECT FileObject, IN ULONG BytesToWrite, IN BOOLEAN Wait, IN UCHAR Retrying)
Definition: copysup.c:214
BOOLEAN NTAPI ExIsResourceAcquiredExclusiveLite(IN PERESOURCE Resource)
Definition: resource.c:1624
#define STATUS_INTERNAL_ERROR
Definition: ntstatus.h:465
#define STATUS_PENDING
Definition: ntstatus.h:82
unsigned short USHORT
Definition: pedump.c:61
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:159
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:34
#define offsetof(TYPE, MEMBER)
int ZEXPORT compress(Bytef *dest, uLongf *destLen, const Bytef *source, uLong sourceLen)
Definition: compress.c:68
#define BTRFS_TYPE_FILE
Definition: shellext.h:85
#define STATUS_SUCCESS
Definition: shellext.h:65
#define BTRFS_TYPE_SYMLINK
Definition: shellext.h:91
#define TRACE(s)
Definition: solgame.cpp:4
uint64_t generation
Definition: btrfs.h:358
uint8_t type
Definition: btrfs.h:363
uint16_t encoding
Definition: btrfs.h:362
uint8_t encryption
Definition: btrfs.h:361
uint8_t compression
Definition: btrfs.h:360
uint64_t decoded_size
Definition: btrfs.h:359
BTRFS_TIME st_mtime
Definition: btrfs.h:303
uint64_t st_size
Definition: btrfs.h:289
uint64_t sequence
Definition: btrfs.h:299
uint64_t st_blocks
Definition: btrfs.h:290
BTRFS_TIME st_ctime
Definition: btrfs.h:302
uint64_t transid
Definition: btrfs.h:288
USHORT MaximumLength
Definition: env_spec_w32.h:377
LARGE_INTEGER FileSize
Definition: cctypes.h:16
LARGE_INTEGER ValidDataLength
Definition: cctypes.h:17
LARGE_INTEGER AllocationSize
Definition: cctypes.h:15
PFILE_OBJECT FileObject
Definition: iotypes.h:3169
bool user_set_change_time
Definition: btrfs_drv.h:390
bool user_set_write_time
Definition: btrfs_drv.h:389
file_ref * fileref
Definition: btrfs_drv.h:383
bool ads
Definition: btrfs_drv.h:330
bool deleted
Definition: btrfs_drv.h:295
uint64_t inode
Definition: btrfs_drv.h:289
ANSI_STRING adsdata
Definition: btrfs_drv.h:334
INODE_ITEM inode_item
Definition: btrfs_drv.h:292
uint8_t type
Definition: btrfs_drv.h:291
struct _device_extension * Vcb
Definition: btrfs_drv.h:287
struct _root * subvol
Definition: btrfs_drv.h:288
ULONG adsmaxlen
Definition: btrfs_drv.h:332
bool inode_item_changed
Definition: btrfs_drv.h:306
FSRTL_ADVANCED_FCB_HEADER Header
Definition: btrfs_drv.h:283
struct _file_ref * parent
Definition: btrfs_drv.h:352
dir_child * dc
Definition: btrfs_drv.h:353
Definition: tftpd.h:138
UNICODE_STRING name
Definition: btrfs_drv.h:256
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
uint32_t ULONG
Definition: typedefs.h:59
#define STATUS_INVALID_DEVICE_REQUEST
Definition: udferr_usr.h:138
#define STATUS_ACCESS_DENIED
Definition: udferr_usr.h:145
#define STATUS_DISK_FULL
Definition: udferr_usr.h:155
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
_In_ WDFREQUEST _In_ WDFFILEOBJECT FileObject
Definition: wdfdevice.h:550
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2793
#define FILE_ACTION_MODIFIED_STREAM
#define FILE_NOTIFY_CHANGE_SIZE
#define FILE_ACTION_MODIFIED
#define FILE_NOTIFY_CHANGE_STREAM_WRITE
#define FILE_NOTIFY_CHANGE_STREAM_SIZE
* PFILE_OBJECT
Definition: iotypes.h:1998
#define IRP_MN_MDL
Definition: iotypes.h:4419
#define FO_SYNCHRONOUS_IO
Definition: iotypes.h:1776
#define FILE_NOTIFY_CHANGE_LAST_WRITE
@ IoReadAccess
Definition: ketypes.h:863
#define MDL_PAGES_LOCKED
Definition: mmtypes.h:19
#define MDL_PARTIAL
Definition: mmtypes.h:22

◆ __attribute__() [5/18]

__attribute__ ( (nonnull(1, 2, 4, 6, 10))  )

Definition at line 1070 of file write.c.

1072 {
1073 uint64_t startoff, endoff, parity_start, parity_end;
1074 uint16_t startoffstripe, endoffstripe, parity, num_data_stripes = c->chunk_item->num_stripes - 1;
1075 uint64_t pos, parity_pos, *stripeoff = NULL;
1076 uint32_t i;
1077 bool file_write = Irp && Irp->MdlAddress && (Irp->MdlAddress->ByteOffset == 0);
1078 PMDL master_mdl;
1080 PFN_NUMBER *pfns, *parity_pfns;
1081 log_stripe* log_stripes = NULL;
1082
1083 if ((address + length - c->offset) % (num_data_stripes * c->chunk_item->stripe_length) > 0) {
1084 uint64_t delta = (address + length - c->offset) % (num_data_stripes * c->chunk_item->stripe_length);
1085
1086 delta = min(length, delta);
1087 Status = add_partial_stripe(Vcb, c, address + length - delta, (uint32_t)delta, (uint8_t*)data + length - delta);
1088 if (!NT_SUCCESS(Status)) {
1089 ERR("add_partial_stripe returned %08lx\n", Status);
1090 goto exit;
1091 }
1092
1093 length -= (uint32_t)delta;
1094 }
1095
1096 if (length > 0 && (address - c->offset) % (num_data_stripes * c->chunk_item->stripe_length) > 0) {
1097 uint64_t delta = (num_data_stripes * c->chunk_item->stripe_length) - ((address - c->offset) % (num_data_stripes * c->chunk_item->stripe_length));
1098
1099 Status = add_partial_stripe(Vcb, c, address, (uint32_t)delta, data);
1100 if (!NT_SUCCESS(Status)) {
1101 ERR("add_partial_stripe returned %08lx\n", Status);
1102 goto exit;
1103 }
1104
1105 address += delta;
1106 length -= (uint32_t)delta;
1107 irp_offset += delta;
1108 data = (uint8_t*)data + delta;
1109 }
1110
1111 if (length == 0) {
1113 goto exit;
1114 }
1115
1116 get_raid0_offset(address - c->offset, c->chunk_item->stripe_length, num_data_stripes, &startoff, &startoffstripe);
1117 get_raid0_offset(address + length - c->offset - 1, c->chunk_item->stripe_length, num_data_stripes, &endoff, &endoffstripe);
1118
1119 pos = 0;
1120 while (pos < length) {
1121 parity = (((address - c->offset + pos) / (num_data_stripes * c->chunk_item->stripe_length)) + num_data_stripes) % c->chunk_item->num_stripes;
1122
1123 if (pos == 0) {
1124 uint16_t stripe = (parity + startoffstripe + 1) % c->chunk_item->num_stripes;
1125 ULONG skip, writelen;
1126
1127 i = startoffstripe;
1128 while (stripe != parity) {
1129 if (i == startoffstripe) {
1130 writelen = (ULONG)min(length, c->chunk_item->stripe_length - (startoff % c->chunk_item->stripe_length));
1131
1132 stripes[stripe].start = startoff;
1133 stripes[stripe].end = startoff + writelen;
1134
1135 pos += writelen;
1136
1137 if (pos == length)
1138 break;
1139 } else {
1140 writelen = (ULONG)min(length - pos, c->chunk_item->stripe_length);
1141
1142 stripes[stripe].start = startoff - (startoff % c->chunk_item->stripe_length);
1143 stripes[stripe].end = stripes[stripe].start + writelen;
1144
1145 pos += writelen;
1146
1147 if (pos == length)
1148 break;
1149 }
1150
1151 i++;
1152 stripe = (stripe + 1) % c->chunk_item->num_stripes;
1153 }
1154
1155 if (pos == length)
1156 break;
1157
1158 for (i = 0; i < startoffstripe; i++) {
1159 stripe = (parity + i + 1) % c->chunk_item->num_stripes;
1160
1161 stripes[stripe].start = stripes[stripe].end = startoff - (startoff % c->chunk_item->stripe_length) + c->chunk_item->stripe_length;
1162 }
1163
1164 stripes[parity].start = stripes[parity].end = startoff - (startoff % c->chunk_item->stripe_length) + c->chunk_item->stripe_length;
1165
1166 if (length - pos > c->chunk_item->num_stripes * num_data_stripes * c->chunk_item->stripe_length) {
1167 skip = (ULONG)(((length - pos) / (c->chunk_item->num_stripes * num_data_stripes * c->chunk_item->stripe_length)) - 1);
1168
1169 for (i = 0; i < c->chunk_item->num_stripes; i++) {
1170 stripes[i].end += skip * c->chunk_item->num_stripes * c->chunk_item->stripe_length;
1171 }
1172
1173 pos += skip * num_data_stripes * c->chunk_item->num_stripes * c->chunk_item->stripe_length;
1174 }
1175 } else if (length - pos >= c->chunk_item->stripe_length * num_data_stripes) {
1176 for (i = 0; i < c->chunk_item->num_stripes; i++) {
1177 stripes[i].end += c->chunk_item->stripe_length;
1178 }
1179
1180 pos += c->chunk_item->stripe_length * num_data_stripes;
1181 } else {
1182 uint16_t stripe = (parity + 1) % c->chunk_item->num_stripes;
1183
1184 i = 0;
1185 while (stripe != parity) {
1186 if (endoffstripe == i) {
1187 stripes[stripe].end = endoff + 1;
1188 break;
1189 } else if (endoffstripe > i)
1190 stripes[stripe].end = endoff - (endoff % c->chunk_item->stripe_length) + c->chunk_item->stripe_length;
1191
1192 i++;
1193 stripe = (stripe + 1) % c->chunk_item->num_stripes;
1194 }
1195
1196 break;
1197 }
1198 }
1199
1200 parity_start = 0xffffffffffffffff;
1201 parity_end = 0;
1202
1203 for (i = 0; i < c->chunk_item->num_stripes; i++) {
1204 if (stripes[i].start != 0 || stripes[i].end != 0) {
1205 parity_start = min(stripes[i].start, parity_start);
1206 parity_end = max(stripes[i].end, parity_end);
1207 }
1208 }
1209
1210 if (parity_end == parity_start) {
1212 goto exit;
1213 }
1214
1215 parity = (((address - c->offset) / (num_data_stripes * c->chunk_item->stripe_length)) + num_data_stripes) % c->chunk_item->num_stripes;
1216 stripes[parity].start = parity_start;
1217
1218 parity = (((address - c->offset + length - 1) / (num_data_stripes * c->chunk_item->stripe_length)) + num_data_stripes) % c->chunk_item->num_stripes;
1219 stripes[parity].end = parity_end;
1220
1221 log_stripes = ExAllocatePoolWithTag(NonPagedPool, sizeof(log_stripe) * num_data_stripes, ALLOC_TAG);
1222 if (!log_stripes) {
1223 ERR("out of memory\n");
1225 goto exit;
1226 }
1227
1228 RtlZeroMemory(log_stripes, sizeof(log_stripe) * num_data_stripes);
1229
1230 for (i = 0; i < num_data_stripes; i++) {
1231 log_stripes[i].mdl = IoAllocateMdl(NULL, (ULONG)(parity_end - parity_start), false, false, NULL);
1232 if (!log_stripes[i].mdl) {
1233 ERR("out of memory\n");
1235 goto exit;
1236 }
1237
1238 log_stripes[i].mdl->MdlFlags |= MDL_PARTIAL;
1239 log_stripes[i].pfns = (PFN_NUMBER*)(log_stripes[i].mdl + 1);
1240 }
1241
1242 wtc->parity1 = ExAllocatePoolWithTag(NonPagedPool, (ULONG)(parity_end - parity_start), ALLOC_TAG);
1243 if (!wtc->parity1) {
1244 ERR("out of memory\n");
1246 goto exit;
1247 }
1248
1249 wtc->parity1_mdl = IoAllocateMdl(wtc->parity1, (ULONG)(parity_end - parity_start), false, false, NULL);
1250 if (!wtc->parity1_mdl) {
1251 ERR("out of memory\n");
1253 goto exit;
1254 }
1255
1256 MmBuildMdlForNonPagedPool(wtc->parity1_mdl);
1257
1258 if (file_write)
1259 master_mdl = Irp->MdlAddress;
1260 else if (((ULONG_PTR)data % PAGE_SIZE) != 0) {
1262 if (!wtc->scratch) {
1263 ERR("out of memory\n");
1265 goto exit;
1266 }
1267
1268 RtlCopyMemory(wtc->scratch, data, length);
1269
1270 master_mdl = IoAllocateMdl(wtc->scratch, length, false, false, NULL);
1271 if (!master_mdl) {
1272 ERR("out of memory\n");
1274 goto exit;
1275 }
1276
1277 MmBuildMdlForNonPagedPool(master_mdl);
1278
1279 wtc->mdl = master_mdl;
1280 } else {
1281 master_mdl = IoAllocateMdl(data, length, false, false, NULL);
1282 if (!master_mdl) {
1283 ERR("out of memory\n");
1285 goto exit;
1286 }
1287
1289
1290 _SEH2_TRY {
1294 } _SEH2_END;
1295
1296 if (!NT_SUCCESS(Status)) {
1297 ERR("MmProbeAndLockPages threw exception %08lx\n", Status);
1298 IoFreeMdl(master_mdl);
1299 return Status;
1300 }
1301
1302 wtc->mdl = master_mdl;
1303 }
1304
1305 pfns = (PFN_NUMBER*)(master_mdl + 1);
1306 parity_pfns = (PFN_NUMBER*)(wtc->parity1_mdl + 1);
1307
1308 if (file_write)
1309 pfns = &pfns[irp_offset >> PAGE_SHIFT];
1310
1311 for (i = 0; i < c->chunk_item->num_stripes; i++) {
1312 if (stripes[i].start != stripes[i].end) {
1313 stripes[i].mdl = IoAllocateMdl((uint8_t*)MmGetMdlVirtualAddress(master_mdl) + irp_offset, (ULONG)(stripes[i].end - stripes[i].start), false, false, NULL);
1314 if (!stripes[i].mdl) {
1315 ERR("IoAllocateMdl failed\n");
1317 goto exit;
1318 }
1319 }
1320 }
1321
1322 stripeoff = ExAllocatePoolWithTag(PagedPool, sizeof(uint64_t) * c->chunk_item->num_stripes, ALLOC_TAG);
1323 if (!stripeoff) {
1324 ERR("out of memory\n");
1326 goto exit;
1327 }
1328
1329 RtlZeroMemory(stripeoff, sizeof(uint64_t) * c->chunk_item->num_stripes);
1330
1331 pos = 0;
1332 parity_pos = 0;
1333
1334 while (pos < length) {
1335 PFN_NUMBER* stripe_pfns;
1336
1337 parity = (((address - c->offset + pos) / (num_data_stripes * c->chunk_item->stripe_length)) + num_data_stripes) % c->chunk_item->num_stripes;
1338
1339 if (pos == 0) {
1340 uint16_t stripe = (parity + startoffstripe + 1) % c->chunk_item->num_stripes;
1341 uint32_t writelen = (uint32_t)min(length - pos, min(stripes[stripe].end - stripes[stripe].start,
1342 c->chunk_item->stripe_length - (stripes[stripe].start % c->chunk_item->stripe_length)));
1343 uint32_t maxwritelen = writelen;
1344
1345 stripe_pfns = (PFN_NUMBER*)(stripes[stripe].mdl + 1);
1346
1347 RtlCopyMemory(stripe_pfns, pfns, writelen * sizeof(PFN_NUMBER) >> PAGE_SHIFT);
1348
1349 RtlCopyMemory(log_stripes[startoffstripe].pfns, pfns, writelen * sizeof(PFN_NUMBER) >> PAGE_SHIFT);
1350 log_stripes[startoffstripe].pfns += writelen >> PAGE_SHIFT;
1351
1352 stripeoff[stripe] = writelen;
1353 pos += writelen;
1354
1355 stripe = (stripe + 1) % c->chunk_item->num_stripes;
1356 i = startoffstripe + 1;
1357
1358 while (stripe != parity) {
1359 stripe_pfns = (PFN_NUMBER*)(stripes[stripe].mdl + 1);
1360 writelen = (uint32_t)min(length - pos, min(stripes[stripe].end - stripes[stripe].start, c->chunk_item->stripe_length));
1361
1362 if (writelen == 0)
1363 break;
1364
1365 if (writelen > maxwritelen)
1366 maxwritelen = writelen;
1367
1368 RtlCopyMemory(stripe_pfns, &pfns[pos >> PAGE_SHIFT], writelen * sizeof(PFN_NUMBER) >> PAGE_SHIFT);
1369
1370 RtlCopyMemory(log_stripes[i].pfns, &pfns[pos >> PAGE_SHIFT], writelen * sizeof(PFN_NUMBER) >> PAGE_SHIFT);
1371 log_stripes[i].pfns += writelen >> PAGE_SHIFT;
1372
1373 stripeoff[stripe] = writelen;
1374 pos += writelen;
1375
1376 stripe = (stripe + 1) % c->chunk_item->num_stripes;
1377 i++;
1378 }
1379
1380 stripe_pfns = (PFN_NUMBER*)(stripes[parity].mdl + 1);
1381
1382 RtlCopyMemory(stripe_pfns, parity_pfns, maxwritelen * sizeof(PFN_NUMBER) >> PAGE_SHIFT);
1383 stripeoff[parity] = maxwritelen;
1384 parity_pos = maxwritelen;
1385 } else if (length - pos >= c->chunk_item->stripe_length * num_data_stripes) {
1386 uint16_t stripe = (parity + 1) % c->chunk_item->num_stripes;
1387
1388 i = 0;
1389 while (stripe != parity) {
1390 stripe_pfns = (PFN_NUMBER*)(stripes[stripe].mdl + 1);
1391
1392 RtlCopyMemory(&stripe_pfns[stripeoff[stripe] >> PAGE_SHIFT], &pfns[pos >> PAGE_SHIFT], (ULONG)(c->chunk_item->stripe_length * sizeof(PFN_NUMBER) >> PAGE_SHIFT));
1393
1394 RtlCopyMemory(log_stripes[i].pfns, &pfns[pos >> PAGE_SHIFT], (ULONG)(c->chunk_item->stripe_length * sizeof(PFN_NUMBER) >> PAGE_SHIFT));
1395 log_stripes[i].pfns += c->chunk_item->stripe_length >> PAGE_SHIFT;
1396
1397 stripeoff[stripe] += c->chunk_item->stripe_length;
1398 pos += c->chunk_item->stripe_length;
1399
1400 stripe = (stripe + 1) % c->chunk_item->num_stripes;
1401 i++;
1402 }
1403
1404 stripe_pfns = (PFN_NUMBER*)(stripes[parity].mdl + 1);
1405
1406 RtlCopyMemory(&stripe_pfns[stripeoff[parity] >> PAGE_SHIFT], &parity_pfns[parity_pos >> PAGE_SHIFT], (ULONG)(c->chunk_item->stripe_length * sizeof(PFN_NUMBER) >> PAGE_SHIFT));
1407 stripeoff[parity] += c->chunk_item->stripe_length;
1408 parity_pos += c->chunk_item->stripe_length;
1409 } else {
1410 uint16_t stripe = (parity + 1) % c->chunk_item->num_stripes;
1411 uint32_t writelen, maxwritelen = 0;
1412
1413 i = 0;
1414 while (pos < length) {
1415 stripe_pfns = (PFN_NUMBER*)(stripes[stripe].mdl + 1);
1416 writelen = (uint32_t)min(length - pos, min(stripes[stripe].end - stripes[stripe].start, c->chunk_item->stripe_length));
1417
1418 if (writelen == 0)
1419 break;
1420
1421 if (writelen > maxwritelen)
1422 maxwritelen = writelen;
1423
1424 RtlCopyMemory(&stripe_pfns[stripeoff[stripe] >> PAGE_SHIFT], &pfns[pos >> PAGE_SHIFT], writelen * sizeof(PFN_NUMBER) >> PAGE_SHIFT);
1425
1426 RtlCopyMemory(log_stripes[i].pfns, &pfns[pos >> PAGE_SHIFT], writelen * sizeof(PFN_NUMBER) >> PAGE_SHIFT);
1427 log_stripes[i].pfns += writelen >> PAGE_SHIFT;
1428
1429 stripeoff[stripe] += writelen;
1430 pos += writelen;
1431
1432 stripe = (stripe + 1) % c->chunk_item->num_stripes;
1433 i++;
1434 }
1435
1436 stripe_pfns = (PFN_NUMBER*)(stripes[parity].mdl + 1);
1437
1438 RtlCopyMemory(&stripe_pfns[stripeoff[parity] >> PAGE_SHIFT], &parity_pfns[parity_pos >> PAGE_SHIFT], maxwritelen * sizeof(PFN_NUMBER) >> PAGE_SHIFT);
1439 }
1440 }
1441
1442 for (i = 0; i < num_data_stripes; i++) {
1444
1445 if (i == 0)
1446 RtlCopyMemory(wtc->parity1, ss, (uint32_t)(parity_end - parity_start));
1447 else
1448 do_xor(wtc->parity1, ss, (uint32_t)(parity_end - parity_start));
1449 }
1450
1452
1453exit:
1454 if (log_stripes) {
1455 for (i = 0; i < num_data_stripes; i++) {
1456 if (log_stripes[i].mdl)
1457 IoFreeMdl(log_stripes[i].mdl);
1458 }
1459
1460 ExFreePool(log_stripes);
1461 }
1462
1463 if (stripeoff)
1464 ExFreePool(stripeoff);
1465
1466 return Status;
1467}
#define skip(...)
Definition: atltest.h:64
_Post_satisfies_ static stripe __inline void get_raid0_offset(_In_ uint64_t off, _In_ uint64_t stripe_length, _In_ uint16_t num_stripes, _Out_ uint64_t *stripeoff, _Out_ uint16_t *stripe)
Definition: btrfs_drv.h:997
_In_ fcb _In_ chunk _In_ uint64_t _In_ uint64_t _In_ bool _In_opt_ void _In_opt_ PIRP _In_ LIST_ENTRY _In_ uint8_t _In_ uint64_t _In_ bool file_write
Definition: btrfs_drv.h:1366
while(CdLookupNextInitialFileDirent(IrpContext, Fcb, FileContext))
xor_func do_xor
Definition: btrfs.c:127
#define PAGE_SIZE
Definition: env_spec_w32.h:49
#define PAGE_SHIFT
Definition: env_spec_w32.h:45
#define NonPagedPool
Definition: env_spec_w32.h:307
MDL * mdl
#define IoFreeMdl
Definition: fxmdl.h:89
#define IoAllocateMdl
Definition: fxmdl.h:88
GLuint start
Definition: gl.h:1545
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define ss
Definition: i386-dis.c:441
VOID NTAPI MmBuildMdlForNonPagedPool(IN PMDL Mdl)
Definition: mdlsup.c:424
static int priority
Definition: timer.c:163
#define uint32_t
Definition: nsiface.idl:61
ULONG PFN_NUMBER
Definition: ke.h:9
#define exit(n)
Definition: config.h:202
PMDL mdl
Definition: write.c:1066
PFN_NUMBER * pfns
Definition: write.c:1067
Definition: write.c:113
uint32_t ULONG_PTR
Definition: typedefs.h:65
#define MmGetMdlVirtualAddress(_Mdl)
#define MmGetSystemAddressForMdlSafe(_Mdl, _Priority)

◆ __attribute__() [6/18]

__attribute__ ( (nonnull(1, 2, 5))  )

Definition at line 982 of file write.c.

983 {
985 LIST_ENTRY* le;
986 partial_stripe* ps;
987 uint64_t stripe_addr;
988 uint16_t num_data_stripes;
989
990 num_data_stripes = c->chunk_item->num_stripes - (c->chunk_item->type & BLOCK_FLAG_RAID5 ? 1 : 2);
991 stripe_addr = address - ((address - c->offset) % (num_data_stripes * c->chunk_item->stripe_length));
992
993 ExAcquireResourceExclusiveLite(&c->partial_stripes_lock, true);
994
995 le = c->partial_stripes.Flink;
996 while (le != &c->partial_stripes) {
998
999 if (ps->address == stripe_addr) {
1000 // update existing entry
1001
1002 RtlCopyMemory(ps->data + address - stripe_addr, data, length);
1003 RtlClearBits(&ps->bmp, (ULONG)((address - stripe_addr) >> Vcb->sector_shift), length >> Vcb->sector_shift);
1004
1005 // if now filled, flush
1006 if (RtlAreBitsClear(&ps->bmp, 0, (ULONG)((num_data_stripes * c->chunk_item->stripe_length) >> Vcb->sector_shift))) {
1008 if (!NT_SUCCESS(Status)) {
1009 ERR("flush_partial_stripe returned %08lx\n", Status);
1010 goto end;
1011 }
1012
1014
1015 if (ps->bmparr)
1016 ExFreePool(ps->bmparr);
1017
1018 ExFreePool(ps);
1019 }
1020
1022 goto end;
1023 } else if (ps->address > stripe_addr)
1024 break;
1025
1026 le = le->Flink;
1027 }
1028
1029 // add new entry
1030
1031 ps = ExAllocatePoolWithTag(NonPagedPool, offsetof(partial_stripe, data[0]) + (ULONG)(num_data_stripes * c->chunk_item->stripe_length), ALLOC_TAG);
1032 if (!ps) {
1033 ERR("out of memory\n");
1035 goto end;
1036 }
1037
1038 ps->bmplen = (ULONG)(num_data_stripes * c->chunk_item->stripe_length) >> Vcb->sector_shift;
1039
1040 ps->address = stripe_addr;
1041 ps->bmparr = ExAllocatePoolWithTag(NonPagedPool, (size_t)sector_align(((ps->bmplen / 8) + 1), sizeof(ULONG)), ALLOC_TAG);
1042 if (!ps->bmparr) {
1043 ERR("out of memory\n");
1044 ExFreePool(ps);
1046 goto end;
1047 }
1048
1049 RtlInitializeBitMap(&ps->bmp, ps->bmparr, ps->bmplen);
1050 RtlSetAllBits(&ps->bmp);
1051
1052 RtlCopyMemory(ps->data + address - stripe_addr, data, length);
1053 RtlClearBits(&ps->bmp, (ULONG)((address - stripe_addr) >> Vcb->sector_shift), length >> Vcb->sector_shift);
1054
1055 InsertHeadList(le->Blink, &ps->list_entry);
1056
1058
1059end:
1060 ExReleaseResourceLite(&c->partial_stripes_lock);
1061
1062 return Status;
1063}
NTSTATUS flush_partial_stripe(device_extension *Vcb, chunk *c, partial_stripe *ps)
Definition: flushthread.c:5958
#define RemoveEntryList(Entry)
Definition: env_spec_w32.h:986
NTSYSAPI void WINAPI RtlInitializeBitMap(PRTL_BITMAP, PULONG, ULONG)
NTSYSAPI void WINAPI RtlSetAllBits(PRTL_BITMAP)
NTSYSAPI BOOLEAN WINAPI RtlAreBitsClear(PCRTL_BITMAP, ULONG, ULONG)
NTSYSAPI void WINAPI RtlClearBits(PRTL_BITMAP, ULONG, ULONG)
#define BLOCK_FLAG_RAID5
Definition: shellext.h:82
struct _LIST_ENTRY * Blink
Definition: typedefs.h:122
uint64_t address
Definition: btrfs_drv.h:553
uint8_t data[1]
Definition: btrfs_drv.h:558
RTL_BITMAP bmp
Definition: btrfs_drv.h:556
ULONG * bmparr
Definition: btrfs_drv.h:554
LIST_ENTRY list_entry
Definition: btrfs_drv.h:557

◆ __attribute__() [7/18]

__attribute__ ( (nonnull(1, 2, 5, 6, 11))  )

Definition at line 3570 of file write.c.

3572 {
3573 EXTENT_DATA* ed = &ext->extent_data;
3574 EXTENT_DATA2* ed2 = (EXTENT_DATA2*)ed->data;
3576 chunk* c = NULL;
3577
3578 if (start_data <= ext->offset && end_data >= ext->offset + ed2->num_bytes) { // replace all
3579 extent* newext;
3580
3581 newext = ExAllocatePoolWithTag(PagedPool, offsetof(extent, extent_data) + ext->datalen, ALLOC_TAG);
3582 if (!newext) {
3583 ERR("out of memory\n");
3585 }
3586
3587 RtlCopyMemory(&newext->extent_data, &ext->extent_data, ext->datalen);
3588
3590
3592 NULL, file_write, irp_offset + ext->offset - start_data, priority);
3593 if (!NT_SUCCESS(Status)) {
3594 ERR("write_data_complete returned %08lx\n", Status);
3595 return Status;
3596 }
3597
3599 ULONG sl = (ULONG)(ed2->num_bytes >> fcb->Vcb->sector_shift);
3600 void* csum = ExAllocatePoolWithTag(PagedPool, sl * fcb->Vcb->csum_size, ALLOC_TAG);
3601
3602 if (!csum) {
3603 ERR("out of memory\n");
3604 ExFreePool(newext);
3606 }
3607
3608 do_calc_job(fcb->Vcb, (uint8_t*)data + ext->offset - start_data, sl, csum);
3609
3610 newext->csum = csum;
3611 } else
3612 newext->csum = NULL;
3613
3614 *written = ed2->num_bytes;
3615
3616 newext->offset = ext->offset;
3617 newext->datalen = ext->datalen;
3618 newext->unique = ext->unique;
3619 newext->ignore = false;
3620 newext->inserted = true;
3621 InsertHeadList(&ext->list_entry, &newext->list_entry);
3622
3623 add_insert_extent_rollback(rollback, fcb, newext);
3624
3625 remove_fcb_extent(fcb, ext, rollback);
3626
3628 } else if (start_data <= ext->offset && end_data < ext->offset + ed2->num_bytes) { // replace beginning
3629 EXTENT_DATA2* ned2;
3630 extent *newext1, *newext2;
3631
3632 newext1 = ExAllocatePoolWithTag(PagedPool, offsetof(extent, extent_data) + ext->datalen, ALLOC_TAG);
3633 if (!newext1) {
3634 ERR("out of memory\n");
3636 }
3637
3638 newext2 = ExAllocatePoolWithTag(PagedPool, offsetof(extent, extent_data) + ext->datalen, ALLOC_TAG);
3639 if (!newext2) {
3640 ERR("out of memory\n");
3641 ExFreePool(newext1);
3643 }
3644
3645 RtlCopyMemory(&newext1->extent_data, &ext->extent_data, ext->datalen);
3647 ned2 = (EXTENT_DATA2*)newext1->extent_data.data;
3648 ned2->num_bytes = end_data - ext->offset;
3649
3650 RtlCopyMemory(&newext2->extent_data, &ext->extent_data, ext->datalen);
3651 ned2 = (EXTENT_DATA2*)newext2->extent_data.data;
3652 ned2->offset += end_data - ext->offset;
3653 ned2->num_bytes -= end_data - ext->offset;
3654
3655 Status = write_data_complete(fcb->Vcb, ed2->address + ed2->offset, (uint8_t*)data + ext->offset - start_data, (uint32_t)(end_data - ext->offset),
3656 Irp, NULL, file_write, irp_offset + ext->offset - start_data, priority);
3657 if (!NT_SUCCESS(Status)) {
3658 ERR("write_data_complete returned %08lx\n", Status);
3659 ExFreePool(newext1);
3660 ExFreePool(newext2);
3661 return Status;
3662 }
3663
3665 ULONG sl = (ULONG)((end_data - ext->offset) >> fcb->Vcb->sector_shift);
3666 void* csum = ExAllocatePoolWithTag(PagedPool, sl * fcb->Vcb->csum_size, ALLOC_TAG);
3667
3668 if (!csum) {
3669 ERR("out of memory\n");
3670 ExFreePool(newext1);
3671 ExFreePool(newext2);
3673 }
3674
3675 do_calc_job(fcb->Vcb, (uint8_t*)data + ext->offset - start_data, sl, csum);
3676
3677 newext1->csum = csum;
3678 } else
3679 newext1->csum = NULL;
3680
3681 *written = end_data - ext->offset;
3682
3683 newext1->offset = ext->offset;
3684 newext1->datalen = ext->datalen;
3685 newext1->unique = ext->unique;
3686 newext1->ignore = false;
3687 newext1->inserted = true;
3688 InsertHeadList(&ext->list_entry, &newext1->list_entry);
3689
3690 add_insert_extent_rollback(rollback, fcb, newext1);
3691
3692 newext2->offset = end_data;
3693 newext2->datalen = ext->datalen;
3694 newext2->unique = ext->unique;
3695 newext2->ignore = false;
3696 newext2->inserted = true;
3697 newext2->csum = NULL;
3698 add_extent(fcb, &newext1->list_entry, newext2);
3699
3700 add_insert_extent_rollback(rollback, fcb, newext2);
3701
3703
3704 if (!c)
3705 ERR("get_chunk_from_address(%I64x) failed\n", ed2->address);
3706 else {
3707 Status = update_changed_extent_ref(fcb->Vcb, c, ed2->address, ed2->size, fcb->subvol->id, fcb->inode, ext->offset - ed2->offset, 1,
3709
3710 if (!NT_SUCCESS(Status)) {
3711 ERR("update_changed_extent_ref returned %08lx\n", Status);
3712 return Status;
3713 }
3714 }
3715
3716 remove_fcb_extent(fcb, ext, rollback);
3717 } else if (start_data > ext->offset && end_data >= ext->offset + ed2->num_bytes) { // replace end
3718 EXTENT_DATA2* ned2;
3719 extent *newext1, *newext2;
3720
3721 newext1 = ExAllocatePoolWithTag(PagedPool, offsetof(extent, extent_data) + ext->datalen, ALLOC_TAG);
3722 if (!newext1) {
3723 ERR("out of memory\n");
3725 }
3726
3727 newext2 = ExAllocatePoolWithTag(PagedPool, offsetof(extent, extent_data) + ext->datalen, ALLOC_TAG);
3728 if (!newext2) {
3729 ERR("out of memory\n");
3730 ExFreePool(newext1);
3732 }
3733
3734 RtlCopyMemory(&newext1->extent_data, &ext->extent_data, ext->datalen);
3735
3736 ned2 = (EXTENT_DATA2*)newext1->extent_data.data;
3737 ned2->num_bytes = start_data - ext->offset;
3738
3739 RtlCopyMemory(&newext2->extent_data, &ext->extent_data, ext->datalen);
3740
3742 ned2 = (EXTENT_DATA2*)newext2->extent_data.data;
3743 ned2->offset += start_data - ext->offset;
3744 ned2->num_bytes = ext->offset + ed2->num_bytes - start_data;
3745
3746 Status = write_data_complete(fcb->Vcb, ed2->address + ned2->offset, data, (uint32_t)ned2->num_bytes, Irp, NULL, file_write, irp_offset, priority);
3747 if (!NT_SUCCESS(Status)) {
3748 ERR("write_data_complete returned %08lx\n", Status);
3749 ExFreePool(newext1);
3750 ExFreePool(newext2);
3751 return Status;
3752 }
3753
3755 ULONG sl = (ULONG)(ned2->num_bytes >> fcb->Vcb->sector_shift);
3756 void* csum = ExAllocatePoolWithTag(PagedPool, sl * fcb->Vcb->csum_size, ALLOC_TAG);
3757
3758 if (!csum) {
3759 ERR("out of memory\n");
3760 ExFreePool(newext1);
3761 ExFreePool(newext2);
3763 }
3764
3765 do_calc_job(fcb->Vcb, data, sl, csum);
3766
3767 newext2->csum = csum;
3768 } else
3769 newext2->csum = NULL;
3770
3771 *written = ned2->num_bytes;
3772
3773 newext1->offset = ext->offset;
3774 newext1->datalen = ext->datalen;
3775 newext1->unique = ext->unique;
3776 newext1->ignore = false;
3777 newext1->inserted = true;
3778 newext1->csum = NULL;
3779 InsertHeadList(&ext->list_entry, &newext1->list_entry);
3780
3781 add_insert_extent_rollback(rollback, fcb, newext1);
3782
3783 newext2->offset = start_data;
3784 newext2->datalen = ext->datalen;
3785 newext2->unique = ext->unique;
3786 newext2->ignore = false;
3787 newext2->inserted = true;
3788 add_extent(fcb, &newext1->list_entry, newext2);
3789
3790 add_insert_extent_rollback(rollback, fcb, newext2);
3791
3793
3794 if (!c)
3795 ERR("get_chunk_from_address(%I64x) failed\n", ed2->address);
3796 else {
3797 Status = update_changed_extent_ref(fcb->Vcb, c, ed2->address, ed2->size, fcb->subvol->id, fcb->inode, ext->offset - ed2->offset, 1,
3799
3800 if (!NT_SUCCESS(Status)) {
3801 ERR("update_changed_extent_ref returned %08lx\n", Status);
3802 return Status;
3803 }
3804 }
3805
3806 remove_fcb_extent(fcb, ext, rollback);
3807 } else if (start_data > ext->offset && end_data < ext->offset + ed2->num_bytes) { // replace middle
3808 EXTENT_DATA2* ned2;
3809 extent *newext1, *newext2, *newext3;
3810
3811 newext1 = ExAllocatePoolWithTag(PagedPool, offsetof(extent, extent_data) + ext->datalen, ALLOC_TAG);
3812 if (!newext1) {
3813 ERR("out of memory\n");
3815 }
3816
3817 newext2 = ExAllocatePoolWithTag(PagedPool, offsetof(extent, extent_data) + ext->datalen, ALLOC_TAG);
3818 if (!newext2) {
3819 ERR("out of memory\n");
3820 ExFreePool(newext1);
3822 }
3823
3824 newext3 = ExAllocatePoolWithTag(PagedPool, offsetof(extent, extent_data) + ext->datalen, ALLOC_TAG);
3825 if (!newext3) {
3826 ERR("out of memory\n");
3827 ExFreePool(newext1);
3828 ExFreePool(newext2);
3830 }
3831
3832 RtlCopyMemory(&newext1->extent_data, &ext->extent_data, ext->datalen);
3833 RtlCopyMemory(&newext2->extent_data, &ext->extent_data, ext->datalen);
3834 RtlCopyMemory(&newext3->extent_data, &ext->extent_data, ext->datalen);
3835
3836 ned2 = (EXTENT_DATA2*)newext1->extent_data.data;
3837 ned2->num_bytes = start_data - ext->offset;
3838
3840 ned2 = (EXTENT_DATA2*)newext2->extent_data.data;
3841 ned2->offset += start_data - ext->offset;
3842 ned2->num_bytes = end_data - start_data;
3843
3844 ned2 = (EXTENT_DATA2*)newext3->extent_data.data;
3845 ned2->offset += end_data - ext->offset;
3846 ned2->num_bytes -= end_data - ext->offset;
3847
3848 ned2 = (EXTENT_DATA2*)newext2->extent_data.data;
3849 Status = write_data_complete(fcb->Vcb, ed2->address + ned2->offset, data, (uint32_t)(end_data - start_data), Irp, NULL, file_write, irp_offset, priority);
3850 if (!NT_SUCCESS(Status)) {
3851 ERR("write_data_complete returned %08lx\n", Status);
3852 ExFreePool(newext1);
3853 ExFreePool(newext2);
3854 ExFreePool(newext3);
3855 return Status;
3856 }
3857
3859 ULONG sl = (ULONG)((end_data - start_data) >> fcb->Vcb->sector_shift);
3860 void* csum = ExAllocatePoolWithTag(PagedPool, sl * fcb->Vcb->csum_size, ALLOC_TAG);
3861
3862 if (!csum) {
3863 ERR("out of memory\n");
3864 ExFreePool(newext1);
3865 ExFreePool(newext2);
3866 ExFreePool(newext3);
3868 }
3869
3870 do_calc_job(fcb->Vcb, data, sl, csum);
3871
3872 newext2->csum = csum;
3873 } else
3874 newext2->csum = NULL;
3875
3876 *written = end_data - start_data;
3877
3878 newext1->offset = ext->offset;
3879 newext1->datalen = ext->datalen;
3880 newext1->unique = ext->unique;
3881 newext1->ignore = false;
3882 newext1->inserted = true;
3883 newext1->csum = NULL;
3884 InsertHeadList(&ext->list_entry, &newext1->list_entry);
3885
3886 add_insert_extent_rollback(rollback, fcb, newext1);
3887
3888 newext2->offset = start_data;
3889 newext2->datalen = ext->datalen;
3890 newext2->unique = ext->unique;
3891 newext2->ignore = false;
3892 newext2->inserted = true;
3893 add_extent(fcb, &newext1->list_entry, newext2);
3894
3895 add_insert_extent_rollback(rollback, fcb, newext2);
3896
3897 newext3->offset = end_data;
3898 newext3->datalen = ext->datalen;
3899 newext3->unique = ext->unique;
3900 newext3->ignore = false;
3901 newext3->inserted = true;
3902 newext3->csum = NULL;
3903 add_extent(fcb, &newext2->list_entry, newext3);
3904
3905 add_insert_extent_rollback(rollback, fcb, newext3);
3906
3908
3909 if (!c)
3910 ERR("get_chunk_from_address(%I64x) failed\n", ed2->address);
3911 else {
3912 Status = update_changed_extent_ref(fcb->Vcb, c, ed2->address, ed2->size, fcb->subvol->id, fcb->inode, ext->offset - ed2->offset, 2,
3914
3915 if (!NT_SUCCESS(Status)) {
3916 ERR("update_changed_extent_ref returned %08lx\n", Status);
3917 return Status;
3918 }
3919 }
3920
3921 remove_fcb_extent(fcb, ext, rollback);
3922 }
3923
3924 if (c)
3925 c->changed = true;
3926
3927 return STATUS_SUCCESS;
3928}
void do_calc_job(device_extension *Vcb, uint8_t *data, uint32_t sectors, void *csum)
Definition: calcthread.c:141
NTSTATUS NTSTATUS NTSTATUS NTSTATUS NTSTATUS chunk * get_chunk_from_address(device_extension *Vcb, uint64_t address) __attribute__((nonnull(1)))
NTSTATUS NTSTATUS NTSTATUS write_data_complete(device_extension *Vcb, uint64_t address, void *data, uint32_t length, PIRP Irp, chunk *c, bool file_write, uint64_t irp_offset, ULONG priority) __attribute__((nonnull(1
NTSTATUS bool void NTSTATUS void add_extent(_In_ fcb *fcb, _In_ LIST_ENTRY *prevextle, _In_ __drv_aliasesMem extent *newext) __attribute__((nonnull(1
NTSTATUS update_changed_extent_ref(device_extension *Vcb, chunk *c, uint64_t address, uint64_t size, uint64_t root, uint64_t objid, uint64_t offset, int32_t count, bool no_csum, bool superseded, PIRP Irp)
Definition: extent-tree.c:1951
#define EXTENT_TYPE_REGULAR
Definition: btrfs.h:75
#define BTRFS_INODE_NODATASUM
Definition: propsheet.h:76
uint64_t num_bytes
Definition: btrfs.h:371
uint64_t address
Definition: btrfs.h:368
uint64_t size
Definition: btrfs.h:369
uint64_t offset
Definition: btrfs.h:370
uint8_t data[1]
Definition: btrfs.h:364
uint32_t flags
Definition: btrfs.h:297
Definition: ffs.h:52
bool unique
Definition: btrfs_drv.h:230
uint16_t datalen
Definition: btrfs_drv.h:229
LIST_ENTRY list_entry
Definition: btrfs_drv.h:235
bool inserted
Definition: btrfs_drv.h:232
EXTENT_DATA extent_data
Definition: btrfs_drv.h:237
uint64_t offset
Definition: btrfs_drv.h:228
bool ignore
Definition: btrfs_drv.h:231
void * csum
Definition: btrfs_drv.h:233

◆ __attribute__() [8/18]

__attribute__ ( (nonnull(1, 2, 5, 7, 10))  )

Definition at line 2908 of file write.c.

2910 {
2911 bool success = false;
2912 EXTENT_DATA* ed;
2913 EXTENT_DATA2* ed2;
2914 chunk* c;
2915 LIST_ENTRY* le;
2916 extent* ext = NULL;
2917
2918 le = fcb->extents.Flink;
2919
2920 while (le != &fcb->extents) {
2921 extent* nextext = CONTAINING_RECORD(le, extent, list_entry);
2922
2923 if (!nextext->ignore) {
2924 if (nextext->offset == start_data) {
2925 ext = nextext;
2926 break;
2927 } else if (nextext->offset > start_data)
2928 break;
2929
2930 ext = nextext;
2931 }
2932
2933 le = le->Flink;
2934 }
2935
2936 if (!ext)
2937 return false;
2938
2939 ed = &ext->extent_data;
2940
2941 if (ed->type != EXTENT_TYPE_REGULAR && ed->type != EXTENT_TYPE_PREALLOC) {
2942 TRACE("not extending extent which is not regular or prealloc\n");
2943 return false;
2944 }
2945
2946 ed2 = (EXTENT_DATA2*)ed->data;
2947
2948 if (ext->offset + ed2->num_bytes != start_data) {
2949 TRACE("last EXTENT_DATA does not run up to start_data (%I64x + %I64x != %I64x)\n", ext->offset, ed2->num_bytes, start_data);
2950 return false;
2951 }
2952
2954
2955 if (c->reloc || c->readonly || c->chunk_item->type != Vcb->data_flags)
2956 return false;
2957
2959
2960 if (length > c->chunk_item->size - c->used) {
2962 return false;
2963 }
2964
2965 if (!c->cache_loaded) {
2967
2968 if (!NT_SUCCESS(Status)) {
2969 ERR("load_cache_chunk returned %08lx\n", Status);
2971 return false;
2972 }
2973 }
2974
2975 le = c->space.Flink;
2976 while (le != &c->space) {
2978
2979 if (s->address == ed2->address + ed2->size) {
2980 uint64_t newlen = min(min(s->size, length), MAX_EXTENT_SIZE);
2981
2982 success = insert_extent_chunk(Vcb, fcb, c, start_data, newlen, false, data, Irp, rollback, BTRFS_COMPRESSION_NONE, newlen, file_write, irp_offset);
2983
2984 if (success)
2985 *written += newlen;
2986 else
2988
2989 return success;
2990 } else if (s->address > ed2->address + ed2->size)
2991 break;
2992
2993 le = le->Flink;
2994 }
2995
2997
2998 return false;
2999}
#define acquire_chunk_lock(c, Vcb)
Definition: btrfs_drv.h:1139
#define MAX_EXTENT_SIZE
Definition: btrfs_drv.h:111
NTSTATUS load_cache_chunk(device_extension *Vcb, chunk *c, PIRP Irp)
Definition: free-space.c:980
#define release_chunk_lock(c, Vcb)
Definition: btrfs_drv.h:1140
#define EXTENT_TYPE_PREALLOC
Definition: btrfs.h:76
bool insert_extent_chunk(_In_ device_extension *Vcb, _In_ fcb *fcb, _In_ chunk *c, _In_ uint64_t start_data, _In_ uint64_t length, _In_ bool prealloc, _In_opt_ void *data, _In_opt_ PIRP Irp, _In_ LIST_ENTRY *rollback, _In_ uint8_t compression, _In_ uint64_t decoded_size, _In_ bool file_write, _In_ uint64_t irp_offset)
Definition: write.c:2824
GLdouble s
Definition: gl.h:2039
#define success(from, fromstr, to, tostr)

◆ __attribute__() [9/18]

__attribute__ ( (nonnull(1, 2, 5, 9))  )

Definition at line 3132 of file write.c.

3134 {
3136 LIST_ENTRY* le;
3137 chunk* c;
3138 uint64_t flags, orig_length = length, written = 0;
3139
3140 TRACE("(%p, (%I64x, %I64x), %I64x, %I64x, %p)\n", Vcb, fcb->subvol->id, fcb->inode, start_data, length, data);
3141
3142 if (start_data > 0) {
3143 try_extend_data(Vcb, fcb, start_data, length, data, Irp, &written, file_write, irp_offset, rollback);
3144
3145 if (written == length)
3146 return STATUS_SUCCESS;
3147 else if (written > 0) {
3148 start_data += written;
3149 irp_offset += written;
3150 length -= written;
3151 data = &((uint8_t*)data)[written];
3152 }
3153 }
3154
3155 flags = Vcb->data_flags;
3156
3157 while (written < orig_length) {
3159 bool done = false;
3160
3161 // Rather than necessarily writing the whole extent at once, we deal with it in blocks of 128 MB.
3162 // First, see if we can write the extent part to an existing chunk.
3163
3164 ExAcquireResourceSharedLite(&Vcb->chunk_lock, true);
3165
3166 le = Vcb->chunks.Flink;
3167 while (le != &Vcb->chunks) {
3169
3170 if (!c->readonly && !c->reloc) {
3172
3173 if (c->chunk_item->type == flags && (c->chunk_item->size - c->used) >= newlen &&
3174 insert_extent_chunk(Vcb, fcb, c, start_data, newlen, false, data, Irp, rollback, BTRFS_COMPRESSION_NONE, newlen, file_write, irp_offset)) {
3175 written += newlen;
3176
3177 if (written == orig_length) {
3178 ExReleaseResourceLite(&Vcb->chunk_lock);
3179 return STATUS_SUCCESS;
3180 } else {
3181 done = true;
3182 start_data += newlen;
3183 irp_offset += newlen;
3184 length -= newlen;
3185 data = &((uint8_t*)data)[newlen];
3186 break;
3187 }
3188 } else
3190 }
3191
3192 le = le->Flink;
3193 }
3194
3195 ExReleaseResourceLite(&Vcb->chunk_lock);
3196
3197 if (done) continue;
3198
3199 // Otherwise, see if we can put it in a new chunk.
3200
3201 ExAcquireResourceExclusiveLite(&Vcb->chunk_lock, true);
3202
3203 Status = alloc_chunk(Vcb, flags, &c, false);
3204
3205 ExReleaseResourceLite(&Vcb->chunk_lock);
3206
3207 if (!NT_SUCCESS(Status)) {
3208 ERR("alloc_chunk returned %08lx\n", Status);
3209 return Status;
3210 }
3211
3212 if (c) {
3214
3215 if (c->chunk_item->type == flags && (c->chunk_item->size - c->used) >= newlen &&
3216 insert_extent_chunk(Vcb, fcb, c, start_data, newlen, false, data, Irp, rollback, BTRFS_COMPRESSION_NONE, newlen, file_write, irp_offset)) {
3217 written += newlen;
3218
3219 if (written == orig_length)
3220 return STATUS_SUCCESS;
3221 else {
3222 done = true;
3223 start_data += newlen;
3224 irp_offset += newlen;
3225 length -= newlen;
3226 data = &((uint8_t*)data)[newlen];
3227 }
3228 } else
3230 }
3231
3232 if (!done) {
3233 Status = insert_chunk_fragmented(fcb, start_data, length, data, false, rollback);
3234 if (!NT_SUCCESS(Status))
3235 ERR("insert_chunk_fragmented returned %08lx\n", Status);
3236
3237 return Status;
3238 }
3239 }
3240
3241 return STATUS_DISK_FULL;
3242}
NTSTATUS alloc_chunk(device_extension *Vcb, uint64_t flags, chunk **pc, bool full_size) __attribute__((nonnull(1
GLbitfield flags
Definition: glext.h:7161

◆ __attribute__() [10/18]

__attribute__ ( (nonnull(1, 2, 6))  )

Definition at line 2401 of file write.c.

2402 {
2404 LIST_ENTRY* le;
2405
2406 le = fcb->extents.Flink;
2407
2408 while (le != &fcb->extents) {
2409 LIST_ENTRY* le2 = le->Flink;
2411
2412 if (!ext->ignore) {
2413 EXTENT_DATA* ed = &ext->extent_data;
2414 uint64_t len;
2415
2416 if (ed->type == EXTENT_TYPE_INLINE)
2417 len = ed->decoded_size;
2418 else
2419 len = ((EXTENT_DATA2*)ed->data)->num_bytes;
2420
2421 if (ext->offset < end_data && ext->offset + len > start_data) {
2422 if (ed->type == EXTENT_TYPE_INLINE) {
2423 if (start_data <= ext->offset && end_data >= ext->offset + len) { // remove all
2424 remove_fcb_extent(fcb, ext, rollback);
2425
2427 fcb->inode_item_changed = true;
2428 } else {
2429 ERR("trying to split inline extent\n");
2430#ifdef DEBUG_PARANOID
2431 int3;
2432#endif
2433 return STATUS_INTERNAL_ERROR;
2434 }
2435 } else {
2436 EXTENT_DATA2* ed2 = (EXTENT_DATA2*)ed->data;
2437
2438 if (start_data <= ext->offset && end_data >= ext->offset + len) { // remove all
2439 if (ed2->size != 0) {
2440 chunk* c;
2441
2443 fcb->inode_item_changed = true;
2444
2446
2447 if (!c) {
2448 ERR("get_chunk_from_address(%I64x) failed\n", ed2->address);
2449 } else {
2450 Status = update_changed_extent_ref(Vcb, c, ed2->address, ed2->size, fcb->subvol->id, fcb->inode, ext->offset - ed2->offset, -1,
2452 if (!NT_SUCCESS(Status)) {
2453 ERR("update_changed_extent_ref returned %08lx\n", Status);
2454 goto end;
2455 }
2456 }
2457 }
2458
2459 remove_fcb_extent(fcb, ext, rollback);
2460 } else if (start_data <= ext->offset && end_data < ext->offset + len) { // remove beginning
2461 EXTENT_DATA2* ned2;
2462 extent* newext;
2463
2464 if (ed2->size != 0) {
2465 fcb->inode_item.st_blocks -= end_data - ext->offset;
2466 fcb->inode_item_changed = true;
2467 }
2468
2469 newext = ExAllocatePoolWithTag(PagedPool, offsetof(extent, extent_data) + sizeof(EXTENT_DATA) - 1 + sizeof(EXTENT_DATA2), ALLOC_TAG);
2470 if (!newext) {
2471 ERR("out of memory\n");
2473 goto end;
2474 }
2475
2476 ned2 = (EXTENT_DATA2*)newext->extent_data.data;
2477
2478 newext->extent_data.generation = Vcb->superblock.generation;
2480 newext->extent_data.compression = ed->compression;
2481 newext->extent_data.encryption = ed->encryption;
2482 newext->extent_data.encoding = ed->encoding;
2483 newext->extent_data.type = ed->type;
2484 ned2->address = ed2->address;
2485 ned2->size = ed2->size;
2486 ned2->offset = ed2->offset + (end_data - ext->offset);
2487 ned2->num_bytes = ed2->num_bytes - (end_data - ext->offset);
2488
2489 newext->offset = end_data;
2490 newext->datalen = sizeof(EXTENT_DATA) - 1 + sizeof(EXTENT_DATA2);
2491 newext->unique = ext->unique;
2492 newext->ignore = false;
2493 newext->inserted = true;
2494
2495 if (ext->csum) {
2497 newext->csum = ExAllocatePoolWithTag(PagedPool, (ULONG)((ned2->num_bytes * Vcb->csum_size) >> Vcb->sector_shift), ALLOC_TAG);
2498 if (!newext->csum) {
2499 ERR("out of memory\n");
2501 ExFreePool(newext);
2502 goto end;
2503 }
2504
2505 RtlCopyMemory(newext->csum, (uint8_t*)ext->csum + (((end_data - ext->offset) * Vcb->csum_size) >> Vcb->sector_shift),
2506 (ULONG)((ned2->num_bytes * Vcb->csum_size) >> Vcb->sector_shift));
2507 } else {
2508 newext->csum = ExAllocatePoolWithTag(PagedPool, (ULONG)((ed2->size * Vcb->csum_size) >> Vcb->sector_shift), ALLOC_TAG);
2509 if (!newext->csum) {
2510 ERR("out of memory\n");
2512 ExFreePool(newext);
2513 goto end;
2514 }
2515
2516 RtlCopyMemory(newext->csum, ext->csum, (ULONG)((ed2->size * Vcb->csum_size) >> Vcb->sector_shift));
2517 }
2518 } else
2519 newext->csum = NULL;
2520
2521 add_extent(fcb, &ext->list_entry, newext);
2522
2523 remove_fcb_extent(fcb, ext, rollback);
2524 } else if (start_data > ext->offset && end_data >= ext->offset + len) { // remove end
2525 EXTENT_DATA2* ned2;
2526 extent* newext;
2527
2528 if (ed2->size != 0) {
2529 fcb->inode_item.st_blocks -= ext->offset + len - start_data;
2530 fcb->inode_item_changed = true;
2531 }
2532
2533 newext = ExAllocatePoolWithTag(PagedPool, offsetof(extent, extent_data) + sizeof(EXTENT_DATA) - 1 + sizeof(EXTENT_DATA2), ALLOC_TAG);
2534 if (!newext) {
2535 ERR("out of memory\n");
2537 goto end;
2538 }
2539
2540 ned2 = (EXTENT_DATA2*)newext->extent_data.data;
2541
2542 newext->extent_data.generation = Vcb->superblock.generation;
2544 newext->extent_data.compression = ed->compression;
2545 newext->extent_data.encryption = ed->encryption;
2546 newext->extent_data.encoding = ed->encoding;
2547 newext->extent_data.type = ed->type;
2548 ned2->address = ed2->address;
2549 ned2->size = ed2->size;
2550 ned2->offset = ed2->offset;
2551 ned2->num_bytes = start_data - ext->offset;
2552
2553 newext->offset = ext->offset;
2554 newext->datalen = sizeof(EXTENT_DATA) - 1 + sizeof(EXTENT_DATA2);
2555 newext->unique = ext->unique;
2556 newext->ignore = false;
2557 newext->inserted = true;
2558
2559 if (ext->csum) {
2561 newext->csum = ExAllocatePoolWithTag(PagedPool, (ULONG)((ned2->num_bytes * Vcb->csum_size) >> Vcb->sector_shift), ALLOC_TAG);
2562 if (!newext->csum) {
2563 ERR("out of memory\n");
2565 ExFreePool(newext);
2566 goto end;
2567 }
2568
2569 RtlCopyMemory(newext->csum, ext->csum, (ULONG)((ned2->num_bytes * Vcb->csum_size) >> Vcb->sector_shift));
2570 } else {
2571 newext->csum = ExAllocatePoolWithTag(PagedPool, (ULONG)((ed2->size * Vcb->csum_size) >> Vcb->sector_shift), ALLOC_TAG);
2572 if (!newext->csum) {
2573 ERR("out of memory\n");
2575 ExFreePool(newext);
2576 goto end;
2577 }
2578
2579 RtlCopyMemory(newext->csum, ext->csum, (ULONG)((ed2->size * Vcb->csum_size) >> Vcb->sector_shift));
2580 }
2581 } else
2582 newext->csum = NULL;
2583
2584 InsertHeadList(&ext->list_entry, &newext->list_entry);
2585
2586 remove_fcb_extent(fcb, ext, rollback);
2587 } else if (start_data > ext->offset && end_data < ext->offset + len) { // remove middle
2588 EXTENT_DATA2 *neda2, *nedb2;
2589 extent *newext1, *newext2;
2590
2591 if (ed2->size != 0) {
2592 chunk* c;
2593
2594 fcb->inode_item.st_blocks -= end_data - start_data;
2595 fcb->inode_item_changed = true;
2596
2598
2599 if (!c) {
2600 ERR("get_chunk_from_address(%I64x) failed\n", ed2->address);
2601 } else {
2602 Status = update_changed_extent_ref(Vcb, c, ed2->address, ed2->size, fcb->subvol->id, fcb->inode, ext->offset - ed2->offset, 1,
2604 if (!NT_SUCCESS(Status)) {
2605 ERR("update_changed_extent_ref returned %08lx\n", Status);
2606 goto end;
2607 }
2608 }
2609 }
2610
2611 newext1 = ExAllocatePoolWithTag(PagedPool, offsetof(extent, extent_data) + sizeof(EXTENT_DATA) - 1 + sizeof(EXTENT_DATA2), ALLOC_TAG);
2612 if (!newext1) {
2613 ERR("out of memory\n");
2615 goto end;
2616 }
2617
2618 newext2 = ExAllocatePoolWithTag(PagedPool, offsetof(extent, extent_data) + sizeof(EXTENT_DATA) - 1 + sizeof(EXTENT_DATA2), ALLOC_TAG);
2619 if (!newext2) {
2620 ERR("out of memory\n");
2622 ExFreePool(newext1);
2623 goto end;
2624 }
2625
2626 neda2 = (EXTENT_DATA2*)newext1->extent_data.data;
2627
2628 newext1->extent_data.generation = Vcb->superblock.generation;
2629 newext1->extent_data.decoded_size = ed->decoded_size;
2630 newext1->extent_data.compression = ed->compression;
2631 newext1->extent_data.encryption = ed->encryption;
2632 newext1->extent_data.encoding = ed->encoding;
2633 newext1->extent_data.type = ed->type;
2634 neda2->address = ed2->address;
2635 neda2->size = ed2->size;
2636 neda2->offset = ed2->offset;
2637 neda2->num_bytes = start_data - ext->offset;
2638
2639 nedb2 = (EXTENT_DATA2*)newext2->extent_data.data;
2640
2641 newext2->extent_data.generation = Vcb->superblock.generation;
2642 newext2->extent_data.decoded_size = ed->decoded_size;
2643 newext2->extent_data.compression = ed->compression;
2644 newext2->extent_data.encryption = ed->encryption;
2645 newext2->extent_data.encoding = ed->encoding;
2646 newext2->extent_data.type = ed->type;
2647 nedb2->address = ed2->address;
2648 nedb2->size = ed2->size;
2649 nedb2->offset = ed2->offset + (end_data - ext->offset);
2650 nedb2->num_bytes = ext->offset + len - end_data;
2651
2652 newext1->offset = ext->offset;
2653 newext1->datalen = sizeof(EXTENT_DATA) - 1 + sizeof(EXTENT_DATA2);
2654 newext1->unique = ext->unique;
2655 newext1->ignore = false;
2656 newext1->inserted = true;
2657
2658 newext2->offset = end_data;
2659 newext2->datalen = sizeof(EXTENT_DATA) - 1 + sizeof(EXTENT_DATA2);
2660 newext2->unique = ext->unique;
2661 newext2->ignore = false;
2662 newext2->inserted = true;
2663
2664 if (ext->csum) {
2666 newext1->csum = ExAllocatePoolWithTag(PagedPool, (ULONG)((neda2->num_bytes * Vcb->csum_size) >> Vcb->sector_shift), ALLOC_TAG);
2667 if (!newext1->csum) {
2668 ERR("out of memory\n");
2670 ExFreePool(newext1);
2671 ExFreePool(newext2);
2672 goto end;
2673 }
2674
2675 newext2->csum = ExAllocatePoolWithTag(PagedPool, (ULONG)((nedb2->num_bytes * Vcb->csum_size) >> Vcb->sector_shift), ALLOC_TAG);
2676 if (!newext2->csum) {
2677 ERR("out of memory\n");
2679 ExFreePool(newext1->csum);
2680 ExFreePool(newext1);
2681 ExFreePool(newext2);
2682 goto end;
2683 }
2684
2685 RtlCopyMemory(newext1->csum, ext->csum, (ULONG)((neda2->num_bytes * Vcb->csum_size) >> Vcb->sector_shift));
2686 RtlCopyMemory(newext2->csum, (uint8_t*)ext->csum + (((end_data - ext->offset) * Vcb->csum_size) >> Vcb->sector_shift),
2687 (ULONG)((nedb2->num_bytes * Vcb->csum_size) >> Vcb->sector_shift));
2688 } else {
2689 newext1->csum = ExAllocatePoolWithTag(PagedPool, (ULONG)((ed2->size * Vcb->csum_size) >> Vcb->sector_shift), ALLOC_TAG);
2690 if (!newext1->csum) {
2691 ERR("out of memory\n");
2693 ExFreePool(newext1);
2694 ExFreePool(newext2);
2695 goto end;
2696 }
2697
2698 newext2->csum = ExAllocatePoolWithTag(PagedPool, (ULONG)((ed2->size * Vcb->csum_size) >> Vcb->sector_shift), ALLOC_TAG);
2699 if (!newext2->csum) {
2700 ERR("out of memory\n");
2702 ExFreePool(newext1->csum);
2703 ExFreePool(newext1);
2704 ExFreePool(newext2);
2705 goto end;
2706 }
2707
2708 RtlCopyMemory(newext1->csum, ext->csum, (ULONG)((ed2->size * Vcb->csum_size) >> Vcb->sector_shift));
2709 RtlCopyMemory(newext2->csum, ext->csum, (ULONG)((ed2->size * Vcb->csum_size) >> Vcb->sector_shift));
2710 }
2711 } else {
2712 newext1->csum = NULL;
2713 newext2->csum = NULL;
2714 }
2715
2716 InsertHeadList(&ext->list_entry, &newext1->list_entry);
2717 add_extent(fcb, &newext1->list_entry, newext2);
2718
2719 remove_fcb_extent(fcb, ext, rollback);
2720 }
2721 }
2722 }
2723 }
2724
2725 le = le2;
2726 }
2727
2729
2730end:
2731 fcb->extents_changed = true;
2733
2734 return Status;
2735}
#define int3
Definition: btrfs_drv.h:1745
GLenum GLsizei len
Definition: glext.h:6722
bool extents_changed
Definition: btrfs_drv.h:323

◆ __attribute__() [11/18]

__attribute__ ( (nonnull(1, 3))  )

Definition at line 366 of file write.c.

367 {
369 uint64_t max_stripe_size, max_chunk_size, stripe_size, stripe_length, factor;
370 uint64_t total_size = 0, logaddr;
371 uint16_t i, type, num_stripes, sub_stripes, max_stripes, min_stripes, allowed_missing;
372 stripe* stripes = NULL;
373 uint16_t cisize;
375 chunk* c = NULL;
376 space* s = NULL;
377 LIST_ENTRY* le;
378
379 le = Vcb->devices.Flink;
380 while (le != &Vcb->devices) {
382 total_size += dev->devitem.num_bytes;
383
384 le = le->Flink;
385 }
386
387 TRACE("total_size = %I64x\n", total_size);
388
389 // We purposely check for DATA first - mixed blocks have the same size
390 // as DATA ones.
391 if (flags & BLOCK_FLAG_DATA) {
392 max_stripe_size = 0x40000000; // 1 GB
393 max_chunk_size = 10 * max_stripe_size;
394 } else if (flags & BLOCK_FLAG_METADATA) {
395 if (total_size > 0xC80000000) // 50 GB
396 max_stripe_size = 0x40000000; // 1 GB
397 else
398 max_stripe_size = 0x10000000; // 256 MB
399
400 max_chunk_size = max_stripe_size;
401 } else if (flags & BLOCK_FLAG_SYSTEM) {
402 max_stripe_size = 0x2000000; // 32 MB
403 max_chunk_size = 2 * max_stripe_size;
404 } else {
405 ERR("unknown chunk type\n");
407 }
408
410 min_stripes = 2;
411 max_stripes = 2;
412 sub_stripes = 0;
414 allowed_missing = 0;
415 } else if (flags & BLOCK_FLAG_RAID0) {
416 min_stripes = 2;
417 max_stripes = (uint16_t)min(0xffff, Vcb->superblock.num_devices);
418 sub_stripes = 0;
420 allowed_missing = 0;
421 } else if (flags & BLOCK_FLAG_RAID1) {
422 min_stripes = 2;
423 max_stripes = 2;
424 sub_stripes = 1;
426 allowed_missing = 1;
427 } else if (flags & BLOCK_FLAG_RAID10) {
428 min_stripes = 4;
429 max_stripes = (uint16_t)min(0xffff, Vcb->superblock.num_devices);
430 sub_stripes = 2;
432 allowed_missing = 1;
433 } else if (flags & BLOCK_FLAG_RAID5) {
434 min_stripes = 3;
435 max_stripes = (uint16_t)min(0xffff, Vcb->superblock.num_devices);
436 sub_stripes = 1;
438 allowed_missing = 1;
439 } else if (flags & BLOCK_FLAG_RAID6) {
440 min_stripes = 4;
441 max_stripes = 257;
442 sub_stripes = 1;
444 allowed_missing = 2;
445 } else if (flags & BLOCK_FLAG_RAID1C3) {
446 min_stripes = 3;
447 max_stripes = 3;
448 sub_stripes = 1;
450 allowed_missing = 2;
451 } else if (flags & BLOCK_FLAG_RAID1C4) {
452 min_stripes = 4;
453 max_stripes = 4;
454 sub_stripes = 1;
456 allowed_missing = 3;
457 } else { // SINGLE
458 min_stripes = 1;
459 max_stripes = 1;
460 sub_stripes = 1;
461 type = 0;
462 allowed_missing = 0;
463 }
464
465 if (max_chunk_size > total_size / 10) { // cap at 10%
466 max_chunk_size = total_size / 10;
467 max_stripe_size = max_chunk_size / min_stripes;
468 }
469
470 if (max_stripe_size > total_size / (10 * min_stripes))
471 max_stripe_size = total_size / (10 * min_stripes);
472
473 TRACE("would allocate a new chunk of %I64x bytes and stripe %I64x\n", max_chunk_size, max_stripe_size);
474
475 stripes = ExAllocatePoolWithTag(PagedPool, sizeof(stripe) * max_stripes, ALLOC_TAG);
476 if (!stripes) {
477 ERR("out of memory\n");
479 goto end;
480 }
481
482 num_stripes = 0;
483
484 if (type == BLOCK_FLAG_DUPLICATE) {
485 if (!find_new_dup_stripes(Vcb, stripes, max_stripe_size, full_size)) {
487 goto end;
488 } else
489 num_stripes = max_stripes;
490 } else {
491 for (i = 0; i < max_stripes; i++) {
492 if (!find_new_stripe(Vcb, stripes, i, max_stripe_size, false, full_size))
493 break;
494 else
495 num_stripes++;
496 }
497 }
498
499 if (num_stripes < min_stripes && Vcb->options.allow_degraded && allowed_missing > 0) {
500 uint16_t added_missing = 0;
501
502 for (i = num_stripes; i < max_stripes; i++) {
503 if (!find_new_stripe(Vcb, stripes, i, max_stripe_size, true, full_size))
504 break;
505 else {
506 added_missing++;
507 if (added_missing >= allowed_missing)
508 break;
509 }
510 }
511
512 num_stripes += added_missing;
513 }
514
515 // for RAID10, round down to an even number of stripes
516 if (type == BLOCK_FLAG_RAID10 && (num_stripes % sub_stripes) != 0) {
517 num_stripes -= num_stripes % sub_stripes;
518 }
519
520 if (num_stripes < min_stripes) {
521 WARN("found %u stripes, needed at least %u\n", num_stripes, min_stripes);
523 goto end;
524 }
525
527 if (!c) {
528 ERR("out of memory\n");
530 goto end;
531 }
532
533 c->devices = NULL;
534
535 cisize = sizeof(CHUNK_ITEM) + (num_stripes * sizeof(CHUNK_ITEM_STRIPE));
536 c->chunk_item = ExAllocatePoolWithTag(NonPagedPool, cisize, ALLOC_TAG);
537 if (!c->chunk_item) {
538 ERR("out of memory\n");
540 goto end;
541 }
542
543 stripe_length = 0x10000; // FIXME? BTRFS_STRIPE_LEN in kernel
544
545 if (type == BLOCK_FLAG_DUPLICATE && stripes[1].dh == stripes[0].dh)
546 stripe_size = min(stripes[0].dh->size / 2, max_stripe_size);
547 else {
548 stripe_size = max_stripe_size;
549 for (i = 0; i < num_stripes; i++) {
550 if (stripes[i].dh->size < stripe_size)
551 stripe_size = stripes[i].dh->size;
552 }
553 }
554
555 if (type == BLOCK_FLAG_RAID0)
556 factor = num_stripes;
557 else if (type == BLOCK_FLAG_RAID10)
558 factor = num_stripes / sub_stripes;
559 else if (type == BLOCK_FLAG_RAID5)
560 factor = num_stripes - 1;
561 else if (type == BLOCK_FLAG_RAID6)
562 factor = num_stripes - 2;
563 else
564 factor = 1; // SINGLE, DUPLICATE, RAID1, RAID1C3, RAID1C4
565
566 if (stripe_size * factor > max_chunk_size)
567 stripe_size = max_chunk_size / factor;
568
569 if (stripe_size % stripe_length > 0)
570 stripe_size -= stripe_size % stripe_length;
571
572 if (stripe_size == 0) {
573 ERR("not enough free space found (stripe_size == 0)\n");
575 goto end;
576 }
577
578 c->chunk_item->size = stripe_size * factor;
579 c->chunk_item->root_id = Vcb->extent_root->id;
580 c->chunk_item->stripe_length = stripe_length;
581 c->chunk_item->type = flags;
582 c->chunk_item->opt_io_alignment = (uint32_t)c->chunk_item->stripe_length;
583 c->chunk_item->opt_io_width = (uint32_t)c->chunk_item->stripe_length;
584 c->chunk_item->sector_size = stripes[0].device->devitem.minimal_io_size;
585 c->chunk_item->num_stripes = num_stripes;
586 c->chunk_item->sub_stripes = sub_stripes;
587
588 c->devices = ExAllocatePoolWithTag(NonPagedPool, sizeof(device*) * num_stripes, ALLOC_TAG);
589 if (!c->devices) {
590 ERR("out of memory\n");
592 goto end;
593 }
594
595 cis = (CHUNK_ITEM_STRIPE*)&c->chunk_item[1];
596 for (i = 0; i < num_stripes; i++) {
597 cis[i].dev_id = stripes[i].device->devitem.dev_id;
598
599 if (type == BLOCK_FLAG_DUPLICATE && i == 1 && stripes[i].dh == stripes[0].dh)
600 cis[i].offset = stripes[0].dh->address + stripe_size;
601 else
602 cis[i].offset = stripes[i].dh->address;
603
604 cis[i].dev_uuid = stripes[i].device->devitem.device_uuid;
605
606 c->devices[i] = stripes[i].device;
607 }
608
609 logaddr = find_new_chunk_address(Vcb, c->chunk_item->size);
610
611 Vcb->superblock.chunk_root_generation = Vcb->superblock.generation;
612
613 c->size = cisize;
614 c->offset = logaddr;
615 c->used = c->oldused = 0;
616 c->cache = c->old_cache = NULL;
617 c->readonly = false;
618 c->reloc = false;
619 c->last_alloc_set = false;
620 c->last_stripe = 0;
621 c->cache_loaded = true;
622 c->changed = false;
623 c->space_changed = false;
624 c->balance_num = 0;
625
626 InitializeListHead(&c->space);
627 InitializeListHead(&c->space_size);
628 InitializeListHead(&c->deleting);
629 InitializeListHead(&c->changed_extents);
630
631 InitializeListHead(&c->range_locks);
632 ExInitializeResourceLite(&c->range_locks_lock);
633 KeInitializeEvent(&c->range_locks_event, NotificationEvent, false);
634
635 InitializeListHead(&c->partial_stripes);
636 ExInitializeResourceLite(&c->partial_stripes_lock);
637
639 ExInitializeResourceLite(&c->changed_extents_lock);
640
642 if (!s) {
643 ERR("out of memory\n");
645 goto end;
646 }
647
648 s->address = c->offset;
649 s->size = c->chunk_item->size;
650 InsertTailList(&c->space, &s->list_entry);
651 InsertTailList(&c->space_size, &s->list_entry_size);
652
654
655 for (i = 0; i < num_stripes; i++) {
656 stripes[i].device->devitem.bytes_used += stripe_size;
657
658 space_list_subtract2(&stripes[i].device->space, NULL, cis[i].offset, stripe_size, NULL, NULL);
659 }
660
662
664 Vcb->superblock.incompat_flags |= BTRFS_INCOMPAT_FLAGS_RAID56;
665
666end:
667 if (stripes)
668 ExFreePool(stripes);
669
670 if (!NT_SUCCESS(Status)) {
671 if (c) {
672 if (c->devices)
673 ExFreePool(c->devices);
674
675 if (c->chunk_item)
676 ExFreePool(c->chunk_item);
677
678 ExFreePool(c);
679 }
680
681 if (s) ExFreePool(s);
682 } else {
683 bool done = false;
684
685 le = Vcb->chunks.Flink;
686 while (le != &Vcb->chunks) {
688
689 if (c2->offset > c->offset) {
690 InsertHeadList(le->Blink, &c->list_entry);
691 done = true;
692 break;
693 }
694
695 le = le->Flink;
696 }
697
698 if (!done)
699 InsertTailList(&Vcb->chunks, &c->list_entry);
700
701 c->created = true;
702 c->changed = true;
703 c->space_changed = true;
704 c->list_entry_balance.Flink = NULL;
705
706 *pc = c;
707 }
708
709 return Status;
710}
void space_list_subtract2(LIST_ENTRY *list, LIST_ENTRY *list_size, uint64_t address, uint64_t length, chunk *c, LIST_ENTRY *rollback)
Definition: free-space.c:2155
void protect_superblocks(_Inout_ chunk *c)
Definition: btrfs.c:3777
#define BTRFS_INCOMPAT_FLAGS_RAID56
Definition: btrfs.h:122
#define BLOCK_FLAG_RAID1C4
Definition: btrfs.h:88
#define BLOCK_FLAG_RAID1C3
Definition: btrfs.h:87
NTSTATUS ExInitializeResourceLite(PULONG res)
Definition: env_spec_w32.h:641
#define KeInitializeEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:477
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint factor
Definition: glfuncs.h:178
#define for
Definition: utility.h:88
#define uint16_t
Definition: nsiface.idl:60
@ NotificationEvent
#define BLOCK_FLAG_DATA
Definition: shellext.h:75
#define BLOCK_FLAG_DUPLICATE
Definition: shellext.h:80
#define BLOCK_FLAG_SYSTEM
Definition: shellext.h:76
#define BLOCK_FLAG_RAID10
Definition: shellext.h:81
#define BLOCK_FLAG_RAID0
Definition: shellext.h:78
#define BLOCK_FLAG_RAID6
Definition: shellext.h:83
#define BLOCK_FLAG_METADATA
Definition: shellext.h:77
#define BLOCK_FLAG_RAID1
Definition: shellext.h:79
BTRFS_UUID dev_uuid
Definition: btrfs.h:354
uint64_t offset
Definition: btrfs.h:353
uint64_t dev_id
Definition: btrfs.h:352
uint32_t minimal_io_size
Definition: btrfs.h:183
uint64_t bytes_used
Definition: btrfs.h:180
BTRFS_UUID device_uuid
Definition: btrfs.h:190
uint64_t dev_id
Definition: btrfs.h:178
uint64_t offset
Definition: btrfs_drv.h:564
DEV_ITEM devitem
Definition: btrfs_drv.h:527
LIST_ENTRY space
Definition: btrfs_drv.h:539
uint64_t address
Definition: btrfs_drv.h:518
device * device
Definition: write.c:115
space * dh
Definition: write.c:114

◆ __attribute__() [12/18]

__attribute__ ( (nonnull(1, 3, 5))  )

Definition at line 1908 of file write.c.

1910 {
1912 uint32_t i;
1913 CHUNK_ITEM_STRIPE* cis;
1914 write_stripe* stripes = NULL;
1915 uint64_t total_writing = 0;
1916 ULONG allowed_missing, missing;
1917
1918 TRACE("(%p, %I64x, %p, %x)\n", Vcb, address, data, length);
1919
1920 if (!c) {
1922 if (!c) {
1923 ERR("could not get chunk for address %I64x\n", address);
1924 return STATUS_INTERNAL_ERROR;
1925 }
1926 }
1927
1928 stripes = ExAllocatePoolWithTag(PagedPool, sizeof(write_stripe) * c->chunk_item->num_stripes, ALLOC_TAG);
1929 if (!stripes) {
1930 ERR("out of memory\n");
1932 }
1933
1934 RtlZeroMemory(stripes, sizeof(write_stripe) * c->chunk_item->num_stripes);
1935
1936 cis = (CHUNK_ITEM_STRIPE*)&c->chunk_item[1];
1937
1938 if (c->chunk_item->type & BLOCK_FLAG_RAID0) {
1939 Status = prepare_raid0_write(c, address, data, length, stripes, file_write ? Irp : NULL, irp_offset, wtc);
1940 if (!NT_SUCCESS(Status)) {
1941 ERR("prepare_raid0_write returned %08lx\n", Status);
1942 goto prepare_failed;
1943 }
1944
1945 allowed_missing = 0;
1946 } else if (c->chunk_item->type & BLOCK_FLAG_RAID10) {
1947 Status = prepare_raid10_write(c, address, data, length, stripes, file_write ? Irp : NULL, irp_offset, wtc);
1948 if (!NT_SUCCESS(Status)) {
1949 ERR("prepare_raid10_write returned %08lx\n", Status);
1950 goto prepare_failed;
1951 }
1952
1953 allowed_missing = 1;
1954 } else if (c->chunk_item->type & BLOCK_FLAG_RAID5) {
1955 Status = prepare_raid5_write(Vcb, c, address, data, length, stripes, file_write ? Irp : NULL, irp_offset, priority, wtc);
1956 if (!NT_SUCCESS(Status)) {
1957 ERR("prepare_raid5_write returned %08lx\n", Status);
1958 goto prepare_failed;
1959 }
1960
1961 allowed_missing = 1;
1962 } else if (c->chunk_item->type & BLOCK_FLAG_RAID6) {
1963 Status = prepare_raid6_write(Vcb, c, address, data, length, stripes, file_write ? Irp : NULL, irp_offset, priority, wtc);
1964 if (!NT_SUCCESS(Status)) {
1965 ERR("prepare_raid6_write returned %08lx\n", Status);
1966 goto prepare_failed;
1967 }
1968
1969 allowed_missing = 2;
1970 } else { // write same data to every location - SINGLE, DUP, RAID1, RAID1C3, RAID1C4
1971 for (i = 0; i < c->chunk_item->num_stripes; i++) {
1972 stripes[i].start = address - c->offset;
1973 stripes[i].end = stripes[i].start + length;
1974 stripes[i].data = data;
1975 stripes[i].irp_offset = irp_offset;
1976
1977 if (c->devices[i]->devobj) {
1978 if (file_write) {
1979 uint8_t* va;
1980 ULONG writelen = (ULONG)(stripes[i].end - stripes[i].start);
1981
1982 va = (uint8_t*)MmGetMdlVirtualAddress(Irp->MdlAddress) + stripes[i].irp_offset;
1983
1984 stripes[i].mdl = IoAllocateMdl(va, writelen, false, false, NULL);
1985 if (!stripes[i].mdl) {
1986 ERR("IoAllocateMdl failed\n");
1988 goto prepare_failed;
1989 }
1990
1991 IoBuildPartialMdl(Irp->MdlAddress, stripes[i].mdl, va, writelen);
1992 } else {
1993 stripes[i].mdl = IoAllocateMdl(stripes[i].data, (ULONG)(stripes[i].end - stripes[i].start), false, false, NULL);
1994 if (!stripes[i].mdl) {
1995 ERR("IoAllocateMdl failed\n");
1997 goto prepare_failed;
1998 }
1999
2001
2002 _SEH2_TRY {
2006 } _SEH2_END;
2007
2008 if (!NT_SUCCESS(Status)) {
2009 ERR("MmProbeAndLockPages threw exception %08lx\n", Status);
2010 IoFreeMdl(stripes[i].mdl);
2011 stripes[i].mdl = NULL;
2012 goto prepare_failed;
2013 }
2014 }
2015 }
2016 }
2017
2018 allowed_missing = c->chunk_item->num_stripes - 1;
2019 }
2020
2021 missing = 0;
2022 for (i = 0; i < c->chunk_item->num_stripes; i++) {
2023 if (!c->devices[i]->devobj)
2024 missing++;
2025 }
2026
2027 if (missing > allowed_missing) {
2028 ERR("cannot write as %lu missing devices (maximum %lu)\n", missing, allowed_missing);
2030 goto prepare_failed;
2031 }
2032
2033 for (i = 0; i < c->chunk_item->num_stripes; i++) {
2036
2038 if (!stripe) {
2039 ERR("out of memory\n");
2041 goto end;
2042 }
2043
2044 if (stripes[i].start == stripes[i].end || !c->devices[i]->devobj) {
2046 stripe->Irp = NULL;
2047 stripe->buf = stripes[i].data;
2048 stripe->mdl = NULL;
2049 } else {
2050 stripe->context = (struct _write_data_context*)wtc;
2051 stripe->buf = stripes[i].data;
2052 stripe->device = c->devices[i];
2053 RtlZeroMemory(&stripe->iosb, sizeof(IO_STATUS_BLOCK));
2055 stripe->mdl = stripes[i].mdl;
2056
2057 if (!Irp) {
2059
2060 if (!stripe->Irp) {
2061 ERR("IoAllocateIrp failed\n");
2064 goto end;
2065 }
2066 } else {
2068
2069 if (!stripe->Irp) {
2070 ERR("IoMakeAssociatedIrp failed\n");
2073 goto end;
2074 }
2075 }
2076
2080
2082 stripe->Irp->AssociatedIrp.SystemBuffer = MmGetSystemAddressForMdlSafe(stripes[i].mdl, priority);
2083
2084 stripe->Irp->Flags = IRP_BUFFERED_IO;
2085 } else if (stripe->device->devobj->Flags & DO_DIRECT_IO)
2086 stripe->Irp->MdlAddress = stripe->mdl;
2087 else
2089
2090#ifdef DEBUG_PARANOID
2091 if (stripes[i].end < stripes[i].start) {
2092 ERR("trying to write stripe with negative length (%I64x < %I64x)\n", stripes[i].end, stripes[i].start);
2093 int3;
2094 }
2095#endif
2096
2097 IrpSp->Parameters.Write.Length = (ULONG)(stripes[i].end - stripes[i].start);
2098 IrpSp->Parameters.Write.ByteOffset.QuadPart = stripes[i].start + cis[i].offset;
2099
2100 total_writing += IrpSp->Parameters.Write.Length;
2101
2102 stripe->Irp->UserIosb = &stripe->iosb;
2103 wtc->stripes_left++;
2104
2105 IoSetCompletionRoutine(stripe->Irp, write_data_completion, stripe, true, true, true);
2106 }
2107
2108 InsertTailList(&wtc->stripes, &stripe->list_entry);
2109 }
2110
2111 if (diskacc)
2112 fFsRtlUpdateDiskCounters(0, total_writing);
2113
2115
2116end:
2117
2119
2120 if (!NT_SUCCESS(Status))
2122
2123 return Status;
2124
2125prepare_failed:
2126 for (i = 0; i < c->chunk_item->num_stripes; i++) {
2127 if (stripes[i].mdl && (i == 0 || stripes[i].mdl != stripes[i-1].mdl)) {
2128 if (stripes[i].mdl->MdlFlags & MDL_PAGES_LOCKED)
2130
2132 }
2133 }
2134
2135 if (wtc->parity1_mdl) {
2136 if (wtc->parity1_mdl->MdlFlags & MDL_PAGES_LOCKED)
2137 MmUnlockPages(wtc->parity1_mdl);
2138
2139 IoFreeMdl(wtc->parity1_mdl);
2140 wtc->parity1_mdl = NULL;
2141 }
2142
2143 if (wtc->parity2_mdl) {
2144 if (wtc->parity2_mdl->MdlFlags & MDL_PAGES_LOCKED)
2145 MmUnlockPages(wtc->parity2_mdl);
2146
2147 IoFreeMdl(wtc->parity2_mdl);
2148 wtc->parity2_mdl = NULL;
2149 }
2150
2151 if (wtc->mdl) {
2152 if (wtc->mdl->MdlFlags & MDL_PAGES_LOCKED)
2153 MmUnlockPages(wtc->mdl);
2154
2155 IoFreeMdl(wtc->mdl);
2156 wtc->mdl = NULL;
2157 }
2158
2159 if (wtc->parity1) {
2160 ExFreePool(wtc->parity1);
2161 wtc->parity1 = NULL;
2162 }
2163
2164 if (wtc->parity2) {
2165 ExFreePool(wtc->parity2);
2166 wtc->parity2 = NULL;
2167 }
2168
2169 if (wtc->scratch) {
2170 ExFreePool(wtc->scratch);
2171 wtc->scratch = NULL;
2172 }
2173
2175 return Status;
2176}
NTSTATUS NTSTATUS NTSTATUS void free_write_data_stripes(write_data_context *wtc) __attribute__((nonnull(1)))
@ WriteDataStatus_Pending
Definition: btrfs_drv.h:915
@ WriteDataStatus_Ignore
Definition: btrfs_drv.h:920
bool diskacc
Definition: btrfs.c:101
tFsRtlUpdateDiskCounters fFsRtlUpdateDiskCounters
Definition: btrfs.c:94
#define DO_BUFFERED_IO
Definition: env_spec_w32.h:394
#define DO_DIRECT_IO
Definition: env_spec_w32.h:396
VOID NTAPI IoBuildPartialMdl(IN PMDL SourceMdl, IN PMDL TargetMdl, IN PVOID VirtualAddress, IN ULONG Length)
Definition: iomdl.c:96
#define IoSetCompletionRoutine(_Irp, _CompletionRoutine, _Context, _InvokeOnSuccess, _InvokeOnError, _InvokeOnCancel)
Definition: irp.cpp:490
PIRP NTAPI IoAllocateIrp(IN CCHAR StackSize, IN BOOLEAN ChargeQuota)
Definition: irp.c:615
PIRP NTAPI IoMakeAssociatedIrp(IN PIRP Irp, IN CCHAR StackSize)
Definition: irp.c:1925
#define IRP_MJ_WRITE
Definition: rdpdr.c:47
#define STATUS_DEVICE_NOT_READY
Definition: shellext.h:70
struct _NAMED_PIPE_CREATE_PARAMETERS * Parameters
Definition: iotypes.h:3128
LIST_ENTRY stripes
Definition: btrfs_drv.h:938
PFILE_OBJECT fileobj
Definition: btrfs_drv.h:526
PDEVICE_OBJECT devobj
Definition: btrfs_drv.h:525
uint64_t irp_offset
Definition: write.c:25
uint8_t * data
Definition: write.c:23
uint64_t start
Definition: write.c:21
PMDL mdl
Definition: write.c:24
uint64_t end
Definition: write.c:22
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetNextIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2695
#define IRP_BUFFERED_IO

◆ __attribute__() [13/18]

__attribute__ ( (nonnull(1, 3, 5, 8))  )

Definition at line 712 of file write.c.

714 {
715 uint64_t startoff, endoff;
716 uint16_t startoffstripe, endoffstripe, stripenum;
717 uint64_t pos, *stripeoff;
718 uint32_t i;
719 bool file_write = Irp && Irp->MdlAddress && (Irp->MdlAddress->ByteOffset == 0);
720 PMDL master_mdl;
721 PFN_NUMBER* pfns;
722
723 stripeoff = ExAllocatePoolWithTag(PagedPool, sizeof(uint64_t) * c->chunk_item->num_stripes, ALLOC_TAG);
724 if (!stripeoff) {
725 ERR("out of memory\n");
727 }
728
729 get_raid0_offset(address - c->offset, c->chunk_item->stripe_length, c->chunk_item->num_stripes, &startoff, &startoffstripe);
730 get_raid0_offset(address + length - c->offset - 1, c->chunk_item->stripe_length, c->chunk_item->num_stripes, &endoff, &endoffstripe);
731
732 if (file_write) {
733 master_mdl = Irp->MdlAddress;
734
735 pfns = (PFN_NUMBER*)(Irp->MdlAddress + 1);
736 pfns = &pfns[irp_offset >> PAGE_SHIFT];
737 } else if (((ULONG_PTR)data % PAGE_SIZE) != 0) {
739 if (!wtc->scratch) {
740 ERR("out of memory\n");
742 }
743
744 RtlCopyMemory(wtc->scratch, data, length);
745
746 master_mdl = IoAllocateMdl(wtc->scratch, length, false, false, NULL);
747 if (!master_mdl) {
748 ERR("out of memory\n");
750 }
751
752 MmBuildMdlForNonPagedPool(master_mdl);
753
754 wtc->mdl = master_mdl;
755
756 pfns = (PFN_NUMBER*)(master_mdl + 1);
757 } else {
759
760 master_mdl = IoAllocateMdl(data, length, false, false, NULL);
761 if (!master_mdl) {
762 ERR("out of memory\n");
764 }
765
766 _SEH2_TRY {
770 } _SEH2_END;
771
772 if (!NT_SUCCESS(Status)) {
773 ERR("MmProbeAndLockPages threw exception %08lx\n", Status);
774 IoFreeMdl(master_mdl);
775 return Status;
776 }
777
778 wtc->mdl = master_mdl;
779
780 pfns = (PFN_NUMBER*)(master_mdl + 1);
781 }
782
783 for (i = 0; i < c->chunk_item->num_stripes; i++) {
784 if (startoffstripe > i)
785 stripes[i].start = startoff - (startoff % c->chunk_item->stripe_length) + c->chunk_item->stripe_length;
786 else if (startoffstripe == i)
787 stripes[i].start = startoff;
788 else
789 stripes[i].start = startoff - (startoff % c->chunk_item->stripe_length);
790
791 if (endoffstripe > i)
792 stripes[i].end = endoff - (endoff % c->chunk_item->stripe_length) + c->chunk_item->stripe_length;
793 else if (endoffstripe == i)
794 stripes[i].end = endoff + 1;
795 else
796 stripes[i].end = endoff - (endoff % c->chunk_item->stripe_length);
797
798 if (stripes[i].start != stripes[i].end) {
799 stripes[i].mdl = IoAllocateMdl(NULL, (ULONG)(stripes[i].end - stripes[i].start), false, false, NULL);
800 if (!stripes[i].mdl) {
801 ERR("IoAllocateMdl failed\n");
802 ExFreePool(stripeoff);
804 }
805 }
806 }
807
808 pos = 0;
809 RtlZeroMemory(stripeoff, sizeof(uint64_t) * c->chunk_item->num_stripes);
810
811 stripenum = startoffstripe;
812
813 while (pos < length) {
814 PFN_NUMBER* stripe_pfns = (PFN_NUMBER*)(stripes[stripenum].mdl + 1);
815
816 if (pos == 0) {
817 uint32_t writelen = (uint32_t)min(stripes[stripenum].end - stripes[stripenum].start,
818 c->chunk_item->stripe_length - (stripes[stripenum].start % c->chunk_item->stripe_length));
819
820 RtlCopyMemory(stripe_pfns, pfns, writelen * sizeof(PFN_NUMBER) >> PAGE_SHIFT);
821
822 stripeoff[stripenum] += writelen;
823 pos += writelen;
824 } else if (length - pos < c->chunk_item->stripe_length) {
825 RtlCopyMemory(&stripe_pfns[stripeoff[stripenum] >> PAGE_SHIFT], &pfns[pos >> PAGE_SHIFT], (ULONG)((length - pos) * sizeof(PFN_NUMBER) >> PAGE_SHIFT));
826 break;
827 } else {
828 RtlCopyMemory(&stripe_pfns[stripeoff[stripenum] >> PAGE_SHIFT], &pfns[pos >> PAGE_SHIFT], (ULONG)(c->chunk_item->stripe_length * sizeof(PFN_NUMBER) >> PAGE_SHIFT));
829
830 stripeoff[stripenum] += c->chunk_item->stripe_length;
831 pos += c->chunk_item->stripe_length;
832 }
833
834 stripenum = (stripenum + 1) % c->chunk_item->num_stripes;
835 }
836
837 ExFreePool(stripeoff);
838
839 return STATUS_SUCCESS;
840}

◆ __attribute__() [14/18]

__attribute__ ( (nonnull(1, 3, 7))  )

Definition at line 2757 of file write.c.

2759 {
2760 extent* ext;
2761 LIST_ENTRY* le;
2762
2763 ext = ExAllocatePoolWithTag(PagedPool, offsetof(extent, extent_data) + edsize, ALLOC_TAG);
2764 if (!ext) {
2765 ERR("out of memory\n");
2767 }
2768
2769 ext->offset = offset;
2770 ext->datalen = edsize;
2771 ext->unique = unique;
2772 ext->ignore = false;
2773 ext->inserted = true;
2774 ext->csum = csum;
2775
2776 RtlCopyMemory(&ext->extent_data, ed, edsize);
2777
2778 le = fcb->extents.Flink;
2779 while (le != &fcb->extents) {
2780 extent* oldext = CONTAINING_RECORD(le, extent, list_entry);
2781
2782 if (oldext->offset >= offset) {
2783 InsertHeadList(le->Blink, &ext->list_entry);
2784 goto end;
2785 }
2786
2787 le = le->Flink;
2788 }
2789
2790 InsertTailList(&fcb->extents, &ext->list_entry);
2791
2792end:
2793 add_insert_extent_rollback(rollback, fcb, ext);
2794
2795 return STATUS_SUCCESS;
2796}

◆ __attribute__() [15/18]

__attribute__ ( (nonnull(1, 4))  )

Definition at line 3058 of file write.c.

3059 {
3060 LIST_ENTRY* le;
3061 chunk* c;
3064 bool page_file = fcb->Header.Flags2 & FSRTL_FLAG2_IS_PAGING_FILE;
3065
3066 flags = fcb->Vcb->data_flags;
3067
3068 do {
3070
3071 ExAcquireResourceSharedLite(&fcb->Vcb->chunk_lock, true);
3072
3073 le = fcb->Vcb->chunks.Flink;
3074 while (le != &fcb->Vcb->chunks) {
3076
3077 if (!c->readonly && !c->reloc) {
3079
3080 if (c->chunk_item->type == flags && (c->chunk_item->size - c->used) >= extlen) {
3081 if (insert_extent_chunk(fcb->Vcb, fcb, c, start, extlen, !page_file, NULL, NULL, rollback, BTRFS_COMPRESSION_NONE, extlen, false, 0)) {
3082 ExReleaseResourceLite(&fcb->Vcb->chunk_lock);
3083 goto cont;
3084 }
3085 }
3086
3088 }
3089
3090 le = le->Flink;
3091 }
3092
3093 ExReleaseResourceLite(&fcb->Vcb->chunk_lock);
3094
3095 ExAcquireResourceExclusiveLite(&fcb->Vcb->chunk_lock, true);
3096
3097 Status = alloc_chunk(fcb->Vcb, flags, &c, false);
3098
3099 ExReleaseResourceLite(&fcb->Vcb->chunk_lock);
3100
3101 if (!NT_SUCCESS(Status)) {
3102 ERR("alloc_chunk returned %08lx\n", Status);
3103 goto end;
3104 }
3105
3107
3108 if (c->chunk_item->type == flags && (c->chunk_item->size - c->used) >= extlen) {
3109 if (insert_extent_chunk(fcb->Vcb, fcb, c, start, extlen, !page_file, NULL, NULL, rollback, BTRFS_COMPRESSION_NONE, extlen, false, 0))
3110 goto cont;
3111 }
3112
3114
3115 Status = insert_chunk_fragmented(fcb, start, length, NULL, true, rollback);
3116 if (!NT_SUCCESS(Status))
3117 ERR("insert_chunk_fragmented returned %08lx\n", Status);
3118
3119 goto end;
3120
3121cont:
3122 length -= extlen;
3123 start += extlen;
3124 } while (length > 0);
3125
3127
3128end:
3129 return Status;
3130}

◆ __attribute__() [16/18]

__attribute__ ( (nonnull(1, 4, 5))  )

Definition at line 2178 of file write.c.

2179 {
2180 uint64_t startoff, endoff;
2181 uint16_t startoffstripe, endoffstripe, datastripes;
2182
2183 datastripes = c->chunk_item->num_stripes - (c->chunk_item->type & BLOCK_FLAG_RAID5 ? 1 : 2);
2184
2185 get_raid0_offset(address - c->offset, c->chunk_item->stripe_length, datastripes, &startoff, &startoffstripe);
2186 get_raid0_offset(address + length - c->offset - 1, c->chunk_item->stripe_length, datastripes, &endoff, &endoffstripe);
2187
2188 startoff -= startoff % c->chunk_item->stripe_length;
2189 endoff = sector_align(endoff, c->chunk_item->stripe_length);
2190
2191 *lockaddr = c->offset + (startoff * datastripes);
2192 *locklen = (endoff - startoff) * datastripes;
2193}

◆ __attribute__() [17/18]

__attribute__ ( (nonnull(1, 6))  )

Definition at line 3336 of file write.c.

3337 {
3338 uint64_t oldalloc, newalloc;
3339 bool cur_inline;
3341
3342 TRACE("(%p, %p, %I64x, %u)\n", fcb, fileref, end, prealloc);
3343
3344 if (fcb->ads) {
3345 if (end > 0xffff)
3346 return STATUS_DISK_FULL;
3347
3348 return stream_set_end_of_file_information(fcb->Vcb, (uint16_t)end, fcb, fileref, false);
3349 } else {
3350 extent* ext = NULL;
3351 LIST_ENTRY* le;
3352
3353 le = fcb->extents.Blink;
3354 while (le != &fcb->extents) {
3356
3357 if (!ext2->ignore) {
3358 ext = ext2;
3359 break;
3360 }
3361
3362 le = le->Blink;
3363 }
3364
3365 oldalloc = 0;
3366 if (ext) {
3367 EXTENT_DATA* ed = &ext->extent_data;
3368 EXTENT_DATA2* ed2 = (EXTENT_DATA2*)ed->data;
3369
3370 oldalloc = ext->offset + (ed->type == EXTENT_TYPE_INLINE ? ed->decoded_size : ed2->num_bytes);
3371 cur_inline = ed->type == EXTENT_TYPE_INLINE;
3372
3373 if (cur_inline && end > fcb->Vcb->options.max_inline) {
3374 uint64_t origlength, length;
3375 uint8_t* data;
3376
3377 TRACE("giving inline file proper extents\n");
3378
3379 origlength = ed->decoded_size;
3380
3381 cur_inline = false;
3382
3383 length = sector_align(origlength, fcb->Vcb->superblock.sector_size);
3384
3386 if (!data) {
3387 ERR("could not allocate %I64x bytes for data\n", length);
3389 }
3390
3391 Status = read_file(fcb, data, 0, origlength, NULL, Irp);
3392 if (!NT_SUCCESS(Status)) {
3393 ERR("read_file returned %08lx\n", Status);
3395 return Status;
3396 }
3397
3398 RtlZeroMemory(data + origlength, (ULONG)(length - origlength));
3399
3401 if (!NT_SUCCESS(Status)) {
3402 ERR("excise_extents returned %08lx\n", Status);
3404 return Status;
3405 }
3406
3407 Status = do_write_file(fcb, 0, length, data, Irp, false, 0, rollback);
3408 if (!NT_SUCCESS(Status)) {
3409 ERR("do_write_file returned %08lx\n", Status);
3411 return Status;
3412 }
3413
3414 oldalloc = ext->offset + length;
3415
3417 }
3418
3419 if (cur_inline) {
3420 uint16_t edsize;
3421
3422 if (end > oldalloc) {
3423 edsize = (uint16_t)(offsetof(EXTENT_DATA, data[0]) + end - ext->offset);
3425
3426 if (!ed) {
3427 ERR("out of memory\n");
3429 }
3430
3431 ed->generation = fcb->Vcb->superblock.generation;
3432 ed->decoded_size = end - ext->offset;
3437
3438 Status = read_file(fcb, ed->data, ext->offset, oldalloc, NULL, Irp);
3439 if (!NT_SUCCESS(Status)) {
3440 ERR("read_file returned %08lx\n", Status);
3441 ExFreePool(ed);
3442 return Status;
3443 }
3444
3445 RtlZeroMemory(ed->data + oldalloc - ext->offset, (ULONG)(end - oldalloc));
3446
3447 remove_fcb_extent(fcb, ext, rollback);
3448
3449 Status = add_extent_to_fcb(fcb, ext->offset, ed, edsize, ext->unique, NULL, rollback);
3450 if (!NT_SUCCESS(Status)) {
3451 ERR("add_extent_to_fcb returned %08lx\n", Status);
3452 ExFreePool(ed);
3453 return Status;
3454 }
3455
3456 ExFreePool(ed);
3457
3458 fcb->extents_changed = true;
3460 }
3461
3462 TRACE("extending inline file (oldalloc = %I64x, end = %I64x)\n", oldalloc, end);
3463
3465 TRACE("setting st_size to %I64x\n", end);
3466
3468
3469 fcb->Header.AllocationSize.QuadPart = fcb->Header.FileSize.QuadPart = fcb->Header.ValidDataLength.QuadPart = end;
3470 } else {
3471 newalloc = sector_align(end, fcb->Vcb->superblock.sector_size);
3472
3473 if (newalloc > oldalloc) {
3474 if (prealloc) {
3475 // FIXME - try and extend previous extent first
3476
3477 Status = insert_prealloc_extent(fcb, oldalloc, newalloc - oldalloc, rollback);
3478
3480 ERR("insert_prealloc_extent returned %08lx\n", Status);
3481 return Status;
3482 }
3483 }
3484
3485 fcb->extents_changed = true;
3486 }
3487
3489 fcb->inode_item_changed = true;
3491
3492 TRACE("setting st_size to %I64x\n", end);
3493
3494 TRACE("newalloc = %I64x\n", newalloc);
3495
3496 fcb->Header.AllocationSize.QuadPart = newalloc;
3497 fcb->Header.FileSize.QuadPart = fcb->Header.ValidDataLength.QuadPart = end;
3498 }
3499 } else {
3500 if (end > fcb->Vcb->options.max_inline) {
3501 newalloc = sector_align(end, fcb->Vcb->superblock.sector_size);
3502
3503 if (prealloc) {
3504 Status = insert_prealloc_extent(fcb, 0, newalloc, rollback);
3505
3507 ERR("insert_prealloc_extent returned %08lx\n", Status);
3508 return Status;
3509 }
3510 }
3511
3512 fcb->extents_changed = true;
3513 fcb->inode_item_changed = true;
3515
3517 TRACE("setting st_size to %I64x\n", end);
3518
3519 TRACE("newalloc = %I64x\n", newalloc);
3520
3521 fcb->Header.AllocationSize.QuadPart = newalloc;
3522 fcb->Header.FileSize.QuadPart = fcb->Header.ValidDataLength.QuadPart = end;
3523 } else {
3524 EXTENT_DATA* ed;
3525 uint16_t edsize;
3526
3527 edsize = (uint16_t)(offsetof(EXTENT_DATA, data[0]) + end);
3529
3530 if (!ed) {
3531 ERR("out of memory\n");
3533 }
3534
3535 ed->generation = fcb->Vcb->superblock.generation;
3536 ed->decoded_size = end;
3541
3542 RtlZeroMemory(ed->data, (ULONG)end);
3543
3544 Status = add_extent_to_fcb(fcb, 0, ed, edsize, false, NULL, rollback);
3545 if (!NT_SUCCESS(Status)) {
3546 ERR("add_extent_to_fcb returned %08lx\n", Status);
3547 ExFreePool(ed);
3548 return Status;
3549 }
3550
3551 ExFreePool(ed);
3552
3553 fcb->extents_changed = true;
3554 fcb->inode_item_changed = true;
3556
3558 TRACE("setting st_size to %I64x\n", end);
3559
3561
3562 fcb->Header.AllocationSize.QuadPart = fcb->Header.FileSize.QuadPart = fcb->Header.ValidDataLength.QuadPart = end;
3563 }
3564 }
3565 }
3566
3567 return STATUS_SUCCESS;
3568}
_In_ fcb _In_ chunk _In_ uint64_t _In_ uint64_t _In_ bool prealloc
Definition: btrfs_drv.h:1364
NTSTATUS stream_set_end_of_file_information(device_extension *Vcb, uint16_t end, fcb *fcb, file_ref *fileref, bool advance_only)
Definition: fileinfo.c:3170
static const BYTE ext2[]
Definition: encode.c:2699

◆ __attribute__() [18/18]

__attribute__ ( (nonnull(2, 3))  )

Definition at line 2278 of file write.c.

2280 {
2281 write_data_stripe* stripe = conptr;
2283 LIST_ENTRY* le;
2284
2286
2287 // FIXME - we need a lock here
2288
2289 if (stripe->status == WriteDataStatus_Cancelling) {
2291 goto end;
2292 }
2293
2294 stripe->iosb = Irp->IoStatus;
2295
2296 if (NT_SUCCESS(Irp->IoStatus.Status)) {
2298 } else {
2299 le = context->stripes.Flink;
2300
2301 stripe->status = WriteDataStatus_Error;
2302
2303 while (le != &context->stripes) {
2305
2306 if (s2->status == WriteDataStatus_Pending) {
2308 IoCancelIrp(s2->Irp);
2309 }
2310
2311 le = le->Flink;
2312 }
2313 }
2314
2315end:
2316 if (InterlockedDecrement(&context->stripes_left) == 0)
2317 KeSetEvent(&context->Event, 0, false);
2318
2320}
#define InterlockedDecrement
Definition: armddk.h:52
@ WriteDataStatus_Cancelled
Definition: btrfs_drv.h:919
@ WriteDataStatus_Error
Definition: btrfs_drv.h:917
@ WriteDataStatus_Cancelling
Definition: btrfs_drv.h:918
@ WriteDataStatus_Success
Definition: btrfs_drv.h:916
#define UNUSED(x)
Definition: btrfs_drv.h:82
#define KeSetEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:476
struct S2 s2
BOOLEAN NTAPI IoCancelIrp(IN PIRP Irp)
Definition: irp.c:1101
#define STATUS_MORE_PROCESSING_REQUIRED
Definition: shellext.h:68
Definition: http.c:7252
_In_ PDEVICE_OBJECT DeviceObject
Definition: wdfdevice.h:2055

◆ _Dispatch_type_()

_Dispatch_type_ ( IRP_MJ_WRITE  )

Definition at line 4663 of file write.c.

4666 {
4668 bool top_level;
4670 device_extension* Vcb = DeviceObject->DeviceExtension;
4672 fcb* fcb = FileObject ? FileObject->FsContext : NULL;
4673 ccb* ccb = FileObject ? FileObject->FsContext2 : NULL;
4675
4677
4678 top_level = is_top_level(Irp);
4679
4680 if (Vcb && Vcb->type == VCB_TYPE_VOLUME) {
4682 goto exit;
4683 } else if (!Vcb || Vcb->type != VCB_TYPE_FS) {
4685 goto end;
4686 }
4687
4688 if (!fcb) {
4689 ERR("fcb was NULL\n");
4691 goto end;
4692 }
4693
4694 if (!ccb) {
4695 ERR("ccb was NULL\n");
4697 goto end;
4698 }
4699
4700 if (Irp->RequestorMode == UserMode && !(ccb->access & (FILE_WRITE_DATA | FILE_APPEND_DATA))) {
4701 WARN("insufficient permissions\n");
4703 goto end;
4704 }
4705
4706 if (fcb == Vcb->volume_fcb) {
4707 if (!Vcb->locked || Vcb->locked_fileobj != FileObject) {
4708 ERR("trying to write to volume when not locked, or locked with another FileObject\n");
4710 goto end;
4711 }
4712
4713 TRACE("writing directly to volume\n");
4714
4716
4717 Status = IoCallDriver(Vcb->Vpb->RealDevice, Irp);
4718 goto exit;
4719 }
4720
4723 goto end;
4724 }
4725
4726 if (Vcb->readonly) {
4728 goto end;
4729 }
4730
4731 _SEH2_TRY {
4733 CcMdlWriteComplete(IrpSp->FileObject, &IrpSp->Parameters.Write.ByteOffset, Irp->MdlAddress);
4734
4735 Irp->MdlAddress = NULL;
4737 } else {
4738 if (!(Irp->Flags & IRP_PAGING_IO))
4740
4741 // Don't offload jobs when doing paging IO - otherwise this can lead to
4742 // deadlocks in CcCopyWrite.
4743 if (Irp->Flags & IRP_PAGING_IO)
4744 wait = true;
4745
4746 Status = write_file(Vcb, Irp, wait, false);
4747 }
4750 } _SEH2_END;
4751
4752end:
4753 Irp->IoStatus.Status = Status;
4754
4755 TRACE("wrote %Iu bytes\n", Irp->IoStatus.Information);
4756
4757 if (Status != STATUS_PENDING)
4759 else {
4761
4762 if (!add_thread_job(Vcb, Irp))
4764 }
4765
4766exit:
4767 if (top_level)
4769
4770 TRACE("returning %08lx\n", Status);
4771
4773
4774 return Status;
4775}
static void write_file(HANDLE hFile, const WCHAR *str)
Definition: export.c:22
#define VCB_TYPE_VOLUME
Definition: btrfs_drv.h:689
bool add_thread_job(device_extension *Vcb, PIRP Irp)
#define VCB_TYPE_FS
Definition: btrfs_drv.h:687
NTSTATUS do_write_job(device_extension *Vcb, PIRP Irp)
Definition: worker-thread.c:68
static __inline POPLOCK fcb_oplock(fcb *fcb)
Definition: btrfs_drv.h:1677
NTSTATUS vol_write(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
Definition: volume.c:225
static __inline bool is_subvol_readonly(root *r, PIRP Irp)
Definition: btrfs_drv.h:1033
VOID NTAPI CcMdlWriteComplete(IN PFILE_OBJECT FileObject, IN PLARGE_INTEGER FileOffset, IN PMDL MdlChain)
Definition: mdlsup.c:102
bool is_top_level(_In_ PIRP Irp)
Definition: btrfs.c:278
#define FsRtlEnterFileSystem
#define FsRtlExitFileSystem
IoMarkIrpPending(Irp)
#define UserMode
Definition: asm.h:35
#define FILE_WRITE_DATA
Definition: nt_native.h:631
#define FILE_APPEND_DATA
Definition: nt_native.h:634
#define IoSkipCurrentIrpStackLocation(Irp)
Definition: ntifs_ex.h:421
#define IoCompleteRequest
Definition: irp.c:1240
BOOLEAN NTAPI IoIsOperationSynchronous(IN PIRP Irp)
Definition: irp.c:1882
#define IoCallDriver
Definition: irp.c:1225
VOID NTAPI IoSetTopLevelIrp(IN PIRP Irp)
Definition: irp.c:2000
NTSTATUS NTAPI FsRtlCheckOplock(IN POPLOCK Oplock, IN PIRP Irp, IN PVOID Context, IN POPLOCK_WAIT_COMPLETE_ROUTINE CompletionRoutine OPTIONAL, IN POPLOCK_FS_PREPOST_IRP PostIrpRoutine OPTIONAL)
Definition: oplock.c:1170
#define true
Definition: stdbool.h:36
ACCESS_MASK access
Definition: btrfs_drv.h:382
#define STATUS_MEDIA_WRITE_PROTECTED
Definition: udferr_usr.h:161
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define IRP_MN_COMPLETE
Definition: iotypes.h:4420
#define IO_NO_INCREMENT
Definition: iotypes.h:598
#define IRP_PAGING_IO

◆ _Function_class_()

_Function_class_ ( IO_COMPLETION_ROUTINE  )

Definition at line 28 of file write.c.

39 {
40 LIST_ENTRY* le;
41 space* s;
42
43 TRACE("(%p, %I64x, %I64x, %p)\n", Vcb, c->offset, length, address);
44
45 if (length > c->chunk_item->size - c->used)
46 return false;
47
48 if (!c->cache_loaded) {
50
51 if (!NT_SUCCESS(Status)) {
52 ERR("load_cache_chunk returned %08lx\n", Status);
53 return false;
54 }
55 }
56
57 if (IsListEmpty(&c->space_size))
58 return false;
59
60 le = c->space_size.Flink;
61 while (le != &c->space_size) {
62 s = CONTAINING_RECORD(le, space, list_entry_size);
63
64 if (s->size == length) {
65 *address = s->address;
66 return true;
67 } else if (s->size < length) {
68 if (le == c->space_size.Flink)
69 return false;
70
71 s = CONTAINING_RECORD(le->Blink, space, list_entry_size);
72
73 *address = s->address;
74 return true;
75 }
76
77 le = le->Flink;
78 }
79
80 s = CONTAINING_RECORD(c->space_size.Blink, space, list_entry_size);
81
82 if (s->size > length) {
83 *address = s->address;
84 return true;
85 }
86
87 return false;
88}

◆ _Releases_lock_()

_Releases_lock_ ( c->  lock)

◆ _Requires_lock_held_()

_Requires_lock_held_ ( c->  lock)
pure virtual

◆ insert_extent_chunk()

bool insert_extent_chunk ( _In_ device_extension Vcb,
_In_ fcb fcb,
_In_ chunk c,
_In_ uint64_t  start_data,
_In_ uint64_t  length,
_In_ bool  prealloc,
_In_opt_ void data,
_In_opt_ PIRP  Irp,
_In_ LIST_ENTRY rollback,
_In_ uint8_t  compression,
_In_ uint64_t  decoded_size,
_In_ bool  file_write,
_In_ uint64_t  irp_offset 
)

Definition at line 2824 of file write.c.

2825 {
2828 EXTENT_DATA* ed;
2829 EXTENT_DATA2* ed2;
2830 uint16_t edsize = (uint16_t)(offsetof(EXTENT_DATA, data[0]) + sizeof(EXTENT_DATA2));
2831 void* csum = NULL;
2832
2833 TRACE("(%p, (%I64x, %I64x), %I64x, %I64x, %I64x, %u, %p, %p)\n", Vcb, fcb->subvol->id, fcb->inode, c->offset, start_data, length, prealloc, data, rollback);
2834
2836 return false;
2837
2838 // add extent data to inode
2840 if (!ed) {
2841 ERR("out of memory\n");
2842 return false;
2843 }
2844
2845 ed->generation = Vcb->superblock.generation;
2851
2852 ed2 = (EXTENT_DATA2*)ed->data;
2853 ed2->address = address;
2854 ed2->size = length;
2855 ed2->offset = 0;
2856 ed2->num_bytes = decoded_size;
2857
2859 ULONG sl = (ULONG)(length >> Vcb->sector_shift);
2860
2861 csum = ExAllocatePoolWithTag(PagedPool, sl * Vcb->csum_size, ALLOC_TAG);
2862 if (!csum) {
2863 ERR("out of memory\n");
2864 ExFreePool(ed);
2865 return false;
2866 }
2867
2868 do_calc_job(Vcb, data, sl, csum);
2869 }
2870
2871 Status = add_extent_to_fcb(fcb, start_data, ed, edsize, true, csum, rollback);
2872 if (!NT_SUCCESS(Status)) {
2873 ERR("add_extent_to_fcb returned %08lx\n", Status);
2874 if (csum) ExFreePool(csum);
2875 ExFreePool(ed);
2876 return false;
2877 }
2878
2879 ExFreePool(ed);
2880
2881 c->used += length;
2883
2885
2886 fcb->extents_changed = true;
2887 fcb->inode_item_changed = true;
2889
2890 ExAcquireResourceExclusiveLite(&c->changed_extents_lock, true);
2891